recording: Lock frameCounter incrementation on initial recording file load or during full/fast boot

Ensures that no frames of input are skipped over on the initial load of a recording file or during a fast/full boot when a recording file is active. Improved consistency.
This commit is contained in:
sonicfind 2020-09-13 14:06:07 -05:00 committed by refractionpcsx2
parent 5c5d3a770f
commit f881bd9bd6
5 changed files with 56 additions and 25 deletions

View File

@ -49,7 +49,7 @@ void SaveStateBase::InputRecordingFreeze()
else if (g_InputRecording.IsActive())
{
// Explicitly set the frame change tracking variable as to not
// detect loading a savestate as a frame being drawn
// detect saving or loading a savestate as a frame being drawn
g_InputRecordingControls.SetFrameCountTracker(g_FrameCount);
if (IsLoading())
@ -77,11 +77,11 @@ void Pcsx2App::RecordingReset()
}
else if (g_InputRecording.IsActive())
{
// Explicitly set the frame change tracking variable as to not
// detect rebooting as a frame being drawn
g_InputRecordingControls.SetFrameCountTracker(g_FrameCount);
g_InputRecording.SetFrameCounter(0);
g_InputRecordingControls.Lock(0, false);
}
else
g_InputRecordingControls.Resume();
}
InputRecording g_InputRecording;
@ -138,7 +138,7 @@ void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 &bufCount, u8 b
}
}
u32 InputRecording::GetFrameCounter()
s32 InputRecording::GetFrameCounter()
{
return frameCounter;
}
@ -218,13 +218,7 @@ void InputRecording::SetToReplayMode()
}
void InputRecording::SetFrameCounter(u32 newGFrameCount)
{
// Forces inputRecording to wait for a confirmed pause before resetting
// frameCounter to the proper value. Ensures that any lingering emulation
// before the load doesn't increment the already reset value
const bool initiallyPaused = g_InputRecordingControls.IsRecordingPaused();
if (!initiallyPaused)
g_InputRecordingControls.PauseImmediately();
{
if (newGFrameCount > startingFrame + g_InputRecording.GetInputRecordingData().GetTotalFrames())
{
recordingConLog(L"[REC]: Warning, you've loaded PCSX2 emulation to a point after the end of the original recording. This should be avoided.\n");
@ -246,10 +240,12 @@ void InputRecording::SetFrameCounter(u32 newGFrameCount)
SetToReplayMode();
}
}
else if (newGFrameCount == 0 && state == InputRecordingMode::Recording)
{
SetToReplayMode();
}
frameCounter = static_cast<s32>(newGFrameCount - startingFrame);
incrementUndo = true;
if (!initiallyPaused)
g_InputRecordingControls.Resume();
}
}
@ -263,6 +259,7 @@ void InputRecording::SetStartingFrame(u32 newStartingFrame)
}
frameCounter = 0;
initialLoad = false;
g_InputRecordingControls.Lock(startingFrame, inputRecordingData.FromSaveState());
}
void InputRecording::Stop()

View File

@ -27,7 +27,7 @@ public:
void ControllerInterrupt(u8 &data, u8 &port, u16 &BufCount, u8 buf[]);
// The running frame counter for the input recording
u32 GetFrameCounter();
s32 GetFrameCounter();
InputRecordingFile &GetInputRecordingData();

View File

