GB MBC: Fix MBC1 mode changing behavior

This commit is contained in:
Vicki Pfau 2020-06-16 20:00:44 -07:00
parent a1c61edf5c
commit 96f1838faa
7 changed files with 38 additions and 20 deletions

View File

@ -5,6 +5,7 @@ Features:
Emulation fixes: Emulation fixes:
- ARM: Fix ALU reading PC after shifting - ARM: Fix ALU reading PC after shifting
- ARM: Fix STR storing PC after address calculation - ARM: Fix STR storing PC after address calculation
- GB MBC: Fix MBC1 mode changing behavior
- GB Video: Fix state after skipping BIOS (fixes mgba.io/i/1715 and mgba.io/i/1716) - GB Video: Fix state after skipping BIOS (fixes mgba.io/i/1715 and mgba.io/i/1716)
- GBA: Fix timing advancing too quickly in rare cases - GBA: Fix timing advancing too quickly in rare cases
- GBA BIOS: Implement dummy sound driver calls - GBA BIOS: Implement dummy sound driver calls

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

View File

@ -1,2 +0,0 @@
[testinfo]
fail=1

View File

@ -108,6 +108,8 @@ enum GBTAMA5Register {
struct GBMBC1State { struct GBMBC1State {
int mode; int mode;
int multicartStride; int multicartStride;
uint8_t bankLo;
uint8_t bankHi;
}; };
struct GBMBC6State { struct GBMBC6State {

View File

@ -362,6 +362,8 @@ struct GBSerializedState {
struct { struct {
uint8_t mode; uint8_t mode;
uint8_t multicartStride; uint8_t multicartStride;
uint8_t bankLo;
uint8_t bankHi;
} mbc1; } mbc1;
struct { struct {
uint64_t lastLatch; uint64_t lastLatch;

View File

@ -419,10 +419,27 @@ static void _latchRtc(struct mRTCSource* rtc, uint8_t* rtcRegs, time_t* rtcLastL
} }
} }
static void _GBMBC1Update(struct GB* gb) {
struct GBMBC1State* state = &gb->memory.mbcState.mbc1;
int bank = state->bankLo;
bank &= (1 << state->multicartStride) - 1;
bank |= state->bankHi << state->multicartStride;
if (state->mode) {
GBMBCSwitchBank0(gb, state->bankHi << state->multicartStride);
GBMBCSwitchSramBank(gb, state->bankHi & 3);
} else {
GBMBCSwitchBank0(gb, 0);
GBMBCSwitchSramBank(gb, 0);
}
if (!(state->bankLo & 0x1F)) {
++bank;
}
GBMBCSwitchBank(gb, bank);
}
void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) { void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) {
struct GBMemory* memory = &gb->memory; struct GBMemory* memory = &gb->memory;
int bank = value & 0x1F; int bank = value & 0x1F;
int stride = 1 << memory->mbcState.mbc1.multicartStride;
switch (address >> 13) { switch (address >> 13) {
case 0x0: case 0x0:
switch (value) { switch (value) {
@ -440,28 +457,17 @@ void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) {
} }
break; break;
case 0x1: case 0x1:
if (!bank) { memory->mbcState.mbc1.bankLo = bank;
++bank; _GBMBC1Update(gb);
}
bank &= stride - 1;
GBMBCSwitchBank(gb, bank | (memory->currentBank & (3 * stride)));
break; break;
case 0x2: case 0x2:
bank &= 3; bank &= 3;
if (memory->mbcState.mbc1.mode) { memory->mbcState.mbc1.bankHi = bank;
GBMBCSwitchBank0(gb, bank << gb->memory.mbcState.mbc1.multicartStride); _GBMBC1Update(gb);
GBMBCSwitchSramBank(gb, bank);
}
GBMBCSwitchBank(gb, (bank << memory->mbcState.mbc1.multicartStride) | (memory->currentBank & (stride - 1)));
break; break;
case 0x3: case 0x3:
memory->mbcState.mbc1.mode = value & 1; memory->mbcState.mbc1.mode = value & 1;
if (memory->mbcState.mbc1.mode) { _GBMBC1Update(gb);
GBMBCSwitchBank0(gb, memory->currentBank & ~((1 << memory->mbcState.mbc1.multicartStride) - 1));
} else {
GBMBCSwitchBank0(gb, 0);
GBMBCSwitchSramBank(gb, 0);
}
break; break;
default: default:
// TODO // TODO

View File

@ -733,6 +733,8 @@ void GBMemorySerialize(const struct GB* gb, struct GBSerializedState* state) {
case GB_MBC1: case GB_MBC1:
state->memory.mbc1.mode = memory->mbcState.mbc1.mode; state->memory.mbc1.mode = memory->mbcState.mbc1.mode;
state->memory.mbc1.multicartStride = memory->mbcState.mbc1.multicartStride; state->memory.mbc1.multicartStride = memory->mbcState.mbc1.multicartStride;
state->memory.mbc1.bankLo = memory->mbcState.mbc1.bankLo;
state->memory.mbc1.bankHi = memory->mbcState.mbc1.bankHi;
break; break;
case GB_MBC3_RTC: case GB_MBC3_RTC:
STORE_64LE(gb->memory.rtcLastLatch, 0, &state->memory.rtc.lastLatch); STORE_64LE(gb->memory.rtcLastLatch, 0, &state->memory.rtc.lastLatch);
@ -801,8 +803,15 @@ void GBMemoryDeserialize(struct GB* gb, const struct GBSerializedState* state) {
case GB_MBC1: case GB_MBC1:
memory->mbcState.mbc1.mode = state->memory.mbc1.mode; memory->mbcState.mbc1.mode = state->memory.mbc1.mode;
memory->mbcState.mbc1.multicartStride = state->memory.mbc1.multicartStride; memory->mbcState.mbc1.multicartStride = state->memory.mbc1.multicartStride;
memory->mbcState.mbc1.bankLo = state->memory.mbc1.bankLo;
memory->mbcState.mbc1.bankHi = state->memory.mbc1.bankHi;
if (!(memory->mbcState.mbc1.bankLo || memory->mbcState.mbc1.bankHi)) {
// Backwards compat
memory->mbcState.mbc1.bankLo = memory->currentBank & ((1 << memory->mbcState.mbc1.multicartStride) - 1);
memory->mbcState.mbc1.bankHi = memory->currentBank >> memory->mbcState.mbc1.multicartStride;
}
if (memory->mbcState.mbc1.mode) { if (memory->mbcState.mbc1.mode) {
GBMBCSwitchBank0(gb, memory->currentBank >> memory->mbcState.mbc1.multicartStride); GBMBCSwitchBank0(gb, memory->mbcState.mbc1.bankHi);
} }
break; break;
case GB_MBC3_RTC: case GB_MBC3_RTC: