コード例 #1
0
 internal void Write(BinaryWriterEx bw)
 {
     bw.BigEndian = BigEndian;
     bw.WriteASCII("BDF4");
     bw.WriteBoolean(Flag1);
     bw.WriteBoolean(Flag2);
     bw.WriteByte(0);
     bw.WriteByte(0);
     bw.WriteInt32(0x10000);
     bw.WriteInt32(0);
     bw.WriteInt64(Unk1);
     bw.WriteFixStr(Timestamp, 8);
     bw.WriteInt64(0);
     bw.WriteInt64(0);
 }
コード例 #2
0
 public void WriteHeader(BinaryWriterEx bw, HKX.HKXVariation variation)
 {
     bw.WriteFixStr(SectionTag, 19);
     bw.WriteByte(0xFF);
     bw.ReserveUInt32("absoffset" + SectionID);
     bw.ReserveUInt32("locoffset" + SectionID);
     bw.ReserveUInt32("globoffset" + SectionID);
     bw.ReserveUInt32("virtoffset" + SectionID);
     bw.ReserveUInt32("expoffset" + SectionID);
     bw.ReserveUInt32("impoffset" + SectionID);
     bw.ReserveUInt32("endoffset" + SectionID);
     if (variation == HKX.HKXVariation.HKXBloodBorne || variation == HKX.HKXVariation.HKXDS3)
     {
         bw.WriteUInt32(0xFFFFFFFF);
         bw.WriteUInt32(0xFFFFFFFF);
         bw.WriteUInt32(0xFFFFFFFF);
         bw.WriteUInt32(0xFFFFFFFF);
     }
 }
コード例 #3
0
            internal void Write(BinaryWriterEx bw, List <BinderFile> files)
            {
                bw.BigEndian = BigEndian;
                bw.WriteASCII("BHF4");
                bw.WriteBoolean(Flag1);
                bw.WriteBoolean(Flag2);
                bw.WriteByte(0);
                bw.WriteByte(0);
                bw.WriteInt32(0x10000);
                bw.WriteInt32(files.Count);
                bw.WriteInt64(0x40);
                bw.WriteFixStr(Timestamp, 8);
                bw.WriteInt64(Binder.FileHeaderSize(Format));
                bw.WriteInt64(0);

                bw.WriteBoolean(Unicode);
                bw.WriteByte((byte)Format);
                bw.WriteByte(Extended);
                bw.WriteByte(0);

                bw.WriteInt32(0);
                if (Extended == 4)
                {
                    bw.ReserveInt64("HashGroups");
                }
                else
                {
                    bw.WriteInt64(0);
                }

                for (int i = 0; i < files.Count; i++)
                {
                    FileHeader.Write(bw, files[i], i, Format);
                }

                for (int i = 0; i < files.Count; i++)
                {
                    BinderFile file = files[i];
                    bw.FillUInt32($"FileName{i}", (uint)bw.Position);
                    if (Unicode)
                    {
                        bw.WriteUTF16(file.Name, true);
                    }
                    else
                    {
                        bw.WriteShiftJIS(file.Name, true);
                    }
                }

                if (Extended == 4)
                {
                    uint groupCount = 0;
                    for (uint p = (uint)files.Count / 7; p <= 100000; p++)
                    {
                        if (SFUtil.IsPrime(p))
                        {
                            groupCount = p;
                            break;
                        }
                    }

                    if (groupCount == 0)
                    {
                        throw new InvalidOperationException("Hash group count not determined in BXF4.");
                    }

                    var hashLists = new List <PathHash> [groupCount];
                    for (int i = 0; i < groupCount; i++)
                    {
                        hashLists[i] = new List <PathHash>();
                    }

                    for (int i = 0; i < files.Count; i++)
                    {
                        var  pathHash = new PathHash(i, files[i].Name);
                        uint group    = pathHash.Hash % groupCount;
                        hashLists[group].Add(pathHash);
                    }

                    for (int i = 0; i < groupCount; i++)
                    {
                        hashLists[i].Sort((ph1, ph2) => ph1.Hash.CompareTo(ph2.Hash));
                    }

                    var hashGroups = new List <HashGroup>();
                    var pathHashes = new List <PathHash>();

                    int count = 0;
                    foreach (List <PathHash> hashList in hashLists)
                    {
                        int index = count;
                        foreach (PathHash pathHash in hashList)
                        {
                            pathHashes.Add(pathHash);
                            count++;
                        }

                        hashGroups.Add(new HashGroup(index, count - index));
                    }

                    bw.Pad(0x8);
                    bw.FillInt64("HashGroups", bw.Position);
                    bw.ReserveInt64("PathHashes");
                    bw.WriteUInt32(groupCount);
                    bw.WriteInt32(0x00080810);

                    foreach (HashGroup hashGroup in hashGroups)
                    {
                        hashGroup.Write(bw);
                    }

                    // No padding after section 1
                    bw.FillInt64("PathHashes", bw.Position);
                    foreach (PathHash pathHash in pathHashes)
                    {
                        pathHash.Write(bw);
                    }
                }
            }
コード例 #4
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();
        }