Exemple #1
0
        /// <summary>
        ///     Encodes a PICA200 Texture.
        /// </summary>
        /// <param name="img">Input image to be encoded</param>
        /// <param name="format">Pixel Format of the Texture</param>
        /// <returns></returns>
        public byte[] encode(Bitmap img, RenderBase.OTextureFormat format)
        {
            byte[] data   = new TextureUtils().getArray(img);
            byte[] output = new byte[data.Length];

            uint outputOffset = 0;

            switch (format)
            {
            case RenderBase.OTextureFormat.rgba8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + ((tY * 8 + y) * img.Width)) * 4;

                            Buffer.BlockCopy(data, (int)dataOffset, output, (int)outputOffset + 1, 3);
                            output[outputOffset] = data[dataOffset + 3];

                            outputOffset += 4;
                        }
                    }
                }
                break;

            default: throw new NotImplementedException();
            }

            return(output);
        }
Exemple #2
0
        private int returnSize(RenderBase.OTextureFormat fmt, int w, int h)
        {
            switch (fmt)
            {
            case RenderBase.OTextureFormat.rgba8: return((w * h) * 4);

            case RenderBase.OTextureFormat.rgb8: return((w * h) * 3);

            case RenderBase.OTextureFormat.rgba5551: return((w * h) * 2);

            case RenderBase.OTextureFormat.rgb565: return((w * h) * 2);

            case RenderBase.OTextureFormat.rgba4: return((w * h) * 2);

            case RenderBase.OTextureFormat.la8: return((w * h) * 2);

            case RenderBase.OTextureFormat.hilo8: return((w * h) * 2);

            case RenderBase.OTextureFormat.l8: return(w * h);

            case RenderBase.OTextureFormat.a8: return(w * h);

            case RenderBase.OTextureFormat.la4: return(w * h);

            case RenderBase.OTextureFormat.l4: return((w * h) >> 1);

            case RenderBase.OTextureFormat.a4: return((w * h) >> 1);

            case RenderBase.OTextureFormat.etc1: return((w * h) >> 1);

            case RenderBase.OTextureFormat.etc1a4: return(w * h);

            default: throw new Exception("OBCHTextureReplacer: Invalid texture format on BCH!");
            }
        }
        public static RenderBase.OTexture loadTexture(string fileName)
        {
            if (File.Exists(fileName))
            {
                Serialization.SERI tex = Serialization.getSERI(fileName);

                int    width           = tex.getIntegerParameter("w");
                int    height          = tex.getIntegerParameter("h");
                int    mipmap          = tex.getIntegerParameter("mipmap");
                int    format          = tex.getIntegerParameter("format");
                string textureName     = tex.getStringParameter("tex");
                string fullTextureName = Path.Combine(Path.GetDirectoryName(fileName), textureName);

                if (File.Exists(fullTextureName))
                {
                    RenderBase.OTextureFormat fmt = RenderBase.OTextureFormat.dontCare;
                    switch (format)
                    {
                    case 0: fmt = RenderBase.OTextureFormat.l4; break;

                    case 1: fmt = RenderBase.OTextureFormat.l8; break;

                    case 7: fmt = RenderBase.OTextureFormat.rgb565; break;

                    case 8: fmt = RenderBase.OTextureFormat.rgba5551; break;

                    case 9: fmt = RenderBase.OTextureFormat.rgba4; break;

                    case 0xa: fmt = RenderBase.OTextureFormat.rgba8; break;

                    case 0xb: fmt = RenderBase.OTextureFormat.rgb8; break;

                    case 0xc: fmt = RenderBase.OTextureFormat.etc1; break;

                    case 0xd: fmt = RenderBase.OTextureFormat.etc1a4; break;

                    default: Debug.WriteLine("NLP Model: Unknown Texture format 0x" + format.ToString("X8")); break;
                    }

                    string name   = Path.GetFileNameWithoutExtension(textureName);
                    byte[] buffer = File.ReadAllBytes(fullTextureName);
                    return(new RenderBase.OTexture(TextureCodec.decode(buffer, width, height, fmt), name));
                }
            }

            return(null);
        }
        /// <summary>
        ///     Decodes a PICA200 Texture.
        /// </summary>
        /// <param name="data">Buffer with the Texture</param>
        /// <param name="width">Width of the Texture</param>
        /// <param name="height">Height of the Texture</param>
        /// <param name="format">Pixel Format of the Texture</param>
        /// <returns></returns>
        public static Bitmap decode(byte[] data, int width, int height, RenderBase.OTextureFormat format)
        {
            byte[] output     = new byte[width * height * 4];
            long   dataOffset = 0;
            bool   toggle     = false;

            switch (format)
            {
            case RenderBase.OTextureFormat.rgba8:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + ((tY * 8 + y) * width)) * 4;

                            Buffer.BlockCopy(data, (int)dataOffset + 1, output, (int)outputOffset, 3);
                            output[outputOffset + 3] = data[dataOffset];

                            dataOffset += 4;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgb8:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            Buffer.BlockCopy(data, (int)dataOffset, output, (int)outputOffset, 3);
                            output[outputOffset + 3] = 0xff;

                            dataOffset += 3;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgba5551:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            ushort pixelData = (ushort)(data[dataOffset] | (data[dataOffset + 1] << 8));

                            byte r = (byte)(((pixelData >> 1) & 0x1f) << 3);
                            byte g = (byte)(((pixelData >> 6) & 0x1f) << 3);
                            byte b = (byte)(((pixelData >> 11) & 0x1f) << 3);
                            byte a = (byte)((pixelData & 1) * 0xff);

                            output[outputOffset]     = (byte)(r | (r >> 5));
                            output[outputOffset + 1] = (byte)(g | (g >> 5));
                            output[outputOffset + 2] = (byte)(b | (b >> 5));
                            output[outputOffset + 3] = a;

                            dataOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgb565:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            ushort pixelData = (ushort)(data[dataOffset] | (data[dataOffset + 1] << 8));

                            byte r = (byte)((pixelData & 0x1f) << 3);
                            byte g = (byte)(((pixelData >> 5) & 0x3f) << 2);
                            byte b = (byte)(((pixelData >> 11) & 0x1f) << 3);

                            output[outputOffset]     = (byte)(r | (r >> 5));
                            output[outputOffset + 1] = (byte)(g | (g >> 6));
                            output[outputOffset + 2] = (byte)(b | (b >> 5));
                            output[outputOffset + 3] = 0xff;

                            dataOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgba4:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            ushort pixelData = (ushort)(data[dataOffset] | (data[dataOffset + 1] << 8));

                            byte r = (byte)((pixelData >> 4) & 0xf);
                            byte g = (byte)((pixelData >> 8) & 0xf);
                            byte b = (byte)((pixelData >> 12) & 0xf);
                            byte a = (byte)(pixelData & 0xf);

                            output[outputOffset]     = (byte)(r | (r << 4));
                            output[outputOffset + 1] = (byte)(g | (g << 4));
                            output[outputOffset + 2] = (byte)(b | (b << 4));
                            output[outputOffset + 3] = (byte)(a | (a << 4));

                            dataOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.la8:
            case RenderBase.OTextureFormat.hilo8:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            output[outputOffset]     = data[dataOffset];
                            output[outputOffset + 1] = data[dataOffset];
                            output[outputOffset + 2] = data[dataOffset];
                            output[outputOffset + 3] = data[dataOffset + 1];

                            dataOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.l8:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            output[outputOffset]     = data[dataOffset];
                            output[outputOffset + 1] = data[dataOffset];
                            output[outputOffset + 2] = data[dataOffset];
                            output[outputOffset + 3] = 0xff;

                            dataOffset++;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.a8:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            output[outputOffset]     = 0xff;
                            output[outputOffset + 1] = 0xff;
                            output[outputOffset + 2] = 0xff;
                            output[outputOffset + 3] = data[dataOffset];

                            dataOffset++;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.la4:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            output[outputOffset]     = (byte)(data[dataOffset] >> 4);
                            output[outputOffset + 1] = (byte)(data[dataOffset] >> 4);
                            output[outputOffset + 2] = (byte)(data[dataOffset] >> 4);
                            output[outputOffset + 3] = (byte)(data[dataOffset] & 0xf);

                            dataOffset++;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.l4:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            byte c = toggle ? (byte)((data[dataOffset++] & 0xf0) >> 4) : (byte)(data[dataOffset] & 0xf);
                            toggle = !toggle;
                            c      = (byte)((c << 4) | c);
                            output[outputOffset]     = c;
                            output[outputOffset + 1] = c;
                            output[outputOffset + 2] = c;
                            output[outputOffset + 3] = 0xff;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.a4:
                for (int tY = 0; tY < height / 8; tY++)
                {
                    for (int tX = 0; tX < width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x            = tileOrder[pixel] % 8;
                            int  y            = (tileOrder[pixel] - x) / 8;
                            long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4;

                            output[outputOffset]     = 0xff;
                            output[outputOffset + 1] = 0xff;
                            output[outputOffset + 2] = 0xff;
                            byte a = toggle ? (byte)((data[dataOffset++] & 0xf0) >> 4) : (byte)(data[dataOffset] & 0xf);
                            toggle = !toggle;
                            output[outputOffset + 3] = (byte)((a << 4) | a);
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.etc1:
            case RenderBase.OTextureFormat.etc1a4:
                byte[] decodedData = etc1Decode(data, width, height, format == RenderBase.OTextureFormat.etc1a4);
                int[]  etc1Order   = etc1Scramble(width, height);

                int i = 0;
                for (int tY = 0; tY < height / 4; tY++)
                {
                    for (int tX = 0; tX < width / 4; tX++)
                    {
                        int TX = etc1Order[i] % (width / 4);
                        int TY = (etc1Order[i] - TX) / (width / 4);
                        for (int y = 0; y < 4; y++)
                        {
                            for (int x = 0; x < 4; x++)
                            {
                                dataOffset = ((TX * 4) + x + (((TY * 4) + y) * width)) * 4;
                                long outputOffset = ((tX * 4) + x + (((tY * 4 + y)) * width)) * 4;

                                Buffer.BlockCopy(decodedData, (int)dataOffset, output, (int)outputOffset, 4);
                            }
                        }
                        i += 1;
                    }
                }

                break;
            }

            return(TextureUtils.getBitmap(output.ToArray(), width, height));
        }
Exemple #5
0
        public static RenderBase.OTexture loadTexture(string fileName)
        {
            if (File.Exists(fileName + ".xml"))
            {
                Serialization.SERI tex = Serialization.getSERI(fileName + ".xml");

                int    width           = tex.getIntegerParameter("w");
                int    height          = tex.getIntegerParameter("h");
                int    mipmap          = tex.getIntegerParameter("mipmap");
                int    format          = tex.getIntegerParameter("format");
                string textureName     = tex.getStringParameter("tex");
                string fullTextureName = fileName;

                if (File.Exists(fullTextureName))
                {
                    RenderBase.OTextureFormat fmt = RenderBase.OTextureFormat.dontCare;
                    switch (format)
                    {
                    case 0: fmt = RenderBase.OTextureFormat.l4; break;

                    case 1: fmt = RenderBase.OTextureFormat.l8; break;

                    case 3: fmt = RenderBase.OTextureFormat.la8; break;

                    case 7: fmt = RenderBase.OTextureFormat.rgb565; break;

                    case 8: fmt = RenderBase.OTextureFormat.rgba5551; break;

                    case 9: fmt = RenderBase.OTextureFormat.rgba4; break;

                    case 0xa: fmt = RenderBase.OTextureFormat.rgba8; break;

                    case 0xb: fmt = RenderBase.OTextureFormat.rgb8; break;

                    case 0xc: fmt = RenderBase.OTextureFormat.etc1; break;

                    case 0xd: fmt = RenderBase.OTextureFormat.etc1a4; break;

                    default: Debug.WriteLine("NLP Model: Unknown Texture format 0x" + format.ToString("X8")); break;
                    }

                    string name   = Path.GetFileNameWithoutExtension(textureName);
                    byte[] buffer = File.ReadAllBytes(fullTextureName);
                    if (mipmap > 1)
                    {
                        int lenght  = 0;
                        var texture = (fmt == RenderBase.OTextureFormat.etc1 || fmt == RenderBase.OTextureFormat.etc1a4?
                                       TextureCodec.decode(buffer, width, height, fmt, out lenght) :
                                       TextureCodec.getIMG(buffer, width, height, fmt, out lenght));
                        List <Bitmap> miptextures = new List <Bitmap>();
                        int           lenghtall   = lenght;
                        for (var i = 1; i < mipmap; i++)
                        {
                            var mip = new byte[lenghtall];
                            Buffer.BlockCopy(buffer, lenghtall, mip, 0, buffer.Length - lenghtall);
                            var miptexture = (fmt == RenderBase.OTextureFormat.etc1 || fmt == RenderBase.OTextureFormat.etc1a4 ?
                                              TextureCodec.decode(mip, width / Convert.ToInt32(Math.Pow(2, i)), height / Convert.ToInt32(Math.Pow(2, i)), fmt, out lenght) :
                                              TextureCodec.getIMG(mip, width / Convert.ToInt32(Math.Pow(2, i)), height / Convert.ToInt32(Math.Pow(2, i)), fmt, out lenght));
                            miptextures.Add(miptexture);
                            lenghtall += lenght;
                        }

                        return(new RenderBase.OTexture(texture, miptextures, name));
                    }
                    else
                    {
                        int dataOffset;

                        //TextureCodec.encode(TextureCodec.decode(buffer, width, height, fmt, out dataOffset), fmt);
                        return(new RenderBase.OTexture(TextureCodec.decode(buffer, width, height, fmt, out dataOffset), name));
                    }
                }
            }

            return(null);
        }
Exemple #6
0
        public static byte[] EncodeTexture(string fileName)
        {
            if (File.Exists(fileName))
            {
                if (File.Exists(fileName.Replace(filetype, ".texi.xml")))
                {
                    Serialization.SERI tex = Serialization.getSERI(fileName.Replace(filetype, ".texi.xml"));
                    int    width           = tex.getIntegerParameter("w");
                    int    height          = tex.getIntegerParameter("h");
                    int    mipmap          = tex.getIntegerParameter("mipmap");
                    int    format          = tex.getIntegerParameter("format");
                    string textureName     = tex.getStringParameter("tex");
                    //string fullTextureName = Path.Combine(Path.GetDirectoryName(fileName), textureName);


                    RenderBase.OTextureFormat fmt = RenderBase.OTextureFormat.dontCare;
                    switch (format)
                    {
                    case 0: fmt = RenderBase.OTextureFormat.l4; break;

                    case 1: fmt = RenderBase.OTextureFormat.l8; break;

                    case 3: fmt = RenderBase.OTextureFormat.la8; break;

                    case 7: fmt = RenderBase.OTextureFormat.rgb565; break;

                    case 8: fmt = RenderBase.OTextureFormat.rgba5551; break;

                    case 9: fmt = RenderBase.OTextureFormat.rgba4; break;

                    case 0xa: fmt = RenderBase.OTextureFormat.rgba8; break;

                    case 0xb: fmt = RenderBase.OTextureFormat.rgb8; break;

                    case 0xc: fmt = RenderBase.OTextureFormat.etc1; break;

                    case 0xd: fmt = RenderBase.OTextureFormat.etc1a4; break;

                    default: Debug.WriteLine("NLP Model: Unknown Texture format 0x" + format.ToString("X8")); break;
                    }

                    Stream           imageStreamSource = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                    PngBitmapDecoder decoder           = new PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                    int          frame        = 0; // adjust/ loop for multiframe tiffs
                    BitmapSource bitmapSource = decoder.Frames[0];

                    // this piece works for 8-bit grayscale. Adjust for other formats.
                    Bitmap     img  = new Bitmap(bitmapSource.PixelWidth, bitmapSource.PixelHeight, PixelFormat.Format32bppArgb);
                    BitmapData data = img.LockBits(new Rectangle(System.Drawing.Point.Empty, img.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
                    bitmapSource.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
                    img.UnlockBits(data);

                    IEnumerable <byte> main = TextureCodec.getPixelData(img, fmt);

                    if (mipmap > 1)
                    {
                        for (var i = 1; i < mipmap; i++)
                        {
                            var mimefile = fileName.Replace(filetype, ".mip" + (img.Width / Convert.ToInt32(Math.Pow(2, i))).ToString() + "X" + (img.Height / Convert.ToInt32(Math.Pow(2, i))).ToString() + filetype);
                            if (File.Exists(mimefile))
                            {
                                Bitmap mip = new Bitmap(mimefile);
                                main = main.Concat(TextureCodec.getPixelData(mip, fmt));
                                mip.Dispose();
                            }
                            else
                            {
                                Console.WriteLine(Path.GetFileName(mimefile) + " not found");
                            }
                        }
                    }
                    img.Dispose();
                    return(main.ToArray());
                }
            }

            return(null);
        }
Exemple #7
0
        internal static Color DecodeColor(uint val, RenderBase.OTextureFormat format)
        {
            int alpha = 0xFF, red, green, blue;

            switch (format)
            {
            case RenderBase.OTextureFormat.l8:     // L8
                return(Color.FromArgb(alpha, (byte)val, (byte)val, (byte)val));

            case RenderBase.OTextureFormat.a8:     // A8
                return(Color.FromArgb((byte)val, alpha, alpha, alpha));

            case RenderBase.OTextureFormat.la4:     // LA4
                red   = (byte)(val >> 4);
                alpha = (byte)(val & 0x0F);
                return(Color.FromArgb(alpha, red, red, red));

            case RenderBase.OTextureFormat.la8:     // LA8
                red   = (byte)((val >> 8 & 0xFF));
                alpha = (byte)(val & 0xFF);
                return(Color.FromArgb(alpha, red, red, red));

            case RenderBase.OTextureFormat.hilo8:     // HILO8
                red   = (byte)(val >> 8);
                green = (byte)(val & 0xFF);
                return(Color.FromArgb(alpha, red, green, 0xFF));

            case RenderBase.OTextureFormat.rgb565:     // RGB565
                red   = Convert5To8[(val >> 11) & 0x1F];
                green = (byte)(((val >> 5) & 0x3F) * 4);
                blue  = Convert5To8[val & 0x1F];
                return(Color.FromArgb(alpha, red, green, blue));

            case RenderBase.OTextureFormat.rgb8:     // RGB8
                red   = (byte)((val >> 16) & 0xFF);
                green = (byte)((val >> 8) & 0xFF);
                blue  = (byte)(val & 0xFF);
                return(Color.FromArgb(alpha, red, green, blue));

            case RenderBase.OTextureFormat.rgba5551:     // RGBA5551
                red   = Convert5To8[(val >> 11) & 0x1F];
                green = Convert5To8[(val >> 6) & 0x1F];
                blue  = Convert5To8[(val >> 1) & 0x1F];
                alpha = (val & 0x0001) == 1 ? 0xFF : 0x00;
                return(Color.FromArgb(alpha, red, green, blue));

            case RenderBase.OTextureFormat.rgba4:     // RGBA4444
                alpha = (byte)(0x11 * (val & 0xf));
                red   = (byte)(0x11 * ((val >> 12) & 0xf));
                green = (byte)(0x11 * ((val >> 8) & 0xf));
                blue  = (byte)(0x11 * ((val >> 4) & 0xf));
                return(Color.FromArgb(alpha, red, green, blue));

            case RenderBase.OTextureFormat.rgba8:     // RGBA8888
                red   = (byte)((val >> 24) & 0xFF);
                green = (byte)((val >> 16) & 0xFF);
                blue  = (byte)((val >> 8) & 0xFF);
                alpha = (byte)(val & 0xFF);
                return(Color.FromArgb(alpha, red, green, blue));

            // case 10:
            // case 11:
            case RenderBase.OTextureFormat.l4:     // L4
                return(Color.FromArgb(alpha, (byte)(val * 0x11), (byte)(val * 0x11), (byte)(val * 0x11)));

            case RenderBase.OTextureFormat.a4:     // A4
                return(Color.FromArgb((byte)(val * 0x11), alpha, alpha, alpha));

            default:
                return(Color.White);
            }
        }
Exemple #8
0
        public static byte[] getPixelData(Bitmap img, RenderBase.OTextureFormat format)
        {
            int w = img.Width;
            int h = img.Height;


            using (MemoryStream mz = new MemoryStream())
                using (BinaryWriter bz = new BinaryWriter(mz))
                {
                    int p = gcm(w, 8) / 8;
                    if (p == 0)
                    {
                        p = 1;
                    }
                    for (uint i = 0; i < w * h; i++)
                    {
                        uint x;
                        uint y;
                        d2xy(i % 64, out x, out y);

                        // Get Shift Tile
                        uint tile = i / 64;

                        // Shift Tile Coordinate into Tilemap
                        x += (uint)(tile % p) * 8;
                        y += (uint)(tile / p) * 8;

                        // Don't write data
                        Color c;
                        if (x >= img.Width || y >= img.Height)
                        {
                            c = Color.FromArgb(0, 0, 0, 0);
                        }
                        else
                        {
                            c = img.GetPixel((int)x, (int)y);
                        }

                        switch (format)
                        {
                        case RenderBase.OTextureFormat.l8: bz.Write(GetL8(c)); break;              // L8

                        case RenderBase.OTextureFormat.a8: bz.Write(GetA8(c)); break;              // A8

                        case RenderBase.OTextureFormat.la4: bz.Write(GetLA4(c)); break;            // LA4(4)

                        case RenderBase.OTextureFormat.la8: bz.Write(GetLA8(c)); break;            // LA8(8)

                        case RenderBase.OTextureFormat.hilo8: bz.Write(GetHILO8(c)); break;        // HILO8

                        case RenderBase.OTextureFormat.rgb565: bz.Write(GetRGB565(c)); break;      // RGB565

                        case RenderBase.OTextureFormat.rgba5551: bz.Write(GetRGBA5551(c)); break;  // RGBA5551

                        case RenderBase.OTextureFormat.rgba4: bz.Write(GetRGBA4444(c)); break;     // RGBA4444

                        case RenderBase.OTextureFormat.rgba8: bz.Write(GetRGBA8888(c)); break;     // RGBA8

                        case RenderBase.OTextureFormat.rgb8: bz.Write(GetRGB8(c)); break;          // RGB8

                        default: throw new Exception("Unsupport format.");
                        }
                    }
                    //while (mz.Length < nlpo2((int)mz.Length)) // pad
                    //    bz.Write((byte)0);
                    return(mz.ToArray());
                }
        }
Exemple #9
0
        /// <summary>
        ///     Encodes a PICA200 Texture.
        /// </summary>
        /// <param name="img">Input image to be encoded</param>
        /// <param name="format">Pixel Format of the Texture</param>
        /// <returns></returns>
        ///
        public static byte[] encode(Bitmap img, RenderBase.OTextureFormat format)
        {
            byte[] data         = TextureUtils.getArray(img);
            byte[] output       = new byte[data.Length];
            bool   toggle       = false;
            uint   outputOffset = 0;

            switch (format)
            {
            case RenderBase.OTextureFormat.rgba8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + ((tY * 8 + y) * img.Width)) * 4;

                            Buffer.BlockCopy(data, (int)dataOffset, output, (int)outputOffset + 1, 3);
                            output[outputOffset] = data[dataOffset + 3];

                            outputOffset += 4;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgb8:
            {
                output = new byte[img.Width * img.Height * 3];
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;
                            if (data[dataOffset + 3] != 0xFF)
                            {
                            }
                            Buffer.BlockCopy(data, (int)dataOffset, output, (int)outputOffset, 3);

                            outputOffset += 3;
                        }
                    }
                }
            }
            break;

            case RenderBase.OTextureFormat.rgba5551:
            {
                output = new byte[img.Width * img.Height * 2];
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int    x          = tileOrder[pixel] % 8;
                            int    y          = (tileOrder[pixel] - x) / 8;
                            long   dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;
                            int    r          = (data[dataOffset + 0] * 31 / 255);
                            int    g          = (data[dataOffset + 1] * 31 / 255);
                            int    b          = (data[dataOffset + 2] * 31 / 255);
                            int    a          = (data[dataOffset + 3] > 0 ? 1 : 0);
                            ushort rShift     = (ushort)(r << 1);
                            ushort gShift     = (ushort)(g << 6);
                            ushort bShift     = (ushort)(b << 11);
                            ushort t          = (ushort)(rShift | gShift | bShift | a);
                            output[outputOffset]     = (byte)(t);
                            output[outputOffset + 1] = (byte)(t >> 8);



                            outputOffset += 2;
                        }
                    }
                }
            }
            break;

            default: throw new NotImplementedException();
            }

            return(output);
        }
