diff --git a/src/core/system.cpp b/src/core/system.cpp index b4c22bab0..e37f18cd9 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -2562,7 +2562,13 @@ void System::ClearMemorySaveStates(bool reallocate_resources, bool recycle_textu s_state.memory_save_state_count = 0; if (reallocate_resources && !s_state.memory_save_states.empty()) - AllocateMemoryStates(s_state.memory_save_states.size(), recycle_textures); + { + if (!AllocateMemoryStates(s_state.memory_save_states.size(), recycle_textures)) + return; + } + + // immediately save a rewind state next frame + s_state.rewind_save_counter = (s_state.rewind_save_frequency > 0) ? 0 : -1; } void System::FreeMemoryStateStorage(bool release_memory, bool release_textures, bool recycle_textures) @@ -4962,7 +4968,8 @@ bool System::LoadOneRewindState() if (s_state.memory_save_state_count == 0) return false; - LoadMemoryState(PopMemoryState(), true); + // keep the last state so we can go back to it with smaller frequencies + LoadMemoryState((s_state.memory_save_state_count > 1) ? PopMemoryState() : GetFirstMemoryState(), true); // back in time, need to reset perf counters GPUThread::RunOnThread(&PerformanceCounters::Reset); @@ -4977,10 +4984,10 @@ bool System::IsRewinding() void System::SetRewinding(bool enabled) { + const bool was_enabled = IsRewinding(); + if (enabled) { - const bool was_enabled = IsRewinding(); - // Try to rewind at the replay speed, or one per second maximum. const float load_frequency = std::min(g_settings.rewind_save_frequency, 1.0f); s_state.rewind_load_frequency = static_cast(std::ceil(load_frequency * s_state.video_frame_rate)); @@ -4988,8 +4995,10 @@ void System::SetRewinding(bool enabled) if (!was_enabled && s_state.system_executing) { - // Drop the save we just created, since we don't want to rewind to where we are. - PopMemoryState(); + // Drop the last save if we just created it, since we don't want to rewind to where we are. + if (s_state.rewind_save_counter == s_state.rewind_save_frequency && s_state.memory_save_state_count > 0) + PopMemoryState(); + s_state.system_interrupted = true; } } @@ -4997,6 +5006,15 @@ void System::SetRewinding(bool enabled) { s_state.rewind_load_frequency = -1; s_state.rewind_load_counter = -1; + + if (was_enabled) + { + // reset perf counters to avoid the spike + GPUThread::RunOnThread(&PerformanceCounters::Reset); + + // and wait the full frequency before filling a new rewind slot + s_state.rewind_save_counter = s_state.rewind_save_frequency; + } } } @@ -5017,6 +5035,10 @@ void System::DoRewind() Host::PumpMessagesOnCPUThread(); IdlePollUpdate(); + // get back into it straight away if we're no longer rewinding + if (!IsRewinding()) + return; + Throttle(Timer::GetCurrentValue(), s_state.next_frame_time); }