Move frame limiter, add limiters for SFD & loading screen.

This commit is contained in:
Skyth 2024-12-22 14:27:35 +03:00
parent 5ed5ff7ff0
commit 6bf029b0bb
5 changed files with 77 additions and 56 deletions

View file

@ -6,35 +6,6 @@
#include <user/config.h> #include <user/config.h>
#include <os/process.h> #include <os/process.h>
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<std::chrono::milliseconds>(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<std::string> restartArgs) void App::Restart(std::vector<std::string> restartArgs)
{ {
os::process::StartProcess(os::process::GetExecutablePath(), restartArgs, os::process::GetWorkingDirectory()); os::process::StartProcess(os::process::GetExecutablePath(), restartArgs, os::process::GetWorkingDirectory());

View file

@ -2,13 +2,6 @@
#include <user/config.h> #include <user/config.h>
struct FrameLimiter
{
std::chrono::steady_clock::time_point next;
void execute(int64_t fps);
};
class App class App
{ {
public: public:

View file

@ -1896,17 +1896,17 @@ struct Profiler
double values[PROFILER_VALUE_COUNT]; double values[PROFILER_VALUE_COUNT];
std::chrono::steady_clock::time_point start; std::chrono::steady_clock::time_point start;
void begin() void Begin()
{ {
start = std::chrono::steady_clock::now(); start = std::chrono::steady_clock::now();
} }
void end() void End()
{ {
value = std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - start).count(); value = std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - start).count();
} }
double updateAndReturnAverage() double UpdateAndReturnAverage()
{ {
values[g_profilerValueIndex] = value; values[g_profilerValueIndex] = value;
return std::accumulate(values, values + PROFILER_VALUE_COUNT, 0.0) / PROFILER_VALUE_COUNT; 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)) if (ImGui::Begin("Profiler", &g_profilerVisible))
{ {
g_applicationValues[g_profilerValueIndex] = App::s_deltaTime * 1000.0; g_applicationValues[g_profilerValueIndex] = App::s_deltaTime * 1000.0;
double renderDirectorAvg = g_renderDirectorProfiler.updateAndReturnAverage(); double renderDirectorAvg = g_renderDirectorProfiler.UpdateAndReturnAverage();
if (ImPlot::BeginPlot("Frame Time")) if (ImPlot::BeginPlot("Frame Time"))
{ {
@ -4849,7 +4849,7 @@ PPC_FUNC(sub_8258C8A0)
PPC_FUNC_IMPL(__imp__sub_8258CAE0); PPC_FUNC_IMPL(__imp__sub_8258CAE0);
PPC_FUNC(sub_8258CAE0) PPC_FUNC(sub_8258CAE0)
{ {
g_renderDirectorProfiler.begin(); g_renderDirectorProfiler.Begin();
if (g_needsResize) if (g_needsResize)
{ {
@ -4864,7 +4864,7 @@ PPC_FUNC(sub_8258CAE0)
__imp__sub_8258CAE0(ctx, base); __imp__sub_8258CAE0(ctx, base);
g_renderDirectorProfiler.end(); g_renderDirectorProfiler.End();
} }
void PostProcessResolutionFix(PPCRegister& r4, PPCRegister& f1, PPCRegister& f2) void PostProcessResolutionFix(PPCRegister& r4, PPCRegister& f1, PPCRegister& f2)

View file

@ -1,12 +1,10 @@
#include <cpu/code_cache.h>
#include <cpu/guest_code.h> #include <cpu/guest_code.h>
#include <api/SWA.h> #include <api/SWA.h>
#include <ui/game_window.h> #include <ui/game_window.h>
#include <user/config.h> #include <user/config.h>
#include <app.h> #include <app.h>
float m_lastLoadingFrameDelta = 0.0f;
std::chrono::high_resolution_clock::time_point m_lastLoadingFrameTime;
void DownForceDeltaTimeFixMidAsmHook(PPCRegister& f0) void DownForceDeltaTimeFixMidAsmHook(PPCRegister& f0)
{ {
f0.f64 = 30.0; f0.f64 = 30.0;
@ -79,14 +77,71 @@ void Camera2DSlopeLerpFixMidAsmHook(PPCRegister& t, PPCRegister& deltaTime)
t.f64 = ComputeLerpFactor(t.f64, deltaTime.f64 / 60.0); 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<float>(now - m_lastLoadingFrameTime).count(), 1.0f / 15.0f); if (now < g_next)
m_lastLoadingFrameTime = now; {
std::this_thread::sleep_for(std::chrono::floor<std::chrono::milliseconds>(g_next - now - 1ms));
auto pDeltaTime = (be<float>*)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<double>(now - g_prev).count(), 1.0 / 15.0);
g_prev = now;
uint8_t* base = reinterpret_cast<uint8_t*>(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<PPCFunc*>(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<std::chrono::milliseconds>(next - now - 1ms));
while (std::chrono::steady_clock::now() < next)
std::this_thread::yield();
} }

View file

@ -425,11 +425,6 @@ name = "ParticleTestDrawIndexedPrimitiveMidAsmHook"
address = 0x827D25AC address = 0x827D25AC
registers = ["r7"] registers = ["r7"]
[[midasm_hook]]
name = "LoadingScreenSpeedFixMidAsmHook"
address = 0x824DAB60
registers = ["r4"]
[[midasm_hook]] [[midasm_hook]]
name = "MotionBlurPrevInvViewProjectionMidAsmHook" name = "MotionBlurPrevInvViewProjectionMidAsmHook"
address = 0x82BA9E7C address = 0x82BA9E7C
@ -592,3 +587,10 @@ registers = ["r3"]
[[midasm_hook]] [[midasm_hook]]
name = "ApplicationUpdateMidAsmHook" name = "ApplicationUpdateMidAsmHook"
address = 0x822C0EC8 address = 0x822C0EC8
[[midasm_hook]]
name = "LoadingUpdateMidAsmHook"
address = 0x825360C8
registers = ["r31"]
jump_address_on_true = 0x825360C8
jump_address_on_false = 0x82536140