New movie format

This commit is contained in:
Jeffrey Pfau 2014-07-27 18:22:39 -07:00
parent f39d7e3640
commit 45b8ffb9cf
2 changed files with 109 additions and 17 deletions

View File

@ -5,6 +5,10 @@
#define FILE_INPUTS "input.log"
static enum GBARRTag _readTag(struct GBARRContext* rr, struct VFile* vf);
static bool _seekTag(struct GBARRContext* rr, struct VFile* vf, enum GBARRTag tag);
static bool _emitTag(struct GBARRContext* rr, struct VFile* vf, uint8_t tag);
void GBARRContextCreate(struct GBA* gba) {
if (gba->rr) {
return;
@ -23,12 +27,12 @@ void GBARRContextDestroy(struct GBA* gba) {
}
bool GBARRSetStream(struct GBARRContext* rr, struct VDir* stream) {
if (rr->inputsStream && !rr->inputsStream->close(rr->inputsStream)) {
if (rr->movieStream && !rr->movieStream->close(rr->movieStream)) {
return false;
}
rr->streamDir = stream;
rr->inputsStream = stream->openFile(stream, FILE_INPUTS, O_CREAT | O_RDWR);
return !!rr->inputsStream;
rr->movieStream = 0;
return true;
}
bool GBARRStartPlaying(struct GBARRContext* rr, bool autorecord) {
@ -36,19 +40,30 @@ bool GBARRStartPlaying(struct GBARRContext* rr, bool autorecord) {
return false;
}
rr->movieStream = rr->streamDir->openFile(rr->streamDir, FILE_INPUTS, O_RDONLY);
rr->autorecord = autorecord;
if (rr->inputsStream->seek(rr->inputsStream, 0, SEEK_SET) < 0) {
return false;
}
if (rr->inputsStream->read(rr->inputsStream, &rr->nextInput, sizeof(rr->nextInput)) != sizeof(rr->nextInput)) {
rr->peekedTag = TAG_INVALID;
_readTag(rr, rr->movieStream); // Discard the buffer
enum GBARRTag tag = _readTag(rr, rr->movieStream);
if (tag != TAG_BEGIN) {
rr->movieStream->close(rr->movieStream);
rr->movieStream = 0;
return false;
}
rr->isPlaying = true;
return true;
}
void GBARRStopPlaying(struct GBARRContext* rr) {
if (!GBARRIsPlaying(rr)) {
return;
}
rr->isPlaying = false;
if (rr->movieStream) {
rr->movieStream->close(rr->movieStream);
rr->movieStream = 0;
}
}
bool GBARRStartRecording(struct GBARRContext* rr) {
@ -56,12 +71,27 @@ bool GBARRStartRecording(struct GBARRContext* rr) {
return false;
}
rr->movieStream = rr->streamDir->openFile(rr->streamDir, FILE_INPUTS, O_TRUNC | O_CREAT | O_WRONLY);
if (!_emitTag(rr, rr->movieStream, TAG_BEGIN)) {
rr->movieStream->close(rr->movieStream);
rr->movieStream = 0;
return false;
}
rr->isRecording = true;
return true;
}
void GBARRStopRecording(struct GBARRContext* rr) {
if (!GBARRIsRecording(rr)) {
return;
}
rr->isRecording = false;
if (rr->movieStream) {
_emitTag(rr, rr->movieStream, TAG_END);
rr->movieStream->close(rr->movieStream);
rr->movieStream = 0;
}
}
bool GBARRIsPlaying(struct GBARRContext* rr) {
@ -73,7 +103,7 @@ bool GBARRIsRecording(struct GBARRContext* rr) {
}
void GBARRNextFrame(struct GBARRContext* rr) {
if (!GBARRIsRecording(rr)) {
if (!GBARRIsRecording(rr) && !GBARRIsPlaying(rr)) {
return;
}
@ -82,7 +112,18 @@ void GBARRNextFrame(struct GBARRContext* rr) {
++rr->lagFrames;
}
rr->inputThisFrame = false;
if (GBARRIsRecording(rr)) {
if (!rr->inputThisFrame) {
_emitTag(rr, rr->movieStream, TAG_LAG);
}
_emitTag(rr, rr->movieStream, TAG_FRAME);
rr->inputThisFrame = false;
} else {
if (!_seekTag(rr, rr->movieStream, TAG_FRAME)) {
GBARRStopPlaying(rr);
}
}
}
void GBARRLogInput(struct GBARRContext* rr, uint16_t keys) {
@ -90,7 +131,11 @@ void GBARRLogInput(struct GBARRContext* rr, uint16_t keys) {
return;
}
rr->inputsStream->write(rr->inputsStream, &keys, sizeof(keys));
if (keys != rr->currentInput) {
_emitTag(rr, rr->movieStream, TAG_INPUT);
rr->movieStream->write(rr->movieStream, &keys, sizeof(keys));
rr->currentInput = keys;
}
rr->inputThisFrame = true;
}
@ -99,10 +144,45 @@ uint16_t GBARRQueryInput(struct GBARRContext* rr) {
return 0;
}
uint16_t keys = rr->nextInput;
rr->isPlaying = rr->inputsStream->read(rr->inputsStream, &rr->nextInput, sizeof(rr->nextInput)) == sizeof(rr->nextInput);
if (!rr->isPlaying && rr->autorecord) {
rr->isRecording = true;
if (rr->peekedTag == TAG_INPUT) {
_readTag(rr, rr->movieStream);
}
return keys;
return rr->currentInput;
}
enum GBARRTag _readTag(struct GBARRContext* rr, struct VFile* vf) {
enum GBARRTag tag = rr->peekedTag;
switch (tag) {
case TAG_INPUT:
vf->read(vf, &rr->currentInput, sizeof(uint16_t));
break;
case TAG_FRAME:
case TAG_LAG:
case TAG_BEGIN:
case TAG_END:
case TAG_INVALID:
break;
}
uint8_t tagBuffer;
if (vf->read(vf, &tagBuffer, 1) != 1) {
tagBuffer = TAG_END;
}
rr->peekedTag = tagBuffer;
return tag;
}
bool _seekTag(struct GBARRContext* rr, struct VFile* vf, enum GBARRTag tag) {
enum GBARRTag readTag;
while ((readTag = _readTag(rr, vf)) != tag) {
if (readTag == TAG_END) {
return false;
}
}
return true;
}
bool _emitTag(struct GBARRContext* rr, struct VFile* vf, uint8_t tag) {
UNUSED(rr);
return vf->write(vf, &tag, 1) == 1;
}

View File

@ -7,11 +7,21 @@ struct GBA;
struct VDir;
struct VFile;
enum GBARRTag {
TAG_INVALID = 0x00,
TAG_INPUT = 0x01,
TAG_FRAME = 0x02,
TAG_LAG = 0x03,
TAG_BEGIN = 0x10,
TAG_END = 0x11,
TAG_PREVIOUSLY = 0x12,
TAG_NEXT_TIME = 0x13
};
struct GBARRContext {
// Playback state
bool isPlaying;
bool autorecord;
uint16_t nextInput;
// Recording state
bool isRecording;
@ -23,7 +33,9 @@ struct GBARRContext {
// Streaming state
struct VDir* streamDir;
struct VFile* inputsStream;
struct VFile* movieStream;
uint16_t currentInput;
enum GBARRTag peekedTag;
};
void GBARRContextCreate(struct GBA*);