Core: Move savestate creation time to extdata
jump to
@@ -16,6 +16,7 @@ EXTDATA_SCREENSHOT = 1,
EXTDATA_SAVEDATA = 2, EXTDATA_CHEATS = 3, EXTDATA_RTC = 4, + EXTDATA_META_TIME = 0x101, EXTDATA_MAX };@@ -23,6 +24,7 @@ #define SAVESTATE_SCREENSHOT 1
#define SAVESTATE_SAVEDATA 2 #define SAVESTATE_CHEATS 4 #define SAVESTATE_RTC 8 +#define SAVESTATE_METADATA 16 struct mStateExtdataItem { int32_t size;
@@ -154,8 +154,7 @@ * | bit 3: IME
* | bit 4: Is HDMA active? * | bits 5 - 7: Active RTC register * | 0x00196 - 0x00197: Reserved (leave zero) - * 0x00198 - 0x0019F: Savestate creation time (usec since 1970) - * 0x001A0 - 0x0025F: Reserved (leave zero) + * 0x00198 - 0x0025F: Reserved (leave zero) * 0x00260 - 0x002FF: OAM * 0x00300 - 0x0037F: I/O memory * 0x00380 - 0x003FE: HRAM@@ -354,9 +353,7 @@ GBSerializedMemoryFlags flags;
uint16_t reserved; } memory; - uint64_t creationUsec; - - uint32_t reserved[48]; + uint32_t reserved[50]; uint8_t oam[GB_SIZE_OAM];
@@ -190,8 +190,7 @@ * | 0x002F4 - 0x002F7: GBA BIOS bus prefetch
* | 0x002F8 - 0x002FB: CPU prefecth (decode slot) * | 0x002FC - 0x002FF: CPU prefetch (fetch slot) * 0x00300 - 0x00303: Associated movie stream ID for record/replay (or 0 if no stream) - * 0x00304 - 0x0030F: Reserved (leave zero) - * 0x00310 - 0x00317: Savestate creation time (usec since 1970) + * 0x00304 - 0x00317: Savestate creation time (usec since 1970) * 0x00318 - 0x0031B: Last prefetched program counter * 0x0031C - 0x0031F: Miscellaneous flags * | bit 0: Is CPU halted?@@ -312,9 +311,7 @@ uint32_t biosPrefetch;
uint32_t cpuPrefetch[2]; uint32_t associatedStreamId; - uint32_t reservedRr[3]; - - uint64_t creationUsec; + uint32_t reservedRr[5]; uint32_t lastPrefetchedPc; GBASerializedMiscFlags miscFlags;
@@ -303,6 +303,36 @@ bool mCoreSaveStateNamed(struct mCore* core, struct VFile* vf, int flags) {
struct mStateExtdata extdata; mStateExtdataInit(&extdata); size_t stateSize = core->stateSize(core); + + if (flags & SAVESTATE_METADATA) { + uint64_t creationUsec; +#ifndef _MSC_VER + struct timeval tv; + if (!gettimeofday(&tv, 0)) { + uint64_t usec = tv.tv_usec; + usec += tv.tv_sec * 1000000LL; + STORE_64LE(usec, 0, &creationUsec); + } +#else + struct timespec ts; + if (timespec_get(&ts, TIME_UTC)) { + uint64_t usec = ts.tv_nsec / 1000; + usec += ts.tv_sec * 1000000LL; + STORE_64LE(usec, 0, &creationUsec); + } +#endif + else { + creationUsec = 0; + } + + struct mStateExtdataItem item = { + .size = sizeof(creationUsec), + .data = &creationUsec, + .clean = NULL + }; + mStateExtdataPut(&extdata, EXTDATA_META_TIME, &item); + } + if (flags & SAVESTATE_SAVEDATA) { void* sram = NULL; size_t size = core->savedataClone(core, &sram);
@@ -431,7 +431,7 @@ case RUNNER_RESET:
runner->core->reset(runner->core); break; case RUNNER_SAVE_STATE: - mCoreSaveState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA); + mCoreSaveState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_METADATA); break; case RUNNER_LOAD_STATE: mCoreLoadState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_RTC);
@@ -118,5 +118,5 @@ }
struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system; - mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC); + mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA); }
@@ -59,25 +59,6 @@ GBIOSerialize(gb, state);
GBVideoSerialize(&gb->video, state); GBTimerSerialize(&gb->timer, state); GBAudioSerialize(&gb->audio, state); - -#ifndef _MSC_VER - struct timeval tv; - if (!gettimeofday(&tv, 0)) { - uint64_t usec = tv.tv_usec; - usec += tv.tv_sec * 1000000LL; - STORE_64LE(usec, 0, &state->creationUsec); - } -#else - struct timespec ts; - if (timespec_get(&ts, TIME_UTC)) { - uint64_t usec = ts.tv_nsec / 1000; - usec += ts.tv_sec * 1000000LL; - STORE_64LE(usec, 0, &state->creationUsec); - } -#endif - else { - state->creationUsec = 0; - } } bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
@@ -119,5 +119,5 @@ }
struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system; - mCoreSaveState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC); + mCoreSaveState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA); }
@@ -69,25 +69,6 @@ GBAVideoSerialize(&gba->video, state);
GBAAudioSerialize(&gba->audio, state); GBASavedataSerialize(&gba->memory.savedata, state); - -#ifndef _MSC_VER - struct timeval tv; - if (!gettimeofday(&tv, 0)) { - uint64_t usec = tv.tv_usec; - usec += tv.tv_sec * 1000000LL; - STORE_64(usec, 0, &state->creationUsec); - } -#else - struct timespec ts; - if (timespec_get(&ts, TIME_UTC)) { - uint64_t usec = ts.tv_nsec / 1000; - usec += ts.tv_sec * 1000000LL; - STORE_64(usec, 0, &state->creationUsec); - } -#endif - else { - state->creationUsec = 0; - } state->associatedStreamId = 0; if (gba->rr) { gba->rr->stateSaved(gba->rr, state);
@@ -40,7 +40,7 @@
GameController::GameController(QObject* parent) : QObject(parent) , m_audioProcessor(AudioProcessor::create()) - , m_saveStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS | SAVESTATE_RTC) + , m_saveStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS | SAVESTATE_RTC | SAVESTATE_METADATA) , m_loadStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_RTC) { #ifdef M_CORE_GBA
@@ -188,7 +188,7 @@ mStateExtdataDeinit(&extdata);
return; } - QDateTime creation/*(QDateTime::fromMSecsSinceEpoch(state->creationUsec / 1000LL))*/; // TODO + QDateTime creation; QImage stateImage; unsigned width, height;@@ -196,6 +196,12 @@ thread->core->desiredVideoDimensions(thread->core, &width, &height);
mStateExtdataItem item; if (mStateExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item) && item.size >= width * height * 4) { stateImage = QImage((uchar*) item.data, width, height, QImage::Format_ARGB32).rgbSwapped(); + } + + if (mStateExtdataGet(&extdata, EXTDATA_META_TIME, &item) && item.size == sizeof(uint64_t)) { + uint64_t creationUsec; + LOAD_64LE(creationUsec, 0, item.data); + creation = QDateTime::fromMSecsSinceEpoch(creationUsec / 1000LL); } if (!stateImage.isNull()) {
@@ -232,7 +232,7 @@ loadState |= m_ui.loadStateSave->isChecked() ? SAVESTATE_SAVEDATA : 0;
loadState |= m_ui.loadStateCheats->isChecked() ? SAVESTATE_CHEATS : 0; saveSetting("loadStateExtdata", loadState); - int saveState = SAVESTATE_RTC; + int saveState = SAVESTATE_RTC | SAVESTATE_METADATA; saveState |= m_ui.saveStateScreenshot->isChecked() ? SAVESTATE_SCREENSHOT : 0; saveState |= m_ui.saveStateSave->isChecked() ? SAVESTATE_SAVEDATA : 0; saveState |= m_ui.saveStateCheats->isChecked() ? SAVESTATE_CHEATS : 0;@@ -319,7 +319,7 @@ m_ui.loadStateCheats->setChecked(loadState & SAVESTATE_CHEATS);
int saveState = loadSetting("saveStateExtdata").toInt(&ok); if (!ok) { - saveState = SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS | SAVESTATE_RTC; + saveState = SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS | SAVESTATE_RTC | SAVESTATE_METADATA; } m_ui.saveStateScreenshot->setChecked(saveState & SAVESTATE_SCREENSHOT); m_ui.saveStateSave->setChecked(saveState & SAVESTATE_SAVEDATA);