all repos — mgba @ b1618cbed35ebdd82b5dc311e0f92537db9951ab

mGBA Game Boy Advance Emulator

GBA Savedata: Add realistic timing for EEPROM
Jeffrey Pfau jeffrey@endrift.com
Sun, 14 Aug 2016 20:56:42 -0700
commit

b1618cbed35ebdd82b5dc311e0f92537db9951ab

parent

ac115422264c242439c19aaf383b6b743a309c69

4 files changed, 21 insertions(+), 6 deletions(-)

jump to
M CHANGESCHANGES

@@ -54,6 +54,7 @@ - GBA Video: Remove old slow path fallback

- GBA Video: Optimize sprite drawing - GBA BIOS: Use custom ArcTan, not relying on OS - PSP2: Sync files per descriptor + - GBA Savedata: Add realistic timing for EEPROM 0.4.1: (2016-07-11) Bugfixes:
M src/gba/memory.csrc/gba/memory.c

@@ -811,7 +811,7 @@ break;

case REGION_CART2_EX: if (memory->savedata.type == SAVEDATA_AUTODETECT) { mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); - GBASavedataInitEEPROM(&memory->savedata); + GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming); } GBASavedataWriteEEPROM(&memory->savedata, value, 1); break;

@@ -1690,7 +1690,7 @@ --wordsRemaining;

} else if (destRegion == REGION_CART2_EX) { if (memory->savedata.type == SAVEDATA_AUTODETECT) { mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); - GBASavedataInitEEPROM(&memory->savedata); + GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming); } word = cpu->memory.load16(cpu, source, 0); gba->bus = word | (word << 16);
M src/gba/savedata.csrc/gba/savedata.c

@@ -20,6 +20,8 @@ // Some games may vary anywhere between about 2000 cycles to up to 30000 cycles. (Observed on a Macronix (09C2) chip).

// Other games vary from very little, with a fairly solid 20500 cycle count. (Observed on a SST (D4BF) chip). // An average estimation is as follows. #define FLASH_SETTLE_CYCLES 18000 +// This needs real testing, and is only an estimation currently +#define EEPROM_SETTLE_CYCLES 14500 #define CLEANUP_THRESHOLD 15 mLOG_DEFINE_CATEGORY(GBA_SAVE, "GBA Savedata");

@@ -201,7 +203,7 @@ savedata->type = type;

GBASavedataInitFlash(savedata, realisticTiming); break; case SAVEDATA_EEPROM: - GBASavedataInitEEPROM(savedata); + GBASavedataInitEEPROM(savedata, realisticTiming); break; case SAVEDATA_SRAM: GBASavedataInitSRAM(savedata);

@@ -247,7 +249,7 @@ memset(&savedata->data[end], 0xFF, flashSize - end);

} } -void GBASavedataInitEEPROM(struct GBASavedata* savedata) { +void GBASavedataInitEEPROM(struct GBASavedata* savedata, bool realisticTiming) { if (savedata->type == SAVEDATA_AUTODETECT) { savedata->type = SAVEDATA_EEPROM; } else {

@@ -265,6 +267,8 @@ savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);

} savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode); } + savedata->dust = 0; + savedata->realisticTiming = realisticTiming; if (end < SIZE_CART_EEPROM) { memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end); }

@@ -430,6 +434,9 @@ current &= ~(1 << (0x7 - (savedata->writeAddress & 0x7)));

current |= (value & 0x1) << (0x7 - (savedata->writeAddress & 0x7)); savedata->dirty |= SAVEDATA_DIRT_NEW; savedata->data[savedata->writeAddress >> 3] = current; + if (savedata->realisticTiming) { + savedata->dust = EEPROM_SETTLE_CYCLES; + } ++savedata->writeAddress; } else { mLOG(GBA_SAVE, GAME_ERROR, "Writing beyond end of EEPROM: %08X", (savedata->writeAddress >> 3));

@@ -452,7 +459,14 @@ }

uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) { if (savedata->command != EEPROM_COMMAND_READ) { - return 1; + if (!savedata->realisticTiming || savedata->dust <= 0) { + return 1; + } else { + // Give some overhead for waitstates and the comparison + // This estimation can probably be improved + savedata->dust -= 10; + return 0; + } } --savedata->readBitsRemaining; if (savedata->readBitsRemaining < 64) {
M src/gba/savedata.hsrc/gba/savedata.h

@@ -103,7 +103,7 @@ bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in);

void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming); void GBASavedataInitFlash(struct GBASavedata* savedata, bool realisticTiming); -void GBASavedataInitEEPROM(struct GBASavedata* savedata); +void GBASavedataInitEEPROM(struct GBASavedata* savedata, bool realisticTiming); void GBASavedataInitSRAM(struct GBASavedata* savedata); uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address);