예제 #1
0
        public override void Load(Stream fileStream)
        {
            ExtendedBinaryReader reader = new ExtendedBinaryReader(fileStream)
            {
                Offset = 0x20
            };
            long pos = 0;

            NinjaInfo = new NinjaInfo()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();
            uint NodeCount  = reader.ReadUInt32();
            uint Unknown1   = reader.ReadUInt32(); //Seems to always be 0x20 (at least in XN*s)?
            uint Unknown2   = reader.ReadUInt32(); //Footer Offset Table Start?
            uint Unknown3   = reader.ReadUInt32(); //Footer Offset Table Data Start?
            uint Unknown4   = reader.ReadUInt32(); //Footer Offset Table Length?
            uint Unknown5   = reader.ReadUInt32(); //Seems to always be 1 (at least in XN*s)?

            for (int i = 0; i < NodeCount; i++)
            {
                //Determine type of node to read
                string NextNodeName   = new string(reader.ReadChars(4));
                uint   NextNodeLength = reader.ReadUInt32();
                reader.JumpBehind(8);
                switch (NextNodeName)
                {
                case "NXTL":
                case "NZTL":
                    NinjaTextureList = ReadNinjaTextureList(reader, pos);
                    break;

                case "NXEF":
                    NinjaEffectList = ReadNinjaEffectList(reader, pos);
                    break;

                case "NXNN":
                    NinjaNodeNameList = ReadNinjaNodeNameList(reader, pos);
                    break;

                case "NXOB":
                case "NZOB":
                    NinjaObject = ReadNinjaObject(reader, pos);
                    break;

                default:
                    reader.JumpAhead(8);
                    reader.JumpAhead(NextNodeLength);
                    //Console.WriteLine($"Block {NextNodeName} Not Implemented!");
                    break;
                }
            }
        }
예제 #2
0
        public override void Load(Stream fileStream)
        {
            ExtendedBinaryReader reader = new ExtendedBinaryReader(fileStream)
            {
                Offset = 0x20
            };
            long pos = 0;

            // NINJA INFO [N*IF]
            InfoList = new NXIF()
            {
                HeaderInfoNode = new string(reader.ReadChars(4)),
                NodeLength     = reader.ReadUInt32(),
                NodeCount      = reader.ReadUInt32()
            };

            reader.JumpTo(InfoList.NodeLength + 8);

            for (int i = 0; i < InfoList.NodeCount; i++)
            {
                string nodeName   = new string(reader.ReadChars(4));
                uint   nodeLength = reader.ReadUInt32();
                reader.JumpBehind(8);
                switch (nodeName)
                {
                case "NXTL":
                case "NZTL":
                    // NINJA TEXTURE LIST [N*TL]
                    TextureList = ReadTextureList(reader, pos);
                    break;

                case "NXEF":
                    // NINJA EFFECTS [N*EF]
                    EffectList = ReadEffectList(reader, pos);
                    break;

                case "NXNN":
                    // NINJA NODE NAMES [N*NN]
                    NodeTree = ReadNodeNames(reader, pos);
                    break;

                case "NXOB":
                case "NZOB":
                    ObjectList = ReadNodes(reader, pos);
                    break;

                default:
                    reader.JumpAhead(8);
                    reader.JumpAhead(nodeLength);
                    Console.WriteLine($"Block {nodeName} Not Implemented!");
                    break;
                }
            }
        }
예제 #3
0
        public NXNN ReadNodeNames(ExtendedBinaryReader reader, long pos)
        {
            NodeTree = new NXNN()
            {
                TreeNode   = new string(reader.ReadChars(4)),
                NodeLength = reader.ReadUInt32()
            };

            pos = reader.BaseStream.Position; //Save Position
            reader.JumpTo(reader.ReadUInt32() + 4, false);
            var nodeCount = reader.ReadUInt32();

            reader.JumpTo(reader.ReadUInt32(), false);
            for (int i = 0; i < nodeCount; i++)
            {
                NodeTree node = new NodeTree();
                node.NodeIndex = reader.ReadUInt32();
                var  nameOffset = reader.ReadUInt32();
                long nodePos    = reader.BaseStream.Position; //Save Position
                reader.JumpTo(nameOffset, false);
                node.NodeName = reader.ReadNullTerminatedString();
                reader.JumpTo(nodePos);
                NodeTree.Nodes.Add(node);
            }
            reader.JumpTo(pos);
            reader.JumpAhead(NodeTree.NodeLength);
            return(NodeTree);
        }
