mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Code cleanup for save state notification, add metadata field
This commit is contained in:
+14
-13
@@ -414,7 +414,7 @@ int g_screenshotFailures;
|
||||
Path backup = GetSysDirectory(DIRECTORY_SAVESTATE) / LOAD_UNDO_NAME;
|
||||
|
||||
std::string prefix(gamePrefix);
|
||||
auto saveCallback = [prefix, fn, backup, slot, callback](Status status, std::string_view message) {
|
||||
auto saveCallback = [prefix, fn, backup, slot, callback](Status status, std::string_view message, std::string_view metadata) {
|
||||
if (status != Status::FAILURE) {
|
||||
DeleteIfExists(backup);
|
||||
File::Rename(backup.WithExtraExtension(".tmp"), backup);
|
||||
@@ -438,7 +438,7 @@ int g_screenshotFailures;
|
||||
} else {
|
||||
if (callback) {
|
||||
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
||||
callback(Status::FAILURE, sy->T("Failed to load state. Error in the file system."));
|
||||
callback(Status::FAILURE, sy->T("Failed to load state. Error in the file system."), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -451,7 +451,7 @@ int g_screenshotFailures;
|
||||
if (g_Config.sStateLoadUndoGame != gamePrefix) {
|
||||
if (callback) {
|
||||
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
||||
callback(Status::FAILURE, sy->T("Error: load undo state is from a different game"));
|
||||
callback(Status::FAILURE, sy->T("Error: load undo state is from a different game"), "");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -463,7 +463,7 @@ int g_screenshotFailures;
|
||||
} else {
|
||||
if (callback) {
|
||||
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
||||
callback(Status::FAILURE, sy->T("Failed to load state for load undo. Error in the file system."));
|
||||
callback(Status::FAILURE, sy->T("Failed to load state for load undo. Error in the file system."), "");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -480,7 +480,7 @@ int g_screenshotFailures;
|
||||
Path shot = GenerateSaveSlotPath(gamePrefix, slot, SCREENSHOT_EXTENSION);
|
||||
|
||||
std::string prefix(gamePrefix);
|
||||
auto renameCallback = [fn, fnUndo, prefix, slot, callback](Status status, std::string_view message) {
|
||||
auto renameCallback = [fn, fnUndo, prefix, slot, callback](Status status, std::string_view message, std::string_view metadata) {
|
||||
if (status != Status::FAILURE) {
|
||||
if (g_Config.bEnableStateUndo) {
|
||||
DeleteIfExists(fnUndo);
|
||||
@@ -494,7 +494,7 @@ int g_screenshotFailures;
|
||||
File::Rename(fn.WithExtraExtension(".tmp"), fn);
|
||||
}
|
||||
if (callback) {
|
||||
callback(status, message);
|
||||
callback(status, message, "");
|
||||
}
|
||||
};
|
||||
// Let's also create a screenshot.
|
||||
@@ -508,7 +508,7 @@ int g_screenshotFailures;
|
||||
} else {
|
||||
if (callback) {
|
||||
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
||||
callback(Status::FAILURE, sy->T("Failed to save state. Error in the file system."));
|
||||
callback(Status::FAILURE, sy->T("Failed to save state. Error in the file system."), "");
|
||||
}
|
||||
}
|
||||
Rescan(gamePrefix);
|
||||
@@ -714,7 +714,7 @@ int g_screenshotFailures;
|
||||
return copy;
|
||||
}
|
||||
|
||||
bool HandleLoadFailure(bool wasRewinding) {
|
||||
static bool HandleLoadFailure(bool wasRewinding, std::string *metadata) {
|
||||
if (wasRewinding) {
|
||||
WARN_LOG(Log::SaveState, "HandleLoadFailure - trying a rewind state.");
|
||||
// Okay, first, let's give the next rewind state a shot - maybe we can at least not reset entirely.
|
||||
@@ -722,7 +722,7 @@ int g_screenshotFailures;
|
||||
CChunkFileReader::Error result;
|
||||
do {
|
||||
std::string errorString;
|
||||
result = rewindStates.Restore(&errorString);
|
||||
result = rewindStates.Restore(&errorString, metadata);
|
||||
} while (result == CChunkFileReader::ERROR_BROKEN_STATE);
|
||||
|
||||
if (result == CChunkFileReader::ERROR_NONE) {
|
||||
@@ -813,6 +813,7 @@ int g_screenshotFailures;
|
||||
CChunkFileReader::Error result;
|
||||
Status callbackResult;
|
||||
std::string callbackMessage;
|
||||
std::string callbackMetadata;
|
||||
std::string title;
|
||||
|
||||
auto sc = GetI18NCategory(I18NCat::SCREEN);
|
||||
@@ -849,7 +850,7 @@ int g_screenshotFailures;
|
||||
#endif
|
||||
g_lastSaveTime = time_now_d();
|
||||
} else if (result == CChunkFileReader::ERROR_BROKEN_STATE) {
|
||||
HandleLoadFailure(false);
|
||||
HandleLoadFailure(false, &callbackMetadata);
|
||||
callbackMessage = std::string(i18nLoadFailure) + ": " + errorString;
|
||||
ERROR_LOG(Log::SaveState, "Load state failure: %s", errorString.c_str());
|
||||
callbackResult = Status::FAILURE;
|
||||
@@ -909,7 +910,7 @@ int g_screenshotFailures;
|
||||
|
||||
case OperationType::Rewind:
|
||||
INFO_LOG(Log::SaveState, "Rewinding to recent savestate snapshot");
|
||||
result = rewindStates.Restore(&errorString);
|
||||
result = rewindStates.Restore(&errorString, &callbackMetadata);
|
||||
if (result == CChunkFileReader::ERROR_NONE) {
|
||||
callbackMessage = sc->T("Loaded State");
|
||||
callbackResult = Status::SUCCESS;
|
||||
@@ -917,7 +918,7 @@ int g_screenshotFailures;
|
||||
Core_ResetException();
|
||||
} else if (result == CChunkFileReader::ERROR_BROKEN_STATE) {
|
||||
// Cripes. Good news is, we might have more. Let's try those too, better than a reset.
|
||||
if (HandleLoadFailure(true)) {
|
||||
if (HandleLoadFailure(true, &callbackMetadata)) {
|
||||
// Well, we did rewind, even if too much...
|
||||
callbackMessage = sc->T("Loaded State");
|
||||
callbackResult = Status::SUCCESS;
|
||||
@@ -940,7 +941,7 @@ int g_screenshotFailures;
|
||||
}
|
||||
|
||||
if (op.callback) {
|
||||
op.callback(callbackResult, callbackMessage);
|
||||
op.callback(callbackResult, callbackMessage, callbackMetadata);
|
||||
}
|
||||
}
|
||||
if (operations.size()) {
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ namespace SaveState {
|
||||
WARNING,
|
||||
SUCCESS,
|
||||
};
|
||||
typedef std::function<void(Status status, std::string_view message)> Callback;
|
||||
typedef std::function<void(Status status, std::string_view message, std::string_view metadata)> Callback;
|
||||
|
||||
static const char * const SCREENSHOT_EXTENSION = "jpg";
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Common/Thread/ThreadUtil.h"
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Core/SaveState.h"
|
||||
#include "Core/SaveStateRewind.h"
|
||||
#include "Core/Core.h"
|
||||
@@ -42,7 +43,7 @@ CChunkFileReader::Error StateRingbuffer::Save() {
|
||||
return err;
|
||||
}
|
||||
|
||||
CChunkFileReader::Error StateRingbuffer::Restore(std::string *errorString) {
|
||||
CChunkFileReader::Error StateRingbuffer::Restore(std::string *errorString, std::string *metadata) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
|
||||
// No valid states left.
|
||||
@@ -53,9 +54,12 @@ CChunkFileReader::Error StateRingbuffer::Restore(std::string *errorString) {
|
||||
if (states_[n].empty())
|
||||
return CChunkFileReader::ERROR_BAD_FILE;
|
||||
|
||||
auto pa = GetI18NCategory(I18NCat::PAUSE);
|
||||
|
||||
static std::vector<u8> buffer;
|
||||
LockedDecompress(buffer, states_[n], bases_[baseMapping_[n]]);
|
||||
CChunkFileReader::Error error = LoadFromRam(buffer, errorString);
|
||||
*metadata = pa->T("Rewind");
|
||||
rewindLastTime_ = time_now_d();
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
}
|
||||
|
||||
CChunkFileReader::Error Save();
|
||||
CChunkFileReader::Error Restore(std::string *errorString);
|
||||
CChunkFileReader::Error Restore(std::string *errorString, std::string *metadata);
|
||||
void ScheduleCompress(std::vector<u8> *result, const std::vector<u8> *state, const std::vector<u8> *base);
|
||||
void Compress(std::vector<u8> &result, const std::vector<u8> &state, const std::vector<u8> &base);
|
||||
void LockedDecompress(std::vector<u8> &result, const std::vector<u8> &compressed, const std::vector<u8> &base);
|
||||
|
||||
+6
-13
@@ -74,7 +74,6 @@ using namespace std::placeholders;
|
||||
#include "Core/Screenshot.h"
|
||||
#include "UI/ImDebugger/ImDebugger.h"
|
||||
#include "Core/HLE/__sceAudio.h"
|
||||
// #include "Core/HLE/proAdhoc.h"
|
||||
#include "Core/HW/Display.h"
|
||||
|
||||
#include "UI/BackgroundAudio.h"
|
||||
@@ -533,12 +532,6 @@ void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) {
|
||||
lastImguiEnabled_ = false;
|
||||
}
|
||||
|
||||
static void AfterSaveStateAction(SaveState::Status status, std::string_view message) {
|
||||
if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) {
|
||||
g_OSD.Show(status == SaveState::Status::SUCCESS ? OSDType::MESSAGE_SUCCESS : OSDType::MESSAGE_ERROR, message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0);
|
||||
}
|
||||
}
|
||||
|
||||
void EmuScreen::focusChanged(ScreenFocusChange focusChange) {
|
||||
Screen::focusChanged(focusChange);
|
||||
|
||||
@@ -609,7 +602,7 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) {
|
||||
if (newGamePath.GetFileExtension() == ".ppst") {
|
||||
// TODO: Should verify that it's for the correct game....
|
||||
INFO_LOG(Log::Loader, "New game is a save state - just load it.");
|
||||
SaveState::Load(newGamePath, -1, [](SaveState::Status status, std::string_view message) {
|
||||
SaveState::Load(newGamePath, -1, [](SaveState::Status status, std::string_view message, std::string_view metadata) {
|
||||
Core_Resume();
|
||||
System_Notify(SystemNotification::DISASSEMBLY);
|
||||
});
|
||||
@@ -965,7 +958,7 @@ void EmuScreen::ProcessVKey(VirtKey virtKey) {
|
||||
case VIRTKEY_REWIND:
|
||||
if (!Achievements::WarnUserIfHardcoreModeActive(false) && !NetworkWarnUserIfOnlineAndCantSavestate() && !bootPending_) {
|
||||
if (SaveState::CanRewind()) {
|
||||
SaveState::Rewind(&AfterSaveStateAction);
|
||||
SaveState::Rewind(&ShowMessageAfterSaveStateAction);
|
||||
} else {
|
||||
g_OSD.Show(OSDType::MESSAGE_WARNING, sc->T("norewind", "No rewind save states available"), 2.0);
|
||||
}
|
||||
@@ -1058,12 +1051,12 @@ void EmuScreen::ProcessVKey(VirtKey virtKey) {
|
||||
|
||||
case VIRTKEY_SAVE_STATE:
|
||||
if (!Achievements::WarnUserIfHardcoreModeActive(true) && !NetworkWarnUserIfOnlineAndCantSavestate() && !bootPending_) {
|
||||
SaveState::SaveSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, &AfterSaveStateAction);
|
||||
SaveState::SaveSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, &ShowMessageAfterSaveStateAction);
|
||||
}
|
||||
break;
|
||||
case VIRTKEY_LOAD_STATE:
|
||||
if (!Achievements::WarnUserIfHardcoreModeActive(false) && !NetworkWarnUserIfOnlineAndCantSavestate() && !bootPending_) {
|
||||
SaveState::LoadSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, &AfterSaveStateAction);
|
||||
SaveState::LoadSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, &ShowMessageAfterSaveStateAction);
|
||||
}
|
||||
break;
|
||||
case VIRTKEY_PREVIOUS_SLOT:
|
||||
@@ -2053,8 +2046,8 @@ void EmuScreen::AutoLoadSaveState() {
|
||||
}
|
||||
|
||||
if (g_Config.iAutoLoadSaveState && autoSlot != -1) {
|
||||
SaveState::LoadSlot(gamePrefix, autoSlot, [this, autoSlot](SaveState::Status status, std::string_view message) {
|
||||
AfterSaveStateAction(status, message);
|
||||
SaveState::LoadSlot(gamePrefix, autoSlot, [this, autoSlot](SaveState::Status status, std::string_view message, std::string_view metadata) {
|
||||
ShowMessageAfterSaveStateAction(status, message, metadata);
|
||||
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
||||
if (status == SaveState::Status::FAILURE) {
|
||||
autoLoadFailed_ = true;
|
||||
|
||||
+2
-6
@@ -133,6 +133,7 @@
|
||||
#include "UI/OnScreenDisplay.h"
|
||||
#include "UI/RemoteISOScreen.h"
|
||||
#include "UI/Theme.h"
|
||||
#include "UI/PauseScreen.h"
|
||||
#include "UI/UIAtlas.h"
|
||||
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
@@ -693,12 +694,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
g_BackgroundAudio.SFX().Init();
|
||||
|
||||
if (!boot_filename.empty() && stateToLoad.Valid()) {
|
||||
SaveState::Load(stateToLoad, -1, [](SaveState::Status status, std::string_view message) {
|
||||
if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) {
|
||||
g_OSD.Show(status == SaveState::Status::SUCCESS ? OSDType::MESSAGE_SUCCESS : OSDType::MESSAGE_ERROR,
|
||||
message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0);
|
||||
}
|
||||
});
|
||||
SaveState::Load(stateToLoad, -1, &ShowMessageAfterSaveStateAction);
|
||||
}
|
||||
|
||||
if (g_Config.bAchievementsEnable) {
|
||||
|
||||
+9
-9
@@ -76,10 +76,10 @@
|
||||
void copyDeepLinkForPath(std::string_view filePath);
|
||||
#endif
|
||||
|
||||
static void AfterSaveStateAction(SaveState::Status status, std::string_view message) {
|
||||
if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) {
|
||||
void ShowMessageAfterSaveStateAction(SaveState::Status status, std::string_view message, std::string_view metadata) {
|
||||
if (!message.empty()) {
|
||||
g_OSD.Show(status == SaveState::Status::SUCCESS ? OSDType::MESSAGE_SUCCESS : OSDType::MESSAGE_ERROR,
|
||||
message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0);
|
||||
message, metadata, status == SaveState::Status::SUCCESS ? 2.0 : 5.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ private:
|
||||
void ScreenshotViewScreen::OnSaveState(UI::EventParams &e) {
|
||||
if (!NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
g_Config.iCurrentStateSlot = slot_;
|
||||
SaveState::SaveSlot(saveStatePrefix_, slot_, &AfterSaveStateAction);
|
||||
SaveState::SaveSlot(saveStatePrefix_, slot_, &ShowMessageAfterSaveStateAction);
|
||||
TriggerFinish(DR_OK); //OK will close the pause screen as well
|
||||
}
|
||||
}
|
||||
@@ -161,7 +161,7 @@ void ScreenshotViewScreen::OnSaveState(UI::EventParams &e) {
|
||||
void ScreenshotViewScreen::OnLoadState(UI::EventParams &e) {
|
||||
if (!NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
g_Config.iCurrentStateSlot = slot_;
|
||||
SaveState::LoadSlot(saveStatePrefix_, slot_, &AfterSaveStateAction);
|
||||
SaveState::LoadSlot(saveStatePrefix_, slot_, &ShowMessageAfterSaveStateAction);
|
||||
TriggerFinish(DR_OK);
|
||||
}
|
||||
}
|
||||
@@ -303,7 +303,7 @@ void SaveSlotView::Draw(UIContext &dc) {
|
||||
void SaveSlotView::OnLoadState(UI::EventParams &e) {
|
||||
if (!NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
g_Config.iCurrentStateSlot = slot_;
|
||||
SaveState::LoadSlot(saveStatePrefix_, slot_, &AfterSaveStateAction);
|
||||
SaveState::LoadSlot(saveStatePrefix_, slot_, &ShowMessageAfterSaveStateAction);
|
||||
UI::EventParams e2{};
|
||||
e2.v = this;
|
||||
OnStateLoaded.Trigger(e2);
|
||||
@@ -313,7 +313,7 @@ void SaveSlotView::OnLoadState(UI::EventParams &e) {
|
||||
void SaveSlotView::OnSaveState(UI::EventParams &e) {
|
||||
if (!NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
g_Config.iCurrentStateSlot = slot_;
|
||||
SaveState::SaveSlot(saveStatePrefix_, slot_, &AfterSaveStateAction);
|
||||
SaveState::SaveSlot(saveStatePrefix_, slot_, &ShowMessageAfterSaveStateAction);
|
||||
UI::EventParams e2{};
|
||||
e2.v = this;
|
||||
OnStateSaved.Trigger(e2);
|
||||
@@ -426,7 +426,7 @@ void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems,
|
||||
UI::Choice *loadUndoButton = buttonRow->Add(new Choice(pa->T("Undo last load"), ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)));
|
||||
loadUndoButton->SetEnabled(SaveState::HasUndoLoad(saveStatePrefix_));
|
||||
loadUndoButton->OnClick.Add([this](UI::EventParams &e) {
|
||||
SaveState::UndoLoad(saveStatePrefix_, &AfterSaveStateAction);
|
||||
SaveState::UndoLoad(saveStatePrefix_, &ShowMessageAfterSaveStateAction);
|
||||
TriggerFinish(DR_CANCEL);
|
||||
});
|
||||
}
|
||||
@@ -435,7 +435,7 @@ void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems,
|
||||
UI::Choice *rewindButton = buttonRow->Add(new Choice(pa->T("Rewind"), ImageID("I_REWIND"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)));
|
||||
rewindButton->SetEnabled(SaveState::CanRewind());
|
||||
rewindButton->OnClick.Add([this](UI::EventParams &e) {
|
||||
SaveState::Rewind(&AfterSaveStateAction);
|
||||
SaveState::Rewind(&ShowMessageAfterSaveStateAction);
|
||||
TriggerFinish(DR_CANCEL);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "Common/File/Path.h"
|
||||
#include "Common/UI/UIScreen.h"
|
||||
#include "Common/UI/ViewGroup.h"
|
||||
#include "Core/SaveState.h"
|
||||
#include "Core/ControlMapper.h"
|
||||
#include "UI/BaseScreens.h"
|
||||
#include "UI/Screen.h"
|
||||
@@ -85,3 +86,4 @@ private:
|
||||
};
|
||||
|
||||
std::string GetConfirmExitMessage();
|
||||
void ShowMessageAfterSaveStateAction(SaveState::Status status, std::string_view message, std::string_view metadata);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "Core/SaveState.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/RetroAchievements.h"
|
||||
#include "UI/PauseScreen.h"
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION
|
||||
#include "ext/rcheevos/include/rc_client_raintegration.h"
|
||||
@@ -394,10 +395,9 @@ namespace MainWindow {
|
||||
});
|
||||
}
|
||||
|
||||
static void SaveStateActionFinished(SaveState::Status status, std::string_view message) {
|
||||
if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) {
|
||||
g_OSD.Show(status == SaveState::Status::SUCCESS ? OSDType::MESSAGE_SUCCESS : OSDType::MESSAGE_ERROR, message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0);
|
||||
}
|
||||
static void SaveStateActionFinished(SaveState::Status status, std::string_view message, std::string_view metadata) {
|
||||
// Reuse the message from the pause screen.
|
||||
ShowMessageAfterSaveStateAction(status, message, metadata);
|
||||
PostMessage(MainWindow::GetHWND(), WM_USER_SAVESTATE_FINISH, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user