Commit Graph

273 Commits

Author SHA1 Message Date
Drew T 40ee73ba75 feat(phase-30 S49): propagate func_8017E404 (adapt lane) 2026-08-14 14:27:10 -06:00
Drew T d6762b5e7d feat(decomp): worker gate — +1 fns x0 propagated (fleet 95.3%) 2026-08-14 14:22:20 -06:00
Drew T fc33766950 feat(decomp): worker gate — +6 fns x0 propagated (fleet 95.3%) 2026-08-14 13:00:07 -06:00
Drew T d89958b341 feat(phase-30 S49): propagate func_8017D808 (adapt lane) 2026-08-14 11:08:47 -06:00
Drew T f398dce9bf feat(phase-30 S49): propagate func_8017CF5C (adapt lane) 2026-08-14 07:35:48 -06:00
Drew T c9f693d68a feat(phase-30 S49): propagate func_8017CE0C (adapt lane) 2026-08-14 07:35:33 -06:00
Drew T 4fde6e3e81 feat(phase-30 S49): propagate func_8017F390 (adapt lane) 2026-08-14 05:25:17 -06:00
Drew T b064d2b869 feat(phase-30 S49): propagate func_80182D0C (adapt lane) 2026-08-14 05:19:22 -06:00
Drew T 62341f4a48 feat(phase-30 S49): propagate func_8017D964 (adapt lane) 2026-08-14 05:14:31 -06:00
Drew T 8cc08a7686 feat(phase-30 S49): propagate func_80182120 (adapt lane) 2026-08-14 05:10:32 -06:00
Drew T 5b9ceafa8b feat(phase-30 S49): propagate func_80183A08 (adapt lane) 2026-08-14 05:10:22 -06:00
Drew T 16b2c1fbf2 feat(phase-30 S49): propagate func_8017F8A8 (adapt lane) 2026-08-14 05:06:15 -06:00
Drew T 972dfbc886 feat(phase-30 S49): propagate func_8017F4F8 (adapt lane) 2026-08-14 05:05:56 -06:00
Drew T 2ab342e3d9 feat(phase-30 S49): propagate func_8017CCF8 (adapt lane) 2026-08-14 05:01:49 -06:00
Drew T 028d9a496a feat(phase-30 S49): propagate func_8017DCD8 (adapt lane) 2026-08-14 05:00:21 -06:00
Drew T 7e90ad4c4f feat(phase-30 S49): propagate func_8017E0C0 (adapt lane) 2026-08-14 04:54:22 -06:00
Drew T d1840d8492 feat(decomp): worker gate — +2 fns x0 propagated (fleet 95.2%) 2026-08-14 02:39:53 -06:00
Drew T bf15795e84 feat(decomp): worker gate — +3 fns x0 propagated (fleet 95.2%) 2026-08-14 02:07:17 -06:00
Drew T 05f924e9f2 feat(phase-30 S49): propagate func_8017DEA0 (adapt lane) 2026-08-14 01:37:37 -06:00
Drew T e3aadd9150 feat(decomp): worker gate — +10 fns x0 propagated (fleet 95.2%) 2026-08-13 23:33:39 -06:00
Drew T dc6bbf5983 feat(decomp): worker gate — +12 fns x0 propagated (fleet 95.2%) 2026-08-13 23:32:27 -06:00
Drew T 94818c30c2 feat(decomp): worker gate — +1 fns x0 propagated (fleet 95.2%) 2026-08-13 23:28:25 -06:00
Drew T a3d748faa5 feat(phase-30 S49): propagate func_80184374 (adapt lane) 2026-08-13 17:38:33 -06:00
Drew T 596afa1385 feat(phase-30 S49): propagate func_80183890 (adapt lane) 2026-08-13 17:38:23 -06:00
Drew T 4c13e9b379 feat(phase-30 S49): propagate func_80182A7C (adapt lane) 2026-08-13 17:38:13 -06:00
Drew T 894b51e0ae feat(phase-30 S49): propagate func_801811F4 (adapt lane) 2026-08-13 17:38:03 -06:00
Drew T 60f54c33da feat(phase-30 S49): propagate func_80180190 (adapt lane) 2026-08-13 17:37:54 -06:00
Drew T c23bc5ef8f feat(phase-30 S49): propagate func_80181538 (adapt lane) 2026-08-13 17:34:36 -06:00
Drew T 77bb2039c8 feat(phase-30 S49): propagate func_801E2AF4 (adapt lane) 2026-08-13 17:31:57 -06:00
Drew T ce64886855 feat(phase-30 S49): propagate func_801EF964 (adapt lane) 2026-08-13 17:29:26 -06:00
Drew T 3a5397c529 feat(phase-30 S49): propagate func_80180954 (adapt lane) 2026-08-13 11:42:04 -06:00
Drew T 9ae5c5b334 feat(phase-30 S49): propagate func_80182C24 (adapt lane) 2026-08-13 11:41:39 -06:00
Drew T b4b578e52d feat(phase-30 S49): propagate func_8018042C (adapt lane) 2026-08-13 11:41:29 -06:00
Drew T 5205be4118 feat(phase-30 S49): propagate func_80188990 (adapt lane) 2026-08-13 11:40:56 -06:00
Drew T c85fc8853b feat(phase-30 S49): propagate func_80188748 (adapt lane) 2026-08-13 11:40:37 -06:00
Drew T 5fc7f16978 feat(phase-30 S49): propagate func_8018B388 to its cousins (wave 7a) 2026-08-13 06:53:52 -06:00
Drew T dabd2d4cb7 feat(phase-30 S49): propagate func_80183838 to its cousins (wave 7a) 2026-08-13 06:52:50 -06:00
Drew T ad7ffe5e6e feat(decomp): worker gate — +1 fns x7 propagated (fleet 95.1%) 2026-08-13 04:36:57 -06:00
Drew T 7f82d95468 feat(decomp): worker gate — +1 fns x8 propagated (fleet 95.1%) 2026-08-13 04:34:15 -06:00
Drew T 49cf2dc15a feat(decomp): worker gate — +1 fns x17 propagated (fleet 95.1%) 2026-08-12 22:56:40 -06:00
Drew T 527c7ffa7d feat(decomp): worker gate — +1 fns x1 propagated (fleet 95.1%) 2026-08-12 22:51:00 -06:00
Drew T 63bb8f8959 feat(decomp): worker gate — +1 fns x36 propagated (fleet 95.1%) 2026-08-12 22:47:24 -06:00
Drew T 019fd51883 feat(decomp): worker gate — +1 fns x9 propagated (fleet 95.1%) 2026-08-12 22:22:06 -06:00
Drew T ce85242084 fix(phase-30 S47-0a.2): conform func_80175414 — 1,845 decls / 1,061 files; R22 213/213
The new head plumbing class after the symbol-kind fix: `conflicting types for func_80175414` (27
member-rows). Byte-true DEF is `void func_80175414(s32 _arg0)` (its DEFINE_ macro). The fleet
declared it 1,845 times in four spellings, of which three are the SAME TYPE (parameter names do not
participate) — the outlier was 28 sites declaring `(void)`.

