feat(phase-29): isolate-with-body FIX + 3 more preserved cracks banked (incl. a 673-ins giant)

THE FIX (harvest_verify._jtbl_prep_one): isolate WITH THE BODY STILL SPLICED.
jr_isolate_all accumulates each object's file-scope decls as the new region's
`ambient` set, so partitioning around an INCLUDE_ASM stub hands the region a
DIFFERENT decl context than the draft's body needs — and the gate then produced a
byte-DIFF rather than a compile error, which is why a batch of these read as
"9 compile / 0 bank" and looked like a codegen wall. §61b's law extends one step:
THE CARVE MUST FOLLOW THE SPLICE — AND SO MUST THE ISOLATION.

The un-splice existed only because the tool is stub-centric (a spliced fn is no
longer in corpus.stubs). New _unsplice_body() handles that properly: it finds the
file that NOW holds the body (isolation may have MOVED it into a fresh region file)
and writes back the stub line for THAT subseg, so the gate re-splices identical text.

BANKED via the corrected path (each whole-binary byte-gated, one per invocation):
  func_80135D20  (100 ins, reach 138)
  func_801749C8  (105 ins, reach 136)
  func_8019059C  (673 ins, reach 3 — a giant)
Together with func_80135888 and func_8018F694 earlier: 5 of the 11 preserved
t5wave cracks are now banked.

THE REMAINING 6, honestly classed: 2 genuine DIFF (func_80135260, func_80191C50),
2 CC1-FAIL (func_801365B8, func_80165CA0), 2 §57 self-decl plumbing
(func_801299C8 `prototype declaration`, func_8012AAAC own-name conflict).

⚠️ RETRACTION: the earlier "the ladder converts 0/10, which prices Task 14 stages
2-3" is WRONG and is withdrawn. Three of those ten bank through harvest_verify
alone with the SAME transformed drafts that gate_stage rejected — so that 0/10 was
measuring gate_stage's own interference, not the residuals. Prime suspect is the
arity pre-pass (fix_arity_callers --apply --any-proto edits engine_core.h before
the gate; the §19 regression mode). GATE_NO_ARITY=1 is the ready A/B. Task 14
stages 2-3 remain UNPRICED until that runs.

