all repos — mgba @ 49ccb3d080ded5e3628921475aa35d7b2692c2b8

mGBA Game Boy Advance Emulator

GB MBC: Minor refactoring, basic Pocket Cam support
Vicki Pfau vi@endrift.com
Wed, 07 Jun 2017 23:06:28 -0700
commit

49ccb3d080ded5e3628921475aa35d7b2692c2b8

parent

a4faf9f07956bbb27c89be21eca9b541f6d84853

M include/mgba/gb/interface.hinclude/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.hinclude/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.hinclude/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.csrc/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.csrc/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? }