From 4dd0d60dec1d2583441f5bc577cc248408f3cd7a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 11 Dec 2023 16:35:50 -0500 Subject: [PATCH] Implement/match more of MxCompositePresenter (#315) * Implement/match more of MxCompositePresenter * Use parameter to `DeleteAll` instead of separate function * StartAction match --- LEGO1/mxbackgroundaudiomanager.cpp | 2 +- LEGO1/mxcompositepresenter.cpp | 99 +++++++++++++++++++++++++++--- LEGO1/mxcompositepresenter.h | 18 +++--- LEGO1/mxdsaction.cpp | 4 +- LEGO1/mxdsaction.h | 14 ++++- LEGO1/mxdsmultiaction.h | 6 +- LEGO1/mxdsobject.h | 10 ++- LEGO1/mxlist.h | 16 ++++- LEGO1/mxmediapresenter.cpp | 4 +- LEGO1/mxpresenter.cpp | 2 +- LEGO1/mxpresenter.h | 5 ++ 11 files changed, 141 insertions(+), 39 deletions(-) diff --git a/LEGO1/mxbackgroundaudiomanager.cpp b/LEGO1/mxbackgroundaudiomanager.cpp index 36f9faa8..b89b5cf4 100644 --- a/LEGO1/mxbackgroundaudiomanager.cpp +++ b/LEGO1/mxbackgroundaudiomanager.cpp @@ -244,7 +244,7 @@ MxResult MxBackgroundAudioManager::PlayMusic(MxDSAction& p_action, undefined4 p_ m_action2.SetAtomId(p_action.GetAtomId()); m_action2.SetObjectId(p_action.GetObjectId()); m_action2.SetUnknown84(this); - m_action2.SetUnknown8c(this); + m_action2.SetOrigin(this); MxResult result = Start(&m_action2); diff --git a/LEGO1/mxcompositepresenter.cpp b/LEGO1/mxcompositepresenter.cpp index d21013d4..6cf14956 100644 --- a/LEGO1/mxcompositepresenter.cpp +++ b/LEGO1/mxcompositepresenter.cpp @@ -1,7 +1,11 @@ #include "mxcompositepresenter.h" #include "decomp.h" +#include "mxactionnotificationparam.h" +#include "mxautolocker.h" +#include "mxdsmultiaction.h" #include "mxnotificationmanager.h" +#include "mxobjectfactory.h" DECOMP_SIZE_ASSERT(MxCompositePresenter, 0x4c); @@ -13,6 +17,9 @@ MxBool MxCompositePresenter::VTable0x64(undefined4 p_unknown) return TRUE; } +// TEMPLATE: LEGO1 0x1004ae90 +// list >::_Buynode + // FUNCTION: LEGO1 0x100b60b0 MxCompositePresenter::MxCompositePresenter() { @@ -43,34 +50,106 @@ MxCompositePresenter::~MxCompositePresenter() NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x100b6410 -MxResult MxCompositePresenter::StartAction(MxStreamController*, MxDSAction*) +// FUNCTION: LEGO1 0x100b6410 +MxResult MxCompositePresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) { - // TODO - return SUCCESS; + MxAutoLocker lock(&m_criticalSection); + + MxResult result = FAILURE; + MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList(); + MxObjectFactory* factory = ObjectFactory(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + if (MxPresenter::StartAction(p_controller, p_action) == SUCCESS) { + // The usual cursor.Next() loop doesn't match here, even though + // the logic is the same. It does match when "deconstructed" into + // the following Head(), Current() and NextFragment() calls, + // but this seems unlikely to be the original code. + // The alpha debug build also uses Next(). + cursor.Head(); + while (cursor.Current(action)) { + cursor.NextFragment(); + + MxBool success = FALSE; + + action->CopyFlags(m_action->GetFlags()); + + const char* presenterName = PresenterNameDispatch(*action); + MxPresenter* presenter = (MxPresenter*) factory->Create(presenterName); + + if (presenter && presenter->AddToManager() == SUCCESS) { + presenter->SetCompositePresenter(this); + if (presenter->StartAction(p_controller, action) == SUCCESS) + success = TRUE; + } + + if (success) { + action->SetOrigin(this); + m_list.push_back(presenter); + } + else if (presenter) + delete presenter; + } + + result = SUCCESS; + } + + return result; } -// STUB: LEGO1 0x100b65e0 +// FUNCTION: LEGO1 0x100b65e0 void MxCompositePresenter::EndAction() { - // TODO + MxAutoLocker lock(&m_criticalSection); + + if (!m_action) + return; + + ((MxDSMultiAction*) m_action)->GetActionList()->DeleteAll(FALSE); + + while (!m_list.empty()) { + MxPresenter* presenter = m_list.front(); + m_list.pop_front(); + presenter->SetCompositePresenter(NULL); + presenter->EndAction(); + } + + MxDSAction* action = m_action; + MxPresenter::EndAction(); + + if (action && action->GetOrigin()) { + NotificationManager()->Send( + action->GetOrigin(), + &MxEndActionNotificationParam(c_notificationEndAction, this, action, FALSE) + ); + } } -// STUB: LEGO1 0x100b6760 +// FUNCTION: LEGO1 0x100b6760 MxLong MxCompositePresenter::Notify(MxParam& p) { - // TODO + MxAutoLocker lock(&m_criticalSection); + + switch (((MxNotificationParam&) p).GetNotification()) { + case c_notificationEndAction: + VTable0x58(p); + break; + case MXPRESENTER_NOTIFICATION: + VTable0x5c(p); + } + return 0; } // STUB: LEGO1 0x100b67f0 -void MxCompositePresenter::VTable0x58() +void MxCompositePresenter::VTable0x58(MxParam& p) { // TODO } // STUB: LEGO1 0x100b69b0 -void MxCompositePresenter::VTable0x5c() +void MxCompositePresenter::VTable0x5c(MxParam& p) { // TODO } diff --git a/LEGO1/mxcompositepresenter.h b/LEGO1/mxcompositepresenter.h index f64de154..38df4516 100644 --- a/LEGO1/mxcompositepresenter.h +++ b/LEGO1/mxcompositepresenter.h @@ -26,15 +26,15 @@ class MxCompositePresenter : public MxPresenter { return !strcmp(name, MxCompositePresenter::ClassName()) || MxPresenter::IsA(name); } - virtual MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c - virtual void EndAction() override; // vtable+0x40 - virtual void SetTickleState(TickleState p_tickleState) override; // vtable+0x44 - virtual MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual void VTable0x58(); // vtable+0x58 - virtual void VTable0x5c(); // vtable+0x5c - virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60 - virtual MxBool VTable0x64(undefined4 p_unknown); // vtable+0x64 + virtual MxResult StartAction(MxStreamController*, MxDSAction* p_action) override; // vtable+0x3c + virtual void EndAction() override; // vtable+0x40 + virtual void SetTickleState(TickleState p_tickleState) override; // vtable+0x44 + virtual MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 + virtual void Enable(MxBool p_enable) override; // vtable+0x54 + virtual void VTable0x58(MxParam& p); // vtable+0x58 + virtual void VTable0x5c(MxParam& p); // vtable+0x5c + virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60 + virtual MxBool VTable0x64(undefined4 p_unknown); // vtable+0x64 private: MxCompositePresenterList m_list; // 0x40 diff --git a/LEGO1/mxdsaction.cpp b/LEGO1/mxdsaction.cpp index 7d2f6645..a01bceff 100644 --- a/LEGO1/mxdsaction.cpp +++ b/LEGO1/mxdsaction.cpp @@ -28,7 +28,7 @@ MxDSAction::MxDSAction() this->m_up.Fill(FLT_MAX); this->m_unk84 = NULL; this->m_unk88 = 0; - this->m_unk8c = NULL; + this->m_origin = NULL; this->m_unkTimingField = INT_MIN; } @@ -84,7 +84,7 @@ void MxDSAction::CopyFrom(MxDSAction& p_dsAction) AppendData(p_dsAction.m_extraLength, p_dsAction.m_extraData); this->m_unk84 = p_dsAction.m_unk84; this->m_unk88 = p_dsAction.m_unk88; - this->m_unk8c = p_dsAction.m_unk8c; + this->m_origin = p_dsAction.m_origin; this->m_unkTimingField = p_dsAction.m_unkTimingField; } diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index e3c6f171..9047c730 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -64,12 +64,20 @@ class MxDSAction : public MxDSObject { inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } inline const Vector3Data& GetLocation() const { return m_location; } inline void SetUnknown84(MxCore* p_unk84) { m_unk84 = p_unk84; } - inline MxCore* GetUnknown8c() { return m_unk8c; } - inline void SetUnknown8c(MxCore* p_unk8c) { m_unk8c = p_unk8c; } + inline MxCore* GetOrigin() { return m_origin; } + inline void SetOrigin(MxCore* p_origin) { m_origin = p_origin; } inline MxBool IsLooping() const { return m_flags & Flag_Looping; } inline MxBool IsBit3() const { return m_flags & Flag_Bit3; } + inline void CopyFlags(MxU32 p_flags) + { + if (p_flags & MxDSAction::Flag_Looping) + SetFlags(GetFlags() | MxDSAction::Flag_Looping); + else if (p_flags & MxDSAction::Flag_Bit3) + SetFlags(GetFlags() | MxDSAction::Flag_Bit3); + } + protected: MxU32 m_sizeOnDisk; // 0x2c MxU32 m_flags; // 0x30 @@ -83,7 +91,7 @@ class MxDSAction : public MxDSObject { MxU16 m_extraLength; // 0x80 MxCore* m_unk84; // 0x84 undefined4 m_unk88; // 0x88 - MxCore* m_unk8c; // 0x8c + MxCore* m_origin; // 0x8c MxLong m_unkTimingField; // 0x90 }; diff --git a/LEGO1/mxdsmultiaction.h b/LEGO1/mxdsmultiaction.h index 267b7a9e..acc98d4e 100644 --- a/LEGO1/mxdsmultiaction.h +++ b/LEGO1/mxdsmultiaction.h @@ -36,9 +36,11 @@ class MxDSMultiAction : public MxDSAction { virtual MxBool HasId(MxU32 p_objectId) override; // vtable+34; virtual void SetUnkTimingField(MxLong p_unkTimingField) override; // vtable+38; + inline MxDSActionList* GetActionList() const { return m_actions; }; + protected: - MxU32 m_sizeOnDisk; - MxDSActionList* m_actions; + MxU32 m_sizeOnDisk; // 0x94 + MxDSActionList* m_actions; // 0x98 }; #endif // MXDSMULTIACTION_H diff --git a/LEGO1/mxdsobject.h b/LEGO1/mxdsobject.h index d4563d9a..967aadd7 100644 --- a/LEGO1/mxdsobject.h +++ b/LEGO1/mxdsobject.h @@ -37,18 +37,16 @@ class MxDSObject : public MxCore { virtual void Deserialize(char** p_source, MxS16 p_unk24); // vtable+1c; inline virtual void SetAtomId(MxAtomId p_atomId) { this->m_atomId = p_atomId; } // vtable+20; - inline const MxAtomId& GetAtomId() { return this->m_atomId; } + inline MxDSType GetType() const { return (MxDSType) this->m_type; } + inline const char* GetSourceName() const { return this->m_sourceName; } inline MxU32 GetObjectId() { return this->m_objectId; } + inline const MxAtomId& GetAtomId() { return this->m_atomId; } inline MxS16 GetUnknown24() { return this->m_unk24; } + inline void SetType(MxDSType p_type) { this->m_type = p_type; } inline void SetObjectId(MxU32 p_objectId) { this->m_objectId = p_objectId; } inline void SetUnknown24(MxS16 p_unk24) { this->m_unk24 = p_unk24; } - inline const char* GetSourceName() const { return this->m_sourceName; } - - inline void SetType(MxDSType p_type) { this->m_type = p_type; } - inline MxDSType GetType() const { return (MxDSType) this->m_type; } - private: MxU32 m_sizeOnDisk; // 0x8 MxU16 m_type; // 0xc diff --git a/LEGO1/mxlist.h b/LEGO1/mxlist.h index 8ca3d199..83b465b9 100644 --- a/LEGO1/mxlist.h +++ b/LEGO1/mxlist.h @@ -60,7 +60,7 @@ class MxList : protected MxCollection { virtual ~MxList() override; void Append(T p_obj) { _InsertEntry(p_obj, this->m_last, NULL); }; - void DeleteAll(); + void DeleteAll(MxBool p_destroy = TRUE); MxU32 GetCount() { return this->m_count; } void SetDestroy(void (*p_customDestructor)(T)) { this->m_customDestructor = p_customDestructor; } @@ -95,6 +95,13 @@ class MxListCursor : public MxCore { void Reset() { m_match = NULL; } void Prepend(T p_newobj); + // TODO: Probably shouldn't exist + void NextFragment() + { + if (m_match) + m_match = m_match->GetNext(); + } + private: MxList* m_list; MxListEntry* m_match; @@ -113,14 +120,17 @@ MxList::~MxList() } template -inline void MxList::DeleteAll() +inline void MxList::DeleteAll(MxBool p_destroy) { for (MxListEntry* t = m_first;;) { if (!t) break; MxListEntry* next = t->GetNext(); - this->m_customDestructor(t->GetValue()); + + if (p_destroy) + this->m_customDestructor(t->GetValue()); + delete t; t = next; } diff --git a/LEGO1/mxmediapresenter.cpp b/LEGO1/mxmediapresenter.cpp index 2d18a839..6ffdab71 100644 --- a/LEGO1/mxmediapresenter.cpp +++ b/LEGO1/mxmediapresenter.cpp @@ -170,9 +170,9 @@ void MxMediaPresenter::EndAction() m_subscriber = NULL; } - if (action && action->GetUnknown8c()) { + if (action && action->GetOrigin()) { NotificationManager()->Send( - action->GetUnknown8c(), + action->GetOrigin(), &MxEndActionNotificationParam(c_notificationEndAction, this, action, FALSE) ); } diff --git a/LEGO1/mxpresenter.cpp b/LEGO1/mxpresenter.cpp index cf11536e..4840c489 100644 --- a/LEGO1/mxpresenter.cpp +++ b/LEGO1/mxpresenter.cpp @@ -195,7 +195,7 @@ void MxPresenter::SendToCompositePresenter(MxOmni* p_omni) NotificationManager()->Send(m_compositePresenter, &MxNotificationParam(MXPRESENTER_NOTIFICATION, this)); - m_action->SetUnknown8c(p_omni ? p_omni : MxOmni::GetInstance()); + m_action->SetOrigin(p_omni ? p_omni : MxOmni::GetInstance()); m_compositePresenter = NULL; } } diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h index 3e2c372f..963fb652 100644 --- a/LEGO1/mxpresenter.h +++ b/LEGO1/mxpresenter.h @@ -74,6 +74,11 @@ class MxPresenter : public MxCore { inline MxS32 GetDisplayZ() const { return this->m_displayZ; } inline MxDSAction* GetAction() const { return this->m_action; } + inline void SetCompositePresenter(MxCompositePresenter* p_compositePresenter) + { + m_compositePresenter = p_compositePresenter; + } + protected: __declspec(dllexport) void Init(); void SendToCompositePresenter(MxOmni*);