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:
- ARM: Fix ALU reading PC after shifting
- 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)
- GBA: Fix timing advancing too quickly in rare cases
- 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 {
int mode;
int multicartStride;
uint8_t bankLo;
uint8_t bankHi;
};
struct GBMBC6State {

View File

@ -362,6 +362,8 @@ struct GBSerializedState {
struct {
uint8_t mode;
uint8_t multicartStride;
uint8_t bankLo;
uint8_t bankHi;
} mbc1;
struct {
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) {
struct GBMemory* memory = &gb->memory;
int bank = value & 0x1F;
int stride = 1 << memory->mbcState.mbc1.multicartStride;
switch (address >> 13) {
case 0x0:
switch (value) {
@ -440,28 +457,17 @@ void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) {
}
break;
case 0x1:
if (!bank) {
++bank;
}
bank &= stride - 1;
GBMBCSwitchBank(gb, bank | (memory->currentBank & (3 * stride)));
memory->mbcState.mbc1.bankLo = bank;
_GBMBC1Update(gb);
break;
case 0x2:
bank &= 3;
if (memory->mbcState.mbc1.mode) {
GBMBCSwitchBank0(gb, bank << gb->memory.mbcState.mbc1.multicartStride);
GBMBCSwitchSramBank(gb, bank);
}
GBMBCSwitchBank(gb, (bank << memory->mbcState.mbc1.multicartStride) | (memory->currentBank & (stride - 1)));
memory->mbcState.mbc1.bankHi = bank;
_GBMBC1Update(gb);
break;
case 0x3:
memory->mbcState.mbc1.mode = value & 1;
if (memory->mbcState.mbc1.mode) {
GBMBCSwitchBank0(gb, memory->currentBank & ~((1 << memory->mbcState.mbc1.multicartStride) - 1));
} else {
GBMBCSwitchBank0(gb, 0);
GBMBCSwitchSramBank(gb, 0);
}
_GBMBC1Update(gb);
break;
default:
// TODO

View File

@ -733,6 +733,8 @@ void GBMemorySerialize(const struct GB* gb, struct GBSerializedState* state) {
case GB_MBC1:
state->memory.mbc1.mode = memory->mbcState.mbc1.mode;
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;
case GB_MBC3_RTC:
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:
memory->mbcState.mbc1.mode = state->memory.mbc1.mode;
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) {
GBMBCSwitchBank0(gb, memory->currentBank >> memory->mbcState.mbc1.multicartStride);
GBMBCSwitchBank0(gb, memory->mbcState.mbc1.bankHi);
}
break;
case GB_MBC3_RTC: