From ce16d8e6c86b685e15015d2c5751a46133251329 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 19 Oct 2024 20:22:11 +0200 Subject: [PATCH] chore: use method static array for zonewriterfactory --- .../Game/IW3/ZoneWriterFactoryIW3.cpp | 80 +++++------- .../Game/IW3/ZoneWriterFactoryIW3.h | 3 - .../Game/IW4/ZoneWriterFactoryIW4.cpp | 90 ++++++-------- .../Game/IW4/ZoneWriterFactoryIW4.h | 3 - .../Game/IW5/ZoneWriterFactoryIW5.cpp | 92 ++++++-------- .../Game/IW5/ZoneWriterFactoryIW5.h | 3 - .../Game/T5/ZoneWriterFactoryT5.cpp | 76 +++++------- src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.h | 1 - .../Game/T6/ZoneWriterFactoryT6.cpp | 114 ++++++++---------- src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.h | 1 - .../Writing/IZoneWriterFactory.cpp | 27 +++++ src/ZoneWriting/Writing/IZoneWriterFactory.h | 3 +- src/ZoneWriting/ZoneWriting.cpp | 24 +--- 13 files changed, 209 insertions(+), 308 deletions(-) create mode 100644 src/ZoneWriting/Writing/IZoneWriterFactory.cpp diff --git a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp index 4fdeead9c..ce9a08249 100644 --- a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp +++ b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp @@ -16,36 +16,26 @@ using namespace IW3; -class ZoneWriterFactory::Impl +namespace { - Zone* m_zone; - std::unique_ptr m_writer; - -public: - explicit Impl(Zone* zone) - : m_zone(zone), - m_writer(std::make_unique()) - { - } - - void SetupBlocks() const + void SetupBlocks(ZoneWriter& writer) { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - m_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)); - m_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)); - m_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)); - m_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)); - m_writer->AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } - static ZoneHeader CreateHeaderForParams() + ZoneHeader CreateHeaderForParams() { ZoneHeader header{}; header.m_version = ZoneConstants::ZONE_VERSION; @@ -53,40 +43,30 @@ class ZoneWriterFactory::Impl return header; } +} // namespace - std::unique_ptr CreateWriter() - { - SetupBlocks(); - - auto contentInMemory = std::make_unique( - std::make_unique(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); - auto* contentInMemoryPtr = contentInMemory.get(); - m_writer->AddWritingStep(std::move(contentInMemory)); +std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const +{ + std::unique_ptr writer; - // Write zone header - m_writer->AddWritingStep(std::make_unique(CreateHeaderForParams())); + SetupBlocks(*writer); - m_writer->AddWritingStep(std::make_unique(std::make_unique())); + 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)); - // Start of the XFile struct - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); - m_writer->AddWritingStep(std::make_unique(m_zone)); + // Write zone header + writer->AddWritingStep(std::make_unique(CreateHeaderForParams())); - // Start of the zone content - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + writer->AddWritingStep(std::make_unique(std::make_unique())); - // Return the fully setup zoneloader - return std::move(m_writer); - } -}; + // Start of the XFile struct + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + writer->AddWritingStep(std::make_unique(zone)); -bool ZoneWriterFactory::SupportsZone(Zone* zone) const -{ - return zone->m_game == &g_GameIW3; -} + // Start of the zone content + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); -std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const -{ - Impl impl(zone); - return impl.CreateWriter(); + return std::move(writer); } diff --git a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.h b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.h index e0f26e1f9..1296ad464 100644 --- a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.h +++ b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.h @@ -8,10 +8,7 @@ namespace IW3 { class ZoneWriterFactory final : public IZoneWriterFactory { - class Impl; - public: - _NODISCARD bool SupportsZone(Zone* zone) const override; _NODISCARD std::unique_ptr CreateWriter(Zone* zone) const override; }; } // namespace IW3 diff --git a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp index 8dbd67549..e9371ba94 100644 --- a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp +++ b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp @@ -18,35 +18,25 @@ using namespace IW4; -class ZoneWriterFactory::Impl +namespace { - Zone* m_zone; - std::unique_ptr m_writer; - -public: - explicit Impl(Zone* zone) - : m_zone(zone), - m_writer(std::make_unique()) - { - } - - void SetupBlocks() const + void SetupBlocks(ZoneWriter& writer) { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - m_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)); - m_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)); - m_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)); - m_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_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)); #undef XBLOCK_DEF } - static ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial) + ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial) { ZoneHeader header{}; header.m_version = ZoneConstants::ZONE_VERSION; @@ -65,49 +55,39 @@ class ZoneWriterFactory::Impl return header; } +}; // namespace - std::unique_ptr CreateWriter() - { - // TODO Support signed fastfiles - bool isSecure = false; - - SetupBlocks(); +std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const +{ + auto writer = std::make_unique(); - auto contentInMemory = std::make_unique( - std::make_unique(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); - auto* contentInMemoryPtr = contentInMemory.get(); - m_writer->AddWritingStep(std::move(contentInMemory)); + // TODO Support signed fastfiles + bool isSecure = false; - // Write zone header - m_writer->AddWritingStep(std::make_unique(CreateHeaderForParams(isSecure, false))); + SetupBlocks(*writer); - // Write dummy byte that the game ignores as well. No clue what it means. - m_writer->AddWritingStep(std::make_unique(1)); + 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 timestamp - m_writer->AddWritingStep(std::make_unique()); + // Write zone header + writer->AddWritingStep(std::make_unique(CreateHeaderForParams(isSecure, false))); - m_writer->AddWritingStep(std::make_unique(std::make_unique())); + // Write dummy byte that the game ignores as well. No clue what it means. + writer->AddWritingStep(std::make_unique(1)); - // Start of the XFile struct - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); - m_writer->AddWritingStep(std::make_unique(m_zone)); + // Write timestamp + writer->AddWritingStep(std::make_unique()); - // Start of the zone content - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + writer->AddWritingStep(std::make_unique(std::make_unique())); - // Return the fully setup zoneloader - return std::move(m_writer); - } -}; + // Start of the XFile struct + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + writer->AddWritingStep(std::make_unique(zone)); -bool ZoneWriterFactory::SupportsZone(Zone* zone) const -{ - return zone->m_game == &g_GameIW4; -} + // Start of the zone content + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); -std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const -{ - Impl impl(zone); - return impl.CreateWriter(); + return std::move(writer); } diff --git a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.h b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.h index 7625668ec..0b5240b3e 100644 --- a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.h +++ b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.h @@ -8,10 +8,7 @@ namespace IW4 { class ZoneWriterFactory final : public IZoneWriterFactory { - class Impl; - public: - _NODISCARD bool SupportsZone(Zone* zone) const override; _NODISCARD std::unique_ptr CreateWriter(Zone* zone) const override; }; } // namespace IW4 diff --git a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp index 1b91a4c5b..402e46bf0 100644 --- a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp +++ b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp @@ -18,36 +18,26 @@ using namespace IW5; -class ZoneWriterFactory::Impl +namespace { - Zone* m_zone; - std::unique_ptr m_writer; - -public: - explicit Impl(Zone* zone) - : m_zone(zone), - m_writer(std::make_unique()) - { - } - - void SetupBlocks() const + void SetupBlocks(ZoneWriter& writer) { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - m_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)); - m_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)); - m_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)); - m_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)); - m_writer->AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlock::Type::BLOCK_TYPE_NORMAL)); + 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 } - static ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial) + ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial) { ZoneHeader header{}; header.m_version = ZoneConstants::ZONE_VERSION; @@ -66,49 +56,39 @@ class ZoneWriterFactory::Impl return header; } +}; // namespace - std::unique_ptr CreateWriter() - { - // TODO Support signed fastfiles - bool isSecure = false; - - SetupBlocks(); +std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const +{ + auto writer = std::make_unique(); - auto contentInMemory = std::make_unique( - std::make_unique(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); - auto* contentInMemoryPtr = contentInMemory.get(); - m_writer->AddWritingStep(std::move(contentInMemory)); + // TODO Support signed fastfiles + bool isSecure = false; - // Write zone header - m_writer->AddWritingStep(std::make_unique(CreateHeaderForParams(isSecure, false))); + SetupBlocks(*writer); - // Write dummy byte that the game ignores as well. No clue what it means. - m_writer->AddWritingStep(std::make_unique(1)); + 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 timestamp - m_writer->AddWritingStep(std::make_unique()); + // Write zone header + writer->AddWritingStep(std::make_unique(CreateHeaderForParams(isSecure, false))); - m_writer->AddWritingStep(std::make_unique(std::make_unique())); + // Write dummy byte that the game ignores as well. No clue what it means. + writer->AddWritingStep(std::make_unique(1)); - // Start of the XFile struct - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); - m_writer->AddWritingStep(std::make_unique(m_zone)); + // Write timestamp + writer->AddWritingStep(std::make_unique()); - // Start of the zone content - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + writer->AddWritingStep(std::make_unique(std::make_unique())); - // Return the fully setup zoneloader - return std::move(m_writer); - } -}; + // Start of the XFile struct + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + writer->AddWritingStep(std::make_unique(zone)); -bool ZoneWriterFactory::SupportsZone(Zone* zone) const -{ - return zone->m_game == &g_GameIW5; -} + // Start of the zone content + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); -std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const -{ - Impl impl(zone); - return impl.CreateWriter(); + return std::move(writer); } diff --git a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.h b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.h index 847dd1149..db9567787 100644 --- a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.h +++ b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.h @@ -8,10 +8,7 @@ namespace IW5 { class ZoneWriterFactory final : public IZoneWriterFactory { - class Impl; - public: - _NODISCARD bool SupportsZone(Zone* zone) const override; _NODISCARD std::unique_ptr CreateWriter(Zone* zone) const override; }; } // namespace IW5 diff --git a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp index 7fe341440..d3a03a337 100644 --- a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp +++ b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp @@ -16,34 +16,24 @@ using namespace T5; -class ZoneWriterFactory::Impl +namespace { - Zone* m_zone; - std::unique_ptr m_writer; - -public: - explicit Impl(Zone* zone) - : m_zone(zone), - m_writer(std::make_unique()) - { - } - - void SetupBlocks() const + void SetupBlocks(ZoneWriter& writer) { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - m_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)); - m_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)); - m_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)); - m_writer->AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } - static ZoneHeader CreateHeaderForParams() + ZoneHeader CreateHeaderForParams() { ZoneHeader header{}; header.m_version = ZoneConstants::ZONE_VERSION; @@ -51,40 +41,30 @@ class ZoneWriterFactory::Impl return header; } +} // namespace - std::unique_ptr CreateWriter() - { - SetupBlocks(); - - auto contentInMemory = std::make_unique( - std::make_unique(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); - auto* contentInMemoryPtr = contentInMemory.get(); - m_writer->AddWritingStep(std::move(contentInMemory)); +std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const +{ + auto writer = std::make_unique(); - // Write zone header - m_writer->AddWritingStep(std::make_unique(CreateHeaderForParams())); + SetupBlocks(*writer); - m_writer->AddWritingStep(std::make_unique(std::make_unique())); + 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)); - // Start of the XFile struct - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); - m_writer->AddWritingStep(std::make_unique(m_zone)); + // Write zone header + writer->AddWritingStep(std::make_unique(CreateHeaderForParams())); - // Start of the zone content - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + writer->AddWritingStep(std::make_unique(std::make_unique())); - // Return the fully setup zoneloader - return std::move(m_writer); - } -}; + // Start of the XFile struct + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + writer->AddWritingStep(std::make_unique(zone)); -bool ZoneWriterFactory::SupportsZone(Zone* zone) const -{ - return zone->m_game == &g_GameT5; -} + // Start of the zone content + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); -std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const -{ - Impl impl(zone); - return impl.CreateWriter(); + return std::move(writer); } diff --git a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.h b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.h index 6a6fa5a7a..f993903bf 100644 --- a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.h +++ b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.h @@ -11,7 +11,6 @@ namespace T5 class Impl; public: - _NODISCARD bool SupportsZone(Zone* zone) const override; _NODISCARD std::unique_ptr CreateWriter(Zone* zone) const override; }; } // namespace T5 diff --git a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp index 20f24c0c3..4baede1fd 100644 --- a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp +++ b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp @@ -23,35 +23,25 @@ using namespace T6; -class ZoneWriterFactory::Impl +namespace { - Zone* m_zone; - std::unique_ptr m_writer; - -public: - explicit Impl(Zone* zone) - : m_zone(zone), - m_writer(std::make_unique()) - { - } - - void SetupBlocks() const + void SetupBlocks(ZoneWriter& writer) { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - m_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)); - m_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)); - m_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)); - m_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_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlock::Type::BLOCK_TYPE_DELAY)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlock::Type::BLOCK_TYPE_DELAY)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlock::Type::BLOCK_TYPE_NORMAL)); #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{}; header.m_version = ZoneConstants::ZONE_VERSION; @@ -74,7 +64,11 @@ class ZoneWriterFactory::Impl 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( ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::XCHUNK_MAX_WRITE_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE); @@ -88,7 +82,7 @@ class ZoneWriterFactory::Impl { // If zone is encrypted, the decryption is applied before the decompression. T6 Zones always use Salsa20. auto chunkProcessorSalsa20 = std::make_unique( - 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 (dataToSignProviderPtr) @@ -97,58 +91,48 @@ class ZoneWriterFactory::Impl xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20)); } - m_writer->AddWritingStep(std::make_unique(std::move(xChunkProcessor))); + writer.AddWritingStep(std::make_unique(std::move(xChunkProcessor))); } +}; // namespace - std::unique_ptr CreateWriter() - { - // TODO Support signed fastfiles - bool isSecure = false; - bool isEncrypted = true; - - SetupBlocks(); +std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const +{ + auto writer = std::make_unique(); - auto contentInMemory = std::make_unique( - std::make_unique(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); - auto* contentInMemoryPtr = contentInMemory.get(); - m_writer->AddWritingStep(std::move(contentInMemory)); + // TODO Support signed fastfiles + bool isSecure = false; + bool isEncrypted = true; - // Write zone header - m_writer->AddWritingStep(std::make_unique(CreateHeaderForParams(isSecure, false, isEncrypted))); + SetupBlocks(*writer); - // Setup loading XChunks from the zone from this point on. - ICapturedDataProvider* dataToSignProvider; - OutputProcessorXChunks* xChunksProcessor; - AddXChunkProcessor(isEncrypted, &dataToSignProvider, &xChunksProcessor); + 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)); - // Start of the XFile struct - // m_writer->AddWritingStep(std::make_unique(8)); // Skip size and externalSize fields since they are not interesting for us - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); - m_writer->AddWritingStep(std::make_unique(m_zone)); + // Write zone header + writer->AddWritingStep(std::make_unique(CreateHeaderForParams(isSecure, false, isEncrypted))); - // Start of the zone content - m_writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + // Setup loading XChunks from the zone from this point on. + ICapturedDataProvider* dataToSignProvider; + OutputProcessorXChunks* xChunksProcessor; + AddXChunkProcessor(*writer, *zone, isEncrypted, &dataToSignProvider, &xChunksProcessor); - // Stop writing in XChunks - m_writer->AddWritingStep(std::make_unique(xChunksProcessor)); + // Start of the XFile struct + // m_writer->AddWritingStep(std::make_unique(8)); // Skip size and externalSize fields since they are not interesting for us + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); + writer->AddWritingStep(std::make_unique(zone)); - // 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(ZoneConstants::FILE_SUFFIX_ZERO_MIN_SIZE)); - m_writer->AddWritingStep(std::make_unique(ZoneConstants::FILE_SUFFIX_ZERO_ALIGN, '\0')); + // Start of the zone content + writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); - // Return the fully setup zoneloader - return std::move(m_writer); - } -}; + // Stop writing in XChunks + writer->AddWritingStep(std::make_unique(xChunksProcessor)); -bool ZoneWriterFactory::SupportsZone(Zone* zone) const -{ - return zone->m_game == &g_GameT6; -} + // 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(ZoneConstants::FILE_SUFFIX_ZERO_MIN_SIZE)); + writer->AddWritingStep(std::make_unique(ZoneConstants::FILE_SUFFIX_ZERO_ALIGN, '\0')); -std::unique_ptr ZoneWriterFactory::CreateWriter(Zone* zone) const -{ - Impl impl(zone); - return impl.CreateWriter(); + return std::move(writer); } diff --git a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.h b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.h index 7f9c6cd5f..895bf82e2 100644 --- a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.h +++ b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.h @@ -11,7 +11,6 @@ namespace T6 class Impl; public: - _NODISCARD bool SupportsZone(Zone* zone) const override; _NODISCARD std::unique_ptr CreateWriter(Zone* zone) const override; }; } // namespace T6 diff --git a/src/ZoneWriting/Writing/IZoneWriterFactory.cpp b/src/ZoneWriting/Writing/IZoneWriterFactory.cpp new file mode 100644 index 000000000..193c4c845 --- /dev/null +++ b/src/ZoneWriting/Writing/IZoneWriterFactory.cpp @@ -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 + +const IZoneWriterFactory* IZoneWriterFactory::GetZoneWriterFactoryForGame(GameId game) +{ + static const IZoneWriterFactory* zoneCreators[static_cast(GameId::COUNT)]{ + new IW3::ZoneWriterFactory(), + new IW4::ZoneWriterFactory(), + new IW5::ZoneWriterFactory(), + new T5::ZoneWriterFactory(), + new T6::ZoneWriterFactory(), + }; + static_assert(std::extent_v == static_cast(GameId::COUNT)); + + assert(static_cast(game) < static_cast(GameId::COUNT)); + const auto* result = zoneCreators[static_cast(game)]; + assert(result); + + return result; +} diff --git a/src/ZoneWriting/Writing/IZoneWriterFactory.h b/src/ZoneWriting/Writing/IZoneWriterFactory.h index 84a1d484f..12f97b34e 100644 --- a/src/ZoneWriting/Writing/IZoneWriterFactory.h +++ b/src/ZoneWriting/Writing/IZoneWriterFactory.h @@ -14,6 +14,7 @@ class IZoneWriterFactory IZoneWriterFactory& operator=(const IZoneWriterFactory& other) = default; IZoneWriterFactory& operator=(IZoneWriterFactory&& other) noexcept = default; - _NODISCARD virtual bool SupportsZone(Zone* zone) const = 0; _NODISCARD virtual std::unique_ptr CreateWriter(Zone* zone) const = 0; + + static const IZoneWriterFactory* GetZoneWriterFactoryForGame(GameId game); }; diff --git a/src/ZoneWriting/ZoneWriting.cpp b/src/ZoneWriting/ZoneWriting.cpp index 48c534075..7b04f431e 100644 --- a/src/ZoneWriting/ZoneWriting.cpp +++ b/src/ZoneWriting/ZoneWriting.cpp @@ -1,38 +1,18 @@ #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 #include #include -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) { const auto start = std::chrono::high_resolution_clock::now(); - std::unique_ptr zoneWriter; - for (auto* factory : ZoneWriterFactories) - { - if (factory->SupportsZone(zone)) - { - zoneWriter = factory->CreateWriter(zone); - break; - } - } + const auto factory = IZoneWriterFactory::GetZoneWriterFactoryForGame(zone->m_game->GetId()); + const auto zoneWriter = factory->CreateWriter(zone); if (zoneWriter == nullptr) { std::cerr << std::format("Could not create ZoneWriter for zone \"{}\".\n", zone->m_name);