From 89b3c5f8ae75eb9424ba030e16730fce0d353817 Mon Sep 17 00:00:00 2001
From: Christian Semmler <mail@csemmler.com>
Date: Thu, 26 Oct 2023 07:19:59 -0400
Subject: [PATCH] Implement/match MxSoundManager::Create (#249)

* Implement/match MxSoundManager::Create

* Fix offset
---
 LEGO1/mxsoundmanager.cpp | 76 +++++++++++++++++++++++++++++++++++++---
 LEGO1/mxsoundmanager.h   |  4 +--
 2 files changed, 74 insertions(+), 6 deletions(-)

diff --git a/LEGO1/mxsoundmanager.cpp b/LEGO1/mxsoundmanager.cpp
index af973d49..95463e87 100644
--- a/LEGO1/mxsoundmanager.cpp
+++ b/LEGO1/mxsoundmanager.cpp
@@ -20,7 +20,7 @@ MxSoundManager::~MxSoundManager()
 // OFFSET: LEGO1 0x100ae830
 void MxSoundManager::Init()
 {
-	m_unk30 = 0;
+	m_directSound = NULL;
 	m_dsBuffer = NULL;
 }
 
@@ -49,11 +49,79 @@ void MxSoundManager::Destroy(MxBool p_fromDestructor)
 	}
 }
 
-// OFFSET: LEGO1 0x100ae8b0 STUB
+// OFFSET: LEGO1 0x100ae8b0
 MxResult MxSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread)
 {
-	// TODO
-	return FAILURE;
+	MxResult status = FAILURE;
+	MxBool locked = FALSE;
+
+	if (MxAudioManager::InitPresenters() != SUCCESS)
+		goto done;
+
+	m_criticalSection.Enter();
+	locked = TRUE;
+
+	if (DirectSoundCreate(NULL, &m_directSound, NULL) != DS_OK)
+		goto done;
+
+	if (m_directSound->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DSSCL_PRIORITY) != DS_OK)
+		goto done;
+
+	DSBUFFERDESC desc;
+	memset(&desc, 0, sizeof(desc));
+	desc.dwSize = sizeof(desc);
+
+	if (MxOmni::IsSound3D())
+		desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
+	else
+		desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
+
+	if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) {
+		if (!MxOmni::IsSound3D())
+			goto done;
+
+		MxOmni::SetSound3D(FALSE);
+		desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
+
+		if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK)
+			goto done;
+	}
+
+	WAVEFORMATEX format;
+
+	format.wFormatTag = WAVE_FORMAT_PCM;
+
+	if (MxOmni::IsSound3D())
+		format.nChannels = 2;
+	else
+		format.nChannels = 1;
+
+	format.nSamplesPerSec = 11025; // KHz
+	format.wBitsPerSample = 16;
+	format.nBlockAlign = format.nChannels * 2;
+	format.nAvgBytesPerSec = format.nBlockAlign * 11025;
+	format.cbSize = 0;
+
+	status = m_dsBuffer->SetFormat(&format);
+
+	if (p_createThread) {
+		m_thread = new MxTickleThread(this, p_frequencyMS);
+
+		if (!m_thread || m_thread->Start(0, 0) != SUCCESS)
+			goto done;
+	}
+	else
+		TickleManager()->RegisterClient(this, p_frequencyMS);
+
+	status = SUCCESS;
+
+done:
+	if (status != SUCCESS)
+		Destroy();
+
+	if (locked)
+		m_criticalSection.Leave();
+	return status;
 }
 
 // OFFSET: LEGO1 0x100aed10 STUB
diff --git a/LEGO1/mxsoundmanager.h b/LEGO1/mxsoundmanager.h
index 3f9ea5ca..ef42e8df 100644
--- a/LEGO1/mxsoundmanager.h
+++ b/LEGO1/mxsoundmanager.h
@@ -23,9 +23,9 @@ private:
 	void Init();
 	void Destroy(MxBool p_fromDestructor);
 
-	undefined4 m_unk30;
+	LPDIRECTSOUND m_directSound;    // 0x30
 	LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x34
-	undefined m_unk35[4];
+	undefined m_unk38[4];
 };
 
 #endif // MXSOUNDMANAGER_H