From 939de46905b09d3cc6f084d5e77788035bb29f6e Mon Sep 17 00:00:00 2001
From: alyosha-tas <alexei.f.k@gmail.com>
Date: Sun, 3 Feb 2019 10:13:51 -0600
Subject: [PATCH] A2600: fix HMove

---
 .../Consoles/Atari/2600/Tia/TIA.cs            | 75 +++++++++++++++----
 .../Consoles/Atari/2600/Tia/Tia.SyncState.cs  |  7 ++
 2 files changed, 68 insertions(+), 14 deletions(-)

diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs
index bb6aa0783d..49d42d352a 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs
@@ -97,6 +97,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 		private byte _hmp0Val;
 		private int _hmp1Delay;
 		private byte _hmp1Val;
+		private int _hmm0Delay;
+		private byte _hmm0Val;
+		private int _hmm1Delay;
+		private byte _hmm1Val;
+		private int _hmbDelay;
+		private byte _hmbVal;
 
 		private int _prg0Delay;
 		private int _prg1Delay;
@@ -104,6 +110,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 		private byte _prg1Val;
 
 		private bool _doTicks;
+		private bool hmove_cnt_up;
 
 		private byte _hsyncCnt;
 		private long _capChargeStart;
@@ -208,6 +215,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 			_hmp0Val = 0;
 			_hmp1Delay = 0;
 			_hmp1Val = 0;
+			_hmm0Delay = 0;
+			_hmm0Val = 0;
+			_hmm1Delay = 0;
+			_hmm1Val = 0;
+			_hmbDelay = 0;
+			_hmbVal = 0;
 
 			_prg0Delay = 0;
 			_prg1Delay = 0;
@@ -338,13 +351,43 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 			if (_hmp1Delay > 0)
 			{
 				_hmp1Delay++;
-				if (_hmp1Delay == 3)
+				if (_hmp1Delay == 4)
 				{
 					_hmp1Delay = 0;
 					_player1.HM = _hmp1Val;
 				}
 			}
 
+			if (_hmm0Delay > 0)
+			{
+				_hmm0Delay++;
+				if (_hmm0Delay == 4)
+				{
+					_hmm0Delay = 0;
+					_player0.Missile.Hm = _hmm0Val;
+				}
+			}
+
+			if (_hmm1Delay > 0)
+			{
+				_hmm1Delay++;
+				if (_hmm1Delay == 4)
+				{
+					_hmm1Delay = 0;
+					_player1.Missile.Hm = _hmm1Val;
+				}
+			}
+
+			if (_hmbDelay > 0)
+			{
+				_hmbDelay++;
+				if (_hmbDelay == 4)
+				{
+					_hmbDelay = 0;
+					_ball.HM = _hmbVal;
+				}
+			}
+
 			// Reset the RDY flag when we reach hblank
 			if (_hsyncCnt <= 0)
 			{
@@ -359,7 +402,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 			if (_hsyncCnt >= (_hmove.LateHBlankReset ? 76 : 68))
 			{
 				_doTicks = false;
-
+				
 				// TODO: Remove this magic number
 				if ((_hsyncCnt / 4) >= 37)
 				{
@@ -614,7 +657,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 					_hmove.HMoveCnt++;
 					_hmove.HMoveCnt %= 4;
 
-					if (_p0Stuff && _hsyncCnt % 4 == 0)
+					if (_p0Stuff)
 					{
 						_p0Stuff = false;
 
@@ -636,7 +679,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 						}
 					}
 
-					if (_p1Stuff && _hsyncCnt % 4 == 0)
+					if (_p1Stuff)
 					{
 						_p1Stuff = false;
 
@@ -658,7 +701,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 						}
 					}
 
-					if (_m0Stuff && _hsyncCnt % 4 == 0)
+					if (_m0Stuff)
 					{
 						_m0Stuff = false;
 
@@ -680,7 +723,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 						}
 					}
 
-					if (_m1Stuff && _hsyncCnt % 4 == 0)
+					if (_m1Stuff)
 					{
 						_m1Stuff = false;
 
@@ -702,7 +745,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 						}
 					}
 
-					if (_bStuff && _hsyncCnt % 4 == 0)
+					if (_bStuff)
 					{
 						_bStuff = false;
 
@@ -725,15 +768,15 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 					}
 				}
 
-				if (_hmove.HMoveDelayCnt < 5)
+				if (hmove_cnt_up)
 				{
 					_hmove.HMoveDelayCnt++;
 				}
 
-				if (_hmove.HMoveDelayCnt == 5)
+				if ((_hmove.HMoveDelayCnt >= 5) && hmove_cnt_up)
 				{
-					_hmove.HMoveDelayCnt++;
-					_hmove.HMoveCnt = 0;
+					hmove_cnt_up = false;
+					_hmove.HMoveCnt = 4;
 					_hmove.DecCntEnabled = true;
 
 					_hmove.test_count_p0 = 0;
@@ -1274,15 +1317,18 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 			}
 			else if (maskedAddr == 0x22) // HMM0
 			{
-				_player0.Missile.Hm = (byte)((value & 0xF0) >> 4);
+				_hmm0Val = (byte)((value & 0xF0) >> 4);
+				_hmm0Delay = 1;
 			}
 			else if (maskedAddr == 0x23) // HMM1
 			{
-				_player1.Missile.Hm = (byte)((value & 0xF0) >> 4);
+				_hmm1Val = (byte)((value & 0xF0) >> 4);
+				_hmm1Delay = 1;
 			}
 			else if (maskedAddr == 0x24) // HMBL
 			{
-				_ball.HM = (byte)((value & 0xF0) >> 4);
+				_hmbVal = (byte)((value & 0xF0) >> 4);
+				_hmbDelay = 1;
 			}
 			else if (maskedAddr == 0x25) // VDELP0
 			{
@@ -1307,6 +1353,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 			else if (maskedAddr == 0x2A) // HMOVE
 			{
 				_hmove.HMoveEnabled = true;
+				hmove_cnt_up = true;
 				_hmove.HMoveDelayCnt = 0;
 			}
 			else if (maskedAddr == 0x2B) // HMCLR
diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs
index 1f3807247a..8a67dc32d6 100644
--- a/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.SyncState.cs
@@ -44,6 +44,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 			ser.Sync("hmp0_val", ref _hmp0Val);
 			ser.Sync("hmp1_delay", ref _hmp1Delay);
 			ser.Sync("hmp1_val", ref _hmp1Val);
+			ser.Sync("hmm0_delay", ref _hmm0Delay);
+			ser.Sync("hmm0_val", ref _hmm0Val);
+			ser.Sync("hmm1_delay", ref _hmm1Delay);
+			ser.Sync("hmm1_val", ref _hmm1Val);
+			ser.Sync("hmb_delay", ref _hmbDelay);
+			ser.Sync("hmb_val", ref _hmbVal);
 
 			ser.Sync("PRG0_delay", ref _prg0Delay);
 			ser.Sync("PRG1_delay", ref _prg1Delay);
@@ -51,6 +57,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
 			ser.Sync("PRG1_val", ref _prg1Val);
 
 			ser.Sync("Ticks", ref _doTicks);
+			ser.Sync("hmove_cnt_up", ref hmove_cnt_up);
 
 			ser.Sync("VBlankDelay", ref _vblankDelay);
 			ser.Sync("VBlankValue", ref _vblankValue);