// 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();
        }
Esempio n. 2
0
        // Methods
        public static void Read(HavokFile h, Stream fs)
        {
            var xml = XDocument.Load(fs);

            // HKPackFile
            var classVersion    = xml.Root.Attribute("classversion");
            var contentsVersion = xml.Root.Attribute("contentsversion");
            var topLevelObject  = xml.Root.Attribute("toplevelobject");

            if (classVersion == null)
            {
                throw new InvalidDataException("No classversion element could be found!");
            }

            if (contentsVersion == null)
            {
                throw new InvalidDataException("No contentsversion element could be found!");
            }

            if (topLevelObject == null)
            {
                throw new InvalidDataException("No toplevelobject element could be found!");
            }

            int.TryParse(classVersion.Value, out h.ClassVersion);
            h.ContentsVersion = contentsVersion.Value;
            h.TopLevelObject  = topLevelObject.Value;

            // HKSections
            foreach (var elem in xml.Root.Elements())
            {
                switch (elem.Name.LocalName.ToLower())
                {
                case "hksection":
                {
                    var section = ReadSection(elem, out string name);
                    h.Sections.Add(name, section);
                    break;
                }

                default:
                    Console.WriteLine(
                        "WARNING: Reading \"{0}\" within hkpackfile not yet supported!",
                        elem.Name.LocalName);
                    break;
                }
            }

            // Sub-Methods
            HavokSection ReadSection(XElement elem, out string name)
            {
                var nameAttr = elem.Attribute("name");

                if (nameAttr == null)
                {
                    throw new InvalidDataException("No name element could be found!");
                }

                name = nameAttr.Value;
                var section = new HavokSection();

                // Sub-Elements
                foreach (var subElem in elem.Elements())
                {
                    switch (subElem.Name.LocalName.ToLower())
                    {
                    case "hkobject":
                    {
                        var obj = ReadObject(subElem, out string objName);
                        section.Objects.Add(objName, obj);
                        break;
                    }

                    default:
                        Console.WriteLine(
                            "WARNING: Reading \"{0}\" within hksection not yet supported!",
                            subElem.Name.LocalName);
                        break;
                    }
                }

                return(section);
            }

            HavokObject ReadObject(XElement elem, out string name)
            {
                var obj       = new HavokObject();
                var nameAttr  = elem.Attribute("name");
                var classAttr = elem.Attribute("class");
                var sigAttr   = elem.Attribute("signature");

                name = nameAttr?.Value;
                string objClass  = classAttr?.Value;
                string signature = sigAttr?.Value;

                obj.Class     = objClass;
                obj.Signature = signature;

                // Sub-Elements
                foreach (var subElem in elem.Elements())
                {
                    switch (subElem.Name.LocalName.ToLower())
                    {
                    case "hkparam":
                    {
                        var param = ReadParameter(subElem, out string paramName);
                        obj.Parameters.Add(paramName, param);
                        break;
                    }

                    default:
                        Console.WriteLine(
                            "WARNING: Reading \"{0}\" within hksection not yet supported!",
                            subElem.Name.LocalName);
                        break;
                    }
                }

                return(obj);
            }

            HavokParam ReadParameter(XElement elem, out string paramName)
            {
                var param           = new HavokParam();
                var nameAttr        = elem.Attribute("name");
                var numElementsAttr = elem.Attribute("numelements");

                paramName         = nameAttr?.Value;
                param.NumElements = (numElementsAttr == null) ?
                                    -1 : Convert.ToInt32(numElementsAttr.Value);

                // Sub-Objects
                foreach (var subElem in elem.Elements("hkobject"))
                {
                    var obj = ReadObject(subElem, out string objName);
                    param.SubObjects.Add(obj);
                }

                // Data
                if (param.SubObjects.Count < 1)
                {
                    param.Data = elem.Value;
                }

                return(param);
            }
        }
Esempio n. 3
0
        public static void Write(HavokFile h, Stream fs)
        {
            // HKPackFile
            var root = new XElement("hkpackfile");

            root.Add(new XAttribute("classversion", h.ClassVersion));
            root.Add(new XAttribute("contentsversion", h.ContentsVersion));
            root.Add(new XAttribute("toplevelobject", h.TopLevelObject));

            // HKSections
            foreach (var section in h.Sections)
            {
                WriteSection(section.Value, section.Key);
            }

            var xml = new XDocument(root);

            xml.Save(fs);

            // Sub-Methods
            void WriteSection(HavokSection section, string name)
            {
                var elem = new XElement("hksection");

                elem.Add(new XAttribute("name", name));

                // HKObjects
                foreach (var obj in section.Objects)
                {
                    WriteObject(elem, obj.Value, obj.Key);
                }

                root.Add(elem);
            }

            void WriteObject(XElement rootElem, HavokObject obj, string name)
            {
                var elem = new XElement("hkobject");

                if (!string.IsNullOrEmpty(name))
                {
                    elem.Add(new XAttribute("name", name));
                }

                if (!string.IsNullOrEmpty(obj.Class))
                {
                    elem.Add(new XAttribute("class", obj.Class));
                }

                if (!string.IsNullOrEmpty(obj.Signature))
                {
                    elem.Add(new XAttribute("signature", obj.Signature));
                }

                // HKParams
                foreach (var param in obj.Parameters)
                {
                    WriteParameter(elem, param.Value, param.Key);
                }

                rootElem.Add(elem);
            }

            void WriteParameter(XElement rootElem, HavokParam param, string name)
            {
                var elem = new XElement("hkparam");

                if (!string.IsNullOrEmpty(name))
                {
                    elem.Add(new XAttribute("name", name));
                }

                if (param.NumElements > 0)
                {
                    elem.Add(new XAttribute("numelements", param.NumElements));
                }

                // Sub-Objects
                foreach (var subObject in param.SubObjects)
                {
                    WriteObject(elem, subObject, null);
                }

                // Elements
                if (!string.IsNullOrEmpty(param.Data))
                {
                    elem.Value = param.Data;
                }

                rootElem.Add(elem);
            }
        }
Esempio n. 4
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
            }
        }