using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES { //generally mapper2 //Mega Man //Castlevania //Contra //Duck Tales //Metal Gear //TODO - look for a mirror=H UNROM--maybe there are none? this may be fixed to the board type. // why are there no bus conflicts in here??????? [NES.INESBoardImplPriority] public sealed class UxROM : NES.NESBoardBase { //configuration int prg_mask; int vram_byte_mask; Func adjust_prg; //state int prg; [MapperProp] public byte Dip_Switch_1; [MapperProp] public byte Dip_Switch_2; [MapperProp] public byte Dip_Switch_3; [MapperProp] public byte Dip_Switch_4; [MapperProp] public byte Dip_Switch_5; [MapperProp] public byte Dip_Switch_6; [MapperProp] public byte Dip_Switch_7; [MapperProp] public byte Dip_Switch_8; //the VS actually does have 2 KB of nametable address space //let's make the extra space here, instead of in the main NES to avoid confusion byte[] CIRAM_VS = new byte[0x800]; public override bool Configure(NES.EDetectionOrigin origin) { adjust_prg = (x) => x; //configure switch (Cart.board_type) { case "MAPPER002": AssertChr(0); Cart.vram_size = 8; break; case "NES-UNROM": //mega man case "HVC-UNROM": case "KONAMI-UNROM": case "NES-UNEPROM": // proto case "IREM-UNROM": case "TAITO-UNROM": AssertPrg(128); AssertChr(0); AssertVram(8); //AssertWram(0); //JJ - Tobidase Daisakusen Part 2 (J) includes WRAM break; case "HVC-UN1ROM": AssertPrg(128); AssertChr(0); AssertWram(0); AssertVram(8); adjust_prg = (x) => ((x >> 2) & 7); break; case "NES-UOROM": //paperboy 2 case "HVC-UOROM": case "JALECO-JF-15": case "JALECO-JF-18": AssertPrg(256); AssertChr(0); AssertVram(8); AssertWram(0); break; case "NES-UNROM_VS": AutoMapperProps.Apply(this); NES._isVS = true; break; default: return false; } //these boards always have 8KB of VRAM vram_byte_mask = (Cart.vram_size*1024) - 1; prg_mask = (Cart.prg_size / 16) - 1; SetMirrorType(Cart.pad_h, Cart.pad_v); return true; } public override byte ReadPRG(int addr) { int block = addr >> 14; int page = block == 1 ? prg_mask : prg; int ofs = addr & 0x3FFF; return ROM[(page << 14) | ofs]; } public override void WritePRG(int addr, byte value) { prg = adjust_prg(value) & prg_mask; } public override byte ReadPPU(int addr) { if (addr < 0x2000) { return VRAM[addr & vram_byte_mask]; } else { if (NES._isVS) { addr = addr - 0x2000; if (addr < 0x800) { return NES.CIRAM[addr]; } else { return CIRAM_VS[addr - 0x800]; } } else return base.ReadPPU(addr); } } public override void WritePPU(int addr, byte value) { if (addr < 0x2000) { VRAM[addr & vram_byte_mask] = value; } else if (NES._isVS) { // The game VS Castlevania apparently scans for more CIRAM then actually exists, so we have to mask out nonsensical values addr &= 0x2FFF; addr = addr - 0x2000; if (addr < 0x800) { NES.CIRAM[addr] = value; } else { CIRAM_VS[addr - 0x800] = value; } } else base.WritePPU(addr,value); } public override void SyncState(Serializer ser) { base.SyncState(ser); ser.Sync("prg", ref prg); if (NES.IsVS) { ser.Sync("VS_CIRAM", ref CIRAM_VS, false); ser.Sync("Dip_1", ref Dip_Switch_1); ser.Sync("Dip_2", ref Dip_Switch_2); ser.Sync("Dip_3", ref Dip_Switch_3); ser.Sync("Dip_4", ref Dip_Switch_4); ser.Sync("Dip_5", ref Dip_Switch_5); ser.Sync("Dip_6", ref Dip_Switch_6); ser.Sync("Dip_7", ref Dip_Switch_7); ser.Sync("Dip_8", ref Dip_Switch_8); } } } }