예제 #1
0
파일: rr.c 프로젝트: MoochMcGee/mgba
bool GBARRReinitStream(struct GBARRContext* rr, enum GBARRInitFrom initFrom) {
	if (!rr) {
		return false;
	}

	if (rr->metadataFile) {
		rr->metadataFile->truncate(rr->metadataFile, 0);
	} else {
		rr->metadataFile = rr->streamDir->openFile(rr->streamDir, METADATA_FILENAME, O_CREAT | O_TRUNC | O_RDWR);
	}
	_emitMagic(rr, rr->metadataFile);

	rr->initFrom = initFrom;
	rr->initFromOffset = rr->metadataFile->seek(rr->metadataFile, 0, SEEK_CUR);
	_emitTag(rr, rr->metadataFile, TAG_INIT | initFrom);

	rr->streamId = 0;
	rr->maxStreamId = 0;
	_emitTag(rr, rr->metadataFile, TAG_MAX_STREAM);
	rr->maxStreamIdOffset = rr->metadataFile->seek(rr->metadataFile, 0, SEEK_CUR);
	rr->metadataFile->write(rr->metadataFile, &rr->maxStreamId, sizeof(rr->maxStreamId));

	rr->rrCount = 0;
	_emitTag(rr, rr->metadataFile, TAG_RR_COUNT);
	rr->rrCountOffset = rr->metadataFile->seek(rr->metadataFile, 0, SEEK_CUR);
	rr->metadataFile->write(rr->metadataFile, &rr->rrCount, sizeof(rr->rrCount));
	return true;
}
예제 #2
0
파일: mgm.c 프로젝트: Sappharad/mgba
bool _emitEnd(struct GBAMGMContext* mgm, struct VFile* vf) {
	// TODO: Error check
	_emitTag(mgm, vf, TAG_END);
	_emitTag(mgm, vf, TAG_FRAME_COUNT);
	vf->write(vf, &mgm->d.frames, sizeof(mgm->d.frames));
	_emitTag(mgm, vf, TAG_LAG_COUNT);
	vf->write(vf, &mgm->d.lagFrames, sizeof(mgm->d.lagFrames));
	_emitTag(mgm, vf, TAG_NEXT_TIME);

	uint32_t newStreamId = 0;
	vf->write(vf, &newStreamId, sizeof(newStreamId));
	return true;
}
예제 #3
0
파일: rr.c 프로젝트: MoochMcGee/mgba
bool _emitEnd(struct GBARRContext* rr, struct VFile* vf) {
	// TODO: Error check
	_emitTag(rr, vf, TAG_END);
	_emitTag(rr, vf, TAG_FRAME_COUNT);
	vf->write(vf, &rr->frames, sizeof(rr->frames));
	_emitTag(rr, vf, TAG_LAG_COUNT);
	vf->write(vf, &rr->lagFrames, sizeof(rr->lagFrames));
	_emitTag(rr, vf, TAG_NEXT_TIME);

	uint32_t newStreamId = 0;
	vf->write(vf, &newStreamId, sizeof(newStreamId));
	return true;
}
예제 #4
0
파일: rr.c 프로젝트: MoochMcGee/mgba
void GBARRLogInput(struct GBARRContext* rr, uint16_t keys) {
	if (!GBARRIsRecording(rr)) {
		return;
	}

	if (keys != rr->currentInput) {
		_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;
}
예제 #5
0
파일: mgm.c 프로젝트: Sappharad/mgba
void GBAMGMNextFrame(struct GBARRContext* rr) {
	if (!rr->isRecording(rr) && !rr->isPlaying(rr)) {
		return;
	}

	struct GBAMGMContext* mgm = (struct GBAMGMContext*) rr;
	if (rr->isPlaying(rr)) {
		while (mgm->peekedTag == TAG_INPUT) {
			_readTag(mgm, mgm->movieStream);
			GBALog(0, GBA_LOG_WARN, "[RR] Desync detected!");
		}
		if (mgm->peekedTag == TAG_LAG) {
			GBALog(0, GBA_LOG_DEBUG, "[RR] Lag frame marked in stream");
			if (mgm->inputThisFrame) {
				GBALog(0, GBA_LOG_WARN, "[RR] Lag frame in stream does not match movie");
			}
		}
	}

	++mgm->d.frames;
	GBALog(0, GBA_LOG_DEBUG, "[RR] Frame: %u", mgm->d.frames);
	if (!mgm->inputThisFrame) {
		++mgm->d.lagFrames;
		GBALog(0, GBA_LOG_DEBUG, "[RR] Lag frame: %u", mgm->d.lagFrames);
	}

	if (rr->isRecording(rr)) {
		if (!mgm->inputThisFrame) {
			_emitTag(mgm, mgm->movieStream, TAG_LAG);
		}
		_emitTag(mgm, mgm->movieStream, TAG_FRAME);
		mgm->inputThisFrame = false;
	} else {
		if (!_seekTag(mgm, mgm->movieStream, TAG_FRAME)) {
			_streamEndReached(mgm);
		}
	}
}
예제 #6
0
파일: mgm.c 프로젝트: Sappharad/mgba
void GBAMGMLogInput(struct GBARRContext* rr, uint16_t keys) {
	if (!rr->isRecording(rr)) {
		return;
	}

	struct GBAMGMContext* mgm = (struct GBAMGMContext*) rr;
	if (keys != mgm->currentInput) {
		_emitTag(mgm, mgm->movieStream, TAG_INPUT);
		mgm->movieStream->write(mgm->movieStream, &keys, sizeof(keys));
		mgm->currentInput = keys;
	}
	GBALog(0, GBA_LOG_DEBUG, "[RR] Input log: %03X", mgm->currentInput);
	mgm->inputThisFrame = true;
}
예제 #7
0
파일: mgm.c 프로젝트: Sappharad/mgba
bool _incrementStream(struct GBAMGMContext* mgm, bool recursive) {
	uint32_t newStreamId = mgm->maxStreamId + 1;
	uint32_t oldStreamId = mgm->streamId;
	if (mgm->d.isRecording(&mgm->d) && mgm->movieStream) {
		if (!_markStreamNext(mgm, newStreamId, recursive)) {
			return false;
		}
	}
	if (!_loadStream(mgm, newStreamId)) {
		return false;
	}
	GBALog(0, GBA_LOG_DEBUG, "[RR] New segment: %u", newStreamId);
	_emitMagic(mgm, mgm->movieStream);
	mgm->maxStreamId = newStreamId;
	_emitTag(mgm, mgm->movieStream, TAG_PREVIOUSLY);
	mgm->movieStream->write(mgm->movieStream, &oldStreamId, sizeof(oldStreamId));
	_emitTag(mgm, mgm->movieStream, TAG_BEGIN);

	mgm->metadataFile->seek(mgm->metadataFile, mgm->maxStreamIdOffset, SEEK_SET);
	mgm->metadataFile->write(mgm->metadataFile, &mgm->maxStreamId, sizeof(mgm->maxStreamId));
	mgm->previously = oldStreamId;
	return true;
}
예제 #8
0
파일: rr.c 프로젝트: MoochMcGee/mgba
bool GBARRStartRecording(struct GBARRContext* rr) {
	if (GBARRIsRecording(rr) || GBARRIsPlaying(rr)) {
		return false;
	}

	if (!rr->maxStreamIdOffset) {
		_emitTag(rr, rr->metadataFile, TAG_MAX_STREAM);
		rr->maxStreamIdOffset = rr->metadataFile->seek(rr->metadataFile, 0, SEEK_CUR);
		rr->metadataFile->write(rr->metadataFile, &rr->maxStreamId, sizeof(rr->maxStreamId));
	}

	rr->isRecording = true;
	return GBARRIncrementStream(rr, false);
}
예제 #9
0
파일: rr.c 프로젝트: MoochMcGee/mgba
bool GBARRIncrementStream(struct GBARRContext* rr, bool recursive) {
	uint32_t newStreamId = rr->maxStreamId + 1;
	uint32_t oldStreamId = rr->streamId;
	if (GBARRIsRecording(rr) && rr->movieStream) {
		if (!_markStreamNext(rr, newStreamId, recursive)) {
			return false;
		}
	}
	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);
	rr->movieStream->write(rr->movieStream, &oldStreamId, sizeof(oldStreamId));
	_emitTag(rr, rr->movieStream, TAG_BEGIN);

	rr->metadataFile->seek(rr->metadataFile, rr->maxStreamIdOffset, SEEK_SET);
	rr->metadataFile->write(rr->metadataFile, &rr->maxStreamId, sizeof(rr->maxStreamId));
	rr->previously = oldStreamId;
	return true;
}
예제 #10
0
파일: mgm.c 프로젝트: Sappharad/mgba
bool GBAMGMStartRecording(struct GBARRContext* rr) {
	if (rr->isRecording(rr) || rr->isPlaying(rr)) {
		return false;
	}

	struct GBAMGMContext* mgm = (struct GBAMGMContext*) rr;
	if (!mgm->maxStreamIdOffset) {
		_emitTag(mgm, mgm->metadataFile, TAG_MAX_STREAM);
		mgm->maxStreamIdOffset = mgm->metadataFile->seek(mgm->metadataFile, 0, SEEK_CUR);
		mgm->metadataFile->write(mgm->metadataFile, &mgm->maxStreamId, sizeof(mgm->maxStreamId));
	}

	mgm->isRecording = true;
	return _incrementStream(mgm, false);
}
예제 #11
0
파일: mgm.c 프로젝트: Sappharad/mgba
bool GBAMGMCreateStream(struct GBAMGMContext* mgm, enum GBARRInitFrom initFrom) {
	if (mgm->metadataFile) {
		mgm->metadataFile->truncate(mgm->metadataFile, 0);
	} else {
		mgm->metadataFile = mgm->streamDir->openFile(mgm->streamDir, METADATA_FILENAME, O_CREAT | O_TRUNC | O_RDWR);
	}
	_emitMagic(mgm, mgm->metadataFile);

	mgm->d.initFrom = initFrom;
	mgm->initFromOffset = mgm->metadataFile->seek(mgm->metadataFile, 0, SEEK_CUR);
	_emitTag(mgm, mgm->metadataFile, TAG_INIT | initFrom);

	mgm->streamId = 0;
	mgm->maxStreamId = 0;
	_emitTag(mgm, mgm->metadataFile, TAG_MAX_STREAM);
	mgm->maxStreamIdOffset = mgm->metadataFile->seek(mgm->metadataFile, 0, SEEK_CUR);
	mgm->metadataFile->write(mgm->metadataFile, &mgm->maxStreamId, sizeof(mgm->maxStreamId));

	mgm->d.rrCount = 0;
	_emitTag(mgm, mgm->metadataFile, TAG_RR_COUNT);
	mgm->rrCountOffset = mgm->metadataFile->seek(mgm->metadataFile, 0, SEEK_CUR);
	mgm->metadataFile->write(mgm->metadataFile, &mgm->d.rrCount, sizeof(mgm->d.rrCount));
	return true;
}