all repos — mgba @ c1d02a1369df031fc877b1800ae5f9f08df5df7b

mGBA Game Boy Advance Emulator

GBA: Savestates now take into account savedata state machines (fixes #109)
Jeffrey Pfau jeffrey@endrift.com
Sat, 21 Mar 2015 01:12:39 -0700
commit

c1d02a1369df031fc877b1800ae5f9f08df5df7b

parent

d36c0ec7df619a26c9229a3c99c836ca6c9783f2

5 files changed, 79 insertions(+), 12 deletions(-)

jump to
M CHANGESCHANGES

@@ -75,6 +75,7 @@ - Qt: Move frame upload back onto main thread

- All: Enable link-time optimization - GBA Thread: Make GBASyncWaitFrameStart time out - GBA: Move A/V stream interface into core + - GBA: Savestates now take into account savedata state machines (fixes #109) 0.1.1: (2015-01-24) Bugfixes:
M src/gba/savedata.csrc/gba/savedata.c

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "savedata.h" #include "gba/gba.h" +#include "gba/serialize.h" #include "util/memory.h" #include "util/vfs.h"

@@ -373,6 +374,37 @@ }

return data & 0x1; } return 0; +} + +void GBASavedataSerialize(const struct GBASavedata* savedata, struct GBASerializedState* state, bool includeData) { + state->savedata.type = savedata->type; + state->savedata.command = savedata->command; + state->savedata.flashState = savedata->flashState; + state->savedata.flashBank = savedata->currentBank == &savedata->data[0x10000]; + state->savedata.readBitsRemaining = savedata->readBitsRemaining; + state->savedata.readAddress = savedata->readAddress; + state->savedata.writeAddress = savedata->writeAddress; + + UNUSED(includeData); // TODO +} + +void GBASavedataDeserialize(struct GBASavedata* savedata, const struct GBASerializedState* state, bool includeData) { + if (state->savedata.type == SAVEDATA_FORCE_NONE) { + return; + } + if (savedata->type != state->savedata.type) { + GBASavedataForceType(savedata, state->savedata.type); + } + savedata->command = state->savedata.command; + savedata->flashState = state->savedata.flashState; + savedata->readBitsRemaining = state->savedata.readBitsRemaining; + savedata->readAddress = state->savedata.readAddress; + savedata->writeAddress = state->savedata.writeAddress; + if (savedata->type == SAVEDATA_FLASH1M) { + _flashSwitchBank(savedata, state->savedata.flashBank); + } + + UNUSED(includeData); // TODO } void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
M src/gba/savedata.hsrc/gba/savedata.h

@@ -13,10 +13,10 @@

enum SavedataType { SAVEDATA_AUTODETECT = -1, SAVEDATA_FORCE_NONE = 0, - SAVEDATA_SRAM, - SAVEDATA_FLASH512, - SAVEDATA_FLASH1M, - SAVEDATA_EEPROM + SAVEDATA_SRAM = 1, + SAVEDATA_FLASH512 = 2, + SAVEDATA_FLASH1M = 3, + SAVEDATA_EEPROM = 4 }; enum SavedataCommand {

@@ -42,8 +42,8 @@ };

enum FlashStateMachine { FLASH_STATE_RAW = 0, - FLASH_STATE_START, - FLASH_STATE_CONTINUE + FLASH_STATE_START = 1, + FLASH_STATE_CONTINUE = 2, }; enum FlashManufacturer {

@@ -67,9 +67,9 @@

int mapMode; struct VFile* realVf; - int readBitsRemaining; - int readAddress; - int writeAddress; + int32_t readBitsRemaining; + uint32_t readAddress; + uint32_t writeAddress; uint8_t* currentBank;

@@ -93,5 +93,9 @@ void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8_t value);

uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata); void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32_t writeSize); + +struct GBASerializedState; +void GBASavedataSerialize(const struct GBASavedata* savedata, struct GBASerializedState* state, bool includeData); +void GBASavedataDeserialize(struct GBASavedata* savedata, const struct GBASerializedState* state, bool includeData); #endif
M src/gba/serialize.csrc/gba/serialize.c

@@ -48,6 +48,7 @@ GBAMemorySerialize(&gba->memory, state);

GBAIOSerialize(gba, state); GBAVideoSerialize(&gba->video, state); GBAAudioSerialize(&gba->audio, state); + GBASavedataSerialize(&gba->memory.savedata, state, false); state->associatedStreamId = 0; if (gba->rr) {

@@ -111,6 +112,7 @@ GBAMemoryDeserialize(&gba->memory, state);

GBAIODeserialize(gba, state); GBAVideoDeserialize(&gba->video, state); GBAAudioDeserialize(&gba->audio, state); + GBASavedataDeserialize(&gba->memory.savedata, state, false); if (gba->rr) { gba->rr->stateLoaded(gba->rr, state);
M src/gba/serialize.hsrc/gba/serialize.h

@@ -129,7 +129,7 @@ * | 0x0028C - 0x0028F: DMA next event

* 0x00290 - 0x002C3: GPIO state * | 0x00290 - 0x00291: Pin state * | 0x00292 - 0x00293: Direction state - * | 0x00294 - 0x002B6: RTC state (see gba-hardware.h for format) + * | 0x00294 - 0x002B6: RTC state (see hardware.h for format) * | 0x002B7 - 0x002B7: GPIO devices * | bit 0: Has RTC values * | bit 1: Has rumble value (reserved)

@@ -150,7 +150,20 @@ * | 0x002C0 - 0x002C0: Light sample

* | 0x002C1 - 0x002C3: Flags * | bits 0 - 1: Tilt state machine * | bits 2 - 31: Reserved - * 0x002C4 - 0x002F3: Reserved (leave zero) + * 0x002C4 - 0x002DF: Reserved (leave zero) + * 0x002E0 - 0x002EF: Savedata state + * | 0x002E0 - 0x002E0: Savedata type + * | 0x002E1 - 0x002E1: Savedata command (see savedata.h) + * | 0x002E2 - 0x002E2: Flags + * | bits 0 - 1: Flash state machine + * | bits 2 - 3: Reserved + * | bit 4: Flash bank + * | bits 5 - 7: Reserved + * | 0x002E3 - 0x002E3: Reserved + * | 0x002E4 - 0x002E7: EEPROM read bits remaining + * | 0x002E8 - 0x002EB: EEPROM read address + * | 0x002EC - 0x002EBF EEPROM write address + * 0x002F0 - 0x002F3: Reserved (leave zero) * 0x002F4 - 0x002FF: Prefetch * | 0x002F4 - 0x002F7: GBA BIOS bus prefetch * | 0x002F8 - 0x002FB: CPU prefecth (decode slot)

@@ -271,7 +284,22 @@ unsigned tiltState : 2;

unsigned : 22; } hw; - uint32_t reservedHardware[12]; + uint32_t reservedHardware[7]; + + struct { + unsigned type : 8; + unsigned command : 8; + unsigned flashState : 2; + unsigned : 2; + unsigned flashBank : 1; + unsigned : 3; + unsigned : 8; + int32_t readBitsRemaining; + uint32_t readAddress; + uint32_t writeAddress; + } savedata; + + uint32_t reservedPadding; uint32_t biosPrefetch; uint32_t cpuPrefetch[2];