renamed to Swine Meeper, title screen, readme
This commit is contained in:
parent
66dcbbdbd7
commit
e98c04584a
73
readme.txt
Executable file
73
readme.txt
Executable file
|
@ -0,0 +1,73 @@
|
||||||
|
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/
|
|
@ -87,9 +87,9 @@ var theme
|
||||||
countcolors + b@ dup 0 colvar = if drop col-grid else fg! then ;
|
countcolors + b@ dup 0 colvar = if drop col-grid else fg! then ;
|
||||||
|
|
||||||
{ :timm deftheme CREATE >t >t >t >t >t >t DOES} theme ! ;
|
{ :timm deftheme CREATE >t >t >t >t >t >t DOES} theme ! ;
|
||||||
( cursor grid block mine flag bg )
|
( cursor grid block mine flag bg )
|
||||||
blue white black black red lgray deftheme win31
|
blue white black magenta red lgray deftheme win31
|
||||||
white yellow black black yellow red deftheme hotdog
|
white yellow black lmagenta yellow red deftheme hotdog
|
||||||
|
|
||||||
win31
|
win31
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ win31
|
||||||
NEIGHBOUR-MASK & dup col-count
|
NEIGHBOUR-MASK & dup col-count
|
||||||
dup if [ key 0 lit ] + else drop [ key lit ] then draw-char ;
|
dup if [ key 0 lit ] + else drop [ key lit ] then draw-char ;
|
||||||
: draw-flag ( -- ) col-flag 0x0d draw-char ;
|
: draw-flag ( -- ) col-flag 0x0d draw-char ;
|
||||||
: draw-mine ( -- ) col-mine 0x0f draw-char ;
|
: draw-mine ( -- ) col-mine 0xec draw-char ;
|
||||||
: draw-block ( -- ) col-block 0xb1 draw-char ;
|
: draw-block ( -- ) col-block 0xb1 draw-char ;
|
||||||
: draw-revealed ( b -- )
|
: draw-revealed ( b -- )
|
||||||
dup FMINE & if draw-mine drop else draw-neighbour-count then ;
|
dup FMINE & if draw-mine drop else draw-neighbour-count then ;
|
||||||
|
@ -207,4 +207,60 @@ IN-PROGRESS bvar, game-state
|
||||||
|
|
||||||
' start ' main redefine
|
' start ' main redefine
|
||||||
|
|
||||||
{ s" mines.com" writecom }
|
( title menu )
|
||||||
|
array title-text t", SWINE MEEPER"
|
||||||
|
|
||||||
|
: emptych? ( ch -- f ) dup 32 = swap 0 = or ;
|
||||||
|
: drawdot? ( st -- f ) dup b@ emptych? swap 1+ b@ emptych? or not ;
|
||||||
|
|
||||||
|
: dot 7 draw-char ;
|
||||||
|
: sp 32 draw-char ;
|
||||||
|
: spacer ( st -- ) sp drawdot? if dot else sp then sp ;
|
||||||
|
|
||||||
|
: draw-spaced-text ( st -- )
|
||||||
|
begin dup b@ dup while draw-char dup spacer 1+ repeat drop drop ;
|
||||||
|
|
||||||
|
2 cells const menu-optsize
|
||||||
|
2 const menu-size
|
||||||
|
array menu-options menu-optsize menu-size * allot
|
||||||
|
|
||||||
|
: menu-option ( iopt -- p ) menu-optsize * menu-options + ;
|
||||||
|
: defmenu ( cp name iopt -- ) menu-option dup >rot ! cell + ! ;
|
||||||
|
|
||||||
|
' start s" Start Game" 0 defmenu
|
||||||
|
' terminate s" Quit" 1 defmenu
|
||||||
|
|
||||||
|
0 var, menu-selected
|
||||||
|
|
||||||
|
: menu-activate menu-selected @ menu-option cell + @ execute ;
|
||||||
|
|
||||||
|
: draw-selection ( iopt -- )
|
||||||
|
menu-selected @ = if draw-mine else sp then sp ;
|
||||||
|
: draw-option ( iopt -- ) white fg! menu-option @ draw-text ;
|
||||||
|
: draw-menu
|
||||||
|
33 10 textxy!
|
||||||
|
textx 0 begin dup menu-size < while
|
||||||
|
dup draw-selection dup draw-option 1+ nextline over textx! repeat
|
||||||
|
drop drop ;
|
||||||
|
|
||||||
|
: draw-title
|
||||||
|
blue bg! yellow fg! 32 fill-page
|
||||||
|
17 3 textxy! title-text draw-spaced-text
|
||||||
|
draw-menu ;
|
||||||
|
|
||||||
|
: menu-selected! ( i -- )
|
||||||
|
dup 0 >= over menu-size < and if menu-selected ! else drop then ;
|
||||||
|
: menu-selected+! ( di -- ) menu-selected @ + menu-selected! ;
|
||||||
|
|
||||||
|
: await-menu
|
||||||
|
wait-key key>scan
|
||||||
|
dup %esc = if terminate then
|
||||||
|
dup %up = if -1 menu-selected+! then
|
||||||
|
dup %down = if 1 menu-selected+! then
|
||||||
|
%enter = if menu-activate then ;
|
||||||
|
|
||||||
|
: title draw-title begin await-menu draw-menu again ;
|
||||||
|
|
||||||
|
' title ' main redefine
|
||||||
|
|
||||||
|
{ s" swine.com" writecom }
|
Loading…
Reference in a new issue