From f3c1fc75e226fa9ab38bbb6249ca8664f0f7200a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 24 Dec 2023 18:09:01 -0500 Subject: [PATCH 01/50] Mostly match MxDSBuffer::AllocateBuffer --- LEGO1/mxdsbuffer.cpp | 63 +++++++++++++++++++++----------------------- LEGO1/mxstreamer.h | 2 +- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/LEGO1/mxdsbuffer.cpp b/LEGO1/mxdsbuffer.cpp index 634afc6e..0060dbdc 100644 --- a/LEGO1/mxdsbuffer.cpp +++ b/LEGO1/mxdsbuffer.cpp @@ -45,68 +45,65 @@ MxDSBuffer::~MxDSBuffer() MxResult MxDSBuffer::AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode) { MxResult result = FAILURE; - MxU32 i = 0; - if (p_mode == MxDSBufferType_Allocate) { - m_pBuffer = new MxU8[p_bufferSize]; - } - else if (p_mode == MxDSBufferType_Chunk) { - MxStreamer* streamer = Streamer(); - // I have no clue as to what this does, or even if its correct. Maybe it's related to storing chunks in - // MxDiskStreamController? - if (p_bufferSize >> 10 == 0x40) { - i = 0; - while (i < 22) { - if ((*(MxU32*) ((streamer->GetSubclass1().GetUnk08() + ((i & 0xffffffe7) >> 3)) & 1 << ((MxU8) i & 0x1f) - )) == 0) { - MxU32* ptr = (MxU32*) ((streamer->GetSubclass1().GetUnk08() + ((i & 0xffffffe7) >> 3)) & - 1 << ((MxU8) i & 0x1f)); - // mark it as used? + switch (p_mode) { + case MxDSBufferType_Allocate: + m_pBuffer = new MxU8[p_bufferSize]; + break; + + case MxDSBufferType_Chunk: { + MxStreamer* streamer = Streamer(); + + switch (p_bufferSize / 1024) { + case 0x40: { + for (MxU32 i = 0; i < 22; i++) { + if (((1 << (i & 0x1f)) & (*(MxU32*) &streamer->GetSubclass1().GetUnk08Ref()[(i & ~0x18u) >> 3])) == 0) { + MxU32* ptr = (MxU32*) &streamer->GetSubclass1().GetUnk08Ref()[(i & 0xffffffe7) >> 3]; + *ptr = *ptr ^ 1 << (i & 0x1f); m_pBuffer = (MxU8*) (streamer->GetSubclass1().GetSize() * i * 0x400 + streamer->GetSubclass1().GetBuffer()); - break; + goto done; } - i++; } m_pBuffer = NULL; + break; } - else if (p_bufferSize >> 10 == 0x80) { - i = 0; - // Same thing as above but it uses subclass2 - while (i < 22) { - if ((*(MxU32*) ((streamer->GetSubclass2().GetUnk08() + ((i & 0xffffffe7) >> 3)) & 1 << ((MxU8) i & 0x1f) - )) == 0) { - MxU32* ptr = (MxU32*) ((streamer->GetSubclass2().GetUnk08() + ((i & 0xffffffe7) >> 3)) & - 1 << ((MxU8) i & 0x1f)); + case 0x80: { + for (MxU32 i = 0; i < 2; i++) { + if (((1 << (i & 0x1f)) & (*(MxU32*) &streamer->GetSubclass2().GetUnk08Ref()[(i & ~0x18u) >> 3])) == 0) { + MxU32* ptr = (MxU32*) &streamer->GetSubclass2().GetUnk08Ref()[(i & 0xffffffe7) >> 3]; - // mark it as used? *ptr = *ptr ^ 1 << (i & 0x1f); m_pBuffer = (MxU8*) (streamer->GetSubclass2().GetSize() * i * 0x400 + streamer->GetSubclass2().GetBuffer()); - break; + goto done; } - i++; } m_pBuffer = NULL; + break; } - else { - m_pIntoBuffer = NULL; + default: + m_pBuffer = NULL; } } + } +done: m_pIntoBuffer = m_pBuffer; m_pIntoBuffer2 = m_pBuffer; + if (m_pBuffer != NULL) { m_mode = p_mode; m_bytesRemaining = p_bufferSize; m_writeOffset = p_bufferSize; result = SUCCESS; } + return result; } @@ -221,8 +218,8 @@ MxResult MxDSBuffer::ParseChunk( // FUNCTION: LEGO1 0x100c6d00 MxCore* MxDSBuffer::ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags) { - // This function reads a chunk. If it is an object, this function returns an MxDSObject. If it is a chunk, returns a - // MxDSChunk. + // This function reads a chunk. If it is an object, this function returns an MxDSObject. If it is a chunk, + // returns a MxDSChunk. MxCore* result = NULL; MxU8* dataStart = (MxU8*) p_chunkData + 8; diff --git a/LEGO1/mxstreamer.h b/LEGO1/mxstreamer.h index 3b58b260..8017e898 100644 --- a/LEGO1/mxstreamer.h +++ b/LEGO1/mxstreamer.h @@ -22,7 +22,7 @@ class MxStreamerSubClass1 { void SetBuffer(undefined* p_buf) { m_buffer = p_buf; } inline undefined* GetBuffer() const { return m_buffer; } - inline undefined4 GetUnk08() const { return m_unk0x08; } + inline undefined* GetUnk08Ref() const { return (undefined*) &m_unk0x08; } private: undefined* m_buffer; From cb8c143ce50c147ff5bdcb67aa64a3e77a6560bf Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Mon, 25 Dec 2023 13:32:01 -0500 Subject: [PATCH 02/50] Finish MxDiskStreamController methods (#359) * more mxdiskstreamcontroller methods * further debugging and fixes * add more functions * Update mxdiskstreamprovider.cpp * fix build * implement MxDiskStreamProvider::PerformWork * Update mxdiskstreamprovider.cpp * Update mxdiskstreamprovider.cpp * Update mxdssource.h * remove debug prints * Update mxdiskstreamprovider.cpp * Mostly match MxDiskStreamController::FUN_100c8540 * Mostly match MxDiskStreamProvider::FUN_100d1780 * Mostly match MxDiskStreamProvider::PerformWork * Fixes * Retype some members * Various annotations --------- Co-authored-by: Christian Semmler --- LEGO1/legosoundmanager.cpp | 2 +- LEGO1/mxcriticalsection.h | 4 +- LEGO1/mxdiskstreamcontroller.cpp | 107 ++++++++++++++++++++++++-- LEGO1/mxdiskstreamcontroller.h | 10 ++- LEGO1/mxdiskstreamprovider.cpp | 127 ++++++++++++++++++++++++++++--- LEGO1/mxdiskstreamprovider.h | 11 +-- LEGO1/mxdsbuffer.cpp | 6 +- LEGO1/mxdsbuffer.h | 7 +- LEGO1/mxdssource.cpp | 6 +- LEGO1/mxdssource.h | 26 ++++--- LEGO1/mxdsstreamingaction.h | 2 + LEGO1/mxnextactiondatastart.h | 8 +- LEGO1/mxsemaphore.cpp | 4 + LEGO1/mxsemaphore.h | 3 +- LEGO1/mxstreamcontroller.cpp | 1 + LEGO1/mxstreamcontroller.h | 1 + LEGO1/mxstreamlist.h | 14 +++- LEGO1/mxstreamprovider.h | 4 +- LEGO1/mxthread.cpp | 4 + LEGO1/mxthread.h | 18 ++--- 20 files changed, 301 insertions(+), 64 deletions(-) diff --git a/LEGO1/legosoundmanager.cpp b/LEGO1/legosoundmanager.cpp index a74ca419..8b8376fa 100644 --- a/LEGO1/legosoundmanager.cpp +++ b/LEGO1/legosoundmanager.cpp @@ -29,7 +29,7 @@ void LegoSoundManager::Destroy(MxBool p_fromDestructor) // STUB: LEGO1 0x100299f0 MxResult LegoSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) { - return FAILURE; + return SUCCESS; } // FUNCTION: LEGO1 0x1002a390 diff --git a/LEGO1/mxcriticalsection.h b/LEGO1/mxcriticalsection.h index 8756853c..8c5f77d6 100644 --- a/LEGO1/mxcriticalsection.h +++ b/LEGO1/mxcriticalsection.h @@ -13,8 +13,8 @@ class MxCriticalSection { void Leave(); private: - CRITICAL_SECTION m_criticalSection; - HANDLE m_mutex; + CRITICAL_SECTION m_criticalSection; // 0x00 + HANDLE m_mutex; // 0x18 }; #endif // MXCRITICALSECTION_H diff --git a/LEGO1/mxdiskstreamcontroller.cpp b/LEGO1/mxdiskstreamcontroller.cpp index 71ebc827..1520ba3b 100644 --- a/LEGO1/mxdiskstreamcontroller.cpp +++ b/LEGO1/mxdiskstreamcontroller.cpp @@ -1,5 +1,6 @@ #include "mxdiskstreamcontroller.h" +#include "mxactionnotificationparam.h" #include "mxautolocker.h" #include "mxdiskstreamprovider.h" #include "mxdsstreamingaction.h" @@ -52,12 +53,31 @@ MxResult MxDiskStreamController::VTable0x18(undefined4, undefined4) return SUCCESS; } +// FUNCTION: LEGO1 0x100c7890 +MxResult MxDiskStreamController::FUN_100c7890(MxDSStreamingAction* p_action) +{ + MxAutoLocker lock(&this->m_criticalSection); + if (p_action == NULL) { + return FAILURE; + } + + m_list0x80.push_back(p_action); + FUN_100c7970(); + return SUCCESS; +} + // FUNCTION: LEGO1 0x100c7960 MxResult MxDiskStreamController::VTable0x34(undefined4) { return FAILURE; } +// FUNCTION: LEGO1 0x100c7970 +void MxDiskStreamController::FUN_100c7970() +{ + // Empty +} + // FUNCTION: LEGO1 0x100c7980 void MxDiskStreamController::FUN_100c7980() { @@ -181,10 +201,29 @@ MxResult MxDiskStreamController::FUN_100c7d10() return SUCCESS; } -// STUB: LEGO1 0x100c7db0 +// FUNCTION: LEGO1 0x100c7db0 MxDSStreamingAction* MxDiskStreamController::FUN_100c7db0() { - // TODO + MxAutoLocker lock(&this->m_criticalSection); + + for (MxStreamListMxNextActionDataStart::iterator it = m_nextActionList.begin(); it != m_nextActionList.end(); + it++) { + MxNextActionDataStart* data = *it; + for (MxStreamListMxDSAction::iterator it2 = m_list0x64.begin(); it2 != m_list0x64.end(); it2++) { + MxDSStreamingAction* streamingAction = (MxDSStreamingAction*) *it2; + if (streamingAction->GetObjectId() == data->GetObjectId() && + streamingAction->GetUnknown24() == data->GetUnknown24() && + streamingAction->GetBufferOffset() == data->GetData()) { + m_nextActionList.erase(it); + + data->SetData(m_provider->GetFileSize() + data->GetData()); + m_nextActionList.push_back(data); + + m_list0x64.erase(it2); + return streamingAction; + } + } + } return NULL; } @@ -203,7 +242,6 @@ MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) MxAutoLocker lock(&this->m_criticalSection); MxDSStreamingAction* entry = (MxDSStreamingAction*) m_list0x80.Find(p_action, FALSE); // TODO: is this a seperate class? - if (entry) { MxDSStreamingAction* action = new MxDSStreamingAction(*p_action, 0); action->SetUnknown28(entry->GetUnknown28()); @@ -224,11 +262,39 @@ MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) return SUCCESS; } -// STUB: LEGO1 0x100c8160 +// FUNCTION: LEGO1 0x100c8160 MxResult MxDiskStreamController::VTable0x24(MxDSAction* p_action) { - // TODO - return FAILURE; + MxAutoLocker lock(&this->m_criticalSection); + if (m_unk0x54.Find(p_action, FALSE) == NULL) { + if (VTable0x30(p_action) == SUCCESS) { + MxOmni::GetInstance()->NotifyCurrentEntity( + &MxEndActionNotificationParam(c_notificationEndAction, NULL, p_action, TRUE) + ); + } + } + + MxDSAction action; + if (m_provider) { + m_provider->VTable0x20(p_action); + } + + do { + if (m_action0x60 != NULL) { + delete m_action0x60; + m_action0x60 = NULL; + } + + action = *p_action; + MxStreamController::VTable0x24(&action); + } while (m_action0x60 != NULL); + + if (m_unk0x3c.size() == 0) { + m_unk0x70 = 0; + m_unk0xc4 = 0; + } + + return SUCCESS; } // FUNCTION: LEGO1 0x100c8360 @@ -269,10 +335,28 @@ void MxDiskStreamController::InsertToList74(MxDSBuffer* p_buffer) m_list0x74.push_back(p_buffer); } -// STUB: LEGO1 0x100c8540 +// FUNCTION: LEGO1 0x100c8540 void MxDiskStreamController::FUN_100c8540() { - // TODO + MxAutoLocker lock(&this->m_criticalSection); + for (list::iterator it = m_list0x74.begin(); it != m_list0x74.end();) { + MxDSBuffer* buf = *it; + // TODO: Match + if (buf->GetRefCount() == 0) { + m_list0x74.erase(it++); + FUN_100c7ce0(buf); + } + else + it++; + } + + if (m_nextActionList.empty()) { + while (!m_list0x64.empty()) { + MxDSStreamingAction* action = (MxDSStreamingAction*) m_list0x64.front(); + m_list0x64.pop_front(); + FUN_100c7cb0(action); + } + } } // FUNCTION: LEGO1 0x100c8640 @@ -292,6 +376,13 @@ MxResult MxDiskStreamController::Tickle() return SUCCESS; } +// FUNCTION: LEGO1 0x100c8670 +void MxDiskStreamController::FUN_100c8670(MxDSStreamingAction* p_streamingAction) +{ + MxAutoLocker lock(&this->m_critical9c); + m_list0xb8.push_back(p_streamingAction); +} + // FUNCTION: LEGO1 0x100c8720 void MxDiskStreamController::FUN_100c8720() { diff --git a/LEGO1/mxdiskstreamcontroller.h b/LEGO1/mxdiskstreamcontroller.h index 1d1cf7d5..28966d9d 100644 --- a/LEGO1/mxdiskstreamcontroller.h +++ b/LEGO1/mxdiskstreamcontroller.h @@ -39,6 +39,11 @@ class MxDiskStreamController : public MxStreamController { return !strcmp(p_name, MxDiskStreamController::ClassName()) || MxStreamController::IsA(p_name); } + inline MxBool GetUnk0xc4() const { return m_unk0xc4; } + + void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); + void FUN_100c8670(MxDSStreamingAction* p_streamingAction); + private: MxStreamListMxDSAction m_list0x64; // 0x64 undefined m_unk0x70; // 0x70 @@ -48,14 +53,15 @@ class MxDiskStreamController : public MxStreamController { MxStreamListMxDSAction m_list0x90; // 0x90 MxCriticalSection m_critical9c; // 0x9c MxStreamListMxDSAction m_list0xb8; // 0xb8 - undefined m_unk0xc4; // 0xc4 + MxBool m_unk0xc4; // 0xc4 + MxResult FUN_100c7890(MxDSStreamingAction* p_action); + void FUN_100c7970(); void FUN_100c7cb0(MxDSStreamingAction* p_action); void FUN_100c7ce0(MxDSBuffer* p_buffer); MxResult FUN_100c7d10(); void FUN_100c7980(); MxDSStreamingAction* FUN_100c7db0(); - void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); MxResult FUN_100c8360(MxDSStreamingAction* p_action); void InsertToList74(MxDSBuffer* p_buffer); void FUN_100c8540(); diff --git a/LEGO1/mxdiskstreamprovider.cpp b/LEGO1/mxdiskstreamprovider.cpp index a8d15984..c7e311eb 100644 --- a/LEGO1/mxdiskstreamprovider.cpp +++ b/LEGO1/mxdiskstreamprovider.cpp @@ -1,13 +1,20 @@ #include "mxdiskstreamprovider.h" +#include "mxautolocker.h" +#include "mxdiskstreamcontroller.h" #include "mxdsbuffer.h" +#include "mxdsstreamingaction.h" #include "mxomni.h" #include "mxstreamcontroller.h" #include "mxstring.h" #include "mxthread.h" +DECOMP_SIZE_ASSERT(MxDiskStreamProviderThread, 0x1c) DECOMP_SIZE_ASSERT(MxDiskStreamProvider, 0x60); +// GLOBAL: LEGO1 0x10102878 +MxU32 g_unk0x10102878 = 0; + // FUNCTION: LEGO1 0x100d0f30 MxResult MxDiskStreamProviderThread::Run() { @@ -29,8 +36,8 @@ MxResult MxDiskStreamProviderThread::StartWithTarget(MxDiskStreamProvider* p_tar MxDiskStreamProvider::MxDiskStreamProvider() { this->m_pFile = NULL; - this->m_remainingWork = 0; - this->m_unk0x35 = 0; + this->m_remainingWork = FALSE; + this->m_unk0x35 = FALSE; } // STUB: LEGO1 0x100d1240 @@ -58,7 +65,7 @@ MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource) goto done; } - m_remainingWork = 1; + m_remainingWork = TRUE; m_busySemaphore.Init(0, 100); if (m_thread.StartWithTarget(this) == SUCCESS && p_resource != NULL) { @@ -79,25 +86,125 @@ void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) // FUNCTION: LEGO1 0x100d1750 MxResult MxDiskStreamProvider::WaitForWorkToComplete() { - while (m_remainingWork != 0) { + while (m_remainingWork) { m_busySemaphore.Wait(INFINITE); - if (m_unk0x35 != 0) + if (m_unk0x35) PerformWork(); } + return SUCCESS; } -// STUB: LEGO1 0x100d1780 +// FUNCTION: LEGO1 0x100d1780 MxResult MxDiskStreamProvider::FUN_100d1780(MxDSStreamingAction* p_action) { - // TODO - return FAILURE; + if (!m_remainingWork) + return FAILURE; + + if (p_action->GetUnknown9c() > 0 && !p_action->GetUnknowna0()) { + MxDSBuffer* buffer = new MxDSBuffer(); + + if (!buffer) + return FAILURE; + + if (buffer->AllocateBuffer(GetFileSize(), MxDSBufferType_Allocate) != SUCCESS) { + delete buffer; + return FAILURE; + } + + p_action->SetUnknowna0(buffer); + } + + if (p_action->GetUnknowna0()->GetWriteOffset() < 0x20000) { + g_unk0x10102878++; + } + + { + MxAutoLocker lock(&m_criticalSection); + m_list.push_back(p_action); + } + + m_unk0x35 = TRUE; + m_busySemaphore.Release(1); + return SUCCESS; } -// STUB: LEGO1 0x100d18f0 +// FUNCTION: LEGO1 0x100d18f0 void MxDiskStreamProvider::PerformWork() { - // TODO + MxDiskStreamController* controller = (MxDiskStreamController*) m_pLookup; + MxDSStreamingAction* streamingAction = NULL; + + { + MxAutoLocker lock(&m_criticalSection); + if (!m_list.empty()) { + streamingAction = (MxDSStreamingAction*) m_list.front(); + + if (streamingAction && !FUN_100d1af0(streamingAction)) { + m_thread.Sleep(500); + m_busySemaphore.Release(1); + return; + } + } + } + + { + MxAutoLocker lock(&m_criticalSection); + + if (!m_list.PopFrontStreamingAction(streamingAction)) + return; + } + + if (streamingAction->GetUnknowna0()->GetWriteOffset() < 0x20000) { + g_unk0x10102878--; + } + + MxDSBuffer* buffer = streamingAction->GetUnknowna0(); + + if (m_pFile->GetPosition() == streamingAction->GetBufferOffset() || + m_pFile->Seek(streamingAction->GetBufferOffset(), 0) == 0) { + buffer->SetUnknown14(m_pFile->GetPosition()); + + if (m_pFile->ReadToBuffer(buffer) == SUCCESS) { + buffer->SetUnknown1c(m_pFile->GetPosition()); + + if (streamingAction->GetUnknown9c() > 0) { + FUN_100d1b20(streamingAction); + } + else { + if (m_pLookup == NULL || !((MxDiskStreamController*) m_pLookup)->GetUnk0xc4()) { + controller->FUN_100c8670(streamingAction); + } + else { + controller->FUN_100c7f40(streamingAction); + } + } + + streamingAction = NULL; + } + } + + if (streamingAction) { + controller->FUN_100c8670(streamingAction); + } + + m_thread.Sleep(0); +} + +// FUNCTION: LEGO1 0x100d1af0 +MxBool MxDiskStreamProvider::FUN_100d1af0(MxDSStreamingAction* p_action) +{ + if (p_action->GetUnknowna0()->GetWriteOffset() == 0x20000) { + return g_unk0x10102878 == 0; + } + + return TRUE; +} + +// STUB: LEGO1 0x100d1b20 +MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) +{ + return FAILURE; } // FUNCTION: LEGO1 0x100d1e90 diff --git a/LEGO1/mxdiskstreamprovider.h b/LEGO1/mxdiskstreamprovider.h index 55d4f0f2..bc73c0e4 100644 --- a/LEGO1/mxdiskstreamprovider.h +++ b/LEGO1/mxdiskstreamprovider.h @@ -13,21 +13,20 @@ class MxDiskStreamProvider; class MxDSStreamingAction; // VTABLE: LEGO1 0x100dd130 +// SIZE 0x1c class MxDiskStreamProviderThread : public MxThread { public: - // Only inlined, no offset inline MxDiskStreamProviderThread() : MxThread() { m_target = NULL; } MxResult Run() override; - MxResult StartWithTarget(MxDiskStreamProvider* p_target); }; // VTABLE: LEGO1 0x100dd138 +// SIZE 0x60 class MxDiskStreamProvider : public MxStreamProvider { public: MxDiskStreamProvider(); - virtual ~MxDiskStreamProvider() override; // FUNCTION: LEGO1 0x100d1160 @@ -46,6 +45,8 @@ class MxDiskStreamProvider : public MxStreamProvider { MxResult WaitForWorkToComplete(); MxResult FUN_100d1780(MxDSStreamingAction* p_action); void PerformWork(); + static MxBool FUN_100d1af0(MxDSStreamingAction* p_action); + MxResult FUN_100d1b20(MxDSStreamingAction* p_action); virtual MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14 virtual MxU32 GetFileSize() override; // vtable+0x18 @@ -57,8 +58,8 @@ class MxDiskStreamProvider : public MxStreamProvider { private: MxDiskStreamProviderThread m_thread; // 0x10 MxSemaphore m_busySemaphore; // 0x2c - undefined m_remainingWork; // 0x34 - undefined m_unk0x35; // 0x35 + MxBool m_remainingWork; // 0x34 + MxBool m_unk0x35; // 0x35 MxCriticalSection m_criticalSection; // 0x38 MxStreamListMxDSAction m_list; // 0x54 }; diff --git a/LEGO1/mxdsbuffer.cpp b/LEGO1/mxdsbuffer.cpp index 0060dbdc..b9908558 100644 --- a/LEGO1/mxdsbuffer.cpp +++ b/LEGO1/mxdsbuffer.cpp @@ -135,7 +135,7 @@ MxResult MxDSBuffer::CreateObject( MxStreamController* p_controller, MxU32* p_data, MxDSAction* p_action, - undefined4 p_undefined + MxDSStreamingAction** p_streamingAction ) { if (p_data == NULL) { @@ -157,7 +157,7 @@ MxResult MxDSBuffer::CreateObject( return SUCCESS; } - return ParseChunk(p_controller, p_data, p_action, p_undefined, chunk); + return ParseChunk(p_controller, p_data, p_action, p_streamingAction, chunk); } delete header; @@ -207,7 +207,7 @@ MxResult MxDSBuffer::ParseChunk( MxStreamController* p_controller, MxU32* p_data, MxDSAction* p_action, - undefined4, + MxDSStreamingAction** p_streamingAction, MxStreamChunk* p_header ) { diff --git a/LEGO1/mxdsbuffer.h b/LEGO1/mxdsbuffer.h index d8532a55..ac003711 100644 --- a/LEGO1/mxdsbuffer.h +++ b/LEGO1/mxdsbuffer.h @@ -42,17 +42,18 @@ class MxDSBuffer : public MxCore { MxStreamController* p_controller, MxU32* p_data, MxDSAction* p_action, - undefined4 p_undefined + MxDSStreamingAction** p_streamingAction ); MxResult StartPresenterFromAction(MxStreamController* p_controller, MxDSAction* p_action1, MxDSAction* p_action2); MxResult ParseChunk( MxStreamController* p_controller, MxU32* p_data, MxDSAction* p_action, - undefined4, + MxDSStreamingAction** p_streamingAction, MxStreamChunk* p_header ); static MxCore* ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags); + void SwapBuffers(); MxU8 ReleaseRef(MxDSChunk*); void AddRef(MxDSChunk* p_chunk); void FUN_100c6f80(MxU32 p_writeOffset); @@ -61,6 +62,8 @@ class MxDSBuffer : public MxCore { inline MxU32 GetWriteOffset() { return m_writeOffset; } inline MxU16 GetRefCount() { return m_refcount; } inline MxDSBufferType GetMode() { return m_mode; } + inline void SetUnknown14(undefined4 p_unk0x14) { m_unk0x14 = p_unk0x14; } + inline void SetUnknown1c(undefined4 p_unk0x1c) { m_unk0x1c = p_unk0x1c; } private: MxU8* m_pBuffer; // 0x08 diff --git a/LEGO1/mxdssource.cpp b/LEGO1/mxdssource.cpp index c38799d3..c2d86abb 100644 --- a/LEGO1/mxdssource.cpp +++ b/LEGO1/mxdssource.cpp @@ -2,10 +2,12 @@ #include "mxdsbuffer.h" +DECOMP_SIZE_ASSERT(MxDSSource, 0x14) + // FUNCTION: LEGO1 0x100bffd0 -void MxDSSource::ReadToBuffer(MxDSBuffer* p_buffer) +MxResult MxDSSource::ReadToBuffer(MxDSBuffer* p_buffer) { - Read(p_buffer->GetBuffer(), p_buffer->GetWriteOffset()); + return Read(p_buffer->GetBuffer(), p_buffer->GetWriteOffset()); } // FUNCTION: LEGO1 0x100bfff0 diff --git a/LEGO1/mxdssource.h b/LEGO1/mxdssource.h index 724efca5..711ba110 100644 --- a/LEGO1/mxdssource.h +++ b/LEGO1/mxdssource.h @@ -6,6 +6,7 @@ class MxDSBuffer; // VTABLE: LEGO1 0x100dc8c8 +// SIZE 0x14 class MxDSSource : public MxCore { public: MxDSSource() : m_lengthInDWords(0), m_pBuffer(NULL), m_position(-1) {} @@ -23,20 +24,21 @@ class MxDSSource : public MxCore { return !strcmp(p_name, MxDSSource::ClassName()) || MxCore::IsA(p_name); } - virtual MxLong Open(MxULong) = 0; - virtual MxLong Close() = 0; - virtual void ReadToBuffer(MxDSBuffer* p_buffer); - virtual MxResult Read(unsigned char*, MxULong) = 0; - virtual MxLong Seek(MxLong, int) = 0; - virtual MxULong GetBufferSize() = 0; - virtual MxULong GetStreamBuffersNum() = 0; - virtual MxLong GetLengthInDWords(); - virtual MxU32* GetBuffer(); // 0x34 + virtual MxLong Open(MxULong) = 0; // vtable+0x14 + virtual MxLong Close() = 0; // vtable+0x18 + virtual MxResult ReadToBuffer(MxDSBuffer* p_buffer); // vtable+0x1c + virtual MxResult Read(unsigned char*, MxULong) = 0; // vtable+0x20 + virtual MxLong Seek(MxLong, int) = 0; // vtable+0x24 + virtual MxULong GetBufferSize() = 0; // vtable+0x28 + virtual MxULong GetStreamBuffersNum() = 0; // vtable+0x2c + virtual MxLong GetLengthInDWords(); // vtable+0x30 + virtual MxU32* GetBuffer(); // vtable+0x34 + inline MxLong GetPosition() const { return m_position; } protected: - MxULong m_lengthInDWords; - MxU32* m_pBuffer; - MxLong m_position; + MxULong m_lengthInDWords; // 0x08 + MxU32* m_pBuffer; // 0x0c + MxLong m_position; // 0x10 }; #endif // MXDSSOURCE_H diff --git a/LEGO1/mxdsstreamingaction.h b/LEGO1/mxdsstreamingaction.h index 1766bd76..7581b217 100644 --- a/LEGO1/mxdsstreamingaction.h +++ b/LEGO1/mxdsstreamingaction.h @@ -32,11 +32,13 @@ class MxDSStreamingAction : public MxDSAction { void FUN_100cd2d0(); inline MxU32 GetUnknown94() { return m_unk0x94; } + inline MxS32 GetUnknown9c() { return m_unk0x9c; } inline MxDSBuffer* GetUnknowna0() { return m_unk0xa0; } inline MxDSBuffer* GetUnknowna4() { return m_unk0xa4; } inline MxDSAction* GetInternalAction() { return m_internalAction; } inline MxU32 GetBufferOffset() { return m_bufferOffset; } inline void SetUnknown94(MxU32 p_unk0x94) { m_unk0x94 = p_unk0x94; } + inline void SetUnknown9c(MxS32 p_unk0x9c) { m_unk0x9c = p_unk0x9c; } inline void SetUnknowna0(MxDSBuffer* p_unk0xa0) { m_unk0xa0 = p_unk0xa0; } inline void SetBufferOffset(MxU32 p_bufferOffset) { m_bufferOffset = p_bufferOffset; } diff --git a/LEGO1/mxnextactiondatastart.h b/LEGO1/mxnextactiondatastart.h index 10d2a2f2..c9534899 100644 --- a/LEGO1/mxnextactiondatastart.h +++ b/LEGO1/mxnextactiondatastart.h @@ -30,11 +30,13 @@ class MxNextActionDataStart : public MxCore { inline MxU32 GetObjectId() const { return m_objectId; } inline MxS16 GetUnknown24() const { return m_unk0x24; } + inline MxU32 GetData() const { return m_data; } + inline void SetData(MxU32 p_data) { m_data = p_data; } private: - MxU32 m_objectId; - MxS16 m_unk0x24; - MxU32 m_data; + MxU32 m_objectId; // 0x08 + MxS16 m_unk0x24; // 0x0c + MxU32 m_data; // 0x10 }; #endif // MXNEXTACTIONDATASTART_H diff --git a/LEGO1/mxsemaphore.cpp b/LEGO1/mxsemaphore.cpp index 18637185..5692a888 100644 --- a/LEGO1/mxsemaphore.cpp +++ b/LEGO1/mxsemaphore.cpp @@ -1,6 +1,10 @@ #include "mxsemaphore.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxSemaphore, 0x08) + // FUNCTION: LEGO1 0x100c87d0 MxSemaphore::MxSemaphore() { diff --git a/LEGO1/mxsemaphore.h b/LEGO1/mxsemaphore.h index 3bc6d66b..ecb6509c 100644 --- a/LEGO1/mxsemaphore.h +++ b/LEGO1/mxsemaphore.h @@ -5,6 +5,7 @@ #include +// SIZE 0x08 class MxSemaphore { public: MxSemaphore(); @@ -18,7 +19,7 @@ class MxSemaphore { void Release(MxU32 p_releaseCount); private: - HANDLE m_hSemaphore; + HANDLE m_hSemaphore; // 0x04 }; #endif // MX_SEMAPHORE_H diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp index 92dcfb26..c7d30cc4 100644 --- a/LEGO1/mxstreamcontroller.cpp +++ b/LEGO1/mxstreamcontroller.cpp @@ -5,6 +5,7 @@ #include "mxautolocker.h" #include "mxdsstreamingaction.h" #include "mxnextactiondatastart.h" +#include "mxstl/stlcompat.h" #include "mxstreamchunk.h" #include "mxtimer.h" diff --git a/LEGO1/mxstreamcontroller.h b/LEGO1/mxstreamcontroller.h index ca3b09b3..b8a5bfbd 100644 --- a/LEGO1/mxstreamcontroller.h +++ b/LEGO1/mxstreamcontroller.h @@ -53,6 +53,7 @@ class MxStreamController : public MxCore { MxResult InsertActionToList54(MxDSAction* p_action); inline MxAtomId& GetAtom() { return m_atom; }; + inline MxStreamListMxDSAction& GetUnk0x3c() { return m_unk0x3c; }; inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; }; protected: diff --git a/LEGO1/mxstreamlist.h b/LEGO1/mxstreamlist.h index 9b65c53d..6aa63de0 100644 --- a/LEGO1/mxstreamlist.h +++ b/LEGO1/mxstreamlist.h @@ -1,7 +1,7 @@ #ifndef MXSTREAMLIST_H #define MXSTREAMLIST_H -#include "mxdsaction.h" +#include "mxdsstreamingaction.h" #include "mxdssubscriber.h" #include "mxnextactiondatastart.h" #include "mxstl/stlcompat.h" @@ -24,6 +24,18 @@ class MxStreamList : public list { class MxStreamListMxDSAction : public MxStreamList { public: MxDSAction* Find(MxDSAction* p_action, MxBool p_delete); + + // There chance this list actually holds MxDSStreamingListAction + // instead of MxDSAction. Until then, we use this helper. + MxBool PopFrontStreamingAction(MxDSStreamingAction*& p_obj) + { + if (empty()) + return FALSE; + + p_obj = (MxDSStreamingAction*) front(); + pop_front(); + return TRUE; + } }; // SIZE 0xc diff --git a/LEGO1/mxstreamprovider.h b/LEGO1/mxstreamprovider.h index ecbe9ab4..73804684 100644 --- a/LEGO1/mxstreamprovider.h +++ b/LEGO1/mxstreamprovider.h @@ -34,8 +34,8 @@ class MxStreamProvider : public MxCore { virtual MxU32* GetBufferForDWords() = 0; // vtable+0x28 protected: - MxStreamController* m_pLookup; - MxDSFile* m_pFile; + MxStreamController* m_pLookup; // 0x08 + MxDSFile* m_pFile; // 0x0c }; #endif // MXSTREAMPROVIDER_H diff --git a/LEGO1/mxthread.cpp b/LEGO1/mxthread.cpp index 899e959e..401860a1 100644 --- a/LEGO1/mxthread.cpp +++ b/LEGO1/mxthread.cpp @@ -1,11 +1,15 @@ #include "mxthread.h" +#include "decomp.h" #include "mxomni.h" #include "mxtimer.h" #include +DECOMP_SIZE_ASSERT(MxThread, 0x1c) +DECOMP_SIZE_ASSERT(MxTickleThread, 0x20) + // FUNCTION: LEGO1 0x100b8bb0 MxTickleThread::MxTickleThread(MxCore* p_target, MxS32 p_frequencyMS) { diff --git a/LEGO1/mxthread.h b/LEGO1/mxthread.h index 3c7faab0..e3af186d 100644 --- a/LEGO1/mxthread.h +++ b/LEGO1/mxthread.h @@ -8,6 +8,7 @@ class MxCore; // VTABLE: LEGO1 0x100dc860 +// SIZE 0x1c class MxThread { public: // Note: Comes before virtual destructor @@ -16,10 +17,8 @@ class MxThread { MxResult Start(MxS32 p_stack, MxS32 p_flag); void Terminate(); - void Sleep(MxS32 p_milliseconds); - // Inferred, not in DLL inline MxBool IsRunning() { return m_running; } protected: @@ -31,27 +30,26 @@ class MxThread { private: static unsigned ThreadProc(void* p_thread); - MxULong m_hThread; - MxU32 m_threadId; - MxBool m_running; - MxSemaphore m_semaphore; + MxULong m_hThread; // 0x04 + MxU32 m_threadId; // 0x08 + MxBool m_running; // 0x0c + MxSemaphore m_semaphore; // 0x10 protected: - MxCore* m_target; + MxCore* m_target; // 0x18 }; // VTABLE: LEGO1 0x100dc6d8 +// SIZE 0x20 class MxTickleThread : public MxThread { public: MxTickleThread(MxCore* p_target, MxS32 p_frequencyMS); - - // Only inlined, no offset virtual ~MxTickleThread() {} MxResult Run() override; private: - MxS32 m_frequencyMS; + MxS32 m_frequencyMS; // 0x1c }; #endif // MXTHREAD_H From 762681a821701e0d70db3b9bc9867e17e8da5141 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 25 Dec 2023 13:34:13 -0500 Subject: [PATCH 03/50] Create MxSoundManager in LegoSoundManager for now --- LEGO1/legosoundmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LEGO1/legosoundmanager.cpp b/LEGO1/legosoundmanager.cpp index 8b8376fa..d31e5d1c 100644 --- a/LEGO1/legosoundmanager.cpp +++ b/LEGO1/legosoundmanager.cpp @@ -29,7 +29,7 @@ void LegoSoundManager::Destroy(MxBool p_fromDestructor) // STUB: LEGO1 0x100299f0 MxResult LegoSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) { - return SUCCESS; + return MxSoundManager::Create(p_frequencyMS, p_createThread); } // FUNCTION: LEGO1 0x1002a390 From 2827ef74ded0ee82bc3793b38e801cdb19599c60 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 25 Dec 2023 15:22:20 -0500 Subject: [PATCH 04/50] Hotfix GetString missing pointer indirection --- LEGO1/legoutil.h | 4 ++-- LEGO1/mxdsmediaaction.cpp | 2 +- LEGO1/mxdsobject.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/LEGO1/legoutil.h b/LEGO1/legoutil.h index a6351395..bd7adae6 100644 --- a/LEGO1/legoutil.h +++ b/LEGO1/legoutil.h @@ -49,10 +49,10 @@ inline void GetDouble(MxU8** p_source, T& p_dest) } template -inline void GetString(MxU8** p_source, const char* p_dest, T* p_obj, void (T::*p_setter)(const char*)) +inline void GetString(MxU8** p_source, char** p_dest, T* p_obj, void (T::*p_setter)(const char*)) { (p_obj->*p_setter)((char*) *p_source); - *p_source += strlen(p_dest) + 1; + *p_source += strlen(*p_dest) + 1; } ExtraActionType MatchActionString(const char*); diff --git a/LEGO1/mxdsmediaaction.cpp b/LEGO1/mxdsmediaaction.cpp index 9e07f2d3..fb9425d2 100644 --- a/LEGO1/mxdsmediaaction.cpp +++ b/LEGO1/mxdsmediaaction.cpp @@ -84,7 +84,7 @@ void MxDSMediaAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24) { MxDSAction::Deserialize(p_source, p_unk0x24); - GetString(p_source, this->m_mediaSrcPath, this, &MxDSMediaAction::CopyMediaSrcPath); + GetString(p_source, &this->m_mediaSrcPath, this, &MxDSMediaAction::CopyMediaSrcPath); GetScalar(p_source, this->m_unk0x9c.m_unk0x00); GetScalar(p_source, this->m_unk0x9c.m_unk0x04); GetScalar(p_source, this->m_framesPerSecond); diff --git a/LEGO1/mxdsobject.cpp b/LEGO1/mxdsobject.cpp index fa0b944c..9a5801d1 100644 --- a/LEGO1/mxdsobject.cpp +++ b/LEGO1/mxdsobject.cpp @@ -129,9 +129,9 @@ MxU32 MxDSObject::GetSizeOnDisk() // FUNCTION: LEGO1 0x100bfa20 void MxDSObject::Deserialize(MxU8** p_source, MxS16 p_unk0x24) { - GetString(p_source, this->m_sourceName, this, &MxDSObject::SetSourceName); + GetString(p_source, &this->m_sourceName, this, &MxDSObject::SetSourceName); GetScalar(p_source, this->m_unk0x14); - GetString(p_source, this->m_objectName, this, &MxDSObject::SetObjectName); + GetString(p_source, &this->m_objectName, this, &MxDSObject::SetObjectName); GetScalar(p_source, this->m_objectId); this->m_unk0x24 = p_unk0x24; From 57b11866ed6f75192e69bcf62b0b12bae5a53f62 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Mon, 25 Dec 2023 17:39:31 -0500 Subject: [PATCH 05/50] Implement MxDSBuffer::FUN_100c67b0 (#361) * push changes * improve match of SwapBuffers * rename function * Improve match of MxDSBuffer::FUN_100c67b0 --------- Co-authored-by: Christian Semmler --- LEGO1/mxdiskstreamcontroller.h | 4 +- LEGO1/mxdsbuffer.cpp | 101 ++++++++++++++++++++++++++++++++- LEGO1/mxdsbuffer.h | 5 +- 3 files changed, 104 insertions(+), 6 deletions(-) diff --git a/LEGO1/mxdiskstreamcontroller.h b/LEGO1/mxdiskstreamcontroller.h index 28966d9d..703b3bf2 100644 --- a/LEGO1/mxdiskstreamcontroller.h +++ b/LEGO1/mxdiskstreamcontroller.h @@ -43,6 +43,8 @@ class MxDiskStreamController : public MxStreamController { void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); void FUN_100c8670(MxDSStreamingAction* p_streamingAction); + void InsertToList74(MxDSBuffer* p_buffer); + void FUN_100c7cb0(MxDSStreamingAction* p_action); private: MxStreamListMxDSAction m_list0x64; // 0x64 @@ -57,13 +59,11 @@ class MxDiskStreamController : public MxStreamController { MxResult FUN_100c7890(MxDSStreamingAction* p_action); void FUN_100c7970(); - void FUN_100c7cb0(MxDSStreamingAction* p_action); void FUN_100c7ce0(MxDSBuffer* p_buffer); MxResult FUN_100c7d10(); void FUN_100c7980(); MxDSStreamingAction* FUN_100c7db0(); MxResult FUN_100c8360(MxDSStreamingAction* p_action); - void InsertToList74(MxDSBuffer* p_buffer); void FUN_100c8540(); void FUN_100c8720(); }; diff --git a/LEGO1/mxdsbuffer.cpp b/LEGO1/mxdsbuffer.cpp index b9908558..f4b30215 100644 --- a/LEGO1/mxdsbuffer.cpp +++ b/LEGO1/mxdsbuffer.cpp @@ -1,5 +1,6 @@ #include "mxdsbuffer.h" +#include "mxdiskstreamcontroller.h" #include "mxdschunk.h" #include "mxdsstreamingaction.h" #include "mxomni.h" @@ -119,15 +120,58 @@ MxResult MxDSBuffer::SetBufferPointer(MxU32* p_buffer, MxU32 p_size) return SUCCESS; } -// STUB: LEGO1 0x100c67b0 +// FUNCTION: LEGO1 0x100c67b0 MxResult MxDSBuffer::FUN_100c67b0( MxStreamController* p_controller, MxDSAction* p_action, MxDSStreamingAction** p_streamingAction ) { - // TODO STUB - return FAILURE; + MxResult result = FAILURE; + + m_unk0x30 = (MxDSStreamingAction*) p_controller->GetUnk0x3c().Find(p_action, FALSE); + if (m_unk0x30 == NULL) + return FAILURE; + + MxU8* data; + while (data = (MxU8*) SkipToData()) { + if (*p_streamingAction == NULL) { + result = CreateObject(p_controller, (MxU32*) data, p_action, p_streamingAction); + + if (result == FAILURE) + return result; + // TODO: Not a MxResult value? + if (result == 1) + break; + } + else { + MxDSBuffer* buffer = (*p_streamingAction)->GetUnknowna0(); + + if (buffer->CalcBytesRemaining(data) != SUCCESS) { + return result; + } + + if (buffer->GetBytesRemaining() == 0) { + buffer->SetUnk30(m_unk0x30); + + result = buffer->CreateObject(p_controller, (MxU32*) buffer->GetBuffer(), p_action, p_streamingAction); + if (result != SUCCESS) { + return result; + } + + if (buffer->GetRefCount() != 0) { + // Note: *p_streamingAction is always null in MxRamStreamProvider + ((MxDiskStreamController*) p_controller)->InsertToList74(buffer); + (*p_streamingAction)->SetUnknowna0(NULL); + } + + ((MxDiskStreamController*) p_controller)->FUN_100c7cb0(*p_streamingAction); + *p_streamingAction = NULL; + } + } + } + + return SUCCESS; } // FUNCTION: LEGO1 0x100c68a0 @@ -212,6 +256,7 @@ MxResult MxDSBuffer::ParseChunk( ) { // TODO + OutputDebugString("ParseChunk() todo\n"); return FAILURE; } @@ -239,6 +284,49 @@ MxCore* MxDSBuffer::ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_ return result; } +// FUNCTION: LEGO1 0x100c6df0 +MxU8* MxDSBuffer::SkipToData() +{ + MxU8* result = NULL; + + if (m_pIntoBuffer != NULL) { + do { + MxU32* ptr = (MxU32*) m_pIntoBuffer; + switch (*ptr) { + case FOURCC('L', 'I', 'S', 'T'): + case FOURCC('R', 'I', 'F', 'F'): + m_pIntoBuffer = (MxU8*) (ptr + 3); + break; + case FOURCC('M', 'x', 'O', 'b'): + case FOURCC('M', 'x', 'C', 'h'): + result = m_pIntoBuffer; + m_pIntoBuffer = (MxU8*) ((ptr[1] & 1) + ptr[1] + (MxU32) ptr); + m_pIntoBuffer = (MxU8*) ((MxU32*) m_pIntoBuffer + 2); + if (m_pBuffer + (m_writeOffset - 8) < m_pIntoBuffer) { + m_pIntoBuffer2 = result; + m_pIntoBuffer = NULL; + return result; + } + goto done; + case FOURCC('M', 'x', 'D', 'a'): + case FOURCC('M', 'x', 'S', 't'): + m_pIntoBuffer = (MxU8*) (ptr + 2); + break; + case FOURCC('M', 'x', 'H', 'd'): + m_pIntoBuffer = (MxU8*) ((MxU32) ptr + ptr[1] + 8); + break; + default: + m_pIntoBuffer = NULL; + m_pIntoBuffer2 = NULL; + return NULL; + } + } while (m_pIntoBuffer <= m_pBuffer + (m_writeOffset - 8)); + } +done: + m_pIntoBuffer2 = result; + return result; +} + // FUNCTION: LEGO1 0x100c6ec0 MxU8 MxDSBuffer::ReleaseRef(MxDSChunk*) { @@ -256,6 +344,13 @@ void MxDSBuffer::AddRef(MxDSChunk* p_chunk) } } +// STUB: LEGO1 0x100c6ef0 +MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) +{ + // TODO + return FAILURE; +} + // FUNCTION: LEGO1 0x100c6f80 void MxDSBuffer::FUN_100c6f80(MxU32 p_writeOffset) { diff --git a/LEGO1/mxdsbuffer.h b/LEGO1/mxdsbuffer.h index ac003711..e9fe2675 100644 --- a/LEGO1/mxdsbuffer.h +++ b/LEGO1/mxdsbuffer.h @@ -53,17 +53,20 @@ class MxDSBuffer : public MxCore { MxStreamChunk* p_header ); static MxCore* ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags); - void SwapBuffers(); + MxU8* SkipToData(); MxU8 ReleaseRef(MxDSChunk*); void AddRef(MxDSChunk* p_chunk); + MxResult CalcBytesRemaining(MxU8* p_data); void FUN_100c6f80(MxU32 p_writeOffset); inline MxU8* GetBuffer() { return m_pBuffer; } inline MxU32 GetWriteOffset() { return m_writeOffset; } + inline MxU32 GetBytesRemaining() { return m_bytesRemaining; } inline MxU16 GetRefCount() { return m_refcount; } inline MxDSBufferType GetMode() { return m_mode; } inline void SetUnknown14(undefined4 p_unk0x14) { m_unk0x14 = p_unk0x14; } inline void SetUnknown1c(undefined4 p_unk0x1c) { m_unk0x1c = p_unk0x1c; } + inline void SetUnk30(MxDSStreamingAction* p_unk0x30) { m_unk0x30 = p_unk0x30; } private: MxU8* m_pBuffer; // 0x08 From c8ec60b62c576665e7bbfb503786b72906f3e281 Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Mon, 25 Dec 2023 17:46:15 -0500 Subject: [PATCH 06/50] LegoLoadCacheSoundPresenter ctor, dtor, init, destroy (#360) * LegoLoadCacheSoundPresenter ctor, dtor, init, destroy * Fixes --------- Co-authored-by: Christian Semmler --- LEGO1/legoloadcachesoundpresenter.cpp | 19 +++++++++++++++---- LEGO1/legoloadcachesoundpresenter.h | 12 ++++++++++++ LEGO1/mxwavepresenter.h | 4 +++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/LEGO1/legoloadcachesoundpresenter.cpp b/LEGO1/legoloadcachesoundpresenter.cpp index 4bc2cbd6..41445182 100644 --- a/LEGO1/legoloadcachesoundpresenter.cpp +++ b/LEGO1/legoloadcachesoundpresenter.cpp @@ -1,19 +1,30 @@ #include "legoloadcachesoundpresenter.h" +DECOMP_SIZE_ASSERT(LegoLoadCacheSoundPresenter, 0x90) + // FUNCTION: LEGO1 0x10018340 LegoLoadCacheSoundPresenter::LegoLoadCacheSoundPresenter() { Init(); } -// STUB: LEGO1 0x10018480 +// FUNCTION: LEGO1 0x10018480 LegoLoadCacheSoundPresenter::~LegoLoadCacheSoundPresenter() { - // TODO + Destroy(TRUE); } -// STUB: LEGO1 0x100184e0 +// FUNCTION: LEGO1 0x100184e0 void LegoLoadCacheSoundPresenter::Init() { - // TODO + this->m_unk0x70 = NULL; + this->m_unk0x78 = 0; + this->m_unk0x7c = 0; +} + +// FUNCTION: LEGO1 0x100184f0 +void LegoLoadCacheSoundPresenter::Destroy(MxBool p_fromDestructor) +{ + delete this->m_unk0x70; + MxWavePresenter::Destroy(p_fromDestructor); } diff --git a/LEGO1/legoloadcachesoundpresenter.h b/LEGO1/legoloadcachesoundpresenter.h index 6f9f473b..c9255b01 100644 --- a/LEGO1/legoloadcachesoundpresenter.h +++ b/LEGO1/legoloadcachesoundpresenter.h @@ -1,6 +1,7 @@ #ifndef LEGOLOADCACHESOUNDPRESENTER_H #define LEGOLOADCACHESOUNDPRESENTER_H +#include "decomp.h" #include "mxwavepresenter.h" // VTABLE: LEGO1 0x100d5fa8 @@ -19,6 +20,17 @@ class LegoLoadCacheSoundPresenter : public MxWavePresenter { private: void Init(); + void Destroy(MxBool p_fromDestructor); + + undefined4* m_unk0x6c; // 0x6c + undefined4* m_unk0x70; // 0x70 + undefined4 m_unk0x74; // 0x74 + undefined4 m_unk0x78; // 0x78 + undefined m_unk0x7c; // 0x7c + undefined4 m_unk0x80[4]; // 0x80 }; +// SYNTHETIC: LEGO1 0x10018460 +// LegoLoadCacheSoundPresenter::`scalar deleting destructor' + #endif // LEGOLOADCACHESOUNDPRESENTER_H diff --git a/LEGO1/mxwavepresenter.h b/LEGO1/mxwavepresenter.h index ddb2b480..4210a44e 100644 --- a/LEGO1/mxwavepresenter.h +++ b/LEGO1/mxwavepresenter.h @@ -50,9 +50,11 @@ class MxWavePresenter : public MxSoundPresenter { MxU32 m_flags; }; +protected: + void Destroy(MxBool p_fromDestructor); + private: void Init(); - void Destroy(MxBool p_fromDestructor); MxS8 GetPlayedChunks(); MxBool FUN_100b1ba0(); void WriteToSoundBuffer(void* p_audioPtr, MxU32 p_length); From 33bf35af95c69012331e798f5adfe70d5a163f96 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 25 Dec 2023 17:51:15 -0500 Subject: [PATCH 07/50] Remove OutputDebugString --- LEGO1/mxdsbuffer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/LEGO1/mxdsbuffer.cpp b/LEGO1/mxdsbuffer.cpp index f4b30215..261f00d3 100644 --- a/LEGO1/mxdsbuffer.cpp +++ b/LEGO1/mxdsbuffer.cpp @@ -256,7 +256,6 @@ MxResult MxDSBuffer::ParseChunk( ) { // TODO - OutputDebugString("ParseChunk() todo\n"); return FAILURE; } From 77755570f2858269a6cf2c81d5a4e7902072ea23 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 25 Dec 2023 19:42:40 -0500 Subject: [PATCH 08/50] Fix a few annotations --- LEGO1/mxrectlist.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LEGO1/mxrectlist.h b/LEGO1/mxrectlist.h index c0527f01..e19c4994 100644 --- a/LEGO1/mxrectlist.h +++ b/LEGO1/mxrectlist.h @@ -69,13 +69,13 @@ class MxRectListCursor : public MxPtrListCursor { // MxRectListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100b4090 -// MxPtrListCursor::~MxPtrListCursor +// MxPtrListCursor::~MxPtrListCursor // SYNTHETIC: LEGO1 0x100b40e0 // MxListCursor::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100b4150 -// MxPtrListCursor::`scalar deleting destructor' +// MxPtrListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100b41c0 // MxListCursor::~MxListCursor From a25bcecf47d65cbdfe488c97ed80596f9b6cc031 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 25 Dec 2023 20:54:44 -0500 Subject: [PATCH 09/50] Fix/match MxBitmap::SetBitDepth --- LEGO1/mxbitmap.cpp | 49 +++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/LEGO1/mxbitmap.cpp b/LEGO1/mxbitmap.cpp index 0aec1a6e..12719e7f 100644 --- a/LEGO1/mxbitmap.cpp +++ b/LEGO1/mxbitmap.cpp @@ -296,36 +296,41 @@ MxResult MxBitmap::SetBitDepth(MxBool p_isHighColor) if (m_isHighColor == p_isHighColor) { // no change: do nothing. ret = SUCCESS; + goto done; } - else { - switch (p_isHighColor) { - case FALSE: - ImportColorsToPalette(m_paletteData, m_palette); - if (m_palette) - delete m_palette; - m_palette = NULL; - break; + switch (p_isHighColor) { + case FALSE: + ImportColorsToPalette(m_paletteData, m_palette); + if (m_palette) + delete m_palette; - case TRUE: - pal = NULL; - pal = new MxPalette(m_paletteData); - if (pal) { - m_palette = pal; + m_palette = NULL; + break; + case TRUE: { + pal = NULL; + pal = new MxPalette(m_paletteData); - // TODO: what is this? zeroing out top half of palette? - MxU16* buf = (MxU16*) m_paletteData; - for (MxU16 i = 0; i < 256; i++) { - buf[i] = i; - } + if (!pal) + goto done; - m_isHighColor = p_isHighColor; - ret = SUCCESS; - } - break; + m_palette = pal; + + // TODO: what is this? zeroing out top half of palette? + MxU16* buf = (MxU16*) m_paletteData; + for (MxU16 i = 0; i < 256; i++) { + buf[i] = i; } + break; + } + default: + goto done; } + m_isHighColor = p_isHighColor; + ret = SUCCESS; + +done: // If we were unsuccessful overall but did manage to alloc // the MxPalette, free it. if (ret && pal) From c507454dd10b797b1b9845416afff8fb5d420caf Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 25 Dec 2023 21:16:14 -0500 Subject: [PATCH 10/50] Match MxBitmap::CreatePalette --- LEGO1/mxbitmap.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/LEGO1/mxbitmap.cpp b/LEGO1/mxbitmap.cpp index 12719e7f..30ba032d 100644 --- a/LEGO1/mxbitmap.cpp +++ b/LEGO1/mxbitmap.cpp @@ -250,17 +250,25 @@ MxPalette* MxBitmap::CreatePalette() switch (this->m_isHighColor) { case FALSE: palette = new MxPalette(this->m_paletteData); - if (palette) - success = TRUE; - break; + if (!palette) + goto done; + + break; case TRUE: palette = this->m_palette->Clone(); - if (palette) - success = TRUE; + + if (!palette) + goto done; + break; + default: + goto done; } + success = TRUE; + +done: if (!success && palette) { delete palette; palette = NULL; From 17522b98d422d1f8ada53f6c4490217c8e05710f Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 25 Dec 2023 21:58:39 -0500 Subject: [PATCH 11/50] Refactor MxBitmap inline functions, match ImportBitmap --- LEGO1/mxbitmap.cpp | 26 ++++---------------------- LEGO1/mxbitmap.h | 23 +++++++++++++++++++---- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/LEGO1/mxbitmap.cpp b/LEGO1/mxbitmap.cpp index 30ba032d..4f2393cf 100644 --- a/LEGO1/mxbitmap.cpp +++ b/LEGO1/mxbitmap.cpp @@ -10,22 +10,6 @@ DECOMP_SIZE_ASSERT(MxBITMAPINFO, 0x428); // (1998) GLOBAL: LEGO1 0x10102184 MxU16 g_bitmapSignature = TWOCC('B', 'M'); -// Bit mask trick to round up to the nearest multiple of four. -// Pixel data may be stored with padding. -// https://learn.microsoft.com/en-us/windows/win32/medfound/image-stride -inline MxLong AlignToFourByte(MxLong p_value) -{ - return (p_value + 3) & -4; -} - -// Same as the one from legoutil.h, but flipped the other way -// TODO: While it's not outside the realm of possibility that they -// reimplemented Abs for only this file, that seems odd, right? -inline MxLong AbsFlipped(MxLong p_value) -{ - return p_value > 0 ? p_value : -p_value; -} - // FUNCTION: LEGO1 0x1004e0d0 int MxBitmap::VTable0x28(int) { @@ -140,16 +124,14 @@ MxResult MxBitmap::ImportBitmap(MxBitmap* p_bitmap) this->m_info = new MxBITMAPINFO; if (this->m_info) { - MxLong height = AbsFlipped(p_bitmap->m_bmiHeader->biHeight); - this->m_data = new MxU8[AlignToFourByte(p_bitmap->m_bmiHeader->biWidth) * height]; + this->m_data = new MxU8[p_bitmap->GetDataSize()]; if (this->m_data) { - memcpy(this->m_info, p_bitmap->m_info, sizeof(*this->m_info)); - height = AbsFlipped(p_bitmap->m_bmiHeader->biHeight); - memcpy(this->m_data, p_bitmap->m_data, AlignToFourByte(p_bitmap->m_bmiHeader->biWidth) * height); + memcpy(this->m_info, p_bitmap->GetBitmapInfo(), MxBITMAPINFO::Size()); + memcpy(this->m_data, p_bitmap->GetBitmapData(), p_bitmap->GetDataSize()); - result = SUCCESS; this->m_bmiHeader = &this->m_info->m_bmiHeader; this->m_paletteData = this->m_info->m_bmiColors; + result = SUCCESS; } } diff --git a/LEGO1/mxbitmap.h b/LEGO1/mxbitmap.h index b87bcdcf..ed944138 100644 --- a/LEGO1/mxbitmap.h +++ b/LEGO1/mxbitmap.h @@ -19,6 +19,8 @@ struct MxBITMAPINFO { BITMAPINFOHEADER m_bmiHeader; RGBQUAD m_bmiColors[256]; + + static MxU32 Size() { return sizeof(MxBITMAPINFO); } }; // Non-standard value for biCompression in the BITMAPINFOHEADER struct. @@ -56,16 +58,29 @@ class MxBitmap : public MxCore { MxS32 p_destHeight ); // vtable+40 + // Bit mask trick to round up to the nearest multiple of four. + // Pixel data may be stored with padding. + // https://learn.microsoft.com/en-us/windows/win32/medfound/image-stride + inline MxLong AlignToFourByte(MxLong p_value) const { return (p_value + 3) & -4; } + + // Same as the one from legoutil.h, but flipped the other way + // TODO: While it's not outside the realm of possibility that they + // reimplemented Abs for only this file, that seems odd, right? + inline MxLong AbsFlipped(MxLong p_value) const { return p_value > 0 ? p_value : -p_value; } + inline BITMAPINFOHEADER* GetBmiHeader() const { return m_bmiHeader; } inline MxLong GetBmiWidth() const { return m_bmiHeader->biWidth; } inline MxLong GetBmiStride() const { return ((m_bmiHeader->biWidth + 3) & -4); } inline MxLong GetBmiHeight() const { return m_bmiHeader->biHeight; } - inline MxLong GetBmiHeightAbs() const - { - return m_bmiHeader->biHeight > 0 ? m_bmiHeader->biHeight : -m_bmiHeader->biHeight; - } + inline MxLong GetBmiHeightAbs() const { return AbsFlipped(m_bmiHeader->biHeight); } inline MxU8* GetBitmapData() const { return m_data; } inline MxBITMAPINFO* GetBitmapInfo() const { return m_info; } + inline MxLong GetDataSize() const + { + MxLong absHeight = GetBmiHeightAbs(); + MxLong alignedWidth = AlignToFourByte(m_bmiHeader->biWidth); + return alignedWidth * absHeight; + } private: MxResult ImportColorsToPalette(RGBQUAD*, MxPalette*); From e824e321e884f042eb7811b1bb6538821a1ea6e1 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Tue, 26 Dec 2023 16:27:54 -0500 Subject: [PATCH 12/50] Implement chunk parsing (#362) * partial parsechunk implementation * fix format * param name fix * rename functions * match MxStreamController::RemoveSubscriber * implement rest of MxDSBuffer * Fixes and better matches * Matche ParseChunk 100% * Match MxDiskStreamProvider::VTable0x20 * Match MxDSBuffer::CalcBytesRemaining * Minor stuff * Minor improvements * Refactor functions --------- Co-authored-by: Christian Semmler --- LEGO1/mxdiskstreamprovider.cpp | 41 ++++++++- LEGO1/mxdsbuffer.cpp | 154 ++++++++++++++++++++++++++++++--- LEGO1/mxdschunk.cpp | 6 ++ LEGO1/mxdschunk.h | 4 + LEGO1/mxdsstreamingaction.h | 1 + LEGO1/mxdssubscriber.cpp | 4 +- LEGO1/mxstreamchunk.cpp | 44 ++++++++++ LEGO1/mxstreamchunk.h | 8 ++ LEGO1/mxstreamcontroller.cpp | 18 ++-- LEGO1/mxstreamcontroller.h | 7 +- 10 files changed, 265 insertions(+), 22 deletions(-) diff --git a/LEGO1/mxdiskstreamprovider.cpp b/LEGO1/mxdiskstreamprovider.cpp index c7e311eb..badc1623 100644 --- a/LEGO1/mxdiskstreamprovider.cpp +++ b/LEGO1/mxdiskstreamprovider.cpp @@ -77,10 +77,47 @@ MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource) return result; } -// STUB: LEGO1 0x100d15e0 +// FUNCTION: LEGO1 0x100d15e0 void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) { - // TODO + MxDSStreamingAction* action; + + if (p_action->GetObjectId() == -1) { + m_unk0x35 = FALSE; + + do { + action = NULL; + + { + MxAutoLocker lock(&m_criticalSection); + m_list.PopFrontStreamingAction(action); + } + + if (!action) + return; + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) + g_unk0x10102878--; + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action); + } + else { + do { + { + MxAutoLocker lock(&m_criticalSection); + action = (MxDSStreamingAction*) m_list.Find(p_action, TRUE); + } + + if (!action) + return; + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) + g_unk0x10102878--; + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action); + } } // FUNCTION: LEGO1 0x100d1750 diff --git a/LEGO1/mxdsbuffer.cpp b/LEGO1/mxdsbuffer.cpp index 261f00d3..da643c17 100644 --- a/LEGO1/mxdsbuffer.cpp +++ b/LEGO1/mxdsbuffer.cpp @@ -30,11 +30,45 @@ MxDSBuffer::MxDSBuffer() MxDSBuffer::~MxDSBuffer() { if (m_pBuffer != NULL) { - if (m_mode == MxDSBufferType_Chunk) { - // TODO - } - else if (m_mode == MxDSBufferType_Allocate || m_mode == MxDSBufferType_Unknown) { + switch (m_mode) { + case MxDSBufferType_Allocate: + case MxDSBufferType_Unknown: delete[] m_pBuffer; + break; + + case MxDSBufferType_Chunk: { + MxU32 offset = m_writeOffset / 1024; + MxStreamer* streamer = Streamer(); + + switch (offset) { + case 0x40: { + MxU32 a = + (m_pBuffer - streamer->GetSubclass1().GetBuffer()) / (streamer->GetSubclass1().GetSize() << 10); + + MxU32 bit = 1 << ((MxU8) a & 0x1f); + MxU32 index = (a & ~0x18u) >> 3; + + if ((*(MxU32*) (&streamer->GetSubclass1().GetUnk08Ref()[index])) & bit) { + MxU32* ptr = (MxU32*) (&streamer->GetSubclass1().GetUnk08Ref()[index]); + *ptr = *ptr ^ bit; + } + break; + } + case 0x80: { + MxU32 a = + (m_pBuffer - streamer->GetSubclass1().GetBuffer()) / (streamer->GetSubclass1().GetSize() << 10); + + MxU32 bit = 1 << ((MxU8) a & 0x1f); + MxU32 index = (a & ~0x18u) >> 3; + + if ((*(MxU32*) (&streamer->GetSubclass2().GetUnk08Ref()[index])) & bit) { + MxU32* ptr = (MxU32*) (&streamer->GetSubclass2().GetUnk08Ref()[index]); + *ptr = *ptr ^ bit; + } + break; + } + } + } } } @@ -246,7 +280,7 @@ MxResult MxDSBuffer::StartPresenterFromAction( return SUCCESS; } -// STUB: LEGO1 0x100c6a50 +// FUNCTION: LEGO1 0x100c6a50 MxResult MxDSBuffer::ParseChunk( MxStreamController* p_controller, MxU32* p_data, @@ -255,8 +289,83 @@ MxResult MxDSBuffer::ParseChunk( MxStreamChunk* p_header ) { - // TODO - return FAILURE; + MxResult result = SUCCESS; + + if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 && m_unk0x30->GetUnknowna8() && p_header->GetTime() < 0) { + delete p_header; + return SUCCESS; + } + + p_header->SetTime(p_header->GetTime() + m_unk0x30->GetUnknowna8()); + + if (p_header->GetFlags() & MxDSChunk::Flag_Bit5) { + MxU32 length = p_header->GetLength() + MxDSChunk::ReturnE() + 8; + MxDSBuffer* buffer = new MxDSBuffer(); + + if (buffer && buffer->AllocateBuffer(length, MxDSBufferType_Allocate) == SUCCESS && + buffer->CalcBytesRemaining((MxU8*) p_data) == SUCCESS) { + *p_streamingAction = new MxDSStreamingAction((MxDSStreamingAction&) *p_action); + ; + + if (*p_streamingAction) { + MxU16* flags = MxStreamChunk::IntoFlags(buffer->GetBuffer()); + *flags = p_header->GetFlags() & ~MxDSChunk::Flag_Bit5; + + delete p_header; + (*p_streamingAction)->SetUnknowna0(buffer); + goto done; + } + } + + if (buffer) + delete buffer; + + delete p_header; + return FAILURE; + } + else { + if (p_header->GetFlags() & MxDSChunk::Flag_Bit2) { + if (m_unk0x30->HasId(p_header->GetObjectId())) { + if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 && + (m_unk0x30->GetLoopCount() > 1 || m_unk0x30->GetDuration() == -1)) { + + if (p_action->GetObjectId() == p_header->GetObjectId()) { + MxU32 val = p_controller->GetProvider()->GetBufferForDWords()[m_unk0x30->GetObjectId()]; + + m_unk0x30->SetUnknown94(val); + m_unk0x30->SetBufferOffset(m_writeOffset * (val / m_writeOffset)); + + MxNextActionDataStart* data = + p_controller->FindNextActionDataStartFromStreamingAction(m_unk0x30); + + if (data) + data->SetData(m_unk0x30->GetBufferOffset()); + + m_unk0x30->FUN_100cd2d0(); + } + + delete p_header; + p_header = NULL; + } + else { + if (p_action->GetObjectId() == p_header->GetObjectId() && + p_controller->VTable0x30(p_action) == SUCCESS) { + p_controller->GetProvider()->VTable0x20(p_action); + result = 1; + } + } + } + } + + if (p_header) { + if (p_header->SendChunk(p_controller->GetSubscriberList(), TRUE, p_action->GetUnknown24()) != SUCCESS) { + delete p_header; + } + } + } + +done: + return result; } // FUNCTION: LEGO1 0x100c6d00 @@ -343,11 +452,36 @@ void MxDSBuffer::AddRef(MxDSChunk* p_chunk) } } -// STUB: LEGO1 0x100c6ef0 +// FUNCTION: LEGO1 0x100c6ef0 MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) { - // TODO - return FAILURE; + MxResult result = FAILURE; + + if (m_mode == MxDSBufferType_Allocate && m_bytesRemaining != 0) { + MxU32 bytesRead; + MxU8* ptr; + + if (m_writeOffset == m_bytesRemaining) { + bytesRead = *(MxU32*) (p_data + 4) + 8; + ptr = p_data; + } + else { + ptr = &p_data[MxStreamChunk::ReturnE() + 8]; + bytesRead = (*(MxU32*) (p_data + 4)) - MxStreamChunk::ReturnE(); + } + + if (bytesRead <= m_bytesRemaining) { + memcpy(m_pBuffer + m_writeOffset - m_bytesRemaining, ptr, bytesRead); + + if (m_writeOffset == m_bytesRemaining) + *(MxU32*) (m_pBuffer + 4) = *MxStreamChunk::IntoPlus0x12(m_pBuffer) + MxStreamChunk::ReturnE(); + + m_bytesRemaining -= bytesRead; + result = SUCCESS; + } + } + + return result; } // FUNCTION: LEGO1 0x100c6f80 diff --git a/LEGO1/mxdschunk.cpp b/LEGO1/mxdschunk.cpp index b44bc475..bf7e08a6 100644 --- a/LEGO1/mxdschunk.cpp +++ b/LEGO1/mxdschunk.cpp @@ -19,3 +19,9 @@ MxDSChunk::~MxDSChunk() delete[] m_data; } } + +// FUNCTION: LEGO1 0x100be1e0 +MxU32 MxDSChunk::ReturnE() +{ + return 0xe; +} diff --git a/LEGO1/mxdschunk.h b/LEGO1/mxdschunk.h index 4cbb2fc9..ec4a8cbe 100644 --- a/LEGO1/mxdschunk.h +++ b/LEGO1/mxdschunk.h @@ -13,6 +13,8 @@ class MxDSChunk : public MxCore { Flag_Bit1 = 0x01, Flag_Bit2 = 0x02, Flag_Bit3 = 0x04, + Flag_Bit4 = 0x08, + Flag_Bit5 = 0x10, Flag_Bit8 = 0x80, Flag_Bit16 = 0x8000 }; @@ -33,6 +35,8 @@ class MxDSChunk : public MxCore { return !strcmp(p_name, MxDSChunk::ClassName()) || MxCore::IsA(p_name); } + static MxU32 ReturnE(); + inline void SetFlags(MxU16 p_flags) { m_flags = p_flags; } inline void SetObjectId(undefined4 p_objectid) { m_objectId = p_objectid; } inline void SetTime(MxLong p_time) { m_time = p_time; } diff --git a/LEGO1/mxdsstreamingaction.h b/LEGO1/mxdsstreamingaction.h index 7581b217..00cd13aa 100644 --- a/LEGO1/mxdsstreamingaction.h +++ b/LEGO1/mxdsstreamingaction.h @@ -35,6 +35,7 @@ class MxDSStreamingAction : public MxDSAction { inline MxS32 GetUnknown9c() { return m_unk0x9c; } inline MxDSBuffer* GetUnknowna0() { return m_unk0xa0; } inline MxDSBuffer* GetUnknowna4() { return m_unk0xa4; } + inline MxLong GetUnknowna8() { return m_unk0xa8; } inline MxDSAction* GetInternalAction() { return m_internalAction; } inline MxU32 GetBufferOffset() { return m_bufferOffset; } inline void SetUnknown94(MxU32 p_unk0x94) { m_unk0x94 = p_unk0x94; } diff --git a/LEGO1/mxdssubscriber.cpp b/LEGO1/mxdssubscriber.cpp index b4fa97a0..33ee11fc 100644 --- a/LEGO1/mxdssubscriber.cpp +++ b/LEGO1/mxdssubscriber.cpp @@ -17,7 +17,7 @@ MxDSSubscriber::MxDSSubscriber() MxDSSubscriber::~MxDSSubscriber() { if (m_controller) - m_controller->FUN_100c1620(this); + m_controller->RemoveSubscriber(this); DeleteChunks(); @@ -48,7 +48,7 @@ MxResult MxDSSubscriber::Create(MxStreamController* p_controller, MxU32 p_object if (!m_unk0x3c) return FAILURE; - m_controller->FUN_100c15d0(this); + m_controller->AddSubscriber(this); return SUCCESS; } diff --git a/LEGO1/mxstreamchunk.cpp b/LEGO1/mxstreamchunk.cpp index 93e76a6c..8dd9ed67 100644 --- a/LEGO1/mxstreamchunk.cpp +++ b/LEGO1/mxstreamchunk.cpp @@ -2,6 +2,7 @@ #include "legoutil.h" #include "mxdsbuffer.h" +#include "mxstreamlist.h" // FUNCTION: LEGO1 0x100c2fe0 MxStreamChunk::~MxStreamChunk() @@ -48,8 +49,51 @@ MxU32 MxStreamChunk::ReadChunkHeader(MxU8* p_chunkData) return headersize; } +// FUNCTION: LEGO1 0x100c30e0 +MxResult MxStreamChunk::SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, MxBool p_append, MxS16 p_obj24val) +{ + for (MxStreamListMxDSSubscriber::iterator it = p_subscriberList.begin(); it != p_subscriberList.end(); it++) { + if ((*it)->GetObjectId() == m_objectId && (*it)->GetUnknown48() == p_obj24val) { + if (m_flags & MxDSChunk::Flag_Bit2 && m_buffer) { + m_buffer->ReleaseRef(this); + m_buffer = NULL; + } + + (*it)->AddChunk(this, p_append); + + return SUCCESS; + } + } + + return FAILURE; +} + // FUNCTION: LEGO1 0x100c3170 void MxStreamChunk::SetBuffer(MxDSBuffer* p_buffer) { m_buffer = p_buffer; } + +// FUNCTION: LEGO1 0x100c3180 +MxU16* MxStreamChunk::IntoFlags(MxU8* p_buffer) +{ + return (MxU16*) (p_buffer + 8); +} + +// FUNCTION: LEGO1 0x100c3190 +MxU32* MxStreamChunk::IntoPlus0xa(MxU8* p_buffer) +{ + return (MxU32*) (p_buffer + 0xa); +} + +// FUNCTION: LEGO1 0x100c31a0 +MxU32* MxStreamChunk::IntoPlus0xe(MxU8* p_buffer) +{ + return (MxU32*) (p_buffer + 0xe); +} + +// FUNCTION: LEGO1 0x100c31b0 +MxU32* MxStreamChunk::IntoPlus0x12(MxU8* p_buffer) +{ + return (MxU32*) (p_buffer + 0x12); +} diff --git a/LEGO1/mxstreamchunk.h b/LEGO1/mxstreamchunk.h index 53cbfc68..18bc2335 100644 --- a/LEGO1/mxstreamchunk.h +++ b/LEGO1/mxstreamchunk.h @@ -2,8 +2,10 @@ #define MXSTREAMCHUNK_H #include "mxdschunk.h" +#include "mxdsobject.h" class MxDSBuffer; +class MxStreamListMxDSSubscriber; // VTABLE: LEGO1 0x100dc2a8 // SIZE 0x20 @@ -29,8 +31,14 @@ class MxStreamChunk : public MxDSChunk { MxResult ReadChunk(MxDSBuffer* p_buffer, MxU8* p_chunkData); MxU32 ReadChunkHeader(MxU8* p_chunkData); + MxResult SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, MxBool p_append, MxS16 p_obj24val); void SetBuffer(MxDSBuffer* p_buffer); + static MxU16* IntoFlags(MxU8* p_buffer); + static MxU32* IntoPlus0x12(MxU8* p_buffer); + static MxU32* IntoPlus0xa(MxU8* p_buffer); + static MxU32* IntoPlus0xe(MxU8* p_buffer); + private: MxDSBuffer* m_buffer; // 0x1c }; diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp index c7d30cc4..726a8fa1 100644 --- a/LEGO1/mxstreamcontroller.cpp +++ b/LEGO1/mxstreamcontroller.cpp @@ -78,16 +78,16 @@ MxResult MxStreamController::Open(const char* p_filename) return SUCCESS; } -// STUB: LEGO1 0x100c15d0 -void MxStreamController::FUN_100c15d0(MxDSSubscriber* p_subscriber) +// FUNCTION: LEGO1 0x100c15d0 +void MxStreamController::AddSubscriber(MxDSSubscriber* p_subscriber) { - // TODO + m_subscriberList.push_back(p_subscriber); } -// STUB: LEGO1 0x100c1620 -void MxStreamController::FUN_100c1620(MxDSSubscriber* p_subscriber) +// FUNCTION: LEGO1 0x100c1620 +void MxStreamController::RemoveSubscriber(MxDSSubscriber* p_subscriber) { - // TODO + m_subscriberList.remove(p_subscriber); } // FUNCTION: LEGO1 0x100c1690 @@ -259,6 +259,12 @@ MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action) return FAILURE; } +// STUB: LEGO1 0x100c20b0 +MxNextActionDataStart* MxStreamController::FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action) +{ + return NULL; +} + // STUB: LEGO1 0x100c20d0 MxBool MxStreamController::FUN_100c20d0(MxDSObject& p_obj) { diff --git a/LEGO1/mxstreamcontroller.h b/LEGO1/mxstreamcontroller.h index b8a5bfbd..0389772b 100644 --- a/LEGO1/mxstreamcontroller.h +++ b/LEGO1/mxstreamcontroller.h @@ -43,18 +43,21 @@ class MxStreamController : public MxCore { virtual MxResult VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval); // vtable+0x2c virtual MxResult VTable0x30(MxDSAction* p_action); // vtable+0x30 - void FUN_100c15d0(MxDSSubscriber* p_subscriber); - void FUN_100c1620(MxDSSubscriber* p_subscriber); + void AddSubscriber(MxDSSubscriber* p_subscriber); + void RemoveSubscriber(MxDSSubscriber* p_subscriber); MxResult FUN_100c1800(MxDSAction* p_action, MxU32 p_val); MxResult FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset); MxPresenter* FUN_100c1e70(MxDSAction& p_action); MxResult FUN_100c1f00(MxDSAction* p_action); MxBool FUN_100c20d0(MxDSObject& p_obj); MxResult InsertActionToList54(MxDSAction* p_action); + MxNextActionDataStart* FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action); inline MxAtomId& GetAtom() { return m_atom; }; + inline MxStreamProvider* GetProvider() { return m_provider; }; inline MxStreamListMxDSAction& GetUnk0x3c() { return m_unk0x3c; }; inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; }; + inline MxStreamListMxDSSubscriber& GetSubscriberList() { return m_subscriberList; }; protected: MxCriticalSection m_criticalSection; // 0x8 From ceca2aac31277b31088afb81ece417fe13918e48 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:20:20 -0500 Subject: [PATCH 13/50] Implement a few LegoVideoManager/MxDisplaySurface functions (#364) * implement a few functions * fixes * Fixes * Add annotations --------- Co-authored-by: Christian Semmler --- LEGO1/lego3dview.h | 12 ++++++-- LEGO1/legovideomanager.cpp | 51 ++++++++++++++++++++++++++++++++-- LEGO1/legovideomanager.h | 10 ++++++- LEGO1/mxdisplaysurface.cpp | 57 ++++++++++++++++++++++++++++++++++++-- LEGO1/mxdisplaysurface.h | 2 +- 5 files changed, 123 insertions(+), 9 deletions(-) diff --git a/LEGO1/lego3dview.h b/LEGO1/lego3dview.h index cafca31a..b984ad0f 100644 --- a/LEGO1/lego3dview.h +++ b/LEGO1/lego3dview.h @@ -2,6 +2,7 @@ #define LEGO3DVIEW_H #include "mxtypes.h" +#include "tgl/d3drm/impl.h" #include "viewmanager/viewmanager.h" class LegoROI; @@ -9,11 +10,18 @@ class LegoROI; class Lego3DView { public: inline ViewManager* GetViewManager() { return this->m_viewManager; } + inline TglImpl::ViewImpl* GetViewPort() { return this->m_viewPort; } LegoROI* PickROI(MxLong p_a, MxLong p_b); private: - char m_pad[0x88]; - ViewManager* m_viewManager; + // TODO: all of these fields are in various base classes + undefined4 m_vtable; // 0x0 (TODO: remove once virtual function added) + undefined4 m_unk0x4; // 0x4 + TglImpl::RendererImpl* m_renderImpl; // 0x8 + TglImpl::DeviceImpl* m_deviceImpl; // 0xc + TglImpl::ViewImpl* m_viewPort; // 0x10 + char m_pad[0x78]; // 0x14 + ViewManager* m_viewManager; // 0x88 }; #endif // LEGO3DVIEW_H diff --git a/LEGO1/legovideomanager.cpp b/LEGO1/legovideomanager.cpp index 167b81a3..098bbe6e 100644 --- a/LEGO1/legovideomanager.cpp +++ b/LEGO1/legovideomanager.cpp @@ -37,6 +37,13 @@ LegoVideoManager::~LegoVideoManager() delete m_palette; } +// STUB: LEGO1 0x1007ac40 +MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) +{ + // TODO + return MxVideoManager::Create(p_videoParam, p_frequencyMS, p_createThread); +} + // FUNCTION: LEGO1 0x1007b5e0 void LegoVideoManager::Destroy() { @@ -69,6 +76,31 @@ void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY) m_cursorY = 463; } +// STUB: LEGO1 0x1007b770 +MxResult LegoVideoManager::Tickle() +{ + // TODO + return FAILURE; +} + +// STUB: LEGO1 0x1007c080 +void LegoVideoManager::VTable0x38(undefined4, undefined4) +{ + // TODO +} + +// FUNCTION: LEGO1 0x1007c290 +MxResult LegoVideoManager::RealizePalette(MxPalette* p_pallete) +{ + if (p_pallete && m_videoParam.GetPalette()) { + p_pallete->GetEntries(m_paletteEntries); + m_videoParam.GetPalette()->SetEntries(m_paletteEntries); + m_displaySurface->SetPalette(m_videoParam.GetPalette()); + } + + return SUCCESS; +} + // FUNCTION: LEGO1 0x1007c300 void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable) { @@ -135,9 +167,7 @@ void LegoVideoManager::SetSkyColor(float p_red, float p_green, float p_blue) colorStrucure.peFlags = -124; m_videoParam.GetPalette()->SetSkyColor(&colorStrucure); m_videoParam.GetPalette()->SetOverrideSkyColor(TRUE); - - // TODO 3d manager - // m_3dManager->m_pViewport->VTable0x1c(red, green, blue) + m_3dManager->GetLego3DView()->GetViewPort()->SetBackgroundColor(p_red, p_green, p_blue); } // FUNCTION: LEGO1 0x1007c4c0 @@ -146,6 +176,21 @@ void LegoVideoManager::OverrideSkyColor(MxBool p_shouldOverride) this->m_videoParam.GetPalette()->SetOverrideSkyColor(p_shouldOverride); } +// FUNCTION: LEGO1 0x1007c4d0 +void LegoVideoManager::VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) +{ + if (p_width == 0) { + p_width = m_videoParam.GetRect().GetWidth(); + } + if (p_height == 0) { + p_height = m_videoParam.GetRect().GetHeight(); + } + + if (!m_initialized) { + m_3dManager->GetLego3DView()->GetViewPort()->ForceUpdate(p_x, p_y, p_width, p_height); + } +} + // STUB: LEGO1 0x1007c560 int LegoVideoManager::EnableRMDevice() { diff --git a/LEGO1/legovideomanager.h b/LEGO1/legovideomanager.h index 11501e2d..122505de 100644 --- a/LEGO1/legovideomanager.h +++ b/LEGO1/legovideomanager.h @@ -21,7 +21,15 @@ class LegoVideoManager : public MxVideoManager { __declspec(dllexport) void EnableFullScreenMovie(MxBool p_enable, MxBool p_scale); __declspec(dllexport) void MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY); - virtual void Destroy() override; // vtable+0x18 + virtual MxResult Tickle() override; // vtable+0x8 + virtual void Destroy() override; // vtable+0x18 + virtual MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) + override; // vtable+0x2c + virtual MxResult RealizePalette(MxPalette*) override; // vtable+0x30 + virtual void VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) override; // vtable+0x34 + virtual void VTable0x38(undefined4, undefined4); // vtable+0x38 + // FUNCTION: LGEO1 0x1007ab10 + virtual undefined4 VTable0x3c() { return m_unk0x4e8; } // vtable+0x3c void SetSkyColor(float p_red, float p_green, float p_blue); void OverrideSkyColor(MxBool p_shouldOverride); diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp index bc1d2078..de4d7006 100644 --- a/LEGO1/mxdisplaysurface.cpp +++ b/LEGO1/mxdisplaysurface.cpp @@ -5,6 +5,8 @@ DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); +MxU32 g_unk0x1010215c = 0; + // FUNCTION: LEGO1 0x100ba500 MxDisplaySurface::MxDisplaySurface() { @@ -248,9 +250,60 @@ undefined4 MxDisplaySurface::VTable0x34(undefined4, undefined4, undefined4, unde return 0; } -// STUB: LEGO1 0x100bba50 -void MxDisplaySurface::Display(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) +// FUNCTION: LEGO1 0x100bba50 +void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height) { + if (m_videoParam.Flags().GetF2bit1()) { + if (m_videoParam.Flags().GetFlipSurfaces()) { + if (g_unk0x1010215c < 2) { + g_unk0x1010215c++; + + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if (m_ddSurface2->Lock(NULL, &ddsd, 1, NULL) == S_OK) { + MxU8* surface = (MxU8*) ddsd.lpSurface; + MxS32 height = m_videoParam.GetRect().GetHeight(); + + for (MxU32 i = 0; i < ddsd.dwHeight; i++) { + memset(surface, 0, ddsd.dwWidth * ddsd.ddpfPixelFormat.dwRGBBitCount / 8); + surface += ddsd.lPitch; + } + + m_ddSurface2->Unlock(ddsd.lpSurface); + } + else { + OutputDebugString("MxDisplaySurface::Display error\n"); + } + } + m_ddSurface1->Flip(NULL, 1); + } + else { + POINT point = {0, 0}; + ClientToScreen(MxOmni::GetInstance()->GetWindowHandle(), &point); + + // TODO: Match + RECT rect1, rect2; + rect1.left = p_left2 + m_videoParam.GetRect().GetLeft() + point.x; + rect2.left = p_left; + rect1.top = p_top2 + m_videoParam.GetRect().GetTop() + point.y; + rect2.right = p_left + p_width; + rect2.top = p_top; + rect2.bottom = p_top + p_height; + rect1.right = rect1.left + p_width; + rect1.bottom = rect1.top + p_height; + + DDBLTFX data; + memset(&data, 0, sizeof(data)); + data.dwSize = sizeof(data); + data.dwDDFX = 8; + + if (m_ddSurface1->Blt(&rect1, m_ddSurface2, &rect2, 0, &data) == DDERR_SURFACELOST) { + m_ddSurface1->Restore(); + m_ddSurface1->Blt(&rect1, m_ddSurface2, &rect2, 0, &data); + } + } + } } // FUNCTION: LEGO1 0x100bbc10 diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index 3d386bb4..45714ce1 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -62,7 +62,7 @@ class MxDisplaySurface : public MxCore { MxBool ); virtual undefined4 VTable0x34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); - virtual void Display(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); + virtual void Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height); virtual void GetDC(HDC* p_hdc); virtual void ReleaseDC(HDC p_hdc); virtual LPDIRECTDRAWSURFACE VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4); From 22d72893f926e5c997107ba88bbecc40438d2acc Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:42:29 -0500 Subject: [PATCH 14/50] Finish LegoEntityPresenter (#363) * Lego entity implementation * Finish LegoEntityPresenter::ReadyTickle * Update legoentitypresenter.h * use empty * Formatting --------- Co-authored-by: Christian Semmler --- LEGO1/define.cpp | 3 ++ LEGO1/define.h | 1 + LEGO1/legoentity.cpp | 6 ++++ LEGO1/legoentity.h | 1 + LEGO1/legoentitypresenter.cpp | 56 +++++++++++++++++++++++++++++++++-- LEGO1/legoentitypresenter.h | 14 ++++++--- LEGO1/mxdsaction.h | 4 ++- LEGO1/mxpresenter.cpp | 23 ++++++++++++++ LEGO1/mxpresenter.h | 2 ++ 9 files changed, 102 insertions(+), 8 deletions(-) diff --git a/LEGO1/define.cpp b/LEGO1/define.cpp index 31f1e521..acd811a8 100644 --- a/LEGO1/define.cpp +++ b/LEGO1/define.cpp @@ -19,6 +19,9 @@ const char* g_strWORLD = "WORLD"; // GLOBAL: LEGO1 0x10101f20 const char* g_strSOUND = "SOUND"; +// GLOBAL: LEGO1 0x10101f58 +const char* g_strOBJECT = "OBJECT"; + // GLOBAL: LEGO1 0x10102040 const char* g_strACTION = "ACTION"; diff --git a/LEGO1/define.h b/LEGO1/define.h index 82e93375..45a536a9 100644 --- a/LEGO1/define.h +++ b/LEGO1/define.h @@ -7,6 +7,7 @@ extern MxU32 g_mxcoreCount[101]; extern const char* g_parseExtraTokens; extern const char* g_strWORLD; extern const char* g_strSOUND; +extern const char* g_strOBJECT; extern const char* g_strACTION; extern const char* g_strVISIBILITY; diff --git a/LEGO1/legoentity.cpp b/LEGO1/legoentity.cpp index 26f9daab..0f813029 100644 --- a/LEGO1/legoentity.cpp +++ b/LEGO1/legoentity.cpp @@ -76,6 +76,12 @@ void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) // TODO } +// STUB: LEGO1 0x100109b0 +void LegoEntity::SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool) +{ + // TODO +} + // STUB: LEGO1 0x10010c30 void LegoEntity::FUN_10010c30() { diff --git a/LEGO1/legoentity.h b/LEGO1/legoentity.h index cdee29c3..4d4c19b6 100644 --- a/LEGO1/legoentity.h +++ b/LEGO1/legoentity.h @@ -49,6 +49,7 @@ class LegoEntity : public MxEntity { virtual void VTable0x4c(); // vtable+0x4c void FUN_10010c30(); + void SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool); protected: void Init(); diff --git a/LEGO1/legoentitypresenter.cpp b/LEGO1/legoentitypresenter.cpp index dc1a44eb..ea484cf1 100644 --- a/LEGO1/legoentitypresenter.cpp +++ b/LEGO1/legoentitypresenter.cpp @@ -1,5 +1,6 @@ #include "legoentitypresenter.h" +#include "islepathactor.h" #include "legoomni.h" #include "legovideomanager.h" @@ -14,7 +15,7 @@ LegoEntityPresenter::LegoEntityPresenter() // FUNCTION: LEGO1 0x100535c0 void LegoEntityPresenter::Init() { - m_unk0x4c = 0; + m_objectBackend = 0; } // FUNCTION: LEGO1 0x100535d0 @@ -24,9 +25,9 @@ LegoEntityPresenter::~LegoEntityPresenter() } // FUNCTION: LEGO1 0x10053630 -undefined4 LegoEntityPresenter::VTable0x6c(undefined4 p_unk0x4c) +undefined4 LegoEntityPresenter::SetBackend(LegoEntity* p_backend) { - m_unk0x4c = p_unk0x4c; + m_objectBackend = p_backend; return 0; } @@ -45,3 +46,52 @@ void LegoEntityPresenter::Destroy() { Destroy(FALSE); } + +// FUNCTION: LEGO1 0x10053680 +MxResult LegoEntityPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + MxResult result = MxCompositePresenter::StartAction(p_controller, p_action); + + if (VideoManager()) { + VideoManager()->AddPresenter(*this); + } + + return result; +} + +// FUNCTION: LEGO1 0x100536c0 +void LegoEntityPresenter::ReadyTickle() +{ + if (GetCurrentWorld()) { + m_objectBackend = (LegoEntity*) MxPresenter::CreateEntityBackend("LegoEntity"); + if (m_objectBackend) { + m_objectBackend->Create(*m_action); + m_objectBackend->SetLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), TRUE); + ParseExtra(); + } + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Starting; + } +} + +// FUNCTION: LEGO1 0x10053720 +void LegoEntityPresenter::RepeatingTickle() +{ + if (m_list.empty()) { + EndAction(); + } +} + +// FUNCTION: LEGO1 0x10053750 +void LegoEntityPresenter::ParseExtra() +{ + char data[512]; + MxU16 len = m_action->GetExtraLength(); + if (len) { + memcpy(data, m_action->GetExtraData(), len); + data[len] = 0; + + len &= MAXWORD; + m_objectBackend->ParseAction(data); + } +} diff --git a/LEGO1/legoentitypresenter.h b/LEGO1/legoentitypresenter.h index 9e072498..847a6b8f 100644 --- a/LEGO1/legoentitypresenter.h +++ b/LEGO1/legoentitypresenter.h @@ -3,6 +3,8 @@ #include "mxcompositepresenter.h" +class LegoEntity; + // VTABLE: LEGO1 0x100d8398 // SIZE 0x50 class LegoEntityPresenter : public MxCompositePresenter { @@ -23,14 +25,18 @@ class LegoEntityPresenter : public MxCompositePresenter { return !strcmp(p_name, LegoEntityPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); } - virtual void Destroy() override; // vtable+0x38 - virtual void Init(); // vtable+0x68 - virtual undefined4 VTable0x6c(undefined4 p_unk0x4c); // vtable+0x6c + virtual void ReadyTickle() override; // vtable+0x18 + virtual void RepeatingTickle(); // vtable+0x24 + virtual void ParseExtra(); // vtable+0x30 + virtual void Destroy() override; // vtable+0x38 + virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + virtual void Init(); // vtable+0x68 + virtual undefined4 SetBackend(LegoEntity* p_unk0x4c); // vtable+0x6c private: void Destroy(MxBool p_fromDestructor); - undefined4 m_unk0x4c; + LegoEntity* m_objectBackend; // 0x4c }; #endif // LEGOENTITYPRESENTER_H diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index eb70b18f..4898eb91 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -63,7 +63,9 @@ class MxDSAction : public MxDSObject { inline MxLong GetStartTime() const { return m_startTime; } inline MxS32 GetLoopCount() { return m_loopCount; } inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } - inline const Vector3Data& GetLocation() const { return m_location; } + inline Vector3Data& GetLocation() { return m_location; } + inline Vector3Data& GetDirection() { return m_direction; } + inline Vector3Data& GetUp() { return m_up; } inline MxCore* GetUnknown84() { return m_unk0x84; } inline void SetUnknown84(MxCore* p_unk0x84) { m_unk0x84 = p_unk0x84; } inline MxCore* GetOrigin() { return m_origin; } diff --git a/LEGO1/mxpresenter.cpp b/LEGO1/mxpresenter.cpp index 31279513..b2404439 100644 --- a/LEGO1/mxpresenter.cpp +++ b/LEGO1/mxpresenter.cpp @@ -2,12 +2,14 @@ #include "decomp.h" #include "define.h" +#include "legoobjectfactory.h" #include "legoomni.h" #include "mxactionnotificationparam.h" #include "mxautolocker.h" #include "mxcompositepresenter.h" #include "mxdsanim.h" #include "mxdssound.h" +#include "mxentity.h" #include "mxnotificationmanager.h" #include "mxparam.h" #include "mxstreamer.h" @@ -304,6 +306,27 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) return name; } +// FUNCTION: LEGO1 0x100b5410 +MxEntity* MxPresenter::CreateEntityBackend(const char* p_name) +{ + char buffer[512]; + char buffer2[512]; + strcpy(buffer, p_name); + + MxU16 extraLen = m_action->GetExtraLength(); + + buffer[0] = extraLen; + buffer[1] = extraLen >> 8; + if (extraLen) { + extraLen &= MAXWORD; + memcpy(buffer2 + 2, m_action->GetExtraData(), extraLen); + buffer2[extraLen + 2] = 0; + KeyValueStringParse(buffer, g_strOBJECT, buffer2 + 2); + } + + return (MxEntity*) ObjectFactory()->Create(buffer); +} + // FUNCTION: LEGO1 0x100b54c0 MxBool MxPresenter::IsEnabled() { diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h index 160329c1..e0e91fe6 100644 --- a/LEGO1/mxpresenter.h +++ b/LEGO1/mxpresenter.h @@ -10,6 +10,7 @@ class MxCompositePresenter; class MxStreamController; +class MxEntity; // VTABLE: LEGO1 0x100d4d38 // SIZE 0x40 @@ -65,6 +66,7 @@ class MxPresenter : public MxCore { virtual MxBool IsHit(MxS32 p_x, MxS32 p_y); // vtable+0x50 __declspec(dllexport) virtual void Enable(MxBool p_enable); // vtable+0x54 + MxEntity* CreateEntityBackend(const char* p_name); MxBool IsEnabled(); inline MxS32 GetCurrentTickleState() const { return this->m_currentTickleState; } From 40d51659d3a25d5a9f2e334bd6a3701e818f3d68 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Tue, 26 Dec 2023 18:10:28 -0500 Subject: [PATCH 15/50] Add most of LegoObjectFactory (#365) * push changes * push changes * fix * Update legoracecar.h --- LEGO1/act3actor.h | 2 +- LEGO1/lego3dwavepresenter.h | 4 +- LEGO1/legoact2.h | 11 +++++ LEGO1/legoobjectfactory.cpp | 97 ++++++++++++++++++++++++++++++++++++ LEGO1/legoobjectfactory.h | 98 ++++++++++++++++++++++++++++++++++++- LEGO1/legoracecar.h | 25 ++++++++++ LEGO1/pizzeria.h | 6 +-- 7 files changed, 236 insertions(+), 7 deletions(-) create mode 100644 LEGO1/legoact2.h create mode 100644 LEGO1/legoracecar.h diff --git a/LEGO1/act3actor.h b/LEGO1/act3actor.h index ef756436..bfdf879a 100644 --- a/LEGO1/act3actor.h +++ b/LEGO1/act3actor.h @@ -3,7 +3,7 @@ // FIXME: Uncertain location. There are three vtables which eventually call this // class' ClassName() function, but none of them call it directly. -class Act3Actor { +class Act3Actor : public MxCore { public: // FUNCTION: LEGO1 0x100431b0 inline virtual const char* ClassName() override diff --git a/LEGO1/lego3dwavepresenter.h b/LEGO1/lego3dwavepresenter.h index a2363518..ca72f212 100644 --- a/LEGO1/lego3dwavepresenter.h +++ b/LEGO1/lego3dwavepresenter.h @@ -1,11 +1,11 @@ #ifndef LEGO3DWAVEPRESENTER_H #define LEGO3DWAVEPRESENTER_H -#include "legowavepresenter.h" +#include "mxwavepresenter.h" // VTABLE: LEGO1 0x100d52b0 // SIZE 0xa0 -class Lego3DWavePresenter : public LegoWavePresenter { +class Lego3DWavePresenter : public MxWavePresenter { public: // FUNCTION: LEGO1 0x1000d890 inline virtual const char* ClassName() const override // vtable+0x0c diff --git a/LEGO1/legoact2.h b/LEGO1/legoact2.h new file mode 100644 index 00000000..b504c11c --- /dev/null +++ b/LEGO1/legoact2.h @@ -0,0 +1,11 @@ +#ifndef LEGOACT2_H +#define LEGOACT2_H + +#include "legocarraceactor.h" +#include "legopathactor.h" + +// VTABLE: LEGO1 0x100d82e0 +// SIZE: 0x1154 +class LegoAct2 : public LegoWorld {}; + +#endif // LEGOACT2_H diff --git a/LEGO1/legoobjectfactory.cpp b/LEGO1/legoobjectfactory.cpp index 2c77c7a9..ff52bad1 100644 --- a/LEGO1/legoobjectfactory.cpp +++ b/LEGO1/legoobjectfactory.cpp @@ -1,7 +1,104 @@ #include "legoobjectfactory.h" +#include "carrace.h" #include "decomp.h" +#include "dunebuggy.h" +#include "elevatorbottom.h" +#include "gasstation.h" +#include "gasstationstate.h" +#include "helicopter.h" +#include "helicopterstate.h" +#include "historybook.h" +#include "hospital.h" +#include "hospitalstate.h" +#include "infocenter.h" +#include "infocenterdoor.h" #include "infocenterstate.h" +#include "isle.h" +#include "jetskirace.h" +#include "lego3dwavepresenter.h" +#include "legoact2.h" +#include "legoact2state.h" +#include "legoactioncontrolpresenter.h" +#include "legoactor.h" +#include "legoactorpresenter.h" +#include "legoanimactor.h" +#include "legoanimpresenter.h" +#include "legocarbuild.h" +#include "legocarbuildanimpresenter.h" +#include "legocarraceactor.h" +#include "legoentity.h" +#include "legoentitypresenter.h" +#include "legoflctexturepresenter.h" +#include "legohideanimpresenter.h" +#include "legojetski.h" +#include "legojetskiraceactor.h" +#include "legoloadcachesoundpresenter.h" +#include "legolocomotionanimpresenter.h" +#include "legoloopinganimpresenter.h" +#include "legomodelpresenter.h" +#include "legopalettepresenter.h" +#include "legopartpresenter.h" +#include "legopathactor.h" +#include "legopathpresenter.h" +#include "legophonemepresenter.h" +#include "legoracecar.h" +#include "legotexturepresenter.h" +#include "legoworld.h" +#include "legoworldpresenter.h" +#include "mxcontrolpresenter.h" +#include "mxvideopresenter.h" +#include "pizza.h" +#include "pizzamissionstate.h" +#include "police.h" +#include "policestate.h" +#include "registrationbook.h" +#include "score.h" +#include "scorestate.h" +#include "skateboard.h" +// #include "act2actor.h" +#include "act2brick.h" +// #include "act2genactor.h" +#include "act2policestation.h" +#include "act3.h" +#include "act3state.h" +#include "ambulance.h" +#include "ambulancemissionstate.h" +#include "bike.h" +#include "doors.h" +#include "jetski.h" +#include "legoanimmmpresenter.h" +#include "motorcycle.h" +#include "racecar.h" +#include "towtrack.h" +#include "towtrackmissionstate.h" +// #include "act3cop.h" +// #include "act3brickster.h" +#include "act1state.h" +#include "act3actor.h" +#include "act3shark.h" +#include "beachhouseentity.h" +#include "bumpbouy.h" +#include "carracestate.h" +#include "gasstationentity.h" +#include "hospitalentity.h" +#include "infocenterentity.h" +#include "jetskiracestate.h" +#include "jukeboxentity.h" +#include "pizzeria.h" +#include "pizzeriastate.h" +#include "policeentity.h" +#include "racestandsentity.h" +#include "radiostate.h" +// #include "caveentity.h" +// #include "jailentity.h" +#include "jukebox.h" +#include "jukeboxstate.h" +#include "mxcompositemediapresenter.h" +// #include "raceskel.h" +#include "animstate.h" + +// TODO: Before HospitalState, add all of the different LegoVehicleBuildState's // TODO: Uncomment once we have all the relevant types ready // DECOMP_SIZE_ASSERT(LegoObjectFactory, 0x1c8); diff --git a/LEGO1/legoobjectfactory.h b/LEGO1/legoobjectfactory.h index 82117d34..3a575c52 100644 --- a/LEGO1/legoobjectfactory.h +++ b/LEGO1/legoobjectfactory.h @@ -3,7 +3,103 @@ #include "mxobjectfactory.h" -#define FOR_LEGOOBJECTFACTORY_OBJECTS(X) X(InfocenterState) +#define FOR_LEGOOBJECTFACTORY_OBJECTS(X) \ + X(LegoModelPresenter) \ + X(LegoTexturePresenter) \ + X(LegoPhonemePresenter) \ + X(LegoFlcTexturePresenter) \ + X(LegoEntityPresenter) \ + X(LegoActorPresenter) \ + X(LegoWorldPresenter) \ + X(LegoWorld) \ + X(LegoPalettePresenter) \ + X(LegoPathPresenter) \ + X(LegoAnimPresenter) \ + X(LegoLoopingAnimPresenter) \ + X(LegoLocomotionAnimPresenter) \ + X(LegoHideAnimPresenter) \ + X(LegoPartPresenter) \ + X(LegoCarBuildAnimPresenter) \ + X(LegoActionControlPresenter) \ + X(MxVideoPresenter) \ + X(LegoLoadCacheSoundPresenter) \ + X(Lego3DWavePresenter) \ + X(LegoActor) \ + X(LegoPathActor) \ + X(LegoRaceCar) \ + X(LegoJetski) \ + /*X(JetskiRace) \*/ \ + X(LegoEntity) \ + X(LegoCarRaceActor) \ + X(LegoJetskiRaceActor) \ + X(LegoCarBuild) \ + X(Infocenter) \ + X(LegoAnimActor) \ + X(MxControlPresenter) \ + X(RegistrationBook) \ + X(HistoryBook) \ + X(ElevatorBottom) \ + X(InfocenterDoor) \ + X(Score) \ + X(ScoreState) \ + X(Hospital) \ + X(Isle) \ + X(Police) \ + X(GasStation) \ + X(LegoAct2) \ + X(LegoAct2State) \ + /*X(CarRace)*/ \ + X(HospitalState) \ + X(InfocenterState) \ + X(PoliceState) \ + X(GasStationState) \ + X(SkateBoard) \ + X(Helicopter) \ + X(HelicopterState) \ + X(DuneBuggy) \ + X(Pizza) \ + X(PizzaMissionState) \ + /*X(Act2Actor)*/ \ + /*X(Act2Brick)*/ \ + /*X(Act2GenActor)*/ \ + X(Act2PoliceStation) \ + X(Act3) \ + X(Act3State) \ + X(Doors) \ + X(LegoAnimMMPresenter) \ + X(RaceCar) \ + X(Jetski) \ + X(Bike) \ + X(Motorcycle) \ + X(Ambulance) \ + X(AmbulanceMissionState) \ + X(TowTrack) \ + X(TowTrackMissionState) \ + /*X(Act3Cop)*/ \ + /*X(Act3Brickster)*/ \ + X(Act3Shark) \ + X(BumpBouy) \ + X(Act3Actor) \ + X(JetskiRaceState) \ + X(CarRaceState) \ + X(Act1State) \ + X(Pizzeria) \ + X(PizzeriaState) \ + X(InfoCenterEntity) \ + X(HospitalEntity) \ + X(GasStationEntity) \ + X(PoliceEntity) \ + X(BeachHouseEntity) \ + X(RaceStandsEntity) \ + X(JukeBoxEntity) \ + X(RadioState) \ + /*X(CaveEntity)*/ \ + /*X(JailEntity)*/ \ + X(MxCompositeMediaPresenter) \ + X(JukeBox) \ + X(JukeBoxState) \ + /*X(RaceSkel)*/ \ + X(AnimState) // VTABLE: LEGO1 0x100d4768 class LegoObjectFactory : public MxObjectFactory { diff --git a/LEGO1/legoracecar.h b/LEGO1/legoracecar.h new file mode 100644 index 00000000..38099af2 --- /dev/null +++ b/LEGO1/legoracecar.h @@ -0,0 +1,25 @@ +#ifndef LEGOCARRACE_H +#define LEGOCARRACE_H + +#include "legocarraceactor.h" +#include "legopathactor.h" + +// VTABLE: LEGO1 0x100d58b8 +// SIZE: 0x200 +class LegoRaceCar : public LegoCarRaceActor { +public: + // FUNCTION: LEGO1 0x10014290 + inline const char* ClassName() const override // vtable+0xc + { + // GLOBAL: LEGO1 0x100f0548 + return "LegoRaceCar"; + } + + // FUNCTION: LEGO1 0x100142b0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name); + } +}; + +#endif // LEGOCARRACE_H diff --git a/LEGO1/pizzeria.h b/LEGO1/pizzeria.h index 65a3b195..b9fcadf3 100644 --- a/LEGO1/pizzeria.h +++ b/LEGO1/pizzeria.h @@ -1,5 +1,5 @@ -#ifndef PIZZERIASTATE_H -#define PIZZERIASTATE_H +#ifndef PIZZERIA_H +#define PIZZERIA_H #include "isleactor.h" @@ -21,4 +21,4 @@ class Pizzeria : public IsleActor { } }; -#endif // PIZZERIASTATE_H +#endif // PIZZERIA_H From b35a121ee2ad19f59f2965e7ce7a0d9a97c1e717 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 26 Dec 2023 19:44:55 -0500 Subject: [PATCH 16/50] Fix LegoModelPresenter::IsA --- LEGO1/legomodelpresenter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LEGO1/legomodelpresenter.h b/LEGO1/legomodelpresenter.h index b529fede..df9cbba1 100644 --- a/LEGO1/legomodelpresenter.h +++ b/LEGO1/legomodelpresenter.h @@ -19,7 +19,7 @@ class LegoModelPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x1000ccc0 inline MxBool IsA(const char* p_name) const override // vtable+0x10 { - return !strcmp(p_name, LegoModelPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); + return !strcmp(p_name, ClassName()) || MxVideoPresenter::IsA(p_name); } }; From 59d999f6dcfa225f4f6291566afa333835c1e542 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Tue, 26 Dec 2023 19:45:48 -0500 Subject: [PATCH 17/50] LegoWorldPresenter vtables (#366) * Legoworld vtables * fixes * fix * formatting --------- Co-authored-by: Christian Semmler --- LEGO1/legoentitypresenter.cpp | 8 +++++++ LEGO1/legoentitypresenter.h | 3 +++ LEGO1/legoomni.cpp | 6 ++++++ LEGO1/legoomni.h | 1 + LEGO1/legoworldpresenter.cpp | 39 +++++++++++++++++++++++++++++++++++ LEGO1/legoworldpresenter.h | 6 ++++++ 6 files changed, 63 insertions(+) diff --git a/LEGO1/legoentitypresenter.cpp b/LEGO1/legoentitypresenter.cpp index ea484cf1..7a586c80 100644 --- a/LEGO1/legoentitypresenter.cpp +++ b/LEGO1/legoentitypresenter.cpp @@ -82,6 +82,14 @@ void LegoEntityPresenter::RepeatingTickle() } } +// FUNCTION: LEGO1 0x10053730 +void LegoEntityPresenter::SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up) +{ + if (m_objectBackend) { + m_objectBackend->SetLocation(p_location, p_direction, p_up, TRUE); + } +} + // FUNCTION: LEGO1 0x10053750 void LegoEntityPresenter::ParseExtra() { diff --git a/LEGO1/legoentitypresenter.h b/LEGO1/legoentitypresenter.h index 847a6b8f..994e5a79 100644 --- a/LEGO1/legoentitypresenter.h +++ b/LEGO1/legoentitypresenter.h @@ -33,9 +33,12 @@ class LegoEntityPresenter : public MxCompositePresenter { virtual void Init(); // vtable+0x68 virtual undefined4 SetBackend(LegoEntity* p_unk0x4c); // vtable+0x6c + void SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up); + private: void Destroy(MxBool p_fromDestructor); +protected: LegoEntity* m_objectBackend; // 0x4c }; diff --git a/LEGO1/legoomni.cpp b/LEGO1/legoomni.cpp index cd3438a7..8c9e5905 100644 --- a/LEGO1/legoomni.cpp +++ b/LEGO1/legoomni.cpp @@ -568,6 +568,12 @@ LegoOmni* LegoOmni::GetInstance() return (LegoOmni*) MxOmni::GetInstance(); } +// FUNCTION: LEGO1 0x1005ad20 +void LegoOmni::AddWorld(LegoWorld* p_world) +{ + m_worldList->Append(p_world); +} + // STUB: LEGO1 0x1005af10 void LegoOmni::RemoveWorld(const MxAtomId&, MxLong) { diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index 69f6964a..81c3d6f1 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -98,6 +98,7 @@ class LegoOmni : public MxOmni { virtual void StopTimer() override; // vtable+3c LegoEntity* FindByEntityIdOrAtomId(const MxAtomId& p_atom, MxS32 p_entityid); + void AddWorld(LegoWorld* p_world); LegoVideoManager* GetVideoManager() { return (LegoVideoManager*) m_videoManager; } LegoSoundManager* GetSoundManager() { return (LegoSoundManager*) m_soundManager; } diff --git a/LEGO1/legoworldpresenter.cpp b/LEGO1/legoworldpresenter.cpp index 9cd12880..52e99926 100644 --- a/LEGO1/legoworldpresenter.cpp +++ b/LEGO1/legoworldpresenter.cpp @@ -1,5 +1,8 @@ #include "legoworldpresenter.h" +#include "legoentity.h" +#include "legoomni.h" + // GLOBAL: LEGO1 0x100f75d4 undefined4 g_legoWorldPresenterQuality = 1; @@ -20,3 +23,39 @@ LegoWorldPresenter::~LegoWorldPresenter() { // TODO } + +// STUB: LEGO1 0x10066870 +MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + return FAILURE; +} + +// FUNCTION: LEGO1 0x10066a50 +void LegoWorldPresenter::ReadyTickle() +{ + m_objectBackend = (LegoEntity*) MxPresenter::CreateEntityBackend("LegoWorld"); + if (m_objectBackend) { + m_objectBackend->Create(*m_action); + Lego()->AddWorld((LegoWorld*) m_objectBackend); + SetBackendLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp()); + } + + ParseExtra(); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Starting; +} + +// STUB: LEGO1 0x10066ac0 +void LegoWorldPresenter::StartingTickle() +{ +} + +// STUB: LEGO1 0x10067a70 +void LegoWorldPresenter::VTable0x60(MxPresenter* p_presenter) +{ +} + +// STUB: LEGO1 0x10067b00 +void LegoWorldPresenter::ParseExtra() +{ +} diff --git a/LEGO1/legoworldpresenter.h b/LEGO1/legoworldpresenter.h index bcae2f5e..3cd02a8f 100644 --- a/LEGO1/legoworldpresenter.h +++ b/LEGO1/legoworldpresenter.h @@ -25,6 +25,12 @@ class LegoWorldPresenter : public LegoEntityPresenter { return !strcmp(p_name, LegoWorldPresenter::ClassName()) || LegoEntityPresenter::IsA(p_name); } + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StartingTickle() override; // vtable+0x1c + virtual void ParseExtra() override; // vtable+0x30 + virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + virtual void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 + private: undefined4 m_unk0x50; }; From cfe28a2b26fa6c10d2e2de3ea65900c50b51da4d Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 26 Dec 2023 20:33:53 -0500 Subject: [PATCH 18/50] Implement/match MxStreamController::FUN_100c1f00 (#367) --- LEGO1/mxdschunk.h | 10 +++++----- LEGO1/mxstreamcontroller.cpp | 31 ++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/LEGO1/mxdschunk.h b/LEGO1/mxdschunk.h index ec4a8cbe..70209596 100644 --- a/LEGO1/mxdschunk.h +++ b/LEGO1/mxdschunk.h @@ -56,11 +56,11 @@ class MxDSChunk : public MxCore { } protected: - MxU16 m_flags; // 0x8 - undefined4 m_objectId; // 0xc - MxLong m_time; // 0x10 - MxU32 m_length; // 0x14 - MxU8* m_data; // 0x18 + MxU16 m_flags; // 0x8 + MxU32 m_objectId; // 0xc + MxLong m_time; // 0x10 + MxU32 m_length; // 0x14 + MxU8* m_data; // 0x18 }; #endif // MXDSCHUNK_H diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp index 726a8fa1..02d43a01 100644 --- a/LEGO1/mxstreamcontroller.cpp +++ b/LEGO1/mxstreamcontroller.cpp @@ -3,6 +3,7 @@ #include "legoomni.h" #include "legoutil.h" #include "mxautolocker.h" +#include "mxdsmultiaction.h" #include "mxdsstreamingaction.h" #include "mxnextactiondatastart.h" #include "mxstl/stlcompat.h" @@ -252,11 +253,35 @@ MxPresenter* MxStreamController::FUN_100c1e70(MxDSAction& p_action) return result; } -// STUB: LEGO1 0x100c1f00 +// FUNCTION: LEGO1 0x100c1f00 MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action) { - // TODO - return FAILURE; + MxAutoLocker lock(&m_criticalSection); + + MxU32 objectId = p_action->GetObjectId(); + MxStreamChunk* chunk = new MxStreamChunk; + + if (!chunk) + return FAILURE; + + chunk->SetFlags(MxDSChunk::Flag_Bit3); + chunk->SetObjectId(objectId); + + if (chunk->SendChunk(m_subscriberList, FALSE, p_action->GetUnknown24()) != SUCCESS) + delete chunk; + + if (p_action->IsA("MxDSMultiAction")) { + MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + while (cursor.Next(action)) { + if (FUN_100c1f00(action) != SUCCESS) + return FAILURE; + } + } + + return SUCCESS; } // STUB: LEGO1 0x100c20b0 From 88d267f9f3be197110c45ca73f0f7b8bdd77fb92 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 26 Dec 2023 20:39:48 -0500 Subject: [PATCH 19/50] Implement/match MxStreamController::FindNextActionDataStartFromStreamingAction (#368) * Implement/match MxStreamController::FUN_100c1f00 * Implement/match MxStreamController::FindNextActionDataStartFromStreamingAction --- LEGO1/mxstreamcontroller.cpp | 6 +++--- LEGO1/mxstreamlist.cpp | 13 ++++++++++++- LEGO1/mxstreamlist.h | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp index 02d43a01..74df9dc9 100644 --- a/LEGO1/mxstreamcontroller.cpp +++ b/LEGO1/mxstreamcontroller.cpp @@ -215,7 +215,7 @@ MxResult MxStreamController::VTable0x30(MxDSAction* p_action) MxResult result = FAILURE; MxDSAction* action = m_unk0x3c.Find(p_action, TRUE); if (action != NULL) { - MxNextActionDataStart* data = m_nextActionList.Find(action->GetObjectId(), action->GetUnknown24()); + MxNextActionDataStart* data = m_nextActionList.FindAndErase(action->GetObjectId(), action->GetUnknown24()); delete action; delete data; result = SUCCESS; @@ -284,10 +284,10 @@ MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action) return SUCCESS; } -// STUB: LEGO1 0x100c20b0 +// FUNCTION: LEGO1 0x100c20b0 MxNextActionDataStart* MxStreamController::FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action) { - return NULL; + return m_nextActionList.Find(p_action->GetObjectId(), p_action->GetUnknown24()); } // STUB: LEGO1 0x100c20d0 diff --git a/LEGO1/mxstreamlist.cpp b/LEGO1/mxstreamlist.cpp index 1fa4dd48..d422c1cb 100644 --- a/LEGO1/mxstreamlist.cpp +++ b/LEGO1/mxstreamlist.cpp @@ -30,8 +30,19 @@ MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) return found; } -// FUNCTION: LEGO1 0x100c2240 +// FUNCTION: LEGO1 0x100c21e0 MxNextActionDataStart* MxStreamListMxNextActionDataStart::Find(MxU32 p_id, MxS16 p_value) +{ + for (iterator it = begin(); it != end(); it++) { + if (p_id == (*it)->GetObjectId() && p_value == (*it)->GetUnknown24()) + return *it; + } + + return NULL; +} + +// FUNCTION: LEGO1 0x100c2240 +MxNextActionDataStart* MxStreamListMxNextActionDataStart::FindAndErase(MxU32 p_id, MxS16 p_value) { MxNextActionDataStart* match = NULL; diff --git a/LEGO1/mxstreamlist.h b/LEGO1/mxstreamlist.h index 6aa63de0..86b9a002 100644 --- a/LEGO1/mxstreamlist.h +++ b/LEGO1/mxstreamlist.h @@ -41,7 +41,8 @@ class MxStreamListMxDSAction : public MxStreamList { // SIZE 0xc class MxStreamListMxNextActionDataStart : public MxStreamList { public: - MxNextActionDataStart* Find(MxU32, MxS16); + MxNextActionDataStart* Find(MxU32 p_id, MxS16 p_value); + MxNextActionDataStart* FindAndErase(MxU32 p_id, MxS16 p_value); }; // SIZE 0xc From 6e947c3789021d87797c4c3ee3fba3eb4977cb71 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 26 Dec 2023 20:54:17 -0500 Subject: [PATCH 20/50] Implement/match MxStreamController::FUN_100c20d0 (#369) * Implement/match MxStreamController::FUN_100c1f00 * Implement/match MxStreamController::FUN_100c20d0 --- LEGO1/mxstreamcontroller.cpp | 17 +++++++++++++++-- LEGO1/mxstreamlist.cpp | 14 ++++++++++++++ LEGO1/mxstreamlist.h | 5 ++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp index 74df9dc9..e45435ac 100644 --- a/LEGO1/mxstreamcontroller.cpp +++ b/LEGO1/mxstreamcontroller.cpp @@ -290,9 +290,22 @@ MxNextActionDataStart* MxStreamController::FindNextActionDataStartFromStreamingA return m_nextActionList.Find(p_action->GetObjectId(), p_action->GetUnknown24()); } -// STUB: LEGO1 0x100c20d0 +// FUNCTION: LEGO1 0x100c20d0 MxBool MxStreamController::FUN_100c20d0(MxDSObject& p_obj) { - // TODO + if (m_subscriberList.Find(&p_obj)) + return FALSE; + + if (p_obj.IsA("MxDSMultiAction")) { + MxDSActionList* actions = ((MxDSMultiAction&) p_obj).GetActionList(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + while (cursor.Next(action)) { + if (!FUN_100c20d0(*action)) + return FALSE; + } + } + return TRUE; } diff --git a/LEGO1/mxstreamlist.cpp b/LEGO1/mxstreamlist.cpp index d422c1cb..729b0d7b 100644 --- a/LEGO1/mxstreamlist.cpp +++ b/LEGO1/mxstreamlist.cpp @@ -5,6 +5,20 @@ DECOMP_SIZE_ASSERT(MxStreamListMxDSAction, 0xc); DECOMP_SIZE_ASSERT(MxStreamListMxNextActionDataStart, 0xc); DECOMP_SIZE_ASSERT(MxStreamListMxDSSubscriber, 0xc); +// FUNCTION: LEGO1 0x100b8450 +MxDSSubscriber* MxStreamListMxDSSubscriber::Find(MxDSObject* p_object) +{ + for (iterator it = begin(); it != end(); it++) { + if (p_object->GetObjectId() == -1 || p_object->GetObjectId() == (*it)->GetObjectId()) { + if (p_object->GetUnknown24() == -2 || p_object->GetUnknown24() == (*it)->GetUnknown48()) { + return *it; + } + } + } + + return NULL; +} + // FUNCTION: LEGO1 0x100bfa80 MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) { diff --git a/LEGO1/mxstreamlist.h b/LEGO1/mxstreamlist.h index 86b9a002..f9164bfb 100644 --- a/LEGO1/mxstreamlist.h +++ b/LEGO1/mxstreamlist.h @@ -46,6 +46,9 @@ class MxStreamListMxNextActionDataStart : public MxStreamList {}; +class MxStreamListMxDSSubscriber : public MxStreamList { +public: + MxDSSubscriber* Find(MxDSObject* p_object); +}; #endif // MXSTREAMLIST_H From ac6eb28dc4d956b6e85921be335e47dacaad2424 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 26 Dec 2023 21:17:20 -0500 Subject: [PATCH 21/50] Implement/match MxStreamer::DeleteObject (#370) --- LEGO1/mxstreamer.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/LEGO1/mxstreamer.cpp b/LEGO1/mxstreamer.cpp index c35a4e8f..1688c1b8 100644 --- a/LEGO1/mxstreamer.cpp +++ b/LEGO1/mxstreamer.cpp @@ -142,7 +142,7 @@ MxResult MxStreamer::FUN_100b99b0(MxDSAction* p_action) return FAILURE; } -// STUB: LEGO1 0x100b99f0 +// FUNCTION: LEGO1 0x100b99f0 MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction) { MxDSAction tempAction; @@ -156,8 +156,16 @@ MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction) tempAction.SetUnknown24(p_dsAction->GetUnknown24()); } - // TODO: remove action from list - return FAILURE; + MxResult result = FAILURE; + for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { + const char* id = p_dsAction->GetAtomId().GetInternal(); + if (!id || id == (*it)->GetAtom().GetInternal()) { + tempAction.SetAtomId((*it)->GetAtom()); + result = (*it)->VTable0x24(&tempAction); + } + } + + return result; } // FUNCTION: LEGO1 0x100b9b30 From 5a1ba0277273e07147649bda9f6edddecae84b38 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:31:06 -0500 Subject: [PATCH 22/50] implement LegoWorldPresenter::StartAction (#371) --- LEGO1/legoworldpresenter.cpp | 58 ++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/LEGO1/legoworldpresenter.cpp b/LEGO1/legoworldpresenter.cpp index 52e99926..7a17ad7a 100644 --- a/LEGO1/legoworldpresenter.cpp +++ b/LEGO1/legoworldpresenter.cpp @@ -2,6 +2,14 @@ #include "legoentity.h" #include "legoomni.h" +#include "legovideomanager.h" +#include "mxactionnotificationparam.h" +#include "mxautolocker.h" +#include "mxdsactionlist.h" +#include "mxdsmultiaction.h" +#include "mxobjectfactory.h" +#include "mxpresenter.h" +#include "mxstl/stlcompat.h" // GLOBAL: LEGO1 0x100f75d4 undefined4 g_legoWorldPresenterQuality = 1; @@ -24,10 +32,56 @@ LegoWorldPresenter::~LegoWorldPresenter() // TODO } -// STUB: LEGO1 0x10066870 +// FUNCTION: LEGO1 0x10066870 MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) { - return FAILURE; + MxAutoLocker lock(&m_criticalSection); + + MxResult result = FAILURE; + MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList(); + MxObjectFactory* factory = ObjectFactory(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + if (MxPresenter::StartAction(p_controller, p_action) == SUCCESS) { + // The usual cursor.Next() loop doesn't match here, even though + // the logic is the same. It does match when "deconstructed" into + // the following Head(), Current() and NextFragment() calls, + // but this seems unlikely to be the original code. + // The alpha debug build also uses Next(). + cursor.Head(); + while (cursor.Current(action)) { + cursor.NextFragment(); + + MxBool success = FALSE; + + action->CopyFlags(m_action->GetFlags()); + + const char* presenterName = PresenterNameDispatch(*action); + MxPresenter* presenter = (MxPresenter*) factory->Create(presenterName); + + if (presenter && presenter->AddToManager() == SUCCESS) { + presenter->SetCompositePresenter(this); + if (presenter->StartAction(p_controller, action) == SUCCESS) { + presenter->SetTickleState(TickleState_Idle); + success = TRUE; + } + } + + if (success) { + action->SetOrigin(this); + m_list.push_back(presenter); + } + else if (presenter) + delete presenter; + } + + VideoManager()->AddPresenter(*this); + + result = SUCCESS; + } + + return result; } // FUNCTION: LEGO1 0x10066a50 From f1f6743d08d654b106750dc45d0ec273b8882d4d Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Wed, 27 Dec 2023 13:27:02 -0500 Subject: [PATCH 23/50] CarRace ctor (#372) * CarRace ctor * Fixes --------- Co-authored-by: Christian Semmler --- LEGO1/carrace.cpp | 7 +++++-- LEGO1/carrace.h | 5 +++++ LEGO1/legorace.h | 37 +++++++++++++++++++++---------------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/LEGO1/carrace.cpp b/LEGO1/carrace.cpp index 6da96168..9fdb353f 100644 --- a/LEGO1/carrace.cpp +++ b/LEGO1/carrace.cpp @@ -1,7 +1,10 @@ #include "carrace.h" -// STUB: LEGO1 0x10016a90 +DECOMP_SIZE_ASSERT(CarRace, 0x154); + +// FUNCTION: LEGO1 0x10016a90 CarRace::CarRace() { - // TODO + this->m_unk0x150 = 0; + this->m_unk0x130 = MxRect32(0x16c, 0x154, 0x1ec, 0x15e); } diff --git a/LEGO1/carrace.h b/LEGO1/carrace.h index b876fd4d..3b9a768e 100644 --- a/LEGO1/carrace.h +++ b/LEGO1/carrace.h @@ -1,6 +1,7 @@ #ifndef CARRACE_H #define CARRACE_H +#include "decomp.h" #include "legorace.h" // VTABLE: LEGO1 0x100d5e50 @@ -21,6 +22,10 @@ class CarRace : public LegoRace { { return !strcmp(p_name, CarRace::ClassName()) || LegoRace::IsA(p_name); } + +private: + undefined m_unk0x144[12]; // 0x144 + undefined4 m_unk0x150; // 0x150 }; #endif // CARRACE_H diff --git a/LEGO1/legorace.h b/LEGO1/legorace.h index 8ae52d8e..9ddbdfb3 100644 --- a/LEGO1/legorace.h +++ b/LEGO1/legorace.h @@ -3,6 +3,7 @@ #include "decomp.h" #include "legoworld.h" +#include "mxrect32.h" #include "mxtypes.h" // VTABLE: LEGO1 0x100d5db0 @@ -38,22 +39,26 @@ class LegoRace : public LegoWorld { virtual void VTable0x7c(undefined4, undefined4); // vtable+0x7c private: - undefined4 m_unk0xf8; // 0xf8 - undefined4 m_unk0xfc; // 0xfc - undefined4 m_unk0x100; // 0x100 - undefined4 m_unk0x104; // 0x104 - undefined4 m_unk0x108; // 0x108 - undefined4 m_unk0x10c; // 0x10c - undefined4 m_unk0x110; // 0x110 - undefined4 m_unk0x114; // 0x114 - undefined4 m_unk0x118; // 0x118 - undefined4 m_unk0x11c; // 0x11c - undefined4 m_unk0x120; // 0x120 - this may be the current vehcle (function at 0x10015880) - undefined4 m_unk0x124; // 0x124 - something game state - undefined4 m_unk0x128; // 0x128 - undefined4 m_unk0x12c; // 0x12c - undefined4 m_unk0x130[4]; // unconfirmed bytes, ghidra claims these are integers - undefined4 m_unk0x140; + undefined4 m_unk0xf8; // 0xf8 + undefined4 m_unk0xfc; // 0xfc + undefined4 m_unk0x100; // 0x100 + undefined4 m_unk0x104; // 0x104 + undefined4 m_unk0x108; // 0x108 + undefined4 m_unk0x10c; // 0x10c + undefined4 m_unk0x110; // 0x110 + undefined4 m_unk0x114; // 0x114 + undefined4 m_unk0x118; // 0x118 + undefined4 m_unk0x11c; // 0x11c + undefined4 m_unk0x120; // 0x120 + undefined4 m_unk0x124; // 0x124 + undefined4 m_unk0x128; // 0x128 + undefined4 m_unk0x12c; // 0x12c + +protected: + MxRect32 m_unk0x130; // 0x130 + +private: + undefined4 m_unk0x140; // 0x140 }; #endif // LEGORACE_H From d2b05a09831b71d0e3c4052d6b2b33dd8540c08f Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Wed, 27 Dec 2023 13:30:16 -0500 Subject: [PATCH 24/50] LegoFlcTexturePresenter init function (#373) * LegoFlcTexturePresenter init function say that 5 times fast * Fixes --------- Co-authored-by: Christian Semmler --- LEGO1/legoflctexturepresenter.cpp | 13 +++++++++++-- LEGO1/legoflctexturepresenter.h | 7 +++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/LEGO1/legoflctexturepresenter.cpp b/LEGO1/legoflctexturepresenter.cpp index 29a49814..f96d2b47 100644 --- a/LEGO1/legoflctexturepresenter.cpp +++ b/LEGO1/legoflctexturepresenter.cpp @@ -1,7 +1,16 @@ #include "legoflctexturepresenter.h" -// STUB: LEGO1 0x1005de80 +DECOMP_SIZE_ASSERT(LegoFlcTexturePresenter, 0x70) + +// FUNCTION: LEGO1 0x1005de80 LegoFlcTexturePresenter::LegoFlcTexturePresenter() { - // TODO + Init(); +} + +// FUNCTION: LEGO1 0x1005df70 +void LegoFlcTexturePresenter::Init() +{ + this->m_unk0x68 = 0; + this->m_unk0x6c = 0; } diff --git a/LEGO1/legoflctexturepresenter.h b/LEGO1/legoflctexturepresenter.h index c68d045d..c55249cf 100644 --- a/LEGO1/legoflctexturepresenter.h +++ b/LEGO1/legoflctexturepresenter.h @@ -1,6 +1,7 @@ #ifndef LEGOFLCTEXTUREPRESENTER_H #define LEGOFLCTEXTUREPRESENTER_H +#include "decomp.h" #include "mxflcpresenter.h" // VTABLE: LEGO1 0x100d89e0 @@ -15,6 +16,12 @@ class LegoFlcTexturePresenter : public MxFlcPresenter { // GLOBAL: LEGO1 0x100f0634 return "LegoFlcTexturePresenter"; } + +private: + void Init(); + + undefined4 m_unk0x68; // 0x68 + undefined4 m_unk0x6c; // 0x6c }; #endif // LEGOFLCTEXTUREPRESENTER_H From c6174c2a13eac4151d72a85076860c66682c7f20 Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Wed, 27 Dec 2023 13:32:32 -0500 Subject: [PATCH 25/50] Bootstrap rest of LegoTexturePresenter (#374) * Bootstrap rest of LegoTexturePresenter * Fixes --------- Co-authored-by: Christian Semmler --- LEGO1/legotexturepresenter.cpp | 19 +++++++++++++++++++ LEGO1/legotexturepresenter.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/LEGO1/legotexturepresenter.cpp b/LEGO1/legotexturepresenter.cpp index 36a7e243..6d0cbe8c 100644 --- a/LEGO1/legotexturepresenter.cpp +++ b/LEGO1/legotexturepresenter.cpp @@ -2,6 +2,7 @@ #include "legoomni.h" #include "legovideomanager.h" +#include "mxcompositepresenter.h" // FUNCTION: LEGO1 0x1004eb40 LegoTexturePresenter::~LegoTexturePresenter() @@ -15,3 +16,21 @@ MxResult LegoTexturePresenter::AddToManager() VideoManager()->AddPresenter(*this); return SUCCESS; } + +// STUB: LEGO1 0x1004fc60 +MxResult LegoTexturePresenter::PutData() +{ + // TODO + return FAILURE; +} + +// FUNCTION: LEGO1 0x1004fcb0 +void LegoTexturePresenter::DoneTickle() +{ + if (this->m_compositePresenter && !this->m_compositePresenter->VTable0x64(2)) { + SetTickleState(TickleState_Idle); + return; + } + + MxMediaPresenter::DoneTickle(); +} diff --git a/LEGO1/legotexturepresenter.h b/LEGO1/legotexturepresenter.h index 22a23500..36cc59b9 100644 --- a/LEGO1/legotexturepresenter.h +++ b/LEGO1/legotexturepresenter.h @@ -22,7 +22,9 @@ class LegoTexturePresenter : public MxMediaPresenter { return !strcmp(p_name, LegoTexturePresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } + virtual void DoneTickle() override; // vtable+0x2c virtual MxResult AddToManager() override; // vtable+0x34 + virtual MxResult PutData() override; // vtable+0x4c }; #endif // LEGOTEXTUREPRESENTER_H From d5854a46aed638b5d646022976327c8d480044c7 Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Wed, 27 Dec 2023 13:36:32 -0500 Subject: [PATCH 26/50] HospitalState ctor (#375) * HospitalState ctor * Add member offsets in HospitalState header * Remove unhelpful comment --------- Co-authored-by: Christian Semmler --- LEGO1/hospitalstate.cpp | 11 +++++++++-- LEGO1/hospitalstate.h | 10 ++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/LEGO1/hospitalstate.cpp b/LEGO1/hospitalstate.cpp index b1727b74..4f865128 100644 --- a/LEGO1/hospitalstate.cpp +++ b/LEGO1/hospitalstate.cpp @@ -1,7 +1,14 @@ #include "hospitalstate.h" -// STUB: LEGO1 0x10076370 +DECOMP_SIZE_ASSERT(HospitalState, 0x18) + +// FUNCTION: LEGO1 0x10076370 HospitalState::HospitalState() { - // TODO + this->m_unk0xc = 0; + this->m_unk0xe = 0; + this->m_unk0x10 = 0; + this->m_unk0x12 = 0; + this->m_unk0x14 = 0; + this->m_unk0x16 = 0; } diff --git a/LEGO1/hospitalstate.h b/LEGO1/hospitalstate.h index 795342b0..8b24a3d5 100644 --- a/LEGO1/hospitalstate.h +++ b/LEGO1/hospitalstate.h @@ -1,6 +1,7 @@ #ifndef HOSPITALSTATE_H #define HOSPITALSTATE_H +#include "decomp.h" #include "legostate.h" // VTABLE: LEGO1 0x100d97a0 @@ -21,6 +22,15 @@ class HospitalState : public LegoState { { return !strcmp(p_name, HospitalState::ClassName()) || LegoState::IsA(p_name); } + +private: + undefined m_unk0x8[4]; // 0x8 + undefined2 m_unk0xc; // 0xc + undefined2 m_unk0xe; // 0xe + undefined2 m_unk0x10; // 0x10 + undefined2 m_unk0x12; // 0x12 + undefined2 m_unk0x14; // 0x14 + undefined2 m_unk0x16; // 0x16 }; #endif // HOSPITALSTATE_H From 306d08c5816c5ca214bc1a6d5aa0478cbc5f88e3 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 27 Dec 2023 15:31:51 -0500 Subject: [PATCH 27/50] Reorder delcarations, add some annotations --- LEGO1/mxdiskstreamcontroller.h | 17 +++++++++-------- LEGO1/mxregion.h | 12 ++++++------ 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/LEGO1/mxdiskstreamcontroller.h b/LEGO1/mxdiskstreamcontroller.h index 703b3bf2..3fc5111f 100644 --- a/LEGO1/mxdiskstreamcontroller.h +++ b/LEGO1/mxdiskstreamcontroller.h @@ -17,14 +17,7 @@ class MxDiskStreamController : public MxStreamController { MxDiskStreamController(); virtual ~MxDiskStreamController() override; - virtual MxResult Tickle() override; // vtable+0x8 - virtual MxResult Open(const char* p_filename) override; // vtable+0x14 - virtual MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18 - virtual MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20 - virtual MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24 - virtual MxDSStreamingAction* VTable0x28() override; // vtable+0x28 - virtual MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30 - virtual MxResult VTable0x34(undefined4); // vtable+0x34 + virtual MxResult Tickle() override; // vtable+0x8 // FUNCTION: LEGO1 0x100c7360 inline virtual const char* ClassName() const override // vtable+0x0c @@ -39,6 +32,14 @@ class MxDiskStreamController : public MxStreamController { return !strcmp(p_name, MxDiskStreamController::ClassName()) || MxStreamController::IsA(p_name); } + virtual MxResult Open(const char* p_filename) override; // vtable+0x14 + virtual MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18 + virtual MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20 + virtual MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24 + virtual MxDSStreamingAction* VTable0x28() override; // vtable+0x28 + virtual MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30 + virtual MxResult VTable0x34(undefined4); // vtable+0x34 + inline MxBool GetUnk0xc4() const { return m_unk0xc4; } void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); diff --git a/LEGO1/mxregion.h b/LEGO1/mxregion.h index be15a672..c7d7dd90 100644 --- a/LEGO1/mxregion.h +++ b/LEGO1/mxregion.h @@ -13,16 +13,16 @@ class MxRegion : public MxCore { MxRegion(); virtual ~MxRegion() override; - virtual void Reset(); - virtual void VTable0x18(MxRect32& p_rect); - virtual MxBool VTable0x1c(MxRect32& p_rect); - virtual MxBool VTable0x20(); + virtual void Reset(); // vtable+0x14 + virtual void VTable0x18(MxRect32& p_rect); // vtable+0x18 + virtual MxBool VTable0x1c(MxRect32& p_rect); // vtable+0x1c + virtual MxBool VTable0x20(); // vtable+0x20 inline MxRect32& GetRect() { return this->m_rect; } private: - MxRegionList* m_list; - MxRect32 m_rect; + MxRegionList* m_list; // 0x08 + MxRect32 m_rect; // 0x0c }; #endif // MXREGION_H From dfad3238804b625a77a0e3cff0b1a0ec7c7e3833 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Wed, 27 Dec 2023 15:44:51 -0500 Subject: [PATCH 28/50] Finish LegoPalettePresenter (#377) * LegoPalettePresenter implementation * Update legopalettepresenter.cpp * Update legopalettepresenter.h --------- Co-authored-by: Christian Semmler --- LEGO1/legopalettepresenter.cpp | 50 ++++++++++++++++++++++++++++++++++ LEGO1/legopalettepresenter.h | 7 +++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/LEGO1/legopalettepresenter.cpp b/LEGO1/legopalettepresenter.cpp index 5ee9279f..f18a22c3 100644 --- a/LEGO1/legopalettepresenter.cpp +++ b/LEGO1/legopalettepresenter.cpp @@ -1,5 +1,10 @@ #include "legopalettepresenter.h" +#include "legoomni.h" +#include "legostream.h" +#include "legovideomanager.h" +#include "mxstreamchunk.h" + DECOMP_SIZE_ASSERT(LegoPalettePresenter, 0x68) // FUNCTION: LEGO1 0x10079e50 @@ -39,3 +44,48 @@ void LegoPalettePresenter::Destroy() { Destroy(FALSE); } + +// FUNCTION: LEGO1 0x1007a130 +MxResult LegoPalettePresenter::ParsePallete(MxStreamChunk* p_chunk) +{ + MxU8 buffer[40]; + RGBQUAD palleteData[256]; + MxResult result = FAILURE; + LegoMemoryStream stream((char*) p_chunk->GetData()); + if (stream.Read(buffer, 40) == SUCCESS) { + if (stream.Read(palleteData, sizeof(RGBQUAD) * 256) == SUCCESS) { + m_palette = new MxPalette(palleteData); + if (m_palette) { + result = SUCCESS; + } + } + } + + if (result != SUCCESS && m_palette) { + delete m_palette; + m_palette = NULL; + } + + return result; +} + +// FUNCTION: LEGO1 0x1007a230 +void LegoPalettePresenter::ReadyTickle() +{ + MxStreamChunk* chunk = m_subscriber->FUN_100b8360(); + if (chunk) { + if (chunk->GetTime() <= m_action->GetElapsedTime()) { + ParseExtra(); + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Starting; + chunk = m_subscriber->FUN_100b8250(); + MxResult result = ParsePallete(chunk); + m_subscriber->FUN_100b8390(chunk); + + if (result == SUCCESS) { + VideoManager()->RealizePalette(m_palette); + } + EndAction(); + } + } +} diff --git a/LEGO1/legopalettepresenter.h b/LEGO1/legopalettepresenter.h index e29b5391..c350159b 100644 --- a/LEGO1/legopalettepresenter.h +++ b/LEGO1/legopalettepresenter.h @@ -25,13 +25,16 @@ class LegoPalettePresenter : public MxVideoPresenter { return !strcmp(p_name, ClassName()) || MxVideoPresenter::IsA(p_name); } - virtual void Destroy() override; // vtable+0x38 + virtual void ReadyTickle() override; // vtable+0x18 + virtual void Destroy() override; // vtable+0x38 + + MxResult ParsePallete(MxStreamChunk* p_chunk); private: void Init(); void Destroy(MxBool p_fromDestructor); - MxPalette* m_palette; + MxPalette* m_palette; // 0x64 }; #endif // LEGOPALETTEPRESENTER_H From bcb7bec68b472c4aa03a1b34248964512a9af221 Mon Sep 17 00:00:00 2001 From: MS Date: Wed, 27 Dec 2023 15:59:42 -0500 Subject: [PATCH 29/50] Improve handling of variables for decomp parser (#376) * Parser refactor: - Handling LIRBARY and STRING markers - Extracting global variable name for future comparison - Marking function static variables - More fluent error messages * String constants annotated with STRING * fix variable name * Should compare LIBRARY markers --- ISLE/define.h | 4 +- LEGO1/act1state.h | 2 +- LEGO1/act2brick.h | 2 +- LEGO1/act2policestation.h | 2 +- LEGO1/act3.h | 2 +- LEGO1/act3actor.h | 2 +- LEGO1/act3shark.h | 2 +- LEGO1/act3state.h | 2 +- LEGO1/ambulance.h | 2 +- LEGO1/ambulancemissionstate.h | 2 +- LEGO1/animstate.h | 2 +- LEGO1/beachhouseentity.h | 2 +- LEGO1/bike.h | 2 +- LEGO1/buildingentity.h | 2 +- LEGO1/bumpbouy.h | 2 +- LEGO1/carrace.h | 2 +- LEGO1/carracestate.h | 2 +- LEGO1/doors.h | 2 +- LEGO1/dunebuggy.h | 2 +- LEGO1/elevatorbottom.h | 2 +- LEGO1/gasstation.h | 2 +- LEGO1/gasstationentity.h | 2 +- LEGO1/gasstationstate.h | 2 +- LEGO1/helicopter.h | 2 +- LEGO1/helicopterstate.h | 2 +- LEGO1/historybook.h | 2 +- LEGO1/hospital.h | 2 +- LEGO1/hospitalentity.h | 2 +- LEGO1/hospitalstate.h | 2 +- LEGO1/infocenter.h | 2 +- LEGO1/infocenterdoor.h | 2 +- LEGO1/infocenterentity.h | 2 +- LEGO1/infocenterstate.h | 2 +- LEGO1/isle.h | 2 +- LEGO1/isleactor.h | 2 +- LEGO1/islepathactor.h | 2 +- LEGO1/jetski.h | 2 +- LEGO1/jetskirace.h | 2 +- LEGO1/jetskiracestate.h | 2 +- LEGO1/jukebox.h | 2 +- LEGO1/jukeboxentity.h | 2 +- LEGO1/jukeboxstate.h | 2 +- LEGO1/lego3dwavepresenter.h | 2 +- LEGO1/legoact2state.h | 2 +- LEGO1/legoactioncontrolpresenter.h | 2 +- LEGO1/legoactor.h | 2 +- LEGO1/legoactorpresenter.h | 2 +- LEGO1/legoanimationmanager.h | 2 +- LEGO1/legoanimmmpresenter.h | 2 +- LEGO1/legoanimpresenter.h | 2 +- LEGO1/legobuildingmanager.h | 2 +- LEGO1/legocachesound.h | 2 +- LEGO1/legocameracontroller.h | 2 +- LEGO1/legocarbuild.h | 2 +- LEGO1/legocarbuildanimpresenter.h | 2 +- LEGO1/legocarraceactor.h | 2 +- LEGO1/legocontrolmanager.h | 2 +- LEGO1/legoentity.h | 2 +- LEGO1/legoentitypresenter.h | 2 +- LEGO1/legoextraactor.h | 2 +- LEGO1/legoflctexturepresenter.h | 2 +- LEGO1/legohideanimpresenter.h | 2 +- LEGO1/legojetski.h | 2 +- LEGO1/legojetskiraceactor.h | 2 +- LEGO1/legoloadcachesoundpresenter.h | 2 +- LEGO1/legolocomotionanimpresenter.h | 2 +- LEGO1/legoloopinganimpresenter.h | 2 +- LEGO1/legomodelpresenter.h | 2 +- LEGO1/legonavcontroller.h | 2 +- LEGO1/legoomni.h | 2 +- LEGO1/legopalettepresenter.h | 2 +- LEGO1/legopartpresenter.h | 2 +- LEGO1/legopathactor.h | 2 +- LEGO1/legopathcontroller.h | 2 +- LEGO1/legopathpresenter.h | 2 +- LEGO1/legophonemepresenter.h | 2 +- LEGO1/legoplantmanager.h | 2 +- LEGO1/legorace.h | 2 +- LEGO1/legoraceactor.h | 2 +- LEGO1/legoracecar.h | 2 +- LEGO1/legostate.h | 2 +- LEGO1/legotexturepresenter.h | 2 +- LEGO1/legoworld.h | 2 +- LEGO1/legoworldpresenter.h | 2 +- LEGO1/motorcycle.h | 2 +- LEGO1/mxaudiopresenter.h | 2 +- LEGO1/mxbackgroundaudiomanager.h | 2 +- LEGO1/mxcompositemediapresenter.h | 2 +- LEGO1/mxcompositepresenter.h | 2 +- LEGO1/mxcontrolpresenter.h | 2 +- LEGO1/mxcore.h | 2 +- LEGO1/mxdiskstreamcontroller.h | 2 +- LEGO1/mxdiskstreamprovider.h | 2 +- LEGO1/mxdsaction.h | 2 +- LEGO1/mxdsanim.h | 2 +- LEGO1/mxdsbuffer.h | 2 +- LEGO1/mxdschunk.h | 2 +- LEGO1/mxdsevent.h | 2 +- LEGO1/mxdsfile.h | 2 +- LEGO1/mxdsmediaaction.h | 2 +- LEGO1/mxdsmultiaction.h | 2 +- LEGO1/mxdsobjectaction.h | 2 +- LEGO1/mxdsparallelaction.h | 2 +- LEGO1/mxdsselectaction.h | 2 +- LEGO1/mxdsserialaction.h | 2 +- LEGO1/mxdssound.h | 2 +- LEGO1/mxdssource.h | 2 +- LEGO1/mxdsstill.h | 2 +- LEGO1/mxdssubscriber.h | 2 +- LEGO1/mxentity.h | 2 +- LEGO1/mxeventpresenter.h | 2 +- LEGO1/mxflcpresenter.h | 2 +- LEGO1/mxloopingflcpresenter.h | 2 +- LEGO1/mxloopingmidipresenter.h | 2 +- LEGO1/mxloopingsmkpresenter.h | 2 +- LEGO1/mxmediapresenter.h | 2 +- LEGO1/mxmidipresenter.h | 2 +- LEGO1/mxmusicpresenter.h | 2 +- LEGO1/mxnextactiondatastart.h | 2 +- LEGO1/mxobjectfactory.h | 2 +- LEGO1/mxpalette.cpp | 1 - LEGO1/mxpresenter.h | 2 +- LEGO1/mxramstreamcontroller.h | 2 +- LEGO1/mxramstreamprovider.h | 2 +- LEGO1/mxsmkpresenter.h | 2 +- LEGO1/mxsoundpresenter.h | 2 +- LEGO1/mxstillpresenter.h | 2 +- LEGO1/mxstreamchunk.h | 2 +- LEGO1/mxstreamcontroller.h | 2 +- LEGO1/mxstreamer.h | 2 +- LEGO1/mxvideopresenter.h | 2 +- LEGO1/mxwavepresenter.h | 2 +- LEGO1/pizza.h | 2 +- LEGO1/pizzamissionstate.h | 2 +- LEGO1/pizzeria.h | 2 +- LEGO1/pizzeriastate.h | 2 +- LEGO1/police.h | 2 +- LEGO1/policeentity.h | 2 +- LEGO1/policestate.h | 2 +- LEGO1/racecar.h | 2 +- LEGO1/racestate.h | 2 +- LEGO1/radio.h | 2 +- LEGO1/radiostate.h | 2 +- LEGO1/realtime/matrix.cpp | 2 +- LEGO1/registrationbook.h | 2 +- LEGO1/score.h | 2 +- LEGO1/scorestate.h | 2 +- LEGO1/skateboard.h | 2 +- LEGO1/tgl/d3drm/renderer.cpp | 4 +- LEGO1/towtrack.h | 2 +- LEGO1/towtrackmissionstate.h | 2 +- tools/isledecomp/isledecomp/parser/error.py | 17 +- tools/isledecomp/isledecomp/parser/marker.py | 103 +++++++++ tools/isledecomp/isledecomp/parser/node.py | 50 +++-- tools/isledecomp/isledecomp/parser/parser.py | 195 +++++++++++------- tools/isledecomp/isledecomp/parser/util.py | 49 ++--- tools/isledecomp/tests/test_parser.py | 73 ++++++- .../tests/test_parser_statechange.py | 84 ++++---- tools/isledecomp/tests/test_parser_util.py | 33 ++- tools/reccmp/reccmp.py | 4 +- 160 files changed, 586 insertions(+), 327 deletions(-) create mode 100644 tools/isledecomp/isledecomp/parser/marker.py diff --git a/ISLE/define.h b/ISLE/define.h index aac9f28d..3f92244b 100644 --- a/ISLE/define.h +++ b/ISLE/define.h @@ -8,9 +8,9 @@ class IsleApp; extern IsleApp* g_isle; extern int g_closed; -// GLOBAL: ISLE 0x4101c4 +// STRING: ISLE 0x4101c4 #define WNDCLASS_NAME "Lego Island MainNoM App" -// GLOBAL: ISLE 0x4101dc +// STRING: ISLE 0x4101dc #define WINDOW_TITLE "LEGO\xAE" extern unsigned char g_mousedown; extern unsigned char g_mousemoved; diff --git a/LEGO1/act1state.h b/LEGO1/act1state.h index e2e8d3e1..d0daec7d 100644 --- a/LEGO1/act1state.h +++ b/LEGO1/act1state.h @@ -12,7 +12,7 @@ class Act1State : public LegoState { // FUNCTION: LEGO1 0x100338a0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0154 + // STRING: LEGO1 0x100f0154 return "Act1State"; }; diff --git a/LEGO1/act2brick.h b/LEGO1/act2brick.h index de4f29b1..10665c40 100644 --- a/LEGO1/act2brick.h +++ b/LEGO1/act2brick.h @@ -16,7 +16,7 @@ class Act2Brick : public LegoPathActor { // FUNCTION: LEGO1 0x1007a360 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0438 + // STRING: LEGO1 0x100f0438 return "Act2Brick"; } diff --git a/LEGO1/act2policestation.h b/LEGO1/act2policestation.h index 2ca1a4e8..887ab542 100644 --- a/LEGO1/act2policestation.h +++ b/LEGO1/act2policestation.h @@ -12,7 +12,7 @@ class Act2PoliceStation : public LegoEntity { // FUNCTION: LEGO1 0x1000e200 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03fc + // STRING: LEGO1 0x100f03fc return "Act2PoliceStation"; } diff --git a/LEGO1/act3.h b/LEGO1/act3.h index cc4a2c3f..76c9722b 100644 --- a/LEGO1/act3.h +++ b/LEGO1/act3.h @@ -14,7 +14,7 @@ class Act3 : public LegoWorld { // FUNCTION: LEGO1 0x10072510 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f013c + // STRING: LEGO1 0x100f013c return "Act3"; } diff --git a/LEGO1/act3actor.h b/LEGO1/act3actor.h index bfdf879a..cd1e1fcd 100644 --- a/LEGO1/act3actor.h +++ b/LEGO1/act3actor.h @@ -8,7 +8,7 @@ class Act3Actor : public MxCore { // FUNCTION: LEGO1 0x100431b0 inline virtual const char* ClassName() override { - // GLOBAL: LEGO1 0x100f03ac + // STRING: LEGO1 0x100f03ac return "Act3Actor"; } }; diff --git a/LEGO1/act3shark.h b/LEGO1/act3shark.h index 63a4e7a6..611cbc38 100644 --- a/LEGO1/act3shark.h +++ b/LEGO1/act3shark.h @@ -9,7 +9,7 @@ class Act3Shark : public LegoAnimActor { // FUNCTION: LEGO1 0x100430c0 inline virtual const char* ClassName() const override { - // GLOBAL: LEGO1 0x100f03a0 + // STRING: LEGO1 0x100f03a0 return "Act3Shark"; } }; diff --git a/LEGO1/act3state.h b/LEGO1/act3state.h index 5da94fac..dca6c3ea 100644 --- a/LEGO1/act3state.h +++ b/LEGO1/act3state.h @@ -12,7 +12,7 @@ class Act3State : public LegoState { // FUNCTION: LEGO1 0x1000e300 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03f0 + // STRING: LEGO1 0x100f03f0 return "Act3State"; } diff --git a/LEGO1/ambulance.h b/LEGO1/ambulance.h index eb46a1ed..3bc80212 100644 --- a/LEGO1/ambulance.h +++ b/LEGO1/ambulance.h @@ -12,7 +12,7 @@ class Ambulance : public IslePathActor { // FUNCTION: LEGO1 0x10035fa0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03c4 + // STRING: LEGO1 0x100f03c4 return "Ambulance"; } diff --git a/LEGO1/ambulancemissionstate.h b/LEGO1/ambulancemissionstate.h index 05d09859..a09bf117 100644 --- a/LEGO1/ambulancemissionstate.h +++ b/LEGO1/ambulancemissionstate.h @@ -12,7 +12,7 @@ class AmbulanceMissionState : public LegoState { // FUNCTION: LEGO1 0x10037600 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00e8 + // STRING: LEGO1 0x100f00e8 return "AmbulanceMissionState"; } diff --git a/LEGO1/animstate.h b/LEGO1/animstate.h index 5e8fa4e5..c1098b6a 100644 --- a/LEGO1/animstate.h +++ b/LEGO1/animstate.h @@ -13,7 +13,7 @@ class AnimState : public LegoState { // FUNCTION: LEGO1 0x10065070 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0460 + // STRING: LEGO1 0x100f0460 return "AnimState"; } diff --git a/LEGO1/beachhouseentity.h b/LEGO1/beachhouseentity.h index cf6a8909..58aa3c68 100644 --- a/LEGO1/beachhouseentity.h +++ b/LEGO1/beachhouseentity.h @@ -12,7 +12,7 @@ class BeachHouseEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000ee80 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0314 + // STRING: LEGO1 0x100f0314 return "BeachHouseEntity"; } diff --git a/LEGO1/bike.h b/LEGO1/bike.h index f3d5c90d..899cfd21 100644 --- a/LEGO1/bike.h +++ b/LEGO1/bike.h @@ -13,7 +13,7 @@ class Bike : public IslePathActor { // FUNCTION: LEGO1 0x100766f0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03d0 + // STRING: LEGO1 0x100f03d0 return "Bike"; } diff --git a/LEGO1/buildingentity.h b/LEGO1/buildingentity.h index f0ba4c3c..7f2abe07 100644 --- a/LEGO1/buildingentity.h +++ b/LEGO1/buildingentity.h @@ -13,7 +13,7 @@ class BuildingEntity : public LegoEntity { // FUNCTION: LEGO1 0x10014f20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07e8 + // STRING: LEGO1 0x100f07e8 return "BuildingEntity"; } diff --git a/LEGO1/bumpbouy.h b/LEGO1/bumpbouy.h index 8399c7ef..a56526e4 100644 --- a/LEGO1/bumpbouy.h +++ b/LEGO1/bumpbouy.h @@ -10,7 +10,7 @@ class BumpBouy : public LegoAnimActor { // FUNCTION: LEGO1 0x100274e0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0394 + // STRING: LEGO1 0x100f0394 return "BumpBouy"; } diff --git a/LEGO1/carrace.h b/LEGO1/carrace.h index 3b9a768e..767fa567 100644 --- a/LEGO1/carrace.h +++ b/LEGO1/carrace.h @@ -13,7 +13,7 @@ class CarRace : public LegoRace { // FUNCTION: LEGO1 0x10016b20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0528 + // STRING: LEGO1 0x100f0528 return "CarRace"; } diff --git a/LEGO1/carracestate.h b/LEGO1/carracestate.h index c922354f..561f277b 100644 --- a/LEGO1/carracestate.h +++ b/LEGO1/carracestate.h @@ -10,7 +10,7 @@ class CarRaceState : public RaceState { // FUNCTION: LEGO1 0x1000dd30 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f009c + // STRING: LEGO1 0x100f009c return "CarRaceState"; } diff --git a/LEGO1/doors.h b/LEGO1/doors.h index a2c142a4..feea0460 100644 --- a/LEGO1/doors.h +++ b/LEGO1/doors.h @@ -10,7 +10,7 @@ class Doors : public LegoPathActor { // FUNCTION: LEGO1 0x1000e430 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03e8 + // STRING: LEGO1 0x100f03e8 return "Doors"; } diff --git a/LEGO1/dunebuggy.h b/LEGO1/dunebuggy.h index 1accaa05..e45fe8fe 100644 --- a/LEGO1/dunebuggy.h +++ b/LEGO1/dunebuggy.h @@ -13,7 +13,7 @@ class DuneBuggy : public IslePathActor { // FUNCTION: LEGO1 0x10067c30 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0410 + // STRING: LEGO1 0x100f0410 return "DuneBuggy"; } diff --git a/LEGO1/elevatorbottom.h b/LEGO1/elevatorbottom.h index 2a0f2570..64b3f221 100644 --- a/LEGO1/elevatorbottom.h +++ b/LEGO1/elevatorbottom.h @@ -14,7 +14,7 @@ class ElevatorBottom : public LegoWorld { // FUNCTION: LEGO1 0x10017f20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04ac + // STRING: LEGO1 0x100f04ac return "ElevatorBottom"; } diff --git a/LEGO1/gasstation.h b/LEGO1/gasstation.h index d6761980..0617e161 100644 --- a/LEGO1/gasstation.h +++ b/LEGO1/gasstation.h @@ -17,7 +17,7 @@ class GasStation : public LegoWorld { // FUNCTION: LEGO1 0x10004780 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0168 + // STRING: LEGO1 0x100f0168 return "GasStation"; } diff --git a/LEGO1/gasstationentity.h b/LEGO1/gasstationentity.h index 17aa22cf..b4a27942 100644 --- a/LEGO1/gasstationentity.h +++ b/LEGO1/gasstationentity.h @@ -10,7 +10,7 @@ class GasStationEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000eb20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0348 + // STRING: LEGO1 0x100f0348 return "GasStationEntity"; } diff --git a/LEGO1/gasstationstate.h b/LEGO1/gasstationstate.h index 2fb7e512..e2768a98 100644 --- a/LEGO1/gasstationstate.h +++ b/LEGO1/gasstationstate.h @@ -12,7 +12,7 @@ class GasStationState : public LegoState { // FUNCTION: LEGO1 0x100061d0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0174 + // STRING: LEGO1 0x100f0174 return "GasStationState"; } diff --git a/LEGO1/helicopter.h b/LEGO1/helicopter.h index cc4f3b35..7c5be4ea 100644 --- a/LEGO1/helicopter.h +++ b/LEGO1/helicopter.h @@ -27,7 +27,7 @@ class Helicopter : public IslePathActor { // FUNCTION: LEGO1 0x10003070 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0130 + // STRING: LEGO1 0x100f0130 return "Helicopter"; } diff --git a/LEGO1/helicopterstate.h b/LEGO1/helicopterstate.h index 1c43b04f..2cb3b747 100644 --- a/LEGO1/helicopterstate.h +++ b/LEGO1/helicopterstate.h @@ -11,7 +11,7 @@ class HelicopterState : public LegoState { // FUNCTION: LEGO1 0x1000e0d0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0144 + // STRING: LEGO1 0x100f0144 return "HelicopterState"; } diff --git a/LEGO1/historybook.h b/LEGO1/historybook.h index 18154c79..80cc78b5 100644 --- a/LEGO1/historybook.h +++ b/LEGO1/historybook.h @@ -15,7 +15,7 @@ class HistoryBook : public LegoWorld { // FUNCTION: LEGO1 0x10082390 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04bc + // STRING: LEGO1 0x100f04bc return "HistoryBook"; } diff --git a/LEGO1/hospital.h b/LEGO1/hospital.h index 014c301d..627dc4cc 100644 --- a/LEGO1/hospital.h +++ b/LEGO1/hospital.h @@ -15,7 +15,7 @@ class Hospital : public LegoWorld { // FUNCTION: LEGO1 0x100746b0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0490 + // STRING: LEGO1 0x100f0490 return "Hospital"; } diff --git a/LEGO1/hospitalentity.h b/LEGO1/hospitalentity.h index 9dc597f1..f4f14b70 100644 --- a/LEGO1/hospitalentity.h +++ b/LEGO1/hospitalentity.h @@ -10,7 +10,7 @@ class HospitalEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000ec40 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0338 + // STRING: LEGO1 0x100f0338 return "HospitalEntity"; } diff --git a/LEGO1/hospitalstate.h b/LEGO1/hospitalstate.h index 8b24a3d5..25c23d96 100644 --- a/LEGO1/hospitalstate.h +++ b/LEGO1/hospitalstate.h @@ -13,7 +13,7 @@ class HospitalState : public LegoState { // FUNCTION: LEGO1 0x10076400 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0480 + // STRING: LEGO1 0x100f0480 return "HospitalState"; } diff --git a/LEGO1/infocenter.h b/LEGO1/infocenter.h index 3b4e7856..89fcc54f 100644 --- a/LEGO1/infocenter.h +++ b/LEGO1/infocenter.h @@ -16,7 +16,7 @@ class Infocenter : public LegoWorld { // FUNCTION: LEGO1 0x1006eb40 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04ec + // STRING: LEGO1 0x100f04ec return "Infocenter"; } diff --git a/LEGO1/infocenterdoor.h b/LEGO1/infocenterdoor.h index 1586dbc8..5bc5e407 100644 --- a/LEGO1/infocenterdoor.h +++ b/LEGO1/infocenterdoor.h @@ -15,7 +15,7 @@ class InfocenterDoor : public LegoWorld { // FUNCTION: LEGO1 0x100377b0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f049c + // STRING: LEGO1 0x100f049c return "InfocenterDoor"; } diff --git a/LEGO1/infocenterentity.h b/LEGO1/infocenterentity.h index 44121ae2..e011aeb8 100644 --- a/LEGO1/infocenterentity.h +++ b/LEGO1/infocenterentity.h @@ -10,7 +10,7 @@ class InfoCenterEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000ea00 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f035c + // STRING: LEGO1 0x100f035c return "InfoCenterEntity"; } diff --git a/LEGO1/infocenterstate.h b/LEGO1/infocenterstate.h index 322e7bec..b1bce306 100644 --- a/LEGO1/infocenterstate.h +++ b/LEGO1/infocenterstate.h @@ -14,7 +14,7 @@ class InfocenterState : public LegoState { // FUNCTION: LEGO1 0x10071840 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04dc + // STRING: LEGO1 0x100f04dc return "InfocenterState"; } diff --git a/LEGO1/isle.h b/LEGO1/isle.h index 9f44eadd..c3579aec 100644 --- a/LEGO1/isle.h +++ b/LEGO1/isle.h @@ -30,7 +30,7 @@ class Isle : public LegoWorld { // FUNCTION: LEGO1 0x10030910 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0458 + // STRING: LEGO1 0x100f0458 return "Isle"; } diff --git a/LEGO1/isleactor.h b/LEGO1/isleactor.h index aa205483..8fd7d039 100644 --- a/LEGO1/isleactor.h +++ b/LEGO1/isleactor.h @@ -9,7 +9,7 @@ class IsleActor : public LegoActor { // FUNCTION: LEGO1 0x1000e660 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07dc + // STRING: LEGO1 0x100f07dc return "IsleActor"; } diff --git a/LEGO1/islepathactor.h b/LEGO1/islepathactor.h index 44f50475..d7a8ff60 100644 --- a/LEGO1/islepathactor.h +++ b/LEGO1/islepathactor.h @@ -18,7 +18,7 @@ class IslePathActor : public LegoPathActor { // FUNCTION: LEGO1 0x10002ea0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0104 + // STRING: LEGO1 0x100f0104 return "IslePathActor"; } diff --git a/LEGO1/jetski.h b/LEGO1/jetski.h index 8c669ca6..1a64a4b6 100644 --- a/LEGO1/jetski.h +++ b/LEGO1/jetski.h @@ -13,7 +13,7 @@ class Jetski : public IslePathActor { // FUNCTION: LEGO1 0x1007e430 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03d8 + // STRING: LEGO1 0x100f03d8 return "Jetski"; } diff --git a/LEGO1/jetskirace.h b/LEGO1/jetskirace.h index 9488ed04..9b16d9a7 100644 --- a/LEGO1/jetskirace.h +++ b/LEGO1/jetskirace.h @@ -10,7 +10,7 @@ class JetskiRace : public LegoRace { // FUNCTION: LEGO1 0x1000daf0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0530 + // STRING: LEGO1 0x100f0530 return "JetskiRace"; } diff --git a/LEGO1/jetskiracestate.h b/LEGO1/jetskiracestate.h index 9724e4a1..5610ac32 100644 --- a/LEGO1/jetskiracestate.h +++ b/LEGO1/jetskiracestate.h @@ -10,7 +10,7 @@ class JetskiRaceState : public RaceState { // FUNCTION: LEGO1 0x1000dc40 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00ac + // STRING: LEGO1 0x100f00ac return "JetskiRaceState"; } diff --git a/LEGO1/jukebox.h b/LEGO1/jukebox.h index 63b04520..59aee194 100644 --- a/LEGO1/jukebox.h +++ b/LEGO1/jukebox.h @@ -13,7 +13,7 @@ class JukeBox : public LegoWorld { // FUNCTION: LEGO1 0x1005d6f0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02cc + // STRING: LEGO1 0x100f02cc return "JukeBox"; } diff --git a/LEGO1/jukeboxentity.h b/LEGO1/jukeboxentity.h index 3e175568..c451787d 100644 --- a/LEGO1/jukeboxentity.h +++ b/LEGO1/jukeboxentity.h @@ -13,7 +13,7 @@ class JukeBoxEntity : public LegoEntity { // FUNCTION: LEGO1 0x10085cc0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02f0 + // STRING: LEGO1 0x100f02f0 return "JukeBoxEntity"; } diff --git a/LEGO1/jukeboxstate.h b/LEGO1/jukeboxstate.h index 8a481437..7a517bb0 100644 --- a/LEGO1/jukeboxstate.h +++ b/LEGO1/jukeboxstate.h @@ -10,7 +10,7 @@ class JukeBoxState : public LegoState { // FUNCTION: LEGO1 0x1000f310 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02bc + // STRING: LEGO1 0x100f02bc return "JukeBoxState"; } diff --git a/LEGO1/lego3dwavepresenter.h b/LEGO1/lego3dwavepresenter.h index ca72f212..ed1942da 100644 --- a/LEGO1/lego3dwavepresenter.h +++ b/LEGO1/lego3dwavepresenter.h @@ -10,7 +10,7 @@ class Lego3DWavePresenter : public MxWavePresenter { // FUNCTION: LEGO1 0x1000d890 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f058c + // STRING: LEGO1 0x100f058c return "Lego3DWavePresenter"; } diff --git a/LEGO1/legoact2state.h b/LEGO1/legoact2state.h index a26cdd7d..38584769 100644 --- a/LEGO1/legoact2state.h +++ b/LEGO1/legoact2state.h @@ -10,7 +10,7 @@ class LegoAct2State : public LegoState { // FUNCTION: LEGO1 0x1000df80 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0428 + // STRING: LEGO1 0x100f0428 return "LegoAct2State"; } diff --git a/LEGO1/legoactioncontrolpresenter.h b/LEGO1/legoactioncontrolpresenter.h index 98815348..746300a6 100644 --- a/LEGO1/legoactioncontrolpresenter.h +++ b/LEGO1/legoactioncontrolpresenter.h @@ -15,7 +15,7 @@ class LegoActionControlPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000d0e0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f05bc + // STRING: LEGO1 0x100f05bc return "LegoActionControlPresenter"; } diff --git a/LEGO1/legoactor.h b/LEGO1/legoactor.h index c8380177..95c991df 100644 --- a/LEGO1/legoactor.h +++ b/LEGO1/legoactor.h @@ -13,7 +13,7 @@ class LegoActor : public LegoEntity { // FUNCTION: LEGO1 0x1002d210 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0124 + // STRING: LEGO1 0x100f0124 return "LegoActor"; } diff --git a/LEGO1/legoactorpresenter.h b/LEGO1/legoactorpresenter.h index 359960dc..a9709686 100644 --- a/LEGO1/legoactorpresenter.h +++ b/LEGO1/legoactorpresenter.h @@ -10,7 +10,7 @@ class LegoActorPresenter : public LegoEntityPresenter { // FUNCTION: LEGO1 0x1000cb10 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f06a4 + // STRING: LEGO1 0x100f06a4 return "LegoActorPresenter"; } diff --git a/LEGO1/legoanimationmanager.h b/LEGO1/legoanimationmanager.h index 0a647e8f..f943b062 100644 --- a/LEGO1/legoanimationmanager.h +++ b/LEGO1/legoanimationmanager.h @@ -16,7 +16,7 @@ class LegoAnimationManager : public MxCore { // FUNCTION: LEGO1 0x1005ec80 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f7508 + // STRING: LEGO1 0x100f7508 return "LegoAnimationManager"; } diff --git a/LEGO1/legoanimmmpresenter.h b/LEGO1/legoanimmmpresenter.h index 9fc9d19f..2e1ab918 100644 --- a/LEGO1/legoanimmmpresenter.h +++ b/LEGO1/legoanimmmpresenter.h @@ -12,7 +12,7 @@ class LegoAnimMMPresenter : public MxCompositePresenter { // FUNCTION: LEGO1 0x1004a950 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f046c + // STRING: LEGO1 0x100f046c return "LegoAnimMMPresenter"; } diff --git a/LEGO1/legoanimpresenter.h b/LEGO1/legoanimpresenter.h index 5961f74a..de8e91d9 100644 --- a/LEGO1/legoanimpresenter.h +++ b/LEGO1/legoanimpresenter.h @@ -11,7 +11,7 @@ class LegoAnimPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x10068530 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f071c + // STRING: LEGO1 0x100f071c return "LegoAnimPresenter"; } diff --git a/LEGO1/legobuildingmanager.h b/LEGO1/legobuildingmanager.h index 38c9cd57..bb9c96bb 100644 --- a/LEGO1/legobuildingmanager.h +++ b/LEGO1/legobuildingmanager.h @@ -13,7 +13,7 @@ class LegoBuildingManager : public MxCore { // FUNCTION: LEGO1 0x1002f930 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f37d0 + // STRING: LEGO1 0x100f37d0 return "LegoBuildingManager"; } diff --git a/LEGO1/legocachesound.h b/LEGO1/legocachesound.h index e045a719..6398c04e 100644 --- a/LEGO1/legocachesound.h +++ b/LEGO1/legocachesound.h @@ -13,7 +13,7 @@ class LegoCacheSound : public MxCore { // FUNCTION: LEGO1 0x10006580 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f01c4 + // STRING: LEGO1 0x100f01c4 return "LegoCacheSound"; } diff --git a/LEGO1/legocameracontroller.h b/LEGO1/legocameracontroller.h index 7fa9552d..09785df1 100644 --- a/LEGO1/legocameracontroller.h +++ b/LEGO1/legocameracontroller.h @@ -15,7 +15,7 @@ class LegoCameraController : public MxCore { // FUNCTION: LEGO1 0x10011ec0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0850 + // STRING: LEGO1 0x100f0850 return "LegoCameraController"; } diff --git a/LEGO1/legocarbuild.h b/LEGO1/legocarbuild.h index b4a93e7c..74d850d4 100644 --- a/LEGO1/legocarbuild.h +++ b/LEGO1/legocarbuild.h @@ -16,7 +16,7 @@ class LegoCarBuild : public LegoWorld { // FUNCTION: LEGO1 0x10022940 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0504 + // STRING: LEGO1 0x100f0504 return "LegoCarBuild"; } diff --git a/LEGO1/legocarbuildanimpresenter.h b/LEGO1/legocarbuildanimpresenter.h index 8be926f7..0440a0f3 100644 --- a/LEGO1/legocarbuildanimpresenter.h +++ b/LEGO1/legocarbuildanimpresenter.h @@ -13,7 +13,7 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { // FUNCTION: LEGO1 0x10078510 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f05ec + // STRING: LEGO1 0x100f05ec return "LegoCarBuildAnimPresenter"; } diff --git a/LEGO1/legocarraceactor.h b/LEGO1/legocarraceactor.h index d03b20eb..f00d900e 100644 --- a/LEGO1/legocarraceactor.h +++ b/LEGO1/legocarraceactor.h @@ -9,7 +9,7 @@ class LegoCarRaceActor : public LegoRaceActor { // FUNCTION: LEGO1 0x10081650 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0568 + // STRING: LEGO1 0x100f0568 return "LegoCarRaceActor"; } diff --git a/LEGO1/legocontrolmanager.h b/LEGO1/legocontrolmanager.h index 591effb6..7bc8dc0f 100644 --- a/LEGO1/legocontrolmanager.h +++ b/LEGO1/legocontrolmanager.h @@ -14,7 +14,7 @@ class LegoControlManager : public MxCore { // FUNCTION: LEGO1 0x10028cb0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f31b8 + // STRING: LEGO1 0x100f31b8 return "LegoControlManager"; } diff --git a/LEGO1/legoentity.h b/LEGO1/legoentity.h index 4d4c19b6..5a2eb715 100644 --- a/LEGO1/legoentity.h +++ b/LEGO1/legoentity.h @@ -22,7 +22,7 @@ class LegoEntity : public MxEntity { // FUNCTION: LEGO1 0x1000c2f0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0064 + // STRING: LEGO1 0x100f0064 return "LegoEntity"; } diff --git a/LEGO1/legoentitypresenter.h b/LEGO1/legoentitypresenter.h index 994e5a79..72af0498 100644 --- a/LEGO1/legoentitypresenter.h +++ b/LEGO1/legoentitypresenter.h @@ -15,7 +15,7 @@ class LegoEntityPresenter : public MxCompositePresenter { // FUNCTION: LEGO1 0x100534b0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f06b8 + // STRING: LEGO1 0x100f06b8 return "LegoEntityPresenter"; } diff --git a/LEGO1/legoextraactor.h b/LEGO1/legoextraactor.h index 6b8a9198..c4c76cee 100644 --- a/LEGO1/legoextraactor.h +++ b/LEGO1/legoextraactor.h @@ -9,7 +9,7 @@ class LegoExtraActor : public LegoAnimActor { // FUNCTION: LEGO1 0x1002b7a0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f3204 + // STRING: LEGO1 0x100f3204 return "LegoExtraActor"; } diff --git a/LEGO1/legoflctexturepresenter.h b/LEGO1/legoflctexturepresenter.h index c55249cf..36d1fefc 100644 --- a/LEGO1/legoflctexturepresenter.h +++ b/LEGO1/legoflctexturepresenter.h @@ -13,7 +13,7 @@ class LegoFlcTexturePresenter : public MxFlcPresenter { // FUNCTION: LEGO1 0x1005def0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0634 + // STRING: LEGO1 0x100f0634 return "LegoFlcTexturePresenter"; } diff --git a/LEGO1/legohideanimpresenter.h b/LEGO1/legohideanimpresenter.h index aca44424..f6e86c2e 100644 --- a/LEGO1/legohideanimpresenter.h +++ b/LEGO1/legohideanimpresenter.h @@ -12,7 +12,7 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { // FUNCTION: LEGO1 0x1006d880 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f06cc + // STRING: LEGO1 0x100f06cc return "LegoHideAnimPresenter"; } diff --git a/LEGO1/legojetski.h b/LEGO1/legojetski.h index b7909a46..09a9f8d1 100644 --- a/LEGO1/legojetski.h +++ b/LEGO1/legojetski.h @@ -9,7 +9,7 @@ class LegoJetski : public LegoJetskiRaceActor { // FUNCTION: LEGO1 0x10013e80 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f053c + // STRING: LEGO1 0x100f053c return "LegoJetski"; } diff --git a/LEGO1/legojetskiraceactor.h b/LEGO1/legojetskiraceactor.h index d2ab88d8..28d151e8 100644 --- a/LEGO1/legojetskiraceactor.h +++ b/LEGO1/legojetskiraceactor.h @@ -9,7 +9,7 @@ class LegoJetskiRaceActor : public LegoCarRaceActor { // FUNCTION: LEGO1 0x10081d80 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0554 + // STRING: LEGO1 0x100f0554 return "LegoJetskiRaceActor"; } diff --git a/LEGO1/legoloadcachesoundpresenter.h b/LEGO1/legoloadcachesoundpresenter.h index c9255b01..1c26cdec 100644 --- a/LEGO1/legoloadcachesoundpresenter.h +++ b/LEGO1/legoloadcachesoundpresenter.h @@ -14,7 +14,7 @@ class LegoLoadCacheSoundPresenter : public MxWavePresenter { // FUNCTION: LEGO1 0x10018450 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f05a0 + // STRING: LEGO1 0x100f05a0 return "LegoLoadCacheSoundPresenter"; } diff --git a/LEGO1/legolocomotionanimpresenter.h b/LEGO1/legolocomotionanimpresenter.h index e7d7af25..36facd1d 100644 --- a/LEGO1/legolocomotionanimpresenter.h +++ b/LEGO1/legolocomotionanimpresenter.h @@ -11,7 +11,7 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { // FUNCTION: LEGO1 0x1006ce50 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f06e4 + // STRING: LEGO1 0x100f06e4 return "LegoLocomotionAnimPresenter"; } diff --git a/LEGO1/legoloopinganimpresenter.h b/LEGO1/legoloopinganimpresenter.h index 7f033a98..a17c671c 100644 --- a/LEGO1/legoloopinganimpresenter.h +++ b/LEGO1/legoloopinganimpresenter.h @@ -10,7 +10,7 @@ class LegoLoopingAnimPresenter : public LegoAnimPresenter { // FUNCTION: LEGO1 0x1000c9a0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0700 + // STRING: LEGO1 0x100f0700 return "LegoLoopingAnimPresenter"; } diff --git a/LEGO1/legomodelpresenter.h b/LEGO1/legomodelpresenter.h index df9cbba1..b55372dd 100644 --- a/LEGO1/legomodelpresenter.h +++ b/LEGO1/legomodelpresenter.h @@ -12,7 +12,7 @@ class LegoModelPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x1000ccb0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f067c + // STRING: LEGO1 0x100f067c return "LegoModelPresenter"; } diff --git a/LEGO1/legonavcontroller.h b/LEGO1/legonavcontroller.h index ffaf99cb..c6505341 100644 --- a/LEGO1/legonavcontroller.h +++ b/LEGO1/legonavcontroller.h @@ -42,7 +42,7 @@ class LegoNavController : public MxCore { // FUNCTION: LEGO1 0x10054b80 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f66d8 + // STRING: LEGO1 0x100f66d8 return "LegoNavController"; } diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index 81c3d6f1..f0ac8369 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -76,7 +76,7 @@ class LegoOmni : public MxOmni { // FUNCTION: LEGO1 0x10058aa0 inline virtual const char* ClassName() const override // vtable+0c { - // GLOBAL: LEGO1 0x100f671c + // STRING: LEGO1 0x100f671c return "LegoOmni"; } diff --git a/LEGO1/legopalettepresenter.h b/LEGO1/legopalettepresenter.h index c350159b..f725149d 100644 --- a/LEGO1/legopalettepresenter.h +++ b/LEGO1/legopalettepresenter.h @@ -15,7 +15,7 @@ class LegoPalettePresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x10079f30 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f061c + // STRING: LEGO1 0x100f061c return "LegoPalettePresenter"; } diff --git a/LEGO1/legopartpresenter.h b/LEGO1/legopartpresenter.h index 936d4876..6695a70b 100644 --- a/LEGO1/legopartpresenter.h +++ b/LEGO1/legopartpresenter.h @@ -10,7 +10,7 @@ class LegoPartPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000cf70 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f05d8 + // STRING: LEGO1 0x100f05d8 return "LegoPartPresenter"; } diff --git a/LEGO1/legopathactor.h b/LEGO1/legopathactor.h index f331e8ce..a3f5756c 100644 --- a/LEGO1/legopathactor.h +++ b/LEGO1/legopathactor.h @@ -15,7 +15,7 @@ class LegoPathActor : public LegoActor { // FUNCTION: LEGO1 0x1000c430 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0114 + // STRING: LEGO1 0x100f0114 return "LegoPathActor"; } diff --git a/LEGO1/legopathcontroller.h b/LEGO1/legopathcontroller.h index 7bb6d30d..f7278ca8 100644 --- a/LEGO1/legopathcontroller.h +++ b/LEGO1/legopathcontroller.h @@ -15,7 +15,7 @@ class LegoPathController : public MxCore { // FUNCTION: LEGO1 0x10045110 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f11b8 + // STRING: LEGO1 0x100f11b8 return "LegoPathController"; } diff --git a/LEGO1/legopathpresenter.h b/LEGO1/legopathpresenter.h index 8fe2d5ee..de7b14d1 100644 --- a/LEGO1/legopathpresenter.h +++ b/LEGO1/legopathpresenter.h @@ -12,7 +12,7 @@ class LegoPathPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x100449a0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0690 + // STRING: LEGO1 0x100f0690 return "LegoPathPresenter"; } diff --git a/LEGO1/legophonemepresenter.h b/LEGO1/legophonemepresenter.h index 7b620723..330b1c7a 100644 --- a/LEGO1/legophonemepresenter.h +++ b/LEGO1/legophonemepresenter.h @@ -16,7 +16,7 @@ class LegoPhonemePresenter : public MxFlcPresenter { // FUNCTION: LEGO1 0x1004e310 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f064c + // STRING: LEGO1 0x100f064c return "LegoPhonemePresenter"; } diff --git a/LEGO1/legoplantmanager.h b/LEGO1/legoplantmanager.h index 87a6ec79..7fd20746 100644 --- a/LEGO1/legoplantmanager.h +++ b/LEGO1/legoplantmanager.h @@ -15,7 +15,7 @@ class LegoPlantManager : public MxCore { // FUNCTION: LEGO1 0x10026290 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f318c + // STRING: LEGO1 0x100f318c return "LegoPlantManager"; } diff --git a/LEGO1/legorace.h b/LEGO1/legorace.h index 9ddbdfb3..530c289c 100644 --- a/LEGO1/legorace.h +++ b/LEGO1/legorace.h @@ -18,7 +18,7 @@ class LegoRace : public LegoWorld { // FUNCTION: LEGO1 0x10015ba0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f07c4 + // STRING: LEGO1 0x100f07c4 return "LegoRace"; } diff --git a/LEGO1/legoraceactor.h b/LEGO1/legoraceactor.h index 9a4e34ec..eb459e81 100644 --- a/LEGO1/legoraceactor.h +++ b/LEGO1/legoraceactor.h @@ -9,7 +9,7 @@ class LegoRaceActor : public LegoAnimActor { // FUNCTION: LEGO1 0x10014af0 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0bf4 + // STRING: LEGO1 0x100f0bf4 return "LegoRaceActor"; } diff --git a/LEGO1/legoracecar.h b/LEGO1/legoracecar.h index 38099af2..d3800b5a 100644 --- a/LEGO1/legoracecar.h +++ b/LEGO1/legoracecar.h @@ -11,7 +11,7 @@ class LegoRaceCar : public LegoCarRaceActor { // FUNCTION: LEGO1 0x10014290 inline const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0548 + // STRING: LEGO1 0x100f0548 return "LegoRaceCar"; } diff --git a/LEGO1/legostate.h b/LEGO1/legostate.h index 55f0a1af..ba4403de 100644 --- a/LEGO1/legostate.h +++ b/LEGO1/legostate.h @@ -14,7 +14,7 @@ class LegoState : public MxCore { // FUNCTION: LEGO1 0x100060d0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f01b8 + // STRING: LEGO1 0x100f01b8 return "LegoState"; } diff --git a/LEGO1/legotexturepresenter.h b/LEGO1/legotexturepresenter.h index 36cc59b9..0ac13926 100644 --- a/LEGO1/legotexturepresenter.h +++ b/LEGO1/legotexturepresenter.h @@ -12,7 +12,7 @@ class LegoTexturePresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000ce50 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0664 + // STRING: LEGO1 0x100f0664 return "LegoTexturePresenter"; } diff --git a/LEGO1/legoworld.h b/LEGO1/legoworld.h index fadeea5c..f6210e8e 100644 --- a/LEGO1/legoworld.h +++ b/LEGO1/legoworld.h @@ -23,7 +23,7 @@ class LegoWorld : public LegoEntity { // FUNCTION: LEGO1 0x1001d690 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0058 + // STRING: LEGO1 0x100f0058 return "LegoWorld"; } diff --git a/LEGO1/legoworldpresenter.h b/LEGO1/legoworldpresenter.h index 3cd02a8f..be18baca 100644 --- a/LEGO1/legoworldpresenter.h +++ b/LEGO1/legoworldpresenter.h @@ -15,7 +15,7 @@ class LegoWorldPresenter : public LegoEntityPresenter { // FUNCTION: LEGO1 0x10066630 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0608 + // STRING: LEGO1 0x100f0608 return "LegoWorldPresenter"; } diff --git a/LEGO1/motorcycle.h b/LEGO1/motorcycle.h index a698fcd8..af04b4ad 100644 --- a/LEGO1/motorcycle.h +++ b/LEGO1/motorcycle.h @@ -13,7 +13,7 @@ class Motorcycle : public IslePathActor { // FUNCTION: LEGO1 0x10035840 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f38e8 + // STRING: LEGO1 0x100f38e8 return "Motorcycle"; } diff --git a/LEGO1/mxaudiopresenter.h b/LEGO1/mxaudiopresenter.h index f1d207e1..73024aac 100644 --- a/LEGO1/mxaudiopresenter.h +++ b/LEGO1/mxaudiopresenter.h @@ -13,7 +13,7 @@ class MxAudioPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000d280 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f078c + // STRING: LEGO1 0x100f078c return "MxAudioPresenter"; } diff --git a/LEGO1/mxbackgroundaudiomanager.h b/LEGO1/mxbackgroundaudiomanager.h index cb03624c..9d47947f 100644 --- a/LEGO1/mxbackgroundaudiomanager.h +++ b/LEGO1/mxbackgroundaudiomanager.h @@ -21,7 +21,7 @@ class MxBackgroundAudioManager : public MxCore { // FUNCTION: LEGO1 0x1007eb70 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f7ac4 + // STRING: LEGO1 0x100f7ac4 return "MxBackgroundAudioManager"; } diff --git a/LEGO1/mxcompositemediapresenter.h b/LEGO1/mxcompositemediapresenter.h index 4f0efc76..ed6f1335 100644 --- a/LEGO1/mxcompositemediapresenter.h +++ b/LEGO1/mxcompositemediapresenter.h @@ -15,7 +15,7 @@ class MxCompositeMediaPresenter : public MxCompositePresenter { // FUNCTION: LEGO1 0x10073f10 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02d4 + // STRING: LEGO1 0x100f02d4 return "MxCompositeMediaPresenter"; } diff --git a/LEGO1/mxcompositepresenter.h b/LEGO1/mxcompositepresenter.h index f6929b6d..6f14e615 100644 --- a/LEGO1/mxcompositepresenter.h +++ b/LEGO1/mxcompositepresenter.h @@ -19,7 +19,7 @@ class MxCompositePresenter : public MxPresenter { // FUNCTION: LEGO1 0x100b6210 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0774 + // STRING: LEGO1 0x100f0774 return "MxCompositePresenter"; } diff --git a/LEGO1/mxcontrolpresenter.h b/LEGO1/mxcontrolpresenter.h index 515af808..9779e45f 100644 --- a/LEGO1/mxcontrolpresenter.h +++ b/LEGO1/mxcontrolpresenter.h @@ -14,7 +14,7 @@ class MxControlPresenter : public MxCompositePresenter { // FUNCTION: LEGO1 0x10044000 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0514 + // STRING: LEGO1 0x100f0514 return "MxControlPresenter"; } diff --git a/LEGO1/mxcore.h b/LEGO1/mxcore.h index 5792eaf2..db812bba 100644 --- a/LEGO1/mxcore.h +++ b/LEGO1/mxcore.h @@ -20,7 +20,7 @@ class MxCore { // FUNCTION: LEGO1 0x100144c0 inline virtual const char* ClassName() const // vtable+0c { - // GLOBAL: LEGO1 0x100f007c + // STRING: LEGO1 0x100f007c return "MxCore"; } diff --git a/LEGO1/mxdiskstreamcontroller.h b/LEGO1/mxdiskstreamcontroller.h index 3fc5111f..52032675 100644 --- a/LEGO1/mxdiskstreamcontroller.h +++ b/LEGO1/mxdiskstreamcontroller.h @@ -22,7 +22,7 @@ class MxDiskStreamController : public MxStreamController { // FUNCTION: LEGO1 0x100c7360 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102144 + // STRING: LEGO1 0x10102144 return "MxDiskStreamController"; } diff --git a/LEGO1/mxdiskstreamprovider.h b/LEGO1/mxdiskstreamprovider.h index bc73c0e4..1314e3f9 100644 --- a/LEGO1/mxdiskstreamprovider.h +++ b/LEGO1/mxdiskstreamprovider.h @@ -32,7 +32,7 @@ class MxDiskStreamProvider : public MxStreamProvider { // FUNCTION: LEGO1 0x100d1160 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x1010287c + // STRING: LEGO1 0x1010287c return "MxDiskStreamProvider"; } diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index 4898eb91..c32dd4aa 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -33,7 +33,7 @@ class MxDSAction : public MxDSObject { // FUNCTION: LEGO1 0x100ad980 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101013f4 + // STRING: LEGO1 0x101013f4 return "MxDSAction"; } diff --git a/LEGO1/mxdsanim.h b/LEGO1/mxdsanim.h index ee206e6a..213fcf87 100644 --- a/LEGO1/mxdsanim.h +++ b/LEGO1/mxdsanim.h @@ -16,7 +16,7 @@ class MxDSAnim : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c9060 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025d8 + // STRING: LEGO1 0x101025d8 return "MxDSAnim"; } diff --git a/LEGO1/mxdsbuffer.h b/LEGO1/mxdsbuffer.h index e9fe2675..daa3263e 100644 --- a/LEGO1/mxdsbuffer.h +++ b/LEGO1/mxdsbuffer.h @@ -27,7 +27,7 @@ class MxDSBuffer : public MxCore { // FUNCTION: LEGO1 0x100c6500 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025b8 + // STRING: LEGO1 0x101025b8 return "MxDSBuffer"; } diff --git a/LEGO1/mxdschunk.h b/LEGO1/mxdschunk.h index 70209596..9f2ac9b6 100644 --- a/LEGO1/mxdschunk.h +++ b/LEGO1/mxdschunk.h @@ -25,7 +25,7 @@ class MxDSChunk : public MxCore { // FUNCTION: LEGO1 0x100be0c0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101e6c + // STRING: LEGO1 0x10101e6c return "MxDSChunk"; } diff --git a/LEGO1/mxdsevent.h b/LEGO1/mxdsevent.h index 8c6e825e..01cf1fa4 100644 --- a/LEGO1/mxdsevent.h +++ b/LEGO1/mxdsevent.h @@ -14,7 +14,7 @@ class MxDSEvent : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c9660 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025f0 + // STRING: LEGO1 0x101025f0 return "MxDSEvent"; } diff --git a/LEGO1/mxdsfile.h b/LEGO1/mxdsfile.h index e453cb9a..34afeccb 100644 --- a/LEGO1/mxdsfile.h +++ b/LEGO1/mxdsfile.h @@ -17,7 +17,7 @@ class MxDSFile : public MxDSSource { // FUNCTION: LEGO1 0x100c0120 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102594 + // STRING: LEGO1 0x10102594 return "MxDSFile"; } diff --git a/LEGO1/mxdsmediaaction.h b/LEGO1/mxdsmediaaction.h index 72fcf036..1f1b97d5 100644 --- a/LEGO1/mxdsmediaaction.h +++ b/LEGO1/mxdsmediaaction.h @@ -18,7 +18,7 @@ class MxDSMediaAction : public MxDSAction { // FUNCTION: LEGO1 0x100c8be0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f7624 + // STRING: LEGO1 0x100f7624 return "MxDSMediaAction"; } diff --git a/LEGO1/mxdsmultiaction.h b/LEGO1/mxdsmultiaction.h index 5003a378..a600b787 100644 --- a/LEGO1/mxdsmultiaction.h +++ b/LEGO1/mxdsmultiaction.h @@ -17,7 +17,7 @@ class MxDSMultiAction : public MxDSAction { // FUNCTION: LEGO1 0x100c9f50 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101dbc + // STRING: LEGO1 0x10101dbc return "MxDSMultiAction"; } diff --git a/LEGO1/mxdsobjectaction.h b/LEGO1/mxdsobjectaction.h index 3286f110..a31f6d6b 100644 --- a/LEGO1/mxdsobjectaction.h +++ b/LEGO1/mxdsobjectaction.h @@ -15,7 +15,7 @@ class MxDSObjectAction : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c88e0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025c4 + // STRING: LEGO1 0x101025c4 return "MxDSObjectAction"; } diff --git a/LEGO1/mxdsparallelaction.h b/LEGO1/mxdsparallelaction.h index 65028ce3..89fc1df0 100644 --- a/LEGO1/mxdsparallelaction.h +++ b/LEGO1/mxdsparallelaction.h @@ -16,7 +16,7 @@ class MxDSParallelAction : public MxDSMultiAction { // FUNCTION: LEGO1 0x100caf00 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102608 + // STRING: LEGO1 0x10102608 return "MxDSParallelAction"; } diff --git a/LEGO1/mxdsselectaction.h b/LEGO1/mxdsselectaction.h index 187e3a72..6b68bfc9 100644 --- a/LEGO1/mxdsselectaction.h +++ b/LEGO1/mxdsselectaction.h @@ -18,7 +18,7 @@ class MxDSSelectAction : public MxDSParallelAction { // FUNCTION: LEGO1 0x100cb6f0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x1010261c + // STRING: LEGO1 0x1010261c return "MxDSSelectAction"; } diff --git a/LEGO1/mxdsserialaction.h b/LEGO1/mxdsserialaction.h index ea758afa..c4fa18b3 100644 --- a/LEGO1/mxdsserialaction.h +++ b/LEGO1/mxdsserialaction.h @@ -17,7 +17,7 @@ class MxDSSerialAction : public MxDSMultiAction { // FUNCTION: LEGO1 0x100caad0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f75dc + // STRING: LEGO1 0x100f75dc return "MxDSSerialAction"; } diff --git a/LEGO1/mxdssound.h b/LEGO1/mxdssound.h index 45f93942..5dc6bbd7 100644 --- a/LEGO1/mxdssound.h +++ b/LEGO1/mxdssound.h @@ -16,7 +16,7 @@ class MxDSSound : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c9330 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025e4 + // STRING: LEGO1 0x101025e4 return "MxDSSound"; } diff --git a/LEGO1/mxdssource.h b/LEGO1/mxdssource.h index 711ba110..db009fb4 100644 --- a/LEGO1/mxdssource.h +++ b/LEGO1/mxdssource.h @@ -14,7 +14,7 @@ class MxDSSource : public MxCore { // FUNCTION: LEGO1 0x100c0010 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102588 + // STRING: LEGO1 0x10102588 return "MxDSSource"; } diff --git a/LEGO1/mxdsstill.h b/LEGO1/mxdsstill.h index 846f8293..268fe79f 100644 --- a/LEGO1/mxdsstill.h +++ b/LEGO1/mxdsstill.h @@ -16,7 +16,7 @@ class MxDSStill : public MxDSMediaAction { // FUNCTION: LEGO1 0x100c9930 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025fc + // STRING: LEGO1 0x101025fc return "MxDSStill"; } diff --git a/LEGO1/mxdssubscriber.h b/LEGO1/mxdssubscriber.h index 13d62040..8187e354 100644 --- a/LEGO1/mxdssubscriber.h +++ b/LEGO1/mxdssubscriber.h @@ -19,7 +19,7 @@ class MxDSSubscriber : public MxCore { // FUNCTION: LEGO1 0x100b7d50 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101020f8 + // STRING: LEGO1 0x101020f8 return "MxDSSubscriber"; } diff --git a/LEGO1/mxentity.h b/LEGO1/mxentity.h index a83462cd..64a003ee 100644 --- a/LEGO1/mxentity.h +++ b/LEGO1/mxentity.h @@ -17,7 +17,7 @@ class MxEntity : public MxCore { // FUNCTION: LEGO1 0x1000c180 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0070 + // STRING: LEGO1 0x100f0070 return "MxEntity"; } diff --git a/LEGO1/mxeventpresenter.h b/LEGO1/mxeventpresenter.h index d022f609..201b15e5 100644 --- a/LEGO1/mxeventpresenter.h +++ b/LEGO1/mxeventpresenter.h @@ -14,7 +14,7 @@ class MxEventPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x100c2c30 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101dcc + // STRING: LEGO1 0x10101dcc return "MxEventPresenter"; } diff --git a/LEGO1/mxflcpresenter.h b/LEGO1/mxflcpresenter.h index 393e2810..0ad44de3 100644 --- a/LEGO1/mxflcpresenter.h +++ b/LEGO1/mxflcpresenter.h @@ -22,7 +22,7 @@ class MxFlcPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x100b33f0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f43c8 + // STRING: LEGO1 0x100f43c8 return "MxFlcPresenter"; } diff --git a/LEGO1/mxloopingflcpresenter.h b/LEGO1/mxloopingflcpresenter.h index e4f781c9..c05c3657 100644 --- a/LEGO1/mxloopingflcpresenter.h +++ b/LEGO1/mxloopingflcpresenter.h @@ -14,7 +14,7 @@ class MxLoopingFlcPresenter : public MxFlcPresenter { // FUNCTION: LEGO1 0x100b4380 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e20 + // STRING: LEGO1 0x10101e20 return "MxLoopingFlcPresenter"; } diff --git a/LEGO1/mxloopingmidipresenter.h b/LEGO1/mxloopingmidipresenter.h index 49df30f4..e47ef30d 100644 --- a/LEGO1/mxloopingmidipresenter.h +++ b/LEGO1/mxloopingmidipresenter.h @@ -10,7 +10,7 @@ class MxLoopingMIDIPresenter : public MxMIDIPresenter { // FUNCTION: LEGO1 0x100b1830 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101de0 + // STRING: LEGO1 0x10101de0 return "MxLoopingMIDIPresenter"; } diff --git a/LEGO1/mxloopingsmkpresenter.h b/LEGO1/mxloopingsmkpresenter.h index 2f20676e..9506de84 100644 --- a/LEGO1/mxloopingsmkpresenter.h +++ b/LEGO1/mxloopingsmkpresenter.h @@ -14,7 +14,7 @@ class MxLoopingSmkPresenter : public MxSmkPresenter { // FUNCTION: LEGO1 0x100b4920 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e08 + // STRING: LEGO1 0x10101e08 return "MxLoopingSmkPresenter"; } diff --git a/LEGO1/mxmediapresenter.h b/LEGO1/mxmediapresenter.h index 4a482a78..32c7b6d0 100644 --- a/LEGO1/mxmediapresenter.h +++ b/LEGO1/mxmediapresenter.h @@ -18,7 +18,7 @@ class MxMediaPresenter : public MxPresenter { // FUNCTION: LEGO1 0x1000c5c0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f074c + // STRING: LEGO1 0x100f074c return "MxMediaPresenter"; } diff --git a/LEGO1/mxmidipresenter.h b/LEGO1/mxmidipresenter.h index 09e11dde..2ec11b0b 100644 --- a/LEGO1/mxmidipresenter.h +++ b/LEGO1/mxmidipresenter.h @@ -14,7 +14,7 @@ class MxMIDIPresenter : public MxMusicPresenter { // FUNCTION: LEGO1 0x100c2650 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101df8 + // STRING: LEGO1 0x10101df8 return "MxMIDIPresenter"; } diff --git a/LEGO1/mxmusicpresenter.h b/LEGO1/mxmusicpresenter.h index 965c38df..bba2afb0 100644 --- a/LEGO1/mxmusicpresenter.h +++ b/LEGO1/mxmusicpresenter.h @@ -13,7 +13,7 @@ class MxMusicPresenter : public MxAudioPresenter { // FUNCTION: LEGO1 0x100c23a0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e48 + // STRING: LEGO1 0x10101e48 return "MxMusicPresenter"; } diff --git a/LEGO1/mxnextactiondatastart.h b/LEGO1/mxnextactiondatastart.h index c9534899..15e35b00 100644 --- a/LEGO1/mxnextactiondatastart.h +++ b/LEGO1/mxnextactiondatastart.h @@ -18,7 +18,7 @@ class MxNextActionDataStart : public MxCore { // FUNCTION: LEGO1 0x100c1900 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x101025a0 + // STRING: LEGO1 0x101025a0 return "MxNextActionDataStart"; } diff --git a/LEGO1/mxobjectfactory.h b/LEGO1/mxobjectfactory.h index cfc97308..3741bfa3 100644 --- a/LEGO1/mxobjectfactory.h +++ b/LEGO1/mxobjectfactory.h @@ -26,7 +26,7 @@ class MxObjectFactory : public MxCore { // FUNCTION: LEGO1 0x10008f70 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0730 + // STRING: LEGO1 0x100f0730 return "MxObjectFactory"; } diff --git a/LEGO1/mxpalette.cpp b/LEGO1/mxpalette.cpp index 6d4f0306..8431fb76 100644 --- a/LEGO1/mxpalette.cpp +++ b/LEGO1/mxpalette.cpp @@ -4,7 +4,6 @@ #include "mxvideomanager.h" // GLOBAL: LEGO1 0x10102188 -// SIZE 0x400 PALETTEENTRY g_defaultPaletteEntries[256] = { {0u, 0u, 0u, 0u}, {128u, 0u, 0u, 0u}, {0u, 128u, 0u, 0u}, {128u, 128u, 0u, 0u}, {0u, 0u, 128u, 0u}, {128u, 0u, 128u, 0u}, {0u, 128u, 128u, 0u}, {128u, 128u, 128u, 0u}, diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h index e0e91fe6..bc327c1f 100644 --- a/LEGO1/mxpresenter.h +++ b/LEGO1/mxpresenter.h @@ -34,7 +34,7 @@ class MxPresenter : public MxCore { // FUNCTION: LEGO1 0x1000bfe0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0740 + // STRING: LEGO1 0x100f0740 return "MxPresenter"; } diff --git a/LEGO1/mxramstreamcontroller.h b/LEGO1/mxramstreamcontroller.h index 008fe458..aa70ec33 100644 --- a/LEGO1/mxramstreamcontroller.h +++ b/LEGO1/mxramstreamcontroller.h @@ -14,7 +14,7 @@ class MxRAMStreamController : public MxStreamController { // FUNCTION: LEGO1 0x100b9430 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10102118 + // STRING: LEGO1 0x10102118 return "MxRAMStreamController"; } diff --git a/LEGO1/mxramstreamprovider.h b/LEGO1/mxramstreamprovider.h index 112f6b71..16ed5a4c 100644 --- a/LEGO1/mxramstreamprovider.h +++ b/LEGO1/mxramstreamprovider.h @@ -12,7 +12,7 @@ class MxRAMStreamProvider : public MxStreamProvider { // FUNCTION: LEGO1 0x100d0970 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10102864 + // STRING: LEGO1 0x10102864 return "MxRAMStreamProvider"; } diff --git a/LEGO1/mxsmkpresenter.h b/LEGO1/mxsmkpresenter.h index 95b6a201..4c3913cc 100644 --- a/LEGO1/mxsmkpresenter.h +++ b/LEGO1/mxsmkpresenter.h @@ -15,7 +15,7 @@ class MxSmkPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x100b3730 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e38 + // STRING: LEGO1 0x10101e38 return "MxSmkPresenter"; } diff --git a/LEGO1/mxsoundpresenter.h b/LEGO1/mxsoundpresenter.h index 1c4051ee..d61d8088 100644 --- a/LEGO1/mxsoundpresenter.h +++ b/LEGO1/mxsoundpresenter.h @@ -13,7 +13,7 @@ class MxSoundPresenter : public MxAudioPresenter { // FUNCTION: LEGO1 0x1000d4a0 inline virtual const char* ClassName() const // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07a0 + // STRING: LEGO1 0x100f07a0 return "MxSoundPresenter"; }; diff --git a/LEGO1/mxstillpresenter.h b/LEGO1/mxstillpresenter.h index e28ab84f..828f58b7 100644 --- a/LEGO1/mxstillpresenter.h +++ b/LEGO1/mxstillpresenter.h @@ -15,7 +15,7 @@ class MxStillPresenter : public MxVideoPresenter { // FUNCTION: LEGO1 0x100435c0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0184 + // STRING: LEGO1 0x100f0184 return "MxStillPresenter"; } diff --git a/LEGO1/mxstreamchunk.h b/LEGO1/mxstreamchunk.h index 18bc2335..5b258603 100644 --- a/LEGO1/mxstreamchunk.h +++ b/LEGO1/mxstreamchunk.h @@ -17,7 +17,7 @@ class MxStreamChunk : public MxDSChunk { // FUNCTION: LEGO1 0x100b1fe0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10101e5c + // STRING: LEGO1 0x10101e5c return "MxStreamChunk"; } diff --git a/LEGO1/mxstreamcontroller.h b/LEGO1/mxstreamcontroller.h index 0389772b..bbd1eb3d 100644 --- a/LEGO1/mxstreamcontroller.h +++ b/LEGO1/mxstreamcontroller.h @@ -24,7 +24,7 @@ class MxStreamController : public MxCore { // FUNCTION: LEGO1 0x100c0f10 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x10102130 + // STRING: LEGO1 0x10102130 return "MxStreamController"; } diff --git a/LEGO1/mxstreamer.h b/LEGO1/mxstreamer.h index 8017e898..4d3684e9 100644 --- a/LEGO1/mxstreamer.h +++ b/LEGO1/mxstreamer.h @@ -78,7 +78,7 @@ class MxStreamer : public MxCore { // FUNCTION: LEGO1 0x100b9000 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x1010210c + // STRING: LEGO1 0x1010210c return "MxStreamer"; } diff --git a/LEGO1/mxvideopresenter.h b/LEGO1/mxvideopresenter.h index d25ecb2b..4c1bab5e 100644 --- a/LEGO1/mxvideopresenter.h +++ b/LEGO1/mxvideopresenter.h @@ -23,7 +23,7 @@ class MxVideoPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000c820 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0760 + // STRING: LEGO1 0x100f0760 return "MxVideoPresenter"; } diff --git a/LEGO1/mxwavepresenter.h b/LEGO1/mxwavepresenter.h index 4210a44e..cd09d486 100644 --- a/LEGO1/mxwavepresenter.h +++ b/LEGO1/mxwavepresenter.h @@ -16,7 +16,7 @@ class MxWavePresenter : public MxSoundPresenter { // FUNCTION: LEGO1 0x1000d6c0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07b4 + // STRING: LEGO1 0x100f07b4 return "MxWavePresenter"; } diff --git a/LEGO1/pizza.h b/LEGO1/pizza.h index f1ac9f45..11bf6814 100644 --- a/LEGO1/pizza.h +++ b/LEGO1/pizza.h @@ -20,7 +20,7 @@ class Pizza : public IsleActor { // FUNCTION: LEGO1 0x10037f90 inline const char* ClassName() const // vtable+0c { - // GLOBAL: LEGO1 0x100f038c + // STRING: LEGO1 0x100f038c return "Pizza"; } diff --git a/LEGO1/pizzamissionstate.h b/LEGO1/pizzamissionstate.h index a9231c81..85b8e4bb 100644 --- a/LEGO1/pizzamissionstate.h +++ b/LEGO1/pizzamissionstate.h @@ -18,7 +18,7 @@ class PizzaMissionState : public LegoState { // FUNCTION: LEGO1 0x10039290 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00d4 + // STRING: LEGO1 0x100f00d4 return "PizzaMissionState"; } diff --git a/LEGO1/pizzeria.h b/LEGO1/pizzeria.h index b9fcadf3..0196d616 100644 --- a/LEGO1/pizzeria.h +++ b/LEGO1/pizzeria.h @@ -10,7 +10,7 @@ class Pizzeria : public IsleActor { // FUNCTION: LEGO1 0x1000e780 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0380 + // STRING: LEGO1 0x100f0380 return "Pizzeria"; } diff --git a/LEGO1/pizzeriastate.h b/LEGO1/pizzeriastate.h index 53f4ddd5..c27fcef0 100644 --- a/LEGO1/pizzeriastate.h +++ b/LEGO1/pizzeriastate.h @@ -12,7 +12,7 @@ class PizzeriaState : public LegoState { // FUNCTION: LEGO1 0x10017c20 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0370 + // STRING: LEGO1 0x100f0370 return "PizzeriaState"; } diff --git a/LEGO1/police.h b/LEGO1/police.h index 0da58828..829c7e66 100644 --- a/LEGO1/police.h +++ b/LEGO1/police.h @@ -16,7 +16,7 @@ class Police : public LegoWorld { // FUNCTION: LEGO1 0x1005e1e0 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0450 + // STRING: LEGO1 0x100f0450 return "Police"; } diff --git a/LEGO1/policeentity.h b/LEGO1/policeentity.h index e2314dd3..735cf0bc 100644 --- a/LEGO1/policeentity.h +++ b/LEGO1/policeentity.h @@ -10,7 +10,7 @@ class PoliceEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000ed60 inline virtual const char* ClassName() const override // vtable+0xc { - // GLOBAL: LEGO1 0x100f0328 + // STRING: LEGO1 0x100f0328 return "PoliceEntity"; } diff --git a/LEGO1/policestate.h b/LEGO1/policestate.h index b3a732c9..2638a393 100644 --- a/LEGO1/policestate.h +++ b/LEGO1/policestate.h @@ -12,7 +12,7 @@ class PoliceState : public LegoState { // FUNCTION: LEGO1 0x1005e860 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0444 + // STRING: LEGO1 0x100f0444 return "PoliceState"; } diff --git a/LEGO1/racecar.h b/LEGO1/racecar.h index b0db77c5..b4a210e6 100644 --- a/LEGO1/racecar.h +++ b/LEGO1/racecar.h @@ -14,7 +14,7 @@ class RaceCar : public IslePathActor { // FUNCTION: LEGO1 0x10028270 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03e0 + // STRING: LEGO1 0x100f03e0 return "RaceCar"; } diff --git a/LEGO1/racestate.h b/LEGO1/racestate.h index 63a775d4..ef3cfa63 100644 --- a/LEGO1/racestate.h +++ b/LEGO1/racestate.h @@ -20,7 +20,7 @@ class RaceState : public LegoState { // FUNCTION: LEGO1 0x10016010 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07d0 + // STRING: LEGO1 0x100f07d0 return "RaceState"; } diff --git a/LEGO1/radio.h b/LEGO1/radio.h index 8d454483..54aef25b 100644 --- a/LEGO1/radio.h +++ b/LEGO1/radio.h @@ -13,7 +13,7 @@ class Radio : public MxCore { // FUNCTION: LEGO1 0x1002c8e0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f328c + // STRING: LEGO1 0x100f328c return "Radio"; } diff --git a/LEGO1/radiostate.h b/LEGO1/radiostate.h index dc2c8b8f..a5ea6035 100644 --- a/LEGO1/radiostate.h +++ b/LEGO1/radiostate.h @@ -12,7 +12,7 @@ class RadioState : public LegoState { // FUNCTION: LEGO1 0x1002cf60 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04f8 + // STRING: LEGO1 0x100f04f8 return "RadioState"; } diff --git a/LEGO1/realtime/matrix.cpp b/LEGO1/realtime/matrix.cpp index 852e14d0..61f7b1a9 100644 --- a/LEGO1/realtime/matrix.cpp +++ b/LEGO1/realtime/matrix.cpp @@ -138,7 +138,7 @@ void Matrix4Impl::ToQuaternion(Vector4Impl* p_outQuat) return; } - // GLOBAL: LEGO1 0x100d4090 + // ~GLOBAL: LEGO1 0x100d4090 static int rotateIndex[] = {1, 2, 0}; // Largest element along the trace diff --git a/LEGO1/registrationbook.h b/LEGO1/registrationbook.h index 4f19a8dc..3ae904c9 100644 --- a/LEGO1/registrationbook.h +++ b/LEGO1/registrationbook.h @@ -15,7 +15,7 @@ class RegistrationBook : public LegoWorld { // FUNCTION: LEGO1 0x10076e10 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f04c8 + // STRING: LEGO1 0x100f04c8 return "RegistrationBook"; } diff --git a/LEGO1/score.h b/LEGO1/score.h index 89d9608d..c927863f 100644 --- a/LEGO1/score.h +++ b/LEGO1/score.h @@ -18,7 +18,7 @@ class Score : public LegoWorld { // FUNCTION: LEGO1 0x100010c0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0050 + // STRING: LEGO1 0x100f0050 return "Score"; } diff --git a/LEGO1/scorestate.h b/LEGO1/scorestate.h index 2797ad34..21be3493 100644 --- a/LEGO1/scorestate.h +++ b/LEGO1/scorestate.h @@ -10,7 +10,7 @@ class ScoreState : public LegoState { // FUNCTION: LEGO1 0x1000de40 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0084 + // STRING: LEGO1 0x100f0084 return "ScoreState"; }; diff --git a/LEGO1/skateboard.h b/LEGO1/skateboard.h index 671c7f86..171705c4 100644 --- a/LEGO1/skateboard.h +++ b/LEGO1/skateboard.h @@ -13,7 +13,7 @@ class SkateBoard : public IslePathActor { // FUNCTION: LEGO1 0x1000fdd0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f041c + // STRING: LEGO1 0x100f041c return "SkateBoard"; } diff --git a/LEGO1/tgl/d3drm/renderer.cpp b/LEGO1/tgl/d3drm/renderer.cpp index d098f7ff..bd9ed873 100644 --- a/LEGO1/tgl/d3drm/renderer.cpp +++ b/LEGO1/tgl/d3drm/renderer.cpp @@ -61,7 +61,7 @@ Device* RendererImpl::CreateDevice(const DeviceDirect3DCreateData& data) } // GLOBAL: LEGO1 0x10101040 -static int gSetBufferCount = 1; +static int g_SetBufferCount = 1; // FUNCTION: LEGO1 0x100a1900 Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& data) @@ -73,7 +73,7 @@ Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& data) data.m_pBackBuffer, &device->m_data ); - if (SUCCEEDED(result) && data.m_pBackBuffer && gSetBufferCount) { + if (SUCCEEDED(result) && data.m_pBackBuffer && g_SetBufferCount) { device->m_data->SetBufferCount(2); } if (!SUCCEEDED(result)) { diff --git a/LEGO1/towtrack.h b/LEGO1/towtrack.h index 2243f9a2..1cc7e6af 100644 --- a/LEGO1/towtrack.h +++ b/LEGO1/towtrack.h @@ -13,7 +13,7 @@ class TowTrack : public IslePathActor { // FUNCTION: LEGO1 0x1004c7c0 inline virtual const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03b8 + // STRING: LEGO1 0x100f03b8 return "TowTrack"; } diff --git a/LEGO1/towtrackmissionstate.h b/LEGO1/towtrackmissionstate.h index 7537cb94..9dc7c587 100644 --- a/LEGO1/towtrackmissionstate.h +++ b/LEGO1/towtrackmissionstate.h @@ -12,7 +12,7 @@ class TowTrackMissionState : public LegoState { // FUNCTION: LEGO1 0x1004dfa0 inline virtual const char* ClassName() const // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00bc + // STRING: LEGO1 0x100f00bc return "TowTrackMissionState"; } diff --git a/tools/isledecomp/isledecomp/parser/error.py b/tools/isledecomp/isledecomp/parser/error.py index 638a806e..eb1aa7b8 100644 --- a/tools/isledecomp/isledecomp/parser/error.py +++ b/tools/isledecomp/isledecomp/parser/error.py @@ -39,6 +39,14 @@ class ParserError(Enum): # WARN: We found a marker to be referenced by name outside of a header file. BYNAME_FUNCTION_IN_CPP = 109 + # WARN: A GLOBAL marker appeared over a variable without the g_ prefix + GLOBAL_MISSING_PREFIX = 110 + + # WARN: GLOBAL marker points at something other than variable declaration. + # We can't match global variables based on position, but the goal here is + # to ignore things like string literal that are not variables. + GLOBAL_NOT_VARIABLE = 111 + # This code or higher is an error, not a warning DECOMP_ERROR_START = 200 @@ -50,13 +58,18 @@ class ParserError(Enum): # For example, a GLOBAL cannot follow FUNCTION/STUB INCOMPATIBLE_MARKER = 201 - # ERROR: The line following a synthetic marker was not a comment - BAD_SYNTHETIC = 202 + # ERROR: The line following an explicit by-name marker was not a comment + # We assume a syntax error here rather than try to use the next line + BAD_NAMEREF = 202 # ERROR: This function offset comes before the previous offset from the same module # This hopefully gives some hint about which functions need to be rearranged. FUNCTION_OUT_OF_ORDER = 203 + # ERROR: The line following an explicit by-name marker that does _not_ expect + # a comment -- i.e. VTABLE or GLOBAL -- could not extract the name + NO_SUITABLE_NAME = 204 + @dataclass class ParserAlert: diff --git a/tools/isledecomp/isledecomp/parser/marker.py b/tools/isledecomp/isledecomp/parser/marker.py new file mode 100644 index 00000000..d2e181dd --- /dev/null +++ b/tools/isledecomp/isledecomp/parser/marker.py @@ -0,0 +1,103 @@ +import re +from typing import Optional +from enum import Enum + + +class MarkerType(Enum): + UNKNOWN = -100 + FUNCTION = 1 + STUB = 2 + SYNTHETIC = 3 + TEMPLATE = 4 + GLOBAL = 5 + VTABLE = 6 + STRING = 7 + LIBRARY = 8 + + +markerRegex = re.compile( + r"\s*//\s*(?P\w+):\s*(?P\w+)\s+(?P0x[a-f0-9]+)", + flags=re.I, +) + + +markerExactRegex = re.compile( + r"\s*// (?P[A-Z]+): (?P[A-Z0-9]+) (?P0x[a-f0-9]+)$" +) + + +class DecompMarker: + def __init__(self, marker_type: str, module: str, offset: int) -> None: + try: + self._type = MarkerType[marker_type.upper()] + except KeyError: + self._type = MarkerType.UNKNOWN + + # Convert to upper here. A lot of other analysis depends on this name + # being consistent and predictable. If the name is _not_ capitalized + # we will emit a syntax error. + self._module: str = module.upper() + self._offset: int = offset + + @property + def type(self) -> MarkerType: + return self._type + + @property + def module(self) -> str: + return self._module + + @property + def offset(self) -> int: + return self._offset + + def is_regular_function(self) -> bool: + """Regular function, meaning: not an explicit byname lookup. FUNCTION + markers can be _implicit_ byname. + FUNCTION and STUB markers are (currently) the only heterogenous marker types that + can be lumped together, although the reasons for doing so are a little vague.""" + return self._type in (MarkerType.FUNCTION, MarkerType.STUB) + + def is_explicit_byname(self) -> bool: + return self._type in ( + MarkerType.SYNTHETIC, + MarkerType.TEMPLATE, + MarkerType.LIBRARY, + ) + + def is_variable(self) -> bool: + return self._type == MarkerType.GLOBAL + + def is_synthetic(self) -> bool: + return self._type == MarkerType.SYNTHETIC + + def is_template(self) -> bool: + return self._type == MarkerType.TEMPLATE + + def is_vtable(self) -> bool: + return self._type == MarkerType.VTABLE + + def is_library(self) -> bool: + return self._type == MarkerType.LIBRARY + + def is_string(self) -> bool: + return self._type == MarkerType.STRING + + def allowed_in_func(self) -> bool: + return self._type in (MarkerType.GLOBAL, MarkerType.STRING) + + +def match_marker(line: str) -> Optional[DecompMarker]: + match = markerRegex.match(line) + if match is None: + return None + + return DecompMarker( + marker_type=match.group("type"), + module=match.group("module"), + offset=int(match.group("offset"), 16), + ) + + +def is_marker_exact(line: str) -> bool: + return markerExactRegex.match(line) is not None diff --git a/tools/isledecomp/isledecomp/parser/node.py b/tools/isledecomp/isledecomp/parser/node.py index 721a24b9..b6561fd6 100644 --- a/tools/isledecomp/isledecomp/parser/node.py +++ b/tools/isledecomp/isledecomp/parser/node.py @@ -1,35 +1,57 @@ +from typing import Optional from dataclasses import dataclass +from .marker import MarkerType @dataclass -class ParserNode: +class ParserSymbol: + """Exported decomp marker with all information (except the code filename) required to + cross-reference with cvdump data.""" + + type: MarkerType line_number: int - - -@dataclass -class ParserSymbol(ParserNode): module: str offset: int + name: str + + # The parser doesn't (currently) know about the code filename, but if you + # wanted to set it here after the fact, here's the spot. + filename: Optional[str] = None + + def should_skip(self) -> bool: + """The default is to compare any symbols we have""" + return False + + def is_nameref(self) -> bool: + """All symbols default to name lookup""" + return True @dataclass class ParserFunction(ParserSymbol): - name: str + # We are able to detect the closing line of a function with some reliability. + # This isn't used for anything right now, but perhaps later it will be. + end_line: Optional[int] = None + + # All marker types are referenced by name except FUNCTION/STUB. These can also be + # referenced by name, but only if this flag is true. lookup_by_name: bool = False - is_stub: bool = False - is_synthetic: bool = False - is_template: bool = False - end_line: int = -1 + + def should_skip(self) -> bool: + return self.type == MarkerType.STUB + + def is_nameref(self) -> bool: + return ( + self.type in (MarkerType.SYNTHETIC, MarkerType.TEMPLATE, MarkerType.LIBRARY) + or self.lookup_by_name + ) @dataclass class ParserVariable(ParserSymbol): - name: str - size: int = -1 is_static: bool = False @dataclass class ParserVtable(ParserSymbol): - class_name: str - num_entries: int = -1 + pass diff --git a/tools/isledecomp/isledecomp/parser/parser.py b/tools/isledecomp/isledecomp/parser/parser.py index 336d4b0c..f9485e65 100644 --- a/tools/isledecomp/isledecomp/parser/parser.py +++ b/tools/isledecomp/isledecomp/parser/parser.py @@ -3,15 +3,19 @@ from typing import List, Iterable, Iterator from enum import Enum from .util import ( - DecompMarker, is_blank_or_comment, - match_marker, - is_marker_exact, get_class_name, + get_variable_name, get_synthetic_name, remove_trailing_comment, ) +from .marker import ( + DecompMarker, + match_marker, + is_marker_exact, +) from .node import ( + ParserSymbol, ParserFunction, ParserVariable, ParserVtable, @@ -28,44 +32,23 @@ class ReaderState(Enum): IN_GLOBAL = 5 IN_FUNC_GLOBAL = 6 IN_VTABLE = 7 + IN_SYNTHETIC = 8 + IN_LIBRARY = 9 DONE = 100 -def marker_is_stub(marker: DecompMarker) -> bool: - return marker.type.upper() == "STUB" - - -def marker_is_variable(marker: DecompMarker) -> bool: - return marker.type.upper() == "GLOBAL" - - -def marker_is_synthetic(marker: DecompMarker) -> bool: - return marker.type.upper() in ("SYNTHETIC", "TEMPLATE") - - -def marker_is_template(marker: DecompMarker) -> bool: - return marker.type.upper() == "TEMPLATE" - - -def marker_is_function(marker: DecompMarker) -> bool: - return marker.type.upper() in ("FUNCTION", "STUB") - - -def marker_is_vtable(marker: DecompMarker) -> bool: - return marker.type.upper() == "VTABLE" - - class MarkerDict: def __init__(self) -> None: self.markers: dict = {} def insert(self, marker: DecompMarker) -> bool: """Return True if this insert would overwrite""" - module = marker.module.upper() + module = marker.module if module in self.markers: return True - self.markers[module] = (marker.type, marker.offset) + # TODO: type converted back to string version here instead of using enum + self.markers[module] = (marker.type.name, marker.offset) return False def iter(self) -> Iterator[DecompMarker]: @@ -82,9 +65,7 @@ class DecompParser: # but not right now def __init__(self) -> None: # The lists to be populated as we parse - self.functions: List[ParserFunction] = [] - self.vtables: List[ParserVtable] = [] - self.variables: List[ParserVariable] = [] + self._symbols: List[ParserSymbol] = [] self.alerts: List[ParserAlert] = [] self.line_number: int = 0 @@ -113,9 +94,7 @@ def __init__(self) -> None: self.function_sig: str = "" def reset(self): - self.functions = [] - self.vtables = [] - self.variables = [] + self._symbols = [] self.alerts = [] self.line_number = 0 @@ -131,6 +110,18 @@ def reset(self): self.function_start = 0 self.function_sig = "" + @property + def functions(self) -> List[ParserSymbol]: + return [s for s in self._symbols if isinstance(s, ParserFunction)] + + @property + def vtables(self) -> List[ParserSymbol]: + return [s for s in self._symbols if isinstance(s, ParserVtable)] + + @property + def variables(self) -> List[ParserSymbol]: + return [s for s in self._symbols if isinstance(s, ParserVariable)] + def _recover(self): """We hit a syntax error and need to reset temp structures""" self.state = ReaderState.SEARCH @@ -159,10 +150,17 @@ def _function_marker(self, marker: DecompMarker): self._syntax_warning(ParserError.DUPLICATE_MODULE) self.state = ReaderState.WANT_SIG - def _synthetic_marker(self, marker: DecompMarker): + def _nameref_marker(self, marker: DecompMarker): + """Functions explicitly referenced by name are set here""" if self.fun_markers.insert(marker): self._syntax_warning(ParserError.DUPLICATE_MODULE) - self.state = ReaderState.IN_TEMPLATE + + if marker.is_template(): + self.state = ReaderState.IN_TEMPLATE + elif marker.is_synthetic(): + self.state = ReaderState.IN_SYNTHETIC + else: + self.state = ReaderState.IN_LIBRARY def _function_done(self, lookup_by_name: bool = False, unexpected: bool = False): end_line = self.line_number @@ -173,16 +171,14 @@ def _function_done(self, lookup_by_name: bool = False, unexpected: bool = False) end_line -= 1 for marker in self.fun_markers.iter(): - self.functions.append( + self._symbols.append( ParserFunction( + type=marker.type, line_number=self.function_start, module=marker.module, offset=marker.offset, - lookup_by_name=lookup_by_name, - is_stub=marker_is_stub(marker), - is_synthetic=marker_is_synthetic(marker), - is_template=marker_is_template(marker), name=self.function_sig, + lookup_by_name=lookup_by_name, end_line=end_line, ) ) @@ -202,12 +198,13 @@ def _vtable_done(self, class_name: str = None): class_name = self.last_line.strip() for marker in self.tbl_markers.iter(): - self.vtables.append( + self._symbols.append( ParserVtable( + type=marker.type, line_number=self.line_number, module=marker.module, offset=marker.offset, - class_name=class_name, + name=class_name, ) ) @@ -223,14 +220,19 @@ def _variable_marker(self, marker: DecompMarker): else: self.state = ReaderState.IN_GLOBAL - def _variable_done(self): + def _variable_done(self, name: str): + if not name.startswith("g_"): + self._syntax_warning(ParserError.GLOBAL_MISSING_PREFIX) + for marker in self.var_markers.iter(): - self.variables.append( + self._symbols.append( ParserVariable( + type=marker.type, line_number=self.line_number, module=marker.module, offset=marker.offset, - name=self.last_line.strip(), + name=name, + is_static=self.state == ReaderState.IN_FUNC_GLOBAL, ) ) @@ -246,12 +248,23 @@ def _handle_marker(self, marker: DecompMarker): self._syntax_error(ParserError.UNEXPECTED_MARKER) return + # If we are inside a function, the only markers we accept are: + # GLOBAL, indicating a static variable + # STRING, indicating a literal string. + # Otherwise we assume that the parser missed the end of the function + # and we have moved on to something else. + # This is unlikely to occur with well-formed code, but + # we can recover easily by just ending the function here. + if self.state == ReaderState.IN_FUNC and not marker.allowed_in_func(): + self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) + self._function_done(unexpected=True) + # TODO: How uncertain are we of detecting the end of a function # in a clang-formatted file? For now we assume we have missed the # end if we detect a non-GLOBAL marker while state is IN_FUNC. # Maybe these cases should be syntax errors instead - if marker_is_function(marker): + if marker.is_regular_function(): if self.state in ( ReaderState.SEARCH, ReaderState.WANT_SIG, @@ -259,29 +272,41 @@ def _handle_marker(self, marker: DecompMarker): # We will allow multiple offsets if we have just begun # the code block, but not after we hit the curly brace. self._function_marker(marker) - elif self.state == ReaderState.IN_FUNC: - # We hit another offset unexpectedly. - # We can recover easily by just ending the function here. - self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) - self._function_done(unexpected=True) - - # Start the next function right after so we can - # read the next line. - self._function_marker(marker) else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker_is_synthetic(marker): + elif marker.is_template(): if self.state in (ReaderState.SEARCH, ReaderState.IN_TEMPLATE): - self._synthetic_marker(marker) - elif self.state == ReaderState.IN_FUNC: - self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) - self._function_done(lookup_by_name=True, unexpected=True) - self._synthetic_marker(marker) + self._nameref_marker(marker) else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker_is_variable(marker): + elif marker.is_synthetic(): + if self.state in (ReaderState.SEARCH, ReaderState.IN_SYNTHETIC): + self._nameref_marker(marker) + else: + self._syntax_error(ParserError.INCOMPATIBLE_MARKER) + + elif marker.is_library(): + if self.state in (ReaderState.SEARCH, ReaderState.IN_LIBRARY): + self._nameref_marker(marker) + else: + self._syntax_error(ParserError.INCOMPATIBLE_MARKER) + + elif marker.is_string(): + # TODO: We are ignoring string markers for the moment. + # We already have a lot of them in the codebase, though, so we'll + # hang onto them for now in case we can use them later. + # To match up string constants, the strategy will be: + # 1. Use cvdump to find all string constants in the recomp + # 2. In the original binary, look at relocated vaddrs from .rdata + # 3. Try to match up string data from #1 with locations in #2 + + # Throw the syntax error we would throw if we were parsing these + if self.state not in (ReaderState.SEARCH, ReaderState.IN_FUNC): + self._syntax_error(ParserError.INCOMPATIBLE_MARKER) + + elif marker.is_variable(): if self.state in ( ReaderState.SEARCH, ReaderState.IN_GLOBAL, @@ -292,13 +317,9 @@ def _handle_marker(self, marker: DecompMarker): else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker_is_vtable(marker): + elif marker.is_vtable(): if self.state in (ReaderState.SEARCH, ReaderState.IN_VTABLE): self._vtable_marker(marker) - elif self.state == ReaderState.IN_FUNC: - self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) - self._function_done(unexpected=True) - self._vtable_marker(marker) else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) @@ -322,12 +343,16 @@ def read_line(self, line: str): return line_strip = line.strip() - if self.state == ReaderState.IN_TEMPLATE: - # TEMPLATE functions are a special case. The signature is - # given on the next line (in a // comment) + if self.state in ( + ReaderState.IN_SYNTHETIC, + ReaderState.IN_TEMPLATE, + ReaderState.IN_LIBRARY, + ): + # Explicit nameref functions provide the function name + # on the next line (in a // comment) name = get_synthetic_name(line) if name is None: - self._syntax_error(ParserError.BAD_SYNTHETIC) + self._syntax_error(ParserError.BAD_NAMEREF) else: self.function_sig = name self._function_starts_here() @@ -384,8 +409,28 @@ def read_line(self, line: str): self._function_done() elif self.state in (ReaderState.IN_GLOBAL, ReaderState.IN_FUNC_GLOBAL): - if not is_blank_or_comment(line): - self._variable_done() + # TODO: Known problem that an error here will cause us to abandon a + # function we have already parsed if state == IN_FUNC_GLOBAL. + # However, we are not tolerant of _any_ syntax problems in our + # CI actions, so the solution is to just fix the invalid marker. + if is_blank_or_comment(line): + self._syntax_error(ParserError.NO_SUITABLE_NAME) + return + + # We don't have a foolproof mechanism to tell what is and is not a variable. + # If the GLOBAL is being declared on a `return` statement, though, this is + # not correct. It is either a string literal (which will be handled differently) + # or it is not the variable declaration, which is incorrect decomp syntax. + if line.strip().startswith("return"): + self._syntax_error(ParserError.GLOBAL_NOT_VARIABLE) + return + + name = get_variable_name(line) + if name is None: + self._syntax_error(ParserError.NO_SUITABLE_NAME) + return + + self._variable_done(name) elif self.state == ReaderState.IN_VTABLE: vtable_class = get_class_name(line) diff --git a/tools/isledecomp/isledecomp/parser/util.py b/tools/isledecomp/isledecomp/parser/util.py index 99ab1c56..a106d841 100644 --- a/tools/isledecomp/isledecomp/parser/util.py +++ b/tools/isledecomp/isledecomp/parser/util.py @@ -1,17 +1,6 @@ # C++ Parser utility functions and data structures -from __future__ import annotations # python <3.10 compatibility import re -from collections import namedtuple - -DecompMarker = namedtuple("DecompMarker", ["type", "module", "offset"]) - - -markerRegex = re.compile( - r"\s*//\s*(\w+):\s*(\w+)\s+(0x[a-f0-9]+)", - flags=re.I, -) - -markerExactRegex = re.compile(r"\s*// ([A-Z]+): ([A-Z0-9]+) (0x[a-f0-9]+)$") +from typing import Optional # The goal here is to just read whatever is on the next line, so some # flexibility in the formatting seems OK @@ -23,7 +12,7 @@ trailingCommentRegex = re.compile(r"(\s*(?://|/\*).*)$") -def get_synthetic_name(line: str) -> str | None: +def get_synthetic_name(line: str) -> Optional[str]: """Synthetic names appear on a single line comment on the line after the marker. If that's not what we have, return None""" template_match = templateCommentRegex.match(line) @@ -51,20 +40,6 @@ def is_blank_or_comment(line: str) -> bool: ) -def match_marker(line: str) -> DecompMarker | None: - match = markerRegex.match(line) - if match is None: - return None - - return DecompMarker( - type=match.group(1), module=match.group(2), offset=int(match.group(3), 16) - ) - - -def is_marker_exact(line: str) -> bool: - return markerExactRegex.match(line) is not None - - template_class_decl_regex = re.compile( r"\s*(?:\/\/)?\s*(?:class|struct) (\w+)<([\w]+)\s*(\*+)?\s*>" ) @@ -73,7 +48,7 @@ def is_marker_exact(line: str) -> bool: class_decl_regex = re.compile(r"\s*(?:\/\/)?\s*(?:class|struct) (\w+)") -def get_class_name(line: str) -> str | None: +def get_class_name(line: str) -> Optional[str]: """For VTABLE markers, extract the class name from the code line or comment where it appears.""" @@ -93,3 +68,21 @@ def get_class_name(line: str) -> str | None: return match.group(1) return None + + +global_regex = re.compile(r"(?Pg_\w+)") +less_strict_global_regex = re.compile(r"(?P\w+)(?:\)\(|\[.*|\s*=.*|;)") + + +def get_variable_name(line: str) -> Optional[str]: + """Grab the name of the variable annotated with the GLOBAL marker. + Correct syntax would have the variable start with the prefix "g_" + but we will try to match regardless.""" + + if (match := global_regex.search(line)) is not None: + return match.group("name") + + if (match := less_strict_global_regex.search(line)) is not None: + return match.group("name") + + return None diff --git a/tools/isledecomp/tests/test_parser.py b/tools/isledecomp/tests/test_parser.py index c31602f1..853e773d 100644 --- a/tools/isledecomp/tests/test_parser.py +++ b/tools/isledecomp/tests/test_parser.py @@ -115,7 +115,7 @@ def test_different_markers_same_module(parser): # Use first marker declaration, don't replace assert len(parser.functions) == 1 - assert parser.functions[0].is_stub is False + assert parser.functions[0].should_skip() is False # Should alert to this assert len(parser.alerts) == 1 @@ -193,7 +193,7 @@ def test_multiple_vtables(parser): ) assert len(parser.alerts) == 0 assert len(parser.vtables) == 2 - assert parser.vtables[0].class_name == "MxString" + assert parser.vtables[0].name == "MxString" def test_multiple_vtables_same_module(parser): @@ -247,7 +247,7 @@ def test_synthetic_no_comment(parser): ) assert len(parser.functions) == 0 assert len(parser.alerts) == 1 - assert parser.alerts[0].code == ParserError.BAD_SYNTHETIC + assert parser.alerts[0].code == ParserError.BAD_NAMEREF assert parser.state == ReaderState.SEARCH @@ -375,3 +375,70 @@ def test_unexpected_eof(parser): assert len(parser.functions) == 1 assert len(parser.alerts) == 1 assert parser.alerts[0].code == ParserError.UNEXPECTED_END_OF_FILE + + +def test_global_variable_prefix(parser): + """Global and static variables should have the g_ prefix.""" + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + 'const char* g_msg = "hello";', + ] + ) + assert len(parser.variables) == 1 + assert len(parser.alerts) == 0 + + parser.read_lines( + [ + "// GLOBAL: TEXT 0x5555", + "int test = 5;", + ] + ) + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.GLOBAL_MISSING_PREFIX + # In spite of that, we should still grab the variable name. + assert parser.variables[1].name == "test" + + +def test_global_nomatch(parser): + """We do our best to grab the variable name, even without the g_ prefix + but this (by design) will not match everything.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "FunctionCall();", + ] + ) + assert len(parser.variables) == 0 + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.NO_SUITABLE_NAME + + +def test_static_variable(parser): + """We can detect whether a variable is a static function variable + based on the parser's state when we detect it. + Checking for the word `static` alone is not a good test. + Static class variables are filed as S_GDATA32, same as regular globals. + Only function statics are filed as S_LDATA32.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "int g_test = 1234;", + ] + ) + assert len(parser.variables) == 1 + assert parser.variables[0].is_static is False + + parser.read_lines( + [ + "// FUNCTION: TEST 0x5555", + "void test_function() {", + "// GLOBAL: TEST 0x8888", + "int g_internal = 0;", + "}", + ] + ) + assert len(parser.variables) == 2 + assert parser.variables[1].is_static is True diff --git a/tools/isledecomp/tests/test_parser_statechange.py b/tools/isledecomp/tests/test_parser_statechange.py index 8d18d547..cb54cf0a 100644 --- a/tools/isledecomp/tests/test_parser_statechange.py +++ b/tools/isledecomp/tests/test_parser_statechange.py @@ -11,9 +11,11 @@ (_rs.SEARCH, "FUNCTION", _rs.WANT_SIG, None), (_rs.SEARCH, "GLOBAL", _rs.IN_GLOBAL, None), (_rs.SEARCH, "STUB", _rs.WANT_SIG, None), - (_rs.SEARCH, "SYNTHETIC", _rs.IN_TEMPLATE, None), + (_rs.SEARCH, "SYNTHETIC", _rs.IN_SYNTHETIC, None), (_rs.SEARCH, "TEMPLATE", _rs.IN_TEMPLATE, None), (_rs.SEARCH, "VTABLE", _rs.IN_VTABLE, None), + (_rs.SEARCH, "LIBRARY", _rs.IN_LIBRARY, None), + (_rs.SEARCH, "STRING", _rs.SEARCH, None), (_rs.WANT_SIG, "FUNCTION", _rs.WANT_SIG, None), (_rs.WANT_SIG, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -21,20 +23,26 @@ (_rs.WANT_SIG, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.WANT_SIG, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.WANT_SIG, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.WANT_SIG, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.WANT_SIG, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC, "FUNCTION", _rs.WANT_SIG, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "GLOBAL", _rs.IN_FUNC_GLOBAL, None), (_rs.IN_FUNC, "STUB", _rs.WANT_SIG, _pe.MISSED_END_OF_FUNCTION), - (_rs.IN_FUNC, "SYNTHETIC", _rs.IN_TEMPLATE, _pe.MISSED_END_OF_FUNCTION), + (_rs.IN_FUNC, "SYNTHETIC", _rs.IN_SYNTHETIC, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "TEMPLATE", _rs.IN_TEMPLATE, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "VTABLE", _rs.IN_VTABLE, _pe.MISSED_END_OF_FUNCTION), + (_rs.IN_FUNC, "LIBRARY", _rs.IN_LIBRARY, _pe.MISSED_END_OF_FUNCTION), + (_rs.IN_FUNC, "STRING", _rs.IN_FUNC, None), (_rs.IN_TEMPLATE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "STUB", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), - (_rs.IN_TEMPLATE, "SYNTHETIC", _rs.IN_TEMPLATE, None), + (_rs.IN_TEMPLATE, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "TEMPLATE", _rs.IN_TEMPLATE, None), (_rs.IN_TEMPLATE, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_TEMPLATE, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_TEMPLATE, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.WANT_CURLY, "FUNCTION", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.WANT_CURLY, "GLOBAL", _rs.SEARCH, _pe.UNEXPECTED_MARKER), @@ -42,6 +50,8 @@ (_rs.WANT_CURLY, "SYNTHETIC", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.WANT_CURLY, "TEMPLATE", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.WANT_CURLY, "VTABLE", _rs.SEARCH, _pe.UNEXPECTED_MARKER), + (_rs.WANT_CURLY, "LIBRARY", _rs.SEARCH, _pe.UNEXPECTED_MARKER), + (_rs.WANT_CURLY, "STRING", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.IN_GLOBAL, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "GLOBAL", _rs.IN_GLOBAL, None), @@ -49,6 +59,8 @@ (_rs.IN_GLOBAL, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_GLOBAL, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_GLOBAL, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "GLOBAL", _rs.IN_FUNC_GLOBAL, None), @@ -56,6 +68,8 @@ (_rs.IN_FUNC_GLOBAL, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_FUNC_GLOBAL, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_FUNC_GLOBAL, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -63,6 +77,26 @@ (_rs.IN_VTABLE, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "VTABLE", _rs.IN_VTABLE, None), + (_rs.IN_VTABLE, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_VTABLE, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + + (_rs.IN_SYNTHETIC, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "STUB", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "SYNTHETIC", _rs.IN_SYNTHETIC, None), + (_rs.IN_SYNTHETIC, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + + (_rs.IN_LIBRARY, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "STUB", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "LIBRARY", _rs.IN_LIBRARY, None), + (_rs.IN_LIBRARY, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), ] # fmt: on @@ -105,47 +139,3 @@ def test_state_search_line(line: str): p.read_line(line) assert p.state == _rs.SEARCH assert len(p.alerts) == 0 - - -global_lines = [ - ("// A comment", _rs.IN_GLOBAL), - ("", _rs.IN_GLOBAL), - ("\t", _rs.IN_GLOBAL), - (" ", _rs.IN_GLOBAL), - # TODO: no check for "likely" variable declaration so these all count - ("void function()", _rs.SEARCH), - ("int x = 123;", _rs.SEARCH), - ("just some text", _rs.SEARCH), -] - - -@pytest.mark.parametrize("line, new_state", global_lines) -def test_state_global_line(line: str, new_state: _rs): - p = DecompParser() - p.read_line("// GLOBAL: TEST 0x1234") - assert p.state == _rs.IN_GLOBAL - p.read_line(line) - assert p.state == new_state - - -# mostly same as above -in_func_global_lines = [ - ("// A comment", _rs.IN_FUNC_GLOBAL), - ("", _rs.IN_FUNC_GLOBAL), - ("\t", _rs.IN_FUNC_GLOBAL), - (" ", _rs.IN_FUNC_GLOBAL), - # TODO: no check for "likely" variable declaration so these all count - ("void function()", _rs.IN_FUNC), - ("int x = 123;", _rs.IN_FUNC), - ("just some text", _rs.IN_FUNC), -] - - -@pytest.mark.parametrize("line, new_state", in_func_global_lines) -def test_state_in_func_global_line(line: str, new_state: _rs): - p = DecompParser() - p.state = _rs.IN_FUNC - p.read_line("// GLOBAL: TEST 0x1234") - assert p.state == _rs.IN_FUNC_GLOBAL - p.read_line(line) - assert p.state == new_state diff --git a/tools/isledecomp/tests/test_parser_util.py b/tools/isledecomp/tests/test_parser_util.py index 643abf3e..af102fc2 100644 --- a/tools/isledecomp/tests/test_parser_util.py +++ b/tools/isledecomp/tests/test_parser_util.py @@ -1,11 +1,15 @@ import pytest from isledecomp.parser.parser import MarkerDict -from isledecomp.parser.util import ( +from isledecomp.parser.marker import ( DecompMarker, - is_blank_or_comment, + MarkerType, match_marker, is_marker_exact, +) +from isledecomp.parser.util import ( + is_blank_or_comment, get_class_name, + get_variable_name, ) @@ -96,7 +100,7 @@ def test_marker_dict_type_replace(): d.insert(DecompMarker("STUB", "TEST", 0x1234)) markers = list(d.iter()) assert len(markers) == 1 - assert markers[0].type == "FUNCTION" + assert markers[0].type == MarkerType.FUNCTION class_name_match_cases = [ @@ -131,3 +135,26 @@ def test_get_class_name(line: str, class_name: str): @pytest.mark.parametrize("line", class_name_no_match_cases) def test_get_class_name_none(line: str): assert get_class_name(line) is None + + +variable_name_cases = [ + # with prefix for easy access + ("char* g_test;", "g_test"), + ("g_test;", "g_test"), + ("void (*g_test)(int);", "g_test"), + ("char g_test[50];", "g_test"), + ("char g_test[50] = {1234,", "g_test"), + ("int g_test = 500;", "g_test"), + # no prefix + ("char* hello;", "hello"), + ("hello;", "hello"), + ("void (*hello)(int);", "hello"), + ("char hello[50];", "hello"), + ("char hello[50] = {1234,", "hello"), + ("int hello = 500;", "hello"), +] + + +@pytest.mark.parametrize("line,name", variable_name_cases) +def test_get_variable_name(line: str, name: str): + assert get_variable_name(line) == name diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index 913154f5..c7db5e2c 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -316,7 +316,7 @@ def main(): parser.read_lines(srcfile) for fun in parser.functions: - if fun.is_stub: + if fun.should_skip(): continue if fun.module != basename: @@ -330,7 +330,7 @@ def main(): else: continue - if fun.lookup_by_name: + if fun.is_nameref(): recinfo = syminfo.get_recompiled_address_from_name(fun.name) if not recinfo: continue From 4d7968c7af4df3d672ee0d776b04493c6b323529 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Wed, 27 Dec 2023 16:05:21 -0500 Subject: [PATCH 30/50] implement LegoWorldPresenter::StartingTickle (#378) --- LEGO1/legovideomanager.cpp | 2 +- LEGO1/legoworldpresenter.cpp | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/LEGO1/legovideomanager.cpp b/LEGO1/legovideomanager.cpp index 098bbe6e..456b10f5 100644 --- a/LEGO1/legovideomanager.cpp +++ b/LEGO1/legovideomanager.cpp @@ -80,7 +80,7 @@ void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY) MxResult LegoVideoManager::Tickle() { // TODO - return FAILURE; + return MxVideoManager::Tickle(); } // STUB: LEGO1 0x1007c080 diff --git a/LEGO1/legoworldpresenter.cpp b/LEGO1/legoworldpresenter.cpp index 7a17ad7a..02578675 100644 --- a/LEGO1/legoworldpresenter.cpp +++ b/LEGO1/legoworldpresenter.cpp @@ -99,9 +99,25 @@ void LegoWorldPresenter::ReadyTickle() m_currentTickleState = TickleState_Starting; } -// STUB: LEGO1 0x10066ac0 +// FUNCTION: LEGO1 0x10066ac0 void LegoWorldPresenter::StartingTickle() { + if (m_action->IsA("MxDSSerialAction")) { + MxPresenter* presenter = *m_list.begin(); + if (presenter->GetCurrentTickleState() == TickleState_Idle) { + presenter->SetTickleState(TickleState_Ready); + } + } + else { + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { + if ((*it)->GetCurrentTickleState() == TickleState_Idle) { + (*it)->SetTickleState(TickleState_Ready); + } + } + } + + m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; + m_currentTickleState = TickleState_Streaming; } // STUB: LEGO1 0x10067a70 From e3488498f95385416a070071ba3c800a5717fbe3 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 28 Dec 2023 11:19:40 -0500 Subject: [PATCH 31/50] Implement/match MxDiskStreamController destructor (#379) --- LEGO1/mxdiskstreamcontroller.cpp | 47 ++++++++++++++++++++++++++------ LEGO1/mxdiskstreamcontroller.h | 2 +- LEGO1/mxramstreamcontroller.cpp | 6 ++-- LEGO1/mxstreamcontroller.cpp | 14 +++++----- 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/LEGO1/mxdiskstreamcontroller.cpp b/LEGO1/mxdiskstreamcontroller.cpp index 1520ba3b..f992443d 100644 --- a/LEGO1/mxdiskstreamcontroller.cpp +++ b/LEGO1/mxdiskstreamcontroller.cpp @@ -15,10 +15,41 @@ MxDiskStreamController::MxDiskStreamController() m_unk0x8c = 0; } -// STUB: LEGO1 0x100c7530 +// FUNCTION: LEGO1 0x100c7530 MxDiskStreamController::~MxDiskStreamController() { - // TODO + MxAutoLocker lock(&this->m_criticalSection); + + m_unk0xc4 = FALSE; + m_unk0x70 = FALSE; + + if (m_provider) + m_provider->VTable0x20(&MxDSAction()); + + MxDSAction* action; + while (m_unk0x3c.PopFront(action)) + delete action; + + if (m_provider) { + delete m_provider; + m_provider = NULL; + } + + FUN_100c8720(); + + while (m_list0x80.PopFront(action)) + FUN_100c7cb0((MxDSStreamingAction*) action); + + while (m_list0x64.PopFront(action)) + FUN_100c7cb0((MxDSStreamingAction*) action); + + while (!m_list0x74.empty()) { + MxDSBuffer* buffer = m_list0x74.front(); + m_list0x74.pop_front(); + FUN_100c7ce0(buffer); + } + + TickleManager()->UnregisterClient(this); } // FUNCTION: LEGO1 0x100c7790 @@ -257,8 +288,8 @@ MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) else if (MxStreamController::VTable0x20(p_action) != SUCCESS) return FAILURE; - m_unk0x70 = 1; - m_unk0xc4 = 1; + m_unk0x70 = TRUE; + m_unk0xc4 = TRUE; return SUCCESS; } @@ -289,9 +320,9 @@ MxResult MxDiskStreamController::VTable0x24(MxDSAction* p_action) MxStreamController::VTable0x24(&action); } while (m_action0x60 != NULL); - if (m_unk0x3c.size() == 0) { - m_unk0x70 = 0; - m_unk0xc4 = 0; + if (m_unk0x3c.empty()) { + m_unk0x70 = FALSE; + m_unk0xc4 = FALSE; } return SUCCESS; @@ -389,7 +420,7 @@ void MxDiskStreamController::FUN_100c8720() MxAutoLocker lock(&this->m_critical9c); MxDSStreamingAction* action; - while (m_list0xb8.size() != 0) { + while (!m_list0xb8.empty()) { action = (MxDSStreamingAction*) m_list0xb8.front(); m_list0xb8.pop_front(); diff --git a/LEGO1/mxdiskstreamcontroller.h b/LEGO1/mxdiskstreamcontroller.h index 52032675..bc5cce61 100644 --- a/LEGO1/mxdiskstreamcontroller.h +++ b/LEGO1/mxdiskstreamcontroller.h @@ -49,7 +49,7 @@ class MxDiskStreamController : public MxStreamController { private: MxStreamListMxDSAction m_list0x64; // 0x64 - undefined m_unk0x70; // 0x70 + MxBool m_unk0x70; // 0x70 list m_list0x74; // 0x74 MxStreamListMxDSAction m_list0x80; // 0x80 undefined2 m_unk0x8c; // 0x8c diff --git a/LEGO1/mxramstreamcontroller.cpp b/LEGO1/mxramstreamcontroller.cpp index 0a5e29cd..71ee1b92 100644 --- a/LEGO1/mxramstreamcontroller.cpp +++ b/LEGO1/mxramstreamcontroller.cpp @@ -11,7 +11,7 @@ undefined* __cdecl ReadData(MxU32* p_fileSizeBuffer, MxU32 p_fileSize); // FUNCTION: LEGO1 0x100c6110 MxResult MxRAMStreamController::Open(const char* p_filename) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); if (MxStreamController::Open(p_filename) != SUCCESS) { return FAILURE; } @@ -39,7 +39,7 @@ MxResult MxRAMStreamController::Open(const char* p_filename) // FUNCTION: LEGO1 0x100c6210 MxResult MxRAMStreamController::VTable0x20(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxS32 unk0x24 = 0; MxResult result = FAILURE; @@ -83,7 +83,7 @@ MxResult MxRAMStreamController::VTable0x24(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c63c0 MxResult MxRAMStreamController::DeserializeObject(MxDSStreamingAction& p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxResult result; MxDSStreamingAction* value = NULL; diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp index e45435ac..f351582a 100644 --- a/LEGO1/mxstreamcontroller.cpp +++ b/LEGO1/mxstreamcontroller.cpp @@ -72,7 +72,7 @@ MxStreamController::~MxStreamController() MxResult MxStreamController::Open(const char* p_filename) { char sourceName[256]; - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MakeSourceName(sourceName, p_filename); this->m_atom = MxAtomId(sourceName, LookupMode_LowerCase2); @@ -94,7 +94,7 @@ void MxStreamController::RemoveSubscriber(MxDSSubscriber* p_subscriber) // FUNCTION: LEGO1 0x100c1690 MxResult MxStreamController::VTable0x20(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxResult result; MxU32 offset = 0; @@ -116,7 +116,7 @@ MxResult MxStreamController::VTable0x20(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c1740 MxResult MxStreamController::VTable0x24(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); VTable0x30(p_action); m_action0x60 = m_unk0x54.Find(p_action, TRUE); if (m_action0x60 == NULL) { @@ -201,7 +201,7 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) // FUNCTION: LEGO1 0x100c1c10 MxResult MxStreamController::VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); if (FUN_100c1a00(p_action, p_bufferval) != SUCCESS) { return FAILURE; } @@ -211,7 +211,7 @@ MxResult MxStreamController::VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval) // FUNCTION: LEGO1 0x100c1ce0 MxResult MxStreamController::VTable0x30(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxResult result = FAILURE; MxDSAction* action = m_unk0x3c.Find(p_action, TRUE); if (action != NULL) { @@ -226,7 +226,7 @@ MxResult MxStreamController::VTable0x30(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c1da0 MxResult MxStreamController::InsertActionToList54(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxDSAction* action = p_action->Clone(); if (action == NULL) { @@ -241,7 +241,7 @@ MxResult MxStreamController::InsertActionToList54(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c1e70 MxPresenter* MxStreamController::FUN_100c1e70(MxDSAction& p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxPresenter* result = NULL; if (p_action.GetObjectId() != -1) { MxDSAction* action = m_unk0x3c.Find(&p_action, FALSE); From e17e8ed5aece899962ec784119b5e2e474e28410 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 28 Dec 2023 11:46:12 -0500 Subject: [PATCH 32/50] Implement/match MxDiskStreamProvider destructor (#381) --- LEGO1/mxdiskstreamprovider.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/LEGO1/mxdiskstreamprovider.cpp b/LEGO1/mxdiskstreamprovider.cpp index badc1623..b9ed63d0 100644 --- a/LEGO1/mxdiskstreamprovider.cpp +++ b/LEGO1/mxdiskstreamprovider.cpp @@ -40,10 +40,39 @@ MxDiskStreamProvider::MxDiskStreamProvider() this->m_unk0x35 = FALSE; } -// STUB: LEGO1 0x100d1240 +// FUNCTION: LEGO1 0x100d1240 MxDiskStreamProvider::~MxDiskStreamProvider() { - // TODO + MxDSStreamingAction* action; + m_unk0x35 = FALSE; + + do { + action = NULL; + + { + MxAutoLocker lock(&m_criticalSection); + m_list.PopFrontStreamingAction(action); + } + + if (!action) + break; + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) + g_unk0x10102878--; + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action); + + if (m_remainingWork) { + m_remainingWork = FALSE; + m_busySemaphore.Release(1); + m_thread.Terminate(); + } + + if (m_pFile) + delete m_pFile; + + m_pFile = NULL; } // FUNCTION: LEGO1 0x100d13d0 From e76cf3427c54cd416d337de584ed5a71f7a82caf Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 28 Dec 2023 11:56:54 -0500 Subject: [PATCH 33/50] Add and fix some annotations --- LEGO1/legoact2.h | 2 +- LEGO1/legoomni.h | 2 +- LEGO1/legoracecar.h | 2 +- LEGO1/mxatomidcounter.h | 2 +- LEGO1/mxdiskstreamcontroller.h | 3 +++ LEGO1/mxdiskstreamprovider.h | 3 +++ LEGO1/mxramstreamcontroller.h | 5 ++++- LEGO1/mxramstreamprovider.h | 14 +++++++++----- LEGO1/mxstreamcontroller.h | 3 +++ LEGO1/mxstreamer.h | 3 +++ LEGO1/mxstreamprovider.h | 3 +++ 11 files changed, 32 insertions(+), 10 deletions(-) diff --git a/LEGO1/legoact2.h b/LEGO1/legoact2.h index b504c11c..79983416 100644 --- a/LEGO1/legoact2.h +++ b/LEGO1/legoact2.h @@ -5,7 +5,7 @@ #include "legopathactor.h" // VTABLE: LEGO1 0x100d82e0 -// SIZE: 0x1154 +// SIZE 0x1154 class LegoAct2 : public LegoWorld {}; #endif // LEGOACT2_H diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index f0ac8369..7fb0a4f3 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -59,7 +59,7 @@ extern MxAtomId* g_creditsScript; extern MxAtomId* g_nocdSourceName; // VTABLE: LEGO1 0x100d8638 -// SIZE: 0x140 +// SIZE 0x140 class LegoOmni : public MxOmni { public: __declspec(dllexport) void CreateBackgroundAudio(); diff --git a/LEGO1/legoracecar.h b/LEGO1/legoracecar.h index d3800b5a..a2a54afb 100644 --- a/LEGO1/legoracecar.h +++ b/LEGO1/legoracecar.h @@ -5,7 +5,7 @@ #include "legopathactor.h" // VTABLE: LEGO1 0x100d58b8 -// SIZE: 0x200 +// SIZE 0x200 class LegoRaceCar : public LegoCarRaceActor { public: // FUNCTION: LEGO1 0x10014290 diff --git a/LEGO1/mxatomidcounter.h b/LEGO1/mxatomidcounter.h index 8fb5ae97..f2c4fb3f 100644 --- a/LEGO1/mxatomidcounter.h +++ b/LEGO1/mxatomidcounter.h @@ -13,7 +13,7 @@ // Also: the increment/decrement methods suggest a custom type was used // for the combined key_value_pair, which doesn't seem possible with . -// SIZE: 0x14 (including padding) +// SIZE 0x14 class MxAtomIdCounter { public: // always inlined diff --git a/LEGO1/mxdiskstreamcontroller.h b/LEGO1/mxdiskstreamcontroller.h index bc5cce61..01ddc78a 100644 --- a/LEGO1/mxdiskstreamcontroller.h +++ b/LEGO1/mxdiskstreamcontroller.h @@ -78,6 +78,9 @@ class MxDiskStreamController : public MxStreamController { // TEMPLATE: LEGO1 0x100c7490 // list >::_Buynode +// SYNTHETIC: LEGO1 0x100c74c0 +// MxDiskStreamController::`scalar deleting destructor' + // TEMPLATE: LEGO1 0x100c74e0 // List::~List diff --git a/LEGO1/mxdiskstreamprovider.h b/LEGO1/mxdiskstreamprovider.h index 1314e3f9..2557eaf9 100644 --- a/LEGO1/mxdiskstreamprovider.h +++ b/LEGO1/mxdiskstreamprovider.h @@ -64,4 +64,7 @@ class MxDiskStreamProvider : public MxStreamProvider { MxStreamListMxDSAction m_list; // 0x54 }; +// SYNTHETIC: LEGO1 0x100d1220 +// MxDiskStreamProvider::`scalar deleting destructor' + #endif // MXDISKSTREAMPROVIDER_H diff --git a/LEGO1/mxramstreamcontroller.h b/LEGO1/mxramstreamcontroller.h index aa70ec33..6b56ee49 100644 --- a/LEGO1/mxramstreamcontroller.h +++ b/LEGO1/mxramstreamcontroller.h @@ -30,9 +30,12 @@ class MxRAMStreamController : public MxStreamController { virtual MxResult VTable0x24(MxDSAction* p_action) override; private: - MxDSBuffer m_buffer; + MxDSBuffer m_buffer; // 0x64 MxResult DeserializeObject(MxDSStreamingAction& p_action); }; +// SYNTHETIC: LEGO1 0x100b94f0 +// MxRAMStreamController::`scalar deleting destructor' + #endif // MXRAMSTREAMCONTROLLER_H diff --git a/LEGO1/mxramstreamprovider.h b/LEGO1/mxramstreamprovider.h index 16ed5a4c..5c8bf59c 100644 --- a/LEGO1/mxramstreamprovider.h +++ b/LEGO1/mxramstreamprovider.h @@ -4,6 +4,7 @@ #include "mxstreamprovider.h" // VTABLE: LEGO1 0x100dd0d0 +// SIZE 0x24 class MxRAMStreamProvider : public MxStreamProvider { public: MxRAMStreamProvider(); @@ -31,11 +32,14 @@ class MxRAMStreamProvider : public MxStreamProvider { inline MxU32* GetBufferOfFileSize() { return m_pBufferOfFileSize; } protected: - MxU32 m_bufferSize; - MxU32 m_fileSize; - MxU32* m_pBufferOfFileSize; - MxU32 m_lengthInDWords; - MxU32* m_bufferForDWords; + MxU32 m_bufferSize; // 0x10 + MxU32 m_fileSize; // 0x14 + MxU32* m_pBufferOfFileSize; // 0x18 + MxU32 m_lengthInDWords; // 0x1c + MxU32* m_bufferForDWords; // 0x20 }; +// SYNTHETIC: LEGO1 0x100d0a30 +// MxRAMStreamProvider::`scalar deleting destructor' + #endif // MXRAMSTREAMPROVIDER_H diff --git a/LEGO1/mxstreamcontroller.h b/LEGO1/mxstreamcontroller.h index bbd1eb3d..790856c1 100644 --- a/LEGO1/mxstreamcontroller.h +++ b/LEGO1/mxstreamcontroller.h @@ -88,6 +88,9 @@ class MxStreamController : public MxCore { // TEMPLATE: LEGO1 0x100c0ee0 // list >::_Buynode +// SYNTHETIC: LEGO1 0x100c0fa0 +// MxStreamController::`scalar deleting destructor' + // FUNCTION: LEGO1 0x100c0fc0 // MxStreamListMxDSSubscriber::~MxStreamListMxDSSubscriber diff --git a/LEGO1/mxstreamer.h b/LEGO1/mxstreamer.h index 4d3684e9..e76f0e36 100644 --- a/LEGO1/mxstreamer.h +++ b/LEGO1/mxstreamer.h @@ -105,4 +105,7 @@ class MxStreamer : public MxCore { MxStreamerSubClass3 m_subclass2; // 0x20 }; +// SYNTHETIC: LEGO1 0x100b9120 +// MxStreamer::`scalar deleting destructor' + #endif // MXSTREAMER_H diff --git a/LEGO1/mxstreamprovider.h b/LEGO1/mxstreamprovider.h index 73804684..17bba38d 100644 --- a/LEGO1/mxstreamprovider.h +++ b/LEGO1/mxstreamprovider.h @@ -38,4 +38,7 @@ class MxStreamProvider : public MxCore { MxDSFile* m_pFile; // 0x0c }; +// SYNTHETIC: LEGO1 0x100d0870 +// MxStreamProvider::`scalar deleting destructor' + #endif // MXSTREAMPROVIDER_H From a06a360dc6509f1e4c4caa5407c2b3263f4a11da Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Thu, 28 Dec 2023 12:38:37 -0500 Subject: [PATCH 34/50] Implement Lego3DManager (#380) * Implement Lego3DManager * Update lego3dview.cpp * fix * fixes * fix wrong vtable address * Fixes/matches * Fix Lego3DView * Use undefined * More fixes * Rename * Rename pad * Add blank line * Delete stuff --------- Co-authored-by: Christian Semmler --- CMakeLists.txt | 2 ++ LEGO1/lego3dmanager.cpp | 46 +++++++++++++++++++++++++++++++++++++ LEGO1/lego3dmanager.h | 19 ++++++++++++--- LEGO1/lego3dview.cpp | 19 +++++++++++++++ LEGO1/lego3dview.h | 21 +++++++++++++---- LEGO1/mxrendersettings.cpp | 21 +++++++++++++++++ LEGO1/mxrendersettings.h | 28 ++++++++++++++++++++++ LEGO1/mxunknown100dbdbc.cpp | 6 +++++ LEGO1/mxunknown100dbdbc.h | 3 ++- 9 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 LEGO1/lego3dmanager.cpp create mode 100644 LEGO1/mxrendersettings.cpp create mode 100644 LEGO1/mxrendersettings.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3650c718..cdf37ff1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ add_library(lego1 SHARED LEGO1/jukebox.cpp LEGO1/jukeboxentity.cpp LEGO1/jukeboxstate.cpp + LEGO1/lego3dmanager.cpp LEGO1/lego3dview.cpp LEGO1/legoact2state.cpp LEGO1/legoactioncontrolpresenter.cpp @@ -161,6 +162,7 @@ add_library(lego1 SHARED LEGO1/mxramstreamcontroller.cpp LEGO1/mxramstreamprovider.cpp LEGO1/mxregion.cpp + LEGO1/mxrendersettings.cpp LEGO1/mxscheduler.cpp LEGO1/mxsemaphore.cpp LEGO1/mxsmack.cpp diff --git a/LEGO1/lego3dmanager.cpp b/LEGO1/lego3dmanager.cpp new file mode 100644 index 00000000..c399b1a8 --- /dev/null +++ b/LEGO1/lego3dmanager.cpp @@ -0,0 +1,46 @@ +#include "lego3dmanager.h" + +#include "decomp.h" +#include "mxrendersettings.h" +#include "mxunknown100dbdbc.h" +#include "tgl/tgl.h" + +DECOMP_SIZE_ASSERT(Lego3DManager, 0x10); + +// FUNCTION: LEGO1 0x100ab320 +Lego3DManager::Lego3DManager() +{ + m_render = NULL; + m_3dView = NULL; + m_unk0x0c = NULL; +} + +// FUNCTION: LEGO1 0x100ab360 +Lego3DManager::~Lego3DManager() +{ + Destroy(); +} + +// FUNCTION: LEGO1 0x100ab370 +void Lego3DManager::Init(MxRenderSettings& p_settings) +{ + m_unk0x0c = new MxUnknown100dbdbc(); + m_render = Tgl::CreateRenderer(); + m_3dView = new Lego3DView(); + + MxRenderSettings settings; + MxRenderSettings::CopyFrom(settings, p_settings); + + m_3dView->Init(settings, *m_render); +} + +// FUNCTION: LEGO1 0x100ab460 +void Lego3DManager::Destroy() +{ + delete m_3dView; + m_3dView = NULL; + delete m_render; + m_render = NULL; + delete m_unk0x0c; + m_unk0x0c = NULL; +} diff --git a/LEGO1/lego3dmanager.h b/LEGO1/lego3dmanager.h index 3e1cf202..78c532a5 100644 --- a/LEGO1/lego3dmanager.h +++ b/LEGO1/lego3dmanager.h @@ -3,14 +3,27 @@ #include "lego3dview.h" +class MxUnknown100dbdbc; + +// VTABLE: LEGO1 0x100dbfa4 +// SIZE 0x10 class Lego3DManager { public: + Lego3DManager(); + virtual ~Lego3DManager(); + inline Lego3DView* GetLego3DView() { return this->m_3dView; } private: - undefined4 m_unk0x00; // 0x00 - undefined4 m_unk0x04; // 0x04 - Lego3DView* m_3dView; // 0x08 + Tgl::Renderer* m_render; // 0x04 + Lego3DView* m_3dView; // 0x08 + MxUnknown100dbdbc* m_unk0x0c; // 0x0c + + void Init(MxRenderSettings& p_settings); + void Destroy(); }; +// SYNTHETIC: LEGO1 0x100ab340 +// Lego3DManager::`scalar deleting destructor' + #endif // LEGO3DMANAGER_H diff --git a/LEGO1/lego3dview.cpp b/LEGO1/lego3dview.cpp index 0bb384e8..096e7b9e 100644 --- a/LEGO1/lego3dview.cpp +++ b/LEGO1/lego3dview.cpp @@ -1,6 +1,25 @@ #include "lego3dview.h" #include "legoroi.h" +#include "tgl/tgl.h" + +DECOMP_SIZE_ASSERT(Lego3DView, 0xa8) + +// STUB: LEGO1 0x100aae90 +Lego3DView::Lego3DView() +{ +} + +// STUB: LEGO1 0x100aaf30 +Lego3DView::~Lego3DView() +{ +} + +// STUB: LEGO1 0x100aaf90 +MxBool Lego3DView::Init(MxRenderSettings& p_renderSettings, Tgl::Renderer& p_render) +{ + return FALSE; +} // STUB: LEGO1 0x100ab2b0 LegoROI* Lego3DView::PickROI(MxLong p_a, MxLong p_b) diff --git a/LEGO1/lego3dview.h b/LEGO1/lego3dview.h index b984ad0f..0681003f 100644 --- a/LEGO1/lego3dview.h +++ b/LEGO1/lego3dview.h @@ -1,27 +1,38 @@ #ifndef LEGO3DVIEW_H #define LEGO3DVIEW_H +#include "mxrendersettings.h" #include "mxtypes.h" #include "tgl/d3drm/impl.h" #include "viewmanager/viewmanager.h" class LegoROI; +class Tgl::Renderer; +// VTABLE: LEGO1 0x100dbf78 +// SIZE 0xa8 class Lego3DView { public: + Lego3DView(); + virtual ~Lego3DView(); + inline ViewManager* GetViewManager() { return this->m_viewManager; } inline TglImpl::ViewImpl* GetViewPort() { return this->m_viewPort; } + MxBool Init(MxRenderSettings& p_renderSettings, Tgl::Renderer& p_render); LegoROI* PickROI(MxLong p_a, MxLong p_b); private: // TODO: all of these fields are in various base classes - undefined4 m_vtable; // 0x0 (TODO: remove once virtual function added) - undefined4 m_unk0x4; // 0x4 - TglImpl::RendererImpl* m_renderImpl; // 0x8 - TglImpl::DeviceImpl* m_deviceImpl; // 0xc + undefined4 m_unk0x4; // 0x04 + TglImpl::RendererImpl* m_renderImpl; // 0x08 + TglImpl::DeviceImpl* m_deviceImpl; // 0x0c TglImpl::ViewImpl* m_viewPort; // 0x10 - char m_pad[0x78]; // 0x14 + undefined m_unk0x14[0x74]; // 0x14 ViewManager* m_viewManager; // 0x88 + undefined m_unk0x8c[0x1c]; // 0x8c }; +// SYNTHETIC: LEGO1 0x100aaf10 +// Lego3DView::`scalar deleting destructor' + #endif // LEGO3DVIEW_H diff --git a/LEGO1/mxrendersettings.cpp b/LEGO1/mxrendersettings.cpp new file mode 100644 index 00000000..4d4476ec --- /dev/null +++ b/LEGO1/mxrendersettings.cpp @@ -0,0 +1,21 @@ +#include "mxrendersettings.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxRenderSettings, 0x28) + +// FUNCTION: LEGO1 0x100ab2d0 +MxU32 MxRenderSettings::CopyFrom(MxRenderSettings& p_dest, const MxRenderSettings& p_src) +{ + p_dest.m_unk0x00 = p_src.m_unk0x00; + p_dest.m_hwnd = p_src.m_hwnd; + p_dest.m_directDraw = p_src.m_directDraw; + p_dest.m_ddSurface1 = p_src.m_ddSurface1; + p_dest.m_ddSurface2 = p_src.m_ddSurface2; + p_dest.m_flags = p_src.m_flags; + p_dest.m_unk0x18 = p_src.m_unk0x18; + p_dest.m_flags2 = p_src.m_flags2; + p_dest.m_direct3d = p_src.m_direct3d; + p_dest.m_d3dDevice = p_src.m_d3dDevice; + return 1; +} diff --git a/LEGO1/mxrendersettings.h b/LEGO1/mxrendersettings.h new file mode 100644 index 00000000..14909ade --- /dev/null +++ b/LEGO1/mxrendersettings.h @@ -0,0 +1,28 @@ +#ifndef MXRENDERSETTINGS_H +#define MXRENDERSETTINGS_H + +#include "decomp.h" +#include "mxtypes.h" + +#include +#include +#include + +// SIZE 0x28 +struct MxRenderSettings { +public: + static MxU32 CopyFrom(MxRenderSettings& p_dest, const MxRenderSettings& p_src); + + undefined4 m_unk0x00; // 0x00 + HWND m_hwnd; // 0x04 + IDirectDraw* m_directDraw; // 0x08 + IDirectDrawSurface* m_ddSurface1; // 0x0c + IDirectDrawSurface* m_ddSurface2; // 0x10 + MxU32 m_flags; // 0x14 + undefined4 m_unk0x18; // 0x18 + MxU32 m_flags2; // 0x1c + IDirect3D* m_direct3d; // 0x20 + IDirect3DDevice* m_d3dDevice; // 0x24 +}; + +#endif // MXRENDERSETTINGS_H diff --git a/LEGO1/mxunknown100dbdbc.cpp b/LEGO1/mxunknown100dbdbc.cpp index a420454a..64254f0b 100644 --- a/LEGO1/mxunknown100dbdbc.cpp +++ b/LEGO1/mxunknown100dbdbc.cpp @@ -9,3 +9,9 @@ MxUnknown100dbdbc::MxUnknown100dbdbc() { // TODO } + +// STUB: LEGO1 0x100a7130 +MxUnknown100dbdbc::~MxUnknown100dbdbc() +{ + // TODO +} diff --git a/LEGO1/mxunknown100dbdbc.h b/LEGO1/mxunknown100dbdbc.h index 157058a7..b5049760 100644 --- a/LEGO1/mxunknown100dbdbc.h +++ b/LEGO1/mxunknown100dbdbc.h @@ -9,9 +9,10 @@ class MxUnknown100dbdbc { public: MxUnknown100dbdbc(); + virtual ~MxUnknown100dbdbc(); private: - undefined m_unk0x4[0x14]; // TODO: change to 0x10 once scalar deconstructor is added + undefined m_unk0x4[0x10]; }; #endif // MXUNKNOWN100DBDBC_H From ff4845a6ea7bdef4712b8f52dc2a35d883270e8c Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Thu, 28 Dec 2023 13:55:03 -0500 Subject: [PATCH 35/50] MxLoopingFlcPresenter::Destroy (#382) * MxLoopingFlcPresenter::Destroy * Use parent class call --------- Co-authored-by: Christian Semmler --- LEGO1/mxloopingflcpresenter.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/LEGO1/mxloopingflcpresenter.cpp b/LEGO1/mxloopingflcpresenter.cpp index cb4fd40b..03b14a5a 100644 --- a/LEGO1/mxloopingflcpresenter.cpp +++ b/LEGO1/mxloopingflcpresenter.cpp @@ -24,10 +24,15 @@ void MxLoopingFlcPresenter::Init() this->m_flags &= ~Flag_Bit3; } -// STUB: LEGO1 0x100b4432 +// FUNCTION: LEGO1 0x100b4430 void MxLoopingFlcPresenter::Destroy(MxBool p_fromDestructor) { - // TODO + m_criticalSection.Enter(); + Init(); + m_criticalSection.Leave(); + + if (!p_fromDestructor) + MxFlcPresenter::Destroy(FALSE); } // FUNCTION: LEGO1 0x100b4470 From 9a6d5555080caac014846dabd6b03f30604ddc4f Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 28 Dec 2023 16:10:57 -0500 Subject: [PATCH 36/50] Cvdump parser and comparing library functions (#383) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Cvdump wrapper and parser. Matching library functions * Remove 'Self' type int (3.11+) * Add temp reference for entrypoints * ISLE using multithreaded libc * 🙄 --- CMakeLists.txt | 2 +- LEGO1/library_msvc.h | 47 +++++ tools/isledecomp/isledecomp/bin.py | 117 ++++++++----- .../isledecomp/isledecomp/cvdump/__init__.py | 2 + tools/isledecomp/isledecomp/cvdump/parser.py | 163 ++++++++++++++++++ tools/isledecomp/isledecomp/cvdump/runner.py | 66 +++++++ tools/isledecomp/isledecomp/syminfo.py | 115 +++++------- 7 files changed, 395 insertions(+), 117 deletions(-) create mode 100644 LEGO1/library_msvc.h create mode 100644 tools/isledecomp/isledecomp/cvdump/__init__.py create mode 100644 tools/isledecomp/isledecomp/cvdump/parser.py create mode 100644 tools/isledecomp/isledecomp/cvdump/runner.py diff --git a/CMakeLists.txt b/CMakeLists.txt index cdf37ff1..b4676767 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,7 +294,7 @@ if (MSVC) # game was originally built with) and tweaked slightly to produce more debugging info for reccmp. # They ensure a recompilation that can be byte/instruction accurate to the original binaries. if (ISLE_BUILD_APP) - target_compile_options(isle PRIVATE "/ML$<$:d>") + target_compile_options(isle PRIVATE "/MT$<$:d>") endif() target_compile_options(lego1 PRIVATE "/MT$<$:d>") diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h new file mode 100644 index 00000000..d07ecef2 --- /dev/null +++ b/LEGO1/library_msvc.h @@ -0,0 +1,47 @@ +#ifdef 0 + +// LIBRARY: ISLE 0x402f80 +// LIBRARY: LEGO1 0x10086240 +// _malloc + +// LIBRARY: ISLE 0x402fa0 +// LIBRARY: LEGO1 0x10086260 +// _free + +// LIBRARY: ISLE 0x408220 +// LIBRARY: LEGO1 0x1008b400 +// _atol + +// LIBRARY: ISLE 0x4082d0 +// LIBRARY: LEGO1 0x1008b4b0 +// _atoi + +// LIBRARY: LEGO1 0x1008b4c0 +// _strtok + +// LIBRARY: ISLE 0x4085c0 +// LIBRARY: LEGO1 0x1008b5a0 +// _sprintf + +// LIBRARY: ISLE 0x4081e0 +// _srand + +// LIBRARY: ISLE 0x4081f0 +// LIBRARY: LEGO1 0x1008b640 +// _rand + +// entry +// LIBRARY: ISLE 0x4082e0 +// _WinMainCRTStartup + +// entry +// LIBRARY: LEGO1 0x1008c860 +// __DllMainCRTStartup@12 + +// LIBRARY: ISLE 0x409110 +// __mtinit + +// LIBRARY: ISLE 0x409190 +// __getptd + +#endif diff --git a/tools/isledecomp/isledecomp/bin.py b/tools/isledecomp/isledecomp/bin.py index 1aec9330..16f70f7a 100644 --- a/tools/isledecomp/isledecomp/bin.py +++ b/tools/isledecomp/isledecomp/bin.py @@ -1,4 +1,6 @@ import struct +from typing import List, Optional +from dataclasses import dataclass from collections import namedtuple @@ -33,44 +35,56 @@ class InvalidVirtualAddressError(IndexError): ], ) -ImageSectionHeader = namedtuple( - "ImageSectionHeader", - [ - "Name", - "Misc", - "VirtualAddress", - "SizeOfRawData", - "PointerToRawData", - "PointerToRelocations", - "PointerToLineNumbers", - "NumberOfRelocations", - "NumberOfLineNumbers", - "Characteristics", - ], -) +@dataclass +class ImageSectionHeader: + # pylint: disable=too-many-instance-attributes + # Most attributes are unused, but this is the struct format + name: bytes + virtual_size: int + virtual_address: int + size_of_raw_data: int + pointer_to_raw_data: int + pointer_to_relocations: int + pointer_to_line_numbers: int + number_of_relocations: int + number_of_line_numbers: int + characteristics: int -def section_name_match(section, name): - return section.Name == struct.pack("8s", name.encode("ascii")) + def match_name(self, name: str) -> bool: + return self.name == struct.pack("8s", name.encode("ascii")) + def contains_vaddr(self, vaddr: int) -> bool: + ofs = vaddr - self.virtual_address + return 0 <= ofs < max(self.size_of_raw_data, self.virtual_size) -def section_contains_vaddr(section, imagebase, vaddr) -> bool: - debased = vaddr - imagebase - ofs = debased - section.VirtualAddress - return 0 <= ofs < section.SizeOfRawData + def addr_is_uninitialized(self, vaddr: int) -> bool: + """We cannot rely on the IMAGE_SCN_CNT_UNINITIALIZED_DATA flag (0x80) in + the characteristics field so instead we determine it this way.""" + if not self.contains_vaddr(vaddr): + return False + + # Should include the case where size_of_raw_data == 0, + # meaning the entire section is uninitialized + return (self.virtual_size > self.size_of_raw_data) and ( + vaddr - self.virtual_address >= self.size_of_raw_data + ) class Bin: """Parses a PE format EXE and allows reading data from a virtual address. Reference: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format""" - def __init__(self, filename, logger=None): + # pylint: disable=too-many-instance-attributes + + def __init__(self, filename: str, logger=None) -> None: self.logger = logger self._debuglog(f'Parsing headers of "{filename}"... ') self.filename = filename self.file = None self.imagebase = None - self.sections = [] + self.entry = None + self.sections: List[ImageSectionHeader] = [] self.last_section = None self._relocated_addrs = set() @@ -95,12 +109,18 @@ def __enter__(self): optional_hdr = self.file.read(pe_hdr.SizeOfOptionalHeader) (self.imagebase,) = struct.unpack(" List[int]: return sorted(self._relocated_addrs) def is_relocated_addr(self, vaddr) -> bool: @@ -165,27 +185,25 @@ def _populate_relocations(self): (relocated_addr,) = struct.unpack(" int: + def get_section_offset_by_index(self, index: int) -> int: """The symbols output from cvdump gives addresses in this format: AAAA.BBBBBBBB where A is the index (1-based) into the section table and B is the local offset. This will return the virtual address for the start of the section at the given index @@ -202,29 +220,33 @@ def get_section_offset_by_index(self, index) -> int: """ section = self.sections[index - 1] - return self.imagebase + section.VirtualAddress + return section.virtual_address - def get_section_offset_by_name(self, name) -> int: + def get_section_offset_by_name(self, name: str) -> int: """Same as above, but use the section name as the lookup""" section = self._get_section_by_name(name) - return self.imagebase + section.VirtualAddress + return section.virtual_address - def get_raw_addr(self, vaddr) -> int: + def get_abs_addr(self, section: int, offset: int) -> int: + """Convenience function for converting section:offset pairs from cvdump + into an absolute vaddr.""" + return self.get_section_offset_by_index(section) + offset + + def get_raw_addr(self, vaddr: int) -> int: """Returns the raw offset in the PE binary for the given virtual address.""" self._set_section_for_vaddr(vaddr) return ( vaddr - - self.imagebase - - self.last_section.VirtualAddress - + self.last_section.PointerToRawData + - self.last_section.virtual_address + + self.last_section.pointer_to_raw_data ) - def is_valid_vaddr(self, vaddr) -> bool: + def is_valid_vaddr(self, vaddr: int) -> bool: """Does this virtual address point to anything in the exe?""" section = next( filter( - lambda section: section_contains_vaddr(section, self.imagebase, vaddr), + lambda section: section.contains_vaddr(vaddr), self.sections, ), None, @@ -232,9 +254,14 @@ def is_valid_vaddr(self, vaddr) -> bool: return section is not None - def read(self, offset, size): + def read(self, offset: int, size: int) -> Optional[bytes]: + """Read (at most) the given number of bytes at the given virtual address. + If we return None, the given address points to uninitialized data.""" self._set_section_for_vaddr(offset) + if self.last_section.addr_is_uninitialized(offset): + return None + raw_addr = self.get_raw_addr(offset) self.file.seek(raw_addr) @@ -242,8 +269,8 @@ def read(self, offset, size): # Reading off the end will most likely misrepresent the virtual addressing. _size = min( size, - self.last_section.PointerToRawData - + self.last_section.SizeOfRawData + self.last_section.pointer_to_raw_data + + self.last_section.size_of_raw_data - raw_addr, ) return self.file.read(_size) diff --git a/tools/isledecomp/isledecomp/cvdump/__init__.py b/tools/isledecomp/isledecomp/cvdump/__init__.py new file mode 100644 index 00000000..e9d66298 --- /dev/null +++ b/tools/isledecomp/isledecomp/cvdump/__init__.py @@ -0,0 +1,2 @@ +from .parser import CvdumpParser +from .runner import Cvdump diff --git a/tools/isledecomp/isledecomp/cvdump/parser.py b/tools/isledecomp/isledecomp/cvdump/parser.py new file mode 100644 index 00000000..ddc2e5f7 --- /dev/null +++ b/tools/isledecomp/isledecomp/cvdump/parser.py @@ -0,0 +1,163 @@ +import re +from typing import Iterable +from collections import namedtuple + +# e.g. `*** PUBLICS` +_section_change_regex = re.compile(r"^\*\*\* (?P
[A-Z/ ]+)") + +# e.g. ` 27 00034EC0 28 00034EE2 29 00034EE7 30 00034EF4` +_line_addr_pairs_findall = re.compile(r"\s+(?P\d+) (?P[A-F0-9]{8})") + +# We assume no spaces in the file name +# e.g. ` Z:\lego-island\isle\LEGO1\viewmanager\viewroi.cpp (None), 0001:00034E90-00034E97, line/addr pairs = 2` +_lines_subsection_header = re.compile( + r"^\s*(?P\S+).*?, (?P
[A-F0-9]{4}):(?P[A-F0-9]{8})-(?P[A-F0-9]{8}), line/addr pairs = (?P\d+)" +) + +# e.g. `S_PUB32: [0001:0003FF60], Flags: 00000000, __read` +_publics_line_regex = re.compile( + r"^(?P\w+): \[(?P
\w{4}):(?P\w{8})], Flags: (?P\w{8}), (?P\S+)" +) + +# e.g. `(00008C) S_GPROC32: [0001:00034E90], Cb: 00000007, Type: 0x1024, ViewROI::IntrinsicImportance` +_symbol_line_regex = re.compile( + r"\(\w+\) (?P\S+): \[(?P
\w{4}):(?P\w{8})\], Cb: (?P\w+), Type:\s+\S+, (?P.+)" +) + +# e.g. ` Debug start: 00000008, Debug end: 0000016E` +_gproc_debug_regex = re.compile( + r"\s*Debug start: (?P\w{8}), Debug end: (?P\w{8})" +) + +# e.g. ` 00DA 0001:00000000 00000073 60501020` +_section_contrib_regex = re.compile( + r"\s*(?P\w{4}) (?P
\w{4}):(?P\w{8}) (?P\w{8}) (?P\w{8})" +) + +# e.g. `S_GDATA32: [0003:000004A4], Type: T_32PRCHAR(0470), g_set` +_gdata32_regex = re.compile( + r"S_GDATA32: \[(?P
\w{4}):(?P\w{8})\], Type:\s*(?P\S+), (?P\S+)" +) + + +LinesEntry = namedtuple("LinesEntry", "filename line_no addr") +PublicsEntry = namedtuple("PublicsEntry", "type section offset flags name") +SymbolsEntry = namedtuple("SymbolsEntry", "type section offset size name") +SizeRefEntry = namedtuple("SizeRefEntry", "section offset size") +GdataEntry = namedtuple("GdataEntry", "section offset type name") + + +class CvdumpParser: + def __init__(self) -> None: + self._section: str = "" + self._lines_filename: str = "" + + self.lines = [] + self.publics = [] + self.symbols = [] + self.sizerefs = [] + self.globals = [] + + def _lines_section(self, line: str): + """Parsing entries from the LINES section. We only care about the pairs of + line_number and address and the subsection header to indicate which code file + we are in.""" + + # Subheader indicates a new function and possibly a new code filename. + if (match := _lines_subsection_header.match(line)) is not None: + self._lines_filename = match.group(1) + return + + if (matches := _line_addr_pairs_findall.findall(line)) is not None: + for line_no, addr in matches: + self.lines.append( + LinesEntry( + filename=self._lines_filename, + line_no=int(line_no), + addr=int(addr, 16), + ) + ) + + def _publics_section(self, line: str): + """Match each line from PUBLICS and pull out the symbol information. + These are MSVC mangled symbol names. String constants and vtable + addresses can only be found here.""" + if (match := _publics_line_regex.match(line)) is not None: + self.publics.append( + PublicsEntry( + type=match.group("type"), + section=int(match.group("section"), 16), + offset=int(match.group("offset"), 16), + flags=int(match.group("flags"), 16), + name=match.group("name"), + ) + ) + + def _globals_section(self, line: str): + """S_PROCREF may be useful later. + Right now we just want S_GDATA32 symbols because it is the simplest + way to access global variables.""" + if (match := _gdata32_regex.match(line)) is not None: + self.globals.append( + GdataEntry( + section=int(match.group("section"), 16), + offset=int(match.group("offset"), 16), + type=match.group("type"), + name=match.group("name"), + ) + ) + + def _symbols_section(self, line: str): + """We are interested in S_GPROC32 symbols only.""" + if (match := _symbol_line_regex.match(line)) is not None: + if match.group("type") == "S_GPROC32": + self.symbols.append( + SymbolsEntry( + type=match.group("type"), + section=int(match.group("section"), 16), + offset=int(match.group("offset"), 16), + size=int(match.group("size"), 16), + name=match.group("name"), + ) + ) + + def _section_contributions(self, line: str): + """Gives the size of elements across all sections of the binary. + This is the easiest way to get the data size for .data and .rdata + members that do not have a primitive data type.""" + if (match := _section_contrib_regex.match(line)) is not None: + self.sizerefs.append( + SizeRefEntry( + section=int(match.group("section"), 16), + offset=int(match.group("offset"), 16), + size=int(match.group("size"), 16), + ) + ) + + def read_line(self, line: str): + # Blank lines are there to help the reader; they have no context significance + if line.strip() == "": + return + + if (match := _section_change_regex.match(line)) is not None: + self._section = match.group(1) + return + + if self._section == "LINES": + self._lines_section(line) + + elif self._section == "PUBLICS": + self._publics_section(line) + + elif self._section == "SYMBOLS": + self._symbols_section(line) + + elif self._section == "SECTION CONTRIBUTIONS": + self._section_contributions(line) + + elif self._section == "GLOBALS": + self._globals_section(line) + + def read_lines(self, lines: Iterable[str]): + for line in lines: + self.read_line(line) diff --git a/tools/isledecomp/isledecomp/cvdump/runner.py b/tools/isledecomp/isledecomp/cvdump/runner.py new file mode 100644 index 00000000..02083c12 --- /dev/null +++ b/tools/isledecomp/isledecomp/cvdump/runner.py @@ -0,0 +1,66 @@ +from os import name as os_name +from enum import Enum +from typing import List +import subprocess +from isledecomp.lib import lib_path_join +from isledecomp.dir import winepath_unix_to_win +from .parser import CvdumpParser + + +class DumpOpt(Enum): + LINES = 0 + SYMBOLS = 1 + GLOBALS = 2 + PUBLICS = 3 + SECTION_CONTRIB = 4 + + +cvdump_opt_map = { + DumpOpt.LINES: "-l", + DumpOpt.SYMBOLS: "-s", + DumpOpt.GLOBALS: "-g", + DumpOpt.PUBLICS: "-p", + DumpOpt.SECTION_CONTRIB: "-seccontrib", +} + + +class Cvdump: + def __init__(self, pdb: str) -> None: + self._pdb: str = pdb + self._options = set() + + def lines(self): + self._options.add(DumpOpt.LINES) + return self + + def symbols(self): + self._options.add(DumpOpt.SYMBOLS) + return self + + def globals(self): + self._options.add(DumpOpt.GLOBALS) + return self + + def publics(self): + self._options.add(DumpOpt.PUBLICS) + return self + + def section_contributions(self): + self._options.add(DumpOpt.SECTION_CONTRIB) + return self + + def cmd_line(self) -> List[str]: + cvdump_exe = lib_path_join("cvdump.exe") + flags = [cvdump_opt_map[opt] for opt in self._options] + + if os_name == "nt": + return [cvdump_exe, *flags, self._pdb] + + return ["wine", *flags, cvdump_exe, winepath_unix_to_win(self._pdb)] + + def run(self) -> CvdumpParser: + p = CvdumpParser() + call = self.cmd_line() + lines = subprocess.check_output(call).decode("utf-8").split("\r\n") + p.read_lines(lines) + return p diff --git a/tools/isledecomp/isledecomp/syminfo.py b/tools/isledecomp/isledecomp/syminfo.py index e7ab0df4..1ecf0010 100644 --- a/tools/isledecomp/isledecomp/syminfo.py +++ b/tools/isledecomp/isledecomp/syminfo.py @@ -1,7 +1,6 @@ import os -import subprocess -from isledecomp.lib import lib_path_join -from isledecomp.dir import PathResolver, winepath_unix_to_win +from isledecomp.dir import PathResolver +from isledecomp.cvdump import Cvdump class RecompiledInfo: @@ -20,81 +19,55 @@ class SymInfo: def __init__(self, pdb, sym_recompfile, sym_logger, base_dir): self.logger = sym_logger path_resolver = PathResolver(base_dir) - call = [lib_path_join("cvdump.exe"), "-l", "-s"] - - if os.name != "nt": - # Run cvdump through wine and convert path to Windows-friendly wine path - call.insert(0, "wine") - call.append(winepath_unix_to_win(pdb)) - else: - call.append(pdb) self.logger.info("Parsing %s ...", pdb) - self.logger.debug("Command = %s", call) - line_dump = subprocess.check_output(call).decode("utf-8").split("\r\n") - - current_section = None - self.logger.debug("Parsing output of cvdump.exe ...") - for i, line in enumerate(line_dump): - if line.startswith("***"): - current_section = line[4:] - - if current_section == "SYMBOLS" and "S_GPROC32" in line: - sym_section = int(line[21:25], 16) - sym_addr = int(line[26:34], 16) - - info = RecompiledInfo() - info.addr = sym_addr + sym_recompfile.get_section_offset_by_index( - sym_section - ) - - use_dbg_offs = False - if use_dbg_offs: - debug_offs = line_dump[i + 2] - debug_start = int(debug_offs[22:30], 16) - debug_end = int(debug_offs[43:], 16) - - info.start = debug_start - info.size = debug_end - debug_start - else: - info.start = 0 - info.size = int(line[41:49], 16) - - info.name = line[77:] - - self.names[info.name] = info - self.funcs[sym_addr] = info - elif ( - current_section == "LINES" - and line.startswith(" ") - and not line.startswith(" ") - ): - sourcepath = line.split()[0] - sourcepath = path_resolver.resolve_cvdump(sourcepath) - - if sourcepath not in self.lines: - self.lines[sourcepath] = {} - - j = i + 2 - while True: - ll = line_dump[j].split() - if len(ll) == 0: - break - - k = 0 - while k < len(ll): - linenum = int(ll[k + 0]) - address = int(ll[k + 1], 16) - if linenum not in self.lines[sourcepath]: - self.lines[sourcepath][linenum] = address - k += 2 - - j += 1 + cv = Cvdump(pdb).lines().symbols().publics().section_contributions().run() self.logger.debug("... Parsing output of cvdump.exe finished") + contrib_dict = {(s.section, s.offset): s.size for s in cv.sizerefs} + for pub in cv.publics: + if ( + pub.type == "S_PUB32" + and pub.name.startswith("_") + and (pub.section, pub.offset) in contrib_dict + ): + size = contrib_dict[(pub.section, pub.offset)] + + info = RecompiledInfo() + info.addr = sym_recompfile.get_abs_addr(pub.section, pub.offset) + + info.start = 0 + info.size = size + info.name = pub.name + self.names[pub.name] = info + self.funcs[pub.offset] = info + + for proc in cv.symbols: + if proc.type != "S_GPROC32": + continue + + info = RecompiledInfo() + info.addr = sym_recompfile.get_abs_addr(proc.section, proc.offset) + + info.start = 0 + info.size = proc.size + info.name = proc.name + + self.names[proc.name] = info + self.funcs[proc.offset] = info + + for sourcepath, line_no, offset in cv.lines: + sourcepath = path_resolver.resolve_cvdump(sourcepath) + + if sourcepath not in self.lines: + self.lines[sourcepath] = {} + + if line_no not in self.lines[sourcepath]: + self.lines[sourcepath][line_no] = offset + def get_recompiled_address(self, filename, line): recompiled_addr = None From 3f63950a7dac2ce45648ac9cdb66ed84cace61e5 Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 28 Dec 2023 18:02:02 -0500 Subject: [PATCH 37/50] Fix new/delete symbol reference (#384) --- LEGO1/library_msvc.h | 12 +++++++++++- tools/isledecomp/isledecomp/syminfo.py | 6 +----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index d07ecef2..c46154a8 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -1,11 +1,21 @@ #ifdef 0 +// aka `operator new` // LIBRARY: ISLE 0x402f80 // LIBRARY: LEGO1 0x10086240 -// _malloc +// ??2@YAPAXI@Z +// aka `operator delete` // LIBRARY: ISLE 0x402fa0 // LIBRARY: LEGO1 0x10086260 +// ??3@YAXPAX@Z + +// LIBRARY: ISLE 0x406dd0 +// LIBRARY: LEGO1 0x1008a090 +// _malloc + +// LIBRARY: ISLE 0x406f00 +// LIBRARY: LEGO1 0x1008a1c0 // _free // LIBRARY: ISLE 0x408220 diff --git a/tools/isledecomp/isledecomp/syminfo.py b/tools/isledecomp/isledecomp/syminfo.py index 1ecf0010..8388eaa5 100644 --- a/tools/isledecomp/isledecomp/syminfo.py +++ b/tools/isledecomp/isledecomp/syminfo.py @@ -29,11 +29,7 @@ def __init__(self, pdb, sym_recompfile, sym_logger, base_dir): contrib_dict = {(s.section, s.offset): s.size for s in cv.sizerefs} for pub in cv.publics: - if ( - pub.type == "S_PUB32" - and pub.name.startswith("_") - and (pub.section, pub.offset) in contrib_dict - ): + if pub.type == "S_PUB32" and (pub.section, pub.offset) in contrib_dict: size = contrib_dict[(pub.section, pub.offset)] info = RecompiledInfo() From d82d062e926e2a726d951afda2810090b6f8f262 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 28 Dec 2023 23:37:21 -0500 Subject: [PATCH 38/50] Implement/match MxRegionCursor class (#385) * Implement/match MxRegionCursor class * Rename function --- CMakeLists.txt | 1 + LEGO1/mxlist.h | 30 +++- LEGO1/mxrect32.h | 8 +- LEGO1/mxregion.cpp | 6 +- LEGO1/mxregion.h | 9 +- LEGO1/mxregioncursor.cpp | 284 +++++++++++++++++++++++++++++++++++++ LEGO1/mxregioncursor.h | 45 ++++++ LEGO1/mxregionlist.h | 31 ++-- LEGO1/mxvideopresenter.cpp | 4 +- LEGO1/mxvideopresenter.h | 2 +- 10 files changed, 391 insertions(+), 29 deletions(-) create mode 100644 LEGO1/mxregioncursor.cpp create mode 100644 LEGO1/mxregioncursor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b4676767..3b31a548 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,6 +162,7 @@ add_library(lego1 SHARED LEGO1/mxramstreamcontroller.cpp LEGO1/mxramstreamprovider.cpp LEGO1/mxregion.cpp + LEGO1/mxregioncursor.cpp LEGO1/mxrendersettings.cpp LEGO1/mxscheduler.cpp LEGO1/mxsemaphore.cpp diff --git a/LEGO1/mxlist.h b/LEGO1/mxlist.h index 8a5f3e0e..80fa0e00 100644 --- a/LEGO1/mxlist.h +++ b/LEGO1/mxlist.h @@ -92,13 +92,23 @@ class MxListCursor : public MxCore { void Detach(); void Destroy(); MxBool Next(T& p_obj); + MxBool Prev(T& p_obj); MxBool Current(T& p_obj); MxBool First(T& p_obj); MxBool Last(T& p_obj); MxBool Advance(); MxBool HasMatch() { return m_match != NULL; } void SetValue(T p_obj); - void Head() { m_match = m_list->m_first; } + MxBool Head() + { + m_match = m_list->m_first; + return m_match != NULL; + } + MxBool Tail() + { + m_match = m_list->m_last; + return m_match != NULL; + } void Reset() { m_match = NULL; } void Prepend(T p_newobj); @@ -110,8 +120,8 @@ class MxListCursor : public MxCore { } private: - MxList* m_list; - MxListEntry* m_match; + MxList* m_list; // 0x08 + MxListEntry* m_match; // 0x0c }; template @@ -226,6 +236,20 @@ inline MxBool MxListCursor::Next(T& p_obj) return m_match != NULL; } +template +inline MxBool MxListCursor::Prev(T& p_obj) +{ + if (!m_match) + m_match = m_list->m_last; + else + m_match = m_match->GetPrev(); + + if (m_match) + p_obj = m_match->GetValue(); + + return m_match != NULL; +} + template inline MxBool MxListCursor::Current(T& p_obj) { diff --git a/LEGO1/mxrect32.h b/LEGO1/mxrect32.h index b54a9d92..7566a9ea 100644 --- a/LEGO1/mxrect32.h +++ b/LEGO1/mxrect32.h @@ -110,10 +110,10 @@ class MxRect32 { inline static MxS32 Min(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_a : p_b; }; inline static MxS32 Max(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_b : p_a; }; - MxS32 m_left; - MxS32 m_top; - MxS32 m_right; - MxS32 m_bottom; + MxS32 m_left; // 0x00 + MxS32 m_top; // 0x04 + MxS32 m_right; // 0x08 + MxS32 m_bottom; // 0x0c }; #endif // MXRECT32_H diff --git a/LEGO1/mxregion.cpp b/LEGO1/mxregion.cpp index f003aceb..d21b9fdb 100644 --- a/LEGO1/mxregion.cpp +++ b/LEGO1/mxregion.cpp @@ -9,7 +9,7 @@ DECOMP_SIZE_ASSERT(MxRegionLeftRight, 0x08); // FUNCTION: LEGO1 0x100c31c0 MxRegion::MxRegion() { - m_list = new MxRegionList; + m_list = new MxRegionTopBottomList; m_rect = MxRect32(INT_MAX, INT_MAX, -1, -1); } @@ -38,7 +38,7 @@ void MxRegion::VTable0x18(MxRect32& p_rect) { MxRect32 rect(p_rect); MxRect32 newRect; - MxRegionListCursor cursor(m_list); + MxRegionTopBottomListCursor cursor(m_list); MxRegionTopBottom* topBottom; while (rect.IsValid() && cursor.Next(topBottom)) { @@ -91,7 +91,7 @@ MxBool MxRegion::VTable0x1c(MxRect32& p_rect) if (!m_rect.IntersectsWith(p_rect)) return FALSE; - MxRegionListCursor cursor(m_list); + MxRegionTopBottomListCursor cursor(m_list); MxRegionTopBottom* topBottom; while (cursor.Next(topBottom)) { diff --git a/LEGO1/mxregion.h b/LEGO1/mxregion.h index c7d7dd90..646866a6 100644 --- a/LEGO1/mxregion.h +++ b/LEGO1/mxregion.h @@ -18,11 +18,14 @@ class MxRegion : public MxCore { virtual MxBool VTable0x1c(MxRect32& p_rect); // vtable+0x1c virtual MxBool VTable0x20(); // vtable+0x20 - inline MxRect32& GetRect() { return this->m_rect; } + inline MxRegionTopBottomList* GetTopBottomList() const { return m_list; } + inline const MxRect32& GetRect() const { return m_rect; } + + friend class MxRegionCursor; private: - MxRegionList* m_list; // 0x08 - MxRect32 m_rect; // 0x0c + MxRegionTopBottomList* m_list; // 0x08 + MxRect32 m_rect; // 0x0c }; #endif // MXREGION_H diff --git a/LEGO1/mxregioncursor.cpp b/LEGO1/mxregioncursor.cpp new file mode 100644 index 00000000..89c90403 --- /dev/null +++ b/LEGO1/mxregioncursor.cpp @@ -0,0 +1,284 @@ +#include "mxregioncursor.h" + +DECOMP_SIZE_ASSERT(MxRegionCursor, 0x18); + +// FUNCTION: LEGO1 0x100c3f70 +MxRegionCursor::MxRegionCursor(MxRegion* p_region) +{ + m_region = p_region; + m_rect = NULL; + m_topBottomCursor = new MxRegionTopBottomListCursor(m_region->m_list); + m_leftRightCursor = NULL; +} + +// FUNCTION: LEGO1 0x100c40b0 +MxRegionCursor::~MxRegionCursor() +{ + if (m_rect) + delete m_rect; + + if (m_topBottomCursor) + delete m_topBottomCursor; + + if (m_leftRightCursor) + delete m_leftRightCursor; +} + +// FUNCTION: LEGO1 0x100c4140 +MxRect32* MxRegionCursor::VTable0x18() +{ + m_topBottomCursor->Head(); + + MxRegionTopBottom* topBottom; + if (m_topBottomCursor->Current(topBottom)) { + FUN_100c46c0(*topBottom->m_leftRightList); + + MxRegionLeftRight* leftRight; + m_leftRightCursor->First(leftRight); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + } + else + Reset(); + + return m_rect; +} + +// FUNCTION: LEGO1 0x100c41d0 +MxRect32* MxRegionCursor::VTable0x20() +{ + m_topBottomCursor->Tail(); + + MxRegionTopBottom* topBottom; + if (m_topBottomCursor->Current(topBottom)) { + FUN_100c46c0(*topBottom->m_leftRightList); + + MxRegionLeftRight* leftRight; + m_leftRightCursor->Last(leftRight); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + } + else + Reset(); + + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4260 +MxRect32* MxRegionCursor::VTable0x28() +{ + MxRegionLeftRight* leftRight; + MxRegionTopBottom* topBottom; + + if (m_leftRightCursor && m_leftRightCursor->Next(leftRight)) { + m_topBottomCursor->Current(topBottom); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + return m_rect; + } + + if (m_topBottomCursor->Next(topBottom)) { + FUN_100c46c0(*topBottom->m_leftRightList); + m_leftRightCursor->First(leftRight); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + return m_rect; + } + + Reset(); + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4360 +MxRect32* MxRegionCursor::VTable0x30() +{ + MxRegionLeftRight* leftRight; + MxRegionTopBottom* topBottom; + + if (m_leftRightCursor && m_leftRightCursor->Prev(leftRight)) { + m_topBottomCursor->Current(topBottom); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + return m_rect; + } + + if (m_topBottomCursor->Prev(topBottom)) { + FUN_100c46c0(*topBottom->m_leftRightList); + m_leftRightCursor->Last(leftRight); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + return m_rect; + } + + Reset(); + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4460 +MxRect32* MxRegionCursor::VTable0x14(MxRect32& p_rect) +{ + m_topBottomCursor->Reset(); + FUN_100c4a20(p_rect); + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4480 +MxRect32* MxRegionCursor::VTable0x1c(MxRect32& p_rect) +{ + m_topBottomCursor->Reset(); + FUN_100c4b50(p_rect); + return m_rect; +} + +// FUNCTION: LEGO1 0x100c44a0 +MxRect32* MxRegionCursor::VTable0x24(MxRect32& p_rect) +{ + MxRegionLeftRight* leftRight; + + if (m_leftRightCursor && m_leftRightCursor->Next(leftRight)) { + MxRegionTopBottom* topBottom; + + m_topBottomCursor->Current(topBottom); + + if (topBottom->IntersectsWith(p_rect) && leftRight->IntersectsWith(p_rect)) { + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + m_rect->Intersect(p_rect); + } + else + FUN_100c4a20(p_rect); + } + else + FUN_100c4a20(p_rect); + + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4590 +MxRect32* MxRegionCursor::VTable0x2c(MxRect32& p_rect) +{ + MxRegionLeftRight* leftRight; + + if (m_leftRightCursor && m_leftRightCursor->Prev(leftRight)) { + MxRegionTopBottom* topBottom; + + m_topBottomCursor->Current(topBottom); + + if (topBottom->IntersectsWith(p_rect) && leftRight->IntersectsWith(p_rect)) { + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + m_rect->Intersect(p_rect); + } + else + FUN_100c4b50(p_rect); + } + else + FUN_100c4b50(p_rect); + + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4680 +void MxRegionCursor::Reset() +{ + if (m_rect) { + delete m_rect; + m_rect = NULL; + } + + m_topBottomCursor->Reset(); + + if (m_leftRightCursor) { + delete m_leftRightCursor; + m_leftRightCursor = NULL; + } +} + +// FUNCTION: LEGO1 0x100c46c0 +void MxRegionCursor::FUN_100c46c0(MxRegionLeftRightList& p_leftRightList) +{ + if (m_leftRightCursor) + delete m_leftRightCursor; + + m_leftRightCursor = new MxRegionLeftRightListCursor(&p_leftRightList); +} + +// FUNCTION: LEGO1 0x100c4980 +void MxRegionCursor::UpdateRect(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) +{ + if (!m_rect) + m_rect = new MxRect32; + + m_rect->SetLeft(p_left); + m_rect->SetTop(p_top); + m_rect->SetRight(p_right); + m_rect->SetBottom(p_bottom); +} + +// FUNCTION: LEGO1 0x100c4a20 +void MxRegionCursor::FUN_100c4a20(MxRect32& p_rect) +{ + MxRegionTopBottom* topBottom; + while (m_topBottomCursor->Next(topBottom)) { + if (p_rect.GetBottom() <= topBottom->GetTop()) { + Reset(); + return; + } + + if (p_rect.GetTop() < topBottom->GetBottom()) { + FUN_100c46c0(*topBottom->m_leftRightList); + + MxRegionLeftRight* leftRight; + while (m_leftRightCursor->Next(leftRight)) { + if (p_rect.GetRight() <= leftRight->GetLeft()) + break; + + if (p_rect.GetLeft() < leftRight->GetRight()) { + UpdateRect( + leftRight->GetLeft(), + topBottom->GetTop(), + leftRight->GetRight(), + topBottom->GetBottom() + ); + m_rect->Intersect(p_rect); + return; + } + } + } + } + + Reset(); +} + +// FUNCTION: LEGO1 0x100c4b50 +void MxRegionCursor::FUN_100c4b50(MxRect32& p_rect) +{ + MxRegionTopBottom* topBottom; + while (m_topBottomCursor->Prev(topBottom)) { + if (topBottom->GetBottom() <= p_rect.GetTop()) { + Reset(); + return; + } + + if (topBottom->GetTop() < p_rect.GetBottom()) { + FUN_100c46c0(*topBottom->m_leftRightList); + + MxRegionLeftRight* leftRight; + while (m_leftRightCursor->Prev(leftRight)) { + if (leftRight->GetRight() <= p_rect.GetLeft()) + break; + + if (leftRight->GetLeft() < p_rect.GetRight()) { + UpdateRect( + leftRight->GetLeft(), + topBottom->GetTop(), + leftRight->GetRight(), + topBottom->GetBottom() + ); + m_rect->Intersect(p_rect); + return; + } + } + } + } + + Reset(); +} diff --git a/LEGO1/mxregioncursor.h b/LEGO1/mxregioncursor.h new file mode 100644 index 00000000..5f4a24b8 --- /dev/null +++ b/LEGO1/mxregioncursor.h @@ -0,0 +1,45 @@ +#ifndef MXREGIONCURSOR_H +#define MXREGIONCURSOR_H + +#include "mxregion.h" + +// VTABLE: LEGO1 0x100dcbb8 +// SIZE 0x18 +class MxRegionCursor : public MxCore { +public: + MxRegionCursor(MxRegion* p_region); + virtual ~MxRegionCursor() override; + + virtual MxRect32* VTable0x14(MxRect32& p_rect); // vtable+0x14 + virtual MxRect32* VTable0x18(); // vtable+0x18 + virtual MxRect32* VTable0x1c(MxRect32& p_rect); // vtable+0x1c + virtual MxRect32* VTable0x20(); // vtable+0x20 + virtual MxRect32* VTable0x24(MxRect32& p_rect); // vtable+0x24 + virtual MxRect32* VTable0x28(); // vtable+0x28 + virtual MxRect32* VTable0x2c(MxRect32& p_rect); // vtable+0x2c + virtual MxRect32* VTable0x30(); // vtable+0x30 + + // FUNCTION: LEGO1 0x100c4070 + virtual MxRect32* GetRect() { return m_rect; } // vtable+0x34 + + // FUNCTION: LEGO1 0x100c4080 + virtual MxBool HasRect() { return m_rect != NULL; } // vtable+0x38 + + virtual void Reset(); // vtable+0x3c + +private: + void FUN_100c46c0(MxRegionLeftRightList& p_leftRightList); + void UpdateRect(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom); + void FUN_100c4a20(MxRect32& p_rect); + void FUN_100c4b50(MxRect32& p_rect); + + MxRegion* m_region; // 0x08 + MxRect32* m_rect; // 0x0c + MxRegionTopBottomListCursor* m_topBottomCursor; // 0x10 + MxRegionLeftRightListCursor* m_leftRightCursor; // 0x14 +}; + +// SYNTHETIC: LEGO1 0x100c4090 +// MxRegionCursor::`scalar deleting destructor' + +#endif // MXREGIONCURSOR_H diff --git a/LEGO1/mxregionlist.h b/LEGO1/mxregionlist.h index ef3712cb..7c6da5c2 100644 --- a/LEGO1/mxregionlist.h +++ b/LEGO1/mxregionlist.h @@ -19,9 +19,11 @@ struct MxRegionLeftRight { inline void SetLeft(MxS32 p_left) { m_left = p_left; } inline void SetRight(MxS32 p_right) { m_right = p_right; } + inline MxBool IntersectsWith(MxRect32& p_rect) { return m_left < p_rect.GetRight() && p_rect.GetTop() < m_right; } + private: - MxS32 m_left; - MxS32 m_right; + MxS32 m_left; // 0x00 + MxS32 m_right; // 0x04 }; // VTABLE: LEGO1 0x100dcc40 @@ -68,12 +70,15 @@ struct MxRegionTopBottom { inline void SetTop(MxS32 p_top) { m_top = p_top; } inline void SetBottom(MxS32 p_bottom) { m_bottom = p_bottom; } - friend class MxRegionList; + inline MxBool IntersectsWith(MxRect32& p_rect) { return m_top < p_rect.GetBottom() && p_rect.GetTop() < m_bottom; } + + friend class MxRegionTopBottomList; + friend class MxRegionCursor; private: - MxS32 m_top; - MxS32 m_bottom; - MxRegionLeftRightList* m_leftRightList; + MxS32 m_top; // 0x00 + MxS32 m_bottom; // 0x04 + MxRegionLeftRightList* m_leftRightList; // 0x08 }; // VTABLE: LEGO1 0x100dcb10 @@ -87,9 +92,9 @@ struct MxRegionTopBottom { // VTABLE: LEGO1 0x100dcb58 // SIZE 0x18 -class MxRegionList : public MxPtrList { +class MxRegionTopBottomList : public MxPtrList { public: - MxRegionList() : MxPtrList(TRUE) {} + MxRegionTopBottomList() : MxPtrList(TRUE) {} }; // VTABLE: LEGO1 0x100dcb70 @@ -98,14 +103,14 @@ class MxRegionList : public MxPtrList { // VTABLE: LEGO1 0x100dcba0 // class MxListCursor -// TODO: The initialize list param type should be MxRegionList, but doing that +// TODO: The initialize list param type should be MxRegionTopBottomList, but doing that // drastically reduced the match percentage for MxRegion::VTable0x18. // It also works with MxPtrList, so we'll do that until we figure this out. // VTABLE: LEGO1 0x100dcb88 -class MxRegionListCursor : public MxPtrListCursor { +class MxRegionTopBottomListCursor : public MxPtrListCursor { public: - MxRegionListCursor(MxPtrList* p_list) : MxPtrListCursor(p_list){}; + MxRegionTopBottomListCursor(MxPtrList* p_list) : MxPtrListCursor(p_list){}; }; // TEMPLATE: LEGO1 0x100c32e0 @@ -127,7 +132,7 @@ class MxRegionListCursor : public MxPtrListCursor { // MxPtrList::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100c3be0 -// MxRegionListCursor::`scalar deleting destructor' +// MxRegionTopBottomListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100c3c50 // MxPtrListCursor::~MxPtrListCursor @@ -142,7 +147,7 @@ class MxRegionListCursor : public MxPtrListCursor { // MxListCursor::~MxListCursor // FUNCTION: LEGO1 0x100c3dd0 -// MxRegionListCursor::~MxRegionListCursor +// MxRegionTopBottomListCursor::~MxRegionTopBottomListCursor // SYNTHETIC: LEGO1 0x100c4790 // MxRegionLeftRightListCursor::`scalar deleting destructor' diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index b1beb08e..4162be43 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -313,7 +313,7 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) } // STUB: LEGO1 0x100b2a70 -void MxVideoPresenter::VTable0x6c() +void MxVideoPresenter::PutFrame() { // TODO } @@ -482,7 +482,7 @@ MxResult MxVideoPresenter::PutData() MxAutoLocker lock(&m_criticalSection); if (IsEnabled() && m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_unk5) - VTable0x6c(); + PutFrame(); return SUCCESS; } diff --git a/LEGO1/mxvideopresenter.h b/LEGO1/mxvideopresenter.h index 4c1bab5e..72ea33d8 100644 --- a/LEGO1/mxvideopresenter.h +++ b/LEGO1/mxvideopresenter.h @@ -47,7 +47,7 @@ class MxVideoPresenter : public MxMediaPresenter { virtual void CreateBitmap(); // vtable+0x60 virtual void NextFrame(); // vtable+0x64 virtual void LoadFrame(MxStreamChunk* p_chunk); // vtable+0x68 - virtual void VTable0x6c(); // vtable+0x6c + virtual void PutFrame(); // vtable+0x6c virtual void RealizePalette(); // vtable+0x70 virtual undefined VTable0x74(); // vtable+0x74 virtual LPDIRECTDRAWSURFACE VTable0x78(); // vtable+0x78 From a95bdcc4ad205c7a89da32db0ef93dd6ae961391 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Fri, 29 Dec 2023 10:22:18 -0500 Subject: [PATCH 39/50] Implement InvokeAction (#386) * push changes * Update legoutil.cpp * Fixes / match --------- Co-authored-by: Christian Semmler --- LEGO1/legoomni.cpp | 2 +- LEGO1/legoomni.h | 4 ++- LEGO1/legoutil.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++-- LEGO1/legoutil.h | 2 +- 4 files changed, 84 insertions(+), 5 deletions(-) diff --git a/LEGO1/legoomni.cpp b/LEGO1/legoomni.cpp index 8c9e5905..ddf0e454 100644 --- a/LEGO1/legoomni.cpp +++ b/LEGO1/legoomni.cpp @@ -390,7 +390,7 @@ void LegoOmni::Init() m_gifManager = NULL; m_worldList = NULL; m_currentWorld = NULL; - m_unk0x80 = FALSE; + m_exit = FALSE; m_currentVehicle = NULL; m_saveDataWriter = NULL; m_plantManager = NULL; diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index 7fb0a4f3..dff06fb5 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -116,6 +116,8 @@ class LegoOmni : public MxOmni { MxTransitionManager* GetTransitionManager() { return m_transitionManager; } MxDSAction& GetCurrentAction() { return m_action; } + inline void SetExit(MxBool p_exit) { m_exit = p_exit; }; + private: undefined4* m_unk0x68; // 0x68 MxUnknown100dbdbc* m_renderMgr; // 0x6c @@ -123,7 +125,7 @@ class LegoOmni : public MxOmni { GifManager* m_gifManager; // 0x74 LegoWorldList* m_worldList; // 0x78 LegoWorld* m_currentWorld; // 0x7c - MxBool m_unk0x80; // 0x80 + MxBool m_exit; // 0x80 LegoNavController* m_navController; // 0x84 IslePathActor* m_currentVehicle; // 0x88 LegoUnkSaveDataWriter* m_saveDataWriter; // 0x8c diff --git a/LEGO1/legoutil.cpp b/LEGO1/legoutil.cpp index 42d14dac..4941d968 100644 --- a/LEGO1/legoutil.cpp +++ b/LEGO1/legoutil.cpp @@ -1,8 +1,13 @@ #include "legoutil.h" +#include "legoomni.h" +#include "legoworld.h" +#include "mxdsaction.h" #include "mxomni.h" +#include "mxstreamer.h" #include "mxtypes.h" +#include #include // FUNCTION: LEGO1 0x1003e300 @@ -34,8 +39,79 @@ ExtraActionType MatchActionString(const char* p_str) return result; } -// STUB: LEGO1 0x1003e430 +MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_entityId); +void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender); + +// FUNCTION: LEGO1 0x1003e430 void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender) +{ + MxDSAction action; + action.SetAtomId(p_pAtom); + action.SetObjectId(p_targetEntityId); + + switch (p_actionId) { + case ExtraActionType_opendisk: + if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { + Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_DiskStream); + Start(&action); + } + break; + case ExtraActionType_openram: + if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { + Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_RAMStream); + Start(&action); + } + break; + case ExtraActionType_close: + action.SetUnknown24(-2); + DeleteObject(action); + Streamer()->Close(p_pAtom.GetInternal()); + break; + case ExtraActionType_start: + if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { + Start(&action); + } + break; + case ExtraActionType_stop: + action.SetUnknown24(-2); + if (!FUN_1003ee00(p_pAtom, p_targetEntityId)) { + DeleteObject(action); + } + break; + case ExtraActionType_run: + _spawnl(0, "\\lego\\sources\\main\\main.exe", "\\lego\\sources\\main\\main.exe", "/script", &p_pAtom, 0); + break; + case ExtraActionType_exit: + Lego()->SetExit(TRUE); + break; + case ExtraActionType_enable: + CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId); + break; + case ExtraActionType_disable: + CheckIfEntityExists(FALSE, p_pAtom.GetInternal(), p_targetEntityId); + break; + case ExtraActionType_notify: + NotifyEntity(p_pAtom.GetInternal(), p_targetEntityId, p_sender); + break; + } +} + +// FUNCTION: LEGO1 0x1003e670 +MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_entityId) +{ + LegoWorld* world = + (LegoWorld*) FindEntityByAtomIdOrEntityId(MxAtomId(p_filename, LookupMode_LowerCase2), p_entityId); + if (world) { + world->VTable0x68(p_enable); + return TRUE; + } + else { + return FALSE; + } +} + +// STUB: LEGO1 0x1003e700 +void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender) { } @@ -108,8 +184,9 @@ void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bO } // STUB: LEGO1 0x1003ee00 -void FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id) +MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id) { + return TRUE; } // STUB: LEGO1 0x1003ef00 diff --git a/LEGO1/legoutil.h b/LEGO1/legoutil.h index bd7adae6..827b8488 100644 --- a/LEGO1/legoutil.h +++ b/LEGO1/legoutil.h @@ -58,7 +58,7 @@ inline void GetString(MxU8** p_source, char** p_dest, T* p_obj, void (T::*p_sett ExtraActionType MatchActionString(const char*); void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender); void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bOut, float* p_gOut); -void FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id); +MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id); void FUN_1003ef00(MxBool); void SetAppCursor(WPARAM p_wparam); MxBool FUN_1003ef60(); From 343715af23a45da767fa8db69c851c2c6f8f236a Mon Sep 17 00:00:00 2001 From: MS Date: Fri, 29 Dec 2023 11:23:42 -0500 Subject: [PATCH 40/50] Wine cvdump bugfix (#388) --- tools/isledecomp/isledecomp/cvdump/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/isledecomp/isledecomp/cvdump/runner.py b/tools/isledecomp/isledecomp/cvdump/runner.py index 02083c12..f1c163b5 100644 --- a/tools/isledecomp/isledecomp/cvdump/runner.py +++ b/tools/isledecomp/isledecomp/cvdump/runner.py @@ -56,7 +56,7 @@ def cmd_line(self) -> List[str]: if os_name == "nt": return [cvdump_exe, *flags, self._pdb] - return ["wine", *flags, cvdump_exe, winepath_unix_to_win(self._pdb)] + return ["wine", cvdump_exe, *flags, winepath_unix_to_win(self._pdb)] def run(self) -> CvdumpParser: p = CvdumpParser() From ceb5339369b96a9fc47f4b44b11f5e2a81e6bc1d Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Fri, 29 Dec 2023 13:04:18 -0500 Subject: [PATCH 41/50] Infocenter vtable (#387) * implement parts of legoworld/infocenter * Update infocenter.cpp * Update infocenter.cpp * Update infocenter.cpp * Update infocenter.cpp * Update infocenter.cpp * Match LegoWorld::Tickle --------- Co-authored-by: Christian Semmler --- LEGO1/infocenter.cpp | 32 ++++++++++++++++++++++++++++++-- LEGO1/infocenter.h | 6 ++++++ LEGO1/legoworld.cpp | 29 +++++++++++++++++++++++++++-- LEGO1/legoworld.h | 6 ++++-- 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/LEGO1/infocenter.cpp b/LEGO1/infocenter.cpp index f062f1e9..8c6bcb8d 100644 --- a/LEGO1/infocenter.cpp +++ b/LEGO1/infocenter.cpp @@ -12,18 +12,46 @@ Infocenter::~Infocenter() // TODO } +// STUB: LEGO1 0x1006ed90 +MxResult Infocenter::Create(MxDSObject& p_dsObject) +{ + return FAILURE; +} + // STUB: LEGO1 0x1006ef10 MxLong Infocenter::Notify(MxParam& p_param) { // TODO - return 0; } +// STUB: LEGO1 0x1006f4e0 +void Infocenter::Stop() +{ + // TODO +} + +// STUB: LEGO1 0x10070aa0 +void Infocenter::VTable0x68(MxBool p_add) +{ + // TODO +} + // STUB: LEGO1 0x10070af0 MxResult Infocenter::Tickle() { // TODO - return 0; } + +// FUNCTION: LEGO1 0x10070d00 +MxBool Infocenter::VTable0x5c() +{ + return TRUE; +} + +// STUB: LEGO1 0x10070f60 +MxBool Infocenter::VTable0x64() +{ + return FALSE; +} diff --git a/LEGO1/infocenter.h b/LEGO1/infocenter.h index 89fcc54f..ec0be745 100644 --- a/LEGO1/infocenter.h +++ b/LEGO1/infocenter.h @@ -25,6 +25,12 @@ class Infocenter : public LegoWorld { { return !strcmp(p_name, Infocenter::ClassName()) || LegoWorld::IsA(p_name); } + + virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 + virtual void Stop() override; // vtable+0x50 + virtual MxBool VTable0x5c() override; // vtable+0x5c + virtual MxBool VTable0x64() override; // vtable+0x64 + virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 }; #endif // INFOCENTER_H diff --git a/LEGO1/legoworld.cpp b/LEGO1/legoworld.cpp index 03139566..ff3969bd 100644 --- a/LEGO1/legoworld.cpp +++ b/LEGO1/legoworld.cpp @@ -2,7 +2,9 @@ #include "legoinputmanager.h" #include "legoomni.h" +#include "legoutil.h" #include "mxactionnotificationparam.h" +#include "mxnotificationmanager.h" #include "mxnotificationparam.h" #include "mxomni.h" #include "mxticklemanager.h" @@ -13,6 +15,9 @@ DECOMP_SIZE_ASSERT(LegoWorld, 0xf8); LegoWorld::LegoWorld() : m_list0x68(TRUE) { // TODO + m_unk0xf6 = FALSE; + m_unk0xf4 = 4; + NotificationManager()->Register(this); } // FUNCTION: LEGO1 0x1001d670 @@ -93,10 +98,30 @@ void LegoWorld::VTable0x68(MxBool p_add) // TODO } -// STUB: LEGO1 0x10022080 +// FUNCTION: LEGO1 0x10022080 MxResult LegoWorld::Tickle() { - return SUCCESS; + if (!m_unk0xf6) { + switch (m_unk0xf4) { + case 0: + m_unk0xf6 = TRUE; + SetAppCursor(0); + Stop(); + return TRUE; + case 2: + if (FUN_100220e0() == 1) + break; + default: + m_unk0xf4--; + } + } + return TRUE; +} + +// STUB: LEGO1 0x100220e0 +undefined LegoWorld::FUN_100220e0() +{ + return TRUE; } // FUNCTION: LEGO1 0x10022340 diff --git a/LEGO1/legoworld.h b/LEGO1/legoworld.h index f6210e8e..d855b530 100644 --- a/LEGO1/legoworld.h +++ b/LEGO1/legoworld.h @@ -44,6 +44,7 @@ class LegoWorld : public LegoEntity { inline LegoCameraController* GetCamera() { return m_camera; } + undefined FUN_100220e0(); MxResult SetAsCurrentWorld(MxDSObject& p_dsObject); void EndAction(MxCore* p_object); void FUN_1001fc80(IslePathActor* p_actor); @@ -59,8 +60,9 @@ class LegoWorld : public LegoEntity { LegoCameraController* m_camera; // 0x98 undefined m_unk0x9c[0x1c]; // 0x9c MxPresenterList m_list0xb8; // 0xb8 - undefined m_unk0xd0[0x26]; // 0xd0 - undefined m_unk0xf6; // 0xf6 + undefined m_unk0xd0[0x24]; // 0xd0 + MxS16 m_unk0xf4; // 0xf4 + MxBool m_unk0xf6; // 0xf6 undefined m_unk0xf7; // 0xf7 }; From 51adb31541ee49f8eccabd3ed0f22d667d11dbaa Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Dec 2023 16:30:17 -0500 Subject: [PATCH 42/50] Implement MxVideoPresenter::PutFrame (#389) * Implementation of MxVideoPresenter::PutFrame * Add TODOs --- LEGO1/mxdisplaysurface.cpp | 24 ++++--- LEGO1/mxdisplaysurface.h | 24 ++++--- LEGO1/mxrect32.h | 18 ++--- LEGO1/mxsize32.h | 12 ++-- LEGO1/mxstillpresenter.cpp | 15 +--- LEGO1/mxvideomanager.h | 1 + LEGO1/mxvideopresenter.cpp | 140 ++++++++++++++++++++++++++++++++++--- LEGO1/mxvideopresenter.h | 2 + 8 files changed, 186 insertions(+), 50 deletions(-) diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp index de4d7006..59aadaff 100644 --- a/LEGO1/mxdisplaysurface.cpp +++ b/LEGO1/mxdisplaysurface.cpp @@ -224,20 +224,28 @@ void MxDisplaySurface::SetPalette(MxPalette* p_palette) } // STUB: LEGO1 0x100bacc0 -MxBool MxDisplaySurface::VTable0x28(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) +MxBool MxDisplaySurface::VTable0x28( + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height +) { return 0; } // STUB: LEGO1 0x100bb1d0 MxBool MxDisplaySurface::VTable0x30( - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height, MxBool ) { diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index 45714ce1..46732afe 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -39,7 +39,15 @@ class MxDisplaySurface : public MxCore { undefined4, undefined4 ); - virtual MxBool VTable0x28(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); + virtual MxBool VTable0x28( + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height + ); virtual MxBool VTable0x2c( LPDDSURFACEDESC, MxBitmap*, @@ -52,13 +60,13 @@ class MxDisplaySurface : public MxCore { MxBool ); virtual MxBool VTable0x30( - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height, MxBool ); virtual undefined4 VTable0x34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); diff --git a/LEGO1/mxrect32.h b/LEGO1/mxrect32.h index 7566a9ea..c05d5c67 100644 --- a/LEGO1/mxrect32.h +++ b/LEGO1/mxrect32.h @@ -16,13 +16,7 @@ class MxRect32 { this->m_bottom = p_bottom; } - MxRect32(const MxPoint32& p_point, const MxSize32& p_size) - { - this->m_left = p_point.GetX(); - this->m_top = p_point.GetY(); - this->m_right = p_size.GetWidth(); - this->m_bottom = p_size.GetHeight(); - } + MxRect32(const MxPoint32& p_point, const MxSize32& p_size) { CopyFrom(p_point, p_size); } MxRect32(const MxRect32& p_a, const MxRect32& p_b) { @@ -98,7 +92,6 @@ class MxRect32 { inline void SetRight(MxS32 p_right) { m_right = p_right; } inline void SetBottom(MxS32 p_bottom) { m_bottom = p_bottom; } -private: inline void CopyFrom(const MxRect32& p_rect) { this->m_left = p_rect.m_left; @@ -107,6 +100,15 @@ class MxRect32 { this->m_bottom = p_rect.m_bottom; } + inline void CopyFrom(const MxPoint32& p_point, const MxSize32& p_size) + { + this->m_left = p_point.GetX(); + this->m_top = p_point.GetY(); + this->m_right = p_size.GetWidth() + p_point.GetX(); + this->m_bottom = p_size.GetHeight() + p_point.GetY(); + } + +private: inline static MxS32 Min(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_a : p_b; }; inline static MxS32 Max(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_b : p_a; }; diff --git a/LEGO1/mxsize32.h b/LEGO1/mxsize32.h index a8b30368..2c0141bc 100644 --- a/LEGO1/mxsize32.h +++ b/LEGO1/mxsize32.h @@ -6,16 +6,18 @@ class MxSize32 { public: MxSize32() {} - MxSize32(MxS32 p_width, MxS32 p_height) - { - this->m_width = p_width; - this->m_height = p_height; - } + MxSize32(MxS32 p_width, MxS32 p_height) { Assign(p_width, p_height); } inline MxS32 GetWidth() const { return m_width; } inline MxS32 GetHeight() const { return m_height; } private: + inline void Assign(MxS32 p_width, MxS32 p_height) + { + this->m_width = p_width; + this->m_height = p_height; + } + MxS32 m_width; MxS32 m_height; }; diff --git a/LEGO1/mxstillpresenter.cpp b/LEGO1/mxstillpresenter.cpp index 5474f8e3..8b17207f 100644 --- a/LEGO1/mxstillpresenter.cpp +++ b/LEGO1/mxstillpresenter.cpp @@ -71,12 +71,7 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) { memcpy(m_bitmap->GetBitmapData(), p_chunk->GetData(), p_chunk->GetLength()); - MxS32 height = GetHeight() - 1; - MxS32 width = GetWidth() - 1; - MxS32 x = m_location.GetX(); - MxS32 y = m_location.GetY(); - - MxRect32 rect(x, y, width + x, height + y); + MxRect32 rect(m_location, MxSize32(GetWidth() - 1, GetHeight() - 1)); MVideoManager()->InvalidateRect(rect); if (m_flags & Flag_Bit2) { @@ -154,6 +149,7 @@ void MxStillPresenter::VTable0x88(MxS32 p_x, MxS32 p_y) m_location.SetY(p_y); if (IsEnabled()) { + // Most likely needs to work with MxSize32 and MxPoint32 MxS32 height = GetHeight() - 1; MxS32 width = GetWidth() - 1; @@ -174,12 +170,7 @@ void MxStillPresenter::Enable(MxBool p_enable) MxVideoPresenter::Enable(p_enable); if (MVideoManager() && (m_alpha || m_bitmap)) { - MxS32 height = GetHeight(); - MxS32 width = GetWidth(); - MxS32 x = m_location.GetX(); - MxS32 y = m_location.GetY(); - - MxRect32 rect(x, y, width + x, height + y); + MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); MVideoManager()->InvalidateRect(rect); MVideoManager()->VTable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); } diff --git a/LEGO1/mxvideomanager.h b/LEGO1/mxvideomanager.h index 6d03d84e..8d4d088c 100644 --- a/LEGO1/mxvideomanager.h +++ b/LEGO1/mxvideomanager.h @@ -40,6 +40,7 @@ class MxVideoManager : public MxMediaManager { inline MxVideoParam& GetVideoParam() { return this->m_videoParam; } inline LPDIRECTDRAW GetDirectDraw() { return this->m_pDirectDraw; } inline MxDisplaySurface* GetDisplaySurface() { return this->m_displaySurface; } + inline MxRegion* GetRegion() { return this->m_region; } protected: MxVideoParam m_videoParam; // 0x2c diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index 4162be43..957c5a01 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -2,6 +2,7 @@ #include "mxautolocker.h" #include "mxdsmediaaction.h" +#include "mxregioncursor.h" #include "mxvideomanager.h" DECOMP_SIZE_ASSERT(MxVideoPresenter, 0x64); @@ -214,13 +215,7 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor) } if (MVideoManager() && (m_alpha || m_bitmap)) { - MxS32 height = GetHeight(); - MxS32 width = GetWidth(); - - MxS32 x = m_location.GetX(); - MxS32 y = m_location.GetY(); - MxRect32 rect(x, y, x + width, y + height); - + MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); MVideoManager()->InvalidateRect(rect); MVideoManager()->VTable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); } @@ -312,10 +307,137 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) return TRUE; } -// STUB: LEGO1 0x100b2a70 +inline MxS32 MxVideoPresenter::PrepareRects(MxRect32& p_rectDest, MxRect32& p_rectSrc) +{ + if (p_rectDest.GetTop() > 480 || p_rectDest.GetLeft() > 640 || p_rectSrc.GetTop() > 480 || + p_rectSrc.GetLeft() > 640) + return -1; + + if (p_rectDest.GetBottom() > 480) + p_rectDest.SetBottom(480); + + if (p_rectDest.GetRight() > 640) + p_rectDest.SetRight(640); + + if (p_rectSrc.GetBottom() > 480) + p_rectSrc.SetBottom(480); + + if (p_rectSrc.GetRight() > 640) + p_rectSrc.SetRight(640); + + MxS32 height = p_rectDest.GetHeight(); + if (height <= 1) + return -1; + + MxS32 width = p_rectDest.GetWidth(); + if (width <= 1) + return -1; + + if (p_rectSrc.GetRight() - width - p_rectSrc.GetLeft() == -1 && + p_rectSrc.GetBottom() - height - p_rectSrc.GetTop() == -1) + return 1; + + p_rectSrc.SetRight(p_rectSrc.GetLeft() + width - 1); + p_rectSrc.SetBottom(p_rectSrc.GetTop() + height - 1); + return 0; +} + +// FUNCTION: LEGO1 0x100b2a70 void MxVideoPresenter::PutFrame() { - // TODO + MxDisplaySurface* displaySurface = MVideoManager()->GetDisplaySurface(); + MxRegion* region = MVideoManager()->GetRegion(); + MxRect32 rect(m_location, MxSize32(GetWidth() - 1, GetHeight() - 1)); + LPDIRECTDRAWSURFACE ddSurface = displaySurface->GetDirectDrawSurface2(); + + MxRect32 rectSrc, rectDest; + if (m_action->GetFlags() & MxDSAction::Flag_Bit5) { + if (m_unk0x58) { + // TODO: Match + rectSrc.CopyFrom(MxPoint32(0, 0), MxSize32(GetWidth(), GetHeight())); + rectDest.CopyFrom(m_location, MxSize32(GetWidth(), GetHeight())); + + switch (PrepareRects(rectDest, rectSrc)) { + case 0: + ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, DDBLT_KEYSRC, NULL); + break; + case 1: + ddSurface->BltFast( + rectDest.GetLeft(), + rectDest.GetTop(), + m_unk0x58, + (LPRECT) &rectSrc, + DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT + ); + } + } + else { + displaySurface->VTable0x30( + m_bitmap, + 0, + 0, + rect.GetLeft(), + rect.GetTop(), + m_bitmap->GetBmiWidth(), + m_bitmap->GetBmiHeightAbs(), + TRUE + ); + } + } + else { + MxRegionCursor cursor(region); + MxRect32* regionRect; + + while (regionRect = cursor.VTable0x24(rect)) { + if (regionRect->GetWidth() >= 1 && regionRect->GetHeight() >= 1) { + if (m_unk0x58) { + // TODO: Match + rectSrc.CopyFrom( + MxPoint32(regionRect->GetLeft() - m_location.GetX(), regionRect->GetTop() - m_location.GetY()), + MxSize32(regionRect->GetWidth(), regionRect->GetHeight()) + ); + rectDest.CopyFrom( + MxPoint32(regionRect->GetLeft(), regionRect->GetTop()), + MxSize32(regionRect->GetWidth(), regionRect->GetHeight()) + ); + } + + if (m_action->GetFlags() & MxDSAction::Flag_Bit4) { + if (m_unk0x58) { + if (PrepareRects(rectDest, rectSrc) >= 0) + ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, DDBLT_KEYSRC, NULL); + } + else { + displaySurface->VTable0x30( + m_bitmap, + regionRect->GetLeft() - m_location.GetX(), + regionRect->GetTop() - m_location.GetY(), + regionRect->GetLeft(), + regionRect->GetTop(), + regionRect->GetWidth(), + regionRect->GetHeight(), + FALSE + ); + } + } + else if (m_unk0x58) { + if (PrepareRects(rectDest, rectSrc) >= 0) + ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, 0, NULL); + } + else { + displaySurface->VTable0x28( + m_bitmap, + regionRect->GetLeft() - m_location.GetX(), + regionRect->GetTop() - m_location.GetY(), + regionRect->GetLeft(), + regionRect->GetTop(), + regionRect->GetWidth(), + regionRect->GetHeight() + ); + } + } + } + } } // FUNCTION: LEGO1 0x100b2f60 diff --git a/LEGO1/mxvideopresenter.h b/LEGO1/mxvideopresenter.h index 72ea33d8..f02f3f08 100644 --- a/LEGO1/mxvideopresenter.h +++ b/LEGO1/mxvideopresenter.h @@ -4,6 +4,7 @@ #include "decomp.h" #include "mxbitmap.h" #include "mxmediapresenter.h" +#include "mxrect32.h" // VTABLE: LEGO1 0x100d4be8 // SIZE 0x64 @@ -68,6 +69,7 @@ class MxVideoPresenter : public MxMediaPresenter { MxS32 IsHit(MxU32 p_x, MxU32 p_y); }; + inline MxS32 PrepareRects(MxRect32& p_rectDest, MxRect32& p_rectSrc); inline MxBitmap* GetBitmap() { return m_bitmap; } private: From a8837a72cf12ebc9d272e89e1b98d90ed8133c73 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Dec 2023 17:34:10 -0500 Subject: [PATCH 43/50] MxVideoPresenter::GetHeight hotfix --- LEGO1/mxvideopresenter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index 957c5a01..cac090b1 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -59,13 +59,13 @@ MxBool MxVideoPresenter::VTable0x7c() // FUNCTION: LEGO1 0x1000c7e0 MxS32 MxVideoPresenter::GetWidth() { - return m_alpha ? m_alpha->m_width : m_bitmap->GetBmiHeader()->biWidth; + return m_alpha ? m_alpha->m_width : m_bitmap->GetBmiWidth(); } // FUNCTION: LEGO1 0x1000c800 MxS32 MxVideoPresenter::GetHeight() { - return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeader()->biHeight; + return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeightAbs(); } // FUNCTION: LEGO1 0x100b24f0 From 6ac505fb4913518bafa961ff3aac18a47f56dd73 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Dec 2023 17:59:09 -0500 Subject: [PATCH 44/50] Add missing annotations to MxDisplaySurface --- LEGO1/mxdisplaysurface.h | 62 ++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index 46732afe..aed5b24a 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -16,19 +16,15 @@ class MxDisplaySurface : public MxCore { MxDisplaySurface(); virtual ~MxDisplaySurface() override; - void Reset(); - - void FUN_100ba640(); - virtual MxResult Init( MxVideoParam& p_videoParam, LPDIRECTDRAWSURFACE p_ddSurface1, LPDIRECTDRAWSURFACE p_ddSurface2, LPDIRECTDRAWCLIPPER p_ddClipper - ); - virtual MxResult Create(MxVideoParam& p_videoParam); - virtual void Clear(); - virtual void SetPalette(MxPalette* p_palette); + ); // vtable+0x14 + virtual MxResult Create(MxVideoParam& p_videoParam); // vtable+0x18 + virtual void Clear(); // vtable+0x1c + virtual void SetPalette(MxPalette* p_palette); // vtable+0x20 virtual void VTable0x24( LPDDSURFACEDESC, MxBitmap*, @@ -38,7 +34,7 @@ class MxDisplaySurface : public MxCore { undefined4, undefined4, undefined4 - ); + ); // vtable+0x24 virtual MxBool VTable0x28( MxBitmap* p_bitmap, MxS32 p_left, @@ -47,7 +43,7 @@ class MxDisplaySurface : public MxCore { MxS32 p_bottom, MxS32 p_width, MxS32 p_height - ); + ); // vtable+0x28 virtual MxBool VTable0x2c( LPDDSURFACEDESC, MxBitmap*, @@ -58,7 +54,7 @@ class MxDisplaySurface : public MxCore { undefined4, undefined4, MxBool - ); + ); // vtable+0x2c virtual MxBool VTable0x30( MxBitmap* p_bitmap, MxS32 p_left, @@ -68,25 +64,43 @@ class MxDisplaySurface : public MxCore { MxS32 p_width, MxS32 p_height, MxBool - ); - virtual undefined4 VTable0x34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); - virtual void Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height); - virtual void GetDC(HDC* p_hdc); - virtual void ReleaseDC(HDC p_hdc); - virtual LPDIRECTDRAWSURFACE VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4); + ); // vtable+0x30 + virtual undefined4 VTable0x34( + undefined4, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4 + ); // vtable+0x34 + virtual void Display( + MxS32 p_left, + MxS32 p_top, + MxS32 p_left2, + MxS32 p_top2, + MxS32 p_width, + MxS32 p_height + ); // vtable+0x38 + virtual void GetDC(HDC* p_hdc); // vtable+0x3c + virtual void ReleaseDC(HDC p_hdc); // vtable+0x40 + virtual LPDIRECTDRAWSURFACE VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4); // vtable+0x44 + + void FUN_100ba640(); inline LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return this->m_ddSurface1; } inline LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return this->m_ddSurface2; } inline MxVideoParam& GetVideoParam() { return this->m_videoParam; } private: - MxVideoParam m_videoParam; - LPDIRECTDRAWSURFACE m_ddSurface1; - LPDIRECTDRAWSURFACE m_ddSurface2; - LPDIRECTDRAWCLIPPER m_ddClipper; - MxBool m_initialized; - DDSURFACEDESC m_surfaceDesc; - MxU16* m_16bitPal; + void Reset(); + + MxVideoParam m_videoParam; // 0x08 + LPDIRECTDRAWSURFACE m_ddSurface1; // 0x2c + LPDIRECTDRAWSURFACE m_ddSurface2; // 0x30 + LPDIRECTDRAWCLIPPER m_ddClipper; // 0x34 + MxBool m_initialized; // 0x38 + DDSURFACEDESC m_surfaceDesc; // 0x3c + MxU16* m_16bitPal; // 0xa8 }; #endif // MXDISPLAYSURFACE_H From 4b08cb4a7ed0a190afc76261a7391a8f3135e99b Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Dec 2023 18:01:24 -0500 Subject: [PATCH 45/50] Rename functions for consistency --- LEGO1/mxdisplaysurface.cpp | 10 +++++----- LEGO1/mxdisplaysurface.h | 7 +++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp index 59aadaff..0aec323e 100644 --- a/LEGO1/mxdisplaysurface.cpp +++ b/LEGO1/mxdisplaysurface.cpp @@ -10,17 +10,17 @@ MxU32 g_unk0x1010215c = 0; // FUNCTION: LEGO1 0x100ba500 MxDisplaySurface::MxDisplaySurface() { - this->Reset(); + this->Init(); } // FUNCTION: LEGO1 0x100ba5a0 MxDisplaySurface::~MxDisplaySurface() { - this->Clear(); + this->Destroy(); } // FUNCTION: LEGO1 0x100ba610 -void MxDisplaySurface::Reset() +void MxDisplaySurface::Init() { this->m_ddSurface1 = NULL; this->m_ddSurface2 = NULL; @@ -199,7 +199,7 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) } // FUNCTION: LEGO1 0x100baa90 -void MxDisplaySurface::Clear() +void MxDisplaySurface::Destroy() { if (this->m_initialized) { if (this->m_ddSurface2) @@ -215,7 +215,7 @@ void MxDisplaySurface::Clear() if (this->m_16bitPal) delete this->m_16bitPal; - this->Reset(); + this->Init(); } // STUB: LEGO1 0x100baae0 diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h index aed5b24a..39a2fda8 100644 --- a/LEGO1/mxdisplaysurface.h +++ b/LEGO1/mxdisplaysurface.h @@ -23,7 +23,7 @@ class MxDisplaySurface : public MxCore { LPDIRECTDRAWCLIPPER p_ddClipper ); // vtable+0x14 virtual MxResult Create(MxVideoParam& p_videoParam); // vtable+0x18 - virtual void Clear(); // vtable+0x1c + virtual void Destroy(); // vtable+0x1c virtual void SetPalette(MxPalette* p_palette); // vtable+0x20 virtual void VTable0x24( LPDDSURFACEDESC, @@ -92,7 +92,7 @@ class MxDisplaySurface : public MxCore { inline MxVideoParam& GetVideoParam() { return this->m_videoParam; } private: - void Reset(); + void Init(); MxVideoParam m_videoParam; // 0x08 LPDIRECTDRAWSURFACE m_ddSurface1; // 0x2c @@ -103,4 +103,7 @@ class MxDisplaySurface : public MxCore { MxU16* m_16bitPal; // 0xa8 }; +// SYNTHETIC: LEGO1 0x100ba580 +// MxDisplaySurface::`scalar deleting destructor' + #endif // MXDISPLAYSURFACE_H From c890831c41f5e473661db03fd6147ce35886d5d0 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Dec 2023 18:04:54 -0500 Subject: [PATCH 46/50] Remove obsolete comment --- LEGO1/mxdiskstreamcontroller.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/LEGO1/mxdiskstreamcontroller.cpp b/LEGO1/mxdiskstreamcontroller.cpp index f992443d..a7e95798 100644 --- a/LEGO1/mxdiskstreamcontroller.cpp +++ b/LEGO1/mxdiskstreamcontroller.cpp @@ -372,7 +372,6 @@ void MxDiskStreamController::FUN_100c8540() MxAutoLocker lock(&this->m_criticalSection); for (list::iterator it = m_list0x74.begin(); it != m_list0x74.end();) { MxDSBuffer* buf = *it; - // TODO: Match if (buf->GetRefCount() == 0) { m_list0x74.erase(it++); FUN_100c7ce0(buf); From 562d6a966eac11f9c1d0916f8a03b32769ab5067 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Dec 2023 18:33:30 -0500 Subject: [PATCH 47/50] Match MxRAMStreamProvider::SetResourceToGet --- LEGO1/mxramstreamprovider.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LEGO1/mxramstreamprovider.cpp b/LEGO1/mxramstreamprovider.cpp index 9c52c20e..fc20bf33 100644 --- a/LEGO1/mxramstreamprovider.cpp +++ b/LEGO1/mxramstreamprovider.cpp @@ -77,14 +77,14 @@ MxResult MxRAMStreamProvider::SetResourceToGet(MxStreamController* p_resource) m_fileSize = m_pFile->CalcFileSize(); if (m_fileSize != 0) { m_bufferSize = m_pFile->GetBufferSize(); - m_pBufferOfFileSize = new MxU32[m_fileSize]; + m_pBufferOfFileSize = (MxU32*) new MxU8[m_fileSize]; if (m_pBufferOfFileSize != NULL && m_pFile->Read((unsigned char*) m_pBufferOfFileSize, m_fileSize) == SUCCESS) { m_lengthInDWords = m_pFile->GetLengthInDWords(); - m_bufferForDWords = new MxU32[m_lengthInDWords * sizeof(MxU32)]; + m_bufferForDWords = new MxU32[m_lengthInDWords]; if (m_bufferForDWords != NULL) { - memcpy(m_bufferForDWords, m_pFile->GetBuffer(), m_lengthInDWords); + memcpy(m_bufferForDWords, m_pFile->GetBuffer(), m_lengthInDWords * sizeof(MxU32)); result = SUCCESS; } } From 56687e86fbdc4e95d188aa657d888792a9bae05b Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Dec 2023 18:40:54 -0500 Subject: [PATCH 48/50] Mostly match MxStreamer::Close --- LEGO1/mxstreamer.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/LEGO1/mxstreamer.cpp b/LEGO1/mxstreamer.cpp index 1688c1b8..add5adcc 100644 --- a/LEGO1/mxstreamer.cpp +++ b/LEGO1/mxstreamer.cpp @@ -79,14 +79,10 @@ MxLong MxStreamer::Close(const char* p_name) if (!p_name || !strcmp(p_name, c->GetAtom().GetInternal())) { m_openStreams.erase(it); - if (!c->FUN_100c20d0(ds)) { - MxStreamerNotification notif(MXSTREAMER_DELETE_NOTIFY, NULL, c); - - NotificationManager()->Send(this, ¬if); - } - else { + if (c->FUN_100c20d0(ds)) delete c; - } + else + NotificationManager()->Send(this, &MxStreamerNotification(MXSTREAMER_DELETE_NOTIFY, NULL, c)); return SUCCESS; } From b4b73465d0f244099be2a17a90870abc724b72a8 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Dec 2023 18:44:46 -0500 Subject: [PATCH 49/50] Mostly match MxStreamer::Notify --- LEGO1/mxstreamer.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/LEGO1/mxstreamer.cpp b/LEGO1/mxstreamer.cpp index add5adcc..cd2272c6 100644 --- a/LEGO1/mxstreamer.cpp +++ b/LEGO1/mxstreamer.cpp @@ -183,13 +183,10 @@ MxLong MxStreamer::Notify(MxParam& p_param) MxStreamController* c = static_cast(p_param).GetController(); - if (!c->FUN_100c20d0(ds)) { - MxStreamerNotification notif(MXSTREAMER_DELETE_NOTIFY, NULL, c); - NotificationManager()->Send(this, ¬if); - } - else { + if (c->FUN_100c20d0(ds)) delete c; - } + else + NotificationManager()->Send(this, &MxStreamerNotification(MXSTREAMER_DELETE_NOTIFY, NULL, c)); } return 0; From bb22b2126014884d917dc67824761424bbcded2f Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Dec 2023 23:55:36 -0500 Subject: [PATCH 50/50] Implement `FUN_100b6e10` and MxRect32 adjustments (#390) * Some WIP rect * Adjustments to MxRect32 * Spacing * Changes * Spacing * Spacing --- LEGO1/legoomni.cpp | 46 ++++++++++++++++++++++++++++++++++++++ LEGO1/legoomni.h | 13 +++++++++++ LEGO1/mxpoint32.h | 17 +++++++------- LEGO1/mxrect32.h | 37 +++++++++++++++++------------- LEGO1/mxsize32.h | 4 ++-- LEGO1/mxstillpresenter.cpp | 16 +++++++++++-- LEGO1/mxvideopresenter.cpp | 37 +++++++++++++++++++----------- 7 files changed, 129 insertions(+), 41 deletions(-) diff --git a/LEGO1/legoomni.cpp b/LEGO1/legoomni.cpp index ddf0e454..48c7a1f5 100644 --- a/LEGO1/legoomni.cpp +++ b/LEGO1/legoomni.cpp @@ -695,6 +695,52 @@ MxResult Start(MxDSAction* p_dsAction) return MxOmni::GetInstance()->Start(p_dsAction); } +// Probably should be somewhere else +// FUNCTION: LEGO1 0x100b6e10 +MxBool FUN_100b6e10( + MxS32 p_bitmapWidth, + MxS32 p_bitmapHeight, + MxS32 p_videoParamWidth, + MxS32 p_videoParamHeight, + MxS32* p_left, + MxS32* p_top, + MxS32* p_right, + MxS32* p_bottom, + MxS32* p_width, + MxS32* p_height +) +{ + MxPoint32 topLeft(*p_left, *p_top); + MxRect32 bitmapRect(MxPoint32(0, 0), MxSize32(p_bitmapWidth, p_bitmapHeight)); + + MxPoint32 bottomRight(*p_right, *p_bottom); + MxRect32 videoParamRect(MxPoint32(0, 0), MxSize32(p_videoParamWidth, p_videoParamHeight)); + + MxRect32 rect(0, 0, *p_width, *p_height); + rect.AddPoint(topLeft); + + if (!rect.IntersectsWith(bitmapRect)) + return FALSE; + + rect.Intersect(bitmapRect); + rect.SubtractPoint(topLeft); + rect.AddPoint(bottomRight); + + if (!rect.IntersectsWith(videoParamRect)) + return FALSE; + + rect.Intersect(videoParamRect); + rect.SubtractPoint(bottomRight); + + *p_left += rect.GetLeft(); + *p_top += rect.GetTop(); + *p_right += rect.GetLeft(); + *p_bottom += rect.GetTop(); + *p_width = rect.GetWidth(); + *p_height = rect.GetHeight(); + return TRUE; +} + // FUNCTION: LEGO1 0x100b6ff0 void MakeSourceName(char* p_output, const char* p_input) { diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index dff06fb5..2aaba4cc 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -166,6 +166,19 @@ void FUN_10015820(MxU32, MxU32); LegoEntity* FindEntityByAtomIdOrEntityId(const MxAtomId& p_atom, MxS32 p_entityid); MxDSAction& GetCurrentAction(); +MxBool FUN_100b6e10( + MxS32 p_bitmapWidth, + MxS32 p_bitmapHeight, + MxS32 p_videoParamWidth, + MxS32 p_videoParamHeight, + MxS32* p_left, + MxS32* p_top, + MxS32* p_right, + MxS32* p_bottom, + MxS32* p_width, + MxS32* p_height +); + void PlayMusic(MxU32 p_index); void SetIsWorldActive(MxBool p_isWorldActive); void RegisterScripts(); diff --git a/LEGO1/mxpoint32.h b/LEGO1/mxpoint32.h index d041e894..37c6dd19 100755 --- a/LEGO1/mxpoint32.h +++ b/LEGO1/mxpoint32.h @@ -6,12 +6,7 @@ class MxPoint32 { public: MxPoint32() {} - MxPoint32(MxS32 p_x, MxS32 p_y) - { - this->m_x = p_x; - this->m_y = p_y; - } - + MxPoint32(MxS32 p_x, MxS32 p_y) { CopyFrom(p_x, p_y); } MxPoint32(const MxPoint32& p_point) { this->m_x = p_point.m_x; @@ -25,8 +20,14 @@ class MxPoint32 { inline void SetY(MxS32 p_y) { m_y = p_y; } private: - MxS32 m_x; - MxS32 m_y; + inline void CopyFrom(MxS32 p_x, MxS32 p_y) + { + this->m_x = p_x; + this->m_y = p_y; + } + + MxS32 m_x; // 0x00 + MxS32 m_y; // 0x04 }; #endif // MXPOINT32_H diff --git a/LEGO1/mxrect32.h b/LEGO1/mxrect32.h index c05d5c67..b52a0c31 100644 --- a/LEGO1/mxrect32.h +++ b/LEGO1/mxrect32.h @@ -8,16 +8,8 @@ class MxRect32 { public: MxRect32() {} - MxRect32(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) - { - this->m_left = p_left; - this->m_top = p_top; - this->m_right = p_right; - this->m_bottom = p_bottom; - } - + MxRect32(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) { CopyFrom(p_left, p_top, p_right, p_bottom); } MxRect32(const MxPoint32& p_point, const MxSize32& p_size) { CopyFrom(p_point, p_size); } - MxRect32(const MxRect32& p_a, const MxRect32& p_b) { m_left = Max(p_a.m_left, p_b.m_left); @@ -56,10 +48,12 @@ class MxRect32 { this->m_bottom += p_point.GetY(); } - inline void SetSize(const MxSize32& p_size) + inline void SubtractPoint(const MxPoint32& p_point) { - this->m_right = p_size.GetWidth(); - this->m_bottom = p_size.GetHeight(); + this->m_left -= p_point.GetX(); + this->m_top -= p_point.GetY(); + this->m_right -= p_point.GetX(); + this->m_bottom -= p_point.GetY(); } inline void UpdateBounds(const MxRect32& p_rect) @@ -92,6 +86,15 @@ class MxRect32 { inline void SetRight(MxS32 p_right) { m_right = p_right; } inline void SetBottom(MxS32 p_bottom) { m_bottom = p_bottom; } +private: + inline void CopyFrom(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) + { + this->m_left = p_left; + this->m_top = p_top; + this->m_right = p_right; + this->m_bottom = p_bottom; + } + inline void CopyFrom(const MxRect32& p_rect) { this->m_left = p_rect.m_left; @@ -100,15 +103,17 @@ class MxRect32 { this->m_bottom = p_rect.m_bottom; } - inline void CopyFrom(const MxPoint32& p_point, const MxSize32& p_size) + // The address might also be the constructor that calls CopyFrom + // FUNCTION: LEGO1 0x100b6fc0 + inline MxRect32* CopyFrom(const MxPoint32& p_point, const MxSize32& p_size) { this->m_left = p_point.GetX(); this->m_top = p_point.GetY(); - this->m_right = p_size.GetWidth() + p_point.GetX(); - this->m_bottom = p_size.GetHeight() + p_point.GetY(); + this->m_right = p_size.GetWidth() + p_point.GetX() - 1; + this->m_bottom = p_size.GetHeight() + p_point.GetY() - 1; + return this; } -private: inline static MxS32 Min(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_a : p_b; }; inline static MxS32 Max(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_b : p_a; }; diff --git a/LEGO1/mxsize32.h b/LEGO1/mxsize32.h index 2c0141bc..8fb90210 100644 --- a/LEGO1/mxsize32.h +++ b/LEGO1/mxsize32.h @@ -6,13 +6,13 @@ class MxSize32 { public: MxSize32() {} - MxSize32(MxS32 p_width, MxS32 p_height) { Assign(p_width, p_height); } + MxSize32(MxS32 p_width, MxS32 p_height) { CopyFrom(p_width, p_height); } inline MxS32 GetWidth() const { return m_width; } inline MxS32 GetHeight() const { return m_height; } private: - inline void Assign(MxS32 p_width, MxS32 p_height) + inline void CopyFrom(MxS32 p_width, MxS32 p_height) { this->m_width = p_width; this->m_height = p_height; diff --git a/LEGO1/mxstillpresenter.cpp b/LEGO1/mxstillpresenter.cpp index 8b17207f..ee659827 100644 --- a/LEGO1/mxstillpresenter.cpp +++ b/LEGO1/mxstillpresenter.cpp @@ -71,7 +71,13 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) { memcpy(m_bitmap->GetBitmapData(), p_chunk->GetData(), p_chunk->GetLength()); - MxRect32 rect(m_location, MxSize32(GetWidth() - 1, GetHeight() - 1)); + // MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); + MxS32 height = GetHeight() - 1; + MxS32 width = GetWidth() - 1; + MxS32 x = m_location.GetX(); + MxS32 y = m_location.GetY(); + + MxRect32 rect(x, y, width + x, height + y); MVideoManager()->InvalidateRect(rect); if (m_flags & Flag_Bit2) { @@ -170,7 +176,13 @@ void MxStillPresenter::Enable(MxBool p_enable) MxVideoPresenter::Enable(p_enable); if (MVideoManager() && (m_alpha || m_bitmap)) { - MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); + // MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); + MxS32 height = GetHeight(); + MxS32 width = GetWidth(); + MxS32 x = m_location.GetX(); + MxS32 y = m_location.GetY(); + + MxRect32 rect(x, y, width + x, height + y); MVideoManager()->InvalidateRect(rect); MVideoManager()->VTable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); } diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/mxvideopresenter.cpp index cac090b1..0e4f3d5b 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/mxvideopresenter.cpp @@ -215,7 +215,13 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor) } if (MVideoManager() && (m_alpha || m_bitmap)) { - MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); + // MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); + MxS32 height = GetHeight(); + MxS32 width = GetWidth(); + MxS32 x = m_location.GetX(); + MxS32 y = m_location.GetY(); + + MxRect32 rect(x, y, x + width, y + height); MVideoManager()->InvalidateRect(rect); MVideoManager()->VTable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); } @@ -347,15 +353,20 @@ void MxVideoPresenter::PutFrame() { MxDisplaySurface* displaySurface = MVideoManager()->GetDisplaySurface(); MxRegion* region = MVideoManager()->GetRegion(); - MxRect32 rect(m_location, MxSize32(GetWidth() - 1, GetHeight() - 1)); + MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); LPDIRECTDRAWSURFACE ddSurface = displaySurface->GetDirectDrawSurface2(); MxRect32 rectSrc, rectDest; if (m_action->GetFlags() & MxDSAction::Flag_Bit5) { if (m_unk0x58) { // TODO: Match - rectSrc.CopyFrom(MxPoint32(0, 0), MxSize32(GetWidth(), GetHeight())); - rectDest.CopyFrom(m_location, MxSize32(GetWidth(), GetHeight())); + rectSrc.SetPoint(MxPoint32(0, 0)); + rectSrc.SetRight(GetWidth()); + rectSrc.SetBottom(GetHeight()); + + rectDest.SetPoint(m_location); + rectDest.SetRight(rectDest.GetLeft() + GetWidth()); + rectDest.SetBottom(rectDest.GetTop() + GetHeight()); switch (PrepareRects(rectDest, rectSrc)) { case 0: @@ -391,15 +402,15 @@ void MxVideoPresenter::PutFrame() while (regionRect = cursor.VTable0x24(rect)) { if (regionRect->GetWidth() >= 1 && regionRect->GetHeight() >= 1) { if (m_unk0x58) { - // TODO: Match - rectSrc.CopyFrom( - MxPoint32(regionRect->GetLeft() - m_location.GetX(), regionRect->GetTop() - m_location.GetY()), - MxSize32(regionRect->GetWidth(), regionRect->GetHeight()) - ); - rectDest.CopyFrom( - MxPoint32(regionRect->GetLeft(), regionRect->GetTop()), - MxSize32(regionRect->GetWidth(), regionRect->GetHeight()) - ); + rectSrc.SetLeft(regionRect->GetLeft() - m_location.GetX()); + rectSrc.SetTop(regionRect->GetTop() - m_location.GetY()); + rectSrc.SetRight(rectSrc.GetLeft() + regionRect->GetWidth()); + rectSrc.SetBottom(rectSrc.GetTop() + regionRect->GetHeight()); + + rectDest.SetLeft(regionRect->GetLeft()); + rectDest.SetTop(regionRect->GetTop()); + rectDest.SetRight(rectDest.GetLeft() + regionRect->GetWidth()); + rectDest.SetBottom(rectDest.GetTop() + regionRect->GetHeight()); } if (m_action->GetFlags() & MxDSAction::Flag_Bit4) {