diff --git a/AssetStudio/AssetsManager.cs b/AssetStudio/AssetsManager.cs index 2a6590c..9821fe0 100644 --- a/AssetStudio/AssetsManager.cs +++ b/AssetStudio/AssetsManager.cs @@ -53,21 +53,21 @@ namespace AssetStudio public void LoadFilesAndFolders(params string[] path) { - List pathList = new List(); + var pathList = new List(); pathList.AddRange(path); LoadFilesAndFolders(out _, pathList); } public void LoadFilesAndFolders(out string parentPath, params string[] path) { - List pathList = new List(); + var pathList = new List(); pathList.AddRange(path); LoadFilesAndFolders(out parentPath, pathList); } public void LoadFilesAndFolders(out string parentPath, List pathList) { - List fileList = new List(); + var fileList = new List(); bool filesInPath = false; parentPath = ""; foreach (var path in pathList) @@ -113,8 +113,14 @@ namespace AssetStudio //use a for loop because list size can change for (var i = 0; i < importFiles.Count; i++) { - LoadFile(importFiles[i]); - Progress.Report(i + 1, importFiles.Count); + if (LoadFile(importFiles[i])) + { + Progress.Report(i + 1, importFiles.Count); + } + else + { + break; + } } importFiles.Clear(); @@ -126,13 +132,13 @@ namespace AssetStudio ProcessAssets(); } - private void LoadFile(string fullName) + private bool LoadFile(string fullName) { var reader = new FileReader(fullName); - LoadFile(reader); + return LoadFile(reader); } - private void LoadFile(FileReader reader) + private bool LoadFile(FileReader reader) { switch (reader?.FileType) { @@ -140,8 +146,7 @@ namespace AssetStudio LoadAssetsFile(reader); break; case FileType.BundleFile: - LoadBundleFile(reader); - break; + return LoadBundleFile(reader); case FileType.WebFile: LoadWebFile(reader); break; @@ -154,7 +159,10 @@ namespace AssetStudio case FileType.ZipFile: LoadZipFile(reader); break; + default: + return false; } + return true; } private void LoadAssetsFile(FileReader reader) @@ -248,7 +256,7 @@ namespace AssetStudio Logger.Info($"Skipping {originalPath} ({reader.FileName})"); } - private void LoadBundleFile(FileReader reader, string originalPath = null) + private bool LoadBundleFile(FileReader reader, string originalPath = null) { Logger.Info("Loading " + reader.FullPath); try @@ -267,10 +275,12 @@ namespace AssetStudio resourceFileReaders.Add(file.fileName, subReader); } } + return true; } catch (NotSupportedException e) { Logger.Error(e.Message); + return false; } catch (Exception e) { @@ -280,6 +290,7 @@ namespace AssetStudio str += $" from {Path.GetFileName(originalPath)}"; } Logger.Warning($"{str}\r\n{e}"); + return true; } finally { diff --git a/AssetStudio/BigArrayPool.cs b/AssetStudio/BigArrayPool.cs index 369e689..8066e13 100644 --- a/AssetStudio/BigArrayPool.cs +++ b/AssetStudio/BigArrayPool.cs @@ -4,7 +4,11 @@ namespace AssetStudio { public static class BigArrayPool { - private static readonly ArrayPool s_shared = ArrayPool.Create(64 * 1024 * 1024, 3); - public static ArrayPool Shared => s_shared; + public static ArrayPool Shared { get; } + + static BigArrayPool() + { + Shared = ArrayPool.Create(256 * 1024 * 1024, 5); + } } } diff --git a/AssetStudio/BundleFile.cs b/AssetStudio/BundleFile.cs index dd82712..f82fb12 100644 --- a/AssetStudio/BundleFile.cs +++ b/AssetStudio/BundleFile.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Linq; +using System.Text.RegularExpressions; namespace AssetStudio { @@ -100,22 +101,22 @@ namespace AssetStudio case "UnityFS": ReadHeader(reader); - bool isUnityCnEnc = false; - string unityVer = string.IsNullOrEmpty(specUnityVer) ? m_Header.unityRevision : specUnityVer; - int[] ver = new string(unityVer.SkipWhile(x => !char.IsDigit(x)).TakeWhile(x => char.IsDigit(x) || x == '.').ToArray()).Split('.').Select(x => int.Parse(x)).ToArray(); - if (ver[0] != 0) + var isUnityCnEnc = false; + var unityVerStr = string.IsNullOrEmpty(specUnityVer) ? m_Header.unityRevision : specUnityVer; + int[] ver = Regex.Matches(unityVerStr, @"\d+").Cast().Select(x => int.Parse(x.Value)).ToArray(); + if (ver.Length > 0 && ver[0] != 0) { // https://issuetracker.unity3d.com/issues/files-within-assetbundles-do-not-start-on-aligned-boundaries-breaking-patching-on-nintendo-switch - if (ver[0] < 2020 || - (ver[0] == 2020 && ver[1] <= 3 && ver[2] < 34) || - (ver[0] == 2021 && ver[1] <= 3 && ver[2] < 2) || - (ver[0] == 2022 && ver[1] <= 1 && ver[2] < 1)) + if (ver[0] < 2020 + || (ver[0] == 2020 && ver[1] <= 3 && ver[2] < 34) + || (ver[0] == 2021 && ver[1] <= 3 && ver[2] < 2) + || (ver[0] == 2022 && ver[1] <= 1 && ver[2] < 1)) { isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.OldFlag) != 0; } else { - isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.NewFlag) != 0; + isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.NewFlag) != 0; } } if (isUnityCnEnc) @@ -133,7 +134,7 @@ namespace AssetStudio } } - private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader) + private void ReadHeaderAndBlocksInfo(FileReader reader) { if (m_Header.version >= 4) { @@ -185,7 +186,7 @@ namespace AssetStudio return blocksStream; } - private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream) + private void ReadBlocksAndDirectory(FileReader reader, Stream blocksStream) { var isCompressed = m_Header.signature == "UnityWeb"; foreach (var blockInfo in m_BlocksInfo) @@ -246,7 +247,7 @@ namespace AssetStudio } } - private void ReadHeader(EndianBinaryReader reader) + private void ReadHeader(FileReader reader) { m_Header.size = reader.ReadInt64(); m_Header.compressedBlocksInfoSize = reader.ReadUInt32(); @@ -258,7 +259,7 @@ namespace AssetStudio } } - private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader, int[] unityVer) + private void ReadBlocksInfoAndDirectory(FileReader reader, int[] unityVer) { byte[] blocksInfoBytes; @@ -290,42 +291,44 @@ namespace AssetStudio { blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); } - MemoryStream blocksInfoUncompresseddStream; + MemoryStream blocksInfoUncompressedStream; var uncompressedSize = m_Header.uncompressedBlocksInfoSize; var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask); switch (compressionType) { case CompressionType.None: - { - blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes); - break; - } + { + blocksInfoUncompressedStream = new MemoryStream(blocksInfoBytes); + break; + } case CompressionType.Lzma: + { + blocksInfoUncompressedStream = new MemoryStream((int) (uncompressedSize)); + using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes)) { - blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize)); - using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes)) - { - SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize); - } - blocksInfoUncompresseddStream.Position = 0; - break; + SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompressedStream, + m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize); } + blocksInfoUncompressedStream.Position = 0; + break; + } case CompressionType.Lz4: case CompressionType.Lz4HC: + { + var uncompressedBytes = new byte[uncompressedSize]; + var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes); + if (numWrite != uncompressedSize) { - 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"); - } - blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes); - break; + throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes"); } + blocksInfoUncompressedStream = new MemoryStream(uncompressedBytes); + break; + } default: throw new IOException($"Unsupported compression type {compressionType}"); } - using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream)) + + using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompressedStream)) { var uncompressedDataHash = blocksInfoReader.ReadBytes(16); var blocksInfoCount = blocksInfoReader.ReadInt32(); @@ -359,7 +362,7 @@ namespace AssetStudio } } - private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream) + private void ReadBlocks(FileReader reader, Stream blocksStream) { foreach (var blockInfo in m_BlocksInfo) { @@ -367,33 +370,39 @@ namespace AssetStudio switch (compressionType) { case CompressionType.None: - { - reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize); - break; - } + { + reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize); + break; + } case CompressionType.Lzma: - { - SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize); - break; - } + { + SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize); + break; + } case CompressionType.Lz4: case CompressionType.Lz4HC: + { + var compressedSize = (int)blockInfo.compressedSize; + var compressedBytes = BigArrayPool.Shared.Rent(compressedSize); + _ = reader.Read(compressedBytes, 0, compressedSize); + var uncompressedSize = (int)blockInfo.uncompressedSize; + var uncompressedBytes = BigArrayPool.Shared.Rent(uncompressedSize); + try { - var compressedSize = (int)blockInfo.compressedSize; - var compressedBytes = BigArrayPool.Shared.Rent(compressedSize); - reader.Read(compressedBytes, 0, compressedSize); - var uncompressedSize = (int)blockInfo.uncompressedSize; - var uncompressedBytes = BigArrayPool.Shared.Rent(uncompressedSize); var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize); if (numWrite != uncompressedSize) { throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes"); } blocksStream.Write(uncompressedBytes, 0, uncompressedSize); - BigArrayPool.Shared.Return(compressedBytes); - BigArrayPool.Shared.Return(uncompressedBytes); - break; } + finally + { + BigArrayPool.Shared.Return(compressedBytes, clearArray: true); + BigArrayPool.Shared.Return(uncompressedBytes, clearArray: true); + } + break; + } default: throw new IOException($"Unsupported compression type {compressionType}"); } diff --git a/AssetStudio/Classes/Texture2D.cs b/AssetStudio/Classes/Texture2D.cs index ee6f978..84a84d0 100644 --- a/AssetStudio/Classes/Texture2D.cs +++ b/AssetStudio/Classes/Texture2D.cs @@ -111,7 +111,6 @@ namespace AssetStudio { reader.AlignStream(); var m_MipmapLimitGroupName = reader.ReadAlignedString(); - reader.AlignStream(); } if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up { diff --git a/AssetStudio/EndianSpanReader.cs b/AssetStudio/EndianSpanReader.cs new file mode 100644 index 0000000..1538a86 --- /dev/null +++ b/AssetStudio/EndianSpanReader.cs @@ -0,0 +1,22 @@ +using System; +using System.Buffers.Binary; + +namespace AssetStudio +{ + public static class EndianSpanReader + { + public static uint SpanToUint32(Span data, int start, bool isBigEndian) + { + return isBigEndian + ? BinaryPrimitives.ReadUInt32BigEndian(data.Slice(start)) + : BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(start)); + } + + public static long SpanToInt64(Span data, int start, bool isBigEndian) + { + return isBigEndian + ? BinaryPrimitives.ReadInt64BigEndian(data.Slice(start)) + : BinaryPrimitives.ReadInt64LittleEndian(data.Slice(start)); + } + } +} diff --git a/AssetStudio/Extensions/BinaryReaderExtensions.cs b/AssetStudio/Extensions/BinaryReaderExtensions.cs index b9753fb..df86cc3 100644 --- a/AssetStudio/Extensions/BinaryReaderExtensions.cs +++ b/AssetStudio/Extensions/BinaryReaderExtensions.cs @@ -40,7 +40,7 @@ namespace AssetStudio if (encoding?.CodePage == 1200) //Unicode (UTF-16LE) return reader.ReadUnicodeStringToNull(maxLength * 2); - var bytes = new List(); + Span bytes = stackalloc byte[maxLength]; var count = 0; while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength) { @@ -49,9 +49,10 @@ namespace AssetStudio { break; } - bytes.Add(b); + bytes[count] = b; count++; } + bytes = bytes.Slice(0, count); return encoding?.GetString(bytes.ToArray()) ?? Encoding.UTF8.GetString(bytes.ToArray()); } diff --git a/AssetStudio/FileReader.cs b/AssetStudio/FileReader.cs index 61426b4..84448c6 100644 --- a/AssetStudio/FileReader.cs +++ b/AssetStudio/FileReader.cs @@ -1,5 +1,6 @@ -using System.IO; -using System.Linq; +using System; +using System.IO; +using static AssetStudio.EndianSpanReader; namespace AssetStudio { @@ -37,66 +38,69 @@ namespace AssetStudio case "UnityWebData1.0": return FileType.WebFile; default: + { + var buff = ReadBytes(40).AsSpan(); + var magic = Span.Empty; + Position = 0; + + magic = buff.Length > 2 ? buff.Slice(0, 2) : magic; + if (magic.SequenceEqual(gzipMagic)) { - byte[] magic = ReadBytes(2); - Position = 0; - if (gzipMagic.SequenceEqual(magic)) - { - return FileType.GZipFile; - } - Position = 0x20; - magic = ReadBytes(6); - Position = 0; - if (brotliMagic.SequenceEqual(magic)) - { - return FileType.BrotliFile; - } - if (IsSerializedFile()) - { - return FileType.AssetsFile; - } - magic = ReadBytes(4); - Position = 0; - if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic)) - return FileType.ZipFile; - return FileType.ResourceFile; + return FileType.GZipFile; } + + magic = buff.Length > 38 ? buff.Slice(32, 6) : magic; + if (magic.SequenceEqual(brotliMagic)) + { + return FileType.BrotliFile; + } + + if (IsSerializedFile(buff)) + { + return FileType.AssetsFile; + } + + magic = buff.Length > 4 ? buff.Slice(0, 4): magic; + if (magic.SequenceEqual(zipMagic) || magic.SequenceEqual(zipSpannedMagic)) + { + return FileType.ZipFile; + } + + return FileType.ResourceFile; + } } } - private bool IsSerializedFile() + private bool IsSerializedFile(Span buff) { var fileSize = BaseStream.Length; if (fileSize < 20) { return false; } - var m_MetadataSize = ReadUInt32(); - long m_FileSize = ReadUInt32(); - var m_Version = ReadUInt32(); - long m_DataOffset = ReadUInt32(); - var m_Endianess = ReadByte(); - var m_Reserved = ReadBytes(3); + var isBigEndian = Endian == EndianType.BigEndian; + + //var m_MetadataSize = SpanToUint32(buff, 0, isBigEndian); + long m_FileSize = SpanToUint32(buff, 4, isBigEndian); + var m_Version = SpanToUint32(buff, 8, isBigEndian); + long m_DataOffset = SpanToUint32(buff, 12, isBigEndian); + //var m_Endianess = buff[16]; + //var m_Reserved = buff.Slice(17, 3); if (m_Version >= 22) { if (fileSize < 48) { - Position = 0; return false; } - m_MetadataSize = ReadUInt32(); - m_FileSize = ReadInt64(); - m_DataOffset = ReadInt64(); + //m_MetadataSize = SpanToUint32(buff, 20, isBigEndian); + m_FileSize = SpanToInt64(buff, 24, isBigEndian); + m_DataOffset = SpanToInt64(buff, 32, isBigEndian); } - Position = 0; - if (m_FileSize != fileSize) - { - return false; - } - if (m_DataOffset > fileSize) + if (m_FileSize != fileSize || m_DataOffset > fileSize) { return false; } + return true; } } diff --git a/AssetStudioGUI/DirectBitmap.cs b/AssetStudioGUI/DirectBitmap.cs index 459fee6..baaa483 100644 --- a/AssetStudioGUI/DirectBitmap.cs +++ b/AssetStudioGUI/DirectBitmap.cs @@ -43,6 +43,6 @@ namespace AssetStudioGUI public Bitmap Bitmap => m_bitmap; private Bitmap m_bitmap; - private readonly GCHandle m_handle; + private GCHandle m_handle; } } diff --git a/AssetStudioUtility/Texture2DConverter.cs b/AssetStudioUtility/Texture2DConverter.cs index 47e7d0e..3d7d7f9 100644 --- a/AssetStudioUtility/Texture2DConverter.cs +++ b/AssetStudioUtility/Texture2DConverter.cs @@ -12,7 +12,7 @@ namespace AssetStudio private TextureFormat m_TextureFormat; private int[] version; private BuildTarget platform; - private int outPutSize; + public int outPutSize; public Texture2DConverter(Texture2D m_Texture2D) { @@ -33,183 +33,189 @@ namespace AssetStudio } var flag = false; var buff = BigArrayPool.Shared.Rent(reader.Size); - reader.GetData(buff); - switch (m_TextureFormat) + try { - case TextureFormat.Alpha8: //test pass - flag = DecodeAlpha8(buff, bytes); - break; - case TextureFormat.ARGB4444: //test pass - SwapBytesForXbox(buff); - flag = DecodeARGB4444(buff, bytes); - break; - case TextureFormat.RGB24: //test pass - flag = DecodeRGB24(buff, bytes); - break; - case TextureFormat.RGBA32: //test pass - flag = DecodeRGBA32(buff, bytes); - break; - case TextureFormat.ARGB32: //test pass - flag = DecodeARGB32(buff, bytes); - break; - case TextureFormat.RGB565: //test pass - SwapBytesForXbox(buff); - flag = DecodeRGB565(buff, bytes); - break; - case TextureFormat.R16: //test pass - flag = DecodeR16(buff, bytes); - break; - case TextureFormat.DXT1: //test pass - SwapBytesForXbox(buff); - flag = DecodeDXT1(buff, bytes); - break; - case TextureFormat.DXT3: - break; - case TextureFormat.DXT5: //test pass - SwapBytesForXbox(buff); - flag = DecodeDXT5(buff, bytes); - break; - case TextureFormat.RGBA4444: //test pass - flag = DecodeRGBA4444(buff, bytes); - break; - case TextureFormat.BGRA32: //test pass - flag = DecodeBGRA32(buff, bytes); - break; - case TextureFormat.RHalf: - flag = DecodeRHalf(buff, bytes); - break; - case TextureFormat.RGHalf: - flag = DecodeRGHalf(buff, bytes); - break; - case TextureFormat.RGBAHalf: //test pass - flag = DecodeRGBAHalf(buff, bytes); - break; - case TextureFormat.RFloat: - flag = DecodeRFloat(buff, bytes); - break; - case TextureFormat.RGFloat: - flag = DecodeRGFloat(buff, bytes); - break; - case TextureFormat.RGBAFloat: - flag = DecodeRGBAFloat(buff, bytes); - break; - case TextureFormat.YUY2: //test pass - flag = DecodeYUY2(buff, bytes); - break; - case TextureFormat.RGB9e5Float: //test pass - flag = DecodeRGB9e5Float(buff, bytes); - break; - case TextureFormat.BC6H: //test pass - flag = DecodeBC6H(buff, bytes); - break; - case TextureFormat.BC7: //test pass - flag = DecodeBC7(buff, bytes); - break; - case TextureFormat.BC4: //test pass - flag = DecodeBC4(buff, bytes); - break; - case TextureFormat.BC5: //test pass - flag = DecodeBC5(buff, bytes); - break; - case TextureFormat.DXT1Crunched: //test pass - flag = DecodeDXT1Crunched(buff, bytes); - break; - case TextureFormat.DXT5Crunched: //test pass - flag = DecodeDXT5Crunched(buff, bytes); - break; - case TextureFormat.PVRTC_RGB2: //test pass - case TextureFormat.PVRTC_RGBA2: //test pass - flag = DecodePVRTC(buff, bytes, true); - break; - case TextureFormat.PVRTC_RGB4: //test pass - case TextureFormat.PVRTC_RGBA4: //test pass - flag = DecodePVRTC(buff, bytes, false); - break; - case TextureFormat.ETC_RGB4: //test pass - case TextureFormat.ETC_RGB4_3DS: - flag = DecodeETC1(buff, bytes); - break; - case TextureFormat.ATC_RGB4: //test pass - flag = DecodeATCRGB4(buff, bytes); - break; - case TextureFormat.ATC_RGBA8: //test pass - flag = DecodeATCRGBA8(buff, bytes); - break; - case TextureFormat.EAC_R: //test pass - flag = DecodeEACR(buff, bytes); - break; - case TextureFormat.EAC_R_SIGNED: - flag = DecodeEACRSigned(buff, bytes); - break; - case TextureFormat.EAC_RG: //test pass - flag = DecodeEACRG(buff, bytes); - break; - case TextureFormat.EAC_RG_SIGNED: - flag = DecodeEACRGSigned(buff, bytes); - break; - case TextureFormat.ETC2_RGB: //test pass - flag = DecodeETC2(buff, bytes); - break; - case TextureFormat.ETC2_RGBA1: //test pass - flag = DecodeETC2A1(buff, bytes); - break; - case TextureFormat.ETC2_RGBA8: //test pass - case TextureFormat.ETC_RGBA8_3DS: - flag = DecodeETC2A8(buff, bytes); - break; - case TextureFormat.ASTC_RGB_4x4: //test pass - case TextureFormat.ASTC_RGBA_4x4: //test pass - case TextureFormat.ASTC_HDR_4x4: //test pass - flag = DecodeASTC(buff, bytes, 4); - break; - case TextureFormat.ASTC_RGB_5x5: //test pass - case TextureFormat.ASTC_RGBA_5x5: //test pass - case TextureFormat.ASTC_HDR_5x5: //test pass - flag = DecodeASTC(buff, bytes, 5); - break; - case TextureFormat.ASTC_RGB_6x6: //test pass - case TextureFormat.ASTC_RGBA_6x6: //test pass - case TextureFormat.ASTC_HDR_6x6: //test pass - flag = DecodeASTC(buff, bytes, 6); - break; - case TextureFormat.ASTC_RGB_8x8: //test pass - case TextureFormat.ASTC_RGBA_8x8: //test pass - case TextureFormat.ASTC_HDR_8x8: //test pass - flag = DecodeASTC(buff, bytes, 8); - break; - case TextureFormat.ASTC_RGB_10x10: //test pass - case TextureFormat.ASTC_RGBA_10x10: //test pass - case TextureFormat.ASTC_HDR_10x10: //test pass - flag = DecodeASTC(buff, bytes, 10); - break; - case TextureFormat.ASTC_RGB_12x12: //test pass - case TextureFormat.ASTC_RGBA_12x12: //test pass - case TextureFormat.ASTC_HDR_12x12: //test pass - flag = DecodeASTC(buff, bytes, 12); - break; - case TextureFormat.RG16: //test pass - flag = DecodeRG16(buff, bytes); - break; - case TextureFormat.R8: //test pass - flag = DecodeR8(buff, bytes); - break; - case TextureFormat.ETC_RGB4Crunched: //test pass - flag = DecodeETC1Crunched(buff, bytes); - break; - case TextureFormat.ETC2_RGBA8Crunched: //test pass - flag = DecodeETC2A8Crunched(buff, bytes); - break; - case TextureFormat.RG32: //test pass - flag = DecodeRG32(buff, bytes); - break; - case TextureFormat.RGB48: //test pass - flag = DecodeRGB48(buff, bytes); - break; - case TextureFormat.RGBA64: //test pass - flag = DecodeRGBA64(buff, bytes); - break; + reader.GetData(buff); + switch (m_TextureFormat) + { + case TextureFormat.Alpha8: //test pass + flag = DecodeAlpha8(buff, bytes); + break; + case TextureFormat.ARGB4444: //test pass + SwapBytesForXbox(buff); + flag = DecodeARGB4444(buff, bytes); + break; + case TextureFormat.RGB24: //test pass + flag = DecodeRGB24(buff, bytes); + break; + case TextureFormat.RGBA32: //test pass + flag = DecodeRGBA32(buff, bytes); + break; + case TextureFormat.ARGB32: //test pass + flag = DecodeARGB32(buff, bytes); + break; + case TextureFormat.RGB565: //test pass + SwapBytesForXbox(buff); + flag = DecodeRGB565(buff, bytes); + break; + case TextureFormat.R16: //test pass + flag = DecodeR16(buff, bytes); + break; + case TextureFormat.DXT1: //test pass + SwapBytesForXbox(buff); + flag = DecodeDXT1(buff, bytes); + break; + case TextureFormat.DXT3: + break; + case TextureFormat.DXT5: //test pass + SwapBytesForXbox(buff); + flag = DecodeDXT5(buff, bytes); + break; + case TextureFormat.RGBA4444: //test pass + flag = DecodeRGBA4444(buff, bytes); + break; + case TextureFormat.BGRA32: //test pass + flag = DecodeBGRA32(buff, bytes); + break; + case TextureFormat.RHalf: + flag = DecodeRHalf(buff, bytes); + break; + case TextureFormat.RGHalf: + flag = DecodeRGHalf(buff, bytes); + break; + case TextureFormat.RGBAHalf: //test pass + flag = DecodeRGBAHalf(buff, bytes); + break; + case TextureFormat.RFloat: + flag = DecodeRFloat(buff, bytes); + break; + case TextureFormat.RGFloat: + flag = DecodeRGFloat(buff, bytes); + break; + case TextureFormat.RGBAFloat: + flag = DecodeRGBAFloat(buff, bytes); + break; + case TextureFormat.YUY2: //test pass + flag = DecodeYUY2(buff, bytes); + break; + case TextureFormat.RGB9e5Float: //test pass + flag = DecodeRGB9e5Float(buff, bytes); + break; + case TextureFormat.BC6H: //test pass + flag = DecodeBC6H(buff, bytes); + break; + case TextureFormat.BC7: //test pass + flag = DecodeBC7(buff, bytes); + break; + case TextureFormat.BC4: //test pass + flag = DecodeBC4(buff, bytes); + break; + case TextureFormat.BC5: //test pass + flag = DecodeBC5(buff, bytes); + break; + case TextureFormat.DXT1Crunched: //test pass + flag = DecodeDXT1Crunched(buff, bytes); + break; + case TextureFormat.DXT5Crunched: //test pass + flag = DecodeDXT5Crunched(buff, bytes); + break; + case TextureFormat.PVRTC_RGB2: //test pass + case TextureFormat.PVRTC_RGBA2: //test pass + flag = DecodePVRTC(buff, bytes, true); + break; + case TextureFormat.PVRTC_RGB4: //test pass + case TextureFormat.PVRTC_RGBA4: //test pass + flag = DecodePVRTC(buff, bytes, false); + break; + case TextureFormat.ETC_RGB4: //test pass + case TextureFormat.ETC_RGB4_3DS: + flag = DecodeETC1(buff, bytes); + break; + case TextureFormat.ATC_RGB4: //test pass + flag = DecodeATCRGB4(buff, bytes); + break; + case TextureFormat.ATC_RGBA8: //test pass + flag = DecodeATCRGBA8(buff, bytes); + break; + case TextureFormat.EAC_R: //test pass + flag = DecodeEACR(buff, bytes); + break; + case TextureFormat.EAC_R_SIGNED: + flag = DecodeEACRSigned(buff, bytes); + break; + case TextureFormat.EAC_RG: //test pass + flag = DecodeEACRG(buff, bytes); + break; + case TextureFormat.EAC_RG_SIGNED: + flag = DecodeEACRGSigned(buff, bytes); + break; + case TextureFormat.ETC2_RGB: //test pass + flag = DecodeETC2(buff, bytes); + break; + case TextureFormat.ETC2_RGBA1: //test pass + flag = DecodeETC2A1(buff, bytes); + break; + case TextureFormat.ETC2_RGBA8: //test pass + case TextureFormat.ETC_RGBA8_3DS: + flag = DecodeETC2A8(buff, bytes); + break; + case TextureFormat.ASTC_RGB_4x4: //test pass + case TextureFormat.ASTC_RGBA_4x4: //test pass + case TextureFormat.ASTC_HDR_4x4: //test pass + flag = DecodeASTC(buff, bytes, 4); + break; + case TextureFormat.ASTC_RGB_5x5: //test pass + case TextureFormat.ASTC_RGBA_5x5: //test pass + case TextureFormat.ASTC_HDR_5x5: //test pass + flag = DecodeASTC(buff, bytes, 5); + break; + case TextureFormat.ASTC_RGB_6x6: //test pass + case TextureFormat.ASTC_RGBA_6x6: //test pass + case TextureFormat.ASTC_HDR_6x6: //test pass + flag = DecodeASTC(buff, bytes, 6); + break; + case TextureFormat.ASTC_RGB_8x8: //test pass + case TextureFormat.ASTC_RGBA_8x8: //test pass + case TextureFormat.ASTC_HDR_8x8: //test pass + flag = DecodeASTC(buff, bytes, 8); + break; + case TextureFormat.ASTC_RGB_10x10: //test pass + case TextureFormat.ASTC_RGBA_10x10: //test pass + case TextureFormat.ASTC_HDR_10x10: //test pass + flag = DecodeASTC(buff, bytes, 10); + break; + case TextureFormat.ASTC_RGB_12x12: //test pass + case TextureFormat.ASTC_RGBA_12x12: //test pass + case TextureFormat.ASTC_HDR_12x12: //test pass + flag = DecodeASTC(buff, bytes, 12); + break; + case TextureFormat.RG16: //test pass + flag = DecodeRG16(buff, bytes); + break; + case TextureFormat.R8: //test pass + flag = DecodeR8(buff, bytes); + break; + case TextureFormat.ETC_RGB4Crunched: //test pass + flag = DecodeETC1Crunched(buff, bytes); + break; + case TextureFormat.ETC2_RGBA8Crunched: //test pass + flag = DecodeETC2A8Crunched(buff, bytes); + break; + case TextureFormat.RG32: //test pass + flag = DecodeRG32(buff, bytes); + break; + case TextureFormat.RGB48: //test pass + flag = DecodeRGB48(buff, bytes); + break; + case TextureFormat.RGBA64: //test pass + flag = DecodeRGBA64(buff, bytes); + break; + } + } + finally + { + BigArrayPool.Shared.Return(buff); } - BigArrayPool.Shared.Return(buff); return flag; } diff --git a/AssetStudioUtility/Texture2DExtensions.cs b/AssetStudioUtility/Texture2DExtensions.cs index e855ad0..25f7c8a 100644 --- a/AssetStudioUtility/Texture2DExtensions.cs +++ b/AssetStudioUtility/Texture2DExtensions.cs @@ -10,7 +10,7 @@ namespace AssetStudio public static Image ConvertToImage(this Texture2D m_Texture2D, bool flip) { var converter = new Texture2DConverter(m_Texture2D); - var buff = BigArrayPool.Shared.Rent(m_Texture2D.m_Width * m_Texture2D.m_Height * 4); + var buff = BigArrayPool.Shared.Rent(converter.outPutSize); try { if (converter.DecodeTexture2D(buff)) @@ -26,7 +26,7 @@ namespace AssetStudio } finally { - BigArrayPool.Shared.Return(buff); + BigArrayPool.Shared.Return(buff, clearArray: true); } }