163 lines
3.4 KiB
C#
163 lines
3.4 KiB
C#
using BizHawk.Common;
|
|
using BizHawk.Common.NumberExtensions;
|
|
|
|
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|
{
|
|
// Supervision 16-in-1 [p1].nes
|
|
public sealed class Mapper053 : NES.NESBoardBase
|
|
{
|
|
private byte _reg0;
|
|
private byte _reg1;
|
|
|
|
private bool Prg16kMode { get { return _reg0.Bit(4); } }
|
|
|
|
public override bool Configure(NES.EDetectionOrigin origin)
|
|
{
|
|
switch (Cart.board_type)
|
|
{
|
|
case "MAPPER053":
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
SetMirrorType(Cart.pad_h, Cart.pad_v);
|
|
|
|
return true;
|
|
}
|
|
|
|
public override void SyncState(Serializer ser)
|
|
{
|
|
base.SyncState(ser);
|
|
ser.Sync("reg0", ref _reg0);
|
|
ser.Sync("reg1", ref _reg1);
|
|
}
|
|
|
|
private void SetMirroring()
|
|
{
|
|
bool mir = _reg0.Bit(5);
|
|
SetMirrorType(mir ? EMirrorType.Horizontal : EMirrorType.Vertical);
|
|
}
|
|
|
|
public override void WriteWRAM(int addr, byte value)
|
|
{
|
|
if (!_reg0.Bit(4))
|
|
{
|
|
_reg0 = value;
|
|
SetMirroring();
|
|
}
|
|
else
|
|
{
|
|
base.WriteWRAM(addr, value);
|
|
}
|
|
}
|
|
|
|
public override void WritePRG(int addr, byte value)
|
|
{
|
|
_reg1 = value;
|
|
}
|
|
|
|
public override byte ReadPRG(int addr)
|
|
{
|
|
if (Prg16kMode)
|
|
{
|
|
// First 32kb of PRG is for the intro game picker, 2 is to offset that
|
|
int bank = addr < 0x4000
|
|
? (((_reg0 & 0xF) << 3) | (_reg1 & 7)) + 2
|
|
: (((_reg0 & 0xF) << 3) | 7) + 2;
|
|
|
|
return ROM[(bank * 0x4000) + (addr & 0x3FFF)];
|
|
}
|
|
|
|
return base.ReadPRG(addr);
|
|
}
|
|
|
|
public override byte ReadWRAM(int addr)
|
|
{
|
|
// First 32kb of PRG is for the intro game picker, 4 is to offset that
|
|
int bank = (((_reg0 & 0xF) << 4) | 0xF) + 4;
|
|
return ROM[(bank * 0x2000) + (addr & 0x1FFF)];
|
|
}
|
|
}
|
|
|
|
// Supervision 16-in-1 [U][p1][!].unf
|
|
// Same as Mapper 53, except the 32kb PRG chip is at the end of the ROM space instead of the beginning
|
|
// These could have been combined to reduce some code, but at the cost of being more convoluted
|
|
public sealed class UNIF_BMC_Supervision16in1 : NES.NESBoardBase
|
|
{
|
|
private byte _reg0;
|
|
private byte _reg1;
|
|
|
|
private bool Prg16kMode { get { return _reg0.Bit(4); } }
|
|
|
|
public override bool Configure(NES.EDetectionOrigin origin)
|
|
{
|
|
switch (Cart.board_type)
|
|
{
|
|
case "UNIF_BMC-Supervision16in1":
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
SetMirrorType(Cart.pad_h, Cart.pad_v);
|
|
|
|
return true;
|
|
}
|
|
|
|
public override void SyncState(Serializer ser)
|
|
{
|
|
base.SyncState(ser);
|
|
ser.Sync("reg0", ref _reg0);
|
|
ser.Sync("reg1", ref _reg1);
|
|
}
|
|
|
|
private void SetMirroring()
|
|
{
|
|
bool mir = _reg0.Bit(5);
|
|
SetMirrorType(mir ? EMirrorType.Horizontal : EMirrorType.Vertical);
|
|
}
|
|
|
|
public override void WriteWRAM(int addr, byte value)
|
|
{
|
|
if (!_reg0.Bit(4))
|
|
{
|
|
_reg0 = value;
|
|
SetMirroring();
|
|
}
|
|
else
|
|
{
|
|
base.WriteWRAM(addr, value);
|
|
}
|
|
}
|
|
|
|
public override void WritePRG(int addr, byte value)
|
|
{
|
|
_reg1 = value;
|
|
}
|
|
|
|
public override byte ReadPRG(int addr)
|
|
{
|
|
if (Prg16kMode)
|
|
{
|
|
// First 32kb of PRG is for the intro game picker, 2 is to offset that
|
|
int bank = addr < 0x4000
|
|
? (((_reg0 & 0xF) << 3) | (_reg1 & 7))
|
|
: (((_reg0 & 0xF) << 3) | 7);
|
|
|
|
return ROM[(bank * 0x4000) + (addr & 0x3FFF)];
|
|
}
|
|
|
|
// Intro screen on the last 512kb chip
|
|
return ROM[0x200000 + addr];
|
|
}
|
|
|
|
public override byte ReadWRAM(int addr)
|
|
{
|
|
// First 32kb of PRG is for the intro game picker, 4 is to offset that
|
|
int bank = (((_reg0 & 0xF) << 4) | 0xF);
|
|
return ROM[(bank * 0x2000) + (addr & 0x1FFF)];
|
|
}
|
|
}
|
|
}
|