mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-27 07:20:49 +00:00
Merge pull request #1268 from unknownbrackets/savestates
Bump savestate version, add better error checking
This commit is contained in:
commit
d92dbf8f6d
@ -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;
|
||||
}
|
||||
|
@ -15,10 +15,11 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "HLE.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
#include "../MIPS/MIPSCodeUtils.h"
|
||||
#include "../MIPS/MIPSInt.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/MIPS/MIPSCodeUtils.h"
|
||||
#include "Core/MIPS/MIPSInt.h"
|
||||
|
||||
#include "Common/LogManager.h"
|
||||
#include "../FileSystems/FileSystem.h"
|
||||
@ -161,6 +162,14 @@ void __KernelShutdown()
|
||||
|
||||
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);
|
||||
p.DoMarker("KernelObjects");
|
||||
@ -456,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;
|
||||
}
|
||||
|
@ -111,6 +111,11 @@ namespace SaveState
|
||||
Enqueue(Operation(SAVESTATE_SAVE, filename, callback, cbUserData));
|
||||
}
|
||||
|
||||
void Verify(Callback callback, void *cbUserData)
|
||||
{
|
||||
Enqueue(Operation(SAVESTATE_VERIFY, std::string(""), callback, cbUserData));
|
||||
}
|
||||
|
||||
|
||||
// Slot utilities
|
||||
|
||||
@ -148,9 +153,10 @@ namespace SaveState
|
||||
(*callback)(false, cbUserData);
|
||||
}
|
||||
|
||||
void HasSaveInSlot(int slot)
|
||||
bool HasSaveInSlot(int slot)
|
||||
{
|
||||
std::string fn = GenerateSaveSlotFilename(slot);
|
||||
return File::Exists(fn);
|
||||
}
|
||||
|
||||
bool operator < (const tm &t1, const tm &t2) {
|
||||
@ -186,11 +192,6 @@ namespace SaveState
|
||||
}
|
||||
|
||||
|
||||
void Verify(Callback callback, void *cbUserData)
|
||||
{
|
||||
Enqueue(Operation(SAVESTATE_VERIFY, std::string(""), callback, cbUserData));
|
||||
}
|
||||
|
||||
std::vector<Operation> Flush()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
@ -24,14 +24,14 @@ namespace SaveState
|
||||
typedef void (*Callback)(bool status, void *cbUserData);
|
||||
|
||||
// TODO: Better place for this?
|
||||
const int REVISION = 1;
|
||||
const int REVISION = 2;
|
||||
const int SAVESTATESLOTS = 4;
|
||||
|
||||
void Init();
|
||||
|
||||
void SaveSlot(int slot, Callback callback, void *cbUserData = 0);
|
||||
void LoadSlot(int slot, Callback callback, void *cbUserData = 0);
|
||||
void HasSaveInSlot(int slot);
|
||||
bool HasSaveInSlot(int slot);
|
||||
int GetNewestSlot();
|
||||
|
||||
// Load the specified file into the current state (async.)
|
||||
|
@ -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…
Reference in New Issue
Block a user