From b26a9556f77fcb99cdee3df19d0171db01fff4e1 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 22 Apr 2024 00:19:44 +1000 Subject: [PATCH] System: Improve reset determinism --- src/core/cpu_core.cpp | 7 ++++--- src/core/gpu.cpp | 6 ++++-- src/core/spu.cpp | 3 ++- src/core/system.cpp | 2 +- src/core/timers.cpp | 15 ++++++++------- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index 7d8ff20cf..681ba1bb5 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -183,8 +183,6 @@ void CPU::Shutdown() void CPU::Reset() { - g_state.pending_ticks = 0; - g_state.downcount = 0; g_state.exception_raised = false; g_state.bus_error = false; @@ -208,8 +206,11 @@ void CPU::Reset() if (g_settings.gpu_pgxp_enable) PGXP::Reset(); - // TODO: This consumes cycles... + // This consumes cycles, so do it first. SetPC(RESET_VECTOR); + + g_state.pending_ticks = 0; + g_state.downcount = 0; } bool CPU::DoState(StateWrapper& sw) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 9fc0cc810..62998ab8d 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -164,6 +164,10 @@ void GPU::Reset(bool clear_vram) if (clear_vram) std::memset(g_vram, 0, sizeof(g_vram)); + // Force event to reschedule itself. + m_crtc_tick_event->Deactivate(); + m_command_tick_event->Deactivate(); + SoftReset(); UpdateDisplay(); } @@ -211,7 +215,6 @@ void GPU::SoftReset() SetTextureWindow(0); UpdateDMARequest(); UpdateCRTCConfig(); - UpdateCRTCTickEvent(); UpdateCommandTickEvent(); UpdateGPUIdle(); } @@ -342,7 +345,6 @@ bool GPU::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_displ if (update_display) UpdateDisplay(); - UpdateCRTCTickEvent(); UpdateCommandTickEvent(); } diff --git a/src/core/spu.cpp b/src/core/spu.cpp index 8d260dcc9..b0d9e0726 100644 --- a/src/core/spu.cpp +++ b/src/core/spu.cpp @@ -529,8 +529,9 @@ void SPU::Reset() v.ignore_loop_address = false; } - s_transfer_fifo.Clear(); + s_tick_event->Deactivate(); s_transfer_event->Deactivate(); + s_transfer_fifo.Clear(); s_ram.fill(0); UpdateEventInterval(); } diff --git a/src/core/system.cpp b/src/core/system.cpp index 222d9820b..1f586fd28 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -2266,6 +2266,7 @@ void System::InternalReset() if (IsShutdown()) return; + TimingEvents::Reset(); CPU::Reset(); CPU::CodeCache::Reset(); if (g_settings.gpu_pgxp_enable) @@ -2284,7 +2285,6 @@ void System::InternalReset() PCDrv::Reset(); s_frame_number = 1; s_internal_frame_number = 0; - TimingEvents::Reset(); InterruptExecution(); ResetPerformanceCounters(); diff --git a/src/core/timers.cpp b/src/core/timers.cpp index 00470a739..eb5cb49d9 100644 --- a/src/core/timers.cpp +++ b/src/core/timers.cpp @@ -75,9 +75,9 @@ static void UpdateSysClkEvent(); static std::unique_ptr s_sysclk_event; static std::array s_states{}; -static TickCount s_syclk_ticks_carry = 0; // 0 unless overclocking is enabled -static u32 s_sysclk_div_8_carry = 0; // partial ticks for timer 3 with sysclk/8 -}; // namespace Timers +static TickCount s_sysclk_ticks_carry = 0; // 0 unless overclocking is enabled +static u32 s_sysclk_div_8_carry = 0; // partial ticks for timer 3 with sysclk/8 +}; // namespace Timers void Timers::Initialize() { @@ -105,7 +105,8 @@ void Timers::Reset() cs.irq_done = false; } - s_syclk_ticks_carry = 0; + s_sysclk_event->Deactivate(); + s_sysclk_ticks_carry = 0; s_sysclk_div_8_carry = 0; UpdateSysClkEvent(); } @@ -124,7 +125,7 @@ bool Timers::DoState(StateWrapper& sw) sw.Do(&cs.irq_done); } - sw.Do(&s_syclk_ticks_carry); + sw.Do(&s_sysclk_ticks_carry); sw.Do(&s_sysclk_div_8_carry); if (sw.IsReading()) @@ -135,7 +136,7 @@ bool Timers::DoState(StateWrapper& sw) void Timers::CPUClocksChanged() { - s_syclk_ticks_carry = 0; + s_sysclk_ticks_carry = 0; } bool Timers::IsUsingExternalClock(u32 timer) @@ -264,7 +265,7 @@ void Timers::CheckForIRQ(u32 timer, u32 old_counter) void Timers::AddSysClkTicks(void*, TickCount sysclk_ticks, TickCount ticks_late) { - sysclk_ticks = System::UnscaleTicksToOverclock(sysclk_ticks, &s_syclk_ticks_carry); + sysclk_ticks = System::UnscaleTicksToOverclock(sysclk_ticks, &s_sysclk_ticks_carry); if (!s_states[0].external_counting_enabled && s_states[0].counting_enabled) AddTicks(0, sysclk_ticks);