ObjLoading: Fix Ipak entry size not specifying the filesize but the difference between start pos and end pos

This commit is contained in:
Jan 2020-02-09 01:22:27 +01:00
parent 345687125f
commit eaa64665d6
2 changed files with 49 additions and 27 deletions

View File

@ -7,7 +7,7 @@
using namespace ipak_consts; using namespace ipak_consts;
IPakEntryReadStream::IPakEntryReadStream(IFile* file, IPakStreamManagerActions* streamManagerActions, 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_file = file;
m_stream_manager_actions = streamManagerActions; m_stream_manager_actions = streamManagerActions;
@ -15,11 +15,12 @@ IPakEntryReadStream::IPakEntryReadStream(IFile* file, IPakStreamManagerActions*
m_file_offset = 0; m_file_offset = 0;
m_file_head = 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_base_pos = startOffset;
m_end_pos = startOffset + entrySize;
m_pos = m_base_pos; m_pos = m_base_pos;
m_buffer_start_pos = 0; m_buffer_start_pos = 0;
m_buffer_end_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); printf("IPak block has more than 31 commands: %u -> Invalid\n", blockHeader->count);
return false; 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, printf("IPak block offset is larger than the entry itself: %u > %u -> Invalid\n", blockHeader->offset,
m_file_length); m_entry_size);
return false; return false;
} }
@ -113,9 +114,9 @@ bool IPakEntryReadStream::AdjustChunkBufferWindowForBlockHeader(IPakDataBlockHea
const size_t requiredChunkCount = AlignForward<size_t>( const size_t requiredChunkCount = AlignForward<size_t>(
blockOffsetInChunk + sizeof IPakDataBlockHeader + commandsSize, IPAK_CHUNK_SIZE) / IPAK_CHUNK_SIZE; blockOffsetInChunk + sizeof IPakDataBlockHeader + commandsSize, IPAK_CHUNK_SIZE) / IPAK_CHUNK_SIZE;
const size_t amountOfReadBlocks = static_cast<size_t>(m_buffer_end_pos - m_buffer_start_pos) / IPAK_CHUNK_SIZE; const size_t amountOfReadChunks = static_cast<size_t>(m_buffer_end_pos - m_buffer_start_pos) / IPAK_CHUNK_SIZE;
if (requiredChunkCount > amountOfReadBlocks) if (requiredChunkCount > amountOfReadChunks)
{ {
if (requiredChunkCount > IPAK_CHUNK_COUNT_PER_READ) if (requiredChunkCount > IPAK_CHUNK_COUNT_PER_READ)
{ {
@ -135,8 +136,8 @@ bool IPakEntryReadStream::ProcessCommand(const size_t commandSize, const bool co
{ {
if (compressed) if (compressed)
{ {
lzo_uint outputSize = m_file_length - m_file_head; lzo_uint outputSize = m_entry_size - m_file_head;
const auto result = lzo1x_decompress(&m_chunk_buffer[m_pos - m_buffer_start_pos], commandSize, const auto result = lzo1x_decompress_safe(&m_chunk_buffer[m_pos - m_buffer_start_pos], commandSize,
&m_file_buffer[m_file_head], &outputSize, nullptr); &m_file_buffer[m_file_head], &outputSize, nullptr);
if (result != LZO_E_OK) if (result != LZO_E_OK)
@ -149,19 +150,20 @@ bool IPakEntryReadStream::ProcessCommand(const size_t commandSize, const bool co
} }
else else
{ {
if (m_file_length - m_file_head < commandSize) if (m_entry_size - m_file_head < commandSize)
{ {
printf( printf(
"There is not enough space in output buffer to extract data from IPak block: %u required, %u available\n", "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; 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); commandSize);
m_file_head += commandSize; m_file_head += commandSize;
} }
m_pos += commandSize;
return true; return true;
} }
@ -171,7 +173,7 @@ bool IPakEntryReadStream::AdvanceStream()
const auto chunkStartPos = AlignBackwards<int64_t>(m_pos, IPAK_CHUNK_SIZE); const auto chunkStartPos = AlignBackwards<int64_t>(m_pos, IPAK_CHUNK_SIZE);
const auto blockOffsetInChunk = static_cast<size_t>(m_pos - chunkStartPos); const auto blockOffsetInChunk = static_cast<size_t>(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) size_t estimatedChunksToRead = AlignForward(blockOffsetInChunk + sizeLeftToRead, IPAK_CHUNK_SIZE)
/ 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) size_t IPakEntryReadStream::Read(void* buffer, const size_t elementSize, const size_t elementCount)
{ {
const size_t bufferSize = elementCount * elementSize; 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) while (m_file_offset + sizeToRead > m_file_head && m_pos < m_end_pos)
sizeToRead = m_file_length - m_file_offset;
while (m_file_offset + sizeToRead > m_file_head)
{ {
if (!AdvanceStream()) 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) if (sizeToRead > 0)
{ {
memcpy_s(buffer, bufferSize, &m_file_buffer[m_file_offset], sizeToRead); 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<size_t>(amount); m_file_offset += static_cast<size_t>(amount);
if (m_file_offset > m_file_length) if (m_file_offset > m_entry_size)
m_file_offset = m_file_length; m_file_offset = m_entry_size;
} }
} }
@ -265,18 +269,34 @@ int64_t IPakEntryReadStream::Pos()
void IPakEntryReadStream::Goto(const int64_t 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<size_t>(pos); m_file_offset = static_cast<size_t>(pos);
if (m_file_offset > m_file_length) if (m_file_offset > m_file_head)
m_file_offset = m_file_length; m_file_offset = m_file_head;
} }
} }
void IPakEntryReadStream::GotoEnd() 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() void IPakEntryReadStream::Close()

View File

@ -15,10 +15,12 @@ class IPakEntryReadStream final : public FileAPI::IFile
size_t m_file_offset; size_t m_file_offset;
size_t m_file_head; size_t m_file_head;
size_t m_file_length;
size_t m_entry_size;
int64_t m_pos; int64_t m_pos;
int64_t m_base_pos; int64_t m_base_pos;
int64_t m_end_pos;
int64_t m_buffer_start_pos; int64_t m_buffer_start_pos;
int64_t m_buffer_end_pos; int64_t m_buffer_end_pos;
@ -41,7 +43,7 @@ class IPakEntryReadStream final : public FileAPI::IFile
bool AdvanceStream(); bool AdvanceStream();
public: 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; ~IPakEntryReadStream() override;
bool IsOpen() override; bool IsOpen() override;