diff --git a/3rdparty/flic/flic.asm b/3rdparty/flic/flic.asm index ef402a14..44f42086 100644 --- a/3rdparty/flic/flic.asm +++ b/3rdparty/flic/flic.asm @@ -6,7 +6,10 @@ assume fs:nothing public DecodeFLCFrame -.text SEGMENT PARA PUBLIC 'CODE' +; This is so reccmp can detect the end of DecodeFLCFrame +public EndOfSection + +.text SEGMENT BYTE PUBLIC 'CODE' ?_25162 LABEL NEAR mov ax, word ptr [esp+0CH] ; 100BD530 _ 66: 8B. 44 24, 0C @@ -37,10 +40,8 @@ public DecodeFLCFrame ; Filling space: 0DH ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH - -ALIGN 16 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH ?_25164 LABEL NEAR lea eax, [esp+18H] ; 100BD580 _ 8D. 44 24, 18 @@ -89,10 +90,8 @@ ALIGN 16 ; Filling space: 0CH ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH -; db 0CCH, 0CCH, 0CCH, 0CCH - -ALIGN 16 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH ?_25168 LABEL NEAR mov ecx, dword ptr [esp+8H] ; 100BD600 _ 8B. 4C 24, 08 @@ -149,9 +148,7 @@ ALIGN 16 ; Filling space: 8H ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH - -ALIGN 16 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH ?_25173 LABEL NEAR lea eax, [esp+18H] ; 100BD680 _ 8D. 44 24, 18 @@ -188,10 +185,8 @@ ALIGN 16 ; Filling space: 0AH ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH -; db 0CCH, 0CCH - -ALIGN 16 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH ?_25176 LABEL NEAR lea eax, [esp+18H] ; 100BD6E0 _ 8D. 44 24, 18 @@ -238,9 +233,7 @@ ALIGN 16 ; Filling space: 3H ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH - -ALIGN 8 + db 0CCH, 0CCH, 0CCH ?_25180 LABEL NEAR mov eax, dword ptr [esp+18H] ; 100BD760 _ 8B. 44 24, 18 @@ -373,10 +366,8 @@ ALIGN 8 ; Filling space: 0DH ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH - -ALIGN 16 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH ?_25195 LABEL NEAR mov eax, dword ptr [esp+8H] ; 100BD8A0 _ 8B. 44 24, 08 @@ -447,9 +438,7 @@ ALIGN 16 ; Filling space: 8H ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH - -ALIGN 16 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH ?_25202 LABEL NEAR mov eax, dword ptr [esp+8H] ; 100BD940 _ 8B. 44 24, 08 @@ -462,10 +451,8 @@ ALIGN 16 ; Filling space: 0DH ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH - -ALIGN 16 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH ?_25203 LABEL NEAR mov eax, dword ptr [esp+10H] ; 100BD960 _ 8B. 44 24, 10 @@ -539,10 +526,8 @@ ALIGN 16 ; Filling space: 0CH ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH -; db 0CCH, 0CCH, 0CCH, 0CCH - -ALIGN 16 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH ?_25213 LABEL NEAR mov ecx, dword ptr [esp+0CH] ; 100BDA10 _ 8B. 4C 24, 0C @@ -621,9 +606,7 @@ ALIGN 16 ; Filling space: 3H ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH - -ALIGN 8 + db 0CCH, 0CCH, 0CCH ?_25220 LABEL NEAR mov edx, dword ptr [esp+10H] ; 100BDAC0 _ 8B. 54 24, 10 @@ -738,9 +721,7 @@ ALIGN 8 ; Filling space: 3H ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH - -ALIGN 8 + db 0CCH, 0CCH, 0CCH ?_25227 LABEL NEAR mov eax, dword ptr [esp+10H] ; 100BDC00 _ 8B. 44 24, 10 @@ -798,10 +779,8 @@ ALIGN 8 ; Filling space: 0CH ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH -; db 0CCH, 0CCH, 0CCH, 0CCH - -ALIGN 16 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH ?_25231 LABEL NEAR mov eax, dword ptr [esp+10H] ; 100BDC90 _ 8B. 44 24, 10 @@ -839,9 +818,7 @@ ALIGN 16 ; Filling space: 7H ; Filler type: INT 3 Debug breakpoint -; db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH - -ALIGN 8 + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH DecodeFLCFrame LABEL NEAR mov ecx, dword ptr [esp+10H] ; 100BDCE0 _ 8B. 4C 24, 10 @@ -863,6 +840,12 @@ DecodeFLCFrame LABEL NEAR add esp, 24 ; 100BDD0A _ 83. C4, 18 ?_25235:ret ; 100BDD0D _ C3 +; Filling space: 2H +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH + +EndOfSection LABEL NEAR + .text ENDS END diff --git a/3rdparty/flic/flic.lib b/3rdparty/flic/flic.lib index 8e297be8..fea46a25 100644 Binary files a/3rdparty/flic/flic.lib and b/3rdparty/flic/flic.lib differ diff --git a/LEGO1/lego/legoomni/include/elevatorbottom.h b/LEGO1/lego/legoomni/include/elevatorbottom.h index ed424efd..1f02d28f 100644 --- a/LEGO1/lego/legoomni/include/elevatorbottom.h +++ b/LEGO1/lego/legoomni/include/elevatorbottom.h @@ -40,6 +40,8 @@ class ElevatorBottom : public LegoWorld { private: undefined4 m_unk0xf8; // 0xf8 + + MxLong HandleNotification17(MxParam& p_param); }; #endif // ELEVATORBOTTOM_H diff --git a/LEGO1/lego/legoomni/include/gifmanager.h b/LEGO1/lego/legoomni/include/gifmanager.h index aa6d2d80..898ab1fb 100644 --- a/LEGO1/lego/legoomni/include/gifmanager.h +++ b/LEGO1/lego/legoomni/include/gifmanager.h @@ -3,73 +3,139 @@ #include "compat.h" #include "decomp.h" +#include "mxstl/stlcompat.h" #include "mxtypes.h" #include #include +#pragma warning(disable : 4237) + +// SIZE 0x14 struct GifData { public: - const char* m_name; - LPDIRECTDRAWSURFACE m_surface; - LPDIRECTDRAWPALETTE m_palette; - LPDIRECT3DRMTEXTURE2 m_texture; - MxU8* m_data; + char* m_name; // 0x00 + LPDIRECTDRAWSURFACE m_surface; // 0x04 + LPDIRECTDRAWPALETTE m_palette; // 0x08 + LPDIRECT3DRMTEXTURE2 m_texture; // 0x0c + MxU8* m_data; // 0x10 + + ~GifData(); }; -struct GifMapEntry { -public: - GifMapEntry* m_right; - GifMapEntry* m_parent; - GifMapEntry* m_left; - const char* m_key; - GifData* m_value; +struct GifMapComparator { + bool operator()(const char* const& p_key0, const char* const& p_key1) const { return strcmp(p_key0, p_key1) > 0; } }; -class GifMap { -public: - GifMapEntry* FindNode(const char*& p_string); - - inline GifData* Get(const char* p_string) - { - GifData* ret = NULL; - GifMapEntry* entry = FindNode(p_string); - if (((m_unk0x4 == entry || strcmp(p_string, entry->m_key) > 0) ? m_unk0x4 : entry) != entry) - ret = entry->m_value; - return ret; - } - - undefined4 m_unk0x0; - GifMapEntry* m_unk0x4; +// SIZE 0x10 +class GifMap : public map { + // SYNTHETIC: LEGO1 0x1005a400 + // GifMap::~GifMap }; +typedef list GifList; + // VTABLE: LEGO1 0x100d86d4 +// SIZE 0x18 class GifManagerBase { public: - // STUB: LEGO1 0x1005b660 - virtual ~GifManagerBase() {} + // FUNCTION: LEGO1 0x1005b660 + virtual ~GifManagerBase() + { + GifMap::iterator it; + for (it = m_map.begin(); it != m_map.end(); it++) { + // DECOMP: Use of const_cast here matches ~ViewLODListManager from 96 source. + const char* const& key = (*it).first; + delete[] const_cast(key); + + if (m_ownership) { + delete (*it).second; // GifData* + } + } + } + + inline GifData* Get(const char* p_name) + { + GifMap::iterator it = m_map.find(p_name); + if (it != m_map.end()) { + return (*it).second; + } + + return NULL; + } // SYNTHETIC: LEGO1 0x1005a310 // GifManagerBase::`scalar deleting destructor' - inline GifData* Get(const char* p_name) { return m_unk0x8.Get(p_name); } - protected: - undefined4 m_unk0x0; - undefined4 m_unk0x4; - GifMap m_unk0x8; + MxBool m_ownership; // 0x04 + GifMap m_map; // 0x08 }; // VTABLE: LEGO1 0x100d86fc +// SIZE 0x24 class GifManager : public GifManagerBase { public: + GifManager() { m_ownership = TRUE; }; virtual ~GifManager() override; // SYNTHETIC: LEGO1 0x1005a580 // GifManager::`scalar deleting destructor' + void FUN_10099cc0(GifData* p_data); + protected: - undefined m_unk0x14[0x1c]; + GifList m_list; // 0x18 }; +// TEMPLATE: LEGO1 0x10059c50 +// allocator::_Charalloc + +// clang-format off +// TEMPLATE: LEGO1 0x10001cc0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Lbound + +// TEMPLATE: LEGO1 0x1004f9b0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Insert + +// TEMPLATE: LEGO1 0x10059c70 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Color + +// TEMPLATE: LEGO1 0x10059c80 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Left + +// TEMPLATE: LEGO1 0x10059c90 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Parent + +// TEMPLATE: LEGO1 0x10059ca0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Right + +// TEMPLATE: LEGO1 0x10059cb0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::~_Tree,map >::_Kfn,GifMapComparator,allocator > + +// TEMPLATE: LEGO1 0x10059d80 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::iterator::_Inc + +// TEMPLATE: LEGO1 0x10059dc0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::erase + +// TEMPLATE: LEGO1 0x1005a210 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Erase + +// TEMPLATE: LEGO1 0x1005a250 +// list >::~list > + +// TEMPLATE: LEGO1 0x1005a2c0 +// map >::~map > + +// TEMPLATE: LEGO1 0x1005a450 +// Map::~Map + +// TEMPLATE: LEGO1 0x1005a5a0 +// List::~List + +// GLOBAL: LEGO1 0x100f0100 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Nil +// clang-format on + #endif // GIFMANAGER_H diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h index 4d8ed408..7de6ec45 100644 --- a/LEGO1/lego/legoomni/include/infocenter.h +++ b/LEGO1/lego/legoomni/include/infocenter.h @@ -170,10 +170,10 @@ class Infocenter : public LegoWorld { InfocenterUnkDataEntry m_entries[7]; // 0x120 MxS16 m_unk0x1c8; // 0x1c8 undefined4 m_unk0x1cc; // 0x1cc - MxU16 m_unk0x1d0; // 0x1d0 - MxU16 m_unk0x1d2; // 0x1d2 + MxS16 m_infoManDialogueTimer; // 0x1d0 + MxS16 m_bookAnimationTimer; // 0x1d2 MxU16 m_unk0x1d4; // 0x1d4 - MxU16 m_unk0x1d6; // 0x1d6 + MxS16 m_unk0x1d6; // 0x1d6 }; #endif // INFOCENTER_H diff --git a/LEGO1/lego/legoomni/include/infocenterdoor.h b/LEGO1/lego/legoomni/include/infocenterdoor.h index effb22cf..1890f0b1 100644 --- a/LEGO1/lego/legoomni/include/infocenterdoor.h +++ b/LEGO1/lego/legoomni/include/infocenterdoor.h @@ -36,6 +36,9 @@ class InfocenterDoor : public LegoWorld { // SYNTHETIC: LEGO1 0x100378d0 // InfocenterDoor::`scalar deleting destructor' + +private: + MxS32 m_unk0xf8; // 0xf8 }; #endif // INFOCENTERDOOR_H diff --git a/LEGO1/lego/legoomni/include/legocontrolmanager.h b/LEGO1/lego/legoomni/include/legocontrolmanager.h index df003f06..385ee92b 100644 --- a/LEGO1/lego/legoomni/include/legocontrolmanager.h +++ b/LEGO1/lego/legoomni/include/legocontrolmanager.h @@ -28,7 +28,7 @@ class LegoControlManager : public MxCore { void FUN_10028df0(MxPresenterList* p_presenterList); void Register(MxCore* p_listener); void Unregister(MxCore* p_listener); - void FUN_100293c0(undefined4, const MxAtomId&, undefined2); + void FUN_100293c0(undefined4, const char*, undefined2); // SYNTHETIC: LEGO1 0x10028d40 // LegoControlManager::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/policestate.h b/LEGO1/lego/legoomni/include/policestate.h index 611ced07..be55ecae 100644 --- a/LEGO1/lego/legoomni/include/policestate.h +++ b/LEGO1/lego/legoomni/include/policestate.h @@ -1,6 +1,7 @@ #ifndef POLICESTATE_H #define POLICESTATE_H +#include "decomp.h" #include "legostate.h" // VTABLE: LEGO1 0x100d8af0 @@ -24,6 +25,10 @@ class PoliceState : public LegoState { // SYNTHETIC: LEGO1 0x1005e920 // PoliceState::`scalar deleting destructor' + +private: + undefined4 m_unk0x8; // 0x8 + undefined4 m_unk0xc; // 0xc }; #endif // POLICESTATE_H diff --git a/LEGO1/lego/legoomni/src/common/gifmanager.cpp b/LEGO1/lego/legoomni/src/common/gifmanager.cpp index c83714d4..cd485b11 100644 --- a/LEGO1/lego/legoomni/src/common/gifmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/gifmanager.cpp @@ -1,32 +1,61 @@ #include "gifmanager.h" DECOMP_SIZE_ASSERT(GifData, 0x14); -DECOMP_SIZE_ASSERT(GifMapEntry, 0x14); -DECOMP_SIZE_ASSERT(GifMap, 0x08); -DECOMP_SIZE_ASSERT(GifManagerBase, 0x14); -DECOMP_SIZE_ASSERT(GifManager, 0x30); +DECOMP_SIZE_ASSERT(GifMap, 0x10); +DECOMP_SIZE_ASSERT(GifManagerBase, 0x18); +DECOMP_SIZE_ASSERT(GifManager, 0x24); -// GLOBAL: LEGO1 0x100f0100 -GifMapEntry* g_unk0x100f0100; - -// FUNCTION: LEGO1 0x10001cc0 -GifMapEntry* GifMap::FindNode(const char*& p_string) +// FUNCTION: LEGO1 0x10065c00 +GifData::~GifData() { - GifMapEntry* ret = m_unk0x4; - GifMapEntry* current = ret->m_parent; - while (current != g_unk0x100f0100) { - if (strcmp(current->m_key, p_string) <= 0) { - ret = current; - current = current->m_right; - } - else - current = current->m_left; + if (m_name) { + delete[] m_name; + m_name = NULL; + } + + if (m_palette) { + m_palette->Release(); + m_palette = NULL; + } + + if (m_surface) { + m_surface->Release(); + m_surface = NULL; + } + + if (m_texture) { + m_texture->Release(); + m_texture = NULL; } - return ret; } -// STUB: LEGO1 0x10099870 +// FUNCTION: LEGO1 0x10099870 GifManager::~GifManager() { - // TODO +} + +// FUNCTION: LEGO1 0x10099cc0 +void GifManager::FUN_10099cc0(GifData* p_data) +{ + if (p_data == NULL) + return; + +#ifdef COMPAT_MODE + GifList::iterator it; + for (it = m_list.begin(); it != m_list.end(); it++) { +#else + for (GifList::iterator it = m_list.begin(); it != m_list.end(); it++) { +#endif + if (*it == p_data) { + // TODO: This is wrong, but what is at +0xc on the iterator? + *it = NULL; + + if (p_data->m_texture->Release() == TRUE) { + delete p_data; + m_list.erase(it); + } + + return; + } + } } diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp index 64c19cd5..481bd9c5 100644 --- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -31,7 +31,7 @@ void LegoControlManager::Unregister(MxCore* p_listener) } // STUB: LEGO1 0x100293c0 -void LegoControlManager::FUN_100293c0(undefined4, const MxAtomId&, undefined2) +void LegoControlManager::FUN_100293c0(undefined4, const char*, undefined2) { } diff --git a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp index ad199882..c3d6a7a2 100644 --- a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp @@ -1,7 +1,5 @@ #include "elevatorbottom.h" -DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc) - #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" @@ -9,6 +7,8 @@ DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc) #include "mxnotificationmanager.h" #include "mxomni.h" +DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc) + // FUNCTION: LEGO1 0x10017e90 ElevatorBottom::ElevatorBottom() { @@ -43,11 +43,24 @@ MxResult ElevatorBottom::Create(MxDSAction& p_dsAction) return result; } -// STUB: LEGO1 0x10018150 +// FUNCTION: LEGO1 0x10018150 MxLong ElevatorBottom::Notify(MxParam& p_param) { - // TODO - return LegoWorld::Notify(p_param); + MxLong ret = 0; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationType17: + ret = HandleNotification17(p_param); + break; + case c_notificationTransitioned: + GameState()->HandleAction(m_unk0xf8); + break; + } + } + + return ret; } // FUNCTION: LEGO1 0x100181b0 @@ -58,6 +71,12 @@ void ElevatorBottom::VTable0x50() FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } +// STUB: LEGO1 0x100181d0 +MxLong ElevatorBottom::HandleNotification17(MxParam& p_param) +{ + return 0; +} + // FUNCTION: LEGO1 0x100182c0 void ElevatorBottom::VTable0x68(MxBool p_add) { diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp index 68090a69..5ffa3676 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -35,14 +35,14 @@ Infocenter::Infocenter() m_currentInfomainScript = c_noInfomain; m_currentCutscene = e_noIntro; - memset(&m_entries, 0, sizeof(InfocenterUnkDataEntry) * 7); + memset(&m_entries, 0, sizeof(m_entries)); m_unk0x1c8 = -1; SetAppCursor(1); NotificationManager()->Register(this); - m_unk0x1d0 = 0; - m_unk0x1d2 = 0; + m_infoManDialogueTimer = 0; + m_bookAnimationTimer = 0; m_unk0x1d4 = 0; m_unk0x1d6 = 0; } @@ -130,7 +130,7 @@ MxLong Infocenter::Notify(MxParam& p_param) break; case c_notificationTransitioned: StopBookAnimation(); - m_unk0x1d2 = 0; + m_bookAnimationTimer = 0; if (m_infocenterState->GetUnknown0x74() == 0xc) { StartCredits(); @@ -198,7 +198,7 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) return result; if (action->GetObjectId() == c_returnBackGuidanceDialogue2) { - ControlManager()->FUN_100293c0(0x10, action->GetAtomId(), 0); + ControlManager()->FUN_100293c0(0x10, action->GetAtomId().GetInternal(), 0); m_unk0x1d6 = 0; } @@ -232,7 +232,7 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) m_currentCutscene = e_noIntro; if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { - m_unk0x1d2 = 1; + m_bookAnimationTimer = 1; return 1; } break; @@ -278,7 +278,7 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) if (m_infocenterState->GetInfocenterBufferElement(0) == 0 && m_currentInfomainScript != 40 && m_currentInfomainScript != 41 && m_currentInfomainScript != 42 && m_currentInfomainScript != 43 && m_currentInfomainScript != 44) { - m_unk0x1d0 = 1; + m_infoManDialogueTimer = 1; PlayMusic(11); } @@ -299,8 +299,8 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) // STUB: LEGO1 0x1006f4e0 void Infocenter::VTable0x50() { - m_unk0x1d0 = 0; - m_unk0x1d2 = 0; + m_infoManDialogueTimer = 0; + m_bookAnimationTimer = 0; m_unk0x1d4 = 0; m_unk0x1d6 = 0; @@ -319,7 +319,7 @@ void Infocenter::VTable0x50() case 4: m_infocenterState->SetUnknown0x74(2); if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { - m_unk0x1d2 = 1; + m_bookAnimationTimer = 1; } PlayAction(c_letsGetStartedDialogue); @@ -337,7 +337,7 @@ void Infocenter::VTable0x50() return; case 0xf: if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { - m_unk0x1d2 = 1; + m_bookAnimationTimer = 1; } PlayAction(c_clickOnInfomanDialogue); @@ -383,7 +383,7 @@ MxLong Infocenter::HandleKeyPress(MxS8 p_key) m_infocenterState->SetUnknown0x74(1); if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { - m_unk0x1d2 = 1; + m_bookAnimationTimer = 1; return 1; } break; @@ -452,11 +452,43 @@ void Infocenter::VTable0x68(MxBool p_add) } } -// STUB: LEGO1 0x10070af0 +// FUNCTION: LEGO1 0x10070af0 MxResult Infocenter::Tickle() { - // TODO - return LegoWorld::Tickle(); + if (m_worldStarted == FALSE) { + LegoWorld::Tickle(); + return SUCCESS; + } + + if (m_infoManDialogueTimer != 0 && (m_infoManDialogueTimer += 100) > 25000) { + PlayAction(c_clickOnInfomanDialogue); + m_infoManDialogueTimer = 0; + } + + if (m_bookAnimationTimer != 0 && (m_bookAnimationTimer += 100) > 3000) { + PlayBookAnimation(); + m_bookAnimationTimer = 1; + } + + if (m_unk0x1d6 != 0) { + m_unk0x1d6 += 100; + + if (m_unk0x1d6 > 3400 && m_unk0x1d6 < 3650) { + ControlManager()->FUN_100293c0(0x10, m_atom.GetInternal(), 1); + } + else if (m_unk0x1d6 > 3650 && m_unk0x1d6 < 3900) { + ControlManager()->FUN_100293c0(0x10, m_atom.GetInternal(), 0); + } + else if (m_unk0x1d6 > 3900 && m_unk0x1d6 < 4150) { + ControlManager()->FUN_100293c0(0x10, m_atom.GetInternal(), 1); + } + else if (m_unk0x1d6 > 4400) { + ControlManager()->FUN_100293c0(0x10, m_atom.GetInternal(), 0); + m_unk0x1d6 = 0; + } + } + + return SUCCESS; } // FUNCTION: LEGO1 0x10070c20 diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp index 4c50a321..7ba892b4 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp @@ -1,24 +1,47 @@ #include "infocenterdoor.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" #include "legoinputmanager.h" #include "legoomni.h" +#include "mxnotificationmanager.h" -// STUB: LEGO1 0x10037730 +DECOMP_SIZE_ASSERT(InfocenterDoor, 0xfc) + +// FUNCTION: LEGO1 0x10037730 InfocenterDoor::InfocenterDoor() { - // TODO + m_unk0xf8 = 0; + + NotificationManager()->Register(this); } -// STUB: LEGO1 0x100378f0 +// FUNCTION: LEGO1 0x100378f0 InfocenterDoor::~InfocenterDoor() { - // TODO + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x10037980 +// FUNCTION: LEGO1 0x10037980 MxResult InfocenterDoor::Create(MxDSAction& p_dsAction) { - return SUCCESS; + MxResult result = LegoWorld::Create(p_dsAction); + if (result == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + SetIsWorldActive(FALSE); + + GameState()->SetUnknown424(3); + GameState()->FUN_1003a720(0); + + return result; } // STUB: LEGO1 0x100379e0 @@ -52,8 +75,10 @@ void InfocenterDoor::VTable0x68(MxBool p_add) } } -// STUB: LEGO1 0x10037cd0 +// FUNCTION: LEGO1 0x10037cd0 MxBool InfocenterDoor::VTable0x64() { + DeleteObjects(&m_atom, 500, 510); + m_unk0xf8 = 2; return TRUE; } diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp index 96e47c55..76ffd3ea 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp @@ -2,15 +2,22 @@ DECOMP_SIZE_ASSERT(InfocenterState, 0x94); -// STUB: LEGO1 0x10071600 +// FUNCTION: LEGO1 0x10071600 InfocenterState::InfocenterState() { // TODO memset(m_buffer, 0, sizeof(m_buffer)); } -// STUB: LEGO1 0x10071920 +// FUNCTION: LEGO1 0x10071920 InfocenterState::~InfocenterState() { - // TODO + MxS16 i = 0; + do { + if (GetInfocenterBufferElement(i) != NULL) { + delete GetInfocenterBufferElement(i)->GetAction(); + delete GetInfocenterBufferElement(i); + } + i++; + } while (i < GetInfocenterBufferSize()); } diff --git a/LEGO1/lego/legoomni/src/infocenter/score.cpp b/LEGO1/lego/legoomni/src/infocenter/score.cpp index c1bba3e6..5a7a95a3 100644 --- a/LEGO1/lego/legoomni/src/infocenter/score.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/score.cpp @@ -227,8 +227,7 @@ void Score::VTable0x68(MxBool p_add) // FUNCTION: LEGO1 0x100019d0 void Score::Paint() { - GifManager* gm = GetGifManager(); - GifData* gd = gm->Get("bigcube.gif"); + GifData* gd = GetGifManager()->Get("bigcube.gif"); if (gd) { RaceState* l78 = (RaceState*) GameState()->GetState("JetskiRaceState"); diff --git a/LEGO1/lego/legoomni/src/police/policestate.cpp b/LEGO1/lego/legoomni/src/police/policestate.cpp index a2c66a45..4965a36f 100644 --- a/LEGO1/lego/legoomni/src/police/policestate.cpp +++ b/LEGO1/lego/legoomni/src/police/policestate.cpp @@ -1,7 +1,12 @@ #include "policestate.h" -// STUB: LEGO1 0x1005e7c0 +#include + +DECOMP_SIZE_ASSERT(PoliceState, 0x10) + +// FUNCTION: LEGO1 0x1005e7c0 PoliceState::PoliceState() { - // TODO + m_unk0xc = 0; + m_unk0x8 = (rand() % 2 == 0) ? 501 : 500; } diff --git a/LEGO1/library_flic.h b/LEGO1/library_flic.h new file mode 100644 index 00000000..1c6a6d8b --- /dev/null +++ b/LEGO1/library_flic.h @@ -0,0 +1,6 @@ +#ifdef 0 + +// LIBRARY: LEGO1 0x100bdce0 +// _DecodeFLCFrame + +#endif diff --git a/LEGO1/library_smack.h b/LEGO1/library_smack.h new file mode 100644 index 00000000..2909ebd3 --- /dev/null +++ b/LEGO1/library_smack.h @@ -0,0 +1,18 @@ +#ifdef 0 + +// LIBRARY: LEGO1 0x100cd782 +// _SmackGetSizeTables + +// LIBRARY: LEGO1 0x100cd7e8 +// _SmackDoTables + +// LIBRARY: LEGO1 0x100cda83 +// _SmackDoFrameToBuffer + +// LIBRARY: LEGO1 0x100d052c +// _SmackGetSizeDeltas + +// LIBRARY: LEGO1 0x100d0543 +// _SmackGetRect + +#endif diff --git a/LEGO1/omni/include/mxomni.h b/LEGO1/omni/include/mxomni.h index 52faf709..9ade97b3 100644 --- a/LEGO1/omni/include/mxomni.h +++ b/LEGO1/omni/include/mxomni.h @@ -57,7 +57,7 @@ class MxOmni : public MxCore { virtual MxBool IsTimerRunning() { return m_timerRunning; }; // vtable+40 static void SetInstance(MxOmni* p_instance); - static MxBool FUN_100b06b0(MxDSAction* p_action, const char* p_name); + static MxBool ActionSourceEquals(MxDSAction* p_action, const char* p_name); HWND GetWindowHandle() const { return this->m_windowHandle; } MxObjectFactory* GetObjectFactory() const { return this->m_objectFactory; } diff --git a/LEGO1/omni/include/mxsmack.h b/LEGO1/omni/include/mxsmack.h index e0f8c76e..227dbd6d 100644 --- a/LEGO1/omni/include/mxsmack.h +++ b/LEGO1/omni/include/mxsmack.h @@ -12,10 +12,7 @@ // but present in SMACK.LIB and used directly by Mindscape. extern "C" { - // (SMACK.LIB) FUNCTION: LEGO1 0x100cd782 u32 SmackGetSizeTables(); - - // (SMACK.LIB) FUNCTION: LEGO1 0x100cd7e8 void SmackDoTables( u8* p_huffmanTrees, u8* p_huffmanTables, @@ -24,14 +21,8 @@ extern "C" u32 p_detailSize, u32 p_typeSize ); - - // (SMACK.LIB) FUNCTION: LEGO1 0x100cda83 void SmackDoFrameToBuffer(u8* p_source, u8* p_huffmanTables, u8* p_unk0x6b4); - - // (SMACK.LIB) FUNCTION: LEGO1 0x100d052c u32 SmackGetSizeDeltas(u32 p_width, u32 p_height); - - // (SMACK.LIB) FUNCTION: LEGO1 0x100d0543 u8 SmackGetRect(u8* p_unk0x6b4, u32* p_rect); } diff --git a/LEGO1/omni/src/main/mxomni.cpp b/LEGO1/omni/src/main/mxomni.cpp index 6df6d009..f9fa5733 100644 --- a/LEGO1/omni/src/main/mxomni.cpp +++ b/LEGO1/omni/src/main/mxomni.cpp @@ -3,6 +3,7 @@ #include "mxactionnotificationparam.h" #include "mxatomidcounter.h" #include "mxautolocker.h" +#include "mxdsmultiaction.h" #include "mxeventmanager.h" #include "mxmusicmanager.h" #include "mxnotificationmanager.h" @@ -377,11 +378,23 @@ void MxOmni::DestroyInstance() } } -// STUB: LEGO1 0x100b06b0 -MxBool MxOmni::FUN_100b06b0(MxDSAction* p_action, const char* p_name) +// FUNCTION: LEGO1 0x100b06b0 +MxBool MxOmni::ActionSourceEquals(MxDSAction* p_action, const char* p_name) { - // TODO - return FAILURE; + if (!strcmp(p_action->GetSourceName(), p_name)) + return TRUE; + + if (p_action->IsA("MxDSMultiAction")) { + MxDSActionListCursor cursor(((MxDSMultiAction*) p_action)->GetActionList()); + MxDSAction* action; + + while (cursor.Next(action)) { + if (ActionSourceEquals(action, p_name)) + return TRUE; + } + } + + return FALSE; } // FUNCTION: LEGO1 0x100b07f0 @@ -404,7 +417,7 @@ MxLong MxOmni::HandleActionEnd(MxParam& p_param) if (controller != NULL) { action = controller->GetUnk0x54().Find(action, FALSE); if (action) { - if (FUN_100b06b0(action, "LegoLoopingAnimPresenter") == FALSE) { + if (ActionSourceEquals(action, "LegoLoopingAnimPresenter") == FALSE) { delete controller->GetUnk0x54().Find(action, TRUE); } } diff --git a/tools/README.md b/tools/README.md index da23d84c..b24a8f50 100644 --- a/tools/README.md +++ b/tools/README.md @@ -58,7 +58,7 @@ Templated functions should be annotated with `TEMPLATE`. Since the goal is to ev ### `SYNTHETIC` -Synthetic functions should be annotated with `SYNTHETIC`. A synthetic function is generated by the compiler; for the time being, the only case is the "scalar deleting destructor" found in virtual tables. Note: `SYNTHETIC` takes precedence over `TEMPLATE`. +Synthetic functions should be annotated with `SYNTHETIC`. A synthetic function is generated by the compiler; most common is the "scalar deleting destructor" found in virtual tables. Other cases include default destructors and assignment operators. Note: `SYNTHETIC` takes precedence over `TEMPLATE`. ``` // SYNTHETIC: LEGO1 0x10003210 @@ -71,7 +71,22 @@ Synthetic functions should be annotated with `SYNTHETIC`. A synthetic function i // MxList::`scalar deleting destructor' ``` -## Virtual tables (**WIP**) +### `LIBRARY` + +Functions located in 3rd party libraries should be annotated with `LIBRARY`. Since the goal is to eventually have a full accounting of all the functions present in the binaries, please make an effort to find and annotate every function of every statically linked library, including the MSVC standard libraries. + +``` +// LIBRARY: ISLE 0x4061b0 +// _MemPoolInit@4 + +// LIBRARY: ISLE 0x406520 +// _MemPoolSetPageSize@8 + +// LIBRARY: ISLE 0x406630 +// _MemPoolSetBlockSizeFS@8 +``` + +## Virtual tables Classes with a virtual table should be annotated using the `VTABLE` marker, which includes the module name and address of the virtual table. Additionally, virtual function declarations should be annotated with a comment indicating their relative offset. Please use the following example as a reference. @@ -112,7 +127,7 @@ private: undefined4 m_unk0x14; // 0x14 ``` -## Global variables (**WIP**) +## Global variables Global variables should be annotated using the `GLOBAL` marker, which includes the module name and address of the variable. @@ -127,6 +142,18 @@ MxAtomId* g_pz5Script = NULL; MxAtomId* g_introScript = NULL; ``` +## Strings + +String values should be annotated using the `STRING` marker, which includes the module name and address of the string. + +``` +inline virtual const char* ClassName() const override // vtable+0x0c +{ + // STRING: LEGO1 0x100f03fc + return "Act2PoliceStation"; +} +``` + # Tooling Use `pip` to install the required packages to be able to use the Python tools found in this folder: diff --git a/tools/isledecomp/isledecomp/compare/db.py b/tools/isledecomp/isledecomp/compare/db.py index dea2b590..43d6811b 100644 --- a/tools/isledecomp/isledecomp/compare/db.py +++ b/tools/isledecomp/isledecomp/compare/db.py @@ -170,6 +170,12 @@ def skip_compare(self, orig: int): def _match_on(self, compare_type: SymbolType, addr: int, name: str) -> bool: # Update the compare_type here too since the marker tells us what we should do + + # Truncate the name to 255 characters. It will not be possible to match a name + # longer than that because MSVC truncates the debug symbols to this length. + # See also: warning C4786. + name = name[:255] + logger.debug("Looking for %s %s", compare_type.name.lower(), name) cur = self._db.execute( """UPDATE `symbols`