From 97b3dcaa2c7f6de6edcc69f5f34cd880157f7aff Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 5 Sep 2024 19:06:40 -0400 Subject: [PATCH 1/8] Beta match* MxStreamer (#1099) * Beta addrs * Streamer changes * Typo and comment. One more beta addr * Rename member to m_controllers --- LEGO1/omni/include/mxatom.h | 7 ++ LEGO1/omni/include/mxbitset.h | 72 ++++++++++++++++ LEGO1/omni/include/mxmemorypool.h | 38 ++++++++ LEGO1/omni/include/mxnotificationparam.h | 9 ++ LEGO1/omni/include/mxparam.h | 6 ++ LEGO1/omni/include/mxstreamer.h | 43 ++++++++-- .../omni/src/notify/mxnotificationmanager.cpp | 1 + LEGO1/omni/src/stream/mxstreamer.cpp | 86 +++++++++++-------- 8 files changed, 222 insertions(+), 40 deletions(-) diff --git a/LEGO1/omni/include/mxatom.h b/LEGO1/omni/include/mxatom.h index 8d81fd6b..d7650bb7 100644 --- a/LEGO1/omni/include/mxatom.h +++ b/LEGO1/omni/include/mxatom.h @@ -74,6 +74,13 @@ class MxAtomId { MxBool operator!=(const MxAtomId& p_atomId) const { return this->m_internal != p_atomId.m_internal; } #endif + // TODO: + // BETA10 0x1007dc20 operator== + // BETA10 0x10096970 operator!= + + // FUNCTION: BETA10 0x10146dd0 + MxBool operator==(const char* p_internal) const { return p_internal && !strcmp(m_internal, p_internal); } + // FUNCTION: BETA10 0x10025d40 MxAtomId() { this->m_internal = 0; } diff --git a/LEGO1/omni/include/mxbitset.h b/LEGO1/omni/include/mxbitset.h index 415470d8..21677b5a 100644 --- a/LEGO1/omni/include/mxbitset.h +++ b/LEGO1/omni/include/mxbitset.h @@ -92,4 +92,76 @@ class MxBitset { MxU32 m_blocks[e_blocksRequired + 1]; // 0x00 }; +// TEMPLATE: BETA10 0x10146600 +// MxBitset<2>::MxBitset<2> + +// TEMPLATE: BETA10 0x101464e0 +// MxBitset<22>::MxBitset<22> + +// TEMPLATE: BETA10 0x10146510 +// MxBitset<22>::Tidy + +// TEMPLATE: BETA10 0x10146570 +// MxBitset<22>::Trim + +// TEMPLATE: BETA10 0x10146630 +// MxBitset<2>::Tidy + +// TEMPLATE: BETA10 0x10146690 +// MxBitset<2>::Trim + +// TEMPLATE: BETA10 0x10146880 +// MxBitset<22>::Size + +// TEMPLATE: BETA10 0x101469d0 +// MxBitset<2>::Size + +// TEMPLATE: BETA10 0x101587a0 +// MxBitset<22>::Reference::Flip + +// TEMPLATE: BETA10 0x101587d0 +// MxBitset<22>::Reference::operator int + +// TEMPLATE: BETA10 0x10158800 +// MxBitset<22>::operator[] + +// TEMPLATE: BETA10 0x10158830 +// MxBitset<22>::Reference::Reference + +// TEMPLATE: BETA10 0x10158860 +// MxBitset<22>::Flip + +// STUB: BETA10 0x101588b0 +// MxBitset<22>::Count + +// TEMPLATE: BETA10 0x10158930 +// MxBitset<22>::Test + +// TEMPLATE: BETA10 0x10158990 +// MxBitset<22>::Xran + +// TEMPLATE: BETA10 0x10158b70 +// MxBitset<2>::Reference::Flip + +// TEMPLATE: BETA10 0x10158ba0 +// MxBitset<2>::Reference::operator int + +// TEMPLATE: BETA10 0x10158bd0 +// MxBitset<2>::operator[] + +// TEMPLATE: BETA10 0x10158c00 +// MxBitset<2>::Reference::Reference + +// TEMPLATE: BETA10 0x10158c30 +// MxBitset<2>::Flip + +// STUB: BETA10 0x10158c80 +// MxBitset<2>::Count + +// TEMPLATE: BETA10 0x10158d00 +// MxBitset<2>::Test + +// TEMPLATE: BETA10 0x10158d60 +// MxBitset<2>::Xran + #endif // MXBITSET_H diff --git a/LEGO1/omni/include/mxmemorypool.h b/LEGO1/omni/include/mxmemorypool.h index cbd1ca40..f794108f 100644 --- a/LEGO1/omni/include/mxmemorypool.h +++ b/LEGO1/omni/include/mxmemorypool.h @@ -78,4 +78,42 @@ void MxMemoryPool::Release(MxU8* p_buf) MxTrace("Release> %d pool: busy %d blocks\n", m_blockSize, m_blockRef.Count()); } +// TEMPLATE: BETA10 0x101464a0 +// MxMemoryPool<64,22>::MxMemoryPool<64,22> + +// TEMPLATE: LEGO1 0x100b9100 +// TEMPLATE: BETA10 0x10146590 +// MxMemoryPool<64,22>::~MxMemoryPool<64,22> + +// TEMPLATE: BETA10 0x101465c0 +// MxMemoryPool<128,2>::MxMemoryPool<128,2> + +// TEMPLATE: LEGO1 0x100b9110 +// TEMPLATE: BETA10 0x101466b0 +// MxMemoryPool<128,2>::~MxMemoryPool<128,2> + +// TEMPLATE: BETA10 0x10146780 +// MxMemoryPool<64,22>::Allocate + +// TEMPLATE: BETA10 0x101468a0 +// MxMemoryPool<64,22>::GetPoolSize + +// TEMPLATE: BETA10 0x101468d0 +// MxMemoryPool<128,2>::Allocate + +// TEMPLATE: BETA10 0x101469f0 +// MxMemoryPool<128,2>::GetPoolSize + +// TEMPLATE: BETA10 0x10158610 +// MxMemoryPool<64,22>::Release + +// TEMPLATE: BETA10 0x101589e0 +// MxMemoryPool<128,2>::Release + +// TEMPLATE: BETA10 0x10158e50 +// MxMemoryPool<64,22>::Get + +// TEMPLATE: BETA10 0x10158f90 +// MxMemoryPool<128,2>::Get + #endif // MXMEMORYPOOL_H diff --git a/LEGO1/omni/include/mxnotificationparam.h b/LEGO1/omni/include/mxnotificationparam.h index 16b2e236..bf1d589b 100644 --- a/LEGO1/omni/include/mxnotificationparam.h +++ b/LEGO1/omni/include/mxnotificationparam.h @@ -35,16 +35,23 @@ enum NotificationId { }; // VTABLE: LEGO1 0x100d56e0 +// VTABLE: BETA10 0x101b86a8 // SIZE 0x0c class MxNotificationParam : public MxParam { public: MxNotificationParam() : m_type(c_notificationType0), m_sender(NULL) {} + + // FUNCTION: BETA10 0x10013490 MxNotificationParam(NotificationId p_type, MxCore* p_sender) : MxParam(), m_type(p_type), m_sender(p_sender) {} // FUNCTION: LEGO1 0x10010390 + // FUNCTION: BETA10 0x100135f0 virtual MxNotificationParam* Clone() const { return new MxNotificationParam(m_type, m_sender); } // vtable+0x04 + // FUNCTION: BETA10 0x100135c0 NotificationId GetNotification() const { return m_type; } + + // FUNCTION: BETA10 0x1003c960 MxCore* GetSender() const { return m_sender; } void SetNotification(NotificationId p_type) { m_type = p_type; } @@ -56,9 +63,11 @@ class MxNotificationParam : public MxParam { }; // SYNTHETIC: LEGO1 0x10010430 +// SYNTHETIC: BETA10 0x100136c0 // MxNotificationParam::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100104a0 +// SYNTHETIC: BETA10 0x10013740 // MxNotificationParam::~MxNotificationParam #endif // MXNOTIFICATIONPARAM_H diff --git a/LEGO1/omni/include/mxparam.h b/LEGO1/omni/include/mxparam.h index a266b12b..57df088e 100644 --- a/LEGO1/omni/include/mxparam.h +++ b/LEGO1/omni/include/mxparam.h @@ -3,16 +3,22 @@ // VTABLE: ISLE 0x40f018 // VTABLE: LEGO1 0x100d56e8 +// VTABLE: BETA10 0x101b86b4 // SIZE 0x04 class MxParam { public: // FUNCTION: ISLE 0x401530 // FUNCTION: LEGO1 0x10010360 + // FUNCTION: BETA10 0x10013540 virtual ~MxParam() {} }; +// SYNTHETIC: BETA10 0x10013710 +// MxParam::MxParam + // SYNTHETIC: ISLE 0x401540 // SYNTHETIC: LEGO1 0x10010370 +// SYNTHETIC: BETA10 0x10013570 // MxParam::`scalar deleting destructor' #endif // MXPARAM_H diff --git a/LEGO1/omni/include/mxstreamer.h b/LEGO1/omni/include/mxstreamer.h index a11decba..208f3ce1 100644 --- a/LEGO1/omni/include/mxstreamer.h +++ b/LEGO1/omni/include/mxstreamer.h @@ -17,9 +17,11 @@ typedef MxMemoryPool<64, 22> MxMemoryPool64; typedef MxMemoryPool<128, 2> MxMemoryPool128; // VTABLE: LEGO1 0x100dc760 +// VTABLE: BETA10 0x101c23c8 // SIZE 0x10 class MxStreamerNotification : public MxNotificationParam { public: + // FUNCTION: BETA10 0x10146e40 MxStreamerNotification(NotificationId p_type, MxCore* p_sender, MxStreamController* p_ctrlr) : MxNotificationParam(p_type, p_sender) { @@ -28,6 +30,7 @@ class MxStreamerNotification : public MxNotificationParam { MxNotificationParam* Clone() const override; + // FUNCTION: BETA10 0x10147190 MxStreamController* GetController() { return m_controller; } private: @@ -53,6 +56,7 @@ class MxStreamer : public MxCore { MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x100b9000 + // FUNCTION: BETA10 0x10145ee0 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x1010210c @@ -60,6 +64,7 @@ class MxStreamer : public MxCore { } // FUNCTION: LEGO1 0x100b9010 + // FUNCTION: BETA10 0x10145f00 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStreamer::ClassName()) || MxCore::IsA(p_name); @@ -74,6 +79,7 @@ class MxStreamer : public MxCore { MxResult FUN_100b99b0(MxDSAction* p_action); MxResult DeleteObject(MxDSAction* p_dsAction); + // FUNCTION: BETA10 0x10158db0 MxU8* GetMemoryBlock(MxU32 p_blockSize) { switch (p_blockSize) { @@ -91,6 +97,7 @@ class MxStreamer : public MxCore { return NULL; } + // FUNCTION: BETA10 0x10158570 void ReleaseMemoryBlock(MxU8* p_block, MxU32 p_blockSize) { switch (p_blockSize) { @@ -109,33 +116,57 @@ class MxStreamer : public MxCore { } private: - list m_openStreams; // 0x08 + list m_controllers; // 0x08 MxMemoryPool64 m_pool64; // 0x14 MxMemoryPool128 m_pool128; // 0x20 }; // clang-format off // TEMPLATE: LEGO1 0x100b9090 -// TEMPLATE: BETA10 0x10146720 +// TEMPLATE: BETA10 0x10146020 // list >::~list > // clang-format on -// TEMPLATE: LEGO1 0x100b9100 -// MxMemoryPool<64,22>::~MxMemoryPool<64,22> +// TEMPLATE: BETA10 0x10146090 +// list >::begin + +// TEMPLATE: BETA10 0x10146120 +// list >::end -// TEMPLATE: LEGO1 0x100b9110 -// MxMemoryPool<128,2>::~MxMemoryPool<128,2> +// TEMPLATE: BETA10 0x101461b0 +// list >::iterator::operator++ // SYNTHETIC: LEGO1 0x100b9120 +// SYNTHETIC: BETA10 0x101466e0 // MxStreamer::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100b9140 +// TEMPLATE: BETA10 0x10146720 // List::~List +// TEMPLATE: BETA10 0x10146ab0 +// list >::iterator::operator* + // SYNTHETIC: LEGO1 0x100b97b0 +// SYNTHETIC: BETA10 0x10146f80 // MxStreamerNotification::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100b9820 +// SYNTHETIC: BETA10 0x10146fc0 // MxStreamerNotification::~MxStreamerNotification +// TEMPLATE: BETA10 0x10147020 +// list >::iterator::operator== + +// TEMPLATE: BETA10 0x10147060 +// list >::push_back + +// TEMPLATE: BETA10 0x10147200 +// ??9@YAHABViterator@?$list@PAVMxStreamController@@V?$allocator@PAVMxStreamController@@@@@@0@Z + +// clang-format off +// TEMPLATE: BETA10 0x10147230 +// ?find@@YA?AViterator@?$list@PAVMxStreamController@@V?$allocator@PAVMxStreamController@@@@@@V12@0ABQAVMxStreamController@@@Z +// clang-format on + #endif // MXSTREAMER_H diff --git a/LEGO1/omni/src/notify/mxnotificationmanager.cpp b/LEGO1/omni/src/notify/mxnotificationmanager.cpp index 58c97e38..dec49818 100644 --- a/LEGO1/omni/src/notify/mxnotificationmanager.cpp +++ b/LEGO1/omni/src/notify/mxnotificationmanager.cpp @@ -63,6 +63,7 @@ MxResult MxNotificationManager::Create(MxU32 p_frequencyMS, MxBool p_createThrea } // FUNCTION: LEGO1 0x100ac6c0 +// FUNCTION: BETA10 0x10125b57 MxResult MxNotificationManager::Send(MxCore* p_listener, const MxNotificationParam& p_param) { AUTOLOCK(m_lock); diff --git a/LEGO1/omni/src/stream/mxstreamer.cpp b/LEGO1/omni/src/stream/mxstreamer.cpp index 2ed16223..c3a64cf9 100644 --- a/LEGO1/omni/src/stream/mxstreamer.cpp +++ b/LEGO1/omni/src/stream/mxstreamer.cpp @@ -37,8 +37,8 @@ MxResult MxStreamer::Create() // FUNCTION: BETA10 0x10145268 MxStreamer::~MxStreamer() { - while (!m_openStreams.empty()) { - MxStreamController* controller = m_openStreams.front(); + while (!m_controllers.empty()) { + MxStreamController* controller = m_controllers.front(); #ifdef COMPAT_MODE { @@ -49,7 +49,7 @@ MxStreamer::~MxStreamer() assert(controller->IsStoped(&MxDSAction())); #endif - m_openStreams.pop_front(); + m_controllers.pop_front(); delete controller; } @@ -99,11 +99,11 @@ MxLong MxStreamer::Close(const char* p_name) MxDSAction ds; ds.SetUnknown24(-2); - for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { + for (list::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) { MxStreamController* c = *it; - if (!p_name || !strcmp(p_name, c->GetAtom().GetInternal())) { - m_openStreams.erase(it); + if (!p_name || c->GetAtom() == p_name) { + m_controllers.erase(it); if (c->IsStoped(&ds)) { delete c; @@ -120,6 +120,7 @@ MxLong MxStreamer::Close(const char* p_name) } // FUNCTION: LEGO1 0x100b9700 +// FUNCTION: BETA10 0x10146ed0 MxNotificationParam* MxStreamerNotification::Clone() const { return new MxStreamerNotification(m_type, m_sender, m_controller); @@ -129,13 +130,9 @@ MxNotificationParam* MxStreamerNotification::Clone() const // FUNCTION: BETA10 0x1014584b MxStreamController* MxStreamer::GetOpenStream(const char* p_name) { - for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { - MxStreamController* c = *it; - MxAtomId& atom = c->GetAtom(); - if (p_name) { - if (!strcmp(atom.GetInternal(), p_name)) { - return *it; - } + for (list::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) { + if ((*it)->GetAtom() == p_name) { + return *it; } } @@ -152,10 +149,16 @@ void MxStreamer::FUN_100b98f0(MxDSAction* p_action) } // FUNCTION: LEGO1 0x100b9930 +// FUNCTION: BETA10 0x101458e5 MxResult MxStreamer::AddStreamControllerToOpenList(MxStreamController* p_stream) { - if (find(m_openStreams.begin(), m_openStreams.end(), p_stream) == m_openStreams.end()) { - m_openStreams.push_back(p_stream); + list::iterator i = find(m_controllers.begin(), m_controllers.end(), p_stream); + + assert(i == m_controllers.end()); + + // DECOMP: Retail is missing the optimization that skips this check if find() reaches the end. + if (i == m_controllers.end()) { + m_controllers.push_back(p_stream); return SUCCESS; } @@ -163,37 +166,41 @@ MxResult MxStreamer::AddStreamControllerToOpenList(MxStreamController* p_stream) } // FUNCTION: LEGO1 0x100b99b0 +// FUNCTION: BETA10 0x101459ad MxResult MxStreamer::FUN_100b99b0(MxDSAction* p_action) { - MxStreamController* controller; - if (p_action != NULL && p_action->GetAtomId().GetInternal() != NULL && p_action->GetObjectId() != -1) { - controller = GetOpenStream(p_action->GetAtomId().GetInternal()); - if (controller == NULL) { - return FAILURE; - } - return controller->VTable0x20(p_action); + // TODO: MxAtomId operator== used here for NULL test. BETA10 0x1007dc20 + if (p_action == NULL || p_action->GetAtomId().GetInternal() == NULL || p_action->GetObjectId() == -1) { + return FAILURE; } - return FAILURE; + + MxStreamController* controller = GetOpenStream(p_action->GetAtomId().GetInternal()); + if (controller == NULL) { + return FAILURE; + } + + return controller->VTable0x20(p_action); } // FUNCTION: LEGO1 0x100b99f0 +// FUNCTION: BETA10 0x10145a54 MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction) { MxDSAction tempAction; - if (p_dsAction == NULL) { - tempAction.SetUnknown24(-2); - } - else { + if (p_dsAction) { tempAction.SetObjectId(p_dsAction->GetObjectId()); tempAction.SetAtomId(p_dsAction->GetAtomId()); tempAction.SetUnknown24(p_dsAction->GetUnknown24()); } + else { + tempAction.SetUnknown24(-2); + } MxResult result = FAILURE; - for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { - const char* id = p_dsAction->GetAtomId().GetInternal(); - if (!id || id == (*it)->GetAtom().GetInternal()) { + for (list::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) { + // TODO: MxAtomId operator== used here for NULL test. BETA10 0x1007dc20 + if (p_dsAction->GetAtomId().GetInternal() == NULL || p_dsAction->GetAtomId() == (*it)->GetAtom()) { tempAction.SetAtomId((*it)->GetAtom()); result = (*it)->VTable0x24(&tempAction); } @@ -203,6 +210,7 @@ MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction) } // FUNCTION: LEGO1 0x100b9b30 +// FUNCTION: BETA10 0x10145d01 MxBool MxStreamer::FUN_100b9b30(MxDSObject& p_dsObject) { MxStreamController* controller = GetOpenStream(p_dsObject.GetAtomId().GetInternal()); @@ -213,14 +221,18 @@ MxBool MxStreamer::FUN_100b9b30(MxDSObject& p_dsObject) } // FUNCTION: LEGO1 0x100b9b60 +// FUNCTION: BETA10 0x10145d51 MxLong MxStreamer::Notify(MxParam& p_param) { - if (((MxNotificationParam&) p_param).GetNotification() == c_notificationStreamer) { - MxDSAction ds; + MxStreamerNotification& s = static_cast(p_param); - ds.SetUnknown24(-2); + switch (s.GetNotification()) { + case c_notificationStreamer: { + // DECOMP: Beta does not use a variable, but this matches retail better. + MxStreamController* c = s.GetController(); - MxStreamController* c = static_cast(p_param).GetController(); + MxDSAction ds; + ds.SetUnknown24(-2); if (c->IsStoped(&ds)) { delete c; @@ -228,6 +240,12 @@ MxLong MxStreamer::Notify(MxParam& p_param) else { NotificationManager()->Send(this, MxStreamerNotification(c_notificationStreamer, NULL, c)); } + + break; + } + default: + assert(0); + break; } return 0; From 4a01d15c3693fa5d7ec510a9bac2b9f0d22e91ad Mon Sep 17 00:00:00 2001 From: MS Date: Fri, 6 Sep 2024 16:13:16 -0400 Subject: [PATCH 2/8] MxStreamListMxDSAction helper functions (#1100) * MxStreamListMxDSAction Find/FindAndErase * Beta addrs for other stream lists --- LEGO1/omni/include/mxstreamlist.h | 15 ++++++++++++++- LEGO1/omni/src/main/mxomni.cpp | 4 ++-- LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp | 13 ++++++------- LEGO1/omni/src/stream/mxdiskstreamprovider.cpp | 2 +- LEGO1/omni/src/stream/mxdsbuffer.cpp | 2 +- LEGO1/omni/src/stream/mxramstreamcontroller.cpp | 8 ++++---- LEGO1/omni/src/stream/mxstreamcontroller.cpp | 8 ++++---- LEGO1/omni/src/stream/mxstreamlist.cpp | 6 +++++- 8 files changed, 37 insertions(+), 21 deletions(-) diff --git a/LEGO1/omni/include/mxstreamlist.h b/LEGO1/omni/include/mxstreamlist.h index 0e0f1e9f..36a9350a 100644 --- a/LEGO1/omni/include/mxstreamlist.h +++ b/LEGO1/omni/include/mxstreamlist.h @@ -24,7 +24,11 @@ class MxStreamList : public list { // SIZE 0x0c class MxStreamListMxDSAction : public MxStreamList { public: - MxDSAction* Find(MxDSAction* p_action, MxBool p_delete); + // FUNCTION: BETA10 0x10150e30 + MxDSAction* FindAndErase(MxDSAction* p_action) { return FindInternal(p_action, TRUE); } + + // FUNCTION: BETA10 0x10150fc0 + MxDSAction* Find(MxDSAction* p_action) { return FindInternal(p_action, FALSE); } // There chance this list actually holds MxDSStreamingListAction // instead of MxDSAction. Until then, we use this helper. @@ -38,6 +42,9 @@ class MxStreamListMxDSAction : public MxStreamList { pop_front(); return TRUE; } + +private: + MxDSAction* FindInternal(MxDSAction* p_action, MxBool p_delete); }; // SIZE 0x0c @@ -53,4 +60,10 @@ class MxStreamListMxDSSubscriber : public MxStreamList { MxDSSubscriber* Find(MxDSObject* p_object); }; +// TEMPLATE: BETA10 0x10150950 +// MxStreamList::PopFront + +// TEMPLATE: BETA10 0x10150a70 +// MxStreamList::PopFront + #endif // MXSTREAMLIST_H diff --git a/LEGO1/omni/src/main/mxomni.cpp b/LEGO1/omni/src/main/mxomni.cpp index 9e16a557..883aa008 100644 --- a/LEGO1/omni/src/main/mxomni.cpp +++ b/LEGO1/omni/src/main/mxomni.cpp @@ -340,10 +340,10 @@ MxLong MxOmni::HandleEndAction(MxParam& p_param) MxStreamController* controller = Streamer()->GetOpenStream(action->GetAtomId().GetInternal()); if (controller != NULL) { - action = controller->GetUnk0x54().Find(action, FALSE); + action = controller->GetUnk0x54().Find(action); if (action) { if (ActionSourceEquals(action, "LegoLoopingAnimPresenter") == FALSE) { - delete controller->GetUnk0x54().Find(action, TRUE); + delete controller->GetUnk0x54().FindAndErase(action); } } } diff --git a/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp index c90e377c..68d3cee3 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp @@ -187,7 +187,7 @@ MxResult MxDiskStreamController::VTable0x30(MxDSAction* p_action) MxDSStreamingAction* item; while (TRUE) { - item = (MxDSStreamingAction*) m_list0x90.Find(p_action, TRUE); + item = (MxDSStreamingAction*) m_list0x90.FindAndErase(p_action); if (item == NULL) { break; } @@ -195,7 +195,7 @@ MxResult MxDiskStreamController::VTable0x30(MxDSAction* p_action) } while (TRUE) { - item = (MxDSStreamingAction*) m_list0x64.Find(p_action, TRUE); + item = (MxDSStreamingAction*) m_list0x64.FindAndErase(p_action); if (item == NULL) { break; } @@ -286,8 +286,7 @@ void MxDiskStreamController::FUN_100c7f40(MxDSStreamingAction* p_streamingaction MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) { AUTOLOCK(m_criticalSection); - MxDSStreamingAction* entry = - (MxDSStreamingAction*) m_list0x80.Find(p_action, FALSE); // TODO: is this a seperate class? + MxDSStreamingAction* entry = (MxDSStreamingAction*) m_list0x80.Find(p_action); // TODO: is this a seperate class? if (entry) { MxDSStreamingAction* action = new MxDSStreamingAction(*p_action, 0); action->SetUnknown28(entry->GetUnknown28()); @@ -320,7 +319,7 @@ void MxDiskStreamController::FUN_100c8120(MxDSAction* p_action) } while (TRUE) { - MxDSAction* found = m_unk0x54.Find(p_action, TRUE); + MxDSAction* found = m_unk0x54.FindAndErase(p_action); if (!found) { break; } @@ -332,7 +331,7 @@ void MxDiskStreamController::FUN_100c8120(MxDSAction* p_action) MxResult MxDiskStreamController::VTable0x24(MxDSAction* p_action) { AUTOLOCK(m_criticalSection); - if (m_unk0x54.Find(p_action, FALSE) == NULL) { + if (m_unk0x54.Find(p_action) == NULL) { if (VTable0x30(p_action) == SUCCESS) { MxOmni::GetInstance()->NotifyCurrentEntity( MxEndActionNotificationParam(c_notificationEndAction, NULL, p_action, TRUE) @@ -368,7 +367,7 @@ MxResult MxDiskStreamController::FUN_100c8360(MxDSStreamingAction* p_action) { AUTOLOCK(m_criticalSection); MxDSBuffer* buffer = p_action->GetUnknowna0(); - MxDSStreamingAction* action2 = (MxDSStreamingAction*) m_list0x90.Find(p_action, TRUE); + MxDSStreamingAction* action2 = (MxDSStreamingAction*) m_list0x90.FindAndErase(p_action); buffer->FUN_100c6f80(p_action->GetUnknown94() - p_action->GetBufferOffset()); buffer->FUN_100c67b0(this, p_action, &action2); diff --git a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp index d6b73a9b..0e100ef9 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp @@ -144,7 +144,7 @@ void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) do { { AUTOLOCK(m_criticalSection); - action = (MxDSStreamingAction*) m_list.Find(p_action, TRUE); + action = (MxDSStreamingAction*) m_list.FindAndErase(p_action); } if (!action) { diff --git a/LEGO1/omni/src/stream/mxdsbuffer.cpp b/LEGO1/omni/src/stream/mxdsbuffer.cpp index e5e69c55..b7dca118 100644 --- a/LEGO1/omni/src/stream/mxdsbuffer.cpp +++ b/LEGO1/omni/src/stream/mxdsbuffer.cpp @@ -103,7 +103,7 @@ MxResult MxDSBuffer::FUN_100c67b0( { MxResult result = FAILURE; - m_unk0x30 = (MxDSStreamingAction*) p_controller->GetUnk0x3c().Find(p_action, FALSE); + m_unk0x30 = (MxDSStreamingAction*) p_controller->GetUnk0x3c().Find(p_action); if (m_unk0x30 == NULL) { return FAILURE; } diff --git a/LEGO1/omni/src/stream/mxramstreamcontroller.cpp b/LEGO1/omni/src/stream/mxramstreamcontroller.cpp index dea72610..46d11196 100644 --- a/LEGO1/omni/src/stream/mxramstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxramstreamcontroller.cpp @@ -43,20 +43,20 @@ MxResult MxRAMStreamController::VTable0x20(MxDSAction* p_action) if (p_action->GetUnknown24() == -1) { p_action->SetUnknown24(-3); - MxDSAction* action = m_unk0x54.Find(p_action, FALSE); + MxDSAction* action = m_unk0x54.Find(p_action); if (action != NULL) { unk0x24 = action->GetUnknown24() + 1; } p_action->SetUnknown24(unk0x24); } else { - if (m_unk0x54.Find(p_action, FALSE)) { + if (m_unk0x54.Find(p_action)) { return FAILURE; } } if (MxStreamController::VTable0x20(p_action) == SUCCESS) { - MxDSStreamingAction* action = (MxDSStreamingAction*) m_unk0x3c.Find(p_action, FALSE); + MxDSStreamingAction* action = (MxDSStreamingAction*) m_unk0x3c.Find(p_action); MxDSStreamingAction streamingaction(*action); result = DeserializeObject(streamingaction); } @@ -89,7 +89,7 @@ MxResult MxRAMStreamController::DeserializeObject(MxDSStreamingAction& p_action) m_buffer.FUN_100c6f80(p_action.GetUnknown94()); // Probably not MxResult, see below result = m_buffer.FUN_100c67b0(this, &p_action, &value); - } while (m_unk0x3c.Find(&p_action, FALSE) != NULL); + } while (m_unk0x3c.Find(&p_action) != NULL); return result == SUCCESS ? SUCCESS : FAILURE; } diff --git a/LEGO1/omni/src/stream/mxstreamcontroller.cpp b/LEGO1/omni/src/stream/mxstreamcontroller.cpp index 537a9ab0..35b1315c 100644 --- a/LEGO1/omni/src/stream/mxstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxstreamcontroller.cpp @@ -135,7 +135,7 @@ MxResult MxStreamController::VTable0x24(MxDSAction* p_action) { AUTOLOCK(m_criticalSection); VTable0x30(p_action); - m_action0x60 = m_unk0x54.Find(p_action, TRUE); + m_action0x60 = m_unk0x54.FindAndErase(p_action); if (m_action0x60 == NULL) { return FAILURE; } @@ -198,7 +198,7 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) p_action->SetUnknown24(newUnknown24 + 1); } else { - if (m_unk0x3c.Find(p_action, FALSE)) { + if (m_unk0x3c.Find(p_action)) { return FAILURE; } } @@ -235,7 +235,7 @@ MxResult MxStreamController::VTable0x30(MxDSAction* p_action) { AUTOLOCK(m_criticalSection); MxResult result = FAILURE; - MxDSAction* action = m_unk0x3c.Find(p_action, TRUE); + MxDSAction* action = m_unk0x3c.FindAndErase(p_action); if (action != NULL) { MxNextActionDataStart* data = m_nextActionList.FindAndErase(action->GetObjectId(), action->GetUnknown24()); delete action; @@ -266,7 +266,7 @@ MxPresenter* MxStreamController::FUN_100c1e70(MxDSAction& p_action) AUTOLOCK(m_criticalSection); MxPresenter* result = NULL; if (p_action.GetObjectId() != -1) { - MxDSAction* action = m_unk0x3c.Find(&p_action, FALSE); + MxDSAction* action = m_unk0x3c.Find(&p_action); if (action != NULL) { result = action->GetUnknown28(); } diff --git a/LEGO1/omni/src/stream/mxstreamlist.cpp b/LEGO1/omni/src/stream/mxstreamlist.cpp index effa987a..37e59463 100644 --- a/LEGO1/omni/src/stream/mxstreamlist.cpp +++ b/LEGO1/omni/src/stream/mxstreamlist.cpp @@ -6,6 +6,7 @@ DECOMP_SIZE_ASSERT(MxStreamListMxNextActionDataStart, 0x0c); DECOMP_SIZE_ASSERT(MxStreamListMxDSSubscriber, 0x0c); // FUNCTION: LEGO1 0x100b8450 +// FUNCTION: BETA10 0x10134c1d MxDSSubscriber* MxStreamListMxDSSubscriber::Find(MxDSObject* p_object) { for (iterator it = begin(); it != end(); it++) { @@ -20,7 +21,8 @@ MxDSSubscriber* MxStreamListMxDSSubscriber::Find(MxDSObject* p_object) } // FUNCTION: LEGO1 0x100bfa80 -MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) +// FUNCTION: BETA10 0x10147e02 +MxDSAction* MxStreamListMxDSAction::FindInternal(MxDSAction* p_action, MxBool p_delete) { // DECOMP ALPHA 0x1008b99d ? @@ -51,6 +53,7 @@ MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) } // FUNCTION: LEGO1 0x100c21e0 +// FUNCTION: BETA10 0x1014f4e6 MxNextActionDataStart* MxStreamListMxNextActionDataStart::Find(MxU32 p_id, MxS16 p_value) { for (iterator it = begin(); it != end(); it++) { @@ -63,6 +66,7 @@ MxNextActionDataStart* MxStreamListMxNextActionDataStart::Find(MxU32 p_id, MxS16 } // FUNCTION: LEGO1 0x100c2240 +// FUNCTION: BETA10 0x1014f58c MxNextActionDataStart* MxStreamListMxNextActionDataStart::FindAndErase(MxU32 p_id, MxS16 p_value) { MxNextActionDataStart* match = NULL; From ece3550e62996546824fc37db6299d3618e40910 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sun, 8 Sep 2024 22:00:08 +0200 Subject: [PATCH 3/8] Fix spurious reccmp warnings (#1101) Co-authored-by: jonschz --- tools/isledecomp/isledecomp/cvdump/symbols.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/isledecomp/isledecomp/cvdump/symbols.py b/tools/isledecomp/isledecomp/cvdump/symbols.py index 73cb152e..cfb9f474 100644 --- a/tools/isledecomp/isledecomp/cvdump/symbols.py +++ b/tools/isledecomp/isledecomp/cvdump/symbols.py @@ -79,7 +79,6 @@ class CvdumpSymbolsParser: "S_THUNK32", "S_LABEL32", "S_LDATA32", - "S_LPROC32", "S_UDT", ] @@ -117,7 +116,7 @@ def _parse_generic_case(self, line, line_match: Match[str]): symbol_type: str = line_match.group("symbol_type") second_part: Optional[str] = line_match.group("second_part") - if symbol_type == "S_GPROC32": + if symbol_type in ["S_GPROC32", "S_LPROC32"]: assert second_part is not None if (match := self._symbol_line_function_regex.match(second_part)) is None: logger.error("Invalid function symbol: %s", line[:-1]) From 5d19b6afe3f554db470262231121d2a913a76c82 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Mon, 9 Sep 2024 21:45:48 +0200 Subject: [PATCH 4/8] Improve `UnknownMx4DPointFloat::FUN_100040a0` (#1102) Co-authored-by: jonschz --- LEGO1/library_msvc.h | 6 +++++ LEGO1/mxgeometry/mxgeometry3d.h | 40 ++++++++++++++++----------------- LEGO1/realtime/vector.h | 8 ++++++- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index a4c6cd0a..b81e2f0b 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -669,4 +669,10 @@ // LIBRARY: BETA10 0x100f9060 // _assert +// LIBRARY: BETA10 0x100fa2fa +// _acos + +// LIBRARY: BETA10 0x100f9a50 +// _sin + #endif diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 289c201a..4a01d955 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -169,36 +169,36 @@ inline void UnknownMx4DPointFloat::Unknown7() // FUNCTION: BETA10 0x1004ab10 inline int UnknownMx4DPointFloat::FUN_100040a0(Vector4& p_v, float p_f) { - undefined4 state = m_unk0x30; - - if (state == 1) { + if (m_unk0x30 == 1) { p_v = m_unk0x00; - p_v[3] = (1.0 - p_f) * acos(p_v[3]) * 2.0; + p_v[3] = (1.0 - p_f) * acos((double) p_v[3]) * 2.0; return p_v.NormalizeQuaternion(); } - else if (state == 2) { + else if (m_unk0x30 == 2) { p_v = m_unk0x18; - p_v[3] = p_f * acos(p_v[3]) * 2.0; + p_v[3] = p_f * acos((double) p_v[3]) * 2.0; return p_v.NormalizeQuaternion(); } - else if (state == 3) { + else if (m_unk0x30 == 3) { + int i; double d1 = p_v.Dot(&m_unk0x00, &m_unk0x18); - double d2; + double a; + double b; if (d1 + 1.0 > 0.00001) { if (1.0 - d1 > 0.00001) { - double d = acos(d1); - double s = sin(d); - d1 = sin((1.0 - p_f) * d) / s; - d2 = sin(p_f * d) / s; + double d2 = acos(d1); + double denominator = sin(d2); + a = sin((1.0 - p_f) * d2) / denominator; + b = sin(p_f * d2) / denominator; } else { - d1 = 1.0 - p_f; - d2 = p_f; + a = 1.0 - p_f; + b = p_f; } - for (int i = 0; i < 4; i++) { - p_v[i] = m_unk0x18[i] * d2 + m_unk0x00[i] * d1; + for (i = 0; i < 4; i++) { + p_v[i] = m_unk0x00[i] * a + m_unk0x18[i] * b; } } else { @@ -206,11 +206,11 @@ inline int UnknownMx4DPointFloat::FUN_100040a0(Vector4& p_v, float p_f) p_v[1] = m_unk0x00[0]; p_v[2] = -m_unk0x00[3]; p_v[3] = m_unk0x00[2]; - d1 = sin((1.0 - p_f) * 1.570796326794895); - d2 = sin(p_f * 1.570796326794895); + a = sin((1.0 - p_f) * 1.570796326794895); + b = sin(p_f * 1.570796326794895); - for (int i = 0; i < 3; i++) { - p_v[i] = m_unk0x00[i] * d1 + p_v[i] * d2; + for (i = 0; i < 3; i++) { + p_v[i] = m_unk0x00[i] * a + p_v[i] * b; } } diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 84d072c3..4c1e17c3 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -154,13 +154,19 @@ class Vector2 { // SYNTHETIC: LEGO1 0x10010be0 // Vector3::operator= + // SYNTHETIC: BETA10 0x1004af40 + // Vector4::operator= + Vector2& operator=(const Vector2& p_other) { Vector2::SetVector(&p_other); return *this; } - // FUNCTION: BETA10 0x10013460 + // SYNTHETIC: BETA10 0x10013460 + // Vector3::operator[] + + // FUNCTION: BETA10 0x10010890 float& operator[](int idx) { return m_data[idx]; } // FUNCTION: BETA10 0x1001d140 From 7a6935a165689c217964ae81601d2fdfdc6ee993 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Thu, 12 Sep 2024 21:51:33 +0200 Subject: [PATCH 5/8] Progress on `LegoCarBuildAnimPresenter` (#1103) * Progress on `LegoCarBuildAnimPresenter` * Rename argument * fix copy-paste error * Address review comments * Remove obsolete comment --------- Co-authored-by: jonschz --- .../lego/legoomni/include/legoanimpresenter.h | 1 + .../legoomni/include/legocarbuildpresenter.h | 48 ++++++---- .../src/build/legocarbuildpresenter.cpp | 88 ++++++++++++++++--- .../legoomni/src/video/legoanimpresenter.cpp | 1 + LEGO1/lego/sources/misc/legotree.h | 9 ++ LEGO1/library_msvc.h | 27 ++++++ LEGO1/mxgeometry/mxgeometry3d.h | 1 + LEGO1/omni/src/system/mxautolock.cpp | 2 + LEGO1/omni/src/system/mxcriticalsection.cpp | 1 + LEGO1/omni/src/video/mxvideopresenter.cpp | 1 + 10 files changed, 152 insertions(+), 27 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index f289fe1d..30da04ff 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -30,6 +30,7 @@ typedef map LegoAnimStruc typedef map LegoAnimSubstMap; // VTABLE: LEGO1 0x100d90c8 +// VTABLE: BETA10 0x101baf90 // SIZE 0xbc class LegoAnimPresenter : public MxVideoPresenter { public: diff --git a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h index 8c97666c..2dbfd20f 100644 --- a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h +++ b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h @@ -5,9 +5,17 @@ #include "legoanimpresenter.h" // VTABLE: LEGO1 0x100d99e0 +// VTABLE: BETA10 0x101bb988 // SIZE 0x150 class LegoCarBuildAnimPresenter : public LegoAnimPresenter { public: + // SIZE 0x0c + struct UnknownListEntry { + LegoChar* m_unk0x00; // 0x00 + LegoChar* m_unk0x04; // 0x04 + undefined m_unk0x08[4]; // 0x08 + }; + LegoCarBuildAnimPresenter(); ~LegoCarBuildAnimPresenter() override; // vtable+0x00 @@ -39,27 +47,35 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { void FUN_10079920(float p_param1); MxBool FUN_10079ca0(const char* p_param1); + MxBool FUN_10079cf0(const LegoChar* p_name); + + // FUNCTION: BETA10 0x10070180 + void SetUnknown0xbc(undefined2 p_unk0xbc) { m_unk0xbc = p_unk0xbc; } + + MxBool StringEndsOnYOrN(const LegoChar* p_string); + + const BoundingSphere& FUN_10079e20(); // SYNTHETIC: LEGO1 0x10078660 // LegoCarBuildAnimPresenter::`scalar deleting destructor' private: - undefined2 m_unk0xbc; // 0xbc - undefined2 m_unk0xbe; // 0xbe - undefined2 m_unk0xc0; // 0xc0 - undefined4 m_unk0xc4; // 0xc4 - LegoAnim m_unk0xc8; // 0xc8 - MxMatrix m_unk0xe0; // 0xe0 - undefined4 m_unk0x128; // 0x128 - undefined4 m_unk0x12c; // 0x12c - undefined4 m_unk0x130; // 0x130 - undefined4 m_unk0x134; // 0x134 - undefined4 m_unk0x138; // 0x138 - undefined4 m_unk0x13c; // 0x13c - undefined4 m_unk0x140; // 0x140 - MxS32 m_unk0x144; // 0x144 - MxS32 m_unk0x148; // 0x148 - undefined4 m_unk0x14c; // 0x14c + undefined2 m_unk0xbc; // 0xbc + MxS16 m_unk0xbe; // 0xbe + MxS16 m_unk0xc0; // 0xc0 + undefined4 m_unk0xc4; // 0xc4 + LegoAnim m_unk0xc8; // 0xc8 + MxMatrix m_unk0xe0; // 0xe0 + UnknownListEntry* m_unk0x128; // 0x128 + undefined4 m_unk0x12c; // 0x12c + undefined4 m_unk0x130; // 0x130 + undefined4 m_unk0x134; // 0x134 + undefined4 m_unk0x138; // 0x138 + undefined4 m_unk0x13c; // 0x13c + LegoEntity* m_unk0x140; // 0x140 + MxS32 m_unk0x144; // 0x144 + MxS32 m_unk0x148; // 0x148 + undefined* m_unk0x14c; // 0x14c }; #endif // LEGOCARBUILDPRESENTER_H diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp index d143e670..12944337 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp @@ -1,23 +1,55 @@ #include "legocarbuildpresenter.h" +#include "legoentity.h" +#include "mxautolock.h" + +DECOMP_SIZE_ASSERT(LegoCarBuildAnimPresenter::UnknownListEntry, 0x0c) DECOMP_SIZE_ASSERT(LegoCarBuildAnimPresenter, 0x150) -// STUB: LEGO1 0x10078400 +// FUNCTION: LEGO1 0x10078400 +// FUNCTION: BETA10 0x100707c0 LegoCarBuildAnimPresenter::LegoCarBuildAnimPresenter() { - // TODO + m_unk0xbc = 0; + m_unk0xbe = 0; + m_unk0xc0 = 0; + m_unk0x128 = NULL; + m_unk0xc4 = 0; + m_unk0x130 = 0; + m_unk0x12c = 0; + m_unk0x134 = 0; + m_unk0x138 = 0; + m_unk0x13c = 0; + m_unk0x140 = NULL; + m_unk0x144 = -1; + m_unk0x148 = -1; + m_unk0x14c = NULL; } -// STUB: LEGO1 0x10078500 +// FUNCTION: LEGO1 0x10078500 void LegoCarBuildAnimPresenter::RepeatingTickle() { - // TODO + // empty } -// STUB: LEGO1 0x10078680 +// FUNCTION: LEGO1 0x10078680 +// FUNCTION: BETA10 0x1007091e LegoCarBuildAnimPresenter::~LegoCarBuildAnimPresenter() { - // TODO + if (m_unk0x128) { + for (MxS16 i = 0; i < m_unk0xbe; i++) { + delete m_unk0x128[i].m_unk0x00; + delete m_unk0x128[i].m_unk0x04; + } + delete[] m_unk0x128; + } + + m_unk0xc8.GetRoot()->SetNumChildren(0); + *m_unk0xc8.GetRoot()->GetChildren() = NULL; + + if (m_unk0x14c) { + delete m_unk0x14c; + } } // STUB: LEGO1 0x10078790 @@ -27,21 +59,28 @@ void LegoCarBuildAnimPresenter::PutFrame() } // STUB: LEGO1 0x100788c0 +// STUB: BETA10 0x10070b56 void LegoCarBuildAnimPresenter::ReadyTickle() { // TODO } // STUB: LEGO1 0x100789e0 +// STUB: BETA10 0x10070cdd void LegoCarBuildAnimPresenter::StreamingTickle() { // TODO } -// STUB: LEGO1 0x10078db0 +// FUNCTION: LEGO1 0x10078db0 +// FUNCTION: BETA10 0x100712f3 void LegoCarBuildAnimPresenter::EndAction() { - // TODO + if (m_action) { + AUTOLOCK(m_criticalSection); + MxVideoPresenter::EndAction(); + m_unk0xbc = 0; + } } // STUB: LEGO1 0x10079920 @@ -51,10 +90,37 @@ void LegoCarBuildAnimPresenter::FUN_10079920(float p_param1) // TODO } -// STUB: LEGO1 0x10079ca0 -// STUB: BETA10 0x10072740 +// FUNCTION: LEGO1 0x10079b80 +// FUNCTION: BETA10 0x1007258f +MxBool LegoCarBuildAnimPresenter::StringEndsOnYOrN(const LegoChar* p_string) +{ + return (p_string[strlen(p_string) - 2] == 'N') || (p_string[strlen(p_string) - 2] == 'n') || + (p_string[strlen(p_string) - 2] == 'Y') || (p_string[strlen(p_string) - 2] == 'y'); +} + +// FUNCTION: LEGO1 0x10079ca0 +// FUNCTION: BETA10 0x10072740 MxBool LegoCarBuildAnimPresenter::FUN_10079ca0(const char* p_param1) { - // TODO; pretty short + for (MxS16 i = 0; i < m_unk0xc0; i++) { + if (strcmpi(p_param1, m_unk0x128[i].m_unk0x00) == 0) { + return TRUE; + } + } + return FALSE; } + +// FUNCTION: LEGO1 0x10079cf0 +// FUNCTION: BETA10 0x100727b3 +MxBool LegoCarBuildAnimPresenter::FUN_10079cf0(const LegoChar* p_string) +{ + return (p_string[strlen(p_string) - 2] == 'Y') || (p_string[strlen(p_string) - 2] == 'y'); +} + +// FUNCTION: LEGO1 0x10079e20 +const BoundingSphere& LegoCarBuildAnimPresenter::FUN_10079e20() +{ + LegoROI* roi = m_unk0x140->GetROI(); + return roi->FindChildROI(m_unk0x128[m_unk0xc0].m_unk0x04, roi)->GetWorldBoundingSphere(); +} diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 2ddf10e7..4537418a 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -29,6 +29,7 @@ DECOMP_SIZE_ASSERT(LegoAnimPresenter, 0xbc) // FUNCTION: LEGO1 0x10068420 +// FUNCTION: BETA10 0x1004e5f0 LegoAnimPresenter::LegoAnimPresenter() { Init(); diff --git a/LEGO1/lego/sources/misc/legotree.h b/LEGO1/lego/sources/misc/legotree.h index 9d4aec69..fb97a612 100644 --- a/LEGO1/lego/sources/misc/legotree.h +++ b/LEGO1/lego/sources/misc/legotree.h @@ -35,10 +35,16 @@ class LegoTreeNode { LegoTreeNodeData* GetData() { return m_data; } void SetData(LegoTreeNodeData* p_data) { m_data = p_data; } LegoU32 GetNumChildren() { return m_numChildren; } + + // FUNCTION: BETA10 0x10073370 void SetNumChildren(LegoU32 p_numChildren) { m_numChildren = p_numChildren; } + LegoTreeNode* GetChild(LegoU32 p_i) { return m_children[p_i]; } void SetChild(LegoU32 p_i, LegoTreeNode* p_child) { m_children[p_i] = p_child; } + + // FUNCTION: BETA10 0x100733a0 LegoTreeNode** GetChildren() { return m_children; } + void SetChildren(LegoTreeNode** p_children) { m_children = p_children; } // SYNTHETIC: LEGO1 0x10099d80 @@ -56,7 +62,10 @@ class LegoTree { public: LegoTree(); virtual ~LegoTree(); + + // FUNCTION: BETA10 0x100121b0 LegoTreeNode* GetRoot() { return m_root; } + void SetRoot(LegoTreeNode* p_root) { m_root = p_root; } virtual LegoResult Read(LegoStorage* p_storage); // vtable+0x04 virtual LegoResult Write(LegoStorage* p_storage); // vtable+0x08 diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index b81e2f0b..157b7acd 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -675,4 +675,31 @@ // LIBRARY: BETA10 0x100f9a50 // _sin +// LIBRARY: BETA10 0x100f95d0 +// _sqrt + +// LIBRARY: BETA10 0x100f9780 +// strlen + +// LIBRARY: BETA10 0x100f8a88 +// operator new + +// LIBRARY: BETA10 0x100f9420 +// memcpy + +// LIBRARY: BETA10 0x100fb080 +// _stricmp + +// LIBRARY: BETA10 0x100fb050 +// fopen + +// LIBRARY: BETA10 0x100fae70 +// fprintf + +// LIBRARY: BETA10 0x100fad10 +// fclose + +// LIBRARY: BETA10 0x100fe5a0 +// abort + #endif diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 4a01d955..f5e2c083 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -52,6 +52,7 @@ class Mx4DPointFloat : public Vector4 { // FUNCTION: LEGO1 0x10048290 Mx4DPointFloat() : Vector4(m_elements) {} + // FUNCTION: BETA10 0x10073bb0 Mx4DPointFloat(float p_x, float p_y, float p_z, float p_a) : Vector4(m_elements) { m_elements[0] = p_x; diff --git a/LEGO1/omni/src/system/mxautolock.cpp b/LEGO1/omni/src/system/mxautolock.cpp index 5ab2e4bb..4508663e 100644 --- a/LEGO1/omni/src/system/mxautolock.cpp +++ b/LEGO1/omni/src/system/mxautolock.cpp @@ -3,6 +3,7 @@ #include "mxcriticalsection.h" // FUNCTION: LEGO1 0x100b8ed0 +// FUNCTION: BETA10 0x101386f0 MxAutoLock::MxAutoLock(MxCriticalSection* p_criticalSection) { m_criticalSection = p_criticalSection; @@ -13,6 +14,7 @@ MxAutoLock::MxAutoLock(MxCriticalSection* p_criticalSection) } // FUNCTION: LEGO1 0x100b8ef0 +// FUNCTION: BETA10 0x10138744 MxAutoLock::~MxAutoLock() { if (m_criticalSection != NULL) { diff --git a/LEGO1/omni/src/system/mxcriticalsection.cpp b/LEGO1/omni/src/system/mxcriticalsection.cpp index f0adc551..5c1ca9bf 100644 --- a/LEGO1/omni/src/system/mxcriticalsection.cpp +++ b/LEGO1/omni/src/system/mxcriticalsection.cpp @@ -36,6 +36,7 @@ MxCriticalSection::~MxCriticalSection() } // FUNCTION: LEGO1 0x100b6d80 +// FUNCTION: BETA10 0x1013c725 void MxCriticalSection::Enter() { DWORD result; diff --git a/LEGO1/omni/src/video/mxvideopresenter.cpp b/LEGO1/omni/src/video/mxvideopresenter.cpp index c94e656c..b9fc6b0d 100644 --- a/LEGO1/omni/src/video/mxvideopresenter.cpp +++ b/LEGO1/omni/src/video/mxvideopresenter.cpp @@ -542,6 +542,7 @@ MxResult MxVideoPresenter::AddToManager() } // FUNCTION: LEGO1 0x100b31d0 +// FUNCTION: BETA10 0x101396d9 void MxVideoPresenter::EndAction() { if (m_action) { From f89ee5c13da0e8f41016986e1957230d0d0ec827 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sat, 14 Sep 2024 16:16:12 +0200 Subject: [PATCH 6/8] BETA10 import: Fix `FUN_...` collisions (#1105) * Improve BETA10 name import, refactor * Run formatter --------- Co-authored-by: jonschz --- .../import_functions_and_types_from_pdb.py | 59 ++++--------------- .../ghidra_scripts/lego_util/ghidra_helper.py | 7 +++ tools/ghidra_scripts/lego_util/globals.py | 42 +++++++++++++ 3 files changed, 60 insertions(+), 48 deletions(-) create mode 100644 tools/ghidra_scripts/lego_util/globals.py diff --git a/tools/ghidra_scripts/import_functions_and_types_from_pdb.py b/tools/ghidra_scripts/import_functions_and_types_from_pdb.py index 54bb7e9f..2ac843b1 100644 --- a/tools/ghidra_scripts/import_functions_and_types_from_pdb.py +++ b/tools/ghidra_scripts/import_functions_and_types_from_pdb.py @@ -21,9 +21,7 @@ # Disable spurious warnings in vscode / pylance # pyright: reportMissingModuleSource=false -from enum import Enum import importlib -from dataclasses import dataclass, field import logging.handlers import sys import logging @@ -53,43 +51,8 @@ def reload_module(module: str): reload_module("lego_util.statistics") -from lego_util.statistics import Statistics - - -@dataclass -class Globals: - verbose: bool - loglevel: int - running_from_ghidra: bool = False - # statistics - statistics: Statistics = field(default_factory=Statistics) - - -class SupportedModules(Enum): - LEGO1 = 1 - BETA10 = 2 - - def orig_filename(self): - if self == self.LEGO1: - return "LEGO1.DLL" - return "BETA10.DLL" - - def recomp_filename_without_extension(self): - # in case we want to support more functions - return "LEGO1" - - def build_dir_name(self): - if self == self.BETA10: - return "build_debug" - return "build" - - -# hard-coded settings that we don't want to prompt in Ghidra every time -GLOBALS = Globals( - verbose=False, - # loglevel=logging.INFO, - loglevel=logging.DEBUG, -) +reload_module("lego_util.globals") +from lego_util.globals import GLOBALS, SupportedModules def setup_logging(): @@ -232,24 +195,24 @@ def main(): origfile_name = getProgramFile().getName() if origfile_name == "LEGO1.DLL": - module = SupportedModules.LEGO1 + GLOBALS.module = SupportedModules.LEGO1 elif origfile_name in ["LEGO1D.DLL", "BETA10.DLL"]: - module = SupportedModules.BETA10 + GLOBALS.module = SupportedModules.BETA10 else: raise Lego1Exception( f"Unsupported file name in import script: {origfile_name}" ) - else: - module = SupportedModules.LEGO1 - logger.info("Importing file: %s", module.orig_filename()) + logger.info("Importing file: %s", GLOBALS.module.orig_filename()) repo_root = get_repository_root() - origfile_path = repo_root.joinpath("legobin").joinpath(module.orig_filename()) - build_directory = repo_root.joinpath(module.build_dir_name()) - recompiledfile_name = f"{module.recomp_filename_without_extension()}.DLL" + origfile_path = repo_root.joinpath("legobin").joinpath( + GLOBALS.module.orig_filename() + ) + build_directory = repo_root.joinpath(GLOBALS.module.build_dir_name()) + recompiledfile_name = f"{GLOBALS.module.recomp_filename_without_extension()}.DLL" recompiledfile_path = build_directory.joinpath(recompiledfile_name) - pdbfile_name = f"{module.recomp_filename_without_extension()}.PDB" + pdbfile_name = f"{GLOBALS.module.recomp_filename_without_extension()}.PDB" pdbfile_path = build_directory.joinpath(pdbfile_name) if not GLOBALS.verbose: diff --git a/tools/ghidra_scripts/lego_util/ghidra_helper.py b/tools/ghidra_scripts/lego_util/ghidra_helper.py index 24e70c65..91717efd 100644 --- a/tools/ghidra_scripts/lego_util/ghidra_helper.py +++ b/tools/ghidra_scripts/lego_util/ghidra_helper.py @@ -8,6 +8,7 @@ TypeNotFoundInGhidraError, MultipleTypesFoundInGhidraError, ) +from lego_util.globals import GLOBALS, SupportedModules # Disable spurious warnings in vscode / pylance # pyright: reportMissingModuleSource=false @@ -105,6 +106,12 @@ def sanitize_name(name: str) -> str: .replace("`", "'") ) + # Importing function names like `FUN_10001234` into BETA10 can be confusing + # because Ghidra's auto-generated functions look exactly the same. + # Therefore, such function names are replaced by `LEGO_10001234` in the BETA10 import. + if GLOBALS.module == SupportedModules.BETA10: + new_name = re.sub(r"FUN_([0-9a-f]{8})", r"LEGO1_\1", new_name) + if "<" in name: new_name = "_template_" + new_name diff --git a/tools/ghidra_scripts/lego_util/globals.py b/tools/ghidra_scripts/lego_util/globals.py new file mode 100644 index 00000000..541b1106 --- /dev/null +++ b/tools/ghidra_scripts/lego_util/globals.py @@ -0,0 +1,42 @@ +import logging +from enum import Enum +from dataclasses import dataclass, field +from lego_util.statistics import Statistics + + +class SupportedModules(Enum): + LEGO1 = 1 + BETA10 = 2 + + def orig_filename(self): + if self == self.LEGO1: + return "LEGO1.DLL" + return "BETA10.DLL" + + def recomp_filename_without_extension(self): + # in case we want to support more functions + return "LEGO1" + + def build_dir_name(self): + if self == self.BETA10: + return "build_debug" + return "build" + + +@dataclass +class Globals: + verbose: bool + loglevel: int + module: SupportedModules + running_from_ghidra: bool = False + # statistics + statistics: Statistics = field(default_factory=Statistics) + + +# hard-coded settings that we don't want to prompt in Ghidra every time +GLOBALS = Globals( + verbose=False, + # loglevel=logging.INFO, + loglevel=logging.DEBUG, + module=SupportedModules.LEGO1, # this default value will be used when run outside of Ghidra +) From a942325b2962a27d38fcdd1fa27223f1dee64988 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sun, 15 Sep 2024 01:14:11 +0200 Subject: [PATCH 7/8] More functions in `LegoCarBuild` (#1104) * Add BETA10 annotations * Clean up * Implement multiple functions * fix minor annotation error * Undo formatting * Fix formatting * Implement more functions * Rename variables, address review comment --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/legoact2.h | 1 + LEGO1/lego/legoomni/include/legocarbuild.h | 75 +-- .../legoomni/include/legocarbuildpresenter.h | 5 +- .../include/legoeventnotificationparam.h | 2 + LEGO1/lego/legoomni/include/legoutils.h | 2 +- .../lego/legoomni/src/build/legocarbuild.cpp | 465 +++++++++++++++--- .../src/build/legocarbuildpresenter.cpp | 13 +- .../legoomni/src/common/legogamestate.cpp | 1 + LEGO1/lego/legoomni/src/common/legoutils.cpp | 3 +- LEGO1/lego/legoomni/src/entity/legoworld.cpp | 1 + LEGO1/lego/legoomni/src/worlds/legoact2.cpp | 1 + LEGO1/library_msvc.h | 4 + LEGO1/mxgeometry/mxmatrix.h | 1 + LEGO1/realtime/matrix.h | 2 + LEGO1/realtime/orientableroi.cpp | 1 + LEGO1/realtime/roi.h | 3 + 16 files changed, 487 insertions(+), 93 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoact2.h b/LEGO1/lego/legoomni/include/legoact2.h index 27ec54b1..3f8b65ef 100644 --- a/LEGO1/lego/legoomni/include/legoact2.h +++ b/LEGO1/lego/legoomni/include/legoact2.h @@ -47,6 +47,7 @@ class LegoAct2State : public LegoState { }; // VTABLE: LEGO1 0x100d82e0 +// VTABLE: BETA10 0x101ba898 // SIZE 0x1154 class LegoAct2 : public LegoWorld { public: diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index d005cf3c..60b5a9c3 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -1,13 +1,16 @@ #ifndef LEGOCARBUILD_H #define LEGOCARBUILD_H +#include "legogamestate.h" #include "legostate.h" #include "legoworld.h" class LegoCarBuildAnimPresenter; +class LegoEventNotificationParam; class MxControlPresenter; class MxStillPresenter; class MxSoundPresenter; +class MxActionNotificationParam; // VTABLE: LEGO1 0x100d66e0 // SIZE 0x50 @@ -90,9 +93,9 @@ class LegoCarBuild : public LegoWorld { void Enable(MxBool p_enable) override; // vtable+0x68 virtual void VTable0x6c(); // vtable+0x6c virtual void VTable0x70(); // vtable+0x70 - virtual void VTable0x74(MxFloat p_param1[3], MxFloat p_param2[3]); // vtable+0x74 - virtual void VTable0x78(MxFloat p_param1[3], MxFloat p_param2[3]); // vtable+0x78 - virtual void VTable0x7c(MxFloat p_param1[3], MxFloat p_param2[3]); // vtable+0x7c + virtual void VTable0x74(MxFloat p_param1[2], MxFloat p_param2[3]); // vtable+0x74 + virtual void VTable0x78(MxFloat p_param1[2], MxFloat p_param2[3]); // vtable+0x78 + virtual void VTable0x7c(MxFloat p_param1[2], MxFloat p_param2[3]); // vtable+0x7c virtual void VTable0x80( MxFloat p_param1[2], MxFloat p_param2[2], @@ -102,45 +105,58 @@ class LegoCarBuild : public LegoWorld { void InitPresenters(); void FUN_10022f30(); + void FUN_10023130(MxLong p_x, MxLong p_y); + undefined4 FUN_10024250(LegoEventNotificationParam* p_param); + void FUN_100243a0(); + undefined4 FUN_10024480(MxActionNotificationParam* p_param); + undefined4 FUN_100244e0(MxLong p_x, MxLong p_y); + undefined4 FUN_100246e0(MxLong p_x, MxLong p_y); + MxS32 FUN_10024850(MxLong p_x, MxLong p_y); + undefined4 FUN_10024890(LegoEventNotificationParam* p_param); + void FUN_10024c20(LegoEventNotificationParam* p_param); void FUN_10024ef0(); void FUN_10024f50(); + void FUN_10024f70(MxBool p_enabled); void SetPresentersEnabled(MxBool p_enabled); void TogglePresentersEnabled(); + void FUN_100250e0(MxBool p_param); + void FUN_10025450(); undefined4 FUN_10025720(undefined4 p_param1); MxS32 FUN_10025d70(); void FUN_10025db0(const char* p_param1, undefined4 p_param2); + void FUN_10025e40(); MxS32 FUN_10025ee0(undefined4 p_param1); // SYNTHETIC: LEGO1 0x10022a60 // LegoCarBuild::`scalar deleting destructor' private: - undefined4 m_unk0xf8; // 0xf8 - MxS16 m_unk0xfc; // 0xfc - undefined m_unk0xfe[2]; // 0xfe - undefined4 m_unk0x100; // 0x100 - undefined4 m_unk0x104; // 0x104 - undefined m_unk0x108; // 0x108 - undefined m_unk0x109; // 0x109 - MxU16 m_unk0x10a; // 0x10a - DWORD m_unk0x10c; // 0x10c - LegoROI* m_unk0x110; // 0x110 - Mx3DPointFloat m_unk0x114; // 0x114 - undefined4 m_unk0x128; // 0x128 - MxMatrix m_unk0x12c; // 0x12c - undefined m_unk0x174; // 0x174 - MxMatrix m_unk0x178; // 0x178 - MxMatrix m_unk0x1c0; // 0x1c0 - MxMatrix m_unk0x208; // 0x208 - undefined m_unk0x250[0x08]; // 0x250 + undefined4 m_unk0xf8; // 0xf8 + MxS16 m_unk0xfc; // 0xfc + undefined m_unk0xfe[2]; // 0xfe + MxS32 m_unk0x100; // 0x100 + undefined4 m_unk0x104; // 0x104 + MxS8 m_unk0x108; // 0x108 + MxU8 m_unk0x109; // 0x109 + MxU16 m_unk0x10a; // 0x10a + DWORD m_unk0x10c; // 0x10c + LegoROI* m_unk0x110; // 0x110 + BoundingSphere m_unk0x114; // 0x114 + MxMatrix m_unk0x12c; // 0x12c + undefined m_unk0x174; // 0x174 + MxMatrix m_unk0x178; // 0x178 + MxMatrix m_unk0x1c0; // 0x1c0 + MxMatrix m_unk0x208; // 0x208 + + // This is likely a location in pixel space + MxS32 m_unk0x250[2]; // 0x250 + LegoCarBuildAnimPresenter* m_unk0x258; // 0x258 UnknownMx4DPointFloat m_unk0x25c; // 0x25c - // These four are likely locations in pixel space - MxS32 m_unk0x290; // 0x290 - MxS32 m_unk0x294; // 0x294 - MxS32 m_unk0x298; // 0x298 - MxS32 m_unk0x29c; // 0x29c + // These two are likely locations in pixel space + MxS32 m_unk0x290[2]; // 0x290 + MxS32 m_unk0x298[2]; // 0x298 MxFloat m_unk0x2a0; // 0x2a0 Mx4DPointFloat m_unk0x2a4; // 0x2a4 @@ -173,8 +189,11 @@ class LegoCarBuild : public LegoWorld { // variable name verified by BETA10 0x1006b219 LegoVehicleBuildState* m_buildState; // 0x32c - undefined4 m_unk0x330; // 0x330 - undefined4 m_unk0x334; // 0x334 + undefined4 m_unk0x330; // 0x330 + + // variable name verified by BETA10 0x1006cba7 + LegoGameState::Area m_destLocation; // 0x334 + undefined4 m_unk0x338; // 0x338 MxControlPresenter* m_unk0x33c; // 0x33c undefined4 m_unk0x340; // 0x340 diff --git a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h index 2dbfd20f..8d707eff 100644 --- a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h +++ b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h @@ -46,8 +46,9 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { void PutFrame() override; // vtable+0x6c void FUN_10079920(float p_param1); - MxBool FUN_10079ca0(const char* p_param1); - MxBool FUN_10079cf0(const LegoChar* p_name); + MxBool FUN_10079c30(const LegoChar* p_name); + MxBool FUN_10079ca0(const LegoChar* p_name); + MxBool FUN_10079cf0(const LegoChar* p_string); // FUNCTION: BETA10 0x10070180 void SetUnknown0xbc(undefined2 p_unk0xbc) { m_unk0xbc = p_unk0xbc; } diff --git a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h index f7c00b48..cbb12b61 100644 --- a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h +++ b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h @@ -46,9 +46,11 @@ class LegoEventNotificationParam : public MxNotificationParam { MxU8 GetKey() const { return m_key; } // FUNCTION: LEGO1 0x10012190 + // FUNCTION: BETA10 0x10024210 MxS32 GetX() const { return m_x; } // FUNCTION: LEGO1 0x100121a0 + // FUNCTION: BETA10 0x10024240 MxS32 GetY() const { return m_y; } void SetROI(LegoROI* p_roi) { m_roi = p_roi; } diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h index ee0a001d..9e8c91fc 100644 --- a/LEGO1/lego/legoomni/include/legoutils.h +++ b/LEGO1/lego/legoomni/include/legoutils.h @@ -40,7 +40,7 @@ LegoEntity* PickEntity(MxLong, MxLong); LegoROI* PickROI(MxLong, MxLong); LegoROI* PickParentROI(MxLong p_a, MxLong p_b); void FUN_1003dde0(LegoROI* p_param1, MxFloat p_param2); -MxBool FUN_1003ded0(MxFloat p_param1[3], MxFloat p_param2[3], MxFloat p_param3[3]); +MxBool FUN_1003ded0(MxFloat p_param1[2], MxFloat p_param2[3], MxFloat p_param3[3]); MxBool TransformWorldToScreen(const MxFloat p_world[3], MxFloat p_screen[4]); MxS16 CountTotalTreeNodes(LegoTreeNode* p_node); void FUN_1003e050(LegoAnimPresenter* p_presenter); diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 5241638d..2d6501c7 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -6,6 +6,7 @@ #include "legoinputmanager.h" #include "legoutils.h" #include "misc.h" +#include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" #include "mxcontrolpresenter.h" #include "mxmisc.h" @@ -13,8 +14,11 @@ #include "mxsoundpresenter.h" #include "mxstillpresenter.h" #include "mxticklemanager.h" +#include "mxtransitionmanager.h" #include "scripts.h" +#include + DECOMP_SIZE_ASSERT(LegoCarBuild, 0x34c) DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50) @@ -27,46 +31,45 @@ MxFloat LegoCarBuild::g_unk0x100d65a8 = 0.07; // GLOBAL: LEGO1 0x100f11cc MxS16 LegoCarBuild::g_unk0x100f11cc = -1; -// STUB: LEGO1 0x100226d0 +// FUNCTION: LEGO1 0x100226d0 // FUNCTION: BETA10 0x1006ac10 LegoCarBuild::LegoCarBuild() { - // Not close yet - might be getting there when more of this class is implemented m_unk0x100 = 0; m_unk0x110 = 0; m_unk0xf8 = 0xffffffff; - m_unk0x2d4 = '\0'; + m_unk0x2d4 = FALSE; m_unk0x258 = 0; - m_ColorBook_Bitmap = 0; - m_Yellow_Ctl = 0; - m_Red_Ctl = 0; - m_Blue_Ctl = 0; - m_Green_Ctl = 0; - m_Gray_Ctl = 0; - m_Black_Ctl = 0; - m_Shelf_Sound = 0; - m_PlaceBrick_Sound = 0; - m_GetBrick_Sound = 0; - m_Paint_Sound = 0; - m_Decal_Sound = 0; - m_Decal_Bitmap = 0; - m_Decals_Ctl = 0; - m_Decals_Ctl1 = 0; - m_Decals_Ctl2 = 0; - m_Decals_Ctl3 = 0; - m_Decals_Ctl4 = 0; - m_Decals_Ctl5 = 0; - m_Decals_Ctl6 = 0; + m_ColorBook_Bitmap = NULL; + m_Yellow_Ctl = NULL; + m_Red_Ctl = NULL; + m_Blue_Ctl = NULL; + m_Green_Ctl = NULL; + m_Gray_Ctl = NULL; + m_Black_Ctl = NULL; + m_Shelf_Sound = NULL; + m_PlaceBrick_Sound = NULL; + m_GetBrick_Sound = NULL; + m_Paint_Sound = NULL; + m_Decal_Sound = NULL; + m_Decal_Bitmap = NULL; + m_Decals_Ctl = NULL; + m_Decals_Ctl1 = NULL; + m_Decals_Ctl2 = NULL; + m_Decals_Ctl3 = NULL; + m_Decals_Ctl4 = NULL; + m_Decals_Ctl5 = NULL; + m_Decals_Ctl6 = NULL; m_Decals_Ctl7 = NULL; - m_unk0x33c = 0; - m_buildState = 0; + m_unk0x33c = NULL; + m_buildState = NULL; m_unk0x104 = 0; - m_unk0x109 = '\0'; - m_unk0x108 = '\0'; + m_unk0x109 = 0; + m_unk0x108 = 0; m_unk0x338 = 0; - m_unk0x334 = 0; + m_destLocation = LegoGameState::e_undefined; m_unk0x344 = 0xffffffff; - m_unk0x174 = '\0'; + m_unk0x174 = 0; NotificationManager()->Register(this); } @@ -78,7 +81,7 @@ MxBool LegoCarBuild::VTable0x5c() } // STUB: LEGO1 0x10022a80 -// FUNCTION: BETA10 0x1006aea3 +// STUB: BETA10 0x1006aea3 LegoCarBuild::~LegoCarBuild() { // TODO @@ -106,22 +109,22 @@ MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) if (m_atomId == *g_copterScript) { buildStateClassName = "LegoCopterBuildState"; - GameState()->SetCurrentArea(LegoGameState::Area::e_copterbuild); + GameState()->SetCurrentArea(LegoGameState::e_copterbuild); m_unk0x330 = 1; } else if (m_atomId == *g_dunecarScript) { buildStateClassName = "LegoDuneCarBuildState"; - GameState()->SetCurrentArea(LegoGameState::Area::e_dunecarbuild); + GameState()->SetCurrentArea(LegoGameState::e_dunecarbuild); m_unk0x330 = 2; } else if (m_atomId == *g_jetskiScript) { buildStateClassName = "LegoJetskiBuildState"; - GameState()->SetCurrentArea(LegoGameState::Area::e_jetskibuild); + GameState()->SetCurrentArea(LegoGameState::e_jetskibuild); m_unk0x330 = 3; } else if (m_atomId == *g_racecarScript) { buildStateClassName = "LegoRaceCarBuildState"; - GameState()->SetCurrentArea(LegoGameState::Area::e_racecarbuild); + GameState()->SetCurrentArea(LegoGameState::e_racecarbuild); m_unk0x330 = 4; } @@ -136,7 +139,7 @@ MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) m_buildState = buildState; m_unk0x174 = m_buildState->m_unk0x4d; - GameState()->StopArea(LegoGameState::Area::e_previousArea); + GameState()->StopArea(LegoGameState::e_previousArea); m_buildState->m_animationState = 1; m_unk0x100 = 0; @@ -196,11 +199,24 @@ void LegoCarBuild::InitPresenters() } } -// STUB: LEGO1 0x10022f30 -// STUB: BETA10 0x1006b835 +// FUNCTION: LEGO1 0x10022f30 +// FUNCTION: BETA10 0x1006b835 void LegoCarBuild::FUN_10022f30() { - // TODO + if (m_unk0x110) { + FUN_10024f70(FALSE); + FUN_100250e0(FALSE); + + if (m_unk0x258->FUN_10079ca0(m_unk0x110->GetName())) { + m_PlaceBrick_Sound->Enable(FALSE); + m_PlaceBrick_Sound->Enable(TRUE); + } + + m_unk0x258->SetUnknown0xbc(1); + m_unk0x258->PutFrame(); + m_unk0x110 = NULL; + m_unk0x100 = 0; + } } // FUNCTION: LEGO1 0x10022fc0 @@ -214,7 +230,7 @@ void LegoCarBuild::VTable0x6c() VTable0x70(); } -// STUB: LEGO1 0x10023020 +// FUNCTION: LEGO1 0x10023020 // FUNCTION: BETA10 0x1006b991 void LegoCarBuild::VTable0x70() { @@ -227,8 +243,8 @@ void LegoCarBuild::VTable0x70() TransformWorldToScreen(worldPos, screenPos); - m_unk0x290 = screenPos[0] / screenPos[3]; - m_unk0x294 = screenPos[1] / screenPos[3]; + m_unk0x290[0] = screenPos[0] / screenPos[3]; + m_unk0x290[1] = screenPos[1] / screenPos[3]; worldPos[0] = m_unk0x2bc[0]; worldPos[1] = m_unk0x2bc[1]; @@ -236,20 +252,74 @@ void LegoCarBuild::VTable0x70() TransformWorldToScreen(worldPos, screenPos); - m_unk0x298 = screenPos[0] / screenPos[3]; - m_unk0x29c = screenPos[1] / screenPos[3]; + m_unk0x298[0] = screenPos[0] / screenPos[3]; + m_unk0x298[1] = screenPos[1] / screenPos[3]; - m_unk0x2a0 = sqrt( - (MxFloat) (m_unk0x298 - m_unk0x290) * (m_unk0x298 - m_unk0x290) + - (m_unk0x29c - m_unk0x294) * (m_unk0x29c - m_unk0x294) - ); + m_unk0x2a0 = sqrt((MxDouble) DISTSQRD2(m_unk0x290, m_unk0x298)); m_unk0x25c.Unknown1(m_unk0x178, m_unk0x208); } +// FUNCTION: LEGO1 0x10023130 +// FUNCTION: BETA10 0x1006bb22 +void LegoCarBuild::FUN_10023130(MxLong p_x, MxLong p_y) +{ + if (m_unk0x110) { + MxFloat pfVar3[2]; + MxFloat local30[3]; + MxFloat local84[3]; + + p_x += (m_unk0x290[0] - m_unk0x250[0]); + p_y += (m_unk0x290[1] - m_unk0x250[1]); + + pfVar3[0] = p_x; + pfVar3[1] = p_y; + + if (FUN_1003ded0(pfVar3, local30, local84)) { + MxFloat local18[3]; + MxFloat local8c[2]; + + local8c[0] = p_x; + local8c[1] = p_y; + + local18[0] = 0; + local18[1] = 0; + local18[2] = 0; + + MxMatrix local78; + + if (p_y < m_unk0x290[1]) { + VTable0x74(local8c, local18); + } + else if (p_y > m_unk0x298[1]) { + VTable0x7c(local8c, local18); + } + else if (p_y >= m_unk0x290[1]) { + VTable0x78(local8c, local18); + } + + MxS32 local20[2]; + + local20[0] = p_x - m_unk0x290[0]; + local20[1] = p_y - m_unk0x290[1]; + + MxFloat local1c = sqrt((double) (NORMSQRD2(local20))) / m_unk0x2a0; + + m_unk0x25c.Unknown6(local78, local1c); + + local78[3][0] = m_unk0x178[3][0] + local18[0]; + local78[3][1] = m_unk0x178[3][1] + local18[1]; + local78[3][2] = m_unk0x178[3][2] + local18[2]; + local78[3][3] = 1.0; + + m_unk0x110->WrappedSetLocalTransform(local78); + } + } +} + // FUNCTION: LEGO1 0x10023500 // FUNCTION: BETA10 0x1006bdf6 -void LegoCarBuild::VTable0x74(MxFloat p_param1[3], MxFloat p_param2[3]) +void LegoCarBuild::VTable0x74(MxFloat p_param1[2], MxFloat p_param2[3]) { MxFloat fVar1; MxFloat local20[3]; @@ -265,7 +335,7 @@ void LegoCarBuild::VTable0x74(MxFloat p_param1[3], MxFloat p_param2[3]) // FUNCTION: LEGO1 0x10023570 // FUNCTION: BETA10 0x1006be91 -void LegoCarBuild::VTable0x78(MxFloat p_param1[3], MxFloat p_param2[3]) +void LegoCarBuild::VTable0x78(MxFloat p_param1[2], MxFloat p_param2[3]) { MxFloat fVar1; MxFloat local18[3]; @@ -273,8 +343,8 @@ void LegoCarBuild::VTable0x78(MxFloat p_param1[3], MxFloat p_param2[3]) FUN_1003ded0(p_param1, local18, localc); - p_param2[2] = - m_unk0x2a4[2] + (m_unk0x2bc[2] - m_unk0x2a4[2]) * ((p_param1[1] - m_unk0x294) / (m_unk0x29c - m_unk0x294)); + p_param2[2] = m_unk0x2a4[2] + + (m_unk0x2bc[2] - m_unk0x2a4[2]) * ((p_param1[1] - m_unk0x290[1]) / (m_unk0x298[1] - m_unk0x290[1])); fVar1 = (p_param2[2] - localc[2]) / local18[2]; p_param2[0] = fVar1 * local18[0] - m_unk0x2a4[0] + localc[0]; p_param2[1] = fVar1 * local18[1] - m_unk0x2a4[1] + localc[1]; @@ -283,7 +353,7 @@ void LegoCarBuild::VTable0x78(MxFloat p_param1[3], MxFloat p_param2[3]) // FUNCTION: LEGO1 0x10023620 // FUNCTION: BETA10 0x1006bfb5 -void LegoCarBuild::VTable0x7c(MxFloat p_param1[3], MxFloat p_param2[3]) +void LegoCarBuild::VTable0x7c(MxFloat p_param1[2], MxFloat p_param2[3]) { MxFloat local18[3]; MxFloat localc[3]; @@ -428,31 +498,276 @@ MxResult LegoCarBuild::Tickle() return 0; } -// STUB: LEGO1 0x10024050 +// FUNCTION: LEGO1 0x10024050 // FUNCTION: BETA10 0x1006c976 MxLong LegoCarBuild::Notify(MxParam& p_param) { - // TODO + MxLong result = LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam*) &p_param)->GetNotification()) { + case c_notificationType0: + FUN_10024c20((LegoEventNotificationParam*) &p_param); + result = 1; + break; + case c_notificationEndAction: + result = FUN_10024480((MxActionNotificationParam*) &p_param); + break; + case c_notificationKeyPress: + result = FUN_10024250((LegoEventNotificationParam*) &p_param); + break; + case c_notificationButtonUp: + result = FUN_100246e0( + ((LegoEventNotificationParam&) p_param).GetX(), + ((LegoEventNotificationParam&) p_param).GetY() + ); + + if (result || m_unk0x10a || m_buildState->m_animationState == 4 || m_buildState->m_animationState == 6) { + m_unk0x109 = 0; + break; + } + + if (++m_unk0x109 > 2) { + FUN_10025720(6); + m_unk0x109 = 0; + } + + break; + case c_notificationButtonDown: + assert(m_buildState); + if (((m_buildState->m_animationState != 4) && (m_buildState->m_animationState != 6)) && + (m_buildState->m_animationState != 2)) { + m_buildState->m_animationState = 0; + result = FUN_100244e0( + ((LegoEventNotificationParam&) p_param).GetX(), + ((LegoEventNotificationParam&) p_param).GetY() + ); + } + + break; + case c_notificationMouseMove: + result = FUN_10024850( + ((LegoEventNotificationParam&) p_param).GetX(), + ((LegoEventNotificationParam&) p_param).GetY() + ); + + if (result == 1) { + m_unk0x109 = 0; + } + + break; + case c_notificationControl: + result = FUN_10024890((LegoEventNotificationParam*) &p_param); + + if (result == 1) { + m_unk0x109 = 0; + } + + break; + case c_notificationEndAnim: + if (m_unk0x108 > 0) { + m_unk0x108 -= 1; + } + + FUN_10025e40(); + m_unk0x10a = 0; + result = 1; + break; + case c_notificationTransitioned: + assert(m_destLocation != LegoGameState::e_undefined); + GameState()->SwitchArea(m_destLocation); + } + } + + return result; +} + +// FUNCTION: LEGO1 0x10024250 +// FUNCTION: BETA10 0x1006cc48 +undefined4 LegoCarBuild::FUN_10024250(LegoEventNotificationParam* p_param) +{ + if (p_param->GetKey() == ' ' && m_buildState->m_animationState != 4 && m_buildState->m_animationState != 2) { + if (m_unk0x108 > 0) { + DeleteObjects(&m_atomId, 500, 0x1fe); + BackgroundAudioManager()->RaiseVolume(); + m_unk0x109 = 0; + } + + return 1; + } + return 0; } -// STUB: LEGO1 0x100242c0 +// FUNCTION: LEGO1 0x100242c0 void LegoCarBuild::ReadyWorld() { m_presentersEnabled = FALSE; InitPresenters(); + if (BackgroundAudioManager()->GetEnabled()) { InvokeAction(Extra::ActionType::e_start, *g_jukeboxScript, FUN_10025ee0(m_unk0x330), NULL); m_buildState->m_animationState = 2; - MxNotificationParam param; - param.SetNotification(c_notificationStartAction); - NotificationManager()->Send(this, param); + NotificationManager()->Send(this, MxNotificationParam()); } else { FUN_10024ef0(); } } +// FUNCTION: LEGO1 0x100243a0 +void LegoCarBuild::FUN_100243a0() +{ + switch (m_unk0x330) { + case 1: + if (GameState()->GetCurrentAct() == LegoGameState::Act::e_act2) { + m_destLocation = LegoGameState::Area::e_act3script; + TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); + break; + } + else { + m_destLocation = LegoGameState::Area::e_polidoor; + TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); + break; + } + case 2: + m_destLocation = LegoGameState::Area::e_garadoor; + TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); + break; + case 3: + m_destLocation = LegoGameState::Area::e_unk17; + TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); + break; + case 4: + m_destLocation = LegoGameState::Area::e_unk20; + TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); + } +} + +// FUNCTION: LEGO1 0x10024480 +undefined4 LegoCarBuild::FUN_10024480(MxActionNotificationParam* p_param) +{ + MxS32 result = 0; + + switch (m_buildState->m_animationState) { + case 3: + BackgroundAudioManager()->RaiseVolume(); + m_buildState->m_animationState = 0; + result = 1; + break; + case 6: + if (p_param->GetAction()->GetObjectId() == m_unk0x344) { + FUN_100243a0(); + result = 1; + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x100244e0 +// FUNCTION: BETA10 0x1006cfb6 +undefined4 LegoCarBuild::FUN_100244e0(MxLong p_x, MxLong p_y) +{ + m_unk0x250[0] = p_x; + m_unk0x250[1] = p_y; + + LegoROI* roi = PickROI(p_x, p_y); + + if (!roi || !m_unk0x258->StringEndsOnYOrN(roi->GetName())) { + return 0; + } + + if (m_unk0x110 != roi) { + FUN_10022f30(); + m_unk0x110 = roi; + FUN_10024f70(TRUE); + FUN_100250e0(TRUE); + } + + if (m_unk0x100 == 5 && m_unk0x258->FUN_10079ca0(m_unk0x110->GetName())) { + m_unk0x2d4 = TRUE; + } + else { + m_unk0x2d4 = FALSE; + } + FUN_10025450(); + VTable0x70(); + + if (m_unk0x258->FUN_10079ca0(m_unk0x110->GetName())) { + if (m_unk0x100 != 5) { + m_unk0x250[0] += m_unk0x290[0] - m_unk0x298[0]; + m_unk0x250[1] += m_unk0x290[1] - m_unk0x298[1]; + } + + if (m_unk0x100 == 0) { + m_unk0x114 = m_unk0x110->GetWorldBoundingSphere(); + } + } + else { + if (m_unk0x258->FUN_10079c30(m_unk0x110->GetName())) { + m_unk0x114 = m_unk0x258->FUN_10079e20(); + } + } + + switch (m_unk0x100) { + case 0: + m_unk0x100 = 4; + break; + case 5: + m_unk0x100 = 3; + break; + } + + m_GetBrick_Sound->Enable(FALSE); + m_GetBrick_Sound->Enable(TRUE); + + m_unk0x258->SetUnknown0xbc(0); + return 1; +} + +// STUB: LEGO1 0x100246e0 +undefined4 LegoCarBuild::FUN_100246e0(MxLong p_x, MxLong p_y) +{ + // TODO + return 0; +} + +// FUNCTION: LEGO1 0x10024850 +// FUNCTION: BETA10 0x1006d48e +MxS32 LegoCarBuild::FUN_10024850(MxLong p_x, MxLong p_y) +{ + MxS32 result = 0; + + switch (m_unk0x100) { + case 3: + case 4: + m_unk0x100 = 6; + case 6: + FUN_10023130(p_x, p_y); + result = 1; + break; + } + + return result; +} + +// STUB: LEGO1 0x10024890 +// STUB: BETA10 0x1006d512 +undefined4 LegoCarBuild::FUN_10024890(LegoEventNotificationParam* p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10024c20 +// STUB: BETA10 0x1006db21 +void LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) +{ + // TODO +} + // FUNCTION: LEGO1 0x10024ef0 void LegoCarBuild::FUN_10024ef0() { @@ -471,6 +786,15 @@ void LegoCarBuild::FUN_10024f50() m_unk0x258->FUN_10079920(g_unk0x100d65a8); } +// FUNCTION: LEGO1 0x10024f70 +// FUNCTION: BETA10 0x1006e002 +void LegoCarBuild::FUN_10024f70(MxBool p_enabled) +{ + if (m_unk0x258->FUN_10079cf0(m_unk0x110->GetName())) { + SetPresentersEnabled(p_enabled); + } +} + // FUNCTION: LEGO1 0x10024fa0 // FUNCTION: BETA10 0x1006e04f void LegoCarBuild::SetPresentersEnabled(MxBool p_enabled) @@ -497,6 +821,20 @@ void LegoCarBuild::TogglePresentersEnabled() m_Black_Ctl->Enable(!m_Black_Ctl->IsEnabled()); } +// STUB: LEGO1 0x100250e0 +// STUB: BETA10 0x1006e124 +void LegoCarBuild::FUN_100250e0(MxBool p_enabled) +{ + // TODO +} + +// STUB: LEGO1 0x10025450 +// STUB: BETA10 0x1006e599 +void LegoCarBuild::FUN_10025450() +{ + // TODO +} + // FUNCTION: LEGO1 0x100256c0 // FUNCTION: BETA10 0x1006e96c void LegoCarBuild::Enable(MxBool p_enable) @@ -561,6 +899,15 @@ void LegoCarBuild::FUN_10025db0(const char* p_param1, undefined4 p_param2) } } +// FUNCTION: LEGO1 0x10025e40 +void LegoCarBuild::FUN_10025e40() +{ + SetPresentersEnabled(m_presentersEnabled); + if (m_unk0x33c && m_Yellow_Ctl != m_unk0x33c) { + m_unk0x33c->VTable0x6c(0); + } +} + // FUNCTION: LEGO1 0x10025e70 MxBool LegoCarBuild::Escape() { @@ -570,7 +917,7 @@ MxBool LegoCarBuild::Escape() DeleteObjects(&m_atomId, 500, 999); m_buildState->m_animationState = 0; - m_unk0x334 = 2; + m_destLocation = LegoGameState::e_infomain; return TRUE; } diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp index 12944337..2ed86f7b 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp @@ -98,12 +98,20 @@ MxBool LegoCarBuildAnimPresenter::StringEndsOnYOrN(const LegoChar* p_string) (p_string[strlen(p_string) - 2] == 'Y') || (p_string[strlen(p_string) - 2] == 'y'); } +// STUB: LEGO1 0x10079c30 +// STUB: BETA10 0x100726a6 +MxBool LegoCarBuildAnimPresenter::FUN_10079c30(const LegoChar* p_name) +{ + // TODO + return FALSE; +} + // FUNCTION: LEGO1 0x10079ca0 // FUNCTION: BETA10 0x10072740 -MxBool LegoCarBuildAnimPresenter::FUN_10079ca0(const char* p_param1) +MxBool LegoCarBuildAnimPresenter::FUN_10079ca0(const LegoChar* p_name) { for (MxS16 i = 0; i < m_unk0xc0; i++) { - if (strcmpi(p_param1, m_unk0x128[i].m_unk0x00) == 0) { + if (strcmpi(p_name, m_unk0x128[i].m_unk0x00) == 0) { return TRUE; } } @@ -119,6 +127,7 @@ MxBool LegoCarBuildAnimPresenter::FUN_10079cf0(const LegoChar* p_string) } // FUNCTION: LEGO1 0x10079e20 +// FUNCTION: BETA10 0x10072959 const BoundingSphere& LegoCarBuildAnimPresenter::FUN_10079e20() { LegoROI* roi = m_unk0x140->GetROI(); diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 75f0ba2a..a4001bc2 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -792,6 +792,7 @@ inline void LoadIsle() } // FUNCTION: LEGO1 0x1003b060 +// FUNCTION: BETA10 0x10085adf void LegoGameState::SwitchArea(Area p_area) { m_previousArea = m_currentArea; diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index eeca0bd0..266ac1b1 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -32,6 +32,7 @@ #include // FUNCTION: LEGO1 0x1003dd70 +// FUNCTION: BETA10 0x100d3410 LegoROI* PickROI(MxLong p_a, MxLong p_b) { LegoVideoManager* videoManager = VideoManager(); @@ -70,7 +71,7 @@ void FUN_1003dde0(LegoROI* p_param1, MxFloat p_param2) // FUNCTION: LEGO1 0x1003ded0 // FUNCTION: BETA10 0x100d3802 -MxBool FUN_1003ded0(MxFloat p_param1[3], MxFloat p_param2[3], MxFloat p_param3[3]) +MxBool FUN_1003ded0(MxFloat p_param1[2], MxFloat p_param2[3], MxFloat p_param3[3]) { MxFloat local1c[4]; MxFloat local10[3]; diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index b8cdc37e..eafc5e1e 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -224,6 +224,7 @@ void LegoWorld::Destroy(MxBool p_fromDestructor) } // FUNCTION: LEGO1 0x1001f5e0 +// FUNCTION: BETA10 0x100d9f5f MxLong LegoWorld::Notify(MxParam& p_param) { MxLong result = 0; diff --git a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp index 3e3a3149..523cee3c 100644 --- a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp +++ b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp @@ -11,6 +11,7 @@ DECOMP_SIZE_ASSERT(LegoAct2, 0x1154) DECOMP_SIZE_ASSERT(LegoAct2State, 0x10) // STUB: LEGO1 0x1004fce0 +// STUB: BETA10 0x1003a5a0 LegoAct2::LegoAct2() { // TODO diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 157b7acd..5df6786c 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -52,6 +52,7 @@ // _sprintf // LIBRARY: LEGO1 0x1008b608 +// LIBRARY: BETA10 0x100f9660 // __ftol // LIBRARY: LEGO1 0x1008b630 @@ -702,4 +703,7 @@ // LIBRARY: BETA10 0x100fe5a0 // abort +// LIBRARY: BETA10 0x100ff82b +// __ctrandisp1 + #endif diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h index 5f471a8d..5ac9b2be 100644 --- a/LEGO1/mxgeometry/mxmatrix.h +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -9,6 +9,7 @@ class MxMatrix : public Matrix4 { public: // FUNCTION: LEGO1 0x1006b120 + // FUNCTION: BETA10 0x10015370 MxMatrix() : Matrix4(m_elements) {} // FUNCTION: LEGO1 0x10032770 diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index a0508c4d..181acedf 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -18,6 +18,7 @@ struct UnknownMatrixType { class Matrix4 { public: // FUNCTION: LEGO1 0x10004500 + // FUNCTION: BETA10 0x1000fc70 Matrix4(float (*p_data)[4]) { SetData(p_data); } // Note: virtual function overloads appear in the virtual table @@ -27,6 +28,7 @@ class Matrix4 { virtual void Equals(float (*p_data)[4]) { memcpy(m_data, p_data, sizeof(float) * 4 * 4); } // vtable+0x04 // FUNCTION: LEGO1 0x10002340 + // FUNCTION: BETA10 0x1000fcf0 virtual void Equals(const Matrix4& p_matrix) { memcpy(m_data, p_matrix.m_data, sizeof(float) * 4 * 4); diff --git a/LEGO1/realtime/orientableroi.cpp b/LEGO1/realtime/orientableroi.cpp index 451df324..9946e78e 100644 --- a/LEGO1/realtime/orientableroi.cpp +++ b/LEGO1/realtime/orientableroi.cpp @@ -22,6 +22,7 @@ OrientableROI::OrientableROI() // Maybe an overload based on MxMatrix type // FUNCTION: LEGO1 0x100a46a0 +// FUNCTION: BETA10 0x10165268 void OrientableROI::WrappedSetLocalTransform(const Matrix4& p_transform) { SetLocalTransform(p_transform); diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h index e263c5b1..3d638feb 100644 --- a/LEGO1/realtime/roi.h +++ b/LEGO1/realtime/roi.h @@ -36,6 +36,9 @@ class BoundingSphere { const float& Radius() const { return radius; } float& Radius() { return radius; } + // SYNTHETIC: BETA10 0x1001fb90 + // BoundingSphere::operator= + private: Mx3DPointFloat center; // 0x00 float radius; // 0x14 From 4878727393bfa15e4ebfc0438878b733413a3f54 Mon Sep 17 00:00:00 2001 From: Cameron <25990062+crtdll@users.noreply.github.com> Date: Fri, 20 Sep 2024 18:17:24 +0100 Subject: [PATCH 8/8] some educated guesses for unknown view manager names (#1106) * some educated guesses for unknown view manager names * Formatting * Pin pylint version * Use snake case for consistency (limited to this class) --------- Co-authored-by: Christian Semmler --- .github/workflows/format.yml | 2 +- .../src/common/legoanimationmanager.cpp | 6 +- LEGO1/viewmanager/viewmanager.cpp | 108 +++++++++--------- LEGO1/viewmanager/viewmanager.h | 46 ++++---- 4 files changed, 82 insertions(+), 80 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 9432beb0..da6ec354 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -28,7 +28,7 @@ jobs: - name: Install python libraries shell: bash run: | - pip install black==23.* pylint==3.* pytest==7.* -r tools/requirements.txt + pip install black==23.* pylint==3.2.7 pytest==7.* -r tools/requirements.txt - name: Run pylint and black shell: bash diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index fb8b39d0..fa42d032 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -1566,7 +1566,7 @@ MxU16 LegoAnimationManager::FUN_10062110( LegoPathActor* actor = (LegoPathActor*) p_roi->GetEntity(); if (actor != NULL && actor->GetBoundary() == p_boundary && actor->GetState() == 0) { - if (GetViewManager()->FUN_100a6150(p_roi->GetWorldBoundingBox())) { + if (GetViewManager()->IsBoundingBoxInFrustum(p_roi->GetWorldBoundingBox())) { Mx3DPointFloat direction(p_roi->GetWorldDirection()); if (direction.Dot(&direction, &p_direction) > 0.707) { @@ -1814,7 +1814,7 @@ void LegoAnimationManager::PurgeExtra(MxBool p_und) if ((p_und && !maOrPa) || (g_characters[m_extras[i].m_characterId].m_unk0x10 >= 0 && time - m_extras[i].m_unk0x08 > und && CharacterManager()->GetRefCount(roi) == 1 && - !viewManager->FUN_100a6150(roi->GetWorldBoundingBox()))) { + !viewManager->IsBoundingBoxInFrustum(roi->GetWorldBoundingBox()))) { m_unk0x414--; LegoPathActor* actor = CharacterManager()->GetExtraActor(roi->GetName()); @@ -2469,7 +2469,7 @@ MxBool LegoAnimationManager::FUN_10064010(LegoPathBoundary* p_boundary, LegoUnkn boundingBox.Min().Sub(vec); boundingBox.Max() = p1; boundingBox.Max().Add(vec); - return GetViewManager()->FUN_100a6150(boundingBox) == FALSE; + return GetViewManager()->IsBoundingBoxInFrustum(boundingBox) == FALSE; } // FUNCTION: LEGO1 0x10064120 diff --git a/LEGO1/viewmanager/viewmanager.cpp b/LEGO1/viewmanager/viewmanager.cpp index c0691587..677cfb84 100644 --- a/LEGO1/viewmanager/viewmanager.cpp +++ b/LEGO1/viewmanager/viewmanager.cpp @@ -9,19 +9,20 @@ DECOMP_SIZE_ASSERT(ViewManager, 0x1bc) // GLOBAL: LEGO1 0x100dbc78 -int g_unk0x100dbc78[8][3] = {{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0}, {0, 1, 1}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1}}; +int g_boundingBoxCornerMap[8][3] = + {{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0}, {0, 1, 1}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1}}; // GLOBAL: LEGO1 0x100dbcd8 -int g_unk0x100dbcd8[18] = {0, 1, 5, 6, 2, 3, 3, 0, 4, 1, 2, 6, 0, 3, 2, 4, 5, 6}; +int g_planePointIndexMap[18] = {0, 1, 5, 6, 2, 3, 3, 0, 4, 1, 2, 6, 0, 3, 2, 4, 5, 6}; // GLOBAL: LEGO1 0x10101050 -float g_unk0x10101050 = 4.0F; +float g_LODScaleFactor = 4.0F; // GLOBAL: LEGO1 0x10101054 -float g_unk0x10101054 = 0.00097656297; +float g_minLODThreshold = 0.00097656297; // GLOBAL: LEGO1 0x10101058 -int g_unk0x10101058 = 6; +int g_maxLODLevels = 6; // GLOBAL: LEGO1 0x1010105c float g_unk0x1010105c = 0.000125F; @@ -38,7 +39,7 @@ ViewManager::ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const Orie : scene(scene), flags(c_bit1 | c_bit2 | c_bit3 | c_bit4) { SetPOVSource(point_of_view); - unk0x28 = 0.09; + prev_render_time = 0.09; GetD3DRM(d3drm, pRenderer); GetFrame(frame, scene); width = 0.0; @@ -48,7 +49,7 @@ ViewManager::ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const Orie front = 0.0; back = 0.0; - memset(unk0xf0, 0, sizeof(unk0xf0)); + memset(transformed_points, 0, sizeof(transformed_points)); seconds_allowed = 1.0; } @@ -60,7 +61,7 @@ ViewManager::~ViewManager() // FUNCTION: LEGO1 0x100a6150 // FUNCTION: BETA10 0x10172164 -unsigned int ViewManager::FUN_100a6150(const BoundingBox& p_bounding_box) +unsigned int ViewManager::IsBoundingBoxInFrustum(const BoundingBox& p_bounding_box) { const Vector3* box[] = {&p_bounding_box.Min(), &p_bounding_box.Max()}; @@ -69,13 +70,14 @@ unsigned int ViewManager::FUN_100a6150(const BoundingBox& p_bounding_box) for (i = 0; i < 8; i++) { for (j = 0; j < 3; j++) { - und[i][j] = box[g_unk0x100dbc78[i][j]]->operator[](j); + und[i][j] = box[g_boundingBoxCornerMap[i][j]]->operator[](j); } } for (i = 0; i < 6; i++) { for (k = 0; k < 8; k++) { - if (unk0x150[i][0] * und[k][0] + unk0x150[i][2] * und[k][2] + unk0x150[i][1] * und[k][1] + unk0x150[i][3] >= + if (frustum_planes[i][0] * und[k][0] + frustum_planes[i][2] * und[k][2] + frustum_planes[i][1] * und[k][1] + + frustum_planes[i][3] >= 0.0f) { break; } @@ -239,7 +241,7 @@ inline void ViewManager::ManageVisibilityAndDetailRecursively(ViewROI* p_roi, in return; } - p_und = Unknown2(und, RealtimeView::GetUserMaxLodPower() * seconds_allowed, p_roi); + p_und = CalculateLODLevel(und, RealtimeView::GetUserMaxLodPower() * seconds_allowed, p_roi); } } @@ -277,11 +279,11 @@ void ViewManager::Update(float p_previousRenderTime, float) MxStopWatch stopWatch; stopWatch.Start(); - unk0x28 = p_previousRenderTime; + prev_render_time = p_previousRenderTime; flags |= c_bit1; if (flags & c_bit3) { - Unknown(); + CalculateFrustumTransformations(); } else if (flags & c_bit2) { UpdateViewTransformations(); @@ -295,7 +297,7 @@ void ViewManager::Update(float p_previousRenderTime, float) g_elapsedSeconds = stopWatch.ElapsedSeconds(); } -inline int ViewManager::Unknown() +inline int ViewManager::CalculateFrustumTransformations() { flags &= ~c_bit3; @@ -314,33 +316,33 @@ inline int ViewManager::Unknown() float fVar5 = fVar4 * fVar1; fVar4 = fVar4 * fVar2; - float* unk0x90 = (float*) this->unk0x90; + float* frustumVertices = (float*) this->frustum_vertices; // clang-format off - *unk0x90 = fVar2; unk0x90++; - *unk0x90 = fVar1; unk0x90++; - *unk0x90 = uVar6; unk0x90++; - *unk0x90 = fVar2; unk0x90++; - *unk0x90 = -fVar1; unk0x90++; - *unk0x90 = uVar6; unk0x90++; - *unk0x90 = -fVar2; unk0x90++; - *unk0x90 = -fVar1; unk0x90++; - *unk0x90 = uVar6; unk0x90++; - *unk0x90 = -fVar2; unk0x90++; - *unk0x90 = fVar1; unk0x90++; - *unk0x90 = uVar6; unk0x90++; - *unk0x90 = fVar4; unk0x90++; - *unk0x90 = fVar5; unk0x90++; - *unk0x90 = fVar3; unk0x90++; - *unk0x90 = fVar4; unk0x90++; - *unk0x90 = -fVar5; unk0x90++; - *unk0x90 = fVar3; unk0x90++; - *unk0x90 = -fVar4; unk0x90++; - *unk0x90 = -fVar5; unk0x90++; - *unk0x90 = fVar3; unk0x90++; - *unk0x90 = -fVar4; unk0x90++; - *unk0x90 = fVar5; unk0x90++; - *unk0x90 = fVar3; + *frustumVertices = fVar2; frustumVertices++; + *frustumVertices = fVar1; frustumVertices++; + *frustumVertices = uVar6; frustumVertices++; + *frustumVertices = fVar2; frustumVertices++; + *frustumVertices = -fVar1; frustumVertices++; + *frustumVertices = uVar6; frustumVertices++; + *frustumVertices = -fVar2; frustumVertices++; + *frustumVertices = -fVar1; frustumVertices++; + *frustumVertices = uVar6; frustumVertices++; + *frustumVertices = -fVar2; frustumVertices++; + *frustumVertices = fVar1; frustumVertices++; + *frustumVertices = uVar6; frustumVertices++; + *frustumVertices = fVar4; frustumVertices++; + *frustumVertices = fVar5; frustumVertices++; + *frustumVertices = fVar3; frustumVertices++; + *frustumVertices = fVar4; frustumVertices++; + *frustumVertices = -fVar5; frustumVertices++; + *frustumVertices = fVar3; frustumVertices++; + *frustumVertices = -fVar4; frustumVertices++; + *frustumVertices = -fVar5; frustumVertices++; + *frustumVertices = fVar3; frustumVertices++; + *frustumVertices = -fVar4; frustumVertices++; + *frustumVertices = fVar5; frustumVertices++; + *frustumVertices = fVar3; // clang-format on UpdateViewTransformations(); @@ -348,13 +350,13 @@ inline int ViewManager::Unknown() } } -inline int ViewManager::Unknown2(float p_und1, float p_und2, ViewROI* p_roi) +inline int ViewManager::CalculateLODLevel(float p_und1, float p_und2, ViewROI* p_roi) { int result; float i; - if (Unknown3(p_roi) != 0) { - if (p_und1 < g_unk0x10101054) { + if (IsROIVisibleAtLOD(p_roi) != 0) { + if (p_und1 < g_minLODThreshold) { return 0; } @@ -364,14 +366,14 @@ inline int ViewManager::Unknown2(float p_und1, float p_und2, ViewROI* p_roi) result = 0; } - for (i = p_und2; result < g_unk0x10101058 && p_und1 >= i; i *= g_unk0x10101050) { + for (i = p_und2; result < g_maxLODLevels && p_und1 >= i; i *= g_LODScaleFactor) { result++; } return result; } -inline int ViewManager::Unknown3(ViewROI* p_roi) +inline int ViewManager::IsROIVisibleAtLOD(ViewROI* p_roi) { const LODListBase* lods = p_roi->GetLODs(); @@ -411,21 +413,21 @@ void ViewManager::UpdateViewTransformations() for (i = 0; i < 8; i++) { for (j = 0; j < 3; j++) { - unk0xf0[i][j] = pov[3][j]; + transformed_points[i][j] = pov[3][j]; for (k = 0; k < 3; k++) { - unk0xf0[i][j] += pov[k][j] * unk0x90[i][k]; + transformed_points[i][j] += pov[k][j] * frustum_vertices[i][k]; } } } for (i = 0; i < 6; i++) { - Vector3 a(unk0xf0[g_unk0x100dbcd8[i * 3]]); - Vector3 b(unk0xf0[g_unk0x100dbcd8[i * 3 + 1]]); - Vector3 c(unk0xf0[g_unk0x100dbcd8[i * 3 + 2]]); + Vector3 a(transformed_points[g_planePointIndexMap[i * 3]]); + Vector3 b(transformed_points[g_planePointIndexMap[i * 3 + 1]]); + Vector3 c(transformed_points[g_planePointIndexMap[i * 3 + 2]]); Mx3DPointFloat x; Mx3DPointFloat y; - Vector3 u(unk0x150[i]); + Vector3 normal(frustum_planes[i]); x = c; ((Vector3&) x).Sub(b); // TODO: Fix call @@ -433,10 +435,10 @@ void ViewManager::UpdateViewTransformations() y = a; ((Vector3&) y).Sub(b); // TODO: Fix call - u.EqualsCross(&x, &y); - u.Unitize(); + normal.EqualsCross(&x, &y); + normal.Unitize(); - unk0x150[i][3] = -u.Dot(&u, &a); + frustum_planes[i][3] = -normal.Dot(&normal, &a); } flags |= c_bit4; diff --git a/LEGO1/viewmanager/viewmanager.h b/LEGO1/viewmanager/viewmanager.h index 4776fad7..92236873 100644 --- a/LEGO1/viewmanager/viewmanager.h +++ b/LEGO1/viewmanager/viewmanager.h @@ -23,7 +23,7 @@ class ViewManager { void Remove(ViewROI* p_roi); void RemoveAll(ViewROI* p_roi); - unsigned int FUN_100a6150(const BoundingBox& p_bounding_box); + unsigned int IsBoundingBoxInFrustum(const BoundingBox& p_bounding_box); void UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_und); void RemoveROIDetailFromScene(ViewROI* p_roi); void SetPOVSource(const OrientableROI* point_of_view); @@ -33,11 +33,11 @@ class ViewManager { void SetFrustrum(float fov, float front, float back); inline void ManageVisibilityAndDetailRecursively(ViewROI* p_roi, int p_und); void Update(float p_previousRenderTime, float); - inline int Unknown(); + inline int CalculateFrustumTransformations(); void UpdateViewTransformations(); - inline static int Unknown2(float p_und1, float p_und2, ViewROI* p_roi); - inline static int Unknown3(ViewROI* p_roi); + inline static int CalculateLODLevel(float p_und1, float p_und2, ViewROI* p_roi); + inline static int IsROIVisibleAtLOD(ViewROI* p_roi); const CompoundObject& GetROIs() { return rois; } void Add(ViewROI* p_roi) { rois.push_back(p_roi); } @@ -46,25 +46,25 @@ class ViewManager { // ViewManager::`scalar deleting destructor' private: - Tgl::Group* scene; // 0x04 - CompoundObject rois; // 0x08 - RealtimeView rt_view; // 0x14 - ROIList visible_rois; // 0x18 - float unk0x28; // 0x28 - float view_area_at_one; // 0x2c - unsigned int flags; // 0x30 - float width; // 0x34 - float height; // 0x38 - float view_angle; // 0x3c - MxMatrix pov; // 0x40 - float front; // 0x88 - float back; // 0x8c - float unk0x90[8][3]; // 0x90 - float unk0xf0[8][3]; // 0xf0 - float unk0x150[6][4]; // 0x150 - IDirect3DRM2* d3drm; // 0x1b0 - IDirect3DRMFrame2* frame; // 0x1b4 - float seconds_allowed; // 0x1b8 + Tgl::Group* scene; // 0x04 + CompoundObject rois; // 0x08 + RealtimeView rt_view; // 0x14 + ROIList visible_rois; // 0x18 + float prev_render_time; // 0x28 + float view_area_at_one; // 0x2c + unsigned int flags; // 0x30 + float width; // 0x34 + float height; // 0x38 + float view_angle; // 0x3c + MxMatrix pov; // 0x40 + float front; // 0x88 + float back; // 0x8c + float frustum_vertices[8][3]; // 0x90 + float transformed_points[8][3]; // 0xf0 + float frustum_planes[6][4]; // 0x150 + IDirect3DRM2* d3drm; // 0x1b0 + IDirect3DRMFrame2* frame; // 0x1b4 + float seconds_allowed; // 0x1b8 }; // TEMPLATE: LEGO1 0x10022030