public void Read(PackFileDeserializer hkx, HKXSection section, BinaryReaderEx br, HKX.HKXVariation variation)
 {
     ClassNames          = new List <HKXClassName>();
     OffsetClassNamesMap = new Dictionary <uint, HKXClassName>();
     while (br.ReadByte() != 0xFF)
     {
         br.Position -= 1;
         uint stringStart = (uint)br.Position + 5;
         var  className   = new HKXClassName(br);
         ClassNames.Add(className);
         OffsetClassNamesMap.Add(stringStart, className);
         if (br.Position == br.Length)
         {
             break;
         }
     }
 }
Exemple #2
0
        public void Serialize(IHavokObject rootObject, BinaryWriterEx bw)
        {
            // Hardcoded for DS3 for now
            bw.BigEndian = false;
            bw.WriteUInt32(0x57E0E057); // magic 1
            bw.WriteUInt32(0x10C0C010); // magic 2
            bw.WriteInt32(0);           // User tag
            bw.WriteInt32(0x0B);        // DS3 havok
            bw.WriteByte(8);            // Pointer size
            bw.WriteByte(1);            // Little endian
            bw.WriteByte(0);            // Padding option
            bw.WriteByte(1);            // Base class?
            bw.WriteInt32(3);           // Always 3 sections

            // Hardcoded content stuff for now?
            bw.WriteInt32(2);                           // Content section index
            bw.WriteInt32(0);                           // Content section offset
            bw.WriteInt32(0);                           // Content class name section index
            bw.WriteInt32(0x4B);                        // Content class name section offset
            bw.WriteFixStr("hk_2014.1.0-r1", 16, 0xFF); // Version string
            bw.WriteInt32(0);                           // Flags
            bw.WriteInt16(21);                          // Unk
            bw.WriteInt16(16);                          // section offset
            bw.WriteInt32(20);                          // Unk
            bw.WriteInt32(0);                           // Unk
            bw.WriteInt32(0);                           // Unk
            bw.WriteInt32(0);                           // Unk

            // Initialize bookkeeping structures
            //_serializationQueue = new Queue<IHavokObject>();
            //_serializationQueue.Enqueue(rootObject);
            _serializationQueues = new List <Queue <IHavokObject> >();
            _serializationQueues.Add(new Queue <IHavokObject>());
            _serializationQueues[0].Enqueue(rootObject);
            _serializedObjects = new HashSet <IHavokObject>();
            _pendingVirtuals   = new HashSet <IHavokObject>();
            _pendingVirtuals.Add(rootObject);
            _virtualTableLookup = new Dictionary <string, uint>();
            _virtualFixups      = new List <VirtualFixup>();
            _localWriteQueues   = new List <Queue <Action> >();
            _localWriteQueues.Add(new Queue <Action>());
            _localFixups = new List <LocalFixup>();

            // Memory stream for writing all the class definitions
            MemoryStream   classms = new MemoryStream();
            BinaryWriterEx classbw = new BinaryWriterEx(false, classms);

            // Data memory stream for havok objects
            MemoryStream   datams = new MemoryStream();
            BinaryWriterEx databw = new BinaryWriterEx(false, datams);

            // Populate class names with some stuff havok always has
            HKXClassName hkclass = new HKXClassName();

            hkclass.ClassName = "hkClass";
            hkclass.Signature = 0x33D42383;
            hkclass.Write(classbw);
            hkclass.ClassName = "hkClassMember";
            hkclass.Signature = 0xB0EFA719;
            hkclass.Write(classbw);
            hkclass.ClassName = "hkClassEnum";
            hkclass.Signature = 0x8A3609CF;
            hkclass.Write(classbw);
            hkclass.ClassName = "hkClassEnumItem";
            hkclass.Signature = 0xCe6F8A6C;
            hkclass.Write(classbw);

            while (_serializationQueues.Count > 1 || _serializationQueues[0].Count > 0)
            {
                var sq = _serializationQueues.Last();
                while (sq != null && sq.Count() == 0 && _serializationQueues.Count > 1)
                {
                    if (_serializationQueues.Count > 1)
                    {
                        _serializationQueues.RemoveAt(_serializationQueues.Count - 1);
                    }
                    sq = _serializationQueues.Last();
                }
                if (sq.Count == 0)
                {
                    continue;
                }
                var obj = sq.Dequeue();
                _currSerializationQueue = _serializationQueues.Count - 1;

                if (_serializedObjects.Contains(obj))
                {
                    continue;
                }
                // See if we need to add virtual bookkeeping
                if (_pendingVirtuals.Contains(obj))
                {
                    _pendingVirtuals.Remove(obj);
                    var classname = obj.GetType().Name;
                    if (!_virtualTableLookup.ContainsKey(classname))
                    {
                        // Need to create a new class name entry and record the position
                        HKXClassName cname = new HKXClassName();
                        cname.ClassName = classname;
                        cname.Signature = obj.Signature;
                        uint offset = (uint)classbw.Position;
                        cname.Write(classbw);
                        _virtualTableLookup.Add(classname, offset + 5);
                    }
                    // Create a new Virtual fixup for this object
                    var vfu = new VirtualFixup();
                    vfu.Src          = (uint)databw.Position;
                    vfu.SectionIndex = 0;
                    vfu.NameOffset   = _virtualTableLookup[classname];
                    _virtualFixups.Add(vfu);

                    // See if we have any pending global references to this object
                    if (_pendingGlobals.ContainsKey(obj))
                    {
                        // If so, create all the needed global fixups
                        foreach (var src in _pendingGlobals[obj])
                        {
                            var gfu = new GlobalFixup();
                            gfu.Src             = src;
                            gfu.Dst             = (uint)databw.Position;
                            gfu.DstSectionIndex = 2;
                            _globalFixups.Add(gfu);
                        }
                        _pendingGlobals.Remove(obj);
                    }

                    // Add global lookup
                    _globalLookup.Add(obj, (uint)databw.Position);
                }
                obj.Write(this, databw);
                _serializedObjects.Add(obj);
                databw.Pad(16);

                // Write local data (such as array contents and strings)
                while (_localWriteQueues.Count > 1 || _localWriteQueues[0].Count > 0)
                {
                    var q = _localWriteQueues.Last();
                    while (q != null && q.Count() == 0 && _localWriteQueues.Count > 1)
                    {
                        if (_localWriteQueues.Count > 1)
                        {
                            _localWriteQueues.RemoveAt(_localWriteQueues.Count - 1);
                        }
                        q = _localWriteQueues.Last();

                        // Do alignment at the popping of a queue frame
                        databw.Pad(16);
                    }
                    if (q.Count == 0)
                    {
                        continue;
                    }
                    var act = q.Dequeue();
                    _currWriteQueue = _localWriteQueues.Count - 1;
                    act.Invoke();
                }
                databw.Pad(16);
            }

            HKXSection classNames = new HKXSection();

            classNames.SectionID   = 0;
            classNames.SectionTag  = "__classnames__";
            classNames.SectionData = classms.ToArray();
            classNames.WriteHeader(bw, HKX.HKXVariation.HKXDS3);

            HKXSection types = new HKXSection();

            types.SectionID   = 1;
            types.SectionTag  = "__types__";
            types.SectionData = new byte[0];
            types.WriteHeader(bw, HKX.HKXVariation.HKXDS3);

            HKXSection data = new HKXSection();

            data.SectionID     = 2;
            data.SectionTag    = "__data__";
            data.SectionData   = datams.ToArray();
            data.VirtualFixups = _virtualFixups;
            data.GlobalFixups  = _globalFixups.OrderBy((x) => x.Src).ToList();
            data.LocalFixups   = _localFixups.OrderBy((x) => x.Dst).ToList();
            data.WriteHeader(bw, HKX.HKXVariation.HKXDS3);

            classNames.WriteData(bw);
            types.WriteData(bw);
            data.WriteData(bw);

            classms.Close();
            datams.Close();
        }