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 7f110ada..e986438f 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -17,6 +17,7 @@ public: Flag_Bit4 = 0x08, Flag_Bit5 = 0x10, Flag_Enabled = 0x20, + Flag_Bit7 = 0x40, Flag_World = 0x80, Flag_Bit9 = 0x200, Flag_Bit10 = 0x400, @@ -50,7 +51,7 @@ public: 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..489a1611 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_data = NULL; + m_unk0c = -1; + m_time = 0; + m_length = 0; } // OFFSET: LEGO1 0x100be170 MxDSChunk::~MxDSChunk() { - if ((this->m_length & 1) != 0) { - delete this->m_unk18; + if (m_flags & Flag_Bit1) { + delete[] m_data; } } diff --git a/LEGO1/mxdschunk.h b/LEGO1/mxdschunk.h index c061a50e..e626d70b 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,27 @@ public: 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 void SetTime(MxLong p_time) { m_time = p_time; } + inline void SetLength(MxU32 p_length) { m_length = p_length; } + inline void SetData(MxU8* p_data) { m_data = p_data; } + + inline MxU16 GetFlags() { return m_flags; } + inline MxLong GetTime() { return m_time; } + inline MxU32 GetLength() { return m_length; } + inline MxU8* GetData() { return m_data; } + + inline void Release() + { + if (m_data) + delete[] m_data; + } + +private: + MxU16 m_flags; // 0x8 + undefined4 m_unk0c; // 0xc + MxLong m_time; // 0x10 + MxU32 m_length; // 0x14 + MxU8* m_data; // 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..4a57c841 100644 --- a/LEGO1/mxdssubscriber.h +++ b/LEGO1/mxdssubscriber.h @@ -4,6 +4,7 @@ #include "decomp.h" #include "mxcore.h" #include "mxdschunk.h" +#include "mxstreamchunk.h" #include "mxstreamcontroller.h" // VTABLE 0x100dc698 @@ -27,7 +28,9 @@ public: } 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 4a298014..919b1fa8 100644 --- a/LEGO1/mxmediapresenter.cpp +++ b/LEGO1/mxmediapresenter.cpp @@ -5,6 +5,7 @@ #include "mxcompositepresenter.h" #include "mxnotificationmanager.h" #include "mxstreamchunk.h" +#include "mxtimer.h" DECOMP_SIZE_ASSERT(MxMediaPresenter, 0x50); @@ -49,8 +50,7 @@ void MxMediaPresenter::Destroy(MxBool p_fromDestructor) MxStreamChunk* chunk; while (cursor.Next(chunk)) - if (chunk->m_unk18) - delete[] chunk->m_unk18; + chunk->Release(); delete m_chunks; } @@ -62,23 +62,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) { + AppendChunk(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 @@ -89,10 +170,24 @@ void MxMediaPresenter::DoneTickle() EndAction(); } -// OFFSET: LEGO1 0x100b6030 STUB +// OFFSET: LEGO1 0x100b6030 void MxMediaPresenter::Enable(MxBool p_enable) { - // TODO + if (MxPresenter::IsEnabled() != p_enable) { + MxPresenter::Enable(p_enable); + + if (p_enable) { + MxLong time = Timer()->GetTime(); + m_action->SetUnkTimingField(time); + SetTickleState(TickleState_Repeating); + } + else { + if (m_cursor) + m_cursor->Reset(); + m_currentChunk = NULL; + SetTickleState(TickleState_Done); + } + } } // OFFSET: LEGO1 0x100b5700 @@ -158,8 +253,16 @@ void MxMediaPresenter::EndAction() } } -// OFFSET: LEGO1 0x100b5f10 STUB -void MxMediaPresenter::VTable0x58() +// OFFSET: LEGO1 0x100b5f10 +void MxMediaPresenter::AppendChunk(MxStreamChunk* p_chunk) { - // TODO + MxStreamChunk* chunk = new MxStreamChunk; + + MxU32 length = p_chunk->GetLength(); + chunk->SetLength(length); + chunk->SetData(new MxU8[length]); + chunk->SetTime(p_chunk->GetTime()); + + memcpy(chunk->GetData(), p_chunk->GetData(), chunk->GetLength()); + m_chunks->Append(chunk); } diff --git a/LEGO1/mxmediapresenter.h b/LEGO1/mxmediapresenter.h index 6c40f93b..3706b225 100644 --- a/LEGO1/mxmediapresenter.h +++ b/LEGO1/mxmediapresenter.h @@ -28,14 +28,14 @@ public: 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 AppendChunk(MxStreamChunk* p_chunk); // vtable+0x58 protected: MxDSSubscriber* m_subscriber; // 0x40 @@ -45,6 +45,8 @@ protected: 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..f31f891a 100644 --- a/LEGO1/mxstreamchunk.h +++ b/LEGO1/mxstreamchunk.h @@ -4,7 +4,11 @@ #include "mxdschunk.h" // VTABLE 0x100dc2a8 +// SIZE 0x20 class MxStreamChunk : public MxDSChunk { +public: + inline MxStreamChunk() : m_unk1c(NULL) {} + // OFFSET: LEGO1 0x100b1fe0 inline virtual const char* ClassName() const override // vtable+0xc { @@ -17,6 +21,9 @@ class MxStreamChunk : public MxDSChunk { { return !strcmp(name, MxStreamChunk::ClassName()) || MxDSChunk::IsA(name); } + +private: + void* m_unk1c; // 0x1c }; #endif // MXSTREAMCHUNK_H