Difference between revisions of "FONT (File Format)"
m |
|||
(19 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
The '''FONT format''' defines fonts that can be used to display text in-game. | The '''FONT format''' defines fonts that can be used to display text in-game. | ||
− | {{research|2|There's some unknowns in the header.}} | + | {{research|2|There's some unknowns in the header. Also, some version 4/5 fonts have outlines on their textures - how do these work?}} |
__TOC__ | __TOC__ | ||
== Format == | == Format == | ||
+ | |||
+ | Note: All measurements are in points. | ||
=== Header === | === Header === | ||
Line 40: | Line 42: | ||
| u32 | | u32 | ||
| 4 | | 4 | ||
− | | '''Vertical offset''' | + | | '''Vertical offset''' ''(note: not present in version 1)'' |
|- | |- | ||
| 0x14 | | 0x14 | ||
Line 48: | Line 50: | ||
|- | |- | ||
| 0x18 | | 0x18 | ||
− | | | + | | bool |
− | | | + | | 1 |
− | | {{unknown|'''Unknown'''}} | + | | {{unknown|'''Unknown'''}} |
|- | |- | ||
− | | | + | | 0x19 |
− | | | + | | bool |
− | | | + | | 1 |
| {{unknown|'''Unknown'''}} | | {{unknown|'''Unknown'''}} | ||
+ | |- | ||
+ | | 0x1A | ||
+ | | u32 | ||
+ | | 4 | ||
+ | | {{unknown|'''Unknown'''}} | ||
|- | |- | ||
| 0x1E | | 0x1E | ||
| u32 | | u32 | ||
| 4 | | 4 | ||
− | | '''Font size''' | + | | '''Font size''' |
|- | |- | ||
| 0x22 | | 0x22 | ||
Line 75: | Line 82: | ||
| u32 | | u32 | ||
| 4 | | 4 | ||
− | + | | '''Texture format''' (see [[#Textures|Textures]]) | |
|- | |- | ||
| - | | - | ||
Line 81: | Line 88: | ||
| 4 | | 4 | ||
| '''Glyph count''' | | '''Glyph count''' | ||
− | |||
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
Line 98: | Line 100: | ||
|- | |- | ||
| 2 | | 2 | ||
− | | ''Metroid Prime'' NTSC | + | | ''Metroid Prime'' NTSC |
|- | |- | ||
| 4 | | 4 | ||
− | | ''Metroid Prime'' PAL | + | | ''Metroid Prime'' PAL and ''Metroid Prime 2'' |
|- | |- | ||
| 5 | | 5 | ||
Line 115: | Line 117: | ||
The kerning index value is the index of the first kerning table entry for the given character. Since the table is sorted in alphabetical order, this can be used to speed up lookup time. | The kerning index value is the index of the first kerning table entry for the given character. Since the table is sorted in alphabetical order, this can be used to speed up lookup time. | ||
− | This section of the file changes somewhat from version 2 to 4. Starting in version 4, | + | This section of the file changes somewhat from version 2 to 4. Starting in version 4, font textures are able to be split up into multiple layers, which allows multiple glyphs to be encoded in the same space on the texture. A "layer index" value was introduced to track which layer the glyph is on. Additionally, a lot of 32-bit values were reduced to 8- or 16-bit. Aside from that, though, the actual layout is still the same, with the same values in the same places. |
− | ==== Version 2 (Metroid Prime | + | ==== Version 2 (Metroid Prime NTSC) ==== |
{| class="wikitable" | {| class="wikitable" | ||
Line 183: | Line 185: | ||
| u32 | | u32 | ||
| 4 | | 4 | ||
− | | '''Kerning index''' | + | | '''Kerning start index''' |
|- | |- | ||
| 0x2E | | 0x2E | ||
Line 189: | Line 191: | ||
|} | |} | ||
− | ==== Version 4 (Metroid Prime PAL) ==== | + | ==== Version 4 (Metroid Prime PAL/Trilogy) ==== |
{| class="wikitable" | {| class="wikitable" | ||
Line 225: | Line 227: | ||
| u8 | | u8 | ||
| 1 | | 1 | ||
− | | ''' | + | | '''Layer index''' |
|- | |- | ||
| 0x13 | | 0x13 | ||
Line 253: | Line 255: | ||
|- | |- | ||
| 0x18 | | 0x18 | ||
+ | | u8 | ||
+ | | 1 | ||
+ | | '''Vertical offset''' | ||
+ | |- | ||
+ | | 0x19 | ||
| u16 | | u16 | ||
| 2 | | 2 | ||
− | | '''Kerning index''' | + | | '''Kerning start index''' |
|- | |- | ||
− | | | + | | 0x1B |
| colspan=3 {{unknown|End of glyph definition}} | | colspan=3 {{unknown|End of glyph definition}} | ||
|} | |} | ||
Line 263: | Line 270: | ||
=== Kerning Table === | === Kerning Table === | ||
− | This table is at the end of the file, and defines kerning pairs. The table is case-sensitively sorted in alphabetical order, which allows for fast lookup times using the glyph kerning indices. After a 32-bit count value, each pair follows this simple structure: | + | This table is at the end of the file, and defines kerning pairs. Kerning pairs horizontally adjust the second character of the pair whenever that particular sequence of characters is encountered. The table is case-sensitively sorted in alphabetical order, which allows for fast lookup times using the glyph kerning indices. After a 32-bit count value, each pair follows this simple structure: |
{| class="wikitable" | {| class="wikitable" | ||
Line 284: | Line 291: | ||
| 0x8 | | 0x8 | ||
| colspan=2 {{unknown|End of entry}} | | colspan=2 {{unknown|End of entry}} | ||
+ | |} | ||
+ | |||
+ | == Textures == | ||
+ | |||
+ | {{research|minor|Someone should look at the code to make sure the info in this section is accurate.}} | ||
+ | |||
+ | Textures used by FONT files are encoded in a bit of an unorthodox manner. The font format allows for multiple glyphs to be encoded in the same spot on the texture by splitting up the texture into multiple layers. The way this is handled on the textures is by encoding the textures with palettes (as C4), but modifying the palette indices at runtime and loading each layer one at a time as a separate texture. Each bit of the palette index corresponds to a layer, so up to four layers per font are supported. The MSB refers to layer 0, while the LSB refers to layer 3. In DKCR, font textures are encoded as C8, so theoretically the game could use up to eight layers per font; however, it still never actually uses more than four. | ||
+ | |||
+ | The texture format is determined by a value in the header. These are the possible settings: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Value | ||
+ | ! Description | ||
+ | ! V1 | ||
+ | ! V2 | ||
+ | ! V4 | ||
+ | ! V5 | ||
+ | |- | ||
+ | | 0 | ||
+ | | One glyph layer, no outlines; fill on layer 0 | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | 1 | ||
+ | | One glyph layer, with outlines; fill on layer 0, outline on layer 1 | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | 2 | ||
+ | | Four glyph layers, no outlines | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | 3 | ||
+ | | Two glyph layers, with outlines; fill on layers 0/2, outlines on layers 1/3 | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | 4 | ||
+ | | Two glyph layers, no outlines; copies on layers 0/1, and layers 2/3 | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | 8 | ||
+ | | Two glyph layers, with outlines; fill on layers 2/3, outlines on layers 0/1 | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{check}} | ||
+ | |} | ||
+ | |||
+ | To dump out every layer into a single texture by encoding each layer on a separate RGBA channel, the following palette colors could be substituted into the texture: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Index | ||
+ | ! Binary | ||
+ | ! Color | ||
+ | ! Description | ||
+ | |- | ||
+ | | 0 | ||
+ | | 0000 | ||
+ | | 0x8000 | ||
+ | | None | ||
+ | |- | ||
+ | | 1 | ||
+ | | 0001 | ||
+ | | 0x7000 | ||
+ | | Alpha | ||
+ | |- | ||
+ | | 2 | ||
+ | | 0010 | ||
+ | | 0xFC00 | ||
+ | | Blue | ||
+ | |- | ||
+ | | 3 | ||
+ | | 0011 | ||
+ | | 0x7F00 | ||
+ | | Blue/Alpha | ||
+ | |- | ||
+ | | 4 | ||
+ | | 0100 | ||
+ | | 0x83E0 | ||
+ | | Green | ||
+ | |- | ||
+ | | 5 | ||
+ | | 0101 | ||
+ | | 0x70F0 | ||
+ | | Green/Alpha | ||
+ | |- | ||
+ | | 6 | ||
+ | | 0110 | ||
+ | | 0xFFE0 | ||
+ | | Green/Blue | ||
+ | |- | ||
+ | | 7 | ||
+ | | 0111 | ||
+ | | 0x7FF0 | ||
+ | | Green/Blue/Alpha | ||
+ | |- | ||
+ | | 8 | ||
+ | | 1000 | ||
+ | | 0x801F | ||
+ | | Red | ||
+ | |- | ||
+ | | 9 | ||
+ | | 1001 | ||
+ | | 0x700F | ||
+ | | Red/Alpha | ||
+ | |- | ||
+ | | 10 | ||
+ | | 1010 | ||
+ | | 0xFC1F | ||
+ | | Red/Blue | ||
+ | |- | ||
+ | | 11 | ||
+ | | 1011 | ||
+ | | 0x7F0F | ||
+ | | Red/Blue/Alpha | ||
+ | |- | ||
+ | | 12 | ||
+ | | 1100 | ||
+ | | 0x83FF | ||
+ | | Red/Green | ||
+ | |- | ||
+ | | 13 | ||
+ | | 1101 | ||
+ | | 0x70FF | ||
+ | | Red/Green/Alpha | ||
+ | |- | ||
+ | | 14 | ||
+ | | 1110 | ||
+ | | 0xFFFF | ||
+ | | Red/Green/Blue | ||
+ | |- | ||
+ | | 15 | ||
+ | | 1111 | ||
+ | | 0x7FFF | ||
+ | | Red/Green/Blue/Alpha | ||
|} | |} | ||
Latest revision as of 14:10, 11 March 2016
The FONT format defines fonts that can be used to display text in-game.
This file format needs more research There's some unknowns in the header. Also, some version 4/5 fonts have outlines on their textures - how do these work? |
Contents
Format
Note: All measurements are in points.
Header
The header has a couple minor differences depending on the version. Version 1 (MP1 Kiosk Demo) is missing the value at 0x18, and starting in Version 5 (MP3/DKCR), the texture ID is 64 bits. Those are the only changes, though (and for that matter, those are the only differences in version 1/5).
Offset | Type | Size | Description |
---|---|---|---|
0x0 | char[4] | 4 | "FONT" magic fourCC |
0x4 | u32 | 4 | Version; see below |
0x8 | u32 | 4 | Unknown |
0xC | s32 | 4 | Line height |
0x10 | u32 | 4 | Vertical offset (note: not present in version 1) |
0x14 | s32 | 4 | Line margin |
0x18 | bool | 1 | Unknown |
0x19 | bool | 1 | Unknown |
0x1A | u32 | 4 | Unknown |
0x1E | u32 | 4 | Font size |
0x22 | string | N | Font name; zero-terminated string |
- | TXTR | 4/8 | Texture ID |
- | u32 | 4 | Texture format (see Textures) |
- | u32 | 4 | Glyph count |
Version
Version | Game |
---|---|
1 | Metroid Prime Kiosk Demo |
2 | Metroid Prime NTSC |
4 | Metroid Prime PAL and Metroid Prime 2 |
5 | Metroid Prime 3, DKCR |
Glyphs
This section of the file details each glyph making up the font. One glyph corresponds to one character. To map the character with the part of the font texture that contains that character, each glyph contains a set of texture coordinates. Since the UV map is always rectangular, the file only stores the min/max X/Y coordinates; they should be mixed and matched to get the absolute values.
In addition, glyphs contain a vertical offset. This offset is necessary because the textures are usually so tightly packed that there's no extra space for vertical spacing. After applying the offset, the vertical offset from the FONT header is applied. This aligns the glyphs at their intended position.
The kerning index value is the index of the first kerning table entry for the given character. Since the table is sorted in alphabetical order, this can be used to speed up lookup time.
This section of the file changes somewhat from version 2 to 4. Starting in version 4, font textures are able to be split up into multiple layers, which allows multiple glyphs to be encoded in the same space on the texture. A "layer index" value was introduced to track which layer the glyph is on. Additionally, a lot of 32-bit values were reduced to 8- or 16-bit. Aside from that, though, the actual layout is still the same, with the same values in the same places.
Version 2 (Metroid Prime NTSC)
Offset | Type | Size | Description |
---|---|---|---|
0x0 | u16 | 2 | UTF-16 character |
0x2 | float | 4 | Left UV coordinate |
0x6 | float | 4 | Top UV coordinate |
0xA | float | 4 | Right UV coordinate |
0xE | float | 4 | Bottom UV coordinate |
0x12 | u32 | 4 | Left padding |
0x16 | u32 | 4 | Print head advance |
0x1A | u32 | 4 | Right padding |
0x1E | u32 | 4 | Width |
0x22 | u32 | 4 | Height |
0x26 | u32 | 4 | Vertical offset |
0x2A | u32 | 4 | Kerning start index |
0x2E | End of glyph definition |
Version 4 (Metroid Prime PAL/Trilogy)
Offset | Type | Size | Description |
---|---|---|---|
0x0 | u16 | 2 | UTF-16 character |
0x2 | float | 4 | Left UV coordinate |
0x6 | float | 4 | Top UV coordinate |
0xA | float | 4 | Right UV coordinate |
0xE | float | 4 | Bottom UV coordinate |
0x12 | u8 | 1 | Layer index |
0x13 | u8 | 1 | Glyph left padding |
0x14 | u8 | 1 | Print head advance |
0x15 | u8 | 1 | Glyph right padding |
0x16 | u8 | 1 | Glyph width |
0x17 | u8 | 1 | Glyph height |
0x18 | u8 | 1 | Vertical offset |
0x19 | u16 | 2 | Kerning start index |
0x1B | End of glyph definition |
Kerning Table
This table is at the end of the file, and defines kerning pairs. Kerning pairs horizontally adjust the second character of the pair whenever that particular sequence of characters is encountered. The table is case-sensitively sorted in alphabetical order, which allows for fast lookup times using the glyph kerning indices. After a 32-bit count value, each pair follows this simple structure:
Offset | Size | Description |
---|---|---|
0x0 | 2 | Character 1 |
0x2 | 2 | Character 2 |
0x4 | 4 | Kerning adjust |
0x8 | End of entry |
Textures
This file format is almost completely documented Someone should look at the code to make sure the info in this section is accurate. |
Textures used by FONT files are encoded in a bit of an unorthodox manner. The font format allows for multiple glyphs to be encoded in the same spot on the texture by splitting up the texture into multiple layers. The way this is handled on the textures is by encoding the textures with palettes (as C4), but modifying the palette indices at runtime and loading each layer one at a time as a separate texture. Each bit of the palette index corresponds to a layer, so up to four layers per font are supported. The MSB refers to layer 0, while the LSB refers to layer 3. In DKCR, font textures are encoded as C8, so theoretically the game could use up to eight layers per font; however, it still never actually uses more than four.
The texture format is determined by a value in the header. These are the possible settings:
Value | Description | V1 | V2 | V4 | V5 |
---|---|---|---|---|---|
0 | One glyph layer, no outlines; fill on layer 0 | ✔ | ✔ | ✔ | ✔ |
1 | One glyph layer, with outlines; fill on layer 0, outline on layer 1 | ✔ | ✔ | ✔ | ✔ |
2 | Four glyph layers, no outlines | ✖ | ✖ | ✔ | ✔ |
3 | Two glyph layers, with outlines; fill on layers 0/2, outlines on layers 1/3 | ✖ | ✖ | ✔ | ✔ |
4 | Two glyph layers, no outlines; copies on layers 0/1, and layers 2/3 | ✖ | ✖ | ✔ | ✔ |
8 | Two glyph layers, with outlines; fill on layers 2/3, outlines on layers 0/1 | ✖ | ✖ | ✖ | ✔ |
To dump out every layer into a single texture by encoding each layer on a separate RGBA channel, the following palette colors could be substituted into the texture:
Index | Binary | Color | Description |
---|---|---|---|
0 | 0000 | 0x8000 | None |
1 | 0001 | 0x7000 | Alpha |
2 | 0010 | 0xFC00 | Blue |
3 | 0011 | 0x7F00 | Blue/Alpha |
4 | 0100 | 0x83E0 | Green |
5 | 0101 | 0x70F0 | Green/Alpha |
6 | 0110 | 0xFFE0 | Green/Blue |
7 | 0111 | 0x7FF0 | Green/Blue/Alpha |
8 | 1000 | 0x801F | Red |
9 | 1001 | 0x700F | Red/Alpha |
10 | 1010 | 0xFC1F | Red/Blue |
11 | 1011 | 0x7F0F | Red/Blue/Alpha |
12 | 1100 | 0x83FF | Red/Green |
13 | 1101 | 0x70FF | Red/Green/Alpha |
14 | 1110 | 0xFFFF | Red/Green/Blue |
15 | 1111 | 0x7FFF | Red/Green/Blue/Alpha |