mirror of https://github.com/mgba-emu/mgba.git
GBA Savedata: Support for 64 kiB SRAM saves
This commit is contained in:
parent
02a15a72c0
commit
3e1793d3f8
1
CHANGES
1
CHANGES
|
@ -5,6 +5,7 @@ Features:
|
||||||
- Tool for converting scanned pictures of e-Reader cards to raw dotcode data
|
- Tool for converting scanned pictures of e-Reader cards to raw dotcode data
|
||||||
- Cheat code support in homebrew ports
|
- Cheat code support in homebrew ports
|
||||||
- Support for combo "Super Game Boy Color" SGB + GBC ROM hacks
|
- Support for combo "Super Game Boy Color" SGB + GBC ROM hacks
|
||||||
|
- Support for 64 kiB SRAM saves used in some bootlegs
|
||||||
Emulation fixes:
|
Emulation fixes:
|
||||||
- GB Video: Clear VRAM on reset (fixes mgba.io/i/2152)
|
- GB Video: Clear VRAM on reset (fixes mgba.io/i/2152)
|
||||||
- GBA SIO: Add missing NORMAL8 implementation bits (fixes mgba.io/i/2172)
|
- GBA SIO: Add missing NORMAL8 implementation bits (fixes mgba.io/i/2172)
|
||||||
|
|
|
@ -68,6 +68,7 @@ enum {
|
||||||
SIZE_CART1 = 0x02000000,
|
SIZE_CART1 = 0x02000000,
|
||||||
SIZE_CART2 = 0x02000000,
|
SIZE_CART2 = 0x02000000,
|
||||||
SIZE_CART_SRAM = 0x00008000,
|
SIZE_CART_SRAM = 0x00008000,
|
||||||
|
SIZE_CART_SRAM512 = 0x00010000,
|
||||||
SIZE_CART_FLASH512 = 0x00010000,
|
SIZE_CART_FLASH512 = 0x00010000,
|
||||||
SIZE_CART_FLASH1M = 0x00020000,
|
SIZE_CART_FLASH1M = 0x00020000,
|
||||||
SIZE_CART_EEPROM = 0x00002000,
|
SIZE_CART_EEPROM = 0x00002000,
|
||||||
|
|
|
@ -24,7 +24,8 @@ enum SavedataType {
|
||||||
SAVEDATA_FLASH512 = 2,
|
SAVEDATA_FLASH512 = 2,
|
||||||
SAVEDATA_FLASH1M = 3,
|
SAVEDATA_FLASH1M = 3,
|
||||||
SAVEDATA_EEPROM = 4,
|
SAVEDATA_EEPROM = 4,
|
||||||
SAVEDATA_EEPROM512 = 5
|
SAVEDATA_EEPROM512 = 5,
|
||||||
|
SAVEDATA_SRAM512 = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SavedataCommand {
|
enum SavedataCommand {
|
||||||
|
@ -110,6 +111,7 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type);
|
||||||
void GBASavedataInitFlash(struct GBASavedata* savedata);
|
void GBASavedataInitFlash(struct GBASavedata* savedata);
|
||||||
void GBASavedataInitEEPROM(struct GBASavedata* savedata);
|
void GBASavedataInitEEPROM(struct GBASavedata* savedata);
|
||||||
void GBASavedataInitSRAM(struct GBASavedata* savedata);
|
void GBASavedataInitSRAM(struct GBASavedata* savedata);
|
||||||
|
void GBASavedataInitSRAM512(struct GBASavedata* savedata);
|
||||||
|
|
||||||
uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address);
|
uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address);
|
||||||
void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8_t value);
|
void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8_t value);
|
||||||
|
|
|
@ -717,6 +717,8 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
value = GBASavedataReadFlash(&memory->savedata, address);
|
value = GBASavedataReadFlash(&memory->savedata, address);
|
||||||
} else if (memory->hw.devices & HW_TILT) {
|
} else if (memory->hw.devices & HW_TILT) {
|
||||||
value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK);
|
value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK);
|
||||||
|
} else if (memory->savedata.type == SAVEDATA_SRAM512) {
|
||||||
|
value = memory->savedata.data[address & (SIZE_CART_SRAM512 - 1)];
|
||||||
} else {
|
} else {
|
||||||
mLOG(GBA_MEM, GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
|
mLOG(GBA_MEM, GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
|
||||||
value = 0xFF;
|
value = 0xFF;
|
||||||
|
@ -1070,6 +1072,9 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
|
||||||
memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
|
memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
|
||||||
} else if (memory->hw.devices & HW_TILT) {
|
} else if (memory->hw.devices & HW_TILT) {
|
||||||
GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
|
GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
|
||||||
|
} else if (memory->savedata.type == SAVEDATA_SRAM512) {
|
||||||
|
memory->savedata.data[address & (SIZE_CART_SRAM512 - 1)] = value;
|
||||||
|
memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
|
||||||
} else {
|
} else {
|
||||||
mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
|
mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,9 @@ bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOver
|
||||||
if (strcasecmp(savetype, "SRAM") == 0) {
|
if (strcasecmp(savetype, "SRAM") == 0) {
|
||||||
found = true;
|
found = true;
|
||||||
override->savetype = SAVEDATA_SRAM;
|
override->savetype = SAVEDATA_SRAM;
|
||||||
|
} else if (strcasecmp(savetype, "SRAM512") == 0) {
|
||||||
|
found = true;
|
||||||
|
override->savetype = SAVEDATA_SRAM512;
|
||||||
} else if (strcasecmp(savetype, "EEPROM") == 0) {
|
} else if (strcasecmp(savetype, "EEPROM") == 0) {
|
||||||
found = true;
|
found = true;
|
||||||
override->savetype = SAVEDATA_EEPROM;
|
override->savetype = SAVEDATA_EEPROM;
|
||||||
|
@ -288,6 +291,9 @@ void GBAOverrideSave(struct Configuration* config, const struct GBACartridgeOver
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
savetype = "SRAM";
|
savetype = "SRAM";
|
||||||
break;
|
break;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
savetype = "SRAM512";
|
||||||
|
break;
|
||||||
case SAVEDATA_EEPROM:
|
case SAVEDATA_EEPROM:
|
||||||
savetype = "EEPROM";
|
savetype = "EEPROM";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -68,6 +68,9 @@ void GBASavedataDeinit(struct GBASavedata* savedata) {
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
|
mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
|
||||||
break;
|
break;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
mappedMemoryFree(savedata->data, SIZE_CART_SRAM512);
|
||||||
|
break;
|
||||||
case SAVEDATA_FLASH512:
|
case SAVEDATA_FLASH512:
|
||||||
mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
|
mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
|
||||||
break;
|
break;
|
||||||
|
@ -124,6 +127,8 @@ bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
|
||||||
switch (savedata->type) {
|
switch (savedata->type) {
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
return out->write(out, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
|
return out->write(out, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
return out->write(out, savedata->data, SIZE_CART_SRAM512) == SIZE_CART_SRAM512;
|
||||||
case SAVEDATA_FLASH512:
|
case SAVEDATA_FLASH512:
|
||||||
return out->write(out, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
|
return out->write(out, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
|
||||||
case SAVEDATA_FLASH1M:
|
case SAVEDATA_FLASH1M:
|
||||||
|
@ -153,6 +158,8 @@ size_t GBASavedataSize(const struct GBASavedata* savedata) {
|
||||||
switch (savedata->type) {
|
switch (savedata->type) {
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
return SIZE_CART_SRAM;
|
return SIZE_CART_SRAM;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
return SIZE_CART_SRAM512;
|
||||||
case SAVEDATA_FLASH512:
|
case SAVEDATA_FLASH512:
|
||||||
return SIZE_CART_FLASH512;
|
return SIZE_CART_FLASH512;
|
||||||
case SAVEDATA_FLASH1M:
|
case SAVEDATA_FLASH1M:
|
||||||
|
@ -233,6 +240,9 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type)
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
GBASavedataInitSRAM(savedata);
|
GBASavedataInitSRAM(savedata);
|
||||||
break;
|
break;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
GBASavedataInitSRAM512(savedata);
|
||||||
|
break;
|
||||||
case SAVEDATA_FORCE_NONE:
|
case SAVEDATA_FORCE_NONE:
|
||||||
savedata->type = SAVEDATA_FORCE_NONE;
|
savedata->type = SAVEDATA_FORCE_NONE;
|
||||||
break;
|
break;
|
||||||
|
@ -322,6 +332,30 @@ void GBASavedataInitSRAM(struct GBASavedata* savedata) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GBASavedataInitSRAM512(struct GBASavedata* savedata) {
|
||||||
|
if (savedata->type == SAVEDATA_AUTODETECT) {
|
||||||
|
savedata->type = SAVEDATA_SRAM512;
|
||||||
|
} else {
|
||||||
|
mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
off_t end;
|
||||||
|
if (!savedata->vf) {
|
||||||
|
end = 0;
|
||||||
|
savedata->data = anonymousMemoryMap(SIZE_CART_SRAM512);
|
||||||
|
} else {
|
||||||
|
end = savedata->vf->size(savedata->vf);
|
||||||
|
if (end < SIZE_CART_SRAM512) {
|
||||||
|
savedata->vf->truncate(savedata->vf, SIZE_CART_SRAM512);
|
||||||
|
}
|
||||||
|
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_SRAM512, savedata->mapMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end < SIZE_CART_SRAM512) {
|
||||||
|
memset(&savedata->data[end], 0xFF, SIZE_CART_SRAM512 - end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) {
|
uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) {
|
||||||
if (savedata->command == FLASH_COMMAND_ID) {
|
if (savedata->command == FLASH_COMMAND_ID) {
|
||||||
if (savedata->type == SAVEDATA_FLASH512) {
|
if (savedata->type == SAVEDATA_FLASH512) {
|
||||||
|
|
|
@ -151,6 +151,11 @@
|
||||||
<string>EEPROM 512 bytes</string>
|
<string>EEPROM 512 bytes</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>SRAM 64kB (bootlegs only)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
|
|
Loading…
Reference in New Issue