Ejemplo n.º 1
0
        public static byte[] Decompress(byte[] Input, int Width, int Height, bool Alpha)
        {
            byte[] Output = new byte[Width * Height * 4];

            byte[] comp = new byte[4] {
                0xFF, 0xFF, 0xFF, 0xFF
            };

            int bpp = (int)STGenericTexture.GetBytesPerPixel(TEX_FORMAT.R4G4_UNORM);

            for (int Y = 0; Y < Height; Y++)
            {
                for (int X = 0; X < Width; X++)
                {
                    int InputOffset  = (Y * Width + X) * bpp;
                    int OutputOffset = (Y * Width + X) * 4;

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

                    comp[0] = (byte)((pixel & 0xF) * 17);
                    comp[1] = (byte)(((pixel & 0xF0) >> 4) * 17);

                    Output[OutputOffset + 0] = comp[0];
                    Output[OutputOffset + 1] = comp[1];
                    Output[OutputOffset + 2] = comp[2];
                    Output[OutputOffset + 3] = comp[3];
                }
            }

            return(Output);
        }
Ejemplo n.º 2
0
        //Method from https://github.com/aboood40091/BNTX-Editor/blob/master/formConv.py
        public static byte[] Decode(byte[] data, int width, int height, TEX_FORMAT format)
        {
            uint bpp  = STGenericTexture.GetBytesPerPixel(format);
            int  size = width * height * 4;

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

            byte[] 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 == TEX_FORMAT.LA8)
            {
                compSel = new byte[4] {
                    0, 0, 0, 1
                };
                bpp = 2;
            }
            else if (format == TEX_FORMAT.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 |= data[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);
        }
    }
Ejemplo n.º 3
0
        public static List <uint[]> GenerateMipSizes(TEX_FORMAT Format, uint Width, uint Height, uint Depth, uint SurfaceCount, uint MipCount, uint ImageSize)
        {
            List <uint[]> MipMapSizes = new List <uint[]>();

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

            uint blockHeight     = GetBlockHeight(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 = DIV_ROUND_UP(width, blkWidth) * DIV_ROUND_UP(height, blkHeight) * bpp;
                    MipOffsets[mipLevel] = size;
                }
                ArrayOffset += (uint)(ImageSize / ArrayCount);

                MipMapSizes.Add(MipOffsets);
            }

            return(MipMapSizes);
        }
Ejemplo n.º 4
0
        public static byte[] GetImageData(STGenericTexture texture, byte[] ImageData, int ArrayLevel, int MipLevel, int DepthLevel, uint BlockHeightLog2, int target = 1, bool LinearTileMode = false)
        {
            uint bpp         = STGenericTexture.GetBytesPerPixel(texture.Format);
            uint blkWidth    = STGenericTexture.GetBlockWidth(texture.Format);
            uint blkHeight   = STGenericTexture.GetBlockHeight(texture.Format);
            uint blkDepth    = STGenericTexture.GetBlockDepth(texture.Format);
            uint blockHeight = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(texture.Height, blkHeight));

            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_ = Utils.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)
                        {
                            System.Windows.Forms.MessageBox.Show($"Failed to swizzle texture {texture.Text}!");
                            Console.WriteLine(e);

                            return(new byte[0]);
                        }
                    }
                    ArrayOffset += (uint)(ImageData.Length / texture.ArrayCount);
                }
            }
            return(new byte[0]);
        }
Ejemplo n.º 5
0
        public static byte[] GetImageData(STGenericTexture texture, byte[] ImageData, int ArrayLevel, int MipLevel, int DepthLevel, uint BlockHeightLog2, int target = 1, bool LinearTileMode = false)
        {
            uint bpp       = STGenericTexture.GetBytesPerPixel(texture.Format);
            uint blkWidth  = STGenericTexture.GetBlockWidth(texture.Format);
            uint blkHeight = STGenericTexture.GetBlockHeight(texture.Format);
            uint blkDepth  = STGenericTexture.GetBlockDepth(texture.Format);

            uint TileMode = 0;

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

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

            var blockHeightMip0 = GetBlockHeight(DIV_ROUND_UP(texture.Height, blkHeight));

            uint arrayOffset = 0;

            // TODO: Why is depth done like this?
            for (int depthLevel = 0; depthLevel < numDepth; depthLevel++)
            {
                for (int arrayLevel = 0; arrayLevel < texture.ArrayCount; arrayLevel++)
                {
                    var mipOffset = 0u;

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

                        uint widthInBlocks  = DIV_ROUND_UP(width, blkWidth);
                        uint heightInBlocks = DIV_ROUND_UP(height, blkHeight);
                        uint depthInBlocks  = DIV_ROUND_UP(depth, blkDepth);

                        // tegra_swizzle only allows block heights supported by the TRM (1,2,4,8,16,32).
                        var mipBlockHeightLog2 = (int)Math.Log(GetMipBlockHeight(heightInBlocks, blockHeightMip0), 2);
                        var mipBlockHeight     = 1 << Math.Max(Math.Min(mipBlockHeightLog2, 5), 0);

                        uint mipSize;
                        if (Environment.Is64BitProcess)
                        {
                            mipSize = (uint)GetSurfaceSizeX64(widthInBlocks, heightInBlocks, depthInBlocks, (ulong)mipBlockHeight, bpp);
                        }
                        else
                        {
                            mipSize = (uint)GetSurfaceSizeX86(widthInBlocks, heightInBlocks, depthInBlocks, (uint)mipBlockHeight, bpp);
                        }

                        // TODO: Avoid this copy.
                        byte[] mipData = Utils.SubArray(ImageData, arrayOffset + mipOffset, mipSize);

                        try
                        {
                            if (ArrayLevel == arrayLevel && MipLevel == mipLevel && DepthLevel == depthLevel)
                            {
                                // The set of swizzled addresses is at least as big as the set of linear addresses.
                                // When defined appropriately, we only require a single memory allocation for the output.
                                byte[] result = deswizzle(width, height, depth, blkWidth, blkHeight, blkDepth, target, bpp, TileMode, mipBlockHeightLog2, mipData);
                                return(result);
                            }
                        }
                        catch (Exception e)
                        {
                            System.Windows.Forms.MessageBox.Show($"Failed to swizzle texture {texture.Text}!");
                            Console.WriteLine(e);

                            return(new byte[0]);
                        }

                        mipOffset += mipSize;
                    }

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

            uint bpp       = STGenericTexture.GetBytesPerPixel(Format);
            uint blkWidth  = STGenericTexture.GetBlockWidth(Format);
            uint blkHeight = STGenericTexture.GetBlockHeight(Format);
            uint blkDepth  = STGenericTexture.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);
        }
Ejemplo n.º 7
0
        public static List <byte[]> SwizzleSurfaceMipMaps(Texture tex, byte[] data, uint MipCount)
        {
            var TexFormat = TextureData.ConvertFormat(tex.Format);

            int  blockHeightShift = 0;
            int  target           = 1;
            uint Pitch            = 0;
            uint SurfaceSize      = 0;
            uint blockHeight      = 0;
            uint blkWidth         = STGenericTexture.GetBlockWidth(TexFormat);
            uint blkHeight        = STGenericTexture.GetBlockHeight(TexFormat);
            uint blkDepth         = STGenericTexture.GetBlockDepth(TexFormat);

            uint bpp = STGenericTexture.GetBytesPerPixel(TexFormat);

            uint linesPerBlockHeight = 0;

            if (tex.TileMode == TileMode.LinearAligned)
            {
                blockHeight         = 1;
                tex.BlockHeightLog2 = 0;
                tex.Alignment       = 1;

                linesPerBlockHeight   = 1;
                tex.ReadTextureLayout = 0;
            }
            else
            {
                blockHeight           = TegraX1Swizzle.GetBlockHeight(DIV_ROUND_UP(tex.Height, blkHeight));
                tex.BlockHeightLog2   = (uint)Convert.ToString(blockHeight, 2).Length - 1;
                tex.Alignment         = 512;
                tex.ReadTextureLayout = 1;

                linesPerBlockHeight = blockHeight * 8;
            }

            List <byte[]> mipmaps = new List <byte[]>();

            for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
            {
                var  result = TextureHelper.GetCurrentMipSize(tex.Width, tex.Height, blkWidth, blkHeight, bpp, mipLevel);
                uint offset = result.Item1;
                uint size   = result.Item2;


                byte[] data_ = Utils.SubArray(data, offset, size);

                uint width_  = Math.Max(1, tex.Width >> mipLevel);
                uint height_ = Math.Max(1, tex.Height >> mipLevel);
                uint depth_  = Math.Max(1, tex.Depth >> mipLevel);

                uint width__  = DIV_ROUND_UP(width_, blkWidth);
                uint height__ = DIV_ROUND_UP(height_, blkHeight);
                uint depth__  = DIV_ROUND_UP(depth_, blkDepth);


                byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, (uint)tex.Alignment) - SurfaceSize)];
                SurfaceSize += (uint)AlignedData.Length;

                //  Console.WriteLine("SurfaceSize Aligned " + AlignedData);

                Console.WriteLine("MipOffsets " + SurfaceSize);
                Console.WriteLine("size " + size);

                tex.MipOffsets[mipLevel] = SurfaceSize;
                if (tex.TileMode == TileMode.LinearAligned)
                {
                    Pitch = width__ * bpp;

                    if (target == 1)
                    {
                        Pitch = TegraX1Swizzle.round_up(width__ * bpp, 32);
                    }

                    SurfaceSize += Pitch * height__;
                }
                else
                {
                    if (TegraX1Swizzle.pow2_round_up(height__) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }

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

                byte[] SwizzledData = TegraX1Swizzle.swizzle(width_, height_, depth_, blkWidth, blkHeight, blkDepth, target, bpp, (uint)tex.TileMode, (int)Math.Max(0, tex.BlockHeightLog2 - blockHeightShift), data_);
                mipmaps.Add(AlignedData.Concat(SwizzledData).ToArray());
            }
            tex.ImageSize = SurfaceSize;

            return(mipmaps);
        }
Ejemplo n.º 8
0
        //Parse info help from
        //https://github.com/Joschuka/fmt_g1m/blob/master/Noesis/plugins/python/fmt_g1m.py
        public void Read(FileReader reader)
        {
            reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;

            long   StartPos = reader.Position;
            string Magic    = reader.ReadString(4);

            if (Magic == "GT1G")
            {
                reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
            }
            else
            {
                reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
            }

            IsBigEndian = reader.IsBigEndian;

            if (Magic == "GT1G")
            {
                Platform = GT1Platform.Switch;
            }
            else
            {
                Platform = GT1Platform.WiiU;
            }

            string Version      = reader.ReadString(4);
            uint   FileSize     = reader.ReadUInt32();
            uint   DataOffset   = reader.ReadUInt32();
            uint   TextureCount = reader.ReadUInt32();

            PlatformID = reader.ReadUInt32();
            uint unk2 = reader.ReadUInt32();

            uint[] unk3s = reader.ReadUInt32s((int)TextureCount);

            for (int i = 0; i < TextureCount; i++)
            {
                reader.SeekBegin(StartPos + DataOffset + (i * 4));

                uint InfoOffset = reader.ReadUInt32();

                reader.SeekBegin(DataOffset + InfoOffset);

                byte mipSys   = reader.ReadByte();
                byte format   = reader.ReadByte();
                byte texDims  = reader.ReadByte();
                byte unknown3 = reader.ReadByte(); //1
                byte unknown4 = reader.ReadByte(); //0
                byte unknown5 = reader.ReadByte(); //1
                reader.ReadByte();
                byte flags = reader.ReadByte();

                if (reader.ByteOrder == Syroot.BinaryData.ByteOrder.LittleEndian)
                {
                    mipSys  = SwapEndianByte(mipSys);
                    texDims = SwapEndianByte(texDims);
                }

                uint Width  = (uint)Math.Pow(2, texDims / 16);
                uint Height = (uint)Math.Pow(2, texDims % 16);
                if (flags > 0)
                {
                    var extSize = reader.ReadInt32();
                    if (extSize < 0xC || extSize > 0x14)
                    {
                        throw new Exception("Extra texture data is not between 0xC and 0x14 Bytes!!");
                    }

                    uint param1 = reader.ReadUInt32();
                    uint param2 = reader.ReadUInt32();

                    if (extSize >= 0x10)
                    {
                        Width = reader.ReadUInt32();
                    }
                    if (extSize >= 0x14)
                    {
                        Height = reader.ReadUInt32();
                    }
                }

                GITextureWrapper tex = new GITextureWrapper(this);
                tex.ImageKey         = "texture";
                tex.SelectedImageKey = tex.ImageKey;
                tex.Text             = $"Texture_{i}";
                tex.Width            = Width;
                tex.Height           = Height;
                tex.MipCount         = (uint)mipSys >> 4;
                uint texSys = (uint)mipSys & 0xF;

                uint textureSize = 0;
                uint mortonWidth = 0;
                switch (format)
                {
                case 0x00:     //ABGR
                case 0x01:     //BGRA 32 bit (no mip maps)
                case 0x09:
                    tex.Format = TEX_FORMAT.R8G8B8A8_UNORM;
                    break;

                case 0x34:
                    tex.Format  = TEX_FORMAT.RGB565;
                    textureSize = Width * Height * 2;
                    break;

                case 0x02:
                case 0x06:
                case 0x3C:
                case 0x3D:
                case 0x59:
                case 0x60:     //Swizzled
                    tex.Format = TEX_FORMAT.BC1_UNORM;
                    break;

                case 0x10:
                    tex.Format  = TEX_FORMAT.BC1_UNORM;
                    mortonWidth = 0x4;
                    break;

                case 0x12:
                    tex.Format  = TEX_FORMAT.BC3_UNORM;
                    mortonWidth = 0x8;
                    break;

                case 0x36:
                    tex.Format  = TEX_FORMAT.B4G4R4A4_UNORM;
                    textureSize = Width * Height * 2;
                    break;

                case 0x3:
                case 0x7:
                case 0x8:
                case 0x5B:
                case 0x62:     //bc1 swizzled
                    tex.Format = TEX_FORMAT.BC3_UNORM;
                    break;

                case 0x5C:
                    tex.Format = TEX_FORMAT.BC4_UNORM;
                    break;

                case 0x5D:     //DXT5 swizzled or ATI2
                    tex.Format = TEX_FORMAT.BC5_UNORM;
                    break;

                case 0x5E:
                    tex.Format = TEX_FORMAT.BC6H_UF16;     //Uses cubemaps
                    break;

                case 0x5F:
                    tex.Format = TEX_FORMAT.BC7_UNORM;
                    break;

                case 0xF:
                    textureSize = Width * Height;
                    tex.Format  = TEX_FORMAT.A8_UNORM;
                    break;

                case 0x56:
                    tex.Format  = TEX_FORMAT.ETC1_UNORM;
                    textureSize = Width * Height % 2;
                    break;

                case 0x6F:
                    tex.Format  = TEX_FORMAT.ETC1_UNORM;
                    textureSize = Width * Height;
                    break;

                default:
                    throw new Exception("Unsupported format! " + format.ToString("x"));
                }

                if (textureSize == 0)
                {
                    textureSize = (Width * Height * STGenericTexture.GetBytesPerPixel(tex.Format)) / 8;
                }

                if (format == 0x09)
                {
                    textureSize = (Width * Height * 64) / 8;
                }
                if (format == 0x01)
                {
                    textureSize = (Width * Height * 32) / 8;
                    tex.Parameters.DontSwapRG = true;
                }

                tex.ImageData = reader.ReadBytes((int)textureSize);
                Textures.Add(tex);
            }
        }
Ejemplo n.º 9
0
        List <byte[]> SwizzleSurfaceMipMaps(STGenericTexture tex, byte[] data, uint MipCount)
        {
            int  blockHeightShift = 0;
            int  target           = 1;
            uint Pitch            = 0;
            uint SurfaceSize      = 0;
            uint blockHeight      = 0;
            uint blkWidth         = tex.GetBlockWidth();
            uint blkHeight        = tex.GetBlockHeight();
            uint blkDepth         = tex.GetBlockDepth();
            uint bpp = tex.GetBytesPerPixel();

            MipOffsets = new uint[MipCount];

            uint linesPerBlockHeight = 0;

            if (LinearMode)
            {
                blockHeight     = 1;
                BlockHeightLog2 = 0;
                Alignment       = 1;

                linesPerBlockHeight = 1;
                ReadTextureLayout   = 0;
            }
            else
            {
                blockHeight       = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(tex.Height, blkHeight));
                BlockHeightLog2   = (uint)Convert.ToString(blockHeight, 2).Length - 1;
                Alignment         = 512;
                ReadTextureLayout = 1;

                linesPerBlockHeight = blockHeight * 8;
            }

            List <byte[]> mipmaps = new List <byte[]>();

            for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
            {
                var  result = WiiU.TextureHelper.GetCurrentMipSize(tex.Width, tex.Height, blkWidth, blkHeight, bpp, mipLevel);
                uint offset = result.Item1;
                uint size   = result.Item2;


                byte[] data_ = ByteUtils.SubArray(data, offset, size);

                uint width_  = Math.Max(1, tex.Width >> mipLevel);
                uint height_ = Math.Max(1, tex.Height >> mipLevel);
                uint depth_  = Math.Max(1, tex.Depth >> mipLevel);

                uint width__  = TegraX1Swizzle.DIV_ROUND_UP(width_, blkWidth);
                uint height__ = TegraX1Swizzle.DIV_ROUND_UP(height_, blkHeight);
                uint depth__  = TegraX1Swizzle.DIV_ROUND_UP(depth_, blkDepth);

                byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, Alignment) - SurfaceSize)];
                SurfaceSize += (uint)AlignedData.Length;

                ImageSize            = 0;
                MipOffsets[mipLevel] = SurfaceSize;
                if (LinearMode)
                {
                    Pitch = width__ * bpp;

                    if (target == 1)
                    {
                        Pitch = TegraX1Swizzle.round_up(width__ * bpp, 32);
                    }

                    SurfaceSize += Pitch * height__;
                }
                else
                {
                    if (TegraX1Swizzle.pow2_round_up(height__) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }

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

                byte[] SwizzledData = TegraX1Swizzle.swizzle(width_, height_, depth_, blkWidth, blkHeight, blkDepth, target, bpp, (uint)TileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), data_);
                mipmaps.Add(AlignedData.Concat(SwizzledData).ToArray());
            }
            ImageSize = SurfaceSize;

            return(mipmaps);
        }
Ejemplo n.º 10
0
        public void Read(FileReader reader)
        {
            reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;

            Text = FileName;

            long   StartPos = reader.Position;
            string Magic    = reader.ReadString(4);

            if (Magic == "GT1G")
            {
                reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
            }
            else
            {
                reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
            }

            if (Magic == "GT1G")
            {
                Platform = GT1Platform.Switch;
            }
            else
            {
                Platform = GT1Platform.WiiU;
            }

            string Version      = reader.ReadString(4);
            uint   FileSize     = reader.ReadUInt32();
            uint   DataOffset   = reader.ReadUInt32();
            uint   TextureCount = reader.ReadUInt32();
            uint   unk          = reader.ReadUInt32();
            uint   unk2         = reader.ReadUInt32();

            uint[] unk3s = reader.ReadUInt32s((int)TextureCount);

            for (int i = 0; i < TextureCount; i++)
            {
                reader.SeekBegin(StartPos + DataOffset + (i * 4));

                uint InfoOffset = reader.ReadUInt32();

                reader.SeekBegin(DataOffset + InfoOffset);

                byte numMips     = reader.ReadByte();
                byte format      = reader.ReadByte();
                byte texDims     = reader.ReadByte();
                byte unknown3    = reader.ReadByte(); //1
                byte unknown4    = reader.ReadByte(); //0
                byte unknown5    = reader.ReadByte(); //1
                byte unknown6    = reader.ReadByte(); //12
                byte extraHeader = reader.ReadByte();

                if (reader.ByteOrder == Syroot.BinaryData.ByteOrder.LittleEndian)
                {
                    numMips     = SwapEndianByte(numMips);
                    texDims     = SwapEndianByte(texDims);
                    extraHeader = SwapEndianByte(extraHeader);
                }

                if (extraHeader == 1)
                {
                    var extSize = reader.ReadInt32();
                    var ext     = reader.ReadBytes(extSize - 4);
                }

                uint Width  = (uint)Math.Pow(2, texDims / 16);
                uint Height = (uint)Math.Pow(2, texDims % 16);

                GITexture tex = new GITexture(this);
                tex.ImageKey         = "texture";
                tex.SelectedImageKey = tex.ImageKey;
                tex.Text             = $"Texture {i}  {format.ToString("x")}";
                tex.Width            = Width;
                tex.Height           = Height;
                tex.MipCount         = numMips;

                switch (format)
                {
                case 0x00:     //ABGR
                case 0x01:     //BGRA 32 bit (no mip maps)
                case 0x02:     //RGBA 32 bit
                case 0x09:
                    tex.Format = TEX_FORMAT.R8G8B8A8_UNORM;
                    break;

                case 0x06:
                case 0x10:     //PC and xbox (swizzled)
                case 0x59:
                case 0x60:     //Swizzled
                    tex.Format = TEX_FORMAT.BC1_UNORM;
                    break;

                case 0x7:
                case 0x8:
                case 0x12:     //PC and xbox (swizzled)
                case 0x5B:
                case 0x62:     //bc1 swizzled
                    tex.Format = TEX_FORMAT.BC3_UNORM;
                    break;

                case 0x5C:
                    tex.Format = TEX_FORMAT.BC4_UNORM;
                    break;

                case 0x5D:     //DXT5 swizzled or ATI2
                    tex.Format = TEX_FORMAT.BC5_UNORM;
                    break;

                case 0x5E:
                    tex.Format = TEX_FORMAT.BC6H_UF16;     //Uses cubemaps
                    break;

                case 0x5F:
                    tex.Format = TEX_FORMAT.BC7_UNORM;
                    break;

                default:
                    throw new Exception("Unsupported format! " + format.ToString("x"));
                }

                uint textureSize = (Width * Height * STGenericTexture.GetBytesPerPixel(tex.Format)) / 8;
                if (format == 0x09)
                {
                    textureSize = (Width * Height * 64) / 8;
                }
                if (format == 0x01)
                {
                    textureSize = (Width * Height * 32) / 8;
                    tex.Parameters.DontSwapRG = true;
                }

                tex.ImageData = reader.ReadBytes((int)textureSize);
                Nodes.Add(tex);
            }
        }