2021-06-19 01:31:21 +00:00
|
|
|
(local util (require :lib.util))
|
2021-06-22 02:09:09 +00:00
|
|
|
(local lume (require :lib.lume))
|
2021-06-19 01:31:21 +00:00
|
|
|
(local {: parse} (util.require :presentation.engine))
|
2021-06-29 03:05:17 +00:00
|
|
|
(local core (require :core))
|
2021-06-19 01:31:21 +00:00
|
|
|
(local style (require :core.style))
|
2021-07-02 15:49:36 +00:00
|
|
|
(local TileEditView (require :editor.tileedit))
|
|
|
|
(local MapEditView (require :editor.mapedit))
|
|
|
|
(local PortraitEditView (require :editor.portraitedit))
|
|
|
|
(local FontEditView (require :editor.fontedit))
|
|
|
|
(local ScreenEditView (require :editor.screenedit))
|
2021-07-04 17:42:00 +00:00
|
|
|
(local files (require :game.files))
|
2021-07-02 15:49:36 +00:00
|
|
|
|
2021-06-19 01:31:21 +00:00
|
|
|
(local h
|
2021-06-22 02:09:09 +00:00
|
|
|
{:style true
|
2021-07-04 17:42:00 +00:00
|
|
|
:font (renderer.font.load "presentation/font/PrintChar21.ttf" 64)
|
2021-06-19 01:31:21 +00:00
|
|
|
:color style.caret
|
2021-06-22 02:09:09 +00:00
|
|
|
:justify :center
|
2021-07-04 17:42:00 +00:00
|
|
|
:topPadding 14
|
2021-06-22 02:09:09 +00:00
|
|
|
:lowerPadding 64})
|
2021-06-19 01:31:21 +00:00
|
|
|
(local **
|
2021-06-22 02:09:09 +00:00
|
|
|
{:style true
|
2021-07-04 17:42:00 +00:00
|
|
|
:font (renderer.font.load "presentation/font/PRNumber3.ttf" 32)
|
2021-06-19 01:31:21 +00:00
|
|
|
:color style.text
|
|
|
|
:justify :left
|
2021-07-04 17:42:00 +00:00
|
|
|
:lowerPadding 7
|
2021-06-19 01:31:21 +00:00
|
|
|
:pause-after true})
|
2021-06-22 02:09:09 +00:00
|
|
|
(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})
|
2021-06-19 01:31:21 +00:00
|
|
|
|
2021-06-29 03:05:17 +00:00
|
|
|
(fn view-cleanup [view]
|
|
|
|
(let [root core.root_view.root_node
|
|
|
|
node (root:get_node_for_view view)]
|
|
|
|
(when node (node:close_active_view root))))
|
|
|
|
|
2021-07-04 17:42:00 +00:00
|
|
|
(fn split-and-open [self f]
|
2021-07-02 15:49:36 +00:00
|
|
|
(let [focused-view core.active_view
|
|
|
|
focused-node (core.root_view:get_active_node)
|
2021-07-04 17:42:00 +00:00
|
|
|
_ (when self.split (focused-node:split self.split))
|
|
|
|
view (f self)
|
2021-07-02 15:49:36 +00:00
|
|
|
node (core.root_view:get_active_node)]
|
|
|
|
(when (= (core.root_view.root_node:get_node_for_view view) nil) (node:add_view view))
|
2021-07-04 17:42:00 +00:00
|
|
|
(when self.split (core.set_active_view focused-view)) ; don't switch focus
|
2021-07-02 15:49:36 +00:00
|
|
|
#(view-cleanup view)))
|
|
|
|
|
2021-07-04 17:42:00 +00:00
|
|
|
(fn openview [f ?extra] (lume.merge {:action #(split-and-open $1 f)} (or ?extra {})))
|
2021-07-04 02:13:04 +00:00
|
|
|
(fn openfile [filename ?extra]
|
2021-07-04 17:42:00 +00:00
|
|
|
(openview #(let [ldoc (core.open_doc filename)
|
|
|
|
view (core.root_view:open_doc ldoc)]
|
|
|
|
(when $1.line (view:scroll_to_line $1.line))
|
|
|
|
view)
|
|
|
|
?extra))
|
2021-06-29 03:05:17 +00:00
|
|
|
|
2021-06-19 01:31:21 +00:00
|
|
|
(parse [
|
2021-06-29 03:05:17 +00:00
|
|
|
[h "" "" ""
|
|
|
|
"Honeylisp"
|
|
|
|
"" "" ""
|
2021-06-22 02:09:09 +00:00
|
|
|
(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"
|
2021-06-19 01:31:21 +00:00
|
|
|
** "In 2019 I built a 16-bit MS-DOS game engine."
|
|
|
|
"* Built on hardware"
|
2021-06-22 02:09:09 +00:00
|
|
|
"* 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"
|
2021-06-19 01:31:21 +00:00
|
|
|
** "In 2020, I did the Global Game Jam on my 286."
|
2021-06-22 02:09:09 +00:00
|
|
|
"Finished 'Shareware Episode 1' a couple of months later."]
|
|
|
|
[h "The Idea"
|
2021-06-29 03:05:17 +00:00
|
|
|
** "What if I took a similar DIY approach with modern tooling?"
|
2021-06-22 02:09:09 +00:00
|
|
|
"* I'd done Forth; what about Lisp?"
|
2021-06-29 03:05:17 +00:00
|
|
|
" https://fennel-lang.org/"
|
2021-06-22 02:09:09 +00:00
|
|
|
"* How far can I push fast iterative development?"
|
|
|
|
"* Could I integrate an editor?"
|
|
|
|
"* How can I leverage emulation?"]
|
2021-06-29 03:05:17 +00:00
|
|
|
[h "Step 1: Assembler"
|
|
|
|
** "Represent instructions using Fennel data literals"
|
2021-07-04 17:42:00 +00:00
|
|
|
(openfile :neuttower/defs.fnl {:split :right :line 57})
|
2021-06-22 02:09:09 +00:00
|
|
|
" [:lda 0xff]"
|
|
|
|
"Represent labels with Fennel strings"
|
|
|
|
" :loop [:bne :loop]"
|
|
|
|
"Lexical scope with nested blocks"
|
|
|
|
" [:block :loop (generate-loop-code) [:bne :loop]]"]
|
2021-07-02 15:49:36 +00:00
|
|
|
; ;; DEMO before tech dive??
|
2021-06-22 02:09:09 +00:00
|
|
|
[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]"]
|
2021-06-29 03:05:17 +00:00
|
|
|
[h "Step 2: Virtual Machine"
|
2021-06-22 02:09:09 +00:00
|
|
|
{: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?"
|
2021-07-02 15:49:36 +00:00
|
|
|
" [:vm 1 2 :+ :.]"
|
|
|
|
"Branching?"
|
|
|
|
" (vm:if [:do-true-thing] [:do-false-thing])"
|
|
|
|
"I can even do short-circuiting OR!"
|
|
|
|
" (vm:if-or [[:dup 1 :=] [:dup 3 :=]] [:do-true-thing] [:do-false-thing])"]
|
|
|
|
[h "Step 3: Tooling And Workflow"
|
|
|
|
** "I want an environment that makes it easy to make graphical tools"
|
|
|
|
"I'm SO tired of web tech"
|
|
|
|
"Could LÖVE2D with an imgui work?"]
|
|
|
|
[h "lite"
|
|
|
|
** "A small, highly-extensible text editor written in Lua"
|
|
|
|
"Backend is SDL"
|
|
|
|
"Could I rewrite it to run under LÖVE2D?"
|
|
|
|
" Yes! In a weekend!"]
|
|
|
|
[h "Custom Editors"
|
2021-07-04 17:42:00 +00:00
|
|
|
** "Retro game programming is just the process of writing a series of barely-usable custom paint programs."
|
|
|
|
{:action #(files.reload :neuttower/game.json)}
|
|
|
|
"14x16 tile editor"
|
2021-07-02 15:49:36 +00:00
|
|
|
(openview #(TileEditView))
|
|
|
|
"Font editor"
|
|
|
|
(openview #(FontEditView))
|
|
|
|
"Portrait editor"
|
|
|
|
(openview #(PortraitEditView))
|
|
|
|
"Map editor"
|
|
|
|
(openview #(MapEditView))
|
2021-07-04 17:42:00 +00:00
|
|
|
"Full-screen bitmap editor"
|
2021-07-04 02:13:04 +00:00
|
|
|
(openview #(ScreenEditView :neuttower/title.screen) {:pause-after true})
|
|
|
|
(openfile :presentation/slides.fnl {:split :right :line 133})
|
|
|
|
"Presentation viewer!?"]
|
|
|
|
[h "Editing Editors With My Editor"
|
|
|
|
** "Lua provides a very dynamic environment that allows me tremendous flexibility"
|
|
|
|
(openview #(MapEditView))
|
2021-07-04 17:42:00 +00:00
|
|
|
(openfile :editor/mapedit.fnl {:split :right :line 235})
|
2021-07-04 02:13:04 +00:00
|
|
|
"Downside:"
|
|
|
|
{:image "presentation/pics/bsod.png" :justify :center :pause-after true}]
|
|
|
|
[h "Step 4: Emulator Integration"
|
|
|
|
** "Directly inspired by Dagen Brock's 2016 KFest talk on GSPlus"
|
|
|
|
"Ended up using MAME - has a full Lua plugin system"
|
|
|
|
"What if I could poke my program directly into an emulator's memory?"
|
|
|
|
"What if I could preserve the current runtime state but rewrite the code?"
|
|
|
|
"... even if the data has moved?"
|
|
|
|
"What if I could interactively try out new code while my game was running?"]
|
|
|
|
[h "Step 5: Running on Hardware"
|
|
|
|
** "I have a IIgs with a serial cable - I can poke bytes in directly from the monitor"
|
|
|
|
"]IN#2\n]PR#2\n]CALL-151"
|
|
|
|
"Easy to send bytes faster than the monitor can process them"]
|
|
|
|
[h "Audio"
|
|
|
|
** "I have a II+ with a cassette port"
|
|
|
|
"LÖVE2D is a game engine - my editor can generate audio and play it back immediately"
|
|
|
|
"Need to generate a BASIC program to bootstrap my machine code"
|
|
|
|
(openfile :asm/tape.fnl {:split :right})
|
|
|
|
" [:basic [10 :call :2061]]"
|
|
|
|
"Future work: Apple Game Server fastloader"]
|
2021-07-04 17:42:00 +00:00
|
|
|
[(bgimg "presentation/pics/beneath-apple-prodos.png")
|
|
|
|
h "ProDOS"
|
|
|
|
** "Disk image is a must-have for distribution"
|
|
|
|
(openfile :asm/prodos.fnl {:split :right :line 132})
|
|
|
|
"Of course I wrote my own disk image generation code!"
|
|
|
|
"Start with a blank ProDOS disk and add to it"
|
|
|
|
"Fun bugs!"
|
|
|
|
"* Accidentally implemented undelete instead of inserting new files at first"
|
|
|
|
"* Read the free space bitmap backwards and overwrote the OS"
|
|
|
|
"* Tried to name a volume starting with a number"]
|
|
|
|
[(bgimg "presentation/pics/boot-tower.jpeg")
|
|
|
|
{:action #(files.reload :neuttower/game.json)}
|
|
|
|
h "Neu] [ower"
|
|
|
|
** "A small puzzle adventure game!"
|
|
|
|
"--== D E M O ==--"]
|
|
|
|
[(bgimg "presentation/pics/bitsy.png")
|
|
|
|
{:action #(files.reload :bitsy/game.json)}
|
|
|
|
h "8-Bitsy"
|
|
|
|
** "Bitsy is a popular free, accessible, web-based game-making tool"
|
|
|
|
"Spring Lisp Game Jam - 10 days to hack"
|
|
|
|
"Could I make my tools a little less... programmer-y?"
|
|
|
|
(openview #(MapEditView) {:pause-after true})]
|
|
|
|
[h "Thanks!"
|
|
|
|
(openfile :neuttower/level6.fnl {:split :right :line 153})
|
|
|
|
** "Questions?"]
|
2021-06-19 01:31:21 +00:00
|
|
|
])
|