From 364ddd7055e3826ade1c57daaa773983b48edbcb Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Sat, 25 Jul 2026 13:04:15 -0600 Subject: [PATCH] =?UTF-8?q?fix(phase-29):=20ENGINE=5FSHB=20=E2=80=94=20the?= =?UTF-8?q?=20carried-#define=20gap=20that=20capped=20func=5F80165CA0=20at?= =?UTF-8?q?=20=C3=973?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CAUSE (measured, not guessed): the 132 extend failures were `undefined reference to 'SHB'` -- a LINK error, not a type conflict. SHB is not a symbol; it is a file-scope `#define SHB(x) __asm__(...)` sign-extension barrier. A body's preamble can carry `#define`s as well as `extern`s, but extraction lifts only the externs -- so the `#define` was left behind in the source overlay. In ov_SC01_077 it sits literally BETWEEN the two carried externs and the instantiation: extern s32 D_8011D030; extern s32 D_80126728; #define SHB(x) __asm__ __volatile__("" : "=r"(x) : "0"(x)) DEFINE_func_80165CA0() The other 132 overlays DO define SHB -- ~300 lines further down the file (stub @4462 vs #define @4781 in ov_SC01_001), i.e. BELOW the splice point, so the preprocessor never expands it and cc1 emits a call to an undeclared `SHB`. Pure ORDERING; nothing was missing. - Also explains why the 3 current members are EXACTLY the 3 files carrying the __volatile__ SHB spelling: that define is the function's own preamble, still sitting above its instantiation. - FIX: engine_core.h owns the barrier as ENGINE_SHB (distinct name, so the overlays' own SHB -- which exists in BOTH a volatile and a non-volatile spelling -- can never collide), and DEFINE_func_80165CA0's 7 uses now call it. Volatile form: what the 3 banked members compile with today. The body is now self-contained wherever it is instantiated. - BYTE-GATED the full existing blast radius: ov_SC01_077 d19c9580 · ov_SC01_000 9052dc0e · ov_SC07_006 7ca772be -- all BYTE-IDENTICAL. - This is the dedup_propagate counterpart of Phase-27's family_remap._carry_macros (§75b). --- src/shared/engine_core.h | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/shared/engine_core.h b/src/shared/engine_core.h index 8fb43a09d2..b8d9c1c201 100644 --- a/src/shared/engine_core.h +++ b/src/shared/engine_core.h @@ -7,6 +7,19 @@ #include "common.h" #include "engine_types.h" /* shared engine struct/union types (§14c struct follow-up) */ +/* ENGINE_SHB — the sign-extension barrier some shared bodies were matched with (§75b). + * A body's preamble may carry file-scope `#define`s as well as `extern`s, but extraction lifts + * only the externs, so a `#define` left behind in the source overlay makes the macro compile + * ONLY where that overlay's define happens to be in scope ABOVE the splice point. func_80165CA0 + * was capped at ×3 by exactly that: its `#define SHB` sits between its two externs and its + * instantiation, and the other 132 overlays define SHB only ~300 lines further down the file. + * Owning it here (under a distinct name, so the overlays' own SHB — which exists in BOTH a + * volatile and a non-volatile spelling — can never collide) makes the body self-contained. + * Volatile form: that is what the 3 banked members compile with today. */ +#ifndef ENGINE_SHB +#define ENGINE_SHB(x) __asm__ __volatile__("" : "=r"(x) : "0"(x)) +#endif + #define DEFINE_func_80128EA8() \ void func_80128EA8(s32 a0, s32 a1, s32 a2) { \ *(s32 *)(a1 + 0x0) = a2; /* sw a2, 0x0(a1) */ \ @@ -28061,19 +28074,19 @@ } while (i < 0x1e); \ i = 0; off = 0; \ do { \ - base = (s32)&D_8011D030; SHB(base); \ + base = (s32)&D_8011D030; ENGINE_SHB(base); \ a1 = off + base; \ p = *(short **)(a1 + 0x20); \ if (p != 0) { \ s32 q2; \ if ((u16)*p == 1) { \ - v = *(short *)(a1 + 6); p[4] = v; SHB(v); *(int *)(p + 0x24) = v; \ - v = *(short *)(a1 + 0xa); p[5] = v; SHB(v); *(int *)(p + 0x26) = v; \ - w = *(short *)(a1 + 0xe); p[6] = w; v = p[0x16] | 1; SHB(w); p[0x16] = v; *(int *)(p + 0x28) = w; \ + v = *(short *)(a1 + 6); p[4] = v; ENGINE_SHB(v); *(int *)(p + 0x24) = v; \ + v = *(short *)(a1 + 0xa); p[5] = v; ENGINE_SHB(v); *(int *)(p + 0x26) = v; \ + w = *(short *)(a1 + 0xe); p[6] = w; v = p[0x16] | 1; ENGINE_SHB(w); p[0x16] = v; *(int *)(p + 0x28) = w; \ } else if ((q2 = *(int *)(p + 0x1a)) != 0) { \ - v = *(short *)(a1 + 6); p[4] = v; SHB(v); *(int *)(q2 + 0x14) = v; \ - v = *(short *)(a1 + 0xa); p[5] = v; q2 = *(int *)(p + 0x1a); SHB(v); *(int *)(q2 + 0x18) = v; \ - v = *(short *)(a1 + 0xe); p[6] = v; q2 = *(int *)(p + 0x1a); SHB(v); *(int *)(q2 + 0x1c) = v; \ + v = *(short *)(a1 + 6); p[4] = v; ENGINE_SHB(v); *(int *)(q2 + 0x14) = v; \ + v = *(short *)(a1 + 0xa); p[5] = v; q2 = *(int *)(p + 0x1a); ENGINE_SHB(v); *(int *)(q2 + 0x18) = v; \ + v = *(short *)(a1 + 0xe); p[6] = v; q2 = *(int *)(p + 0x1a); ENGINE_SHB(v); *(int *)(q2 + 0x1c) = v; \ } else { \ p[4] = *(short *)(a1 + 6); p[5] = *(short *)(a1 + 0xa); p[6] = *(short *)(a1 + 0xe); \ } \