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
1 files changed,
37 insertions(+),
35 deletions(-)
jump to
M
src/gba/gba-rr.c
→
src/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) {