HostInterface: Add helpers for resume save state

This commit is contained in:
Connor McLaughlin 2020-02-16 00:14:47 +09:00
parent 5f3be68028
commit e738b87a25
2 changed files with 90 additions and 5 deletions

View file

@ -432,7 +432,7 @@ bool HostInterface::LoadState(const char* filename)
return true;
}
bool HostInterface::LoadState(bool global, u32 slot)
bool HostInterface::LoadState(bool global, s32 slot)
{
if (!global && (!m_system || m_system->GetRunningCode().empty()))
{
@ -468,7 +468,7 @@ bool HostInterface::SaveState(const char* filename)
return result;
}
bool HostInterface::SaveState(bool global, u32 slot)
bool HostInterface::SaveState(bool global, s32 slot)
{
const std::string& code = m_system->GetRunningCode();
if (!global && code.empty())
@ -481,6 +481,48 @@ bool HostInterface::SaveState(bool global, u32 slot)
return SaveState(save_path.c_str());
}
bool HostInterface::ResumeSystemFromState(const char* filename, bool boot_on_failure)
{
if (!BootSystemFromFile(filename))
return false;
const bool global = m_system->GetRunningCode().empty();
const std::string path =
global ? GetGlobalSaveStateFileName(-1) : GetGameSaveStateFileName(m_system->GetRunningCode().c_str(), -1);
if (FileSystem::FileExists(path.c_str()))
{
if (!LoadState(path.c_str()) && !boot_on_failure)
{
DestroySystem();
return false;
}
}
else
{
ReportFormattedError("Resume save state not found for '%s' ('%s').", m_system->GetRunningCode().c_str(),
m_system->GetRunningTitle().c_str());
if (!boot_on_failure)
{
DestroySystem();
return false;
}
}
return true;
}
bool HostInterface::ResumeSystemFromMostRecentState()
{
const std::string path = GetMostRecentResumeSaveStatePath();
if (path.empty())
{
ReportError("No resume save state found.");
return false;
}
return LoadState(path.c_str());
}
void HostInterface::UpdateSpeedLimiterState()
{
m_speed_limiter_enabled = m_settings.speed_limiter_enabled && !m_speed_limiter_temp_disabled;
@ -660,7 +702,7 @@ std::vector<HostInterface::SaveStateInfo> HostInterface::GetAvailableSaveStates(
std::vector<SaveStateInfo> si;
std::string path;
auto add_path = [&si](std::string path, s32 slot, bool global) {
auto add_path = [&si](const std::string& path, s32 slot, bool global) {
FILESYSTEM_STAT_DATA sd;
if (!FileSystem::StatFile(path.c_str(), &sd))
return;
@ -670,6 +712,7 @@ std::vector<HostInterface::SaveStateInfo> HostInterface::GetAvailableSaveStates(
if (game_code && std::strlen(game_code) > 0)
{
add_path(GetGameSaveStateFileName(game_code, -1), -1, false);
for (s32 i = 1; i <= PER_GAME_SAVE_STATE_SLOTS; i++)
add_path(GetGameSaveStateFileName(game_code, i), i, false);
}
@ -680,6 +723,26 @@ std::vector<HostInterface::SaveStateInfo> HostInterface::GetAvailableSaveStates(
return si;
}
std::string HostInterface::GetMostRecentResumeSaveStatePath() const
{
std::vector<FILESYSTEM_FIND_DATA> files;
if (!FileSystem::FindFiles(GetUserDirectoryRelativePath("savestates").c_str(), "*resume.sav", FILESYSTEM_FIND_FILES,
&files) ||
files.empty())
{
return {};
}
FILESYSTEM_FIND_DATA* most_recent = &files[0];
for (FILESYSTEM_FIND_DATA& file : files)
{
if (file.ModificationTime > most_recent->ModificationTime)
most_recent = &file;
}
return std::move(most_recent->FileName);
}
void HostInterface::SetDefaultSettings()
{
m_settings.region = ConsoleRegion::Auto;
@ -856,3 +919,12 @@ void HostInterface::SetTimerResolutionIncreased(bool enabled)
timeEndPeriod(1);
#endif
}
bool HostInterface::SaveResumeSaveState()
{
if (!m_system)
return false;
const bool global = m_system->GetRunningCode().empty();
return SaveState(global, -1);
}

View file

@ -46,13 +46,23 @@ public:
void DestroySystem();
/// Loads the current emulation state from file. Specifying a slot of -1 loads the "resume" game state.
bool LoadState(bool global, u32 slot);
bool LoadState(bool global, s32 slot);
bool LoadState(const char* filename);
/// Saves the current emulation state to a file. Specifying a slot of -1 saves the "resume" save state.
bool SaveState(bool global, u32 slot);
bool SaveState(bool global, s32 slot);
bool SaveState(const char* filename);
/// Loads the resume save state for the given game. Optionally boots the game anyway if loading fails.
bool ResumeSystemFromState(const char* filename, bool boot_on_failure);
/// Loads the most recent resume save state. This may be global or per-game.
bool ResumeSystemFromMostRecentState();
/// Saves the resume save state, call when shutting down. Not called automatically on DestroySystem() since that can
/// be called as a result of an error.
bool SaveResumeSaveState();
virtual void ReportError(const char* message);
virtual void ReportMessage(const char* message);
@ -135,6 +145,9 @@ protected:
/// Returns a list of save states for the specified game code.
std::vector<SaveStateInfo> GetAvailableSaveStates(const char* game_code) const;
/// Returns the most recent resume save state.
std::string GetMostRecentResumeSaveStatePath() const;
/// Loads the BIOS image for the specified region.
std::optional<std::vector<u8>> GetBIOSImage(ConsoleRegion region);