TEX File Format

Hover! uses the Microsoft Foundation Classes (MFC) serialization framework to store texture data in TEX files. This documentation describes the binary file structure and explains how to read TEX files without relying on MFC.

All multi-byte integer values are stored in little-endian byte order, meaning the least significant byte comes first. For example, the 16-bit value 0x1234 is stored as 34 12.

The TEX format consists of a global 256-color palette, a collection of serialized CMerlinTexture objects, and an optional extension data block. Each texture contains one or more mipmap images, including pixel data and transparency information stored as spans.

General Structure

The structure shows the general layout using 4 entries the collection to demonstrate counting of the MFC objects. The structure is split into 2 sections for better readability.

Color Table
Color Definition (index 0)
Color Definition (index 1)
Color Definition (index 2)
...
Color Definition (index 255)
CMerlinTexture Collection
CObArray (object_count)
NEW_CLASS_TAG
MFC Class Definition "CMerlinTexture" (MFC object 1)
CMerlinTexture (index 0, MFC object 2)
CLASS_TAG
CMerlinTexture (index 1, MFC object 3)
CLASS_TAG
CMerlinTexture (index 2, MFC object 4)
CLASS_TAG
CMerlinTexture (index 3, MFC object 5)
Extension Data Block
Extension Data

MFC Data Structure

MFC CObArray

NameDatatypeDescription
object_countuint16Number of elements in the serialized CObArray.

MFC Tags

The CLASS_TAG is formed by performing a bitwise OR operation between 0x8000 and the reference ID of an existing class definition. For example, class ID 1 results in 0x8001.

NameDatatypeDescription
NEW_CLASS_TAGuint160xFFFF – Defines and registers a new class in the MFC reference table.
CLASS_TAGuint160x8000 | class_id – References an existing class definition (e.g., 0x8001 for class definition at ID 1).

MFC Class Definition

NameDatatypeDescription
schema_versionuint160x0100
name_lengthuint16Length of the string in bytes.
nameunit8[name_length]String data (ANSI). The class name of serialized object.

MFC CString

This is a simplified representation of the MFC CString type. The length prefix uses a variable-size encoding depending on the string length. Since all texture names in Hover! are shorter than 255 characters, only the single-byte length prefix is required.

string_lengthuint8Length of the string in bytes (0–254).
stringuint8[string_length]String data (ANSI, not null-terminated).

CMerlin Data Structures

Color Definition

NameDatatypeDescription
reduint8Red color component (0–255).
greenuint8Green color component (0–255).
blueuint8Blue color component (0–255).
reserveduint8Always 0x00.

CMerlinTexture

NameDatatypeDescription
nameCStringName of the texture.
extension_dataExtension DataOptional length-prefixed data block, normally empty (0x0000).
transparentuint16Enables transparent rendering when non-zero.
image_countuint16Number of images, including the base texture and all mipmap levels.
imagesImage[image_count]Array of images including mipmaps, ordered from highest to lowest resolution.

Image

NameDatatypeDescription
image_widthuint16Width of this mipmap image in pixels (must be a power of two).
u_wrapuint16Bitmask used to wrap horizontal texture coordinates. Typically width - 1.
image_heightuint16Height of this mipmap image in pixels (must be a power of two).
v_wrapuint16Bitmask used to wrap vertical texture coordinates. Typically height - 1.
height_log2uint16Base-2 logarithm of the texture height. Used to calculate pixel offsets using bit shifts instead of multiplication.
pixel_countuint32Number of stored palette indices, excluding transparent pixels.
pixeluin8[pixel_count]Palette indices stored in column-major order.
total_span_countuint32Total number of spans across all columns.
span_columnsSpan Column[image_width]Span information for each image column.
image_extension_dataExtension DataOptional length-prefixed data block, normally empty (0x0000).

Span Column

span_countuint16Number of spans in this column.
spansSpan[span_count]Array of spans defining the non-transparent pixel ranges.

Span

startuint16Inclusive start coordinate, relative to the original texture height.
enduint16Inclusive end coordinate, relative to the original texture height.

Extension Data

A length-prefixed data block containing additional object-specific information. Its exact purpose is currently unknown. It is read by Hover! but the bytes are discarded.

NameDatatypeDescription
lengthuint16Number of additional bytes to read.
datauint8[length]Optional data, ignored by Hover!

Example values of a texture

Image Dimensions

In the original TEX files, mipmap levels are generated down to a minimum image height of 4 pixels, regardless of the texture width.

Image Sizeu_wrap, v_wrapMipMap Levelheight_log2
256 x 128255, 12707
128 x 64127, 6316
64 x 3263, 3125
32 x 1631, 1534
16 x 815, 743
8 x 47, 352

Span Calculation

Span coordinates are stored relative to the base texture dimensions. For each mipmap level, the actual pixel coordinates are scaled by 2mipLevel before being stored. This allows all mipmap levels to use the same coordinate space.

MipMap LevelEffective Pixel RangeStored Span Coordinates
020 - 10820 - 108
110 - 5420 - 108 (pixel value multiplied by 2 or value << 1)
25 - 2720 - 108 (pixel value multiplied by 4 or value << 2)
32 - 1316 - 104 (pixel value multiplied by 8 or value << 3)
41 - 616 - 96 (pixel value multiplied by 16 or value << 4)
50 - 30 - 96 (pixel value multiplied by 32 or value << 5)

Details on pixel and span data

The following image illustrates an 8x8 texture and how its color and transparency information is stored. Pixel data is stored in a single array in column-major order, with each pixel represented by an index into the TEX file's global color palette. Transparency is represented by spans, which define the ranges of non-transparent pixels within each column. Both pixel data and span information are organized and processed column by column.

Illustration on TEX color and span data.