mirror of https://github.com/mgba-emu/mgba.git
Core: Move savestate creation time to extdata
This commit is contained in:
parent
49ccb3d080
commit
87791b9db9
1
CHANGES
1
CHANGES
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 @@ 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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue