(local util (require :lib.util)) (local lume (require :lib.lume)) (local {: parse} (util.require :presentation.engine)) (local style (require :core.style)) (local h {:style true :font (renderer.font.load "presentation/font/PrintChar21.ttf" (* 64 SCALE)) :color style.caret :justify :center :topPadding (* style.padding.y 2) :lowerPadding 64}) (local ** {:style true :font (renderer.font.load "presentation/font/PRNumber3.ttf" (* 32 SCALE)) :color style.text :justify :left :pause-after true}) (fn p [style] (lume.merge style {:pause-after true})) (fn np [style] (lume.merge style {:pause-after false})) (fn bgimg [filename] {:image filename :justify :center :overlay true :alpha 0.3 :topPadding 0}) (parse [ [h "" "" "Honeylisp" "" (np **) "Jeremy Penner" "https://spindleyq.itch.io/" "https://blog.information-superhighway.net/" "https://bitbucket.org/SpindleyQ/honeylisp" "https://gamemaking.social/@SpindleyQ" "https://twitter.com/SpindleyQ" {:pause-after true}] [(bgimg "presentation/pics/pete286.jpeg") h "Some Background" ** "In 2019 I built a 16-bit MS-DOS game engine." "* Built on hardware" "* Using only period-appropriate software (Turbo C, NeoPaint)" "* Powered by Forth" "* Integrated custom tools" "* Interactive development via serial terminal"] [(bgimg "presentation/pics/ggj2020.jpeg") h "Neut Tower" ** "In 2020, I did the Global Game Jam on my 286." "Finished 'Shareware Episode 1' a couple of months later."] [h "The Idea" ** "What if I took a similar DIY approach with modern tools?" "* I'd done Forth; what about Lisp?" "* How far can I push fast iterative development?" "* Could I integrate an editor?" "* How can I leverage emulation?"] [h "Honeylisp" ** "* Written in Fennel, a Lisp that compiles to Lua" "* Assembler" "* Forth-like 'virtual machine' / inner interpreter" "* 'lite' editor, ported to love2d" " * Integrated custom editors" "* MAME integration" " * Upload new builds directly into RAM" " * Interactive code injection" " * Hot code reload" "* Tape upload" "* ProDOS disk image generation"] [h "Assembler" ** "Represent instructions using Fennel data literals" " [:lda 0xff]" "Represent labels with Fennel strings" " :loop [:bne :loop]" "Lexical scope with nested blocks" " [:block :loop (generate-loop-code) [:bne :loop]]"] [h "Wait WTF Is An Assembler" ** "It's just converting mnemonics to bytes, right?" {:image "presentation/pics/assembly-markup.png" :justify :center :pause-after true} "Whoooops, actually the hard part is converting labels to addresses" "Zero-page instructions are a different size, which messes up data layout!" "Initial pass is needed to gather all symbols to determine sizes" "What about data?" " [:db 123] [:dw 12345] [:bytes \"HELLO WORLD\"] [:ref :hello]" "Must be able to line up bytes on page boundaries" " [:align 0x100]"] [h "Virtual Machine" {:image "presentation/pics/thinkhard.png" :justify :center} ** "Not super keen on writing a complicated compiler" "I'm already very comfortable with Forth" "Let's build a stack machine!" "\"Direct threaded\" inner interpreter" "\"Immediate words\" can be Fennel functions that generate code!"] [h "Extensible Assembler??" ** "How do you turn code into bytes?" " [:vm 1 2 :+ :.]"] ])