Exemple #10
0
        internal static Bitmap getIMG(byte[] data, int Width, int Height, RenderBase.OTextureFormat format, out int dataOffset)
        {
            dataOffset = 0;
            Bitmap img  = new Bitmap(Width, Height);
            int    area = img.Width * img.Height;
            // Tiles Per Width
            int p = gcm(img.Width, 8) / 8;

            if (p == 0)
            {
                p = 1;
            }
            using (Stream BitmapStream = new MemoryStream(data))
                using (BinaryReader br = new BinaryReader(BitmapStream))
                    for (uint i = 0; i < area; i++) // for every pixel
                    {
                        uint x;
                        uint y;
                        d2xy(i % 64, out x, out y);
                        uint tile = i / 64;

                        // Shift Tile Coordinate into Tilemap
                        x += (uint)(tile % p) * 8;
                        y += (uint)(tile / p) * 8;

                        // Get Color
                        Color c;
                        switch (format)
                        {
                        case RenderBase.OTextureFormat.l8:  // L8        // 8bit/1 byte
                        case RenderBase.OTextureFormat.a8:  // A8
                        case RenderBase.OTextureFormat.la4: // LA4
                            c = DecodeColor(br.ReadByte(), format);
                            break;

                        case RenderBase.OTextureFormat.la8:      // LA8       // 16bit/2 byte
                        case RenderBase.OTextureFormat.hilo8:    // HILO8
                        case RenderBase.OTextureFormat.rgb565:   // RGB565
                        case RenderBase.OTextureFormat.rgba4:    // RGBA4444
                        case RenderBase.OTextureFormat.rgba5551: // RGBA5551
                            c = DecodeColor(br.ReadUInt16(), format);
                            break;

                        case RenderBase.OTextureFormat.rgb8:  // RGB8:     // 24bit
                            byte[] data1 = br.ReadBytes(3); Array.Resize(ref data1, 4);
                            c = DecodeColor(BitConverter.ToUInt32(data1, 0), format);
                            break;

                        case RenderBase.OTextureFormat.rgba8:  // RGBA8888
                            c = DecodeColor(br.ReadUInt32(), format);
                            break;

                        case RenderBase.OTextureFormat.l4:                                // L4
                        case RenderBase.OTextureFormat.a4:                                // A4        // 4bit - Do 2 pixels at a time.
                            uint val = br.ReadByte();
                            img.SetPixel((int)x, (int)y, DecodeColor(val & 0xF, format)); // lowest bits for the low pixel
                            i++; x++;
                            c = DecodeColor(val >> 4, format);                            // highest bits for the high pixel
                            break;

                        default: throw new Exception("Invalid FileFormat.");
                        }
                        img.SetPixel((int)x, (int)y, c);
                        dataOffset = (int)br.BaseStream.Position;
                    }

            return(img);
        }