예제 #4
0
        public NXTL ReadTextureList(ExtendedBinaryReader reader, long pos)
        {
            TextureList = new NXTL()
            {
                TextureListNode = new string(reader.ReadChars(4)),
                NodeLength      = reader.ReadUInt32()
            };

            pos = reader.BaseStream.Position; //Save Position
            reader.JumpTo(reader.ReadUInt32(), false);
            TextureList.TextureCount = reader.ReadUInt32();
            uint textureListOffset = reader.ReadUInt32();

            reader.JumpTo(textureListOffset, false);

            for (int i = 0; i < TextureList.TextureCount; i++)
            {
                reader.JumpAhead(0x4);
                uint textureNameOffset = reader.ReadUInt32();
                long texturePos        = reader.BaseStream.Position; //Save Position
                reader.JumpTo(textureNameOffset, false);
                TEXFILE tex = new TEXFILE();
                tex.Filename = reader.ReadNullTerminatedString();
                reader.JumpTo(texturePos);
                tex.Filters = reader.ReadUInt32();
                reader.JumpAhead(0x8);
                TextureList.Textures.Add(tex);
            }
            reader.JumpTo(pos);
            reader.JumpAhead(TextureList.NodeLength);
            return(TextureList);
        }
        // Methods
        public static void Read(HavokFile h, ExtendedBinaryReader reader)
        {
            // Header
            reader.JumpAhead(0x10);

            // A lot of this was gathered from the Max Havok exporter.
            byte bytesInPointer = reader.ReadByte();

            reader.IsBigEndian = !reader.ReadBoolean();
            byte reusePaddingOpt   = reader.ReadByte();
            byte emptyBaseClassOpt = reader.ReadByte();

            // We jump around a lot here, but there's not really a much cleaner way to do it.
            reader.JumpTo(8, true);
            h.UserTag      = reader.ReadUInt32();
            h.ClassVersion = reader.ReadInt32();
            reader.JumpAhead(4);

            uint  sectionsCount = reader.ReadUInt32();
            uint  unknown1      = reader.ReadUInt32();
            ulong padding1      = reader.ReadUInt64();

            uint unknown2 = reader.ReadUInt32();

            h.ContentsVersion = reader.ReadNullTerminatedString();
            reader.JumpAhead(9); // Seems to be padding

            // Sections
            for (uint i = 0; i < sectionsCount; ++i)
            {
                string sectionName = new string(reader.ReadChars(0x10));
                sectionName = sectionName.Replace("\0", string.Empty);

                // TODO
                reader.JumpAhead(0x20);
            }

            // Padding Checks
            if (padding1 != 0)
            {
                Console.WriteLine($"WARNING: Padding1 != 0 ({padding1})");
            }

            // TODO
            throw new NotImplementedException();
        }
예제 #6
0
        public NXEF ReadEffectList(ExtendedBinaryReader reader, long pos)
        {
            EffectList = new NXEF()
            {
                EffectNode = new string(reader.ReadChars(4)),
                NodeLength = reader.ReadUInt32()
            };

            pos = reader.BaseStream.Position; //Save Position
            reader.JumpTo(reader.ReadUInt32() + 4, false);
            var effectTypeCount  = reader.ReadUInt32();
            var effectTypeOffset = reader.ReadUInt32();
            var techiqueCount    = reader.ReadUInt32();
            var techniqueOffset  = reader.ReadUInt32();

            reader.JumpTo(effectTypeOffset, false);
            for (int i = 0; i < effectTypeCount; i++)
            {
                EFFFILE effFile = new EFFFILE();
                effFile.Type = reader.ReadUInt32();
                var  jumpPoint = reader.ReadUInt32();
                long effectPos = reader.BaseStream.Position; //Save Position
                reader.JumpTo(jumpPoint, false);
                effFile.Filename = reader.ReadNullTerminatedString();
                reader.JumpTo(effectPos);
                EffectList.Effects.Add(effFile);
            }
            reader.JumpTo(techniqueOffset, false);
            for (int i = 0; i < techiqueCount; i++)
            {
                TECHNAME tech = new TECHNAME();
                tech.Type   = reader.ReadUInt32();
                tech.NodeID = reader.ReadUInt32();
                var  jumpPoint = reader.ReadUInt32();
                long techPos   = reader.BaseStream.Position; //Save Position
                reader.JumpTo(jumpPoint, false);
                tech.Filename = reader.ReadNullTerminatedString();
                reader.JumpTo(techPos);
                EffectList.Techs.Add(tech);
            }
            reader.JumpTo(pos);
            reader.JumpAhead(EffectList.NodeLength);
            return(EffectList);
        }
예제 #7
0
        public NinjaTextureList ReadNinjaTextureList(ExtendedBinaryReader reader, long pos)
        {
            NinjaTextureList = new NinjaTextureList()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();

            pos = reader.BaseStream.Position; //Save Position
            uint NodeOffset = reader.ReadUInt32();

            reader.JumpTo(NodeOffset, false);

            uint TextureCount      = reader.ReadUInt32();
            uint TextureListOffset = reader.ReadUInt32();

            reader.JumpTo(TextureListOffset, false);

            for (int i = 0; i < TextureCount; i++)
            {
                uint Unknown1          = reader.ReadUInt32();        //Seems to always be 0 (at least in XN*s)? (Padding?)
                uint TextureNameOffset = reader.ReadUInt32();
                long currentPos        = reader.BaseStream.Position; //Save Position
                reader.JumpTo(TextureNameOffset, false);
                NinjaTextureFile TextureFile = new NinjaTextureFile()
                {
                    TextureName = reader.ReadNullTerminatedString()
                };
                reader.JumpTo(currentPos, true);
                TextureFile.Filters = reader.ReadUInt32();
                uint Unknown2 = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?)
                uint Unknown3 = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?)
                NinjaTextureList.TextureFiles.Add(TextureFile);
            }

            reader.JumpTo(pos, true);
            reader.JumpAhead(NodeLength);
            return(NinjaTextureList);
        }
