Core: Move savestate creation time to extdata

This commit is contained in:
Vicki Pfau 2017-06-08 23:33:23 -07:00
parent 49ccb3d080
commit 87791b9db9
13 changed files with 50 additions and 55 deletions

View File

@ -126,6 +126,7 @@ Misc:
- Qt: Relax hard dependency on OpenGL
- GB Video: Improved video timings
- Core: List memory segments in the core
- Core: Move savestate creation time to extdata
0.5.2: (2016-12-31)
Bugfixes:

View File

@ -16,6 +16,7 @@ enum mStateExtdataTag {
EXTDATA_SAVEDATA = 2,
EXTDATA_CHEATS = 3,
EXTDATA_RTC = 4,
EXTDATA_META_TIME = 0x101,
EXTDATA_MAX
};
@ -23,6 +24,7 @@ enum mStateExtdataTag {
#define SAVESTATE_SAVEDATA 2
#define SAVESTATE_CHEATS 4
#define SAVESTATE_RTC 8
#define SAVESTATE_METADATA 16
struct mStateExtdataItem {
int32_t size;

View File

@ -154,8 +154,7 @@ mLOG_DECLARE_CATEGORY(GB_STATE);
* | 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 @@ struct GBSerializedState {
uint16_t reserved;
} memory;
uint64_t creationUsec;
uint32_t reserved[48];
uint32_t reserved[50];
uint8_t oam[GB_SIZE_OAM];

View File

@ -190,8 +190,7 @@ mLOG_DECLARE_CATEGORY(GBA_STATE);
* | 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 @@ struct GBASerializedState {
uint32_t cpuPrefetch[2];
uint32_t associatedStreamId;
uint32_t reservedRr[3];
uint64_t creationUsec;
uint32_t reservedRr[5];
uint32_t lastPrefetchedPc;
GBASerializedMiscFlags miscFlags;

View File

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

View File

@ -431,7 +431,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 | 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);

View File

@ -118,5 +118,5 @@ static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
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);
}

View File

@ -59,25 +59,6 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* 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) {

View File

@ -119,5 +119,5 @@ static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
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);
}

View File

@ -69,25 +69,6 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* 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);

View File

@ -40,7 +40,7 @@ using namespace std;
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

View File

@ -188,7 +188,7 @@ void LoadSaveState::loadState(int slot) {
return;
}
QDateTime creation/*(QDateTime::fromMSecsSinceEpoch(state->creationUsec / 1000LL))*/; // TODO
QDateTime creation;
QImage stateImage;
unsigned width, height;
@ -198,6 +198,12 @@ void LoadSaveState::loadState(int slot) {
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()) {
QPixmap statePixmap;
statePixmap.convertFromImage(stateImage);

View File

@ -232,7 +232,7 @@ void SettingsView::updateConfig() {
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 @@ void SettingsView::reloadConfig() {
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);