From 7263041f3a87cbcf7aba30edf107594cdc818ffe Mon Sep 17 00:00:00 2001
From: adelikat <adelikat@tasvideos.org>
Date: Sun, 18 Sep 2016 13:32:58 -0400
Subject: [PATCH] Start mapper 199, everything seems to be working except chr
 mapping

---
 Assets/gamedb/gamedb.txt                      |  3 +
 .../BizHawk.Emulation.Cores.csproj            |  1 +
 .../Nintendo/NES/Boards/MMC3_family/MMC3.cs   | 25 +++++-
 .../NES/Boards/MMC3_family/Mapper199.cs       | 84 +++++++++++++++++++
 4 files changed, 110 insertions(+), 3 deletions(-)
 create mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper199.cs

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 @@
     <Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper195.cs" />
     <Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper196.cs" />
     <Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper197.cs" />
+    <Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper199.cs" />
     <Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper205.cs" />
     <Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper208.cs" />
     <Compile Include="Consoles\Nintendo\NES\Boards\MMC3_family\Mapper219.cs" />
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);
+		}
+	}
+}