mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-26 13:33:34 -04:00
feat(carve): §323 blocker 2 cleared — jr-isolate ov_SC03_029 for func_80186A34, byte-identical
The type-name scan matched `}\s*(\w+)\s*;`, which reads `__attribute__` as the name and fails on the following `((` — so a packed file-local typedef never entered the carried set, every decl naming it read as an unknown type, and the isolate refused the whole overlay. Stripping attributes before the scan is the entire fix.
This commit is contained in:
@@ -122,6 +122,7 @@ segments:
|
||||
- [0x52cd4, c, ov_SC03_029_jr_8017AE2C]
|
||||
- [0x55b18, c, ov_SC03_029_jr_8017DC70]
|
||||
- [0x57e24, c, ov_SC03_029_jr_8017FF7C]
|
||||
- [0x5e8dc, c, ov_SC03_029_jr_80186A34]
|
||||
- [0x5f66c, data, tail]
|
||||
- [0xaed6c, .rodata, ov_SC03_029] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0xaee48, .rodata, ov_SC03_029_jr_8012ACE0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
|
||||
@@ -7863,626 +7863,3 @@ L9F0:
|
||||
func_80131E00(a0, 0x12);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC03_029/nonmatchings/ov_SC03_029_jr_8017FF7C", func_80186A34);
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern void func_8012CBA4(s32 a0);
|
||||
extern void func_8012CC64(s32 a0, s32 a1);
|
||||
extern s32 func_8012CBCC(s32 a0);
|
||||
extern s32 func_8012BEE8(s32 a0);
|
||||
extern void func_8012B23C(s32 a0);
|
||||
extern void func_80131E00();
|
||||
extern void func_8013240C(s32 a0);
|
||||
extern void func_80186D90(s32 a0);
|
||||
|
||||
extern s32 D_801C92DC;
|
||||
extern s32 D_801D98C8;
|
||||
|
||||
void func_80186B4C(s32 a0) {
|
||||
s32 s0;
|
||||
s32 s1;
|
||||
s32 v0;
|
||||
s32 v1;
|
||||
s32 t;
|
||||
s32 p;
|
||||
s32 q;
|
||||
|
||||
s0 = a0;
|
||||
v1 = *(u16 *)(s0 + 0x34);
|
||||
s1 = 0;
|
||||
|
||||
switch (v1) {
|
||||
case 0:
|
||||
t = *(s32 *)(s0 + 0x1C) + 1;
|
||||
*(s32 *)(s0 + 0x1C) = t;
|
||||
if (t >= 0x29) {
|
||||
goto timeout;
|
||||
}
|
||||
q = *(s32 *)(s0 + 0x20);
|
||||
*(u16 *)(q + 0x10) -= 0x100;
|
||||
s1 = ((s32 (*)(s32, s32))func_8012CC64)(s0, (s32)&D_801C92DC);
|
||||
if (s1 & 0x2000) {
|
||||
*(s32 *)(s0 + 0x1C) = 0xF;
|
||||
*(u16 *)(s0 + 0x34) = *(u16 *)(s0 + 0x34) + 1;
|
||||
*(u16 *)(*(s32 *)(s0 + 0x20) + 0x10) = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
s1 = ((s32 (*)(s32))func_8012CBA4)(s0);
|
||||
if (!(s1 & 0x2000)) {
|
||||
*(u16 *)(s0 + 0x34) = 2;
|
||||
*(s32 *)(s0 + 0x1C) = 0;
|
||||
func_8012B23C(s0);
|
||||
break;
|
||||
}
|
||||
v0 = func_8012BEE8(s0);
|
||||
goto merge2;
|
||||
|
||||
case 2:
|
||||
t = *(s32 *)(s0 + 0x1C) + 1;
|
||||
*(s32 *)(s0 + 0x1C) = t;
|
||||
if (t >= 0x29) {
|
||||
timeout:
|
||||
func_80131E00(s0, 0xD);
|
||||
break;
|
||||
}
|
||||
s1 = ((s32 (*)(s32))func_8012CBCC)(s0);
|
||||
v0 = s1 & 0x2000;
|
||||
merge2:
|
||||
if (v0) {
|
||||
p = *(s32 *)(s0 + 0x20);
|
||||
*(u8 *)(s0 + 0xC1) = 0;
|
||||
*(u16 *)(p + 0x10) = 0;
|
||||
*(s16 *)(s0 + 0x5E) = 0;
|
||||
func_80186D90(s0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
((void (*)(s32))func_8013240C)((s32)&D_801D98C8);
|
||||
if ((s1 & 0xFF) == 2) {
|
||||
func_80131E00(s0, 0x12);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern void func_80132288(s32 *param_1, s32 *param_2, s32 param_3);
|
||||
extern void func_80186ECC(s32 a0, s32 a1);
|
||||
extern s32 D_801D98C8;
|
||||
extern s32 D_801C920C[];
|
||||
extern s32 D_801CA0A0;
|
||||
|
||||
void func_80186CE4(s32 a0) {
|
||||
func_80132288(&D_801D98C8, &D_801C920C, D_801CA0A0);
|
||||
func_80186ECC(a0, 1);
|
||||
}
|
||||
|
||||
|
||||
extern void func_8013240C(s32 a0);
|
||||
extern s32 D_801D98C8;
|
||||
|
||||
void func_80186D34(void) {
|
||||
((void (*)(s32))func_8013240C)((s32)&D_801D98C8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern void func_80186F9C(s32 arg0, s32 arg1, s32 arg2);
|
||||
extern void func_8002D4C8(s32 a0, s32 a1);
|
||||
void func_80186D5C(void)
|
||||
{
|
||||
|
||||
extern M2C_UNK D_801C9234;
|
||||
int new_var;
|
||||
func_80186F9C(new_var, (s32) (&D_801C9234), 0);
|
||||
new_var = 0xA74;
|
||||
func_8002D4C8(0xA74, 0);
|
||||
dummy_label_648936: ;
|
||||
}
|
||||
|
||||
|
||||
void func_80186D90(s32 a0) {
|
||||
extern u8 D_80187B3C[];
|
||||
*(s16 *)(a0 + 0x2) = 1;
|
||||
func_8012A828(a0, D_80187B3C);
|
||||
*(u16 *)(a0 + 0x5C) = 0xAA10;
|
||||
*(s16 *)(a0 + 0xEA) = 0;
|
||||
}
|
||||
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern void func_8012CBA4(s32 a0);
|
||||
extern void func_80131E00();
|
||||
extern s32 func_8012CBCC(s32 a0);
|
||||
extern void func_8012ADE4(s32 a0);
|
||||
|
||||
s32 func_80186DD4(s32 a0) {
|
||||
s32 s0;
|
||||
s32 t;
|
||||
|
||||
s0 = a0;
|
||||
if (*(s16 *)(s0 + 0xE8) == 0) {
|
||||
a0 = ((s32 (*)(s32))func_8012CBA4)(a0);
|
||||
if ((a0 & 0xFF) == 2) {
|
||||
func_80131E00(s0, 0x12);
|
||||
return -1;
|
||||
}
|
||||
if (!(a0 & 0x2000)) {
|
||||
func_8012ADE4(s0);
|
||||
*(s16 *)(s0 + 0xEA) = 2;
|
||||
return 0;
|
||||
}
|
||||
if (a0 & 0x4000) {
|
||||
func_8012ADE4(s0);
|
||||
*(s16 *)(s0 + 0xEA) = 1;
|
||||
return 0;
|
||||
}
|
||||
if (a0 & 0x8000) {
|
||||
*(s16 *)(s0 + 0xEA) = 1;
|
||||
return 0;
|
||||
}
|
||||
*(s16 *)(s0 + 0xEA) = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
a0 = func_8012CBCC(s0);
|
||||
if (!(a0 & 0x2000)) {
|
||||
t = *(u16 *)(s0 + 0xE8) + 1;
|
||||
*(u16 *)(s0 + 0xE8) = t;
|
||||
if ((s16)t >= 0x5A) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*(u16 *)(s0 + 0xE8) = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
extern s32 func_80186ECC_def(s32 a0, s32 a1) __asm__("func_80186ECC");
|
||||
|
||||
s32 func_80186ECC_def(s32 a0, s32 a1) {
|
||||
extern s32 D_801CA248;
|
||||
extern s32 D_801CA418;
|
||||
extern void func_800183E0(s32);
|
||||
s32 ptr;
|
||||
|
||||
if (a1 & 1) {
|
||||
if ((*(u16 *)(a0 + 0xDC) & 2) == 0) {
|
||||
return 1;
|
||||
}
|
||||
ptr = (s32)&D_801CA248;
|
||||
} else if (a1 & 2) {
|
||||
if ((*(u16 *)(a0 + 0xDC) & 1) == 0) {
|
||||
return 1;
|
||||
}
|
||||
ptr = (s32)&D_801CA418;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
func_800183E0(ptr);
|
||||
*(u16 *)(a0 + 0xDC) = a1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern s32 rand(void);
|
||||
void func_80186F60(s32 arg0) {
|
||||
if ((rand() & 1) != 0) {
|
||||
*(s16*)(arg0 + 0x2) = 0x1;
|
||||
} else {
|
||||
*(s16*)(arg0 + 0x2) = 0x3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern void func_8012B23C(s32 a0);
|
||||
extern void func_80132288(s32 *param_1, s32 *param_2, s32 param_3);
|
||||
extern void func_800183E0(s32 a0);
|
||||
|
||||
extern s32 D_801D98C8;
|
||||
extern s32 D_801CA0A0;
|
||||
extern s32 D_801CA248;
|
||||
|
||||
void func_80186F9C(s32 a0, s32 a1, s32 a2) {
|
||||
register s32 s1 __asm__("$17") = a0;
|
||||
register s32 s0 __asm__("$16");
|
||||
register s32 s2 __asm__("$18") = a2;
|
||||
s32 p;
|
||||
|
||||
__asm__("" :: "r"(s1));
|
||||
s0 = a1;
|
||||
|
||||
func_8012B23C(s1);
|
||||
func_80132288(&D_801D98C8, (s32 *)s0, D_801CA0A0);
|
||||
s0 = 1;
|
||||
if (*(u16 *)(s1 + 0xDC) & 2) {
|
||||
func_800183E0((s32)&D_801CA248);
|
||||
*(u16 *)(s1 + 0xDC) = s0;
|
||||
}
|
||||
*(u16 *)(s1 + 0x5C) &= 0xFFFE;
|
||||
*(s32 *)(s1 + 0x1C) = s2;
|
||||
*(u16 *)(*(s32 *)(s1 + 0x20) + 0x12) = (*(u16 *)(s1 + 0x62) + 0x800) & 0xFFF;
|
||||
p = *(s32 *)(s1 + 0x20);
|
||||
*(s16 *)(p + 0x14) = 0;
|
||||
*(s16 *)(p + 0x10) = 0;
|
||||
}
|
||||
|
||||
|
||||
extern void func_8012C218(void*);
|
||||
|
||||
void func_80187050(void *arg0) {
|
||||
int iVar1;
|
||||
if ((*(s16 *)((char *)arg0 + 0x70) & 0x8000) == 0) {
|
||||
iVar1 = *(int *)((char *)arg0 + 0x68);
|
||||
if ((iVar1 != 0) && ((*(s16 *)((char *)arg0 + 0x72) & 0x8000) != 0)) {
|
||||
*(unsigned short *)(iVar1 + 10) = *(unsigned short *)(iVar1 + 10) & 0x7FFF;
|
||||
}
|
||||
}
|
||||
func_8012C218(arg0);
|
||||
}
|
||||
|
||||
|
||||
extern void Square0(s32 *a0, s32 *a1);
|
||||
|
||||
s32 func_801870B8(s32 a0) {
|
||||
s32 sp10[4];
|
||||
|
||||
sp10[0] = *(s16 *)((s32)a0 + 6) - *(s16 *)((s32)a0 + 0x88);
|
||||
sp10[1] = 0;
|
||||
sp10[2] = *(s16 *)((s32)a0 + 0xE) - *(s16 *)((s32)a0 + 0x8C);
|
||||
Square0(&sp10[0], &sp10[0]);
|
||||
return 0x18FFFF >= (sp10[0] + sp10[2]);
|
||||
}
|
||||
|
||||
|
||||
typedef struct { s16 vx; u16 vy; s16 vz, pad; } SVec_8017F67C_801869CC;
|
||||
|
||||
|
||||
/* match_one's standalone common.h does not reach src/shared/engine_types.h, where the
|
||||
* real TU's Blk20 { s32 w[8]; } and Vec32 { s32 vx, vy, vz, pad; } live. Local copies here;
|
||||
* integrator may drop these and reuse the TU's own (engine_types.h:472, :1098). */
|
||||
typedef struct { s32 w[8]; } Blk20_80188AF4;
|
||||
typedef struct { s32 vx, vy, vz, pad; } Vec32_80188AF4;
|
||||
|
||||
s32 func_80187118(s32 a0, s32 a1)
|
||||
{
|
||||
extern s32 func_8012B864(s32 a0);
|
||||
extern void RotMatrixY(s32 a0, void *a1);
|
||||
extern void func_800484EC(s32 a0, s32 a1, s32 a2);
|
||||
extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2);
|
||||
extern struct Mtx32_80184008 D_800AE620;
|
||||
|
||||
u32 pos[3];
|
||||
Vec32_80188AF4 out;
|
||||
u8 rotIn[8];
|
||||
u8 rotOut[8];
|
||||
Blk20_80188AF4 m;
|
||||
|
||||
m = (*(Blk20_80188AF4 *)&(*(Mtx8_8017DE10_8017E710 *)&D_800AE620));
|
||||
RotMatrixY(func_8012B864(a0), &m);
|
||||
func_800484EC((s32)&m, a1, (s32)&out);
|
||||
|
||||
pos[0] = *(s32 *)(a0 + 0x4) + out.vx;
|
||||
pos[1] = *(s32 *)(a0 + 0x8) + out.vy;
|
||||
pos[2] = *(s32 *)(a0 + 0xC) + out.vz;
|
||||
|
||||
{
|
||||
register u16 rix __asm__("$2");
|
||||
register u16 roy __asm__("$3");
|
||||
register u16 roz __asm__("$7");
|
||||
register u16 riz __asm__("$8");
|
||||
|
||||
rix = *(u16 *)(a0 + 0x3A);
|
||||
roy = *((u16 *)&pos[1] + 1);
|
||||
roz = *((u16 *)&pos[2] + 1);
|
||||
*(u16 *)(rotIn + 0) = rix;
|
||||
*(u16 *)(rotIn + 2) = *(u16 *)(a0 + 0x3E);
|
||||
riz = *(u16 *)(a0 + 0x42);
|
||||
*(u16 *)(rotOut + 0) = *((u16 *)&pos[0] + 1);
|
||||
*(u16 *)(rotOut + 2) = roy;
|
||||
*(u16 *)(rotOut + 4) = roz;
|
||||
*(u16 *)(rotIn + 4) = riz;
|
||||
}
|
||||
|
||||
func_8012CEB0((s32)&rotIn[0], (s32)&rotOut[0], 0);
|
||||
}
|
||||
|
||||
|
||||
s32 func_8018723C(void *a0) {
|
||||
short a[4];
|
||||
short b[4];
|
||||
s32 pa, pb;
|
||||
s32 r;
|
||||
a[0] = *(u16 *)((s32)a0 + 0x6);
|
||||
a[1] = *(u16 *)((s32)a0 + 0xA);
|
||||
a[2] = *(u16 *)((s32)a0 + 0xE);
|
||||
pa = (s32)a;
|
||||
pb = (s32)b;
|
||||
__builtin_memcpy((void *)pb, (void *)pa, 8);
|
||||
b[1] += 8;
|
||||
r = func_80133784(1, pa, pb) & 0x2000;
|
||||
return r != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* func_801872B4 — tiny matrix wrapper.
|
||||
* 0x20-byte local scratch matrix at sp+0x10 (frame 0x40 = 0x10 outgoing args
|
||||
* + 0x20 matrix + 0x10 for $s0/$s1/$s2/$ra).
|
||||
* func_80013F3C(&m); identity/init
|
||||
* func_80187318((s16)a0, &m); rotate by a *sign-extended halfword* angle
|
||||
* ApplyMatrixSV(&m, a1, a2);
|
||||
* The `sll/sra 16` pair lands AFTER the first call (a0 lives in $s0 across it),
|
||||
* which is the cast-at-use-site form: an s32 parameter narrowed at the call.
|
||||
*/
|
||||
|
||||
extern void func_80013F3C(s32 a0);
|
||||
extern void ApplyMatrixSV(void *a0, void *a1, void *a2);
|
||||
extern void func_80187318();
|
||||
|
||||
void func_801872B4(s32 a0, void *a1, void *a2) {
|
||||
s32 m[8];
|
||||
|
||||
((void (*)(void *))func_80013F3C)((void *)m);
|
||||
((void (*)(s32, void *))func_80187318)((s16)a0, (void *)m);
|
||||
ApplyMatrixSV((void *)m, a1, a2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void func_80187318(s32 param_1, s32 *param_2)
|
||||
{
|
||||
s32 s0;
|
||||
s32 s1;
|
||||
s32 cos_val;
|
||||
s16 sin_val;
|
||||
s32 v1;
|
||||
s16 matrix_stack[16];
|
||||
|
||||
s1 = (s32)param_2;
|
||||
s0 = param_1 & 0xFFF;
|
||||
|
||||
cos_val = func_80187718(s0);
|
||||
sin_val = func_8018765C(s0);
|
||||
|
||||
/* Build rotation matrix on stack */
|
||||
v1 = 0x7FF8;
|
||||
*(short *)((s32)matrix_stack + 0x04) = sin_val;
|
||||
*(short *)((s32)matrix_stack + 0x00) = cos_val;
|
||||
*(short *)((s32)matrix_stack + 0x02) = 0;
|
||||
*(short *)((s32)matrix_stack + 0x06) = 0;
|
||||
*(short *)((s32)matrix_stack + 0x08) = v1;
|
||||
*(short *)((s32)matrix_stack + 0x0A) = 0;
|
||||
*(short *)((s32)matrix_stack + 0x0C) = -sin_val;
|
||||
*(short *)((s32)matrix_stack + 0x0E) = 0;
|
||||
*(short *)((s32)matrix_stack + 0x10) = cos_val;
|
||||
|
||||
__asm__ volatile (
|
||||
"lw $12, 0(%0);"
|
||||
"lw $13, 4(%0);"
|
||||
"ctc2 $12, $0;"
|
||||
"ctc2 $13, $1;"
|
||||
"lw $12, 8(%0);"
|
||||
"lw $13, 12(%0);"
|
||||
"lw $14, 16(%0);"
|
||||
"ctc2 $12, $2;"
|
||||
"ctc2 $13, $3;"
|
||||
"ctc2 $14, $4;"
|
||||
"addiu $2, $sp, 0x10;"
|
||||
"lhu $12, 0($2);"
|
||||
"lhu $13, 6($2);"
|
||||
"lhu $14, 12($2);"
|
||||
"mtc2 $12, $9;"
|
||||
"mtc2 $13, $10;"
|
||||
"mtc2 $14, $11;"
|
||||
"nop;"
|
||||
"nop;"
|
||||
"mvmva 1, 0, 3, 3, 0;"
|
||||
"mfc2 $12, $9;"
|
||||
"mfc2 $13, $10;"
|
||||
"mfc2 $14, $11;"
|
||||
"sh $12, 0(%0);"
|
||||
"sh $13, 6(%0);"
|
||||
"sh $14, 12(%0);"
|
||||
"addiu $2, $sp, 0x12;"
|
||||
"lhu $12, 0($2);"
|
||||
"lhu $13, 6($2);"
|
||||
"lhu $14, 12($2);"
|
||||
"mtc2 $12, $9;"
|
||||
"mtc2 $13, $10;"
|
||||
"mtc2 $14, $11;"
|
||||
"nop;"
|
||||
"nop;"
|
||||
"mvmva 1, 0, 3, 3, 0;"
|
||||
"addiu $2, %0, 0x2;"
|
||||
"mfc2 $12, $9;"
|
||||
"mfc2 $13, $10;"
|
||||
"mfc2 $14, $11;"
|
||||
"sh $12, 0($2);"
|
||||
"sh $13, 6($2);"
|
||||
"sh $14, 12($2);"
|
||||
"addiu $2, $sp, 0x14;"
|
||||
"lhu $12, 0($2);"
|
||||
"lhu $13, 6($2);"
|
||||
"lhu $14, 12($2);"
|
||||
"mtc2 $12, $9;"
|
||||
"mtc2 $13, $10;"
|
||||
"mtc2 $14, $11;"
|
||||
"nop;"
|
||||
"nop;"
|
||||
"mvmva 1, 0, 3, 3, 0;"
|
||||
"addiu %0, %0, 4;"
|
||||
"mfc2 $12, $9;"
|
||||
"mfc2 $13, $10;"
|
||||
"mfc2 $14, $11;"
|
||||
"sh $12, 0(%0);"
|
||||
"sh $13, 6(%0);"
|
||||
"sh $14, 12(%0)"
|
||||
: "=r"(s1)
|
||||
: "0"(s1)
|
||||
: "$12", "$13", "$14", "$2"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void func_80187478(u16 *r, s16 *m) {
|
||||
s16 cx;
|
||||
s16 sx;
|
||||
s16 cy;
|
||||
s16 sy;
|
||||
s16 cz;
|
||||
s16 sz;
|
||||
s32 sxsy;
|
||||
s32 cxcz;
|
||||
s32 cxsz;
|
||||
|
||||
cx = func_80187718(r[0] & 0xFFF);
|
||||
sx = func_8018765C(r[0] & 0xFFF);
|
||||
cy = func_80187718(r[1] & 0xFFF);
|
||||
sy = func_8018765C(r[1] & 0xFFF);
|
||||
cz = func_80187718(r[2] & 0xFFF);
|
||||
sz = func_8018765C(r[2] & 0xFFF);
|
||||
|
||||
cxsz = (cx * sz) >> 15;
|
||||
cxcz = (cx * cz) >> 15;
|
||||
sxsy = (sx * sy) >> 15;
|
||||
|
||||
m[0] = (cz * cy) >> 15;
|
||||
m[1] = ((sxsy * cz) >> 15) - cxsz;
|
||||
m[2] = ((cxcz * sy) >> 15) + ((sx * sz) >> 15);
|
||||
m[3] = (sz * cy) >> 15;
|
||||
m[4] = ((sxsy * sz) >> 15) + cxcz;
|
||||
m[5] = ((cxsz * sy) >> 15) - ((sx * cz) >> 15);
|
||||
m[6] = -sy;
|
||||
m[7] = (cy * sx) >> 15;
|
||||
m[8] = (cy * cx) >> 15;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* func_8018765C — quadrant-folded sine lookup over a 0x400-entry u16 table.
|
||||
*
|
||||
* asm evidence:
|
||||
* Q0 (a<0x400) : lh tbl[a]
|
||||
* Q1 (a-0x400 < 0x400) : lh tbl[0x7FF - a]
|
||||
* Q2 (a-0x800 < 0x400) : lhu tbl[a - 0x800], negu, sll/sra 16
|
||||
* Q3 (a-0xC00 < 0x400) : lhu tbl[0xFFF - a], negu, sll/sra 16
|
||||
* else : NO value is produced at all (see below)
|
||||
*
|
||||
* The `lhu` + `negu` + 16-bit sign-extend in Q2/Q3 pins BOTH types:
|
||||
* - the table element is UNSIGNED (zero-extending load feeding the negate), and
|
||||
* - the result is truncated back to 16 bits => the function returns s16.
|
||||
* (An s16 table would give `lh`; an s32 return would drop the sll/sra pair.)
|
||||
*
|
||||
* Q2's base is D_801D517C == D_801D617C - 0x1000: gcc folded the `- 0x800`
|
||||
* element offset into the symbol addend and indexes with the raw parameter
|
||||
* (`sll $v0, $a0, 1`). Writing `tbl[a0 - 0x800]` reproduces that exactly.
|
||||
*
|
||||
* LOAD-BEARING: there is deliberately NO trailing `return 0;`. The original
|
||||
* falls off the end of a non-void function, so the out-of-range path returns
|
||||
* whatever `$v0` happens to hold — which is the failing `sltiu` result, i.e. 0.
|
||||
* That is why the target's last test is `beqz $v0, .L8018BA04` + a bare `nop`
|
||||
* delay slot (gcc may not clobber $v0 on the taken edge) with no `move $v0,
|
||||
* $zero` anywhere. Adding `return 0;` costs 2 instructions AND lets
|
||||
* find_cross_jump tail-merge the Q2/Q3 `negu; sll; sra` tails (cookbook §5a):
|
||||
* 45 ins / 19 mismatched instead of MATCH.
|
||||
*/
|
||||
|
||||
|
||||
s16 func_8018765C(u32 a0)
|
||||
{
|
||||
|
||||
extern u16 D_801D617C[];
|
||||
if (a0 < 0x400) {
|
||||
return D_801D617C[a0];
|
||||
}
|
||||
if (a0 - 0x400 < 0x400) {
|
||||
return D_801D617C[0x7FF - a0];
|
||||
}
|
||||
if (a0 - 0x800 < 0x400) {
|
||||
return -D_801D617C[a0 - 0x800];
|
||||
}
|
||||
if (a0 - 0xC00 < 0x400) {
|
||||
return -D_801D617C[0xFFF - a0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* func_80187718 — quarter-table cosine lookup (sibling of func_8018B950, the sine).
|
||||
*
|
||||
* The four `lui/addu/l[h|hu] %lo(...)` bases in the target are all the SAME 0x400-entry
|
||||
* signed s16 quarter table at ((s16 *)D_801D617C); gcc folds the per-quadrant constant index
|
||||
* offset into the symbol:
|
||||
* ((s16 *)D_801D617C)[a - 0x400] -> base ((s16 *)D_801D617C)-0x800 = D_801D597C, index a*2
|
||||
* ((s16 *)D_801D617C)[a - 0xC00] -> base ((s16 *)D_801D617C)-0x1800 = D_801D497C, index a*2
|
||||
* so no extra externs are needed for D_801D597C / D_801D497C.
|
||||
*
|
||||
* Types: the positive quadrants return the `lh` value straight through (already
|
||||
* sign-extended, no sll/sra); the negative quadrants take an explicit (s16) cast on
|
||||
* the negation, which forces the truncate -> the return's sign-extend becomes the
|
||||
* `sll 16 / sra 16` pair, and combine downgrades those loads to `lhu`. Writing the
|
||||
* arms as four flat `return`s (not one shared s16 local) keeps the extension OFF the
|
||||
* positive quadrants; cross-jump then merges the two `sll/sra` tails.
|
||||
*
|
||||
* The tail has NO `return 0`. A trailing `return 0` costs an extra `move $v0,$zero`
|
||||
* block AND lets dbr steal `sll $v0,$a0,1` into the final beqz delay slot (target has
|
||||
* a `nop` there). Falling off the end keeps `expand_function_end`'s `(use $v0)` live
|
||||
* over the epilogue, so the delay slot stays empty and the branch lands straight on
|
||||
* the shared `jr $ra` with the `sltiu` zero already in $v0 — which IS the 0 the
|
||||
* caller observes. Same shape as the sibling func_8018B950.
|
||||
*/
|
||||
|
||||
|
||||
s32 func_80187718(u32 a0v)
|
||||
{
|
||||
|
||||
extern u16 D_801D617C[];
|
||||
if (a0v < 0x400) {
|
||||
return ((s16 *)D_801D617C)[0x3FF - a0v];
|
||||
}
|
||||
if (a0v - 0x400 < 0x400) {
|
||||
return (s16)-((s16 *)D_801D617C)[a0v - 0x400];
|
||||
}
|
||||
if (a0v - 0x800 < 0x400) {
|
||||
return (s16)-((s16 *)D_801D617C)[0xBFF - a0v];
|
||||
}
|
||||
if (a0v - 0xC00 < 0x400) {
|
||||
return ((s16 *)D_801D617C)[a0v - 0xC00];
|
||||
}
|
||||
/* no trailing `return 0`: gcc's end-of-function (use $v0) keeps the return
|
||||
* register live over the epilogue, so dbr cannot steal `sll $v0,$a0,1` into
|
||||
* the beqz delay slot, and the 0 the caller sees is the sltiu result. */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user