diff --git a/pk3DS/3DS/BCLIM.cs b/pk3DS/3DS/BCLIM.cs
index 8f79cde..e6605b3 100644
--- a/pk3DS/3DS/BCLIM.cs
+++ b/pk3DS/3DS/BCLIM.cs
@@ -2,6 +2,8 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
+using System.Runtime.InteropServices;
+using pk3DS.Properties; // For other projects, replace this line with the namespace that contains your ETC1Lib.dll resource.
namespace CTR
{
@@ -97,7 +99,7 @@ internal static Image makeBMP(string path, bool autosave = false, bool crop = tr
else
img = getIMG(bclim);
- if (img == null) return img;
+ if (img == null) return null;
Rectangle cropRect = new Rectangle(0, 0, bclim.Width, bclim.Height);
Bitmap CropBMP = new Bitmap(cropRect.Width, cropRect.Height);
using (Graphics g = Graphics.FromImage(CropBMP))
@@ -235,22 +237,99 @@ internal static Bitmap getIMG_XY7(CLIM bclim)
}
internal static Bitmap getIMG_ETC(CLIM bclim)
{
- //int format = bclim.FileFormat;
- //if (format != 10 && format != 11)
- // return null;
+ Bitmap img = new Bitmap(Math.Max(nlpo2(bclim.Width), 16), Math.Max(nlpo2(bclim.Height), 16));
+ string dllpath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + "\\ETC1Lib.dll";
+ if (!File.Exists(dllpath)) File.WriteAllBytes(dllpath, Resources.ETC1Lib);
- //byte[] data = ETC1_Decompress(bclim.Data, bclim.Width, bclim.Height, format + 2);
- //Bitmap img = new Bitmap(bclim.Width, bclim.Height);
+ try
+ {
+ /* http://jul.rustedlogic.net/thread.php?id=17312
+ * Much of this code is taken/modified from Tharsis. Thank you to Tharsis's creator, xdaniel.
+ * https://github.com/xdanieldzd/Tharsis
+ */
- //for (int i = 0; i < bclim.Width * bclim.Height; i++) // for every pixel
- //{
- // Color c = DecodeColor(BitConverter.ToUInt32(data, i * 4), 9);
- // int x = i % bclim.Width;
- // int y = i / bclim.Width;
- // img.SetPixel(x, y, c);
- //}
- //return img;
- return null;
+ /* Get compressed data & handle to it */
+ byte[] textureData = bclim.Data;
+ //textureData = switchEndianness(textureData, 0x10);
+ ushort[] input = new ushort[textureData.Length/sizeof (ushort)];
+ Buffer.BlockCopy(textureData, 0, input, 0, textureData.Length);
+ GCHandle pInput = GCHandle.Alloc(input, GCHandleType.Pinned);
+
+ /* Marshal data around, invoke ETC1.dll for conversion, etc */
+ UInt32 size1 = 0;
+ UInt16 w = (ushort)img.Width, h = (ushort)img.Height;
+
+ ETC1.ConvertETC1(IntPtr.Zero, ref size1, IntPtr.Zero, w, h, bclim.FileFormat == 0xB); // true = etc1a4, false = etc1
+ // System.Diagnostics.Debug.WriteLine(size1);
+ uint[] output = new uint[size1];
+ GCHandle pOutput = GCHandle.Alloc(output, GCHandleType.Pinned);
+ ETC1.ConvertETC1(pOutput.AddrOfPinnedObject(), ref size1, pInput.AddrOfPinnedObject(), w, h, bclim.FileFormat == 0xB);
+ pOutput.Free();
+ pInput.Free();
+
+
+ /* Unscramble if needed // could probably be done in ETC1Lib.dll, it's probably pretty ugly, but whatever... */
+ /* Non-square code blocks could need some cleanup, verification, etc. as well... */
+ uint[] finalized = new uint[output.Length];
+
+ // Act if it's square because BCLIM swizzling is stupid
+ Buffer.BlockCopy(output, 0, finalized, 0, finalized.Length);
+
+ byte[] tmp = new byte[finalized.Length];
+ Buffer.BlockCopy(finalized, 0, tmp, 0, tmp.Length);
+ byte[] imgData = tmp;
+
+ for (int i = 0; i < w; i++)
+ {
+ for (int j = 0; j < h; j++)
+ {
+ int k = (j + i*img.Height)*4;
+ img.SetPixel(i, j, Color.FromArgb(imgData[k + 3], imgData[k], imgData[k + 1], imgData[k + 2]));
+ }
+ }
+ // Image is 13 instead of 12
+ // 24 34
+ img.RotateFlip(RotateFlipType.Rotate90FlipX);
+ if (w > h)
+ {
+ // Image is now in appropriate order, but the shifting is messed up. Let's fix that.
+ Bitmap img2 = new Bitmap(Math.Max(nlpo2(bclim.Width), 16), Math.Max(nlpo2(bclim.Height), 16));
+ for (int y = 0; y < Math.Max(nlpo2(bclim.Width), 16); y += 8)
+ {
+ for (int x = 0; x < Math.Max(nlpo2(bclim.Height), 16); x++)
+ {
+ for (int j = 0; j < 8; j++)
+ // Treat every 8 vertical pixels as 1 pixel for purposes of calculation, add to offset later.
+ {
+ int x1 = (x + ((y/8)*h))%img2.Width; // Reshift x
+ int y1 = ((x + ((y/8)*h))/img2.Width)*8; // Reshift y
+ img2.SetPixel(x1, y1 + j, img.GetPixel(x, y + j)); // Reswizzle
+ }
+ }
+ }
+ img = img2;
+ }
+ else if (h > w)
+ {
+ Bitmap img2 = new Bitmap(Math.Max(nlpo2(bclim.Width), 16), Math.Max(nlpo2(bclim.Height), 16));
+ for (int y = 0; y < Math.Max(nlpo2(bclim.Width), 16); y += 8)
+ {
+ for (int x = 0; x < Math.Max(nlpo2(bclim.Height), 16); x++)
+ {
+ for (int j = 0; j < 8; j++)
+ // Treat every 8 vertical pixels as 1 pixel for purposes of calculation, add to offset later.
+ {
+ int x1 = x%img2.Width; // Reshift x
+ int y1 = ((x + ((y/8)*h))/img2.Width)*8; // Reshift y
+ img2.SetPixel(x1, y1 + j, img.GetPixel(x, y + j)); // Reswizzle
+ }
+ }
+ }
+ img = img2;
+ }
+ }
+ catch { }
+ return img;
}
// BCLIM Data Writing
diff --git a/pk3DS/3DS/ETC1.cs b/pk3DS/3DS/ETC1.cs
index f269887..d78b93b 100644
--- a/pk3DS/3DS/ETC1.cs
+++ b/pk3DS/3DS/ETC1.cs
@@ -1,6 +1,11 @@
-namespace CTR
+using System;
+using System.Runtime.InteropServices;
+
+namespace CTR
{
class ETC1
{
+ [DllImport("ETC1Lib.dll", EntryPoint = "ConvertETC1", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ConvertETC1(IntPtr dataOut, ref UInt32 dataOutSize, IntPtr dataIn, UInt16 width, UInt16 height, bool alpha);
}
-}
+}
\ No newline at end of file
diff --git a/pk3DS/Properties/Resources.Designer.cs b/pk3DS/Properties/Resources.Designer.cs
index fd7e2bb..18d273d 100644
--- a/pk3DS/Properties/Resources.Designer.cs
+++ b/pk3DS/Properties/Resources.Designer.cs
@@ -10470,6 +10470,16 @@ internal class Resources {
}
}
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] ETC1Lib {
+ get {
+ object obj = ResourceManager.GetObject("ETC1Lib", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
diff --git a/pk3DS/Properties/Resources.resx b/pk3DS/Properties/Resources.resx
index 0d9c780..fd64127 100644
--- a/pk3DS/Properties/Resources.resx
+++ b/pk3DS/Properties/Resources.resx
@@ -4519,4 +4519,7 @@
..\Resources\romdata\txt\3dsgames.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
+ ..\Resources\ETC1Lib.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
\ No newline at end of file
diff --git a/pk3DS/Resources/ETC1Lib.dll b/pk3DS/Resources/ETC1Lib.dll
new file mode 100644
index 0000000..81bf863
Binary files /dev/null and b/pk3DS/Resources/ETC1Lib.dll differ
diff --git a/pk3DS/pk3DS.csproj b/pk3DS/pk3DS.csproj
index 9ca3c09..f5137c0 100644
--- a/pk3DS/pk3DS.csproj
+++ b/pk3DS/pk3DS.csproj
@@ -4677,6 +4677,9 @@
+
+
+