diff --git a/LEGO1/lego/legoomni/include/animstate.h b/LEGO1/lego/legoomni/include/animstate.h index 16c92120..5812b6da 100644 --- a/LEGO1/lego/legoomni/include/animstate.h +++ b/LEGO1/lego/legoomni/include/animstate.h @@ -3,6 +3,33 @@ #include "legostate.h" +struct ModelInfo { + char* m_modelName; // 0x00 + MxU8 m_unk0x4; // 0x04 + float m_location[3]; // 0x08 + float m_direction[3]; // 0x14 + float m_up[3]; // 0x20 + MxU8 m_unk0x2c; // 0x2c + undefined m_unk0x2d[3]; // 0x2d +}; + +struct AnimInfo { + char* m_animName; // 0x00 + undefined4 m_unk0x4; // 0x04 + MxS16 m_unk0x8; // 0x08 + MxU8 m_unk0xa; // 0x0a + MxU8 m_unk0xb; // 0x0b + MxU8 m_unk0xc; // 0x0c + MxU8 m_unk0xd; // 0x0d + MxU32 m_unk0x10[4]; // 0x10 + MxU8 m_modelCount; // 0x20 + ModelInfo* m_models; // 0x24 + MxU8 m_unk0x28; // 0x28 + MxU8 m_unk0x29; // 0x29 + MxS8 m_unk0x2a[3]; // 0x2a + undefined m_unk0x2d[3]; // 0x2d +}; + // VTABLE: LEGO1 0x100d8d80 // SIZE 0x1c class AnimState : public LegoState { @@ -26,6 +53,9 @@ class AnimState : public LegoState { MxBool SetFlag() override; // vtable+0x18 MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c + void FUN_100651d0(MxU32, AnimInfo*, MxU32&); + void FUN_10065240(MxU32, AnimInfo*, MxU32); + // SYNTHETIC: LEGO1 0x10065130 // AnimState::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index 31ee5a37..28ac522b 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -1,9 +1,69 @@ #ifndef LEGOANIMATIONMANAGER_H #define LEGOANIMATIONMANAGER_H +#include "animstate.h" #include "decomp.h" #include "mxcore.h" +struct Character { + char* m_name; + undefined m_unk0x4[0x10]; // 0x04 + MxBool m_active; // 0x14 + undefined m_unk0x15; // 0x15 + undefined m_unk0x16; // 0x16 + undefined m_unk0x17; // 0x17 +}; + +struct Vehicle { + char* m_name; // 0x00 + undefined4 m_unk0x4; // 0x04 +}; + +void C100d8ca8_Handler(); +void C100d8cd8_Handler(); + +// VTABLE: LEGO1 0x100d8ca8 +// SIZE 0x10 +class C100d8ca8 : public MxCore { +public: + inline C100d8ca8() + { + m_unk0x8 = 0; + SetHandler(C100d8ca8_Handler); + } + inline void SetHandler(void (*p_handler)()) { m_unk0xc = p_handler; } + +private: + MxU32 m_unk0x8; // 0x08 + void (*m_unk0xc)(); // 0x0c +}; + +// VTABLE: LEGO1 0x100d8cc0 +// SIZE 0x18 +class C100d8cc0 : public C100d8ca8 { +public: + inline C100d8cc0() { m_unk0x10 = m_unk0x14 = 0; } + +private: + MxU32 m_unk0x10; // 0x10 + MxU32 m_unk0x14; // 0x14 +}; + +// VTABLE: LEGO1 0x100d8cd8 +// SIZE 0x18 +class C100d8cd8 : public C100d8cc0 { +public: + inline C100d8cd8(MxBool p_mode) { SetHandler(p_mode); } + inline void SetHandler(MxBool p_mode) { C100d8ca8::SetHandler(p_mode ? C100d8cd8_Handler : C100d8ca8_Handler); } +}; + +// VTABLE: LEGO1 0x100d8c90 +// SIZE 0x18 +class C100d8c90 : public C100d8cd8 { +public: + inline C100d8c90() : C100d8cd8(FALSE) {} +}; + // VTABLE: LEGO1 0x100d8c18 // SIZE 0x500 class LegoAnimationManager : public MxCore { @@ -31,8 +91,14 @@ class LegoAnimationManager : public MxCore { void FUN_1005ef10(); void FUN_1005f0b0(); void FUN_1005f6d0(MxBool); - void FUN_1005f720(MxS32 p_scriptIndex); + MxResult LoadScriptInfo(MxS32 p_scriptIndex); + MxBool FUN_10060140(char* p_name, MxU32& index); + MxResult ReadAnimInfo(LegoFile* p_file, AnimInfo* p_info); + MxResult ReadModelInfo(LegoFile* p_file, ModelInfo* p_info); + void FUN_100603c0(); void FUN_10061010(undefined4); + void FUN_100617c0(MxS32, MxU16&, MxU32&); + MxS8 FUN_10062360(char*); void FUN_10064670(MxBool); static void configureLegoAnimationManager(MxS32 p_legoAnimationManagerConfig); @@ -43,7 +109,34 @@ class LegoAnimationManager : public MxCore { private: void Init(); - undefined m_unk0x08[0x4f8]; // 0x08 + undefined4 m_unk0x08; // 0x08 + MxU16 m_animCount; // 0x0c + MxU16 m_unk0x0e; // 0x0e + MxU32 m_unk0x10; // 0x10 + AnimInfo* m_anims; // 0x14 + undefined m_unk0x018[8]; // 0x18 + C100d8c90* m_tranInfoList; // 0x20 + C100d8c90* m_tranInfoList2; // 0x24 + undefined4 m_unk0x28[2]; // 0x28 + undefined4 m_unk0x30[2]; // 0x30 + undefined m_unk0x38; // 0x38 + undefined m_unk0x39; // 0x39 + undefined m_unk0x3a; // 0x3a + undefined m_unk0x3b[0x3c1]; // 0x3b + undefined4 m_unk0x3fc; // 0x3fc + MxU8 m_unk0x400; // 0x400 + undefined m_unk0x401; // 0x401 + MxU8 m_unk0x402; // 0x402 + undefined m_unk0x403[0x1d]; // 0x403 + AnimState* m_animState; // 0x420 + undefined4 m_unk0x424; // 0x424 + undefined m_unk0x428; // 0x428 + undefined m_unk0x429; // 0x429 + undefined m_unk0x42a; // 0x42a + undefined m_unk0x42b; // 0x42b + undefined4 m_unk0x42c; // 0x42c + undefined m_unk0x430; // 0x430 + undefined m_unk0x431[0xcf]; // 0x431 }; #endif // LEGOANIMATIONMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legoomni.h b/LEGO1/lego/legoomni/include/legoomni.h index 5d1df4fa..a8fb5191 100644 --- a/LEGO1/lego/legoomni/include/legoomni.h +++ b/LEGO1/lego/legoomni/include/legoomni.h @@ -98,7 +98,6 @@ class LegoOmni : public MxOmni { inline MxS32 GetIndex() { return m_index; } inline const char* GetKey() { return m_key; } - private: MxS32 m_index; // 0x00 char m_key[20]; // 0x04 MxAtomId* m_script; // 0x18 @@ -203,6 +202,7 @@ class LegoOmni : public MxOmni { MxS32 GetScriptIndex(const char* p_key); static MxS32 GetCurrPathInfo(LegoPathBoundary**, MxS32&); + const char* FindScript(MxU32 p_id); static void CreateInstance(); static LegoOmni* GetInstance(); diff --git a/LEGO1/lego/legoomni/src/common/animstate.cpp b/LEGO1/lego/legoomni/src/common/animstate.cpp index c7665237..71323c7a 100644 --- a/LEGO1/lego/legoomni/src/common/animstate.cpp +++ b/LEGO1/lego/legoomni/src/common/animstate.cpp @@ -17,6 +17,16 @@ AnimState::~AnimState() // TODO } +// STUB: LEGO1 0x100651d0 +void AnimState::FUN_100651d0(MxU32, AnimInfo*, MxU32&) +{ +} + +// STUB: LEGO1 0x10065240 +void AnimState::FUN_10065240(MxU32, AnimInfo*, MxU32) +{ +} + // STUB: LEGO1 0x100652d0 MxResult AnimState::VTable0x1c(LegoFile* p_legoFile) { diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index bdf3eb98..ece9dfad 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -1,7 +1,17 @@ #include "legoanimationmanager.h" +#include "legogamestate.h" +#include "legoomni.h" +#include "misc.h" +#include "mxutilities.h" + +#include + DECOMP_SIZE_ASSERT(LegoAnimationManager, 0x500) +// GLOBAL: LEGO1 0x100f7048 +Character g_characters[0x2f]; + // GLOBAL: LEGO1 0x100f74f8 int g_legoAnimationManagerConfig = 1; @@ -53,10 +63,224 @@ void LegoAnimationManager::FUN_1005f6d0(MxBool) // TODO } -// STUB: LEGO1 0x1005f720 -void LegoAnimationManager::FUN_1005f720(MxS32 p_scriptIndex) +// FUNCTION: LEGO1 0x1005f720 +MxResult LegoAnimationManager::LoadScriptInfo(MxS32 p_scriptIndex) +{ + MxResult result = FAILURE; + if (m_unk0x08 != p_scriptIndex) { + if (m_tranInfoList != NULL) { + delete m_tranInfoList; + m_tranInfoList = NULL; + } + if (m_tranInfoList2 != NULL) { + delete m_tranInfoList2; + m_tranInfoList2 = NULL; + } + for (int i = 0; i < 2; i++) { + m_unk0x28[i] = 0; + m_unk0x30[i] = 0; + } + m_unk0x38 = 0; + m_unk0x39 = 0; + m_unk0x430 = 0; + m_unk0x42c = 0; + for (int i2 = 0; i2 < 0x2f; i2++) { + g_characters[i2].m_active = FALSE; + } + m_animState = (AnimState*) GameState()->GetState("AnimState"); + if (m_animState == NULL) { + m_animState = (AnimState*) GameState()->CreateState("AnimState"); + } + if (m_unk0x08 == 0) { + m_animState->FUN_10065240(m_animCount, m_anims, m_unk0x3fc); + } + FUN_100603c0(); + LegoFile file; + if (p_scriptIndex == -1) { + result = SUCCESS; + } + else { + char filename[128]; + char path[1024]; + sprintf(filename, "lego\\data\\%sinf.dta", Lego()->FindScript(p_scriptIndex)); + sprintf(path, "%s", MxOmni::GetHD()); + if (path[strlen(path) - 1] != '\\') { + strcat(path, "\\"); + } + strcat(path, filename); + if (_access(path, 4)) { + sprintf(path, "%s", MxOmni::GetCD()); + if (path[strlen(path) - 1] != '\\') { + strcat(path, "\\"); + } + strcat(path, filename); + if (_access(path, 4)) { + goto done; + } + } + if (file.Open(path, LegoFile::c_read) == FAILURE) { + goto done; + } + MxU32 version; + if (file.Read(&version, 4) == FAILURE) { + goto done; + } + if (version != 3) { + OmniError("World animation version mismatch", 0); + goto done; + } + if (file.Read(&m_animCount, 2) == FAILURE) { + goto done; + } + m_anims = new AnimInfo[m_animCount]; + memset(m_anims, 0, m_animCount * sizeof(AnimInfo)); + for (int i = 0; i < m_animCount; i++) { + if (ReadAnimInfo(&file, &m_anims[i]) == FAILURE) { + goto done; + } + m_anims[i].m_unk0x28 = FUN_10062360(m_anims[i].m_animName + strlen(m_anims[i].m_animName) - 2); + m_anims[i].m_unk0x29 = 0; + for (int j = 0; j < 3; j++) { + m_anims[i].m_unk0x2a[j] = -1; + } + if (m_anims[i].m_unk0x8 == -1) { + for (int j = 0; j < m_anims[i].m_modelCount; j++) { + MxS32 index = FUN_10062360(m_anims[i].m_models[j].m_modelName); + if (index >= 0) { + g_characters[index].m_active = TRUE; + } + } + } + MxS32 count = 0; + for (int j2 = 0; j2 < m_anims[i].m_modelCount; j2++) { + MxU32 k; + if (FUN_10060140(m_anims[i].m_models[j2].m_modelName, k) && m_anims[i].m_models[j2].m_unk0x2c) { + m_anims[i].m_unk0x2a[count++] = k; + if (count > 3) + break; + } + } + } + m_unk0x08 = p_scriptIndex; + m_tranInfoList = new C100d8c90(); + m_tranInfoList2 = new C100d8c90(); + FUN_100617c0(-1, m_unk0x0e, m_unk0x10); + result = SUCCESS; + m_unk0x402 = 1; + if (m_unk0x42b) { + m_unk0x42a = 1; + m_unk0x402 = 0; + m_unk0x428 = m_unk0x3a; + m_unk0x3a = 0; + m_unk0x429 = m_unk0x400; + m_unk0x400 = 0; + } + if (p_scriptIndex == 0) { + m_animState->FUN_100651d0(m_animCount, m_anims, m_unk0x3fc); + } + } + } +done: + if (result == FAILURE) { + FUN_100603c0(); + } + return result; +} + +// STUB: LEGO1 0x10060140 +MxBool LegoAnimationManager::FUN_10060140(char* p_name, MxU32& index) +{ + return FALSE; +} + +// FUNCTION: LEGO1 0x10060180 +MxResult LegoAnimationManager::ReadAnimInfo(LegoFile* p_file, AnimInfo* p_info) +{ + MxResult result = FAILURE; + MxU8 length; + int i, i2; + if (p_file->Read(&length, 1) == FAILURE) { + goto fail; + } + p_info->m_animName = new char[length + 1]; + if (p_file->Read(p_info->m_animName, length) == FAILURE) { + goto fail; + } + p_info->m_animName[length] = 0; + if (p_file->Read(&p_info->m_unk0x4, 4) == FAILURE) { + goto fail; + } + if (p_file->Read(&p_info->m_unk0x8, 2) == FAILURE) { + goto fail; + } + if (p_file->Read(&p_info->m_unk0xa, 1) == FAILURE) { + goto fail; + } + if (p_file->Read(&p_info->m_unk0xb, 1) == FAILURE) { + goto fail; + } + if (p_file->Read(&p_info->m_unk0xc, 1) == FAILURE) { + goto fail; + } + if (p_file->Read(&p_info->m_unk0xd, 1) == FAILURE) { + goto fail; + } + for (i = 0; i < 4; i++) { + if (p_file->Read(&p_info->m_unk0x10[i], 4) != SUCCESS) { + goto fail; + } + } + if (p_file->Read(&p_info->m_modelCount, 1) == FAILURE) { + goto fail; + } + p_info->m_models = new ModelInfo[p_info->m_modelCount]; + memset(p_info->m_models, 0, p_info->m_modelCount * sizeof(ModelInfo)); + for (i2 = 0; i2 < p_info->m_modelCount; i2++) { + if (ReadModelInfo(p_file, &p_info->m_models[i2]) == FAILURE) { + goto fail; + } + } + result = SUCCESS; +fail: + return result; +} + +// FUNCTION: LEGO1 0x10060310 +MxResult LegoAnimationManager::ReadModelInfo(LegoFile* p_file, ModelInfo* p_info) +{ + MxResult result = FAILURE; + MxU8 length; + if (p_file->Read(&length, 1) == FAILURE) { + goto fail; + } + p_info->m_modelName = new char[length + 1]; + if (p_file->Read(p_info->m_modelName, length) == FAILURE) { + goto fail; + } + p_info->m_modelName[length] = 0; + if (p_file->Read(&p_info->m_unk0x4, 1) == FAILURE) { + goto fail; + } + if (p_file->Read(p_info->m_location, 12) != SUCCESS) { + goto fail; + } + if (p_file->Read(p_info->m_direction, 12) != SUCCESS) { + goto fail; + } + if (p_file->Read(p_info->m_up, 12) != SUCCESS) { + goto fail; + } + if (p_file->Read(&p_info->m_unk0x2c, 1) == FAILURE) { + goto fail; + } + result = SUCCESS; +fail: + return result; +} + +// STUB: LEGO1 0x100603c0 +void LegoAnimationManager::FUN_100603c0() { - // TODO } // STUB: LEGO1 0x10061010 @@ -65,6 +289,11 @@ void LegoAnimationManager::FUN_10061010(undefined4) // TODO } +// STUB: LEGO1 0x100617c0 +void LegoAnimationManager::FUN_100617c0(MxS32, MxU16&, MxU32&) +{ +} + // STUB: LEGO1 0x100619f0 MxLong LegoAnimationManager::Notify(MxParam& p_param) { @@ -81,7 +310,22 @@ MxResult LegoAnimationManager::Tickle() return SUCCESS; } +// STUB: LEGO1 0x10062360 +MxS8 LegoAnimationManager::FUN_10062360(char*) +{ + return 0; +} + // STUB: LEGO1 0x10064670 void LegoAnimationManager::FUN_10064670(MxBool) { } + +// STUB: LEGO1 0x1005fe50 +void C100d8ca8_Handler() +{ +} + +void C100d8cd8_Handler() +{ +} diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index fc31b459..12a69958 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -577,7 +577,7 @@ void LegoWorld::Enable(MxBool p_enable) if (m_scriptIndex != -1) { PlantManager()->FUN_10026360(m_scriptIndex); - AnimationManager()->FUN_1005f720(m_scriptIndex); + AnimationManager()->LoadScriptInfo(m_scriptIndex); BuildingManager()->FUN_1002fa00(); AnimationManager()->FUN_1005f0b0(); } diff --git a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp index 756e32f9..e336c362 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp @@ -54,7 +54,7 @@ LegoWorldPresenter::~LegoWorldPresenter() if (m_entity) { MxS32 scriptIndex = ((LegoWorld*) m_entity)->GetScriptIndex(); PlantManager()->FUN_10026360(scriptIndex); - AnimationManager()->FUN_1005f720(scriptIndex); + AnimationManager()->LoadScriptInfo(scriptIndex); BuildingManager()->FUN_1002fa00(); result = ((LegoWorld*) m_entity)->VTable0x5c(); } diff --git a/LEGO1/lego/legoomni/src/main/legoomni.cpp b/LEGO1/lego/legoomni/src/main/legoomni.cpp index cb1f5b05..a37dc0fa 100644 --- a/LEGO1/lego/legoomni/src/main/legoomni.cpp +++ b/LEGO1/lego/legoomni/src/main/legoomni.cpp @@ -706,6 +706,17 @@ MxS32 LegoOmni::GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value) return ::CurrentWorld()->GetCurrPathInfo(p_path, p_value); } +// FUNCTION: LEGO1 0x1005b430 +const char* LegoOmni::FindScript(MxU32 p_index) +{ + for (int i = 0; i < 19; i++) { + if (m_scripts[i].m_index == p_index) { + return m_scripts[i].m_key; + } + } + return NULL; +} + // FUNCTION: LEGO1 0x1005b490 MxS32 LegoOmni::GetScriptIndex(const char* p_key) {