diff --git a/CMakeLists.txt b/CMakeLists.txt index 0da82a25..818d3773 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,6 +140,7 @@ add_library(lego1 SHARED LEGO1/mxmatrix.cpp LEGO1/mxmediamanager.cpp LEGO1/mxmediapresenter.cpp + LEGO1/mxmidimanager.cpp LEGO1/mxmidipresenter.cpp LEGO1/mxmusicpresenter.cpp LEGO1/mxnotificationmanager.cpp @@ -272,4 +273,4 @@ if (MSVC) set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/incremental:no") set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "/incremental:no /debug") set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "/incremental:no") -endif() \ No newline at end of file +endif() diff --git a/LEGO1/mxaudiomanager.cpp b/LEGO1/mxaudiomanager.cpp index c7ecdc12..bb358e47 100644 --- a/LEGO1/mxaudiomanager.cpp +++ b/LEGO1/mxaudiomanager.cpp @@ -20,7 +20,21 @@ MxAudioManager::~MxAudioManager() // OFFSET: LEGO1 0x100b8df0 void MxAudioManager::Init() { - this->m_unk2c = 100; + this->m_volume = 100; +} + +// OFFSET: LEGO1 0x10029910 +MxS32 MxAudioManager::GetVolume() +{ + return this->m_volume; +} + +// OFFSET: LEGO1 0x100b8ea0 +void MxAudioManager::SetVolume(MxS32 p_volume) +{ + this->m_criticalSection.Enter(); + this->m_volume = p_volume; + this->m_criticalSection.Leave(); } // OFFSET: LEGO1 0x100b8e00 diff --git a/LEGO1/mxaudiomanager.h b/LEGO1/mxaudiomanager.h index 1403f36d..1ba5b6fd 100644 --- a/LEGO1/mxaudiomanager.h +++ b/LEGO1/mxaudiomanager.h @@ -11,18 +11,20 @@ class MxAudioManager : public MxMediaManager MxAudioManager(); virtual ~MxAudioManager() override; - virtual MxResult InitPresenters(); // vtable+14 - virtual void Destroy(); // vtable+18 + virtual MxResult InitPresenters() override; // vtable+14 + virtual void Destroy() override; // vtable+18 + virtual MxS32 GetVolume(); // vtable+28 + virtual void SetVolume(MxS32 p_volume); // vtable+2c private: - void LockedReinitialize(MxBool); + void LockedReinitialize(MxBool p_skipDestroy); static MxS32 g_unkCount; protected: void Init(); - undefined4 m_unk2c; + MxS32 m_volume; // 0x2c }; #endif // MXAUDIOMANAGER_H diff --git a/LEGO1/mxmidimanager.cpp b/LEGO1/mxmidimanager.cpp new file mode 100644 index 00000000..62bcb6d2 --- /dev/null +++ b/LEGO1/mxmidimanager.cpp @@ -0,0 +1,161 @@ +#include "mxmidimanager.h" +#include "mxomni.h" +#include + +DECOMP_SIZE_ASSERT(MxMIDIManager, 0x58); + +// OFFSET: LEGO1 0x100c05a0 +MxMIDIManager::MxMIDIManager() +{ + Init(); +} + +// OFFSET: LEGO1 0x100c0630 +MxMIDIManager::~MxMIDIManager() +{ + LockedReinitialize(TRUE); +} + +// OFFSET: LEGO1 0x100c0b20 +void MxMIDIManager::DeinitializeMIDI() +{ + m_criticalSection.Enter(); + + if (this->m_MIDIInitialized) + { + this->m_MIDIInitialized = FALSE; + midiStreamStop(this->m_MIDIStreamH); + midiOutUnprepareHeader(this->m_MIDIStreamH, this->m_MIDIHdrP, sizeof(MIDIHDR)); + midiOutSetVolume(this->m_MIDIStreamH, this->m_MIDIVolume); + midiStreamClose(this->m_MIDIStreamH); + delete this->m_MIDIHdrP; + this->InitData(); + } + + this->m_criticalSection.Leave(); +} + +// OFFSET: LEGO1 0x100c0690 +void MxMIDIManager::Init() +{ + this->m_multiplier = 100; + InitData(); +} + +// OFFSET: LEGO1 0x100c06a0 +void MxMIDIManager::InitData() +{ + this->m_MIDIStreamH = 0; + this->m_MIDIInitialized = FALSE; + this->m_unk38 = 0; + this->m_unk3c = 0; + this->m_unk40 = 0; + this->m_unk44 = 0; + this->m_unk48 = 0; + this->m_MIDIHdrP = NULL; +} + +// OFFSET: LEGO1 0x100c06c0 +void MxMIDIManager::LockedReinitialize(MxBool p_skipDestroy) +{ + if (this->m_thread) + { + this->m_thread->Terminate(); + if (this->m_thread) + { + delete m_thread; + } + } + else + { + TickleManager()->UnregisterClient(this); + } + + this->m_criticalSection.Enter(); + DeinitializeMIDI(); + Init(); + this->m_criticalSection.Leave(); + + if (!p_skipDestroy) + { + MxAudioManager::Destroy(); + } +} + +// OFFSET: LEGO1 0x100c0930 +void MxMIDIManager::Destroy() +{ + LockedReinitialize(FALSE); +} + +// OFFSET: LEGO1 0x100c09a0 +MxS32 MxMIDIManager::CalculateVolume(MxS32 p_volume) +{ + MxS32 result = (p_volume * 0xffff) / 100; + return (result << 0x10) | result; +} + +// OFFSET: LEGO1 0x100c07f0 +void MxMIDIManager::SetMIDIVolume() +{ + MxS32 result = (this->m_volume * this->m_multiplier) / 0x64; + HMIDISTRM streamHandle = this->m_MIDIStreamH; + + if (streamHandle) + { + MxS32 volume = CalculateVolume(result); + midiOutSetVolume(streamHandle, volume); + } +} + +// OFFSET: LEGO1 0x100c0940 +void MxMIDIManager::SetVolume(MxS32 p_volume) +{ + MxAudioManager::SetVolume(p_volume); + this->m_criticalSection.Enter(); + SetMIDIVolume(); + this->m_criticalSection.Leave(); +} + +// OFFSET: LEGO1 0x100c0840 +MxResult MxMIDIManager::StartMIDIThread(MxU32 p_frequencyMS, MxBool p_noRegister) +{ + MxResult status = FAILURE; + MxBool locked = FALSE; + + MxResult result = MxAudioManager::InitPresenters(); + if (result == SUCCESS) + { + if (p_noRegister) + { + this->m_criticalSection.Enter(); + locked = TRUE; + this->m_thread = new MxTickleThread(this, p_frequencyMS); + + if (this->m_thread) + { + if (this->m_thread->Start(0, 0) == SUCCESS) + { + status = SUCCESS; + } + } + } + else + { + TickleManager()->RegisterClient(this, p_frequencyMS); + status = SUCCESS; + } + } + + if (status != SUCCESS) + { + Destroy(); + } + + if (locked) + { + this->m_criticalSection.Leave(); + } + + return status; +} \ No newline at end of file diff --git a/LEGO1/mxmidimanager.h b/LEGO1/mxmidimanager.h new file mode 100644 index 00000000..f944d67d --- /dev/null +++ b/LEGO1/mxmidimanager.h @@ -0,0 +1,42 @@ +#ifndef MXMIDIMANAGER_H +#define MXMIDIMANAGER_H + +#include "decomp.h" +#include "mxaudiomanager.h" + +// VTABLE 0x100dc930 +// SIZE 0x58 +class MxMIDIManager : public MxAudioManager +{ +public: + MxMIDIManager(); + virtual ~MxMIDIManager() override; + + virtual void Destroy() override; // vtable+18 + virtual void SetVolume(MxS32 p_volume) override; // vtable+2c + virtual MxResult StartMIDIThread(MxU32 p_frequencyMS, MxU8 p_noRegister); // vtable+30 + +private: + void LockedReinitialize(MxBool p_skipDestroy); + void DeinitializeMIDI(); + + MxS32 CalculateVolume(MxS32 p_volume); + void SetMIDIVolume(); + + HMIDISTRM m_MIDIStreamH; // 0x30 + MxBool m_MIDIInitialized; // 0x34 + undefined4 m_unk38; // 0x38 + undefined4 m_unk3c; // 0x3c + undefined4 m_unk40; // 0x40 + undefined4 m_unk44; // 0x44 + undefined4 m_unk48; // 0x48 + MIDIHDR *m_MIDIHdrP; // 0x4c + MxS32 m_multiplier; // 0x50 + DWORD m_MIDIVolume; // 0x54 + +protected: + void Init(); + void InitData(); +}; + +#endif // MXMIDIMANAGER_H \ No newline at end of file