65 lines
2.1 KiB
Plaintext
65 lines
2.1 KiB
Plaintext
|
(local util (require :lib.util))
|
||
|
(local {: spawn : kill} (util.require :lib.spawn))
|
||
|
(local nrepl (require :link.nrepl))
|
||
|
(local Session (require :link.nrepl-session))
|
||
|
(local bencode (require :lib.bencode))
|
||
|
(local lume (require :lib.lume))
|
||
|
|
||
|
(fn start-mame [platform]
|
||
|
(spawn [:mame :-debug :-plugins :-pluginspath "/home/jeremy/src;/usr/share/mame/plugins" :-plugin :jeejah platform]))
|
||
|
|
||
|
(local Machine (Session:extend))
|
||
|
(fn Machine.new [self]
|
||
|
(Machine.super.new self {:out (fn []) :value (fn [])}))
|
||
|
(fn Machine.boot [self]
|
||
|
(when (not self.pid)
|
||
|
(set self.pid (start-mame :apple2p))))
|
||
|
(fn Machine.run [self]
|
||
|
(self:boot)
|
||
|
(self:connect))
|
||
|
(fn Machine.die [self]
|
||
|
(self:disconnect)
|
||
|
(when self.pid
|
||
|
(kill (- self.pid) 1)
|
||
|
(set self.pid nil)))
|
||
|
(fn Machine.running? [self] self.pid)
|
||
|
(fn Machine.connected? [self] self.session)
|
||
|
(fn Machine.connect [self]
|
||
|
(util.in-coro (fn []
|
||
|
(when (not (nrepl:connected?))
|
||
|
(util.waitfor
|
||
|
#(if (nrepl:connected?) true
|
||
|
(do (pcall #(nrepl:connect)) false))))
|
||
|
(self:init-session))))
|
||
|
(fn Machine.disconnect [self]
|
||
|
(when (nrepl:connected?) (nrepl:disconnect))
|
||
|
(set self.session nil))
|
||
|
(fn Machine.write [self addr bytes]
|
||
|
(self:send
|
||
|
{:op :eval
|
||
|
:code
|
||
|
"(let [bencode (require :bencode)
|
||
|
{: addr : bytes} (bencode.decode (io.read))
|
||
|
mem (-> (manager:machine) (. :devices ::maincpu :spaces :program))]
|
||
|
(print :writing (bytes:len) :to addr)
|
||
|
(for [i 1 (bytes:len)]
|
||
|
(mem:write_u8 (+ addr i -1) (string.byte (bytes:sub i i)))))"}
|
||
|
{:status/need-input #(self:send-oob {:op :stdin :stdin (bencode.encode {: addr : bytes})})}))
|
||
|
(fn Machine.reboot [self] (self:eval "(: (manager:machine) :hard_reset)"))
|
||
|
(fn Machine.coro-eval [self code]
|
||
|
(var result nil)
|
||
|
(self:eval code
|
||
|
(self:coro-handlers (coroutine.running) {:out #(set result $2)}))
|
||
|
(coroutine.yield)
|
||
|
(or result "<no result?>"))
|
||
|
(fn Machine.dbgcmd [self cmd]
|
||
|
(self:eval (.. "(-> (manager:machine) (: :debugger) (: :command \"" cmd "\"))")))
|
||
|
(fn Machine.continue [self] (self:dbgcmd :go))
|
||
|
(fn Machine.step [self] (self:dbgcmd :s))
|
||
|
(fn Machine.stop-at [self addr])
|
||
|
(Machine:new)
|
||
|
|
||
|
Machine
|
||
|
|
||
|
|