From 6bf029b0bbdec98978e8925b516a1d7ba91fc649 Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Sun, 22 Dec 2024 14:27:35 +0300 Subject: [PATCH] Move frame limiter, add limiters for SFD & loading screen. --- UnleashedRecomp/app.cpp | 29 ---------- UnleashedRecomp/app.h | 7 --- UnleashedRecomp/gpu/video.cpp | 12 ++-- UnleashedRecomp/patches/fps_patches.cpp | 73 ++++++++++++++++++++++--- UnleashedRecompLib/config/SWA.toml | 12 ++-- 5 files changed, 77 insertions(+), 56 deletions(-) diff --git a/UnleashedRecomp/app.cpp b/UnleashedRecomp/app.cpp index 157b8424..f411a7bd 100644 --- a/UnleashedRecomp/app.cpp +++ b/UnleashedRecomp/app.cpp @@ -6,35 +6,6 @@ #include #include -void FrameLimiter::execute(int64_t fps) -{ - using namespace std::chrono_literals; - - auto now = std::chrono::steady_clock::now(); - - if (now < next) - { - std::this_thread::sleep_for(std::chrono::floor(next - now - 1ms)); - - while ((now = std::chrono::steady_clock::now()) < next) - std::this_thread::yield(); - } - else - { - next = now; - } - - next += 1000000000ns / fps; -} - -static FrameLimiter g_frameLimiter; - -void ApplicationUpdateMidAsmHook() -{ - if (Config::FPS >= 15 && Config::FPS < 240) - g_frameLimiter.execute(Config::FPS); -} - void App::Restart(std::vector restartArgs) { os::process::StartProcess(os::process::GetExecutablePath(), restartArgs, os::process::GetWorkingDirectory()); diff --git a/UnleashedRecomp/app.h b/UnleashedRecomp/app.h index d8441383..54794207 100644 --- a/UnleashedRecomp/app.h +++ b/UnleashedRecomp/app.h @@ -2,13 +2,6 @@ #include -struct FrameLimiter -{ - std::chrono::steady_clock::time_point next; - - void execute(int64_t fps); -}; - class App { public: diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index d3007697..376d10cb 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -1896,17 +1896,17 @@ struct Profiler double values[PROFILER_VALUE_COUNT]; std::chrono::steady_clock::time_point start; - void begin() + void Begin() { start = std::chrono::steady_clock::now(); } - void end() + void End() { value = std::chrono::duration(std::chrono::steady_clock::now() - start).count(); } - double updateAndReturnAverage() + double UpdateAndReturnAverage() { values[g_profilerValueIndex] = value; return std::accumulate(values, values + PROFILER_VALUE_COUNT, 0.0) / PROFILER_VALUE_COUNT; @@ -1939,7 +1939,7 @@ static void DrawProfiler() if (ImGui::Begin("Profiler", &g_profilerVisible)) { g_applicationValues[g_profilerValueIndex] = App::s_deltaTime * 1000.0; - double renderDirectorAvg = g_renderDirectorProfiler.updateAndReturnAverage(); + double renderDirectorAvg = g_renderDirectorProfiler.UpdateAndReturnAverage(); if (ImPlot::BeginPlot("Frame Time")) { @@ -4849,7 +4849,7 @@ PPC_FUNC(sub_8258C8A0) PPC_FUNC_IMPL(__imp__sub_8258CAE0); PPC_FUNC(sub_8258CAE0) { - g_renderDirectorProfiler.begin(); + g_renderDirectorProfiler.Begin(); if (g_needsResize) { @@ -4864,7 +4864,7 @@ PPC_FUNC(sub_8258CAE0) __imp__sub_8258CAE0(ctx, base); - g_renderDirectorProfiler.end(); + g_renderDirectorProfiler.End(); } void PostProcessResolutionFix(PPCRegister& r4, PPCRegister& f1, PPCRegister& f2) diff --git a/UnleashedRecomp/patches/fps_patches.cpp b/UnleashedRecomp/patches/fps_patches.cpp index 684421cb..d5155020 100644 --- a/UnleashedRecomp/patches/fps_patches.cpp +++ b/UnleashedRecomp/patches/fps_patches.cpp @@ -1,12 +1,10 @@ +#include #include #include #include #include #include -float m_lastLoadingFrameDelta = 0.0f; -std::chrono::high_resolution_clock::time_point m_lastLoadingFrameTime; - void DownForceDeltaTimeFixMidAsmHook(PPCRegister& f0) { f0.f64 = 30.0; @@ -79,14 +77,71 @@ void Camera2DSlopeLerpFixMidAsmHook(PPCRegister& t, PPCRegister& deltaTime) t.f64 = ComputeLerpFactor(t.f64, deltaTime.f64 / 60.0); } -void LoadingScreenSpeedFixMidAsmHook(PPCRegister& r4) +using namespace std::chrono_literals; + +static std::chrono::steady_clock::time_point g_next; + +void ApplicationUpdateMidAsmHook() { - auto now = std::chrono::high_resolution_clock::now(); + if (Config::FPS >= 15 && Config::FPS < 240) + { + auto now = std::chrono::steady_clock::now(); - m_lastLoadingFrameDelta = std::min(std::chrono::duration(now - m_lastLoadingFrameTime).count(), 1.0f / 15.0f); - m_lastLoadingFrameTime = now; + if (now < g_next) + { + std::this_thread::sleep_for(std::chrono::floor(g_next - now - 1ms)); - auto pDeltaTime = (be*)g_memory.Translate(r4.u32); + while ((now = std::chrono::steady_clock::now()) < g_next) + std::this_thread::yield(); + } + else + { + g_next = now; + } - *pDeltaTime = m_lastLoadingFrameDelta; + g_next += 1000000000ns / Config::FPS; + } } + +static std::chrono::steady_clock::time_point g_prev; + +bool LoadingUpdateMidAsmHook(PPCRegister& r31) +{ + auto now = std::chrono::steady_clock::now(); + double deltaTime = std::min(std::chrono::duration(now - g_prev).count(), 1.0 / 15.0); + g_prev = now; + + uint8_t* base = reinterpret_cast(g_memory.base); + uint32_t application = PPC_LOAD_U32(PPC_LOAD_U32(r31.u32 + 4)); + uint32_t update = PPC_LOAD_U32(PPC_LOAD_U32(application) + 20); + + g_ppcContext->r3.u32 = application; + g_ppcContext->f1.f64 = deltaTime; + reinterpret_cast(g_codeCache.Find(update))(*g_ppcContext, base); + + bool loading = PPC_LOAD_U8(0x83367A4C); + if (loading) + { + now = std::chrono::steady_clock::now(); + constexpr auto INTERVAL = 1000000000ns / 30; + auto next = now + (INTERVAL - now.time_since_epoch() % INTERVAL); + + std::this_thread::sleep_until(next); + } + + return loading; +} + +// ADXM_WaitVsync +PPC_FUNC_IMPL(__imp__sub_8312DBF8); +PPC_FUNC(sub_8312DBF8) +{ + auto now = std::chrono::steady_clock::now(); + constexpr auto INTERVAL = 1000000000ns / 60; + auto next = now + (INTERVAL - now.time_since_epoch() % INTERVAL); + + std::this_thread::sleep_for(std::chrono::floor(next - now - 1ms)); + + while (std::chrono::steady_clock::now() < next) + std::this_thread::yield(); +} \ No newline at end of file diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index 269911ea..6436a26b 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -425,11 +425,6 @@ name = "ParticleTestDrawIndexedPrimitiveMidAsmHook" address = 0x827D25AC registers = ["r7"] -[[midasm_hook]] -name = "LoadingScreenSpeedFixMidAsmHook" -address = 0x824DAB60 -registers = ["r4"] - [[midasm_hook]] name = "MotionBlurPrevInvViewProjectionMidAsmHook" address = 0x82BA9E7C @@ -592,3 +587,10 @@ registers = ["r3"] [[midasm_hook]] name = "ApplicationUpdateMidAsmHook" address = 0x822C0EC8 + +[[midasm_hook]] +name = "LoadingUpdateMidAsmHook" +address = 0x825360C8 +registers = ["r31"] +jump_address_on_true = 0x825360C8 +jump_address_on_false = 0x82536140 \ No newline at end of file