bsnes/higan/fc/cartridge/chip/mmc6.cpp

193 lines
5.0 KiB
C++
Raw Normal View History

struct MMC6 : Chip {
MMC6(Board& board) : Chip(board) {
}
auto main() -> void {
if(irqDelay) irqDelay--;
cpu.irqLine(irqLine);
tick();
}
auto irqTest(uint addr) -> void {
if(!(chrAbus & 0x1000) && (addr & 0x1000)) {
if(irqDelay == 0) {
if(irqCounter == 0) {
irqCounter = irqLatch;
} else if(--irqCounter == 0) {
if(irqEnable) irqLine = 1;
}
}
irqDelay = 6;
}
chrAbus = addr;
}
auto addrPRG(uint addr) const -> uint {
switch((addr >> 13) & 3) {
case 0:
if(prgMode == 1) return (0x3e << 13) | (addr & 0x1fff);
return (prgBank[0] << 13) | (addr & 0x1fff);
case 1:
return (prgBank[1] << 13) | (addr & 0x1fff);
case 2:
if(prgMode == 0) return (0x3e << 13) | (addr & 0x1fff);
return (prgBank[0] << 13) | (addr & 0x1fff);
case 3:
return (0x3f << 13) | (addr & 0x1fff);
}
}
auto addrCHR(uint addr) const -> uint {
if(chrMode == 0) {
if(addr <= 0x07ff) return (chrBank[0] << 10) | (addr & 0x07ff);
if(addr <= 0x0fff) return (chrBank[1] << 10) | (addr & 0x07ff);
if(addr <= 0x13ff) return (chrBank[2] << 10) | (addr & 0x03ff);
if(addr <= 0x17ff) return (chrBank[3] << 10) | (addr & 0x03ff);
if(addr <= 0x1bff) return (chrBank[4] << 10) | (addr & 0x03ff);
if(addr <= 0x1fff) return (chrBank[5] << 10) | (addr & 0x03ff);
} else {
if(addr <= 0x03ff) return (chrBank[2] << 10) | (addr & 0x03ff);
if(addr <= 0x07ff) return (chrBank[3] << 10) | (addr & 0x03ff);
if(addr <= 0x0bff) return (chrBank[4] << 10) | (addr & 0x03ff);
if(addr <= 0x0fff) return (chrBank[5] << 10) | (addr & 0x03ff);
if(addr <= 0x17ff) return (chrBank[0] << 10) | (addr & 0x07ff);
if(addr <= 0x1fff) return (chrBank[1] << 10) | (addr & 0x07ff);
}
}
auto addrCIRAM(uint addr) const -> uint {
if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff);
if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff);
}
auto readRAM(uint addr) -> uint8 {
if(ramEnable == false) return cpu.mdr();
if(ramReadable[0] == false && ramReadable[1] == false) return cpu.mdr();
bool region = addr & 0x0200;
if(ramReadable[region] == false) return 0x00;
return board.prgram.read((region * 0x0200) + (addr & 0x01ff));
}
auto writeRAM(uint addr, uint8 data) -> void {
if(ramEnable == false) return;
bool region = addr & 0x0200;
if(ramWritable[region] == false) return;
return board.prgram.write((region * 0x0200) + (addr & 0x01ff), data);
}
auto writeIO(uint addr, uint8 data) -> void {
switch(addr & 0xe001) {
case 0x8000:
chrMode = data & 0x80;
prgMode = data & 0x40;
ramEnable = data & 0x20;
bankSelect = data & 0x07;
if(ramEnable == false) {
for(auto &n : ramReadable) n = false;
for(auto &n : ramWritable) n = false;
}
break;
case 0x8001:
switch(bankSelect) {
case 0: chrBank[0] = data & ~1; break;
case 1: chrBank[1] = data & ~1; break;
case 2: chrBank[2] = data; break;
case 3: chrBank[3] = data; break;
case 4: chrBank[4] = data; break;
case 5: chrBank[5] = data; break;
case 6: prgBank[0] = data & 0x3f; break;
case 7: prgBank[1] = data & 0x3f; break;
}
break;
case 0xa000:
mirror = data & 0x01;
break;
case 0xa001:
if(ramEnable == false) break;
ramReadable[1] = data & 0x80;
ramWritable[1] = data & 0x40;
ramReadable[0] = data & 0x20;
ramWritable[0] = data & 0x10;
break;
case 0xc000:
irqLatch = data;
break;
case 0xc001:
irqCounter = 0;
break;
case 0xe000:
irqEnable = false;
irqLine = 0;
break;
case 0xe001:
irqEnable = true;
break;
}
}
auto power() -> void {
}
auto reset() -> void {
chrMode = 0;
prgMode = 0;
ramEnable = 0;
bankSelect = 0;
for(auto& n : prgBank) n = 0;
for(auto& n : chrBank) n = 0;
mirror = 0;
for(auto& n : ramReadable) n = 0;
for(auto& n : ramWritable) n = 0;
irqLatch = 0;
irqCounter = 0;
irqEnable = 0;
irqDelay = 0;
irqLine = 0;
chrAbus = 0;
}
auto serialize(serializer& s) -> void {
s.integer(chrMode);
s.integer(prgMode);
s.integer(ramEnable);
s.integer(bankSelect);
for(auto& n : prgBank) s.integer(n);
for(auto& n : chrBank) s.integer(n);
s.integer(mirror);
for(auto& n : ramReadable) s.integer(n);
for(auto& n : ramWritable) s.integer(n);
s.integer(irqLatch);
s.integer(irqCounter);
s.integer(irqEnable);
s.integer(irqDelay);
s.integer(irqLine);
s.integer(chrAbus);
}
bool chrMode;
bool prgMode;
bool ramEnable;
uint3 bankSelect;
uint8 prgBank[2];
uint8 chrBank[6];
bool mirror;
bool ramReadable[2];
bool ramWritable[2];
uint8 irqLatch;
uint8 irqCounter;
bool irqEnable;
uint irqDelay;
bool irqLine;
uint16 chrAbus;
};