mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-25 05:40:21 -04:00
Fix for new compression type
This commit is contained in:
parent
0e097bda04
commit
f144037bc0
@ -35,7 +35,7 @@ namespace AssetStudio
|
|||||||
Lzma,
|
Lzma,
|
||||||
Lz4,
|
Lz4,
|
||||||
Lz4HC,
|
Lz4HC,
|
||||||
Lzham
|
Lz4Inv,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BundleFile
|
public class BundleFile
|
||||||
@ -378,20 +378,31 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
case CompressionType.Lz4:
|
case CompressionType.Lz4:
|
||||||
case CompressionType.Lz4HC:
|
case CompressionType.Lz4HC:
|
||||||
|
case CompressionType.Lz4Inv:
|
||||||
{
|
{
|
||||||
var compressedSize = (int)blockInfo.compressedSize;
|
var compressedSize = (int)blockInfo.compressedSize;
|
||||||
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
||||||
reader.Read(compressedBytes, 0, compressedSize);
|
_ = reader.Read(compressedBytes, 0, compressedSize);
|
||||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||||
var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
|
try
|
||||||
if (numWrite != uncompressedSize)
|
|
||||||
{
|
{
|
||||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
var compressedSpan = compressedBytes.AsSpan(0, compressedSize);
|
||||||
|
var uncompressedSpan = uncompressedBytes.AsSpan(0, uncompressedSize);
|
||||||
|
var numWrite = compressionType == CompressionType.Lz4Inv
|
||||||
|
? LZ4Inv.Instance.Decompress(compressedSpan, uncompressedSpan)
|
||||||
|
: LZ4Codec.Decode(compressedSpan, uncompressedSpan);
|
||||||
|
if (numWrite != uncompressedSize)
|
||||||
|
{
|
||||||
|
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||||
|
}
|
||||||
|
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
||||||
|
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||||
}
|
}
|
||||||
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
|
|
||||||
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
|
||||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
75
AssetStudio/LZ4/LZ4.cs
Normal file
75
AssetStudio/LZ4/LZ4.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class LZ4
|
||||||
|
{
|
||||||
|
public static LZ4 Instance => new LZ4();
|
||||||
|
|
||||||
|
public virtual int Decompress(ReadOnlySpan<byte> cmp, Span<byte> dec)
|
||||||
|
{
|
||||||
|
int cmpPos = 0;
|
||||||
|
int decPos = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var (encCount, litCount) = GetLiteralToken(cmp, ref cmpPos);
|
||||||
|
|
||||||
|
//Copy literal chunk
|
||||||
|
litCount = GetLength(litCount, cmp, ref cmpPos);
|
||||||
|
|
||||||
|
cmp.Slice(cmpPos, litCount).CopyTo(dec.Slice(decPos));
|
||||||
|
|
||||||
|
cmpPos += litCount;
|
||||||
|
decPos += litCount;
|
||||||
|
|
||||||
|
if (cmpPos >= cmp.Length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Copy compressed chunk
|
||||||
|
int back = GetChunkEnd(cmp, ref cmpPos);
|
||||||
|
|
||||||
|
encCount = GetLength(encCount, cmp, ref cmpPos) + 4;
|
||||||
|
|
||||||
|
int encPos = decPos - back;
|
||||||
|
|
||||||
|
if (encCount <= back)
|
||||||
|
{
|
||||||
|
dec.Slice(encPos, encCount).CopyTo(dec.Slice(decPos));
|
||||||
|
decPos += encCount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (encCount-- > 0)
|
||||||
|
{
|
||||||
|
dec[decPos++] = dec[encPos++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (cmpPos < cmp.Length && decPos < dec.Length);
|
||||||
|
|
||||||
|
return decPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual (int encCount, int litCount) GetLiteralToken(ReadOnlySpan<byte> cmp, ref int cmpPos) =>
|
||||||
|
((cmp[cmpPos] >> 0) & 0xf, (cmp[cmpPos++] >> 4) & 0xf);
|
||||||
|
|
||||||
|
protected virtual int GetChunkEnd(ReadOnlySpan<byte> cmp, ref int cmpPos) =>
|
||||||
|
cmp[cmpPos++] << 0 | cmp[cmpPos++] << 8;
|
||||||
|
|
||||||
|
protected virtual int GetLength(int length, ReadOnlySpan<byte> cmp, ref int cmpPos)
|
||||||
|
{
|
||||||
|
byte sum;
|
||||||
|
|
||||||
|
if (length == 0xf)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
length += sum = cmp[cmpPos++];
|
||||||
|
} while (sum == 0xff);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
AssetStudio/LZ4/LZ4Inv.cs
Normal file
15
AssetStudio/LZ4/LZ4Inv.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class LZ4Inv : LZ4
|
||||||
|
{
|
||||||
|
public new static LZ4Inv Instance => new LZ4Inv();
|
||||||
|
|
||||||
|
protected override (int encCount, int litCount) GetLiteralToken(ReadOnlySpan<byte> cmp, ref int cmpPos) =>
|
||||||
|
((cmp[cmpPos] >> 4) & 0xf, (cmp[cmpPos++] >> 0) & 0xf);
|
||||||
|
|
||||||
|
protected override int GetChunkEnd(ReadOnlySpan<byte> cmp, ref int cmpPos) =>
|
||||||
|
cmp[cmpPos++] << 8 | cmp[cmpPos++] << 0;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user