Skip to content

Commit 78a8f18

Browse files
committed
Only use safe code for AtcDecoder
1 parent 696a677 commit 78a8f18

4 files changed

Lines changed: 24 additions & 40 deletions

File tree

AssetRipper.TextureDecoder.Tests/AtcTests.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,25 @@ public sealed class AtcTests
55
[Test]
66
public void DecompressAtcRgb4Test()
77
{
8-
ReadOnlySpan<byte> data = File.ReadAllBytes(TestFileFolders.AtcTestFiles + "test.atc_rgb4");
9-
int bytesRead = Atc.AtcDecoder.DecompressAtcRgb4(data, 256, 256, out _);
10-
Assert.That(bytesRead, Is.EqualTo(data.Length));
8+
byte[] data = File.ReadAllBytes(TestFileFolders.AtcTestFiles + "test.atc_rgb4");
9+
int bytesRead = Atc.AtcDecoder.DecompressAtcRgb4(data, 256, 256, out byte[] decodedData);
10+
Assert.Multiple(() =>
11+
{
12+
Assert.That(bytesRead, Is.EqualTo(data.Length));
13+
Assert.That(decodedData, Is.EqualTo(File.ReadAllBytes(TestFileFolders.AtcTestFiles + "test.atc_rgb4_decoded")));
14+
});
1115
}
1216

1317
[Test]
1418
public void DecompressAtcRgba8Test()
1519
{
16-
ReadOnlySpan<byte> data = File.ReadAllBytes(TestFileFolders.AtcTestFiles + "test.atc_rgba8");
17-
int bytesRead = Atc.AtcDecoder.DecompressAtcRgba8(data, 256, 256, out _);
18-
Assert.That(bytesRead, Is.EqualTo(data.Length));
20+
byte[] data = File.ReadAllBytes(TestFileFolders.AtcTestFiles + "test.atc_rgba8");
21+
int bytesRead = Atc.AtcDecoder.DecompressAtcRgba8(data, 256, 256, out byte[] decodedData);
22+
Assert.Multiple(() =>
23+
{
24+
Assert.That(bytesRead, Is.EqualTo(data.Length));
25+
Assert.That(decodedData, Is.EqualTo(File.ReadAllBytes(TestFileFolders.AtcTestFiles + "test.atc_rgba8_decoded")));
26+
});
1927
}
2028
}
2129
}

AssetRipper.TextureDecoder/Atc/AtcDecoder.cs

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,26 @@ public static int DecompressAtcRgb4(ReadOnlySpan<byte> input, int width, int hei
1111
return DecompressAtcRgb4(input, width, height, output);
1212
}
1313

14-
public unsafe static int DecompressAtcRgb4(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
15-
{
16-
fixed (byte* outputPtr = output)
17-
{
18-
return DecompressAtcRgb4(input, width, height, outputPtr);
19-
}
20-
}
21-
22-
private unsafe static int DecompressAtcRgb4(ReadOnlySpan<byte> input, int width, int height, byte* output)
14+
public static int DecompressAtcRgb4(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
2315
{
2416
int bcw = (width + 3) / 4;
2517
int bch = (height + 3) / 4;
2618
int clen_last = (width + 3) % 4 + 1;
27-
uint* buf = stackalloc uint[16];
19+
Span<uint> buf = stackalloc uint[16];
2820
int inputOffset = 0;
2921
for (int t = 0; t < bch; t++)
3022
{
3123
for (int s = 0; s < bcw; s++, inputOffset += 8)
3224
{
33-
DecodeAtcRgb4Block(input.Slice(inputOffset, 8), new Span<uint>(buf, 16));
25+
DecodeAtcRgb4Block(input.Slice(inputOffset, 8), buf);
3426
int clen = s < bcw - 1 ? 4 : clen_last;
35-
uint* outputPtr = (uint*)(output + (t * 16 * width + s * 16));
36-
uint* bufPtr = buf;
3727
for (int i = 0, y = t * 4; i < 4 && y < height; i++, y++)
3828
{
29+
int outputOffset = t * 16 * width + s * 16 + i * width * sizeof(uint);
3930
for (int j = 0; j < clen; j++)
4031
{
41-
outputPtr[j] = bufPtr[j];
32+
BinaryPrimitives.WriteUInt32LittleEndian(output.Slice(outputOffset + j * sizeof(uint)), buf[j + 4 * i]);
4233
}
43-
44-
outputPtr += width;
45-
bufPtr += 4;
4634
}
4735
}
4836
}
@@ -55,38 +43,26 @@ public static int DecompressAtcRgba8(ReadOnlySpan<byte> input, int width, int he
5543
return DecompressAtcRgba8(input, width, height, output);
5644
}
5745

58-
public unsafe static int DecompressAtcRgba8(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
59-
{
60-
fixed (byte* outputPtr = output)
61-
{
62-
return DecompressAtcRgba8(input, width, height, outputPtr);
63-
}
64-
}
65-
66-
private unsafe static int DecompressAtcRgba8(ReadOnlySpan<byte> input, int width, int height, byte* output)
46+
public static int DecompressAtcRgba8(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
6747
{
6848
int bcw = (width + 3) / 4;
6949
int bch = (height + 3) / 4;
7050
int clen_last = (width + 3) % 4 + 1;
71-
uint* buf = stackalloc uint[16];
51+
Span<uint> buf = stackalloc uint[16];
7252
int inputOffset = 0;
7353
for (int t = 0; t < bch; t++)
7454
{
7555
for (int s = 0; s < bcw; s++, inputOffset += 16)
7656
{
77-
DecodeAtcRgba8Block(input.Slice(inputOffset, 16), new Span<uint>(buf, 16));
57+
DecodeAtcRgba8Block(input.Slice(inputOffset, 16), buf);
7858
int clen = s < bcw - 1 ? 4 : clen_last;
79-
uint* outputPtr = (uint*)(output + (t * 16 * width + s * 16));
80-
uint* bufPtr = buf;
8159
for (int i = 0, y = t * 4; i < 4 && y < height; i++, y++)
8260
{
61+
int outputOffset = t * 16 * width + s * 16 + i * width * sizeof(uint);
8362
for (int j = 0; j < clen; j++)
8463
{
85-
outputPtr[j] = bufPtr[j];
64+
BinaryPrimitives.WriteUInt32LittleEndian(output.Slice(outputOffset + j * sizeof(uint)), buf[j + 4 * i]);
8665
}
87-
88-
outputPtr += width;
89-
bufPtr += 4;
9066
}
9167
}
9268
}
256 KB
Binary file not shown.
256 KB
Binary file not shown.

0 commit comments

Comments
 (0)