From afa5b90117b2f363d9931ac5437942c5848650e6 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sun, 7 Jul 2024 14:10:46 +0200 Subject: [PATCH] Implement `LegoRaceCar::FUN_10012ff0()`, refactoring (#1063) * Implement `LegoRaceCar::FUN_10012ff0()`, refactor based on BETA10 * Add BETA10 annotations * Rename functions and variables based on BETA10 assertions * Address issues raised by linter * Rename variable, add BETA10 vtables * Rename legoracecar files to legoracers --------- Co-authored-by: jonschz --- CMakeLists.txt | 2 +- LEGO1/lego/legoomni/include/legoanimactor.h | 4 ++ .../include/{legoracecar.h => legoracers.h} | 15 +++-- LEGO1/lego/legoomni/include/legoworld.h | 2 + .../src/common/legoanimationmanager.cpp | 2 +- .../legoomni/src/common/legoobjectfactory.cpp | 2 +- LEGO1/lego/legoomni/src/common/misc.cpp | 2 + .../src/entity/legocameracontroller.cpp | 1 + .../lego/legoomni/src/paths/legoanimactor.cpp | 2 + .../race/{legoracecar.cpp => legoracers.cpp} | 62 +++++++++++++++++-- .../legoomni/src/video/legoanimpresenter.cpp | 4 +- LEGO1/lego/sources/anim/legoanim.cpp | 10 +-- LEGO1/lego/sources/anim/legoanim.h | 9 ++- LEGO1/lego/sources/geom/legoweedge.h | 3 + LEGO1/mxgeometry/mxmatrix.h | 1 + LEGO1/realtime/matrix.h | 1 + LEGO1/realtime/orientableroi.cpp | 1 + LEGO1/realtime/orientableroi.h | 1 + 18 files changed, 102 insertions(+), 22 deletions(-) rename LEGO1/lego/legoomni/include/{legoracecar.h => legoracers.h} (85%) rename LEGO1/lego/legoomni/src/race/{legoracecar.cpp => legoracers.cpp} (69%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08e4424a..5e9a675c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -373,7 +373,7 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/race/jetskirace.cpp LEGO1/lego/legoomni/src/race/legorace.cpp LEGO1/lego/legoomni/src/race/legoraceactor.cpp - LEGO1/lego/legoomni/src/race/legoracecar.cpp + LEGO1/lego/legoomni/src/race/legoracers.cpp LEGO1/lego/legoomni/src/race/legoracemap.cpp LEGO1/lego/legoomni/src/race/raceskel.cpp LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp diff --git a/LEGO1/lego/legoomni/include/legoanimactor.h b/LEGO1/lego/legoomni/include/legoanimactor.h index e2843c3d..72f6bc1c 100644 --- a/LEGO1/lego/legoomni/include/legoanimactor.h +++ b/LEGO1/lego/legoomni/include/legoanimactor.h @@ -15,6 +15,10 @@ struct LegoAnimActorStruct { float GetUnknown0x00() { return m_unk0x00; } + // FUNCTION: BETA10 0x10012210 + LegoAnim* GetAnimTreePtr() { return m_AnimTreePtr; } + + // TODO: Possibly private float m_unk0x00; // 0x00 LegoAnim* m_AnimTreePtr; // 0x04 LegoROI** m_roiMap; // 0x08 diff --git a/LEGO1/lego/legoomni/include/legoracecar.h b/LEGO1/lego/legoomni/include/legoracers.h similarity index 85% rename from LEGO1/lego/legoomni/include/legoracecar.h rename to LEGO1/lego/legoomni/include/legoracers.h index d85e7d7b..290a849f 100644 --- a/LEGO1/lego/legoomni/include/legoracecar.h +++ b/LEGO1/lego/legoomni/include/legoracers.h @@ -1,5 +1,5 @@ -#ifndef LEGORACECAR_H -#define LEGORACECAR_H +#ifndef LEGORACERS_H +#define LEGORACERS_H #include "legocarraceactor.h" #include "legoracemap.h" @@ -15,6 +15,11 @@ struct EdgeReference { // VTABLE: LEGO1 0x100d58b8 LegoPathActor // VTABLE: LEGO1 0x100d5984 LegoRaceMap // VTABLE: LEGO1 0x100d5988 LegoCarRaceActor +// VTABLE: BETA10 0x101be6ec LegoRaceActor +// VTABLE: BETA10 0x101be6f0 LegoAnimActor +// VTABLE: BETA10 0x101be708 LegoPathActor +// VTABLE: BETA10 0x101be7f8 LegoRaceMap +// VTABLE: BETA10 0x101be800 LegoCarRaceActor // SIZE 0x200 class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { public: @@ -60,8 +65,8 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { // LegoRaceCar::`scalar deleting destructor' private: - undefined m_unk0x54; // 0x54 - undefined4 m_unk0x58; // 0x58 + undefined m_userState; // 0x54 + float m_unk0x58; // 0x58 Mx3DPointFloat m_unk0x5c; // 0x5c LegoAnimActorStruct* m_unk0x70; // 0x70 LegoAnimActorStruct* m_unk0x74; // 0x74 @@ -72,4 +77,4 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { static const EdgeReference* g_pEdgeReferences; }; -#endif // LEGORACECAR_H +#endif // LEGORACERS_H diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index 8cec279c..d248ab5b 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -97,7 +97,9 @@ class LegoWorld : public LegoEntity { MxCore* Find(const char* p_class, const char* p_name); MxCore* Find(const MxAtomId& p_atom, MxS32 p_entityId); + // FUNCTION: BETA10 0x1002b4f0 LegoCameraController* GetCamera() { return m_cameraController; } + LegoEntityList* GetEntityList() { return m_entityList; } MxS32 GetWorldId() { return m_worldId; } MxBool GetUnknown0xd0Empty() { return m_set0xd0.empty(); } diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index fa136321..fb8b39d0 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -1220,7 +1220,7 @@ void LegoAnimationManager::FUN_10061010(MxBool p_und) if (tranInfo->m_presenter->GetPresenter() != NULL && (anim = tranInfo->m_presenter->GetPresenter()->GetAnimation()) != NULL && - anim->GetScene() != NULL) { + anim->GetCamAnim() != NULL) { if (flags & LegoTranInfo::c_bit2) { BackgroundAudioManager()->RaiseVolume(); tranInfo->m_flags &= ~LegoTranInfo::c_bit2; diff --git a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp index fca0c0cb..00f88397 100644 --- a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp +++ b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp @@ -57,7 +57,7 @@ #include "legopathactor.h" #include "legopathpresenter.h" #include "legophonemepresenter.h" -#include "legoracecar.h" +#include "legoracers.h" #include "legotexturepresenter.h" #include "legoworld.h" #include "legoworldpresenter.h" diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 29cc4cd6..6d879aa1 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -73,8 +73,10 @@ LegoPathActor* UserActor() } // FUNCTION: LEGO1 0x100157a0 +// FUNCTION: BETA10 0x100e4a46 LegoWorld* CurrentWorld() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetCurrentWorld(); } diff --git a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp index 3db91002..bd757bd5 100644 --- a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp @@ -140,6 +140,7 @@ void LegoCameraController::FUN_10012320(float p_angle) } // FUNCTION: LEGO1 0x100123e0 +// FUNCTION: BETA10 0x10068cb2 void LegoCameraController::FUN_100123e0(const Matrix4& p_transform, MxU32 p_und) { if (m_lego3DView != NULL) { diff --git a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp index 70c73fe2..eaad8ba9 100644 --- a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp @@ -29,8 +29,10 @@ LegoAnimActorStruct::~LegoAnimActorStruct() } // FUNCTION: LEGO1 0x1001c130 +// FUNCTION: BETA10 0x1003df5f float LegoAnimActorStruct::GetDuration() { + assert(m_AnimTreePtr); return m_AnimTreePtr->GetDuration(); } diff --git a/LEGO1/lego/legoomni/src/race/legoracecar.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp similarity index 69% rename from LEGO1/lego/legoomni/src/race/legoracecar.cpp rename to LEGO1/lego/legoomni/src/race/legoracers.cpp index 2a2b2a7e..2a4e2185 100644 --- a/LEGO1/lego/legoomni/src/race/legoracecar.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -1,6 +1,8 @@ -#include "legoracecar.h" +#include "legoracers.h" +#include "anim/legoanim.h" #include "define.h" +#include "legocameracontroller.h" #include "legorace.h" #include "misc.h" #include "mxmisc.h" @@ -44,7 +46,7 @@ const EdgeReference* LegoRaceCar::g_pEdgeReferences = g_edgeReferences; // FUNCTION: LEGO1 0x10012950 LegoRaceCar::LegoRaceCar() { - m_unk0x54 = 0; + m_userState = 0; m_unk0x70 = 0; m_unk0x74 = 0; m_unk0x5c.Clear(); @@ -131,10 +133,60 @@ void LegoRaceCar::ParseAction(char* p_extra) } } -// STUB: LEGO1 0x10012ff0 -void LegoRaceCar::FUN_10012ff0(float) +// FUNCTION: LEGO1 0x10012ff0 +// FUNCTION: BETA10 0x100cb60e +void LegoRaceCar::FUN_10012ff0(float p_param) { - // TODO + LegoAnimActorStruct* a; // called `a` in BETA10 + float deltaTime; + + if (m_userState == 2) { + a = m_unk0x70; + } + else { + // TODO: Possibly an enum? + const char legoracecarKick2 = 4; // original name: LEGORACECAR_KICK2 + assert(m_userState == legoracecarKick2); + a = m_unk0x74; + } + + assert(a && a->GetAnimTreePtr() && a->GetAnimTreePtr()->GetCamAnim()); + + if (a->GetAnimTreePtr()) { + deltaTime = p_param - m_unk0x58; + + if (a->GetDuration() <= deltaTime || deltaTime < 0.0) { + if (m_userState == 2) { + LegoEdge** edges = m_unk0x78->GetEdges(); + m_destEdge = (LegoUnknown100db7f4*) (edges[2]); + m_boundary = m_unk0x78; + } + else { + LegoEdge** edges = m_unk0x78->GetEdges(); + m_destEdge = (LegoUnknown100db7f4*) (edges[1]); + m_boundary = m_unk0x7c; + } + + m_userState = 0; + } + else if (a->GetAnimTreePtr()->GetCamAnim()) { + MxMatrix transformationMatrix; + + LegoWorld* r = CurrentWorld(); // called `r` in BETA10 + assert(r); + + transformationMatrix.SetIdentity(); + + // Possible bug in the original code: The first argument is not initialized + a->GetAnimTreePtr()->GetCamAnim()->FUN_1009f490(deltaTime, transformationMatrix); + + if (r->GetCamera()) { + r->GetCamera()->FUN_100123e0(transformationMatrix, 0); + } + + m_roi->FUN_100a58f0(transformationMatrix); + } + } } // STUB: LEGO1 0x10013130 diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 723a1a30..faebd3d4 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -922,9 +922,9 @@ void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p } } - if (p_anim->GetScene() != NULL) { + if (p_anim->GetCamAnim() != NULL) { MxMatrix transform(mat); - p_anim->GetScene()->FUN_1009f490(p_time, transform); + p_anim->GetCamAnim()->FUN_1009f490(p_time, transform); if (m_currentWorld != NULL && m_currentWorld->GetCamera() != NULL) { m_currentWorld->GetCamera()->FUN_100123e0(transform, 0); diff --git a/LEGO1/lego/sources/anim/legoanim.cpp b/LEGO1/lego/sources/anim/legoanim.cpp index 45844ca9..77801f61 100644 --- a/LEGO1/lego/sources/anim/legoanim.cpp +++ b/LEGO1/lego/sources/anim/legoanim.cpp @@ -785,7 +785,7 @@ LegoAnim::LegoAnim() m_duration = 0; m_actors = NULL; m_numActors = 0; - m_scene = NULL; + m_camAnim = NULL; } // FUNCTION: LEGO1 0x100a0bc0 @@ -799,8 +799,8 @@ LegoAnim::~LegoAnim() delete[] m_actors; } - if (m_scene != NULL) { - delete m_scene; + if (m_camAnim != NULL) { + delete m_camAnim; } } @@ -845,9 +845,9 @@ LegoResult LegoAnim::Read(LegoStorage* p_storage, LegoS32 p_parseScene) } if (p_parseScene) { - m_scene = new LegoAnimScene(); + m_camAnim = new LegoAnimScene(); - result = m_scene->Read(p_storage); + result = m_camAnim->Read(p_storage); if (result != SUCCESS) { goto done; diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h index a7f7ee72..1a861eb6 100644 --- a/LEGO1/lego/sources/anim/legoanim.h +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -208,6 +208,7 @@ struct LegoAnimActorEntry { undefined4 m_unk0x04; // 0x04 }; +// TODO: Possibly called `LegoCameraAnim(ation)`? // SIZE 0x24 class LegoAnimScene { public: @@ -242,7 +243,10 @@ class LegoAnim : public LegoTree { public: LegoAnim(); ~LegoAnim() override; + + // FUNCTION: BETA10 0x100284c0 LegoTime GetDuration() { return m_duration; } + LegoU32 GetNumActors() { return m_numActors; } LegoResult Write(LegoStorage* p_storage) override; // vtable+0x08 virtual LegoResult Read(LegoStorage* p_storage, LegoS32 p_parseScene); // vtable+0x10 @@ -250,7 +254,8 @@ class LegoAnim : public LegoTree { const LegoChar* GetActorName(LegoU32 p_index); undefined4 GetActorUnknown0x04(LegoU32 p_index); - LegoAnimScene* GetScene() { return m_scene; } + // FUNCTION: BETA10 0x1005abf0 + LegoAnimScene* GetCamAnim() { return m_camAnim; } // SYNTHETIC: LEGO1 0x100a0ba0 // LegoAnim::`scalar deleting destructor' @@ -259,7 +264,7 @@ class LegoAnim : public LegoTree { LegoTime m_duration; // 0x08 LegoAnimActorEntry* m_actors; // 0x0c LegoU32 m_numActors; // 0x10 - LegoAnimScene* m_scene; // 0x14 + LegoAnimScene* m_camAnim; // 0x14 // FUNCTION: LEGO1 0x100a1040 LegoTreeNodeData* CreateData() override { return new LegoAnimNodeData(); } // vtable+0x0c diff --git a/LEGO1/lego/sources/geom/legoweedge.h b/LEGO1/lego/sources/geom/legoweedge.h index c5a8b83d..74dc6a45 100644 --- a/LEGO1/lego/sources/geom/legoweedge.h +++ b/LEGO1/lego/sources/geom/legoweedge.h @@ -16,7 +16,10 @@ class LegoWEEdge { virtual LegoResult VTable0x04(); // vtable+0x04 LegoU8 GetNumEdges() { return m_numEdges; } + + // FUNCTION: BETA10 0x1001cc30 LegoEdge** GetEdges() { return m_edges; } + LegoU32 IsEqual(LegoWEEdge& p_other) { return this == &p_other; } void SetEdges(LegoEdge** p_edges, LegoU8 p_numEdges) diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h index a33d92b9..1b8bbfbc 100644 --- a/LEGO1/mxgeometry/mxmatrix.h +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -4,6 +4,7 @@ #include "realtime/matrix.h" // VTABLE: LEGO1 0x100d4300 +// VTABLE: BETA10 0x101b82e0 // SIZE 0x48 class MxMatrix : public Matrix4 { public: diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index a63b69d6..92c7ac7d 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -13,6 +13,7 @@ struct UnknownMatrixType { // The class needs to undergo a very careful refactoring to fix that (no matches should break). // VTABLE: LEGO1 0x100d4350 +// VTABLE: BETA10 0x101b8340 // SIZE 0x08 class Matrix4 { public: diff --git a/LEGO1/realtime/orientableroi.cpp b/LEGO1/realtime/orientableroi.cpp index 21a6b75a..451df324 100644 --- a/LEGO1/realtime/orientableroi.cpp +++ b/LEGO1/realtime/orientableroi.cpp @@ -98,6 +98,7 @@ void OrientableROI::GetLocalTransform(Matrix4& p_transform) } // FUNCTION: LEGO1 0x100a58f0 +// FUNCTION: BETA10 0x10167b77 void OrientableROI::FUN_100a58f0(const Matrix4& p_transform) { m_local2world = p_transform; diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h index b707bbe3..25e09a5d 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -47,6 +47,7 @@ class OrientableROI : public ROI { void SetParentROI(OrientableROI* p_parentROI) { m_parentROI = p_parentROI; } + // FUNCTION: BETA10 0x10168800 void ToggleUnknown0xd8(BOOL p_enable) { if (p_enable) {