From 3ce7123685dff41d273012708f389b69c2dd7aec Mon Sep 17 00:00:00 2001 From: esuo1198 <54134.es@gmail.com> Date: Sun, 6 Jul 2025 23:05:23 +0900 Subject: [PATCH] Re-implement FPS Limiter --- CMakeLists.txt | 4 +- README.md | 2 +- dist/config.toml | 2 +- src/config.h | 1 + src/dllmain.cpp | 2 +- src/patches/dxgi.cpp | 143 ++----------------------------------- src/patches/fpslimiter.cpp | 7 +- src/patches/patches.h | 2 +- 8 files changed, 14 insertions(+), 149 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 10a4a1e..014d393 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,8 +162,8 @@ set(SOURCES src/Windows/WindowsError.cpp src/Windows/MinimumLatencyAudioClient.cpp src/patches/amauth.cpp - # src/patches/dxgi.cpp - # src/patches/fpslimiter.cpp + src/patches/dxgi.cpp + src/patches/fpslimiter.cpp src/patches/audio.cpp src/patches/plugins.cpp src/patches/scanner.cpp diff --git a/README.md b/README.md index 57d0fd0..7c608c3 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ res = { x = 1920, y = 1080 } windowed = false # if set to false, will automatically go Fullscreen cursor = true # Fullscreen will automatically hide cursor vsync = false # Enable this if you are using a 120fps screen (and use "Let Application Decide" in Nvidia panel) -# fpslimit = 0 # Temporarily disabled, limit to 120 fps in Nvidia panel instead!!! +fpslimit = true # Limit the game to 120fps model_res_rate = 1.0 # Don-Model resolution rate (currently JPN39 only) # | rate <= 0: default 1280x720 # | rate > 0: current resolution * rate diff --git a/dist/config.toml b/dist/config.toml index a071508..22345df 100644 --- a/dist/config.toml +++ b/dist/config.toml @@ -36,7 +36,7 @@ res = { x = 1920, y = 1080 } windowed = false # if set to false, will automatically go Fullscreen cursor = true # Fullscreen will automatically hide cursor vsync = false # Enable this if you are using a 120fps screen (and use "Let Application Decide" in Nvidia panel) -# fpslimit = 0 # Temporarily disabled, limit to 120 fps in Nvidia panel instead!!! +fpslimit = true # Limit the game to 120fps model_res_rate = 1.0 # Don-Model resolution rate (currently JPN39 only) # | rate <= 0: default 1280x720 # | rate > 0: current resolution * rate diff --git a/src/config.h b/src/config.h index 616439d..b838697 100644 --- a/src/config.h +++ b/src/config.h @@ -68,6 +68,7 @@ struct graphicsConfig { }; resConfig res; bool vsync = false; + bool fpslimit = true; float model_res_rate = 1.0f; }; diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 41360f3..cdcdc25 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -277,7 +277,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { patches::Lua::Init (); patches::Scanner::Init (); patches::Audio::Init (); - // patches::Dxgi::Init (); + patches::Dxgi::Init (); patches::AmAuth::Init (); patches::Language::Init (); patches::TestMode::Init (); diff --git a/src/patches/dxgi.cpp b/src/patches/dxgi.cpp index ffc38a3..87816ff 100644 --- a/src/patches/dxgi.cpp +++ b/src/patches/dxgi.cpp @@ -2,18 +2,11 @@ #define D3D11_NO_HELPERS #define INITGUID -#include "d3d11.h" -#include "d3d12.h" #include "dxgi1_2.h" -#include "dxgi1_3.h" -#include "dxgi1_4.h" -#include "dxgi1_5.h" -#include "dxgi1_6.h" #include "helpers.h" - +#include "config.h" #include "bnusio.h" #include "patches.h" -#include /* * Reference: https://github.com/teknogods/OpenParrot/blob/master/OpenParrot/src/Functions/WindowedDxgi.cpp @@ -25,40 +18,15 @@ namespace patches::Dxgi { static bool FpsLimiterEnable = false; // Prototypes -static HRESULT (STDMETHODCALLTYPE *g_oldCreateSwapChain) (IDXGIFactory *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, - IDXGISwapChain **ppSwapChain); -static HRESULT (STDMETHODCALLTYPE *g_oldCreateSwapChainForHwnd) (IDXGIFactory2 *This, IUnknown *pDevice, HWND hWnd, - const DXGI_SWAP_CHAIN_DESC1 *pDesc, - const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc, - IDXGIOutput *pRestrictToOutput, IDXGISwapChain1 **ppSwapChain); static HRESULT (STDMETHODCALLTYPE *g_oldPresentWrap) (IDXGISwapChain *pSwapChain, UINT SyncInterval, UINT Flags); -static HRESULT (STDMETHODCALLTYPE *g_oldPresent1Wrap) (IDXGISwapChain1 *pSwapChain, UINT SyncInterval, UINT Flags); static HRESULT (STDMETHODCALLTYPE *g_oldCreateSwapChain2) (IDXGIFactory2 *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGISwapChain **ppSwapChain); static HRESULT (WINAPI *g_origCreateDXGIFactory2) (UINT Flags, REFIID riid, void **ppFactory); -static HRESULT (WINAPI *g_origCreateDXGIFactory) (REFIID, void **); -static HRESULT (WINAPI *g_origD3D11CreateDeviceAndSwapChain) (IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, - const D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, - /*const*/ DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, IDXGISwapChain **ppSwapChain, - ID3D11Device **ppDevice, D3D_FEATURE_LEVEL *pFeatureLevel, - ID3D11DeviceContext **ppImmediateContext); -static HRESULT STDMETHODCALLTYPE CreateSwapChainWrap (IDXGIFactory *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, - IDXGISwapChain **ppSwapChain); -static HRESULT STDMETHODCALLTYPE CreateSwapChainForHwndWrap (IDXGIFactory2 *This, IUnknown *pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1 *pDesc, - const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc, IDXGIOutput *pRestrictToOutput, - IDXGISwapChain1 **ppSwapChain); static HRESULT STDMETHODCALLTYPE PresentWrap (IDXGISwapChain *pSwapChain, UINT SyncInterval, UINT Flags); -static HRESULT STDMETHODCALLTYPE Present1Wrap (IDXGISwapChain1 *pSwapChain, UINT SyncInterval, UINT Flags); static HRESULT STDMETHODCALLTYPE CreateSwapChain2Wrap (IDXGIFactory2 *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGISwapChain **ppSwapChain); static HRESULT WINAPI CreateDXGIFactory2Wrap (UINT Flags, REFIID riid, void **ppFactory); -static HRESULT WINAPI CreateDXGIFactoryWrap (REFIID riid, _COM_Outptr_ void **ppFactory); -static HRESULT WINAPI D3D11CreateDeviceAndSwapChainWrap (IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, - const D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, - /*const*/ DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, IDXGISwapChain **ppSwapChain, - ID3D11Device **ppDevice, D3D_FEATURE_LEVEL *pFeatureLevel, - ID3D11DeviceContext **ppImmediateContext); // Functions template @@ -72,35 +40,6 @@ HookVtableFunction (T *functionPtr, T target) { return old; } -static HRESULT STDMETHODCALLTYPE -CreateSwapChainWrap (IDXGIFactory *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGISwapChain **ppSwapChain) { - const HRESULT hr = g_oldCreateSwapChain (This, pDevice, pDesc, ppSwapChain); - - if (*ppSwapChain) { - if (FpsLimiterEnable) { - const auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, PresentWrap); - g_oldPresentWrap = old2 ? old2 : g_oldPresentWrap; - } - } - - return hr; -} - -static HRESULT STDMETHODCALLTYPE -CreateSwapChainForHwndWrap (IDXGIFactory2 *This, IUnknown *pDevice, const HWND hWnd, const DXGI_SWAP_CHAIN_DESC1 *pDesc, - const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc, IDXGIOutput *pRestrictToOutput, IDXGISwapChain1 **ppSwapChain) { - const HRESULT hr = g_oldCreateSwapChainForHwnd (This, pDevice, hWnd, pDesc, nullptr, pRestrictToOutput, ppSwapChain); - - if (*ppSwapChain) { - if (FpsLimiterEnable) { - const auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, Present1Wrap); - g_oldPresent1Wrap = old2 ? old2 : g_oldPresent1Wrap; - } - } - - return hr; -} - static HRESULT STDMETHODCALLTYPE PresentWrap (IDXGISwapChain *pSwapChain, const UINT SyncInterval, const UINT Flags) { if (FpsLimiterEnable) FpsLimiter::Update (); @@ -110,15 +49,6 @@ PresentWrap (IDXGISwapChain *pSwapChain, const UINT SyncInterval, const UINT Fla return g_oldPresentWrap (pSwapChain, SyncInterval, Flags); } -static HRESULT STDMETHODCALLTYPE -Present1Wrap (IDXGISwapChain1 *pSwapChain, const UINT SyncInterval, const UINT Flags) { - if (FpsLimiterEnable) FpsLimiter::Update (); - - bnusio::Update (); - - return g_oldPresent1Wrap (pSwapChain, SyncInterval, Flags); -} - static HRESULT STDMETHODCALLTYPE CreateSwapChain2Wrap (IDXGIFactory2 *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGISwapChain **ppSwapChain) { const HRESULT hr = g_oldCreateSwapChain2 (This, pDevice, pDesc, ppSwapChain); @@ -147,82 +77,17 @@ CreateDXGIFactory2Wrap (const UINT Flags, REFIID riid, void **ppFactory) { return hr; } -static HRESULT WINAPI -CreateDXGIFactoryWrap (REFIID riid, _COM_Outptr_ void **ppFactory) { - const HRESULT hr = g_origCreateDXGIFactory (riid, ppFactory); - - if (SUCCEEDED (hr)) { - int factoryType = 0; - - if (IsEqualIID (riid, IID_IDXGIFactory1)) factoryType = 1; - else if (IsEqualIID (riid, IID_IDXGIFactory2)) factoryType = 2; - else if (IsEqualIID (riid, IID_IDXGIFactory3)) factoryType = 3; - else if (IsEqualIID (riid, IID_IDXGIFactory4)) factoryType = 4; - else if (IsEqualIID (riid, IID_IDXGIFactory5)) factoryType = 5; - else if (IsEqualIID (riid, IID_IDXGIFactory6)) factoryType = 6; - else if (IsEqualIID (riid, IID_IDXGIFactory7)) factoryType = 7; - - // ReSharper disable once CppDFAConstantConditions - if (factoryType >= 0) { - const IDXGIFactory *factory = static_cast (*ppFactory); - - const auto old = HookVtableFunction (&factory->lpVtbl->CreateSwapChain, CreateSwapChainWrap); - g_oldCreateSwapChain = old ? old : g_oldCreateSwapChain; - } - - if (factoryType >= 2) { - const IDXGIFactory2 *factory = static_cast (*ppFactory); - - const auto old = HookVtableFunction (&factory->lpVtbl->CreateSwapChainForHwnd, CreateSwapChainForHwndWrap); - g_oldCreateSwapChainForHwnd = old ? old : g_oldCreateSwapChainForHwnd; - } - } - - return hr; -} - -static HRESULT WINAPI -D3D11CreateDeviceAndSwapChainWrap (IDXGIAdapter *pAdapter, const D3D_DRIVER_TYPE DriverType, const HMODULE Software, const UINT Flags, - const D3D_FEATURE_LEVEL *pFeatureLevels, const UINT FeatureLevels, const UINT SDKVersion, - /*const*/ DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, IDXGISwapChain **ppSwapChain, ID3D11Device **ppDevice, - D3D_FEATURE_LEVEL *pFeatureLevel, ID3D11DeviceContext **ppImmediateContext) { - const HRESULT hr = g_origD3D11CreateDeviceAndSwapChain (pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, - pSwapChainDesc, ppSwapChain, ppDevice, pFeatureLevel, ppImmediateContext); - - if (ppSwapChain) { - if (FpsLimiterEnable) { - const auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, PresentWrap); - g_oldPresentWrap = old2 ? old2 : g_oldPresentWrap; - } - } - - return hr; -} - void Init () { - LogMessage (LogLevel::INFO, "Init Dxgi patches"); - i32 fpsLimit = 120; - - const auto configPath = std::filesystem::current_path () / "config.toml"; - const std::unique_ptr config_ptr (openConfig (configPath), toml_free); - if (config_ptr) { - if (const auto graphics = openConfigSection (config_ptr.get (), "graphics")) - fpsLimit = static_cast (readConfigInt (graphics, "fpslimit", fpsLimit)); - } - - FpsLimiterEnable = fpsLimit > 0; + LogMessage (LogLevel::INFO, "Init DXGI patches"); + FpsLimiterEnable = Config::ConfigManager::instance ().getGraphicsConfig ().fpslimit; if (FpsLimiterEnable) { - FpsLimiter::Init (static_cast (fpsLimit)); + FpsLimiter::Init (); MH_Initialize (); - MH_CreateHookApi (L"dxgi.dll", "CreateDXGIFactory", reinterpret_cast (CreateDXGIFactoryWrap), - reinterpret_cast (&g_origCreateDXGIFactory)); MH_CreateHookApi (L"dxgi.dll", "CreateDXGIFactory2", reinterpret_cast (CreateDXGIFactory2Wrap), reinterpret_cast (&g_origCreateDXGIFactory2)); - MH_CreateHookApi (L"d3d11.dll", "D3D11CreateDeviceAndSwapChain", reinterpret_cast (D3D11CreateDeviceAndSwapChainWrap), - reinterpret_cast (&g_origD3D11CreateDeviceAndSwapChain)); MH_EnableHook (nullptr); } } diff --git a/src/patches/fpslimiter.cpp b/src/patches/fpslimiter.cpp index 127095f..893d4a8 100644 --- a/src/patches/fpslimiter.cpp +++ b/src/patches/fpslimiter.cpp @@ -10,14 +10,13 @@ namespace patches::FpsLimiter { static LARGE_INTEGER PerformanceCount1; static LARGE_INTEGER PerformanceCount2; static bool bOnce1 = false; -static double targetFrameTime = 1000.0 / 60.0; +static double targetFrameTime = 1000.0 / 120.0; static double t = 0.0; static u32 i = 0; void -Init (const float fpsLimit) { - if (fpsLimit > 0) LogMessage (LogLevel::INFO, "Init Fps Limiter"); - targetFrameTime = 1000.0 / fpsLimit; +Init () { + LogMessage (LogLevel::INFO, "Init FPS Limiter"); } void diff --git a/src/patches/patches.h b/src/patches/patches.h index 47b1c6c..4e3f731 100644 --- a/src/patches/patches.h +++ b/src/patches/patches.h @@ -22,7 +22,7 @@ namespace Dxgi { void Init (); } // namespace Dxgi namespace FpsLimiter { -void Init (float fpsLimit); +void Init (); void Update (); } // namespace FpsLimiter namespace Audio {