More fixes to 3ds formats. Fix gzip decompressing giving wrong size.
This commit is contained in:
parent
a905fcab5e
commit
017c1ab1e3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -385,6 +385,7 @@ namespace FirstPlugin
|
||||
{
|
||||
return new TEX_FORMAT[]
|
||||
{
|
||||
|
||||
TEX_FORMAT.BC1_UNORM,
|
||||
TEX_FORMAT.BC1_UNORM_SRGB,
|
||||
TEX_FORMAT.BC2_UNORM,
|
||||
@ -395,19 +396,22 @@ namespace FirstPlugin
|
||||
TEX_FORMAT.BC4_SNORM,
|
||||
TEX_FORMAT.BC5_UNORM,
|
||||
TEX_FORMAT.BC5_SNORM,
|
||||
TEX_FORMAT.B5G5R5A1_UNORM,
|
||||
TEX_FORMAT.B5G6R5_UNORM,
|
||||
TEX_FORMAT.B8G8R8A8_UNORM_SRGB,
|
||||
TEX_FORMAT.B8G8R8A8_UNORM,
|
||||
TEX_FORMAT.R10G10B10A2_UNORM,
|
||||
TEX_FORMAT.R16_UNORM,
|
||||
TEX_FORMAT.B4G4R4A4_UNORM,
|
||||
TEX_FORMAT.B5_G5_R5_A1_UNORM,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM_SRGB,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM,
|
||||
TEX_FORMAT.R8_UNORM,
|
||||
TEX_FORMAT.R8G8_UNORM,
|
||||
TEX_FORMAT.R32G8X24_FLOAT,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM_SRGB,
|
||||
TEX_FORMAT.R8G8_SNORM,
|
||||
TEX_FORMAT.B4G4R4A4_UNORM,
|
||||
TEX_FORMAT.ETC1,
|
||||
TEX_FORMAT.ETC1_A4,
|
||||
TEX_FORMAT.HIL08,
|
||||
TEX_FORMAT.L4,
|
||||
TEX_FORMAT.A4,
|
||||
TEX_FORMAT.L8,
|
||||
TEX_FORMAT.A8_UNORM,
|
||||
TEX_FORMAT.LA8,
|
||||
TEX_FORMAT.LA4,
|
||||
TEX_FORMAT.B5G5R5A1_UNORM,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -430,7 +434,7 @@ namespace FirstPlugin
|
||||
T_BC5_SNORM = 12,
|
||||
TC_R8_UNORM = 13,
|
||||
TC_R8_G8_UNORM = 14,
|
||||
TCS_R8_G8_B8_A8_UNORM = 15,
|
||||
TC_R8_G8_B8_A8_SRGB = 15,
|
||||
TC_R8_SNORM = 16,
|
||||
TC_R4_R4_SNORM = 17,
|
||||
ETC1_A4 = 18,
|
||||
@ -440,7 +444,13 @@ namespace FirstPlugin
|
||||
A4 = 22,
|
||||
L8 = 23,
|
||||
A8 = 24,
|
||||
TCS_R5_G6_B5_UNORM = 25,
|
||||
LA4 = 25,
|
||||
LA8 = 26,
|
||||
TCS_R5_G5_B5_A1_UNORM = 27,
|
||||
TC_R4_G4_B4_UNORM = 28,
|
||||
TC_R8_G8_B8_A8_UNORM = 29,
|
||||
TC_R8_G8_B8_UNORM = 30,
|
||||
TCS_R5_G6_B5_UNORM = 31,
|
||||
};
|
||||
|
||||
public uint TileMode;
|
||||
@ -465,6 +475,7 @@ namespace FirstPlugin
|
||||
{
|
||||
CanReplace = true;
|
||||
CanRename = false;
|
||||
PlatformSwizzle = PlatformSwizzle.Platform_3DS;
|
||||
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadUInt16();
|
||||
@ -558,14 +569,13 @@ namespace FirstPlugin
|
||||
case SurfaceFormat.TC_R8_G8_UNORM:
|
||||
Format = TEX_FORMAT.R8G8_UNORM;
|
||||
break;
|
||||
case SurfaceFormat.TCS_R8_G8_B8_A8_UNORM:
|
||||
Format = TEX_FORMAT.R8G8B8A8_UNORM;
|
||||
case SurfaceFormat.TC_R8_G8_B8_A8_SRGB:
|
||||
Format = TEX_FORMAT.R8G8B8A8_UNORM_SRGB;
|
||||
break;
|
||||
case SurfaceFormat.TCS_R8_G8_B8_A8:
|
||||
Format = TEX_FORMAT.R8G8B8A8_UNORM;
|
||||
break;
|
||||
case SurfaceFormat.TC_R8_UNORM:
|
||||
GX2Format = (uint)GX2.GX2SurfaceFormat.TC_R8_UNORM;
|
||||
Format = TEX_FORMAT.R8_UNORM;
|
||||
break;
|
||||
case SurfaceFormat.TCS_R5_G6_B5_UNORM:
|
||||
@ -578,10 +588,28 @@ namespace FirstPlugin
|
||||
Format = TEX_FORMAT.ETC1_A4;
|
||||
break;
|
||||
case SurfaceFormat.L4:
|
||||
// Format = TEX_FORMAT.A8_UNORM;
|
||||
Format = TEX_FORMAT.L4;
|
||||
break;
|
||||
case SurfaceFormat.L8:
|
||||
// Format = TEX_FORMAT.A8_UNORM;
|
||||
Format = TEX_FORMAT.L8;
|
||||
break;
|
||||
case SurfaceFormat.LA4:
|
||||
Format = TEX_FORMAT.LA4;
|
||||
break;
|
||||
case SurfaceFormat.LA8:
|
||||
Format = TEX_FORMAT.LA8;
|
||||
break;
|
||||
case SurfaceFormat.HIL08:
|
||||
Format = TEX_FORMAT.HIL08;
|
||||
break;
|
||||
case SurfaceFormat.TC_R8_G8_B8_A8_UNORM:
|
||||
Format = TEX_FORMAT.R8G8B8A8_UNORM;
|
||||
break;
|
||||
case SurfaceFormat.TC_R4_G4_B4_UNORM:
|
||||
Format = TEX_FORMAT.B4G4R4A4_UNORM;
|
||||
break;
|
||||
case SurfaceFormat.TC_R8_G8_B8_UNORM:
|
||||
Format = TEX_FORMAT.R8G8B8A8_UNORM;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Format unsupported! " + SurfFormat);
|
||||
|
@ -189,6 +189,7 @@ namespace FirstPlugin
|
||||
|
||||
while (reader.Position < reader.BaseStream.Length)
|
||||
{
|
||||
Console.WriteLine("BLOCK POS " + reader.Position + " " + reader.BaseStream.Length);
|
||||
GTXDataBlock block = new GTXDataBlock();
|
||||
block.Read(reader);
|
||||
blocks.Add(block);
|
||||
|
Binary file not shown.
Binary file not shown.
45
Switch_Toolbox_Library/FileFormats/3DS/A8.cs
Normal file
45
Switch_Toolbox_Library/FileFormats/3DS/A8.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
namespace Switch_Toolbox.Library
|
||||
{
|
||||
public class A8
|
||||
{
|
||||
public static byte[] Decompress(byte[] Input, int Width, int Height, bool Alpha)
|
||||
{
|
||||
byte[] Output = new byte[Width * Height * 4];
|
||||
|
||||
int bpp = 16;
|
||||
int Increment = bpp / 8;
|
||||
|
||||
int IOffset = 0;
|
||||
|
||||
for (int TY = 0; TY < Height; TY += 8)
|
||||
{
|
||||
for (int TX = 0; TX < Width; TX += 8)
|
||||
{
|
||||
for (int Px = 0; Px < 64; Px++)
|
||||
{
|
||||
int X = Swizzle_3DS.SwizzleLUT[Px] & 7;
|
||||
int Y = (Swizzle_3DS.SwizzleLUT[Px] - X) >> 3;
|
||||
|
||||
int OOffet = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;
|
||||
|
||||
Output[OOffet + 0] = 0xff;
|
||||
Output[OOffet + 1] = 0xff;
|
||||
Output[OOffet + 2] = 0xff;
|
||||
Output[OOffet + 3] = Input[IOffset];
|
||||
|
||||
IOffset += Increment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
}
|
||||
}
|
45
Switch_Toolbox_Library/FileFormats/3DS/HiLo8.cs
Normal file
45
Switch_Toolbox_Library/FileFormats/3DS/HiLo8.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
namespace Switch_Toolbox.Library
|
||||
{
|
||||
public class HiLo8
|
||||
{
|
||||
public static byte[] Decompress(byte[] Input, int Width, int Height, bool Alpha)
|
||||
{
|
||||
byte[] Output = new byte[Width * Height * 4];
|
||||
|
||||
int bpp = 16;
|
||||
int Increment = 16 / 8;
|
||||
|
||||
int IOffset = 0;
|
||||
|
||||
for (int TY = 0; TY < Height; TY += 8)
|
||||
{
|
||||
for (int TX = 0; TX < Width; TX += 8)
|
||||
{
|
||||
for (int Px = 0; Px < 64; Px++)
|
||||
{
|
||||
int X = Swizzle_3DS.SwizzleLUT[Px] & 7;
|
||||
int Y = (Swizzle_3DS.SwizzleLUT[Px] - X) >> 3;
|
||||
|
||||
int OOffet = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;
|
||||
|
||||
Output[OOffet + 0] = Input[IOffset + 1];
|
||||
Output[OOffet + 1] = Input[IOffset + 0];
|
||||
Output[OOffet + 2] = 0;
|
||||
Output[OOffet + 3] = 0xff;
|
||||
|
||||
IOffset += Increment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
}
|
||||
}
|
46
Switch_Toolbox_Library/FileFormats/3DS/L4.cs
Normal file
46
Switch_Toolbox_Library/FileFormats/3DS/L4.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
namespace Switch_Toolbox.Library
|
||||
{
|
||||
public class L4
|
||||
{
|
||||
public static byte[] Decompress(byte[] Input, int Width, int Height, bool Alpha)
|
||||
{
|
||||
byte[] Output = new byte[Width * Height * 4];
|
||||
|
||||
int bpp = 16;
|
||||
int Increment = 16 / 8;
|
||||
|
||||
int IOffset = 0;
|
||||
|
||||
for (int TY = 0; TY < Height; TY += 8)
|
||||
{
|
||||
for (int TX = 0; TX < Width; TX += 8)
|
||||
{
|
||||
for (int Px = 0; Px < 64; Px++)
|
||||
{
|
||||
int X = Swizzle_3DS.SwizzleLUT[Px] & 7;
|
||||
int Y = (Swizzle_3DS.SwizzleLUT[Px] - X) >> 3;
|
||||
|
||||
int OOffet = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;
|
||||
|
||||
int L = (Input[IOffset >> 1] >> ((IOffset & 1) << 2)) & 0xf;
|
||||
Output[OOffet + 0] = (byte)((L << 4) | L);
|
||||
Output[OOffet + 1] = (byte)((L << 4) | L);
|
||||
Output[OOffet + 2] = (byte)((L << 4) | L);
|
||||
Output[OOffet + 3] = 0xff;
|
||||
|
||||
IOffset += Increment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
}
|
||||
}
|
45
Switch_Toolbox_Library/FileFormats/3DS/L8.cs
Normal file
45
Switch_Toolbox_Library/FileFormats/3DS/L8.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
namespace Switch_Toolbox.Library
|
||||
{
|
||||
public class L8
|
||||
{
|
||||
public static byte[] Decompress(byte[] Input, int Width, int Height, bool Alpha)
|
||||
{
|
||||
byte[] Output = new byte[Width * Height * 4];
|
||||
|
||||
int bpp = 16;
|
||||
int Increment = 16 / 8;
|
||||
|
||||
int IOffset = 0;
|
||||
|
||||
for (int TY = 0; TY < Height; TY += 8)
|
||||
{
|
||||
for (int TX = 0; TX < Width; TX += 8)
|
||||
{
|
||||
for (int Px = 0; Px < 64; Px++)
|
||||
{
|
||||
int X = Swizzle_3DS.SwizzleLUT[Px] & 7;
|
||||
int Y = (Swizzle_3DS.SwizzleLUT[Px] - X) >> 3;
|
||||
|
||||
int OOffet = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;
|
||||
|
||||
Output[OOffet + 0] = Input[IOffset];
|
||||
Output[OOffet + 1] = Input[IOffset];
|
||||
Output[OOffet + 2] = Input[IOffset];
|
||||
Output[OOffet + 3] = 0xff;
|
||||
|
||||
IOffset += Increment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
}
|
||||
}
|
45
Switch_Toolbox_Library/FileFormats/3DS/LA4.cs
Normal file
45
Switch_Toolbox_Library/FileFormats/3DS/LA4.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
namespace Switch_Toolbox.Library
|
||||
{
|
||||
public class L4A
|
||||
{
|
||||
public static byte[] Decompress(byte[] Input, int Width, int Height, bool Alpha)
|
||||
{
|
||||
byte[] Output = new byte[Width * Height * 4];
|
||||
|
||||
int bpp = 16;
|
||||
int Increment = 16 / 8;
|
||||
|
||||
int IOffset = 0;
|
||||
|
||||
for (int TY = 0; TY < Height; TY += 8)
|
||||
{
|
||||
for (int TX = 0; TX < Width; TX += 8)
|
||||
{
|
||||
for (int Px = 0; Px < 64; Px++)
|
||||
{
|
||||
int X = Swizzle_3DS.SwizzleLUT[Px] & 7;
|
||||
int Y = (Swizzle_3DS.SwizzleLUT[Px] - X) >> 3;
|
||||
|
||||
int OOffet = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;
|
||||
|
||||
Output[OOffet + 0] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
|
||||
Output[OOffet + 1] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
|
||||
Output[OOffet + 2] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
|
||||
Output[OOffet + 3] = (byte)((Input[IOffset] << 4) | (Input[IOffset] & 0x0f));
|
||||
|
||||
IOffset += Increment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
}
|
||||
}
|
45
Switch_Toolbox_Library/FileFormats/3DS/LA8.cs
Normal file
45
Switch_Toolbox_Library/FileFormats/3DS/LA8.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
namespace Switch_Toolbox.Library
|
||||
{
|
||||
public class L8A
|
||||
{
|
||||
public static byte[] Decompress(byte[] Input, int Width, int Height, bool Alpha)
|
||||
{
|
||||
byte[] Output = new byte[Width * Height * 4];
|
||||
|
||||
int bpp = 16;
|
||||
int Increment = 16 / 8;
|
||||
|
||||
int IOffset = 0;
|
||||
|
||||
for (int TY = 0; TY < Height; TY += 8)
|
||||
{
|
||||
for (int TX = 0; TX < Width; TX += 8)
|
||||
{
|
||||
for (int Px = 0; Px < 64; Px++)
|
||||
{
|
||||
int X = Swizzle_3DS.SwizzleLUT[Px] & 7;
|
||||
int Y = (Swizzle_3DS.SwizzleLUT[Px] - X) >> 3;
|
||||
|
||||
int OOffet = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;
|
||||
|
||||
Output[OOffet + 0] = Input[IOffset + 1];
|
||||
Output[OOffet + 1] = Input[IOffset + 1];
|
||||
Output[OOffet + 2] = Input[IOffset + 1];
|
||||
Output[OOffet + 3] = Input[IOffset + 0];
|
||||
|
||||
IOffset += Increment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,16 @@ namespace Switch_Toolbox.Library
|
||||
Zero
|
||||
}
|
||||
|
||||
public enum PlatformSwizzle
|
||||
{
|
||||
None = 0,
|
||||
Platform_3DS = 1,
|
||||
Platform_Wii = 2,
|
||||
Platform_Gamecube = 3,
|
||||
Platform_WiiU = 4,
|
||||
Platform_Switch = 5,
|
||||
}
|
||||
|
||||
public class EditedBitmap
|
||||
{
|
||||
public int ArrayLevel = 0;
|
||||
@ -37,6 +47,11 @@ namespace Switch_Toolbox.Library
|
||||
RenderableTex.GLInitialized = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The swizzle method to use when decoding or encoding back a texture.
|
||||
/// </summary>
|
||||
public PlatformSwizzle PlatformSwizzle;
|
||||
|
||||
public bool IsSwizzled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
@ -240,6 +255,14 @@ namespace Switch_Toolbox.Library
|
||||
{ TEX_FORMAT.ASTC_10x5_SRGB, new FormatInfo(16, 10, 5, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.ASTC_10x6_UNORM, new FormatInfo(16, 10, 6, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.ASTC_10x6_SRGB, new FormatInfo(16, 10, 6, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.ETC1, new FormatInfo(1, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.ETC1_A4, new FormatInfo(1, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.HIL08, new FormatInfo(8, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.L4, new FormatInfo(1, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.LA4, new FormatInfo(1, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.L8, new FormatInfo(2, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.LA8, new FormatInfo(1, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.A4, new FormatInfo(1, 1, 1, 1, TargetBuffer.Color) },
|
||||
|
||||
{ TEX_FORMAT.D16_UNORM, new FormatInfo(2, 1, 1, 1, TargetBuffer.Depth) },
|
||||
{ TEX_FORMAT.D24_UNORM_S8_UINT, new FormatInfo(4, 1, 1, 1, TargetBuffer.Depth) },
|
||||
@ -314,6 +337,11 @@ namespace Switch_Toolbox.Library
|
||||
if (data == null)
|
||||
throw new Exception("Data is null!");
|
||||
|
||||
if (PlatformSwizzle == PlatformSwizzle.Platform_3DS && !IsCompressed(Format)) {
|
||||
return BitmapExtension.GetBitmap(Swizzle_3DS.DecodeBlock(data, (int)width, (int)height, Format),
|
||||
(int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
}
|
||||
|
||||
switch (Format)
|
||||
{
|
||||
case TEX_FORMAT.BC5_SNORM:
|
||||
|
@ -129,7 +129,6 @@ namespace Switch_Toolbox.Library
|
||||
V208 = 131,
|
||||
V408 = 132,
|
||||
R32G8X24_FLOAT = 133,
|
||||
|
||||
ASTC_4x4_UNORM = 134,
|
||||
ASTC_4x4_SRGB = 135,
|
||||
ASTC_5x4_UNORM = 138,
|
||||
@ -162,5 +161,11 @@ namespace Switch_Toolbox.Library
|
||||
|
||||
ETC1 = 230,
|
||||
ETC1_A4 = 231,
|
||||
L4 = 232,
|
||||
LA4 = 233,
|
||||
L8 = 234,
|
||||
LA8 = 235,
|
||||
HIL08 = 236,
|
||||
A4 = 237,
|
||||
}
|
||||
}
|
||||
|
@ -189,10 +189,9 @@ namespace Switch_Toolbox.Library.IO
|
||||
{
|
||||
using (MemoryStream mem = new MemoryStream())
|
||||
{
|
||||
using (GZipStream gzip = new GZipStream(new MemoryStream(b), CompressionMode.Decompress))
|
||||
using (GZipStream source = new GZipStream(new MemoryStream(b), CompressionMode.Decompress))
|
||||
{
|
||||
gzip.CopyTo(mem);
|
||||
mem.Write(b, 0, b.Length);
|
||||
source.CopyTo(mem);
|
||||
}
|
||||
return mem.ToArray();
|
||||
}
|
||||
|
@ -137,7 +137,6 @@ namespace Switch_Toolbox.Library.IO
|
||||
CompressionType.Lz4f, DecompressedFileSize, CompressedFileSize);
|
||||
}
|
||||
|
||||
fileReader.Dispose();
|
||||
fileReader.Close();
|
||||
|
||||
Stream stream;
|
||||
|
@ -200,6 +200,11 @@
|
||||
<Compile Include="Audio\AudioFileRipper.cs" />
|
||||
<Compile Include="Audio\VGAudioFile.cs" />
|
||||
<Compile Include="Config.cs" />
|
||||
<Compile Include="FileFormats\3DS\HiLo8.cs" />
|
||||
<Compile Include="FileFormats\3DS\A8.cs" />
|
||||
<Compile Include="FileFormats\3DS\L4.cs" />
|
||||
<Compile Include="FileFormats\3DS\LA4.cs" />
|
||||
<Compile Include="FileFormats\3DS\LA8.cs" />
|
||||
<Compile Include="FileFormats\Animation\SMD.cs" />
|
||||
<Compile Include="FileFormats\APNG\APNG.cs" />
|
||||
<Compile Include="FileFormats\APNG\CRC.cs" />
|
||||
@ -208,7 +213,8 @@
|
||||
<Compile Include="FileFormats\DAE\ColladaHelper.cs" />
|
||||
<Compile Include="FileFormats\DAE\collada_schema_1_4.cs" />
|
||||
<Compile Include="FileFormats\DAE\DAE.cs" />
|
||||
<Compile Include="FileFormats\ETC1.cs" />
|
||||
<Compile Include="FileFormats\3DS\ETC1.cs" />
|
||||
<Compile Include="FileFormats\3DS\L8.cs" />
|
||||
<Compile Include="FileFormats\OBJ.cs" />
|
||||
<Compile Include="Forms\BatchFormatExport.cs">
|
||||
<SubType>Form</SubType>
|
||||
@ -606,6 +612,7 @@
|
||||
<Compile Include="STToolStipMenuItem.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Swizzling\Swizzle_3DS.cs" />
|
||||
<Compile Include="Swizzling\GX2.cs" />
|
||||
<Compile Include="Swizzling\NewSwizzleCodeBackup.cs" />
|
||||
<Compile Include="Swizzling\TegraX1Swizzle.cs" />
|
||||
|
183
Switch_Toolbox_Library/Swizzling/Swizzle_3DS.cs
Normal file
183
Switch_Toolbox_Library/Swizzling/Swizzle_3DS.cs
Normal file
@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Switch_Toolbox.Library
|
||||
{
|
||||
public class Swizzle_3DS
|
||||
{
|
||||
//From https://github.com/gdkchan/SPICA/blob/42c4181e198b0fd34f0a567345ee7e75b54cb58b/SPICA/PICA/Converters/TextureConverter.cs
|
||||
|
||||
public static int[] SwizzleLUT =
|
||||
{
|
||||
0, 1, 8, 9, 2, 3, 10, 11,
|
||||
16, 17, 24, 25, 18, 19, 26, 27,
|
||||
4, 5, 12, 13, 6, 7, 14, 15,
|
||||
20, 21, 28, 29, 22, 23, 30, 31,
|
||||
32, 33, 40, 41, 34, 35, 42, 43,
|
||||
48, 49, 56, 57, 50, 51, 58, 59,
|
||||
36, 37, 44, 45, 38, 39, 46, 47,
|
||||
52, 53, 60, 61, 54, 55, 62, 63
|
||||
};
|
||||
|
||||
public static byte[] DecodeBlock(byte[] Input, int Width, int Height, TEX_FORMAT Format)
|
||||
{
|
||||
if (Format == TEX_FORMAT.ETC1 || Format == TEX_FORMAT.ETC1_A4)
|
||||
return ETC1.ETC1Decompress(Input, Width, Height, Format == TEX_FORMAT.ETC1_A4);
|
||||
|
||||
byte[] Output = new byte[Width * Height * 4];
|
||||
|
||||
int Increment = (int)STGenericTexture.GetBytesPerPixel(Format);
|
||||
|
||||
int IOffset = 0;
|
||||
|
||||
for (int TY = 0; TY < Height; TY += 8)
|
||||
{
|
||||
for (int TX = 0; TX < Width; TX += 8)
|
||||
{
|
||||
for (int Px = 0; Px < 64; Px++)
|
||||
{
|
||||
int X = Swizzle_3DS.SwizzleLUT[Px] & 7;
|
||||
int Y = (Swizzle_3DS.SwizzleLUT[Px] - X) >> 3;
|
||||
|
||||
int OOffet = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;
|
||||
|
||||
switch (Format)
|
||||
{
|
||||
case TEX_FORMAT.R8G8_UNORM:
|
||||
Output[OOffet + 0] = Input[IOffset + 3];
|
||||
Output[OOffet + 1] = Input[IOffset + 2];
|
||||
Output[OOffet + 2] = Input[IOffset + 1];
|
||||
Output[OOffet + 3] = Input[IOffset + 0];
|
||||
break;
|
||||
case TEX_FORMAT.R8G8B8A8_UNORM:
|
||||
Output[OOffet + 0] = Input[IOffset + 2];
|
||||
Output[OOffet + 1] = Input[IOffset + 1];
|
||||
Output[OOffet + 2] = Input[IOffset + 0];
|
||||
Output[OOffet + 3] = 0xff;
|
||||
break;
|
||||
case TEX_FORMAT.B5G5R5A1_UNORM:
|
||||
DecodeRGBA5551(Output, OOffet, GetUShort(Input, IOffset));
|
||||
break;
|
||||
case TEX_FORMAT.B5G6R5_UNORM:
|
||||
DecodeRGB565(Output, OOffet, GetUShort(Input, IOffset));
|
||||
break;
|
||||
case TEX_FORMAT.B4G4R4A4_UNORM:
|
||||
DecodeRGBA4(Output, OOffet, GetUShort(Input, IOffset));
|
||||
break;
|
||||
case TEX_FORMAT.LA8:
|
||||
Output[OOffet + 0] = Input[IOffset + 1];
|
||||
Output[OOffet + 1] = Input[IOffset + 1];
|
||||
Output[OOffet + 2] = Input[IOffset + 1];
|
||||
Output[OOffet + 3] = Input[IOffset + 0];
|
||||
break;
|
||||
case TEX_FORMAT.HIL08:
|
||||
Output[OOffet + 0] = Input[IOffset + 1];
|
||||
Output[OOffet + 1] = Input[IOffset + 0];
|
||||
Output[OOffet + 2] = 0;
|
||||
Output[OOffet + 3] = 0xff;
|
||||
break;
|
||||
case TEX_FORMAT.L8:
|
||||
Output[OOffet + 0] = Input[IOffset];
|
||||
Output[OOffet + 1] = Input[IOffset];
|
||||
Output[OOffet + 2] = Input[IOffset];
|
||||
Output[OOffet + 3] = 0xff;
|
||||
break;
|
||||
|
||||
case TEX_FORMAT.A8_UNORM:
|
||||
Output[OOffet + 0] = 0xff;
|
||||
Output[OOffet + 1] = 0xff;
|
||||
Output[OOffet + 2] = 0xff;
|
||||
Output[OOffet + 3] = Input[IOffset];
|
||||
break;
|
||||
case TEX_FORMAT.LA4:
|
||||
Output[OOffet + 0] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
|
||||
Output[OOffet + 1] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
|
||||
Output[OOffet + 2] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
|
||||
Output[OOffet + 3] = (byte)((Input[IOffset] << 4) | (Input[IOffset] & 0x0f));
|
||||
break;
|
||||
case TEX_FORMAT.L4:
|
||||
int L = (Input[IOffset >> 1] >> ((IOffset & 1) << 2)) & 0xf;
|
||||
Output[OOffet + 0] = (byte)((L << 4) | L);
|
||||
Output[OOffet + 1] = (byte)((L << 4) | L);
|
||||
Output[OOffet + 2] = (byte)((L << 4) | L);
|
||||
Output[OOffet + 3] = 0xff;
|
||||
break;
|
||||
case TEX_FORMAT.A4:
|
||||
int A = (Input[IOffset >> 1] >> ((IOffset & 1) << 2)) & 0xf;
|
||||
|
||||
Output[OOffet + 0] = 0xff;
|
||||
Output[OOffet + 1] = 0xff;
|
||||
Output[OOffet + 2] = 0xff;
|
||||
Output[OOffet + 3] = (byte)((A << 4) | A);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Output[OOffet + 0] = 0xff;
|
||||
Output[OOffet + 1] = 0xff;
|
||||
Output[OOffet + 2] = 0xff;
|
||||
Output[OOffet + 3] = Input[IOffset];
|
||||
|
||||
IOffset += Increment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
private static void DecodeRGB565(byte[] Buffer, int Address, ushort Value)
|
||||
{
|
||||
int R = ((Value >> 0) & 0x1f) << 3;
|
||||
int G = ((Value >> 5) & 0x3f) << 2;
|
||||
int B = ((Value >> 11) & 0x1f) << 3;
|
||||
|
||||
SetColor(Buffer, Address, 0xff,
|
||||
B | (B >> 5),
|
||||
G | (G >> 6),
|
||||
R | (R >> 5));
|
||||
}
|
||||
|
||||
private static void DecodeRGBA4(byte[] Buffer, int Address, ushort Value)
|
||||
{
|
||||
int R = (Value >> 4) & 0xf;
|
||||
int G = (Value >> 8) & 0xf;
|
||||
int B = (Value >> 12) & 0xf;
|
||||
|
||||
SetColor(Buffer, Address, (Value & 0xf) | (Value << 4),
|
||||
B | (B << 4),
|
||||
G | (G << 4),
|
||||
R | (R << 4));
|
||||
}
|
||||
|
||||
private static void DecodeRGBA5551(byte[] Buffer, int Address, ushort Value)
|
||||
{
|
||||
int R = ((Value >> 1) & 0x1f) << 3;
|
||||
int G = ((Value >> 6) & 0x1f) << 3;
|
||||
int B = ((Value >> 11) & 0x1f) << 3;
|
||||
|
||||
SetColor(Buffer, Address, (Value & 1) * 0xff,
|
||||
B | (B >> 5),
|
||||
G | (G >> 5),
|
||||
R | (R >> 5));
|
||||
}
|
||||
|
||||
private static void SetColor(byte[] Buffer, int Address, int A, int B, int G, int R)
|
||||
{
|
||||
Buffer[Address + 0] = (byte)B;
|
||||
Buffer[Address + 1] = (byte)G;
|
||||
Buffer[Address + 2] = (byte)R;
|
||||
Buffer[Address + 3] = (byte)A;
|
||||
}
|
||||
|
||||
private static ushort GetUShort(byte[] Buffer, int Address)
|
||||
{
|
||||
return (ushort)(
|
||||
Buffer[Address + 0] << 0 |
|
||||
Buffer[Address + 1] << 8);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user