diff --git a/src/ov_SC06_020/ov_SC06_020_jr_80180B04.c b/src/ov_SC06_020/ov_SC06_020_jr_80180B04.c index badd36150..811e7a1ff 100644 --- a/src/ov_SC06_020/ov_SC06_020_jr_80180B04.c +++ b/src/ov_SC06_020/ov_SC06_020_jr_80180B04.c @@ -3166,7 +3166,52 @@ INCLUDE_ASM("asm/ov_SC06_020/nonmatchings/ov_SC06_020_jr_80180B04", func_8018165 INCLUDE_ASM("asm/ov_SC06_020/nonmatchings/ov_SC06_020_jr_80180B04", func_801817CC); -INCLUDE_ASM("asm/ov_SC06_020/nonmatchings/ov_SC06_020_jr_80180B04", func_8018182C); + +/* Family exemplar (S48 wave-4). Two compiler-shape levers used, both already + * documented in the cookbook: + * - §164z (func_8018A974 refutation): a non-volatile `__asm__("" ::: "memory")` + * barrier forces a genuine second `lw` reload of *(a0+0x90) at the C/D-group + * check, matching the target's register-clash reload, at zero extra stack cost. + * - §45 Lever 4: the call is written literally duplicated in each of the three + * arms rather than shared through one fall-through tail; gcc-2.7.2's jump.c + * cross-jumps the duplicates back together, which is what lets `addiu $a0,$zero,0x53` + * (not the unrelated stack-arg constant 0x14) win both branch-delay slots. + */ + +extern s32 func_801469C8(int, void*, int, int, u16, int, int, int); + +void func_8018182C(s32 a0, s32 a1) { + + extern u8 D_801B5A18[]; + extern u8 D_801B63D8[]; + extern u8 D_801B64D0[]; + extern u8 D_801B6098[]; + extern u16 D_800B99DA; + if ((*(s16 *)(a0 + 0x70) & 0x8000) == 0) { + return; + } + if ((a1 & 0xFF) != 0x24) { + return; + } + + if (*(u8 **)(a0 + 0x90) == D_801B5A18) { + if (D_800B99DA % 3 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } else if (*(u8 **)(a0 + 0x90) == D_801B63D8 && *(u16 *)(a0 + 2) == 0xB) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } else { + __asm__("" ::: "memory"); + if ((*(u8 **)(a0 + 0x90) == D_801B64D0 || *(u8 **)(a0 + 0x90) == D_801B6098) && + D_800B99DA % 6 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } +} + INCLUDE_ASM("asm/ov_SC06_020/nonmatchings/ov_SC06_020_jr_80180B04", func_80181954); diff --git a/src/ov_SC06_022/ov_SC06_022_jr_80184A28.c b/src/ov_SC06_022/ov_SC06_022_jr_80184A28.c index 2e32e36c4..8e54a293a 100644 --- a/src/ov_SC06_022/ov_SC06_022_jr_80184A28.c +++ b/src/ov_SC06_022/ov_SC06_022_jr_80184A28.c @@ -2739,7 +2739,6 @@ extern void func_80182610(s32 p); extern s32 func_8012BDBC(s32 a0, s32 a1); extern void func_80142414(s32 a0, s16 a1); extern void func_801828D8(s32 p); -extern u8 D_801D47C0[]; extern void func_80182998(s32 param_1); extern void func_801832FC(s32 param_1); extern void func_80185878(s32 a0); @@ -3199,7 +3198,52 @@ INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_80184A28", func_8018557 INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_80184A28", func_801856F0); -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_80184A28", func_80185750); + +/* Family exemplar (S48 wave-4). Two compiler-shape levers used, both already + * documented in the cookbook: + * - §164z (func_8018A974 refutation): a non-volatile `__asm__("" ::: "memory")` + * barrier forces a genuine second `lw` reload of *(a0+0x90) at the C/D-group + * check, matching the target's register-clash reload, at zero extra stack cost. + * - §45 Lever 4: the call is written literally duplicated in each of the three + * arms rather than shared through one fall-through tail; gcc-2.7.2's jump.c + * cross-jumps the duplicates back together, which is what lets `addiu $a0,$zero,0x53` + * (not the unrelated stack-arg constant 0x14) win both branch-delay slots. + */ + +extern s32 func_801469C8(int, void*, int, int, u16, int, int, int); + +void func_80185750(s32 a0, s32 a1) { + + extern u8 D_801D4140[]; + extern u8 D_801D4B00[]; + extern u8 D_801D4BF8[]; + extern u8 D_801D47C0[]; + extern u16 D_800B99DA; + if ((*(s16 *)(a0 + 0x70) & 0x8000) == 0) { + return; + } + if ((a1 & 0xFF) != 0x24) { + return; + } + + if (*(u8 **)(a0 + 0x90) == D_801D4140) { + if (D_800B99DA % 3 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } else if (*(u8 **)(a0 + 0x90) == D_801D4B00 && *(u16 *)(a0 + 2) == 0xB) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } else { + __asm__("" ::: "memory"); + if ((*(u8 **)(a0 + 0x90) == D_801D4BF8 || *(u8 **)(a0 + 0x90) == D_801D47C0) && + D_800B99DA % 6 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } +} + INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_80184A28", func_80185878); diff --git a/src/ov_SC06_024/ov_SC06_024_jr_80186F00.c b/src/ov_SC06_024/ov_SC06_024_jr_80186F00.c index 162381ab9..d682438fa 100644 --- a/src/ov_SC06_024/ov_SC06_024_jr_80186F00.c +++ b/src/ov_SC06_024/ov_SC06_024_jr_80186F00.c @@ -3231,7 +3231,52 @@ INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_80186F00", func_80187A5 INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_80186F00", func_80187BC8); -INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_80186F00", func_80187C28); + +/* Family exemplar (S48 wave-4). Two compiler-shape levers used, both already + * documented in the cookbook: + * - §164z (func_8018A974 refutation): a non-volatile `__asm__("" ::: "memory")` + * barrier forces a genuine second `lw` reload of *(a0+0x90) at the C/D-group + * check, matching the target's register-clash reload, at zero extra stack cost. + * - §45 Lever 4: the call is written literally duplicated in each of the three + * arms rather than shared through one fall-through tail; gcc-2.7.2's jump.c + * cross-jumps the duplicates back together, which is what lets `addiu $a0,$zero,0x53` + * (not the unrelated stack-arg constant 0x14) win both branch-delay slots. + */ + +extern s32 func_801469C8(int, void*, int, int, u16, int, int, int); + +void func_80187C28(s32 a0, s32 a1) { + + extern u8 D_801D3284[]; + extern u8 D_801D3C44[]; + extern u8 D_801D3D3C[]; + extern u8 D_801D3904[]; + extern u16 D_800B99DA; + if ((*(s16 *)(a0 + 0x70) & 0x8000) == 0) { + return; + } + if ((a1 & 0xFF) != 0x24) { + return; + } + + if (*(u8 **)(a0 + 0x90) == D_801D3284) { + if (D_800B99DA % 3 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } else if (*(u8 **)(a0 + 0x90) == D_801D3C44 && *(u16 *)(a0 + 2) == 0xB) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } else { + __asm__("" ::: "memory"); + if ((*(u8 **)(a0 + 0x90) == D_801D3D3C || *(u8 **)(a0 + 0x90) == D_801D3904) && + D_800B99DA % 6 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } +} + INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_80186F00", func_80187D50); diff --git a/src/ov_SC06_032/ov_SC06_032_jr_80181014.c b/src/ov_SC06_032/ov_SC06_032_jr_80181014.c index 65ee9e48d..b4d33054d 100644 --- a/src/ov_SC06_032/ov_SC06_032_jr_80181014.c +++ b/src/ov_SC06_032/ov_SC06_032_jr_80181014.c @@ -2734,7 +2734,6 @@ extern u8 D_801A63EC[]; extern u8 D_801A6604[]; extern u8 D_801BD9C0[]; extern u8 D_801BDA28[]; -extern u8 D_801BDCF8[]; extern u8 D_801BDDB0[]; extern void func_8017FA18(s32 p); extern void func_8018000C(s32 param_1); @@ -3109,7 +3108,52 @@ INCLUDE_ASM("asm/ov_SC06_032/nonmatchings/ov_SC06_032_jr_80181014", func_8018228 INCLUDE_ASM("asm/ov_SC06_032/nonmatchings/ov_SC06_032_jr_80181014", func_80182400); -INCLUDE_ASM("asm/ov_SC06_032/nonmatchings/ov_SC06_032_jr_80181014", func_80182460); + +/* Family exemplar (S48 wave-4). Two compiler-shape levers used, both already + * documented in the cookbook: + * - §164z (func_8018A974 refutation): a non-volatile `__asm__("" ::: "memory")` + * barrier forces a genuine second `lw` reload of *(a0+0x90) at the C/D-group + * check, matching the target's register-clash reload, at zero extra stack cost. + * - §45 Lever 4: the call is written literally duplicated in each of the three + * arms rather than shared through one fall-through tail; gcc-2.7.2's jump.c + * cross-jumps the duplicates back together, which is what lets `addiu $a0,$zero,0x53` + * (not the unrelated stack-arg constant 0x14) win both branch-delay slots. + */ + +extern s32 func_801469C8(int, void*, int, int, u16, int, int, int); + +void func_80182460(s32 a0, s32 a1) { + + extern u8 D_801BD678[]; + extern u8 D_801BE038[]; + extern u8 D_801BE130[]; + extern u8 D_801BDCF8[]; + extern u16 D_800B99DA; + if ((*(s16 *)(a0 + 0x70) & 0x8000) == 0) { + return; + } + if ((a1 & 0xFF) != 0x24) { + return; + } + + if (*(u8 **)(a0 + 0x90) == D_801BD678) { + if (D_800B99DA % 3 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } else if (*(u8 **)(a0 + 0x90) == D_801BE038 && *(u16 *)(a0 + 2) == 0xB) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } else { + __asm__("" ::: "memory"); + if ((*(u8 **)(a0 + 0x90) == D_801BE130 || *(u8 **)(a0 + 0x90) == D_801BDCF8) && + D_800B99DA % 6 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } +} + INCLUDE_ASM("asm/ov_SC06_032/nonmatchings/ov_SC06_032_jr_80181014", func_80182588); diff --git a/src/ov_SC06_033/ov_SC06_033_jr_80184CF8.c b/src/ov_SC06_033/ov_SC06_033_jr_80184CF8.c index 5940b1296..25f116e3d 100644 --- a/src/ov_SC06_033/ov_SC06_033_jr_80184CF8.c +++ b/src/ov_SC06_033/ov_SC06_033_jr_80184CF8.c @@ -3319,7 +3319,52 @@ INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_80184CF8", func_80185F6 INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_80184CF8", func_801860E4); -INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_80184CF8", func_80186144); + +/* Family exemplar (S48 wave-4). Two compiler-shape levers used, both already + * documented in the cookbook: + * - §164z (func_8018A974 refutation): a non-volatile `__asm__("" ::: "memory")` + * barrier forces a genuine second `lw` reload of *(a0+0x90) at the C/D-group + * check, matching the target's register-clash reload, at zero extra stack cost. + * - §45 Lever 4: the call is written literally duplicated in each of the three + * arms rather than shared through one fall-through tail; gcc-2.7.2's jump.c + * cross-jumps the duplicates back together, which is what lets `addiu $a0,$zero,0x53` + * (not the unrelated stack-arg constant 0x14) win both branch-delay slots. + */ + +extern s32 func_801469C8(int, void*, int, int, u16, int, int, int); + +void func_80186144(s32 a0, s32 a1) { + + extern u8 D_801C6A0C[]; + extern u8 D_801C73CC[]; + extern u8 D_801C74C4[]; + extern u8 D_801C708C[]; + extern u16 D_800B99DA; + if ((*(s16 *)(a0 + 0x70) & 0x8000) == 0) { + return; + } + if ((a1 & 0xFF) != 0x24) { + return; + } + + if (*(u8 **)(a0 + 0x90) == D_801C6A0C) { + if (D_800B99DA % 3 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } else if (*(u8 **)(a0 + 0x90) == D_801C73CC && *(u16 *)(a0 + 2) == 0xB) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } else { + __asm__("" ::: "memory"); + if ((*(u8 **)(a0 + 0x90) == D_801C74C4 || *(u8 **)(a0 + 0x90) == D_801C708C) && + D_800B99DA % 6 == 0) { + ((s32 (*)(int, void *, int, int, s32, int, int, int))func_801469C8)(0x53, (void *)a0, *(s16 *)(a0 + 6), (s16)(*(u16 *)(a0 + 0xA) - 0xA0), + *(s16 *)(a0 + 0xE), 0, 0, 0x14); + } + } +} + INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_80184CF8", func_8018626C);