diff --git a/src/gba/gba-memory.h b/src/gba/gba-memory.h index b28973134..8f773cb5a 100644 --- a/src/gba/gba-memory.h +++ b/src/gba/gba-memory.h @@ -114,6 +114,7 @@ struct GBAMemory { struct GBASavedata savedata; size_t romSize; + uint16_t romID; int fullBios; char waitstates32[256]; diff --git a/src/gba/gba-savedata.c b/src/gba/gba-savedata.c index c5b3c1009..a1586f156 100644 --- a/src/gba/gba-savedata.c +++ b/src/gba/gba-savedata.c @@ -21,6 +21,14 @@ void GBASavedataInit(struct GBASavedata* savedata, const char* filename) { savedata->filename = filename; } +void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type) { + if (savedata->type != SAVEDATA_NONE) { + GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata"); + return; + } + savedata->type = type; +} + void GBASavedataDeinit(struct GBASavedata* savedata) { switch (savedata->type) { case SAVEDATA_SRAM: @@ -43,7 +51,13 @@ void GBASavedataDeinit(struct GBASavedata* savedata) { } void GBASavedataInitFlash(struct GBASavedata* savedata) { - savedata->type = SAVEDATA_FLASH512; + if (savedata->type == SAVEDATA_NONE) { + savedata->type = SAVEDATA_FLASH512; + } + if (savedata->type != SAVEDATA_FLASH512 && savedata->type != SAVEDATA_FLASH1M) { + GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata"); + return; + } savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666); off_t end; int flags = MAP_SHARED; @@ -66,7 +80,12 @@ void GBASavedataInitFlash(struct GBASavedata* savedata) { } void GBASavedataInitEEPROM(struct GBASavedata* savedata) { - savedata->type = SAVEDATA_EEPROM; + if (savedata->type == SAVEDATA_NONE) { + savedata->type = SAVEDATA_EEPROM; + } else { + GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata"); + return; + } savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666); off_t end; int flags = MAP_SHARED; @@ -87,7 +106,12 @@ void GBASavedataInitEEPROM(struct GBASavedata* savedata) { } void GBASavedataInitSRAM(struct GBASavedata* savedata) { - savedata->type = SAVEDATA_SRAM; + if (savedata->type == SAVEDATA_NONE) { + savedata->type = SAVEDATA_SRAM; + } else { + GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata"); + return; + } savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666); off_t end; int flags = MAP_SHARED; diff --git a/src/gba/gba-savedata.h b/src/gba/gba-savedata.h index 068a61629..c09d623a4 100644 --- a/src/gba/gba-savedata.h +++ b/src/gba/gba-savedata.h @@ -68,9 +68,16 @@ struct GBASavedata { enum FlashStateMachine flashState; }; +struct SavedataOverride { + uint32_t id; + enum SavedataType type; +}; + void GBASavedataInit(struct GBASavedata* savedata, const char* filename); void GBASavedataDeinit(struct GBASavedata* savedata); +void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type); + void GBASavedataInitFlash(struct GBASavedata* savedata); void GBASavedataInitEEPROM(struct GBASavedata* savedata); void GBASavedataInitSRAM(struct GBASavedata* savedata); diff --git a/src/gba/gba.c b/src/gba/gba.c index 73c3796dc..2cd36ebf7 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -22,10 +22,17 @@ enum { SP_BASE_SUPERVISOR = 0x03FFFFE0 }; +static const struct SavedataOverride _savedataOverrides[] = { + { 'EEPB', SAVEDATA_FLASH1M }, + { 0, 0 } +}; + static void GBAProcessEvents(struct ARMBoard* board); static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles); static void GBAHitStub(struct ARMBoard* board, uint32_t opcode); +static void _checkOverrides(struct GBA* gba, uint32_t code); + void GBAInit(struct GBA* gba) { gba->errno = GBA_NO_ERROR; gba->errstr = 0; @@ -270,6 +277,7 @@ void GBALoadROM(struct GBA* gba, int fd, const char* fname) { gba->activeFile = fname; fstat(fd, &info); gba->memory.romSize = info.st_size; + _checkOverrides(gba, ((struct GBACartridge*) gba->memory.rom)->id); // TODO: error check } @@ -432,3 +440,27 @@ void GBAHitStub(struct ARMBoard* board, uint32_t opcode) { ARMDebuggerEnter(gbaBoard->p->debugger); } } + +void _checkOverrides(struct GBA* gba, uint32_t id) { + int i; + for (i = 0; _savedataOverrides[i].id; ++i) { + if (_savedataOverrides[i].id == id) { + gba->memory.savedata.type = _savedataOverrides[i].type; + switch (_savedataOverrides[i].type) { + case SAVEDATA_FLASH512: + case SAVEDATA_FLASH1M: + GBASavedataInitFlash(&gba->memory.savedata); + break; + case SAVEDATA_EEPROM: + GBASavedataInitEEPROM(&gba->memory.savedata); + break; + case SAVEDATA_SRAM: + GBASavedataInitSRAM(&gba->memory.savedata); + break; + case SAVEDATA_NONE: + break; + } + return; + } + } +} diff --git a/src/gba/gba.h b/src/gba/gba.h index 6484218ea..601d16050 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -93,6 +93,21 @@ struct GBA { int logLevel; }; +struct GBACartridge { + uint32_t entry; + uint8_t logo[156]; + char title[12]; + uint32_t id; + uint16_t maker; + uint8_t type; + uint8_t unit; + uint8_t device; + uint8_t reserved[7]; + uint8_t version; + uint8_t checksum; + // And ROM data... +}; + void GBAInit(struct GBA* gba); void GBADeinit(struct GBA* gba);