diff --git a/CMakeLists.txt b/CMakeLists.txt index 05a82e5a..3a47fc78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,7 @@ add_library(lego1 SHARED LEGO1/mxpalette.cpp LEGO1/mxparam.cpp LEGO1/mxpresenter.cpp + LEGO1/mxpresenterlist.cpp LEGO1/mxscheduler.cpp LEGO1/mxsemaphore.cpp LEGO1/mxsmkpresenter.cpp diff --git a/LEGO1/mxhashtable.h b/LEGO1/mxhashtable.h index f9505bb5..3d91717b 100644 --- a/LEGO1/mxhashtable.h +++ b/LEGO1/mxhashtable.h @@ -67,7 +67,7 @@ class MxHashTable : protected HashTableParent virtual ~MxHashTable(); void Resize(); - void MxHashTable::Add(T* ); + void Add(T* ); virtual MxS8 Compare(T*, T*) = 0; diff --git a/LEGO1/mxlist.h b/LEGO1/mxlist.h new file mode 100644 index 00000000..da2c3e4e --- /dev/null +++ b/LEGO1/mxlist.h @@ -0,0 +1,196 @@ +#ifndef MXLIST_H +#define MXLIST_H + +#include "mxtypes.h" +#include "mxcore.h" + +template +// SIZE 0xc +class MxListEntry +{ +public: + MxListEntry() {} + MxListEntry(T *p_obj, MxListEntry *p_prev) { + m_obj = p_obj; + m_prev = p_prev; + m_next = NULL; + } + + T *m_obj; + MxListEntry *m_prev; + MxListEntry *m_next; +}; + +// VTABLE 0x100d6350 +// SIZE 0x10 +template +class MxListParent : public MxCore +{ +public: + MxListParent() { + m_count = 0; + m_customDestructor = Destroy; + } + // OFFSET: LEGO1 0x1001cdd0 + virtual ~MxListParent() {} + + // OFFSET: LEGO1 0x1001cd30 + static void Destroy(T *) {}; + + // OFFSET: LEGO1 0x1001cd20 + virtual MxS8 Compare(T *, T *) = 0; + +protected: + MxU32 m_count; // +0x8 + void (*m_customDestructor)(T *); // +0xc +}; + +// VTABLE 0x100d6368 +// SIZE 0x18 +template +class MxList : protected MxListParent +{ +public: + MxList() { + m_last = NULL; + m_first = NULL; + } + + virtual ~MxList(); + + void Append(T*); + + friend class MxListCursor; + +protected: + MxListEntry *m_first; // +0x10 + MxListEntry *m_last; // +0x14 + +private: + void _DeleteEntry(MxListEntry *match); +}; + +// VTABLE 0x100d6488 +template +class MxListCursor : public MxCore +{ +public: + MxListCursor(MxList *p_list) { + m_list = p_list; + m_match = NULL; + } + + MxBool Find(T *p_obj); + void Detach(); + MxBool Next(T*& p_obj); + void Reset() { m_match = NULL; } + +private: + MxList *m_list; + MxListEntry *m_match; +}; + +// Unclear purpose +// VTABLE 0x100d6530 +template +class MxListCursorChild : public MxListCursor +{ +public: + MxListCursorChild(MxList *p_list) : MxListCursor(p_list) {} +}; + +// Unclear purpose +// VTABLE 0x100d6470 +template +class MxListCursorChildChild : public MxListCursorChild +{ +public: + MxListCursorChildChild(MxList *p_list) : MxListCursorChild(p_list) {} +}; + +template +// OFFSET: LEGO1 0x1001ce20 +MxList::~MxList() +{ + for (MxListEntry *t = m_first;;) { + if (!t) + break; + + MxListEntry *next = t->m_next; + m_customDestructor(t->m_obj); + delete t; + t = next; + } + + m_count = 0; + m_last = NULL; + m_first = NULL; +} + +template +inline void MxList::Append(T *p_newobj) +{ + MxListEntry *currentLast = this->m_last; + MxListEntry *newEntry = new MxListEntry(p_newobj, currentLast); + + if (currentLast) + currentLast->m_next = newEntry; + else + this->m_first = newEntry; + + this->m_last = newEntry; + this->m_count++; +} + +template +inline void MxList::_DeleteEntry(MxListEntry *match) +{ + MxListEntry **pPrev = &match->m_prev; + MxListEntry **pNext = &match->m_next; + + if (match->m_prev) + match->m_prev->m_next = *pNext; + else + m_first = *pNext; + + if (*pNext) + (*pNext)->m_prev = *pPrev; + else + m_last = *pPrev; + + delete match; + m_count--; +} + +template +inline MxBool MxListCursor::Find(T *p_obj) +{ + for (m_match = m_list->m_first; + m_match && m_list->Compare(m_match->m_obj, p_obj); + m_match = m_match->m_next); + + return m_match != NULL; +} + +template +inline void MxListCursor::Detach() +{ + m_list->_DeleteEntry(m_match); + m_match = NULL; +} + +template +inline MxBool MxListCursor::Next(T*& p_obj) +{ + if (!m_match) + m_match = m_list->m_first; + else + m_match = m_match->m_next; + + if (m_match) + p_obj = m_match->m_obj; + + return m_match != NULL; +} + +#endif // MXLIST_H \ No newline at end of file diff --git a/LEGO1/mxmediamanager.cpp b/LEGO1/mxmediamanager.cpp index a6c8a9c0..b890eec4 100644 --- a/LEGO1/mxmediamanager.cpp +++ b/LEGO1/mxmediamanager.cpp @@ -1,8 +1,12 @@ #include "mxmediamanager.h" +#include "mxautolocker.h" +#include "mxpresenter.h" #include "decomp.h" DECOMP_SIZE_ASSERT(MxMediaManager, 0x2c); +typedef MxListCursorChildChild MxPresenterListCursor; + // OFFSET: LEGO1 0x100b84c0 MxMediaManager::MxMediaManager() { @@ -12,22 +16,86 @@ MxMediaManager::MxMediaManager() // OFFSET: LEGO1 0x100b8560 MxMediaManager::~MxMediaManager() { - Teardown(); + Destroy(); } // OFFSET: LEGO1 0x100b85d0 MxResult MxMediaManager::Init() { - this->m_unk08 = NULL; + this->m_presenters = NULL; this->m_thread = NULL; return SUCCESS; } -// OFFSET: LEGO1 0x100b8710 -void MxMediaManager::Teardown() +// OFFSET: LEGO1 0x100b8790 +MxResult MxMediaManager::Tickle() { - if(this->m_unk08) { - delete this->m_unk08; + MxAutoLocker lock(&this->m_criticalSection); + MxPresenter *presenter; + MxPresenterListCursor cursor(this->m_presenters); + + while (cursor.Next(presenter)) + presenter->Tickle(); + + cursor.Reset(); + + while (cursor.Next(presenter)) + presenter->VTable0x4c(); + + return SUCCESS; +} + +// OFFSET: LEGO1 0x100b85e0 +MxResult MxMediaManager::InitPresenters() +{ + MxAutoLocker lock(&this->m_criticalSection); + + this->m_presenters = new MxPresenterList; + + if (!this->m_presenters) { + this->Destroy(); + return FAILURE; } + + return SUCCESS; +} + +// OFFSET: LEGO1 0x100b8710 +void MxMediaManager::Destroy() +{ + MxAutoLocker lock(&this->m_criticalSection); + + if (this->m_presenters) + delete this->m_presenters; + Init(); -} \ No newline at end of file +} + +// OFFSET: LEGO1 0x100b88c0 +void MxMediaManager::AddPresenter(MxPresenter &p_presenter) +{ + MxAutoLocker lock(&this->m_criticalSection); + + this->m_presenters->Append(&p_presenter); +} + +// OFFSET: LEGO1 0x100b8980 +void MxMediaManager::RemovePresenter(MxPresenter &p_presenter) +{ + MxAutoLocker lock(&this->m_criticalSection); + MxPresenterListCursor cursor(this->m_presenters); + + if (cursor.Find(&p_presenter)) + cursor.Detach(); +} + +// OFFSET: LEGO1 0x100b8ac0 +void MxMediaManager::StopPresenters() +{ + MxAutoLocker lock(&this->m_criticalSection); + MxPresenter *presenter; + MxPresenterListCursor cursor(this->m_presenters); + + while (cursor.Next(presenter)) + presenter->EndAction(); +} diff --git a/LEGO1/mxmediamanager.h b/LEGO1/mxmediamanager.h index 76af63fb..9df073bc 100644 --- a/LEGO1/mxmediamanager.h +++ b/LEGO1/mxmediamanager.h @@ -4,20 +4,29 @@ #include "mxcore.h" #include "mxcriticalsection.h" #include "mxthread.h" +#include "mxpresenterlist.h" #include "mxtypes.h" // VTABLE 0x100dc6b0 +// SIZE 0x2c class MxMediaManager : public MxCore { public: MxMediaManager(); virtual ~MxMediaManager() override; + virtual MxResult Tickle(); // vtable+08 + virtual MxResult InitPresenters(); // vtable+14 + virtual void Destroy(); // vtable+18 + virtual void AddPresenter(MxPresenter &p_presenter); // vtable+1c + virtual void RemovePresenter(MxPresenter &p_presenter); // vtable+20 + virtual void StopPresenters(); // vtable+24 + MxResult Init(); - void Teardown(); + private: - void* m_unk08; - MxThread* m_thread; // 0xc + MxPresenterList *m_presenters; + MxThread *m_thread; // 0xc protected: MxCriticalSection m_criticalSection; // 0x10 diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h index 4b8659ec..87ef9645 100644 --- a/LEGO1/mxpresenter.h +++ b/LEGO1/mxpresenter.h @@ -77,7 +77,7 @@ class MxPresenter : public MxCore undefined4 m_unk0x10; undefined4 m_unk0x14; undefined4 m_unk0x18; - MxDSAction* m_action; // 0 + MxDSAction *m_action; // 0 MxCriticalSection m_criticalSection; MxPresenter *m_unkPresenter; // 0x3c }; diff --git a/LEGO1/mxpresenterlist.cpp b/LEGO1/mxpresenterlist.cpp new file mode 100644 index 00000000..ca3f15a8 --- /dev/null +++ b/LEGO1/mxpresenterlist.cpp @@ -0,0 +1,14 @@ +#include "mxpresenterlist.h" +#include "mxpresenter.h" + +DECOMP_SIZE_ASSERT(MxPresenterList, 0x18); + +// OFFSET: LEGO1 0x1001cd00 +MxS8 MxPresenterList::Compare(MxPresenter *p_var0, MxPresenter *p_var1) +{ + if (p_var1 == p_var0) + return 0; + if (p_var1 <= p_var0) + return 1; + return -1; +} diff --git a/LEGO1/mxpresenterlist.h b/LEGO1/mxpresenterlist.h new file mode 100644 index 00000000..9373040d --- /dev/null +++ b/LEGO1/mxpresenterlist.h @@ -0,0 +1,27 @@ +#ifndef MXPRESENTERLIST_H +#define MXPRESENTERLIST_H + +#include "mxlist.h" + +class MxPresenter; + +// Unclear what the purpose of this class is +// VTABLE 0x100d62f0 +// SIZE 0x18 +class MxPresenterListParent : public MxList +{ +public: + MxPresenterListParent() { + m_customDestructor = Destroy; + } +}; + +// VTABLE 0x100d6308 +// SIZE 0x18 +class MxPresenterList : public MxPresenterListParent +{ +public: + virtual MxS8 Compare(MxPresenter *, MxPresenter *); // +0x14 +}; + +#endif // MXPRESENTERLIST_H