From 394902f4099c6a01a423904f3b815972592651ca Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Sat, 18 Jun 2016 13:57:10 -0400
Subject: [PATCH] Switched to clocking the 6522 by the half-cycle. Very trivial
 test now passes.

---
 Components/6522/6522.hpp                      | 55 ++++++++++++-------
 Machines/Vic-20/Vic20.cpp                     |  4 +-
 .../Mac/Clock SignalTests/6522Tests.swift     | 17 ++++++
 .../Mac/Clock SignalTests/MOS6522Bridge.mm    |  2 +-
 4 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/Components/6522/6522.hpp b/Components/6522/6522.hpp
index 816f7ce8d..b0edbd770 100644
--- a/Components/6522/6522.hpp
+++ b/Components/6522/6522.hpp
@@ -144,30 +144,38 @@ template <class T> class MOS6522 {
 		{
 		}
 
-		void run_for_cycles(unsigned int number_of_cycles)
+		void run_for_half_cycles(unsigned int number_of_cycles)
 		{
-			_registers.timer[0] -= number_of_cycles;
-			_registers.timer[1] -= number_of_cycles;
-
-			if(!_registers.timer[1] && _timer_is_running[1])
+			while(number_of_cycles--)
 			{
-				_timer_is_running[1] = false;
-				_registers.interrupt_flags |= InterruptFlag::Timer2;
-				reevaluate_interrupts();
-			}
+				if(_is_phase2)
+				{
+					_registers.timer[0] --;
+					_registers.timer[1] --;
 
-			if(!_registers.timer[0] && _timer_is_running[0])
-			{
-				_registers.interrupt_flags |= InterruptFlag::Timer1;
-				reevaluate_interrupts();
+					if(!_registers.timer[1] && _timer_is_running[1])
+					{
+						_timer_is_running[1] = false;
+						_registers.interrupt_flags |= InterruptFlag::Timer2;
+						reevaluate_interrupts();
+					}
 
-				// TODO: reload shouldn't occur for a further 1.5 cycles
-				if(_registers.auxiliary_control&0x40)
-					_registers.timer[0] = _registers.timer_latch[0];
-				else
-					_timer_is_running[0] = false;
+					if(!_registers.timer[0] && _timer_is_running[0])
+					{
+						_registers.interrupt_flags |= InterruptFlag::Timer1;
+						reevaluate_interrupts();
+
+						// TODO: reload shouldn't occur for a further 1.5 cycles
+						if(_registers.auxiliary_control&0x40)
+							_registers.timer[0] = _registers.timer_latch[0];
+						else
+							_timer_is_running[0] = false;
+					}
+					// TODO: lots of other status effects
+				}
+
+				_is_phase2 ^= true;
 			}
-			// TODO: lots of other status effects
 		}
 
 		bool get_interrupt_line()
@@ -178,13 +186,18 @@ template <class T> class MOS6522 {
 
 		MOS6522() :
 			_timer_is_running{false, false},
-			_last_posted_interrupt_status(false)
+			_last_posted_interrupt_status(false),
+			_is_phase2(false)
 		{}
 
 	private:
-		// Intended to be overwritten
+		// Intended to be overridden
 		uint8_t get_port_input(int port)				{	return 0xff;	}
 		void set_port_output(int port, uint8_t value)	{}
+//		void set_interrupt_status(bool status)			{}
+
+		// Phase toggle
+		bool _is_phase2;
 
 		// Delegate and communications
 		bool _last_posted_interrupt_status;
diff --git a/Machines/Vic-20/Vic20.cpp b/Machines/Vic-20/Vic20.cpp
index 5a60dcc1d..71888551f 100644
--- a/Machines/Vic-20/Vic20.cpp
+++ b/Machines/Vic-20/Vic20.cpp
@@ -79,8 +79,8 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
 		}
 	}
 
-	_userPortVIA.run_for_cycles(1);
-	_keyboardVIA.run_for_cycles(1);
+	_userPortVIA.run_for_half_cycles(2);
+	_keyboardVIA.run_for_half_cycles(2);
 	return 1;
 }
 
diff --git a/OSBindings/Mac/Clock SignalTests/6522Tests.swift b/OSBindings/Mac/Clock SignalTests/6522Tests.swift
index 833d17621..567337c4a 100644
--- a/OSBindings/Mac/Clock SignalTests/6522Tests.swift	
+++ b/OSBindings/Mac/Clock SignalTests/6522Tests.swift	
@@ -10,4 +10,21 @@ import XCTest
 import Foundation
 
 class MOS6522Tests: XCTestCase {
+
+	private func with6522(action: (MOS6522Bridge) -> ()) {
+		let bridge = MOS6522Bridge()
+		action(bridge)
+	}
+
+	func testTimerCount() {
+		with6522 {
+			$0.setValue(10, forRegister: 4)
+			$0.setValue(0, forRegister: 5)
+
+			$0.runForHalfCycles(10)
+
+			XCTAssert($0.valueForRegister(4) == 5, "Low order byte of timer should be 5; was \($0.valueForRegister(4))")
+			XCTAssert($0.valueForRegister(5) == 0, "High order byte of timer should be 5; was \($0.valueForRegister(5))")
+		}
+	}
 }
diff --git a/OSBindings/Mac/Clock SignalTests/MOS6522Bridge.mm b/OSBindings/Mac/Clock SignalTests/MOS6522Bridge.mm
index 0f1a725ed..329dbb06a 100644
--- a/OSBindings/Mac/Clock SignalTests/MOS6522Bridge.mm	
+++ b/OSBindings/Mac/Clock SignalTests/MOS6522Bridge.mm	
@@ -49,7 +49,7 @@ class VanillaVIA: public MOS::MOS6522<VanillaVIA> {
 
 - (void)runForHalfCycles:(NSUInteger)numberOfHalfCycles
 {
-	_via.run_for_cycles(numberOfHalfCycles);
+	_via.run_for_half_cycles(numberOfHalfCycles);
 }
 
 @end