From b524b47723ec0277f71fdbeb9e22f67874b41572 Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Mon, 26 Feb 2024 10:12:14 -0500 Subject: [PATCH] jukebox functions (#592) * start jukebox functions * JukeBox::notify * implement remaining functions/fixes * Fixes/matches --------- Co-authored-by: Christian Semmler --- LEGO1/lego/legoomni/include/jukebox.h | 74 ++++--- LEGO1/lego/legoomni/include/jukeboxstate.h | 1 + LEGO1/lego/legoomni/src/isle/jukebox.cpp | 231 +++++++++++++++++++-- 3 files changed, 261 insertions(+), 45 deletions(-) diff --git a/LEGO1/lego/legoomni/include/jukebox.h b/LEGO1/lego/legoomni/include/jukebox.h index 94728ee2..c9424051 100644 --- a/LEGO1/lego/legoomni/include/jukebox.h +++ b/LEGO1/lego/legoomni/include/jukebox.h @@ -2,39 +2,25 @@ #define JUKEBOX_H #include "decomp.h" +#include "jukeboxstate.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" #include "legoworld.h" // VTABLE: LEGO1 0x100d8958 // SIZE 0x104 class JukeBox : public LegoWorld { public: - JukeBox(); - - MxLong Notify(MxParam& p_param) override; // vtable+0x04 - MxResult Tickle() override; // vtable+0x08 - - // FUNCTION: LEGO1 0x1005d6f0 - inline const char* ClassName() const override // vtable+0x0c - { - // STRING: LEGO1 0x100f02cc - return "JukeBox"; - } - - // FUNCTION: LEGO1 0x1005d700 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, JukeBox::ClassName()) || LegoWorld::IsA(p_name); - } - - MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void ReadyWorld() override; // vtable+0x50 - MxBool VTable0x5c() override; // vtable+0x5c - MxBool VTable0x64() override; // vtable+0x64 - void Enable(MxBool p_enable) override; // vtable+0x68 - - // SYNTHETIC: LEGO1 0x1005d810 - // JukeBox::`scalar deleting destructor' + // JUKEBOXW.SI + enum JukeBoxWorldScript { + c_volDownCtl = 1, + c_volUpCtl = 2, + c_dBackCtl = 3, + c_dFwdCtl = 4, + c_noteCtl = 5 + }; + // JUKEBOX.SI (the actual audio) enum JukeBoxScript { e_mamaPapaBrickolini, e_jailUnused, @@ -108,10 +94,40 @@ class JukeBox : public LegoWorld { e_pizzaMission, }; + JukeBox(); + ~JukeBox() override; + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1005d6f0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f02cc + return "JukeBox"; + } + + // FUNCTION: LEGO1 0x1005d700 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, JukeBox::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x1005d810 + // JukeBox::`scalar deleting destructor' + private: - undefined m_unk0xf8[4]; // 0xf8 - undefined4 m_unk0xfc; // 0xfc - undefined2 m_unk0x100; // 0x100 + MxBool HandleClick(LegoControlManagerEvent& p_param); + + LegoGameState::Area m_transitionDestination; // 0xf8 + JukeBoxState* m_state; // 0xfc + undefined2 m_unk0x100; // 0x100 }; #endif // JUKEBOX_H diff --git a/LEGO1/lego/legoomni/include/jukeboxstate.h b/LEGO1/lego/legoomni/include/jukeboxstate.h index a12c97e5..18a4aa62 100644 --- a/LEGO1/lego/legoomni/include/jukeboxstate.h +++ b/LEGO1/lego/legoomni/include/jukeboxstate.h @@ -25,6 +25,7 @@ class JukeBoxState : public LegoState { inline MxU32 IsActive() { return m_active; } inline void SetActive(MxU32 p_active) { m_active = p_active; } inline MxU32 GetState() { return m_state; } + inline void SetState(MxU32 p_state) { m_state = p_state; } // SYNTHETIC: LEGO1 0x1000f3d0 // JukeBoxState::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/src/isle/jukebox.cpp b/LEGO1/lego/legoomni/src/isle/jukebox.cpp index 73b03ab0..70c1bb0a 100644 --- a/LEGO1/lego/legoomni/src/isle/jukebox.cpp +++ b/LEGO1/lego/legoomni/src/isle/jukebox.cpp @@ -1,7 +1,17 @@ #include "jukebox.h" +#include "act1state.h" +#include "jukeboxstate.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoomni.h" #include "mxnotificationmanager.h" #include "mxomni.h" +#include "mxstillpresenter.h" +#include "mxticklemanager.h" +#include "mxtransitionmanager.h" +#include "mxvideopresenter.h" DECOMP_SIZE_ASSERT(JukeBox, 0x104) @@ -9,7 +19,7 @@ DECOMP_SIZE_ASSERT(JukeBox, 0x104) JukeBox::JukeBox() { m_unk0x100 = 0; - m_unk0xfc = 0; + m_state = NULL; NotificationManager()->Register(this); } @@ -19,42 +29,231 @@ MxBool JukeBox::VTable0x5c() return TRUE; } -// STUB: LEGO1 0x1005d8d0 +// FUNCTION: LEGO1 0x1005d830 +JukeBox::~JukeBox() +{ + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + + ControlManager()->Unregister(this); + TickleManager()->UnregisterClient(this); + NotificationManager()->Unregister(this); +} + +// FUNCTION: LEGO1 0x1005d8d0 MxResult JukeBox::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult ret = LegoWorld::Create(p_dsAction); + if (ret == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + InputManager()->SetCamera(NULL); + + m_state = (JukeBoxState*) GameState()->GetState("JukeBoxState"); + if (!m_state) { + m_state = (JukeBoxState*) GameState()->CreateState("JukeBoxState"); + m_state->SetState(0); + } + + GameState()->SetCurrentArea(LegoGameState::e_jukeboxw); + GameState()->StopArea(LegoGameState::e_previousArea); + TickleManager()->RegisterClient(this, 2000); + return ret; } -// STUB: LEGO1 0x1005d980 +// FUNCTION: LEGO1 0x1005d980 MxLong JukeBox::Notify(MxParam& p_param) { - // TODO - return 0; + MxLong result = 0; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetNotification()) { + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(m_transitionDestination); + result = 1; + break; + } + } + + return result; } -// STUB: LEGO1 0x1005d9f0 +// FUNCTION: LEGO1 0x1005d9f0 void JukeBox::ReadyWorld() { - // TODO + MxStillPresenter* presenter = NULL; + + switch (m_state->GetState()) { + case 1: + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Right_Bitmap"); + break; + case 2: + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Decal_Bitmap"); + break; + case 3: + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Wallis_Bitmap"); + break; + case 4: + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Nelson_Bitmap"); + break; + case 5: + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Torpedos_Bitmap"); + break; + } + + if (presenter) { + presenter->Enable(TRUE); + } + + m_unk0x100 = 1; } -// STUB: LEGO1 0x1005dde0 +// FUNCTION: LEGO1 0x1005da70 +MxBool JukeBox::HandleClick(LegoControlManagerEvent& p_param) +{ + MxStillPresenter* presenter; + + if (p_param.GetUnknown0x28() == 1) { + switch (p_param.GetClickedObjectId()) { + case c_dBackCtl: + switch (m_state->GetState()) { + case JukeBoxScript::e_mamaPapaBrickolini: + m_state->SetState(JukeBoxScript::e_residentialArea); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Torpedos_Bitmap"); + presenter->Enable(TRUE); + break; + case JukeBoxScript::e_jailUnused: + m_state->SetState(JukeBoxScript::e_mamaPapaBrickolini); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Right_Bitmap"); + presenter->Enable(FALSE); + break; + case JukeBoxScript::e_act2Cave: + m_state->SetState(JukeBoxScript::e_jailUnused); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Decal_Bitmap"); + presenter->Enable(FALSE); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Right_Bitmap"); + presenter->Enable(TRUE); + break; + case JukeBoxScript::e_bricksterChase: + m_state->SetState(JukeBoxScript::e_act2Cave); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Wallis_Bitmap"); + presenter->Enable(FALSE); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Decal_Bitmap"); + presenter->Enable(TRUE); + break; + case JukeBoxScript::e_brickHunt: + m_state->SetState(JukeBoxScript::e_bricksterChase); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Nelson_Bitmap"); + presenter->Enable(FALSE); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Wallis_Bitmap"); + presenter->Enable(TRUE); + break; + case JukeBoxScript::e_residentialArea: + m_state->SetState(JukeBoxScript::e_brickHunt); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Torpedos_Bitmap"); + presenter->Enable(FALSE); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Nelson_Bitmap"); + presenter->Enable(TRUE); + break; + } + break; + case JukeBoxWorldScript::c_dFwdCtl: + switch (m_state->GetState()) { + case JukeBoxScript::e_mamaPapaBrickolini: + m_state->SetState(JukeBoxScript::e_jailUnused); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Right_Bitmap"); + presenter->Enable(TRUE); + break; + case JukeBoxScript::e_jailUnused: + m_state->SetState(JukeBoxScript::e_act2Cave); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Right_Bitmap"); + presenter->Enable(FALSE); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Decal_Bitmap"); + presenter->Enable(TRUE); + break; + case JukeBoxScript::e_act2Cave: + m_state->SetState(JukeBoxScript::e_bricksterChase); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Decal_Bitmap"); + presenter->Enable(FALSE); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Wallis_Bitmap"); + presenter->Enable(TRUE); + break; + case JukeBoxScript::e_bricksterChase: + m_state->SetState(JukeBoxScript::e_brickHunt); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Wallis_Bitmap"); + presenter->Enable(FALSE); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Nelson_Bitmap"); + presenter->Enable(TRUE); + break; + case JukeBoxScript::e_brickHunt: + m_state->SetState(JukeBoxScript::e_residentialArea); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Nelson_Bitmap"); + presenter->Enable(FALSE); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Torpedos_Bitmap"); + presenter->Enable(TRUE); + break; + case JukeBoxScript::e_residentialArea: + m_state->SetState(JukeBoxScript::e_mamaPapaBrickolini); + presenter = (MxStillPresenter*) Find("MxStillPresenter", "Torpedos_Bitmap"); + presenter->Enable(FALSE); + break; + } + break; + case JukeBoxWorldScript::c_noteCtl: + LegoGameState* gameState = GameState(); + Act1State* act1State = (Act1State*) gameState->GetState("Act1State"); + act1State->SetUnknown18(11); + m_transitionDestination = LegoGameState::Area::e_unk54; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, 0, FALSE); + break; + } + } + + return TRUE; +} + +// FUNCTION: LEGO1 0x1005dde0 void JukeBox::Enable(MxBool p_enable) { - // TODO + LegoWorld::Enable(p_enable); + + if (p_enable) { + InputManager()->SetWorld(this); + InputManager()->SetCamera(NULL); + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } } -// STUB: LEGO1 0x1005de30 +// FUNCTION: LEGO1 0x1005de30 MxResult JukeBox::Tickle() { - // TODO + if (m_worldStarted == FALSE) { + LegoWorld::Tickle(); + return SUCCESS; + } + + if (m_unk0x100 == 1) { + m_unk0x100 = 0; + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + } + return SUCCESS; } -// STUB: LEGO1 0x1005de70 +// FUNCTION: LEGO1 0x1005de70 MxBool JukeBox::VTable0x64() { - // TODO - return FALSE; + m_transitionDestination = LegoGameState::e_infomain; + return TRUE; }