Example #1
0
            public void Read(FileData d)
            {
                names.Clear();
                d.skip(8);// magic and section size
                int c1 = d.readInt();

                int start = d.pos();

                for (int i = 0; i < c1; i++)
                {
                    int offset = d.readInt();
                    int size   = d.readInt();

                    int temp = d.pos();
                    d.seek(start + offset);

                    d.readInt();
                    int s = (sbyte)d.readByte();
                    names.Add(d.readString(d.pos(), -1));
                    d.skip(s);
                    d.align(4);


                    d.seek(temp);
                }
            }
Example #2
0
                public void Read(FileData d)
                {
                    hash = d.readInt();
                    unk1 = d.readInt();

                    int s = d.readByte();

                    name = d.readString(d.pos(), -1);
                    d.skip(s);
                    d.align(4);

                    d.skip(8);

                    offset = d.readInt();
                    size   = d.readInt();

                    for (int i = 0; i < param.Length; i++)
                    {
                        param[i] = d.readFloat();
                    }

                    offsets = new int[d.readInt()];
                    for (int i = 0; i < offsets.Length; i++)
                    {
                        offsets[i] = d.readInt();
                    }

                    unkvalues = new float[d.readInt()];
                    for (int i = 0; i < unkvalues.Length; i++)
                    {
                        unkvalues[d.readInt()] = d.readFloat();
                    }

                    List <int> une = new List <int>();

                    while (true)
                    {
                        int i = d.readInt();
                        une.Add(i);
                        if (i == -1)
                        {
                            break;
                        }
                    }
                    unkending = une.ToArray();

                    end = new int[3 + (int)Math.Ceiling((double)((unk1 >> 8) & 0xFF) / 4)];

                    for (int i = 0; i < end.Length; i++)
                    {
                        end[i] = d.readInt();
                    }

                    //Console.WriteLine(id + " " + name + " " + offset.ToString("x"));
                }
Example #3
0
            public void Read(FileData d)
            {
                d.skip(12);
                unk1 = d.readInt();

                int s = d.readByte();

                name = d.readString(d.pos(), s - 1);
                d.skip(s);
                d.align(4);
                flag = d.readInt();
            }
Example #4
0
        // temp stuff
        public static Dictionary <string, SkelAnimation> LoadAJ(string fname, VBN vbn)
        {
            // a note, I know that the main player file has the offsets for
            // animations, this is just for viewing
            FileData f = new FileData(fname);

            f.Endian = System.IO.Endianness.Big;

            int pos = 0;

            Dictionary <string, SkelAnimation> animations = new Dictionary <string, SkelAnimation>();
            AnimationGroupNode group = new AnimationGroupNode()
            {
                Text = fname
            };

            MainForm.Instance.animList.treeView1.Nodes.Add(group);
            while (pos < f.size())
            {
                Console.WriteLine(pos.ToString("x"));
                int           len  = f.readInt();
                DAT_Animation anim = new DAT_Animation();
                anim.Read(new FileData(f.getSection(pos, len)));
                AnimTrack track = new AnimTrack(anim);

                if (pos == 0)
                {
                    //track.Show();
                }
                group.Nodes.Add(track.toAnimation(vbn));
                SkelAnimation sa = track.BakeToSkel(vbn);
                //sa.Tag = track;
                //Runtime.Animations.Add(anim.Name, sa);
                // MainForm.Instance.animList.treeView1.Nodes.Add(anim.Name);
                animations.Add(anim.Name, sa);

                if (pos != 0)
                {
                    track.Dispose();
                    track.Close();
                }

                f.skip(len - 4);
                f.align(32);
                pos = f.pos();
            }

            return(animations);
        }
Example #5
0
                public void Read(FileData d)
                {
                    hash = d.readInt();
                    unk1 = d.readInt();

                    int s = d.readByte();

                    name = d.readString(d.pos(), s - 1);
                    d.skip(s);
                    d.align(4);
                    data = new float[0x2c];
                    for (int i = 0; i < 0x2c; i++)
                    {
                        data[i] = d.readFloat();
                    }
                }
