How to use this page

Check here before committing to a reading that looks obvious. Rows are terminal - if new evidence reopens one, it moves back to open RE threads rather than having its verdict edited in place, because the falsification trail is what makes the row useful.

Two classes recur often enough to name up front. VA aliasing: a bare virtual address is not an identity, because slot-A and slot-B overlays host different code at the same VA, so a dump labelled by address can be a different function entirely. Ghidra's collapsed switch: a jump table's arms can render as bare breaks or as fake FUN_x calls, inventing opcode semantics the raw table does not have.

World map / kingdom bundles

ThreadVerdictWhyDetail
Slot-4 → cluster-A converter site falsified No converter exists. The cluster-A pool DAT_8007C018 is filled exclusively by FUN_80026B4C, reached only from FUN_8001f05c case 0x02 (TMD pack) and 0x09 (bare TMD); slot-4's type-0x05 case never calls it. world-map-overlay
World-map outline / coastline reading falsified The slot-4 bodies are small object-local 3D meshes, not kingdom border / coastline wireframe. Treat any future "kingdom border lines" claim with suspicion. world-map-overlay

Battle / arts / level-up

ThreadVerdictWhyDetail
Move-VM op 0x2F extension dispatcher — per-overlay copies? falsified (one copy, field overlay 0897 only) One copy, field overlay 0897 only. The capture-derived _801d362c dumps are identical to each other (0897 observed under world-map / dialog / cutscene scenario labels); the 0897 static dump is a strict subset of them rather than a byte-identical twin, carrying no address the captures lack. Substance is unchanged: every other mapped slot-A overlay + the title overlay carries unrelated bytes at the fixed call VA and no jump table at 0x801CE868, so op 0x2F is executable only while 0897 is resident and battle-side move records cannot use it. move-vm
"FUN_801F3894 spirit/magic damage roll" (state-0x3D chain caller) falsified (VA-aliased dump) The overlay_0897_801f3894 dump is FUN_801DD0AC byte-for-byte under a double VA shift (0897's extraction over-reads into 0898; the program maps the file at 0x801C0000, not the slot-A base 0x801CE818), so the already-ported damage kernel surfaces at a fake entry VA. The real state-0x3D callee FUN_801F3990 is a cast audio-cue dispatcher; spirit damage is state 0x3E's inline formula (battle_formulas::spirit_damage). Corollary, widened: every overlay_0897_801Exxxx and 801Fxxxx dump is suspect - the band is not just 0x801F. Two further casualties are settled: 801f0348 (escape roll) and 801e23ec, whose aliased reading recovered only the base initiative roll and silently dropped all three modifier terms. 0x801F1ED4/0x801F45A4 remain unverified. battle-formulas
"About 2 % of retail camera beats set a non-zero roll" falsified (the figure was the scan's own filter) The number came from a byte scan - decode an op-0x45 CONFIGURE at every offset of every scene MAN - which finds 4257 "sites" where control flow reaches 371. Junk sites set a junk roll almost every time, so the scan applied a post-hoc "credible" filter and then measured roll over the survivors: the ratio is a property of that filter. Its sibling strict linear sweep reported the opposite (zero non-zero rolls) by reaching 21 sites and none of the eight real ones. The answer - retail does roll, in eight scenes, up to −58° - came from executing the records, not decoding them. Generalises: a measurement instrument has no oracle, so check its explanation against the artifact rather than against its own plausibility. settled threads
Navmesh / per-scene navigation data falsified 0x80108EA4..0x80109550 is per-scene GPU primitive scratch. Real region / event data lives in the field-file preamble (count + u16 offset table + records - not the field-pack schema slots, a global-constant template); collision is the +0x4000 MAP grid. navmesh
Op-0x4E sub-ops 4..8 "absolute jump" / "rand → next PC" readings falsified (all sub-ops 0..9 are the 7-byte compare-and-skip) Ghidra's collapsed switch invented both. The raw 12-entry jump table at 0x801CEE30 routes every sub-op 0..9 to a value loader that joins one shared compare-and-skip continuation at 0x801E0B40. details ↓ script-vm
801d58f0 / 801d63b0 as single shared port blockers falsified (VA-aliasing artifact) The two addresses host different code in different overlays (byte-verified: 80/228/124/308/1 B and 208/1036 B across 0897/baka/cutscene/debug-menu/fishing/slot/dance) - the port-catalog's bare-VA keying aggregated their refs into phantom top blockers. Tracked per-overlay via overlay_<label>_<addr> identities; catalog ignore category va_aliased_overlay_local. port-catalog
Charm battle softlock = unbounded reroll in FUN_801E7320 falsified (cannot spin from any reachable state) The reroll loops are unbounded in isolation, but every reachable caller state has an exit: the scheduler FUN_801DABA4 never seeds a dead actor (predicate +0x14C != 0 && !(+0x16E & 0x4)), the acting 0x380 monster is itself an in-band self-pick exit (0x801E73E8 clears +0x1DE), and a band with zero living members means the previous 0x5A already fired the wipe. The real defect is downstream in the 0x5A victory arm's roster indexing. Lesson: an unbounded loop hangs only under a reachable all-invalid state - check the predicates feeding it first. battle
Gaza 2 0x51 park: overkill-clamp asymmetry as a standalone retail generator falsified (amplifier only) The damage kernel's two overkill clamps (accumulator vs displayed readout, live HP vs itself) can only disagree when the readout already lags live HP at action start - and the previous party-targeted action's own settle wait guarantees it doesn't. The capture that anchored the generator reading (live HP 266, readout 0, zero accumulator) turned out to be phased crediting: a multi-strike action credits the readout per strike while live HP commits once at the end, so mid-action watchpoints see the "absorbing" shape on perfectly healthy fights. Only a mismatch surviving the action's own commit and settle wait counts - none has been captured from retail-only play. battle-action
Gaza 2 0x51 park: the Lost Grail auto-revive lands mid-drain "at the worst possible moment" falsified (on the Gaza 2 move set; 12/12 revives clean) The revive path's bare accumulator assign is real, but the timing premise fails: readout credits land per strike early in a resolution, the revive state arrives only after the remaining targets and effects wind down, and the quarter-step drain empties any accumulator faster than every observed gap. A three-capture campaign with a Lost-Grail-armed party (no harness writes to any HP, readout, or accumulator field) drove twelve retail auto-revives across cast-path, kernel-path, single-target and party-wide kills: every restore found the accumulator already at zero, margins 143–280 vsyncs. The surviving question is narrower and lives on the open-threads page. battle-action

Audio / sound driver

ThreadVerdictWhyDetail
FUN_80068D94 as "SsSepOpen / SEP loader" (with FUN_80068B98 as "SsSeqOpen") falsified (it is the VAB-open head) The plausible part: it validates a magic, reads a count at +0x12, SsSpuMallocs, and patches a pointer table - the shape of a SEP/track loader, with the magic read as 'VAP'. The disassembly refutes it: the compare is 0x564142 against word >> 8 plus low byte 0x70 - pBAV, the VAB magic - and +0x12 is ps. The "per-track pointer table" is the ProgAtr table receiving the program → packed-tone-page rank map; the mislabel hid that map, and with it the engine's tone collapse on sparse banks. Correct roles: audio. vab
The entry matching "[u32 format == 2][u16 spu_addr[256]], every address ≥ 0x8000" is monster.snd falsified (it is summon.dat; monster.snd is a multi-bank VAB two entries away) 0x8000 is exactly the boundary an SPU sample address clears once the reserved low region is skipped, so 256 halfwords all above it read as a fully-populated address table - and one PROT entry matched, under a CDNAME label naming the sound cluster. What it matched is summon.dat, whose header word is a mode 2 and whose next 0x200 bytes are a BGR555 CLUT with the STP bit forced on every non-zero entry, setting bit 15 of all 256 halfwords for a reason unrelated to addresses. The tell the predicate cannot see: the values repeat, and SPU addresses are strictly increasing. monster.snd is a 206-bank multi-VAB archive two extraction slots away, named by its loader's own li v0,0x37d. Generalises to: a threshold over a fixed-size run identifies a shape, never a format - where the shape encodes an ordering, assert the ordering. summon-readef

Field / locomotion

ThreadVerdictWhyDetail
Scene-bundle type-6 descriptors are "all small placeholders" falsified (12 are walker tables) Plausible: the modal slot really is a 4-byte count = 0 filler (85 of 97 bundles) and the three kingdom tables had been attributed to a "kingdom slot 5" special. But the 80/172/516-byte type-6 payloads (garmel, dohaty, the geremi/rayman/tunnel/son/edson family) parse as the same CLUT-walk table, installed identically for every bundle — the water/waterfall shimmer. The rayman-family carrier is the count-4 MAN-less table variant the strict detector rejects; resolve the slot by type byte. docs/subsystems/field-ambient-fx.md
Move-VM loop op 0x19 "retires past itself (size 2), loops back to the saved PC" falsified (both halves inverted by the C rendering) Wrong against the raw arm (80023070.txt 0x800235DC + the 0x80024150 epilogue): retail loops while the decremented count has not underflowed, retires on underflow with size 1, and the loop-back lands at saved + 2 (the epilogue adds a2 = 2 after the PC store) — re-running the 0x18 itself would re-seed the counter forever. jou's 15-instance ambient cycler fan-out is the disc witness. Sibling correction: ext 0x1E returns size 4, hidden behind a func_0x801d4a3c() label-call return. move-vm
"~270 undumped field-overlay functions" (recomp dispatch-entry seed list) falsified (not a function inventory gap) Not a function inventory. The recomp capture's seed PCs are interpreter dispatch entries — return sites, interrupt-resume PCs and jr-table labels — accumulated across every overlay generation of the session (title / FMV / menu / field) while only the byte snapshot is per-dump. Dozens of listed addresses land in 0897's data head, one source capture's resident bytes match disc 0897 at only ~16%, and only two coincidental hits verify at all (both in the never-resident slot-machine image), the rest being j-target labels rather than function entries. Seed lists need per-hit resident-image resolution before any identity claim. details ↓
Prologue gold grade = per-node +0x74/+0x78 depth-cue crush falsified (grade is a palette-space collapse; the nodes carry no IR0) Plausible because FUN_8002735C really does load per-node DPCS far colour + IR0, and the motion/move VMs carry op 0x0C writers of those fields - but the opening never uses them: a live recomp capture reads node +0x78 (IR0) = 0 on every node at every beat, and the opdeene MAN motion section has no op 0x0C. The real mechanism is a load-time CLUT/TMD palette collapse L=max(r,g,b) → (L, max(L-1,0), L>>1); the far-field crush is that law seen through dark authored gouraud. cutscene

Containers / entry coordinates

ThreadVerdictWhyDetail
The world-map kingdom bundle is PROT 0085 / 0244 / 0391 falsified It is 0086 / 0245 / 0392. Those indices are the block's prescript entry; the bundle's 7-asset table is at offset 0 of the next entry, which the over-read window saw as "offset 0x1800". below
The battle-form character pack holds seven atlases inside PROT 1204, the last truncated, with CLUT row 496 skipped falsified Eight whole atlases, in PROT 1205. Row 496 is the eighth atlas, not a gap; the "seven" and the "truncation" were where the over-read window stopped. below
The title TIM ships as three multi-bank duplicates in PROT 0888 / 0889 / 0890 falsified One copy, in 0890 at 0x14228. All three (entry, offset) pairs resolve to the same absolute PROT.DAT offset. below

Details

Assets named by the entry the over-read window started in

Status: falsified - each asset is where it always was; only the (entry, offset) name for it was wrong.

Under the pre-correction PROT entry size a reader positioned on entry N could see entries N+1, N+2…, so an asset got recorded as "PROT N offset K" whenever the scan that found it started at N. The coordinate is not wrong about the disc - start_lba(N)*0x800 + K really is where the bytes are - it is wrong about which entry owns them, which is the only thing a correctly-bounded reader can use. The symptom is a name rather than a corruption, which is why it outlived the reader.

Each wrong name came with corroboration, and that is the instructive part. The kingdom bundle's table really was at 0x1800, with the right count and the right first descriptor offset. The battle-pack atlases really did sit at a consistent stride from a consistent base, and a truncated last member is an ordinary thing to find at the end of a container. The title TIM's three "duplicates" really were byte-equal.

Two transferable lessons. Byte-equality between two (entry, offset) pairs is evidence of duplication only once you have shown the pairs resolve to different absolute offsets - otherwise it is a tautology, the same shape as the falsified "PROT 0900 and 0901 are shifted copies". And a container's member count and a member's size are properties of its framing - a chunk chain, a descriptor count in the header - not of where a buffer happens to end; a count derived from "how many fit before the buffer ran out" is measuring the reader, not the disc.

Corrected coordinates and the two invariants that keep them honest: prot § a (entry, offset) pair.

Op-0x4E sub-op family - every sub-op 0..9 is a compare

Status: falsified ("absolute jump" 5..8 and "rand → next PC" 4 were Ghidra's collapsed switch).

The raw 12-entry jump table at 0x801CEE30 (field overlay, PROT 0897 file +0x618) routes every sub-op 0..9 to a value loader that joins the shared 7-byte compare-and-skip continuation at 0x801E0B40:

subloaderstate value
0 / 10x801E0A40 / 0x801E0A70char-record HP / MP (cur, max) pair - the only scaled form (max * arg >> 8)
20x801E0AC0char level byte +0x130
30x801E0AECparty gold _DAT_8008459C
40x801E0AFCBIOS Rand() & 0xFF - a random-chance branch
5..80x801E0B0Cslot table 0x801C6460[sub - 5] (s16; the read side of the 4C CA/CB/CC slot writes)
90x801E0B34coin bank _DAT_800845A4

Sub-ops 10/11 keep the 9-byte u32 gold/coin form; 12..15 fall through (PC += 7). The decompiled bare-break arms for 2..9 were the collapsed switch - each raw loader ends j 0x801e0b40 / j 0x801e0b3c with the operand pointer staged in the delay slot, the same class of trap as the label-call idiom. Disassembler + executing VM corrected: field_disasm::decode_subops, engine-vm field/step/flow.rs. cave01's P2[12] spawn gate is the live sub-5 exemplar.

"~270 undumped field-overlay functions" - the recomp dispatch-entry seed list

Status: falsified (not a function inventory gap).

The seed PCs are the recomp interpreter's dispatch entries - return sites, interrupt-resume PCs and jr-table labels - and the capture accumulates them across the whole session (title → FMV → menus → field), so a "field window" list mixes title-overlay, cutscene-overlay (0970) and menu-era PCs with field-era ones. Smoking guns: one source capture's resident bytes match the disc 0897 image at only ~16% (title-era, a different occupant); dozens of listed PCs land inside 0897's data head (debug strings + pointer tables, impossible as 0897 code); and two entries the list marked as already-known resolve to the cutscene overlay's STR dispatch FUN_801CEA3C and the actor-VM jump table 0x801CED70 - a different overlay's function and a data address.

Sweeping all mapped slot-A overlay images plus the slot-B field library for prologues / static jal targets at the listed addresses yields only two coincidental hits (both in the never-resident slot-machine image) and a handful of j-target labels. The durable lessons: seed lists from a recomp's interpreter dispatcher need per-hit resident-image resolution before any identity claim, and a "new function" claim needs a prologue or a static-call witness in the image that was actually resident. The real undumped-code question for 0897 is better served by the port-catalog dashboard.

No overlay function lives below 0x801CE818

Falsified: "an undocumented address in the 0x801C0164..0x801CE000 band is an overlay-resident function awaiting a doc entry."

The reading is plausible because the project's own orientation says overlay code lives "at 0x801C0000+", and because dumps in that band disassemble cleanly, carry function-shaped prologues and epilogues, and are filed under overlay_<label>_801c….txt names. Nothing about them looks wrong.

They are not functions. They are printed addresses from imports based at 0x801C0000, and the true VA of every one is printed + delta. The structural argument needs no dump at all: every occupant of the slot-A overlay window bases at 0x801CE818 and every slot-B occupant at 0x801F69D8, so no extracted overlay image contains any VA below 0x801CE818. An address in that band cannot name a function in any overlay, whatever its dump looks like. The measurement agrees: disassembling every extracted image at its mapped base and asking which of those addresses is a jal target, a j target or an instruction boundary returns nothing at all for the whole band.

The deltas are constant per import - +0xE818 into the field (0897) or menu (0899) overlay, +0xD018 into fishing (0972), +0x9818 into dance (0980), +0x5818 for the overlay_0896_* family - so the whole band resolves mechanically. Worked examples: the "function at 0x801C6FEC" is the fishing reel tug-of-war FUN_801D4004; "0x801C56B4" is the hooked-fish handler FUN_801D26CC; "0x801C2704" is menu-overlay FUN_801D0F1C. Each is already documented under its real address.

The same failure extends above 0x801CE818, where it is harder to see because the printed address then falls inside a real overlay's span and cannot be rejected on range alone. There the working test is the same one: resolve the dump's bytes to an image and offset, and separately ask whether the printed VA is a jr ra-preceded boundary in any image. A VA that is only ever a j or branch target is an intra-function label, not a port site.

Generalises to: treat "the dump prints an address" as evidence about the import, never about the game. Which image, which offset, is this a function at all - those are answered from the extracted image at its mapped base, and only from there. The same deltas drive the static overlay pipeline, which attaches each image's identity from its PROT entry rather than from a filename.

Measurement readings

Falsified claims about the instruments, not about the game. They belong here for the same reason the rest do: each was a plausible reading, each was believed, and each shaped what work looked worth doing.

ThreadVerdictWhy
The disc-coverage report's excluded dumps are "typically the ones that report 0 instructions and hold only decompiled C" falsified (zero of them reported 0 instructions) The files that do report 0 instructions were passing the header regex and being credited a byte each. Of the excluded set, three were C-only and four fifths were not dumps at all. The count was real; the sentence attached to it had never been checked against the files.
The inner of two nested overlay spans "cannot be repaired … no amount of dumping moves it" falsified Address ambiguity really is total for the inner span. Byte attribution then places most of those extents in one image or the other, and the row reports. The starting point of a measurement was mistaken for its limit, and the structural-sounding argument made it read as settled.
The unattributable residue "is repaired by re-dumping, not by extracting another overlay" falsified Re-dumping repairs almost none of it. The residue had been described from its class names rather than counted from the artifact.
0x8005BA38 is "not a function - the dump reports size=1 bytes, 0 instructions" falsified (it is a complete RotTransPers) The dump was empty when the row was written and is 11 instructions now. Nothing re-reads a caveat when its dump improves, so a claim quoting a dump statistic decays silently while still reading as evidence-backed.
"About 2 % of retail camera beats set a non-zero roll" falsified (the figure was the scan's own filter) The number came from a byte scan that finds 4257 "sites" where control flow reaches 371, then applied a post-hoc "credible" filter and measured the ratio over the survivors. The answer - retail does roll, in eight scenes - came from executing the records, not decoding them.
An over-strict header regex is one instrument's bug falsified (every instrument had its own) Each tool over the dump corpus carried a private header regex, and the corpus spells all four header fields several ways, so each silently rejected a different subset of real dumps and reported them as a corpus deficiency.

Generalises to: a measurement instrument has no oracle, so a number it prints is believed on the strength of its explanation. Check the explanation against the files, not against its own plausibility - most of the rows above are a correct count with a wrong story attached, and the story is what directed effort.

See also