For education purposes only · no game files included · bring your own THUG
Guide 08

Button hints

How to make "△ = Accept" say <Enter> = Accept on a keyboard, Ⓐ on an Xbox pad and ✕ on a PlayStation one, following the bindings and switching the moment you touch another device.

GoalEvery hint in every menu and level shows what you have to press, on the device you're holding.

1Find out why everything was a triangle

Text draws \b<n> as glyph n of the buttons font, and \m<n> through a meta table first. The PC port only loaded ButtonsPs2. Dumping both fonts shows glyphs 0–18 and nothing more:

GlyphButtonsPs2ButtonsXbox
0–3△ □ ○ ✕Y X B A
4–7↓ → ← ↑↓ → ← ↑
8, 9Start, SelectSTART, BACK
10–13↘ ↖ ↙ ↗↘ ↖ ↙ ↗
14–17L1 R1 L2 R2L trigger, R trigger, White, Black
18L1+R1L+R
19+nothing: falls back to glyph 0

Same index, same position: 0 is the top face button, 3 the bottom one. (Found by dumping the fonts' glyph tables: header, char map, 8-bit texture, palette, sub-texture rects.)

The PC scripts use codes 19 and up (\bm = Accept, \bn = Back) that no font has, and a missing glyph falls back to glyph 0. Hence: a triangle, on a keyboard.

The original PC exe must have mapped those codes to key names. We don't have that exe's code, so: archaeology.

2Decode the tag zoo

TagMeansExample
\b0–\biPS2 buttons by position, D-pad, diagonals, L1/R1/L2/R2\b7/\b4 = Select
\bm \bn \bo \bpPC only: Xbox A, B, X, Y\bm = Accept
\bq \br \bs \btPC only: Black, White, left/right trigger\bs/\bt = Rotate
\bkPC only: the right stickcolour menu
\m<n>An action, through meta_button_map_xbox to an Xbox button\m5 to talk → B

3Resolve a tag the way the game reads it

Each tag becomes the PS2 pad bit the game expects there (B is Back in menus, Grab when skating), then whatever is bound to that bit for the device: a key name, or a glyph from the right font, written as new tags \x (Xbox font) and \p (PlayStation font).

new fileWn32/Code/Plat/Sys/SIO/p_buttonglyphs.cpp · working tree

The fonts have no [ ]. They do have < >. So keys look like <Num 6> to talk, which is at least unambiguous: "A to talk" reads like the Xbox button.

4Follow the last device

new fileWn32/Code/Plat/Sys/SIO/p_buttonglyphs.cpp

5Draw the new tags, load both fonts

diffWn32/Code/Plat/Gfx/nx/chars.cpp · working tree
diffCode/Gfx/NxFontMan.cpp · working tree

6Expand on SetText, re-expand on switch, re-layout the menu

Text elements keep the original string and where it was set. When the device or a binding changes, they re-expand, re-measure, and nudge their menu (menus only lay out children when locked), so the helper bar re-spaces itself.

diffCode/Gfx/2D/TextElement.cpp · working tree
diffCode/Gfx/NxFont.h · working tree

7Shrink a hint bar that got too wide

Key names are wider than icons; five keyboard hints ran off the screen. Horizontal menus now scale themselves down to fit, and back up when they fit again.

diffCode/Gfx/2D/Menu2.cpp · working tree

\bm is 3 bytes. <Num\_Enter> is 14. A 96-byte strcpy buffer had opinions about that.