conform_decls REFUSED the naive conform and was right to: 29 ZERO-ARG CALL SITES exist across 28
files, so conforming the declaration alone turns each into `too few arguments` — a fleet-wide
COMPILE break the per-binary gate cannot see (the tool cites 138/140 binaries, measured). It named
the count, the consequence, why the cheap check misses it, and the flag that repairs it, then
forced the two-step: --cast-zero-arg-calls (29 sites cast to the 0-arg fn-ptr shape, §17a-1 — gcc
folds the cast of a known symbol to a direct jal, so it is codegen-neutral), then the conform.

Result: 1,845 declaration sites rewritten across 1,061 files, 0 non-canonical remaining (axis
complete, R32). R22 clean-fleet: check-all 213 passed / 0 failed of 213.

WORTH RECORDING AS A TOOLCHAIN STANDARD: this is the instrument that has not wasted a cycle today.
Every other one reported SUCCESS over a defect — a classifier that discarded every gcc-2.7.2 hard
error (no `error:` prefix), a diff that miscounted 116 data-bundled .s files, a --verified-out
truncated to zero bytes over 62 real banks, a --band default that reported "0 families" on a real
135-member family, and a scope stamp describing the filesystem instead of the run. conform_decls
reports FAILURE with a repair path. A guard must state its COVERAGE, not just its verdict; the
in-repo exemplars are this tool and the §53 jr interlock.
2026-08-11 14:15:01 -06:00
Drew T 206b279ffc feat(phase-30 S47-F4): canonicalize the 2 incompatible memcpy decls (+29); the feared class was 2 lines
engine_core.h carried memcpy in 5 spellings across 9 macro-local declarations. SEVEN already agreed
in TYPE — only parameter NAMES differed, which does not conflict, and u32 IS unsigned int. Exactly
two were incompatible, and both are safe for reasons verified against the code, not assumed:

  * DEFINE_func_801325B8 declared `void memcpy()` — return type void against every draft's void*,
    which is the actual collision in ov_MAIN_012. Its only plain calls are `memcpy(dv, sv, n * 8)`
    with a VARIABLE size, which gcc cannot inline-expand, so it emits a library call under either
    prototype; the return value is discarded, so the return-type change is invisible.
  * DEFINE_func_801638A0 declared `(void *, void *, s32)` but NEVER CALLS memcpy — the body uses
    __builtin_memcpy, which is expanded directly and is unaffected by the declaration. Vestigial.

