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

126 lines
2.6 KiB
C++

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 {
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;
};