예제 #8
0
        public NinjaNodeNameList ReadNinjaNodeNameList(ExtendedBinaryReader reader, long pos)
        {
            NinjaNodeNameList = new NinjaNodeNameList()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();

            pos = reader.BaseStream.Position; //Save Position
            uint NodeOffset = reader.ReadUInt32();

            reader.JumpTo(NodeOffset, false);

            uint Unknown1        = reader.ReadUInt32(); //Padding?
            uint NodeTableCount  = reader.ReadUInt32();
            uint NodeTableOffset = reader.ReadUInt32();

            reader.JumpTo(NodeTableOffset, false);

            for (int i = 0; i < NodeTableCount; i++)
            {
                NinjaNodeName NodeName = new NinjaNodeName()
                {
                    ID = reader.ReadUInt32()
                };
                uint NodeNameIndex = reader.ReadUInt32();
                long currentPos    = reader.BaseStream.Position; //Save Position
                reader.JumpTo(NodeNameIndex, false);
                NodeName.Name = reader.ReadNullTerminatedString();
                reader.JumpTo(currentPos, true);
                NinjaNodeNameList.NinjaNodeNames.Add(NodeName);
            }

            reader.JumpTo(pos, true);
            reader.JumpAhead(NodeLength);
            return(NinjaNodeNameList);
        }
예제 #9
0
        /// <summary>
        /// Reads a SEAnim from a stream
        /// </summary>
        /// <param name="Stream">The stream to read from</param>
        /// <returns>A SEAnim if successful, otherwise throws an error and returns null</returns>
        public static SEModel Read(Stream Stream)
        {
            // Create a new model
            var model = new SEModel();

            // Setup a new reader
            using (ExtendedBinaryReader readFile = new ExtendedBinaryReader(Stream))
            {
                // Magic
                var Magic = readFile.ReadChars(7);
                // Version
                var Version = readFile.ReadInt16();
                // Header size
                var HeaderSize = readFile.ReadInt16();
                // Check magic
                if (!Magic.SequenceEqual(new char[] { 'S', 'E', 'M', 'o', 'd', 'e', 'l' }))
                {
                    // Bad file
                    throw new Exception("Bad SEModel file, magic was invalid");
                }
                // Data present flags
                var DataPresentFlags = readFile.ReadByte();
                // Bone data present flags
                var BoneDataPresentFlags = readFile.ReadByte();
                // Mesh data present flags
                var MeshDataPresentFlags = readFile.ReadByte();

                // Read counts
                var BoneCount = readFile.ReadInt32();
                var MeshCount = readFile.ReadInt32();
                var MatCount  = readFile.ReadInt32();

                // Skip 3 reserved bytes
                readFile.BaseStream.Position += 3;

                // Read bone tag names
                List <string> BoneNames = new List <string>();
                // Loop
                for (int i = 0; i < BoneCount; i++)
                {
                    BoneNames.Add(readFile.ReadNullTermString());
                }

                // Loop and read bones
                for (int i = 0; i < BoneCount; i++)
                {
                    // Read bone flags (unused)
                    var BoneFlags = readFile.ReadByte();

                    // Read bone index
                    var ParentIndex = readFile.ReadInt32();

                    // Check for global matricies
                    Vector3    GlobalPosition = Vector3.Zero;
                    Quaternion GlobalRotation = Quaternion.Identity;
                    // Check
                    if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_GLOBAL_MATRIX))
                    {
                        GlobalPosition = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle());
                        GlobalRotation = new Quaternion(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle());
                    }

                    // Check for local matricies
                    Vector3    LocalPosition = Vector3.Zero;
                    Quaternion LocalRotation = Quaternion.Identity;
                    // Check
                    if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_LOCAL_MATRIX))
                    {
                        LocalPosition = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle());
                        LocalRotation = new Quaternion(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle());
                    }

                    // Check for scales
                    Vector3 Scale = Vector3.One;
                    // Check
                    if (Convert.ToBoolean(BoneDataPresentFlags & (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_SCALES))
                    {
                        Scale = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle());
                    }

                    // Add the bone
                    model.AddBone(BoneNames[i], ParentIndex, GlobalPosition, GlobalRotation, LocalPosition, LocalRotation, Scale);
                }

                // Loop and read meshes
                for (int i = 0; i < MeshCount; i++)
                {
                    // Make a new submesh
                    var mesh = new SEModelMesh();

                    // Read mesh flags (unused)
                    var MeshFlags = readFile.ReadByte();

                    // Read counts
                    var MatIndiciesCount      = readFile.ReadByte();
                    var MaxSkinInfluenceCount = readFile.ReadByte();
                    var VertexCount           = readFile.ReadInt32();
                    var FaceCount             = readFile.ReadInt32();

                    // Loop and read positions
                    for (int v = 0; v < VertexCount; v++)
                    {
                        mesh.AddVertex(new SEModelVertex()
                        {
                            Position = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle())
                        });
                    }

                    // Read uvlayers
                    if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_UVSET))
                    {
                        for (int v = 0; v < VertexCount; v++)
                        {
                            for (int l = 0; l < MatIndiciesCount; l++)
                            {
                                mesh.Verticies[v].UVSets.Add(new Vector2(readFile.ReadSingle(), readFile.ReadSingle()));
                            }
                        }
                    }

                    // Read normals
                    if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_NORMALS))
                    {
                        // Loop and read vertex normals
                        for (int v = 0; v < VertexCount; v++)
                        {
                            mesh.Verticies[v].VertexNormal = new Vector3(readFile.ReadSingle(), readFile.ReadSingle(), readFile.ReadSingle());
                        }
                    }

                    // Read colors
                    if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_COLOR))
                    {
                        // Loop and read colors
                        for (int v = 0; v < VertexCount; v++)
                        {
                            mesh.Verticies[v].VertexColor = new Color(readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte());
                        }
                    }

                    // Read weights
                    if (Convert.ToBoolean(MeshDataPresentFlags & (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_WEIGHTS))
                    {
                        for (int v = 0; v < VertexCount; v++)
                        {
                            // Read IDs and Values
                            for (int l = 0; l < MaxSkinInfluenceCount; l++)
                            {
                                if (BoneCount <= 0xFF)
                                {
                                    mesh.Verticies[v].Weights.Add(new SEModelWeight()
                                    {
                                        BoneIndex = readFile.ReadByte(), BoneWeight = readFile.ReadSingle()
                                    });
                                }
                                else if (BoneCount <= 0xFFFF)
                                {
                                    mesh.Verticies[v].Weights.Add(new SEModelWeight()
                                    {
                                        BoneIndex = readFile.ReadUInt16(), BoneWeight = readFile.ReadSingle()
                                    });
                                }
                                else
                                {
                                    mesh.Verticies[v].Weights.Add(new SEModelWeight()
                                    {
                                        BoneIndex = readFile.ReadUInt32(), BoneWeight = readFile.ReadSingle()
                                    });
                                }
                            }
                        }
                    }

                    // Loop and read faces
                    for (int f = 0; f < FaceCount; f++)
                    {
                        if (VertexCount <= 0xFF)
                        {
                            mesh.AddFace(readFile.ReadByte(), readFile.ReadByte(), readFile.ReadByte());
                        }
                        else if (VertexCount <= 0xFFFF)
                        {
                            mesh.AddFace(readFile.ReadUInt16(), readFile.ReadUInt16(), readFile.ReadUInt16());
                        }
                        else
                        {
                            mesh.AddFace(readFile.ReadUInt32(), readFile.ReadUInt32(), readFile.ReadUInt32());
                        }
                    }

                    // Read material reference indicies
                    for (int f = 0; f < MatIndiciesCount; f++)
                    {
                        mesh.AddMaterialIndex(readFile.ReadInt32());
                    }

                    // Add the mesh
                    model.AddMesh(mesh);
                }

                // Loop and read materials
                for (int m = 0; m < MatCount; m++)
                {
                    var mat = new SEModelMaterial();

                    // Read the name
                    mat.Name = readFile.ReadNullTermString();
                    // Read IsSimpleMaterial
                    var IsSimpleMaterial = readFile.ReadBoolean();

                    // Read the material
                    if (IsSimpleMaterial)
                    {
                        mat.MaterialData = new SEModelSimpleMaterial()
                        {
                            DiffuseMap  = readFile.ReadNullTermString(),
                            NormalMap   = readFile.ReadNullTermString(),
                            SpecularMap = readFile.ReadNullTermString()
                        };
                    }

                    // Add the material
                    model.AddMaterial(mat);
                }
            }
            // Return result
            return(model);
        }
