mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
chore: use method static array for zonewriterfactory
This commit is contained in:
parent
a1851b0ea0
commit
ce16d8e6c8
@ -16,36 +16,26 @@
|
|||||||
|
|
||||||
using namespace IW3;
|
using namespace IW3;
|
||||||
|
|
||||||
class ZoneWriterFactory::Impl
|
namespace
|
||||||
{
|
{
|
||||||
Zone* m_zone;
|
void SetupBlocks(ZoneWriter& writer)
|
||||||
std::unique_ptr<ZoneWriter> m_writer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Impl(Zone* zone)
|
|
||||||
: m_zone(zone),
|
|
||||||
m_writer(std::make_unique<ZoneWriter>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupBlocks() const
|
|
||||||
{
|
{
|
||||||
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
||||||
|
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
|
|
||||||
#undef XBLOCK_DEF
|
#undef XBLOCK_DEF
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZoneHeader CreateHeaderForParams()
|
ZoneHeader CreateHeaderForParams()
|
||||||
{
|
{
|
||||||
ZoneHeader header{};
|
ZoneHeader header{};
|
||||||
header.m_version = ZoneConstants::ZONE_VERSION;
|
header.m_version = ZoneConstants::ZONE_VERSION;
|
||||||
@ -53,40 +43,30 @@ public:
|
|||||||
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
std::unique_ptr<ZoneWriter> CreateWriter()
|
|
||||||
{
|
|
||||||
SetupBlocks();
|
|
||||||
|
|
||||||
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
|
||||||
std::make_unique<ContentWriter>(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
|
|
||||||
auto* contentInMemoryPtr = contentInMemory.get();
|
|
||||||
m_writer->AddWritingStep(std::move(contentInMemory));
|
|
||||||
|
|
||||||
// Write zone header
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneHeader>(CreateHeaderForParams()));
|
|
||||||
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::make_unique<OutputProcessorDeflate>()));
|
|
||||||
|
|
||||||
// Start of the XFile struct
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(m_zone));
|
|
||||||
|
|
||||||
// Start of the zone content
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
|
||||||
|
|
||||||
// Return the fully setup zoneloader
|
|
||||||
return std::move(m_writer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ZoneWriterFactory::SupportsZone(Zone* zone) const
|
|
||||||
{
|
|
||||||
return zone->m_game == &g_GameIW3;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
||||||
{
|
{
|
||||||
Impl impl(zone);
|
std::unique_ptr<ZoneWriter> writer;
|
||||||
return impl.CreateWriter();
|
|
||||||
|
SetupBlocks(*writer);
|
||||||
|
|
||||||
|
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
||||||
|
std::make_unique<ContentWriter>(), 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<StepWriteZoneHeader>(CreateHeaderForParams()));
|
||||||
|
|
||||||
|
writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::make_unique<OutputProcessorDeflate>()));
|
||||||
|
|
||||||
|
// Start of the XFile struct
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(zone));
|
||||||
|
|
||||||
|
// Start of the zone content
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
||||||
|
|
||||||
|
return std::move(writer);
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,7 @@ namespace IW3
|
|||||||
{
|
{
|
||||||
class ZoneWriterFactory final : public IZoneWriterFactory
|
class ZoneWriterFactory final : public IZoneWriterFactory
|
||||||
{
|
{
|
||||||
class Impl;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_NODISCARD bool SupportsZone(Zone* zone) const override;
|
|
||||||
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
||||||
};
|
};
|
||||||
} // namespace IW3
|
} // namespace IW3
|
||||||
|
@ -18,35 +18,25 @@
|
|||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
class ZoneWriterFactory::Impl
|
namespace
|
||||||
{
|
{
|
||||||
Zone* m_zone;
|
void SetupBlocks(ZoneWriter& writer)
|
||||||
std::unique_ptr<ZoneWriter> m_writer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Impl(Zone* zone)
|
|
||||||
: m_zone(zone),
|
|
||||||
m_writer(std::make_unique<ZoneWriter>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupBlocks() const
|
|
||||||
{
|
{
|
||||||
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
||||||
|
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
|
|
||||||
#undef XBLOCK_DEF
|
#undef XBLOCK_DEF
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial)
|
ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial)
|
||||||
{
|
{
|
||||||
ZoneHeader header{};
|
ZoneHeader header{};
|
||||||
header.m_version = ZoneConstants::ZONE_VERSION;
|
header.m_version = ZoneConstants::ZONE_VERSION;
|
||||||
@ -65,49 +55,39 @@ public:
|
|||||||
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
}; // namespace
|
||||||
std::unique_ptr<ZoneWriter> CreateWriter()
|
|
||||||
{
|
|
||||||
// TODO Support signed fastfiles
|
|
||||||
bool isSecure = false;
|
|
||||||
|
|
||||||
SetupBlocks();
|
|
||||||
|
|
||||||
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
|
||||||
std::make_unique<ContentWriter>(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
|
|
||||||
auto* contentInMemoryPtr = contentInMemory.get();
|
|
||||||
m_writer->AddWritingStep(std::move(contentInMemory));
|
|
||||||
|
|
||||||
// Write zone header
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneHeader>(CreateHeaderForParams(isSecure, false)));
|
|
||||||
|
|
||||||
// Write dummy byte that the game ignores as well. No clue what it means.
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZero>(1));
|
|
||||||
|
|
||||||
// Write timestamp
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteTimestamp>());
|
|
||||||
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::make_unique<OutputProcessorDeflate>()));
|
|
||||||
|
|
||||||
// Start of the XFile struct
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(m_zone));
|
|
||||||
|
|
||||||
// Start of the zone content
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
|
||||||
|
|
||||||
// Return the fully setup zoneloader
|
|
||||||
return std::move(m_writer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ZoneWriterFactory::SupportsZone(Zone* zone) const
|
|
||||||
{
|
|
||||||
return zone->m_game == &g_GameIW4;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
||||||
{
|
{
|
||||||
Impl impl(zone);
|
auto writer = std::make_unique<ZoneWriter>();
|
||||||
return impl.CreateWriter();
|
|
||||||
|
// TODO Support signed fastfiles
|
||||||
|
bool isSecure = false;
|
||||||
|
|
||||||
|
SetupBlocks(*writer);
|
||||||
|
|
||||||
|
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
||||||
|
std::make_unique<ContentWriter>(), 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<StepWriteZoneHeader>(CreateHeaderForParams(isSecure, false)));
|
||||||
|
|
||||||
|
// Write dummy byte that the game ignores as well. No clue what it means.
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZero>(1));
|
||||||
|
|
||||||
|
// Write timestamp
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteTimestamp>());
|
||||||
|
|
||||||
|
writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::make_unique<OutputProcessorDeflate>()));
|
||||||
|
|
||||||
|
// Start of the XFile struct
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(zone));
|
||||||
|
|
||||||
|
// Start of the zone content
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
||||||
|
|
||||||
|
return std::move(writer);
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,7 @@ namespace IW4
|
|||||||
{
|
{
|
||||||
class ZoneWriterFactory final : public IZoneWriterFactory
|
class ZoneWriterFactory final : public IZoneWriterFactory
|
||||||
{
|
{
|
||||||
class Impl;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_NODISCARD bool SupportsZone(Zone* zone) const override;
|
|
||||||
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
||||||
};
|
};
|
||||||
} // namespace IW4
|
} // namespace IW4
|
||||||
|
@ -18,36 +18,26 @@
|
|||||||
|
|
||||||
using namespace IW5;
|
using namespace IW5;
|
||||||
|
|
||||||
class ZoneWriterFactory::Impl
|
namespace
|
||||||
{
|
{
|
||||||
Zone* m_zone;
|
void SetupBlocks(ZoneWriter& writer)
|
||||||
std::unique_ptr<ZoneWriter> m_writer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Impl(Zone* zone)
|
|
||||||
: m_zone(zone),
|
|
||||||
m_writer(std::make_unique<ZoneWriter>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupBlocks() const
|
|
||||||
{
|
{
|
||||||
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
||||||
|
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
|
|
||||||
#undef XBLOCK_DEF
|
#undef XBLOCK_DEF
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial)
|
ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial)
|
||||||
{
|
{
|
||||||
ZoneHeader header{};
|
ZoneHeader header{};
|
||||||
header.m_version = ZoneConstants::ZONE_VERSION;
|
header.m_version = ZoneConstants::ZONE_VERSION;
|
||||||
@ -66,49 +56,39 @@ public:
|
|||||||
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
}; // namespace
|
||||||
std::unique_ptr<ZoneWriter> CreateWriter()
|
|
||||||
{
|
|
||||||
// TODO Support signed fastfiles
|
|
||||||
bool isSecure = false;
|
|
||||||
|
|
||||||
SetupBlocks();
|
|
||||||
|
|
||||||
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
|
||||||
std::make_unique<ContentWriter>(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
|
|
||||||
auto* contentInMemoryPtr = contentInMemory.get();
|
|
||||||
m_writer->AddWritingStep(std::move(contentInMemory));
|
|
||||||
|
|
||||||
// Write zone header
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneHeader>(CreateHeaderForParams(isSecure, false)));
|
|
||||||
|
|
||||||
// Write dummy byte that the game ignores as well. No clue what it means.
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZero>(1));
|
|
||||||
|
|
||||||
// Write timestamp
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteTimestamp>());
|
|
||||||
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::make_unique<OutputProcessorDeflate>()));
|
|
||||||
|
|
||||||
// Start of the XFile struct
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(m_zone));
|
|
||||||
|
|
||||||
// Start of the zone content
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
|
||||||
|
|
||||||
// Return the fully setup zoneloader
|
|
||||||
return std::move(m_writer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ZoneWriterFactory::SupportsZone(Zone* zone) const
|
|
||||||
{
|
|
||||||
return zone->m_game == &g_GameIW5;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
||||||
{
|
{
|
||||||
Impl impl(zone);
|
auto writer = std::make_unique<ZoneWriter>();
|
||||||
return impl.CreateWriter();
|
|
||||||
|
// TODO Support signed fastfiles
|
||||||
|
bool isSecure = false;
|
||||||
|
|
||||||
|
SetupBlocks(*writer);
|
||||||
|
|
||||||
|
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
||||||
|
std::make_unique<ContentWriter>(), 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<StepWriteZoneHeader>(CreateHeaderForParams(isSecure, false)));
|
||||||
|
|
||||||
|
// Write dummy byte that the game ignores as well. No clue what it means.
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZero>(1));
|
||||||
|
|
||||||
|
// Write timestamp
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteTimestamp>());
|
||||||
|
|
||||||
|
writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::make_unique<OutputProcessorDeflate>()));
|
||||||
|
|
||||||
|
// Start of the XFile struct
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(zone));
|
||||||
|
|
||||||
|
// Start of the zone content
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
||||||
|
|
||||||
|
return std::move(writer);
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,7 @@ namespace IW5
|
|||||||
{
|
{
|
||||||
class ZoneWriterFactory final : public IZoneWriterFactory
|
class ZoneWriterFactory final : public IZoneWriterFactory
|
||||||
{
|
{
|
||||||
class Impl;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_NODISCARD bool SupportsZone(Zone* zone) const override;
|
|
||||||
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
||||||
};
|
};
|
||||||
} // namespace IW5
|
} // namespace IW5
|
||||||
|
@ -16,34 +16,24 @@
|
|||||||
|
|
||||||
using namespace T5;
|
using namespace T5;
|
||||||
|
|
||||||
class ZoneWriterFactory::Impl
|
namespace
|
||||||
{
|
{
|
||||||
Zone* m_zone;
|
void SetupBlocks(ZoneWriter& writer)
|
||||||
std::unique_ptr<ZoneWriter> m_writer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Impl(Zone* zone)
|
|
||||||
: m_zone(zone),
|
|
||||||
m_writer(std::make_unique<ZoneWriter>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupBlocks() const
|
|
||||||
{
|
{
|
||||||
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
||||||
|
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
|
|
||||||
#undef XBLOCK_DEF
|
#undef XBLOCK_DEF
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZoneHeader CreateHeaderForParams()
|
ZoneHeader CreateHeaderForParams()
|
||||||
{
|
{
|
||||||
ZoneHeader header{};
|
ZoneHeader header{};
|
||||||
header.m_version = ZoneConstants::ZONE_VERSION;
|
header.m_version = ZoneConstants::ZONE_VERSION;
|
||||||
@ -51,40 +41,30 @@ public:
|
|||||||
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
std::unique_ptr<ZoneWriter> CreateWriter()
|
|
||||||
{
|
|
||||||
SetupBlocks();
|
|
||||||
|
|
||||||
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
|
||||||
std::make_unique<ContentWriter>(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
|
|
||||||
auto* contentInMemoryPtr = contentInMemory.get();
|
|
||||||
m_writer->AddWritingStep(std::move(contentInMemory));
|
|
||||||
|
|
||||||
// Write zone header
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneHeader>(CreateHeaderForParams()));
|
|
||||||
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::make_unique<OutputProcessorDeflate>()));
|
|
||||||
|
|
||||||
// Start of the XFile struct
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(m_zone));
|
|
||||||
|
|
||||||
// Start of the zone content
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
|
||||||
|
|
||||||
// Return the fully setup zoneloader
|
|
||||||
return std::move(m_writer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ZoneWriterFactory::SupportsZone(Zone* zone) const
|
|
||||||
{
|
|
||||||
return zone->m_game == &g_GameT5;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
||||||
{
|
{
|
||||||
Impl impl(zone);
|
auto writer = std::make_unique<ZoneWriter>();
|
||||||
return impl.CreateWriter();
|
|
||||||
|
SetupBlocks(*writer);
|
||||||
|
|
||||||
|
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
||||||
|
std::make_unique<ContentWriter>(), 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<StepWriteZoneHeader>(CreateHeaderForParams()));
|
||||||
|
|
||||||
|
writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::make_unique<OutputProcessorDeflate>()));
|
||||||
|
|
||||||
|
// Start of the XFile struct
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(zone));
|
||||||
|
|
||||||
|
// Start of the zone content
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
||||||
|
|
||||||
|
return std::move(writer);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ namespace T5
|
|||||||
class Impl;
|
class Impl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_NODISCARD bool SupportsZone(Zone* zone) const override;
|
|
||||||
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
||||||
};
|
};
|
||||||
} // namespace T5
|
} // namespace T5
|
||||||
|
@ -23,35 +23,25 @@
|
|||||||
|
|
||||||
using namespace T6;
|
using namespace T6;
|
||||||
|
|
||||||
class ZoneWriterFactory::Impl
|
namespace
|
||||||
{
|
{
|
||||||
Zone* m_zone;
|
void SetupBlocks(ZoneWriter& writer)
|
||||||
std::unique_ptr<ZoneWriter> m_writer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Impl(Zone* zone)
|
|
||||||
: m_zone(zone),
|
|
||||||
m_writer(std::make_unique<ZoneWriter>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupBlocks() const
|
|
||||||
{
|
{
|
||||||
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
||||||
|
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlock::Type::BLOCK_TYPE_DELAY));
|
writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlock::Type::BLOCK_TYPE_DELAY));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlock::Type::BLOCK_TYPE_DELAY));
|
writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlock::Type::BLOCK_TYPE_DELAY));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||||
|
|
||||||
#undef XBLOCK_DEF
|
#undef XBLOCK_DEF
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial, const bool isEncrypted)
|
ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial, const bool isEncrypted)
|
||||||
{
|
{
|
||||||
ZoneHeader header{};
|
ZoneHeader header{};
|
||||||
header.m_version = ZoneConstants::ZONE_VERSION;
|
header.m_version = ZoneConstants::ZONE_VERSION;
|
||||||
@ -74,7 +64,11 @@ public:
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXChunkProcessor(const bool isEncrypted, ICapturedDataProvider** dataToSignProviderPtr, OutputProcessorXChunks** xChunkProcessorPtr) const
|
void AddXChunkProcessor(ZoneWriter& writer,
|
||||||
|
const Zone& zone,
|
||||||
|
const bool isEncrypted,
|
||||||
|
ICapturedDataProvider** dataToSignProviderPtr,
|
||||||
|
OutputProcessorXChunks** xChunkProcessorPtr)
|
||||||
{
|
{
|
||||||
auto xChunkProcessor = std::make_unique<OutputProcessorXChunks>(
|
auto xChunkProcessor = std::make_unique<OutputProcessorXChunks>(
|
||||||
ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::XCHUNK_MAX_WRITE_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE);
|
ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::XCHUNK_MAX_WRITE_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE);
|
||||||
@ -88,7 +82,7 @@ public:
|
|||||||
{
|
{
|
||||||
// If zone is encrypted, the decryption is applied before the decompression. T6 Zones always use Salsa20.
|
// If zone is encrypted, the decryption is applied before the decompression. T6 Zones always use Salsa20.
|
||||||
auto chunkProcessorSalsa20 = std::make_unique<XChunkProcessorSalsa20Encryption>(
|
auto chunkProcessorSalsa20 = std::make_unique<XChunkProcessorSalsa20Encryption>(
|
||||||
ZoneConstants::STREAM_COUNT, m_zone->m_name, ZoneConstants::SALSA20_KEY_TREYARCH, sizeof(ZoneConstants::SALSA20_KEY_TREYARCH));
|
ZoneConstants::STREAM_COUNT, zone.m_name, ZoneConstants::SALSA20_KEY_TREYARCH, sizeof(ZoneConstants::SALSA20_KEY_TREYARCH));
|
||||||
|
|
||||||
// If there is encryption, the signed data of the zone is the final hash blocks provided by the Salsa20 IV adaption algorithm
|
// If there is encryption, the signed data of the zone is the final hash blocks provided by the Salsa20 IV adaption algorithm
|
||||||
if (dataToSignProviderPtr)
|
if (dataToSignProviderPtr)
|
||||||
@ -97,58 +91,48 @@ public:
|
|||||||
xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20));
|
xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::move(xChunkProcessor)));
|
writer.AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::move(xChunkProcessor)));
|
||||||
}
|
}
|
||||||
|
}; // namespace
|
||||||
std::unique_ptr<ZoneWriter> CreateWriter()
|
|
||||||
{
|
|
||||||
// TODO Support signed fastfiles
|
|
||||||
bool isSecure = false;
|
|
||||||
bool isEncrypted = true;
|
|
||||||
|
|
||||||
SetupBlocks();
|
|
||||||
|
|
||||||
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
|
||||||
std::make_unique<ContentWriter>(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
|
|
||||||
auto* contentInMemoryPtr = contentInMemory.get();
|
|
||||||
m_writer->AddWritingStep(std::move(contentInMemory));
|
|
||||||
|
|
||||||
// Write zone header
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneHeader>(CreateHeaderForParams(isSecure, false, isEncrypted)));
|
|
||||||
|
|
||||||
// Setup loading XChunks from the zone from this point on.
|
|
||||||
ICapturedDataProvider* dataToSignProvider;
|
|
||||||
OutputProcessorXChunks* xChunksProcessor;
|
|
||||||
AddXChunkProcessor(isEncrypted, &dataToSignProvider, &xChunksProcessor);
|
|
||||||
|
|
||||||
// Start of the XFile struct
|
|
||||||
// m_writer->AddWritingStep(std::make_unique<StepSkipBytes>(8)); // Skip size and externalSize fields since they are not interesting for us
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(m_zone));
|
|
||||||
|
|
||||||
// Start of the zone content
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
|
||||||
|
|
||||||
// Stop writing in XChunks
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepRemoveOutputProcessor>(xChunksProcessor));
|
|
||||||
|
|
||||||
// Pad ending with zeros like the original linker does it. The game's reader needs it for some reason.
|
|
||||||
// From my observations this is most likely the logic behind the amount of bytes: At least 0x40 bytes and aligned to the next 0x40
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZero>(ZoneConstants::FILE_SUFFIX_ZERO_MIN_SIZE));
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepAlign>(ZoneConstants::FILE_SUFFIX_ZERO_ALIGN, '\0'));
|
|
||||||
|
|
||||||
// Return the fully setup zoneloader
|
|
||||||
return std::move(m_writer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ZoneWriterFactory::SupportsZone(Zone* zone) const
|
|
||||||
{
|
|
||||||
return zone->m_game == &g_GameT6;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
||||||
{
|
{
|
||||||
Impl impl(zone);
|
auto writer = std::make_unique<ZoneWriter>();
|
||||||
return impl.CreateWriter();
|
|
||||||
|
// TODO Support signed fastfiles
|
||||||
|
bool isSecure = false;
|
||||||
|
bool isEncrypted = true;
|
||||||
|
|
||||||
|
SetupBlocks(*writer);
|
||||||
|
|
||||||
|
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
|
||||||
|
std::make_unique<ContentWriter>(), 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<StepWriteZoneHeader>(CreateHeaderForParams(isSecure, false, isEncrypted)));
|
||||||
|
|
||||||
|
// Setup loading XChunks from the zone from this point on.
|
||||||
|
ICapturedDataProvider* dataToSignProvider;
|
||||||
|
OutputProcessorXChunks* xChunksProcessor;
|
||||||
|
AddXChunkProcessor(*writer, *zone, isEncrypted, &dataToSignProvider, &xChunksProcessor);
|
||||||
|
|
||||||
|
// Start of the XFile struct
|
||||||
|
// m_writer->AddWritingStep(std::make_unique<StepSkipBytes>(8)); // Skip size and externalSize fields since they are not interesting for us
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(zone));
|
||||||
|
|
||||||
|
// Start of the zone content
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
||||||
|
|
||||||
|
// Stop writing in XChunks
|
||||||
|
writer->AddWritingStep(std::make_unique<StepRemoveOutputProcessor>(xChunksProcessor));
|
||||||
|
|
||||||
|
// Pad ending with zeros like the original linker does it. The game's reader needs it for some reason.
|
||||||
|
// From my observations this is most likely the logic behind the amount of bytes: At least 0x40 bytes and aligned to the next 0x40
|
||||||
|
writer->AddWritingStep(std::make_unique<StepWriteZero>(ZoneConstants::FILE_SUFFIX_ZERO_MIN_SIZE));
|
||||||
|
writer->AddWritingStep(std::make_unique<StepAlign>(ZoneConstants::FILE_SUFFIX_ZERO_ALIGN, '\0'));
|
||||||
|
|
||||||
|
return std::move(writer);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ namespace T6
|
|||||||
class Impl;
|
class Impl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_NODISCARD bool SupportsZone(Zone* zone) const override;
|
|
||||||
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
||||||
};
|
};
|
||||||
} // namespace T6
|
} // namespace T6
|
||||||
|
27
src/ZoneWriting/Writing/IZoneWriterFactory.cpp
Normal file
27
src/ZoneWriting/Writing/IZoneWriterFactory.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "IZoneWriterFactory.h"
|
||||||
|
|
||||||
|
#include "Game/IW3/ZoneWriterFactoryIW3.h"
|
||||||
|
#include "Game/IW4/ZoneWriterFactoryIW4.h"
|
||||||
|
#include "Game/IW5/ZoneWriterFactoryIW5.h"
|
||||||
|
#include "Game/T5/ZoneWriterFactoryT5.h"
|
||||||
|
#include "Game/T6/ZoneWriterFactoryT6.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
const IZoneWriterFactory* IZoneWriterFactory::GetZoneWriterFactoryForGame(GameId game)
|
||||||
|
{
|
||||||
|
static const IZoneWriterFactory* zoneCreators[static_cast<unsigned>(GameId::COUNT)]{
|
||||||
|
new IW3::ZoneWriterFactory(),
|
||||||
|
new IW4::ZoneWriterFactory(),
|
||||||
|
new IW5::ZoneWriterFactory(),
|
||||||
|
new T5::ZoneWriterFactory(),
|
||||||
|
new T6::ZoneWriterFactory(),
|
||||||
|
};
|
||||||
|
static_assert(std::extent_v<decltype(zoneCreators)> == static_cast<unsigned>(GameId::COUNT));
|
||||||
|
|
||||||
|
assert(static_cast<unsigned>(game) < static_cast<unsigned>(GameId::COUNT));
|
||||||
|
const auto* result = zoneCreators[static_cast<unsigned>(game)];
|
||||||
|
assert(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
@ -14,6 +14,7 @@ public:
|
|||||||
IZoneWriterFactory& operator=(const IZoneWriterFactory& other) = default;
|
IZoneWriterFactory& operator=(const IZoneWriterFactory& other) = default;
|
||||||
IZoneWriterFactory& operator=(IZoneWriterFactory&& other) noexcept = default;
|
IZoneWriterFactory& operator=(IZoneWriterFactory&& other) noexcept = default;
|
||||||
|
|
||||||
_NODISCARD virtual bool SupportsZone(Zone* zone) const = 0;
|
|
||||||
_NODISCARD virtual std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const = 0;
|
_NODISCARD virtual std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const = 0;
|
||||||
|
|
||||||
|
static const IZoneWriterFactory* GetZoneWriterFactoryForGame(GameId game);
|
||||||
};
|
};
|
||||||
|
@ -1,38 +1,18 @@
|
|||||||
#include "ZoneWriting.h"
|
#include "ZoneWriting.h"
|
||||||
|
|
||||||
#include "Game/IW3/ZoneWriterFactoryIW3.h"
|
|
||||||
#include "Game/IW4/ZoneWriterFactoryIW4.h"
|
|
||||||
#include "Game/IW5/ZoneWriterFactoryIW5.h"
|
|
||||||
#include "Game/T5/ZoneWriterFactoryT5.h"
|
|
||||||
#include "Game/T6/ZoneWriterFactoryT6.h"
|
|
||||||
#include "Writing/IZoneWriterFactory.h"
|
#include "Writing/IZoneWriterFactory.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
IZoneWriterFactory* ZoneWriterFactories[]{
|
|
||||||
new IW3::ZoneWriterFactory(),
|
|
||||||
new IW4::ZoneWriterFactory(),
|
|
||||||
new IW5::ZoneWriterFactory(),
|
|
||||||
new T5::ZoneWriterFactory(),
|
|
||||||
new T6::ZoneWriterFactory(),
|
|
||||||
};
|
|
||||||
|
|
||||||
bool ZoneWriting::WriteZone(std::ostream& stream, Zone* zone)
|
bool ZoneWriting::WriteZone(std::ostream& stream, Zone* zone)
|
||||||
{
|
{
|
||||||
const auto start = std::chrono::high_resolution_clock::now();
|
const auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
std::unique_ptr<ZoneWriter> zoneWriter;
|
const auto factory = IZoneWriterFactory::GetZoneWriterFactoryForGame(zone->m_game->GetId());
|
||||||
for (auto* factory : ZoneWriterFactories)
|
|
||||||
{
|
|
||||||
if (factory->SupportsZone(zone))
|
|
||||||
{
|
|
||||||
zoneWriter = factory->CreateWriter(zone);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const auto zoneWriter = factory->CreateWriter(zone);
|
||||||
if (zoneWriter == nullptr)
|
if (zoneWriter == nullptr)
|
||||||
{
|
{
|
||||||
std::cerr << std::format("Could not create ZoneWriter for zone \"{}\".\n", zone->m_name);
|
std::cerr << std::format("Could not create ZoneWriter for zone \"{}\".\n", zone->m_name);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user