From b711c02c2585f3017952042551d4f4a09149ccc3 Mon Sep 17 00:00:00 2001 From: ThirteenAG Date: Fri, 12 Jan 2024 00:01:38 +0800 Subject: [PATCH] bugfixes --- data/plugins/GTAIV.EFLC.FusionFix.ini | 2 ++ source/fixes.ixx | 7 ----- source/framelimit.ixx | 29 ++++++++++++++++++++- source/frameratevigilante.ixx | 37 +++++++++++++++++++++++++++ source/loadingdelays.ixx | 20 ++++++++++----- source/shaders.ixx | 3 ++- 6 files changed, 83 insertions(+), 15 deletions(-) diff --git a/data/plugins/GTAIV.EFLC.FusionFix.ini b/data/plugins/GTAIV.EFLC.FusionFix.ini index 45b16ff3..0a9bb683 100644 --- a/data/plugins/GTAIV.EFLC.FusionFix.ini +++ b/data/plugins/GTAIV.EFLC.FusionFix.ini @@ -13,6 +13,8 @@ FrameLimitType = 2 // 1: realtime (thread-lock) | 2 FpsLimit = 0 // used when FPS Limit menu toggle is set to ON CutsceneFpsLimit = 0 ScriptCutsceneFovLimit = 30 +LoadingFpsLimit = 30 // used to avoid game freeze on loading (e.g. Off Route mission) +UnlockFramerateDuringLoadscreens = 0 [MISC] DefaultCameraAngleInTLAD = 0 diff --git a/source/fixes.ixx b/source/fixes.ixx index b422fb17..1ef0d58b 100644 --- a/source/fixes.ixx +++ b/source/fixes.ixx @@ -301,13 +301,6 @@ public: injector::MakeNOP(pattern.get_first(0), 16, true); } - // Off Route infinite loading - { - auto pattern = hook::pattern("68 ? ? ? ? FF B6 ? ? ? ? E8 ? ? ? ? 83 C4 08 84 C0 74 E2"); - if (!pattern.empty()) - injector::WriteMemory(pattern.get_first(1), 0xFFFFFFFF, true); - } - // Fix for light coronas being rendered through objects in water reflections. { static auto bCoronaShader = false; diff --git a/source/framelimit.ixx b/source/framelimit.ixx index 07af1420..c6adac84 100644 --- a/source/framelimit.ixx +++ b/source/framelimit.ixx @@ -15,6 +15,7 @@ float fFpsLimit; float fCutsceneFpsLimit; float fScriptCutsceneFpsLimit; float fScriptCutsceneFovLimit; +float fLoadingFpsLimit; class FrameLimiter { @@ -127,13 +128,15 @@ bool __cdecl sub_411F50(uint32_t* a1, uint32_t* a2) FrameLimiter FpsLimiter; FrameLimiter CutsceneFpsLimiter; FrameLimiter ScriptCutsceneFpsLimiter; +FrameLimiter LoadingFpsLimiter; bool(*CCutscenes__hasCutsceneFinished)(); bool(*CCamera__isWidescreenBordersActive)(); +bool bUnlockFramerateDuringLoadscreens = true; void __cdecl sub_855640() { static auto preset = FusionFixSettings.GetRef("PREF_FPS_LIMIT_PRESET"); - if (bLoadscreenShown && !*bLoadscreenShown && !bLoadingShown) + if ((bLoadscreenShown && !*bLoadscreenShown && !bLoadingShown) || !bUnlockFramerateDuringLoadscreens) { if (preset && *preset >= FusionFixSettings.FpsCaps.eCustom) { if (fFpsLimit > 0.0f || (*preset > FusionFixSettings.FpsCaps.eCustom && *preset < int32_t(FusionFixSettings.FpsCaps.data.size()))) @@ -151,6 +154,16 @@ void __cdecl sub_855640() } } +bool __cdecl sub_403CD0(HANDLE hHandle, DWORD dwMilliseconds) +{ + if (CMenuManager__m_MenuActive) + { + if (!*CMenuManager__m_MenuActive) + LoadingFpsLimiter.Sync(); + } + return hHandle && WaitForSingleObject(hHandle, dwMilliseconds) == WAIT_OBJECT_0; +} + class Framelimit { public: @@ -166,6 +179,8 @@ public: fCutsceneFpsLimit = static_cast(iniReader.ReadInteger("FRAMELIMIT", "CutsceneFpsLimit", 0)); fScriptCutsceneFpsLimit = static_cast(iniReader.ReadInteger("FRAMELIMIT", "ScriptCutsceneFpsLimit", 0)); fScriptCutsceneFovLimit = static_cast(iniReader.ReadInteger("FRAMELIMIT", "ScriptCutsceneFovLimit", 0)); + fLoadingFpsLimit = static_cast(iniReader.ReadInteger("FRAMELIMIT", "LoadingFpsLimit", 30)); + bUnlockFramerateDuringLoadscreens = iniReader.ReadInteger("FRAMELIMIT", "UnlockFramerateDuringLoadscreens", 0) != 0; //if (fFpsLimit || fCutsceneFpsLimit || fScriptCutsceneFpsLimit) { @@ -180,6 +195,7 @@ public: FpsLimiter.Init(mode, fFpsLimit); CutsceneFpsLimiter.Init(mode, fCutsceneFpsLimit); ScriptCutsceneFpsLimiter.Init(mode, fScriptCutsceneFpsLimit); + LoadingFpsLimiter.Init(mode, std::clamp(fLoadingFpsLimit, 30.0f, FLT_MAX)); auto pattern = find_pattern("E8 ? ? ? ? 84 C0 75 89", "E8 ? ? ? ? 84 C0 75 15 38 05"); CCutscenes__hasCutsceneFinished = (bool(*)()) injector::GetBranchDestination(pattern.get_first(0)).get(); @@ -224,6 +240,17 @@ public: } }; injector::MakeInline(pattern.get_first(0), pattern.get_first(6)); } + + // Off Route infinite loading + { + auto pattern = hook::pattern("E8 ? ? ? ? 83 C4 08 84 C0 74 E2"); + if (!pattern.empty()) + injector::MakeCALL(pattern.get_first(), sub_403CD0, true); + + pattern = hook::pattern("E8 ? ? ? ? 83 C4 0C 84 C0 75 25"); + if (!pattern.empty()) + injector::MakeCALL(pattern.get_first(), sub_403CD0, true); + } }; FusionFix::onShutdownEvent() += []() diff --git a/source/frameratevigilante.ixx b/source/frameratevigilante.ixx index 807c0467..eb34803c 100644 --- a/source/frameratevigilante.ixx +++ b/source/frameratevigilante.ixx @@ -50,6 +50,43 @@ public: } }; injector::MakeInline(pattern.get_first(0), pattern.get_first(6)); } + + pattern = hook::pattern("F3 0F 10 05 ? ? ? ? F3 0F 58 C1 F3 0F 11 05 ? ? ? ? EB 36"); + static auto f1032790 = *pattern.get_first(4); + if (!pattern.empty()) + { + struct LoadingTextSpeed + { + void operator()(SafetyHookContext& regs) + { + regs.xmm0.f32[0] = (*f1032790) / 10.0f; + } + }; injector::MakeInline2(pattern.get_first(0), pattern.get_first(8)); + } + + pattern = hook::pattern("F3 0F 59 05 ? ? ? ? F3 0F 59 05 ? ? ? ? F3 0F 59 05 ? ? ? ? F3 0F 58 05 ? ? ? ? F3 0F 11 05"); + if (!pattern.empty()) + { + struct LoadingTextSpeed2 + { + void operator()(SafetyHookContext& regs) + { + regs.xmm0.f32[0] *= (1000.0f) / 10.0f; + } + }; injector::MakeInline2(pattern.get_first(0), pattern.get_first(8)); + } + + pattern = hook::pattern("F3 0F 58 0D ? ? ? ? 0F 5B C0 F3 0F 11 0D"); + if (!pattern.empty()) + { + struct LoadingTextSparks + { + void operator()(SafetyHookContext& regs) + { + regs.xmm1.f32[0] += (0.085f) / 10.0f; + } + }; injector::MakeInline2(pattern.get_first(0), pattern.get_first(8)); + } }; } } FramerateVigilante; \ No newline at end of file diff --git a/source/loadingdelays.ixx b/source/loadingdelays.ixx index f1aef085..8e82643a 100644 --- a/source/loadingdelays.ixx +++ b/source/loadingdelays.ixx @@ -8,14 +8,17 @@ import common; import framelimit; import comvars; +bool bRestoreSleep = false; void WINAPI FusionSleep(DWORD dwMilliseconds) { - auto bMenuActive = CMenuManager__m_MenuActive && *CMenuManager__m_MenuActive; - auto bLoadscreenActive = (bLoadscreenShown && *bLoadscreenShown) || bLoadingShown; - - if (!bMenuActive && bLoadscreenActive) - return Sleep(0); + if (!bRestoreSleep) + { + auto bMenuActive = CMenuManager__m_MenuActive && *CMenuManager__m_MenuActive; + auto bLoadscreenActive = (bLoadscreenShown && *bLoadscreenShown) || bLoadingShown; + if (!bMenuActive && bLoadscreenActive) + return Sleep(0); + } return Sleep(dwMilliseconds); } @@ -33,11 +36,16 @@ public: injector::MakeJMP(pattern.get_first(), hook::get_pattern("6A FF 6A 01 6A 00 6A 01 6A 01 6A 00 6A 01 6A 01 6A 00 6A 00 6A 00 6A 00 6A 00 6A 00 B9 ? ? ? ? C6 46 04 00")); }; - FusionFix::onAfterUALRestoredIATEvent() += []() + FusionFix::onInitEvent() += []() { IATHook::Replace(GetModuleHandleA(NULL), "kernel32.DLL", std::forward_as_tuple("Sleep", FusionSleep) ); }; + + FusionFix::onGameInitEvent() += []() + { + bRestoreSleep = true; + }; } } LoadingDelays; \ No newline at end of file diff --git a/source/shaders.ixx b/source/shaders.ixx index bcd777f7..49205af8 100644 --- a/source/shaders.ixx +++ b/source/shaders.ixx @@ -91,8 +91,9 @@ public: // Setup variables for shaders static auto dw11A2948 = *find_pattern("C7 05 ? ? ? ? ? ? ? ? 0F 85 ? ? ? ? 6A 00", "D8 05 ? ? ? ? D9 1D ? ? ? ? 83 05").get_first(2); static auto dw103E49C = *hook::get_pattern("A3 ? ? ? ? C7 80", 1); + auto bLoadscreenActive = (bLoadscreenShown && *bLoadscreenShown) || bLoadingShown; - if (*dw103E49C) + if (*dw103E49C && !bLoadscreenActive) { static Cam cam = 0; Natives::GetRootCam(&cam);