diff --git a/LEGO1/omni/include/mxdiskstreamprovider.h b/LEGO1/omni/include/mxdiskstreamprovider.h index 2557eaf9..6df049da 100644 --- a/LEGO1/omni/include/mxdiskstreamprovider.h +++ b/LEGO1/omni/include/mxdiskstreamprovider.h @@ -20,6 +20,9 @@ public: MxResult Run() override; MxResult StartWithTarget(MxDiskStreamProvider* p_target); + + // SYNTHETIC: LEGO1 0x100d10a0 + // MxDiskStreamProviderThread::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dd138 @@ -55,6 +58,9 @@ public: virtual MxU32 GetLengthInDWords() override; // vtable+0x24 virtual MxU32* GetBufferForDWords() override; // vtable+0x28 + // SYNTHETIC: LEGO1 0x100d1220 + // MxDiskStreamProvider::`scalar deleting destructor' + private: MxDiskStreamProviderThread m_thread; // 0x10 MxSemaphore m_busySemaphore; // 0x2c @@ -64,7 +70,4 @@ private: MxStreamListMxDSAction m_list; // 0x54 }; -// SYNTHETIC: LEGO1 0x100d1220 -// MxDiskStreamProvider::`scalar deleting destructor' - #endif // MXDISKSTREAMPROVIDER_H diff --git a/LEGO1/omni/include/mxdsbuffer.h b/LEGO1/omni/include/mxdsbuffer.h index daa3263e..3a336af7 100644 --- a/LEGO1/omni/include/mxdsbuffer.h +++ b/LEGO1/omni/include/mxdsbuffer.h @@ -32,7 +32,7 @@ public: } MxResult AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode); - MxResult SetBufferPointer(MxU32* p_buffer, MxU32 p_size); + MxResult SetBufferPointer(MxU8* p_buffer, MxU32 p_size); MxResult FUN_100c67b0( MxStreamController* p_controller, MxDSAction* p_action, @@ -52,20 +52,27 @@ public: MxDSStreamingAction** p_streamingAction, MxStreamChunk* p_header ); - static MxCore* ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags); MxU8* SkipToData(); MxU8 ReleaseRef(MxDSChunk*); void AddRef(MxDSChunk* p_chunk); MxResult CalcBytesRemaining(MxU8* p_data); void FUN_100c6f80(MxU32 p_writeOffset); + MxU8* FUN_100c6fa0(MxU8* p_data); + MxResult FUN_100c7090(MxDSBuffer* p_buf); + + static MxCore* ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags); + static MxResult Append(MxU8* p_buffer1, MxU8* p_buffer2); inline MxU8* GetBuffer() { return m_pBuffer; } - inline MxU32 GetWriteOffset() { return m_writeOffset; } - inline MxU32 GetBytesRemaining() { return m_bytesRemaining; } + inline MxU8** GetBufferRef() { return &m_pBuffer; } + inline undefined4 GetUnknown14() { return m_unk0x14; } inline MxU16 GetRefCount() { return m_refcount; } inline MxDSBufferType GetMode() { return m_mode; } + inline MxU32 GetWriteOffset() { return m_writeOffset; } + inline MxU32 GetBytesRemaining() { return m_bytesRemaining; } inline void SetUnknown14(undefined4 p_unk0x14) { m_unk0x14 = p_unk0x14; } inline void SetUnknown1c(undefined4 p_unk0x1c) { m_unk0x1c = p_unk0x1c; } + inline void SetMode(MxDSBufferType p_mode) { m_mode = p_mode; } inline void SetUnk30(MxDSStreamingAction* p_unk0x30) { m_unk0x30 = p_unk0x30; } private: diff --git a/LEGO1/omni/include/mxdschunk.h b/LEGO1/omni/include/mxdschunk.h index 83693bc0..3cd60b27 100644 --- a/LEGO1/omni/include/mxdschunk.h +++ b/LEGO1/omni/include/mxdschunk.h @@ -33,7 +33,11 @@ public: return !strcmp(p_name, MxDSChunk::ClassName()) || MxCore::IsA(p_name); } - static MxU32 ReturnE(); + static MxU32 GetHeaderSize(); + inline static MxU32* IntoType(MxU8* p_buffer) { return (MxU32*) p_buffer; } + inline static MxU32* IntoLength(MxU8* p_buffer) { return (MxU32*) (p_buffer + 4); } + inline static MxU32 Size(MxU32 p_dataSize) { return (p_dataSize & 1) + p_dataSize + 8; } + inline static MxU8* End(MxU8* p_buffer) { return p_buffer + Size(*IntoLength(p_buffer)); } inline void SetFlags(MxU16 p_flags) { m_flags = p_flags; } inline void SetObjectId(undefined4 p_objectid) { m_objectId = p_objectid; } diff --git a/LEGO1/omni/include/mxdsstreamingaction.h b/LEGO1/omni/include/mxdsstreamingaction.h index 00cd13aa..ab21bac2 100644 --- a/LEGO1/omni/include/mxdsstreamingaction.h +++ b/LEGO1/omni/include/mxdsstreamingaction.h @@ -41,6 +41,7 @@ public: inline void SetUnknown94(MxU32 p_unk0x94) { m_unk0x94 = p_unk0x94; } inline void SetUnknown9c(MxS32 p_unk0x9c) { m_unk0x9c = p_unk0x9c; } inline void SetUnknowna0(MxDSBuffer* p_unk0xa0) { m_unk0xa0 = p_unk0xa0; } + inline void SetUnknowna4(MxDSBuffer* p_unk0xa4) { m_unk0xa4 = p_unk0xa4; } inline void SetBufferOffset(MxU32 p_bufferOffset) { m_bufferOffset = p_bufferOffset; } private: diff --git a/LEGO1/omni/include/mxramstreamprovider.h b/LEGO1/omni/include/mxramstreamprovider.h index 5c8bf59c..f5ac0897 100644 --- a/LEGO1/omni/include/mxramstreamprovider.h +++ b/LEGO1/omni/include/mxramstreamprovider.h @@ -29,17 +29,19 @@ public: virtual MxU32 GetLengthInDWords() override; // vtable+0x24 virtual MxU32* GetBufferForDWords() override; // vtable+0x28 - inline MxU32* GetBufferOfFileSize() { return m_pBufferOfFileSize; } + inline MxU8* GetBufferOfFileSize() { return m_pBufferOfFileSize; } protected: - MxU32 m_bufferSize; // 0x10 - MxU32 m_fileSize; // 0x14 - MxU32* m_pBufferOfFileSize; // 0x18 - MxU32 m_lengthInDWords; // 0x1c - MxU32* m_bufferForDWords; // 0x20 + MxU32 m_bufferSize; // 0x10 + MxU32 m_fileSize; // 0x14 + MxU8* m_pBufferOfFileSize; // 0x18 + MxU32 m_lengthInDWords; // 0x1c + MxU32* m_bufferForDWords; // 0x20 }; // SYNTHETIC: LEGO1 0x100d0a30 // MxRAMStreamProvider::`scalar deleting destructor' +MxU32 ReadData(MxU8* p_fileSizeBuffer, MxU32 p_fileSize); + #endif // MXRAMSTREAMPROVIDER_H diff --git a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp index b9ed63d0..08046ad4 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp @@ -5,6 +5,7 @@ #include "mxdsbuffer.h" #include "mxdsstreamingaction.h" #include "mxomni.h" +#include "mxramstreamprovider.h" #include "mxstreamcontroller.h" #include "mxstring.h" #include "mxthread.h" @@ -267,10 +268,103 @@ MxBool MxDiskStreamProvider::FUN_100d1af0(MxDSStreamingAction* p_action) return TRUE; } -// STUB: LEGO1 0x100d1b20 +// FUNCTION: LEGO1 0x100d1b20 MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) { - return FAILURE; + MxDSBuffer* buffer = new MxDSBuffer(); + + if (!buffer) + return FAILURE; + + MxU32 size = p_action->GetUnknowna0()->GetWriteOffset() - p_action->GetUnknown94() + p_action->GetBufferOffset() + + (p_action->GetUnknowna4() ? p_action->GetUnknowna4()->GetWriteOffset() : 0); + + if (buffer->AllocateBuffer(size, MxDSBufferType_Allocate) != SUCCESS) { + if (!buffer) + return FAILURE; + + delete buffer; + return FAILURE; + } + + MxDSBuffer* buffer2 = p_action->GetUnknowna4(); + MxU8** pdata; + MxU8* data; + + if (buffer2 == NULL) { + pdata = buffer->GetBufferRef(); + + memcpy( + data = *pdata, + p_action->GetUnknowna0()->GetBuffer() - p_action->GetBufferOffset() + p_action->GetUnknown94(), + size + ); + } + else { + buffer->FUN_100c7090(buffer2); + pdata = buffer->GetBufferRef(); + + memcpy( + data = (p_action->GetUnknowna4()->GetWriteOffset() + *pdata), + p_action->GetUnknowna0()->GetBuffer(), + p_action->GetUnknowna0()->GetWriteOffset() + ); + + delete p_action->GetUnknowna4(); + } + + p_action->SetUnknowna4(buffer); + + while (data) { + if (*MxDSChunk::IntoType(data) != FOURCC('M', 'x', 'O', 'b')) { + if (*MxStreamChunk::IntoTime(data) > p_action->GetUnknown9c()) { + *MxDSChunk::IntoType(data) = FOURCC('p', 'a', 'd', ' '); + + memcpy(data + 8, *pdata, buffer->GetWriteOffset() + *pdata - data - 8); + size = ReadData(*pdata, buffer->GetWriteOffset()); + + MxDSBuffer* buffer3 = new MxDSBuffer(); + if (!buffer3) + return FAILURE; + + if (buffer3->AllocateBuffer(size, MxDSBufferType_Allocate) == SUCCESS) { + memcpy(buffer3->GetBuffer(), p_action->GetUnknowna4()->GetBuffer(), size); + p_action->GetUnknowna4()->SetMode(MxDSBufferType_Allocate); + delete p_action->GetUnknowna4(); + + buffer3->SetMode(MxDSBufferType_Unknown); + p_action->SetUnknowna4(buffer3); + MxDSBuffer* buffer4 = p_action->GetUnknowna0(); + MxU32 unk0x14 = buffer4->GetUnknown14(); + MxU8* data2 = buffer4->GetBuffer(); + + while (TRUE) { + if (*MxStreamChunk::IntoTime(data2) > p_action->GetUnknown9c()) + break; + + data += MxDSChunk::Size(*MxDSChunk::IntoLength(data)); + unk0x14 += MxDSChunk::Size(*MxDSChunk::IntoLength(data)); + } + + p_action->SetUnknown94(unk0x14); + p_action->SetBufferOffset(p_action->GetUnknowna0()->GetUnknown14()); + delete p_action->GetUnknowna0(); + return SUCCESS; + } + else { + delete buffer3; + return FAILURE; + } + } + } + + data = buffer->FUN_100c6fa0(data); + } + + p_action->SetUnknown94(GetFileSize() + p_action->GetBufferOffset()); + p_action->SetBufferOffset(GetFileSize() + p_action->GetBufferOffset()); + FUN_100d1780(p_action); + return SUCCESS; } // FUNCTION: LEGO1 0x100d1e90 diff --git a/LEGO1/omni/src/stream/mxdsbuffer.cpp b/LEGO1/omni/src/stream/mxdsbuffer.cpp index 5e4b277d..54ed0ca2 100644 --- a/LEGO1/omni/src/stream/mxdsbuffer.cpp +++ b/LEGO1/omni/src/stream/mxdsbuffer.cpp @@ -143,11 +143,11 @@ done: } // FUNCTION: LEGO1 0x100c6780 -MxResult MxDSBuffer::SetBufferPointer(MxU32* p_buffer, MxU32 p_size) +MxResult MxDSBuffer::SetBufferPointer(MxU8* p_buffer, MxU32 p_size) { - m_pBuffer = (MxU8*) p_buffer; - m_pIntoBuffer = (MxU8*) p_buffer; - m_pIntoBuffer2 = (MxU8*) p_buffer; + m_pBuffer = p_buffer; + m_pIntoBuffer = p_buffer; + m_pIntoBuffer2 = p_buffer; m_bytesRemaining = p_size; m_writeOffset = p_size; m_mode = MxDSBufferType_Preallocated; @@ -299,7 +299,7 @@ MxResult MxDSBuffer::ParseChunk( p_header->SetTime(p_header->GetTime() + m_unk0x30->GetUnknowna8()); if (p_header->GetFlags() & MxDSChunk::Flag_Split) { - MxU32 length = p_header->GetLength() + MxDSChunk::ReturnE() + 8; + MxU32 length = p_header->GetLength() + MxDSChunk::GetHeaderSize() + 8; MxDSBuffer* buffer = new MxDSBuffer(); if (buffer && buffer->AllocateBuffer(length, MxDSBufferType_Allocate) == SUCCESS && @@ -465,15 +465,15 @@ MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) ptr = p_data; } else { - ptr = &p_data[MxStreamChunk::ReturnE() + 8]; - bytesRead = (*(MxU32*) (p_data + 4)) - MxStreamChunk::ReturnE(); + ptr = &p_data[MxStreamChunk::GetHeaderSize() + 8]; + bytesRead = (*(MxU32*) (p_data + 4)) - MxStreamChunk::GetHeaderSize(); } if (bytesRead <= m_bytesRemaining) { memcpy(m_pBuffer + m_writeOffset - m_bytesRemaining, ptr, bytesRead); if (m_writeOffset == m_bytesRemaining) - *(MxU32*) (m_pBuffer + 4) = *MxStreamChunk::IntoLength(m_pBuffer) + MxStreamChunk::ReturnE(); + *(MxU32*) (m_pBuffer + 4) = *MxStreamChunk::IntoLength(m_pBuffer) + MxStreamChunk::GetHeaderSize(); m_bytesRemaining -= bytesRead; result = SUCCESS; @@ -491,3 +491,61 @@ void MxDSBuffer::FUN_100c6f80(MxU32 p_writeOffset) m_pIntoBuffer = m_pBuffer + p_writeOffset; } } + +// FUNCTION: LEGO1 0x100c6fa0 +MxU8* MxDSBuffer::FUN_100c6fa0(MxU8* p_data) +{ + MxU8* current = p_data ? p_data : m_pBuffer; + MxU8* end = m_writeOffset + m_pBuffer - 8; + + while (current <= end) { + switch (*((MxU32*) current)) { + case FOURCC('L', 'I', 'S', 'T'): + case FOURCC('R', 'I', 'F', 'F'): + current += 12; + break; + case FOURCC('M', 'x', 'D', 'a'): + case FOURCC('M', 'x', 'S', 't'): + current += 8; + break; + case FOURCC('M', 'x', 'O', 'b'): + case FOURCC('M', 'x', 'C', 'h'): + if (current != p_data) + return current; + current = ((MxU32) current & 1) + current; + current += 8; + break; + case FOURCC('M', 'x', 'H', 'd'): + current += (((MxU32*) current)[1] + 8); + break; + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x100c7090 +MxResult MxDSBuffer::FUN_100c7090(MxDSBuffer* p_buf) +{ + MxResult result = FAILURE; + + if (m_writeOffset >= p_buf->m_writeOffset) { + memcpy(m_pBuffer, p_buf->m_pBuffer, p_buf->m_writeOffset); + result = SUCCESS; + } + + m_unk0x1c = p_buf->m_unk0x1c; + return result; +} + +// FUNCTION: LEGO1 0x100c70d0 +MxResult MxDSBuffer::Append(MxU8* p_buffer1, MxU8* p_buffer2) +{ + if (p_buffer1 && p_buffer2) { + MxU32 size = ((MxU32*) p_buffer2)[1] - MxDSChunk::GetHeaderSize(); + memcpy(p_buffer1 + ((MxU32*) p_buffer1)[1] + 8, p_buffer2 + MxDSChunk::GetHeaderSize() + 8, size); + ((MxU32*) p_buffer1)[1] += size; + return SUCCESS; + } + return FAILURE; +} diff --git a/LEGO1/omni/src/stream/mxdschunk.cpp b/LEGO1/omni/src/stream/mxdschunk.cpp index bee247d2..79b9fea1 100644 --- a/LEGO1/omni/src/stream/mxdschunk.cpp +++ b/LEGO1/omni/src/stream/mxdschunk.cpp @@ -20,7 +20,7 @@ MxDSChunk::~MxDSChunk() } // FUNCTION: LEGO1 0x100be1e0 -MxU32 MxDSChunk::ReturnE() +MxU32 MxDSChunk::GetHeaderSize() { return 0xe; } diff --git a/LEGO1/omni/src/stream/mxramstreamcontroller.cpp b/LEGO1/omni/src/stream/mxramstreamcontroller.cpp index 71ee1b92..b480255c 100644 --- a/LEGO1/omni/src/stream/mxramstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxramstreamcontroller.cpp @@ -6,8 +6,6 @@ DECOMP_SIZE_ASSERT(MxRAMStreamController, 0x98); -undefined* __cdecl ReadData(MxU32* p_fileSizeBuffer, MxU32 p_fileSize); - // FUNCTION: LEGO1 0x100c6110 MxResult MxRAMStreamController::Open(const char* p_filename) { @@ -95,9 +93,3 @@ MxResult MxRAMStreamController::DeserializeObject(MxDSStreamingAction& p_action) return result == SUCCESS ? SUCCESS : FAILURE; } - -// STUB: LEGO1 0x100d0d80 -undefined* __cdecl ReadData(MxU32* p_fileSizeBuffer, MxU32 p_fileSize) -{ - return NULL; -} diff --git a/LEGO1/omni/src/stream/mxramstreamprovider.cpp b/LEGO1/omni/src/stream/mxramstreamprovider.cpp index fc20bf33..232e347b 100644 --- a/LEGO1/omni/src/stream/mxramstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxramstreamprovider.cpp @@ -1,6 +1,7 @@ #include "mxramstreamprovider.h" #include "decomp.h" +#include "mxdsbuffer.h" #include "mxomni.h" #include "mxstreamcontroller.h" @@ -77,7 +78,7 @@ MxResult MxRAMStreamProvider::SetResourceToGet(MxStreamController* p_resource) m_fileSize = m_pFile->CalcFileSize(); if (m_fileSize != 0) { m_bufferSize = m_pFile->GetBufferSize(); - m_pBufferOfFileSize = (MxU32*) new MxU8[m_fileSize]; + m_pBufferOfFileSize = new MxU8[m_fileSize]; if (m_pBufferOfFileSize != NULL && m_pFile->Read((unsigned char*) m_pBufferOfFileSize, m_fileSize) == SUCCESS) { m_lengthInDWords = m_pFile->GetLengthInDWords(); @@ -96,3 +97,60 @@ done: m_pFile = NULL; return result; } + +// FUNCTION: LEGO1 0x100d0d80 +MxU32 ReadData(MxU8* p_buffer, MxU32 p_size) +{ + MxU32 id; + MxU8* data = p_buffer; + MxU8* end = p_buffer + p_size; + MxU8* data2; + + if (p_buffer < end) { + do { + if (*MxDSChunk::IntoType(data) == FOURCC('M', 'x', 'O', 'b')) { + data2 = data; + data += 8; + + MxDSObject* obj = DeserializeDSObjectDispatch(&data, -1); + id = obj->GetObjectId(); + delete obj; + + data = MxDSChunk::End(data2); + while (data < end) { + if (*MxDSChunk::IntoType(data) == FOURCC('M', 'x', 'C', 'h')) { + MxU8* data3 = data; + MxU32* psize = MxDSChunk::IntoLength(data); + data += MxDSChunk::Size(*psize); + + if ((*MxDSChunk::IntoType(data2) == FOURCC('M', 'x', 'C', 'h')) && + (*MxStreamChunk::IntoFlags(data2) & MxDSChunk::Flag_Split)) { + if (*MxStreamChunk::IntoObjectId(data2) == *MxStreamChunk::IntoObjectId(data3) && + (*MxStreamChunk::IntoFlags(data3) & MxDSChunk::Flag_Split) && + *MxStreamChunk::IntoTime(data2) == *MxStreamChunk::IntoTime(data3)) { + MxDSBuffer::Append(data2, data3); + continue; + } + else + *MxStreamChunk::IntoFlags(data2) &= ~MxDSChunk::Flag_Split; + } + + data2 += MxDSChunk::Size(*MxDSChunk::IntoLength(data2)); + memcpy(data2, data3, MxDSChunk::Size(*psize)); + + if (*MxStreamChunk::IntoObjectId(data2) == id && + (*MxStreamChunk::IntoFlags(data2) & MxDSChunk::Flag_End)) + break; + } + else + data++; + } + } + else + data++; + } while (data < end); + } + + *MxStreamChunk::IntoFlags(data2) &= ~MxDSChunk::Flag_Split; + return MxDSChunk::End(data2) - p_buffer; +}