예제 #10
0
        public const uint TAGMagic = 0x30474154; // "TAG0" in little-endian

        // Methods
        public static void Read(HavokFile h, ExtendedBinaryReader reader)
        {
            var  fs     = reader.BaseStream;
            long pos    = fs.Position;
            long endPos = pos;

            var types = new List <string>();

            reader.IsBigEndian = true;
            while (pos < fs.Length)
            {
                uint   size    = reader.ReadUInt32();
                string type    = new string(reader.ReadChars(4));
                bool   isParam = (((size & 0xC0000000) >> 24) == 0x40);

                // Remove the param marker from the beginning of the size
                if (isParam)
                {
                    size &= 0xFFFFFF;
                }

                size  -= 8;
                pos    = fs.Position;
                endPos = pos + size;

                Console.WriteLine("{0}: \"{1}\"",
                                  (isParam) ? "Parameter" : "Section",
                                  type);

                // Read based on type
                switch (type)
                {
                // SDK Version
                case "SDKV":
                    h.ContentsVersion = new string(reader.ReadChars((int)size));
                    Console.WriteLine($"Contents Version: {h.ContentsVersion}");
                    break;

                case "DATA":
                    ReadDATASection();
                    break;

                // Type Strings
                case "TSTR":
                {
                    Console.WriteLine();
                    while (fs.Position < endPos)
                    {
                        string t = reader.ReadNullTerminatedString();
                        if (string.IsNullOrEmpty(t))
                        {
                            continue;
                        }

                        Console.WriteLine(t);
                        types.Add(t);
                        // TODO
                    }
                    Console.WriteLine();
                    break;
                }

                // Type Names (??)
                case "TNAM":
                {
                    uint unknown1 = reader.ReadUInt32();
                    // TODO
                    break;
                }

                // Format Strings
                case "FSTR":
                {
                    Console.WriteLine();
                    while (fs.Position < endPos)
                    {
                        string t = reader.ReadNullTerminatedString();
                        if (string.IsNullOrEmpty(t))
                        {
                            continue;
                        }

                        Console.WriteLine(t);
                        // TODO
                    }
                    Console.WriteLine();
                    // TODO
                    break;
                }
                }

                // TODO

                // Jump ahead to the next parameter
                if (isParam)
                {
                    pos = endPos;

                    if (fs.Position != pos)
                    {
                        reader.JumpTo(pos);
                    }
                }
            }

            // Sub-Methods
            //HavokSection ReadSection()
            //{
            //    var section = new HavokSection();
            //    // TODO
            //    return section;
            //}

            void ReadDATASection()
            {
                reader.IsBigEndian = false; // TODO

                ulong unknown1 = reader.ReadUInt64();
                ulong unknown2 = reader.ReadUInt64();
                ulong unknown3 = reader.ReadUInt64();
                ulong unknown4 = reader.ReadUInt64();
                ulong unknown5 = reader.ReadUInt64();

                for (uint i = 0; i < unknown1; ++i)
                {
                    string s = reader.ReadNullTerminatedString();
                    Console.WriteLine(s);
                }
                // TODO

                // Padding Checks
                if (unknown2 != 0)
                {
                    Console.WriteLine($"WARNING: DATA Unknown2 != 0 ({unknown2})");
                }

                reader.IsBigEndian = true; // TODO
            }
        }
예제 #11
0
        // Methods
        public static List <SetObject> Read(ExtendedBinaryReader reader,
                                            Dictionary <string, SetObjectType> objectTemplates, SOBJType type)
        {
            var objs = new List <SetObject>();

            // SOBJ Header
            var sig = reader.ReadChars(4);

            if (!reader.IsBigEndian)
            {
                Array.Reverse(sig);
            }

            string sigString = new string(sig);

            if (sigString != Signature)
            {
                throw new InvalidSignatureException(Signature, sigString);
            }

            uint unknown1             = reader.ReadUInt32();
            uint objTypeCount         = reader.ReadUInt32();
            uint objTypeOffsetsOffset = reader.ReadUInt32();

            reader.JumpAhead(4);
            uint objOffsetsOffset = reader.ReadUInt32();
            uint objCount         = reader.ReadUInt32();
            uint unknown2         = reader.ReadUInt32(); // Probably just padding

            if (unknown2 != 0)
            {
                Console.WriteLine("WARNING: Unknown2 != 0! ({0})", unknown2);
            }

            uint transformsCount = reader.ReadUInt32();

            // Object Offsets
            var objOffsets = new uint[objCount];

            reader.JumpTo(objOffsetsOffset, false);

            for (uint i = 0; i < objCount; ++i)
            {
                objOffsets[i] = reader.ReadUInt32();
                objs.Add(new SetObject());
            }

            // Object Types
            reader.JumpTo(objTypeOffsetsOffset, false);

            for (uint i = 0; i < objTypeCount; ++i)
            {
                // Object Type
                string objName          = reader.GetString();
                uint   objOfTypeCount   = reader.ReadUInt32();
                uint   objIndicesOffset = reader.ReadUInt32();
                long   curTypePos       = reader.BaseStream.Position;

                // Objects
                reader.JumpTo(objIndicesOffset, false);

                for (uint i2 = 0; i2 < objOfTypeCount; ++i2)
                {
                    ushort objIndex = reader.ReadUInt16();
                    long   curPos   = reader.BaseStream.Position;
                    var    obj      = new SetObject();

                    // We do this check here so we can print an offset that's actually helpful
                    if (!objectTemplates.ContainsKey(objName))
                    {
                        Console.WriteLine("{0} \"{1}\" (Offset: 0x{2:X})! Skipping this object...",
                                          "WARNING: No object template exists for object type",
                                          objName, (objOffsets[objIndex] + reader.Offset));

                        // Object Data without a template
                        reader.JumpTo(objOffsets[objIndex], false);
                        obj = ReadObject(reader,
                                         null, objName, type);
                    }
                    else
                    {
                        // Object Data with a template
                        reader.JumpTo(objOffsets[objIndex], false);
                        obj = ReadObject(reader,
                                         objectTemplates[objName], objName, type);
                    }

                    objs[objIndex]             = obj;
                    reader.BaseStream.Position = curPos;
                }

                reader.BaseStream.Position = curTypePos;
            }
            return(objs);
        }
예제 #12
0
        public NinjaObject ReadNinjaObject(ExtendedBinaryReader reader, long pos)
        {
            NinjaObject = new NinjaObject()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();

            pos = reader.BaseStream.Position; //Save Position
            uint NodeOffset = reader.ReadUInt32();

            reader.JumpTo(NodeOffset, false);

            NinjaObject.ObjectCenter = reader.ReadVector3();
            NinjaObject.ObjectRadius = reader.ReadSingle();
            uint ObjectMaterialCount   = reader.ReadUInt32();
            uint ObjectMaterialOffset  = reader.ReadUInt32();
            uint ObjectVTXCount        = reader.ReadUInt32();
            uint ObjectVTXOffset       = reader.ReadUInt32();
            uint ObjectPrimitiveCount  = reader.ReadUInt32();
            uint ObjectPrimitiveOffset = reader.ReadUInt32();
            uint ObjectNodeCount       = reader.ReadUInt32();

            NinjaObject.ObjectMaxNodeDepth = reader.ReadUInt32();
            uint ObjectNodeOffset = reader.ReadUInt32();

            NinjaObject.ObjectMTXPAL = reader.ReadUInt32();
            uint ObjectSubObjectCount  = reader.ReadUInt32();
            uint ObjectSubObjectOffset = reader.ReadUInt32();

            NinjaObject.ObjectTextureCount = reader.ReadUInt32();

            //Materials
            reader.JumpTo(ObjectMaterialOffset, false);
            for (int i = 0; i < ObjectMaterialCount; i++)
            {
                //TO-DO: Figure out how all this fits together
                NinjaObjectMaterial ObjectMaterial = new NinjaObjectMaterial()
                {
                    MaterialType = reader.ReadUInt32()
                };
                uint MaterialOffset = reader.ReadUInt32();
                long currentPos     = reader.BaseStream.Position; //Save Position
                reader.JumpTo(MaterialOffset, false);

                ObjectMaterial.MaterialFlags = reader.ReadUInt32();
                ObjectMaterial.User          = reader.ReadUInt32();
                uint MaterialColourOffset  = reader.ReadUInt32();
                uint MaterialLogicOffset   = reader.ReadUInt32();
                uint MaterialTexDescOffset = reader.ReadUInt32();

                reader.JumpTo(MaterialColourOffset, false);
                ObjectMaterial.MaterialDiffuse  = reader.ReadVector4();
                ObjectMaterial.MaterialAmbient  = reader.ReadVector4();
                ObjectMaterial.MaterialSpecular = reader.ReadVector4();
                ObjectMaterial.MaterialEmissive = reader.ReadVector4();
                ObjectMaterial.MaterialPower    = reader.ReadSingle();

                reader.JumpTo(MaterialLogicOffset, false);
                ObjectMaterial.MaterialBlendenable   = reader.ReadUInt32();
                ObjectMaterial.MaterialSRCBlend      = reader.ReadUInt32();
                ObjectMaterial.MaterialDSTBlend      = reader.ReadUInt32();
                ObjectMaterial.MaterialBlendFactor   = reader.ReadUInt32();
                ObjectMaterial.MaterialBlendOP       = reader.ReadUInt32();
                ObjectMaterial.MaterialLogicOP       = reader.ReadUInt32();
                ObjectMaterial.MaterialAlphaEnable   = reader.ReadUInt32();
                ObjectMaterial.MaterialAlphaFunction = reader.ReadUInt32();
                ObjectMaterial.MaterialAlphaRef      = reader.ReadUInt32();
                ObjectMaterial.MaterialZCompenable   = reader.ReadUInt32();
                ObjectMaterial.MaterialZFunction     = reader.ReadUInt32();
                ObjectMaterial.MaterialZUpdateEnable = reader.ReadUInt32();

                reader.JumpTo(MaterialTexDescOffset, false);
                ObjectMaterial.TextureTexMapType  = reader.ReadUInt32();
                ObjectMaterial.TextureID          = reader.ReadUInt32();
                ObjectMaterial.TextureOffset      = reader.ReadVector2();
                ObjectMaterial.TextureBlend       = reader.ReadSingle();
                ObjectMaterial.TextureInfoPTR     = reader.ReadUInt32();
                ObjectMaterial.TextureMinFilter   = reader.ReadUInt32();
                ObjectMaterial.TextureMagFilter   = reader.ReadUInt32();
                ObjectMaterial.TextureMipMapBias  = reader.ReadSingle();
                ObjectMaterial.TextureMaxMipLevel = reader.ReadUInt32();

                reader.JumpTo(currentPos, true);
                NinjaObject.ObjectMaterialList.Add(ObjectMaterial);
            }

            //Vertexes
            reader.JumpTo(ObjectVTXOffset, false);
            for (int i = 0; i < ObjectVTXCount; i++)
            {
                NinjaObjectVertex ObjectVertex = new NinjaObjectVertex()
                {
                    Type = reader.ReadUInt32()
                };
                uint VTXOffset  = reader.ReadUInt32();
                long currentPos = reader.BaseStream.Position; //Save Position

                reader.JumpTo(VTXOffset, false);
                ObjectVertex.VTXFormat = reader.ReadUInt32();
                ObjectVertex.VTXFVF    = reader.ReadUInt32();
                ObjectVertex.VTXSize   = reader.ReadUInt32();
                uint VTXNumber     = reader.ReadUInt32();
                uint VTXListOffset = reader.ReadUInt32();
                ObjectVertex.VTXBlendNum = reader.ReadUInt32();
                uint VTXMTXOffset = reader.ReadUInt32();
                ObjectVertex.VTXHDRCommon = reader.ReadUInt32();
                ObjectVertex.VTXHDRData   = reader.ReadUInt32();
                ObjectVertex.VTXHDRLock   = reader.ReadUInt32();

                reader.JumpTo(VTXListOffset, false);
                for (int v = 0; v < VTXNumber; v++)
                {
                    NinjaObjectVertexList Vertex = new NinjaObjectVertexList();
                    switch (ObjectVertex.VTXSize)
                    {
                    //Any ones other than 52 & 76 are probably wrong here, as they're not in the XTO and are instead based on the MaxScript
                    //This is such a mess
                    case 20:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 24:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 28:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 32:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 36:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 44:
                        Vertex.Position  = reader.ReadVector3();
                        Vertex.Normals   = reader.ReadVector3();
                        Vertex.RGBA8888  = reader.ReadBytes(4);
                        Vertex.ST0       = reader.ReadVector2();
                        Vertex.UnknownV2 = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 48:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 52:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.MTXIDX   = reader.ReadBytes(4);
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 60:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.Tan      = reader.ReadVector3();
                        Vertex.BNormal  = reader.ReadVector3();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 72:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.MTXIDX   = reader.ReadBytes(4);
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.ST0      = reader.ReadVector2();
                        Vertex.Tan      = reader.ReadVector3();
                        Vertex.BNormal  = reader.ReadVector3();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    case 76:
                        Vertex.Position = reader.ReadVector3();
                        Vertex.Weight3  = reader.ReadVector3();
                        Vertex.MTXIDX   = reader.ReadBytes(4);
                        Vertex.Normals  = reader.ReadVector3();
                        Vertex.RGBA8888 = reader.ReadBytes(4);
                        Vertex.ST0      = reader.ReadVector2();
                        Vertex.Tan      = reader.ReadVector3();
                        Vertex.BNormal  = reader.ReadVector3();
                        ObjectVertex.Vertexes.Add(Vertex);
                        break;

                    default:
                        Console.WriteLine($"Vertex Size of {ObjectVertex.VTXSize} not handled!");
                        continue;
                    }
                }

                if (VTXMTXOffset != 0)
                {
                    reader.JumpTo(VTXMTXOffset, false);
                    ObjectVertex.VTXMTX = reader.ReadInt32();
                }

                reader.JumpTo(currentPos, true);
                NinjaObject.ObjectVertexList.Add(ObjectVertex);
            }

            reader.JumpTo(ObjectPrimitiveOffset, false);
            for (int i = 0; i < ObjectPrimitiveCount; i++)
            {
                NinjaObjectPrimitive ObjectPrimitive = new NinjaObjectPrimitive()
                {
                    Type = reader.ReadUInt32()
                };
                uint PrimitiveListOffset = reader.ReadUInt32();
                long currentPos          = reader.BaseStream.Position; //Save Position

                reader.JumpTo(PrimitiveListOffset, false);
                ObjectPrimitive.Format = reader.ReadUInt32();
                ObjectPrimitive.Index  = reader.ReadUInt32();
                ObjectPrimitive.Strip  = reader.ReadUInt32();
                uint LengthOffset = reader.ReadUInt32();
                uint IndexOffset  = reader.ReadUInt32();
                ObjectPrimitive.IndexBuf = reader.ReadUInt32();

                reader.JumpTo(LengthOffset, false);
                ObjectPrimitive.IndexLength = reader.ReadUInt16(); //May be the same as Index all the time???

                reader.JumpTo(IndexOffset, false);
                for (int v = 0; v < ObjectPrimitive.Index; v++)
                {
                    ObjectPrimitive.VertexIndexList.Add(reader.ReadUInt16());
                }

                reader.JumpTo(currentPos, true);
                NinjaObject.ObjectPrimitiveList.Add(ObjectPrimitive);
            }

            reader.JumpTo(ObjectNodeOffset, false);
            for (int i = 0; i < ObjectNodeCount; i++)
            {
                NinjaObjectNodeList Node = new NinjaObjectNodeList()
                {
                    Type      = reader.ReadUInt32(),
                    Matrix    = reader.ReadUInt16(),
                    Parent    = reader.ReadUInt16(),
                    Child     = reader.ReadUInt16(),
                    Sibling   = reader.ReadUInt16(),
                    Transform = reader.ReadVector3(),
                    Rotation  = reader.ReadVector3(),
                    Scale     = reader.ReadVector3()
                };
                for (int v = 0; v < 16; v++)
                {
                    Node.Invinit.Add(reader.ReadSingle());
                }
                Node.Center = reader.ReadVector3();
                Node.User   = reader.ReadUInt32();
                Node.RSV0   = reader.ReadUInt32();
                Node.RSV1   = reader.ReadUInt32();
                Node.RSV2   = reader.ReadUInt32();
                reader.JumpAhead(0x4);
                NinjaObject.ObjectNodeList.Add(Node);
            }

            reader.JumpTo(ObjectSubObjectOffset, false);
            for (int i = 0; i < ObjectSubObjectCount; i++)
            {
                uint Type           = reader.ReadUInt32();
                uint NMSST          = reader.ReadUInt32();
                uint MSSTOffset     = reader.ReadUInt32();
                uint Textures       = reader.ReadUInt32();
                uint TexturesOffset = reader.ReadUInt32();
                long currentPos     = reader.BaseStream.Position; //Save Position

                reader.JumpTo(MSSTOffset, false);
                for (int v = 0; v < NMSST; v++)
                {
                    NinjaObjectSubObject SubObject = new NinjaObjectSubObject()
                    {
                        Center     = reader.ReadVector3(),
                        Radius     = reader.ReadSingle(),
                        Node       = reader.ReadUInt32(),
                        Matrix     = reader.ReadUInt32(),
                        Material   = reader.ReadUInt32(),
                        VertexList = reader.ReadUInt32(),
                        PrimList   = reader.ReadUInt32(),
                        ShaderList = reader.ReadUInt32()
                    };
                    NinjaObject.ObjectSubObjectList.Add(SubObject);
                }

                reader.JumpTo(currentPos, true);
            }

            reader.JumpTo(pos, true);
            reader.JumpAhead(NodeLength);
            return(NinjaObject);
        }
