feat(decomp): worker gate — +2 fns x0 propagated (fleet 95.2%)

This commit is contained in:
Drew T
2026-08-13 11:20:41 -06:00
parent b8b3b66f84
commit 5968226e9f
+157 -2
View File
@@ -4192,7 +4192,17 @@ void func_80188694(void *a0) {
}
INCLUDE_ASM("asm/ov_SC03_118/nonmatchings/ov_SC03_118_jr_801863CC", func_80188748);
void func_80188748(void *a0) {
s32 *p = *(s32 **)((s32)a0 + 0x20);
p[1] = p[1] | 0x58000000;
*(s16 *)((s32)p + 0x1E) = 0;
*(s16 *)((s32)p + 0x18) = 0;
*(s16 *)((s32)p + 0x1A) = 0;
*(s16 *)((s32)p + 0x1C) = 0;
*(s32 *)((s32)a0 + 0x2C) = 0x400;
*(u16 *)((s32)a0 + 0x2) = *(u16 *)((s32)a0 + 0x2) + 1;
}
INCLUDE_ASM("asm/ov_SC03_118/nonmatchings/ov_SC03_118_jr_801863CC", func_80188788);
@@ -4244,7 +4254,152 @@ s32 func_801887DC(s32 a0, s16 a1, s16 a2) {
}
INCLUDE_ASM("asm/ov_SC03_118/nonmatchings/ov_SC03_118_jr_801863CC", func_80188990);
#include "common.h"
/*
* func_80188990 -- adapted from func_80181500 (src/ov_SC03_107/ov_SC03_107_jr_801789AC.c),
* a byte-matched sibling in ov_SC03_107. Measured 9-site / 30-instruction diff vs that seed:
*
* 1. The seed's leading `if (*(s16*)(a0+0xA) >= 0x10) { func_80131C78(a0); ... }` guard is
* ABSENT here -- the target .s goes straight from the prologue into the `lbu $v1,0xC2($s0)`
* switch read with no lh/slti/bnez/jal func_80131C78 at all.
* 2. In case 0's `if (D & 0x6000) { if (D & 0x1000) {...return;} ... }` body, the order of the
* two calls is swapped relative to the seed: func_8002D4C8(0x754, 0) now precedes
* func_80143B6C(a0, 1) (seed had func_80143B6C first). Case 1 already had this order in the
* seed (that's the whole point of the `t = D_..` scheduling comment there), so case 1 is
* unchanged.
* 3. In case 2, both `* 15 / 16` roundings lost their `bgez/addiu +0xF` sign-correction dance --
* the target uses a plain arithmetic right shift (`(x * 15) >> 4`), not a C signed division.
* 4. The seed's tail call `func_8018134C(a0, -0x28, 1);` is not present anywhere in the target
* .s (func_8018134C's opcode/address never appears) -- it is simply not called here.
*
* Everything else (switch skeleton, both early-return blocks, case1 body, the shared >=0x78/>=0x28
* reset tail, and the final 0x108 countdown) is structurally identical to the seed.
*
* Decls chosen to agree with the seed's own choices (func_8012CBCC returns void there too, read
* through the same function-pointer cast; D_801D46D8/D_801D46DC are this overlay's counterparts of
* the seed's D_8019BBC8/D_8019BBCC, declared nowhere else in this standalone draft -- free choice).
*/
extern void func_8002D4C8(s32 a0, s32 a1);
extern s32 func_8012B030(u8 *a0);
extern void func_8012CBCC(s32);
extern void func_80131C78(s32 a0);
extern s32 func_80143B6C(s32 a0, s32 a1);
extern void func_800291C8(s32, s32);
extern s32 D_801D46D8;
extern s32 D_801D46DC;
void func_80188990(s32 a0) {
/* §162i1 dead-local pad: target frame 0x28 = args 0x10 + vars 0x10 + 4*2 regs;
* the raw draft compiles vars=0. Never read, never &-taken, >=2 elements. */
s32 pad[4];
switch (*(u8 *)(a0 + 0xC2)) {
case 0:
D_801D46D8 = ((s32 (*)(s32))func_8012CBCC)(a0);
if (D_801D46D8 & 0x6000) {
if (D_801D46D8 & 0x1000) {
*(s16 *)(a0 + 0x2) = 2;
*(u8 *)(a0 + 0xC1) = 0;
*(s16 *)(a0 + 0x5E) = 0;
*(s32 *)(a0 + 0x1C) = 0x30;
func_8002D4C8(0x7DF, 0);
func_800291C8(0xA, *(s16 *)(a0 + 0xFE));
return;
}
func_8002D4C8(0x754, 0);
func_80143B6C(a0, 1);
*(u8 *)(a0 + 0xC2) = 1;
*(s32 *)(a0 + 0x14) = 0xFFF30000;
*(s32 *)(a0 + 0x1C) = 0;
*(s32 *)(a0 + 0x10) = *(s32 *)(a0 + 0x10) >> 2;
*(s32 *)(a0 + 0x18) = *(s32 *)(a0 + 0x18) >> 2;
}
*(s32 *)(a0 + 0x1C) += 1;
if (*(s32 *)(a0 + 0x1C) >= 0x78) {
func_80131C78(a0);
*(s16 *)(a0 + 0x2) = 2;
*(s32 *)(a0 + 0x1C) = 1;
}
break;
case 1:
D_801D46DC = *(s32 *)(a0 + 0x14);
D_801D46D8 = ((s32 (*)(s32))func_8012CBCC)(a0);
if (D_801D46D8 & 0x6000) {
if (D_801D46D8 & 0x1000) {
*(s16 *)(a0 + 0x2) = 2;
*(u8 *)(a0 + 0xC1) = 0;
*(s16 *)(a0 + 0x5E) = 0;
*(s32 *)(a0 + 0x1C) = 0x30;
func_8002D4C8(0x7DF, 0);
func_800291C8(0xA, *(s16 *)(a0 + 0xFE));
return;
}
{
/* The read of D_801D46DC MUST precede the two pointer stores in the
* source: gcc-2.7.2's scheduler cannot hoist a symbol_ref load above a
* store through a register base (may-alias), so writing it inline in the
* `-D_801D46DC` expression leaves the load-delay slot unfilled -> a nop,
* and the function is 1 instruction long. */
s32 t;
func_8002D4C8(0x754, 0);
func_80143B6C(a0, 1);
t = D_801D46DC;
*(u8 *)(a0 + 0xC2) = 2;
*(s32 *)(a0 + 0x1C) = 0;
*(s32 *)(a0 + 0x14) = -t;
}
}
*(s32 *)(a0 + 0x1C) += 1;
if (*(s32 *)(a0 + 0x1C) >= 0x28) {
func_80131C78(a0);
*(s16 *)(a0 + 0x2) = 2;
*(s32 *)(a0 + 0x1C) = 1;
}
break;
case 2:
*(s32 *)(a0 + 0x10) = (*(s32 *)(a0 + 0x10) * 15) >> 4;
*(s32 *)(a0 + 0x18) = (*(s32 *)(a0 + 0x18) * 15) >> 4;
D_801D46D8 = ((s32 (*)(s32))func_8012CBCC)(a0);
if (D_801D46D8 & 0x6000) {
*(s32 *)(a0 + 0x14) = 0;
if (D_801D46D8 & 0x1000) {
*(s16 *)(a0 + 0x2) = 2;
*(u8 *)(a0 + 0xC1) = 0;
*(s16 *)(a0 + 0x5E) = 0;
*(s32 *)(a0 + 0x1C) = 0x30;
func_8002D4C8(0x7DF, 0);
func_800291C8(0xA, *(s16 *)(a0 + 0xFE));
return;
}
if (!(*(u16 *)(a0 + 0x84) & 1)) {
*(u16 *)(a0 + 0x84) |= 1;
func_8002D4C8(0x754, 0);
}
if ((*(s32 *)(a0 + 0x1C) & 3) == 3) {
func_80143B6C(a0, 1);
}
*(s32 *)(a0 + 0x1C) += 1;
if (*(s32 *)(a0 + 0x1C) >= 0x11) {
func_80131C78(a0);
func_8012B030((u8 *)a0);
*(s16 *)(a0 + 0x2) = 1;
*(u16 *)(a0 + 0x84) &= 0xFFFE;
}
}
break;
}
*(s16 *)(a0 + 0x108) = *(u16 *)(a0 + 0x108) - 1;
if (*(s16 *)(a0 + 0x108) == 0) {
func_800291C8(0xA, *(s16 *)(a0 + 0xFE));
}
}
INCLUDE_ASM("asm/ov_SC03_118/nonmatchings/ov_SC03_118_jr_801863CC", func_80188C8C);