Exemple #11
0
        private loadedTexture loadPKM(FileStream data, BinaryReader input)
        {
            loadedTexture tex;

            tex.modified = false;
            long descAddress2 = data.Position;

            data.Seek(descAddress2 + 0x18, SeekOrigin.Begin);
            int texLength = input.ReadInt32();

            data.Seek(descAddress2 + 0x28, SeekOrigin.Begin);
            string textureName = IOUtils.readStringWithLength(input, 0x40);

            data.Seek(descAddress2 + 0x68, SeekOrigin.Begin);
            ushort width      = input.ReadUInt16();
            ushort height     = input.ReadUInt16();
            ushort texFormat  = input.ReadUInt16();
            ushort texMipMaps = input.ReadUInt16();

            data.Seek(0x10, SeekOrigin.Current);
            tex.offset = (uint)data.Position;
            byte[] texBuffer = input.ReadBytes(texLength);

            RenderBase.OTextureFormat fmt = RenderBase.OTextureFormat.dontCare;

            switch (texFormat)
            {
            case 0x2: fmt = RenderBase.OTextureFormat.rgb565; break;

            case 0x3: fmt = RenderBase.OTextureFormat.rgb8; break;

            case 0x4: fmt = RenderBase.OTextureFormat.rgba8; break;

            case 0x17: fmt = RenderBase.OTextureFormat.rgba5551; break;

            case 0x23: fmt = RenderBase.OTextureFormat.la8; break;

            case 0x24: fmt = RenderBase.OTextureFormat.hilo8; break;

            case 0x25: fmt = RenderBase.OTextureFormat.l8; break;

            case 0x26: fmt = RenderBase.OTextureFormat.a8; break;

            case 0x27: fmt = RenderBase.OTextureFormat.la4; break;

            case 0x28: fmt = RenderBase.OTextureFormat.l4; break;

            case 0x29: fmt = RenderBase.OTextureFormat.a4; break;

            case 0x2a: fmt = RenderBase.OTextureFormat.etc1; break;

            case 0x2b: fmt = RenderBase.OTextureFormat.etc1a4; break;
            }

            Bitmap texture = TextureCodec.decode(texBuffer, width, height, fmt);

            tex.texture              = new RenderBase.OTexture(texture, textureName);
            tex.type                 = fmt;
            tex.gpuCommandsOffset    = 0;
            tex.gpuCommandsWordCount = 0;
            tex.length               = texLength;
            return(tex);
        }
