diff --git a/Assets/gamedb/gamedb.txt b/Assets/gamedb/gamedb.txt
index 7349c4b5fb..32c4e3c4d9 100644
--- a/Assets/gamedb/gamedb.txt
+++ b/Assets/gamedb/gamedb.txt
@@ -149,6 +149,9 @@ sha1:F99E8B7C7A2174BF0B2330F5457AEE478A938C93 G Captain Tsubasa Vol. II - Super
sha1:9958BED493E8C5727F96937BF254AC33FA3BCF81 G Captain Tsubasa Vol. II - Super Striker (Ch) [a2] NES board=MAPPER195
sha1:B4AA3F10908DC3D6B8152F5DEB1B8543B8B46BF6 G Captain Tsubasa Vol. II - Super Striker (Ch) [a3] NES board=MAPPER195
sha1:60FC5FA5B5ACCAF3AEFEBA73FC8BFFD3C4DAE558 G Pegasus 5-in-1 (Golden Five) NES board=MAPPER104
+sha1:6282051DA49C286863463AF105F851AACF896563 G San Guo Zhi 2 (Ch) NES board=MAPPER199
+sha1:71234F9DCA4C31B4E9F0719425963878F3F045C9 G Dragon Ball Z II - Gekishin Freeza!! (Ch) NES board=MAPPER199
+sha1:A907E600CEDA175ECD115B406B28155397A4C1FA G Dragon Ball Z Gaiden - Saiya Jin Zetsumetsu Keikaku (Ch) NES board=MAPPER199
;;;;;;;;;;;;;;;;;;;-----------------------------------------------------------------------
diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index 20b3f2dc7a..c2537cbf19 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -688,6 +688,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 08bd3def00..acd448b27f 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
@@ -59,11 +59,25 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
prg_regs_8k.Dispose();
}
- public NES.NESBoardBase.EMirrorType MirrorType { get { return mirror == 0 ? NES.NESBoardBase.EMirrorType.Vertical : NES.NESBoardBase.EMirrorType.Horizontal; } }
+ public NES.NESBoardBase.EMirrorType MirrorType
+ {
+ get
+ {
+ switch (mirror)
+ {
+ default:
+ case 0: return NES.NESBoardBase.EMirrorType.Vertical;
+ case 1: return NES.NESBoardBase.EMirrorType.Horizontal;
+ case 2: return NES.NESBoardBase.EMirrorType.OneScreenA;
+ case 3: return NES.NESBoardBase.EMirrorType.OneScreenB;
+ }
+ }
+ }
protected NES.NESBoardBase board;
public MMC3(NES.NESBoardBase board, int num_prg_banks)
{
+ MirrorMask = 1;
this.board = board;
if (board.Cart.chips.Contains("MMC3A")) MMC3Type = EMMC3Type.MMC3A;
else if (board.Cart.chips.Contains("MMC3B")) MMC3Type = EMMC3Type.MMC3BSharp;
@@ -158,11 +172,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
board.SyncIRQ(irq_pending);
}
+ public byte cmd;
+
+ public int MirrorMask { get; set; }
+
public void WritePRG(int addr, byte value)
{
switch (addr & 0x6001)
{
case 0x0000: //$8000
+ cmd = value;
chr_mode = value.Bit(7);
prg_mode = value.Bit(6);
reg_addr = (value & 7);
@@ -173,8 +192,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
Sync();
break;
case 0x2000: //$A000
- //mirroring
- mirror = (byte)(value & 1);
+ //mirroring
+ mirror = (byte)(value & MirrorMask);
board.SetMirrorType(MirrorType);
break;
case 0x2001: //$A001
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper199.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper199.cs
new file mode 100644
index 0000000000..42bdc7ad07
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper199.cs
@@ -0,0 +1,84 @@
+using BizHawk.Common;
+
+namespace BizHawk.Emulation.Cores.Nintendo.NES
+{
+ public sealed class Mapper199 : MMC3Board_Base
+ {
+ private ByteBuffer exRegs = new ByteBuffer(4);
+
+ public override bool Configure(NES.EDetectionOrigin origin)
+ {
+ switch (Cart.board_type)
+ {
+ case "MAPPER199":
+ break;
+ default:
+ return false;
+ }
+
+ exRegs[0] = (byte)(Cart.prg_size / 8 - 2);
+ exRegs[1] = (byte)(Cart.prg_size / 8 - 1);
+ exRegs[2] = 1;
+ exRegs[3] = 3;
+
+ BaseSetup();
+ mmc3.MirrorMask = 3;
+ return true;
+ }
+
+ public override void SyncState(Serializer ser)
+ {
+ base.SyncState(ser);
+ ser.Sync("exRegs", ref exRegs);
+ }
+
+ protected override int Get_CHRBank_1K(int addr)
+ {
+ if (addr < 0x400)
+ {
+ return mmc3.regs[0];
+ }
+ else if (addr < 0x800)
+ {
+ return exRegs[2];
+ }
+ else if (addr < 0xC00)
+ {
+ return mmc3.regs[1];
+ }
+ else if (addr < 0x1000)
+ {
+ return exRegs[3];
+ }
+
+ return base.Get_CHRBank_1K(addr);
+ }
+
+ protected override int Get_PRGBank_8K(int addr)
+ {
+ if (addr >= 0x4000 && addr < 0x6000)
+ {
+ return exRegs[0];
+ }
+ else if (addr >= 0x6000)
+ {
+ return exRegs[1];
+ }
+
+ return base.Get_PRGBank_8K(addr);
+ }
+
+ public override void WritePRG(int addr, byte value)
+ {
+ if (addr == 1)
+ {
+ if ((mmc3.cmd & 0x8) > 0)
+ {
+ exRegs[mmc3.cmd & 3] = value;
+ }
+ }
+
+ base.WritePRG(addr, value);
+ }
+ }
+}