From 412dda3e99df1c57b82a693e49ae1af0fc9104e1 Mon Sep 17 00:00:00 2001
From: Christian Semmler <mail@csemmler.com>
Date: Sat, 16 Dec 2023 10:59:01 -0500
Subject: [PATCH] Implement/match rest of MxCompositeMediaPresenter (#331)

* Implement/match rest of MxCompositeMediaPresenter

* Fix annotation
---
 LEGO1/mxcompositemediapresenter.cpp | 80 ++++++++++++++++++++++++++---
 LEGO1/mxcompositemediapresenter.h   |  4 +-
 LEGO1/mxcompositepresenter.h        |  2 +-
 LEGO1/mxdsaction.h                  |  5 +-
 LEGO1/mxmediapresenter.h            |  2 +
 LEGO1/mxtransitionmanager.cpp       |  2 +-
 LEGO1/mxvideopresenter.cpp          |  6 +--
 7 files changed, 85 insertions(+), 16 deletions(-)

diff --git a/LEGO1/mxcompositemediapresenter.cpp b/LEGO1/mxcompositemediapresenter.cpp
index 454fb976..0547c815 100644
--- a/LEGO1/mxcompositemediapresenter.cpp
+++ b/LEGO1/mxcompositemediapresenter.cpp
@@ -5,6 +5,7 @@
 #include "legovideomanager.h"
 #include "mxautolocker.h"
 #include "mxdsmultiaction.h"
+#include "mxmediapresenter.h"
 #include "mxobjectfactory.h"
 #include "mxtimer.h"
 
@@ -14,7 +15,7 @@ DECOMP_SIZE_ASSERT(MxCompositeMediaPresenter, 0x50)
 MxCompositeMediaPresenter::MxCompositeMediaPresenter()
 {
 	m_unk0x4c = 0;
-	m_unk0x4e = 0;
+	m_unk0x4e = FALSE;
 	VideoManager()->AddPresenter(*this);
 }
 
@@ -85,22 +86,87 @@ MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller
 	return result;
 }
 
-// STUB: LEGO1 0x100742e0
+// FUNCTION: LEGO1 0x100742e0
 void MxCompositeMediaPresenter::StartingTickle()
 {
-	// TODO
+	MxAutoLocker lock(&m_criticalSection);
+
+	if (!m_unk0x4e) {
+		for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
+			if ((*it)->GetCurrentTickleState() < TickleState_Streaming) {
+				(*it)->Tickle();
+
+				if ((*it)->GetCurrentTickleState() == TickleState_Streaming ||
+					((*it)->GetAction() && (*it)->GetAction()->GetStartTime()))
+					m_unk0x4c++;
+			}
+		}
+
+		if (m_list.size() == m_unk0x4c) {
+			m_unk0x4e = TRUE;
+			m_unk0x4c = 0;
+
+			for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
+				if (!(*it)->GetAction()->GetStartTime())
+					m_unk0x4c++;
+			}
+		}
+	}
+	else {
+		for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
+			if (!(*it)->GetAction()->GetStartTime() && ((MxMediaPresenter*) *it)->FUN_100b5650() &&
+				!((*it)->GetAction()->GetFlags() & MxDSAction::Flag_Bit9)) {
+				(*it)->Tickle();
+				(*it)->GetAction()->SetFlags((*it)->GetAction()->GetFlags() | MxDSAction::Flag_Bit9);
+				m_unk0x4c--;
+			}
+		}
+
+		if (!m_unk0x4c) {
+			m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
+			m_currentTickleState = TickleState_Streaming;
+			MxLong time = Timer()->GetTime();
+			m_action->SetUnknown90(time);
+		}
+	}
 }
 
-// STUB: LEGO1 0x10074470
+// FUNCTION: LEGO1 0x10074470
 MxResult MxCompositeMediaPresenter::Tickle()
 {
-	// TODO
+	MxAutoLocker lock(&m_criticalSection);
+
+	switch (m_currentTickleState) {
+	case TickleState_Ready:
+		m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
+		m_currentTickleState = TickleState_Starting;
+	case TickleState_Starting:
+		StartingTickle();
+		break;
+	case TickleState_Streaming:
+	case TickleState_Repeating:
+	case TickleState_unk5:
+	case TickleState_Done: {
+		for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++)
+			(*it)->Tickle();
+		break;
+	}
+	default:
+		break;
+	}
+
 	return SUCCESS;
 }
 
-// STUB: LEGO1 0x10074540
+// FUNCTION: LEGO1 0x10074540
 MxResult MxCompositeMediaPresenter::PutData()
 {
-	// TODO
+	MxAutoLocker lock(&m_criticalSection);
+
+	if (m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_Done) {
+		for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++)
+			(*it)->PutData();
+	}
+
 	return SUCCESS;
 }
