Files
BFM-decomp/cookbook/C0187.md
T

1.9 KiB
Raw Blame History

§176b — BATCH-GATING MECHANICS (P31): what changes when N drafts land in ONE .c

Gate cost scales with (binary, TU) GROUPS, not with drafts. Each group is one whole-binary rebuild. Wave D was 42 drafts spread over 23 groups (~40 min of gate); waves F–N were 40–56 drafts in 1 group. tools/build_wave_atlas.py packs a wave into few TUs for exactly this reason — it is free throughput, purely a selection change.

Batched drafts must agree WITH EACH OTHER, not just with the file. Each draft is written to compile standalone, so N drafts bring N independent extern sets into one TU:

  • Type conflicts: D_800A4ED4 declared s16 by one draft and u16 by another; func_8001C9D0 as void / void * / s32 across three. C rejects the TU.
  • Duplicate typedefs: every draft carries its own typedef struct {…} SVECTOR;. Once one banks, that typedef lives in the .c forever and every later draft collides. Strip duplicates on substitution (harvest_verify already did; gate_main now does).
  • Compatibility compares TYPE SIGNATURES ONLY. Parameter names are irrelevant to C — a checker that compares them wrongly discards good drafts (my first version dropped 2 that way). But the DECLARATOR SUFFIX absolutely matters: u8 D_x and u8 D_x[] are incompatible, and ignoring it let a real conflict reach the build (my second version). Too-strict and too-coarse are both defects.
  • Recovery, not rejection: a conflict-dropped draft is usually CORRECT. Adopt the other declaration verbatim and adapt at the USE site — extern u8 D_80076251; + (&D_80076251)[i], or void f(s32 a0) + D_x[(s16)a0] — which emits identical bytes (§174 Law 4).

A COMPILE error names its own culprit; only a BYTE mismatch needs a search. Bisecting a batch costs a full clean rebuild per step (a 41-draft bisect ran 28 minutes producing nothing) while the compiler had already printed the symbol and line. Read the error first.