8b67739b3eb8

Clean up key await functionality, add resetting
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sat, 19 Nov 2016 12:23:13 +0000
parents 8ca52e1d0bb0
children 11cac4bb8d4c 2f3e461098af
branches/tags (none)
files src/emulator.lisp src/gui.lisp

Changes

--- a/src/emulator.lisp	Sat Nov 19 11:57:42 2016 +0000
+++ b/src/emulator.lisp	Sat Nov 19 12:23:13 2016 +0000
@@ -94,8 +94,6 @@
   (keys (make-simple-array 'boolean 16)
         :type (basic-array boolean 16)
         :read-only t)
-  (awaiting-key nil
-                :type (or null (integer 0 15)))
   (video (make-simple-array 'fixnum (* 32 64))
          :type (basic-array fixnum #.(* 32 64))
          :read-only t)
@@ -111,7 +109,9 @@
            :adjustable nil
            :fill-pointer 0
            :element-type 'int12)
-         :type (stack 16))
+         :type (stack 16)
+         :read-only t)
+  (loaded-rom nil :type (or null string))
   (debugger (make-debugger) :type debugger :read-only t))
 
 (define-with-macro chip
@@ -122,8 +122,9 @@
   delay-timer sound-timer
   random-state
   video video-dirty
-  keys awaiting-key
+  keys
   stack
+  loaded-rom
   debugger)
 
 (define-with-macro debugger
@@ -366,11 +367,7 @@
 (declaim (ftype (function (chip (integer 0 (16)))) keydown keyup))
 
 (defun keydown (chip key)
-  (with-chip (chip)
-    (setf (aref keys key) t)
-    (when-let* ((waiting-for awaiting-key))
-      (setf (aref registers waiting-for) key
-            awaiting-key nil))))
+  (setf (aref (chip-keys chip) key) t))
 
 (defun keyup (chip key)
   (setf (aref (chip-keys chip) key) nil))
@@ -492,7 +489,18 @@
   (replace registers memory :end1 n :start2 index))
 
 (define-opcode op-ld-reg<key (_ r _ _)                  ;; LD Vx, Key (await)
-  (setf awaiting-key r))
+  ;; I'm unsure how this instruction is supposed to interact with the timers.
+  ;;
+  ;; Either the timers should continue to count down while we wait for a key, or
+  ;; they should pause while waiting, but I can't find anything in the docs that
+  ;; spells it out.
+  ;;
+  ;; This implementation chooses the former (timers keep running) for now.
+  (let ((key (position t keys)))
+    (if key
+      (setf (register r) key)
+      ;; If we don't have a key, just execute this instruction again next time.
+      (decf program-counter 2))))
 
 (define-opcode op-shr (_ r _ _)                         ;; SHR
   (let ((value (register r)))
@@ -527,12 +535,26 @@
 (defparameter *c* nil)
 
 
+(defun reset (chip)
+  (with-chip (chip)
+    (fill memory 0)
+    (fill registers 0)
+    (fill keys 0)
+    (fill video 0)
+    (load-font chip)
+    (replace memory (read-file-into-byte-vector loaded-rom)
+             :start1 #x200)
+    (setf clock 0
+          video-dirty t
+          program-counter #x200
+          delay-timer 0
+          sound-timer 0
+          (fill-pointer stack) 0))
+  (values))
+
 (defun load-rom (chip filename)
-  (fill (chip-memory chip) 0)
-  (load-font chip)
-  (replace (chip-memory chip) (read-file-into-byte-vector filename)
-           :start1 #x200)
-  (values))
+  (setf (chip-loaded-rom chip) filename)
+  (reset chip))
 
 (defun update-timers (chip)
   (with-chip (chip)
@@ -586,17 +608,16 @@
 (defun emulate-cycle (chip)
   (with-chip (chip)
     (debugger-print debugger chip)
-    (cond
-      ((debugger-should-wait-p debugger) (sleep 10/1000))
-      (awaiting-key (sleep 10/1000))
-      (t (let ((instruction (cat-bytes (aref memory program-counter)
-                                       (aref memory (1+ program-counter)))))
-           (zapf program-counter (chop 12 (+ % 2)))
-           (incf clock)
-           (when (zerop (mod clock +cycles-per-timer-tick+))
-             (update-timers chip))
-           (dispatch-instruction chip instruction)
-           (sleep (/ 1 +cycles-per-second+)))))
+    (if (debugger-should-wait-p debugger)
+      (sleep 10/1000)
+      (let ((instruction (cat-bytes (aref memory program-counter)
+                                    (aref memory (1+ program-counter)))))
+        (zapf program-counter (chop 12 (+ % 2)))
+        (incf clock)
+        (when (zerop (mod clock +cycles-per-timer-tick+))
+          (update-timers chip))
+        (dispatch-instruction chip instruction)
+        (sleep (/ 1 +cycles-per-second+))))
     nil))
 
 
--- a/src/gui.lisp	Sat Nov 19 11:57:42 2016 +0000
+++ b/src/gui.lisp	Sat Nov 19 12:23:13 2016 +0000
@@ -186,6 +186,9 @@
         ((q+:qt.key_space)
          (-> chip chip8::chip-debugger chip8::debugger-toggle-pause))
 
+        ((q+:qt.key_r)
+         (-> chip chip8::reset))
+
         ((q+:qt.key_f7)
          (-> chip chip8::chip-debugger chip8::debugger-step))