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);
+ }
+ }
+}