From ce52aaccc13f97ffe65a29588090a8499f3d984f Mon Sep 17 00:00:00 2001 From: jonschz Date: Sat, 6 Jul 2024 11:19:28 +0200 Subject: [PATCH] Implement `LegoRaceCar::FUN_10012ff0()`, refactor based on BETA10 * Add BETA10 annotations * Rename functions and variables based on BETA10 assertions --- LEGO1/lego/legoomni/include/legoanimactor.h | 4 ++ LEGO1/lego/legoomni/include/legoracecar.h | 4 +- LEGO1/lego/legoomni/include/legoworld.h | 2 + .../src/common/legoanimationmanager.cpp | 2 +- LEGO1/lego/legoomni/src/common/misc.cpp | 2 + .../src/entity/legocameracontroller.cpp | 1 + .../lego/legoomni/src/paths/legoanimactor.cpp | 2 + LEGO1/lego/legoomni/src/race/legoracecar.cpp | 60 +++++++++++++++++-- .../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 + 16 files changed, 91 insertions(+), 16 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimactor.h b/LEGO1/lego/legoomni/include/legoanimactor.h index e2843c3d..25376346 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; } + // BETA10: FUNCTION 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/legoracecar.h index d85e7d7b..45c631cf 100644 --- a/LEGO1/lego/legoomni/include/legoracecar.h +++ b/LEGO1/lego/legoomni/include/legoracecar.h @@ -60,8 +60,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 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/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/legoracecar.cpp index 2a2b2a7e..7f8544a9 100644 --- a/LEGO1/lego/legoomni/src/race/legoracecar.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracecar.cpp @@ -1,6 +1,8 @@ #include "legoracecar.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 LEGORACECAR_KICK2 = 4; + assert(m_userState == LEGORACECAR_KICK2); + 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* current_world = CurrentWorld(); // called `r` in BETA10 + assert(current_world); + + transformationMatrix.SetIdentity(); + + // Possible bug in the original code: The first argument is not initialized + a->GetAnimTreePtr()->GetCamAnim()->FUN_1009f490(deltaTime, transformationMatrix); + + if (current_world->GetCamera()) { + current_world->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) {