1
0
mirror of synced 2024-11-30 18:24:39 +01:00

More fixes to 3ds formats. Fix gzip decompressing giving wrong size.

This commit is contained in:
KillzXGaming 2019-05-04 12:03:07 -04:00
parent a905fcab5e
commit 017c1ab1e3
21 changed files with 545 additions and 24 deletions

Binary file not shown.

View File

@ -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);

View File

@ -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);

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View File

@ -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:

View File

@ -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,
}
}

View File

@ -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();
}

View File

@ -137,7 +137,6 @@ namespace Switch_Toolbox.Library.IO
CompressionType.Lz4f, DecompressedFileSize, CompressedFileSize);
}
fileReader.Dispose();
fileReader.Close();
Stream stream;

View File

@ -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" />

View 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);
}
}
}