using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES { // basic on FCEUX src internal sealed class Mapper150 : NesBoardBase { private byte[] latch = new byte[8]; private int cmd; private int chr_mask; private int prg_mask; public override bool Configure(EDetectionOrigin origin) { switch (Cart.BoardType) { case "MAPPER150": break; default: return false; } chr_mask = (Cart.ChrSize / 8) - 1; prg_mask = (Cart.PrgSize / 32) - 1; latch[1] = 3; return true; } public override void SyncState(Serializer ser) { base.SyncState(ser); ser.Sync(nameof(latch), ref latch, false); ser.Sync(nameof(cmd), ref cmd); } public override void WriteExp(int addr, byte value) { addr += 0x4000; Write(addr, value); SetMirroring(latch[2]); } public override void WriteWram(int addr, byte value) { addr += 0x6000; Write(addr, value); SetMirroring(latch[2]); } private void Write(int addr, byte value) { addr &= 0x4101; if (addr == 0x4100) { cmd = value & 7; } else { switch (cmd) { case 2: latch[0] = (byte)(value & 1); latch[3] = (byte)((value & 1) << 3); break; case 4: latch[4] = (byte)((value & 1) << 2); break; case 5: latch[0] = (byte)(value & 7); break; case 6: latch[1] = (byte)(value & 3); break; case 7: latch[2] = (byte)(value >> 1); break; } } } private void SetMirroring(byte val) { switch (val & 3) { case 0: SetMirrorType(EMirrorType.Horizontal); break; case 1: SetMirrorType(EMirrorType.Vertical); break; case 2: SetMirroring(0, 1, 1, 1); break; case 3: SetMirrorType(EMirrorType.OneScreenB); break; } } public override byte ReadExp(int addr) { byte ret; addr += 0x4000; if ((addr & 0x4100) == 0x4100) { ret = (byte)((~cmd) & 0x3F); } else { ret = NES.DB; } return ret; } public override byte ReadPrg(int addr) { return Rom[((latch[0] & prg_mask) << 15) + addr]; } public override byte ReadPpu(int addr) { if (addr < 0x2000) { int bank = latch[1] | latch[3] | latch[4]; bank &= chr_mask; return Vrom[(bank << 13) + addr]; } return base.ReadPpu(addr); } } }