diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index 03afb148..de66cdc6 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -52,6 +52,9 @@ class LegoState : public MxCore { MxU16 m_unk0x08; // 0x08 StateStruct(); + + MxU32 FUN_10014d00(); + MxBool FUN_10014de0(MxU32 p_objectId); }; }; diff --git a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h index 787484b0..cb2e3435 100644 --- a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h +++ b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h @@ -31,6 +31,8 @@ class MxBackgroundAudioManager : public MxCore { return !strcmp(p_name, MxBackgroundAudioManager::ClassName()) || MxCore::IsA(p_name); } + inline MxBool GetMusicEnabled() { return m_musicEnabled; } + void StartAction(MxParam& p_param); void StopAction(MxParam& p_param); MxResult PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, undefined4 p_unk0x13c); diff --git a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h index 0903f557..1ead16da 100644 --- a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h +++ b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h @@ -43,7 +43,6 @@ class MxControlPresenter : public MxCompositePresenter { private: MxBool FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter); - void FUN_10044540(undefined2); undefined2 m_unk0x4c; // 0x4c MxS16 m_unk0x4e; // 0x4e diff --git a/LEGO1/lego/legoomni/include/radio.h b/LEGO1/lego/legoomni/include/radio.h index 1adde033..347a22d1 100644 --- a/LEGO1/lego/legoomni/include/radio.h +++ b/LEGO1/lego/legoomni/include/radio.h @@ -1,6 +1,8 @@ #ifndef RADIO_H #define RADIO_H +#include "legocontrolmanager.h" +#include "mxactionnotificationparam.h" #include "mxcore.h" #include "radiostate.h" @@ -32,10 +34,15 @@ class Radio : public MxCore { // Radio::`scalar deleting destructor' private: - RadioState* m_state; // 0x08 - MxBool m_unk0x0c; // 0x0c + RadioState* m_state; // 0x08 + MxBool m_unk0x0c; // 0x0c + MxBool m_bgAudioPreviouslyEnabled; // 0x0d void CreateRadioState(); + void Play(); + void Stop(); + MxLong HandleEndAction(MxEndActionNotificationParam& p_param); + MxLong HandleNotification17(LegoControlManagerEvent& p_param); }; #endif // RADIO_H diff --git a/LEGO1/lego/legoomni/include/radiostate.h b/LEGO1/lego/legoomni/include/radiostate.h index fa992da5..adfbe623 100644 --- a/LEGO1/lego/legoomni/include/radiostate.h +++ b/LEGO1/lego/legoomni/include/radiostate.h @@ -2,6 +2,7 @@ #define RADIOSTATE_H #include "legostate.h" +#include "mxdsaction.h" // VTABLE: LEGO1 0x100d6d28 // SIZE 0x30 @@ -27,10 +28,17 @@ class RadioState : public LegoState { // SYNTHETIC: LEGO1 0x1002d020 // RadioState::`scalar deleting destructor' + inline MxBool IsActive() { return m_active; } + + inline void SetActive(MxBool p_active) { m_active = p_active; } + + undefined4 FUN_1002d090(); + MxBool FUN_1002d0c0(const MxAtomId& p_atom, MxU32 p_objectId); + private: StateStruct m_unk0x08[3]; // 0x08 MxS16 m_unk0x2c; // 0x2c - undefined m_unk0x2e; // 0x2e + MxBool m_active; // 0x2e }; #endif // RADIOSTATE_H diff --git a/LEGO1/lego/legoomni/src/common/legostate.cpp b/LEGO1/lego/legoomni/src/common/legostate.cpp index 33248b5c..5d3bcf4e 100644 --- a/LEGO1/lego/legoomni/src/common/legostate.cpp +++ b/LEGO1/lego/legoomni/src/common/legostate.cpp @@ -3,6 +3,20 @@ DECOMP_SIZE_ASSERT(LegoState, 0x08) DECOMP_SIZE_ASSERT(LegoState::StateStruct, 0x0c) +// STUB: LEGO1 0x10014d00 +MxU32 LegoState::StateStruct::FUN_10014d00() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10014de0 +MxBool LegoState::StateStruct::FUN_10014de0(MxU32 p_objectId) +{ + // TODO + return FALSE; +} + // FUNCTION: LEGO1 0x10017c00 LegoState::StateStruct::StateStruct() { diff --git a/LEGO1/lego/legoomni/src/isle/radio.cpp b/LEGO1/lego/legoomni/src/isle/radio.cpp index 995d4ae0..ad5d96b7 100644 --- a/LEGO1/lego/legoomni/src/isle/radio.cpp +++ b/LEGO1/lego/legoomni/src/isle/radio.cpp @@ -3,6 +3,8 @@ #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoomni.h" +#include "mxbackgroundaudiomanager.h" +#include "mxcontrolpresenter.h" #include "mxnotificationmanager.h" DECOMP_SIZE_ASSERT(Radio, 0x10); @@ -17,15 +19,119 @@ Radio::Radio() CreateRadioState(); } -// STUB: LEGO1 0x1002c990 +// FUNCTION: LEGO1 0x1002c990 Radio::~Radio() { + if (m_state->IsActive()) { + BackgroundAudioManager()->Stop(); + m_state->SetActive(FALSE); + } + + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x1002ca30 +// FUNCTION: LEGO1 0x1002ca30 MxLong Radio::Notify(MxParam& p_param) { - // TODO + MxLong result = 0; + + if (m_unk0x0c) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationEndAction: + result = HandleEndAction((MxEndActionNotificationParam&) p_param); + break; + case c_notificationType17: + result = HandleNotification17((LegoControlManagerEvent&) p_param); + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x1002ca70 +void Radio::Play() +{ + if (!m_state->IsActive()) { + GetCurrentWorld(); + + MxDSAction action; + action.SetObjectId(m_state->FUN_1002d090()); + action.SetAtomId(*g_jukeboxScript); + action.SetLoopCount(1); + + m_bgAudioPreviouslyEnabled = BackgroundAudioManager()->GetMusicEnabled(); + if (!m_bgAudioPreviouslyEnabled) { + BackgroundAudioManager()->Enable(TRUE); + } + + BackgroundAudioManager()->PlayMusic(action, 3, 4); + m_state->SetActive(TRUE); + } +} + +// FUNCTION: LEGO1 0x1002cb70 +void Radio::Stop() +{ + if (m_state->IsActive()) { + LegoWorld* world = GetCurrentWorld(); + + MxControlPresenter* presenter = (MxControlPresenter*) world->Find(world->GetAtom(), 18); + + if (presenter) + presenter->VTable0x6c(0); + + BackgroundAudioManager()->Stop(); + BackgroundAudioManager()->Enable(m_bgAudioPreviouslyEnabled); + m_state->SetActive(FALSE); + } +} + +// FUNCTION: LEGO1 0x1002cbc0 +MxLong Radio::HandleNotification17(LegoControlManagerEvent& p_param) +{ + MxDSAction action; // Unused + MxS32 objectId = p_param.GetClickedObjectId(); + + if (objectId == 18) { + if (m_state->IsActive()) { + Stop(); + } + else { + Play(); + } + + if (GetCurrentWorld()) { +#ifdef COMPAT_MODE + MxNotificationParam param(c_notificationEndAction, this); + GetCurrentWorld()->Notify(param); +#else + GetCurrentWorld()->Notify(MxNotificationParam(c_notificationType0, this)); +#endif + } + + return 1; + } + + return 0; +} + +// FUNCTION: LEGO1 0x1002ccc0 +MxLong Radio::HandleEndAction(MxEndActionNotificationParam& p_param) +{ + if (m_state->IsActive() && + m_state->FUN_1002d0c0(p_param.GetAction()->GetAtomId(), p_param.GetAction()->GetObjectId())) { + + MxDSAction action; + action.SetAtomId(*g_jukeboxScript); + action.SetObjectId(m_state->FUN_1002d090()); + action.SetLoopCount(1); + + BackgroundAudioManager()->PlayMusic(action, 3, 4); + return 1; + } + return 0; } diff --git a/LEGO1/lego/legoomni/src/isle/radiostate.cpp b/LEGO1/lego/legoomni/src/isle/radiostate.cpp index ab9dc5d4..f83ba0bb 100644 --- a/LEGO1/lego/legoomni/src/isle/radiostate.cpp +++ b/LEGO1/lego/legoomni/src/isle/radiostate.cpp @@ -53,10 +53,12 @@ RadioState::RadioState() MxS32 random = rand(); m_unk0x2c = random % 3; - m_unk0x08[0].m_unk0x08 = 0; - m_unk0x08[0].m_unk0x06 = 0; + // TODO: Most likely inline function + m_unk0x08[0].m_unk0x04 = 6; m_unk0x08[0].m_unk0x00 = m_unk0x100f3218; + m_unk0x08[0].m_unk0x08 = 0; + m_unk0x08[0].m_unk0x06 = 0; random = rand(); @@ -78,12 +80,36 @@ RadioState::RadioState() m_unk0x08[2].m_unk0x08 = (MxU32) random % 9; - m_unk0x2e = 0; + m_active = FALSE; } -// STUB: LEGO1 0x1002cf50 +// FUNCTION: LEGO1 0x1002cf50 MxBool RadioState::VTable0x14() { - // TODO + return FALSE; +} + +// FUNCTION: LEGO1 0x1002d090 +MxU32 RadioState::FUN_1002d090() +{ + if (m_unk0x2c == 2) { + m_unk0x2c = 0; + } + else { + m_unk0x2c++; + } + + return m_unk0x08[m_unk0x2c].FUN_10014d00(); +} + +// FUNCTION: LEGO1 0x1002d0c0 +MxBool RadioState::FUN_1002d0c0(const MxAtomId& p_atom, MxU32 p_objectId) +{ + if (*g_jukeboxScript == p_atom) { + for (MxS16 i = 0; i < 3; i++) + if (m_unk0x08[i].FUN_10014de0(p_objectId)) + return TRUE; + } + return FALSE; }