예제 #13
0
        public NinjaEffectList ReadNinjaEffectList(ExtendedBinaryReader reader, long pos)
        {
            NinjaEffectList = new NinjaEffectList()
            {
                NodeName = new string(reader.ReadChars(4))
            };
            uint NodeLength = reader.ReadUInt32();

            pos = reader.BaseStream.Position; //Save Position
            uint NodeOffset = reader.ReadUInt32();

            reader.JumpTo(NodeOffset, false);

            uint Unknown1           = reader.ReadUInt32(); //Seems to always be 0 (at least in XN*s)? (Padding?)
            uint EffectTypeCount    = reader.ReadUInt32();
            uint EffectTypeOffset   = reader.ReadUInt32();
            uint TechniqueCount     = reader.ReadUInt32();
            uint TechniqueOffset    = reader.ReadUInt32();
            uint TechniqueIDXCount  = reader.ReadUInt32();
            uint TechniqueIDXOffset = reader.ReadUInt32();

            //Effect Files
            reader.JumpTo(EffectTypeOffset, false);
            for (int i = 0; i < EffectTypeCount; i++)
            {
                NinjaEffectFile EffectFile = new NinjaEffectFile()
                {
                    Type = reader.ReadUInt32()
                };
                uint EffectFilenameOffset = reader.ReadUInt32();
                long currentPos           = reader.BaseStream.Position; //Save Position
                reader.JumpTo(EffectFilenameOffset, false);
                EffectFile.Filename = reader.ReadNullTerminatedString();
                reader.JumpTo(currentPos, true);
                NinjaEffectList.EffectFiles.Add(EffectFile);
            }

            //Effect List
            reader.JumpTo(TechniqueOffset, false);
            for (int i = 0; i < TechniqueCount; i++)
            {
                NinjaEffectTechnique Technique = new NinjaEffectTechnique()
                {
                    Type = reader.ReadUInt32(),
                    ID   = reader.ReadUInt32()
                };
                uint TechniqueNameOffset = reader.ReadUInt32();
                long currentPos          = reader.BaseStream.Position; //Save Position
                reader.JumpTo(TechniqueNameOffset, false);
                Technique.TechniqueName = reader.ReadNullTerminatedString();
                reader.JumpTo(currentPos, true);
                NinjaEffectList.Techniques.Add(Technique);
            }

            //Technique IDX (not sure what this is for)
            reader.JumpTo(TechniqueIDXOffset, false);
            for (int i = 0; i < TechniqueIDXCount; i++)
            {
                NinjaEffectList.TechniqueIDX.Add(reader.ReadUInt16());
            }

            reader.JumpTo(pos, true);
            reader.JumpAhead(NodeLength);
            return(NinjaEffectList);
        }
