(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 "")) (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