mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-10-04 08:21:50 -04:00
6.0 KiB
6.0 KiB
T3 — head-type layouts and canonical files
Status: done | expert: expert-fable (2 attempts, handoff after c3) | ctx-at-completion: n/a | commit: see COMMIT | coder runs: c1 opus55 done (5aaa25154), c2 opus55 blocked→committed (e4341ee11), c3 opus55 done (1a35655ab)
Done: the two head types and the player block are each defined once in include/struct_types.h (included by include/common.h, so visible to ov, main and md_* alike), every overlapping offset resolved by the max-site split with a per-offset record; proven IDENTICAL on 9 exemplar TUs across ov/md/main; restruct now sees include/ and no longer refuses nested-base overlap edits.
Files:
- include/struct_types.h — generated block (head_types.py) for
Unkstruct_800B5CB8(0x10C, 101 fields) andUnkstruct_80126B58(0x24C, 152 fields); hand-writtenUnkstruct_80078E78(0x98, evidence-named) - include/common.h:64 —
#include "struct_types.h" - tools/head_types.py — new: max-site split over the struct map's layout ∪ conflicts (weighted-interval DP);
--header,--decisions,--selftest - tools/type_census.py:56 —
CANON_HEADERS = ("src/shared/engine_types.h", "include/struct_types.h") - docs/struct-map-decisions.md — canonical file set, resolution rule, player block, generated per-offset records
- tools/delever.py —
includers()follows-Iinclude(relative first, else include/x; scans include/*.h) - tools/restruct.py —
pass_hinttolerates non-str residual rows;drop_overlapskeeps nested-base overlapping edits as KEPT(overlap-edit); +2 selftests (56) - src/800.c:8 —
typedef Unkstruct_80078E78 Blk98_80029274;(byte-identical) - docs/struct-map.md, .run/P37/census/{struct_map_top.json,type_census.json,type_census.txt}, .run/P36/delever/calibration.json — regenerated outputs Decisions:
- binding: head-type width conflicts resolve by the max-site split (the width most sites use wins the offset; the losers are recorded per offset in docs/struct-map-decisions.md); unions are deferred until a reader-facing reason appears (27 union candidates on 800B5CB8, 4 on 80126B58 listed there).
- binding: the canonical file for cross-space types is
include/struct_types.hreached throughinclude/common.h, not per-space files — the map shows one layout per head across ov, md_* and main, so a per-space file would be a duplicate by construction. - Field names in the generated blocks stay
unkHEX(G62); only the player block carries evidence-named fields (docs/actor-struct.md, memory-map §3.4). Deviations: Unkstruct_80078E00was defined asUnkstruct_80078E78: no cluster, global or access exists at 0x80078E00; the code's player record starts at 0x80078E78 (Blk98_80029274,Blk80078E78,D_80078E78in 880 TUs) and its widths disagree with both heads. Same object, evidence-correct name; not a redefinition of the clause.- "one main exemplar" holds for 800B5CB8 (src/800.c) but not for 80126B58: the map has 0 main bodies for it (ov 16,773 · md 311 · main 0), so none can exist.
- Plan's file list named src/shared/main/ and src/800_shared.h; the canonical file went to include/ instead (see Decisions), and three tool fixes outside the list were needed to prove the layouts (delever include graph; two restruct
--try-filedefects that pre-dated this task). - The verify of record ran after an extra prep step (R22 → snapshot-baseline → calibrate at
54c26d08a): the c3 commit had made the a1 calibration stale. Findings: - head_types:
800B5CB8 fields=101 kept_sites=75717 dropped_sites=25393 conflict_offsets=50 overlaps=167 misaligned=4 union_candidates=27;80126B58 fields=152 kept_sites=61599 dropped_sites=1713 conflict_offsets=50 overlaps=71 misaligned=5 union_candidates=4. - 800B5CB8 drops 25 % of its sites in the split: it is a suspect merged cluster (several layouts keyed to one AT global); 80126B58 drops 1.5 %.
- Exemplar proofs, all final IDENTICAL, 0 TYPE-NOT-VISIBLE: 800B5CB8 → ov_SC06_032_jr_80182890, ov_SC02_027_jr_8017D898, md_SC07_004, md_SC07_003, src/800.c; 80126B58 → ov_MAIN_012_jr_8015A3C8, ov_SC03_107_jr_8015A3C8, md_MAIN_046, md_MAIN_036 (
.run/logs/t3c3_try_1..9.log). - REFUSED bodies in the exemplar runs were per-candidate compile errors (e.g. md_MAIN_036:300
ar46E98undeclared), not layout faults. - The P37 T4e census had merged the heads as
Unkstruct_800D3888through a stalebody_base_type.json; a fresh--sitescensus separates them. restruct reads.run/P37/census/*(hard-coded). - audit-types still 26 (all in engine_types.h, 0 in struct_types.h). Gotchas:
- harness:
restruct --selftest --realreads red after ANY commit (calibration pinned to a HEAD hash); the log/summary commit necessarily post-dates the verify. Re-prep = R22 →delever_oracle --snapshot-baseline→--calibrate ov_SC04_011 ov_SC03_015 md_SC07_004 main -j 16(bare--calibraterefuses; ~4 min total). - harness: a
/* 0xNN */field comment nested inside another C comment kills the build; generated headers must not wrap offset comments. - generalizable: an include graph that ignores
-Ipaths hides every type placed in include/ from the judge ("type not visible" on a visible type); model the compiler's search order (relative, then each -I dir). - harness: the expert's Bash hook denies reading tool sources even by range; use retriever-code.
Research: none (three retriever-code answers, no reports)
Next task needs: T4 applies
include/struct_types.hfleet-wide via rung L cycles;Unkstruct_800B5CB8is a split candidate for T5 (25 % dropped sites); 80126B58 has no main bodies; recalibrate before any--selftest --real; REFUSED bodies are compile errors to fix per candidate, not layout rejects. Verified: .venv/bin/python tools/restruct.py --selftest --real && make clean && make extract-all JOBS=16 && make check-all JOBS=16 → rc 0 at54c26d08aafter recalibration (calibrate 146/146 identical, positive control DIFFERS); restruct --selftest --real 61/61 OK; extract-all 217 extracted, 0 failed of 217; check-all 218 passed, 0 failed of 218 (.run/logs/t3_verify3.log) Full log: phase-ends/current/logs/T3.md