all repos — mgba @ 5167fce4c70711a221c4179ae245aca19b6f394a

mGBA Game Boy Advance Emulator

Core: Fix rewinding getting out of sync (fixes #791)
Vicki Pfau vi@endrift.com
Mon, 10 Jul 2017 21:59:49 -0700
commit

5167fce4c70711a221c4179ae245aca19b6f394a

parent

253719d7a14e0002c8e987beff4c6a6a3604704f

3 files changed, 15 insertions(+), 12 deletions(-)

jump to
M CHANGESCHANGES

@@ -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.hinclude/mgba/core/rewind.h

@@ -31,6 +31,7 @@ bool onThread;

Thread thread; Condition cond; Mutex mutex; + bool ready; #endif };
M src/core/rewind.csrc/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;