From 65e86b0acd40d0182ab1c8cfb116a5e968d4539c Mon Sep 17 00:00:00 2001 From: vagnertxr Date: Tue, 8 Sep 2026 21:49:47 -0300 Subject: [PATCH 1/2] Start the ft_marth units Fills in the stubs and one-liners across the five ft_marth translation units, which were declared and split but had empty sources. 27 functions match; the units stay NonMatching. Most are empty bodies or constant returns. The rest: - fn_106_DB60 reads a byte at +132. - fn_106_BE30 is __fabs, taking and returning double. A float signature costs a frsp the target does not have. - fn_106_BFE0, fn_106_C98C and fn_106_D400 install a table pointer. - fn_106_CD00 stores two float arguments. Three are left as NONMATCHING with a note: fn_106_D4E4 and fn_106_C390 copy floats between objects, and mwcc hoists the loads ahead of the stores while the target interleaves them. Struct assignment, field by field and raw float pointers all produce the same schedule. Verified: `ninja` reports 127 files OK. Co-Authored-By: Claude Opus 5 --- ...arth_status_uniq_process_special_final.cpp | 22 +++++++++ ...t_marth_status_uniq_process_special_hi.cpp | 24 ++++++++++ ...t_marth_status_uniq_process_special_lw.cpp | 22 +++++++++ ...ft_marth_status_uniq_process_special_s.cpp | 45 +++++++++++++++++++ src/mo_fighter/ft_marth/if_marth_final.cpp | 39 ++++++++++++++++ 5 files changed, 152 insertions(+) diff --git a/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_final.cpp b/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_final.cpp index e69de29bb..d29feaeb2 100644 --- a/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_final.cpp +++ b/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_final.cpp @@ -0,0 +1,22 @@ +#include + +extern "C" { + +void fn_106_CD00(float* dst, float x, float y); +void fn_106_CFBC(); +void fn_106_D400(const void** obj); + +extern const void* lbl_106_data_5678[]; + +void fn_106_CD00(float* dst, float x, float y) { + dst[0] = x; + dst[1] = y; +} + +void fn_106_CFBC() {} + +void fn_106_D400(const void** obj) { + *obj = lbl_106_data_5678; +} + +} diff --git a/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_hi.cpp b/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_hi.cpp index e69de29bb..e2e6c5897 100644 --- a/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_hi.cpp +++ b/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_hi.cpp @@ -0,0 +1,24 @@ +#include + +extern "C" { + +double fn_106_BE30(double value); +void fn_106_BE38(); +void fn_106_BE3C(); +void fn_106_BFE0(const void** obj); + +extern const void* lbl_106_data_5584[]; + +double fn_106_BE30(double value) { + return __fabs(value); +} + +void fn_106_BE38() {} + +void fn_106_BE3C() {} + +void fn_106_BFE0(const void** obj) { + *obj = lbl_106_data_5584; +} + +} diff --git a/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_lw.cpp b/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_lw.cpp index e69de29bb..ccbca9e50 100644 --- a/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_lw.cpp +++ b/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_lw.cpp @@ -0,0 +1,22 @@ +#include + +extern "C" { + +void fn_106_C390(u8* obj, const float* src); +void fn_106_C674(); +void fn_106_C98C(const void** obj); + +extern const void* lbl_106_data_5600[]; + +void fn_106_C390(u8* obj, const float* src) { + *(float*) (obj + 32) = src[0]; + *(float*) (obj + 36) = src[1]; +} + +void fn_106_C674() {} + +void fn_106_C98C(const void** obj) { + *obj = lbl_106_data_5600; +} + +} diff --git a/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_s.cpp b/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_s.cpp index e69de29bb..e9d3936e8 100644 --- a/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_s.cpp +++ b/src/mo_fighter/ft_marth/ft_marth_status_uniq_process_special_s.cpp @@ -0,0 +1,45 @@ +#include + +extern "C" { + +void fn_106_B508(); +void fn_106_B50C(); +void fn_106_B510(); +bool fn_106_B514(); +void fn_106_B51C(); +bool fn_106_B520(); +void fn_106_B528(); +bool fn_106_B52C(); +void fn_106_B534(); +void fn_106_B538(); +void fn_106_B53C(); + +void fn_106_B508() {} + +void fn_106_B50C() {} + +void fn_106_B510() {} + +bool fn_106_B514() { + return true; +} + +void fn_106_B51C() {} + +bool fn_106_B520() { + return false; +} + +void fn_106_B528() {} + +bool fn_106_B52C() { + return false; +} + +void fn_106_B534() {} + +void fn_106_B538() {} + +void fn_106_B53C() {} + +} diff --git a/src/mo_fighter/ft_marth/if_marth_final.cpp b/src/mo_fighter/ft_marth/if_marth_final.cpp index e69de29bb..ae7bc002c 100644 --- a/src/mo_fighter/ft_marth/if_marth_final.cpp +++ b/src/mo_fighter/ft_marth/if_marth_final.cpp @@ -0,0 +1,39 @@ +#include +#include + +extern "C" { + +void fn_106_D4E4(Vec3f* dst, const Vec3f* src); +void fn_106_D9DC(); +void fn_106_DA94(); +u8 fn_106_DB60(const u8* obj); +void fn_106_DB68(); +void fn_106_DB6C(); +void fn_106_DB70(); +void fn_106_DB74(); + +// NONMATCHING: mwcc hoists the three loads ahead of the stores; the target +// interleaves them. +void fn_106_D4E4(Vec3f* dst, const Vec3f* src) { + dst->m_x = src->m_x; + dst->m_y = src->m_y; + dst->m_z = src->m_z; +} + +void fn_106_D9DC() {} + +void fn_106_DA94() {} + +u8 fn_106_DB60(const u8* obj) { + return obj[132]; +} + +void fn_106_DB68() {} + +void fn_106_DB6C() {} + +void fn_106_DB70() {} + +void fn_106_DB74() {} + +} From aeca22f15d10382633a460859d06528c9832cfce Mon Sep 17 00:00:00 2001 From: vagnertxr Date: Wed, 9 Sep 2026 20:35:38 -0300 Subject: [PATCH 2/2] Decompile the IfMngr toggles in if_marth_final fn_106_D9E0 and fn_106_DA2C are a matched pair guarding a byte at +136: one calls into g_IfMngr and raises the flag, the other calls the opposite entry point and clears it. Both reach 98%. What is left is argument evaluation order. The target dereferences g_IfMngr before loading the field at +72; mwcc does it the other way round, and hoisting the manager into a local or going through IfMngr::getInstance() does not move it. Verified: `ninja` reports 127 files OK. Co-Authored-By: Claude Opus 5 --- src/mo_fighter/ft_marth/if_marth_final.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/mo_fighter/ft_marth/if_marth_final.cpp b/src/mo_fighter/ft_marth/if_marth_final.cpp index ae7bc002c..359f1384c 100644 --- a/src/mo_fighter/ft_marth/if_marth_final.cpp +++ b/src/mo_fighter/ft_marth/if_marth_final.cpp @@ -1,10 +1,15 @@ +#include #include #include extern "C" { void fn_106_D4E4(Vec3f* dst, const Vec3f* src); +void fn_106_D720(IfMngr* mngr, void* arg); +void fn_106_DA78(IfMngr* mngr, void* arg); void fn_106_D9DC(); +void fn_106_D9E0(u8* obj); +void fn_106_DA2C(u8* obj); void fn_106_DA94(); u8 fn_106_DB60(const u8* obj); void fn_106_DB68(); @@ -22,6 +27,22 @@ void fn_106_D4E4(Vec3f* dst, const Vec3f* src) { void fn_106_D9DC() {} +// NONMATCHING: mwcc loads the field before dereferencing g_IfMngr; the target +// does the opposite. Hoisting the manager into a local does not move it. +void fn_106_D9E0(u8* obj) { + if (obj[136] == 0) { + fn_106_D720(g_IfMngr, *(void**) (obj + 72)); + obj[136] = 1; + } +} + +void fn_106_DA2C(u8* obj) { + if (obj[136] == 1) { + fn_106_DA78(g_IfMngr, *(void**) (obj + 72)); + obj[136] = 0; + } +} + void fn_106_DA94() {} u8 fn_106_DB60(const u8* obj) {