Exemple #12
0
        private bool open(string fileName)
        {
            using (FileStream data = new FileStream(fileName, FileMode.Open))
            {
                BinaryReader input = new BinaryReader(data);

                if (peek(input) == 0x00010000)
                {
                    currentFile = fileName;
                    bch         = new loadedBCH();
                    bch.isBCH   = false;
                    bch.mips.Add(new MIPlayer());
                    packPNK(data, input, bch);
                }
                if (peek(input) == 0x15041213)
                {
                    currentFile = fileName;
                    bch         = new loadedBCH();
                    bch.isBCH   = false;
                    bch.mips.Add(new MIPlayer());
                    bch.mips[0].textures.Add(loadPKM(data, input));
                }
                string magic2b = getMagic(input, 2);
                if (magic2b == "PC" || magic2b == "CM")
                {
                    bch         = new loadedBCH();
                    bch.isBCH   = false;
                    currentFile = fileName;
                    data.Seek(2, SeekOrigin.Current);
                    ushort numEntrys = input.ReadUInt16();
                    for (int i = 0; i < (int)numEntrys; i++)
                    {
                        data.Seek(4 + (i * 4), SeekOrigin.Begin);
                        uint offset = input.ReadUInt32();
                        uint end    = input.ReadUInt32();
                        uint lenth  = end - offset;
                        long rtn    = data.Position;
                        data.Seek(offset, SeekOrigin.Begin);
                        if (magic2b == "CM" & i == 0)
                        {
                            packPNK(data, input, bch);
                        }
                        if (lenth > 4)
                        {
                            if (magic2b == "PC")
                            {
                                if (peek(input) == 0x15041213)
                                {
                                    bch.mips[0].textures.Add(loadPKM(data, input));
                                }
                            }
                        }
                    }
                }
                string magic = IOUtils.readString(input, 0);
                if (magic == "BCH")
                {
                    currentFile = fileName;
                    data.Seek(4, SeekOrigin.Current);
                    byte   backwardCompatibility = input.ReadByte();
                    byte   forwardCompatibility  = input.ReadByte();
                    ushort version = input.ReadUInt16();

                    uint mainHeaderOffset      = input.ReadUInt32();
                    uint stringTableOffset     = input.ReadUInt32();
                    uint gpuCommandsOffset     = input.ReadUInt32();
                    uint dataOffset            = input.ReadUInt32();
                    uint dataExtendedOffset    = backwardCompatibility > 0x20 ? input.ReadUInt32() : 0;
                    uint relocationTableOffset = input.ReadUInt32();

                    uint mainHeaderLength      = input.ReadUInt32();
                    uint stringTableLength     = input.ReadUInt32();
                    uint gpuCommandsLength     = input.ReadUInt32();
                    uint dataLength            = input.ReadUInt32();
                    uint dataExtendedLength    = backwardCompatibility > 0x20 ? input.ReadUInt32() : 0;
                    uint relocationTableLength = input.ReadUInt32();

                    data.Seek(mainHeaderOffset, SeekOrigin.Begin);
                    uint modelsPointerTableOffset  = input.ReadUInt32() + mainHeaderOffset;
                    uint modelsPointerTableEntries = input.ReadUInt32();

                    data.Seek(mainHeaderOffset + 0x24, SeekOrigin.Begin);
                    uint texturesPointerTableOffset  = input.ReadUInt32() + mainHeaderOffset;
                    uint texturesPointerTableEntries = input.ReadUInt32();

                    bch       = new loadedBCH();
                    bch.isBCH = true;
                    for (int i = 0; i < 6; i++)
                    {
                        bch.mips.Add(new MIPlayer());
                    }
                    MipSelect.Enabled = true;

                    //Textures
                    for (int index = 0; index < texturesPointerTableEntries; index++)
                    {
                        data.Seek(texturesPointerTableOffset + (index * 4), SeekOrigin.Begin);
                        data.Seek(input.ReadUInt32() + mainHeaderOffset, SeekOrigin.Begin);

                        loadedTexture tex;
                        tex.modified             = false;
                        tex.gpuCommandsOffset    = input.ReadUInt32() + gpuCommandsOffset;
                        tex.gpuCommandsWordCount = input.ReadUInt32();
                        data.Seek(0x14, SeekOrigin.Current);
                        uint   textureNameOffset = input.ReadUInt32();
                        string textureName       = IOUtils.readString(input, textureNameOffset + stringTableOffset);

                        data.Seek(tex.gpuCommandsOffset, SeekOrigin.Begin);
                        PICACommandReader textureCommands = new PICACommandReader(data, tex.gpuCommandsWordCount);

                        tex.offset = textureCommands.getTexUnit0Address() + dataOffset;
                        RenderBase.OTextureFormat fmt = textureCommands.getTexUnit0Format();
                        Size textureSize = textureCommands.getTexUnit0Size();
                        tex.type = fmt;

                        int OGW = textureSize.Width;
                        int OGH = textureSize.Height;
                        for (int i = 0; i < 6; i++)
                        {
                            textureSize.Width  = OGW / Convert.ToInt32(Math.Pow(2, i));
                            textureSize.Height = OGH / Convert.ToInt32(Math.Pow(2, i));
                            tex.length         = returnSize(fmt, textureSize.Width, textureSize.Height);

                            if (textureSize.Height >= 8 & textureSize.Width >= 8)
                            {
                                data.Seek(tex.offset, SeekOrigin.Begin);
                                byte[] buffer = new byte[tex.length];

                                //data.Seek(tex.length + returnSize(fmt, textureSize.Width / 2, textureSize.Height / 2), SeekOrigin.Current);
                                tex.offset = (uint)data.Position;
                                input.Read(buffer, 0, tex.length);
                                Bitmap texture = TextureCodec.decode(
                                    buffer,
                                    textureSize.Width,
                                    textureSize.Height,
                                    fmt);

                                tex.texture = new RenderBase.OTexture(texture, textureName);

                                bch.mips[i].textures.Add(tex);
                                tex.offset = (uint)data.Position;
                            }
                        }
                    }

                    bch.mainHeaderOffset      = mainHeaderOffset;
                    bch.gpuCommandsOffset     = gpuCommandsOffset;
                    bch.dataOffset            = dataOffset;
                    bch.relocationTableOffset = relocationTableOffset;
                    bch.relocationTableLength = relocationTableLength;
                }
                else if (magic == "CTPK\u0001")
                {
                    currentFile = fileName;
                    data.Seek(4, SeekOrigin.Current);
                    ushort ver                  = input.ReadUInt16();
                    ushort numTexture           = input.ReadUInt16();
                    uint   TextureSectionOffset = input.ReadUInt32();
                    uint   TextureSectionSize   = input.ReadUInt32();
                    uint   HashSectionOffset    = input.ReadUInt32();
                    uint   TextureInfoSection   = input.ReadUInt32();

                    bch       = new loadedBCH();
                    bch.isBCH = false;
                    bch.mips.Add(new MIPlayer());
                    for (int i = 0; i < numTexture; i++)
                    {
                        data.Seek(0x20 * (i + 1), SeekOrigin.Begin);
                        loadedTexture tex;
                        tex.modified          = false;
                        tex.gpuCommandsOffset = (uint)(0x20 * (i + 1));
                        uint   textureNameOffset = input.ReadUInt32();
                        string textureName       = IOUtils.readString(input, textureNameOffset);
                        tex.length = input.ReadInt32();
                        tex.offset = input.ReadUInt32() + TextureSectionOffset;
                        tex.type   = (RenderBase.OTextureFormat)input.ReadUInt32();
                        ushort Width  = input.ReadUInt16();
                        ushort Height = input.ReadUInt16();
                        data.Seek(tex.offset, SeekOrigin.Begin);
                        byte[] buffer = new byte[tex.length];

                        input.Read(buffer, 0, buffer.Length);
                        Bitmap texture = TextureCodec.decode(
                            buffer,
                            Width,
                            Height,
                            tex.type);

                        tex.texture = new RenderBase.OTexture(texture, textureName);

                        tex.gpuCommandsWordCount = 0;

                        bch.mips[0].textures.Add(tex);
                    }
                }
            }

            updateTexturesList();
            return(true);
        }
