mirror of https://github.com/PCSX2/pcsx2.git
recording: Resolve issues discovered while testing around savestate handling
* Add a flag to explicitly indicate if the initial SS has been loaded. * Additionally: bracket formatting / spaces -> tabs.
This commit is contained in:
parent
6c80e6b93f
commit
74bba35765
|
@ -39,27 +39,51 @@ void SaveStateBase::InputRecordingFreeze()
|
|||
Freeze(g_FrameCount);
|
||||
|
||||
#ifndef DISABLE_RECORDING
|
||||
// Explicitly set the frame change tracking variable as to not
|
||||
// detect loading a savestate as a frame being drawn
|
||||
g_InputRecordingControls.SetFrameCountTracker(g_FrameCount);
|
||||
if (g_InputRecording.IsRecordingActive())
|
||||
{
|
||||
// Explicitly set the frame change tracking variable as to not
|
||||
// detect loading a savestate as a frame being drawn
|
||||
g_InputRecordingControls.SetFrameCountTracker(g_FrameCount);
|
||||
|
||||
// If the starting savestate has been loaded (on a current-frame recording) and a save-state is loaded while recording
|
||||
// or replaying the movie it is an undo operation that needs to be tracked.
|
||||
//
|
||||
// The reason it's also an undo operation when replaying is because the user can switch modes at any time
|
||||
// and begin undoing. While this isn't impossible to resolve, it's a separate issue and not of the utmost importance (this is just interesting metadata)
|
||||
if (IsLoading() && !g_InputRecording.IsSavestateInitializing())
|
||||
{
|
||||
g_InputRecording.GetInputRecordingData().IncrementUndoCount();
|
||||
// Reloading a save-state means the internal recording frame counter may need to be adjusted
|
||||
// Since we persist the g_FrameCount of the beginning of the movie, we can use it to recalculate it
|
||||
u32 newFrameCounter = g_FrameCount - (g_InputRecording.GetStartingFrame());
|
||||
// It is possible for someone to load a savestate outside of the original recording's context
|
||||
// this should be avoided (hence the log) but I don't think there is a mechanism to reverse loading
|
||||
// the save-state
|
||||
// Therefore, the best we can do is limit the frame counter within the min/max of the recording
|
||||
if (newFrameCounter < 0)
|
||||
{
|
||||
newFrameCounter = 0;
|
||||
recordingConLog(L"[REC]: Warning, you loaded a savestate outside of the bounds of the original recording. This should be avoided. Savestate's framecount has been ignored.\n");
|
||||
}
|
||||
else if (newFrameCounter >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
|
||||
{
|
||||
newFrameCounter = g_InputRecording.GetInputRecordingData().GetTotalFrames();
|
||||
recordingConLog(L"[REC]: Warning, you loaded a savestate outside of the bounds of the original recording. This should be avoided. Savestate's framecount has been ignored.\n");
|
||||
}
|
||||
g_InputRecording.SetFrameCounter(newFrameCounter);
|
||||
}
|
||||
}
|
||||
|
||||
// Loading a save-state is an asynchronous task, if we are playing a recording
|
||||
// that starts from a savestate (not power-on) and the starting (pcsx2 internal) frame
|
||||
// marker has not been set (which comes from the save-state), we initialize it.
|
||||
// TODO - get rid of the -1
|
||||
if (g_InputRecording.GetStartingFrame() == -1 && g_InputRecording.GetInputRecordingData().FromSaveState()) {
|
||||
if (g_InputRecording.IsSavestateInitializing())
|
||||
{
|
||||
g_InputRecording.SetStartingFrame(g_FrameCount);
|
||||
g_InputRecording.SavestateInitialized();
|
||||
// TODO - make a function of my own to simplify working with the logging macros
|
||||
recordingConLog(wxString::Format(L"[REC]: Internal Starting Frame: %d\n", g_InputRecording.GetStartingFrame()));
|
||||
}
|
||||
// Otherwise the starting savestate has been loaded and if loaded a save-state while recording the movie
|
||||
// it is an undo operation that needs to be tracked.
|
||||
else if (g_InputRecording.RecordingActive() && IsLoading())
|
||||
{
|
||||
g_InputRecording.GetInputRecordingData().IncrementUndoCount();
|
||||
// Reloading a save-state means the internal recording frame counter may need to be adjusted
|
||||
// Since we persist the g_FrameCount of the beginning of the movie, we can use it to recalculate it
|
||||
g_InputRecording.SetFrameCounter(g_FrameCount - (g_InputRecording.GetStartingFrame()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -142,7 +166,8 @@ u32 InputRecording::GetStartingFrame()
|
|||
void InputRecording::IncrementFrameCounter()
|
||||
{
|
||||
frameCounter++;
|
||||
if (state == InputRecordingMode::Recording) {
|
||||
if (state == InputRecordingMode::Recording)
|
||||
{
|
||||
GetInputRecordingData().SetTotalFrames(frameCounter);
|
||||
}
|
||||
}
|
||||
|
@ -152,16 +177,21 @@ bool InputRecording::IsInterruptFrame()
|
|||
return fInterruptFrame;
|
||||
}
|
||||
|
||||
bool InputRecording::IsRecordingReplaying()
|
||||
{
|
||||
return RecordingActive() && state == InputRecordingMode::Replaying;
|
||||
}
|
||||
|
||||
bool InputRecording::RecordingActive()
|
||||
bool InputRecording::IsRecordingActive()
|
||||
{
|
||||
return state != InputRecordingMode::NoneActive;
|
||||
}
|
||||
|
||||
bool InputRecording::IsSavestateInitializing()
|
||||
{
|
||||
return savestateInitializing;
|
||||
}
|
||||
|
||||
bool InputRecording::IsRecordingReplaying()
|
||||
{
|
||||
return IsRecordingActive() && state == InputRecordingMode::Replaying;
|
||||
}
|
||||
|
||||
wxString InputRecording::RecordingModeTitleSegment()
|
||||
{
|
||||
switch (state)
|
||||
|
@ -192,6 +222,11 @@ void InputRecording::RecordModeToggle()
|
|||
}
|
||||
}
|
||||
|
||||
void InputRecording::SavestateInitialized()
|
||||
{
|
||||
savestateInitializing = false;
|
||||
}
|
||||
|
||||
void InputRecording::SetFrameCounter(u32 newFrameCounter)
|
||||
{
|
||||
frameCounter = newFrameCounter;
|
||||
|
@ -210,7 +245,8 @@ void InputRecording::Stop()
|
|||
{
|
||||
// Reset the frame counter when starting a new recording
|
||||
frameCounter = 0;
|
||||
startingFrame = -1;
|
||||
startingFrame = 0;
|
||||
savestateInitializing = false;
|
||||
state = InputRecordingMode::NoneActive;
|
||||
if (inputRecordingData.Close())
|
||||
{
|
||||
|
@ -220,6 +256,7 @@ void InputRecording::Stop()
|
|||
|
||||
bool InputRecording::Create(wxString FileName, bool fromSaveState, wxString authorName)
|
||||
{
|
||||
savestateInitializing = fromSaveState;
|
||||
if (!inputRecordingData.OpenNew(FileName, fromSaveState))
|
||||
{
|
||||
return false;
|
||||
|
@ -232,6 +269,7 @@ bool InputRecording::Create(wxString FileName, bool fromSaveState, wxString auth
|
|||
{
|
||||
inputRecordingData.GetHeader().SetAuthor(authorName);
|
||||
}
|
||||
|
||||
// Set Game Name
|
||||
inputRecordingData.GetHeader().SetGameName(resolveGameName());
|
||||
// Write header contents
|
||||
|
@ -243,7 +281,7 @@ bool InputRecording::Create(wxString FileName, bool fromSaveState, wxString auth
|
|||
|
||||
bool InputRecording::Play(wxString fileName)
|
||||
{
|
||||
if (RecordingActive())
|
||||
if (IsRecordingActive())
|
||||
Stop();
|
||||
|
||||
if (!inputRecordingData.OpenExisting(fileName))
|
||||
|
@ -259,21 +297,17 @@ bool InputRecording::Play(wxString fileName)
|
|||
inputRecordingData.Close();
|
||||
return false;
|
||||
}
|
||||
FILE* ssFileCheck = wxFopen(inputRecordingData.GetFilename() + "_SaveState.p2s", "r");
|
||||
if (ssFileCheck == NULL)
|
||||
if (!wxFileExists(inputRecordingData.GetFilename() + "_SaveState.p2s"))
|
||||
{
|
||||
recordingConLog(wxString::Format("[REC]: Could not locate savestate file at location - %s_SaveState.p2s\n", inputRecordingData.GetFilename()));
|
||||
inputRecordingData.Close();
|
||||
return false;
|
||||
}
|
||||
fclose(ssFileCheck);
|
||||
savestateInitializing = true;
|
||||
StateCopy_LoadFromFile(inputRecordingData.GetFilename() + "_SaveState.p2s");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_InputRecordingControls.Resume();
|
||||
sApp.SysExecute();
|
||||
}
|
||||
|
||||
// Check if the current game matches with the one used to make the original recording
|
||||
if (!g_Conf->CurrentIso.IsEmpty())
|
||||
|
|
|
@ -41,8 +41,15 @@ public:
|
|||
bool IsInterruptFrame();
|
||||
|
||||
// If there is currently an input recording being played back or actively being recorded
|
||||
bool RecordingActive();
|
||||
bool IsRecordingReplaying();
|
||||
bool IsRecordingActive();
|
||||
|
||||
// Whether or not the recording's initial save state has yet to be loaded or saved and
|
||||
// the rest of the recording can be initialized
|
||||
// This is not applicable to recordings from a "power-on" state
|
||||
bool IsSavestateInitializing();
|
||||
|
||||
// If there is currently an input recording being played back
|
||||
bool IsRecordingReplaying();
|
||||
|
||||
// String representation of the current recording mode to be interpolated into the title
|
||||
wxString RecordingModeTitleSegment();
|
||||
|
@ -50,8 +57,12 @@ public:
|
|||
// Switches between recording and replaying the active input recording file
|
||||
void RecordModeToggle();
|
||||
|
||||
// Mark the recording's initial savestate as having been loaded or saved successfully
|
||||
void SavestateInitialized();
|
||||
|
||||
// Set the running frame counter for the input recording to an arbitrary value
|
||||
void SetFrameCounter(u32 newFrameCounter);
|
||||
|
||||
// Store the starting internal PCSX2 g_FrameCount value
|
||||
void SetStartingFrame(u32 newStartingFrame);
|
||||
|
||||
|
@ -65,18 +76,20 @@ public:
|
|||
void Stop();
|
||||
|
||||
private:
|
||||
enum class InputRecordingMode {
|
||||
enum class InputRecordingMode
|
||||
{
|
||||
NoneActive,
|
||||
Recording,
|
||||
Replaying,
|
||||
};
|
||||
|
||||
// DEPRECATED: Slated for removal
|
||||
bool fInterruptFrame = false;
|
||||
|
||||
InputRecordingFile inputRecordingData;
|
||||
bool savestateInitializing = false;
|
||||
u32 startingFrame = 0;
|
||||
InputRecordingMode state = InputRecording::InputRecordingMode::NoneActive;
|
||||
u32 frameCounter = 0;
|
||||
u32 startingFrame = -1;
|
||||
|
||||
// Resolve the name and region of the game currently loaded using the GameDB
|
||||
// If the game cannot be found in the DB, the fallback is the ISO filename
|
||||
|
|
|
@ -39,18 +39,23 @@ void InputRecordingControls::HandleFrameAdvanceAndPausing()
|
|||
// 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) {
|
||||
if (frameCountTracker != g_FrameCount)
|
||||
{
|
||||
frameCountTracker = g_FrameCount;
|
||||
g_InputRecording.IncrementFrameCounter();
|
||||
} else {
|
||||
if (pauseEmulation) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pauseEmulation)
|
||||
{
|
||||
emulationCurrentlyPaused = true;
|
||||
CoreThread.PauseSelf();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames()) {
|
||||
if (g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
|
||||
{
|
||||
pauseEmulation = true;
|
||||
}
|
||||
|
||||
|
@ -62,7 +67,8 @@ void InputRecordingControls::HandleFrameAdvanceAndPausing()
|
|||
}
|
||||
|
||||
// Pause emulation if we need to (either due to frame advancing, or pause has been explicitly toggled on)
|
||||
if (pauseEmulation && CoreThread.IsOpen() && CoreThread.IsRunning()) {
|
||||
if (pauseEmulation && CoreThread.IsOpen() && CoreThread.IsRunning())
|
||||
{
|
||||
emulationCurrentlyPaused = true;
|
||||
CoreThread.PauseSelf();
|
||||
}
|
||||
|
@ -70,7 +76,8 @@ void InputRecordingControls::HandleFrameAdvanceAndPausing()
|
|||
|
||||
void InputRecordingControls::ResumeCoreThreadIfStarted()
|
||||
{
|
||||
if (resumeEmulation && CoreThread.IsOpen() && CoreThread.IsPaused()) {
|
||||
if (resumeEmulation && CoreThread.IsOpen() && CoreThread.IsPaused())
|
||||
{
|
||||
CoreThread.Resume();
|
||||
resumeEmulation = false;
|
||||
emulationCurrentlyPaused = false;
|
||||
|
@ -81,7 +88,7 @@ void InputRecordingControls::FrameAdvance()
|
|||
{
|
||||
if (g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
|
||||
{
|
||||
g_InputRecording.RecordModeToggle();
|
||||
g_InputRecording.RecordModeToggle();
|
||||
return;
|
||||
}
|
||||
frameAdvanceMarker = g_InputRecording.GetFrameCounter();
|
||||
|
@ -102,11 +109,13 @@ void InputRecordingControls::Pause()
|
|||
|
||||
void InputRecordingControls::PauseImmediately()
|
||||
{
|
||||
if (CoreThread.IsPaused()) {
|
||||
if (CoreThread.IsPaused())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Pause();
|
||||
if (pauseEmulation && CoreThread.IsOpen() && CoreThread.IsRunning()) {
|
||||
if (pauseEmulation && CoreThread.IsOpen() && CoreThread.IsRunning())
|
||||
{
|
||||
emulationCurrentlyPaused = true;
|
||||
CoreThread.PauseSelf();
|
||||
}
|
||||
|
@ -114,8 +123,9 @@ void InputRecordingControls::PauseImmediately()
|
|||
|
||||
void InputRecordingControls::Resume()
|
||||
{
|
||||
if (g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames()) {
|
||||
g_InputRecording.RecordModeToggle();
|
||||
if (g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
|
||||
{
|
||||
g_InputRecording.RecordModeToggle();
|
||||
return;
|
||||
}
|
||||
pauseEmulation = false;
|
||||
|
@ -129,8 +139,9 @@ void InputRecordingControls::SetFrameCountTracker(u32 newFrame)
|
|||
|
||||
void InputRecordingControls::TogglePause()
|
||||
{
|
||||
if (pauseEmulation && g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames()) {
|
||||
g_InputRecording.RecordModeToggle();
|
||||
if (pauseEmulation && g_InputRecording.IsRecordingReplaying() && g_InputRecording.GetFrameCounter() >= g_InputRecording.GetInputRecordingData().GetTotalFrames())
|
||||
{
|
||||
g_InputRecording.RecordModeToggle();
|
||||
return;
|
||||
}
|
||||
pauseEmulation = !pauseEmulation;
|
||||
|
|
|
@ -38,26 +38,26 @@ public:
|
|||
|
||||
// Resume emulation (incase the emulation is currently paused) and pause after a single frame has passed
|
||||
void FrameAdvance();
|
||||
// Returns true if the input recording has been paused, which can occur:
|
||||
// - After a single frame has passed after InputRecordingControls::FrameAdvance
|
||||
// - Explicitly paused via InputRecordingControls::TogglePause
|
||||
bool IsRecordingPaused();
|
||||
// Returns true if the input recording has been paused, which can occur:
|
||||
// - After a single frame has passed after InputRecordingControls::FrameAdvance
|
||||
// - Explicitly paused via InputRecordingControls::TogglePause
|
||||
bool IsRecordingPaused();
|
||||
// Pause emulation at the next available Vsync
|
||||
void Pause();
|
||||
// Pause emulation immediately, not waiting for the next Vsync
|
||||
void PauseImmediately();
|
||||
// Resume emulation when the next pcsx2 App event is handled
|
||||
void Resume();
|
||||
void SetFrameCountTracker(u32 newFrame);
|
||||
void SetFrameCountTracker(u32 newFrame);
|
||||
// Alternates emulation between a paused and unpaused state
|
||||
void TogglePause();
|
||||
|
||||
private:
|
||||
// Indicates if the input recording controls have explicitly paused emulation or not
|
||||
bool emulationCurrentlyPaused = false;
|
||||
// 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;
|
||||
// Indicates if the input recording controls have explicitly paused emulation or not
|
||||
bool emulationCurrentlyPaused = false;
|
||||
// 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
|
||||
u32 frameAdvanceMarker = 0;
|
||||
// Used to detect if the internal PCSX2 g_FrameCount has changed
|
||||
|
|
|
@ -156,7 +156,7 @@ bool InputRecordingFile::OpenNew(const wxString path, bool fromSavestate)
|
|||
sApp.SysExecute();
|
||||
return true;
|
||||
}
|
||||
return open(path, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputRecordingFile::OpenExisting(const wxString path)
|
||||
|
|
|
@ -1059,7 +1059,7 @@ void Pcsx2App::OnProgramLogClosed( wxWindowID id )
|
|||
void Pcsx2App::OnMainFrameClosed( wxWindowID id )
|
||||
{
|
||||
#ifndef DISABLE_RECORDING
|
||||
if (g_InputRecording.RecordingActive())
|
||||
if (g_InputRecording.IsRecordingActive())
|
||||
{
|
||||
g_InputRecording.Stop();
|
||||
}
|
||||
|
|
|
@ -732,7 +732,7 @@ void GSFrame::OnUpdateTitle( wxTimerEvent& evt )
|
|||
#ifndef DISABLE_RECORDING
|
||||
wxString title;
|
||||
wxString movieMode;
|
||||
if (g_InputRecording.RecordingActive())
|
||||
if (g_InputRecording.IsRecordingActive())
|
||||
{
|
||||
title = templates.RecordingTemplate;
|
||||
title.Replace(L"${frame}", pxsFmt(L"%d", g_InputRecording.GetFrameCounter()));
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#ifndef DISABLE_RECORDING
|
||||
# include "Recording/InputRecording.h"
|
||||
# include "Recording/InputRecordingControls.h"
|
||||
# include "Recording/InputRecordingControls.h"
|
||||
# include "Recording/VirtualPad.h"
|
||||
#endif
|
||||
|
||||
|
@ -473,7 +473,6 @@ void MainEmuFrame::Menu_EnableBackupStates_Click( wxCommandEvent& )
|
|||
// (1st save after the toggle keeps the old pre-toggle value)..
|
||||
// wonder what that means for all the other menu checkboxes which only use AppSaveSettings... (avih)
|
||||
AppApplySettings();
|
||||
|
||||
AppSaveSettings();
|
||||
}
|
||||
|
||||
|
@ -530,7 +529,7 @@ void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent& event)
|
|||
else
|
||||
{
|
||||
//Properly close any currently loaded recording file before disabling
|
||||
if (g_InputRecording.RecordingActive())
|
||||
if (g_InputRecording.IsRecordingActive())
|
||||
Menu_Recording_Stop_Click(event);
|
||||
GetMenuBar()->Remove(TopLevelMenu_InputRecording);
|
||||
// Always turn controller logs off, but never turn it on by default
|
||||
|
@ -876,16 +875,16 @@ void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event)
|
|||
const bool initiallyPaused = g_InputRecordingControls.IsRecordingPaused();
|
||||
if (!initiallyPaused)
|
||||
g_InputRecordingControls.PauseImmediately();
|
||||
NewRecordingFrame* NewRecordingFrame = wxGetApp().GetNewRecordingFramePtr();
|
||||
if (NewRecordingFrame)
|
||||
NewRecordingFrame* newRecordingFrame = wxGetApp().GetNewRecordingFramePtr();
|
||||
if (newRecordingFrame)
|
||||
{
|
||||
if (NewRecordingFrame->ShowModal() == wxID_CANCEL)
|
||||
if (newRecordingFrame->ShowModal() == wxID_CANCEL)
|
||||
{
|
||||
if (!initiallyPaused)
|
||||
g_InputRecordingControls.Resume();
|
||||
return;
|
||||
}
|
||||
if (!g_InputRecording.Create(NewRecordingFrame->GetFile(), !NewRecordingFrame->GetFrom(), NewRecordingFrame->GetAuthor()))
|
||||
if (!g_InputRecording.Create(newRecordingFrame->GetFile(), !newRecordingFrame->GetFrom(), newRecordingFrame->GetAuthor()))
|
||||
{
|
||||
if (!initiallyPaused)
|
||||
g_InputRecordingControls.Resume();
|
||||
|
@ -913,7 +912,7 @@ void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event)
|
|||
}
|
||||
|
||||
wxString path = openFileDialog.GetPath();
|
||||
const bool recordingLoaded = g_InputRecording.RecordingActive();
|
||||
const bool recordingLoaded = g_InputRecording.IsRecordingActive();
|
||||
if (!g_InputRecording.Play(path))
|
||||
{
|
||||
if (recordingLoaded)
|
||||
|
|
Loading…
Reference in New Issue