 //
 
 import Foundation
+
+// Adapted from "A Software Model of the CIA6526" by Wolfgang Lorenz http://ist.uwaterloo.ca/~schepers/MJK/cia6526.html
+private struct CIATimerState {
+    
+    private struct CIATimerStateFlags {
+        private static let Count0: UInt8 = 0x01
+        private static let Count1: UInt8 = 0x02
+        private static let Count2: UInt8 = 0x04
+        private static let Count3: UInt8 = 0x08
+        private static let Load0: UInt8 = 0x10
+        private static let Load1: UInt8 = 0x20
+        private static let Load2: UInt8 = 0x40
+    }
+    
+    private var delay: UInt8 = 0
+    private var feed: UInt8 = 0
+    
+    mutating func cycle() {
+        delay = ((delay << 1) & ~(CIATimerStateFlags.Count0 | CIATimerStateFlags.Load0)) | feed
+    }
+    
+    func shouldDecrement() -> Bool {
+        return delay & CIATimerStateFlags.Count3 != 0
+    }
+    
+    func shouldOutput() -> Bool {
+        return delay & CIATimerStateFlags.Count2 != 0
+    }
+    
+    mutating func start() {
+        delay |= CIATimerStateFlags.Count1 | CIATimerStateFlags.Count0
+        feed |= CIATimerStateFlags.Count0
+    }
+    
+    mutating func stop() {
+        delay &= ~(CIATimerStateFlags.Count1 | CIATimerStateFlags.Count0)
+        feed &= ~CIATimerStateFlags.Count0
+    }
+    
+    mutating func stopOneShot() {
+        delay &= ~(CIATimerStateFlags.Count2 | CIATimerStateFlags.Count1 | CIATimerStateFlags.Count0)
+        feed &= ~CIATimerStateFlags.Count0
+    }
+    
+    mutating func setSkipNextClock() {
+        delay &= ~CIATimerStateFlags.Count2
+    }
+    
+    func shouldLoad() -> Bool {
+        return delay & CIATimerStateFlags.Load1 != 0
+    }
+    
+    mutating func setLoadNextCycle() {
+        delay |= CIATimerStateFlags.Load0
+    }
+    
+    mutating func setLoadThisCycle() {
+        delay |= CIATimerStateFlags.Load1
+    }
+    
+}
 
 internal struct CIAState: ComponentState {
     

        case 0x05:
            state.latchA = (UInt16(byte) << 8) | (state.latchA & 0xFF);
            if state.cra & 0x01 == 0 {
                state.counterA = state.latchA
            }
        case 0x06:
            state.latchB = (state.latchB & 0xFF00) | UInt16(byte)
        case 0x07:
            state.latchB = (UInt16(byte) << 8) | (state.latchB & 0xFF);
            if state.crb & 0x01 == 0 {
                state.counterB = state.latchB
            }
        case 0x08:
            let value = byte & 0x0F

        if state.pb6Pulse {
            state.pb6Pulse = false
        }
        if state.timerAState.shouldDecrement() {
            state.counterA = state.counterA &- 1
        }
        if state.counterA == 0 && state.timerAState.shouldOutput() {
            if state.cra & 0x08 != 0 {
                state.cra &= ~0x01
                state.timerAState.stopOneShot()
            }
            state.icr |= 0x01
            if state.imr & 0x01 != 0 {
                state.interruptDelay = 1
            }
            state.pb6Toggle = !state.pb6Toggle
            state.pb6Pulse = true
            state.timerAState.setLoadThisCycle()
        }
        if state.timerAState.shouldLoad() {
            state.counterA = state.latchA
            state.timerAState.setSkipNextClock()
        }
        state.timerAState.cycle()
        if state.pb7Pulse {
            state.pb7Pulse = false
        }
        if state.timerBState.shouldDecrement() {
            state.counterB = state.counterB &- 1
        }
        if state.counterB == 0 && state.timerBState.shouldOutput() {
            if state.crb & 0x08 != 0 {
                state.crb &= ~0x01
                state.timerBState.stopOneShot()
            }
            state.icr |= 0x02
            if state.imr & 0x02 != 0 {
                state.interruptDelay = 1
            }
            state.pb7Toggle = !state.pb7Toggle
            state.pb7Pulse = true
            state.timerBState.setLoadThisCycle()
        }
        if state.timerBState.shouldLoad() {
            state.counterB = state.latchB
            state.timerBState.setSkipNextClock()
        }
        state.timerBState.cycle()
        if state.interruptDelay == 0 {
            state.icr |= 0x80
            state.interruptDelay = -1
