feat(phase-30 S47-W1): reach-15 crack wave — 10 exemplars banked, 191 member-slots unlocked

First wave of the reach-ordered campaign: the 15 highest-reach zero-crack sibling families.
15 agents (size-routed Haiku<=30 / Sonnet 30-120 / Opus>=120), every MATCH claim re-verified by an
independent skeptic that re-ran match_one itself. 22 of 25 agents completed; 3 were rate-limited by
the API and never attempted their targets.

BANKED 10 exemplars (reach in parens), all gate-verified, R22 213 passed / 0 failed of 213:
  func_801EDC80 (28) func_801ED99C (28) func_801EDDAC (28)  md_SC05_023
  func_801EDED4 (24)  md_SC05_023        func_800CB8B4 (24)  md_MAIN_036
  func_801E8254 (14) func_801E7C04 (13)  md_SC04_025
  func_80181070 (12)  ov_SC03_024        func_8017E384 (10)  ov_SC01_005
  func_80185D70 (10, jr) ov_SC04_018 — gate auto-carved it into its own subseg (§53 machinery)

NEAR, not banked: func_801EDC18 (reach 57 — the single largest multiplier on the board) at
closeness 6, and func_8017C294 (reach 16) at closeness 2. Both are grinder/permuter candidates
rather than redraft work.
NOT ATTEMPTED (rate-limited): func_801EFBF4 (12), func_801EFDC8 (12), func_8018CC40 (10) — a clean
retry, since they never ran.

COUNTING (§55b, and the second time today this trap fired): git diff showed 12 INCLUDE_ASM removals
but only 10 are banks. func_80186460 and func_8018651C were RELOCATED into the untracked carve file
ov_SC04_018_jr_80185D70.c, not banked — verified by grepping the new file, where both still carry
INCLUDE_ASM. Any count taken across a carve must come from the stub oracle, never from git diff.

TREE SAFETY: zero agent writes to src/ or config/, despite 5 agents running while the safety
classifier was unavailable. The "drafts live in .run/ only" rule held under exactly the conditions
where it mattered.

gate_stage's --verified-out came back populated for all 6 binaries — this morning's truncation fix
(S47-C) confirmed on live traffic, not just controls.

