add iw3 asset dumping basics

This commit is contained in:
Jan
2021-04-15 13:42:19 +02:00
parent dbcbb4a4b3
commit 07fb470466
16 changed files with 574 additions and 0 deletions

View File

@ -0,0 +1,48 @@
#include "AssetDumperGfxImage.h"
#include <cassert>
#include "ObjWriting.h"
#include "Image/IwiWriter6.h"
#include "Image/DdsWriter.h"
using namespace IW3;
AssetDumperGfxImage::AssetDumperGfxImage()
{
switch (ObjWriting::Configuration.ImageOutputFormat)
{
case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS:
m_writer = std::make_unique<DdsWriter>();
break;
case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI:
m_writer = std::make_unique<iwi6::IwiWriter>();
break;
default:
assert(false);
m_writer = nullptr;
break;
}
}
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
{
const auto* image = asset->Asset();
return image->cardMemory.platform[0] > 0;
}
bool AssetDumperGfxImage::CanDumpAsRaw()
{
return true;
}
std::string AssetDumperGfxImage::GetFileNameForAsset(Zone* zone, XAssetInfo<GfxImage>* asset)
{
return "images/" + asset->m_name + m_writer->GetFileExtension();
}
void AssetDumperGfxImage::DumpRaw(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset, std::ostream& stream)
{
const auto* image = asset->Asset();
m_writer->DumpImage(stream, image->texture.texture);
}

View File

@ -0,0 +1,24 @@
#pragma once
#include <memory>
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW3/IW3.h"
#include "Image/IImageWriter.h"
namespace IW3
{
class AssetDumperGfxImage final : public AbstractAssetDumper<GfxImage>
{
std::unique_ptr<IImageWriter> m_writer;
protected:
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
bool CanDumpAsRaw() override;
std::string GetFileNameForAsset(Zone* zone, XAssetInfo<GfxImage>* asset) override;
void DumpRaw(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset, std::ostream& stream) override;
public:
AssetDumperGfxImage();
};
}

View File

@ -0,0 +1,76 @@
#include "AssetDumperLoadedSound.h"
#include "Sound/WavTypes.h"
using namespace IW3;
bool AssetDumperLoadedSound::ShouldDump(XAssetInfo<LoadedSound>* asset)
{
return true;
}
bool AssetDumperLoadedSound::CanDumpAsRaw()
{
return true;
}
std::string AssetDumperLoadedSound::GetFileNameForAsset(Zone* zone, XAssetInfo<LoadedSound>* asset)
{
return "sound/" + asset->m_name;
}
void AssetDumperLoadedSound::DumpWavPcm(AssetDumpingContext& context, const LoadedSound* asset, std::ostream& stream)
{
const auto riffMasterChunkSize = sizeof(WAV_CHUNK_ID_RIFF)
+ sizeof(uint32_t)
+ sizeof(WAV_WAVE_ID)
+ sizeof(WavChunkHeader)
+ sizeof(WavFormatChunkPcm)
+ sizeof(WavChunkHeader)
+ sizeof(asset->sound.info.data_len);
stream.write(reinterpret_cast<const char*>(&WAV_CHUNK_ID_RIFF), sizeof(WAV_CHUNK_ID_RIFF));
stream.write(reinterpret_cast<const char*>(&riffMasterChunkSize), sizeof(riffMasterChunkSize));
stream.write(reinterpret_cast<const char*>(&WAV_WAVE_ID), sizeof(WAV_WAVE_ID));
const WavChunkHeader formatChunkHeader
{
WAV_CHUNK_ID_FMT,
sizeof(WavFormatChunkPcm)
};
stream.write(reinterpret_cast<const char*>(&formatChunkHeader), sizeof(formatChunkHeader));
WavFormatChunkPcm formatChunk
{
WavFormat::PCM,
static_cast<uint16_t>(asset->sound.info.channels),
asset->sound.info.rate,
asset->sound.info.rate * asset->sound.info.channels * asset->sound.info.bits / 8,
static_cast<uint16_t>(asset->sound.info.block_size),
static_cast<uint16_t>(asset->sound.info.bits)
};
stream.write(reinterpret_cast<const char*>(&formatChunk), sizeof(formatChunk));
const WavChunkHeader dataChunkHeader
{
WAV_CHUNK_ID_DATA,
asset->sound.info.data_len
};
stream.write(reinterpret_cast<const char*>(&dataChunkHeader), sizeof(dataChunkHeader));
stream.write(asset->sound.data, asset->sound.info.data_len);
}
void AssetDumperLoadedSound::DumpRaw(AssetDumpingContext& context, XAssetInfo<LoadedSound>* asset, std::ostream& stream)
{
const auto* loadedSound = asset->Asset();
switch (static_cast<WavFormat>(loadedSound->sound.info.format))
{
case WavFormat::PCM:
DumpWavPcm(context, loadedSound, stream);
break;
default:
printf("Unknown format %i for loaded sound: %s\n", loadedSound->sound.info.format, loadedSound->name);
break;
}
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW3/IW3.h"
namespace IW3
{
class AssetDumperLoadedSound final : public AbstractAssetDumper<LoadedSound>
{
static void DumpWavPcm(AssetDumpingContext& context, const LoadedSound* asset, std::ostream& stream);
protected:
bool ShouldDump(XAssetInfo<LoadedSound>* asset) override;
bool CanDumpAsRaw() override;
std::string GetFileNameForAsset(Zone* zone, XAssetInfo<LoadedSound>* asset) override;
void DumpRaw(AssetDumpingContext& context, XAssetInfo<LoadedSound>* asset, std::ostream& stream) override;
};
}

View File

@ -0,0 +1,53 @@
#include "AssetDumperLocalizeEntry.h"
#include <fstream>
#include <filesystem>
#include "Localize/LocalizeCommon.h"
#include "Dumping/Localize/StringFileDumper.h"
using namespace IW3;
namespace fs = std::filesystem;
void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool<LocalizeEntry>* pool)
{
if (pool->m_asset_lookup.empty())
return;
const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone->m_language);
fs::path stringsPath(context.m_base_path);
stringsPath.append(language);
stringsPath.append("localizedstrings");
create_directories(stringsPath);
auto stringFilePath(stringsPath);
stringFilePath.append(context.m_zone->m_name + ".str");
std::ofstream stringFile(stringFilePath, std::fstream::out | std::ofstream::binary);
if (stringFile.is_open())
{
StringFileDumper stringFileDumper(context.m_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", context.m_zone->m_name.c_str());
}
}

