using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES { internal sealed class Mapper142 : NesBoardBase { private byte[] _reg = new byte[8]; private byte _cmd; private int _lastBank; private bool _isIrqUsed; private byte _irqA; private int _irqCount; public override bool Configure(EDetectionOrigin origin) { switch (Cart.BoardType) { case "MAPPER142": case "UNIF_UNL-KS7032": break; default: return false; } SetMirrorType(EMirrorType.Horizontal); _lastBank = Cart.PrgSize / 8 - 1; return true; } public override void SyncState(Serializer ser) { base.SyncState(ser); ser.Sync(nameof(_reg), ref _reg, false); ser.Sync(nameof(_cmd), ref _cmd); ser.Sync(nameof(_lastBank), ref _lastBank); ser.Sync(nameof(_isIrqUsed), ref _isIrqUsed); ser.Sync(nameof(_irqA), ref _irqA); ser.Sync(nameof(_irqCount), ref _irqCount); } public override byte ReadWram(int addr) { return Rom[(_reg[4] << 13) + (addr & 0x1FFF)]; } public override byte ReadPrg(int addr) { if (addr < 0x2000) { return Rom[(_reg[1] << 13) + (addr & 0x1FFF)]; } if (addr < 0x4000) { return Rom[(_reg[2] << 13) + (addr & 0x1FFF)]; } if (addr < 0x6000) { return Rom[(_reg[3] << 13) + (addr & 0x1FFF)]; } return Rom[(_lastBank << 13) + (addr & 0x1FFF)]; } public override void WriteExp(int addr, byte value) { Write(addr + 0x4000, value); } public override void WriteWram(int addr, byte value) { Write(addr + 0x6000, value); } public override void WritePrg(int addr, byte value) { Write(addr + 0x8000, value); } private void IRQHook(int a) { if (_irqA > 0) { _irqCount += a; if (_irqCount >= 0xFFFF) { _irqA = 0; _irqCount = 0; IrqSignal = true; } } } public override void ClockPpu() { IRQHook(1); } private void Write(int addr, byte value) { switch (addr & 0xF000) { case 0x8000: IrqSignal = false; _irqCount = (_irqCount & 0x000F) | (value & 0x0F); _isIrqUsed = true; break; case 0x9000: IrqSignal = false; _irqCount = (_irqCount & 0x00F0) | ((value & 0x0F) << 4); _isIrqUsed = true; break; case 0xA000: IrqSignal = false; _irqCount = (_irqCount & 0x0F00) | ((value & 0x0F) << 8); _isIrqUsed = true; break; case 0xB000: IrqSignal = false; _irqCount = (_irqCount & 0xF000) | (value << 12); _isIrqUsed = true; break; case 0xC000: if (_isIrqUsed) { IrqSignal = false; _irqA = 1; } break; case 0xE000: _cmd = (byte)(value & 7); break; case 0xF000: _reg[_cmd] = value; break; } } } }