@ -36,10 +36,28 @@ void InputRecordingControls::HandleFrameAdvanceAndPausing()
// often this is twice per frame but this may vary as Counters.cpp mentions the
// vsync timing can change.
//
// When loading a recording file or rebooting with a recording active, lock will be enabled.
// Emulation will be forced into and remain in a paused state until the transition in progress
// has completed - signaled when g_framecount and frameCountTracker are equal.
if (frameLock)
{
if (!emulationCurrentlyPaused && CoreThread.IsOpen() && CoreThread.IsRunning())
{
pauseEmulation = true;
emulationCurrentlyPaused = true;
CoreThread.PauseSelf();
}
else if (g_FrameCount == frameCountTracker)
{
frameLock = false;
g_InputRecordingControls.Resume();
}
return;
}
// As a safeguard, use the global g_FrameCount to know when the frame counter has truly changed.
//
//
// NOTE - Do not mutate g_FrameCount or use it's value to set the input recording's internal frame counter
if (frameCountTracker != g_FrameCount)
else if (frameCountTracker != g_FrameCount)
{
frameCountTracker = g_FrameCount;
g_InputRecording.IncrementFrameCounter();
@ -60,7 +78,7 @@ void InputRecordingControls::HandleFrameAdvanceAndPausing()
switchToReplay = false;
}
if (g_InputRecording.IsReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
if (g_InputRecording.IsReplaying() && g_InputRecording.GetFrameCounter() >= (s32)g_InputRecording.GetInputRecordingData().GetTotalFrames())
{
pauseEmulation = true;
}
@ -92,7 +110,7 @@ void InputRecordingControls::ResumeCoreThreadIfStarted()
void InputRecordingControls::FrameAdvance()
{
if (g_InputRecording.IsReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
if (g_InputRecording.IsReplaying() && g_InputRecording.GetFrameCounter() >= (s32)g_InputRecording.GetInputRecordingData().GetTotalFrames())
{
g_InputRecording.SetToRecordMode();
return;
@ -120,7 +138,7 @@ void InputRecordingControls::PauseImmediately()
return;
}
Pause();
if (pauseEmulation && CoreThread.IsOpen() && CoreThread.IsRunning())
if (CoreThread.IsOpen() && CoreThread.IsRunning())
{
emulationCurrentlyPaused = true;
CoreThread.PauseSelf();
@ -129,7 +147,7 @@ void InputRecordingControls::PauseImmediately()
void InputRecordingControls::Resume()
{
if (g_InputRecording.IsReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
if (g_InputRecording.IsReplaying() && g_InputRecording.GetFrameCounter() >= (s32)g_InputRecording.GetInputRecordingData().GetTotalFrames())
{
g_InputRecording.SetToRecordMode();
return;
@ -145,7 +163,7 @@ void InputRecordingControls::SetFrameCountTracker(u32 newFrame)
void InputRecordingControls::TogglePause()
{
if (pauseEmulation && g_InputRecording.IsReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
if (pauseEmulation && g_InputRecording.IsReplaying() && g_InputRecording.GetFrameCounter() >= (s32)g_InputRecording.GetInputRecordingData().GetTotalFrames())
{
g_InputRecording.SetToRecordMode();
return;
@ -156,7 +174,7 @@ void InputRecordingControls::TogglePause()
void InputRecordingControls::RecordModeToggle()
{
if (IsRecordingPaused() || g_InputRecording.IsReplaying() || g_InputRecording.GetFrameCounter() < g_InputRecording.GetInputRecordingData().GetTotalFrames())
if (IsRecordingPaused() || g_InputRecording.IsReplaying() || g_InputRecording.GetFrameCounter() < (s32)g_InputRecording.GetInputRecordingData().GetTotalFrames())
{
if (g_InputRecording.IsReplaying())
{
@ -170,4 +188,15 @@ void InputRecordingControls::RecordModeToggle()
else if (g_InputRecording.IsRecording())
switchToReplay = true;
}
void InputRecordingControls::Lock(u32 frame, bool savestate)
{
frameLock = true;
frameCountTracker = frame;
if (!savestate)
{
//Ensures that g_frameCount can be used to resume emulation after a fast/full boot
g_FrameCount = frame + 1;
}
}
#endif

View File

@ -53,6 +53,10 @@ public:
void TogglePause();
// Switches between recording and replaying the active input recording file
void RecordModeToggle();
// Enables the frame locking mechanism so that when recordings are loaded
// or when processing a reboot with a recording active that no frames are
// lost in prior emulation
void Lock(u32 frame, bool savestate);
private:
// Indicates if the input recording controls have explicitly paused emulation or not
@ -61,7 +65,7 @@ private:
// and should be cleared once a single frame has passed
bool frameAdvancing = false;
// The input recording frame that frame advancing began on
u32 frameAdvanceMarker = 0;
s32 frameAdvanceMarker = 0;
// Used to detect if the internal PCSX2 g_FrameCount has changed
u32 frameCountTracker = -1;
// Indicates if we intend to call CoreThread.PauseSelf() on the current or next available vsync
@ -70,6 +74,8 @@ private:
bool resumeEmulation = false;
// Indicates to switch to replay mode after the next vsync
bool switchToReplay = false;
// Used to stop recording frames from incrementing during a reset
bool frameLock = false;
};
extern InputRecordingControls g_InputRecordingControls;

View File

@ -926,7 +926,6 @@ void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event)
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(false);
m_menuRecording.FindChildItem(MenuId_Recording_Stop)->Enable(true);
}
g_InputRecordingControls.Resume();
}
void MainEmuFrame::Menu_Recording_Stop_Click(wxCommandEvent &event)