Пример #1
0
        public BRTI(FileData f) //Docs thanks to gdkchan!!
        {
            ImageKey         = "texture";
            SelectedImageKey = "texture";

            f.skip(4);

            int  BRTISize1 = f.readInt();
            long BRTISize2 = (f.readInt() | f.readInt() << 32);

            surf = new Swizzle.Surface();

            surf.tileMode = (sbyte)f.readByte();
            surf.dim      = (sbyte)f.readByte();
            ushort Flags = (ushort)f.readShort();

            surf.swizzle = (ushort)f.readShort();
            surf.numMips = (ushort)f.readShort();
            uint unk18 = (uint)f.readInt();

            surf.format = (uint)f.readInt();
            DataType    = (byte)(surf.format & 0xFF);
            uint unk20 = (uint)f.readInt();

            surf.width  = f.readInt();
            surf.height = f.readInt();
            surf.depth  = f.readInt();
            int FaceCount = f.readInt();

            surf.sizeRange = f.readInt();
            uint unk38 = (uint)f.readInt();
            uint unk3C = (uint)f.readInt();
            uint unk40 = (uint)f.readInt();
            uint unk44 = (uint)f.readInt();
            uint unk48 = (uint)f.readInt();
            uint unk4C = (uint)f.readInt();

            surf.imageSize = f.readInt();
            surf.alignment = f.readInt();
            int ChannelType = f.readInt();
            int TextureType = f.readInt();

            Text = f.readString((f.readInt() | f.readInt() << 32) + BNTX.temp + 2, -1);
            long ParentOffset = f.readInt() | f.readInt() << 32;
            long PtrsOffset   = f.readInt() | f.readInt() << 32;

            format = surf.format;

            f.seek((int)PtrsOffset + BNTX.temp);
            long dataOff = f.readInt() | f.readInt() << 32;

            surf.data = f.getSection((int)dataOff + BNTX.temp, surf.imageSize);
            //Console.WriteLine(surf.data.Length + " " + dataOff.ToString("x") + " " + surf.imageSize);

            uint blk_dim = Formats.blk_dims(surf.format >> 8);

            blkWidth  = blk_dim >> 4;
            blkHeight = blk_dim & 0xF;

            bpp = Formats.bpps(surf.format >> 8);

            //     Console.WriteLine($"{Name} Height {surf.height}wdith = {surf.width}allignment = {surf.alignment}blkwidth = {blkWidth}blkheight = {blkHeight}blkdims = {blk_dim} format = {surf.format} datatype = {DataType} dataoffset = {dataOff}");


            // byte[] result = surf.data;



            byte[] result = Swizzle.deswizzle((uint)surf.width, (uint)surf.height, blkWidth, blkHeight, bpp, (uint)surf.tileMode, (uint)surf.alignment, surf.sizeRange, surf.data, 0);


            uint width  = Swizzle.DIV_ROUND_UP((uint)surf.width, blkWidth);
            uint height = Swizzle.DIV_ROUND_UP((uint)surf.height, blkHeight);

            result_ = new byte[width * height * bpp];

            Array.Copy(result, 0, result_, 0, width * height * bpp);

            byte[] Swizzled = Swizzle.swizzle((uint)surf.width, (uint)surf.height, blkWidth, blkHeight, bpp, (uint)surf.tileMode, (uint)surf.alignment, surf.sizeRange, surf.data, 1);


            texture.data   = result_;
            texture.width  = surf.width;
            texture.height = surf.height;

            Width  = surf.width;
            Height = surf.height;

            texture.mipmaps.Add(result_);
            texture.mipMapCount = surf.numMips;

            switch (surf.format >> 8)
            {
            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC1):
                texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC2):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SRGB)
                {
                    texture.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext;
                }
                else
                {
                    throw new Exception("Unsupported data type for BC2");
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC3):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SRGB)
                {
                    texture.pixelInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext;
                }
                else
                {
                    throw new Exception("Unsupported data type for BC3");
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC4):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    texture.pixelInternalFormat = PixelInternalFormat.CompressedRedRgtc1;
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SNORM)
                {
                    texture.pixelInternalFormat = PixelInternalFormat.CompressedSignedRedRgtc1;
                }
                else
                {
                    throw new Exception("Unsupported data type for BC4");
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC5):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    texture.pixelInternalFormat = PixelInternalFormat.CompressedRgRgtc2;
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SNORM)
                {
                    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;
                }
                else
                {
                    Console.WriteLine("Unsupported data type for BC5");
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC7):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM || DataType == (byte)Formats.BNTXImageTypes.SRGB)
                {
                    texture.pixelInternalFormat = PixelInternalFormat.CompressedRgbaBptcUnorm;
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_R8_G8_B8_A8):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM || DataType == (byte)Formats.BNTXImageTypes.SRGB)
                {
                    texture.pixelInternalFormat = PixelInternalFormat.Rgba;
                    texture.pixelFormat         = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                }
                else
                {
                    throw new Exception("Unsupported data type for R8_G8_B8_A8");
                }
                break;
            }

            RenderableTex.Add(texture);
        }
Пример #2
0
 public void Read(FileData f)
 {
     Unk1  = f.readInt();
     Depth = f.readShort();
     Unk2  = f.readShort();
 }
Пример #3
0
        /**
         * Reading and saving --------------------
         **/

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

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

            format = d.readShort();
            unkown = (ushort)d.readShort();
            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.readShort();
                            }
                            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.readShort());
                        }
                        d.align(32);
                    }
                }
            }

            PreRender();
        }
