Dark Seed investigation

Dark Seed was a video game released by Cyberdreams. The first release was in 1992 for MS-DOS with VGA graphics.

The manual suggests that Lennard Fedderson (Ironwind Software) had been "developing an engine for this type of game since September 1990". Federson's name appears in the game credits along with other programmers but there is no mention of Ironwind Software nor "Tos" in the public-facing resources.

The DOS edition has file names with some consistent extensions

# type
107 PAL files (presumably palettes)
104 OBT (objects?)
104 NSP (animations?)
98 PIC (still images)
66 ROM files (room defintions?)
24 VOC files (voice recordings etc, standard file format)
22 SBR (music as well)
22 PCS (maybe music?)
17 SIT (instruments for music maybe?)
17 DIG (music)
2 EXE (START and TOS)
1 SPR (mouse pointer sprites etc, bitmap with indexed-colour bytes)
1 SBI
1 PREFS (a five-byte store)
1 NTE
1 NAM
1 BIN (uncompressed text resource database)
1 ADT (a font made of only 08 and 0f bytes plus a few 00s at the end)

Palette files

Dark Seed includes over 100 separate PAL files. Almost all of them are exactly 48 bytes in size, while three of them are 768 bytes (CYBER.PAL, TITLE.PAL, and TOSSTD.PAL).

The 48-byte files are presumably 16 colours. The colours are stored with no header. Three bytes per colour entry: one byte for red, one byte for green, one byte for blue. VGA colours supported 64 levels of each channel, so the bytes range from 0x00 to 0x3f.

r0 g0 b0 r1 g1 b1 r2 g2 b2

The 768-byte files are the same headerless format, but they cover 256 colours.

TOSICONS.SPR

The one and only SPR file is called TOSICONS.SPR and contains a bunch of images.

The header is pairs of bytes (width, height) that represent the size in bytes (and pixels) of each image. 0x25 0x0f means 0x25 pixels (bytes) wide by 0xf pixels (bytes) high.

offset width height description
0x021? ???
0x102 15 15 <-> horizontal arrows
0x1e3 15 15 vertical arrows
0x2c4 15 15 floppy disk (save)
0x3a5 15 15 hand
0x486 15 15 turn-right arrow
0x648 15 15 plus
0x729 15 15 minus
0x80a 15 15 left arrow
0x8eb 15 15 right arrow
0x9cc 39 15 undo button
0xc15 37 15 help button
0xe40 48 17 scrap button
0x1170 37 11 quit button
0x139b 120 120 title screen (120x120)
0x4bdb 11 12 smaller hand
15 15 bottle/pot/brush?
35 16 yes button
29 16 no button
39 16 ok button
49 17 cancel button
0x56f1 9 10 scrollbar up
0x574b 9 10 scrollbar down
0x57a5 9 47 scrollbar
0x594c 15 15 scissors tool
0x5a1e 15 15 magnify/tweezer tool
0x5b0e 15 15 ?? tool
0x5bef 15 15 hammer tool
0x5cd0 15 15 film camera tool
0x5db1 15 15 film strip tool
0x5e92 0x2e 16 links button
0x6172 49 17 background button
0x64b2 0x33 17 insert button
0x6826 0x33 17 delete button
41 next button
41 lost button

PIC files

These are presumably images of some sort. The filenames seem to mostly be locations: GARAGE.PIC, STORE.PIC, STUDYA.PIC.

There are nearly a hundred PIC files, and they vary in bytes somewhat. They range from around 20kB to around 60kB but most tend to be around 40 kilobytes, give or take 5 kilobytes.

Many of the pictures are presumably the same pixel dimensions as each other, so the variation in bytes suggests some compression.

The file with the biggest byte size is GFRAME.PIC and it begins with the same byte sequence as the similarly-named CFRAME.PIC:

02 80 01 5e

All the other PIC files begin with another byte sequence:

01 f5 00 c8

These four byte headers can be interpreted as a pair of big-endian 16-bit integers:

width height
0x0280 (640) 0x015e (350) the two FRAME pictures
0x01f5 (501) 0x00c8 (200) the remaining pictures

Since the game is advertised to use "high resolution" 640x350 graphics, it seems reasonable that the FRAME graphics would cover that whole size and the location pictures which go in the smaller area inside the frame would be a second smaller size.

Byte forking examination

CLCARD.PIC starts with the same 4-byte header that all the inner pictures have, then the same 45 bytes as dozens of other light-world pictures. It then has a 19-byte sequence where the others have 28-and-a-half bytes before the nybble values align again for a long stretch. This suggests several things:

  • The light world inner pictures start with the same 45 bytes, perhaps representing the overlaid frame
  • The format can align on half-byte (nybble) values

The CLCARD nybbles align with all the other light pictures for another 75 half-bytes (37.5 bytes) where CLCARD has a run of 20 nybbles, alternating 8 and 0, where the others have 35 nybbles with a little more variation.

After that it's back to a shared run for 167 nybbles. Five light-world pictures - JOURN01, BNOC, CARINT, CJOUR201, CLADY share the same initial 4+211 bytes

DIG and SIT files

Although Dark Seed comes with more than a dozen DIG files, they are mostly copies of each other. There are only four unique files, and one of those four is essentially blank (repeating the three-byte sequence 00-03-00 over and over).

I believe they are music (and perhaps music-like sound effects). The biggest files (HOUSE, QUIET, TOS1, and TOWN) probably contain instrument definitions (FM synthesiser configuration) while the smaller ones probably only contain which notes to play.

Every DIG file has a SIT file with a matching name. QUIET.DIG and QUIET.SIT, BOOK.DIG and BOOK.SIT.

Every SIT file is exactly 4096 bytes. Most SIT files are unique, but six have the exact same content as each other (ALIEN, CREDITS, DOLL, IMPLANT, NIGHT2 and NIGHT3)

SBR and PCS files

Each pair of DIG and SIT files has a matching pair of SBR and PCS files. Furthermore, there are five more SBR/PCS pairs beyond the ones that match DIG/SIT.

ROM files

Each of the 66 ROM files are exactly 1187 bytes. There are big stretches of 00 bytes as well as fairly long stretches of 0xff bytes in each one. Many of these 0xff stretches are in the same position or at least end in the same position./202e70696300

Each file begins with fixed-length "8.3" null-terminated (ASCIIZ) filenames.

Here "x" represents a space, which is eliminated in DOS file access (presumably).

offset format ROOM0.ROM ROOM1.ROM ROOM2.ROM ROOM3.ROM
0 12z "EDITxxxx.nsp" "CBASExxx.nsp" "EDITxxxx.nsp"
0xd 12z "BED1Axxx.pic" "BED2Axxx.pic" "SECRET1x.pic" "SECRET2x.pic"
0x1a 12z "CYBERxxx.pal" "ROOM1xxx.pal" "ROOM2xxx.pal "ROOM0xxx.pal"
0x27 uint16? 01ad 00c3 0060 005b
0x29 uint16? 005e 006a 0084 0093
0x2b uint16? 000f 000f 0002 0002
0x2d uint16? 0002 0002 000f 000f
0x2f uint16? 0004 0004 0000 0009
0x31 uint16? 0001 0001 0301 0301
0x33 uint16? 3000 4000 8200 ea00
0x35 uint16? 5d00 6a00 db00 8700
0x37 uint16? 0f00 0f00 0200 0200
0x39 uint16? 0200 0200 0f00 0f00
0x3b uint16? 0500 0500 0301 ff01
0x3d uint16? 0205 00bd 0138
0x3f uint16? 008b 0075 008b
...
0x7f 640[uint8]? 40-stride 40-stride 40-stride
0x28f 0x60[uint8]?
0x2ff 30[7[uint16]]

Most (all?) room files seem to have some stretches that look like a visual bitmap if you view them with 40-byte strides (beginning at offset 0x7f).

At least 11 rows, probably 15 or 16 rows. Seems to be 640 bytes.

Just before that visual map there's a section that seems to be pattern with a 11-byte stride.

ROOM4.ROM has at offset 0x53 9 null bytes followed by 0xff 0x03, then that 11-byte pattern repeated four times. Same for ROOM3.ROM and ROOM1.ROM.

Just after the visual map there's a pattern of bytes that are valued either 01 or 00. offset 0x287 in ROOM10.ROM - and seems to make a pattern with stride length of 16 bytes. Maybe 6 or 7 rows of that pattern.

Some rooms (ROOM2, ROOM3) seem to have all-zero rows beginning at 0x25f.

Near the end of the file are 14-byte stride patterns. and some stretches that look patterned with 14-byte strides (starting at 0x36f)

It might be these 14-byte data structures always start at offset 0x2ff and the repeating pattern is an empty slot or something.

In fact, these 14-byte data structures start with 0000, 0001, 0004, or 03e8 and 0x3e8 is decimal 1000. Perhaps they are the target information: bounding boxes (x, y, width, height?), command (look, touch, go to?).

The lines that start with 0004 seem to follow a fairly predictable pattern:

0004 sequence sub600 sub240 usuallycor7 usallyc seqseq

The sequence seems to be (mostly) 1 for the first 0004 line, 2 for the second, and so on. The final two bytes seem to be (almost always) the same value as the sequence, so a line beginning with 00040002 will almost certainly end with 0202.

ps @ 13
px 13 * 40 @ 0x7f @e:hex.cols=40
px 8 * 16 @ 0x28f @e:hex.cols=16

Looking at the shapes in the 40-stride visualisation and being familiar with the game suggests that this area is a representation of the walkable parts of the room, "turned on its side and flipped": The first bytes represent the left of the screen, from top to bottom, with each successive 40 bytes representing another vertical slice of the room. The last 40 bytes of this section represent the rightmost slice of the play area.

room file picture file
ROOM0.ROM BED1A.pic
ROOM1.ROM BED2A.pic
ROOM2.ROM SECRET1.pic
ROOM3.ROM SECRET2.pic
ROOM4.ROM BATHA.pic
ROOM5.ROM UPHALLA.pic
ROOM6.ROM DOWNHALL.pic
ROOM7.ROM LIVINGA.pic
ROOM8.ROM KITCHENA.pic
ROOM9.ROM STUDYA.pic
ROOM10.ROM STREETA.pic
ROOM11.ROM STREETB.pic
ROOM12.ROM STREETC.pic
ROOM13.ROM ROOF.pic
ROOM14.ROM PATHA.pic
ROOM15.ROM POLICE.pic
ROOM16.ROM STORE.pic
ROOM17.ROM LDESK.pic
ROOM18.ROM LPERIOD.pic
ROOM19.ROM STACKA.pic
ROOM20.ROM STACKB.pic
ROOM21.ROM STACKC.pic
ROOM22.ROM STACKD.pic
ROOM24.ROM CEMA.pic
ROOM25.ROM CEMB.pic
ROOM26.ROM CEMC.pic
ROOM27.ROM CEMD.pic
ROOM28.ROM STACK.pic
ROOM30.ROM NCELL1.pic
ROOM31.ROM DELYARD.pic
ROOM32.ROM SIDE.pic
ROOM33.ROM GARAGE.pic
ROOM34.ROM CARINT.pic
ROOM35.ROM ANTE.pic
ROOM36.ROM BALCONY.pic
ROOM37.ROM URNS.pic
ROOM38.ROM NURSERY.pic
ROOM39.ROM GHALL.pic
ROOM40.ROM GDESIGN.pic
ROOM41.ROM TURBO1.pic
ROOM42.ROM LAB.pic
ROOM43.ROM OBSERV1.pic
ROOM44.ROM TURBO2.pic
ROOM45.ROM LEECH.pic
ROOM46.ROM STARSHP1.pic
ROOM48.ROM CATEXT.pic
ROOM49.ROM CATENT.pic
ROOM50.ROM ANCIENTS.pic
ROOM51.ROM POWNEX.pic
ROOM53.ROM ABYSS.pic
ROOM54.ROM GPRISON.pic
ROOM55.ROM DREKETH.pic
ROOM56.ROM ARCHIVES.pic
ROOM57.ROM GPRISENT.pic
ROOM58.ROM GCELLEXT.pic
ROOM59.ROM GCELL1.pic
ROOM60.ROM INSTRSHP.pic
ROOM61A.ROM ATTIC.pic
ROOM61.ROM ATTIC.pic
ROOM62.ROM CELLAR.pic
ROOM63.ROM TOTOWN.pic
ROOM64.ROM BARBER.pic
ROOM65.ROM TOCEM.pic
ROOM66.ROM TOABYSS.pic
ROOM67.ROM DREKPOST.pic
ROOM68.ROM TOCAT.pic