From 5c5be73c473a957af45eff152425e4c0207a0d6d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 4 Jul 2019 17:45:03 -0700 Subject: [PATCH] GB MBC: Support for unlicensed Wisdom Tree Game Boy mapper --- CHANGES | 1 + README.md | 1 + include/mgba/gb/interface.h | 1 + src/gb/mbc.c | 42 +++++++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/CHANGES b/CHANGES index 13f5c13e8..a8304684e 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,7 @@ Features: - Ports: Ability to crop SGB borders off screen (closes mgba.io/i/1204) - Cheats: Add support for loading Libretro-style cht files - GBA Cheats: Add support for loading EZ Flash-style cht files + - Support for unlicensed Wisdom Tree Game Boy mapper Emulation fixes: - GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208) - GBA: Reset now reloads multiboot ROMs diff --git a/README.md b/README.md index 803e1de0f..111eaa337 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ The following mappers are fully supported: - MBC5 - MBC5+Rumble - MBC7 +- Wisdom Tree (unlicensed) The following mappers are partially supported: diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h index 300846c6a..d17593f21 100644 --- a/include/mgba/gb/interface.h +++ b/include/mgba/gb/interface.h @@ -34,6 +34,7 @@ enum GBMemoryBankControllerType { GB_HuC3 = 0x12, GB_POCKETCAM = 0x13, GB_TAMA5 = 0x14, + GB_UNL_WISDOM_TREE = 0x20, GB_MBC3_RTC = 0x103, GB_MBC5_RUMBLE = 0x105 }; diff --git a/src/gb/mbc.c b/src/gb/mbc.c index e87a2a36f..f499f5d18 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -35,6 +35,7 @@ static void _GBHuC1(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 void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value); +static void _GBWisdomTree(struct GB* gb, uint16_t address, uint8_t value); static uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address); static uint8_t _GBMBC6Read(struct GBMemory*, uint16_t address); @@ -119,6 +120,24 @@ static bool _isMulticart(const uint8_t* mem) { return success; } +static bool _isWisdomTree(const uint8_t* mem) { + int i; + for (i = 0x134; i < 0x14C; i += 4) { + if (*(uint32_t*) &mem[i] != 0) { + return false; + } + } + for (i = 0xF0; i < 0x100; i += 4) { + if (*(uint32_t*) &mem[i] != 0) { + return false; + } + } + if (mem[0x14D] != 0xE7) { + return false; + } + return true; +} + void GBMBCSwitchSramBank(struct GB* gb, int bank) { size_t bankStart = bank * GB_SIZE_EXTERNAL_RAM; if (bankStart + GB_SIZE_EXTERNAL_RAM > gb->sramSize) { @@ -180,6 +199,11 @@ void GBMBCInit(struct GB* gb) { if (gb->memory.mbcType == GB_MBC_AUTODETECT) { switch (cart->type) { case 0: + if (_isWisdomTree(gb->memory.rom)) { + gb->memory.mbcType = GB_UNL_WISDOM_TREE; + break; + } + // Fall through case 8: case 9: gb->memory.mbcType = GB_MBC_NONE; @@ -310,6 +334,9 @@ void GBMBCInit(struct GB* gb) { gb->memory.cam->startRequestImage(gb->memory.cam, GBCAM_WIDTH, GBCAM_HEIGHT, mCOLOR_ANY); } break; + case GB_UNL_WISDOM_TREE: + gb->memory.mbcWrite = _GBWisdomTree; + break; } gb->memory.currentBank = 1; @@ -1167,6 +1194,21 @@ uint8_t _GBTAMA5Read(struct GBMemory* memory, uint16_t address) { } } +void _GBWisdomTree(struct GB* gb, uint16_t address, uint8_t value) { + UNUSED(value); + int bank = address & 0x3F; + switch (address >> 14) { + case 0x0: + GBMBCSwitchBank0(gb, bank * 2); + GBMBCSwitchBank(gb, bank * 2 + 1); + break; + default: + // TODO + mLOG(GB_MBC, STUB, "Wisdom Tree unknown address: %04X:%02X", address, value); + break; + } +} + void GBMBCRTCRead(struct GB* gb) { struct GBMBCRTCSaveBuffer rtcBuffer; struct VFile* vf = gb->sramVf;