Example #6
0
            public void Read(FileData d)
            {
                d.skip(8); // magic and section size
                d.skip(4); // 0 padding?
                unk1 = d.readInt();
                d.skip(2); //0
                unk2 = d.readShort();

                int ssize = d.readByte();

                project = d.readString(d.pos(), ssize - 1);
                d.skip(ssize - 1);
                d.skip(6);
                unk3 = d.readShort();
                d.align(4);
                ssize     = d.readByte();
                timestamp = d.readString(d.pos(), ssize - 1);
                d.skip(ssize - 1);
                d.skip(4);
            }
Example #7
0
        /**
         * Reading and saving --------------------
         **/

        public override void Read(string filename)
        {
            FileData d = new FileData(filename);

            d.seek(0);
            d.Endian = Endianness.Little;

            format  = d.readUShort();
            unknown = d.readUShort();
            flags   = d.readInt();
            mode    = d.readInt();
            bool hasNameTable = (flags & 2) > 0;

            int polyCount = d.readInt();

            mesh     = new List <Mesh>();
            descript = new List <Descriptor>();
            List <List <int> > prim = new List <List <int> >();

            for (int i = 0; i < polyCount; i++)
            {
                if (i == 0 && mode == 1)
                {
                    Descriptor des = new Descriptor();
                    des.ReadDescription(d);
                    descript.Add(des);
                }

                Mesh m = new Mesh();
                mesh.Add(m);

                int        faceCount = d.readInt();
                List <int> prims     = new List <int>();
                prim.Add(prims);
                for (int j = 0; j < faceCount; j++)
                {
                    int        nodeCount = d.readInt();
                    List <int> nodeList  = new List <int>();
                    m.nodeList.Add(nodeList);

                    for (int k = 0; k < nodeCount; k++)
                    {
                        nodeList.Add(d.readInt()); // for a node list?
                    }
                    int primitiveCount = d.readInt();
                    prims.Add(primitiveCount);

                    if (hasNameTable)
                    {
                        int nameId = d.readInt();
                    }

                    if (mode == 0)
                    {
                        if (format == 4)
                        {
                            int[] buffer = new int[primitiveCount];
                            for (int k = 0; k < primitiveCount; k++)
                            {
                                buffer[k] = d.readUShort();
                            }
                            d.align(4);
                            List <int> buf = new List <int>();
                            buf.AddRange(buffer);
                            m.faces.Add(buf);
                        }
                        else
                        {
                            Descriptor des = new Descriptor();
                            des.ReadDescription(d);
                            descript.Add(des);
                        }
                    }
                }
            }

            if (mode == 0)
            {
                //Console.WriteLine("Extra!");
            }

            // TODO: STRING TABLE
            if (hasNameTable)
            {
                for (int i = 0; i < mesh.Count; i++)
                {
                    int index = d.readByte();
                    nameTable.Add(d.readString());
                }
            }


            if (format != 4)
            {
                d.align(32);
            }

            // Vertex Bank
            int start = d.pos();

            for (int i = 0; i < 1; i++)
            {
                if (mode == 0 || i == 0)
                {
                    Descriptor des = descript[i];

                    if (format != 4)
                    {
                        while (d.pos() < start + des.length)
                        {
                            Vertex v = new Vertex();
                            vertices.Add(v);

                            for (int k = 0; k < des.type.Length; k++)
                            {
                                d.align(2);
                                switch (des.type[k])
                                {
                                case 0:     //Position
                                    v.pos.X = readType(d, des.format[k], des.scale[k]);
                                    v.pos.Y = readType(d, des.format[k], des.scale[k]);
                                    v.pos.Z = readType(d, des.format[k], des.scale[k]);
                                    break;

                                case 1:     //Normal
                                    v.nrm.X = readType(d, des.format[k], des.scale[k]);
                                    v.nrm.Y = readType(d, des.format[k], des.scale[k]);
                                    v.nrm.Z = readType(d, des.format[k], des.scale[k]);
                                    break;

                                case 2:     //Color
                                    v.col.X = (int)(readType(d, des.format[k], des.scale[k]));
                                    v.col.Y = (int)(readType(d, des.format[k], des.scale[k]));
                                    v.col.Z = (int)(readType(d, des.format[k], des.scale[k]));
                                    v.col.W = (int)(readType(d, des.format[k], des.scale[k]));
                                    break;

                                case 3:     //Tex0
                                    v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k])));
                                    break;

                                case 4:     //Tex1
                                    v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k])));
                                    break;

                                case 5:     //Bone Index
                                    v.node.Add(d.readByte());
                                    v.node.Add(d.readByte());
                                    break;

                                case 6:     //Bone Weight
                                    v.weight.Add(readType(d, des.format[k], des.scale[k]));
                                    v.weight.Add(readType(d, des.format[k], des.scale[k]));
                                    break;
                                    //default:
                                    //    Console.WriteLine("WTF is this");
                                }
                            }
                        }
                        d.align(32);
                    }
                }

                for (int j = 0; j < mesh.Count; j++)
                {
                    foreach (int l in prim[j])
                    {
                        List <int> face = new List <int>();
                        mesh[j].faces.Add(face);
                        for (int k = 0; k < l; k++)
                        {
                            face.Add(d.readUShort());
                        }
                        d.align(32);
                    }
                }
            }

            PreRender();
        }
