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 ;
|
||||
|
||||
{ :timm deftheme CREATE >t >t >t >t >t >t DOES} theme ! ;
|
||||
( cursor grid block mine flag bg )
|
||||
blue white black black red lgray deftheme win31
|
||||
white yellow black black yellow red deftheme hotdog
|
||||
( cursor grid block mine flag bg )
|
||||
blue white black magenta red lgray deftheme win31
|
||||
white yellow black lmagenta yellow red deftheme hotdog
|
||||
|
||||
win31
|
||||
|
||||
|
@ -97,7 +97,7 @@ win31
|
|||
NEIGHBOUR-MASK & dup col-count
|
||||
dup if [ key 0 lit ] + else drop [ key lit ] then 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-revealed ( b -- )
|
||||
dup FMINE & if draw-mine drop else draw-neighbour-count then ;
|
||||
|
@ -207,4 +207,60 @@ IN-PROGRESS bvar, game-state
|
|||
|
||||
' 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