Пример #4
0
        public override void Read(string filename)
        {
            FileData f = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;
            f.skip(4);
            int backwardCompatibility = f.readByte();
            int forwardCompatibility  = f.readByte();
            int version = f.readShort();

            int mainHeaderOffset   = f.readInt();
            int stringTableOffset  = f.readInt();
            int gpuCommandsOffset  = f.readInt();
            int dataOffset         = f.readInt();
            int dataExtendedOffset = 0;
            int dataExtendedLength = 0;

            if (backwardCompatibility > 0x20)
            {
                dataExtendedOffset = f.readInt();
            }
            int relocationTableOffset = f.readInt();

            int mainHeaderLength  = f.readInt();
            int stringTableLength = f.readInt();
            int gpuCommandsLength = f.readInt();
            int dataLength        = f.readInt();

            if (backwardCompatibility > 0x20)
            {
                dataExtendedLength = f.readInt();
            }
            int relocationTableLength = f.readInt();

            int uninitializedDataSectionLength        = f.readInt();
            int uninitializedDescriptionSectionLength = f.readInt();

            if (backwardCompatibility > 7)
            {
                int flags        = f.readShort();
                int addressCount = f.readShort();
            }

            // Relocation table
            for (int i = 0; i < relocationTableLength; i += 4)
            {
                f.seek(relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + mainHeaderOffset);
                    f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + mainHeaderOffset);
                    f.writeInt((off) + mainHeaderOffset, f.readInt() + stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + mainHeaderOffset);
                    f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + mainHeaderOffset);
                    f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + dataOffset);
                    break;
                }

                f.seek((off * 4) + gpuCommandsOffset);
                if (backwardCompatibility < 6)
                {
                    switch (flag)
                    {
                    case 0x23: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex

                    //case 0x26: f.writeInt((off * 4) + int gpuCommandsOffset, ((f.readInt() + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (backwardCompatibility < 8)
                {
                    switch (flag)
                    {
                    case 0x24: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex

                    //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (backwardCompatibility < 0x21)
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex

                    //case 0x28: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x29: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex relative to Data Offset

                    //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset
                    case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset

                    case 0x2b: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataExtendedOffset); break;        //Vertex relative to Data Extended Offset

                    //case 0x2c: writer.Write(((peek(input) + int dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset
                    case 0x2d: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataExtendedOffset) & 0x7fffffff); break;     //Index 8 bits mode relative to Data Extended Offset
                    }
                }
            }

            //File.WriteAllBytes(filename + "_offset", f.getSection(0, f.size()));

            f.seek(mainHeaderOffset);
            int modelsPointerTableOffset        = f.readInt();
            int modelsPointerTableEntries       = f.readInt();
            int modelsNameOffset                = f.readInt();
            int materialsPointerTableOffset     = f.readInt();
            int materialsPointerTableEntries    = f.readInt();
            int materialsNameOffset             = f.readInt();
            int shadersPointerTableOffset       = f.readInt();
            int shadersPointerTableEntries      = f.readInt();
            int shadersNameOffset               = f.readInt();
            int texturesPointerTableOffset      = f.readInt();
            int texturesPointerTableEntries     = f.readInt();
            int texturesNameOffset              = f.readInt();
            int materialsLUTPointerTableOffset  = f.readInt();
            int materialsLUTPointerTableEntries = f.readInt();
            int materialsLUTNameOffset          = f.readInt();
            int lightsPointerTableOffset        = f.readInt();
            int lightsPointerTableEntries       = f.readInt();
            int lightsNameOffset                = f.readInt();
            int camerasPointerTableOffset       = f.readInt();
            int camerasPointerTableEntries      = f.readInt();
            int camerasNameOffset               = f.readInt();
            int fogsPointerTableOffset          = f.readInt();
            int fogsPointerTableEntries         = f.readInt();
            int fogsNameOffset = f.readInt();
            int skeletalAnimationsPointerTableOffset    = f.readInt();
            int skeletalAnimationsPointerTableEntries   = f.readInt();
            int skeletalAnimationsNameOffset            = f.readInt();
            int materialAnimationsPointerTableOffset    = f.readInt();
            int materialAnimationsPointerTableEntries   = f.readInt();
            int materialAnimationsNameOffset            = f.readInt();
            int visibilityAnimationsPointerTableOffset  = f.readInt();
            int visibilityAnimationsPointerTableEntries = f.readInt();
            int visibilityAnimationsNameOffset          = f.readInt();
            int lightAnimationsPointerTableOffset       = f.readInt();
            int lightAnimationsPointerTableEntries      = f.readInt();
            int lightAnimationsNameOffset           = f.readInt();
            int cameraAnimationsPointerTableOffset  = f.readInt();
            int cameraAnimationsPointerTableEntries = f.readInt();
            int cameraAnimationsNameOffset          = f.readInt();
            int fogAnimationsPointerTableOffset     = f.readInt();
            int fogAnimationsPointerTableEntries    = f.readInt();
            int fogAnimationsNameOffset             = f.readInt();
            int scenePointerTableOffset             = f.readInt();
            int scenePointerTableEntries            = f.readInt();
            int sceneNameOffset = f.readInt();

            Console.WriteLine(modelsPointerTableEntries > 0 ? "Has Models" : "");
            Console.WriteLine(shadersPointerTableEntries > 0 ? "Has Shaders" : "");
            Console.WriteLine(texturesPointerTableEntries > 0 ? "Has Textures" : "");
            Console.WriteLine(materialsPointerTableEntries > 0 ? "Has Materials" : "");
            Console.WriteLine(materialsLUTPointerTableEntries > 0 ? "Has Material LUT" : "");
            Console.WriteLine(materialAnimationsPointerTableEntries > 0 ? "Has Material Animation" : "");
            Console.WriteLine(lightsPointerTableEntries > 0 ? "Has Lights" : "");
            Console.WriteLine(lightAnimationsPointerTableEntries > 0 ? "Has LightAnimations" : "");
            Console.WriteLine(camerasPointerTableEntries > 0 ? "Has Camera" : "");
            Console.WriteLine(cameraAnimationsPointerTableEntries > 0 ? "Has CameraAnimation" : "");
            Console.WriteLine(fogsPointerTableEntries > 0 ? "Has Fog" : "");
            Console.WriteLine(fogAnimationsPointerTableEntries > 0 ? "Has FogAnimation" : "");
            Console.WriteLine(skeletalAnimationsPointerTableEntries > 0 ? "Has Skeletal Animations" : "");
            Console.WriteLine(visibilityAnimationsPointerTableEntries > 0 ? "Has Visibility" : "");
            Console.WriteLine(scenePointerTableEntries > 0 ? "Has Scene" : "");

            // Textures
            for (int index = 0; index < texturesPointerTableEntries; index++)
            {
                f.seek(texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset);

                // one for each mip I assume
                int textureCommandsOffset     = f.readInt();
                int textureCommandsWordCount  = f.readInt();
                int textureCommandsOffset2    = f.readInt();
                int textureCommandsWordCount2 = f.readInt();
                int textureCommandsOffset3    = f.readInt();
                int textureCommandsWordCount3 = f.readInt();

                int unk = f.readInt();

                BCH_Texture tex = new BCH_Texture();
                tex.Text = f.readString(f.readInt(), -1);
                Textures.Nodes.Add(tex);

                f.seek(textureCommandsOffset);
                tex.ReadParameters(f, textureCommandsWordCount);
            }


            //Models

            for (int index = 0; index < modelsPointerTableEntries; index++)
            {
                f.seek(modelsPointerTableOffset + (index * 4));

                f.seek(f.readInt());

                BCH_Model model = new BCH_Model();
                Models.Nodes.Add(model);
                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readShort();
                model.worldTransform            = new OpenTK.Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                                     , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                                     , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                                     , 0, 0, 0, 1);

                int materialsTableOffset  = f.readInt();
                int materialsTableEntries = f.readInt();
                int materialNameOffset    = f.readInt();
                int verticesTableOffset   = f.readInt();
                int verticesTableEntries  = f.readInt();
                f.skip(0x28);
                int skeletonOffset              = f.readInt();
                int skeletonEntries             = f.readInt();
                int skeletonNameOffset          = f.readInt();
                int objectsNodeVisibilityOffset = f.readInt();
                int objectsNodeCount            = f.readInt();
                model.Text = f.readString(f.readInt(), -1);
                int objectsNodeNameEntries = f.readInt();
                int objectsNodeNameOffset  = f.readInt();
                f.readInt(); //0x0
                int metaDataPointerOffset = f.readInt();

                f.seek(objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[objectsNodeNameEntries];
                f.seek(objectsNodeNameOffset);
                int rootReferenceBit = f.readInt();
                int rootLeftNode     = f.readShort();
                int rootRightNode    = f.readShort();
                int rootNameOffset   = f.readInt();

                //Console.WriteLine(rootReferenceBit.ToString("x") + " " + f.readString(rootNameOffset, -1) + " " + rootLeftNode + " " + rootRightNode);
                // Object name tree Radix Tree
                for (int i = 0; i < objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = (short)f.readShort();
                    short rightNode    = (short)f.readShort();
                    objectName[i] = f.readString(f.readInt(), -1);
                    Console.WriteLine((referenceBit >> 3) + " " + (referenceBit & 0x7) + " " + objectName[i] + " " + leftNode + " " + rightNode);
                }

                //TODO: Metadata, boundingbox, normal mesh, materials
                f.seek(verticesTableOffset);
                Dictionary <int, BCH_Mesh> MeshIndex = new Dictionary <int, BCH_Mesh>();
                int nim = 0;
                for (int i = 0; i < verticesTableEntries; i++)
                {
                    BCH_Mesh Mesh = new BCH_Mesh();
                    Mesh.MaterialIndex = f.readShort();
                    int mflags = f.readShort();
                    int meshId = f.readShort();
                    if (!MeshIndex.ContainsKey(meshId))
                    {
                        MeshIndex.Add(meshId, Mesh);
                        Mesh.Text = nim < objectName.Length ? objectName[nim++] : i + "";
                        model.Nodes.Add(Mesh);
                    }
                    else
                    {
                        BCH_Mesh m = MeshIndex[meshId];
                        Mesh.Text = m.Text;
                        model.Nodes.Insert(model.Nodes.IndexOf(m) - 1, Mesh);
                    }

                    // node visibility TODO: finish...
                    Mesh.Checked = ((nodeVisibility & (1 << i)) > 0);

                    Mesh.renderPriority = f.readShort();

                    int vshAttBufferCommandOffset = f.readInt();
                    int vshAttBufferCommandCount  = f.readInt();
                    int faceOffset = f.readInt();
                    int faceCount  = f.readInt();
                    int vshAttBufferCommandOffsetEx = f.readInt();
                    int vshAttBufferCommandCountEx  = f.readInt();

                    Vector3 Center     = new Vector3(f.readFloat(), f.readFloat(), f.readFloat());
                    int     flagoffset = f.readInt(); // flagsOffset
                    f.skip(4);                        // 0?
                    int boundingBoxOffset = f.readInt();
                }


                //Materials
                Console.WriteLine(materialsTableOffset.ToString("x") + " " + materialsPointerTableOffset.ToString("x"));
                for (int i = 0; i < materialsTableEntries; i++)
                {
                    f.seek(materialsTableOffset + (i * 0x2c));
                    int paramOffset = f.readInt();
                    f.skip(12); // other offsets
                    int texCommandOffset = f.readInt();
                    int texCommandCount  = f.readInt();
                    int mapperOffset     = f.readInt();

                    BCH_Material mat = new BCH_Material();
                    Materials.Nodes.Add(mat);
                    mat.Text = f.readString(f.readInt(), -1);
                    Console.WriteLine(mat.Text);
                    //Console.WriteLine(f.readString(f.readInt(), -1));
                    //Console.WriteLine(f.readString(f.readInt(), -1));
                    //Console.WriteLine(f.readString(f.readInt(), -1));

                    // TODO: Parameters
                }


                //Skeleton
                f.seek(skeletonOffset);
                for (int bindex = 0; bindex < skeletonEntries; bindex++)
                {
                    Bone bone      = new Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = (short)f.readShort();
                    short boneSpace = (short)f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.Text = f.readString(f.readInt(), -1);

                    int metaDataPointerOffset2 = f.readInt();
                    if (metaDataPointerOffset2 != 0)
                    {
                        int position = f.pos();
                        f.seek(metaDataPointerOffset2);
                        //bone.userData = getMetaData(input);
                        f.seek(position);
                    }

                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();
                model.skeleton.update();
            }
        }
