diff --git a/LEGO1/mxdiskstreamprovider.cpp b/LEGO1/mxdiskstreamprovider.cpp index c7e311eb..bd52e3a4 100644 --- a/LEGO1/mxdiskstreamprovider.cpp +++ b/LEGO1/mxdiskstreamprovider.cpp @@ -77,10 +77,50 @@ MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource) return result; } -// STUB: LEGO1 0x100d15e0 +// FUNCTION: LEGO1 0x100d15e0 void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) { - // TODO + MxDSStreamingAction* action; + if (p_action->GetObjectId() == -1) { + m_unk0x35 = 1; + do { + { + MxAutoLocker lock(&m_criticalSection); + action = NULL; + if (m_list.size()) { + m_list.pop_front(); + } + } + + if (action == NULL) { + return; + } + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) { + g_unk0x10102878--; + } + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action != NULL); + } + else { + do { + { + MxAutoLocker lock(&m_criticalSection); + action = (MxDSStreamingAction*) m_list.Find(p_action, TRUE); + } + + if (action == NULL) { + return; + } + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) { + g_unk0x10102878--; + } + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action != NULL); + } } // FUNCTION: LEGO1 0x100d1750 diff --git a/LEGO1/mxdsbuffer.cpp b/LEGO1/mxdsbuffer.cpp index 261f00d3..d7f4d64d 100644 --- a/LEGO1/mxdsbuffer.cpp +++ b/LEGO1/mxdsbuffer.cpp @@ -246,7 +246,7 @@ MxResult MxDSBuffer::StartPresenterFromAction( return SUCCESS; } -// STUB: LEGO1 0x100c6a50 +// FUNCTION: LEGO1 0x100c6a50 MxResult MxDSBuffer::ParseChunk( MxStreamController* p_controller, MxU32* p_data, @@ -255,8 +255,63 @@ MxResult MxDSBuffer::ParseChunk( MxStreamChunk* p_header ) { - // TODO - return FAILURE; + MxResult result = SUCCESS; + + if ((m_unk0x30->GetFlags() & 4) == 0 || m_unk0x30->GetUnknowna4() == NULL || -1 < p_header->GetTime()) { + MxLong& ptr = p_header->GetTimeRef(); + ptr = ptr + m_unk0x30->GetUnknowna8(); + + if ((p_header->GetFlags() & 0x10) == 0) { + if ((p_header->GetFlags() & 2) != 0) { + if (m_unk0x30->HasId(p_header->GetObjectId())) { + // this could be an inlined function + if ((m_unk0x30->GetFlags() & 4) == 0 || + m_unk0x30->GetLoopCount() < 2 && m_unk0x30->GetDuration() != -1) { + if (p_action->GetObjectId() == m_unk0x30->GetObjectId() && + p_controller->VTable0x30(p_action) == SUCCESS) { + p_controller->GetProvider()->VTable0x20(p_action); + result = 1; + } + } + else { + OutputDebugString("Case A not implemented in parse Chunk\n"); + } + } + } + + if (p_header) { + if (p_header->SendChunk(p_controller->GetSubscriberList(), TRUE, p_action->GetUnknown24()) != SUCCESS) + { + delete p_header; + } + } + } + else { + MxDSBuffer* buffer = new MxDSBuffer(); + if (buffer) { + if (buffer->AllocateBuffer(p_header->GetLength() + 8 + MxDSChunk::ReturnE(), MxDSBufferType_Allocate) == + SUCCESS && + CalcBytesRemaining((MxU8*) p_data) == SUCCESS) { + MxDSStreamingAction* streamingAction = new MxDSStreamingAction((MxDSStreamingAction&) *p_action); + *p_streamingAction = streamingAction; + if (streamingAction) { + MxU32* ptr2 = MxStreamChunk::ReturnPlus8Ptr((MxU32*) m_pBuffer); + *ptr2 = *ptr2 & 0xffef; + delete p_header; + (*p_streamingAction)->SetUnknowna0(buffer); + return SUCCESS; + } + } + delete buffer; + } + delete p_header; + } + } + else { + delete p_header; + result = SUCCESS; + } + return result; } // FUNCTION: LEGO1 0x100c6d00 @@ -343,11 +398,37 @@ void MxDSBuffer::AddRef(MxDSChunk* p_chunk) } } -// STUB: LEGO1 0x100c6ef0 +// FUNCTION: LEGO1 0x100c6ef0 MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) { - // TODO - return FAILURE; + MxResult result = FAILURE; + MxU8* ptr; + MxU32 bytesRead; + if (m_mode == MxDSBufferType_Allocate) { + if (m_bytesRemaining != 0) { + + if (m_writeOffset == m_bytesRemaining) { + bytesRead = (*(MxU32*) p_data) + 8; + ptr = p_data; + } + else { + ptr = &p_data[MxStreamChunk::ReturnE() + 8]; + bytesRead = (*(MxU32*) p_data) - MxStreamChunk::ReturnE(); + } + + if (bytesRead <= m_bytesRemaining) { + memcpy(m_pBuffer + (m_writeOffset - m_bytesRemaining), ptr, bytesRead); + if (m_writeOffset == m_bytesRemaining) { + MxU8* buffer = m_pBuffer; + buffer[1] = *MxStreamChunk::ReturnPlus18Ptr((MxU32*) buffer) + MxStreamChunk::ReturnE(); + } + + result = SUCCESS; + m_bytesRemaining = m_bytesRemaining - bytesRead; + } + } + } + return result; } // FUNCTION: LEGO1 0x100c6f80 diff --git a/LEGO1/mxdschunk.h b/LEGO1/mxdschunk.h index 4cbb2fc9..9b7f8136 100644 --- a/LEGO1/mxdschunk.h +++ b/LEGO1/mxdschunk.h @@ -42,9 +42,16 @@ class MxDSChunk : public MxCore { inline MxU16 GetFlags() { return m_flags; } inline undefined4 GetObjectId() { return m_objectId; } inline MxLong GetTime() { return m_time; } + inline MxLong& GetTimeRef() { return m_time; } inline MxU32 GetLength() { return m_length; } inline MxU8* GetData() { return m_data; } + // FUNCTION: LEGO1 0x100be1e0 + static MxU32 ReturnE() + { + return 0xe; + } + inline void Release() { if (m_data) diff --git a/LEGO1/mxdsstreamingaction.h b/LEGO1/mxdsstreamingaction.h index 7581b217..00cd13aa 100644 --- a/LEGO1/mxdsstreamingaction.h +++ b/LEGO1/mxdsstreamingaction.h @@ -35,6 +35,7 @@ class MxDSStreamingAction : public MxDSAction { inline MxS32 GetUnknown9c() { return m_unk0x9c; } inline MxDSBuffer* GetUnknowna0() { return m_unk0xa0; } inline MxDSBuffer* GetUnknowna4() { return m_unk0xa4; } + inline MxLong GetUnknowna8() { return m_unk0xa8; } inline MxDSAction* GetInternalAction() { return m_internalAction; } inline MxU32 GetBufferOffset() { return m_bufferOffset; } inline void SetUnknown94(MxU32 p_unk0x94) { m_unk0x94 = p_unk0x94; } diff --git a/LEGO1/mxstreamchunk.cpp b/LEGO1/mxstreamchunk.cpp index 93e76a6c..1b463a71 100644 --- a/LEGO1/mxstreamchunk.cpp +++ b/LEGO1/mxstreamchunk.cpp @@ -2,6 +2,7 @@ #include "legoutil.h" #include "mxdsbuffer.h" +#include "mxstreamlist.h" // FUNCTION: LEGO1 0x100c2fe0 MxStreamChunk::~MxStreamChunk() @@ -48,6 +49,25 @@ MxU32 MxStreamChunk::ReadChunkHeader(MxU8* p_chunkData) return headersize; } +// FUNCTION: LEGO1 0x100c30e0 +MxResult MxStreamChunk::SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, MxBool p_preappend, MxS16 p_unk24val) +{ + for (MxStreamListMxDSSubscriber::iterator it = p_subscriberList.begin(); it != p_subscriberList.end(); it++) { + if ((*it)->GetObjectId() == m_objectId && (*it)->GetUnknown48() == p_unk24val) { + if ((m_flags & 2) != 0 && m_buffer) { + m_buffer->ReleaseRef(this); + m_buffer = NULL; + } + + (*it)->AddChunk(this, p_preappend); + + return SUCCESS; + } + } + + return FAILURE; +} + // FUNCTION: LEGO1 0x100c3170 void MxStreamChunk::SetBuffer(MxDSBuffer* p_buffer) { diff --git a/LEGO1/mxstreamchunk.h b/LEGO1/mxstreamchunk.h index 53cbfc68..582233d4 100644 --- a/LEGO1/mxstreamchunk.h +++ b/LEGO1/mxstreamchunk.h @@ -2,8 +2,10 @@ #define MXSTREAMCHUNK_H #include "mxdschunk.h" +#include "mxdsobject.h" class MxDSBuffer; +class MxStreamListMxDSSubscriber; // VTABLE: LEGO1 0x100dc2a8 // SIZE 0x20 @@ -29,8 +31,21 @@ class MxStreamChunk : public MxDSChunk { MxResult ReadChunk(MxDSBuffer* p_buffer, MxU8* p_chunkData); MxU32 ReadChunkHeader(MxU8* p_chunkData); + MxResult SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, MxBool p_preappend, MxS16 p_unk24val); void SetBuffer(MxDSBuffer* p_buffer); + // FUNCTION: LEGO1 0x100c3180 + static MxU32* ReturnPlus8Ptr(MxU32* p_chunk) { return p_chunk + 8; } + + // FUNCTION: LEGO1 0x100c3190 + static MxU32* ReturnPlus10Ptr(MxU32* p_chunk) { return p_chunk + 10; } + + // FUNCTION: LEGO1 0x100c31a0 + static MxU32* ReturnPlus14Ptr(MxU32* p_chunk) { return p_chunk + 14; } + + // FUNCTION: LEGO1 0x100c31b0 + static MxU32* ReturnPlus18Ptr(MxU32* p_chunk) { return p_chunk + 18; } + private: MxDSBuffer* m_buffer; // 0x1c }; diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/mxstreamcontroller.cpp index c7d30cc4..09869db6 100644 --- a/LEGO1/mxstreamcontroller.cpp +++ b/LEGO1/mxstreamcontroller.cpp @@ -78,16 +78,17 @@ MxResult MxStreamController::Open(const char* p_filename) return SUCCESS; } -// STUB: LEGO1 0x100c15d0 +// FUNCTION: LEGO1 0x100c15d0 void MxStreamController::FUN_100c15d0(MxDSSubscriber* p_subscriber) { - // TODO + m_subscriberList.push_back(p_subscriber); } // STUB: LEGO1 0x100c1620 void MxStreamController::FUN_100c1620(MxDSSubscriber* p_subscriber) { // TODO + OutputDebugString("MxStreamController::FUN_100c1620 STUB\n"); } // FUNCTION: LEGO1 0x100c1690 diff --git a/LEGO1/mxstreamcontroller.h b/LEGO1/mxstreamcontroller.h index b8a5bfbd..8953de92 100644 --- a/LEGO1/mxstreamcontroller.h +++ b/LEGO1/mxstreamcontroller.h @@ -53,8 +53,10 @@ class MxStreamController : public MxCore { MxResult InsertActionToList54(MxDSAction* p_action); inline MxAtomId& GetAtom() { return m_atom; }; + inline MxStreamProvider* GetProvider() { return m_provider; }; inline MxStreamListMxDSAction& GetUnk0x3c() { return m_unk0x3c; }; inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; }; + inline MxStreamListMxDSSubscriber& GetSubscriberList() { return m_subscriberList; }; protected: MxCriticalSection m_criticalSection; // 0x8