#include "ZoneWriterFactoryIW5.h" #include "ContentWriterIW5.h" #include "Game/IW5/GameIW5.h" #include "Game/IW5/IW5.h" #include "Game/IW5/ZoneConstantsIW5.h" #include "Writing/Processor/OutputProcessorDeflate.h" #include "Writing/Steps/StepAddOutputProcessor.h" #include "Writing/Steps/StepWriteTimestamp.h" #include "Writing/Steps/StepWriteXBlockSizes.h" #include "Writing/Steps/StepWriteZero.h" #include "Writing/Steps/StepWriteZoneContentToFile.h" #include "Writing/Steps/StepWriteZoneContentToMemory.h" #include "Writing/Steps/StepWriteZoneHeader.h" #include "Writing/Steps/StepWriteZoneSizes.h" #include using namespace IW5; namespace { void SetupBlocks(ZoneWriter& writer) { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlock::Type::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial) { ZoneHeader header{}; header.m_version = ZoneConstants::ZONE_VERSION; if (isSecure) { if (isOfficial) memcpy(header.m_magic, ZoneConstants::MAGIC_SIGNED_INFINITY_WARD, sizeof(ZoneHeader::m_magic)); else memcpy(header.m_magic, ZoneConstants::MAGIC_SIGNED_OAT, sizeof(ZoneHeader::m_magic)); } else { memcpy(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, sizeof(ZoneHeader::m_magic)); } return header; } }; // namespace std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const { auto writer = std::make_unique(); // TODO Support signed fastfiles bool isSecure = false; SetupBlocks(*writer); auto contentInMemory = std::make_unique( std::make_unique(), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); auto* contentInMemoryPtr = contentInMemory.get(); writer->AddWritingStep(std::move(contentInMemory)); // Write zone header writer->AddWritingStep(std::make_unique(CreateHeaderForParams(isSecure, false))); // Write dummy byte that the game ignores as well. No clue what it means. writer->AddWritingStep(std::make_unique(1)); // Write timestamp writer->AddWritingStep(std::make_unique()); writer->AddWritingStep(std::make_unique(std::make_unique())); // Start of the XFile struct writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); writer->AddWritingStep(std::make_unique(zone)); // Start of the zone content writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); return std::move(writer); }