recording: Complete separation of pasuing execution

Unhooks the execution of emulation pausing from pre-set static frame counts
This commit is contained in:
sonicfind 2020-12-18 12:42:58 -06:00 committed by refractionpcsx2
parent b5b74388f4
commit d49acfc087
4 changed files with 20 additions and 54 deletions

View File

@ -482,7 +482,7 @@ static __fi void VSyncStart(u32 sCycle)
{
// It is imperative that any frame locking that must happen occurs before Vsync is started
// Not doing so would sacrifice a frame of a savestate-based recording when loading any savestate
g_InputRecordingControls.HandleFrameCountLocking();
g_InputRecordingControls.HandlePausingAndLocking();
}
#endif
@ -543,7 +543,7 @@ static __fi void VSyncEnd(u32 sCycle)
#ifndef DISABLE_RECORDING
if (g_Conf->EmuOptions.EnableRecordingTools)
{
g_InputRecordingControls.HandleFrameAdvanceAndPausing();
g_InputRecordingControls.CheckPauseStatus();
}
#endif

View File

@ -46,15 +46,8 @@ void SaveStateBase::InputRecordingFreeze()
// marker has not been set (which comes from the save-state), we initialize it.
if (g_InputRecording.IsInitialLoad())
g_InputRecording.SetupInitialState(g_FrameCount);
else if (g_InputRecording.IsActive())
{
// Explicitly set the frame change tracking variable as to not
// detect saving or loading a savestate as a frame being drawn
g_InputRecordingControls.SetFrameCountTracker(g_FrameCount);
if (IsLoading())
g_InputRecording.SetFrameCounter(g_FrameCount);
}
else if (g_InputRecording.IsActive() && IsLoading())
g_InputRecording.SetFrameCounter(g_FrameCount);
}
#endif
}
@ -186,7 +179,7 @@ void InputRecording::IncrementFrameCounter()
switch (state)
{
case InputRecordingMode::Recording:
GetInputRecordingData().SetTotalFrames(frameCounter);
inputRecordingData.SetTotalFrames(frameCounter);
[[fallthrough]];
case InputRecordingMode::Replaying:
if (frameCounter == inputRecordingData.GetTotalFrames())
@ -264,11 +257,11 @@ void InputRecording::SetToReplayMode()
void InputRecording::SetFrameCounter(u32 newGFrameCount)
{
if (newGFrameCount > startingFrame + (u32)g_InputRecording.GetInputRecordingData().GetTotalFrames())
if (newGFrameCount > startingFrame + (u32)inputRecordingData.GetTotalFrames())
{
inputRec::consoleLog("Warning, you've loaded PCSX2 emulation to a point after the end of the original recording. This should be avoided.");
inputRec::consoleLog("Savestate's framecount has been ignored.");
frameCounter = g_InputRecording.GetInputRecordingData().GetTotalFrames();
frameCounter = inputRecordingData.GetTotalFrames();
if (state == InputRecordingMode::Replaying)
SetToRecordMode();
incrementUndo = false;
@ -283,7 +276,7 @@ void InputRecording::SetFrameCounter(u32 newGFrameCount)
}
else if (newGFrameCount == 0 && state == InputRecordingMode::Recording)
SetToReplayMode();
frameCounter = static_cast<s32>(newGFrameCount - startingFrame);
frameCounter = newGFrameCount - (s32)startingFrame;
incrementUndo = true;
}
}
@ -316,7 +309,6 @@ void InputRecording::SetupInitialState(u32 newStartingFrame)
SetToReplayMode();
}
g_InputRecordingControls.DisableFrameAdvance();
if (inputRecordingData.FromSaveState())
inputRec::consoleLog(fmt::format("Internal Starting Frame: {}", startingFrame));
frameCounter = 0;

View File

