# The guest's UI quad class — a foothold found from the capture's vertex layout **Status:** 🟔 `PROBABLE` for the identification below (it is a static read, but the layout it matches was *measured* first). ā” the element walk that decides paint order is **not** in this note — that is what the search was for, and it was not reached. ## How it was found The runtime capture says exactly what a UI vertex looks like: `prim = 13` (quad list), stride **24**, attributes `57@0` (`k_32_32_32_FLOAT` position), `6@12` (`k_8_8_8_8` colour), `37@16` (`k_32_32_FLOAT` UV). That is a fingerprint a store sequence in the guest must match, so the binary was searched for functions that write floats at +0/+4/+8, a word at +12, floats at +16/+20, and advance a pointer by 24 (`sylpheed.db`, 15 candidates ranked by how many of each they contain). The tightest match is **`sub_82250138`** (288 B, three of each store, two `addi …, 24`), and it is unambiguous: ``` 82250150 addi r5, r0, 13 ; primitive type 13 = QUAD LIST 82250154 addi r4, r0, 4 ; 4 vertices 82250158 lwz r11, 0(r31) … ; renderer->slot0(4, 13) -> allocate 82250170 lwz r11, 8(r11) … ; renderer->slot2() -> vertex pointer 82250188 addi r10, r0, -1 ; colour = 0xFFFFFFFF 82250194 stfs f13, 0(r3) ; x 82250198 stw r10, 12(r3) ; colour ← +12, as the capture says 822501A0 stfs f13, 4(r3) ; y 822501A4 addi r11, r3, 24 ; next vertex ← stride 24, as the capture says 822501AC stfs f0, 8(r3) ; z 822501B0 stfs f0, 20(r3) ; v 822501B4 stfs f0, 16(r3) ; u ``` `prim = 13`, four vertices, colour `0xFFFFFFFF` and stride 24 all match what the title screen was measured drawing. ## What it is (and what it is not) Its only caller, `sub_8224FB78` (752 B), is a **constructor**: it stores a vtable pointer into `0(r29)`, zeroes a run of fields, sets a colour, and has the emitter lay down a default quad. So `sub_82250138` builds an object's *initial* geometry rather than drawing a frame. The vtable it installs is **`0x820A7264`** — class `ANON_Class_AAFDBF89`, **2 slots** (`sub_8224FF98`, `sub_8224FB18`). That is the UI quad/sprite class. **It is not the element walk.** Following the callers upward: ``` sub_82250138 (quad emitter) ā”” sub_8224FB78 (constructor, installs vtable 0x820A7264) ā”” sub_82222E70 (2 260 B) ā”” sub_821A5F10 (756 B) ā”” sub_821A8578 (3 120 B) ← a top-level render function ā”” sub_821A8428 (284 B) ``` `sub_821A8578` is not data-driven: it is an **unrolled** run of about thirty identical `bl 8217FA08 / bl 821AC450 / bl 82454918` triplets. So it sequences a fixed list of subsystems, not a list of screen elements. The element order this project is chasing is somewhere else — most likely behind one of those three repeated calls, or behind the sprite class's own two vtable slots. ## Why this is worth keeping Two reasons, neither of which is "it looks right": * the identification is anchored to a **measurement** — the vertex layout came from the running game first, and the search was for code that matches it; * it names a concrete class (`0x820A7264`) and a concrete API shape (`allocate(count, prim)` then `get vertex pointer`), which is the thing to instrument or trace next. **Not settled:** everything the search was actually for. No function that iterates screen elements has been found, and nothing here bears on the paint order yet. ## Second pass: the drawing API is small, and a UI item is 244 bytes Continuing the search for the element walk (2026-08-19). Three more facts, none of which is the walk: * **The drawing API is enumerable.** The renderer accessor `sub_823C2AC0` — the one the quad emitter calls to get its vertex pointer — has exactly **6 callers**, and four of them (`sub_821D6A40`, `sub_822380B0`, `sub_82234610`, `sub_821BC718`, ~160 instructions each) are sibling quad emitters. So the number of places in the whole title that can emit a UI quad is small enough to enumerate, which is worth knowing before instrumenting anything. * **`sub_823C2990` is a factory, not a singleton accessor** — a correction to what its use inside the top-level render function suggested. It allocates twice from a heap held at `[0x828E2B14]` via `sub_82150EF8`: 4 bytes for a handle, then **244 bytes** for the object, and runs `sub_823DE0C0`, which is the head of the chain that ends in `sub_823CB2A0` — the constructor that installs vtable `0x820b30b4`. So **a UI item object is 244 bytes**, and the "LOGO item" class named in the emulator-era notes is what this factory builds. * **The `0x823C…` region is the screen/bundle subsystem.** It contains both the item class (constructors at `823CB2A0/823CB558/823CBB90`, methods `823CE558…823CFD90`) and four of the functions that load the `RATC` fourcc (`823CAF10`, `823CABE0`, `823CB1F0`, `823CBEE8`), so bundle parsing and item construction live together. ## Stated plainly: this is becoming a rabbit hole Three iterations have added map without answering the question. The searches keep landing on *construction* and *emission*, never on the per-frame walk that orders elements — and each step is a plausible next query rather than a decisive test, which is the shape of a search that can run indefinitely. The decisive alternative, costed rather than started: the vertex buffers the capture already records (`vb=0x14D10B90`, …) are written by the **guest CPU** just before the draw. A Canary memory watch on that range would report the guest **PC** doing the writing, which names the emitter and its caller directly instead of inferring them. That is a real change to the emulator (the watch machinery exists for shared-memory invalidation, not for reporting PCs), so it is the next thing to weigh — against simply leaving the paint order unresolved, which costs the port one screen's fidelity and nothing else.