all repos — mgba @ 4c439e3819c6c749a2a9a3592ce8ee4dc529be32

mGBA Game Boy Advance Emulator

GB Serialize: Add MBC state serialization
Vicki Pfau vi@endrift.com
Sat, 08 Jul 2017 16:27:49 -0700
commit

4c439e3819c6c749a2a9a3592ce8ee4dc529be32

parent

5ce943c5801e1621be8754183d4b34dd12899fc7

M CHANGESCHANGES

@@ -177,6 +177,7 @@ - GBA Timer: Improve accuracy of timers

- Qt: Minor test fixes - PSP2: Update toolchain to use vita.cmake - Qt: Move shader settings into main settings window + - GB Serialize: Add MBC state serialization 0.6 beta 1: (2017-06-29) - Initial beta for 0.6
M include/mgba/internal/gb/mbc.hinclude/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.hinclude/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.csrc/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.csrc/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) {