From 13fc4e328534238f0ffe1bcfcaf37c820c64f2ec Mon Sep 17 00:00:00 2001 From: Nathan M Gilbert Date: Sat, 24 Feb 2024 08:55:00 -0500 Subject: [PATCH 01/14] LegoGameState::SwitchArea (#590) --- LEGO1/lego/legoomni/include/legogamestate.h | 37 +-- .../lego/legoomni/include/legonavcontroller.h | 1 + LEGO1/lego/legoomni/include/legoutil.h | 1 + .../legoomni/src/common/legogamestate.cpp | 245 ++++++++++-------- LEGO1/lego/legoomni/src/common/legoutil.cpp | 7 + .../legoomni/src/entity/legonavcontroller.cpp | 5 + .../src/infocenter/elevatorbottom.cpp | 2 +- .../legoomni/src/infocenter/infocenter.cpp | 12 +- LEGO1/lego/legoomni/src/police/police.cpp | 2 +- .../lego/sources/3dmanager/lego3dmanager.cpp | 8 + LEGO1/lego/sources/3dmanager/lego3dmanager.h | 2 + 11 files changed, 192 insertions(+), 130 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 011fbf8a..e4458213 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -35,35 +35,35 @@ class LegoGameState { e_infodoor, e_unk4, e_elevbott, - e_unk6, - e_unk7, - e_unk8, - e_unk9, - e_unk10, - e_unk11, + e_elevride, + e_elevride2, + e_elevopen, + e_seaview, + e_observe, + e_elevdown, e_regbook, e_infoscor, e_jetrace, - e_unk15, - e_unk16, + e_jetrace2, + e_jetraceExterior, e_unk17, e_carrace, - e_unk19, + e_carraceExterior, e_unk20, e_unk21, - e_unk22, + e_pizzeriaExterior, - e_unk25 = 25, + e_garageExterior = 25, e_garage, - e_unk27, - - e_unk29 = 29, + e_garadoor, + e_unk28, + e_hospitalExterior, e_hospital, e_unk31, - e_unk32, - - e_police = 34, - e_unk35, + e_policeExterior, + e_unk33, + e_police, + e_polidoor, e_copter, e_dunecar, e_jetski, @@ -73,6 +73,7 @@ class LegoGameState { e_act3script, e_jukeboxw = 53, + e_unk54, e_histbook = 56, e_unk57, diff --git a/LEGO1/lego/legoomni/include/legonavcontroller.h b/LEGO1/lego/legoomni/include/legonavcontroller.h index 58ace217..e5c74f35 100644 --- a/LEGO1/lego/legoomni/include/legonavcontroller.h +++ b/LEGO1/lego/legoomni/include/legonavcontroller.h @@ -56,6 +56,7 @@ class LegoNavController : public MxCore { void SetControlMax(int p_hMax, int p_vMax); void ResetToDefault(); void SetTargets(int p_hPos, int p_vPos, MxBool p_accel); + static void SetLocation(MxU32 p_location); float CalculateNewTargetSpeed(int p_pos, int p_center, float p_maxSpeed); float CalculateNewAccel(int p_pos, int p_center, float p_maxAccel, int p_minAccel); float CalculateNewVel(float p_targetVel, float p_currentVel, float p_accel, float p_time); diff --git a/LEGO1/lego/legoomni/include/legoutil.h b/LEGO1/lego/legoomni/include/legoutil.h index 696a1cc4..0b35fc61 100644 --- a/LEGO1/lego/legoomni/include/legoutil.h +++ b/LEGO1/lego/legoomni/include/legoutil.h @@ -34,6 +34,7 @@ class NamedTexture { void FUN_1003e050(LegoAnimPresenter* p_presenter); Extra::ActionType MatchActionString(const char*); void InvokeAction(Extra::ActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender); +void SetCameraControllerFromIsle(); void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bOut, float* p_gOut); MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id); void FUN_1003ef00(MxBool); diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 9d81f699..0c43d19e 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -1,7 +1,11 @@ #include "legogamestate.h" +#include "act1state.h" +#include "define.h" #include "infocenterstate.h" +#include "islepathactor.h" #include "legoanimationmanager.h" +#include "legonavcontroller.h" #include "legoomni.h" #include "legostate.h" #include "legoutil.h" @@ -298,8 +302,8 @@ void LegoGameState::StopArea(Area p_area) InvokeAction(Extra::e_stop, *g_elevbottScript, 0, NULL); InvokeAction(Extra::e_close, *g_elevbottScript, 0, NULL); break; - case e_unk6: - case e_unk7: + case e_elevride: + case e_elevride2: RemoveFromWorld(*g_isleScript, 0x41b, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 1052, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x41d, *g_isleScript, 0); @@ -312,17 +316,17 @@ void LegoGameState::StopArea(Area p_area) RemoveFromWorld(*g_isleScript, 0x42a, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x42b, *g_isleScript, 0); break; - case e_unk8: + case e_elevopen: RemoveFromWorld(*g_isleScript, 0x45b, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x45c, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x45d, *g_isleScript, 0); break; - case e_unk9: + case e_seaview: RemoveFromWorld(*g_isleScript, 0x475, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x476, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x477, *g_isleScript, 0); break; - case e_unk10: + case e_observe: RemoveFromWorld(*g_isleScript, 0x45f, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x460, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x461, *g_isleScript, 0); @@ -344,7 +348,7 @@ void LegoGameState::StopArea(Area p_area) RemoveFromWorld(*g_isleScript, 0x472, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x12, *g_isleScript, 0); break; - case e_unk11: + case e_elevdown: RemoveFromWorld(*g_isleScript, 0x47a, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x47b, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x47c, *g_isleScript, 0); @@ -373,7 +377,7 @@ void LegoGameState::StopArea(Area p_area) InvokeAction(Extra::e_stop, *g_garageScript, 0, NULL); InvokeAction(Extra::e_close, *g_garageScript, 0, NULL); break; - case e_unk27: + case e_garadoor: RemoveFromWorld(*g_isleScript, 0x489, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x48a, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x48b, *g_isleScript, 0); @@ -387,7 +391,7 @@ void LegoGameState::StopArea(Area p_area) InvokeAction(Extra::e_stop, *g_policeScript, 0, NULL); InvokeAction(Extra::e_close, *g_policeScript, 0, NULL); break; - case e_unk35: + case e_polidoor: RemoveFromWorld(*g_isleScript, 0x47f, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x480, *g_isleScript, 0); RemoveFromWorld(*g_isleScript, 0x481, *g_isleScript, 0); @@ -437,6 +441,26 @@ void LegoGameState::StopArea(Area p_area) } } +inline void LoadIsle() +{ + LegoWorld* world = FindWorld(*g_isleScript, 0); + if (world != NULL) { + if (!world->GetUnknown0xd0().empty()) { +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType20, NULL); + NotificationManager()->Send(world, ¶m); + } +#else + NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); +#endif + } + } + else { + InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); + } +} + // FUNCTION: LEGO1 0x1003b060 void LegoGameState::SwitchArea(Area p_area) { @@ -448,8 +472,6 @@ void LegoGameState::SwitchArea(Area p_area) AnimationManager()->FUN_1005ef10(); VideoManager()->SetUnk0x554(FALSE); - LegoWorld* world; - switch (p_area) { case e_isle: InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); @@ -463,17 +485,17 @@ void LegoGameState::SwitchArea(Area p_area) InvokeAction(Extra::ActionType::e_opendisk, *g_infodoorScript, 0, NULL); break; case e_unk4: - case e_unk15: - case e_unk16: + case e_jetrace2: + case e_jetraceExterior: case e_unk17: - case e_unk19: + case e_carraceExterior: case e_unk20: case e_unk21: - case e_unk22: - case e_unk25: - case e_unk29: + case e_pizzeriaExterior: + case e_garageExterior: + case e_hospitalExterior: case e_unk31: - case e_unk32: + case e_policeExterior: case e_unk57: case e_unk58: case e_unk59: @@ -481,58 +503,27 @@ void LegoGameState::SwitchArea(Area p_area) case e_unk61: case e_unk64: case e_unk66: - world = FindWorld(*g_isleScript, 0); - if (world != NULL) { - if (world->GetUnknown0xd0().empty()) { - break; - } - else { -#ifdef COMPAT_MODE - { - MxNotificationParam param(c_notificationType20, NULL); - NotificationManager()->Send(world, ¶m); - } -#else - NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); -#endif - break; - } - } - InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); + LoadIsle(); break; case e_elevbott: InvokeAction(Extra::ActionType::e_opendisk, *g_elevbottScript, 0, NULL); break; - case e_unk6: - case e_unk7: - world = FindWorld(*g_isleScript, 0); - - if (world == NULL) { - InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); - } - else if (!world->GetUnknown0xd0().empty()) { -#ifdef COMPAT_MODE - { - MxNotificationParam param(c_notificationType20, NULL); - NotificationManager()->Send(world, ¶m); - } -#else - NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); -#endif - } + case e_elevride: + case e_elevride2: + LoadIsle(); InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1050, NULL); break; - case e_unk8: + case e_elevopen: VideoManager()->SetUnk0x554(TRUE); InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1114, NULL); break; - case e_unk9: + case e_seaview: InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1140, NULL); break; - case e_unk10: + case e_observe: InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1118, NULL); break; - case e_unk11: + case e_elevdown: InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1145, NULL); break; case e_regbook: @@ -545,64 +536,110 @@ void LegoGameState::SwitchArea(Area p_area) break; case e_jetrace: if (m_previousArea == e_infomain) { - m_currentArea = e_unk15; - - world = FindWorld(*g_isleScript, 0); - if (world != NULL) { - if (world->GetUnknown0xd0().empty()) { - return; - } - else { -#ifdef COMPAT_MODE - { - MxNotificationParam param(c_notificationType20, NULL); - NotificationManager()->Send(world, ¶m); - } -#else - NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); -#endif - } - return; - } - else { - InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); - break; - } + m_currentArea = e_jetrace2; + LoadIsle(); + } + else { + InvokeAction(Extra::ActionType::e_opendisk, *g_jetraceScript, 0, NULL); } - - InvokeAction(Extra::ActionType::e_opendisk, *g_jetraceScript, 0, NULL); break; case e_carrace: if (m_previousArea == e_infomain) { - m_currentArea = e_unk19; - - world = FindWorld(*g_isleScript, 0); - if (world != NULL) { - if (world->GetUnknown0xd0().empty()) { - return; - } - else { -#ifdef COMPAT_MODE - { - MxNotificationParam param(c_notificationType20, NULL); - NotificationManager()->Send(world, ¶m); - } -#else - NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); -#endif - } - return; - } + m_currentArea = e_carraceExterior; + LoadIsle(); + } + else { + InvokeAction(Extra::ActionType::e_opendisk, *g_carraceScript, 0, NULL); } - - InvokeAction(Extra::ActionType::e_opendisk, *g_carraceScript, 0, NULL); break; case e_garage: VideoManager()->SetUnk0x554(TRUE); InvokeAction(Extra::ActionType::e_opendisk, *g_garageScript, 0, NULL); break; - - // TODO: implement other cases + case e_garadoor: + LoadIsle(); + VariableTable()->SetVariable("VISIBILITY", "Hide Gas"); + CurrentVehicle()->ResetWorldTransform(FALSE); + NavController()->SetLocation(0x3b); + VideoManager()->Get3DManager()->SetFrustrum(90, 0.1f, 250.0f); + InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1160, NULL); + break; + case e_unk28: { + Act1State* state = (Act1State*) GameState()->GetState("Act1State"); + LoadIsle(); + if (state->GetUnknown18() == 7) { + VideoManager()->Get3DManager()->SetFrustrum(90, 0.1f, 250.0f); + } + else { + SetCameraControllerFromIsle(); + CurrentVehicle()->ResetWorldTransform(TRUE); + AnimationManager()->FUN_1005f0b0(); + } + CurrentVehicle()->VTable0xe8(p_area, TRUE, 7); + break; + } + case e_hospital: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_hospitalScript, 0, NULL); + break; + case e_unk33: + LoadIsle(); + SetCameraControllerFromIsle(); + CurrentVehicle()->ResetWorldTransform(TRUE); + AnimationManager()->FUN_1005f0b0(); + CurrentVehicle()->VTable0xe8(p_area, TRUE, 7); + break; + case e_police: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_policeScript, 0, NULL); + break; + case e_polidoor: + LoadIsle(); + InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1150, NULL); + break; + case e_copter: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_copterScript, 0, NULL); + break; + case e_dunecar: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_dunecarScript, 0, NULL); + break; + case e_jetski: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_jetskiScript, 0, NULL); + break; + case e_racecar: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_racecarScript, 0, NULL); + break; + case e_act2main: { + LegoWorld* act2main = FindWorld(*g_act2mainScript, 0); + if (act2main == NULL) { + InvokeAction(Extra::ActionType::e_opendisk, *g_act2mainScript, 0, NULL); + } + else { + act2main->Enable(TRUE); + } + break; + } + case e_act3script: { + LegoWorld* act3 = FindWorld(*g_act3Script, 0); + if (act3 == NULL) { + InvokeAction(Extra::ActionType::e_opendisk, *g_act3Script, 0, NULL); + } + else { + act3->Enable(TRUE); + } + break; + } + case e_jukeboxw: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_jukeboxwScript, 0, NULL); + break; + case e_unk54: + LoadIsle(); + break; case e_histbook: VideoManager()->SetUnk0x554(TRUE); InvokeAction(Extra::ActionType::e_opendisk, *g_histbookScript, 0, NULL); diff --git a/LEGO1/lego/legoomni/src/common/legoutil.cpp b/LEGO1/lego/legoomni/src/common/legoutil.cpp index 3951f94f..fabe18d6 100644 --- a/LEGO1/lego/legoomni/src/common/legoutil.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutil.cpp @@ -1,5 +1,6 @@ #include "legoutil.h" +#include "legoinputmanager.h" #include "legoomni.h" #include "legoworld.h" #include "legoworldlist.h" @@ -161,6 +162,12 @@ void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender } } +// FUNCTION: LEGO1 0x1003eab0 +void SetCameraControllerFromIsle() +{ + InputManager()->SetCamera(FindWorld(*g_isleScript, 0)->GetCamera()); +} + // FUNCTION: LEGO1 0x1003eae0 void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bOut, float* p_gOut) { diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index 8a9ec812..e6dc33a2 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -230,6 +230,11 @@ float LegoNavController::CalculateNewVel(float p_targetVel, float p_currentVel, return newVel; } +// STUB: LEGO1 0x10055620 +void LegoNavController::SetLocation(MxU32 p_location) +{ +} + // STUB: LEGO1 0x10055a60 MxLong LegoNavController::Notify(MxParam& p_param) { diff --git a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp index 5ef0d580..960cf40e 100644 --- a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp @@ -101,7 +101,7 @@ MxLong ElevatorBottom::HandleClick(LegoControlManagerEvent& p_param) } state->SetUnknown1c(1); - m_unk0xf8 = LegoGameState::e_unk6; + m_unk0xf8 = LegoGameState::e_elevride; TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); VariableTable()->SetVariable(g_varCAMERALOCATION, "LCAMZI1,90"); result = 1; diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp index 64bd9e58..cef49c68 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -756,37 +756,37 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) break; case 10: if (m_selectedCharacter) { - m_transitionDestination = LegoGameState::e_unk16; + m_transitionDestination = LegoGameState::e_jetraceExterior; m_infocenterState->SetUnknown0x74(5); } break; case 11: if (m_selectedCharacter) { - m_transitionDestination = LegoGameState::e_unk19; + m_transitionDestination = LegoGameState::e_carraceExterior; m_infocenterState->SetUnknown0x74(5); } break; case 12: if (m_selectedCharacter) { - m_transitionDestination = LegoGameState::e_unk22; + m_transitionDestination = LegoGameState::e_pizzeriaExterior; m_infocenterState->SetUnknown0x74(5); } break; case 13: if (m_selectedCharacter) { - m_transitionDestination = LegoGameState::e_unk25; + m_transitionDestination = LegoGameState::e_garageExterior; m_infocenterState->SetUnknown0x74(5); } break; case 14: if (m_selectedCharacter) { - m_transitionDestination = LegoGameState::e_unk29; + m_transitionDestination = LegoGameState::e_hospitalExterior; m_infocenterState->SetUnknown0x74(5); } break; case 15: if (m_selectedCharacter) { - m_transitionDestination = LegoGameState::e_unk32; + m_transitionDestination = LegoGameState::e_policeExterior; m_infocenterState->SetUnknown0x74(5); } break; diff --git a/LEGO1/lego/legoomni/src/police/police.cpp b/LEGO1/lego/legoomni/src/police/police.cpp index 6c404a33..b95938ee 100644 --- a/LEGO1/lego/legoomni/src/police/police.cpp +++ b/LEGO1/lego/legoomni/src/police/police.cpp @@ -108,7 +108,7 @@ MxLong Police::HandleClick(LegoControlManagerEvent& p_param) } BackgroundAudioManager()->Stop(); - m_transitionDestination = LegoGameState::Area::e_unk35; + m_transitionDestination = LegoGameState::Area::e_polidoor; TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); break; case c_infoCtl: diff --git a/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp b/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp index 4fa43a3c..f58a519a 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp +++ b/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp @@ -94,3 +94,11 @@ double Lego3DManager::Render(double p_und) return m_pLego3DView->Render(p_und); } + +// FUNCTION: LEGO1 0x100ab4d0 +int Lego3DManager::SetFrustrum(float p_fov, float p_front, float p_back) +{ + m_pLego3DView->GetView()->SetFrustrum(p_front, p_back, p_fov); + m_pLego3DView->GetViewManager()->SetFrustrum(p_fov, p_front, p_back); + return 0; +} diff --git a/LEGO1/lego/sources/3dmanager/lego3dmanager.h b/LEGO1/lego/sources/3dmanager/lego3dmanager.h index 9d993f26..82f4e4a3 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dmanager.h +++ b/LEGO1/lego/sources/3dmanager/lego3dmanager.h @@ -51,6 +51,8 @@ class Lego3DManager { double Render(double p_und); + int SetFrustrum(float p_fov, float p_front, float p_back); + Tgl::Renderer* GetRenderer(); Tgl::Group* GetScene(); Lego3DView* GetLego3DView(); From b281866ea6068b853a7b8bba67f105d309b249c7 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sat, 24 Feb 2024 11:48:16 -0500 Subject: [PATCH 02/14] Implement/match LegoModelPresenter::CreateROI (#591) * Implement/match LegoModelPresenter::CreateROI * Match * Use inline function * Note about Get() --- LEGO1/lego/legoomni/include/legoomni.h | 2 + LEGO1/lego/legoomni/src/main/legoomni.cpp | 6 + .../legoomni/src/video/legomodelpresenter.cpp | 154 +++++++++++++++++- LEGO1/lego/sources/misc/legocontainer.cpp | 4 +- LEGO1/lego/sources/misc/legocontainer.h | 42 ++++- LEGO1/lego/sources/misc/legostorage.cpp | 14 -- LEGO1/lego/sources/misc/legostorage.h | 16 +- LEGO1/lego/sources/misc/version.h | 2 +- LEGO1/lego/sources/roi/legoroi.cpp | 18 ++ LEGO1/lego/sources/roi/legoroi.h | 12 ++ LEGO1/mxdirectx/mxdirect3d.h | 1 + LEGO1/mxgeometry/mxgeometry3d.h | 4 + 12 files changed, 248 insertions(+), 27 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoomni.h b/LEGO1/lego/legoomni/include/legoomni.h index a8b27b4d..c66df6fc 100644 --- a/LEGO1/lego/legoomni/include/legoomni.h +++ b/LEGO1/lego/legoomni/include/legoomni.h @@ -213,6 +213,7 @@ class LegoOmni : public MxOmni { LegoSoundManager* GetSoundManager() { return (LegoSoundManager*) m_soundManager; } LegoInputManager* GetInputManager() { return m_inputManager; } LegoTextureContainer* GetTextureContainer() { return m_textureContainer; } + ViewLODListManager* GetViewLODListManager() { return m_viewLODListManager; } LegoWorld* GetCurrentWorld() { return m_currentWorld; } LegoNavController* GetNavController() { return m_navController; } IslePathActor* GetCurrentVehicle() { return m_currentVehicle; } @@ -276,6 +277,7 @@ LegoPlantManager* PlantManager(); LegoWorld* CurrentWorld(); LegoUnkSaveDataWriter* UnkSaveDataWriter(); LegoTextureContainer* TextureContainer(); +ViewLODListManager* GetViewLODListManager(); void FUN_10015820(MxBool p_disable, MxU16 p_flags); void SetROIUnknown0x0c(const char* p_name, undefined p_unk0x0c); LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid); diff --git a/LEGO1/lego/legoomni/src/main/legoomni.cpp b/LEGO1/lego/legoomni/src/main/legoomni.cpp index 0ea4607d..f0081e2c 100644 --- a/LEGO1/lego/legoomni/src/main/legoomni.cpp +++ b/LEGO1/lego/legoomni/src/main/legoomni.cpp @@ -220,6 +220,12 @@ LegoTextureContainer* TextureContainer() return LegoOmni::GetInstance()->GetTextureContainer(); } +// FUNCTION: LEGO1 0x10015810 +ViewLODListManager* GetViewLODListManager() +{ + return LegoOmni::GetInstance()->GetViewLODListManager(); +} + // FUNCTION: LEGO1 0x10015820 void FUN_10015820(MxBool p_disable, MxU16 p_flags) { diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index abc43b4e..ad3199e2 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -1,5 +1,6 @@ #include "legomodelpresenter.h" +#include "anim/legoanim.h" #include "define.h" #include "legoentity.h" #include "legoentitypresenter.h" @@ -7,6 +8,9 @@ #include "legounksavedatawriter.h" #include "legovideomanager.h" #include "legoworld.h" +#include "misc/legocontainer.h" +#include "misc/legotexture.h" +#include "misc/version.h" #include "mxcompositepresenter.h" #include "mxutil.h" #include "roi/legoroi.h" @@ -47,11 +51,155 @@ void LegoModelPresenter::Destroy(MxBool p_fromDestructor) } } -// STUB: LEGO1 0x1007f6b0 +// FUNCTION: LEGO1 0x1007f6b0 MxResult LegoModelPresenter::CreateROI(MxStreamChunk* p_chunk) { - // TODO - return FAILURE; + MxResult result = FAILURE; + LegoU32 numROIs; + Mx3DPointFloat vect; + LegoMemory storage(p_chunk->GetData()); + LegoAnim anim; + LegoU32 version, textureInfoOffset, i, numTextures, skipTextures; + MxMatrix mat; + LegoChar* textureName = NULL; + LegoTexture* texture = NULL; + LegoS32 hardwareMode = VideoManager()->GetDirect3D()->AssignedDevice()->GetHardwareMode(); + + if (m_roi) { + delete m_roi; + } + if (!(m_roi = new LegoROI(VideoManager()->GetRenderer()))) { + goto done; + } + if (storage.Read(&version, sizeof(version)) != SUCCESS) { + goto done; + } + if (version != MODEL_VERSION) { + goto done; + } + if (storage.Read(&textureInfoOffset, sizeof(textureInfoOffset)) != SUCCESS) { + goto done; + } + + storage.SetPosition(textureInfoOffset); + + if (storage.Read(&numTextures, sizeof(numTextures)) != SUCCESS) { + goto done; + } + if (storage.Read(&skipTextures, sizeof(skipTextures)) != SUCCESS) { + goto done; + } + + for (i = 0; i < numTextures; i++) { + LegoU32 textureNameLength; + + storage.Read(&textureNameLength, sizeof(textureNameLength)); + textureName = new LegoChar[textureNameLength + 1]; + storage.Read(textureName, textureNameLength); + textureName[textureNameLength] = '\0'; + + strlwr(textureName); + + if (textureName[0] == '^') { + strcpy(textureName, textureName + 1); + + if (g_modelPresenterConfig) { + texture = new LegoTexture(); + if (texture->Read(&storage, hardwareMode) != SUCCESS) { + goto done; + } + + LegoTexture* discardTexture = new LegoTexture(); + if (discardTexture->Read(&storage, FALSE) != SUCCESS) { + goto done; + } + delete discardTexture; + } + else { + LegoTexture* discardTexture = new LegoTexture(); + if (discardTexture->Read(&storage, FALSE) != SUCCESS) { + goto done; + } + delete discardTexture; + + texture = new LegoTexture(); + if (texture->Read(&storage, hardwareMode) != SUCCESS) { + goto done; + } + } + } + else { + texture = new LegoTexture(); + if (texture->Read(&storage, hardwareMode) != SUCCESS) { + goto done; + } + } + + if (!skipTextures) { + if (TextureContainer()->Get(textureName) == NULL) { + LegoTextureInfo* textureInfo = LegoTextureInfo::Create(textureName, texture); + + if (textureInfo == NULL) { + goto done; + } + + TextureContainer()->Add(textureName, textureInfo); + } + + delete[] textureName; + textureName = NULL; + delete texture; + texture = NULL; + } + } + + storage.SetPosition(8); + + if (storage.Read(&numROIs, sizeof(numROIs)) != SUCCESS) { + goto done; + } + if (anim.Read(&storage, FALSE) != SUCCESS) { + goto done; + } + if (m_roi->Read(NULL, VideoManager()->GetRenderer(), GetViewLODListManager(), TextureContainer(), &storage) != + SUCCESS) { + goto done; + } + if (m_roi->SetFrame(&anim, 0) != SUCCESS) { + goto done; + } + + // Get scripted location, direction and up vectors + + CalcLocalTransform( + Mx3DPointFloat(m_action->GetLocation().GetX(), m_action->GetLocation().GetY(), m_action->GetLocation().GetZ()), + Mx3DPointFloat( + m_action->GetDirection().GetX(), + m_action->GetDirection().GetY(), + m_action->GetDirection().GetZ() + ), + Mx3DPointFloat(m_action->GetUp().GetX(), m_action->GetUp().GetY(), m_action->GetUp().GetZ()), + mat + ); + m_roi->FUN_100a46b0(mat); + + result = SUCCESS; + +done: + if (textureName != NULL) { + delete[] textureName; + } + if (texture != NULL) { + delete texture; + } + if (result != SUCCESS) { + if (m_roi) { + delete m_roi; + m_roi = NULL; + } + } + + return result; } // FUNCTION: LEGO1 0x10080050 diff --git a/LEGO1/lego/sources/misc/legocontainer.cpp b/LEGO1/lego/sources/misc/legocontainer.cpp index aebfc96d..7ccaf2d1 100644 --- a/LEGO1/lego/sources/misc/legocontainer.cpp +++ b/LEGO1/lego/sources/misc/legocontainer.cpp @@ -14,7 +14,7 @@ LegoTextureContainer::~LegoTextureContainer() } // FUNCTION: LEGO1 0x100998e0 -LegoTextureInfo* LegoTextureContainer::Insert(LegoTextureInfo* p_textureInfo) +LegoTextureInfo* LegoTextureContainer::AddToList(LegoTextureInfo* p_textureInfo) { DDSURFACEDESC desc, newDesc; DWORD width, height; @@ -110,7 +110,7 @@ LegoTextureInfo* LegoTextureContainer::Insert(LegoTextureInfo* p_textureInfo) } // FUNCTION: LEGO1 0x10099cc0 -void LegoTextureContainer::Erase(LegoTextureInfo* p_textureInfo) +void LegoTextureContainer::EraseFromList(LegoTextureInfo* p_textureInfo) { if (p_textureInfo == NULL) { return; diff --git a/LEGO1/lego/sources/misc/legocontainer.h b/LEGO1/lego/sources/misc/legocontainer.h index a1b869f1..561c2cbd 100644 --- a/LEGO1/lego/sources/misc/legocontainer.h +++ b/LEGO1/lego/sources/misc/legocontainer.h @@ -13,7 +13,7 @@ #pragma warning(disable : 4237) struct LegoContainerInfoComparator { - bool operator()(const char* const& p_key0, const char* const& p_key1) const { return strcmp(p_key0, p_key1) > 0; } + LegoU8 operator()(const char* const& p_key0, const char* const& p_key1) const { return strcmp(p_key0, p_key1) > 0; } }; // SIZE 0x10 @@ -44,16 +44,45 @@ class LegoContainer { inline T* Get(const char* p_name) { + // TODO: Score::Paint matches better with no `value` on the stack, + // while LegoModelPresenter::CreateROI only matches with `value` + T* value = NULL; + #ifdef COMPAT_MODE typename LegoContainerInfo::iterator it = m_map.find(p_name); #else LegoContainerInfo::iterator it = m_map.find(p_name); #endif + if (it != m_map.end()) { - return (*it).second; + value = (*it).second; } - return NULL; + return value; + } + + inline void Add(const char* p_name, T* p_value) + { +#ifdef COMPAT_MODE + typename LegoContainerInfo::iterator it = m_map.find(p_name); +#else + LegoContainerInfo::iterator it = m_map.find(p_name); +#endif + + char* name; + if (it != m_map.end()) { + name = const_cast((*it).first); + + if (m_ownership) { + delete (*it).second; + } + } + else { + name = new char[strlen(p_name) + 1]; + strcpy(name, p_name); + } + + m_map[name] = p_value; } inline void SetOwnership(LegoBool p_ownership) { m_ownership = p_ownership; } @@ -76,8 +105,8 @@ class LegoTextureContainer : public LegoContainer { LegoTextureContainer() { m_ownership = TRUE; } ~LegoTextureContainer() override; - LegoTextureInfo* Insert(LegoTextureInfo* p_textureInfo); - void Erase(LegoTextureInfo* p_textureInfo); + LegoTextureInfo* AddToList(LegoTextureInfo* p_textureInfo); + void EraseFromList(LegoTextureInfo* p_textureInfo); protected: LegoTextureList m_list; // 0x18 @@ -90,6 +119,9 @@ class LegoTextureContainer : public LegoContainer { // TEMPLATE: LEGO1 0x10001cc0 // _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Lbound +// TEMPLATE: LEGO1 0x1004f960 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::iterator::_Dec + // TEMPLATE: LEGO1 0x1004f9b0 // _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Insert diff --git a/LEGO1/lego/sources/misc/legostorage.cpp b/LEGO1/lego/sources/misc/legostorage.cpp index 8fa71553..7da93569 100644 --- a/LEGO1/lego/sources/misc/legostorage.cpp +++ b/LEGO1/lego/sources/misc/legostorage.cpp @@ -126,17 +126,3 @@ LegoResult LegoFile::Open(const char* p_name, LegoU32 p_mode) } return SUCCESS; } - -// FUNCTION: LEGO1 0x100994a0 -LegoResult LegoMemory::GetPosition(LegoU32& p_position) -{ - p_position = m_position; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x100994b0 -LegoResult LegoMemory::SetPosition(LegoU32 p_position) -{ - m_position = p_position; - return SUCCESS; -} diff --git a/LEGO1/lego/sources/misc/legostorage.h b/LEGO1/lego/sources/misc/legostorage.h index e975c347..2e7eb30b 100644 --- a/LEGO1/lego/sources/misc/legostorage.h +++ b/LEGO1/lego/sources/misc/legostorage.h @@ -47,8 +47,20 @@ class LegoMemory : public LegoStorage { LegoMemory(void* p_buffer); LegoResult Read(void* p_buffer, LegoU32 p_size) override; LegoResult Write(const void* p_buffer, LegoU32 p_size) override; - LegoResult GetPosition(LegoU32& p_position) override; - LegoResult SetPosition(LegoU32 p_position) override; + + // FUNCTION: LEGO1 0x100994a0 + LegoResult GetPosition(LegoU32& p_position) override + { + p_position = m_position; + return SUCCESS; + } + + // FUNCTION: LEGO1 0x100994b0 + LegoResult SetPosition(LegoU32 p_position) override + { + m_position = p_position; + return SUCCESS; + } // SYNTHETIC: LEGO1 0x10045a80 // LegoMemory::~LegoMemory diff --git a/LEGO1/lego/sources/misc/version.h b/LEGO1/lego/sources/misc/version.h index 1eaa84af..7f88091c 100644 --- a/LEGO1/lego/sources/misc/version.h +++ b/LEGO1/lego/sources/misc/version.h @@ -1,6 +1,6 @@ #ifndef __VERSION_H #define __VERSION_H -#define MODEL_VERSION 3 +#define MODEL_VERSION 19 #endif // __VERSION_H diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index bc0131f7..3463022e 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -96,6 +96,24 @@ LegoROI::~LegoROI() } } +// STUB: LEGO1 0x100a84a0 +LegoResult LegoROI::Read( + OrientableROI* p_unk0xd4, + Tgl::Renderer* p_renderer, + ViewLODListManager* p_viewLODListManager, + LegoTextureContainer* p_textureContainer, + LegoStorage* p_storage +) +{ + return SUCCESS; +} + +// STUB: LEGO1 0x100a90f0 +LegoResult LegoROI::SetFrame(LegoAnim* p_anim, LegoTime p_time) +{ + return SUCCESS; +} + // FUNCTION: LEGO1 0x100a9a50 TimeROI::TimeROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, int p_time) : LegoROI(p_renderer, p_lodList) { diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index 8b6c78ce..ab2b45d1 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -7,6 +7,9 @@ typedef unsigned char (*ROIHandler)(char*, char*, unsigned int); class LegoEntity; +class LegoTextureContainer; +class LegoStorage; +class LegoAnim; // VTABLE: LEGO1 0x100dbe38 // SIZE 0x108 @@ -16,6 +19,15 @@ class LegoROI : public ViewROI { LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList); ~LegoROI() override; + LegoResult Read( + OrientableROI* p_unk0xd4, + Tgl::Renderer* p_renderer, + ViewLODListManager* p_viewLODListManager, + LegoTextureContainer* p_textureContainer, + LegoStorage* p_storage + ); + LegoResult SetFrame(LegoAnim* p_anim, LegoTime p_time); + float IntrinsicImportance() const override; // vtable+0x04 void UpdateWorldBoundingVolumes() override; // vtable+0x18 diff --git a/LEGO1/mxdirectx/mxdirect3d.h b/LEGO1/mxdirectx/mxdirect3d.h index 341f9c69..bbfe7e3b 100644 --- a/LEGO1/mxdirectx/mxdirect3d.h +++ b/LEGO1/mxdirectx/mxdirect3d.h @@ -22,6 +22,7 @@ class MxAssignedDevice { ~MxAssignedDevice(); inline unsigned int GetFlags() { return m_flags; } + inline BOOL GetHardwareMode() { return ((int) m_flags << 31) >> 31; } inline D3DDEVICEDESC& GetDesc() { return m_desc; } friend class MxDirect3D; diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index bdb3f191..48c46fcf 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -15,6 +15,10 @@ class Mx3DPointFloat : public Vector3 { m_elements[2] = p_z; } + inline float GetX() { return m_data[0]; } + inline float GetY() { return m_data[1]; } + inline float GetZ() { return m_data[2]; } + // FUNCTION: LEGO1 0x100343a0 inline Mx3DPointFloat(const Mx3DPointFloat& p_other) : Vector3(m_elements) { EqualsImpl(p_other.m_data); } From 377eebb61039b4f93eb7ab973d38f3b88454e3cb Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 25 Feb 2024 09:14:39 -0500 Subject: [PATCH 03/14] Minor style/naming fixes (#593) --- LEGO1/lego/legoomni/include/legoanimpresenter.h | 2 +- LEGO1/lego/legoomni/include/legocachesoundlist.h | 2 +- LEGO1/lego/legoomni/include/legoentitylist.h | 2 +- LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h | 2 +- LEGO1/lego/legoomni/include/legopathcontrollerlist.h | 2 +- LEGO1/lego/legoomni/include/legoworldlist.h | 2 +- LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp | 4 ++-- .../legoomni/src/video/legolocomotionanimpresenter.cpp | 4 ++-- LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp | 4 ++-- LEGO1/lego/sources/misc/legocontainer.h | 5 ++++- LEGO1/lego/sources/misc/legostorage.h | 2 +- LEGO1/omni/include/mxcollection.h | 2 +- LEGO1/omni/include/mxdsactionlist.h | 2 +- LEGO1/omni/include/mxlist.h | 2 +- LEGO1/omni/include/mxpresenterlist.h | 2 +- LEGO1/omni/include/mxrectlist.h | 2 +- LEGO1/omni/include/mxregionlist.h | 4 ++-- LEGO1/omni/include/mxstreamchunklist.h | 2 +- LEGO1/omni/include/mxstringlist.h | 2 +- LEGO1/omni/include/mxvideopresenter.h | 8 ++++---- 20 files changed, 30 insertions(+), 27 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 7ae607fd..6492c701 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -38,7 +38,7 @@ class LegoAnimPresenter : public MxVideoPresenter { MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c void EndAction() override; // vtable+0x40 void PutFrame() override; // vtable+0x6c - virtual MxResult VTable0x88(MxStreamChunk* p_chunk); // vtable+0x88 + virtual MxResult CreateAnim(MxStreamChunk* p_chunk); // vtable+0x88 inline LegoAnim* GetAnimation() { return m_anim; } diff --git a/LEGO1/lego/legoomni/include/legocachesoundlist.h b/LEGO1/lego/legoomni/include/legocachesoundlist.h index 25459911..4960f6b3 100644 --- a/LEGO1/lego/legoomni/include/legocachesoundlist.h +++ b/LEGO1/lego/legoomni/include/legocachesoundlist.h @@ -38,7 +38,7 @@ class LegoCacheSoundList : public MxPtrList { // SIZE 0x10 class LegoCacheSoundListCursor : public MxPtrListCursor { public: - LegoCacheSoundListCursor(LegoCacheSoundList* p_list) : MxPtrListCursor(p_list){}; + LegoCacheSoundListCursor(LegoCacheSoundList* p_list) : MxPtrListCursor(p_list) {} }; // TEMPLATE: LEGO1 0x1001e670 diff --git a/LEGO1/lego/legoomni/include/legoentitylist.h b/LEGO1/lego/legoomni/include/legoentitylist.h index 938c85d4..783692b3 100644 --- a/LEGO1/lego/legoomni/include/legoentitylist.h +++ b/LEGO1/lego/legoomni/include/legoentitylist.h @@ -38,7 +38,7 @@ class LegoEntityList : public MxPtrList { // SIZE 0x10 class LegoEntityListCursor : public MxPtrListCursor { public: - LegoEntityListCursor(LegoEntityList* p_list) : MxPtrListCursor(p_list){}; + LegoEntityListCursor(LegoEntityList* p_list) : MxPtrListCursor(p_list) {} }; // TEMPLATE: LEGO1 0x1001e2f0 diff --git a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h index 2a78176d..55eda20b 100644 --- a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h @@ -30,7 +30,7 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { void Destroy() override; // vtable+0x38 void EndAction() override; // vtable+0x40 void PutFrame() override; // vtable+0x6c - MxResult VTable0x88(MxStreamChunk* p_chunk) override; // vtable+0x88 + MxResult CreateAnim(MxStreamChunk* p_chunk) override; // vtable+0x88 // SYNTHETIC: LEGO1 0x1006cfe0 // LegoLocomotionAnimPresenter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legopathcontrollerlist.h b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h index af2642a2..f3728b06 100644 --- a/LEGO1/lego/legoomni/include/legopathcontrollerlist.h +++ b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h @@ -37,7 +37,7 @@ class LegoPathControllerList : public MxPtrList { // SIZE 0x10 class LegoPathControllerListCursor : public MxPtrListCursor { public: - LegoPathControllerListCursor(LegoPathControllerList* p_list) : MxPtrListCursor(p_list){}; + LegoPathControllerListCursor(LegoPathControllerList* p_list) : MxPtrListCursor(p_list) {} }; // TEMPLATE: LEGO1 0x1001d230 diff --git a/LEGO1/lego/legoomni/include/legoworldlist.h b/LEGO1/lego/legoomni/include/legoworldlist.h index 577d310f..6d1006b0 100644 --- a/LEGO1/lego/legoomni/include/legoworldlist.h +++ b/LEGO1/lego/legoomni/include/legoworldlist.h @@ -38,7 +38,7 @@ class LegoWorldList : public MxPtrList { // SIZE 0x10 class LegoWorldListCursor : public MxPtrListCursor { public: - LegoWorldListCursor(LegoWorldList* p_list) : MxPtrListCursor(p_list){}; + LegoWorldListCursor(LegoWorldList* p_list) : MxPtrListCursor(p_list) {} }; // SYNTHETIC: LEGO1 0x1003e870 diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index ba22865c..a841b50d 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -54,7 +54,7 @@ void LegoAnimPresenter::Destroy(MxBool p_fromDestructor) } // FUNCTION: LEGO1 0x10068fb0 -MxResult LegoAnimPresenter::VTable0x88(MxStreamChunk* p_chunk) +MxResult LegoAnimPresenter::CreateAnim(MxStreamChunk* p_chunk) { MxResult result = FAILURE; LegoMemory storage(p_chunk->GetData()); @@ -120,7 +120,7 @@ void LegoAnimPresenter::ReadyTickle() if (chunk && chunk->GetTime() + m_action->GetStartTime() <= m_action->GetElapsedTime()) { chunk = m_subscriber->PopData(); - MxResult result = VTable0x88(chunk); + MxResult result = CreateAnim(chunk); m_subscriber->FreeDataChunk(chunk); if (result == SUCCESS) { diff --git a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp index 45098aac..4886245e 100644 --- a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp @@ -52,9 +52,9 @@ void LegoLocomotionAnimPresenter::Destroy(MxBool p_fromDestructor) } // FUNCTION: LEGO1 0x1006d140 -MxResult LegoLocomotionAnimPresenter::VTable0x88(MxStreamChunk* p_chunk) +MxResult LegoLocomotionAnimPresenter::CreateAnim(MxStreamChunk* p_chunk) { - MxResult result = LegoAnimPresenter::VTable0x88(p_chunk); + MxResult result = LegoAnimPresenter::CreateAnim(p_chunk); return result == SUCCESS ? SUCCESS : result; } diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index ad3199e2..7a0dac49 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -214,7 +214,7 @@ void LegoModelPresenter::ReadyTickle() if (m_roi != NULL) { if (m_compositePresenter && m_compositePresenter->IsA("LegoEntityPresenter")) { - ((LegoEntityPresenter*) m_compositePresenter)->GetEntity()->SetROI((LegoROI*) m_roi, m_addedToView, TRUE); + ((LegoEntityPresenter*) m_compositePresenter)->GetEntity()->SetROI(m_roi, m_addedToView, TRUE); ((LegoEntityPresenter*) m_compositePresenter) ->GetEntity() ->SetFlags( @@ -240,7 +240,7 @@ void LegoModelPresenter::ReadyTickle() VideoManager()->Get3DManager()->GetLego3DView()->Moved(*m_roi); if (m_compositePresenter != NULL && m_compositePresenter->IsA("LegoEntityPresenter")) { - ((LegoEntityPresenter*) m_compositePresenter)->GetEntity()->SetROI((LegoROI*) m_roi, TRUE, TRUE); + ((LegoEntityPresenter*) m_compositePresenter)->GetEntity()->SetROI(m_roi, TRUE, TRUE); ((LegoEntityPresenter*) m_compositePresenter) ->GetEntity() ->SetFlags( diff --git a/LEGO1/lego/sources/misc/legocontainer.h b/LEGO1/lego/sources/misc/legocontainer.h index 561c2cbd..ac387e0d 100644 --- a/LEGO1/lego/sources/misc/legocontainer.h +++ b/LEGO1/lego/sources/misc/legocontainer.h @@ -13,7 +13,10 @@ #pragma warning(disable : 4237) struct LegoContainerInfoComparator { - LegoU8 operator()(const char* const& p_key0, const char* const& p_key1) const { return strcmp(p_key0, p_key1) > 0; } + LegoBool operator()(const char* const& p_key0, const char* const& p_key1) const + { + return strcmp(p_key0, p_key1) > 0; + } }; // SIZE 0x10 diff --git a/LEGO1/lego/sources/misc/legostorage.h b/LEGO1/lego/sources/misc/legostorage.h index 2e7eb30b..08e295f4 100644 --- a/LEGO1/lego/sources/misc/legostorage.h +++ b/LEGO1/lego/sources/misc/legostorage.h @@ -20,7 +20,7 @@ class LegoStorage { LegoStorage() : m_mode(0) {} // FUNCTION: LEGO1 0x10045ad0 - virtual ~LegoStorage(){}; + virtual ~LegoStorage() {} virtual LegoResult Read(void* p_buffer, LegoU32 p_size) = 0; virtual LegoResult Write(const void* p_buffer, LegoU32 p_size) = 0; diff --git a/LEGO1/omni/include/mxcollection.h b/LEGO1/omni/include/mxcollection.h index 84acdeef..0c21438c 100644 --- a/LEGO1/omni/include/mxcollection.h +++ b/LEGO1/omni/include/mxcollection.h @@ -12,7 +12,7 @@ class MxCollection : public MxCore { SetDestroy(Destroy); } - static void Destroy(T){}; + static void Destroy(T) {} void SetDestroy(void (*p_customDestructor)(T)) { this->m_customDestructor = p_customDestructor; } diff --git a/LEGO1/omni/include/mxdsactionlist.h b/LEGO1/omni/include/mxdsactionlist.h index b413cd2b..6c8b8024 100644 --- a/LEGO1/omni/include/mxdsactionlist.h +++ b/LEGO1/omni/include/mxdsactionlist.h @@ -41,7 +41,7 @@ class MxDSActionList : public MxList { // SIZE 0x10 class MxDSActionListCursor : public MxListCursor { public: - MxDSActionListCursor(MxDSActionList* p_list) : MxListCursor(p_list){}; + MxDSActionListCursor(MxDSActionList* p_list) : MxListCursor(p_list) {} }; // TEMPLATE: LEGO1 0x100c9cc0 diff --git a/LEGO1/omni/include/mxlist.h b/LEGO1/omni/include/mxlist.h index 5ad02492..aeed9646 100644 --- a/LEGO1/omni/include/mxlist.h +++ b/LEGO1/omni/include/mxlist.h @@ -135,7 +135,7 @@ class MxListCursor : public MxCore { template class MxPtrListCursor : public MxListCursor { public: - MxPtrListCursor(MxPtrList* p_list) : MxListCursor(p_list){}; + MxPtrListCursor(MxPtrList* p_list) : MxListCursor(p_list) {} }; template diff --git a/LEGO1/omni/include/mxpresenterlist.h b/LEGO1/omni/include/mxpresenterlist.h index 1c52f360..87430a53 100644 --- a/LEGO1/omni/include/mxpresenterlist.h +++ b/LEGO1/omni/include/mxpresenterlist.h @@ -32,7 +32,7 @@ class MxPresenterList : public MxPtrList { // VTABLE: LEGO1 0x100d6470 class MxPresenterListCursor : public MxPtrListCursor { public: - MxPresenterListCursor(MxPresenterList* p_list) : MxPtrListCursor(p_list){}; + MxPresenterListCursor(MxPresenterList* p_list) : MxPtrListCursor(p_list) {} }; // VTABLE: LEGO1 0x100d6350 diff --git a/LEGO1/omni/include/mxrectlist.h b/LEGO1/omni/include/mxrectlist.h index c25c2483..88cffa9f 100644 --- a/LEGO1/omni/include/mxrectlist.h +++ b/LEGO1/omni/include/mxrectlist.h @@ -20,7 +20,7 @@ class MxRectList : public MxPtrList { // VTABLE: LEGO1 0x100dc420 class MxRectListCursor : public MxPtrListCursor { public: - MxRectListCursor(MxRectList* p_list) : MxPtrListCursor(p_list){}; + MxRectListCursor(MxRectList* p_list) : MxPtrListCursor(p_list) {} }; // VTABLE: LEGO1 0x100dc3d8 diff --git a/LEGO1/omni/include/mxregionlist.h b/LEGO1/omni/include/mxregionlist.h index 9dfd78bd..b7eff3ae 100644 --- a/LEGO1/omni/include/mxregionlist.h +++ b/LEGO1/omni/include/mxregionlist.h @@ -54,7 +54,7 @@ class MxRegionLeftRightList : public MxPtrList { // VTABLE: LEGO1 0x100dcc10 class MxRegionLeftRightListCursor : public MxPtrListCursor { public: - MxRegionLeftRightListCursor(MxRegionLeftRightList* p_list) : MxPtrListCursor(p_list){}; + MxRegionLeftRightListCursor(MxRegionLeftRightList* p_list) : MxPtrListCursor(p_list) {} }; // SIZE 0x0c @@ -116,7 +116,7 @@ class MxRegionTopBottomList : public MxPtrList { // VTABLE: LEGO1 0x100dcb88 class MxRegionTopBottomListCursor : public MxPtrListCursor { public: - MxRegionTopBottomListCursor(MxPtrList* p_list) : MxPtrListCursor(p_list){}; + MxRegionTopBottomListCursor(MxPtrList* p_list) : MxPtrListCursor(p_list) {} }; // TEMPLATE: LEGO1 0x100c32e0 diff --git a/LEGO1/omni/include/mxstreamchunklist.h b/LEGO1/omni/include/mxstreamchunklist.h index defdd4a0..4ae8fabe 100644 --- a/LEGO1/omni/include/mxstreamchunklist.h +++ b/LEGO1/omni/include/mxstreamchunklist.h @@ -35,7 +35,7 @@ class MxStreamChunkList : public MxList { // SIZE 0x10 class MxStreamChunkListCursor : public MxListCursor { public: - MxStreamChunkListCursor(MxStreamChunkList* p_list) : MxListCursor(p_list){}; + MxStreamChunkListCursor(MxStreamChunkList* p_list) : MxListCursor(p_list) {} }; // VTABLE: LEGO1 0x100dc528 diff --git a/LEGO1/omni/include/mxstringlist.h b/LEGO1/omni/include/mxstringlist.h index 6d07584f..7894aabd 100644 --- a/LEGO1/omni/include/mxstringlist.h +++ b/LEGO1/omni/include/mxstringlist.h @@ -12,7 +12,7 @@ class MxStringList : public MxList {}; // SIZE 0x10 class MxStringListCursor : public MxListCursor { public: - MxStringListCursor(MxStringList* p_list) : MxListCursor(p_list){}; + MxStringListCursor(MxStringList* p_list) : MxListCursor(p_list) {} // SYNTHETIC: LEGO1 0x100cb860 // MxStringList::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxvideopresenter.h b/LEGO1/omni/include/mxvideopresenter.h index 06436163..b7d12597 100644 --- a/LEGO1/omni/include/mxvideopresenter.h +++ b/LEGO1/omni/include/mxvideopresenter.h @@ -43,20 +43,20 @@ class MxVideoPresenter : public MxMediaPresenter { MxBool IsHit(MxS32 p_x, MxS32 p_y) override; // vtable+0x50 // FUNCTION: LEGO1 0x1000c700 - virtual void LoadHeader(MxStreamChunk* p_chunk){}; // vtable+0x5c + virtual void LoadHeader(MxStreamChunk* p_chunk) {} // vtable+0x5c // FUNCTION: LEGO1 0x1000c710 - virtual void CreateBitmap(){}; // vtable+0x60 + virtual void CreateBitmap() {} // vtable+0x60 virtual void NextFrame(); // vtable+0x64 // FUNCTION: LEGO1 0x1000c720 - virtual void LoadFrame(MxStreamChunk* p_chunk){}; // vtable+0x68 + virtual void LoadFrame(MxStreamChunk* p_chunk) {} // vtable+0x68 virtual void PutFrame(); // vtable+0x6c // FUNCTION: LEGO1 0x1000c730 - virtual void RealizePalette(){}; // vtable+0x70 + virtual void RealizePalette() {} // vtable+0x70 virtual undefined VTable0x74(); // vtable+0x74 From 96c98cec3dbd699b25f2ed2503a4bbce6384d158 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 25 Feb 2024 12:04:30 -0500 Subject: [PATCH 04/14] Implement LegoAnimPresenter::FUN_100692b0 (#594) * Implement LegoAnimPresenter::FUN_100692b0 * Match --- .../lego/legoomni/include/legoanimpresenter.h | 6 +- LEGO1/lego/legoomni/include/legoroilist.h | 54 +++++++++++ .../legoomni/include/legounksavedatawriter.h | 2 + .../src/common/legounksavedatawriter.cpp | 12 +++ .../legoomni/src/video/legoanimpresenter.cpp | 96 ++++++++++++++++++- LEGO1/lego/sources/anim/legoanim.cpp | 20 ++++ LEGO1/lego/sources/anim/legoanim.h | 4 + 7 files changed, 190 insertions(+), 4 deletions(-) create mode 100644 LEGO1/lego/legoomni/include/legoroilist.h diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 6492c701..86206fee 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -2,6 +2,7 @@ #define LEGOANIMPRESENTER_H #include "anim/legoanim.h" +#include "legoroilist.h" #include "mxgeometry/mxgeometry3d.h" #include "mxvideopresenter.h" @@ -47,12 +48,15 @@ class LegoAnimPresenter : public MxVideoPresenter { protected: void Init(); void Destroy(MxBool p_fromDestructor); + LegoChar* FUN_10069150(const LegoChar*); + void FUN_100692b0(); + LegoChar* FUN_100697c0(const LegoChar*, LegoChar*); LegoAnim* m_anim; // 0x64 undefined4 m_unk0x68; // 0x68 undefined4 m_unk0x6c; // 0x6c undefined4 m_unk0x70; // 0x70 - undefined4 m_unk0x74; // 0x74 + LegoROIList* m_unk0x74; // 0x74 undefined4 m_unk0x78; // 0x78 undefined4 m_unk0x7c; // 0x7c LegoWorld* m_currentWorld; // 0x80 diff --git a/LEGO1/lego/legoomni/include/legoroilist.h b/LEGO1/lego/legoomni/include/legoroilist.h new file mode 100644 index 00000000..fb2cb3f1 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoroilist.h @@ -0,0 +1,54 @@ +#ifndef LEGOROILIST_H +#define LEGOROILIST_H + +#include "mxlist.h" +#include "mxtypes.h" +#include "roi/legoroi.h" + +// VTABLE: LEGO1 0x100d8c30 +// class MxCollection + +// VTABLE: LEGO1 0x100d8c48 +// class MxList + +// VTABLE: LEGO1 0x100d8c60 +// class MxPtrList + +// VTABLE: LEGO1 0x100d8c78 +// SIZE 0x18 +class LegoROIList : public MxPtrList { +public: + LegoROIList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} + + // FUNCTION: LEGO1 0x1005f360 + MxS8 Compare(LegoROI* p_a, LegoROI* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 + + // SYNTHETIC: LEGO1 0x1005f480 + // LegoROIList::`scalar deleting destructor' +}; + +// TEMPLATE: LEGO1 0x1005f380 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x1005f390 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x1005f3e0 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x1005f3f0 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x1005f4f0 +// MxPtrList::~MxPtrList + +// SYNTHETIC: LEGO1 0x1005f540 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1005f5b0 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1005f660 +// MxPtrList::`scalar deleting destructor' + +#endif // LEGOROILIST_H diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index 7fa539ca..7c49bfa1 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -64,6 +64,8 @@ class LegoUnkSaveDataWriter { void FUN_100832a0(); void FUN_10083db0(LegoROI* p_roi); void FUN_10083f10(LegoROI* p_roi); + LegoROI* FUN_10085210(LegoChar*, LegoChar*, undefined); + LegoROI* FUN_10085a80(LegoChar* p_und1, LegoChar* p_und2, undefined p_und3); private: static char* g_customizeAnimFile; diff --git a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp index 336c5838..a1055e63 100644 --- a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp +++ b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp @@ -127,3 +127,15 @@ void LegoUnkSaveDataWriter::SetCustomizeAnimFile(const char* p_value) g_customizeAnimFile = NULL; } } + +// STUB: LEGO1 0x10085210 +LegoROI* LegoUnkSaveDataWriter::FUN_10085210(LegoChar*, LegoChar*, undefined) +{ + return NULL; +} + +// FUNCTION: LEGO1 0x10085a80 +LegoROI* LegoUnkSaveDataWriter::FUN_10085a80(LegoChar* p_und1, LegoChar* p_und2, undefined p_und3) +{ + return FUN_10085210(p_und1, p_und2, p_und3); +} diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index a841b50d..2eae93ca 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -1,6 +1,7 @@ #include "legoanimpresenter.h" #include "legoomni.h" +#include "legounksavedatawriter.h" #include "legoworld.h" #include "mxcompositepresenter.h" #include "mxdsanim.h" @@ -27,7 +28,7 @@ void LegoAnimPresenter::Init() m_anim = NULL; m_unk0x68 = 0; m_unk0x6c = 0; - m_unk0x74 = 0; + m_unk0x74 = NULL; m_unk0x70 = 0; m_unk0x78 = 0; m_unk0x7c = 0; @@ -104,6 +105,95 @@ MxResult LegoAnimPresenter::CreateAnim(MxStreamChunk* p_chunk) return result; } +// STUB: LEGO1 0x10069150 +LegoChar* LegoAnimPresenter::FUN_10069150(const LegoChar*) +{ + return NULL; +} + +// FUNCTION: LEGO1 0x100692b0 +void LegoAnimPresenter::FUN_100692b0() +{ + m_unk0x74 = new LegoROIList(); + + if (m_unk0x74) { + LegoU32 numActors = m_anim->GetNumActors(); + + for (LegoU32 i = 0; i < numActors; i++) { + LegoChar* str = FUN_100697c0(m_anim->GetActorName(i), NULL); + undefined4 unk0x04 = m_anim->GetActorUnknown0x04(i); + LegoROI* roi = NULL; + + if (unk0x04 == 2) { + LegoChar* src; + if (str[0] == '*') { + src = str + 1; + } + else { + src = str; + } + + roi = UnkSaveDataWriter()->FUN_10083500(src, TRUE); + + if (roi != NULL && str[0] == '*') { + roi->SetUnknown0x0c(0); + } + } + else if (unk0x04 == 4) { + LegoChar* src = new LegoChar[strlen(str)]; + strcpy(src, str + 1); + strlwr(src); + + LegoChar* und = FUN_10069150(str); + roi = UnkSaveDataWriter()->FUN_10085a80(und, src, 1); + + if (roi != NULL) { + roi->SetUnknown0x0c(0); + } + + delete[] src; + delete[] und; + } + else if (unk0x04 == 3) { + LegoChar* src = new LegoChar[strlen(str)]; + strcpy(src, str + 1); + + for (LegoChar* i = &src[strlen(src) - 1]; i > src; i--) { + if ((*i < '0' || *i > '9') && *i != '_') { + break; + } + + *i = '\0'; + } + + strlwr(src); + + LegoChar* und = FUN_10069150(str); + roi = UnkSaveDataWriter()->FUN_10085210(und, src, 1); + + if (roi != NULL) { + roi->SetUnknown0x0c(0); + } + + delete[] src; + delete[] und; + } + + if (roi != NULL) { + m_unk0x74->Append(roi); + } + + delete[] str; + } + } +} + +// STUB: LEGO1 0x100697c0 +LegoChar* LegoAnimPresenter::FUN_100697c0(const LegoChar*, LegoChar*) +{ + return NULL; +} + // STUB: LEGO1 0x1006ad30 void LegoAnimPresenter::PutFrame() { @@ -165,10 +255,10 @@ void LegoAnimPresenter::StreamingTickle() } } -// STUB: LEGO1 0x1006b8c0 +// FUNCTION: LEGO1 0x1006b8c0 void LegoAnimPresenter::DoneTickle() { - // TODO + MxVideoPresenter::DoneTickle(); } // FUNCTION: LEGO1 0x1006b8d0 diff --git a/LEGO1/lego/sources/anim/legoanim.cpp b/LEGO1/lego/sources/anim/legoanim.cpp index d172ceb8..5cae74c3 100644 --- a/LEGO1/lego/sources/anim/legoanim.cpp +++ b/LEGO1/lego/sources/anim/legoanim.cpp @@ -504,6 +504,26 @@ LegoResult LegoAnim::Write(LegoStorage* p_storage) return SUCCESS; } +// FUNCTION: LEGO1 0x100a0f20 +const LegoChar* LegoAnim::GetActorName(LegoU32 p_index) +{ + if (p_index < m_numActors) { + return m_actors[p_index].m_name; + } + + return NULL; +} + +// FUNCTION: LEGO1 0x100a0f40 +undefined4 LegoAnim::GetActorUnknown0x04(LegoU32 p_index) +{ + if (p_index < m_numActors) { + return m_actors[p_index].m_unk0x04; + } + + return NULL; +} + // FUNCTION: LEGO1 0x100a0f60 LegoMorphKey::LegoMorphKey() { diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h index a16b2415..ce8326d0 100644 --- a/LEGO1/lego/sources/anim/legoanim.h +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -139,9 +139,13 @@ class LegoAnim : public LegoTree { LegoAnim(); ~LegoAnim() override; LegoTime GetDuration() { return m_duration; } + LegoU32 GetNumActors() { return m_numActors; } LegoResult Write(LegoStorage* p_storage) override; // vtable+0x08 virtual LegoResult Read(LegoStorage* p_storage, LegoS32 p_parseScene); // vtable+0x10 + const LegoChar* GetActorName(LegoU32 p_index); + undefined4 GetActorUnknown0x04(LegoU32 p_index); + // SYNTHETIC: LEGO1 0x100a0ba0 // LegoAnim::`scalar deleting destructor' From c5318dca1350cb9a11bef5002de49dc4418536d7 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 25 Feb 2024 12:55:57 -0500 Subject: [PATCH 05/14] Implement/match LegoAnimPresenter::FUN_100695c0 (#595) --- .../lego/legoomni/include/legoanimpresenter.h | 4 +- .../legoomni/include/legounksavedatawriter.h | 2 +- .../src/common/legounksavedatawriter.cpp | 2 +- .../legoomni/src/video/legoanimpresenter.cpp | 46 ++++++++++++++++++- LEGO1/library_msvc.h | 3 ++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 86206fee..9d1a6416 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -50,12 +50,14 @@ class LegoAnimPresenter : public MxVideoPresenter { void Destroy(MxBool p_fromDestructor); LegoChar* FUN_10069150(const LegoChar*); void FUN_100692b0(); + void FUN_100695c0(); LegoChar* FUN_100697c0(const LegoChar*, LegoChar*); + LegoBool FUN_100698b0(CompoundObject&, const LegoChar*); LegoAnim* m_anim; // 0x64 undefined4 m_unk0x68; // 0x68 undefined4 m_unk0x6c; // 0x6c - undefined4 m_unk0x70; // 0x70 + LegoROIList* m_unk0x70; // 0x70 LegoROIList* m_unk0x74; // 0x74 undefined4 m_unk0x78; // 0x78 undefined4 m_unk0x7c; // 0x7c diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index 7c49bfa1..7dd38998 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -64,7 +64,7 @@ class LegoUnkSaveDataWriter { void FUN_100832a0(); void FUN_10083db0(LegoROI* p_roi); void FUN_10083f10(LegoROI* p_roi); - LegoROI* FUN_10085210(LegoChar*, LegoChar*, undefined); + LegoROI* FUN_10085210(const LegoChar*, LegoChar*, undefined); LegoROI* FUN_10085a80(LegoChar* p_und1, LegoChar* p_und2, undefined p_und3); private: diff --git a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp index a1055e63..2fdc658c 100644 --- a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp +++ b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp @@ -129,7 +129,7 @@ void LegoUnkSaveDataWriter::SetCustomizeAnimFile(const char* p_value) } // STUB: LEGO1 0x10085210 -LegoROI* LegoUnkSaveDataWriter::FUN_10085210(LegoChar*, LegoChar*, undefined) +LegoROI* LegoUnkSaveDataWriter::FUN_10085210(const LegoChar*, LegoChar*, undefined) { return NULL; } diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 2eae93ca..0c04bb25 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -2,6 +2,7 @@ #include "legoomni.h" #include "legounksavedatawriter.h" +#include "legovideomanager.h" #include "legoworld.h" #include "mxcompositepresenter.h" #include "mxdsanim.h" @@ -29,7 +30,7 @@ void LegoAnimPresenter::Init() m_unk0x68 = 0; m_unk0x6c = 0; m_unk0x74 = NULL; - m_unk0x70 = 0; + m_unk0x70 = NULL; m_unk0x78 = 0; m_unk0x7c = 0; m_unk0xa8.Clear(); @@ -108,6 +109,7 @@ MxResult LegoAnimPresenter::CreateAnim(MxStreamChunk* p_chunk) // STUB: LEGO1 0x10069150 LegoChar* LegoAnimPresenter::FUN_10069150(const LegoChar*) { + // TODO return NULL; } @@ -188,12 +190,54 @@ void LegoAnimPresenter::FUN_100692b0() } } +// FUNCTION: LEGO1 0x100695c0 +void LegoAnimPresenter::FUN_100695c0() +{ + m_unk0x70 = new LegoROIList(); + + if (m_unk0x70) { + CompoundObject& unk0x08 = VideoManager()->Get3DManager()->GetLego3DView()->GetViewManager()->GetUnknown0x08(); + LegoU32 numActors = m_anim->GetNumActors(); + + for (LegoU32 i = 0; i < numActors; i++) { + if (FUN_100698b0(unk0x08, m_anim->GetActorName(i)) == FALSE) { + undefined4 unk0x04 = m_anim->GetActorUnknown0x04(i); + + if (unk0x04 == 5 || unk0x04 == 6) { + LegoChar dest[256]; + const LegoChar* str = m_anim->GetActorName(i); + + LegoU32 len = strlen(str); + strcpy(dest, str); + + for (LegoChar* i = &dest[len - 1]; isdigit(*i) || *i == '_'; i--) { + *i = '\0'; + } + + strlwr(dest); + + UnkSaveDataWriter()->FUN_10085210(str, dest, 0); + FUN_100698b0(unk0x08, str); + } + } + } + } +} + // STUB: LEGO1 0x100697c0 LegoChar* LegoAnimPresenter::FUN_100697c0(const LegoChar*, LegoChar*) { + // TODO return NULL; } +// STUB: LEGO1 0x100698b0 +LegoBool LegoAnimPresenter::FUN_100698b0(CompoundObject&, const LegoChar*) +{ + // TODO + return FALSE; +} + // STUB: LEGO1 0x1006ad30 void LegoAnimPresenter::PutFrame() { diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 259ed919..f08a4876 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -81,6 +81,9 @@ // LIBRARY: LEGO1 0x1008c5c0 // _fseek +// LIBRARY: LEGO1 0x1008c6a0 +// _isdigit + // LIBRARY: LEGO1 0x1008ca60 // _abort From b524b47723ec0277f71fdbeb9e22f67874b41572 Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Mon, 26 Feb 2024 10:12:14 -0500 Subject: [PATCH 06/14] 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; } From 124b73046bc43a0cf835793575220be685cf8360 Mon Sep 17 00:00:00 2001 From: Nathan M Gilbert Date: Mon, 26 Feb 2024 11:19:16 -0500 Subject: [PATCH 07/14] Continued work on LegoGameState (#596) * Continued work on LegoGameState * Fixes/matches/refactor --------- Co-authored-by: Christian Semmler --- LEGO1/lego/legoomni/include/legoactor.h | 8 +- LEGO1/lego/legoomni/include/legoentity.h | 1 + LEGO1/lego/legoomni/include/legogamestate.h | 41 ++-- LEGO1/lego/legoomni/include/legoomni.h | 8 +- LEGO1/lego/legoomni/include/legopathactor.h | 7 +- .../legoomni/include/legounksavedatawriter.h | 4 +- LEGO1/lego/legoomni/src/build/helicopter.cpp | 12 +- .../legoomni/src/common/legogamestate.cpp | 190 +++++++++++++----- .../src/common/legounksavedatawriter.cpp | 25 +-- LEGO1/lego/legoomni/src/entity/legoactor.cpp | 16 +- LEGO1/lego/legoomni/src/entity/legoworld.cpp | 6 +- .../legoomni/src/infocenter/infocenter.cpp | 22 +- .../src/infocenter/infocenterdoor.cpp | 2 +- LEGO1/lego/legoomni/src/isle/historybook.cpp | 12 +- LEGO1/lego/legoomni/src/isle/isle.cpp | 6 +- .../lego/legoomni/src/isle/jukeboxentity.cpp | 4 +- LEGO1/lego/legoomni/src/main/legoomni.cpp | 12 +- .../lego/legoomni/src/police/policestate.cpp | 2 +- .../src/towtrack/towtrackmissionstate.cpp | 40 ++-- LEGO1/lego/sources/roi/legoroi.cpp | 2 +- LEGO1/lego/sources/roi/legoroi.h | 2 +- 21 files changed, 268 insertions(+), 154 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoactor.h b/LEGO1/lego/legoomni/include/legoactor.h index 114bf4bb..bd24137f 100644 --- a/LEGO1/lego/legoomni/include/legoactor.h +++ b/LEGO1/lego/legoomni/include/legoactor.h @@ -41,16 +41,18 @@ class LegoActor : public LegoEntity { virtual MxFloat VTable0x5c() { return m_unk0x70; } // vtable+0x5c // FUNCTION: LEGO1 0x10002d00 - virtual MxU8 VTable0x60() { return m_unk0x74; } // vtable+0x60 + virtual MxU8 GetActorId() { return m_actorId; } // vtable+0x60 // FUNCTION: LEGO1 0x10002d10 - virtual void VTable0x64(MxU8 p_unk0x74) { m_unk0x74 = p_unk0x74; } // vtable+0x64 + virtual void SetActorId(MxU8 p_actorId) { m_actorId = p_actorId; } // vtable+0x64 + + static const char* GetActorName(MxU8 p_id); private: MxFloat m_unk0x68; // 0x68 LegoCacheSound* m_sound; // 0x6c MxFloat m_unk0x70; // 0x70 - MxU8 m_unk0x74; // 0x74 + MxU8 m_actorId; // 0x74 }; // SYNTHETIC: LEGO1 0x1002d300 diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index d0f64079..68a246b5 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -63,6 +63,7 @@ class LegoEntity : public MxEntity { inline MxU8 GetFlags() { return m_flags; } inline void SetFlags(MxU8 p_flags) { m_flags = p_flags; } + inline void ClearFlag(MxU8 p_flag) { m_flags &= ~p_flag; } protected: void Init(); diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index e4458213..59dc8784 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -88,8 +88,10 @@ class LegoGameState { }; // SIZE 0x0c - struct ScoreName { - ScoreName* operator=(const ScoreName* p_other); + struct Username { + Username(); + MxResult ReadWrite(LegoStorage* p_storage); + Username* operator=(const Username* p_other); MxS16 m_letters[7]; // 0x00 }; @@ -97,13 +99,14 @@ class LegoGameState { // SIZE 0x2c struct ScoreItem { undefined2 m_unk0x00; // 0x00 - MxU8 m_state[25]; // 0x02 - ScoreName m_name; // 0x1c + MxU8 m_state[5][5]; // 0x02 + Username m_name; // 0x1c undefined2 m_unk0x2a; // 0x2a }; // SIZE 0x372 - struct Scores { + struct History { + History(); void WriteScoreHistory(); void FUN_1003ccf0(LegoFile&); @@ -111,6 +114,7 @@ class LegoGameState { MxS16 m_count; // 0x00 ScoreItem m_scores[20]; // 0x02 + undefined2 m_unk0x372; // 0x372 }; LegoGameState(); @@ -129,47 +133,49 @@ class LegoGameState { void StopArea(Area p_area); void SwitchArea(Area p_area); - inline MxU8 GetUnknownC() { return m_unk0x0c; } + inline MxU8 GetActorId() { return m_actorId; } inline Act GetCurrentAct() { return m_currentAct; } inline Act GetLoadedAct() { return m_loadedAct; } inline Area GetCurrentArea() { return m_currentArea; } inline Area GetPreviousArea() { return m_previousArea; } inline MxU32 GetUnknown0x41c() { return m_unk0x41c; } inline Area GetUnknown0x42c() { return m_unk0x42c; } - inline Scores* GetScores() { return &m_unk0xa6; } + inline History* GetHistory() { return &m_history; } inline void SetDirty(MxBool p_dirty) { m_isDirty = p_dirty; } inline void SetCurrentArea(Area p_currentArea) { m_currentArea = p_currentArea; } inline void SetPreviousArea(Area p_previousArea) { m_previousArea = p_previousArea; } - inline void SetUnknown0x0c(MxU8 p_unk0x0c) { m_unk0x0c = p_unk0x0c; } + inline void SetActorId(MxU8 p_actorId) { m_actorId = p_actorId; } inline void SetUnknown0x41c(undefined4 p_unk0x41c) { m_unk0x41c = p_unk0x41c; } inline void SetUnknown0x42c(Area p_unk0x42c) { m_unk0x42c = p_unk0x42c; } void SetCurrentAct(Act p_currentAct); void FindLoadedAct(); - void FUN_10039780(MxU8); + void SetActor(MxU8 p_actorId); void FUN_10039940(); private: void RegisterState(LegoState* p_state); - MxResult WriteVariable(LegoStorage* p_stream, MxVariableTable* p_from, const char* p_variableName); - MxResult WriteEndOfVariables(LegoStorage* p_stream); - MxS32 ReadVariable(LegoStorage* p_stream, MxVariableTable* p_to); + MxResult WriteVariable(LegoStorage* p_storage, MxVariableTable* p_from, const char* p_variableName); + MxResult WriteEndOfVariables(LegoStorage* p_storage); + MxS32 ReadVariable(LegoStorage* p_storage, MxVariableTable* p_to); + void SetColors(); void SetROIHandlerFunction(); char* m_savePath; // 0x00 MxS16 m_stateCount; // 0x04 LegoState** m_stateArray; // 0x08 - MxU8 m_unk0x0c; // 0x0c + MxU8 m_actorId; // 0x0c Act m_currentAct; // 0x10 Act m_loadedAct; // 0x14 LegoBackgroundColor* m_backgroundColor; // 0x18 LegoBackgroundColor* m_tempBackgroundColor; // 0x1c LegoFullScreenMovie* m_fullScreenMovie; // 0x20 MxU16 m_unk0x24; // 0x24 - undefined m_unk0x26[128]; // 0x26 - Scores m_unk0xa6; // 0xa6 - undefined4 m_unk0x418; // 0x418 + undefined2 m_unk0x26; // 0x26 + Username m_players[9]; // 0x28 + History m_history; // 0xa6 + undefined2 m_unk0x41a; // 0x41a undefined4 m_unk0x41c; // 0x41c MxBool m_isDirty; // 0x420 Area m_currentArea; // 0x424 @@ -179,4 +185,7 @@ class LegoGameState { MxBool ROIHandlerFunction(char* p_input, char* p_output, MxU32 p_copyLen); +// SYNTHETIC: LEGO1 0x1003c860 +// LegoGameState::ScoreItem::ScoreItem + #endif // LEGOGAMESTATE_H diff --git a/LEGO1/lego/legoomni/include/legoomni.h b/LEGO1/lego/legoomni/include/legoomni.h index c66df6fc..19324e42 100644 --- a/LEGO1/lego/legoomni/include/legoomni.h +++ b/LEGO1/lego/legoomni/include/legoomni.h @@ -216,7 +216,7 @@ class LegoOmni : public MxOmni { ViewLODListManager* GetViewLODListManager() { return m_viewLODListManager; } LegoWorld* GetCurrentWorld() { return m_currentWorld; } LegoNavController* GetNavController() { return m_navController; } - IslePathActor* GetCurrentVehicle() { return m_currentVehicle; } + IslePathActor* GetCurrentActor() { return m_currentActor; } LegoPlantManager* GetLegoPlantManager() { return m_plantManager; } LegoAnimationManager* GetAnimationManager() { return m_animationManager; } LegoBuildingManager* GetLegoBuildingManager() { return m_buildingManager; } @@ -228,6 +228,7 @@ class LegoOmni : public MxOmni { LegoWorldList* GetWorldList() { return m_worldList; } inline void SetNavController(LegoNavController* p_navController) { m_navController = p_navController; } + inline void SetCurrentActor(IslePathActor* p_currentActor) { m_currentActor = p_currentActor; } inline void SetCurrentWorld(LegoWorld* p_currentWorld) { m_currentWorld = p_currentWorld; } inline void SetExit(MxBool p_exit) { m_exit = p_exit; } @@ -245,7 +246,7 @@ class LegoOmni : public MxOmni { LegoWorld* m_currentWorld; // 0x7c MxBool m_exit; // 0x80 LegoNavController* m_navController; // 0x84 - IslePathActor* m_currentVehicle; // 0x88 + IslePathActor* m_currentActor; // 0x88 LegoUnkSaveDataWriter* m_saveDataWriter; // 0x8c LegoPlantManager* m_plantManager; // 0x90 LegoAnimationManager* m_animationManager; // 0x94 @@ -271,7 +272,7 @@ LegoAnimationManager* AnimationManager(); LegoNavController* NavController(); LegoBuildingManager* BuildingManager(); LegoControlManager* ControlManager(); -IslePathActor* CurrentVehicle(); +IslePathActor* CurrentActor(); ViewManager* GetViewManager(); LegoPlantManager* PlantManager(); LegoWorld* CurrentWorld(); @@ -280,6 +281,7 @@ LegoTextureContainer* TextureContainer(); ViewLODListManager* GetViewLODListManager(); void FUN_10015820(MxBool p_disable, MxU16 p_flags); void SetROIUnknown0x0c(const char* p_name, undefined p_unk0x0c); +void SetCurrentActor(IslePathActor* p_currentActor); LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid); LegoROI* FindROI(const char* p_name); MxDSAction& GetCurrentAction(); diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index c2a2026c..15cbce4c 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -65,13 +65,18 @@ class LegoPathActor : public LegoActor { // FUNCTION: LEGO1 0x10002de0 virtual void VTable0xc8(MxU8 p_unk0x148) { m_unk0x148 = p_unk0x148; } // vtable+0xc8 + inline MxU32 GetUnknown88() { return m_unk0x88; } + + inline void SetUnknown88(MxU32 p_unk0x88) { m_unk0x88 = p_unk0x88; } inline void SetUnknownDC(MxU32 p_unk0xdc) { m_unk0xdc = p_unk0xdc; } // SYNTHETIC: LEGO1 0x1002d800 // LegoPathActor::`scalar deleting destructor' protected: - undefined m_unk0x78[0x64]; // 0x78 + undefined m_unk0x78[0x10]; // 0x78 + MxU32 m_unk0x88; // 0x88 + undefined m_unk0x8c[0x50]; // 0x8c MxU32 m_unk0xdc; // 0xdc undefined m_unk0xe0[0xa]; // 0xe0 MxU8 m_unk0xea; // 0xea diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index 7dd38998..deea67b0 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -55,8 +55,8 @@ class LegoUnkSaveDataWriter { public: LegoUnkSaveDataWriter(); - MxResult WriteSaveData3(LegoStorage* p_stream); - LegoROI* FUN_10083500(char*, MxBool); + MxResult WriteSaveData3(LegoStorage* p_storage); + LegoROI* FUN_10083500(const char*, MxBool); static void InitSaveData(); static void SetCustomizeAnimFile(const char* p_value); diff --git a/LEGO1/lego/legoomni/src/build/helicopter.cpp b/LEGO1/lego/legoomni/src/build/helicopter.cpp index d4888773..c4d610a6 100644 --- a/LEGO1/lego/legoomni/src/build/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/build/helicopter.cpp @@ -67,9 +67,9 @@ void Helicopter::VTable0xe4() if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { GameState()->SetCurrentArea(LegoGameState::e_unk60); - if (CurrentVehicle()) { - if (CurrentVehicle()->IsA("IslePathActor")) { - ((IslePathActor*) CurrentVehicle())->VTable0xe8(0x37, TRUE, 7); + if (CurrentActor()) { + if (CurrentActor()->IsA("IslePathActor")) { + ((IslePathActor*) CurrentActor())->VTable0xe8(0x37, TRUE, 7); } } } @@ -102,9 +102,9 @@ MxU32 Helicopter::VTable0xcc() AnimationManager()->FUN_1005f6d0(FALSE); - if (CurrentVehicle()) { - if (CurrentVehicle()->VTable0x60() != GameState()->GetUnknownC()) { - CurrentVehicle()->VTable0xe4(); + if (CurrentActor()) { + if (CurrentActor()->GetActorId() != GameState()->GetActorId()) { + CurrentActor()->VTable0xe4(); } } diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 0c43d19e..9f1c6482 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -8,6 +8,7 @@ #include "legonavcontroller.h" #include "legoomni.h" #include "legostate.h" +#include "legounksavedatawriter.h" #include "legoutil.h" #include "legovideomanager.h" #include "legoworld.h" @@ -19,9 +20,9 @@ #include -DECOMP_SIZE_ASSERT(LegoGameState::ScoreName, 0xe) +DECOMP_SIZE_ASSERT(LegoGameState::Username, 0xe) DECOMP_SIZE_ASSERT(LegoGameState::ScoreItem, 0x2c) -DECOMP_SIZE_ASSERT(LegoGameState::Scores, 0x372) +DECOMP_SIZE_ASSERT(LegoGameState::History, 0x374) DECOMP_SIZE_ASSERT(LegoGameState, 0x430) // GLOBAL: LEGO1 0x100f3e40 @@ -45,21 +46,28 @@ const char* g_endOfVariables = "END_OF_VARIABLES"; // GLOBAL: LEGO1 0x100f3e58 ColorStringStruct g_colorSaveData[43] = { - {"c_dbbkfny0", "lego red"}, {"c_dbbkxly0", "lego white"}, {"c_chbasey0", "lego black"}, - {"c_chbacky0", "lego black"}, {"c_chdishy0", "lego white"}, {"c_chhorny0", "lego black"}, - {"c_chljety1", "lego black"}, {"c_chrjety1", "lego black"}, {"c_chmidly0", "lego black"}, - {"c_chmotry0", "lego blue"}, {"c_chsidly0", "lego black"}, {"c_chsidry0", "lego black"}, - {"c_chstuty0", "lego black"}, {"c_chtaily0", "lego black"}, {"c_chwindy1", "lego black"}, - {"c_dbfbrdy0", "lego red"}, {"c_dbflagy0", "lego yellow"}, {"c_dbfrfny4", "lego red"}, - {"c_dbfrxly0", "lego white"}, {"c_dbhndly0", "lego white"}, {"c_dbltbry0", "lego white"}, - {"c_jsdashy0", "lego white"}, {"c_jsexhy0", "lego black"}, {"c_jsfrnty5", "lego black"}, - {"c_jshndly0", "lego red"}, {"c_jslsidy0", "lego black"}, {"c_jsrsidy0", "lego black"}, - {"c_jsskiby0", "lego red"}, {"c_jswnshy5", "lego white"}, {"c_rcbacky6", "lego green"}, - {"c_rcedgey0", "lego green"}, {"c_rcfrmey0", "lego red"}, {"c_rcfrnty6", "lego green"}, - {"c_rcmotry0", "lego white"}, {"c_rcsidey0", "lego green"}, {"c_rcstery0", "lego white"}, - {"c_rcstrpy0", "lego yellow"}, {"c_rctailya", "lego white"}, {"c_rcwhl1y0", "lego white"}, - {"c_rcwhl2y0", "lego white"}, {"c_jsbasey0", "lego white"}, {"c_chblady0", "lego black"}, - {"c_chseaty0", "lego white"}, + {"c_dbbkfny0", "lego red"}, {"c_dbbkxly0", "lego white"}, // dunebuggy back fender, dunebuggy back axle + {"c_chbasey0", "lego black"}, {"c_chbacky0", "lego black"}, // copter base, copter back + {"c_chdishy0", "lego white"}, {"c_chhorny0", "lego black"}, // copter dish, copter horn + {"c_chljety1", "lego black"}, {"c_chrjety1", "lego black"}, // copter left jet, copter right jet + {"c_chmidly0", "lego black"}, {"c_chmotry0", "lego blue"}, // copter middle, copter motor + {"c_chsidly0", "lego black"}, {"c_chsidry0", "lego black"}, // copter side left, copter side right + {"c_chstuty0", "lego black"}, {"c_chtaily0", "lego black"}, // copter ???, copter tail + {"c_chwindy1", "lego black"}, {"c_dbfbrdy0", "lego red"}, // copter ???, dunebuggy ??? + {"c_dbflagy0", "lego yellow"}, {"c_dbfrfny4", "lego red"}, // dunebuggy flag, dunebuggy front fender + {"c_dbfrxly0", "lego white"}, {"c_dbhndly0", "lego white"}, // dunebuggy front axle, dunebuggy handlebar + {"c_dbltbry0", "lego white"}, {"c_jsdashy0", "lego white"}, // dunebuggy ???, jetski dash + {"c_jsexhy0", "lego black"}, {"c_jsfrnty5", "lego black"}, // jetski exhaust, jetski front + {"c_jshndly0", "lego red"}, {"c_jslsidy0", "lego black"}, // jetski handlebar, jetski left side + {"c_jsrsidy0", "lego black"}, {"c_jsskiby0", "lego red"}, // jetski right side, jetski ??? + {"c_jswnshy5", "lego white"}, {"c_rcbacky6", "lego green"}, // jetski windshield, racecar back + {"c_rcedgey0", "lego green"}, {"c_rcfrmey0", "lego red"}, // racecar edge, racecar frame + {"c_rcfrnty6", "lego green"}, {"c_rcmotry0", "lego white"}, // racecar front, racecar motor + {"c_rcsidey0", "lego green"}, {"c_rcstery0", "lego white"}, // racecar side, racecar steering wheel + {"c_rcstrpy0", "lego yellow"}, {"c_rctailya", "lego white"}, // racecar stripe, racecar tail + {"c_rcwhl1y0", "lego white"}, {"c_rcwhl2y0", "lego white"}, // racecar wheels 1, racecar wheels 2 + {"c_jsbasey0", "lego white"}, {"c_chblady0", "lego black"}, // jetski base, copter blades + {"c_chseaty0", "lego white"}, // copter seat }; // NOTE: This offset = the end of the variables table, the last entry @@ -69,22 +77,26 @@ extern const char* g_endOfVariables; // FUNCTION: LEGO1 0x10039550 LegoGameState::LegoGameState() { - // TODO + SetColors(); SetROIHandlerFunction(); - this->m_stateCount = 0; - this->m_unk0x0c = 0; - this->m_savePath = NULL; - this->m_currentArea = e_noArea; - this->m_previousArea = e_noArea; - this->m_unk0x42c = e_noArea; - this->m_isDirty = FALSE; - this->m_loadedAct = e_actNotFound; + m_stateCount = 0; + m_actorId = 0; + m_savePath = NULL; + m_stateArray = NULL; + m_unk0x41c = -1; + m_currentArea = e_noArea; + m_previousArea = e_noArea; + m_unk0x42c = e_noArea; + m_unk0x26 = 0; + m_isDirty = FALSE; + m_loadedAct = e_actNotFound; + SetCurrentAct(e_act1); m_backgroundColor = new LegoBackgroundColor("backgroundcolor", "set 56 54 68"); VariableTable()->SetVariable(m_backgroundColor); - m_tempBackgroundColor = new LegoBackgroundColor("tempBackgroundcolor", "set 56 54 68"); + m_tempBackgroundColor = new LegoBackgroundColor("tempBackgroundColor", "set 56 54 68"); VariableTable()->SetVariable(m_tempBackgroundColor); m_fullScreenMovie = new LegoFullScreenMovie("fsmovie", "disable"); @@ -113,10 +125,35 @@ LegoGameState::~LegoGameState() delete[] m_savePath; } -// STUB: LEGO1 0x10039780 -void LegoGameState::FUN_10039780(MxU8) +// FUNCTION: LEGO1 0x10039780 +void LegoGameState::SetActor(MxU8 p_actorId) { - // TODO + if (p_actorId) { + m_actorId = p_actorId; + } + + IslePathActor* oldActor = CurrentActor(); + SetCurrentActor(NULL); + + IslePathActor* newActor = new IslePathActor(); + const char* actorName = LegoActor::GetActorName(m_actorId); + LegoROI* roi = UnkSaveDataWriter()->FUN_10083500(actorName, FALSE); + MxDSAction action; + + action.SetAtomId(*g_isleScript); + action.SetObjectId(100000); + newActor->Create(action); + newActor->SetActorId(p_actorId); + newActor->SetROI(roi, FALSE, FALSE); + + if (oldActor) { + newActor->GetROI()->FUN_100a58f0(oldActor->GetROI()->GetLocal2World()); + newActor->SetUnknown88(oldActor->GetUnknown88()); + delete oldActor; + } + + newActor->ClearFlag(0x02); + SetCurrentActor(newActor); } // STUB: LEGO1 0x10039940 @@ -145,7 +182,7 @@ MxResult LegoGameState::Save(MxULong p_slot) fileStream.Write(&maybeVersion, 4); fileStream.Write(&m_unk0x24, 2); fileStream.Write(&m_currentAct, 2); - fileStream.Write(&m_unk0x0c, 1); + fileStream.Write(&m_actorId, 1); for (MxS32 i = 0; i < sizeof(g_colorSaveData) / sizeof(g_colorSaveData[0]); ++i) { if (WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) { @@ -190,55 +227,58 @@ void LegoGameState::SetSavePath(char* p_savePath) } // FUNCTION: LEGO1 0x10039f70 -MxResult LegoGameState::WriteVariable(LegoStorage* p_stream, MxVariableTable* p_from, const char* p_variableName) +MxResult LegoGameState::WriteVariable(LegoStorage* p_storage, MxVariableTable* p_from, const char* p_variableName) { MxResult result = FAILURE; const char* variableValue = p_from->GetVariable(p_variableName); if (variableValue) { MxU8 length = strlen(p_variableName); - if (p_stream->Write((char*) &length, 1) == SUCCESS) { - if (p_stream->Write(p_variableName, length) == SUCCESS) { + if (p_storage->Write((char*) &length, 1) == SUCCESS) { + if (p_storage->Write(p_variableName, length) == SUCCESS) { length = strlen(variableValue); - if (p_stream->Write((char*) &length, 1) == SUCCESS) { - result = p_stream->Write((char*) variableValue, length); + if (p_storage->Write((char*) &length, 1) == SUCCESS) { + result = p_storage->Write((char*) variableValue, length); } } } } + return result; } // FUNCTION: LEGO1 0x1003a020 -MxResult LegoGameState::WriteEndOfVariables(LegoStorage* p_stream) +MxResult LegoGameState::WriteEndOfVariables(LegoStorage* p_storage) { MxU8 len = strlen(g_endOfVariables); - if (p_stream->Write(&len, 1) == SUCCESS) { - return p_stream->Write(g_endOfVariables, len); + + if (p_storage->Write(&len, 1) == SUCCESS) { + return p_storage->Write(g_endOfVariables, len); } + return FAILURE; } // 95% match, just some instruction ordering differences on the call to // MxVariableTable::SetVariable at the end. // FUNCTION: LEGO1 0x1003a080 -MxS32 LegoGameState::ReadVariable(LegoStorage* p_stream, MxVariableTable* p_to) +MxS32 LegoGameState::ReadVariable(LegoStorage* p_storage, MxVariableTable* p_to) { MxS32 result = 1; MxU8 length; - if (p_stream->Read((char*) &length, 1) == SUCCESS) { + if (p_storage->Read((char*) &length, 1) == SUCCESS) { char nameBuffer[256]; - if (p_stream->Read(nameBuffer, length) == SUCCESS) { + if (p_storage->Read(nameBuffer, length) == SUCCESS) { nameBuffer[length] = '\0'; if (strcmp(nameBuffer, g_endOfVariables) == 0) { // 2 -> "This was the last entry, done reading." result = 2; } else { - if (p_stream->Read((char*) &length, 1) == SUCCESS) { + if (p_storage->Read((char*) &length, 1) == SUCCESS) { char valueBuffer[256]; - if (p_stream->Read(valueBuffer, length) == SUCCESS) { + if (p_storage->Read(valueBuffer, length) == SUCCESS) { result = 0; valueBuffer[length] = '\0'; p_to->SetVariable(nameBuffer, valueBuffer); @@ -247,6 +287,7 @@ MxS32 LegoGameState::ReadVariable(LegoStorage* p_stream, MxVariableTable* p_to) } } } + return result; } @@ -559,7 +600,7 @@ void LegoGameState::SwitchArea(Area p_area) case e_garadoor: LoadIsle(); VariableTable()->SetVariable("VISIBILITY", "Hide Gas"); - CurrentVehicle()->ResetWorldTransform(FALSE); + CurrentActor()->ResetWorldTransform(FALSE); NavController()->SetLocation(0x3b); VideoManager()->Get3DManager()->SetFrustrum(90, 0.1f, 250.0f); InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1160, NULL); @@ -572,10 +613,10 @@ void LegoGameState::SwitchArea(Area p_area) } else { SetCameraControllerFromIsle(); - CurrentVehicle()->ResetWorldTransform(TRUE); + CurrentActor()->ResetWorldTransform(TRUE); AnimationManager()->FUN_1005f0b0(); } - CurrentVehicle()->VTable0xe8(p_area, TRUE, 7); + CurrentActor()->VTable0xe8(p_area, TRUE, 7); break; } case e_hospital: @@ -585,9 +626,9 @@ void LegoGameState::SwitchArea(Area p_area) case e_unk33: LoadIsle(); SetCameraControllerFromIsle(); - CurrentVehicle()->ResetWorldTransform(TRUE); + CurrentActor()->ResetWorldTransform(TRUE); AnimationManager()->FUN_1005f0b0(); - CurrentVehicle()->VTable0xe8(p_area, TRUE, 7); + CurrentActor()->VTable0xe8(p_area, TRUE, 7); break; case e_police: VideoManager()->SetUnk0x554(TRUE); @@ -649,6 +690,16 @@ void LegoGameState::SwitchArea(Area p_area) } } +// FUNCTION: LEGO1 0x1003ba90 +void LegoGameState::SetColors() +{ + MxVariableTable* variableTable = VariableTable(); + + for (MxS32 i = 0; i < _countof(g_colorSaveData); i++) { + variableTable->SetVariable(g_colorSaveData[i].m_targetName, g_colorSaveData[i].m_colorName); + } +} + // FUNCTION: LEGO1 0x1003bac0 void LegoGameState::SetROIHandlerFunction() { @@ -725,21 +776,52 @@ void LegoGameState::RegisterState(LegoState* p_state) m_stateArray[targetIndex] = p_state; } +// FUNCTION: LEGO1 0x1003c670 +LegoGameState::Username::Username() +{ + memset(m_letters, -1, sizeof(m_letters)); +} + +// FUNCTION: LEGO1 0x1003c690 +MxResult LegoGameState::Username::ReadWrite(LegoStorage* p_storage) +{ + if (p_storage->IsReadMode()) { + for (MxS16 i = 0; i < 7; i++) { + p_storage->Read(&m_letters[i], sizeof(m_letters[i])); + } + } + else if (p_storage->IsWriteMode()) { + for (MxS16 i = 0; i < 7; i++) { + MxS16 letter = m_letters[i]; + p_storage->Write(&letter, sizeof(letter)); + } + } + + return SUCCESS; +} + // FUNCTION: LEGO1 0x1003c710 -LegoGameState::ScoreName* LegoGameState::ScoreName::operator=(const ScoreName* p_other) +LegoGameState::Username* LegoGameState::Username::operator=(const Username* p_other) { memcpy(m_letters, p_other->m_letters, sizeof(m_letters)); return this; } +// FUNCTION: LEGO1 0x1003c830 +LegoGameState::History::History() +{ + m_count = 0; + m_unk0x372 = 0; +} + // STUB: LEGO1 0x1003c870 -void LegoGameState::Scores::WriteScoreHistory() +void LegoGameState::History::WriteScoreHistory() { // TODO } // STUB: LEGO1 0x1003ccf0 -void LegoGameState::Scores::FUN_1003ccf0(LegoFile&) +void LegoGameState::History::FUN_1003ccf0(LegoFile&) { // TODO } @@ -753,11 +835,11 @@ void LegoGameState::SerializeScoreHistory(MxS16 p_flags) savePath += g_historyGSI; if (p_flags == LegoFile::c_write) { - m_unk0xa6.WriteScoreHistory(); + m_history.WriteScoreHistory(); } if (stream.Open(savePath.GetData(), p_flags) == SUCCESS) { - m_unk0xa6.FUN_1003ccf0(stream); + m_history.FUN_1003ccf0(stream); } } diff --git a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp index 2fdc658c..52c57f71 100644 --- a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp +++ b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp @@ -41,7 +41,7 @@ void LegoUnkSaveDataWriter::FUN_100832a0() } // FUNCTION: LEGO1 0x10083310 -MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStorage* p_stream) +MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStorage* p_storage) { MxResult result = FAILURE; @@ -51,34 +51,34 @@ MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStorage* p_stream) const LegoSaveDataEntry3* end = &g_saveData3[66]; while (TRUE) { - if (p_stream->Write(&entry->m_savePart1, 4) != SUCCESS) { + if (p_storage->Write(&entry->m_savePart1, 4) != SUCCESS) { break; } - if (p_stream->Write(&entry->m_savePart2, 4) != SUCCESS) { + if (p_storage->Write(&entry->m_savePart2, 4) != SUCCESS) { break; } - if (p_stream->Write(&entry->m_savePart3, 1) != SUCCESS) { + if (p_storage->Write(&entry->m_savePart3, 1) != SUCCESS) { break; } - if (p_stream->Write(&entry->m_currentFrame, 1) != SUCCESS) { + if (p_storage->Write(&entry->m_currentFrame, 1) != SUCCESS) { break; } - if (p_stream->Write(&entry->m_savePart5, 1) != SUCCESS) { + if (p_storage->Write(&entry->m_savePart5, 1) != SUCCESS) { break; } - if (p_stream->Write(&entry->m_savePart6, 1) != SUCCESS) { + if (p_storage->Write(&entry->m_savePart6, 1) != SUCCESS) { break; } - if (p_stream->Write(&entry->m_savePart7, 1) != SUCCESS) { + if (p_storage->Write(&entry->m_savePart7, 1) != SUCCESS) { break; } - if (p_stream->Write(&entry->m_savePart8, 1) != SUCCESS) { + if (p_storage->Write(&entry->m_savePart8, 1) != SUCCESS) { break; } - if (p_stream->Write(&entry->m_savePart9, 1) != SUCCESS) { + if (p_storage->Write(&entry->m_savePart9, 1) != SUCCESS) { break; } - if (p_stream->Write(&entry->m_savePart10, 1) != SUCCESS) { + if (p_storage->Write(&entry->m_savePart10, 1) != SUCCESS) { break; } if (++entry >= end) { @@ -86,11 +86,12 @@ MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStorage* p_stream) break; } } + return result; } // STUB: LEGO1 0x10083500 -LegoROI* LegoUnkSaveDataWriter::FUN_10083500(char* p_key, MxBool p_option) +LegoROI* LegoUnkSaveDataWriter::FUN_10083500(const char* p_key, MxBool p_option) { // TODO // involves an STL map with a _Nil node at 0x100fc508 diff --git a/LEGO1/lego/legoomni/src/entity/legoactor.cpp b/LEGO1/lego/legoomni/src/entity/legoactor.cpp index 4fc0daa2..8932217e 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -3,7 +3,7 @@ DECOMP_SIZE_ASSERT(LegoActor, 0x78) // GLOBAL: LEGO1 0x100f32d0 -const char* g_unk0x100f32d0[] = {"none", "pepper", "mama", "papa", "nick", "laura", "The_Brickster!"}; +const char* g_actorNames[] = {"none", "pepper", "mama", "papa", "nick", "laura", "The_Brickster!"}; // FUNCTION: LEGO1 0x1002d110 LegoActor::LegoActor() @@ -12,7 +12,7 @@ LegoActor::LegoActor() m_sound = NULL; m_unk0x70 = 0.0f; m_unk0x10 = 0; - m_unk0x74 = 0; + m_actorId = 0; } // FUNCTION: LEGO1 0x1002d320 @@ -29,16 +29,22 @@ void LegoActor::ParseAction(char*) // TODO } +// FUNCTION: LEGO1 0x1002d660 +const char* LegoActor::GetActorName(MxU8 p_id) +{ + return g_actorNames[p_id]; +} + // FUNCTION: LEGO1 0x1002d670 void LegoActor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) { if (p_roi) { const char* name = p_roi->GetName(); - for (MxU32 i = 1; i <= _countof(g_unk0x100f32d0) - 1; i++) { - if (!strcmpi(name, g_unk0x100f32d0[i])) { + for (MxU32 i = 1; i <= _countof(g_actorNames) - 1; i++) { + if (!strcmpi(name, g_actorNames[i])) { m_unk0x59 = 0; - m_unk0x74 = i; + m_actorId = i; break; } } diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index c1fe9e39..ad66e1cf 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -588,10 +588,10 @@ void LegoWorld::Enable(MxBool p_enable) else if (!p_enable && m_set0xd0.empty()) { MxPresenter* presenter; LegoPathController* controller; - IslePathActor* vehicle = CurrentVehicle(); + IslePathActor* actor = CurrentActor(); - if (vehicle) { - FUN_1001fc80(vehicle); + if (actor) { + FUN_1001fc80(actor); } AnimationManager()->FUN_1005ee80(FALSE); diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp index cef49c68..f69fa761 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -201,7 +201,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) if (!m_unk0x1d4) { PlayMusic(JukeBox::e_informationCenter); - GameState()->FUN_10039780(m_selectedCharacter); + GameState()->SetActor(m_selectedCharacter); switch (m_selectedCharacter) { case e_pepper: @@ -303,7 +303,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) case 5: if (action->GetObjectId() == m_currentInfomainScript) { if (GameState()->GetCurrentAct() != LegoGameState::e_act3 && m_selectedCharacter != e_noCharacter) { - GameState()->FUN_10039780(m_selectedCharacter); + GameState()->SetActor(m_selectedCharacter); } TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); m_infocenterState->SetUnknown0x74(14); @@ -734,7 +734,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) switch (m_mapAreas[m_unk0x1c8].m_unk0x04) { case 3: - GameState()->FUN_10039780(m_selectedCharacter); + GameState()->SetActor(m_selectedCharacter); switch (m_selectedCharacter) { case e_pepper: @@ -810,23 +810,23 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) switch (m_selectedCharacter) { case e_pepper: dialogueToPlay = c_pepperCharacterSelect; - GameState()->SetUnknown0x0c(m_selectedCharacter); + GameState()->SetActorId(m_selectedCharacter); break; case e_mama: dialogueToPlay = c_mamaCharacterSelect; - GameState()->SetUnknown0x0c(m_selectedCharacter); + GameState()->SetActorId(m_selectedCharacter); break; case e_papa: dialogueToPlay = c_papaCharacterSelect; - GameState()->SetUnknown0x0c(m_selectedCharacter); + GameState()->SetActorId(m_selectedCharacter); break; case e_nick: dialogueToPlay = c_nickCharacterSelect; - GameState()->SetUnknown0x0c(m_selectedCharacter); + GameState()->SetActorId(m_selectedCharacter); break; case e_laura: dialogueToPlay = c_lauraCharacterSelect; - GameState()->SetUnknown0x0c(m_selectedCharacter); + GameState()->SetActorId(m_selectedCharacter); break; default: dialogueToPlay = @@ -948,7 +948,7 @@ MxU8 Infocenter::HandleClick(LegoControlManagerEvent& p_param) InputManager()->SetUnknown336(TRUE); break; case LegoGameState::e_unk4: - if (state->GetUnknownC()) { + if (state->GetActorId()) { if (m_infocenterState->HasRegistered()) { m_infocenterState->SetUnknown0x74(5); m_transitionDestination = state->GetPreviousArea(); @@ -1228,7 +1228,7 @@ void Infocenter::UpdateFrameHot(MxBool p_display) if (p_display) { MxS32 x, y; - switch (GameState()->GetUnknownC()) { + switch (GameState()->GetActorId()) { case 1: x = 302; y = 81; @@ -1292,7 +1292,7 @@ void Infocenter::Reset() InitializeBitmaps(); m_selectedCharacter = e_pepper; - GameState()->FUN_10039780(e_pepper); + GameState()->SetActor(e_pepper); HelicopterState* state = (HelicopterState*) GameState()->GetState("HelicopterState"); diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp index 74d1cfdc..2553956b 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp @@ -109,7 +109,7 @@ MxLong InfocenterDoor::HandleClick(LegoControlManagerEvent& p_param) result = 1; break; case 4: - if (GameState()->GetUnknownC()) { + if (GameState()->GetActorId()) { InfocenterState* state = (InfocenterState*) GameState()->GetState("InfocenterState"); if (state->HasRegistered()) { m_unk0xf8 = LegoGameState::e_unk4; diff --git a/LEGO1/lego/legoomni/src/isle/historybook.cpp b/LEGO1/lego/legoomni/src/isle/historybook.cpp index 981d3018..33659bf5 100644 --- a/LEGO1/lego/legoomni/src/isle/historybook.cpp +++ b/LEGO1/lego/legoomni/src/isle/historybook.cpp @@ -80,7 +80,7 @@ inline void SetColor(MxStillPresenter* p_presenter, MxU8 p_color, MxU8* p_colors void HistoryBook::ReadyWorld() { LegoWorld::ReadyWorld(); - GameState()->GetScores()->WriteScoreHistory(); + GameState()->GetHistory()->WriteScoreHistory(); char bitmap[] = "A_Bitmap"; for (MxS16 i = 0; i < 26; i++) { @@ -93,8 +93,8 @@ void HistoryBook::ReadyWorld() {0x76, 0x4c, 0x38}; // yellow - #FFB900, blue - #00548C, red - #CB1220, background - #CECECE, border - #74818B MxS32 scoreY = 0x79; - for (MxS16 scoreIndex = 0; scoreIndex < GameState()->GetScores()->m_count; scoreIndex++) { - LegoGameState::ScoreItem* score = GameState()->GetScores()->GetScore(scoreIndex); + for (MxS16 scoreIndex = 0; scoreIndex < GameState()->GetHistory()->m_count; scoreIndex++) { + LegoGameState::ScoreItem* score = GameState()->GetHistory()->GetScore(scoreIndex); MxStillPresenter** scorebox = &m_scores[scoreIndex]; *scorebox = scoreboxMaster->Clone(); @@ -110,14 +110,14 @@ void HistoryBook::ReadyWorld() MxS32 scoreboxX = 1; MxS32 scoreboxRow = 5; - MxU8* scoreState = score->m_state; + MxS32 scoreState = 0; for (; scoreboxRow > 0; scoreboxRow--) { for (MxS32 scoreBoxColumn = 0, scoreboxY = 1; scoreBoxColumn < 5; scoreBoxColumn++, scoreboxY += 5) { - SetColor(*scorebox, scoreState[scoreBoxColumn], scoreColors, scoreboxX, scoreboxY); + SetColor(*scorebox, score->m_state[scoreState][scoreBoxColumn], scoreColors, scoreboxX, scoreboxY); } - scoreState += 5; + scoreState++; scoreboxX += 5; } diff --git a/LEGO1/lego/legoomni/src/isle/isle.cpp b/LEGO1/lego/legoomni/src/isle/isle.cpp index 1f2085c2..bf3f912d 100644 --- a/LEGO1/lego/legoomni/src/isle/isle.cpp +++ b/LEGO1/lego/legoomni/src/isle/isle.cpp @@ -46,8 +46,8 @@ Isle::~Isle() InputManager()->ClearWorld(); } - if (CurrentVehicle() != NULL) { - VTable0x6c(CurrentVehicle()); + if (CurrentActor() != NULL) { + VTable0x6c(CurrentActor()); } NotificationManager()->Unregister(this); @@ -121,7 +121,7 @@ MxLong Isle::Notify(MxParam& p_param) case c_notificationType18: switch (m_act1state->GetUnknown18()) { case 4: - result = CurrentVehicle()->Notify(p_param); + result = CurrentActor()->Notify(p_param); break; case 8: result = m_towtrack->Notify(p_param); diff --git a/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp b/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp index 47d81510..1fed8533 100644 --- a/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp +++ b/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp @@ -29,8 +29,8 @@ MxLong JukeBoxEntity::Notify(MxParam& p_param) return 1; } - if (CurrentVehicle()->VTable0x60() != GameState()->GetUnknownC()) { - CurrentVehicle()->VTable0xe4(); + if (CurrentActor()->GetActorId() != GameState()->GetActorId()) { + CurrentActor()->VTable0xe4(); } ((Isle*) FindWorld(*g_isleScript, 0))->SetUnknown13c(0x35); diff --git a/LEGO1/lego/legoomni/src/main/legoomni.cpp b/LEGO1/lego/legoomni/src/main/legoomni.cpp index f0081e2c..1da15cee 100644 --- a/LEGO1/lego/legoomni/src/main/legoomni.cpp +++ b/LEGO1/lego/legoomni/src/main/legoomni.cpp @@ -179,9 +179,9 @@ LegoNavController* NavController() } // FUNCTION: LEGO1 0x10015790 -IslePathActor* CurrentVehicle() +IslePathActor* CurrentActor() { - return LegoOmni::GetInstance()->GetCurrentVehicle(); + return LegoOmni::GetInstance()->GetCurrentActor(); } // FUNCTION: LEGO1 0x100157a0 @@ -248,6 +248,12 @@ void SetROIUnknown0x0c(const char* p_name, undefined p_unk0x0c) } } +// FUNCTION: LEGO1 0x10015880 +void SetCurrentActor(IslePathActor* p_currentActor) +{ + LegoOmni::GetInstance()->SetCurrentActor(p_currentActor); +} + // FUNCTION: LEGO1 0x100158c0 LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid) { @@ -478,7 +484,7 @@ void LegoOmni::Init() m_worldList = NULL; m_currentWorld = NULL; m_exit = FALSE; - m_currentVehicle = NULL; + m_currentActor = NULL; m_saveDataWriter = NULL; m_plantManager = NULL; m_gameState = NULL; diff --git a/LEGO1/lego/legoomni/src/police/policestate.cpp b/LEGO1/lego/legoomni/src/police/policestate.cpp index 07ef3a55..c1d978e1 100644 --- a/LEGO1/lego/legoomni/src/police/policestate.cpp +++ b/LEGO1/lego/legoomni/src/police/policestate.cpp @@ -44,7 +44,7 @@ void PoliceState::FUN_1005ea40() return; } - switch (CurrentVehicle()->VTable0x60()) { + switch (CurrentActor()->GetActorId()) { case 4: policeScript = Police::PoliceScript::c_lauraAnim; m_policeScript = policeScript; diff --git a/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp b/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp index 9a85e0b6..7378bcb3 100644 --- a/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp +++ b/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp @@ -28,47 +28,47 @@ MxResult TowTrackMissionState::VTable0x1c(LegoFile* p_legoFile) } if (p_legoFile->IsReadMode()) { - p_legoFile->Read(&m_unk0x12, sizeof(MxU16)); - p_legoFile->Read(&m_unk0x14, sizeof(MxU16)); - p_legoFile->Read(&m_unk0x16, sizeof(MxU16)); - p_legoFile->Read(&m_unk0x18, sizeof(MxU16)); - p_legoFile->Read(&m_unk0x1a, sizeof(MxU16)); - p_legoFile->Read(&m_unk0x1c, sizeof(MxU16)); - p_legoFile->Read(&m_color1, sizeof(MxU16)); - p_legoFile->Read(&m_color2, sizeof(MxU16)); - p_legoFile->Read(&m_color3, sizeof(MxU16)); - p_legoFile->Read(&m_color4, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x12, sizeof(m_unk0x12)); + p_legoFile->Read(&m_unk0x14, sizeof(m_unk0x14)); + p_legoFile->Read(&m_unk0x16, sizeof(m_unk0x16)); + p_legoFile->Read(&m_unk0x18, sizeof(m_unk0x18)); + p_legoFile->Read(&m_unk0x1a, sizeof(m_unk0x1a)); + p_legoFile->Read(&m_unk0x1c, sizeof(m_unk0x1c)); + p_legoFile->Read(&m_color1, sizeof(m_color1)); + p_legoFile->Read(&m_color2, sizeof(m_color2)); + p_legoFile->Read(&m_color3, sizeof(m_color3)); + p_legoFile->Read(&m_color4, sizeof(m_color4)); } else if (p_legoFile->IsWriteMode()) { MxU16 write = m_unk0x12; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); write = m_unk0x14; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); write = m_unk0x16; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); write = m_unk0x18; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); write = m_unk0x1a; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); write = m_unk0x1c; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); write = m_color1; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); write = m_color2; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); write = m_color3; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); write = m_color4; - p_legoFile->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(m_unk0x12)); } return SUCCESS; diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index 3463022e..9086b286 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -50,7 +50,7 @@ void LegoROI::FUN_100a46b0(Matrix4& p_transform) } // STUB: LEGO1 0x100a58f0 -void LegoROI::FUN_100a58f0(Matrix4& p_transform) +void LegoROI::FUN_100a58f0(const Matrix4& p_transform) { } diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index ab2b45d1..c84f3eba 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -46,7 +46,7 @@ class LegoROI : public ViewROI { void WrappedSetLocalTransform(Matrix4& p_transform); void FUN_100a46b0(Matrix4& p_transform); - void FUN_100a58f0(Matrix4& p_transform); + void FUN_100a58f0(const Matrix4& p_transform); inline const char* GetName() const { return m_name; } inline LegoEntity* GetUnknown0x104() { return m_unk0x104; } From e6c347b8ab4901bbc9331fcc6bd48a0c4d81bc51 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 26 Feb 2024 12:41:18 -0500 Subject: [PATCH 08/14] Implement/match LegoAnimPresenter::FUN_100697c0 (#597) * Implement/match LegoAnimPresenter::FUN_100697c0 * Use LegoU32 --- .../lego/legoomni/include/legoanimpresenter.h | 2 +- .../legoomni/src/video/legoanimpresenter.cpp | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 9d1a6416..3e2f98f4 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -51,7 +51,7 @@ class LegoAnimPresenter : public MxVideoPresenter { LegoChar* FUN_10069150(const LegoChar*); void FUN_100692b0(); void FUN_100695c0(); - LegoChar* FUN_100697c0(const LegoChar*, LegoChar*); + LegoChar* FUN_100697c0(const LegoChar* p_und1, const LegoChar* p_und2); LegoBool FUN_100698b0(CompoundObject&, const LegoChar*); LegoAnim* m_anim; // 0x64 diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 0c04bb25..a98b3b49 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -224,11 +224,31 @@ void LegoAnimPresenter::FUN_100695c0() } } -// STUB: LEGO1 0x100697c0 -LegoChar* LegoAnimPresenter::FUN_100697c0(const LegoChar*, LegoChar*) +// FUNCTION: LEGO1 0x100697c0 +LegoChar* LegoAnimPresenter::FUN_100697c0(const LegoChar* p_und1, const LegoChar* p_und2) { - // TODO - return NULL; + const LegoChar* str = p_und1; + const char* var = VariableTable()->GetVariable(p_und1); + + if (*var) { + str = var; + } + + LegoU32 len = strlen(str) + (p_und2 ? strlen(p_und2) : 0) + 2; + LegoChar* result = new LegoChar[len]; + + if (result != NULL) { + *result = '\0'; + + if (p_und2) { + strcpy(result, p_und2); + strcat(result, ":"); + } + + strcat(result, str); + } + + return result; } // STUB: LEGO1 0x100698b0 From 60161c43b5b49f3676cae03bc030b153bc23c78f Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 26 Feb 2024 13:39:03 -0500 Subject: [PATCH 09/14] Implement/match LegoAnimPresenter::FUN_100698b0 (#598) * Implement/match LegoAnimPresenter::FUN_100698b0 * Use const_iterator --- .../lego/legoomni/include/legoanimpresenter.h | 2 +- LEGO1/lego/legoomni/include/legoroilist.h | 3 ++ .../legoomni/src/video/legoanimpresenter.cpp | 32 ++++++++++++++++--- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 3e2f98f4..ac585d53 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -52,7 +52,7 @@ class LegoAnimPresenter : public MxVideoPresenter { void FUN_100692b0(); void FUN_100695c0(); LegoChar* FUN_100697c0(const LegoChar* p_und1, const LegoChar* p_und2); - LegoBool FUN_100698b0(CompoundObject&, const LegoChar*); + LegoBool FUN_100698b0(const CompoundObject& p_und1, const LegoChar* p_und2); LegoAnim* m_anim; // 0x64 undefined4 m_unk0x68; // 0x68 diff --git a/LEGO1/lego/legoomni/include/legoroilist.h b/LEGO1/lego/legoomni/include/legoroilist.h index fb2cb3f1..3e1239bb 100644 --- a/LEGO1/lego/legoomni/include/legoroilist.h +++ b/LEGO1/lego/legoomni/include/legoroilist.h @@ -51,4 +51,7 @@ class LegoROIList : public MxPtrList { // SYNTHETIC: LEGO1 0x1005f660 // MxPtrList::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x1006ea00 +// MxListEntry::MxListEntry + #endif // LEGOROILIST_H diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index a98b3b49..10cffd9c 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -251,11 +251,35 @@ LegoChar* LegoAnimPresenter::FUN_100697c0(const LegoChar* p_und1, const LegoChar return result; } -// STUB: LEGO1 0x100698b0 -LegoBool LegoAnimPresenter::FUN_100698b0(CompoundObject&, const LegoChar*) +// FUNCTION: LEGO1 0x100698b0 +LegoBool LegoAnimPresenter::FUN_100698b0(const CompoundObject& p_und1, const LegoChar* p_und2) { - // TODO - return FALSE; + LegoBool result = FALSE; + + LegoChar* str; + if (*(str = FUN_100697c0(p_und2, NULL)) == '*') { + LegoChar* tmp = FUN_10069150(str); + delete[] str; + str = tmp; + } + + if (str != NULL && *str != '\0' && p_und1.size() > 0) { + for (CompoundObject::const_iterator it = p_und1.begin(); it != p_und1.end(); it++) { + LegoROI* roi = (LegoROI*) *it; + const char* name = roi->GetName(); + + if (name != NULL) { + if (!strcmpi(name, str)) { + m_unk0x70->Append(roi); + result = TRUE; + break; + } + } + } + } + + delete[] str; + return result; } // STUB: LEGO1 0x1006ad30 From 9d65812c1303e3f69aa8b97f62ed4b0a36d76b2e Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Tue, 27 Feb 2024 10:21:06 +0100 Subject: [PATCH 10/14] cmake: fix isle runtime library + parallel building with ninja (#599) --- CMakeLists.txt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 87e23acb..293c86bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -514,12 +514,12 @@ if (MSVC_FOR_DECOMP) # game was originally built with) and tweaked slightly to produce more debugging info for reccmp. # They ensure a recompilation that can be byte/instruction accurate to the original binaries. if (ISLE_BUILD_APP) - target_compile_options(isle PRIVATE "/MT$<$:d>") target_link_options(isle PRIVATE "/OPT:REF") + set_property(TARGET isle ${lego1_targets} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() # Equivalent to target_compile_options(... PRIVATE "/MT$<$:d>") - set_property(TARGET lego1 ${lego1_targets} PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>) + set_property(TARGET lego1 ${lego1_targets} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") set(CMAKE_CXX_FLAGS "/W3 /GX /D \"WIN32\" /D \"_WINDOWS\"") set(CMAKE_CXX_FLAGS_DEBUG "/Gm /Zi /Od /D \"_DEBUG\"") @@ -545,14 +545,19 @@ if (MSVC_FOR_DECOMP) # Force non-parallel builds of isle and lego1 by putting them in a pool with 1 available job. if (CMAKE_CXX_COMPILER_ID VERSION_LESS 12) foreach(tgt IN LISTS lego1_targets) - set_property(GLOBAL APPEND PROPERTY JOB_POOLS "msvc_${tgt}=1;msvc_lego1=1") - set_property(TARGET ${tgt} PROPERTY JOB_POOL_COMPILE msvc_${tgt}) - set_property(TARGET ${tgt} PROPERTY JOB_POOL_LINK msvc_${tgt}) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS "msvc_${tgt}=1") + set_property(TARGET ${tgt} PROPERTY JOB_POOL_COMPILE "msvc_${tgt}") + set_property(TARGET ${tgt} PROPERTY JOB_POOL_LINK "msvc_${tgt}") endforeach() if (TARGET isle) set_property(GLOBAL APPEND PROPERTY JOB_POOLS "msvc_isle=1") - set_property(TARGET isle PROPERTY JOB_POOL_COMPILE msvc_isle) - set_property(TARGET isle PROPERTY JOB_POOL_LINK msvc_isle) + set_property(TARGET isle PROPERTY JOB_POOL_COMPILE "msvc_isle") + set_property(TARGET isle PROPERTY JOB_POOL_LINK "msvc_isle") + endif() + if (TARGET config) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS "msvc_config=1") + set_property(TARGET config PROPERTY JOB_POOL_COMPILE "msvc_config") + set_property(TARGET config PROPERTY JOB_POOL_LINK "msvc_config") endif() endif() endif() From 68893d67ed0c95e569145519c889da39c31ada19 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 27 Feb 2024 10:13:00 -0500 Subject: [PATCH 11/14] Implement/match LegoAnimPresenter::FUN_10069150 (#600) --- .../lego/legoomni/include/legoanimpresenter.h | 2 +- .../legoomni/include/legounksavedatawriter.h | 1 + .../src/common/legounksavedatawriter.cpp | 7 +++++ .../legoomni/src/video/legoanimpresenter.cpp | 28 ++++++++++++++++--- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index ac585d53..0cf8f2bb 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -48,7 +48,7 @@ class LegoAnimPresenter : public MxVideoPresenter { protected: void Init(); void Destroy(MxBool p_fromDestructor); - LegoChar* FUN_10069150(const LegoChar*); + LegoChar* FUN_10069150(const LegoChar* p_und1); void FUN_100692b0(); void FUN_100695c0(); LegoChar* FUN_100697c0(const LegoChar* p_und1, const LegoChar* p_und2); diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index deea67b0..8013699c 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -60,6 +60,7 @@ class LegoUnkSaveDataWriter { static void InitSaveData(); static void SetCustomizeAnimFile(const char* p_value); + static MxBool FUN_10084c00(const LegoChar*); void FUN_100832a0(); void FUN_10083db0(LegoROI* p_roi); diff --git a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp index 52c57f71..ad3f91c6 100644 --- a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp +++ b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp @@ -110,6 +110,13 @@ void LegoUnkSaveDataWriter::FUN_10083f10(LegoROI* p_roi) // TODO } +// STUB: LEGO1 0x10084c00 +MxBool LegoUnkSaveDataWriter::FUN_10084c00(const LegoChar*) +{ + // TODO + return FALSE; +} + // FUNCTION: LEGO1 0x100851a0 void LegoUnkSaveDataWriter::SetCustomizeAnimFile(const char* p_value) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 10cffd9c..3572137b 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -106,11 +106,31 @@ MxResult LegoAnimPresenter::CreateAnim(MxStreamChunk* p_chunk) return result; } -// STUB: LEGO1 0x10069150 -LegoChar* LegoAnimPresenter::FUN_10069150(const LegoChar*) +// FUNCTION: LEGO1 0x10069150 +LegoChar* LegoAnimPresenter::FUN_10069150(const LegoChar* p_und1) { - // TODO - return NULL; + LegoChar* str; + + if (LegoUnkSaveDataWriter::FUN_10084c00(p_und1 + 1)) { + str = new LegoChar[strlen(p_und1)]; + + if (str != NULL) { + strcpy(str, p_und1 + 1); + } + } + else { + LegoChar buffer[32]; + sprintf(buffer, "%d", m_action->GetUnknown24()); + str = new LegoChar[strlen(p_und1) + strlen(buffer) + strlen(GetActionObjectName()) + 1]; + + if (str != NULL) { + strcpy(str, p_und1); + strcat(str, buffer); + strcat(str, GetActionObjectName()); + } + } + + return str; } // FUNCTION: LEGO1 0x100692b0 From c0a988b0fe1cd2d89ccc29b5e5f805a6fcb47888 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 27 Feb 2024 11:49:31 -0500 Subject: [PATCH 12/14] Implement/match LegoAnimPresenter::StartingTickle (#601) * Implement/match LegoAnimPresenter::StartingTickle * Fix vtable * Fix vtable --- .../legoomni/include/legoanimmmpresenter.h | 2 + .../lego/legoomni/include/legoanimpresenter.h | 24 +++- .../legoomni/include/legohideanimpresenter.h | 2 + .../src/video/legoanimmmpresenter.cpp | 7 + .../legoomni/src/video/legoanimpresenter.cpp | 122 +++++++++++++++++- .../src/video/legohideanimpresenter.cpp | 12 ++ .../src/video/legolocomotionanimpresenter.cpp | 2 +- LEGO1/mxgeometry/mxgeometry3d.h | 2 +- LEGO1/omni/include/mxtimer.h | 5 +- LEGO1/realtime/vector.h | 2 +- 10 files changed, 165 insertions(+), 15 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimmmpresenter.h b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h index c79c8043..56945d8a 100644 --- a/LEGO1/lego/legoomni/include/legoanimmmpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h @@ -36,6 +36,8 @@ class LegoAnimMMPresenter : public MxCompositePresenter { // SYNTHETIC: LEGO1 0x1004aa40 // LegoAnimMMPresenter::`scalar deleting destructor' + + MxBool FUN_1004b8b0(); }; #endif // LEGOANIMMMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 0cf8f2bb..be7beed8 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -13,6 +13,10 @@ class LegoAnimClass; // SIZE 0xc0 class LegoAnimPresenter : public MxVideoPresenter { public: + enum { + c_bit2 = 0x02 + }; + LegoAnimPresenter(); ~LegoAnimPresenter() override; @@ -40,6 +44,15 @@ class LegoAnimPresenter : public MxVideoPresenter { void EndAction() override; // vtable+0x40 void PutFrame() override; // vtable+0x6c virtual MxResult CreateAnim(MxStreamChunk* p_chunk); // vtable+0x88 + virtual void VTable0x8c(); // vtable+0x8c + virtual void VTable0x90(); // vtable+0x90 + virtual void VTable0x94(); // vtable+0x94 + virtual void VTable0x98(); // vtable+0x98 + + // STUB: LEGO1 0x1000c990 + virtual void VTable0x9c() {} // vtable+0x9c + + virtual void VTable0xa0(); // vtable+0xa0 inline LegoAnim* GetAnimation() { return m_anim; } @@ -53,13 +66,18 @@ class LegoAnimPresenter : public MxVideoPresenter { void FUN_100695c0(); LegoChar* FUN_100697c0(const LegoChar* p_und1, const LegoChar* p_und2); LegoBool FUN_100698b0(const CompoundObject& p_und1, const LegoChar* p_und2); + void FUN_10069b10(); + LegoBool FUN_1006aba0(); + LegoBool FUN_1006abb0(LegoTreeNode*, undefined4); + void FUN_1006ac90(); + void FUN_1006c8a0(LegoBool); LegoAnim* m_anim; // 0x64 - undefined4 m_unk0x68; // 0x68 + undefined4* m_unk0x68; // 0x68 undefined4 m_unk0x6c; // 0x6c LegoROIList* m_unk0x70; // 0x70 LegoROIList* m_unk0x74; // 0x74 - undefined4 m_unk0x78; // 0x78 + MxMatrix* m_unk0x78; // 0x78 undefined4 m_unk0x7c; // 0x7c LegoWorld* m_currentWorld; // 0x80 MxAtomId m_animAtom; // 0x84 @@ -68,7 +86,7 @@ class LegoAnimPresenter : public MxVideoPresenter { undefined4 m_unk0x90; // 0x90 undefined m_unk0x94; // 0x94 undefined m_unk0x95; // 0x95 - undefined m_unk0x96; // 0x96 + MxBool m_unk0x96; // 0x96 undefined m_unk0x97; // 0x97 undefined4 m_unk0x98; // 0x98 MxS16 m_unk0x9c; // 0x9c diff --git a/LEGO1/lego/legoomni/include/legohideanimpresenter.h b/LEGO1/lego/legoomni/include/legohideanimpresenter.h index 37b8c475..6c4a9791 100644 --- a/LEGO1/lego/legoomni/include/legohideanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legohideanimpresenter.h @@ -30,6 +30,8 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { void Destroy() override; // vtable+0x38 void EndAction() override; // vtable+0x40 void PutFrame() override; // vtable+0x6c + void VTable0x8c() override; // vtable+0x8c + void VTable0x90() override; // vtable+0x90 private: void Init(); diff --git a/LEGO1/lego/legoomni/src/video/legoanimmmpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimmmpresenter.cpp index 6b5a6040..97c6e230 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimmmpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimmmpresenter.cpp @@ -67,3 +67,10 @@ void LegoAnimMMPresenter::ParseExtra() { // TODO } + +// STUB: LEGO1 0x1004b8b0 +MxBool LegoAnimMMPresenter::FUN_1004b8b0() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 3572137b..0d89365f 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -1,5 +1,6 @@ #include "legoanimpresenter.h" +#include "legoanimmmpresenter.h" #include "legoomni.h" #include "legounksavedatawriter.h" #include "legovideomanager.h" @@ -7,6 +8,7 @@ #include "mxcompositepresenter.h" #include "mxdsanim.h" #include "mxstreamchunk.h" +#include "mxtimer.h" #include "mxvideomanager.h" DECOMP_SIZE_ASSERT(LegoAnimPresenter, 0xc0) @@ -27,11 +29,11 @@ LegoAnimPresenter::~LegoAnimPresenter() void LegoAnimPresenter::Init() { m_anim = NULL; - m_unk0x68 = 0; + m_unk0x68 = NULL; m_unk0x6c = 0; m_unk0x74 = NULL; m_unk0x70 = NULL; - m_unk0x78 = 0; + m_unk0x78 = NULL; m_unk0x7c = 0; m_unk0xa8.Clear(); m_unk0xa4 = 0; @@ -44,7 +46,7 @@ void LegoAnimPresenter::Init() m_unk0x8c = 0; m_unk0x90 = 0; m_unk0x94 = 0; - m_unk0x96 = 1; + m_unk0x96 = TRUE; m_unk0xa0 = 0; } @@ -302,6 +304,31 @@ LegoBool LegoAnimPresenter::FUN_100698b0(const CompoundObject& p_und1, const Leg return result; } +// STUB: LEGO1 0x10069b10 +void LegoAnimPresenter::FUN_10069b10() +{ + // TODO +} + +// FUNCTION: LEGO1 0x1006aba0 +LegoBool LegoAnimPresenter::FUN_1006aba0() +{ + return FUN_1006abb0(m_anim->GetRoot(), 0); +} + +// STUB: LEGO1 0x1006abb0 +LegoBool LegoAnimPresenter::FUN_1006abb0(LegoTreeNode*, undefined4) +{ + // TODO + return FALSE; +} + +// STUB: LEGO1 0x1006ac90 +void LegoAnimPresenter::FUN_1006ac90() +{ + // TODO +} + // STUB: LEGO1 0x1006ad30 void LegoAnimPresenter::PutFrame() { @@ -332,12 +359,57 @@ void LegoAnimPresenter::ReadyTickle() } } -// STUB: LEGO1 0x1006b5e0 +// FUNCTION: LEGO1 0x1006b5e0 void LegoAnimPresenter::StartingTickle() { - // TODO - ProgressTickleState(e_streaming); - EndAction(); // Allow game to start + FUN_1006ac90(); + FUN_100692b0(); + FUN_100695c0(); + + if ((m_unk0x7c & c_bit2) == 0 || FUN_1006aba0()) { + FUN_10069b10(); + FUN_1006c8a0(TRUE); + + if (m_unk0x78 == NULL) { + if (fabs(m_action->GetDirection().GetX()) >= 0.00000047683716F || + fabs(m_action->GetDirection().GetY()) >= 0.00000047683716F || + fabs(m_action->GetDirection().GetZ()) >= 0.00000047683716F) { + m_unk0x78 = new MxMatrix(); + CalcLocalTransform(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), *m_unk0x78); + } + else if (m_unk0x68) { + MxU8* und = (MxU8*) m_unk0x68[1]; + + if (und) { + MxMatrix mat; + mat = *(Matrix4*) (und + 0x10); + m_unk0x78 = new MxMatrix(mat); + } + } + } + + if ((m_action->GetDuration() == -1 || ((MxDSMediaAction*) m_action)->GetSustainTime() == -1) && + m_compositePresenter) { + m_compositePresenter->VTable0x60(this); + } + else { + m_action->SetUnknown90(Timer()->GetTime()); + } + + ProgressTickleState(e_streaming); + + if (m_compositePresenter && m_compositePresenter->IsA("LegoAnimMMPresenter")) { + m_unk0x96 = ((LegoAnimMMPresenter*) m_compositePresenter)->FUN_1004b8b0(); + m_compositePresenter->VTable0x60(this); + } + + VTable0x8c(); + } + + if (m_unk0x70 != NULL) { + delete m_unk0x70; + m_unk0x70 = NULL; + } } // FUNCTION: LEGO1 0x1006b840 @@ -393,6 +465,12 @@ void LegoAnimPresenter::ParseExtra() // TODO } +// STUB: LEGO1 0x1006c570 +void LegoAnimPresenter::VTable0xa0() +{ + // TODO +} + // FUNCTION: LEGO1 0x1006c620 MxResult LegoAnimPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) { @@ -407,3 +485,33 @@ void LegoAnimPresenter::EndAction() // TODO MxVideoPresenter::EndAction(); } + +// STUB: LEGO1 0x1006c7d0 +void LegoAnimPresenter::VTable0x8c() +{ + // TODO +} + +// STUB: LEGO1 0x1006c860 +void LegoAnimPresenter::VTable0x90() +{ + // TODO +} + +// STUB: LEGO1 0x1006c8a0 +void LegoAnimPresenter::FUN_1006c8a0(LegoBool) +{ + // TODO +} + +// STUB: LEGO1 0x1006c8f0 +void LegoAnimPresenter::VTable0x94() +{ + // TODO +} + +// STUB: LEGO1 0x1006ca50 +void LegoAnimPresenter::VTable0x98() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp index 5bb59615..19b2e3a4 100644 --- a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp @@ -8,6 +8,18 @@ LegoHideAnimPresenter::LegoHideAnimPresenter() Init(); } +// STUB: LEGO1 0x1006d860 +void LegoHideAnimPresenter::VTable0x8c() +{ + // TODO +} + +// STUB: LEGO1 0x1006d870 +void LegoHideAnimPresenter::VTable0x90() +{ + // TODO +} + // FUNCTION: LEGO1 0x1006d9f0 LegoHideAnimPresenter::~LegoHideAnimPresenter() { diff --git a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp index 4886245e..0c6db766 100644 --- a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp @@ -41,7 +41,7 @@ void LegoLocomotionAnimPresenter::Destroy(MxBool p_fromDestructor) delete m_unk0xc8; } - m_unk0x68 = 0; + m_unk0x68 = NULL; Init(); m_criticalSection.Leave(); diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 48c46fcf..b0cf26cf 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -43,7 +43,7 @@ class Mx3DPointFloat : public Vector3 { inline void EqualsCross(Mx3DPointFloat& p_a, Mx3DPointFloat& p_b) { EqualsCrossImpl(p_a.m_data, p_b.m_data); } private: - float m_elements[3]; + float m_elements[3]; // 0x08 }; // VTABLE: LEGO1 0x100d41e8 diff --git a/LEGO1/omni/include/mxtimer.h b/LEGO1/omni/include/mxtimer.h index 468cd602..980719de 100644 --- a/LEGO1/omni/include/mxtimer.h +++ b/LEGO1/omni/include/mxtimer.h @@ -28,8 +28,9 @@ class MxTimer : public MxCore { // MxTimer::`scalar deleting destructor' private: - MxLong m_startTime; - MxBool m_isRunning; + MxLong m_startTime; // 0x08 + MxBool m_isRunning; // 0x0c + static MxLong g_lastTimeCalculated; static MxLong g_lastTimeTimerStarted; }; diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index a28a9874..8b41cc13 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -145,7 +145,7 @@ class Vector2 { inline const float& operator[](size_t idx) const { return m_data[idx]; } protected: - float* m_data; + float* m_data; // 0x04 }; // VTABLE: LEGO1 0x100d4518 From 4d84157888c3fd06bc4d0c108a275fa1f5172b2c Mon Sep 17 00:00:00 2001 From: Nathan M Gilbert Date: Tue, 27 Feb 2024 15:04:17 -0500 Subject: [PATCH 13/14] Implement Save, Load, DeleteState (#602) * Implement Save, Load, DeleteState * WIP * WIP * Match LegoGameState::Save * Spacing * Match LegoGameState::DeleteState() * More match * Match * Move vars * Other fixes * Rename * Fix error --------- Co-authored-by: Christian Semmler --- .../legoomni/include/legobackgroundcolor.h | 2 + .../legoomni/include/legobuildingmanager.h | 3 + LEGO1/lego/legoomni/include/legogamestate.h | 5 +- .../lego/legoomni/include/legoplantmanager.h | 3 + .../legoomni/include/legounksavedatawriter.h | 1 + LEGO1/lego/legoomni/include/legoutil.h | 1 + .../src/build/legobuildingmanager.cpp | 12 + .../src/common/legobackgroundcolor.cpp | 13 + .../legoomni/src/common/legogamestate.cpp | 229 +++++++++++++++--- .../legoomni/src/common/legoplantmanager.cpp | 12 + .../src/common/legounksavedatawriter.cpp | 6 + LEGO1/lego/legoomni/src/common/legoutil.cpp | 5 + LEGO1/lego/legoomni/src/entity/legoworld.cpp | 2 +- LEGO1/lego/sources/misc/legostorage.h | 40 +-- LEGO1/omni/include/mxutil.h | 3 +- LEGO1/omni/src/common/mxutil.cpp | 17 +- 16 files changed, 300 insertions(+), 54 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legobackgroundcolor.h b/LEGO1/lego/legoomni/include/legobackgroundcolor.h index 672e39be..3a301a39 100644 --- a/LEGO1/lego/legoomni/include/legobackgroundcolor.h +++ b/LEGO1/lego/legoomni/include/legobackgroundcolor.h @@ -9,6 +9,8 @@ class LegoBackgroundColor : public MxVariable { public: LegoBackgroundColor(const char* p_key, const char* p_value); void SetValue(const char* p_colorString) override; + void SetLights(float p_r, float p_g, float p_b); + void SetLights(); private: float m_h; diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index f6b5c0e6..2c50c027 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -2,6 +2,7 @@ #define LEGOBUILDINGMANAGER_H #include "decomp.h" +#include "lego/sources/misc/legostorage.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d6f50 @@ -25,6 +26,8 @@ class LegoBuildingManager : public MxCore { void FUN_1002fa00(); void FUN_1002fb30(); + MxResult Save(LegoStorage* p_storage); + MxResult Load(LegoStorage* p_storage); void FUN_10030590(); // SYNTHETIC: LEGO1 0x1002f940 diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 59dc8784..d35c0764 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -120,8 +120,9 @@ class LegoGameState { LegoGameState(); ~LegoGameState(); - MxResult Load(MxULong); MxResult Save(MxULong); + MxResult DeleteState(); + MxResult Load(MxULong); void SerializePlayersInfo(MxS16); void SerializeScoreHistory(MxS16 p_flags); void SetSavePath(char*); @@ -152,7 +153,7 @@ class LegoGameState { void SetCurrentAct(Act p_currentAct); void FindLoadedAct(); void SetActor(MxU8 p_actorId); - void FUN_10039940(); + void ResetROI(); private: void RegisterState(LegoState* p_state); diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h index 5d64ca27..622eb500 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -2,6 +2,7 @@ #define LEGOPLANTMANAGER_H #include "decomp.h" +#include "lego/sources/misc/legostorage.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d6758 @@ -22,6 +23,8 @@ class LegoPlantManager : public MxCore { void FUN_10026360(MxS32 p_scriptIndex); void FUN_100263a0(undefined4 p_und); + void Save(LegoStorage* p_storage); + MxResult Load(LegoStorage* p_storage); void FUN_10027120(); static void SetCustomizeAnimFile(const char* p_value); diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index 8013699c..482ecd9e 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -56,6 +56,7 @@ class LegoUnkSaveDataWriter { LegoUnkSaveDataWriter(); MxResult WriteSaveData3(LegoStorage* p_storage); + MxResult ReadSaveData3(LegoStorage* p_storage); LegoROI* FUN_10083500(const char*, MxBool); static void InitSaveData(); diff --git a/LEGO1/lego/legoomni/include/legoutil.h b/LEGO1/lego/legoomni/include/legoutil.h index 0b35fc61..01f6c516 100644 --- a/LEGO1/lego/legoomni/include/legoutil.h +++ b/LEGO1/lego/legoomni/include/legoutil.h @@ -41,6 +41,7 @@ void FUN_1003ef00(MxBool); void SetAppCursor(WPARAM p_wparam); MxBool FUN_1003ef60(); MxBool RemoveFromWorld(MxAtomId& p_atomId1, MxS32 p_id1, MxAtomId& p_atomId2, MxS32 p_id2); +void SetLightPosition(MxU32); NamedTexture* ReadNamedTexture(LegoFile* p_file); void FUN_1003f540(LegoFile* p_file, const char* p_filename); void WriteNamedTexture(LegoFile* p_file, NamedTexture* p_texture); diff --git a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp index ddb2788d..42b161f5 100644 --- a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp @@ -44,6 +44,18 @@ void LegoBuildingManager::FUN_1002fb30() // TODO } +// STUB: LEGO1 0x1002fb80 +MxResult LegoBuildingManager::Save(LegoStorage* p_storage) +{ + return SUCCESS; +} + +// STUB: LEGO1 0x1002fc10 +MxResult LegoBuildingManager::Load(LegoStorage* p_storage) +{ + return SUCCESS; +} + // FUNCTION: LEGO1 0x1002ff90 void LegoBuildingManager::SetCustomizeAnimFile(const char* p_value) { diff --git a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp index 461e84db..e6cd3fed 100644 --- a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp +++ b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp @@ -66,3 +66,16 @@ void LegoBackgroundColor::SetValue(const char* p_colorString) delete[] colorStringCopy; } + +// STUB: LEGO1 0x1003c400 +void LegoBackgroundColor::SetLights(float p_r, float p_g, float p_b) +{ +} + +// FUNCTION: LEGO1 0x1003c4b0 +void LegoBackgroundColor::SetLights() +{ + float convertedR, convertedG, convertedB; + ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB); + SetLights(convertedR, convertedG, convertedB); +} diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 9f1c6482..9c794f97 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -5,8 +5,10 @@ #include "infocenterstate.h" #include "islepathactor.h" #include "legoanimationmanager.h" +#include "legobuildingmanager.h" #include "legonavcontroller.h" #include "legoomni.h" +#include "legoplantmanager.h" #include "legostate.h" #include "legounksavedatawriter.h" #include "legoutil.h" @@ -156,58 +158,219 @@ void LegoGameState::SetActor(MxU8 p_actorId) SetCurrentActor(newActor); } -// STUB: LEGO1 0x10039940 -void LegoGameState::FUN_10039940() +// FUNCTION: LEGO1 0x10039940 +void LegoGameState::ResetROI() { - // TODO + if (m_actorId) { + IslePathActor* actor = CurrentActor(); + + if (actor) { + LegoROI* roi = actor->GetROI(); + + if (roi) { + VideoManager()->Get3DManager()->GetLego3DView()->Remove(*roi); + VideoManager()->Get3DManager()->GetLego3DView()->Add(*roi); + } + } + } } // FUNCTION: LEGO1 0x10039980 MxResult LegoGameState::Save(MxULong p_slot) { - MxResult result; InfocenterState* infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); if (!infocenterState || !infocenterState->HasRegistered()) { - result = SUCCESS; + return SUCCESS; } - else { - result = FAILURE; - MxVariableTable* variableTable = VariableTable(); - MxString savePath; - GetFileSavePath(&savePath, p_slot); - LegoFile fileStream; - if (fileStream.Open(savePath.GetData(), LegoFile::c_write) != FAILURE) { - MxU32 maybeVersion = 0x1000C; - fileStream.Write(&maybeVersion, 4); - fileStream.Write(&m_unk0x24, 2); - fileStream.Write(&m_currentAct, 2); - fileStream.Write(&m_actorId, 1); - for (MxS32 i = 0; i < sizeof(g_colorSaveData) / sizeof(g_colorSaveData[0]); ++i) { - if (WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) { - return result; - } - } + MxResult result = FAILURE; + LegoFile fileStream; + MxVariableTable* variableTable = VariableTable(); + MxS16 count = 0; + MxU32 i; + MxS32 j; + MxU16 area; - if (WriteVariable(&fileStream, variableTable, "backgroundcolor") != FAILURE) { - if (WriteVariable(&fileStream, variableTable, "lightposition") != FAILURE) { - WriteEndOfVariables(&fileStream); + MxString savePath; + GetFileSavePath(&savePath, p_slot); - // TODO: Calls down to more aggregate writing functions - return SUCCESS; - } - } + if (fileStream.Open(savePath.GetData(), LegoFile::c_write) == FAILURE) { + goto done; + } + + Write(&fileStream, 0x1000c); + Write(&fileStream, m_unk0x24); + Write(&fileStream, (MxU16) m_currentAct); + Write(&fileStream, m_actorId); + + for (i = 0; i < _countof(g_colorSaveData); i++) { + if (WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) { + goto done; } } + + if (WriteVariable(&fileStream, variableTable, "backgroundcolor") == FAILURE) { + goto done; + } + if (WriteVariable(&fileStream, variableTable, "lightposition") == FAILURE) { + goto done; + } + + WriteEndOfVariables(&fileStream); + UnkSaveDataWriter()->WriteSaveData3(&fileStream); + PlantManager()->Save(&fileStream); + result = BuildingManager()->Save(&fileStream); + + for (j = 0; j < m_stateCount; j++) { + if (m_stateArray[j]->VTable0x14()) { + count++; + } + } + + Write(&fileStream, count); + + for (j = 0; j < m_stateCount; j++) { + if (m_stateArray[j]->VTable0x14()) { + m_stateArray[j]->VTable0x1c(&fileStream); + } + } + + area = m_unk0x42c; + Write(&fileStream, (MxU16) area); + SerializeScoreHistory(2); + m_isDirty = FALSE; + +done: return result; } -// STUB: LEGO1 0x10039c60 -MxResult LegoGameState::Load(MxULong) +// FUNCTION: LEGO1 0x10039bf0 +MxResult LegoGameState::DeleteState() { - // TODO - return 0; + MxS16 stateCount = m_stateCount; + LegoState** stateArray = m_stateArray; + + m_stateCount = 0; + m_stateArray = NULL; + + for (MxS32 count = 0; count < stateCount; count++) { + if (!stateArray[count]->SetFlag() && stateArray[count]->VTable0x14()) { + delete stateArray[count]; + } + else { + RegisterState(stateArray[count]); + stateArray[count] = NULL; + } + } + + delete[] stateArray; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10039c60 +MxResult LegoGameState::Load(MxULong p_slot) +{ + MxResult result = FAILURE; + LegoFile fileStream; + MxVariableTable* variableTable = VariableTable(); + + MxString savePath; + GetFileSavePath(&savePath, p_slot); + + if (fileStream.Open(savePath.GetData(), LegoFile::c_read) == FAILURE) { + goto done; + } + + MxU32 version, status; + MxS16 count, area, act; + const char* lightPosition; + + Read(&fileStream, &version); + + if (version != 0x1000c) { + OmniError("Saved game version mismatch", 0); + goto done; + } + + Read(&fileStream, &m_unk0x24); + + Read(&fileStream, &act); + SetCurrentAct((Act) act); + + Read(&fileStream, &m_actorId); + if (m_actorId) { + SetActor(m_actorId); + } + + do { + status = ReadVariable(&fileStream, variableTable); + if (status == 1) { + goto done; + } + } while (status != 2); + + m_backgroundColor->SetLights(); + lightPosition = VariableTable()->GetVariable("lightposition"); + + if (lightPosition) { + SetLightPosition(atoi(lightPosition)); + } + + if (UnkSaveDataWriter()->ReadSaveData3(&fileStream) == FAILURE) { + goto done; + } + if (PlantManager()->Load(&fileStream) == FAILURE) { + goto done; + } + if (BuildingManager()->Load(&fileStream) == FAILURE) { + goto done; + } + if (DeleteState() != SUCCESS) { + goto done; + } + + char stateName[80]; + Read(&fileStream, &count); + + if (count) { + for (MxS16 i = 0; i < count; i++) { + MxS16 stateNameLength; + Read(&fileStream, &stateNameLength); + Read(&fileStream, stateName, (MxULong) stateNameLength); + stateName[stateNameLength] = 0; + + LegoState* state = GetState(stateName); + if (!state) { + state = CreateState(stateName); + + if (!state) { + goto done; + } + } + + state->VTable0x1c(&fileStream); + } + } + + Read(&fileStream, &area); + + if (m_currentAct == 0) { + m_unk0x42c = e_noArea; + } + else { + m_unk0x42c = (Area) area; + } + + result = SUCCESS; + m_isDirty = FALSE; + +done: + if (result != SUCCESS) { + OmniError("Game state loading was not successful!", 0); + } + + return result; } // FUNCTION: LEGO1 0x10039f00 diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 2b2cc4e9..11f722e8 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -35,6 +35,18 @@ void LegoPlantManager::FUN_100263a0(undefined4 p_und) // TODO } +// STUB: LEGO1 0x10026720 +void LegoPlantManager::Save(LegoStorage* p_storage) +{ + // TODO +} + +// STUB: LEGO1 0x100267b0 +MxResult LegoPlantManager::Load(LegoStorage* p_storage) +{ + return SUCCESS; +} + // FUNCTION: LEGO1 0x10026be0 void LegoPlantManager::SetCustomizeAnimFile(const char* p_value) { diff --git a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp index ad3f91c6..74d1ff22 100644 --- a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp +++ b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp @@ -90,6 +90,12 @@ MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStorage* p_storage) return result; } +// STUB: LEGO1 0x100833f0 +MxResult LegoUnkSaveDataWriter::ReadSaveData3(LegoStorage* p_storage) +{ + return SUCCESS; +} + // STUB: LEGO1 0x10083500 LegoROI* LegoUnkSaveDataWriter::FUN_10083500(const char* p_key, MxBool p_option) { diff --git a/LEGO1/lego/legoomni/src/common/legoutil.cpp b/LEGO1/lego/legoomni/src/common/legoutil.cpp index fabe18d6..970ba3df 100644 --- a/LEGO1/lego/legoomni/src/common/legoutil.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutil.cpp @@ -291,6 +291,11 @@ MxBool FUN_1003ef60() return TRUE; } +// STUB: LEGO1 0x1003f0d0 +void SetLightPosition(MxU32) +{ +} + // STUB: LEGO1 0x1003f3b0 NamedTexture* ReadNamedTexture(LegoFile* p_file) { diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index ad66e1cf..2f24feb9 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -581,7 +581,7 @@ void LegoWorld::Enable(MxBool p_enable) AnimationManager()->FUN_1005f0b0(); } - GameState()->FUN_10039940(); + GameState()->ResetROI(); SetIsWorldActive(TRUE); } } diff --git a/LEGO1/lego/sources/misc/legostorage.h b/LEGO1/lego/sources/misc/legostorage.h index 08e295f4..daa3153d 100644 --- a/LEGO1/lego/sources/misc/legostorage.h +++ b/LEGO1/lego/sources/misc/legostorage.h @@ -22,16 +22,16 @@ class LegoStorage { // FUNCTION: LEGO1 0x10045ad0 virtual ~LegoStorage() {} - virtual LegoResult Read(void* p_buffer, LegoU32 p_size) = 0; - virtual LegoResult Write(const void* p_buffer, LegoU32 p_size) = 0; - virtual LegoResult GetPosition(LegoU32& p_position) = 0; - virtual LegoResult SetPosition(LegoU32 p_position) = 0; + virtual LegoResult Read(void* p_buffer, LegoU32 p_size) = 0; // vtable+0x04 + virtual LegoResult Write(const void* p_buffer, LegoU32 p_size) = 0; // vtable+0x08 + virtual LegoResult GetPosition(LegoU32& p_position) = 0; // vtable+0x0c + virtual LegoResult SetPosition(LegoU32 p_position) = 0; // vtable+0x10 // FUNCTION: LEGO1 0x10045ae0 - virtual LegoBool IsWriteMode() { return m_mode == c_write; } + virtual LegoBool IsWriteMode() { return m_mode == c_write; } // vtable+0x14 // FUNCTION: LEGO1 0x10045af0 - virtual LegoBool IsReadMode() { return m_mode == c_read; } + virtual LegoBool IsReadMode() { return m_mode == c_read; } // vtable+0x18 // SYNTHETIC: LEGO1 0x10045b00 // LegoStorage::`scalar deleting destructor' @@ -40,23 +40,35 @@ class LegoStorage { LegoU8 m_mode; // 0x04 }; +template +inline void Read(LegoStorage* p_storage, T* p_variable, LegoU32 p_size = sizeof(T)) +{ + p_storage->Read(p_variable, p_size); +} + +template +inline void Write(LegoStorage* p_storage, T p_variable) +{ + p_storage->Write(&p_variable, sizeof(p_variable)); +} + // VTABLE: LEGO1 0x100db710 // SIZE 0x10 class LegoMemory : public LegoStorage { public: LegoMemory(void* p_buffer); - LegoResult Read(void* p_buffer, LegoU32 p_size) override; - LegoResult Write(const void* p_buffer, LegoU32 p_size) override; + LegoResult Read(void* p_buffer, LegoU32 p_size) override; // vtable+0x04 + LegoResult Write(const void* p_buffer, LegoU32 p_size) override; // vtable+0x08 // FUNCTION: LEGO1 0x100994a0 - LegoResult GetPosition(LegoU32& p_position) override + LegoResult GetPosition(LegoU32& p_position) override // vtable+0x0c { p_position = m_position; return SUCCESS; } // FUNCTION: LEGO1 0x100994b0 - LegoResult SetPosition(LegoU32 p_position) override + LegoResult SetPosition(LegoU32 p_position) override // vtable+0x10 { m_position = p_position; return SUCCESS; @@ -79,10 +91,10 @@ class LegoFile : public LegoStorage { public: LegoFile(); ~LegoFile() override; - LegoResult Read(void* p_buffer, LegoU32 p_size) override; - LegoResult Write(const void* p_buffer, LegoU32 p_size) override; - LegoResult GetPosition(LegoU32& p_position) override; - LegoResult SetPosition(LegoU32 p_position) override; + LegoResult Read(void* p_buffer, LegoU32 p_size) override; // vtable+0x04 + LegoResult Write(const void* p_buffer, LegoU32 p_size) override; // vtable+0x08 + LegoResult GetPosition(LegoU32& p_position) override; // vtable+0x0c + LegoResult SetPosition(LegoU32 p_position) override; // vtable+0x10 LegoResult Open(const char* p_name, LegoU32 p_mode); // FUNCTION: LEGO1 0x100343d0 diff --git a/LEGO1/omni/include/mxutil.h b/LEGO1/omni/include/mxutil.h index c85259bb..801ca3c1 100644 --- a/LEGO1/omni/include/mxutil.h +++ b/LEGO1/omni/include/mxutil.h @@ -72,7 +72,8 @@ MxBool GetRectIntersection( ); void MakeSourceName(char*, const char*); -void SetOmniUserMessage(void (*)(const char*, int)); +void OmniError(const char* p_message, MxS32 p_status); +void SetOmniUserMessage(void (*p_omniUserMessage)(const char*, MxS32)); MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* p_presenter); void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags); MxDSObject* CreateStreamObject(MxDSFile*, MxS16); diff --git a/LEGO1/omni/src/common/mxutil.cpp b/LEGO1/omni/src/common/mxutil.cpp index 5ffab77c..61af4f6e 100644 --- a/LEGO1/omni/src/common/mxutil.cpp +++ b/LEGO1/omni/src/common/mxutil.cpp @@ -127,10 +127,21 @@ MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* return FALSE; } -// FUNCTION: LEGO1 0x100b7210 -void SetOmniUserMessage(void (*p_userMsg)(const char*, int)) +// FUNCTION: LEGO1 0x100b71e0 +void OmniError(const char* p_message, MxS32 p_status) { - g_omniUserMessage = p_userMsg; + if (g_omniUserMessage) { + g_omniUserMessage(p_message, p_status); + } + else if (p_status) { + abort(); + } +} + +// FUNCTION: LEGO1 0x100b7210 +void SetOmniUserMessage(void (*p_omniUserMessage)(const char*, MxS32)) +{ + g_omniUserMessage = p_omniUserMessage; } // FUNCTION: LEGO1 0x100b7220 From 0e7823cedd3629667154ad410c2260ebdf663bcc Mon Sep 17 00:00:00 2001 From: Nathan M Gilbert Date: Wed, 28 Feb 2024 15:03:27 -0500 Subject: [PATCH 14/14] LegoGameState player functions (#603) * LegoGameState player functions * Style * use sizeof --------- Co-authored-by: Christian Semmler --- .../legoomni/include/legobuildingmanager.h | 5 +- LEGO1/lego/legoomni/include/legogamestate.h | 23 +- .../lego/legoomni/include/legoplantmanager.h | 5 +- .../legoomni/include/legounksavedatawriter.h | 2 +- .../legoomni/src/common/legogamestate.cpp | 249 ++++++++++++++---- 5 files changed, 223 insertions(+), 61 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index 2c50c027..c8351413 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -2,7 +2,7 @@ #define LEGOBUILDINGMANAGER_H #include "decomp.h" -#include "lego/sources/misc/legostorage.h" +#include "misc/legostorage.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d6f50 @@ -24,6 +24,7 @@ class LegoBuildingManager : public MxCore { static void configureLegoBuildingManager(MxS32); static void SetCustomizeAnimFile(const char* p_value); + void Init(); void FUN_1002fa00(); void FUN_1002fb30(); MxResult Save(LegoStorage* p_storage); @@ -36,8 +37,6 @@ class LegoBuildingManager : public MxCore { private: static char* g_customizeAnimFile; - void Init(); - undefined m_unk0x08[0x28]; // 0x08 }; diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index d35c0764..7358df5f 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -90,8 +90,11 @@ class LegoGameState { // SIZE 0x0c struct Username { Username(); + inline Username(Username& p_other) { Set(p_other); } + inline void Set(Username& p_other) { memcpy(m_letters, p_other.m_letters, sizeof(m_letters)); } + MxResult ReadWrite(LegoStorage* p_storage); - Username* operator=(const Username* p_other); + Username& operator=(const Username& p_other); MxS16 m_letters[7]; // 0x00 }; @@ -120,19 +123,29 @@ class LegoGameState { LegoGameState(); ~LegoGameState(); + void SetActor(MxU8 p_actorId); + void RemoveActor(); + void ResetROI(); + MxResult Save(MxULong); MxResult DeleteState(); MxResult Load(MxULong); - void SerializePlayersInfo(MxS16); + + void SerializePlayersInfo(MxS16 p_flags); + MxResult AddPlayer(Username& p_player); + void SwitchPlayer(MxS16 p_playerId); + MxS16 FindPlayer(Username& p_player); + void SerializeScoreHistory(MxS16 p_flags); void SetSavePath(char*); LegoState* GetState(const char* p_stateName); LegoState* CreateState(const char* p_stateName); - void GetFileSavePath(MxString* p_outPath, MxULong p_slotn); + void GetFileSavePath(MxString* p_outPath, MxU8 p_slotn); void StopArea(Area p_area); void SwitchArea(Area p_area); + void Init(); inline MxU8 GetActorId() { return m_actorId; } inline Act GetCurrentAct() { return m_currentAct; } @@ -152,8 +165,6 @@ class LegoGameState { void SetCurrentAct(Act p_currentAct); void FindLoadedAct(); - void SetActor(MxU8 p_actorId); - void ResetROI(); private: void RegisterState(LegoState* p_state); @@ -173,7 +184,7 @@ class LegoGameState { LegoBackgroundColor* m_tempBackgroundColor; // 0x1c LegoFullScreenMovie* m_fullScreenMovie; // 0x20 MxU16 m_unk0x24; // 0x24 - undefined2 m_unk0x26; // 0x26 + MxS16 m_playerCount; // 0x26 Username m_players[9]; // 0x28 History m_history; // 0xa6 undefined2 m_unk0x41a; // 0x41a diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h index 622eb500..581ec7b4 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -2,7 +2,7 @@ #define LEGOPLANTMANAGER_H #include "decomp.h" -#include "lego/sources/misc/legostorage.h" +#include "misc/legostorage.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d6758 @@ -21,6 +21,7 @@ class LegoPlantManager : public MxCore { return "LegoPlantManager"; } + void Init(); void FUN_10026360(MxS32 p_scriptIndex); void FUN_100263a0(undefined4 p_und); void Save(LegoStorage* p_storage); @@ -35,8 +36,6 @@ class LegoPlantManager : public MxCore { private: static char* g_customizeAnimFile; - void Init(); - undefined m_unk0x08[0x24]; // 0x08 }; diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index 482ecd9e..9f3d1235 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -59,7 +59,7 @@ class LegoUnkSaveDataWriter { MxResult ReadSaveData3(LegoStorage* p_storage); LegoROI* FUN_10083500(const char*, MxBool); - static void InitSaveData(); + void InitSaveData(); static void SetCustomizeAnimFile(const char* p_value); static MxBool FUN_10084c00(const LegoChar*); diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 9c794f97..ccd0a445 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -2,8 +2,12 @@ #include "act1state.h" #include "define.h" +#include "dunebuggy.h" +#include "helicopter.h" #include "infocenterstate.h" +#include "isle.h" #include "islepathactor.h" +#include "jetski.h" #include "legoanimationmanager.h" #include "legobuildingmanager.h" #include "legonavcontroller.h" @@ -18,6 +22,7 @@ #include "mxobjectfactory.h" #include "mxstring.h" #include "mxvariabletable.h" +#include "racecar.h" #include "roi/legoroi.h" #include @@ -90,7 +95,7 @@ LegoGameState::LegoGameState() m_currentArea = e_noArea; m_previousArea = e_noArea; m_unk0x42c = e_noArea; - m_unk0x26 = 0; + m_playerCount = 0; m_isDirty = FALSE; m_loadedAct = e_actNotFound; SetCurrentAct(e_act1); @@ -158,6 +163,15 @@ void LegoGameState::SetActor(MxU8 p_actorId) SetCurrentActor(newActor); } +// FUNCTION: LEGO1 0x10039910 +void LegoGameState::RemoveActor() +{ + IslePathActor* actor = CurrentActor(); + SetCurrentActor(NULL); + delete actor; + m_actorId = 0; +} + // FUNCTION: LEGO1 0x10039940 void LegoGameState::ResetROI() { @@ -185,7 +199,7 @@ MxResult LegoGameState::Save(MxULong p_slot) } MxResult result = FAILURE; - LegoFile fileStream; + LegoFile fileStorage; MxVariableTable* variableTable = VariableTable(); MxS16 count = 0; MxU32 i; @@ -195,32 +209,32 @@ MxResult LegoGameState::Save(MxULong p_slot) MxString savePath; GetFileSavePath(&savePath, p_slot); - if (fileStream.Open(savePath.GetData(), LegoFile::c_write) == FAILURE) { + if (fileStorage.Open(savePath.GetData(), LegoFile::c_write) == FAILURE) { goto done; } - Write(&fileStream, 0x1000c); - Write(&fileStream, m_unk0x24); - Write(&fileStream, (MxU16) m_currentAct); - Write(&fileStream, m_actorId); + Write(&fileStorage, 0x1000c); + Write(&fileStorage, m_unk0x24); + Write(&fileStorage, (MxU16) m_currentAct); + Write(&fileStorage, m_actorId); for (i = 0; i < _countof(g_colorSaveData); i++) { - if (WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) { + if (WriteVariable(&fileStorage, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) { goto done; } } - if (WriteVariable(&fileStream, variableTable, "backgroundcolor") == FAILURE) { + if (WriteVariable(&fileStorage, variableTable, "backgroundcolor") == FAILURE) { goto done; } - if (WriteVariable(&fileStream, variableTable, "lightposition") == FAILURE) { + if (WriteVariable(&fileStorage, variableTable, "lightposition") == FAILURE) { goto done; } - WriteEndOfVariables(&fileStream); - UnkSaveDataWriter()->WriteSaveData3(&fileStream); - PlantManager()->Save(&fileStream); - result = BuildingManager()->Save(&fileStream); + WriteEndOfVariables(&fileStorage); + UnkSaveDataWriter()->WriteSaveData3(&fileStorage); + PlantManager()->Save(&fileStorage); + result = BuildingManager()->Save(&fileStorage); for (j = 0; j < m_stateCount; j++) { if (m_stateArray[j]->VTable0x14()) { @@ -228,16 +242,16 @@ MxResult LegoGameState::Save(MxULong p_slot) } } - Write(&fileStream, count); + Write(&fileStorage, count); for (j = 0; j < m_stateCount; j++) { if (m_stateArray[j]->VTable0x14()) { - m_stateArray[j]->VTable0x1c(&fileStream); + m_stateArray[j]->VTable0x1c(&fileStorage); } } area = m_unk0x42c; - Write(&fileStream, (MxU16) area); + Write(&fileStorage, (MxU16) area); SerializeScoreHistory(2); m_isDirty = FALSE; @@ -272,13 +286,13 @@ MxResult LegoGameState::DeleteState() MxResult LegoGameState::Load(MxULong p_slot) { MxResult result = FAILURE; - LegoFile fileStream; + LegoFile fileStorage; MxVariableTable* variableTable = VariableTable(); MxString savePath; GetFileSavePath(&savePath, p_slot); - if (fileStream.Open(savePath.GetData(), LegoFile::c_read) == FAILURE) { + if (fileStorage.Open(savePath.GetData(), LegoFile::c_read) == FAILURE) { goto done; } @@ -286,25 +300,25 @@ MxResult LegoGameState::Load(MxULong p_slot) MxS16 count, area, act; const char* lightPosition; - Read(&fileStream, &version); + Read(&fileStorage, &version); if (version != 0x1000c) { OmniError("Saved game version mismatch", 0); goto done; } - Read(&fileStream, &m_unk0x24); + Read(&fileStorage, &m_unk0x24); - Read(&fileStream, &act); + Read(&fileStorage, &act); SetCurrentAct((Act) act); - Read(&fileStream, &m_actorId); + Read(&fileStorage, &m_actorId); if (m_actorId) { SetActor(m_actorId); } do { - status = ReadVariable(&fileStream, variableTable); + status = ReadVariable(&fileStorage, variableTable); if (status == 1) { goto done; } @@ -317,13 +331,13 @@ MxResult LegoGameState::Load(MxULong p_slot) SetLightPosition(atoi(lightPosition)); } - if (UnkSaveDataWriter()->ReadSaveData3(&fileStream) == FAILURE) { + if (UnkSaveDataWriter()->ReadSaveData3(&fileStorage) == FAILURE) { goto done; } - if (PlantManager()->Load(&fileStream) == FAILURE) { + if (PlantManager()->Load(&fileStorage) == FAILURE) { goto done; } - if (BuildingManager()->Load(&fileStream) == FAILURE) { + if (BuildingManager()->Load(&fileStorage) == FAILURE) { goto done; } if (DeleteState() != SUCCESS) { @@ -331,13 +345,13 @@ MxResult LegoGameState::Load(MxULong p_slot) } char stateName[80]; - Read(&fileStream, &count); + Read(&fileStorage, &count); if (count) { for (MxS16 i = 0; i < count; i++) { MxS16 stateNameLength; - Read(&fileStream, &stateNameLength); - Read(&fileStream, stateName, (MxULong) stateNameLength); + Read(&fileStorage, &stateNameLength); + Read(&fileStorage, stateName, (MxULong) stateNameLength); stateName[stateNameLength] = 0; LegoState* state = GetState(stateName); @@ -349,11 +363,11 @@ MxResult LegoGameState::Load(MxULong p_slot) } } - state->VTable0x1c(&fileStream); + state->VTable0x1c(&fileStorage); } } - Read(&fileStream, &area); + Read(&fileStorage, &area); if (m_currentAct == 0) { m_unk0x42c = e_noArea; @@ -397,11 +411,11 @@ MxResult LegoGameState::WriteVariable(LegoStorage* p_storage, MxVariableTable* p if (variableValue) { MxU8 length = strlen(p_variableName); - if (p_storage->Write((char*) &length, 1) == SUCCESS) { + if (p_storage->Write(&length, sizeof(length)) == SUCCESS) { if (p_storage->Write(p_variableName, length) == SUCCESS) { length = strlen(variableValue); - if (p_storage->Write((char*) &length, 1) == SUCCESS) { - result = p_storage->Write((char*) variableValue, length); + if (p_storage->Write(&length, sizeof(length)) == SUCCESS) { + result = p_storage->Write(variableValue, length); } } } @@ -415,22 +429,20 @@ MxResult LegoGameState::WriteEndOfVariables(LegoStorage* p_storage) { MxU8 len = strlen(g_endOfVariables); - if (p_storage->Write(&len, 1) == SUCCESS) { + if (p_storage->Write(&len, sizeof(len)) == SUCCESS) { return p_storage->Write(g_endOfVariables, len); } return FAILURE; } -// 95% match, just some instruction ordering differences on the call to -// MxVariableTable::SetVariable at the end. // FUNCTION: LEGO1 0x1003a080 MxS32 LegoGameState::ReadVariable(LegoStorage* p_storage, MxVariableTable* p_to) { MxS32 result = 1; MxU8 length; - if (p_storage->Read((char*) &length, 1) == SUCCESS) { + if (p_storage->Read(&length, sizeof(length)) == SUCCESS) { char nameBuffer[256]; if (p_storage->Read(nameBuffer, length) == SUCCESS) { nameBuffer[length] = '\0'; @@ -439,12 +451,12 @@ MxS32 LegoGameState::ReadVariable(LegoStorage* p_storage, MxVariableTable* p_to) result = 2; } else { - if (p_storage->Read((char*) &length, 1) == SUCCESS) { + if (p_storage->Read(&length, sizeof(length)) == SUCCESS) { char valueBuffer[256]; if (p_storage->Read(valueBuffer, length) == SUCCESS) { - result = 0; valueBuffer[length] = '\0'; p_to->SetVariable(nameBuffer, valueBuffer); + result = SUCCESS; } } } @@ -455,7 +467,7 @@ MxS32 LegoGameState::ReadVariable(LegoStorage* p_storage, MxVariableTable* p_to) } // FUNCTION: LEGO1 0x1003a170 -void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) +void LegoGameState::GetFileSavePath(MxString* p_outPath, MxU8 p_slotn) { char baseForSlot[2] = "0"; char path[1024] = ""; @@ -475,10 +487,97 @@ void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) *p_outPath = MxString(path); } -// STUB: LEGO1 0x1003a2e0 -void LegoGameState::SerializePlayersInfo(MxS16) +// FUNCTION: LEGO1 0x1003a2e0 +void LegoGameState::SerializePlayersInfo(MxS16 p_flags) { - // TODO + LegoFile fileStorage; + MxString playersGSI = MxString(m_savePath); + + playersGSI += "\\"; + playersGSI += g_playersGSI; + + if (fileStorage.Open(playersGSI.GetData(), p_flags) == SUCCESS) { + if (fileStorage.IsReadMode()) { + Read(&fileStorage, &m_playerCount); + } + else if (fileStorage.IsWriteMode()) { + Write(&fileStorage, m_playerCount); + } + + for (MxS16 i = 0; i < m_playerCount; i++) { + m_players[i].ReadWrite(&fileStorage); + } + } +} + +// FUNCTION: LEGO1 0x1003a3f0 +MxResult LegoGameState::AddPlayer(Username& p_player) +{ + MxString from, to; + + if (m_playerCount == 9) { + GetFileSavePath(&from, 8); + DeleteFile(from.GetData()); + m_playerCount--; + } + + for (MxS16 i = m_playerCount; i > 0; i--) { + m_players[i] = m_players[i - 1]; + GetFileSavePath(&from, i - 1); + GetFileSavePath(&to, i); + MoveFile(from.GetData(), to.GetData()); + } + + m_playerCount++; + m_players[0].Set(p_player); + m_unk0x24 = m_history.m_unk0x372; + m_history.m_unk0x372 = m_unk0x24 + 1; + m_history.WriteScoreHistory(); + SetCurrentAct(e_act1); + + return DeleteState(); +} + +// FUNCTION: LEGO1 0x1003a540 +void LegoGameState::SwitchPlayer(MxS16 p_playerId) +{ + if (p_playerId > 0) { + MxString from, temp, to; + + GetFileSavePath(&from, p_playerId); + GetFileSavePath(&temp, 36); + + Username selectedName(m_players[p_playerId]); + + MoveFile(from.GetData(), temp.GetData()); + + for (MxS16 i = p_playerId; i > 0; i--) { + m_players[i] = m_players[i - 1]; + GetFileSavePath(&from, i - 1); + GetFileSavePath(&to, i); + MoveFile(from.GetData(), to.GetData()); + } + + m_players[0] = selectedName; + GetFileSavePath(&from, 0); + MoveFile(temp.GetData(), from.GetData()); + } + + if (Load(0) != SUCCESS) { + Init(); + } +} + +// FUNCTION: LEGO1 0x1003a6e0 +MxS16 LegoGameState::FindPlayer(Username& p_player) +{ + for (MxS16 i = 0; i < m_playerCount; i++) { + if (memcmp(&m_players[i], &p_player, sizeof(p_player)) == 0) { + return i; + } + } + + return -1; } // FUNCTION: LEGO1 0x1003a720 @@ -939,6 +1038,60 @@ void LegoGameState::RegisterState(LegoState* p_state) m_stateArray[targetIndex] = p_state; } +// FUNCTION: LEGO1 0x1003bd00 +void LegoGameState::Init() +{ + m_backgroundColor->SetValue("set 56 54 68"); + m_backgroundColor->SetLights(); + m_tempBackgroundColor->SetValue("set 56 54 68"); + VariableTable()->SetVariable("lightposition", "2"); + SetLightPosition(2); + PlantManager()->Init(); + BuildingManager()->Init(); + UnkSaveDataWriter()->InitSaveData(); + AnimationManager()->FUN_1005ee80(TRUE); + SetColors(); + RemoveActor(); + DeleteState(); + m_isDirty = FALSE; + FindLoadedAct(); + SetCurrentAct(e_act1); + + if (m_loadedAct == e_act1) { + Isle* isle = (Isle*) FindWorld(*g_isleScript, 0); + + Helicopter* copter = (Helicopter*) isle->Find(*g_copterScript, 1); + if (copter) { + isle->FUN_1001fc80(copter); + isle->VTable0x6c(copter); + delete copter; + } + + DuneBuggy* dunebuggy = (DuneBuggy*) isle->Find(*g_dunecarScript, 2); + if (dunebuggy) { + isle->FUN_1001fc80(dunebuggy); + isle->VTable0x6c(dunebuggy); + delete dunebuggy; + } + + Jetski* jetski = (Jetski*) isle->Find(*g_jetskiScript, 3); + if (jetski) { + isle->FUN_1001fc80(jetski); + isle->VTable0x6c(jetski); + delete jetski; + } + + RaceCar* racecar = (RaceCar*) isle->Find(*g_racecarScript, 4); + if (racecar) { + isle->FUN_1001fc80(racecar); + isle->VTable0x6c(racecar); + delete racecar; + } + } + + m_unk0x42c = e_noArea; +} + // FUNCTION: LEGO1 0x1003c670 LegoGameState::Username::Username() { @@ -964,10 +1117,10 @@ MxResult LegoGameState::Username::ReadWrite(LegoStorage* p_storage) } // FUNCTION: LEGO1 0x1003c710 -LegoGameState::Username* LegoGameState::Username::operator=(const Username* p_other) +LegoGameState::Username& LegoGameState::Username::operator=(const Username& p_other) { - memcpy(m_letters, p_other->m_letters, sizeof(m_letters)); - return this; + memcpy(m_letters, p_other.m_letters, sizeof(m_letters)); + return *this; } // FUNCTION: LEGO1 0x1003c830