Beispiel #1
0
        public void ReadNTWU(FileData d)
        {
            d.Seek(0x6);

            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.CubemapAllfaces) == (uint)Dds.Ddscaps2.CubemapAllfaces)
                    {
                        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);
            }
        }
Beispiel #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;
            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.Gx2SurfaceFormatTBc1Unorm):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case ((int)Gtx.Gx2SurfaceFormat.Gx2SurfaceFormatTBc1Srgb):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case ((int)Gtx.Gx2SurfaceFormat.Gx2SurfaceFormatTBc2Unorm):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
                break;

            case ((int)Gtx.Gx2SurfaceFormat.Gx2SurfaceFormatTBc2Srgb):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext;
                break;

            case ((int)Gtx.Gx2SurfaceFormat.Gx2SurfaceFormatTBc3Unorm):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
                break;

            case ((int)Gtx.Gx2SurfaceFormat.Gx2SurfaceFormatTBc3Srgb):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext;
                break;

            case ((int)Gtx.Gx2SurfaceFormat.Gx2SurfaceFormatTBc4Unorm):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRedRgtc1;
                break;

            case ((int)Gtx.Gx2SurfaceFormat.Gx2SurfaceFormatTBc4Snorm):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedSignedRedRgtc1;
                break;

            case ((int)Gtx.Gx2SurfaceFormat.Gx2SurfaceFormatTBc5Unorm):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgRgtc2;
                break;

            case ((int)Gtx.Gx2SurfaceFormat.Gx2SurfaceFormatTBc5Snorm):
                //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.Gx2SurfaceFormatTcsR8G8B8A8Unorm):
                texture.pixelInternalFormat = PixelInternalFormat.Rgba;
                texture.pixelFormat         = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                break;
            }
        }