Dump a few iw4 assets

This commit is contained in:
Jan 2020-09-09 18:40:01 +02:00
parent 4aafbac113
commit 14666ed944
32 changed files with 734 additions and 220 deletions

View File

@ -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";
}
}

View File

@ -0,0 +1,11 @@
#pragma once
#include <string>
#include "Game/GameLanguage.h"
class LocalizeCommon
{
public:
static std::string GetNameOfLanguage(GameLanguage language);
};

View File

@ -0,0 +1,47 @@
#include "AssetDumperGfxImage.h"
#include <cassert>
#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);
}

View File

@ -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<IW4::GfxImage>
{
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;
};
}

View File

@ -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<LocalizeEntry>* 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());
}
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW4/IW4.h"
namespace IW4
{
class AssetDumperLocalizeEntry final : public IAssetDumper<IW4::LocalizeEntry>
{
public:
void DumpPool(Zone* zone, AssetPool<IW4::LocalizeEntry>* pool, const std::string& basePath) override;
};
}

View File

@ -0,0 +1,63 @@
#include "AssetDumperRawFile.h"
#include <zlib.h>
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<const Bytef*>(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);
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW4/IW4.h"
namespace IW4
{
class AssetDumperRawFile final : public AbstractAssetDumper<RawFile>
{
protected:
bool ShouldDump(RawFile* asset) override;
std::string GetFileNameForAsset(Zone* zone, RawFile* asset) override;
void DumpAsset(Zone* zone, RawFile* asset, FileAPI::File* out) override;
};
}

View File

@ -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();
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW4/IW4.h"
namespace IW4
{
class AssetDumperStringTable final : public AbstractAssetDumper<IW4::StringTable>
{
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;
};
}

View File

@ -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<GameAssetPoolIW4*>(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
}

View File

@ -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;
};
}

View File

@ -3,10 +3,13 @@
#include "Dumping/AbstractAssetDumper.h"
#include "Game/T6/T6.h"
class AssetDumperFontIcon final : public AbstractAssetDumper<T6::FontIcon>
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;
};
class AssetDumperFontIcon final : public AbstractAssetDumper<T6::FontIcon>
{
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;
};
}

View File

@ -1,8 +1,10 @@
#include "AssetDumperGfxImage.h"
#include <cassert>
#include "ObjWriting.h"
#include "Image/IwiWriter27.h"
#include "Image/DdsWriter.h"
#include <cassert>
using namespace T6;

View File

@ -4,21 +4,24 @@
#include "Game/T6/T6.h"
#include "Image/IImageWriter.h"
class AssetDumperGfxImage final : public AbstractAssetDumper<T6::GfxImage>
namespace T6
{
IImageWriter* m_writer;
class AssetDumperGfxImage final : public AbstractAssetDumper<T6::GfxImage>
{
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;
};
AssetDumperGfxImage(const AssetDumperGfxImage& other) = delete;
AssetDumperGfxImage(AssetDumperGfxImage&& other) noexcept = delete;
AssetDumperGfxImage& operator=(const AssetDumperGfxImage& other) = delete;
AssetDumperGfxImage& operator=(AssetDumperGfxImage&& other) noexcept = delete;
};
}

View File

@ -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<LocalizeEntry>* 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);

View File

@ -2,12 +2,12 @@
#include "Dumping/AbstractAssetDumper.h"
#include "Game/T6/T6.h"
#include "Game/GameLanguage.h"
class AssetDumperLocalizeEntry final : public IAssetDumper<T6::LocalizeEntry>
namespace T6
{
static std::string GetNameOfLanguage(GameLanguage language);
public:
void DumpPool(Zone* zone, AssetPool<T6::LocalizeEntry>* pool, const std::string& basePath) override;
};
class AssetDumperLocalizeEntry final : public IAssetDumper<T6::LocalizeEntry>
{
public:
void DumpPool(Zone* zone, AssetPool<T6::LocalizeEntry>* pool, const std::string& basePath) override;
};
}

View File

@ -3,10 +3,13 @@
#include "Dumping/AbstractAssetDumper.h"
#include "Game/T6/T6.h"
class AssetDumperQdb final : public AbstractAssetDumper<T6::Qdb>
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;
};
class AssetDumperQdb final : public AbstractAssetDumper<T6::Qdb>
{
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;
};
}

View File

@ -3,10 +3,13 @@
#include "Dumping/AbstractAssetDumper.h"
#include "Game/T6/T6.h"
class AssetDumperRawFile final : public AbstractAssetDumper<T6::RawFile>
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;
};
class AssetDumperRawFile final : public AbstractAssetDumper<T6::RawFile>
{
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;
};
}

View File

@ -3,10 +3,13 @@
#include "Dumping/AbstractAssetDumper.h"
#include "Game/T6/T6.h"
class AssetDumperScriptParseTree final : public AbstractAssetDumper<T6::ScriptParseTree>
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;
};
class AssetDumperScriptParseTree final : public AbstractAssetDumper<T6::ScriptParseTree>
{
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;
};
}

View File

@ -3,10 +3,13 @@
#include "Dumping/AbstractAssetDumper.h"
#include "Game/T6/T6.h"
class AssetDumperSlug final : public AbstractAssetDumper<T6::Slug>
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;
};
class AssetDumperSlug final : public AbstractAssetDumper<T6::Slug>
{
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;
};
}

View File

@ -3,10 +3,13 @@
#include "Dumping/AbstractAssetDumper.h"
#include "Game/T6/T6.h"
class AssetDumperStringTable final : public AbstractAssetDumper<T6::StringTable>
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;
};
class AssetDumperStringTable final : public AbstractAssetDumper<T6::StringTable>
{
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;
};
}

View File

@ -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) \

View File

@ -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;
};
}

View File

View File

@ -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;
};
}

View File

@ -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)

View File

@ -0,0 +1,70 @@
#include "ZoneDefWriterIW4.h"
#include "Game/IW4/GameIW4.h"
#include "Game/IW4/CommonIW4.h"
#include "Game/IW4/GameAssetPoolIW4.h"
#include <sstream>
#include <iomanip>
#include <cassert>
using namespace IW4;
namespace IW4
{
class ZoneDefWriterInternal final : public AbstractZoneDefWriter
{
void WriteContent() const
{
const auto* pools = dynamic_cast<GameAssetPoolIW4*>(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();
}

View File

@ -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;
};
}

View File

@ -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<GameAssetPoolT6*>(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<GameAssetPoolT6*>(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<GameAssetPoolT6*>(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<GameAssetPoolT6*>(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();
}

View File

@ -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;
};
class ZoneDefWriter final : public IZoneDefWriter
{
public:
bool CanHandleZone(Zone* zone) const override;
void WriteZoneDef(Zone* zone, FileAPI::IFile* file) const override;
};
}

View File

@ -1,5 +1,9 @@
#include "Unlinker.h"
#include <set>
#include <regex>
#include <filesystem>
#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 <set>
#include <regex>
#include <filesystem>
#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