From e544d043bda7f4362d3275cbf9cc2f91302901b5 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 24 Jul 2021 13:51:41 +0200 Subject: [PATCH] Fix rawfile dumping and loading for iw5 --- .../IW5/AssetLoaders/AssetLoaderRawFile.cpp | 50 +++++++++++--- .../IW5/AssetLoaders/AssetLoaderRawFile.h | 2 + .../IW5/AssetDumpers/AssetDumperRawFile.cpp | 67 +++++++++---------- 3 files changed, 75 insertions(+), 44 deletions(-) diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.cpp index 8a866f1d..41912d7a 100644 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.cpp +++ b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.cpp @@ -1,6 +1,9 @@ #include "AssetLoaderRawFile.h" #include +#include +#include +#include #include "Game/IW5/IW5.h" #include "Pool/GlobalAssetPool.h" @@ -26,17 +29,48 @@ bool AssetLoaderRawFile::LoadFromRaw(const std::string& assetName, ISearchPath* if (!file.IsOpen()) return false; - auto* rawFile = memory->Create(); - rawFile->name = memory->Dup(assetName.c_str()); - rawFile->compressedLen = static_cast(file.m_length + 1); - - auto* fileBuffer = static_cast(memory->Alloc(static_cast(file.m_length + 1))); - file.m_stream->read(fileBuffer, file.m_length); + const auto uncompressedBuffer = std::make_unique(static_cast(file.m_length)); + file.m_stream->read(uncompressedBuffer.get(), file.m_length); if (file.m_stream->gcount() != file.m_length) return false; - fileBuffer[file.m_length] = '\0'; - rawFile->buffer = fileBuffer; + const auto compressionBufferSize = static_cast(file.m_length + COMPRESSED_BUFFER_SIZE_PADDING); + auto* compressedBuffer = static_cast(memory->Alloc(compressionBufferSize)); + + z_stream_s zs{}; + + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = static_cast(file.m_length); + zs.avail_out = compressionBufferSize; + zs.next_in = reinterpret_cast(uncompressedBuffer.get()); + zs.next_out = reinterpret_cast(compressedBuffer); + + int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION); + + if (ret != Z_OK) + { + throw std::runtime_error("Initializing deflate failed"); + } + + ret = deflate(&zs, Z_FINISH); + + if (ret != Z_STREAM_END) + { + std::cout << "Deflate failed for loading rawfile \"" << assetName << "\"" << std::endl; + deflateEnd(&zs); + return false; + } + + const auto compressedSize = compressionBufferSize - zs.avail_out; + + auto* rawFile = memory->Create(); + rawFile->name = memory->Dup(assetName.c_str()); + rawFile->compressedLen = static_cast(compressedSize); + rawFile->len = static_cast(file.m_length); + rawFile->buffer = static_cast(compressedBuffer); + manager->AddAsset(ASSET_TYPE_RAWFILE, assetName, rawFile); return true; diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.h index b5d4f9e3..da6fe90a 100644 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.h +++ b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.h @@ -8,6 +8,8 @@ namespace IW5 { class AssetLoaderRawFile final : public BasicAssetLoader { + static constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64; + public: _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD bool CanLoadFromRaw() const override; diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.cpp index a37ff468..2435ec66 100644 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.cpp +++ b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.cpp @@ -37,48 +37,43 @@ std::string AssetDumperRawFile::GetFileNameForAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* rawFile = asset->Asset(); - if (rawFile->compressedLen > 0) + 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) { - z_stream_s zs{}; + throw std::runtime_error("Initializing inflate failed"); + } - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = 0; - zs.next_in = Z_NULL; + zs.next_in = reinterpret_cast(rawFile->buffer); + zs.avail_in = rawFile->compressedLen; - int ret = inflateInit(&zs); + Bytef buffer[0x1000]; - if (ret != Z_OK) + while (zs.avail_in > 0) + { + zs.next_out = buffer; + zs.avail_out = sizeof buffer; + ret = inflate(&zs, Z_SYNC_FLUSH); + + if (ret < 0) { - throw std::runtime_error("Initializing inflate failed"); + printf("Inflate failed for dumping rawfile '%s'\n", rawFile->name); + inflateEnd(&zs); + return; } - 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) - { - printf("Inflate failed for dumping rawfile '%s'\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->buffer, rawFile->len); + stream.write(reinterpret_cast(buffer), sizeof buffer - zs.avail_out); } + + inflateEnd(&zs); }