mirror of https://github.com/mgba-emu/mgba.git
RR starting from savegame (currently broken) and savestate
This commit is contained in:
parent
86a2edbdf1
commit
82b31c46f1
|
@ -1,6 +1,7 @@
|
|||
#include "gba-rr.h"
|
||||
|
||||
#include "gba.h"
|
||||
#include "gba-serialize.h"
|
||||
#include "util/vfs.h"
|
||||
|
||||
#define BINARY_EXT ".dat"
|
||||
|
@ -14,6 +15,9 @@ static bool _seekTag(struct GBARRContext* rr, struct VFile* vf, enum GBARRTag ta
|
|||
static bool _emitTag(struct GBARRContext* rr, struct VFile* vf, uint8_t tag);
|
||||
static bool _parseMetadata(struct GBARRContext* rr, struct VFile* vf);
|
||||
|
||||
static struct VFile* _openSavedata(struct GBARRContext* rr, int flags);
|
||||
static struct VFile* _openSavestate(struct GBARRContext* rr, int flags);
|
||||
|
||||
void GBARRContextCreate(struct GBA* gba) {
|
||||
if (gba->rr) {
|
||||
return;
|
||||
|
@ -36,21 +40,63 @@ void GBARRContextDestroy(struct GBA* gba) {
|
|||
if (gba->rr->metadataFile) {
|
||||
gba->rr->metadataFile->close(gba->rr->metadataFile);
|
||||
}
|
||||
if (gba->rr->savedata) {
|
||||
gba->rr->savedata->close(gba->rr->savedata);
|
||||
}
|
||||
|
||||
free(gba->rr);
|
||||
gba->rr = 0;
|
||||
}
|
||||
|
||||
void GBARRAlterSavedata(struct GBA* gba) {
|
||||
void GBARRSaveState(struct GBA* gba) {
|
||||
if (!gba || !gba->rr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gba->rr->initFrom & INIT_FROM_SAVEGAME) {
|
||||
// TOOD
|
||||
if (gba->rr->savedata) {
|
||||
gba->rr->savedata->close(gba->rr->savedata);
|
||||
}
|
||||
gba->rr->savedata = _openSavedata(gba->rr, O_TRUNC | O_CREAT | O_WRONLY);
|
||||
GBASavedataClone(&gba->memory.savedata, gba->rr->savedata);
|
||||
gba->rr->savedata->close(gba->rr->savedata);
|
||||
gba->rr->savedata = _openSavedata(gba->rr, O_RDONLY);
|
||||
GBASavedataMask(&gba->memory.savedata, gba->rr->savedata);
|
||||
} else {
|
||||
GBASavedataMask(&gba->memory.savedata, 0);
|
||||
}
|
||||
|
||||
if (gba->rr->initFrom & INIT_FROM_SAVESTATE) {
|
||||
struct VFile* vf = _openSavestate(gba->rr, O_TRUNC | O_CREAT | O_RDWR);
|
||||
GBASaveStateNamed(gba, vf, false);
|
||||
vf->close(vf);
|
||||
} else {
|
||||
ARMReset(gba->cpu);
|
||||
}
|
||||
}
|
||||
|
||||
void GBARRLoadState(struct GBA* gba) {
|
||||
if (!gba || !gba->rr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gba->rr->initFrom & INIT_FROM_SAVEGAME) {
|
||||
if (gba->rr->savedata) {
|
||||
gba->rr->savedata->close(gba->rr->savedata);
|
||||
}
|
||||
gba->rr->savedata = _openSavedata(gba->rr, O_RDONLY);
|
||||
GBASavedataMask(&gba->memory.savedata, gba->rr->savedata);
|
||||
} else {
|
||||
GBASavedataMask(&gba->memory.savedata, 0);
|
||||
}
|
||||
|
||||
if (gba->rr->initFrom & INIT_FROM_SAVESTATE) {
|
||||
struct VFile* vf = _openSavestate(gba->rr, O_RDONLY);
|
||||
GBALoadStateNamed(gba, vf);
|
||||
vf->close(vf);
|
||||
} else {
|
||||
ARMReset(gba->cpu);
|
||||
}
|
||||
}
|
||||
|
||||
bool GBARRInitStream(struct GBARRContext* rr, struct VDir* stream) {
|
||||
|
@ -427,3 +473,11 @@ bool _parseMetadata(struct GBARRContext* rr, struct VFile* vf) {
|
|||
rr->maxStreamIdOffset = vf->seek(vf, 0, SEEK_SET);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct VFile* _openSavedata(struct GBARRContext* rr, int flags) {
|
||||
return rr->streamDir->openFile(rr->streamDir, "movie.sav", flags);
|
||||
}
|
||||
|
||||
struct VFile* _openSavestate(struct GBARRContext* rr, int flags) {
|
||||
return rr->streamDir->openFile(rr->streamDir, "movie.ssm", flags);
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ struct GBARRContext {
|
|||
enum GBARRInitFrom initFrom;
|
||||
off_t initFromOffset;
|
||||
|
||||
struct VFile* savedata;
|
||||
|
||||
// Streaming state
|
||||
struct VDir* streamDir;
|
||||
struct VFile* metadataFile;
|
||||
|
@ -77,7 +79,8 @@ struct GBARRContext {
|
|||
|
||||
void GBARRContextCreate(struct GBA*);
|
||||
void GBARRContextDestroy(struct GBA*);
|
||||
void GBARRAlterSavedata(struct GBA*);
|
||||
void GBARRSaveState(struct GBA*);
|
||||
void GBARRLoadState(struct GBA*);
|
||||
|
||||
bool GBARRInitStream(struct GBARRContext*, struct VDir*);
|
||||
bool GBARRReinitStream(struct GBARRContext*, enum GBARRInitFrom);
|
||||
|
|
|
@ -72,6 +72,32 @@ void GBASavedataUnmask(struct GBASavedata* savedata) {
|
|||
savedata->vf = savedata->realVf;
|
||||
}
|
||||
|
||||
bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
|
||||
if (savedata->data) {
|
||||
switch (savedata->type) {
|
||||
case SAVEDATA_SRAM:
|
||||
return out->write(out, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
|
||||
case SAVEDATA_FLASH512:
|
||||
return out->write(out, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
|
||||
case SAVEDATA_FLASH1M:
|
||||
return out->write(out, savedata->data, SIZE_CART_FLASH1M) == SIZE_CART_FLASH1M;
|
||||
case SAVEDATA_EEPROM:
|
||||
return out->write(out, savedata->data, SIZE_CART_EEPROM) == SIZE_CART_EEPROM;
|
||||
case SAVEDATA_NONE:
|
||||
return true;
|
||||
}
|
||||
} else if (savedata->vf) {
|
||||
off_t read = 0;
|
||||
uint8_t buffer[2048];
|
||||
do {
|
||||
read = savedata->vf->read(savedata->vf, buffer, sizeof(buffer));
|
||||
out->write(out, buffer, read);
|
||||
} while (read == sizeof(buffer));
|
||||
return read >= 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GBASavedataInitFlash(struct GBASavedata* savedata) {
|
||||
if (savedata->type == SAVEDATA_NONE) {
|
||||
savedata->type = SAVEDATA_FLASH512;
|
||||
|
|
|
@ -75,6 +75,7 @@ void GBASavedataDeinit(struct GBASavedata* savedata);
|
|||
|
||||
void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf);
|
||||
void GBASavedataUnmask(struct GBASavedata* savedata);
|
||||
bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out);
|
||||
|
||||
void GBASavedataInitFlash(struct GBASavedata* savedata);
|
||||
void GBASavedataInitEEPROM(struct GBASavedata* savedata);
|
||||
|
|
|
@ -123,31 +123,26 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents
|
|||
break;
|
||||
case SDLK_t:
|
||||
if (context->stateDir) {
|
||||
GBAThreadReset(context);
|
||||
GBAThreadInterrupt(context);
|
||||
GBARRContextCreate(context->gba);
|
||||
if (!GBARRIsRecording(context->gba->rr)) {
|
||||
GBARRStopPlaying(context->gba->rr);
|
||||
GBARRInitStream(context->gba->rr, context->stateDir);
|
||||
GBARRReinitStream(context->gba->rr, INIT_EX_NIHILO);
|
||||
GBARRStopPlaying(context->gba->rr);
|
||||
GBARRStartRecording(context->gba->rr);
|
||||
GBARRAlterSavedata(context->gba);
|
||||
GBARRSaveState(context->gba);
|
||||
}
|
||||
GBAThreadContinue(context);
|
||||
}
|
||||
break;
|
||||
case SDLK_y:
|
||||
if (context->stateDir) {
|
||||
GBAThreadReset(context);
|
||||
GBAThreadInterrupt(context);
|
||||
GBARRContextCreate(context->gba);
|
||||
GBARRInitStream(context->gba->rr, context->stateDir);
|
||||
GBARRStopRecording(context->gba->rr);
|
||||
GBARRInitStream(context->gba->rr, context->stateDir);
|
||||
GBARRStartPlaying(context->gba->rr, false);
|
||||
if (context->gba->rr->initFrom & INIT_FROM_SAVESTATE) {
|
||||
// TODO
|
||||
}
|
||||
GBARRAlterSavedata(context->gba);
|
||||
GBARRLoadState(context->gba);
|
||||
GBAThreadContinue(context);
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue