Westwood Font Format v4
Format type | Font |
---|---|
Max glyph count | 256 |
Minimum glyph size (pixels) | 0×0 |
Maximum glyph size (pixels) | 255×255 |
Access mode | Indexed |
Metadata? | None |
Bitmap glyphs? | Yes |
Vector glyphs? | No |
Compressed glyphs? | No |
Hidden data? | Yes |
Games |
Lands of Lore III (Installer) |
The fourth type of bitmap font created by Westwood Studios is not used in any DOS games, but its format is virtually identical to v3, so it is included for completeness' sake. It is an 8-bit-per-pixel font, though the games that use it never use it beyond 16 colors, making it functionally identical to the 4-bpp v3 font. Like its predecessor, it has a variable amount of characters, and allows the separate symbols to specify their width, height and Y-offset.
Unlike the v3 fonts, v4 fonts usually seem to correspond to the Windows-1252 encoding, and not to classic DOS code page 437.
File format
Since the source code of C&C: Renegade was released, the full handling of these fonts is now available. It can be looked into here, in the files wwfont.h and wwfont.cpp. Internally, it is called WWFontClass.
Header
The font format starts with the following header.
Offset | Data type | Name | Description |
---|---|---|---|
0x00 | UINT16LE | FontLength | File size. |
0x02 | BYTE | FontCompress | Somewhat oddly named, since this simply indicates the data format. 0x00 for v3, 0x02 for v4. The internal logic in the games actually allows both values, with 0x00 and 0x02 indicating respectively a 4-bit and an 8-bit font, but the 4-bit variety is never actually used in the later games. |
0x03 | BYTE | FontDataBlocks | Always 0x00 for v4. |
0x04 | UINT16LE | InfoBlockOffset | Indicates the InfoBlock offset. Always 0x0E; right after the header. |
0x06 | UINT16LE | OffsetBlockOffset | Offset of the array of data offsets. |
0x08 | UINT16LE | WidthBlockOffset | Offset of the array of symbol widths |
0x0A | UINT16LE | DataBlockOffset | Offsets are relative to this value. While this is unused in v3, v4 fills this in with the start of its font data block, making the values at the address in OffsetBlockOffset start at 0. This allows addressing slightly more data with the 16-bit integer data offsets, theoretically allowing the fonts to contain larger characters. However, the default placement of the height data behind all image data seems to negate this potential advantage.
|
0x0C | UINT16LE | HeightOffset | Offset of the array containing the symbol heights and Y-offsets. |
This is normally immediately followed by the InfoBlock, as specified by InfoBlockOffset
. The games only seem to use MaxHeight
and MaxWidth
from this block.
The block has the following structure. Note that in the Red Alert 1 source code, its first four bytes are taken together as a single int32 named "huh", which seems to indicate they lost the information on what exactly this area contains. In v3, this unknown information seemed to include a byte indicating the last stored symbol, but even so, the information was never used. This means that the only reliable way to determine the amount of characters is through reading the index arrays and seeing where they need to end to avoid overlapping with the other addressed data.
Offset | Data type | Name | Description |
---|---|---|---|
0x00 | UINT32LE | huh | Unknown, and unused. Always 0 for v4. |
0x04 | BYTE | MaxHeight | Overall font symbols maximum height, in pixels. |
0x05 | BYTE | MaxWidth | Overall font symbols maximum width, in pixels. |
Following this header are the referenced arrays and the font data, normally in this order:
- Array of UINT16LE values indicating the offset of the data for each symbol, relative to
DataBlockOffset
. The start offset of this list is specified byOffsetBlockOffset
. - Array of byte values indicating the symbol widths, in pixels. The start offset of this list is specified by
WidthBlockOffset
. - Actual symbol data referenced in the offsets list.
- Array containing two bytes per entry; the first being the Y-offset, the second the height in pixels. The start offset of this array is specified by
HeightOffset
.
Unlike in v3, v4 fonts seem to put the height and Y data behind the actual character data, splitting the data into a header and a footer around the actual image data. However, since the games just follow the offsets as they read them, the order probably doesn't matter at all.
As with version 3, the font data is uncompressed, but it is optimised by making the offsets for any identical symbols in the font refer to the same data.
Image data
The actual font data is very simply straightforward 8 bit per pixel, always using the minimum stride per line, so the exact amount of bytes of the width. However, the games themselves never seems to use colour indices higher than 16 on the fonts; there are simply no colours supplied for these indices, and if they are used on the font they seem to use random memory junk as colours. Because of this, the v4 format doesn't really offer any advantage over its 4-bit predecessor, except in unutilized potential.
Tools
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 | Automatically trims off the top of the characters on save, and saves the trimmed amount as Y-offset. Has an option to limit 8-bit fonts to 16 colours to prevent using unusable indices on this font type. |
Engie File Converter | Windows | Yes | Yes | Yes | No | N/A | Automatically trims off the top of the characters on save, and saves the trimmed amount as Y-offset. This font type was added to Engie to allow creation of font sheets. |