Both canonicalized to `extern void *memcpy(void *, const void *, u32);`. All 9 decls are now one
type. Gated byte-identical on ov_MAIN_012 and ov_SC03_099 BEFORE sweeping; 142 binaries instantiate
DEFINE_func_801325B8, so R22 is the real arbiter: check-all 213 passed / 0 failed of 213.

Sweep: banked +29, failures 699 -> 670.

The documented hazard (ov_MAIN_012.c:14333 — an `extern memcpy` turning an inlined block-move into
a CALL) is real but applies to a case neither macro has: a CONSTANT-size call under a
builtin-compatible prototype. The checkpoint's caution was correct; the danger just did not apply
to these two. Task B was right to defer this rather than sweep it blind.
2026-08-10 22:53:22 -06:00
Drew T 320a14921c fix(phase-30 S47): CdFileLoc_80128C98 aliases CdFileLoc — clears 136 sweep conflicts
`conflicting types for cdFileLocTable` was the single largest remaining propagation-sweep failure
class (136 of 875). Cause: engine_types.h defined the SAME layout twice —

    typedef struct { s32 word0; s32 word4; } CdFileLoc;
    typedef struct { s32 word0; s32 word4; } CdFileLoc_80128C98;

Each anonymous struct definition mints a DISTINCT C type, so a TU holding both
`extern CdFileLoc_80128C98 cdFileLocTable[]` (137 sites) and `extern CdFileLoc cdFileLocTable[]`
(9 sites) is declaring one object with two incompatible types. This is the same type-IDENTITY
collision scope_data_externs documents for S_AF634: no type-STRING compare can see it, and
cdecl.compatible correctly answers "compatible".

Fix is one line — `typedef CdFileLoc CdFileLoc_80128C98;` — so the two NAMES denote one type.
Byte-neutral by construction: identical layout, so indexing scales by the same 8 bytes either way.

NOT unified with the 3 `extern u8 cdFileLocTable[]` sites: element size drives index scaling and
those sites carry their own explicit `<< 3` (note at resident.c:656). Folding them in would change
codegen, which is exactly the memcpy-class trap.

Verified byte-identical on ov_SC01_077 and ov_SC03_099. Committed ahead of the re-sweep so the
sweep's per-member revert cannot undo it mid-run; fleet R22 lands with the sweep batch.
2026-08-10 20:36:33 -06:00
Drew T 9ab9120e04 feat(phase-30 S47-B): conform 8 declaration axes (~10,930 sites); 3 guard defects fixed; 213/213
Task B, re-scoped from evidence. The 129 dedup_extend failures are 106 conflicting-types /
21 CC1-FAIL / 4 undefined-ref / 3 DIFF — real byte divergence is 2%, and memcpy is 17 of 106,
not the story. Direction reversed too: the byte-true DEF of func_80128ED8 is what the target
.c files already declare; engine_core.h's macro-local extern was the stub-era guess.

Conformed 8 axes to byte-truth (func_8012F14C 2843, func_8012E5CC 2052, func_8012F038 2214,
func_8014C568 1816, func_80128ED8 1524, func_8012C750 406, func_8012C0EC 50, func_80144A04 25).
R22 clean-fleet: check-all 213 passed / 0 failed of 213. Zero functions banked by design.

