GBA Savedata: Add realistic timing for EEPROM

This commit is contained in:
Jeffrey Pfau 2016-08-14 20:56:42 -07:00
parent ac11542226
commit b1618cbed3
4 changed files with 21 additions and 6 deletions

View File

@ -54,6 +54,7 @@ Misc:
- GBA Video: Optimize sprite drawing - GBA Video: Optimize sprite drawing
- GBA BIOS: Use custom ArcTan, not relying on OS - GBA BIOS: Use custom ArcTan, not relying on OS
- PSP2: Sync files per descriptor - PSP2: Sync files per descriptor
- GBA Savedata: Add realistic timing for EEPROM
0.4.1: (2016-07-11) 0.4.1: (2016-07-11)
Bugfixes: Bugfixes:

View File

@ -811,7 +811,7 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
case REGION_CART2_EX: case REGION_CART2_EX:
if (memory->savedata.type == SAVEDATA_AUTODETECT) { if (memory->savedata.type == SAVEDATA_AUTODETECT) {
mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
GBASavedataInitEEPROM(&memory->savedata); GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming);
} }
GBASavedataWriteEEPROM(&memory->savedata, value, 1); GBASavedataWriteEEPROM(&memory->savedata, value, 1);
break; break;
@ -1690,7 +1690,7 @@ void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
} else if (destRegion == REGION_CART2_EX) { } else if (destRegion == REGION_CART2_EX) {
if (memory->savedata.type == SAVEDATA_AUTODETECT) { if (memory->savedata.type == SAVEDATA_AUTODETECT) {
mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
GBASavedataInitEEPROM(&memory->savedata); GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming);
} }
word = cpu->memory.load16(cpu, source, 0); word = cpu->memory.load16(cpu, source, 0);
gba->bus = word | (word << 16); gba->bus = word | (word << 16);

View File

@ -20,6 +20,8 @@
// Other games vary from very little, with a fairly solid 20500 cycle count. (Observed on a SST (D4BF) 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. // An average estimation is as follows.
#define FLASH_SETTLE_CYCLES 18000 #define FLASH_SETTLE_CYCLES 18000
// This needs real testing, and is only an estimation currently
#define EEPROM_SETTLE_CYCLES 14500
#define CLEANUP_THRESHOLD 15 #define CLEANUP_THRESHOLD 15
mLOG_DEFINE_CATEGORY(GBA_SAVE, "GBA Savedata"); mLOG_DEFINE_CATEGORY(GBA_SAVE, "GBA Savedata");
@ -201,7 +203,7 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type,
GBASavedataInitFlash(savedata, realisticTiming); GBASavedataInitFlash(savedata, realisticTiming);
break; break;
case SAVEDATA_EEPROM: case SAVEDATA_EEPROM:
GBASavedataInitEEPROM(savedata); GBASavedataInitEEPROM(savedata, realisticTiming);
break; break;
case SAVEDATA_SRAM: case SAVEDATA_SRAM:
GBASavedataInitSRAM(savedata); GBASavedataInitSRAM(savedata);
@ -247,7 +249,7 @@ void GBASavedataInitFlash(struct GBASavedata* savedata, bool realisticTiming) {
} }
} }
void GBASavedataInitEEPROM(struct GBASavedata* savedata) { void GBASavedataInitEEPROM(struct GBASavedata* savedata, bool realisticTiming) {
if (savedata->type == SAVEDATA_AUTODETECT) { if (savedata->type == SAVEDATA_AUTODETECT) {
savedata->type = SAVEDATA_EEPROM; savedata->type = SAVEDATA_EEPROM;
} else { } else {
@ -265,6 +267,8 @@ void GBASavedataInitEEPROM(struct GBASavedata* savedata) {
} }
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode); savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
} }
savedata->dust = 0;
savedata->realisticTiming = realisticTiming;
if (end < SIZE_CART_EEPROM) { if (end < SIZE_CART_EEPROM) {
memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end); memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end);
} }
@ -430,6 +434,9 @@ void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32
current |= (value & 0x1) << (0x7 - (savedata->writeAddress & 0x7)); current |= (value & 0x1) << (0x7 - (savedata->writeAddress & 0x7));
savedata->dirty |= SAVEDATA_DIRT_NEW; savedata->dirty |= SAVEDATA_DIRT_NEW;
savedata->data[savedata->writeAddress >> 3] = current; savedata->data[savedata->writeAddress >> 3] = current;
if (savedata->realisticTiming) {
savedata->dust = EEPROM_SETTLE_CYCLES;
}
++savedata->writeAddress; ++savedata->writeAddress;
} else { } else {
mLOG(GBA_SAVE, GAME_ERROR, "Writing beyond end of EEPROM: %08X", (savedata->writeAddress >> 3)); mLOG(GBA_SAVE, GAME_ERROR, "Writing beyond end of EEPROM: %08X", (savedata->writeAddress >> 3));
@ -452,7 +459,14 @@ void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32
uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) { uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) {
if (savedata->command != EEPROM_COMMAND_READ) { if (savedata->command != EEPROM_COMMAND_READ) {
if (!savedata->realisticTiming || savedata->dust <= 0) {
return 1; return 1;
} else {
// Give some overhead for waitstates and the comparison
// This estimation can probably be improved
savedata->dust -= 10;
return 0;
}
} }
--savedata->readBitsRemaining; --savedata->readBitsRemaining;
if (savedata->readBitsRemaining < 64) { if (savedata->readBitsRemaining < 64) {

View File

@ -103,7 +103,7 @@ bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in);
void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming); void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming);
void GBASavedataInitFlash(struct GBASavedata* savedata, 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); void GBASavedataInitSRAM(struct GBASavedata* savedata);
uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address); uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address);