From 76d486cc655cd2f0943c336cfaa8f930a0687b15 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 5 Jan 2016 02:33:25 -0800 Subject: [PATCH] GBA RR: Add support for resets in movies --- CHANGES | 1 + src/gba/gba.c | 7 +++++++ src/gba/rr/mgm.c | 12 ++++++++++++ src/gba/rr/mgm.h | 1 + src/gba/rr/rr.h | 1 + src/gba/rr/vbm.c | 14 ++++++++++++++ 6 files changed, 36 insertions(+) diff --git a/CHANGES b/CHANGES index 60b6794a5..d079b3a50 100644 --- a/CHANGES +++ b/CHANGES @@ -52,6 +52,7 @@ Misc: - Libretro: Add install target for libretro core - 3DS: Update to new ctrulib API - GBA RR: Add preliminary SRAM support for VBM loading + - GBA RR: Add support for resets in movies 0.3.2: (2015-12-16) Bugfixes: diff --git a/src/gba/gba.c b/src/gba/gba.c index 30df843a7..860d23cc0 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -912,6 +912,13 @@ void GBAFrameEnded(struct GBA* gba) { if (thread->frameCallback) { thread->frameCallback(thread); } + + if (gba->rr && gba->rr->queryReset(gba->rr)) { + // TODO: Clean up reset scheduling + MutexLock(&thread->stateMutex); + thread->state = THREAD_RESETING; + MutexUnlock(&thread->stateMutex); + } } void GBASetBreakpoint(struct GBA* gba, struct ARMComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) { diff --git a/src/gba/rr/mgm.c b/src/gba/rr/mgm.c index cf7f46c2b..a6a619c26 100644 --- a/src/gba/rr/mgm.c +++ b/src/gba/rr/mgm.c @@ -30,6 +30,7 @@ static bool GBAMGMIsRecording(const struct GBARRContext*); static void GBAMGMNextFrame(struct GBARRContext*); static void GBAMGMLogInput(struct GBARRContext*, uint16_t input); static uint16_t GBAMGMQueryInput(struct GBARRContext*); +static bool GBAMGMQueryReset(struct GBARRContext*); static void GBAMGMStateSaved(struct GBARRContext* rr, struct GBASerializedState* state); static void GBAMGMStateLoaded(struct GBARRContext* rr, const struct GBASerializedState* state); @@ -71,6 +72,7 @@ void GBAMGMContextCreate(struct GBAMGMContext* mgm) { mgm->d.nextFrame = GBAMGMNextFrame; mgm->d.logInput = GBAMGMLogInput; mgm->d.queryInput = GBAMGMQueryInput; + mgm->d.queryReset = GBAMGMQueryReset; mgm->d.stateSaved = GBAMGMStateSaved; mgm->d.stateLoaded = GBAMGMStateLoaded; @@ -324,6 +326,15 @@ uint16_t GBAMGMQueryInput(struct GBARRContext* rr) { return mgm->currentInput; } +bool GBAMGMQueryReset(struct GBARRContext* rr) { + if (!rr->isPlaying(rr)) { + return 0; + } + + struct GBAMGMContext* mgm = (struct GBAMGMContext*) rr; + return mgm->peekedTag == TAG_RESET; +} + void GBAMGMStateSaved(struct GBARRContext* rr, struct GBASerializedState* state) { struct GBAMGMContext* mgm = (struct GBAMGMContext*) rr; if (rr->isRecording(rr)) { @@ -441,6 +452,7 @@ enum GBAMGMTag _readTag(struct GBAMGMContext* mgm, struct VFile* vf) { // Empty markers case TAG_FRAME: case TAG_LAG: + case TAG_RESET: case TAG_BEGIN: case TAG_END: case TAG_INVALID: diff --git a/src/gba/rr/mgm.h b/src/gba/rr/mgm.h index 5870afb56..9c494d50f 100644 --- a/src/gba/rr/mgm.h +++ b/src/gba/rr/mgm.h @@ -20,6 +20,7 @@ enum GBAMGMTag { TAG_INPUT = 0x01, TAG_FRAME = 0x02, TAG_LAG = 0x03, + TAG_RESET = 0x04, // Stream chunking tags TAG_BEGIN = 0x10, diff --git a/src/gba/rr/rr.h b/src/gba/rr/rr.h index 940f9c425..15fa5984d 100644 --- a/src/gba/rr/rr.h +++ b/src/gba/rr/rr.h @@ -33,6 +33,7 @@ struct GBARRContext { void (*nextFrame)(struct GBARRContext*); void (*logInput)(struct GBARRContext*, uint16_t input); uint16_t (*queryInput)(struct GBARRContext*); + bool (*queryReset)(struct GBARRContext*); void (*stateSaved)(struct GBARRContext*, struct GBASerializedState*); void (*stateLoaded)(struct GBARRContext*, const struct GBASerializedState*); diff --git a/src/gba/rr/vbm.c b/src/gba/rr/vbm.c index 71deb345b..5a3f0d0b6 100644 --- a/src/gba/rr/vbm.c +++ b/src/gba/rr/vbm.c @@ -27,6 +27,7 @@ static bool GBAVBMIsRecording(const struct GBARRContext*); static void GBAVBMNextFrame(struct GBARRContext*); static uint16_t GBAVBMQueryInput(struct GBARRContext*); +static bool GBAVBMQueryReset(struct GBARRContext*); static void GBAVBMStateSaved(struct GBARRContext* rr, struct GBASerializedState* state); static void GBAVBMStateLoaded(struct GBARRContext* rr, const struct GBASerializedState* state); @@ -50,6 +51,7 @@ void GBAVBMContextCreate(struct GBAVBMContext* vbm) { vbm->d.nextFrame = GBAVBMNextFrame; vbm->d.logInput = 0; vbm->d.queryInput = GBAVBMQueryInput; + vbm->d.queryReset = GBAVBMQueryReset; vbm->d.stateSaved = GBAVBMStateSaved; vbm->d.stateLoaded = GBAVBMStateLoaded; @@ -118,6 +120,18 @@ uint16_t GBAVBMQueryInput(struct GBARRContext* rr) { return input & 0x3FF; } +bool GBAVBMQueryReset(struct GBARRContext* rr) { + if (!rr->isPlaying(rr)) { + return false; + } + + struct GBAVBMContext* vbm = (struct GBAVBMContext*) rr; + uint16_t input; + vbm->vbmFile->read(vbm->vbmFile, &input, sizeof(input)); + vbm->vbmFile->seek(vbm->vbmFile, -sizeof(input), SEEK_CUR); + return input & 0x800; +} + void GBAVBMStateSaved(struct GBARRContext* rr, struct GBASerializedState* state) { UNUSED(rr); UNUSED(state);