Core: Fix rewinding getting out of sync (fixes #791)
Vicki Pfau vi@endrift.com
Mon, 10 Jul 2017 21:59:49 -0700
3 files changed,
15 insertions(+),
12 deletions(-)
M
CHANGES
→
CHANGES
@@ -178,6 +178,7 @@ - GB Serialize: Fix timer serialization
- GB Audio: Fix incorrect channel 4 iteration - GB Audio: Fix zombie mode bit masking - GBA Timer: Fix count-up timing overflowing timer 3 + - Core: Fix rewinding getting out of sync (fixes mgba.io/i/791) Misc: - Qt: Add language selector - GBA Timer: Improve accuracy of timers
M
include/mgba/core/rewind.h
→
include/mgba/core/rewind.h
@@ -31,6 +31,7 @@ bool onThread;
Thread thread; Condition cond; Mutex mutex; + bool ready; #endif };
M
src/core/rewind.c
→
src/core/rewind.c
@@ -30,6 +30,7 @@ context->size = 0;
context->stateFlags = SAVESTATE_SAVEDATA; #ifndef DISABLE_THREADING context->onThread = onThread; + context->ready = false; if (onThread) { MutexInit(&context->mutex); ConditionInit(&context->cond);@@ -73,6 +74,7 @@ context->previousState = context->currentState;
context->currentState = nextState; #ifndef DISABLE_THREADING if (context->onThread) { + context->ready = true; ConditionWake(&context->cond); MutexUnlock(&context->mutex); return;@@ -121,6 +123,12 @@ return false;
} --context->size; + mCoreLoadStateNamed(core, context->previousState, context->stateFlags); + if (context->current == 0) { + context->current = mCoreRewindPatchesSize(&context->patchMemory); + } + --context->current; + struct PatchFast* patch = mCoreRewindPatchesGetPointer(&context->patchMemory, context->current); size_t size2 = context->previousState->size(context->previousState); size_t size = context->currentState->size(context->currentState);@@ -129,18 +137,12 @@ size = size2;
} void* current = context->currentState->map(context->currentState, size, MAP_READ); void* previous = context->previousState->map(context->previousState, size, MAP_WRITE); - patch->d.applyPatch(&patch->d, current, size, previous, size); + patch->d.applyPatch(&patch->d, previous, size, current, size); context->currentState->unmap(context->currentState, current, size); context->previousState->unmap(context->previousState, previous, size); - mCoreLoadStateNamed(core, context->previousState, context->stateFlags); struct VFile* nextState = context->previousState; context->previousState = context->currentState; context->currentState = nextState; - - if (context->current == 0) { - context->current = mCoreRewindPatchesSize(&context->patchMemory); - } - --context->current; #ifndef DISABLE_THREADING if (context->onThread) { MutexUnlock(&context->mutex);@@ -154,13 +156,12 @@ THREAD_ENTRY _rewindThread(void* context) {
struct mCoreRewindContext* rewindContext = context; ThreadSetName("Rewind Diff Thread"); MutexLock(&rewindContext->mutex); - struct VFile* state = rewindContext->currentState; while (rewindContext->onThread) { - if (rewindContext->currentState != state) { - _rewindDiff(rewindContext); - state = rewindContext->currentState; + while (!rewindContext->ready) { + ConditionWait(&rewindContext->cond, &rewindContext->mutex); } - ConditionWait(&rewindContext->cond, &rewindContext->mutex); + _rewindDiff(rewindContext); + rewindContext->ready = false; } MutexUnlock(&rewindContext->mutex); return 0;