diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a47fc78..681b8a07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,6 +154,7 @@ add_library(lego1 SHARED LEGO1/mxsoundmanager.cpp LEGO1/mxsoundpresenter.cpp LEGO1/mxstillpresenter.cpp + LEGO1/mxstreamcontroller.cpp LEGO1/mxstreamer.cpp LEGO1/mxstring.cpp LEGO1/mxthread.cpp diff --git a/LEGO1/mxatomid.h b/LEGO1/mxatomid.h index 8efef679..7c89f35f 100644 --- a/LEGO1/mxatomid.h +++ b/LEGO1/mxatomid.h @@ -28,8 +28,11 @@ class MxAtomId { return this->m_internal == other.m_internal; } + void Clear(); + const char *GetInternal() const { return m_internal; } + private: MxAtomIdCounter* GetCounter(const char *, LookupMode); void Destroy(); diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp new file mode 100644 index 00000000..a149bb92 --- /dev/null +++ b/LEGO1/mxstreamcontroller.cpp @@ -0,0 +1,8 @@ +#include "mxstreamcontroller.h" + +// OFFSET: LEGO1 0x100c20d0 STUB +MxBool MxStreamController::IsStillInUse() +{ + // TODO + return TRUE; +} diff --git a/LEGO1/mxstreamcontroller.h b/LEGO1/mxstreamcontroller.h index 4ec95e9e..8c360166 100644 --- a/LEGO1/mxstreamcontroller.h +++ b/LEGO1/mxstreamcontroller.h @@ -2,6 +2,7 @@ #define MXSTREAMCONTROLLER_H #include "mxatomid.h" +#include "mxcriticalsection.h" #include "mxcore.h" // VTABLE 0x100dc968 @@ -21,13 +22,9 @@ class MxStreamController : public MxCore return !strcmp(name, MxStreamController::ClassName()) || MxCore::IsA(name); } - int m_unk08; - int m_unk0c; - int m_unk10; - int m_unk14; - int m_unk18; - int m_unk1c; - int m_unk20; + MxBool IsStillInUse(); + + MxCriticalSection m_criticalSection; MxAtomId atom; int m_unk28; int m_unk2c; diff --git a/LEGO1/mxstreamer.cpp b/LEGO1/mxstreamer.cpp index 12f51f99..ebb48d1f 100644 --- a/LEGO1/mxstreamer.cpp +++ b/LEGO1/mxstreamer.cpp @@ -1,26 +1,94 @@ #include "mxstreamer.h" -// OFFSET: LEGO1 0x100b91d0 STUB -MxStreamer::~MxStreamer() +#include "legoomni.h" + +DECOMP_SIZE_ASSERT(MxStreamer, 0x2c); + +// OFFSET: LEGO1 0x100b8f00 +MxStreamer::MxStreamer() { - // TODO + NotificationManager()->Register(this); } -// OFFSET: LEGO1 0x100b92c0 STUB -MxStreamController *MxStreamer::Open(const char *name, MxU16 p) +// OFFSET: LEGO1 0x100b9190 +MxResult MxStreamer::Init() +{ + undefined *b = new undefined[m_subclass1.GetSize() * 0x5800]; + m_subclass1.SetBuffer(b); + if (b) { + b = new undefined[m_subclass2.GetSize() * 0x800]; + m_subclass2.SetBuffer(b); + if (b) { + return SUCCESS; + } + } + + return FAILURE; +} + +// OFFSET: LEGO1 0x100b91d0 +MxStreamer::~MxStreamer() +{ + while (!m_openStreams.empty()) { + MxStreamController *c = m_openStreams.front(); + m_openStreams.pop_front(); + delete c; + } + + NotificationManager()->Unregister(this); +} + +// OFFSET: LEGO1 0x100b92c0 +MxStreamController *MxStreamer::Open(const char *name, MxU16 p_lookupType) { // TODO + + MxStreamController *c = GetOpenStream(name); + return NULL; } -// OFFSET: LEGO1 0x100b9570 STUB +// OFFSET: LEGO1 0x100b9570 MxLong MxStreamer::Close(const char *p) { - // TODO - return 0; + MxDSAction ds; + + ds.SetUnknown24(-2); + + for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { + MxStreamController *c = *it; + + if (!p || !strcmp(p, c->atom.GetInternal())) { + m_openStreams.erase(it); + + if (c->IsStillInUse()) { + // TODO: Send notification to `c` + } else { + delete c; + } + + return SUCCESS; + } + } + + return FAILURE; } -// OFFSET: LEGO1 0x100b9b60 STUB +// OFFSET: LEGO1 0x100b9870 +MxStreamController *MxStreamer::GetOpenStream(const char *p_name) +{ + for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { + if (p_name) { + if (!strcmp(((*it)->atom.GetInternal()), p_name)) { + return *it; + } + } + } + + return NULL; +} + +// OFFSET: LEGO1 0x100b9b60 MxLong MxStreamer::Notify(MxParam &p) { // TODO @@ -28,10 +96,13 @@ MxLong MxStreamer::Notify(MxParam &p) return 0; } -// OFFSET: LEGO1 0x100b9190 STUB -MxResult MxStreamer::VTable0x14() +// No offset, function is always inlined +MxStreamerSubClass1::MxStreamerSubClass1(undefined4 size) { - // TODO - - return MxResult(); + m_buffer = NULL; + m_size = size; + undefined4 *ptr = &m_unk08; + for (int i = 0; i >= 0; i--) { + ptr[i] = 0; + } } diff --git a/LEGO1/mxstreamer.h b/LEGO1/mxstreamer.h index f14ac66d..48bd804e 100644 --- a/LEGO1/mxstreamer.h +++ b/LEGO1/mxstreamer.h @@ -1,21 +1,77 @@ #ifndef MXSTREAMER_H #define MXSTREAMER_H +#include + +#include "decomp.h" #include "mxcore.h" #include "mxstreamcontroller.h" #include "mxtypes.h" +class MxStreamerSubClass1 +{ +public: + inline MxStreamerSubClass1(undefined4 size); + + ~MxStreamerSubClass1() { delete [] m_buffer; } + + undefined4 GetSize() { return m_size; } + + void SetBuffer(undefined *p_buf) { m_buffer = p_buf; } + +private: + undefined *m_buffer; + undefined4 m_size; + undefined4 m_unk08; +}; + +class MxStreamerSubClass2 : public MxStreamerSubClass1 +{ +public: + inline MxStreamerSubClass2() : MxStreamerSubClass1(0x40) {} +}; + +class MxStreamerSubClass3 : public MxStreamerSubClass1 +{ +public: + inline MxStreamerSubClass3() : MxStreamerSubClass1(0x80) {} +}; + // VTABLE 0x100dc710 +// SIZE 0x2c class MxStreamer : public MxCore { public: + MxStreamer(); virtual ~MxStreamer() override; __declspec(dllexport) MxStreamController *Open(const char *name, MxU16 p); __declspec(dllexport) MxLong Close(const char *p); virtual MxLong Notify(MxParam &p) override; // vtable+0x4 - virtual MxResult VTable0x14(); // vtable+0x14 + + // OFFSET: LEGO1 0x100b9000 + inline virtual const char *ClassName() const override // vtable+0x0c + { + // 0x1010210c + return "MxStreamer"; + } + + // OFFSET: LEGO1 0x100b9010 + inline virtual MxBool IsA(const char *name) const override // vtable+0x10 + { + return !strcmp(name, MxStreamer::ClassName()) || MxCore::IsA(name); + } + + virtual MxResult Init(); // vtable+0x14 + + MxStreamController *GetOpenStream(const char *p_name); + +private: + list m_openStreams; // 0x8 + MxStreamerSubClass2 m_subclass1; // 0x14 + MxStreamerSubClass3 m_subclass2; // 0x20 + }; #endif // MXSTREAMER_H