Exemple #13
0
        /// <summary>
        ///     Encodes a PICA200 Texture.
        /// </summary>
        /// <param name="img">Input image to be encoded</param>
        /// <param name="format">Pixel Format of the Texture</param>
        /// <returns></returns>
        public static byte[] encode(Bitmap img, RenderBase.OTextureFormat format)
        {
            byte[] data         = TextureUtils.getArray(img);
            byte[] output       = new byte[data.Length];
            bool   toggle       = false;
            uint   outputOffset = 0;

            switch (format)
            {
            case RenderBase.OTextureFormat.rgba8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + ((tY * 8 + y) * img.Width)) * 4;
                            byte b          = (byte)(data[dataOffset]);
                            byte g          = (byte)(data[dataOffset + 1]);
                            byte r          = (byte)(data[dataOffset + 2]);
                            output[outputOffset + 1] = b;
                            output[outputOffset + 2] = g;
                            output[outputOffset + 3] = r;
                            output[outputOffset]     = data[dataOffset + 3];

                            outputOffset += 4;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgb8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + ((tY * 8 + y) * img.Width)) * 4;
                            byte b          = (byte)(data[dataOffset]);
                            byte g          = (byte)(data[dataOffset + 1]);
                            byte r          = (byte)(data[dataOffset + 2]);
                            output[outputOffset]     = b;
                            output[outputOffset + 1] = g;
                            output[outputOffset + 2] = r;

                            outputOffset += 3;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgba5551:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            ulong pixelData = (ulong)(data[dataOffset]);

                            byte b = (byte)(data[dataOffset]);
                            byte g = (byte)(data[dataOffset + 1]);
                            byte r = (byte)(data[dataOffset + 2]);
                            byte a = (byte)(data[dataOffset + 3]);

                            output[outputOffset]     = (byte)((((g >> 3) & 3) << 6) + ((b >> 3) << 1) + (a & 1));
                            output[outputOffset + 1] = (byte)(((r >> 3) << 3) + (g >> 5));

                            outputOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgb565:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            byte b = (byte)(data[dataOffset] / 8);
                            byte g = (byte)(data[dataOffset + 1] / 4);
                            byte r = (byte)(data[dataOffset + 2] / 8);

                            output[outputOffset]     = (byte)(((g & 7) << 5) | b);
                            output[outputOffset + 1] = (byte)((r << 3) | ((g & 0x38) >> 3));

                            outputOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgba4:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            byte b = (byte)(data[dataOffset] / 16);
                            byte g = (byte)(data[dataOffset + 1] / 16);
                            byte r = (byte)(data[dataOffset + 2] / 16);
                            byte a = (byte)(data[dataOffset + 3] / 16);

                            output[outputOffset + 1] = (byte)((r << 4) | g);
                            output[outputOffset]     = (byte)((b << 4) | a);

                            outputOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.la8:
            case RenderBase.OTextureFormat.hilo8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            output[outputOffset]     = data[dataOffset];
                            output[outputOffset + 1] = data[dataOffset + 3];

                            outputOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.l8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            output[outputOffset] = data[dataOffset];

                            outputOffset++;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.a8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            output[outputOffset] = data[dataOffset + 3];

                            outputOffset++;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.la4:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            output[outputOffset] = (byte)((data[dataOffset] / 16) << 4 | data[dataOffset + 3] / 16);

                            outputOffset++;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.l4:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;


                            byte c         = (byte)(data[dataOffset++] >> 4);
                            byte wholeByte = 0;
                            if (toggle)
                            {
                                wholeByte            = (byte)((wholeByte << 4) | (data[dataOffset++] >> 4));
                                output[outputOffset] = wholeByte;
                                outputOffset++;
                            }
                            else
                            {
                                wholeByte = c;
                            }
                            toggle = !toggle;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.a4:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            byte c         = (byte)(data[dataOffset + 3] >> 4);
                            byte wholeByte = 0;
                            if (toggle)
                            {
                                wholeByte            = (byte)((wholeByte << 4) | (data[dataOffset++] >> 4));
                                output[outputOffset] = wholeByte;
                                outputOffset++;
                            }
                            else
                            {
                                wholeByte = c;
                            }
                            toggle = !toggle;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.etc1:
            case RenderBase.OTextureFormat.etc1a4:
                int[] etc1Order = etc1Scramble(img.Width, img.Height);

                int i = 0;
                for (int tY = 0; tY < img.Height / 4; tY++)
                {
                    for (int tX = 0; tX < img.Width / 4; tX++)
                    {
                        int TX = etc1Order[i] % (img.Width / 4);
                        int TY = (etc1Order[i] - TX) / (img.Width / 4);
                        outputOffset = (uint)((TX * 4) + (((TY * 4)) * (img.Width / 4))) * 2;
                        if (format == RenderBase.OTextureFormat.etc1a4)
                        {
                            outputOffset = (uint)((TX * 4) + (((TY * 4)) * (img.Width / 4))) * 4;
                            ulong alpha = 0;
                            int   iiii  = 0;
                            for (int x = 0; x < 4; x++)
                            {
                                for (int y = 0; y < 4; y++)
                                {
                                    long dataOffset = ((tX * 4) + (x) + (((tY * 4) + (y)) * img.Width)) * 4;
                                    uint a          = (uint)data[dataOffset + 3] / 16;
                                    alpha |= (ulong)a << (iiii);
                                    iiii  += 4;
                                }
                            }
                            output[outputOffset + 7] = (byte)((alpha >> 56) & 0xFF);
                            output[outputOffset + 6] = (byte)((alpha >> 48) & 0xFF);
                            output[outputOffset + 5] = (byte)((alpha >> 40) & 0xFF);
                            output[outputOffset + 4] = (byte)((alpha >> 32) & 0xFF);
                            output[outputOffset + 3] = (byte)((alpha >> 24) & 0xFF);
                            output[outputOffset + 2] = (byte)((alpha >> 16) & 0xFF);
                            output[outputOffset + 1] = (byte)((alpha >> 8) & 0xFF);
                            output[outputOffset]     = (byte)(alpha & 0xFF);
                            outputOffset            += 8;
                        }
                        Color[] pixels = new Color[4 * 4];
                        for (int yy = 0; yy < 4; yy++)
                        {
                            for (int xx = 0; xx < 4; xx++)
                            {
                                long dataOffset = ((tX * 4) + (xx) + (((tY * 4) + (yy)) * img.Width)) * 4;
                                //if (TX + xx >= img.Width) pixels[yy * 4 + xx] = Color.Transparent;
                                //else if (TY + yy >= img.Height) pixels[yy * 4 + xx] = Color.Transparent;
                                pixels[yy * 4 + xx] = Color.FromArgb((int)data[dataOffset + 0] | (int)data[dataOffset + 1] << 8 | (int)data[dataOffset + 2] << 16 | (int)data[dataOffset + 3] << 24);
                            }
                        }
                        ulong ETC1Chunk = ETC1.GenETC1(pixels);
                        output[outputOffset + 7] = (byte)((ETC1Chunk >> 56) & 0xFF);
                        output[outputOffset + 6] = (byte)((ETC1Chunk >> 48) & 0xFF);
                        output[outputOffset + 5] = (byte)((ETC1Chunk >> 40) & 0xFF);
                        output[outputOffset + 4] = (byte)((ETC1Chunk >> 32) & 0xFF);
                        output[outputOffset + 3] = (byte)((ETC1Chunk >> 24) & 0xFF);
                        output[outputOffset + 2] = (byte)((ETC1Chunk >> 16) & 0xFF);
                        output[outputOffset + 1] = (byte)((ETC1Chunk >> 8) & 0xFF);
                        output[outputOffset + 0] = (byte)(ETC1Chunk & 0xFF);
                        outputOffset            += 8;
                        i += 1;
                    }
                }


                break;

            default: throw new NotImplementedException();
            }

            return(output);
        }
        /// <summary>
        ///     Loads a Game freak texture.
        /// </summary>
        /// <param name="data">The texture data</param>
        /// <returns>The image as a texture</returns>
        public static Ohana3DS_Transfigured.Ohana.RenderBase.OTexture load(Stream data, bool keepOpen = false)
        {
            BinaryReader input       = new BinaryReader(data);
            long         descAddress = data.Position;

            data.Seek(8, SeekOrigin.Current);
            if (Ohana3DS_Transfigured.Ohana.IOUtils.readStringWithLength(input, 7) != "texture")
            {
                return(null);
            }

            data.Seek(descAddress + 0x18, SeekOrigin.Begin);
            int texLength = input.ReadInt32();

            data.Seek(descAddress + 0x28, SeekOrigin.Begin);
            string texName = IOUtils.readStringWithLength(input, 0x40);

            data.Seek(descAddress + 0x68, SeekOrigin.Begin);
            ushort width      = input.ReadUInt16();
            ushort height     = input.ReadUInt16();
            ushort texFormat  = input.ReadUInt16();
            ushort texMipMaps = input.ReadUInt16();

            data.Seek(0x10, SeekOrigin.Current);
            byte[] texBuffer = input.ReadBytes(texLength);

            RenderBase.OTextureFormat fmt = RenderBase.OTextureFormat.dontCare;

            switch (texFormat)
            {
            case 0x2: fmt = RenderBase.OTextureFormat.rgb565; break;

            case 0x3: fmt = RenderBase.OTextureFormat.rgb8; break;

            case 0x4: fmt = RenderBase.OTextureFormat.rgba8; break;

            case 0x16: fmt = RenderBase.OTextureFormat.rgba4; break;

            case 0x17: fmt = RenderBase.OTextureFormat.rgba5551; break;

            case 0x23: fmt = RenderBase.OTextureFormat.la8; break;

            case 0x24: fmt = RenderBase.OTextureFormat.hilo8; break;

            case 0x25: fmt = RenderBase.OTextureFormat.l8; break;

            case 0x26: fmt = RenderBase.OTextureFormat.a8; break;

            case 0x27: fmt = RenderBase.OTextureFormat.la4; break;

            case 0x28: fmt = RenderBase.OTextureFormat.l4; break;

            case 0x29: fmt = RenderBase.OTextureFormat.a4; break;

            case 0x2a: fmt = RenderBase.OTextureFormat.etc1; break;

            case 0x2b: fmt = RenderBase.OTextureFormat.etc1a4; break;

            default: Debug.WriteLine("Unk tex fmt " + texFormat.ToString("X4") + " @ " + texName); break;
            }

            Bitmap tex = TextureCodec.decode(texBuffer, width, height, fmt);

            if (!keepOpen)
            {
                data.Close();
            }

            return(new RenderBase.OTexture(tex, texName));
        }
