all repos — mgba @ ec1fc632b23749add411a2d9a9a4a32bd957a99c

mGBA Game Boy Advance Emulator

GB MBC: MBC6 skeleton
Vicki Pfau vi@endrift.com
Fri, 11 Aug 2017 18:19:31 -0700
commit

ec1fc632b23749add411a2d9a9a4a32bd957a99c

parent

8b8d8462720f48ac37a4c12f69deddf14e4fc491

4 files changed, 66 insertions(+), 7 deletions(-)

jump to
M include/mgba/internal/gb/mbc.hinclude/mgba/internal/gb/mbc.h

@@ -19,6 +19,7 @@ struct GBMemory;

void GBMBCInit(struct GB* gb); void GBMBCSwitchBank(struct GB* gb, int bank); void GBMBCSwitchBank0(struct GB* gb, int bank); +void GBMBCSwitchHalfBank(struct GB* gb, int half, int bank); void GBMBCSwitchSramBank(struct GB* gb, int bank); enum GBCam {
M include/mgba/internal/gb/memory.hinclude/mgba/internal/gb/memory.h

@@ -22,6 +22,8 @@

enum { GB_BASE_CART_BANK0 = 0x0000, GB_BASE_CART_BANK1 = 0x4000, + GB_BASE_CART_HALFBANK1 = 0x4000, + GB_BASE_CART_HALFBANK2 = 0x6000, GB_BASE_VRAM = 0x8000, GB_BASE_EXTERNAL_RAM = 0xA000, GB_BASE_WORKING_RAM_BANK0 = 0xC000,

@@ -46,6 +48,7 @@ };

enum { GB_SIZE_CART_BANK0 = 0x4000, + GB_SIZE_CART_HALFBANK = 0x2000, GB_SIZE_CART_MAX = 0x800000, GB_SIZE_VRAM = 0x4000, GB_SIZE_VRAM_BANK0 = 0x2000,

@@ -104,6 +107,11 @@ int mode;

int multicartStride; }; +struct GBMBC6State { + int currentBank1; + uint8_t* romBank1; +}; + struct GBMBC7State { enum GBMBC7MachineState state; uint16_t sr;

@@ -127,6 +135,7 @@ };

union GBMBCState { struct GBMBC1State mbc1; + struct GBMBC6State mbc6; struct GBMBC7State mbc7; struct GBPocketCamState pocketCam; struct GBTAMA5State tama5;
M src/gb/mbc.csrc/gb/mbc.c

@@ -68,6 +68,28 @@ gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);

} } +void GBMBCSwitchHalfBank(struct GB* gb, int half, int bank) { + size_t bankStart = bank * GB_SIZE_CART_HALFBANK; + if (bankStart + GB_SIZE_CART_HALFBANK > gb->memory.romSize) { + mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank); + bankStart &= (gb->memory.romSize - 1); + bank = bankStart / GB_SIZE_CART_HALFBANK; + if (!bank) { + ++bank; + } + } + if (!half) { + gb->memory.romBank = &gb->memory.rom[bankStart]; + gb->memory.currentBank = bank; + } else { + gb->memory.mbcState.mbc6.romBank1 = &gb->memory.rom[bankStart]; + gb->memory.mbcState.mbc6.currentBank1 = bank; + } + if (gb->cpu->pc < GB_BASE_VRAM) { + gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc); + } +} + static bool _isMulticart(const uint8_t* mem) { bool success = true; struct VFile* vf;

@@ -496,11 +518,34 @@ }

} void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) { - // TODO - mLOG(GB_MBC, STUB, "MBC6 unimplemented"); - UNUSED(gb); - UNUSED(address); - UNUSED(value); + struct GBMemory* memory = &gb->memory; + int bank = value & 0x7F; + switch (address >> 10) { + case 0: + switch (value) { + case 0: + memory->sramAccess = false; + break; + case 0xA: + memory->sramAccess = true; + GBMBCSwitchSramBank(gb, memory->sramCurrentBank); + break; + default: + // TODO + mLOG(GB_MBC, STUB, "MBC6 unknown value %02X", value); + break; + } + break; + case 0x9: + GBMBCSwitchHalfBank(gb, 0, bank); + break; + case 0xD: + GBMBCSwitchHalfBank(gb, 1, bank); + break; + default: + mLOG(GB_MBC, STUB, "MBC6 unknown address: %04X:%02X", address, value); + break; + } } void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) {
M src/gb/memory.csrc/gb/memory.c

@@ -207,10 +207,14 @@ case GB_REGION_CART_BANK0 + 1:

case GB_REGION_CART_BANK0 + 2: case GB_REGION_CART_BANK0 + 3: return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)]; - case GB_REGION_CART_BANK1: - case GB_REGION_CART_BANK1 + 1: case GB_REGION_CART_BANK1 + 2: case GB_REGION_CART_BANK1 + 3: + if (memory->mbcType == GB_MBC6) { + return memory->mbcState.mbc6.romBank1[address & (GB_SIZE_CART_HALFBANK - 1)]; + } + // Fall through + case GB_REGION_CART_BANK1: + case GB_REGION_CART_BANK1 + 1: return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)]; case GB_REGION_VRAM: case GB_REGION_VRAM + 1: