From 7cf6c78d203aace9a2a289b7bfaeb2b4b55f2897 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 8 Aug 2024 19:09:08 -0700 Subject: [PATCH 01/18] Implement TowTrack::HandlePathStruct (#1081) --- LEGO1/lego/legoomni/include/ambulance.h | 2 +- LEGO1/lego/legoomni/include/towtrack.h | 23 ++-- LEGO1/lego/legoomni/src/actors/ambulance.cpp | 8 +- LEGO1/lego/legoomni/src/actors/towtrack.cpp | 137 +++++++++++++++++-- 4 files changed, 145 insertions(+), 25 deletions(-) diff --git a/LEGO1/lego/legoomni/include/ambulance.h b/LEGO1/lego/legoomni/include/ambulance.h index a8ec5a00..7278c126 100644 --- a/LEGO1/lego/legoomni/include/ambulance.h +++ b/LEGO1/lego/legoomni/include/ambulance.h @@ -86,7 +86,7 @@ class AmbulanceMissionState : public LegoState { // AmbulanceMissionState::`scalar deleting destructor' undefined4 m_unk0x08; // 0x08 - MxLong m_unk0x0c; // 0x0c + MxLong m_startTime; // 0x0c MxS16 m_peScore; // 0x10 MxS16 m_maScore; // 0x12 MxS16 m_paScore; // 0x14 diff --git a/LEGO1/lego/legoomni/include/towtrack.h b/LEGO1/lego/legoomni/include/towtrack.h index da5ca2aa..3783b611 100644 --- a/LEGO1/lego/legoomni/include/towtrack.h +++ b/LEGO1/lego/legoomni/include/towtrack.h @@ -50,7 +50,7 @@ class TowTrackMissionState : public LegoState { // TowTrackMissionState::`scalar deleting destructor' undefined4 m_unk0x08; // 0x08 - MxLong m_unk0x0c; // 0x0c + MxLong m_startTime; // 0x0c MxBool m_unk0x10; // 0x10 MxS16 m_unk0x12; // 0x12 MxS16 m_unk0x14; // 0x14 @@ -105,18 +105,19 @@ class TowTrack : public IslePathActor { private: void Leave(); + void PlayFinalAnimation(IsleScript::Script p_objectId); void PlayAction(IsleScript::Script p_objectId); - undefined4 m_unk0x160; // 0x160 - TowTrackMissionState* m_state; // 0x164 - MxS16 m_unk0x168; // 0x168 - MxS16 m_actorId; // 0x16a - MxS16 m_unk0x16c; // 0x16c - MxS16 m_unk0x16e; // 0x16e - IsleScript::Script m_lastAction; // 0x170 - MxS32 m_unk0x174; // 0x174 - MxFloat m_fuel; // 0x178 - MxFloat m_time; // 0x17c + undefined4 m_unk0x160; // 0x160 + TowTrackMissionState* m_state; // 0x164 + MxS16 m_unk0x168; // 0x168 + MxS16 m_actorId; // 0x16a + MxS16 m_unk0x16c; // 0x16c + MxS16 m_unk0x16e; // 0x16e + IsleScript::Script m_lastAction; // 0x170 + IsleScript::Script m_lastAnimation; // 0x174 + MxFloat m_fuel; // 0x178 + MxFloat m_time; // 0x17c }; #endif // TOWTRACK_H diff --git a/LEGO1/lego/legoomni/src/actors/ambulance.cpp b/LEGO1/lego/legoomni/src/actors/ambulance.cpp index a044e431..22d34e74 100644 --- a/LEGO1/lego/legoomni/src/actors/ambulance.cpp +++ b/LEGO1/lego/legoomni/src/actors/ambulance.cpp @@ -283,7 +283,7 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param) } Leave(); - MxLong time = Timer()->GetTime() - m_state->m_unk0x0c; + MxLong time = Timer()->GetTime() - m_state->m_startTime; if (time < 300000) { m_state->UpdateScore(LegoState::e_red, m_actorId); @@ -393,7 +393,7 @@ MxLong Ambulance::HandleClick() if (m_state->m_unk0x08 == 1) { SpawnPlayer(LegoGameState::e_unk31, TRUE, 0); - m_state->m_unk0x0c = Timer()->GetTime(); + m_state->m_startTime = Timer()->GetTime(); InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_pns018rd_RunAnim, NULL); } @@ -586,7 +586,7 @@ void Ambulance::FUN_10037250() g_isleFlags |= Isle::c_playMusic; AnimationManager()->EnableCamAnims(TRUE); AnimationManager()->FUN_1005f6d0(TRUE); - m_state->m_unk0x0c = INT_MIN; + m_state->m_startTime = INT_MIN; m_state = NULL; } @@ -629,7 +629,7 @@ void Ambulance::PlayAction(IsleScript::Script p_objectId) AmbulanceMissionState::AmbulanceMissionState() { m_unk0x08 = 0; - m_unk0x0c = 0; + m_startTime = 0; m_peScore = 0; m_maScore = 0; m_paScore = 0; diff --git a/LEGO1/lego/legoomni/src/actors/towtrack.cpp b/LEGO1/lego/legoomni/src/actors/towtrack.cpp index 9acea958..d2b5158e 100644 --- a/LEGO1/lego/legoomni/src/actors/towtrack.cpp +++ b/LEGO1/lego/legoomni/src/actors/towtrack.cpp @@ -7,6 +7,7 @@ #include "legocontrolmanager.h" #include "legogamestate.h" #include "legonavcontroller.h" +#include "legopathstruct.h" #include "legoutils.h" #include "legovariables.h" #include "legoworld.h" @@ -33,7 +34,7 @@ TowTrack::TowTrack() m_unk0x16c = 0; m_lastAction = IsleScript::c_noneIsle; m_unk0x16e = 0; - m_unk0x174 = -1; + m_lastAnimation = IsleScript::c_noneIsle; m_maxLinearVel = 40.0; m_fuel = 1.0; } @@ -94,7 +95,7 @@ void TowTrack::VTable0x70(float p_time) sprintf(buf, "%g", m_fuel); VariableTable()->SetVariable(g_varTOWFUEL, buf); - if (p_time - m_state->m_unk0x0c > 100000.0f && m_state->m_unk0x08 == 1 && !m_state->m_unk0x10) { + if (p_time - m_state->m_startTime > 100000.0f && m_state->m_unk0x08 == 1 && !m_state->m_unk0x10) { PlayAction(IsleScript::c_Avo909In_PlayWav); m_state->m_unk0x10 = TRUE; } @@ -152,10 +153,120 @@ MxLong TowTrack::HandleEndAction(MxEndActionNotificationParam& p_param) return 0; } -// STUB: LEGO1 0x1004d330 +// FUNCTION: LEGO1 0x1004d330 +// FUNCTION: BETA10 0x100f74c0 MxLong TowTrack::HandlePathStruct(LegoPathStructNotificationParam& p_param) { - // TODO + MxDSAction action; + + // 0x168 corresponds to the path at the gas station + if (p_param.GetData() == 0x168) { + m_fuel = 1.0f; + } + + if (UserActor() != this) { + return 0; + } + + if (m_state->m_unk0x08 == 2 && + ((p_param.GetTrigger() == LegoPathStruct::c_camAnim && (p_param.GetData() == 9 || p_param.GetData() == 8)) || + (p_param.GetTrigger() == LegoPathStruct::c_w && p_param.GetData() == 0x169))) { + m_state->m_unk0x08 = 0; + + MxLong time = Timer()->GetTime() - m_state->m_startTime; + Leave(); + + if (time < 200000) { + PlayFinalAnimation(IsleScript::c_wgs083nu_RunAnim); + } + else if (time < 300000) { + PlayFinalAnimation(IsleScript::c_wgs090nu_RunAnim); + } + else { + PlayFinalAnimation(IsleScript::c_wgs097nu_RunAnim); + } + } + else if (m_state->m_unk0x08 == 1 && p_param.GetTrigger() == LegoPathStruct::c_camAnim && p_param.GetData() == 0x37) { + m_state->m_unk0x08 = 3; + StopActions(); + + if (m_lastAction != IsleScript::c_noneIsle) { + InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL); + } + + Leave(); + PlayFinalAnimation(IsleScript::c_wrt060bm_RunAnim); + } + else if (p_param.GetTrigger() == LegoPathStruct::c_w && m_state->m_unk0x08 == 1) { + if (p_param.GetData() == 0x15f) { + if (m_unk0x16c == 0) { + m_unk0x16c = 1; + InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns050p1_RunAnim, NULL); + } + } + else if (p_param.GetData() == 0x160) { + if (m_unk0x16e == 0) { + m_unk0x16e = 1; + InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns046mg_RunAnim, NULL); + } + + if (!m_state->m_unk0x10 && m_lastAction == IsleScript::c_noneIsle) { + if (m_actorId < LegoActor::c_pepper || m_actorId > LegoActor::c_laura) { + m_actorId = LegoActor::c_laura; + } + + IsleScript::Script objectId; + + switch (m_actorId) { + case c_pepper: + objectId = IsleScript::c_wns034na_PlayWav; + break; + case c_mama: + switch ((rand() % 2) + 1) { + case 1: + objectId = IsleScript::c_wns037na_PlayWav; + break; + case 2: + objectId = IsleScript::c_wns038na_PlayWav; + break; + } + break; + case c_papa: + switch ((rand() % 2) + 1) { + case 1: + objectId = IsleScript::c_wns041na_PlayWav; + break; + case 2: + objectId = IsleScript::c_wns042na_PlayWav; + break; + } + break; + case c_nick: + switch ((rand() % 2) + 1) { + case 1: + objectId = IsleScript::c_wns039na_PlayWav; + break; + case 2: + objectId = IsleScript::c_wns040na_PlayWav; + break; + } + case c_laura: + switch ((rand() % 2) + 1) { + case 1: + objectId = IsleScript::c_wns043na_PlayWav; + break; + case 2: + objectId = IsleScript::c_wns044na_PlayWav; + break; + } + break; + } + + PlayAction(objectId); + } + } + } + return 0; } @@ -196,8 +307,8 @@ MxLong TowTrack::HandleClick() else { SpawnPlayer(LegoGameState::e_unk28, TRUE, 0); m_lastAction = IsleScript::c_noneIsle; - m_unk0x174 = -1; - m_state->m_unk0x0c = Timer()->GetTime(); + m_lastAnimation = IsleScript::c_noneIsle; + m_state->m_startTime = Timer()->GetTime(); m_state->m_unk0x10 = FALSE; InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns057rd_RunAnim, NULL); InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns048p1_RunAnim, NULL); @@ -313,17 +424,25 @@ void TowTrack::FUN_1004dbe0() g_isleFlags |= Isle::c_playMusic; AnimationManager()->EnableCamAnims(TRUE); AnimationManager()->FUN_1005f6d0(TRUE); - m_state->m_unk0x0c = INT_MIN; + m_state->m_startTime = INT_MIN; m_state->m_unk0x10 = FALSE; m_state = NULL; m_unk0x16c = 0; m_unk0x16e = 0; } +// FUNCTION: LEGO1 0x1004dc80 +// FUNCTION: BETA10 0x100f86a0 +void TowTrack::PlayFinalAnimation(IsleScript::Script p_objectId) +{ + AnimationManager()->FUN_10060dc0(p_objectId, NULL, TRUE, FALSE, NULL, FALSE, FALSE, FALSE, TRUE); + m_lastAnimation = p_objectId; +} + // FUNCTION: LEGO1 0x1004dcf0 void TowTrack::PlayAction(IsleScript::Script p_objectId) { - if (p_objectId != -1) { + if (p_objectId != IsleScript::c_noneIsle) { InvokeAction(Extra::e_start, *g_isleScript, p_objectId, NULL); } @@ -339,7 +458,7 @@ TowTrackMissionState::TowTrackMissionState() m_unk0x16 = 0; m_unk0x08 = 0; m_unk0x18 = 0; - m_unk0x0c = 0; + m_startTime = 0; m_unk0x1a = 0; m_unk0x10 = FALSE; m_score1 = 0; From 53924c3d2d6382725b71b3b461abf3ce7f0f6679 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 9 Aug 2024 11:32:46 -0700 Subject: [PATCH 02/18] Implement/match TowTrack::HandleEndAction (#1082) * Implement/match TowTrack::HandleEndAction * Fix offset --- LEGO1/lego/legoomni/include/towtrack.h | 82 +++++--- LEGO1/lego/legoomni/src/actors/towtrack.cpp | 202 ++++++++++++++++---- 2 files changed, 229 insertions(+), 55 deletions(-) diff --git a/LEGO1/lego/legoomni/include/towtrack.h b/LEGO1/lego/legoomni/include/towtrack.h index 3783b611..74f710be 100644 --- a/LEGO1/lego/legoomni/include/towtrack.h +++ b/LEGO1/lego/legoomni/include/towtrack.h @@ -28,40 +28,77 @@ class TowTrackMissionState : public LegoState { MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c - MxS16 GetHighScore(MxU8 p_id) + MxS16 GetHighScore(MxU8 p_actorId) { - switch (p_id) { - case 1: - return m_score1; - case 2: - return m_score2; - case 3: - return m_score3; - case 4: - return m_score4; - case 5: - return m_score5; + switch (p_actorId) { + case LegoActor::c_pepper: + return m_peHighScore; + case LegoActor::c_mama: + return m_maHighScore; + case LegoActor::c_papa: + return m_paHighScore; + case LegoActor::c_nick: + return m_niHighScore; + case LegoActor::c_laura: + return m_laHighScore; default: return 0; } } + // FUNCTION: BETA10 0x100f8530 + void UpdateScore(ScoreColor p_score, MxS16 p_actorId) + { + switch (p_actorId) { + case LegoActor::c_pepper: + m_peScore = p_score; + if (m_peHighScore < p_score) { + m_peHighScore = p_score; + } + break; + case LegoActor::c_mama: + m_maScore = p_score; + if (m_maHighScore < p_score) { + m_maHighScore = p_score; + } + break; + case LegoActor::c_papa: + m_paScore = p_score; + if (m_paHighScore < p_score) { + m_paHighScore = p_score; + } + break; + case LegoActor::c_nick: + m_niScore = p_score; + if (m_niHighScore < p_score) { + m_niHighScore = p_score; + } + break; + case LegoActor::c_laura: + m_laScore = p_score; + if (m_laHighScore < p_score) { + m_laHighScore = p_score; + } + break; + } + } + // SYNTHETIC: LEGO1 0x1004e060 // TowTrackMissionState::`scalar deleting destructor' undefined4 m_unk0x08; // 0x08 MxLong m_startTime; // 0x0c MxBool m_unk0x10; // 0x10 - MxS16 m_unk0x12; // 0x12 - MxS16 m_unk0x14; // 0x14 - MxS16 m_unk0x16; // 0x16 - MxS16 m_unk0x18; // 0x18 - MxS16 m_unk0x1a; // 0x1a - MxS16 m_score1; // 0x1c - MxS16 m_score2; // 0x1e - MxS16 m_score3; // 0x20 - MxS16 m_score4; // 0x22 - MxS16 m_score5; // 0x24 + MxS16 m_peScore; // 0x12 + MxS16 m_maScore; // 0x14 + MxS16 m_paScore; // 0x16 + MxS16 m_niScore; // 0x18 + MxS16 m_laScore; // 0x1a + MxS16 m_peHighScore; // 0x1c + MxS16 m_maHighScore; // 0x1e + MxS16 m_paHighScore; // 0x20 + MxS16 m_niHighScore; // 0x22 + MxS16 m_laHighScore; // 0x24 }; // VTABLE: LEGO1 0x100d7ee0 @@ -106,6 +143,7 @@ class TowTrack : public IslePathActor { private: void Leave(); void PlayFinalAnimation(IsleScript::Script p_objectId); + void FUN_1004dcb0(IsleScript::Script p_objectId); void PlayAction(IsleScript::Script p_objectId); undefined4 m_unk0x160; // 0x160 diff --git a/LEGO1/lego/legoomni/src/actors/towtrack.cpp b/LEGO1/lego/legoomni/src/actors/towtrack.cpp index d2b5158e..65ab9105 100644 --- a/LEGO1/lego/legoomni/src/actors/towtrack.cpp +++ b/LEGO1/lego/legoomni/src/actors/towtrack.cpp @@ -12,6 +12,7 @@ #include "legovariables.h" #include "legoworld.h" #include "misc.h" +#include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" #include "mxmisc.h" #include "mxsoundpresenter.h" @@ -146,11 +147,137 @@ MxLong TowTrack::HandleEndAnim(LegoEndAnimNotificationParam& p_param) return 1; } -// STUB: LEGO1 0x1004cd40 +// FUNCTION: LEGO1 0x1004cd40 +// FUNCTION: BETA10 0x100f6f1f MxLong TowTrack::HandleEndAction(MxEndActionNotificationParam& p_param) { - // TODO - return 0; + if (p_param.GetAction() != NULL) { + IsleScript::Script objectId = (IsleScript::Script) p_param.GetAction()->GetObjectId(); + + if (m_lastAnimation == objectId) { + m_lastAnimation = IsleScript::c_noneIsle; + } + + if (m_lastAction == objectId) { + if (m_lastAnimation == IsleScript::c_noneIsle) { + BackgroundAudioManager()->RaiseVolume(); + } + + m_lastAction = IsleScript::c_noneIsle; + } + else if (objectId == IsleScript::c_wrt060bm_RunAnim) { + if (m_actorId < LegoActor::c_pepper || m_actorId > LegoActor::c_laura) { + m_actorId = LegoActor::c_laura; + } + + switch ((rand() % ((m_actorId != 4 ? 4 : 3))) + 1) { + case 1: + PlayFinalAnimation(IsleScript::c_wrt074sl_RunAnim); + break; + case 2: + PlayFinalAnimation(IsleScript::c_wrt075rh_RunAnim); + break; + case 3: + PlayFinalAnimation(IsleScript::c_wrt076df_RunAnim); + break; + case 4: + PlayFinalAnimation(IsleScript::c_wrt078ni_RunAnim); + break; + } + } + else if (objectId == IsleScript::c_wrt074sl_RunAnim || objectId == IsleScript::c_wrt075rh_RunAnim || objectId == IsleScript::c_wrt076df_RunAnim || objectId == IsleScript::c_wrt078ni_RunAnim) { + m_state->m_unk0x08 = 2; + CurrentWorld()->PlaceActor(UserActor()); + HandleClick(); + } + else if (objectId == IsleScript::c_wgs083nu_RunAnim) { + if (m_actorId < LegoActor::c_pepper || m_actorId > LegoActor::c_laura) { + m_actorId = LegoActor::c_laura; + } + + switch (m_actorId) { + case c_pepper: + FUN_1004dcb0(IsleScript::c_wgs085nu_RunAnim); + break; + case c_mama: + FUN_1004dcb0(IsleScript::c_wgs086nu_RunAnim); + break; + case c_papa: + FUN_1004dcb0(IsleScript::c_wgs088nu_RunAnim); + break; + case c_nick: + FUN_1004dcb0(IsleScript::c_wgs087nu_RunAnim); + break; + case c_laura: + FUN_1004dcb0(IsleScript::c_wgs089nu_RunAnim); + break; + } + + m_state->UpdateScore(LegoState::e_red, m_actorId); + + AnimationManager()->FUN_1005f6d0(TRUE); + g_isleFlags |= Isle::c_playMusic; + AnimationManager()->EnableCamAnims(TRUE); + } + else if (objectId == IsleScript::c_wgs090nu_RunAnim) { + if (m_actorId < LegoActor::c_pepper || m_actorId > LegoActor::c_laura) { + m_actorId = LegoActor::c_laura; + } + + switch (m_actorId) { + case c_pepper: + FUN_1004dcb0(IsleScript::c_wgs091nu_RunAnim); + break; + case c_mama: + FUN_1004dcb0(IsleScript::c_wgs092nu_RunAnim); + break; + case c_papa: + FUN_1004dcb0(IsleScript::c_wgs094nu_RunAnim); + break; + case c_nick: + FUN_1004dcb0(IsleScript::c_wgs093nu_RunAnim); + break; + case c_laura: + FUN_1004dcb0(IsleScript::c_wgs095nu_RunAnim); + break; + } + + m_state->UpdateScore(LegoState::e_blue, m_actorId); + } + else if (objectId == IsleScript::c_wgs097nu_RunAnim) { + if (m_actorId < LegoActor::c_pepper || m_actorId > LegoActor::c_laura) { + m_actorId = LegoActor::c_laura; + } + + switch (m_actorId) { + case c_pepper: + FUN_1004dcb0(IsleScript::c_wgs098nu_RunAnim); + break; + case c_mama: + FUN_1004dcb0(IsleScript::c_wgs099nu_RunAnim); + break; + case c_papa: + FUN_1004dcb0(IsleScript::c_wgs101nu_RunAnim); + break; + case c_nick: + FUN_1004dcb0(IsleScript::c_wgs100nu_RunAnim); + break; + case c_laura: + FUN_1004dcb0(IsleScript::c_wgs102nu_RunAnim); + break; + } + + m_state->UpdateScore(LegoState::e_yellow, m_actorId); + } + else if (objectId == IsleScript::c_wgs098nu_RunAnim || objectId == IsleScript::c_wgs099nu_RunAnim || objectId == IsleScript::c_wgs100nu_RunAnim || objectId == IsleScript::c_wgs101nu_RunAnim || objectId == IsleScript::c_wgs102nu_RunAnim || objectId == IsleScript::c_wgs085nu_RunAnim || objectId == IsleScript::c_wgs086nu_RunAnim || objectId == IsleScript::c_wgs087nu_RunAnim || objectId == IsleScript::c_wgs088nu_RunAnim || objectId == IsleScript::c_wgs089nu_RunAnim || objectId == IsleScript::c_wgs091nu_RunAnim || objectId == IsleScript::c_wgs092nu_RunAnim || objectId == IsleScript::c_wgs093nu_RunAnim || objectId == IsleScript::c_wgs094nu_RunAnim || objectId == IsleScript::c_wgs095nu_RunAnim) { + ((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 0; + AnimationManager()->FUN_1005f6d0(TRUE); + g_isleFlags |= Isle::c_playMusic; + AnimationManager()->EnableCamAnims(TRUE); + } + } + + return 1; } // FUNCTION: LEGO1 0x1004d330 @@ -250,6 +377,7 @@ MxLong TowTrack::HandlePathStruct(LegoPathStructNotificationParam& p_param) objectId = IsleScript::c_wns040na_PlayWav; break; } + break; case c_laura: switch ((rand() % 2) + 1) { case 1: @@ -439,6 +567,14 @@ void TowTrack::PlayFinalAnimation(IsleScript::Script p_objectId) m_lastAnimation = p_objectId; } +// FUNCTION: LEGO1 0x1004dcb0 +void TowTrack::FUN_1004dcb0(IsleScript::Script p_objectId) +{ + AnimationManager()->FUN_1005f6d0(TRUE); + AnimationManager()->FUN_10060dc0(p_objectId, NULL, TRUE, TRUE, NULL, FALSE, TRUE, TRUE, TRUE); + m_lastAnimation = p_objectId; +} + // FUNCTION: LEGO1 0x1004dcf0 void TowTrack::PlayAction(IsleScript::Script p_objectId) { @@ -453,19 +589,19 @@ void TowTrack::PlayAction(IsleScript::Script p_objectId) // FUNCTION: LEGO1 0x1004dd30 TowTrackMissionState::TowTrackMissionState() { - m_unk0x12 = 0; - m_unk0x14 = 0; - m_unk0x16 = 0; m_unk0x08 = 0; - m_unk0x18 = 0; m_startTime = 0; - m_unk0x1a = 0; m_unk0x10 = FALSE; - m_score1 = 0; - m_score2 = 0; - m_score3 = 0; - m_score4 = 0; - m_score5 = 0; + m_peScore = 0; + m_maScore = 0; + m_paScore = 0; + m_niScore = 0; + m_laScore = 0; + m_peHighScore = 0; + m_maHighScore = 0; + m_paHighScore = 0; + m_niHighScore = 0; + m_laHighScore = 0; } // FUNCTION: LEGO1 0x1004dde0 @@ -474,28 +610,28 @@ MxResult TowTrackMissionState::Serialize(LegoFile* p_file) LegoState::Serialize(p_file); if (p_file->IsReadMode()) { - Read(p_file, &m_unk0x12); - Read(p_file, &m_unk0x14); - Read(p_file, &m_unk0x16); - Read(p_file, &m_unk0x18); - Read(p_file, &m_unk0x1a); - Read(p_file, &m_score1); - Read(p_file, &m_score2); - Read(p_file, &m_score3); - Read(p_file, &m_score4); - Read(p_file, &m_score5); + Read(p_file, &m_peScore); + Read(p_file, &m_maScore); + Read(p_file, &m_paScore); + Read(p_file, &m_niScore); + Read(p_file, &m_laScore); + Read(p_file, &m_peHighScore); + Read(p_file, &m_maHighScore); + Read(p_file, &m_paHighScore); + Read(p_file, &m_niHighScore); + Read(p_file, &m_laHighScore); } else if (p_file->IsWriteMode()) { - Write(p_file, m_unk0x12); - Write(p_file, m_unk0x14); - Write(p_file, m_unk0x16); - Write(p_file, m_unk0x18); - Write(p_file, m_unk0x1a); - Write(p_file, m_score1); - Write(p_file, m_score2); - Write(p_file, m_score3); - Write(p_file, m_score4); - Write(p_file, m_score5); + Write(p_file, m_peScore); + Write(p_file, m_maScore); + Write(p_file, m_paScore); + Write(p_file, m_niScore); + Write(p_file, m_laScore); + Write(p_file, m_peHighScore); + Write(p_file, m_maHighScore); + Write(p_file, m_paHighScore); + Write(p_file, m_niHighScore); + Write(p_file, m_laHighScore); } return SUCCESS; From 9ab3954bbb8712526edcf305a7410ada6775c0e6 Mon Sep 17 00:00:00 2001 From: MS Date: Sun, 11 Aug 2024 16:23:39 -0400 Subject: [PATCH 03/18] Minor tweak to MxList template (#1083) * Beta addrs for MxList and related functions * MxList DeleteAll and Empty functions --- .../legoomni/include/legopathcontrollerlist.h | 58 ++++++ LEGO1/lego/legoomni/src/entity/legoworld.cpp | 1 + LEGO1/omni/include/mxcore.h | 3 + LEGO1/omni/include/mxdsactionlist.h | 78 +++++++ LEGO1/omni/include/mxdsmultiaction.h | 5 + LEGO1/omni/include/mxdsselectaction.h | 4 + LEGO1/omni/include/mxlist.h | 45 ++-- LEGO1/omni/include/mxrectlist.h | 76 ++++++- LEGO1/omni/include/mxregionlist.h | 197 ++++++++++++++++++ LEGO1/omni/include/mxstringlist.h | 62 +++++- LEGO1/omni/src/action/mxdsmultiaction.cpp | 1 + LEGO1/omni/src/action/mxdsselectaction.cpp | 2 + .../omni/src/common/mxcompositepresenter.cpp | 4 +- LEGO1/omni/src/video/mxregion.cpp | 5 + LEGO1/omni/src/video/mxregioncursor.cpp | 1 + 15 files changed, 515 insertions(+), 27 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legopathcontrollerlist.h b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h index f3728b06..0bc1cb27 100644 --- a/LEGO1/lego/legoomni/include/legopathcontrollerlist.h +++ b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h @@ -6,21 +6,27 @@ #include "mxtypes.h" // VTABLE: LEGO1 0x100d6380 +// VTABLE: BETA10 0x101bf130 // class MxCollection // VTABLE: LEGO1 0x100d6398 +// VTABLE: BETA10 0x101bf110 // class MxList // VTABLE: LEGO1 0x100d6320 +// VTABLE: BETA10 0x101bf0f0 // class MxPtrList // VTABLE: LEGO1 0x100d6338 +// VTABLE: BETA10 0x101bf0d0 // SIZE 0x18 class LegoPathControllerList : public MxPtrList { public: + // FUNCTION: BETA10 0x100dd060 LegoPathControllerList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} // FUNCTION: LEGO1 0x1001d210 + // FUNCTION: BETA10 0x100dd100 MxS8 Compare(LegoPathController* p_a, LegoPathController* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; @@ -28,70 +34,122 @@ class LegoPathControllerList : public MxPtrList { }; // VTABLE: LEGO1 0x100d6578 +// VTABLE: BETA10 0x101bf200 // class MxListCursor // VTABLE: LEGO1 0x100d6548 +// VTABLE: BETA10 0x101bf1e8 // class MxPtrListCursor // VTABLE: LEGO1 0x100d6560 +// VTABLE: BETA10 0x101bf1d0 // SIZE 0x10 class LegoPathControllerListCursor : public MxPtrListCursor { public: + // FUNCTION: BETA10 0x100dfd00 LegoPathControllerListCursor(LegoPathControllerList* p_list) : MxPtrListCursor(p_list) {} }; // TEMPLATE: LEGO1 0x1001d230 +// TEMPLATE: BETA10 0x100dd1f0 // MxCollection::Compare // TEMPLATE: LEGO1 0x1001d240 +// TEMPLATE: BETA10 0x100dd210 // MxList::MxList // TEMPLATE: LEGO1 0x1001d2d0 +// TEMPLATE: BETA10 0x100dd370 // MxCollection::~MxCollection // TEMPLATE: LEGO1 0x1001d320 +// TEMPLATE: BETA10 0x100dd430 // MxCollection::Destroy // TEMPLATE: LEGO1 0x1001d330 +// TEMPLATE: BETA10 0x100dd450 // MxList::~MxList // TEMPLATE: LEGO1 0x1001d3c0 +// TEMPLATE: BETA10 0x100dd530 // MxPtrList::Destroy // SYNTHETIC: LEGO1 0x1001d3d0 +// SYNTHETIC: BETA10 0x100dd580 // LegoPathControllerList::`scalar deleting destructor' // TEMPLATE: LEGO1 0x1001d440 +// TEMPLATE: BETA10 0x100dd5d0 // MxPtrList::~MxPtrList // SYNTHETIC: LEGO1 0x1001d490 +// SYNTHETIC: BETA10 0x100dd650 // MxCollection::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x1001d500 +// SYNTHETIC: BETA10 0x100dd6a0 // MxList::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x1001d5b0 +// SYNTHETIC: BETA10 0x100dd6f0 // MxPtrList::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x1001d620 +// SYNTHETIC: BETA10 0x100dd740 // LegoPathControllerList::~LegoPathControllerList // SYNTHETIC: LEGO1 0x1001f830 +// SYNTHETIC: BETA10 0x100dfef0 // LegoPathControllerListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x1001f8a0 +// TEMPLATE: BETA10 0x100dff40 // MxPtrListCursor::~MxPtrListCursor // SYNTHETIC: LEGO1 0x1001f8f0 +// SYNTHETIC: BETA10 0x100dffc0 // MxListCursor::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x1001f960 +// SYNTHETIC: BETA10 0x100e0010 // MxPtrListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x1001f9d0 +// TEMPLATE: BETA10 0x100e0060 // MxListCursor::~MxListCursor // FUNCTION: LEGO1 0x1001fa20 +// FUNCTION: BETA10 0x100e00e0 // LegoPathControllerListCursor::~LegoPathControllerListCursor +// TEMPLATE: BETA10 0x100dd150 +// MxPtrList::MxPtrList + +// TEMPLATE: BETA10 0x100dd2c0 +// MxCollection::MxCollection + +// TEMPLATE: BETA10 0x100dd400 +// MxCollection::SetDestroy + +// TEMPLATE: BETA10 0x100dd4e0 +// MxPtrList::SetOwnership + +// TEMPLATE: BETA10 0x100dfda0 +// MxPtrListCursor::MxPtrListCursor + +// TEMPLATE: BETA10 0x100dfe40 +// MxListCursor::MxListCursor + +// TEMPLATE: BETA10 0x100e1cb0 +// MxList::DeleteAll + +// TEMPLATE: BETA10 0x100e1d70 +// MxListCursor::Next + +// TEMPLATE: BETA10 0x100e1ff0 +// MxListEntry::GetNext + +// TEMPLATE: BETA10 0x100e2050 +// MxListEntry::GetValue + #endif // LEGOPATHCONTROLLERLIST_H diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index b7fd9aab..dce201c0 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -106,6 +106,7 @@ MxResult LegoWorld::Create(MxDSAction& p_dsAction) } // FUNCTION: LEGO1 0x1001e9d0 +// FUNCTION: BETA10 0x100d99ea void LegoWorld::Destroy(MxBool p_fromDestructor) { m_destroyed = TRUE; diff --git a/LEGO1/omni/include/mxcore.h b/LEGO1/omni/include/mxcore.h index 4bdc6193..4f271536 100644 --- a/LEGO1/omni/include/mxcore.h +++ b/LEGO1/omni/include/mxcore.h @@ -48,4 +48,7 @@ class MxCore { MxU32 m_id; // 0x04 }; +// SYNTHETIC: BETA10 0x10096940 +// MxCore::operator= + #endif // MXCORE_H diff --git a/LEGO1/omni/include/mxdsactionlist.h b/LEGO1/omni/include/mxdsactionlist.h index 989508e6..0124188d 100644 --- a/LEGO1/omni/include/mxdsactionlist.h +++ b/LEGO1/omni/include/mxdsactionlist.h @@ -6,18 +6,23 @@ #include "mxlist.h" // VTABLE: LEGO1 0x100dcea8 +// VTABLE: BETA10 0x101c2928 // class MxCollection // VTABLE: LEGO1 0x100dcec0 +// VTABLE: BETA10 0x101c2910 // class MxList // VTABLE: LEGO1 0x100dced8 +// VTABLE: BETA10 0x101c28f8 // SIZE 0x1c class MxDSActionList : public MxList { public: + // FUNCTION: BETA10 0x1015ad10 MxDSActionList() { this->m_unk0x18 = 0; } // FUNCTION: LEGO1 0x100c9c90 + // FUNCTION: BETA10 0x1015ad90 MxS8 Compare(MxDSAction* p_a, MxDSAction* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; @@ -27,6 +32,7 @@ class MxDSActionList : public MxList { static void Destroy(MxDSAction* p_action) { delete p_action; } // SYNTHETIC: LEGO1 0x100c9dc0 + // SYNTHETIC: BETA10 0x1015b070 // MxDSActionList::`scalar deleting destructor' private: @@ -34,31 +40,103 @@ class MxDSActionList : public MxList { }; // VTABLE: LEGO1 0x100d7e68 +// VTABLE: BETA10 0x101baf30 // class MxListCursor // VTABLE: LEGO1 0x100d7e50 +// VTABLE: BETA10 0x101baf18 // SIZE 0x10 class MxDSActionListCursor : public MxListCursor { public: + // FUNCTION: BETA10 0x1004db00 MxDSActionListCursor(MxDSActionList* p_list) : MxListCursor(p_list) {} }; // TEMPLATE: LEGO1 0x100c9cc0 +// TEMPLATE: BETA10 0x1015aed0 // MxCollection::Compare // TEMPLATE: LEGO1 0x100c9cd0 +// TEMPLATE: BETA10 0x1015af80 // MxCollection::~MxCollection // TEMPLATE: LEGO1 0x100c9d20 +// TEMPLATE: BETA10 0x1015aff0 // MxCollection::Destroy // TEMPLATE: LEGO1 0x100c9d30 +// TEMPLATE: BETA10 0x1015b000 // MxList::~MxList // SYNTHETIC: LEGO1 0x100c9e30 +// SYNTHETIC: BETA10 0x1015b0b0 // MxCollection::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100c9ea0 +// SYNTHETIC: BETA10 0x1015b0f0 // MxList::`scalar deleting destructor' +// TEMPLATE: BETA10 0x1004dba0 +// MxListCursor::MxListCursor + +// TEMPLATE: BETA10 0x1004e460 +// MxListCursor::Head + +// TEMPLATE: BETA10 0x1004e4b0 +// ?Next@?$MxListCursor@PAVMxDSAction@@@@QAEEXZ + +// TEMPLATE: BETA10 0x1004e530 +// MxListCursor::Current + +// TEMPLATE: BETA10 0x1004e590 +// MxListEntry::GetNext + +// TEMPLATE: BETA10 0x1004e5c0 +// MxListEntry::GetValue + +// TEMPLATE: BETA10 0x10137190 +// ?Next@?$MxListCursor@PAVMxDSAction@@@@QAEEAAPAVMxDSAction@@@Z + +// TEMPLATE: BETA10 0x101384e0 +// MxListCursor::Find + +// TEMPLATE: BETA10 0x10138580 +// MxListCursor::Detach + +// TEMPLATE: BETA10 0x101385c0 +// MxList::DeleteEntry + +// TEMPLATE: BETA10 0x10138670 +// MxListEntry::GetPrev + +// TEMPLATE: BETA10 0x10138690 +// MxListEntry::SetPrev + +// TEMPLATE: BETA10 0x101386c0 +// MxListEntry::SetNext + +// TEMPLATE: BETA10 0x1015ae10 +// MxCollection::SetDestroy + +// TEMPLATE: BETA10 0x1015ae40 +// MxList::MxList + +// TEMPLATE: BETA10 0x1015aef0 +// MxCollection::MxCollection + +// SYNTHETIC: BETA10 0x1015b130 +// MxDSActionList::~MxDSActionList + +// TEMPLATE: BETA10 0x1015b250 +// MxList::Append + +// TEMPLATE: BETA10 0x1015bca0 +// MxList::InsertEntry + +// TEMPLATE: BETA10 0x1015c140 +// MxListEntry::MxListEntry + +// TEMPLATE: BETA10 0x1015bd90 +// MxList::DeleteAll + #endif // MXDSACTIONLIST_H diff --git a/LEGO1/omni/include/mxdsmultiaction.h b/LEGO1/omni/include/mxdsmultiaction.h index 65ecb411..84ad1a4a 100644 --- a/LEGO1/omni/include/mxdsmultiaction.h +++ b/LEGO1/omni/include/mxdsmultiaction.h @@ -36,6 +36,7 @@ class MxDSMultiAction : public MxDSAction { MxBool HasId(MxU32 p_objectId) override; // vtable+34; void SetUnknown90(MxLong p_unk0x90) override; // vtable+38; + // FUNCTION: BETA10 0x1004e180 MxDSActionList* GetActionList() const { return m_actions; } // SYNTHETIC: LEGO1 0x100ca040 @@ -47,15 +48,19 @@ class MxDSMultiAction : public MxDSAction { }; // SYNTHETIC: LEGO1 0x1004ad10 +// SYNTHETIC: BETA10 0x1004dc50 // MxDSActionListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x1004ad80 +// TEMPLATE: BETA10 0x1004dca0 // MxListCursor::~MxListCursor // SYNTHETIC: LEGO1 0x1004add0 +// SYNTHETIC: BETA10 0x1004dd20 // MxListCursor::`scalar deleting destructor' // FUNCTION: LEGO1 0x1004ae40 +// FUNCTION: BETA10 0x1004dd70 // MxDSActionListCursor::~MxDSActionListCursor #endif // MXDSMULTIACTION_H diff --git a/LEGO1/omni/include/mxdsselectaction.h b/LEGO1/omni/include/mxdsselectaction.h index 271819a8..3f3e4874 100644 --- a/LEGO1/omni/include/mxdsselectaction.h +++ b/LEGO1/omni/include/mxdsselectaction.h @@ -41,15 +41,19 @@ class MxDSSelectAction : public MxDSParallelAction { }; // SYNTHETIC: LEGO1 0x100cbbd0 +// SYNTHETIC: BETA10 0x1015bb60 // MxStringListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100cbc40 +// TEMPLATE: BETA10 0x1015bba0 // MxListCursor::~MxListCursor // SYNTHETIC: LEGO1 0x100cbc90 +// SYNTHETIC: BETA10 0x1015bc00 // MxListCursor::`scalar deleting destructor' // FUNCTION: LEGO1 0x100cbd00 +// FUNCTION: BETA10 0x1015bc40 // MxStringListCursor::~MxStringListCursor #endif // MXDSSELECTACTION_H diff --git a/LEGO1/omni/include/mxlist.h b/LEGO1/omni/include/mxlist.h index 985c48d2..b020eeb3 100644 --- a/LEGO1/omni/include/mxlist.h +++ b/LEGO1/omni/include/mxlist.h @@ -45,17 +45,14 @@ class MxListEntry { template class MxList : protected MxCollection { public: - MxList() - { - m_last = NULL; - m_first = NULL; - } + MxList() { m_first = m_last = NULL; } ~MxList() override; void Append(T p_obj) { InsertEntry(p_obj, this->m_last, NULL); } void Prepend(T p_obj) { InsertEntry(p_obj, NULL, this->m_first); } - void DeleteAll(MxBool p_destroy = TRUE); + void DeleteAll(); + void Empty(); MxU32 GetCount() { return this->m_count; } friend class MxListCursor; @@ -136,27 +133,33 @@ MxList::~MxList() DeleteAll(); } +// Delete entries and values template -inline void MxList::DeleteAll(MxBool p_destroy) +inline void MxList::DeleteAll() { - for (MxListEntry* t = m_first;;) { - if (!t) { - break; - } - - MxListEntry* next = t->GetNext(); - - if (p_destroy) { - this->m_customDestructor(t->GetValue()); - } - + MxListEntry* next; + for (MxListEntry* t = m_first; t; t = next) { + next = t->GetNext(); + this->m_customDestructor(t->GetValue()); delete t; - t = next; } this->m_count = 0; - m_last = NULL; - m_first = NULL; + m_first = m_last = NULL; +} + +// Delete entries only +template +inline void MxList::Empty() +{ + MxListEntry* next; + for (MxListEntry* t = m_first; t; t = next) { + next = t->GetNext(); + delete t; + } + + this->m_count = 0; + m_first = m_last = NULL; } template diff --git a/LEGO1/omni/include/mxrectlist.h b/LEGO1/omni/include/mxrectlist.h index 88cffa9f..c4be8dcd 100644 --- a/LEGO1/omni/include/mxrectlist.h +++ b/LEGO1/omni/include/mxrectlist.h @@ -5,85 +5,157 @@ #include "mxrect32.h" // VTABLE: LEGO1 0x100dc3f0 +// VTABLE: BETA10 0x101c1fb8 // SIZE 0x18 class MxRectList : public MxPtrList { public: + // FUNCTION: BETA10 0x1013b980 MxRectList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} }; // VTABLE: LEGO1 0x100dc438 +// VTABLE: BETA10 0x101c2048 // class MxListCursor // VTABLE: LEGO1 0x100dc408 +// VTABLE: BETA10 0x101c2030 // class MxPtrListCursor // VTABLE: LEGO1 0x100dc420 +// VTABLE: BETA10 0x101c2018 class MxRectListCursor : public MxPtrListCursor { public: + // FUNCTION: BETA10 0x1013bf10 MxRectListCursor(MxRectList* p_list) : MxPtrListCursor(p_list) {} }; // VTABLE: LEGO1 0x100dc3d8 +// VTABLE: BETA10 0x101c1fd0 // class MxPtrList // VTABLE: LEGO1 0x100dc450 +// VTABLE: BETA10 0x101c1fe8 // class MxList // VTABLE: LEGO1 0x100dc468 +// VTABLE: BETA10 0x101c2000 // class MxCollection // TEMPLATE: LEGO1 0x100b3c00 +// TEMPLATE: BETA10 0x1013ba00 // MxCollection::Compare // TEMPLATE: LEGO1 0x100b3c10 +// TEMPLATE: BETA10 0x1013bb30 // MxCollection::MxCollection // TEMPLATE: LEGO1 0x100b3c80 +// TEMPLATE: BETA10 0x1013bbc0 // MxCollection::~MxCollection // TEMPLATE: LEGO1 0x100b3cd0 +// TEMPLATE: BETA10 0x1013bc60 // MxCollection::Destroy // TEMPLATE: LEGO1 0x100b3ce0 +// TEMPLATE: BETA10 0x1013bc70 // MxList::~MxList // TEMPLATE: LEGO1 0x100b3d70 +// TEMPLATE: BETA10 0x1013bd20 // MxPtrList::Destroy // SYNTHETIC: LEGO1 0x100b3d80 +// SYNTHETIC: BETA10 0x1013bd50 // MxRectList::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100b3df0 +// TEMPLATE: BETA10 0x1013bd90 // MxPtrList::~MxPtrList // SYNTHETIC: LEGO1 0x100b3e40 +// SYNTHETIC: BETA10 0x1013bdf0 // MxCollection::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100b3eb0 +// SYNTHETIC: BETA10 0x1013be30 // MxList::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100b3f60 +// SYNTHETIC: BETA10 0x1013be70 // MxPtrList::`scalar deleting destructor' -// TEMPLATE: LEGO1 0x100b3fd0 +// SYNTHETIC: LEGO1 0x100b3fd0 +// SYNTHETIC: BETA10 0x1013beb0 // MxRectList::~MxRectList // SYNTHETIC: LEGO1 0x100b4020 +// SYNTHETIC: BETA10 0x1013c0a0 // MxRectListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100b4090 +// TEMPLATE: BETA10 0x1013c0e0 // MxPtrListCursor::~MxPtrListCursor // SYNTHETIC: LEGO1 0x100b40e0 +// SYNTHETIC: BETA10 0x1013c140 // MxListCursor::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100b4150 +// SYNTHETIC: BETA10 0x1013c180 // MxPtrListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100b41c0 +// TEMPLATE: BETA10 0x1013c1c0 // MxListCursor::~MxListCursor -// TEMPLATE: LEGO1 0x100b4210 +// SYNTHETIC: LEGO1 0x100b4210 +// SYNTHETIC: BETA10 0x1013c220 // MxRectListCursor::~MxRectListCursor +// TEMPLATE: BETA10 0x1013ba20 +// MxPtrList::MxPtrList + +// TEMPLATE: BETA10 0x1013baa0 +// MxList::MxList + +// TEMPLATE: BETA10 0x1013bc30 +// MxCollection::SetDestroy + +// TEMPLATE: BETA10 0x1013bce0 +// MxPtrList::SetOwnership + +// TEMPLATE: BETA10 0x1013bf90 +// MxPtrListCursor::MxPtrListCursor + +// TEMPLATE: BETA10 0x1013c010 +// MxListCursor::MxListCursor + +// TEMPLATE: BETA10 0x1013c3c0 +// MxList::DeleteAll + +// TEMPLATE: BETA10 0x1013c450 +// MxListCursor::Next + +// TEMPLATE: BETA10 0x1013c610 +// MxListEntry::GetNext + +// TEMPLATE: BETA10 0x1013c630 +// MxListEntry::GetValue + +// TEMPLATE: BETA10 0x10152860 +// MxList::Append + +// TEMPLATE: BETA10 0x10152890 +// MxList::InsertEntry + +// TEMPLATE: BETA10 0x10152980 +// MxListEntry::MxListEntry + +// TEMPLATE: BETA10 0x101529c0 +// MxListEntry::SetPrev + +// TEMPLATE: BETA10 0x101529f0 +// MxListEntry::SetNext + #endif // MXRECTLIST_H diff --git a/LEGO1/omni/include/mxregionlist.h b/LEGO1/omni/include/mxregionlist.h index 0852feda..3fc220ff 100644 --- a/LEGO1/omni/include/mxregionlist.h +++ b/LEGO1/omni/include/mxregionlist.h @@ -27,33 +27,43 @@ struct MxRegionLeftRight { }; // VTABLE: LEGO1 0x100dcc40 +// VTABLE: BETA10 0x101c2628 // class MxCollection // VTABLE: LEGO1 0x100dcc58 +// VTABLE: BETA10 0x101c2610 // class MxList // VTABLE: LEGO1 0x100dcc70 +// VTABLE: BETA10 0x101c25f8 // class MxPtrList // VTABLE: LEGO1 0x100dcc88 +// VTABLE: BETA10 0x101c25e0 // SIZE 0x18 class MxRegionLeftRightList : public MxPtrList { public: + // FUNCTION: BETA10 0x1014bdd0 MxRegionLeftRightList() : MxPtrList(TRUE) {} // SYNTHETIC: LEGO1 0x100c4e90 + // SYNTHETIC: BETA10 0x1014c1a0 // MxRegionLeftRightList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dcbf8 +// VTABLE: BETA10 0x101c25b0 // class MxPtrListCursor // VTABLE: LEGO1 0x100dcc28 +// VTABLE: BETA10 0x101c25c8 // class MxListCursor // VTABLE: LEGO1 0x100dcc10 +// VTABLE: BETA10 0x101c2598 class MxRegionLeftRightListCursor : public MxPtrListCursor { public: + // FUNCTION: BETA10 0x1014ba10 MxRegionLeftRightListCursor(MxRegionLeftRightList* p_list) : MxPtrListCursor(p_list) {} }; @@ -85,28 +95,36 @@ struct MxRegionTopBottom { }; // VTABLE: LEGO1 0x100dcb10 +// VTABLE: BETA10 0x101c24f8 // class MxCollection // VTABLE: LEGO1 0x100dcb28 +// VTABLE: BETA10 0x101c24e0 // class MxList // VTABLE: LEGO1 0x100dcb40 +// VTABLE: BETA10 0x101c24c8 // class MxPtrList // VTABLE: LEGO1 0x100dcb58 +// VTABLE: BETA10 0x101c24b0 // SIZE 0x18 class MxRegionTopBottomList : public MxPtrList { public: + // FUNCTION: BETA10 0x1014abb0 MxRegionTopBottomList() : MxPtrList(TRUE) {} // SYNTHETIC: LEGO1 0x100c3410 + // SYNTHETIC: BETA10 0x1014af90 // MxRegionTopBottomList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dcb70 +// VTABLE: BETA10 0x101c2528 // class MxPtrListCursor // VTABLE: LEGO1 0x100dcba0 +// VTABLE: BETA10 0x101c2540 // class MxListCursor // TODO: The initialize list param type should be MxRegionTopBottomList, but doing that @@ -114,96 +132,127 @@ class MxRegionTopBottomList : public MxPtrList { // It also works with MxPtrList, so we'll do that until we figure this out. // VTABLE: LEGO1 0x100dcb88 +// VTABLE: BETA10 0x101c2510 class MxRegionTopBottomListCursor : public MxPtrListCursor { public: + // FUNCTION: BETA10 0x1014b470 MxRegionTopBottomListCursor(MxPtrList* p_list) : MxPtrListCursor(p_list) {} }; // TEMPLATE: LEGO1 0x100c32e0 +// TEMPLATE: BETA10 0x1014ac30 // MxCollection::Compare // TEMPLATE: LEGO1 0x100c32f0 +// TEMPLATE: BETA10 0x1014adf0 // MxCollection::~MxCollection // TEMPLATE: LEGO1 0x100c3340 +// TEMPLATE: BETA10 0x1014ae90 // MxCollection::Destroy // TEMPLATE: LEGO1 0x100c3350 +// TEMPLATE: BETA10 0x1014aea0 // MxList::~MxList // TEMPLATE: LEGO1 0x100c33e0 +// TEMPLATE: BETA10 0x1014af50 // MxPtrList::Destroy // TEMPLATE: LEGO1 0x100c3480 +// TEMPLATE: BETA10 0x1014afd0 // MxPtrList::~MxPtrList // SYNTHETIC: LEGO1 0x100c34d0 +// SYNTHETIC: BETA10 0x1014b030 // MxCollection::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100c3540 +// SYNTHETIC: BETA10 0x1014b070 // MxList::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100c35f0 +// SYNTHETIC: BETA10 0x1014b130 // MxPtrList::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100c3be0 +// SYNTHETIC: BETA10 0x1014b600 // MxRegionTopBottomListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100c3c50 +// TEMPLATE: BETA10 0x1014b640 // MxPtrListCursor::~MxPtrListCursor // SYNTHETIC: LEGO1 0x100c3ca0 +// SYNTHETIC: BETA10 0x1014b6a0 // MxListCursor::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100c3d10 +// SYNTHETIC: BETA10 0x1014b6e0 // MxPtrListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100c3d80 +// TEMPLATE: BETA10 0x1014b720 // MxListCursor::~MxListCursor // FUNCTION: LEGO1 0x100c3dd0 +// FUNCTION: BETA10 0x1014b780 // MxRegionTopBottomListCursor::~MxRegionTopBottomListCursor // SYNTHETIC: LEGO1 0x100c4790 +// SYNTHETIC: BETA10 0x1014bba0 // MxRegionLeftRightListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100c4800 +// TEMPLATE: BETA10 0x1014bbe0 // MxPtrListCursor::~MxPtrListCursor // SYNTHETIC: LEGO1 0x100c4850 +// SYNTHETIC: BETA10 0x1014bc40 // MxListCursor::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100c48c0 +// SYNTHETIC: BETA10 0x1014bc80 // MxPtrListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100c4930 +// TEMPLATE: BETA10 0x1014bcc0 // MxListCursor::~MxListCursor // TEMPLATE: LEGO1 0x100c4d80 +// TEMPLATE: BETA10 0x1014be50 // MxCollection::Compare // TEMPLATE: LEGO1 0x100c4d90 +// TEMPLATE: BETA10 0x1014c010 // MxCollection::~MxCollection // TEMPLATE: LEGO1 0x100c4de0 +// TEMPLATE: BETA10 0x1014c0b0 // MxCollection::Destroy // TEMPLATE: LEGO1 0x100c4df0 +// TEMPLATE: BETA10 0x1014c0c0 // MxList::~MxList // TEMPLATE: LEGO1 0x100c4f00 +// TEMPLATE: BETA10 0x1014c1e0 // MxPtrList::~MxPtrList // SYNTHETIC: LEGO1 0x100c4f50 +// SYNTHETIC: BETA10 0x1014c240 // MxCollection::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100c4e80 +// TEMPLATE: BETA10 0x1014c170 // MxPtrList::Destroy // SYNTHETIC: LEGO1 0x100c4fc0 +// SYNTHETIC: BETA10 0x1014c280 // MxList::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100c5070 +// SYNTHETIC: BETA10 0x1014c2c0 // MxPtrList::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100c54f0 @@ -216,15 +265,163 @@ class MxRegionTopBottomListCursor : public MxPtrListCursor { // MxListCursor::operator= // TEMPLATE: LEGO1 0x100c58c0 +// TEMPLATE: BETA10 0x1014c650 // MxList::InsertEntry // TEMPLATE: LEGO1 0x100c5970 +// TEMPLATE: BETA10 0x1014cb20 // MxList::InsertEntry // TEMPLATE: LEGO1 0x100c5a20 +// TEMPLATE: BETA10 0x1014d050 // MxListEntry::MxListEntry // TEMPLATE: LEGO1 0x100c5a40 +// TEMPLATE: BETA10 0x1014d150 // MxList::DeleteEntry +// TEMPLATE: BETA10 0x1014ac50 +// MxPtrList::MxPtrList + +// TEMPLATE: BETA10 0x1014acd0 +// MxList::MxList + +// TEMPLATE: BETA10 0x1014ad60 +// MxCollection::MxCollection + +// TEMPLATE: BETA10 0x1014ae60 +// MxCollection::SetDestroy + +// TEMPLATE: BETA10 0x1014af10 +// MxPtrList::SetOwnership + +// FUNCTION: BETA10 0x1014b170 +// MxRegionTopBottomList::~MxRegionTopBottomList + +// TEMPLATE: BETA10 0x1014b440 +// MxList::Append + +// TEMPLATE: BETA10 0x1014b4f0 +// MxPtrListCursor::MxPtrListCursor + +// TEMPLATE: BETA10 0x1014b570 +// MxListCursor::MxListCursor + +// TEMPLATE: BETA10 0x1014ba90 +// MxPtrListCursor::MxPtrListCursor + +// TEMPLATE: BETA10 0x1014bb10 +// MxListCursor::MxListCursor + +// FUNCTION: BETA10 0x1014bd20 +// MxRegionLeftRightListCursor::~MxRegionLeftRightListCursor + +// TEMPLATE: BETA10 0x1014be70 +// MxPtrList::MxPtrList + +// TEMPLATE: BETA10 0x1014bef0 +// MxList::MxList + +// TEMPLATE: BETA10 0x1014bf80 +// MxCollection::MxCollection + +// TEMPLATE: BETA10 0x1014c080 +// MxCollection::SetDestroy + +// TEMPLATE: BETA10 0x1014c130 +// MxPtrList::SetOwnership + +// FUNCTION: BETA10 0x1014c300 +// MxRegionLeftRightList::~MxRegionLeftRightList + +// TEMPLATE: BETA10 0x1014c390 +// MxList::Append + +// SYNTHETIC: BETA10 0x1014c3c0 +// MxRegionLeftRightListCursor::operator= + +// SYNTHETIC: BETA10 0x1014c3f0 +// MxPtrListCursor::operator= + +// SYNTHETIC: BETA10 0x1014c420 +// MxListCursor::operator= + +// TEMPLATE: BETA10 0x1014c740 +// MxList::DeleteAll + +// TEMPLATE: BETA10 0x1014c7d0 +// MxListCursor::First + +// TEMPLATE: BETA10 0x1014c830 +// MxListCursor::Last + +// TEMPLATE: BETA10 0x1014c890 +// MxListCursor::Next + +// TEMPLATE: BETA10 0x1014c970 +// MxListCursor::Prev + +// TEMPLATE: BETA10 0x1014c9f0 +// MxListCursor::Current + +// TEMPLATE: BETA10 0x1014ca40 +// MxListCursor::Prepend + +// TEMPLATE: BETA10 0x1014ca90 +// MxListCursor::Destroy + +// TEMPLATE: BETA10 0x1014caf0 +// MxListCursor::HasMatch + +// TEMPLATE: BETA10 0x1014cc10 +// MxList::DeleteAll + +// TEMPLATE: BETA10 0x1014cd20 +// MxListCursor::Next + +// TEMPLATE: BETA10 0x1014cda0 +// MxListCursor::Prev + +// TEMPLATE: BETA10 0x1014ce70 +// MxListCursor::Prepend + +// TEMPLATE: BETA10 0x1014cec0 +// MxListCursor::Destroy + +// TEMPLATE: BETA10 0x1014cf50 +// MxListEntry::MxListEntry + +// TEMPLATE: BETA10 0x1014cf90 +// MxListEntry::GetPrev + +// TEMPLATE: BETA10 0x1014cfb0 +// MxListEntry::SetPrev + +// TEMPLATE: BETA10 0x1014cfe0 +// MxListEntry::GetNext + +// TEMPLATE: BETA10 0x1014d000 +// MxListEntry::SetNext + +// TEMPLATE: BETA10 0x1014d030 +// MxListEntry::GetValue + +// TEMPLATE: BETA10 0x1014d090 +// MxListEntry::GetPrev + +// TEMPLATE: BETA10 0x1014d0b0 +// MxListEntry::SetPrev + +// TEMPLATE: BETA10 0x1014d0e0 +// MxListEntry::GetNext + +// TEMPLATE: BETA10 0x1014d100 +// MxListEntry::SetNext + +// TEMPLATE: BETA10 0x1014d130 +// MxListEntry::GetValue + +// TEMPLATE: BETA10 0x1014d200 +// MxList::DeleteEntry + #endif // MXREGIONLIST_H diff --git a/LEGO1/omni/include/mxstringlist.h b/LEGO1/omni/include/mxstringlist.h index 7894aabd..e8556522 100644 --- a/LEGO1/omni/include/mxstringlist.h +++ b/LEGO1/omni/include/mxstringlist.h @@ -5,56 +5,112 @@ #include "mxstring.h" // VTABLE: LEGO1 0x100dd040 +// VTABLE: BETA10 0x101c2a18 // SIZE 0x18 class MxStringList : public MxList {}; +// SYNTHETIC: BETA10 0x1015b520 +// MxStringList::MxStringList + +// SYNTHETIC: LEGO1 0x100cb860 +// SYNTHETIC: BETA10 0x1015b920 +// MxStringList::`scalar deleting destructor' + +// SYNTHETIC: BETA10 0x1015b960 +// MxStringList::~MxStringList + // VTABLE: LEGO1 0x100dd058 +// VTABLE: BETA10 0x101c2a60 // SIZE 0x10 class MxStringListCursor : public MxListCursor { public: + // FUNCTION: BETA10 0x1015ba50 MxStringListCursor(MxStringList* p_list) : MxListCursor(p_list) {} - - // SYNTHETIC: LEGO1 0x100cb860 - // MxStringList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dd010 +// VTABLE: BETA10 0x101c2a48 // class MxCollection // VTABLE: LEGO1 0x100dd028 +// VTABLE: BETA10 0x101c2a30 // class MxList // VTABLE: LEGO1 0x100dd070 +// VTABLE: BETA10 0x101c2a78 // class MxListCursor // TEMPLATE: LEGO1 0x100cb3c0 +// TEMPLATE: BETA10 0x1015b590 // MxCollection::Compare // TEMPLATE: LEGO1 0x100cb420 +// TEMPLATE: BETA10 0x1015b730 // MxCollection::~MxCollection // TEMPLATE: LEGO1 0x100cb470 +// TEMPLATE: BETA10 0x1015b7d0 // MxCollection::Destroy // TEMPLATE: LEGO1 0x100cb4c0 +// TEMPLATE: BETA10 0x1015b830 // MxList::~MxList // SYNTHETIC: LEGO1 0x100cb590 +// SYNTHETIC: BETA10 0x1015b8a0 // MxCollection::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100cb600 +// SYNTHETIC: BETA10 0x1015b8e0 // MxList::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100cbb40 +// TEMPLATE: BETA10 0x1015b9c0 // MxList::Append // TEMPLATE: LEGO1 0x100cc2d0 +// TEMPLATE: BETA10 0x1015be50 // MxList::InsertEntry // TEMPLATE: LEGO1 0x100cc3c0 +// TEMPLATE: BETA10 0x1015c180 // MxListEntry::MxListEntry // TEMPLATE: LEGO1 0x100cc450 +// TEMPLATE: BETA10 0x1015c2a0 // MxListEntry::GetValue +// TEMPLATE: BETA10 0x1015b610 +// MxList::MxList + +// TEMPLATE: BETA10 0x1015b6a0 +// MxCollection::MxCollection + +// TEMPLATE: BETA10 0x1015b7a0 +// MxCollection::SetDestroy + +// TEMPLATE: BETA10 0x1015bad0 +// MxListCursor::MxListCursor + +// TEMPLATE: BETA10 0x1015bf80 +// MxList::DeleteAll + +// TEMPLATE: BETA10 0x1015c070 +// MxListCursor::Next + +// TEMPLATE: BETA10 0x1015c220 +// MxListEntry::SetPrev + +// TEMPLATE: BETA10 0x1015c250 +// MxListEntry::GetNext + +// TEMPLATE: BETA10 0x1015c270 +// MxListEntry::SetNext + +// SYNTHETIC: BETA10 0x1015c310 +// MxListEntry::`scalar deleting destructor' + +// TEMPLATE: BETA10 0x1015c350 +// MxListEntry::~MxListEntry + #endif // MXSTRINGLIST_H diff --git a/LEGO1/omni/src/action/mxdsmultiaction.cpp b/LEGO1/omni/src/action/mxdsmultiaction.cpp index edf01c1d..0425b508 100644 --- a/LEGO1/omni/src/action/mxdsmultiaction.cpp +++ b/LEGO1/omni/src/action/mxdsmultiaction.cpp @@ -22,6 +22,7 @@ MxDSMultiAction::~MxDSMultiAction() } // FUNCTION: LEGO1 0x100ca0d0 +// FUNCTION: BETA10 0x101595ad void MxDSMultiAction::CopyFrom(MxDSMultiAction& p_dsMultiAction) { this->m_actions->DeleteAll(); diff --git a/LEGO1/omni/src/action/mxdsselectaction.cpp b/LEGO1/omni/src/action/mxdsselectaction.cpp index 0aa5f053..89eb4e9a 100644 --- a/LEGO1/omni/src/action/mxdsselectaction.cpp +++ b/LEGO1/omni/src/action/mxdsselectaction.cpp @@ -26,6 +26,7 @@ MxDSSelectAction::~MxDSSelectAction() } // FUNCTION: LEGO1 0x100cb950 +// FUNCTION: BETA10 0x1015a6ae void MxDSSelectAction::CopyFrom(MxDSSelectAction& p_dsSelectAction) { this->m_unk0x9c = p_dsSelectAction.m_unk0x9c; @@ -82,6 +83,7 @@ MxU32 MxDSSelectAction::GetSizeOnDisk() } // FUNCTION: LEGO1 0x100cbf60 +// FUNCTION: BETA10 0x1015aa30 void MxDSSelectAction::Deserialize(MxU8*& p_source, MxS16 p_unk0x24) { MxString string; diff --git a/LEGO1/omni/src/common/mxcompositepresenter.cpp b/LEGO1/omni/src/common/mxcompositepresenter.cpp index a88279ac..124d6b0a 100644 --- a/LEGO1/omni/src/common/mxcompositepresenter.cpp +++ b/LEGO1/omni/src/common/mxcompositepresenter.cpp @@ -23,6 +23,7 @@ MxCompositePresenter::~MxCompositePresenter() } // FUNCTION: LEGO1 0x100b6410 +// FUNCTION: BETA10 0x100e9d37 MxResult MxCompositePresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) { AUTOLOCK(m_criticalSection); @@ -76,6 +77,7 @@ MxResult MxCompositePresenter::StartAction(MxStreamController* p_controller, MxD } // FUNCTION: LEGO1 0x100b65e0 +// FUNCTION: BETA10 0x101375bc void MxCompositePresenter::EndAction() { AUTOLOCK(m_criticalSection); @@ -84,7 +86,7 @@ void MxCompositePresenter::EndAction() return; } - ((MxDSMultiAction*) m_action)->GetActionList()->DeleteAll(FALSE); + ((MxDSMultiAction*) m_action)->GetActionList()->Empty(); while (!m_list.empty()) { MxPresenter* presenter = m_list.front(); diff --git a/LEGO1/omni/src/video/mxregion.cpp b/LEGO1/omni/src/video/mxregion.cpp index f499d54e..f294d3a5 100644 --- a/LEGO1/omni/src/video/mxregion.cpp +++ b/LEGO1/omni/src/video/mxregion.cpp @@ -7,6 +7,7 @@ DECOMP_SIZE_ASSERT(MxRegionTopBottom, 0x0c); DECOMP_SIZE_ASSERT(MxRegionLeftRight, 0x08); // FUNCTION: LEGO1 0x100c31c0 +// FUNCTION: BETA10 0x10148f00 MxRegion::MxRegion() { m_list = new MxRegionTopBottomList; @@ -28,6 +29,7 @@ MxRegion::~MxRegion() } // FUNCTION: LEGO1 0x100c3700 +// FUNCTION: BETA10 0x1014907a void MxRegion::Reset() { m_list->DeleteAll(); @@ -35,6 +37,7 @@ void MxRegion::Reset() } // FUNCTION: LEGO1 0x100c3750 +// FUNCTION: BETA10 0x101490bd void MxRegion::VTable0x18(MxRect32& p_rect) { MxRect32 rect(p_rect); @@ -117,6 +120,7 @@ MxRegionTopBottom::MxRegionTopBottom(MxS32 p_top, MxS32 p_bottom) } // FUNCTION: LEGO1 0x100c50e0 +// FUNCTION: BETA10 0x1014a2d6 MxRegionTopBottom::MxRegionTopBottom(MxRect32& p_rect) { m_top = p_rect.GetTop(); @@ -128,6 +132,7 @@ MxRegionTopBottom::MxRegionTopBottom(MxRect32& p_rect) } // FUNCTION: LEGO1 0x100c5280 +// FUNCTION: BETA10 0x1014a3fc void MxRegionTopBottom::MergeOrExpandRegions(MxS32 p_left, MxS32 p_right) { MxRegionLeftRightListCursor a(m_leftRightList); diff --git a/LEGO1/omni/src/video/mxregioncursor.cpp b/LEGO1/omni/src/video/mxregioncursor.cpp index 7fd4ddc8..827c1947 100644 --- a/LEGO1/omni/src/video/mxregioncursor.cpp +++ b/LEGO1/omni/src/video/mxregioncursor.cpp @@ -3,6 +3,7 @@ DECOMP_SIZE_ASSERT(MxRegionCursor, 0x18); // FUNCTION: LEGO1 0x100c3f70 +// FUNCTION: BETA10 0x10149663 MxRegionCursor::MxRegionCursor(MxRegion* p_region) { m_region = p_region; From 30e9e43cda6bc94ddd5835c118dd63491d41c599 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 12 Aug 2024 09:21:18 -0700 Subject: [PATCH 04/18] Implement/match RegistrationBook::HandlePathStruct (#1084) --- LEGO1/lego/legoomni/include/isle.h | 8 +- .../lego/legoomni/include/registrationbook.h | 3 +- LEGO1/lego/legoomni/src/actors/pizza.cpp | 2 +- LEGO1/lego/legoomni/src/actors/radio.cpp | 2 +- LEGO1/lego/legoomni/src/entity/legoentity.cpp | 4 +- .../legoomni/src/entity/legonavcontroller.cpp | 2 +- LEGO1/lego/legoomni/src/entity/legoworld.cpp | 2 +- LEGO1/lego/legoomni/src/main/legomain.cpp | 4 +- .../legoomni/src/worlds/elevatorbottom.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/gasstation.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/hospital.cpp | 30 +++--- LEGO1/lego/legoomni/src/worlds/infocenter.cpp | 52 +++++------ .../legoomni/src/worlds/infocenterdoor.cpp | 6 +- LEGO1/lego/legoomni/src/worlds/isle.cpp | 40 ++++---- LEGO1/lego/legoomni/src/worlds/police.cpp | 12 +-- .../legoomni/src/worlds/registrationbook.cpp | 92 ++++++++++++++++--- LEGO1/lego/legoomni/src/worlds/score.cpp | 4 +- LEGO1/omni/include/mxentity.h | 23 +++-- 18 files changed, 182 insertions(+), 108 deletions(-) diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index 485cbf8f..5125cc3d 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -130,19 +130,19 @@ class Act1State : public LegoState { LegoNamedTexture* m_unk0x154; // 0x154 LegoNamedTexture* m_unk0x158; // 0x158 LegoNamedTexture* m_unk0x15c; // 0x15c - MxCore* m_unk0x160; // 0x160 + Helicopter* m_helicopter; // 0x160 NamedPlane m_unk0x164; // 0x164 LegoNamedTexture* m_unk0x1b0; // 0x1b0 LegoNamedTexture* m_unk0x1b4; // 0x1b4 - MxCore* m_unk0x1b8; // 0x1b8 + Jetski* m_jetski; // 0x1b8 NamedPlane m_unk0x1bc; // 0x1bc LegoNamedTexture* m_unk0x208; // 0x208 - MxCore* m_unk0x20c; // 0x20c + DuneBuggy* m_dunebuggy; // 0x20c NamedPlane m_unk0x210; // 0x210 LegoNamedTexture* m_unk0x25c; // 0x25c LegoNamedTexture* m_unk0x260; // 0x260 LegoNamedTexture* m_unk0x264; // 0x264 - MxCore* m_unk0x268; // 0x268 + RaceCar* m_racecar; // 0x268 }; // FUNCTION: LEGO1 0x10033a70 diff --git a/LEGO1/lego/legoomni/include/registrationbook.h b/LEGO1/lego/legoomni/include/registrationbook.h index 3fc73929..c405a06b 100644 --- a/LEGO1/lego/legoomni/include/registrationbook.h +++ b/LEGO1/lego/legoomni/include/registrationbook.h @@ -8,6 +8,7 @@ class MxControlPresenter; class MxEndActionNotificationParam; class MxStillPresenter; class LegoControlManagerNotificationParam; +class LegoPathStructNotificationParam; // VTABLE: LEGO1 0x100d9928 // SIZE 0x2d0 @@ -65,7 +66,7 @@ class RegistrationBook : public LegoWorld { MxLong HandleEndAction(MxEndActionNotificationParam& p_param); MxLong HandleKeyPress(MxU8 p_key); MxLong HandleControl(LegoControlManagerNotificationParam& p_param); - MxLong HandleNotification19(MxParam& p_param); + MxLong HandlePathStruct(LegoPathStructNotificationParam& p_param); void FUN_100775c0(MxS16 p_playerIndex); void WriteInfocenterLetters(MxS16); void FUN_100778c0(); diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index 1ff18396..e634891b 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -36,7 +36,7 @@ MxResult Pizza::Create(MxDSAction& p_dsAction) if (result == SUCCESS) { CreateState(); - m_skateboard = (SkateBoard*) m_world->Find(m_atom, IsleScript::c_SkateBoard_Actor); + m_skateboard = (SkateBoard*) m_world->Find(m_atomId, IsleScript::c_SkateBoard_Actor); } return result; diff --git a/LEGO1/lego/legoomni/src/actors/radio.cpp b/LEGO1/lego/legoomni/src/actors/radio.cpp index 6c3ff702..8d267d5a 100644 --- a/LEGO1/lego/legoomni/src/actors/radio.cpp +++ b/LEGO1/lego/legoomni/src/actors/radio.cpp @@ -126,7 +126,7 @@ void Radio::Stop() if (m_state->IsActive()) { LegoWorld* world = CurrentWorld(); - MxControlPresenter* presenter = (MxControlPresenter*) world->Find(world->GetAtom(), IsleScript::c_Radio_Ctl); + MxControlPresenter* presenter = (MxControlPresenter*) world->Find(world->GetAtomId(), IsleScript::c_Radio_Ctl); if (presenter) { presenter->VTable0x6c(0); diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index f18c689e..f59c83a9 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -80,8 +80,8 @@ void LegoEntity::SetWorldTransform(const Vector3& p_location, const Vector3& p_d // FUNCTION: LEGO1 0x100107e0 MxResult LegoEntity::Create(MxDSAction& p_dsAction) { - m_mxEntityId = p_dsAction.GetObjectId(); - m_atom = p_dsAction.GetAtomId(); + m_entityId = p_dsAction.GetObjectId(); + m_atomId = p_dsAction.GetAtomId(); SetWorld(); return SUCCESS; } diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index 01facf17..100d1659 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -689,7 +689,7 @@ MxLong LegoNavController::Notify(MxParam& p_param) if (world) { MxDSAction action; action.SetObjectId(1); - action.SetAtomId(world->GetAtom()); + action.SetAtomId(world->GetAtomId()); LegoOmni::GetInstance()->Start(&action); } } diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index dce201c0..fd449d52 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -608,7 +608,7 @@ MxCore* LegoWorld::Find(const MxAtomId& p_atom, MxS32 p_entityId) LegoEntity* entity; while (entityCursor.Next(entity)) { - if (entity->GetAtom() == p_atom && entity->GetEntityId() == p_entityId) { + if (entity->GetAtomId() == p_atom && entity->GetEntityId() == p_entityId) { return entity; } } diff --git a/LEGO1/lego/legoomni/src/main/legomain.cpp b/LEGO1/lego/legoomni/src/main/legomain.cpp index 62a927ff..4244c5bb 100644 --- a/LEGO1/lego/legoomni/src/main/legomain.cpp +++ b/LEGO1/lego/legoomni/src/main/legomain.cpp @@ -346,7 +346,7 @@ void LegoOmni::RemoveWorld(const MxAtomId& p_atom, MxLong p_objectId) b.Next(); if ((p_objectId == -1 || world->GetEntityId() == p_objectId) && - (!p_atom.GetInternal() || world->GetAtom() == p_atom)) { + (!p_atom.GetInternal() || world->GetAtomId() == p_atom)) { a.Detach(); delete world; } @@ -365,7 +365,7 @@ LegoWorld* LegoOmni::FindWorld(const MxAtomId& p_atom, MxS32 p_entityid) while (cursor.Next(world)) { if ((p_entityid == -1 || world->GetEntityId() == p_entityid) && - (!p_atom.GetInternal() || world->GetAtom() == p_atom)) { + (!p_atom.GetInternal() || world->GetAtomId() == p_atom)) { return world; } } diff --git a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp index 30a33b03..cfe25812 100644 --- a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp @@ -135,7 +135,7 @@ void ElevatorBottom::Enable(MxBool p_enable) // FUNCTION: LEGO1 0x10018310 MxBool ElevatorBottom::Escape() { - DeleteObjects(&m_atom, ElevbottScript::c_iica31in_PlayWav, 999); + DeleteObjects(&m_atomId, ElevbottScript::c_iica31in_PlayWav, 999); m_destLocation = LegoGameState::e_infomain; return TRUE; } diff --git a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp index c71db07c..453b0862 100644 --- a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp @@ -309,7 +309,7 @@ MxLong GasStation::HandleEndAction(MxEndActionNotificationParam& p_param) if (result == 0) { MxDSAction* action = p_param.GetAction(); - if (action->GetAtomId() == m_atom && action->GetObjectId()) { + if (action->GetAtomId() == m_atomId && action->GetObjectId()) { m_state->FUN_10006460((GarageScript::Script) action->GetObjectId()); m_unk0x106 = 0; diff --git a/LEGO1/lego/legoomni/src/worlds/hospital.cpp b/LEGO1/lego/legoomni/src/worlds/hospital.cpp index 550818f3..2bf024f2 100644 --- a/LEGO1/lego/legoomni/src/worlds/hospital.cpp +++ b/LEGO1/lego/legoomni/src/worlds/hospital.cpp @@ -227,7 +227,7 @@ MxLong Hospital::HandleKeyPress(MxS8 p_key) MxLong result = 0; if (p_key == VK_SPACE && g_unk0x100f7918 == 0) { - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); + DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); result = 1; } @@ -241,7 +241,7 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param) MxDSAction* action = p_param.GetAction(); Act1State* act1State; - if (action->GetAtomId() != m_atom) { + if (action->GetAtomId() != m_atomId) { return result; } @@ -375,7 +375,7 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param) m_unk0x128 = 1; m_destLocation = LegoGameState::e_unk31; - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); + DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); } break; @@ -384,7 +384,7 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param) m_unk0x128 = 1; m_destLocation = LegoGameState::e_infomain; - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); + DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); } break; @@ -425,7 +425,11 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param) act1State->SetUnknown18(9); m_destLocation = LegoGameState::e_unk31; - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); + DeleteObjects( + &m_atomId, + HospitalScript::c_hho002cl_RunAnim, + HospitalScript::c_hho006cl_RunAnim + ); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); } } @@ -434,7 +438,11 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param) m_hospitalState->m_unk0x08.m_unk0x00 = 11; BackgroundAudioManager()->RaiseVolume(); - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); + DeleteObjects( + &m_atomId, + HospitalScript::c_hho002cl_RunAnim, + HospitalScript::c_hho006cl_RunAnim + ); } else { switch (m_currentActorId) { @@ -558,7 +566,7 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param) switch (p_param.GetClickedObjectId()) { case HospitalScript::c_Info_Ctl: BackgroundAudioManager()->RaiseVolume(); - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); + DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); if (m_unk0x100 == 1) { m_hospitalState->m_unk0x08.m_unk0x00 = 14; @@ -572,14 +580,14 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param) m_hospitalState->m_unk0x08.m_unk0x00 = 13; m_destLocation = LegoGameState::e_infomain; - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); + DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); } break; case HospitalScript::c_Door_Ctl: - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); + DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); if (m_unk0x100 == 1) { m_hospitalState->m_unk0x08.m_unk0x00 = 15; @@ -593,7 +601,7 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param) m_hospitalState->m_unk0x08.m_unk0x00 = 13; m_destLocation = LegoGameState::e_unk31; - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); + DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); } @@ -664,7 +672,7 @@ MxResult Hospital::Tickle() // FUNCTION: LEGO1 0x10076330 MxBool Hospital::Escape() { - DeleteObjects(&m_atom, HospitalScript::c_hho002cl_RunAnim, 999); + DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, 999); m_hospitalState->m_unk0x08.m_unk0x00 = 0; m_destLocation = LegoGameState::e_infomain; diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp index d88fe79b..48e04d38 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp @@ -285,11 +285,11 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) return 1; } - if (action->GetAtomId() == m_atom && (action->GetObjectId() == InfomainScript::c_Mama_All_Movie || - action->GetObjectId() == InfomainScript::c_Papa_All_Movie || - action->GetObjectId() == InfomainScript::c_Pepper_All_Movie || - action->GetObjectId() == InfomainScript::c_Nick_All_Movie || - action->GetObjectId() == InfomainScript::c_Laura_All_Movie)) { + if (action->GetAtomId() == m_atomId && (action->GetObjectId() == InfomainScript::c_Mama_All_Movie || + action->GetObjectId() == InfomainScript::c_Papa_All_Movie || + action->GetObjectId() == InfomainScript::c_Pepper_All_Movie || + action->GetObjectId() == InfomainScript::c_Nick_All_Movie || + action->GetObjectId() == InfomainScript::c_Laura_All_Movie)) { if (m_unk0x1d4) { m_unk0x1d4--; } @@ -324,7 +324,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) MxLong result = m_radio.Notify(p_param); - if (result || (action->GetAtomId() != m_atom && action->GetAtomId() != *g_introScript)) { + if (result || (action->GetAtomId() != m_atomId && action->GetAtomId() != *g_introScript)) { return result; } @@ -614,21 +614,21 @@ void Infocenter::InitializeBitmaps() { m_radio.Initialize(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_LeftArrow_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_RightArrow_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Info_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Boat_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Race_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Pizza_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Gas_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Med_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Cop_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Mama_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Papa_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Pepper_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Nick_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Laura_Ctl))->Enable(TRUE); - ((MxPresenter*) Find(m_atom, InfomainScript::c_Radio_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_LeftArrow_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_RightArrow_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Info_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Boat_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Race_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Pizza_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Gas_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Med_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Cop_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Mama_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Papa_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Pepper_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Nick_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Laura_Ctl))->Enable(TRUE); + ((MxPresenter*) Find(m_atomId, InfomainScript::c_Radio_Ctl))->Enable(TRUE); m_mapAreas[0].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Info_A_Bitmap"); m_mapAreas[0].m_area.SetLeft(391); @@ -1120,7 +1120,7 @@ MxU8 Infocenter::HandleControl(LegoControlManagerNotificationParam& p_param) } if (characterBitmap != InfomainScript::c_noneInfomain) { - m_unk0x11c = (MxStillPresenter*) Find(m_atom, characterBitmap); + m_unk0x11c = (MxStillPresenter*) Find(m_atomId, characterBitmap); } } @@ -1241,16 +1241,16 @@ MxResult Infocenter::Tickle() m_unk0x1d6 += 100; if (m_unk0x1d6 > 3400 && m_unk0x1d6 < 3650) { - ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, m_atom.GetInternal(), 1); + ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, m_atomId.GetInternal(), 1); } else if (m_unk0x1d6 > 3650 && m_unk0x1d6 < 3900) { - ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, m_atom.GetInternal(), 0); + ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, m_atomId.GetInternal(), 0); } else if (m_unk0x1d6 > 3900 && m_unk0x1d6 < 4150) { - ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, m_atom.GetInternal(), 1); + ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, m_atomId.GetInternal(), 1); } else if (m_unk0x1d6 > 4400) { - ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, m_atom.GetInternal(), 0); + ControlManager()->FUN_100293c0(InfomainScript::c_BigInfo_Ctl, m_atomId.GetInternal(), 0); m_unk0x1d6 = 0; } } diff --git a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp index f2812ecf..4b6d7850 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp @@ -63,7 +63,7 @@ MxLong InfocenterDoor::Notify(MxParam& p_param) if (m_worldStarted) { switch (((MxNotificationParam&) p_param).GetNotification()) { case c_notificationEndAction: - if (((MxEndActionNotificationParam&) p_param).GetAction()->GetAtomId() == m_atom) { + if (((MxEndActionNotificationParam&) p_param).GetAction()->GetAtomId() == m_atomId) { BackgroundAudioManager()->RaiseVolume(); result = 1; } @@ -95,7 +95,7 @@ MxLong InfocenterDoor::HandleControl(LegoControlManagerNotificationParam& p_para MxLong result = 0; if (p_param.GetUnknown0x28() == 1) { - DeleteObjects(&m_atom, InfodoorScript::c_iic037in_PlayWav, 510); + DeleteObjects(&m_atomId, InfodoorScript::c_iic037in_PlayWav, 510); switch (p_param.GetClickedObjectId()) { case InfodoorScript::c_LeftArrow_Ctl: @@ -167,7 +167,7 @@ void InfocenterDoor::Enable(MxBool p_enable) // FUNCTION: LEGO1 0x10037cd0 MxBool InfocenterDoor::Escape() { - DeleteObjects(&m_atom, InfodoorScript::c_iic037in_PlayWav, 510); + DeleteObjects(&m_atomId, InfodoorScript::c_iic037in_PlayWav, 510); m_destLocation = LegoGameState::e_infomain; return TRUE; } diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index cc759ea8..13ea3cbf 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -894,7 +894,7 @@ void Isle::FUN_10032620() MxLong Isle::HandleTransitionEnd() { InvokeAction(Extra::e_stop, *g_isleScript, IsleScript::c_Avo917In_PlayWav, NULL); - DeleteObjects(&m_atom, IsleScript::c_Avo900Ps_PlayWav, IsleScript::c_Avo907Ps_PlayWav); + DeleteObjects(&m_atomId, IsleScript::c_Avo900Ps_PlayWav, IsleScript::c_Avo907Ps_PlayWav); if (m_destLocation != LegoGameState::e_skateboard) { m_act1state->m_unk0x018 = 0; @@ -915,7 +915,7 @@ MxLong Isle::HandleTransitionEnd() FUN_10032d30(IsleScript::c_ElevRide_Background_Bitmap, JukeboxScript::c_Elevator_Music, "LCAMZI2,90", FALSE); if (m_destLocation == LegoGameState::e_undefined) { - ((MxStillPresenter*) Find(m_atom, IsleScript::c_Meter3_Bitmap))->Enable(TRUE); + ((MxStillPresenter*) Find(m_atomId, IsleScript::c_Meter3_Bitmap))->Enable(TRUE); } break; case LegoGameState::e_elevopen: @@ -1064,7 +1064,7 @@ void Isle::FUN_10032d30( ) { if (m_act1state->m_unk0x01f) { - MxPresenter* presenter = (MxPresenter*) Find(m_atom, p_script); + MxPresenter* presenter = (MxPresenter*) Find(m_atomId, p_script); if (presenter != NULL && presenter->GetCurrentTickleState() == MxPresenter::e_repeating) { if (p_music != JukeboxScript::c_MusicTheme1) { @@ -1216,7 +1216,7 @@ MxBool Isle::Escape() m_act1state->m_elevFloor = Act1State::c_floor1; AnimationManager()->FUN_10061010(FALSE); - DeleteObjects(&m_atom, IsleScript::c_sba001bu_RunAnim, IsleScript::c_FNS018EN_Wav_518); + DeleteObjects(&m_atomId, IsleScript::c_sba001bu_RunAnim, IsleScript::c_FNS018EN_Wav_518); if (UserActor()) { if (UserActor()->GetActorId() != GameState()->GetActorId()) { @@ -1297,19 +1297,19 @@ Act1State::Act1State() : m_unk0x00c(0), m_unk0x00e(0), m_unk0x008(NULL), m_unk0x m_unk0x154 = NULL; m_unk0x158 = NULL; m_unk0x15c = NULL; - m_unk0x160 = NULL; + m_helicopter = NULL; m_unk0x1b0 = NULL; m_unk0x021 = 1; m_elevFloor = Act1State::c_floor1; m_unk0x00c = sizeOfArray(g_unk0x100f37f0); m_unk0x1b4 = NULL; - m_unk0x1b8 = NULL; + m_jetski = NULL; m_unk0x208 = NULL; - m_unk0x20c = NULL; + m_dunebuggy = NULL; m_unk0x25c = NULL; m_unk0x260 = NULL; m_unk0x264 = NULL; - m_unk0x268 = NULL; + m_racecar = NULL; SetFlag(); } @@ -1491,9 +1491,9 @@ MxBool Act1State::SetFlag() m_unk0x15c = NULL; } - if (m_unk0x160) { - delete m_unk0x160; - m_unk0x160 = NULL; + if (m_helicopter) { + delete m_helicopter; + m_helicopter = NULL; } m_unk0x164.SetName(""); @@ -1508,9 +1508,9 @@ MxBool Act1State::SetFlag() m_unk0x1b4 = NULL; } - if (m_unk0x1b8) { - delete m_unk0x1b8; - m_unk0x1b8 = NULL; + if (m_jetski) { + delete m_jetski; + m_jetski = NULL; } m_unk0x1bc.SetName(""); @@ -1520,9 +1520,9 @@ MxBool Act1State::SetFlag() m_unk0x208 = NULL; } - if (m_unk0x20c) { - delete m_unk0x20c; - m_unk0x20c = NULL; + if (m_dunebuggy) { + delete m_dunebuggy; + m_dunebuggy = NULL; } m_unk0x210.SetName(""); @@ -1542,9 +1542,9 @@ MxBool Act1State::SetFlag() m_unk0x264 = NULL; } - if (m_unk0x268) { - delete m_unk0x268; - m_unk0x268 = NULL; + if (m_racecar) { + delete m_racecar; + m_racecar = NULL; } return TRUE; diff --git a/LEGO1/lego/legoomni/src/worlds/police.cpp b/LEGO1/lego/legoomni/src/worlds/police.cpp index e5e09a1c..cf7bb0f8 100644 --- a/LEGO1/lego/legoomni/src/worlds/police.cpp +++ b/LEGO1/lego/legoomni/src/worlds/police.cpp @@ -110,7 +110,7 @@ MxLong Police::HandleControl(LegoControlManagerNotificationParam& p_param) case PoliceScript::c_LeftArrow_Ctl: case PoliceScript::c_RightArrow_Ctl: if (m_policeState->GetUnknown0x0c() == 1) { - DeleteObjects(&m_atom, PoliceScript::c_nps001ni_RunAnim, PoliceScript::c_nps002la_RunAnim); + DeleteObjects(&m_atomId, PoliceScript::c_nps001ni_RunAnim, PoliceScript::c_nps002la_RunAnim); } BackgroundAudioManager()->Stop(); @@ -119,7 +119,7 @@ MxLong Police::HandleControl(LegoControlManagerNotificationParam& p_param) break; case PoliceScript::c_Info_Ctl: if (m_policeState->GetUnknown0x0c() == 1) { - DeleteObjects(&m_atom, PoliceScript::c_nps001ni_RunAnim, PoliceScript::c_nps002la_RunAnim); + DeleteObjects(&m_atomId, PoliceScript::c_nps001ni_RunAnim, PoliceScript::c_nps002la_RunAnim); } BackgroundAudioManager()->Stop(); @@ -128,7 +128,7 @@ MxLong Police::HandleControl(LegoControlManagerNotificationParam& p_param) break; case PoliceScript::c_Door_Ctl: if (m_policeState->GetUnknown0x0c() == 1) { - DeleteObjects(&m_atom, PoliceScript::c_nps001ni_RunAnim, PoliceScript::c_nps002la_RunAnim); + DeleteObjects(&m_atomId, PoliceScript::c_nps001ni_RunAnim, PoliceScript::c_nps002la_RunAnim); } BackgroundAudioManager()->Stop(); @@ -148,7 +148,7 @@ MxLong Police::HandleEndAction(MxEndActionNotificationParam& p_param) { MxDSAction* action = p_param.GetAction(); - if (m_radio.Notify(p_param) == 0 && m_atom == action->GetAtomId()) { + if (m_radio.Notify(p_param) == 0 && m_atomId == action->GetAtomId()) { if (m_policeState->GetUnknown0x0c() == 1) { m_policeState->SetUnknown0x0c(0); return 1; @@ -166,7 +166,7 @@ MxLong Police::HandleKeyPress(LegoEventNotificationParam& p_param) MxLong result = 0; if (p_param.GetKey() == VK_SPACE && m_policeState->GetUnknown0x0c() == 1) { - DeleteObjects(&m_atom, PoliceScript::c_nps001ni_RunAnim, PoliceScript::c_nps002la_RunAnim); + DeleteObjects(&m_atomId, PoliceScript::c_nps001ni_RunAnim, PoliceScript::c_nps002la_RunAnim); m_policeState->SetUnknown0x0c(0); return 1; } @@ -193,7 +193,7 @@ void Police::Enable(MxBool p_enable) // FUNCTION: LEGO1 0x1005e790 MxBool Police::Escape() { - DeleteObjects(&m_atom, PoliceScript::c_nps001ni_RunAnim, 510); + DeleteObjects(&m_atomId, PoliceScript::c_nps001ni_RunAnim, 510); m_destLocation = LegoGameState::e_infomain; return TRUE; } diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index 430abcc7..234903bf 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -1,10 +1,18 @@ #include "registrationbook.h" +#include "copter_actions.h" +#include "dunebuggy.h" +#include "dunecar_actions.h" +#include "helicopter.h" #include "infocenter.h" +#include "isle.h" +#include "jetski.h" +#include "jetski_actions.h" #include "jukebox_actions.h" #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" +#include "legopathstruct.h" #include "misc.h" #include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" @@ -15,6 +23,8 @@ #include "mxstillpresenter.h" #include "mxtimer.h" #include "mxtransitionmanager.h" +#include "racecar.h" +#include "racecar_actions.h" #include "regbook_actions.h" #include "scripts.h" @@ -44,7 +54,7 @@ RegistrationBook::RegistrationBook() : m_registerDialogueTimer(0x80000000), m_un NotificationManager()->Register(this); - m_unk0x2c1 = 0; + m_unk0x2c1 = FALSE; m_checkboxHilite = NULL; m_checkboxSurface = NULL; m_checkboxNormal = NULL; @@ -118,7 +128,7 @@ MxLong RegistrationBook::Notify(MxParam& p_param) result = HandleControl((LegoControlManagerNotificationParam&) p_param); break; case c_notificationPathStruct: - result = HandleNotification19(p_param); + result = HandlePathStruct((LegoPathStructNotificationParam&) p_param); break; case c_notificationTransitioned: GameState()->SwitchArea(LegoGameState::e_infomain); @@ -132,13 +142,13 @@ MxLong RegistrationBook::Notify(MxParam& p_param) // FUNCTION: LEGO1 0x10077210 MxLong RegistrationBook::HandleEndAction(MxEndActionNotificationParam& p_param) { - if (p_param.GetAction()->GetAtomId() != m_atom) { + if (p_param.GetAction()->GetAtomId() != m_atomId) { return 0; } switch ((MxS32) p_param.GetAction()->GetObjectId()) { case RegbookScript::c_Textures: - m_unk0x2c1 = 0; + m_unk0x2c1 = FALSE; if (m_unk0x2b8 == 0) { TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); @@ -168,7 +178,7 @@ MxLong RegistrationBook::HandleKeyPress(MxU8 p_key) if ((key < 'A' || key > 'Z') && key != VK_BACK) { if (key == VK_SPACE) { - DeleteObjects(&m_atom, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); + DeleteObjects(&m_atomId, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); BackgroundAudioManager()->RaiseVolume(); } } @@ -217,7 +227,7 @@ MxLong RegistrationBook::HandleControl(LegoControlManagerNotificationParam& p_pa if (unk0x28 >= 1 && unk0x28 <= 28) { if (p_param.GetClickedObjectId() == RegbookScript::c_Alphabet_Ctl) { if (unk0x28 == 28) { - DeleteObjects(&m_atom, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); + DeleteObjects(&m_atomId, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { m_infocenterState->SetUnknown0x74(15); @@ -238,7 +248,7 @@ MxLong RegistrationBook::HandleControl(LegoControlManagerNotificationParam& p_pa } else { InputManager()->DisableInputProcessing(); - DeleteObjects(&m_atom, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); + DeleteObjects(&m_atomId, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); MxS16 i; for (i = 0; i < 10; i++) { @@ -278,7 +288,7 @@ void RegistrationBook::FUN_100775c0(MxS16 p_playerIndex) PlayAction(RegbookScript::c_Textures); - m_unk0x2c1 = 1; + m_unk0x2c1 = TRUE; // TOOD: structure incorrect GameState()->AddPlayer(*(LegoGameState::Username*) &m_unk0x280.m_letters); @@ -293,7 +303,7 @@ void RegistrationBook::FUN_100775c0(MxS16 p_playerIndex) PlayAction(RegbookScript::c_Textures); - m_unk0x2c1 = 1; + m_unk0x2c1 = TRUE; GameState()->SwitchPlayer(player); @@ -304,8 +314,8 @@ void RegistrationBook::FUN_100775c0(MxS16 p_playerIndex) } m_infocenterState->SetUnknown0x74(4); - if (m_unk0x2b8 == 0 && m_unk0x2c1 == 0) { - DeleteObjects(&m_atom, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); + if (m_unk0x2b8 == 0 && !m_unk0x2c1) { + DeleteObjects(&m_atomId, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); } } @@ -454,10 +464,62 @@ void RegistrationBook::Enable(MxBool p_enable) } } -// STUB: LEGO1 0x100781d0 -MxLong RegistrationBook::HandleNotification19(MxParam& p_param) +// FUNCTION: LEGO1 0x100781d0 +MxLong RegistrationBook::HandlePathStruct(LegoPathStructNotificationParam& p_param) { - return 0; + LegoPathActor* actor = NULL; + Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); + + switch (p_param.GetData()) { + case CopterScript::c_Helicopter_Actor: + actor = (LegoPathActor*) Find(m_atomId, CopterScript::c_Helicopter_Actor); + act1state->m_helicopter = (Helicopter*) actor; + if (actor != NULL) { + actor->SetAtomId(*g_copterScript); + actor->SetEntityId(CopterScript::c_Helicopter_Actor); + } + break; + case DunecarScript::c_DuneBugy_Actor: + actor = (LegoPathActor*) Find(m_atomId, DunecarScript::c_DuneBugy_Actor); + act1state->m_dunebuggy = (DuneBuggy*) actor; + if (actor != NULL) { + actor->SetAtomId(*g_dunecarScript); + actor->SetEntityId(DunecarScript::c_DuneBugy_Actor); + } + break; + case JetskiScript::c_Jetski_Actor: + actor = (LegoPathActor*) Find(m_atomId, JetskiScript::c_Jetski_Actor); + act1state->m_jetski = (Jetski*) actor; + if (actor != NULL) { + actor->SetAtomId(*g_jetskiScript); + actor->SetEntityId(JetskiScript::c_Jetski_Actor); + } + break; + case RacecarScript::c_RaceCar_Actor: + actor = (LegoPathActor*) Find(m_atomId, RacecarScript::c_RaceCar_Actor); + act1state->m_racecar = (RaceCar*) actor; + if (actor != NULL) { + actor->SetAtomId(*g_racecarScript); + actor->SetEntityId(RacecarScript::c_RaceCar_Actor); + } + break; + } + + if (actor == NULL) { + NotificationManager()->Send(this, p_param); + } + else { + RemoveActor(actor); + Remove(actor); + m_unk0x2b8--; + } + + if (m_unk0x2b8 == 0 && !m_unk0x2c1) { + DeleteObjects(&m_atomId, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + } + + return 1; } // FUNCTION: LEGO1 0x10078350 @@ -495,6 +557,6 @@ MxBool RegistrationBook::CreateSurface() // FUNCTION: LEGO1 0x100783e0 MxBool RegistrationBook::Escape() { - DeleteObjects(&m_atom, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); + DeleteObjects(&m_atomId, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); return TRUE; } diff --git a/LEGO1/lego/legoomni/src/worlds/score.cpp b/LEGO1/lego/legoomni/src/worlds/score.cpp index aba65f4a..db9a24ec 100644 --- a/LEGO1/lego/legoomni/src/worlds/score.cpp +++ b/LEGO1/lego/legoomni/src/worlds/score.cpp @@ -125,7 +125,7 @@ MxLong Score::FUN_10001510(MxEndActionNotificationParam& p_param) { MxDSAction* action = p_param.GetAction(); - if (m_atom == action->GetAtomId()) { + if (m_atomId == action->GetAtomId()) { switch (action->GetObjectId()) { case InfoscorScript::c_GoTo_HistBook: m_destLocation = LegoGameState::e_histbook; @@ -148,7 +148,7 @@ void Score::ReadyWorld() MxDSAction action; action.SetObjectId(InfoscorScript::c_nin001pr_RunAnim); - action.SetAtomId(m_atom); + action.SetAtomId(m_atomId); action.SetUnknown84(this); Start(&action); diff --git a/LEGO1/omni/include/mxentity.h b/LEGO1/omni/include/mxentity.h index 75891d75..cf16ad07 100644 --- a/LEGO1/omni/include/mxentity.h +++ b/LEGO1/omni/include/mxentity.h @@ -12,7 +12,7 @@ class MxEntity : public MxCore { public: // FUNCTION: LEGO1 0x1001d190 - MxEntity() { this->m_mxEntityId = -1; } + MxEntity() { m_entityId = -1; } // FUNCTION: LEGO1 0x1000c110 ~MxEntity() override {} @@ -31,29 +31,32 @@ class MxEntity : public MxCore { } // FUNCTION: LEGO1 0x10001070 - virtual MxResult Create(MxS32 p_id, const MxAtomId& p_atom) + virtual MxResult Create(MxS32 p_entityId, const MxAtomId& p_atomId) { - this->m_mxEntityId = p_id; - this->m_atom = p_atom; + m_entityId = p_entityId; + m_atomId = p_atomId; return SUCCESS; } // vtable+0x14 MxResult Create(MxDSAction& p_dsAction) { - m_mxEntityId = p_dsAction.GetObjectId(); - m_atom = p_dsAction.GetAtomId(); + m_entityId = p_dsAction.GetObjectId(); + m_atomId = p_dsAction.GetAtomId(); return SUCCESS; } - MxS32 GetEntityId() { return m_mxEntityId; } - MxAtomId& GetAtom() { return m_atom; } + MxS32 GetEntityId() { return m_entityId; } + MxAtomId& GetAtomId() { return m_atomId; } + + void SetEntityId(MxS32 p_entityId) { m_entityId = p_entityId; } + void SetAtomId(const MxAtomId& p_atomId) { m_atomId = p_atomId; } // SYNTHETIC: LEGO1 0x1000c210 // MxEntity::`scalar deleting destructor' protected: - MxS32 m_mxEntityId; // 0x08 - MxAtomId m_atom; // 0x0c + MxS32 m_entityId; // 0x08 + MxAtomId m_atomId; // 0x0c }; #endif // MXENTITY_H From 9555aaba748678ec8118edf43e0e0c0b4cdc66cf Mon Sep 17 00:00:00 2001 From: MS Date: Sat, 17 Aug 2024 11:56:25 -0400 Subject: [PATCH 05/18] Remove USHRT_MAX from ParseExtra functions (#1086) --- .../src/common/legoactioncontrolpresenter.cpp | 6 +++--- .../lego/legoomni/src/common/legoanimmmpresenter.cpp | 6 +++--- .../lego/legoomni/src/common/mxcontrolpresenter.cpp | 6 +++--- .../lego/legoomni/src/control/legometerpresenter.cpp | 6 +++--- .../lego/legoomni/src/entity/legoactorpresenter.cpp | 6 +++--- .../lego/legoomni/src/entity/legoentitypresenter.cpp | 6 +++--- .../lego/legoomni/src/entity/legoworldpresenter.cpp | 6 +++--- LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp | 6 +++--- LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp | 12 ++++++------ LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp | 6 +++--- LEGO1/omni/src/audio/mxwavepresenter.cpp | 6 +++--- LEGO1/omni/src/common/mxpresenter.cpp | 12 ++++++------ LEGO1/omni/src/video/mxstillpresenter.cpp | 6 +++--- 13 files changed, 45 insertions(+), 45 deletions(-) diff --git a/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp index 69ca127f..1afc9d64 100644 --- a/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp @@ -77,10 +77,10 @@ void LegoActionControlPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[1024]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; char output[1024]; if (KeyValueStringParse(output, g_strACTION, extraCopy)) { diff --git a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp index 1708460a..ed7edf34 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp @@ -241,10 +241,10 @@ void LegoAnimMMPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[1024]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; char output[1024]; if (KeyValueStringParse(output, g_strANIMMAN_ID, extraCopy)) { diff --git a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp index 70a7aece..db96f60a 100644 --- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp @@ -244,10 +244,10 @@ void MxControlPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[256]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; char output[256]; if (KeyValueStringParse(output, g_strSTYLE, extraCopy)) { diff --git a/LEGO1/lego/legoomni/src/control/legometerpresenter.cpp b/LEGO1/lego/legoomni/src/control/legometerpresenter.cpp index 398a29e9..0f45b60c 100644 --- a/LEGO1/lego/legoomni/src/control/legometerpresenter.cpp +++ b/LEGO1/lego/legoomni/src/control/legometerpresenter.cpp @@ -40,10 +40,10 @@ void LegoMeterPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[256]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; char output[256]; if (KeyValueStringParse(output, g_strTYPE, extraCopy)) { diff --git a/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp index 40cfb958..eca29d4d 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp @@ -34,10 +34,10 @@ void LegoActorPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[512]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; m_entity->ParseAction(extraCopy); } diff --git a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp index 70be36c4..ec6c402d 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp @@ -96,10 +96,10 @@ void LegoEntityPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[512]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; m_entity->ParseAction(extraCopy); } diff --git a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp index 070f05e6..cbf711ae 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp @@ -429,10 +429,10 @@ void LegoWorldPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[1024]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; char output[1024]; if (KeyValueStringParse(output, g_strWORLD, extraCopy)) { diff --git a/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp b/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp index 42366127..55f6d30c 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp @@ -122,10 +122,10 @@ void LegoPathPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[256], output[256]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; strupr(extraCopy); diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index faebd3d4..2ddf10e7 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -942,18 +942,18 @@ void LegoAnimPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[256]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; char output[256]; if (KeyValueStringParse(NULL, g_strFROM_PARENT, extraCopy) && m_compositePresenter != NULL) { m_compositePresenter->GetAction()->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + if (extraLength) { + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; } } diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index 4a2cf715..d6100be7 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -297,11 +297,11 @@ void LegoModelPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[1024], output[1024]; output[0] = '\0'; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; if (KeyValueStringParse(output, g_strAUTO_CREATE, extraCopy) != 0) { char* token = strtok(output, g_parseExtraTokens); diff --git a/LEGO1/omni/src/audio/mxwavepresenter.cpp b/LEGO1/omni/src/audio/mxwavepresenter.cpp index caac77cc..ffc7e708 100644 --- a/LEGO1/omni/src/audio/mxwavepresenter.cpp +++ b/LEGO1/omni/src/audio/mxwavepresenter.cpp @@ -331,10 +331,10 @@ void MxWavePresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[512]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; char soundValue[512]; if (KeyValueStringParse(soundValue, g_strSOUND, extraCopy)) { diff --git a/LEGO1/omni/src/common/mxpresenter.cpp b/LEGO1/omni/src/common/mxpresenter.cpp index e599f568..214f35c6 100644 --- a/LEGO1/omni/src/common/mxpresenter.cpp +++ b/LEGO1/omni/src/common/mxpresenter.cpp @@ -87,10 +87,10 @@ void MxPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[512]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; char worldValue[512]; if (KeyValueStringParse(worldValue, g_strWORLD, extraCopy)) { @@ -251,10 +251,10 @@ MxEntity* MxPresenter::CreateEntity(const char* p_defaultName) char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[512]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; KeyValueStringParse(objectName, g_strOBJECT, extraCopy); } diff --git a/LEGO1/omni/src/video/mxstillpresenter.cpp b/LEGO1/omni/src/video/mxstillpresenter.cpp index 4cae0f26..7074ae26 100644 --- a/LEGO1/omni/src/video/mxstillpresenter.cpp +++ b/LEGO1/omni/src/video/mxstillpresenter.cpp @@ -202,10 +202,10 @@ void MxStillPresenter::ParseExtra() char* extraData; m_action->GetExtra(extraLength, extraData); - if (extraLength & USHRT_MAX) { + if (extraLength) { char extraCopy[512]; - memcpy(extraCopy, extraData, extraLength & USHRT_MAX); - extraCopy[extraLength & USHRT_MAX] = '\0'; + memcpy(extraCopy, extraData, extraLength); + extraCopy[extraLength] = '\0'; char output[512]; if (KeyValueStringParse(output, g_strVISIBILITY, extraCopy)) { From 34047c0cb69602ca868dbb6bea61bd768f03bf12 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sat, 17 Aug 2024 17:59:22 +0200 Subject: [PATCH 06/18] Implement/match `LegoCarRaceActor::VTable0x6c` (#1085) * Implement/match `LegoCarRaceActor::VTable0x6c` * Rename variable --------- Co-authored-by: jonschz --- .../lego/legoomni/include/legopathboundary.h | 6 ++ .../lego/legoomni/src/paths/legopathactor.cpp | 1 + .../legoomni/src/race/legoracespecial.cpp | 89 +++++++++++++++++-- LEGO1/realtime/roi.h | 2 + 4 files changed, 93 insertions(+), 5 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legopathboundary.h b/LEGO1/lego/legoomni/include/legopathboundary.h index e8ad9dd2..f9bc970b 100644 --- a/LEGO1/lego/legoomni/include/legopathboundary.h +++ b/LEGO1/lego/legoomni/include/legopathboundary.h @@ -56,7 +56,10 @@ class LegoPathBoundary : public LegoWEGEdge { MxU32 FUN_10057fe0(LegoAnimPresenter* p_presenter); MxU32 FUN_100586e0(LegoAnimPresenter* p_presenter); + // FUNCTION: BETA10 0x1001ffb0 LegoPathActorSet& GetActors() { return m_actors; } + + // FUNCTION: BETA10 0x10082b10 LegoAnimPresenterSet& GetPresenters() { return m_presenters; } // SYNTHETIC: LEGO1 0x10047a80 @@ -170,6 +173,9 @@ class LegoPathBoundary : public LegoWEGEdge { // TEMPLATE: LEGO1 0x100589a0 // _Distance +// TEMPLATE: LEGO1 0x10081cd0 +// _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::lower_bound + // GLOBAL: LEGO1 0x100f11a4 // _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::_Nil diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 9aa817c3..e8aa7044 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -424,6 +424,7 @@ void LegoPathActor::VTable0x70(float p_time) // FUNCTION: BETA10 0x100af2f7 void LegoPathActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4) { + assert(m_boundary); m_boundary->SwitchBoundary(this, p_boundary, p_edge, p_unk0xe4); } diff --git a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp index bd6e4330..4c7d0c19 100644 --- a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp @@ -280,7 +280,7 @@ MxResult LegoCarRaceActor::VTable0x9c() return SUCCESS; } -// STUB: LEGO1 0x10081840 +// FUNCTION: LEGO1 0x10081840 // FUNCTION: BETA10 0x100cf680 MxU32 LegoCarRaceActor::VTable0x6c( LegoPathBoundary* p_boundary, @@ -291,11 +291,90 @@ MxU32 LegoCarRaceActor::VTable0x6c( Vector3& p_v3 ) { - // LegoAnimPresenterSet& presenters = p_boundary->GetPresenters(); + // STRING: LEGO1 0x100f7af4 + const char* str_rcdor = "rcdor"; - // Significant overlap with parent function -> Try to copy-paste LegoPathActor::VTable0x6c here - // and see by how much we diverge + LegoAnimPresenterSet& presenters = p_boundary->GetPresenters(); + + for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) { + if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) { + return 1; + } + } + + LegoPathActorSet& plpas = p_boundary->GetActors(); + LegoPathActorSet lpas(plpas); + + for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) { + if (plpas.end() != plpas.find(*itpa)) { + LegoPathActor* actor = *itpa; + + if (actor != this) { + LegoROI* roi = actor->GetROI(); + + if (roi != NULL && (roi->GetVisibility() || actor->GetCameraFlag())) { + if (strncmp(roi->GetName(), str_rcdor, 5) == 0) { + const CompoundObject* co = roi->GetComp(); // name verified by BETA10 0x100cf8ba + + if (co) { + assert(co->size() == 2); + + LegoROI* firstROI = (LegoROI*) co->front(); + + if (firstROI->FUN_100a9410( + p_v1, + p_v2, + p_f1, + p_f2, + p_v3, + m_collideBox && actor->GetCollideBox() + )) { + VTable0x94(actor, TRUE); + + if (actor->VTable0x94(this, FALSE) < 0) { + return 0; + } + else { + return 2; + } + } + + LegoROI* lastROI = (LegoROI*) co->back(); + + if (lastROI->FUN_100a9410( + p_v1, + p_v2, + p_f1, + p_f2, + p_v3, + m_collideBox && actor->GetCollideBox() + )) { + VTable0x94(actor, TRUE); + + if (actor->VTable0x94(this, FALSE) < 0) { + return 0; + } + else { + return 2; + } + } + } + } + else { + if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { + VTable0x94(actor, TRUE); + if (actor->VTable0x94(this, FALSE) < 0) { + return 0; + } + else { + return 2; + } + } + } + } + } + } + } - // TODO return 0; } diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h index c8c6b473..e263c5b1 100644 --- a/LEGO1/realtime/roi.h +++ b/LEGO1/realtime/roi.h @@ -110,6 +110,8 @@ class ROI { return (*lods)[i]; } int GetLODCount() const { return lods ? lods->Size() : 0; } + + // FUNCTION: BETA10 0x10027110 const CompoundObject* GetComp() const { return comp; } unsigned char GetVisibility() { return m_visible; } From 757df96c0dae77ec70a92e7ffddf6cd4f6f29dba Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sat, 17 Aug 2024 20:30:39 +0200 Subject: [PATCH 07/18] Implement/match LegoRaceMap (#1087) * Implement/match LegoRaceMap * Fix CI, address review comments --------- Co-authored-by: jonschz --- .../lego/legoomni/include/legoinputmanager.h | 2 + LEGO1/lego/legoomni/include/legomain.h | 3 + LEGO1/lego/legoomni/include/legoracemap.h | 49 +++++-- .../lego/legoomni/include/legovideomanager.h | 1 + LEGO1/lego/legoomni/src/common/misc.cpp | 2 + LEGO1/lego/legoomni/src/race/legoracemap.cpp | 123 ++++++++++++++++-- .../legoomni/src/video/legovideomanager.cpp | 22 ++++ LEGO1/omni/include/mxdsobject.h | 4 + LEGO1/omni/include/mxpresenter.h | 3 + LEGO1/omni/include/mxpresenterlist.h | 11 ++ tools/ncc/skip.yml | 1 + 11 files changed, 200 insertions(+), 21 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 545a948f..859d1a64 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -118,7 +118,9 @@ class LegoInputManager : public MxPresenter { m_unk0x336 = FALSE; } + // FUNCTION: BETA10 0x10031ba0 LegoControlManager* GetControlManager() { return m_controlManager; } + LegoWorld* GetWorld() { return m_world; } LegoCameraController* GetCamera() { return m_camera; } diff --git a/LEGO1/lego/legoomni/include/legomain.h b/LEGO1/lego/legoomni/include/legomain.h index a1c35500..75df917d 100644 --- a/LEGO1/lego/legoomni/include/legomain.h +++ b/LEGO1/lego/legoomni/include/legomain.h @@ -122,7 +122,10 @@ class LegoOmni : public MxOmni { LegoVideoManager* GetVideoManager() { return (LegoVideoManager*) m_videoManager; } LegoSoundManager* GetSoundManager() { return (LegoSoundManager*) m_soundManager; } + + // FUNCTION: BETA10 0x1009e7a0 LegoInputManager* GetInputManager() { return m_inputManager; } + LegoTextureContainer* GetTextureContainer() { return m_textureContainer; } ViewLODListManager* GetViewLODListManager() { return m_viewLODListManager; } LegoWorld* GetCurrentWorld() { return m_currentWorld; } diff --git a/LEGO1/lego/legoomni/include/legoracemap.h b/LEGO1/lego/legoomni/include/legoracemap.h index 3cbd7739..1380cd0c 100644 --- a/LEGO1/lego/legoomni/include/legoracemap.h +++ b/LEGO1/lego/legoomni/include/legoracemap.h @@ -3,10 +3,17 @@ #include "legoraceactor.h" +class MxControlPresenter; +class MxStillPresenter; + // VTABLE: LEGO1 0x100d8858 LegoRaceActor // VTABLE: LEGO1 0x100d8860 LegoAnimActor // VTABLE: LEGO1 0x100d8870 LegoPathActor // VTABLE: LEGO1 0x100d893c LegoRaceMap +// VTABLE: BETA10 0x101be4dc LegoRaceActor +// VTABLE: BETA10 0x101be4e0 LegoAnimActor +// VTABLE: BETA10 0x101be4f8 LegoPathActor +// VTABLE: BETA10 0x101be5e8 LegoRaceMap // SIZE 0x1b4 class LegoRaceMap : public virtual LegoRaceActor { public: @@ -28,17 +35,37 @@ class LegoRaceMap : public virtual LegoRaceActor { // LegoRaceMap::`scalar deleting destructor' private: - MxBool m_unk0x08; // 0x08 - void* m_unk0x0c; // 0x0c - undefined4 m_unk0x10; // 0x10 - float m_unk0x14; // 0x14 - float m_unk0x18; // 0x18 - float m_unk0x1c; // 0x1c - float m_unk0x20; // 0x20 - float m_unk0x24; // 0x24 - float m_unk0x28; // 0x28 - float m_unk0x2c; // 0x2c - undefined4 m_unk0x30; // 0x30 + MxBool m_unk0x08; // 0x08 + MxStillPresenter* m_stillPresenter; // 0x0c + + // variable name verified by BETA10 0x100ca82b + MxControlPresenter* m_Map_Ctl; // 0x10 + + // likely an x-offset of the race map in world space + float m_unk0x14; // 0x14 + // inversely scales the map in x direction (either convert world->screen space or to control the size) + float m_unk0x18; // 0x18 + // likely a y-offset of the race map in world space + float m_unk0x1c; // 0x1c + // inversely scales the map in y direction (either convert world->screen space or to control the size) + float m_unk0x20; // 0x20 + // scales the map in x direction (either convert world->screen space or to change the size) + float m_unk0x24; // 0x24 + // scales the map in y direction (either convert world->screen space or to change the size) + float m_unk0x28; // 0x28 + // likely an x-offset of the race map in screen space + float m_unk0x2c; // 0x2c + // likely a y-offset of the race map in screen space + float m_unk0x30; // 0x30 }; +// GLOBAL: LEGO1 0x100d8848 +// LegoRaceMap::`vbtable' + +// GLOBAL: LEGO1 0x100d8840 +// LegoRaceMap::`vbtable'{for `LegoAnimActor'} + +// GLOBAL: LEGO1 0x100d8830 +// LegoRaceMap::`vbtable'{for `LegoRaceActor'} + #endif // LEGORACEMAP_H diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h index 9381a055..c077422c 100644 --- a/LEGO1/lego/legoomni/include/legovideomanager.h +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -44,6 +44,7 @@ class LegoVideoManager : public MxVideoManager { void SetSkyColor(float p_red, float p_green, float p_blue); void OverrideSkyColor(MxBool p_shouldOverride); MxResult ResetPalette(MxBool p_ignoreSkyColor); + MxPresenter* GetPresenterByActionObjectName(const char* p_char); void FUN_1007c520(); diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 05dcf678..8d035c74 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -43,8 +43,10 @@ LegoInputManager* InputManager() } // FUNCTION: LEGO1 0x10015750 +// FUNCTION: BETA10 0x100e48dc LegoControlManager* ControlManager() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetInputManager()->GetControlManager(); } diff --git a/LEGO1/lego/legoomni/src/race/legoracemap.cpp b/LEGO1/lego/legoomni/src/race/legoracemap.cpp index 710e9140..950c344b 100644 --- a/LEGO1/lego/legoomni/src/race/legoracemap.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracemap.cpp @@ -1,40 +1,143 @@ #include "legoracemap.h" +#include "define.h" #include "legocontrolmanager.h" +#include "legovideomanager.h" +#include "legoworld.h" #include "misc.h" +#include "mxcontrolpresenter.h" +#include "mxstillpresenter.h" +#include "mxutilities.h" DECOMP_SIZE_ASSERT(LegoRaceMap, 0x1b4) // FUNCTION: LEGO1 0x1005d0d0 +// FUNCTION: BETA10 0x100ca2c0 LegoRaceMap::LegoRaceMap() { m_unk0x08 = FALSE; - m_unk0x0c = NULL; - m_unk0x10 = 0; + m_stillPresenter = NULL; + m_Map_Ctl = 0; ControlManager()->Register(this); } -// STUB: LEGO1 0x1005d2b0 +// FUNCTION: LEGO1 0x1005d2b0 +// FUNCTION: BETA10 0x100ca48c LegoRaceMap::~LegoRaceMap() { - // TODO + ControlManager()->Unregister(this); } -// STUB: LEGO1 0x1005d310 +// GLOBAL: LEGO1 0x1010208c +// STRING: LEGO1 0x10101f88 +const char* g_mapLocator = "MAP_LOCATOR"; + +// GLOBAL: LEGO1 0x10102090 +// STRING: LEGO1 0x10101f78 +const char* g_mapGeometry = "MAP_GEOMETRY"; + +// FUNCTION: LEGO1 0x1005d310 +// FUNCTION: BETA10 0x100ca543 void LegoRaceMap::ParseAction(char* p_extra) { - // TODO + char value[256]; + + if (KeyValueStringParse(value, g_mapLocator, p_extra)) { + // variable name verified by BETA10 0x100ca5ac + MxStillPresenter* p = (MxStillPresenter*) VideoManager()->GetPresenterByActionObjectName(value); + + assert(p); + p->Enable(FALSE); + m_stillPresenter = p; + } + + if (KeyValueStringParse(value, g_mapGeometry, p_extra)) { + char* token = strtok(value, g_parseExtraTokens); + if (token != NULL) { + m_unk0x14 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x18 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x1c = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x20 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x24 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x28 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x2c = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x30 = atof(token); + } + } + + LegoWorld* currentWorld = CurrentWorld(); + + if (currentWorld) { + // STRING: LEGO1 0x100f67bc + const char* mapCtl = "Map_Ctl"; + + m_Map_Ctl = (MxControlPresenter*) currentWorld->Find("MxControlPresenter", mapCtl); + assert(m_Map_Ctl); + } } // FUNCTION: LEGO1 0x1005d4b0 +// FUNCTION: BETA10 0x100ca849 void LegoRaceMap::FUN_1005d4b0() { - // TODO + if (m_unk0x08) { + short xPos = (GetWorldPosition()[0] - m_unk0x14) / m_unk0x18 * m_unk0x24; + short yPos = (GetWorldPosition()[2] - m_unk0x1c) / m_unk0x20 * m_unk0x28; + + m_stillPresenter->SetPosition(xPos + m_unk0x2c, m_unk0x30 - yPos); + } } -// STUB: LEGO1 0x1005d550 +// FUNCTION: LEGO1 0x1005d550 +// FUNCTION: BETA10 0x100ca92d MxLong LegoRaceMap::Notify(MxParam& p_param) { - // TODO - return 0; + if (!m_stillPresenter) { + return 1; + } + + if (((MxNotificationParam&) p_param).GetNotification() == c_notificationControl && + m_Map_Ctl->GetAction()->GetObjectId() == + ((LegoControlManagerNotificationParam&) p_param).GetClickedObjectId()) { + + if (((LegoControlManagerNotificationParam&) p_param).GetUnknown0x28() == 1) { + m_unk0x08 = TRUE; + FUN_1005d4b0(); + m_stillPresenter->Enable(TRUE); + } + else { + m_unk0x08 = FALSE; + m_stillPresenter->Enable(FALSE); + } + } + + return 1; } diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 21147b1f..9a41de96 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -409,6 +409,28 @@ MxPresenter* LegoVideoManager::GetPresenterAt(MxS32 p_x, MxS32 p_y) return NULL; } +// FUNCTION: LEGO1 0x1007c180 +// FUNCTION: BETA10 0x100d6df4 +MxPresenter* LegoVideoManager::GetPresenterByActionObjectName(const char* p_actionObjectName) +{ + MxPresenterListCursor cursor(m_presenters); + MxPresenter* presenter; + + while (TRUE) { + if (!cursor.Prev(presenter)) { + return NULL; + } + + if (!presenter->GetAction()) { + continue; + } + + if (strcmpi(presenter->GetAction()->GetObjectName(), p_actionObjectName) == 0) { + return presenter; + } + } +} + // FUNCTION: LEGO1 0x1007c290 MxResult LegoVideoManager::RealizePalette(MxPalette* p_pallete) { diff --git a/LEGO1/omni/include/mxdsobject.h b/LEGO1/omni/include/mxdsobject.h index e291d7d9..3bb0a3ff 100644 --- a/LEGO1/omni/include/mxdsobject.h +++ b/LEGO1/omni/include/mxdsobject.h @@ -63,8 +63,12 @@ class MxDSObject : public MxCore { // FUNCTION: BETA10 0x1012efb0 const char* GetSourceName() const { return m_sourceName; } + // FUNCTION: BETA10 0x10028460 const char* GetObjectName() const { return m_objectName; } + + // FUNCTION: BETA10 0x10017910 MxU32 GetObjectId() { return m_objectId; } + const MxAtomId& GetAtomId() { return m_atomId; } MxS16 GetUnknown24() { return m_unk0x24; } MxPresenter* GetUnknown28() { return m_unk0x28; } diff --git a/LEGO1/omni/include/mxpresenter.h b/LEGO1/omni/include/mxpresenter.h index 15323d2f..a30897d1 100644 --- a/LEGO1/omni/include/mxpresenter.h +++ b/LEGO1/omni/include/mxpresenter.h @@ -123,7 +123,10 @@ class MxPresenter : public MxCore { MxS32 GetX() const { return this->m_location.GetX(); } MxS32 GetY() const { return this->m_location.GetY(); } MxS32 GetDisplayZ() const { return this->m_displayZ; } + + // FUNCTION: BETA10 0x10028430 MxDSAction* GetAction() const { return this->m_action; } + void SetAction(MxDSAction* p_action) { m_action = p_action; } void SetCompositePresenter(MxCompositePresenter* p_compositePresenter) diff --git a/LEGO1/omni/include/mxpresenterlist.h b/LEGO1/omni/include/mxpresenterlist.h index 87430a53..34714def 100644 --- a/LEGO1/omni/include/mxpresenterlist.h +++ b/LEGO1/omni/include/mxpresenterlist.h @@ -30,8 +30,10 @@ class MxPresenterList : public MxPtrList { // class MxPtrListCursor // VTABLE: LEGO1 0x100d6470 +// SIZE 0x10 class MxPresenterListCursor : public MxPtrListCursor { public: + // FUNCTION: BETA10 0x1007d130 MxPresenterListCursor(MxPresenterList* p_list) : MxPtrListCursor(p_list) {} }; @@ -98,4 +100,13 @@ class MxPresenterListCursor : public MxPtrListCursor { // TEMPLATE: LEGO1 0x100225e0 // MxList::DeleteEntry +// TEMPLATE: BETA10 0x1007d1d0 +// MxPtrListCursor::MxPtrListCursor + +// TEMPLATE: BETA10 0x1007d270 +// MxListCursor::MxListCursor + +// TEMPLATE: BETA10 0x100d9420 +// MxListCursor::Prev + #endif // MXPRESENTERLIST_H diff --git a/tools/ncc/skip.yml b/tools/ncc/skip.yml index 46229e07..6062e7b1 100644 --- a/tools/ncc/skip.yml +++ b/tools/ncc/skip.yml @@ -30,3 +30,4 @@ i_activity: "Allow original naming from beta" i_actor: "Allow original naming from beta" score: "Allow original naming from beta" c_LOCATIONS_NUM: "Allow original naming from beta" +m_Map_Ctl: "Allow original naming from beta" From b6499025781dc621f525028be5bd914d2d4f7ee5 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:42:49 +0200 Subject: [PATCH 08/18] Various fixes in constructors (#1089) * Various fixes in constructors * Address review comment --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/legocarbuild.h | 6 ++++ LEGO1/lego/legoomni/include/legojetski.h | 17 ++++++++- .../legoomni/include/legojetskiraceactor.h | 6 ++++ LEGO1/lego/legoomni/include/legorace.h | 8 +++++ LEGO1/lego/legoomni/include/legoracers.h | 12 +++++++ LEGO1/lego/legoomni/include/legoracespecial.h | 3 ++ .../lego/legoomni/src/build/legocarbuild.cpp | 36 +++++++++++++++++++ LEGO1/lego/legoomni/src/entity/legojetski.cpp | 4 +-- LEGO1/lego/legoomni/src/race/legorace.cpp | 19 ++++++++-- 9 files changed, 106 insertions(+), 5 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index e333c1e8..4312c52b 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -82,6 +82,12 @@ class LegoCarBuild : public LegoWorld { MxBool VTable0x5c() override; // vtable+0x5c MxBool Escape() override; // vtable+0x64 void Enable(MxBool p_enable) override; // vtable+0x68 + virtual void VTable0x6c(); // vtable+0x6c + virtual void VTable0x70(); // vtable+0x70 + virtual void VTable0x74(); // vtable+0x74 + virtual void VTable0x78(); // vtable+0x78 + virtual void VTable0x7c(); // vtable+0x7c + virtual void VTable0x80(); // vtable+0x80 // SYNTHETIC: LEGO1 0x10022a60 // LegoCarBuild::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legojetski.h b/LEGO1/lego/legoomni/include/legojetski.h index 8559cac7..56057da2 100644 --- a/LEGO1/lego/legoomni/include/legojetski.h +++ b/LEGO1/lego/legoomni/include/legojetski.h @@ -4,7 +4,7 @@ #include "legojetskiraceactor.h" #include "legoracemap.h" -// VTABLE: LEGO1 0x100d5a08 LegoJetskiRaceActor +// VTABLE: LEGO1 0x100d5a08 LegoCarRaceActor // VTABLE: LEGO1 0x100d5a28 LegoRaceActor // VTABLE: LEGO1 0x100d5a30 LegoAnimActor // VTABLE: LEGO1 0x100d5a40 LegoPathActor @@ -52,4 +52,19 @@ class LegoJetski : public LegoJetskiRaceActor, public LegoRaceMap { // LegoJetski::`scalar deleting destructor' }; +// GLOBAL: LEGO1 0x100d59b8 +// LegoJetski::`vbtable'{for `LegoCarRaceActor'} + +// GLOBAL: LEGO1 0x100d59c8 +// LegoJetski::`vbtable'{for `LegoRaceActor'} + +// GLOBAL: LEGO1 0x100d59d8 +// LegoJetski::`vbtable'{for `LegoAnimActor'} + +// GLOBAL: LEGO1 0x100d59e0 +// LegoJetski::`vbtable' + +// GLOBAL: LEGO1 0x100d59f0 +// LegoJetski::`vbtable'{for `LegoJetskiRaceActor'} + #endif // LEGOJETSKI_H diff --git a/LEGO1/lego/legoomni/include/legojetskiraceactor.h b/LEGO1/lego/legoomni/include/legojetskiraceactor.h index 2f5b3d19..e2689968 100644 --- a/LEGO1/lego/legoomni/include/legojetskiraceactor.h +++ b/LEGO1/lego/legoomni/include/legojetskiraceactor.h @@ -36,8 +36,14 @@ class LegoJetskiRaceActor : public virtual LegoCarRaceActor { void VTable0x70(float p_float) override; // vtable+0x70 MxS32 VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge) override; // vtable+0x1c + // SYNTHETIC: LEGO1 0x10013a80 + // LegoJetskiRaceActor::`vbase destructor' + // SYNTHETIC: LEGO1 0x10081d50 // LegoJetskiRaceActor::`scalar deleting destructor' + + // SYNTHETIC: LEGO1 0x10013ba0 + // LegoJetskiRaceActor::~LegoJetskiRaceActor }; #endif // LEGOJETSKIRACEACTOR_H diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h index 6bc7dde3..ff463538 100644 --- a/LEGO1/lego/legoomni/include/legorace.h +++ b/LEGO1/lego/legoomni/include/legorace.h @@ -23,6 +23,14 @@ class RaceState : public LegoState { // SIZE 0x06 struct Entry { public: + // FUNCTION: LEGO1 0x10016000 + Entry() + { + m_id = 0; + m_unk0x02 = 0; + m_score = 0; + } + MxS16 GetUnknown0x02() { return m_unk0x02; } MxS16 GetHighScore() { return m_score; } diff --git a/LEGO1/lego/legoomni/include/legoracers.h b/LEGO1/lego/legoomni/include/legoracers.h index 7e207ef8..ea8472d1 100644 --- a/LEGO1/lego/legoomni/include/legoracers.h +++ b/LEGO1/lego/legoomni/include/legoracers.h @@ -115,3 +115,15 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { }; #endif // LEGORACERS_H + +// GLOBAL: LEGO1 0x100d5890 +// LegoRaceCar::`vbtable'{for `LegoCarRaceActor'} + +// GLOBAL: LEGO1 0x100d5880 +// LegoRaceCar::`vbtable'{for `LegoRaceMap'} + +// GLOBAL: LEGO1 0x100d5878 +// LegoRaceCar::`vbtable'{for `LegoAnimActor'} + +// GLOBAL: LEGO1 0x100d5868 +// LegoRaceCar::`vbtable'{for `LegoRaceActor'} diff --git a/LEGO1/lego/legoomni/include/legoracespecial.h b/LEGO1/lego/legoomni/include/legoracespecial.h index a85a967f..76245493 100644 --- a/LEGO1/lego/legoomni/include/legoracespecial.h +++ b/LEGO1/lego/legoomni/include/legoracespecial.h @@ -72,6 +72,9 @@ class LegoCarRaceActor : public virtual LegoRaceActor { // SYNTHETIC: LEGO1 0x10081620 // LegoCarRaceActor::`scalar deleting destructor' + // SYNTHETIC: LEGO1 0x10012d80 + // LegoCarRaceActor::~LegoCarRaceActor + protected: MxFloat m_unk0x08; // 0x08 MxU8 m_unk0x0c; // 0x0c diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 3eae3094..e5d2c381 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -28,6 +28,42 @@ MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) return SUCCESS; } +// STUB: LEGO1 0x10022fc0 +void LegoCarBuild::VTable0x6c() +{ + // TODO +} + +// STUB: LEGO1 0x10023020 +void LegoCarBuild::VTable0x70() +{ + // TODO +} + +// STUB: LEGO1 0x10023500 +void LegoCarBuild::VTable0x74() +{ + // TODO +} + +// STUB: LEGO1 0x10023570 +void LegoCarBuild::VTable0x78() +{ + // TODO +} + +// STUB: LEGO1 0x10023620 +void LegoCarBuild::VTable0x7c() +{ + // TODO +} + +// STUB: LEGO1 0x100236a0 +void LegoCarBuild::VTable0x80() +{ + // TODO +} + // STUB: LEGO1 0x100238b0 MxResult LegoCarBuild::Tickle() { diff --git a/LEGO1/lego/legoomni/src/entity/legojetski.cpp b/LEGO1/lego/legoomni/src/entity/legojetski.cpp index 42a7ed5b..5ad8524d 100644 --- a/LEGO1/lego/legoomni/src/entity/legojetski.cpp +++ b/LEGO1/lego/legoomni/src/entity/legojetski.cpp @@ -36,10 +36,10 @@ LegoJetski::LegoJetski() NotificationManager()->Register(this); } -// STUB: LEGO1 0x10013aa0 +// FUNCTION: LEGO1 0x10013aa0 LegoJetski::~LegoJetski() { - // TODO + NotificationManager()->Unregister(this); } // STUB: LEGO1 0x10013bb0 diff --git a/LEGO1/lego/legoomni/src/race/legorace.cpp b/LEGO1/lego/legoomni/src/race/legorace.cpp index 2113be16..f4cad9d0 100644 --- a/LEGO1/lego/legoomni/src/race/legorace.cpp +++ b/LEGO1/lego/legoomni/src/race/legorace.cpp @@ -128,10 +128,25 @@ void LegoRace::Enable(MxBool p_enable) LegoWorld::Enable(p_enable); } -// STUB: LEGO1 0x10015f30 +// FUNCTION: LEGO1 0x10015f30 RaceState::RaceState() { - // TODO + m_state[0].m_id = 1; + m_state[0].m_unk0x02 = 0; + m_state[0].m_score = 0; + m_state[1].m_id = 2; + m_state[1].m_unk0x02 = 0; + m_state[1].m_score = 0; + m_state[2].m_id = 3; + m_state[2].m_unk0x02 = 0; + m_state[2].m_score = 0; + m_state[3].m_id = 4; + m_state[3].m_unk0x02 = 0; + m_state[3].m_score = 0; + m_state[4].m_id = 5; + m_state[4].m_unk0x02 = 0; + m_state[4].m_score = 0; + m_unk0x28 = 0; } // FUNCTION: LEGO1 0x10016140 From 1b46859cf6ea3cfc64812e1d8ead990645c319b2 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:30:27 +0200 Subject: [PATCH 09/18] Implement `RaceSkel`, add BETA10 annotations (#1088) * Implement `RaceSkel`, add BETA10 annotations * fix formatting * Fix order * Address some review comments --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/carrace.h | 9 +++- LEGO1/lego/legoomni/include/legoanimactor.h | 6 +++ LEGO1/lego/legoomni/include/legoextraactor.h | 1 + .../lego/legoomni/include/legoobjectfactory.h | 1 + LEGO1/lego/legoomni/include/raceskel.h | 19 ++++++-- .../legoomni/src/common/legoobjectfactory.cpp | 5 +++ LEGO1/lego/legoomni/src/entity/legoworld.cpp | 1 + .../lego/legoomni/src/paths/legoanimactor.cpp | 26 ++++++++--- LEGO1/lego/legoomni/src/race/carrace.cpp | 2 +- LEGO1/lego/legoomni/src/race/legoracers.cpp | 3 +- LEGO1/lego/legoomni/src/race/raceskel.cpp | 44 ++++++++++++++++++- LEGO1/lego/sources/roi/legoroi.h | 1 + LEGO1/mxgeometry/mxgeometry3d.h | 1 + LEGO1/omni/include/mxobjectfactory.h | 1 + LEGO1/omni/src/common/mxobjectfactory.cpp | 2 + 15 files changed, 104 insertions(+), 18 deletions(-) diff --git a/LEGO1/lego/legoomni/include/carrace.h b/LEGO1/lego/legoomni/include/carrace.h index 954c1326..38a6e77a 100644 --- a/LEGO1/lego/legoomni/include/carrace.h +++ b/LEGO1/lego/legoomni/include/carrace.h @@ -4,6 +4,8 @@ #include "decomp.h" #include "legorace.h" +class RaceSkel; + // VTABLE: LEGO1 0x100d4b70 // VTABLE: BETA10 0x101bd5f0 // SIZE 0x2c @@ -59,14 +61,17 @@ class CarRace : public LegoRace { MxLong HandleType0Notification(MxNotificationParam&) override; // vtable+0x78 // FUNCTION: BETA10 0x100cd060 - undefined4 GetUnk0x150() { return m_unk0x150; } + RaceSkel* GetSkeleton() { return m_skeleton; } + + // FUNCTION: BETA10 0x100f16f0 + void SetSkeleton(RaceSkel* p_skeleton) { m_skeleton = p_skeleton; } // SYNTHETIC: LEGO1 0x10016c70 // CarRace::`scalar deleting destructor' private: undefined m_unk0x144[12]; // 0x144 - undefined4 m_unk0x150; // 0x150 + RaceSkel* m_skeleton; // 0x150 }; #endif // CARRACE_H diff --git a/LEGO1/lego/legoomni/include/legoanimactor.h b/LEGO1/lego/legoomni/include/legoanimactor.h index 72f6bc1c..f74e8c00 100644 --- a/LEGO1/lego/legoomni/include/legoanimactor.h +++ b/LEGO1/lego/legoomni/include/legoanimactor.h @@ -28,13 +28,18 @@ struct LegoAnimActorStruct { // VTABLE: LEGO1 0x100d5440 LegoPathActor // VTABLE: LEGO1 0x100d5510 LegoAnimActor +// VTABLE: BETA10 0x101b81d8 LegoPathActor +// VTABLE: BETA10 0x101b82c8 LegoAnimActor // SIZE 0x174 class LegoAnimActor : public virtual LegoPathActor { public: + // FUNCTION: BETA10 0x1000f6c0 LegoAnimActor() { m_curAnim = -1; } + ~LegoAnimActor() override; // FUNCTION: LEGO1 0x1000fba0 + // FUNCTION: BETA10 0x10012400 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f057c @@ -42,6 +47,7 @@ class LegoAnimActor : public virtual LegoPathActor { } // FUNCTION: LEGO1 0x1000fbc0 + // FUNCTION: BETA10 0x10012440 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoAnimActor::ClassName()) || LegoPathActor::IsA(p_name); diff --git a/LEGO1/lego/legoomni/include/legoextraactor.h b/LEGO1/lego/legoomni/include/legoextraactor.h index d933ff44..dfb880f8 100644 --- a/LEGO1/lego/legoomni/include/legoextraactor.h +++ b/LEGO1/lego/legoomni/include/legoextraactor.h @@ -6,6 +6,7 @@ // VTABLE: LEGO1 0x100d6c00 LegoAnimActor // VTABLE: LEGO1 0x100d6c10 LegoPathActor // VTABLE: LEGO1 0x100d6cdc LegoExtraActor +// VTABLE: BETA10 0x101bc2b8 LegoAnimActor // SIZE 0x1dc class LegoExtraActor : public virtual LegoAnimActor { public: diff --git a/LEGO1/lego/legoomni/include/legoobjectfactory.h b/LEGO1/lego/legoomni/include/legoobjectfactory.h index e77cb802..4cb450be 100644 --- a/LEGO1/lego/legoomni/include/legoobjectfactory.h +++ b/LEGO1/lego/legoomni/include/legoobjectfactory.h @@ -106,6 +106,7 @@ X(AnimState) // VTABLE: LEGO1 0x100d4768 +// VTABLE: BETA10 0x101bccd8 // SIZE 0x1c8 class LegoObjectFactory : public MxObjectFactory { public: diff --git a/LEGO1/lego/legoomni/include/raceskel.h b/LEGO1/lego/legoomni/include/raceskel.h index fca57dde..48830bea 100644 --- a/LEGO1/lego/legoomni/include/raceskel.h +++ b/LEGO1/lego/legoomni/include/raceskel.h @@ -3,19 +3,30 @@ #include "legoanimactor.h" -/* - VTABLE: LEGO1 0x100d7668 LegoPathActor - VTABLE: LEGO1 0x100d7738 LegoAnimActor -*/ +// VTABLE: LEGO1 0x100d93f8 LegoPathActor +// VTABLE: LEGO1 0x100d94c8 LegoAnimActor +// VTABLE: BETA10 0x101bf9d0 LegoPathActor +// VTABLE: BETA10 0x101bfac0 LegoAnimActor // SIZE 0x178 class RaceSkel : public LegoAnimActor { public: RaceSkel(); + ~RaceSkel() override; + + void ParseAction(char* p_extra) override; // vtable+0x20 + + MxResult FUN_1001c360(float p_und, Matrix4& p_transform) override; void GetCurrentAnimData(float* p_outCurAnimPosition, float* p_outCurAnimDuration); + // SYNTHETIC: LEGO1 0x10071cf0 + // RaceSkel::`scalar deleting destructor' + private: float m_animPosition; // 0x1c }; +// GLOBAL: LEGO1 0x100d93f0 +// RaceSkel::`vbtable' + #endif // RACESKEL_H diff --git a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp index 4eebe624..0c4a7314 100644 --- a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp +++ b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp @@ -184,6 +184,7 @@ LegoObjectFactory::LegoObjectFactory() } // FUNCTION: LEGO1 0x10009a90 +// FUNCTION: BETA10 0x100a1021 MxCore* LegoObjectFactory::Create(const char* p_name) { MxCore* object = NULL; @@ -491,6 +492,10 @@ MxCore* LegoObjectFactory::Create(const char* p_name) object = MxObjectFactory::Create(p_name); } + // clang-format off + assert(object!=NULL); + // clang-format on + return object; } diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index fd449d52..b8cdc37e 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -541,6 +541,7 @@ void LegoWorld::Remove(MxCore* p_object) } // FUNCTION: LEGO1 0x100213a0 +// FUNCTION: BETA10 0x100db027 MxCore* LegoWorld::Find(const char* p_class, const char* p_name) { if (!strcmp(p_class, "MxControlPresenter")) { diff --git a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp index eaad8ba9..a8180af8 100644 --- a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp @@ -37,6 +37,7 @@ float LegoAnimActorStruct::GetDuration() } // FUNCTION: LEGO1 0x1001c140 +// FUNCTION: BETA10 0x1003dfe4 LegoAnimActor::~LegoAnimActor() { for (MxS32 i = 0; i < m_animMaps.size(); i++) { @@ -89,9 +90,12 @@ void LegoAnimActor::VTable0x70(float p_float) } // FUNCTION: LEGO1 0x1001c360 +// FUNCTION: BETA10 0x1003e2d3 MxResult LegoAnimActor::FUN_1001c360(float p_und, Matrix4& p_transform) { if (p_und >= 0) { + assert((m_curAnim >= 0) && (m_curAnim < m_animMaps.size())); + LegoROI** roiMap = m_animMaps[m_curAnim]->m_roiMap; MxU32 numROIs = m_animMaps[m_curAnim]->m_numROIs; @@ -108,7 +112,11 @@ MxResult LegoAnimActor::FUN_1001c360(float p_und, Matrix4& p_transform) } } else { - LegoTreeNode* root = m_animMaps[m_curAnim]->m_AnimTreePtr->GetRoot(); + // name verified by BETA10 0x1003e407 + LegoTreeNode* n = m_animMaps[m_curAnim]->m_AnimTreePtr->GetRoot(); + + assert(roiMap && n && m_roi && m_boundary); + m_roi->SetVisibility(TRUE); for (MxU32 i = 0; i < numROIs; i++) { @@ -119,8 +127,8 @@ MxResult LegoAnimActor::FUN_1001c360(float p_und, Matrix4& p_transform) } } - for (MxS32 j = 0; j < root->GetNumChildren(); j++) { - LegoROI::FUN_100a8e80(root->GetChild(j), p_transform, p_und, roiMap); + for (MxS32 j = 0; j < n->GetNumChildren(); j++) { + LegoROI::FUN_100a8e80(n->GetChild(j), p_transform, p_und, roiMap); } if (m_cameraFlag) { @@ -192,6 +200,7 @@ void LegoAnimActor::SetWorldSpeed(MxFloat p_worldSpeed) } // FUNCTION: LEGO1 0x1001c920 +// FUNCTION: BETA10 0x1003e914 void LegoAnimActor::ParseAction(char* p_extra) { LegoPathActor::ParseAction(p_extra); @@ -201,17 +210,20 @@ void LegoAnimActor::ParseAction(char* p_extra) if (world) { if (KeyValueStringParse(value, g_strANIMATION, p_extra)) { + // name verified by BETA10 0x1003ea46 char* token = strtok(value, g_parseExtraTokens); while (token) { - LegoLocomotionAnimPresenter* presenter = - (LegoLocomotionAnimPresenter*) world->Find("LegoAnimPresenter", token); + // name verified by BETA10 0x1003e9f5 + LegoLocomotionAnimPresenter* p = (LegoLocomotionAnimPresenter*) world->Find("LegoAnimPresenter", token); - if (presenter != NULL) { + assert(p); + + if (p != NULL) { token = strtok(NULL, g_parseExtraTokens); if (token) { - presenter->FUN_1006d680(this, atof(token)); + p->FUN_1006d680(this, atof(token)); } } diff --git a/LEGO1/lego/legoomni/src/race/carrace.cpp b/LEGO1/lego/legoomni/src/race/carrace.cpp index 5552df4d..6ffb2ebd 100644 --- a/LEGO1/lego/legoomni/src/race/carrace.cpp +++ b/LEGO1/lego/legoomni/src/race/carrace.cpp @@ -7,7 +7,7 @@ DECOMP_SIZE_ASSERT(CarRace, 0x154) // FUNCTION: LEGO1 0x10016a90 CarRace::CarRace() { - this->m_unk0x150 = 0; + this->m_skeleton = NULL; this->m_unk0x130 = MxRect32(0x16c, 0x154, 0x1ec, 0x15e); } diff --git a/LEGO1/lego/legoomni/src/race/legoracers.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp index d9f15050..7a60d59c 100644 --- a/LEGO1/lego/legoomni/src/race/legoracers.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -304,11 +304,10 @@ MxU32 LegoRaceCar::HandleSkeletonKicks(float p_param1) { const SkeletonKickPhase* current = g_skeletonKickPhases; - // TODO: Type is guesswork so far CarRace* r = (CarRace*) CurrentWorld(); // called `r` in BETA10 assert(r); - RaceSkel* s = (RaceSkel*) r->GetUnk0x150(); // called `s` in BETA10 + RaceSkel* s = r->GetSkeleton(); // called `s` in BETA10 assert(s); float skeletonCurAnimPosition; diff --git a/LEGO1/lego/legoomni/src/race/raceskel.cpp b/LEGO1/lego/legoomni/src/race/raceskel.cpp index 2d5c71bf..213e788d 100644 --- a/LEGO1/lego/legoomni/src/race/raceskel.cpp +++ b/LEGO1/lego/legoomni/src/race/raceskel.cpp @@ -1,13 +1,53 @@ #include "raceskel.h" +#include "carrace.h" +#include "legoworld.h" +#include "misc.h" + #include DECOMP_SIZE_ASSERT(RaceSkel, 0x178) -// STUB: LEGO1 0x100719b0 +// FUNCTION: LEGO1 0x100719b0 +// FUNCTION: BETA10 0x100f1240 RaceSkel::RaceSkel() { - // TODO + m_animPosition = 0.0f; +} + +// FUNCTION: LEGO1 0x10071ad0 +RaceSkel::~RaceSkel() +{ +} + +// FUNCTION: LEGO1 0x10071b50 +// FUNCTION: BETA10 0x100f13cf +MxResult RaceSkel::FUN_1001c360(float p_und, Matrix4& p_transform) +{ + p_transform[3][0] = -630.0f; + p_transform[3][1] = -4.688f; + p_transform[3][2] = 323.0f; + + m_animPosition = p_und; + + return LegoAnimActor::FUN_1001c360(p_und, p_transform); +} + +// FUNCTION: LEGO1 0x10071b90 +// FUNCTION: BETA10 0x100f1444 +void RaceSkel::ParseAction(char* p_extra) +{ + LegoAnimActor::ParseAction(p_extra); + + // name verified by BETA10 0x100f147d + CarRace* w = (CarRace*) CurrentWorld(); + assert(w); + w->SetSkeleton(this); + + assert(m_roi); + BoundingSphere sphere = m_roi->GetBoundingSphere(); + sphere.Radius() *= 100.0f; + m_roi->SetBoundingSphere(sphere); } // FUNCTION: LEGO1 0x10071cb0 diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index d570ac56..fb96b2a5 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -64,6 +64,7 @@ class LegoROI : public ViewROI { const LegoChar* GetName() const { return m_name; } LegoEntity* GetEntity() { return m_entity; } + BoundingSphere& GetBoundingSphere() { return m_sphere; } void SetEntity(LegoEntity* p_entity) { m_entity = p_entity; } void SetComp(CompoundObject* p_comp) { comp = p_comp; } diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index f675a350..0e2e00b3 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -21,6 +21,7 @@ class Mx3DPointFloat : public Vector3 { // FUNCTION: BETA10 0x10011600 Mx3DPointFloat(const Mx3DPointFloat& p_other) : Vector3(m_elements) { EqualsImpl(p_other.m_data); } + // FUNCTION: BETA10 0x100151e0 Mx3DPointFloat(const Vector3& p_other) : Vector3(m_elements) { EqualsImpl(p_other.m_data); } // SYNTHETIC: LEGO1 0x1001d170 diff --git a/LEGO1/omni/include/mxobjectfactory.h b/LEGO1/omni/include/mxobjectfactory.h index aad3f2b2..4abdf766 100644 --- a/LEGO1/omni/include/mxobjectfactory.h +++ b/LEGO1/omni/include/mxobjectfactory.h @@ -19,6 +19,7 @@ X(MxLoopingMIDIPresenter) // VTABLE: LEGO1 0x100dc220 +// VTABLE: BETA10 0x101c2280 class MxObjectFactory : public MxCore { public: MxObjectFactory(); diff --git a/LEGO1/omni/src/common/mxobjectfactory.cpp b/LEGO1/omni/src/common/mxobjectfactory.cpp index 3722bb0e..3e733dfe 100644 --- a/LEGO1/omni/src/common/mxobjectfactory.cpp +++ b/LEGO1/omni/src/common/mxobjectfactory.cpp @@ -25,6 +25,7 @@ MxObjectFactory::MxObjectFactory() } // FUNCTION: LEGO1 0x100b12c0 +// FUNCTION: BETA10 0x10143177 MxCore* MxObjectFactory::Create(const char* p_name) { MxCore* object = NULL; @@ -43,6 +44,7 @@ MxCore* MxObjectFactory::Create(const char* p_name) } // FUNCTION: LEGO1 0x100b1a30 +// FUNCTION: BETA10 0x10143814 void MxObjectFactory::Destroy(MxCore* p_object) { delete p_object; From ce3fc57025849e8e6a207e704e828ebde54bb992 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Fri, 23 Aug 2024 21:22:03 +0200 Subject: [PATCH 10/18] BETA10 Readme additions (#1090) Co-authored-by: jonschz --- README.md | 1 + tools/README.md | 71 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3afbe0cc..519f6422 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo - `NMake Makefiles` is most recommended because it will be immediately compatible with Visual C++ 4.2. For faster builds, you can use `Ninja` (if you have it installed), however due to limitations in Visual C++ 4.2, you can only build `Release` builds this way (debug symbols cannot be generated with `Ninja`). 1. Build the project by running `nmake` or `cmake --build ` 1. When this is done, there should a recompiled `ISLE.EXE` and `LEGO1.DLL` in the build folder. +1. Note that `nmake` must be run twice under certain conditions, so it is advisable to always (re-)compile using `nmake && nmake`. If you have a CMake-compatible IDE, it should be pretty straightforward to use this repository, as long as you can use `VCVARS32.BAT` and set the generator to `NMake Makefiles`. diff --git a/tools/README.md b/tools/README.md index 0a998f2b..98eb1f8d 100644 --- a/tools/README.md +++ b/tools/README.md @@ -101,7 +101,7 @@ public: virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x28 ``` -## Class size (**WIP**) +## Class size Classes should be annotated using the `SIZE` marker to indicate their size. If you are unsure about the class size in the original binary, please use the currently available information (known member variables) and detail the circumstances in an extra comment if necessary. @@ -114,7 +114,9 @@ public: static void SetDoMutex(); ``` -## Member variables (**WIP**) +Furthermore, add `DECOMP_SIZE_ASSERT(MxCriticalSection, 0x1c)` to the respective `.cpp` file (if the class has no dedicated `.cpp` file, use any appropriate `.cpp` file where the class is used). + +## Member variables Member variables should be annotated with their relative offsets. @@ -162,14 +164,23 @@ Use `pip` to install the required packages to be able to use the Python tools fo pip install -r tools/requirements.txt ``` +The example usages below assume that the current working directory is this repository's root and that the retail binaries have been copied to `./legobin`. + * [`decomplint`](/tools/decomplint): Checks the decompilation annotations (see above) + * e.g. `py -m tools.decomplint.decomplint --module LEGO1 LEGO1` * [`isledecomp`](/tools/isledecomp): A library that implements a parser to identify the decompilation annotations (see above) * [`ncc`](/tools/ncc): Checks naming conventions based on a set of rules -* [`reccmp`](/tools/reccmp): Compares an original binary with a recompiled binary, provided a PDB file +* [`reccmp`](/tools/reccmp): Compares an original binary with a recompiled binary, provided a PDB file. For example: + * Display the diff for a single function: `py -m tools.reccmp.reccmp --verbose 0x100ae1a0 legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .` + * Generate an HTML report: `py -m tools.reccmp.reccmp --html output.html legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .` + * Create a base file for diffs: `py -m tools.reccmp.reccmp --json base.json --silent legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .` + * Diff against a base file: `py -m tools.reccmp.reccmp --diff base.json legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .` * [`roadmap`](/tools/roadmap): Compares symbol locations in an original binary with the same symbol locations of a recompiled binary * [`verexp`](/tools/verexp): Verifies exports by comparing the exports of the original DLL and the recompiled DLL * [`vtable`](/tools/vtable): Asserts virtual table correctness by comparing a recompiled binary with the original -* [`datacmp.py`](/tools/datacmp.py): Compares global data found in the original with the recompiled version + * e.g. `py -m tools.vtable.vtable legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .` +* [`datacmp.py`](/tools/datacmp.py): Compares global data found in the original with the recompiled version + * e.g. `py -m tools.datacmp legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .` * [`patch_c2.py`](/tools/patch_c2.py): Patches `C2.EXE` (part of MSVC 4.20) to get rid of a bugged warning ## Testing @@ -181,9 +192,9 @@ pip install pytest pytest tools/isledecomp/tests/ ``` -## Development +## Tool Development -In order to keep the code clean and consistent, we use `pylint` and `black`: +In order to keep the Python code clean and consistent, we use `pylint` and `black`: `pip install black pylint` @@ -191,10 +202,54 @@ In order to keep the code clean and consistent, we use `pylint` and `black`: `pylint tools/ --ignore=build,ncc` -### Check code formatting without rewriting files +### Check Python code formatting without rewriting files `black --check tools/` -### Apply code formatting +### Apply Python code formatting `black tools/` + +# Modules +The following is a list of all the modules found in the annotations (e.g. `// FUNCTION: [module] [address]`) and which binaries they refer to. See [this list of all known versions of the game](https://www.legoisland.org/wiki/LEGO_Island#Download). + +## Retail v1.1.0.0 (v1.1) +* `LEGO1` -> `LEGO1.DLL` +* `CONFIG`-> `CONFIG.EXE` +* `ISLE` -> `ISLE.EXE` + +These modules are the most important ones and refer to the English retail version 1.1.0.0 (often shortened to v1.1), which is the most widely released one. These are the ones we attempt to decompile and match as best as possible. + +## BETA v1.0 + +* `BETA10` -> `LEGO1D.DLL` + +The Beta 1.0 version contains a debug build of the game. While it does not have debug symbols, it still has a number of benefits: +* It is built with less or no optimisation, leading to better decompilations in Ghidra +* Far fewer functions are inlined by the compiler, so it can be used to recognise inlined functions +* It contains assertions that tell us original variable names and code file paths + +It is therefore advisable to search for the corresponding function in `BETA10` when decompiling a function in `LEGO1`. Finding the correct function can be tricky, but is usually worth it, especially for longer functions. + +Unfortunately, some code has been changed after this beta version was created. Therefore, we are not aiming for a perfect binary match of `BETA10`. In case of discrepancies, `LEGO1` (as defined above) is our "gold standard" for matching. + +### Re-compiling a beta build (**WIP**) + +If you want to match the code against `BETA10`, use the following `cmake` setup to create a debug build: +``` +cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_BUILD_TYPE=Debug -DISLE_USE_SMARTHEAP=OFF +``` +**TODO**: If you can figure out how to make a debug build with SmartHeap enabled, please add it here. + +If you want to run scripts to compare your debug build to `BETA10` (e.g. `reccmp`), it is advisable to add a copy of `LEGO1D.DLL` to `/legobin` and rename it to `BETA10.DLL`. + +### Finding matching functions + +This is not a recipe, but rather a list of things you can try. +* If you are working on a virtual function in a class, try to find the class' vtable. Many (but not all) classes implement `ClassName()`. These functions are usually easy to find by searching the memory for the string consisting of the class name. Keep in mind that not all child classes overwrite this function, so if the function you found is used in multiple vtables (or if you found multiple `ClassName()`-like functions), make sure you actually have the parent's vtable. +* If that does not help, you can try to walk up the call tree and try to locate a function that calls the function you are interested in. +* Assertions can also help you - most `.cpp` file names have already been matched based on `BETA10`, so you can search for the name of your `.cpp` file and check all the assertions in that file. While that does not find all functions in a given source file, it usually finds the more complex ones. +* _If you have found any other strategies, please add them here._ + +## Others (**WIP**) +* `ALPHA` (only used twice) From b898d985158f67e51d7aa9958743b6da6be6c79c Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Thu, 29 Aug 2024 20:54:23 +0200 Subject: [PATCH 11/18] BETA10: reccomp support and Ghidra imports (#1091) * Implement core functionality (before linter) * run linter + formatter * Review: remove redundant code * Implement end of range check for vtables --------- Co-authored-by: jonschz --- .gitignore | 9 +- .../legoomni/src/race/legoracespecial.cpp | 2 +- LEGO1/realtime/vector.h | 6 +- .../import_functions_and_types_from_pdb.py | 52 ++++++++- .../lego_util/function_importer.py | 96 ++++++++++++---- .../ghidra_scripts/lego_util/ghidra_helper.py | 36 ++++-- tools/ghidra_scripts/lego_util/headers.pyi | 3 +- .../lego_util/pdb_extraction.py | 29 ++--- tools/isledecomp/isledecomp/compare/core.py | 107 +++++++++++------- tools/isledecomp/isledecomp/compare/db.py | 5 + util/decomp.h | 6 + 11 files changed, 254 insertions(+), 97 deletions(-) diff --git a/.gitignore b/.gitignore index d335e177..b5e87a00 100644 --- a/.gitignore +++ b/.gitignore @@ -12,11 +12,16 @@ ENV/ VENV/ env.bak/ venv.bak/ -ISLE.EXE -LEGO1.DLL /build/ +/build_debug/ +/legobin/ *.swp LEGO1PROGRESS.* ISLEPROGRESS.* *.pyc tools/ghidra_scripts/import.log + +# By convention we put the retail binaries into ./legobin. +# These entries are kept for now since that convention has not always been around. +ISLE.EXE +LEGO1.DLL diff --git a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp index 4c7d0c19..6bfb2565 100644 --- a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp @@ -209,7 +209,7 @@ void LegoCarRaceActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown } // FUNCTION: LEGO1 0x10080b70 -// FUNCTION: BETA10 0x1000366b +// FUNCTION: BETA10 0x100cdbae void LegoCarRaceActor::VTable0x70(float p_float) { // m_unk0x0c is not an MxBool, there are places where it is set to 2 or higher diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 9c73f31f..2db647c3 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -89,7 +89,7 @@ class Vector2 { virtual float Dot(float* p_a, float* p_b) const { return DotImpl(p_a, p_b); } // vtable+0x3c // FUNCTION: LEGO1 0x100020f0 - // FUNCTION: BETA10 0x100028f6 + // FUNCTION: BETA10 0x100108c0 virtual float Dot(Vector2* p_a, Vector2* p_b) const { return DotImpl(p_a->m_data, p_b->m_data); } // vtable+0x38 // FUNCTION: LEGO1 0x10002110 @@ -188,7 +188,7 @@ class Vector3 : public Vector2 { // in reverse order of appearance. // FUNCTION: LEGO1 0x10002270 - // FUNCTION: BETA10 0x100064a1 + // FUNCTION: BETA10 0x10011350 virtual void EqualsCrossImpl(float* p_a, float* p_b) { m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; @@ -275,7 +275,7 @@ class Vector3 : public Vector2 { void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 3); } // vtable+0x20 // FUNCTION: LEGO1 0x10003bc0 - // FUNCTION: BETA10 0x1000132a + // FUNCTION: BETA10 0x100114f0 void Clear() override { memset(m_data, 0, sizeof(float) * 3); } // vtable+0x2c // FUNCTION: LEGO1 0x10003bd0 diff --git a/tools/ghidra_scripts/import_functions_and_types_from_pdb.py b/tools/ghidra_scripts/import_functions_and_types_from_pdb.py index 0d77e7f6..54bb7e9f 100644 --- a/tools/ghidra_scripts/import_functions_and_types_from_pdb.py +++ b/tools/ghidra_scripts/import_functions_and_types_from_pdb.py @@ -21,6 +21,7 @@ # Disable spurious warnings in vscode / pylance # pyright: reportMissingModuleSource=false +from enum import Enum import importlib from dataclasses import dataclass, field import logging.handlers @@ -64,6 +65,25 @@ class Globals: statistics: Statistics = field(default_factory=Statistics) +class SupportedModules(Enum): + LEGO1 = 1 + BETA10 = 2 + + def orig_filename(self): + if self == self.LEGO1: + return "LEGO1.DLL" + return "BETA10.DLL" + + def recomp_filename_without_extension(self): + # in case we want to support more functions + return "LEGO1" + + def build_dir_name(self): + if self == self.BETA10: + return "build_debug" + return "build" + + # hard-coded settings that we don't want to prompt in Ghidra every time GLOBALS = Globals( verbose=False, @@ -133,7 +153,7 @@ def import_function_into_ghidra( # Find the Ghidra function at that address ghidra_address = getAddressFactory().getAddress(hex_original_address) # pylint: disable=possibly-used-before-assignment - function_importer = PdbFunctionImporter(api, pdb_function, type_importer) + function_importer = PdbFunctionImporter.build(api, pdb_function, type_importer) ghidra_function = getFunctionAt(ghidra_address) if ghidra_function is None: @@ -208,11 +228,29 @@ def log_and_track_failure( def main(): + if GLOBALS.running_from_ghidra: + origfile_name = getProgramFile().getName() + + if origfile_name == "LEGO1.DLL": + module = SupportedModules.LEGO1 + elif origfile_name in ["LEGO1D.DLL", "BETA10.DLL"]: + module = SupportedModules.BETA10 + else: + raise Lego1Exception( + f"Unsupported file name in import script: {origfile_name}" + ) + else: + module = SupportedModules.LEGO1 + + logger.info("Importing file: %s", module.orig_filename()) + repo_root = get_repository_root() - origfile_path = repo_root.joinpath("LEGO1.DLL") - build_path = repo_root.joinpath("build") - recompiledfile_path = build_path.joinpath("LEGO1.DLL") - pdb_path = build_path.joinpath("LEGO1.pdb") + origfile_path = repo_root.joinpath("legobin").joinpath(module.orig_filename()) + build_directory = repo_root.joinpath(module.build_dir_name()) + recompiledfile_name = f"{module.recomp_filename_without_extension()}.DLL" + recompiledfile_path = build_directory.joinpath(recompiledfile_name) + pdbfile_name = f"{module.recomp_filename_without_extension()}.PDB" + pdbfile_path = build_directory.joinpath(pdbfile_name) if not GLOBALS.verbose: logging.getLogger("isledecomp.bin").setLevel(logging.WARNING) @@ -225,7 +263,9 @@ def main(): with Bin(str(origfile_path), find_str=True) as origfile, Bin( str(recompiledfile_path) ) as recompfile: - isle_compare = IsleCompare(origfile, recompfile, str(pdb_path), str(repo_root)) + isle_compare = IsleCompare( + origfile, recompfile, str(pdbfile_path), str(repo_root) + ) logger.info("Comparison complete.") diff --git a/tools/ghidra_scripts/lego_util/function_importer.py b/tools/ghidra_scripts/lego_util/function_importer.py index 6ccc6935..379d412f 100644 --- a/tools/ghidra_scripts/lego_util/function_importer.py +++ b/tools/ghidra_scripts/lego_util/function_importer.py @@ -5,6 +5,7 @@ import logging from typing import Optional +from abc import ABC, abstractmethod from ghidra.program.model.listing import Function, Parameter from ghidra.program.flatapi import FlatProgramAPI @@ -24,6 +25,7 @@ ) from lego_util.ghidra_helper import ( add_data_type_or_reuse_existing, + create_ghidra_namespace, get_or_add_pointer_type, get_ghidra_namespace, sanitize_name, @@ -32,12 +34,10 @@ from lego_util.exceptions import StackOffsetMismatchError, Lego1Exception from lego_util.type_importer import PdbTypeImporter - logger = logging.getLogger(__name__) -# pylint: disable=too-many-instance-attributes -class PdbFunctionImporter: +class PdbFunctionImporter(ABC): """A representation of a function from the PDB with each type replaced by a Ghidra type instance.""" def __init__( @@ -48,20 +48,79 @@ def __init__( ): self.api = api self.match_info = func.match_info - self.signature = func.signature - self.is_stub = func.is_stub self.type_importer = type_importer - if self.signature.class_type is not None: - # Import the base class so the namespace exists - self.type_importer.import_pdb_type_into_ghidra(self.signature.class_type) - assert self.match_info.name is not None colon_split = sanitize_name(self.match_info.name).split("::") self.name = colon_split.pop() namespace_hierachy = colon_split - self.namespace = get_ghidra_namespace(api, namespace_hierachy) + self.namespace = self._do_get_namespace(namespace_hierachy) + + def _do_get_namespace(self, namespace_hierarchy: list[str]): + return get_ghidra_namespace(self.api, namespace_hierarchy) + + def get_full_name(self) -> str: + return f"{self.namespace.getName()}::{self.name}" + + @staticmethod + def build(api: FlatProgramAPI, func: PdbFunction, type_importer: "PdbTypeImporter"): + return ( + ThunkPdbFunctionImport(api, func, type_importer) + if func.signature is None + else FullPdbFunctionImporter(api, func, type_importer) + ) + + @abstractmethod + def matches_ghidra_function(self, ghidra_function: Function) -> bool: + ... + + @abstractmethod + def overwrite_ghidra_function(self, ghidra_function: Function): + ... + + +class ThunkPdbFunctionImport(PdbFunctionImporter): + """For importing thunk functions (like vtordisp or debug build thunks) into Ghidra. + Only the name of the function will be imported.""" + + def _do_get_namespace(self, namespace_hierarchy: list[str]): + """We need to create the namespace because we don't import the return type here""" + return create_ghidra_namespace(self.api, namespace_hierarchy) + + def matches_ghidra_function(self, ghidra_function: Function) -> bool: + name_match = self.name == ghidra_function.getName(False) + namespace_match = self.namespace == ghidra_function.getParentNamespace() + + logger.debug("Matches: namespace=%s name=%s", namespace_match, name_match) + + return name_match and namespace_match + + def overwrite_ghidra_function(self, ghidra_function: Function): + ghidra_function.setName(self.name, SourceType.USER_DEFINED) + ghidra_function.setParentNamespace(self.namespace) + + +# pylint: disable=too-many-instance-attributes +class FullPdbFunctionImporter(PdbFunctionImporter): + """For importing functions into Ghidra where all information are available.""" + + def __init__( + self, + api: FlatProgramAPI, + func: PdbFunction, + type_importer: "PdbTypeImporter", + ): + super().__init__(api, func, type_importer) + + assert func.signature is not None + self.signature = func.signature + + self.is_stub = func.is_stub + + if self.signature.class_type is not None: + # Import the base class so the namespace exists + self.type_importer.import_pdb_type_into_ghidra(self.signature.class_type) self.return_type = type_importer.import_pdb_type_into_ghidra( self.signature.return_type @@ -75,17 +134,6 @@ def __init__( for (index, type_name) in enumerate(self.signature.arglist) ] - @property - def call_type(self): - return self.signature.call_type - - @property - def stack_symbols(self): - return self.signature.stack_symbols - - def get_full_name(self) -> str: - return f"{self.namespace.getName()}::{self.name}" - def matches_ghidra_function(self, ghidra_function: Function) -> bool: """Checks whether this function declaration already matches the description in Ghidra""" name_match = self.name == ghidra_function.getName(False) @@ -235,7 +283,7 @@ def overwrite_ghidra_function(self, ghidra_function: Function): ghidra_function.setName(self.name, SourceType.USER_DEFINED) ghidra_function.setParentNamespace(self.namespace) ghidra_function.setReturnType(self.return_type, SourceType.USER_DEFINED) - ghidra_function.setCallingConvention(self.call_type) + ghidra_function.setCallingConvention(self.signature.call_type) if self.is_stub: logger.debug( @@ -306,7 +354,7 @@ def get_matching_stack_symbol(self, stack_offset: int) -> Optional[CppStackSymbo return next( ( symbol - for symbol in self.stack_symbols + for symbol in self.signature.stack_symbols if isinstance(symbol, CppStackSymbol) and symbol.stack_offset == stack_offset ), @@ -319,7 +367,7 @@ def get_matching_register_symbol( return next( ( symbol - for symbol in self.stack_symbols + for symbol in self.signature.stack_symbols if isinstance(symbol, CppRegisterSymbol) and symbol.register == register ), None, diff --git a/tools/ghidra_scripts/lego_util/ghidra_helper.py b/tools/ghidra_scripts/lego_util/ghidra_helper.py index f6726482..24e70c65 100644 --- a/tools/ghidra_scripts/lego_util/ghidra_helper.py +++ b/tools/ghidra_scripts/lego_util/ghidra_helper.py @@ -1,6 +1,7 @@ """A collection of helper functions for the interaction with Ghidra.""" import logging +import re from lego_util.exceptions import ( ClassOrNamespaceNotFoundInGhidraError, @@ -80,25 +81,42 @@ def create_ghidra_namespace( return namespace +# These appear in debug builds +THUNK_OF_RE = re.compile(r"^Thunk of '(.*)'$") + + def sanitize_name(name: str) -> str: """ Takes a full class or function name and replaces characters not accepted by Ghidra. - Applies mostly to templates and names like `vbase destructor`. + Applies mostly to templates, names like `vbase destructor`, and thunks in debug build. """ - new_class_name = ( + if (match := THUNK_OF_RE.fullmatch(name)) is not None: + is_thunk = True + name = match.group(1) + else: + is_thunk = False + + # Replace characters forbidden in Ghidra + new_name = ( name.replace("<", "[") .replace(">", "]") .replace("*", "#") .replace(" ", "_") .replace("`", "'") ) - if "<" in name: - new_class_name = "_template_" + new_class_name - if new_class_name != name: - logger.warning( - "Class or function name contains characters forbidden by Ghidra, changing from '%s' to '%s'", + if "<" in name: + new_name = "_template_" + new_name + + if is_thunk: + split = new_name.split("::") + split[-1] = "_thunk_" + split[-1] + new_name = "::".join(split) + + if new_name != name: + logger.info( + "Changed class or function name from '%s' to '%s' to avoid Ghidra issues", name, - new_class_name, + new_name, ) - return new_class_name + return new_name diff --git a/tools/ghidra_scripts/lego_util/headers.pyi b/tools/ghidra_scripts/lego_util/headers.pyi index 89960443..b1655437 100644 --- a/tools/ghidra_scripts/lego_util/headers.pyi +++ b/tools/ghidra_scripts/lego_util/headers.pyi @@ -1,4 +1,4 @@ -from typing import TypeVar +from typing import TypeVar, Any import ghidra # pylint: disable=invalid-name,unused-argument @@ -17,3 +17,4 @@ def getFunctionAt( def createFunction( entryPoint: ghidra.program.model.address.Address, name: str ) -> ghidra.program.model.listing.Function: ... +def getProgramFile() -> Any: ... # actually java.io.File diff --git a/tools/ghidra_scripts/lego_util/pdb_extraction.py b/tools/ghidra_scripts/lego_util/pdb_extraction.py index 4ba1ac71..a45242b4 100644 --- a/tools/ghidra_scripts/lego_util/pdb_extraction.py +++ b/tools/ghidra_scripts/lego_util/pdb_extraction.py @@ -3,6 +3,7 @@ from typing import Any, Optional import logging +from isledecomp.bin import InvalidVirtualAddressError from isledecomp.cvdump.symbols import SymbolsEntry from isledecomp.compare import Compare as IsleCompare from isledecomp.compare.db import MatchInfo @@ -43,7 +44,7 @@ class FunctionSignature: @dataclass class PdbFunction: match_info: MatchInfo - signature: FunctionSignature + signature: Optional[FunctionSignature] is_stub: bool @@ -74,9 +75,7 @@ def _get_cvdump_type(self, type_name: Optional[str]) -> Optional[dict[str, Any]] def get_func_signature(self, fn: SymbolsEntry) -> Optional[FunctionSignature]: function_type_str = fn.func_type if function_type_str == "T_NOTYPE(0000)": - logger.debug( - "Skipping a NOTYPE (synthetic or template + synthetic): %s", fn.name - ) + logger.debug("Treating NOTYPE function as thunk: %s", fn.name) return None # get corresponding function type @@ -145,8 +144,6 @@ def handle_matched_function(self, match_info: MatchInfo) -> Optional[PdbFunction assert match_info.orig_addr is not None match_options = self.compare.get_match_options(match_info.orig_addr) assert match_options is not None - if match_options.get("skip", False): - return None function_data = next( ( @@ -156,11 +153,19 @@ def handle_matched_function(self, match_info: MatchInfo) -> Optional[PdbFunction ), None, ) - if not function_data: - logger.error( - "Did not find function in nodes, skipping: %s", match_info.name - ) - return None + if function_data is None: + try: + # this can be either a thunk (which we want) or an external function + # (which we don't want), so we tell them apart based on the validity of their address. + self.compare.orig_bin.get_relative_addr(match_info.orig_addr) + return PdbFunction(match_info, None, False) + except InvalidVirtualAddressError: + logger.debug( + "Skipping external function %s (address 0x%x not in original binary)", + match_info.name, + match_info.orig_addr, + ) + return None function_symbol = function_data.symbol_entry if function_symbol is None: @@ -171,8 +176,6 @@ def handle_matched_function(self, match_info: MatchInfo) -> Optional[PdbFunction return None function_signature = self.get_func_signature(function_symbol) - if function_signature is None: - return None is_stub = match_options.get("stub", False) diff --git a/tools/isledecomp/isledecomp/compare/core.py b/tools/isledecomp/isledecomp/compare/core.py index 3cf827e9..8a1fc153 100644 --- a/tools/isledecomp/isledecomp/compare/core.py +++ b/tools/isledecomp/isledecomp/compare/core.py @@ -479,14 +479,31 @@ def _find_vtordisp(self): construct the name of the vtordisp function and match based on that.""" for match in self._db.get_matches_by_type(SymbolType.VTABLE): + assert ( + match.name is not None + and match.orig_addr is not None + and match.recomp_addr is not None + and match.size is not None + ) # We need some method of identifying vtables that # might have thunks, and this ought to work okay. if "{for" not in match.name: continue + next_orig = self._db.get_next_orig_addr(match.orig_addr) + assert next_orig is not None + orig_upper_size_limit = next_orig - match.orig_addr + if orig_upper_size_limit < match.size: + # This could happen in debug builds due to code changes between BETA10 and LEGO1, + # but we have not seen it yet as of 2024-08-28. + logger.warning( + "Recomp vtable is larger than orig vtable for %s", + match.name, + ) + # TODO: We might want to fix this at the source (cvdump) instead. # Any problem will be logged later when we compare the vtable. - vtable_size = 4 * (match.size // 4) + vtable_size = 4 * (min(match.size, orig_upper_size_limit) // 4) orig_table = self.orig_bin.read(match.orig_addr, vtable_size) recomp_table = self.recomp_bin.read(match.recomp_addr, vtable_size) @@ -497,51 +514,65 @@ def _find_vtordisp(self): # Now walk both vtables looking for thunks. for orig_addr, recomp_addr in raw_addrs: - if not self._db.is_vtordisp(recomp_addr): - continue + if orig_addr == 0: + # This happens in debug builds due to code changes between BETA10 and LEGO1. + # Note that there is a risk of running into the next vtable if there is no gap in between, + # which we cannot protect against at the moment. + logger.warning( + "Recomp vtable is larger than orig vtable for %s", match.name + ) + break - thunk_fn = self.get_by_recomp(recomp_addr) + if self._db.is_vtordisp(recomp_addr): + self._match_vtordisp_in_vtable(orig_addr, recomp_addr) - # Read the function bytes here. - # In practice, the adjuster thunk will be under 16 bytes. - # If we have thunks of unequal size, we can still tell whether - # they are thunking the same function by grabbing the - # JMP instruction at the end. - thunk_presumed_size = max(thunk_fn.size, 16) + def _match_vtordisp_in_vtable(self, orig_addr, recomp_addr): + thunk_fn = self.get_by_recomp(recomp_addr) + assert thunk_fn is not None + assert thunk_fn.size is not None - # Strip off MSVC padding 0xcc bytes. - # This should be safe to do; it is highly unlikely that - # the MSB of the jump displacement would be 0xcc. (huge jump) - orig_thunk_bin = self.orig_bin.read( - orig_addr, thunk_presumed_size - ).rstrip(b"\xcc") + # Read the function bytes here. + # In practice, the adjuster thunk will be under 16 bytes. + # If we have thunks of unequal size, we can still tell whether they are thunking + # the same function by grabbing the JMP instruction at the end. + thunk_presumed_size = max(thunk_fn.size, 16) - recomp_thunk_bin = self.recomp_bin.read( - recomp_addr, thunk_presumed_size - ).rstrip(b"\xcc") + # Strip off MSVC padding 0xcc bytes. + # This should be safe to do; it is highly unlikely that + # the MSB of the jump displacement would be 0xcc. (huge jump) + orig_thunk_bin = self.orig_bin.read(orig_addr, thunk_presumed_size).rstrip( + b"\xcc" + ) - # Read jump opcode and displacement (last 5 bytes) - (orig_jmp, orig_disp) = struct.unpack(" bool: if "`vtordisp" in name: return True + if decorated_name is None: + # happens in debug builds, e.g. for "Thunk of 'LegoAnimActor::ClassName'" + return False + new_name = get_vtordisp_name(decorated_name) if new_name is None: return False diff --git a/util/decomp.h b/util/decomp.h index 81cb1d13..673df553 100644 --- a/util/decomp.h +++ b/util/decomp.h @@ -1,6 +1,12 @@ #ifndef DECOMP_H #define DECOMP_H +#ifndef NDEBUG +// Disable size assertions for debug builds because the sizes differ between debug and release builds. +// The release LEGO1.DLL is what we ultimately want to decompile, so this is what we assert against. +#undef ENABLE_DECOMP_ASSERTS +#endif + #if defined(ENABLE_DECOMP_ASSERTS) #define DECOMP_STATIC_ASSERT(V) \ namespace \ From 0256fc4acf34f246050d4d6f145b883c3117b2b4 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sat, 31 Aug 2024 17:00:35 +0200 Subject: [PATCH 12/18] Fix Ghidra import call type (#1093) Co-authored-by: jonschz --- .../ghidra_scripts/lego_util/function_importer.py | 14 +++++++------- tools/ghidra_scripts/lego_util/pdb_extraction.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/ghidra_scripts/lego_util/function_importer.py b/tools/ghidra_scripts/lego_util/function_importer.py index 379d412f..45e93c8d 100644 --- a/tools/ghidra_scripts/lego_util/function_importer.py +++ b/tools/ghidra_scripts/lego_util/function_importer.py @@ -162,30 +162,30 @@ def matches_ghidra_function(self, ghidra_function: Function) -> bool: return_type_match = True # match arguments: decide if thiscall or not, and whether the `this` type matches - thiscall_matches = ( + calling_convention_match = ( self.signature.call_type == ghidra_function.getCallingConventionName() ) ghidra_params_without_this = list(ghidra_function.getParameters()) - if thiscall_matches and self.signature.call_type == "__thiscall": + if calling_convention_match and self.signature.call_type == "__thiscall": this_argument = ghidra_params_without_this.pop(0) - thiscall_matches = self._this_type_match(this_argument) + calling_convention_match = self._this_type_match(this_argument) if self.is_stub: # We do not import the argument list for stubs, so it should be excluded in matches args_match = True - elif thiscall_matches: + elif calling_convention_match: args_match = self._parameter_lists_match(ghidra_params_without_this) else: args_match = False logger.debug( - "Matches: namespace=%s name=%s return_type=%s thiscall=%s args=%s", + "Matches: namespace=%s name=%s return_type=%s calling_convention=%s args=%s", namespace_match, name_match, return_type_match, - thiscall_matches, + calling_convention_match, "ignored" if self.is_stub else args_match, ) @@ -193,7 +193,7 @@ def matches_ghidra_function(self, ghidra_function: Function) -> bool: name_match and namespace_match and return_type_match - and thiscall_matches + and calling_convention_match and args_match ) diff --git a/tools/ghidra_scripts/lego_util/pdb_extraction.py b/tools/ghidra_scripts/lego_util/pdb_extraction.py index a45242b4..6a0db6f8 100644 --- a/tools/ghidra_scripts/lego_util/pdb_extraction.py +++ b/tools/ghidra_scripts/lego_util/pdb_extraction.py @@ -61,7 +61,7 @@ def __init__(self, compare: IsleCompare): _call_type_map = { "ThisCall": "__thiscall", - "C Near": "__thiscall", + "C Near": "default", "STD Near": "__stdcall", } From 990725ba0b6e0a22cd64d18205b84d1ea517c0c5 Mon Sep 17 00:00:00 2001 From: MS Date: Sat, 31 Aug 2024 23:02:19 -0400 Subject: [PATCH 13/18] Add more MSVC annotations for LEGO1 (#1094) --- LEGO1/library_msvc.h | 530 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 526 insertions(+), 4 deletions(-) diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 7a4153b6..dfddcfcb 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -12,6 +12,9 @@ // LIBRARY: LEGO1 0x1008a090 // _malloc +// LIBRARY: LEGO1 0x1008a100 +// _calloc + // LIBRARY: LEGO1 0x1008a1c0 // _free @@ -24,9 +27,15 @@ // LIBRARY: LEGO1 0x1008b28e // __local_unwind2 +// LIBRARY: LEGO1 0x1008b319 +// __NLG_Notify1 + // LIBRARY: LEGO1 0x1008b322 // __NLG_Notify +// LIBRARY: LEGO1 0x1008b340 +// __FPinit + // LIBRARY: LEGO1 0x1008b3dc // __CIacos @@ -51,6 +60,9 @@ // LIBRARY: LEGO1 0x1008b640 // _rand +// LIBRARY: LEGO1 0x1008b670 +// __purecall + // LIBRARY: LEGO1 0x1008b680 // _strncmp @@ -60,21 +72,42 @@ // LIBRARY: LEGO1 0x1008b730 // _fprintf -// LIBRARY: LEGO1 0x1008b670 -// __purecall - // LIBRARY: LEGO1 0x1008b780 // _fwrite +// LIBRARY: LEGO1 0x1008b7c0 +// __fwrite_lk + // LIBRARY: LEGO1 0x1008b950 // _fread +// LIBRARY: LEGO1 0x1008b990 +// __fread_lk + // LIBRARY: LEGO1 0x1008bbd0 // _fclose +// LIBRARY: LEGO1 0x1008bc10 +// __fclose_lk + +// LIBRARY: LEGO1 0x1008bc70 +// __cinit + +// LIBRARY: LEGO1 0x1008bca0 +// __exit + +// LIBRARY: LEGO1 0x1008bcc0 +// __cexit + // LIBRARY: LEGO1 0x1008bdd0 // _ftell +// LIBRARY: LEGO1 0x1008be00 +// __ftell_lk + +// LIBRARY: LEGO1 0x1008bfb0 +// __fsopen + // LIBRARY: LEGO1 0x1008bff0 // _fopen @@ -108,21 +141,345 @@ // LIBRARY: LEGO1 0x1008c5c0 // _fseek +// LIBRARY: LEGO1 0x1008c600 +// __fseek_lk + // LIBRARY: LEGO1 0x1008c6a0 // _isdigit +// LIBRARY: LEGO1 0x1008c6d0 +// _isspace + +// LIBRARY: LEGO1 0x1008c700 +// __CRT_INIT@12 + +// LIBRARY: LEGO1 0x1008c920 +// __amsg_exit + // LIBRARY: LEGO1 0x1008c980 // __except_handler3 // LIBRARY: LEGO1 0x1008ca60 // _abort +// LIBRARY: LEGO1 0x1008ca80 +// ___InternalCxxFrameHandler + +// LIBRARY: LEGO1 0x1008cf60 +// ___FrameUnwindToState + +// LIBRARY: LEGO1 0x1008d4f0 +// __CallSettingFrame@12 + +// LIBRARY: LEGO1 0x1008d540 +// __mtinit + +// LIBRARY: LEGO1 0x1008d5a0 +// __mtterm + +// LIBRARY: LEGO1 0x1008d5d0 +// __initptd + +// LIBRARY: LEGO1 0x1008d5f0 +// __getptd + +// LIBRARY: LEGO1 0x1008d660 +// __freeptd + +// LIBRARY: LEGO1 0x1008dd90 +// __cintrindisp2 + +// LIBRARY: LEGO1 0x1008e000 +// __isctype + +// LIBRARY: LEGO1 0x1008e0a0 +// __allmul + +// LIBRARY: LEGO1 0x1008e0e0 +// __flsbuf + +// LIBRARY: LEGO1 0x1008e230 +// __output + +// LIBRARY: LEGO1 0x1008ecf0 +// __fltin2 + +// LIBRARY: LEGO1 0x1008ed90 +// __mtinitlocks + +// LIBRARY: LEGO1 0x1008edc0 +// __mtdeletelocks + +// LIBRARY: LEGO1 0x1008ee30 +// __lock + +// LIBRARY: LEGO1 0x1008eea0 +// __unlock + +// LIBRARY: LEGO1 0x1008eec0 +// __lock_file + +// LIBRARY: LEGO1 0x1008ef00 +// __lock_file2 + +// LIBRARY: LEGO1 0x1008ef30 +// __unlock_file + +// LIBRARY: LEGO1 0x1008ef70 +// __unlock_file2 + +// LIBRARY: LEGO1 0x1008efa0 +// __stbuf + +// LIBRARY: LEGO1 0x1008f040 +// __ftbuf + +// LIBRARY: LEGO1 0x1008f080 +// __write + +// LIBRARY: LEGO1 0x1008f100 +// __write_lk + +// LIBRARY: LEGO1 0x1008f340 +// __flush + +// LIBRARY: LEGO1 0x1008f490 +// __filbuf + +// LIBRARY: LEGO1 0x1008f590 +// __read + +// LIBRARY: LEGO1 0x1008f610 +// __read_lk + +// LIBRARY: LEGO1 0x1008f840 +// __ioinit + +// LIBRARY: LEGO1 0x1008fa20 +// __ioterm + +// LIBRARY: LEGO1 0x1008fb20 +// __close + +// LIBRARY: LEGO1 0x1008fb90 +// __close_lk + +// LIBRARY: LEGO1 0x1008fc20 +// __freebuf + +// LIBRARY: LEGO1 0x1008fc90 +// __chkstk + +// LIBRARY: LEGO1 0x1008fcc0 +// __lseek + +// LIBRARY: LEGO1 0x1008fd40 +// __lseek_lk + +// LIBRARY: LEGO1 0x1008fdd0 +// __dosmaperr + +// LIBRARY: LEGO1 0x1008fe30 +// __unlock_file + +// LIBRARY: LEGO1 0x1008fe50 +// __errno + +// LIBRARY: LEGO1 0x1008fe60 +// ___doserrno + +// LIBRARY: LEGO1 0x1008fe70 +// __openfile + +// LIBRARY: LEGO1 0x10090080 +// __getstream + +// LIBRARY: LEGO1 0x100901f0 +// __tolower_lk + +// LIBRARY: LEGO1 0x100902e0 +// __spawnve + +// LIBRARY: LEGO1 0x10090580 +// __input + +// LIBRARY: LEGO1 0x100912e0 +// ?terminate@@YAXXZ + +// LIBRARY: LEGO1 0x10091360 +// ?_inconsistency@@YAXXZ + +// LIBRARY: LEGO1 0x100913e0 +// ___crtLCMapStringA + +// LIBRARY: LEGO1 0x10091640 +// __heap_init + +// LIBRARY: LEGO1 0x10091680 +// __heap_term + +// LIBRARY: LEGO1 0x100916c0 +// __setenvp + +// LIBRARY: LEGO1 0x100917b0 +// __setargv + +// LIBRARY: LEGO1 0x10091a20 +// __setmbcp + +// LIBRARY: LEGO1 0x10091d30 +// ___initmbctable + +// LIBRARY: LEGO1 0x10091d40 +// ___crtGetEnvironmentStringsA + +// LIBRARY: LEGO1 0x10091ed0 +// ___set_app_type + +// LIBRARY: LEGO1 0x10091ef0 +// __FF_MSGBANNER + +// LIBRARY: LEGO1 0x10091f30 +// __NMSG_WRITE + +// LIBRARY: LEGO1 0x10092130 +// _raise + +// LIBRARY: LEGO1 0x10092310 +// _siglookup + +// LIBRARY: LEGO1 0x100928c0 +// __fptrap + +// LIBRARY: LEGO1 0x100928d0 +// __ZeroTail + +// LIBRARY: LEGO1 0x10092940 +// __IncMan + +// LIBRARY: LEGO1 0x100929b0 +// __RoundMan + +// LIBRARY: LEGO1 0x10092a60 +// __CopyMan + +// LIBRARY: LEGO1 0x10092a80 +// __FillZeroMan + +// LIBRARY: LEGO1 0x10092a90 +// __IsZeroMan + +// LIBRARY: LEGO1 0x10092ab0 +// __ShrMan + +// LIBRARY: LEGO1 0x10092b60 +// __ld12cvt + +// LIBRARY: LEGO1 0x10092d30 +// __ld12tod + +// LIBRARY: LEGO1 0x10093037 +// __trandisp2 + +// LIBRARY: LEGO1 0x10093480 +// ___crtGetStringTypeA + +// LIBRARY: LEGO1 0x100935b0 +// __getbuf + +// LIBRARY: LEGO1 0x10093600 +// __isatty + +// LIBRARY: LEGO1 0x10093630 +// _wctomb + +// LIBRARY: LEGO1 0x10093690 +// __wctomb_lk + +// LIBRARY: LEGO1 0x10093730 +// __aulldiv + +// LIBRARY: LEGO1 0x100937a0 +// __aullrem + +// LIBRARY: LEGO1 0x10093820 +// ___strgtold12 + +// LIBRARY: LEGO1 0x10093f70 +// __alloc_osfhnd + +// LIBRARY: LEGO1 0x100940b0 +// __set_osfhnd + +// LIBRARY: LEGO1 0x10094160 +// __free_osfhnd + +// LIBRARY: LEGO1 0x10094200 +// __get_osfhandle + +// LIBRARY: LEGO1 0x10094250 +// __lock_fhandle + +// LIBRARY: LEGO1 0x100942c0 +// __unlock_fhandle + +// LIBRARY: LEGO1 0x100943a0 +// __sopen + +// LIBRARY: LEGO1 0x10095820 +// __mbsrchr + +// LIBRARY: LEGO1 0x100958b0 +// __mbschr + +// LIBRARY: LEGO1 0x10095f90 +// _mbtowc + +// LIBRARY: LEGO1 0x10095ff0 +// __mbtowc_lk + +// LIBRARY: LEGO1 0x10096190 +// ___sbh_new_region + +// LIBRARY: LEGO1 0x10096300 +// ___crtMessageBoxA + +// LIBRARY: LEGO1 0x10096490 +// ___addl + +// LIBRARY: LEGO1 0x100964c0 +// ___add_12 + +// LIBRARY: LEGO1 0x10096530 +// ___shl_12 + +// LIBRARY: LEGO1 0x10096570 +// ___shr_12 + +// LIBRARY: LEGO1 0x100965b0 +// ___mtold12 + +// LIBRARY: LEGO1 0x10097190 +// ___ld12mul + +// LIBRARY: LEGO1 0x10097440 +// ___multtenpow12 + +// LIBRARY: LEGO1 0x100974c0 +// __chsize_lk + // LIBRARY: LEGO1 0x100977c0 // _itoa +// LIBRARY: LEGO1 0x10097ad0 +// _strrchr + // LIBRARY: LEGO1 0x10097b10 // _strchr +// LIBRARY: LEGO1 0x10097d70 +// __setmode_lk + // LIBRARY: LEGO1 0x100d1ed0 // _strnicmp @@ -141,7 +498,172 @@ // LIBRARY: LEGO1 0x100d2270 // __beginthreadex -// LIBRARY: LEGO1 0x100fc8bc +// GLOBAL: LEGO1 0x100daab8 +// ___lookuptable + +// GLOBAL: LEGO1 0x100f0000 +// ___xc_a + +// GLOBAL: LEGO1 0x100f0020 +// ___xc_z + +// GLOBAL: LEGO1 0x100f0024 +// ___xi_a + +// GLOBAL: LEGO1 0x100f0030 +// ___xi_z + +// GLOBAL: LEGO1 0x100fc8bc // __NLG_Destination +// GLOBAL: LEGO1 0x100fc8f0 +// __iob + +// GLOBAL: LEGO1 0x100fcb70 +// __cflush + +// GLOBAL: LEGO1 0x100fcb74 +// __umaskval + +// GLOBAL: LEGO1 0x100fcb78 +// __osver + +// GLOBAL: LEGO1 0x100fcb7c +// __winver + +// GLOBAL: LEGO1 0x100fcb80 +// __winmajor + +// GLOBAL: LEGO1 0x100fcb84 +// __winminor + +// GLOBAL: LEGO1 0x100fcb88 +// ___argc + +// GLOBAL: LEGO1 0x100fcb8c +// ___argv + +// GLOBAL: LEGO1 0x100fcb94 +// __environ + +// GLOBAL: LEGO1 0x100fcba4 +// __pgmptr + +// GLOBAL: LEGO1 0x100fcbb0 +// __C_Termination_Done + +// GLOBAL: LEGO1 0x100fcf04 +// __aenvptr + +// GLOBAL: LEGO1 0x100fcf10 +// ___error_mode + +// GLOBAL: LEGO1 0x100fcf14 +// ___app_type + +// GLOBAL: LEGO1 0x100fcf20 +// ___tlsindex + +// GLOBAL: LEGO1 0x100fcf60 +// __OP_ACOSjmptab + +// GLOBAL: LEGO1 0x100fcff0 +// __pctype + +// GLOBAL: LEGO1 0x100fd1fc +// ___mb_cur_max + +// GLOBAL: LEGO1 0x100fd200 +// ___decimal_point + +// GLOBAL: LEGO1 0x100fd210 +// ___nullstring + +// GLOBAL: LEGO1 0x100fd214 +// ___wnullstring + +// GLOBAL: LEGO1 0x100fd218 +// __locktable + +// GLOBAL: LEGO1 0x100fd2d8 +// __stdbuf + +// GLOBAL: LEGO1 0x100fd2e0 +// ___badioinfo + +// GLOBAL: LEGO1 0x100fd478 +// ___lc_handle + +// GLOBAL: LEGO1 0x100fd490 +// ___lc_codepage + +// GLOBAL: LEGO1 0x100fd624 +// ?__pInconsistency@@3P6AXXZA + +// GLOBAL: LEGO1 0x100fd638 +// __mbctype + +// GLOBAL: LEGO1 0x100fd73c +// ___mbcodepage + +// GLOBAL: LEGO1 0x100fd740 +// ___mblcid + +// GLOBAL: LEGO1 0x100fd748 +// ___mbulinfo + +// GLOBAL: LEGO1 0x100fd8e8 +// __adbgmsg + +// GLOBAL: LEGO1 0x100fd910 +// __XcptActTab + +// GLOBAL: LEGO1 0x100fd988 +// __First_FPE_Indx + +// GLOBAL: LEGO1 0x100fd98c +// __Num_FPE + +// GLOBAL: LEGO1 0x100fda10 +// __commode + +// GLOBAL: LEGO1 0x100fe250 +// ___small_block_heap + +// GLOBAL: LEGO1 0x100feb58 +// __matherr_flag + +// GLOBAL: LEGO1 0x100feb7c +// __fmode + +// GLOBAL: LEGO1 0x101028da +// __OP_POWjmptab + +// GLOBAL: LEGO1 0x101095f8 +// __crtheap + +// GLOBAL: LEGO1 0x101095fc +// ___setlc_active + +// GLOBAL: LEGO1 0x10109600 +// ___unguarded_readlc_active + +// GLOBAL: LEGO1 0x10109610 +// ___pioinfo + +// GLOBAL: LEGO1 0x10109710 +// __nhandle + +// GLOBAL: LEGO1 0x10109714 +// __acmdln + +// GLOBAL: LEGO1 0x10109718 +// __pRawDllMain + +// GLOBAL: LEGO1 0x10109724 +// ___piob + +// GLOBAL: LEGO1 0x1010a730 +// __nstream + #endif From f24213038232e685d604e046edcad44760b30eff Mon Sep 17 00:00:00 2001 From: MS Date: Sun, 1 Sep 2024 01:37:32 -0400 Subject: [PATCH 14/18] Sanitize args for assert in BETA10 (#1095) --- tools/isledecomp/isledecomp/compare/asm/fixes.py | 12 ++++++++++++ tools/isledecomp/isledecomp/compare/core.py | 7 ++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/isledecomp/isledecomp/compare/asm/fixes.py b/tools/isledecomp/isledecomp/compare/asm/fixes.py index bca22681..d0e326da 100644 --- a/tools/isledecomp/isledecomp/compare/asm/fixes.py +++ b/tools/isledecomp/isledecomp/compare/asm/fixes.py @@ -300,3 +300,15 @@ def find_effective_match( ) return corrections.issuperset(recomp_lines_disputed) + + +def assert_fixup(asm: List[Tuple[str, str]]): + """Detect assert calls and replace the code filename and line number + values with macros (from assert.h).""" + for i, (_, line) in enumerate(asm): + if "_assert" in line and line.startswith("call"): + try: + asm[i - 3] = (asm[i - 3][0], "push __LINE__") + asm[i - 2] = (asm[i - 2][0], "push __FILE__") + except IndexError: + continue diff --git a/tools/isledecomp/isledecomp/compare/core.py b/tools/isledecomp/isledecomp/compare/core.py index 8a1fc153..1ba77f27 100644 --- a/tools/isledecomp/isledecomp/compare/core.py +++ b/tools/isledecomp/isledecomp/compare/core.py @@ -13,7 +13,7 @@ from isledecomp.dir import walk_source_dir from isledecomp.types import SymbolType from isledecomp.compare.asm import ParseAsm -from isledecomp.compare.asm.fixes import find_effective_match +from isledecomp.compare.asm.fixes import assert_fixup, find_effective_match from .db import CompareDb, MatchInfo from .diff import combined_diff from .lines import LinesDb @@ -661,6 +661,11 @@ def recomp_lookup(addr: int, exact: bool) -> Optional[str]: if self.debug: self._dump_asm(orig_combined, recomp_combined) + # Check for assert calls only if we expect to find them + if self.orig_bin.is_debug or self.recomp_bin.is_debug: + assert_fixup(orig_combined) + assert_fixup(recomp_combined) + # Detach addresses from asm lines for the text diff. orig_asm = [x[1] for x in orig_combined] recomp_asm = [x[1] for x in recomp_combined] From 2af5f87051e2428dd06aaf943f929f71691d0462 Mon Sep 17 00:00:00 2001 From: MS Date: Sun, 1 Sep 2024 14:51:33 -0400 Subject: [PATCH 15/18] MxTimer touch-up (#1096) --- LEGO1/omni/include/mxtimer.h | 12 ++++++++++-- LEGO1/omni/src/common/mxtimer.cpp | 20 +++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/LEGO1/omni/include/mxtimer.h b/LEGO1/omni/include/mxtimer.h index 034b1565..02e55146 100644 --- a/LEGO1/omni/include/mxtimer.h +++ b/LEGO1/omni/include/mxtimer.h @@ -4,6 +4,7 @@ #include "mxcore.h" // VTABLE: LEGO1 0x100dc0e0 +// VTABLE: BETA10 0x101c1bb0 // SIZE 0x10 class MxTimer : public MxCore { public: @@ -14,19 +15,23 @@ class MxTimer : public MxCore { MxLong GetRealTime(); + // FUNCTION: BETA10 0x1012bf50 + void InitLastTimeCalculated() { g_lastTimeCalculated = m_startTime; } + // FUNCTION: BETA10 0x10017810 MxLong GetTime() { // Note that the BETA10 implementation differs - it only consists of the second branch of this `if` call - if (this->m_isRunning) { + if (m_isRunning) { return g_lastTimeTimerStarted; } else { - return g_lastTimeCalculated - this->m_startTime; + return g_lastTimeCalculated - m_startTime; } } // SYNTHETIC: LEGO1 0x100ae0d0 + // SYNTHETIC: BETA10 0x1012bf80 // MxTimer::`scalar deleting destructor' private: @@ -37,4 +42,7 @@ class MxTimer : public MxCore { static MxLong g_lastTimeTimerStarted; }; +// SYNTHETIC: BETA10 0x1012bfc0 +// MxTimer::~MxTimer + #endif // MXTIMER_H diff --git a/LEGO1/omni/src/common/mxtimer.cpp b/LEGO1/omni/src/common/mxtimer.cpp index 0d6d00f1..98111b50 100644 --- a/LEGO1/omni/src/common/mxtimer.cpp +++ b/LEGO1/omni/src/common/mxtimer.cpp @@ -3,40 +3,42 @@ #include // GLOBAL: LEGO1 0x10101414 +// GLOBAL: BETA10 0x10201f84 MxLong MxTimer::g_lastTimeCalculated = 0; // GLOBAL: LEGO1 0x10101418 MxLong MxTimer::g_lastTimeTimerStarted = 0; // FUNCTION: LEGO1 0x100ae060 +// FUNCTION: BETA10 0x1012bea0 MxTimer::MxTimer() { - this->m_isRunning = FALSE; + m_isRunning = FALSE; m_startTime = timeGetTime(); - // yeah this is somehow what the asm is - g_lastTimeCalculated = m_startTime; + InitLastTimeCalculated(); } // FUNCTION: LEGO1 0x100ae140 +// FUNCTION: BETA10 0x1012bf23 MxLong MxTimer::GetRealTime() { MxTimer::g_lastTimeCalculated = timeGetTime(); - return MxTimer::g_lastTimeCalculated - this->m_startTime; + return MxTimer::g_lastTimeCalculated - m_startTime; } // FUNCTION: LEGO1 0x100ae160 void MxTimer::Start() { - g_lastTimeTimerStarted = this->GetRealTime(); - this->m_isRunning = TRUE; + g_lastTimeTimerStarted = GetRealTime(); + m_isRunning = TRUE; } // FUNCTION: LEGO1 0x100ae180 void MxTimer::Stop() { - MxLong elapsed = this->GetRealTime(); + MxLong elapsed = GetRealTime(); MxLong startTime = elapsed - MxTimer::g_lastTimeTimerStarted; - this->m_isRunning = FALSE; + m_isRunning = FALSE; // this feels very stupid but it's what the assembly does - this->m_startTime = this->m_startTime + startTime - 5; + m_startTime = m_startTime + startTime - 5; } From 30be1ed4b8e079786386e32ef54e43168fca905f Mon Sep 17 00:00:00 2001 From: MS Date: Sun, 1 Sep 2024 16:34:58 -0400 Subject: [PATCH 16/18] Brute force string search for BETA10 (#1097) * Brute force string search for BETA10 * improved string check * Skip this unless source binary is debug * remove misplaced comment --- tools/isledecomp/isledecomp/bin.py | 16 +++++++++ tools/isledecomp/isledecomp/compare/core.py | 39 +++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/tools/isledecomp/isledecomp/bin.py b/tools/isledecomp/isledecomp/bin.py index 05ecfa92..2f20224b 100644 --- a/tools/isledecomp/isledecomp/bin.py +++ b/tools/isledecomp/isledecomp/bin.py @@ -465,6 +465,22 @@ def _populate_exports(self, export_rva: int, _: int): for (func_addr, name_addr) in combined ] + def iter_string(self, encoding: str = "ascii") -> Iterator[Tuple[int, str]]: + """Search for possible strings at each verified address in .data.""" + section = self.get_section_by_name(".data") + for addr in self._relocated_addrs: + if section.contains_vaddr(addr): + raw = self.read_string(addr) + if raw is None: + continue + + try: + string = raw.decode(encoding) + except UnicodeDecodeError: + continue + + yield (addr, string) + def get_section_by_name(self, name: str) -> Section: section = next( filter(lambda section: section.match_name(name), self.sections), diff --git a/tools/isledecomp/isledecomp/compare/core.py b/tools/isledecomp/isledecomp/compare/core.py index 1ba77f27..c44f3987 100644 --- a/tools/isledecomp/isledecomp/compare/core.py +++ b/tools/isledecomp/isledecomp/compare/core.py @@ -82,8 +82,9 @@ def __init__( self._load_cvdump() self._load_markers() - self._find_original_strings() + # Detect floats first to eliminate potential overlap with string data self._find_float_const() + self._find_original_strings() self._match_imports() self._match_exports() self._match_thunks() @@ -314,7 +315,7 @@ def _find_original_strings(self): """Go to the original binary and look for the specified string constants to find a match. This is a (relatively) expensive operation so we only look at strings that we have not already matched via a STRING annotation.""" - + # Release builds give each de-duped string a symbol so they are easy to find and match. for string in self._db.get_unmatched_strings(): addr = self.orig_bin.find_string(string.encode("latin1")) if addr is None: @@ -324,6 +325,40 @@ def _find_original_strings(self): self._db.match_string(addr, string) + def is_real_string(s: str) -> bool: + """Heuristic to ignore values that only look like strings. + This is mostly about short strings (len <= 4) that could be byte or word values. + """ + # 0x10 is the MSB of the address space for DLLs (LEGO1), so this is a pointer + if len(s) == 0 or "\x10" in s: + return False + + # assert(0) is common + if len(s) == 1 and s[0] != "0": + return False + + # Hack because str.isprintable() will fail on strings with newlines or tabs + if len(s) <= 4 and "\\x" in repr(s): + return False + + return True + + # Debug builds do not de-dupe the strings, so we need to find them via brute force scan. + # We could try to match the string addrs if there is only one in orig and recomp. + # When we sanitize the asm, the result is the same regardless. + if self.orig_bin.is_debug: + for addr, string in self.orig_bin.iter_string("latin1"): + if is_real_string(string): + self._db.set_orig_symbol( + addr, SymbolType.STRING, string, len(string) + ) + + for addr, string in self.recomp_bin.iter_string("latin1"): + if is_real_string(string): + self._db.set_recomp_symbol( + addr, SymbolType.STRING, string, None, len(string) + ) + def _find_float_const(self): """Add floating point constants in each binary to the database. We are not matching anything right now because these values are not From 73938ac2ab4fcfc64ae2757a86e9d1ca93061c3d Mon Sep 17 00:00:00 2001 From: MS Date: Sun, 1 Sep 2024 20:08:53 -0400 Subject: [PATCH 17/18] Beta match MxDSFile (#1098) --- LEGO1/omni/include/mxdsfile.h | 19 +++++--- LEGO1/omni/src/stream/mxdsfile.cpp | 75 ++++++++++++++++++------------ 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/LEGO1/omni/include/mxdsfile.h b/LEGO1/omni/include/mxdsfile.h index 524b7fee..09772b68 100644 --- a/LEGO1/omni/include/mxdsfile.h +++ b/LEGO1/omni/include/mxdsfile.h @@ -9,6 +9,7 @@ #include // VTABLE: LEGO1 0x100dc890 +// VTABLE: BETA10 0x101c2418 // SIZE 0x7c class MxDSFile : public MxDSSource { public: @@ -20,10 +21,12 @@ class MxDSFile : public MxDSSource { // We have to explicitly use dllexport, otherwise this function cannot be exported, // since it is inlined everywhere in LEGO1.DLL // FUNCTION: LEGO1 0x100bfed0 + // FUNCTION: BETA10 0x10148ac0 __declspec(dllexport) ~MxDSFile() override { Close(); } #endif // FUNCTION: LEGO1 0x100c0120 + // FUNCTION: BETA10 0x10148dc0 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10102594 @@ -31,38 +34,42 @@ class MxDSFile : public MxDSSource { } // FUNCTION: LEGO1 0x100c0130 + // FUNCTION: BETA10 0x10148de0 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSFile::ClassName()) || MxDSSource::IsA(p_name); } - MxLong Open(MxULong) override; // vtable+0x14 - MxLong Close() override; // vtable+0x18 + MxResult Open(MxULong) override; // vtable+0x14 + MxResult Close() override; // vtable+0x18 MxResult Read(unsigned char*, MxULong) override; // vtable+0x20 - MxLong Seek(MxLong, int) override; // vtable+0x24 + MxResult Seek(MxLong, int) override; // vtable+0x24 MxULong GetBufferSize() override; // vtable+0x28 MxULong GetStreamBuffersNum() override; // vtable+0x2c + // FUNCTION: BETA10 0x1015e110 void SetFileName(const char* p_filename) { m_filename = p_filename; } MxS32 CalcFileSize() { return GetFileSize(m_io.m_info.hmmio, NULL); } // SYNTHETIC: LEGO1 0x100c01e0 + // SYNTHETIC: BETA10 0x10148e40 // MxDSFile::`scalar deleting destructor' // SIZE 0x0c struct ChunkHeader { + // FUNCTION: BETA10 0x1015e040 ChunkHeader() : m_majorVersion(0), m_minorVersion(0), m_bufferSize(0), m_streamBuffersNum(0) {} - MxU16 m_majorVersion; // 0x00 - MxU16 m_minorVersion; // 0x02 + MxS16 m_majorVersion; // 0x00 + MxS16 m_minorVersion; // 0x02 MxULong m_bufferSize; // 0x04 MxS16 m_streamBuffersNum; // 0x08 MxS16 m_reserved; // 0x0a }; private: - MxLong ReadChunks(); + MxResult ReadChunks(); MxString m_filename; // 0x14 MXIOINFO m_io; // 0x24 diff --git a/LEGO1/omni/src/stream/mxdsfile.cpp b/LEGO1/omni/src/stream/mxdsfile.cpp index 9b6fa661..0f3b5227 100644 --- a/LEGO1/omni/src/stream/mxdsfile.cpp +++ b/LEGO1/omni/src/stream/mxdsfile.cpp @@ -1,6 +1,7 @@ #include "mxdsfile.h" #include "decomp.h" +#include "mxdebug.h" #include @@ -11,42 +12,44 @@ DECOMP_SIZE_ASSERT(MxDSFile::ChunkHeader, 0x0c) DECOMP_SIZE_ASSERT(MxDSFile, 0x7c) // FUNCTION: LEGO1 0x100cc4b0 +// FUNCTION: BETA10 0x1015db90 MxDSFile::MxDSFile(const char* p_filename, MxULong p_skipReadingChunks) { - m_filename = p_filename; + SetFileName(p_filename); m_skipReadingChunks = p_skipReadingChunks; } // FUNCTION: LEGO1 0x100cc590 -MxLong MxDSFile::Open(MxULong p_uStyle) +// FUNCTION: BETA10 0x1015dc57 +MxResult MxDSFile::Open(MxULong p_uStyle) { - MXIOINFO& io = m_io; - MxLong longResult = 1; - memset(&io, 0, sizeof(MXIOINFO)); + MxResult result = -FAILURE; // Non-standard value of 1 here + memset(&m_io, 0, sizeof(MXIOINFO)); - if (io.Open(m_filename.GetData(), p_uStyle) != 0) { + if (m_io.Open(m_filename.GetData(), p_uStyle) != 0) { return -1; } - io.SetBuffer(NULL, 0, 0); + m_io.SetBuffer(NULL, 0, 0); m_position = 0; if (m_skipReadingChunks == 0) { - longResult = ReadChunks(); + result = ReadChunks(); } - if (longResult != 0) { + if (result != SUCCESS) { Close(); } else { Seek(0, 0); } - return longResult; + return result; } // FUNCTION: LEGO1 0x100cc620 -MxLong MxDSFile::ReadChunks() +// FUNCTION: BETA10 0x1015dd18 +MxResult MxDSFile::ReadChunks() { _MMCKINFO topChunk; _MMCKINFO childChunk; @@ -54,33 +57,37 @@ MxLong MxDSFile::ReadChunks() topChunk.fccType = FOURCC('O', 'M', 'N', 'I'); if (m_io.Descend(&topChunk, NULL, MMIO_FINDRIFF) != 0) { - return -1; + MxTrace("Unable to find Streamer RIFF chunk in file: %s\n", m_filename); + return FAILURE; } + childChunk.ckid = FOURCC('M', 'x', 'H', 'd'); if (m_io.Descend(&childChunk, &topChunk, 0) != 0) { - return -1; + MxTrace("Unable to find Header chunk in file: %s\n", m_filename); + return FAILURE; } m_io.Read(&m_header, 0x0c); - if ((m_header.m_majorVersion == SI_MAJOR_VERSION) && (m_header.m_minorVersion == SI_MINOR_VERSION)) { - childChunk.ckid = FOURCC('M', 'x', 'O', 'f'); - if (m_io.Descend(&childChunk, &topChunk, 0) != 0) { - return -1; - } - MxULong* pLengthInDWords = &m_lengthInDWords; - m_io.Read(pLengthInDWords, 4); - m_pBuffer = new MxU32[*pLengthInDWords]; - m_io.Read(m_pBuffer, *pLengthInDWords * 4); - return 0; - } - else { + if ((m_header.m_majorVersion != SI_MAJOR_VERSION) || (m_header.m_minorVersion != SI_MINOR_VERSION)) { sprintf(tempBuffer, "Wrong SI file version. %d.%d expected.", SI_MAJOR_VERSION, SI_MINOR_VERSION); MessageBoxA(NULL, tempBuffer, NULL, MB_ICONERROR); - return -1; + return FAILURE; } + + childChunk.ckid = FOURCC('M', 'x', 'O', 'f'); + if (m_io.Descend(&childChunk, &topChunk, 0) != 0) { + MxTrace("Unable to find Header chunk in file: %s\n", m_filename); + return FAILURE; + } + + m_io.Read(&m_lengthInDWords, 4); + m_pBuffer = new MxU32[m_lengthInDWords]; + m_io.Read(m_pBuffer, m_lengthInDWords * 4); + return SUCCESS; } // FUNCTION: LEGO1 0x100cc740 +// FUNCTION: BETA10 0x1015ded2 MxLong MxDSFile::Close() { m_io.Close(0); @@ -91,10 +98,12 @@ MxLong MxDSFile::Close() delete[] m_pBuffer; m_pBuffer = NULL; } - return 0; + + return SUCCESS; } // FUNCTION: LEGO1 0x100cc780 +// FUNCTION: BETA10 0x1015df50 MxResult MxDSFile::Read(unsigned char* p_buf, MxULong p_nbytes) { if (m_io.Read(p_buf, p_nbytes) != p_nbytes) { @@ -106,18 +115,26 @@ MxResult MxDSFile::Read(unsigned char* p_buf, MxULong p_nbytes) } // FUNCTION: LEGO1 0x100cc7b0 -MxLong MxDSFile::Seek(MxLong p_lOffset, MxS32 p_iOrigin) +// FUNCTION: BETA10 0x1015dfee +MxResult MxDSFile::Seek(MxLong p_lOffset, MxS32 p_iOrigin) { - return (m_position = m_io.Seek(p_lOffset, p_iOrigin)) == -1 ? -1 : 0; + m_position = m_io.Seek(p_lOffset, p_iOrigin); + if (m_position == -1) { + return FAILURE; + } + + return SUCCESS; } // FUNCTION: LEGO1 0x100cc7e0 +// FUNCTION: BETA10 0x10148d80 MxULong MxDSFile::GetBufferSize() { return m_header.m_bufferSize; } // FUNCTION: LEGO1 0x100cc7f0 +// FUNCTION: BETA10 0x10148da0 MxULong MxDSFile::GetStreamBuffersNum() { return m_header.m_streamBuffersNum; From 2b14d3d6a5d1f0b4f515ba61f93daaf4dafa3e6e Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Tue, 3 Sep 2024 22:50:30 +0200 Subject: [PATCH 18/18] Implement parts of `LegoCarBuild` and dependents (#1092) * Implement parts of `LegoCarBuild` and dependents * Fix BETA10 offset * Fix constants * Code style: Rename parameters * Linter fixes v2 * Linter errors v3 * Add BETA10 variable names for presenters * Address review comments --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/legocarbuild.h | 170 +++--- .../legoomni/include/legocarbuildpresenter.h | 3 + LEGO1/lego/legoomni/include/legoutils.h | 3 + .../lego/legoomni/include/legovideomanager.h | 3 + .../include/mxbackgroundaudiomanager.h | 2 +- .../src/audio/mxbackgroundaudiomanager.cpp | 1 + .../lego/legoomni/src/build/legocarbuild.cpp | 549 +++++++++++++++++- .../src/build/legocarbuildpresenter.cpp | 15 + .../legoomni/src/common/legogamestate.cpp | 13 +- LEGO1/lego/legoomni/src/common/legoutils.cpp | 44 ++ LEGO1/lego/legoomni/src/common/misc.cpp | 2 + .../src/control/legocontrolmanager.cpp | 1 + .../legoomni/src/input/legoinputmanager.cpp | 1 + LEGO1/lego/sources/3dmanager/lego3dmanager.h | 1 + LEGO1/lego/sources/3dmanager/tglsurface.h | 1 + LEGO1/library_msvc.h | 3 + LEGO1/mxgeometry/mxgeometry3d.h | 2 + LEGO1/realtime/vector.h | 6 + tools/ncc/skip.yml | 21 + 19 files changed, 744 insertions(+), 97 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index 4312c52b..d005cf3c 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -4,6 +4,11 @@ #include "legostate.h" #include "legoworld.h" +class LegoCarBuildAnimPresenter; +class MxControlPresenter; +class MxStillPresenter; +class MxSoundPresenter; + // VTABLE: LEGO1 0x100d66e0 // SIZE 0x50 class LegoVehicleBuildState : public LegoState { @@ -55,15 +60,13 @@ typedef LegoVehicleBuildState LegoDuneCarBuildState; typedef LegoVehicleBuildState LegoJetskiBuildState; // VTABLE: LEGO1 0x100d6658 +// VTABLE: BETA10 0x101bb880 // SIZE 0x34c class LegoCarBuild : public LegoWorld { public: LegoCarBuild(); ~LegoCarBuild() override; - MxLong Notify(MxParam& p_param) override; // vtable+0x04 - MxResult Tickle() override; // vtable+0x08 - // FUNCTION: LEGO1 0x10022940 const char* ClassName() const override // vtable+0x0c { @@ -71,79 +74,116 @@ class LegoCarBuild : public LegoWorld { return "LegoCarBuild"; } + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + // FUNCTION: LEGO1 0x10022950 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoCarBuild::ClassName()) || LegoWorld::IsA(p_name); } - MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void ReadyWorld() override; // vtable+0x50 - MxBool VTable0x5c() override; // vtable+0x5c - MxBool Escape() override; // vtable+0x64 - void Enable(MxBool p_enable) override; // vtable+0x68 - virtual void VTable0x6c(); // vtable+0x6c - virtual void VTable0x70(); // vtable+0x70 - virtual void VTable0x74(); // vtable+0x74 - virtual void VTable0x78(); // vtable+0x78 - virtual void VTable0x7c(); // vtable+0x7c - virtual void VTable0x80(); // vtable+0x80 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool Escape() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + virtual void VTable0x6c(); // vtable+0x6c + virtual void VTable0x70(); // vtable+0x70 + virtual void VTable0x74(MxFloat p_param1[3], MxFloat p_param2[3]); // vtable+0x74 + virtual void VTable0x78(MxFloat p_param1[3], MxFloat p_param2[3]); // vtable+0x78 + virtual void VTable0x7c(MxFloat p_param1[3], MxFloat p_param2[3]); // vtable+0x7c + virtual void VTable0x80( + MxFloat p_param1[2], + MxFloat p_param2[2], + MxFloat p_param3, + MxFloat p_param4[2] + ); // vtable+0x80 + + void InitPresenters(); + void FUN_10022f30(); + void FUN_10024ef0(); + void FUN_10024f50(); + void SetPresentersEnabled(MxBool p_enabled); + void TogglePresentersEnabled(); + undefined4 FUN_10025720(undefined4 p_param1); + MxS32 FUN_10025d70(); + void FUN_10025db0(const char* p_param1, undefined4 p_param2); + MxS32 FUN_10025ee0(undefined4 p_param1); // SYNTHETIC: LEGO1 0x10022a60 // LegoCarBuild::`scalar deleting destructor' private: - undefined4 m_unk0xf8; // 0xf8 - undefined m_unk0xfc[0x8]; // 0xfc - undefined4 m_unk0x104; // 0x104 - undefined m_unk0x108; // 0x108 - undefined m_unk0x109; // 0x109 - undefined4 m_unk0x10c; // 0x10c - undefined4 m_unk0x110; // 0x110 - Mx3DPointFloat m_unk0x114; // 0x114 - undefined4 m_unk0x128; // 0x128 - MxMatrix m_unk0x12c; // 0x12c - undefined m_unk0x174; // 0x174 - MxMatrix m_unk0x178; // 0x178 - MxMatrix m_unk0x1c0; // 0x1c0 - MxMatrix m_unk0x208; // 0x208 - undefined m_unk0x250[0x08]; // 0x250 - undefined4 m_unk0x258; // 0x258 - Mx4DPointFloat m_unk0x25c; // 0x25c - Mx4DPointFloat m_unk0x274; // 0x274 - undefined m_unk0x28c[0x18]; // 0x28c - Mx4DPointFloat m_unk0x2a4; // 0x2a4 - Mx4DPointFloat m_unk0x2bc; // 0x2bc - undefined m_unk0x2d4; // 0x2d4 - undefined4 m_unk0x2dc; // 0x2dc - undefined4 m_unk0x2e0; // 0x2e0 - undefined4 m_unk0x2e4; // 0x2e4 - undefined4 m_unk0x2e8; // 0x2e8 - undefined4 m_unk0x2ec; // 0x2ec - undefined4 m_unk0x2f0; // 0x2f0 - undefined4 m_unk0x2f4; // 0x2f4 - undefined4 m_unk0x2f8; // 0x2f8 - undefined4 m_unk0x2fc; // 0x2fc - undefined4 m_unk0x300; // 0x300 - undefined4 m_unk0x304; // 0x304 - undefined4 m_unk0x308; // 0x308 - undefined4 m_unk0x30c; // 0x30c - undefined4 m_unk0x310; // 0x310 - undefined4 m_unk0x314; // 0x314 - undefined4 m_unk0x318; // 0x318 - undefined4 m_unk0x31c; // 0x31c - undefined4 m_unk0x320; // 0x320 - undefined4 m_unk0x324; // 0x324 - undefined4 m_unk0x328; // 0x328 - undefined4 m_unk0x2d8; // 0x2d8 - undefined4 m_unk0x32c; // 0x32c - undefined4 m_unk0x330; // 0x330 - undefined4 m_unk0x334; // 0x334 - undefined4 m_unk0x338; // 0x338 - undefined4 m_unk0x33c; // 0x33c - undefined4 m_unk0x340; // 0x340 - undefined4 m_unk0x344; // 0x344 - undefined4 m_unk0x348; // 0x348 + undefined4 m_unk0xf8; // 0xf8 + MxS16 m_unk0xfc; // 0xfc + undefined m_unk0xfe[2]; // 0xfe + undefined4 m_unk0x100; // 0x100 + undefined4 m_unk0x104; // 0x104 + undefined m_unk0x108; // 0x108 + undefined m_unk0x109; // 0x109 + MxU16 m_unk0x10a; // 0x10a + DWORD m_unk0x10c; // 0x10c + LegoROI* m_unk0x110; // 0x110 + Mx3DPointFloat m_unk0x114; // 0x114 + undefined4 m_unk0x128; // 0x128 + MxMatrix m_unk0x12c; // 0x12c + undefined m_unk0x174; // 0x174 + MxMatrix m_unk0x178; // 0x178 + MxMatrix m_unk0x1c0; // 0x1c0 + MxMatrix m_unk0x208; // 0x208 + undefined m_unk0x250[0x08]; // 0x250 + LegoCarBuildAnimPresenter* m_unk0x258; // 0x258 + UnknownMx4DPointFloat m_unk0x25c; // 0x25c + + // These four are likely locations in pixel space + MxS32 m_unk0x290; // 0x290 + MxS32 m_unk0x294; // 0x294 + MxS32 m_unk0x298; // 0x298 + MxS32 m_unk0x29c; // 0x29c + + MxFloat m_unk0x2a0; // 0x2a0 + Mx4DPointFloat m_unk0x2a4; // 0x2a4 + Mx4DPointFloat m_unk0x2bc; // 0x2bc + MxBool m_unk0x2d4; // 0x2d4 + + // variable names verified by BETA10 0x1006b27a + MxStillPresenter* m_ColorBook_Bitmap; // 0x2dc + MxControlPresenter* m_Yellow_Ctl; // 0x2e0 + MxControlPresenter* m_Red_Ctl; // 0x2e4 + MxControlPresenter* m_Blue_Ctl; // 0x2e8 + MxControlPresenter* m_Green_Ctl; // 0x2ec + MxControlPresenter* m_Gray_Ctl; // 0x2f0 + MxControlPresenter* m_Black_Ctl; // 0x2f4 + MxSoundPresenter* m_Shelf_Sound; // 0x2f8 + MxSoundPresenter* m_PlaceBrick_Sound; // 0x2fc + MxSoundPresenter* m_GetBrick_Sound; // 0x300 + MxSoundPresenter* m_Paint_Sound; // 0x304 + MxSoundPresenter* m_Decal_Sound; // 0x308 + MxStillPresenter* m_Decal_Bitmap; // 0x30c + MxControlPresenter* m_Decals_Ctl; // 0x310 + MxControlPresenter* m_Decals_Ctl1; // 0x314 + MxControlPresenter* m_Decals_Ctl2; // 0x318 + MxControlPresenter* m_Decals_Ctl3; // 0x31c + MxControlPresenter* m_Decals_Ctl4; // 0x320 + MxControlPresenter* m_Decals_Ctl5; // 0x324 + MxControlPresenter* m_Decals_Ctl6; // 0x328 + MxControlPresenter* m_Decals_Ctl7; // 0x32c + + // variable name verified by BETA10 0x1006b219 + LegoVehicleBuildState* m_buildState; // 0x32c + + undefined4 m_unk0x330; // 0x330 + undefined4 m_unk0x334; // 0x334 + undefined4 m_unk0x338; // 0x338 + MxControlPresenter* m_unk0x33c; // 0x33c + undefined4 m_unk0x340; // 0x340 + undefined4 m_unk0x344; // 0x344 + MxU8 m_presentersEnabled; // 0x348 + + static MxS16 g_unk0x100f11cc; + static MxFloat g_unk0x100d65a4; + static MxFloat g_unk0x100d65a8; }; #endif // LEGOCARBUILD_H diff --git a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h index 25253a6b..8c97666c 100644 --- a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h +++ b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h @@ -37,6 +37,9 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { void EndAction() override; // vtable+0x40 void PutFrame() override; // vtable+0x6c + void FUN_10079920(float p_param1); + MxBool FUN_10079ca0(const char* p_param1); + // SYNTHETIC: LEGO1 0x10078660 // LegoCarBuildAnimPresenter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h index adb09677..ee0a001d 100644 --- a/LEGO1/lego/legoomni/include/legoutils.h +++ b/LEGO1/lego/legoomni/include/legoutils.h @@ -39,6 +39,9 @@ extern MxAtomId* g_isleScript; LegoEntity* PickEntity(MxLong, MxLong); LegoROI* PickROI(MxLong, MxLong); LegoROI* PickParentROI(MxLong p_a, MxLong p_b); +void FUN_1003dde0(LegoROI* p_param1, MxFloat p_param2); +MxBool FUN_1003ded0(MxFloat p_param1[3], MxFloat p_param2[3], MxFloat p_param3[3]); +MxBool TransformWorldToScreen(const MxFloat p_world[3], MxFloat p_screen[4]); MxS16 CountTotalTreeNodes(LegoTreeNode* p_node); void FUN_1003e050(LegoAnimPresenter* p_presenter); Extra::ActionType MatchActionString(const char*); diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h index c077422c..edfd345e 100644 --- a/LEGO1/lego/legoomni/include/legovideomanager.h +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -49,7 +49,10 @@ class LegoVideoManager : public MxVideoManager { void FUN_1007c520(); Tgl::Renderer* GetRenderer() { return m_renderer; } + + // FUNCTION: BETA10 0x100117e0 Lego3DManager* Get3DManager() { return m_3dManager; } + LegoROI* GetViewROI() { return m_viewROI; } MxDirect3D* GetDirect3D() { return m_direct3d; } MxBool GetRender3D() { return m_render3d; } diff --git a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h index 5407a282..20aa07bb 100644 --- a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h +++ b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h @@ -43,6 +43,7 @@ class MxBackgroundAudioManager : public MxCore { void Enable(MxBool p_enable); virtual MxResult Create(MxAtomId& p_script, MxU32 p_frequencyMS); + void Init(); void Stop(); void LowerVolume(); void RaiseVolume(); @@ -51,7 +52,6 @@ class MxBackgroundAudioManager : public MxCore { // MxBackgroundAudioManager::`scalar deleting destructor' private: - void Init(); MxResult OpenMusic(MxAtomId& p_script); void DestroyMusic(); diff --git a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index d10888ff..90d9df9b 100644 --- a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -273,6 +273,7 @@ MxResult MxBackgroundAudioManager::PlayMusic(MxDSAction& p_action, undefined4 p_ } // FUNCTION: LEGO1 0x1007f470 +// FUNCTION: BETA10 0x100e9388 void MxBackgroundAudioManager::Stop() { if (m_action2.GetObjectId() != -1) { diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index e5d2c381..5241638d 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -1,102 +1,595 @@ #include "legocarbuild.h" +#include "legocarbuildpresenter.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoutils.h" +#include "misc.h" +#include "mxbackgroundaudiomanager.h" +#include "mxcontrolpresenter.h" +#include "mxmisc.h" +#include "mxnotificationmanager.h" +#include "mxsoundpresenter.h" +#include "mxstillpresenter.h" +#include "mxticklemanager.h" +#include "scripts.h" + DECOMP_SIZE_ASSERT(LegoCarBuild, 0x34c) DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50) +// GLOBAL: LEGO1 0x100d65a4 +MxFloat LegoCarBuild::g_unk0x100d65a4 = -0.1f; + +// GLOBAL: LEGO1 0x100d65a8 +MxFloat LegoCarBuild::g_unk0x100d65a8 = 0.07; + +// GLOBAL: LEGO1 0x100f11cc +MxS16 LegoCarBuild::g_unk0x100f11cc = -1; + // STUB: LEGO1 0x100226d0 +// FUNCTION: BETA10 0x1006ac10 LegoCarBuild::LegoCarBuild() { - // TODO + // Not close yet - might be getting there when more of this class is implemented + m_unk0x100 = 0; + m_unk0x110 = 0; + m_unk0xf8 = 0xffffffff; + m_unk0x2d4 = '\0'; + m_unk0x258 = 0; + m_ColorBook_Bitmap = 0; + m_Yellow_Ctl = 0; + m_Red_Ctl = 0; + m_Blue_Ctl = 0; + m_Green_Ctl = 0; + m_Gray_Ctl = 0; + m_Black_Ctl = 0; + m_Shelf_Sound = 0; + m_PlaceBrick_Sound = 0; + m_GetBrick_Sound = 0; + m_Paint_Sound = 0; + m_Decal_Sound = 0; + m_Decal_Bitmap = 0; + m_Decals_Ctl = 0; + m_Decals_Ctl1 = 0; + m_Decals_Ctl2 = 0; + m_Decals_Ctl3 = 0; + m_Decals_Ctl4 = 0; + m_Decals_Ctl5 = 0; + m_Decals_Ctl6 = 0; + m_Decals_Ctl7 = NULL; + m_unk0x33c = 0; + m_buildState = 0; + m_unk0x104 = 0; + m_unk0x109 = '\0'; + m_unk0x108 = '\0'; + m_unk0x338 = 0; + m_unk0x334 = 0; + m_unk0x344 = 0xffffffff; + m_unk0x174 = '\0'; + NotificationManager()->Register(this); } // FUNCTION: LEGO1 0x10022930 +// FUNCTION: BETA10 0x10070070 MxBool LegoCarBuild::VTable0x5c() { return TRUE; } // STUB: LEGO1 0x10022a80 +// FUNCTION: BETA10 0x1006aea3 LegoCarBuild::~LegoCarBuild() { // TODO + // ... + NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x10022b70 +// FUNCTION: LEGO1 0x10022b70 +// FUNCTION: BETA10 0x1006afd9 MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult result = LegoWorld::Create(p_dsAction); + + if (!result) { + // TickleManager()->RegisterClient(this, 100); + InputManager()->SetWorld(this); + ControlManager()->Register(this); + + SetIsWorldActive(FALSE); + + InputManager()->Register(this); + + // variable name verified by BETA10 0x1006b1a6 + const char* buildStateClassName = NULL; + + if (m_atomId == *g_copterScript) { + buildStateClassName = "LegoCopterBuildState"; + GameState()->SetCurrentArea(LegoGameState::Area::e_copterbuild); + m_unk0x330 = 1; + } + else if (m_atomId == *g_dunecarScript) { + buildStateClassName = "LegoDuneCarBuildState"; + GameState()->SetCurrentArea(LegoGameState::Area::e_dunecarbuild); + m_unk0x330 = 2; + } + else if (m_atomId == *g_jetskiScript) { + buildStateClassName = "LegoJetskiBuildState"; + GameState()->SetCurrentArea(LegoGameState::Area::e_jetskibuild); + m_unk0x330 = 3; + } + else if (m_atomId == *g_racecarScript) { + buildStateClassName = "LegoRaceCarBuildState"; + GameState()->SetCurrentArea(LegoGameState::Area::e_racecarbuild); + m_unk0x330 = 4; + } + + LegoGameState* gameState = GameState(); + + LegoVehicleBuildState* buildState = (LegoVehicleBuildState*) gameState->GetState(buildStateClassName); + + if (!buildState) { + buildState = (LegoVehicleBuildState*) gameState->CreateState(buildStateClassName); + } + + m_buildState = buildState; + m_unk0x174 = m_buildState->m_unk0x4d; + + GameState()->StopArea(LegoGameState::Area::e_previousArea); + + m_buildState->m_animationState = 1; + m_unk0x100 = 0; + + BackgroundAudioManager()->Stop(); + EnableAnimations(FALSE); + + result = SUCCESS; + } + + return result; } -// STUB: LEGO1 0x10022fc0 -void LegoCarBuild::VTable0x6c() +// FUNCTION: LEGO1 0x10022d10 +// FUNCTION: BETA10 0x1006b27a +void LegoCarBuild::InitPresenters() +{ + m_ColorBook_Bitmap = (MxStillPresenter*) Find("MxStillPresenter", "ColorBook_Bitmap"); + assert(m_ColorBook_Bitmap); + m_Yellow_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Yellow_Ctl"); + assert(m_Yellow_Ctl); + m_Red_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Red_Ctl"); + assert(m_Red_Ctl); + m_Blue_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Blue_Ctl"); + assert(m_Blue_Ctl); + m_Green_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Green_Ctl"); + assert(m_Green_Ctl); + m_Gray_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Gray_Ctl"); + assert(m_Gray_Ctl); + m_Black_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Black_Ctl"); + assert(m_Black_Ctl); + m_Shelf_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "Shelf_Sound"); + assert(m_Shelf_Sound); + m_PlaceBrick_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "PlaceBrick_Sound"); + assert(m_PlaceBrick_Sound); + m_GetBrick_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "GetBrick_Sound"); + assert(m_GetBrick_Sound); + m_Paint_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "Paint_Sound"); + assert(m_Paint_Sound); + m_Decal_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "Decal_Sound"); + m_Decals_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl"); + m_Decals_Ctl1 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl1"); + m_Decals_Ctl2 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl2"); + m_Decal_Bitmap = (MxStillPresenter*) Find("MxStillPresenter", "Decal_Bitmap"); + assert(m_Decal_Bitmap); + if (m_Decal_Bitmap) { + m_Decals_Ctl3 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl3"); + assert(m_Decals_Ctl3); + m_Decals_Ctl4 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl4"); + assert(m_Decals_Ctl4); + m_Decals_Ctl5 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl5"); + assert(m_Decals_Ctl5); + m_Decals_Ctl6 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl6"); + assert(m_Decals_Ctl6); + m_Decals_Ctl7 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl7"); + assert(m_Decals_Ctl7); + } +} + +// STUB: LEGO1 0x10022f30 +// STUB: BETA10 0x1006b835 +void LegoCarBuild::FUN_10022f30() { // TODO } +// FUNCTION: LEGO1 0x10022fc0 +// FUNCTION: BETA10 0x1006b90b +void LegoCarBuild::VTable0x6c() +{ + m_unk0x178 = m_unk0x1c0; + m_unk0x110->WrappedSetLocalTransform(m_unk0x178); + m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition()); + + VTable0x70(); +} + // STUB: LEGO1 0x10023020 +// FUNCTION: BETA10 0x1006b991 void LegoCarBuild::VTable0x70() { - // TODO + MxFloat worldPos[3]; + MxFloat screenPos[4]; + + worldPos[0] = m_unk0x2a4[0]; + worldPos[1] = m_unk0x2a4[1]; + worldPos[2] = m_unk0x2a4[2]; + + TransformWorldToScreen(worldPos, screenPos); + + m_unk0x290 = screenPos[0] / screenPos[3]; + m_unk0x294 = screenPos[1] / screenPos[3]; + + worldPos[0] = m_unk0x2bc[0]; + worldPos[1] = m_unk0x2bc[1]; + worldPos[2] = m_unk0x2bc[2]; + + TransformWorldToScreen(worldPos, screenPos); + + m_unk0x298 = screenPos[0] / screenPos[3]; + m_unk0x29c = screenPos[1] / screenPos[3]; + + m_unk0x2a0 = sqrt( + (MxFloat) (m_unk0x298 - m_unk0x290) * (m_unk0x298 - m_unk0x290) + + (m_unk0x29c - m_unk0x294) * (m_unk0x29c - m_unk0x294) + ); + + m_unk0x25c.Unknown1(m_unk0x178, m_unk0x208); } -// STUB: LEGO1 0x10023500 -void LegoCarBuild::VTable0x74() +// FUNCTION: LEGO1 0x10023500 +// FUNCTION: BETA10 0x1006bdf6 +void LegoCarBuild::VTable0x74(MxFloat p_param1[3], MxFloat p_param2[3]) { - // TODO + MxFloat fVar1; + MxFloat local20[3]; + MxFloat local14[3]; + + FUN_1003ded0(p_param1, local14, local20); + + fVar1 = (m_unk0x2a4[2] - local20[2]) / local14[2]; + p_param2[0] = (fVar1 * local14[0] + local20[0]) - m_unk0x2a4[0]; + p_param2[1] = (fVar1 * local14[1] + local20[1]) - m_unk0x2a4[1]; + p_param2[2] = 0.0; } -// STUB: LEGO1 0x10023570 -void LegoCarBuild::VTable0x78() +// FUNCTION: LEGO1 0x10023570 +// FUNCTION: BETA10 0x1006be91 +void LegoCarBuild::VTable0x78(MxFloat p_param1[3], MxFloat p_param2[3]) { - // TODO + MxFloat fVar1; + MxFloat local18[3]; + MxFloat localc[3]; + + FUN_1003ded0(p_param1, local18, localc); + + p_param2[2] = + m_unk0x2a4[2] + (m_unk0x2bc[2] - m_unk0x2a4[2]) * ((p_param1[1] - m_unk0x294) / (m_unk0x29c - m_unk0x294)); + fVar1 = (p_param2[2] - localc[2]) / local18[2]; + p_param2[0] = fVar1 * local18[0] - m_unk0x2a4[0] + localc[0]; + p_param2[1] = fVar1 * local18[1] - m_unk0x2a4[1] + localc[1]; + p_param2[2] = p_param2[2] - m_unk0x2a4[2]; } -// STUB: LEGO1 0x10023620 -void LegoCarBuild::VTable0x7c() +// FUNCTION: LEGO1 0x10023620 +// FUNCTION: BETA10 0x1006bfb5 +void LegoCarBuild::VTable0x7c(MxFloat p_param1[3], MxFloat p_param2[3]) { - // TODO + MxFloat local18[3]; + MxFloat localc[3]; + FUN_1003ded0(p_param1, local18, localc); + + MxFloat fVar1 = (m_unk0x2bc[1] - localc[1]) / local18[1]; + p_param2[0] = fVar1 * local18[0] - m_unk0x2a4[0] + localc[0]; + p_param2[1] = m_unk0x2bc[1] - m_unk0x2a4[1]; + p_param2[2] = fVar1 * local18[2] - m_unk0x2a4[2] + localc[2]; } -// STUB: LEGO1 0x100236a0 -void LegoCarBuild::VTable0x80() +// FUNCTION: LEGO1 0x100236a0 +// FUNCTION: BETA10 0x100701f0 +void LegoCarBuild::VTable0x80(MxFloat p_param1[2], MxFloat p_param2[2], MxFloat p_param3, MxFloat p_param4[2]) { - // TODO + if (p_param1[1] == 0.0f) { + return; + } + p_param4[0] = ((p_param3 - p_param2[1]) / p_param1[1]) * p_param1[0] + p_param2[0]; + p_param4[1] = p_param3; } -// STUB: LEGO1 0x100238b0 +#define LEGOCARBUILD_TICKLE_CASE(subtract, start, end, str) \ + if (start < dTime && dTime < end) { \ + FUN_10025db0(str, dTime - subtract); \ + return SUCCESS; \ + } + +// FUNCTION: LEGO1 0x100238b0 +// FUNCTION: BETA10 0x1006c18f MxResult LegoCarBuild::Tickle() { - // TODO + if (!m_worldStarted) { + LegoWorld::Tickle(); + return SUCCESS; + } + + if (m_unk0xf8 == 8) { + if (m_unk0xfc == 1) { + FUN_10024f50(); + } + + if (m_unk0x110) { + if (m_unk0x258->FUN_10079ca0(m_unk0x110->GetName())) { + FUN_10022f30(); + } + } + } + + if (m_unk0x100 == 5 && m_unk0x110) { + FUN_1003dde0(m_unk0x110, g_unk0x100d65a4); + } + + if (m_unk0x10a) { + DWORD time = timeGetTime(); + DWORD dTime = (time - m_unk0x10c) / 100; + + if (m_unk0x330 == 4) { + switch (m_unk0x10a) { + // TODO: Work out constants + case 500: + LEGOCARBUILD_TICKLE_CASE(160, 160, 180, "Exit_Ctl") + LEGOCARBUILD_TICKLE_CASE(260, 260, 280, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(330, 330, 340, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(340, 340, 360, "Platform_Ctl") + LEGOCARBUILD_TICKLE_CASE(390, 390, 410, "Exit_Ctl") + case 503: + LEGOCARBUILD_TICKLE_CASE(50, 50, 60, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(63, 65, 70, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(70, 70, 80, "Platform_Ctl") + LEGOCARBUILD_TICKLE_CASE(95, 95, 105, "Exit_Ctl") + case 504: + LEGOCARBUILD_TICKLE_CASE(22, 24, 29, "Exit_Ctl") + LEGOCARBUILD_TICKLE_CASE(33, 35, 40, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(43, 45, 50, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(56, 58, 63, "Platform_Ctl") + default: + return SUCCESS; + } + } + else if (m_unk0x330 == 3) { + switch (m_unk0x10a) { + case 500: + LEGOCARBUILD_TICKLE_CASE(291, 291, 311, "Exit_Ctl") + LEGOCARBUILD_TICKLE_CASE(311, 311, 331, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(412, 412, 432, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(437, 437, 457, "Platform_Ctl") + LEGOCARBUILD_TICKLE_CASE(485, 485, 505, "Exit_Ctl") + case 501: + LEGOCARBUILD_TICKLE_CASE(32, 34, 39, "Exit_Ctl") + LEGOCARBUILD_TICKLE_CASE(68, 70, 75, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(105, 105, 115, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(133, 135, 140, "Platform_Ctl") + case 504: + LEGOCARBUILD_TICKLE_CASE(78, 78, 98, "Exit_Ctl") + case 505: + LEGOCARBUILD_TICKLE_CASE(93, 93, 113, "Exit_Ctl") + // default: // not sure if present + // return SUCCESS; + } + } + else if (m_unk0x330 == 2) { + switch (m_unk0x10a) { + case 500: + LEGOCARBUILD_TICKLE_CASE(155, 155, 175, "Exit_Ctl") + LEGOCARBUILD_TICKLE_CASE(215, 215, 235, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(285, 285, 305, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(300, 300, 320, "Platform_Ctl") + LEGOCARBUILD_TICKLE_CASE(340, 340, 360, "Exit_Ctl") + case 501: + LEGOCARBUILD_TICKLE_CASE(23, 23, 33, "Exit_Ctl") + LEGOCARBUILD_TICKLE_CASE(37, 39, 44, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(105, 105, 115, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(122, 124, 129, "Platform_Ctl") + default: + return SUCCESS; + } + } + else if (m_unk0x330 == 1) { + switch (m_unk0x10a) { + case 500: + LEGOCARBUILD_TICKLE_CASE(185, 185, 205, "Exit_Ctl") + LEGOCARBUILD_TICKLE_CASE(235, 235, 255, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(292, 292, 312, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(315, 315, 335, "Platform_Ctl") + LEGOCARBUILD_TICKLE_CASE(353, 353, 373, "Exit_Ctl") + case 501: + LEGOCARBUILD_TICKLE_CASE(43, 45, 50, "Exit_Ctl") + LEGOCARBUILD_TICKLE_CASE(72, 74, 79, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(114, 116, 121, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(128, 130, 135, "Platform_Ctl") + case 505: + LEGOCARBUILD_TICKLE_CASE(30, 30, 40, "ShelfUp_Ctl") + LEGOCARBUILD_TICKLE_CASE(60, 60, 70, "Yellow_Ctl") + LEGOCARBUILD_TICKLE_CASE(48, 48, 58, "Platform_Ctl") + default: + return SUCCESS; + } + } + } return 0; } // STUB: LEGO1 0x10024050 +// FUNCTION: BETA10 0x1006c976 MxLong LegoCarBuild::Notify(MxParam& p_param) { // TODO - return 0; } // STUB: LEGO1 0x100242c0 void LegoCarBuild::ReadyWorld() { - // TODO + m_presentersEnabled = FALSE; + InitPresenters(); + if (BackgroundAudioManager()->GetEnabled()) { + InvokeAction(Extra::ActionType::e_start, *g_jukeboxScript, FUN_10025ee0(m_unk0x330), NULL); + m_buildState->m_animationState = 2; + MxNotificationParam param; + param.SetNotification(c_notificationStartAction); + NotificationManager()->Send(this, param); + } + else { + FUN_10024ef0(); + } } -// STUB: LEGO1 0x100256c0 +// FUNCTION: LEGO1 0x10024ef0 +void LegoCarBuild::FUN_10024ef0() +{ + FUN_1003eda0(); + m_buildState->m_animationState = 3; + FUN_10025720(FUN_10025d70()); + m_buildState->m_unk0x4c += 1; + FUN_10015820(FALSE, 7); +} + +// FUNCTION: LEGO1 0x10024f50 +// FUNCTION: BETA10 0x1006dfce +void LegoCarBuild::FUN_10024f50() +{ + m_unk0x2d4 = FALSE; + m_unk0x258->FUN_10079920(g_unk0x100d65a8); +} + +// FUNCTION: LEGO1 0x10024fa0 +// FUNCTION: BETA10 0x1006e04f +void LegoCarBuild::SetPresentersEnabled(MxBool p_enabled) +{ + m_presentersEnabled = p_enabled; + m_ColorBook_Bitmap->Enable(p_enabled); + m_Yellow_Ctl->Enable(p_enabled); + m_Red_Ctl->Enable(p_enabled); + m_Blue_Ctl->Enable(p_enabled); + m_Green_Ctl->Enable(p_enabled); + m_Gray_Ctl->Enable(p_enabled); + m_Black_Ctl->Enable(p_enabled); +} + +// FUNCTION: LEGO1 0x10025010 +void LegoCarBuild::TogglePresentersEnabled() +{ + m_ColorBook_Bitmap->Enable(!m_ColorBook_Bitmap->IsEnabled()); + m_Yellow_Ctl->Enable(!m_Yellow_Ctl->IsEnabled()); + m_Red_Ctl->Enable(!m_Red_Ctl->IsEnabled()); + m_Blue_Ctl->Enable(!m_Blue_Ctl->IsEnabled()); + m_Green_Ctl->Enable(!m_Green_Ctl->IsEnabled()); + m_Gray_Ctl->Enable(!m_Gray_Ctl->IsEnabled()); + m_Black_Ctl->Enable(!m_Black_Ctl->IsEnabled()); +} + +// FUNCTION: LEGO1 0x100256c0 +// FUNCTION: BETA10 0x1006e96c void LegoCarBuild::Enable(MxBool p_enable) { - // TODO + LegoWorld::Enable(p_enable); + + if (p_enable) { + InputManager()->SetWorld(this); + SetIsWorldActive(FALSE); + } + else { + BackgroundAudioManager()->Init(); + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } } -// STUB: LEGO1 0x10025e70 -MxBool LegoCarBuild::Escape() +// STUB: LEGO1 0x10025720 +undefined4 LegoCarBuild::FUN_10025720(undefined4 p_param1) { // TODO - return FALSE; + return 0; +} + +// FUNCTION: LEGO1 0x10025d70 +MxS32 LegoCarBuild::FUN_10025d70() +{ + switch (m_buildState->m_unk0x4c % 3) { + case 1: + return 1; + case 2: + return 2; + case 3: + return 3; + default: + return 0; + } +} + +// FUNCTION: LEGO1 0x10025db0 +// FUNCTION: BETA10 0x1006ed18 +void LegoCarBuild::FUN_10025db0(const char* p_param1, undefined4 p_param2) +{ + m_unk0x33c = (MxControlPresenter*) Find("MxControlPresenter", p_param1); + + MxS16 sVar3 = 1 - ((p_param2 / 5) & 1); + + if (m_Yellow_Ctl == m_unk0x33c) { + if (sVar3 != g_unk0x100f11cc) { + TogglePresentersEnabled(); + g_unk0x100f11cc = sVar3; + } + } + else { + if (m_unk0x33c->GetUnknown0x4e() != sVar3) { + m_unk0x33c->VTable0x6c(sVar3); + } + + g_unk0x100f11cc = -1; + SetPresentersEnabled(m_presentersEnabled); + } +} + +// FUNCTION: LEGO1 0x10025e70 +MxBool LegoCarBuild::Escape() +{ + BackgroundAudioManager()->Init(); + MxS32 targetEntityId = FUN_10025ee0(m_unk0x330); + InvokeAction(Extra::ActionType::e_stop, *g_jukeboxScript, targetEntityId, NULL); + DeleteObjects(&m_atomId, 500, 999); + + m_buildState->m_animationState = 0; + m_unk0x334 = 2; + return TRUE; +} + +// FUNCTION: LEGO1 0x10025ee0 +MxS32 LegoCarBuild::FUN_10025ee0(undefined4 p_param1) +{ + // TODO: Work out constants + switch (p_param1) { + case 1: + return 0x2f; + case 2: + return 0x31; + case 3: + return 0x33; + case 4: + return 0x35; + default: + return -1; + } } // FUNCTION: LEGO1 0x10025f30 diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp index fddac82e..d143e670 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp @@ -43,3 +43,18 @@ void LegoCarBuildAnimPresenter::EndAction() { // TODO } + +// STUB: LEGO1 0x10079920 +// STUB: BETA10 0x1007225d +void LegoCarBuildAnimPresenter::FUN_10079920(float p_param1) +{ + // TODO +} + +// STUB: LEGO1 0x10079ca0 +// STUB: BETA10 0x10072740 +MxBool LegoCarBuildAnimPresenter::FUN_10079ca0(const char* p_param1) +{ + // TODO; pretty short + return FALSE; +} diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 6ac670d7..75f0ba2a 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -56,6 +56,7 @@ #include "scripts.h" #include "sndanim_actions.h" +#include #include DECOMP_SIZE_ASSERT(LegoGameState::Username, 0x0e) @@ -613,6 +614,7 @@ MxS16 LegoGameState::FindPlayer(Username& p_player) } // FUNCTION: LEGO1 0x1003a720 +// FUNCTION: BETA10 0x10085211 void LegoGameState::StopArea(Area p_area) { if (p_area == e_previousArea) { @@ -1031,6 +1033,7 @@ MxBool ROIHandlerFunction(const char* p_input, char* p_output, MxU32 p_copyLen) } // FUNCTION: LEGO1 0x1003bbb0 +// FUNCTION: BETA10 0x10086280 LegoState* LegoGameState::GetState(const char* p_stateName) { for (MxS32 i = 0; i < m_stateCount; ++i) { @@ -1042,12 +1045,16 @@ LegoState* LegoGameState::GetState(const char* p_stateName) } // FUNCTION: LEGO1 0x1003bc00 +// FUNCTION: BETA10 0x100862fc LegoState* LegoGameState::CreateState(const char* p_stateName) { - LegoState* newState = (LegoState*) ObjectFactory()->Create(p_stateName); - RegisterState(newState); + // variable name verified by BETA10 0x10086341 + LegoState* state = (LegoState*) ObjectFactory()->Create(p_stateName); + assert(state); - return newState; + RegisterState(state); + + return state; } // FUNCTION: LEGO1 0x1003bc30 diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index 8699ffc1..eeca0bd0 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -61,6 +61,49 @@ LegoEntity* PickEntity(MxLong, MxLong) return NULL; } +// STUB: LEGO1 0x1003dde0 +// STUB: BETA10 0x100d358e +void FUN_1003dde0(LegoROI* p_param1, MxFloat p_param2) +{ + // TODO +} + +// FUNCTION: LEGO1 0x1003ded0 +// FUNCTION: BETA10 0x100d3802 +MxBool FUN_1003ded0(MxFloat p_param1[3], MxFloat p_param2[3], MxFloat p_param3[3]) +{ + MxFloat local1c[4]; + MxFloat local10[3]; + + Tgl::View* view = VideoManager()->Get3DManager()->GetLego3DView()->GetView(); + + local1c[0] = p_param1[0]; + local1c[1] = p_param1[1]; + local1c[2] = 1.0f; + local1c[3] = 1.0f; + + view->TransformScreenToWorld(local1c, p_param3); + + local1c[0] *= 2.0; + local1c[1] *= 2.0; + local1c[3] = 2.0; + + view->TransformScreenToWorld(local1c, local10); + + p_param2[0] = local10[0] - p_param3[0]; + p_param2[1] = local10[1] - p_param3[1]; + p_param2[2] = local10[2] - p_param3[2]; + return TRUE; +} + +// FUNCTION: LEGO1 0x1003df70 +// FUNCTION: BETA10 0x100d38cb +MxBool TransformWorldToScreen(const MxFloat p_world[3], MxFloat p_screen[4]) +{ + VideoManager()->Get3DManager()->GetLego3DView()->GetView()->TransformWorldToScreen(p_world, p_screen); + return TRUE; +} + // FUNCTION: LEGO1 0x1003df90 MxS16 CountTotalTreeNodes(LegoTreeNode* p_node) { @@ -454,6 +497,7 @@ MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_wor } // FUNCTION: LEGO1 0x1003ef00 +// FUNCTION: BETA10 0x100d4e1e void EnableAnimations(MxBool p_enable) { if (p_enable) { diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 8d035c74..dee4ac0e 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -25,8 +25,10 @@ LegoSoundManager* SoundManager() } // FUNCTION: LEGO1 0x10015720 +// FUNCTION: BETA10 0x100e4807 LegoVideoManager* VideoManager() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetVideoManager(); } diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp index 4a16d930..b8125c50 100644 --- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -38,6 +38,7 @@ void LegoControlManager::FUN_10028df0(MxPresenterList* p_presenterList) } // FUNCTION: LEGO1 0x10028e10 +// FUNCTION: BETA10 0x1007c232 void LegoControlManager::Register(MxCore* p_listener) { m_notifyList.Append(p_listener); diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index a0195af8..5383d39c 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -332,6 +332,7 @@ void LegoInputManager::ClearCamera() } // FUNCTION: LEGO1 0x1005c720 +// FUNCTION: BETA10 0x100896b8 void LegoInputManager::SetWorld(LegoWorld* p_world) { m_world = p_world; diff --git a/LEGO1/lego/sources/3dmanager/lego3dmanager.h b/LEGO1/lego/sources/3dmanager/lego3dmanager.h index 82f4e4a3..ac0f7bc1 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dmanager.h +++ b/LEGO1/lego/sources/3dmanager/lego3dmanager.h @@ -113,6 +113,7 @@ inline Tgl::Group* Lego3DManager::GetScene() return m_pLego3DView->GetScene(); } +// FUNCTION: BETA10 0x10011840 inline Lego3DView* Lego3DManager::GetLego3DView() { return m_pLego3DView; diff --git a/LEGO1/lego/sources/3dmanager/tglsurface.h b/LEGO1/lego/sources/3dmanager/tglsurface.h index 0ee9a61c..7ceb5565 100644 --- a/LEGO1/lego/sources/3dmanager/tglsurface.h +++ b/LEGO1/lego/sources/3dmanager/tglsurface.h @@ -47,6 +47,7 @@ class TglSurface { // FUNCTION: BETA10 0x100d5570 Tgl::View* GetView() const { return m_pView; } + Tgl::Group* GetScene() const { return m_pScene; } // FUNCTION: BETA10 0x1017cbc0 diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index dfddcfcb..a4c6cd0a 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -666,4 +666,7 @@ // GLOBAL: LEGO1 0x1010a730 // __nstream +// LIBRARY: BETA10 0x100f9060 +// _assert + #endif diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 0e2e00b3..289c201a 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -65,7 +65,9 @@ class Mx4DPointFloat : public Vector4 { // FUNCTION: LEGO1 0x10003200 virtual void operator=(const Vector4& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x98 + // FUNCTION: BETA10 0x1004af10 float& operator[](int idx) { return m_data[idx]; } + const float& operator[](int idx) const { return m_data[idx]; } // SYNTHETIC: LEGO1 0x10064b20 diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 2db647c3..84d072c3 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -294,6 +294,12 @@ class Vector4 : public Vector3 { public: Vector4(float* p_data) : Vector3(p_data) {} + // Hack: Some code initializes a Vector4 from a (most likely) const float* source. + // Example: LegoCarBuild::VTable0x6c + // Vector4 however is a class that can mutate its underlying source, making + // initialization with a const source fundamentally incompatible. + Vector4(const float* p_data) : Vector3((float*) p_data) {} + // Note: virtual function overloads appear in the virtual table // in reverse order of appearance. diff --git a/tools/ncc/skip.yml b/tools/ncc/skip.yml index 6062e7b1..6950fbca 100644 --- a/tools/ncc/skip.yml +++ b/tools/ncc/skip.yml @@ -31,3 +31,24 @@ i_actor: "Allow original naming from beta" score: "Allow original naming from beta" c_LOCATIONS_NUM: "Allow original naming from beta" m_Map_Ctl: "Allow original naming from beta" +m_ColorBook_Bitmap: "Allow original naming from beta" +m_Yellow_Ctl: "Allow original naming from beta" +m_Red_Ctl: "Allow original naming from beta" +m_Blue_Ctl: "Allow original naming from beta" +m_Green_Ctl: "Allow original naming from beta" +m_Gray_Ctl: "Allow original naming from beta" +m_Black_Ctl: "Allow original naming from beta" +m_Shelf_Sound: "Allow original naming from beta" +m_PlaceBrick_Sound: "Allow original naming from beta" +m_GetBrick_Sound: "Allow original naming from beta" +m_Paint_Sound: "Allow original naming from beta" +m_Decal_Sound: "Allow original naming from beta" +m_Decal_Bitmap: "Allow original naming from beta" +m_Decals_Ctl: "Allow original naming from beta" +m_Decals_Ctl1: "Allow original naming from beta" +m_Decals_Ctl2: "Allow original naming from beta" +m_Decals_Ctl3: "Allow original naming from beta" +m_Decals_Ctl4: "Allow original naming from beta" +m_Decals_Ctl5: "Allow original naming from beta" +m_Decals_Ctl6: "Allow original naming from beta" +m_Decals_Ctl7: "Allow original naming from beta"