From 58040d478aad749ffae87b0097c26614bf820a4f Mon Sep 17 00:00:00 2001 From: Eladash Date: Thu, 28 Oct 2021 21:53:34 +0300 Subject: [PATCH] rsx: Implement NTSC fixup mode, improve VBLANK accuracy --- rpcs3/Emu/RSX/RSXThread.cpp | 31 ++++++++++++++++++++++++++++--- rpcs3/Emu/system_config.h | 1 + 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index ff71fc757c..3d0bcd2902 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -641,20 +641,45 @@ namespace rsx #endif u64 start_time = get_system_time(); + u64 vblank_rate = g_cfg.video.vblank_rate; + u64 vblank_period = 1'000'000 + u64{g_cfg.video.vblank_ntsc.get()} * 1000; + + u64 local_vblank_count = 0; + // TODO: exit condition while (!is_stopped()) { + // Get current time const u64 current = get_system_time(); - const u64 period_time = 1000000 / g_cfg.video.vblank_rate; - const u64 wait_for = period_time - std::min(current - start_time, period_time); + + // Calculate the time at which we need to send a new VBLANK signal + const u64 post_event_time = start_time + (local_vblank_count + 1) * vblank_period / vblank_rate; + + // Calculate time remaining to that time (0 if we passed it) + const u64 wait_for = current >= post_event_time ? 0 : post_event_time - current; + + // Substract host operating system min sleep quantom to get sleep time const u64 wait_sleep = wait_for - u64{wait_for >= host_min_quantum} * host_min_quantum; if (!wait_for) { { - start_time += period_time; + local_vblank_count++; vblank_count++; + if (local_vblank_count == vblank_rate) + { + // Advance start_time to the moment of the current VBLANK + // Which is the last VBLANK event in this period + // This is in order for multiplication by ratio above to use only small numbers + start_time += vblank_period; + local_vblank_count = 0; + + // We have a rare chance to update settings without losing precision whenever local_vblank_count is 0 + vblank_rate = g_cfg.video.vblank_rate; + vblank_period = 1'000'000 + u64{g_cfg.video.vblank_ntsc.get()} * 1000; + } + if (isHLE) { if (vblank_handler) diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 099baa1f21..da0b170b76 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -142,6 +142,7 @@ struct cfg_root : cfg::node cfg::_int<0, 30000000> driver_recovery_timeout{ this, "Driver Recovery Timeout", 1000000, true }; cfg::_int<0, 16667> driver_wakeup_delay{ this, "Driver Wake-Up Delay", 1, true }; cfg::_int<1, 1800> vblank_rate{ this, "Vblank Rate", 60, true }; // Changing this from 60 may affect game speed in unexpected ways + cfg::_bool vblank_ntsc{ this, "Vblank NTSC Fixup", false, true }; cfg::_bool decr_memory_layout{ this, "DECR memory layout", false}; // Force enable increased allowed main memory range as DECR console struct node_vk : cfg::node