Permalink
Browse files

GBA Savedata: Fix 512 byte EEPROM saving as 8kB (fixes #877)

  • Loading branch information...
endrift committed Sep 17, 2017
1 parent 7fc91b1 commit d582cf7d36a2f1f99b45ba6bc919ea431e08342b
Showing with 29 additions and 16 deletions.
  1. +1 −0 CHANGES
  2. +2 −1 include/mgba/internal/gba/memory.h
  3. +24 −6 src/gba/savedata.c
  4. +2 −9 src/platform/libretro/libretro.c
View
@@ -37,6 +37,7 @@ Bugfixes:
- GB, GBA: Fix sync to video with frameskip
- GB Audio: Fix NRx2 writes while active (fixes mgba.io/i/866)
- GBA BIOS: Use core's VRAM variable instead of renderer's
+ - GBA Savedata: Fix 512 byte EEPROM saving as 8kB (fixes mgba.io/i/877)
Misc:
- GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
@@ -67,7 +67,8 @@ enum {
SIZE_CART_SRAM = 0x00010000,
SIZE_CART_FLASH512 = 0x00010000,
SIZE_CART_FLASH1M = 0x00020000,
- SIZE_CART_EEPROM = 0x00002000
+ SIZE_CART_EEPROM = 0x00002000,
+ SIZE_CART_EEPROM512 = 0x00000200
};
enum {
View
@@ -147,7 +147,7 @@ size_t GBASavedataSize(struct GBASavedata* savedata) {
case SAVEDATA_FLASH1M:
return SIZE_CART_FLASH1M;
case SAVEDATA_EEPROM:
- return SIZE_CART_EEPROM;
+ return (savedata->vf && savedata->vf->size(savedata->vf) == SIZE_CART_EEPROM512) ? SIZE_CART_EEPROM512 : SIZE_CART_EEPROM;
case SAVEDATA_FORCE_NONE:
return 0;
case SAVEDATA_AUTODETECT:
@@ -257,20 +257,23 @@ void GBASavedataInitEEPROM(struct GBASavedata* savedata, bool realisticTiming) {
mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
return;
}
+ int32_t eepromSize = SIZE_CART_EEPROM512;
off_t end;
if (!savedata->vf) {
end = 0;
savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
} else {
end = savedata->vf->size(savedata->vf);
- if (end < SIZE_CART_EEPROM) {
- savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);
+ if (end < SIZE_CART_EEPROM512) {
+ savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM512);
+ } else if (end > SIZE_CART_EEPROM512) {
+ eepromSize = SIZE_CART_EEPROM;
}
- savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
+ savedata->data = savedata->vf->map(savedata->vf, eepromSize, savedata->mapMode);
}
savedata->realisticTiming = realisticTiming;
- if (end < SIZE_CART_EEPROM) {
- memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end);
+ if (end < SIZE_CART_EEPROM512) {
+ memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM512 - end);
}
}
@@ -405,6 +408,19 @@ void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8
}
}
+static void _ensureEeprom(struct GBASavedata* savedata, uint32_t size) {
+ if (size < SIZE_CART_EEPROM512) {
+ return;
+ }
+ if (!savedata->vf || savedata->vf->size(savedata->vf) > SIZE_CART_EEPROM512) {
+ return;
+ }
+ savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_EEPROM512);
+ savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);
+ savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
+ memset(&savedata->data[SIZE_CART_EEPROM512], 0xFF, SIZE_CART_EEPROM - SIZE_CART_EEPROM512);
+}
+
void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32_t writeSize) {
switch (savedata->command) {
// Read header
@@ -430,6 +446,7 @@ void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32
} else if (writeSize == 1) {
savedata->command = EEPROM_COMMAND_NULL;
} else if ((savedata->writeAddress >> 3) < SIZE_CART_EEPROM) {
+ _ensureEeprom(savedata, savedata->writeAddress >> 3);
uint8_t current = savedata->data[savedata->writeAddress >> 3];
current &= ~(1 << (0x7 - (savedata->writeAddress & 0x7)));
current |= (value & 0x1) << (0x7 - (savedata->writeAddress & 0x7));
@@ -471,6 +488,7 @@ uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) {
if (savedata->readBitsRemaining < 64) {
int step = 63 - savedata->readBitsRemaining;
uint32_t address = (savedata->readAddress + step) >> 3;
+ _ensureEeprom(savedata, address);
if (address >= SIZE_CART_EEPROM) {
mLOG(GBA_SAVE, GAME_ERROR, "Reading beyond end of EEPROM: %08X", address);
return 0xFF;
@@ -528,16 +528,9 @@ size_t retro_get_memory_size(unsigned id) {
if (core->platform(core) == PLATFORM_GBA) {
switch (((struct GBA*) core->board)->memory.savedata.type) {
case SAVEDATA_AUTODETECT:
- case SAVEDATA_FLASH1M:
return SIZE_CART_FLASH1M;
- case SAVEDATA_FLASH512:
- return SIZE_CART_FLASH512;
- case SAVEDATA_EEPROM:
- return SIZE_CART_EEPROM;
- case SAVEDATA_SRAM:
- return SIZE_CART_SRAM;
- case SAVEDATA_FORCE_NONE:
- return 0;
+ default:
+ return GBASavedataSize(&((struct GBA*) core->board)->memory.savedata);
}
}
#endif

0 comments on commit d582cf7

Please sign in to comment.