@ -29,7 +29,7 @@
InputRecordingControls g_InputRecordingControls;
void InputRecordingControls::HandleFrameAdvanceAndPausing()
void InputRecordingControls::CheckPauseStatus()
{
// We do not want to increment/advance anything while the frame lock mechanism is active
if (frameLock)
@ -58,21 +58,14 @@ void InputRecordingControls::HandleFrameAdvanceAndPausing()
pauseEmulation = true;
}
}
// Pause emulation if we need to (either due to frame advancing, or pause has been explicitly toggled on)
if (pauseEmulation && CoreThread.IsOpen() && CoreThread.IsRunning())
{
emulationCurrentlyPaused = true;
CoreThread.PauseSelf();
}
}
void InputRecordingControls::HandleFrameCountLocking()
void InputRecordingControls::HandlePausingAndLocking()
{
// Explicit frame locking
if (frameLock)
{
if (g_FrameCount == frameCountTracker)
if (g_FrameCount == frameLockTracker)
{
frameLock = false;
Resume();
@ -83,11 +76,7 @@ void InputRecordingControls::HandleFrameCountLocking()
CoreThread.PauseSelf();
}
}
// Soft frame locking due to a savestate
//
// This must be done here and not somewhere else as emulation would advance a single frame
// after loading a savestate even with emulation already paused
else if (g_FrameCount == frameCountTracker && pauseEmulation)
else if (pauseEmulation && CoreThread.IsOpen() && CoreThread.IsRunning())
{
emulationCurrentlyPaused = true;
CoreThread.PauseSelf();
@ -156,16 +145,6 @@ void InputRecordingControls::Resume()
resumeEmulation = true;
}
void InputRecordingControls::SetFrameCountTracker(u32 newFrame)
{
frameCountTracker = newFrame;
}
void InputRecordingControls::DisableFrameAdvance()
{
frameAdvancing = false;
}
void InputRecordingControls::TogglePause()
{
if (pauseEmulation &&
@ -198,7 +177,8 @@ void InputRecordingControls::RecordModeToggle()
void InputRecordingControls::Lock(u32 frame)
{
frameLock = true;
frameCountTracker = frame;
frameLockTracker = frame;
frameAdvancing = false;
//Ensures that g_frameCount can be used to resume emulation after a fast/full boot
if (!g_InputRecording.GetInputRecordingData().FromSaveState())
g_FrameCount = frame + 1;

View File

@ -22,18 +22,18 @@ class InputRecordingControls
public:
// Intended to be called at the end of each frame, but will no-op if frame lock is active
//
// Will pause emulation if:
// Will set the pausing parameters for emulation if:
// - The InputRecordingControls::FrameAdvance was hit on the previous frame
// - Emulation was explicitly paused using InputRecordingControls::TogglePause
// - We are replaying an input recording and have hit the end
void HandleFrameAdvanceAndPausing();
void CheckPauseStatus();
// When loading a recording file or booting 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
//
// Additonally, this function will ensure emulation stays paused after loading a savestate
void HandleFrameCountLocking();
// This function also handles actually pausing emulation when told to
void HandlePausingAndLocking();
// Called much more frequently than HandleFrameAdvanceAndPausing, instead of being per frame
// this hooks into pcsx2's main App event handler as it has to be able to resume emulation
@ -58,10 +58,6 @@ public:
void PauseImmediately();
// Resume emulation when the next pcsx2 App event is handled
void Resume();
void SetFrameCountTracker(u32 newFrame);
// Sets frameAdvancing variable to false
// Used to restrict a frameAdvanceTracker value from transferring between recordings
void DisableFrameAdvance();
// Alternates emulation between a paused and unpaused state
void TogglePause();
// Switches between recording and replaying the active input recording file
@ -77,10 +73,6 @@ private:
// Indicates on the next VSync if we are frame advancing, this value
// and should be cleared once a single frame has passed
bool frameAdvancing = false;
// The input recording frame that frame advancing began on
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
bool pauseEmulation = false;
// Indicates if we intend to call CoreThread.Resume() when the next pcsx2 App event is handled
@ -89,6 +81,8 @@ private:
bool switchToReplay = false;
// Used to stop recording frames from incrementing during a reset
bool frameLock = false;
// The frame value to use as the frame lock reset point
u32 frameLockTracker = 0;
};
extern InputRecordingControls g_InputRecordingControls;