bool _loadStream(struct GBAMGMContext* mgm, uint32_t streamId) { if (mgm->movieStream && !mgm->movieStream->close(mgm->movieStream)) { return false; } mgm->movieStream = 0; mgm->streamId = streamId; mgm->currentInput = INVALID_INPUT; char buffer[14]; snprintf(buffer, sizeof(buffer), "%u" BINARY_EXT, streamId); if (mgm->d.isRecording(&mgm->d)) { int flags = O_CREAT | O_RDWR; if (streamId > mgm->maxStreamId) { flags |= O_TRUNC; } mgm->movieStream = mgm->streamDir->openFile(mgm->streamDir, buffer, flags); } else if (mgm->d.isPlaying(&mgm->d)) { mgm->movieStream = mgm->streamDir->openFile(mgm->streamDir, buffer, O_RDONLY); mgm->peekedTag = TAG_INVALID; if (!mgm->movieStream || !_verifyMagic(mgm, mgm->movieStream) || !_seekTag(mgm, mgm->movieStream, TAG_BEGIN)) { mgm->d.stopPlaying(&mgm->d); } } GBALog(0, GBA_LOG_DEBUG, "[RR] Loading segment: %u", streamId); mgm->d.frames = 0; mgm->d.lagFrames = 0; return true; }
bool GBARRLoadStream(struct GBARRContext* rr, uint32_t streamId) { if (rr->movieStream && !rr->movieStream->close(rr->movieStream)) { 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)) { int flags = O_CREAT | O_RDWR; if (streamId > rr->maxStreamId) { flags |= O_TRUNC; } rr->movieStream = rr->streamDir->openFile(rr->streamDir, buffer, flags); } else if (GBARRIsPlaying(rr)) { rr->movieStream = rr->streamDir->openFile(rr->streamDir, buffer, O_RDONLY); rr->peekedTag = TAG_INVALID; 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; }
bool _markStreamNext(struct GBAMGMContext* mgm, uint32_t newStreamId, bool recursive) { if (mgm->movieStream->seek(mgm->movieStream, -sizeof(newStreamId) - 1, SEEK_END) < 0) { return false; } uint8_t tagBuffer; if (mgm->movieStream->read(mgm->movieStream, &tagBuffer, 1) != 1) { return false; } if (tagBuffer != TAG_NEXT_TIME) { return false; } if (mgm->movieStream->write(mgm->movieStream, &newStreamId, sizeof(newStreamId)) != sizeof(newStreamId)) { return false; } if (recursive) { if (mgm->movieStream->seek(mgm->movieStream, 0, SEEK_SET) < 0) { return false; } if (!_verifyMagic(mgm, mgm->movieStream)) { return false; } _readTag(mgm, mgm->movieStream); if (_readTag(mgm, mgm->movieStream) != TAG_PREVIOUSLY) { return false; } if (mgm->previously == 0) { return true; } uint32_t currentStreamId = mgm->streamId; if (!_loadStream(mgm, mgm->previously)) { return false; } return _markStreamNext(mgm, currentStreamId, mgm->previously); } return true; }
bool _parseMetadata(struct GBAMGMContext* mgm, struct VFile* vf) { if (!_verifyMagic(mgm, vf)) { return false; } while (_readTag(mgm, vf) != TAG_EOF) { switch (mgm->peekedTag) { case TAG_MAX_STREAM: mgm->maxStreamIdOffset = vf->seek(vf, 0, SEEK_CUR); break; case TAG_INIT_EX_NIHILO: case TAG_INIT_FROM_SAVEGAME: case TAG_INIT_FROM_SAVESTATE: case TAG_INIT_FROM_BOTH: mgm->initFromOffset = vf->seek(vf, 0, SEEK_CUR); break; case TAG_RR_COUNT: mgm->rrCountOffset = vf->seek(vf, 0, SEEK_CUR); break; default: break; } } return true; }