From 311b27b6971aa2eaf2c1beb71bbb96cff230aeed Mon Sep 17 00:00:00 2001 From: MS Date: Wed, 24 Apr 2024 12:10:51 -0400 Subject: [PATCH] Beta matching MxString (#842) * Beta matching MxString * Add /opt:ref for lego1. Reorder MxString header. * const fix * Remove lego1 Opt:ref --- LEGO1/lego/legoomni/include/legophonemelist.h | 2 + .../legoomni/src/common/legovariables.cpp | 3 +- LEGO1/omni/include/mxstring.h | 34 +++++--- LEGO1/omni/src/common/mxstring.cpp | 81 +++++++++++++++++-- 4 files changed, 103 insertions(+), 17 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legophonemelist.h b/LEGO1/lego/legoomni/include/legophonemelist.h index 10ade657..37e4b8b6 100644 --- a/LEGO1/lego/legoomni/include/legophonemelist.h +++ b/LEGO1/lego/legoomni/include/legophonemelist.h @@ -12,12 +12,14 @@ // class MxList // VTABLE: LEGO1 0x100d9d00 +// VTABLE: BETA10 0x101bef58 // SIZE 0x18 class LegoPhonemeList : public MxList { public: LegoPhonemeList() { SetDestroy(Destroy); } // FUNCTION: LEGO1 0x1007b210 + // FUNCTION: BETA10 0x100d8340 MxS8 Compare(LegoPhoneme* p_a, LegoPhoneme* p_b) override { MxString a(p_a->GetName()); diff --git a/LEGO1/lego/legoomni/src/common/legovariables.cpp b/LEGO1/lego/legoomni/src/common/legovariables.cpp index 83a17084..71e6e587 100644 --- a/LEGO1/lego/legoomni/src/common/legovariables.cpp +++ b/LEGO1/lego/legoomni/src/common/legovariables.cpp @@ -68,12 +68,13 @@ const char* g_nick = "Nick"; const char* g_laura = "Laura"; // FUNCTION: LEGO1 0x10037d00 +// FUNCTION: BETA10 0x100d5620 void VisibilityVariable::SetValue(const char* p_value) { MxVariable::SetValue(p_value); if (p_value) { - char* instruction = strtok(m_value.GetDataPtr(), g_delimiter2); + char* instruction = strtok(m_value.GetData(), g_delimiter2); char* name = strtok(NULL, g_delimiter2); MxBool show; diff --git a/LEGO1/omni/include/mxstring.h b/LEGO1/omni/include/mxstring.h index 231d2e2c..5d973e69 100644 --- a/LEGO1/omni/include/mxstring.h +++ b/LEGO1/omni/include/mxstring.h @@ -4,28 +4,42 @@ #include "mxcore.h" // VTABLE: LEGO1 0x100dc110 +// VTABLE: BETA10 0x101c1be0 // SIZE 0x10 class MxString : public MxCore { public: - MxString(const MxString& p_str); - ~MxString() override; - const MxString& operator=(const char* p_data); - MxString(); - MxString(const char*); + MxString(const MxString& p_str); + MxString(const char* p_str); + MxString(const char* p_str, MxU16 p_maxlen); + ~MxString() override; + + void Reverse(); void ToUpperCase(); void ToLowerCase(); + MxString& operator=(const MxString& p_str); - MxString operator+(const char* p_str); + const MxString& operator=(const char* p_str); + MxString operator+(const MxString& p_str) const; + MxString operator+(const char* p_str) const; MxString& operator+=(const char* p_str); - inline MxS8 Compare(const MxString& p_str) const { return strcmp(m_data, p_str.m_data); } - inline MxBool Equal(const MxString& p_str) const { return strcmp(m_data, p_str.m_data) == 0; } - inline const char* GetData() const { return m_data; } - inline char* GetDataPtr() const { return m_data; } + static void CharSwap(char* p_a, char* p_b); + + // FUNCTION: BETA10 0x10017c50 + inline char* GetData() const { return m_data; } + + // FUNCTION: BETA10 0x10067630 inline const MxU16 GetLength() const { return m_length; } + // FUNCTION: BETA10 0x100d8a30 + inline MxBool Equal(const MxString& p_str) const { return strcmp(m_data, p_str.m_data) == 0; } + + // FUNCTION: BETA10 0x1012a810 + inline MxS8 Compare(const MxString& p_str) const { return strcmp(m_data, p_str.m_data); } + // SYNTHETIC: LEGO1 0x100ae280 + // SYNTHETIC: BETA10 0x1012c9d0 // MxString::`scalar deleting destructor' private: diff --git a/LEGO1/omni/src/common/mxstring.cpp b/LEGO1/omni/src/common/mxstring.cpp index 09194eb7..b33a7f10 100644 --- a/LEGO1/omni/src/common/mxstring.cpp +++ b/LEGO1/omni/src/common/mxstring.cpp @@ -8,6 +8,7 @@ DECOMP_SIZE_ASSERT(MxString, 0x10) // FUNCTION: LEGO1 0x100ae200 +// FUNCTION: BETA10 0x1012c110 MxString::MxString() { // Set string to one char in length and set that char to null terminator @@ -17,6 +18,7 @@ MxString::MxString() } // FUNCTION: LEGO1 0x100ae2a0 +// FUNCTION: BETA10 0x1012c1a1 MxString::MxString(const MxString& p_str) { this->m_length = p_str.m_length; @@ -25,6 +27,7 @@ MxString::MxString(const MxString& p_str) } // FUNCTION: LEGO1 0x100ae350 +// FUNCTION: BETA10 0x1012c24f MxString::MxString(const char* p_str) { if (p_str) { @@ -39,25 +42,65 @@ MxString::MxString(const char* p_str) } } +// FUNCTION: BETA10 0x1012c330 +MxString::MxString(const char* p_str, MxU16 p_maxlen) +{ + if (p_str) { + if (strlen(p_str) <= p_maxlen) { + this->m_length = strlen(p_str); + } + else { + this->m_length = p_maxlen; + } + + // Basically strncpy + this->m_data = new char[this->m_length + 1]; + memcpy(this->m_data, p_str, this->m_length); + this->m_data[this->m_length] = '\0'; + } + else { + this->m_data = new char[1]; + this->m_data[0] = 0; + this->m_length = 0; + } +} + // FUNCTION: LEGO1 0x100ae420 +// FUNCTION: BETA10 0x1012c45b MxString::~MxString() { delete[] this->m_data; } +// FUNCTION: BETA10 0x1012c4de +void MxString::Reverse() +{ + char* start = this->m_data; + char* end = this->m_data + this->m_length - 1; + + while (start < end) { + CharSwap(start, end); + start++; + end--; + } +} + // FUNCTION: LEGO1 0x100ae490 +// FUNCTION: BETA10 0x1012c537 void MxString::ToUpperCase() { strupr(this->m_data); } // FUNCTION: LEGO1 0x100ae4a0 +// FUNCTION: BETA10 0x1012c55c void MxString::ToLowerCase() { strlwr(this->m_data); } // FUNCTION: LEGO1 0x100ae4b0 +// FUNCTION: BETA10 0x1012c581 MxString& MxString::operator=(const MxString& p_str) { if (this->m_data != p_str.m_data) { @@ -71,22 +114,39 @@ MxString& MxString::operator=(const MxString& p_str) } // FUNCTION: LEGO1 0x100ae510 -const MxString& MxString::operator=(const char* p_data) +// FUNCTION: BETA10 0x1012c606 +const MxString& MxString::operator=(const char* p_str) { - if (this->m_data != p_data) { + if (this->m_data != p_str) { delete[] this->m_data; - this->m_length = strlen(p_data); + this->m_length = strlen(p_str); this->m_data = new char[this->m_length + 1]; - strcpy(this->m_data, p_data); + strcpy(this->m_data, p_str); } return *this; } +// FUNCTION: BETA10 0x1012c68a +MxString MxString::operator+(const MxString& p_str) const +{ + MxString tmp; + delete[] tmp.m_data; + + tmp.m_length = p_str.m_length + this->m_length; + tmp.m_data = new char[tmp.m_length + 1]; + + strcpy(tmp.m_data, this->m_data); + strcpy(tmp.m_data + this->m_length, p_str.m_data); + + return MxString(tmp); +} + // Return type is intentionally just MxString, not MxString&. // This forces MSVC to add $ReturnUdt$ to the stack for 100% match. // FUNCTION: LEGO1 0x100ae580 -MxString MxString::operator+(const char* p_str) +// FUNCTION: BETA10 0x1012c78d +MxString MxString::operator+(const char* p_str) const { // MxString constructor allocates 1 byte for m_data, so free that first MxString tmp; @@ -102,6 +162,7 @@ MxString MxString::operator+(const char* p_str) } // FUNCTION: LEGO1 0x100ae690 +// FUNCTION: BETA10 0x1012c92f MxString& MxString::operator+=(const char* p_str) { int newlen = this->m_length + strlen(p_str); @@ -111,8 +172,16 @@ MxString& MxString::operator+=(const char* p_str) strcpy(tmp + this->m_length, p_str); delete[] this->m_data; - this->m_length = newlen; this->m_data = tmp; + this->m_length = newlen; return *this; } + +// FUNCTION: BETA10 0x1012ca10 +void MxString::CharSwap(char* p_a, char* p_b) +{ + char t = *p_a; + *p_a = *p_b; + *p_b = t; +}