From dede20000fbad11b57e129450b31447a77e9dbc2 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sun, 28 Apr 2024 13:23:29 +0200 Subject: [PATCH 1/9] Progress towards implementing SkateBoard (#864) * Implement SkateBoard::~SkateBoard() * Implement SkateBoard::VTable0xd4 * Implement SkateBoard::Create() - one typecast is still not clear * Add SkateBoard::VTable0xe4() * apply clang-format * Apply clang-format to legocontrolmanager.h * Address review comments --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/pizza.h | 7 +- LEGO1/lego/legoomni/include/skateboard.h | 6 +- LEGO1/lego/legoomni/src/actors/pizza.cpp | 10 +++ LEGO1/lego/legoomni/src/actors/skateboard.cpp | 66 +++++++++++++++---- 4 files changed, 72 insertions(+), 17 deletions(-) diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index 7884334d..15e34af2 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -31,13 +31,18 @@ class Pizza : public IsleActor { undefined4 HandleEndAction(MxEndActionNotificationParam&) override; // vtable+0x74 undefined4 VTable0x80(MxParam&) override; // vtable+0x80 + void FUN_100382b0(); + void FUN_10038380(); + + inline void SetUnknown0x84(undefined* p_unk0x84) { m_unk0x84 = p_unk0x84; } + // SYNTHETIC: LEGO1 0x100380e0 // Pizza::`scalar deleting destructor' private: undefined4 m_unk0x7c; // 0x7c undefined4 m_unk0x80; // 0x80 - undefined4 m_unk0x84; // 0x84 + undefined* m_unk0x84; // 0x84 undefined4 m_unk0x88; // 0x88 undefined4 m_unk0x8c; // 0x8c undefined4 m_unk0x90; // 0x90 diff --git a/LEGO1/lego/legoomni/include/skateboard.h b/LEGO1/lego/legoomni/include/skateboard.h index b5d4fbf1..dc567b9f 100644 --- a/LEGO1/lego/legoomni/include/skateboard.h +++ b/LEGO1/lego/legoomni/include/skateboard.h @@ -9,6 +9,7 @@ class SkateBoard : public IslePathActor { public: SkateBoard(); + ~SkateBoard() override; // FUNCTION: LEGO1 0x1000fdd0 inline const char* ClassName() const override // vtable+0x0c @@ -35,9 +36,8 @@ class SkateBoard : public IslePathActor { // SkateBoard::`scalar deleting destructor' private: - // TODO: SkateBoard types - undefined m_unk0x160; - undefined m_unk0x161[0x7]; + undefined m_unk0x160; // 0x160 + undefined* m_unk0x164; // 0x164 }; #endif // SKATEBOARD_H diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index 6a16c580..106ea918 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -30,6 +30,16 @@ MxResult Pizza::Create(MxDSAction& p_dsAction) return SUCCESS; } +// STUB: LEGO1 0x100382b0 +void Pizza::FUN_100382b0() +{ +} + +// STUB: LEGO1 0x10038380 +void Pizza::FUN_10038380() +{ +} + // STUB: LEGO1 0x100383f0 undefined4 Pizza::VTable0x68() { diff --git a/LEGO1/lego/legoomni/src/actors/skateboard.cpp b/LEGO1/lego/legoomni/src/actors/skateboard.cpp index a111c7a7..93d29c00 100644 --- a/LEGO1/lego/legoomni/src/actors/skateboard.cpp +++ b/LEGO1/lego/legoomni/src/actors/skateboard.cpp @@ -1,33 +1,66 @@ #include "skateboard.h" #include "decomp.h" +#include "isle_actions.h" +#include "legoutils.h" +#include "misc.h" #include "mxmisc.h" #include "mxnotificationmanager.h" +#include "pizza.h" DECOMP_SIZE_ASSERT(SkateBoard, 0x168) // FUNCTION: LEGO1 0x1000fd40 SkateBoard::SkateBoard() { - this->m_unk0x160 = 0; - this->m_unk0x13c = 15.0; - this->m_unk0x150 = 3.5; - this->m_unk0x148 = 1; + m_unk0x160 = 0; + m_unk0x13c = 15.0; + m_unk0x150 = 3.5; + m_unk0x148 = 1; NotificationManager()->Register(this); } -// STUB: LEGO1 0x10010000 -MxResult SkateBoard::Create(MxDSAction& p_dsAction) +// FUNCTION: LEGO1 0x1000ff80 +SkateBoard::~SkateBoard() { - // TODO - return SUCCESS; + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x10010050 +// FUNCTION: LEGO1 0x10010000 +MxResult SkateBoard::Create(MxDSAction& p_dsAction) +{ + MxResult result = IslePathActor::Create(p_dsAction); + + if (result == SUCCESS) { + m_world = CurrentWorld(); + m_world->Add(this); + // The type `Pizza` is an educated guesss, inferred from VTable0xe4() below + Pizza* findResult = (Pizza*) CurrentWorld()->Find(*g_isleScript, IsleScript::c_Pizza_Actor); + if (findResult) { + findResult->SetUnknown0x84((undefined*) this); + } + } + + return result; +} + +// FUNCTION: LEGO1 0x10010050 void SkateBoard::VTable0xe4() { - // TODO + // TODO: Work out what kind of structure this points to + if (*(int*) (m_unk0x164 + 0x18) == 3) { + Pizza* pizza = (Pizza*) CurrentWorld()->Find(*g_isleScript, IsleScript::c_Pizza_Actor); + pizza->FUN_10038380(); + pizza->FUN_100382b0(); + m_unk0x160 = 0; + } + IslePathActor::VTable0xe4(); + GameState()->m_currentArea = LegoGameState::Area::e_skateboard; + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_SkateArms_Ctl); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_SkatePizza_Bitmap); + ControlManager()->Unregister(this); } // STUB: LEGO1 0x100100e0 @@ -37,11 +70,18 @@ MxU32 SkateBoard::VTable0xcc() return 0; } -// STUB: LEGO1 0x10010230 +// FUNCTION: LEGO1 0x10010230 MxU32 SkateBoard::VTable0xd4(LegoControlManagerEvent& p_param) { - // TODO - return 0; + MxU32 result = 0; + + if (p_param.GetUnknown0x28() == 1 && p_param.GetClickedObjectId() == 0xc3) { + VTable0xe4(); + GameState()->m_currentArea = LegoGameState::Area::e_unk66; + result = 1; + } + + return result; } // STUB: LEGO1 0x100104f0 From b17d76c2cc73c0d8b9a89ce9112aa9936eb1f18c Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sun, 28 Apr 2024 13:27:17 +0200 Subject: [PATCH 2/9] Refactor: Replace magic values by enum values (#865) Co-authored-by: jonschz --- LEGO1/lego/legoomni/src/actors/radio.cpp | 2 +- LEGO1/lego/legoomni/src/common/legogamestate.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/LEGO1/lego/legoomni/src/actors/radio.cpp b/LEGO1/lego/legoomni/src/actors/radio.cpp index e21a399f..5aaea1ab 100644 --- a/LEGO1/lego/legoomni/src/actors/radio.cpp +++ b/LEGO1/lego/legoomni/src/actors/radio.cpp @@ -80,7 +80,7 @@ void Radio::Stop() if (m_state->IsActive()) { LegoWorld* world = CurrentWorld(); - MxControlPresenter* presenter = (MxControlPresenter*) world->Find(world->GetAtom(), 18); + MxControlPresenter* presenter = (MxControlPresenter*) world->Find(world->GetAtom(), IsleScript::c_Radio_Ctl); if (presenter) { presenter->VTable0x6c(0); diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 9ef5b33a..3fedc6c4 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -1083,28 +1083,28 @@ void LegoGameState::Init() if (m_loadedAct == e_act1) { Isle* isle = (Isle*) FindWorld(*g_isleScript, 0); - Helicopter* copter = (Helicopter*) isle->Find(*g_copterScript, 1); + Helicopter* copter = (Helicopter*) isle->Find(*g_copterScript, CopterScript::c_Helicopter_Actor); if (copter) { isle->FUN_1001fc80(copter); isle->VTable0x6c(copter); delete copter; } - DuneBuggy* dunebuggy = (DuneBuggy*) isle->Find(*g_dunecarScript, 2); + DuneBuggy* dunebuggy = (DuneBuggy*) isle->Find(*g_dunecarScript, DunecarScript::c_DuneBugy_Actor); if (dunebuggy) { isle->FUN_1001fc80(dunebuggy); isle->VTable0x6c(dunebuggy); delete dunebuggy; } - Jetski* jetski = (Jetski*) isle->Find(*g_jetskiScript, 3); + Jetski* jetski = (Jetski*) isle->Find(*g_jetskiScript, JetskiScript::c_Jetski_Actor); if (jetski) { isle->FUN_1001fc80(jetski); isle->VTable0x6c(jetski); delete jetski; } - RaceCar* racecar = (RaceCar*) isle->Find(*g_racecarScript, 4); + RaceCar* racecar = (RaceCar*) isle->Find(*g_racecarScript, RacecarScript::c_RaceCar_Actor); if (racecar) { isle->FUN_1001fc80(racecar); isle->VTable0x6c(racecar); From ca9b6112519242a13c454bdd4f30337b0202ea9e Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 28 Apr 2024 08:49:07 -0400 Subject: [PATCH 3/9] Add enums for character LODs and parts (#866) --- LEGO1/lego/legoomni/include/legocharacters.h | 27 ++++++ .../src/common/legocharactermanager.cpp | 82 +++++++++++-------- 2 files changed, 77 insertions(+), 32 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocharacters.h b/LEGO1/lego/legoomni/include/legocharacters.h index 309d6f00..0d0ce6f0 100644 --- a/LEGO1/lego/legoomni/include/legocharacters.h +++ b/LEGO1/lego/legoomni/include/legocharacters.h @@ -45,6 +45,33 @@ struct LegoCharacterLOD { float m_up[3]; // 0x4c }; +enum LegoCharacterLODs { + c_topLOD, + c_bodyLOD, + c_infohatLOD, + c_infogronLOD, + c_headLOD, + c_armlftLOD, + c_armrtLOD, + c_clawlftLOD, + c_clawrtLOD, + c_leglftLOD, + c_legrtLOD +}; + +enum LegoCharacterParts { + c_bodyPart, + c_infohatPart, + c_infogronPart, + c_headPart, + c_armlftPart, + c_armrtPart, + c_clawlftPart, + c_clawrtPart, + c_leglftPart, + c_legrtPart +}; + extern LegoCharacterData g_characterDataInit[66]; extern LegoCharacterLOD g_characterLODs[11]; diff --git a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp index ba2ddde5..2b7e598d 100644 --- a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp @@ -94,25 +94,34 @@ MxResult LegoCharacterManager::Write(LegoStorage* p_storage) if (p_storage->Write(&data->m_unk0x14, sizeof(data->m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[1].m_unk0x08, sizeof(data->m_parts[1].m_unk0x08)) != SUCCESS) { + if (p_storage->Write(&data->m_parts[c_infohatPart].m_unk0x08, sizeof(data->m_parts[c_infohatPart].m_unk0x08)) != + SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[1].m_unk0x14, sizeof(data->m_parts[1].m_unk0x14)) != SUCCESS) { + if (p_storage->Write(&data->m_parts[c_infohatPart].m_unk0x14, sizeof(data->m_parts[c_infohatPart].m_unk0x14)) != + SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[2].m_unk0x14, sizeof(data->m_parts[2].m_unk0x14)) != SUCCESS) { + if (p_storage->Write( + &data->m_parts[c_infogronPart].m_unk0x14, + sizeof(data->m_parts[c_infogronPart].m_unk0x14) + ) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[4].m_unk0x14, sizeof(data->m_parts[4].m_unk0x14)) != SUCCESS) { + if (p_storage->Write(&data->m_parts[c_armlftPart].m_unk0x14, sizeof(data->m_parts[c_armlftPart].m_unk0x14)) != + SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[5].m_unk0x14, sizeof(data->m_parts[5].m_unk0x14)) != SUCCESS) { + if (p_storage->Write(&data->m_parts[c_armrtPart].m_unk0x14, sizeof(data->m_parts[c_armrtPart].m_unk0x14)) != + SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[8].m_unk0x14, sizeof(data->m_parts[8].m_unk0x14)) != SUCCESS) { + if (p_storage->Write(&data->m_parts[c_leglftPart].m_unk0x14, sizeof(data->m_parts[c_leglftPart].m_unk0x14)) != + SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[9].m_unk0x14, sizeof(data->m_parts[9].m_unk0x14)) != SUCCESS) { + if (p_storage->Write(&data->m_parts[c_legrtPart].m_unk0x14, sizeof(data->m_parts[c_legrtPart].m_unk0x14)) != + SUCCESS) { goto done; } } @@ -140,25 +149,34 @@ MxResult LegoCharacterManager::Read(LegoStorage* p_storage) if (p_storage->Read(&data->m_unk0x14, sizeof(data->m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[1].m_unk0x08, sizeof(data->m_parts[1].m_unk0x08)) != SUCCESS) { + if (p_storage->Read(&data->m_parts[c_infohatPart].m_unk0x08, sizeof(data->m_parts[c_infohatPart].m_unk0x08)) != + SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[1].m_unk0x14, sizeof(data->m_parts[1].m_unk0x14)) != SUCCESS) { + if (p_storage->Read(&data->m_parts[c_infohatPart].m_unk0x14, sizeof(data->m_parts[c_infohatPart].m_unk0x14)) != + SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[2].m_unk0x14, sizeof(data->m_parts[2].m_unk0x14)) != SUCCESS) { + if (p_storage->Read( + &data->m_parts[c_infogronPart].m_unk0x14, + sizeof(data->m_parts[c_infogronPart].m_unk0x14) + ) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[4].m_unk0x14, sizeof(data->m_parts[4].m_unk0x14)) != SUCCESS) { + if (p_storage->Read(&data->m_parts[c_armlftPart].m_unk0x14, sizeof(data->m_parts[c_armlftPart].m_unk0x14)) != + SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[5].m_unk0x14, sizeof(data->m_parts[5].m_unk0x14)) != SUCCESS) { + if (p_storage->Read(&data->m_parts[c_armrtPart].m_unk0x14, sizeof(data->m_parts[c_armrtPart].m_unk0x14)) != + SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[8].m_unk0x14, sizeof(data->m_parts[8].m_unk0x14)) != SUCCESS) { + if (p_storage->Read(&data->m_parts[c_leglftPart].m_unk0x14, sizeof(data->m_parts[c_leglftPart].m_unk0x14)) != + SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[9].m_unk0x14, sizeof(data->m_parts[9].m_unk0x14)) != SUCCESS) { + if (p_storage->Read(&data->m_parts[c_legrtPart].m_unk0x14, sizeof(data->m_parts[c_legrtPart].m_unk0x14)) != + SUCCESS) { goto done; } } @@ -402,18 +420,18 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key) roi = new LegoROI(renderer); roi->SetName(p_key); - boundingSphere.Center()[0] = g_characterLODs[0].m_boundingSphere[0]; - boundingSphere.Center()[1] = g_characterLODs[0].m_boundingSphere[1]; - boundingSphere.Center()[2] = g_characterLODs[0].m_boundingSphere[2]; - boundingSphere.Radius() = g_characterLODs[0].m_boundingSphere[3]; + boundingSphere.Center()[0] = g_characterLODs[c_topLOD].m_boundingSphere[0]; + boundingSphere.Center()[1] = g_characterLODs[c_topLOD].m_boundingSphere[1]; + boundingSphere.Center()[2] = g_characterLODs[c_topLOD].m_boundingSphere[2]; + boundingSphere.Radius() = g_characterLODs[c_topLOD].m_boundingSphere[3]; roi->SetBoundingSphere(boundingSphere); - boundingBox.Min()[0] = g_characterLODs[0].m_boundingBox[0]; - boundingBox.Min()[1] = g_characterLODs[0].m_boundingBox[1]; - boundingBox.Min()[2] = g_characterLODs[0].m_boundingBox[2]; - boundingBox.Max()[0] = g_characterLODs[0].m_boundingBox[3]; - boundingBox.Max()[1] = g_characterLODs[0].m_boundingBox[4]; - boundingBox.Max()[2] = g_characterLODs[0].m_boundingBox[5]; + boundingBox.Min()[0] = g_characterLODs[c_topLOD].m_boundingBox[0]; + boundingBox.Min()[1] = g_characterLODs[c_topLOD].m_boundingBox[1]; + boundingBox.Min()[2] = g_characterLODs[c_topLOD].m_boundingBox[2]; + boundingBox.Max()[0] = g_characterLODs[c_topLOD].m_boundingBox[3]; + boundingBox.Max()[1] = g_characterLODs[c_topLOD].m_boundingBox[4]; + boundingBox.Max()[2] = g_characterLODs[c_topLOD].m_boundingBox[5]; roi->SetUnknown0x80(boundingBox); comp = new CompoundObject(); @@ -495,9 +513,9 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key) } CalcLocalTransform( - Mx3DPointFloat(g_characterLODs[0].m_position), - Mx3DPointFloat(g_characterLODs[0].m_direction), - Mx3DPointFloat(g_characterLODs[0].m_up), + Mx3DPointFloat(g_characterLODs[c_topLOD].m_position), + Mx3DPointFloat(g_characterLODs[c_topLOD].m_direction), + Mx3DPointFloat(g_characterLODs[c_topLOD].m_up), mat ); roi->WrappedSetLocalTransform(mat); @@ -519,12 +537,12 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key) MxBool LegoCharacterManager::FUN_100849a0(LegoROI* p_roi, LegoTextureInfo* p_textureInfo) { LegoResult result = SUCCESS; - LegoROI* head = FindChildROI(p_roi, g_characterLODs[4].m_name); + LegoROI* head = FindChildROI(p_roi, g_characterLODs[c_headLOD].m_name); if (head != NULL) { char lodName[256]; - ViewLODList* lodList = GetViewLODListManager()->Lookup(g_characterLODs[4].m_parentName); + ViewLODList* lodList = GetViewLODListManager()->Lookup(g_characterLODs[c_headLOD].m_parentName); MxS32 lodSize = lodList->Size(); sprintf(lodName, "%s%s%d", p_roi->GetName(), "head", g_unk0x100fc4e8++); ViewLODList* dupLodList = GetViewLODListManager()->Create(lodName, lodSize); @@ -533,7 +551,7 @@ MxBool LegoCharacterManager::FUN_100849a0(LegoROI* p_roi, LegoTextureInfo* p_tex if (p_textureInfo == NULL) { LegoCharacterData* info = GetData(p_roi->GetName()); - LegoCharacterData::Part& part = info->m_parts[3]; + LegoCharacterData::Part& part = info->m_parts[c_headPart]; p_textureInfo = TextureContainer()->Get(part.m_unk0x10[part.m_unk0x0c[part.m_unk0x14]]); } @@ -652,7 +670,7 @@ MxBool LegoCharacterManager::SwitchHat(LegoROI* p_roi) return FALSE; } - LegoCharacterData::Part& part = data->m_parts[1]; + LegoCharacterData::Part& part = data->m_parts[c_infohatPart]; part.m_unk0x08++; MxU8 unk0x00 = part.m_unk0x00[part.m_unk0x08]; @@ -662,7 +680,7 @@ MxBool LegoCharacterManager::SwitchHat(LegoROI* p_roi) unk0x00 = part.m_unk0x00[part.m_unk0x08]; } - LegoROI* childROI = FindChildROI(p_roi, g_characterLODs[2].m_name); + LegoROI* childROI = FindChildROI(p_roi, g_characterLODs[c_infohatLOD].m_name); if (childROI != NULL) { char lodName[256]; From 7c6c68d6f95b70a3b07128abd976fd7c20264b7b Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 28 Apr 2024 09:04:27 -0400 Subject: [PATCH 4/9] Rename LegoCharacterData to LegoCharacterInfo (#867) --- .../legoomni/include/legocharactermanager.h | 6 +- LEGO1/lego/legoomni/include/legocharacters.h | 4 +- .../src/common/legocharactermanager.cpp | 166 +++++++++--------- .../legoomni/src/common/legocharacters.cpp | 6 +- 4 files changed, 91 insertions(+), 91 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocharactermanager.h b/LEGO1/lego/legoomni/include/legocharactermanager.h index 038c31e8..1b8610f8 100644 --- a/LEGO1/lego/legoomni/include/legocharactermanager.h +++ b/LEGO1/lego/legoomni/include/legocharactermanager.h @@ -40,7 +40,7 @@ struct LegoCharacter { MxU32 m_refCount; // 0x04 }; -struct LegoCharacterData; +struct LegoCharacterInfo; typedef map LegoCharacterMap; @@ -64,8 +64,8 @@ class LegoCharacterManager { void FUN_10083f10(LegoROI* p_roi); MxBool FUN_100849a0(LegoROI* p_roi, LegoTextureInfo* p_textureInfo); LegoExtraActor* GetActor(const char* p_key); - LegoCharacterData* GetData(const char* p_key); - LegoCharacterData* GetData(LegoROI* p_roi); + LegoCharacterInfo* GetInfo(const char* p_key); + LegoCharacterInfo* GetInfo(LegoROI* p_roi); MxBool SwitchHat(LegoROI* p_roi); MxU32 FUN_10085140(LegoROI* p_roi, MxBool p_und); LegoROI* FUN_10085210(const char* p_name, const char* p_lodName, MxBool p_createEntity); diff --git a/LEGO1/lego/legoomni/include/legocharacters.h b/LEGO1/lego/legoomni/include/legocharacters.h index 0d0ce6f0..313a49e4 100644 --- a/LEGO1/lego/legoomni/include/legocharacters.h +++ b/LEGO1/lego/legoomni/include/legocharacters.h @@ -8,7 +8,7 @@ class LegoExtraActor; class LegoROI; // SIZE 0x108 -struct LegoCharacterData { +struct LegoCharacterInfo { // SIZE 0x18 struct Part { MxU8* m_unk0x00; // 0x00 @@ -72,7 +72,7 @@ enum LegoCharacterParts { c_legrtPart }; -extern LegoCharacterData g_characterDataInit[66]; +extern LegoCharacterInfo g_characterInfoInit[66]; extern LegoCharacterLOD g_characterLODs[11]; #endif // LEGOCHARACTERS_H diff --git a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp index 2b7e598d..2d851715 100644 --- a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp @@ -35,7 +35,7 @@ MxU32 g_unk0x100fc4ec = 2; MxU32 g_unk0x100fc4f0 = 0; // GLOBAL: LEGO1 0x10104f20 -LegoCharacterData g_characterData[66]; +LegoCharacterInfo g_chracterInfo[66]; // FUNCTION: LEGO1 0x10082a20 LegoCharacterManager::LegoCharacterManager() @@ -50,22 +50,22 @@ LegoCharacterManager::LegoCharacterManager() // FUNCTION: LEGO1 0x10083270 void LegoCharacterManager::Init() { - for (MxS32 i = 0; i < _countof(g_characterData); i++) { - g_characterData[i] = g_characterDataInit[i]; + for (MxS32 i = 0; i < _countof(g_chracterInfo); i++) { + g_chracterInfo[i] = g_characterInfoInit[i]; } } // FUNCTION: LEGO1 0x100832a0 void LegoCharacterManager::FUN_100832a0() { - for (MxS32 i = 0; i < _countof(g_characterData); i++) { - LegoCharacterData* data = GetData(g_characterData[i].m_name); + for (MxS32 i = 0; i < _countof(g_chracterInfo); i++) { + LegoCharacterInfo* info = GetInfo(g_chracterInfo[i].m_name); - if (data != NULL) { - LegoExtraActor* actor = data->m_actor; + if (info != NULL) { + LegoExtraActor* actor = info->m_actor; if (actor != NULL && actor->IsA("LegoExtraActor")) { - LegoROI* roi = g_characterData[i].m_roi; + LegoROI* roi = g_chracterInfo[i].m_roi; MxU32 refCount = GetRefCount(roi); while (refCount != 0) { @@ -82,45 +82,45 @@ MxResult LegoCharacterManager::Write(LegoStorage* p_storage) { MxResult result = FAILURE; - for (MxS32 i = 0; i < _countof(g_characterData); i++) { - LegoCharacterData* data = &g_characterData[i]; + for (MxS32 i = 0; i < _countof(g_chracterInfo); i++) { + LegoCharacterInfo* info = &g_chracterInfo[i]; - if (p_storage->Write(&data->m_unk0x0c, sizeof(data->m_unk0x0c)) != SUCCESS) { + if (p_storage->Write(&info->m_unk0x0c, sizeof(info->m_unk0x0c)) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_unk0x10, sizeof(data->m_unk0x10)) != SUCCESS) { + if (p_storage->Write(&info->m_unk0x10, sizeof(info->m_unk0x10)) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_unk0x14, sizeof(data->m_unk0x14)) != SUCCESS) { + if (p_storage->Write(&info->m_unk0x14, sizeof(info->m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[c_infohatPart].m_unk0x08, sizeof(data->m_parts[c_infohatPart].m_unk0x08)) != + if (p_storage->Write(&info->m_parts[c_infohatPart].m_unk0x08, sizeof(info->m_parts[c_infohatPart].m_unk0x08)) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[c_infohatPart].m_unk0x14, sizeof(data->m_parts[c_infohatPart].m_unk0x14)) != + if (p_storage->Write(&info->m_parts[c_infohatPart].m_unk0x14, sizeof(info->m_parts[c_infohatPart].m_unk0x14)) != SUCCESS) { goto done; } if (p_storage->Write( - &data->m_parts[c_infogronPart].m_unk0x14, - sizeof(data->m_parts[c_infogronPart].m_unk0x14) + &info->m_parts[c_infogronPart].m_unk0x14, + sizeof(info->m_parts[c_infogronPart].m_unk0x14) ) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[c_armlftPart].m_unk0x14, sizeof(data->m_parts[c_armlftPart].m_unk0x14)) != + if (p_storage->Write(&info->m_parts[c_armlftPart].m_unk0x14, sizeof(info->m_parts[c_armlftPart].m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[c_armrtPart].m_unk0x14, sizeof(data->m_parts[c_armrtPart].m_unk0x14)) != + if (p_storage->Write(&info->m_parts[c_armrtPart].m_unk0x14, sizeof(info->m_parts[c_armrtPart].m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[c_leglftPart].m_unk0x14, sizeof(data->m_parts[c_leglftPart].m_unk0x14)) != + if (p_storage->Write(&info->m_parts[c_leglftPart].m_unk0x14, sizeof(info->m_parts[c_leglftPart].m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Write(&data->m_parts[c_legrtPart].m_unk0x14, sizeof(data->m_parts[c_legrtPart].m_unk0x14)) != + if (p_storage->Write(&info->m_parts[c_legrtPart].m_unk0x14, sizeof(info->m_parts[c_legrtPart].m_unk0x14)) != SUCCESS) { goto done; } @@ -137,45 +137,45 @@ MxResult LegoCharacterManager::Read(LegoStorage* p_storage) { MxResult result = FAILURE; - for (MxS32 i = 0; i < _countof(g_characterData); i++) { - LegoCharacterData* data = &g_characterData[i]; + for (MxS32 i = 0; i < _countof(g_chracterInfo); i++) { + LegoCharacterInfo* info = &g_chracterInfo[i]; - if (p_storage->Read(&data->m_unk0x0c, sizeof(data->m_unk0x0c)) != SUCCESS) { + if (p_storage->Read(&info->m_unk0x0c, sizeof(info->m_unk0x0c)) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_unk0x10, sizeof(data->m_unk0x10)) != SUCCESS) { + if (p_storage->Read(&info->m_unk0x10, sizeof(info->m_unk0x10)) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_unk0x14, sizeof(data->m_unk0x14)) != SUCCESS) { + if (p_storage->Read(&info->m_unk0x14, sizeof(info->m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[c_infohatPart].m_unk0x08, sizeof(data->m_parts[c_infohatPart].m_unk0x08)) != + if (p_storage->Read(&info->m_parts[c_infohatPart].m_unk0x08, sizeof(info->m_parts[c_infohatPart].m_unk0x08)) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[c_infohatPart].m_unk0x14, sizeof(data->m_parts[c_infohatPart].m_unk0x14)) != + if (p_storage->Read(&info->m_parts[c_infohatPart].m_unk0x14, sizeof(info->m_parts[c_infohatPart].m_unk0x14)) != SUCCESS) { goto done; } if (p_storage->Read( - &data->m_parts[c_infogronPart].m_unk0x14, - sizeof(data->m_parts[c_infogronPart].m_unk0x14) + &info->m_parts[c_infogronPart].m_unk0x14, + sizeof(info->m_parts[c_infogronPart].m_unk0x14) ) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[c_armlftPart].m_unk0x14, sizeof(data->m_parts[c_armlftPart].m_unk0x14)) != + if (p_storage->Read(&info->m_parts[c_armlftPart].m_unk0x14, sizeof(info->m_parts[c_armlftPart].m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[c_armrtPart].m_unk0x14, sizeof(data->m_parts[c_armrtPart].m_unk0x14)) != + if (p_storage->Read(&info->m_parts[c_armrtPart].m_unk0x14, sizeof(info->m_parts[c_armrtPart].m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[c_leglftPart].m_unk0x14, sizeof(data->m_parts[c_leglftPart].m_unk0x14)) != + if (p_storage->Read(&info->m_parts[c_leglftPart].m_unk0x14, sizeof(info->m_parts[c_leglftPart].m_unk0x14)) != SUCCESS) { goto done; } - if (p_storage->Read(&data->m_parts[c_legrtPart].m_unk0x14, sizeof(data->m_parts[c_legrtPart].m_unk0x14)) != + if (p_storage->Read(&info->m_parts[c_legrtPart].m_unk0x14, sizeof(info->m_parts[c_legrtPart].m_unk0x14)) != SUCCESS) { goto done; } @@ -231,7 +231,7 @@ LegoROI* LegoCharacterManager::GetROI(const char* p_key, MxBool p_createEntity) actor->SetROI(character->m_roi, FALSE, FALSE); actor->SetType(LegoEntity::e_character); actor->SetFlag(LegoActor::c_bit2); - GetData(p_key)->m_actor = actor; + GetInfo(p_key)->m_actor = actor; } return character->m_roi; @@ -268,7 +268,7 @@ void LegoCharacterManager::FUN_10083c30(const char* p_name) character = (*it).second; if (character->RemoveRef() == 0) { - LegoCharacterData* data = GetData(p_name); + LegoCharacterInfo* info = GetInfo(p_name); LegoEntity* entity = character->m_roi->GetEntity(); if (entity != NULL) { @@ -282,18 +282,18 @@ void LegoCharacterManager::FUN_10083c30(const char* p_name) m_characters->erase(it); - if (data != NULL) { - if (data->m_actor != NULL) { - data->m_actor->ClearFlag(LegoEntity::c_bit2); - delete data->m_actor; + if (info != NULL) { + if (info->m_actor != NULL) { + info->m_actor->ClearFlag(LegoEntity::c_bit2); + delete info->m_actor; } else if (entity != NULL && entity->GetFlagsIsSet(LegoEntity::c_bit2)) { entity->ClearFlag(LegoEntity::c_bit2); delete entity; } - data->m_roi = NULL; - data->m_actor = NULL; + info->m_roi = NULL; + info->m_actor = NULL; } } } @@ -310,7 +310,7 @@ void LegoCharacterManager::FUN_10083db0(LegoROI* p_roi) if (character->m_roi == p_roi) { if (character->RemoveRef() == 0) { - LegoCharacterData* data = GetData(character->m_roi->GetName()); + LegoCharacterInfo* info = GetInfo(character->m_roi->GetName()); LegoEntity* entity = character->m_roi->GetEntity(); if (entity != NULL) { @@ -324,18 +324,18 @@ void LegoCharacterManager::FUN_10083db0(LegoROI* p_roi) m_characters->erase(it); - if (data != NULL) { - if (data->m_actor != NULL) { - data->m_actor->ClearFlag(LegoEntity::c_bit2); - delete data->m_actor; + if (info != NULL) { + if (info->m_actor != NULL) { + info->m_actor->ClearFlag(LegoEntity::c_bit2); + delete info->m_actor; } else if (entity != NULL && entity->GetFlagsIsSet(LegoEntity::c_bit2)) { entity->ClearFlag(LegoEntity::c_bit2); delete entity; } - data->m_roi = NULL; - data->m_actor = NULL; + info->m_roi = NULL; + info->m_actor = NULL; } } @@ -399,21 +399,21 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key) Tgl::Renderer* renderer = VideoManager()->GetRenderer(); ViewLODListManager* lodManager = GetViewLODListManager(); LegoTextureContainer* textureContainer = TextureContainer(); - LegoCharacterData* data = GetData(p_key); + LegoCharacterInfo* info = GetInfo(p_key); - if (data == NULL) { + if (info == NULL) { goto done; } if (!strcmpi(p_key, "pep")) { - LegoCharacterData* pepper = GetData("pepper"); + LegoCharacterInfo* pepper = GetInfo("pepper"); - data->m_unk0x0c = pepper->m_unk0x0c; - data->m_unk0x10 = pepper->m_unk0x10; - data->m_unk0x14 = pepper->m_unk0x14; + info->m_unk0x0c = pepper->m_unk0x0c; + info->m_unk0x10 = pepper->m_unk0x10; + info->m_unk0x14 = pepper->m_unk0x14; - for (i = 0; i < _countof(data->m_parts); i++) { - data->m_parts[i] = pepper->m_parts[i]; + for (i = 0; i < _countof(info->m_parts); i++) { + info->m_parts[i] = pepper->m_parts[i]; } } @@ -439,7 +439,7 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key) for (i = 0; i < _countof(g_characterLODs) - 1; i++) { char lodName[256]; - LegoCharacterData::Part& part = data->m_parts[i]; + LegoCharacterInfo::Part& part = info->m_parts[i]; const char* parentName; if (i == 0 || i == 1) { @@ -520,7 +520,7 @@ LegoROI* LegoCharacterManager::CreateROI(const char* p_key) ); roi->WrappedSetLocalTransform(mat); - data->m_roi = roi; + info->m_roi = roi; success = TRUE; done: @@ -550,8 +550,8 @@ MxBool LegoCharacterManager::FUN_100849a0(LegoROI* p_roi, LegoTextureInfo* p_tex Tgl::Renderer* renderer = VideoManager()->GetRenderer(); if (p_textureInfo == NULL) { - LegoCharacterData* info = GetData(p_roi->GetName()); - LegoCharacterData::Part& part = info->m_parts[c_headPart]; + LegoCharacterInfo* info = GetInfo(p_roi->GetName()); + LegoCharacterInfo::Part& part = info->m_parts[c_headPart]; p_textureInfo = TextureContainer()->Get(part.m_unk0x10[part.m_unk0x0c[part.m_unk0x14]]); } @@ -583,8 +583,8 @@ MxBool LegoCharacterManager::FUN_100849a0(LegoROI* p_roi, LegoTextureInfo* p_tex // FUNCTION: LEGO1 0x10084c00 MxBool LegoCharacterManager::Exists(const char* p_key) { - for (MxU32 i = 0; i < _countof(g_characterData); i++) { - if (!strcmpi(g_characterData[i].m_name, p_key)) { + for (MxU32 i = 0; i < _countof(g_chracterInfo); i++) { + if (!strcmpi(g_chracterInfo[i].m_name, p_key)) { return TRUE; } } @@ -595,46 +595,46 @@ MxBool LegoCharacterManager::Exists(const char* p_key) // FUNCTION: LEGO1 0x10084c40 LegoExtraActor* LegoCharacterManager::GetActor(const char* p_key) { - LegoCharacterData* data = GetData(p_key); + LegoCharacterInfo* info = GetInfo(p_key); - if (data != NULL) { - return data->m_actor; + if (info != NULL) { + return info->m_actor; } return NULL; } // FUNCTION: LEGO1 0x10084c60 -LegoCharacterData* LegoCharacterManager::GetData(const char* p_key) +LegoCharacterInfo* LegoCharacterManager::GetInfo(const char* p_key) { MxU32 i; - for (i = 0; i < _countof(g_characterData); i++) { - if (!strcmpi(g_characterData[i].m_name, p_key)) { + for (i = 0; i < _countof(g_chracterInfo); i++) { + if (!strcmpi(g_chracterInfo[i].m_name, p_key)) { break; } } - if (i < _countof(g_characterData)) { - return &g_characterData[i]; + if (i < _countof(g_chracterInfo)) { + return &g_chracterInfo[i]; } return NULL; } // FUNCTION: LEGO1 0x10084cb0 -LegoCharacterData* LegoCharacterManager::GetData(LegoROI* p_roi) +LegoCharacterInfo* LegoCharacterManager::GetInfo(LegoROI* p_roi) { MxU32 i; - for (i = 0; i < _countof(g_characterData); i++) { - if (g_characterData[i].m_roi == p_roi) { + for (i = 0; i < _countof(g_chracterInfo); i++) { + if (g_chracterInfo[i].m_roi == p_roi) { break; } } - if (i < _countof(g_characterData)) { - return &g_characterData[i]; + if (i < _countof(g_chracterInfo)) { + return &g_chracterInfo[i]; } return NULL; @@ -664,13 +664,13 @@ LegoROI* LegoCharacterManager::FindChildROI(LegoROI* p_roi, const char* p_name) // FUNCTION: LEGO1 0x10084ec0 MxBool LegoCharacterManager::SwitchHat(LegoROI* p_roi) { - LegoCharacterData* data = GetData(p_roi->GetName()); + LegoCharacterInfo* info = GetInfo(p_roi->GetName()); - if (data == NULL) { + if (info == NULL) { return FALSE; } - LegoCharacterData::Part& part = data->m_parts[c_infohatPart]; + LegoCharacterInfo::Part& part = info->m_parts[c_infohatPart]; part.m_unk0x08++; MxU8 unk0x00 = part.m_unk0x00[part.m_unk0x08]; @@ -718,14 +718,14 @@ MxBool LegoCharacterManager::SwitchHat(LegoROI* p_roi) // FUNCTION: LEGO1 0x10085140 MxU32 LegoCharacterManager::FUN_10085140(LegoROI* p_roi, MxBool p_und) { - LegoCharacterData* data = GetData(p_roi); + LegoCharacterInfo* info = GetInfo(p_roi); if (p_und) { - return data->m_unk0x14 + g_unk0x100fc4dc; + return info->m_unk0x14 + g_unk0x100fc4dc; } - if (data != NULL) { - return data->m_unk0x0c + g_unk0x100fc4d8; + if (info != NULL) { + return info->m_unk0x0c + g_unk0x100fc4d8; } return 0; diff --git a/LEGO1/lego/legoomni/src/common/legocharacters.cpp b/LEGO1/lego/legoomni/src/common/legocharacters.cpp index bd30b0d4..d80b49c8 100644 --- a/LEGO1/lego/legoomni/src/common/legocharacters.cpp +++ b/LEGO1/lego/legoomni/src/common/legocharacters.cpp @@ -1,7 +1,7 @@ #include "legocharacters.h" -DECOMP_SIZE_ASSERT(LegoCharacterData, 0x108) -DECOMP_SIZE_ASSERT(LegoCharacterData::Part, 0x18) +DECOMP_SIZE_ASSERT(LegoCharacterInfo, 0x108) +DECOMP_SIZE_ASSERT(LegoCharacterInfo::Part, 0x18) DECOMP_SIZE_ASSERT(LegoCharacterLOD, 0x58) // Unclear whether g_characterLODs[0] (top) is its own global, see: LegoCharacterManager::CreateROI @@ -172,7 +172,7 @@ const char* g_unk0x100f80a0[] = {"lego white", "lego black", "lego yellow", "lego red", "lego blue", "lego brown", "lego lt grey", "lego green"}; // GLOBAL: LEGO1 0x100f80c0 -LegoCharacterData g_characterDataInit[] = { +LegoCharacterInfo g_characterInfoInit[] = { {"pepper", NULL, NULL, From e7670f9a8153530b77133c0bb8c62dd2b812f051 Mon Sep 17 00:00:00 2001 From: MS Date: Mon, 29 Apr 2024 14:33:16 -0400 Subject: [PATCH 5/9] Read floating point constants up front (#868) * Read floating point constants before sanitize * Fix roadmap --- tools/isledecomp/isledecomp/bin.py | 53 ++++++++++++++++++- .../isledecomp/compare/asm/parse.py | 44 --------------- tools/isledecomp/isledecomp/compare/core.py | 13 +++++ tools/isledecomp/isledecomp/compare/db.py | 17 ++++++ tools/isledecomp/isledecomp/types.py | 1 + tools/isledecomp/tests/test_sanitize.py | 2 + tools/roadmap/roadmap.py | 14 ++++- 7 files changed, 97 insertions(+), 47 deletions(-) diff --git a/tools/isledecomp/isledecomp/bin.py b/tools/isledecomp/isledecomp/bin.py index 9ca3195b..05ecfa92 100644 --- a/tools/isledecomp/isledecomp/bin.py +++ b/tools/isledecomp/isledecomp/bin.py @@ -2,7 +2,7 @@ import struct import bisect from functools import cached_property -from typing import List, Optional, Tuple +from typing import Iterator, List, Optional, Tuple from dataclasses import dataclass from collections import namedtuple @@ -77,6 +77,18 @@ def match_name(self, name: str) -> bool: def contains_vaddr(self, vaddr: int) -> bool: return self.virtual_address <= vaddr < self.virtual_address + self.extent + def read_virtual(self, vaddr: int, size: int) -> memoryview: + ofs = vaddr - self.virtual_address + + # Negative index will read from the end, which we don't want + if ofs < 0: + raise InvalidVirtualAddressError + + try: + return self.view[ofs : ofs + size] + except IndexError as ex: + raise InvalidVirtualAddressError from ex + def addr_is_uninitialized(self, vaddr: int) -> bool: """We cannot rely on the IMAGE_SCN_CNT_UNINITIALIZED_DATA flag (0x80) in the characteristics field so instead we determine it this way.""" @@ -109,6 +121,7 @@ def __init__(self, filename: str, find_str: bool = False) -> None: self._section_vaddr: List[int] = [] self.find_str = find_str self._potential_strings = {} + self._relocations = set() self._relocated_addrs = set() self.imports = [] self.thunks = [] @@ -279,11 +292,49 @@ def _populate_relocations(self): # We are now interested in the relocated addresses themselves. Seek to the # address where there is a relocation, then read the four bytes into our set. reloc_addrs.sort() + self._relocations = set(reloc_addrs) + for section_id, offset in map(self.get_relative_addr, reloc_addrs): section = self.get_section_by_index(section_id) (relocated_addr,) = struct.unpack(" Iterator[Tuple[int, int, float]]: + """Floating point instructions that refer to a memory address can + point to constant values. Search the code sections to find FP + instructions and check whether the pointer address refers to + read-only data.""" + + # TODO: Should check any section that has code, not just .text + text = self.get_section_by_name(".text") + rdata = self.get_section_by_name(".rdata") + + # These are the addresses where a relocation occurs. + # Meaning: it points to an absolute address of something + for addr in self._relocations: + if not text.contains_vaddr(addr): + continue + + # Read the two bytes before the relocated address. + # We will check against possible float opcodes + raw = text.read_virtual(addr - 2, 6) + (opcode, opcode_ext, const_addr) = struct.unpack(" Optional[int]: return None -def bytes_to_float(b: bytes) -> Optional[float]: - if len(b) == 4: - return struct.unpack(" Optional[int]: if len(b) == 4: return struct.unpack(" bool: return False - def float_replace(self, addr: int, data_size: int) -> Optional[str]: - if callable(self.bin_lookup): - float_bytes = self.bin_lookup(addr, data_size) - if float_bytes is None: - return None - - float_value = bytes_to_float(float_bytes) - if float_value is not None: - return f"{float_value} (FLOAT)" - - return None - def lookup( self, addr: int, use_cache: bool = True, exact: bool = False ) -> Optional[str]: @@ -165,25 +143,6 @@ def hex_replace_indirect(self, match: re.Match) -> str: return match.group(0).replace(match.group(1), self.replace(value)) - def hex_replace_float(self, match: re.Match) -> str: - """Special case for replacements on float instructions. - If the pointer is a float constant, read it from the binary.""" - value = int(match.group(1), 16) - - # If we can find a variable name for this pointer, use it. - placeholder = self.lookup(value) - - # Read what's under the pointer and show the decimal value. - if placeholder is None: - float_size = 8 if "qword" in match.string else 4 - placeholder = self.float_replace(value, float_size) - - # If we can't read the float, use a regular placeholder. - if placeholder is None: - placeholder = self.replace(value) - - return match.group(0).replace(match.group(1), placeholder) - def sanitize(self, inst: DisasmLiteInst) -> Tuple[str, str]: # For jumps or calls, if the entire op_str is a hex number, the value # is a relative offset. @@ -224,9 +183,6 @@ def sanitize(self, inst: DisasmLiteInst) -> Tuple[str, str]: if inst.mnemonic == "call": # Special handling for absolute indirect CALL. op_str = ptr_replace_regex.sub(self.hex_replace_indirect, inst.op_str) - elif inst.mnemonic.startswith("f"): - # If floating point instruction - op_str = ptr_replace_regex.sub(self.hex_replace_float, inst.op_str) else: op_str = ptr_replace_regex.sub(self.hex_replace_always, inst.op_str) diff --git a/tools/isledecomp/isledecomp/compare/core.py b/tools/isledecomp/isledecomp/compare/core.py index c66cee94..b49600d0 100644 --- a/tools/isledecomp/isledecomp/compare/core.py +++ b/tools/isledecomp/isledecomp/compare/core.py @@ -82,6 +82,7 @@ def __init__( self._load_cvdump() self._load_markers() self._find_original_strings() + self._find_float_const() self._match_imports() self._match_exports() self._match_thunks() @@ -249,6 +250,18 @@ def _find_original_strings(self): self._db.match_string(addr, 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 + deduped like strings.""" + for addr, size, float_value in self.orig_bin.find_float_consts(): + self._db.set_orig_symbol(addr, SymbolType.FLOAT, str(float_value), size) + + for addr, size, float_value in self.recomp_bin.find_float_consts(): + self._db.set_recomp_symbol( + addr, SymbolType.FLOAT, str(float_value), None, size + ) + def _match_imports(self): """We can match imported functions based on the DLL name and function symbol name.""" diff --git a/tools/isledecomp/isledecomp/compare/db.py b/tools/isledecomp/isledecomp/compare/db.py index f055e8fd..634cf455 100644 --- a/tools/isledecomp/isledecomp/compare/db.py +++ b/tools/isledecomp/isledecomp/compare/db.py @@ -84,6 +84,23 @@ def __init__(self): self._db = sqlite3.connect(":memory:") self._db.executescript(_SETUP_SQL) + def set_orig_symbol( + self, + addr: int, + compare_type: Optional[SymbolType], + name: Optional[str], + size: Optional[int], + ): + # Ignore collisions here. + if self._orig_used(addr): + return + + compare_value = compare_type.value if compare_type is not None else None + self._db.execute( + "INSERT INTO `symbols` (orig_addr, compare_type, name, size) VALUES (?,?,?,?)", + (addr, compare_value, name, size), + ) + def set_recomp_symbol( self, addr: int, diff --git a/tools/isledecomp/isledecomp/types.py b/tools/isledecomp/isledecomp/types.py index 4d518dd3..31829c65 100644 --- a/tools/isledecomp/isledecomp/types.py +++ b/tools/isledecomp/isledecomp/types.py @@ -10,3 +10,4 @@ class SymbolType(Enum): POINTER = 3 STRING = 4 VTABLE = 5 + FLOAT = 6 diff --git a/tools/isledecomp/tests/test_sanitize.py b/tools/isledecomp/tests/test_sanitize.py index ca23c861..deb3c825 100644 --- a/tools/isledecomp/tests/test_sanitize.py +++ b/tools/isledecomp/tests/test_sanitize.py @@ -189,6 +189,7 @@ def substitute_1234(addr: int, _: bool) -> Optional[str]: assert op_str == "0x5555" +@pytest.mark.skip(reason="changed implementation") def test_float_replacement(): """Floating point constants often appear as pointers to data. A good example is ViewROI::IntrinsicImportance and the subclass override @@ -208,6 +209,7 @@ def bin_lookup(addr: int, _: int) -> Optional[bytes]: assert op_str == "dword ptr [3.1415927410125732 (FLOAT)]" +@pytest.mark.skip(reason="changed implementation") def test_float_variable(): """If there is a variable at the address referenced by a float instruction, use the name instead of calling into the float replacement handler.""" diff --git a/tools/roadmap/roadmap.py b/tools/roadmap/roadmap.py index 379fcfc2..a0df3cbc 100644 --- a/tools/roadmap/roadmap.py +++ b/tools/roadmap/roadmap.py @@ -10,6 +10,7 @@ from typing import Iterator, List, Optional, Tuple from collections import namedtuple from isledecomp import Bin as IsleBin +from isledecomp.bin import InvalidVirtualAddressError from isledecomp.cvdump import Cvdump from isledecomp.compare import Compare as IsleCompare from isledecomp.types import SymbolType @@ -87,7 +88,7 @@ def print_sections(sections): print() -ALLOWED_TYPE_ABBREVIATIONS = ["fun", "dat", "poi", "str", "vta"] +ALLOWED_TYPE_ABBREVIATIONS = ["fun", "dat", "poi", "str", "vta", "flo"] def match_type_abbreviation(mtype: Optional[SymbolType]) -> str: @@ -456,7 +457,16 @@ def to_roadmap_row(match): module_name, ) - results = list(map(to_roadmap_row, engine.get_all())) + def roadmap_row_generator(matches): + for match in matches: + try: + yield to_roadmap_row(match) + except InvalidVirtualAddressError: + # This is here to work around the fact that we have RVA + # values (i.e. not real virtual addrs) in our compare db. + pass + + results = list(roadmap_row_generator(engine.get_all())) if args.order is not None: suggest_order(results, module_map, args.order) From 599d8c91c88845bd1700595320b380dd1e655b51 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 30 Apr 2024 04:27:57 -0400 Subject: [PATCH 6/9] Implement/match LegoAnimationManager::Resume (#869) * Implement/match LegoAnimationManager::FUN_1005f0b0 * Rename --- .../legoomni/include/legoanimationmanager.h | 6 ++-- .../src/common/legoanimationmanager.cpp | 31 ++++++++++++------- .../legoomni/src/common/legogamestate.cpp | 6 ++-- LEGO1/lego/legoomni/src/entity/legoworld.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/isle.cpp | 4 +-- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index ae8bc302..073db18a 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -67,8 +67,8 @@ class LegoAnimationManager : public MxCore { } void Reset(MxBool p_und); - void FUN_1005ef10(); - void FUN_1005f0b0(); + void Suspend(); + void Resume(); void FUN_1005f6d0(MxBool); void FUN_1005f700(MxBool); MxResult LoadScriptInfo(MxS32 p_scriptIndex); @@ -154,7 +154,7 @@ class LegoAnimationManager : public MxCore { undefined m_unk0x428; // 0x428 undefined m_unk0x429; // 0x429 undefined m_unk0x42a; // 0x42a - undefined m_unk0x42b; // 0x42b + MxBool m_suspended; // 0x42b undefined4 m_unk0x42c; // 0x42c undefined m_unk0x430; // 0x430 undefined4 m_unk0x434[2]; // 0x434 diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index 2bf7664f..1a708b32 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -158,8 +158,8 @@ void LegoAnimationManager::Reset(MxBool p_und) m_animState->SetFlag(); } - undefined unk0x42b = m_unk0x42b; - FUN_1005ef10(); + MxBool suspended = m_suspended; + Suspend(); if (m_tranInfoList != NULL) { delete m_tranInfoList; @@ -172,22 +172,31 @@ void LegoAnimationManager::Reset(MxBool p_und) DeleteAnimations(); Init(); - m_unk0x42b = unk0x42b; + m_suspended = suspended; m_unk0x428 = m_unk0x3a; m_unk0x429 = m_unk0x400; m_unk0x42a = m_unk0x402; } // STUB: LEGO1 0x1005ef10 -void LegoAnimationManager::FUN_1005ef10() +// FUNCTION: BETA10 0x1003fc7a +void LegoAnimationManager::Suspend() { // TODO } -// STUB: LEGO1 0x1005f0b0 -void LegoAnimationManager::FUN_1005f0b0() +// FUNCTION: LEGO1 0x1005f0b0 +// FUNCTION: BETA10 0x1003fefe +void LegoAnimationManager::Resume() { - // TODO + if (m_suspended) { + m_unk0x408 = m_unk0x40c = m_unk0x404 = Timer()->GetTime(); + m_unk0x410 = 5000; + m_unk0x3a = m_unk0x428; + m_unk0x400 = m_unk0x429; + m_unk0x402 = m_unk0x42a; + m_suspended = FALSE; + } } // FUNCTION: LEGO1 0x1005f130 @@ -227,7 +236,7 @@ void LegoAnimationManager::Init() m_unk0x0e = 0; m_unk0x10 = 0; m_unk0x401 = 0; - m_unk0x42b = 0; + m_suspended = FALSE; m_unk0x430 = 0; m_unk0x42c = 0; m_unk0x408 = m_unk0x40c = m_unk0x404 = Timer()->GetTime(); @@ -402,7 +411,7 @@ MxResult LegoAnimationManager::LoadScriptInfo(MxS32 p_scriptIndex) result = SUCCESS; m_unk0x402 = 1; - if (m_unk0x42b) { + if (m_suspended) { m_unk0x428 = m_unk0x3a; m_unk0x429 = m_unk0x400; m_unk0x42a = 1; @@ -541,7 +550,7 @@ MxResult LegoAnimationManager::ReadModelInfo(LegoFile* p_file, ModelInfo* p_info // FUNCTION: LEGO1 0x100603c0 void LegoAnimationManager::DeleteAnimations() { - undefined unk0x42b = m_unk0x42b; + MxBool suspended = m_suspended; if (m_anims != NULL) { for (MxS32 i = 0; i < m_animCount; i++) { @@ -560,7 +569,7 @@ void LegoAnimationManager::DeleteAnimations() } Init(); - m_unk0x42b = unk0x42b; + m_suspended = suspended; } // STUB: LEGO1 0x10060570 diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 3fedc6c4..ef1a436e 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -791,7 +791,7 @@ void LegoGameState::SwitchArea(Area p_area) FUN_10015820(TRUE, LegoOmni::c_disableInput | LegoOmni::c_disable3d); BackgroundAudioManager()->Stop(); - AnimationManager()->FUN_1005ef10(); + AnimationManager()->Suspend(); VideoManager()->SetUnk0x554(FALSE); switch (p_area) { @@ -896,7 +896,7 @@ void LegoGameState::SwitchArea(Area p_area) else { SetCameraControllerFromIsle(); CurrentActor()->ResetWorldTransform(TRUE); - AnimationManager()->FUN_1005f0b0(); + AnimationManager()->Resume(); } CurrentActor()->VTable0xe8(p_area, TRUE, 7); @@ -910,7 +910,7 @@ void LegoGameState::SwitchArea(Area p_area) LoadIsle(); SetCameraControllerFromIsle(); CurrentActor()->ResetWorldTransform(TRUE); - AnimationManager()->FUN_1005f0b0(); + AnimationManager()->Resume(); CurrentActor()->VTable0xe8(p_area, TRUE, 7); break; case e_police: diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index 13696cbb..522c9918 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -630,7 +630,7 @@ void LegoWorld::Enable(MxBool p_enable) PlantManager()->FUN_10026360(m_scriptIndex); AnimationManager()->LoadScriptInfo(m_scriptIndex); BuildingManager()->FUN_1002fa00(); - AnimationManager()->FUN_1005f0b0(); + AnimationManager()->Resume(); } GameState()->ResetROI(); diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index f26dca62..d917427a 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -857,7 +857,7 @@ MxLong Isle::HandleTransitionEnd() GameState()->StopArea(LegoGameState::e_previousArea); m_destLocation = LegoGameState::e_undefined; VariableTable()->SetVariable("VISIBILITY", "Show Gas"); - AnimationManager()->FUN_1005f0b0(); + AnimationManager()->Resume(); FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); SetAppCursor(0); SetIsWorldActive(TRUE); @@ -867,7 +867,7 @@ MxLong Isle::HandleTransitionEnd() GameState()->StopArea(LegoGameState::e_previousArea); m_destLocation = LegoGameState::e_undefined; VariableTable()->SetVariable("VISIBILITY", "Show Policsta"); - AnimationManager()->FUN_1005f0b0(); + AnimationManager()->Resume(); FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); SetAppCursor(0); SetIsWorldActive(TRUE); From 60796eff74914e22ee7a25691be3946cecf9bee6 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 30 Apr 2024 06:18:44 -0400 Subject: [PATCH 7/9] Implement/match LegoAnimationManager::Suspend (#870) --- .../legoomni/include/legoanimationmanager.h | 4 +- .../src/common/legoanimationmanager.cpp | 72 +++++++++++++++++-- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index 073db18a..10a9158e 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -37,10 +37,10 @@ struct Vehicle { // SIZE 0x18 struct Unknown0x3c { LegoROI* m_roi; // 0x00 - MxU32 m_id; // 0x04 + MxS32 m_characterId; // 0x04 undefined m_unk0x08[0x08]; // 0x08 float m_unk0x10; // 0x10 - undefined m_unk0x14; // 0x14 + MxBool m_unk0x14; // 0x14 }; // VTABLE: LEGO1 0x100d8c18 diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index 1a708b32..55ae98d7 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -178,11 +178,73 @@ void LegoAnimationManager::Reset(MxBool p_und) m_unk0x42a = m_unk0x402; } -// STUB: LEGO1 0x1005ef10 +// FUNCTION: LEGO1 0x1005ef10 // FUNCTION: BETA10 0x1003fc7a void LegoAnimationManager::Suspend() { - // TODO + m_animState = (AnimState*) GameState()->GetState("AnimState"); + if (m_animState == NULL) { + m_animState = (AnimState*) GameState()->CreateState("AnimState"); + } + + if (m_scriptIndex == 0) { + m_animState->FUN_10065240(m_animCount, m_anims, m_unk0x3fc); + } + + if (!m_suspended) { + m_suspended = TRUE; + m_unk0x428 = m_unk0x3a; + m_unk0x429 = m_unk0x400; + m_unk0x42a = m_unk0x402; + m_unk0x402 = 0; + + FUN_10061010(0); + + MxS32 i; + for (i = 0; i < (MxS32) _countof(m_unk0x3c); i++) { + LegoROI* roi = m_unk0x3c[i].m_roi; + + if (roi != NULL) { + LegoPathActor* actor = CharacterManager()->GetActor(roi->GetName()); + + if (actor != NULL && actor->GetController() != NULL) { + actor->GetController()->FUN_10046770(actor); + actor->ClearController(); + } + + CharacterManager()->FUN_10083db0(roi); + } + + if (m_unk0x3c[i].m_unk0x14) { + m_unk0x3c[i].m_unk0x14 = FALSE; + + MxS32 vehicleId = g_characters[m_unk0x3c[i].m_characterId].m_vehicleId; + if (vehicleId >= 0) { + g_vehicles[vehicleId].m_unk0x05 = FALSE; + + LegoROI* roi = Lego()->FindROI(g_vehicles[vehicleId].m_name); + if (roi != NULL) { + roi->SetVisibility(FALSE); + } + } + } + + m_unk0x3c[i].m_roi = NULL; + m_unk0x3c[i].m_characterId = -1; + m_unk0x3c[i].m_unk0x10 = -1.0f; + } + + m_unk0x18 = 0; + m_unk0x1a = 0; + m_unk0x3a = 0; + m_unk0x400 = 0; + m_unk0x414 = 0; + m_unk0x401 = 0; + + for (i = 0; i < (MxS32) _countof(g_characters); i++) { + g_characters[i].m_unk0x04 = FALSE; + } + } } // FUNCTION: LEGO1 0x1005f0b0 @@ -221,9 +283,9 @@ void LegoAnimationManager::Init() for (i = 0; i < (MxS32) _countof(m_unk0x3c); i++) { m_unk0x3c[i].m_roi = NULL; - m_unk0x3c[i].m_id = -1; + m_unk0x3c[i].m_characterId = -1; m_unk0x3c[i].m_unk0x10 = -1.0f; - m_unk0x3c[i].m_unk0x14 = 0; + m_unk0x3c[i].m_unk0x14 = FALSE; } m_unk0x38 = FALSE; @@ -666,7 +728,7 @@ MxResult LegoAnimationManager::StartEntityAction(MxDSAction& p_dsAction, LegoEnt for (MxS32 i = 0; i < (MxS32) _countof(m_unk0x3c); i++) { if (m_unk0x3c[i].m_roi == roi) { - MxU32 characterId = m_unk0x3c[i].m_id; + MxS32 characterId = m_unk0x3c[i].m_characterId; g_characters[characterId].m_unk0x07 = TRUE; MxS32 vehicleId = g_characters[characterId].m_vehicleId; From b902790c54aec89c009f398434705904437a79a1 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 30 Apr 2024 06:38:55 -0400 Subject: [PATCH 8/9] Implement/match LegoAnimationManager::FUN_1005f6d0 and FUN_1005f700 (#871) * Implement/match LegoAnimationManager::FUN_1005f6d0 and FUN_1005f700 * Use bool constants --- .../legoomni/include/legoanimationmanager.h | 12 +++--- .../src/common/legoanimationmanager.cpp | 40 +++++++++++++------ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index 10a9158e..7ba6705b 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -69,8 +69,8 @@ class LegoAnimationManager : public MxCore { void Reset(MxBool p_und); void Suspend(); void Resume(); - void FUN_1005f6d0(MxBool); - void FUN_1005f700(MxBool); + void FUN_1005f6d0(MxBool p_unk0x400); + void FUN_1005f700(MxBool p_unk0x3a); MxResult LoadScriptInfo(MxS32 p_scriptIndex); MxBool FindVehicle(const char* p_name, MxU32& p_index); MxResult ReadAnimInfo(LegoFile* p_file, AnimInfo* p_info); @@ -136,10 +136,10 @@ class LegoAnimationManager : public MxCore { MxLong m_unk0x30[2]; // 0x30 MxBool m_unk0x38; // 0x38 MxBool m_unk0x39; // 0x39 - undefined m_unk0x3a; // 0x3a + MxBool m_unk0x3a; // 0x3a Unknown0x3c m_unk0x3c[40]; // 0x3c undefined4 m_unk0x3fc; // 0x3fc - MxU8 m_unk0x400; // 0x400 + MxBool m_unk0x400; // 0x400 undefined m_unk0x401; // 0x401 MxU8 m_unk0x402; // 0x402 MxLong m_unk0x404; // 0x404 @@ -151,8 +151,8 @@ class LegoAnimationManager : public MxCore { undefined4 m_unk0x41c; // 0x41c AnimState* m_animState; // 0x420 LegoROIList* m_unk0x424; // 0x424 - undefined m_unk0x428; // 0x428 - undefined m_unk0x429; // 0x429 + MxBool m_unk0x428; // 0x428 + MxBool m_unk0x429; // 0x429 undefined m_unk0x42a; // 0x42a MxBool m_suspended; // 0x42b undefined4 m_unk0x42c; // 0x42c diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index 55ae98d7..61f801f2 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -236,8 +236,8 @@ void LegoAnimationManager::Suspend() m_unk0x18 = 0; m_unk0x1a = 0; - m_unk0x3a = 0; - m_unk0x400 = 0; + m_unk0x3a = FALSE; + m_unk0x400 = FALSE; m_unk0x414 = 0; m_unk0x401 = 0; @@ -290,9 +290,9 @@ void LegoAnimationManager::Init() m_unk0x38 = FALSE; m_unk0x39 = FALSE; - m_unk0x3a = 1; + m_unk0x3a = TRUE; m_unk0x3fc = 0; - m_unk0x400 = 0; + m_unk0x400 = FALSE; m_unk0x414 = 0; m_unk0x418 = 5; m_unk0x0e = 0; @@ -322,16 +322,32 @@ void LegoAnimationManager::Init() m_unk0x424 = new LegoROIList(); } -// STUB: LEGO1 0x1005f6d0 -void LegoAnimationManager::FUN_1005f6d0(MxBool) +// FUNCTION: LEGO1 0x1005f6d0 +// FUNCTION: BETA10 0x100401e7 +void LegoAnimationManager::FUN_1005f6d0(MxBool p_unk0x400) { - // TODO + if (m_suspended) { + m_unk0x429 = p_unk0x400; + } + else { + m_unk0x400 = p_unk0x400; + + if (!p_unk0x400) { + FUN_100627d0(TRUE); + } + } } -// STUB: LEGO1 0x1005f700 -void LegoAnimationManager::FUN_1005f700(MxBool) +// FUNCTION: LEGO1 0x1005f700 +// FUNCTION: BETA10 0x1004024c +void LegoAnimationManager::FUN_1005f700(MxBool p_unk0x3a) { - // TODO + if (m_suspended) { + m_unk0x428 = p_unk0x3a; + } + else { + m_unk0x3a = p_unk0x3a; + } } // FUNCTION: LEGO1 0x1005f720 @@ -477,8 +493,8 @@ MxResult LegoAnimationManager::LoadScriptInfo(MxS32 p_scriptIndex) m_unk0x428 = m_unk0x3a; m_unk0x429 = m_unk0x400; m_unk0x42a = 1; - m_unk0x3a = 0; - m_unk0x400 = 0; + m_unk0x3a = FALSE; + m_unk0x400 = FALSE; m_unk0x402 = 0; } From 20dee07b9ca0863bf3c7258dd97f0cc2bd6b951e Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 30 Apr 2024 10:02:58 -0400 Subject: [PATCH 9/9] Implement/match LegoAnimationManager::FUN_100605e0 (#872) * Implement/match LegoAnimationManager::FUN_100605e0 * Remove padding * Fix annotation --- LEGO1/lego/legoomni/include/animstate.h | 5 +- .../legoomni/include/legoanimationmanager.h | 28 ++-- LEGO1/lego/legoomni/include/legotraninfo.h | 3 +- LEGO1/lego/legoomni/include/misc.h | 6 - .../src/common/legoanimationmanager.cpp | 152 +++++++++++++++--- LEGO1/lego/legoomni/src/common/misc.cpp | 7 + LEGO1/lego/legoomni/src/worlds/isle.cpp | 4 +- 7 files changed, 160 insertions(+), 45 deletions(-) diff --git a/LEGO1/lego/legoomni/include/animstate.h b/LEGO1/lego/legoomni/include/animstate.h index d81c26d8..9d15fd50 100644 --- a/LEGO1/lego/legoomni/include/animstate.h +++ b/LEGO1/lego/legoomni/include/animstate.h @@ -18,15 +18,16 @@ struct AnimInfo { char* m_animName; // 0x00 MxU32 m_objectId; // 0x04 MxS16 m_unk0x08; // 0x08 - MxU8 m_unk0x0a; // 0x0a + MxBool m_unk0x0a; // 0x0a MxU8 m_unk0x0b; // 0x0b MxU8 m_unk0x0c; // 0x0c MxU8 m_unk0x0d; // 0x0d MxU32 m_unk0x10[4]; // 0x10 MxU8 m_modelCount; // 0x20 + MxS16 m_unk0x22; // 0x22 ModelInfo* m_models; // 0x24 MxU8 m_unk0x28; // 0x28 - MxU8 m_unk0x29; // 0x29 + MxBool m_unk0x29; // 0x29 MxS8 m_unk0x2a[3]; // 0x2a }; diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index 7ba6705b..abc4d96e 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -80,13 +80,13 @@ class LegoAnimationManager : public MxCore { MxResult FUN_10060dc0( IsleScript::Script p_objectId, MxMatrix* p_matrix, - undefined p_param3, + MxBool p_param3, undefined p_param4, - undefined4 p_param5, - undefined p_param6, + LegoROI* p_roi, + MxBool p_param6, MxBool p_param7, MxBool p_param8, - undefined p_param9 + MxBool p_param9 ); void FUN_10061010(undefined4); void FUN_100617c0(MxS32, MxU16&, MxU16&); @@ -108,21 +108,25 @@ class LegoAnimationManager : public MxCore { void Init(); MxResult FUN_100605e0( MxU32 p_index, - MxU8 p_unk0x0a, + MxBool p_unk0x0a, MxMatrix* p_matrix, - undefined, - undefined4, - undefined, - MxBool, - MxBool, - undefined + MxBool p_bool1, + LegoROI* p_roi, + MxBool p_bool2, + MxBool p_bool3, + MxBool p_bool4, + MxBool p_bool5 ); MxResult FUN_100609f0(MxU32 p_objectId, MxMatrix* p_matrix, MxBool p_und1, MxBool p_und2); void DeleteAnimations(); MxS8 GetCharacterIndex(const char* p_name); + MxBool FUN_100623a0(AnimInfo& p_info); + void FUN_10062580(AnimInfo& p_info); + MxBool FUN_10062710(AnimInfo& p_info); void FUN_10063aa0(); + void FUN_100648f0(LegoTranInfo*, MxLong); - MxU32 m_scriptIndex; // 0x08 + MxS32 m_scriptIndex; // 0x08 MxU16 m_animCount; // 0x0c MxU16 m_unk0x0e; // 0x0e MxU16 m_unk0x10; // 0x10 diff --git a/LEGO1/lego/legoomni/include/legotraninfo.h b/LEGO1/lego/legoomni/include/legotraninfo.h index dfea986a..c15617e8 100644 --- a/LEGO1/lego/legoomni/include/legotraninfo.h +++ b/LEGO1/lego/legoomni/include/legotraninfo.h @@ -4,6 +4,7 @@ #include "decomp.h" #include "mxgeometry/mxmatrix.h" +struct AnimInfo; class LegoAnimMMPresenter; // SIZE 0x78 @@ -30,7 +31,7 @@ struct LegoTranInfo { m_unk0x2c.SetIdentity(); } - undefined4 m_unk0x00; // 0x00 + AnimInfo* m_animInfo; // 0x00 MxU32 m_index; // 0x04 LegoROI* m_unk0x08; // 0x08 MxMatrix* m_unk0x0c; // 0x0c diff --git a/LEGO1/lego/legoomni/include/misc.h b/LEGO1/lego/legoomni/include/misc.h index 67c97c78..2d809258 100644 --- a/LEGO1/lego/legoomni/include/misc.h +++ b/LEGO1/lego/legoomni/include/misc.h @@ -64,10 +64,4 @@ void PlayMusic(JukeboxScript::Script p_script); void SetIsWorldActive(MxBool p_isWorldActive); void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last); -// FUNCTION: LEGO1 0x10015890 -inline MxResult StartActionIfUnknown0x13c(MxDSAction& p_dsAction) -{ - return LegoOmni::GetInstance()->StartActionIfUnknown0x13c(p_dsAction); -} - #endif // MISC_H diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index 61f801f2..27dcce84 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -451,7 +451,7 @@ MxResult LegoAnimationManager::LoadScriptInfo(MxS32 p_scriptIndex) } m_anims[j].m_unk0x28 = GetCharacterIndex(m_anims[j].m_animName + strlen(m_anims[j].m_animName) - 2); - m_anims[j].m_unk0x29 = 0; + m_anims[j].m_unk0x29 = FALSE; for (k = 0; k < 3; k++) { m_anims[j].m_unk0x2a[k] = -1; @@ -656,22 +656,100 @@ void LegoAnimationManager::FUN_10060570(MxBool) // TODO } -// STUB: LEGO1 0x100605e0 +// FUNCTION: LEGO1 0x100605e0 // FUNCTION: BETA10 0x1004152b MxResult LegoAnimationManager::FUN_100605e0( MxU32 p_index, - MxU8 p_unk0x0a, + MxBool p_unk0x0a, MxMatrix* p_matrix, - undefined, - undefined4, - undefined, - MxBool, - MxBool, - undefined + MxBool p_bool1, + LegoROI* p_roi, + MxBool p_bool2, + MxBool p_bool3, + MxBool p_bool4, + MxBool p_bool5 ) { - // TODO - return FAILURE; + MxResult result = FAILURE; + + if (m_scriptIndex != -1 && p_index < m_animCount && m_tranInfoList != NULL) { + FUN_100627d0(FALSE); + FUN_10062770(); + + MxDSAction action; + AnimInfo& animInfo = m_anims[p_index]; + + if (!p_bool1) { + if (m_unk0x39 || !animInfo.m_unk0x29) { + return FAILURE; + } + + if (FUN_100623a0(animInfo)) { + return FAILURE; + } + + if (FUN_10062710(animInfo)) { + return FAILURE; + } + } + + FUN_10062580(animInfo); + + LegoTranInfo* tranInfo = new LegoTranInfo(); + tranInfo->m_animInfo = &animInfo; + tranInfo->m_index = ++m_unk0x1c; + tranInfo->m_unk0x10 = 0; + tranInfo->m_unk0x08 = p_roi; + tranInfo->m_unk0x12 = m_anims[p_index].m_unk0x08; + tranInfo->m_unk0x14 = p_unk0x0a; + tranInfo->m_objectId = animInfo.m_objectId; + tranInfo->m_unk0x15 = p_bool2; + + if (p_matrix != NULL) { + tranInfo->m_unk0x0c = new MxMatrix(*p_matrix); + } + + tranInfo->m_unk0x1c = m_unk0x28; + tranInfo->m_unk0x20 = m_unk0x30; + tranInfo->m_unk0x28 = p_bool3; + tranInfo->m_unk0x29 = p_bool4; + + if (m_tranInfoList != NULL) { + m_tranInfoList->Append(tranInfo); + } + + char buf[256]; + sprintf(buf, "%s:%d", g_strANIMMAN_ID, tranInfo->m_index); + + action.SetAtomId(*Lego()->GetScriptAtom(m_scriptIndex)); + action.SetObjectId(animInfo.m_objectId); + action.SetUnknown24(-1); + action.AppendExtra(strlen(buf) + 1, buf); + + if (StartActionIfUnknown0x13c(action) == SUCCESS) { + BackgroundAudioManager()->LowerVolume(); + tranInfo->m_flags |= LegoTranInfo::c_bit2; + animInfo.m_unk0x22++; + m_unk0x404 = Timer()->GetTime(); + + if (p_bool5) { + FUN_100648f0(tranInfo, m_unk0x404); + } + else if (p_unk0x0a) { + IslePathActor* actor = CurrentActor(); + + if (actor != NULL) { + actor->SetState(4); + actor->SetWorldSpeed(0.0f); + } + } + + m_unk0x39 = TRUE; + result = SUCCESS; + } + } + + return result; } // FUNCTION: LEGO1 0x100609f0 @@ -684,12 +762,12 @@ MxResult LegoAnimationManager::FUN_100609f0(MxU32 p_objectId, MxMatrix* p_matrix FUN_100627d0(FALSE); LegoTranInfo* info = new LegoTranInfo(); - info->m_unk0x00 = 0; + info->m_animInfo = NULL; info->m_index = ++m_unk0x1c; info->m_unk0x10 = 0; info->m_unk0x08 = NULL; info->m_unk0x12 = -1; - info->m_unk0x14 = 0; + info->m_unk0x14 = FALSE; info->m_objectId = p_objectId; if (p_matrix != NULL) { @@ -758,7 +836,7 @@ MxResult LegoAnimationManager::StartEntityAction(MxDSAction& p_dsAction, LegoEnt } } - if (StartActionIfUnknown0x13c(p_dsAction) == SUCCESS) { + if (LegoOmni::GetInstance()->StartActionIfUnknown0x13c(p_dsAction) == SUCCESS) { result = SUCCESS; } @@ -770,13 +848,13 @@ MxResult LegoAnimationManager::StartEntityAction(MxDSAction& p_dsAction, LegoEnt MxResult LegoAnimationManager::FUN_10060dc0( IsleScript::Script p_objectId, MxMatrix* p_matrix, - undefined p_param3, + MxBool p_param3, undefined p_param4, - undefined4 p_param5, - undefined p_param6, + LegoROI* p_roi, + MxBool p_param6, MxBool p_param7, MxBool p_param8, - undefined p_param9 + MxBool p_param9 ) { MxResult result = FAILURE; @@ -789,21 +867,21 @@ MxResult LegoAnimationManager::FUN_10060dc0( for (MxS32 i = 0; i < m_animCount; i++) { if (m_anims[i].m_objectId == p_objectId) { found = TRUE; - undefined unk0x0a; + MxBool unk0x0a; switch (p_param4) { case 0: unk0x0a = m_anims[i].m_unk0x0a; break; case 1: - unk0x0a = 1; + unk0x0a = TRUE; break; default: - unk0x0a = 0; + unk0x0a = FALSE; break; } - result = FUN_100605e0(i, unk0x0a, p_matrix, p_param3, p_param5, p_param6, p_param7, p_param8, p_param9); + result = FUN_100605e0(i, unk0x0a, p_matrix, p_param3, p_roi, p_param6, p_param7, p_param8, p_param9); break; } } @@ -874,6 +952,29 @@ MxS8 LegoAnimationManager::GetCharacterIndex(const char* p_name) return -1; } +// STUB: LEGO1 0x100623a0 +// FUNCTION: BETA10 0x10043342 +MxBool LegoAnimationManager::FUN_100623a0(AnimInfo& p_info) +{ + // TODO + return FALSE; +} + +// STUB: LEGO1 0x10062580 +// FUNCTION: BETA10 0x10043552 +void LegoAnimationManager::FUN_10062580(AnimInfo& p_info) +{ + // TODO +} + +// STUB: LEGO1 0x10062710 +// FUNCTION: BETA10 0x10043787 +MxBool LegoAnimationManager::FUN_10062710(AnimInfo& p_info) +{ + // TODO + return FALSE; +} + // FUNCTION: LEGO1 0x10062770 // FUNCTION: BETA10 0x1004381a void LegoAnimationManager::FUN_10062770() @@ -949,3 +1050,10 @@ void LegoAnimationManager::FUN_10064740(MxBool) { // TODO } + +// STUB: LEGO1 0x100648f0 +// FUNCTION: BETA10 0x10045daf +void LegoAnimationManager::FUN_100648f0(LegoTranInfo*, MxLong) +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index cc1d5218..fe4c6f7d 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -136,6 +136,13 @@ void SetCurrentActor(IslePathActor* p_currentActor) LegoOmni::GetInstance()->SetCurrentActor(p_currentActor); } +// FUNCTION: LEGO1 0x10015890 +// FUNCTION: BETA10 0x100e4d80 +MxResult StartActionIfUnknown0x13c(MxDSAction& p_dsAction) +{ + return LegoOmni::GetInstance()->StartActionIfUnknown0x13c(p_dsAction); +} + // FUNCTION: LEGO1 0x100158b0 void DeleteAction() { diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index d917427a..72d9d7d9 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -666,7 +666,7 @@ void Isle::Enable(MxBool p_enable) break; } - AnimationManager()->FUN_10060dc0(script, NULL, 1, 1, 0, 0, FALSE, TRUE, 0); + AnimationManager()->FUN_10060dc0(script, NULL, TRUE, 1, NULL, FALSE, FALSE, TRUE, 0); } m_act1state->m_unk0x018 = 0; @@ -694,7 +694,7 @@ void Isle::Enable(MxBool p_enable) break; } - AnimationManager()->FUN_10060dc0(script, NULL, 1, 1, 0, 0, FALSE, TRUE, 0); + AnimationManager()->FUN_10060dc0(script, NULL, TRUE, 1, NULL, FALSE, FALSE, TRUE, 0); } m_act1state->m_unk0x018 = 0;