diff --git a/pcsx2/Recording/InputRecording.cpp b/pcsx2/Recording/InputRecording.cpp index 01dcd281f8..88a4745598 100644 --- a/pcsx2/Recording/InputRecording.cpp +++ b/pcsx2/Recording/InputRecording.cpp @@ -315,7 +315,7 @@ void InputRecording::SetupInitialState(u32 newStartingFrame) void InputRecording::FailedSavestate() { - inputRec::consoleLog(fmt::format("{}_SaveState.p2s is not compatible with this version of PCSX2", inputRecordingData.GetFilename())); + inputRec::consoleLog(fmt::format("{} is not compatible with this version of PCSX2", savestate)); inputRec::consoleLog(fmt::format("Original PCSX2 version used: {}", inputRecordingData.GetHeader().emu)); inputRecordingData.Close(); initialLoad = false; @@ -342,9 +342,10 @@ bool InputRecording::Create(wxString fileName, const bool fromSaveState, wxStrin state = InputRecordingMode::Recording; if (fromSaveState) { - if (wxFileExists(fileName + "_SaveState.p2s")) - wxCopyFile(fileName + "_SaveState.p2s", fileName + "_SaveState.p2s.bak", true); - StateCopy_SaveToFile(fileName + "_SaveState.p2s"); + savestate = fileName + "_SaveState.p2s"; + if (wxFileExists(savestate)) + wxCopyFile(savestate, savestate + ".bak", true); + StateCopy_SaveToFile(savestate); } else sApp.SysExecute(g_Conf->CdvdSource); @@ -363,12 +364,11 @@ bool InputRecording::Create(wxString fileName, const bool fromSaveState, wxStrin return true; } -bool InputRecording::Play(wxString fileName) +bool InputRecording::Play(wxWindow* parent, wxString filename) { - if (!inputRecordingData.OpenExisting(fileName)) + if (!inputRecordingData.OpenExisting(filename)) return false; - state = InputRecordingMode::Replaying; // Either load the savestate, or restart the game if (inputRecordingData.FromSaveState()) { @@ -378,42 +378,69 @@ bool InputRecording::Play(wxString fileName) inputRecordingData.Close(); return false; } - if (!wxFileExists(inputRecordingData.GetFilename() + "_SaveState.p2s")) + + savestate = inputRecordingData.GetFilename() + "_SaveState.p2s"; + if (!wxFileExists(savestate)) { - inputRec::consoleLog(fmt::format("Could not locate savestate file at location - {}_SaveState.p2s", - inputRecordingData.GetFilename().ToStdString())); - inputRecordingData.Close(); - return false; + wxFileDialog loadStateDialog(parent, _("Select the savestate that will accompany this recording"), L"", L"", + L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN); + if (loadStateDialog.ShowModal() == wxID_CANCEL) + { + inputRec::consoleLog(fmt::format("Could not locate savestate file at location - {}", savestate)); + inputRec::log("Savestate load failed"); + inputRecordingData.Close(); + return false; + } + + savestate = loadStateDialog.GetPath(); + inputRec::consoleLog(fmt::format("Base savestate set to {}", savestate)); } + state = InputRecordingMode::Replaying; initialLoad = true; - StateCopy_LoadFromFile(inputRecordingData.GetFilename() + "_SaveState.p2s"); + StateCopy_LoadFromFile(savestate); } else { + state = InputRecordingMode::Replaying; initialLoad = true; sApp.SysExecute(g_Conf->CdvdSource); } return true; } -bool InputRecording::GoToFirstFrame() +void InputRecording::GoToFirstFrame(wxWindow* parent) { if (inputRecordingData.FromSaveState()) { - if (!wxFileExists(inputRecordingData.GetFilename() + "_SaveState.p2s")) + if (!wxFileExists(savestate)) { - inputRec::consoleLog(fmt::format("[REC]: Could not locate savestate file at location - {}_SaveState.p2s\n", - inputRecordingData.GetFilename())); - return false; + const bool initiallyPaused = g_InputRecordingControls.IsPaused(); + + if (!initiallyPaused) + g_InputRecordingControls.PauseImmediately(); + + inputRec::consoleLog(fmt::format("Could not locate savestate file at location - {}\n", savestate)); + wxFileDialog loadStateDialog(parent, _("Select a savestate to accompany the recording with"), L"", L"", + L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN); + int result = loadStateDialog.ShowModal(); + if (!initiallyPaused) + g_InputRecordingControls.Resume(); + + if (result == wxID_CANCEL) + { + inputRec::log("Savestate load cancelled"); + return; + } + savestate = loadStateDialog.GetPath(); + inputRec::consoleLog(fmt::format ("Base savestate swapped to {}", savestate)); } - StateCopy_LoadFromFile(inputRecordingData.GetFilename() + "_SaveState.p2s"); + StateCopy_LoadFromFile(savestate); } else sApp.SysExecute(g_Conf->CdvdSource); if (IsRecording()) SetToReplayMode(); - return true; } wxString InputRecording::resolveGameName() diff --git a/pcsx2/Recording/InputRecording.h b/pcsx2/Recording/InputRecording.h index f21a7bfa9c..7157fe6801 100644 --- a/pcsx2/Recording/InputRecording.h +++ b/pcsx2/Recording/InputRecording.h @@ -85,7 +85,8 @@ public: // Create a new input recording file bool Create(wxString filename, const bool fromSaveState, wxString authorName); // Play an existing input recording from a file - bool Play(wxString filename); + // Calls a file dialog if it fails to locate the default base savestate + bool Play(wxWindow* parent, wxString filename); // Stop the active input recording void Stop(); // Displays the VirtualPad window for the chosen pad @@ -93,7 +94,8 @@ public: // Logs the padData and redraws the virtualPad windows of active pads void LogAndRedraw(); // Resets emulation to the beginning of a recording - bool GoToFirstFrame(); + // Calls a file dialog if it fails to locate the base savestate + void GoToFirstFrame(wxWindow* parent); // Resets a recording if the base savestate could not be loaded at the start void FailedSavestate(); @@ -123,6 +125,7 @@ private: s32 frameCounter = 0; bool incrementUndo = false; InputRecordingMode state = InputRecording::InputRecordingMode::NotActive; + wxString savestate; // Array of usable pads (currently, only 2) struct InputRecordingPad diff --git a/pcsx2/gui/GlobalCommands.cpp b/pcsx2/gui/GlobalCommands.cpp index 6ddb0ce35e..08a8dd3c51 100644 --- a/pcsx2/gui/GlobalCommands.cpp +++ b/pcsx2/gui/GlobalCommands.cpp @@ -545,10 +545,8 @@ namespace Implementations { if (g_Conf->EmuOptions.EnableRecordingTools && g_InputRecording.IsActive()) { - if (!g_InputRecording.GoToFirstFrame()) - { - sMainFrame.StopInputRecording(); - } + // Assumes that gui is active, as you can't access recording options without it + g_InputRecording.GoToFirstFrame(GetMainFramePtr()); } } diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp index 672168b8a6..62999b4961 100644 --- a/pcsx2/gui/MainMenuClicks.cpp +++ b/pcsx2/gui/MainMenuClicks.cpp @@ -485,10 +485,7 @@ void MainEmuFrame::Menu_BootCdvd_Click(wxCommandEvent& event) { #ifndef DISABLE_RECORDING if (g_InputRecording.IsActive()) - { - if (!g_InputRecording.GoToFirstFrame()) - StopInputRecording(); - } + g_InputRecording.GoToFirstFrame(this); else #endif { @@ -1058,7 +1055,7 @@ void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent& event) } StopInputRecording(); - if (!g_InputRecording.Play(openFileDialog.GetPath())) + if (!g_InputRecording.Play(this, openFileDialog.GetPath())) { if (!initiallyPaused) g_InputRecordingControls.Resume();