mirror of https://github.com/mgba-emu/mgba.git
GB MBC: Add GGB-81 support
This commit is contained in:
parent
a305882dba
commit
ad2a7a748a
2
CHANGES
2
CHANGES
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
10
src/gb/mbc.c
10
src/gb/mbc.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 } }
|
||||
};
|
||||
|
|
|
@ -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)");
|
||||
|
|
Loading…
Reference in New Issue