Idioms harvested for the cookbook: the ASYMMETRIC INDEX RELOAD (a just-stored narrow field read
twice emits reuse-then-reload; the C is deliberately asymmetric — local for use #1, memory re-read
for #2), a stack-layout scheduling rule now byte-proven on a SECOND independent function
(func_8017D364 + func_801EDED4, promoting it from coincidence to rule), and a process finding:
sibling-search keyed on the CALLEE SET should be step 0 of every wave prompt — one grep turned a
126-instruction crack into a copy-edit.
This commit is contained in:
Drew T
2026-08-11 11:33:42 -06:00
parent f212ebcc28
commit 49f50ec7d2
9 changed files with 3677 additions and 382 deletions
+1 -1
View File
@@ -416,7 +416,7 @@ ov_SC04_018_ELF := $(ov_SC04_018_OUT).elf
ov_SC04_018_MAPFILE := $(ov_SC04_018_OUT).map
ov_SC04_018_LD_SCRIPT := $(ov_SC04_018_OUT).ld
ov_SC04_018_SPLAT_YAML := config/splat.ov_SC04_018.yaml
ov_SC04_018_JTBL_INTERLEAVE := --order tail.data.o,ov_SC04_018.o,ov_SC04_018_jr_8012ACE0.o,tail2.data.o,ov_SC04_018_jr_80135888.o,tail3.data.o,ov_SC04_018_jr_80135A4C.o,tail4.data.o,ov_SC04_018_jr_80135D20.o,tail5.data.o,ov_SC04_018_jr_801380E0.o,ov_SC04_018_o0c.o,tail6.data.o,ov_SC04_018_jr_8013F350.o,tail7.data.o,ov_SC04_018_jr_8013FFD8.o,tail8.data.o,ov_SC04_018_jr_80140608.o,tail9.data.o,ov_SC04_018_jr_8015444C.o,ov_SC04_018_jr_80154C24.o,ov_SC04_018_jr_801588CC.o,ov_SC04_018_jr_80159C84.o,tail10.data.o,ov_SC04_018_jr_8015A3C8.o,tail11.data.o,ov_SC04_018_jr_8015AE2C.o,tail12.data.o,ov_SC04_018_jr_8015C32C.o,tail13.data.o,ov_SC04_018_jr_8016AB6C.o,tail14.data.o,ov_SC04_018_jr_80171B4C.o,ov_SC04_018_jr_801734BC.o,tail15.data.o,ov_SC04_018_jr_801789AC.o,ov_SC04_018_jr_80178D40.o,tail16.data.o,ov_SC04_018_jr_8017A4AC.o,tail17.data.o,ov_SC04_018_jr_8017AE2C.o,tail18.data.o,ov_SC04_018_jr_80186570.o,tail19.data.o,ov_SC04_018_jr_801878E8.o,tail20.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
ov_SC04_018_JTBL_INTERLEAVE := --order tail.data.o,ov_SC04_018.o,ov_SC04_018_jr_8012ACE0.o,tail2.data.o,ov_SC04_018_jr_80135888.o,tail3.data.o,ov_SC04_018_jr_80135A4C.o,tail4.data.o,ov_SC04_018_jr_80135D20.o,tail5.data.o,ov_SC04_018_jr_801380E0.o,ov_SC04_018_o0c.o,tail6.data.o,ov_SC04_018_jr_8013F350.o,tail7.data.o,ov_SC04_018_jr_8013FFD8.o,tail8.data.o,ov_SC04_018_jr_80140608.o,tail9.data.o,ov_SC04_018_jr_8015444C.o,ov_SC04_018_jr_80154C24.o,ov_SC04_018_jr_801588CC.o,ov_SC04_018_jr_80159C84.o,tail10.data.o,ov_SC04_018_jr_8015A3C8.o,tail11.data.o,ov_SC04_018_jr_8015AE2C.o,tail12.data.o,ov_SC04_018_jr_8015C32C.o,tail13.data.o,ov_SC04_018_jr_8016AB6C.o,tail14.data.o,ov_SC04_018_jr_80171B4C.o,ov_SC04_018_jr_801734BC.o,tail15.data.o,ov_SC04_018_jr_801789AC.o,ov_SC04_018_jr_80178D40.o,tail16.data.o,ov_SC04_018_jr_8017A4AC.o,tail17.data.o,ov_SC04_018_jr_8017AE2C.o,tail18.data.o,ov_SC04_018_jr_80185D70.o,tail19.data.o,ov_SC04_018_jr_80186570.o,tail20.data.o,ov_SC04_018_jr_801878E8.o,tail21.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
build/src/ov_SC04_018/ov_SC04_018.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14
build/src/ov_SC04_018/ov_SC04_018_jr_8012ACE0.o: JTBL_PADS := 0,0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0xcc,+0xe0
build/src/ov_SC04_018/ov_SC04_018_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18
+5 -2
View File
@@ -120,6 +120,7 @@ segments:
- [0x50be8, c, ov_SC04_018_jr_80178D40]
- [0x52354, c, ov_SC04_018_jr_8017A4AC]
- [0x52cd4, c, ov_SC04_018_jr_8017AE2C]
- [0x5dc18, c, ov_SC04_018_jr_80185D70]
- [0x5e418, c, ov_SC04_018_jr_80186570]
- [0x5f790, c, ov_SC04_018_jr_801878E8]
- [0x64dd0, data, tail]
@@ -164,10 +165,12 @@ segments:
- [0xbd404, data, tail17]
- [0xbd408, .rodata, ov_SC04_018_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xbd43c, data, tail18]
- [0xbd4a8, .rodata, ov_SC04_018_jr_80185D70] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xbd4c4, data, tail19]
- [0xbd764, .rodata, ov_SC04_018_jr_80186570] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xbd778, data, tail19]
- [0xbd778, data, tail20]
- [0xbd7ec, .rodata, ov_SC04_018_jr_801878E8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xbd824, data, tail20]
- [0xbd824, data, tail21]
- [0xBF9CC, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word)
- [0xBF9CF] # 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
+13 -1
View File
@@ -55,7 +55,19 @@ INCLUDE_ASM("asm/md_MAIN_036/nonmatchings/md_MAIN_036", func_800CB774);
INCLUDE_ASM("asm/md_MAIN_036/nonmatchings/md_MAIN_036", func_800CB794);
INCLUDE_ASM("asm/md_MAIN_036/nonmatchings/md_MAIN_036", func_800CB8B4);
extern u8 D_80078EC1;
extern void (*D_800CC01C[])(void);
extern void func_80146C3C(void);
void func_800CB8B4(void *arg0) {
if (D_80078EC1 == 0x17) {
u16 v0 = *(u16 *)((u8 *)arg0 + 2);
D_800CC01C[v0]();
} else {
func_80146C3C();
}
}
INCLUDE_ASM("asm/md_MAIN_036/nonmatchings/md_MAIN_036", func_800CB910);
+31 -2
View File
@@ -22,7 +22,27 @@ s32 func_801E7BB8(s32 param_1) {
}
INCLUDE_ASM("asm/md_SC04_025/nonmatchings/md_SC04_025", func_801E7C04);
extern s32 func_800D1E28(void);
extern s32 func_8002D4C8(s32, s32);
extern s32 func_8001BFD0(void);
extern s32 func_800291B4(s32);
extern s32 func_80029524(void);
extern s32 func_800D0C48(s32);
s32 func_801E7C04(s32 param_1) {
if ((*(s32 *)(param_1 + 0x28) = *(s32 *)(param_1 + 0x28) - 1) == -1) {
func_800D1E28();
func_8002D4C8(0x1C, 0);
func_8001BFD0();
if ((func_800291B4(0xCE) & 0xFF) == 0 && func_80029524() == 0) {
func_8002D4C8(0x1D, 0);
func_800D0C48(1);
}
*(u8 *)(param_1 + 0x15) = *(u8 *)(param_1 + 0x15) + 1;
}
return 0;
}
INCLUDE_ASM("asm/md_SC04_025/nonmatchings/md_SC04_025", func_801E7CA4);
@@ -95,7 +115,16 @@ INCLUDE_ASM("asm/md_SC04_025/nonmatchings/md_SC04_025", func_801E8034);
INCLUDE_ASM("asm/md_SC04_025/nonmatchings/md_SC04_025", func_801E805C);
INCLUDE_ASM("asm/md_SC04_025/nonmatchings/md_SC04_025", func_801E8254);
u8 func_801E8254(u32 a0) {
if ((u32)(a0 - 0x384) < 0x6E) {
return 0x65;
}
if ((u32)(a0 - 0x64) < 0x1E) {
return 0x28;
}
return 0xE;
}
+124 -4
View File
@@ -1,6 +1,19 @@
#include "common.h"
INCLUDE_ASM("asm/md_SC05_023/nonmatchings/md_SC05_023", func_801ED99C);
extern u8 D_801EE444[];
extern u8 *D_80126B10;
void func_800167B8(int);
void func_80175414(void);
int func_801ED99C(u8 *arg) {
D_80126B10 = D_801EE444;
func_800167B8(0);
func_80175414();
arg[0x15]++;
return 0;
}
extern s32 func_800167F0(s32 a0);
@@ -59,7 +72,20 @@ INCLUDE_RODATA("asm/md_SC05_023/nonmatchings/md_SC05_023", D_801ED988);
INCLUDE_ASM("asm/md_SC05_023/nonmatchings/md_SC05_023", func_801EDC18);
INCLUDE_ASM("asm/md_SC05_023/nonmatchings/md_SC05_023", func_801EDC80);
extern s32 func_80014C54(s32, s32, s32);
extern void func_800D1724(void *);
extern void func_80171A1C(void *);
extern u8 D_801EE444[];
void func_801EDC80(void *arg0) {
s32 result;
result = func_80014C54(0, 0, 0x80);
if ((result << 16) != 0) {
func_800D1724(&(*(int *)D_801EE444));
func_80171A1C(arg0);
}
}
void func_801EDCD8(void) {
}
@@ -80,7 +106,45 @@ INCLUDE_ASM("asm/md_SC05_023/nonmatchings/md_SC05_023", func_801EDD3C);
void func_801EDDA4(void) {
}
INCLUDE_ASM("asm/md_SC05_023/nonmatchings/md_SC05_023", func_801EDDAC);
#include "common.h"
extern void func_8012A018(s32 a0, s32 a1);
extern void func_8012A094(s32 a0);
extern void func_801EDE70(void *a0);
void func_801EDDAC(void) {
extern s32 D_80126950;
extern s32 D_80126954;
extern s32 D_8012695C;
extern s16 D_80126968;
extern s16 D_8012696A;
extern s16 D_8012696C;
extern s16 D_80126976;
extern s16 D_80126978;
extern s16 D_8012697A;
extern u8 D_80126948[];
extern s16 D_801274E8;
extern s16 D_801274EA;
extern s16 D_801274EC;
D_80126954 = 0x190;
D_80126950 = 0x190;
D_8012695C = 0x82;
D_80126968 = 0xFB1;
D_8012696A = 0x7C7;
D_8012696C = 0;
D_80126976 = 0;
D_80126978 = -0x36;
D_8012697A = 0;
func_8012A018((s32)func_801EDE70, 0);
func_801EDE70(D_80126948);
func_8012A094((s32)D_80126948);
D_801274EA = -0x82;
D_801274E8 = 0;
D_801274EC = -0x1B0;
}
@@ -93,7 +157,63 @@ void func_801EDE70(void *a0) {
INCLUDE_ASM("asm/md_SC05_023/nonmatchings/md_SC05_023", func_801EDEAC);
INCLUDE_ASM("asm/md_SC05_023/nonmatchings/md_SC05_023", func_801EDED4);
#include "common.h"
/* MATRIX 0x20: short m[3][3] @0x00 (18B) + 2B pad, long t[3] @0x14 (PsyQ layout) */
typedef struct { short m[3][3]; long t[3]; } MATRIX_801EDED4;
typedef struct { short vx, vy, vz, pad; } SVECTOR_801EDED4;
extern u16 func_80148800(s32 *a0);
extern s32 func_80012C6C(s32 a0, s32 a1, s32 a2);
extern s32 func_80012ABC(s32 a0, s32 a1, s32 a2);
extern void func_80049CAC(s32 a0, s32 a1);
extern void func_8012F14C(s32 a0, s32 a1, s32 a2);
void func_801EDED4(s32 param_1, s16 *param_2) {
extern s32 D_80126B58;
extern s16 D_801EE494[];
extern u16 D_801EE498[];
MATRIX_801EDED4 m1;
SVECTOR_801EDED4 svec_in;
SVECTOR_801EDED4 svec_out;
u8 t;
if (func_80148800(&D_80126B58) & 3) {
t = (*(u8 *)(param_1 + 5) + 1) & 1;
*(u8 *)(param_1 + 5) = t;
*(s32 *)(param_1 + 0xC) = D_801EE494[t];
*(s16 *)(param_1 + 0x2E) = D_801EE498[*(u8 *)(param_1 + 5)];
}
*(s32 *)(param_1 + 0x8) = (s16)func_80012C6C((s32)*(s16 *)(param_1 + 0x8), (s32)*(s16 *)(param_1 + 0xC), 0xA);
*(s32 *)(param_1 + 0x10) = (s16)func_80012C6C((s32)*(s16 *)(param_1 + 0x10), (s32)*(s16 *)(param_1 + 0x14), 0xA);
*(s16 *)(param_1 + 0x18) = func_80012ABC((s32)*(s16 *)(param_1 + 0x18), (s32)*(s16 *)(param_1 + 0x20), 0xA);
*(s16 *)(param_1 + 0x1A) = func_80012ABC((s32)*(s16 *)(param_1 + 0x1A), (s32)*(s16 *)(param_1 + 0x22), 0xA);
*(s16 *)(param_1 + 0x1C) = func_80012ABC((s32)*(s16 *)(param_1 + 0x1C), (s32)*(s16 *)(param_1 + 0x24), 0xA);
*(s16 *)(param_1 + 0x28) = func_80012C6C((s32)*(s16 *)(param_1 + 0x28), (s32)*(s16 *)(param_1 + 0x2E), 0xA);
*(s16 *)(param_1 + 0x2A) = func_80012C6C((s32)*(s16 *)(param_1 + 0x2A), (s32)*(s16 *)(param_1 + 0x30), 0xA);
*(s16 *)(param_1 + 0x2C) = func_80012C6C((s32)*(s16 *)(param_1 + 0x2C), (s32)*(s16 *)(param_1 + 0x32), 0xA);
*(s32 *)(param_1 + 0x48) = (s32)*(s16 *)(param_1 + 0x28) + (s32)param_2[0];
*(s32 *)(param_1 + 0x4C) = (s32)*(s16 *)(param_1 + 0x2A) + (s32)param_2[1];
*(s32 *)(param_1 + 0x50) = (s32)*(s16 *)(param_1 + 0x2C) + (s32)param_2[2];
func_80049CAC(param_1 + 0x18, (s32)&m1);
m1.t[0] = *(s16 *)(param_1 + 0x28) + param_2[0];
m1.t[1] = *(s16 *)(param_1 + 0x2A) + param_2[1];
m1.t[2] = *(s16 *)(param_1 + 0x2C) + param_2[2];
svec_in.vx = 0;
svec_in.vy = 0;
svec_in.vz = *(s32 *)(param_1 + 0x10);
((void (*)(s32, s32, s32))func_8012F14C)((s32)&m1, (s32)&svec_in, (s32)&svec_out);
*(s32 *)(param_1 + 0x3C) = (s32)svec_out.vx;
*(s32 *)(param_1 + 0x40) = (s32)svec_out.vy;
*(s32 *)(param_1 + 0x44) = (s32)svec_out.vz;
}
INCLUDE_ASM("asm/md_SC05_023/nonmatchings/md_SC05_023", func_801EE0CC);
+19 -1
View File
@@ -3504,7 +3504,25 @@ INCLUDE_ASM("asm/ov_SC01_005/nonmatchings/ov_SC01_005_jr_8017C340", func_8017E10
INCLUDE_ASM("asm/ov_SC01_005/nonmatchings/ov_SC01_005_jr_8017C340", func_8017E258);
INCLUDE_ASM("asm/ov_SC01_005/nonmatchings/ov_SC01_005_jr_8017C340", func_8017E384);
extern short D_800B9A02;
extern u16 D_80115114;
extern u16 D_80115112;
extern void func_800D2624(void);
void func_8017E384(void) {
u16 v0 = (*(u16 *)&D_800B9A02);
u16 v1 = D_80115114;
v0 ^= 0x1;
if (v1 == v0) {
func_800D2624();
} else {
D_80115112++;
}
}
extern void func_8002D4C8(s32 a0, s32 a1);
+7 -1
View File
@@ -4555,7 +4555,13 @@ int func_80181040(int param_1)
}
INCLUDE_ASM("asm/ov_SC03_024/nonmatchings/ov_SC03_024_jr_8017DF84", func_80181070);
extern void func_8001ABBC(u32, u32, void *, u32, u32);
extern u8 D_800AEE88[];
void func_80181070(void) {
func_8001ABBC(0, 0, D_800AEE88, 0, 0);
}
INCLUDE_ASM("asm/ov_SC03_024/nonmatchings/ov_SC03_024_jr_8017DF84", func_801810A4);
-370
View File
@@ -7965,373 +7965,3 @@ s32 func_80185D10(void *a0) {
func_8012F2E8((s32)a0, (s32)in, (s32)out);
return func_8012CB64((s32)out, -0x80, 0x80, -0x60, 0);
}
INCLUDE_ASM("asm/ov_SC04_018/nonmatchings/ov_SC04_018_jr_8017AE2C", func_80185D70);
/*
* Declaration reconciliation (byte-neutral) — these notes MUST travel with the body.
*
* 1. func_80185EEC (the function being defined). This TU already carries the
* canonical declaration
* extern s32 func_80185EEC(void);
* FIVE times above the splice point (L7450, L7492, L7504, L7534, L7559), and
* its banked callers reach it through `((void (*)(s32))func_80185EEC)(x)`
* casts. The real function takes one argument and returns void, so defining
* it under its own C name collides:
* 7740: conflicting types for `func_80185EEC'
* 7559: previous declaration of `func_80185EEC'
* Fix = the §37/§124 asm-label alias: define under the C name aF80185EEC
* carrying __asm__("func_80185EEC"). The emitted symbol is unchanged, the
* C-level name never meets the canonical declaration, blast radius is zero.
*
* 2. func_80185F20 (a callee). The TU DEFINES it BELOW the splice point
* (pre-splice L7740) as
* void func_80185F20(void *a0)
* so the invented prototype `extern void func_80185F20(s32 a0);` conflicted
* with that later definition:
* 7753: conflicting types for `func_80185F20'
* 7738: previous declaration of `func_80185F20'
* Fix = conform the prototype to the TU's own signature and push the type
* disagreement to a cast at the call site. Casting an s32 to void * emits
* no instruction, so this is byte-neutral.
*
* match_one.py still reports MATCH (13/13) after both changes.
*/
extern void func_80185F20(void *a0);
void aF80185EEC(s32 a0) __asm__("func_80185EEC");
void aF80185EEC(s32 a0) {
u16 v0;
s32 v1;
v0 = *(u16 *)(a0 + 0xFE);
v1 = *(s32 *)(a0 + 0x20);
v0 = -v0;
*(s16 *)(a0 + 0xF4) = v0;
*(s32 *)(v1 + 0x20) = a0 + 0xEC;
func_80185F20((void *)a0);
}
void func_80185F20(void *a0) {
if (*(u16 *)(a0 + 0x2) != 4) {
*(s16 *)(a0 + 0x5C) = 0x800;
} else if (*(s32 *)(a0 + 0xCC) != 1) {
*(s16 *)(a0 + 0x5C) = 0;
} else {
*(s16 *)(a0 + 0x5C) = 0x800;
}
}
extern s32 func_8012E57C(s32 a0, s32 a1);
void func_80185F54(void *a0, s32 a1, s32 a2) {
s32 v1 = func_8012E57C(0x61, (s32)(s16)a1);
if (v1 != 0) {
s32 v0 = *(s32 *)((char *)v1 + 0xCC);
if (v0 == 0) {
*(s32 *)((char *)v1 + 0xCC) = a2;
*(s32 *)((char *)v1 + 0xD0) = (s32)a0;
}
}
}
extern s32 func_8012E57C(s32 a0, s32 a1);
void func_80185FB8(s32 a0, s32 a1, s32 a2) {
s32 s1;
s32 s0;
s32 v1;
s32 shift_temp;
s1 = a0;
s0 = a2;
shift_temp = ((a1 << 16) >> 16);
v1 = func_8012E57C(0x61, shift_temp);
if (v1 == 0) {
return;
}
if (*(s32 *)((char *)v1 + 0xCC) != s0) {
return;
}
if (*(s32 *)((char *)v1 + 0xD0) != s1) {
return;
}
*(s32 *)((char *)v1 + 0xCC) = 0;
*(s32 *)((char *)v1 + 0xD0) = 0;
}
extern s32 func_8012E57C(s32 a0, s32 a1);
void func_8018602C(s32 a0, s32 a1) {
s32 v1 = func_8012E57C(0x61, (s32)(s16)a0);
if (v1 != 0) {
if (*(s16 *)(v1 + 0x10A) < a1) {
*(s16 *)(v1 + 0x10A) = a1;
}
}
}
DEFINE_func_80186084() /* dedup: shared engine-core @0x80186084 (src/shared) */
extern void func_8012C1B8(void);
extern void func_8012CAE4(void *a0);
extern void func_8001C214(s32, s32);
extern s32 D_801B8A2C;
void func_801860C0(void *a0)
{
s32 v0;
u16 v0_2;
v0 = ((s32 (*)(void))func_8012C1B8)();
*(s32 *)((u8 *)a0 + 0x20) = v0;
if (v0 == 0) {
((void (*)(void *))func_8012CAE4)(a0);
} else {
((void (*)(s32, s32))func_8001C214)(v0, 0);
*(s32 *)((u8 *)a0 + 0x58) = (s32)&D_801B8A2C | 0x40000000;
v0_2 = *(u16 *)((u8 *)a0 + 0x2);
*(u16 *)((u8 *)a0 + 0x34) = 0;
*(s32 *)((u8 *)a0 + 0x1C) = 0;
*(u16 *)((u8 *)a0 + 0x5C) = 0x800;
*(u16 *)((u8 *)a0 + 0x2) = v0_2 + 1;
}
}
/* func_8018613C — scan the 96-entry / 0x10C-stride D_801202A0 actor table for
* the lowest-scoring slot whose u16 tag at +0 is 0x61, then splat 3 words plus
* an align-1 8-byte block into the caller's struct.
*
* Byte-verified idioms (all four were needed; each was a real residual):
*
* 1. The 0x61 compare constant is NOT a source variable. gcc keeps it in a
* callee-saved reg and LICM sinks the `li` into the loop PREHEADER, so
* `addiu $s5,$zero,0x61` lands AFTER the guard branch's delay slot. Pinning
* an `s5` local puts the `li` in the entry block instead (+1 wrong slot).
*
* 2. The 8-byte copy at +0x10 is ONE align-1 struct assign, not two 4-byte
* ones. gcc's MIPS block move loads BOTH words first (lwl/lwr $a0,
* lwl/lwr $a1) then stores both; splitting it emits load/nop/store twice
* and costs an instruction (cookbook-index: "align-1 4xu8 struct assign
* emits the inline form").
*
* 3. The parameter must NOT be register-pinned. With `register u8 *s2
* __asm__("$18")` the entry-block `move` is a schedulable body insn and
* the list scheduler ranks the higher-priority `lui $s0` chain ahead of
* it, so the anti-dependent prologue `sw`s come out in regno order
* (s0,s1,s2,s3) instead of the target's def order (s2,s0,s1,s3). Letting
* gcc allocate the incoming parameter itself keeps the copy first and the
* whole prologue falls into place. (The other five pins are still needed.)
*
* 4. After the block store, gcc-2.7.2 CSE has invalidated memory, so
* a0->0x20 is RELOADED into a second pseudo — two separate C variables,
* not one reused variable (one variable => one pseudo => $a3 for both).
* The destination pointer must also be loaded BEFORE the source pointer:
* that source order is what lets the scheduler hoist `lw $v1,0x20($s2)`
* up into the first word-copy's load-delay slot.
*/
extern u8 D_801202A0[];
extern s32 func_8012BD14(s32 a0);
/* align-1 8-byte payload — drives the lwl/lwr + swl/swr inline block move */
void func_8018613C(void *a0)
{
register u8 *s0 __asm__("$16");
register s32 s1 __asm__("$17");
register u8 *s3 __asm__("$19");
register u8 *s4 __asm__("$20");
u8 *s2;
u8 *v0;
u8 *v1;
u8 *a0p;
s2 = (u8 *)a0;
s0 = D_801202A0;
s1 = 0x7FFF;
s3 = s0 + 0x6480;
while (s0 != s3) {
if (*(u16 *)s0 == 0x61) {
s32 v1_val = func_8012BD14((s32)s0);
if (v1_val < s1) {
s1 = v1_val;
s4 = s0;
}
}
s0 += 0x10C;
}
s0 = s4;
if (s1 == 0x7FFF) {
*(s16 *)((s32)s2 + 0x5C) = 0;
} else {
*(s32 *)(s2 + 0x4) = *(s32 *)(s0 + 0x4);
*(s32 *)(s2 + 0x8) = *(s32 *)(s0 + 0x8);
*(s32 *)(s2 + 0xC) = *(s32 *)(s0 + 0xC);
v1 = *(u8 **)(s2 + 0x20);
v0 = *(u8 **)(s0 + 0x20);
*(struct Un8_8018613C *)(v1 + 0x10) = *(struct Un8_8018613C *)(v0 + 0x10);
a0p = *(u8 **)(s2 + 0x20);
*(u16 *)(a0p + 0x12) = *(u16 *)(a0p + 0x12) - *(u16 *)(s0 + 0xFE);
*(s16 *)((s32)s2 + 0x5C) = 0x800;
}
}
DEFINE_func_8018625C() /* dedup: shared engine-core @0x8018625C (src/shared) */
/* func_801862A8 — scan the 96-entry / 0x10C-stride D_801202A0 actor table for
* an entry whose world position, transformed into a0's local frame, falls
* inside the box (x in [-0xA0,0x80), y in [-0xC0,0x80)). Returns 1 on the
* first hit, 0 if none.
*
* Two idioms carry this one:
*
* 1. ONE source pointer, TWO induction registers. The target walks $s1 (the
* record base, used for the +0 tag load and as the func_801863B4 argument)
* and $s0 = $s1 + 0xE, which serves the +6 / +0xA / +0xE / +0x20 fields as
* -8 / -4 / 0 / +0x12. That second register is loop.c's own giv: write
* ONE pointer `p` and address every field as `p + const`, and combine_givs
* rebases them all onto a single p+0xE representative. Writing the second
* pointer explicitly in source is what breaks it — gcc then treats it as a
* second biv AND still manufactures a giv at p+0xA, giving three IV
* registers and +2 instructions ($s4 spill, 69 ins).
*
* 2. The zero-byte `__asm__("")` fence before `return 1` (cookbook §34
* toolkit). Without it, reorg.c cannot fill the `beqz` delay slot from
* the fall-through thread (`li v0,1` clobbers the branch's own operand),
* leaves the slot empty, and then relax_delay_slots' "conditional jump
* around an unconditional jump" rule INVERTS the branch into
* `bnez $v0, <epilogue>` + `li $v0,1` — a strictly shorter tail (65 ins)
* that the original does not have. The asm insn stops both the eager
* filler and the inversion test (`next_active_insn` is no longer the `j`),
* so reorg falls back to copying `addiu $s1,$s1,0x10C` out of the branch
* target and advancing the label — the target's duplicated increment.
*/
extern u8 D_801202A0[];
extern s32 func_801863B4(s32 a0);
extern void func_8012F2E8(s32 a0, s32 a1, s32 a2);
extern s32 func_8012CB64(s32 a0, s32 a1, s32 a2, s32 a3, s32 a4);
s32 func_801862A8(void *a0) {
u8 *p;
u8 *end;
s32 t;
u16 tag;
s16 out[3];
s16 in[3];
p = D_801202A0;
end = p + 0x6480;
if (p != end) {
do {
tag = *(u16 *)p;
if (tag != 0 && tag != 0x61 && func_801863B4((s32)p) != 0) {
t = *(s32 *)(p + 0x20);
if (t != 0 && *(s32 *)(t + 0x24) != 0 && *(s32 *)(t + 0x4) >= 0) {
in[0] = *(u16 *)(p + 0x6);
in[1] = *(u16 *)(p + 0xA);
in[2] = *(u16 *)(p + 0xE);
func_8012F2E8((s32)a0, (s32)in, (s32)out);
if (func_8012CB64((s32)out, -0xA0, 0x80, -0xC0, 0x80) != 0) {
__asm__("");
return 1;
}
}
}
p += 0x10C;
} while (p != end);
}
return 0;
}
extern s16 D_801B8A44[];
s32 func_801863B4(s32 a0) {
s16 *p;
s16 v;
s32 x;
p = D_801B8A44;
v = *p;
if (*p != -1) {
x = *(u16 *)a0;
do {
if (x == v) {
return 1;
}
p++;
v = *p;
} while (*p != -1);
}
return 0;
}
extern void func_8012F214(s32 arg0, s32 arg1, s32 arg2);
extern s32 D_801B87D8;
extern s32 D_801E7AAC;
void func_80186410(void) {
register s32 a0 __asm__("$4");
u16 buffer[4];
s32 val;
s32 *p;
func_8012F214(a0, (s32)&D_801B87D8, (s32)buffer);
val = buffer[0] | (((s16)buffer[2]) << 16);
p = *(s32**)&D_801E7AAC;
p[1] = val;
}
extern s16 D_801E7030;
s32 func_80186450(void) {
return D_801E7030;
}
INCLUDE_ASM("asm/ov_SC04_018/nonmatchings/ov_SC04_018_jr_8017AE2C", func_80186460);
extern void func_80029444(void);
extern void func_801754A8(void);
extern void func_80141C04(void);
void func_801864AC(void) {
extern u16 D_80115112;
extern u16 D_80115116;
extern void (*D_801B94B0[])(void);
u16 i;
func_80029444();
func_801754A8();
i = D_80115112;
D_801B94B0[i]();
func_80141C04();
D_80115116++;
}
INCLUDE_ASM("asm/ov_SC04_018/nonmatchings/ov_SC04_018_jr_8017AE2C", func_8018651C);
File diff suppressed because it is too large Load Diff