Exemple #1
0
        public void ReadFTEX(Texture tex)
        {
            ImageKey         = "texture";
            SelectedImageKey = "texture";

            reserve = tex.Data;

            texture.width  = (int)tex.Width;
            texture.height = (int)tex.Height;
            format         = (int)tex.Format;
            int swizzle = (int)tex.Swizzle;
            int pitch   = (int)tex.Pitch;

            texture.data = GTX.swizzleBC(tex.Data, texture.width, texture.height, format, (int)tex.TileMode, pitch, swizzle);
            Text         = tex.Name;


            //Setup variables for treenode data

            width  = texture.width;
            height = texture.height;
            texture.mipMapCount = (int)tex.MipCount;

            FileData f = new FileData(tex.MipData);

            for (int level = 0; level < tex.MipCount; level++)
            {
                if (level != 0)
                {
                }

                //  byte[] mip = f.getSection((int)tex.MipOffsets[level - 1], (int)tex.MipOffsets[level + 1]);

                //  texture.mipMapData.Add(mip);
            }

            switch (format)
            {
            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRedRgtc1;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedSignedRedRgtc1;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgRgtc2;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM):
                //OpenTK doesn't load BC5 SNORM textures right so I'll use the same decompress method bntx has
                byte[] fixBC5 = DDS_Decompress.DecompressBC5(texture.data, texture.width, texture.height, true);
                texture.data = fixBC5;
                texture.pixelInternalFormat = PixelInternalFormat.Rgba;
                texture.pixelFormat         = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;

                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM):
                texture.pixelInternalFormat = PixelInternalFormat.Rgba;
                texture.pixelFormat         = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                break;
            }
        }
Exemple #2
0
        public void ReadFTEX(Texture tex)
        {
            ImageKey         = "texture";
            SelectedImageKey = "texture";

            reserve = tex.Data;

            texture.width  = (int)tex.Width;
            texture.height = (int)tex.Height;
            format         = (int)tex.Format;
            int swizzle = (int)tex.Swizzle;
            int pitch   = (int)tex.Pitch;

            texture.data = GTX.swizzleBC(tex.Data, texture.width, texture.height, format, (int)tex.TileMode, pitch, swizzle);
            Text         = tex.Name;

            //Setup variables for treenode data

            width  = texture.width;
            height = texture.height;


            switch (format)
            {
            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM):
                texture.type = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB):
                texture.type = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt1Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM):
                texture.type = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB):
                texture.type = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM):
                texture.type = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB):
                texture.type = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM):
                texture.type = PixelInternalFormat.CompressedRedRgtc1;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM):
                texture.type = PixelInternalFormat.CompressedSignedRedRgtc1;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM):
                texture.type = PixelInternalFormat.CompressedRgRgtc2;
                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM):
                //OpenTK doesn't load BC5 SNORM textures right so I'll use the same decompress method bntx has
                byte[] fixBC5 = DDS_Decompress.DecompressBC5(texture.data, texture.width, texture.height, true);
                texture.data  = fixBC5;
                texture.type  = PixelInternalFormat.Rgba;
                texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;

                break;

            case ((int)GTX.GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM):
                texture.type  = PixelInternalFormat.Rgba;
                texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                break;
            }
            texture.display = loadImage(texture);
            display         = texture.display;
        }
Exemple #3
0
        public void ReadNTWU(FileData d)
        {
            d.skip(0x02);
            int count = d.readShort();

            d.skip(0x10);
            int headerPtr       = d.pos();
            int dataPtr         = 0;
            int gtxHeaderOffset = 0;

            for (int i = 0; i < count; i++)
            {
                NUD_Texture tex = new NUD_Texture();
                tex.type = PixelInternalFormat.Rgba32ui;

                d.seek(headerPtr);
                int totalSize  = d.readInt();
                int headerSize = d.readShort();
                int numMips    = d.readInt();
                tex.setPixelFormatFromNutFormat(d.readShort());
                tex.width  = d.readShort();
                tex.height = d.readShort();

                d.skip(8); // mipmaps and padding
                int dataOffset = d.readInt() + dataPtr + 0x10;

                headerPtr += headerSize;
                dataPtr   += headerSize;

                d.skip(0x04);
                if (i == 0)
                {
                    gtxHeaderOffset = d.readInt() + 0x10;
                }
                else
                {
                    gtxHeaderOffset += 0x80;
                    d.skip(0x04);
                }

                d.skip(0x04);
                d.skip(headerSize - 0x50);

                d.skip(0x18);
                tex.id = d.readInt();

                d.seek(gtxHeaderOffset);
                d.skip(0x04); // dim
                d.skip(0x04); // width
                d.skip(0x04); // height
                d.skip(0x04); // depth
                d.skip(0x04); // numMips
                int format = d.readInt();
                d.skip(0x04); // aa
                d.skip(0x04); // use
                int imageSize = d.readInt();
                d.skip(0x04); // imagePtr
                d.skip(0x04); // mipSize
                d.skip(0x04); // mipPtr
                int tileMode = d.readInt();
                int swizzle  = d.readInt();
                d.skip(0x04); // alignment
                int pitch = d.readInt();

                for (int mipLevel = 0; mipLevel < numMips; mipLevel++)
                {
                    // Maybe this is the problem?
                    int mipSize = imageSize >> (mipLevel * 2);

                    //if (mipLevel == 0)
                    {
                        tex.mipmaps.Add(GTX.swizzleBC(
                                            d.getSection(dataOffset, mipSize),
                                            (tex.width >> mipLevel),
                                            (tex.height >> mipLevel),
                                            format,
                                            tileMode,
                                            pitch,
                                            swizzle
                                            ));
                    }

                    dataOffset += mipSize;
                }

                textures.Add(tex);
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, loadImage(tex));
                }
            }
        }
Exemple #4
0
        public void ReadNTWU(FileData d)
        {
            d.skip(0x02);
            int count = d.readShort();

            d.skip(0x10);
            int headerPtr       = d.pos();
            int dataPtr         = 0;
            int gtxHeaderOffset = 0;

            for (int i = 0; i < count; i++)
            {
                NUD_Texture tex = new NUD_Texture();
                tex.type = PixelInternalFormat.Rgba32ui;

                d.seek(headerPtr);
                int totalSize  = d.readInt();
                int headerSize = d.readShort();
                int numMips    = d.readInt();
                tex.setPixelFormatFromNutFormat(d.readShort());
                tex.width  = d.readShort();
                tex.height = d.readShort();

                d.skip(8); // mipmaps and padding
                int dataOffset = d.readInt() + dataPtr + 0x10;

                headerPtr += headerSize;
                dataPtr   += headerSize;

                d.skip(0x04);
                if (i == 0)
                {
                    gtxHeaderOffset = d.readInt() + 0x10;
                }
                else
                {
                    gtxHeaderOffset += 0x80;
                    d.skip(0x04);
                }

                d.skip(0x04);

                // check for cubemap
                bool cmap = (d.readInt() == d.readInt());
                d.seek(d.pos() - 8);
                if (cmap)
                {
                    Console.WriteLine("cubemap detected");
                }

                d.skip(headerSize - 0x50);

                d.skip(0x18);
                tex.id = d.readInt();

                d.seek(gtxHeaderOffset);
                d.skip(0x04); // dim
                d.skip(0x04); // width
                d.skip(0x04); // height
                d.skip(0x04); // depth
                d.skip(0x04); // numMips
                int format = d.readInt();
                d.skip(0x04); // aa
                d.skip(0x04); // use
                int imageSize = d.readInt();
                d.skip(0x04); // imagePtr
                d.skip(0x04); // mipSize
                d.skip(0x04); // mipPtr
                int tileMode = d.readInt();
                int swizzle  = d.readInt();
                d.skip(0x04); // alignment
                int pitch = d.readInt();

                for (int mipLevel = 0; mipLevel < numMips; mipLevel++)
                {
                    // Maybe this is the problem?
                    int mipSize = imageSize >> (mipLevel * 2);
                    int p       = pitch >> mipLevel;

                    //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle);
                    //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel));

                    //if (cmap) tex.height *= 2;

                    int w = (tex.width >> mipLevel);
                    int h = (tex.height >> mipLevel);

                    //if (mipSize % 0x10 != 0) mipSize += mipSize % 0x10;
                    //if (cmap) mipSize /= 6;

                    //if (p <= 16) p = 64;
                    {
                        tex.mipmaps.Add(GTX.swizzleBC(
                                            d.getSection(dataOffset, mipSize),
                                            w,
                                            h,
                                            format,
                                            tileMode,
                                            p,
                                            swizzle
                                            ));
                    }
                    dataOffset += mipSize;

                    /*if (cmap)
                     * {
                     *  for(int k = 0; k < 5; k++)
                     *  {
                     *      p = pitch >> (mipLevel + k + 1);
                     *      tex.mipmaps.Add(GTX.swizzleBC(
                     *          d.getSection(dataOffset, mipSize),
                     *          w,
                     *          h,
                     *          format,
                     *          tileMode,
                     *          p,
                     *          swizzle
                     *      ));
                     *
                     *      dataOffset += mipSize;
                     *  }
                     * }*/

                    //while (dataOffset % 1024 != 0) dataOffset++;
                    //if (mipSize == 0x4000) dataOffset += 0x400;
                }

                // fix mipmap swizzle for rgba types
                if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17)
                {
                    Console.WriteLine("Endian swap");
                    // swap
                    foreach (byte[] mip in tex.mipmaps)
                    {
                        for (int t = 0; t < mip.Length; t += 4)
                        {
                            /*byte t1 = mip[t];
                             * byte t2 = mip[t+1];
                             * mip[t] = mip[t + 3];
                             * mip[t + 1] = mip[t + 2];
                             * mip[t + 2] = t2;
                             * mip[t + 3] = t1;*/
                        }
                    }
                }

                textures.Add(tex);
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, loadImage(tex));
                }
            }
        }
Exemple #5
0
        public void ReadNTWU(FileData d)
        {
            d.seek(0x4);

            Version = d.readUShort();
            ushort count = d.readUShort();

            d.skip(0x8);
            int headerPtr = 0x10;

            for (ushort i = 0; i < count; ++i)
            {
                d.seek(headerPtr);

                NutTexture tex = new NutTexture();
                tex.pixelInternalFormat = PixelInternalFormat.Rgba32ui;

                int totalSize = d.readInt();
                d.skip(4);
                int dataSize   = d.readInt();
                int headerSize = d.readUShort();
                d.skip(2);

                d.skip(1);
                byte mipmapCount = d.readByte();
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.Width  = d.readUShort();
                tex.Height = d.readUShort();
                d.readInt(); //Always 1?
                uint caps2 = d.readUInt();

                bool isCubemap    = false;
                byte surfaceCount = 1;
                if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP)
                {
                    //Only supporting all six faces
                    if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES)
                    {
                        isCubemap    = true;
                        surfaceCount = 6;
                    }
                    else
                    {
                        throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HashId:X}. Six faces are required.");
                    }
                }

                int dataOffset      = d.readInt() + headerPtr;
                int mipDataOffset   = d.readInt() + headerPtr;
                int gtxHeaderOffset = d.readInt() + headerPtr;
                d.readInt();

                int cmapSize1 = 0;
                int cmapSize2 = 0;
                if (isCubemap)
                {
                    cmapSize1 = d.readInt();
                    cmapSize2 = d.readInt();
                    d.skip(8);
                }

                int imageSize = 0; //Total size of first mipmap of every surface
                int mipSize   = 0; //Total size of mipmaps other than the first of every surface
                if (mipmapCount == 1)
                {
                    if (isCubemap)
                    {
                        imageSize = cmapSize1;
                    }
                    else
                    {
                        imageSize = dataSize;
                    }
                }
                else
                {
                    imageSize = d.readInt();
                    mipSize   = d.readInt();
                    d.skip((mipmapCount - 2) * 4);
                    d.align(0x10);
                }

                d.skip(0x10); //eXt data - always the same

                d.skip(4);    //GIDX
                d.readInt();  //Always 0x10
                tex.HashId = d.readInt();
                d.skip(4);    // padding align 8

                d.seek(gtxHeaderOffset);
                GTX.GX2Surface gtxHeader = new GTX.GX2Surface();

                gtxHeader.dim       = d.readInt();
                gtxHeader.width     = d.readInt();
                gtxHeader.height    = d.readInt();
                gtxHeader.depth     = d.readInt();
                gtxHeader.numMips   = d.readInt();
                gtxHeader.format    = d.readInt();
                gtxHeader.aa        = d.readInt();
                gtxHeader.use       = d.readInt();
                gtxHeader.imageSize = d.readInt();
                gtxHeader.imagePtr  = d.readInt();
                gtxHeader.mipSize   = d.readInt();
                gtxHeader.mipPtr    = d.readInt();
                gtxHeader.tileMode  = d.readInt();
                gtxHeader.swizzle   = d.readInt();
                gtxHeader.alignment = d.readInt();
                gtxHeader.pitch     = d.readInt();

                //mipOffsets[0] is not in this list and is simply the start of the data (dataOffset)
                //mipOffsets[1] is relative to the start of the data (dataOffset + mipOffsets[1])
                //Other mipOffsets are relative to mipOffset[1] (dataOffset + mipOffsets[1] + mipOffsets[i])
                int[] mipOffsets = new int[mipmapCount];
                mipOffsets[0] = 0;
                for (byte mipLevel = 1; mipLevel < mipmapCount; ++mipLevel)
                {
                    mipOffsets[mipLevel] = 0;
                    mipOffsets[mipLevel] = mipOffsets[1] + d.readInt();
                }

                for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                {
                    tex.surfaces.Add(new TextureSurface());
                }

                int w = tex.Width, h = tex.Height;
                for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                {
                    int p = gtxHeader.pitch / (gtxHeader.width / w);

                    int size;
                    if (mipmapCount == 1)
                    {
                        size = imageSize;
                    }
                    else if (mipLevel + 1 == mipmapCount)
                    {
                        size = (mipSize + mipOffsets[1]) - mipOffsets[mipLevel];
                    }
                    else
                    {
                        size = mipOffsets[mipLevel + 1] - mipOffsets[mipLevel];
                    }

                    size /= surfaceCount;

                    for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                    {
                        gtxHeader.data = d.getSection(dataOffset + mipOffsets[mipLevel] + (size * surfaceLevel), size);

                        //Real size
                        //Leave the below line commented for now because it breaks RGBA textures
                        //size = ((w + 3) >> 2) * ((h + 3) >> 2) * (GTX.getBPP(gtxHeader.format) / 8);
                        if (size < (GTX.getBPP(gtxHeader.format) / 8))
                        {
                            size = (GTX.getBPP(gtxHeader.format) / 8);
                        }

                        byte[] deswiz = GTX.swizzleBC(
                            gtxHeader.data,
                            w,
                            h,
                            gtxHeader.format,
                            gtxHeader.tileMode,
                            p,
                            gtxHeader.swizzle
                            );
                        tex.surfaces[surfaceLevel].mipmaps.Add(new FileData(deswiz).getSection(0, size));
                    }

                    w /= 2;
                    h /= 2;

                    if (w < 1)
                    {
                        w = 1;
                    }
                    if (h < 1)
                    {
                        h = 1;
                    }
                }

                headerPtr += headerSize;

                Nodes.Add(tex);
            }
        }
Exemple #6
0
        public void ReadNTWU(FileData d)
        {
            d.skip(0x02);
            int count = d.readShort();

            d.skip(0x10);
            int headerPtr       = d.pos();
            int dataPtr         = 0;
            int gtxHeaderOffset = 0;

            for (int i = 0; i < count; i++)
            {
                NutTexture tex = new NutTexture();
                tex.type = PixelInternalFormat.Rgba32ui;

                d.seek(headerPtr);
                int totalSize  = d.readInt();
                int headerSize = d.readShort();
                int numMips    = d.readInt();
                tex.setPixelFormatFromNutFormat(d.readShort());
                tex.Width  = d.readShort();
                tex.Height = d.readShort();

                d.skip(8); // mipmaps and padding
                int dataOffset = d.readInt() + dataPtr + 0x10;

                headerPtr += headerSize;
                dataPtr   += headerSize;

                d.skip(0x04);
                if (i == 0)
                {
                    gtxHeaderOffset = d.readInt() + 0x10;
                }
                else
                {
                    gtxHeaderOffset += 0x80;
                    d.skip(0x04);
                }

                d.skip(0x04);

                // check for cubemap
                bool cmap = (d.readInt() == d.readInt());
                d.seek(d.pos() - 8);
                if (cmap)
                {
                    Console.WriteLine("cubemap detected");
                }

                d.skip(headerSize - 0x50);

                d.skip(0x18);
                tex.HASHID = d.readInt();

                Console.WriteLine(gtxHeaderOffset.ToString("x"));
                d.seek(gtxHeaderOffset);
                d.skip(0x04);              // dim
                d.skip(0x04);              // width
                d.skip(0x04);              // height
                d.skip(0x04);              // depth
                d.skip(0x04);              // numMips
                int format = d.readInt();
                d.skip(0x04);              // aa
                d.skip(0x04);              // use
                int imageSize = d.readInt();
                d.skip(0x04);              // imagePtr
                int maxSize = d.readInt(); // mipSize
                d.skip(0x04);              // mipPtr
                int tileMode = d.readInt();
                int swizzle  = d.readInt();
                d.skip(0x04); // alignment
                int pitch = d.readInt();

                int ds   = dataOffset;
                int s1   = 0;
                int size = 0;
                Console.WriteLine(totalSize.ToString("x"));
                for (int mipLevel = 0; mipLevel < numMips; mipLevel++)
                {
                    // Maybe this is the problem?
                    int mipSize = imageSize >> (mipLevel * 2);
                    int p       = pitch >> mipLevel;

                    size = d.readInt();
                    //Console.WriteLine("\tMIP: " + size.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + (size == 0 ? ds + totalSize - dataOffset : size));

                    //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle);
                    //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel));

                    //if (cmap) tex.height *= 2;

                    int w = (tex.Width >> mipLevel);
                    int h = (tex.Height >> mipLevel);

                    {
                        byte[] deswiz = GTX.swizzleBC(
                            d.getSection(dataOffset, d.size() - dataOffset),
                            w,
                            h,
                            format,
                            tileMode,
                            p,
                            swizzle
                            );
                        tex.mipmaps.Add(new FileData(deswiz).getSection(0, mipSize));
                    }
                    if (mipLevel == 0)
                    {
                        s1         = size;
                        dataOffset = ds + size;
                    }
                    else
                    {
                        dataOffset = ds + s1 + size;
                    }
                    //dataOffset += mipSize;

                    /*if (cmap)
                     * {
                     *  for(int k = 0; k < 5; k++)
                     *  {
                     *      p = pitch >> (mipLevel + k + 1);
                     *      tex.mipmaps.Add(GTX.swizzleBC(
                     *          d.getSection(dataOffset, mipSize),
                     *          w,
                     *          h,
                     *          format,
                     *          tileMode,
                     *          p,
                     *          swizzle
                     *      ));
                     *
                     *      dataOffset += mipSize;
                     *  }
                     * }*/

                    //while (dataOffset % 1024 != 0) dataOffset++;
                    //if (mipSize == 0x4000) dataOffset += 0x400;
                }

                Nodes.Add(tex);
            }

            foreach (NutTexture tex in Nodes)
            {
                if (!draw.ContainsKey(tex.HASHID))
                {
                    draw.Add(tex.HASHID, loadImage(tex, false));
                }

                // redo mipmaps

                /*GL.BindTexture(TextureTarget.Texture2D, draw[tex.id]);
                 * for (int k = 1; k < tex.mipmaps.Count; k++)
                 * {
                 *  tex.mipmaps[k] = new byte[tex.mipmaps[k].Length];
                 *  GCHandle pinnedArray = GCHandle.Alloc(tex.mipmaps[k], GCHandleType.Pinned);
                 *  IntPtr pointer = pinnedArray.AddrOfPinnedObject();
                 *  GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, pointer);
                 *  pinnedArray.Free();
                 * }*/
            }


            //File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\mip1.bin", bytearray);

            //Console.WriteLine(GL.GetError());

            /*int j = 0;
             * foreach(byte[] b in textures[0].mipmaps)
             * {
             *  if (j == 3)
             *  {
             *      for(int w = 3; w < 8; w++)
             *      {
             *          for (int p = 3; p < 6; p++)
             *          {
             *              byte[] deswiz = GTX.swizzleBC(
             *                  b,
             *                  (int)Math.Pow(2, w),
             *                  64,
             *                  51,
             *                  4,
             *                   (int)Math.Pow(2, p),
             *                  197632
             *              );
             *              File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\chunk_" + (int)Math.Pow(2, p) + "_" + (int)Math.Pow(2, w), deswiz);
             *          }
             *      }
             *
             *  }
             *  j++;
             * }*/
        }
Exemple #7
0
        public void ReadNTWU(FileData d)
        {
            d.seek(0x4);

            Version = d.readUShort();
            ushort count = d.readUShort();

            d.skip(0x8);
            int headerPtr = 0x10;

            for (ushort i = 0; i < count; ++i)
            {
                d.seek(headerPtr);

                NutTexture tex = new NutTexture();
                tex.type = PixelInternalFormat.Rgba32ui;

                int totalSize = d.readInt();
                d.skip(4);
                int dataSize   = d.readInt();
                int headerSize = d.readUShort();
                d.skip(2);

                d.skip(1);
                byte mipMapCount = d.readByte();
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.Width  = d.readUShort();
                tex.Height = d.readUShort();
                d.readInt(); //Always 1?
                uint caps2 = d.readUInt();

                bool isCubemap    = false;
                byte surfaceCount = 1;
                if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP)
                {
                    //Only supporting all six faces
                    if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES)
                    {
                        isCubemap    = true;
                        surfaceCount = 6;
                    }
                    else
                    {
                        throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HASHID:X}. Six faces are required.");
                    }
                }

                int dataOffset      = d.readInt() + headerPtr;
                int mipDataOffset   = d.readInt() + headerPtr;
                int gtxHeaderOffset = d.readInt() + headerPtr;
                d.readInt();

                int cmapSize1 = 0;
                int cmapSize2 = 0;
                if (isCubemap)
                {
                    cmapSize1 = d.readInt();
                    cmapSize2 = d.readInt();
                    d.skip(8);
                }

                int imageSize = 0; //Total size of first mipmap of every surface
                int mipSize   = 0; //Total size of mipmaps other than the first of every surface
                if (mipMapCount == 1)
                {
                    if (isCubemap)
                    {
                        imageSize = cmapSize1;
                    }
                    else
                    {
                        imageSize = dataSize;
                    }
                }
                else
                {
                    imageSize = d.readInt();
                    mipSize   = d.readInt();
                    d.skip((mipMapCount - 2) * 4);
                    d.align(0x10);
                }

                d.skip(0x10); //eXt data - always the same

                d.skip(4);    //GIDX
                d.readInt();  //Always 0x10
                tex.HASHID = d.readInt();
                d.skip(4);    // padding align 8

                d.seek(gtxHeaderOffset);
                GTX.GX2Surface gtxHeader = new GTX.GX2Surface();

                gtxHeader.dim       = d.readInt();
                gtxHeader.width     = d.readInt();
                gtxHeader.height    = d.readInt();
                gtxHeader.depth     = d.readInt();
                gtxHeader.numMips   = d.readInt();
                gtxHeader.format    = d.readInt();
                gtxHeader.aa        = d.readInt();
                gtxHeader.use       = d.readInt();
                gtxHeader.imageSize = d.readInt();
                gtxHeader.imagePtr  = d.readInt();
                gtxHeader.mipSize   = d.readInt();
                gtxHeader.mipPtr    = d.readInt();
                gtxHeader.tileMode  = d.readInt();
                gtxHeader.swizzle   = d.readInt();
                gtxHeader.alignment = d.readInt();
                gtxHeader.pitch     = d.readInt();

                //mipOffsets[0] is not in this list and is simply the start of the data (dataOffset)
                //mipOffsets[1] is relative to the start of the data (dataOffset + mipOffsets[1])
                //Other mipOffsets are relative to mipOffset[1] (dataOffset + mipOffsets[1] + mipOffsets[i])
                int[] mipOffsets = new int[mipMapCount];
                mipOffsets[0] = 0;
                for (byte mipLevel = 1; mipLevel < mipMapCount; ++mipLevel)
                {
                    mipOffsets[mipLevel] = 0;
                    mipOffsets[mipLevel] = mipOffsets[1] + d.readInt();
                }

                for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                {
                    tex.surfaces.Add(new TextureSurface());
                }

                int w = tex.Width, h = tex.Height;
                for (byte mipLevel = 0; mipLevel < mipMapCount; ++mipLevel)
                {
                    int p = gtxHeader.pitch / (gtxHeader.width / w);

                    int size;
                    if (mipMapCount == 1)
                    {
                        size = imageSize;
                    }
                    else if (mipLevel + 1 == mipMapCount)
                    {
                        size = (mipSize + mipOffsets[1]) - mipOffsets[mipLevel];
                    }
                    else
                    {
                        size = mipOffsets[mipLevel + 1] - mipOffsets[mipLevel];
                    }

                    size /= surfaceCount;

                    for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                    {
                        gtxHeader.data = d.getSection(dataOffset + mipOffsets[mipLevel] + (size * surfaceLevel), size);

                        //Real size
                        //Leave the below line commented for now because it breaks RGBA textures
                        //size = ((w + 3) >> 2) * ((h + 3) >> 2) * (GTX.getBPP(gtxHeader.format) / 8);
                        if (size < (GTX.getBPP(gtxHeader.format) / 8))
                        {
                            size = (GTX.getBPP(gtxHeader.format) / 8);
                        }

                        byte[] deswiz = GTX.swizzleBC(
                            gtxHeader.data,
                            w,
                            h,
                            gtxHeader.format,
                            gtxHeader.tileMode,
                            p,
                            gtxHeader.swizzle
                            );
                        tex.surfaces[surfaceLevel].mipmaps.Add(new FileData(deswiz).getSection(0, size));
                    }

                    w /= 2;
                    h /= 2;

                    if (w < 1)
                    {
                        w = 1;
                    }
                    if (h < 1)
                    {
                        h = 1;
                    }
                }

                headerPtr += headerSize;

                Nodes.Add(tex);
            }

            RefreshGlTexturesByHashId();

            //Console.WriteLine("\tMIP: " + size.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + (size == 0 ? ds + dataSize - dataOffset : size));

            //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle);
            //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel));

            //File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\mip1.bin", bytearray);

            //Console.WriteLine(GL.GetError());

            /*int j = 0;
             * foreach(byte[] b in textures[0].mipmaps)
             * {
             *  if (j == 3)
             *  {
             *      for(int w = 3; w < 8; w++)
             *      {
             *          for (int p = 3; p < 6; p++)
             *          {
             *              byte[] deswiz = GTX.swizzleBC(
             *                  b,
             *                  (int)Math.Pow(2, w),
             *                  64,
             *                  51,
             *                  4,
             *                   (int)Math.Pow(2, p),
             *                  197632
             *              );
             *              File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\chunk_" + (int)Math.Pow(2, p) + "_" + (int)Math.Pow(2, w), deswiz);
             *          }
             *      }
             *
             *  }
             *  j++;
             * }*/
        }