From cdc7b43db2f943d605cb4450a6464330c7e2a4a1 Mon Sep 17 00:00:00 2001 From: Christian Semmler <mail@csemmler.com> Date: Fri, 22 Dec 2023 14:05:42 -0500 Subject: [PATCH] Implement/match MxLoopingSmkPresenter (#351) * Implement/match MxLoopingSmkPresenter * Rename variable * Rename variable --- LEGO1/mxdsmediaaction.h | 1 + LEGO1/mxlist.h | 22 +++++++ LEGO1/mxloopingsmkpresenter.cpp | 107 +++++++++++++++++++++++++++++++- LEGO1/mxloopingsmkpresenter.h | 12 +++- LEGO1/mxsmkpresenter.cpp | 22 ++++--- LEGO1/mxsmkpresenter.h | 6 +- 6 files changed, 156 insertions(+), 14 deletions(-) diff --git a/LEGO1/mxdsmediaaction.h b/LEGO1/mxdsmediaaction.h index 6cddd8c1..72fcf036 100644 --- a/LEGO1/mxdsmediaaction.h +++ b/LEGO1/mxdsmediaaction.h @@ -33,6 +33,7 @@ public: void CopyMediaSrcPath(const char* p_mediaSrcPath); + inline MxS32 GetFramesPerSecond() const { return this->m_framesPerSecond; } inline MxS32 GetMediaFormat() const { return this->m_mediaFormat; } inline MxS32 GetPaletteManagement() const { return this->m_paletteManagement; } inline MxLong GetSustainTime() const { return this->m_sustainTime; } diff --git a/LEGO1/mxlist.h b/LEGO1/mxlist.h index afdeadf4..11afe695 100644 --- a/LEGO1/mxlist.h +++ b/LEGO1/mxlist.h @@ -92,6 +92,8 @@ public: void Destroy(); MxBool Next(T& p_obj); MxBool Current(T& p_obj); + MxBool First(T& p_obj); + MxBool Last(T& p_obj); MxBool Advance(); MxBool HasMatch() { return m_match != NULL; } void SetValue(T p_obj); @@ -229,6 +231,26 @@ inline MxBool MxListCursor<T>::Current(T& p_obj) return m_match != NULL; } +template <class T> +inline MxBool MxListCursor<T>::First(T& p_obj) +{ + m_match = m_list->m_first; + if (m_match) + p_obj = m_match->GetValue(); + + return m_match != NULL; +} + +template <class T> +inline MxBool MxListCursor<T>::Last(T& p_obj) +{ + m_match = m_list->m_last; + if (m_match) + p_obj = m_match->GetValue(); + + return m_match != NULL; +} + template <class T> inline MxBool MxListCursor<T>::Advance() { diff --git a/LEGO1/mxloopingsmkpresenter.cpp b/LEGO1/mxloopingsmkpresenter.cpp index 26cf3d43..7f9a5851 100644 --- a/LEGO1/mxloopingsmkpresenter.cpp +++ b/LEGO1/mxloopingsmkpresenter.cpp @@ -1,6 +1,7 @@ #include "mxloopingsmkpresenter.h" -#include "decomp.h" +#include "mxautolocker.h" +#include "mxdsmediaaction.h" DECOMP_SIZE_ASSERT(MxLoopingSmkPresenter, 0x724); @@ -19,12 +20,112 @@ MxLoopingSmkPresenter::~MxLoopingSmkPresenter() // FUNCTION: LEGO1 0x100b49b0 void MxLoopingSmkPresenter::Init() { - this->m_unk0x720 = 0; + this->m_elapsedDuration = 0; this->m_flags &= 0xfd; this->m_flags &= 0xfb; } -// STUB: LEGO1 0x100b49d0 +// FUNCTION: LEGO1 0x100b49d0 void MxLoopingSmkPresenter::Destroy(MxBool p_fromDestructor) { + m_criticalSection.Enter(); + Init(); + m_criticalSection.Leave(); + + if (!p_fromDestructor) + MxSmkPresenter::Destroy(); +} + +// FUNCTION: LEGO1 0x100b4a00 +void MxLoopingSmkPresenter::VTable0x88() +{ + if (m_mxSmack.m_smackTag.Frames == m_currentFrame) { + m_currentFrame = 0; + // TODO: struct incorrect, Palette at wrong offset? + memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette)); + } +} + +// FUNCTION: LEGO1 0x100b4a30 +void MxLoopingSmkPresenter::NextFrame() +{ + MxStreamChunk* chunk = NextChunk(); + + if (chunk->GetFlags() & MxStreamChunk::Flag_Bit2) { + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Repeating; + } + else { + LoadFrame(chunk); + AppendChunk(chunk); + m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond(); + } + + m_subscriber->FUN_100b8390(chunk); +} + +// FUNCTION: LEGO1 0x100b4a90 +void MxLoopingSmkPresenter::VTable0x8c() +{ + if (m_action->GetDuration() < m_elapsedDuration) { + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_unk5; + } + else { + MxStreamChunk* chunk; + m_cursor->Current(chunk); + LoadFrame(chunk); + m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond(); + } +} + +// FUNCTION: LEGO1 0x100b4b00 +void MxLoopingSmkPresenter::RepeatingTickle() +{ + for (MxS16 i = 0; i < m_unk0x5c; i++) { + if (!m_cursor->HasMatch()) { + MxStreamChunk* chunk; + MxStreamChunkListCursor cursor(m_chunks); + + cursor.Last(chunk); + MxLong time = chunk->GetTime(); + + cursor.First(chunk); + + time -= chunk->GetTime(); + time += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond(); + + cursor.Reset(); + while (cursor.Next(chunk)) + chunk->SetTime(chunk->GetTime() + time); + + m_cursor->Advance(); + } + + MxStreamChunk* chunk; + m_cursor->Current(chunk); + + if (m_action->GetElapsedTime() < chunk->GetTime()) + break; + + VTable0x8c(); + + m_cursor->Next(chunk); + + if (m_currentTickleState != TickleState_Repeating) + break; + } +} + +// FUNCTION: LEGO1 0x100b4cd0 +MxResult MxLoopingSmkPresenter::AddToManager() +{ + MxAutoLocker lock(&m_criticalSection); + return MxSmkPresenter::AddToManager(); +} + +// FUNCTION: LEGO1 0x100b4d40 +void MxLoopingSmkPresenter::Destroy() +{ + Destroy(FALSE); } diff --git a/LEGO1/mxloopingsmkpresenter.h b/LEGO1/mxloopingsmkpresenter.h index b2eba1ca..2f20676e 100644 --- a/LEGO1/mxloopingsmkpresenter.h +++ b/LEGO1/mxloopingsmkpresenter.h @@ -18,11 +18,21 @@ public: return "MxLoopingSmkPresenter"; } + virtual void RepeatingTickle() override; // vtable+0x24 + virtual MxResult AddToManager() override; // vtable+0x34 + virtual void Destroy() override; // vtable+0x38 + virtual void NextFrame() override; // vtable+0x64 + virtual void VTable0x88() override; // vtable+0x88 + virtual void VTable0x8c(); // vtable+0x8c + private: void Init(); void Destroy(MxBool p_fromDestructor); - undefined4 m_unk0x720; + MxLong m_elapsedDuration; // 0x720 }; +// SYNTHETIC: LEGO1 0x100b4930 +// MxLoopingSmkPresenter::`scalar deleting destructor' + #endif // MXLOOPINGSMKPRESENTER_H diff --git a/LEGO1/mxsmkpresenter.cpp b/LEGO1/mxsmkpresenter.cpp index 442e59a7..709151c3 100644 --- a/LEGO1/mxsmkpresenter.cpp +++ b/LEGO1/mxsmkpresenter.cpp @@ -21,7 +21,7 @@ MxSmkPresenter::~MxSmkPresenter() // FUNCTION: LEGO1 0x100b38d0 void MxSmkPresenter::Init() { - m_unk0x71c = 0; + m_currentFrame = 0; memset(&m_mxSmack, 0, sizeof(m_mxSmack)); m_flags &= 0xfd; m_flags &= 0xfb; @@ -65,8 +65,8 @@ void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk) MxU8* bitmapData = m_bitmap->GetBitmapData(); MxU8* chunkData = p_chunk->GetData(); - MxBool paletteChanged = m_mxSmack.m_frameTypes[m_unk0x71c] & 1; - m_unk0x71c++; + MxBool paletteChanged = m_mxSmack.m_frameTypes[m_currentFrame] & 1; + m_currentFrame++; VTable0x88(); MxRectList list(TRUE); @@ -90,13 +90,13 @@ void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk) void MxSmkPresenter::VTable0x88() { if ((m_mxSmack.m_smackTag.SmackerType & 1) != 0) { - MxU32 und = (m_unk0x71c % m_mxSmack.m_smackTag.Frames); - if (1 < m_unk0x71c && und == 1) - m_unk0x71c = 1; + MxU32 und = (m_currentFrame % m_mxSmack.m_smackTag.Frames); + if (1 < m_currentFrame && und == 1) + m_currentFrame = 1; } else { - if (m_mxSmack.m_smackTag.Frames == m_unk0x71c) { - m_unk0x71c = 0; + if (m_mxSmack.m_smackTag.Frames == m_currentFrame) { + m_currentFrame = 0; // TODO: struct incorrect, Palette at wrong offset? memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette)); } @@ -111,6 +111,12 @@ void MxSmkPresenter::RealizePalette() delete palette; } +// FUNCTION: LEGO1 0x100b42f0 +MxResult MxSmkPresenter::AddToManager() +{ + return MxVideoPresenter::AddToManager(); +} + // FUNCTION: LEGO1 0x100b4300 void MxSmkPresenter::Destroy() { diff --git a/LEGO1/mxsmkpresenter.h b/LEGO1/mxsmkpresenter.h index c70894d7..95b6a201 100644 --- a/LEGO1/mxsmkpresenter.h +++ b/LEGO1/mxsmkpresenter.h @@ -25,6 +25,7 @@ public: return !strcmp(p_name, MxSmkPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); } + virtual MxResult AddToManager() override; // vtable+0x34 virtual void Destroy() override; // vtable+0x38 virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c virtual void CreateBitmap() override; // vtable+0x60 @@ -36,8 +37,9 @@ private: void Init(); void Destroy(MxBool p_fromDestructor); - MxSmack m_mxSmack; // 0x64 - undefined4 m_unk0x71c; // 0x71c +protected: + MxSmack m_mxSmack; // 0x64 + MxU32 m_currentFrame; // 0x71c }; #endif // MXSMKPRESENTER_H