View File

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

View File

@ -0,0 +1,24 @@
#include "AssetDumperRawFile.h"
using namespace IW3;
bool AssetDumperRawFile::ShouldDump(XAssetInfo<RawFile>* asset)
{
return true;
}
bool AssetDumperRawFile::CanDumpAsRaw()
{
return true;
}
std::string AssetDumperRawFile::GetFileNameForAsset(Zone* zone, XAssetInfo<RawFile>* asset)
{
return asset->m_name;
}
void AssetDumperRawFile::DumpRaw(AssetDumpingContext& context, XAssetInfo<RawFile>* asset, std::ostream& stream)
{
const auto* rawFile = asset->Asset();
stream.write(rawFile->buffer, rawFile->len);
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW3/IW3.h"
namespace IW3
{
class AssetDumperRawFile final : public AbstractAssetDumper<RawFile>
{
protected:
bool ShouldDump(XAssetInfo<RawFile>* asset) override;
bool CanDumpAsRaw() override;
std::string GetFileNameForAsset(Zone* zone, XAssetInfo<RawFile>* asset) override;
void DumpRaw(AssetDumpingContext& context, XAssetInfo<RawFile>* asset, std::ostream& stream) override;
};
}

View File

@ -0,0 +1,36 @@
#include "AssetDumperStringTable.h"
#include "Csv/CsvStream.h"
using namespace IW3;
bool AssetDumperStringTable::ShouldDump(XAssetInfo<StringTable>* asset)
{
return true;
}
bool AssetDumperStringTable::CanDumpAsRaw()
{
return true;
}
std::string AssetDumperStringTable::GetFileNameForAsset(Zone* zone, XAssetInfo<StringTable>* asset)
{
return asset->m_name;
}
void AssetDumperStringTable::DumpRaw(AssetDumpingContext& context, XAssetInfo<StringTable>* asset, std::ostream& stream)
{
const auto* stringTable = asset->Asset();
CsvOutputStream csv(stream);
for (auto row = 0; row < stringTable->rowCount; row++)
{
for (auto column = 0; column < stringTable->columnCount; column++)
{
csv.WriteColumn(stringTable->values[column + row * stringTable->columnCount]);
}
csv.NextRow();
}
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW3/IW3.h"
namespace IW3
{
class AssetDumperStringTable final : public AbstractAssetDumper<StringTable>
{
protected:
bool ShouldDump(XAssetInfo<StringTable>* asset) override;
bool CanDumpAsRaw() override;
std::string GetFileNameForAsset(Zone* zone, XAssetInfo<StringTable>* asset) override;
void DumpRaw(AssetDumpingContext& context, XAssetInfo<StringTable>* asset, std::ostream& stream) override;
};
}

View File

@ -0,0 +1,66 @@
#include "ZoneDumperIW3.h"
#include "Game/IW3/GameIW3.h"
#include "Game/IW3/GameAssetPoolIW3.h"
#include "AssetDumpers/AssetDumperGfxImage.h"
#include "AssetDumpers/AssetDumperLoadedSound.h"
#include "AssetDumpers/AssetDumperLocalizeEntry.h"
#include "AssetDumpers/AssetDumperRawFile.h"
#include "AssetDumpers/AssetDumperStringTable.h"
#include "AssetDumpers/AssetDumperWeapon.h"
using namespace IW3;
bool ZoneDumper::CanHandleZone(AssetDumpingContext& context) const
{
return context.m_zone->m_game == &g_GameIW3;
}
bool ZoneDumper::DumpZone(AssetDumpingContext& context) const
{
#define DUMP_ASSET_POOL(dumperType, poolName) \
if(assetPools->poolName) \
{ \
dumperType dumper; \
dumper.DumpPool(context, assetPools->poolName.get()); \
}
const auto* assetPools = dynamic_cast<GameAssetPoolIW3*>(context.m_zone->m_pools.get());
// 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(AssetDumperWeapon, 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)
return true;
#undef DUMP_ASSET_POOL
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "Dumping/IZoneDumper.h"
namespace IW3
{
class ZoneDumper final : public IZoneDumper
{
public:
bool CanHandleZone(AssetDumpingContext& context) const override;
bool DumpZone(AssetDumpingContext& context) const override;
};
}