Example #8
0
        public void OpenMBN(FileData f)
        {
            f.Endian = Endianness.Little;
            f.seek(0);

            int format = f.readShort();

            f.skip(2);//0xFFFF
            int flags     = f.readInt();
            int mode      = f.readInt();
            int meshCount = f.readInt();

            int length = 0;

            if (mode == 1)
            {
                //One Attribute
                int count = f.readInt();
                for (int i = 0; i < count; i++)
                {
                    VertexAttribute a = new VertexAttribute();
                    a.Read(f);
                    Attributes.Add(a);
                }
                length = f.readInt();
            }

            // Get Mesh Nodes

            /*List<BCH_Mesh> meshes = new List<BCH_Mesh>();
             * foreach(BCH_Mesh m in Nodes)
             * {
             *  meshes.Add(m);
             *  foreach (BCH_Mesh m2 in m.Nodes)
             *      meshes.Add(m);
             * }*/

            for (int i = 0; i < meshCount; i++)
            {
                BCH_Mesh m = (BCH_Mesh)Nodes[i];

                int polyCount = f.readInt();
                for (int j = 0; j < polyCount; j++)
                {
                    BCH_PolyGroup pg = new BCH_PolyGroup();
                    m.Nodes.Add(pg);
                    int   nodeCount = f.readInt();
                    int[] nodeList  = new int[nodeCount];
                    pg.BoneList = (nodeList);
                    for (int k = 0; k < nodeCount; k++)
                    {
                        nodeList[k] = f.readInt();
                    }
                    pg.Count = (f.readInt());
                    if ((flags & 2) > 0)
                    {
                        f.readInt();
                    }
                }
            }


            if (format != 4)
            {
                f.align(32);
            }

            int stride = 0;

            foreach (VertexAttribute a in Attributes)
            {
                stride += _3DSGPU.getTypeSize(a.format) * _3DSGPU.getFormatSize(a.type);
            }

            // Vertex Bank
            Vertices = new Vertex[length / (stride + stride % 2)];
            for (int vi = 0; vi < Vertices.Length; vi++)
            {
                Vertex v = new Vertex();
                foreach (VertexAttribute a in Attributes)
                {
                    //f.align(2);
                    a.ReadVertex(f, ref v);
                }
                Vertices[vi] = v;
            }
            f.align(32);


            for (int i = 0; i < meshCount; i++)
            {
                BCH_Mesh m = (BCH_Mesh)Nodes[i];

                int pi = 0;
                foreach (BCH_PolyGroup pg in m.Nodes)
                {
                    pg.Text  = "Polygroup_" + pi++;
                    pg.Faces = new int[pg.Count];
                    for (int k = 0; k < pg.Count; k++)
                    {
                        pg.Faces[k] = f.readShort();
                    }
                    f.align(32);
                }
            }
        }
