From 14666ed9441a4f08b10edf006ed64d3cffabe0b3 Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 9 Sep 2020 18:40:01 +0200 Subject: [PATCH] Dump a few iw4 assets --- .../Dumping/Localize/LocalizeCommon.cpp | 69 +++++++ .../Dumping/Localize/LocalizeCommon.h | 11 ++ .../IW4/AssetDumpers/AssetDumperGfxImage.cpp | 47 +++++ .../IW4/AssetDumpers/AssetDumperGfxImage.h | 27 +++ .../AssetDumpers/AssetDumperLocalizeEntry.cpp | 44 +++++ .../AssetDumpers/AssetDumperLocalizeEntry.h | 13 ++ .../IW4/AssetDumpers/AssetDumperRawFile.cpp | 63 +++++++ .../IW4/AssetDumpers/AssetDumperRawFile.h | 15 ++ .../AssetDumpers/AssetDumperStringTable.cpp | 31 ++++ .../IW4/AssetDumpers/AssetDumperStringTable.h | 15 ++ src/ObjWriting/Game/IW4/ZoneDumperIW4.cpp | 69 +++++++ src/ObjWriting/Game/IW4/ZoneDumperIW4.h | 12 ++ .../T6/AssetDumpers/AssetDumperFontIcon.h | 15 +- .../T6/AssetDumpers/AssetDumperGfxImage.cpp | 4 +- .../T6/AssetDumpers/AssetDumperGfxImage.h | 31 ++-- .../AssetDumpers/AssetDumperLocalizeEntry.cpp | 60 +----- .../AssetDumpers/AssetDumperLocalizeEntry.h | 14 +- .../Game/T6/AssetDumpers/AssetDumperQdb.h | 15 +- .../Game/T6/AssetDumpers/AssetDumperRawFile.h | 15 +- .../AssetDumpers/AssetDumperScriptParseTree.h | 15 +- .../Game/T6/AssetDumpers/AssetDumperSlug.h | 15 +- .../T6/AssetDumpers/AssetDumperStringTable.h | 15 +- src/ObjWriting/Game/T6/ZoneDumperT6.cpp | 8 +- src/ObjWriting/Game/T6/ZoneDumperT6.h | 13 +- src/ObjWriting/Image/IwiWriter8.cpp | 0 src/ObjWriting/Image/IwiWriter8.h | 30 +++ src/ObjWriting/ObjWriting.cpp | 4 +- src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp | 70 +++++++ src/Unlinker/Game/IW4/ZoneDefWriterIW4.h | 13 ++ src/Unlinker/Game/T6/ZoneDefWriterT6.cpp | 173 +++++++++--------- src/Unlinker/Game/T6/ZoneDefWriterT6.h | 13 +- src/Unlinker/Unlinker.cpp | 15 +- 32 files changed, 734 insertions(+), 220 deletions(-) create mode 100644 src/ObjWriting/Dumping/Localize/LocalizeCommon.cpp create mode 100644 src/ObjWriting/Dumping/Localize/LocalizeCommon.h create mode 100644 src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp create mode 100644 src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h create mode 100644 src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp create mode 100644 src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.h create mode 100644 src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp create mode 100644 src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h create mode 100644 src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp create mode 100644 src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h create mode 100644 src/ObjWriting/Game/IW4/ZoneDumperIW4.cpp create mode 100644 src/ObjWriting/Game/IW4/ZoneDumperIW4.h create mode 100644 src/ObjWriting/Image/IwiWriter8.cpp create mode 100644 src/ObjWriting/Image/IwiWriter8.h create mode 100644 src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp create mode 100644 src/Unlinker/Game/IW4/ZoneDefWriterIW4.h diff --git a/src/ObjWriting/Dumping/Localize/LocalizeCommon.cpp b/src/ObjWriting/Dumping/Localize/LocalizeCommon.cpp new file mode 100644 index 00000000..025cbc93 --- /dev/null +++ b/src/ObjWriting/Dumping/Localize/LocalizeCommon.cpp @@ -0,0 +1,69 @@ +#include "LocalizeCommon.h" + +std::string LocalizeCommon::GetNameOfLanguage(GameLanguage language) +{ + switch (language) + { + case GameLanguage::LANGUAGE_NONE: + case GameLanguage::LANGUAGE_ENGLISH: + default: + return "english"; + + case GameLanguage::LANGUAGE_FRENCH: + return "french"; + + case GameLanguage::LANGUAGE_GERMAN: + return "german"; + + case GameLanguage::LANGUAGE_ITALIAN: + return "italian"; + + case GameLanguage::LANGUAGE_SPANISH: + return "spanish"; + + case GameLanguage::LANGUAGE_BRITISH: + return "british"; + + case GameLanguage::LANGUAGE_RUSSIAN: + return "russian"; + + case GameLanguage::LANGUAGE_POLISH: + return "polish"; + + case GameLanguage::LANGUAGE_KOREAN: + return "korean"; + + case GameLanguage::LANGUAGE_JAPANESE: + return "japanese"; + + case GameLanguage::LANGUAGE_CZECH: + return "czech"; + + case GameLanguage::LANGUAGE_FRENCH_CAN: + return "frenchcan"; + + case GameLanguage::LANGUAGE_AUSTRIAN: + return "austrian"; + + case GameLanguage::LANGUAGE_PORTUGUESE: + return "portuguese"; + + case GameLanguage::LANGUAGE_MEXICAN_SPANISH: + return "mexicanspanish"; + + case GameLanguage::LANGUAGE_FULL_JAPANESE: + return "fulljapanese"; + + case GameLanguage::LANGUAGE_TAIWANESE: + return "taiwanese"; + + case GameLanguage::LANGUAGE_CHINESE: + return "chinese"; + + case GameLanguage::LANGUAGE_THAI: + return "thai"; + + case GameLanguage::LANGUAGE_LEET: + return "leet"; + } +} diff --git a/src/ObjWriting/Dumping/Localize/LocalizeCommon.h b/src/ObjWriting/Dumping/Localize/LocalizeCommon.h new file mode 100644 index 00000000..d5ee88fd --- /dev/null +++ b/src/ObjWriting/Dumping/Localize/LocalizeCommon.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include "Game/GameLanguage.h" + +class LocalizeCommon +{ +public: + static std::string GetNameOfLanguage(GameLanguage language); +}; diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp new file mode 100644 index 00000000..74ea1d94 --- /dev/null +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp @@ -0,0 +1,47 @@ +#include "AssetDumperGfxImage.h" + +#include + +#include "ObjWriting.h" +#include "Image/IwiWriter27.h" +#include "Image/DdsWriter.h" + +using namespace IW4; + +AssetDumperGfxImage::AssetDumperGfxImage() +{ + switch (ObjWriting::Configuration.ImageOutputFormat) + { + case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: + m_writer = new DdsWriter(); + break; + case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: + m_writer = new IwiWriter27(); + break; + default: + assert(false); + m_writer = nullptr; + break; + } +} + +AssetDumperGfxImage::~AssetDumperGfxImage() +{ + delete m_writer; + m_writer = nullptr; +} + +bool AssetDumperGfxImage::ShouldDump(GfxImage* asset) +{ + return asset->cardMemory.platform[0] > 0; +} + +std::string AssetDumperGfxImage::GetFileNameForAsset(Zone* zone, GfxImage* asset) +{ + return "images/" + std::string(asset->name) + m_writer->GetFileExtension(); +} + +void AssetDumperGfxImage::DumpAsset(Zone* zone, GfxImage* asset, FileAPI::File* out) +{ + m_writer->DumpImage(out, asset->texture.texture); +} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h new file mode 100644 index 00000000..082d4476 --- /dev/null +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" +#include "Image/IImageWriter.h" + +namespace IW4 +{ + class AssetDumperGfxImage final : public AbstractAssetDumper + { + IImageWriter* m_writer; + + protected: + bool ShouldDump(IW4::GfxImage* asset) override; + std::string GetFileNameForAsset(Zone* zone, IW4::GfxImage* asset) override; + void DumpAsset(Zone* zone, IW4::GfxImage* asset, FileAPI::File* out) override; + + public: + AssetDumperGfxImage(); + ~AssetDumperGfxImage(); + + AssetDumperGfxImage(const AssetDumperGfxImage& other) = delete; + AssetDumperGfxImage(AssetDumperGfxImage&& other) noexcept = delete; + AssetDumperGfxImage& operator=(const AssetDumperGfxImage& other) = delete; + AssetDumperGfxImage& operator=(AssetDumperGfxImage&& other) noexcept = delete; + }; +} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp new file mode 100644 index 00000000..fe98a9f9 --- /dev/null +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp @@ -0,0 +1,44 @@ +#include "AssetDumperLocalizeEntry.h" + +#include "Dumping/Localize/LocalizeCommon.h" +#include "Dumping/Localize/StringFileDumper.h" + +using namespace IW4; + +void AssetDumperLocalizeEntry::DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) +{ + if (pool->m_asset_lookup.empty()) + return; + + const std::string language = LocalizeCommon::GetNameOfLanguage(zone->m_language); + const std::string stringsPath = utils::Path::Combine(basePath, language + "/localizedstrings"); + + FileAPI::DirectoryCreate(stringsPath); + + FileAPI::File stringFile = FileAPI::Open(utils::Path::Combine(stringsPath, zone->m_name + ".str"), FileAPI::Mode::MODE_WRITE); + + if (stringFile.IsOpen()) + { + StringFileDumper stringFileDumper(zone, &stringFile); + + stringFileDumper.SetLanguageName(language); + + // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. + stringFileDumper.SetConfigFile(R"(C:\trees\cod3\cod3\bin\StringEd.cfg)"); + + stringFileDumper.SetNotes(""); + + for (auto localizeEntry : *pool) + { + stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); + } + + stringFileDumper.Finalize(); + + stringFile.Close(); + } + else + { + printf("Could not create string file for dumping localized strings of zone '%s'\n", zone->m_name.c_str()); + } +} \ No newline at end of file diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.h new file mode 100644 index 00000000..5355f354 --- /dev/null +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace IW4 +{ + class AssetDumperLocalizeEntry final : public IAssetDumper + { + public: + void DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) override; + }; +} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp new file mode 100644 index 00000000..0e4b927c --- /dev/null +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp @@ -0,0 +1,63 @@ +#include "AssetDumperRawFile.h" + +#include + +using namespace IW4; + +bool AssetDumperRawFile::ShouldDump(RawFile* asset) +{ + return true; +} + +std::string AssetDumperRawFile::GetFileNameForAsset(Zone* zone, RawFile* asset) +{ + return std::string(asset->name); +} + +void AssetDumperRawFile::DumpAsset(Zone* zone, RawFile* asset, FileAPI::File* out) +{ + if (asset->compressedLen > 0) + { + z_stream_s zs{}; + + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = 0; + zs.next_in = Z_NULL; + + int ret = inflateInit(&zs); + + if (ret != Z_OK) + { + throw std::exception("Initializing inflate failed"); + } + + zs.next_in = reinterpret_cast(asset->data.compressedBuffer); + zs.avail_in = asset->compressedLen; + + Bytef buffer[0x1000]; + + while(zs.avail_in > 0) + { + zs.next_out = buffer; + zs.avail_out = sizeof buffer; + ret = inflate(&zs, Z_SYNC_FLUSH); + + if (ret < 0) + { + printf("Inflate failed for dumping rawfile '%s'\n", asset->name); + inflateEnd(&zs); + return; + } + + out->Write(buffer, 1, sizeof buffer - zs.avail_out); + } + + inflateEnd(&zs); + } + else if (asset->len > 0) + { + out->Write(asset->data.buffer, 1, asset->len); + } +} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h new file mode 100644 index 00000000..1216321e --- /dev/null +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace IW4 +{ + class AssetDumperRawFile final : public AbstractAssetDumper + { + protected: + bool ShouldDump(RawFile* asset) override; + std::string GetFileNameForAsset(Zone* zone, RawFile* asset) override; + void DumpAsset(Zone* zone, RawFile* asset, FileAPI::File* out) override; + }; +} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp new file mode 100644 index 00000000..72097ce6 --- /dev/null +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp @@ -0,0 +1,31 @@ +#include "AssetDumperStringTable.h" + +#include "Dumping/CsvWriter.h" + +using namespace IW4; + +bool AssetDumperStringTable::ShouldDump(StringTable* asset) +{ + return true; +} + +std::string AssetDumperStringTable::GetFileNameForAsset(Zone* zone, StringTable* asset) +{ + return std::string(asset->name); +} + +void AssetDumperStringTable::DumpAsset(Zone* zone, StringTable* asset, FileAPI::File* out) +{ + CsvWriter csv(out); + + for (int row = 0; row < asset->rowCount; row++) + { + for (int column = 0; column < asset->columnCount; column++) + { + const auto* cell = &asset->values[column + row * asset->columnCount]; + csv.WriteColumn(cell->string); + } + + csv.NextRow(); + } +} \ No newline at end of file diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h new file mode 100644 index 00000000..7c48f647 --- /dev/null +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace IW4 +{ + class AssetDumperStringTable final : public AbstractAssetDumper + { + protected: + bool ShouldDump(IW4::StringTable* asset) override; + std::string GetFileNameForAsset(Zone* zone, IW4::StringTable* asset) override; + void DumpAsset(Zone* zone, IW4::StringTable* asset, FileAPI::File* out) override; + }; +} diff --git a/src/ObjWriting/Game/IW4/ZoneDumperIW4.cpp b/src/ObjWriting/Game/IW4/ZoneDumperIW4.cpp new file mode 100644 index 00000000..acf6927b --- /dev/null +++ b/src/ObjWriting/Game/IW4/ZoneDumperIW4.cpp @@ -0,0 +1,69 @@ +#include "ZoneDumperIW4.h" + +#include "Game/IW4/GameIW4.h" +#include "Game/IW4/GameAssetPoolIW4.h" + +#include "AssetDumpers/AssetDumperRawFile.h" +#include "AssetDumpers/AssetDumperStringTable.h" +#include "AssetDumpers/AssetDumperLocalizeEntry.h" +#include "AssetDumpers/AssetDumperGfxImage.h" + +using namespace IW4; + +bool ZoneDumper::CanHandleZone(Zone* zone) const +{ + return zone->m_game == &g_GameIW4; +} + +bool ZoneDumper::DumpZone(Zone* zone, const std::string& basePath) const +{ +#define DUMP_ASSET_POOL(dumperType, poolName) \ + if(assetPools->poolName) \ + { \ + dumperType dumper; \ + dumper.DumpPool(zone, assetPools->poolName.get(), basePath); \ + } + + const auto* assetPools = dynamic_cast(zone->GetPools()); + + // DUMP_ASSET_POOL(AssetDumperPhysPreset, m_phys_preset); + // DUMP_ASSET_POOL(AssetDumperPhysCollmap, m_phys_collmap); + // DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts); + // DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel); + // DUMP_ASSET_POOL(AssetDumperMaterial, m_material); + // DUMP_ASSET_POOL(AssetDumperMaterialPixelShader, m_material_pixel_shader); + // DUMP_ASSET_POOL(AssetDumperMaterialVertexShader, m_material_vertex_shader); + // DUMP_ASSET_POOL(AssetDumperMaterialVertexDeclaration, m_material_vertex_decl); + // DUMP_ASSET_POOL(AssetDumperMaterialTechniqueSet, m_technique_set); + // DUMP_ASSET_POOL(AssetDumperGfxImage, m_image); + // DUMP_ASSET_POOL(AssetDumpersnd_alias_list_t, m_sound); + // DUMP_ASSET_POOL(AssetDumperSndCurve, m_sound_curve); + // DUMP_ASSET_POOL(AssetDumperLoadedSound, m_loaded_sound); + // DUMP_ASSET_POOL(AssetDumperclipMap_t, m_clip_map); + // DUMP_ASSET_POOL(AssetDumperComWorld, m_com_world); + // DUMP_ASSET_POOL(AssetDumperGameWorldSp, m_game_world_sp); + // DUMP_ASSET_POOL(AssetDumperGameWorldMp, m_game_world_mp); + // DUMP_ASSET_POOL(AssetDumperMapEnts, m_map_ents); + // DUMP_ASSET_POOL(AssetDumperFxWorld, m_fx_world); + // DUMP_ASSET_POOL(AssetDumperGfxWorld, m_gfx_world); + // DUMP_ASSET_POOL(AssetDumperGfxLightDef, m_gfx_light_def); + // DUMP_ASSET_POOL(AssetDumperFont_s, m_font); + // DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list); + // DUMP_ASSET_POOL(AssetDumpermenuDef_t, m_menu_def); + DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize); + // DUMP_ASSET_POOL(AssetDumperWeaponCompleteDef, m_weapon); + // DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals); + // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx); + // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table); + DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file); + DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table); + // DUMP_ASSET_POOL(AssetDumperLeaderboardDef, m_leaderboard); + // DUMP_ASSET_POOL(AssetDumperStructuredDataDefSet, m_structed_data_def_set); + // DUMP_ASSET_POOL(AssetDumperTracerDef, m_tracer); + // DUMP_ASSET_POOL(AssetDumperVehicleDef, m_vehicle); + // DUMP_ASSET_POOL(AssetDumperAddonMapEnts, m_addon_map_ents); + + return true; + +#undef DUMP_ASSET_POOL +} diff --git a/src/ObjWriting/Game/IW4/ZoneDumperIW4.h b/src/ObjWriting/Game/IW4/ZoneDumperIW4.h new file mode 100644 index 00000000..82865a13 --- /dev/null +++ b/src/ObjWriting/Game/IW4/ZoneDumperIW4.h @@ -0,0 +1,12 @@ +#pragma once +#include "Dumping/IZoneDumper.h" + +namespace IW4 +{ + class ZoneDumper final : public IZoneDumper + { + public: + bool CanHandleZone(Zone* zone) const override; + bool DumpZone(Zone* zone, const std::string& basePath) const override; + }; +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.h index f2402dfc..2d52a42f 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.h @@ -3,10 +3,13 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/T6/T6.h" -class AssetDumperFontIcon final : public AbstractAssetDumper +namespace T6 { -protected: - bool ShouldDump(T6::FontIcon* asset) override; - std::string GetFileNameForAsset(Zone* zone, T6::FontIcon* asset) override; - void DumpAsset(Zone* zone, T6::FontIcon* asset, FileAPI::File* out) override; -}; \ No newline at end of file + class AssetDumperFontIcon final : public AbstractAssetDumper + { + protected: + bool ShouldDump(T6::FontIcon* asset) override; + std::string GetFileNameForAsset(Zone* zone, T6::FontIcon* asset) override; + void DumpAsset(Zone* zone, T6::FontIcon* asset, FileAPI::File* out) override; + }; +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp index c7119ad7..351d8021 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp @@ -1,8 +1,10 @@ #include "AssetDumperGfxImage.h" + +#include + #include "ObjWriting.h" #include "Image/IwiWriter27.h" #include "Image/DdsWriter.h" -#include using namespace T6; diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h index cec25771..c597051d 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h @@ -4,21 +4,24 @@ #include "Game/T6/T6.h" #include "Image/IImageWriter.h" -class AssetDumperGfxImage final : public AbstractAssetDumper +namespace T6 { - IImageWriter* m_writer; + class AssetDumperGfxImage final : public AbstractAssetDumper + { + IImageWriter* m_writer; -protected: - bool ShouldDump(T6::GfxImage* asset) override; - std::string GetFileNameForAsset(Zone* zone, T6::GfxImage* asset) override; - void DumpAsset(Zone* zone, T6::GfxImage* asset, FileAPI::File* out) override; + protected: + bool ShouldDump(T6::GfxImage* asset) override; + std::string GetFileNameForAsset(Zone* zone, T6::GfxImage* asset) override; + void DumpAsset(Zone* zone, T6::GfxImage* asset, FileAPI::File* out) override; -public: - AssetDumperGfxImage(); - ~AssetDumperGfxImage(); + public: + AssetDumperGfxImage(); + ~AssetDumperGfxImage(); - AssetDumperGfxImage(const AssetDumperGfxImage& other) = delete; - AssetDumperGfxImage(AssetDumperGfxImage&& other) noexcept = delete; - AssetDumperGfxImage& operator=(const AssetDumperGfxImage& other) = delete; - AssetDumperGfxImage& operator=(AssetDumperGfxImage&& other) noexcept = delete; -}; \ No newline at end of file + AssetDumperGfxImage(const AssetDumperGfxImage& other) = delete; + AssetDumperGfxImage(AssetDumperGfxImage&& other) noexcept = delete; + AssetDumperGfxImage& operator=(const AssetDumperGfxImage& other) = delete; + AssetDumperGfxImage& operator=(AssetDumperGfxImage&& other) noexcept = delete; + }; +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp index 353bef5f..7e9e7b51 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp @@ -1,70 +1,16 @@ #include "AssetDumperLocalizeEntry.h" + +#include "Dumping/Localize/LocalizeCommon.h" #include "Dumping/Localize/StringFileDumper.h" using namespace T6; -std::string AssetDumperLocalizeEntry::GetNameOfLanguage(GameLanguage language) -{ - switch(language) - { - case GameLanguage::LANGUAGE_NONE: - case GameLanguage::LANGUAGE_ENGLISH: - default: - return "english"; - - case GameLanguage::LANGUAGE_FRENCH: - return "french"; - - case GameLanguage::LANGUAGE_GERMAN: - return "german"; - - case GameLanguage::LANGUAGE_ITALIAN: - return "italian"; - - case GameLanguage::LANGUAGE_SPANISH: - return "spanish"; - - case GameLanguage::LANGUAGE_BRITISH: - return "british"; - - case GameLanguage::LANGUAGE_RUSSIAN: - return "russian"; - - case GameLanguage::LANGUAGE_POLISH: - return "polish"; - - case GameLanguage::LANGUAGE_KOREAN: - return "korean"; - - case GameLanguage::LANGUAGE_JAPANESE: - return "japanese"; - - case GameLanguage::LANGUAGE_CZECH: - return "czech"; - - case GameLanguage::LANGUAGE_FRENCH_CAN: - return "frenchcan"; - - case GameLanguage::LANGUAGE_AUSTRIAN: - return "austrian"; - - case GameLanguage::LANGUAGE_PORTUGUESE: - return "portuguese"; - - case GameLanguage::LANGUAGE_MEXICAN_SPANISH: - return "mexicanspanish"; - - case GameLanguage::LANGUAGE_FULL_JAPANESE: - return "fulljapanese"; - } -} - void AssetDumperLocalizeEntry::DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) { if (pool->m_asset_lookup.empty()) return; - const std::string language = GetNameOfLanguage(zone->m_language); + const std::string language = LocalizeCommon::GetNameOfLanguage(zone->m_language); const std::string stringsPath = utils::Path::Combine(basePath, language + "/localizedstrings"); FileAPI::DirectoryCreate(stringsPath); diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h index 49c7e1e1..ffb2d6e3 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h @@ -2,12 +2,12 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/T6/T6.h" -#include "Game/GameLanguage.h" -class AssetDumperLocalizeEntry final : public IAssetDumper +namespace T6 { - static std::string GetNameOfLanguage(GameLanguage language); - -public: - void DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) override; -}; \ No newline at end of file + class AssetDumperLocalizeEntry final : public IAssetDumper + { + public: + void DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) override; + }; +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h index 5ae6a2c1..e71e50d2 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h @@ -3,10 +3,13 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/T6/T6.h" -class AssetDumperQdb final : public AbstractAssetDumper +namespace T6 { -protected: - bool ShouldDump(T6::Qdb* asset) override; - std::string GetFileNameForAsset(Zone* zone, T6::Qdb* asset) override; - void DumpAsset(Zone* zone, T6::Qdb* asset, FileAPI::File* out) override; -}; \ No newline at end of file + class AssetDumperQdb final : public AbstractAssetDumper + { + protected: + bool ShouldDump(T6::Qdb* asset) override; + std::string GetFileNameForAsset(Zone* zone, T6::Qdb* asset) override; + void DumpAsset(Zone* zone, T6::Qdb* asset, FileAPI::File* out) override; + }; +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h index cc72e68f..4529d026 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h @@ -3,10 +3,13 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/T6/T6.h" -class AssetDumperRawFile final : public AbstractAssetDumper +namespace T6 { -protected: - bool ShouldDump(T6::RawFile* asset) override; - std::string GetFileNameForAsset(Zone* zone, T6::RawFile* asset) override; - void DumpAsset(Zone* zone, T6::RawFile* asset, FileAPI::File* out) override; -}; \ No newline at end of file + class AssetDumperRawFile final : public AbstractAssetDumper + { + protected: + bool ShouldDump(T6::RawFile* asset) override; + std::string GetFileNameForAsset(Zone* zone, T6::RawFile* asset) override; + void DumpAsset(Zone* zone, T6::RawFile* asset, FileAPI::File* out) override; + }; +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h index 65b75f93..874df319 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h @@ -3,10 +3,13 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/T6/T6.h" -class AssetDumperScriptParseTree final : public AbstractAssetDumper +namespace T6 { -protected: - bool ShouldDump(T6::ScriptParseTree* asset) override; - std::string GetFileNameForAsset(Zone* zone, T6::ScriptParseTree* asset) override; - void DumpAsset(Zone* zone, T6::ScriptParseTree* asset, FileAPI::File* out) override; -}; \ No newline at end of file + class AssetDumperScriptParseTree final : public AbstractAssetDumper + { + protected: + bool ShouldDump(T6::ScriptParseTree* asset) override; + std::string GetFileNameForAsset(Zone* zone, T6::ScriptParseTree* asset) override; + void DumpAsset(Zone* zone, T6::ScriptParseTree* asset, FileAPI::File* out) override; + }; +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h index 70eedbfd..f6a91bf6 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h @@ -3,10 +3,13 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/T6/T6.h" -class AssetDumperSlug final : public AbstractAssetDumper +namespace T6 { -protected: - bool ShouldDump(T6::Slug* asset) override; - std::string GetFileNameForAsset(Zone* zone, T6::Slug* asset) override; - void DumpAsset(Zone* zone, T6::Slug* asset, FileAPI::File* out) override; -}; \ No newline at end of file + class AssetDumperSlug final : public AbstractAssetDumper + { + protected: + bool ShouldDump(T6::Slug* asset) override; + std::string GetFileNameForAsset(Zone* zone, T6::Slug* asset) override; + void DumpAsset(Zone* zone, T6::Slug* asset, FileAPI::File* out) override; + }; +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h index 0a0ed007..75040694 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h @@ -3,10 +3,13 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/T6/T6.h" -class AssetDumperStringTable final : public AbstractAssetDumper +namespace T6 { -protected: - bool ShouldDump(T6::StringTable* asset) override; - std::string GetFileNameForAsset(Zone* zone, T6::StringTable* asset) override; - void DumpAsset(Zone* zone, T6::StringTable* asset, FileAPI::File* out) override; -}; \ No newline at end of file + class AssetDumperStringTable final : public AbstractAssetDumper + { + protected: + bool ShouldDump(T6::StringTable* asset) override; + std::string GetFileNameForAsset(Zone* zone, T6::StringTable* asset) override; + void DumpAsset(Zone* zone, T6::StringTable* asset, FileAPI::File* out) override; + }; +} diff --git a/src/ObjWriting/Game/T6/ZoneDumperT6.cpp b/src/ObjWriting/Game/T6/ZoneDumperT6.cpp index 8dd7de35..8c03b2d0 100644 --- a/src/ObjWriting/Game/T6/ZoneDumperT6.cpp +++ b/src/ObjWriting/Game/T6/ZoneDumperT6.cpp @@ -12,12 +12,14 @@ #include "AssetDumpers/AssetDumperGfxImage.h" #include "AssetDumpers/AssetDumperFontIcon.h" -bool ZoneDumperT6::CanHandleZone(Zone* zone) const +using namespace T6; + +bool ZoneDumper::CanHandleZone(Zone* zone) const { return zone->m_game == &g_GameT6; } -bool ZoneDumperT6::DumpZone(Zone* zone, const std::string& basePath) const +bool ZoneDumper::DumpZone(Zone* zone, const std::string& basePath) const { #define DUMP_ASSET_POOL(dumperType, poolName) \ if(assetPools->poolName) \ @@ -80,4 +82,4 @@ bool ZoneDumperT6::DumpZone(Zone* zone, const std::string& basePath) const return true; #undef DUMP_ASSET_POOL -} \ No newline at end of file +} diff --git a/src/ObjWriting/Game/T6/ZoneDumperT6.h b/src/ObjWriting/Game/T6/ZoneDumperT6.h index 0d5205be..7625646d 100644 --- a/src/ObjWriting/Game/T6/ZoneDumperT6.h +++ b/src/ObjWriting/Game/T6/ZoneDumperT6.h @@ -1,9 +1,12 @@ #pragma once #include "Dumping/IZoneDumper.h" -class ZoneDumperT6 final : public IZoneDumper +namespace T6 { -public: - bool CanHandleZone(Zone* zone) const override; - bool DumpZone(Zone* zone, const std::string& basePath) const override; -}; + class ZoneDumper final : public IZoneDumper + { + public: + bool CanHandleZone(Zone* zone) const override; + bool DumpZone(Zone* zone, const std::string& basePath) const override; + }; +} diff --git a/src/ObjWriting/Image/IwiWriter8.cpp b/src/ObjWriting/Image/IwiWriter8.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/ObjWriting/Image/IwiWriter8.h b/src/ObjWriting/Image/IwiWriter8.h new file mode 100644 index 00000000..ee60524e --- /dev/null +++ b/src/ObjWriting/Image/IwiWriter8.h @@ -0,0 +1,30 @@ +#pragma once + +#include "IImageWriter.h" +#include "Image/IwiTypes.h" + +namespace iwi8 +{ + class IwiWriter final : public IImageWriter + { + static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat); + + static void WriteVersion(FileAPI::IFile* file); + static void FillHeader2D(IwiHeader* header, Texture2D* texture); + static void FillHeaderCube(IwiHeader* header, TextureCube* texture); + static void FillHeader3D(IwiHeader* header, Texture3D* texture); + + public: + IwiWriter(); + IwiWriter(const IwiWriter& other) = delete; + IwiWriter(IwiWriter&& other) noexcept = delete; + ~IwiWriter() override; + + IwiWriter& operator=(const IwiWriter& other) = delete; + IwiWriter& operator=(IwiWriter&& other) noexcept = delete; + + bool SupportsImageFormat(const ImageFormat* imageFormat) override; + std::string GetFileExtension() override; + void DumpImage(FileAPI::IFile* file, Texture* texture) override; + }; +} diff --git a/src/ObjWriting/ObjWriting.cpp b/src/ObjWriting/ObjWriting.cpp index 2f692e65..7833e59b 100644 --- a/src/ObjWriting/ObjWriting.cpp +++ b/src/ObjWriting/ObjWriting.cpp @@ -1,12 +1,14 @@ #include "ObjWriting.h" #include "Dumping/IZoneDumper.h" +#include "Game/IW4/ZoneDumperIW4.h" #include "Game/T6/ZoneDumperT6.h" ObjWriting::Configuration_t ObjWriting::Configuration; const IZoneDumper* const ZONE_DUMPER[] { - new ZoneDumperT6() + new IW4::ZoneDumper(), + new T6::ZoneDumper() }; bool ObjWriting::DumpZone(Zone* zone, const std::string& basePath) diff --git a/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp new file mode 100644 index 00000000..47e68c65 --- /dev/null +++ b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp @@ -0,0 +1,70 @@ +#include "ZoneDefWriterIW4.h" +#include "Game/IW4/GameIW4.h" +#include "Game/IW4/CommonIW4.h" +#include "Game/IW4/GameAssetPoolIW4.h" + +#include +#include +#include + +using namespace IW4; + +namespace IW4 +{ + class ZoneDefWriterInternal final : public AbstractZoneDefWriter + { + void WriteContent() const + { + const auto* pools = dynamic_cast(m_zone->GetPools()); + + assert(pools); + if (!pools) + return; + + // Localized strings are all collected in one string file. So only add this to the zone file. + if (!pools->m_localize->m_asset_lookup.empty()) + { + WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), m_zone->m_name); + } + + for (const auto& asset : *pools) + { + switch (asset->m_type) + { + case ASSET_TYPE_LOCALIZE_ENTRY: + break; + + default: + WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name); + break; + } + } + } + + public: + ZoneDefWriterInternal(Zone* zone, FileAPI::IFile* file) + : AbstractZoneDefWriter(zone, file) + { + } + + void WriteZoneDef() override + { + WriteComment("Call Of Duty: Modern Warfare 2"); + WriteMetaData(META_DATA_KEY_GAME, "iw4"); + EmptyLine(); + + WriteContent(); + } + }; +} + +bool ZoneDefWriter::CanHandleZone(Zone* zone) const +{ + return zone->m_game == &g_GameIW4; +} + +void ZoneDefWriter::WriteZoneDef(Zone* zone, FileAPI::IFile* file) const +{ + ZoneDefWriterInternal writer(zone, file); + writer.WriteZoneDef(); +} diff --git a/src/Unlinker/Game/IW4/ZoneDefWriterIW4.h b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.h new file mode 100644 index 00000000..719f9be2 --- /dev/null +++ b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "ContentLister/ZoneDefWriter.h" + +namespace IW4 +{ + class ZoneDefWriter final : public IZoneDefWriter + { + public: + bool CanHandleZone(Zone* zone) const override; + void WriteZoneDef(Zone* zone, FileAPI::IFile* file) const override; + }; +} \ No newline at end of file diff --git a/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp b/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp index b8b3487e..63e6e584 100644 --- a/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp +++ b/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp @@ -9,113 +9,116 @@ using namespace T6; -class ZoneDefWriterT6Impl final : public AbstractZoneDefWriter +namespace T6 { - class KnownKey + class ZoneDefWriterInternal final : public AbstractZoneDefWriter { - public: - std::string m_key; - int m_hash; - - explicit KnownKey(std::string key) + class KnownKey { - m_key = std::move(key); - m_hash = CommonT6::Com_HashKey(m_key.c_str(), 64); - } - }; + public: + std::string m_key; + int m_hash; - inline static const KnownKey KNOWN_KEYS[] - { - KnownKey("ipak_read"), - KnownKey("ipak_write"), - KnownKey("initial_xmodels"), - KnownKey("initial_materials"), - }; - - void WriteKeyValuePair(KeyValuePair* kvp) const - { - for (const auto& knownKey : KNOWN_KEYS) - { - if(knownKey.m_hash == kvp->keyHash) + explicit KnownKey(std::string key) { - WriteMetaData("level." + knownKey.m_key, kvp->value); - return; + m_key = std::move(key); + m_hash = CommonT6::Com_HashKey(m_key.c_str(), 64); } - } + }; - std::ostringstream str; - str << "level.@" << std::setfill('0') << std::setw(sizeof(int) * 2) << std::hex << kvp->keyHash; - WriteMetaData(str.str(), kvp->value); - } - - void WriteContent() const - { - const auto* pools = dynamic_cast(m_zone->GetPools()); - - assert(pools); - if (!pools) - return; - - // Localized strings are all collected in one string file. So only add this to the zone file. - if(!pools->m_localize->m_asset_lookup.empty()) + inline static const KnownKey KNOWN_KEYS[] { - WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), m_zone->m_name); - } + KnownKey("ipak_read"), + KnownKey("ipak_write"), + KnownKey("initial_xmodels"), + KnownKey("initial_materials"), + }; - for (const auto& asset : *pools) + void WriteKeyValuePair(KeyValuePair* kvp) const { - switch (asset->m_type) + for (const auto& knownKey : KNOWN_KEYS) { - case ASSET_TYPE_LOCALIZE_ENTRY: - case ASSET_TYPE_KEYVALUEPAIRS: // KeyValuePairs should be included as zone file metadata and not as content - break; - - default: - WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name); - break; - } - } - } - -public: - ZoneDefWriterT6Impl(Zone* zone, FileAPI::IFile* file) - : AbstractZoneDefWriter(zone, file) - { - } - - void WriteZoneDef() override - { - WriteComment("Call Of Duty: Black Ops II"); - WriteMetaData(META_DATA_KEY_GAME, "t6"); - EmptyLine(); - - auto* assetPoolT6 = dynamic_cast(m_zone->GetPools()); - - if(assetPoolT6 && !assetPoolT6->m_key_value_pairs->m_asset_lookup.empty()) - { - for (auto kvpAsset : *assetPoolT6->m_key_value_pairs) - { - KeyValuePairs* keyValuePairs = kvpAsset->Asset(); - for(int varIndex = 0; varIndex < keyValuePairs->numVariables; varIndex++) + if (knownKey.m_hash == kvp->keyHash) { - WriteKeyValuePair(&keyValuePairs->keyValuePairs[varIndex]); + WriteMetaData("level." + knownKey.m_key, kvp->value); + return; } } - EmptyLine(); + std::ostringstream str; + str << "level.@" << std::setfill('0') << std::setw(sizeof(int) * 2) << std::hex << kvp->keyHash; + WriteMetaData(str.str(), kvp->value); } - WriteContent(); - } -}; + void WriteContent() const + { + const auto* pools = dynamic_cast(m_zone->GetPools()); -bool ZoneDefWriterT6::CanHandleZone(Zone* zone) const + assert(pools); + if (!pools) + return; + + // Localized strings are all collected in one string file. So only add this to the zone file. + if (!pools->m_localize->m_asset_lookup.empty()) + { + WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), m_zone->m_name); + } + + for (const auto& asset : *pools) + { + switch (asset->m_type) + { + case ASSET_TYPE_LOCALIZE_ENTRY: + case ASSET_TYPE_KEYVALUEPAIRS: // KeyValuePairs should be included as zone file metadata and not as content + break; + + default: + WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name); + break; + } + } + } + + public: + ZoneDefWriterInternal(Zone* zone, FileAPI::IFile* file) + : AbstractZoneDefWriter(zone, file) + { + } + + void WriteZoneDef() override + { + WriteComment("Call Of Duty: Black Ops II"); + WriteMetaData(META_DATA_KEY_GAME, "t6"); + EmptyLine(); + + auto* assetPoolT6 = dynamic_cast(m_zone->GetPools()); + + if (assetPoolT6 && !assetPoolT6->m_key_value_pairs->m_asset_lookup.empty()) + { + for (auto kvpAsset : *assetPoolT6->m_key_value_pairs) + { + KeyValuePairs* keyValuePairs = kvpAsset->Asset(); + for (int varIndex = 0; varIndex < keyValuePairs->numVariables; varIndex++) + { + WriteKeyValuePair(&keyValuePairs->keyValuePairs[varIndex]); + } + } + + EmptyLine(); + } + + WriteContent(); + } + }; +} + +bool ZoneDefWriter::CanHandleZone(Zone* zone) const { return zone->m_game == &g_GameT6; } -void ZoneDefWriterT6::WriteZoneDef(Zone* zone, FileAPI::IFile* file) const +void ZoneDefWriter::WriteZoneDef(Zone* zone, FileAPI::IFile* file) const { - ZoneDefWriterT6Impl writer(zone, file); + ZoneDefWriterInternal writer(zone, file); writer.WriteZoneDef(); } diff --git a/src/Unlinker/Game/T6/ZoneDefWriterT6.h b/src/Unlinker/Game/T6/ZoneDefWriterT6.h index 59a82b5b..26202574 100644 --- a/src/Unlinker/Game/T6/ZoneDefWriterT6.h +++ b/src/Unlinker/Game/T6/ZoneDefWriterT6.h @@ -2,9 +2,12 @@ #include "ContentLister/ZoneDefWriter.h" -class ZoneDefWriterT6 final : public IZoneDefWriter +namespace T6 { -public: - bool CanHandleZone(Zone* zone) const override; - void WriteZoneDef(Zone* zone, FileAPI::IFile* file) const override; -}; \ No newline at end of file + class ZoneDefWriter final : public IZoneDefWriter + { + public: + bool CanHandleZone(Zone* zone) const override; + void WriteZoneDef(Zone* zone, FileAPI::IFile* file) const override; + }; +} \ No newline at end of file diff --git a/src/Unlinker/Unlinker.cpp b/src/Unlinker/Unlinker.cpp index 1e9c253a..752af671 100644 --- a/src/Unlinker/Unlinker.cpp +++ b/src/Unlinker/Unlinker.cpp @@ -1,5 +1,9 @@ #include "Unlinker.h" +#include +#include +#include + #include "Utils/Arguments/ArgumentParser.h" #include "ZoneLoading.h" #include "ObjWriting.h" @@ -10,17 +14,16 @@ #include "SearchPath/SearchPaths.h" #include "SearchPath/SearchPathFilesystem.h" #include "ContentLister/ZoneDefWriter.h" -#include "Game/T6/ZoneDefWriterT6.h" - -#include -#include -#include #include "ObjContainer/IWD/IWD.h" #include "UnlinkerArgs.h" +#include "Game/IW4/ZoneDefWriterIW4.h" +#include "Game/T6/ZoneDefWriterT6.h" + const IZoneDefWriter* const ZONE_DEF_WRITERS[] { - new ZoneDefWriterT6() + new IW4::ZoneDefWriter(), + new T6::ZoneDefWriter() }; class Unlinker::Impl