Пример #5
0
        public override void Read(string filename)
        {
            FileData f = new FileData(filename);

            header.magic = f.readInt();
            header.unk0  = f.readInt();

            if (header.unk0 == 0x10000000)
            {
                f.Endian = Endianness.Little;

                f.skip(f.pos() - 4);
                header.unk0 = f.readInt();
            }

            header.unk1     = f.readInt();
            header.unk2     = f.readInt();
            header.unk3     = f.readInt();
            header.unk4     = f.readInt();
            header.unk5     = f.readInt();
            header.filesize = f.readInt();
            header.unk6     = f.readInt();
            header.unk7     = f.readInt();
            header.unk8     = f.readInt();
            header.unk9     = f.readInt();
            header.unk10    = f.readInt();
            header.unk11    = f.readInt();
            header.unk12    = f.readInt();
            header.unk13    = f.readInt();

            bool done = false;

            while (!done)
            {
                int tagOffset = f.pos();

                TagType tagType = (TagType)f.readInt();
                int     tagSize = f.readInt(); // in dwords!

                switch (tagType)
                {
                case TagType.Invalid:
                {
                    // uhhh. i think there's a specific exception for this
                    throw new Exception("Malformed file");
                }

                case TagType.Symbols:
                {
                    int numSymbols = f.readInt();

                    while (Strings.Count < numSymbols)
                    {
                        int len = f.readInt();

                        Strings.Add(f.readString());
                        f.skip(4 - (f.pos() % 4));
                    }

                    break;
                }

                case TagType.Colors:
                {
                    int numColors = f.readInt();

                    for (int i = 0; i < numColors; i++)
                    {
                        AddColor(new Vector4(f.readShort() / 256f, f.readShort() / 256f, f.readShort() / 256f, f.readShort() / 256f));
                    }

                    break;
                }

                case TagType.Fonts:
                {
                    unk000A = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.UnkF00A:
                {
                    unkF00A = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.UnkF00B:
                {
                    unkF00B = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.UnkF008:
                {
                    unkF008 = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.UnkF009:
                {
                    unkF009 = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.Defines:
                {
                    Defines = new Properties2(f);
                    break;
                }

                case TagType.ActionScript:
                {
                    Actionscript = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.ActionScript2:
                {
                    Actionscript2 = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.End:
                {
                    done = true;
                    break;
                }

                case TagType.Transforms:
                {
                    int numTransforms = f.readInt();

                    for (int i = 0; i < numTransforms; i++)
                    {
                        float a = f.readFloat();
                        float b = f.readFloat();
                        float c = f.readFloat();
                        float d = f.readFloat();
                        float x = f.readFloat();
                        float y = f.readFloat();

                        var mat = new Matrix4(
                            a, b, 0, 0,
                            c, d, 0, 0,
                            0, 0, 1, 0,
                            x, y, 0, 1
                            );

                        Transforms.Add(mat);
                    }

                    break;
                }

                case TagType.Positions:
                {
                    int numPositions = f.readInt();

                    for (int i = 0; i < numPositions; i++)
                    {
                        Positions.Add(new Vector2(f.readFloat(), f.readFloat()));
                    }

                    break;
                }

                case TagType.Bounds:
                {
                    int numBounds = f.readInt();

                    for (int i = 0; i < numBounds; i++)
                    {
                        Bounds.Add(new Rect(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()));
                    }
                    break;
                }

                case TagType.Properties:
                {
                    properties = new Properties(f);
                    break;
                }

                case TagType.TextureAtlases:
                {
                    int numAtlases = f.readInt();

                    for (int i = 0; i < numAtlases; i++)
                    {
                        TextureAtlas atlas = new TextureAtlas();
                        atlas.id     = f.readInt();
                        atlas.nameId = f.readInt();
                        atlas.width  = f.readFloat();
                        atlas.height = f.readFloat();

                        Atlases.Add(atlas);
                    }

                    break;
                }

                case TagType.Shape:
                {
                    Shapes.Add(new Shape(f));
                    break;
                }

                case TagType.DynamicText:
                {
                    Texts.Add(new DynamicText(f));
                    break;
                }

                case TagType.DefineSprite:
                {
                    Sprites.Add(new Sprite(f));
                    break;
                }

                default:
                {
                    throw new NotImplementedException($"Unhandled tag id: 0x{(uint)tagType:X} @ 0x{tagOffset:X}");
                }
                }
            }
        } // Read()
Пример #6
0
        public void ReadNTP3(FileData d)
        {
            d.skip(0x2);
            int count = d.readShort();

            d.skip(0x10);

            int headerPtr = d.pos();
            int dataPtr   = 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();
                headerPtr += headerSize;

                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;
                d.skip(0x0C);

                int[] mipSizes = new int[numMips];

                if (headerSize == 0x50)
                {
                    mipSizes[0] = totalSize;
                }
                else
                {
                    for (int j = 0; j < numMips; j++)
                    {
                        mipSizes[j] = d.readInt();
                    }
                }

                // NOTE: I have no clue what these other header sizes are.
                // pls send help.
                if (headerSize > 0x60)
                {
                    d.skip(headerSize - 0x60);
                }

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

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

                dataPtr += headerSize;

                textures.Add(tex);
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, loadImage(tex));
                }
            }
        }
Пример #7
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));
                }
            }
        }
