The HUD is rendered using function RenderHud: 802E3D2C/09ED2C. This function reads state to determine which HUD elements to display and calls several other subroutines and makes use of the PrintStr() and PrintInt() functions.
RenderHudMarioLives: 802E3744/09E744
PrintStr(0x16, 0xD1, 0x80338380); // "," = Mario PrintStr(0x26, 0xD1, 0x80338384); // "*" = X PrintInt(0x36, 0xD1, 0x80338388, *0x8033b260); // "%d"
RenderHudCoins: 802E37A8/09E7A8
PrintStr(0xA8, 0xD1, 0x8033838C); // "+" = coin PrintStr(0xB8, 0xD1, 0x80338390); // "*" = X PrintInt(0xC6, 0xD1, 0x80338394, *0x8033b262); // "%d"
RenderHudStars: 802E380C/09E80C
int showX = 0; // 0x1F($SP) if ((*0x803316d4 == 1) || (*0x8032d5d4 & 0x8 == 0)) { if (*0x8033b264 < 100) { showX = 1; } PrintStr(0xF2, 0xD1, 0x80338398); // "-" = star if (showX) { PrintStr(0x102, 0xD1, 0x8033839C); // "*" = X } PrintInt(0x102+14*showX, 0xD1, 0x803383A0, *0x8033B264); // "%d" }
RenderHudHp: 802E3654/09E654
ShowCameraStatus: 802E3B3C/09EB3C
RenderHudTimer: 802E395C/09E95C
The two commonly used printing functions PrintStr and PrintInt accept null-terminated ASCII strings as input. It then uses a lookup table to determine which letter to display. This table is located in segment 02 alongside the letters. It notably contains missing entries for the letters J,Q,X,Z.
PrintStr: 802D6554/091554
void PrintStr(int X, int Y, char *string);
PrintInt: 802D62D8/0912D8 This is more of a generic printf() style function that accepts a format and variable arguments.
void PrintInt(int X, int Y, char *format, ...);
The lookup table for each of the ASCII characters is located at segment address 0x02007700 (80A856 in extended ROM) and contains entries for each 16×16 RGBA texture. The default table has null entries for J,Q,X,Z and uses some symbols for HUD characters.
Before referencing the lookup table, the character in ASCII is converted to an offset within this table by the function at 802D6858/091858.
int convertchar(int ascii) { if (ascii >= 0x41 && ascii < 0x5B) { // 'A' <= ascii <= 'Z' return ascii - 0x37; } else if (ascii >= 0x61 && ascii < 0x7B) { // 'a' <= ascii <= 'z' return ascii - 0x57; } else if (ascii >= 0x30 && ascii < 0x3A) { // '0' <= ascii <= '9' return ascii - 0x30; } else { switch (ascii) { case 0x20: return -1; break; // ' ' case 0x21: return 0x24; break; // '!' case 0x23: return 0x25; break; // '#' case 0x3F: return 0x26; break; // '?' case 0x26: return 0x27; break; // '&' case 0x25: return 0x28; break; // '%' case 0x2A: return 0x32; break; // '*' case 0x2B: return 0x33; break; // '+' case 0x2C: return 0x34; break; // ',' case 0x2D: return 0x35; break; // '-' case 0x2E: return 0x36; break; // '.' case 0x2F: return 0x37; break; // '/' } } return -1; }