all repos — mgba @ cdf9105f56182a207662c93da1e7a3a7f6bb2040

mGBA Game Boy Advance Emulator

GB MBC: Support for unlicensed Pokemon Jade/Diamond Game Boy mapper
Vicki Pfau vi@endrift.com
Tue, 07 Jul 2020 18:11:18 -0700
commit

cdf9105f56182a207662c93da1e7a3a7f6bb2040

parent

3062a6a2d740593e14c99feb102169c83926c2e6

M CHANGESCHANGES

@@ -2,6 +2,7 @@ 0.9.0: (Future)

Features: - e-Reader card scanning - Add APNG recording + - Support for unlicensed Pokemon Jade/Diamond Game Boy mapper Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation
M README.mdREADME.md

@@ -51,6 +51,7 @@ - MBC5

- MBC5+Rumble - MBC7 - Wisdom Tree (unlicensed) +- Pokémon Jade/Diamond (unlicensed) The following mappers are partially supported:
M include/mgba/gb/interface.hinclude/mgba/gb/interface.h

@@ -34,9 +34,10 @@ GB_HuC1 = 0x11,

GB_HuC3 = 0x12, GB_POCKETCAM = 0x13, GB_TAMA5 = 0x14, - GB_UNL_WISDOM_TREE = 0x20, GB_MBC3_RTC = 0x103, - GB_MBC5_RUMBLE = 0x105 + GB_MBC5_RUMBLE = 0x105, + GB_UNL_WISDOM_TREE = 0x200, + GB_UNL_PKJD = 0x203, }; struct GBSIODriver {
M include/mgba/internal/gb/memory.hinclude/mgba/internal/gb/memory.h

@@ -146,6 +146,10 @@ uint8_t reg;

uint8_t registers[GBTAMA5_MAX]; }; +struct GBPKJDState { + uint8_t reg[2]; +}; + union GBMBCState { struct GBMBC1State mbc1; struct GBMBC6State mbc6;

@@ -153,6 +157,7 @@ struct GBMBC7State mbc7;

struct GBMMM01State mmm01; struct GBPocketCamState pocketCam; struct GBTAMA5State tama5; + struct GBPKJDState pkjd; }; struct mRotationSource;

@@ -171,6 +176,7 @@ uint8_t* wramBank;

int wramCurrentBank; bool sramAccess; + bool directSramAccess; uint8_t* sram; uint8_t* sramBank; int sramCurrentBank;
M src/core/core.csrc/core/core.c

@@ -162,6 +162,10 @@ cb(total, size, context);

} } vf->close(vf); + if (read < 0) { + vfm->close(vfm); + return false; + } bool ret = core->loadROM(core, vfm); if (!ret) { vfm->close(vfm);
M src/gb/mbc.csrc/gb/mbc.c

@@ -36,6 +36,7 @@ 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 void _GBPKJD(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);

@@ -43,6 +44,7 @@ static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address);

static void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value); static uint8_t _GBTAMA5Read(struct GBMemory*, uint16_t address); +static uint8_t _GBPKJDRead(struct GBMemory*, uint16_t address); static uint8_t _GBPocketCamRead(struct GBMemory*, uint16_t address); static void _GBPocketCamCapture(struct GBMemory*);

@@ -273,6 +275,7 @@ } else {

gb->memory.mbcType = GB_MBC_NONE; } gb->memory.mbcRead = NULL; + gb->memory.directSramAccess = true; switch (gb->memory.mbcType) { case GB_MBC_NONE: gb->memory.mbcWrite = _GBMBCNone;

@@ -288,6 +291,7 @@ break;

case GB_MBC2: gb->memory.mbcWrite = _GBMBC2; gb->memory.mbcRead = _GBMBC2Read; + gb->memory.directSramAccess = false; gb->sramSize = 0x100; break; case GB_MBC3:

@@ -300,9 +304,9 @@ case GB_MBC5:

gb->memory.mbcWrite = _GBMBC5; break; case GB_MBC6: - mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6"); gb->memory.mbcWrite = _GBMBC6; gb->memory.mbcRead = _GBMBC6Read; + gb->memory.directSramAccess = false; break; case GB_MBC7: gb->memory.mbcWrite = _GBMBC7;

@@ -342,6 +346,10 @@ break;

case GB_UNL_WISDOM_TREE: gb->memory.mbcWrite = _GBWisdomTree; break; + case GB_UNL_PKJD: + gb->memory.mbcWrite = _GBPKJD; + gb->memory.mbcRead = _GBPKJDRead; + break; } gb->memory.currentBank = 1;

