From eaa64665d6cb03a67e696402f5f2c99ffccd83b8 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 9 Feb 2020 01:22:27 +0100 Subject: [PATCH] ObjLoading: Fix Ipak entry size not specifying the filesize but the difference between start pos and end pos --- .../ObjContainer/IPak/IPakEntryReadStream.cpp | 70 ++++++++++++------- .../ObjContainer/IPak/IPakEntryReadStream.h | 6 +- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.cpp b/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.cpp index 97f3edef..ac87eb36 100644 --- a/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.cpp +++ b/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.cpp @@ -7,7 +7,7 @@ using namespace ipak_consts; IPakEntryReadStream::IPakEntryReadStream(IFile* file, IPakStreamManagerActions* streamManagerActions, - uint8_t* chunkBuffer, const int64_t startOffset, const size_t fileSize) + uint8_t* chunkBuffer, const int64_t startOffset, const size_t entrySize) { m_file = file; m_stream_manager_actions = streamManagerActions; @@ -15,11 +15,12 @@ IPakEntryReadStream::IPakEntryReadStream(IFile* file, IPakStreamManagerActions* m_file_offset = 0; m_file_head = 0; - m_file_length = fileSize; + m_entry_size = entrySize; - m_file_buffer = new uint8_t[fileSize]; + m_file_buffer = new uint8_t[entrySize]; m_base_pos = startOffset; + m_end_pos = startOffset + entrySize; m_pos = m_base_pos; m_buffer_start_pos = 0; m_buffer_end_pos = 0; @@ -91,10 +92,10 @@ bool IPakEntryReadStream::ValidateBlockHeader(IPakDataBlockHeader* blockHeader) printf("IPak block has more than 31 commands: %u -> Invalid\n", blockHeader->count); return false; } - if (blockHeader->offset > m_file_length) + if (blockHeader->offset > m_entry_size) { - printf("IPak block offset is larger than file itself: %u > %u -> Invalid\n", blockHeader->offset, - m_file_length); + printf("IPak block offset is larger than the entry itself: %u > %u -> Invalid\n", blockHeader->offset, + m_entry_size); return false; } @@ -113,9 +114,9 @@ bool IPakEntryReadStream::AdjustChunkBufferWindowForBlockHeader(IPakDataBlockHea const size_t requiredChunkCount = AlignForward( blockOffsetInChunk + sizeof IPakDataBlockHeader + commandsSize, IPAK_CHUNK_SIZE) / IPAK_CHUNK_SIZE; - const size_t amountOfReadBlocks = static_cast(m_buffer_end_pos - m_buffer_start_pos) / IPAK_CHUNK_SIZE; + const size_t amountOfReadChunks = static_cast(m_buffer_end_pos - m_buffer_start_pos) / IPAK_CHUNK_SIZE; - if (requiredChunkCount > amountOfReadBlocks) + if (requiredChunkCount > amountOfReadChunks) { if (requiredChunkCount > IPAK_CHUNK_COUNT_PER_READ) { @@ -135,8 +136,8 @@ bool IPakEntryReadStream::ProcessCommand(const size_t commandSize, const bool co { if (compressed) { - lzo_uint outputSize = m_file_length - m_file_head; - const auto result = lzo1x_decompress(&m_chunk_buffer[m_pos - m_buffer_start_pos], commandSize, + lzo_uint outputSize = m_entry_size - m_file_head; + const auto result = lzo1x_decompress_safe(&m_chunk_buffer[m_pos - m_buffer_start_pos], commandSize, &m_file_buffer[m_file_head], &outputSize, nullptr); if (result != LZO_E_OK) @@ -149,19 +150,20 @@ bool IPakEntryReadStream::ProcessCommand(const size_t commandSize, const bool co } else { - if (m_file_length - m_file_head < commandSize) + if (m_entry_size - m_file_head < commandSize) { printf( "There is not enough space in output buffer to extract data from IPak block: %u required, %u available\n", - commandSize, m_file_length - m_file_head); + commandSize, m_entry_size - m_file_head); return false; } - memcpy_s(&m_file_buffer[m_file_head], m_file_length - m_file_head, &m_chunk_buffer[m_pos - m_buffer_start_pos], + memcpy_s(&m_file_buffer[m_file_head], m_entry_size - m_file_head, &m_chunk_buffer[m_pos - m_buffer_start_pos], commandSize); m_file_head += commandSize; } + m_pos += commandSize; return true; } @@ -171,7 +173,7 @@ bool IPakEntryReadStream::AdvanceStream() const auto chunkStartPos = AlignBackwards(m_pos, IPAK_CHUNK_SIZE); const auto blockOffsetInChunk = static_cast(m_pos - chunkStartPos); - const size_t sizeLeftToRead = m_file_length - m_file_head; + const size_t sizeLeftToRead = m_entry_size - m_file_head; size_t estimatedChunksToRead = AlignForward(blockOffsetInChunk + sizeLeftToRead, IPAK_CHUNK_SIZE) / IPAK_CHUNK_SIZE; @@ -211,12 +213,9 @@ bool IPakEntryReadStream::IsOpen() size_t IPakEntryReadStream::Read(void* buffer, const size_t elementSize, const size_t elementCount) { const size_t bufferSize = elementCount * elementSize; - size_t sizeToRead = bufferSize <= m_file_length - m_file_offset ? bufferSize : m_file_length - m_file_offset; + size_t sizeToRead = bufferSize <= m_entry_size - m_file_offset ? bufferSize : m_entry_size - m_file_offset; - if (sizeToRead) - sizeToRead = m_file_length - m_file_offset; - - while (m_file_offset + sizeToRead > m_file_head) + while (m_file_offset + sizeToRead > m_file_head && m_pos < m_end_pos) { if (!AdvanceStream()) { @@ -225,6 +224,11 @@ size_t IPakEntryReadStream::Read(void* buffer, const size_t elementSize, const s } } + if(sizeToRead > m_file_head - m_file_offset) + { + sizeToRead = m_file_head - m_file_offset; + } + if (sizeToRead > 0) { memcpy_s(buffer, bufferSize, &m_file_buffer[m_file_offset], sizeToRead); @@ -246,8 +250,8 @@ void IPakEntryReadStream::Skip(const int64_t amount) { m_file_offset += static_cast(amount); - if (m_file_offset > m_file_length) - m_file_offset = m_file_length; + if (m_file_offset > m_entry_size) + m_file_offset = m_entry_size; } } @@ -265,18 +269,34 @@ int64_t IPakEntryReadStream::Pos() void IPakEntryReadStream::Goto(const int64_t pos) { - if (pos <= 0) + if (pos >= 0) { + while (m_file_head < pos && m_pos < m_end_pos) + { + if (!AdvanceStream()) + { + break; + } + } + m_file_offset = static_cast(pos); - if (m_file_offset > m_file_length) - m_file_offset = m_file_length; + if (m_file_offset > m_file_head) + m_file_offset = m_file_head; } } void IPakEntryReadStream::GotoEnd() { - m_pos = m_file_length; + while (m_pos < m_end_pos) + { + if (!AdvanceStream()) + { + break; + } + } + + m_file_offset = m_file_head; } void IPakEntryReadStream::Close() diff --git a/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.h b/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.h index 099aa226..ce6bc2e9 100644 --- a/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.h +++ b/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.h @@ -15,10 +15,12 @@ class IPakEntryReadStream final : public FileAPI::IFile size_t m_file_offset; size_t m_file_head; - size_t m_file_length; + + size_t m_entry_size; int64_t m_pos; int64_t m_base_pos; + int64_t m_end_pos; int64_t m_buffer_start_pos; int64_t m_buffer_end_pos; @@ -41,7 +43,7 @@ class IPakEntryReadStream final : public FileAPI::IFile bool AdvanceStream(); public: - IPakEntryReadStream(IFile* file, IPakStreamManagerActions* streamManagerActions, uint8_t* chunkBuffer, int64_t startOffset, size_t fileSize); + IPakEntryReadStream(IFile* file, IPakStreamManagerActions* streamManagerActions, uint8_t* chunkBuffer, int64_t startOffset, size_t entrySize); ~IPakEntryReadStream() override; bool IsOpen() override;