# The UI screen object at runtime — found in live guest memory **Status:** ✅ `CONFIRMED` for the object's identity and its element array (five independent field matches against the file, on a running game). 🟡 the remaining arrays are unidentified. ❔ nothing here settles the paint order — see the "what this does not answer" section, which is the reason the search happened. ## How it was found, in one step The item class from the emulator-era splash work has vtable **`0x820b30b4`**, and `sub_823C2990` allocates its objects at **244 bytes** each ([`ui-quad-class-foothold.md`](../ui-quad-class-foothold.md)). A vtable pointer is a fixed 4-byte value at offset 0 of every instance, so the objects are findable in the live guest image without a debugger: ```bash tools/re-capture/gmem.py find hex:820b30b4 # while the title screen is up ``` Seven live objects, at `0xBCD24D88`, `0xBCD25188`, `0xBCD25388`, `0xBCD25488`, `0xBCD25588`, `0xBCD25688`, `0xBCD26488` — spaced 0x100 apart, consistent with a 244-byte object plus allocator overhead. ## What they are Each object begins with **two** vtable pointers (`0x820b30b4`, `0x820b31a4` — multiple inheritance) and then a run of `{pointer, count, capacity}` triplets. The counts identify the objects immediately: | object | first triplet's count | which `GP_TITLE` build | |---|---|---| | `0xBCD25188` | **7** | builds 0/1 — the loading overlay (7 elements) | | `0xBCD25388` | **24** | **build 4 — the title (24 elements)** | | `0xBCD24D88` | **1** | builds 2/3 — the `PRESS Ⓐ BUTTON` bundle (1 element) | So the three bundles this project decoded statically are all resident, with the element counts the files declare — including the two-bundle composition of the title screen that the draw capture inferred. ## The element array `+0x08` of the screen object is `{ptr, count, capacity}` pointing at an array of **48-byte entries, one per element, in declaration order**. Verified field-by-file at five positions on the title build, with no misses: | index | file says (build 4) | live memory at `+0x10`/`+0x14` | |---|---|---| | 0 | `ptlogo1.t32` pivot (451,50) | 451.0, 50.0 | | 1 | `ptlogo2.t32` pivot (449,46) | 449.0, 46.0 | | 6 | `pteff01.t32` pivot (320,160) | 320.0, 160.0 | | 9 | `ptbase2.t32` pivot (320,180) | 320.0, 180.0 | | 21 | `ptcopyright.t32` pivot (309,10) | 309.0, 10.0 | Entry layout as far as it is read: ``` +0x00 u32 pointer (per-element data) +0x04 u32 0 +0x08 u32 flags (0x10081021 on element 0) +0x0C u32 ? +0x10 f32 pivot X ← the declaration entry's pivot, as a FLOAT +0x14 f32 pivot Y +0x18 u32 0 +0x1C u32 ? +0x20 u32 pointer } +0x24 u32 count } the element's KEYFRAMES — 8/8 on elements 0 and 1, +0x28 u32 capacity } which is exactly their keyframe count in the file +0x2C u32 ? ``` So the pivot and the keyframe group, which this project reads out of the bundle, are present at runtime in the same order and with the same values. ## What this does not answer **The paint order.** The array is in *declaration* order, and the capture proves the screen is not painted in that order, so the renderer either walks something else or sorts. Three more `{ptr,count,capacity}` triplets are present in the screen object and unidentified — `+0x14` (24 entries of 12 bytes, each `{ptr,1,1}`, pointing into a densely packed region), `+0x24` (2 entries) and `+0x30` (24). The `+0x14` one is *not* an index list (its entries are pointers, not small integers), so the obvious "draw order table" reading is already out. **What is better than before:** the question is now a *data* question on a live structure that can be dumped in seconds, rather than a code-reading exercise. The next probe is to dump `+0x24` and `+0x30` on the title build and see whether either is 24 entries in a non-declaration order.