mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-21 00:25:44 +00:00
ObjLoading: Fix loading the wrong chunkbuffer window data when trying to shift chunkbuffer
This commit is contained in:
parent
76712328b2
commit
53b03c1fdb
@ -126,10 +126,12 @@ void ObjLoaderT6::LoadImageFromIwi(T6::GfxImage* image, ISearchPath* searchPath,
|
|||||||
delete ipakStream;
|
delete ipakStream;
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
if (loadedTexture != nullptr)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(loadedTexture == nullptr)
|
if(loadedTexture == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -38,33 +38,64 @@ IPakEntryReadStream::~IPakEntryReadStream()
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPakEntryReadStream::SetChunkBufferWindow(const int64_t startPos, const size_t chunkCount)
|
size_t IPakEntryReadStream::ReadChunks(uint8_t* buffer, const int64_t startPos, const size_t chunkCount) const
|
||||||
|
{
|
||||||
|
m_stream_manager_actions->StartReading();
|
||||||
|
m_file->Goto(startPos);
|
||||||
|
const auto readSize = m_file->Read(buffer, 1, chunkCount * IPAK_CHUNK_SIZE);
|
||||||
|
m_stream_manager_actions->StopReading();
|
||||||
|
|
||||||
|
return readSize / IPAK_CHUNK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPakEntryReadStream::SetChunkBufferWindow(const int64_t startPos, size_t chunkCount)
|
||||||
{
|
{
|
||||||
// Cannot load more than IPAK_CHUNK_COUNT_PER_READ chunks without overflowing the buffer
|
// Cannot load more than IPAK_CHUNK_COUNT_PER_READ chunks without overflowing the buffer
|
||||||
assert(chunkCount <= IPAK_CHUNK_COUNT_PER_READ);
|
assert(chunkCount <= IPAK_CHUNK_COUNT_PER_READ);
|
||||||
|
|
||||||
|
if (chunkCount > IPAK_CHUNK_COUNT_PER_READ)
|
||||||
|
chunkCount = IPAK_CHUNK_COUNT_PER_READ;
|
||||||
|
|
||||||
// The start position must be aligned to IPAK_CHUNK_SIZE
|
// The start position must be aligned to IPAK_CHUNK_SIZE
|
||||||
assert(startPos % IPAK_CHUNK_SIZE == 0);
|
assert(startPos % IPAK_CHUNK_SIZE == 0);
|
||||||
|
|
||||||
const int64_t endPos = startPos + static_cast<int64_t>(chunkCount) * IPAK_CHUNK_SIZE;
|
if (chunkCount == 0)
|
||||||
|
{
|
||||||
|
m_buffer_start_pos = startPos;
|
||||||
|
m_buffer_end_pos = startPos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t* readBuffer = m_chunk_buffer;
|
const int64_t endPos = startPos + static_cast<int64_t>(chunkCount) * IPAK_CHUNK_SIZE;
|
||||||
size_t readChunkCount = chunkCount;
|
|
||||||
|
|
||||||
if (startPos >= m_buffer_start_pos && startPos < m_buffer_end_pos)
|
if (startPos >= m_buffer_start_pos && startPos < m_buffer_end_pos)
|
||||||
{
|
{
|
||||||
if (startPos != m_buffer_start_pos)
|
if (m_buffer_start_pos != startPos)
|
||||||
{
|
{
|
||||||
|
const int64_t moveEnd = endPos < m_buffer_end_pos ? endPos : m_buffer_end_pos;
|
||||||
memmove_s(m_chunk_buffer,
|
memmove_s(m_chunk_buffer,
|
||||||
IPAK_CHUNK_SIZE * IPAK_CHUNK_COUNT_PER_READ,
|
IPAK_CHUNK_SIZE * IPAK_CHUNK_COUNT_PER_READ,
|
||||||
&m_chunk_buffer[startPos - m_buffer_start_pos],
|
&m_chunk_buffer[startPos - m_buffer_start_pos],
|
||||||
static_cast<size_t>(m_buffer_end_pos - startPos));
|
static_cast<size_t>(moveEnd - startPos));
|
||||||
readBuffer = &m_chunk_buffer[m_buffer_end_pos - startPos];
|
m_buffer_start_pos = startPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
readChunkCount = endPos > m_buffer_end_pos
|
if (endPos > m_buffer_end_pos)
|
||||||
? static_cast<size_t>(endPos - m_buffer_end_pos) / IPAK_CHUNK_SIZE
|
{
|
||||||
: 0;
|
const size_t readChunkCount = ReadChunks(&m_chunk_buffer[m_buffer_end_pos - startPos],
|
||||||
|
m_buffer_end_pos,
|
||||||
|
static_cast<size_t>(endPos - m_buffer_end_pos) / IPAK_CHUNK_SIZE);
|
||||||
|
|
||||||
|
m_buffer_end_pos += static_cast<int64_t>(readChunkCount) * IPAK_CHUNK_SIZE;
|
||||||
|
|
||||||
|
return m_buffer_end_pos == endPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_buffer_end_pos = endPos;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (endPos > m_buffer_start_pos && endPos <= m_buffer_end_pos)
|
else if (endPos > m_buffer_start_pos && endPos <= m_buffer_end_pos)
|
||||||
{
|
{
|
||||||
@ -73,21 +104,26 @@ bool IPakEntryReadStream::SetChunkBufferWindow(const int64_t startPos, const siz
|
|||||||
m_chunk_buffer,
|
m_chunk_buffer,
|
||||||
static_cast<size_t>(endPos - m_buffer_start_pos));
|
static_cast<size_t>(endPos - m_buffer_start_pos));
|
||||||
|
|
||||||
readChunkCount = static_cast<size_t>(m_buffer_start_pos - startPos) / IPAK_CHUNK_SIZE;
|
const size_t readChunkCount = ReadChunks(m_chunk_buffer,
|
||||||
}
|
startPos,
|
||||||
|
static_cast<size_t>(m_buffer_start_pos - startPos) / IPAK_CHUNK_SIZE);
|
||||||
if (readChunkCount == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
m_stream_manager_actions->StartReading();
|
|
||||||
m_file->Goto(startPos);
|
|
||||||
const auto readSize = m_file->Read(readBuffer, 1, readChunkCount * IPAK_CHUNK_SIZE);
|
|
||||||
m_stream_manager_actions->StopReading();
|
|
||||||
|
|
||||||
m_buffer_start_pos = startPos;
|
m_buffer_start_pos = startPos;
|
||||||
m_buffer_end_pos = AlignBackwards<int64_t>(m_buffer_start_pos + readSize, IPAK_CHUNK_SIZE);
|
m_buffer_end_pos = readChunkCount == (m_buffer_start_pos - startPos) / IPAK_CHUNK_SIZE
|
||||||
|
? endPos
|
||||||
|
: startPos + static_cast<int64_t>(readChunkCount) * IPAK_CHUNK_SIZE;
|
||||||
|
|
||||||
return readSize == readChunkCount * IPAK_CHUNK_SIZE;
|
return m_buffer_end_pos == endPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t readChunkCount = ReadChunks(m_chunk_buffer,
|
||||||
|
startPos,
|
||||||
|
chunkCount);
|
||||||
|
|
||||||
|
m_buffer_start_pos = startPos;
|
||||||
|
m_buffer_end_pos = startPos + static_cast<int64_t>(readChunkCount) * IPAK_CHUNK_SIZE;
|
||||||
|
|
||||||
|
return chunkCount == readChunkCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPakEntryReadStream::ValidateBlockHeader(IPakDataBlockHeader* blockHeader) const
|
bool IPakEntryReadStream::ValidateBlockHeader(IPakDataBlockHeader* blockHeader) const
|
||||||
@ -97,12 +133,19 @@ 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_entry_size)
|
if (blockHeader->offset != m_file_head)
|
||||||
{
|
{
|
||||||
printf("IPak block offset is larger than the entry itself: %u > %u -> Invalid\n", blockHeader->offset,
|
// A matching offset is only relevant if a command contains data.
|
||||||
m_entry_size);
|
for(unsigned currentCommand = 0; currentCommand < blockHeader->count; currentCommand++)
|
||||||
|
{
|
||||||
|
if(blockHeader->_commands[currentCommand].compressed == 0
|
||||||
|
|| blockHeader->_commands[currentCommand].compressed == 1)
|
||||||
|
{
|
||||||
|
printf("IPak block offset is not the file head: %u != %u -> Invalid\n", blockHeader->offset, m_file_head);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -148,7 +191,7 @@ bool IPakEntryReadStream::NextBlock()
|
|||||||
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_entry_size - 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(m_entry_size - static_cast<size_t>(m_pos - m_base_pos), IPAK_CHUNK_SIZE)
|
||||||
/ IPAK_CHUNK_SIZE;
|
/ IPAK_CHUNK_SIZE;
|
||||||
|
|
||||||
if (estimatedChunksToRead > IPAK_CHUNK_COUNT_PER_READ)
|
if (estimatedChunksToRead > IPAK_CHUNK_COUNT_PER_READ)
|
||||||
@ -213,7 +256,8 @@ bool IPakEntryReadStream::AdvanceStream()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessCommand(m_current_block->_commands[m_next_command].size, m_current_block->_commands[m_next_command].compressed);
|
ProcessCommand(m_current_block->_commands[m_next_command].size,
|
||||||
|
m_current_block->_commands[m_next_command].compressed);
|
||||||
m_next_command++;
|
m_next_command++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -244,7 +288,8 @@ size_t IPakEntryReadStream::Read(void* buffer, const size_t elementSize, const s
|
|||||||
|
|
||||||
if (sizeToRead > 0)
|
if (sizeToRead > 0)
|
||||||
{
|
{
|
||||||
memcpy_s(&destBuffer[countRead], bufferSize - countRead, &m_current_command_buffer[m_current_command_offset], sizeToRead);
|
memcpy_s(&destBuffer[countRead], bufferSize - countRead,
|
||||||
|
&m_current_command_buffer[m_current_command_offset], sizeToRead);
|
||||||
countRead += sizeToRead;
|
countRead += sizeToRead;
|
||||||
m_current_command_offset += sizeToRead;
|
m_current_command_offset += sizeToRead;
|
||||||
m_file_offset += sizeToRead;
|
m_file_offset += sizeToRead;
|
||||||
|
@ -44,6 +44,7 @@ class IPakEntryReadStream final : public FileAPI::IFile
|
|||||||
return num / alignTo * alignTo;
|
return num / alignTo * alignTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ReadChunks(uint8_t* buffer, int64_t startPos, size_t chunkCount) const;
|
||||||
bool SetChunkBufferWindow(int64_t startPos, size_t chunkCount);
|
bool SetChunkBufferWindow(int64_t startPos, size_t chunkCount);
|
||||||
bool ValidateBlockHeader(IPakDataBlockHeader* blockHeader) const;
|
bool ValidateBlockHeader(IPakDataBlockHeader* blockHeader) const;
|
||||||
bool AdjustChunkBufferWindowForBlockHeader(IPakDataBlockHeader* blockHeader, size_t blockOffsetInChunk);
|
bool AdjustChunkBufferWindowForBlockHeader(IPakDataBlockHeader* blockHeader, size_t blockOffsetInChunk);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user