Difference between revisions of "FONT (File Format)"

From Retro Modding Wiki
Jump to: navigation, search
m ({{research}})
 
(30 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.
  
{{todo|Notate differences between different versions of the format. Only Metroid Prime's FONT version is documented at the moment. Character definition structure should be expanded on; there should be a section explaining what each value does, and it should be made more clear which UV coordinate corresponds to which vertex.}}
+
{{research|2|There's some unknowns in the header. Also, some version 4/5 fonts have outlines on their textures - how do these work?}}
{{research|2|There's some unknowns in the header, and some of the values in the character definition structure should be double-checked.}}
+
  
 
__TOC__
 
__TOC__
  
 
== Format ==
 
== Format ==
 +
 +
Note: All measurements are in points.
  
 
=== Header ===
 
=== 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).
  
 
{| class="wikitable"
 
{| class="wikitable"
 
! Offset
 
! Offset
 +
! Type
 
! Size
 
! Size
 
! Description
 
! Description
 
|-
 
|-
 
| 0x0
 
| 0x0
 +
| char[4]
 
| 4
 
| 4
 
| '''"FONT" magic fourCC'''
 
| '''"FONT" magic fourCC'''
 
|-
 
|-
 
| 0x4
 
| 0x4
 +
| u32
 
| 4
 
| 4
 
| '''Version'''; see below
 
| '''Version'''; see below
 
|-
 
|-
 
| 0x8
 
| 0x8
 +
| u32
 
| 4
 
| 4
| '''Max glyph height''' (plus padding, in points)
+
| {{unknown|'''Unknown'''}}
 
|-
 
|-
 
| 0xC
 
| 0xC
 +
| s32
 
| 4
 
| 4
| '''Min glyph height''' (plus padding, in points)
+
| '''Line height'''
 
|-
 
|-
 
| 0x10
 
| 0x10
 +
| u32
 
| 4
 
| 4
| '''Max glyph width''' (plus padding, in points)
+
| '''Vertical offset''' ''(note: not present in version 1)''
 
|-
 
|-
 
| 0x14
 
| 0x14
 +
| s32
 
| 4
 
| 4
| '''Min glyph width''' (plus padding, in points)
+
| '''Line margin'''
 
|-
 
|-
 
| 0x18
 
| 0x18
| 4
+
| bool
 +
| 1
 
| {{unknown|'''Unknown'''}}
 
| {{unknown|'''Unknown'''}}
 
|-
 
|-
| 0x1C
+
| 0x19
| 2
+
| bool
 +
| 1
 
| {{unknown|'''Unknown'''}}
 
| {{unknown|'''Unknown'''}}
 +
|-
 +
| 0x1A
 +
| u32
 +
| 4
 +
| {{unknown|'''Unknown'''}}
 
|-
 
|-
 
| 0x1E
 
| 0x1E
 +
| u32
 
| 4
 
| 4
| '''Font Size''' (in points)
+
| '''Font size'''
 
|-
 
|-
 
| 0x22
 
| 0x22
 +
| string
 
| N
 
| N
 
| '''Font name'''; zero-terminated string
 
| '''Font name'''; zero-terminated string
 
|-
 
|-
| 0x22+N
+
| -
| 4
+
| [[TXTR (Metroid Prime)|TXTR]]
| '''[[TXTR (Metroid Prime)|TXTR]] file ID'''
+
| 4/8
 +
| '''Texture ID'''
 
|-
 
|-
| 0x26+N
+
| -
 +
| u32
 
| 4
 
| 4
| {{unknown|'''Unknown'''}}
+
| '''Texture format''' (see [[#Textures|Textures]])
 
|-
 
|-
| 0x2A+N
+
| -
 +
| u32
 
| 4
 
| 4
| '''Glyph Count'''
+
| '''Glyph count'''
|-
+
| 0x2E+N
+
|
+
| '''Glyphs''' ([[#Glyph Entry (Version 2)|Version 2]], [[#Glyph Entry (Version 4)|Version 4]])
+
 
|}
 
|}
  
Line 82: Line 100:
 
|-
 
|-
 
| 2
 
| 2
| ''Metroid Prime''
+
| ''Metroid Prime'' NTSC
 
|-
 
|-
 
| 4
 
| 4
| ''Metroid Prime 2'' (and demo), ''Metroid Prime'' Wii releases
+
| ''Metroid Prime'' PAL and ''Metroid Prime 2''
 
|-
 
|-
 
| 5
 
| 5
Line 91: Line 109:
 
|}
 
|}
  
=== Glyph Entry (Version 2) ===
+
=== 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) ====
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 127: Line 155:
 
| u32
 
| u32
 
| 4
 
| 4
| '''Glyph left padding'''
+
| '''Left padding'''
 
|-
 
|-
 
| 0x16
 
| 0x16
Line 137: Line 165:
 
| u32
 
| u32
 
| 4
 
| 4
| '''Glyph right padding'''
+
| '''Right padding'''
 
|-
 
|-
 
| 0x1E
 
| 0x1E
 
| u32
 
| u32
 
| 4
 
| 4
| '''Glyph width'''
+
| '''Width'''
 
|-
 
|-
 
| 0x22
 
| 0x22
 
| u32
 
| u32
 
| 4
 
| 4
| '''Glyph height'''
+
| '''Height'''
 
|-
 
|-
 
| 0x26
 
| 0x26
 
| u32
 
| u32
 
| 4
 
| 4
| '''Kerning index'''
+
| '''Vertical offset'''
 
|-
 
|-
 
| 0x2A
 
| 0x2A
 +
| u32
 +
| 4
 +
| '''Kerning start index'''
 +
|-
 +
| 0x2E
 
| colspan=3 {{unknown|End of glyph definition}}
 
| colspan=3 {{unknown|End of glyph definition}}
 
|}
 
|}
  
=== Glyph Entry (Version 4) ===
+
==== Version 4 (Metroid Prime PAL/Trilogy) ====
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 194: Line 227:
 
| u8
 
| u8
 
| 1
 
| 1
| '''Layer Index'''
+
| '''Layer index'''
<ol start="0">
+
<li>TXTR Red channel is fill, Green channel is outline</li>
+
<li>TXTR Blue channel is fill, Alpha channel is outline</li>
+
</ol>
+
 
|-
 
|-
 
| 0x13
 
| 0x13
| u32
+
| u8
| 4
+
| 1
 
| '''Glyph left padding'''
 
| '''Glyph left padding'''
 
|-
 
|-
| 0x17
+
| 0x14
| u32
+
| u8
| 4
+
| 1
 
| '''Print head advance'''
 
| '''Print head advance'''
 
|-
 
|-
| 0x1B
+
| 0x15
| u32
+
| u8
| 4
+
| 1
 
| '''Glyph right padding'''
 
| '''Glyph right padding'''
 
|-
 
|-
| 0x1F
+
| 0x16
| u32
+
| u8
| 4
+
| 1
 
| '''Glyph width'''
 
| '''Glyph width'''
 
|-
 
|-
| 0x23
+
| 0x17
| u32
+
| u8
| 4
+
| 1
 
| '''Glyph height'''
 
| '''Glyph height'''
 
|-
 
|-
| 0x27
+
| 0x18
| u32
+
| u8
| 4
+
| 1
| '''Kerning index'''
+
| '''Vertical offset'''
 
|-
 
|-
| 0x2B
+
| 0x19
 +
| u16
 +
| 2
 +
| '''Kerning start index'''
 +
|-
 +
| 0x1B
 
| colspan=3 {{unknown|End of glyph definition}}
 
| colspan=3 {{unknown|End of glyph definition}}
 
|}
 
|}
Line 236: Line 270:
 
=== Kerning Table ===
 
=== Kerning Table ===
  
This table is at the end of the file, and defines kerning pairs. It starts with a 32-bit count value and then loops the following 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 257: 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.


Morphball wirerender.png 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?


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

Morphball render.png 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