diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index 1b5269469b..8c4a218d52 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -221,6 +221,7 @@ Code + Code diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NanJing.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NanJing.cs new file mode 100644 index 0000000000..da32726c4f --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NanJing.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + public class NanJing : NES.NESBoardBase + { + /* + * China Pirate Stuff. Not very tested. + * + * switches prg in 32K blocks, uses exp space for io ports + * 8k wram, 8k vram, supports swapping 4k blocks of vram at scanline 128 + * + * TODO: The mapper telepathically switches VRAM based on scanline. + * For more accurate emulation, the actual method used to count scanlines + * (MMC3?) must be implemented. + */ + + // config + int prg_mask; + + // state + byte reg0 = 0; + byte reg1 = 0xff; + int prg = 15; + byte security = 0; + bool trigger = false; + bool strobe = true; + + + public override bool Configure(NES.EDetectionOrigin origin) + { + switch (Cart.board_type) + { + case "MAPPER163": + AssertChr(0); AssertVram(8); AssertWram(8); + break; + + default: + return false; + } + prg_mask = (Cart.prg_size / 32) - 1; + SetMirrorType(Cart.pad_h, Cart.pad_v); + return true; + } + + public override byte ReadPRG(int addr) + { + return ROM[(prg << 15) | addr]; + } + + /* + public override void WritePRG(int addr, byte value) + { + }*/ + + public override byte ReadEXP(int addr) + { + if (addr >= 0x1000) + { + switch (addr & 0x3700) + { + case 0x1100: + return security; + case 0x1500: + if (trigger) + return security; + else + return 0; + default: + return 4; + } + } + else + return 0; + } + + public override void WriteEXP(int addr, byte value) + { + if (addr == 0x1101) + { + if (strobe && value == 0) + trigger ^= true; + strobe = (value != 0); + } + else if (addr == 0x1100) + { + if (value == 6) + prg = 3; + } + else + { + switch (addr & 0x3300) + { + case 0x1000: + reg1 = value; + prg = (reg1 & 0xf) | (reg0 << 4) & prg_mask; + break; + case 0x1200: + reg0 = value; + prg = (reg1 & 0xf) | (reg0 << 4) & prg_mask; + break; + case 0x1300: + security = value; + break; + } + } + } + + /* + public override byte ReadWRAM(int addr) + { + return base.ReadWRAM(addr); + } + + public override void WriteWRAM(int addr, byte value) + { + base.WriteWRAM(addr, value); + }*/ + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + if ((reg1 & 0x80) != 0) + { + if (NES.ppu.ppur.status.sl <= 128) + return VRAM[addr & 0xfff]; + else + return VRAM[(addr & 0xfff) + 0x1000]; + } + else + return VRAM[addr]; + } + else + return base.ReadPPU(addr); + } + + public override void WritePPU(int addr, byte value) + { + if (addr < 0x2000) + { + if ((reg1 & 0x80) != 0 && NES.ppu.ppur.status.rendering) + { + if (NES.ppu.ppur.status.sl <= 128) + VRAM[addr & 0xfff] = value; + else + VRAM[(addr & 0xfff) + 0x1000] = value; + } + else + VRAM[addr] = value; + } + else + base.WritePPU(addr, value); + } + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + ser.Sync("reg0", ref reg0); + ser.Sync("reg1", ref reg1); + ser.Sync("prg", ref prg); + ser.Sync("security", ref security); + ser.Sync("trigger", ref trigger); + ser.Sync("strobe", ref strobe); + } + } +}