mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-11-04 00:11:58 +00:00
96 lines
3.8 KiB
C++
96 lines
3.8 KiB
C++
#include "ZoneLoaderFactoryT4.h"
|
|
|
|
#include "ContentLoaderT4.h"
|
|
#include "Game/GameLanguage.h"
|
|
#include "Game/T4/GameT4.h"
|
|
#include "Game/T4/T4.h"
|
|
#include "Game/T4/ZoneConstantsT4.h"
|
|
#include "Loading/Processor/ProcessorInflate.h"
|
|
#include "Loading/Steps/StepAddProcessor.h"
|
|
#include "Loading/Steps/StepAllocXBlocks.h"
|
|
#include "Loading/Steps/StepLoadZoneContent.h"
|
|
#include "Loading/Steps/StepLoadZoneSizes.h"
|
|
#include "Loading/Steps/StepSkipBytes.h"
|
|
#include "Utils/ClassUtils.h"
|
|
#include "Utils/Endianness.h"
|
|
|
|
#include <cstring>
|
|
|
|
using namespace T4;
|
|
|
|
namespace
|
|
{
|
|
void SetupBlock(ZoneMemory& zoneMemory)
|
|
{
|
|
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
|
|
|
zoneMemory.AddBlock(XBLOCK_DEF(T4::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP));
|
|
zoneMemory.AddBlock(XBLOCK_DEF(T4::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME));
|
|
zoneMemory.AddBlock(XBLOCK_DEF(T4::XFILE_BLOCK_LARGE_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME));
|
|
zoneMemory.AddBlock(XBLOCK_DEF(T4::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME));
|
|
zoneMemory.AddBlock(XBLOCK_DEF(T4::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL));
|
|
zoneMemory.AddBlock(XBLOCK_DEF(T4::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL));
|
|
zoneMemory.AddBlock(XBLOCK_DEF(T4::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL));
|
|
|
|
#undef XBLOCK_DEF
|
|
}
|
|
} // namespace
|
|
|
|
std::optional<ZoneLoaderInspectionResult> ZoneLoaderFactory::InspectZoneHeader(ZoneDataPeeking& filePeek) const
|
|
{
|
|
const auto& header = filePeek.PeekStruct<ZoneHeader>();
|
|
if (endianness::FromLittleEndian(header.m_version) == ZoneConstants::ZONE_VERSION_PC
|
|
&& !memcmp(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, std::char_traits<char>::length(ZoneConstants::MAGIC_UNSIGNED)))
|
|
{
|
|
return ZoneLoaderInspectionResult{
|
|
.m_game_id = GameId::T4,
|
|
.m_variant_id = GameVariantId::T4_PC,
|
|
// There is no way to know whether unsigned zones are official.
|
|
.m_is_official = false,
|
|
.m_is_signed = false,
|
|
.m_is_encrypted = false,
|
|
};
|
|
}
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::unique_ptr<ZoneLoader> ZoneLoaderFactory::CreateLoaderForHeader(ZoneDataPeeking& filePeek,
|
|
const std::string& fileName,
|
|
std::optional<std::unique_ptr<ProgressCallback>> progressCallback) const
|
|
{
|
|
const auto inspectResult = InspectZoneHeader(filePeek);
|
|
if (!inspectResult)
|
|
return nullptr;
|
|
|
|
// Create new zone
|
|
auto zone = std::make_unique<Zone>(fileName, 0, inspectResult->m_variant_id);
|
|
auto* zonePtr = zone.get();
|
|
zone->m_language = GameLanguage::LANGUAGE_NONE;
|
|
|
|
// File is supported. Now setup all required steps for loading this file.
|
|
auto zoneLoader = std::make_unique<ZoneLoader>(std::move(zone));
|
|
|
|
SetupBlock(zonePtr->Memory());
|
|
|
|
// Skip the initial header that we peeked at before
|
|
zoneLoader->AddLoadingStep(step::CreateStepSkipBytes(sizeof(ZoneHeader)));
|
|
|
|
zoneLoader->AddLoadingStep(step::CreateStepAddProcessor(processor::CreateProcessorInflate(ZoneConstants::AUTHED_CHUNK_SIZE)));
|
|
zoneLoader->AddLoadingStep(step::CreateStepLoadZoneSizes());
|
|
zoneLoader->AddLoadingStep(step::CreateStepAllocXBlocks(zonePtr));
|
|
zoneLoader->AddLoadingStep(step::CreateStepLoadZoneContent(
|
|
[zonePtr](ZoneInputStream& stream)
|
|
{
|
|
return std::make_unique<ContentLoader>(*zonePtr, stream);
|
|
},
|
|
32u,
|
|
ZoneConstants::ZONE_POINTER_OFFSET_BIT_COUNT,
|
|
ZoneConstants::ZONE_POINTER_BLOCK_BIT_COUNT,
|
|
ZoneConstants::INSERT_BLOCK,
|
|
zonePtr,
|
|
std::move(progressCallback)));
|
|
|
|
return zoneLoader;
|
|
}
|