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

View File

@ -407,10 +407,10 @@ bool mCoreLoadStateNamed(struct mCore* core, struct VFile* vf, int flags) {
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;

View File

@ -424,7 +424,7 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
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);

View File

@ -177,7 +177,7 @@ static bool _GBCoreLoadSave(struct mCore* core, struct VFile* vf) {
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 @@ static size_t _GBCoreSavedataClone(struct mCore* core, void** sram) {
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 @@ struct mCore* GBCoreCreate(void) {
core->detachDebugger = _GBCoreDetachDebugger;
core->cheatDevice = _GBCoreCheatDevice;
core->savedataClone = _GBCoreSavedataClone;
core->savedataLoad = _GBCoreSavedataLoad;
core->savedataRestore = _GBCoreSavedataRestore;
return core;
}

View File

@ -118,8 +118,7 @@ static void GBSramDeinit(struct GB* gb) {
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 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);
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 @@ void GBUnloadROM(struct GB* gb) {
gb->romVf = 0;
}
struct VFile* vf = gb->sramVf;
GBSramDeinit(gb);
if (vf) {
vf->close(vf);
}
}
void GBLoadBIOS(struct GB* gb, struct VFile* vf) {

View File

@ -70,6 +70,7 @@ struct GB {
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;

View File

@ -211,7 +211,7 @@ static bool _GBACoreLoadSave(struct mCore* core, struct VFile* vf) {
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 @@ static size_t _GBACoreSavedataClone(struct mCore* core, void** sram) {
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 @@ struct mCore* GBACoreCreate(void) {
core->detachDebugger = _GBACoreDetachDebugger;
core->cheatDevice = _GBACoreCheatDevice;
core->savedataClone = _GBACoreSavedataClone;
core->savedataLoad = _GBACoreSavedataLoad;
core->savedataRestore = _GBACoreSavedataRestore;
return core;
}

View File

@ -92,6 +92,7 @@ void GBAMemoryDeinit(struct GBA* gba) {
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);

View File

@ -23,9 +23,9 @@ void GBARRInitRecord(struct GBA* gba) {
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 @@ void GBARRInitPlay(struct GBA* gba) {
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) {

View File

@ -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 @@ void GBASavedataDeinit(struct GBASavedata* savedata) {
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 @@ void GBASavedataClean(struct GBASavedata* savedata, uint32_t frameCount) {
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)) {

View File

@ -74,6 +74,7 @@ struct GBASavedata {
struct VFile* vf;
int mapMode;
bool maskWriteback;
struct VFile* realVf;
int32_t readBitsRemaining;
@ -95,7 +96,7 @@ struct GBASavedata {
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);

View File

@ -470,7 +470,7 @@ static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer*
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: