Core: Revise how savegame loading works

This commit is contained in:
Jeffrey Pfau 2016-09-18 00:09:15 -07:00
parent d746a33338
commit e2807b3915
12 changed files with 57 additions and 28 deletions

View File

@ -126,7 +126,7 @@ void (*busWrite16)(struct mCore*, uint32_t address, uint16_t);
struct mCheatDevice* (*cheatDevice)(struct mCore*); struct mCheatDevice* (*cheatDevice)(struct mCore*);
size_t (*savedataClone)(struct mCore*, void** sram); 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 #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2

View File

@ -407,10 +407,10 @@ bool mCoreLoadStateNamed(struct mCore* core, struct VFile* vf, int flags) {
mLOG(SAVESTATE, WARN, "Savestate includes invalid screenshot"); 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"); mLOG(SAVESTATE, INFO, "Loading savedata");
if (item.data) { if (item.data) {
core->savedataLoad(core, item.data, item.size); core->savedataRestore(core, item.data, item.size, flags & SAVESTATE_SAVEDATA);
} }
} }
struct mCheatDevice* device; struct mCheatDevice* device;

View File

@ -424,7 +424,7 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
runner->core->reset(runner->core); runner->core->reset(runner->core);
break; break;
case RUNNER_SAVE_STATE: 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; break;
case RUNNER_LOAD_STATE: case RUNNER_LOAD_STATE:
mCoreLoadState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT); mCoreLoadState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT);

View File

@ -177,7 +177,7 @@ static bool _GBCoreLoadSave(struct mCore* core, struct VFile* vf) {
static bool _GBCoreLoadTemporarySave(struct mCore* core, struct VFile* vf) { static bool _GBCoreLoadTemporarySave(struct mCore* core, struct VFile* vf) {
struct GB* gb = core->board; struct GB* gb = core->board;
GBSavedataMask(gb, vf); GBSavedataMask(gb, vf, false);
return true; // TODO: Return a real value return true; // TODO: Return a real value
} }
@ -484,8 +484,13 @@ static size_t _GBCoreSavedataClone(struct mCore* core, void** sram) {
return 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; struct GB* gb = core->board;
if (!writeback) {
struct VFile* vf = VFileFromConstMemory(sram, size);
GBSavedataMask(gb, vf, true);
return true;
}
struct VFile* vf = gb->sramVf; struct VFile* vf = gb->sramVf;
if (vf) { if (vf) {
vf->seek(vf, 0, SEEK_SET); vf->seek(vf, 0, SEEK_SET);
@ -563,6 +568,6 @@ struct mCore* GBCoreCreate(void) {
core->detachDebugger = _GBCoreDetachDebugger; core->detachDebugger = _GBCoreDetachDebugger;
core->cheatDevice = _GBCoreCheatDevice; core->cheatDevice = _GBCoreCheatDevice;
core->savedataClone = _GBCoreSavedataClone; core->savedataClone = _GBCoreSavedataClone;
core->savedataLoad = _GBCoreSavedataLoad; core->savedataRestore = _GBCoreSavedataRestore;
return core; return core;
} }

View File

@ -118,8 +118,7 @@ static void GBSramDeinit(struct GB* gb) {
if (gb->memory.mbcType == GB_MBC3_RTC) { if (gb->memory.mbcType == GB_MBC3_RTC) {
GBMBCRTCWrite(gb); GBMBCRTCWrite(gb);
} }
gb->sramVf->close(gb->sramVf); gb->sramVf = NULL;
gb->sramVf = 0;
} else if (gb->memory.sram) { } else if (gb->memory.sram) {
mappedMemoryFree(gb->memory.sram, gb->sramSize); mappedMemoryFree(gb->memory.sram, gb->sramSize);
} }
@ -210,9 +209,10 @@ void GBSramClean(struct GB* gb, uint32_t frameCount) {
} }
} }
void GBSavedataMask(struct GB* gb, struct VFile* vf) { void GBSavedataMask(struct GB* gb, struct VFile* vf, bool writeback) {
GBSramDeinit(gb); GBSramDeinit(gb);
gb->sramVf = vf; gb->sramVf = vf;
gb->sramMaskWriteback = writeback;
gb->memory.sram = vf->map(vf, gb->sramSize, MAP_READ); gb->memory.sram = vf->map(vf, gb->sramSize, MAP_READ);
} }
@ -220,9 +220,14 @@ void GBSavedataUnmask(struct GB* gb) {
if (gb->sramVf == gb->sramRealVf) { if (gb->sramVf == gb->sramRealVf) {
return; return;
} }
struct VFile* vf = gb->sramVf;
GBSramDeinit(gb); GBSramDeinit(gb);
gb->sramVf = gb->sramRealVf; gb->sramVf = gb->sramRealVf;
gb->memory.sram = gb->sramVf->map(gb->sramVf, gb->sramSize, MAP_WRITE); 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) { void GBUnloadROM(struct GB* gb) {
@ -247,7 +252,11 @@ void GBUnloadROM(struct GB* gb) {
gb->romVf = 0; gb->romVf = 0;
} }
struct VFile* vf = gb->sramVf;
GBSramDeinit(gb); GBSramDeinit(gb);
if (vf) {
vf->close(vf);
}
} }
void GBLoadBIOS(struct GB* gb, struct VFile* vf) { void GBLoadBIOS(struct GB* gb, struct VFile* vf) {

View File

@ -70,6 +70,7 @@ struct GB {
uint32_t sramSize; uint32_t sramSize;
int sramDirty; int sramDirty;
int32_t sramDirtAge; int32_t sramDirtAge;
bool sramMaskWriteback;
struct mAVStream* stream; struct mAVStream* stream;
@ -121,7 +122,7 @@ void GBLoadBIOS(struct GB* gb, struct VFile* vf);
void GBSramClean(struct GB* gb, uint32_t frameCount); void GBSramClean(struct GB* gb, uint32_t frameCount);
void GBResizeSram(struct GB* gb, size_t size); 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); void GBSavedataUnmask(struct GB* gb);
struct Patch; struct Patch;

View File

@ -211,7 +211,7 @@ static bool _GBACoreLoadSave(struct mCore* core, struct VFile* vf) {
static bool _GBACoreLoadTemporarySave(struct mCore* core, struct VFile* vf) { static bool _GBACoreLoadTemporarySave(struct mCore* core, struct VFile* vf) {
struct GBA* gba = core->board; struct GBA* gba = core->board;
GBASavedataMask(&gba->memory.savedata, vf); GBASavedataMask(&gba->memory.savedata, vf, false);
return true; // TODO: Return a real value return true; // TODO: Return a real value
} }
@ -507,14 +507,19 @@ static size_t _GBACoreSavedataClone(struct mCore* core, void** sram) {
return size; 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); struct VFile* vf = VFileFromConstMemory(sram, size);
if (!vf) { if (!vf) {
return false; return false;
} }
struct GBA* gba = core->board; struct GBA* gba = core->board;
bool success = GBASavedataLoad(&gba->memory.savedata, vf); bool success = true;
vf->close(vf); if (writeback) {
success = GBASavedataLoad(&gba->memory.savedata, vf);
vf->close(vf);
} else {
GBASavedataMask(&gba->memory.savedata, vf, true);
}
return success; return success;
} }
@ -582,6 +587,6 @@ struct mCore* GBACoreCreate(void) {
core->detachDebugger = _GBACoreDetachDebugger; core->detachDebugger = _GBACoreDetachDebugger;
core->cheatDevice = _GBACoreCheatDevice; core->cheatDevice = _GBACoreCheatDevice;
core->savedataClone = _GBACoreSavedataClone; core->savedataClone = _GBACoreSavedataClone;
core->savedataLoad = _GBACoreSavedataLoad; core->savedataRestore = _GBACoreSavedataRestore;
return core; return core;
} }

View File

@ -92,6 +92,7 @@ void GBAMemoryDeinit(struct GBA* gba) {
if (gba->memory.rom) { if (gba->memory.rom) {
mappedMemoryFree(gba->memory.rom, gba->memory.romSize); mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
} }
GBASavedataUnmask(&gba->memory.savedata);
GBASavedataDeinit(&gba->memory.savedata); GBASavedataDeinit(&gba->memory.savedata);
if (gba->memory.savedata.realVf) { if (gba->memory.savedata.realVf) {
gba->memory.savedata.realVf->close(gba->memory.savedata.realVf); gba->memory.savedata.realVf->close(gba->memory.savedata.realVf);

View File

@ -23,9 +23,9 @@ void GBARRInitRecord(struct GBA* gba) {
GBASavedataClone(&gba->memory.savedata, gba->rr->savedata); GBASavedataClone(&gba->memory.savedata, gba->rr->savedata);
gba->rr->savedata->close(gba->rr->savedata); gba->rr->savedata->close(gba->rr->savedata);
gba->rr->savedata = gba->rr->openSavedata(gba->rr, O_RDONLY); 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 { } else {
GBASavedataMask(&gba->memory.savedata, 0); GBASavedataMask(&gba->memory.savedata, 0, false);
} }
if (gba->rr->initFrom & INIT_FROM_SAVESTATE) { if (gba->rr->initFrom & INIT_FROM_SAVESTATE) {
@ -47,9 +47,9 @@ void GBARRInitPlay(struct GBA* gba) {
gba->rr->savedata->close(gba->rr->savedata); gba->rr->savedata->close(gba->rr->savedata);
} }
gba->rr->savedata = gba->rr->openSavedata(gba->rr, O_RDONLY); 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 { } else {
GBASavedataMask(&gba->memory.savedata, 0); GBASavedataMask(&gba->memory.savedata, 0, false);
} }
if (gba->rr->initFrom & INIT_FROM_SAVESTATE) { if (gba->rr->initFrom & INIT_FROM_SAVESTATE) {

View File

@ -47,10 +47,7 @@ void GBASavedataDeinit(struct GBASavedata* savedata) {
if (savedata->vf) { if (savedata->vf) {
size_t size = GBASavedataSize(savedata); size_t size = GBASavedataSize(savedata);
savedata->vf->unmap(savedata->vf, savedata->data, size); savedata->vf->unmap(savedata->vf, savedata->data, size);
if (savedata->vf != savedata->realVf) { savedata->vf = NULL;
savedata->vf->close(savedata->vf);
}
savedata->vf = 0;
} else { } else {
switch (savedata->type) { switch (savedata->type) {
case SAVEDATA_SRAM: case SAVEDATA_SRAM:
@ -74,23 +71,30 @@ void GBASavedataDeinit(struct GBASavedata* savedata) {
savedata->type = SAVEDATA_AUTODETECT; 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; enum SavedataType type = savedata->type;
GBASavedataDeinit(savedata); GBASavedataDeinit(savedata);
savedata->vf = vf; savedata->vf = vf;
savedata->mapMode = MAP_READ; savedata->mapMode = MAP_READ;
savedata->maskWriteback = writeback;
GBASavedataForceType(savedata, type, savedata->realisticTiming); GBASavedataForceType(savedata, type, savedata->realisticTiming);
} }
void GBASavedataUnmask(struct GBASavedata* savedata) { void GBASavedataUnmask(struct GBASavedata* savedata) {
if (savedata->mapMode != MAP_READ) { if (savedata->vf == savedata->realVf) {
return; return;
} }
enum SavedataType type = savedata->type; enum SavedataType type = savedata->type;
struct VFile* vf = savedata->vf;
GBASavedataDeinit(savedata); GBASavedataDeinit(savedata);
savedata->vf = savedata->realVf; savedata->vf = savedata->realVf;
savedata->mapMode = MAP_WRITE; savedata->mapMode = MAP_WRITE;
GBASavedataForceType(savedata, type, savedata->realisticTiming); 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) { bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
@ -488,6 +492,9 @@ void GBASavedataClean(struct GBASavedata* savedata, uint32_t frameCount) {
savedata->dirty |= SAVEDATA_DIRT_SEEN; savedata->dirty |= SAVEDATA_DIRT_SEEN;
} }
} else if ((savedata->dirty & SAVEDATA_DIRT_SEEN) && frameCount - savedata->dirtAge > CLEANUP_THRESHOLD) { } else if ((savedata->dirty & SAVEDATA_DIRT_SEEN) && frameCount - savedata->dirtAge > CLEANUP_THRESHOLD) {
if (savedata->maskWriteback) {
GBASavedataUnmask(savedata);
}
size_t size = GBASavedataSize(savedata); size_t size = GBASavedataSize(savedata);
savedata->dirty = 0; savedata->dirty = 0;
if (savedata->data && savedata->vf->sync(savedata->vf, savedata->data, size)) { if (savedata->data && savedata->vf->sync(savedata->vf, savedata->data, size)) {

View File

@ -74,6 +74,7 @@ struct GBASavedata {
struct VFile* vf; struct VFile* vf;
int mapMode; int mapMode;
bool maskWriteback;
struct VFile* realVf; struct VFile* realVf;
int32_t readBitsRemaining; int32_t readBitsRemaining;
@ -95,7 +96,7 @@ struct GBASavedata {
void GBASavedataInit(struct GBASavedata* savedata, struct VFile* vf); void GBASavedataInit(struct GBASavedata* savedata, struct VFile* vf);
void GBASavedataDeinit(struct GBASavedata* savedata); 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); void GBASavedataUnmask(struct GBASavedata* savedata);
size_t GBASavedataSize(struct GBASavedata* savedata); size_t GBASavedataSize(struct GBASavedata* savedata);
bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out); bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out);

View File

@ -470,7 +470,7 @@ static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer*
case SDLK_F8: case SDLK_F8:
case SDLK_F9: case SDLK_F9:
mCoreThreadInterrupt(context); 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); mCoreThreadContinue(context);
break; break;
default: default: