From 2cb5004c47f016387c69bbc531d5c6ee01731e60 Mon Sep 17 00:00:00 2001 From: somewhatlurker <52014015+somewhatlurker@users.noreply.github.com> Date: Fri, 6 Sep 2019 02:37:38 +1000 Subject: [PATCH] replace FrameRateManager with new approach -- now keeps sync much better, but makes wind effects and some stuff outside PVs run at the wrong speed --- .../TLAC/Components/FrameRateManager.cpp | 198 ++++++++++++++---- .../TLAC/Components/FrameRateManager.h | 12 +- 2 files changed, 160 insertions(+), 50 deletions(-) diff --git a/source-code/source/plugins/TLAC/Components/FrameRateManager.cpp b/source-code/source/plugins/TLAC/Components/FrameRateManager.cpp index c902a2f..d011719 100644 --- a/source-code/source/plugins/TLAC/Components/FrameRateManager.cpp +++ b/source-code/source/plugins/TLAC/Components/FrameRateManager.cpp @@ -1,4 +1,4 @@ -#include "FrameRateManager.h" +#include "FrameRateManager.h" #include "../Constants.h" #include "GameState.h" #include @@ -30,57 +30,177 @@ namespace TLAC::Components defaultAetFrameDuration = *aetFrameDuration; // This const variable is stored inside a data segment so we don't want to throw any access violations - DWORD oldProtect; + DWORD oldProtect, bck; VirtualProtect((void*)AET_FRAME_DURATION_ADDRESS, sizeof(float), PAGE_EXECUTE_READWRITE, &oldProtect); + + + // fix auto speed for high fps + VirtualProtect((BYTE*)0x140192d7b, 3, PAGE_EXECUTE_READWRITE, &oldProtect); + *((BYTE*)0x140192d7b + 0) = 0x90; + *((BYTE*)0x140192d7b + 1) = 0x90; + *((BYTE*)0x140192d7b + 2) = 0x90; + VirtualProtect((BYTE*)0x140192d7b, 3, oldProtect, &bck); + + + // fix edit PV AETs (thanks lyb) + VirtualProtect((BYTE*)0x140192D30, 8, PAGE_EXECUTE_READWRITE, &oldProtect); // MOVSS XMM0, dword ptr [0x140192f94] + *((BYTE*)0x140192D30 + 0) = 0xF3; + *((BYTE*)0x140192D30 + 1) = 0x0F; + *((BYTE*)0x140192D30 + 2) = 0x10; + *((BYTE*)0x140192D30 + 3) = 0x05; + *((BYTE*)0x140192D30 + 4) = 0x5C; + *((BYTE*)0x140192D30 + 5) = 0x02; + *((BYTE*)0x140192D30 + 6) = 0x00; + *((BYTE*)0x140192D30 + 7) = 0x00; + VirtualProtect((BYTE*)0x140192D30, 8, oldProtect, &bck); + + + // fix ageage hair effect + VirtualProtect((BYTE*)0x14054352f, 5, PAGE_EXECUTE_READWRITE, &oldProtect); // CALL 0x140192d50 (getFrameSpeed) + *((BYTE*)0x14054352f + 0) = 0xE8; + *((BYTE*)0x14054352f + 1) = 0x1C; + *((BYTE*)0x14054352f + 2) = 0xF8; + *((BYTE*)0x14054352f + 3) = 0xC4; + *((BYTE*)0x14054352f + 4) = 0xFF; + VirtualProtect((BYTE*)0x14054352f, 5, oldProtect, &bck); + + VirtualProtect((BYTE*)0x140543534, 4, PAGE_EXECUTE_READWRITE, &oldProtect); // MULSS XMM3, XMM0 + *((BYTE*)0x140543534 + 0) = 0xF3; + *((BYTE*)0x140543534 + 1) = 0x0F; + *((BYTE*)0x140543534 + 2) = 0x59; + *((BYTE*)0x140543534 + 3) = 0xD8; + VirtualProtect((BYTE*)0x140543534, 4, oldProtect, &bck); + + VirtualProtect((BYTE*)0x140543538, 2, PAGE_EXECUTE_READWRITE, &oldProtect); // JMP 0x1405434f0 + *((BYTE*)0x140543538 + 0) = 0xEB; + *((BYTE*)0x140543538 + 1) = 0xB6; + VirtualProtect((BYTE*)0x140543538, 2, oldProtect, &bck); + + + + // below are patches for the alternate method (breaks physics) + + //// run motions at motionSpeedMultiplier x rate + // // skip unncessary code to free code space + // VirtualProtect((BYTE*)0x140194b2b, 2, PAGE_EXECUTE_READWRITE, &oldProtect); // JMP 0x140194b51 + // *((BYTE*)0x140194b2b + 0) = 0xEB; + // *((BYTE*)0x140194b2b + 1) = 0x24; + // VirtualProtect((BYTE*)0x140194b2b, 2, oldProtect, &bck); + + + // VirtualProtect((BYTE*)0x140194b2d, 5, PAGE_EXECUTE_READWRITE, &oldProtect); // CALL 0x140192d50 + // *((BYTE*)0x140194b2d + 0) = 0xE8; + // *((BYTE*)0x140194b2d + 1) = 0x1E; + // *((BYTE*)0x140194b2d + 2) = 0xE2; + // *((BYTE*)0x140194b2d + 3) = 0xFF; + // *((BYTE*)0x140194b2d + 4) = 0xFF; + // VirtualProtect((BYTE*)0x140194b2d, 5, oldProtect, &bck); + + // VirtualProtect((BYTE*)0x140194b32, 10, PAGE_EXECUTE_READWRITE, &oldProtect); // MOV ECX, &motionSpeedMultiplier + // *((BYTE*)0x140194b32 + 0) = 0x48; + // *((BYTE*)0x140194b32 + 1) = 0xB9; + // *((BYTE*)0x140194b32 + 2) = (uint64_t)&motionSpeedMultiplier & 0xFF; + // *((BYTE*)0x140194b32 + 3) = ((uint64_t)&motionSpeedMultiplier >> 8) & 0xFF; + // *((BYTE*)0x140194b32 + 4) = ((uint64_t)&motionSpeedMultiplier >> 16) & 0xFF; + // *((BYTE*)0x140194b32 + 5) = ((uint64_t)&motionSpeedMultiplier >> 24) & 0xFF; + // *((BYTE*)0x140194b32 + 6) = ((uint64_t)&motionSpeedMultiplier >> 32) & 0xFF; + // *((BYTE*)0x140194b32 + 7) = ((uint64_t)&motionSpeedMultiplier >> 40) & 0xFF; + // *((BYTE*)0x140194b32 + 8) = ((uint64_t)&motionSpeedMultiplier >> 48) & 0xFF; + // *((BYTE*)0x140194b32 + 9) = ((uint64_t)&motionSpeedMultiplier >> 56) & 0xFF; + // VirtualProtect((BYTE*)0x140194b32, 10, oldProtect, &bck); + + // VirtualProtect((BYTE*)0x140194b3c, 5, PAGE_EXECUTE_READWRITE, &oldProtect); // MOVD XMM1, dword ptr [ECX] + // *((BYTE*)0x140194b3c + 0) = 0x66; + // *((BYTE*)0x140194b3c + 1) = 0x67; + // *((BYTE*)0x140194b3c + 2) = 0x0F; + // *((BYTE*)0x140194b3c + 3) = 0x6E; + // *((BYTE*)0x140194b3c + 4) = 0x09; + // VirtualProtect((BYTE*)0x140194b3c, 5, oldProtect, &bck); + + // VirtualProtect((BYTE*)0x140194b41, 4, PAGE_EXECUTE_READWRITE, &oldProtect); // MULSS XMM0, XMM1 + // *((BYTE*)0x140194b41 + 0) = 0xF3; + // *((BYTE*)0x140194b41 + 1) = 0x0F; + // *((BYTE*)0x140194b41 + 2) = 0x59; + // *((BYTE*)0x140194b41 + 3) = 0xC1; + // VirtualProtect((BYTE*)0x140194b41, 4, oldProtect, &bck); + + // VirtualProtect((BYTE*)0x140194b45, 2, PAGE_EXECUTE_READWRITE, &oldProtect); // JMP 0x140194ae8 + // *((BYTE*)0x140194b45 + 0) = 0xEB; + // *((BYTE*)0x140194b45 + 1) = 0xA1; + // VirtualProtect((BYTE*)0x140194b45, 2, oldProtect, &bck); + + + // // jump to new code + // VirtualProtect((BYTE*)0x140194ae3, 2, PAGE_EXECUTE_READWRITE, &oldProtect); // JMP 0x140194b2d + // *((BYTE*)0x140194ae3 + 0) = 0xEB; + // *((BYTE*)0x140194ae3 + 1) = 0x48; + // VirtualProtect((BYTE*)0x140194ae3, 2, oldProtect, &bck); + + + //// // trying to fix physics (fail) + //// VirtualProtect((BYTE*)0x14011d537, 9, PAGE_EXECUTE_READWRITE, &oldProtect); // change source to dword ptr [0x140b0d4f0] + //// *((BYTE*)0x14011d537 + 0) = 0xF3; + //// *((BYTE*)0x14011d537 + 1) = 0x0F; + //// *((BYTE*)0x14011d537 + 2) = 0x10; + //// *((BYTE*)0x14011d537 + 3) = 0x05; + //// *((BYTE*)0x14011d537 + 4) = 0xB1; + //// *((BYTE*)0x14011d537 + 5) = 0xFF; + //// *((BYTE*)0x14011d537 + 6) = 0x9E; + //// *((BYTE*)0x14011d537 + 7) = 0x00; + //// *((BYTE*)0x14011d537 + 8) = 0x90; + //// VirtualProtect((BYTE*)0x14011d537, 9, oldProtect, &bck); } void FrameRateManager::Update() { - float frameRate = 0.0f; - frameRate = RoundFrameRate(GetGameFrameRate()); + // this alterante way makes physics slowmo, but overall may be better if that's fixed - *aetFrameDuration = 1.0f / frameRate; - *pvFrameRate = frameRate; + //// target framerate + //*(float*)0x140eda6cc = 60.0f; + + //// enable dynamic framerate + //*(bool*)0x140eda79c = true; + + //*pvFrameRate = 60.0f; + + //*aetFrameDuration = 1.0f / GetGameFrameRate(); + + //bool inGame = *(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME; + //if (inGame) + //{ + // // This PV struct creates a copy of the PvFrameRate & PvFrameSpeed during the loading screen + // // so we'll make sure to keep updating it as well. + // // Each new motion also creates its own copy of these values but keeping track of the active motions is annoying + // // and they usually change multiple times per PV anyway so this should suffice for now + // float* pvStructPvFrameRate = (float*)(0x0000000140CDD978 + 0x2BF98); + // float* pvStructPvFrameSpeed = (float*)(0x0000000140CDD978 + 0x2BF9C); + + // *pvStructPvFrameRate = 60.0; // ? + // *pvStructPvFrameSpeed = 1.0 / motionSpeedMultiplier; + //} + + + + + // this way breaks some anim speeds, but they're fixable + + *pvFrameRate = 60.0f * motionSpeedMultiplier; + + // target framerate + *(float*)0x140eda6cc = *pvFrameRate; + + *aetFrameDuration = 1.0f / GetGameFrameRate(); bool inGame = *(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME; - if (inGame) { - // During the GAME state the frame rate will be handled by the PvFrameRate instead - - constexpr float defaultFrameSpeed = 1.0f; - constexpr float defaultFrameRate = 60.0f; - - // This PV struct creates a copy of the PvFrameRate & PvFrameSpeed during the loading screen - // so we'll make sure to keep updating it as well. - // Each new motion also creates its own copy of these values but keeping track of the active motions is annoying - // and they usually change multiple times per PV anyway so this should suffice for now - float* pvStructPvFrameRate = (float*)(0x0000000140CDD978 + 0x2BF98); - float* pvStructPvFrameSpeed = (float*)(0x0000000140CDD978 + 0x2BF9C); - - *pvStructPvFrameRate = *pvFrameRate; - *pvStructPvFrameSpeed = (defaultFrameRate / *pvFrameRate); - - *frameSpeed = defaultFrameSpeed; + // enable dynamic framerate + *(bool*)0x140eda79c = true; } else { - *frameSpeed = *aetFrameDuration / defaultAetFrameDuration; + // disable dynamic framerate + *(bool*)0x140eda79c = false; } } - - float FrameRateManager::RoundFrameRate(float frameRate) - { - constexpr float roundingThreshold = 4.0f; - - for (int i = 0; i < sizeof(commonRefreshRates) / sizeof(float); i++) - { - float refreshRate = commonRefreshRates[i]; - - if (frameRate > refreshRate - roundingThreshold && frameRate < refreshRate + roundingThreshold) - frameRate = refreshRate; - } - - return frameRate; - } } diff --git a/source-code/source/plugins/TLAC/Components/FrameRateManager.h b/source-code/source/plugins/TLAC/Components/FrameRateManager.h index f6a6600..512f49c 100644 --- a/source-code/source/plugins/TLAC/Components/FrameRateManager.h +++ b/source-code/source/plugins/TLAC/Components/FrameRateManager.h @@ -19,16 +19,6 @@ namespace TLAC::Components float *frameSpeed; float *aetFrameDuration; float defaultAetFrameDuration; - - float commonRefreshRates[5] - { - 60.0f, - 75.0f, - 120.0f, - 144.0f, - 240.0f, - }; - - float RoundFrameRate(float frameRate); + float motionSpeedMultiplier = 3.0; }; }