Add better savestate error handling.
Aborts when it can't load.
This commit is contained in:
parent
117ffaeb60
commit
fe97fd6fc5
7 changed files with 37 additions and 8 deletions
|
@ -115,16 +115,30 @@ public:
|
|||
MODE_VERIFY, // compare
|
||||
};
|
||||
|
||||
enum Error {
|
||||
ERROR_NONE = 0,
|
||||
ERROR_WARNING = 1,
|
||||
ERROR_FAILURE = 2,
|
||||
};
|
||||
|
||||
u8 **ptr;
|
||||
Mode mode;
|
||||
Error error;
|
||||
|
||||
public:
|
||||
PointerWrap(u8 **ptr_, Mode mode_) : ptr(ptr_), mode(mode_) {}
|
||||
PointerWrap(unsigned char **ptr_, int mode_) : ptr((u8**)ptr_), mode((Mode)mode_) {}
|
||||
PointerWrap(u8 **ptr_, Mode mode_) : ptr(ptr_), mode(mode_), error(ERROR_NONE) {}
|
||||
PointerWrap(unsigned char **ptr_, int mode_) : ptr((u8**)ptr_), mode((Mode)mode_), error(ERROR_NONE) {}
|
||||
|
||||
void SetMode(Mode mode_) {mode = mode_;}
|
||||
Mode GetMode() const {return mode;}
|
||||
u8 **GetPPtr() {return ptr;}
|
||||
void SetError(Error error_)
|
||||
{
|
||||
if (error < error_)
|
||||
error = error_;
|
||||
if (error != ERROR_NONE)
|
||||
mode = PointerWrap::MODE_MEASURE;
|
||||
}
|
||||
|
||||
void DoVoid(void *data, int size)
|
||||
{
|
||||
|
@ -556,7 +570,7 @@ public:
|
|||
if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber)
|
||||
{
|
||||
PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
|
||||
mode = PointerWrap::MODE_MEASURE;
|
||||
SetError(ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -642,7 +656,7 @@ public:
|
|||
delete[] buf;
|
||||
|
||||
INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str());
|
||||
return true;
|
||||
return p.error != p.ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Save file template
|
||||
|
@ -712,7 +726,7 @@ public:
|
|||
|
||||
INFO_LOG(COMMON,"ChunkReader: Done writing %s",
|
||||
_rFilename.c_str());
|
||||
return true;
|
||||
return p.error != p.ERROR_FAILURE;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
|
|
@ -611,6 +611,7 @@ std::vector<PSPFileInfo> DirectoryFileSystem::GetDirListing(std::string path) {
|
|||
|
||||
void DirectoryFileSystem::DoState(PointerWrap &p) {
|
||||
if (!entries.empty()) {
|
||||
p.SetError(p.ERROR_WARNING);
|
||||
ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly.");
|
||||
}
|
||||
}
|
||||
|
@ -761,6 +762,7 @@ std::vector<PSPFileInfo> VFSFileSystem::GetDirListing(std::string path) {
|
|||
|
||||
void VFSFileSystem::DoState(PointerWrap &p) {
|
||||
if (!entries.empty()) {
|
||||
p.SetError(p.ERROR_WARNING);
|
||||
ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -422,6 +422,7 @@ void MetaFileSystem::DoState(PointerWrap &p)
|
|||
p.Do(n);
|
||||
if (n != (u32) fileSystems.size())
|
||||
{
|
||||
p.SetError(p.ERROR_FAILURE);
|
||||
ERROR_LOG(FILESYS, "Savestate failure: number of filesystems doesn't match.");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -165,7 +165,10 @@ void __KernelDoState(PointerWrap &p)
|
|||
std::string git_version = PPSSPP_GIT_VERSION;
|
||||
p.Do(git_version);
|
||||
if (git_version != PPSSPP_GIT_VERSION)
|
||||
{
|
||||
p.SetError(p.ERROR_WARNING);
|
||||
WARN_LOG(HLE, "Warning: this savestate was generated by a different version of PPSSPP. It may not load properly.");
|
||||
}
|
||||
|
||||
p.Do(kernelRunning);
|
||||
kernelObjects.DoState(p);
|
||||
|
@ -462,7 +465,11 @@ void KernelObjectPool::DoState(PointerWrap &p)
|
|||
p.Do(_maxCount);
|
||||
|
||||
if (_maxCount != maxCount)
|
||||
{
|
||||
p.SetError(p.ERROR_FAILURE);
|
||||
ERROR_LOG(HLE, "Unable to load state: different kernel object storage.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (p.mode == p.MODE_READ)
|
||||
{
|
||||
|
|
|
@ -227,6 +227,7 @@ void __InterruptsDoState(PointerWrap &p)
|
|||
p.Do(numInterrupts);
|
||||
if (numInterrupts != PSP_NUMBER_INTERRUPTS)
|
||||
{
|
||||
p.SetError(p.ERROR_FAILURE);
|
||||
ERROR_LOG(HLE, "Savestate failure: wrong number of interrupts, can't load.");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -405,7 +405,11 @@ public:
|
|||
u32 numCallbacks = THREAD_CALLBACK_NUM_TYPES;
|
||||
p.Do(numCallbacks);
|
||||
if (numCallbacks != THREAD_CALLBACK_NUM_TYPES)
|
||||
ERROR_LOG(HLE, "Unable to load state: different kernel object storage.");
|
||||
{
|
||||
p.SetError(p.ERROR_FAILURE);
|
||||
ERROR_LOG(HLE, "Unable to load state: different thread callback storage.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < THREAD_CALLBACK_NUM_TYPES; ++i)
|
||||
{
|
||||
|
@ -581,6 +585,7 @@ struct ThreadQueueList
|
|||
p.Do(numQueues);
|
||||
if (numQueues != NUM_QUEUES)
|
||||
{
|
||||
p.SetError(p.ERROR_FAILURE);
|
||||
ERROR_LOG(HLE, "Savestate loading error: invalid data");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -879,9 +879,8 @@ namespace MainWindow
|
|||
|
||||
void SaveStateActionFinished(bool result, void *userdata)
|
||||
{
|
||||
// TODO: Improve messaging?
|
||||
if (!result)
|
||||
MessageBox(0, "Savestate failure. Please try again later.", "Sorry", MB_OK);
|
||||
MessageBox(0, "Savestate failure. Using savestates between different PPSSPP versions is not supported.", "Sorry", MB_OK);
|
||||
SetCursor(LoadCursor(0, IDC_ARROW));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue