GBA: Rewind now shows the frame after rewinding
Jeffrey Pfau jeffrey@endrift.com
Sun, 12 Apr 2015 20:22:04 -0700
4 files changed,
22 insertions(+),
0 deletions(-)
M
CHANGES
→
CHANGES
@@ -5,6 +5,7 @@ - Ability to mute individual audio channels
- Palette viewer - Volume control - More shortcuts are editable (e.g. quick save/load, solar sensor) + - Rewind now shows the frame after rewinding Bugfixes: - GBA: Fix timers not updating timing when writing to only the reload register - All: Fix sanitize-deb script not cleaning up after itself
M
src/gba/serialize.c
→
src/gba/serialize.c
@@ -256,6 +256,18 @@ state = GBAAllocateState();
thread->rewindBuffer[offset] = state; } GBASerialize(thread->gba, state); + + if (thread->rewindScreenBuffer) { + unsigned stride; + uint8_t* pixels = 0; + thread->gba->video.renderer->getPixels(thread->gba->video.renderer, &stride, (void*) &pixels); + if (pixels) { + size_t y; + for (y = 0; y < VIDEO_VERTICAL_PIXELS; ++y) { + memcpy(&thread->rewindScreenBuffer[(offset * VIDEO_VERTICAL_PIXELS + y) * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL], &pixels[y * stride * BYTES_PER_PIXEL], VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); + } + } + } thread->rewindBufferSize = thread->rewindBufferSize == thread->rewindBufferCapacity ? thread->rewindBufferCapacity : thread->rewindBufferSize + 1; thread->rewindBufferWriteOffset = (offset + 1) % thread->rewindBufferCapacity; }@@ -273,12 +285,15 @@ for (i = 0; i < threadContext->rewindBufferCapacity; ++i) {
GBADeallocateState(threadContext->rewindBuffer[i]); } free(threadContext->rewindBuffer); + free(threadContext->rewindScreenBuffer); } threadContext->rewindBufferCapacity = newCapacity; if (threadContext->rewindBufferCapacity > 0) { threadContext->rewindBuffer = calloc(threadContext->rewindBufferCapacity, sizeof(struct GBASerializedState*)); + threadContext->rewindScreenBuffer = calloc(threadContext->rewindBufferCapacity, VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); } else { threadContext->rewindBuffer = 0; + threadContext->rewindScreenBuffer = 0; } }@@ -300,6 +315,9 @@ }
thread->rewindBufferSize -= nStates; thread->rewindBufferWriteOffset = offset; GBADeserialize(thread->gba, state); + if (thread->rewindScreenBuffer) { + thread->gba->video.renderer->putPixels(thread->gba->video.renderer, VIDEO_HORIZONTAL_PIXELS, &thread->rewindScreenBuffer[offset * VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL]); + } } void GBARewindAll(struct GBAThread* thread) {
M
src/gba/supervisor/thread.c
→
src/gba/supervisor/thread.c
@@ -381,6 +381,7 @@ threadContext->sync.videoFrameOn = true;
threadContext->sync.videoFrameSkip = 0; threadContext->rewindBuffer = 0; + threadContext->rewindScreenBuffer = 0; int newCapacity = threadContext->rewindBufferCapacity; int newInterval = threadContext->rewindBufferInterval; threadContext->rewindBufferCapacity = 0;@@ -531,6 +532,7 @@ GBADeallocateState(threadContext->rewindBuffer[i]);
} } free(threadContext->rewindBuffer); + free(threadContext->rewindScreenBuffer); if (threadContext->rom) { threadContext->rom->close(threadContext->rom);
M
src/gba/supervisor/thread.h
→
src/gba/supervisor/thread.h
@@ -106,6 +106,7 @@ int rewindBufferInterval;
int rewindBufferNext; struct GBASerializedState** rewindBuffer; int rewindBufferWriteOffset; + uint8_t* rewindScreenBuffer; struct GBACheatDevice* cheats; };