From 1db882c150c13b56e92a0c1ed294b460279ab6d3 Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sat, 15 May 2021 11:50:53 -0400 Subject: [PATCH] Preserve state across hot code reload!! --- 8Bitsy.dsk | Bin 143360 -> 143360 bytes asm/asm.fnl | 25 +++++++++++++++++++++++-- asm/vm.fnl | 5 +++-- game/defs.fnl | 2 +- game/game.json | 2 +- game/init.fnl | 2 +- link/mame.fnl | 30 ++++++++++++++++++++++++------ link/nrepl-session.fnl | 8 +++++--- 8 files changed, 58 insertions(+), 16 deletions(-) diff --git a/8Bitsy.dsk b/8Bitsy.dsk index 135046c06470368cd79b921e98331a1a74253b19..de496c6f030d51f810d4e2f2d9f9bed44d275538 100644 GIT binary patch delta 2156 zcmY+Fdu&rx9LMkNYc2M+Wl-2CBX_c~Iub-zlqCvlx3=s0%5CrM)~?;7+gdO%77zy; zYy*--dHCpY647a5f{&ID(>oh?@|MG8`_xg;~$~Z^rubQr$dF-s>(FxCi zV`5_bimXDH+&3*v6&>b0$It&jj@%eN5qnc+;?3*x%x0c8GXqU&EXX$+6|^lTtZXsa z(bQh8T3ZKbAv=Ipqe_HfyhwEgt%hMDFxG1vXnC`?U#qfPxLlQmV}chA8V>BBK&;Jy zm4b!y)~&HwIA2{k?YGrc(f)9q-!^1hNS{fka{}a4vyHIvC1gpwkd2e|@wW`BblSsc zJ>?GC!&=1H+TKfDeIbFXFC}pGs|2oQBygps>>p%lWTp_XJ3@1;Gz8DB4#9IZ$RhKs z9$6Gw0$CE7Q#-#i7ItQ;&1|i9P|$ErjO#}c*10B@M8yMnymXXmS}LEg%HT^^6i?@P5Bdv!T6 z5t5_Gc^$1*K8f}=d9eiZ3*?*8a`GXxI{Bs$%r8=nqji;dsl!UExCUk!pR3Z&yIrCf zE~F#eyOD-gAwufhBBaiP+x3c=R@jpdp&wyA!l+1IO%woo7TF-O=a9W7lJP_#>1k8x zDIY_A9yvXGMsjMmo)jg&F>3!3{?O9wpW!f!oB)idVluT^-`iJn$ck@fl*Yrjvj%gvh zdtW$Bx5hAVL`Jw#0X1g&oHXEI`^6O15;)GuT=AY;RQ3AH%Q=xxD3e zVvxnj_gj~xwoH(TCM8kHay1=$c5UB5TT5!|RdTh-lxm+)^Fh%c2(RH&+cuDm+g3q| zet^~fAy)e(toFaL+Mz^mBD;lbc^FEkC=6%mPRfeIaL!hR;hf!#tPGhpFu;8m4pD^# z6&q1efr@%m{8y;G99C+5rcmo=3w6GXHEQ~5nli8{Q^mD@$y3FL{St4p^WHG;2)OLN zs*R8ozk{#zOM#$$z93p?7zGgsbVURLy(a>jxHpoyXN=r>gyjgU5ZWVz?Ml;x?mxL* ztH=+Y7JiA3a7$Z$cg%1*g%M8Q64TC19h(|1en`)<0$JDDP5Yrv6YW3iTp^nj$WNV5 zm(zv$W>~ne85Z8q3=7vZ&s}hCWFBM*WJzTA(IdC3OqbcKODusqgx1npvUc}aFL$m1 z+Z{^Y-AirM(Ni&SbTkHz-j0Ezi!pF? zSs37=4RDCQMa4KO(x}M8_(9Q1!reRJ6eb$LO|k*p9KcOJk0NmJF0%K4^=o0m9tE)@ z3gXr%thqZn7kn48Ze+)hy@>2*h$jY5zl4gHQE>(o_jA|gC9ScAc98a?bP}c4QF;@d z-I`ZE8H2CkC4n5=(_X}=%uzUjYQ+p%oie`x#!Af?T7%NsNS5z4$>>+MeD7$g=VAKc Te55DIDi2Kej7;~i`k{XT`{_RQ delta 1798 zcmY+Fe@t6d6vy9dOKInOlpkZuf^4q>j<|)ftc!GU$YT^zDD7L{>u60|TFS=MNr45~ z#?M71E*q0@Ll*zh`QxAcB~TP($q+M{KM5voF3J#{8XXgYU=|&t-g6jO-yiqn=JUPh zoO|xM_jSzZI%afz<2p7ga!of^stQSDNZzaJl_GO;vWhK_u!rum>iSY5E7^*Z0$CY(Pq0D`X#YlX!Y7k z56n}vQ)u7)JB)TRV{YN5Kf`vLkRvb=GjzHL|O=MG*kv&cFs)mhm(Ws5#Z02G*LU5j`co?9f zThj9-9AQ=SsX~#%W)qzfONJLiRSYtH?f4$V7E|dqRAJ45iY< ze~gw>GYZTfQSU>$LEVOySC6AjP`A2(r)ZbZTDO-AqFoRr$!5s`AS+JMUSioPcpNUl z=5Uk=Hfxzh5QPJxf&$!hD$S{Y?lWNG?YL0~Zd8)jihU4^5JpyqtR7hjJ=hYb(mh)_F2FT!ShUCW7v55tqhqB*%4$l$exnO z=!rcEt64BsWxGt9nARl{iMAv>XAjOO|UA0c);n9W!m1@i%_WZK8X054jiPWcWsvqUSP+O^&oo#*=@+j2kzcP#YI$%fnq=Z)4Ig#OR|8p4W+kH`ZG!w z(b>|v@|+Le=}C$7wA6}XF|CcgNMN*r7aj+l<}b7faY=rd$LT*syZ#X3Um@nvCSvQT dZuME*@9k-Om1W48wi;IR(n8zNLK|!7{}&&82K@j4 diff --git a/asm/asm.fnl b/asm/asm.fnl index cddd9f8..df0a382 100644 --- a/asm/asm.fnl +++ b/asm/asm.fnl @@ -115,7 +115,7 @@ ; takes the form [:op args] ; pdat - a parsed dat; takes the form {:type type :addr addr ...} (local dat-parser {}) - (fn new-block [last-symbol] {:type :block :pdats [] :symbols {} :globals {} : last-symbol}) + (fn new-block [last-symbol] {:type :block :pdats [] :preserved {} :symbols {} :globals {} : last-symbol}) (fn parse-dats [block dats] (each [_ dat (ipairs dats)] @@ -139,7 +139,10 @@ (table.insert block.pdats pdat) (when pdat.globals (each [name _ (pairs pdat.globals)] - (tset block.globals name (length block.pdats)))))))) + (tset block.globals name (length block.pdats)))) + (when pdat.preserved + (each [name pdat-preserved (pairs pdat.preserved)] + (tset block.preserved name pdat-preserved))))))) block) (fn dat-parser.op [op] @@ -166,6 +169,13 @@ nil) (fn dat-parser.align [pad] {:type :pad :align (. pad 2)}) + (fn dat-parser.hot-preserve [[_ label & dats] block] + (let [preserve-block (new-block)] + (tset block.preserved label preserve-block) + (tset preserve-block.globals label true) + (parse-dats preserve-block [label]) + (parse-dats preserve-block dats) + preserve-block)) (local pdat-processor { :op {} @@ -338,6 +348,17 @@ (self.dbgfile:close) (set self.dbgfile nil)) self) + :read-hotswap + (fn [self machine] + (let [hotswap {}] + (each [_ block (pairs self.org-to-block)] + (each [label pdat (pairs block.preserved)] + (tset hotswap label (machine:read pdat.addr pdat.size)))) + hotswap)) + :write-hotswap + (fn [self machine hotswap] + (each [label bytes (pairs hotswap)] + (machine:write (self:lookup-addr label) bytes))) :upload (fn [self machine] (if machine.upload (machine:upload self) diff --git a/asm/vm.fnl b/asm/vm.fnl index a54a2fd..a8ea02f 100644 --- a/asm/vm.fnl +++ b/asm/vm.fnl @@ -385,8 +385,9 @@ (fn vm.var [self name init] (self.code:append name [:jsr :$dovar] - (if (= (type init) :table) init - [:dw init]))) + [:hot-preserve (.. :G-HOT-PRESERVE- name) + (if (= (type init) :table) init + [:dw init])])) (vm:def :$doconst ; usage: [jsr :$doconst] followed by two bytes (vm:reserve) diff --git a/game/defs.fnl b/game/defs.fnl index 84f93a9..5ccc8f0 100644 --- a/game/defs.fnl +++ b/game/defs.fnl @@ -132,7 +132,7 @@ [:jmp (if (= (or map.moveword "") "") :move-noop map.moveword)] [:jmp (if (= (or map.loadword "") "") :next map.loadword)])) -(vm.code:append :map-ptr [:db 0] :map-page [:db 0]) +(vm.code:append :map-ptr [:db 0] [:hot-preserve :map-page [:db 0]]) (vm:word :map :lit :map-ptr :get) (vm:word :entity-count :map 240 :+ :bget) (vm:word :map-player-yx-ptr 241 :+) diff --git a/game/game.json b/game/game.json index 49ebf2e..06ea0d3 100644 --- a/game/game.json +++ b/game/game.json @@ -1 +1 @@ -{"tiles":[{"gfx":"8080808080808080808080808080808080808080808080808080808080808080","word":"","label":"","flags":{"walkable":true}},{"gfx":"8080C0C0C0C0E0F0F8FCE6E6E0B0B0B0808183838383878F9FBFE7E7868C8C8C","word":"","label":"player-frame1","flags":[]},{"gfx":"8080808084CCFCFCFCFCFCF8F0B0B0B080808080E1E1E1F1B99F9F8F8F8C8C8C","word":"","label":"","flags":[]},{"gfx":"D5D55555D5D55555D5D55555D5D555552A2AAAAA2A2AAAAA2A2AAAAA2A2AAAAA","word":"","label":"","flags":[]},{"gfx":"8080D4D0D0D0D4D45454D4D4D4D0808080808A8282828A8A8A0A0A8A8A828080","word":"pot","label":"","flags":[]},{"gfx":"8080808080D490948484A48494D080808080808080AA88A8A0A5A5A0A88A8080","word":"","label":"","flags":[]},{"gfx":"808080F8F89898989898989E9F9E80808080809F9F9898989898989E9F9E8080","word":"","label":"","flags":[]},{"gfx":"000000A0908884827E0A0A0A0000000000000000201008040785858500000000","word":"","label":"","flags":[]},{"gfx":"000014040414500000000000A888A8800000282020280A010101010195919580","word":"","label":"","flags":[]},{"gfx":"00008C92921C60105010781C0E070300000098A4A41C030504050F1C38706000","word":"","label":"","flags":[]},{"gfx":"000000004040000000D4D4ECECECD480000000000202010101AAAAB6B6B6AA80","word":"","label":"","flags":[]},{"gfx":"0000000000004828282828482800000000000000000004050505050405000000","word":"","label":"","flags":[]},{"flags":{"walkable":true},"word":"","label":"","gfx":"000000002020202020000A080808000000000000000000415111111111110100"},{"flags":[],"word":"","label":"","gfx":"00002028282A2A2A2820A0A0A0A0A08000000515155555151505858585858580"},{"flags":[],"word":"","label":"","gfx":"8080808080F8FCFC9C9CBCFEE6E6E68080808287878780818784848484848480"},{"flags":[],"word":"","label":"","gfx":"C0C0D0D0D4D4D4D5D5D080C0D0D4D4D08282828080828AAAAA8A8A8A82808282"},{"flags":{},"word":"","label":"stickbob","gfx":"E090B090A0C0A8D0D0A8C0E0B0988080838486848281958A8A958183868C8080"},{"flags":[],"word":"","label":"","gfx":"8080808080A0A8A8A0A0A0A8A8A8A08081818181818594948585859594948580"},{"flags":[],"word":"","label":"","gfx":"008AA88A000020282A0A0A0A2A28000000151115140505010000101014150500"}],"levels":[{"loadword":"","map":"000000000000000000000000000000000000000000606060606060606060606060606060606060000060000000000000000000000000000000006000006000000000000000000000000000000000600000600000A00000000000000000004000000060600060000000000000000000000000000000000000006000000000000000000000000000000000606000600000000000000000000000000000000060000060000000000000000080808080800000006000006000000000000000000000000000000000600000606060606060606060606060606060606060000000000000000000000000000000000000000000","player":{"y":4,"x":5},"tickword":"","moveword":"","objects":[{"x":15,"func":"cat","linkentity":"","y":8,"linkword":"","name":"","steps":[{"action":"say","character":"cat","lines":["I'm an apple.","","",""]},{"action":"say","character":"player","lines":["Strange, you look like a cat.","","",""]}]},{"x":5,"y":8,"linkentity":"","func":"fish","name":"","linkword":"","steps":[{"lines":["","","Grr! Go away!",""],"action":"say","character":"angryfish"}]},{"x":13,"y":4,"linkentity":"","func":"pot","linkword":"","name":"","steps":[{"character":"player","lines":["","Just another empty pot.","",""],"action":"say"}]},{"x":12,"y":4,"linkentity":"","func":"suspiciouspot","linkword":"","name":"","steps":[{"lines":["","","",""],"action":"disappear","character":"player"},{"lines":["","Whoops, I broke it!","",""],"action":"say","character":"player"}]},{"x":11,"y":4,"linkentity":"","func":"pot","name":"","linkword":"","steps":[{"character":"player","lines":["","It's a plain old empty pot.","",""],"action":"say"}]},{"x":14,"y":4,"linkentity":"","func":"pot","name":"","linkword":"","steps":[{"character":"player","lines":["","Nothing special about these pots.","",""],"action":"say"}]},{"x":15,"y":4,"linkentity":"","func":"pot","name":"","linkword":"","steps":[{"character":"player","lines":["","This one has a million dollars","inside!!",""],"action":"say"},{"character":"player","lines":["","Oh, no, wait. That was just","a dust bunny.",""],"action":"say"},{"character":"player","lines":["","There's really nothing special","about this pot.",""],"action":"say"},{"character":"player","lines":["","Probably.","",""],"action":"say"}]},{"func":"","x":20,"y":7,"steps":[{"position":1537,"character":"player","lines":["","","",""],"action":"warp","map":"map2"}]}]},{"loadword":"","objects":[{"func":"","x":1,"y":7,"steps":[{"position":1554,"character":"player","lines":["","","",""],"action":"warp","map":"map1"}]},{"func":"","x":18,"y":2,"steps":[{"lines":["","Neat, it's a pair of 3D glasses!","I wonder what I can see with","these..."],"action":"say","character":"player"},{"lines":["","","",""],"action":"disappear","character":"player"},{"flag":"has glasses","action":"set-flag","lines":["","","",""],"rhs":{"label":"","value":65535},"character":"player"}]},{"func":"","x":10,"y":7,"steps":[{"character":"old man","lines":["","I am but a weary old man,","living alone in these woods.",""],"action":"say"},{"action":"say","character":"player","lines":["","Cool story. Any words of wisdom","for me?",""]},{"action":"say","character":"old man","lines":["","Not really.","",""]},{"condition":"has glasses","character":"glasses","lines":["Holy cow!!","","This \"old man\" is actually","an alien!!"],"action":"say"}]},{"func":"","x":20,"y":7,"steps":[{"position":1537,"character":"player","lines":["","","",""],"action":"warp","map":"map3"}]},{"func":"","x":10,"y":1,"steps":[{"position":2057,"character":"player","action":"warp","lines":["","","",""],"map":"map4"}]}],"tickword":"","moveword":"","map":"A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1000000A1A1A1A10000818181818181A1A1A10000000000A1A1A1000000818181818181A1A1A1000000000000A1A100000000818181818100A160600000000000000000000000000081000000A1000000000000000000C10000000000000000000060600000000000000000000000000000000000A1A1000081818100000000000000A1A100000000A1A10081818181810000000000A1A1A1A1000000A1A100818181818100000000A1A1A1A1A1A10000A1A10000008181000000000000A1A1A1A1A1E0A1A1A1A1A1A1A1A1A1A1A100A1A1A1A1A1A1A1A1A1A1"},{"loadword":"","map":"A1A1A1A1A1818181818181E1E181818181818181A1A1A1A18181818181818181E181818181818181A1A181818142810000008181E1E1818181000000A1000081818100000000818181E1E18181000000A100000000000000000000818181E181818100000000000000000000000000008181E18181810000A181810000000000000000000000E10000000000A181818181000000A10000818181E18181000000A1818181810000000000008181E1E18181000000A1A181818100000000818181E1E1818181818181A1A1A1818181000081818181E181818181818181A1A1A1A18181818181818181E181818181818181","tickword":"","moveword":"","objects":[{"func":"","x":1,"y":7,"steps":[{"position":1554,"character":"player","lines":["","","",""],"action":"warp","map":"map2"}]},{"func":"","x":9,"y":5,"steps":[{"action":"say","character":"player","lines":["","This wood would be perfect to","build a bridge with!",""]},{"action":"say","character":"player","lines":["","Haha, \"wood would\". Wood would","wood would.",""]},{"action":"say","character":"player","lines":["","Hey, I bet I could cut down this","tree with my cool time scissors!",""],"condition":"has scissors"},{"action":"disappear","character":"player","lines":["","","",""],"condition":"has scissors"},{"action":"say","character":"player","lines":["","Haha, awesome.","",""],"condition":"has scissors"},{"condition":"has scissors","flag":"has wood","character":"player","lines":["","","",""],"rhs":{"label":"","value":65535},"action":"set-flag"}]},{"func":"","x":15,"y":6,"steps":[{"action":"say","character":"player","lines":["","If only there was some convenient","way to cross this ankle-deep","stream!"]},{"condition":"has wood","character":"player","lines":["","Guess I'll just have to build a","raft and sail it across.",""],"action":"say"},{"condition":"has wood","character":"player","lines":["","","",""],"action":"disappear"}]},{"func":"","x":6,"y":10,"steps":[{"character":"snake","lines":["","Badger badger badger badger","badger badger badger badger","badger badger badger badger"],"action":"say"},{"character":"player","lines":["","A snake! A snake!","",""],"action":"say"}]}]},{"loadword":"","map":"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000600000000000000000000000606060606060600060606060606060000000000060C00000000000000000000000C060000000000060000000000000000000000000006000000000006000000000000002000000000000600000000000600000000000000000000000000060000000000060C00000210000000000220000C060000000000060606060606060606060606060606000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","tickword":"","moveword":"","objects":[{"func":"","x":10,"y":6,"steps":[{"lines":["","Would you like to hear a jig","and a reel?",""],"action":"say","character":"stick bob"},{"lines":["","Do you play the theremin?","",""],"action":"say","character":"player"},{"lines":["","I can play anything!","",""],"action":"say","character":"stick bob"}]},{"func":"","x":10,"y":10,"steps":[{"position":265,"character":"player","action":"warp","lines":["","","",""],"map":"map2"}]},{"func":"","x":13,"y":4,"steps":[{"lines":["","It's a fiddle. I promise.","I worked hard to draw it.",""],"action":"say","character":"player"}]},{"func":"","x":7,"y":4,"steps":[{"lines":["","Scissors with a clock on them?","They're super sharp!",""],"action":"say","character":"player"},{"lines":["","I'm sure they'll come in handy!","",""],"action":"say","character":"player"},{"flag":"has scissors","character":"player","lines":["","","",""],"rhs":{"label":"","value":65535},"action":"set-flag"},{"lines":["","","",""],"action":"disappear","character":"player"}]}]}],"flags":["has wood","has scissors","","has glasses"],"portraits":[{"gfx":"000000000000000000000000000000000000007C7C7E7E7E7E7E7E7E7E7E7E7E00000000707F7F7F7F7F7F7F7F7F7F7F7E7E7E7E7F7F7F7F7F7F7F7F7F7F7F7F0000000F0F1F1F1F1F1F1F1F1F1F1F1F000000000000000000000000000000001F1F1F1F7F7F7F7F7F7F7F7F7F7F7F7F00000000077F7F7F7F7F7F7F7F7F7F7F","label":"player","flags":[]},{"gfx":"00000000004040606060707070707070000000000000010103037F7F7F7F7F7F707060604000000000000000000000007F7F7F7F7F7F7800004040406060606000000000001018383C3C7F7F7F7F7F7F000000000000000000000000000000007F7F7F3F0F67717C7F7F7F7F7F7F7F7F00007C7E7F7F7F7F7F7F7F7F7F7F7F7F","label":"cat","flags":[]},{"gfx":"80808080808080808080D5818181858480808080808080808080AA80808080808484848484A4848484A48484848494D0809090D0D4F5D5D5D5D5D480808080AA80808080808080808080D5808080808080808080808080808080AAA0A0A0A888808080808AA8AAAAAA828080808080D588888888888889898888888888888A82","label":"angryfish","flags":[]},{"flags":[],"label":"old man","gfx":"0000000000000000000000000000000000000000000000707C7872737373736300000000303F3F3F7F7F7F7F7F7F7F7F0F7F7F7F7E7E7E7E7C7C79797979797300000000000000073F3F7F7F7F7F7F60000000000000000000000000000000000E7F3F3F3F3F7F7F7F7F7F7F7F3F1F1F00000000000000000004040C0C1C1E1F"},{"flags":[],"label":"stick bob","gfx":"808080808080808080A0A8E8E8F0F0F08080808080C0D4D5FDFFFFF3F1F1FFFFF0F0E0E0C08080808080808080808080FFFFF983FFBFBEFCF4D4D4D4D4D4D4D480808080808AAAABAFBFFFE7C7C7FFFF80808080808080808185858583838383FFFFCFE0FFFEBE8F8B8A8A8A8A8A8A8A83838383818080808080808080808080"},{"flags":[],"label":"snake","gfx":"000000000000808080808AA88A8080000000000000000014557155455054545000000020202020202020000000000000505455150505050505155554545040000000000000000000000202020202020200000000000000000000000000000000002020202000000000000002022A2A2A00000001010505051514141414150505"},{"flags":[],"label":"glasses","gfx":"000000000000000000000000000000000000007C7C7E7E7E7E555555757E7E7E00000000707F7F7F7F7F7F7F7F7F7F7F7E7E7E7E7F7F7F7F7F7F7F7F7F7F7F7F0000000F0F1F1F1F9FAAAAAAAB1F1F1F000000000000000000000000000000001F1F1F1F7F7F7F7F7F7F7F7F7F7F7F7F00000000077F7F7F7F7F7F7F7F7F7F7F"}],"font":[{"flags":[],"gfx":"0000000000000000"},{"flags":[],"gfx":"081C1C1C08000800"},{"flags":[],"gfx":"3636241200000000"},{"flags":[],"gfx":"123F1212123F1200"},{"flags":[],"gfx":"083C0A1C281E0800"},{"flags":[],"gfx":"0026160834320000"},{"flags":[],"gfx":"0E1B1B062F1B3600"},{"flags":[],"gfx":"0C0C080400000000"},{"flags":[],"gfx":"180C0606060C1800"},{"flags":[],"gfx":"0C18303030180C00"},{"flags":[],"gfx":"082A1C081C2A0800"},{"flags":[],"gfx":"000C0C3F3F0C0C00"},{"flags":[],"gfx":"000000000C0C0804"},{"flags":[],"gfx":"0000001E1E000000"},{"flags":[],"gfx":"00000000000C0C00"},{"flags":[],"gfx":"002030180C060200"},{"flags":[],"gfx":"1C26263E26261C00"},{"flags":[],"gfx":"181C181818183C00"},{"flags":[],"gfx":"1C2620180C063E00"},{"flags":[],"gfx":"1C26201820261C00"},{"flags":[],"gfx":"2626263C30303000"},{"flags":[],"gfx":"3E061E2020201E00"},{"flags":[],"gfx":"1C26061E26261C00"},{"flags":[],"gfx":"3E2630180C0C0C00"},{"flags":[],"gfx":"1C26261C26261C00"},{"flags":[],"gfx":"1C26263C20201C00"},{"flags":[],"gfx":"000C0C000C0C0000"},{"flags":[],"gfx":"000C0C000C0C0804"},{"flags":[],"gfx":"30180C060C183000"},{"flags":[],"gfx":"00003E003E000000"},{"flags":[],"gfx":"060C1830180C0600"},{"flags":[],"gfx":"1C3630180C000C00"},{"flags":[],"gfx":"1E33212D3D011E00"},{"flags":[],"gfx":"1C3E26263E262600"},{"flags":[],"gfx":"1E26261E26261E00"},{"flags":[],"gfx":"1C26060606261C00"},{"flags":[],"gfx":"1E26262626261E00"},{"flags":[],"gfx":"3E06061E06063E00"},{"flags":[],"gfx":"3E06061E06060600"},{"flags":[],"gfx":"1C26063626263C00"},{"flags":[],"gfx":"2626263E26262600"},{"flags":[],"gfx":"3C18181818183C00"},{"flags":[],"gfx":"3C30303036361C00"},{"flags":[],"gfx":"2626261E26262600"},{"flags":[],"gfx":"0606060606063E00"},{"flags":[],"gfx":"373F2B2B23232300"},{"flags":[],"gfx":"26262E3626262600"},{"flags":[],"gfx":"1C26262626261C00"},{"flags":[],"gfx":"1E26261E06060600"},{"flags":[],"gfx":"1C26262626363C00"},{"flags":[],"gfx":"1E26261E26262600"},{"flags":[],"gfx":"3C26061C20221E00"},{"flags":[],"gfx":"3F0C0C0C0C0C0C00"},{"flags":[],"gfx":"2626262626261C00"},{"flags":[],"gfx":"2626261C1C1C0800"},{"flags":[],"gfx":"2323232B2B2A3600"},{"flags":[],"gfx":"2626261C26262600"},{"flags":[],"gfx":"2626261C18181800"},{"flags":[],"gfx":"3E3E30180C063E00"},{"flags":[],"gfx":"1C0C0C0C0C0C1C00"},{"flags":[],"gfx":"0002060C18302000"},{"flags":[],"gfx":"1C18181818181C00"},{"flags":[],"gfx":"081C260000000000"},{"flags":[],"gfx":"0000000000003E00"},{"flags":[],"gfx":"0C0C100000000000"}]} \ No newline at end of file +{"tiles":[{"gfx":"8080808080808080808080808080808080808080808080808080808080808080","word":"","label":"","flags":{"walkable":true}},{"gfx":"8080C0C0C0C0E0F0F8FCE6E6E0B0B0B0808183838383878F9FBFE7E7868C8C8C","word":"","label":"player-frame1","flags":[]},{"gfx":"8080808084CCFCFCFCFCFCF8F0B0B0B080808080E1E1E1F1B99F9F8F8F8C8C8C","word":"","label":"","flags":[]},{"gfx":"D5D55555D5D55555D5D55555D5D555552A2AAAAA2A2AAAAA2A2AAAAA2A2AAAAA","word":"","label":"","flags":[]},{"gfx":"8080D4D0D0D0D4D45454D4D4D4D0808080808A8282828A8A8A0A0A8A8A828080","word":"pot","label":"","flags":[]},{"gfx":"8080808080D490948484A48494D080808080808080AA88A8A0A5A5A0A88A8080","word":"","label":"","flags":[]},{"gfx":"808080F8F89898989898989E9F9E80808080809F9F9898989898989E9F9E8080","word":"","label":"","flags":[]},{"gfx":"000000A0908884827E0A0A0A0000000000000000201008040785858500000000","word":"","label":"","flags":[]},{"gfx":"000014040414500000000000A888A8800000282020280A010101010195919580","word":"","label":"","flags":[]},{"gfx":"00008C92921C60105010781C0E070300000098A4A41C030504050F1C38706000","word":"","label":"","flags":[]},{"gfx":"000000004040000000D4D4ECECECD480000000000202010101AAAAB6B6B6AA80","word":"","label":"","flags":[]},{"gfx":"0000000000004828282828482800000000000000000004050505050405000000","word":"","label":"","flags":[]},{"flags":{"walkable":true},"word":"","label":"","gfx":"000000002020202020000A080808000000000000000000415111111111110100"},{"flags":[],"word":"","label":"","gfx":"00002028282A2A2A2820A0A0A0A0A08000000515155555151505858585858580"},{"flags":[],"word":"","label":"","gfx":"8080808080F8FCFC9C9CBCFEE6E6E68080808287878780818784848484848480"},{"flags":[],"word":"","label":"","gfx":"C0C0D0D0D4D4D4D5D5D080C0D0D4D4D08282828080828AAAAA8A8A8A82808282"},{"flags":{},"word":"","label":"stickbob","gfx":"E090B090A0C0A8D0D0A8C0E0B0988080838486848281958A8A958183868C8080"},{"flags":[],"word":"","label":"","gfx":"8080808080A0A8A8A0A0A0A8A8A8A08081818181818594948585859594948580"},{"flags":[],"word":"","label":"","gfx":"008AA88A000020282A0A0A0A2A28000000151115140505010000101014150500"},{"flags":[],"word":"","label":"","gfx":"000000002028381828282020202028000000000005151D191515040404041400"}],"levels":[{"loadword":"","objects":[{"x":15,"y":8,"linkentity":"","func":"cat","name":"","linkword":"","steps":[{"lines":["I'm a cat.","","",""],"action":"say","character":"cat"},{"character":"player","lines":["","Nice kitty!","",""],"action":"say"}]},{"x":5,"func":"fish","linkentity":"","y":8,"linkword":"","name":"","steps":[{"character":"angryfish","lines":["","","Grr! Go away!",""],"action":"say"}]},{"x":13,"func":"pot","linkentity":"","y":4,"name":"","linkword":"","steps":[{"action":"say","character":"player","lines":["","Just another empty pot.","",""]}]},{"x":12,"func":"suspiciouspot","linkentity":"","y":4,"name":"","linkword":"","steps":[{"character":"player","lines":["","","",""],"action":"disappear"},{"character":"player","lines":["","Whoops, I broke it!","",""],"action":"say"}]},{"x":11,"func":"pot","linkentity":"","y":4,"linkword":"","name":"","steps":[{"action":"say","character":"player","lines":["","It's a plain old empty pot.","",""]}]},{"x":14,"func":"pot","linkentity":"","y":4,"linkword":"","name":"","steps":[{"action":"say","character":"player","lines":["","Nothing special about these pots.","",""]}]},{"x":15,"func":"pot","linkentity":"","y":4,"linkword":"","name":"","steps":[{"action":"say","character":"player","lines":["","This one has a million dollars","inside!!",""]},{"action":"say","character":"player","lines":["","Oh, no, wait. That was just","a dust bunny.",""]},{"action":"say","character":"player","lines":["","There's really nothing special","about this pot.",""]},{"action":"say","character":"player","lines":["","Probably.","",""]}]},{"func":"","x":20,"y":7,"steps":[{"position":1537,"character":"player","action":"warp","lines":["","","",""],"map":"map2"}]}],"player":{"y":4,"x":5},"tickword":"","moveword":"","map":"000000000000000000000000000000000000000000606060606060606060606060606060606060000060000000000000000000000000000000006000006000000000000000000000000000000000600000600000A00000000000000000004000000060600060000000000000000000000000000000000000006000000000000000000000000000000000606000600000000000000000000000000000000060000060000000000000000080808080800000006000006000000000000000000000000000000000600000606060606060606060606060606060606060000000000000000000000000000000000000000000"},{"loadword":"","map":"A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1000000A1A1A1A10000818181818181A1A1A10000000000A1A1A1000000818181628181A1A1A1000000000000A1A100000000818181818100A160600000000000000000000000000081000000A1000000000000000000C10000000000000000000060600000000000000000000000000000000000A1A1000081818100000000000000A1A100000000A1A10081818181810000000000A1A1A1A1000000A1A100818181818100000000A1A1A1A1A1A10000A1A10000008181000000000000A1A1A1A1A1E0A1A1A1A1A1A1A1A1A1A1A100A1A1A1A1A1A1A1A1A1A1","tickword":"","moveword":"","objects":[{"func":"","x":1,"y":7,"steps":[{"position":1554,"character":"player","action":"warp","lines":["","","",""],"map":"map1"}]},{"func":"","x":18,"y":2,"steps":[{"character":"player","lines":["","Neat, it's a pair of 3D glasses!","I wonder what I can see with","these..."],"action":"say"},{"character":"player","lines":["","","",""],"action":"disappear"},{"flag":"has glasses","character":"player","lines":["","","",""],"rhs":{"label":"","value":65535},"action":"set-flag"}]},{"func":"","x":10,"y":7,"steps":[{"action":"say","character":"old man","lines":["","I am but a weary old man,","living alone in these woods.",""]},{"lines":["","Cool story. Any words of wisdom","for me?",""],"action":"say","character":"player"},{"lines":["","Not really.","",""],"action":"say","character":"old man"},{"action":"say","character":"glasses","lines":["Holy cow!!","","This \"old man\" is actually","an alien!!"],"condition":"has glasses"}]},{"func":"","x":20,"y":7,"steps":[{"position":1537,"character":"player","action":"warp","lines":["","","",""],"map":"map3"}]},{"func":"","x":10,"y":1,"steps":[{"position":2057,"character":"player","lines":["","","",""],"action":"warp","map":"map4"}]},{"func":"","x":16,"y":10,"steps":[{"character":"charismatic frog","lines":["","Would you be my friend?","",""],"action":"say"},{"character":"player","lines":["","OF COURSE!","",""],"action":"say"}]}]},{"loadword":"","objects":[{"func":"","x":1,"y":7,"steps":[{"position":1554,"character":"player","action":"warp","lines":["","","",""],"map":"map2"}]},{"func":"","x":9,"y":5,"steps":[{"lines":["","This wood would be perfect to","build a bridge with!",""],"action":"say","character":"player"},{"lines":["","Haha, \"wood would\". Wood would","wood would.",""],"action":"say","character":"player"},{"condition":"has scissors","character":"player","lines":["","Hey, I bet I could cut down this","tree with my cool time scissors!",""],"action":"say"},{"condition":"has scissors","character":"player","lines":["","","",""],"action":"disappear"},{"condition":"has scissors","character":"player","lines":["","Haha, awesome.","",""],"action":"say"},{"condition":"has scissors","flag":"has wood","action":"set-flag","lines":["","","",""],"rhs":{"label":"","value":65535},"character":"player"}]},{"func":"","x":15,"y":6,"steps":[{"lines":["","If only there was some convenient","way to cross this ankle-deep","stream!"],"action":"say","character":"player"},{"action":"say","character":"player","lines":["","Guess I'll just have to build a","raft and sail it across.",""],"condition":"has wood"},{"action":"disappear","character":"player","lines":["","","",""],"condition":"has wood"}]},{"func":"","x":6,"y":10,"steps":[{"action":"say","character":"snake","lines":["","Badger badger badger badger","badger badger badger badger","badger badger badger badger"]},{"action":"say","character":"player","lines":["","A snake! A snake!","",""]}]},{"func":"","x":17,"y":6,"steps":[{"character":"charismatic frog","lines":["","Ribbit.","",""],"action":"say"},{"character":"player","lines":["","I thought you'd be more","charismatic.",""],"action":"say"}]}],"tickword":"","moveword":"","map":"A1A1A1A1A1818181818181E1E181818181818181A1A1A1A18181818181818181E181818181818181A1A181818142810000008181E1E1818181000000A1000081818100000000818181E1E18181000000A100000000000000000000818181E181818100000000000000000000000000008181E18181810000A181810000000000000000000000E10062000000A181818181000000A10000818181E18181000000A1818181810000000000008181E1E18181000000A1A181818100000000818181E1E1818181818181A1A1A1818181000081818181E181818181818181A1A1A1A18181818181818181E181818181818181"},{"loadword":"","objects":[{"func":"","x":10,"y":6,"steps":[{"character":"stick bob","lines":["","Would you like to hear a jig","and a reel?",""],"action":"say"},{"character":"player","lines":["","Do you play the theremin?","",""],"action":"say"},{"character":"stick bob","lines":["","I can play anything!","",""],"action":"say"}]},{"func":"","x":10,"y":10,"steps":[{"position":265,"character":"player","lines":["","","",""],"action":"warp","map":"map2"}]},{"func":"","x":13,"y":4,"steps":[{"character":"player","lines":["","It's a fiddle. I promise.","I worked hard to draw it.",""],"action":"say"}]},{"func":"","x":7,"y":4,"steps":[{"character":"player","lines":["","Scissors with a clock on them?","They're super sharp!",""],"action":"say"},{"character":"player","lines":["","I'm sure they'll come in handy!","",""],"action":"say"},{"flag":"has scissors","action":"set-flag","lines":["","","",""],"rhs":{"label":"","value":65535},"character":"player"},{"character":"player","lines":["","","",""],"action":"disappear"}]}],"tickword":"","moveword":"","map":"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000600000000000000000000000606060606060600060606060606060000000000060C00000000000000000000000C060000000000060000000000000000000000000006000000000006000000000000002000000000000600000000000600000000000000000000000000060000000000060C00000210000000000220000C060000000000060606060606060606060606060606000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}],"flags":["has wood","has scissors","","has glasses"],"portraits":[{"gfx":"000000000000000000000000000000000000007C7C7E7E7E7E7E7E7E7E7E7E7E00000000707F7F7F7F7F7F7F7F7F7F7F7E7E7E7E7F7F7F7F7F7F7F7F7F7F7F7F0000000F0F1F1F1F1F1F1F1F1F1F1F1F000000000000000000000000000000001F1F1F1F7F7F7F7F7F7F7F7F7F7F7F7F00000000077F7F7F7F7F7F7F7F7F7F7F","label":"player","flags":[]},{"gfx":"00000000004040606060707070707070000000000000010103037F7F7F7F7F7F707060604000000000000000000000007F7F7F7F7F7F7800004040406060606000000000001018383C3C7F7F7F7F7F7F000000000000000000000000000000007F7F7F3F0F67717C7F7F7F7F7F7F7F7F00007C7E7F7F7F7F7F7F7F7F7F7F7F7F","label":"cat","flags":[]},{"gfx":"80808080808080808080D5818181858480808080808080808080AA80808080808484848484A4848484A48484848494D0809090D0D4F5D5D5D5D5D480808080AA80808080808080808080D5808080808080808080808080808080AAA0A0A0A888808080808AA8AAAAAA828080808080D588888888888889898888888888888A82","label":"angryfish","flags":[]},{"flags":[],"label":"old man","gfx":"0000000000000000000000000000000000000000000000707C7872737373736300000000303F3F3F7F7F7F7F7F7F7F7F0F7F7F7F7E7E7E7E7C7C79797979797300000000000000073F3F7F7F7F7F7F60000000000000000000000000000000000E7F3F3F3F3F7F7F7F7F7F7F7F3F1F1F00000000000000000004040C0C1C1E1F"},{"flags":[],"label":"stick bob","gfx":"808080808080808080A0A8E8E8F0F0F08080808080C0D4D5FDFFFFF3F1F1FFFFF0F0E0E0C08080808080808080808080FFFFF983FFBFBEFCF4D4D4D4D4D4D4D480808080808AAAABAFBFFFE7C7C7FFFF80808080808080808185858583838383FFFFCFE0FFFEBE8F8B8A8A8A8A8A8A8A83838383818080808080808080808080"},{"flags":[],"label":"snake","gfx":"000000000000808080808AA88A8080000000000000000014557155455054545000000020202020202020000000000000505455150505050505155554545040000000000000000000000202020202020200000000000000000000000000000000002020202000000000000002022A2A2A00000001010505051514141414150505"},{"flags":[],"label":"glasses","gfx":"000000000000000000000000000000000000007C7C7E7E7E7E555555757E7E7E00000000707F7F7F7F7F7F7F7F7F7F7F7E7E7E7E7F7F7F7F7F7F7F7F7F7F7F7F0000000F0F1F1F1F9FAAAAAAAB1F1F1F000000000000000000000000000000001F1F1F1F7F7F7F7F7F7F7F7F7F7F7F7F00000000077F7F7F7F7F7F7F7F7F7F7F"},{"flags":[],"label":"charismatic frog","gfx":"00000000000020202020202020202000000000005455555F47475555050055550000000000000000002820282028000054040404040404040405050505010000000000002A2A2A7A62622A2A2A002A2A000000000001050505050505050405012A20202020202020202020202000000000000000000000000015051505150000"}],"font":[{"flags":[],"gfx":"0000000000000000"},{"flags":[],"gfx":"081C1C1C08000800"},{"flags":[],"gfx":"3636241200000000"},{"flags":[],"gfx":"123F1212123F1200"},{"flags":[],"gfx":"083C0A1C281E0800"},{"flags":[],"gfx":"0026160834320000"},{"flags":[],"gfx":"0E1B1B062F1B3600"},{"flags":[],"gfx":"0C0C080400000000"},{"flags":[],"gfx":"180C0606060C1800"},{"flags":[],"gfx":"0C18303030180C00"},{"flags":[],"gfx":"082A1C081C2A0800"},{"flags":[],"gfx":"000C0C3F3F0C0C00"},{"flags":[],"gfx":"000000000C0C0804"},{"flags":[],"gfx":"0000001E1E000000"},{"flags":[],"gfx":"00000000000C0C00"},{"flags":[],"gfx":"002030180C060200"},{"flags":[],"gfx":"1C26263E26261C00"},{"flags":[],"gfx":"181C181818183C00"},{"flags":[],"gfx":"1C2620180C063E00"},{"flags":[],"gfx":"1C26201820261C00"},{"flags":[],"gfx":"2626263C30303000"},{"flags":[],"gfx":"3E061E2020201E00"},{"flags":[],"gfx":"1C26061E26261C00"},{"flags":[],"gfx":"3E2630180C0C0C00"},{"flags":[],"gfx":"1C26261C26261C00"},{"flags":[],"gfx":"1C26263C20201C00"},{"flags":[],"gfx":"000C0C000C0C0000"},{"flags":[],"gfx":"000C0C000C0C0804"},{"flags":[],"gfx":"30180C060C183000"},{"flags":[],"gfx":"00003E003E000000"},{"flags":[],"gfx":"060C1830180C0600"},{"flags":[],"gfx":"1C3630180C000C00"},{"flags":[],"gfx":"1E33212D3D011E00"},{"flags":[],"gfx":"1C3E26263E262600"},{"flags":[],"gfx":"1E26261E26261E00"},{"flags":[],"gfx":"1C26060606261C00"},{"flags":[],"gfx":"1E26262626261E00"},{"flags":[],"gfx":"3E06061E06063E00"},{"flags":[],"gfx":"3E06061E06060600"},{"flags":[],"gfx":"1C26063626263C00"},{"flags":[],"gfx":"2626263E26262600"},{"flags":[],"gfx":"3C18181818183C00"},{"flags":[],"gfx":"3C30303036361C00"},{"flags":[],"gfx":"2626261E26262600"},{"flags":[],"gfx":"0606060606063E00"},{"flags":[],"gfx":"373F2B2B23232300"},{"flags":[],"gfx":"26262E3626262600"},{"flags":[],"gfx":"1C26262626261C00"},{"flags":[],"gfx":"1E26261E06060600"},{"flags":[],"gfx":"1C26262626363C00"},{"flags":[],"gfx":"1E26261E26262600"},{"flags":[],"gfx":"3C26061C20221E00"},{"flags":[],"gfx":"3F0C0C0C0C0C0C00"},{"flags":[],"gfx":"2626262626261C00"},{"flags":[],"gfx":"2626261C1C1C0800"},{"flags":[],"gfx":"2323232B2B2A3600"},{"flags":[],"gfx":"2626261C26262600"},{"flags":[],"gfx":"2626261C18181800"},{"flags":[],"gfx":"3E3E30180C063E00"},{"flags":[],"gfx":"1C0C0C0C0C0C1C00"},{"flags":[],"gfx":"0002060C18302000"},{"flags":[],"gfx":"1C18181818181C00"},{"flags":[],"gfx":"081C260000000000"},{"flags":[],"gfx":"0000000000003E00"},{"flags":[],"gfx":"0C0C100000000000"}]} \ No newline at end of file diff --git a/game/init.fnl b/game/init.fnl index e2a5cd8..877dfe1 100644 --- a/game/init.fnl +++ b/game/init.fnl @@ -45,7 +45,7 @@ [:vm :hires :lit :map1 :load-level (vm:forever - (vm:hotswap-sync :lit :map1 :load-level) + (vm:hotswap-sync :full-redraw) :interactive-eval-checkpoint :handle-key ) diff --git a/link/mame.fnl b/link/mame.fnl index 7aad450..93a4adb 100644 --- a/link/mame.fnl +++ b/link/mame.fnl @@ -87,6 +87,20 @@ (when self.monitor (self.monitor:shutdown-session)) (when (nrepl:connected?) (nrepl:disconnect)) (set self.breakpoints {})) +(fn Machine.read [self addr len] + (-> (self:coro-eval + (.. "(let [bencode (require :bencode) + addr " addr " + len " len " + mem (. manager.machine.devices ::maincpu :spaces :program)] + (var bytes \"\") + (print :reading len :from addr) + (for [i 1 len] + (set bytes (.. bytes (string.char (mem:read_u8 (+ addr i -1)))))) + bytes)")) + ; result is piped through fennelview; have to eval it to turn it back into bytes + ; would be nice if io.write worked + (fennel.eval))) (fn Machine.write [self addr bytes] (if (> (bytes:len) 0x1000) (do (self:write addr (bytes:sub 1 0x1000)) @@ -103,11 +117,11 @@ (self:eval "(manager.machine:soft_reset)") (self:eval (string.format "(emu.keypost \"CALL-151\\n %xG\\n\")" (prg:lookup-addr prg.start-symbol)))) (fn Machine.reboot [self] (self:eval "(manager.machine:hard_reset)")) -(fn Machine.coro-eval [self code] +(fn Machine.coro-eval [self code ?handlers] (var result nil) (local append-to-result #(set result (.. (or result "") $2))) (self:eval code - (self:coro-handlers (coroutine.running) {:value append-to-result :out append-to-result})) + (self:coro-handlers (coroutine.running) {:value append-to-result :out append-to-result} ?handlers)) (coroutine.yield) (or result "")) (fn Machine.dbgcmd [self cmd ?handlers] @@ -130,10 +144,14 @@ (fn Machine.hotswap [self prg-old prg-new] (local addr (prg-old:lookup-addr :debug-stub)) (self:set-bp addr - (fn [] (self:clear-bp addr) - (prg-new:upload self) - (self:jump (prg-new:lookup-addr :on-hotswap)) - (self:continue)))) + #(util.in-coro (fn [] + (self:clear-bp addr) + (local hotswap (prg-old:read-hotswap self)) + (prg-new:upload self) + (prg-new:write-hotswap self hotswap) + (self:jump (prg-new:lookup-addr :on-hotswap)) + (self:continue))))) + (fn Machine.overlay [self prg-overlay] (self:step) (prg-overlay:upload self) diff --git a/link/nrepl-session.fnl b/link/nrepl-session.fnl index 94d7545..2ce491b 100644 --- a/link/nrepl-session.fnl +++ b/link/nrepl-session.fnl @@ -19,7 +19,7 @@ (fn Session.shutdown-session [self] (set self.queue []) (set self.in-progress false) - (set self.sesion nil)) + (set self.session nil)) (fn Session.cleanup-handlers [self] {:status/done #(self:done-msg) @@ -63,9 +63,11 @@ (fn Session.eval [self code ?handlers] (self:send {:op :eval : code} ?handlers)) +(fn Session.input-handler [self input] + {:status/need-input #(self:send-oob {:op :stdin :stdin input})}) + (fn Session.eval-input [self code input ?handlers] (self:send {:op :eval : code} - (lume.merge (or ?handlers {}) - {:status/need-input #(self:send-oob {:op :stdin :stdin input})}))) + (lume.merge (or ?handlers {}) (self:input-handler input)))) Session