2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-01-24 17:03:05 +00:00

refactor: implement base x64 fastfile loading for iw4

This commit is contained in:
Jan
2025-05-03 17:31:17 +01:00
parent 78d8fba6f8
commit 03ccede91c
43 changed files with 1025 additions and 331 deletions

View File

@@ -1,15 +1,22 @@
#include "ContentLoaderBase.h"
#include <cassert>
const void* ContentLoaderBase::PTR_FOLLOWING = reinterpret_cast<void*>(-1);
const void* ContentLoaderBase::PTR_INSERT = reinterpret_cast<void*>(-2);
#include <cstdint>
#include <limits>
ContentLoaderBase::ContentLoaderBase(Zone& zone, ZoneInputStream& stream)
: varXString(nullptr),
m_zone(zone),
m_memory(zone.Memory()),
m_stream(stream)
m_stream(stream),
// -1
m_zone_ptr_following(
reinterpret_cast<const void*>(std::numeric_limits<std::uintptr_t>::max() >> ((sizeof(std::uintptr_t) * 8u) - stream.GetPointerBitCount()))),
// -2
m_zone_ptr_insert(
reinterpret_cast<const void*>((std::numeric_limits<std::uintptr_t>::max() >> ((sizeof(std::uintptr_t) * 8u) - stream.GetPointerBitCount())) - 1u))
{
}
@@ -22,9 +29,9 @@ void ContentLoaderBase::LoadXString(const bool atStreamStart) const
if (*varXString != nullptr)
{
if (*varXString == PTR_FOLLOWING)
if (GetZonePointerType(*varXString) == ZonePointerType::FOLLOWING)
{
*varXString = m_stream.Alloc<const char>(alignof(const char));
*varXString = m_stream.Alloc<const char>(1);
m_stream.LoadNullTerminated(const_cast<char*>(*varXString));
}
else
@@ -39,7 +46,12 @@ void ContentLoaderBase::LoadXStringArray(const bool atStreamStart, const size_t
assert(varXString != nullptr);
if (atStreamStart)
m_stream.Load<const char*>(varXString, count);
{
const auto fill = m_stream.LoadWithFill(4u * count);
for (size_t index = 0; index < count; index++)
fill.FillPtr(varXString[index], 4u * index);
}
for (size_t index = 0; index < count; index++)
{
@@ -47,3 +59,13 @@ void ContentLoaderBase::LoadXStringArray(const bool atStreamStart, const size_t
varXString++;
}
}
ZonePointerType ContentLoaderBase::GetZonePointerType(const void* zonePtr) const
{
if (zonePtr == m_zone_ptr_following)
return ZonePointerType::FOLLOWING;
if (zonePtr == m_zone_ptr_insert)
return ZonePointerType::INSERT;
return ZonePointerType::OFFSET;
}

View File

@@ -3,12 +3,17 @@
#include "Zone/Stream/ZoneInputStream.h"
#include "Zone/Zone.h"
#include <cstdint>
enum class ZonePointerType : std::uint8_t
{
FOLLOWING,
INSERT,
OFFSET
};
class ContentLoaderBase
{
protected:
static const void* PTR_FOLLOWING;
static const void* PTR_INSERT;
public:
virtual ~ContentLoaderBase() = default;
ContentLoaderBase(const ContentLoaderBase& other) = default;
@@ -22,9 +27,20 @@ protected:
void LoadXString(bool atStreamStart) const;
void LoadXStringArray(bool atStreamStart, size_t count);
[[nodiscard]] ZonePointerType GetZonePointerType(const void* zonePtr) const;
template<typename T> [[nodiscard]] ZonePointerType GetZonePointerType(T* zonePtr) const
{
return GetZonePointerType(reinterpret_cast<const void*>(zonePtr));
}
const char** varXString;
Zone& m_zone;
MemoryManager& m_memory;
ZoneInputStream& m_stream;
private:
const void* m_zone_ptr_following;
const void* m_zone_ptr_insert;
};

View File

@@ -0,0 +1,19 @@
#include "InvalidAliasLookupException.h"
#include <format>
InvalidAliasLookupException::InvalidAliasLookupException(const size_t lookupIndex, const size_t lookupCount)
: m_lookup_index(lookupIndex),
m_lookup_count(lookupCount)
{
}
std::string InvalidAliasLookupException::DetailedMessage()
{
return std::format("Tried to resolve zone alias lookup {} when there are only {} entries in the lookup", m_lookup_index, m_lookup_count);
}
char const* InvalidAliasLookupException::what() const noexcept
{
return "Tried to resolve invalid zone alias lookup";
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include "LoadingException.h"
#include "Zone/XBlock.h"
class InvalidAliasLookupException final : public LoadingException
{
public:
InvalidAliasLookupException(size_t lookupIndex, size_t lookupCount);
std::string DetailedMessage() override;
[[nodiscard]] char const* what() const noexcept override;
private:
size_t m_lookup_index;
size_t m_lookup_count;
};

View File

@@ -4,7 +4,7 @@
namespace
{
constexpr uint64_t MAX_XBLOCK_SIZE = 0x3C000000;
constexpr uint64_t MAX_XBLOCK_SIZE = 0x3C000000; // ~1GB
class StepAllocXBlocks final : public ILoadingStep
{

View File

@@ -10,17 +10,20 @@ namespace
StepLoadZoneContent(std::function<std::unique_ptr<IContentLoadingEntryPoint>(ZoneInputStream&)> entryPointFactory,
const unsigned pointerBitCount,
const unsigned offsetBlockBitCount,
const block_t insertBlock)
const block_t insertBlock,
MemoryManager& memory)
: m_entry_point_factory(std::move(entryPointFactory)),
m_pointer_bit_count(pointerBitCount),
m_offset_block_bit_count(offsetBlockBitCount),
m_insert_block(insertBlock)
m_insert_block(insertBlock),
m_memory(memory)
{
}
void PerformStep(ZoneLoader& zoneLoader, ILoadingStream& stream) override
{
const auto inputStream = ZoneInputStream::Create(m_pointer_bit_count, m_offset_block_bit_count, zoneLoader.m_blocks, m_insert_block, stream);
const auto inputStream =
ZoneInputStream::Create(m_pointer_bit_count, m_offset_block_bit_count, zoneLoader.m_blocks, m_insert_block, stream, m_memory);
const auto entryPoint = m_entry_point_factory(*inputStream);
assert(entryPoint);
@@ -33,6 +36,7 @@ namespace
unsigned m_pointer_bit_count;
unsigned m_offset_block_bit_count;
block_t m_insert_block;
MemoryManager& m_memory;
};
} // namespace
@@ -41,8 +45,9 @@ namespace step
std::unique_ptr<ILoadingStep> CreateStepLoadZoneContent(std::function<std::unique_ptr<IContentLoadingEntryPoint>(ZoneInputStream&)> entryPointFactory,
const unsigned pointerBitCount,
const unsigned offsetBlockBitCount,
const block_t insertBlock)
const block_t insertBlock,
MemoryManager& memory)
{
return std::make_unique<StepLoadZoneContent>(std::move(entryPointFactory), pointerBitCount, offsetBlockBitCount, insertBlock);
return std::make_unique<StepLoadZoneContent>(std::move(entryPointFactory), pointerBitCount, offsetBlockBitCount, insertBlock, memory);
}
} // namespace step

View File

@@ -12,5 +12,6 @@ namespace step
std::unique_ptr<ILoadingStep> CreateStepLoadZoneContent(std::function<std::unique_ptr<IContentLoadingEntryPoint>(ZoneInputStream&)> entryPointFactory,
unsigned pointerBitCount,
unsigned offsetBlockBitCount,
block_t insertBlock);
block_t insertBlock,
MemoryManager& memory);
}