#include "pso/TObject.h" #define MATCHING #define o(name) const char *name##_name = #name; OBJECT_NAMES #undef o void debug_print(const char *fmt) { } bool TObject::toggle_flag_9_if_flag_10_is_clear() { if (get_flags(0x400)) { return false; } if (!get_flag_9()) { set_flag_9(); return true; } else { clear_flag_9(); return false; } } void TObject::free(void *ptr) { } void *TObject::alloc(unsigned long size) { return NULL; } bool TObject::is_flag_0_clear_for_all_parents() { for (TObject *parent = this; parent != NULL; parent = parent->up) { if (parent->get_flags(1)) { return false; } } return true; } int TObject::get_node_count() { // NOTE: The order of the variable declarations matter for matching. TObject *child; int node_count = 0; for (child = this->down; child != NULL; child = child->next) { node_count += child->get_node_count() + 1; } return node_count; } void TObject::log(const char *str) { debug_print(str); } void TObject::empty_func2() { } void TObject::func_0x14() { } void TObject::func_0x10() { } void TObject::run_task() { } void TObject::set_parent(TObject *parent) { remove_parent(); add_parent(parent, true); } void TObject::empty_func() { } void TObject::call_func_0x10_for_each_node2() { for (TObject *child = this->down; child != NULL; child = child->next) { if (child->get_flags(0x200)) { child->func_0x10(); child->clear_flag_9(); } child->call_func_0x10_for_each_node2(); } } void TObject::call_func_0x14_for_each_node() { for (TObject *child = this->down; child != NULL; child = child->next) { if (!child->get_flags(0x100)) { child->func_0x14(); child->call_func_0x14_for_each_node(); } } } void TObject::call_func_0x10_for_each_node() { for (TObject *child = this->down; child != NULL; child = child->next) { if (!child->get_flags(0x10)) { child->func_0x10(); child->call_func_0x10_for_each_node(); } } } #ifndef MATCHING // Near perfect match, just a single register allocation issue. void TObject::run_tasks() { TObject *child = this->down; while (this->down != NULL && child != NULL) { TObject *node = child; child = child->next; if (node->get_flags(0x0f)) { if (node->get_flags(1)) { node->clear_flags(1); if (!node->get_flags(0x20)) { delete node; } else { // Clearing child's flags with nothing here // causes the redundant load to appear. child->clear_flags(0); if (node->get_flags(2)) { node->delete_children(); node->run_task(); node->clear_flags(2); } if (!node->get_flags(4)) { // Adding this here somehow causes the // dead code to be compiled. // Register allocation still wrong. // If `node` was used, it'd use the // proper register, but it'd also add // an unwanted `sth`. child->clear_flags(0); } } } } else { node->run_task(); node->run_tasks(); } } } #else asm void TObject::run_tasks() { nofralloc /* 80229828 9421FFE0 */ stwu r1, -0x20(r1) /* 8022982C 7C0802A6 */ mflr r0 /* 80229830 90010024 */ stw r0, 0x24(r1) /* 80229834 BFA10014 */ stmw r29, 0x14(r1) /* 80229838 7C7D1B78 */ mr r29, r3 /* 8022983C 83E30014 */ lwz r31, 0x14(r3) /* 80229840 480000B8 */ b lbl_802298f8 lbl_80229844: /* 80229844 7FFEFB78 */ mr r30, r31 /* 80229848 83FF000C */ lwz r31, 0xc(r31) /* 8022984C A07E0004 */ lhz r3, 4(r30) /* 80229850 5460073F */ clrlwi. r0, r3, 0x1c /* 80229854 41820088 */ beq- lbl_802298dc /* 80229858 546007FF */ clrlwi. r0, r3, 0x1f /* 8022985C 4182003C */ beq- lbl_80229898 /* 80229860 5460043C */ rlwinm r0, r3, 0, 0x10, 0x1e /* 80229864 B01E0004 */ sth r0, 4(r30) /* 80229868 A01E0004 */ lhz r0, 4(r30) /* 8022986C 540006B5 */ rlwinm. r0, r0, 0, 0x1a, 0x1a /* 80229870 40820028 */ bne- lbl_80229898 /* 80229874 281E0000 */ cmplwi r30, 0 /* 80229878 41820080 */ beq- lbl_802298f8 /* 8022987C 7FC3F378 */ mr r3, r30 /* 80229880 38800001 */ li r4, 0x1 /* 80229884 819E0018 */ lwz r12, 0x18(r30) /* 80229888 818C0008 */ lwz r12, 8(r12) /* 8022988C 7D8903A6 */ mtctr r12 /* 80229890 4E800421 */ bctrl /* 80229894 48000064 */ b lbl_802298f8 lbl_80229898: /* 80229898 A01E0004 */ lhz r0, 4(r30) /* 8022989C 540007BD */ rlwinm. r0, r0, 0, 0x1e, 0x1e /* 802298A0 4182002C */ beq- lbl_802298cc /* 802298A4 7FC3F378 */ mr r3, r30 /* 802298A8 480000C1 */ bl delete_children /* 802298AC 7FC3F378 */ mr r3, r30 /* 802298B0 819E0018 */ lwz r12, 0x18(r30) /* 802298B4 818C000C */ lwz r12, 0xc(r12) /* 802298B8 7D8903A6 */ mtctr r12 /* 802298BC 4E800421 */ bctrl /* 802298C0 A01E0004 */ lhz r0, 4(r30) /* 802298C4 540007FA */ rlwinm r0, r0, 0, 0x1f, 0x1d /* 802298C8 B01E0004 */ sth r0, 4(r30) lbl_802298cc: /* 802298CC A07E0004 */ lhz r3, 4(r30) /* 802298D0 5460077B */ rlwinm. r0, r3, 0, 0x1d, 0x1d /* 802298D4 40820024 */ bne- lbl_802298f8 /* 802298D8 48000020 */ b lbl_802298f8 lbl_802298dc: /* 802298DC 7FC3F378 */ mr r3, r30 /* 802298E0 819E0018 */ lwz r12, 0x18(r30) /* 802298E4 818C000C */ lwz r12, 0xc(r12) /* 802298E8 7D8903A6 */ mtctr r12 /* 802298EC 4E800421 */ bctrl /* 802298F0 7FC3F378 */ mr r3, r30 /* 802298F4 4BFFFF35 */ bl run_tasks lbl_802298f8: /* 802298F8 801D0014 */ lwz r0, 0x14(r29) /* 802298FC 28000000 */ cmplwi r0, 0 /* 80229900 4182000C */ beq- lbl_8022990c /* 80229904 281F0000 */ cmplwi r31, 0 /* 80229908 4082FF3C */ bne+ lbl_80229844 lbl_8022990c: /* 8022990C BBA10014 */ lmw r29, 0x14(r1) /* 80229910 80010024 */ lwz r0, 0x24(r1) /* 80229914 7C0803A6 */ mtlr r0 /* 80229918 38210020 */ addi r1, r1, 0x20 /* 8022991C 4E800020 */ blr } #endif void TObject::set_flag_0_for_each_node() { for (TObject *child = this->down; child != NULL; child = child->next) { child->set_flag_0(); child->set_flag_0_for_each_node(); } } void TObject::delete_children() { _delete_children(); } TObject::~TObject() { if (!get_flags(0x20)) { set_flags(0x20); _delete_children(); remove_parent(); } } TObject::TObject(TObject *parent) { flags = 0; up = parent; down = NULL; name = TObject_name; add_parent(parent, false); } void TObject::clear_flag_9() { clear_flags(0x200); } void TObject::set_flag_9() { set_flags(0x200); } u32 TObject::get_flag_9() { return get_flags(0x200); } void TObject::set_flag_0() { set_flags(1); }