@@ -626,10 +634,10 @@ switch (address >> 10) {

case 0: switch (value) { case 0: - memory->mbcState.mbc6.sramAccess = false; + memory->sramAccess = false; break; case 0xA: - memory->mbcState.mbc6.sramAccess = true; + memory->sramAccess = true; break; default: // TODO

@@ -655,7 +663,7 @@ case 0x28:

case 0x29: case 0x2A: case 0x2B: - if (memory->mbcState.mbc6.sramAccess) { + if (memory->sramAccess) { memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value; } break;

@@ -663,7 +671,7 @@ case 0x2C:

case 0x2D: case 0x2E: case 0x2F: - if (memory->mbcState.mbc6.sramAccess) { + if (memory->sramAccess) { memory->mbcState.mbc6.sramBank1[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value; } break;

@@ -674,7 +682,7 @@ }

} uint8_t _GBMBC6Read(struct GBMemory* memory, uint16_t address) { - if (!memory->mbcState.mbc6.sramAccess) { + if (!memory->sramAccess) { return 0xFF; } switch (address >> 12) {

@@ -1226,6 +1234,74 @@ default:

// TODO mLOG(GB_MBC, STUB, "Wisdom Tree unknown address: %04X:%02X", address, value); break; + } +} + +void _GBPKJD(struct GB* gb, uint16_t address, uint8_t value) { + struct GBMemory* memory = &gb->memory; + switch (address >> 13) { + case 0x2: + if (value < 8) { + memory->directSramAccess = true; + memory->activeRtcReg = 0; + } else if (value >= 0xD && value <= 0xF) { + memory->directSramAccess = false; + memory->rtcAccess = false; + memory->activeRtcReg = value - 8; + } + break; + case 0x5: + if (!memory->sramAccess) { + return; + } + switch (memory->activeRtcReg) { + case 0: + memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value; + break; + case 5: + case 6: + memory->mbcState.pkjd.reg[memory->activeRtcReg - 5] = value; + break; + case 7: + switch (value) { + case 0x11: + memory->mbcState.pkjd.reg[0]--; + break; + case 0x12: + memory->mbcState.pkjd.reg[1]--; + break; + case 0x41: + memory->mbcState.pkjd.reg[0] += memory->mbcState.pkjd.reg[1]; + break; + case 0x42: + memory->mbcState.pkjd.reg[1] += memory->mbcState.pkjd.reg[0]; + break; + case 0x51: + memory->mbcState.pkjd.reg[0]++; + break; + case 0x52: + memory->mbcState.pkjd.reg[1]--; + break; + } + break; + } + return; + } + _GBMBC3(gb, address, value); +} + +static uint8_t _GBPKJDRead(struct GBMemory* memory, uint16_t address) { + if (!memory->sramAccess) { + return 0xFF; + } + switch (memory->activeRtcReg) { + case 0: + return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)]; + case 5: + case 6: + return memory->mbcState.pkjd.reg[memory->activeRtcReg - 5]; + default: + return 0; } }
M src/gb/memory.csrc/gb/memory.c

@@ -361,7 +361,7 @@ case GB_REGION_EXTERNAL_RAM:

case GB_REGION_EXTERNAL_RAM + 1: if (memory->rtcAccess) { memory->rtcRegs[memory->activeRtcReg] = value; - } else if (memory->sramAccess && memory->sram && memory->mbcType != GB_MBC2) { + } else if (memory->sramAccess && memory->sram && memory->directSramAccess) { memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value; } else { memory->mbcWrite(gb, address, value);
M src/gb/overrides.csrc/gb/overrides.c

@@ -495,6 +495,7 @@ { 0x232a067d, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Gold (debug)

{ 0x630ed957, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Gold (non-debug) { 0x5aff0038, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Silver (debug) { 0xa61856bd, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Silver (non-debug) + { 0x30f8f86c, GB_MODEL_AUTODETECT, GB_UNL_PKJD, { 0 } }, // Pokemon Jade Version (Telefang Speed bootleg) { 0, 0, 0, { 0 } } };
M src/platform/qt/OverrideView.cppsrc/platform/qt/OverrideView.cpp

@@ -50,6 +50,7 @@ s_mbcList.append(GB_TAMA5);

s_mbcList.append(GB_HuC1); s_mbcList.append(GB_HuC3); s_mbcList.append(GB_UNL_WISDOM_TREE); + s_mbcList.append(GB_UNL_PKJD); } if (s_gbModelList.isEmpty()) { // NB: Keep in sync with OverrideView.ui
M src/platform/qt/OverrideView.uisrc/platform/qt/OverrideView.ui

@@ -359,6 +359,11 @@ <property name="text">

<string>Wisdom Tree (Unlicensed)</string> </property> </item> + <item> + <property name="text"> + <string>Pokémon Jade/Diamond (Unlicensed)</string> + </property> + </item> </widget> </item> <item row="2" column="0">