diff --git a/.gitignore b/.gitignore index b5e87a00..81e69517 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +reccmp-user.yml +reccmp-build.yml Debug/ Release/ *.ncb diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index 60b5a9c3..0afb0824 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -16,6 +16,14 @@ class MxActionNotificationParam; // SIZE 0x50 class LegoVehicleBuildState : public LegoState { public: + enum AnimationState { + e_unknown0 = 0, + e_entering = 1, + e_unknown2 = 2, + e_cutscene = 3, + e_exiting = 6 + }; + LegoVehicleBuildState(const char* p_classType); // FUNCTION: LEGO1 0x10025ff0 @@ -46,15 +54,11 @@ class LegoVehicleBuildState : public LegoState { // * LegoJetskiBuildState MxString m_className; // 0x38 - // Known States: - // * 1 == enter(ing) build screen - // * 3 == cutscene/dialogue - // * 6 == exit(ing) build screen - MxU32 m_animationState; // 0x48 - undefined m_unk0x4c; // 0x4c - MxBool m_unk0x4d; // 0x4d - MxBool m_unk0x4e; // 0x4e - MxU8 m_placedPartCount; // 0x4f + AnimationState m_animationState; // 0x48 + undefined m_unk0x4c; // 0x4c + MxBool m_unk0x4d; // 0x4d + MxBool m_unk0x4e; // 0x4e + MxU8 m_placedPartCount; // 0x4f }; typedef LegoVehicleBuildState LegoRaceCarBuildState; @@ -103,6 +107,7 @@ class LegoCarBuild : public LegoWorld { MxFloat p_param4[2] ); // vtable+0x80 + MxS16 GetPlacedPartCount(); void InitPresenters(); void FUN_10022f30(); void FUN_10023130(MxLong p_x, MxLong p_y); @@ -113,7 +118,7 @@ class LegoCarBuild : public LegoWorld { undefined4 FUN_100246e0(MxLong p_x, MxLong p_y); MxS32 FUN_10024850(MxLong p_x, MxLong p_y); undefined4 FUN_10024890(LegoEventNotificationParam* p_param); - void FUN_10024c20(LegoEventNotificationParam* p_param); + undefined4 FUN_10024c20(LegoEventNotificationParam* p_param); void FUN_10024ef0(); void FUN_10024f50(); void FUN_10024f70(MxBool p_enabled); @@ -127,6 +132,9 @@ class LegoCarBuild : public LegoWorld { void FUN_10025e40(); MxS32 FUN_10025ee0(undefined4 p_param1); + // FUNCTION: BETA10 0x100735b0 + void SetUnknown0x258(LegoCarBuildAnimPresenter* p_unk0x258) { m_unk0x258 = p_unk0x258; } + // SYNTHETIC: LEGO1 0x10022a60 // LegoCarBuild::`scalar deleting destructor' @@ -194,7 +202,7 @@ class LegoCarBuild : public LegoWorld { // variable name verified by BETA10 0x1006cba7 LegoGameState::Area m_destLocation; // 0x334 - undefined4 m_unk0x338; // 0x338 + MxPresenter* m_unk0x338; // 0x338 MxControlPresenter* m_unk0x33c; // 0x33c undefined4 m_unk0x340; // 0x340 undefined4 m_unk0x344; // 0x344 @@ -202,7 +210,7 @@ class LegoCarBuild : public LegoWorld { static MxS16 g_unk0x100f11cc; static MxFloat g_unk0x100d65a4; - static MxFloat g_unk0x100d65a8; + static MxFloat g_rotationAngleStepYAxis; }; #endif // LEGOCARBUILD_H diff --git a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h index 8d707eff..b1233ada 100644 --- a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h +++ b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h @@ -9,11 +9,28 @@ // SIZE 0x150 class LegoCarBuildAnimPresenter : public LegoAnimPresenter { public: + enum { + c_bit1 = 0x01 + }; + // SIZE 0x0c struct UnknownListEntry { - LegoChar* m_unk0x00; // 0x00 - LegoChar* m_unk0x04; // 0x04 - undefined m_unk0x08[4]; // 0x08 + // FUNCTION: LEGO1 0x100795c0 + // FUNCTION: BETA10 0x10073850 + UnknownListEntry() + { + m_name = NULL; + m_wiredName = NULL; + m_unk0x08 = 0; + } + + // variable name verified by BETA10 0x10071b56 + LegoChar* m_name; // 0x00 + + // variable name verified by BETA10 0x100719f0 + LegoChar* m_wiredName; // 0x04 + + undefined2 m_unk0x08; // 0x08 }; LegoCarBuildAnimPresenter(); @@ -45,14 +62,26 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { void EndAction() override; // vtable+0x40 void PutFrame() override; // vtable+0x6c - void FUN_10079920(float p_param1); + void FUN_10079050(MxS16 p_index); + void SwapNodesByName(LegoChar* p_param1, LegoChar* p_param2); + void FUN_10079160(); + void FUN_100795d0(LegoChar* p_param); + void FUN_10079680(LegoChar* p_param); + LegoAnimNodeData* FindNodeDataByName(LegoTreeNode* p_treeNode, const LegoChar* p_name); + LegoTreeNode* FindNodeByName(LegoTreeNode* p_treeNode, const LegoChar* p_name); + void RotateAroundYAxis(MxFloat p_angle); MxBool FUN_10079c30(const LegoChar* p_name); - MxBool FUN_10079ca0(const LegoChar* p_name); - MxBool FUN_10079cf0(const LegoChar* p_string); + MxBool PartIsPlaced(const LegoChar* p_name); + void FUN_10079a90(); + MxBool StringEqualsPlatform(const LegoChar* p_string); + MxBool StringEqualsShelf(const LegoChar* p_string); + MxBool StringEndsOnY(const LegoChar* p_string); + MxBool StringEndsOnZero(const LegoChar* p_string); // FUNCTION: BETA10 0x10070180 void SetUnknown0xbc(undefined2 p_unk0xbc) { m_unk0xbc = p_unk0xbc; } + MxBool StringEndsOnW(LegoChar* p_param); MxBool StringEndsOnYOrN(const LegoChar* p_string); const BoundingSphere& FUN_10079e20(); @@ -61,22 +90,36 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { // LegoCarBuildAnimPresenter::`scalar deleting destructor' private: - undefined2 m_unk0xbc; // 0xbc - MxS16 m_unk0xbe; // 0xbe - MxS16 m_unk0xc0; // 0xc0 - undefined4 m_unk0xc4; // 0xc4 - LegoAnim m_unk0xc8; // 0xc8 - MxMatrix m_unk0xe0; // 0xe0 - UnknownListEntry* m_unk0x128; // 0x128 - undefined4 m_unk0x12c; // 0x12c - undefined4 m_unk0x130; // 0x130 - undefined4 m_unk0x134; // 0x134 - undefined4 m_unk0x138; // 0x138 - undefined4 m_unk0x13c; // 0x13c - LegoEntity* m_unk0x140; // 0x140 - MxS32 m_unk0x144; // 0x144 - MxS32 m_unk0x148; // 0x148 - undefined* m_unk0x14c; // 0x14c + void Beta10Inline0x100733d0(); + + MxU16 m_unk0xbc; // 0xbc + + // variable name verified by BETA10 0x1007184f + MxS16 m_numberOfParts; // 0xbe + + // name derived from LegoVehicleBuildState, field 0x4f + MxS16 m_placedPartCount; // 0xc0 + + LegoAnimNodeData* m_unk0xc4; // 0xc4 + LegoAnim m_unk0xc8; // 0xc8 + MxMatrix m_unk0xe0; // 0xe0 + + // variable name verified by BETA10 0x100719f0 + UnknownListEntry* m_parts; // 0x128 + + MxFloat m_unk0x12c; // 0x12c + MxFloat m_unk0x130; // 0x130 + MxFloat m_unk0x134; // 0x134 + MxFloat m_unk0x138; // 0x138 + MxLong m_unk0x13c; // 0x13c + LegoEntity* m_unk0x140; // 0x140 + MxS32 m_unk0x144; // 0x144 + MxS32 m_unk0x148; // 0x148 + + // name verified by BETA10 0x10070d63 + LegoChar* m_mainSourceId; // 0x14c + + friend class LegoCarBuild; }; #endif // LEGOCARBUILDPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoextraactor.h b/LEGO1/lego/legoomni/include/legoextraactor.h index dfb880f8..f6295efa 100644 --- a/LEGO1/lego/legoomni/include/legoextraactor.h +++ b/LEGO1/lego/legoomni/include/legoextraactor.h @@ -6,7 +6,7 @@ // VTABLE: LEGO1 0x100d6c00 LegoAnimActor // VTABLE: LEGO1 0x100d6c10 LegoPathActor // VTABLE: LEGO1 0x100d6cdc LegoExtraActor -// VTABLE: BETA10 0x101bc2b8 LegoAnimActor +// VTABLE: BETA10 0x101bc2b8 LegoPathActor // SIZE 0x1dc class LegoExtraActor : public virtual LegoAnimActor { public: diff --git a/LEGO1/lego/legoomni/include/legomain.h b/LEGO1/lego/legoomni/include/legomain.h index 75df917d..182500c1 100644 --- a/LEGO1/lego/legoomni/include/legomain.h +++ b/LEGO1/lego/legoomni/include/legomain.h @@ -134,7 +134,10 @@ class LegoOmni : public MxOmni { LegoPlantManager* GetPlantManager() { return m_plantManager; } LegoAnimationManager* GetAnimationManager() { return m_animationManager; } LegoBuildingManager* GetBuildingManager() { return m_buildingManager; } + + // FUNCTION: BETA10 0x100e52b0 LegoGameState* GetGameState() { return m_gameState; } + MxBackgroundAudioManager* GetBackgroundAudioManager() { return m_bkgAudioManager; } MxTransitionManager* GetTransitionManager() { return m_transitionManager; } MxDSAction& GetCurrentAction() { return m_action; } diff --git a/LEGO1/lego/legoomni/include/legomodelpresenter.h b/LEGO1/lego/legoomni/include/legomodelpresenter.h index 29c069b5..7f9886a9 100644 --- a/LEGO1/lego/legoomni/include/legomodelpresenter.h +++ b/LEGO1/lego/legoomni/include/legomodelpresenter.h @@ -9,6 +9,7 @@ class LegoEntity; class MxDSChunk; // VTABLE: LEGO1 0x100d4e50 +// VTABLE: BETA10 0x101bcd88 // SIZE 0x6c class LegoModelPresenter : public MxVideoPresenter { public: diff --git a/LEGO1/lego/legoomni/include/legoraceactor.h b/LEGO1/lego/legoomni/include/legoraceactor.h index 1fb1b28c..6fa69eff 100644 --- a/LEGO1/lego/legoomni/include/legoraceactor.h +++ b/LEGO1/lego/legoomni/include/legoraceactor.h @@ -35,6 +35,7 @@ class LegoRaceActor : public virtual LegoAnimActor { MxResult VTable0x94(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94 // FUNCTION: LEGO1 0x10014aa0 + // FUNCTION: BETA10 0x100ca038 virtual MxResult FUN_10014aa0() { return SUCCESS; } // SYNTHETIC: LEGO1 0x10012c10 diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h index 9e8c91fc..b6143c36 100644 --- a/LEGO1/lego/legoomni/include/legoutils.h +++ b/LEGO1/lego/legoomni/include/legoutils.h @@ -43,6 +43,7 @@ void FUN_1003dde0(LegoROI* p_param1, MxFloat p_param2); MxBool FUN_1003ded0(MxFloat p_param1[2], MxFloat p_param2[3], MxFloat p_param3[3]); MxBool TransformWorldToScreen(const MxFloat p_world[3], MxFloat p_screen[4]); MxS16 CountTotalTreeNodes(LegoTreeNode* p_node); +LegoTreeNode* GetTreeNode(LegoTreeNode* p_node, MxU32 p_index); void FUN_1003e050(LegoAnimPresenter* p_presenter); Extra::ActionType MatchActionString(const char*); void InvokeAction(Extra::ActionType p_actionId, const MxAtomId& p_pAtom, MxS32 p_targetEntityId, LegoEntity* p_sender); diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h index edfd345e..605d0626 100644 --- a/LEGO1/lego/legoomni/include/legovideomanager.h +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -53,7 +53,9 @@ class LegoVideoManager : public MxVideoManager { // FUNCTION: BETA10 0x100117e0 Lego3DManager* Get3DManager() { return m_3dManager; } + // FUNCTION: BETA10 0x1003a380 LegoROI* GetViewROI() { return m_viewROI; } + MxDirect3D* GetDirect3D() { return m_direct3d; } MxBool GetRender3D() { return m_render3d; } double GetElapsedSeconds() { return m_elapsedSeconds; } diff --git a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h index 20aa07bb..88bec8b1 100644 --- a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h +++ b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h @@ -3,6 +3,7 @@ #include "mxcore.h" #include "mxdsaction.h" +#include "mxpresenter.h" #include "mxtypes.h" class MxAudioPresenter; @@ -34,7 +35,7 @@ class MxBackgroundAudioManager : public MxCore { void StartAction(MxParam& p_param); void StopAction(MxParam& p_param); - MxResult PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, undefined4 p_unk0x13c); + MxResult PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, MxPresenter::TickleState p_tickleState); void FUN_1007ee70(); void FUN_1007ef40(); @@ -47,6 +48,7 @@ class MxBackgroundAudioManager : public MxCore { void Stop(); void LowerVolume(); void RaiseVolume(); + undefined4 FUN_1007f610(MxPresenter* p_unk0x138, MxS32 p_unk0x140, MxPresenter::TickleState p_tickleState); // SYNTHETIC: LEGO1 0x1007ec00 // MxBackgroundAudioManager::`scalar deleting destructor' @@ -60,11 +62,14 @@ class MxBackgroundAudioManager : public MxCore { MxAudioPresenter* m_unk0xa0; // 0xa0 MxDSAction m_action2; // 0xa4 MxAudioPresenter* m_unk0x138; // 0x138 - MxS32 m_unk0x13c; // 0x13c - MxS32 m_unk0x140; // 0x140 - MxS32 m_targetVolume; // 0x144 - MxS16 m_unk0x148; // 0x148 - MxAtomId m_script; // 0x14c + + // name is inferred from context + MxPresenter::TickleState m_tickleState; // 0x13c + + MxS32 m_unk0x140; // 0x140 + MxS32 m_targetVolume; // 0x144 + MxS16 m_unk0x148; // 0x148 + MxAtomId m_script; // 0x14c }; #endif // MXBACKGROUNDAUDIOMANAGER_H diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index 70dd2126..e8bd71c9 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -38,8 +38,7 @@ class PizzaMissionState : public LegoState { undefined m_unk0x03[3]; // 0x03 MxS16 m_unk0x06; // 0x06 undefined m_unk0x08[8]; // 0x08 - MxS16 m_unk0x10; // 0x10 - MxS16 m_unk0x12; // 0x12 + undefined4 m_unk0x10; // 0x10 MxS16 m_unk0x14; // 0x14 MxS16 m_unk0x16; // 0x16 MxS16 m_score; // 0x18 @@ -107,6 +106,7 @@ class Pizza : public IsleActor { void FUN_10038220(MxU32 p_objectId); void FUN_100382b0(); void FUN_10038380(); + void FUN_10038fe0(MxU32 p_objectId, MxBool); void SetSkateboard(SkateBoard* p_skateboard) { m_skateboard = p_skateboard; } @@ -114,14 +114,14 @@ class Pizza : public IsleActor { // Pizza::`scalar deleting destructor' private: - PizzaMissionState* m_state; // 0x7c - undefined4 m_unk0x80; // 0x80 - SkateBoard* m_skateboard; // 0x84 - Act1State* m_act1state; // 0x88 - undefined4 m_unk0x8c; // 0x8c - undefined4 m_unk0x90; // 0x90 - undefined4 m_unk0x94; // 0x94 - undefined m_unk0x98; // 0x98 + PizzaMissionState* m_state; // 0x7c + PizzaMissionState::Entry* m_entry; // 0x80 + SkateBoard* m_skateboard; // 0x84 + Act1State* m_act1state; // 0x88 + undefined4 m_unk0x8c; // 0x8c + undefined4 m_unk0x90; // 0x90 + undefined4 m_unk0x94; // 0x94 + undefined m_unk0x98; // 0x98 }; #endif // PIZZA_H diff --git a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp index 2ab12451..4aafa214 100644 --- a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp +++ b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp @@ -600,7 +600,7 @@ void IslePathActor::SpawnPlayer(LegoGameState::Area p_area, MxBool p_enter, MxU8 MxDSAction action; action.SetAtomId(*g_jukeboxScript); action.SetObjectId(g_spawnLocations[i].m_music); - BackgroundAudioManager()->PlayMusic(action, 5, 4); + BackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); } } } diff --git a/LEGO1/lego/legoomni/src/actors/jukeboxentity.cpp b/LEGO1/lego/legoomni/src/actors/jukeboxentity.cpp index 6888ebfa..a504fcbc 100644 --- a/LEGO1/lego/legoomni/src/actors/jukeboxentity.cpp +++ b/LEGO1/lego/legoomni/src/actors/jukeboxentity.cpp @@ -92,7 +92,7 @@ void JukeBoxEntity::StartAction() BackgroundAudioManager()->Enable(TRUE); } - BackgroundAudioManager()->PlayMusic(action, 5, 4); + BackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); } // FUNCTION: LEGO1 0x100860f0 diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index e634891b..593d7f74 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -1,6 +1,8 @@ #include "pizza.h" +#include "isle.h" #include "isle_actions.h" +#include "legoanimationmanager.h" #include "legogamestate.h" #include "legoworld.h" #include "misc.h" @@ -11,11 +13,14 @@ DECOMP_SIZE_ASSERT(Pizza, 0x9c) DECOMP_SIZE_ASSERT(PizzaMissionState, 0xb4) DECOMP_SIZE_ASSERT(PizzaMissionState::Entry, 0x20) +// Flags used in isle.cpp +extern MxU32 g_isleFlags; + // FUNCTION: LEGO1 0x10037ef0 Pizza::Pizza() { m_state = NULL; - m_unk0x80 = 0; + m_entry = NULL; m_skateboard = NULL; m_act1state = NULL; m_unk0x8c = -1; @@ -56,9 +61,19 @@ void Pizza::CreateState() } } -// STUB: LEGO1 0x10038220 +// FUNCTION: LEGO1 0x10038220 void Pizza::FUN_10038220(MxU32 p_objectId) { + AnimationManager()->FUN_10064740(NULL); + m_entry = m_state->GetState(GameState()->GetActorId()); + m_state->m_unk0x0c = 1; + m_act1state->m_unk0x018 = 3; + m_entry->m_unk0x10 = 0x80000000; + g_isleFlags &= ~Isle::c_playMusic; + AnimationManager()->EnableCamAnims(FALSE); + AnimationManager()->FUN_1005f6d0(FALSE); + FUN_10038fe0(p_objectId, FALSE); + m_unk0x8c = -1; } // STUB: LEGO1 0x100382b0 @@ -99,6 +114,12 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam&) return 0; } +// STUB: LEGO1 0x10038fe0 +void Pizza::FUN_10038fe0(MxU32 p_objectId, MxBool) +{ + // TODO +} + // STUB: LEGO1 0x10039030 PizzaMissionState::PizzaMissionState() { diff --git a/LEGO1/lego/legoomni/src/actors/radio.cpp b/LEGO1/lego/legoomni/src/actors/radio.cpp index 8d267d5a..4704ca29 100644 --- a/LEGO1/lego/legoomni/src/actors/radio.cpp +++ b/LEGO1/lego/legoomni/src/actors/radio.cpp @@ -115,7 +115,7 @@ void Radio::Play() BackgroundAudioManager()->Enable(TRUE); } - BackgroundAudioManager()->PlayMusic(action, 3, 4); + BackgroundAudioManager()->PlayMusic(action, 3, MxPresenter::e_repeating); m_state->SetActive(TRUE); } } @@ -178,7 +178,7 @@ MxLong Radio::HandleEndAction(MxEndActionNotificationParam& p_param) action.SetObjectId(m_state->FUN_1002d090()); action.SetLoopCount(1); - BackgroundAudioManager()->PlayMusic(action, 3, 4); + BackgroundAudioManager()->PlayMusic(action, 3, MxPresenter::e_repeating); return 1; } diff --git a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index 90d9df9b..d3e08256 100644 --- a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -20,7 +20,7 @@ MxBackgroundAudioManager::MxBackgroundAudioManager() NotificationManager()->Register(this); m_unk0xa0 = 0; m_unk0x138 = 0; - m_unk0x13c = 0; + m_tickleState = MxPresenter::e_idle; m_unk0x140 = 0; m_targetVolume = 0; m_unk0x148 = 0; @@ -81,7 +81,7 @@ void MxBackgroundAudioManager::DestroyMusic() // FUNCTION: LEGO1 0x1007ee40 MxResult MxBackgroundAudioManager::Tickle() { - switch (m_unk0x13c) { + switch (m_tickleState) { case MxPresenter::e_starting: FadeInOrFadeOut(); break; @@ -108,7 +108,7 @@ void MxBackgroundAudioManager::FUN_1007ee70() m_unk0x138 = NULL; m_action2.SetObjectId(-1); m_action2.SetAtomId(MxAtomId()); - m_unk0x13c = 0; + m_tickleState = MxPresenter::e_idle; } } @@ -141,7 +141,7 @@ void MxBackgroundAudioManager::FUN_1007ef40() m_unk0x138 = NULL; m_action2.SetObjectId(-1); m_action2.SetAtomId(MxAtomId()); - m_unk0x13c = 0; + m_tickleState = MxPresenter::e_idle; } } } @@ -187,11 +187,11 @@ void MxBackgroundAudioManager::FadeInOrFadeOut() } else { m_unk0xa0->SetVolume(volume); - m_unk0x13c = 0; + m_tickleState = MxPresenter::e_idle; } } else { - m_unk0x13c = 0; + m_tickleState = MxPresenter::e_idle; } } @@ -238,7 +238,11 @@ void MxBackgroundAudioManager::StopAction(MxParam& p_param) } // FUNCTION: LEGO1 0x1007f2f0 -MxResult MxBackgroundAudioManager::PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, undefined4 p_unk0x13c) +MxResult MxBackgroundAudioManager::PlayMusic( + MxDSAction& p_action, + undefined4 p_unk0x140, + MxPresenter::TickleState p_tickleState +) { if (!m_enabled) { return SUCCESS; @@ -262,7 +266,7 @@ MxResult MxBackgroundAudioManager::PlayMusic(MxDSAction& p_action, undefined4 p_ GetCurrentAction().SetUnknown24(action.GetUnknown24()); if (result == SUCCESS) { - m_unk0x13c = p_unk0x13c; + m_tickleState = p_tickleState; m_unk0x140 = p_unk0x140; } @@ -292,15 +296,15 @@ void MxBackgroundAudioManager::Stop() m_action1.SetAtomId(MxAtomId()); m_unk0x148 = 0; m_action1.SetObjectId(-1); - m_unk0x13c = 0; + m_tickleState = MxPresenter::e_idle; } // FUNCTION: LEGO1 0x1007f570 void MxBackgroundAudioManager::LowerVolume() { if (m_unk0x148 == 0) { - if (m_unk0x13c == 0) { - m_unk0x13c = 2; + if (m_tickleState == 0) { + m_tickleState = MxPresenter::e_starting; } m_unk0x140 = 20; } @@ -313,8 +317,8 @@ void MxBackgroundAudioManager::RaiseVolume() if (m_unk0x148 != 0) { m_unk0x148--; if (m_unk0x148 == 0) { - if (m_unk0x13c == 0) { - m_unk0x13c = 2; + if (m_tickleState == 0) { + m_tickleState = MxPresenter::e_starting; } m_unk0x140 = 10; } @@ -333,9 +337,28 @@ void MxBackgroundAudioManager::Enable(MxBool p_enable) } } +// FUNCTION: LEGO1 0x1007f610 +// FUNCTION: BETA10 0x100e95ee +undefined4 MxBackgroundAudioManager::FUN_1007f610( + MxPresenter* p_unk0x138, + MxS32 p_unk0x140, + MxPresenter::TickleState p_tickleState +) + +{ + m_unk0x138 = (MxAudioPresenter*) p_unk0x138; + m_targetVolume = ((MxDSSound*) m_unk0x138->GetAction())->GetVolume(); + + ((MxCompositePresenter*) m_unk0x138)->VTable0x60(NULL); + + m_unk0x140 = p_unk0x140; + m_tickleState = p_tickleState; + return 0; +} + // FUNCTION: LEGO1 0x1007f650 void MxBackgroundAudioManager::Init() { this->m_unk0xa0 = 0; - this->m_unk0x13c = 0; + this->m_tickleState = MxPresenter::e_idle; } diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 2d6501c7..48e6bb03 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -1,9 +1,14 @@ #include "legocarbuild.h" +#include "dunebuggy.h" +#include "helicopter.h" +#include "jetski.h" +#include "jukebox_actions.h" #include "legocarbuildpresenter.h" #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" +#include "legosoundmanager.h" #include "legoutils.h" #include "misc.h" #include "mxactionnotificationparam.h" @@ -15,8 +20,10 @@ #include "mxstillpresenter.h" #include "mxticklemanager.h" #include "mxtransitionmanager.h" +#include "racecar.h" #include "scripts.h" +#include #include DECOMP_SIZE_ASSERT(LegoCarBuild, 0x34c) @@ -26,7 +33,7 @@ DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50) MxFloat LegoCarBuild::g_unk0x100d65a4 = -0.1f; // GLOBAL: LEGO1 0x100d65a8 -MxFloat LegoCarBuild::g_unk0x100d65a8 = 0.07; +MxFloat LegoCarBuild::g_rotationAngleStepYAxis = 0.07; // GLOBAL: LEGO1 0x100f11cc MxS16 LegoCarBuild::g_unk0x100f11cc = -1; @@ -141,7 +148,7 @@ MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) GameState()->StopArea(LegoGameState::e_previousArea); - m_buildState->m_animationState = 1; + m_buildState->m_animationState = LegoVehicleBuildState::e_entering; m_unk0x100 = 0; BackgroundAudioManager()->Stop(); @@ -153,6 +160,17 @@ MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) return result; } +// FUNCTION: LEGO1 0x10022cd0 +MxS16 LegoCarBuild::GetPlacedPartCount() +{ + if (m_buildState) { + return m_buildState->m_placedPartCount; + } + else { + return 0; + } +} + // FUNCTION: LEGO1 0x10022d10 // FUNCTION: BETA10 0x1006b27a void LegoCarBuild::InitPresenters() @@ -207,7 +225,7 @@ void LegoCarBuild::FUN_10022f30() FUN_10024f70(FALSE); FUN_100250e0(FALSE); - if (m_unk0x258->FUN_10079ca0(m_unk0x110->GetName())) { + if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) { m_PlaceBrick_Sound->Enable(FALSE); m_PlaceBrick_Sound->Enable(TRUE); } @@ -397,7 +415,7 @@ MxResult LegoCarBuild::Tickle() } if (m_unk0x110) { - if (m_unk0x258->FUN_10079ca0(m_unk0x110->GetName())) { + if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) { FUN_10022f30(); } } @@ -537,7 +555,7 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) assert(m_buildState); if (((m_buildState->m_animationState != 4) && (m_buildState->m_animationState != 6)) && (m_buildState->m_animationState != 2)) { - m_buildState->m_animationState = 0; + m_buildState->m_animationState = LegoVehicleBuildState::e_unknown0; result = FUN_100244e0( ((LegoEventNotificationParam&) p_param).GetX(), ((LegoEventNotificationParam&) p_param).GetY() @@ -607,7 +625,7 @@ void LegoCarBuild::ReadyWorld() if (BackgroundAudioManager()->GetEnabled()) { InvokeAction(Extra::ActionType::e_start, *g_jukeboxScript, FUN_10025ee0(m_unk0x330), NULL); - m_buildState->m_animationState = 2; + m_buildState->m_animationState = LegoVehicleBuildState::e_unknown2; NotificationManager()->Send(this, MxNotificationParam()); } else { @@ -652,7 +670,7 @@ undefined4 LegoCarBuild::FUN_10024480(MxActionNotificationParam* p_param) switch (m_buildState->m_animationState) { case 3: BackgroundAudioManager()->RaiseVolume(); - m_buildState->m_animationState = 0; + m_buildState->m_animationState = LegoVehicleBuildState::e_unknown0; result = 1; break; case 6: @@ -686,7 +704,7 @@ undefined4 LegoCarBuild::FUN_100244e0(MxLong p_x, MxLong p_y) FUN_100250e0(TRUE); } - if (m_unk0x100 == 5 && m_unk0x258->FUN_10079ca0(m_unk0x110->GetName())) { + if (m_unk0x100 == 5 && m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) { m_unk0x2d4 = TRUE; } else { @@ -695,7 +713,7 @@ undefined4 LegoCarBuild::FUN_100244e0(MxLong p_x, MxLong p_y) FUN_10025450(); VTable0x70(); - if (m_unk0x258->FUN_10079ca0(m_unk0x110->GetName())) { + if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) { if (m_unk0x100 != 5) { m_unk0x250[0] += m_unk0x290[0] - m_unk0x298[0]; m_unk0x250[1] += m_unk0x290[1] - m_unk0x298[1]; @@ -761,18 +779,115 @@ undefined4 LegoCarBuild::FUN_10024890(LegoEventNotificationParam* p_param) return 0; } -// STUB: LEGO1 0x10024c20 -// STUB: BETA10 0x1006db21 -void LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) +// FUNCTION: LEGO1 0x10024c20 +// FUNCTION: BETA10 0x1006db21 +undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) { - // TODO + LegoEntity* entity; + assert(m_buildState); + + switch (m_buildState->m_animationState) { + case 4: + entity = (LegoEntity*) Find(m_atomId, m_unk0x330); + + if (entity && entity->GetROI()) { + + // This function was changed between BETA10 and LEGO1. + // These lines looks like a relic from older code. + LegoWorld* destWorld = NULL; + destWorld = FindWorld(*g_isleScript, 0); + + Act1State* gameState = (Act1State*) GameState()->GetState("Act1State"); + + switch (GameState()->GetCurrentArea()) { + case LegoGameState::e_copterbuild: + if (gameState->m_helicopter) { + delete gameState->m_helicopter; + } + + gameState->m_helicopter = (Helicopter*) entity; + gameState->m_unk0x108.SetName(""); + break; + case LegoGameState::e_dunecarbuild: + if (gameState->m_dunebuggy) { + delete gameState->m_dunebuggy; + } + + gameState->m_dunebuggy = (DuneBuggy*) entity; + gameState->m_unk0x1bc.SetName(""); + break; + case LegoGameState::e_jetskibuild: + if (gameState->m_jetski) { + delete gameState->m_jetski; + } + + gameState->m_jetski = (Jetski*) entity; + gameState->m_unk0x164.SetName(""); + break; + case LegoGameState::e_racecarbuild: + if (gameState->m_racecar) { + delete gameState->m_racecar; + } + + gameState->m_racecar = (RaceCar*) entity; + gameState->m_unk0x210.SetName(""); + break; + } + + assert(destWorld); + m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; + + if (m_unk0x258->m_numberOfParts != m_unk0x258->m_placedPartCount) { + FUN_100243a0(); + } + else { + FUN_10025720(5); + } + } + else { + MxNotificationParam param; + NotificationManager()->Send(this, param); + } + break; + case 2: + MxU32 jukeboxScript; + + switch (m_unk0x330) { + case 1: + jukeboxScript = JukeboxScript::c_HelicopterBuild_Music; + break; + case 2: + jukeboxScript = JukeboxScript::c_DuneCarBuild_Music; + break; + case 3: + jukeboxScript = JukeboxScript::c_JetskiBuild_Music; + break; + case 4: + jukeboxScript = JukeboxScript::c_RaceCarBuild_Music; + } + + m_unk0x338 = SoundManager()->FUN_100aebd0(*g_jukeboxScript, jukeboxScript); + + if (m_unk0x338) { + BackgroundAudioManager()->FUN_1007f610(m_unk0x338, 5, MxPresenter::e_repeating); + FUN_10024ef0(); + } + else { + MxNotificationParam p; + // In BETA10, NotificationManager->Send() also takes __FILE__ and __LINE__ arguments + NotificationManager()->Send(this, p); + } + break; + } + + return 1; } // FUNCTION: LEGO1 0x10024ef0 void LegoCarBuild::FUN_10024ef0() { FUN_1003eda0(); - m_buildState->m_animationState = 3; + m_buildState->m_animationState = LegoVehicleBuildState::e_cutscene; FUN_10025720(FUN_10025d70()); m_buildState->m_unk0x4c += 1; FUN_10015820(FALSE, 7); @@ -783,14 +898,14 @@ void LegoCarBuild::FUN_10024ef0() void LegoCarBuild::FUN_10024f50() { m_unk0x2d4 = FALSE; - m_unk0x258->FUN_10079920(g_unk0x100d65a8); + m_unk0x258->RotateAroundYAxis(g_rotationAngleStepYAxis); } // FUNCTION: LEGO1 0x10024f70 // FUNCTION: BETA10 0x1006e002 void LegoCarBuild::FUN_10024f70(MxBool p_enabled) { - if (m_unk0x258->FUN_10079cf0(m_unk0x110->GetName())) { + if (m_unk0x258->StringEndsOnY(m_unk0x110->GetName())) { SetPresentersEnabled(p_enabled); } } @@ -821,11 +936,41 @@ void LegoCarBuild::TogglePresentersEnabled() m_Black_Ctl->Enable(!m_Black_Ctl->IsEnabled()); } -// STUB: LEGO1 0x100250e0 -// STUB: BETA10 0x1006e124 +// FUNCTION: LEGO1 0x100250e0 +// FUNCTION: BETA10 0x1006e124 void LegoCarBuild::FUN_100250e0(MxBool p_enabled) { - // TODO + if (m_unk0x258->StringEndsOnZero(m_unk0x110->GetName()) && m_Decals_Ctl) { + if (strnicmp(m_unk0x110->GetName(), "JSFRNT", strlen("JSFRNT")) == 0) { + m_Decal_Bitmap->Enable(p_enabled); + m_Decals_Ctl->Enable(p_enabled); + m_Decals_Ctl1->Enable(p_enabled); + m_Decals_Ctl2->Enable(p_enabled); + m_Decals_Ctl3->Enable(p_enabled); + } + else if (strnicmp(m_unk0x110->GetName(), "JSWNSH", strlen("JSWNSH")) == 0) { + m_Decal_Bitmap->Enable(p_enabled); + m_Decals_Ctl4->Enable(p_enabled); + m_Decals_Ctl5->Enable(p_enabled); + m_Decals_Ctl6->Enable(p_enabled); + m_Decals_Ctl7->Enable(p_enabled); + } + else if (strnicmp(m_unk0x110->GetName(), "RCBACK", strlen("RCBACK")) == 0) { + m_Decals_Ctl1->Enable(p_enabled); + } + else if (strnicmp(m_unk0x110->GetName(), "RCTAIL", strlen("RCTAIL")) == 0) { + m_Decals_Ctl2->Enable(p_enabled); + } + else if (m_Decals_Ctl1 && strnicmp(m_unk0x110->GetName(), "chljety", strlen("chljety")) == 0) { + m_Decals_Ctl1->Enable(p_enabled); + } + else if (m_Decals_Ctl2 && strnicmp(m_unk0x110->GetName(), "chrjety", strlen("chrjety")) == 0) { + m_Decals_Ctl2->Enable(p_enabled); + } + else if (m_Decals_Ctl) { + m_Decals_Ctl->Enable(p_enabled); + } + } } // STUB: LEGO1 0x10025450 @@ -916,7 +1061,7 @@ MxBool LegoCarBuild::Escape() InvokeAction(Extra::ActionType::e_stop, *g_jukeboxScript, targetEntityId, NULL); DeleteObjects(&m_atomId, 500, 999); - m_buildState->m_animationState = 0; + m_buildState->m_animationState = LegoVehicleBuildState::e_unknown0; m_destLocation = LegoGameState::e_infomain; return TRUE; } diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp index 2ed86f7b..28cfbc53 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp @@ -1,7 +1,19 @@ #include "legocarbuildpresenter.h" +#include "3dmanager/lego3dmanager.h" +#include "legocarbuild.h" #include "legoentity.h" +#include "legogamestate.h" +#include "legomain.h" +#include "legoutils.h" +#include "legovideomanager.h" +#include "legoworld.h" +#include "misc.h" #include "mxautolock.h" +#include "mxcompositepresenter.h" +#include "mxmisc.h" +#include "mxtimer.h" +#include "realtime/realtime.h" DECOMP_SIZE_ASSERT(LegoCarBuildAnimPresenter::UnknownListEntry, 0x0c) DECOMP_SIZE_ASSERT(LegoCarBuildAnimPresenter, 0x150) @@ -11,10 +23,10 @@ DECOMP_SIZE_ASSERT(LegoCarBuildAnimPresenter, 0x150) LegoCarBuildAnimPresenter::LegoCarBuildAnimPresenter() { m_unk0xbc = 0; - m_unk0xbe = 0; - m_unk0xc0 = 0; - m_unk0x128 = NULL; - m_unk0xc4 = 0; + m_numberOfParts = 0; + m_placedPartCount = 0; + m_parts = NULL; + m_unk0xc4 = NULL; m_unk0x130 = 0; m_unk0x12c = 0; m_unk0x134 = 0; @@ -23,7 +35,7 @@ LegoCarBuildAnimPresenter::LegoCarBuildAnimPresenter() m_unk0x140 = NULL; m_unk0x144 = -1; m_unk0x148 = -1; - m_unk0x14c = NULL; + m_mainSourceId = NULL; } // FUNCTION: LEGO1 0x10078500 @@ -36,40 +48,238 @@ void LegoCarBuildAnimPresenter::RepeatingTickle() // FUNCTION: BETA10 0x1007091e LegoCarBuildAnimPresenter::~LegoCarBuildAnimPresenter() { - if (m_unk0x128) { - for (MxS16 i = 0; i < m_unk0xbe; i++) { - delete m_unk0x128[i].m_unk0x00; - delete m_unk0x128[i].m_unk0x04; + if (m_parts) { + for (MxS16 i = 0; i < m_numberOfParts; i++) { + delete m_parts[i].m_name; + delete m_parts[i].m_wiredName; } - delete[] m_unk0x128; + delete[] m_parts; } m_unk0xc8.GetRoot()->SetNumChildren(0); *m_unk0xc8.GetRoot()->GetChildren() = NULL; - if (m_unk0x14c) { - delete m_unk0x14c; + if (m_mainSourceId) { + delete[] m_mainSourceId; } } -// STUB: LEGO1 0x10078790 +// FUNCTION: BETA10 0x100733d0 +inline void LegoCarBuildAnimPresenter::Beta10Inline0x100733d0() +{ + MxLong time = Timer()->GetTime(); + MxLong bvar5; + + if (m_unk0x13c < time) { + bvar5 = FALSE; + + // I have no idea why this conditional is so convoluted + if (m_unk0x13c & c_bit1) { + bvar5 = TRUE; + m_unk0x13c = time + 400; + } + else { + m_unk0x13c = time + 200; + } + + if (bvar5) { + m_unk0x13c &= ~c_bit1; + } + else { + m_unk0x13c |= c_bit1; + } + + if (m_placedPartCount < m_numberOfParts) { + + const LegoChar* wiredName = m_parts[m_placedPartCount].m_wiredName; + + if (wiredName) { + for (MxS32 i = 1; i <= m_roiMapSize; i++) { + LegoROI* roi = m_roiMap[i]; + + if (roi) { + const LegoChar* name = roi->GetName(); + + if (name && stricmp(wiredName, name) == 0) { + if (bvar5) { + roi->SetVisibility(TRUE); + } + else { + roi->SetVisibility(FALSE); + } + } + } + } + } + } + } +} + +// FUNCTION: LEGO1 0x10078790 +// FUNCTION: BETA10 0x10070ab1 void LegoCarBuildAnimPresenter::PutFrame() { - // TODO + switch (m_unk0xbc) { + case 0: + break; + case 2: + FUN_10079a90(); + case 1: + if (m_unk0x140->GetROI()) { + FUN_1006b9a0(m_anim, m_unk0x12c, NULL); + } + default: + break; + } + + Beta10Inline0x100733d0(); } -// STUB: LEGO1 0x100788c0 -// STUB: BETA10 0x10070b56 +// FUNCTION: LEGO1 0x100788c0 +// FUNCTION: BETA10 0x10070b56 void LegoCarBuildAnimPresenter::ReadyTickle() { - // TODO + if (!m_anim) { + LegoAnimPresenter::ReadyTickle(); + + if (!m_currentWorld) { + return; + } + +#ifdef NDEBUG + if (!m_anim) { + return; + } +#else + assert(m_anim); +#endif + } + + m_unk0x140 = (LegoEntity*) m_currentWorld->Find("MxEntity", "Dunebld"); + + if (!m_unk0x140) { + m_unk0x140 = (LegoEntity*) m_currentWorld->Find("MxEntity", "Chptrbld"); + } + + if (!m_unk0x140) { + m_unk0x140 = (LegoEntity*) m_currentWorld->Find("MxEntity", "Jetbld"); + } + + if (!m_unk0x140) { + m_unk0x140 = (LegoEntity*) m_currentWorld->Find("MxEntity", "bldrace"); + } + + if (m_unk0x140) { + ((LegoCarBuild*) m_currentWorld)->SetUnknown0x258(this); + m_placedPartCount = ((LegoCarBuild*) m_currentWorld)->GetPlacedPartCount(); + SetUnknown0xbc(1); + m_previousTickleStates |= 1 << m_currentTickleState; + m_currentTickleState = e_starting; + m_compositePresenter->SendToCompositePresenter(Lego()); + } + else { + m_previousTickleStates |= 1 << m_currentTickleState; + m_currentTickleState = e_ready; + } } -// STUB: LEGO1 0x100789e0 -// STUB: BETA10 0x10070cdd +// FUNCTION: LEGO1 0x100789e0 +// FUNCTION: BETA10 0x10070cdd void LegoCarBuildAnimPresenter::StreamingTickle() { - // TODO + if (!m_unk0x140->GetROI()) { + return; + } + + m_mainSourceId = new LegoChar[strlen(m_action->GetAtomId().GetInternal()) + 1]; + assert(m_mainSourceId); + + strcpy(m_mainSourceId, m_action->GetAtomId().GetInternal()); + m_mainSourceId[strlen(m_mainSourceId) - 1] = 'M'; + + FUN_10079160(); + + if (GameState()->GetCurrentAct() == LegoGameState::e_act2) { + m_placedPartCount = 10; + } + + MxS16 i; + + for (i = 0; i < m_numberOfParts; i++) { + if (m_placedPartCount == i) { + FUN_10079680(m_parts[i].m_wiredName); + } + else { + FUN_100795d0(m_parts[i].m_wiredName); + } + + if (i < m_placedPartCount) { + FUN_10079050(i); + FUN_10079680(m_parts[i].m_name); + } + + LegoChar* name = m_parts[i].m_wiredName; + + if (name) { + for (MxS32 j = 0; j <= m_roiMapSize; j++) { + LegoROI* roi = m_roiMap[j]; + + if (roi && roi->GetName() && (strcmpi(name, roi->GetName()) == 0)) { + roi->FUN_100a9dd0(); + roi->FUN_100a9350("lego red"); + } + } + } + } + + LegoVideoManager* videoManager = VideoManager(); + assert(videoManager); // verifies variable name 'videoManager' + + Lego3DView* lego3dview = videoManager->Get3DManager()->GetLego3DView(); + LegoROI* videoManagerROI = videoManager->GetViewROI(); + LegoROI* local60 = m_unk0x140->GetROI(); + LegoROI* camera = NULL; + MxFloat fov; + + MxS16 totalNodes = CountTotalTreeNodes(m_anim->GetRoot()); + + for (i = 0; i < totalNodes; i++) { + LegoAnimNodeData* animNodeData = (LegoAnimNodeData*) GetTreeNode(m_anim->GetRoot(), i)->GetData(); + + if (strnicmp(animNodeData->GetName(), "CAM", strlen("CAM")) == 0) { + camera = local60->FindChildROI(animNodeData->GetName(), local60); + fov = atof(&animNodeData->GetName()[strlen(animNodeData->GetName()) - 2]); + break; + } + } + + assert(camera); // verifies variable name 'camera' + + LegoROI* targetROI = local60->FindChildROI("TARGET", local60); + + Mx3DPointFloat dirVec; + + Vector3 cameraPosition(camera->GetWorldPosition()); + Vector3 upVec(camera->GetWorldUp()); + Vector3 targetPosition(targetROI->GetWorldPosition()); + + MxMatrix localTransform; + + dirVec[0] = targetPosition[0] - cameraPosition[0]; + dirVec[1] = targetPosition[1] - cameraPosition[1]; + dirVec[2] = targetPosition[2] - cameraPosition[2]; + dirVec.Unitize(); + + CalcLocalTransform(cameraPosition, dirVec, upVec, localTransform); + + videoManagerROI->WrappedSetLocalTransform(localTransform); + lego3dview->Moved(*videoManagerROI); + videoManager->Get3DManager()->SetFrustrum(fov, 0.1, 250.0); + + m_unk0xe0 = local60->FindChildROI("VIEW", local60)->GetLocal2World(); + + m_previousTickleStates |= 1 << m_currentTickleState; + m_currentTickleState = e_repeating; } // FUNCTION: LEGO1 0x10078db0 @@ -83,11 +293,284 @@ void LegoCarBuildAnimPresenter::EndAction() } } -// STUB: LEGO1 0x10079920 -// STUB: BETA10 0x1007225d -void LegoCarBuildAnimPresenter::FUN_10079920(float p_param1) +// FUNCTION: LEGO1 0x10079050 +// FUNCTION: BETA10 0x1007151e +void LegoCarBuildAnimPresenter::FUN_10079050(MxS16 p_index) { - // TODO + SwapNodesByName(m_parts[p_index].m_wiredName, m_parts[p_index].m_name); + FUN_100795d0(m_parts[p_index].m_wiredName); +} + +// FUNCTION: LEGO1 0x10079090 +// FUNCTION: BETA10 0x10071584 +void LegoCarBuildAnimPresenter::SwapNodesByName(LegoChar* p_name1, LegoChar* p_name2) +{ + char buffer[40]; + + if (stricmp(p_name1, p_name2) != 0) { + LegoAnimNodeData* node1 = FindNodeDataByName(m_anim->GetRoot(), p_name1); + LegoAnimNodeData* node2 = FindNodeDataByName(m_anim->GetRoot(), p_name2); + + strcpy(buffer, node1->GetName()); + strcpy(node1->GetName(), node2->GetName()); + strcpy(node2->GetName(), buffer); + + LegoU16 val1 = node1->GetUnknown0x20(); + node1->SetUnknown0x20(node2->GetUnknown0x20()); + node2->SetUnknown0x20(val1); + } +} + +// FUNCTION: LEGO1 0x10079160 +// FUNCTION: BETA10 0x1007165d +void LegoCarBuildAnimPresenter::FUN_10079160() +{ + LegoTreeNode* root; + LegoAnimNodeData* data2; + MxS16 i; + MxS16 totalNodes = CountTotalTreeNodes(m_anim->GetRoot()); + LegoChar* name; + LegoTreeNode* destNode; + LegoAnimNodeData* destData; + LegoTreeNode** children; + + for (i = 0; i < totalNodes; i++) { + LegoAnimNodeData* data = (LegoAnimNodeData*) GetTreeNode(m_anim->GetRoot(), i)->GetData(); + name = data->GetName(); + + if (StringEqualsPlatform(name)) { + m_unk0xc4 = data; + if (m_unk0xc4->GetNumRotationKeys() == 0) { + LegoRotationKey* key = new LegoRotationKey(); + m_unk0xc4->SetNumRotationKeys(1); + m_unk0xc4->SetRotationKeys(key); + } + } + else { + if (StringEndsOnYOrN(name)) { + m_numberOfParts++; + } + else { + if (m_unk0x134 == 0.0f && StringEqualsShelf(name)) { + m_unk0x134 = m_anim->GetDuration(); + m_unk0x138 = m_unk0x134 / (data->GetNumTranslationKeys() - 1); + } + } + } + } + + assert(m_numberOfParts); + m_parts = new UnknownListEntry[m_numberOfParts]; + assert(m_parts); + + for (i = 0; i < totalNodes; i++) { + name = ((LegoAnimNodeData*) GetTreeNode(m_anim->GetRoot(), i)->GetData())->GetName(); + + strupr(name); + + if (StringEndsOnW(name)) { + m_parts[name[strlen(name) - 1] - 'A'].m_wiredName = new LegoChar[strlen(name) + 1]; + + // clang-format off + assert(m_parts[name[strlen(name)-1] - 'A'].m_wiredName); + // clang-format on + + strcpy(m_parts[name[strlen(name) - 1] - 'A'].m_wiredName, name); + } + } + + MxS16 counter = 0; + + for (i = 0; i < totalNodes; i++) { + name = ((LegoAnimNodeData*) GetTreeNode(m_anim->GetRoot(), i)->GetData())->GetName(); + if (StringEndsOnYOrN(name)) { + for (MxS16 ii = 0; ii < m_numberOfParts; ii++) { + if (strnicmp(m_parts[ii].m_wiredName, name, strlen(name) - 2) == 0) { + m_parts[ii].m_name = new LegoChar[strlen(name) + 1]; + assert(m_parts[ii].m_name); + strcpy(m_parts[ii].m_name, name); + + counter++; + if (m_numberOfParts == counter) { + break; + } + } + } + } + } + + destNode = new LegoTreeNode(); + assert(destNode); + destData = new LegoAnimNodeData(); + assert(destData); + destNode->SetData(destData); + + root = m_anim->GetRoot(); + data2 = (LegoAnimNodeData*) root->GetData(); + destData->FUN_100a0360(data2->GetName()); + + destNode->SetNumChildren(1); + children = new LegoTreeNode*; + assert(children); + *children = FindNodeByName(m_anim->GetRoot(), "PLATFORM"); + + destNode->SetChildren(children); + m_unk0xc8.SetRoot(destNode); +} + +// FUNCTION: LEGO1 0x100795d0 +// FUNCTION: BETA10 0x10071d96 +void LegoCarBuildAnimPresenter::FUN_100795d0(LegoChar* p_param) +{ + LegoAnimNodeData* data = FindNodeDataByName(m_anim->GetRoot(), p_param); + + if (data) { + LegoMorphKey* oldMorphKeys = data->GetMorphKeys(); + + LegoMorphKey* newHideKey = new LegoMorphKey(); + assert(newHideKey); + + newHideKey->SetTime(0); + newHideKey->SetUnknown0x08(FALSE); + + data->SetNumMorphKeys(1); + data->SetMorphKeys(newHideKey); + + delete oldMorphKeys; + } +} + +// FUNCTION: LEGO1 0x10079680 +// FUNCTION: BETA10 0x10071ec5 +void LegoCarBuildAnimPresenter::FUN_10079680(LegoChar* p_param) +{ + LegoAnimNodeData* data = FindNodeDataByName(m_anim->GetRoot(), p_param); + + if (data) { + LegoMorphKey* oldMorphKeys = data->GetMorphKeys(); + + data->SetNumMorphKeys(0); + data->SetMorphKeys(NULL); + + delete oldMorphKeys; + } +} + +// FUNCTION: LEGO1 0x100796b0 +// FUNCTION: BETA10 0x10071f3c +LegoAnimNodeData* LegoCarBuildAnimPresenter::FindNodeDataByName(LegoTreeNode* p_treeNode, const LegoChar* p_name) +{ + LegoAnimNodeData* data = NULL; + + if (p_treeNode) { + data = (LegoAnimNodeData*) p_treeNode->GetData(); + + if (stricmp(data->GetName(), p_name) == 0) { + return data; + } + + for (MxS32 i = 0; i < p_treeNode->GetNumChildren(); i++) { + data = FindNodeDataByName(p_treeNode->GetChildren()[i], p_name); + + if (data) { + return data; + } + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x10079720 +// FUNCTION: BETA10 0x10071fec +LegoTreeNode* LegoCarBuildAnimPresenter::FindNodeByName(LegoTreeNode* p_treeNode, const LegoChar* p_name) +{ + LegoAnimNodeData* data = NULL; + LegoTreeNode* node = NULL; + + if (p_treeNode) { + data = (LegoAnimNodeData*) p_treeNode->GetData(); + + if (stricmp(data->GetName(), p_name) == 0) { + return p_treeNode; + } + + for (MxS32 i = 0; i < p_treeNode->GetNumChildren(); i++) { + node = FindNodeByName(p_treeNode->GetChildren()[i], p_name); + + if (node) { + return node; + } + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x10079920 +// FUNCTION: BETA10 0x1007225d +void LegoCarBuildAnimPresenter::RotateAroundYAxis(MxFloat p_angle) +{ + if (m_unk0xc4) { + LegoRotationKey* rotationKey = m_unk0xc4->GetRotationKey(0); + + Mx4DPointFloat + currentRotation(rotationKey->GetX(), rotationKey->GetY(), rotationKey->GetZ(), rotationKey->GetAngle()); + Mx4DPointFloat additionalRotation(0.0f, 1.0f, 0.0f, -p_angle); + Mx4DPointFloat newRotation; + + additionalRotation.NormalizeQuaternion(); + newRotation.EqualsHamiltonProduct(¤tRotation, &additionalRotation); + + if (newRotation[3] < 0.9999) { + rotationKey->FUN_100739a0(TRUE); + } + else { + rotationKey->FUN_100739a0(FALSE); + } + + m_unk0xc4->GetRotationKey(0)->SetX(newRotation[0]); + m_unk0xc4->GetRotationKey(0)->SetY(newRotation[1]); + m_unk0xc4->GetRotationKey(0)->SetZ(newRotation[2]); + m_unk0xc4->GetRotationKey(0)->SetAngle(newRotation[3]); + + if (m_unk0x140->GetROI()) { + FUN_1006b9a0(&m_unk0xc8, m_unk0x12c, NULL); + } + } +} + +// FUNCTION: LEGO1 0x10079a90 +// FUNCTION: BETA10 0x10072412 +void LegoCarBuildAnimPresenter::FUN_10079a90() +{ + if (m_unk0x12c >= m_unk0x134) { + m_unk0x130 = 0.0; + m_unk0x12c = m_unk0x130; + m_unk0xbc = 1; + } + else if (m_unk0x12c >= m_unk0x138 + m_unk0x130) { + m_unk0x130 = m_unk0x138 + m_unk0x130; + m_unk0x12c = m_unk0x130; + m_unk0xbc = 1; + } + else { + m_unk0x12c = m_unk0x138 / 10.0f + m_unk0x12c; + } +} + +// FUNCTION: LEGO1 0x10079b20 +// FUNCTION: BETA10 0x100724fa +MxBool LegoCarBuildAnimPresenter::StringEqualsPlatform(const LegoChar* p_string) +{ + return stricmp(p_string, "PLATFORM") == 0; +} + +// FUNCTION: LEGO1 0x10079b40 +// FUNCTION: BETA10 0x10072534 +MxBool LegoCarBuildAnimPresenter::StringEndsOnW(LegoChar* p_param) +{ + return (p_param[strlen(p_param) - 2] == 'W') || (p_param[strlen(p_param) - 2] == 'w'); } // FUNCTION: LEGO1 0x10079b80 @@ -98,20 +581,31 @@ MxBool LegoCarBuildAnimPresenter::StringEndsOnYOrN(const LegoChar* p_string) (p_string[strlen(p_string) - 2] == 'Y') || (p_string[strlen(p_string) - 2] == 'y'); } -// STUB: LEGO1 0x10079c30 -// STUB: BETA10 0x100726a6 +// FUNCTION: LEGO1 0x10079bf0 +// FUNCTION: BETA10 0x10072624 +MxBool LegoCarBuildAnimPresenter::StringEqualsShelf(const LegoChar* p_string) +{ + return strnicmp(p_string, "SHELF", strlen("SHELF")) == 0; +} + +// FUNCTION: LEGO1 0x10079c30 +// FUNCTION: BETA10 0x100726a6 MxBool LegoCarBuildAnimPresenter::FUN_10079c30(const LegoChar* p_name) { - // TODO - return FALSE; + if (PartIsPlaced(p_name)) { + return FALSE; + } + + return m_placedPartCount < m_numberOfParts && + strnicmp(p_name, m_parts[m_placedPartCount].m_name, strlen(p_name) - 3) == 0; } // FUNCTION: LEGO1 0x10079ca0 // FUNCTION: BETA10 0x10072740 -MxBool LegoCarBuildAnimPresenter::FUN_10079ca0(const LegoChar* p_name) +MxBool LegoCarBuildAnimPresenter::PartIsPlaced(const LegoChar* p_name) { - for (MxS16 i = 0; i < m_unk0xc0; i++) { - if (strcmpi(p_name, m_unk0x128[i].m_unk0x00) == 0) { + for (MxS16 i = 0; i < m_placedPartCount; i++) { + if (strcmpi(p_name, m_parts[i].m_name) == 0) { return TRUE; } } @@ -121,15 +615,22 @@ MxBool LegoCarBuildAnimPresenter::FUN_10079ca0(const LegoChar* p_name) // FUNCTION: LEGO1 0x10079cf0 // FUNCTION: BETA10 0x100727b3 -MxBool LegoCarBuildAnimPresenter::FUN_10079cf0(const LegoChar* p_string) +MxBool LegoCarBuildAnimPresenter::StringEndsOnY(const LegoChar* p_string) { return (p_string[strlen(p_string) - 2] == 'Y') || (p_string[strlen(p_string) - 2] == 'y'); } +// FUNCTION: LEGO1 0x10079d30 +// FUNCTION: BETA10 0x1007280e +MxBool LegoCarBuildAnimPresenter::StringEndsOnZero(const LegoChar* p_string) +{ + return (p_string[strlen(p_string) - 2] != '0'); +} + // FUNCTION: LEGO1 0x10079e20 // FUNCTION: BETA10 0x10072959 const BoundingSphere& LegoCarBuildAnimPresenter::FUN_10079e20() { LegoROI* roi = m_unk0x140->GetROI(); - return roi->FindChildROI(m_unk0x128[m_unk0xc0].m_unk0x04, roi)->GetWorldBoundingSphere(); + return roi->FindChildROI(m_parts[m_placedPartCount].m_wiredName, roi)->GetWorldBoundingSphere(); } diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index 870e2d7c..73ffec1a 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -107,6 +107,7 @@ MxBool TransformWorldToScreen(const MxFloat p_world[3], MxFloat p_screen[4]) } // FUNCTION: LEGO1 0x1003df90 +// FUNCTION: BETA10 0x100d39a3 MxS16 CountTotalTreeNodes(LegoTreeNode* p_node) { MxS16 result = 1; @@ -119,6 +120,7 @@ MxS16 CountTotalTreeNodes(LegoTreeNode* p_node) } // FUNCTION: LEGO1 0x1003dfd0 +// FUNCTION: BETA10 0x100d3a09 LegoTreeNode* GetTreeNode(LegoTreeNode* p_node, MxU32 p_index) { LegoTreeNode* result = NULL; diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index dee4ac0e..f9c78e5d 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -53,8 +53,10 @@ LegoControlManager* ControlManager() } // FUNCTION: LEGO1 0x10015760 +// FUNCTION: BETA10 0x100e492a LegoGameState* GameState() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetGameState(); } @@ -166,8 +168,10 @@ void DeleteAction() } // FUNCTION: LEGO1 0x100158c0 +// FUNCTION: BETA10 0x100e4e18 LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid) { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->FindWorld(p_atom, p_entityid); } @@ -196,7 +200,7 @@ void PlayMusic(JukeboxScript::Script p_script) action.SetAtomId(*g_jukeboxScript); action.SetObjectId(p_script); - LegoOmni::GetInstance()->GetBackgroundAudioManager()->PlayMusic(action, 5, 4); + LegoOmni::GetInstance()->GetBackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); } // FUNCTION: LEGO1 0x100159c0 diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index f59c83a9..81cb3fe3 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -213,6 +213,7 @@ Mx3DPointFloat LegoEntity::GetWorldUp() } // FUNCTION: LEGO1 0x10010d80 +// FUNCTION: BETA10 0x1007ebbe Mx3DPointFloat LegoEntity::GetWorldPosition() { if (m_roi != NULL) { diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index eafc5e1e..822121e6 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -380,6 +380,7 @@ void LegoWorld::AddPath(LegoPathController* p_controller) } // FUNCTION: LEGO1 0x10020020 +// FUNCTION: BETA10 0x100da77c LegoPathBoundary* LegoWorld::FindPathBoundary(const char* p_name) { LegoPathControllerListCursor cursor(&m_list0x68); diff --git a/LEGO1/lego/legoomni/src/main/legomain.cpp b/LEGO1/lego/legoomni/src/main/legomain.cpp index 6db16c66..ab697a97 100644 --- a/LEGO1/lego/legoomni/src/main/legomain.cpp +++ b/LEGO1/lego/legoomni/src/main/legomain.cpp @@ -357,6 +357,7 @@ void LegoOmni::RemoveWorld(const MxAtomId& p_atom, MxLong p_objectId) } // FUNCTION: LEGO1 0x1005b0c0 +// FUNCTION: BETA10 0x1008e827 LegoWorld* LegoOmni::FindWorld(const MxAtomId& p_atom, MxS32 p_entityid) { if (m_worldList) { diff --git a/LEGO1/lego/legoomni/src/main/scripts.cpp b/LEGO1/lego/legoomni/src/main/scripts.cpp index 32c3f86e..b5d7fe54 100644 --- a/LEGO1/lego/legoomni/src/main/scripts.cpp +++ b/LEGO1/lego/legoomni/src/main/scripts.cpp @@ -27,6 +27,7 @@ MxAtomId* g_jetraceScript = NULL; MxAtomId* g_jetracerScript = NULL; // GLOBAL: LEGO1 0x100f453c +// GLOBAL: BETA10 0x10211534 MxAtomId* g_isleScript = NULL; // GLOBAL: LEGO1 0x100f4540 diff --git a/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp b/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp index 1a39478e..970402c8 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp @@ -161,6 +161,6 @@ void LegoPathStruct::PlayMusic(MxBool p_direction, MxU32 p_data) } if (action.GetObjectId() != -1) { - BackgroundAudioManager()->PlayMusic(action, 5, 4); + BackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); } } diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 4537418a..7b08d2f8 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -750,6 +750,7 @@ MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi) } // FUNCTION: LEGO1 0x1006b550 +// FUNCTION: BETA10 0x10050a9c void LegoAnimPresenter::ReadyTickle() { m_currentWorld = CurrentWorld(); @@ -789,9 +790,9 @@ void LegoAnimPresenter::StartingTickle() FUN_1006c8a0(TRUE); if (m_unk0x78 == NULL) { - if (fabs(m_action->GetDirection().GetX()) >= 0.00000047683716F || - fabs(m_action->GetDirection().GetY()) >= 0.00000047683716F || - fabs(m_action->GetDirection().GetZ()) >= 0.00000047683716F) { + if (fabs(m_action->GetDirection()[0]) >= 0.00000047683716F || + fabs(m_action->GetDirection()[1]) >= 0.00000047683716F || + fabs(m_action->GetDirection()[2]) >= 0.00000047683716F) { m_unk0x78 = new MxMatrix(); CalcLocalTransform(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), *m_unk0x78); } @@ -903,6 +904,7 @@ void LegoAnimPresenter::FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p } // FUNCTION: LEGO1 0x1006b9a0 +// FUNCTION: BETA10 0x1005118b void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix) { LegoTreeNode* root = p_anim->GetRoot(); diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index d6100be7..a495f528 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -50,6 +50,7 @@ void LegoModelPresenter::Destroy(MxBool p_fromDestructor) } // FUNCTION: LEGO1 0x1007f6b0 +// FUNCTION: BETA10 0x1009845e MxResult LegoModelPresenter::CreateROI(MxDSChunk* p_chunk) { MxResult result = FAILURE; @@ -171,13 +172,9 @@ MxResult LegoModelPresenter::CreateROI(MxDSChunk* p_chunk) // Get scripted location, direction and up vectors CalcLocalTransform( - Mx3DPointFloat(m_action->GetLocation().GetX(), m_action->GetLocation().GetY(), m_action->GetLocation().GetZ()), - Mx3DPointFloat( - m_action->GetDirection().GetX(), - m_action->GetDirection().GetY(), - m_action->GetDirection().GetZ() - ), - Mx3DPointFloat(m_action->GetUp().GetX(), m_action->GetUp().GetY(), m_action->GetUp().GetZ()), + Mx3DPointFloat(m_action->GetLocation()[0], m_action->GetLocation()[1], m_action->GetLocation()[2]), + Mx3DPointFloat(m_action->GetDirection()[0], m_action->GetDirection()[1], m_action->GetDirection()[2]), + Mx3DPointFloat(m_action->GetUp()[0], m_action->GetUp()[1], m_action->GetUp()[2]), mat ); m_roi->UpdateTransformationRelativeToParent(mat); @@ -234,6 +231,7 @@ MxResult LegoModelPresenter::FUN_1007ff70( } // FUNCTION: LEGO1 0x10080050 +// FUNCTION: BETA10 0x100991c2 void LegoModelPresenter::ReadyTickle() { if (m_compositePresenter != NULL && m_compositePresenter->IsA("LegoEntityPresenter") && diff --git a/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp b/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp index 1781870a..750f54c6 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp +++ b/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp @@ -97,6 +97,7 @@ double Lego3DManager::Render(double p_und) } // FUNCTION: LEGO1 0x100ab4d0 +// FUNCTION: BETA10 0x1017baeb int Lego3DManager::SetFrustrum(float p_fov, float p_front, float p_back) { m_pLego3DView->GetView()->SetFrustrum(p_front, p_back, p_fov); diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.cpp b/LEGO1/lego/sources/3dmanager/lego3dview.cpp index e895e378..4f69fa40 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dview.cpp +++ b/LEGO1/lego/sources/3dmanager/lego3dview.cpp @@ -119,6 +119,7 @@ BOOL Lego3DView::SetPointOfView(ViewROI& rROI) } // FUNCTION: LEGO1 0x100ab210 +// FUNCTION: BETA10 0x1017d230 BOOL Lego3DView::Moved(ViewROI& rROI) { assert(m_pViewManager); diff --git a/LEGO1/lego/sources/anim/legoanim.cpp b/LEGO1/lego/sources/anim/legoanim.cpp index 77801f61..9b5e560a 100644 --- a/LEGO1/lego/sources/anim/legoanim.cpp +++ b/LEGO1/lego/sources/anim/legoanim.cpp @@ -221,10 +221,11 @@ LegoResult LegoAnimScene::FUN_1009f490(LegoFloat p_time, Matrix4& p_matrix) } // FUNCTION: LEGO1 0x1009f900 +// FUNCTION: BETA10 0x1017df90 LegoAnimKey::LegoAnimKey() { - m_flags = 0; m_time = 0; + m_flags = 0; } // FUNCTION: LEGO1 0x1009f910 @@ -279,6 +280,7 @@ LegoResult LegoTranslationKey::Read(LegoStorage* p_storage) } // FUNCTION: LEGO1 0x1009faa0 +// FUNCTION: BETA10 0x1017e2b3 LegoRotationKey::LegoRotationKey() { m_angle = 1.0F; @@ -356,6 +358,7 @@ LegoResult LegoScaleKey::Read(LegoStorage* p_storage) } // FUNCTION: LEGO1 0x1009fcf0 +// FUNCTION: BETA10 0x1017e71a LegoAnimNodeData::LegoAnimNodeData() { m_numTranslationKeys = 0; @@ -494,6 +497,13 @@ LegoResult LegoAnimNodeData::Write(LegoStorage* p_storage) return SUCCESS; } +// STUB: LEGO1 0x100a0360 +// STUB: BETA10 0x1017f1e5 +void LegoAnimNodeData::FUN_100a0360(LegoChar* p_param) +{ + // TODO +} + // FUNCTION: LEGO1 0x100a03c0 LegoResult LegoAnimNodeData::CreateLocalTransform(LegoFloat p_time, Matrix4& p_matrix) { @@ -898,6 +908,7 @@ undefined4 LegoAnim::GetActorUnknown0x04(LegoU32 p_index) } // FUNCTION: LEGO1 0x100a0f60 +// FUNCTION: BETA10 0x1018027c LegoMorphKey::LegoMorphKey() { m_unk0x08 = 0; diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h index 1a861eb6..5da5ffd6 100644 --- a/LEGO1/lego/sources/anim/legoanim.h +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -19,11 +19,26 @@ class LegoAnimKey { LegoAnimKey(); LegoResult Read(LegoStorage* p_storage); LegoFloat GetTime() { return m_time; } - void SetTime(LegoFloat p_time) { m_time = p_time; } + + // The different types (LegoFloat vs. MxS32) are correct according to BETA10 + // FUNCTION: BETA10 0x100738a0 + void SetTime(MxS32 p_time) { m_time = p_time; } + LegoU32 TestBit1() { return m_flags & c_bit1; } LegoU32 TestBit2() { return m_flags & c_bit2; } LegoU32 TestBit3() { return m_flags & c_bit3; } + // FUNCTION: BETA10 0x100739a0 + void FUN_100739a0(MxS32 p_param) + { + if (p_param) { + m_flags |= c_bit1; + } + else { + m_flags &= ~c_bit1; + } + } + protected: LegoU8 m_flags; // 0x00 LegoFloat m_time; // 0x04 @@ -52,13 +67,29 @@ class LegoRotationKey : public LegoAnimKey { public: LegoRotationKey(); LegoResult Read(LegoStorage* p_storage); + + // FUNCTION: BETA10 0x10073a00 LegoFloat GetAngle() { return m_angle; } + + // FUNCTION: BETA10 0x10073a30 void SetAngle(LegoFloat p_angle) { m_angle = p_angle; } + + // FUNCTION: BETA10 0x10073a60 LegoFloat GetX() { return m_x; } + + // FUNCTION: BETA10 0x10073a90 void SetX(LegoFloat p_x) { m_x = p_x; } + + // FUNCTION: BETA10 0x10073ac0 LegoFloat GetY() { return m_y; } + + // FUNCTION: BETA10 0x10073af0 void SetY(LegoFloat p_y) { m_y = p_y; } + + // FUNCTION: BETA10 0x10073b20 LegoFloat GetZ() { return m_z; } + + // FUNCTION: BETA10 0x10073b50 void SetZ(LegoFloat p_z) { m_z = p_z; } protected: @@ -93,6 +124,9 @@ class LegoMorphKey : public LegoAnimKey { LegoResult Read(LegoStorage* p_storage); LegoBool GetUnknown0x08() { return m_unk0x08; } + // FUNCTION: BETA10 0x100738d0 + void SetUnknown0x08(LegoBool p_unk0x08) { m_unk0x08 = p_unk0x08; } + protected: LegoBool m_unk0x08; // 0x08 }; @@ -118,22 +152,64 @@ class LegoAnimNodeData : public LegoTreeNodeData { LegoResult Read(LegoStorage* p_storage) override; // vtable+0x04 LegoResult Write(LegoStorage* p_storage) override; // vtable+0x08 + void FUN_100a0360(LegoChar* p_param); LegoResult CreateLocalTransform(LegoFloat p_time, Matrix4& p_matrix); LegoBool FUN_100a0990(LegoFloat p_time); - const LegoChar* GetName() { return m_name; } + // FUNCTION: BETA10 0x100595d0 + LegoChar* GetName() { return m_name; } + + // FUNCTION: BETA10 0x10073780 + LegoU16 GetNumTranslationKeys() { return m_numTranslationKeys; } + + // FUNCTION: BETA10 0x100737b0 + LegoU16 GetNumRotationKeys() { return m_numRotationKeys; } + + // FUNCTION: BETA10 0x100737e0 + void SetNumRotationKeys(LegoU16 p_numRotationKeys) { m_numRotationKeys = p_numRotationKeys; } + + // FUNCTION: BETA10 0x10073810 + void SetRotationKeys(LegoRotationKey* p_keys) + { + m_rotationKeys = p_keys; + m_rotationIndex = 0; + } + LegoU32 GetTranslationIndex() { return m_translationIndex; } LegoU32 GetRotationIndex() { return m_rotationIndex; } LegoU32 GetScaleIndex() { return m_scaleIndex; } LegoU32 GetMorphIndex() { return m_morphIndex; } + + // FUNCTION: BETA10 0x1005abc0 LegoU16 GetUnknown0x20() { return m_unk0x20; } + LegoU16 GetUnknown0x22() { return m_unk0x22; } + // FUNCTION: BETA10 0x10073b80 + LegoRotationKey* GetRotationKey(MxS32 index) { return &m_rotationKeys[index]; } + void SetTranslationIndex(LegoU32 p_translationIndex) { m_translationIndex = p_translationIndex; } void SetRotationIndex(LegoU32 p_rotationIndex) { m_rotationIndex = p_rotationIndex; } void SetScaleIndex(LegoU32 p_scaleIndex) { m_scaleIndex = p_scaleIndex; } void SetMorphIndex(LegoU32 p_morphIndex) { m_morphIndex = p_morphIndex; } + + // FUNCTION: BETA10 0x10073930 + LegoMorphKey* GetMorphKeys() { return m_morphKeys; } + + // FUNCTION: BETA10 0x10073960 + void SetMorphKeys(LegoMorphKey* p_morphKeys) + { + m_morphKeys = p_morphKeys; + m_morphIndex = 0; + } + + // FUNCTION: BETA10 0x10073900 + void SetNumMorphKeys(LegoU16 p_numMorphKeys) { m_numMorphKeys = p_numMorphKeys; } + + // FUNCTION: BETA10 0x10059600 void SetUnknown0x20(LegoU16 p_unk0x20) { m_unk0x20 = p_unk0x20; } + + // FUNCTION: BETA10 0x1005f2e0 void SetUnknown0x22(LegoU16 p_unk0x22) { m_unk0x22 = p_unk0x22; } LegoResult CreateLocalTransform(LegoTime p_time, Matrix4& p_matrix) diff --git a/LEGO1/lego/sources/geom/legounkown100db7f4.h b/LEGO1/lego/sources/geom/legounkown100db7f4.h index 68f4c9f2..ae877b58 100644 --- a/LEGO1/lego/sources/geom/legounkown100db7f4.h +++ b/LEGO1/lego/sources/geom/legounkown100db7f4.h @@ -25,9 +25,9 @@ struct LegoUnknown100db7f4 : public LegoEdge { LegoResult FUN_1002ddc0(LegoWEEdge& p_f, Vector3& p_point) { if (p_f.IsEqual(*m_faceA)) { - p_point[0] = -m_unk0x28[0]; - p_point[1] = -m_unk0x28[1]; - p_point[2] = -m_unk0x28[2]; + p_point[0] = -m_unk0x28.index_operator(0); + p_point[1] = -m_unk0x28.index_operator(1); + p_point[2] = -m_unk0x28.index_operator(2); } else { // clang-format off diff --git a/LEGO1/lego/sources/misc/legotree.cpp b/LEGO1/lego/sources/misc/legotree.cpp index e7f24513..f9fb626a 100644 --- a/LEGO1/lego/sources/misc/legotree.cpp +++ b/LEGO1/lego/sources/misc/legotree.cpp @@ -8,6 +8,7 @@ DECOMP_SIZE_ASSERT(LegoTreeNode, 0x010) DECOMP_SIZE_ASSERT(LegoTree, 0x08) // FUNCTION: LEGO1 0x10099d60 +// FUNCTION: BETA10 0x10187dd0 LegoTreeNode::LegoTreeNode() { m_data = NULL; @@ -16,6 +17,7 @@ LegoTreeNode::LegoTreeNode() } // FUNCTION: LEGO1 0x10099da0 +// FUNCTION: BETA10 0x10187e10 LegoTreeNode::~LegoTreeNode() { if (m_data) { diff --git a/LEGO1/lego/sources/misc/legotree.h b/LEGO1/lego/sources/misc/legotree.h index fb97a612..9a4eeb3e 100644 --- a/LEGO1/lego/sources/misc/legotree.h +++ b/LEGO1/lego/sources/misc/legotree.h @@ -13,6 +13,7 @@ class LegoStorage; class LegoTreeNodeData { public: LegoTreeNodeData() {} + // FUNCTION: LEGO1 0x1009a0e0 virtual ~LegoTreeNodeData() {} @@ -27,27 +28,38 @@ class LegoTreeNodeData { }; // VTABLE: LEGO1 0x100db764 +// VTABLE: BETA10 0x101c37f4 // SIZE 0x10 class LegoTreeNode { public: LegoTreeNode(); virtual ~LegoTreeNode(); + + // FUNCTION: BETA10 0x100595a0 LegoTreeNodeData* GetData() { return m_data; } + + // FUNCTION: BETA10 0x100736f0 void SetData(LegoTreeNodeData* p_data) { m_data = p_data; } + + // FUNCTION: BETA10 0x10012150 LegoU32 GetNumChildren() { return m_numChildren; } // FUNCTION: BETA10 0x10073370 void SetNumChildren(LegoU32 p_numChildren) { m_numChildren = p_numChildren; } + // FUNCTION: BETA10 0x10012180 LegoTreeNode* GetChild(LegoU32 p_i) { return m_children[p_i]; } + void SetChild(LegoU32 p_i, LegoTreeNode* p_child) { m_children[p_i] = p_child; } // FUNCTION: BETA10 0x100733a0 LegoTreeNode** GetChildren() { return m_children; } + // FUNCTION: BETA10 0x10073720 void SetChildren(LegoTreeNode** p_children) { m_children = p_children; } // SYNTHETIC: LEGO1 0x10099d80 + // SYNTHETIC: BETA10 0x10188cb0 // LegoTreeNode::`scalar deleting destructor' protected: @@ -66,7 +78,9 @@ class LegoTree { // FUNCTION: BETA10 0x100121b0 LegoTreeNode* GetRoot() { return m_root; } + // FUNCTION: BETA10 0x10073750 void SetRoot(LegoTreeNode* p_root) { m_root = p_root; } + virtual LegoResult Read(LegoStorage* p_storage); // vtable+0x04 virtual LegoResult Write(LegoStorage* p_storage); // vtable+0x08 diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index a11436f3..94fed7c6 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -341,6 +341,7 @@ LegoResult LegoROI::FUN_100a8cb0(LegoAnimNodeData* p_data, LegoTime p_time, Matr } // FUNCTION: LEGO1 0x100a8ce0 +// FUNCTION: BETA10 0x1018a815 LegoROI* LegoROI::FindChildROI(const LegoChar* p_name, LegoROI* p_roi) { CompoundObject::iterator it; @@ -551,6 +552,18 @@ LegoResult LegoROI::GetTexture(LegoTextureInfo*& p_textureInfo) return FAILURE; } +// FUNCTION: LEGO1 0x100a9350 +// FUNCTION: BETA10 0x1018b25c +LegoResult LegoROI::FUN_100a9350(const LegoChar* p_color) +{ + MxFloat red, green, blue, alpha; + if (ColorAliasLookup(p_color, red, green, blue, alpha)) { + return FUN_100a9170(red, green, blue, alpha); + } + + return SUCCESS; +} + // FUNCTION: LEGO1 0x100a9410 // FUNCTION: BETA10 0x1018b324 LegoU32 LegoROI::FUN_100a9410( @@ -778,6 +791,13 @@ void LegoROI::SetName(const LegoChar* p_name) } } +// STUB: LEGO1 0x100a9dd0 +// STUB: BETA10 0x1018bfdb +void LegoROI::FUN_100a9dd0() +{ + // TODO +} + // FUNCTION: LEGO1 0x100a9e10 void LegoROI::SetDisplayBB(int p_displayBB) { diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index fb96b2a5..babb566a 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -38,12 +38,14 @@ class LegoROI : public ViewROI { LegoResult FUN_100a9170(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult FUN_100a9210(LegoTextureInfo* p_textureInfo); LegoResult GetTexture(LegoTextureInfo*& p_textureInfo); + LegoResult FUN_100a9350(const LegoChar* p_color); LegoU32 FUN_100a9410(Vector3& p_v1, Vector3& p_v2, float p_f1, float p_f2, Vector3& p_v3, LegoBool p_collideBox); void SetName(const LegoChar* p_name); float IntrinsicImportance() const override; // vtable+0x04 void UpdateWorldBoundingVolumes() override; // vtable+0x18 + void FUN_100a9dd0(); void SetDisplayBB(int p_displayBB); static LegoResult FUN_100a8cb0(LegoAnimNodeData* p_data, LegoTime p_time, Matrix4& p_matrix); diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 5df6786c..49e2efbd 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -482,6 +482,7 @@ // __setmode_lk // LIBRARY: LEGO1 0x100d1ed0 +// LIBRARY: BETA10 0x1018ec70 // _strnicmp // LIBRARY: LEGO1 0x100d1fd0 @@ -682,6 +683,9 @@ // LIBRARY: BETA10 0x100f9780 // strlen +// LIBRARY: BETA10 0x100fa200 +// strcpy + // LIBRARY: BETA10 0x100f8a88 // operator new @@ -703,7 +707,31 @@ // LIBRARY: BETA10 0x100fe5a0 // abort +// LIBRARY: BETA10 0x100fa0e0 +// atof + +// LIBRARY: BETA10 0x1005a9c0 +// fabs + +// LIBRARY: BETA10 0x1005a9f0 +// fabsf + +// LIBRARY: BETA10 0x100f9bb0 +// _fabs + +// LIBRARY: BETA10 0x100f9570 +// memset + // LIBRARY: BETA10 0x100ff82b // __ctrandisp1 +// LIBRARY: BETA10 0x100f8a92 +// operator delete + +// LIBRARY: BETA10 0x1018ed70 +// _strupr + +// LIBRARY: BETA10 0x1001d1a0 +// `vector constructor iterator' + #endif diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index f5e2c083..58d36198 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -6,10 +6,15 @@ #include "realtime/vector.h" // VTABLE: LEGO1 0x100d4488 +// VTABLE: BETA10 0x101b84d0 // SIZE 0x14 class Mx3DPointFloat : public Vector3 { public: + // FUNCTION: LEGO1 0x1001d170 + // FUNCTION: BETA10 0x10011990 Mx3DPointFloat() : Vector3(m_elements) {} + + // FUNCTION: BETA10 0x10011870 Mx3DPointFloat(float p_x, float p_y, float p_z) : Vector3(m_elements) { m_elements[0] = p_x; @@ -24,18 +29,18 @@ class Mx3DPointFloat : public Vector3 { // FUNCTION: BETA10 0x100151e0 Mx3DPointFloat(const Vector3& p_other) : Vector3(m_elements) { EqualsImpl(p_other.m_data); } - // SYNTHETIC: LEGO1 0x1001d170 - // Mx3DPointFloat::Mx3DPointFloat - // FUNCTION: LEGO1 0x10003c10 virtual void operator=(const Vector3& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x88 - float GetX() { return m_data[0]; } - float GetY() { return m_data[1]; } - float GetZ() { return m_data[2]; } - + // FUNCTION: BETA10 0x10013460 float& operator[](int idx) { return m_data[idx]; } - const float& operator[](int idx) const { return m_data[idx]; } + + // According to the PDB, BETA10 will not link this one if it is never used + // const float& operator[](int idx) const { return m_data[idx]; } + + // only used by LegoUnknown100db7f4::FUN_1002ddc0() for some unknown reason + // FUNCTION: BETA10 0x100373c0 + float& index_operator(int idx) { return m_data[idx]; } // SYNTHETIC: LEGO1 0x10010c00 // Mx3DPointFloat::operator= @@ -50,6 +55,7 @@ class Mx3DPointFloat : public Vector3 { class Mx4DPointFloat : public Vector4 { public: // FUNCTION: LEGO1 0x10048290 + // FUNCTION: BETA10 0x100484c0 Mx4DPointFloat() : Vector4(m_elements) {} // FUNCTION: BETA10 0x10073bb0 diff --git a/LEGO1/omni/include/mxdsaction.h b/LEGO1/omni/include/mxdsaction.h index 1820a68c..a68dbc51 100644 --- a/LEGO1/omni/include/mxdsaction.h +++ b/LEGO1/omni/include/mxdsaction.h @@ -86,13 +86,13 @@ class MxDSAction : public MxDSObject { void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } // FUNCTION: BETA10 0x1003db50 - Mx3DPointFloat& GetLocation() { return m_location; } + Vector3& GetLocation() { return m_location; } // FUNCTION: BETA10 0x1003db80 - Mx3DPointFloat& GetDirection() { return m_direction; } + Vector3& GetDirection() { return m_direction; } // FUNCTION: BETA10 0x1003dbb0 - Mx3DPointFloat& GetUp() { return m_up; } + Vector3& GetUp() { return m_up; } void SetLocation(const Vector3& p_location) { m_location = p_location; } void SetDirection(const Vector3& p_direction) { m_direction = p_direction; } diff --git a/LEGO1/omni/include/mxdsobject.h b/LEGO1/omni/include/mxdsobject.h index 3bb0a3ff..eb80044b 100644 --- a/LEGO1/omni/include/mxdsobject.h +++ b/LEGO1/omni/include/mxdsobject.h @@ -69,7 +69,9 @@ class MxDSObject : public MxCore { // FUNCTION: BETA10 0x10017910 MxU32 GetObjectId() { return m_objectId; } + // FUNCTION: BETA10 0x10017940 const MxAtomId& GetAtomId() { return m_atomId; } + MxS16 GetUnknown24() { return m_unk0x24; } MxPresenter* GetUnknown28() { return m_unk0x28; } diff --git a/LEGO1/omni/include/mxdssound.h b/LEGO1/omni/include/mxdssound.h index a0b81b4b..ae69e2d9 100644 --- a/LEGO1/omni/include/mxdssound.h +++ b/LEGO1/omni/include/mxdssound.h @@ -30,6 +30,7 @@ class MxDSSound : public MxDSMediaAction { void Deserialize(MxU8*& p_source, MxS16 p_unk0x24) override; // vtable+1c; MxDSAction* Clone() override; // vtable+2c; + // FUNCTION: BETA10 0x1008d060 MxS32 GetVolume() const { return m_volume; } // SYNTHETIC: LEGO1 0x100c9450 diff --git a/LEGO1/omni/include/mxnotificationparam.h b/LEGO1/omni/include/mxnotificationparam.h index bf1d589b..a5b30b24 100644 --- a/LEGO1/omni/include/mxnotificationparam.h +++ b/LEGO1/omni/include/mxnotificationparam.h @@ -39,6 +39,7 @@ enum NotificationId { // SIZE 0x0c class MxNotificationParam : public MxParam { public: + // FUNCTION: BETA10 0x100702d0 MxNotificationParam() : m_type(c_notificationType0), m_sender(NULL) {} // FUNCTION: BETA10 0x10013490 diff --git a/LEGO1/omni/include/mxpresenter.h b/LEGO1/omni/include/mxpresenter.h index a30897d1..3358c832 100644 --- a/LEGO1/omni/include/mxpresenter.h +++ b/LEGO1/omni/include/mxpresenter.h @@ -98,6 +98,7 @@ class MxPresenter : public MxCore { virtual void EndAction(); // vtable+0x40 // FUNCTION: LEGO1 0x1000bf90 + // FUNCTION: BETA10 0x10054a50 virtual void SetTickleState(TickleState p_tickleState) { ProgressTickleState(p_tickleState); } // vtable+0x44 // FUNCTION: LEGO1 0x1000bfb0 diff --git a/LEGO1/omni/include/mxsoundmanager.h b/LEGO1/omni/include/mxsoundmanager.h index ddd1fea6..0010f8e5 100644 --- a/LEGO1/omni/include/mxsoundmanager.h +++ b/LEGO1/omni/include/mxsoundmanager.h @@ -25,10 +25,11 @@ class MxSoundManager : public MxAudioManager { float GetAttenuation(MxU32 p_volume); + MxPresenter* FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_objectId); + protected: void Init(); void Destroy(MxBool p_fromDestructor); - MxPresenter* FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_objectId); // [library:audio] // Upscaling everything to 44.1KHz, since we have various sample rates throughout the game. diff --git a/LEGO1/omni/include/mxstreamchunk.h b/LEGO1/omni/include/mxstreamchunk.h index f71f78e7..fb72ee82 100644 --- a/LEGO1/omni/include/mxstreamchunk.h +++ b/LEGO1/omni/include/mxstreamchunk.h @@ -7,10 +7,13 @@ class MxDSBuffer; class MxStreamListMxDSSubscriber; // VTABLE: LEGO1 0x100dc2a8 +// VTABLE: BETA10 0x101c1d20 // SIZE 0x20 class MxStreamChunk : public MxDSChunk { public: + // FUNCTION: BETA10 0x10134420 MxStreamChunk() : m_buffer(NULL) {} + ~MxStreamChunk() override; // FUNCTION: LEGO1 0x100b1fe0 diff --git a/LEGO1/omni/include/mxvideopresenter.h b/LEGO1/omni/include/mxvideopresenter.h index 98c9948b..30d65354 100644 --- a/LEGO1/omni/include/mxvideopresenter.h +++ b/LEGO1/omni/include/mxvideopresenter.h @@ -52,14 +52,17 @@ class MxVideoPresenter : public MxMediaPresenter { MxBool IsHit(MxS32 p_x, MxS32 p_y) override; // vtable+0x50 // FUNCTION: LEGO1 0x1000c700 + // FUNCTION: BETA10 0x10054a80 virtual void LoadHeader(MxStreamChunk* p_chunk) {} // vtable+0x5c // FUNCTION: LEGO1 0x1000c710 + // FUNCTION: BETA10 0x10054aa0 virtual void CreateBitmap() {} // vtable+0x60 virtual void NextFrame(); // vtable+0x64 // FUNCTION: LEGO1 0x1000c720 + // FUNCTION: BETA10 0x10054ac0 virtual void LoadFrame(MxStreamChunk* p_chunk) {} // vtable+0x68 virtual void PutFrame(); // vtable+0x6c diff --git a/LEGO1/omni/src/common/mxmediapresenter.cpp b/LEGO1/omni/src/common/mxmediapresenter.cpp index 462b8987..0a1b96d9 100644 --- a/LEGO1/omni/src/common/mxmediapresenter.cpp +++ b/LEGO1/omni/src/common/mxmediapresenter.cpp @@ -229,6 +229,7 @@ void MxMediaPresenter::DoneTickle() } // FUNCTION: LEGO1 0x100b5f10 +// FUNCTION: BETA10 0x101366e9 void MxMediaPresenter::LoopChunk(MxStreamChunk* p_chunk) { MxStreamChunk* chunk = new MxStreamChunk; @@ -243,6 +244,7 @@ void MxMediaPresenter::LoopChunk(MxStreamChunk* p_chunk) } // FUNCTION: LEGO1 0x100b6030 +// FUNCTION: BETA10 0x10136814 void MxMediaPresenter::Enable(MxBool p_enable) { if (IsEnabled() != p_enable) { diff --git a/LEGO1/omni/src/common/mxpresenter.cpp b/LEGO1/omni/src/common/mxpresenter.cpp index 58e3dcac..845a82e7 100644 --- a/LEGO1/omni/src/common/mxpresenter.cpp +++ b/LEGO1/omni/src/common/mxpresenter.cpp @@ -110,6 +110,7 @@ void MxPresenter::ParseExtra() } // FUNCTION: LEGO1 0x100b5120 +// FUNCTION: BETA10 0x1012e5d8 void MxPresenter::SendToCompositePresenter(MxOmni* p_omni) { if (m_compositePresenter) { @@ -260,6 +261,7 @@ MxEntity* MxPresenter::CreateEntity(const char* p_defaultName) } // FUNCTION: LEGO1 0x100b54c0 +// FUNCTION: BETA10 0x1012ebaf MxBool MxPresenter::IsEnabled() { return this->m_action && this->m_action->GetFlags() & MxDSAction::c_enabled; diff --git a/LEGO1/omni/src/video/mxvideopresenter.cpp b/LEGO1/omni/src/video/mxvideopresenter.cpp index b9fc6b0d..c92e5dc4 100644 --- a/LEGO1/omni/src/video/mxvideopresenter.cpp +++ b/LEGO1/omni/src/video/mxvideopresenter.cpp @@ -176,6 +176,7 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor) } // FUNCTION: LEGO1 0x100b28b0 +// FUNCTION: BETA10 0x101389c1 void MxVideoPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); @@ -191,6 +192,7 @@ void MxVideoPresenter::NextFrame() } // FUNCTION: LEGO1 0x100b2900 +// FUNCTION: BETA10 0x10138a3a MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) { MxDSAction* action = GetAction(); @@ -563,6 +565,7 @@ void MxVideoPresenter::EndAction() } // FUNCTION: LEGO1 0x100b3280 +// FUNCTION: BETA10 0x101397c0 MxResult MxVideoPresenter::PutData() { AUTOLOCK(m_criticalSection); diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index 181acedf..729239e2 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -25,6 +25,7 @@ class Matrix4 { // in reverse order of appearance. // FUNCTION: LEGO1 0x10002320 + // FUNCTION: BETA10 0x1000fcb0 virtual void Equals(float (*p_data)[4]) { memcpy(m_data, p_data, sizeof(float) * 4 * 4); } // vtable+0x04 // FUNCTION: LEGO1 0x10002340 @@ -35,27 +36,35 @@ class Matrix4 { } // vtable+0x00 // FUNCTION: LEGO1 0x10002360 + // FUNCTION: BETA10 0x1000fd30 virtual void SetData(float (*p_data)[4]) { m_data = p_data; } // vtable+0x0c // FUNCTION: LEGO1 0x10002370 + // FUNCTION: BETA10 0x1000fd60 virtual void SetData(UnknownMatrixType& p_matrix) { m_data = p_matrix.m_data; } // vtable+0x08 // FUNCTION: LEGO1 0x10002380 + // FUNCTION: BETA10 0x1000fd90 virtual float (*GetData())[4] { return m_data; } // vtable+0x14 // FUNCTION: LEGO1 0x10002390 + // FUNCTION: BETA10 0x1000fdc0 virtual float (*GetData() const)[4] { return m_data; } // vtable+0x10 // FUNCTION: LEGO1 0x100023a0 + // FUNCTION: BETA10 0x1000fdf0 virtual float* Element(int p_row, int p_col) { return &m_data[p_row][p_col]; } // vtable+0x1c // FUNCTION: LEGO1 0x100023c0 + // FUNCTION: BETA10 0x1000fe30 virtual const float* Element(int p_row, int p_col) const { return &m_data[p_row][p_col]; } // vtable+0x18 // FUNCTION: LEGO1 0x100023e0 + // FUNCTION: BETA10 0x1000fe70 virtual void Clear() { memset(m_data, 0, 16 * sizeof(float)); } // vtable+0x20 // FUNCTION: LEGO1 0x100023f0 + // FUNCTION: BETA10 0x1000feb0 virtual void SetIdentity() { Clear(); @@ -66,9 +75,11 @@ class Matrix4 { } // vtable+0x24 // FUNCTION: LEGO1 0x10002420 + // FUNCTION: BETA10 0x1000ff20 virtual void operator=(const Matrix4& p_matrix) { Equals(p_matrix); } // vtable+0x28 // FUNCTION: LEGO1 0x10002430 + // FUNCTION: BETA10 0x1000ff50 virtual Matrix4& operator+=(float (*p_data)[4]) { for (int i = 0; i < 16; i++) { @@ -78,6 +89,7 @@ class Matrix4 { } // vtable+0x2c // FUNCTION: LEGO1 0x10002460 + // FUNCTION: BETA10 0x1000ffc0 virtual void TranslateBy(const float& p_x, const float& p_y, const float& p_z) { m_data[3][0] += p_x; @@ -86,6 +98,7 @@ class Matrix4 { } // vtable+0x30 // FUNCTION: LEGO1 0x100024a0 + // FUNCTION: BETA10 0x10010040 virtual void SetTranslation(const float& p_x, const float& p_y, const float& p_z) { m_data[3][0] = p_x; @@ -94,6 +107,7 @@ class Matrix4 { } // vtable+0x34 // FUNCTION: LEGO1 0x100024d0 + // FUNCTION: BETA10 0x100100a0 virtual void Product(float (*p_a)[4], float (*p_b)[4]) { float* cur = (float*) m_data; @@ -109,6 +123,7 @@ class Matrix4 { } // vtable+0x3c // FUNCTION: LEGO1 0x10002530 + // FUNCTION: BETA10 0x10010180 virtual void Product(const Matrix4& p_a, const Matrix4& p_b) { Product(p_a.m_data, p_b.m_data); } // vtable+0x38 inline virtual void ToQuaternion(Vector4& p_resultQuat); // vtable+0x40 @@ -183,6 +198,7 @@ class Matrix4 { }; // FUNCTION: LEGO1 0x10002550 +// FUNCTION: BETA10 0x100101c0 inline void Matrix4::ToQuaternion(Vector4& p_outQuat) { float trace = m_data[0][0] + m_data[1][1] + m_data[2][2]; @@ -223,6 +239,7 @@ inline void Matrix4::ToQuaternion(Vector4& p_outQuat) } // FUNCTION: LEGO1 0x10002710 +// FUNCTION: BETA10 0x10010550 inline int Matrix4::FromQuaternion(const Vector4& p_vec) { float len = p_vec.LenSquared(); diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h index 61b61645..5e70aa5e 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -48,7 +48,9 @@ class OrientableROI : public ROI { // FUNCTION: BETA10 0x10011780 const float* GetWorldDirection() const { return m_local2world[2]; } + // FUNCTION: BETA10 0x1004aa70 const float* GetWorldUp() const { return m_local2world[1]; } + OrientableROI* GetParentROI() const { return m_parentROI; } void SetParentROI(OrientableROI* p_parentROI) { m_parentROI = p_parentROI; } diff --git a/LEGO1/realtime/realtime.cpp b/LEGO1/realtime/realtime.cpp index 829b2271..944b093c 100644 --- a/LEGO1/realtime/realtime.cpp +++ b/LEGO1/realtime/realtime.cpp @@ -3,6 +3,7 @@ #include // FUNCTION: LEGO1 0x100a5b40 +// FUNCTION: BETA10 0x10168127 void CalcLocalTransform(const Vector3& p_posVec, const Vector3& p_dirVec, const Vector3& p_upVec, Matrix4& p_outMatrix) { float x_axis[3], y_axis[3], z_axis[3]; diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h index 3d638feb..224c9607 100644 --- a/LEGO1/realtime/roi.h +++ b/LEGO1/realtime/roi.h @@ -118,6 +118,8 @@ class ROI { const CompoundObject* GetComp() const { return comp; } unsigned char GetVisibility() { return m_visible; } + + // FUNCTION: BETA10 0x10011720 void SetVisibility(unsigned char p_visible) { m_visible = p_visible; } // SYNTHETIC: LEGO1 0x100a5d60 diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 4c1e17c3..a09e62c4 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -163,13 +163,10 @@ class Vector2 { return *this; } - // SYNTHETIC: BETA10 0x10013460 - // Vector3::operator[] - - // FUNCTION: BETA10 0x10010890 + // FUNCTION: BETA10 0x1001d140 float& operator[](int idx) { return m_data[idx]; } - // FUNCTION: BETA10 0x1001d140 + // FUNCTION: BETA10 0x1001d170 const float& operator[](int idx) const { return m_data[idx]; } protected: @@ -182,12 +179,15 @@ class Vector2 { class Vector3 : public Vector2 { public: // FUNCTION: LEGO1 0x1001d150 + // FUNCTION: BETA10 0x10011660 Vector3(float* p_data) : Vector2(p_data) {} // Hack: Some code initializes a Vector3 from a (most likely) const float* source. // Example: LegoCameraController::GetWorldUp // Vector3 however is a class that can mutate its underlying source, making // initialization with a const source fundamentally incompatible. + + // FUNCTION: BETA10 0x100109a0 Vector3(const float* p_data) : Vector2((float*) p_data) {} // Note: virtual function overloads appear in the virtual table @@ -298,6 +298,7 @@ class Vector3 : public Vector2 { // SIZE 0x08 class Vector4 : public Vector3 { public: + // FUNCTION: BETA10 0x10048780 Vector4(float* p_data) : Vector3(p_data) {} // Hack: Some code initializes a Vector4 from a (most likely) const float* source. @@ -407,6 +408,11 @@ class Vector4 : public Vector3 { m_data[3] = p_value; } // vtable+0x84 + float& operator[](int idx) { return m_data[idx]; } + + // FUNCTION: BETA10 0x10010890 + const float& operator[](int idx) const { return m_data[idx]; } + friend class Mx4DPointFloat; };