Add basic support for rewinding (not enabled.)
This commit is contained in:
parent
e55c05503a
commit
b3c6e6c012
2 changed files with 91 additions and 0 deletions
|
@ -32,6 +32,7 @@
|
|||
#include "Core/MemMap.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/MIPS/JitCommon/JitCommon.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "UI/OnScreenDisplay.h"
|
||||
#include "i18n/i18n.h"
|
||||
|
||||
|
@ -47,6 +48,7 @@ namespace SaveState
|
|||
SAVESTATE_SAVE,
|
||||
SAVESTATE_LOAD,
|
||||
SAVESTATE_VERIFY,
|
||||
SAVESTATE_REWIND,
|
||||
};
|
||||
|
||||
struct Operation
|
||||
|
@ -62,10 +64,58 @@ namespace SaveState
|
|||
void *cbUserData;
|
||||
};
|
||||
|
||||
struct StateRingbuffer
|
||||
{
|
||||
StateRingbuffer(int size) : first_(0), next_(0), size_(size)
|
||||
{
|
||||
states_.resize(size);
|
||||
}
|
||||
|
||||
CChunkFileReader::Error Save()
|
||||
{
|
||||
int n = next_++ % size_;
|
||||
if (n == first_)
|
||||
++first_;
|
||||
|
||||
SaveStart state;
|
||||
size_t sz = CChunkFileReader::MeasurePtr(state);
|
||||
if (states_[n].size() < sz)
|
||||
states_[n].resize(sz);
|
||||
|
||||
return CChunkFileReader::SavePtr(states_[n].data(), state);
|
||||
}
|
||||
|
||||
CChunkFileReader::Error Restore()
|
||||
{
|
||||
// No valid states left.
|
||||
if (next_ == first_)
|
||||
return CChunkFileReader::ERROR_BAD_FILE;
|
||||
|
||||
int n = (next_-- + size_) % size_;
|
||||
if (states_[n].empty())
|
||||
return CChunkFileReader::ERROR_BAD_FILE;
|
||||
|
||||
SaveStart state;
|
||||
return CChunkFileReader::LoadPtr(states_[n].data(), state);
|
||||
}
|
||||
|
||||
typedef std::vector<u8> StateBuffer;
|
||||
int first_;
|
||||
int next_;
|
||||
int size_;
|
||||
std::vector<StateBuffer> states_;
|
||||
};
|
||||
|
||||
static bool needsProcess = false;
|
||||
static std::vector<Operation> pending;
|
||||
static std::recursive_mutex mutex;
|
||||
|
||||
// TODO: Should this be configurable?
|
||||
static const int REWIND_NUM_STATES = 5;
|
||||
static StateRingbuffer rewindStates(REWIND_NUM_STATES);
|
||||
// TODO: g_Config setting or something instead.
|
||||
static int rewindStateFreq = 0;
|
||||
|
||||
void SaveStart::DoState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("SaveStart", 1);
|
||||
|
@ -120,6 +170,11 @@ namespace SaveState
|
|||
Enqueue(Operation(SAVESTATE_VERIFY, std::string(""), callback, cbUserData));
|
||||
}
|
||||
|
||||
void Rewind(Callback callback, void *cbUserData)
|
||||
{
|
||||
Enqueue(Operation(SAVESTATE_REWIND, std::string(""), callback, cbUserData));
|
||||
}
|
||||
|
||||
|
||||
// Slot utilities
|
||||
|
||||
|
@ -230,6 +285,12 @@ namespace SaveState
|
|||
|
||||
void Process()
|
||||
{
|
||||
if (rewindStateFreq != 0)
|
||||
{
|
||||
if (gpuStats.numFlips % rewindStateFreq == 0)
|
||||
rewindStates.Save();
|
||||
}
|
||||
|
||||
if (!needsProcess)
|
||||
return;
|
||||
needsProcess = false;
|
||||
|
@ -289,6 +350,32 @@ namespace SaveState
|
|||
callbackResult = CChunkFileReader::Verify(state) == CChunkFileReader::ERROR_NONE;
|
||||
break;
|
||||
|
||||
case SAVESTATE_REWIND:
|
||||
INFO_LOG(COMMON, "Rewinding to recent savestate snapshot");
|
||||
result = rewindStates.Restore();
|
||||
if (result == CChunkFileReader::ERROR_NONE) {
|
||||
osm.Show(s->T("Loaded State"), 2.0);
|
||||
callbackResult = true;
|
||||
} else if (result == CChunkFileReader::ERROR_BROKEN_STATE) {
|
||||
// Cripes. Good news is, we might have more. Let's try those too, better than a reset.
|
||||
do
|
||||
result = rewindStates.Restore();
|
||||
while (result == CChunkFileReader::ERROR_BROKEN_STATE);
|
||||
|
||||
if (result == CChunkFileReader::ERROR_NONE) {
|
||||
osm.Show(s->T("Loaded State"), 2.0);
|
||||
callbackResult = true;
|
||||
} else {
|
||||
// We tried our best.
|
||||
HandleFailure();
|
||||
callbackResult = false;
|
||||
}
|
||||
} else {
|
||||
osm.Show(s->T("Load savestate failed"), 2.0);
|
||||
callbackResult = false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(COMMON, "Savestate failure: unknown operation type %d", op.type);
|
||||
callbackResult = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue