Esempio n. 1
0
        public byte[] DecodeImage(STGenericTexture texture, byte[] data, uint width, uint height, int array, int mip)
        {
            uint bpp = TextureFormatHelper.GetBytesPerPixel(OutputFormat);

            GX2.GX2Surface surf = new GX2.GX2Surface();
            surf.bpp       = bpp;
            surf.height    = texture.Height;
            surf.width     = texture.Width;
            surf.depth     = texture.ArrayCount;
            surf.alignment = Alignment;
            surf.aa        = (uint)AAMode;
            surf.dim       = (uint)SurfaceDimension;
            surf.format    = (uint)Format;
            surf.use       = (uint)SurfaceUse;
            surf.pitch     = Pitch;
            surf.data      = data;
            surf.mipData   = MipData != null ? MipData : data;
            surf.mipOffset = MipOffsets != null ? MipOffsets : new uint[0];
            surf.numMips   = texture.MipCount;
            surf.numArray  = texture.ArrayCount;
            surf.tileMode  = (uint)TileMode;
            surf.swizzle   = Swizzle;

            Console.WriteLine("WII U DECODE");

            return(GX2.Decode(surf, array, mip));
        }
        //Method from https://github.com/aboood40091/BNTX-Editor/blob/master/formConv.py
        public bool Decode(TexFormat format, byte[] input, int width, int height, out byte[] output)
        {
            if (!IsSupported(format))
            {
                output = null;
                return(false);
            }

            uint bpp  = TextureFormatHelper.GetBytesPerPixel(format);
            int  size = width * height * 4;

            bpp = (uint)(input.Length / (width * height));

            output = new byte[size];

            int inPos  = 0;
            int outPos = 0;

            byte[] comp    = new byte[] { 0, 0, 0, 0xFF, 0, 0xFF };
            byte[] compSel = new byte[4] {
                0, 1, 2, 3
            };

            if (format == TexFormat.LA8)
            {
                compSel = new byte[4] {
                    0, 0, 0, 1
                };
                bpp = 2;
            }
            else if (format == TexFormat.L8)
            {
                compSel = new byte[4] {
                    0, 0, 0, 5
                }
            }
            ;

            for (int Y = 0; Y < height; Y++)
            {
                for (int X = 0; X < width; X++)
                {
                    inPos  = (Y * width + X) * (int)bpp;
                    outPos = (Y * width + X) * 4;

                    int pixel = 0;
                    for (int i = 0; i < bpp; i++)
                    {
                        pixel |= input[inPos + i] << (8 * i);
                    }

                    comp = GetComponentsFromPixel(format, pixel, comp);

                    output[outPos + 3] = comp[compSel[3]];
                    output[outPos + 2] = comp[compSel[2]];
                    output[outPos + 1] = comp[compSel[1]];
                    output[outPos + 0] = comp[compSel[0]];
                }
            }

            return(output != null);
        }
Esempio n. 3
0
        public static byte[] GetImageData(STGenericTexture texture, byte[] ImageData, int ArrayLevel, int MipLevel, int DepthLevel, uint BlockHeightLog2, int target = 1, bool LinearTileMode = false)
        {
            var  format      = texture.Platform.OutputFormat;
            uint bpp         = TextureFormatHelper.GetBytesPerPixel(format);
            uint blkWidth    = texture.GetBlockWidth();
            uint blkHeight   = texture.GetBlockHeight();
            uint blkDepth    = texture.GetBlockDepth();
            uint blockHeight = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(texture.Height, blkHeight));

            Console.WriteLine($"format {format} {bpp} {blkWidth} {blkHeight} {blockHeight}");
            Console.WriteLine($"ArrayLevel {ArrayLevel} {MipLevel} {DepthLevel} {BlockHeightLog2}");

            uint Pitch         = 0;
            uint DataAlignment = 512;
            uint TileMode      = 0;

            if (LinearTileMode)
            {
                TileMode = 1;
            }
            uint numDepth = 1;

            if (texture.Depth > 1)
            {
                numDepth = texture.Depth;
            }

            int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;

            uint ArrayOffset = 0;

            for (int depthLevel = 0; depthLevel < numDepth; depthLevel++)
            {
                for (int arrayLevel = 0; arrayLevel < texture.ArrayCount; arrayLevel++)
                {
                    uint SurfaceSize      = 0;
                    int  blockHeightShift = 0;

                    List <uint> MipOffsets = new List <uint>();

                    for (int mipLevel = 0; mipLevel < texture.MipCount; mipLevel++)
                    {
                        uint width  = (uint)Math.Max(1, texture.Width >> mipLevel);
                        uint height = (uint)Math.Max(1, texture.Height >> mipLevel);
                        uint depth  = (uint)Math.Max(1, texture.Depth >> mipLevel);

                        uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;

                        Console.WriteLine($"size " + size);

                        if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
                        {
                            blockHeightShift += 1;
                        }


                        uint width__  = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth);
                        uint height__ = TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight);

                        //Calculate the mip size instead
                        byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, DataAlignment) - SurfaceSize)];
                        SurfaceSize += (uint)AlignedData.Length;
                        MipOffsets.Add(SurfaceSize);

                        //Get the first mip offset and current one and the total image size
                        int msize = (int)((MipOffsets[0] + ImageData.Length - MipOffsets[mipLevel]) / texture.ArrayCount);

                        byte[] data_ = ByteUtils.SubArray(ImageData, ArrayOffset + MipOffsets[mipLevel], (uint)msize);

                        try
                        {
                            Pitch        = TegraX1Swizzle.round_up(width__ * bpp, 64);
                            SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);

                            byte[] result = TegraX1Swizzle.deswizzle(width, height, depth, blkWidth, blkHeight, blkDepth, target, bpp, TileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), data_);
                            //Create a copy and use that to remove uneeded data
                            byte[] result_ = new byte[size];
                            Array.Copy(result, 0, result_, 0, size);
                            result = null;

                            if (ArrayLevel == arrayLevel && MipLevel == mipLevel && DepthLevel == depthLevel)
                            {
                                return(result_);
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"Failed to swizzle texture {texture.Name}!");
                            Console.WriteLine(e);

                            return(new byte[0]);
                        }
                    }
                    ArrayOffset += (uint)(ImageData.Length / texture.ArrayCount);
                }
            }
            return(new byte[0]);
        }
        public static List <uint[]> GenerateMipSizes(TexFormat Format, uint Width, uint Height, uint Depth, uint SurfaceCount, uint MipCount, uint ImageSize)
        {
            List <uint[]> MipMapSizes = new List <uint[]>();

            uint bpp       = TextureFormatHelper.GetBytesPerPixel(Format);
            uint blkWidth  = TextureFormatHelper.GetBlockWidth(Format);
            uint blkHeight = TextureFormatHelper.GetBlockHeight(Format);
            uint blkDepth  = TextureFormatHelper.GetBlockDepth(Format);

            uint blockHeight     = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(Height, blkHeight));
            uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;

            uint Pitch         = 0;
            uint DataAlignment = 512;

            int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;

            uint ArrayCount = SurfaceCount;

            uint ArrayOffset = 0;

            for (int arrayLevel = 0; arrayLevel < ArrayCount; arrayLevel++)
            {
                uint SurfaceSize      = 0;
                int  blockHeightShift = 0;

                uint[] MipOffsets = new uint[MipCount];

                for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
                {
                    uint width  = (uint)Math.Max(1, Width >> mipLevel);
                    uint height = (uint)Math.Max(1, Height >> mipLevel);
                    uint depth  = (uint)Math.Max(1, Depth >> mipLevel);

                    uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;

                    if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }

                    uint width__  = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth);
                    uint height__ = TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight);

                    //Calculate the mip size instead
                    byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, DataAlignment) - SurfaceSize)];
                    SurfaceSize         += (uint)AlignedData.Length;
                    MipOffsets[mipLevel] = (SurfaceSize);

                    //Get the first mip offset and current one and the total image size
                    int msize = (int)((MipOffsets[0] + ImageSize - MipOffsets[mipLevel]) / ArrayCount);

                    Pitch        = TegraX1Swizzle.round_up(width__ * bpp, 64);
                    SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);
                }
                ArrayOffset += (uint)(ImageSize / ArrayCount);

                MipMapSizes.Add(MipOffsets);
            }

            return(MipMapSizes);
        }