diff --git a/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp b/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp index 5aa9db1d..be2b3472 100644 --- a/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp +++ b/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp @@ -7,7 +7,7 @@ #include "Localize/LocalizeDumperIW3.h" #include "Maps/MapEntsDumperIW3.h" #include "ObjWriting.h" -#include "RawFile/AssetDumperRawFile.h" +#include "RawFile/RawFileDumperIW3.h" #include "Sound/AssetDumperLoadedSound.h" #include "StringTable/AssetDumperStringTable.h" #include "Weapon/AssetDumperWeapon.h" @@ -49,7 +49,7 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(raw_file::Dumper, m_raw_file, ASSET_TYPE_RAWFILE) DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) return true; diff --git a/src/ObjWriting/Game/IW3/RawFile/AssetDumperRawFile.cpp b/src/ObjWriting/Game/IW3/RawFile/AssetDumperRawFile.cpp deleted file mode 100644 index bd9b7ecd..00000000 --- a/src/ObjWriting/Game/IW3/RawFile/AssetDumperRawFile.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "AssetDumperRawFile.h" - -using namespace IW3; - -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - stream.write(rawFile->buffer, rawFile->len); -} diff --git a/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.cpp b/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.cpp new file mode 100644 index 00000000..22af389d --- /dev/null +++ b/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.cpp @@ -0,0 +1,23 @@ +#include "RawFileDumperIW3.h" + +using namespace IW3; + +namespace IW3::raw_file +{ + bool Dumper::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void Dumper::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + stream.write(rawFile->buffer, rawFile->len); + } +} // namespace IW3::raw_file diff --git a/src/ObjWriting/Game/IW3/RawFile/AssetDumperRawFile.h b/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.h similarity index 69% rename from src/ObjWriting/Game/IW3/RawFile/AssetDumperRawFile.h rename to src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.h index abeeda26..3ea995c8 100644 --- a/src/ObjWriting/Game/IW3/RawFile/AssetDumperRawFile.h +++ b/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.h @@ -3,12 +3,12 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/IW3/IW3.h" -namespace IW3 +namespace IW3::raw_file { - class AssetDumperRawFile final : public AbstractAssetDumper + class Dumper final : public AbstractAssetDumper { protected: bool ShouldDump(XAssetInfo* asset) override; void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; }; -} // namespace IW3 +} // namespace IW3::raw_file diff --git a/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp b/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp index 4dd466d9..c00e44f0 100644 --- a/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp +++ b/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp @@ -14,7 +14,7 @@ #include "ObjWriting.h" #include "PhysCollmap/AssetDumperPhysCollmap.h" #include "PhysPreset/PhysPresetInfoStringDumperIW4.h" -#include "RawFile/AssetDumperRawFile.h" +#include "RawFile/RawFileDumperIW4.h" #include "Shader/AssetDumperPixelShader.h" #include "Shader/AssetDumperVertexShader.h" #include "Sound/AssetDumperLoadedSound.h" @@ -70,7 +70,7 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(raw_file::Dumper, m_raw_file, ASSET_TYPE_RAWFILE) DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) DUMP_ASSET_POOL(leaderboard::JsonDumper, m_leaderboard, ASSET_TYPE_LEADERBOARD) DUMP_ASSET_POOL(AssetDumperStructuredDataDefSet, m_structed_data_def_set, ASSET_TYPE_STRUCTURED_DATA_DEF) diff --git a/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.cpp b/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.cpp new file mode 100644 index 00000000..ec4224af --- /dev/null +++ b/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.cpp @@ -0,0 +1,70 @@ +#include "RawFileDumperIW4.h" + +#include +#include +#include + +using namespace IW4; + +namespace IW4::raw_file +{ + bool Dumper::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void Dumper::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + if (rawFile->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::runtime_error("Initializing inflate failed"); + } + + zs.next_in = reinterpret_cast(rawFile->data.compressedBuffer); + zs.avail_in = rawFile->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) + { + std::cerr << std::format("Inflate failed when attempting to dump rawfile '{}'\n", rawFile->name); + inflateEnd(&zs); + return; + } + + stream.write(reinterpret_cast(buffer), sizeof(buffer) - zs.avail_out); + } + + inflateEnd(&zs); + } + else if (rawFile->len > 0) + { + stream.write(rawFile->data.buffer, rawFile->len); + } + } +} // namespace IW4::raw_file diff --git a/src/ObjWriting/Game/IW4/RawFile/AssetDumperRawFile.h b/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.h similarity index 69% rename from src/ObjWriting/Game/IW4/RawFile/AssetDumperRawFile.h rename to src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.h index 5b2c2120..a1657fb5 100644 --- a/src/ObjWriting/Game/IW4/RawFile/AssetDumperRawFile.h +++ b/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.h @@ -3,12 +3,12 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/IW4/IW4.h" -namespace IW4 +namespace IW4::raw_file { - class AssetDumperRawFile final : public AbstractAssetDumper + class Dumper final : public AbstractAssetDumper { protected: bool ShouldDump(XAssetInfo* asset) override; void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; }; -} // namespace IW4 +} // namespace IW4::raw_file diff --git a/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp b/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp index 2e735cb7..254a0d9b 100644 --- a/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp +++ b/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp @@ -10,7 +10,7 @@ #include "Menu/AssetDumperMenuDef.h" #include "Menu/AssetDumperMenuList.h" #include "ObjWriting.h" -#include "RawFile/AssetDumperRawFile.h" +#include "RawFile/RawFileDumperIW5.h" #include "Script/AssetDumperScriptFile.h" #include "Sound/AssetDumperLoadedSound.h" #include "StringTable/AssetDumperStringTable.h" @@ -61,7 +61,7 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) // DUMP_ASSET_POOL(AssetDumperSurfaceFxTable, m_surface_fx_table, ASSET_TYPE_SURFACE_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(raw_file::Dumper, m_raw_file, ASSET_TYPE_RAWFILE) DUMP_ASSET_POOL(AssetDumperScriptFile, m_script_file, ASSET_TYPE_SCRIPTFILE) DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) DUMP_ASSET_POOL(leaderboard::JsonDumper, m_leaderboard, ASSET_TYPE_LEADERBOARD) diff --git a/src/ObjWriting/Game/IW5/RawFile/AssetDumperRawFile.cpp b/src/ObjWriting/Game/IW5/RawFile/AssetDumperRawFile.cpp deleted file mode 100644 index 283b8bda..00000000 --- a/src/ObjWriting/Game/IW5/RawFile/AssetDumperRawFile.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "AssetDumperRawFile.h" - -#include -#include -#include - -using namespace IW5; - -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - if (rawFile->compressedLen <= 0) - return; - - 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::runtime_error("Initializing inflate failed"); - } - - zs.next_in = reinterpret_cast(rawFile->buffer); - zs.avail_in = rawFile->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) - { - std::cerr << std::format("Inflate failed when attempting to dump rawfile '{}'\n", rawFile->name); - inflateEnd(&zs); - return; - } - - stream.write(reinterpret_cast(buffer), sizeof(buffer) - zs.avail_out); - } - - inflateEnd(&zs); -} diff --git a/src/ObjWriting/Game/IW4/RawFile/AssetDumperRawFile.cpp b/src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.cpp similarity index 61% rename from src/ObjWriting/Game/IW4/RawFile/AssetDumperRawFile.cpp rename to src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.cpp index a1669136..ba444e30 100644 --- a/src/ObjWriting/Game/IW4/RawFile/AssetDumperRawFile.cpp +++ b/src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.cpp @@ -1,29 +1,31 @@ -#include "AssetDumperRawFile.h" +#include "RawFileDumperIW5.h" #include #include #include -using namespace IW4; +using namespace IW5; -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) +namespace IW5::raw_file { - return true; -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - if (rawFile->compressedLen > 0) + bool Dumper::ShouldDump(XAssetInfo* asset) { - z_stream_s zs{}; + return true; + } + void Dumper::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + if (rawFile->compressedLen <= 0) + return; + + z_stream_s zs{}; zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; @@ -37,7 +39,7 @@ void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo(rawFile->data.compressedBuffer); + zs.next_in = reinterpret_cast(rawFile->buffer); zs.avail_in = rawFile->compressedLen; Bytef buffer[0x1000]; @@ -60,8 +62,4 @@ void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfolen > 0) - { - stream.write(rawFile->data.buffer, rawFile->len); - } -} +} // namespace IW5::raw_file diff --git a/src/ObjWriting/Game/IW5/RawFile/AssetDumperRawFile.h b/src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.h similarity index 69% rename from src/ObjWriting/Game/IW5/RawFile/AssetDumperRawFile.h rename to src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.h index 57e35274..b3fff52f 100644 --- a/src/ObjWriting/Game/IW5/RawFile/AssetDumperRawFile.h +++ b/src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.h @@ -3,12 +3,12 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/IW5/IW5.h" -namespace IW5 +namespace IW5::raw_file { - class AssetDumperRawFile final : public AbstractAssetDumper + class Dumper final : public AbstractAssetDumper { protected: bool ShouldDump(XAssetInfo* asset) override; void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; }; -} // namespace IW5 +} // namespace IW5::raw_file diff --git a/src/ObjWriting/Game/T5/ObjWriterT5.cpp b/src/ObjWriting/Game/T5/ObjWriterT5.cpp index baaf5a32..ce3c8eec 100644 --- a/src/ObjWriting/Game/T5/ObjWriterT5.cpp +++ b/src/ObjWriting/Game/T5/ObjWriterT5.cpp @@ -6,7 +6,7 @@ #include "Image/ImageDumperT5.h" #include "Localize/LocalizeDumperT5.h" #include "ObjWriting.h" -#include "RawFile/AssetDumperRawFile.h" +#include "RawFile/RawFileDumperT5.h" #include "Sound/AssetDumperSndBank.h" #include "StringTable/AssetDumperStringTable.h" #include "Weapon/AssetDumperWeapon.h" @@ -49,7 +49,7 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(raw_file::Dumper, m_raw_file, ASSET_TYPE_RAWFILE) DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) // DUMP_ASSET_POOL(AssetDumperPackIndex, m_pack_index, ASSET_TYPE_PACK_INDEX) // DUMP_ASSET_POOL(AssetDumperXGlobals, m_xglobals, ASSET_TYPE_XGLOBALS) diff --git a/src/ObjWriting/Game/T5/RawFile/AssetDumperRawFile.cpp b/src/ObjWriting/Game/T5/RawFile/AssetDumperRawFile.cpp deleted file mode 100644 index 45827890..00000000 --- a/src/ObjWriting/Game/T5/RawFile/AssetDumperRawFile.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "AssetDumperRawFile.h" - -#include -#include -#include - -using namespace T5; - -namespace fs = std::filesystem; - -void AssetDumperRawFile::DumpGsc(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream) -{ - const auto* rawFile = asset->Asset(); - - if (rawFile->len <= 8) - { - std::cout << "Invalid len of gsc file \"" << rawFile->name << "\"\n"; - return; - } - - const auto outLen = reinterpret_cast(rawFile->buffer)[0]; - const auto inLen = reinterpret_cast(rawFile->buffer)[1]; - - assert(inLen == static_cast(rawFile->len) - 8); - - if (inLen > static_cast(rawFile->len - 8) + 1) - { - std::cout << "Invalid compression of gsc file \"" << rawFile->name << "\": " << inLen << "\n"; - return; - } - - if (outLen > GSC_MAX_SIZE) - { - std::cout << "Invalid size of gsc file \"" << rawFile->name << "\": " << outLen << "\n"; - return; - } - - 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::runtime_error("Initializing inflate failed"); - } - - zs.next_in = reinterpret_cast(&rawFile->buffer[8]); - zs.avail_in = inLen; - - Bytef buffer[0x1000]; - - size_t writtenSize = 0; - while (zs.avail_in > 0) - { - zs.next_out = buffer; - zs.avail_out = sizeof(buffer); - ret = inflate(&zs, Z_SYNC_FLUSH); - - if (ret < 0) - { - std::cout << "Inflate failed for dumping gsc file \"" << rawFile->name << "\"\n"; - inflateEnd(&zs); - return; - } - - const auto inflateOutSize = sizeof(buffer) - zs.avail_out; - - if (writtenSize + inflateOutSize >= outLen) - { - // Last byte is a \0 byte. Skip it. - stream.write(reinterpret_cast(buffer), inflateOutSize - 1); - } - else - { - stream.write(reinterpret_cast(buffer), inflateOutSize); - } - writtenSize += inflateOutSize; - } - - inflateEnd(&zs); -} - -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const fs::path rawFilePath(rawFile->name); - const auto extension = rawFilePath.extension().string(); - - if (extension == ".gsc" || extension == ".csc") - { - DumpGsc(context, asset, stream); - } - else - { - stream.write(rawFile->buffer, rawFile->len); - } -} diff --git a/src/ObjWriting/Game/T5/RawFile/AssetDumperRawFile.h b/src/ObjWriting/Game/T5/RawFile/AssetDumperRawFile.h deleted file mode 100644 index b2d10763..00000000 --- a/src/ObjWriting/Game/T5/RawFile/AssetDumperRawFile.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T5/T5.h" - -namespace T5 -{ - class AssetDumperRawFile final : public AbstractAssetDumper - { - constexpr static size_t GSC_MAX_SIZE = 0xC000000; - - static void DumpGsc(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T5 diff --git a/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.cpp b/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.cpp new file mode 100644 index 00000000..5c57964a --- /dev/null +++ b/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.cpp @@ -0,0 +1,121 @@ +#include "RawFileDumperT5.h" + +#include "Utils/StringUtils.h" + +#include +#include +#include + +using namespace T5; + +namespace fs = std::filesystem; + +namespace +{ + constexpr static size_t GSC_MAX_SIZE = 0xC000000; + + void DumpGsc(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream) + { + const auto* rawFile = asset->Asset(); + + if (rawFile->len <= 8) + { + std::cout << "Invalid len of gsc file \"" << rawFile->name << "\"\n"; + return; + } + + const auto outLen = reinterpret_cast(rawFile->buffer)[0]; + const auto inLen = reinterpret_cast(rawFile->buffer)[1]; + + assert(inLen == static_cast(rawFile->len) - 8); + + if (inLen > static_cast(rawFile->len - 8) + 1) + { + std::cout << "Invalid compression of gsc file \"" << rawFile->name << "\": " << inLen << "\n"; + return; + } + + if (outLen > GSC_MAX_SIZE) + { + std::cout << "Invalid size of gsc file \"" << rawFile->name << "\": " << outLen << "\n"; + return; + } + + 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::runtime_error("Initializing inflate failed"); + } + + zs.next_in = reinterpret_cast(&rawFile->buffer[8]); + zs.avail_in = inLen; + + Bytef buffer[0x1000]; + + size_t writtenSize = 0; + while (zs.avail_in > 0) + { + zs.next_out = buffer; + zs.avail_out = sizeof(buffer); + ret = inflate(&zs, Z_SYNC_FLUSH); + + if (ret < 0) + { + std::cout << "Inflate failed for dumping gsc file \"" << rawFile->name << "\"\n"; + inflateEnd(&zs); + return; + } + + const auto inflateOutSize = sizeof(buffer) - zs.avail_out; + + if (writtenSize + inflateOutSize >= outLen) + { + // Last byte is a \0 byte. Skip it. + stream.write(reinterpret_cast(buffer), inflateOutSize - 1); + } + else + { + stream.write(reinterpret_cast(buffer), inflateOutSize); + } + writtenSize += inflateOutSize; + } + + inflateEnd(&zs); + } +} // namespace + +namespace T5::raw_file +{ + bool Dumper::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void Dumper::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const fs::path rawFilePath(rawFile->name); + auto extension = rawFilePath.extension().string(); + utils::MakeStringLowerCase(extension); + + if (extension == ".gsc" || extension == ".csc") + DumpGsc(context, asset, stream); + else + stream.write(rawFile->buffer, rawFile->len); + } +} // namespace T5::raw_file diff --git a/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.h b/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.h new file mode 100644 index 00000000..2c6f6ba2 --- /dev/null +++ b/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T5/T5.h" + +namespace T5::raw_file +{ + class Dumper final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace T5::raw_file diff --git a/src/ObjWriting/Game/T6/ObjWriterT6.cpp b/src/ObjWriting/Game/T6/ObjWriterT6.cpp index 3e8de73d..79c6778c 100644 --- a/src/ObjWriting/Game/T6/ObjWriterT6.cpp +++ b/src/ObjWriting/Game/T6/ObjWriterT6.cpp @@ -12,7 +12,7 @@ #include "PhysConstraints/PhysConstraintsInfoStringDumperT6.h" #include "PhysPreset/PhysPresetInfoStringDumperT6.h" #include "Qdb/AssetDumperQdb.h" -#include "RawFile/AssetDumperRawFile.h" +#include "RawFile/RawFileDumperT6.h" #include "Script/AssetDumperScriptParseTree.h" #include "Slug/AssetDumperSlug.h" #include "Sound/AssetDumperSndBank.h" @@ -75,7 +75,7 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(raw_file::Dumper, m_raw_file, ASSET_TYPE_RAWFILE) DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) DUMP_ASSET_POOL(leaderboard::JsonDumper, m_leaderboard, ASSET_TYPE_LEADERBOARD) // DUMP_ASSET_POOL(AssetDumperXGlobals, m_xglobals, ASSET_TYPE_XGLOBALS) diff --git a/src/ObjWriting/Game/T6/RawFile/AssetDumperRawFile.cpp b/src/ObjWriting/Game/T6/RawFile/AssetDumperRawFile.cpp deleted file mode 100644 index 291d969e..00000000 --- a/src/ObjWriting/Game/T6/RawFile/AssetDumperRawFile.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "AssetDumperRawFile.h" - -#include -#include -#include - -using namespace T6; - -namespace fs = std::filesystem; - -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperRawFile::DumpAnimtree(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream) -{ - const auto* rawFile = asset->Asset(); - - if (rawFile->len <= 4) - { - std::cerr << "Invalid len of animtree file \"" << rawFile->name << "\"\n"; - return; - } - - const auto outLen = reinterpret_cast(rawFile->buffer)[0]; - const auto inLen = rawFile->len; - - if (outLen > ANIMTREE_MAX_SIZE) - { - std::cerr << "Invalid size of animtree file \"" << rawFile->name << "\": " << outLen << "\n"; - return; - } - - 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 = inflateInit2(&zs, -DEF_WBITS); - - if (ret != Z_OK) - { - throw std::runtime_error("Initializing inflate failed"); - } - - zs.next_in = reinterpret_cast(&rawFile->buffer[4]); - zs.avail_in = inLen - sizeof(uint32_t); - - 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) - { - std::cerr << "Inflate failed for dumping animtree file \"" << rawFile->name << "\"\n"; - inflateEnd(&zs); - return; - } - - const auto inflateOutSize = sizeof(buffer) - zs.avail_out; - - stream.write(reinterpret_cast(buffer), inflateOutSize); - } - - inflateEnd(&zs); -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const fs::path rawFilePath(rawFile->name); - const auto extension = rawFilePath.extension().string(); - - if (extension == ".atr") - { - DumpAnimtree(context, asset, stream); - } - else - { - stream.write(rawFile->buffer, rawFile->len); - } -} diff --git a/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.cpp b/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.cpp new file mode 100644 index 00000000..b456eb9c --- /dev/null +++ b/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.cpp @@ -0,0 +1,104 @@ +#include "RawFileDumperT6.h" + +#include +#include +#include + +using namespace T6; + +namespace fs = std::filesystem; + +namespace +{ + constexpr size_t ANIMTREE_MAX_SIZE = 0xC000000; + + void DumpAnimtree(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream) + { + const auto* rawFile = asset->Asset(); + + if (rawFile->len <= 4) + { + std::cerr << "Invalid len of animtree file \"" << rawFile->name << "\"\n"; + return; + } + + const auto outLen = reinterpret_cast(rawFile->buffer)[0]; + const auto inLen = rawFile->len; + + if (outLen > ANIMTREE_MAX_SIZE) + { + std::cerr << "Invalid size of animtree file \"" << rawFile->name << "\": " << outLen << "\n"; + return; + } + + 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 = inflateInit2(&zs, -DEF_WBITS); + + if (ret != Z_OK) + { + throw std::runtime_error("Initializing inflate failed"); + } + + zs.next_in = reinterpret_cast(&rawFile->buffer[4]); + zs.avail_in = inLen - sizeof(uint32_t); + + 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) + { + std::cerr << "Inflate failed for dumping animtree file \"" << rawFile->name << "\"\n"; + inflateEnd(&zs); + return; + } + + const auto inflateOutSize = sizeof(buffer) - zs.avail_out; + + stream.write(reinterpret_cast(buffer), inflateOutSize); + } + + inflateEnd(&zs); + } +} // namespace + +namespace T6::raw_file +{ + bool Dumper::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void Dumper::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const fs::path rawFilePath(rawFile->name); + const auto extension = rawFilePath.extension().string(); + + if (extension == ".atr") + { + DumpAnimtree(context, asset, stream); + } + else + { + stream.write(rawFile->buffer, rawFile->len); + } + } +} // namespace T6::raw_file diff --git a/src/ObjWriting/Game/T6/RawFile/AssetDumperRawFile.h b/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.h similarity index 52% rename from src/ObjWriting/Game/T6/RawFile/AssetDumperRawFile.h rename to src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.h index 1f9f033f..b784a1f2 100644 --- a/src/ObjWriting/Game/T6/RawFile/AssetDumperRawFile.h +++ b/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.h @@ -3,14 +3,10 @@ #include "Dumping/AbstractAssetDumper.h" #include "Game/T6/T6.h" -namespace T6 +namespace T6::raw_file { - class AssetDumperRawFile final : public AbstractAssetDumper + class Dumper final : public AbstractAssetDumper { - constexpr static size_t ANIMTREE_MAX_SIZE = 0xC000000; - - void DumpAnimtree(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream); - protected: bool ShouldDump(XAssetInfo* asset) override; void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override;