GB MBC: Add GGB-81 support

This commit is contained in:
Vicki Pfau 2022-10-17 01:31:04 -07:00
parent a305882dba
commit ad2a7a748a
9 changed files with 50 additions and 2 deletions

View File

@ -1,6 +1,6 @@
0.11.0: (Future)
Features:
- New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng
- New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81
- Debugger: Add range watchpoints
Other fixes:
- Qt: Manually split filename to avoid overzealous splitting (fixes mgba.io/i/2681)

View File

@ -71,6 +71,7 @@ The following mappers are partially supported:
- Sachen MMC2 (missing alternate wiring support)
- BBD (missing logo switching)
- Hitek (missing logo switching)
- GGB-81 (missing logo switching)
- Li Cheng (missing logo switching)
### Planned features

View File

@ -47,6 +47,7 @@ enum GBMemoryBankControllerType {
GB_UNL_BBD = 0x220,
GB_UNL_HITEK = 0x221,
GB_UNL_LI_CHENG = 0x222,
GB_UNL_GGB81 = 0x223,
GB_UNL_SACHEN_MMC1 = 0x230,
GB_UNL_SACHEN_MMC2 = 0x231,
};

View File

@ -126,7 +126,7 @@ static struct {
{"SAM2", GB_UNL_SACHEN_MMC2},
{"ROCK", GB_MBC_AUTODETECT}, // TODO
{"NGHK", GB_MBC_AUTODETECT}, // TODO
{"GB81", GB_MBC_AUTODETECT}, // TODO
{"GB81", GB_UNL_GGB81},
{"TPP1", GB_MBC_AUTODETECT}, // TODO
{NULL, GB_MBC_AUTODETECT},
@ -211,6 +211,9 @@ static enum GBMemoryBankControllerType _detectUnlMBC(const uint8_t* mem, size_t
return GB_UNL_BBD;
}
break;
case 0x79f34594: // DATA.
case 0x7e8c539b: // TD-SOFT
return GB_UNL_GGB81;
case 0x20d092e2:
case 0xd2b57657:
if (cart->type == 0x01) { // Make sure we're not using a "fixed" version
@ -479,6 +482,11 @@ void GBMBCInit(struct GB* gb) {
case GB_UNL_LI_CHENG:
gb->memory.mbcWrite = _GBLiCheng;
break;
case GB_UNL_GGB81:
gb->memory.mbcWrite = _GBGGB81;
gb->memory.mbcRead = _GBGGB81Read;
gb->memory.mbcReadBank1 = true;
break;
case GB_UNL_SACHEN_MMC1:
gb->memory.mbcWrite = _GBSachen;
gb->memory.mbcRead = _GBSachenMMC1Read;

View File

@ -36,6 +36,7 @@ void _GBNTNew(struct GB* gb, uint16_t address, uint8_t value);
void _GBBBD(struct GB* gb, uint16_t address, uint8_t value);
void _GBHitek(struct GB* gb, uint16_t address, uint8_t value);
void _GBLiCheng(struct GB* gb, uint16_t address, uint8_t value);
void _GBGGB81(struct GB* gb, uint16_t address, uint8_t value);
void _GBSachen(struct GB* gb, uint16_t address, uint8_t value);
uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address);
@ -50,6 +51,7 @@ uint8_t _GBHuC3Read(struct GBMemory*, uint16_t address);
uint8_t _GBPKJDRead(struct GBMemory*, uint16_t address);
uint8_t _GBBBDRead(struct GBMemory*, uint16_t address);
uint8_t _GBHitekRead(struct GBMemory*, uint16_t address);
uint8_t _GBGGB81Read(struct GBMemory*, uint16_t address);
uint8_t _GBSachenMMC1Read(struct GBMemory*, uint16_t address);
uint8_t _GBSachenMMC2Read(struct GBMemory*, uint16_t address);

View File

@ -362,6 +362,37 @@ uint8_t _GBHitekRead(struct GBMemory* memory, uint16_t address) {
}
}
static const uint8_t _ggb81DataReordering[8][8] = {
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 0, 2, 1, 3, 4, 6, 5, 7 },
{ 0, 6, 5, 3, 4, 2, 1, 7 },
{ 0, 5, 1, 3, 4, 2, 6, 7 },
{ 0, 5, 2, 3, 4, 1, 6, 7 },
{ 0, 2, 6, 3, 4, 5, 1, 7 },
{ 0, 1, 6, 3, 4, 2, 5, 7 },
{ 0, 2, 5, 3, 4, 6, 1, 7 },
};
void _GBGGB81(struct GB* gb, uint16_t address, uint8_t value) {
struct GBMemory* memory = &gb->memory;
switch (address & 0xF0FF) {
case 0x2001:
memory->mbcState.bbd.dataSwapMode = value & 0x07;
break;
}
_GBMBC5(gb, address, value);
}
uint8_t _GBGGB81Read(struct GBMemory* memory, uint16_t address) {
switch (address >> 14) {
case 0:
default:
return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
case 1:
return _reorderBits(memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)], _ggb81DataReordering[memory->mbcState.bbd.dataSwapMode]);
}
}
void _GBLiCheng(struct GB* gb, uint16_t address, uint8_t value) {
if (address > 0x2100 && address < 0x3000) {
return;

View File

@ -816,6 +816,7 @@ void GBMemorySerialize(const struct GB* gb, struct GBSerializedState* state) {
break;
case GB_UNL_BBD:
case GB_UNL_HITEK:
case GB_UNL_GGB81:
state->memory.bbd.dataSwapMode = memory->mbcState.bbd.dataSwapMode;
state->memory.bbd.bankSwapMode = memory->mbcState.bbd.bankSwapMode;
break;
@ -978,6 +979,7 @@ void GBMemoryDeserialize(struct GB* gb, const struct GBSerializedState* state) {
break;
case GB_UNL_BBD:
case GB_UNL_HITEK:
case GB_UNL_GGB81:
memory->mbcState.bbd.dataSwapMode = state->memory.bbd.dataSwapMode & 0x7;
memory->mbcState.bbd.bankSwapMode = state->memory.bbd.bankSwapMode & 0x7;
break;

View File

@ -695,6 +695,7 @@ static const struct GBCartridgeOverride _overrides[] = {
{ 0xBC75D7B8, GB_MODEL_AUTODETECT, GB_UNL_NT_NEW, { 0 } }, // Pokemon - Mewtwo Strikes Back
{ 0xFF0B60CC, GB_MODEL_AUTODETECT, GB_UNL_NT_NEW, { 0 } }, // Shuma Baolong 02 4
{ 0x14A992A6, GB_MODEL_AUTODETECT, GB_UNL_NT_NEW, { 0 } }, // /Street Fighter Zero 4
{ 0x3EF5AFB2, GB_MODEL_AUTODETECT, GB_UNL_LI_CHENG, { 0 } }, // Pokemon Jade Version (Telefang Speed bootleg)
{ 0, 0, 0, { 0 } }
};

View File

@ -40,6 +40,7 @@ static const QList<GBMemoryBankControllerType> s_mbcList{
GB_UNL_NT_NEW,
GB_UNL_BBD,
GB_UNL_HITEK,
GB_UNL_GGB81,
GB_UNL_LI_CHENG,
GB_UNL_SACHEN_MMC1,
GB_UNL_SACHEN_MMC2,
@ -97,6 +98,7 @@ QString GameBoy::mbcName(GBMemoryBankControllerType mbc) {
s_mbcNames[GB_UNL_PKJD] = tr("Pokémon Jade/Diamond");
s_mbcNames[GB_UNL_BBD] = tr("BBD");
s_mbcNames[GB_UNL_HITEK] = tr("Hitek");
s_mbcNames[GB_UNL_GGB81] = tr("GGB-81");
s_mbcNames[GB_UNL_LI_CHENG] = tr("Li Cheng");
s_mbcNames[GB_UNL_SACHEN_MMC1] = tr("Sachen (MMC1)");
s_mbcNames[GB_UNL_SACHEN_MMC2] = tr("Sachen (MMC2)");