Skip to content

Write the port's own text in the game's message font - #64

Merged
Adubbz merged 3 commits into
TheMoonPeople:portfrom
carrdylan52:pr/game-text-20261006
Oct 6, 2026
Merged

Adubbz merged 3 commits into
TheMoonPeople:portfrom
carrdylan52:pr/game-text-20261006

Conversation

@carrdylan52

Copy link
Copy Markdown
Contributor

The port's own menus need to show text in the game's own font. This adds that, as the base for the new Options screen and, later, for moving the localisations to JSON. Three commits on current port. Nothing under ps2/ changes.

What it is

  • The character table. PAL text is negative codes: -0x300 to -0x2E0 are the pad buttons and icons, -0x2DF to -0x288 are the 88 cells of gaiji.img's letter grid, and -0x287 to -0x254 are œ ¡ ¿ ß Œ Ç ç and the accented letters DrawGaijiFont builds by drawing an accent over a base letter. I read the table off gaiji.img in every meswin/mes_tex_N.pak and checked it by decoding every .mes on the disc (about 670 files). All seven packs draw the same characters in the same cells, so one table serves every language, and each language's text uses only its own accents. It agrees with MakeMesWinTbl_value's digits and the PAL NameRegistCodeJtoE table.
  • GameTextEncode / GameTextDecode (port/src/gametext.cpp) turn UTF-8 into those codes and back. Typographic quotes and dashes become the font's own. A character the font lacks, or a byte that isn't UTF-8, becomes ? and is counted. {N} writes code N as it is (control codes, icons, colours), and {{ a {. Every message on the disc decodes and encodes back to the same codes.
  • GameTextFile lays texts out as a message file for ClsMes::SetBuff. That is where JSON localisation would plug in later.
  • GameText is one piece of text drawn the way the menus draw their help line (CommonMenuMes2 under InitMenuMesSet): the menu font, white with a black edge, shown whole. Set the text, SetColour a FontColor, then Draw(x, y, alpha) from a menu's draw function. Width returns the width, for right-aligning a value. Each holds its own ClsMes, so labels, values and a help line are one each.

Limits

ClsMes has fixed tables: 720 laid-out glyphs and ten line positions.

  • The glyph table. SetMesWinTbl wrote past the 720-entry table without a check. A PC_OVERRIDE copy now stops at 720; apart from that one check it is retail's body, character for character. A GameText that doesn't fit returns -1 and draws nothing.
  • Line positions. DrawMesWin read line_pos[10] for an eleventh line. It now draws such a line as it draws a line with no position entry; lines 0 to 9 draw exactly as before.
  • Message files. GameTextFile refuses an id outside s16, and a file whose offsets don't fit in s16, instead of dropping messages.

Testing

Windows (Debug, clang 23): 109 of 109. Linux (clang 23): a clean build; ctest 102 of 102 on RADV and on lavapipe; git clang-format clean; truncations.py --check passes; Doxygen gives no new warning; the two recorded replays (a debug item grant, a dungeon floor) run to the end. The eight GameText tests are pure table tests (no game data), about half a second together. macOS is not built here.

Shown in the title's Options screen through a temporary hook, not part of this PR, as it will be used: "PC Settings" in gold beside the header, a label with a right-aligned value, and a line of French, German and Spanish accents.

Things you may want different

  1. Fixed pitch. The menu message font is fixed-pitch (11 px), so this text looks like the help line, not like option.pac's sprite labels. The Options PR uses it for every row, which you and Dylan preferred.
  2. The wide glyph page (12 px, which shop dialogue uses) isn't offered. It would be a flag on GameText.
  3. English only for now. The port's own strings stay English literals until the localisation work; GameTextFile is the seam for that.

GameTextEncode turns UTF-8 into the s16 codes ClsMes draws, by the PAL
font's table read off every language's gaiji.img and checked against
every message file on the disc. GameTextFile lays texts out as a message
file for ClsMes::SetBuff, and GameText draws one piece of text as the
menus draw their help line, for labels, values and help in the Options
screen.
SetMesWinTbl now takes nothing past MES_WIN_LINE_MAX laid-out characters,
where retail writes on over the window, and GameText::Set reports a text
that did not fit (its end never laid out) rather than drawing part of it.
DrawMesWin draws a line past the ten line_pos entries in the block
layout instead of reading beyond them. GameTextFile::Set refuses an id
outside s16 and a message that would start beyond the file's s16
offsets, leaving the file as it was.
SetColour's new layout can overflow the window where a value code now
prints more digits; Set reported the old count and never laid the text
out again. Set now retries while nothing is laid out, and SetColour
records the failure. Say plainly that every message in a file must
start within its s16 offsets.
@Adubbz
Adubbz merged commit 0cedaca into TheMoonPeople:port Oct 6, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants