mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 14:02:04 -04:00
109ce6a2c3
- CRACKED at xHigh and VERIFIED INDEPENDENTLY: match_one MATCH (1061 ins); agent re-matched 3x from clean runs (100% register-masked AND register-kept, all 10 regions, frame 0x270 exact). §81 carve chain clean first try: jr_isolate_all --only -> byte-identical cacaf7c2 -> jtbl_carve (43-piece set) -> byte-identical -> bank -> R22 clean-fleet 140/140, tools-health OK. instr 80.6%; distinct-code 3,844,100 -> 3,845,161. - WHAT IT IS: the matched base func_8017CA80 + camera height-band cull + distance-driven CLUT fade. func_8004974C (TransposeMatrix) sits in a 36-ins prologue deriving a Y band; the part-level `lim >= g.otz` cull is GONE; flat arms gain an `sz < lim` near-plane cull. The base+one-extra-callee fingerprint predicted this exactly. - §82 ORACLE 1 -- A DUPLICATED `addiu $aN,$sp,K` ACROSS A `jal` MEANS THE BLOCK WAS INLINED. `&X` on any non-first local always creates a pseudo and CSE always merges two of them (expr.c:6260 ADDR_EXPR -> force_operand(..., NULL); exception: virtual-stack-vars offset 0). So the same stack address re-materialised at two sites separated by a jal means CSE was PREVENTED from merging => not the same function body. 17 non-inline spellings failed; a `static inline` helper reproduced the prologue BYTE-FOR-BYTE first try. Reusable probe: scan the ~1,200 built objects for that signature in NON-INCLUDE_ASM functions. - §82 ORACLE 2 -- SCALAR vs AGGREGATE DECIDES *WHEN* A STACK SLOT IS ALLOCATED: lazily at first `&` for a scalar, AT DECLARATION for an aggregate. Six GTE result words had to be six separate longs, not a struct, or they don't land after the inlined helper's temps and the frame isn't 0x270. Second-order: it also flips MEM_IN_STRUCT_P (§30's /s) -- with one word a fixed-address scalar, ((PolyF3*)pkt)->rgbc stops aliasing it, so a store needed respelling to keep the target's nop. A scalar-vs-struct choice is simultaneously a frame-layout AND an aliasing decision. - BANKING FOOTNOTE (§75a class A): first bank rejected `conflicting types for ApplyMatrixSV` -- draft (MATRIX2*, SVECTOR2*, SVECTOR2*) vs the TU/fleet canon (void*, void*, void*), 2,286 of 2,835 sites. Conforming the decl is byte-neutral and banked first try. On a jr function expect BOTH gates to speak: the carve chain answers the jump table, §75a answers the declarations. - Also reproduced: §78 (reuse a busy variable), §80(i) (a lever went -8 -> exactly neutral as the base moved), §72 (a register pin made it worse). - AGENT'S OWN CAVEAT, recorded not hidden: one zero-byte __asm__ keeps a vestigial `mnc = hmid` alive that flow.c would delete (costing 10 ins + the 0x130 spill slot). Emits nothing, compile is 1061 exact, but it is a documented stand-in -- 12 natural spellings measured, all DCE'd.