Пример #8
0
        public static SkelAnimation read(FileData d)
        {
            d.Endian = Endianness.Big;

            d.skip(4); // header OMO
            d.skip(4); // two shorts, idk

            d.skip(4); //flags?

            d.skip(2);
            int numOfBones = d.readShort();
            int frameSize  = d.readShort();
            int frameStart = d.readShort();

            int offset1 = d.readInt();
            int offset2 = d.readInt();
            int offset3 = d.readInt();

            SkelAnimation anim = new SkelAnimation();

            anim.Tag = d;
            //anim.setModel(m);

            // base frames
            // These are linked to bones somehow, hash??
            d.seek(offset1); //
            int[]     framekey = new int[numOfBones];
            KeyNode[] baseNode = new KeyNode[numOfBones];

            for (int i = 0; i < numOfBones; i++)
            {
                int flags = d.readByte();
                int tFlag = d.readByte();
                int rFlag = d.readByte();
                int sFlag = d.readByte();
                int hash  = d.readInt(); // used to find the identifying bone
                int off1  = d.readInt() + offset2;
                framekey[i] = d.readInt();

                bool hasTrans = (flags & 0x01) == 0x01;
                bool hasScale = (flags & 0x04) == 0x04;
                bool hasRot   = (flags & 0x02) == 0x02;

                KeyNode node = new KeyNode();
                baseNode[i] = node;

                node.hash = (uint)hash;

                int temp = d.pos();
                d.seek(off1);

                if (hasTrans)
                {
                    if (tFlag == 0x8)
                    { // interpolated
                        node.t_type = KeyNode.INTERPOLATED;
                        node.t      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.t2     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    else if (tFlag == 0x20)
                    {
                        node.t_type = KeyNode.CONSTANT;
                        node.t      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                }
                if (hasRot)
                {
                    if ((rFlag & 0xF) != 0x50 && (rFlag & 0xF0) != 0x70 && (rFlag & 0xF0) != 0x60 && (rFlag & 0xF0) != 0xA0)
                    {
                        //Console.WriteLine(rFlag);
                    }

                    if ((rFlag & 0xF0) == 0xA0)
                    {
                        node.r_type = 3;
                    }

                    if ((rFlag & 0xF0) == 0x50)
                    { // interpolated
                        node.r_type = KeyNode.INTERPOLATED;
                        node.rv     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.rv2    = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    if ((rFlag & 0xF0) == 0x70 || (rFlag & 0xF0) == 0x60)
                    { // constant
                        node.r_type = KeyNode.CONSTANT;
                        node.rv     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        if ((rFlag & 0xF0) == 0x60)
                        {
                            d.skip(4);
                        }
                    }
                }

                if (hasScale)
                {
                    if ((sFlag & 0xF0) == 0x80)
                    { // interpolated
                        node.s_type = KeyNode.INTERPOLATED;
                        node.s      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.s2     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    if ((rFlag & 0x0F) == 0x02 || (rFlag & 0x0F) == 0x03)
                    { // constant
                        node.s_type = KeyNode.CONSTANT;
                        node.s      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                }
                d.seek(temp);
            }


            d.seek(offset3);
            for (int i = 0; i < frameSize; i++)
            {
                KeyFrame key = new KeyFrame();
                key.frame = i;

                int off = d.pos();

                for (int j = 0; j < numOfBones; j++)
                {
                    KeyNode node = new KeyNode();

                    node.t_type = baseNode[j].t_type;
                    node.r_type = baseNode[j].r_type;
                    node.s_type = baseNode[j].s_type;

                    node.id   = baseNode[j].id;
                    node.hash = baseNode[j].hash;

                    d.seek(off + framekey[j]);

                    if (baseNode[j].t_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / 0xffff);
                        float i2 = ((float)d.readShort() / 0xffff);
                        float i3 = ((float)d.readShort() / 0xffff);

                        float x = baseNode[j].t.X + (baseNode[j].t2.X * (i1));
                        float y = baseNode[j].t.Y + (baseNode[j].t2.Y * (i2));
                        float z = baseNode[j].t.Z + (baseNode[j].t2.Z * (i3));

                        node.t = new Vector3(x, y, z);
                    }
                    else
                    {
                        node.t = baseNode[j].t;
                    }

                    if (baseNode[j].r_type == 3)
                    {
                        float i4 = ((float)d.readShort() / (0xffff));
                        float i1 = ((float)d.readShort() / (0xffff));
                        float i2 = ((float)d.readShort() / (0xffff));
                        float i3 = ((float)d.readShort() / (0xffff));

                        node.r      = new Quaternion(new Vector3(i1, i2, i3), i4);
                        node.r      = VBN.FromEulerAngles(i4 * i1, i4 * i2, i4 * i3);
                        node.r_type = KeyNode.INTERPOLATED;
                        //node.r.Normalize();
                    }
                    else
                    if (baseNode[j].r_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / (0xffff));
                        float i2 = ((float)d.readShort() / (0xffff));
                        float i3 = ((float)d.readShort() / (0xffff));

                        float x = baseNode[j].rv.X + (baseNode[j].rv2.X * (i1));
                        float y = baseNode[j].rv.Y + (baseNode[j].rv2.Y * (i2));
                        float z = baseNode[j].rv.Z + (baseNode[j].rv2.Z * (i3));

                        float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z)));

                        node.r = new Quaternion(new Vector3(x, y, z), w);
                        node.r.Normalize();
                    }
                    else
                    {
                        float x = baseNode[j].rv.X;
                        float y = baseNode[j].rv.Y;
                        float z = baseNode[j].rv.Z;

                        float w = (float)Math.Sqrt(1 - (x * x + y * y + z * z));

                        node.r = new Quaternion(baseNode[j].rv, w);
                    }

                    if (baseNode[j].s_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / (0xffff));
                        float i2 = ((float)d.readShort() / (0xffff));
                        float i3 = ((float)d.readShort() / (0xffff));

                        float x = baseNode[j].s.X + (baseNode[j].s2.X * (i1));
                        float y = baseNode[j].s.Y + (baseNode[j].s2.Y * (i2));
                        float z = baseNode[j].s.Z + (baseNode[j].s2.Z * (i3));

                        node.s = new Vector3(x, y, z);
                    }
                    else
                    {
                        node.s = baseNode[j].s;
                    }

                    key.addNode(node);
                }
                d.seek(off + frameStart);

                anim.addKeyframe(key);
            }

            return(anim);
        }
Пример #9
0
        public static Animation read(FileData d)
        {
            d.Endian = Endianness.Big;

            d.skip(4); // header OMO
            d.skip(4); // two shorts, idk

            d.skip(4); //flags?

            d.skip(2);
            int boneCount  = d.readShort();
            int frameCount = d.readShort();
            int frameSize  = d.readShort();

            int offset1 = d.readInt();  // nodeOffset
            int offset2 = d.readInt();  // interOffset
            int offset3 = d.readInt();  // keyOffset

            SkelAnimation anim = new SkelAnimation();

            anim.Tag = d;

            if (boneCount > offset2 / 0x10)
            {
                boneCount = offset2 / 0x10;
                anim.Tag  = null;
            }

            // base frames
            // These are linked to bones via hashes
            d.seek(offset1); //
            int[]     framekey = new int[boneCount];
            KeyNode[] baseNode = new KeyNode[boneCount];

            // Start positions for bones/nodes
            for (int i = 0; i < boneCount; i++)
            {
                flagsused = flagsused | d.readInt(); d.seek(d.pos() - 4);
                //Console.WriteLine(flagsused.ToString("x"));

                int flags = d.readByte();
                int tFlag = d.readByte();
                int rFlag = d.readByte();
                int sFlag = d.readByte();
                int hash  = d.readInt(); // used to find the identifying bone
                int off1  = d.readInt() + offset2;
                framekey[i] = d.readInt();

                bool hasTrans = (flags & 0x01) == 0x01;
                bool hasScale = (flags & 0x04) == 0x04;
                bool hasRot   = (flags & 0x02) == 0x02;

                KeyNode node = new KeyNode();
                baseNode[i] = node;

                node.hash = (uint)hash;

                int temp = d.pos();
                d.seek(off1);

                if (hasTrans)
                {
                    if (tFlag == 0x8)
                    { // interpolated
                        node.t_type = KeyNode.INTERPOLATED;
                        node.t      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.t2     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    else if (tFlag == 0x20)
                    {
                        node.t_type = KeyNode.CONSTANT;
                        node.t      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    else if (tFlag == 0x4)
                    {
                        // entire Vector3 provided in keyframe data i.e. KEYFRAME type
                        node.t_type = KeyNode.KEYFRAME;
                    }
                }
                if (hasRot)
                {
                    if ((rFlag & 0xF0) != 0x50 && (rFlag & 0xF0) != 0x70 && (rFlag & 0xF0) != 0x60 && (rFlag & 0xF0) != 0xA0)
                    {
                        //Console.WriteLine(rFlag);
                    }

                    if ((rFlag & 0xF0) == 0xA0)
                    {
                        // All data is in the keyframe for this type
                        node.r_type = KeyNode.COMPRESSED;
                    }

                    if ((rFlag & 0xF0) == 0x50)
                    { // interpolated
                        node.r_type = KeyNode.INTERPOLATED;
                        node.rv     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.rv2    = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }

                    if ((rFlag & 0xF0) == 0x60)
                    {
                        node.r_type  = KeyNode.KEYFRAME;
                        node.rv      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.r_extra = d.readFloat() / 65535;
                    }

                    if ((rFlag & 0xF0) == 0x70)
                    {
                        node.r_type = KeyNode.CONSTANT;
                        node.rv     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                }

                if (hasScale)
                {
                    if ((sFlag & 0xF0) == 0x80)
                    { // interpolated
                        node.s_type = KeyNode.INTERPOLATED;
                        node.s      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.s2     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    // TODO: investigate the difference between these
                    if ((rFlag & 0x0F) == 0x02 || (rFlag & 0x0F) == 0x03)
                    { // constant
                        node.s_type = KeyNode.CONSTANT;
                        node.s      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                }
                d.seek(temp);
            }

            // Interpolated type below here is always a set translation/rotation/scale
            // from the coords specified with the bone node above

            Animation a = new Animation("Anim");

            a.Tag        = anim.Tag;
            a.FrameCount = frameCount;

            d.seek(offset3);

            for (int j = 0; j < boneCount; j++)
            {
                string bid  = "";
                int    hash = -1;
                if (!MainForm.Hashes.ids.TryGetValue(baseNode[j].hash, out bid))
                {
                    hash = (int)baseNode[j].hash;
                }
                Animation.KeyNode n = new Animation.KeyNode(bid);
                n.Hash = hash;
                a.Bones.Add(n);
                n.Type = Animation.BoneType.NORMAL;

                /*foreach (ModelContainer con in Runtime.ModelContainers)
                 *  if (con.VBN != null)
                 *      bid = con.VBN.getBone(baseNode[j].hash) == null ? "" : con.VBN.getBone(baseNode[j].hash).Text;*/

                for (int i = 0; i < a.FrameCount; i++)
                {
                    d.seek(offset3 + frameSize * i + framekey[j]);

                    if (baseNode[j].t_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / 0xffff);
                        float i2 = ((float)d.readShort() / 0xffff);
                        float i3 = ((float)d.readShort() / 0xffff);

                        float x = baseNode[j].t.X + (baseNode[j].t2.X * (i1));
                        float y = baseNode[j].t.Y + (baseNode[j].t2.Y * (i2));
                        float z = baseNode[j].t.Z + (baseNode[j].t2.Z * (i3));

                        //node.t = new Vector3(x, y, z);  // Translation
                        n.XPOS.Keys.Add(new Animation.KeyFrame(x, i));
                        n.YPOS.Keys.Add(new Animation.KeyFrame(y, i));
                        n.ZPOS.Keys.Add(new Animation.KeyFrame(z, i));
                    }
                    else if (baseNode[j].t_type == KeyNode.CONSTANT)
                    {
                        //node.t = baseNode[j].t;
                        n.XPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.X, i));
                        n.YPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.Y, i));
                        n.ZPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.Z, i));
                    }
                    else if (baseNode[j].t_type == 2)
                    {
                        float x = d.readFloat();
                        float y = d.readFloat();
                        float z = d.readFloat();

                        //node.t = new Vector3(x, y, z);
                        n.XPOS.Keys.Add(new Animation.KeyFrame(x, i));
                        n.YPOS.Keys.Add(new Animation.KeyFrame(y, i));
                        n.ZPOS.Keys.Add(new Animation.KeyFrame(z, i));
                    }

                    if (baseNode[j].r_type == KeyNode.COMPRESSED)
                    {
                        // There are 64 bits present for each node of this rot type
                        // The format is: 20bits * 3 of encoded floats, and 4 bits of flags
                        // The flags describe which 3 components of the quaternion are being presented
                        int b1 = d.readByte();
                        int b2 = d.readByte();
                        int b3 = d.readByte();
                        int b4 = d.readByte();
                        int b5 = d.readByte();
                        int b6 = d.readByte();
                        int b7 = d.readByte();
                        int b8 = d.readByte();

                        // Capture 20 bits at a time of the raw data
                        int f1    = (b1 << 12) | (b2 << 4) | ((b3 & 0xF0) >> 4);
                        int f2    = ((b3 & 0xF) << 16) | (b4 << 8) | b5;
                        int f3    = (b6 << 12) | (b7 << 4) | ((b8 & 0xF0) >> 4);
                        int flags = b8 & 0xF;

                        Quaternion r = new Quaternion();
                        switch (flags)
                        {
                        case 0:      // y, z, w provided
                            r.Y = encodedRot10ToQuaternionComponent(f1);
                            r.Z = encodedRot10ToQuaternionComponent(f2);
                            r.W = encodedRot10ToQuaternionComponent(f3);

                            r.X = (float)Math.Sqrt(Math.Abs(1 - (r.Y * r.Y + r.Z * r.Z + r.W * r.W)));
                            break;

                        case 1:      // x, z, w provided
                            r.X = encodedRot10ToQuaternionComponent(f1);
                            r.Z = encodedRot10ToQuaternionComponent(f2);
                            r.W = encodedRot10ToQuaternionComponent(f3);

                            r.Y = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Z * r.Z + r.W * r.W)));
                            break;

                        case 2:      // x, y, w provided
                            r.X = encodedRot10ToQuaternionComponent(f1);
                            r.Y = encodedRot10ToQuaternionComponent(f2);
                            r.W = encodedRot10ToQuaternionComponent(f3);

                            r.Z = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.W * r.W)));
                            break;

                        case 3:      // x, y, z, provided
                            r.X = encodedRot10ToQuaternionComponent(f1);
                            r.Y = encodedRot10ToQuaternionComponent(f2);
                            r.Z = encodedRot10ToQuaternionComponent(f3);

                            r.W = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.Z * r.Z)));
                            break;

                        default:
                            Console.WriteLine("Unknown rotation type3 flags: " + flags);
                            break;
                        }
                        n.RotType = Animation.RotationType.QUATERNION;
                        n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i));
                        n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i));
                        n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i));
                        n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i));
                    }
                    else if (baseNode[j].r_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / (0xffff));
                        float i2 = ((float)d.readShort() / (0xffff));
                        float i3 = ((float)d.readShort() / (0xffff));

                        float x = baseNode[j].rv.X + (baseNode[j].rv2.X * (i1));
                        float y = baseNode[j].rv.Y + (baseNode[j].rv2.Y * (i2));
                        float z = baseNode[j].rv.Z + (baseNode[j].rv2.Z * (i3));

                        float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z)));

                        Quaternion r = new Quaternion(new Vector3(x, y, z), w);
                        r.Normalize();

                        n.RotType = Animation.RotationType.QUATERNION;
                        n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i));
                        n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i));
                        n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i));
                        n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i));
                    }
                    else if (baseNode[j].r_type == KeyNode.KEYFRAME)
                    {
                        float scale = d.readShort() * baseNode[j].r_extra;
                        float x     = baseNode[j].rv.X;
                        float y     = baseNode[j].rv.Y;
                        float z     = baseNode[j].rv.Z + scale;
                        float w     = rot6CalculateW(x, y, z);

                        Quaternion r = new Quaternion(x, y, z, w);
                        n.RotType = Animation.RotationType.QUATERNION;
                        n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i));
                        n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i));
                        n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i));
                        n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i));
                    }
                    else
                    {
                        float x = baseNode[j].rv.X;
                        float y = baseNode[j].rv.Y;
                        float z = baseNode[j].rv.Z;
                        float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z)));

                        Quaternion r = new Quaternion(baseNode[j].rv, w);
                        r.Normalize();
                        n.RotType = Animation.RotationType.QUATERNION;
                        n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i));
                        n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i));
                        n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i));
                        n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i));
                    }

                    if (baseNode[j].s_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / (0xffff));
                        float i2 = ((float)d.readShort() / (0xffff));
                        float i3 = ((float)d.readShort() / (0xffff));

                        float x = baseNode[j].s.X + (baseNode[j].s2.X * (i1));
                        float y = baseNode[j].s.Y + (baseNode[j].s2.Y * (i2));
                        float z = baseNode[j].s.Z + (baseNode[j].s2.Z * (i3));

                        //node.s = new Vector3(x, y, z);
                        n.XSCA.Keys.Add(new Animation.KeyFrame(x, i));
                        n.YSCA.Keys.Add(new Animation.KeyFrame(y, i));
                        n.ZSCA.Keys.Add(new Animation.KeyFrame(z, i));
                    }
                    else
                    {
                        //node.s = baseNode[j].s;
                        n.XSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.X, i));
                        n.YSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.Y, i));
                        n.ZSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.Z, i));
                    }
                }
            }

            return(a);
        }
