- [Core] Fix bug where some buffers are unintentionally cached, causing undesired side effects.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Texture2DDecoder;
|
||||
|
||||
@@ -32,7 +33,9 @@ namespace AssetStudio
|
||||
return false;
|
||||
}
|
||||
var flag = false;
|
||||
var buff = BigArrayPool<byte>.Shared.Rent(reader.Size);
|
||||
var buff = ArrayPool<byte>.Shared.Rent(reader.Size);
|
||||
try
|
||||
{
|
||||
reader.GetData(buff);
|
||||
switch (m_TextureFormat)
|
||||
{
|
||||
@@ -210,7 +213,12 @@ namespace AssetStudio
|
||||
flag = DecodeRGBA64(buff, bytes);
|
||||
break;
|
||||
}
|
||||
BigArrayPool<byte>.Shared.Return(buff);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buff, true);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
@@ -17,7 +18,7 @@ namespace AssetStudio
|
||||
public static Image<Bgra32> ConvertToImage(this Texture2D m_Texture2D, bool flip)
|
||||
{
|
||||
var converter = new Texture2DConverter(m_Texture2D);
|
||||
var buff = BigArrayPool<byte>.Shared.Rent(m_Texture2D.m_Width * m_Texture2D.m_Height * 4);
|
||||
var buff = ArrayPool<byte>.Shared.Rent(m_Texture2D.m_Width * m_Texture2D.m_Height * 4);
|
||||
try
|
||||
{
|
||||
if (converter.DecodeTexture2D(buff))
|
||||
@@ -33,7 +34,7 @@ namespace AssetStudio
|
||||
}
|
||||
finally
|
||||
{
|
||||
BigArrayPool<byte>.Shared.Return(buff);
|
||||
ArrayPool<byte>.Shared.Return(buff, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Buffers;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class BigArrayPool<T>
|
||||
{
|
||||
private static readonly ArrayPool<T> s_shared = ArrayPool<T>.Create(64 * 1024 * 1024, 3);
|
||||
public static ArrayPool<T> Shared => s_shared;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -124,8 +125,10 @@ namespace AssetStudio
|
||||
var compressedSize = (int)blockInfo.compressedSize;
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
|
||||
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
var compressedBytes = ArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
var uncompressedBytes = ArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
try
|
||||
{
|
||||
reader.Read(compressedBytes, 0, compressedSize);
|
||||
|
||||
var compressedBytesSpan = compressedBytes.AsSpan(0, compressedSize);
|
||||
@@ -138,8 +141,12 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
|
||||
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(compressedBytes, true);
|
||||
ArrayPool<byte>.Shared.Return(uncompressedBytes, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
using System.Buffers;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
@@ -445,7 +446,9 @@ namespace AssetStudio
|
||||
case CompressionType.Lz4: //LZ4
|
||||
case CompressionType.Lz4HC: //LZ4HC
|
||||
{
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent((int)uncompressedSize);
|
||||
var uncompressedBytes = ArrayPool<byte>.Shared.Rent((int)uncompressedSize);
|
||||
try
|
||||
{
|
||||
var uncompressedBytesSpan = uncompressedBytes.AsSpan(0, (int)uncompressedSize);
|
||||
var numWrite = LZ4.Decompress(blocksInfoBytesSpan, uncompressedBytesSpan);
|
||||
if (numWrite != uncompressedSize)
|
||||
@@ -453,7 +456,11 @@ namespace AssetStudio
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytesSpan.ToArray());
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(uncompressedBytes, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lz4Mr0k: //Lz4Mr0k
|
||||
@@ -544,9 +551,17 @@ namespace AssetStudio
|
||||
case CompressionType.Lz4Mr0k when Game.Type.IsMhyGroup(): //Lz4Mr0k
|
||||
{
|
||||
var compressedSize = (int)blockInfo.compressedSize;
|
||||
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
reader.Read(compressedBytes, 0, compressedSize);
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
|
||||
var compressedBytes = ArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
var uncompressedBytes = ArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
|
||||
try
|
||||
{
|
||||
var compressedBytesSpan = compressedBytes.AsSpan(0, compressedSize);
|
||||
var uncompressedBytesSpan = uncompressedBytes.AsSpan(0, uncompressedSize);
|
||||
|
||||
reader.Read(compressedBytesSpan);
|
||||
if (compressionType == CompressionType.Lz4Mr0k && Mr0kUtils.IsMr0k(compressedBytes))
|
||||
{
|
||||
Logger.Verbose($"Block encrypted with mr0k, decrypting...");
|
||||
@@ -569,69 +584,81 @@ namespace AssetStudio
|
||||
{
|
||||
OPFPUtils.Decrypt(compressedBytesSpan, reader.FullPath);
|
||||
}
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
var uncompressedBytesSpan = uncompressedBytes.AsSpan(0, uncompressedSize);
|
||||
var numWrite = LZ4.Decompress(compressedBytesSpan, uncompressedBytesSpan);
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
|
||||
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||
blocksStream.Write(uncompressedBytesSpan);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(compressedBytes, true);
|
||||
ArrayPool<byte>.Shared.Return(uncompressedBytes, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lz4Inv when Game.Type.IsArknightsEndfield():
|
||||
{
|
||||
var compressedSize = (int)blockInfo.compressedSize;
|
||||
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
reader.Read(compressedBytes, 0, compressedSize);
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
|
||||
var compressedBytes = ArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
var uncompressedBytes = ArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
|
||||
var compressedBytesSpan = compressedBytes.AsSpan(0, compressedSize);
|
||||
var uncompressedBytesSpan = uncompressedBytes.AsSpan(0, uncompressedSize);
|
||||
|
||||
try
|
||||
{
|
||||
reader.Read(compressedBytesSpan);
|
||||
if (i == 0)
|
||||
{
|
||||
FairGuardUtils.Decrypt(compressedBytesSpan);
|
||||
|
||||
}
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
var uncompressedBytesSpan = uncompressedBytes.AsSpan(0, uncompressedSize);
|
||||
var numWrite = LZ4Inv.Decompress(compressedBytesSpan, uncompressedBytesSpan);
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
|
||||
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||
blocksStream.Write(uncompressedBytesSpan);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(compressedBytes, true);
|
||||
ArrayPool<byte>.Shared.Return(uncompressedBytes, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CompressionType.Zstd when !Game.Type.IsMhyGroup(): //Zstd
|
||||
{
|
||||
var compressedSize = (int)blockInfo.compressedSize;
|
||||
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
reader.Read(compressedBytes, 0, compressedSize);
|
||||
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
|
||||
var compressedBytes = ArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
var uncompressedBytes = ArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
|
||||
try
|
||||
{
|
||||
reader.Read(compressedBytes, 0, compressedSize);
|
||||
using var decompressor = new Decompressor();
|
||||
var numWrite = decompressor.Unwrap(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
throw new IOException($"Zstd decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksStream.Write(uncompressedBytes.ToArray(), 0, uncompressedSize);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Zstd decompression error:\n{ex}");
|
||||
}
|
||||
|
||||
blocksStream.Write(uncompressedBytes.ToArray(), 0, uncompressedSize);
|
||||
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(compressedBytes, true);
|
||||
ArrayPool<byte>.Shared.Return(uncompressedBytes, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -1981,7 +1981,7 @@ namespace AssetStudio
|
||||
var aclClip = m_MuscleClip.m_Clip.m_ACLClip as GIACLClip;
|
||||
|
||||
var resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size);
|
||||
var ms = new MemoryStream();
|
||||
using var ms = new MemoryStream();
|
||||
ms.Write(aclClip.m_DatabaseData);
|
||||
|
||||
ms.Write(resourceReader.GetData());
|
||||
|
||||
@@ -815,7 +815,7 @@ namespace AssetStudio
|
||||
return reader;
|
||||
}
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
MemoryStream ms = new();
|
||||
if (version == 0x10)
|
||||
{
|
||||
var buffer = (stackalloc byte[8]);
|
||||
@@ -929,7 +929,7 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
Logger.Verbose("Decrypted Reverse: 1999 file successfully !!");
|
||||
var stream = new MemoryStream();
|
||||
MemoryStream stream = new();
|
||||
stream.Write(signatureBytes);
|
||||
stream.Write(remaining);
|
||||
stream.Position = 0;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -46,18 +47,21 @@ namespace AssetStudio
|
||||
|
||||
private void ReadBlocksInfoAndDirectory(FileReader reader)
|
||||
{
|
||||
int offset = 0x20;
|
||||
var blocksInfo = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||
DescrambleHeader(blocksInfo);
|
||||
|
||||
Logger.Verbose($"Descrambled blocksInfo signature {Convert.ToHexString(blocksInfo, 0 , 4)}");
|
||||
using var blocksInfoStream = new MemoryStream(blocksInfo, offset, (int)m_Header.compressedBlocksInfoSize - offset);
|
||||
using var blocksInfoStream = new MemoryStream(blocksInfo, 0x20, (int)m_Header.compressedBlocksInfoSize - 0x20);
|
||||
using var blocksInfoReader = new EndianBinaryReader(blocksInfoStream);
|
||||
m_Header.uncompressedBlocksInfoSize = blocksInfoReader.ReadMhyUInt();
|
||||
Logger.Verbose($"uncompressed blocksInfo size: 0x{m_Header.uncompressedBlocksInfoSize:X8}");
|
||||
var compressedBlocksInfo = blocksInfoReader.ReadBytes((int)blocksInfoReader.Remaining);
|
||||
var uncompressedBlocksInfo = BigArrayPool<byte>.Shared.Rent((int)m_Header.uncompressedBlocksInfoSize);
|
||||
|
||||
var uncompressedBlocksInfo = ArrayPool<byte>.Shared.Rent((int)m_Header.uncompressedBlocksInfoSize);
|
||||
var uncompressedBlocksInfoSpan = uncompressedBlocksInfo.AsSpan(0, (int)m_Header.uncompressedBlocksInfoSize);
|
||||
|
||||
try
|
||||
{
|
||||
var numWrite = LZ4.Decompress(compressedBlocksInfo, uncompressedBlocksInfoSpan);
|
||||
if (numWrite != m_Header.uncompressedBlocksInfoSize)
|
||||
{
|
||||
@@ -65,7 +69,7 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
Logger.Verbose($"Writing block and directory to blocks stream...");
|
||||
using var blocksInfoUncompressedStream = new MemoryStream(uncompressedBlocksInfo);
|
||||
using var blocksInfoUncompressedStream = new MemoryStream(uncompressedBlocksInfo, 0, (int)m_Header.uncompressedBlocksInfoSize);
|
||||
using var blocksInfoUncompressedReader = new EndianBinaryReader(blocksInfoUncompressedStream);
|
||||
var nodesCount = blocksInfoUncompressedReader.ReadMhyInt();
|
||||
m_DirectoryInfo = new List<BundleFile.Node>();
|
||||
@@ -97,8 +101,11 @@ namespace AssetStudio
|
||||
|
||||
Logger.Verbose($"Block {i} Info: {m_BlocksInfo[i]}");
|
||||
}
|
||||
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBlocksInfo);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(uncompressedBlocksInfo, true);
|
||||
}
|
||||
}
|
||||
|
||||
private Stream CreateBlocksStream(string path)
|
||||
@@ -124,25 +131,31 @@ namespace AssetStudio
|
||||
throw new Exception($"Wrong compressed length: {compressedSize}");
|
||||
}
|
||||
|
||||
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
reader.Read(compressedBytes, 0, compressedSize);
|
||||
var compressedBytes = ArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
var uncompressedBytes = ArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
|
||||
var offset = 0xC;
|
||||
try
|
||||
{
|
||||
var compressedBytesSpan = compressedBytes.AsSpan(0, compressedSize);
|
||||
var uncompressedBytesSpan = uncompressedBytes.AsSpan(0, uncompressedSize);
|
||||
|
||||
reader.Read(compressedBytesSpan);
|
||||
DescrambleEntry(compressedBytesSpan);
|
||||
|
||||
Logger.Verbose($"Descrambled block signature {Convert.ToHexString(compressedBytes, 0, 4)}");
|
||||
var numWrite = LZ4.Decompress(compressedBytesSpan[offset..], uncompressedBytesSpan);
|
||||
var numWrite = LZ4.Decompress(compressedBytesSpan[0xC..], uncompressedBytesSpan);
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
|
||||
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
|
||||
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||
blocksStream.Write(uncompressedBytesSpan);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(compressedBytes, true);
|
||||
ArrayPool<byte>.Shared.Return(uncompressedBytes, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@@ -94,7 +95,9 @@ namespace AssetStudio
|
||||
Logger.Verbose($"Prased signature: {signature}");
|
||||
|
||||
var signatureBytes = Encoding.UTF8.GetBytes(signature);
|
||||
var buffer = BigArrayPool<byte>.Shared.Rent(BufferSize);
|
||||
var buffer = ArrayPool<byte>.Shared.Rent(BufferSize);
|
||||
try
|
||||
{
|
||||
while (Remaining > 0)
|
||||
{
|
||||
var index = 0;
|
||||
@@ -110,7 +113,11 @@ namespace AssetStudio
|
||||
index++;
|
||||
}
|
||||
}
|
||||
BigArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user