The header is text: four lines, each ended by a line feed (0A). It has no
length field. The pixels, or the colour table in front of them, start at the byte after
the fourth line feed, so a reader has to read the lines to find where the data begins.
In the files checked the header is 45 to 53 bytes long, four more when its lines end in CR LF.
Layout
| Line | Text | Meaning |
|---|---|---|
| 1 | 3df v1.1 | Signature and version |
| 2 | rgb565 | Pixel format name |
| 3 | lod range: 1 256 | Smallest and largest level |
| 4 | aspect ratio: 1 1 | Width and height in proportion |
Every line is plain ASCII. In the lines with numbers the text, a colon and a single space come first, then the numbers separated by single spaces.
Signature and version
The first line is 3df v followed by a major and a minor number. These
versions are found in real files, with the number of distinct files in the 212 checked
for this reference:
| Line | Files |
|---|---|
3df v1.0 | 18 |
3df v1.1 | 192 |
3df v1.4 | 2 |
The layout after the header is the same in all three. The version is the only thing that tells the files apart; no file checked has a field that depends on it.
Pixel format
The second line names the format of every pixel in the file. The names, all lower case:
rgb332, yiq, a8, i8,
ai44, p8, argb8332, ayiq8422,
rgb565, argb1555, argb4444, ai88,
ap88 and argb8888.
Each is described on Pixel formats. The line also says whether a colour table follows the header.
LOD range
The third line holds two numbers, the smallest and then the
largest level of detail in the file. Each is the length in pixels of
the longer side of a level, and each is a power of two from 1 to 256, the largest a
Voodoo card can hold. The levels in between are every power of two from the largest
down to the smallest, so the number of levels is
log2(largest ÷ smallest) + 1.
| Line | Levels | Meaning |
|---|---|---|
lod range: 1 256 | 9 | 256, 128, 64, 32, 16, 8, 4, 2 and 1 pixels: a full set, the most common |
lod range: 1 128 | 8 | a full set from 128 pixels |
lod range: 128 128 | 1 | one level only: no smaller levels are stored |
lod range: 64 128 | 2 | two levels |
The first number is the smaller. A reader that took the first number as the largest would find no pixels where it expected them.
Aspect ratio
The fourth line holds the width and the height as a ratio. The longer side of every level is the level’s length from the LOD range, and the other side is that length scaled by the ratio, never less than 1. At 256 pixels:
| Line | Largest level | Found in files |
|---|---|---|
aspect ratio: 8 1 | 256 × 32 | no |
aspect ratio: 4 1 | 256 × 64 | yes |
aspect ratio: 2 1 | 256 × 128 | yes |
aspect ratio: 1 1 | 256 × 256 | yes, the usual one |
aspect ratio: 1 2 | 128 × 256 | yes |
aspect ratio: 1 4 | 64 × 256 | yes |
aspect ratio: 1 8 | 32 × 256 | no |
These seven ratios are the ones Glide defines (GR_ASPECT_8x1 to
GR_ASPECT_1x8). Of the 212 files checked, none uses 8 1 or 1 8: those two
follow Glide’s header and are not checked against a file.
Line endings
Nearly every file ends its lines with a line feed alone. Eight of the files checked
end every line with CR LF (0D 0A) instead, and their pixels start after
the last line feed all the same. A reader should therefore find the data by counting
line feeds, not by adding up the lengths it expects.
Example
The start of a 256 × 256 RGB 5-6-5 texture. The header is 51 bytes, so the pixels
start at offset 33 (hexadecimal), the byte after the fourth 0A:
00000000 33 64 66 20 76 31 2e 31 0a 72 67 62 35 36 35 0a 3df v1.1.rgb565.
00000010 6c 6f 64 20 72 61 6e 67 65 3a 20 31 20 32 35 36 lod range: 1 256
00000020 0a 61 73 70 65 63 74 20 72 61 74 69 6f 3a 20 31 .aspect ratio: 1
00000030 20 31 0a 49 e4 18 e3 19 e3 52 04 49 e3 51 e4 49 1.I.....R.I.Q.I
The first pixel is 49 E4, the 16-bit number 49E4: red 9,
green 15 and blue 4 on the 5-6-5 scale.