diff --git a/asm/MetroidPrime/CWeaponMgr.s b/asm/MetroidPrime/CWeaponMgr.s index dde031f7..f008f2e6 100644 --- a/asm/MetroidPrime/CWeaponMgr.s +++ b/asm/MetroidPrime/CWeaponMgr.s @@ -323,7 +323,7 @@ lbl_800C20C4: /* 800C20DC 000BF03C 38 05 00 01 */ addi r0, r5, 1 /* 800C20E0 000BF040 7C 08 39 2E */ stwx r0, r8, r7 /* 800C20E4 000BF044 80 A4 00 10 */ lwz r5, 0x10(r4) -/* 800C20E8 000BF048 48 00 02 3D */ bl sub_800c2324 +/* 800C20E8 000BF048 48 00 02 3D */ bl "insert_into__Q24rstl215red_black_tree<9TUniqueId,Q24rstl47pair<9TUniqueId,Q24rstl21reserved_vector>,0,Q24rstl67select1st>>,Q24rstl16less<9TUniqueId>,Q24rstl17rmemory_allocator>FPQ34rstl215red_black_tree<9TUniqueId,Q24rstl47pair<9TUniqueId,Q24rstl21reserved_vector>,0,Q24rstl67select1st>>,Q24rstl16less<9TUniqueId>,Q24rstl17rmemory_allocator>4nodeRCQ24rstl47pair<9TUniqueId,Q24rstl21reserved_vector>" /* 800C20EC 000BF04C 28 1F 00 00 */ cmplwi r31, 0 /* 800C20F0 000BF050 41 82 00 70 */ beq lbl_800C2160 /* 800C20F4 000BF054 80 A1 00 64 */ lwz r5, 0x64(r1) @@ -497,8 +497,8 @@ __dl__FPv: /* 800C231C 000BF27C 38 21 00 10 */ addi r1, r1, 0x10 /* 800C2320 000BF280 4E 80 00 20 */ blr -.global sub_800c2324 -sub_800c2324: +.global "insert_into__Q24rstl215red_black_tree<9TUniqueId,Q24rstl47pair<9TUniqueId,Q24rstl21reserved_vector>,0,Q24rstl67select1st>>,Q24rstl16less<9TUniqueId>,Q24rstl17rmemory_allocator>FPQ34rstl215red_black_tree<9TUniqueId,Q24rstl47pair<9TUniqueId,Q24rstl21reserved_vector>,0,Q24rstl67select1st>>,Q24rstl16less<9TUniqueId>,Q24rstl17rmemory_allocator>4nodeRCQ24rstl47pair<9TUniqueId,Q24rstl21reserved_vector>" +"insert_into__Q24rstl215red_black_tree<9TUniqueId,Q24rstl47pair<9TUniqueId,Q24rstl21reserved_vector>,0,Q24rstl67select1st>>,Q24rstl16less<9TUniqueId>,Q24rstl17rmemory_allocator>FPQ34rstl215red_black_tree<9TUniqueId,Q24rstl47pair<9TUniqueId,Q24rstl21reserved_vector>,0,Q24rstl67select1st>>,Q24rstl16less<9TUniqueId>,Q24rstl17rmemory_allocator>4nodeRCQ24rstl47pair<9TUniqueId,Q24rstl21reserved_vector>": /* 800C2324 000BF284 94 21 FF E0 */ stwu r1, -0x20(r1) /* 800C2328 000BF288 7C 08 02 A6 */ mflr r0 /* 800C232C 000BF28C 28 05 00 00 */ cmplwi r5, 0 diff --git a/configure.py b/configure.py index 3346d6f7..e9ee8863 100755 --- a/configure.py +++ b/configure.py @@ -120,7 +120,7 @@ LIBS = [ "MetroidPrime/CParticleDatabase", "MetroidPrime/Tweaks/CTweakGunRes", "MetroidPrime/CTargetReticles", - "MetroidPrime/CWeaponMgr", + ["MetroidPrime/CWeaponMgr", False], ["MetroidPrime/ScriptObjects/CScriptPickup", True], ["MetroidPrime/CDamageInfo", False], ["MetroidPrime/CMemoryDrawEnum", True], diff --git a/include/MetroidPrime/CWeaponMgr.hpp b/include/MetroidPrime/CWeaponMgr.hpp index 430c29e8..53007b47 100644 --- a/include/MetroidPrime/CWeaponMgr.hpp +++ b/include/MetroidPrime/CWeaponMgr.hpp @@ -4,13 +4,38 @@ #include "types.h" #include "MetroidPrime/TGameTypes.hpp" +#include "MetroidPrime/Weapons/WeaponTypes.hpp" #include "rstl/map.hpp" #include "rstl/reserved_vector.hpp" class CWeaponMgr { +public: + typedef rstl::reserved_vector< int, 15 > Vec; + + CWeaponMgr(); + void Remove(TUniqueId); + void IncrCount(TUniqueId, EWeaponType); + void DecrCount(TUniqueId, EWeaponType); + int GetNumActive(TUniqueId, EWeaponType) const; + + void Add(TUniqueId uid, EWeaponType type) { + rstl::pair< TUniqueId, Vec > newIndex(uid, Vec(0)); + newIndex.second[type] += 1; + x0_weapons.insert(newIndex); + } + + Vec* GetIndex(TUniqueId uid) const { + rstl::map< TUniqueId, Vec >::const_iterator iter = x0_weapons.find(uid); + + if (iter != x0_weapons.end()) { + return const_cast(&iter->second); + } + return nullptr; + } + private: - rstl::map< TUniqueId, rstl::reserved_vector< int, 15 > > x0_weapons; + rstl::map< TUniqueId, Vec > x0_weapons; }; CHECK_SIZEOF(CWeaponMgr, 0x14); diff --git a/include/MetroidPrime/TGameTypes.hpp b/include/MetroidPrime/TGameTypes.hpp index 4fff46a0..44b2e4e3 100644 --- a/include/MetroidPrime/TGameTypes.hpp +++ b/include/MetroidPrime/TGameTypes.hpp @@ -53,7 +53,7 @@ struct TUniqueId { bool operator==(const TUniqueId& other) const { return value == other.value; } bool operator!=(const TUniqueId& other) const { return value != other.value; } - bool operator<(const TUniqueId& other) const; // TODO + bool operator<(const TUniqueId& other) const { return value < other.value; } private: }; diff --git a/include/rstl/map.hpp b/include/rstl/map.hpp index 6cf825e5..34a4d07b 100644 --- a/include/rstl/map.hpp +++ b/include/rstl/map.hpp @@ -18,16 +18,20 @@ private: typedef red_black_tree< K, value_type, 0, select1st< value_type >, Cmp, Alloc > rep_type; public: - // typedef typename rep_type::iterator iterator; + typedef typename rep_type::iterator iterator; typedef typename rep_type::const_iterator const_iterator; - void insert(const value_type& item) { inner.insert(item); } + iterator insert(const value_type& item) { return inner.insert(item); } const_iterator begin() const { return inner.begin(); } const_iterator end() const { return inner.end(); } + iterator find(const K& key) { return inner.find(key); } const_iterator find(const K& key) const { return inner.find(key); } + void erase(iterator it) { inner.erase(it); } + + rep_type& get_inner() { return inner; } // hack for CWeaponMgr inlining depth private: rep_type inner; }; diff --git a/include/rstl/red_black_tree.hpp b/include/rstl/red_black_tree.hpp index 72bd48b9..929fa317 100644 --- a/include/rstl/red_black_tree.hpp +++ b/include/rstl/red_black_tree.hpp @@ -29,6 +29,7 @@ enum node_color { void rbtree_rebalance(void*, void*); void* rbtree_traverse_forward(const void*, void*); +void* rbtree_rebalance_for_erase(void* header_void, void* node_void); template < typename T, typename P, int U, typename S = select1st< P >, typename Cmp = less< T >, typename Alloc = rmemory_allocator > @@ -45,6 +46,9 @@ private: : mLeft(left), mRight(right), mParent(parent), mColor(color) { construct(get_value(), value); } + ~node() { + get_value()->~P(); + } P* get_value() { return reinterpret_cast< P* >(&mValue); } const P* get_value() const { return reinterpret_cast< const P* >(&mValue); } @@ -106,6 +110,10 @@ public: }; struct iterator : public const_iterator { iterator(node* node, const header* header, bool b) : const_iterator(node, header, b) {} + + P* operator->() { return mNode->get_value(); } + P* operator*() { return mNode->get_value(); } + node* get_node() { return mNode; } }; red_black_tree() : x0_(0), x1_(0), x4_count(0) {} @@ -144,6 +152,35 @@ public: return const_iterator(needle, &x8_header, false); } + iterator find(const T& key) { + node* n = x8_header.get_root(); + node* needle = nullptr; + while (n != nullptr) { + if (!x2_cmp(x3_selector(*n->get_value()), key)) { + needle = n; + n = n->get_left(); + } else { + n = n->get_right(); + } + } + bool noResult = false; + if (needle == nullptr || x2_cmp(key, x3_selector(*needle->get_value()))) { + noResult = true; + } + if (noResult) { + needle = nullptr; + } + return iterator(needle, &x8_header, false); + } + + iterator erase(iterator it) { + node* node = it.get_node(); + ++it; + free_node(rebalance_for_erase(node)); + x4_count--; + return it; + } + void clear() { node* root = x8_header.get_root(); if (root != nullptr) { @@ -186,6 +223,8 @@ private: } void rebalance(node* n) { rbtree_rebalance(&x8_header, n); } + + node* rebalance_for_erase(node* n) { return static_cast(rbtree_rebalance_for_erase(&x8_header, n)); } }; static bool kUnknownValueNewRoot = true; diff --git a/src/MetroidPrime/CWeaponMgr.cpp b/src/MetroidPrime/CWeaponMgr.cpp new file mode 100644 index 00000000..dae290d5 --- /dev/null +++ b/src/MetroidPrime/CWeaponMgr.cpp @@ -0,0 +1,50 @@ +#include "MetroidPrime/CWeaponMgr.hpp" + +CWeaponMgr::CWeaponMgr() {} + +void CWeaponMgr::Remove(TUniqueId uid) { + rstl::map< TUniqueId, Vec >::iterator iter = x0_weapons.find(uid); + if (iter != x0_weapons.end()) { + x0_weapons.get_inner().erase(iter); + } +} + +void CWeaponMgr::IncrCount(TUniqueId uid, EWeaponType type) { + Vec* vec = GetIndex(uid); + if (vec == nullptr) { + Add(uid, type); + } else { + (*vec)[type]++; + } +} + +void CWeaponMgr::DecrCount(TUniqueId uid, EWeaponType type) { + Vec* vecP = GetIndex(uid); + if (!vecP) { + return; + } + + Vec& vec = *vecP; + vec[type]--; + + bool found = true; + rstl::reserved_vector< int, 15 >::iterator vit = vec.begin(), end = vec.end(); + for (; vit != end; ++vit) { + if (*vit > 0) { + found = false; + break; + } + } + if (found) { + Remove(uid); + } +} + +int CWeaponMgr::GetNumActive(TUniqueId uid, EWeaponType type) const { + Vec* vecP = GetIndex(uid); + if (vecP) { + return (*vecP)[type]; + } else { + return 0; + } +}