diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index 6c75b3a8b8..c38bd67ada 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -679,6 +679,7 @@
+
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3.cs
index 77265305e9..08bd3def00 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3.cs
@@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//state
int reg_addr;
public bool get_chr_mode { get { return chr_mode; } } // one of the pirate mappers needs this
- bool chr_mode;
+ public bool chr_mode;
bool prg_mode;
public ByteBuffer regs = new ByteBuffer(8);
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper123.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper123.cs
index 6894140673..69603575ab 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper123.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper123.cs
@@ -22,6 +22,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
return true;
}
+ public override void SyncState(Serializer ser)
+ {
+ base.SyncState(ser);
+ ser.Sync("expregs", ref EXPREGS);
+ }
+
public override void WriteEXP(int addr, byte value)
{
if (addr >= 0x1000)
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper187.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper187.cs
new file mode 100644
index 0000000000..41159496db
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper187.cs
@@ -0,0 +1,115 @@
+using BizHawk.Common;
+
+namespace BizHawk.Emulation.Cores.Nintendo.NES
+{
+ // Adapted from FCEUX src
+ public class Mapper187 : MMC3Board_Base
+ {
+ private ByteBuffer exRegs = new ByteBuffer(2);
+
+ private readonly byte[] prot_data = { 0x83, 0x83, 0x42, 0x00 };
+
+ public override bool Configure(NES.EDetectionOrigin origin)
+ {
+ switch (Cart.board_type)
+ {
+ case "MAPPER187":
+ break;
+ default:
+ return false;
+ }
+
+ BaseSetup();
+ return true;
+ }
+
+ public override void SyncState(Serializer ser)
+ {
+ base.SyncState(ser);
+ ser.Sync("expregs", ref exRegs);
+ }
+
+ public override void WritePRG(int addr, byte value)
+ {
+ if (addr == 0 || addr == 1)
+ {
+ exRegs[1] = value;
+ }
+
+ base.WritePRG(addr, value);
+ }
+
+ public override void WriteEXP(int addr, byte value)
+ {
+ if (addr == 0x1000) // 0x5000
+ {
+ exRegs[0] = value;
+ }
+
+ base.WriteEXP(addr, value);
+ }
+
+ public override void WriteWRAM(int addr, byte value)
+ {
+ if (addr == 0x6000)
+ {
+ exRegs[0] = value;
+ }
+
+ base.WriteWRAM(addr, value);
+ }
+
+ public override byte ReadEXP(int addr)
+ {
+ if (addr >= 0x1000)
+ {
+ return prot_data[exRegs[1] & 3];
+ }
+
+ return base.ReadEXP(addr);
+ }
+
+ private byte MMc3_cmd
+ {
+ get
+ {
+ return (byte)(mmc3.chr_mode ? 0x80 : 0);
+ }
+ }
+
+ protected override int Get_CHRBank_1K(int addr)
+ {
+ if ((addr & 0x1000) == ((MMc3_cmd & 0x80) << 5))
+ {
+ return base.Get_CHRBank_1K(addr) | 0100;
+ }
+
+ return base.Get_CHRBank_1K(addr);
+ }
+
+ public override byte ReadPRG(int addr)
+ {
+ if ((exRegs[0] & 0x80) > 0)
+ {
+ var bank = exRegs[0] & 0x1F;
+ if ((exRegs[0] & 0x20) > 0)
+ {
+ if ((exRegs[0] & 0x40) > 0)
+ {
+ return ROM[((bank >> 2) << 15) + addr];
+ }
+ else
+ {
+ return ROM[((bank >> 1) << 15) + addr]; // hacky! two mappers in one! need real hw carts to test
+ }
+ }
+ else
+ {
+ return ROM[(bank << 14) + (addr & 0x3FFF)];
+ }
+ }
+
+ return base.ReadPRG(addr);
+ }
+ }
+}