all repos — mgba @ fd7d883e69cc573c7f1582eceaf1892e7e7a60e2

mGBA Game Boy Advance Emulator

GB MBC: Initial TAMA5 support
Vicki Pfau vi@endrift.com
Mon, 24 Jul 2017 10:26:29 -0700
commit

fd7d883e69cc573c7f1582eceaf1892e7e7a60e2

parent

ef82480a8b94f5c7ed39f8f747914c229752a44e

M include/mgba/gb/interface.hinclude/mgba/gb/interface.h

@@ -31,6 +31,7 @@ GB_MMM01 = 0x10,

GB_HuC1 = 0x11, GB_HuC3 = 0x12, GB_POCKETCAM = 0x13, + GB_TAMA5 = 0x14, GB_MBC3_RTC = 0x103, GB_MBC5_RUMBLE = 0x105 };
M include/mgba/internal/gb/mbc.hinclude/mgba/internal/gb/mbc.h

@@ -37,8 +37,6 @@ };

void GBMBCRTCRead(struct GB* gb); void GBMBCRTCWrite(struct GB* gb); -void GBMBC7Write(struct GBMemory*, uint16_t address, uint8_t value); - CXX_GUARD_END #endif
M include/mgba/internal/gb/memory.hinclude/mgba/internal/gb/memory.h

@@ -86,6 +86,11 @@ GBMBC7_STATE_EEPROM_READ = 0x18,

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;
M src/gb/gb.csrc/gb/gb.c

@@ -613,7 +613,7 @@

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 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 = {
M src/gb/mbc.csrc/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,10 +165,13 @@ case 0xFC:

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; } }

@@ -210,6 +218,12 @@ gb->memory.mbcWrite = _GBMBC1;

break; 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));

@@ -493,6 +507,8 @@ } else {

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 @@ return 0xFF;

} } -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;

@@ -748,6 +764,55 @@ if (!memory->sramAccess) {

return 0xFF; } 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) {
M src/gb/memory.csrc/gb/memory.c

@@ -289,8 +289,8 @@ if (memory->rtcAccess) {

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;