mirror of
https://github.com/libretro/mgba.git
synced 2024-11-23 07:59:46 +00:00
GB MBC: Fix MBC1 mode changing behavior
This commit is contained in:
parent
a1c61edf5c
commit
96f1838faa
1
CHANGES
1
CHANGES
@ -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 |
@ -1,2 +0,0 @@
|
||||
[testinfo]
|
||||
fail=1
|
@ -108,6 +108,8 @@ enum GBTAMA5Register {
|
||||
struct GBMBC1State {
|
||||
int mode;
|
||||
int multicartStride;
|
||||
uint8_t bankLo;
|
||||
uint8_t bankHi;
|
||||
};
|
||||
|
||||
struct GBMBC6State {
|
||||
|
@ -362,6 +362,8 @@ struct GBSerializedState {
|
||||
struct {
|
||||
uint8_t mode;
|
||||
uint8_t multicartStride;
|
||||
uint8_t bankLo;
|
||||
uint8_t bankHi;
|
||||
} mbc1;
|
||||
struct {
|
||||
uint64_t lastLatch;
|
||||
|
40
src/gb/mbc.c
40
src/gb/mbc.c
@ -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
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user