From fd7d883e69cc573c7f1582eceaf1892e7e7a60e2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 24 Jul 2017 10:26:29 -0700 Subject: [PATCH] GB MBC: Initial TAMA5 support --- include/mgba/gb/interface.h | 1 + include/mgba/internal/gb/mbc.h | 2 - include/mgba/internal/gb/memory.h | 13 ++++++ src/gb/gb.c | 4 +- src/gb/mbc.c | 69 ++++++++++++++++++++++++++++++- src/gb/memory.c | 4 +- 6 files changed, 85 insertions(+), 8 deletions(-) diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h index ef0771bca..73996746c 100644 --- a/include/mgba/gb/interface.h +++ b/include/mgba/gb/interface.h @@ -31,6 +31,7 @@ enum GBMemoryBankControllerType { GB_HuC1 = 0x11, GB_HuC3 = 0x12, GB_POCKETCAM = 0x13, + GB_TAMA5 = 0x14, GB_MBC3_RTC = 0x103, GB_MBC5_RUMBLE = 0x105 }; diff --git a/include/mgba/internal/gb/mbc.h b/include/mgba/internal/gb/mbc.h index 96a27ddc9..7ec4cf052 100644 --- a/include/mgba/internal/gb/mbc.h +++ b/include/mgba/internal/gb/mbc.h @@ -37,8 +37,6 @@ struct GBMBCRTCSaveBuffer { void GBMBCRTCRead(struct GB* gb); void GBMBCRTCWrite(struct GB* gb); -void GBMBC7Write(struct GBMemory*, uint16_t address, uint8_t value); - CXX_GUARD_END #endif diff --git a/include/mgba/internal/gb/memory.h b/include/mgba/internal/gb/memory.h index d28338cff..c2d5e92fa 100644 --- a/include/mgba/internal/gb/memory.h +++ b/include/mgba/internal/gb/memory.h @@ -86,6 +86,11 @@ enum GBMBC7MachineState { GBMBC7_STATE_EEPROM_ERASE = 0x1C, }; +enum GBTAMA5Register { + GBTAMA5_BANK = 0x0, + GBTAMA5_MAX +}; + struct GBMBC1State { int mode; int multicartStride; @@ -106,10 +111,18 @@ struct GBPocketCamState { bool registersActive; }; +struct GBTAMA5State { + bool unlocked; + uint8_t reg; + uint8_t value; + uint8_t registers[GBTAMA5_MAX]; +}; + union GBMBCState { struct GBMBC1State mbc1; struct GBMBC7State mbc7; struct GBPocketCamState pocketCam; + struct GBTAMA5State tama5; }; struct mRotationSource; diff --git a/src/gb/gb.c b/src/gb/gb.c index e6f620ce1..720a862c7 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -613,7 +613,7 @@ void GBHalt(struct LR35902Core* cpu) { void GBStop(struct LR35902Core* cpu) { struct GB* gb = (struct GB*) cpu->master; if (cpu->bus) { - mLOG(GB, GAME_ERROR, "Hit illegal stop at address %04X:%02X\n", cpu->pc, cpu->bus); + mLOG(GB, GAME_ERROR, "Hit illegal stop at address %04X:%02X", cpu->pc, cpu->bus); } if (gb->memory.io[REG_KEY1] & 1) { gb->doubleSpeed ^= 1; @@ -639,7 +639,7 @@ void GBStop(struct LR35902Core* cpu) { void GBIllegal(struct LR35902Core* cpu) { struct GB* gb = (struct GB*) cpu->master; - mLOG(GB, GAME_ERROR, "Hit illegal opcode at address %04X:%02X\n", cpu->pc, cpu->bus); + mLOG(GB, GAME_ERROR, "Hit illegal opcode at address %04X:%02X", cpu->pc, cpu->bus); #ifdef USE_DEBUGGERS if (cpu->components && cpu->components[CPU_COMPONENT_DEBUGGER]) { struct mDebuggerEntryInfo info = { diff --git a/src/gb/mbc.c b/src/gb/mbc.c index 559e3b2f9..9b628c322 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -29,8 +29,13 @@ 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 void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value); 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 _GBPocketCamRead(struct GBMemory*, uint16_t address); void GBMBCSwitchBank(struct GB* gb, int bank) { @@ -160,11 +165,14 @@ void GBMBCInit(struct GB* gb) { gb->memory.mbcType = GB_POCKETCAM; break; case 0xFD: - gb->memory.mbcType = GB_HuC1; + gb->memory.mbcType = GB_TAMA5; break; case 0xFE: gb->memory.mbcType = GB_HuC3; break; + case 0xFF: + gb->memory.mbcType = GB_HuC1; + break; } } } else { @@ -211,6 +219,12 @@ void GBMBCInit(struct GB* gb) { case GB_HuC3: gb->memory.mbcWrite = _GBHuC3; break; + case GB_TAMA5: + mLOG(GB_MBC, WARN, "unimplemented MBC: TAMA5"); + memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs)); + gb->memory.mbcWrite = _GBTAMA5; + gb->memory.mbcRead = _GBTAMA5Read; + break; case GB_MBC3_RTC: memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs)); gb->memory.mbcWrite = _GBMBC3; @@ -493,6 +507,8 @@ void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) { gb->memory.mbcState.mbc7.access &= ~2; } break; + case 0x5: + _GBMBC7Write(&gb->memory, address, value); default: // TODO mLOG(GB_MBC, STUB, "MBC7 unknown address: %04X:%02X", address, value); @@ -547,7 +563,7 @@ uint8_t _GBMBC7Read(struct GBMemory* memory, uint16_t address) { } } -void GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value) { +static void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value) { struct GBMBC7State* mbc7 = &memory->mbcState.mbc7; if (mbc7->access != 3) { return; @@ -750,6 +766,55 @@ uint8_t _GBPocketCamRead(struct GBMemory* memory, uint16_t address) { return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)]; } +void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value) { + struct GBMemory* memory = &gb->memory; + struct GBTAMA5State* tama5 = &memory->mbcState.tama5; + switch (address >> 13) { + case 0x5: + if (address & 1) { + if (tama5->unlocked) { + tama5->reg = value; + } else if (value == 0xA) { + tama5->unlocked = true; + } + } else { + uint8_t reg = tama5->reg >> 1; + if (reg < GBTAMA5_MAX) { + uint8_t mask = 0xF << (4 * (tama5->reg & 1)); + value <<= (4 * (tama5->reg & 1)); + value |= tama5->registers[reg] & ~mask; + tama5->registers[reg] = value; + if (tama5->reg & 1) { + switch (reg) { + case GBTAMA5_BANK: + GBMBCSwitchBank(gb, value & 0x1F); + // Fall through + default: + mLOG(GB_MBC, STUB, "TAMA5 unknown register: %02X:%02X", reg, value); + break; + } + tama5->unlocked = false; + } + } else { + mLOG(GB_MBC, STUB, "TAMA5 unknown register: %02X", reg); + } + } + break; + default: + mLOG(GB_MBC, STUB, "TAMA5 unknown address: %04X:%02X", address, value); + } +} + +uint8_t _GBTAMA5Read(struct GBMemory* memory, uint16_t address) { + struct GBTAMA5State* tama5 = &memory->mbcState.tama5; + mLOG(GB_MBC, STUB, "TAMA5 unknown address: %04X", address); + if (address & 1) { + return 0xFF; + } else { + return 0xF0 | tama5->unlocked; + } +} + void GBMBCRTCRead(struct GB* gb) { struct GBMBCRTCSaveBuffer rtcBuffer; struct VFile* vf = gb->sramVf; diff --git a/src/gb/memory.c b/src/gb/memory.c index f37f6ef73..1d40bb7a9 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -289,8 +289,8 @@ void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) { memory->rtcRegs[memory->activeRtcReg] = value; } else if (memory->sramAccess) { memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value; - } else if (memory->mbcType == GB_MBC7) { - GBMBC7Write(memory, address, value); + } else { + memory->mbcWrite(gb, address, value); } gb->sramDirty |= GB_SRAM_DIRT_NEW; return;