diff --git a/README.md b/README.md index 179c0d413..ce1fa0bb1 100644 --- a/README.md +++ b/README.md @@ -57,9 +57,7 @@ The following mappers are fully supported: - NT "old type" 1 and 2 (unlicensed multicart) - NT "new type" (unlicensed MBC5-like) - Pokémon Jade/Diamond (unlicensed) -- BBD (unlicensed MBC5-like) -- Hitek (unlicensed MBC5-like) -- Sachen MMC1 +- Sachen MMC1 (unlicensed) The following mappers are partially supported: @@ -70,6 +68,9 @@ The following mappers are partially supported: - HuC-1 (missing IR support) - HuC-3 (missing IR support) - Sachen MMC2 (missing alternate wiring support) +- BBD (missing logo switching) +- Hitek (missing logo switching) +- Li Cheng (missing logo switching) ### Planned features diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h index 35170ea82..7c23bb8dd 100644 --- a/include/mgba/gb/interface.h +++ b/include/mgba/gb/interface.h @@ -44,8 +44,9 @@ enum GBMemoryBankControllerType { GB_UNL_NT_OLD_1 = 0x210, GB_UNL_NT_OLD_2 = 0x211, GB_UNL_NT_NEW = 0x212, - GB_UNL_BBD = 0x220, // Also used as a mask for MBCs that need special read behavior + GB_UNL_BBD = 0x220, GB_UNL_HITEK = 0x221, + GB_UNL_LI_CHENG = 0x222, GB_UNL_SACHEN_MMC1 = 0x230, GB_UNL_SACHEN_MMC2 = 0x231, }; diff --git a/src/gb/mbc.c b/src/gb/mbc.c index 18ec32ce6..0ce1f4590 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -50,6 +50,7 @@ static void _GBNTOld2(struct GB* gb, uint16_t address, uint8_t value); static void _GBNTNew(struct GB* gb, uint16_t address, uint8_t value); static void _GBBBD(struct GB* gb, uint16_t address, uint8_t value); static void _GBHitek(struct GB* gb, uint16_t address, uint8_t value); +static void _GBLiCheng(struct GB* gb, uint16_t address, uint8_t value); static void _GBSachen(struct GB* gb, uint16_t address, uint8_t value); static uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address); @@ -164,7 +165,7 @@ static struct { {"NTO1", GB_UNL_NT_OLD_1}, {"NTO2", GB_UNL_NT_OLD_2}, {"NTN", GB_UNL_NT_NEW}, - {"LICH", GB_MBC_AUTODETECT}, // TODO + {"LICH", GB_UNL_LI_CHENG}, {"LBMC", GB_MBC_AUTODETECT}, // TODO {"LIBA", GB_MBC_AUTODETECT}, // TODO {"PKJD", GB_UNL_PKJD}, @@ -257,6 +258,13 @@ static enum GBMemoryBankControllerType _detectUnlMBC(const uint8_t* mem, size_t if (mem[0x7FFF] != 0x01) { // Make sure we're not using a "fixed" version return GB_UNL_BBD; } + break; + case 0x20d092e2: + case 0xd2b57657: + if (cart->type == 0x01) { // Make sure we're not using a "fixed" version + return GB_UNL_LI_CHENG; + } + break; } if (mem[0x104] == 0xCE && mem[0x144] == 0xED && mem[0x114] == 0x66) { @@ -513,6 +521,9 @@ void GBMBCInit(struct GB* gb) { gb->memory.mbcState.bbd.bankSwapMode = 7; gb->memory.mbcReadBank1 = true; break; + case GB_UNL_LI_CHENG: + gb->memory.mbcWrite = _GBLiCheng; + break; case GB_UNL_SACHEN_MMC1: gb->memory.mbcWrite = _GBSachen; gb->memory.mbcRead = _GBSachenMMC1Read; @@ -2242,6 +2253,13 @@ uint8_t _GBHitekRead(struct GBMemory* memory, uint16_t address) { } } +void _GBLiCheng(struct GB* gb, uint16_t address, uint8_t value) { + if (address > 0x2100 && address < 0x3000) { + return; + } + _GBMBC5(gb, address, value); +} + void _GBSachen(struct GB* gb, uint16_t address, uint8_t value) { struct GBSachenState* state = &gb->memory.mbcState.sachen; uint8_t bank = value;