Beispiel #1
0
        public void WriteClassPointer <T>(BinaryWriterEx bw, T d) where T : IHavokObject
        {
            if (d == null)
            {
                bw.WriteUInt64(0);
                return;
            }

            // If we're referencing an already serialized object, add a global ref
            if (_globalLookup.ContainsKey(d))
            {
                GlobalFixup gfu = new GlobalFixup();
                gfu.Src             = (uint)bw.Position;
                gfu.DstSectionIndex = 2;
                gfu.Dst             = _globalLookup[d];
                _globalFixups.Add(gfu);
            }
            // Otherwise need to add a pending reference and mark the object for serialization
            else
            {
                if (!_pendingGlobals.ContainsKey(d))
                {
                    _pendingGlobals.Add(d, new List <uint>());
                    PushSerializationQueue();
                    _serializationQueues[_currSerializationQueue].Enqueue(d);
                    PopSerializationQueue(bw);
                    _pendingVirtuals.Add(d);
                }
                _pendingGlobals[d].Add((uint)bw.Position);
            }
            bw.WriteUInt64(0);
        }
        internal HKXSection(BinaryReaderEx br, HKXVariation variation)
        {
            SectionTag = br.ReadFixStr(19);
            br.AssertByte(0xFF);
            var AbsoluteDataStart   = br.ReadUInt32();
            var LocalFixupsOffset   = br.ReadUInt32();
            var GlobalFixupsOffset  = br.ReadUInt32();
            var VirtualFixupsOffset = br.ReadUInt32();
            var ExportsOffset       = br.ReadUInt32();
            var ImportsOffset       = br.ReadUInt32();
            var EndOffset           = br.ReadUInt32();

            // Read Data
            br.StepIn(AbsoluteDataStart);
            SectionData = br.ReadBytes((int)LocalFixupsOffset);
            br.StepOut();

            // Local fixups
            LocalFixups = new List <LocalFixup>();
            br.StepIn(AbsoluteDataStart + LocalFixupsOffset);
            for (int i = 0; i < (GlobalFixupsOffset - LocalFixupsOffset) / 8; i++)
            {
                if (br.ReadUInt32() != 0xFFFFFFFF)
                {
                    br.Position -= 4;
                    var f = new LocalFixup(br);
                    _localMap.Add(f.Src, f);
                    LocalFixups.Add(f);
                }
            }
            br.StepOut();

            // Global fixups
            GlobalFixups = new List <GlobalFixup>();
            br.StepIn(AbsoluteDataStart + GlobalFixupsOffset);
            for (int i = 0; i < (VirtualFixupsOffset - GlobalFixupsOffset) / 12; i++)
            {
                if (br.ReadUInt32() != 0xFFFFFFFF)
                {
                    br.Position -= 4;
                    var f = new GlobalFixup(br);
                    _globalMap.Add(f.Src, f);
                    GlobalFixups.Add(f);
                }
            }
            br.StepOut();

            // Virtual fixups
            VirtualFixups = new List <VirtualFixup>();
            br.StepIn(AbsoluteDataStart + VirtualFixupsOffset);
            for (int i = 0; i < (ExportsOffset - VirtualFixupsOffset) / 12; i++)
            {
                if (br.ReadUInt32() != 0xFFFFFFFF)
                {
                    br.Position -= 4;
                    var f = new VirtualFixup(br);
                    _virtualMap.Add(f.Src, f);
                    VirtualFixups.Add(f);
                }
            }
            br.StepOut();

            if (variation == HKXVariation.HKXBloodBorne || variation == HKXVariation.HKXDS3)
            {
                br.AssertUInt32(0xFFFFFFFF);
                br.AssertUInt32(0xFFFFFFFF);
                br.AssertUInt32(0xFFFFFFFF);
                br.AssertUInt32(0xFFFFFFFF);
            }
        }
Beispiel #3
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();
        }