From 9367f91ec0106b14dd23a40211d340acb196d8b7 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Mon, 24 Aug 2026 10:07:43 +0000 Subject: [PATCH] formats: decode the HUD glyph quad behind the objective counter Following the pointers that move with REMAINING OB lands on four identical objects whose first word is 0x820B2A64. Read live: that address holds 32 consecutive code pointers in 0x823c43b0..0x823c45a0 terminated by 0xfffffffc - a vtable - and sylpheed.db has three ref xrefs to it from sub_823C3060, sub_823C3148 and sub_823C31E0, i.e. three construction sites, the same pattern the splash item vtable shows. No name: the disc's RTTI carries none. The instance is a textured quad: a pixel size at +0x1c/+0x20 (34 x 42 for a digit) and four vertices at +0x30/+0x48/+0x60/+0x78, each a colour and a UV pair. The four UVs measured are the corners of an axis-aligned rectangle in order, all 0xffffffff. The atlas size is a check rather than a guess: the UV rectangle is 0.0265 x 0.0547, and multiplying by 1280 x 768 gives 33.9 x 42.0 against the 34.0 x 42.0 stored in the object's own size fields - two independent fields agreeing to a rounding step. Also recorded: these objects churn. Re-reading an old pointer target a minute later returned unrelated data, so this is a snapshot of a live pool. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE --- docs/re/structures/hud-glyph-quad.md | 75 ++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 docs/re/structures/hud-glyph-quad.md diff --git a/docs/re/structures/hud-glyph-quad.md b/docs/re/structures/hud-glyph-quad.md new file mode 100644 index 00000000..a15ab0f4 --- /dev/null +++ b/docs/re/structures/hud-glyph-quad.md @@ -0,0 +1,75 @@ +# The HUD's glyph quad — vtable `0x820B2A64` + +**Status: ✅ `CONFIRMED` for the object layout and the atlas size**, read live off +a Stage 02 run and checked against itself. 🟡 the class has no name (RTTI carries +none disc-wide). + +## How it was reached + +[`mission-objective-counter.md`](mission-objective-counter.md) found that the +words moving with `REMAINING OB` are four ASCII digits and four guest pointers. +Following the pointers lands on four objects with an identical shape, whose first +word is `0x820B2A64`. + +## It is a vtable, with three constructors + +Read out of guest memory: **32 consecutive code pointers**, all inside +`0x823c43b0 … 0x823c45a0`, terminated by `0xfffffffc`. `sylpheed.db` has three +`ref` xrefs to it, from `sub_823C3060`, `sub_823C3148` and `sub_823C31E0` — three +construction sites, the same pattern the splash item vtable `0x820b30b4` shows. +The DB does not classify `0x820B2A64` itself as a vtable and knows no name for +it, which is expected: the disc's RTTI carries no class names. + +## The instance + +``` + -0x0c f32 1280.0 ) the design space, immediately before the object + -0x08 f32 720.0 ) + +0x00 u32 0x820B2A64 vtable + +0x1c f32 34.0 width in pixels + +0x20 f32 42.0 height in pixels + +0x30 u32 0xffffffff vertex 0 colour + +0x34 f32 u u + +0x38 f32 v v + +0x48 … vertex 1 (+0x18 stride) + +0x60 … vertex 2 + +0x78 … vertex 3 +``` + +Measured on one digit glyph: + +| vertex | colour | u | v | +|---|---|---|---| +| 0 | `0xffffffff` | 0.5477 | 0.5013 | +| 1 | `0xffffffff` | 0.5742 | 0.5013 | +| 2 | `0xffffffff` | 0.5742 | 0.5560 | +| 3 | `0xffffffff` | 0.5477 | 0.5560 | + +Four corners of an axis-aligned rectangle, in order, all untinted — a textured +quad. + +## ✅ The atlas is 1280 × 768, and that is a check rather than a guess + +The UV rectangle is 0.0265 × 0.0547. Multiply by **1280 × 768**: + +``` +0.0265 × 1280 = 33.9 -> the width stored at +0x1c is 34.0 +0.0547 × 768 = 42.0 -> the height stored at +0x20 is 42.0 +``` + +Two independent fields of the same object agree to within a rounding step, which +is what makes the atlas size a measurement instead of a plausible number. + +## ⚠️ These objects churn + +The four pointers next to the counter swap as the digit changes, and re-reading +one of the *old* targets a minute later returned unrelated data — the object had +been recycled. Anything read here is a snapshot of a live pool, not a stable +address. + +## What this is for + +It gives the port a decoded HUD text primitive: a glyph is a quad with a pixel +size and four UVs into a 1280×768 atlas, drawn by a class with 32 virtual methods +and three constructors. And it explains why the objective counter was so easy to +find in RAM — the value sits inside the widget that renders it.