RES Format (Stellar 7)

From ModdingWiki
Jump to: navigation, search
RES Format (Stellar 7)
Format typeArchive
Max filesUnlimited
File Allocation Table (FAT)Embedded
Filenames?Yes, 4 chars
Metadata?None
Supports compression?Yes
Supports encryption?No
Supports subdirectories?Yes
Hidden data?No
Games

The RES format is used by Stellar 7 to store much of the game data. The PC version has 29 files using this format.

File format

It is a binary format containing any number of entries which themselves can contain other entries. Various items are stored in these files, such as compressed images and palette data, or the mission briefing text. The entries begin with a content type which can be clearly read even with a text editor.

Signature

There is no known signature, other than carefully reading the file structure and verifying it seems correct (e.g. offsets don't go past the end of the file.)

File entry

The file consists of one or more file entries, one after the other.

Data type Description
char contentType[4] Content type (see below), not null-terminated
UINT32LE isfolder_length Length of the data, most significant bit is folder bit
BYTE data[length] length bytes of data

If the most significant bit in isfolder_length is set, the data is comprised of more file entries in the same format as above, like a subdirectory. None of the game's data files appear to nest folders more than one level deep. The values can be extracted like this:

 length = isfolder_length & 0x7FFFFFFF
 if (isfolder_length & 0x80000000) then it is a folder

Content types

The following values for contentType are known. Any types that refer to sub-blocks mean "files" in the "subdirectory" as described above.

BMP: Image

The game supports VGA and earlier modes including EGA and CGA. The main palette information for VGA is located in the file STELART.RES while the EGA/CGA palettes are in STELARTE.RES.

contentType Description
INF: Slice guides for the bitmap. See below.

Some BMP: entries contain an INF: tag which appears to be layout guides for the image.

Data type Description
UINT16LE pair_count Number of size pairs to read
UINT16LE[2 * pair_count] Sizes; stored with the width values first followed by the height values.

The sizes correspond to the image data. In LEVEL1.RES there are five size pairs:

(256,16) (256,16) (256,16) (256,16) (32,27)

These are combined with two images of 8,624 bytes each for a total of 17,248 bytes. If you multiply out these size pairs and add the results they should come up to the same number of bytes, as VGA palettes have a 1:1 pixel-to-byte ratio.

FNT: Font

There are two FNT: blocks in STELLAR.RES. They are both uncompressed in one of two formats; hints about these formats was found at the ScummVM-DGDS Project. Over there they are known as simple and complex.

The structure of these fonts are:

Simple Font

Simple fonts are fixed width.

Data type Description
BYTE width Width of the font in bits and pixels
BYTE height Height of the font in bits and pixels
BYTE start First character code in the font file
BYTE count Number of characters in the font file
BYTE[height*count] Font data

Therefore, the file size for a simple font would be:

  4 + (height * count)

Typically, the first character code is 0x20 (32). A font with a full uppercase set has a count of at least 0x40 (64) while a font with an upper/lowercase set has a count of at least 0x60 (96).

To find a particular character, look at the following position in the font data:

  (character_code - start) * height

The simple font included in STELLAR.RES has a size of 8x6 pixels and starts at character 0x20. For character code 0x41 (65, letter A) the position would be (0x41 - 0x20) * 0x6 = 0xC6 (196). The data in this location is:

  0x 7c 82 fe 82 82 00

This font is just a basic raster bitmap using 1 bit-per-pixel:

  .11111..
  1.....1.
  1111111.
  1.....1.
  1.....1.
  ........
Complex Font

Complex fonts have varying widths.

Data type Description
BYTE magic Magic value 0xff
BYTE width Maximum width of the font in bits and pixels
BYTE height Height of the font in bits and pixels
BYTE unknown
BYTE start First character code in the font file
BYTE count Number of characters in the font file
UINT16LE size Size of the font data
BYTE unknown Compression algorithm? Seems to be 0x02
UINT32LE uncompressed_size Size of the uncompressed data
BYTE[font_size-13] data LZW compressed font data

The size and uncompressed_size appear to match. The uncompressed data contains what appears to be the following layout:

Data type Description
UINT16LE[count] offsets Positions for the characters in the data stream
BYTE[count] widths Bit (or pixel) width for each characters
BYTE[uncompressed_size - (3*count)] data Character data

The complex font in STELLAR.RES appears to have only two characters with widths greater than eight requiring two bytes to be read for each glyph row rather than one. These characters are 0x42 (*) and 0x64 (@).

PAL: Palette

The PAL: block contains palette data. It has sub-blocks for different palette types:

contentType Description
VGA: VGA Palette (three byte, 0-63)
EGA:
CGA:

SCR: Fullscreen image

Fullscreen images are 320x200 pixels; 32,000 bytes for EGA and 64,000 bytes for VGA.

The VGA files are split into two 32,000 byte "planes" using two pixels per byte. The second plane contains the more significant bits. If the starting bytes of the first plane are 0xFD 0xFF and the second plane are 0x99 0x88 then the first four horizontal pixels are palette entries 0x9F 0x9D 0x8F 0x8F.

contentType Description
BIN: 32000 byte (16-colour EGA / Least significant VGA bits)
VGA: 32000 byte (Most significant VGA bits)

VER: Version

Null terminated version string (e.g. "3.37")

SSM: Sounds and music

The SSM: block seems to contain media data in most cases. It has sub-blocks for different media types:

contentType Description
SNG: Song? Seems to be 8-bit unsigned 11025Hz PCM data with an unknown header
SNG: Song - also can contain raw MIDI data (theme song is in this format)

The file STELLAR.RES contains three SSM: entries; two of them contain SNG: blocks while the third has entries for various sound cards, most likely a version of the theme song in a format suitable for that device. The content type tags for these are as follows:

contentType Description
STD: ?
TAN: Tandy
M32: Roland?
ADL: AdLib
SBL: Sound Blaster
001: ?
002: ?

Compression

Some file entries are compressed using the LZW algorithm. The entries which are compressed cannot be identified by the 4-byte content type alone, and it is suspected that certain types are always compressed. Those entries that are compressed are in the following layout:

Data type Description
BYTE unknown Compression algorithm? Always seems to be 0x02
UINT32LE decompressedSize Size of data after decompression
BYTE data[] LZW-compressed data

The following content types never seem to be compressed:

Data type Description
VQT:
FNT:
ARR:
PAG:
VGA: Only if contained within a PAL: folder entry.

The LZW algorithm uses a dynamic bit length, from 9 bits to 12 bits. Data is split into bytes in little-endian order. The first codeword is 257, with code 256 reserved to indicate a dictionary reset.

When the dictionary is reset, some bytes in the input data are discarded. Why this happens is currently unknown. The number of bytes discarded seems to vary depending on the number of bytes read (perhaps it is aligning to a DWORD boundary?)

There is some sample decompression code for similar games which seems to (mostly) work.

Credits

This file format was reverse engineered by Malvineous, with some subformats identified by Zab. Hints about the compression algorithm were obtained from the ScummVM project. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)