Font Knowledge

Started by ak2yny, November 22, 2020, 04:40PM

Previous topic - Next topic
November 22, 2020, 04:40PM Last Edit: July 31, 2022, 04:16AM by ak2yny
Font Knowledge

Let's start with a menu or area. These are found in ui/menus folder (mlm[...].igb files) or in the exe (presumeably). The menu defines the text area (1) and the size and position of it. This is important to understand alignment later.

With the menu file comes a menu engb file that sets the parameters for a menu and its text. In it, all text elements have the following entries:

            "style": "MED_DEFAULT",
            "text": "$BX_ControlsOpt_Player1",
            "textalignx": "TEXT_ALIGN_LEFT",
            "textaligny": "TEXT_ALIGN_TOP",
(decompiled with nikita488 tools)

style: This is set in the styles.xmlb in data folder.
text:  This is the text and can be anything. Some autotext doesn't need this entry.
textalignx: This can be TEXT_ALIGN_LEFT, TEXT_ALIGN_RIGHT, or TEXT_ALIGN_CENTER_X. Optional.
textaligny: This can be TEXT_ALIGN_TOP, TEXT_ALIGN_BOTTOM, or TEXT_ALIGN_CENTER_Y. Optional.
More information on alignment will follow further below.


So from menu engb files, let's go to styles.xmlb. In here we find all possible styles with many different colours. By default there are two different fonts given: big and medium. When we search the font files, we soon find some smaller xmlb-files that contain the medium and big "fonts". Inside we find something like this:

{
    "FONTFILES": {
        "font": {
            "data": "360_big_hd",
            "index": "big",
            "texture": "360_big_hd"
        },
        "font": {
            "data": "beenox_med_hd",
            "index": "medium",
            "language": "eng",
            "texture": "360_med_hd_eng"
        },
[...]

These are the contents of fonts_beenox_hd.xmlb, the file that MUA PC 2006 uses with high resolutions.
We can add various styles and filter them by language, if there are multiple textures around. My attempts to add new styles failed, but this might be related to trying to change the style of a hardcoded text area (or the fact that one of the files was the wrong one).
Notice, how we go backwards from the result to the style, to the font, and finally to the texture and its xmlb. The texture font is found in the textures\fonts folder and is used with igb's.

Beenox has a special version for medium font, because they created a working version where we can bind any key to a function. For that, they have a Fullkeyset png file in the texs folder. The game creates a new texture out of FontTexture0_beenox360_hd.png (or Logitech version depending on what controllers are plugged in) and Fullkeyset_eng.png (or ita, depending on the language), called xbox_med_eng_hd.png (or ita).

Check the two versions of a medium font below:


In addition to the igb (or png), we need a xmlb file with the name set in the "data" entry, found in ui/fonts.
Important: These two files (texture and data) need to go together. Never mix versions.
But let's have a look into the xmlb font file:

{
    "FONT_TABLE": {
        "ascender": 28,
        "descender": 8,
        "height": 43,
        "pointsize": 40,
        "glyph": {
            "baseline": 1,
            "height": 3,
            "horizadvance": 7,
            "horizoffset": -1,
            "num": 32,
            "s": 0.2421875,
            "s2": 0.248046875,
            "t": 0.046875,
            "t2": 0.052734375,
            "width": 3
        },
        "glyph": {
            "baseline": 15,
            "height": 17,
            "horizadvance": 7,
            "horizoffset": 1,
            "num": 33,
            "s": 0.001953125,
            "s2": 0.021484375,
            "t": 0.15234375,
            "t2": 0.185546875,
            "width": 10
        },
[...]

we have three groups of values that are not immediately seen.
The first group are the vertical parameters:
        "ascender": 28,
        "descender": 8,
        "height": 43,
        "pointsize": 40,
They're set in the beginning and are the same for all letters.
The second group are the horizontal and size parameters:
            "baseline": 15,
            "height": 17,
            "horizadvance": 7,
            "horizoffset": 1,
            "width": 10
In most fonts, each letter has different values here, but most capital letters have the same "height" values for example. Punctuation is considerably smaller, that's one way to identify them.
The last group are the coordinates of the letter on the texture font file:
            "s": 0.001953125,
            "s2": 0.021484375,
            "t": 0.15234375,
            "t2": 0.185546875,
In the picture above, you can see the two arrows with a t and s at their tail. That's how you can read these values on the texture. I use a calculator and multiply the texture's width with the s value. The new number tells me how many pixels from the left (s) and top (t) edge the letter is located. In IrfanView (and most other image programs), you can select an area (letter) and the selection will have the information how many pixels it's from the left and top edges, and how big it is. With a calculator (pixel value from selection divided by total width or height of texture) we can find the "s" and "t" values fairly quick. The difference of each pair of values is the size of the letter texture (which gets extracted from the whole font textue). For future reference, let's call this small texture "Typeface".
In addition to the three groups of values, there is also a num entry. This number tells the game what letter it is. I made a table of beenox_med_hd.xmlb, with most letters and symbols below:

basel. height width horiza. horizo. # ident.# sign
1 3 3 7 -1 32 160 (space)
15 17 10 7 1 33 !
15 8 14 12 2 34 "
15 17 20 16 0 35 53,66 #
17 21 19 16 0 36 $
16 18 23 21 1 37 %
16 18 23 19 0 38 &
15 8 8 6 2 39 '
15 21 14 8 -1 40 (
15 21 14 8 -2 41 )
16 12 15 16 3 42 *
14 14 18 16 1 43 +
4 9 9 7 -1 44 ,
7 5 11 7 -1 45 -
4 6 8 7 0 46 .
15 21 22 13 -4 47 /
16 18 19 16 0 48 49,51,52,54 0
16 18 19 16 0 49 1
15 17 19 16 0 50 2
16 18 19 16 0 51 3
16 18 19 16 0 52 4
15 17 20 16 0 53 5
16 18 19 16 0 54 6
15 17 18 16 2 55 7
16 18 20 16 0 56 8
16 18 19 16 1 57 9
11 13 9 7 0 58 :
11 16 10 7 -1 59 ;
14 15 17 16 2 60 <
11 8 18 16 1 61 =
14 15 17 16 1 62 >
16 18 17 14 1 63 ?
16 19 24 19 0 64 @
15 17 20 16 -1 65 A
15 17 20 16 0 66 B
16 19 19 16 1 67 C
15 17 21 18 0 68 78 D
15 17 19 15 0 69 E
15 17 19 14 0 70 107 F
16 18 20 17 0 71 G
15 17 21 17 0 72 75,82 H
15 17 11 7 0 73 I
15 17 15 10 -1 74 J
15 17 21 17 0 75 K
15 17 16 13 0 76 L
15 17 25 22 0 77 M
15 17 21 18 0 78 N
16 18 20 17 1 79 O
15 17 21 16 0 80 P
16 21 21 17 0 81 Q
15 17 21 17 0 82 R
16 18 20 15 -1 83 S
15 17 18 13 1 84 T
15 17 19 16 1 85 U
15 17 18 15 2 86 V
15 17 27 24 2 87 W
15 17 21 15 -1 88 X
15 17 20 15 1 89 Y
15 17 20 14 -1 90 Z
16 22 12 8 0 91 [
15 21 14 13 2 92 \
16 22 13 8 -1 93 ]
15 10 17 14 0 94 ^
0 5 18 14 -2 95 _
17 7 10 14 4 96 `
12 14 17 15 0 97 110 a
15 17 18 15 0 98 100,104 b
12 14 16 13 0 99 c
15 17 18 15 0 100 d
12 14 17 14 0 101 111 e
16 18 13 9 1 102 f
14 20 21 14 -2 103 g
15 17 18 15 0 104 h
16 18 10 7 0 105 i
16 22 14 7 -4 106 j
15 17 19 14 0 107 k
15 17 10 7 0 108 l
12 14 26 23 0 109 m
12 14 17 15 0 110 n
12 14 17 14 0 111 o
12 18 18 15 0 112 p
12 17 18 15 0 113 q
12 14 13 9 0 114 r
12 14 16 12 -1 115 s
15 17 11 9 1 116 t
12 14 17 15 1 117 u
12 14 16 12 1 118 v
12 14 22 19 1 119 w
12 14 17 12 -1 120 x
12 18 18 12 -1 121 y
12 14 16 11 -1 122 z
12 21 13 8 0 123 {
15 21 11 14 3 124 |
15 21 12 8 -1 125 }
10 7 18 16 1 126 ~
...
1 3 3 7 -1 160
...
18 24 24 24 0 162-188 194-196 xbox (15), upgr circl (12)
16 18 24 21 0 189-190 ©, ®
15 11 24 21 1 191
20 22 20 16 -1 192 À
193
18 24 24 24 0 194-196 (shield logo blue), (cross), !
197
198
199
20 22 19 15 0 200-201 È, É
...
20 22 12 7 0 204 Ì
20 22 14 7 0 205 Í
...
20 22 20 17 1 210-211 Ò, Ó
...
20 22 19 16 1 217-218 Ù, Ú
...
17 19 17 15 0 224 à
...
16 10 13 9 1 230 °
...  231
17 19 17 14 0 232-233 242-243 è, é
...
17 19 11 7 0 236 ì
17 19 13 7 0 237 í
...
17 19 17 14 0 242-243 ò, ó
...
17 19 17 15 1 249-250 ù, ú
...
20 30 30 30 0 256-306 400-411,512-562 Keyboard
...
20 30 75 75 0 284 286-292 Keyboard
20 30 120 120 0 285 Keyboard
20 30 75 75 0 286-292 Keyboard
20 30 90 90 0 393-398 Keyboard
20 30 60 60 0 399 Keyboard
20 30 30 30 0 400-411 Keyboard
...
20 30 30 30 0 512-562 Keyboard



Now, I want to write a bit about the possibilities we have with the font xmlb (with the values for the texture):
The easiest and quickest way to do change a font, is the first group, the vertical parameters. Thanks to UltraMegaMagnus for discovering this. Without the fix for RE UI he made, I probably wouldn't have discorered anything about fonts. I will try to explain each value with the pictures below:


ascender (7)
The ascender is commonly the part of letters that go above the "x-height" (eg. on a "h"). In this game, it's the whole distance from the baseline.
descender (8)
The descender is commonly the part of letters that go below the baseline (eg. on a "g"). It's the same in this game.
height
This is bigger than pointsize (see below), to set a distance between lines. Most likely it's the distance between baselines (commonly referred to as leading in typography). The value needs to be equal or higher than the highest height of the glyph's.
pointsize (Td)
I have to disapoint: We cannot change the font's size by editing this value. It rather changes the text boundaries as well.
See the pointsize in the picture below.

Abbreviations with prefix T (eg. "Tc")                           Click on the picture
It's basically ascender plus descender, but ascender + descender don't have to equal pointsize.
If a text in a menu doesn't align properly, and we can't help it by changing alignment in the menu engb (because the text box (1) is too big or small), we might get lucky by changing some values: A top aligned text (2) can easily be adjusted in height by changing the ascender value (i.e. moving the ascender line). This has no effect on center and bottom aligned text, but it also increases the space between lines of paragraphs with multiple lines (while not affecting the letters). Equally, center aligned text (3) can be adjusted by changing height and/or pointsize, while it has little effect on bottom aligned text.
height (9) and width (6) (=T2)
So how do we scale a font? We have to use the second group of parameters, which means, that we need to scale each letter seperately (that's why I collected information in the table above). Remember the "Typeface" from before? This texture has a certain size (in pixel) that will be very useful for the two values "height" and "width". By default, the Typeface width and height are equal to this width and height. To scale a font, we have to adjust height (9) and width (6) in each glyph.
baseline (10)
This is the vertical offset, measured from the baseline. Important for letters that float, compared to the others (eg. ' ), or that go lower (eg. "g"). To have letters appear on a line, the "height" (9) and "baseline" (10) should be equal for letters that are "grounded" on the Typeface (most uppercase letters). Every letter that floats must have a bigger baseline value and every letter that goes below the baseline or has empty space below it (in the Typeface itself) must have a smaller baseline value. Letters that align on the top (eg. AhBb) have the same baseline value, if they align on the Typeface as well. Letters that don't exceed x-height (eg. gxnrq) also have the same baseline value, if they align on the Typeface as well. Round letters usually have a smaller baseline value, because it looks better (eg. "C" has a smaller baseline value than "T").
horizadvance (4, Tc)
This is usually the same or almost the same as width. For a console font, this value would have to be consistent (same for each letter). Most fonts have an equal "type metal width" (Tc) and "typeface width" (6). But if it differs, it's very important to know the difference between the two. Where the two values (Tc and 6) align (centered, left, right) is defined by the creator of the font and differs. For MUA, they align left: If horizadvance (4) is bigger than the width (6), the character will have a space after (right of) it.
horizoffset (5)
This is usually 0 or very small. Some letters need to be adjusted to go closer (kerning) to the previous letter, or get further apart (spacing). Horizoffset is used to move them relative to the previous character. Horizadvance can be used to move them relative to the following character. Sometimes both values have to be changed to horizontally align a character properly between the others.


This is quite advanced, I realize. Ask, if you're uncertain about something. I will try to answer.

Honestly, this is a very fascinating find! Considering how these games don't have much documentation left behind on how they work internally, discovering things like this will get us closer to fully understanding it