diff --git a/CMakeLists.txt b/CMakeLists.txt index e7114c92..8d83e879 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,7 @@ add_library(lego1 SHARED LEGO1/legostream.cpp LEGO1/legotexturepresenter.cpp LEGO1/legoutil.cpp + LEGO1/legounksavedatawriter.cpp LEGO1/legovideomanager.cpp LEGO1/legoworld.cpp LEGO1/legoworldpresenter.cpp diff --git a/LEGO1/infocenterstate.h b/LEGO1/infocenterstate.h index 7ceccdb4..47500b47 100644 --- a/LEGO1/infocenterstate.h +++ b/LEGO1/infocenterstate.h @@ -26,34 +26,37 @@ class InfocenterState : public LegoState return !strcmp(name, InfocenterState::ClassName()) || LegoState::IsA(name); } - inline MxU32 GetInfocenterBufferElement(int p_index) { return m_buffer[p_index]; } + inline MxU32 GetInfocenterBufferElement(MxS32 p_index) { return m_buffer[p_index]; } private: - // Size: 0xC - struct SomeStruct - { - undefined4 unk1; - undefined2 unk2; - undefined2 unk3; - undefined2 unk4; - }; + /* + struct SomeStruct + { + undefined4 unk1; + undefined2 unk2; + undefined2 unk3; + undefined2 unk4; + }; - undefined2 unk1; - undefined2 unk2; - undefined4 unk3; - undefined4 padding1; - void *unk4; - undefined2 unk5; - undefined2 unk6; - undefined2 unk7; - undefined2 padding2; - void *unk8; - undefined2 unk9; - undefined2 unk10; - undefined2 unk11; - undefined2 padding3; - SomeStruct unk12[6]; - undefined4 unk13; + undefined2 unk1; + undefined2 unk2; + undefined4 unk3; + undefined4 padding1; + void *unk4; + undefined2 unk5; + undefined2 unk6; + undefined2 unk7; + undefined2 padding2; + void *unk8; + undefined2 unk9; + undefined2 unk10; + undefined2 unk11; + undefined2 padding3; + SomeStruct unk12[6]; + undefined4 unk13; + */ + + undefined pad[0x70]; MxU32 m_buffer[7]; }; diff --git a/LEGO1/legogamestate.cpp b/LEGO1/legogamestate.cpp index acbd3f24..77cca7e6 100644 --- a/LEGO1/legogamestate.cpp +++ b/LEGO1/legogamestate.cpp @@ -4,6 +4,7 @@ #include "legostate.h" #include "infocenterstate.h" #include "legostream.h" +#include "mxobjectfactory.h" #include "mxvariabletable.h" #include "mxstring.h" @@ -11,67 +12,10 @@ // There may be other members that come after. DECOMP_SIZE_ASSERT(LegoGameState, 0x430) -// OFFSET: LEGO1 0x10039550 -LegoGameState::LegoGameState() -{ - // TODO - m_stateCount = 0; - m_backgroundColor = new LegoBackgroundColor("backgroundcolor", "set 56 54 68"); - VariableTable()->SetVariable(m_backgroundColor); - - m_tempBackgroundColor = new LegoBackgroundColor("tempBackgroundcolor", "set 56 54 68"); - VariableTable()->SetVariable(m_tempBackgroundColor); - - m_fullScreenMovie = new LegoFullScreenMovie("fsmovie", "disable"); - VariableTable()->SetVariable(m_fullScreenMovie); - - VariableTable()->SetVariable("lightposition", "2"); - SerializeScoreHistory(1); -} - -// OFFSET: LEGO1 0x10039720 STUB -LegoGameState::~LegoGameState() -{ - // TODO -} - -// OFFSET: LEGO1 0x10039c60 STUB -MxResult LegoGameState::Load(MxULong) -{ - // TODO - return 0; -} - -// OFFSET: LEGO1 0x100f3e40 +// GLOBAL OFFSET: LEGO1 0x100f3e40 const char *g_fileExtensionGS = ".GS"; -// OFFSET: LEGO1 0x1003a170 -void LegoGameState::GetFileSavePath(MxString *p_outPath, MxULong p_slotn) -{ - char baseForSlot[2] = "0"; - char path[1024] = ""; - - // Save path base - if (m_savePath != NULL) - strcpy(path, m_savePath); - - // Slot: "G0", "G1", ... - strcat(path, "G"); - baseForSlot[0] += p_slotn; - strcat(path, baseForSlot); - - // Extension: ".GS" - strcat(path, g_fileExtensionGS); - *p_outPath = &MxString(path); -} - -struct ColorStringStruct -{ - const char *m_targetName; - const char *m_colorName; -}; - -// OFFSET: LEGO1 0x100f3e58 +// GLOBAL OFFSET: LEGO1 0x100f3e58 ColorStringStruct g_colorSaveData[43] = { {"c_dbbkfny0", "lego red"}, {"c_dbbkxly0", "lego white"}, @@ -120,145 +64,102 @@ ColorStringStruct g_colorSaveData[43] = { // NOTE: This offset = the end of the variables table, the last entry // in that table is a special entry, the string "END_OF_VARIABLES" -// OFFSET: LEGO1 0x100f3e50 +// GLOBAL OFFSET: LEGO1 0x100f3e50 extern const char *s_endOfVariables; -// OFFSET: LEGO1 0x1003a020 -MxResult __stdcall WriteEndOfVariables(LegoStream *p_stream) +// OFFSET: LEGO1 0x10039550 +LegoGameState::LegoGameState() { - unsigned char len = strlen(s_endOfVariables); + // TODO + m_stateCount = 0; + m_backgroundColor = new LegoBackgroundColor("backgroundcolor", "set 56 54 68"); + VariableTable()->SetVariable(m_backgroundColor); + + m_tempBackgroundColor = new LegoBackgroundColor("tempBackgroundcolor", "set 56 54 68"); + VariableTable()->SetVariable(m_tempBackgroundColor); + + m_fullScreenMovie = new LegoFullScreenMovie("fsmovie", "disable"); + VariableTable()->SetVariable(m_fullScreenMovie); + + VariableTable()->SetVariable("lightposition", "2"); + SerializeScoreHistory(1); +} + +// OFFSET: LEGO1 0x10039720 STUB +LegoGameState::~LegoGameState() +{ + // TODO +} + +// OFFSET: LEGO1 0x10039c60 STUB +MxResult LegoGameState::Load(MxULong) +{ + // TODO + return 0; +} + +// OFFSET: LEGO1 0x1003a170 +void LegoGameState::GetFileSavePath(MxString *p_outPath, MxULong p_slotn) +{ + char baseForSlot[2] = "0"; + char path[1024] = ""; + + // Save path base + if (m_savePath != NULL) + strcpy(path, m_savePath); + + // Slot: "G0", "G1", ... + strcat(path, "G"); + baseForSlot[0] += p_slotn; + strcat(path, baseForSlot); + + // Extension: ".GS" + strcat(path, g_fileExtensionGS); + *p_outPath = MxString(path); +} + +// OFFSET: LEGO1 0x1003a020 +MxResult LegoGameState::WriteEndOfVariables(LegoStream *p_stream) +{ + MxU8 len = strlen(s_endOfVariables); if (p_stream->Write(&len, 1) == SUCCESS) return p_stream->Write(s_endOfVariables, len); return FAILURE; } -struct LegoSaveDataEntry3 -{ - char *m_name; - void *m_pSomething1; - void *m_pSomething2; - int m_savePart1; - int m_savePart2; - MxU8 m_savePart3; - undefined padding1[3]; - undefined unk1[24]; - MxU8 m_frameOffsetInDwords; - int *m_pFrameData; - MxU8 m_currentFrame; - undefined padding2[3]; - undefined unk2[8]; - MxU8 m_savePart5; - undefined padding3[3]; - undefined unk3[20]; - MxU8 m_savePart6; - undefined padding4[3]; - undefined unk4[44]; - MxU8 m_savePart7; - undefined padding5[3]; - undefined unk5[20]; - MxU8 m_savePart8; - undefined padding6[3]; - undefined unk6[68]; - MxU8 m_savePart9; - undefined padding7[3]; - undefined unk7[20]; - MxU8 m_savePart10; - undefined padding8[3]; -}; - -DECOMP_SIZE_ASSERT(LegoSaveDataEntry3, 0x108); - -// OFFSET: LEGO1 0x10104f20 -LegoSaveDataEntry3 g_saveData3[66]; - -// Some Mx singleton which is in 0x8C of LegoOmni -class UnknownWritingSaveData3 { - MxResult WriteSaveData3(LegoStream *p_stream); -}; - -// Match except for swapped registers -// OFFSET: LEGO1 0x10083310 -MxResult UnknownWritingSaveData3::WriteSaveData3(LegoStream *p_stream) -{ - MxResult result = FAILURE; - - // This should probably be a for loop but I can't figure out how to - // make it match as a for loop. - LegoSaveDataEntry3 *entry = g_saveData3; - const LegoSaveDataEntry3 *end = &g_saveData3[66]; - while (true) - { - if (p_stream->Write(&entry->m_savePart1, 4) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart2, 4) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart3, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_currentFrame, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart5, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart6, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart7, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart8, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart9, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart10, 1) != SUCCESS) - break; - if (++entry >= end) - { - result = SUCCESS; - break; - } - } - return result; -} - -// OFFSET: LEGO1 0x10039980 STUB +// OFFSET: LEGO1 0x10039980 MxResult LegoGameState::Save(MxULong p_slot) { MxResult result; InfocenterState *infocenterState = (InfocenterState *)GameState()->GetState("InfocenterState"); - if (infocenterState == NULL || infocenterState->GetInfocenterBufferElement(0) == 0) - { + if (!infocenterState || infocenterState->GetInfocenterBufferElement(0) == 0) result = SUCCESS; - } - else - { + else { result = FAILURE; MxVariableTable *variableTable = VariableTable(); MxString savePath; GetFileSavePath(&savePath, p_slot); LegoFileStream fileStream; - if (fileStream.Open(savePath.GetData(), LegoStream::WriteBit) != FAILURE) - { + if (fileStream.Open(savePath.GetData(), LegoStream::WriteBit) != FAILURE) { MxU32 maybeVersion = 0x1000C; fileStream.Write(&maybeVersion, 4); fileStream.Write(&m_secondThingWritten, 2); fileStream.Write(&m_someEnumState, 2); fileStream.Write(&m_someModeSwitch, 1); - for (int i = 0; i < sizeof(g_colorSaveData) / sizeof(g_colorSaveData[0]); ++i) - { + for (MxS32 i = 0; i < sizeof(g_colorSaveData) / sizeof(g_colorSaveData[0]); ++i) { if (LegoStream::WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) return result; } - if (LegoStream::WriteVariable(&fileStream, variableTable, "backgroundcolor") != FAILURE) - { - if (LegoStream::WriteVariable(&fileStream, variableTable, "lightposition") != FAILURE) - { + if (LegoStream::WriteVariable(&fileStream, variableTable, "backgroundcolor") != FAILURE) { + if (LegoStream::WriteVariable(&fileStream, variableTable, "lightposition") != FAILURE) { WriteEndOfVariables(&fileStream); // TODO: Calls down to more aggregate writing functions - return SUCCESS; } } - } } return result; @@ -280,30 +181,22 @@ void LegoGameState::SerializeScoreHistory(MxS16 p) void LegoGameState::SetSavePath(char *p_savePath) { if (m_savePath != NULL) - { delete[] m_savePath; - } - if (p_savePath) - { + + if (p_savePath) { m_savePath = new char[strlen(p_savePath) + 1]; strcpy(m_savePath, p_savePath); } else - { m_savePath = NULL; - } } // OFFSET: LEGO1 0x1003bbb0 LegoState *LegoGameState::GetState(char *p_stateName) { for (MxS32 i = 0; i < m_stateCount; ++i) - { if (m_stateArray[i]->IsA(p_stateName)) - { return m_stateArray[i]; - } - } return NULL; } @@ -319,27 +212,25 @@ LegoState *LegoGameState::CreateState(char *p_stateName) // OFFSET: LEGO1 0x1003bc30 void LegoGameState::RegisterState(LegoState *p_state) { - int targetIndex; + MxS32 targetIndex; for (targetIndex = 0; targetIndex < m_stateCount; ++targetIndex) - { if (m_stateArray[targetIndex]->IsA(p_state->ClassName())) break; - } - if (targetIndex == m_stateCount) - { - LegoState **newBuffer = (LegoState**)malloc(m_stateCount * 4 + 4); - if (m_stateCount != 0) - { + + if (targetIndex == m_stateCount) { + LegoState **newBuffer = new LegoState*[m_stateCount + 1]; + + if (m_stateCount != 0) { memcpy(newBuffer, m_stateArray, m_stateCount * sizeof(LegoState*)); - free(m_stateArray); + delete[] m_stateArray; } + newBuffer[m_stateCount++] = p_state; m_stateArray = newBuffer; return; } - if (m_stateArray[targetIndex] != NULL) - { + + if (m_stateArray[targetIndex]) delete m_stateArray[targetIndex]; - } m_stateArray[targetIndex] = p_state; -} +} \ No newline at end of file diff --git a/LEGO1/legogamestate.h b/LEGO1/legogamestate.h index c11387f9..cec74785 100644 --- a/LEGO1/legogamestate.h +++ b/LEGO1/legogamestate.h @@ -7,9 +7,16 @@ #include "legofullscreenmovie.h" class LegoState; +class LegoStream; class MxVariable; class MxString; +struct ColorStringStruct +{ + const char *m_targetName; + const char *m_colorName; +}; + // SIZE 0x430 (at least) class LegoGameState { @@ -29,6 +36,7 @@ class LegoGameState private: void RegisterState(LegoState *p_state); + MxResult WriteEndOfVariables(LegoStream *p_stream); private: char *m_savePath; // 0x0 @@ -41,7 +49,7 @@ class LegoGameState LegoBackgroundColor *m_tempBackgroundColor; // 0x1c LegoFullScreenMovie *m_fullScreenMovie; // 0x20 MxU16 m_secondThingWritten; - undefined m_unk24[1036]; + undefined m_unk24[1032]; }; #endif // LEGOGAMESTATE_H diff --git a/LEGO1/legoobjectfactory.cpp b/LEGO1/legoobjectfactory.cpp index cdd38513..c5747482 100644 --- a/LEGO1/legoobjectfactory.cpp +++ b/LEGO1/legoobjectfactory.cpp @@ -1,13 +1,12 @@ #include "legoobjectfactory.h" #include "infocenterstate.h" - #include "decomp.h" // TODO: Uncomment once we have all the relevant types ready -// DECOMP_SIZE_ASSERT(LegoObjectFactory, 0x1c4); +// DECOMP_SIZE_ASSERT(LegoObjectFactory, 0x1c8); -// OFFSET: LEGO1 0x100b0d80 +// OFFSET: LEGO1 0x10006e40 LegoObjectFactory::LegoObjectFactory() { #define X(V) this->m_id##V = MxAtomId(#V, LookupMode_Exact); @@ -15,8 +14,8 @@ LegoObjectFactory::LegoObjectFactory() #undef X } -// OFFSET: LEGO1 0x100b12c0 -void *LegoObjectFactory::Create(const char *p_name) +// OFFSET: LEGO1 0x10009a90 +MxCore *LegoObjectFactory::Create(const char *p_name) { MxAtomId atom(p_name, LookupMode_Exact); @@ -29,7 +28,8 @@ void *LegoObjectFactory::Create(const char *p_name) } } -// OFFSET: LEGO1 0x100b1a30 STUB -void LegoObjectFactory::Destroy(void *p_object) { - // FIXME +// OFFSET: LEGO1 0x1000fb30 STUB +void LegoObjectFactory::Destroy(void *p_object) +{ + // TODO } diff --git a/LEGO1/legoobjectfactory.h b/LEGO1/legoobjectfactory.h index e6409ee0..d01a1196 100644 --- a/LEGO1/legoobjectfactory.h +++ b/LEGO1/legoobjectfactory.h @@ -6,13 +6,13 @@ #define FOR_LEGOOBJECTFACTORY_OBJECTS(X) \ X(InfocenterState) -// VTABLE 0x100dc220 +// VTABLE 0x100d4768 class LegoObjectFactory : public MxObjectFactory { public: LegoObjectFactory(); - virtual void *Create(const char *p_name); // vtable 0x14 - virtual void Destroy(void *p_object); // vtable 0x18 + virtual MxCore *Create(const char *p_name) override; // vtable 0x14 + virtual void Destroy(void *p_object) override; // vtable 0x18 private: #define X(V) MxAtomId m_id##V; FOR_LEGOOBJECTFACTORY_OBJECTS(X) diff --git a/LEGO1/legoomni.cpp b/LEGO1/legoomni.cpp index d18587e2..7e306af1 100644 --- a/LEGO1/legoomni.cpp +++ b/LEGO1/legoomni.cpp @@ -262,7 +262,7 @@ void LegoOmni::Init() m_currentWorld = NULL; m_unk80 = FALSE; m_isle = NULL; - m_unk8c = 0; + m_unkLegoSaveDataWriter = NULL; m_plantManager = NULL; m_gameState = NULL; m_animationManager = NULL; diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index e4074463..37d3ef4b 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -16,6 +16,7 @@ class LegoPathBoundary; class LegoPlantManager; class LegoROI; class LegoSoundManager; +class LegoUnkSaveDataWriter; class LegoVideoManager; class LegoWorld; class MxAtomId; @@ -77,8 +78,8 @@ class LegoOmni : public MxOmni LegoWorld *GetCurrentWorld() { return m_currentWorld; } private: - int m_unk68; - int m_unk6c; + undefined4 m_unk68; + undefined4 m_unk6c; LegoInputManager *m_inputMgr; // 0x70 undefined4 m_unk74; undefined4 m_unk78; @@ -86,7 +87,7 @@ class LegoOmni : public MxOmni MxBool m_unk80; LegoNavController *m_navController; // 0x84 Isle* m_isle; // 0x88 - undefined4 m_unk8c; + LegoUnkSaveDataWriter* m_unkLegoSaveDataWriter; LegoPlantManager* m_plantManager; // 0x90 LegoAnimationManager* m_animationManager; LegoBuildingManager* m_buildingManager; // 0x98 diff --git a/LEGO1/legostream.cpp b/LEGO1/legostream.cpp index f8d788fd..0bc24db9 100644 --- a/LEGO1/legostream.cpp +++ b/LEGO1/legostream.cpp @@ -6,6 +6,12 @@ #include "mxvariabletable.h" +// This is a pointer to the end of the global variable name table, which has +// the text "END_OF_VARIABLES" in it. +// TODO: make s_endOfVariables reference the actual end of the variable array. +// GLOBAL OFFSET: LEGO1 0x100f3e50 +const char *s_endOfVariables = "END_OF_VARIABLES"; + // Very likely but not certain sizes. // The classes are only used on the stack in functions we have not 100% matched // yet, we can confirm the size once we have. @@ -153,13 +159,11 @@ MxResult LegoStream::WriteVariable(LegoStream* p_stream, MxVariableTable* p_from { MxResult result = FAILURE; const char *variableValue = p_from->GetVariable(p_variableName); - if (variableValue != NULL) - { + + if (variableValue) { MxU8 length = strlen(p_variableName); - if (p_stream->Write((char*)&length, 1) == SUCCESS) - { - if (p_stream->Write(p_variableName, length) == SUCCESS) - { + if (p_stream->Write((char*)&length, 1) == SUCCESS) { + if (p_stream->Write(p_variableName, length) == SUCCESS) { length = strlen(variableValue); if (p_stream->Write((char*)&length, 1) == SUCCESS) result = p_stream->Write((char *)variableValue, length); @@ -169,37 +173,25 @@ MxResult LegoStream::WriteVariable(LegoStream* p_stream, MxVariableTable* p_from return result; } -// This is a pointer to the end of the global variable name table, which has -// the text "END_OF_VARIABLES" in it. -// TODO: make s_endOfVariables reference the actual end of the variable array. -// OFFSET: LEGO1 0x100f3e50 -const char *s_endOfVariables = "END_OF_VARIABLES"; - // 95% match, just some instruction ordering differences on the call to // MxVariableTable::SetVariable at the end. // OFFSET: LEGO1 0x1003a080 -int LegoStream::ReadVariable(LegoStream* p_stream, MxVariableTable* p_to) +MxS32 LegoStream::ReadVariable(LegoStream* p_stream, MxVariableTable* p_to) { - int result = 1; + MxS32 result = 1; MxU8 length; - if (p_stream->Read((char*)&length, 1) == SUCCESS) - { + + if (p_stream->Read((char*)&length, 1) == SUCCESS) { char nameBuffer[256]; - if (p_stream->Read(nameBuffer, length) == SUCCESS) - { + if (p_stream->Read(nameBuffer, length) == SUCCESS) { nameBuffer[length] = '\0'; if (strcmp(nameBuffer, s_endOfVariables) == 0) - { // 2 -> "This was the last entry, done reading." result = 2; - } - else - { - if (p_stream->Read((char*)&length, 1) == SUCCESS) - { + else { + if (p_stream->Read((char*)&length, 1) == SUCCESS) { char valueBuffer[256]; - if (p_stream->Read(valueBuffer, length) == SUCCESS) - { + if (p_stream->Read(valueBuffer, length) == SUCCESS) { result = 0; valueBuffer[length] = '\0'; p_to->SetVariable(nameBuffer, valueBuffer); diff --git a/LEGO1/legostream.h b/LEGO1/legostream.h index 35c37960..6555f6b6 100644 --- a/LEGO1/legostream.h +++ b/LEGO1/legostream.h @@ -34,8 +34,8 @@ class LegoStream BinaryBit = 4, }; - static MxResult __stdcall WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName); - static int __stdcall ReadVariable(LegoStream* p_stream, MxVariableTable* p_to); + static MxResult WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName); + static MxS32 ReadVariable(LegoStream* p_stream, MxVariableTable* p_to); protected: MxU8 m_mode; diff --git a/LEGO1/legounksavedatawriter.cpp b/LEGO1/legounksavedatawriter.cpp new file mode 100644 index 00000000..61b41f28 --- /dev/null +++ b/LEGO1/legounksavedatawriter.cpp @@ -0,0 +1,48 @@ + +#include "legounksavedatawriter.h" +#include "legogamestate.h" +#include "legostream.h" + +DECOMP_SIZE_ASSERT(LegoSaveDataEntry3, 0x108); + +// GLOBAL OFFSET: LEGO1 0x10104f20 +LegoSaveDataEntry3 g_saveData3[66]; + +// OFFSET: LEGO1 0x10083310 +MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStream *p_stream) +{ + MxResult result = FAILURE; + + // This should probably be a for loop but I can't figure out how to + // make it match as a for loop. + LegoSaveDataEntry3 *entry = g_saveData3; + const LegoSaveDataEntry3 *end = &g_saveData3[66]; + + while (TRUE) { + if (p_stream->Write(&entry->m_savePart1, 4) != SUCCESS) + break; + if (p_stream->Write(&entry->m_savePart2, 4) != SUCCESS) + break; + if (p_stream->Write(&entry->m_savePart3, 1) != SUCCESS) + break; + if (p_stream->Write(&entry->m_currentFrame, 1) != SUCCESS) + break; + if (p_stream->Write(&entry->m_savePart5, 1) != SUCCESS) + break; + if (p_stream->Write(&entry->m_savePart6, 1) != SUCCESS) + break; + if (p_stream->Write(&entry->m_savePart7, 1) != SUCCESS) + break; + if (p_stream->Write(&entry->m_savePart8, 1) != SUCCESS) + break; + if (p_stream->Write(&entry->m_savePart9, 1) != SUCCESS) + break; + if (p_stream->Write(&entry->m_savePart10, 1) != SUCCESS) + break; + if (++entry >= end) { + result = SUCCESS; + break; + } + } + return result; +} diff --git a/LEGO1/legounksavedatawriter.h b/LEGO1/legounksavedatawriter.h new file mode 100644 index 00000000..0280077a --- /dev/null +++ b/LEGO1/legounksavedatawriter.h @@ -0,0 +1,40 @@ +#ifndef LEGOUNKSAVEDATAWRITER_H +#define LEGOUNKSAVEDATAWRITER_H + +#include "mxtypes.h" +#include "decomp.h" + +class LegoStream; + +struct LegoSaveDataEntry3 +{ + char *m_name; + void *m_unk0x04; + void *m_unk0x08; + MxS32 m_savePart1; + MxS32 m_savePart2; + MxU8 m_savePart3; + undefined4 m_unk0x18[6]; + MxU8 m_frameOffsetInDwords; // 0x30 + MxS32 *m_pFrameData; + MxU8 m_currentFrame; + undefined4 m_unk0x3c[2]; + MxU8 m_savePart5; // 0x44 + undefined4 m_unk0x48[5]; + MxU8 m_savePart6; // 0x5c + undefined4 m_unk0x60[11]; + MxU8 m_savePart7; // 0x8c + undefined4 m_unk0x90[5]; + MxU8 m_savePart8; // 0xa4 + undefined4 m_unk0xa8[17]; + MxU8 m_savePart9; // 0xec + undefined4 m_unk0xf0[5]; + MxU8 m_savePart10; // 0x104 +}; + +class LegoUnkSaveDataWriter +{ + MxResult WriteSaveData3(LegoStream *p_stream); +}; + +#endif // LEGOUNKSAVEDATAWRITER_H diff --git a/LEGO1/mxatomid.cpp b/LEGO1/mxatomid.cpp index df69e76c..092f5deb 100644 --- a/LEGO1/mxatomid.cpp +++ b/LEGO1/mxatomid.cpp @@ -15,7 +15,7 @@ MxAtomId::MxAtomId(const char *p_str, LookupMode p_mode) counter->Inc(); } -// OFFSET: LEGO1 0x100acfd0 STUB +// OFFSET: LEGO1 0x100acfd0 MxAtomId::~MxAtomId() { Destroy(); diff --git a/LEGO1/mxobjectfactory.cpp b/LEGO1/mxobjectfactory.cpp index 334ed746..78615f55 100644 --- a/LEGO1/mxobjectfactory.cpp +++ b/LEGO1/mxobjectfactory.cpp @@ -26,7 +26,7 @@ MxObjectFactory::MxObjectFactory() } // OFFSET: LEGO1 0x100b12c0 -void *MxObjectFactory::Create(const char *p_name) +MxCore *MxObjectFactory::Create(const char *p_name) { MxAtomId atom(p_name, LookupMode_Exact); diff --git a/LEGO1/mxobjectfactory.h b/LEGO1/mxobjectfactory.h index 03196992..eb7030ed 100644 --- a/LEGO1/mxobjectfactory.h +++ b/LEGO1/mxobjectfactory.h @@ -23,7 +23,21 @@ class MxObjectFactory : public MxCore { public: MxObjectFactory(); - virtual void *Create(const char *p_name); // vtable 0x14 + + // OFFSET: LEGO1 0x1008f70 + inline virtual const char *ClassName() const override // vtable+0xc + { + // 0x100f0730 + return "MxObjectFactory"; + } + + // OFFSET: LEGO1 0x1008f80 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, MxObjectFactory::ClassName()) || MxCore::IsA(name); + } + + virtual MxCore *Create(const char *p_name); // vtable 0x14 virtual void Destroy(void *p_object); // vtable 0x18 private: #define X(V) MxAtomId m_id##V; diff --git a/LEGO1/mxomni.h b/LEGO1/mxomni.h index 8fddbec1..ab07d2bd 100644 --- a/LEGO1/mxomni.h +++ b/LEGO1/mxomni.h @@ -93,9 +93,9 @@ __declspec(dllexport) MxVariableTable * VariableTable(); __declspec(dllexport) MxMusicManager * MusicManager(); __declspec(dllexport) MxEventManager * EventManager(); __declspec(dllexport) MxNotificationManager * NotificationManager(); -MxVideoManager * MVideoManager(); -MxAtomIdCounterSet* AtomIdCounterSet(); +MxVideoManager *MVideoManager(); +MxAtomIdCounterSet *AtomIdCounterSet(); MxObjectFactory *ObjectFactory(); #endif // MXOMNI_H