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 with the absurd plan I had in mind, I knew that getting _anything_ playable by the end of September 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/