- R22 clean-fleet 140/140 BYTE-IDENTICAL; tree clean before and after
This commit is contained in:
Drew T
2026-07-22 11:18:43 -06:00
parent 1ded372164
commit 52e772628b
8 changed files with 4601 additions and 491 deletions
+1 -1
View File
@@ -3261,7 +3261,7 @@ ov_SC06_018_ELF := $(ov_SC06_018_OUT).elf
ov_SC06_018_MAPFILE := $(ov_SC06_018_OUT).map
ov_SC06_018_LD_SCRIPT := $(ov_SC06_018_OUT).ld
ov_SC06_018_SPLAT_YAML := config/splat.ov_SC06_018.yaml
ov_SC06_018_JTBL_INTERLEAVE := --order tail.data.o,ov_SC06_018_jr_8012ACE0.o,tail2.data.o,ov_SC06_018_jr_80135888.o,tail3.data.o,ov_SC06_018_jr_80135A4C.o,tail4.data.o,ov_SC06_018_jr_801380E0.o,tail5.data.o,ov_SC06_018_jr_8013F350.o,tail6.data.o,ov_SC06_018_jr_8013FFD8.o,tail7.data.o,ov_SC06_018_jr_80140608.o,tail8.data.o,ov_SC06_018_jr_8015444C.o,tail9.data.o,ov_SC06_018_jr_80154C24.o,ov_SC06_018_jr_801588CC.o,tail10.data.o,ov_SC06_018_jr_80159C84.o,tail11.data.o,ov_SC06_018_jr_8015A3C8.o,tail12.data.o,ov_SC06_018_jr_8015AE2C.o,tail13.data.o,ov_SC06_018_jr_8015C32C.o,tail14.data.o,ov_SC06_018_jr_8016AB6C.o,tail15.data.o,ov_SC06_018_jr_801734BC.o,tail16.data.o,ov_SC06_018_jr_80178D40.o,tail17.data.o,ov_SC06_018_jr_8017A4AC.o,tail18.data.o,ov_SC06_018_jr_8017AE2C.o,ov_SC06_018_jr_8017C24C.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
ov_SC06_018_JTBL_INTERLEAVE := --order tail.data.o,ov_SC06_018_jr_8012ACE0.o,tail2.data.o,ov_SC06_018_jr_80135888.o,tail3.data.o,ov_SC06_018_jr_80135A4C.o,tail4.data.o,ov_SC06_018_jr_80135D20.o,tail5.data.o,ov_SC06_018_jr_801380E0.o,tail6.data.o,ov_SC06_018_jr_8013F350.o,tail7.data.o,ov_SC06_018_jr_8013FFD8.o,tail8.data.o,ov_SC06_018_jr_80140608.o,tail9.data.o,ov_SC06_018_jr_8015444C.o,tail10.data.o,ov_SC06_018_jr_80154C24.o,ov_SC06_018_jr_801588CC.o,tail11.data.o,ov_SC06_018_jr_80159C84.o,tail12.data.o,ov_SC06_018_jr_8015A3C8.o,tail13.data.o,ov_SC06_018_jr_8015AE2C.o,tail14.data.o,ov_SC06_018_jr_8015C32C.o,tail15.data.o,ov_SC06_018_jr_8016AB6C.o,tail16.data.o,ov_SC06_018_jr_801734BC.o,tail17.data.o,ov_SC06_018_jr_80178D40.o,tail18.data.o,ov_SC06_018_jr_8017A4AC.o,tail19.data.o,ov_SC06_018_jr_8017AE2C.o,ov_SC06_018_jr_8017C24C.o,tail20.data.o,ov_SC06_018_jr_8019059C.o,tail21.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
build/src/ov_SC06_018/ov_SC06_018_jr_8012ACE0.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py)
build/src/ov_SC06_018/ov_SC06_018_jr_8013F350.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20
build/src/ov_SC06_018/ov_SC06_018_jr_80154C24.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x24
+21 -15
View File
@@ -97,6 +97,7 @@ segments:
- [0x2b88, c, ov_SC06_018_jr_8012ACE0]
- [0xd730, c, ov_SC06_018_jr_80135888]
- [0xd8f4, c, ov_SC06_018_jr_80135A4C]
- [0xdbc8, c, ov_SC06_018_jr_80135D20]
- [0xff88, c, ov_SC06_018_jr_801380E0]
- [0x171f8, c, ov_SC06_018_jr_8013F350]
- [0x17e80, c, ov_SC06_018_jr_8013FFD8]
@@ -116,6 +117,7 @@ segments:
- [0x52354, c, ov_SC06_018_jr_8017A4AC]
- [0x52cd4, c, ov_SC06_018_jr_8017AE2C]
- [0x540f4, c, ov_SC06_018_jr_8017C24C]
- [0x68444, c, ov_SC06_018_jr_8019059C]
- [0x6b430, data, tail]
- [0xaa810, .rodata, ov_SC06_018_jr_8012ACE0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xaa8f0, data, tail2]
@@ -123,38 +125,42 @@ segments:
- [0xaa91c, data, tail3]
- [0xaa920, .rodata, ov_SC06_018_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xaa934, data, tail4]
- [0xaa938, .rodata, ov_SC06_018_jr_80135D20] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xaa94c, data, tail5]
- [0xaa988, .rodata, ov_SC06_018_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xaa9ec, data, tail5]
- [0xaa9ec, data, tail6]
- [0xaaff8, .rodata, ov_SC06_018_jr_8013F350] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab02c, data, tail6]
- [0xab02c, data, tail7]
- [0xab030, .rodata, ov_SC06_018_jr_8013FFD8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab064, data, tail7]
- [0xab064, data, tail8]
- [0xab0a0, .rodata, ov_SC06_018_jr_80140608] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab0b4, data, tail8]
- [0xab0b4, data, tail9]
- [0xab0cc, .rodata, ov_SC06_018_jr_8015444C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab138, data, tail9]
- [0xab138, data, tail10]
- [0xab1a8, .rodata, ov_SC06_018_jr_80154C24] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab1ec, .rodata, ov_SC06_018_jr_801588CC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab234, data, tail10]
- [0xab234, data, tail11]
- [0xab294, .rodata, ov_SC06_018_jr_80159C84] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab2c8, data, tail11]
- [0xab2c8, data, tail12]
- [0xab2cc, .rodata, ov_SC06_018_jr_8015A3C8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab2e8, data, tail12]
- [0xab2e8, data, tail13]
- [0xab2ec, .rodata, ov_SC06_018_jr_8015AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab308, data, tail13]
- [0xab308, data, tail14]
- [0xab32c, .rodata, ov_SC06_018_jr_8015C32C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab348, data, tail14]
- [0xab348, data, tail15]
- [0xab360, .rodata, ov_SC06_018_jr_8016AB6C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab380, data, tail15]
- [0xab380, data, tail16]
- [0xab400, .rodata, ov_SC06_018_jr_801734BC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab414, data, tail16]
- [0xab414, data, tail17]
- [0xab5bc, .rodata, ov_SC06_018_jr_80178D40] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab734, data, tail17]
- [0xab734, data, tail18]
- [0xab7c4, .rodata, ov_SC06_018_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab850, data, tail18]
- [0xab850, data, tail19]
- [0xab854, .rodata, ov_SC06_018_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab868, .rodata, ov_SC06_018_jr_8017C24C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xab888, data, tail19]
- [0xab888, data, tail20]
- [0xab9f4, .rodata, ov_SC06_018_jr_8019059C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xaba1c, data, tail21]
- [0xADA44, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word)
- [0xADA47] # EOF marker = the 0.4.dec byte length
# @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes
-429
View File
@@ -794,432 +794,3 @@ out:
}
return 0;
}
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80135A4C", func_80135D20);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80135A4C", func_80135EB0);
s32 func_80136334(void *arg0, s32 arg1, s32 arg2) {
extern u8 D_801152A8[];
extern s16 D_801152AA;
extern s16 D_801152AC;
extern s16 D_80126722;
extern s16 D_80126724;
register s32 a1v __asm__("$11");
register s32 a2v __asm__("$12");
register s32 n __asm__("$5");
register s16 *b4 __asm__("$7");
s32 d;
s32 dx;
s32 denom;
s32 result;
s32 frame_pad[2];
(void)&frame_pad;
__asm__("" : "=r"(a1v) : "0"(arg1));
a2v = arg2;
if (!(arg1 & 1)) {
dx = (s16) arg2 - (*(s16 **)&D_80193B64)[2];
d = dx;
denom = -(*(s16 **)&D_80193B70)[2];
} else {
denom = (*(s16 **)&D_80193B70)[2];
d = (*(s16 **)&D_80193B64)[2] - (s16) arg2;
dx = -d;
}
n = -d;
{
register s16 *b8 __asm__("$6") = *(s16 **)&D_80193B70;
u16 *ac = *(u16 **)&D_80193B64;
b4 = D_80193B6C;
b4[0] = ac[0] + n * b8[0] / denom;
b4[1] = ac[1] + n * b8[1] / denom;
b4[2] = ac[2] + dx;
}
if (b4[0] < M2C_FIELD(arg0, s16 *, 4)) return 0;
if (M2C_FIELD(arg0, s16 *, 6) < b4[0]) return 0;
if (b4[1] < M2C_FIELD(arg0, s16 *, 8)) return 0;
if (M2C_FIELD(arg0, s16 *, 0xA) < b4[1]) return 0;
if (a1v & 0x8000) {
u16 *b0 = *(u16 **)&D_80193B68;
b4[0] = b0[0];
b4[1] = b0[1];
}
D_801152AA = 0;
(*(s16 *)D_801152A8) = 0;
if (a1v & 1) {
D_80193B6C[2] = a2v + 2;
__asm__ __volatile__("");
D_801152AC = 0xFFF;
} else {
D_801152AC = -0xFFF;
D_80193B6C[2] = a2v - 2;
}
__asm__ __volatile__("" :: "r"(a1v), "r"(a2v));
(*(s16 *)D_80126720) = (M2C_FIELD(arg0, s16 *, 4) + M2C_FIELD(arg0, s16 *, 6)) >> 1;
D_80126722 = (M2C_FIELD(arg0, s16 *, 8) + M2C_FIELD(arg0, s16 *, 0xA)) >> 1;
result = 1;
D_80126724 = (M2C_FIELD(arg0, s16 *, 0xC) + M2C_FIELD(arg0, s16 *, 0xE)) >> 1;
return result;
}
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80135A4C", func_801365B8);
// @class: pointer-type — pointer-vs-array reconcile for func_80136824 (ov_SC01_077_a)
// D_80193B64/B0/B8 are file-scope `extern u8`, D_80193B6C is `extern s32 []`; each HOLDS a
// pointer value that the target loads via lw then derefs. Read as pointer via *(T**)&sym.
// D_80193B6C must be a SCALAR pointer (not s32[]) — as an array it decays and gcc CSEs the
// base address into a held reg (lui;addiu;lw 0(reg)) across the 3 reloads; as a scalar
// pointer it folds %lo (lui;lw %lo). Retype all 3 file-TU occurrences (byte-neutral: the
// siblings read it once via *(u16**)&sym == direct lw either way).
s32 func_80136824(s32 arg0, s32 arg1, s32 arg2) {
extern u8 D_801152A8[];
extern s16 D_801152AA;
extern s16 D_801152AC;
extern s16 D_80126722;
extern s16 D_80126724;
register u16 *ac __asm__("$4");
register s16 *b8 __asm__("$6");
register s16 *b4 __asm__("$9");
register s32 r __asm__("$3");
register s32 pos __asm__("$12");
register s32 a1v __asm__("$5");
s16 temp_v0;
s16 temp_v1;
s32 var_a3;
s16 var_v0_3;
s32 temp_a1;
s32 var_t0;
s32 var_v1;
s16 *b4b;
u16 *p;
__asm__ ("" : "=r"(a1v) : "0"(arg1));
pos = arg2;
if (!(a1v & 1)) {
var_t0 = (s16) arg2 - (*(s16 **)&D_80193B64)[1];
var_v1 = var_t0;
var_a3 = -(*(s16 **)&D_80193B70)[1];
} else {
var_a3 = (*(s16 **)&D_80193B70)[1];
var_v1 = (*(s16 **)&D_80193B64)[1] - (s16) arg2;
var_t0 = -var_v1;
}
b8 = (*(s16 **)&D_80193B70);
ac = (*(u16 **)&D_80193B64);
b4 = D_80193B6C;
temp_a1 = -var_v1;
r = (temp_a1 * b8[0]) / var_a3;
b4[0] = ac[0] + r;
b4[1] = ac[1] + var_t0;
r = (temp_a1 * b8[2]) / var_a3;
temp_v0 = ac[2] + r;
b4[2] = temp_v0;
temp_v1 = b4[0];
if (temp_v1 < M2C_FIELD(((void *)arg0), s16 *, 4)) {
return 0;
}
if (M2C_FIELD(((void *)arg0), s16 *, 6) < temp_v1) {
return 0;
}
if (temp_v0 < M2C_FIELD(((void *)arg0), s16 *, 0xC)) {
return 0;
}
if (M2C_FIELD(((void *)arg0), s16 *, 0xE) < temp_v0) {
return 0;
}
if (arg1 & 0x8000) {
p = (*(u16 **)&D_80193B68);
b4[0] = (s16) p[0];
b4[2] = (s16) p[2];
}
D_801152AC = 0;
(*(s16 *)D_801152A8) = 0;
if (arg1 & 1) {
b4b = D_80193B6C;
D_801152AA = 0xFFF;
__asm__ __volatile__("");
var_v0_3 = pos + 2;
} else {
b4b = D_80193B6C;
D_801152AA = -0xFFF;
__asm__ __volatile__("");
var_v0_3 = pos - 2;
}
b4b[1] = var_v0_3;
__asm__ __volatile__("" :: "r"(pos));
(*(s16 *)D_80126720) = (s16) ((s32) (M2C_FIELD(((void *)arg0), s16 *, 4) + M2C_FIELD(((void *)arg0), s16 *, 6)) >> 1);
D_80126722 = (s16) ((s32) (M2C_FIELD(((void *)arg0), s16 *, 8) + M2C_FIELD(((void *)arg0), s16 *, 0xA)) >> 1);
D_80126724 = (s16) ((s32) (M2C_FIELD(((void *)arg0), s16 *, 0xC) + M2C_FIELD(((void *)arg0), s16 *, 0xE)) >> 1);
return 1;
}
// @class: schedule
// @stuck: none — MATCH (76 ins, relocation-masked). Key lever: the D_80126720/22/24 tail is a
// global-short RMW `+=`. Writing it via a cast `*(u16*)&SYM = *(u16*)&SYM + x` makes gcc CSE
// the address into a base reg (base-reuse) for ALL three — but the target only base-reuses
// D_80126720 (a SCHEDULER artifact: its addr-lui fills the load-delay slot after the pb4[4]
// load, and since $v0 is live it lands in $a0, reused for load+store). D_80126722/24 use the
// plain inline 2-lui form. Fix = DIRECT scalar RMW `SYM = SYM + x` (no &/cast) → inline %hi/%lo;
// the scheduler alone forces base-reuse on #1. Also: `s16 D_80126724 = D_80126724 + int` emits
// LHU (gcc-2.7.2 drops the sign-extend because the sum is truncated to 16b on the sh) — so the
// canonical s16 decl is byte-safe here (no u16 retype needed, keeps the sign-sensitive callers).
extern s16 *D_80193B6C; /* holds a pointer value (*(u16**)&D_80193B6C) */
s32 func_80136A94(s32 a0, s32 a1, s32 a2, s32 a3) {
extern void ApplyMatrixSV(void *m, void *v0, void *v1);
extern void ApplyRotMatrix(void *v0, void *v1);
extern u16 D_80126722;
extern s16 D_80126724;
extern s16 D_801152AA;
extern s16 D_801152AC;
s32 out[4];
u16 *pb4;
if (a0) {
ApplyMatrixSV((void *)a3, *(void **)&D_80193B6C, *(void **)&D_80193B6C);
ApplyMatrixSV((void *)a3, (void *)D_80126720, (void *)D_80126720);
ApplyRotMatrix((void *)D_801152A8, (void *)out);
*(s16 *)D_801152A8 = out[0];
D_801152AA = out[1];
D_801152AC = out[2];
}
pb4 = *(u16 **)&D_80193B6C;
*(s16 *)(a2) = pb4[0] + *(s32 *)(a1 + 0x48);
*(s16 *)(a2 + 2) = pb4[1] + *(s32 *)(a1 + 0x4C);
*(s16 *)(a2 + 4) = pb4[2] + *(s32 *)(a1 + 0x50);
*(u16 *)D_80126720 = *(u16 *)D_80126720 + *(s32 *)(a1 + 0x48);
D_80126722 = D_80126722 + *(s32 *)(a1 + 0x4C);
D_80126724 = D_80126724 + *(s32 *)(a1 + 0x50);
}
DEFINE_func_80136BC4() /* dedup: shared engine-core @0x80136BC4 (src/shared) */
DEFINE_func_80136C1C() /* dedup: shared engine-core @0x80136C1C (src/shared) */
DEFINE_func_80136C3C() /* dedup: shared engine-core @0x80136C3C (src/shared) */
DEFINE_func_80136C44() /* dedup: shared engine-core @0x80136C44 (src/shared) */
DEFINE_func_80136C4C() /* dedup: shared engine-core @0x80136C4C (src/shared) */
extern unsigned short D_800B99F0;
extern void (*D_80193B80[])(void);
void func_80136C54(void)
{
D_80193B80[D_800B99F0]();
}
// @class: struct
// @stuck: none — MATCH (28 ins). 10-byte 1-aligned struct copy (S10_80136C90{char s[10]}) from global D_801D2AD4 into a stack buffer, then func_8001534C(0,&buf,0x78,0x10,0,0). gcc emits the block move as 2 unaligned words (lwl/lwr+swl/swr) + 2 bytes (lb/sb).
typedef struct { char s[10]; } S10_80136C90;
s32 func_80136C90()
{
extern void func_8001534C(int, void *, int, int, int, int);
extern S10_80136C90 D_801D2AD4;
S10_80136C90 buf = D_801D2AD4;
func_8001534C(0, &buf, 0x78, 0x10, 0, 0);
}
DEFINE_func_80136D00() /* dedup: shared engine-core @0x80136D00 (src/shared) */
DEFINE_func_80136D08() /* dedup: shared engine-core @0x80136D08 (src/shared) */
DEFINE_func_80136DFC() /* dedup: shared engine-core @0x80136DFC (src/shared) */
DEFINE_func_80136EC4() /* dedup: shared engine-core @0x80136EC4 (src/shared) */
DEFINE_func_80136ECC() /* dedup: shared engine-core @0x80136ECC (src/shared) */
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80135A4C", func_80136F3C);
DEFINE_func_80137030() /* dedup: shared engine-core @0x80137030 (src/shared) */
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80135A4C", func_80137178);
DEFINE_func_801372B0() /* dedup: shared engine-core @0x801372B0 (src/shared) */
DEFINE_func_801375EC() /* dedup: shared engine-core @0x801375EC (src/shared) */
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80135A4C", func_80137614);
DEFINE_func_8013767C() /* dedup: shared engine-core @0x8013767C (src/shared) */
DEFINE_func_801376C8() /* dedup: shared engine-core @0x801376C8 (src/shared) */
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80135A4C", func_801376E8);
DEFINE_func_801377B4() /* dedup: shared engine-core @0x801377B4 (src/shared) */
DEFINE_func_80137840() /* dedup: shared engine-core @0x80137840 (src/shared) */
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_80135A4C", func_801378F0);
DEFINE_func_801379D8() /* dedup: shared engine-core @0x801379D8 (src/shared) */
DEFINE_func_801379EC() /* dedup: shared engine-core @0x801379EC (src/shared) */
// @class: regalloc-order (walker-family, §52/§52a) — PIN-FREE
// Role-swap ($s0<->$s2 between loop1 and loops2/3) is driven by DENSITY (K2), not pins:
// - loop1 pointer has an extra ref (p != D_80127524 compare) -> wins $s0; index -> $s2
// - loop2/3 index has >= pointer refs -> wins $s0; pointer -> $s2
// Separate per-loop pointer/index vars => separate pseudos => can take different regs.
extern void func_80138BE0(s32 a0);
extern void func_80137BD8(s32 a0);
extern void func_8013A380(void);
void func_801379FC(void) {
extern s32 D_80127524;
extern s32 D_80127548[];
extern s32 D_801269F0;
extern s16 D_801269F4;
extern s32 D_801269F8;
s32 i;
(*(s32 *)D_80127548) = 0x24;
if ((D_80127524 != 0) && (*(s32 *)D_80127524 != 0)) {
s32 p;
s32 idx;
func_80138BE0(D_80127524);
i = 0;
p = (s32)&D_801269F0;
idx = 0;
do {
if ((p != D_80127524) && (*(s32 *)((s32)&D_801269F0 + idx) != 0)) {
func_80138BE0(p);
}
p = p + 0x4c;
i = i + 1;
idx = idx + 0x4c;
} while (i < 3);
} else {
s32 p;
s32 idx;
i = 0;
p = (s32)&D_801269F0;
idx = 0;
do {
if (*(s32 *)((s32)&D_801269F0 + idx) != 0) {
func_80138BE0(p);
}
p = p + 0x4c;
i = i + 1;
idx = idx + 0x4c;
} while (i < 3);
}
{
s32 p;
s32 idx;
s32 flags;
i = 0;
p = (s32)&D_801269F0;
idx = 0;
do {
if (*(s16 *)((s32)&D_801269F4 + idx) != 0) {
if (*(s32 *)((s32)&D_801269F0 + idx) != 0) {
flags = *(s32 *)((s32)&D_801269F8 + idx);
if ((flags & 0x1000) != 0) {
if ((flags & 0x2000) == 0) {
func_80137BD8(p);
}
}
}
}
p = p + 0x4c;
i = i + 1;
idx = idx + 0x4c;
} while (i < 3);
}
func_8013A380();
}
// @class: remat
// @stuck: target CSEs &D_801269F0 once for load+call arg; force via local pointer
extern s32 D_80127548[];
extern int D_80193BD4;
extern int D_801269F0;
extern void func_80138BE0(int p);
void func_80137B80(void) {
int *p = &D_801269F0;
(*(int *)&D_80127548) = 0x24;
if (*p != 0) {
((void (*)(int *))func_80138BE0)(p);
}
D_80193BD4 += 1;
}
DEFINE_func_80137BD8() /* dedup: shared engine-core @0x80137BD8 (src/shared) */
// @class: plumbing
// @stuck: none — MATCH (51 ins). Three globals stored/loaded around 3 calls; &D_801269F0 held in $s1, arg1 in $s0 across calls; return reloads global D_800A5E60.
extern unsigned char D_80126A0E;
extern short D_80126A0A;
extern s16 D_801269F4;
extern int D_800A5E60;
extern int D_80193BD4;
extern int D_801269F0;
extern void func_801392FC();
extern void func_80137DD4(s32 a0, u8 *a1, u8 *a2);
extern void func_80139680(s32 a0, u8 *a1);
int func_80137D08(int arg0, int arg1, short arg2)
{
unsigned char buf[3];
D_800A5E60 = arg0;
D_80126A0A = arg2;
((void (*)(void *, int, int))func_801392FC)(&D_801269F0, D_80126A0E, arg1);
if ((*(short *)&D_801269F4) == 7) {
buf[0] = 0x39;
buf[1] = 0xFF;
buf[2] = 0x71;
((void (*)(void *, void *, int))func_80137DD4)(&D_801269F0, buf, arg1);
} else if ((*(short *)&D_801269F4) == 3) {
if (D_80193BD4 & 4) {
((void (*)(void *, int))func_80139680)(&D_801269F0, arg1);
}
}
return D_800A5E60;
}
DEFINE_func_80137DD4() /* dedup: shared engine-core @0x80137DD4 (src/shared) */
DEFINE_func_80137FD8() /* dedup: shared engine-core @0x80137FD8 (src/shared) */
File diff suppressed because it is too large Load Diff
+73 -1
View File
@@ -2713,7 +2713,79 @@ s32 func_8017496C(void *a0) {
DEFINE_func_801749A8() /* dedup: shared engine-core @0x801749A8 (src/shared) */
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_801734BC", func_801749C8);
// @class: schedule
// @stuck: none — MATCH (105 ins)
//
// func_801749C8 — per-frame actor pose/transform update (ov_SC06_018 jr_801734BC family).
// Levers used (all byte-proven here):
// * register pins (§17): cx=$s2/$18 (D_80126B5E), cz=$s1/$17 (sign-extended D_80126B66);
// both are the only values live across the func_80049CAC call (D_80126B62 is RELOADED,
// so it must be read inline, never hoisted into a local).
// * lhu+sll+sra (NOT lh): `(s16)D_80126B66` is folded by combine into a single `lh`.
// An intervening STORE between the u16 load and the sign-extension blocks that fold
// (same mechanism as cookbook §49) — hence `czr = D_80126B66;` ... store ... `cz = (czr<<16)>>16;`
// with czr a SEPARATE temp (reusing one var costs 5 more mismatches).
// * LUID dial (§49/§50-A): materializing `t28 = *(s16*)(param_1+0x28)` BEFORE `cx = ...`
// moves the 0x28 load ahead of the D_80126B5E lui/lh in the expand stream — the last 3.
// * frame: MATRIX at sp+0x10 (t[] at sp+0x24), SVECTOR in at sp+0x30, SVECTOR out at sp+0x38;
// locals are laid out in DECLARATION order.
// * canonical sigs kept (func_8012F14C is `void(s32)` in the TU) -> cast at the call site.
typedef struct { s16 vx, vy, vz, pad; } SV4_801749C8;
typedef struct { s16 m[3][3]; s16 pad; s32 t[3]; } MTX_801749C8;
extern s32 func_80012C6C(s32 a0, s32 a1, s32 a2);
extern s16 func_80012ABC(s32 a0, s32 a1, s32 a2);
extern void func_80049CAC(s32 a0, s32 a1);
extern void func_8012F14C(s32);
extern u16 D_80126B5E;
extern u16 D_80126B62;
extern u16 D_80126B66;
s32 func_801749C8(s32 param_1)
{
MTX_801749C8 mtx; /* sp+0x10 */
SV4_801749C8 in; /* sp+0x30 */
SV4_801749C8 out; /* sp+0x38 */
register s32 cx __asm__("$18");
register s32 cz __asm__("$17");
s32 czr;
s32 t28;
*(s32 *)(param_1 + 0x08) = (s16)func_80012C6C(*(s16 *)(param_1 + 0x08), *(s16 *)(param_1 + 0x0C), 4);
*(s32 *)(param_1 + 0x10) = (s16)func_80012C6C(*(s16 *)(param_1 + 0x10), *(s16 *)(param_1 + 0x14), 4);
*(s16 *)(param_1 + 0x18) = func_80012ABC(*(s16 *)(param_1 + 0x18), *(s16 *)(param_1 + 0x20), 4);
*(s16 *)(param_1 + 0x1A) = func_80012ABC(*(s16 *)(param_1 + 0x1A), *(s16 *)(param_1 + 0x22), 4);
*(s16 *)(param_1 + 0x1C) = func_80012ABC(*(s16 *)(param_1 + 0x1C), *(s16 *)(param_1 + 0x24), 4);
*(s16 *)(param_1 + 0x28) = func_80012C6C(*(s16 *)(param_1 + 0x28), *(s16 *)(param_1 + 0x2E), 0x10);
*(s16 *)(param_1 + 0x2A) = func_80012C6C(*(s16 *)(param_1 + 0x2A), *(s16 *)(param_1 + 0x30), 0x10);
*(s16 *)(param_1 + 0x2C) = func_80012C6C(*(s16 *)(param_1 + 0x2C), *(s16 *)(param_1 + 0x32), 0x10);
t28 = *(s16 *)(param_1 + 0x28);
cx = (s16)D_80126B5E;
czr = D_80126B66;
*(s32 *)(param_1 + 0x48) = t28 + cx;
cz = (czr << 16) >> 16;
*(s32 *)(param_1 + 0x4C) = *(s16 *)(param_1 + 0x2A) + (s16)D_80126B62;
*(s32 *)(param_1 + 0x50) = *(s16 *)(param_1 + 0x2C) + cz;
func_80049CAC(param_1 + 0x18, (s32)&mtx);
mtx.t[0] = *(s16 *)(param_1 + 0x28) + cx;
mtx.t[1] = *(s16 *)(param_1 + 0x2A) + (s16)D_80126B62;
mtx.t[2] = *(s16 *)(param_1 + 0x2C) + cz;
in.vx = 0;
in.vy = 0;
in.vz = *(s32 *)(param_1 + 0x10);
((void (*)(s32, s32, s32))func_8012F14C)((s32)&mtx, (s32)&in, (s32)&out);
*(s32 *)(param_1 + 0x3C) = out.vx;
*(s32 *)(param_1 + 0x40) = out.vy;
*(s32 *)(param_1 + 0x44) = out.vz;
}
DEFINE_func_80174B6C() /* dedup: shared engine-core @0x80174B6C (src/shared) */
-35
View File
@@ -4473,38 +4473,3 @@ void func_8018F694(void)
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_8018FE0C);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_8018FF98);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_8019059C);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80191020);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80191320);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80191A78);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80191C50);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80192768);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80192B60);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80192F64);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_801932EC);
void func_8019334C(void) {
}
void func_80193354(void) {
}
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_8019335C);
INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80193458);
void func_80193580(void) {
}
File diff suppressed because it is too large Load Diff
+38 -10
View File
@@ -276,6 +276,30 @@ def _jtbl_restore(snap):
_reload_corpus()
def _unsplice_body(fn, st, orig_txt):
"""Restore fn's INCLUDE_ASM stub after a prep that left the body spliced.
The isolation may have MOVED the body into a freshly-created region file, so the stub cannot
simply be written back to the path it came from — that would also undo the partition. Locate
the file that actually holds the body now and put back the stub line for THAT subseg (the
`asm/<bin>/nonmatchings/<subseg>` convention, subseg == the region file's basename). If nothing
moved, this restores the original file verbatim."""
body = drafts[fn]['c']
for cf in sorted(glob.glob(os.path.join(REPO, 'src/%s/*.c' % a.binary))):
t = open(cf).read()
if body in t:
sub = os.path.basename(cf)[:-2]
stub = 'INCLUDE_ASM("asm/%s/nonmatchings/%s", %s);' % (a.binary, sub, fn)
open(cf, 'w').write(t.replace(body, stub, 1))
return True
# body not found: nothing was spliced anywhere (carve failed before the splice landed) —
# restore the original text so the caller's snapshot logic sees an untouched tree.
if st is not None and orig_txt is not None:
open(st.path, 'w').write(orig_txt)
return True
return False
def _jtbl_prep_one(fn):
"""Prep ONE table-bearing draft's carve. Returns (ok, snapshot)."""
if not _fn_has_jtbl(fn):
@@ -294,21 +318,25 @@ def _jtbl_prep_one(fn):
r = _sh([PY, 'tools/jtbl_carve.py', a.binary, '--func', fn])
out = (r.stdout or '') + (r.stderr or '')
if r.returncode and any(w in out for w in _ISO_WALLS):
open(st.path, 'w').write(txt) # un-splice before isolating
# ISOLATE WITH THE BODY STILL SPLICED (byte-proven 2026-07-22, func_80135888).
# This used to un-splice first. `jr_isolate_all` accumulates each object's file-scope
# decls as the new region's `ambient` set, so partitioning around an INCLUDE_ASM stub
# gives the region a DIFFERENT decl context than the one the draft's body needs — and
# the gate then produced a byte-DIFF rather than a compile error, which is exactly why
# a batch of these read as "9/10 compile, 0 bank" and looked like a codegen wall.
# §61b's law (THE CARVE MUST FOLLOW THE SPLICE) extends one step: SO MUST THE
# ISOLATION. The un-splice was there only because the tool is stub-centric and a
# spliced function is no longer in corpus.stubs — a plumbing problem, handled below.
if _sh([PY, 'tools/jr_isolate_all.py', a.binary, '--only', fn]).returncode:
print(' [jtbl] isolate FAILED %s' % fn); continue
if _sh(['make', '--no-print-directory', 'extract', 'BINARY=%s' % a.binary]).returncode:
print(' [jtbl] extract-after-isolate FAILED %s' % fn); continue
_reload_corpus()
st = _stubs.get(fn)
if st is None:
print(' [jtbl] stub vanished after isolate %s' % fn); continue
line, txt = _stub_line(fn), open(st.path).read()
if line not in txt:
print(' [jtbl] no stub after isolate %s' % fn); continue
open(st.path, 'w').write(txt.replace(line, drafts[fn]['c'], 1))
r = _sh([PY, 'tools/jtbl_carve.py', a.binary, '--func', fn])
open(st.path, 'w').write(txt) # ALWAYS un-splice
# ALWAYS un-splice — but the isolation may have MOVED the body to a new region file, so
# find where it actually is now and restore the stub line for THAT subseg. The gate then
# re-splices identical text, so the build it verifies is the one proven above.
if not _unsplice_body(fn, st, txt):
print(' [jtbl] could not un-splice %s (body not found)' % fn); continue
if r.returncode:
last = ((r.stdout or '') + (r.stderr or '')).strip().splitlines()[-1:] or ['']
print(' [jtbl] carve FAILED %s: %s' % (fn, last[0][:120])); continue