diff --git a/3DS/GPU/Textures.cs b/3DS/GPU/Textures.cs
index 4259eac..1ab6166 100644
--- a/3DS/GPU/Textures.cs
+++ b/3DS/GPU/Textures.cs
@@ -72,7 +72,7 @@ namespace _3DS.GPU
Height = 1 << (int)Math.Ceiling(Math.Log(Height, 2));
}
Bitmap bitm = new Bitmap(physicalwidth, physicalheight);
- BitmapData d = bitm.LockBits(new Rectangle(0, 0, bitm.Width, bitm.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+ BitmapData d = bitm.LockBits(new Rectangle(0, 0, bitm.Width, bitm.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
uint* res = (uint*)d.Scan0;
int offs = Offset;//0;
int stride = d.Stride / 4;
@@ -90,12 +90,17 @@ namespace _3DS.GPU
int y2 = i / 8;
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
- Data[offs + pos * 4],
- Data[offs + pos * 4 + 3],
- Data[offs + pos * 4 + 2],
- Data[offs + pos * 4 + 1]
- );
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(
+ IOUtil.ReadU32LE(Data, offs + pos * 4),
+ ColorFormat.RGBA8888,
+ ColorFormat.ARGB8888);
+ /*GFXUtil.ToArgb(
+ Data[offs + pos * 4],
+ Data[offs + pos * 4 + 3],
+ Data[offs + pos * 4 + 2],
+ Data[offs + pos * 4 + 1]
+ );*/
}
offs += 64 * 4;
}
@@ -113,11 +118,16 @@ namespace _3DS.GPU
int y2 = i / 8;
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
- Data[offs + pos * 3 + 2],
- Data[offs + pos * 3 + 1],
- Data[offs + pos * 3 + 0]
- );
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(
+ IOUtil.ReadU24LE(Data, offs + pos * 3),
+ ColorFormat.RGB888,
+ ColorFormat.ARGB8888);
+ /*GFXUtil.ToArgb(
+ Data[offs + pos * 3 + 2],
+ Data[offs + pos * 3 + 1],
+ Data[offs + pos * 3 + 0]
+ );*/
}
offs += 64 * 3;
}
@@ -136,7 +146,11 @@ namespace _3DS.GPU
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
res[(y + y2) * stride + x + x2] =
- GFXUtil.ARGB1555ToArgb(IOUtil.ReadU16LE(Data, offs + pos * 2));
+ GFXUtil.ConvertColorFormat(
+ IOUtil.ReadU16LE(Data, offs + pos * 2),
+ ColorFormat.ARGB1555,
+ ColorFormat.ARGB8888);
+ //GFXUtil.ARGB1555ToArgb(IOUtil.ReadU16LE(Data, offs + pos * 2));
}
offs += 64 * 2;
}
@@ -155,7 +169,11 @@ namespace _3DS.GPU
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
res[(y + y2) * stride + x + x2] =
- GFXUtil.RGB565ToArgb(IOUtil.ReadU16LE(Data, offs + pos * 2));
+ GFXUtil.ConvertColorFormat(
+ IOUtil.ReadU16LE(Data, offs + pos * 2),
+ ColorFormat.RGB565,
+ ColorFormat.ARGB8888);
+ //GFXUtil.RGB565ToArgb(IOUtil.ReadU16LE(Data, offs + pos * 2));
}
offs += 64 * 2;
}
@@ -173,12 +191,17 @@ namespace _3DS.GPU
int y2 = i / 8;
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
- (byte)((Data[offs + pos * 2] & 0xF) * 0x11),
- (byte)((Data[offs + pos * 2 + 1] >> 4) * 0x11),
- (byte)((Data[offs + pos * 2 + 1] & 0xF) * 0x11),
- (byte)((Data[offs + pos * 2] >> 4) * 0x11)
- );
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(
+ IOUtil.ReadU16LE(Data, offs + pos * 2),
+ ColorFormat.RGBA4444,
+ ColorFormat.ARGB8888);
+ /*GFXUtil.ToArgb(
+ (byte)((Data[offs + pos * 2] & 0xF) * 0x11),
+ (byte)((Data[offs + pos * 2 + 1] >> 4) * 0x11),
+ (byte)((Data[offs + pos * 2 + 1] & 0xF) * 0x11),
+ (byte)((Data[offs + pos * 2] >> 4) * 0x11)
+ );*/
}
offs += 64 * 2;
}
@@ -196,11 +219,12 @@ namespace _3DS.GPU
int y2 = i / 8;
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
Data[offs + pos * 2],
Data[offs + pos * 2 + 1],
Data[offs + pos * 2 + 1],
- Data[offs + pos * 2 + 1]
+ Data[offs + pos * 2 + 1],
+ ColorFormat.ARGB8888
);
}
offs += 64 * 2;
@@ -219,11 +243,12 @@ namespace _3DS.GPU
int y2 = i / 8;
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
Data[offs + pos * 2],
Data[offs + pos * 2 + 1],
Data[offs + pos * 2 + 1],
- Data[offs + pos * 2 + 1]
+ Data[offs + pos * 2 + 1],
+ ColorFormat.ARGB8888
);
}
offs += 64 * 2;
@@ -242,10 +267,11 @@ namespace _3DS.GPU
int y2 = i / 8;
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
Data[offs + pos],
Data[offs + pos],
- Data[offs + pos]
+ Data[offs + pos],
+ ColorFormat.ARGB8888
);
}
offs += 64;
@@ -264,11 +290,12 @@ namespace _3DS.GPU
int y2 = i / 8;
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
Data[offs + pos],
255,
255,
- 255
+ 255,
+ ColorFormat.ARGB8888
);
}
offs += 64;
@@ -287,11 +314,12 @@ namespace _3DS.GPU
int y2 = i / 8;
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
(byte)((Data[offs + pos] & 0xF) * 0x11),
(byte)((Data[offs + pos] >> 4) * 0x11),
(byte)((Data[offs + pos] >> 4) * 0x11),
- (byte)((Data[offs + pos] >> 4) * 0x11)
+ (byte)((Data[offs + pos] >> 4) * 0x11),
+ ColorFormat.ARGB8888
);
}
offs += 64;
@@ -311,10 +339,11 @@ namespace _3DS.GPU
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
int shift = (pos & 1) * 4;
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
(byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11),
(byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11),
- (byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11)
+ (byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11),
+ ColorFormat.ARGB8888
);
}
offs += 64 / 2;
@@ -334,11 +363,12 @@ namespace _3DS.GPU
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
int shift = (pos & 1) * 4;
- res[(y + y2) * stride + x + x2] = GFXUtil.ToArgb(
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
(byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11),
255,
255,
- 255
+ 255,
+ ColorFormat.ARGB8888
);
}
offs += 64 / 2;
@@ -405,12 +435,12 @@ namespace _3DS.GPU
if ((flipbit && y3 < 2) || (!flipbit && x3 < 2))
{
int add = ETC1Modifiers[Table1, val] * (neg ? -1 : 1);
- c = GFXUtil.ToArgb((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r1 + add), (byte)ColorClamp(g1 + add), (byte)ColorClamp(b1 + add));
+ c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r1 + add), (byte)ColorClamp(g1 + add), (byte)ColorClamp(b1 + add), ColorFormat.ARGB8888);
}
else
{
int add = ETC1Modifiers[Table2, val] * (neg ? -1 : 1);
- c = GFXUtil.ToArgb((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r2 + add), (byte)ColorClamp(g2 + add), (byte)ColorClamp(b2 + add));
+ c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r2 + add), (byte)ColorClamp(g2 + add), (byte)ColorClamp(b2 + add), ColorFormat.ARGB8888);
}
res[(i + y3) * stride + x + j + x3] = c;
}
@@ -479,7 +509,7 @@ namespace _3DS.GPU
int y2 = i / 8;
if (y + y2 >= physicalheight) continue;
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
- IOUtil.WriteU16LE(result, offs + pos * 2, GFXUtil.ArgbToRGB565(res[(y + y2) * d.Stride / 4 + x + x2]));
+ IOUtil.WriteU16LE(result, offs + pos * 2, (ushort)GFXUtil.ConvertColorFormat(res[(y + y2) * d.Stride / 4 + x + x2], ColorFormat.ARGB8888, ColorFormat.RGB565)); //GFXUtil.ArgbToRGB565(res[(y + y2) * d.Stride / 4 + x + x2]));
}
offs += 64 * 2;
}
diff --git a/GCNWii/GCNWii.csproj b/GCNWii/GCNWii.csproj
index 1a7c5c9..4b7414d 100644
--- a/GCNWii/GCNWii.csproj
+++ b/GCNWii/GCNWii.csproj
@@ -21,6 +21,7 @@
DEBUG;TRACE
prompt
4
+ true
pdbonly
@@ -43,8 +44,16 @@
+
+
+
+ Form
+
+
+ BTIViewer.cs
+
Form
@@ -59,10 +68,14 @@
+
+ BTIViewer.cs
+
RARCViewer.cs
+
copy "$(TargetPath)" "$(SolutionDir)\EveryFileExplorer\bin\Debug\Plugins\$(TargetFileName)"
diff --git a/GCNWii/GPU/Textures.cs b/GCNWii/GPU/Textures.cs
new file mode 100644
index 0000000..16dab16
--- /dev/null
+++ b/GCNWii/GPU/Textures.cs
@@ -0,0 +1,298 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Drawing;
+using System.Drawing.Imaging;
+using LibEveryFileExplorer.IO;
+using LibEveryFileExplorer.GFX;
+
+namespace GCNWii.GPU
+{
+ public class Textures
+ {
+ public enum ImageFormat : uint
+ {
+ I4 = 0,
+ I8 = 1,
+ IA4 = 2,
+ IA8 = 3,
+ RGB565 = 4,
+ RGB5A3 = 5,
+ RGBA8 = 6,
+ //
+ CI4 = 8,
+ CI8 = 9,
+ CI14X2 = 10,
+ //
+ CMP = 14
+ }
+
+ public enum PaletteFormat : uint
+ {
+ IA8 = 0,
+ RGB565 = 1,
+ RGB5A3 = 2
+ }
+
+ private static readonly int[] Bpp = { 4, 8, 8, 16, 16, 16, 32, 0, 4, 8, 16, 0, 0, 0, 4 };
+
+ public static int GetBpp(ImageFormat Format) { return Bpp[(uint)Format]; }
+
+ public static unsafe Bitmap ToBitmap(byte[] TexData, int TexOffset, byte[] PalData, int PalOffset, int Width, int Height, ImageFormat Format, PaletteFormat PalFormat, bool ExactSize = false)
+ {
+ Bitmap bitm = new Bitmap(Width, Height);
+ BitmapData d = bitm.LockBits(new Rectangle(0, 0, bitm.Width, bitm.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
+ uint* res = (uint*)d.Scan0;
+ int offs = TexOffset;
+ int stride = d.Stride / 4;
+ switch (Format)
+ {
+ case ImageFormat.I4:
+ {
+ for (int y = 0; y < Height; y += 8)
+ {
+ for (int x = 0; x < Width; x += 8)
+ {
+ for (int y2 = 0; y2 < 8; y2++)
+ {
+ for (int x2 = 0; x2 < 8; x2 += 2)
+ {
+ byte I1 = (byte)((TexData[offs] >> 4) * 0x11);
+ byte I2 = (byte)((TexData[offs] & 0xF) * 0x11);
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(I1, I1, I1, ColorFormat.ARGB8888);
+ res[(y + y2) * stride + x + x2 + 1] = GFXUtil.ToColorFormat(I2, I2, I2, ColorFormat.ARGB8888);
+ offs++;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ImageFormat.I8:
+ {
+ for (int y = 0; y < Height; y += 4)
+ {
+ for (int x = 0; x < Width; x += 8)
+ {
+ for (int y2 = 0; y2 < 4; y2++)
+ {
+ for (int x2 = 0; x2 < 8; x2++)
+ {
+ byte I = TexData[offs];
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(I, I, I, ColorFormat.ARGB8888);
+ offs++;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ImageFormat.IA4:
+ {
+ for (int y = 0; y < Height; y += 4)
+ {
+ for (int x = 0; x < Width; x += 8)
+ {
+ for (int y2 = 0; y2 < 4; y2++)
+ {
+ for (int x2 = 0; x2 < 8; x2++)
+ {
+ byte I = (byte)((TexData[offs] & 0xF) * 0x11);
+ byte A = (byte)((TexData[offs] >> 4) * 0x11);
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(A, I, I, I, ColorFormat.ARGB8888);
+ offs++;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ImageFormat.IA8:
+ {
+ for (int y = 0; y < Height; y += 4)
+ {
+ for (int x = 0; x < Width; x += 4)
+ {
+ for (int y2 = 0; y2 < 4; y2++)
+ {
+ for (int x2 = 0; x2 < 4; x2++)
+ {
+ byte I = TexData[offs + 1];
+ byte A = TexData[offs];
+ res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(A, I, I, I, ColorFormat.ARGB8888);
+ offs += 2;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ImageFormat.RGB565:
+ {
+ for (int y = 0; y < Height; y += 4)
+ {
+ for (int x = 0; x < Width; x += 4)
+ {
+ for (int y2 = 0; y2 < 4; y2++)
+ {
+ for (int x2 = 0; x2 < 4; x2++)
+ {
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(
+ IOUtil.ReadU16BE(TexData, offs),
+ ColorFormat.RGB565,
+ ColorFormat.ARGB8888);
+ //GFXUtil.RGB565ToArgb(IOUtil.ReadU16BE(TexData, offs));
+ offs += 2;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ImageFormat.RGB5A3:
+ {
+ for (int y = 0; y < Height; y += 4)
+ {
+ for (int x = 0; x < Width; x += 4)
+ {
+ for (int y2 = 0; y2 < 4; y2++)
+ {
+ for (int x2 = 0; x2 < 4; x2++)
+ {
+ ushort data = IOUtil.ReadU16BE(TexData, offs);
+ if ((data & 0x8000) != 0)
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(data, ColorFormat.XRGB1555, ColorFormat.ARGB8888);
+ else
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(data, ColorFormat.ARGB3444, ColorFormat.ARGB8888);
+ offs += 2;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ImageFormat.CI4:
+ {
+ for (int y = 0; y < Height; y += 8)
+ {
+ for (int x = 0; x < Width; x += 8)
+ {
+ for (int y2 = 0; y2 < 8; y2++)
+ {
+ for (int x2 = 0; x2 < 8; x2 += 2)
+ {
+ byte index1 = (byte)(TexData[offs] >> 4);
+ byte index2 = (byte)(TexData[offs] & 0xF);
+ switch (PalFormat)
+ {
+ case PaletteFormat.RGB5A3:
+ {
+ ushort data = IOUtil.ReadU16BE(PalData, PalOffset + index1 * 2);
+ if ((data & 0x8000) != 0)
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(data, ColorFormat.XRGB1555, ColorFormat.ARGB8888);
+ else
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(data, ColorFormat.ARGB3444, ColorFormat.ARGB8888);
+ data = IOUtil.ReadU16BE(PalData, PalOffset + index2 * 2);
+ if ((data & 0x8000) != 0)
+ res[(y + y2) * stride + x + x2 + 1] =
+ GFXUtil.ConvertColorFormat(data, ColorFormat.XRGB1555, ColorFormat.ARGB8888);
+ else
+ res[(y + y2) * stride + x + x2 + 1] =
+ GFXUtil.ConvertColorFormat(data, ColorFormat.ARGB3444, ColorFormat.ARGB8888);
+ break;
+ }
+ }
+ offs++;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ImageFormat.CI8:
+ {
+ for (int y = 0; y < Height; y += 4)
+ {
+ for (int x = 0; x < Width; x += 8)
+ {
+ for (int y2 = 0; y2 < 4; y2++)
+ {
+ for (int x2 = 0; x2 < 8; x2++)
+ {
+ byte index = TexData[offs];
+ switch (PalFormat)
+ {
+ case PaletteFormat.RGB5A3:
+ {
+ ushort data = IOUtil.ReadU16BE(PalData, PalOffset + index * 2);
+ if ((data & 0x8000) != 0)
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(data, ColorFormat.XRGB1555, ColorFormat.ARGB8888);
+ else
+ res[(y + y2) * stride + x + x2] =
+ GFXUtil.ConvertColorFormat(data, ColorFormat.ARGB3444, ColorFormat.ARGB8888);
+ break;
+ }
+ }
+ offs++;
+ }
+ }
+ }
+ }
+ break;
+ }
+ case ImageFormat.CMP:
+ for (int y = 0; y < Height; y += 8)
+ {
+ for (int x = 0; x < Width; x += 8)
+ {
+ for (int y2 = 0; y2 < 8; y2 += 4)
+ {
+ for (int x2 = 0; x2 < 8; x2 += 4)
+ {
+ ushort color0 = IOUtil.ReadU16BE(TexData, offs);
+ ushort color1 = IOUtil.ReadU16BE(TexData, offs + 2);
+ uint data = IOUtil.ReadU32BE(TexData, offs + 4);
+ uint[] Palette = new uint[4];
+ Palette[0] = GFXUtil.ConvertColorFormat(color0, ColorFormat.RGB565, ColorFormat.ARGB8888);
+ Palette[1] = GFXUtil.ConvertColorFormat(color1, ColorFormat.RGB565, ColorFormat.ARGB8888);
+ Color a = Color.FromArgb((int)Palette[0]);
+ Color b = Color.FromArgb((int)Palette[1]);
+ if (color0 > color1)//1/3 and 2/3
+ {
+ Palette[2] = GFXUtil.ToColorFormat((a.R * 2 + b.R * 1) / 3, (a.G * 2 + b.G * 1) / 3, (a.B * 2 + b.B * 1) / 3, ColorFormat.ARGB8888);
+ Palette[3] = GFXUtil.ToColorFormat((a.R * 1 + b.R * 2) / 3, (a.G * 1 + b.G * 2) / 3, (a.B * 1 + b.B * 2) / 3, ColorFormat.ARGB8888);
+ }
+ else//1/2 and transparent
+ {
+ Palette[2] = GFXUtil.ToColorFormat((a.R + b.R) / 2, (a.G + b.G) / 2, (a.B + b.B) / 2, ColorFormat.ARGB8888);
+ Palette[3] = 0;
+ }
+
+ int q = 30;
+ for (int y3 = 0; y3 < 4; y3++)
+ {
+ for (int x3 = 0; x3 < 4; x3++)
+ {
+ res[(y + y2 + y3) * stride + x + x2 + x3] = Palette[(data >> q) & 3];
+ q -= 2;
+ }
+ }
+ offs += 8;
+ }
+ }
+ }
+ }
+ break;
+ }
+ bitm.UnlockBits(d);
+ return bitm;
+ }
+ }
+}
diff --git a/GCNWii/JSystem/BTI.cs b/GCNWii/JSystem/BTI.cs
new file mode 100644
index 0000000..2e082ba
--- /dev/null
+++ b/GCNWii/JSystem/BTI.cs
@@ -0,0 +1,148 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using LibEveryFileExplorer.Files;
+using System.Drawing;
+using GCNWii.GPU;
+using System.IO;
+using System.Windows.Forms;
+using GCNWii.UI;
+
+namespace GCNWii.JSystem
+{
+ public class BTI : FileFormat, IConvertable, IViewable
+ {
+ public BTI(byte[] Data)
+ {
+ EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(Data), Endianness.BigEndian);
+ try
+ {
+ Header = new BTIHeader(er);
+ er.BaseStream.Position = Header.TextureOffset;
+ int len = (int)(er.BaseStream.Length - Header.TextureOffset);
+ if (Header.PaletteOffset != 0) len = (int)(Header.PaletteOffset - Header.TextureOffset);
+ Texture = er.ReadBytes(len);
+ if (Header.PaletteOffset != 0)
+ {
+ er.BaseStream.Position = Header.PaletteOffset;
+ Palette = er.ReadBytes(Header.NrPaletteEntries * 2);
+ }
+ }
+ finally
+ {
+ er.Close();
+ }
+ }
+
+ public string GetConversionFileFilters()
+ {
+ return "Portable Network Graphics (*.png)|*.png";
+ }
+
+ public bool Convert(int FilterIndex, string Path)
+ {
+ switch (FilterIndex)
+ {
+ case 0:
+ File.Create(Path).Close();
+ ToBitmap().Save(Path, System.Drawing.Imaging.ImageFormat.Png);
+ return true;
+ }
+ return false;
+ }
+
+ public Form GetDialog()
+ {
+ return new BTIViewer(this);
+ }
+
+ public BTIHeader Header;
+ public class BTIHeader
+ {
+ public BTIHeader(EndianBinaryReader er)
+ {
+ TextureFormat = (Textures.ImageFormat)er.ReadByte();
+ Unknown1 = er.ReadByte();
+ Width = er.ReadUInt16();
+ Height = er.ReadUInt16();
+ Unknown2 = er.ReadUInt16();
+ Unknown3 = er.ReadByte();
+ PaletteFormat = (Textures.PaletteFormat)er.ReadByte();
+ NrPaletteEntries = er.ReadUInt16();
+ PaletteOffset = er.ReadUInt32();
+ Unknown4 = er.ReadUInt32();
+ Unknown5 = er.ReadUInt16();
+ Unknown6 = er.ReadUInt16();
+ MipMapCount = er.ReadByte();
+ Unknown7 = er.ReadByte();
+ Unknown8 = er.ReadUInt16();
+ TextureOffset = er.ReadUInt32();
+ }
+ public Textures.ImageFormat TextureFormat; //1
+ public Byte Unknown1;
+ public UInt16 Width;
+ public UInt16 Height;
+ public UInt16 Unknown2;
+ public Byte Unknown3;
+ public Textures.PaletteFormat PaletteFormat; //1
+ public UInt16 NrPaletteEntries;
+ public UInt32 PaletteOffset;
+ public UInt32 Unknown4;
+ public UInt16 Unknown5;
+ public UInt16 Unknown6;
+ public Byte MipMapCount;
+ public Byte Unknown7;
+ public UInt16 Unknown8;
+ public UInt32 TextureOffset;
+ }
+ public byte[] Texture;
+ public byte[] Palette;
+
+ public Bitmap ToBitmap(int Level = 0)
+ {
+ int l = Level;
+ uint w = Header.Width;
+ uint h = Header.Height;
+ int bpp = GPU.Textures.GetBpp(Header.TextureFormat);
+ int offset = 0;
+ while (l > 0)
+ {
+ offset += (int)(w * h * bpp / 8);
+ w /= 2;
+ h /= 2;
+ l--;
+ }
+ return GPU.Textures.ToBitmap(Texture, offset, Palette, 0, (int)w, (int)h, Header.TextureFormat, Header.PaletteFormat);
+ }
+
+ public class BTIIdentifier : FileFormatIdentifier
+ {
+ public override string GetCategory()
+ {
+ return Category_Graphics;
+ }
+
+ public override string GetFileDescription()
+ {
+ return "Binary Texture Image (BTI)";
+ }
+
+ public override string GetFileFilter()
+ {
+ return "Binary Texture Image (*.bti)|*.bti";
+ }
+
+ public override Bitmap GetIcon()
+ {
+ return null;
+ }
+
+ public override FormatMatch IsFormat(EFEFile File)
+ {
+ if (File.Name.ToLower().EndsWith(".bti")) return FormatMatch.Extension;
+ return FormatMatch.No;
+ }
+ }
+ }
+}
diff --git a/GCNWii/UI/BTIViewer.Designer.cs b/GCNWii/UI/BTIViewer.Designer.cs
new file mode 100644
index 0000000..3befdc5
--- /dev/null
+++ b/GCNWii/UI/BTIViewer.Designer.cs
@@ -0,0 +1,66 @@
+namespace GCNWii.UI
+{
+ partial class BTIViewer
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BTIViewer));
+ this.pictureBox1 = new System.Windows.Forms.PictureBox();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // pictureBox1
+ //
+ this.pictureBox1.BackColor = System.Drawing.Color.White;
+ this.pictureBox1.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBox1.BackgroundImage")));
+ this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.pictureBox1.Location = new System.Drawing.Point(0, 0);
+ this.pictureBox1.Name = "pictureBox1";
+ this.pictureBox1.Size = new System.Drawing.Size(565, 386);
+ this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
+ this.pictureBox1.TabIndex = 0;
+ this.pictureBox1.TabStop = false;
+ //
+ // CLIMViewer
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(565, 386);
+ this.Controls.Add(this.pictureBox1);
+ this.Name = "CLIMViewer";
+ this.Text = "CLIMViewer";
+ this.Load += new System.EventHandler(this.CLIMViewer_Load);
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.PictureBox pictureBox1;
+ }
+}
\ No newline at end of file
diff --git a/GCNWii/UI/BTIViewer.cs b/GCNWii/UI/BTIViewer.cs
new file mode 100644
index 0000000..b6b1c3d
--- /dev/null
+++ b/GCNWii/UI/BTIViewer.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using GCNWii.JSystem;
+
+namespace GCNWii.UI
+{
+ public partial class BTIViewer : Form
+ {
+ BTI Image;
+ public BTIViewer(BTI Image)
+ {
+ this.Image = Image;
+ InitializeComponent();
+ }
+
+ private void CLIMViewer_Load(object sender, EventArgs e)
+ {
+ pictureBox1.Image = Image.ToBitmap();
+ }
+ }
+}
diff --git a/GCNWii/UI/BTIViewer.resx b/GCNWii/UI/BTIViewer.resx
new file mode 100644
index 0000000..94641fc
--- /dev/null
+++ b/GCNWii/UI/BTIViewer.resx
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ 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
+ CVKmAAAAAElFTkSuQmCC
+
+
+
\ No newline at end of file
diff --git a/LibEveryFileExplorer/GFX/ColorFormat.cs b/LibEveryFileExplorer/GFX/ColorFormat.cs
new file mode 100644
index 0000000..a2f11b7
--- /dev/null
+++ b/LibEveryFileExplorer/GFX/ColorFormat.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace LibEveryFileExplorer.GFX
+{
+ public class ColorFormat
+ {
+ public readonly int AShift, ASize, RShift, RSize, GShift, GSize, BShift, BSize;
+
+ public ColorFormat(int AShift, int ASize, int RShift, int RSize, int GShift, int GSize, int BShift, int BSize)
+ {
+ this.AShift = AShift;
+ this.ASize = ASize;
+ this.RShift = RShift;
+ this.RSize = RSize;
+ this.GShift = GShift;
+ this.GSize = GSize;
+ this.BShift = BShift;
+ this.BSize = BSize;
+ }
+ //The naming is based on the bit order when read out in the correct endianness
+ public static readonly ColorFormat ARGB8888 = new ColorFormat(24, 8, 16, 8, 8, 8, 0, 8);
+
+ public static readonly ColorFormat ARGB3444 = new ColorFormat(12, 3, 8, 4, 4, 4, 0, 4);
+
+ public static readonly ColorFormat RGBA8888 = new ColorFormat(0, 8, 24, 8, 16, 8, 8, 8);
+
+ public static readonly ColorFormat RGBA4444 = new ColorFormat(0, 4, 12, 4, 8, 4, 4, 4);
+
+ public static readonly ColorFormat RGB888 = new ColorFormat(0, 0, 16, 8, 8, 8, 0, 8);
+
+ public static readonly ColorFormat RGB565 = new ColorFormat(0, 0, 11, 5, 5, 6, 0, 5);
+
+ public static readonly ColorFormat ARGB1555 = new ColorFormat(15, 1, 10, 5, 5, 5, 0, 5);
+ public static readonly ColorFormat XRGB1555 = new ColorFormat(0, 0, 10, 5, 5, 5, 0, 5);
+
+ public static readonly ColorFormat ABGR1555 = new ColorFormat(15, 1, 0, 5, 5, 5, 10, 5);
+ public static readonly ColorFormat XBGR1555 = new ColorFormat(0, 0, 0, 5, 5, 5, 10, 5);
+ }
+}
diff --git a/LibEveryFileExplorer/GFX/ETC1.cs b/LibEveryFileExplorer/GFX/ETC1.cs
index 71a302c..acb15f6 100644
--- a/LibEveryFileExplorer/GFX/ETC1.cs
+++ b/LibEveryFileExplorer/GFX/ETC1.cs
@@ -386,12 +386,12 @@ namespace LibEveryFileExplorer.GFX
if ((flipbit && y3 < 2) || (!flipbit && x3 < 2))
{
int add = ETC1Modifiers[Table1, val] * (neg ? -1 : 1);
- c = GFXUtil.ToArgb((byte)(((Alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r1 + add), (byte)ColorClamp(g1 + add), (byte)ColorClamp(b1 + add));
+ c = GFXUtil.ToColorFormat((byte)(((Alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r1 + add), (byte)ColorClamp(g1 + add), (byte)ColorClamp(b1 + add), ColorFormat.ARGB8888);
}
else
{
int add = ETC1Modifiers[Table2, val] * (neg ? -1 : 1);
- c = GFXUtil.ToArgb((byte)(((Alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r2 + add), (byte)ColorClamp(g2 + add), (byte)ColorClamp(b2 + add));
+ c = GFXUtil.ToColorFormat((byte)(((Alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r2 + add), (byte)ColorClamp(g2 + add), (byte)ColorClamp(b2 + add), ColorFormat.ARGB8888);
}
Result[y3 * 4 + x3] = Color.FromArgb((int)c);
//res[(i + y3) * stride + x + j + x3] = c;
diff --git a/LibEveryFileExplorer/GFX/GFXUtil.cs b/LibEveryFileExplorer/GFX/GFXUtil.cs
index f59f4f5..e8f967a 100644
--- a/LibEveryFileExplorer/GFX/GFXUtil.cs
+++ b/LibEveryFileExplorer/GFX/GFXUtil.cs
@@ -8,119 +8,6 @@ namespace LibEveryFileExplorer.GFX
{
public class GFXUtil
{
- ///
- /// Converts the given color to the default 32bpp color format used in C#. (System.Drawing.Imaging.PixelFormat.Format32bppArgb)
- ///
- /// The XBGR1555 color to convert.
- ///
- public static uint XBGR1555ToArgb(ushort Color)
- {
- return ToArgb(
- 255,
- (byte)((Color & 0x1F) * 8),
- (byte)(((Color >> 5) & 0x1F) * 8),
- (byte)(((Color >> 10) & 0x1F) * 8)
- );
- }
-
- public static ushort ArgbToXBGR1555(uint Color)
- {
- return (ushort)(
- ((((Color >> 0) & 0xFF) >> 3) << 10) |
- ((((Color >> 8) & 0xFF) >> 3) << 5) |
- ((((Color >> 16) & 0xFF) >> 3) << 0));
- }
-
- ///
- /// Converts the given color to the default 32bpp color format used in C#. (System.Drawing.Imaging.PixelFormat.Format32bppArgb)
- ///
- /// The ABGR1555 color to convert.
- ///
- public static uint ABGR1555ToArgb(ushort Color)
- {
- return ToArgb(
- (byte)((Color >> 15) * 255),
- (byte)((Color & 0x1F) * 8),
- (byte)(((Color >> 5) & 0x1F) * 8),
- (byte)(((Color >> 10) & 0x1F) * 8)
- );
- }
-
- ///
- /// Converts the given color to the default 32bpp color format used in C#. (System.Drawing.Imaging.PixelFormat.Format32bppArgb)
- ///
- /// The RGBA5551 color to convert.
- ///
- public static uint ARGB1555ToArgb(ushort Color)
- {
- return ToArgb(
- (byte)((Color >> 15) * 255),
- (byte)(((Color >> 10) & 0x1F) * 8),
- (byte)(((Color >> 5) & 0x1F) * 8),
- (byte)((Color & 0x1F) * 8)
- );
- }
-
- ///
- /// Converts the given color to the default 32bpp color format used in C#. (System.Drawing.Imaging.PixelFormat.Format32bppArgb)
- ///
- /// The RGB565 color to convert.
- ///
- public static uint RGB565ToArgb(ushort Color)
- {
- return ToArgb(
- 255,
- (byte)(((Color >> 11) & 0x1F) * 8),
- (byte)(((Color >> 5) & 0x3F) * 4),
- (byte)((Color & 0x1F) * 8)
- );
- }
-
- ///
- /// Converts the given color to RGB565.
- ///
- /// The color to convert in the default 32bpp color format used in C#. (System.Drawing.Imaging.PixelFormat.Format32bppArgb)
- ///
- public static ushort ArgbToRGB565(uint Color)
- {
- uint A = (Color >> 24) & 0xFF;
- uint R = (Color >> 16) & 0xFF;
- uint G = (Color >> 8) & 0xFF;
- uint B = (Color >> 0) & 0xFF;
- if (A < 128) { R = 0; G = 0; B = 0; }
- return (ushort)((((R >> 3) << 11) | ((G >> 2) << 5) | ((B >> 3) << 0)) & 0xFFFF);
- }
-
- ///
- /// Converts the given color to the default 32bpp color format used in C# with an alpha value of 255. (System.Drawing.Imaging.PixelFormat.Format32bppArgb)
- ///
- /// Red
- /// Green
- /// Blue
- ///
- public static uint ToArgb(byte R, byte G, byte B)
- {
- return ToArgb(255, R, G, B);
- }
-
- ///
- /// Converts the given color to the default 32bpp color format used in C#. (System.Drawing.Imaging.PixelFormat.Format32bppArgb)
- ///
- /// Alpha
- /// Red
- /// Green
- /// Blue
- ///
- public static uint ToArgb(byte A, byte R, byte G, byte B)
- {
- return (uint)(A << 24 | R << 16 | G << 8 | B);
- }
-
- public static uint SetArgbAlpha(uint Argb, byte A)
- {
- return (uint)((uint)A << 24 | (Argb & 0xFFFFFF));
- }
-
public static Bitmap Resize(Bitmap Original, int Width, int Height)
{
if (Original.Width == Width && Original.Height == Height) return Original;
@@ -135,5 +22,59 @@ namespace LibEveryFileExplorer.GFX
}
return res;
}
+
+ public static uint ConvertColorFormat(uint InColor, ColorFormat InputFormat, ColorFormat OutputFormat)
+ {
+ if (InputFormat == OutputFormat) return InColor;
+ //From color format to components:
+ uint A, R, G, B;
+ uint mask;
+ if (InputFormat.ASize == 0) A = 255;
+ else
+ {
+ mask = ~(0xFFFFFFFFu << InputFormat.ASize);
+ A = ((((InColor >> InputFormat.AShift) & mask) * 255u) + mask / 2) / mask;
+ }
+ mask = ~(0xFFFFFFFFu << InputFormat.RSize);
+ R = ((((InColor >> InputFormat.RShift) & mask) * 255u) + mask / 2) / mask;
+ mask = ~(0xFFFFFFFFu << InputFormat.GSize);
+ G = ((((InColor >> InputFormat.GShift) & mask) * 255u) + mask / 2) / mask;
+ mask = ~(0xFFFFFFFFu << InputFormat.BSize);
+ B = ((((InColor >> InputFormat.BShift) & mask) * 255u) + mask / 2) / mask;
+ return ToColorFormat(A, R, G, B, OutputFormat);
+ }
+
+ public static uint ToColorFormat(int R, int G, int B, ColorFormat OutputFormat)
+ {
+ return ToColorFormat(255u, (uint)R, (uint)G, (uint)B, OutputFormat);
+ }
+
+ public static uint ToColorFormat(int A, int R, int G, int B, ColorFormat OutputFormat)
+ {
+ return ToColorFormat((uint)A, (uint)R, (uint)G, (uint)B, OutputFormat);
+ }
+
+ public static uint ToColorFormat(uint R, uint G, uint B, ColorFormat OutputFormat)
+ {
+ return ToColorFormat(255u, R, G, B, OutputFormat);
+ }
+
+ public static uint ToColorFormat(uint A, uint R, uint G, uint B, ColorFormat OutputFormat)
+ {
+ uint result = 0;
+ uint mask;
+ if (OutputFormat.ASize != 0)
+ {
+ mask = ~(0xFFFFFFFFu << OutputFormat.ASize);
+ result |= ((A * mask + 127u) / 255u) << OutputFormat.AShift;
+ }
+ mask = ~(0xFFFFFFFFu << OutputFormat.RSize);
+ result |= ((R * mask + 127u) / 255u) << OutputFormat.RShift;
+ mask = ~(0xFFFFFFFFu << OutputFormat.GSize);
+ result |= ((G * mask + 127u) / 255u) << OutputFormat.GShift;
+ mask = ~(0xFFFFFFFFu << OutputFormat.BSize);
+ result |= ((B * mask + 127u) / 255u) << OutputFormat.BShift;
+ return result;
+ }
}
}
diff --git a/LibEveryFileExplorer/IO/IOUtil.cs b/LibEveryFileExplorer/IO/IOUtil.cs
index 70a9637..166f13b 100644
--- a/LibEveryFileExplorer/IO/IOUtil.cs
+++ b/LibEveryFileExplorer/IO/IOUtil.cs
@@ -38,17 +38,32 @@ namespace LibEveryFileExplorer.IO
return (ushort)(Data[Offset] | (Data[Offset + 1] << 8));
}
+ public static ushort ReadU16BE(byte[] Data, int Offset)
+ {
+ return (ushort)((Data[Offset] << 8) | Data[Offset + 1]);
+ }
+
public static void WriteU16LE(byte[] Data, int Offset, ushort Value)
{
Data[Offset] = (byte)(Value & 0xFF);
Data[Offset + 1] = (byte)((Value >> 8) & 0xFF);
}
+ public static uint ReadU24LE(byte[] Data, int Offset)
+ {
+ return (uint)(Data[Offset] | (Data[Offset + 1] << 8) | (Data[Offset + 2] << 16));
+ }
+
public static uint ReadU32LE(byte[] Data, int Offset)
{
return (uint)(Data[Offset] | (Data[Offset + 1] << 8) | (Data[Offset + 2] << 16) | (Data[Offset + 3] << 24));
}
+ public static uint ReadU32BE(byte[] Data, int Offset)
+ {
+ return (uint)((Data[Offset] << 24) | (Data[Offset + 1] << 16) | (Data[Offset + 2] << 8) | Data[Offset + 3]);
+ }
+
public static void WriteU32LE(byte[] Data, int Offset, uint Value)
{
Data[Offset] = (byte)(Value & 0xFF);
diff --git a/LibEveryFileExplorer/LibEveryFileExplorer.csproj b/LibEveryFileExplorer/LibEveryFileExplorer.csproj
index 6c4b579..97b80fc 100644
--- a/LibEveryFileExplorer/LibEveryFileExplorer.csproj
+++ b/LibEveryFileExplorer/LibEveryFileExplorer.csproj
@@ -56,6 +56,7 @@
+
diff --git a/Libraries/HashTable.saht b/Libraries/HashTable.saht
index e2fd820..f4390da 100644
Binary files a/Libraries/HashTable.saht and b/Libraries/HashTable.saht differ
diff --git a/MarioKart/MKDS/NKM/STAG.cs b/MarioKart/MKDS/NKM/STAG.cs
index 7feb7be..2164be4 100644
--- a/MarioKart/MKDS/NKM/STAG.cs
+++ b/MarioKart/MKDS/NKM/STAG.cs
@@ -49,12 +49,12 @@ namespace MarioKart.MKDS.NKM
FogSlope = er.ReadByte();
UnknownData1 = er.ReadBytes(0x8);
FogDensity = er.ReadFx32();
- FogColor = Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(er.ReadUInt16()));
+ FogColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888));
FogAlpha = er.ReadUInt16();
- KclColor1 = Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(er.ReadUInt16()));
- KclColor2 = Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(er.ReadUInt16()));
- KclColor3 = Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(er.ReadUInt16()));
- KclColor4 = Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(er.ReadUInt16()));
+ KclColor1 = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888));
+ KclColor2 = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888));
+ KclColor3 = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888));
+ KclColor4 = Color.FromArgb((int)GFXUtil.ConvertColorFormat(er.ReadUInt16(), ColorFormat.XBGR1555, ColorFormat.ARGB8888));
FrustumFar = er.ReadFx32();
UnknownData2 = er.ReadBytes(0x4);
}
@@ -70,12 +70,12 @@ namespace MarioKart.MKDS.NKM
er.Write(FogSlope);
er.Write(UnknownData1, 0, 8);
er.WriteFx32(FogDensity);
- er.Write((UInt16)(GFXUtil.ArgbToXBGR1555((uint)FogColor.ToArgb()) | 0x8000));
+ er.Write((UInt16)(GFXUtil.ConvertColorFormat((uint)FogColor.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555) | 0x8000));
er.Write(FogAlpha);
- er.Write(GFXUtil.ArgbToXBGR1555((uint)KclColor1.ToArgb()));
- er.Write(GFXUtil.ArgbToXBGR1555((uint)KclColor2.ToArgb()));
- er.Write(GFXUtil.ArgbToXBGR1555((uint)KclColor3.ToArgb()));
- er.Write(GFXUtil.ArgbToXBGR1555((uint)KclColor4.ToArgb()));
+ er.Write((UInt16)GFXUtil.ConvertColorFormat((uint)KclColor1.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555));
+ er.Write((UInt16)GFXUtil.ConvertColorFormat((uint)KclColor2.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555));
+ er.Write((UInt16)GFXUtil.ConvertColorFormat((uint)KclColor3.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555));
+ er.Write((UInt16)GFXUtil.ConvertColorFormat((uint)KclColor4.ToArgb(), ColorFormat.ARGB8888, ColorFormat.XBGR1555));
er.WriteFx32(FrustumFar);
er.Write(UnknownData2, 0, 4);
}
diff --git a/NDS/GPU/CommandContext.cs b/NDS/GPU/CommandContext.cs
index 2aa2b73..6bf8f6c 100644
--- a/NDS/GPU/CommandContext.cs
+++ b/NDS/GPU/CommandContext.cs
@@ -294,7 +294,7 @@ namespace NDS.GPU
}
public void Color(uint color)
{
- Color(System.Drawing.Color.FromArgb((int)GFXUtil.XBGR1555ToArgb((ushort)color)));
+ Color(System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(color, ColorFormat.XBGR1555, ColorFormat.ARGB8888)));
}
public void Color(Color color)
{
@@ -474,8 +474,8 @@ namespace NDS.GPU
ushort diff = (ushort)(cmd & 0x7FFF);
bool vtx = (cmd & 0x8000) != 0;
ushort amb = (ushort)((cmd >> 16) & 0x7FFF);
- DiffuseColor = System.Drawing.Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(diff));
- AmbientColor = System.Drawing.Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(amb));
+ DiffuseColor = System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(diff, ColorFormat.XBGR1555, ColorFormat.ARGB8888));
+ AmbientColor = System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(amb, ColorFormat.XBGR1555, ColorFormat.ARGB8888));
if (vtx) Color(DiffuseColor);
}
public void MaterialColor1(uint cmd)
@@ -484,8 +484,8 @@ namespace NDS.GPU
bool shine = (cmd & 0x8000) != 0;
ushort emiss = (ushort)((cmd >> 16) & 0x7FFF);
UsesSpecularReflectionTable = shine;
- SpecularColor = System.Drawing.Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(spec));
- EmissionColor = System.Drawing.Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(emiss));
+ SpecularColor = System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(spec, ColorFormat.XBGR1555, ColorFormat.ARGB8888));
+ EmissionColor = System.Drawing.Color.FromArgb((int)GFXUtil.ConvertColorFormat(emiss, ColorFormat.XBGR1555, ColorFormat.ARGB8888));
}
public void Shininess(uint[] SpecReflectTable)
{
diff --git a/NDS/GPU/Textures.cs b/NDS/GPU/Textures.cs
index 5d04130..ef62d65 100644
--- a/NDS/GPU/Textures.cs
+++ b/NDS/GPU/Textures.cs
@@ -364,7 +364,7 @@ namespace NDS.GPU
Color[] data = new Color[Data.Length / 2];
for (int i = 0; i < Data.Length; i += 2)
{
- data[i / 2] = Color.FromArgb((int)GFXUtil.ABGR1555ToArgb(IOUtil.ReadU16LE(Data, i)));
+ data[i / 2] = Color.FromArgb((int)GFXUtil.ConvertColorFormat(IOUtil.ReadU16LE(Data, i), ColorFormat.ABGR1555, ColorFormat.ARGB8888));
}
return data;
}
@@ -374,7 +374,7 @@ namespace NDS.GPU
Color[] data = new Color[Data.Length / 2];
for (int i = 0; i < Data.Length; i += 2)
{
- data[i / 2] = Color.FromArgb((int)GFXUtil.XBGR1555ToArgb(IOUtil.ReadU16LE(Data, i)));
+ data[i / 2] = Color.FromArgb((int)GFXUtil.ConvertColorFormat(IOUtil.ReadU16LE(Data, i), ColorFormat.XBGR1555, ColorFormat.ARGB8888));
}
return data;
}
diff --git a/NDS/UI/MDL0MaterialEditor.cs b/NDS/UI/MDL0MaterialEditor.cs
index da25521..dfb8558 100644
--- a/NDS/UI/MDL0MaterialEditor.cs
+++ b/NDS/UI/MDL0MaterialEditor.cs
@@ -37,12 +37,12 @@ namespace NDS.UI
trackBar2.Value = (int)((Material.polyAttr >> 24) & 63);
checkBox1.Checked = (Material.diffAmb & 0x8000) != 0;
- button1.BackColor = System.Drawing.Color.FromArgb((int)GFXUtil.XBGR1555ToArgb((ushort)(Material.diffAmb & 0x7FFF)));
- button2.BackColor = System.Drawing.Color.FromArgb((int)GFXUtil.XBGR1555ToArgb((ushort)((Material.diffAmb >> 16) & 0x7FFF)));
+ button1.BackColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat(Material.diffAmb & 0x7FFF, ColorFormat.XBGR1555, ColorFormat.ARGB8888));//(int)GFXUtil.XBGR1555ToArgb((ushort)(Material.diffAmb & 0x7FFF)));
+ button2.BackColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat((Material.diffAmb >> 16) & 0x7FFF, ColorFormat.XBGR1555, ColorFormat.ARGB8888));
checkBox2.Checked = (Material.specEmi & 0x8000) != 0;
- button3.BackColor = System.Drawing.Color.FromArgb((int)GFXUtil.XBGR1555ToArgb((ushort)(Material.specEmi & 0x7FFF)));
- button4.BackColor = System.Drawing.Color.FromArgb((int)GFXUtil.XBGR1555ToArgb((ushort)((Material.specEmi >> 16) & 0x7FFF)));
+ button3.BackColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat(Material.specEmi & 0x7FFF, ColorFormat.XBGR1555, ColorFormat.ARGB8888));
+ button4.BackColor = Color.FromArgb((int)GFXUtil.ConvertColorFormat((Material.specEmi >> 16) & 0x7FFF, ColorFormat.XBGR1555, ColorFormat.ARGB8888));
uint wrapS = (Material.texImageParam >> 16) & 1;
if (wrapS != 0) wrapS += (Material.texImageParam >> 18) & 1;