2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-05-17 07:21:43 +00:00

chore: enable reading of big endian ipaks

This commit is contained in:
Jan Laupetin
2026-05-11 23:54:25 +02:00
parent 7ae7cf85ff
commit e1bb8ae4d2
7 changed files with 183 additions and 129 deletions
+39 -5
View File
@@ -2,8 +2,10 @@
#include "IPakStreamManager.h"
#include "ObjContainer/IPak/IPakTypes.h"
#include "Utils/Endianness.h"
#include "Utils/Logging/Log.h"
#include <concepts>
#include <filesystem>
#include <format>
#include <iostream>
@@ -37,9 +39,10 @@ namespace
: m_path(std::move(path)),
m_stream(std::move(stream)),
m_initialized(false),
m_little_endian(true),
m_index_section(nullptr),
m_data_section(nullptr),
m_stream_manager(*m_stream)
m_stream_manager(nullptr)
{
}
@@ -65,7 +68,7 @@ namespace
{
if (entry.key.combinedKey == wantedKey.combinedKey)
{
return m_stream_manager.OpenStream(static_cast<int64_t>(m_data_section->offset) + entry.offset, entry.size);
return m_stream_manager->OpenStream(static_cast<int64_t>(m_data_section->offset) + entry.offset, entry.size);
}
else if (entry.key.combinedKey > wantedKey.combinedKey)
{
@@ -102,7 +105,11 @@ namespace
return false;
}
m_index_entries.push_back(indexEntry);
SwapBytesIfNecessary(indexEntry.key.combinedKey);
SwapBytesIfNecessary(indexEntry.offset);
SwapBytesIfNecessary(indexEntry.size);
m_index_entries.emplace_back(indexEntry);
}
std::ranges::sort(m_index_entries,
@@ -125,6 +132,11 @@ namespace
return false;
}
SwapBytesIfNecessary(section.type);
SwapBytesIfNecessary(section.offset);
SwapBytesIfNecessary(section.size);
SwapBytesIfNecessary(section.itemCount);
switch (section.type)
{
case ipak_consts::IPAK_INDEX_SECTION:
@@ -153,18 +165,31 @@ namespace
return false;
}
if (header.magic != ipak_consts::IPAK_MAGIC)
if (header.magic == ipak_consts::IPAK_MAGIC_LITTLE_ENDIAN)
{
m_little_endian = true;
m_stream_manager = IPakStreamManager::Create(*m_stream, true);
}
else if (header.magic == ipak_consts::IPAK_MAGIC_BIG_ENDIAN)
{
m_little_endian = false;
m_stream_manager = IPakStreamManager::Create(*m_stream, false);
}
else
{
con::error("Invalid ipak magic '{:#x}'.", header.magic);
return false;
}
SwapBytesIfNecessary(header.version);
if (header.version != ipak_consts::IPAK_VERSION)
{
con::error("Unsupported ipak version '{}'.", header.version);
return false;
}
SwapBytesIfNecessary(header.size);
SwapBytesIfNecessary(header.sectionCount);
for (unsigned section = 0; section < header.sectionCount; section++)
{
if (!ReadSection())
@@ -189,17 +214,26 @@ namespace
return true;
}
template<std::integral T> void SwapBytesIfNecessary(T& value)
{
if (m_little_endian)
value = endianness::FromLittleEndian(value);
else
value = endianness::FromBigEndian(value);
}
std::string m_path;
std::unique_ptr<std::istream> m_stream;
bool m_initialized;
bool m_little_endian;
std::unique_ptr<IPakSection> m_index_section;
std::unique_ptr<IPakSection> m_data_section;
std::vector<IPakIndexEntry> m_index_entries;
IPakStreamManager m_stream_manager;
std::unique_ptr<IPakStreamManager> m_stream_manager;
};
} // namespace