diff --git a/docs/re/data/difficulty-is-a-dialog.txt b/docs/re/data/difficulty-is-a-dialog.txt index 85adc71c..609706a5 100644 --- a/docs/re/data/difficulty-is-a-dialog.txt +++ b/docs/re/data/difficulty-is-a-dialog.txt @@ -75,7 +75,16 @@ # one. Every DLG_ string in the image is pointed at by exactly one aligned word, # at a regular 12-byte stride. The table is: # -# struct { u32 handler; u32 id; u32 name_ptr; } // 12 bytes, big-endian +# struct { u32 id; u32 name_ptr; u32 handler; } // 12 bytes, big-endian +# +# 🔴 CORRECTED 2026-08-31: this first read as `{handler, id, name_ptr}`, which is +# the same three fields SHIFTED BY ONE WORD, so every record was credited with the +# PREVIOUS record's handler. Caught by a control dump: under the old alignment +# record 0 (DLG_LET_SIGNIN) had a "handler" of 0x10000000, which is not a code +# address. ids and names are unaffected -- they are the same fields either way, +# and DLG_SELECT_DIFFICULTY is still id 2000. Only the handler attribution moved. +# Under the corrected alignment its handler is 0x821D0808, and the histogram over +# all 70 records is 0x821D0808 x43, 0x821D05D8 x24, 0x821CFD80 x3. # # spanning 0x820A0A2C .. 0x820A0D68, three distinct handler values # (0x821CFD80, 0x821D05D8, 0x821D0808). @@ -243,3 +252,34 @@ # It cost two scans and went AGAINST the reading I had offered. A bound nobody is # incentivised to test is exactly where a convenient claim survives -- and the # next reader cannot tell whether a bound was respected or merely never revisited. + + +################################################################################ +# ❌ THE id -> PAK-ENTRY BINDING IS NOT IN THE IMAGE BY THIS ROUTE. 2026-08-31. +# +# Positional ordering was already ruled out. The next route was the dialog +# table's own handlers: if anything joins a dialog id to an archive entry, the +# code that builds a dialog should touch it. +# +# All three handlers were disassembled from the image. All three begin by loading +# the SAME global -- `lis r11,0x828E` then `lwz r3,0x2B14(r11)` -> 0x828E2B14 -- +# and two take addresses at 0x828E45E0 / 0x828E4640 / 0x828E467C. +# +# ❌ EVERY ONE OF THOSE IS BSS. They sit inside a single contiguous ZERO RUN of +# 364 601 bytes (0x828A28C7 .. 0x828FB900) -- uninitialised data, zero in the +# image, populated only at runtime. +# +# ✅ CONTROL, because an all-zero read is also what a bad address gives: the +# dialog table itself at 0x820A0A2C reads non-zero through the same arithmetic +# (10000000 00000000 820a4598 821cfd80). The addressing is right; the data is +# genuinely absent. +# +# => The handlers operate on RUNTIME state. If the id -> entry join exists there, +# it is visible only in a running game, not in the image. That is a route +# closed rather than a question answered, and it says where the next attempt +# has to look: guest memory at 0x828E2B14 with the game up. +# +# ⚠️ REACH: one route (the table's own handlers). Not looked at: the archive +# loader, the GamePart that opens GP_DIALOG, or any table keyed by id elsewhere +# in the image. "Not in the image" is NOT established -- what is established is +# "not reachable from the dialog handlers, because they read BSS".