diff --git a/source-code/data/plugins/components.ini b/source-code/data/plugins/components.ini index 20d0154..1aeda5c 100644 --- a/source-code/data/plugins/components.ini +++ b/source-code/data/plugins/components.ini @@ -42,8 +42,5 @@ scale_component = true # enabling this component is not recommended for most users. debug_component = false -# enables the ability to set a cap on the framerate by setting FPS.Limit in config.ini -fps_limiter = true - # allows the usage of hold transfer target_inspector = true \ No newline at end of file diff --git a/source-code/data/plugins/config.ini b/source-code/data/plugins/config.ini index 6932c46..a173c38 100644 --- a/source-code/data/plugins/config.ini +++ b/source-code/data/plugins/config.ini @@ -40,7 +40,7 @@ Enhanced_Stage_Manager=0 Enhanced_Stage_Manager_Encore=1 [Graphics] -#FPS Limiter requires "fps_limiter" component to be enabled in "components.ini" +# Set to -1 to unlock the frame rate. FPS.Limit=60 # Temporal Anti-Aliasing TAA=1 diff --git a/source-code/source/plugins/Launcher/framework.h b/source-code/source/plugins/Launcher/framework.h index 25a6f20..4d575e3 100644 --- a/source-code/source/plugins/Launcher/framework.h +++ b/source-code/source/plugins/Launcher/framework.h @@ -166,7 +166,7 @@ ConfigOptionBase* optionsArray[] = { new DropdownOption(L"status_icons", PATCHES_SECTION, CONFIG_FILE, L"Status Icons:", L"Set the state of card reader and network status icons.", 3, std::vector({ L"Default", L"Hidden", L"Error", L"OK", L"Partial OK" })), - new NumericOption(L"FPS.Limit", GRAPHICS_SECTION, CONFIG_FILE, L"FPS Limit:", L"Using the FPS limit requires the \"FPS Limiter\" component to be enabled.", 60, 0, INT_MAX), + new NumericOption(L"FPS.Limit", GRAPHICS_SECTION, CONFIG_FILE, L"FPS Limit:", L"Allows you to set a frame rate cap. Set to -1 to unlock the frame rate.", 60, -1, INT_MAX), new StringOption(L"command_line", LAUNCHER_SECTION, CONFIG_FILE, L"Command Line:", L"Allows setting command line parameters for the game when using the launcher.\nDisabling the launcher will bypass this.", L"", false), }; @@ -213,8 +213,6 @@ ConfigOptionBase* componentsArray[] = { new BooleanOption(L"debug_component", COMPONENTS_SECTION, COMPONENTS_FILE, L"Debug Component", L"Allows for changing game state (F4-F8 keys), using dev GUI and tests, and speeding up 2d animations/menus (hold SHIFT+TAB).", false, true), - new BooleanOption(L"fps_limiter", COMPONENTS_SECTION, COMPONENTS_FILE, L"FPS Limiter", L"Lets you set a framerate cap. The value of the limit is in the options tab.", false, true), - new BooleanOption(L"target_inspector", COMPONENTS_SECTION, COMPONENTS_FILE, L"Target Inspector", L"Enables hold transfers.", false, true), }; diff --git a/source-code/source/plugins/Render/dllmain.cpp b/source-code/source/plugins/Render/dllmain.cpp index de931be..0e670ea 100644 --- a/source-code/source/plugins/Render/dllmain.cpp +++ b/source-code/source/plugins/Render/dllmain.cpp @@ -7,6 +7,10 @@ #include #include +#include + +using namespace std::chrono; + int hookedCreateWindow(const char* title, void(__cdecl* exit_function)(int)) { SetProcessDPIAware(); @@ -91,6 +95,21 @@ __int64 hookedParseParameters(int a1, __int64* a2) return divaParseParameters(a1, a2); } +time_point nextUpdate; +microseconds expectedFrameDuration(1000000 / nFpsLimit); + +__int64 __fastcall hookedEngineUpdate(__int64 a1) +{ + if (high_resolution_clock::now() < nextUpdate) + return 0; + + const auto result = divaEngineUpdate(a1); + + nextUpdate = high_resolution_clock::now() + expectedFrameDuration; + + return result; +} + BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, @@ -109,6 +128,14 @@ BOOL APIENTRY DllMain(HMODULE hModule, DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)divaParseParameters, hookedParseParameters); DetourTransactionCommit(); + + if (nFpsLimit > 0) + { + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(&(PVOID&)divaEngineUpdate, hookedEngineUpdate); + DetourTransactionCommit(); + } } return TRUE; } diff --git a/source-code/source/plugins/Render/framework.h b/source-code/source/plugins/Render/framework.h index d870bed..e8cf93e 100644 --- a/source-code/source/plugins/Render/framework.h +++ b/source-code/source/plugins/Render/framework.h @@ -7,6 +7,7 @@ static int(__cdecl* divaCreateWindow)(const char* title, void(__cdecl* exitfunc)(int)) = (int(__cdecl*)(const char* title, void(__cdecl * exitfunc)(int)))0x140194D00; __int64 (__fastcall* divaParseParameters)(int a1, __int64* a2) = (__int64(__fastcall*)(int a1, __int64* a2))0x140193630; +__int64(__fastcall* divaEngineUpdate)(__int64 a1) = (__int64(__fastcall*)(__int64 a1))0x140194D20; uint8_t* fullScreenFlag = (uint8_t*)0x140EDA5D1; DWORD* resolutionType = (DWORD*)0x140EDA5D4; @@ -34,6 +35,8 @@ int nIntResHeight = GetPrivateProfileIntW(L"resolution", L"r.height", 720, CONFI int nBitDepth = GetPrivateProfileIntW(L"resolution", L"bitdepth", 32, CONFIG_FILE); int nRefreshRate = GetPrivateProfileIntW(L"resolution", L"refreshrate", 60, CONFIG_FILE); +int nFpsLimit = GetPrivateProfileIntW(L"graphics", L"fps.limit", 60, CONFIG_FILE); + // used to trick Optimus into switching to the NVIDIA GPU HMODULE nvcudaModule = LoadLibraryW(L"nvcuda.dll"); // cuInit actually returns a CUresult, but we don't really care about it diff --git a/source-code/source/plugins/TLAC/Components/ComponentsManager.cpp b/source-code/source/plugins/TLAC/Components/ComponentsManager.cpp index 1ad90b3..2a0deb2 100644 --- a/source-code/source/plugins/TLAC/Components/ComponentsManager.cpp +++ b/source-code/source/plugins/TLAC/Components/ComponentsManager.cpp @@ -12,7 +12,6 @@ #include "CameraController.h" #include "DebugComponent.h" #include "ScaleComponent.h" -#include "FPSLimiter.h" #include "GameTargets/TargetInspector.h" using ConfigFile = TLAC::FileSystem::ConfigFile; @@ -42,7 +41,6 @@ namespace TLAC::Components new FrameRateManager(), new FastLoader(), new ScaleComponent(), - new FPSLimiter(), new StageManager(), new CameraController(), new DebugComponent(), diff --git a/source-code/source/plugins/TLAC/Components/FPSLimiter.cpp b/source-code/source/plugins/TLAC/Components/FPSLimiter.cpp deleted file mode 100644 index 54b4d1c..0000000 --- a/source-code/source/plugins/TLAC/Components/FPSLimiter.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "FPSLimiter.h" -#include -#include -#include -#include -#include -#include - -using dsec = std::chrono::duration; -using seconds = std::chrono::seconds; - -// this is pretty much just lybxlpsv's limiter, but removed from GLComponent - -namespace TLAC::Components -{ - using namespace std::chrono; - - static std::chrono::time_point mBeginFrame = system_clock::now(); - static std::chrono::time_point prevTimeInSeconds = time_point_cast(mBeginFrame); - - const LPCTSTR config_file_name = _T(".\\config.ini"); - int fpsLimit = GetPrivateProfileIntW(L"graphics", L"fps.limit", 0, config_file_name); - - FPSLimiter::FPSLimiter() - { - } - - FPSLimiter::~FPSLimiter() - { - } - - const char* FPSLimiter::GetDisplayName() - { - return "fps_limiter"; - } - - void FPSLimiter::Initialize(ComponentsManager* manager) - { - mBeginFrame = std::chrono::system_clock::now(); - prevTimeInSeconds = std::chrono::time_point_cast(mBeginFrame); - frameCountPerSecond = 0; - if(fpsLimit != 0) - printf("FPSLimiter fpsLimit: %d\n", fpsLimit); - } - - // I assume this gets called once per frame... if not this won't work - void FPSLimiter::Update() - { - auto invFpsLimit = round(dsec{ 1. / fpsLimit }); - auto mEndFrame = mBeginFrame + invFpsLimit; - auto timeInSeconds = std::chrono::time_point_cast(std::chrono::system_clock::now()); - - ++frameCountPerSecond; - if (timeInSeconds > prevTimeInSeconds) - { - //printf("FPSLimiter::Update(): FPS: %d\n", frameCountPerSecond); - frameCountPerSecond = 0; - prevTimeInSeconds = timeInSeconds; - } - - // This part keeps the frame rate. - if (fpsLimit > 19) // not sure why lyb used 19 here - std::this_thread::sleep_until(mEndFrame); - mBeginFrame = mEndFrame; - mEndFrame = mBeginFrame + invFpsLimit; - } -} \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Components/FPSLimiter.h b/source-code/source/plugins/TLAC/Components/FPSLimiter.h deleted file mode 100644 index d975a53..0000000 --- a/source-code/source/plugins/TLAC/Components/FPSLimiter.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "EmulatorComponent.h" -#include - -using seconds = std::chrono::seconds; - -namespace TLAC::Components -{ - class FPSLimiter : public EmulatorComponent - { - public: - FPSLimiter(); - ~FPSLimiter(); - - virtual const char* GetDisplayName() override; - - virtual void Initialize(ComponentsManager*) override; - virtual void Update() override; - - private: - int frameCountPerSecond; - }; -} \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/TLAC.vcxproj b/source-code/source/plugins/TLAC/TLAC.vcxproj index df1945c..da181a9 100644 --- a/source-code/source/plugins/TLAC/TLAC.vcxproj +++ b/source-code/source/plugins/TLAC/TLAC.vcxproj @@ -177,7 +177,6 @@ - @@ -238,7 +237,6 @@ - diff --git a/source-code/source/plugins/TLAC/TLAC.vcxproj.filters b/source-code/source/plugins/TLAC/TLAC.vcxproj.filters index 7659af6..f131383 100644 --- a/source-code/source/plugins/TLAC/TLAC.vcxproj.filters +++ b/source-code/source/plugins/TLAC/TLAC.vcxproj.filters @@ -177,9 +177,6 @@ Header Files - - Header Files - Header Files @@ -326,9 +323,6 @@ Source Files - - Source Files - Source Files