2011-10-01 12:06:48 +00:00
|
|
|
struct MMC3 : Chip {
|
2015-12-05 05:44:49 +00:00
|
|
|
MMC3(Board& board) : Chip(board) {
|
|
|
|
}
|
2011-10-01 12:06:48 +00:00
|
|
|
|
2015-12-05 05:44:49 +00:00
|
|
|
auto main() -> void {
|
2016-06-27 13:07:57 +00:00
|
|
|
if(irqDelay) irqDelay--;
|
|
|
|
cpu.irqLine(irqLine);
|
2016-02-09 11:51:12 +00:00
|
|
|
tick();
|
2011-10-01 12:06:48 +00:00
|
|
|
}
|
2015-12-05 05:44:49 +00:00
|
|
|
|
2016-06-27 13:07:57 +00:00
|
|
|
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;
|
2015-12-05 05:44:49 +00:00
|
|
|
}
|
2011-10-01 12:06:48 +00:00
|
|
|
}
|
2016-06-27 13:07:57 +00:00
|
|
|
irqDelay = 6;
|
2011-10-01 12:06:48 +00:00
|
|
|
}
|
2016-06-27 13:07:57 +00:00
|
|
|
chrAbus = addr;
|
2011-10-01 12:06:48 +00:00
|
|
|
}
|
2015-12-05 05:44:49 +00:00
|
|
|
|
2016-06-27 13:07:57 +00:00
|
|
|
auto addrPRG(uint addr) const -> uint {
|
2015-12-05 05:44:49 +00:00
|
|
|
switch((addr >> 13) & 3) {
|
|
|
|
case 0:
|
2016-06-27 13:07:57 +00:00
|
|
|
if(prgMode == 1) return (0x3e << 13) | (addr & 0x1fff);
|
|
|
|
return (prgBank[0] << 13) | (addr & 0x1fff);
|
2015-12-05 05:44:49 +00:00
|
|
|
case 1:
|
2016-06-27 13:07:57 +00:00
|
|
|
return (prgBank[1] << 13) | (addr & 0x1fff);
|
2015-12-05 05:44:49 +00:00
|
|
|
case 2:
|
2016-06-27 13:07:57 +00:00
|
|
|
if(prgMode == 0) return (0x3e << 13) | (addr & 0x1fff);
|
|
|
|
return (prgBank[0] << 13) | (addr & 0x1fff);
|
2015-12-05 05:44:49 +00:00
|
|
|
case 3:
|
|
|
|
return (0x3f << 13) | (addr & 0x1fff);
|
|
|
|
}
|
2011-10-01 12:06:48 +00:00
|
|
|
}
|
2015-12-05 05:44:49 +00:00
|
|
|
|
2016-06-27 13:07:57 +00:00
|
|
|
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);
|
2015-12-05 05:44:49 +00:00
|
|
|
} else {
|
2016-06-27 13:07:57 +00:00
|
|
|
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);
|
2011-11-04 11:57:54 +00:00
|
|
|
}
|
2015-12-05 05:44:49 +00:00
|
|
|
}
|
2011-11-04 11:57:54 +00:00
|
|
|
|
2016-06-27 13:07:57 +00:00
|
|
|
auto addrCIRAM(uint addr) const -> uint {
|
2015-12-05 05:44:49 +00:00
|
|
|
if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff);
|
|
|
|
if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff);
|
|
|
|
}
|
2011-11-04 11:57:54 +00:00
|
|
|
|
2016-06-27 13:07:57 +00:00
|
|
|
auto readRAM(uint addr) -> uint8 {
|
|
|
|
if(ramEnable) return board.prgram.data[addr & 0x1fff];
|
2015-12-05 05:44:49 +00:00
|
|
|
return 0x00;
|
|
|
|
}
|
2011-11-04 11:57:54 +00:00
|
|
|
|
2016-06-27 13:07:57 +00:00
|
|
|
auto writeRAM(uint addr, uint8 data) -> void {
|
|
|
|
if(ramEnable && !ramWriteProtect) board.prgram.data[addr & 0x1fff] = data;
|
2015-12-05 05:44:49 +00:00
|
|
|
}
|
2011-11-04 11:57:54 +00:00
|
|
|
|
2016-06-27 13:07:57 +00:00
|
|
|
auto writeIO(uint addr, uint8 data) -> void {
|
2015-12-05 05:44:49 +00:00
|
|
|
switch(addr & 0xe001) {
|
|
|
|
case 0x8000:
|
2016-06-27 13:07:57 +00:00
|
|
|
chrMode = data & 0x80;
|
|
|
|
prgMode = data & 0x40;
|
|
|
|
bankSelect = data & 0x07;
|
2015-12-05 05:44:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x8001:
|
2016-06-27 13:07:57 +00:00
|
|
|
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;
|
2015-12-05 05:44:49 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0xa000:
|
|
|
|
mirror = data & 0x01;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0xa001:
|
2016-06-27 13:07:57 +00:00
|
|
|
ramEnable = data & 0x80;
|
|
|
|
ramWriteProtect = data & 0x40;
|
2015-12-05 05:44:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0xc000:
|
2016-06-27 13:07:57 +00:00
|
|
|
irqLatch = data;
|
2015-12-05 05:44:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0xc001:
|
2016-06-27 13:07:57 +00:00
|
|
|
irqCounter = 0;
|
2015-12-05 05:44:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0xe000:
|
2016-06-27 13:07:57 +00:00
|
|
|
irqEnable = false;
|
|
|
|
irqLine = 0;
|
2015-12-05 05:44:49 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0xe001:
|
2016-06-27 13:07:57 +00:00
|
|
|
irqEnable = true;
|
2015-12-05 05:44:49 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto power() -> void {
|
|
|
|
}
|
2011-11-04 11:57:54 +00:00
|
|
|
|
2015-12-05 05:44:49 +00:00
|
|
|
auto reset() -> void {
|
2016-06-27 13:07:57 +00:00
|
|
|
chrMode = 0;
|
|
|
|
prgMode = 0;
|
|
|
|
bankSelect = 0;
|
|
|
|
prgBank[0] = 0;
|
|
|
|
prgBank[1] = 0;
|
|
|
|
chrBank[0] = 0;
|
|
|
|
chrBank[1] = 0;
|
|
|
|
chrBank[2] = 0;
|
|
|
|
chrBank[3] = 0;
|
|
|
|
chrBank[4] = 0;
|
|
|
|
chrBank[5] = 0;
|
2015-12-05 05:44:49 +00:00
|
|
|
mirror = 0;
|
2016-06-27 13:07:57 +00:00
|
|
|
ramEnable = 1;
|
|
|
|
ramWriteProtect = 0;
|
|
|
|
irqLatch = 0;
|
|
|
|
irqCounter = 0;
|
|
|
|
irqEnable = false;
|
|
|
|
irqDelay = 0;
|
|
|
|
irqLine = 0;
|
|
|
|
|
|
|
|
chrAbus = 0;
|
2015-12-05 05:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto serialize(serializer& s) -> void {
|
2016-06-27 13:07:57 +00:00
|
|
|
s.integer(chrMode);
|
|
|
|
s.integer(prgMode);
|
|
|
|
s.integer(bankSelect);
|
|
|
|
s.array(prgBank);
|
|
|
|
s.array(chrBank);
|
2015-12-05 05:44:49 +00:00
|
|
|
s.integer(mirror);
|
2016-06-27 13:07:57 +00:00
|
|
|
s.integer(ramEnable);
|
|
|
|
s.integer(ramWriteProtect);
|
|
|
|
s.integer(irqLatch);
|
|
|
|
s.integer(irqCounter);
|
|
|
|
s.integer(irqEnable);
|
|
|
|
s.integer(irqDelay);
|
|
|
|
s.integer(irqLine);
|
|
|
|
|
|
|
|
s.integer(chrAbus);
|
2011-11-04 11:57:54 +00:00
|
|
|
}
|
2011-10-01 12:06:48 +00:00
|
|
|
|
2016-06-27 13:07:57 +00:00
|
|
|
bool chrMode;
|
|
|
|
bool prgMode;
|
|
|
|
uint3 bankSelect;
|
|
|
|
uint8 prgBank[2];
|
|
|
|
uint8 chrBank[6];
|
2015-12-05 05:44:49 +00:00
|
|
|
bool mirror;
|
2016-06-27 13:07:57 +00:00
|
|
|
bool ramEnable;
|
|
|
|
bool ramWriteProtect;
|
|
|
|
uint8 irqLatch;
|
|
|
|
uint8 irqCounter;
|
|
|
|
bool irqEnable;
|
|
|
|
uint irqDelay;
|
|
|
|
bool irqLine;
|
|
|
|
|
|
|
|
uint16 chrAbus;
|
2011-10-01 12:06:48 +00:00
|
|
|
};
|