GB MBC: Minor refactoring, basic Pocket Cam support
Vicki Pfau vi@endrift.com
Wed, 07 Jun 2017 23:06:28 -0700
5 files changed,
94 insertions(+),
23 deletions(-)
M
include/mgba/gb/interface.h
→
include/mgba/gb/interface.h
@@ -30,6 +30,7 @@ GB_MBC7 = 7,
GB_MMM01 = 0x10, GB_HuC1 = 0x11, GB_HuC3 = 0x12, + GB_POCKETCAM = 0x13, GB_MBC3_RTC = 0x103, GB_MBC5_RUMBLE = 0x105 };
M
include/mgba/internal/gb/mbc.h
→
include/mgba/internal/gb/mbc.h
@@ -36,7 +36,6 @@ };
void GBMBCRTCRead(struct GB* gb); void GBMBCRTCWrite(struct GB* gb); -uint8_t GBMBC7Read(struct GBMemory*, uint16_t address); void GBMBC7Write(struct GBMemory*, uint16_t address, uint8_t value); CXX_GUARD_END
M
include/mgba/internal/gb/memory.h
→
include/mgba/internal/gb/memory.h
@@ -63,7 +63,8 @@ GB_SRAM_DIRT_SEEN = 2
}; struct GBMemory; -typedef void (*GBMemoryBankController)(struct GB*, uint16_t address, uint8_t value); +typedef void (*GBMemoryBankControllerWrite)(struct GB*, uint16_t address, uint8_t value); +typedef uint8_t (*GBMemoryBankControllerRead)(struct GBMemory*, uint16_t address); DECL_BITFIELD(GBMBC7Field, uint8_t); DECL_BIT(GBMBC7Field, SK, 6);@@ -98,9 +99,14 @@ int command;
GBMBC7Field field; }; +struct GBPocketCamState { + bool registersActive; +}; + union GBMBCState { struct GBMBC1State mbc1; struct GBMBC7State mbc7; + struct GBPocketCamState pocketCam; }; struct mRotationSource;@@ -109,7 +115,8 @@ uint8_t* rom;
uint8_t* romBase; uint8_t* romBank; enum GBMemoryBankControllerType mbcType; - GBMemoryBankController mbc; + GBMemoryBankControllerWrite mbcWrite; + GBMemoryBankControllerRead mbcRead; union GBMBCState mbcState; int currentBank;
M
src/gb/mbc.c
→
src/gb/mbc.c
@@ -28,6 +28,10 @@ static void _GBMBC5(struct GB*, uint16_t address, uint8_t value);
static void _GBMBC6(struct GB*, uint16_t address, uint8_t value); static void _GBMBC7(struct GB*, uint16_t address, uint8_t value); static void _GBHuC3(struct GB*, uint16_t address, uint8_t value); +static void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value); + +static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address); +static uint8_t _GBPocketCamRead(struct GBMemory*, uint16_t address); void GBMBCSwitchBank(struct GB* gb, int bank) { size_t bankStart = bank * GB_SIZE_CART_BANK0;@@ -148,6 +152,12 @@ break;
case 0x22: gb->memory.mbcType = GB_MBC7; break; + case 0xFC: + gb->memory.mbcType = GB_POCKETCAM; + break; + case 0xFD: + gb->memory.mbcType = GB_HuC1; + break; case 0xFE: gb->memory.mbcType = GB_HuC3; break;@@ -156,51 +166,57 @@ }
} else { gb->memory.mbcType = GB_MBC_NONE; } + gb->memory.mbcRead = NULL; switch (gb->memory.mbcType) { case GB_MBC_NONE: - gb->memory.mbc = _GBMBCNone; + gb->memory.mbcWrite = _GBMBCNone; break; case GB_MBC1: - gb->memory.mbc = _GBMBC1; + gb->memory.mbcWrite = _GBMBC1; break; case GB_MBC2: - gb->memory.mbc = _GBMBC2; + gb->memory.mbcWrite = _GBMBC2; gb->sramSize = 0x200; break; case GB_MBC3: - gb->memory.mbc = _GBMBC3; + gb->memory.mbcWrite = _GBMBC3; break; default: mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type); // Fall through case GB_MBC5: - gb->memory.mbc = _GBMBC5; + gb->memory.mbcWrite = _GBMBC5; break; case GB_MBC6: mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6"); - gb->memory.mbc = _GBMBC6; + gb->memory.mbcWrite = _GBMBC6; break; case GB_MBC7: - gb->memory.mbc = _GBMBC7; + gb->memory.mbcWrite = _GBMBC7; + gb->memory.mbcRead = _GBMBC7Read; gb->sramSize = GB_SIZE_EXTERNAL_RAM; break; case GB_MMM01: mLOG(GB_MBC, WARN, "unimplemented MBC: MMM01"); - gb->memory.mbc = _GBMBC1; + gb->memory.mbcWrite = _GBMBC1; break; case GB_HuC1: mLOG(GB_MBC, WARN, "unimplemented MBC: HuC-1"); - gb->memory.mbc = _GBMBC1; + gb->memory.mbcWrite = _GBMBC1; break; case GB_HuC3: - gb->memory.mbc = _GBHuC3; + gb->memory.mbcWrite = _GBHuC3; break; case GB_MBC3_RTC: memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs)); - gb->memory.mbc = _GBMBC3; + gb->memory.mbcWrite = _GBMBC3; break; case GB_MBC5_RUMBLE: - gb->memory.mbc = _GBMBC5; + gb->memory.mbcWrite = _GBMBC5; + break; + case GB_POCKETCAM: + gb->memory.mbcWrite = _GBPocketCam; + gb->memory.mbcRead = _GBPocketCamRead; break; }@@ -350,7 +366,8 @@ default:
// TODO mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value); break; - }} + } +} void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) { struct GBMemory* memory = &gb->memory;@@ -466,7 +483,7 @@ break;
} } -uint8_t GBMBC7Read(struct GBMemory* memory, uint16_t address) { +uint8_t _GBMBC7Read(struct GBMemory* memory, uint16_t address) { struct GBMBC7State* mbc7 = &memory->mbcState.mbc7; switch (address & 0xF0) { case 0x00:@@ -672,6 +689,52 @@ // TODO
mLOG(GB_MBC, STUB, "HuC-3 unknown address: %04X:%02X", address, value); break; } +} + +void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value) { + struct GBMemory* memory = &gb->memory; + int bank = value & 0x3F; + switch (address >> 13) { + case 0x0: + switch (value) { + case 0: + memory->sramAccess = false; + break; + case 0xA: + memory->sramAccess = true; + GBMBCSwitchSramBank(gb, memory->sramCurrentBank); + break; + default: + // TODO + mLOG(GB_MBC, STUB, "Pocket Cam unknown value %02X", value); + break; + } + break; + case 0x1: + GBMBCSwitchBank(gb, bank); + break; + case 0x2: + if (value < 0x10) { + GBMBCSwitchSramBank(gb, value); + memory->mbcState.pocketCam.registersActive = false; + } else { + memory->mbcState.pocketCam.registersActive = true; + } + break; + default: + mLOG(GB_MBC, STUB, "Pocket Cam unknown address: %04X:%02X", address, value); + break; + } +} + +uint8_t _GBPocketCamRead(struct GBMemory* memory, uint16_t address) { + if (memory->mbcState.pocketCam.registersActive) { + return 0; + } + if (!memory->sramAccess) { + return 0xFF; + } + return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)]; } void GBMBCRTCRead(struct GB* gb) {
M
src/gb/memory.c
→
src/gb/memory.c
@@ -99,7 +99,8 @@ gb->memory.romBank = 0;
gb->memory.romSize = 0; gb->memory.sram = 0; gb->memory.mbcType = GB_MBC_AUTODETECT; - gb->memory.mbc = 0; + gb->memory.mbcRead = NULL; + gb->memory.mbcWrite = NULL; gb->memory.rtc = NULL;@@ -215,10 +216,10 @@ case GB_REGION_EXTERNAL_RAM:
case GB_REGION_EXTERNAL_RAM + 1: if (memory->rtcAccess) { return memory->rtcRegs[memory->activeRtcReg]; + } else if (memory->mbcRead) { + return memory->mbcRead(memory, address); } else if (memory->sramAccess) { return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)]; - } else if (memory->mbcType == GB_MBC7) { - return GBMBC7Read(memory, address); } else if (memory->mbcType == GB_HuC3) { return 0x01; // TODO: Is this supposed to be the current SRAM bank? }@@ -274,7 +275,7 @@ case GB_REGION_CART_BANK1:
case GB_REGION_CART_BANK1 + 1: case GB_REGION_CART_BANK1 + 2: case GB_REGION_CART_BANK1 + 3: - memory->mbc(gb, address, value); + memory->mbcWrite(gb, address, value); cpu->memory.setActiveRegion(cpu, cpu->pc); return; case GB_REGION_VRAM:@@ -391,8 +392,8 @@ return memory->sram[(address & (GB_SIZE_EXTERNAL_RAM - 1)) + segment *GB_SIZE_EXTERNAL_RAM];
} else { return 0xFF; } - } else if (memory->mbcType == GB_MBC7) { - return GBMBC7Read(memory, address); + } else if (memory->mbcRead) { + return memory->mbcRead(memory, address); } else if (memory->mbcType == GB_HuC3) { return 0x01; // TODO: Is this supposed to be the current SRAM bank? }