src/gba/gba-rr.c (view raw)
1#include "gba-rr.h"
2
3#include "gba.h"
4#include "util/vfs.h"
5
6#define FILE_INPUTS "input.log"
7
8void GBARRContextCreate(struct GBA* gba) {
9 if (gba->rr) {
10 return;
11 }
12
13 gba->rr = calloc(1, sizeof(*gba->rr));
14}
15
16void GBARRContextDestroy(struct GBA* gba) {
17 if (!gba->rr) {
18 return;
19 }
20
21 free(gba->rr);
22 gba->rr = 0;
23}
24
25bool GBARRSetStream(struct GBARRContext* rr, struct VDir* stream) {
26 if (rr->inputsStream && !rr->inputsStream->close(rr->inputsStream)) {
27 return false;
28 }
29 rr->streamDir = stream;
30 rr->inputsStream = stream->openFile(stream, FILE_INPUTS, O_CREAT | O_RDWR);
31 return !!rr->inputsStream;
32}
33
34bool GBARRStartPlaying(struct GBARRContext* rr, bool autorecord) {
35 if (GBARRIsRecording(rr) || GBARRIsPlaying(rr)) {
36 return false;
37 }
38
39 rr->autorecord = autorecord;
40 if (rr->inputsStream->seek(rr->inputsStream, 0, SEEK_SET) < 0) {
41 return false;
42 }
43 if (rr->inputsStream->read(rr->inputsStream, &rr->nextInput, sizeof(rr->nextInput)) != sizeof(rr->nextInput)) {
44 return false;
45 }
46 rr->isPlaying = true;
47 return true;
48}
49
50void GBARRStopPlaying(struct GBARRContext* rr) {
51 rr->isPlaying = false;
52}
53
54bool GBARRStartRecording(struct GBARRContext* rr) {
55 if (GBARRIsRecording(rr) || GBARRIsPlaying(rr)) {
56 return false;
57 }
58
59 rr->isRecording = true;
60 return true;
61}
62
63void GBARRStopRecording(struct GBARRContext* rr) {
64 rr->isRecording = false;
65}
66
67bool GBARRIsPlaying(struct GBARRContext* rr) {
68 return rr && rr->isPlaying;
69}
70
71bool GBARRIsRecording(struct GBARRContext* rr) {
72 return rr && rr->isRecording;
73}
74
75void GBARRNextFrame(struct GBARRContext* rr) {
76 if (!GBARRIsRecording(rr)) {
77 return;
78 }
79
80 ++rr->frames;
81 if (!rr->inputThisFrame) {
82 ++rr->lagFrames;
83 }
84
85 rr->inputThisFrame = false;
86}
87
88void GBARRLogInput(struct GBARRContext* rr, uint16_t keys) {
89 if (!GBARRIsRecording(rr)) {
90 return;
91 }
92
93 rr->inputsStream->write(rr->inputsStream, &keys, sizeof(keys));
94 rr->inputThisFrame = true;
95}
96
97uint16_t GBARRQueryInput(struct GBARRContext* rr) {
98 if (!GBARRIsPlaying(rr)) {
99 return 0;
100 }
101
102 uint16_t keys = rr->nextInput;
103 rr->isPlaying = rr->inputsStream->read(rr->inputsStream, &rr->nextInput, sizeof(rr->nextInput)) == sizeof(rr->nextInput);
104 if (!rr->isPlaying && rr->autorecord) {
105 rr->isRecording = true;
106 }
107 return keys;
108}