Dark Seed morgles

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

struct_c9h[20] {
 byte ARDEN;
 int32_t[20] humpty_dumpties_earlier;
 int32_t[20] humpty_dumpties_later;
 byte[20] borises;
 byte[20] charlies;
}
  • 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