diff --git a/LEGO1/mxdsaction.cpp b/LEGO1/mxdsaction.cpp index 91db4e57..3dc58a99 100644 --- a/LEGO1/mxdsaction.cpp +++ b/LEGO1/mxdsaction.cpp @@ -196,11 +196,8 @@ MxLong MxDSAction::GetUnkTimingField() return this->m_unkTimingField; } -// Win32 defines GetCurrentTime to GetTickCount -#undef GetCurrentTime - // OFFSET: LEGO1 0x100adcd0 -MxLong MxDSAction::GetCurrentTime() +MxLong MxDSAction::GetElapsedTime() { return Timer()->GetTime() - this->m_unkTimingField; } diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index c56a71e4..0aa90d8e 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -17,6 +17,7 @@ class MxDSAction : public MxDSObject { Flag_Bit4 = 0x08, Flag_Bit5 = 0x10, Flag_Enabled = 0x20, + Flag_Bit7 = 0x40, Flag_Parsed = 0x80, Flag_Bit9 = 0x200, Flag_Bit10 = 0x400, @@ -50,7 +51,7 @@ class MxDSAction : public MxDSObject { virtual MxBool HasId(MxU32 p_objectId); // vtable+34; virtual void SetUnkTimingField(MxLong p_unkTimingField); // vtable+38; virtual MxLong GetUnkTimingField(); // vtable+3c; - virtual MxLong GetCurrentTime(); // vtable+40; + virtual MxLong GetElapsedTime(); // vtable+40; void AppendData(MxU16 p_extraLength, const char* p_extraData); diff --git a/LEGO1/mxdschunk.cpp b/LEGO1/mxdschunk.cpp index 3abfb573..83a2d914 100644 --- a/LEGO1/mxdschunk.cpp +++ b/LEGO1/mxdschunk.cpp @@ -1,19 +1,21 @@ #include "mxdschunk.h" +DECOMP_SIZE_ASSERT(MxDSChunk, 0x1c); + // OFFSET: LEGO1 0x100be050 MxDSChunk::MxDSChunk() { - this->m_length = 0; - this->m_unk18 = NULL; - this->m_buffer = -1; - this->m_unk10 = 0; - this->m_unk14 = 0; + m_flags = 0; + m_unk18 = NULL; + m_unk0c = -1; + m_time = 0; + m_unk14 = 0; } // OFFSET: LEGO1 0x100be170 MxDSChunk::~MxDSChunk() { - if ((this->m_length & 1) != 0) { - delete this->m_unk18; + if (m_flags & Flag_Bit1) { + delete[] m_unk18; } } diff --git a/LEGO1/mxdschunk.h b/LEGO1/mxdschunk.h index c061a50e..1fe00460 100644 --- a/LEGO1/mxdschunk.h +++ b/LEGO1/mxdschunk.h @@ -1,12 +1,20 @@ #ifndef MXDSCHUNK_H #define MXDSCHUNK_H +#include "decomp.h" #include "mxcore.h" #include "mxtypes.h" // VTABLE 0x100dc7f8 +// SIZE 0x1c class MxDSChunk : public MxCore { public: + enum { + Flag_Bit1 = 0x01, + Flag_Bit2 = 0x02, + Flag_Bit3 = 0x04, + }; + MxDSChunk(); virtual ~MxDSChunk() override; @@ -23,13 +31,21 @@ class MxDSChunk : public MxCore { return !strcmp(name, MxDSChunk::ClassName()) || MxCore::IsA(name); } - // private: - MxS16 m_length; // 0x8 - MxLong m_buffer; // 0xc - MxLong m_unk10; // 0x10 - MxLong m_unk14; // 0x14 - void* m_unk18; // 0x18 - void* m_unk1c; // 0x1c + inline MxU16 GetFlags() { return m_flags; } + inline MxLong GetTime() { return m_time; } + + inline void ReleaseUnk18() + { + if (m_unk18) + delete[] m_unk18; + } + +private: + MxU16 m_flags; // 0x8 + undefined4 m_unk0c; // 0xc + MxLong m_time; // 0x10 + undefined4 m_unk14; // 0x14 + MxU8* m_unk18; // 0x18 }; #endif // MXDSCHUNK_H diff --git a/LEGO1/mxdssubscriber.cpp b/LEGO1/mxdssubscriber.cpp index 530a3a09..151572eb 100644 --- a/LEGO1/mxdssubscriber.cpp +++ b/LEGO1/mxdssubscriber.cpp @@ -21,8 +21,22 @@ MxResult MxDSSubscriber::FUN_100b7ed0(MxStreamController*, MxU32, MxS16) return SUCCESS; } +// OFFSET: LEGO1 0x100b8250 STUB +MxStreamChunk* MxDSSubscriber::FUN_100b8250() +{ + // TODO + return NULL; +} + +// OFFSET: LEGO1 0x100b8360 STUB +MxStreamChunk* MxDSSubscriber::FUN_100b8360() +{ + // TODO + return NULL; +} + // OFFSET: LEGO1 0x100b8390 STUB -void MxDSSubscriber::FUN_100b8390(MxDSChunk*) +void MxDSSubscriber::FUN_100b8390(MxStreamChunk*) { // TODO } diff --git a/LEGO1/mxdssubscriber.h b/LEGO1/mxdssubscriber.h index c8efc64d..d1d69956 100644 --- a/LEGO1/mxdssubscriber.h +++ b/LEGO1/mxdssubscriber.h @@ -3,7 +3,7 @@ #include "decomp.h" #include "mxcore.h" -#include "mxdschunk.h" +#include "mxstreamchunk.h" #include "mxstreamcontroller.h" // VTABLE 0x100dc698 @@ -27,7 +27,9 @@ class MxDSSubscriber : public MxCore { } MxResult FUN_100b7ed0(MxStreamController*, MxU32, MxS16); - void FUN_100b8390(MxDSChunk*); + MxStreamChunk* FUN_100b8250(); + MxStreamChunk* FUN_100b8360(); + void FUN_100b8390(MxStreamChunk*); private: undefined m_pad[0x44]; // 0x8 diff --git a/LEGO1/mxmediapresenter.cpp b/LEGO1/mxmediapresenter.cpp index d2ebd702..ae18354c 100644 --- a/LEGO1/mxmediapresenter.cpp +++ b/LEGO1/mxmediapresenter.cpp @@ -46,8 +46,7 @@ void MxMediaPresenter::Destroy(MxBool p_fromDestructor) MxStreamChunk* chunk; while (cursor.Next(chunk)) - if (chunk->m_unk18) - delete[] chunk->m_unk18; + chunk->ReleaseUnk18(); delete m_chunks; } @@ -59,23 +58,104 @@ void MxMediaPresenter::Destroy(MxBool p_fromDestructor) MxPresenter::Destroy(); } -// OFFSET: LEGO1 0x100b5d10 STUB +// OFFSET: LEGO1 0x100b5650 +MxStreamChunk* MxMediaPresenter::FUN_100b5650() +{ + MxStreamChunk* result = NULL; + + if (m_subscriber) { + result = m_subscriber->FUN_100b8360(); + + if (result && result->GetFlags() & MxDSChunk::Flag_Bit3) { + m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7); + m_subscriber->FUN_100b8250(); + m_subscriber->FUN_100b8390(result); + result = NULL; + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Done; + } + } + + return result; +} + +// OFFSET: LEGO1 0x100b56b0 +MxStreamChunk* MxMediaPresenter::NextChunk() +{ + MxStreamChunk* result = NULL; + + if (m_subscriber) { + result = m_subscriber->FUN_100b8250(); + + if (result && result->GetFlags() & MxDSChunk::Flag_Bit3) { + m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7); + m_subscriber->FUN_100b8390(result); + result = NULL; + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Done; + } + } + + return result; +} + +// OFFSET: LEGO1 0x100b5d10 MxResult MxMediaPresenter::Tickle() { - // TODO - return SUCCESS; + MxAutoLocker lock(&m_criticalSection); + + FUN_100b5650(); + + return MxPresenter::Tickle(); } -// OFFSET: LEGO1 0x100b5d90 STUB +// OFFSET: LEGO1 0x100b5d90 void MxMediaPresenter::StreamingTickle() { - // TODO + if (!m_currentChunk) { + m_currentChunk = NextChunk(); + + if (m_currentChunk) { + if (m_currentChunk->GetFlags() & MxDSChunk::Flag_Bit2) { + m_subscriber->FUN_100b8390(m_currentChunk); + m_currentChunk = NULL; + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Repeating; + } + else if (m_action->GetFlags() & MxDSAction::Flag_Looping) { + VTable0x58(m_currentChunk); + + if (!MxPresenter::IsEnabled()) { + m_subscriber->FUN_100b8390(m_currentChunk); + m_currentChunk = NULL; + } + } + } + } } -// OFFSET: LEGO1 0x100b5e10 STUB +// OFFSET: LEGO1 0x100b5e10 void MxMediaPresenter::RepeatingTickle() { - // TODO + if (MxPresenter::IsEnabled() && !m_currentChunk) { + if (m_cursor) + if (!m_cursor->Next(m_currentChunk)) + m_cursor->Next(m_currentChunk); + + if (m_currentChunk) { + MxLong time = m_currentChunk->GetTime(); + if (time <= m_action->GetElapsedTime() % m_action->GetLoopCount()) { + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_unk5; + } + } + else { + if (m_action->GetElapsedTime() <= m_action->GetStartTime() + m_action->GetDuration()) { + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_unk5; + } + } + } } // OFFSET: LEGO1 0x100b5ef0 @@ -129,7 +209,7 @@ void MxMediaPresenter::EndAction() } // OFFSET: LEGO1 0x100b5f10 STUB -void MxMediaPresenter::VTable0x58() +void MxMediaPresenter::VTable0x58(MxStreamChunk* p_chunk) { // TODO } diff --git a/LEGO1/mxmediapresenter.h b/LEGO1/mxmediapresenter.h index 6c40f93b..4fb35f7b 100644 --- a/LEGO1/mxmediapresenter.h +++ b/LEGO1/mxmediapresenter.h @@ -28,14 +28,14 @@ class MxMediaPresenter : public MxPresenter { return !strcmp(name, MxMediaPresenter::ClassName()) || MxPresenter::IsA(name); } - virtual void StreamingTickle() override; - virtual void RepeatingTickle() override; - virtual void DoneTickle() override; - virtual void Destroy() override; - virtual MxResult StartAction(MxStreamController*, MxDSAction*) override; - virtual void EndAction() override; - virtual void Enable(MxBool p_enable) override; - virtual void VTable0x58(); + virtual void StreamingTickle() override; // vtable+0x20 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void DoneTickle() override; // vtable+0x2c + virtual void Destroy() override; // vtable+0x38 + virtual MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c + virtual void EndAction() override; // vtable+0x40 + virtual void Enable(MxBool p_enable) override; // vtable+0x54 + virtual void VTable0x58(MxStreamChunk* p_chunk); // vtable+0x58 protected: MxDSSubscriber* m_subscriber; // 0x40 @@ -45,6 +45,8 @@ class MxMediaPresenter : public MxPresenter { void Init(); void Destroy(MxBool p_fromDestructor); + MxStreamChunk* FUN_100b5650(); + MxStreamChunk* NextChunk(); }; #endif // MXMEDIAPRESENTER_H diff --git a/LEGO1/mxstreamchunk.h b/LEGO1/mxstreamchunk.h index 18c137e5..92d7094e 100644 --- a/LEGO1/mxstreamchunk.h +++ b/LEGO1/mxstreamchunk.h @@ -4,6 +4,7 @@ #include "mxdschunk.h" // VTABLE 0x100dc2a8 +// SIZE 0x20 class MxStreamChunk : public MxDSChunk { // OFFSET: LEGO1 0x100b1fe0 inline virtual const char* ClassName() const override // vtable+0xc @@ -17,6 +18,8 @@ class MxStreamChunk : public MxDSChunk { { return !strcmp(name, MxStreamChunk::ClassName()) || MxDSChunk::IsA(name); } + + void* m_unk1c; // 0x1c }; #endif // MXSTREAMCHUNK_H