all repos — mgba @ e2807b39158b867d1226b211dc592d5d9a24dbba

mGBA Game Boy Advance Emulator

Core: Revise how savegame loading works
Jeffrey Pfau jeffrey@endrift.com
Sun, 18 Sep 2016 00:09:15 -0700
commit

e2807b39158b867d1226b211dc592d5d9a24dbba

parent

d746a333381cca520d1bd155fe2a554538db985a

M src/core/core.hsrc/core/core.h

@@ -126,7 +126,7 @@

struct mCheatDevice* (*cheatDevice)(struct mCore*); size_t (*savedataClone)(struct mCore*, void** sram); - bool (*savedataLoad)(struct mCore*, const void* sram, size_t size); + bool (*savedataRestore)(struct mCore*, const void* sram, size_t size, bool writeback); }; #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
M src/core/serialize.csrc/core/serialize.c

@@ -407,10 +407,10 @@ } else {

mLOG(SAVESTATE, WARN, "Savestate includes invalid screenshot"); } } - if (flags & SAVESTATE_SAVEDATA && mStateExtdataGet(&extdata, EXTDATA_SAVEDATA, &item)) { + if (mStateExtdataGet(&extdata, EXTDATA_SAVEDATA, &item)) { mLOG(SAVESTATE, INFO, "Loading savedata"); if (item.data) { - core->savedataLoad(core, item.data, item.size); + core->savedataRestore(core, item.data, item.size, flags & SAVESTATE_SAVEDATA); } } struct mCheatDevice* device;
M src/feature/gui/gui-runner.csrc/feature/gui/gui-runner.c

@@ -424,7 +424,7 @@ case RUNNER_RESET:

runner->core->reset(runner->core); break; case RUNNER_SAVE_STATE: - mCoreSaveState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT); + mCoreSaveState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_SAVEGAME); break; case RUNNER_LOAD_STATE: mCoreLoadState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT);
M src/gb/core.csrc/gb/core.c

@@ -177,7 +177,7 @@ }

static bool _GBCoreLoadTemporarySave(struct mCore* core, struct VFile* vf) { struct GB* gb = core->board; - GBSavedataMask(gb, vf); + GBSavedataMask(gb, vf, false); return true; // TODO: Return a real value }

@@ -484,8 +484,13 @@ memcpy(*sram, gb->memory.sram, gb->sramSize);

return gb->sramSize; } -static bool _GBCoreSavedataLoad(struct mCore* core, const void* sram, size_t size) { +static bool _GBCoreSavedataRestore(struct mCore* core, const void* sram, size_t size, bool writeback) { struct GB* gb = core->board; + if (!writeback) { + struct VFile* vf = VFileFromConstMemory(sram, size); + GBSavedataMask(gb, vf, true); + return true; + } struct VFile* vf = gb->sramVf; if (vf) { vf->seek(vf, 0, SEEK_SET);

@@ -563,6 +568,6 @@ core->attachDebugger = _GBCoreAttachDebugger;

core->detachDebugger = _GBCoreDetachDebugger; core->cheatDevice = _GBCoreCheatDevice; core->savedataClone = _GBCoreSavedataClone; - core->savedataLoad = _GBCoreSavedataLoad; + core->savedataRestore = _GBCoreSavedataRestore; return core; }
M src/gb/gb.csrc/gb/gb.c

@@ -118,8 +118,7 @@ gb->sramVf->unmap(gb->sramVf, gb->memory.sram, gb->sramSize);

if (gb->memory.mbcType == GB_MBC3_RTC) { GBMBCRTCWrite(gb); } - gb->sramVf->close(gb->sramVf); - gb->sramVf = 0; + gb->sramVf = NULL; } else if (gb->memory.sram) { mappedMemoryFree(gb->memory.sram, gb->sramSize); }

@@ -210,9 +209,10 @@ }

} } -void GBSavedataMask(struct GB* gb, struct VFile* vf) { +void GBSavedataMask(struct GB* gb, struct VFile* vf, bool writeback) { GBSramDeinit(gb); gb->sramVf = vf; + gb->sramMaskWriteback = writeback; gb->memory.sram = vf->map(vf, gb->sramSize, MAP_READ); }

@@ -220,9 +220,14 @@ void GBSavedataUnmask(struct GB* gb) {

if (gb->sramVf == gb->sramRealVf) { return; } + struct VFile* vf = gb->sramVf; GBSramDeinit(gb); gb->sramVf = gb->sramRealVf; gb->memory.sram = gb->sramVf->map(gb->sramVf, gb->sramSize, MAP_WRITE); + if (gb->sramMaskWriteback) { + vf->read(vf, gb->memory.sram, gb->sramSize); + } + vf->close(vf); } void GBUnloadROM(struct GB* gb) {

@@ -247,7 +252,11 @@ gb->pristineRom = 0;

gb->romVf = 0; } + struct VFile* vf = gb->sramVf; GBSramDeinit(gb); + if (vf) { + vf->close(vf); + } } void GBLoadBIOS(struct GB* gb, struct VFile* vf) {
M src/gb/gb.hsrc/gb/gb.h

@@ -70,6 +70,7 @@ struct VFile* sramRealVf;

uint32_t sramSize; int sramDirty; int32_t sramDirtAge; + bool sramMaskWriteback; struct mAVStream* stream;

@@ -121,7 +122,7 @@ void GBLoadBIOS(struct GB* gb, struct VFile* vf);

void GBSramClean(struct GB* gb, uint32_t frameCount); void GBResizeSram(struct GB* gb, size_t size); -void GBSavedataMask(struct GB* gb, struct VFile* vf); +void GBSavedataMask(struct GB* gb, struct VFile* vf, bool writeback); void GBSavedataUnmask(struct GB* gb); struct Patch;
M src/gba/core.csrc/gba/core.c

@@ -211,7 +211,7 @@ }

