Add better savestate error handling.

Aborts when it can't load.
This commit is contained in:
Unknown W. Brackets 2013-04-13 01:39:17 -07:00
parent 117ffaeb60
commit fe97fd6fc5
7 changed files with 37 additions and 8 deletions

View file

@ -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>

View file

@ -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.");
}
}

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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));
}