diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ac80152..0d02143c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -103,7 +103,7 @@ jobs: upload: needs: [build, compare] runs-on: ubuntu-latest - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'isledecomp/isle' }} steps: - uses: actions/checkout@v3 with: diff --git a/CMakeLists.txt b/CMakeLists.txt index 3645e122..2034c28a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,7 @@ add_library(lego1 SHARED LEGO1/legoworldpresenter.cpp LEGO1/motorcycle.cpp LEGO1/mxatomid.cpp + LEGO1/mxatomidcounter.cpp LEGO1/mxaudiopresenter.cpp LEGO1/mxautolocker.cpp LEGO1/mxbackgroundaudiomanager.cpp @@ -117,6 +118,7 @@ add_library(lego1 SHARED LEGO1/mxdsparallelaction.cpp LEGO1/mxdsselectaction.cpp LEGO1/mxdsserialaction.cpp + LEGO1/mxdsstreamingaction.cpp LEGO1/mxdssound.cpp LEGO1/mxdssource.cpp LEGO1/mxdsstill.cpp diff --git a/LEGO1/compat.h b/LEGO1/compat.h index c682dc0e..33b97d5a 100644 --- a/LEGO1/compat.h +++ b/LEGO1/compat.h @@ -14,17 +14,21 @@ // DIsable "nonstandard extension used : 'bool'" warning spam #pragma warning( disable : 4237 ) +// Disable "identifier was truncated to '255' characters" warning. +// Impossible to avoid this if using STL map or set. +// This removes most (but not all) occurrences of the warning. +#pragma warning( disable : 4786 ) + #define MSVC420_VERSION 1020 // STL compatibility. #if defined(_MSC_VER) && _MSC_VER <= MSVC420_VERSION -#include +#include "mxstl.h" #else #include #include +#include using namespace std; -template -using List = list; #endif // We use `override` so newer compilers can tell us our vtables are valid, diff --git a/LEGO1/mxatomid.cpp b/LEGO1/mxatomid.cpp index 007e2de3..092f5deb 100644 --- a/LEGO1/mxatomid.cpp +++ b/LEGO1/mxatomid.cpp @@ -1,20 +1,97 @@ #include "mxatomid.h" +#include "mxomni.h" // OFFSET: LEGO1 0x100acf90 -MxAtomId::MxAtomId(const char *, LookupMode) +MxAtomId::MxAtomId(const char *p_str, LookupMode p_mode) { - // TODO + if (!MxOmni::GetInstance()) + return; + + if (!AtomIdCounterSet()) + return; + + MxAtomIdCounter *counter = GetCounter(p_str, p_mode); + m_internal = counter->GetKey()->GetData(); + counter->Inc(); } // OFFSET: LEGO1 0x100acfd0 MxAtomId::~MxAtomId() { - // TODO + Destroy(); +} + +// OFFSET: LEGO1 0x100acfe0 +void MxAtomId::Destroy() +{ + if (!m_internal) + return; + + if (!MxOmni::GetInstance()) + return; + + if (!AtomIdCounterSet()) + return; + + // The dtor is called on the counter object immediately, + // so this syntax should be correct. + MxAtomIdCounterSet::iterator it = AtomIdCounterSet()->find( + &MxAtomIdCounter(m_internal) + ); + + MxAtomIdCounter *counter = (MxAtomIdCounter*)(*it); + counter->Dec(); } // OFFSET: LEGO1 0x100ad1c0 -MxAtomId &MxAtomId::operator=(const MxAtomId &id) +MxAtomId &MxAtomId::operator=(const MxAtomId &p_atomId) { - // TODO + if (m_internal) + Destroy(); + + if (p_atomId.m_internal && MxOmni::GetInstance() && AtomIdCounterSet()) { + MxAtomIdCounter *counter = GetCounter(p_atomId.m_internal, LookupMode_Exact); + counter->Inc(); + } + + m_internal = p_atomId.m_internal; + return *this; } + +// OFFSET: LEGO1 0x100ad210 +MxAtomIdCounter* MxAtomId::GetCounter(const char *p_str, LookupMode p_mode) +{ + MxAtomId _unused; + MxAtomIdCounter *counter = new MxAtomIdCounter(p_str); + + switch (p_mode) { + case LookupMode_LowerCase: + case LookupMode_LowerCase2: + counter->GetKey()->ToLowerCase(); + break; + case LookupMode_UpperCase: + counter->GetKey()->ToUpperCase(); + break; + } + + MxAtomIdCounterSet::iterator it = AtomIdCounterSet()->find(counter); + if (it != AtomIdCounterSet()->end()) { + // Counter already in the set. Delete temp value and return it. + delete counter; + counter = *it; + } else { + // Counter is not in the set. Add it. + AtomIdCounterSet()->insert(counter); + } + + return counter; +} + +// OFFSET: LEGO1 0x100ad7e0 +void MxAtomId::Clear() +{ + // Reset but do not delete MxAtomId object. + Destroy(); + m_internal = NULL; +} diff --git a/LEGO1/mxatomid.h b/LEGO1/mxatomid.h index 4a2082cf..8efef679 100644 --- a/LEGO1/mxatomid.h +++ b/LEGO1/mxatomid.h @@ -2,6 +2,7 @@ #define MXATOMID_H #include "mxtypes.h" +#include "mxatomidcounter.h" enum LookupMode { @@ -27,9 +28,13 @@ class MxAtomId { return this->m_internal == other.m_internal; } + void Clear(); private: - char *m_internal; + MxAtomIdCounter* GetCounter(const char *, LookupMode); + void Destroy(); + + const char *m_internal; }; #endif // MXATOMID_H diff --git a/LEGO1/mxatomidcounter.cpp b/LEGO1/mxatomidcounter.cpp new file mode 100644 index 00000000..a38dbe6f --- /dev/null +++ b/LEGO1/mxatomidcounter.cpp @@ -0,0 +1,18 @@ +#include "mxatomidcounter.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxAtomIdCounter, 0x14); +DECOMP_SIZE_ASSERT(MxAtomIdCounterSet, 0x10); + +// OFFSET: LEGO1 0x100ad7f0 +void MxAtomIdCounter::Inc() +{ + m_value++; +} + +// OFFSET: LEGO1 0x100ad800 +void MxAtomIdCounter::Dec() +{ + if (m_value) + m_value--; +} diff --git a/LEGO1/mxatomidcounter.h b/LEGO1/mxatomidcounter.h new file mode 100644 index 00000000..79e7c7f5 --- /dev/null +++ b/LEGO1/mxatomidcounter.h @@ -0,0 +1,49 @@ +#ifndef MXATOMIDCOUNTER_H +#define MXATOMIDCOUNTER_H + +#include "mxstring.h" +#include "compat.h" // STL + +// Counts the number of existing MxAtomId objects based +// on the matching char* string. A seems fit for purpose here: +// We have an MxString as a key and MxU16 as the value. +// And yet a is the best match. The malloc in MxOmni::Create +// for the _Nil node asks for more bytes than a regular node if a +// is used, but all nodes are 20 bytes wide with a . +// 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) +class MxAtomIdCounter +{ +public: + // always inlined + MxAtomIdCounter(const char *p_str) + { + m_key = p_str; + m_value = 0; + } + + void Inc(); + void Dec(); + inline MxString* GetKey() { return &m_key; }; + inline MxU16 GetValue() { return m_value; }; + +private: + MxString m_key; + MxU16 m_value; +}; + +struct MxAtomIdCounterCompare +{ + // OFFSET: LEGO1 0x100ad120 + int operator()(MxAtomIdCounter* const & p_val0, MxAtomIdCounter* const & p_val1) const + { + return strcmp(p_val0->GetKey()->GetData(), p_val1->GetKey()->GetData()) > 0; + } +}; + +class MxAtomIdCounterSet : public set +{}; + +#endif //MXATOMIDCOUNTER_H \ No newline at end of file diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index 2d177f8f..843d8275 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -46,8 +46,12 @@ class MxDSAction : public MxDSObject MxU32 m_sizeOnDisk; DWORD m_flags; DWORD m_startTime; + +protected: MxLong m_duration; MxS32 m_loopCount; + +private: MxVector3Data m_location; MxVector3Data m_direction; MxVector3Data m_up; diff --git a/LEGO1/mxdsanim.cpp b/LEGO1/mxdsanim.cpp index b9b887cd..050d40e0 100644 --- a/LEGO1/mxdsanim.cpp +++ b/LEGO1/mxdsanim.cpp @@ -1,5 +1,7 @@ #include "mxdsanim.h" +DECOMP_SIZE_ASSERT(MxDSAnim, 0xb8) + // OFFSET: LEGO1 0x100c8ff0 MxDSAnim::MxDSAnim() { @@ -10,3 +12,30 @@ MxDSAnim::MxDSAnim() MxDSAnim::~MxDSAnim() { } + +// OFFSET: LEGO1 0x100c91f0 +void MxDSAnim::CopyFrom(MxDSAnim &p_dsAnim) +{ +} + +// OFFSET: LEGO1 0x100c9200 +MxDSAnim &MxDSAnim::operator=(MxDSAnim &p_dsAnim) +{ + if (this == &p_dsAnim) + return *this; + + MxDSMediaAction::operator=(p_dsAnim); + this->CopyFrom(p_dsAnim); + return *this; +} + +// OFFSET: LEGO1 0x100c9230 +MxDSAction *MxDSAnim::Clone() +{ + MxDSAnim *clone = new MxDSAnim(); + + if (clone) + *clone = *this; + + return clone; +} \ No newline at end of file diff --git a/LEGO1/mxdsanim.h b/LEGO1/mxdsanim.h index fdef0859..92890e8e 100644 --- a/LEGO1/mxdsanim.h +++ b/LEGO1/mxdsanim.h @@ -9,9 +9,11 @@ class MxDSAnim : public MxDSMediaAction { public: MxDSAnim(); - virtual ~MxDSAnim() override; + void CopyFrom(MxDSAnim &p_dsAnim); + MxDSAnim &operator=(MxDSAnim &p_dsAnim); + // OFFSET: LEGO1 0x100c9060 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -24,6 +26,8 @@ class MxDSAnim : public MxDSMediaAction { return !strcmp(name, MxDSAnim::ClassName()) || MxDSMediaAction::IsA(name); } + + virtual MxDSAction *Clone(); // vtable+2c; }; #endif // MXDSANIM_H diff --git a/LEGO1/mxdsevent.cpp b/LEGO1/mxdsevent.cpp index b6571075..2894f074 100644 --- a/LEGO1/mxdsevent.cpp +++ b/LEGO1/mxdsevent.cpp @@ -1,5 +1,7 @@ #include "mxdsevent.h" +DECOMP_SIZE_ASSERT(MxDSEvent, 0xb8) + // OFFSET: LEGO1 0x100c95f0 MxDSEvent::MxDSEvent() { @@ -10,3 +12,30 @@ MxDSEvent::MxDSEvent() MxDSEvent::~MxDSEvent() { } + +// OFFSET: LEGO1 0x100c97f0 +void MxDSEvent::CopyFrom(MxDSEvent &p_dsEvent) +{ +} + +// OFFSET: LEGO1 0x100c9800 +MxDSEvent &MxDSEvent::operator=(MxDSEvent &p_dsEvent) +{ + if (this == &p_dsEvent) + return *this; + + MxDSMediaAction::operator=(p_dsEvent); + this->CopyFrom(p_dsEvent); + return *this; +} + +// OFFSET: LEGO1 0x100c9830 +MxDSAction *MxDSEvent::Clone() +{ + MxDSEvent *clone = new MxDSEvent(); + + if (clone) + *clone = *this; + + return clone; +} \ No newline at end of file diff --git a/LEGO1/mxdsevent.h b/LEGO1/mxdsevent.h index 59a00bb5..b8fedace 100644 --- a/LEGO1/mxdsevent.h +++ b/LEGO1/mxdsevent.h @@ -9,6 +9,9 @@ class MxDSEvent : public MxDSMediaAction MxDSEvent(); virtual ~MxDSEvent() override; + void CopyFrom(MxDSEvent &p_dsEvent); + MxDSEvent &operator=(MxDSEvent &p_dsEvent); + // OFFSET: LEGO1 0x100c9660 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -21,6 +24,8 @@ class MxDSEvent : public MxDSMediaAction { return !strcmp(name, MxDSEvent::ClassName()) || MxDSMediaAction::IsA(name); } + + virtual MxDSAction *Clone(); // vtable+2c; }; #endif // MXDSEVENT_H diff --git a/LEGO1/mxdsobject.h b/LEGO1/mxdsobject.h index 5dfc894c..c46ee609 100644 --- a/LEGO1/mxdsobject.h +++ b/LEGO1/mxdsobject.h @@ -42,6 +42,7 @@ class MxDSObject : public MxCore protected: inline void SetType(MxDSType p_type) { this->m_type = p_type; } + inline MxDSType GetType() { return (MxDSType) this->m_type; } private: MxU32 m_sizeOnDisk; diff --git a/LEGO1/mxdsobjectaction.cpp b/LEGO1/mxdsobjectaction.cpp index d468f30a..a51cdb87 100644 --- a/LEGO1/mxdsobjectaction.cpp +++ b/LEGO1/mxdsobjectaction.cpp @@ -1,5 +1,7 @@ #include "mxdsobjectaction.h" +DECOMP_SIZE_ASSERT(MxDSObjectAction, 0xb8) + // OFFSET: LEGO1 0x100c8870 MxDSObjectAction::MxDSObjectAction() { @@ -10,3 +12,30 @@ MxDSObjectAction::MxDSObjectAction() MxDSObjectAction::~MxDSObjectAction() { } + +// OFFSET: LEGO1 0x100c8a70 +void MxDSObjectAction::CopyFrom(MxDSObjectAction &p_dsObjectAction) +{ +} + +// OFFSET: LEGO1 0x100c8a80 +MxDSObjectAction &MxDSObjectAction::operator=(MxDSObjectAction &p_dsObjectAction) +{ + if (this == &p_dsObjectAction) + return *this; + + MxDSMediaAction::operator=(p_dsObjectAction); + this->CopyFrom(p_dsObjectAction); + return *this; +} + +// OFFSET: LEGO1 0x100c8ab0 +MxDSAction *MxDSObjectAction::Clone() +{ + MxDSObjectAction *clone = new MxDSObjectAction(); + + if (clone) + *clone = *this; + + return clone; +} diff --git a/LEGO1/mxdsobjectaction.h b/LEGO1/mxdsobjectaction.h index 12e147fc..4a1b68bb 100644 --- a/LEGO1/mxdsobjectaction.h +++ b/LEGO1/mxdsobjectaction.h @@ -11,6 +11,8 @@ class MxDSObjectAction : public MxDSMediaAction MxDSObjectAction(); virtual ~MxDSObjectAction() override; + MxDSObjectAction &operator=(MxDSObjectAction &p_dsObjectAction); + // OFFSET: LEGO1 0x100c88e0 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -23,6 +25,9 @@ class MxDSObjectAction : public MxDSMediaAction { return !strcmp(name, MxDSObjectAction::ClassName()) || MxDSMediaAction::IsA(name); } + + virtual MxDSAction *Clone(); // vtable+2c; + virtual void CopyFrom(MxDSObjectAction &p_dsObjectAction); // vtable+44; }; #endif // MXDSOBJECTACTION_H diff --git a/LEGO1/mxdssound.cpp b/LEGO1/mxdssound.cpp index d05f785d..cbb1c057 100644 --- a/LEGO1/mxdssound.cpp +++ b/LEGO1/mxdssound.cpp @@ -1,9 +1,11 @@ #include "mxdssound.h" +DECOMP_SIZE_ASSERT(MxDSSound, 0xc0) + // OFFSET: LEGO1 0x100c92c0 MxDSSound::MxDSSound() { - this->m_lastField = 0x4f; + this->m_volume = 0x4f; this->SetType(MxDSType_Sound); } @@ -11,3 +13,50 @@ MxDSSound::MxDSSound() MxDSSound::~MxDSSound() { } + +// OFFSET: LEGO1 0x100c94c0 +void MxDSSound::CopyFrom(MxDSSound &p_dsSound) +{ + this->SetType(p_dsSound.GetType()); + this->m_volume = p_dsSound.m_volume; +} + +// OFFSET: LEGO1 0x100c94e0 +MxDSSound &MxDSSound::operator=(MxDSSound &p_dsSound) +{ + if (this == &p_dsSound) + return *this; + + MxDSMediaAction::operator=(p_dsSound); + this->CopyFrom(p_dsSound); + return *this; +} + +// OFFSET: LEGO1 0x100c95d0 +MxU32 MxDSSound::GetSizeOnDisk() +{ + MxU32 totalSizeOnDisk = MxDSMediaAction::GetSizeOnDisk(); + + this->m_sizeOnDisk = sizeof(this->m_volume); + return totalSizeOnDisk + 4; +} + +// OFFSET: LEGO1 0x100c95a0 +void MxDSSound::Deserialize(char **p_source, MxS16 p_unk24) +{ + MxDSMediaAction::Deserialize(p_source, p_unk24); + + this->m_volume = *(MxS32*) *p_source; + *p_source += sizeof(MxS32); +} + +// OFFSET: LEGO1 0x100c9510 +MxDSAction *MxDSSound::Clone() +{ + MxDSSound *clone = new MxDSSound(); + + if (clone) + *clone = *this; + + return clone; +} \ No newline at end of file diff --git a/LEGO1/mxdssound.h b/LEGO1/mxdssound.h index eca6c055..de345e51 100644 --- a/LEGO1/mxdssound.h +++ b/LEGO1/mxdssound.h @@ -2,7 +2,6 @@ #define MXDSSOUND_H #include "mxdsmediaaction.h" -#include "mxtypes.h" // VTABLE 0x100dcdd0 // SIZE 0xc0 @@ -12,6 +11,9 @@ class MxDSSound : public MxDSMediaAction MxDSSound(); virtual ~MxDSSound() override; + void CopyFrom(MxDSSound &p_dsSound); + MxDSSound &operator=(MxDSSound &p_dsSound); + // OFFSET: LEGO1 0x100c9330 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -24,10 +26,14 @@ class MxDSSound : public MxDSMediaAction { return !strcmp(name, MxDSSound::ClassName()) || MxDSMediaAction::IsA(name); } + + virtual MxU32 GetSizeOnDisk(); // vtable+18; + virtual void Deserialize(char **p_source, MxS16 p_unk24); // vtable+1c; + virtual MxDSAction *Clone(); // vtable+2c; + private: - MxS32 m_unkb8; - MxLong m_lastField; // 0xbc + MxU32 m_sizeOnDisk; + MxS32 m_volume; // 0xbc }; - #endif // MXDSSOUND_H diff --git a/LEGO1/mxdsstill.cpp b/LEGO1/mxdsstill.cpp index 938afe83..6d9a78a2 100644 --- a/LEGO1/mxdsstill.cpp +++ b/LEGO1/mxdsstill.cpp @@ -1,5 +1,7 @@ #include "mxdsstill.h" +DECOMP_SIZE_ASSERT(MxDSStill, 0xb8) + // OFFSET: LEGO1 0x100c98c0 MxDSStill::MxDSStill() { @@ -10,3 +12,30 @@ MxDSStill::MxDSStill() MxDSStill::~MxDSStill() { } + +// OFFSET: LEGO1 0x100c9ac0 +void MxDSStill::CopyFrom(MxDSStill &p_dsStill) +{ +} + +// OFFSET: LEGO1 0x100c9ad0 +MxDSStill &MxDSStill::operator=(MxDSStill &p_dsStill) +{ + if (this == &p_dsStill) + return *this; + + MxDSMediaAction::operator=(p_dsStill); + this->CopyFrom(p_dsStill); + return *this; +} + +// OFFSET: LEGO1 0x100c9b00 +MxDSAction *MxDSStill::Clone() +{ + MxDSStill *clone = new MxDSStill(); + + if (clone) + *clone = *this; + + return clone; +} \ No newline at end of file diff --git a/LEGO1/mxdsstill.h b/LEGO1/mxdsstill.h index 920f890a..084fe931 100644 --- a/LEGO1/mxdsstill.h +++ b/LEGO1/mxdsstill.h @@ -11,6 +11,9 @@ class MxDSStill : public MxDSMediaAction MxDSStill(); virtual ~MxDSStill() override; + void CopyFrom(MxDSStill &p_dsStill); + MxDSStill &operator=(MxDSStill &p_dsStill); + // OFFSET: LEGO1 0x100c9930 inline virtual const char *ClassName() const override // vtable+0x0c { @@ -23,6 +26,8 @@ class MxDSStill : public MxDSMediaAction { return !strcmp(name, MxDSStill::ClassName()) || MxDSMediaAction::IsA(name); } + + virtual MxDSAction *Clone(); // vtable+2c; }; #endif // MXDSSTILL_H diff --git a/LEGO1/mxdsstreamingaction.cpp b/LEGO1/mxdsstreamingaction.cpp new file mode 100644 index 00000000..ab04c19e --- /dev/null +++ b/LEGO1/mxdsstreamingaction.cpp @@ -0,0 +1,91 @@ +#include "mxdsstreamingaction.h" + +DECOMP_SIZE_ASSERT(MxDSStreamingAction, 0xb4) + +// OFFSET: LEGO1 0x100cd010 +MxDSStreamingAction::MxDSStreamingAction(MxDSAction &p_dsAction, MxU32 p_offset) +{ + Init(); + + *this = p_dsAction; + this->m_unk94 = p_offset; + this->m_bufferOffset = p_offset; +} + +// OFFSET: LEGO1 0x100cd0d0 +MxDSStreamingAction::MxDSStreamingAction(MxDSStreamingAction &p_dsStreamingAction) +{ + Init(); + CopyFrom(p_dsStreamingAction); +} + +// OFFSET: LEGO1 0x100cd150 +MxDSStreamingAction::~MxDSStreamingAction() +{ + // TODO: Implement MxDSBuffer + if (this->m_unka0) + delete this->m_unka0; + if (this->m_unka4) + delete this->m_unka4; + if (this->m_internalAction) + delete this->m_internalAction; +} + +// OFFSET: LEGO1 0x100cd220 +MxDSStreamingAction *MxDSStreamingAction::CopyFrom(MxDSStreamingAction &p_dsStreamingAction) +{ + *this = p_dsStreamingAction; + this->m_unk94 = p_dsStreamingAction.m_unk94; + this->m_bufferOffset = p_dsStreamingAction.m_bufferOffset; + this->m_unk9c = p_dsStreamingAction.m_unk9c; + this->m_unka0 = NULL; + this->m_unka4 = NULL; + this->m_unkac = p_dsStreamingAction.m_unkac; + this->m_unka8 = p_dsStreamingAction.m_unka8; + SetInternalAction(p_dsStreamingAction.m_internalAction ? p_dsStreamingAction.m_internalAction->Clone() : NULL); + + return this; +} + +// OFFSET: LEGO1 0x100cd090 +MxBool MxDSStreamingAction::HasId(MxU32 p_objectId) +{ + if (this->m_internalAction) + return this->m_internalAction->HasId(p_objectId); + return FALSE; +} + +// OFFSET: LEGO1 0x100cd1e0 +MxResult MxDSStreamingAction::Init() +{ + this->m_unk94 = 0; + this->m_bufferOffset = 0; + this->m_unk9c = 0; + this->m_unka0 = NULL; + this->m_unka4 = NULL; + this->m_unka8 = 0; + this->m_unkac = 2; + this->m_internalAction = NULL; + return SUCCESS; +} + +// OFFSET: LEGO1 0x100cd2a0 +void MxDSStreamingAction::SetInternalAction(MxDSAction *p_dsAction) +{ + if (this->m_internalAction) + delete this->m_internalAction; + this->m_internalAction = p_dsAction; +} + +// OFFSET: LEGO1 0x100cd2d0 +void MxDSStreamingAction::FUN_100CD2D0() +{ + if (this->m_duration == -1) + return; + + MxLong duration = this->m_duration / this->m_loopCount; + this->m_loopCount--; + + this->m_duration -= duration; + this->m_unka8 += duration; +} \ No newline at end of file diff --git a/LEGO1/mxdsstreamingaction.h b/LEGO1/mxdsstreamingaction.h new file mode 100644 index 00000000..d50dbed8 --- /dev/null +++ b/LEGO1/mxdsstreamingaction.h @@ -0,0 +1,44 @@ +#ifndef MXDSSTREAMINGACTION_H +#define MXDSSTREAMINGACTION_H + +#include "mxdsaction.h" + +class MxDSBuffer; + +// VTABLE 0x100dd088 +// SIZE 0xb4 +class MxDSStreamingAction : public MxDSAction +{ +public: + MxDSStreamingAction(MxDSAction &p_dsAction, MxU32 p_offset); + MxDSStreamingAction(MxDSStreamingAction &p_dsStreamingAction); + virtual ~MxDSStreamingAction(); + + MxDSStreamingAction *CopyFrom(MxDSStreamingAction &p_dsStreamingAction); + MxDSStreamingAction &operator=(MxDSAction &p_dsAction) { + MxDSAction::operator=(p_dsAction); + return *this; + } + MxDSStreamingAction &operator=(MxDSStreamingAction &p_dsStreamingAction) { + MxDSAction::operator=(p_dsStreamingAction); + return *this; + } + + virtual MxBool HasId(MxU32 p_objectId); // vtable+34; + + MxResult Init(); + void SetInternalAction(MxDSAction *p_dsAction); + void FUN_100CD2D0(); + +private: + MxU32 m_unk94; + MxU32 m_bufferOffset; + MxS32 m_unk9c; + MxDSBuffer *m_unka0; + MxDSBuffer *m_unka4; + MxLong m_unka8; + undefined2 m_unkac; + MxDSAction *m_internalAction; +}; + +#endif // MXDSSTREAMINGACTION_H diff --git a/LEGO1/mxnotificationmanager.h b/LEGO1/mxnotificationmanager.h index e313510b..1c2aee7c 100644 --- a/LEGO1/mxnotificationmanager.h +++ b/LEGO1/mxnotificationmanager.h @@ -28,10 +28,10 @@ class MxNotification MxParam *m_param; // 0x4 }; -class MxIdList : public List +class MxIdList : public list {}; -class MxNotificationPtrList : public List +class MxNotificationPtrList : public list {}; // VTABLE 0x100dc078 diff --git a/LEGO1/mxomni.cpp b/LEGO1/mxomni.cpp index f5022b30..4048a0b5 100644 --- a/LEGO1/mxomni.cpp +++ b/LEGO1/mxomni.cpp @@ -38,7 +38,7 @@ void MxOmni::Init() m_eventManager = NULL; m_timer = NULL; m_streamer = NULL; - m_unk44 = NULL; + m_atomIdCounterSet = NULL; m_unk64 = NULL; } @@ -104,6 +104,8 @@ void MxOmni::SetInstance(MxOmni *instance) // OFFSET: LEGO1 0x100af0c0 MxResult MxOmni::Create(MxOmniCreateParam &p) { + m_atomIdCounterSet = new MxAtomIdCounterSet(); + if (p.CreateFlags().CreateVariableTable()) { MxVariableTable *variableTable = new MxVariableTable(); @@ -129,6 +131,40 @@ MxResult MxOmni::Create(MxOmniCreateParam &p) void MxOmni::Destroy() { // FIXME: Stub + + /* + // TODO: private members + if (m_notificationManager) { + while (m_notificationManager->m_queue->size()) { + m_notificationManager->Tickle(); + } + } + + m_notificationManager->m_active = 0; + */ + + delete m_eventManager; + delete m_soundManager; + delete m_musicManager; + delete m_videoManager; + delete m_streamer; + delete m_timer; + delete m_objectFactory; + delete m_variableTable; + delete m_notificationManager; + delete m_tickleManager; + + // There could be a tree/iterator function that does this inline + if (m_atomIdCounterSet) { + while (!m_atomIdCounterSet->empty()) { + // Pop each node and delete its value + MxAtomIdCounterSet::iterator begin = m_atomIdCounterSet->begin(); + MxAtomIdCounter *value = *begin; + m_atomIdCounterSet->erase(begin); + delete value; + } + delete m_atomIdCounterSet; + } } // OFFSET: LEGO1 0x100b07f0 @@ -162,6 +198,12 @@ MxTimer *Timer() return MxOmni::GetInstance()->GetTimer(); } +// OFFSET: LEGO1 0x100acee0 +MxAtomIdCounterSet *AtomIdCounterSet() +{ + return MxOmni::GetInstance()->GetAtomIdCounterSet(); +} + // OFFSET: LEGO1 0x100acef0 MxStreamer* Streamer() { diff --git a/LEGO1/mxomni.h b/LEGO1/mxomni.h index b09d11ad..fb0a9f3e 100644 --- a/LEGO1/mxomni.h +++ b/LEGO1/mxomni.h @@ -14,6 +14,7 @@ #include "mxtimer.h" #include "mxvariabletable.h" #include "mxvideomanager.h" +#include "mxatomidcounter.h" // VTABLE 0x100dc168 // SIZE 0x68 @@ -47,6 +48,7 @@ class MxOmni : public MxCore MxVariableTable* GetVariableTable() const { return this->m_variableTable; } MxMusicManager* GetMusicManager() const { return this->m_musicManager; } MxEventManager* GetEventManager() const { return this->m_eventManager; } + MxAtomIdCounterSet* GetAtomIdCounterSet() const { return this->m_atomIdCounterSet; } protected: static MxOmni* g_instance; @@ -63,7 +65,7 @@ class MxOmni : public MxCore MxTimer* m_timer; //0x3C MxStreamer* m_streamer; //0x40 - int m_unk44; // 0x44 + MxAtomIdCounterSet* m_atomIdCounterSet; // 0x44 MxCriticalSection m_criticalsection; // 0x48 @@ -78,5 +80,6 @@ __declspec(dllexport) MxMusicManager * MusicManager(); __declspec(dllexport) MxEventManager * EventManager(); __declspec(dllexport) MxNotificationManager * NotificationManager(); MxVideoManager * MVideoManager(); +MxAtomIdCounterSet* AtomIdCounterSet(); #endif // MXOMNI_H diff --git a/LEGO1/mxstl.h b/LEGO1/mxstl.h new file mode 100644 index 00000000..8ee3d1dd --- /dev/null +++ b/LEGO1/mxstl.h @@ -0,0 +1,218 @@ +#ifndef MXSTL_H +#define MXSTL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef _MSC_VER +/* + * Currently, all MS C compilers for Win32 platforms default to 8 byte + * alignment. + */ +#pragma pack(push,8) +#endif // _MSC_VER + +template +class Deque : public deque<_TYPE, allocator<_TYPE> > +{ +public: + typedef Deque<_TYPE> _Myt; + typedef allocator<_TYPE> _A; + + explicit Deque(const _A& _Al = _A()) : deque<_TYPE, _A>(_Al) + {} + + explicit Deque(size_type _N, const _TYPE& _V = _TYPE()) : deque<_TYPE, _A>(_N, _V) + {} + + void swap(_Myt& _X) + { + deque<_TYPE, _A>::swap((deque<_TYPE, _A>&)_X); + } + + friend void swap(_Myt& _X, _Myt& _Y) + { + _X.swap(_Y); + } +}; + +template +class List : public list<_TYPE, allocator<_TYPE> > +{ +public: + typedef List<_TYPE> _Myt; + typedef allocator<_TYPE> _A; + + explicit List() : list<_TYPE, _A>() + {} + + explicit List(size_type _N, const _TYPE& _V = _TYPE()) : list<_TYPE, _A>(_N, _V) + {} + + void swap(_Myt& _X) + { + list<_TYPE, _A>::swap((list<_TYPE, _A>&)_X); + } + + friend void swap(_Myt& _X, _Myt& _Y) + { + _X.swap(_Y); + } +}; + +template +class Map : public map<_K, _TYPE, _Pr, allocator<_TYPE> > +{ +public: + typedef Map<_K, _TYPE, _Pr> _Myt; + typedef allocator<_TYPE> _A; + + explicit Map(const _Pr& _Pred = _Pr()) + : map<_K, _TYPE, _Pr, _A>(_Pred) + {} + + void swap(_Myt& _X) + { + map<_K, _TYPE, _Pr, _A>::swap((map<_K, _TYPE, _Pr, _A>&)_X); + } + + friend void swap(_Myt& _X, _Myt& _Y) + { + _X.swap(_Y); + } +}; + +template +class Multimap : public multimap<_K, _TYPE, _Pr, allocator<_TYPE> > +{ +public: + typedef Multimap<_K, _TYPE, _Pr> _Myt; + typedef allocator<_TYPE> _A; + + explicit Multimap(const _Pr& _Pred = _Pr()) : multimap<_K, _TYPE, _Pr, _A>(_Pred) + {} + + void swap(_Myt& _X) + { + multimap<_K, _TYPE, _Pr, _A>::swap((multimap<_K, _TYPE, _Pr, _A>&)_X); + } + + friend void swap(_Myt& _X, _Myt& _Y) + { + _X.swap(_Y); + } +}; + +template +class Set : public set<_K, _Pr, allocator<_K> > +{ +public: + typedef Set<_K, _Pr> _Myt; + typedef allocator<_K> _A; + + explicit Set(const _Pr& _Pred = _Pr()) : set<_K, _Pr, _A>(_Pred) + {} + + void swap(_Myt& _X) + { + set<_K, _Pr, _A>::swap((set<_K, _Pr, _A>&)_X); + } + + friend void swap(_Myt& _X, _Myt& _Y) + { + _X.swap(_Y); + } +}; + +template +class Multiset : public multiset<_K, _Pr, allocator<_K> > +{ +public: + typedef Multiset<_K, _Pr> _Myt; + typedef allocator<_K> _A; + + explicit Multiset(const _Pr& _Pred = _Pr()) + : multiset<_K, _Pr, _A>(_Pred) + {} + + void swap(_Myt& _X) + { + multiset<_K, _Pr, _A>::swap((multiset<_K, _Pr, _A>&)_X); + } + + friend void swap(_Myt& _X, _Myt& _Y) + { + _X.swap(_Y); + } +}; + +template +class Vector : public vector<_TYPE, allocator<_TYPE> > +{ +public: + typedef Vector<_TYPE> _Myt; + typedef allocator<_TYPE> _A; + + explicit Vector(const _A& _Al = _A()) : vector<_TYPE, _A>(_Al) + {} + + void swap(_Myt& _X) + { + vector<_TYPE, _A>::swap((vector<_TYPE, _A>&)_X); + } + + friend void swap(_Myt& _X, _Myt& _Y) + { + _X.swap(_Y); + } +}; + +template +class Priority_queue : public priority_queue<_C::value_type, _C, _Pr, _C::allocator_type> +{ +public: + typedef _C::value_type _TYPE; + typedef _C::allocator_type _A; + typedef _C::allocator_type allocator_type; + + explicit Priority_queue(const _Pr& _X = _Pr(), const _C::allocator_type& _Al = _C::allocator_type()) : priority_queue<_C::value_type, _C, _Pr, _C::allocator_type>(_X, _Al) + {} +}; + +template +class Queue : public queue<_C::value_type, _C, _C::allocator_type> +{}; + +template +class Stack : public stack<_C::value_type, _C, _C::allocator_type> +{}; + +#define deque Deque +#define list List +#define map Map +#define multimap Multimap +#define set Set +#define multiset Multiset +#define vector Vector +#define priority_queue Priority_queue +#define queue Queue +#define stack Stack + +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +#endif // MXSTL_H diff --git a/LEGO1/mxticklemanager.h b/LEGO1/mxticklemanager.h index 103d3721..cc7b6282 100644 --- a/LEGO1/mxticklemanager.h +++ b/LEGO1/mxticklemanager.h @@ -53,7 +53,7 @@ class MxTickleClient MxU16 m_flags; // 0xc }; -class MxTickleClientPtrList : public List +class MxTickleClientPtrList : public list {}; // VTABLE 0x100d86d8