Dynamix Font Format v4-v5
The Dynamix v4 font is a 1-bpp indexed font with compression support, with the file header specifying the global height for all symbols and the amount of symbols, and with the widths of all symbols defined separately. It is optimized by only saving the used range of symbols.
The v5 font is identical, except that it stores 8-bit data instead of 1-bit data. It is distinguished with a different version byte in the header.
The font is embedded in a typical Dynamix chunk of type "FNT", meaning it is preceded by
"FNT:" + UINT32 chunk size. The following descriptions cover the data format inside the FNT chunk.
|0x00||UINT8||Version||Version indicator. 0xFF for the one bit per pixel version, 0xFD for the eight bit per pixel version.|
|0x01||UINT8||FontWidth||Maximum width of the font in pixels.|
|0x02||UINT8||FontHeight||Height of the font in pixels.|
|0x03||UINT8||BaseLine||This appears to indicate the Y-offset of the base line of the font. It generally corresponds to the most commonly used lowest pixel Y-position in the symbols, but can be different if the font has a dropped shadow, which is a common feature in v5 fonts.|
|0x04||UINT8||StartSymbol||First symbol code in the font file.|
|0x05||UINT8||NrOfSymbols||Number of symbols in the font file. Since this is a byte, the font is limited to a maximum of only 255 symbols, and not the full 256. However, since C-style strings end with byte 0x00, index 0 is technically useless, and can be skipped to get the full real range.|
|0x06||UINT16LE||SymbolDataSize||Size of the (uncompressed) symbol data block.|
|0x08||UINT8||CompressionMethod||ID of the used compression algorithm. See below.|
|0x09||UINT32LE||UncompressedSize||Size of the uncompressed data.|
The following compression types are supported by the format:
- 0x00: Uncompressed
- 0x01: Code-based RLE with 1-byte codes. If the highest bit in a code is set, this indicates a Repeat command. The remaining 7 bits specify the amount to copy or repeat.
- 0x02: LZW. The actual LZW implementation is an adaptive LZW with expanding dictionary size. Decompression code for it is available in a set of MIDI tools released by user tikalat on the VOGONS forum.
- 0x03: Huffman compression. Decompression code is available in the aforementioned MIDI tools. Note that Huffman was only introduced in later games, so using Huffman-compressed fonts may not work on some earlier games.
This header is followed by the symbol data block, compressed in one of the three known compression methods. After the symbol data is uncompressed, it starts with the offsets and widths data:
|UINT16LE[NrOfSymbols]||offsets||Offsets of the data for each symbol, relative to the start of the uncompressed block.|
|UINT8[NrOfSymbols]||widths||Width of the individual symbols, in pixels.|
Behind this, the font file symbols data can be found, using the offset from
offsets, the width from
widths, and the global
FontHeight. The formula to convert the width to the stride (the actual byte length of a line of pixels) is
((width * BitsPerPixel) + 7) / 8.
Since this data is referenced through an index, the same optimisation technique used in the Westwood Studios v3 font could be applied to it; when multiple symbols have identical image data, the data could be stored only once, and the index positions for these symbols can then point to the same data. This technique is not used by any of the original font files, but the games accept it without issues, since they just follow the references in the index. The Westwood Font Editor allows saving the fonts with this optimisation.
The following tools are able to work with files in this format.
|Name||Platform||View images in this format?||Convert/export to another file/format?||Import from another file/format?||Access hidden data?||Edit metadata?||Notes|
|Westwood Font Editor||Windows||Yes||Yes||Yes||No||N/A|