GBA: Fix SharkPort saves for EEPROM games
Vicki Pfau vi@endrift.com
Mon, 05 Feb 2018 22:06:44 -0800
4 files changed,
34 insertions(+),
27 deletions(-)
M
CHANGES
→
CHANGES
@@ -50,6 +50,7 @@ - GBA: Fix some GBA ROM misdetection (fixes mgba.io/i/978)
- GBA Hardware: RTC accuracy improvements - GB Timer: Minor accuracy improvements - GB Audio: Clock frame events on DIV + - GBA: Fix SharkPort saves for EEPROM games Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
M
include/mgba/internal/gba/savedata.h
→
include/mgba/internal/gba/savedata.h
@@ -102,7 +102,7 @@ void GBASavedataDeinit(struct GBASavedata* savedata);
void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback); void GBASavedataUnmask(struct GBASavedata* savedata); -size_t GBASavedataSize(struct GBASavedata* savedata); +size_t GBASavedataSize(const struct GBASavedata* savedata); bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out); bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in); void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming);
M
src/gba/savedata.c
→
src/gba/savedata.c
@@ -138,7 +138,7 @@ }
return true; } -size_t GBASavedataSize(struct GBASavedata* savedata) { +size_t GBASavedataSize(const struct GBASavedata* savedata) { switch (savedata->type) { case SAVEDATA_SRAM: return SIZE_CART_SRAM;
M
src/gba/sharkport.c
→
src/gba/sharkport.c
@@ -130,8 +130,21 @@ case SAVEDATA_AUTODETECT:
goto cleanup; } - memcpy(gba->memory.savedata.data, &payload[0x1C], copySize); - gba->memory.savedata.vf && gba->memory.savedata.vf->sync(gba->memory.savedata.vf, gba->memory.savedata.data, size); + if (gba->memory.savedata.type == SAVEDATA_EEPROM) { + size_t i; + for (i = 0; i < copySize; i += 8) { + uint32_t lo, hi; + LOAD_32BE(lo, i + 0x1C, payload); + LOAD_32BE(hi, i + 0x20, payload); + STORE_32LE(hi, i, gba->memory.savedata.data); + STORE_32LE(lo, i + 4, gba->memory.savedata.data); + } + } else { + memcpy(gba->memory.savedata.data, &payload[0x1C], copySize); + } + if (gba->memory.savedata.vf) { + gba->memory.savedata.vf->sync(gba->memory.savedata.vf, gba->memory.savedata.data, size); + } free(payload); return true;@@ -146,7 +159,7 @@ union {
char c[0x1C]; int32_t i; } buffer; - int32_t size = strlen(SHARKPORT_HEADER); + uint32_t size = strlen(SHARKPORT_HEADER); STORE_32(size, 0, &buffer.i); if (vf->write(vf, &buffer.i, 4) < 4) { return false;@@ -187,22 +200,8 @@ return false;
} // Write payload - size = 0x1C; - switch (gba->memory.savedata.type) { - case SAVEDATA_SRAM: - size += SIZE_CART_SRAM; - break; - case SAVEDATA_FLASH512: - size += SIZE_CART_FLASH512; - break; - case SAVEDATA_FLASH1M: - size += SIZE_CART_FLASH1M; - break; - case SAVEDATA_EEPROM: - size += SIZE_CART_EEPROM; - break; - case SAVEDATA_FORCE_NONE: - case SAVEDATA_AUTODETECT: + size = 0x1C + GBASavedataSize(&gba->memory.savedata); + if (size == 0x1C) { return false; } STORE_32(size, 0, &buffer.i);@@ -229,17 +228,24 @@ return false;
} uint32_t checksum = 0; - int i; + size_t i; for (i = 0; i < 0x1C; ++i) { checksum += buffer.c[i] << (checksum % 24); } - if (vf->write(vf, gba->memory.savedata.data, size) < size) { + + if (gba->memory.savedata.type == SAVEDATA_EEPROM) { + for (i = 0; i < size; ++i) { + char byte = gba->memory.savedata.data[i ^ 7]; + checksum += byte << (checksum % 24); + vf->write(vf, &byte, 1); + } + } else if (vf->write(vf, gba->memory.savedata.data, size) < size) { return false; - } - - for (i = 0; i < size; ++i) { - checksum += ((char) gba->memory.savedata.data[i]) << (checksum % 24); + } else { + for (i = 0; i < size; ++i) { + checksum += ((char) gba->memory.savedata.data[i]) << (checksum % 24); + } } STORE_32(checksum, 0, &buffer.i);