static bool _GBACoreLoadTemporarySave(struct mCore* core, struct VFile* vf) { struct GBA* gba = core->board; - GBASavedataMask(&gba->memory.savedata, vf); + GBASavedataMask(&gba->memory.savedata, vf, false); return true; // TODO: Return a real value }

@@ -507,14 +507,19 @@ }

return size; } -static bool _GBACoreSavedataLoad(struct mCore* core, const void* sram, size_t size) { +static bool _GBACoreSavedataRestore(struct mCore* core, const void* sram, size_t size, bool writeback) { struct VFile* vf = VFileFromConstMemory(sram, size); if (!vf) { return false; } struct GBA* gba = core->board; - bool success = GBASavedataLoad(&gba->memory.savedata, vf); - vf->close(vf); + bool success = true; + if (writeback) { + success = GBASavedataLoad(&gba->memory.savedata, vf); + vf->close(vf); + } else { + GBASavedataMask(&gba->memory.savedata, vf, true); + } return success; }

@@ -582,6 +587,6 @@ core->attachDebugger = _GBACoreAttachDebugger;

core->detachDebugger = _GBACoreDetachDebugger; core->cheatDevice = _GBACoreCheatDevice; core->savedataClone = _GBACoreSavedataClone; - core->savedataLoad = _GBACoreSavedataLoad; + core->savedataRestore = _GBACoreSavedataRestore; return core; }
M src/gba/memory.csrc/gba/memory.c

@@ -92,6 +92,7 @@ mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);

