S W I N E M E E P E R
=======================
Created for the DOS COM Game Jam 2023
https://itch.io/jam/dos-com-game-jam
Technical Details
-----------------
This source repository contains a full development toolchain for creating
DOS COM programs in Forth and assembly. This toolchain was written in a
custom Forth dialect originally built for Neut Tower[1]; through a fairly
involved bootstrapping process it is now completely capable of rebuilding
itself. Every byte of every .COM file in this repository has been generated
from the included 8086 assembler, including the .COM file of the assembler.
We start with MINIJORT.EXE, compiled with Borland Turbo C++ from MINIJORT.C
and MAIN.C. This is a stripped-down version of the Jorth engine that Neut
Tower[1] was built with, and the only part of this project that existed in
any form before August 14, 2023. (I started early on the jam because I
basically knew what I wanted to implement, and I knew that getting _anything_
playable by the end of September with the absurd plan I had in mind was
going to be a long shot.) MINIJORT.EXE is a simple Forth interpreter that
loads BOOT.JOR and then reads the rest of its input from stdin.
We then use MiniJort to generate TINYJORT.COM. This is done by piping the
contents of TINYBOOT.JRT to MiniJort. TINYBOOT loads some common definitions
from DEFS.JRT and the assembler from TARGET.JRT and ASM.JRT, then executes
TINYJORT.JRT, which assembles a second Forth interpreter that understands
a substantially similar vocabulary as MiniJort, with some improvements.
TinyJort internally embeds the definitions from BOOT.JOR and is entirely
self-contained.
We could load TINYBOOT into TINYJORT.COM to rebuild itself, but one of the
big advantages of TinyJort over MiniJort is that TinyJort is trivially
capable of adding more definitions to itself and then writing out a new
.COM file with those definitions already loaded. So the next step is to use
TinyJort to build ASSEMBLE.COM, which is just TinyJort with the basic defs
and assembler pre-loaded, ready to get to work as soon as you launch it,
saving precious seconds of build time. TINYJORT.JRT can be loaded directly
into ASSEMBLE.COM in order to produce a byte-exact copy of TINYJORT.COM.
REBUILD.BAT automates the process of bootstrapping TinyJort, and includes
a check to ensure that both Jorts produce the same .COM file. REASM.BAT
regenerates TINYJORT.COM and ASSEMBLE.COM using TINYJORT.COM and
ASSEMBLE.COM and is much faster.
But that's not enough Forth interpreters yet! This tooling would allow us
to write assembly code _using_ Forth, and it would allow us to _extend_
TinyForth to produce another Forth interpreter, but it does not yet allow
us to generate .COM files, written in Forth, that do not include extraneous
data like the Forth dictionary and the assembler. Since the .COM format is
limited to 64kb, space is at a premium. The final custom Forth interpreter
is ZIPOFF.COM and ZIPSTUB.SEG.
Why ZipOff? Imagine a pair of Jorts - these are the Forth interpreter,
assembler, and extended runtime. Now imagine extending these Jorts into
full-on Jeans, by bringing in the definitions of the code that needs to
actually be included in the final product. When the two pieces are together,
the host Jorts can take advantage of the immediate interactive development
workflow of Forth, calling out to words defined in the final .COM, and
providing useful debugging tools not needed for the final product. But once
the development cycle is complete, the legs of the Jeans can be jettisoned -
zipped off, if you will - and... worn on their own, I guess? The metaphor
breaks down a little bit here. The point is that the target .COM file is
minimal and completely self-sufficient.
Yo dawg, I heard you liked Forth, so I wrote a Forth interpreter in Forth
that I used to implement another Forth.
THIS, finally, is the tool we use to build games and demos with. Importing
SWINE.JRT into ZipOff produces SWINE.COM; importing DIRTRECT.JRT produces
DIRTRECT.COM, and so forth.
[1] https://spindleyq.itch.io/neut-tower/