From a74fe13506d1f7adfc3b4d2074830417b5b3e750 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 8 Jan 2018 18:24:29 -0800 Subject: [PATCH] GB MBC: Fix MBC2 saves (fixes #954) --- CHANGES | 1 + src/gb/mbc.c | 19 +++++++++++++++++-- src/gb/memory.c | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 72d9bc232..206f877b2 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,7 @@ Bugfixes: - GBA Audio: Increase PSG volume (fixes mgba.io/i/932) - GBA BIOS: Fix incorrect exit condition in LZ77 - 3DS: Fix opening files in directory names with trailing slashes + - GB MBC: Fix MBC2 saves (fixes mgba.io/i/954) Misc: - GBA: Improve multiboot image detection - GB MBC: Remove erroneous bank 0 wrapping diff --git a/src/gb/mbc.c b/src/gb/mbc.c index 2f2d1216e..a1c56574f 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -30,6 +30,7 @@ static void _GBMBC7(struct GB*, uint16_t address, uint8_t value); static void _GBHuC3(struct GB*, uint16_t address, uint8_t value); static void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value); +static uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address); static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address); static uint8_t _GBPocketCamRead(struct GBMemory*, uint16_t address); @@ -183,7 +184,8 @@ void GBMBCInit(struct GB* gb) { break; case GB_MBC2: gb->memory.mbcWrite = _GBMBC2; - gb->sramSize = 0x200; + gb->memory.mbcRead = _GBMBC2Read; + gb->sramSize = 0x100; break; case GB_MBC3: gb->memory.mbcWrite = _GBMBC3; @@ -355,6 +357,7 @@ void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) { void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) { struct GBMemory* memory = &gb->memory; + int shift = (address & 1) * 4; int bank = value & 0xF; switch (address >> 13) { case 0x0: @@ -364,7 +367,6 @@ void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) { break; case 0xA: memory->sramAccess = true; - GBMBCSwitchSramBank(gb, memory->sramCurrentBank); break; default: // TODO @@ -378,6 +380,13 @@ void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) { } GBMBCSwitchBank(gb, bank); break; + case 0x5: + if (!memory->sramAccess) { + return; + } + address &= 0x1FF; + memory->sramBank[(address >> 1)] &= 0xF0 >> shift; + memory->sramBank[(address >> 1)] |= (value & 0xF) << shift; default: // TODO mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value); @@ -385,6 +394,12 @@ void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) { } } +static uint8_t _GBMBC2Read(struct GBMemory* memory, uint16_t address) { + address &= 0x1FF; + int shift = (address & 1) * 4; + return (memory->sramBank[(address >> 1)] >> shift) | 0xF0; +} + void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) { struct GBMemory* memory = &gb->memory; int bank = value & 0x7F; diff --git a/src/gb/memory.c b/src/gb/memory.c index 953588990..071f11e0f 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -289,7 +289,7 @@ void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) { case GB_REGION_EXTERNAL_RAM + 1: if (memory->rtcAccess) { memory->rtcRegs[memory->activeRtcReg] = value; - } else if (memory->sramAccess && memory->sram) { + } else if (memory->sramAccess && memory->sram && memory->mbcType != GB_MBC2) { memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value; } else if (memory->mbcType == GB_MBC7) { GBMBC7Write(memory, address, value);