From 03ffb9c5de0aefda46634d57bb8f6be5ed345917 Mon Sep 17 00:00:00 2001
From: Christian Semmler <mail@csemmler.com>
Date: Sat, 1 Jun 2024 17:29:37 -0400
Subject: [PATCH] Implement/match LegoCacheSound::Create and
 LegoLoadCacheSoundPresenter::StreamingTickle (#986)

* Implement/match LegoCacheSound::Create

* Naming

* Fix naming

* Fix parens
---
 .../legoomni/include/legocachesoundmanager.h  |   2 +-
 LEGO1/lego/legoomni/include/legocachsound.h   |  28 +++--
 .../include/legoloadcachesoundpresenter.h     |   8 +-
 .../src/audio/legocachesoundmanager.cpp       |   8 +-
 .../lego/legoomni/src/audio/legocachsound.cpp | 112 +++++++++++++++---
 .../src/audio/legoloadcachesoundpresenter.cpp |  50 +++++---
 LEGO1/omni/include/mxdsmediaaction.h          |   3 +
 LEGO1/omni/include/mxdssound.h                |   4 +-
 LEGO1/omni/src/audio/mxwavepresenter.cpp      |   4 +-
 9 files changed, 165 insertions(+), 54 deletions(-)

diff --git a/LEGO1/lego/legoomni/include/legocachesoundmanager.h b/LEGO1/lego/legoomni/include/legocachesoundmanager.h
index e8dbc204..8297b416 100644
--- a/LEGO1/lego/legoomni/include/legocachesoundmanager.h
+++ b/LEGO1/lego/legoomni/include/legocachesoundmanager.h
@@ -12,7 +12,7 @@
 struct LegoCacheSoundEntry {
 	LegoCacheSoundEntry() : m_sound(NULL), m_name(NULL) {}
 	LegoCacheSoundEntry(LegoCacheSound* p_sound, const char* p_name) : m_sound(p_sound), m_name(p_name) {}
-	LegoCacheSoundEntry(LegoCacheSound* p_sound) : m_sound(p_sound), m_name(p_sound->GetString0x48().GetData()) {}
+	LegoCacheSoundEntry(LegoCacheSound* p_sound) : m_sound(p_sound), m_name(p_sound->GetUnknown0x48().GetData()) {}
 
 	// FUNCTION: LEGO1 0x1003d030
 	~LegoCacheSoundEntry()
diff --git a/LEGO1/lego/legoomni/include/legocachsound.h b/LEGO1/lego/legoomni/include/legocachsound.h
index 86255152..10d0108b 100644
--- a/LEGO1/lego/legoomni/include/legocachsound.h
+++ b/LEGO1/lego/legoomni/include/legocachsound.h
@@ -26,12 +26,18 @@ public:
 		return !strcmp(p_name, LegoCacheSound::ClassName()) || MxCore::IsA(p_name);
 	}
 
-	virtual MxResult FUN_10006710();                   // vtable+0x14
+	virtual MxResult Create(
+		LPPCMWAVEFORMAT p_pwfx,
+		MxString p_mediaSrcPath,
+		MxS32 p_volume,
+		MxU8* p_data,
+		MxU32 p_dataSize
+	);                                                 // vtable+0x14
 	virtual void Destroy();                            // vtable+0x18
 	virtual void FUN_10006cd0(undefined4, undefined4); // vtable+0x1c
 
-	inline const MxString& GetString0x48() const { return m_string0x48; }
-	inline const undefined GetUnk0x58() const { return m_unk0x58; }
+	inline const MxString& GetUnknown0x48() const { return m_unk0x48; }
+	inline const undefined GetUnknown0x58() const { return m_unk0x58; }
 
 	LegoCacheSound* FUN_10006960();
 	MxResult FUN_10006a30(const char* p_str, MxBool);
@@ -44,20 +50,22 @@ public:
 
 private:
 	void Init();
+	void CopyData(MxU8* p_data, MxU32 p_dataSize);
+	MxString FUN_10006d80(const MxString& p_str);
 
 	LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x08
-	undefined m_unk0xc[4];          // 0x0c
+	undefined m_unk0x0c[4];         // 0x0c
 	Lego3DSound m_sound;            // 0x10
-	undefined* m_unk0x40;           // 0x40
-	undefined4 m_unk0x44;           // 0x44
-	MxString m_string0x48;          // 0x48
+	MxU8* m_data;                   // 0x40
+	MxU32 m_dataSize;               // 0x44
+	MxString m_unk0x48;             // 0x48
 	undefined m_unk0x58;            // 0x58
-	PCMWAVEFORMAT m_unk0x59;        // 0x59
+	PCMWAVEFORMAT m_wfx;            // 0x59
 	MxBool m_isLooping;             // 0x69
 	MxBool m_unk0x6a;               // 0x6a
-	undefined4 m_unk0x6c;           // 0x6c
+	MxS32 m_volume;                 // 0x6c
 	undefined m_unk0x70;            // 0x70
-	MxString m_string0x74;          // 0x74
+	MxString m_unk0x74;             // 0x74
 	undefined m_unk0x84;            // 0x84
 };
 
