all repos — mgba @ 82b31c46f11c81193809e26479d8699b771b1be1

mGBA Game Boy Advance Emulator

RR starting from savegame (currently broken) and savestate
Jeffrey Pfau jeffrey@endrift.com
Mon, 04 Aug 2014 23:37:37 -0700
commit

82b31c46f11c81193809e26479d8699b771b1be1

parent

86a2edbdf1b79b0a6a55f3b1e9452d90a4c67999

M src/gba/gba-rr.csrc/gba/gba-rr.c

@@ -1,6 +1,7 @@

#include "gba-rr.h" #include "gba.h" +#include "gba-serialize.h" #include "util/vfs.h" #define BINARY_EXT ".dat"

@@ -13,6 +14,9 @@ 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); 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) {

@@ -35,21 +39,63 @@ GBARRStopRecording(gba->rr);

} 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); } }

@@ -427,3 +473,11 @@ }

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); +}
M src/gba/gba-rr.hsrc/gba/gba-rr.h

@@ -65,6 +65,8 @@

enum GBARRInitFrom initFrom; off_t initFromOffset; + struct VFile* savedata; + // Streaming state struct VDir* streamDir; struct VFile* metadataFile;

@@ -77,7 +79,8 @@ };

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);
M src/gba/gba-savedata.csrc/gba/gba-savedata.c

@@ -72,6 +72,32 @@ GBASavedataDeinit(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;
M src/gba/gba-savedata.hsrc/gba/gba-savedata.h

@@ -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);
M src/platform/sdl/sdl-events.csrc/platform/sdl/sdl-events.c

@@ -123,31 +123,26 @@ GBAThreadReset(context);

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); + GBARRStopRecording(context->gba->rr); GBARRInitStream(context->gba->rr, context->stateDir); - GBARRStopRecording(context->gba->rr); GBARRStartPlaying(context->gba->rr, false); - if (context->gba->rr->initFrom & INIT_FROM_SAVESTATE) { - // TODO - } - GBARRAlterSavedata(context->gba); + GBARRLoadState(context->gba); GBAThreadContinue(context); } break;