Exemple #15
0
        private bool open(string fileName)
        {
            using (FileStream data = new FileStream(fileName, FileMode.Open))
            {
                BinaryReader input = new BinaryReader(data);

                string magic = IOUtils.readString(input, 0);
                if (magic != "BCH")
                {
                    return(false);
                }
                currentFile = fileName;
                data.Seek(4, SeekOrigin.Current);
                byte   backwardCompatibility = input.ReadByte();
                byte   forwardCompatibility  = input.ReadByte();
                ushort version = input.ReadUInt16();

                uint mainHeaderOffset      = input.ReadUInt32();
                uint stringTableOffset     = input.ReadUInt32();
                uint gpuCommandsOffset     = input.ReadUInt32();
                uint dataOffset            = input.ReadUInt32();
                uint dataExtendedOffset    = backwardCompatibility > 0x20 ? input.ReadUInt32() : 0;
                uint relocationTableOffset = input.ReadUInt32();

                uint mainHeaderLength      = input.ReadUInt32();
                uint stringTableLength     = input.ReadUInt32();
                uint gpuCommandsLength     = input.ReadUInt32();
                uint dataLength            = input.ReadUInt32();
                uint dataExtendedLength    = backwardCompatibility > 0x20 ? input.ReadUInt32() : 0;
                uint relocationTableLength = input.ReadUInt32();

                data.Seek(mainHeaderOffset, SeekOrigin.Begin);
                uint modelsPointerTableOffset  = input.ReadUInt32() + mainHeaderOffset;
                uint modelsPointerTableEntries = input.ReadUInt32();

                data.Seek(mainHeaderOffset + 0x24, SeekOrigin.Begin);
                uint texturesPointerTableOffset  = input.ReadUInt32() + mainHeaderOffset;
                uint texturesPointerTableEntries = input.ReadUInt32();

                bch = new loadedBCH();

                //Textures
                for (int index = 0; index < texturesPointerTableEntries; index++)
                {
                    data.Seek(texturesPointerTableOffset + (index * 4), SeekOrigin.Begin);
                    data.Seek(input.ReadUInt32() + mainHeaderOffset, SeekOrigin.Begin);

                    loadedTexture tex;
                    tex.modified             = false;
                    tex.gpuCommandsOffset    = input.ReadUInt32() + gpuCommandsOffset;
                    tex.gpuCommandsWordCount = input.ReadUInt32();
                    data.Seek(0x14, SeekOrigin.Current);
                    uint   textureNameOffset = input.ReadUInt32();
                    string textureName       = IOUtils.readString(input, textureNameOffset + stringTableOffset);

                    data.Seek(tex.gpuCommandsOffset, SeekOrigin.Begin);
                    PICACommandReader textureCommands = new PICACommandReader(data, tex.gpuCommandsWordCount);

                    tex.offset = textureCommands.getTexUnit0Address() + dataOffset;
                    RenderBase.OTextureFormat fmt = textureCommands.getTexUnit0Format();
                    Size textureSize = textureCommands.getTexUnit0Size();
                    switch (fmt)
                    {
                    case RenderBase.OTextureFormat.rgba8: tex.length = (textureSize.Width * textureSize.Height) * 4; break;

                    case RenderBase.OTextureFormat.rgb8: tex.length = (textureSize.Width * textureSize.Height) * 3; break;

                    case RenderBase.OTextureFormat.rgba5551: tex.length = (textureSize.Width * textureSize.Height) * 2; break;

                    case RenderBase.OTextureFormat.rgb565: tex.length = (textureSize.Width * textureSize.Height) * 2; break;

                    case RenderBase.OTextureFormat.rgba4: tex.length = (textureSize.Width * textureSize.Height) * 2; break;

                    case RenderBase.OTextureFormat.la8: tex.length = (textureSize.Width * textureSize.Height) * 2; break;

                    case RenderBase.OTextureFormat.hilo8: tex.length = (textureSize.Width * textureSize.Height) * 2; break;

                    case RenderBase.OTextureFormat.l8: tex.length = textureSize.Width * textureSize.Height; break;

                    case RenderBase.OTextureFormat.a8: tex.length = textureSize.Width * textureSize.Height; break;

                    case RenderBase.OTextureFormat.la4: tex.length = textureSize.Width * textureSize.Height; break;

                    case RenderBase.OTextureFormat.l4: tex.length = (textureSize.Width * textureSize.Height) >> 1; break;

                    case RenderBase.OTextureFormat.a4: tex.length = (textureSize.Width * textureSize.Height) >> 1; break;

                    case RenderBase.OTextureFormat.etc1: tex.length = (textureSize.Width * textureSize.Height) >> 1; break;

                    case RenderBase.OTextureFormat.etc1a4: tex.length = textureSize.Width * textureSize.Height; break;

                    default: throw new Exception("OBCHTextureReplacer: Invalid texture format on BCH!");
                    }

                    while ((tex.length & 0x7f) > 0)
                    {
                        tex.length++;
                    }

                    data.Seek(tex.offset, SeekOrigin.Begin);
                    byte[] buffer = new byte[textureSize.Width * textureSize.Height * 4];
                    input.Read(buffer, 0, buffer.Length);
                    Bitmap texture = TextureCodec.decode(
                        buffer,
                        textureSize.Width,
                        textureSize.Height,
                        fmt);

                    tex.texture = new RenderBase.OTexture(texture, textureName);

                    bch.textures.Add(tex);
                }

                //Materials
                for (int mdlIndex = 0; mdlIndex < modelsPointerTableEntries; mdlIndex++)
                {
                    data.Seek(modelsPointerTableOffset + (mdlIndex * 4), SeekOrigin.Begin);
                    data.Seek(input.ReadUInt32() + mainHeaderOffset, SeekOrigin.Begin);
                    data.Seek(0x34, SeekOrigin.Current);

                    uint materialsTableOffset  = input.ReadUInt32() + mainHeaderOffset;
                    uint materialsTableEntries = input.ReadUInt32();

                    for (int index = 0; index < materialsTableEntries; index++)
                    {
                        if (backwardCompatibility < 0x21)
                        {
                            data.Seek(materialsTableOffset + (index * 0x58), SeekOrigin.Begin);
                        }
                        else
                        {
                            data.Seek(materialsTableOffset + (index * 0x2c), SeekOrigin.Begin);
                        }

                        loadedMaterial mat;

                        data.Seek(0x10, SeekOrigin.Current);
                        mat.gpuCommandsOffset    = input.ReadUInt32() + gpuCommandsOffset;
                        mat.gpuCommandsWordCount = input.ReadUInt32();

                        if (backwardCompatibility < 0x21)
                        {
                            data.Seek(0x30, SeekOrigin.Current);
                        }
                        else
                        {
                            data.Seek(4, SeekOrigin.Current);
                        }

                        uint texture0Offset = input.ReadUInt32() + stringTableOffset;
                        uint texture1Offset = input.ReadUInt32() + stringTableOffset;
                        uint texture2Offset = input.ReadUInt32() + stringTableOffset;

                        mat.texture0 = IOUtils.readString(input, texture0Offset);
                        mat.texture1 = IOUtils.readString(input, texture1Offset);
                        mat.texture2 = IOUtils.readString(input, texture2Offset);

                        bch.materials.Add(mat);
                    }
                }

                bch.mainHeaderOffset      = mainHeaderOffset;
                bch.gpuCommandsOffset     = gpuCommandsOffset;
                bch.dataOffset            = dataOffset;
                bch.relocationTableOffset = relocationTableOffset;
                bch.relocationTableLength = relocationTableLength;
            }

            updateTexturesList();
            return(true);
        }