all repos — mgba @ ba993980dc31841d02fcd994e88c524c78317019

mGBA Game Boy Advance Emulator

Big cleanup to how RR handles separate segments, and adding lots of logging (fixes #106)
Jeffrey Pfau jeffrey@endrift.com
Thu, 07 Aug 2014 00:24:25 -0700
commit

ba993980dc31841d02fcd994e88c524c78317019

parent

f0053268003218ffc5252198c0d44ac234b02ff9

1 files changed, 37 insertions(+), 35 deletions(-)

jump to
M src/gba/gba-rr.csrc/gba/gba-rr.c

@@ -8,6 +8,10 @@ #define BINARY_EXT ".dat"

#define BINARY_MAGIC "GBAb" #define METADATA_FILENAME "metadata" BINARY_EXT +enum { + INVALID_INPUT = 0x8000 +}; + static bool _emitMagic(struct GBARRContext* rr, struct VFile* vf); static bool _verifyMagic(struct GBARRContext* rr, struct VFile* vf); static enum GBARRTag _readTag(struct GBARRContext* rr, struct VFile* vf);

@@ -114,6 +118,7 @@ }

rr->streamDir = stream; rr->metadataFile = rr->streamDir->openFile(rr->streamDir, METADATA_FILENAME, O_CREAT | O_RDWR); + rr->currentInput = INVALID_INPUT; if (!_parseMetadata(rr, rr->metadataFile)) { rr->metadataFile->close(rr->metadataFile); rr->metadataFile = 0;

@@ -153,6 +158,7 @@ return false;

} rr->movieStream = 0; rr->streamId = streamId; + rr->currentInput = INVALID_INPUT; char buffer[14]; snprintf(buffer, sizeof(buffer), "%u" BINARY_EXT, streamId); if (GBARRIsRecording(rr)) {

@@ -168,6 +174,7 @@ if (!rr->movieStream || !_verifyMagic(rr, rr->movieStream) || !_seekTag(rr, rr->movieStream, TAG_BEGIN)) {

GBARRStopPlaying(rr); } } + GBALog(0, GBA_LOG_DEBUG, "[RR] Loading segment: %u", streamId); rr->frames = 0; rr->lagFrames = 0; return true;

@@ -184,6 +191,7 @@ }

if (!GBARRLoadStream(rr, newStreamId)) { return false; } + GBALog(0, GBA_LOG_DEBUG, "[RR] New segment: %u", newStreamId); _emitMagic(rr, rr->movieStream); rr->maxStreamId = newStreamId; _emitTag(rr, rr->movieStream, TAG_PREVIOUSLY);

@@ -201,33 +209,12 @@ if (GBARRIsRecording(rr) || GBARRIsPlaying(rr)) {

return false; } - char buffer[14]; - snprintf(buffer, sizeof(buffer), "%u" BINARY_EXT, rr->streamId); - rr->movieStream = rr->streamDir->openFile(rr->streamDir, buffer, O_RDONLY); - if (!rr->movieStream) { + rr->isPlaying = true; + if (!GBARRLoadStream(rr, 1)) { + rr->isPlaying = false; return false; } - rr->autorecord = autorecord; - if (!_verifyMagic(rr, rr->movieStream)) { - return false; - } - rr->peekedTag = TAG_INVALID; - _readTag(rr, rr->movieStream); // Discard the buffer - enum GBARRTag tag = _readTag(rr, rr->movieStream); - if (tag == TAG_PREVIOUSLY) { - if (rr->previously != 0) { - return false; - } - tag = _readTag(rr, rr->movieStream); - } - if (tag != TAG_BEGIN) { - rr->movieStream->close(rr->movieStream); - rr->movieStream = 0; - return false; - } - - rr->isPlaying = true; return true; }

@@ -282,9 +269,24 @@ if (!GBARRIsRecording(rr) && !GBARRIsPlaying(rr)) {

return; } + if (GBARRIsPlaying(rr)) { + while (rr->peekedTag == TAG_INPUT) { + _readTag(rr, rr->movieStream); + GBALog(0, GBA_LOG_WARN, "[RR] Desync detected!"); + } + if (rr->peekedTag == TAG_LAG) { + GBALog(0, GBA_LOG_DEBUG, "[RR] Lag frame marked in stream"); + if (rr->inputThisFrame) { + GBALog(0, GBA_LOG_WARN, "[RR] Lag frame in stream does not match movie"); + } + } + } + ++rr->frames; + GBALog(0, GBA_LOG_DEBUG, "[RR] Frame: %u", rr->frames); if (!rr->inputThisFrame) { ++rr->lagFrames; + GBALog(0, GBA_LOG_DEBUG, "[RR] Lag frame: %u", rr->lagFrames); } if (GBARRIsRecording(rr)) {

@@ -292,12 +294,8 @@ if (!rr->inputThisFrame) {

_emitTag(rr, rr->movieStream, TAG_LAG); } _emitTag(rr, rr->movieStream, TAG_FRAME); - rr->inputThisFrame = false; } else { - if (rr->peekedTag == TAG_INPUT) { - GBALog(0, GBA_LOG_WARN, "RR desync detected!"); - } if (!_seekTag(rr, rr->movieStream, TAG_FRAME)) { uint32_t endStreamId = rr->streamId; GBARRStopPlaying(rr);

@@ -320,6 +318,7 @@ _emitTag(rr, rr->movieStream, TAG_INPUT);

rr->movieStream->write(rr->movieStream, &keys, sizeof(keys)); rr->currentInput = keys; } + GBALog(0, GBA_LOG_DEBUG, "[RR] Input log: %03X", rr->currentInput); rr->inputThisFrame = true; }

@@ -331,6 +330,11 @@

if (rr->peekedTag == TAG_INPUT) { _readTag(rr, rr->movieStream); } + rr->inputThisFrame = true; + if (rr->currentInput == INVALID_INPUT) { + GBALog(0, GBA_LOG_WARN, "[RR] Stream did not specify input"); + } + GBALog(0, GBA_LOG_DEBUG, "[RR] Input replay: %03X", rr->currentInput); return rr->currentInput; }

@@ -429,18 +433,17 @@ rr->peekedTag = TAG_EOF;

} else { rr->peekedTag = tagBuffer; } + + if (rr->peekedTag == TAG_END) { + GBARRSkipSegment(rr); + } return tag; } bool _seekTag(struct GBARRContext* rr, struct VFile* vf, enum GBARRTag tag) { enum GBARRTag readTag; while ((readTag = _readTag(rr, vf)) != tag) { - if (vf == rr->movieStream && readTag == TAG_END) { - if (!GBARRSkipSegment(rr)) { - return false; - } - vf = rr->movieStream; - } else if (readTag == TAG_EOF) { + if (readTag == TAG_EOF) { return false; } }

@@ -525,7 +528,6 @@ }

return _markStreamNext(rr, currentStreamId, rr->previously); } return true; - } struct VFile* _openSavedata(struct GBARRContext* rr, int flags) {