Example #9
0
        public void ReadNTP3(FileData d)
        {
            d.skip(0x2);
            int count = d.readShort();

            d.skip(0x8);

            int dataPtr = 0;

            for (int i = 0; i < count; i++)
            {
                Debug.WriteLine(d.pos().ToString("x"));
                NUD_Texture tex = new NUD_Texture();
                tex.type = PixelInternalFormat.Rgba32ui;

                int totalSize = d.readInt();
                d.skip(4); // padding

                int dataSize   = d.readInt();
                int headerSize = d.readShort();
                d.skip(3);
                int numMips = d.readByte();
                Debug.WriteLine(numMips);
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.width  = d.readShort();
                tex.height = d.readShort();

                d.skip(8); // padding?

                int dataOffset = d.readInt() + dataPtr + 0x10;
                d.skip(0x0C);

                int[] mipSizes = new int[numMips];

                if (numMips == 1)
                {
                    mipSizes[0] = dataSize;
                }
                else
                {
                    for (int j = 0; j < numMips; j++)
                    {
                        mipSizes[j] = d.readInt();
                    }
                }
                d.align(16);

                d.skip(0x18);
                tex.id = d.readInt();
                d.skip(4); // padding align 8

                // add mipmap data
                for (int miplevel = 0; miplevel < numMips; miplevel++)
                {
                    byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]);
                    tex.mipmaps.Add(texArray);
                    dataOffset += mipSizes[miplevel];
                }

                dataPtr += headerSize;

                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];
                            mip[t]     = mip[t + 1];
                            mip[t + 1] = mip[t + 2];
                            mip[t + 2] = mip[t + 3];
                            mip[t + 3] = t1;

                            /*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);

                /*for (int miplevel = 0; miplevel < numMips; miplevel++)
                 * {
                 *  byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]);
                 *
                 *  if (tex.getNutFormat() == 14)
                 *  {
                 *      byte[] oldArray = texArray;
                 *      for (int pos = 0; pos < mipSizes[miplevel]; pos+=4)
                 *      {
                 *
                 *          for (int p = 0; p < 4; p++)
                 *          {
                 *              if (p == 0)
                 *                  texArray[pos + 3] = oldArray[pos];
                 *              else
                 *                  texArray[pos + p - 1] = oldArray[pos + p];
                 *          }
                 *
                 *      }
                 *  }
                 *  tex.mipmaps.Add(texArray);
                 *  dataOffset += mipSizes[miplevel];
                 * }*/
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, loadImage(tex, true));
                }
            }
        }
Example #10
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);
            }
        }
Example #11
0
        public void ReadNTP3(FileData d)
        {
            d.seek(0x4);

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

            if (Version == 0x100)
            {
                count -= 1;
            }

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

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

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

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

                //It might seem that mipmapCount and pixelFormat would be shorts, but they're bytes because they stay in the same place regardless of endianness
                d.skip(1);
                byte mipmapCount = d.readByte();
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.Width  = d.readUShort();
                tex.Height = d.readUShort();
                d.skip(4);
                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;
                d.readInt();
                d.readInt();
                d.readInt();

                //The size of a single cubemap face (discounting mipmaps). I don't know why it is repeated. If mipmaps are present, this is also specified in the mipSize section anyway.
                int cmapSize1 = 0;
                int cmapSize2 = 0;
                if (isCubemap)
                {
                    cmapSize1 = d.readInt();
                    cmapSize2 = d.readInt();
                    d.skip(8);
                }

                int[] mipSizes = new int[mipmapCount];
                if (mipmapCount == 1)
                {
                    if (isCubemap)
                    {
                        mipSizes[0] = cmapSize1;
                    }
                    else
                    {
                        mipSizes[0] = dataSize;
                    }
                }
                else
                {
                    for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                    {
                        mipSizes[mipLevel] = d.readInt();
                    }
                    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

                if (Version == 0x100)
                {
                    dataOffset = d.pos();
                }

                for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                {
                    TextureSurface surface = new TextureSurface();
                    for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                    {
                        byte[] texArray = d.getSection(dataOffset, mipSizes[mipLevel]);
                        surface.mipmaps.Add(texArray);
                        dataOffset += mipSizes[mipLevel];
                    }
                    tex.surfaces.Add(surface);
                }

                if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17)
                {
                    tex.SwapChannelOrderUp();
                }

                headerPtr += headerSize;

                Nodes.Add(tex);
            }
        }
Example #12
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++;
             * }*/
        }