Пример #10
0
        public void Read(FileData d)
        {
            d.Endian = System.IO.Endianness.Big;
            d.seek(4); // skip filesize
            int dataSize         = d.readInt();
            int offsetTableCount = d.readInt();
            int rootA            = d.readInt();
            int headerSize       = 0x20;

            int rootOffset = headerSize + dataSize + offsetTableCount * 4;

            d.seek(rootOffset);
            int figtree = d.readInt() + headerSize;

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

            this.Name = name;

            d.seek(figtree);
            d.skip(8);
            float frameCount = d.readFloat();
            int   keyOffset  = d.readInt();

            if (Debug)
            {
                Console.WriteLine(name + "\tCount: " + frameCount);
            }
            this.frameCount = (int)frameCount;

            int temp = d.pos();

            d.seek(keyOffset + 0x20);
            //int boneCount = 0x2E; // TODO: Use actual bone count 0x35
            List <int> keyFrameCount = new List <int>();
            int        bid           = d.readByte();

            while (bid != 0xFF)
            {
                keyFrameCount.Add(bid);
                bid = d.readByte();
                nodes.Add(new List <DATAnimTrack>());
            }
            int boneCount = keyFrameCount.Count;

            if (Debug)
            {
                Console.WriteLine(boneCount);
            }

            d.seek(temp);

            int animDataOffset = 0;

            int[] trackcount = new int[offsetTableCount];
            for (int i = 0; i < offsetTableCount; i++)
            {
                trackcount[i] = d.readInt();
                if (i == 0)
                {
                    animDataOffset = trackcount[i];
                }
            }

            d.seek(animDataOffset + 0x20);
            for (int i = 0; i < boneCount; i++)
            { // bonecount
                if (Debug)
                {
                    Console.WriteLine("Bone " + i + ": " + keyFrameCount[i] + "\t" + d.pos().ToString("x"));
                }

                for (int j = 0; j < keyFrameCount[i]; j++)
                {
                    int length = d.readShort();
                    d.skip(2);
                    int trackType   = d.readByte();
                    int valueFormat = d.readByte();
                    int tanFormat   = d.readByte();
                    d.skip(1);
                    int dataoff = d.readInt() + 0x20;

                    if (Debug)
                    {
                        Console.WriteLine((AnimType)trackType + "\tLength: " + length + "\tOffset: " + dataoff.ToString("x") + " " + valueFormat.ToString("x") + " " + tanFormat.ToString("x"));
                    }
                    // System.out.println(valueFormat + " " + tanFormat);
                    readKeyFrame(d, length, dataoff, valueFormat, tanFormat, keyFrameCount[i], i, trackType);
                }
            }
        }