diff --git a/LEGO1/mxcompositemediapresenter.h b/LEGO1/mxcompositemediapresenter.h
index 93a74642..4f0efc76 100644
--- a/LEGO1/mxcompositemediapresenter.h
+++ b/LEGO1/mxcompositemediapresenter.h
@@ -30,8 +30,8 @@ public:
 	virtual MxResult PutData() override;                                              // vtable+0x4c
 
 private:
-	undefined2 m_unk0x4c; // 0x4c
-	undefined m_unk0x4e;  // 0x4e
+	MxS16 m_unk0x4c;  // 0x4c
+	MxBool m_unk0x4e; // 0x4e
 };
 
 // SYNTHETIC: LEGO1 0x10074000
diff --git a/LEGO1/mxcompositepresenter.h b/LEGO1/mxcompositepresenter.h
index 93148065..f6929b6d 100644
--- a/LEGO1/mxcompositepresenter.h
+++ b/LEGO1/mxcompositepresenter.h
@@ -59,6 +59,6 @@ protected:
 // List<MxPresenter *>::~List<MxPresenter *>
 
 // TEMPLATE: LEGO1 0x100b6cd0
-// MxList<MxDSAction *>::_DeleteEntry
+// MxList<MxDSAction *>::DeleteEntry
 
 #endif // MXCOMPOSITEPRESENTER_H
diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h
index 6ea57a4a..041322e7 100644
--- a/LEGO1/mxdsaction.h
+++ b/LEGO1/mxdsaction.h
@@ -19,8 +19,9 @@ public:
 		Flag_Enabled = 0x20,
 		Flag_Bit7 = 0x40,
 		Flag_World = 0x80,
-		Flag_Bit9 = 0x200,
-		Flag_Bit10 = 0x400,
+		Flag_Bit9 = 0x100,
+		Flag_Bit10 = 0x200,
+		Flag_Bit11 = 0x400,
 	};
 
 	__declspec(dllexport) MxDSAction();
diff --git a/LEGO1/mxmediapresenter.h b/LEGO1/mxmediapresenter.h
index 6e75000f..4a482a78 100644
--- a/LEGO1/mxmediapresenter.h
+++ b/LEGO1/mxmediapresenter.h
@@ -45,6 +45,8 @@ protected:
 
 	void Init();
 	void Destroy(MxBool p_fromDestructor);
+
+public:
 	MxStreamChunk* FUN_100b5650();
 	MxStreamChunk* NextChunk();
 };
diff --git a/LEGO1/mxtransitionmanager.cpp b/LEGO1/mxtransitionmanager.cpp
index 02366257..b319e6c9 100644
--- a/LEGO1/mxtransitionmanager.cpp
+++ b/LEGO1/mxtransitionmanager.cpp
@@ -102,7 +102,7 @@ MxResult MxTransitionManager::StartTransition(
 
 			MxDSAction* action = m_waitIndicator->GetAction();
 			action->SetLoopCount(10000);
-			action->SetFlags(action->GetFlags() | MxDSAction::Flag_Bit9);
+			action->SetFlags(action->GetFlags() | MxDSAction::Flag_Bit10);
 		}
 
 		MxU32 time = timeGetTime();
diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp
index 186c5016..3c3f7530 100644
--- a/LEGO1/mxvideopresenter.cpp
+++ b/LEGO1/mxvideopresenter.cpp
@@ -254,7 +254,7 @@ void MxVideoPresenter::NextFrame()
 MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y)
 {
 	MxDSAction* action = GetAction();
-	if ((action == NULL) || (((action->GetFlags() & MxDSAction::Flag_Bit10) == 0) && !IsEnabled()) ||
+	if ((action == NULL) || (((action->GetFlags() & MxDSAction::Flag_Bit11) == 0) && !IsEnabled()) ||
 		(!m_bitmap && !m_alpha))
 		return FALSE;
 
@@ -347,7 +347,7 @@ void MxVideoPresenter::StartingTickle()
 // FUNCTION: LEGO1 0x100b2fe0
 void MxVideoPresenter::StreamingTickle()
 {
-	if (m_action->GetFlags() & MxDSAction::Flag_Bit9) {
+	if (m_action->GetFlags() & MxDSAction::Flag_Bit10) {
 		if (!m_currentChunk)
 			MxMediaPresenter::StreamingTickle();
 
@@ -386,7 +386,7 @@ void MxVideoPresenter::StreamingTickle()
 void MxVideoPresenter::RepeatingTickle()
 {
 	if (IsEnabled()) {
-		if (m_action->GetFlags() & MxDSAction::Flag_Bit9) {
+		if (m_action->GetFlags() & MxDSAction::Flag_Bit10) {
 			if (!m_currentChunk)
 				MxMediaPresenter::RepeatingTickle();