all repos — mgba @ f187fba4fbee89d8fab91b445ed43d4ed0c0bc45

mGBA Game Boy Advance Emulator

GB MBC: More detailed TAMA5 implementation, working saves
Vicki Pfau vi@endrift.com
Mon, 24 Jul 2017 13:48:59 -0700
commit

f187fba4fbee89d8fab91b445ed43d4ed0c0bc45

parent

fd7d883e69cc573c7f1582eceaf1892e7e7a60e2

2 files changed, 66 insertions(+), 26 deletions(-)

jump to
M include/mgba/internal/gb/memory.hinclude/mgba/internal/gb/memory.h

@@ -87,8 +87,16 @@ GBMBC7_STATE_EEPROM_ERASE = 0x1C,

}; enum GBTAMA5Register { - GBTAMA5_BANK = 0x0, - GBTAMA5_MAX + GBTAMA5_BANK_LO = 0x0, + GBTAMA5_BANK_HI = 0x1, + GBTAMA5_WRITE_LO = 0x4, + GBTAMA5_WRITE_HI = 0x5, + GBTAMA5_CS = 0x6, + GBTAMA5_ADDR_LO = 0x7, + GBTAMA5_MAX = 0x8, + GBTAMA5_ACTIVE = 0xA, + GBTAMA5_READ_LO = 0xC, + GBTAMA5_READ_HI = 0xD, }; struct GBMBC1State {

@@ -112,9 +120,7 @@ bool registersActive;

}; struct GBTAMA5State { - bool unlocked; uint8_t reg; - uint8_t value; uint8_t registers[GBTAMA5_MAX]; };
M src/gb/mbc.csrc/gb/mbc.c

@@ -224,6 +224,7 @@ mLOG(GB_MBC, WARN, "unimplemented MBC: TAMA5");

memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs)); gb->memory.mbcWrite = _GBTAMA5; gb->memory.mbcRead = _GBTAMA5Read; + gb->sramSize = 0x20; break; case GB_MBC3_RTC: memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));

@@ -772,31 +773,39 @@ 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; - } + tama5->reg = value; } 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 + value &= 0xF; + if (tama5->reg < GBTAMA5_MAX) { + tama5->registers[tama5->reg] = value; + uint8_t address = ((tama5->registers[GBTAMA5_CS] << 4) & 0x10) | tama5->registers[GBTAMA5_ADDR_LO]; + uint8_t out = (tama5->registers[GBTAMA5_WRITE_HI] << 4) | tama5->registers[GBTAMA5_WRITE_LO]; + switch (tama5->reg) { + case GBTAMA5_BANK_LO: + case GBTAMA5_BANK_HI: + GBMBCSwitchBank(gb, tama5->registers[GBTAMA5_BANK_LO] | (tama5->registers[GBTAMA5_BANK_HI] << 4)); + break; + case GBTAMA5_WRITE_LO: + case GBTAMA5_WRITE_HI: + case GBTAMA5_CS: + break; + case GBTAMA5_ADDR_LO: + switch (tama5->registers[GBTAMA5_CS] >> 1) { + case 0x0: // RAM write + memory->sram[address] = out; + break; + case 0x1: // RAM read + break; default: - mLOG(GB_MBC, STUB, "TAMA5 unknown register: %02X:%02X", reg, value); - break; + mLOG(GB_MBC, STUB, "TAMA5 unknown address: %X-%02X:%02X", tama5->registers[GBTAMA5_CS] >> 1, address, out); } - tama5->unlocked = false; + break; + default: + mLOG(GB_MBC, STUB, "TAMA5 unknown write: %02X:%X", tama5->reg, value); + break; } } else { - mLOG(GB_MBC, STUB, "TAMA5 unknown register: %02X", reg); + mLOG(GB_MBC, STUB, "TAMA5 unknown write: %02X", tama5->reg); } } break;

@@ -807,11 +816,36 @@ }

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 & 0x1FFF) > 1) { + mLOG(GB_MBC, STUB, "TAMA5 unknown address: %04X", address); + } if (address & 1) { return 0xFF; } else { - return 0xF0 | tama5->unlocked; + uint8_t value = 0xF0; + uint8_t address = ((tama5->registers[GBTAMA5_CS] << 4) & 0x10) | tama5->registers[GBTAMA5_ADDR_LO]; + switch (tama5->reg) { + case GBTAMA5_ACTIVE: + return 0xF1; + case GBTAMA5_READ_LO: + case GBTAMA5_READ_HI: + switch (tama5->registers[GBTAMA5_CS] >> 1) { + case 1: + value = memory->sram[address]; + break; + default: + mLOG(GB_MBC, STUB, "TAMA5 unknown read: %02X", tama5->reg); + break; + } + if (tama5->reg == GBTAMA5_READ_HI) { + value >>= 4; + } + value |= 0xF0; + return value; + default: + mLOG(GB_MBC, STUB, "TAMA5 unknown read: %02X", tama5->reg); + return 0xF1; + } } }