Пример #11
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();

                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;
                }

                textures.Add(tex);
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, 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++;
             * }*/
        }
Пример #12
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));
                }
            }
        }
Пример #13
0
        public override void Read(string filename)
        {
            FileData file = new FileData(filename);

            if (file != null)
            {
                file.Endian = Endianness.Little;
                Endian      = Endianness.Little;
                string magic = file.readString(0, 4);
                if (magic == "VBN ")
                {
                    file.Endian = Endianness.Big;
                    Endian      = Endianness.Big;
                }

                file.seek(4);

                unk_1               = (short)file.readShort();
                unk_2               = (short)file.readShort();
                totalBoneCount      = (UInt32)file.readInt();
                boneCountPerType[0] = (UInt32)file.readInt();
                boneCountPerType[1] = (UInt32)file.readInt();
                boneCountPerType[2] = (UInt32)file.readInt();
                boneCountPerType[3] = (UInt32)file.readInt();

                int[] pi = new int[totalBoneCount];
                for (int i = 0; i < totalBoneCount; i++)
                {
                    Bone temp = new Bone(this);
                    temp.Text = file.readString(file.pos(), -1);
                    file.skip(64);
                    temp.boneType = (UInt32)file.readInt();
                    pi[i]         = file.readInt();
                    temp.boneId   = (UInt32)file.readInt();
                    temp.position = new float[3];
                    temp.rotation = new float[3];
                    temp.scale    = new float[3];
                    bones.Add(temp);
                }

                for (int i = 0; i < bones.Count; i++)
                {
                    bones[i].position[0] = file.readFloat();
                    bones[i].position[1] = file.readFloat();
                    bones[i].position[2] = file.readFloat();
                    bones[i].rotation[0] = file.readFloat();
                    bones[i].rotation[1] = file.readFloat();
                    bones[i].rotation[2] = file.readFloat();
                    bones[i].scale[0]    = file.readFloat();
                    bones[i].scale[1]    = file.readFloat();
                    bones[i].scale[2]    = file.readFloat();
                    Bone temp = bones[i];
                    temp.parentIndex = pi[i];
                    //Debug.Write(temp.parentIndex);
                    //if (temp.parentIndex != 0x0FFFFFFF && temp.parentIndex > -1)
                    //    bones[temp.parentIndex].children.Add(i);
                    bones[i] = temp;
                }
                reset();
            }
        }
