diff --git a/LEGO1/legoomni.cpp b/LEGO1/legoomni.cpp index b5cbca8e..e5574058 100644 --- a/LEGO1/legoomni.cpp +++ b/LEGO1/legoomni.cpp @@ -43,6 +43,42 @@ void MakeSourceName(char *, const char *) // TODO } +// OFFSET: LEGO1 0x100b7050 +MxBool KeyValueStringParse(char *p_outputValue, char *p_key, char *p_source) +{ + MxBool didMatch = FALSE; + + MxS16 len = strlen(p_source); + char *temp = new char[len + 1]; + strcpy(temp, p_source); + + char *token = strtok(temp, ", \t\r\n:"); + while (token) { + len -= (strlen(token) + 1); + + if (strcmpi(token, p_key) == 0) { + if (p_outputValue && len > 0) { + char *cur = &token[strlen(p_key)]; + cur++; + while (*cur != ',') { + if (*cur == ' ' || *cur == '\0' || *cur == '\t' || *cur == '\n' || *cur == '\r') + break; + *p_outputValue++ = *cur++; + } + *p_outputValue = '\0'; + } + + didMatch = TRUE; + break; + } + + token = strtok(NULL, ", \t\r\n:"); + } + + delete[] temp; + return didMatch; +} + // OFFSET: LEGO1 0x100b7210 void SetOmniUserMessage(void (*p_userMsg)(const char *,int)) { diff --git a/LEGO1/legoomni.h b/LEGO1/legoomni.h index 0ba27cf2..485da46c 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/legoomni.h @@ -113,5 +113,6 @@ __declspec(dllexport) MxLong Start(MxDSAction *a); LegoBuildingManager* BuildingManager(); Isle* GetIsle(); LegoPlantManager* PlantManager(); +MxBool KeyValueStringParse(char *, char *, char *); #endif // LEGOOMNI_H diff --git a/LEGO1/mxdsaction.cpp b/LEGO1/mxdsaction.cpp index e9b65037..cccea39c 100644 --- a/LEGO1/mxdsaction.cpp +++ b/LEGO1/mxdsaction.cpp @@ -13,8 +13,8 @@ MxDSAction::MxDSAction() { this->m_flags = 32; this->m_startTime = INT_MIN; - this->m_unkData = NULL; - this->m_unkLength = 0; + this->m_extraData = NULL; + this->m_extraLength = 0; this->m_duration = INT_MIN; this->m_loopCount = -1; @@ -44,7 +44,7 @@ MxDSAction::MxDSAction() // OFFSET: LEGO1 0x100ada80 MxDSAction::~MxDSAction() { - delete[] this->m_unkData; + delete[] this->m_extraData; } // OFFSET: LEGO1 0x100adaf0 @@ -60,7 +60,7 @@ void MxDSAction::CopyFrom(MxDSAction &p_dsAction) this->m_direction.CopyFrom(p_dsAction.m_direction); this->m_up.CopyFrom(p_dsAction.m_up); - AppendData(p_dsAction.m_unkLength, p_dsAction.m_unkData); + AppendData(p_dsAction.m_extraLength, p_dsAction.m_extraData); this->m_unk84 = p_dsAction.m_unk84; this->m_unk88 = p_dsAction.m_unk88; this->m_omni = p_dsAction.m_omni; @@ -83,7 +83,7 @@ MxU32 MxDSAction::GetSizeOnDisk() { MxU32 totalSizeOnDisk; - totalSizeOnDisk = MxDSObject::GetSizeOnDisk() + 90 + this->m_unkLength; + totalSizeOnDisk = MxDSObject::GetSizeOnDisk() + 90 + this->m_extraLength; this->m_sizeOnDisk = totalSizeOnDisk - MxDSObject::GetSizeOnDisk(); return totalSizeOnDisk; @@ -186,13 +186,13 @@ void MxDSAction::MergeFrom(MxDSAction &p_dsAction) this->m_up[2] = p_dsAction.m_up[2]; // TODO - MxU16 unkLength = p_dsAction.m_unkLength; - char *unkData = p_dsAction.m_unkData; - if (unkLength && unkData) { - if (!this->m_unkData || !strncmp("XXX", this->m_unkData, 3)) { - delete[] this->m_unkData; - this->m_unkLength = 0; - AppendData(unkLength, unkData); + MxU16 extraLength = p_dsAction.m_extraLength; + char *extraData = p_dsAction.m_extraData; + if (extraLength && extraData) { + if (!this->m_extraData || !strncmp("XXX", this->m_extraData, 3)) { + delete[] this->m_extraData; + this->m_extraLength = 0; + AppendData(extraLength, extraData); } } } @@ -222,29 +222,29 @@ MxLong MxDSAction::GetCurrentTime() } // OFFSET: LEGO1 0x100ade60 -void MxDSAction::AppendData(MxU16 p_unkLength, const char *p_unkData) +void MxDSAction::AppendData(MxU16 p_extraLength, const char *p_extraData) { - if (this->m_unkData == p_unkData || !p_unkData) + if (this->m_extraData == p_extraData || !p_extraData) return; - if (this->m_unkLength) { - char *concat = new char[p_unkLength + this->m_unkLength + sizeof(g_unkSep)]; - memcpy(concat, this->m_unkData, this->m_unkLength); + if (this->m_extraLength) { + char *concat = new char[p_extraLength + this->m_extraLength + sizeof(g_unkSep)]; + memcpy(concat, this->m_extraData, this->m_extraLength); - *(MxU16*) &concat[this->m_unkLength] = g_unkSep; - memcpy(&concat[this->m_unkLength + sizeof(g_unkSep)], p_unkData, p_unkLength); + *(MxU16*) &concat[this->m_extraLength] = g_unkSep; + memcpy(&concat[this->m_extraLength + sizeof(g_unkSep)], p_extraData, p_extraLength); - this->m_unkLength += p_unkLength + sizeof(g_unkSep); - delete[] this->m_unkData; - this->m_unkData = concat; + this->m_extraLength += p_extraLength + sizeof(g_unkSep); + delete[] this->m_extraData; + this->m_extraData = concat; } else { - char *copy = new char[p_unkLength]; - this->m_unkData = copy; + char *copy = new char[p_extraLength]; + this->m_extraData = copy; if (copy) { - this->m_unkLength = p_unkLength; - memcpy(copy, p_unkData, p_unkLength); + this->m_extraLength = p_extraLength; + memcpy(copy, p_extraData, p_extraLength); } } } diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index a85e6494..11388c0f 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -13,6 +13,7 @@ public: enum { Flag_Enabled = 0x20, + Flag_Parsed = 0x80, }; __declspec(dllexport) MxDSAction(); @@ -45,10 +46,13 @@ public: virtual MxLong GetSomeTimingField(); // vtable+3c; virtual MxLong GetCurrentTime(); // vtable+40; - void AppendData(MxU16 p_unkLength, const char *p_unkData); + void AppendData(MxU16 p_extraLength, const char *p_extraData); inline MxU32 GetFlags() { return this->m_flags; } inline void SetFlags(MxU32 m_flags) { this->m_flags = m_flags; } + inline char *GetExtraData() { return m_extraData; } + inline MxU16 GetExtraLength() const { return m_extraLength; } + inline void SetOmni(MxOmni *p_omni) { m_omni = p_omni; } private: MxU32 m_sizeOnDisk; @@ -63,8 +67,8 @@ private: MxVector3Data m_location; MxVector3Data m_direction; MxVector3Data m_up; - char *m_unkData; - MxU16 m_unkLength; + char *m_extraData; + MxU16 m_extraLength; undefined4 m_unk84; undefined4 m_unk88; MxOmni *m_omni; // 0x8c diff --git a/LEGO1/mxomni.cpp b/LEGO1/mxomni.cpp index 4048a0b5..446ac4f9 100644 --- a/LEGO1/mxomni.cpp +++ b/LEGO1/mxomni.cpp @@ -42,6 +42,55 @@ void MxOmni::Init() m_unk64 = NULL; } +// OFFSET: LEGO1 0x100b0090 STUB +void MxOmni::vtable0x20() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b00c0 STUB +void MxOmni::DeleteObject() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b09a0 STUB +void MxOmni::DoesEntityExist() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b00e0 STUB +void MxOmni::vtable0x2c() +{ + // TODO +} + +// OFFSET: LEGO1 0x100aefb0 STUB +int MxOmni::vtable0x30(char*, int, MxCore*) +{ + // TODO + return 0; +} + +// OFFSET: LEGO1 0x100aefc0 STUB +void MxOmni::NotifyCurrentEntity() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b09d0 STUB +void MxOmni::StartTimer() +{ + // TODO +} + +// OFFSET: LEGO1 0x100b0a00 STUB +void MxOmni::vtable0x3c() +{ + // TODO +} + // OFFSET: LEGO1 0x100b0690 void MxOmni::DestroyInstance() { diff --git a/LEGO1/mxomni.h b/LEGO1/mxomni.h index bbaf4cb0..8cacc5fc 100644 --- a/LEGO1/mxomni.h +++ b/LEGO1/mxomni.h @@ -37,6 +37,14 @@ public: virtual void Init(); // vtable+14 virtual MxResult Create(MxOmniCreateParam &p); // vtable+18 virtual void Destroy(); // vtable+1c + virtual void vtable0x20(); // vtable+20 + virtual void DeleteObject(); // vtable+24 + virtual void DoesEntityExist(); // vtable+28 + virtual void vtable0x2c(); // vtable+2c + virtual int vtable0x30(char*, int, MxCore*); // vtable+30 + virtual void NotifyCurrentEntity(); // vtable+34 + virtual void StartTimer(); // vtable+38 + virtual void vtable0x3c(); // vtable+3c static void SetInstance(MxOmni* instance); HWND GetWindowHandle() const { return this->m_windowHandle; } MxObjectFactory* GetObjectFactory() const { return this->m_objectFactory; } diff --git a/LEGO1/mxpresenter.cpp b/LEGO1/mxpresenter.cpp index 5fbdb8e4..56688233 100644 --- a/LEGO1/mxpresenter.cpp +++ b/LEGO1/mxpresenter.cpp @@ -1,26 +1,77 @@ #include "mxpresenter.h" #include "mxautolocker.h" +#include "mxparam.h" +#include "legoomni.h" +#include #include "decomp.h" DECOMP_SIZE_ASSERT(MxPresenter, 0x40); +// 0x10101eac +char *g_parseExtraTokens = ":;"; + +// 0x10101edc +char *g_strWORLD = "WORLD"; + // OFFSET: LEGO1 0x100b4d50 void MxPresenter::Init() { m_currentTickleState = TickleState_Idle; m_action = NULL; m_unk0x18 = 0; - m_unk0x3c = 0; + m_unkPresenter = NULL; m_previousTickleStates = 0; m_unk0x10 = 0; m_unk0x14 = 0; } -// OFFSET: LEGO1 0x100b4fc0 STUB +// OFFSET: LEGO1 0x100b4fc0 void MxPresenter::ParseExtra() { - // TODO + + MxAutoLocker lock(&m_criticalSection); + MxU32 len = m_action->GetExtraLength(); + char *extraData = m_action->GetExtraData(); + + if (len) { + len &= MAXWORD; + char extraCopy[512]; + memcpy(extraCopy, extraData, len); + extraCopy[len] = '\0'; + + char t_worldValue[512]; + if (KeyValueStringParse(t_worldValue, g_strWORLD, extraCopy)) { + char *token = strtok(t_worldValue, g_parseExtraTokens); + char t_token[256]; + strcpy(t_token, token); + + token = strtok(NULL, g_parseExtraTokens); + int val = token ? atoi(token) : 0; + + int result = MxOmni::GetInstance()->vtable0x30(t_token, val, this); + + m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Parsed); + + if (result) + SendTo_unkPresenter(MxOmni::GetInstance()); + + } + } +} + +// OFFSET: LEGO1 0x100b5120 +void MxPresenter::SendTo_unkPresenter(MxOmni *p_omni) +{ + if (m_unkPresenter) { + MxAutoLocker lock(&m_criticalSection); + + // TOOD: magic number used for notification type. replace with enum + NotificationManager()->Send(m_unkPresenter, &MxParam(5, this)); + + m_action->SetOmni(p_omni ? p_omni : MxOmni::GetInstance()); + m_unkPresenter = NULL; + } } // OFFSET: LEGO1 0x1000bf00 diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h index 6f50984e..4b8659ec 100644 --- a/LEGO1/mxpresenter.h +++ b/LEGO1/mxpresenter.h @@ -4,6 +4,7 @@ #include "mxcore.h" #include "mxdsaction.h" #include "mxcriticalsection.h" +#include "mxomni.h" #include "decomp.h" @@ -68,6 +69,7 @@ public: protected: __declspec(dllexport) void Init(); + void SendTo_unkPresenter(MxOmni *); private: MxS32 m_currentTickleState; // 0x8 @@ -77,7 +79,7 @@ private: undefined4 m_unk0x18; MxDSAction* m_action; // 0 MxCriticalSection m_criticalSection; - undefined4 m_unk0x3c; + MxPresenter *m_unkPresenter; // 0x3c }; #endif // MXPRESENTER_H