Run save state operations at next Advance().

Should take some question marks out of things.
This commit is contained in:
Unknown W. Brackets 2012-12-27 11:28:12 -08:00
parent abeaaa9105
commit 2197d96989
4 changed files with 139 additions and 37 deletions

View File

@ -94,7 +94,3 @@ void WriteSyscall(const char *module, u32 nib, u32 address);
void CallSyscall(u32 op);
void ResolveSyscall(const char *moduleName, u32 nib, u32 address);
// Need to be able to save entire kernel state
int GetStateSize();
void SaveState(u8 *ptr);
void LoadState(const u8 *ptr);

View File

@ -24,6 +24,7 @@
#include "../FileSystems/MetaFileSystem.h"
#include "../PSPLoaders.h"
#include "../../Core/CoreTiming.h"
#include "../../Core/SaveState.h"
#include "../../Core/System.h"
#include "../../GPU/GPUInterface.h"
#include "../../GPU/GPUState.h"
@ -77,6 +78,7 @@ void __KernelInit()
return;
}
SaveState::Init();
__KernelMemoryInit();
__KernelThreadingInit();
__KernelMutexInit();

View File

@ -15,32 +15,130 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "../Common/StdMutex.h"
#include <vector>
#include "SaveState.h"
#include "MemMap.h"
#include "CoreTiming.h"
#include "HLE/sceKernel.h"
#include "MemMap.h"
// TODO: Need a way to schedule via CoreTiming and actually run then.
bool SaveState::Load(std::string &filename)
namespace SaveState
{
SaveState state;
return CChunkFileReader::Load(filename, REVISION, state);
struct SaveStart
{
void DoState(PointerWrap &p);
};
enum OperationType
{
SAVESTATE_SAVE,
SAVESTATE_LOAD,
SAVESTATE_VERIFY,
};
struct Operation
{
Operation(OperationType t, std::string &f, Callback cb)
: type(t), filename(f), callback(cb)
{
}
OperationType type;
std::string filename;
Callback callback;
};
static int timer;
static std::vector<Operation> pending;
static std::recursive_mutex mutex;
// This is where the magic happens.
void SaveStart::DoState(PointerWrap &p)
{
// This save state even saves its own state.
p.Do(timer);
p.DoMarker("SaveState");
Memory::DoState(p);
__KernelDoState(p);
}
void Enqueue(SaveState::Operation op)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
pending.push_back(op);
// Don't actually run it until next CoreTiming::Advance().
// It's possible there might be a duplicate but it won't hurt us.
// TODO: If paused, just run, don't wait?
CoreTiming::ScheduleEvent_Threadsafe(0, timer);
}
void Load(std::string &filename, Callback callback)
{
Enqueue(Operation(SAVESTATE_LOAD, filename, callback));
}
void Save(std::string &filename, Callback callback)
{
Enqueue(Operation(SAVESTATE_SAVE, filename, callback));
}
void Verify(Callback callback)
{
Enqueue(Operation(SAVESTATE_VERIFY, std::string(""), callback));
}
std::vector<Operation> Flush()
{
std::lock_guard<std::recursive_mutex> guard(mutex);
std::vector<Operation> copy = pending;
pending.clear();
return copy;
}
void Process(u64 userdata, int cyclesLate)
{
std::vector<Operation> operations = Flush();
SaveStart state;
for (size_t i = 0, n = operations.size(); i < n; ++i)
{
Operation &op = operations[i];
bool result;
switch (op.type)
{
case SAVESTATE_LOAD:
INFO_LOG(COMMON, "Loading state from %s", op.filename.c_str());
result = CChunkFileReader::Load(op.filename, REVISION, state);
break;
case SAVESTATE_SAVE:
INFO_LOG(COMMON, "Saving state to %s", op.filename.c_str());
result = CChunkFileReader::Save(op.filename, REVISION, state);
break;
case SAVESTATE_VERIFY:
INFO_LOG(COMMON, "Verifying save state system");
result = CChunkFileReader::Verify(state);
break;
default:
ERROR_LOG(COMMON, "Savestate failure: unknown operation type %d", op.type);
result = false;
break;
}
if (op.callback != NULL)
op.callback(result);
}
}
void Init()
{
timer = CoreTiming::RegisterEvent("SaveState", Process);
}
}
bool SaveState::Save(std::string &filename)
{
SaveState state;
return CChunkFileReader::Save(filename, REVISION, state);
}
bool SaveState::Verify()
{
SaveState state;
return CChunkFileReader::Verify(state);
}
void SaveState::DoState(PointerWrap &p)
{
Memory::DoState(p);
__KernelDoState(p);
}

View File

@ -16,18 +16,24 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "../Common/ChunkFile.h"
#include <string>
struct SaveState
namespace SaveState
{
typedef void (*Callback)(bool status);
// TODO: Better place for this?
static const int REVISION = 1;
const int REVISION = 1;
// Load the specified file into the current state.
static bool Load(std::string &filename);
// Save the current state to the specified file.
static bool Save(std::string &filename);
// For testing / automated tests. Runs a save state verification pass.
static bool Verify();
void Init();
void DoState(PointerWrap &p);
// Load the specified file into the current state (async.)
// Warning: callback will be called on a different thread.
void Load(std::string &filename, Callback callback = NULL);
// Save the current state to the specified file (async.)
// Warning: callback will be called on a different thread.
void Save(std::string &filename, Callback callback = NULL);
// For testing / automated tests. Runs a save state verification pass (async.)
// Warning: callback will be called on a different thread.
void Verify(Callback callback = NULL);
};