ce548c40237a

Clean up
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Wed, 21 Dec 2016 12:36:37 -0500
parents c261dec56365
children 219d8676e914
branches/tags (none)
files content/blog/2016/12/chip8-cpu.markdown content/blog/2016/12/chip8-graphics.markdown

Changes

--- a/content/blog/2016/12/chip8-cpu.markdown	Wed Dec 21 12:00:08 2016 -0500
+++ b/content/blog/2016/12/chip8-cpu.markdown	Wed Dec 21 12:36:37 2016 -0500
@@ -1067,6 +1067,26 @@
         (<<_8 (register r))))
 ```
 
+**Update:** as [fernly pointed out][shift-hn], this [may not have been the
+original intended behavior][shift-yahoo].  If we want to make our emulator match
+the original intent, it's pretty simple:
+
+```lisp
+(define-instruction op-shr (_ rx ry)                 ;; SHR
+  (setf (values (register ry) flag)
+        (>>_8 (register rx))))
+
+(define-instruction op-shl (_ rx ry)                 ;; SHL
+  (setf (values (register ry) flag)
+        (<<_8 (register rx))))
+```
+
+But I suspect that this will probably break some ROMs that rely on the
+incorrectly-documented behavior.
+
+[shift-hn]: https://news.ycombinator.com/item?id=13217352
+[shift-yahoo]: https://groups.yahoo.com/neo/groups/rcacosmac/conversations/topics/328
+
 ### Logical Operations
 
 Next up are the logical `AND`/`OR`/`XOR` instructions.  We could define these
--- a/content/blog/2016/12/chip8-graphics.markdown	Wed Dec 21 12:00:08 2016 -0500
+++ b/content/blog/2016/12/chip8-graphics.markdown	Wed Dec 21 12:36:37 2016 -0500
@@ -208,7 +208,7 @@
 draws sprites.  The instruction itself will delegate to a helper function:
 
 ```lisp
-(define-instruction op-draw (_ rx ry size)              ;; DRW Vx, Vy, size
+(define-instruction op-draw (_ rx ry size)       ;; DRW Vx, Vy, size
   (draw-sprite chip (register rx) (register ry) size))
 ```
 
@@ -292,22 +292,21 @@
 
 ```lisp
 (defun-inline wrap (chip x y)
-  (cond
-    ((chip-screen-wrapping-enabled chip)
-     (values (mod x +screen-width+)
-             (mod y +screen-height+)
-             t))
-    ((and (in-range-p 0 x +screen-width+)
-          (in-range-p 0 y +screen-height+))
-     (values x y t))
-    (t (values nil nil nil))))
+  (cond ((chip-screen-wrapping-enabled chip)
+         (values (mod x +screen-width+)
+                 (mod y +screen-height+)
+                 t))
+        ((and (in-range-p 0 x +screen-width+)
+              (in-range-p 0 y +screen-height+))
+         (values x y t))
+        (t (values nil nil nil))))
 ```
 
 `wrap` will take `x` and `y` coordinates and return three values:
 
 * The screen X coordinate to draw to (if any).
 * The screen Y coordinate to draw to (if any).
-* A boolean that will be `t` when the pixel should be draw, or `nil` if not.
+* A boolean that will be `t` when the pixel should be drawn, or `nil` if not.
 
 [`in-range-p`][in-range-p] is a predicate from my utility library that checks if
 `low <= val < high` (which is [often useful][dijkstra]).
@@ -369,6 +368,8 @@
   nil)
 ```
 
+`xor` is the exclusive-or variant of `and`/`or` from Alexandria.
+
 And we're finally done.  `draw-sprite` is 22 lines, which is getting a bit long
 by Lisp standards, so it might be worth breaking into separate functions.  But
 it's also the most performance-critical function in the emulator, so keeping it
@@ -538,7 +539,8 @@
   (let ((chip (screen-chip screen)))
     (when (chip8::chip-video-dirty chip)
       (setf (chip8::chip-video-dirty chip) nil)
-      (gl:tex-sub-image-2d :texture-2d 0 0 0 64 32 :luminance :unsigned-byte
+      (gl:tex-sub-image-2d :texture-2d 0 0 0 64 32
+                           :luminance :unsigned-byte
                            (chip8::chip-video chip))))
 
   ;; Draw the quad