struct MMC1 : Chip { MMC1(Board& board) : Chip(board) { revision = Revision::MMC1B2; } auto main() -> void { if(writedelay) writedelay--; tick(); } auto addrPRG(uint addr) -> uint { bool region = addr & 0x4000; uint bank = (prgBank & ~1) + region; if(prgSize) { bank = (region == 0 ? 0x0 : 0xf); if(region != prgMode) bank = prgBank; } return (bank << 14) | (addr & 0x3fff); } auto addrCHR(uint addr) -> uint { bool region = addr & 0x1000; uint bank = chrBank[region]; if(chrMode == 0) bank = (chrBank[0] & ~1) | region; return (bank << 12) | (addr & 0x0fff); } auto addrCIRAM(uint addr) -> uint { switch(mirror) { case 0: return 0x0000 | (addr & 0x03ff); case 1: return 0x0400 | (addr & 0x03ff); case 2: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); case 3: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); } } auto writeIO(uint addr, uint8 data) -> void { if(writedelay) return; writedelay = 2; if(data & 0x80) { shiftaddr = 0; prgSize = 1; prgMode = 1; } else { shiftdata = ((data & 1) << 4) | (shiftdata >> 1); if(++shiftaddr == 5) { shiftaddr = 0; switch((addr >> 13) & 3) { case 0: chrMode = (shiftdata & 0x10); prgSize = (shiftdata & 0x08); prgMode = (shiftdata & 0x04); mirror = (shiftdata & 0x03); break; case 1: chrBank[0] = (shiftdata & 0x1f); break; case 2: chrBank[1] = (shiftdata & 0x1f); break; case 3: ramDisable = (shiftdata & 0x10); prgBank = (shiftdata & 0x0f); break; } } } } auto power() -> void { } auto reset() -> void { writedelay = 0; shiftaddr = 0; shiftdata = 0; chrMode = 0; prgSize = 1; prgMode = 1; mirror = 0; chrBank[0] = 0; chrBank[1] = 1; ramDisable = 0; prgBank = 0; } auto serialize(serializer& s) -> void { s.integer(writedelay); s.integer(shiftaddr); s.integer(shiftdata); s.integer(chrMode); s.integer(prgSize); s.integer(prgMode); s.integer(mirror); s.array(chrBank); s.integer(ramDisable); s.integer(prgBank); } enum class Revision : uint { MMC1, MMC1A, MMC1B1, MMC1B2, MMC1B3, MMC1C, } revision; uint writedelay; uint shiftaddr; uint shiftdata; bool chrMode; bool prgSize; //0 = 32K, 1 = 16K bool prgMode; uint2 mirror; //0 = first, 1 = second, 2 = vertical, 3 = horizontal uint5 chrBank[2]; bool ramDisable; uint4 prgBank; };