diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index 983afdc06b..fc15ae156a 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -617,6 +617,7 @@
+
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper150.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper150.cs
new file mode 100644
index 0000000000..31b6d8f4e3
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper150.cs
@@ -0,0 +1,134 @@
+using BizHawk.Common;
+
+namespace BizHawk.Emulation.Cores.Nintendo.NES
+{
+ // basic on FCEUX src
+ public sealed class Mapper150 : NES.NESBoardBase
+ {
+ private ByteBuffer latch = new ByteBuffer(8);
+ private int cmd;
+ private int chr_mask;
+ private int prg_mask;
+
+ public override bool Configure(NES.EDetectionOrigin origin)
+ {
+ switch (Cart.board_type)
+ {
+ case "MAPPER150":
+ break;
+ default:
+ return false;
+ }
+
+ chr_mask = (Cart.chr_size / 8) - 1;
+ prg_mask = (Cart.prg_size / 32) - 1;
+
+ latch[1] = 3;
+ return true;
+ }
+
+ public override void SyncState(Serializer ser)
+ {
+ base.SyncState(ser);
+ ser.Sync("latch", ref latch);
+ ser.Sync("cmd", ref cmd);
+ }
+
+ public override void WriteEXP(int addr, byte value)
+ {
+ addr += 0x4000;
+ Write(addr, value);
+ SetMirroring(latch[2]);
+ }
+
+ public override void WriteWRAM(int addr, byte value)
+ {
+ addr += 0x6000;
+ Write(addr, value);
+ SetMirroring(latch[2]);
+ }
+
+ private void Write(int addr, byte value)
+ {
+ addr &= 0x4101;
+ if (addr == 0x4100)
+ {
+ cmd = value & 7;
+ }
+ else
+ {
+ switch (cmd)
+ {
+ case 2:
+ latch[0] = (byte)(value & 1);
+ latch[3] = (byte)((value & 1) << 3);
+ break;
+ case 4:
+ latch[4] = (byte)((value & 1) << 2);
+ break;
+ case 5:
+ latch[0] = (byte)(value & 7);
+ break;
+ case 6:
+ latch[1] = (byte)(value & 3);
+ break;
+ case 7:
+ latch[2] = (byte)(value >> 1);
+ break;
+ }
+ }
+ }
+
+ private void SetMirroring(byte val)
+ {
+ switch (val & 3)
+ {
+ case 0:
+ SetMirrorType(EMirrorType.Horizontal);
+ break;
+ case 1:
+ SetMirrorType(EMirrorType.Vertical);
+ break;
+ case 2:
+ SetMirroring(0, 1, 1, 1);
+ break;
+ case 3:
+ SetMirrorType(EMirrorType.OneScreenB);
+ break;
+ }
+ }
+
+ public override byte ReadEXP(int addr)
+ {
+ byte ret;
+ addr += 0x4000;
+ if ((addr & 0x4100) == 0x4100)
+ {
+ ret = (byte)((~cmd) & 0x3F);
+ }
+ else
+ {
+ ret = NES.DB;
+ }
+
+ return ret;
+ }
+
+ public override byte ReadPRG(int addr)
+ {
+ return ROM[((latch[0] & prg_mask) << 15) + addr];
+ }
+
+ public override byte ReadPPU(int addr)
+ {
+ if (addr < 0x2000)
+ {
+ int bank = latch[1] | latch[3] | latch[4];
+ bank &= chr_mask;
+ return VROM[(bank << 13) + addr];
+ }
+
+ return base.ReadPPU(addr);
+ }
+ }
+}