 (defn- VxVy [V x y]
   [(nth V x) (nth V y)])
 
-(defn- update-memory
+
+(defn- write-pc
+  [state pc]
+  (assoc-in state [:cpu :pc] pc))
+
+(defn- write-sp
+  [state sp]
+  (assoc-in state [:cpu :sp] sp))
+
+(defn- write-i
+  [state i]
+  (assoc-in state [:cpu :i] i))
+
+(defn- write-dt
+  [state dt]
+  (assoc-in state [:cpu :dt] dt))
+
+(defn- write-st
+  [state st]
+  (assoc-in state [:cpu :st] st))
+
+(defn- write-draw-flag
+  [state draw-flag]
+  (assoc-in state [:cpu :draw-flag] draw-flag))
+
+(defn- write-stack
+  ([{{:keys [stack]} :cpu :as state} idx val]
+   (write-stack state (assoc stack idx val)))
+  ([state stack]
+   (assoc-in state [:cpu :stack] stack)))
+
+(defn- write-memory
   ([{{:keys [memory]} :cpu :as state} arr start]
-   (update-memory state (assoc-in-range memory arr start)))
+   (write-memory state (assoc-in-range memory arr start)))
   ([state memory]
    (assoc-in state [:cpu :memory] memory)))
 
-(defn- update-pc
-  [state pc]
-  (assoc-in state [:cpu :pc] pc))
-
-(defn- update-sp
-  [state sp]
-  (assoc-in state [:cpu :sp] sp))
-
-(defn- update-i
-  [state i]
-  (assoc-in state [:cpu :i] i))
-
-(defn- update-dt
-  [state dt]
-  (assoc-in state [:cpu :dt] dt))
-
-(defn- update-st
-  [state st]
-  (assoc-in state [:cpu :st] st))
-
-(defn- update-draw-flag
-  [state draw-flag]
-  (assoc-in state [:cpu :draw-flag] draw-flag))
-
-(defn- update-stack
-  ([{{:keys [stack]} :cpu :as state} idx val]
-   (update-stack state (assoc stack idx val)))
-  ([state stack]
-   (assoc-in state [:cpu :stack] stack)))
-
-(defn- update-v
+(defn- write-v
   ([{{:keys [v]} :cpu :as state} x val]
-   (update-v state (assoc v x val)))
+   (write-v state (assoc v x val)))
   ([{{:keys [v]} :cpu :as state} val]
-   (assoc-in state [:cpu :v]
-             (if (sequential? val)
-               (assoc-in-range v val) val))))
-
+   (assoc-in state [:cpu :v] (assoc-in-range v val))))
 
 (def ^{:private true}
   default-state

  [{{:keys [v]} :cpu :as state} x]
  (let [Vx (nth v x)]
    (-> state
        (update-dt Vx)
        (update-pc 2))))

(defn opcode-FX18
  "Set sound timer = Vx."
  [{{:keys [v]} :cpu :as state} X]
  (let [Vx (nth v X)]
    (-> state
        (update-st Vx)
        (update-pc 2))))

(defn opcode-FX29
  "Set I = location of sprite for digit Vx."
  [{{:keys [v]} :cpu :as state} X]
  (let [Vx (nth v X)]
    (-> state
        (update-i (* 5 Vx))
        (update-pc 2))))

;; FIXME:
(defn opcode-FX33
  "Store BCD representation of Vx in memory locations I, I+1, I+2."
  [{{:keys [i v memory]} :cpu :as state} X]
  (let [Vx (nth v X)
        val (->bcd Vx)]
    (-> state
        (assoc-in [:cpu :memory]
                  (assoc-in-range memory val i))
        (assoc-in [:cpu :pc] 2))))

;; FIXME:
(defn opcode-FX55
  "Store registers V0 through Vx in memory starting at location I."
  [{{:keys [i v memory]} :cpu :as state} X]
  (-> state
      (assoc-in [:cpu :memory]
                (assoc-in-range memory (get-in-range v 0 (inc X)) i))
      (update-pc 2)
      ))

(defn opcode-FX65
  "Read registers V0 through Vx from memory starting at location I."
  [{{:keys [i v memory]} :cpu :as state} X]
  (-> state
      (update-v (get-in-range memory i (+ i X 1)))
      (update-pc 2)))

(defn opcode-FX1E
  "Set I = I + Vx."
  [{{:keys [i v]} :cpu :as state} x]
  (let [Vx (nth v x)]
    (-> state
        (update-i (+ i Vx))
        (update-pc 2))))

(defn initial-vm [state]


  "Load rom to memory. The program will be loaded start at 0x200."
  [state rom]
  (-> state
      (write-memory (vec rom) 0x200)))

;; FIXME:
(defn opcode-00E0