Пример #14
0
        public void Read(FileData f)
        {
            f.Endian = Endianness.Little;
            f.seek(4);
            int count = f.readInt();

            f.skip(12);
            int dataCount  = f.readInt();
            int boneCount  = f.readInt();
            int hashCount  = f.readInt();
            int hashOffset = f.readInt() + 0x28;

            f.skip(4);

            int pos = f.pos();

            f.seek(hashOffset);

            csvHashes     csv      = new csvHashes(Path.Combine(MainForm.executableDir, "hashTable.csv"));
            List <string> bonename = new List <string>();

            for (int i = 0; i < hashCount; i++)
            {
                uint hash = (uint)f.readInt();
                for (int j = 0; j < csv.ids.Count; j++)
                {
                    if (csv.ids[j] == hash)
                    {
                        Console.WriteLine(csv.names[j]);
                        bonename.Add(csv.names[j]);
                        break;
                    }
                }
            }

            f.seek(pos);
            Console.WriteLine("Count " + count);

            for (int i = 0; i < dataCount; i++)
            {
                Console.WriteLine("Bone " + i + " start at " + f.pos().ToString("x"));
                // 3 sections
                int secLength = f.readInt();
                int someCount = f.readInt(); // usually 2?

                for (int sec = 0; sec < 5; sec++)
                {
                    int size = f.readInt();
                    int id   = f.readInt();
                    Console.WriteLine(id + ":\t" + size.ToString("x"));
                    for (int j = 0; j < ((size - 1) / 4) - 1; j++)
                    {
                        Console.Write("\t" + f.readShort() + " " + f.readShort() + "\t");
                    }
                    Console.WriteLine();
                }

                f.skip(8);
            }

            Console.WriteLine("0x" + f.pos().ToString("X"));
            f.skip(8);
            int hashSize = f.readInt();
            int unk      = f.readInt();
        }