mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-03 12:12:06 +00:00
Merge pull request #14434 from unknownbrackets/savestate
SaveState: Show a warning when loading if saved after savestate
This commit is contained in:
commit
229e18420a
@ -25,23 +25,23 @@
|
||||
#include <ctime>
|
||||
#include <thread>
|
||||
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
#include "Common/Thread/ThreadUtil.h"
|
||||
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/Serialize/Serializer.h"
|
||||
#include "Common/Serialize/SerializeFuncs.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/Thread/ThreadUtil.h"
|
||||
#include "Core/Dialog/PSPSaveDialog.h"
|
||||
#include "Core/FileSystems/MetaFileSystem.h"
|
||||
#include "Core/Util/PPGeDraw.h"
|
||||
#include "Core/HLE/sceCtrl.h"
|
||||
#include "Core/HLE/sceUtility.h"
|
||||
#include "Core/HW/MemoryStick.h"
|
||||
#include "Core/MemMapHelpers.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/HW/MemoryStick.h"
|
||||
#include "Core/Dialog/PSPSaveDialog.h"
|
||||
#include "Core/SaveState.h"
|
||||
|
||||
const static float FONT_SCALE = 0.55f;
|
||||
|
||||
@ -1048,6 +1048,7 @@ void PSPSaveDialog::ExecuteIOAction() {
|
||||
}
|
||||
break;
|
||||
case DS_SAVE_SAVING:
|
||||
SaveState::NotifySaveData();
|
||||
if (param.Save(param.GetPspParam(), GetSelectedSaveDirName()) == 0) {
|
||||
display = DS_SAVE_DONE;
|
||||
} else {
|
||||
@ -1085,6 +1086,7 @@ void PSPSaveDialog::ExecuteNotVisibleIOAction() {
|
||||
break;
|
||||
case SCE_UTILITY_SAVEDATA_TYPE_SAVE: // Only save and exit
|
||||
case SCE_UTILITY_SAVEDATA_TYPE_AUTOSAVE:
|
||||
SaveState::NotifySaveData();
|
||||
result = param.Save(param.GetPspParam(), GetSelectedSaveDirName());
|
||||
break;
|
||||
case SCE_UTILITY_SAVEDATA_TYPE_SIZES:
|
||||
@ -1129,6 +1131,7 @@ void PSPSaveDialog::ExecuteNotVisibleIOAction() {
|
||||
// TODO: Should reset the directory's other files.
|
||||
case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATA:
|
||||
case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE:
|
||||
SaveState::NotifySaveData();
|
||||
result = param.Save(param.GetPspParam(), GetSelectedSaveDirName(), param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE);
|
||||
if (result == SCE_UTILITY_SAVEDATA_ERROR_SAVE_MS_NOSPACE) {
|
||||
result = SCE_UTILITY_SAVEDATA_ERROR_RW_MEMSTICK_FULL;
|
||||
@ -1136,6 +1139,7 @@ void PSPSaveDialog::ExecuteNotVisibleIOAction() {
|
||||
break;
|
||||
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA:
|
||||
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE:
|
||||
SaveState::NotifySaveData();
|
||||
result = param.Save(param.GetPspParam(), GetSelectedSaveDirName(), param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE);
|
||||
break;
|
||||
case SCE_UTILITY_SAVEDATA_TYPE_READDATA:
|
||||
|
@ -260,6 +260,8 @@ namespace SaveState
|
||||
// 4 hours of total gameplay since the virtual PSP started the game.
|
||||
static const u64 STALE_STATE_TIME = 4 * 3600 * 1000000ULL;
|
||||
static int saveStateGeneration = 0;
|
||||
static int saveDataGeneration = 0;
|
||||
static int lastSaveDataGeneration = 0;
|
||||
static std::string saveStateInitialGitVersion = "";
|
||||
|
||||
// TODO: Should this be configurable?
|
||||
@ -289,6 +291,12 @@ namespace SaveState
|
||||
} else {
|
||||
saveStateGeneration = 1;
|
||||
}
|
||||
if (s >= 3) {
|
||||
// Keep track of savedata (not save states) too.
|
||||
Do(p, saveDataGeneration);
|
||||
} else {
|
||||
saveDataGeneration = 0;
|
||||
}
|
||||
|
||||
// Gotta do CoreTiming first since we'll restore into it.
|
||||
CoreTiming::DoState(p);
|
||||
@ -779,6 +787,37 @@ namespace SaveState
|
||||
return state < gitVer;
|
||||
}
|
||||
|
||||
static Status TriggerLoadWarnings(std::string &callbackMessage) {
|
||||
auto sc = GetI18NCategory("Screen");
|
||||
|
||||
if (g_Config.bHideStateWarnings)
|
||||
return Status::SUCCESS;
|
||||
|
||||
if (IsStale()) {
|
||||
// For anyone wondering why (too long to put on the screen in an osm):
|
||||
// Using save states instead of saves simulates many hour play sessions.
|
||||
// Sometimes this exposes game bugs that were rarely seen on real devices,
|
||||
// because few people played on a real PSP for 10 hours straight.
|
||||
callbackMessage = sc->T("Loaded. Save in game, restart, and load for less bugs.");
|
||||
return Status::WARNING;
|
||||
}
|
||||
if (IsOldVersion()) {
|
||||
// Save states also preserve bugs from old PPSSPP versions, so warn.
|
||||
callbackMessage = sc->T("Loaded. Save in game, restart, and load for less bugs.");
|
||||
return Status::WARNING;
|
||||
}
|
||||
// If the loaded state (saveDataGeneration) is older, the game may prevent saving again.
|
||||
// This can happen with newer too, but ignore to/from 0 as a common likely safe case.
|
||||
if (saveDataGeneration != lastSaveDataGeneration && saveDataGeneration != 0 && lastSaveDataGeneration != 0) {
|
||||
if (saveDataGeneration < lastSaveDataGeneration)
|
||||
callbackMessage = sc->T("Loaded. Game may refuse to save over newer savedata.");
|
||||
else
|
||||
callbackMessage = sc->T("Loaded. Game may refuse to save over different savedata.");
|
||||
return Status::WARNING;
|
||||
}
|
||||
return Status::SUCCESS;
|
||||
}
|
||||
|
||||
void Process()
|
||||
{
|
||||
if (g_Config.iRewindFlipFrequency != 0 && gpuStats.numFlips != 0)
|
||||
@ -824,22 +863,12 @@ namespace SaveState
|
||||
// Use the state's latest version as a guess for saveStateInitialGitVersion.
|
||||
result = CChunkFileReader::Load(op.filename, &saveStateInitialGitVersion, state, &errorString);
|
||||
if (result == CChunkFileReader::ERROR_NONE) {
|
||||
callbackMessage = op.slot != LOAD_UNDO_SLOT ? slot_prefix + sc->T("Loaded State") : sc->T("State load undone");
|
||||
callbackResult = Status::SUCCESS;
|
||||
callbackMessage = op.slot != LOAD_UNDO_SLOT ? sc->T("Loaded State") : sc->T("State load undone");
|
||||
callbackResult = TriggerLoadWarnings(callbackMessage);
|
||||
hasLoadedState = true;
|
||||
|
||||
if (!g_Config.bHideStateWarnings && IsStale()) {
|
||||
// For anyone wondering why (too long to put on the screen in an osm):
|
||||
// Using save states instead of saves simulates many hour play sessions.
|
||||
// Sometimes this exposes game bugs that were rarely seen on real devices,
|
||||
// because few people played on a real PSP for 10 hours straight.
|
||||
callbackMessage = slot_prefix + sc->T("Loaded. Save in game, restart, and load for less bugs.");
|
||||
callbackResult = Status::WARNING;
|
||||
} else if (!g_Config.bHideStateWarnings && IsOldVersion()) {
|
||||
// Save states also preserve bugs from old PPSSPP versions, so warn.
|
||||
callbackMessage = slot_prefix + sc->T("Loaded. Save in game, restart, and load for less bugs.");
|
||||
callbackResult = Status::WARNING;
|
||||
}
|
||||
if (!slot_prefix.empty())
|
||||
callbackMessage = slot_prefix + callbackMessage;
|
||||
|
||||
#ifndef MOBILE_DEVICE
|
||||
if (g_Config.bSaveLoadResetsAVdumping) {
|
||||
@ -963,6 +992,11 @@ namespace SaveState
|
||||
}
|
||||
}
|
||||
|
||||
void NotifySaveData() {
|
||||
saveDataGeneration++;
|
||||
lastSaveDataGeneration = saveDataGeneration;
|
||||
}
|
||||
|
||||
void Cleanup() {
|
||||
if (needsRestart) {
|
||||
PSP_Shutdown();
|
||||
@ -989,6 +1023,8 @@ namespace SaveState
|
||||
|
||||
hasLoadedState = false;
|
||||
saveStateGeneration = 0;
|
||||
saveDataGeneration = 0;
|
||||
lastSaveDataGeneration = 0;
|
||||
saveStateInitialGitVersion.clear();
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,9 @@ namespace SaveState
|
||||
// Check if there's any save stating needing to be done. Normally called once per frame.
|
||||
void Process();
|
||||
|
||||
// Notify save state code that new save data has been written.
|
||||
void NotifySaveData();
|
||||
|
||||
// Cleanup by triggering a restart if needed.
|
||||
void Cleanup();
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user