diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index 1fcad3e9b4..9198471301 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -167,6 +167,7 @@ + diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper168.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper168.cs new file mode 100644 index 0000000000..b337b423b1 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper168.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + // RacerMate II + // 64KB PRGROM, 64KB CHRRAM(!), CHRRAM is battry backed (!!) + // the "ram protect" function is not emulated. the notes i found said that it + // defaults to off, the control regs are write only, and cannot be reenabled. so... + + // todo: special controller, and IRQ is possibly wrong + public class Mapper168 : NES.NESBoardBase + { + int prg = 0; + int chr = 0; + int irqclock = 2048 * 3; + + public override bool Configure(NES.EDetectionOrigin origin) + { + switch (Cart.board_type) + { + case "MAPPER168": + case "UNL-RACERMATE": + break; + default: + return false; + } + AssertPrg(64); + Cart.chr_size = 0; //AssertChr(0); //shitty dumps + Cart.vram_size = 64; //AssertVram(64); //shitty dumps + AssertWram(0); + //AssertBattery(true); // battery is handled directly + SetMirrorType(Cart.pad_h, Cart.pad_v); + return true; + } + + public override byte ReadPRG(int addr) + { + if (addr >= 0x4000) + return ROM[addr + 0x8000]; + else + return ROM[addr + (prg << 14)]; + } + + // the chr reg on hardware is supposedly bitscrambled and then inverted from + // what would be expected. since it doesn't make a difference and i don't know + // of any clear source on what it's actually supposed to be, ignore. + int Scramble(int chr) + { + return chr; + } + + public override void WritePRG(int addr, byte value) + { + if (addr < 0x4000) + { + chr = value & 15; + prg = value >> 6 & 3; + } + else if (addr == 0x7080) // ack + IRQSignal = false; + else if (addr == 0x7000) // start count + irqclock = 0; + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x1000) + return VRAM[addr | Scramble(0) << 12]; + else if (addr < 0x2000) + return VRAM[(addr & 0xfff) | Scramble(chr) << 12]; + else + return base.ReadPPU(addr); + } + + public override void WritePPU(int addr, byte value) + { + if (addr < 0x1000) + VRAM[addr | Scramble(0) << 12] = value; + else if (addr < 0x2000) + VRAM[(addr & 0xfff) | Scramble(chr) << 12] = value; + else + base.WritePPU(addr, value); + } + + public override byte[] SaveRam { get { return VRAM; } } + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + ser.Sync("prg", ref prg); + ser.Sync("chr", ref chr); + ser.Sync("irqclock", ref irqclock); + } + + public override void ClockPPU() + { + if (irqclock == 2048 * 3 - 1) + { + irqclock++; + IRQSignal = true; + } + else if (irqclock < 2048 * 3 - 1) + { + irqclock++; + } + } + } +}