CommonHostInterface: Add undo load state feature

This commit is contained in:
Connor McLaughlin
2021-07-03 15:58:29 +10:00
parent af7dc40f5f
commit 762ab3ff43
4 changed files with 85 additions and 0 deletions

View File

@ -215,6 +215,7 @@ bool CommonHostInterface::BootSystem(std::shared_ptr<SystemBootParameters> param
void CommonHostInterface::DestroySystem()
{
m_undo_load_state.reset();
SetTimerResolutionIncreased(false);
m_save_state_selector_ui->Close();
m_display->SetPostProcessingChain({});
@ -700,9 +701,57 @@ void CommonHostInterface::UpdateControllerInterface()
}
}
bool CommonHostInterface::UndoLoadState()
{
if (!m_undo_load_state)
return false;
Assert(System::IsValid());
m_undo_load_state->SeekAbsolute(0);
if (!System::LoadState(m_undo_load_state.get()))
{
ReportError("Failed to load undo state, resetting system.");
m_undo_load_state.reset();
ResetSystem();
return false;
}
System::ResetPerformanceCounters();
System::ResetThrottler();
#ifdef WITH_CHEEVOS
Cheevos::Reset();
#endif
Log_InfoPrintf("Loaded undo save state.");
m_undo_load_state.reset();
return true;
}
bool CommonHostInterface::SaveUndoLoadState()
{
if (m_undo_load_state)
m_undo_load_state.reset();
m_undo_load_state = ByteStream_CreateGrowableMemoryStream(nullptr, System::MAX_SAVE_STATE_SIZE);
if (!System::SaveState(m_undo_load_state.get(), 0))
{
AddOSDMessage(TranslateStdString("OSDMessage", "Failed to save undo load state."), 15.0f);
m_undo_load_state.reset();
return false;
}
Log_InfoPrintf("Saved undo load state: % " PRIu64 " bytes", m_undo_load_state->GetSize());
return true;
}
bool CommonHostInterface::LoadState(const char* filename)
{
const bool system_was_valid = System::IsValid();
if (system_was_valid)
SaveUndoLoadState();
const bool result = HostInterface::LoadState(filename);
if (system_was_valid || !result)
{
@ -711,6 +760,9 @@ bool CommonHostInterface::LoadState(const char* filename)
#endif
}
if (!result && CanUndoLoadState())
UndoLoadState();
return result;
}
@ -2320,6 +2372,12 @@ void CommonHostInterface::RegisterSaveStateHotkeys()
m_save_state_selector_ui->SelectNextSlot();
});
RegisterHotkey(StaticString(TRANSLATABLE("Hotkeys", "Save States")), StaticString("UndoLoadState"),
StaticString(TRANSLATABLE("Hotkeys", "Undo Load State")), [this](bool pressed) {
if (pressed)
UndoLoadState();
});
for (u32 slot = 1; slot <= PER_GAME_SAVE_STATE_SLOTS; slot++)
{
RegisterHotkey(StaticString(TRANSLATABLE("Hotkeys", "Save States")),

View File

@ -155,6 +155,9 @@ public:
/// Returns true if the fullscreen UI is enabled.
ALWAYS_INLINE bool IsFullscreenUIEnabled() const { return m_fullscreen_ui_enabled; }
/// Returns true if an undo load state exists.
ALWAYS_INLINE bool CanUndoLoadState() const { return static_cast<bool>(m_undo_load_state); }
/// Parses command line parameters for all frontends.
bool ParseCommandLineParameters(int argc, char* argv[], std::unique_ptr<SystemBootParameters>* out_boot_params);
@ -176,6 +179,9 @@ public:
/// Powers off the system, optionally saving the resume state.
void PowerOffSystem(bool save_resume_state);
/// Undoes a load state, i.e. restores the state prior to the load.
bool UndoLoadState();
/// Loads state from the specified filename.
bool LoadState(const char* filename);
@ -352,6 +358,9 @@ protected:
/// Executes per-frame tasks such as controller polling.
virtual void PollAndUpdate();
/// Saves the undo load state, so it can be restored.
bool SaveUndoLoadState();
virtual std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) override;
virtual s32 GetAudioOutputVolume() const override;
virtual void UpdateControllerInterface();
@ -548,6 +557,9 @@ private:
};
std::vector<ControllerAutoFireState> m_controller_autofires;
// temporary save state, created when loading, used to undo load state
std::unique_ptr<ByteStream> m_undo_load_state;
#ifdef WITH_DISCORD_PRESENCE
// discord rich presence
bool m_discord_presence_enabled = false;