GB Serialize: Add MBC state serialization
Vicki Pfau vi@endrift.com
Sat, 08 Jul 2017 16:27:49 -0700
5 files changed,
64 insertions(+),
11 deletions(-)
M
include/mgba/internal/gb/mbc.h
→
include/mgba/internal/gb/mbc.h
@@ -18,6 +18,7 @@ struct GB;
struct GBMemory; void GBMBCInit(struct GB* gb); void GBMBCSwitchBank(struct GB* gb, int bank); +void GBMBCSwitchBank0(struct GB* gb, int bank); void GBMBCSwitchSramBank(struct GB* gb, int bank); struct GBMBCRTCSaveBuffer {
M
include/mgba/internal/gb/serialize.h
→
include/mgba/internal/gb/serialize.h
@@ -145,7 +145,7 @@ * | 0x0017A - 0x0017B: Next HDMA destination
* | 0x0017C - 0x0017D: HDMA remaining * | 0x0017E: DMA remaining * | 0x0017F - 0x00183: RTC registers - * | 0x00184 - 0x00193: MBC state (TODO) + * | 0x00184 - 0x00193: MBC state * | 0x00194 - 0x00195: Flags * | bit 0: SRAM accessable * | bit 1: RTC accessible@@ -331,18 +331,21 @@ uint8_t rtcRegs[5];
union { struct { - uint32_t mode; + uint8_t mode; + uint8_t multicartStride; } mbc1; struct { uint64_t lastLatch; } rtc; struct { - int8_t machineState; - GBMBC7Field field; - int8_t address; + uint8_t state; + GBMBC7Field eeprom; + uint8_t address; + uint8_t access; + uint8_t latch; uint8_t srBits; - uint32_t sr; - GBSerializedMBC7Flags flags; + uint16_t sr; + uint32_t writable; } mbc7; struct { uint8_t reserved[16];
M
src/gb/mbc.c
→
src/gb/mbc.c
@@ -50,7 +50,7 @@ gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
} } -static void _switchBank0(struct GB* gb, int bank) { +void GBMBCSwitchBank0(struct GB* gb, int bank) { size_t bankStart = bank * GB_SIZE_CART_BANK0 << gb->memory.mbcState.mbc1.multicartStride; if (bankStart + GB_SIZE_CART_BANK0 > gb->memory.romSize) { mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);@@ -320,7 +320,7 @@ break;
case 0x2: bank &= 3; if (memory->mbcState.mbc1.mode) { - _switchBank0(gb, bank); + GBMBCSwitchBank0(gb, bank); GBMBCSwitchSramBank(gb, bank); } GBMBCSwitchBank(gb, (bank << memory->mbcState.mbc1.multicartStride) | (memory->currentBank & (stride - 1)));@@ -328,9 +328,9 @@ break;
case 0x3: memory->mbcState.mbc1.mode = value & 1; if (memory->mbcState.mbc1.mode) { - _switchBank0(gb, memory->currentBank >> memory->mbcState.mbc1.multicartStride); + GBMBCSwitchBank0(gb, memory->currentBank >> memory->mbcState.mbc1.multicartStride); } else { - _switchBank0(gb, 0); + GBMBCSwitchBank0(gb, 0); GBMBCSwitchSramBank(gb, 0); } break;
M
src/gb/memory.c
→
src/gb/memory.c
@@ -629,6 +629,28 @@ flags = GBSerializedMemoryFlagsSetIme(flags, memory->ime);
flags = GBSerializedMemoryFlagsSetIsHdma(flags, memory->isHdma); flags = GBSerializedMemoryFlagsSetActiveRtcReg(flags, memory->activeRtcReg); STORE_16LE(flags, 0, &state->memory.flags); + + switch (memory->mbcType) { + case GB_MBC1: + state->memory.mbc1.mode = memory->mbcState.mbc1.mode; + state->memory.mbc1.multicartStride = memory->mbcState.mbc1.multicartStride; + break; + case GB_MBC3_RTC: + STORE_64LE(gb->memory.rtcLastLatch, 0, &state->memory.rtc.lastLatch); + break; + case GB_MBC7: + state->memory.mbc7.state = memory->mbcState.mbc7.state; + state->memory.mbc7.eeprom = memory->mbcState.mbc7.eeprom; + state->memory.mbc7.address = memory->mbcState.mbc7.address; + state->memory.mbc7.access = memory->mbcState.mbc7.access; + state->memory.mbc7.latch = memory->mbcState.mbc7.latch; + state->memory.mbc7.srBits = memory->mbcState.mbc7.srBits; + STORE_16LE(memory->mbcState.mbc7.sr, 0, &state->memory.mbc7.sr); + STORE_32LE(memory->mbcState.mbc7.writable, 0, &state->memory.mbc7.writable); + break; + default: + break; + } } void GBMemoryDeserialize(struct GB* gb, const struct GBSerializedState* state) {@@ -671,6 +693,32 @@ memory->rtcLatched = GBSerializedMemoryFlagsGetRtcLatched(flags);
memory->ime = GBSerializedMemoryFlagsGetIme(flags); memory->isHdma = GBSerializedMemoryFlagsGetIsHdma(flags); memory->activeRtcReg = GBSerializedMemoryFlagsGetActiveRtcReg(flags); + + switch (memory->mbcType) { + case GB_MBC1: + memory->mbcState.mbc1.mode = state->memory.mbc1.mode; + memory->mbcState.mbc1.multicartStride = state->memory.mbc1.multicartStride; + if (memory->mbcState.mbc1.mode) { + GBMBCSwitchBank0(gb, memory->currentBank >> memory->mbcState.mbc1.multicartStride); + } + break; + case GB_MBC3_RTC: + // TODO? + //LOAD_64LE(gb->memory.rtcLastLatch, 0, &state->memory.rtc.lastLatch); + break; + case GB_MBC7: + memory->mbcState.mbc7.state = state->memory.mbc7.state; + memory->mbcState.mbc7.eeprom = state->memory.mbc7.eeprom; + memory->mbcState.mbc7.address = state->memory.mbc7.address & 0x7F; + memory->mbcState.mbc7.access = state->memory.mbc7.access; + memory->mbcState.mbc7.latch = state->memory.mbc7.latch; + memory->mbcState.mbc7.srBits = state->memory.mbc7.srBits; + LOAD_16LE(memory->mbcState.mbc7.sr, 0, &state->memory.mbc7.sr); + LOAD_32LE(memory->mbcState.mbc7.writable, 0, &state->memory.mbc7.writable); + break; + default: + break; + } } void _pristineCow(struct GB* gb) {