Tooling (R33/R35) — three guards that asserted completeness over a narrowed population:
- NEW tools/macro_draft.py: a deduped fn has no definition in any .c (body lives in a DEFINE_
  macro), so conform_decls had been refusing the largest class it was built for.
- conform_decls skipped engine_core.h wholesale as "a defining TU": 10 stale externs survived
  while 1,514 fleet sites moved, and it still printed "axis complete". Skip now scoped to the
  defining macro's span.
- Return-axis compare was literal: typedef int/s32 and a missing `extern` faked a return change.
  Now compares normalized types.
- §85 consumer scan under-reported (the dangerous direction): a cast between `=` and the call
  hid `s0 = (s32 *)func_80144A04(...)`. Now classified by position, validated both ways.

Corrections to my own predictions (R14): the documented scalar-narrowing hazard was benign
across 2,052 sites; the breaks were arity (6 call sites, fixed with §17a-1 fn-ptr casts) and
the consumer-guard gap. A header-only first probe broke ov_SC01_000 — §85 is literal.

Not done, named: memcpy (builtin codegen), ApplyMatrixSV (no DEF), gte_SetRotMatrix (link bug),
func_80147364 (unparseable macro), D_800AE620/D_80126CC4 (data axis). Cookbook §159.
2026-08-10 16:01:49 -06:00
Drew T b005312127 feat(phase-30 S46-3): propagation banked — 29 fns / +2,815 member-instances; R22 213/213
The S45p9 blocker is closed, and the recovery loop that kept it from finishing is rewritten.

- BANKED: dedup_propagate --auto-from ov_SC02_037 --recover -> 29 functions propagated,
  141 overlays byte-identical, dedup 1920 -> 1949 groups, member instances 246,284 ->
  249,099 (+2,815). make clean && extract-all && check-all -> 213 passed / 0 failed (R22).
- WHY IT FINISHED THIS TIME: gate_all -> gate_failures returns EVERY failure from the sweep
  that already computed them, and the recovery loop resolves them all per round. Converged in
  3 rounds; the old one-overlay-per-sweep design needed ~138. That reframes the S45 run — it
  was not nearly done when it died, it had barely started.
- Batching did NOT cost capability: per-overlay necessity probes excluded four of the nine
  culprits from only the 9 overlays that needed it (not all 138), and ov_SC07_006 was
  RECOVERED by the Part-B caller-extern reconcile instead of excluded.
- Plan phase parallelised: 5 min -> 26 s, plan + skip classification byte-identical. Its
  compiles_standalone temp file is per-call now — the fixed `t.c` was the same fake-isolation
  class as match_one's shared --work dir (P28 T5), latent until something ran it in parallel.
- docs/accelerators.md (NEW, Drew 2026-08-07): the reusable-workflow ledger — what we learned
  late that a future decomp should know on day one, each entry with when we found it, when it
  WAS findable, what it cost, and the honest prerequisite where one exists.
