|
|
|
@@ -6,6 +6,16 @@ namespace AssetRipper.Conversions.UnityCrunch;
|
|
|
|
|
|
|
|
|
|
public static partial class UnityCrunch
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <see href="https://github.com/Unity-Technologies/crunch/blob/8708900eca8ec609d279270e72936258f81ddfb7/inc/crnlib.h#L92"/>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const int MaxFaces = 6;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <see href="https://github.com/Unity-Technologies/crunch/blob/8708900eca8ec609d279270e72936258f81ddfb7/inc/crnlib.h#L93"/>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const int MaxLevels = 16;
|
|
|
|
|
|
|
|
|
|
public static bool TryDecompress(ReadOnlySpan<byte> input, [NotNullWhen(true)] out byte[]? output)
|
|
|
|
|
{
|
|
|
|
|
return TryDecompress(input, 0, out output);
|
|
|
|
@@ -35,16 +45,33 @@ public static partial class UnityCrunch
|
|
|
|
|
return False(out output);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// m_struct_size
|
|
|
|
|
int width = int.Max(1, textureInfo.field_1 >> levelIndex);
|
|
|
|
|
int height = int.Max(1, textureInfo.field_2 >> levelIndex);
|
|
|
|
|
int blocksX = int.Max(1, (width + 3) >> 2);
|
|
|
|
|
int blocksY = int.Max(1, (height + 3) >> 2);
|
|
|
|
|
// m_levels
|
|
|
|
|
int faceCount = textureInfo.field_4;
|
|
|
|
|
int bytesPerBlock = textureInfo.field_5;
|
|
|
|
|
// m_userdata0
|
|
|
|
|
// m_userdata1
|
|
|
|
|
// m_format
|
|
|
|
|
|
|
|
|
|
int blocksX = (width + 3) >> 2;
|
|
|
|
|
int blocksY = (height + 3) >> 2;
|
|
|
|
|
int rowPitch = blocksX * crnd_get_bytes_per_dxt_block(textureInfo.field_8);
|
|
|
|
|
int totalFaceSize = rowPitch * blocksY;
|
|
|
|
|
int faceSize = rowPitch * blocksY;
|
|
|
|
|
int totalFaceSize = faceCount * faceSize;
|
|
|
|
|
|
|
|
|
|
byte[] result = new byte[totalFaceSize];
|
|
|
|
|
|
|
|
|
|
fixed (byte* pResult = result)
|
|
|
|
|
{
|
|
|
|
|
if (!crnd_unpack_level(context, &pResult, totalFaceSize, rowPitch, levelIndex))
|
|
|
|
|
byte** pResultArray = stackalloc byte*[MaxFaces] { null, null, null, null, null, null };
|
|
|
|
|
for (int i = 0; i < faceCount; i++)
|
|
|
|
|
{
|
|
|
|
|
pResultArray[i] = pResult + i * faceSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!crnd_unpack_level(context, pResultArray, faceSize, rowPitch, levelIndex))
|
|
|
|
|
{
|
|
|
|
|
crnd_unpack_end(context);
|
|
|
|
|
return False(out output);
|
|
|
|
|