# HG changeset patch # User Steve Losh # Date 1479328902 0 # Node ID 5cfbf08cb54df4a821584041e72ba999cad5f934 # Parent f7f47291a61aca73fb06dffeb1d35d32b95c1b81 Add GUI and implement a bit more diff -r f7f47291a61a -r 5cfbf08cb54d cl-chip8.asd --- a/cl-chip8.asd Wed Nov 16 02:01:44 2016 +0000 +++ b/cl-chip8.asd Wed Nov 16 20:41:42 2016 +0000 @@ -23,5 +23,5 @@ (:file "quickutils"))) (:file "package") (:module "src" :serial t - :components (#+no (:module "gui" :serial t :components ((:file "main"))) - (:file "emulator"))))) + :components ((:file "emulator") + (:file "gui"))))) diff -r f7f47291a61a -r 5cfbf08cb54d src/emulator.lisp --- a/src/emulator.lisp Wed Nov 16 02:01:44 2016 +0000 +++ b/src/emulator.lisp Wed Nov 16 20:41:42 2016 +0000 @@ -19,7 +19,7 @@ ;;;; Utils -------------------------------------------------------------------- -(declaim (inline nibble not= +_8 -_8)) +(declaim (inline not= +_8 -_8 chop cat-bytes)) (defun make-simple-array (element-type size &rest args) (apply #'make-array size @@ -28,20 +28,20 @@ :element-type element-type args)) -(defun nibble (position integer) - (ldb (byte 4 (* position 4)) integer)) - (defun not= (x y) (not (= x y))) +(defun chop (size integer) + (ldb (byte size 0) integer)) + (defun +_8 (x y) (let ((result (+ x y))) - (values (ldb (byte 8 0) result) + (values (chop 8 result) (if (> result 255) 1 0)))) (defun -_8 (x y) (let ((result (- x y))) - (values (ldb (byte 8 0) result) + (values (chop 8 result) (if (> x y) 1 0)))) @@ -52,21 +52,30 @@ (collect `(,macro ,@(ensure-list item))))))) +(defun cat-bytes (high-order low-order) + (dpb high-order (byte 8 8) low-order)) + + ;;;; Data --------------------------------------------------------------------- -(defstruct chip +(defstruct (chip (:constructor make-chip%)) (memory (make-simple-array 'int8 4096) :type (basic-array int8 4096) :read-only t) (registers (make-simple-array 'int8 16) :type (basic-array int8 16) :read-only t) - (video (make-simple-array 'fixnum #.(* 64 32)) - :type (basic-array fixnum #.(* 64 32)) - :read-only t) - (video-dirty t :type boolean) (keys (make-simple-array 'boolean 16) :type (basic-array boolean 16) :read-only t) + (awaiting-key nil + :type (or null (integer 0 15))) + (video-raw (error "Required") + :type (basic-array fixnum #.(* 32 64)) + :read-only t) + (video (error "Required") + :type (array fixnum (32 64)) ; row major :\ + :read-only t) + (video-dirty t :type boolean) (index 0 :type int16) (program-counter 0 :type int12) (delay-timer 0 :type int8) @@ -80,28 +89,55 @@ :element-type 'int12) :type (stack 16))) +(defun make-chip () + (let* ((video-raw (make-simple-array 'fixnum (* 32 64))) + (video (make-array '(32 64) + :displaced-to video-raw + :element-type 'fixnum))) + (make-chip% :video-raw video-raw :video video))) + + (define-with-macro chip - memory registers video keys + memory registers index program-counter delay-timer sound-timer random-state - video-dirty + video video-raw video-dirty + keys awaiting-key stack) +;;;; Graphics ----------------------------------------------------------------- +(defmacro vref (video x y) + `(aref ,video ,y ,x)) + + +;;;; Keyboard ----------------------------------------------------------------- +(defun keydown (chip key) + (with-chip (chip) + (setf (aref keys key) t) + (when awaiting-key + (setf (aref registers awaiting-key) key + awaiting-key nil)))) + +(defun keyup (chip key) + (setf (aref (chip-keys chip) key) nil)) + + ;;;; Opcodes ------------------------------------------------------------------ -(defun parse-opcode-argument-bindings (argument-list) - (flet ((normalize-arg (arg) - (destructuring-bind (symbol &optional (nibbles 1)) - (ensure-list arg) - (list symbol nibbles)))) - (iterate - (for (symbol nibbles) :in (mapcar #'normalize-arg argument-list)) - (for position :first 3 :then (- position nibbles)) - (when (not (eql symbol '_)) - (collect `(,symbol (ldb (byte ,(* nibbles 4) - ,(* position 4)) - opcode))))))) +(eval-when (:compile-toplevel :load-toplevel :execute) + (defun parse-opcode-argument-bindings (argument-list) + (flet ((normalize-arg (arg) + (destructuring-bind (symbol &optional (nibbles 1)) + (ensure-list arg) + (list symbol nibbles)))) + (iterate + (for (symbol nibbles) :in (mapcar #'normalize-arg argument-list)) + (for position :first 3 :then (- position nibbles)) + (when (not (eql symbol '_)) + (collect `(,symbol (ldb (byte ,(* nibbles 4) + ,(* position 4)) + opcode)))))))) (defmacro define-opcode (name argument-list &body body) `(progn @@ -127,13 +163,11 @@ (op-ld-dt