From d8bf4aebf4358523cf5f611ce63fd07bd4442be7 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 14 Nov 2023 15:25:14 -0500 Subject: [PATCH] Implement/match most of MxVideoPresenter (#280) * Bootstrap MxMediaPresenter * Implement/match MxMediaPresenter::Tickle and related * Implement AppendChunk and Enable * Implement/match most of MxVideoPresenter * Add missing offset --- LEGO1/mxdsaction.h | 34 +++---- LEGO1/mxdsmediaaction.h | 16 ++-- LEGO1/mxmediapresenter.cpp | 6 +- LEGO1/mxvideopresenter.cpp | 189 ++++++++++++++++++++++++++++++++++++- LEGO1/mxvideopresenter.h | 33 ++++--- 5 files changed, 232 insertions(+), 46 deletions(-) diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index e986438f..01e4af51 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -70,27 +70,21 @@ public: inline MxBool IsLooping() const { return m_flags & Flag_Looping; } inline MxBool IsBit3() const { return m_flags & Flag_Bit3; } -private: - MxU32 m_sizeOnDisk; - MxU32 m_flags; - MxLong m_startTime; - protected: - MxLong m_duration; - MxS32 m_loopCount; - -private: - MxVector3Data m_location; - MxVector3Data m_direction; - MxVector3Data m_up; - char* m_extraData; - MxU16 m_extraLength; - MxCore* m_unk84; - undefined4 m_unk88; - MxCore* m_unk8c; - -protected: - MxLong m_unkTimingField; // 0x90 + MxU32 m_sizeOnDisk; // 0x2c + MxU32 m_flags; // 0x30 + MxLong m_startTime; // 0x34 + MxLong m_duration; // 0x38 + MxS32 m_loopCount; // 0x3c + MxVector3Data m_location; // 0x40 + MxVector3Data m_direction; // 0x54 + MxVector3Data m_up; // 0x68 + char* m_extraData; // 0x7c + MxU16 m_extraLength; // 0x80 + MxCore* m_unk84; // 0x84 + undefined4 m_unk88; // 0x88 + MxCore* m_unk8c; // 0x8c + MxLong m_unkTimingField; // 0x90 }; #endif // MXDSACTION_H diff --git a/LEGO1/mxdsmediaaction.h b/LEGO1/mxdsmediaaction.h index f987e8f9..adeb049e 100644 --- a/LEGO1/mxdsmediaaction.h +++ b/LEGO1/mxdsmediaaction.h @@ -37,17 +37,17 @@ public: inline MxLong GetSustainTime() const { return this->m_sustainTime; } private: - MxU32 m_sizeOnDisk; - char* m_mediaSrcPath; + MxU32 m_sizeOnDisk; // 0x94 + char* m_mediaSrcPath; // 0x98 struct { undefined4 m_unk00; undefined4 m_unk04; - } m_unk9c; - MxS32 m_framesPerSecond; - MxS32 m_mediaFormat; - MxS32 m_paletteManagement; - MxLong m_sustainTime; - undefined4 m_unkb4; + } m_unk9c; // 0x9c + MxS32 m_framesPerSecond; // 0xa4 + MxS32 m_mediaFormat; // 0xa8 + MxS32 m_paletteManagement; // 0xac + MxLong m_sustainTime; // 0xb0 + undefined4 m_unkb4; // 0xb4 }; #endif // MXDSMEDIAACTION_H diff --git a/LEGO1/mxmediapresenter.cpp b/LEGO1/mxmediapresenter.cpp index 919b1fa8..0a4d691a 100644 --- a/LEGO1/mxmediapresenter.cpp +++ b/LEGO1/mxmediapresenter.cpp @@ -129,7 +129,7 @@ void MxMediaPresenter::StreamingTickle() else if (m_action->GetFlags() & MxDSAction::Flag_Looping) { AppendChunk(m_currentChunk); - if (!MxPresenter::IsEnabled()) { + if (!IsEnabled()) { m_subscriber->FUN_100b8390(m_currentChunk); m_currentChunk = NULL; } @@ -141,7 +141,7 @@ void MxMediaPresenter::StreamingTickle() // OFFSET: LEGO1 0x100b5e10 void MxMediaPresenter::RepeatingTickle() { - if (MxPresenter::IsEnabled() && !m_currentChunk) { + if (IsEnabled() && !m_currentChunk) { if (m_cursor) if (!m_cursor->Next(m_currentChunk)) m_cursor->Next(m_currentChunk); @@ -173,7 +173,7 @@ void MxMediaPresenter::DoneTickle() // OFFSET: LEGO1 0x100b6030 void MxMediaPresenter::Enable(MxBool p_enable) { - if (MxPresenter::IsEnabled() != p_enable) { + if (IsEnabled() != p_enable) { MxPresenter::Enable(p_enable); if (p_enable) { diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index e39a92bf..25a2d850 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -1,12 +1,14 @@ #include "mxvideopresenter.h" +#include "mxautolocker.h" +#include "mxdsmediaaction.h" #include "mxvideomanager.h" DECOMP_SIZE_ASSERT(MxVideoPresenter, 0x64); DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0xc); // OFFSET: LEGO1 0x1000c700 -void MxVideoPresenter::VTable0x5c(undefined4 p_unknown1) +void MxVideoPresenter::VTable0x5c(MxStreamChunk* p_chunk) { // Empty } @@ -18,7 +20,7 @@ void MxVideoPresenter::VTable0x60() } // OFFSET: LEGO1 0x1000c720 -void MxVideoPresenter::VTable0x68(undefined4 p_unknown1) +void MxVideoPresenter::VTable0x68(MxStreamChunk* p_chunk) { // Empty } @@ -232,10 +234,20 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor) MxMediaPresenter::Destroy(FALSE); } -// OFFSET: LEGO1 0x100b28b0 STUB +// OFFSET: LEGO1 0x100b28b0 void MxVideoPresenter::VTable0x64() { - // TODO + MxStreamChunk* chunk = NextChunk(); + + if (chunk->GetFlags() & MxStreamChunk::Flag_Bit2) { + m_subscriber->FUN_100b8390(chunk); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Repeating; + } + else { + VTable0x68(chunk); + m_subscriber->FUN_100b8390(chunk); + } } // OFFSET: LEGO1 0x100b2900 @@ -306,6 +318,175 @@ void MxVideoPresenter::VTable0x6c() // TODO } +// OFFSET: LEGO1 0x100b2f60 +void MxVideoPresenter::ReadyTickle() +{ + MxStreamChunk* chunk = NextChunk(); + + if (chunk) { + VTable0x5c(chunk); + m_subscriber->FUN_100b8390(chunk); + ParseExtra(); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Starting; + } +} + +// OFFSET: LEGO1 0x100b2fa0 +void MxVideoPresenter::StartingTickle() +{ + MxStreamChunk* chunk = FUN_100b5650(); + + if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { + VTable0x60(); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Streaming; + } +} + +// OFFSET: LEGO1 0x100b2fe0 +void MxVideoPresenter::StreamingTickle() +{ + if (m_action->GetFlags() & MxDSAction::Flag_Bit9) { + if (!m_currentChunk) + MxMediaPresenter::StreamingTickle(); + + if (m_currentChunk) { + VTable0x68(m_currentChunk); + m_currentChunk = NULL; + } + } + else { + for (MxS16 i = 0; i < m_unk5c; i++) { + if (!m_currentChunk) { + MxMediaPresenter::StreamingTickle(); + + if (!m_currentChunk) + break; + } + + if (m_action->GetElapsedTime() < m_currentChunk->GetTime()) + break; + + VTable0x68(m_currentChunk); + m_subscriber->FUN_100b8390(m_currentChunk); + m_currentChunk = NULL; + m_flags |= Flag_Bit1; + + if (m_currentTickleState != TickleState_Streaming) + break; + } + + if (m_flags & Flag_Bit1) + m_unk5c = 5; + } +} + +// OFFSET: LEGO1 0x100b3080 +void MxVideoPresenter::RepeatingTickle() +{ + if (IsEnabled()) { + if (m_action->GetFlags() & MxDSAction::Flag_Bit9) { + if (!m_currentChunk) + MxMediaPresenter::RepeatingTickle(); + + if (m_currentChunk) { + VTable0x68(m_currentChunk); + m_currentChunk = NULL; + } + } + else { + for (MxS16 i = 0; i < m_unk5c; i++) { + if (!m_currentChunk) { + MxMediaPresenter::RepeatingTickle(); + + if (!m_currentChunk) + break; + } + + if (m_action->GetElapsedTime() % m_action->GetLoopCount() < m_currentChunk->GetTime()) + break; + + VTable0x68(m_currentChunk); + m_currentChunk = NULL; + m_flags |= Flag_Bit1; + + if (m_currentTickleState != TickleState_Repeating) + break; + } + + if (m_flags & Flag_Bit1) + m_unk5c = 5; + } + } +} + +// OFFSET: LEGO1 0x100b3130 +void MxVideoPresenter::Unk5Tickle() +{ + MxLong sustainTime = ((MxDSMediaAction*) m_action)->GetSustainTime(); + + if (sustainTime != -1) { + if (sustainTime) { + if (m_unk60 == -1) + m_unk60 = m_action->GetElapsedTime(); + + if (m_action->GetElapsedTime() >= m_unk60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) { + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Done; + } + } + else { + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Done; + } + } +} + +// OFFSET: LEGO1 0x100b31a0 +MxResult MxVideoPresenter::AddToManager() +{ + MxResult result = FAILURE; + + if (MVideoManager()) { + result = SUCCESS; + MVideoManager()->AddPresenter(*this); + } + + return result; +} + +// OFFSET: LEGO1 0x100b31d0 +void MxVideoPresenter::EndAction() +{ + if (m_action) { + MxMediaPresenter::EndAction(); + MxAutoLocker lock(&m_criticalSection); + + if (m_bitmap) { + MxLong height = m_bitmap->GetBmiHeightAbs(); + MxLong width = m_bitmap->GetBmiWidth(); + MxS32 x = m_location.m_x; + MxS32 y = m_location.m_y; + + MxRect32 rect(x, y, x + width, y + height); + + MVideoManager()->InvalidateRect(rect); + } + } +} + +// OFFSET: LEGO1 0x100b3280 +undefined4 MxVideoPresenter::PutData() +{ + MxAutoLocker lock(&m_criticalSection); + + if (IsEnabled() && m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_unk5) + VTable0x6c(); + + return 0; +} + // OFFSET: LEGO1 0x100b3300 undefined MxVideoPresenter::VTable0x74() { diff --git a/LEGO1/mxvideopresenter.h b/LEGO1/mxvideopresenter.h index 14ad2d78..34406255 100644 --- a/LEGO1/mxvideopresenter.h +++ b/LEGO1/mxvideopresenter.h @@ -6,10 +6,14 @@ #include "mxmediapresenter.h" // VTABLE 0x100d4be8 +// SIZE 0x64 class MxVideoPresenter : public MxMediaPresenter { public: - MxVideoPresenter() { Init(); } + enum { + Flag_Bit1 = 0x01, + }; + MxVideoPresenter() { Init(); } virtual ~MxVideoPresenter() override; // vtable+0x0 // OFFSET: LEGO1 0x1000c820 @@ -28,13 +32,20 @@ public: void Init(); void Destroy(MxBool p_fromDestructor); - virtual void Destroy() override; // vtable+0x38 - + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StartingTickle() override; // vtable+0x1c + virtual void StreamingTickle() override; // vtable+0x20 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void Unk5Tickle() override; // vtable+0x28 + virtual MxResult AddToManager() override; // vtable+0x34 + virtual void Destroy() override; // vtable+0x38 + virtual void EndAction() override; // vtable+0x40 + virtual undefined4 PutData() override; // vtable+0x4c virtual MxBool IsHit(MxS32 p_x, MxS32 p_y) override; // vtable+0x50 - virtual void VTable0x5c(undefined4 p_unknown1); // vtable+0x5c + virtual void VTable0x5c(MxStreamChunk* p_chunk); // vtable+0x5c virtual void VTable0x60(); // vtable+0x60 virtual void VTable0x64(); // vtable+0x64 - virtual void VTable0x68(undefined4 p_unknown1); // vtable+0x68 + virtual void VTable0x68(MxStreamChunk* p_chunk); // vtable+0x68 virtual void VTable0x6c(); // vtable+0x6c virtual void VTable0x70(); // vtable+0x70 virtual undefined VTable0x74(); // vtable+0x74 @@ -56,12 +67,12 @@ public: MxS32 IsHit(MxU32 p_x, MxU32 p_y); }; - MxBitmap* m_bitmap; - AlphaMask* m_alpha; - LPDIRECTDRAWSURFACE m_unk58; - undefined2 m_unk5c; - unsigned char m_flags; // 0x5e - MxLong m_unk60; + MxBitmap* m_bitmap; // 0x50 + AlphaMask* m_alpha; // 0x54 + LPDIRECTDRAWSURFACE m_unk58; // 0x58 + MxS16 m_unk5c; // 0x5c + MxU8 m_flags; // 0x5e + MxLong m_unk60; // 0x60 }; #endif // MXVIDEOPRESENTER_H