diff --git a/AssetStudio.PInvoke/DllLoader.cs b/AssetStudio.PInvoke/DllLoader.cs index 347ea0a..5ae21b3 100644 --- a/AssetStudio.PInvoke/DllLoader.cs +++ b/AssetStudio.PInvoke/DllLoader.cs @@ -11,7 +11,7 @@ namespace AssetStudio.PInvoke { public static void PreloadDll(string dllName) { - var localPath = Process.GetCurrentProcess().MainModule.FileName; + var localPath = Process.GetCurrentProcess().MainModule?.FileName; var localDir = Path.GetDirectoryName(localPath); // Not using OperatingSystem.Platform. @@ -35,7 +35,6 @@ namespace AssetStudio.PInvoke private static class Win32 { - internal static void LoadDll(string dllDir, string dllName) { var dllFileName = $"{dllName}.dll"; diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj index eded92c..e63d987 100644 --- a/AssetStudio/AssetStudio.csproj +++ b/AssetStudio/AssetStudio.csproj @@ -16,6 +16,8 @@ + + diff --git a/AssetStudio/AssetsManager.cs b/AssetStudio/AssetsManager.cs index f871877..2082c44 100644 --- a/AssetStudio/AssetsManager.cs +++ b/AssetStudio/AssetsManager.cs @@ -13,8 +13,9 @@ namespace AssetStudio { public class AssetsManager { - public bool ZstdEnabled = true; public bool LoadingViaTypeTreeEnabled = true; + public CompressionType CustomBlockCompression = CompressionType.Auto; + public CompressionType CustomBlockInfoCompression = CompressionType.Auto; public List assetsFileList = new List(); internal Dictionary assetsFileIndexCache = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -177,7 +178,10 @@ namespace AssetStudio private bool LoadFile(FileReader reader) { - switch (reader?.FileType) + if (reader == null) + return false; + + switch (reader.FileType) { case FileType.AssetsFile: return LoadAssetsFile(reader); @@ -306,7 +310,7 @@ namespace AssetStudio try { - var bundleFile = new BundleFile(bundleReader, ZstdEnabled, specifiedUnityVersion); + var bundleFile = new BundleFile(bundleReader, CustomBlockInfoCompression, CustomBlockCompression, specifiedUnityVersion); var isLoaded = LoadBundleFiles(bundleReader, bundleFile, originalPath); if (!isLoaded) return false; @@ -322,7 +326,7 @@ namespace AssetStudio bundleReader.FileName = $"{reader.FileName}_0x{bundleStream.Offset:X}"; } Logger.Info($"[MultiBundle] Loading \"{reader.FileName}\" from offset: 0x{bundleStream.Offset:X}"); - bundleFile = new BundleFile(bundleReader, ZstdEnabled, specifiedUnityVersion); + bundleFile = new BundleFile(bundleReader, CustomBlockInfoCompression, CustomBlockCompression, specifiedUnityVersion); isLoaded = LoadBundleFiles(bundleReader, bundleFile, originalPath ?? reader.FullPath); } return isLoaded; diff --git a/AssetStudio/BundleCompression/Oodle/Oodle.cs b/AssetStudio/BundleCompression/Oodle/Oodle.cs new file mode 100644 index 0000000..b074a69 --- /dev/null +++ b/AssetStudio/BundleCompression/Oodle/Oodle.cs @@ -0,0 +1,43 @@ +using System; +using System.Runtime.InteropServices; +#if NETFRAMEWORK +using AssetStudio.PInvoke; +#endif + +namespace BundleCompression.Oodle +{ + public static class OodleLZ + { + private const string LibName = "ooz"; + +#if NETFRAMEWORK + static OodleLZ() + { + DllLoader.PreloadDll(LibName); + } +#endif + + [DllImport(LibName)] + private static extern int Ooz_Decompress( + in byte srcBuffer, + UIntPtr srcLen, + ref byte dstBuffer, + UIntPtr dstLen, + int fuzzSafetyFlag, + int crcCheckFlag, + int logVerbosityFlag, + UIntPtr rawBuffer, + UIntPtr rawBufferSize, + UIntPtr chunkDecodeCallback, + UIntPtr chunkDecodeContext, + UIntPtr scratchBuf, + UIntPtr scratchBufSize, + int threadPhase); + + public static int Decompress(ReadOnlySpan srcSpanBuffer, Span dstSpanBuffer) + { + return Ooz_Decompress(in srcSpanBuffer[0], (UIntPtr)srcSpanBuffer.Length, ref dstSpanBuffer[0], (UIntPtr)dstSpanBuffer.Length, + 0, 0, 0, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, 0); + } + } +} diff --git a/AssetStudio/7zip/Common/CRC.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Common/CRC.cs similarity index 100% rename from AssetStudio/7zip/Common/CRC.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Common/CRC.cs diff --git a/AssetStudio/7zip/Common/CommandLineParser.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Common/CommandLineParser.cs similarity index 100% rename from AssetStudio/7zip/Common/CommandLineParser.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Common/CommandLineParser.cs diff --git a/AssetStudio/7zip/Common/InBuffer.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Common/InBuffer.cs similarity index 100% rename from AssetStudio/7zip/Common/InBuffer.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Common/InBuffer.cs diff --git a/AssetStudio/7zip/Common/OutBuffer.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Common/OutBuffer.cs similarity index 100% rename from AssetStudio/7zip/Common/OutBuffer.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Common/OutBuffer.cs diff --git a/AssetStudio/7zip/Compress/LZ/IMatchFinder.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZ/IMatchFinder.cs similarity index 100% rename from AssetStudio/7zip/Compress/LZ/IMatchFinder.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZ/IMatchFinder.cs diff --git a/AssetStudio/7zip/Compress/LZ/LzBinTree.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZ/LzBinTree.cs similarity index 100% rename from AssetStudio/7zip/Compress/LZ/LzBinTree.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZ/LzBinTree.cs diff --git a/AssetStudio/7zip/Compress/LZ/LzInWindow.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZ/LzInWindow.cs similarity index 100% rename from AssetStudio/7zip/Compress/LZ/LzInWindow.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZ/LzInWindow.cs diff --git a/AssetStudio/7zip/Compress/LZ/LzOutWindow.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZ/LzOutWindow.cs similarity index 100% rename from AssetStudio/7zip/Compress/LZ/LzOutWindow.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZ/LzOutWindow.cs diff --git a/AssetStudio/7zip/Compress/LZMA/LzmaBase.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZMA/LzmaBase.cs similarity index 100% rename from AssetStudio/7zip/Compress/LZMA/LzmaBase.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZMA/LzmaBase.cs diff --git a/AssetStudio/7zip/Compress/LZMA/LzmaDecoder.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZMA/LzmaDecoder.cs similarity index 100% rename from AssetStudio/7zip/Compress/LZMA/LzmaDecoder.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZMA/LzmaDecoder.cs diff --git a/AssetStudio/7zip/Compress/LZMA/LzmaEncoder.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZMA/LzmaEncoder.cs similarity index 100% rename from AssetStudio/7zip/Compress/LZMA/LzmaEncoder.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/LZMA/LzmaEncoder.cs diff --git a/AssetStudio/7zip/Compress/RangeCoder/RangeCoder.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/RangeCoder/RangeCoder.cs similarity index 100% rename from AssetStudio/7zip/Compress/RangeCoder/RangeCoder.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/RangeCoder/RangeCoder.cs diff --git a/AssetStudio/7zip/Compress/RangeCoder/RangeCoderBit.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/RangeCoder/RangeCoderBit.cs similarity index 100% rename from AssetStudio/7zip/Compress/RangeCoder/RangeCoderBit.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/RangeCoder/RangeCoderBit.cs diff --git a/AssetStudio/7zip/Compress/RangeCoder/RangeCoderBitTree.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/RangeCoder/RangeCoderBitTree.cs similarity index 100% rename from AssetStudio/7zip/Compress/RangeCoder/RangeCoderBitTree.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/Compress/RangeCoder/RangeCoderBitTree.cs diff --git a/AssetStudio/7zip/ICoder.cs b/AssetStudio/BundleCompression/SevenZipLzma/7zip/ICoder.cs similarity index 100% rename from AssetStudio/7zip/ICoder.cs rename to AssetStudio/BundleCompression/SevenZipLzma/7zip/ICoder.cs diff --git a/AssetStudio/SevenZipHelper.cs b/AssetStudio/BundleCompression/SevenZipLzma/SevenZipLzma.cs similarity index 86% rename from AssetStudio/SevenZipHelper.cs rename to AssetStudio/BundleCompression/SevenZipLzma/SevenZipLzma.cs index b06edd3..03adabc 100644 --- a/AssetStudio/SevenZipHelper.cs +++ b/AssetStudio/BundleCompression/SevenZipLzma/SevenZipLzma.cs @@ -2,12 +2,11 @@ using System; using System.IO; using SevenZip.Compression.LZMA; - -namespace AssetStudio +namespace BundleCompression.Lzma { - public static class SevenZipHelper + public static class SevenZipLzma { - public static MemoryStream StreamDecompress(MemoryStream inStream) + public static MemoryStream DecompressStream(MemoryStream inStream) { var decoder = new Decoder(); @@ -34,7 +33,7 @@ namespace AssetStudio return newOutStream; } - public static void StreamDecompress(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize) + public static long DecompressStream(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize) { var basePosition = compressedStream.Position; var decoder = new Decoder(); @@ -44,6 +43,7 @@ namespace AssetStudio decoder.SetDecoderProperties(properties); decoder.Code(compressedStream, decompressedStream, compressedSize - 5, decompressedSize, null); compressedStream.Position = basePosition + compressedSize; + return decompressedStream.Position; } } } diff --git a/AssetStudio/BundleDecompressionHelper.cs b/AssetStudio/BundleDecompressionHelper.cs new file mode 100644 index 0000000..f5409b1 --- /dev/null +++ b/AssetStudio/BundleDecompressionHelper.cs @@ -0,0 +1,65 @@ +using BundleCompression.Lzma; +using BundleCompression.Oodle; +using System; +using System.IO; +using System.Text.RegularExpressions; +using K4os.Compression.LZ4; +using ZstdSharp; + +namespace AssetStudio +{ + public static class BundleDecompressionHelper + { + private static readonly Decompressor ZstdDecompressor = new Decompressor(); + private static readonly string MsgPattern = @"\. "; + + public static MemoryStream DecompressLzmaStream(MemoryStream inStream) + { + return SevenZipLzma.DecompressStream(inStream); + } + + public static long DecompressLzmaStream(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize, ref string errorMsg) + { + var numWrite = -1L; + try + { + numWrite = SevenZipLzma.DecompressStream(compressedStream, decompressedStream, compressedSize, decompressedSize); + } + catch (Exception e) + { + Logger.Debug(e.ToString()); + errorMsg = $"({Regex.Split(e.Message, MsgPattern, RegexOptions.CultureInvariant)[0]})"; + } + return numWrite; + } + + public static int DecompressBlock(CompressionType type, ReadOnlySpan srcBuffer, Span dstBuffer, ref string errorMsg) + { + var numWrite = -1; + try + { + switch (type) + { + case CompressionType.Lz4: + case CompressionType.Lz4HC: + numWrite = LZ4Codec.Decode(srcBuffer, dstBuffer); + break; + case CompressionType.Zstd: + numWrite = ZstdDecompressor.Unwrap(srcBuffer, dstBuffer); + break; + case CompressionType.Oodle: + numWrite = OodleLZ.Decompress(srcBuffer, dstBuffer); + break; + default: + throw new NotSupportedException(); + } + } + catch (Exception e) + { + Logger.Debug(e.ToString()); + errorMsg = $"({Regex.Split(e.Message, MsgPattern, RegexOptions.CultureInvariant)[0]})"; + } + return numWrite; + } + } +} diff --git a/AssetStudio/BundleFile.cs b/AssetStudio/BundleFile.cs index 70a3074..db06be2 100644 --- a/AssetStudio/BundleFile.cs +++ b/AssetStudio/BundleFile.cs @@ -1,6 +1,4 @@ -using K4os.Compression.LZ4; -using ZstdSharp; -using System; +using System; using System.IO; using System.Linq; @@ -32,12 +30,14 @@ namespace AssetStudio public enum CompressionType { + Auto = -1, None, Lzma, Lz4, Lz4HC, Lzham, - Custom, + Zstd, //custom + Oodle, //custom } public class BundleFile @@ -77,7 +77,7 @@ namespace AssetStudio public StreamFile[] fileList; - public BundleFile(FileReader reader, bool useZstd, UnityVersion specUnityVer = null) + public BundleFile(FileReader reader, CompressionType customBlockInfoCompression, CompressionType customBlockCompression, UnityVersion specUnityVer = null) { m_Header = new Header(); m_Header.signature = reader.ReadStringToNull(); @@ -152,10 +152,10 @@ namespace AssetStudio throw new NotSupportedException(msg); } - ReadBlocksInfoAndDirectory(reader, unityVer); + ReadBlocksInfoAndDirectory(reader, customBlockInfoCompression, unityVer); using (var blocksStream = CreateBlocksStream(reader.FullPath)) { - ReadBlocks(reader, blocksStream, useZstd); + ReadBlocks(reader, customBlockCompression, blocksStream); ReadFiles(blocksStream, reader.FullPath); } break; @@ -224,7 +224,7 @@ namespace AssetStudio { using (var memoryStream = new MemoryStream(uncompressedBytes)) { - using (var decompressStream = SevenZipHelper.StreamDecompress(memoryStream)) + using (var decompressStream = BundleDecompressionHelper.DecompressLzmaStream(memoryStream)) { uncompressedBytes = decompressStream.ToArray(); } @@ -287,7 +287,7 @@ namespace AssetStudio } } - private void ReadBlocksInfoAndDirectory(FileReader reader, UnityVersion unityVer) + private void ReadBlocksInfoAndDirectory(FileReader reader, CompressionType customBlockInfoCompression, UnityVersion unityVer, bool silent = false) { byte[] blocksInfoBytes; @@ -308,52 +308,82 @@ namespace AssetStudio } } + var compressedSize = (int)m_Header.compressedBlocksInfoSize; + var uncompressedSize = (int)m_Header.uncompressedBlocksInfoSize; if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0) { var position = reader.Position; - reader.Position = m_Header.size - m_Header.compressedBlocksInfoSize; - blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); + reader.Position = m_Header.size - compressedSize; + blocksInfoBytes = reader.ReadBytes(compressedSize); reader.Position = position; } else //0x40 BlocksAndDirectoryInfoCombined { - blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); + blocksInfoBytes = reader.ReadBytes(compressedSize); } - MemoryStream blocksInfoUncompressedStream; - var uncompressedSize = m_Header.uncompressedBlocksInfoSize; + var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask); + if (customBlockInfoCompression == CompressionType.Auto) + { + if (!silent && compressionType > CompressionType.Lzham && Enum.IsDefined(typeof(CompressionType), compressionType)) + { + Logger.Warning($"Non-standard blockInfo compression type: {(int)compressionType}. Trying to decompress as {compressionType} archive.."); + } + } + else if (compressionType != CompressionType.None) + { + compressionType = customBlockInfoCompression; + if (!silent) + { + Logger.Info($"Custom blockInfo compression type: {customBlockInfoCompression}"); + } + } + Logger.Debug($"BlockInfo compression: {compressionType}"); + + int numWrite; + var errorMsg = string.Empty; + MemoryStream blocksInfoUncompressedStream; switch (compressionType) { case CompressionType.None: { blocksInfoUncompressedStream = new MemoryStream(blocksInfoBytes); + numWrite = compressedSize; break; } case CompressionType.Lzma: { - blocksInfoUncompressedStream = new MemoryStream((int) (uncompressedSize)); + blocksInfoUncompressedStream = new MemoryStream(uncompressedSize); using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes)) { - SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompressedStream, - m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize); + numWrite = (int)BundleDecompressionHelper.DecompressLzmaStream(blocksInfoCompressedStream, blocksInfoUncompressedStream, compressedSize, uncompressedSize, ref errorMsg); } blocksInfoUncompressedStream.Position = 0; break; } case CompressionType.Lz4: case CompressionType.Lz4HC: + case CompressionType.Zstd: + case CompressionType.Oodle: { var uncompressedBytes = new byte[uncompressedSize]; - var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes); - if (numWrite != uncompressedSize) - { - throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes"); - } + numWrite = BundleDecompressionHelper.DecompressBlock(compressionType, blocksInfoBytes, uncompressedBytes, ref errorMsg); blocksInfoUncompressedStream = new MemoryStream(uncompressedBytes); break; } + case CompressionType.Lzham: + throw new IOException($"Unsupported blockInfo compression type: {compressionType}.\n"); default: - throw new IOException($"Unsupported block info compression type {compressionType}"); + throw new IOException($"Unknown blockInfo compression type: {compressionType}.\nYou may try to specify the compression type manually.\n"); + } + + if (numWrite != uncompressedSize) + { + var msg = $"{compressionType} blockInfo decompression error. {errorMsg}\nWrite {numWrite} bytes but expected {uncompressedSize} bytes."; + var exMsg = compressionType > CompressionType.Lz4HC + ? "Wrong compression type or blockInfo data might be encrypted." + : "BlockInfo data might be encrypted."; + throw new IOException($"{msg}\n{exMsg}\n"); } using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompressedStream)) @@ -390,62 +420,65 @@ namespace AssetStudio } } - private void ReadBlocks(FileReader reader, Stream blocksStream, bool useZstd) + private void ReadBlocks(FileReader reader, CompressionType customBlockCompression, Stream blocksStream) { - var zstdCodec = new Decompressor(); - var i = 0; + var showCustomTypeWarning = true; foreach (var blockInfo in m_BlocksInfo) { var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask); + if (customBlockCompression == CompressionType.Auto) + { + if (showCustomTypeWarning && compressionType > CompressionType.Lzham && Enum.IsDefined(typeof(CompressionType), compressionType)) + { + Logger.Warning($"Non-standard block compression type: {(int)compressionType}. Trying to decompress as {compressionType} archive.."); + showCustomTypeWarning = false; + } + } + else if (compressionType != CompressionType.None) + { + compressionType = customBlockCompression; + if (showCustomTypeWarning) + { + Logger.Info($"Custom block compression type: {customBlockCompression}"); + showCustomTypeWarning = false; + } + } + Logger.Debug($"Block compression: {compressionType}"); + + long numWrite; + var errorMsg = string.Empty; switch (compressionType) { case CompressionType.None: { reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize); + numWrite = blockInfo.compressedSize; break; } case CompressionType.Lzma: { - SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize); + numWrite = BundleDecompressionHelper.DecompressLzmaStream(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize, ref errorMsg); break; } case CompressionType.Lz4: case CompressionType.Lz4HC: - case CompressionType.Custom: + case CompressionType.Zstd: + case CompressionType.Oodle: { var compressedSize = (int)blockInfo.compressedSize; - var compressedBytes = BigArrayPool.Shared.Rent(compressedSize); - _ = reader.Read(compressedBytes, 0, compressedSize); var uncompressedSize = (int)blockInfo.uncompressedSize; + + var compressedBytes = BigArrayPool.Shared.Rent(compressedSize); var uncompressedBytes = BigArrayPool.Shared.Rent(uncompressedSize); try { - var compTypeStr = compressionType.ToString(); - if (compressionType == CompressionType.Custom) - { - compTypeStr = useZstd ? "Zstd" : "Lz4"; - if (i == 0) - { - Logger.Debug($"Custom block compression type was detected. Trying to decompress as {compTypeStr} archive.."); - i++; - } - } + _ = reader.Read(compressedBytes, 0, compressedSize); + var compressedSpan = new ReadOnlySpan(compressedBytes, 0, compressedSize); + var uncompressedSpan = new Span(uncompressedBytes, 0, uncompressedSize); - int numWrite; - if (compressionType == CompressionType.Custom && useZstd) - { - numWrite = zstdCodec.Unwrap(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize); - } - else - { - numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize); - } - - if (numWrite != uncompressedSize) - { - throw new IOException($"{compTypeStr} block decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes"); - } - blocksStream.Write(uncompressedBytes, 0, uncompressedSize); + numWrite = BundleDecompressionHelper.DecompressBlock(compressionType, compressedSpan, uncompressedSpan, ref errorMsg); + if (numWrite == uncompressedSize) + blocksStream.Write(uncompressedBytes, 0, uncompressedSize); } finally { @@ -454,8 +487,19 @@ namespace AssetStudio } break; } + case CompressionType.Lzham: + throw new IOException($"Unsupported block compression type: {compressionType}.\n"); default: - throw new IOException($"Unsupported block compression type {compressionType}"); + throw new IOException($"Unknown block compression type: {compressionType}.\nYou may try to specify the compression type manually.\n"); + } + + if (numWrite != blockInfo.uncompressedSize) + { + var msg = $"{compressionType} block decompression error. {errorMsg}\nWrite {numWrite} bytes but expected {blockInfo.uncompressedSize} bytes."; + var exMsg = compressionType > CompressionType.Lz4HC + ? "Wrong compression type or block data might be encrypted." + : "Block data might be encrypted."; + throw new IOException($"{msg}\n{exMsg}\n"); } } blocksStream.Position = 0; diff --git a/AssetStudioCLI/AssetStudioCLI.csproj b/AssetStudioCLI/AssetStudioCLI.csproj index d8d274c..58fb8c4 100644 --- a/AssetStudioCLI/AssetStudioCLI.csproj +++ b/AssetStudioCLI/AssetStudioCLI.csproj @@ -30,6 +30,8 @@ + + @@ -37,12 +39,20 @@ + + + + + + + + @@ -56,6 +66,8 @@ + + @@ -63,12 +75,20 @@ + + + + + + + + @@ -77,6 +97,7 @@ + @@ -84,6 +105,7 @@ + @@ -91,6 +113,7 @@ + @@ -107,36 +130,42 @@ + + + + + + diff --git a/AssetStudioCLI/Libraries/linux-arm64/libooz.so b/AssetStudioCLI/Libraries/linux-arm64/libooz.so new file mode 100644 index 0000000..dbbe0d6 Binary files /dev/null and b/AssetStudioCLI/Libraries/linux-arm64/libooz.so differ diff --git a/AssetStudioCLI/Libraries/linux-x64/libooz.so b/AssetStudioCLI/Libraries/linux-x64/libooz.so new file mode 100644 index 0000000..b9b2f0e Binary files /dev/null and b/AssetStudioCLI/Libraries/linux-x64/libooz.so differ diff --git a/AssetStudioCLI/Libraries/linux-x86/libooz.so b/AssetStudioCLI/Libraries/linux-x86/libooz.so new file mode 100644 index 0000000..45920ad Binary files /dev/null and b/AssetStudioCLI/Libraries/linux-x86/libooz.so differ diff --git a/AssetStudioCLI/Libraries/osx-arm64/libooz.dylib b/AssetStudioCLI/Libraries/osx-arm64/libooz.dylib new file mode 100644 index 0000000..cb813b2 Binary files /dev/null and b/AssetStudioCLI/Libraries/osx-arm64/libooz.dylib differ diff --git a/AssetStudioCLI/Libraries/osx-x64/libooz.dylib b/AssetStudioCLI/Libraries/osx-x64/libooz.dylib new file mode 100644 index 0000000..f013314 Binary files /dev/null and b/AssetStudioCLI/Libraries/osx-x64/libooz.dylib differ diff --git a/AssetStudioCLI/Libraries/win-x64/ooz.dll b/AssetStudioCLI/Libraries/win-x64/ooz.dll new file mode 100644 index 0000000..fe0dc09 Binary files /dev/null and b/AssetStudioCLI/Libraries/win-x64/ooz.dll differ diff --git a/AssetStudioCLI/Libraries/win-x86/ooz.dll b/AssetStudioCLI/Libraries/win-x86/ooz.dll new file mode 100644 index 0000000..0629ec4 Binary files /dev/null and b/AssetStudioCLI/Libraries/win-x86/ooz.dll differ diff --git a/AssetStudioCLI/Options/CLIOptions.cs b/AssetStudioCLI/Options/CLIOptions.cs index 95216af..70bfec7 100644 --- a/AssetStudioCLI/Options/CLIOptions.cs +++ b/AssetStudioCLI/Options/CLIOptions.cs @@ -68,12 +68,6 @@ namespace AssetStudioCLI.Options NameAndContainer, } - internal enum CustomCompressionType - { - Zstd, - Lz4, - } - internal static class CLIOptions { public static bool isParsed; @@ -115,7 +109,8 @@ namespace AssetStudioCLI.Options public static Option> o_filterByPathID; public static Option> o_filterByText; //advanced - public static Option o_customCompressionType; + public static Option o_bundleBlockInfoCompression; + public static Option o_bundleBlockCompression; public static Option o_maxParallelExportTasks; public static Option o_exportAssetList; public static Option o_assemblyPath; @@ -425,15 +420,33 @@ namespace AssetStudioCLI.Options #endregion #region Init Advanced Options - o_customCompressionType = new GroupedOption + o_bundleBlockInfoCompression = new GroupedOption ( - optionDefaultValue: CustomCompressionType.Zstd, - optionName: "--custom-compression ", - optionDescription: "Specify the compression type for assets that use custom compression\n" + - "\n" + + optionDefaultValue: CompressionType.Auto, + optionName: "--blockinfo-comp ", + optionDescription: "Specify the compression type of bundle's blockInfo data\n" + + "\n" + + "Auto - Use compression type specified in an asset bundle\n" + "Zstd - Try to decompress as zstd archive\n" + - "Lz4 - Try to decompress as lz4 archive\n", - optionExample: "Example: \"--custom-compression lz4\"\n", + "Oodle - Try to decompress as oodle archive\n" + + "Lz4 - Try to decompress as lz4/lz4hc archive\n" + + "Lzma - Try to decompress as lzma archive\n", + optionExample: "Example: \"--blockinfo-comp lz4\"\n", + optionHelpGroup: HelpGroups.Advanced + ); + + o_bundleBlockCompression = new GroupedOption + ( + optionDefaultValue: CompressionType.Auto, + optionName: "--block-comp ", + optionDescription: "Specify the compression type of bundle's block data\n" + + "\n" + + "Auto - Use compression type specified in an asset bundle\n" + + "Zstd - Try to decompress as zstd archive\n" + + "Oodle - Try to decompress as oodle archive\n" + + "Lz4 - Try to decompress as lz4/lz4hc archive\n" + + "Lzma - Try to decompress as lzma archive\n", + optionExample: "Example: \"--block-comp zstd\"\n", optionHelpGroup: HelpGroups.Advanced ); @@ -975,19 +988,53 @@ namespace AssetStudioCLI.Options } break; } - case "--custom-compression": + case "--blockinfo-comp": switch (value.ToLower()) { + case "auto": + o_bundleBlockInfoCompression.Value = CompressionType.Zstd; + break; case "zstd": - o_customCompressionType.Value = CustomCompressionType.Zstd; + o_bundleBlockInfoCompression.Value = CompressionType.Zstd; + break; + case "oodle": + o_bundleBlockInfoCompression.Value = CompressionType.Oodle; break; case "lz4": case "lz4hc": - o_customCompressionType.Value = CustomCompressionType.Lz4; + o_bundleBlockInfoCompression.Value = CompressionType.Lz4HC; + break; + case "lzma": + o_bundleBlockInfoCompression.Value = CompressionType.Lzma; break; default: Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option.Color(brightYellow)}] option. Unsupported compression type: [{value.Color(brightRed)}].\n"); - ShowOptionDescription(o_customCompressionType); + ShowOptionDescription(o_bundleBlockInfoCompression); + return; + } + break; + case "--block-comp": + switch (value.ToLower()) + { + case "auto": + o_bundleBlockCompression.Value = CompressionType.Zstd; + break; + case "zstd": + o_bundleBlockCompression.Value = CompressionType.Zstd; + break; + case "oodle": + o_bundleBlockCompression.Value = CompressionType.Oodle; + break; + case "lz4": + case "lz4hc": + o_bundleBlockCompression.Value = CompressionType.Lz4HC; + break; + case "lzma": + o_bundleBlockCompression.Value = CompressionType.Lzma; + break; + default: + Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option.Color(brightYellow)}] option. Unsupported compression type: [{value.Color(brightRed)}].\n"); + ShowOptionDescription(o_bundleBlockCompression); return; } break; @@ -1235,10 +1282,6 @@ namespace AssetStudioCLI.Options var sb = new StringBuilder(); sb.AppendLine("[Current Options]"); sb.AppendLine($"# Working Mode: {o_workMode}"); - if (o_customCompressionType.Value != o_customCompressionType.DefaultValue) - { - sb.AppendLine($"# Custom Compression Type: {o_customCompressionType}"); - } if (o_workMode.Value != WorkMode.Extract) { sb.AppendLine($"# Parse Assets Using TypeTree: {!f_avoidLoadingViaTypetree.Value}"); @@ -1248,6 +1291,8 @@ namespace AssetStudioCLI.Options { sb.AppendLine($"# Output Path: \"{o_outputFolder}\""); } + sb.AppendLine($"Bundle BlockInfo Compression Type: {o_bundleBlockInfoCompression}"); + sb.AppendLine($"Bundle Block Compression Type: {o_bundleBlockCompression}"); switch (o_workMode.Value) { case WorkMode.Export: diff --git a/AssetStudioCLI/Studio.cs b/AssetStudioCLI/Studio.cs index b3fb587..9ee08c2 100644 --- a/AssetStudioCLI/Studio.cs +++ b/AssetStudioCLI/Studio.cs @@ -92,7 +92,7 @@ namespace AssetStudioCLI var count = 0; var bundleStream = new OffsetStream(reader); var bundleReader = new FileReader(reader.FullPath, bundleStream); - var bundleFile = new BundleFile(bundleReader, assetsManager.ZstdEnabled, assetsManager.SpecifyUnityVersion); + var bundleFile = new BundleFile(bundleReader, assetsManager.CustomBlockInfoCompression, assetsManager.CustomBlockCompression, assetsManager.SpecifyUnityVersion); var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked"); if (bundleFile.fileList.Length > 0) { @@ -109,7 +109,7 @@ namespace AssetStudioCLI bundleReader.FileName = $"{reader.FileName}_0x{bundleStream.Offset:X}"; } Logger.Info($"[MultiBundle] Decompressing \"{reader.FileName}\" from offset: 0x{bundleStream.Offset:X}.."); - bundleFile = new BundleFile(bundleReader, assetsManager.ZstdEnabled, assetsManager.SpecifyUnityVersion); + bundleFile = new BundleFile(bundleReader, assetsManager.CustomBlockInfoCompression, assetsManager.CustomBlockCompression, assetsManager.SpecifyUnityVersion); if (bundleFile.fileList.Length > 0) { count += ExtractStreamFile(extractPath, bundleFile.fileList); @@ -160,7 +160,8 @@ namespace AssetStudioCLI { var isLoaded = false; assetsManager.SpecifyUnityVersion = CLIOptions.o_unityVersion.Value; - assetsManager.ZstdEnabled = CLIOptions.o_customCompressionType.Value == CustomCompressionType.Zstd; + assetsManager.CustomBlockInfoCompression = CLIOptions.o_bundleBlockInfoCompression.Value; + assetsManager.CustomBlockCompression = CLIOptions.o_bundleBlockCompression.Value; assetsManager.LoadingViaTypeTreeEnabled = !CLIOptions.f_avoidLoadingViaTypetree.Value; if (!CLIOptions.f_loadAllAssets.Value) { diff --git a/AssetStudioGUI/AssetStudioGUI.csproj b/AssetStudioGUI/AssetStudioGUI.csproj index 5daf55b..f59d08c 100644 --- a/AssetStudioGUI/AssetStudioGUI.csproj +++ b/AssetStudioGUI/AssetStudioGUI.csproj @@ -82,6 +82,8 @@ + + @@ -107,6 +111,7 @@ + @@ -114,6 +119,7 @@ + @@ -121,6 +127,7 @@ + diff --git a/AssetStudioGUI/AssetStudioGUIForm.Designer.cs b/AssetStudioGUI/AssetStudioGUIForm.Designer.cs index 4123ce2..f2a28d6 100644 --- a/AssetStudioGUI/AssetStudioGUIForm.Designer.cs +++ b/AssetStudioGUI/AssetStudioGUIForm.Designer.cs @@ -47,8 +47,10 @@ this.useDumpTreeViewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.buildTreeStructureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.customCompressionTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.customCompressionZstdToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.customCompressionLZ4ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.blockInfoCompressionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.customBlockInfoCompressionComboBoxToolStripMenuItem = new System.Windows.Forms.ToolStripComboBox(); + this.blockCompressionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.customBlockCompressionComboBoxToolStripMenuItem = new System.Windows.Forms.ToolStripComboBox(); this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem(); this.specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox(); this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem(); @@ -359,33 +361,59 @@ // customCompressionTypeToolStripMenuItem // this.customCompressionTypeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.customCompressionZstdToolStripMenuItem, - this.customCompressionLZ4ToolStripMenuItem}); + this.blockInfoCompressionToolStripMenuItem, + this.customBlockInfoCompressionComboBoxToolStripMenuItem, + this.blockCompressionToolStripMenuItem, + this.customBlockCompressionComboBoxToolStripMenuItem}); this.customCompressionTypeToolStripMenuItem.Name = "customCompressionTypeToolStripMenuItem"; this.customCompressionTypeToolStripMenuItem.Size = new System.Drawing.Size(241, 22); - this.customCompressionTypeToolStripMenuItem.Text = "Custom compression type"; + this.customCompressionTypeToolStripMenuItem.Text = "Bundle compression type"; // - // customCompressionZstdToolStripMenuItem + // blockInfoCompressionToolStripMenuItem // - this.customCompressionZstdToolStripMenuItem.Checked = true; - this.customCompressionZstdToolStripMenuItem.CheckOnClick = true; - this.customCompressionZstdToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; - this.customCompressionZstdToolStripMenuItem.Name = "customCompressionZstdToolStripMenuItem"; - this.customCompressionZstdToolStripMenuItem.Size = new System.Drawing.Size(130, 22); - this.customCompressionZstdToolStripMenuItem.Text = "Zstd"; - this.customCompressionZstdToolStripMenuItem.ToolTipText = "If selected, Zstd-decompression will be used for assets with custom compression t" + - "ype"; - this.customCompressionZstdToolStripMenuItem.CheckedChanged += new System.EventHandler(this.customCompressionZstd_CheckedChanged); + this.blockInfoCompressionToolStripMenuItem.Enabled = false; + this.blockInfoCompressionToolStripMenuItem.Name = "blockInfoCompressionToolStripMenuItem"; + this.blockInfoCompressionToolStripMenuItem.Size = new System.Drawing.Size(197, 22); + this.blockInfoCompressionToolStripMenuItem.Text = "BlockInfo Compression"; // - // customCompressionLZ4ToolStripMenuItem + // customBlockInfoCompressionComboBoxToolStripMenuItem // - this.customCompressionLZ4ToolStripMenuItem.CheckOnClick = true; - this.customCompressionLZ4ToolStripMenuItem.Name = "customCompressionLZ4ToolStripMenuItem"; - this.customCompressionLZ4ToolStripMenuItem.Size = new System.Drawing.Size(130, 22); - this.customCompressionLZ4ToolStripMenuItem.Text = "Lz4/Lz4HC"; - this.customCompressionLZ4ToolStripMenuItem.ToolTipText = "If selected, Lz4-decompression will be used for assets with custom compression ty" + - "pe"; - this.customCompressionLZ4ToolStripMenuItem.CheckedChanged += new System.EventHandler(this.customCompressionLZ4_CheckedChanged); + this.customBlockInfoCompressionComboBoxToolStripMenuItem.DropDownHeight = 80; + this.customBlockInfoCompressionComboBoxToolStripMenuItem.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.customBlockInfoCompressionComboBoxToolStripMenuItem.IntegralHeight = false; + this.customBlockInfoCompressionComboBoxToolStripMenuItem.Items.AddRange(new object[] { + "Auto", + "Zstd", + "Oodle", + "Lz4/Lz4HC", + "Lzma"}); + this.customBlockInfoCompressionComboBoxToolStripMenuItem.Name = "customBlockInfoCompressionComboBoxToolStripMenuItem"; + this.customBlockInfoCompressionComboBoxToolStripMenuItem.Size = new System.Drawing.Size(100, 23); + this.customBlockInfoCompressionComboBoxToolStripMenuItem.ToolTipText = "Selected compression type will override detected type from asset bundle"; + this.customBlockInfoCompressionComboBoxToolStripMenuItem.SelectedIndexChanged += new System.EventHandler(this.customBlockInfoCompressionComboBoxToolStripMenuItem_SelectedIndexChanged); + // + // blockCompressionToolStripMenuItem + // + this.blockCompressionToolStripMenuItem.Enabled = false; + this.blockCompressionToolStripMenuItem.Name = "blockCompressionToolStripMenuItem"; + this.blockCompressionToolStripMenuItem.Size = new System.Drawing.Size(197, 22); + this.blockCompressionToolStripMenuItem.Text = "Block Compression"; + // + // customBlockCompressionComboBoxToolStripMenuItem + // + this.customBlockCompressionComboBoxToolStripMenuItem.DropDownHeight = 80; + this.customBlockCompressionComboBoxToolStripMenuItem.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.customBlockCompressionComboBoxToolStripMenuItem.IntegralHeight = false; + this.customBlockCompressionComboBoxToolStripMenuItem.Items.AddRange(new object[] { + "Auto", + "Zstd", + "Oodle", + "Lz4/Lz4HC", + "Lzma"}); + this.customBlockCompressionComboBoxToolStripMenuItem.Name = "customBlockCompressionComboBoxToolStripMenuItem"; + this.customBlockCompressionComboBoxToolStripMenuItem.Size = new System.Drawing.Size(100, 23); + this.customBlockCompressionComboBoxToolStripMenuItem.ToolTipText = "Selected compression type will override detected type from asset bundle"; + this.customBlockCompressionComboBoxToolStripMenuItem.SelectedIndexChanged += new System.EventHandler(this.customBlockCompressionComboBoxToolStripMenuItem_SelectedIndexChanged); // // toolStripMenuItem14 // @@ -1746,8 +1774,6 @@ private System.Windows.Forms.ToolStripMenuItem l2DModelWithFadeListToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exportL2DWithFadeLstToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem customCompressionTypeToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem customCompressionZstdToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem customCompressionLZ4ToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem useAssetLoadingViaTypetreeToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator assetLoadingToolStripSeparator; private System.Windows.Forms.TreeView dumpTreeView; @@ -1763,6 +1789,10 @@ private System.Windows.Forms.ToolStripMenuItem colorThemeDarkToolStripMenuItem; private System.Windows.Forms.Label FMODaudioChannelsLabel; private System.Windows.Forms.ToolStripMenuItem autoPlayAudioAssetsToolStripMenuItem; + private System.Windows.Forms.ToolStripComboBox customBlockCompressionComboBoxToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem blockCompressionToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem blockInfoCompressionToolStripMenuItem; + private System.Windows.Forms.ToolStripComboBox customBlockInfoCompressionComboBoxToolStripMenuItem; } } diff --git a/AssetStudioGUI/AssetStudioGUIForm.cs b/AssetStudioGUI/AssetStudioGUIForm.cs index 9fafa10..41a54b1 100644 --- a/AssetStudioGUI/AssetStudioGUIForm.cs +++ b/AssetStudioGUI/AssetStudioGUIForm.cs @@ -145,6 +145,8 @@ namespace AssetStudioGUI useAssetLoadingViaTypetreeToolStripMenuItem.Checked = Properties.Settings.Default.useTypetreeLoading; useDumpTreeViewToolStripMenuItem.Checked = Properties.Settings.Default.useDumpTreeView; autoPlayAudioAssetsToolStripMenuItem.Checked = Properties.Settings.Default.autoplayAudio; + customBlockCompressionComboBoxToolStripMenuItem.SelectedIndex = 0; + customBlockInfoCompressionComboBoxToolStripMenuItem.SelectedIndex = 0; FMODinit(); listSearchFilterMode.SelectedIndex = 0; if (string.IsNullOrEmpty(Properties.Settings.Default.fbxSettings)) @@ -2422,16 +2424,50 @@ namespace AssetStudioGUI } } - private void customCompressionZstd_CheckedChanged(object sender, EventArgs e) + private void customBlockCompressionComboBoxToolStripMenuItem_SelectedIndexChanged(object sender, EventArgs e) { - customCompressionLZ4ToolStripMenuItem.Checked = !customCompressionZstdToolStripMenuItem.Checked; - assetsManager.ZstdEnabled = customCompressionZstdToolStripMenuItem.Checked; + var selectedTypeIndex = customBlockCompressionComboBoxToolStripMenuItem.SelectedIndex; + switch (selectedTypeIndex) + { + case 0: + assetsManager.CustomBlockCompression = CompressionType.Auto; + break; + case 1: + assetsManager.CustomBlockCompression = CompressionType.Zstd; + break; + case 2: + assetsManager.CustomBlockCompression = CompressionType.Oodle; + break; + case 3: + assetsManager.CustomBlockCompression = CompressionType.Lz4HC; + break; + case 4: + assetsManager.CustomBlockCompression = CompressionType.Lzma; + break; + } } - private void customCompressionLZ4_CheckedChanged(object sender, EventArgs e) + private void customBlockInfoCompressionComboBoxToolStripMenuItem_SelectedIndexChanged(object sender, EventArgs e) { - customCompressionZstdToolStripMenuItem.Checked = !customCompressionLZ4ToolStripMenuItem.Checked; - assetsManager.ZstdEnabled = customCompressionZstdToolStripMenuItem.Checked; + var selectedTypeIndex = customBlockInfoCompressionComboBoxToolStripMenuItem.SelectedIndex; + switch (selectedTypeIndex) + { + case 0: + assetsManager.CustomBlockInfoCompression = CompressionType.Auto; + break; + case 1: + assetsManager.CustomBlockInfoCompression = CompressionType.Zstd; + break; + case 2: + assetsManager.CustomBlockInfoCompression = CompressionType.Oodle; + break; + case 3: + assetsManager.CustomBlockInfoCompression = CompressionType.Lz4HC; + break; + case 4: + assetsManager.CustomBlockInfoCompression = CompressionType.Lzma; + break; + } } private void useAssetLoadingViaTypetreeToolStripMenuItem_CheckedChanged(object sender, EventArgs e) diff --git a/AssetStudioGUI/Studio.cs b/AssetStudioGUI/Studio.cs index e26140d..eba18b9 100644 --- a/AssetStudioGUI/Studio.cs +++ b/AssetStudioGUI/Studio.cs @@ -140,7 +140,7 @@ namespace AssetStudioGUI var count = 0; var bundleStream = new OffsetStream(reader); var bundleReader = new FileReader(reader.FullPath, bundleStream); - var bundleFile = new BundleFile(bundleReader, assetsManager.ZstdEnabled, assetsManager.SpecifyUnityVersion); + var bundleFile = new BundleFile(bundleReader, assetsManager.CustomBlockInfoCompression, assetsManager.CustomBlockCompression, assetsManager.SpecifyUnityVersion); var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked"); if (bundleFile.fileList.Length > 0) { @@ -157,7 +157,7 @@ namespace AssetStudioGUI bundleReader.FileName = $"{reader.FileName}_0x{bundleStream.Offset:X}"; } Logger.Info($"[MultiBundle] Decompressing \"{reader.FileName}\" from offset: 0x{bundleStream.Offset:X}.."); - bundleFile = new BundleFile(bundleReader, assetsManager.ZstdEnabled, assetsManager.SpecifyUnityVersion); + bundleFile = new BundleFile(bundleReader, assetsManager.CustomBlockInfoCompression, assetsManager.CustomBlockCompression, assetsManager.SpecifyUnityVersion); if (bundleFile.fileList.Length > 0) { count += ExtractStreamFile(extractPath, bundleFile.fileList);