From 9f875d01e5b02b939d3687c2335c9aead8fdd1c2 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sat, 9 Mar 2024 12:27:53 -0500 Subject: [PATCH] Implement/match LegoPartPresenter::Read (#642) * WIP * Match * Remove TODO * Fix --- LEGO1/lego/legoomni/include/legolodlist.h | 52 ++++++ LEGO1/lego/legoomni/include/legonamedpart.h | 26 +++ .../lego/legoomni/include/legonamedpartlist.h | 53 ++++++ .../lego/legoomni/include/legopartpresenter.h | 5 +- .../legoomni/include/legoworldpresenter.h | 5 +- .../legoomni/src/video/legomodelpresenter.cpp | 3 +- .../legoomni/src/video/legopartpresenter.cpp | 174 +++++++++++++++++- .../src/video/legotexturepresenter.cpp | 1 + 8 files changed, 311 insertions(+), 8 deletions(-) create mode 100644 LEGO1/lego/legoomni/include/legolodlist.h create mode 100644 LEGO1/lego/legoomni/include/legonamedpart.h create mode 100644 LEGO1/lego/legoomni/include/legonamedpartlist.h diff --git a/LEGO1/lego/legoomni/include/legolodlist.h b/LEGO1/lego/legoomni/include/legolodlist.h new file mode 100644 index 00000000..b9e52096 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legolodlist.h @@ -0,0 +1,52 @@ +#ifndef LEGOLODLIST_H +#define LEGOLODLIST_H + +#include "mxlist.h" +#include "roi/legolod.h" + +#pragma warning(disable : 4786) + +// VTABLE: LEGO1 0x100d9d30 +// class MxCollection + +// VTABLE: LEGO1 0x100d9d48 +// class MxList + +// VTABLE: LEGO1 0x100d9d60 +// class MxPtrList + +// VTABLE: LEGO1 0x100d9d78 +// SIZE 0x18 +class LegoLODList : public MxPtrList { +public: + LegoLODList() : MxPtrList(FALSE) {} + + // SYNTHETIC: LEGO1 0x1007de40 + // LegoLODList::`scalar deleting destructor' +}; + +// TEMPLATE: LEGO1 0x1007d480 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x1007d490 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x1007d4e0 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x1007d4f0 +// MxList::~MxList + +// SYNTHETIC: LEGO1 0x1007d580 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1007d5f0 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1007d6a0 +// MxPtrList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1007d710 +// MxPtrList::~MxPtrList + +#endif // LEGOLODLIST_H diff --git a/LEGO1/lego/legoomni/include/legonamedpart.h b/LEGO1/lego/legoomni/include/legonamedpart.h new file mode 100644 index 00000000..876090e2 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legonamedpart.h @@ -0,0 +1,26 @@ +#ifndef LEGONAMEDPART_H +#define LEGONAMEDPART_H + +#include "legolodlist.h" +#include "mxstring.h" + +// SIZE 0x14 +class LegoNamedPart { +public: + LegoNamedPart(const char* p_name, LegoLODList* p_list) + { + m_name = p_name; + m_list = p_list; + } + ~LegoNamedPart() { delete m_list; } + + const MxString* GetName() const { return &m_name; } + + LegoLODList* GetList() { return m_list; } + +private: + MxString m_name; // 0x00 + LegoLODList* m_list; // 0x04 +}; + +#endif // LEGONAMEDPART_H diff --git a/LEGO1/lego/legoomni/include/legonamedpartlist.h b/LEGO1/lego/legoomni/include/legonamedpartlist.h new file mode 100644 index 00000000..ddab4f67 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legonamedpartlist.h @@ -0,0 +1,53 @@ +#ifndef LEGONAMEDPARTLIST_H +#define LEGONAMEDPARTLIST_H + +#include "legonamedpart.h" +#include "mxlist.h" + +// VTABLE: LEGO1 0x100d9d90 +// class MxCollection + +// VTABLE: LEGO1 0x100d9da8 +// class MxList + +// VTABLE: LEGO1 0x100d9dc0 +// class MxPtrList + +// VTABLE: LEGO1 0x100d9dd8 +// SIZE 0x18 +class LegoNamedPartList : public MxPtrList { +public: + LegoNamedPartList() : MxPtrList(TRUE) {} + + // SYNTHETIC: LEGO1 0x1007dbf0 + // LegoNamedPartList::`scalar deleting destructor' +}; + +// TEMPLATE: LEGO1 0x1007d760 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x1007d770 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x1007d7c0 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x1007d7d0 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x1007d860 +// MxPtrList::Destroy + +// TEMPLATE: LEGO1 0x1007dc60 +// MxPtrList::~MxPtrList + +// SYNTHETIC: LEGO1 0x1007dcb0 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1007dd20 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1007ddd0 +// MxPtrList::`scalar deleting destructor' + +#endif // LEGONAMEDPARTLIST_H diff --git a/LEGO1/lego/legoomni/include/legopartpresenter.h b/LEGO1/lego/legoomni/include/legopartpresenter.h index 8f3cda07..ac1fcc5e 100644 --- a/LEGO1/lego/legoomni/include/legopartpresenter.h +++ b/LEGO1/lego/legoomni/include/legopartpresenter.h @@ -1,6 +1,7 @@ #ifndef LEGOPARTPRESENTER_H #define LEGOPARTPRESENTER_H +#include "legonamedpartlist.h" #include "mxmediapresenter.h" // VTABLE: LEGO1 0x100d4df0 @@ -34,7 +35,7 @@ public: // SYNTHETIC: LEGO1 0x1000d060 // LegoPartPresenter::`scalar deleting destructor' - inline void Reset() { m_partData = NULL; } + inline void Reset() { m_parts = NULL; } MxResult Read(MxDSChunk& p_chunk); void FUN_1007df20(); @@ -42,7 +43,7 @@ public: private: void Destroy(MxBool p_fromDestructor); - MxDSChunk* m_partData; // 0x54 + LegoNamedPartList* m_parts; // 0x50 }; #endif // LEGOPARTPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoworldpresenter.h b/LEGO1/lego/legoomni/include/legoworldpresenter.h index e101acfb..831b64f5 100644 --- a/LEGO1/lego/legoomni/include/legoworldpresenter.h +++ b/LEGO1/lego/legoomni/include/legoworldpresenter.h @@ -37,14 +37,15 @@ public: MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 - MxResult FUN_10067360(ModelDbPart& p_part, FILE* p_wdbFile); - MxResult FUN_100674b0(ModelDbModel& p_model, FILE* p_wdbFile, LegoWorld* p_world); MxResult LoadWorld(char* p_worldName, LegoWorld* p_world); // SYNTHETIC: LEGO1 0x10066750 // LegoWorldPresenter::`scalar deleting destructor' private: + MxResult FUN_10067360(ModelDbPart& p_part, FILE* p_wdbFile); + MxResult FUN_100674b0(ModelDbModel& p_model, FILE* p_wdbFile, LegoWorld* p_world); + undefined4 m_unk0x50; }; diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index 8e3daf69..76f994c9 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -63,6 +63,7 @@ MxResult LegoModelPresenter::CreateROI(MxDSChunk* p_chunk) MxMatrix mat; LegoChar* textureName = NULL; LegoTexture* texture = NULL; + LegoTextureInfo* textureInfo = NULL; LegoS32 hardwareMode = VideoManager()->GetDirect3D()->AssignedDevice()->GetHardwareMode(); if (m_roi) { @@ -137,7 +138,7 @@ MxResult LegoModelPresenter::CreateROI(MxDSChunk* p_chunk) if (!skipTextures) { if (TextureContainer()->Get(textureName) == NULL) { - LegoTextureInfo* textureInfo = LegoTextureInfo::Create(textureName, texture); + textureInfo = LegoTextureInfo::Create(textureName, texture); if (textureInfo == NULL) { goto done; diff --git a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp index e121e475..a41c4164 100644 --- a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp @@ -2,6 +2,13 @@ #include "legoomni.h" #include "legovideomanager.h" +#include "misc/legocontainer.h" +#include "misc/legostorage.h" +#include "misc/legotexture.h" + +DECOMP_SIZE_ASSERT(LegoLODList, 0x18) +DECOMP_SIZE_ASSERT(LegoNamedPart, 0x14) +DECOMP_SIZE_ASSERT(LegoNamedPartList, 0x18) // GLOBAL: LEGO1 0x100f7aa0 MxS32 g_partPresenterConfig1 = 1; @@ -35,11 +42,172 @@ void LegoPartPresenter::Destroy(MxBool p_fromDestructor) // TODO } -// STUB: LEGO1 0x1007ca30 +// FUNCTION: LEGO1 0x1007ca30 MxResult LegoPartPresenter::Read(MxDSChunk& p_chunk) { - // TODO - return SUCCESS; + MxResult result = FAILURE; + LegoU32 numROIs, numLODs; + LegoMemory storage(p_chunk.GetData()); + LegoU32 textureInfoOffset, i, j, numTextures; + LegoU32 roiNameLength, roiInfoOffset, surplusLODs; + LegoLODList* lods; + LegoNamedPart* namedPart; + LegoChar* roiName = NULL; + LegoChar* textureName = NULL; + LegoTexture* texture = NULL; + LegoTextureInfo* textureInfo = NULL; + LegoS32 hardwareMode = VideoManager()->GetDirect3D()->AssignedDevice()->GetHardwareMode(); + + if (storage.Read(&textureInfoOffset, sizeof(textureInfoOffset)) != SUCCESS) { + goto done; + } + if (storage.SetPosition(textureInfoOffset) != SUCCESS) { + goto done; + } + if (storage.Read(&numTextures, sizeof(numTextures)) != SUCCESS) { + goto done; + } + + for (i = 0; i < numTextures; i++) { + LegoU32 textureNameLength; + + storage.Read(&textureNameLength, sizeof(textureNameLength)); + textureName = new LegoChar[textureNameLength + 1]; + storage.Read(textureName, textureNameLength); + textureName[textureNameLength] = '\0'; + + strlwr(textureName); + + if (textureName[0] == '^') { + strcpy(textureName, textureName + 1); + + if (g_partPresenterConfig1) { + texture = new LegoTexture(); + if (texture->Read(&storage, hardwareMode) != SUCCESS) { + goto done; + } + + LegoTexture* discardTexture = new LegoTexture(); + if (discardTexture->Read(&storage, FALSE) != SUCCESS) { + goto done; + } + delete discardTexture; + } + else { + LegoTexture* discardTexture = new LegoTexture(); + if (discardTexture->Read(&storage, FALSE) != SUCCESS) { + goto done; + } + delete discardTexture; + + texture = new LegoTexture(); + if (texture->Read(&storage, hardwareMode) != SUCCESS) { + goto done; + } + } + } + else { + texture = new LegoTexture(); + if (texture->Read(&storage, hardwareMode) != SUCCESS) { + goto done; + } + } + + if (TextureContainer()->Get(textureName) == NULL) { + textureInfo = LegoTextureInfo::Create(textureName, texture); + + if (textureInfo == NULL) { + goto done; + } + + TextureContainer()->Add(textureName, textureInfo); + } + + delete[] textureName; + textureName = NULL; + delete texture; + texture = NULL; + } + + if (storage.SetPosition(4) != SUCCESS) { + goto done; + } + + m_parts = new LegoNamedPartList(); + + if (storage.Read(&numROIs, sizeof(numROIs)) != SUCCESS) { + goto done; + } + + for (i = 0; i < numROIs; i++) { + + if (storage.Read(&roiNameLength, sizeof(roiNameLength)) != SUCCESS) { + goto done; + } + + roiName = new LegoChar[roiNameLength + 1]; + if (storage.Read(roiName, roiNameLength) != SUCCESS) { + goto done; + } + + roiName[roiNameLength] = '\0'; + strlwr(roiName); + + if (storage.Read(&numLODs, sizeof(numLODs)) != SUCCESS) { + goto done; + } + if (storage.Read(&roiInfoOffset, sizeof(roiInfoOffset)) != SUCCESS) { + goto done; + } + + if (numLODs > g_partPresenterConfig2) { + surplusLODs = numLODs - g_partPresenterConfig2; + numLODs = g_partPresenterConfig2; + } + else { + surplusLODs = 0; + } + + lods = new LegoLODList(); + + for (j = 0; j < numLODs; j++) { + LegoLOD* lod = new LegoLOD(VideoManager()->GetRenderer()); + + if (lod->Read(VideoManager()->GetRenderer(), TextureContainer(), &storage) != SUCCESS) { + goto done; + } + + if (j == 0) { + if (surplusLODs != 0 && lod->GetUnknown0x08Test8()) { + numLODs++; + surplusLODs--; + } + } + + lods->Append(lod); + } + + storage.SetPosition(roiInfoOffset); + + namedPart = new LegoNamedPart(roiName, lods); + m_parts->Append(namedPart); + + delete[] roiName; + roiName = NULL; + } + + result = SUCCESS; + +done: + if (roiName != NULL) { + delete[] roiName; + } + if (result != SUCCESS && m_parts != NULL) { + delete m_parts; + m_parts = NULL; + } + + return result; } // STUB: LEGO1 0x1007deb0 diff --git a/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp b/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp index 1033bf62..b0148455 100644 --- a/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp @@ -10,6 +10,7 @@ DECOMP_SIZE_ASSERT(LegoTexturePresenter, 0x54) DECOMP_SIZE_ASSERT(LegoNamedTexture, 0x14) DECOMP_SIZE_ASSERT(LegoNamedTextureList, 0x18) +DECOMP_SIZE_ASSERT(LegoNamedTextureListCursor, 0x10) // FUNCTION: LEGO1 0x1004eb40 LegoTexturePresenter::~LegoTexturePresenter()