From 883f3429a73dd79a0902478c5897ff55f2a7c685 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sat, 27 Jan 2024 11:48:50 -0500 Subject: [PATCH] Implement/match LegoWorld::Destroy (and destructor) (#492) * Implement/match LegoWorld::Destroy * Match * Match --- CMakeLists.txt | 1 + .../legoomni/include/legobuildingmanager.h | 1 + LEGO1/lego/legoomni/include/legoentity.h | 4 +- .../include/legolocomotionanimpresenter.h | 8 ++ .../lego/legoomni/include/legoplantmanager.h | 1 + .../lego/legoomni/include/legosoundmanager.h | 7 +- .../legoomni/include/legounknown100d6b4c.h | 15 +++ LEGO1/lego/legoomni/include/legoworld.h | 5 +- .../src/audio/legounknown100d6b4c.cpp | 7 + .../src/build/legobuildingmanager.cpp | 6 + .../legoomni/src/common/legoplantmanager.cpp | 6 + LEGO1/lego/legoomni/src/entity/legoworld.cpp | 125 +++++++++++++++++- 12 files changed, 177 insertions(+), 9 deletions(-) create mode 100644 LEGO1/lego/legoomni/include/legounknown100d6b4c.h create mode 100644 LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index da1c41f6..388c4777 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,6 +225,7 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/audio/legocachesound.cpp LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp + LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp LEGO1/lego/legoomni/src/build/buildingentity.cpp LEGO1/lego/legoomni/src/build/dunebuggy.cpp diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index d96d9583..7bde7ad9 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -22,6 +22,7 @@ class LegoBuildingManager : public MxCore { static void configureLegoBuildingManager(MxS32); void FUN_1002fa00(); + void FUN_1002fb30(); // SYNTHETIC: LEGO1 0x1002f940 // LegoBuildingManager::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index 12b1ecf1..99813972 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -13,7 +13,8 @@ class LegoEntity : public MxEntity { public: enum { - c_bit1 = 0x01 + c_bit1 = 0x01, + c_bit2 = 0x02 }; // Inlined at 0x100853f7 @@ -58,6 +59,7 @@ class LegoEntity : public MxEntity { void SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool); inline LegoROI* GetROI() { return m_roi; } + inline MxU8 GetFlags() { return m_flags; } protected: void Init(); diff --git a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h index cb7e3334..ab3da3eb 100644 --- a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h @@ -35,6 +35,14 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { // SYNTHETIC: LEGO1 0x1006cfe0 // LegoLocomotionAnimPresenter::`scalar deleting destructor' + inline void DecrementUnknown0xd4() + { + if (m_unk0xd4) + --m_unk0xd4; + } + + inline undefined2 GetUnknown0xd4() { return m_unk0xd4; } + private: void Init(); void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h index e199f11b..a47825f3 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -21,6 +21,7 @@ class LegoPlantManager : public MxCore { } void FUN_10026360(undefined4 p_world); + void FUN_100263a0(undefined4 p_und); // SYNTHETIC: LEGO1 0x100262a0 // LegoPlantManager::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legosoundmanager.h b/LEGO1/lego/legoomni/include/legosoundmanager.h index 0e4bbbbd..b1afffe3 100644 --- a/LEGO1/lego/legoomni/include/legosoundmanager.h +++ b/LEGO1/lego/legoomni/include/legosoundmanager.h @@ -1,6 +1,7 @@ #ifndef LEGOSOUNDMANAGER_H #define LEGOSOUNDMANAGER_H +#include "legounknown100d6b4c.h" #include "mxsoundmanager.h" // VTABLE: LEGO1 0x100d6b10 @@ -17,12 +18,14 @@ class LegoSoundManager : public MxSoundManager { // SYNTHETIC: LEGO1 0x10029920 // LegoSoundManager::`scalar deleting destructor' + inline LegoUnknown100d6b4c* GetUnknown0x40() { return m_unk0x40; } + private: void Init(); void Destroy(MxBool p_fromDestructor); - undefined4 m_unk0x3c; - undefined4 m_unk0x40; + undefined4 m_unk0x3c; // 0x3c + LegoUnknown100d6b4c* m_unk0x40; // 0x40 }; #endif // LEGOSOUNDMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legounknown100d6b4c.h b/LEGO1/lego/legoomni/include/legounknown100d6b4c.h new file mode 100644 index 00000000..9b10bd50 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legounknown100d6b4c.h @@ -0,0 +1,15 @@ +#ifndef LEGOUNKNOWN100D6B4C_H +#define LEGOUNKNOWN100D6B4C_H + +#include "decomp.h" + +class LegoCacheSound; + +// VTABLE: LEGO1 0x100d6b4c +// SIZE 0x20 +class LegoUnknown100d6b4c { +public: + void FUN_1003dc40(LegoCacheSound** p_und); +}; + +#endif // LEGOUNKNOWN100D6B4C_H diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index 51b47fbf..2e0fcee6 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -79,7 +79,7 @@ class LegoWorld : public LegoEntity { LegoCameraController* m_cameraController; // 0x98 LegoEntityList* m_entityList; // 0x9c LegoCacheSoundList* m_cacheSoundList; // 0xa0 - undefined m_unk0xa4; // 0xa4 + MxBool m_destroyed; // 0xa4 MxCoreSet m_set0xa8; // 0xa8 MxPresenterList m_controlPresenters; // 0xb8 MxCoreSet m_set0xd0; // 0xd0 @@ -122,6 +122,9 @@ class LegoWorld : public LegoEntity { // TEMPLATE: LEGO1 0x1001df00 // Set::~Set +// TEMPLATE: LEGO1 0x1001f590 +// list >::erase + // TEMPLATE: LEGO1 0x100208b0 // _Tree >::_Kfn,CoreSetCompare,allocator >::insert diff --git a/LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp b/LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp new file mode 100644 index 00000000..2ed5f178 --- /dev/null +++ b/LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp @@ -0,0 +1,7 @@ +#include "legounknown100d6b4c.h" + +// STUB: LEGO1 0x1003dc40 +void LegoUnknown100d6b4c::FUN_1003dc40(LegoCacheSound** p_und) +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp index ed890166..cb5fad99 100644 --- a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp @@ -33,6 +33,12 @@ void LegoBuildingManager::FUN_1002fa00() // TODO } +// STUB: LEGO1 0x1002fb30 +void LegoBuildingManager::FUN_1002fb30() +{ + // TODO +} + // STUB: LEGO1 0x10030220 MxResult LegoBuildingManager::Tickle() { diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 193f5c8a..ec04cf6a 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -24,6 +24,12 @@ void LegoPlantManager::FUN_10026360(undefined4 p_world) // TODO } +// STUB: LEGO1 0x100263a0 +void LegoPlantManager::FUN_100263a0(undefined4 p_und) +{ + // TODO +} + // STUB: LEGO1 0x10026e00 MxResult LegoPlantManager::Tickle() { diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index 7454e5cd..e2a912ef 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -1,9 +1,13 @@ #include "legoworld.h" #include "legoanimpresenter.h" +#include "legobuildingmanager.h" #include "legocontrolmanager.h" #include "legoinputmanager.h" +#include "legolocomotionanimpresenter.h" #include "legoomni.h" +#include "legoplantmanager.h" +#include "legosoundmanager.h" #include "legoutil.h" #include "legovideomanager.h" #include "mxactionnotificationparam.h" @@ -26,7 +30,7 @@ LegoWorld::LegoWorld() : m_list0x68(TRUE) m_cameraController = NULL; m_entityList = NULL; m_cacheSoundList = NULL; - m_unk0xa4 = 0; // MxBool? + m_destroyed = FALSE; m_hideAnimPresenter = NULL; m_worldStarted = FALSE; @@ -45,10 +49,13 @@ MxBool LegoWorld::VTable0x64() return FALSE; } -// STUB: LEGO1 0x1001dfa0 +// FUNCTION: LEGO1 0x1001dfa0 LegoWorld::~LegoWorld() { - // TODO + Destroy(TRUE); + + TickleManager()->UnregisterClient(this); + NotificationManager()->Unregister(this); } // FUNCTION: LEGO1 0x1001e0b0 @@ -84,10 +91,118 @@ MxResult LegoWorld::Create(MxDSAction& p_dsAction) return SUCCESS; } -// STUB: LEGO1 0x1001e9d0 +// FUNCTION: LEGO1 0x1001e9d0 void LegoWorld::Destroy(MxBool p_fromDestructor) { - // TODO + m_destroyed = TRUE; + + if (GetCurrentWorld() == this) { + ControlManager()->FUN_10028df0(NULL); + SetCurrentWorld(NULL); + } + + m_list0x68.DeleteAll(); + + if (m_cameraController) { + delete m_cameraController; + m_cameraController = NULL; + } + + MxPresenterListCursor animPresenterCursor(&m_animPresenters); + MxPresenter* presenter; + + while (animPresenterCursor.First(presenter)) { + animPresenterCursor.Detach(); + + MxDSAction* action = presenter->GetAction(); + if (action) { + if (presenter->IsA("LegoLocomotionAnimPresenter")) { + LegoLocomotionAnimPresenter* animPresenter = (LegoLocomotionAnimPresenter*) presenter; + + animPresenter->DecrementUnknown0xd4(); + if (animPresenter->GetUnknown0xd4() == 0) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + else { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + } + + while (!m_set0xa8.empty()) { + MxCoreSet::iterator it = m_set0xa8.begin(); + MxCore* object = *it; + m_set0xa8.erase(it); + + if (object->IsA("MxPresenter")) { + MxPresenter* presenter = (MxPresenter*) object; + MxDSAction* action = presenter->GetAction(); + + if (action) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + else + delete object; + } + + MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); + + while (controlPresenterCursor.First(presenter)) { + controlPresenterCursor.Detach(); + + MxDSAction* action = presenter->GetAction(); + if (action) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + + if (m_unk0xec != -1 && m_set0xd0.empty()) { + PlantManager()->FUN_100263a0(m_unk0xec); + BuildingManager()->FUN_1002fb30(); + } + + if (m_entityList) { + LegoEntityListCursor cursor(m_entityList); + LegoEntity* entity; + + while (cursor.First(entity)) { + cursor.Detach(); + + if (!(entity->GetFlags() & LegoEntity::c_bit2)) + delete entity; + } + + delete m_entityList; + m_entityList = NULL; + } + + if (m_cacheSoundList) { + LegoCacheSoundListCursor cursor(m_cacheSoundList); + LegoCacheSound* sound; + + while (cursor.First(sound)) { + cursor.Detach(); + SoundManager()->GetUnknown0x40()->FUN_1003dc40(&sound); + } + + delete m_cacheSoundList; + m_cacheSoundList = NULL; + } + + while (!m_list0xe0.empty()) { + AutoROI* roi = m_list0xe0.front(); + m_list0xe0.pop_front(); + delete roi; + } + + if (!p_fromDestructor) + LegoEntity::Destroy(FALSE); } // FUNCTION: LEGO1 0x1001f5e0