add -raw mode for vm.scm

This commit is contained in:
~d6 2025-02-04 23:11:58 -05:00
parent e63f77f98e
commit 1debdb2ba8
1 changed files with 65 additions and 30 deletions

95
vm.scm
View File

@ -7,15 +7,18 @@
;; === implementation-dependent functions; uncomment one stanza
;; chicken scheme
(import (chicken bitwise) (chicken process-context) (chicken time posix))
(define (get-u8 port)
(let ((c (read-char port))) (if (eof-object? c) c (char->integer c))))
(import (chicken bitwise))
(import (chicken file))
(import (chicken process))
(import (chicken process-context))
(import (chicken time posix))
(import (chicken io))
(define (get-u8 port) (read-byte port))
(define (open-rom path) (open-input-file path #:binary))
(define (get-date-time)
(let* ((v (seconds->local-time))
(y (vector-ref v 5)))
(vector-set! v 5 (+ y 1900))
v))
(vector-set! v 5 (+ y 1900)) v))
;; ;; guile, invoke with guile vm.scm ROM ...
;; (use-modules (srfi srfi-60) (ice-9 binary-ports))
@ -69,6 +72,8 @@
(define rst (cons 0 (make-vector 256 0)))
(define pc 256)
(define done #f)
(define raw-tty #f)
(define saved-tty '())
;; instruction modes
(define _2 #f)
@ -245,8 +250,8 @@
((= 4 port) (set-car! wst byte))
((= 5 port) (set-car! rst byte))
((= 14 port) (u:debug))
((= 24 port) (write-char (integer->char byte) (current-output-port)))
((= 25 port) (write-char (integer->char byte) (current-error-port)))
((= 24 port) (write-byte byte (current-output-port)))
((= 25 port) (write-byte byte (current-error-port)))
(* '())))
(define (u:debug)
@ -345,26 +350,28 @@
(fn)
(u:eval))))
(define (u:exit n) (u:restore-tty) (exit n))
(define (u:run addr)
(set! done #f)
(set! pc addr)
(u:eval)
(let ((n (vector-ref dev 15)))
(if (= n 0) '()
(exit (bitwise-and n 127)))))
(u:exit (bitwise-and n 127)))))
(define (u:read-args args)
(if (null? args)
(u:send-input #\newline 4)
(u:send-input 10 4)
(begin
(u:read-arg (string->list (car args)))
(if (null? (cdr args)) '() (u:send-input #\newline 3))
(if (null? (cdr args)) '() (u:send-input 10 3))
(u:read-args (cdr args)))))
(define (u:read-arg chars)
(if (null? chars) '()
(begin
(u:send-input (car chars) 2)
(u:send-input (char->integer (car chars)) 2)
(u:read-arg (cdr chars)))))
;; send a character of console input with type
@ -373,22 +380,22 @@
;; - 2 argument data
;; - 3 spacer between arguments
;; - 4 spacer after arguments, or end of stdin
(define (u:send-input c type)
(define (u:send-input n type)
(let* ((hi (vector-ref dev 16))
(lo (vector-ref dev 17))
(addr (hilo->u16 hi lo)))
(if (= 0 addr) '()
(begin
(vector-set! dev 18 (u8 (char->integer c)))
(vector-set! dev 18 (u8 n))
(vector-set! dev 23 (u8 type))
(u:run addr)))))
(define (u:read-stdin port)
(let ((c (read-char port)))
(if (eof-object? c)
(u:send-input #\newline 4)
(let ((byte (read-byte port)))
(if (eof-object? byte)
(u:send-input 10 4)
(begin
(u:send-input c 1)
(u:send-input byte 1)
(u:read-stdin port)))))
;; load a ROM from a file, byte-by-byte
@ -399,16 +406,44 @@
(begin (vector-set! mem addr (u8 byte))
(u:load-rom rom (+ addr 1))))))
(let ((prog-args (command-line-arguments)))
(if (null? prog-args)
(begin (display "usage: ./vm ROM [ARGS...]\n") (exit))
(let* ((rom-path (car prog-args))
(rom-args (cdr prog-args))
(rom (open-rom rom-path))
(start 256))
(vector-set! dev 23 (if (null? rom-args) 0 1))
(u:load-rom rom start)
(u:run start)
(if (null? rom-args) '() (u:read-args rom-args))
(u:read-stdin (current-input-port))
(exit 0))))
(define (u:read-cmd cmd)
(with-input-from-pipe cmd (lambda () (read-string #f (current-input-port)))))
(define (u:usage)
(display "usage: ./vm [-raw] ROM [ARGS...]\n")
(exit))
(define (u:parse-args args)
(if (null? args) (u:usage))
(if (equal? (car args) "-raw")
(begin (set! raw-tty #t)
(u:parse-args (cdr args)))
args))
(define (u:check-rom path)
(if (and (file-exists? path) (file-readable? path)) '()
(begin (display "ERROR: cannot open ROM '")
(display path)
(display "'\n")
(u:usage))))
(define (u:set-tty)
(if raw-tty (begin (set! saved-tty (u:read-cmd "stty -g"))
(system* "stty raw -echo"))))
(define (u:restore-tty)
(if raw-tty (system* (string-append "stty " saved-tty))))
(let* ((prog-args (u:parse-args (command-line-arguments)))
(_ (u:set-tty))
(rom-path (car prog-args))
(rom-args (cdr prog-args))
(_ (u:check-rom rom-path))
(rom (open-rom rom-path))
(start 256))
(vector-set! dev 23 (if (null? rom-args) 0 1))
(u:load-rom rom start)
(u:run start)
(if (null? rom-args) '() (u:read-args rom-args))
(u:read-stdin (current-input-port))
(u:exit 0))