struct MMC6 : Chip { MMC6(Board& board) : Chip(board) { } auto main() -> void { if(irq_delay) irq_delay--; cpu.set_irq_line(irq_line); tick(); } auto irq_test(uint addr) -> void { if(!(chr_abus & 0x1000) && (addr & 0x1000)) { if(irq_delay == 0) { if(irq_counter == 0) { irq_counter = irq_latch; } else if(--irq_counter == 0) { if(irq_enable) irq_line = 1; } } irq_delay = 6; } chr_abus = addr; } auto prg_addr(uint addr) const -> uint { switch((addr >> 13) & 3) { case 0: if(prg_mode == 1) return (0x3e << 13) | (addr & 0x1fff); return (prg_bank[0] << 13) | (addr & 0x1fff); case 1: return (prg_bank[1] << 13) | (addr & 0x1fff); case 2: if(prg_mode == 0) return (0x3e << 13) | (addr & 0x1fff); return (prg_bank[0] << 13) | (addr & 0x1fff); case 3: return (0x3f << 13) | (addr & 0x1fff); } } auto chr_addr(uint addr) const -> uint { if(chr_mode == 0) { if(addr <= 0x07ff) return (chr_bank[0] << 10) | (addr & 0x07ff); if(addr <= 0x0fff) return (chr_bank[1] << 10) | (addr & 0x07ff); if(addr <= 0x13ff) return (chr_bank[2] << 10) | (addr & 0x03ff); if(addr <= 0x17ff) return (chr_bank[3] << 10) | (addr & 0x03ff); if(addr <= 0x1bff) return (chr_bank[4] << 10) | (addr & 0x03ff); if(addr <= 0x1fff) return (chr_bank[5] << 10) | (addr & 0x03ff); } else { if(addr <= 0x03ff) return (chr_bank[2] << 10) | (addr & 0x03ff); if(addr <= 0x07ff) return (chr_bank[3] << 10) | (addr & 0x03ff); if(addr <= 0x0bff) return (chr_bank[4] << 10) | (addr & 0x03ff); if(addr <= 0x0fff) return (chr_bank[5] << 10) | (addr & 0x03ff); if(addr <= 0x17ff) return (chr_bank[0] << 10) | (addr & 0x07ff); if(addr <= 0x1fff) return (chr_bank[1] << 10) | (addr & 0x07ff); } } auto ciram_addr(uint addr) const -> uint { if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); } auto ram_read(uint addr) -> uint8 { if(ram_enable == false) return cpu.mdr(); if(ram_readable[0] == false && ram_readable[1] == false) return cpu.mdr(); bool region = addr & 0x0200; if(ram_readable[region] == false) return 0x00; return board.prgram.read((region * 0x0200) + (addr & 0x01ff)); } auto ram_write(uint addr, uint8 data) -> void { if(ram_enable == false) return; bool region = addr & 0x0200; if(ram_writable[region] == false) return; return board.prgram.write((region * 0x0200) + (addr & 0x01ff), data); } auto reg_write(uint addr, uint8 data) -> void { switch(addr & 0xe001) { case 0x8000: chr_mode = data & 0x80; prg_mode = data & 0x40; ram_enable = data & 0x20; bank_select = data & 0x07; if(ram_enable == false) { for(auto &n : ram_readable) n = false; for(auto &n : ram_writable) n = false; } break; case 0x8001: switch(bank_select) { case 0: chr_bank[0] = data & ~1; break; case 1: chr_bank[1] = data & ~1; break; case 2: chr_bank[2] = data; break; case 3: chr_bank[3] = data; break; case 4: chr_bank[4] = data; break; case 5: chr_bank[5] = data; break; case 6: prg_bank[0] = data & 0x3f; break; case 7: prg_bank[1] = data & 0x3f; break; } break; case 0xa000: mirror = data & 0x01; break; case 0xa001: if(ram_enable == false) break; ram_readable[1] = data & 0x80; ram_writable[1] = data & 0x40; ram_readable[0] = data & 0x20; ram_writable[0] = data & 0x10; break; case 0xc000: irq_latch = data; break; case 0xc001: irq_counter = 0; break; case 0xe000: irq_enable = false; irq_line = 0; break; case 0xe001: irq_enable = true; break; } } auto power() -> void { } auto reset() -> void { chr_mode = 0; prg_mode = 0; ram_enable = 0; bank_select = 0; for(auto& n : prg_bank) n = 0; for(auto& n : chr_bank) n = 0; mirror = 0; for(auto& n : ram_readable) n = 0; for(auto& n : ram_writable) n = 0; irq_latch = 0; irq_counter = 0; irq_enable = 0; irq_delay = 0; irq_line = 0; chr_abus = 0; } auto serialize(serializer& s) -> void { s.integer(chr_mode); s.integer(prg_mode); s.integer(ram_enable); s.integer(bank_select); for(auto& n : prg_bank) s.integer(n); for(auto& n : chr_bank) s.integer(n); s.integer(mirror); for(auto& n : ram_readable) s.integer(n); for(auto& n : ram_writable) s.integer(n); s.integer(irq_latch); s.integer(irq_counter); s.integer(irq_enable); s.integer(irq_delay); s.integer(irq_line); s.integer(chr_abus); } bool chr_mode; bool prg_mode; bool ram_enable; uint3 bank_select; uint8 prg_bank[2]; uint8 chr_bank[6]; bool mirror; bool ram_readable[2]; bool ram_writable[2]; uint8 irq_latch; uint8 irq_counter; bool irq_enable; uint irq_delay; bool irq_line; uint16 chr_abus; };