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;
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<size_t>(
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)
{
@ -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<int64_t>(m_pos, IPAK_CHUNK_SIZE);
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)
/ 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<size_t>(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<size_t>(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()

View File

@ -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;