if (gba->memory.rom) { mappedMemoryFree(gba->memory.rom, gba->memory.romSize); } + GBASavedataUnmask(&gba->memory.savedata); GBASavedataDeinit(&gba->memory.savedata); if (gba->memory.savedata.realVf) { gba->memory.savedata.realVf->close(gba->memory.savedata.realVf);
M src/gba/rr/rr.csrc/gba/rr/rr.c

@@ -23,9 +23,9 @@ gba->rr->savedata = gba->rr->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 = gba->rr->openSavedata(gba->rr, O_RDONLY); - GBASavedataMask(&gba->memory.savedata, gba->rr->savedata); + GBASavedataMask(&gba->memory.savedata, gba->rr->savedata, false); } else { - GBASavedataMask(&gba->memory.savedata, 0); + GBASavedataMask(&gba->memory.savedata, 0, false); } if (gba->rr->initFrom & INIT_FROM_SAVESTATE) {

@@ -47,9 +47,9 @@ if (gba->rr->savedata) {

gba->rr->savedata->close(gba->rr->savedata); } gba->rr->savedata = gba->rr->openSavedata(gba->rr, O_RDONLY); - GBASavedataMask(&gba->memory.savedata, gba->rr->savedata); + GBASavedataMask(&gba->memory.savedata, gba->rr->savedata, false); } else { - GBASavedataMask(&gba->memory.savedata, 0); + GBASavedataMask(&gba->memory.savedata, 0, false); } if (gba->rr->initFrom & INIT_FROM_SAVESTATE) {
M src/gba/savedata.csrc/gba/savedata.c

@@ -47,10 +47,7 @@ void GBASavedataDeinit(struct GBASavedata* savedata) {

if (savedata->vf) { size_t size = GBASavedataSize(savedata); savedata->vf->unmap(savedata->vf, savedata->data, size); - if (savedata->vf != savedata->realVf) { - savedata->vf->close(savedata->vf); - } - savedata->vf = 0; + savedata->vf = NULL; } else { switch (savedata->type) { case SAVEDATA_SRAM:

@@ -74,23 +71,30 @@ savedata->data = 0;

savedata->type = SAVEDATA_AUTODETECT; } -void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf) { +void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback) { enum SavedataType type = savedata->type; GBASavedataDeinit(savedata); savedata->vf = vf; savedata->mapMode = MAP_READ; + savedata->maskWriteback = writeback; GBASavedataForceType(savedata, type, savedata->realisticTiming); } void GBASavedataUnmask(struct GBASavedata* savedata) { - if (savedata->mapMode != MAP_READ) { + if (savedata->vf == savedata->realVf) { return; } enum SavedataType type = savedata->type; + struct VFile* vf = savedata->vf; GBASavedataDeinit(savedata); savedata->vf = savedata->realVf; savedata->mapMode = MAP_WRITE; GBASavedataForceType(savedata, type, savedata->realisticTiming); + if (savedata->maskWriteback) { + GBASavedataLoad(savedata, vf); + savedata->maskWriteback = false; + } + vf->close(vf); } bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {

@@ -488,6 +492,9 @@ if (!(savedata->dirty & SAVEDATA_DIRT_SEEN)) {

savedata->dirty |= SAVEDATA_DIRT_SEEN; } } else if ((savedata->dirty & SAVEDATA_DIRT_SEEN) && frameCount - savedata->dirtAge > CLEANUP_THRESHOLD) { + if (savedata->maskWriteback) { + GBASavedataUnmask(savedata); + } size_t size = GBASavedataSize(savedata); savedata->dirty = 0; if (savedata->data && savedata->vf->sync(savedata->vf, savedata->data, size)) {
M src/gba/savedata.hsrc/gba/savedata.h

@@ -74,6 +74,7 @@ enum SavedataCommand command;

struct VFile* vf; int mapMode; + bool maskWriteback; struct VFile* realVf; int32_t readBitsRemaining;

@@ -95,7 +96,7 @@

void GBASavedataInit(struct GBASavedata* savedata, struct VFile* vf); void GBASavedataDeinit(struct GBASavedata* savedata); -void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf); +void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback); void GBASavedataUnmask(struct GBASavedata* savedata); size_t GBASavedataSize(struct GBASavedata* savedata); bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out);
M src/platform/sdl/sdl-events.csrc/platform/sdl/sdl-events.c

@@ -470,7 +470,7 @@ case SDLK_F7:

case SDLK_F8: case SDLK_F9: mCoreThreadInterrupt(context); - mCoreSaveState(context->core, event->keysym.sym - SDLK_F1 + 1, SAVESTATE_SCREENSHOT); + mCoreSaveState(context->core, event->keysym.sym - SDLK_F1 + 1, SAVESTATE_SAVEDATA | SAVESTATE_SCREENSHOT); mCoreThreadContinue(context); break; default: