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)
|
0.11.0: (Future)
|
||||||
Features:
|
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
|
- Debugger: Add range watchpoints
|
||||||
Other fixes:
|
Other fixes:
|
||||||
- Qt: Manually split filename to avoid overzealous splitting (fixes mgba.io/i/2681)
|
- 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)
|
- Sachen MMC2 (missing alternate wiring support)
|
||||||
- BBD (missing logo switching)
|
- BBD (missing logo switching)
|
||||||
- Hitek (missing logo switching)
|
- Hitek (missing logo switching)
|
||||||
|
- GGB-81 (missing logo switching)
|
||||||
- Li Cheng (missing logo switching)
|
- Li Cheng (missing logo switching)
|
||||||
|
|
||||||
### Planned features
|
### Planned features
|
||||||
|
|
|
@ -47,6 +47,7 @@ enum GBMemoryBankControllerType {
|
||||||
GB_UNL_BBD = 0x220,
|
GB_UNL_BBD = 0x220,
|
||||||
GB_UNL_HITEK = 0x221,
|
GB_UNL_HITEK = 0x221,
|
||||||
GB_UNL_LI_CHENG = 0x222,
|
GB_UNL_LI_CHENG = 0x222,
|
||||||
|
GB_UNL_GGB81 = 0x223,
|
||||||
GB_UNL_SACHEN_MMC1 = 0x230,
|
GB_UNL_SACHEN_MMC1 = 0x230,
|
||||||
GB_UNL_SACHEN_MMC2 = 0x231,
|
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},
|
{"SAM2", GB_UNL_SACHEN_MMC2},
|
||||||
{"ROCK", GB_MBC_AUTODETECT}, // TODO
|
{"ROCK", GB_MBC_AUTODETECT}, // TODO
|
||||||
{"NGHK", GB_MBC_AUTODETECT}, // TODO
|
{"NGHK", GB_MBC_AUTODETECT}, // TODO
|
||||||
{"GB81", GB_MBC_AUTODETECT}, // TODO
|
{"GB81", GB_UNL_GGB81},
|
||||||
{"TPP1", GB_MBC_AUTODETECT}, // TODO
|
{"TPP1", GB_MBC_AUTODETECT}, // TODO
|
||||||
|
|
||||||
{NULL, GB_MBC_AUTODETECT},
|
{NULL, GB_MBC_AUTODETECT},
|
||||||
|
@ -211,6 +211,9 @@ static enum GBMemoryBankControllerType _detectUnlMBC(const uint8_t* mem, size_t
|
||||||
return GB_UNL_BBD;
|
return GB_UNL_BBD;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0x79f34594: // DATA.
|
||||||
|
case 0x7e8c539b: // TD-SOFT
|
||||||
|
return GB_UNL_GGB81;
|
||||||
case 0x20d092e2:
|
case 0x20d092e2:
|
||||||
case 0xd2b57657:
|
case 0xd2b57657:
|
||||||
if (cart->type == 0x01) { // Make sure we're not using a "fixed" version
|
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:
|
case GB_UNL_LI_CHENG:
|
||||||
gb->memory.mbcWrite = _GBLiCheng;
|
gb->memory.mbcWrite = _GBLiCheng;
|
||||||
break;
|
break;
|
||||||
|
case GB_UNL_GGB81:
|
||||||
|
gb->memory.mbcWrite = _GBGGB81;
|
||||||
|
gb->memory.mbcRead = _GBGGB81Read;
|
||||||
|
gb->memory.mbcReadBank1 = true;
|
||||||
|
break;
|
||||||
case GB_UNL_SACHEN_MMC1:
|
case GB_UNL_SACHEN_MMC1:
|
||||||
gb->memory.mbcWrite = _GBSachen;
|
gb->memory.mbcWrite = _GBSachen;
|
||||||
gb->memory.mbcRead = _GBSachenMMC1Read;
|
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 _GBBBD(struct GB* gb, uint16_t address, uint8_t value);
|
||||||
void _GBHitek(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 _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);
|
void _GBSachen(struct GB* gb, uint16_t address, uint8_t value);
|
||||||
|
|
||||||
uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address);
|
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 _GBPKJDRead(struct GBMemory*, uint16_t address);
|
||||||
uint8_t _GBBBDRead(struct GBMemory*, uint16_t address);
|
uint8_t _GBBBDRead(struct GBMemory*, uint16_t address);
|
||||||
uint8_t _GBHitekRead(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 _GBSachenMMC1Read(struct GBMemory*, uint16_t address);
|
||||||
uint8_t _GBSachenMMC2Read(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) {
|
void _GBLiCheng(struct GB* gb, uint16_t address, uint8_t value) {
|
||||||
if (address > 0x2100 && address < 0x3000) {
|
if (address > 0x2100 && address < 0x3000) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -816,6 +816,7 @@ void GBMemorySerialize(const struct GB* gb, struct GBSerializedState* state) {
|
||||||
break;
|
break;
|
||||||
case GB_UNL_BBD:
|
case GB_UNL_BBD:
|
||||||
case GB_UNL_HITEK:
|
case GB_UNL_HITEK:
|
||||||
|
case GB_UNL_GGB81:
|
||||||
state->memory.bbd.dataSwapMode = memory->mbcState.bbd.dataSwapMode;
|
state->memory.bbd.dataSwapMode = memory->mbcState.bbd.dataSwapMode;
|
||||||
state->memory.bbd.bankSwapMode = memory->mbcState.bbd.bankSwapMode;
|
state->memory.bbd.bankSwapMode = memory->mbcState.bbd.bankSwapMode;
|
||||||
break;
|
break;
|
||||||
|
@ -978,6 +979,7 @@ void GBMemoryDeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
||||||
break;
|
break;
|
||||||
case GB_UNL_BBD:
|
case GB_UNL_BBD:
|
||||||
case GB_UNL_HITEK:
|
case GB_UNL_HITEK:
|
||||||
|
case GB_UNL_GGB81:
|
||||||
memory->mbcState.bbd.dataSwapMode = state->memory.bbd.dataSwapMode & 0x7;
|
memory->mbcState.bbd.dataSwapMode = state->memory.bbd.dataSwapMode & 0x7;
|
||||||
memory->mbcState.bbd.bankSwapMode = state->memory.bbd.bankSwapMode & 0x7;
|
memory->mbcState.bbd.bankSwapMode = state->memory.bbd.bankSwapMode & 0x7;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -695,6 +695,7 @@ static const struct GBCartridgeOverride _overrides[] = {
|
||||||
{ 0xBC75D7B8, GB_MODEL_AUTODETECT, GB_UNL_NT_NEW, { 0 } }, // Pokemon - Mewtwo Strikes Back
|
{ 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
|
{ 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
|
{ 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 } }
|
{ 0, 0, 0, { 0 } }
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,6 +40,7 @@ static const QList<GBMemoryBankControllerType> s_mbcList{
|
||||||
GB_UNL_NT_NEW,
|
GB_UNL_NT_NEW,
|
||||||
GB_UNL_BBD,
|
GB_UNL_BBD,
|
||||||
GB_UNL_HITEK,
|
GB_UNL_HITEK,
|
||||||
|
GB_UNL_GGB81,
|
||||||
GB_UNL_LI_CHENG,
|
GB_UNL_LI_CHENG,
|
||||||
GB_UNL_SACHEN_MMC1,
|
GB_UNL_SACHEN_MMC1,
|
||||||
GB_UNL_SACHEN_MMC2,
|
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_PKJD] = tr("Pokémon Jade/Diamond");
|
||||||
s_mbcNames[GB_UNL_BBD] = tr("BBD");
|
s_mbcNames[GB_UNL_BBD] = tr("BBD");
|
||||||
s_mbcNames[GB_UNL_HITEK] = tr("Hitek");
|
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_LI_CHENG] = tr("Li Cheng");
|
||||||
s_mbcNames[GB_UNL_SACHEN_MMC1] = tr("Sachen (MMC1)");
|
s_mbcNames[GB_UNL_SACHEN_MMC1] = tr("Sachen (MMC1)");
|
||||||
s_mbcNames[GB_UNL_SACHEN_MMC2] = tr("Sachen (MMC2)");
|
s_mbcNames[GB_UNL_SACHEN_MMC2] = tr("Sachen (MMC2)");
|
||||||
|
|
Loading…
Reference in New Issue