mirror of
https://github.com/AssetRipper/AssetRipper.TextureDecoder.git
synced 2026-11-13 04:26:30 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13b4f6ee49 | ||
|
|
2cdd532c31 | ||
|
|
d772c2790d | ||
|
|
0201123b0a | ||
|
|
02531ab941 | ||
|
|
2f8d0b4a8b | ||
|
|
0fb5e24d81 | ||
|
|
ec91662b4a | ||
|
|
03713d8d57 | ||
|
|
3cf2170242 | ||
|
|
0a8bae09cf | ||
|
|
a7a12fdd72 | ||
|
|
801edea4cf | ||
|
|
3cb859c6ac | ||
|
|
0738ba4b50 | ||
|
|
09067cecbb | ||
|
|
ec6754a5d2 |
No files matched your search
@@ -12,9 +12,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v7
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v5.1.0
|
uses: actions/setup-dotnet@v6.0.0
|
||||||
with:
|
with:
|
||||||
dotnet-version: 9.0.x
|
dotnet-version: 9.0.x
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AssetRipper.Text.SourceGeneration" Version="1.2.2" />
|
<PackageReference Include="AssetRipper.Text.SourceGeneration" Version="1.2.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -82,14 +82,14 @@ internal static class NumericConversionGenerator
|
|||||||
writer.WriteLine("if (typeof(TFrom) == typeof(TTo))");
|
writer.WriteLine("if (typeof(TFrom) == typeof(TTo))");
|
||||||
using (new CurlyBrackets(writer))
|
using (new CurlyBrackets(writer))
|
||||||
{
|
{
|
||||||
writer.WriteLine("return Unsafe.As<TFrom, TTo>(ref value);");
|
writer.WriteLine("return Unsafe.BitCast<TFrom, TTo>(value);");
|
||||||
}
|
}
|
||||||
foreach (CSharpPrimitives.Data from in CSharpPrimitives.List)
|
foreach (CSharpPrimitives.Data from in CSharpPrimitives.List)
|
||||||
{
|
{
|
||||||
writer.WriteLine($"else if (typeof(TFrom) == typeof({from.LangName}))");
|
writer.WriteLine($"else if (typeof(TFrom) == typeof({from.LangName}))");
|
||||||
using (new CurlyBrackets(writer))
|
using (new CurlyBrackets(writer))
|
||||||
{
|
{
|
||||||
writer.WriteLine($"return {ConvertMethodName(from.Type)}<TTo>(Unsafe.As<TFrom, {from.LangName}>(ref value));");
|
writer.WriteLine($"return {ConvertMethodName(from.Type)}<TTo>(Unsafe.BitCast<TFrom, {from.LangName}>(value));");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.WriteLine("else");
|
writer.WriteLine("else");
|
||||||
@@ -133,32 +133,32 @@ internal static class NumericConversionGenerator
|
|||||||
{
|
{
|
||||||
if (from == to)
|
if (from == to)
|
||||||
{
|
{
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref value);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(value);");
|
||||||
}
|
}
|
||||||
else if (to.HasPointerSize(out CSharpPrimitives.Data? bit32To, out CSharpPrimitives.Data? bit64To))
|
else if (to.HasPointerSize(out CSharpPrimitives.Data? bit32To, out CSharpPrimitives.Data? bit64To))
|
||||||
{
|
{
|
||||||
using (new If(writer, "IntPtr.Size == sizeof(int)"))
|
using (new If(writer, "IntPtr.Size == sizeof(int)"))
|
||||||
{
|
{
|
||||||
writer.WriteLine($"{to.LangName} converted = ({to.LangName}){methodName}<{bit32To.LangName}>(value);");
|
writer.WriteLine($"{to.LangName} converted = ({to.LangName}){methodName}<{bit32To.LangName}>(value);");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
using (new Else(writer))
|
using (new Else(writer))
|
||||||
{
|
{
|
||||||
writer.WriteLine($"{to.LangName} converted = ({to.LangName}){methodName}<{bit64To.LangName}>(value);");
|
writer.WriteLine($"{to.LangName} converted = ({to.LangName}){methodName}<{bit64To.LangName}>(value);");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (to.IsSignedInteger(out CSharpPrimitives.Data? unsignedTo))
|
else if (to.IsSignedInteger(out CSharpPrimitives.Data? unsignedTo))
|
||||||
{
|
{
|
||||||
writer.WriteLine($"{to.LangName} converted = {ChangeSign}({methodName}<{unsignedTo.LangName}>(value));");
|
writer.WriteLine($"{to.LangName} converted = {ChangeSign}({methodName}<{unsignedTo.LangName}>(value));");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
else if (from.IsFloatingPoint)
|
else if (from.IsFloatingPoint)
|
||||||
{
|
{
|
||||||
if (to.IsFloatingPoint)
|
if (to.IsFloatingPoint)
|
||||||
{
|
{
|
||||||
writer.WriteLine($"{to.LangName} converted = ({to.LangName})value;");
|
writer.WriteLine($"{to.LangName} converted = ({to.LangName})value;");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -176,7 +176,7 @@ internal static class NumericConversionGenerator
|
|||||||
string maxValue = to.MaxValue;
|
string maxValue = to.MaxValue;
|
||||||
writer.WriteLine($"{from.LangName} x = value * ({from.LangName}){maxValue};");
|
writer.WriteLine($"{from.LangName} x = value * ({from.LangName}){maxValue};");
|
||||||
writer.WriteLine($"{to.LangName} converted = ({from.LangName}){maxValue} < x ? {maxValue} : (x > ({from.LangName}){minValue} ? ({to.LangName})x : {minValue});");
|
writer.WriteLine($"{to.LangName} converted = ({from.LangName}){maxValue} < x ? {maxValue} : (x > ({from.LangName}){minValue} ? ({to.LangName})x : {minValue});");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,12 +191,12 @@ internal static class NumericConversionGenerator
|
|||||||
writer.WriteComment($"There isn't enough precision to convert from {from.LangName} to {to.LangName}, so we convert to {conversionType.LangName} first.");
|
writer.WriteComment($"There isn't enough precision to convert from {from.LangName} to {to.LangName}, so we convert to {conversionType.LangName} first.");
|
||||||
writer.WriteLine($"{conversionType.LangName} x = {methodName}<{conversionType.LangName}>(value);");
|
writer.WriteLine($"{conversionType.LangName} x = {methodName}<{conversionType.LangName}>(value);");
|
||||||
writer.WriteLine($"{to.LangName} converted = ({to.LangName})x;");
|
writer.WriteLine($"{to.LangName} converted = ({to.LangName})x;");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
writer.WriteLine($"{to.LangName} converted = ({to.LangName})value / ({to.LangName}){from.MaxValue};");
|
writer.WriteLine($"{to.LangName} converted = ({to.LangName})value / ({to.LangName}){from.MaxValue};");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -216,7 +216,7 @@ internal static class NumericConversionGenerator
|
|||||||
writer.Write($"(({conversionType})value << {i * from.Size * 8}) | ");
|
writer.Write($"(({conversionType})value << {i * from.Size * 8}) | ");
|
||||||
}
|
}
|
||||||
writer.WriteLine("value);");
|
writer.WriteLine("value);");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -227,14 +227,14 @@ internal static class NumericConversionGenerator
|
|||||||
writer.WriteComment("This is a special case where we already know an optimal algorithm.");
|
writer.WriteComment("This is a special case where we already know an optimal algorithm.");
|
||||||
writer.WriteLine("uint x = (value * 255u + 32895u) >> 16;");
|
writer.WriteLine("uint x = (value * 255u + 32895u) >> 16;");
|
||||||
writer.WriteLine("byte converted = unchecked((byte)x);");
|
writer.WriteLine("byte converted = unchecked((byte)x);");
|
||||||
writer.WriteLine("return Unsafe.As<byte, TTo>(ref converted);");
|
writer.WriteLine("return Unsafe.BitCast<byte, TTo>(converted);");
|
||||||
}
|
}
|
||||||
else if (from.Size < sizeof(double) && to.Size < sizeof(double))
|
else if (from.Size < sizeof(double) && to.Size < sizeof(double))
|
||||||
{
|
{
|
||||||
writer.WriteLine($"double interpolated = (double)value / (double){from.MaxValue};");
|
writer.WriteLine($"double interpolated = (double)value / (double){from.MaxValue};");
|
||||||
writer.WriteLine($"double exact = interpolated * (double){to.MaxValue};");
|
writer.WriteLine($"double exact = interpolated * (double){to.MaxValue};");
|
||||||
writer.WriteLine($"{to.LangName} converted = ({to.LangName})double.Round(exact, MidpointRounding.AwayFromZero);");
|
writer.WriteLine($"{to.LangName} converted = ({to.LangName})double.Round(exact, MidpointRounding.AwayFromZero);");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -245,7 +245,7 @@ internal static class NumericConversionGenerator
|
|||||||
{
|
{
|
||||||
int offset = (from.Size / to.Size - 1) * to.Size * 8;
|
int offset = (from.Size / to.Size - 1) * to.Size * 8;
|
||||||
writer.WriteLine($"{to.LangName} converted = ({to.LangName})(({conversionType})value >> {offset});");
|
writer.WriteLine($"{to.LangName} converted = ({to.LangName})(({conversionType})value >> {offset});");
|
||||||
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
|
writer.WriteLine($"return Unsafe.BitCast<{to.LangName}, TTo>(converted);");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,7 +276,7 @@ internal static class NumericConversionGenerator
|
|||||||
using (new CurlyBrackets(writer))
|
using (new CurlyBrackets(writer))
|
||||||
{
|
{
|
||||||
writer.WriteLine($"{from.LangName} value = {methodName}Safe<{from.LangName}>();");
|
writer.WriteLine($"{from.LangName} value = {methodName}Safe<{from.LangName}>();");
|
||||||
writer.WriteLine($"return Unsafe.As<{from.LangName}, T>(ref value);");
|
writer.WriteLine($"return Unsafe.BitCast<{from.LangName}, T>(value);");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.WriteLine("else");
|
writer.WriteLine("else");
|
||||||
|
|||||||
@@ -13,18 +13,23 @@ internal static partial class Program
|
|||||||
private const string FormatsNamespace = "AssetRipper.TextureDecoder.Rgb.Formats";
|
private const string FormatsNamespace = "AssetRipper.TextureDecoder.Rgb.Formats";
|
||||||
private const string FormatsFolder = "../../../../AssetRipper.TextureDecoder/Rgb/Formats/";
|
private const string FormatsFolder = "../../../../AssetRipper.TextureDecoder/Rgb/Formats/";
|
||||||
|
|
||||||
/// <summary>
|
private readonly record struct CustomColorDetails(string Name, Type Type, bool HasRed, bool HasGreen, bool HasBlue, bool HasAlpha, bool FullyUtilized)
|
||||||
/// Name, Type, Red, Blue, Green, Alpha, Fully Utilized
|
|
||||||
/// </summary>
|
|
||||||
private static readonly List<(string, Type, bool, bool, bool, bool, bool)> CustomColors = new()
|
|
||||||
{
|
{
|
||||||
|
public static implicit operator CustomColorDetails((string, Type, bool, bool, bool, bool, bool) details)
|
||||||
|
{
|
||||||
|
return new CustomColorDetails(details.Item1, details.Item2, details.Item3, details.Item4, details.Item5, details.Item6, details.Item7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly CustomColorDetails[] CustomColors =
|
||||||
|
[
|
||||||
( "ColorARGB16", typeof(byte), true, true, true, true, false ),
|
( "ColorARGB16", typeof(byte), true, true, true, true, false ),
|
||||||
( "ColorRGB16", typeof(byte), true, true, true, false, false ),
|
( "ColorRGB16", typeof(byte), true, true, true, false, false ),
|
||||||
( "ColorRGB9e5", typeof(double), true, true, true, false, false ),
|
( "ColorRGB9e5", typeof(double), true, true, true, false, false ),
|
||||||
( "ColorRGBA16", typeof(byte), true, true, true, true, false ),
|
( "ColorRGBA16", typeof(byte), true, true, true, true, false ),
|
||||||
};
|
];
|
||||||
|
|
||||||
private static readonly List<string> GenericColors =
|
private static readonly string[] GenericColors =
|
||||||
[
|
[
|
||||||
"ColorR",
|
"ColorR",
|
||||||
"ColorRG",
|
"ColorRG",
|
||||||
@@ -38,7 +43,7 @@ internal static partial class Program
|
|||||||
|
|
||||||
static void Main()
|
static void Main()
|
||||||
{
|
{
|
||||||
foreach (var customColor in CustomColors)
|
foreach (CustomColorDetails customColor in CustomColors)
|
||||||
{
|
{
|
||||||
WriteCustomColor(customColor);
|
WriteCustomColor(customColor);
|
||||||
}
|
}
|
||||||
@@ -54,7 +59,7 @@ internal static partial class Program
|
|||||||
Console.WriteLine("Done!");
|
Console.WriteLine("Done!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteCustomColor((string, Type, bool, bool, bool, bool, bool) details)
|
private static void WriteCustomColor(CustomColorDetails details)
|
||||||
{
|
{
|
||||||
(string name, Type type, bool hasRed, bool hasGreen, bool hasBlue, bool hasAlpha, bool fullyUtilized) = details;
|
(string name, Type type, bool hasRed, bool hasGreen, bool hasBlue, bool hasAlpha, bool fullyUtilized) = details;
|
||||||
Console.WriteLine(name);
|
Console.WriteLine(name);
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AssetRipper.Text.SourceGeneration" Version="1.2.2" />
|
<PackageReference Include="AssetRipper.Text.SourceGeneration" Version="1.2.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -5,17 +5,13 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.9.0" />
|
||||||
<PackageReference Include="NUnit" Version="4.4.0" />
|
<PackageReference Include="NUnit" Version="4.6.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="6.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="6.2.0" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.11.2">
|
<PackageReference Include="NUnit.Analyzers" Version="4.14.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ public sealed class AstcTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(new byte[16] { 83, 1, 147, 104, 198, 173, 55, 116, 182, 66, 105, 11, 102, 43, 148, 125 }, 8, 8, TestName = "GetBits Should not throw in DecodeIntseq")]
|
[TestCase(new byte[16] { 83, 1, 147, 104, 198, 173, 55, 116, 182, 66, 105, 11, 102, 43, 148, 125 }, 8, 8, TestName = "GetBits Should not throw in DecodeIntseq")]
|
||||||
|
[TestCase(new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 8, 8, TestName = "Zero blocks should not throw", Description = "Blocks of all zeros are valid")]
|
||||||
|
[TestCase(new byte[16] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, 8, 8, TestName = "0xFF blocks should not throw", Description = "Blocks with all bits set are invalid, but should be handled gracefully")]
|
||||||
public void DecodesBlockWithoutThrowing(byte[] block, int blockWidth, int blockHeight)
|
public void DecodesBlockWithoutThrowing(byte[] block, int blockWidth, int blockHeight)
|
||||||
{
|
{
|
||||||
Assert.DoesNotThrow(() => AstcDecoder.DecodeASTC<ColorBGRA<byte>, byte>(block, blockWidth, blockHeight, blockWidth, blockHeight, out _));
|
Assert.DoesNotThrow(() => AstcDecoder.DecodeASTC<ColorBGRA<byte>, byte>(block, blockWidth, blockHeight, blockWidth, blockHeight, out _));
|
||||||
|
|||||||
File renamed without changes.
@@ -1,9 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<IsTrimmable>true</IsTrimmable>
|
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
|
||||||
<PackageId>AssetRipper.TextureDecoder</PackageId>
|
<PackageId>AssetRipper.TextureDecoder</PackageId>
|
||||||
<PackageTags>C# Texture</PackageTags>
|
<PackageTags>C# Texture</PackageTags>
|
||||||
<RepositoryUrl>https://github.com/AssetRipper/TextureDecoder</RepositoryUrl>
|
<RepositoryUrl>https://github.com/AssetRipper/TextureDecoder</RepositoryUrl>
|
||||||
@@ -15,12 +15,11 @@
|
|||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<DocumentationFile>bin\TextureDecoder.xml</DocumentationFile>
|
|
||||||
<NoWarn>1591</NoWarn>
|
<NoWarn>1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.102">
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.400">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace AssetRipper.TextureDecoder.Astc
|
|||||||
where TOutputChannelValue : unmanaged
|
where TOutputChannelValue : unmanaged
|
||||||
where TOutputColor : unmanaged, IColor<TOutputChannelValue>
|
where TOutputColor : unmanaged, IColor<TOutputChannelValue>
|
||||||
{
|
{
|
||||||
output = new byte[width * height * 4];
|
output = new byte[width * height * Unsafe.SizeOf<TOutputColor>()];
|
||||||
return DecodeASTC<TOutputColor, TOutputChannelValue>(input, width, height, blockWidth, blockHeight, output);
|
return DecodeASTC<TOutputColor, TOutputChannelValue>(input, width, height, blockWidth, blockHeight, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,10 +66,7 @@ namespace AssetRipper.TextureDecoder.Astc
|
|||||||
if (input[0] == 0xfc && (input[1] & 1) == 1)
|
if (input[0] == 0xfc && (input[1] & 1) == 1)
|
||||||
{
|
{
|
||||||
ColorRGBA<byte> c = new(input[9], input[11], input[13], input[15]);
|
ColorRGBA<byte> c = new(input[9], input[11], input[13], input[15]);
|
||||||
for (int i = 0; i < blockWidth * blockHeight; i++)
|
output[..(blockWidth * blockHeight)].Fill(c);
|
||||||
{
|
|
||||||
output[i] = c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -886,6 +883,11 @@ namespace AssetRipper.TextureDecoder.Astc
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static int GetBits(ReadOnlySpan<byte> input, int bit, int len)
|
private static int GetBits(ReadOnlySpan<byte> input, int bit, int len)
|
||||||
{
|
{
|
||||||
|
if (bit < 0 || input.Length * 8 < bit + len)
|
||||||
|
{
|
||||||
|
// Invalid input, but we should return something instead of throwing an exception
|
||||||
|
return default;
|
||||||
|
}
|
||||||
ReadOnlySpan<byte> slice = input[(bit / 8)..];
|
ReadOnlySpan<byte> slice = input[(bit / 8)..];
|
||||||
int bitBuffer;
|
int bitBuffer;
|
||||||
if (slice.Length >= sizeof(int))
|
if (slice.Length >= sizeof(int))
|
||||||
|
|||||||
@@ -76,16 +76,16 @@ internal static class BinaryWriterExtensions
|
|||||||
switch (Unsafe.SizeOf<T>())
|
switch (Unsafe.SizeOf<T>())
|
||||||
{
|
{
|
||||||
case sizeof(byte):
|
case sizeof(byte):
|
||||||
writer.Write(Unsafe.As<T, byte>(ref value));
|
writer.Write(Unsafe.BitCast<T, byte>(value));
|
||||||
break;
|
break;
|
||||||
case sizeof(ushort):
|
case sizeof(ushort):
|
||||||
writer.Write(Unsafe.As<T, ushort>(ref value));
|
writer.Write(Unsafe.BitCast<T, ushort>(value));
|
||||||
break;
|
break;
|
||||||
case sizeof(uint):
|
case sizeof(uint):
|
||||||
writer.Write(Unsafe.As<T, uint>(ref value));
|
writer.Write(Unsafe.BitCast<T, uint>(value));
|
||||||
break;
|
break;
|
||||||
case sizeof(ulong):
|
case sizeof(ulong):
|
||||||
writer.Write(Unsafe.As<T, ulong>(ref value));
|
writer.Write(Unsafe.BitCast<T, ulong>(value));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ public readonly record struct ExrChannelList(ExrChannel[] Channels) : IExrDataTy
|
|||||||
{
|
{
|
||||||
public static ReadOnlySpan<byte> TypeName => "chlist"u8;
|
public static ReadOnlySpan<byte> TypeName => "chlist"u8;
|
||||||
|
|
||||||
public int Size => Channels.Sum(c => c.Size);
|
public int Size => Channels.Sum(c => c.Size) + sizeof(byte);
|
||||||
|
|
||||||
public void Write(BinaryWriter writer)
|
public void Write(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public static class ExrWriter
|
|||||||
for (int i = 0; i < height; i++)
|
for (int i = 0; i < height; i++)
|
||||||
{
|
{
|
||||||
writer.Write(offset);
|
writer.Write(offset);
|
||||||
offset += sizeof(int) + ChannelCount * ChannelSize * width;
|
offset += sizeof(int) + sizeof(int) + ChannelCount * ChannelSize * width;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Scan lines
|
//Scan lines
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public static class Color
|
|||||||
{
|
{
|
||||||
if (typeof(TThis) == typeof(TTarget))
|
if (typeof(TThis) == typeof(TTarget))
|
||||||
{
|
{
|
||||||
return Unsafe.As<TThis, TTarget>(ref color);
|
return Unsafe.BitCast<TThis, TTarget>(color);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public static partial class NumericConversion
|
|||||||
|
|
||||||
TFrom SignBit = TFrom.One << (Unsafe.SizeOf<TFrom>() * 8 - 1);
|
TFrom SignBit = TFrom.One << (Unsafe.SizeOf<TFrom>() * 8 - 1);
|
||||||
TFrom converted = (SignBit ^ value);
|
TFrom converted = (SignBit ^ value);
|
||||||
return Unsafe.As<TFrom, TTo>(ref converted);
|
return Unsafe.BitCast<TFrom, TTo>(converted);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
@@ -56,6 +56,6 @@ public static partial class NumericConversion
|
|||||||
}
|
}
|
||||||
|
|
||||||
TTo SignBit = TTo.One << (Unsafe.SizeOf<TTo>() * 8 - 1);
|
TTo SignBit = TTo.One << (Unsafe.SizeOf<TTo>() * 8 - 1);
|
||||||
return SignBit ^ Unsafe.As<TFrom, TTo>(ref value);
|
return SignBit ^ Unsafe.BitCast<TFrom, TTo>(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -6,7 +6,7 @@
|
|||||||
<IsAotCompatible>true</IsAotCompatible>
|
<IsAotCompatible>true</IsAotCompatible>
|
||||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||||
|
|
||||||
<VersionPrefix>2.6.0</VersionPrefix>
|
<VersionPrefix>2.6.3</VersionPrefix>
|
||||||
<Copyright>Copyright © ds5678</Copyright>
|
<Copyright>Copyright © ds5678</Copyright>
|
||||||
<Authors>ds5678</Authors>
|
<Authors>ds5678</Authors>
|
||||||
<Company>AssetRipper</Company>
|
<Company>AssetRipper</Company>
|
||||||
|
|||||||
Reference in new issue
Block a user