diff --git a/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h b/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h
index 883f4b01..6def0dee 100644
--- a/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h
+++ b/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h
@@ -37,10 +37,10 @@ private:
 	void Destroy(MxBool p_fromDestructor);
 
 	LegoCacheSound* m_cacheSound;  // 0x6c
-	undefined* m_unk0x70;          // 0x70
-	undefined* m_unk0x74;          // 0x74
-	undefined4 m_unk0x78;          // 0x78
-	undefined m_unk0x7c;           // 0x7c
+	MxU8* m_data;                  // 0x70
+	MxU8* m_pData;                 // 0x74
+	MxU32 m_dataSize;              // 0x78
+	MxBool m_unk0x7c;              // 0x7c
 	PCMWAVEFORMAT m_pcmWaveFormat; // 0x7d
 };
 
diff --git a/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp b/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp
index 8d645dfd..6628246b 100644
--- a/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp
+++ b/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp
@@ -37,7 +37,7 @@ MxResult LegoCacheSoundManager::Tickle()
 	for (Set100d6b4c::iterator setIter = m_set.begin(); setIter != m_set.end(); setIter++) {
 #endif
 		LegoCacheSound* sound = (*setIter).GetSound();
-		if (sound->GetUnk0x58()) {
+		if (sound->GetUnknown0x58()) {
 			sound->FUN_10006be0();
 		}
 	}
@@ -46,7 +46,7 @@ MxResult LegoCacheSoundManager::Tickle()
 	while (listIter != m_list.end()) {
 		LegoCacheSound* sound = (*listIter).GetSound();
 
-		if (sound->GetUnk0x58()) {
+		if (sound->GetUnknown0x58()) {
 			sound->FUN_10006be0();
 			listIter++;
 		}
@@ -84,7 +84,7 @@ LegoCacheSound* LegoCacheSoundManager::ManageSoundEntry(LegoCacheSound* p_sound)
 	if (it != m_set.end()) {
 		LegoCacheSound* sound = (*it).GetSound();
 
-		if (sound->GetUnk0x58()) {
+		if (sound->GetUnknown0x58()) {
 			m_list.push_back(LegoCacheSoundEntry(p_sound));
 			return p_sound;
 		}
@@ -117,7 +117,7 @@ LegoCacheSound* LegoCacheSoundManager::FUN_1003db10(LegoCacheSound* p_one, const
 		return NULL;
 	}
 
-	if (p_one->GetUnk0x58()) {
+	if (p_one->GetUnknown0x58()) {
 		LegoCacheSound* result = p_one->FUN_10006960();
 
 		if (result) {
diff --git a/LEGO1/lego/legoomni/src/audio/legocachsound.cpp b/LEGO1/lego/legoomni/src/audio/legocachsound.cpp
index b426da5a..19ba06f3 100644
--- a/LEGO1/lego/legoomni/src/audio/legocachsound.cpp
+++ b/LEGO1/lego/legoomni/src/audio/legocachsound.cpp
@@ -12,10 +12,9 @@ LegoCacheSound::LegoCacheSound()
 	Init();
 }
 
-// STUB: LEGO1 0x10006630
+// FUNCTION: LEGO1 0x10006630
 LegoCacheSound::~LegoCacheSound()
 {
-	// TODO
 	Destroy();
 }
 
@@ -23,39 +22,85 @@ LegoCacheSound::~LegoCacheSound()
 void LegoCacheSound::Init()
 {
 	m_dsBuffer = NULL;
-	m_unk0x40 = NULL;
+	m_data = NULL;
 	m_unk0x58 = 0;
-	memset(&m_unk0x59, 0, sizeof(m_unk0x59));
+	memset(&m_wfx, 0, sizeof(m_wfx));
 	m_unk0x6a = FALSE;
 	m_unk0x70 = 0;
 	m_isLooping = TRUE;
-	m_unk0x6c = 79;
+	m_volume = 79;
 	m_unk0x84 = 0;
 }
 
-// STUB: LEGO1 0x10006710
+// FUNCTION: LEGO1 0x10006710
 // FUNCTION: BETA10 0x10066505
-MxResult LegoCacheSound::FUN_10006710()
+MxResult LegoCacheSound::Create(
+	LPPCMWAVEFORMAT p_pwfx,
+	MxString p_mediaSrcPath,
+	MxS32 p_volume,
+	MxU8* p_data,
+	MxU32 p_dataSize
+)
 {
-	// TODO
+	WAVEFORMATEX wfx;
+	wfx.wFormatTag = p_pwfx->wf.wFormatTag;
+	wfx.nChannels = p_pwfx->wf.nChannels;
+	wfx.nSamplesPerSec = p_pwfx->wf.nSamplesPerSec;
+	wfx.nAvgBytesPerSec = p_pwfx->wf.nAvgBytesPerSec;
+	wfx.nBlockAlign = p_pwfx->wf.nBlockAlign;
+	wfx.wBitsPerSample = p_pwfx->wBitsPerSample;
+	wfx.cbSize = 0;
+
 	DSBUFFERDESC desc;
 	memset(&desc, 0, sizeof(desc));
 	desc.dwSize = sizeof(desc);
 
 	if (MxOmni::IsSound3D()) {
-		desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
+		desc.dwFlags =
+			DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE | DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME;
 	}
 	else {
-		desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
+		desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME;
 	}
 
+	desc.dwBufferBytes = p_dataSize;
+	desc.lpwfxFormat = &wfx;
+
 	if (SoundManager()->GetDirectSound()->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) {
 		return FAILURE;
 	}
 
+	m_volume = p_volume;
+
+	MxS32 volume = m_volume * SoundManager()->GetVolume() / 100;
+	MxS32 attenuation = SoundManager()->GetAttenuation(volume);
+	m_dsBuffer->SetVolume(attenuation);
+
+	if (m_sound.Create(m_dsBuffer, NULL, m_volume) != SUCCESS) {
+		m_dsBuffer->Release();
+		m_dsBuffer = NULL;
+		return FAILURE;
+	}
+
+	if (p_data != NULL && p_dataSize != 0) {
+		CopyData(p_data, p_dataSize);
+	}
+
+	m_unk0x48 = FUN_10006d80(p_mediaSrcPath);
+	m_wfx = *p_pwfx;
 	return SUCCESS;
 }
 
+// FUNCTION: LEGO1 0x100068e0
+// FUNCTION: BETA10 0x100667a0
+void LegoCacheSound::CopyData(MxU8* p_data, MxU32 p_dataSize)
+{
+	delete[] m_data;
+	m_dataSize = p_dataSize;
+	m_data = new MxU8[m_dataSize];
+	memcpy(m_data, p_data, m_dataSize);
+}
+
 // FUNCTION: LEGO1 0x10006920
 void LegoCacheSound::Destroy()
 {
@@ -65,7 +110,7 @@ void LegoCacheSound::Destroy()
 		m_dsBuffer = NULL;
 	}
 
-	delete m_unk0x40;
+	delete[] m_data;
 	Init();
 }
 
@@ -81,7 +126,7 @@ MxResult LegoCacheSound::FUN_10006a30(const char* p_str, MxBool)
 {
 	// TODO
 	// gets param2 from FUN_1003db10
-	if (!m_unk0x40 && !m_unk0x44) {
+	if (m_data == NULL && m_dataSize == 0) {
 		return FAILURE;
 	}
 
@@ -102,8 +147,8 @@ void LegoCacheSound::FUN_10006b80()
 	m_unk0x6a = FALSE;
 
 	m_sound.Reset();
-	if (m_string0x74.GetLength() != 0) {
-		m_string0x74 = "";
+	if (m_unk0x74.GetLength() != 0) {
+		m_unk0x74 = "";
 	}
 }
 
@@ -125,8 +170,8 @@ void LegoCacheSound::FUN_10006be0()
 		if (dwStatus == 0) {
 			m_dsBuffer->Stop();
 			m_sound.Reset();
-			if (m_string0x74.GetLength() != 0) {
-				m_string0x74 = "";
+			if (m_unk0x74.GetLength() != 0) {
+				m_unk0x74 = "";
 			}
 
 			m_unk0x58 = 0;
@@ -134,7 +179,7 @@ void LegoCacheSound::FUN_10006be0()
 		}
 	}
 
-	if (m_string0x74.GetLength() != 0 && !m_unk0x84) {
+	if (m_unk0x74.GetLength() != 0 && !m_unk0x84) {
 		if (!m_sound.UpdatePosition(m_dsBuffer)) {
 			if (m_unk0x6a) {
 				return;
@@ -160,3 +205,36 @@ void LegoCacheSound::SetDistance(MxS32 p_min, MxS32 p_max)
 void LegoCacheSound::FUN_10006cd0(undefined4, undefined4)
 {
 }
+
+// FUNCTION: LEGO1 0x10006d80
+// FUNCTION: BETA10 0x100670e7
+MxString LegoCacheSound::FUN_10006d80(const MxString& p_str)
+{
+	// TODO: Clean up code
+	char* str = p_str.GetData();
+	MxU32 length = strlen(str);
+
+	char* local28 = str + length;
+	char* local14 = local28;
+	char* pVar1 = local28;
+
+	do {
+		local14 = pVar1;
+		pVar1 = local14 + -1;
+
+		if (str == local14) {
+			break;
+		}
+
+		if (*pVar1 == '.') {
+			local28 = pVar1;
+		}
+	} while (*pVar1 != '\\');
+
+	local14 = pVar1;
+
+	MxString local24;
+	local14++;
+	*local28 = '\0';
+	return local24 = local14;
+}
diff --git a/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp b/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp
index 7bf31340..a0a66e89 100644
--- a/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp
@@ -4,6 +4,7 @@
 #include "legocachsound.h"
 #include "legosoundmanager.h"
 #include "misc.h"
+#include "mxdssound.h"
 #include "mxdssubscriber.h"
 #include "mxstreamchunk.h"
 #include "mxwavepresenter.h"
@@ -25,50 +26,71 @@ LegoLoadCacheSoundPresenter::~LegoLoadCacheSoundPresenter()
 // FUNCTION: LEGO1 0x100184e0
 void LegoLoadCacheSoundPresenter::Init()
 {
-	this->m_unk0x70 = NULL;
-	this->m_unk0x78 = 0;
-	this->m_unk0x7c = 0;
+	m_data = NULL;
+	m_dataSize = 0;
+	m_unk0x7c = FALSE;
 }
 
 // FUNCTION: LEGO1 0x100184f0
 void LegoLoadCacheSoundPresenter::Destroy(MxBool p_fromDestructor)
 {
-	delete[] this->m_unk0x70;
+	delete[] m_data;
 	MxWavePresenter::Destroy(p_fromDestructor);
 }
 
 // FUNCTION: LEGO1 0x10018510
+// FUNCTION: BETA10 0x1008c305
 void LegoLoadCacheSoundPresenter::ReadyTickle()
 {
 	MxStreamChunk* chunk = NextChunk();
 
 	if (chunk) {
 		WaveFormat* header = (WaveFormat*) chunk->GetData();
-		m_unk0x78 = 0;
+		m_dataSize = 0;
 
 		MxU8* data = new MxU8[header->m_dataSize];
-		m_unk0x70 = data;
-		m_unk0x74 = data;
+		m_data = data;
+		m_pData = data;
 
-		m_cacheSound = new LegoCacheSound;
-		memcpy(&m_pcmWaveFormat, &header->m_pcmWaveFormat, sizeof(m_pcmWaveFormat));
+		m_cacheSound = new LegoCacheSound();
+		m_pcmWaveFormat = header->m_pcmWaveFormat;
 
 		m_subscriber->FreeDataChunk(chunk);
 		ProgressTickleState(e_streaming);
 	}
 }
 
-// STUB: LEGO1 0x100185f0
+// FUNCTION: LEGO1 0x100185f0
+// FUNCTION: BETA10 0x1008c48f
 void LegoLoadCacheSoundPresenter::StreamingTickle()
 {
-	// TODO
-	EndAction();
+	MxStreamChunk* chunk = NextChunk();
+
+	if (chunk) {
+		if (chunk->GetChunkFlags() & DS_CHUNK_END_OF_STREAM) {
+			m_cacheSound->Create(
+				&m_pcmWaveFormat,
+				((MxDSSound*) m_action)->GetMediaSrcPath(),
+				((MxDSSound*) m_action)->GetVolume(),
+				m_data + 2,
+				m_dataSize - 2
+			);
+			ProgressTickleState(e_done);
+		}
+		else {
+			memcpy(m_pData, chunk->GetData(), chunk->GetLength());
+			m_dataSize += chunk->GetLength();
+			m_pData += chunk->GetLength();
+		}
+
+		m_subscriber->FreeDataChunk(chunk);
+	}
 }
 
 // FUNCTION: LEGO1 0x100186f0
 void LegoLoadCacheSoundPresenter::DoneTickle()
 {
-	if (m_unk0x7c != 0) {
+	if (m_unk0x7c) {
 		EndAction();
 	}
 }
@@ -80,7 +102,7 @@ MxResult LegoLoadCacheSoundPresenter::PutData()
 
 	if (m_currentTickleState == e_done) {
 		m_cacheSound = SoundManager()->GetCacheSoundManager()->ManageSoundEntry(m_cacheSound);
-		m_unk0x7c = 1;
+		m_unk0x7c = TRUE;
 	}
 
 	m_criticalSection.Leave();
diff --git a/LEGO1/omni/include/mxdsmediaaction.h b/LEGO1/omni/include/mxdsmediaaction.h
index 9b5f8604..ec393c05 100644
--- a/LEGO1/omni/include/mxdsmediaaction.h
+++ b/LEGO1/omni/include/mxdsmediaaction.h
@@ -42,6 +42,9 @@ public:
 
 	void CopyMediaSrcPath(const char* p_mediaSrcPath);
 
+	// FUNCTION: LEGO1 0x100186e0
+	inline const char* GetMediaSrcPath() { return m_mediaSrcPath; }
+
 	// FUNCTION: BETA10 0x1013c2e0
 	inline MxS32 GetFramesPerSecond() const { return m_framesPerSecond; }
 
diff --git a/LEGO1/omni/include/mxdssound.h b/LEGO1/omni/include/mxdssound.h
index c406ba92..bd4f7c6b 100644
--- a/LEGO1/omni/include/mxdssound.h
+++ b/LEGO1/omni/include/mxdssound.h
@@ -36,8 +36,8 @@ public:
 	// MxDSSound::`scalar deleting destructor'
 
 private:
-	MxU32 m_sizeOnDisk;
-	MxS32 m_volume; // 0xbc
+	MxU32 m_sizeOnDisk; // 0xb8
+	MxS32 m_volume;     // 0xbc
 };
 
 #endif // MXDSSOUND_H
diff --git a/LEGO1/omni/src/audio/mxwavepresenter.cpp b/LEGO1/omni/src/audio/mxwavepresenter.cpp
index 80e52dd1..caac77cc 100644
--- a/LEGO1/omni/src/audio/mxwavepresenter.cpp
+++ b/LEGO1/omni/src/audio/mxwavepresenter.cpp
@@ -299,8 +299,8 @@ void MxWavePresenter::SetVolume(MxS32 p_volume)
 	m_volume = p_volume;
 	if (m_dsBuffer != NULL) {
 		MxS32 volume = p_volume * MxOmni::GetInstance()->GetSoundManager()->GetVolume() / 100;
-		MxS32 otherVolume = MxOmni::GetInstance()->GetSoundManager()->GetAttenuation(volume);
-		m_dsBuffer->SetVolume(otherVolume);
+		MxS32 attenuation = MxOmni::GetInstance()->GetSoundManager()->GetAttenuation(volume);
+		m_dsBuffer->SetVolume(attenuation);
 	}
 
 	m_criticalSection.Leave();