From b126333d49129658b1b9f676b1c506b79ef8b13a Mon Sep 17 00:00:00 2001 From: Razmoth <32140579+Razmoth@users.noreply.github.com> Date: Sat, 9 Dec 2023 12:26:39 +0400 Subject: [PATCH] Implement `Zstd` support (#1125) * Implement `Zstd` support. * Implement requested changes --- .../AssetRipper.IO.Files.csproj | 1 + .../FileStream/BundleFileBlockReader.cs | 9 +++++- .../BundleFiles/ZstdCompression.cs | 28 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 Source/AssetRipper.IO.Files/BundleFiles/ZstdCompression.cs diff --git a/Source/AssetRipper.IO.Files/AssetRipper.IO.Files.csproj b/Source/AssetRipper.IO.Files/AssetRipper.IO.Files.csproj index f81b0e398..674d0b212 100644 --- a/Source/AssetRipper.IO.Files/AssetRipper.IO.Files.csproj +++ b/Source/AssetRipper.IO.Files/AssetRipper.IO.Files.csproj @@ -10,6 +10,7 @@ + diff --git a/Source/AssetRipper.IO.Files/BundleFiles/FileStream/BundleFileBlockReader.cs b/Source/AssetRipper.IO.Files/BundleFiles/FileStream/BundleFileBlockReader.cs index e6ccd5ed3..9b1f68b16 100644 --- a/Source/AssetRipper.IO.Files/BundleFiles/FileStream/BundleFileBlockReader.cs +++ b/Source/AssetRipper.IO.Files/BundleFiles/FileStream/BundleFileBlockReader.cs @@ -107,7 +107,14 @@ namespace AssetRipper.IO.Files.BundleFiles.FileStream break; default: - UnsupportedBundleDecompression.Throw(entry.PathFixed, compressType); + if (ZstdCompression.IsZstd(m_stream)) + { + ZstdCompression.DecompressStream(m_stream, block.CompressedSize, m_cachedBlockStream, block.UncompressedSize); + } + else + { + UnsupportedBundleDecompression.Throw(entry.PathFixed, compressType); + } break; } blockStream = m_cachedBlockStream; diff --git a/Source/AssetRipper.IO.Files/BundleFiles/ZstdCompression.cs b/Source/AssetRipper.IO.Files/BundleFiles/ZstdCompression.cs new file mode 100644 index 000000000..b9ecd0fc4 --- /dev/null +++ b/Source/AssetRipper.IO.Files/BundleFiles/ZstdCompression.cs @@ -0,0 +1,28 @@ +using AssetRipper.IO.Files.Streams; +using ZstdSharp; + +namespace AssetRipper.IO.Files.BundleFiles +{ + public static class ZstdCompression + { + private static readonly byte[] Signature = [0x28, 0xB5, 0x2F, 0xFD]; + public static bool IsZstd(Stream Stream) + { + Span buffer = stackalloc byte[4]; + + long pos = Stream.Position; + Stream.ReadExactly(buffer); + Stream.Position = pos; + + return buffer.SequenceEqual(Signature); + } + + public static void DecompressStream(Stream compressedStream, long compressedSize, Stream decompressedStream, long decompressedSize) + { + using PartialStream compressedPartialStream = new PartialStream(compressedStream, compressedStream.Position, compressedSize, true); + using PartialStream decompressedPartialStream = new PartialStream(decompressedStream, decompressedStream.Position, decompressedSize, true); + using DecompressionStream zstdStream = new DecompressionStream(compressedPartialStream); + zstdStream.CopyTo(decompressedPartialStream); + } + } +}