From e93240f90c75a5f174efaf1647a18a8102ce95e5 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 28 Mar 2015 03:25:46 -0700 Subject: [PATCH] GBA: Add somewhat more realistic flash timings, disabled currently --- src/gba/gba.c | 3 +++ src/gba/gba.h | 2 ++ src/gba/memory.c | 2 +- src/gba/savedata.c | 25 +++++++++++++++++++++---- src/gba/savedata.h | 8 ++++++-- src/gba/serialize.h | 9 +++++---- src/gba/supervisor/overrides.c | 2 +- 7 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/gba/gba.c b/src/gba/gba.c index 2402fcc77..e2aabd148 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -89,6 +89,9 @@ static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component) { gba->lastJump = 0; gba->idleDetectionStep = 0; gba->idleDetectionFailures = 0; + + gba->realisticTiming = false; + gba->performingDMA = false; } diff --git a/src/gba/gba.h b/src/gba/gba.h index 3594b4ab8..1694919e4 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -161,6 +161,8 @@ struct GBA { int idleDetectionFailures; int32_t cachedRegisters[16]; bool taintedRegisters[16]; + + bool realisticTiming; }; struct GBACartridge { diff --git a/src/gba/memory.c b/src/gba/memory.c index 85b2809af..0923edd1e 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -778,7 +778,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo if (memory->savedata.type == SAVEDATA_AUTODETECT) { if (address == SAVEDATA_FLASH_BASE) { GBALog(gba, GBA_LOG_INFO, "Detected Flash savegame"); - GBASavedataInitFlash(&memory->savedata); + GBASavedataInitFlash(&memory->savedata, gba->realisticTiming); } else { GBALog(gba, GBA_LOG_INFO, "Detected SRAM savegame"); GBASavedataInitSRAM(&memory->savedata); diff --git a/src/gba/savedata.c b/src/gba/savedata.c index bc9a34851..0d1c82475 100644 --- a/src/gba/savedata.c +++ b/src/gba/savedata.c @@ -14,6 +14,8 @@ #include #include +#define FLASH_SETTLE_CYCLES 18000 + static void _flashSwitchBank(struct GBASavedata* savedata, int bank); static void _flashErase(struct GBASavedata* savedata); static void _flashEraseSector(struct GBASavedata* savedata, uint16_t sectorStart); @@ -113,7 +115,7 @@ bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) { return true; } -void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type) { +void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming) { if (savedata->type != SAVEDATA_AUTODETECT) { struct VFile* vf = savedata->vf; GBASavedataDeinit(savedata); @@ -123,7 +125,7 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type) case SAVEDATA_FLASH512: case SAVEDATA_FLASH1M: savedata->type = type; - GBASavedataInitFlash(savedata); + GBASavedataInitFlash(savedata, realisticTiming); break; case SAVEDATA_EEPROM: GBASavedataInitEEPROM(savedata); @@ -139,7 +141,7 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type) } } -void GBASavedataInitFlash(struct GBASavedata* savedata) { +void GBASavedataInitFlash(struct GBASavedata* savedata, bool realisticTiming) { if (savedata->type == SAVEDATA_AUTODETECT) { savedata->type = SAVEDATA_FLASH512; } @@ -162,6 +164,8 @@ void GBASavedataInitFlash(struct GBASavedata* savedata) { } savedata->currentBank = savedata->data; + savedata->dust = 0; + savedata->realisticTiming = realisticTiming; if (end < SIZE_CART_FLASH512) { memset(&savedata->data[end], 0xFF, flashSize - end); } @@ -226,6 +230,10 @@ uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) { } } } + if (savedata->dust > 0 && (address >> 12) == savedata->settling) { + --savedata->dust; + return 0x5F; + } return savedata->currentBank[address]; } @@ -384,6 +392,8 @@ void GBASavedataSerialize(const struct GBASavedata* savedata, struct GBASerializ state->savedata.readBitsRemaining = savedata->readBitsRemaining; state->savedata.readAddress = savedata->readAddress; state->savedata.writeAddress = savedata->writeAddress; + state->savedata.settlingSector = savedata->settling; + state->savedata.settlingDust = savedata->dust; UNUSED(includeData); // TODO } @@ -393,13 +403,16 @@ void GBASavedataDeserialize(struct GBASavedata* savedata, const struct GBASerial return; } if (savedata->type != state->savedata.type) { - GBASavedataForceType(savedata, state->savedata.type); + GBASavedataForceType(savedata, state->savedata.type, savedata->realisticTiming); } savedata->command = state->savedata.command; savedata->flashState = state->savedata.flashState; savedata->readBitsRemaining = state->savedata.readBitsRemaining; savedata->readAddress = state->savedata.readAddress; savedata->writeAddress = state->savedata.writeAddress; + savedata->settling = state->savedata.settlingSector; + savedata->dust = state->savedata.settlingDust; + if (savedata->type == SAVEDATA_FLASH1M) { _flashSwitchBank(savedata, state->savedata.flashBank); } @@ -434,5 +447,9 @@ void _flashEraseSector(struct GBASavedata* savedata, uint16_t sectorStart) { if (savedata->type == SAVEDATA_FLASH1M) { GBALog(0, GBA_LOG_DEBUG, "Performing unknown sector-size erase at 0x%04x", sectorStart); } + savedata->settling = sectorStart >> 12; + if (savedata->realisticTiming) { + savedata->dust = FLASH_SETTLE_CYCLES; + } memset(&savedata->currentBank[sectorStart & ~(size - 1)], 0xFF, size); } diff --git a/src/gba/savedata.h b/src/gba/savedata.h index d1614283a..a3030eb03 100644 --- a/src/gba/savedata.h +++ b/src/gba/savedata.h @@ -73,6 +73,10 @@ struct GBASavedata { uint8_t* currentBank; + bool realisticTiming; + unsigned settling; + int dust; + enum FlashStateMachine flashState; }; @@ -82,9 +86,9 @@ void GBASavedataDeinit(struct GBASavedata* savedata); void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf); void GBASavedataUnmask(struct GBASavedata* savedata); bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out); -void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type); +void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming); -void GBASavedataInitFlash(struct GBASavedata* savedata); +void GBASavedataInitFlash(struct GBASavedata* savedata, bool realisticTiming); void GBASavedataInitEEPROM(struct GBASavedata* savedata); void GBASavedataInitSRAM(struct GBASavedata* savedata); diff --git a/src/gba/serialize.h b/src/gba/serialize.h index 5a2d9a34b..3bb416655 100644 --- a/src/gba/serialize.h +++ b/src/gba/serialize.h @@ -162,8 +162,9 @@ extern const uint32_t GBA_SAVESTATE_MAGIC; * | 0x002E3 - 0x002E3: Reserved * | 0x002E4 - 0x002E7: EEPROM read bits remaining * | 0x002E8 - 0x002EB: EEPROM read address - * | 0x002EC - 0x002EBF EEPROM write address - * 0x002F0 - 0x002F3: Reserved (leave zero) + * | 0x002EC - 0x002EF: EEPROM write address + * | 0x002F0 - 0x002F1: Flash settling sector + * | 0x002F2 - 0x002F3: Flash settling remaining * 0x002F4 - 0x002FF: Prefetch * | 0x002F4 - 0x002F7: GBA BIOS bus prefetch * | 0x002F8 - 0x002FB: CPU prefecth (decode slot) @@ -297,10 +298,10 @@ struct GBASerializedState { int32_t readBitsRemaining; uint32_t readAddress; uint32_t writeAddress; + uint16_t settlingSector; + uint16_t settlingDust; } savedata; - uint32_t reservedPadding; - uint32_t biosPrefetch; uint32_t cpuPrefetch[2]; diff --git a/src/gba/supervisor/overrides.c b/src/gba/supervisor/overrides.c index 2c5759040..9a0ff9bea 100644 --- a/src/gba/supervisor/overrides.c +++ b/src/gba/supervisor/overrides.c @@ -249,7 +249,7 @@ void GBAOverrideSave(struct Configuration* config, const struct GBACartridgeOver void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* override) { if (override->savetype != SAVEDATA_AUTODETECT) { - GBASavedataForceType(&gba->memory.savedata, override->savetype); + GBASavedataForceType(&gba->memory.savedata, override->savetype, gba->realisticTiming); } if (override->hardware != HW_NO_OVERRIDE) {