mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Fix the internal savestate API to better reflect how it actually works
This commit is contained in:
1 parent
e6e82c9ad3
commit
2959ad214c
7 files changed
+140
-102
No files matched your search
+69
-48
@@ -315,9 +315,13 @@ enum class OperationType {
|
||||
return filename.GetFilename() + " " + std::string(sy->T("(broken)"));
|
||||
}
|
||||
|
||||
std::string GenerateFullDiscId(const Path &gameFilename) {
|
||||
std::string discId = g_paramSFO.GetValueString("DISC_ID");
|
||||
std::string discVer = g_paramSFO.GetValueString("DISC_VERSION");
|
||||
// TODO: gameFilename is ignored!
|
||||
// This means that this must always be called in-game, otherwise it will not work!
|
||||
//
|
||||
// This particular ID string generation is specific for save states.
|
||||
static std::string GenerateFullDiscId(const ParamSFOData ¶mSFO) {
|
||||
std::string discId = paramSFO.GetValueString("DISC_ID");
|
||||
std::string discVer = paramSFO.GetValueString("DISC_VERSION");
|
||||
if (discId.empty()) {
|
||||
// Should never happen.
|
||||
discId = g_paramSFO.GenerateFakeID(Path());
|
||||
@@ -326,9 +330,13 @@ enum class OperationType {
|
||||
return StringFromFormat("%s_%s", discId.c_str(), discVer.c_str());
|
||||
}
|
||||
|
||||
Path GenerateSaveSlotFilename(const Path &gameFilename, int slot, const char *extension)
|
||||
{
|
||||
std::string filename = StringFromFormat("%s_%d.%s", GenerateFullDiscId(gameFilename).c_str(), slot, extension);
|
||||
std::string GetGamePrefix(const ParamSFOData ¶mSFO) {
|
||||
return GenerateFullDiscId(paramSFO);
|
||||
}
|
||||
|
||||
// The prefix is always based on GenerateFullDiscId. So we can find these by scanning, too.
|
||||
Path GenerateSaveSlotFilename(std::string_view gamePrefix, int slot, const char *extension) {
|
||||
std::string filename = StringFromFormat("%.*s_%d.%s", STR_VIEW(gamePrefix), slot, extension);
|
||||
return GetSysDirectory(DIRECTORY_SAVESTATE) / filename;
|
||||
}
|
||||
|
||||
@@ -364,13 +372,12 @@ enum class OperationType {
|
||||
}
|
||||
}
|
||||
|
||||
void LoadSlot(const Path &gameFilename, int slot, Callback callback)
|
||||
{
|
||||
void LoadSlot(std::string_view gamePrefix, int slot, Callback callback) {
|
||||
if (!NetworkAllowSaveState()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, slot, STATE_EXTENSION);
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, slot, STATE_EXTENSION);
|
||||
if (!fn.empty()) {
|
||||
// This add only 1 extra state, should we just always enable it?
|
||||
if (g_Config.bEnableStateUndo) {
|
||||
@@ -380,7 +387,7 @@ enum class OperationType {
|
||||
if (status != Status::FAILURE) {
|
||||
DeleteIfExists(backup);
|
||||
File::Rename(backup.WithExtraExtension(".tmp"), backup);
|
||||
g_Config.sStateLoadUndoGame = GenerateFullDiscId(gameFilename);
|
||||
g_Config.sStateLoadUndoGame = gamePrefix;
|
||||
g_Config.Save("Saving config for savestate last load undo");
|
||||
} else {
|
||||
ERROR_LOG(Log::SaveState, "Saving load undo state failed: %.*s", (int)message.size(), message.data());
|
||||
@@ -405,12 +412,12 @@ enum class OperationType {
|
||||
}
|
||||
}
|
||||
|
||||
bool UndoLoad(const Path &gameFilename, Callback callback) {
|
||||
bool UndoLoad(std::string_view gamePrefix, Callback callback) {
|
||||
if (!NetworkAllowSaveState()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_Config.sStateLoadUndoGame != GenerateFullDiscId(gameFilename)) {
|
||||
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"));
|
||||
@@ -431,21 +438,21 @@ enum class OperationType {
|
||||
}
|
||||
}
|
||||
|
||||
void SaveSlot(const Path &gameFilename, int slot, Callback callback) {
|
||||
void SaveSlot(std::string_view gamePrefix, int slot, Callback callback) {
|
||||
if (!NetworkAllowSaveState()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, slot, STATE_EXTENSION);
|
||||
Path fnUndo = GenerateSaveSlotFilename(gameFilename, slot, UNDO_STATE_EXTENSION);
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, slot, STATE_EXTENSION);
|
||||
Path fnUndo = GenerateSaveSlotFilename(gamePrefix, slot, UNDO_STATE_EXTENSION);
|
||||
if (!fn.empty()) {
|
||||
Path shot = GenerateSaveSlotFilename(gameFilename, slot, SCREENSHOT_EXTENSION);
|
||||
Path shot = GenerateSaveSlotFilename(gamePrefix, slot, SCREENSHOT_EXTENSION);
|
||||
auto renameCallback = [=](Status status, std::string_view message) {
|
||||
if (status != Status::FAILURE) {
|
||||
if (g_Config.bEnableStateUndo) {
|
||||
DeleteIfExists(fnUndo);
|
||||
RenameIfExists(fn, fnUndo);
|
||||
g_Config.sStateUndoLastSaveGame = GenerateFullDiscId(gameFilename);
|
||||
g_Config.sStateUndoLastSaveGame = gamePrefix;
|
||||
g_Config.iStateUndoLastSaveSlot = slot;
|
||||
g_Config.Save("Saving config for savestate last save undo");
|
||||
} else {
|
||||
@@ -459,7 +466,7 @@ enum class OperationType {
|
||||
};
|
||||
// Let's also create a screenshot.
|
||||
if (g_Config.bEnableStateUndo) {
|
||||
Path shotUndo = GenerateSaveSlotFilename(gameFilename, slot, UNDO_SCREENSHOT_EXTENSION);
|
||||
Path shotUndo = GenerateSaveSlotFilename(gamePrefix, slot, UNDO_SCREENSHOT_EXTENSION);
|
||||
DeleteIfExists(shotUndo);
|
||||
RenameIfExists(shot, shotUndo);
|
||||
}
|
||||
@@ -473,18 +480,18 @@ enum class OperationType {
|
||||
}
|
||||
}
|
||||
|
||||
bool UndoSaveSlot(const Path &gameFilename, int slot) {
|
||||
bool UndoSaveSlot(std::string_view gamePrefix, int slot) {
|
||||
if (!NetworkAllowSaveState()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Path fnUndo = GenerateSaveSlotFilename(gameFilename, slot, UNDO_STATE_EXTENSION);
|
||||
Path fnUndo = GenerateSaveSlotFilename(gamePrefix, slot, UNDO_STATE_EXTENSION);
|
||||
|
||||
// Do nothing if there's no undo.
|
||||
if (File::Exists(fnUndo)) {
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, slot, STATE_EXTENSION);
|
||||
Path shot = GenerateSaveSlotFilename(gameFilename, slot, SCREENSHOT_EXTENSION);
|
||||
Path shotUndo = GenerateSaveSlotFilename(gameFilename, slot, UNDO_SCREENSHOT_EXTENSION);
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, slot, STATE_EXTENSION);
|
||||
Path shot = GenerateSaveSlotFilename(gamePrefix, slot, SCREENSHOT_EXTENSION);
|
||||
Path shotUndo = GenerateSaveSlotFilename(gamePrefix, slot, UNDO_SCREENSHOT_EXTENSION);
|
||||
// Swap them so they can undo again to redo. Mistakes happen.
|
||||
SwapIfExists(shotUndo, shot);
|
||||
SwapIfExists(fnUndo, fn);
|
||||
@@ -494,9 +501,9 @@ enum class OperationType {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeleteSlot(const Path &gameFilename, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, slot, STATE_EXTENSION);
|
||||
Path shot = GenerateSaveSlotFilename(gameFilename, slot, SCREENSHOT_EXTENSION);
|
||||
void DeleteSlot(std::string_view gamePrefix, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, slot, STATE_EXTENSION);
|
||||
Path shot = GenerateSaveSlotFilename(gamePrefix, slot, SCREENSHOT_EXTENSION);
|
||||
|
||||
if (File::Exists(fn)) {
|
||||
DeleteIfExists(fn);
|
||||
@@ -504,42 +511,57 @@ enum class OperationType {
|
||||
}
|
||||
}
|
||||
|
||||
bool UndoLastSave(const Path &gameFilename) {
|
||||
bool UndoLastSave(std::string_view gamePrefix) {
|
||||
if (!NetworkAllowSaveState()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_Config.sStateUndoLastSaveGame != GenerateFullDiscId(gameFilename))
|
||||
if (g_Config.sStateUndoLastSaveGame != gamePrefix)
|
||||
return false;
|
||||
|
||||
return UndoSaveSlot(gameFilename, g_Config.iStateUndoLastSaveSlot);
|
||||
return UndoSaveSlot(gamePrefix, g_Config.iStateUndoLastSaveSlot);
|
||||
}
|
||||
|
||||
bool HasSaveInSlot(const Path &gameFilename, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, slot, STATE_EXTENSION);
|
||||
void Rescan(std::string_view gamePrefix) {
|
||||
// Currently nothing to do here.
|
||||
// On Android this would be important to rescan the save state directory.
|
||||
std::vector<File::FileInfo> file;
|
||||
|
||||
std::string prefix(gamePrefix);
|
||||
prefix += "_";
|
||||
|
||||
File::GetFilesInDir(GetSysDirectory(DIRECTORY_SAVESTATE), &file, nullptr, 0, prefix);
|
||||
|
||||
for (const auto &f : file) {
|
||||
INFO_LOG(Log::System, "%s", f.name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool HasSaveInSlot(std::string_view gamePrefix, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, slot, STATE_EXTENSION);
|
||||
return File::Exists(fn);
|
||||
}
|
||||
|
||||
bool HasUndoSaveInSlot(const Path &gameFilename, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, slot, UNDO_STATE_EXTENSION);
|
||||
bool HasUndoSaveInSlot(std::string_view gamePrefix, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, slot, UNDO_STATE_EXTENSION);
|
||||
return File::Exists(fn);
|
||||
}
|
||||
|
||||
bool HasUndoLastSave(const Path &gameFilename) {
|
||||
if (g_Config.sStateUndoLastSaveGame != GenerateFullDiscId(gameFilename))
|
||||
bool HasUndoLastSave(std::string_view gamePrefix) {
|
||||
if (g_Config.sStateUndoLastSaveGame != gamePrefix)
|
||||
return false;
|
||||
|
||||
return HasUndoSaveInSlot(gameFilename, g_Config.iStateUndoLastSaveSlot);
|
||||
return HasUndoSaveInSlot(gamePrefix, g_Config.iStateUndoLastSaveSlot);
|
||||
}
|
||||
|
||||
bool HasScreenshotInSlot(const Path &gameFilename, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, slot, SCREENSHOT_EXTENSION);
|
||||
bool HasScreenshotInSlot(std::string_view gamePrefix, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, slot, SCREENSHOT_EXTENSION);
|
||||
return File::Exists(fn);
|
||||
}
|
||||
|
||||
bool HasUndoLoad(const Path &gameFilename) {
|
||||
bool HasUndoLoad(std::string_view gamePrefix) {
|
||||
Path fn = GetSysDirectory(DIRECTORY_SAVESTATE) / LOAD_UNDO_NAME;
|
||||
return File::Exists(fn) && g_Config.sStateLoadUndoGame == GenerateFullDiscId(gameFilename);
|
||||
return File::Exists(fn) && g_Config.sStateLoadUndoGame == gamePrefix;
|
||||
}
|
||||
|
||||
bool operator < (const tm &t1, const tm &t2) {
|
||||
@@ -579,11 +601,11 @@ enum class OperationType {
|
||||
return true;
|
||||
}
|
||||
|
||||
int GetNewestSlot(const Path &gameFilename) {
|
||||
int GetNewestSlot(std::string_view gamePrefix) {
|
||||
int newestSlot = -1;
|
||||
tm newestDate = {0};
|
||||
for (int i = 0; i < Config::iSaveStateSlotCount; i++) {
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, i, STATE_EXTENSION);
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, i, STATE_EXTENSION);
|
||||
if (File::Exists(fn)) {
|
||||
tm time;
|
||||
bool success = File::GetModifTime(fn, time);
|
||||
@@ -596,11 +618,11 @@ enum class OperationType {
|
||||
return newestSlot;
|
||||
}
|
||||
|
||||
int GetOldestSlot(const Path &gameFilename) {
|
||||
int GetOldestSlot(std::string_view gamePrefix) {
|
||||
int oldestSlot = -1;
|
||||
tm oldestDate = {0};
|
||||
for (int i = 0; i < Config::iSaveStateSlotCount; i++) {
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, i, STATE_EXTENSION);
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, i, STATE_EXTENSION);
|
||||
if (File::Exists(fn)) {
|
||||
tm time;
|
||||
bool success = File::GetModifTime(fn, time);
|
||||
@@ -613,8 +635,8 @@ enum class OperationType {
|
||||
return oldestSlot;
|
||||
}
|
||||
|
||||
std::string GetSlotDateAsString(const Path &gameFilename, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gameFilename, slot, STATE_EXTENSION);
|
||||
std::string GetSlotDateAsString(std::string_view gamePrefix, int slot) {
|
||||
Path fn = GenerateSaveSlotFilename(gamePrefix, slot, STATE_EXTENSION);
|
||||
tm time;
|
||||
if (File::GetModifTime(fn, time)) {
|
||||
char buf[256];
|
||||
@@ -637,8 +659,7 @@ enum class OperationType {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<Operation> Flush()
|
||||
{
|
||||
std::vector<Operation> Flush() {
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
std::vector<Operation> copy = pending;
|
||||
pending.clear();
|
||||
|
||||
+24
-15
@@ -25,6 +25,9 @@
|
||||
#include "Common/File/Path.h"
|
||||
#include "Common/Serialize/Serializer.h"
|
||||
|
||||
class ParamSFOData;
|
||||
#undef Process
|
||||
|
||||
namespace SaveState {
|
||||
enum class Status {
|
||||
FAILURE,
|
||||
@@ -42,30 +45,36 @@ namespace SaveState {
|
||||
void PrevSlot();
|
||||
void NextSlot();
|
||||
|
||||
std::string GetGamePrefix(const ParamSFOData ¶mSFO);
|
||||
|
||||
// Run the various actions directly.
|
||||
void SaveSlot(const Path &gameFilename, int slot, Callback callback);
|
||||
void LoadSlot(const Path &gameFilename, int slot, Callback callback);
|
||||
bool UndoSaveSlot(const Path &gameFilename, int slot);
|
||||
bool UndoLastSave(const Path &gameFilename);
|
||||
bool UndoLoad(const Path &gameFilename, Callback callback);
|
||||
void DeleteSlot(const Path &gameFilename, int slot);
|
||||
void SaveSlot(std::string_view gamePrefix, int slot, Callback callback);
|
||||
void LoadSlot(std::string_view gamePrefix, int slot, Callback callback);
|
||||
bool UndoSaveSlot(std::string_view gamePrefix, int slot);
|
||||
bool UndoLastSave(std::string_view gamePrefix);
|
||||
bool UndoLoad(std::string_view gamePrefix, Callback callback);
|
||||
void DeleteSlot(std::string_view gamePrefix, int slot);
|
||||
|
||||
// This will rescan the save state directory for files associated with the specified game.
|
||||
// Note that when we have many save states, this is really important on Android.
|
||||
void Rescan(std::string_view gamePrefix);
|
||||
|
||||
// Checks whether there's an existing save in the specified slot.
|
||||
bool HasSaveInSlot(const Path &gameFilename, int slot);
|
||||
bool HasUndoSaveInSlot(const Path &gameFilename, int slot);
|
||||
bool HasUndoLastSave(const Path &gameFilename);
|
||||
bool HasUndoLoad(const Path &gameFilename);
|
||||
bool HasScreenshotInSlot(const Path &gameFilename, int slot);
|
||||
bool HasSaveInSlot(std::string_view gamePrefix, int slot);
|
||||
bool HasUndoSaveInSlot(std::string_view gamePrefix, int slot);
|
||||
bool HasUndoLastSave(std::string_view gamePrefix);
|
||||
bool HasUndoLoad(std::string_view gamePrefix);
|
||||
bool HasScreenshotInSlot(std::string_view gamePrefix, int slot);
|
||||
|
||||
// Just returns the current slot from config.
|
||||
int GetCurrentSlot();
|
||||
|
||||
// Returns -1 if there's no oldest/newest slot.
|
||||
int GetNewestSlot(const Path &gameFilename);
|
||||
int GetOldestSlot(const Path &gameFilename);
|
||||
int GetNewestSlot(std::string_view gamePrefix);
|
||||
int GetOldestSlot(std::string_view gamePrefix);
|
||||
|
||||
std::string GetSlotDateAsString(const Path &gameFilename, int slot);
|
||||
Path GenerateSaveSlotFilename(const Path &gameFilename, int slot, const char *extension);
|
||||
std::string GetSlotDateAsString(std::string_view gamePrefix, int slot);
|
||||
Path GenerateSaveSlotFilename(std::string_view gamePrefix, int slot, const char *extension);
|
||||
|
||||
std::string GetTitle(const Path &filename);
|
||||
|
||||
|
||||
+2
-2
@@ -168,13 +168,13 @@ static void SaveStateActionFinished(SaveState::Status status, std::string_view m
|
||||
void MainWindow::qlstateAct()
|
||||
{
|
||||
Path gamePath = PSP_CoreParameter().fileToStart;
|
||||
SaveState::LoadSlot(gamePath, 0, SaveStateActionFinished);
|
||||
SaveState::LoadSlot(SaveState::GetGamePrefix(g_paramSFO), 0, SaveStateActionFinished);
|
||||
}
|
||||
|
||||
void MainWindow::qsstateAct()
|
||||
{
|
||||
Path gamePath = PSP_CoreParameter().fileToStart;
|
||||
SaveState::SaveSlot(gamePath, 0, SaveStateActionFinished);
|
||||
SaveState::SaveSlot(SaveState::GetGamePrefix(g_paramSFO), 0, SaveStateActionFinished);
|
||||
}
|
||||
|
||||
void MainWindow::lstateAct()
|
||||
|
||||
+12
-8
@@ -821,12 +821,12 @@ void EmuScreen::onVKey(VirtKey virtualKeyCode, bool down) {
|
||||
|
||||
case VIRTKEY_SAVE_STATE:
|
||||
if (down && !Achievements::WarnUserIfHardcoreModeActive(true) && !NetworkWarnUserIfOnlineAndCantSavestate() && !bootPending_) {
|
||||
SaveState::SaveSlot(gamePath_, g_Config.iCurrentStateSlot, &AfterSaveStateAction);
|
||||
SaveState::SaveSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, &AfterSaveStateAction);
|
||||
}
|
||||
break;
|
||||
case VIRTKEY_LOAD_STATE:
|
||||
if (down && !Achievements::WarnUserIfHardcoreModeActive(false) && !NetworkWarnUserIfOnlineAndCantSavestate() && !bootPending_) {
|
||||
SaveState::LoadSlot(gamePath_, g_Config.iCurrentStateSlot, &AfterSaveStateAction);
|
||||
SaveState::LoadSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, &AfterSaveStateAction);
|
||||
}
|
||||
break;
|
||||
case VIRTKEY_PREVIOUS_SLOT:
|
||||
@@ -1481,9 +1481,11 @@ void EmuScreen::update() {
|
||||
if (saveStateSlot_ != currentSlot) {
|
||||
saveStateSlot_ = currentSlot;
|
||||
|
||||
const std::string gamePrefix = SaveState::GetGamePrefix(g_paramSFO);
|
||||
|
||||
Path fn;
|
||||
if (SaveState::HasSaveInSlot(gamePath_, currentSlot)) {
|
||||
fn = SaveState::GenerateSaveSlotFilename(gamePath_, currentSlot, SaveState::SCREENSHOT_EXTENSION);
|
||||
if (SaveState::HasSaveInSlot(gamePrefix, currentSlot)) {
|
||||
fn = SaveState::GenerateSaveSlotFilename(gamePrefix, currentSlot, SaveState::SCREENSHOT_EXTENSION);
|
||||
}
|
||||
|
||||
saveStatePreview_->SetFilename(fn);
|
||||
@@ -2035,23 +2037,25 @@ void EmuScreen::AutoLoadSaveState() {
|
||||
|
||||
int autoSlot = -1;
|
||||
|
||||
std::string gamePrefix = SaveState::GetGamePrefix(g_paramSFO);
|
||||
|
||||
//check if save state has save, if so, load
|
||||
switch (g_Config.iAutoLoadSaveState) {
|
||||
case (int)AutoLoadSaveState::OFF: // "AutoLoad Off"
|
||||
return;
|
||||
case (int)AutoLoadSaveState::OLDEST: // "Oldest Save"
|
||||
autoSlot = SaveState::GetOldestSlot(gamePath_);
|
||||
autoSlot = SaveState::GetOldestSlot(gamePrefix);
|
||||
break;
|
||||
case (int)AutoLoadSaveState::NEWEST: // "Newest Save"
|
||||
autoSlot = SaveState::GetNewestSlot(gamePath_);
|
||||
autoSlot = SaveState::GetNewestSlot(gamePrefix);
|
||||
break;
|
||||
default: // try the specific save state slot specified
|
||||
autoSlot = (SaveState::HasSaveInSlot(gamePath_, g_Config.iAutoLoadSaveState - 3)) ? (g_Config.iAutoLoadSaveState - 3) : -1;
|
||||
autoSlot = (SaveState::HasSaveInSlot(gamePrefix, g_Config.iAutoLoadSaveState - 3)) ? (g_Config.iAutoLoadSaveState - 3) : -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_Config.iAutoLoadSaveState && autoSlot != -1) {
|
||||
SaveState::LoadSlot(gamePath_, autoSlot, [this, autoSlot](SaveState::Status status, std::string_view message) {
|
||||
SaveState::LoadSlot(gamePrefix, autoSlot, [this, autoSlot](SaveState::Status status, std::string_view message) {
|
||||
AfterSaveStateAction(status, message);
|
||||
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
||||
std::string msg = std::string(sy->T("Auto Load Savestate")) + ": " + StringFromFormat("%d", autoSlot);
|
||||
|
||||
+27
-25
@@ -78,8 +78,8 @@ static void AfterSaveStateAction(SaveState::Status status, std::string_view mess
|
||||
|
||||
class ScreenshotViewScreen : public UI::PopupScreen {
|
||||
public:
|
||||
ScreenshotViewScreen(const Path &filename, std::string title, int slot, Path gamePath)
|
||||
: PopupScreen(title), filename_(filename), slot_(slot), gamePath_(gamePath), title_(title) {} // PopupScreen will translate Back on its own
|
||||
ScreenshotViewScreen(const Path &screenshotFilename, std::string_view saveStatePrefix, std::string_view title, int slot, Path gamePath)
|
||||
: PopupScreen(title), screenshotFilename_(screenshotFilename), saveStatePrefix_(saveStatePrefix), slot_(slot), gamePath_(gamePath), title_(title) {} // PopupScreen will translate Back on its own
|
||||
|
||||
int GetSlot() const {
|
||||
return slot_;
|
||||
@@ -100,7 +100,7 @@ protected:
|
||||
ScrollView *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
|
||||
LinearLayout *content = new LinearLayout(ORIENT_VERTICAL);
|
||||
Margins contentMargins(10, 0);
|
||||
content->Add(new AsyncImageFileView(filename_, IS_KEEP_ASPECT, new LinearLayoutParams(480, 272, contentMargins)))->SetCanBeFocused(false);
|
||||
content->Add(new AsyncImageFileView(screenshotFilename_, IS_KEEP_ASPECT, new LinearLayoutParams(480, 272, contentMargins)))->SetCanBeFocused(false);
|
||||
|
||||
GridLayoutSettings gridsettings(240, 64, 5);
|
||||
gridsettings.fillCells = true;
|
||||
@@ -108,7 +108,7 @@ protected:
|
||||
|
||||
Choice *back = new Choice(di->T("Back"));
|
||||
|
||||
const bool hasUndo = SaveState::HasUndoSaveInSlot(gamePath_, slot_);
|
||||
const bool hasUndo = SaveState::HasUndoSaveInSlot(saveStatePrefix_, slot_);
|
||||
const bool undoEnabled = g_Config.bEnableStateUndo;
|
||||
|
||||
Choice *undoButton = nullptr;
|
||||
@@ -138,8 +138,9 @@ private:
|
||||
void OnUndoState(UI::EventParams &e);
|
||||
void OnDeleteState(UI::EventParams &e);
|
||||
|
||||
Path filename_;
|
||||
Path screenshotFilename_;
|
||||
Path gamePath_;
|
||||
std::string saveStatePrefix_;
|
||||
std::string title_;
|
||||
int slot_;
|
||||
};
|
||||
@@ -147,7 +148,7 @@ private:
|
||||
void ScreenshotViewScreen::OnSaveState(UI::EventParams &e) {
|
||||
if (!NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
g_Config.iCurrentStateSlot = slot_;
|
||||
SaveState::SaveSlot(gamePath_, slot_, &AfterSaveStateAction);
|
||||
SaveState::SaveSlot(saveStatePrefix_, slot_, &AfterSaveStateAction);
|
||||
TriggerFinish(DR_OK); //OK will close the pause screen as well
|
||||
}
|
||||
}
|
||||
@@ -155,14 +156,14 @@ void ScreenshotViewScreen::OnSaveState(UI::EventParams &e) {
|
||||
void ScreenshotViewScreen::OnLoadState(UI::EventParams &e) {
|
||||
if (!NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
g_Config.iCurrentStateSlot = slot_;
|
||||
SaveState::LoadSlot(gamePath_, slot_, &AfterSaveStateAction);
|
||||
SaveState::LoadSlot(saveStatePrefix_, slot_, &AfterSaveStateAction);
|
||||
TriggerFinish(DR_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenshotViewScreen::OnUndoState(UI::EventParams &e) {
|
||||
if (!NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
SaveState::UndoSaveSlot(gamePath_, slot_);
|
||||
SaveState::UndoSaveSlot(saveStatePrefix_, slot_);
|
||||
TriggerFinish(DR_CANCEL);
|
||||
}
|
||||
}
|
||||
@@ -180,7 +181,7 @@ void ScreenshotViewScreen::OnDeleteState(UI::EventParams &e) {
|
||||
|
||||
screenManager()->push(new UI::MessagePopupScreen(title, message, di->T("Delete"), di->T("Cancel"), [=](bool result) {
|
||||
if (result) {
|
||||
SaveState::DeleteSlot(gamePath_, slot_);
|
||||
SaveState::DeleteSlot(saveStatePrefix_, slot_);
|
||||
TriggerFinish(DR_CANCEL);
|
||||
}
|
||||
}));
|
||||
@@ -188,7 +189,7 @@ void ScreenshotViewScreen::OnDeleteState(UI::EventParams &e) {
|
||||
|
||||
class SaveSlotView : public UI::LinearLayout {
|
||||
public:
|
||||
SaveSlotView(const Path &gamePath, int slot, UI::LayoutParams *layoutParams = nullptr);
|
||||
SaveSlotView(std::string_view saveStatePrefix, int slot, UI::LayoutParams *layoutParams = nullptr);
|
||||
|
||||
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override {
|
||||
w = 500; h = 90;
|
||||
@@ -205,7 +206,7 @@ public:
|
||||
}
|
||||
|
||||
std::string GetScreenshotTitle() const {
|
||||
return SaveState::GetSlotDateAsString(gamePath_, slot_);
|
||||
return SaveState::GetSlotDateAsString(saveStatePrefix_, slot_);
|
||||
}
|
||||
|
||||
UI::Event OnStateLoaded;
|
||||
@@ -221,14 +222,14 @@ private:
|
||||
UI::Button *loadStateButton_ = nullptr;
|
||||
|
||||
int slot_;
|
||||
Path gamePath_;
|
||||
std::string saveStatePrefix_;
|
||||
Path screenshotFilename_;
|
||||
};
|
||||
|
||||
SaveSlotView::SaveSlotView(const Path &gameFilename, int slot, UI::LayoutParams *layoutParams) : UI::LinearLayout(ORIENT_HORIZONTAL, layoutParams), slot_(slot), gamePath_(gameFilename) {
|
||||
SaveSlotView::SaveSlotView(std::string_view saveStatePrefix, int slot, UI::LayoutParams *layoutParams) : UI::LinearLayout(ORIENT_HORIZONTAL, layoutParams), slot_(slot), saveStatePrefix_(saveStatePrefix) {
|
||||
using namespace UI;
|
||||
|
||||
screenshotFilename_ = SaveState::GenerateSaveSlotFilename(gamePath_, slot, SaveState::SCREENSHOT_EXTENSION);
|
||||
screenshotFilename_ = SaveState::GenerateSaveSlotFilename(saveStatePrefix_, slot, SaveState::SCREENSHOT_EXTENSION);
|
||||
|
||||
std::string number = StringFromFormat("%d", slot + 1);
|
||||
Add(new Spacer(5));
|
||||
@@ -263,13 +264,13 @@ SaveSlotView::SaveSlotView(const Path &gameFilename, int slot, UI::LayoutParams
|
||||
OnScreenshotClicked.Trigger(e);
|
||||
});
|
||||
|
||||
if (SaveState::HasSaveInSlot(gamePath_, slot)) {
|
||||
if (SaveState::HasSaveInSlot(saveStatePrefix_, slot)) {
|
||||
if (!Achievements::HardcoreModeActive()) {
|
||||
loadStateButton_ = buttons->Add(new Button(pa->T("Load State"), new LinearLayoutParams(0.0, Gravity::G_VCENTER)));
|
||||
loadStateButton_->OnClick.Handle(this, &SaveSlotView::OnLoadState);
|
||||
}
|
||||
|
||||
std::string dateStr = SaveState::GetSlotDateAsString(gamePath_, slot_);
|
||||
std::string dateStr = SaveState::GetSlotDateAsString(saveStatePrefix_, slot_);
|
||||
if (!dateStr.empty()) {
|
||||
TextView *dateView = new TextView(dateStr, new LinearLayoutParams(0.0, Gravity::G_VCENTER));
|
||||
dateView->SetSmall(true);
|
||||
@@ -291,7 +292,7 @@ void SaveSlotView::Draw(UIContext &dc) {
|
||||
void SaveSlotView::OnLoadState(UI::EventParams &e) {
|
||||
if (!NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
g_Config.iCurrentStateSlot = slot_;
|
||||
SaveState::LoadSlot(gamePath_, slot_, &AfterSaveStateAction);
|
||||
SaveState::LoadSlot(saveStatePrefix_, slot_, &AfterSaveStateAction);
|
||||
UI::EventParams e2{};
|
||||
e2.v = this;
|
||||
OnStateLoaded.Trigger(e2);
|
||||
@@ -301,7 +302,7 @@ void SaveSlotView::OnLoadState(UI::EventParams &e) {
|
||||
void SaveSlotView::OnSaveState(UI::EventParams &e) {
|
||||
if (!NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
g_Config.iCurrentStateSlot = slot_;
|
||||
SaveState::SaveSlot(gamePath_, slot_, &AfterSaveStateAction);
|
||||
SaveState::SaveSlot(saveStatePrefix_, slot_, &AfterSaveStateAction);
|
||||
UI::EventParams e2{};
|
||||
e2.v = this;
|
||||
OnStateSaved.Trigger(e2);
|
||||
@@ -342,6 +343,7 @@ GamePauseScreen::GamePauseScreen(const Path &filename, bool bootPending)
|
||||
// So we can tell if something blew up while on the pause screen.
|
||||
std::string assertStr = "PauseScreen: " + filename.GetFilename();
|
||||
SetExtraAssertInfo(assertStr.c_str());
|
||||
saveStatePrefix_ = SaveState::GetGamePrefix(g_paramSFO);
|
||||
}
|
||||
|
||||
GamePauseScreen::~GamePauseScreen() {
|
||||
@@ -373,17 +375,17 @@ void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems)
|
||||
|
||||
leftColumnItems->SetSpacing(10.0);
|
||||
for (int i = 0; i < Config::iSaveStateSlotCount; i++) {
|
||||
SaveSlotView *slot = leftColumnItems->Add(new SaveSlotView(gamePath_, i, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, Gravity::G_HCENTER, Margins(0,0,0,0))));
|
||||
SaveSlotView *slot = leftColumnItems->Add(new SaveSlotView(saveStatePrefix_, i, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, Gravity::G_HCENTER, Margins(0,0,0,0))));
|
||||
slot->OnStateLoaded.Handle(this, &GamePauseScreen::OnState);
|
||||
slot->OnStateSaved.Handle(this, &GamePauseScreen::OnState);
|
||||
slot->OnScreenshotClicked.Add([this](UI::EventParams &e) {
|
||||
SaveSlotView *v = static_cast<SaveSlotView *>(e.v);
|
||||
int slot = v->GetSlot();
|
||||
g_Config.iCurrentStateSlot = v->GetSlot();
|
||||
if (SaveState::HasSaveInSlot(gamePath_, slot)) {
|
||||
if (SaveState::HasSaveInSlot(saveStatePrefix_, slot)) {
|
||||
Path fn = v->GetScreenshotFilename();
|
||||
std::string title = v->GetScreenshotTitle();
|
||||
Screen *screen = new ScreenshotViewScreen(fn, title, v->GetSlot(), gamePath_);
|
||||
Screen *screen = new ScreenshotViewScreen(fn, saveStatePrefix_, title, v->GetSlot(), gamePath_);
|
||||
screenManager()->push(screen);
|
||||
}
|
||||
});
|
||||
@@ -398,11 +400,11 @@ void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems)
|
||||
LinearLayout *buttonRow = leftColumnItems->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(Margins(10, 0, 0, 0))));
|
||||
if (g_Config.bEnableStateUndo && !Achievements::HardcoreModeActive() && NetworkAllowSaveState()) {
|
||||
UI::Choice *loadUndoButton = buttonRow->Add(new Choice(pa->T("Undo last load"), ImageID("I_NAVIGATE_BACK")));
|
||||
loadUndoButton->SetEnabled(SaveState::HasUndoLoad(gamePath_));
|
||||
loadUndoButton->SetEnabled(SaveState::HasUndoLoad(saveStatePrefix_));
|
||||
loadUndoButton->OnClick.Handle(this, &GamePauseScreen::OnLoadUndo);
|
||||
|
||||
UI::Choice *saveUndoButton = buttonRow->Add(new Choice(pa->T("Undo last save"), ImageID("I_NAVIGATE_BACK")));
|
||||
saveUndoButton->SetEnabled(SaveState::HasUndoLastSave(gamePath_));
|
||||
saveUndoButton->SetEnabled(SaveState::HasUndoLastSave(saveStatePrefix_));
|
||||
saveUndoButton->OnClick.Handle(this, &GamePauseScreen::OnLastSaveUndo);
|
||||
}
|
||||
|
||||
@@ -821,13 +823,13 @@ void GamePauseScreen::OnRewind(UI::EventParams &e) {
|
||||
}
|
||||
|
||||
void GamePauseScreen::OnLoadUndo(UI::EventParams &e) {
|
||||
SaveState::UndoLoad(gamePath_, &AfterSaveStateAction);
|
||||
SaveState::UndoLoad(saveStatePrefix_, &AfterSaveStateAction);
|
||||
|
||||
TriggerFinish(DR_CANCEL);
|
||||
}
|
||||
|
||||
void GamePauseScreen::OnLastSaveUndo(UI::EventParams &e) {
|
||||
SaveState::UndoLastSave(gamePath_);
|
||||
SaveState::UndoLastSave(saveStatePrefix_);
|
||||
|
||||
RecreateViews();
|
||||
}
|
||||
|
||||
@@ -75,6 +75,8 @@ private:
|
||||
bool lastDNSConfigLoaded_ = false;
|
||||
|
||||
bool bootPending_ = false;
|
||||
|
||||
std::string saveStatePrefix_;
|
||||
};
|
||||
|
||||
std::string GetConfirmExitMessage();
|
||||
@@ -613,7 +613,7 @@ namespace MainWindow {
|
||||
case ID_FILE_QUICKLOADSTATE:
|
||||
if (!Achievements::WarnUserIfHardcoreModeActive(false) && !NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
SetCursor(LoadCursor(0, IDC_WAIT));
|
||||
SaveState::LoadSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
|
||||
SaveState::LoadSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, SaveStateActionFinished);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -622,7 +622,7 @@ namespace MainWindow {
|
||||
if (!Achievements::WarnUserIfHardcoreModeActive(false) && !NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
if (!KeyMap::PspButtonHasMappings(VIRTKEY_LOAD_STATE)) {
|
||||
SetCursor(LoadCursor(0, IDC_WAIT));
|
||||
SaveState::LoadSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
|
||||
SaveState::LoadSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, SaveStateActionFinished);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -631,7 +631,7 @@ namespace MainWindow {
|
||||
{
|
||||
if (!Achievements::WarnUserIfHardcoreModeActive(true) && !NetworkWarnUserIfOnlineAndCantSavestate()) {
|
||||
SetCursor(LoadCursor(0, IDC_WAIT));
|
||||
SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
|
||||
SaveState::SaveSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, SaveStateActionFinished);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -642,7 +642,7 @@ namespace MainWindow {
|
||||
if (!KeyMap::PspButtonHasMappings(VIRTKEY_SAVE_STATE))
|
||||
{
|
||||
SetCursor(LoadCursor(0, IDC_WAIT));
|
||||
SaveState::SaveSlot(PSP_CoreParameter().fileToStart, g_Config.iCurrentStateSlot, SaveStateActionFinished);
|
||||
SaveState::SaveSlot(SaveState::GetGamePrefix(g_paramSFO), g_Config.iCurrentStateSlot, SaveStateActionFinished);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user