7e805d0a00a3

Proof and publish
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Thu, 05 Jan 2017 16:39:56 +0000
parents 12929efa02b5
children d9aba755de81
branches/tags (none)
files content/blog/2017/01/chip8-debugging-infrastructure.markdown

Changes

--- a/content/blog/2017/01/chip8-debugging-infrastructure.markdown	Thu Jan 05 13:17:43 2017 +0000
+++ b/content/blog/2017/01/chip8-debugging-infrastructure.markdown	Thu Jan 05 16:39:56 2017 +0000
@@ -1,8 +1,8 @@
 +++
 title = "CHIP-8 in Common Lisp: Debugging Infrastructure"
 snip = "What's happening inside this computer?"
-date = 2017-01-03T18:50:00Z
-draft = true
+date = 2017-01-05T16:40:00Z
+draft = false
 
 +++
 
@@ -39,8 +39,8 @@
 All information about the state of the debugger (e.g. breakpoints, pause status,
 etc) will be stored in a separate debugger data structure.  We'll define a small
 API for interacting with this structure.  The `chip` struct will have
-a `debugger` slot and will use the debugger API to interact with it.  Later on,
-the graphical debugger UI will also use this API.
+a `debugger` slot and will use the debugger API to interact with it.  Later the
+graphical debugger UI will also use this API.
 
 ## The Debugger Data Structure
 
@@ -84,21 +84,24 @@
 ```lisp
 (defun debugger-pause (debugger)
   (with-debugger (debugger)
-    (setf paused t print-needed t)))
+    (setf paused t)))
 
 (defun debugger-unpause (debugger)
   (with-debugger (debugger)
-    (setf paused nil print-needed nil)))
-
-(defun debugger-toggle-pause (debugger)
-  (if (debugger-paused debugger)
-    (debugger-unpause debugger)
-    (debugger-pause debugger)))
+    (setf paused nil)))
 
 (defun debugger-paused-p (debugger)
   (debugger-paused debugger))
+
+(defun debugger-toggle-pause (debugger)
+  (if (debugger-paused-p debugger)
+    (debugger-unpause debugger)
+    (debugger-pause debugger)))
 ```
 
+Notice how `debugger-toggle-pause` uses the lower-level API functions instead of
+directly modifying the slot.  This will become important shortly.
+
 Now we need to start modifying the emulator itself to pause execution when the
 debugger is paused.  Unfortunately this is going to be pretty invasive, but
 I don't think there's much of a way around that.
@@ -166,7 +169,7 @@
 (define-override (screen key-release-event) (ev)
   (let* ((key (q+:key ev))
          (pad-key (pad-key-for key))
-         (debugger (chip8::chip-debugger chip)))
+         (debugger (chip8::chip-debugger chip))) ; NEW
     (if pad-key
       (chip8::keyup chip pad-key)
       (qtenumcase key
@@ -228,6 +231,11 @@
       (t t))))
 ```
 
+I didn't name it with a `-p` suffix because although it qualifies as a predicate
+according to the Common Lisp spec ("a function that returns a generalized
+boolean as its first value") it has side effects, and I generally don't expect
+predicates to modify state.
+
 We can wire this into `emulate-cycle`, replacing the vanilla
 `debugger-paused-p`:
 
@@ -266,8 +274,11 @@
 ```
 
 Now we can walk through the code one instruction at a time by pausing the
-emulator and hitting `F7` to take a step.  This is great, but is pretty useless
-unless we can also see what instruction is about to run.
+emulator and hitting `F7` to take a step.  I picked `F7` because it matches the
+"take step" key for another emulator I use.
+
+This is all great, but pretty useless unless we can also see what instruction is
+about to run.
 
 ## Printing
 
@@ -334,6 +345,9 @@
       (t t))))
 ```
 
+We didn't have to touch `debugger-toggle-pause` because it uses the lower-level
+API functions, so everything works properly.
+
 Now we can implement `debugger-arrive`:
 
 ```lisp
@@ -396,10 +410,10 @@
     nil))
 ```
 
-Note that we use our own `debugger-pause` API function here to make sure we
-handle setting the `paused` and `awaiting-arrival` slots properly.  Now we can
-modify `debugger-check-wait` to use this function.  We'll also need to update it
-to take the current instruction's address:
+Note that we use the `debugger-pause` API function here to make sure we handle
+setting the `paused` and `awaiting-arrival` slots properly.  Now we can modify
+`debugger-check-wait` to use this function.  We'll also need to update it to
+take the current instruction's address:
 
 ```lisp
                                      ; NEW