diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h index d514d550..de62c91d 100644 --- a/LEGO1/lego/legoomni/include/infocenter.h +++ b/LEGO1/lego/legoomni/include/infocenter.h @@ -2,6 +2,17 @@ #define INFOCENTER_H #include "legoworld.h" +#include "radio.h" + +class InfocenterState; + +// SIZE 0x18 +struct InfocenterUnkDataEntry { + // FUNCTION: LEGO1 0x1006ec80 + InfocenterUnkDataEntry() {} + + undefined m_pad[0x18]; +}; // VTABLE: LEGO1 0x100d9338 // SIZE 0x1d8 @@ -31,6 +42,43 @@ class Infocenter : public LegoWorld { virtual MxBool VTable0x5c() override; // vtable+0x5c virtual MxBool VTable0x64() override; // vtable+0x64 virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + +private: + void PlayCutScene(MxU32 p_entityId, MxBool p_scale); + void InitializeBitmaps(); + + // notifications + MxLong HandleMouseMove(MxS32 p_x, MxS32 p_y); + MxU8 HandleKeyPress(char p_key); + MxU8 HandleButtonUp(MxS32 p_x, MxS32 p_y); + MxU8 HandleNotification17(MxParam&); + MxLong HandleEndAction(MxParam&); + MxLong HandleNotification0(MxParam&); + + void FUN_10070e90(); + + // utility functions + void StartCredits(); + static void DeleteCredits(); + void FUN_10071300(MxS32 p_objectId); + void FUN_100713d0(); + static void FUN_100714a0(); + static void FUN_10071550(); + + MxS32 m_unk0xf8; // 0xf8 + MxS16 m_unk0xfc; // 0xfc + InfocenterState* m_infocenterState; // 0x100 + undefined4 m_unk0x104; // 0x104 + MxS32 m_currentCutScene; // 0x108 + Radio m_radio; // 0x10c + undefined4 m_unk0x11c; // 0x11c + InfocenterUnkDataEntry m_entries[7]; // 0x120 + MxS16 m_unk0x1c8; // 0x1c8 + undefined4 m_unk0x1cc; // 0x1cc + MxU16 m_unk0x1d0; // 0x1d0 + MxU16 m_unk0x1d2; // 0x1d2 + MxU16 m_unk0x1d4; // 0x1d4 + MxU16 m_unk0x1d6; // 0x1d6 }; #endif // INFOCENTER_H diff --git a/LEGO1/lego/legoomni/include/infocenterstate.h b/LEGO1/lego/legoomni/include/infocenterstate.h index b1bce306..51dbac72 100644 --- a/LEGO1/lego/legoomni/include/infocenterstate.h +++ b/LEGO1/lego/legoomni/include/infocenterstate.h @@ -25,6 +25,9 @@ class InfocenterState : public LegoState { } inline MxU32 GetInfocenterBufferElement(MxS32 p_index) { return m_buffer[p_index]; } + inline MxU32 GetUnknown0x74() { return m_unk0x74; } + + inline void SetUnknown0x74(MxU32 p_unk0x74) { m_unk0x74 = p_unk0x74; } private: // Members should be renamed with their offsets before use @@ -55,7 +58,8 @@ class InfocenterState : public LegoState { undefined4 unk13; */ - undefined m_pad[0x70]; + undefined m_pad[0x6c]; + MxU32 m_unk0x74; // 0x74 MxU32 m_buffer[7]; // 0x78 }; diff --git a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h index 8f752cce..ce6cbc88 100644 --- a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h +++ b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h @@ -24,6 +24,8 @@ class LegoEventNotificationParam : public MxNotificationParam { } inline MxU8 GetKey() const { return m_key; } + inline MxS32 GetX() const { return m_x; } + inline MxS32 GetY() const { return m_y; } protected: MxU8 m_modifier; // 0x0c diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 455c2f1a..7a546702 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -52,6 +52,7 @@ class LegoInputManager : public MxPresenter { void ClearWorld(); inline void SetUnknown88(MxBool p_unk0x88) { m_unk0x88 = p_unk0x88; } + inline void SetUnknown335(MxBool p_unk0x335) { m_unk0x335 = p_unk0x335; } inline void SetUnknown336(MxBool p_unk0x336) { m_unk0x336 = p_unk0x336; } inline void SetUseJoystick(MxBool p_useJoystick) { m_useJoystick = p_useJoystick; } inline void SetJoystickIndex(MxS32 p_joystickIndex) { m_joystickIndex = p_joystickIndex; } diff --git a/LEGO1/lego/legoomni/include/legoomni.h b/LEGO1/lego/legoomni/include/legoomni.h index deab2d44..e3da6851 100644 --- a/LEGO1/lego/legoomni/include/legoomni.h +++ b/LEGO1/lego/legoomni/include/legoomni.h @@ -119,6 +119,8 @@ class LegoOmni : public MxOmni { inline void SetWorld(LegoWorld* p_currentWorld) { m_currentWorld = p_currentWorld; } inline void SetExit(MxBool p_exit) { m_exit = p_exit; }; + inline void CloseMainWindow() { PostMessageA(m_windowHandle, WM_CLOSE, 0, 0); } + private: undefined4* m_unk0x68; // 0x68 ViewLODListManager* m_viewLODListManager; // 0x6c diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index 4ac7ca37..a423ec09 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -58,6 +58,7 @@ class LegoWorld : public LegoEntity { void FUN_10073400(); void FUN_10073430(); MxS32 GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value); + MxPresenter* FindPresenter(const char* p_presenter, const char* p_name); protected: LegoPathControllerList m_list0x68; // 0x68 diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index dca2115f..34c6dee5 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -157,6 +157,12 @@ void LegoWorld::VTable0x68(MxBool p_add) // TODO } +// STUB: LEGO1 0x100213a0 +MxPresenter* LegoWorld::FindPresenter(const char* p_presenter, const char* p_name) +{ + return NULL; +} + // FUNCTION: LEGO1 0x10022080 MxResult LegoWorld::Tickle() { diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp index 9201adf9..1629eb49 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -1,9 +1,37 @@ #include "infocenter.h" -// STUB: LEGO1 0x1006ea20 +#include "infocenterstate.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoomni.h" +#include "legoutil.h" +#include "legovideomanager.h" +#include "mxactionnotificationparam.h" +#include "mxbackgroundaudiomanager.h" +#include "mxnotificationmanager.h" +#include "mxstillpresenter.h" + +DECOMP_SIZE_ASSERT(Infocenter, 0x1d8) + +// FUNCTION: LEGO1 0x1006ea20 Infocenter::Infocenter() { - // TODO + m_unk0xfc = 0; + m_unk0x11c = 0; + m_infocenterState = NULL; + m_unk0x11c = 0; + m_unk0x104 = 0; + m_unk0xf8 = -1; + m_currentCutScene = -1; + memset(&m_entries, 0, sizeof(InfocenterUnkDataEntry) * 7); + m_unk0x1c8 = -1; + SetAppCursor(1); + NotificationManager()->Register(this); + m_unk0x1d0 = 0; + m_unk0x1d2 = 0; + m_unk0x1d4 = 0; + m_unk0x1d6 = 0; } // STUB: LEGO1 0x1006ec90 @@ -15,20 +43,135 @@ Infocenter::~Infocenter() // STUB: LEGO1 0x1006ed90 MxResult Infocenter::Create(MxDSAction& p_dsAction) { - return FAILURE; + OutputDebugString("create called\n"); + if (LegoWorld::Create(p_dsAction) == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + LegoGameState* gs = GameState(); + m_infocenterState = (InfocenterState*) gs->GetState("InfocenterState"); + if (!m_infocenterState) { + m_infocenterState = (InfocenterState*) gs->CreateState("InfocenterState"); + m_infocenterState->SetUnknown0x74(3); + } + else { + // TODO + } + + // TODO + InputManager()->Register(this); + SetIsWorldActive(FALSE); + return SUCCESS; } -// STUB: LEGO1 0x1006ef10 +// FUNCTION: LEGO1 0x1006ef10 MxLong Infocenter::Notify(MxParam& p_param) { - // TODO + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + + switch (((MxNotificationParam&) p_param).GetNotification()) { + case 0: + return HandleNotification0(p_param); + case c_notificationEndAction: + return HandleEndAction(p_param); + case c_notificationKeyPress: + return HandleKeyPress(((LegoEventNotificationParam&) p_param).GetKey()) & 0xff; + case c_notificationButtonUp: + return HandleButtonUp( + ((LegoEventNotificationParam&) p_param).GetX(), + ((LegoEventNotificationParam&) p_param).GetY() + ) & + 0xff; + case c_notificationMouseMove: + return HandleMouseMove( + ((LegoEventNotificationParam&) p_param).GetX(), + ((LegoEventNotificationParam&) p_param).GetY() + ) & + 0xff; + case TYPE17: + return HandleNotification17(p_param); + case MXTRANSITIONMANAGER_TRANSITIONENDED: + FUN_10071550(); + m_unk0x1d2 = 0; + if (m_infocenterState->GetUnknown0x74() == 0xc) { + StartCredits(); + m_infocenterState->SetUnknown0x74(0xd); + return 0; + } + if (m_unk0x104 != 0) { + BackgroundAudioManager()->RaiseVolume(); + GameState()->HandleAction(m_unk0x104); + m_unk0x104 = 0; + } + break; + } + } return 0; } -// STUB: LEGO1 0x1006f4e0 +// FUNCTION: LEGO1 0x1006f4e0 void Infocenter::VTable0x50() { - // TODO + m_unk0x1d0 = 0; + m_unk0x1d2 = 0; + m_unk0x1d4 = 0; + m_unk0x1d6 = 0; + + MxStillPresenter* bg = (MxStillPresenter*) FindPresenter("MxStillPresenter", "Background_Bitmap"); + MxStillPresenter* bgRed = (MxStillPresenter*) FindPresenter("MxStillPresenter", "BackgroundRed_Bitmap"); + + switch (GameState()->GetUnknown10()) { + case 0: + // bg->Enable(1); + InitializeBitmaps(); + switch (m_infocenterState->GetUnknown0x74()) { + case 3: + PlayCutScene(0, TRUE); + m_infocenterState->SetUnknown0x74(0); + return; + case 4: + m_infocenterState->SetUnknown0x74(2); + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_unk0x1d2 = 1; + } + + FUN_10071300(504); // Play "Ok, lets get started" dialogue + PlayMusic(11); + FUN_10015820(0, 7); + return; + default: + PlayMusic(11); + // TODO + break; + case 8: + PlayMusic(11); + FUN_10071300(522); // Are you sure you want to exit lego island? + FUN_10015820(0, 7); + return; + case 0xf: + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_unk0x1d2 = 1; + } + FUN_10071300(502); + PlayMusic(11); + FUN_10015820(0, 7); + return; + } + break; + case 1: + // TODO + break; + case 2: + // TODO + break; + default: + m_infocenterState->SetUnknown0x74(11); + FUN_10015820(0, 7); + return; + } } // STUB: LEGO1 0x10070aa0 @@ -37,11 +180,78 @@ void Infocenter::VTable0x68(MxBool p_add) // TODO } +// STUB: LEGO1 0x1006f9a0 +void Infocenter::InitializeBitmaps() +{ + // TODO: Infocenter class size is wrong +} + +// STUB: LEGO1 0x1006fd00 +MxLong Infocenter::HandleMouseMove(MxS32 p_x, MxS32 p_y) +{ + return 1; +} + +// STUB: LEGO1 0x1006fda0 +MxU8 Infocenter::HandleKeyPress(char p_key) +{ + return 1; +} + +// STUB: LEGO1 0x1006feb0 +MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) +{ + return 1; +} + +// STUB: LEGO1 0x10070370 +MxU8 Infocenter::HandleNotification17(MxParam&) +{ + return 1; +} + +// STUB: LEGO1 0x1006f080 +MxLong Infocenter::HandleEndAction(MxParam& p_param) +{ + MxDSAction* endedAction = ((MxEndActionNotificationParam&) p_param).GetAction(); + if (endedAction->GetAtomId() == *g_creditsScript && endedAction->GetObjectId() == 499) { + Lego()->CloseMainWindow(); + } + + // TODO + return 1; +} + +// STUB: LEGO1 0x10070870 +MxLong Infocenter::HandleNotification0(MxParam&) +{ + return 1; +} + // STUB: LEGO1 0x10070af0 MxResult Infocenter::Tickle() { // TODO - return 0; + return LegoWorld::Tickle(); +} + +// FUNCTION: LEGO1 0x10070c20 +void Infocenter::PlayCutScene(MxU32 p_entityId, MxBool p_scale) +{ + m_currentCutScene = p_entityId; + VideoManager()->EnableFullScreenMovie(TRUE, p_scale); + InputManager()->SetUnknown336(TRUE); + InputManager()->SetUnknown335(TRUE); + SetAppCursor(0xb); // Hide cursor + VideoManager()->GetDisplaySurface()->FUN_100ba640(); // Clear screen + + if (m_currentCutScene != -1) { + // check if the cutscene is not an ending + if (m_currentCutScene >= 4 && m_currentCutScene <= 5) { + FUN_10070e90(); + } + InvokeAction(ExtraActionType_opendisk, *g_introScript, m_currentCutScene, NULL); + } } // FUNCTION: LEGO1 0x10070d00 @@ -50,8 +260,73 @@ MxBool Infocenter::VTable0x5c() return TRUE; } +// STUB: LEGO1 0x10070e90 +void Infocenter::FUN_10070e90() +{ +} + // STUB: LEGO1 0x10070f60 MxBool Infocenter::VTable0x64() { return FALSE; } + +// STUB: LEGO1 0x10071030 +void Infocenter::StartCredits() +{ +} + +// FUNCTION: LEGO1 0x10071250 +void DeleteCredits() +{ + MxDSAction action; + action.SetObjectId(499); + action.SetAtomId(*g_creditsScript); + action.SetUnknown24(-2); + DeleteObject(action); +} + +// FUNCTION: LEGO1 0x10071300 +void Infocenter::FUN_10071300(MxS32 p_objectId) +{ + MxDSAction action; + action.SetObjectId(p_objectId); + action.SetAtomId(*g_infomainScript); + FUN_100713d0(); + + m_unk0xf8 = p_objectId; + BackgroundAudioManager()->LowerVolume(); + Start(&action); +} + +// FUNCTION: LEGO1 0x100713d0 +void Infocenter::FUN_100713d0() +{ + if (m_unk0xf8 != -1) { + MxDSAction action; + action.SetObjectId(m_unk0xf8); + action.SetAtomId(*g_infomainScript); + action.SetUnknown24(-2); + DeleteObject(action); + m_unk0xf8 = -1; + } +} + +// FUNCTION: LEGO1 0x100714a0 +void Infocenter::FUN_100714a0() +{ + MxDSAction action; + action.SetObjectId(400); + action.SetAtomId(*g_sndAnimScript); + Start(&action); +} + +// FUNCTION: LEGO1 0x10071550 +void Infocenter::FUN_10071550() +{ + MxDSAction action; + action.SetObjectId(400); + action.SetAtomId(*g_sndAnimScript); + action.SetUnknown24(-2); + DeleteObject(action); +} diff --git a/LEGO1/lego/legoomni/src/main/legoomni.cpp b/LEGO1/lego/legoomni/src/main/legoomni.cpp index 9cb67852..d3f0ce10 100644 --- a/LEGO1/lego/legoomni/src/main/legoomni.cpp +++ b/LEGO1/lego/legoomni/src/main/legoomni.cpp @@ -697,7 +697,7 @@ MxLong LegoOmni::Notify(MxParam& p_param) MxLong result = MxOmni::Notify(p_param); if (isCD) { // Exit the game if nocd.si ended - PostMessageA(m_windowHandle, WM_CLOSE, 0, 0); + CloseMainWindow(); } return result;