diff --git a/src/gba/gba-memory.c b/src/gba/gba-memory.c index dce3214be..fdb04b58e 100644 --- a/src/gba/gba-memory.c +++ b/src/gba/gba-memory.c @@ -196,8 +196,13 @@ uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address) { case BASE_CART1: case BASE_CART1_EX: case BASE_CART2: - case BASE_CART2_EX: return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; + case BASE_CART2_EX: + if ((address & (SIZE_CART0 - 1)) < gbaMemory->romSize) { + return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1]; + } else { + return GBASavedataReadEEPROM(&gbaMemory->savedata); + } case BASE_CART_SRAM: break; default: @@ -309,8 +314,6 @@ void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value) { break; case BASE_CART0: break; - case BASE_CART2_EX: - break; case BASE_CART_SRAM: break; default: @@ -345,6 +348,10 @@ void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value) { case BASE_CART0: break; case BASE_CART2_EX: + if (gbaMemory->savedata.type == SAVEDATA_NONE) { + GBASavedataInitEEPROM(&gbaMemory->savedata); + } + GBASavedataWriteEEPROM(&gbaMemory->savedata, value); break; case BASE_CART_SRAM: break; @@ -373,8 +380,6 @@ void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value) { break; case BASE_CART0: break; - case BASE_CART2_EX: - break; case BASE_CART_SRAM: if (gbaMemory->savedata.type == SAVEDATA_NONE) { if (address == SAVEDATA_FLASH_BASE) { diff --git a/src/gba/gba-memory.h b/src/gba/gba-memory.h index 72d0653f5..a3d3d508d 100644 --- a/src/gba/gba-memory.h +++ b/src/gba/gba-memory.h @@ -5,6 +5,8 @@ #include "gba-savedata.h" +#include + enum GBAMemoryRegion { REGION_BIOS = 0x0, REGION_WORKING_RAM = 0x2, @@ -111,6 +113,7 @@ struct GBAMemory { uint16_t io[SIZE_IO >> 1]; struct GBASavedata savedata; + size_t romSize; char waitstates32[256]; char waitstates16[256]; diff --git a/src/gba/gba-savedata.c b/src/gba/gba-savedata.c index e669b499a..43e2a13a4 100644 --- a/src/gba/gba-savedata.c +++ b/src/gba/gba-savedata.c @@ -43,7 +43,7 @@ void GBASavedataInitFlash(struct GBASavedata* savedata) { return; } // mmap enough so that we can expand the file if we need to - savedata->data = mmap(0, SIZE_CART_FLASH1M, PROT_READ | PROT_WRITE, 0, savedata->fd, 0); + savedata->data = mmap(0, SIZE_CART_FLASH1M, PROT_READ | PROT_WRITE, MAP_SHARED, savedata->fd, 0); off_t end = lseek(savedata->fd, 0, SEEK_END); if (end < SIZE_CART_FLASH512) { @@ -52,6 +52,22 @@ void GBASavedataInitFlash(struct GBASavedata* savedata) { } } +void GBASavedataInitEEPROM(struct GBASavedata* savedata) { + savedata->type = SAVEDATA_EEPROM; + savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666); + if (savedata->fd < 0) { + GBALog(GBA_LOG_WARN, "Cannot open savedata file %s", savedata->filename); + return; + } + savedata->data = mmap(0, SIZE_CART_EEPROM, PROT_READ | PROT_WRITE, MAP_SHARED, savedata->fd, 0); + + off_t end = lseek(savedata->fd, 0, SEEK_END); + if (end < SIZE_CART_EEPROM) { + ftruncate(savedata->fd, SIZE_CART_EEPROM); + memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end); + } +} + void GBASavedataInitSRAM(struct GBASavedata* savedata) { savedata->type = SAVEDATA_SRAM; savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666); @@ -73,8 +89,21 @@ void GBASavedataInitSRAM(struct GBASavedata* savedata) { } } + void GBASavedataWriteFlash(struct GBASavedata* savedata, uint8_t value) { (void)(savedata); (void)(value); GBALog(GBA_LOG_STUB, "Flash memory unimplemented"); } + +void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value) { + (void)(savedata); + (void)(value); + GBALog(GBA_LOG_STUB, "EEPROM unimplemented"); +} + +uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) { + (void)(savedata); + GBALog(GBA_LOG_STUB, "EEPROM unimplemented"); + return 0; +} diff --git a/src/gba/gba-savedata.h b/src/gba/gba-savedata.h index 106144fb7..9cca4f58f 100644 --- a/src/gba/gba-savedata.h +++ b/src/gba/gba-savedata.h @@ -26,8 +26,12 @@ void GBASavedataInit(struct GBASavedata* savedata, const char* filename); void GBASavedataDeinit(struct GBASavedata* savedata); void GBASavedataInitFlash(struct GBASavedata* savedata); +void GBASavedataInitEEPROM(struct GBASavedata* savedata); void GBASavedataInitSRAM(struct GBASavedata* savedata); void GBASavedataWriteFlash(struct GBASavedata* savedata, uint8_t value); +uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata); +void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value); + #endif diff --git a/src/gba/gba.c b/src/gba/gba.c index 3cd5b706d..110d753cd 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -11,6 +11,7 @@ #include #include #include +#include enum { SP_BASE_SYSTEM = 0x03FFFF00, @@ -228,7 +229,10 @@ void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger) { } void GBALoadROM(struct GBA* gba, int fd) { + struct stat info; gba->memory.rom = mmap(0, SIZE_CART0, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + fstat(fd, &info); + gba->memory.romSize = info.st_size; // TODO: error check }