Dark Seed for DOS
Flow between game programs
The game code passes back and forth between two executables
(START.EXE
and TOS.EXE
) via a batch
script (DS.BAT
).
START.EXE plays slideshow sequences like the opening credits, the animated nightmares, and the double visions (doll/alien).
TOS.EXE handles the interactive gameplay.
When TOS.EXE wants START.EXE to play a sequence, it writes the fifth byte of the five-byte PREFS file to signal which sequence, then terminates itself with an exit code. DS.BAT then proceeds to launch START.EXE, which reads PREFS and sees that fifth byte. START.EXE exits with an error code so DS.BAT launches TOS.EXE which (if appropriate) loads a special auto-save game and appears to continue from where it left off.
Some file structures
ART files: IMG and ANM
These are read by START.EXE (function around 0x7471)
table of offsets to filenames including IMG and ANM files mostly
assumes data segment of 0xa38 (section.seg_008
)
header 4 bytes
first 2 bytes of header is word count of words to read?
second 2 bytes is word index of something
these values in ANM files are low
0x4c is the biggest first word in ANM files 0x148 is the biggest second word in ANM files
on the other hand, IMG files have much bigger values 0xdac9 0xf608
maybe they are a different format and loader
the variable-length section following the four-byte header is n words long (based on first header word) and loaded into memory at an offset from 0xaa4 (based on the second word)
after that, the remaining bytes from the file are loaded a
segment at a time into the memory address based on
[word at 0xf24]
+[word at 0xaa2]
presumably 0xf24 is the segment to load animation data into and 0xaa2 is the length (end-segment)
after loading, first-word bytes are set to 1 starting at 0xda4 + index (second word)
somewhere something reads word for x then word for y
then reads word, word, byte from ds:4, seemingly height, width, starting memory offset
nsp seems to be a fixed number of pairs of bytes.
- width0, height0
- width1, height1
- width2, height2
- ...
- width95, height95
then 96 rectangular images, 4 bits-per-pixel, minimum of one byte, odd widths padded out to byte level.
OBT files
obt201 structure
indexed by "di" (< 0x14) multiplied by 0xc9
further indexed by "si" (< 0x14 also) multiplied by 4 presumably one field is an array of (20?) 4-structs??
offset 0 byte ARDEN read from file
offset 1 word lsb of something from file, divided by 100
offset 3 word msb of something from file, divided by 100
offset 0x51 word lsb of something from file, divided by 100
offset 0x53 word msb of something from file, divided by 100 (possibily negated and subtract-with-carry)
substructure
- offset 0xa1 byte BORIS read from file
- offset 0xb5 byte CHARLIE read from file
a different word array ending at ds:0x63e5
indexed
by di (< 0x14) values are bytes (msb 0) taken from
obt201[di * 0xc9 + 0xb5]
at the beginning of each "di" loop, a byte ARDEN is read from
the file and stored at di*0xc9+0
at the beginning of each "si" loop, a byte MINGO is read then
two bytes HUMPTY-DUMPTY which form a word value (dumpty is MSB)
this value is divided by 100 and stored in the four bytes starting
at di*0c9+si*4+1
if MINGO was nonzero, the value is
negated
another three bytes are read in the same way, MINGO, HUMPTY,
DUMPTY the same process applies but the result of the division (and
possibly negation) is stored at the four bytes starting at
di*0xc9+si*4+0x51
(0x50 bytes later)
the next byte, BORIS, is read from the file and stored at
di*0xc9+si+0xa1
the next byte, CHARLIE, is read from
the file and stored at di*0xc9+si+0xb5
(20 bytes after
where BORIS is stored)
this continues 20 times, for each "si" value in the loop
at the end of the "di" loop, the CHARLIE byte for si 0 is stored in an external array
so in summary
the file is 3220 bytes (and most are exactly that, though a few are 3072 bytes)
20 * [
[ARDEN] for this diset
20 * [
[ MINGO, HUMPTY, DUMPTY ] for 1
[ MINGO, HUMPTY, DUMPTY ] for 20 * 4
[ BORIS ]
[ CHARLIE ]
]
]
and the data structure is
[20] {
struct_c9h;
byte ARDENint32_t[20] humpty_dumpties_earlier;
int32_t[20] humpty_dumpties_later;
[20] borises;
byte[20] charlies;
byte}
- ARDEN bytes are often 1, CHARLIE bytes are often 5, the rest are usually 0.
- ARDEN bytes can be 9, 10, 4, 5, 8, even 17
- BORIS and CHARLIE can both be 255
- BORIS can be 1, 2, 3, 4, 5, 6, 7, 8 -- seems sequential
- CHARLIE can be 3, 5 but not seemingly not much else