예제 #14
0
        public NXOB ReadNodes(ExtendedBinaryReader reader, long pos)
        {
            /*
             * Sonic 4 Decompilation Ref
             * public NNS_NODE( AppMain.NNS_NODE node )
             * {
             *  this.fType = node.fType;
             *  this.iMatrix = node.iMatrix;
             *  this.iParent = node.iParent;
             *  this.iChild = node.iChild;
             *  this.iSibling = node.iSibling;
             *  this.Translation.Assign( node.Translation );
             *  this.Rotation = node.Rotation;
             *  this.Scaling.Assign( node.Scaling );
             *  this.InvInitMtx.Assign( node.InvInitMtx );
             *  this.Center.Assign( node.Center );
             *  this.Radius = node.Radius;
             *  this.User = node.User;
             *  this.SIIKBoneLength = node.SIIKBoneLength;
             *  this.BoundingBoxY = node.BoundingBoxY;
             *  this.BoundingBoxZ = node.BoundingBoxZ;
             * }
             */
            ObjectList = new NXOB()
            {
                ObjectList = new string(reader.ReadChars(4)),
                NodeLength = reader.ReadUInt32()
            };

            pos = reader.BaseStream.Position; //Save Position
            reader.JumpTo(reader.ReadUInt32(), false);
            reader.JumpAhead(0x10);

            //Variable Names Copy & Pasted from MaxScript
            var TexElmTotal  = reader.ReadUInt32();
            var TexElmOffset = reader.ReadUInt32();

            var VertGroupTotal  = reader.ReadUInt32();
            var VertGroupOffset = reader.ReadUInt32();

            var PolyElmTotal  = reader.ReadUInt32();
            var PolyElmOffset = reader.ReadUInt32();

            //Nodes
            var NodeTotal     = reader.ReadUInt32();
            var UnknownCount1 = reader.ReadUInt32(); //Count of SOMETHING?
            var NodeOffset    = reader.ReadUInt32();

            var UnknownCount2 = reader.ReadUInt32(); //MaxScript calls this NodeTotal, but I'm sure what they call BoneTotal is actually NodeTotal? Seems to be a Count of something
            var LinkTotal     = reader.ReadUInt32();
            var LinkOffset    = reader.ReadUInt32();
            var UnknownCount3 = reader.ReadUInt32(); //Count of SOMETHING?

            //NNS_NODE
            reader.JumpTo(NodeOffset, false);
            for (int i = 0; i < NodeTotal; i++)
            {
                Node node = new Node();
                node.NODE_TYPE    = reader.ReadUInt32();
                node.NODE_MATRIX  = reader.ReadUInt16();
                node.NODE_PARENT  = reader.ReadUInt16();
                node.NODE_CHILD   = reader.ReadUInt16();
                node.NODE_SIBLING = reader.ReadUInt16();

                for (int n = 0; n < 3; n++)
                {
                    node.NODE_TRN.Add(reader.ReadSingle());
                }

                for (int n = 0; n < 3; n++)
                {
                    node.NODE_ROT.Add(reader.ReadSingle());
                }

                for (int n = 0; n < 3; n++)
                {
                    node.NODE_SCL.Add(reader.ReadSingle());
                }

                for (int n = 0; n < 16; n++)
                {
                    node.NODE_INVINIT_MTX.Add(reader.ReadSingle());
                }

                for (int n = 0; n < 3; n++)
                {
                    node.NODE_CENTER.Add(reader.ReadSingle());
                }

                node.NODE_RADIUS = reader.ReadSingle();
                node.NODE_USER   = reader.ReadUInt32();
                node.NODE_RSV0   = reader.ReadUInt32();
                node.NODE_RSV1   = reader.ReadUInt32();
                node.NODE_RSV2   = reader.ReadUInt32();
                ObjectList.Nodes.Add(node);
            }

            reader.JumpTo(TexElmOffset, false);
            var Unknown1 = reader.ReadUInt32(); //Assume this is a count???

            reader.JumpTo(reader.ReadUInt32(), false);

            return(ObjectList);
        }