2026-08-07 22:24:35 -06:00
Drew T fe946595fd fix(phase-30 S45p7): dedup_propagate leaves no orphaned reconcile on failure + func_8015C030 propagated x7
ROOT CAUSE of the 141/213 breakage earlier this session (correctly derived this time;
my first attribution to F1 was WRONG -- no arity journal ever touched func_80146A6C and
the arity undo reported success):

  dedup_propagate --recover's Part B reconciles a conflicting caller extern and
  DELIBERATELY leaves the edit on disk when it buys the byte-match ("keep the reconcile
  on disk"). Correct while the fn survives -- but a fn can still be dropped by a LATER
  iteration against a different overlay, and when the plan finally emptied, the
  "all candidates dropped" sys.exit fired with NO restore. Reconciles kept for
  ov_SC07_001..009 were orphaned: no-proto'd caller externs for functions that were
  never propagated -> ov_SC07_010 "passing arg 2 of func_80146A6C makes pointer from
  integer" -> 141 of 213 binaries failed check-all.

  The byte-gate never mis-banked (it fails closed). The real cost was VERDICT VOIDING:
  every subsequent gate reported "near" against the broken tree, so two whole batches
  (4/4 and 20/20) were mis-read as draft failures when they measured the tree (R35).

FIX: a reconcile LEDGER. Every kept reconcile is recorded against its fn, undone the
moment that fn leaves the plan, and ALL outstanding reconciles are restored before the
failure exit -- so a failed propagation leaves the tree exactly as it found it.

HONESTY: the fix is IMPLEMENTED AND REVIEWED BUT NOT YET PROVEN. The negative control
aimed at the exact failing propagation SUCCEEDED instead (different tree state), so the
guarded path never executed. A targeted test of the ledger is still owed.

Also lands the propagation that control performed: func_8015C030 x7 overlays
(func_80168B70 excluded from 4 SC07 overlays, survived elsewhere). check-all 213/213.
2026-08-07 18:49:56 -06:00
Drew T 9f61cd33c5 feat(phase-30 S6): BOTH GIANT WALLS CRACKED ×138 (+50,094 ins) — the verdicts were stale, not wrong
The two functions the roadmap has carried as PERMANENT WALLS since Phase 24 are matched in all 138
overlays. Neither needed a siege. Both matched from drafts ALREADY ON DISK.

  func_80178004  165 ins x 138 = 22,770   Phase 26: Fable5, ~477k tokens, "intrinsic 3-integer
                                          regalloc wall". THREE stored drafts report match_one
                                          MATCH today; one banked first try, no new work.
  func_801412A8  198 ins x 138 = 27,324   close=29/110 since Phase 24. Matched from 1 of 31 stored
                                          drafts + the §37/§124 alias.

WHY func_801412A8 LOOKED INTRINSIC (worth understanding — match_one is structurally blind to it):
the TU declares `extern int func_801412A8(int,int,int,int,int,int)` and its callers USE the return
(`param_1 = func_801412A8(...)`), while the byte-true definition is
`Prim_1412A8 *(Prim_1412A8 *, int, int, int, u16, u16)`. Narrow params cannot agree with an `int`
prototype and the no-prototype escape is illegal once a param promotes, so NEITHER side can move --
and the resulting byte difference is in the CALLERS, which match_one never compiles. The §37/§124
def-side asm-label alias decouples them: the TU decl keeps governing the call sites (codegen
untouched), the definition keeps its byte-true signature.

THEN PROPAGATION RETURNED 0/137 TWICE, both times a missing TYPE, not codegen:
  family_remap's `_carry_macros` carries file-scope #defines but (a) NOT typedefs, and (b) is NOT
  TRANSITIVE -- it brought addPrim_1412A8 and stopped, though that macro calls setaddr/getaddr and
  getaddr casts to PTag_1412A8. Lifted Env_1412A8 / PTag_1412A8 / Prim_1412A8 + OT/getaddr/setaddr
  into src/shared/engine_types.h (inside the include guard) -> 137/137, 0 failed.

MY ERROR, CAUGHT BY THE GATE: I lifted the typedefs but did not STRIP them from ov_SC01_077.c, so
they were declared twice and gcc-2.7.2 rejects a repeated typedef even when identical -- the lesson
already recorded at the foot of engine_types.h. R22 came back 139/140 with [FAIL] ov_SC01_077 (the
exemplar's own overlay). Stripped, re-verified, 140/140. A proper lift strips the source;
build_engine_types --strip does both and I did it by hand.

Also a measurement error worth recording: I checked whether the draft defined Prim_1412A8 with a
plain `grep -c` -- which matches inside `addPrim_1412A8` -- and briefly concluded the carry worked.
Substring false positive; the same shape as reading a `return` as a declaration.

VERIFIED: make clean && make extract-all && make check-all -> 140 passed, 0 failed of 140.
Fleet 12432941 -> 12483035 instr (+50,094 -- EXACTLY the two giants x138); fn-count +276;
instr-weighted 94.5% -> 94.8%. audit-digest OK. 0 NON_MATCHING (G4).

THE RULE THIS BUYS: re-measure a wall before respecting it, and SCAN every stored draft rather than
sampling (my first pass checked 8 of 31 and reported "closeness 40" for a function whose MATCH was
in the 9th). Four minutes of re-measurement was worth 50,094 instructions.
2026-08-05 12:51:06 -06:00