コード例 #1
0
        private static byte[] GetUncompressedPayload(Record record)
        {
            byte[] result             = new byte[GetUncompressedPayloadSize(record)];
            MArrayPosition <byte> pos = new MArrayPosition <byte>(result);

            foreach (var field in record.Fields)
            {
                int    fieldLength       = field.Payload.Length;
                ushort storedFieldLength = unchecked ((ushort)fieldLength);
                if (fieldLength > UInt16.MaxValue)
                {
                    MBitConverter.Set(pos, XXXX);
                    pos += 4;

                    MBitConverter.Set(pos, (ushort)4);
                    pos += 2;

                    MBitConverter.Set(pos, fieldLength);
                    pos += 4;
                    storedFieldLength = 0;
                }

                MBitConverter.Set(pos, field.FieldType);
                pos += 4;

                MBitConverter.Set(pos, storedFieldLength);
                pos += 2;

                MBuffer.BlockCopy(field.Payload, 0, pos, 0, fieldLength);
                pos += fieldLength;
            }

            return(result);
        }
コード例 #2
0
        private static bool FieldsAreIdentical(B4S recordType, Field f1, Field f2)
        {
            // clear out unused bytes before doing the check.
            switch (f1.FieldType)
            {
            case _CTDA:
                if (recordType != IDLE)
                {
                    goto default;
                }

                f1 = new Field(f1);
                f2 = new Field(f2);
                MBitConverter.Set(f1.Payload, 0, (uint)f1.Payload[0]);
                MBitConverter.Set(f2.Payload, 0, (uint)f2.Payload[0]);

                MBitConverter.Set(f1.Payload, 10, (ushort)0);
                MBitConverter.Set(f2.Payload, 10, (ushort)0);

                // TODO: ugh, [IDLE:00013344]'s field is apparently allowed
                // to differ non-trivially.
                goto default;

            case _ENAM:
                if (f1.Payload.LongLength != f2.Payload.LongLength)
                {
                    return(false);
                }

                if (recordType != IDLE)
                {
                    goto default;
                }

                // ENAM is apparently case-insensitive, according to xEdit.
                f1 = new Field(f1);
                f2 = new Field(f2);

                for (long i = 0; i < f1.Payload.LongLength; i++)
                {
                    f1.Payload[i] = unchecked ((byte)(f1.Payload[i] & 0xDF));
                    f2.Payload[i] = unchecked ((byte)(f1.Payload[i] & 0xDF));
                }

                goto default;

            default:
                return(f1.Payload.SequenceEqual(f2.Payload));
            }
        }
コード例 #3
0
        private static byte[] CompressDNAM(byte[] dnamPayload)
        {
            MArrayPosition <byte> pos = new MArrayPosition <byte>(dnamPayload);

            for (int i = 0; i < dnamPayload.Length; i += 8)
            {
                ulong val = MBitConverter.To <ulong>(dnamPayload, i);
                if (val == 0)
                {
                    continue;
                }

                MBitConverter.Set(pos, val);
                pos += 8;
            }

            Array.Resize(ref dnamPayload, pos.Offset);
            return(dnamPayload);
        }
コード例 #4
0
        private unsafe byte *ConvertToIntFromLogBuffer(byte *logBuffer, ref int bufferLength, out int intValue)
        {
            switch (m_LuaSizetLength)
            {
            case 4:
                intValue = MBitConverter.ToInt32(logBuffer);
                break;

            case 8:
                intValue = (int)MBitConverter.ToInt64(logBuffer);
                break;

            default:
                throw new Exception("Not handle size_t = " + m_LuaSizetLength);
            }

            logBuffer    += m_LuaSizetLength;
            bufferLength -= m_LuaSizetLength;

            return(logBuffer);
        }
コード例 #5
0
        private static void FinalizeHeader(Record root)
        {
            var onamField = root.Fields.SingleOrDefault(f => f.FieldType == ONAM);

            if (onamField == null)
            {
                goto afterOnam;
            }

            HashSet <uint> prevOnams = Doer.GetOnams(root);
            List <uint>    currOnams = new List <uint>(prevOnams.Count);

            foreach (Record rec in Doer.FindRecords(root))
            {
                if (prevOnams.Remove(rec.Id) && (!rec.Flags.HasFlag(BethesdaRecordFlags.InitiallyDisabled) || !rec.Flags.HasFlag(BethesdaRecordFlags.PersistentReference)))
                {
                    currOnams.Add(rec.Id);
                }
            }

            uint[] onamsArray = currOnams.ToArray();
            Array.Sort(onamsArray);

            onamField.Payload = new byte[unchecked ((uint)(onamsArray.Length) * 4u)];

            MArrayPosition <byte> pos = new MArrayPosition <byte>(onamField.Payload);

            foreach (uint onam in onamsArray)
            {
                MBitConverter.Set(pos, onam);
                pos += 4;
            }

            root.CompressedFieldData = null;

afterOnam:
            MBitConverter.Set(new MArrayPosition <byte>(root.Fields.Single(f => f.FieldType == HEDR).Payload, 4), Doer.CountItems(root) - 1);
        }
コード例 #6
0
        private static BethesdaGroup Write(Group group, ref MArrayPosition <byte> pos)
        {
            MBitConverter.Set(pos, GRUP);

            BethesdaGroup grp = new BethesdaGroup(pos)
            {
                DataSize   = unchecked ((uint)(CalculateSize(group) - 24)),
                Label      = group.Label,
                GroupType  = group.GroupType,
                Stamp      = group.Stamp,
                UNKNOWN_18 = group.UNKNOWN_18,
                Version    = group.Version,
                UNKNOWN_22 = group.UNKNOWN_22
            };

            pos += 24;
            foreach (var rec in group.Records)
            {
                Write(rec, ref pos);
            }

            return(grp);
        }
コード例 #7
0
        // assumes all IDs were deleted by PerformDeletes.
        public static void PerformUDRs(Record root, Merged master, IEnumerable <uint> ids)
        {
            foreach (uint id in ids)
            {
                Record orig = master.FindRecord(id);
                orig = new Record(orig)
                {
                    Parent = orig.Parent
                };

                orig.Flags |= BethesdaRecordFlags.InitiallyDisabled;
                if (orig.RecordType == ACHR || orig.RecordType == ACRE)
                {
                    orig.Flags |= BethesdaRecordFlags.PersistentReference;
                }

                if (orig.Flags.HasFlag(BethesdaRecordFlags.PersistentReference) && orig.Parent.GroupType != BethesdaGroupType.CellPersistentChildren)
                {
                    Record wrldParent = null;

                    // persistent children of the HIGHEST cell in the world
                    while (orig.Parent != null)
                    {
                        Record rrrr = orig.Parent.Parent;
                        if (rrrr.RecordType == WRLD)
                        {
                            wrldParent = rrrr;
                        }

                        orig.Parent = rrrr.Parent;
                    }

                    orig.Parent = wrldParent.Subgroups
                                  .Single(g => g.GroupType == BethesdaGroupType.WorldChildren)
                                  .Records
                                  .Single(r => r.RecordType == CELL)
                                  .Subgroups
                                  .Single(g => g.GroupType == BethesdaGroupType.CellChildren)
                                  .Records
                                  .Single()
                                  .Subgroups
                                  .Single(g => g.GroupType == BethesdaGroupType.CellPersistentChildren);
                }

                bool isPersistent = orig.Flags.HasFlag(BethesdaRecordFlags.PersistentReference);
                if (!isPersistent)
                {
                    Field dataField = orig.Fields.Find(f => f.FieldType == DATA);
                    if (dataField == null)
                    {
                        orig.Fields.Add(dataField = new Field
                        {
                            FieldType = DATA,
                            Payload   = new byte[24]
                        });
                    }

                    MBitConverter.Set(dataField.Payload, 8, 3337248768);
                }

                Field xespField = orig.Fields.Find(f => f.FieldType == XESP);
                if (xespField == null)
                {
                    orig.Fields.Add(xespField = new Field
                    {
                        FieldType = XESP,
                        Payload   = new byte[8]
                    });
                }

                MBitConverter.Set(xespField.Payload, 0, (uint)0x14);
                MBitConverter.Set(xespField.Payload, 4, (uint)0x01);
                orig.CompressedFieldData = null;

                MergeInto(orig, root);
            }
        }
コード例 #8
0
        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="buffer">目标Buffer</param>
        /// <param name="offset">写入位置</param>
        /// <param name="enableSerializeValueType">
        /// 是否序列化<see cref="ValueType"/>
        /// 需要这个开关是因为序列化<see cref="ValueType.FixedValueTypeArray"/>时,不需要序列化数组中每个元素的<see cref="ValueType"/>
        /// </param>
        public void Serialize(byte[] buffer
                              , ref int offset
                              , bool enableSerializeValueType = true)
        {
            if (enableSerializeValueType)
            {
                MBitConverter.WriteTo(buffer, ref offset, (byte)ValueType);
            }

            switch (ValueType)
            {
            case ValueType.Byte:
                MBitConverter.WriteTo(buffer, ref offset, ByteValue);
                break;

            case ValueType.Short:
                MBitConverter.WriteTo(buffer, ref offset, ShortValue);
                break;

            case ValueType.Int:
                MBitConverter.WriteTo(buffer, ref offset, IntValue);
                break;

            case ValueType.Long:
                MBitConverter.WriteTo(buffer, ref offset, LongValue);
                break;

            case ValueType.Float:
                MBitConverter.WriteTo(buffer, ref offset, FloatValue);
                break;

            case ValueType.Double:
                MBitConverter.WriteTo(buffer, ref offset, DoubleValue);
                break;

            case ValueType.FixedValueTypeArray:
            {
                int elementCount = ArrayValue.GetSize();
                MBitConverter.WriteTo(buffer, ref offset, elementCount);
                MDebug.Assert(elementCount > 0
                              , "Rpc"
                              , "elementCount > 0");

                int        startPoint       = ArrayValue.GetOffset();
                int        endPoint         = startPoint + elementCount;
                RpcValue[] elements         = ArrayValue.GetBuffer();
                ValueType  elementValueType = elements[startPoint].ValueType;
                MBitConverter.WriteTo(buffer, ref offset, (byte)elementValueType);
                for (int iElement = startPoint; iElement < endPoint; iElement++)
                {
                    RpcValue iterElement = elements[iElement];
#if GF_DEBUG
                    MDebug.Assert(iterElement.ValueType == elementValueType
                                  , "Rpc"
                                  , "iterElement.ValueType == elementValueType");
#endif
                    iterElement.Serialize(buffer, ref offset, false);
                }
            }
            break;

            case ValueType.VariableValueTypeArray:
            {
                int elementCount = ArrayValue.GetSize();
                MBitConverter.WriteTo(buffer, ref offset, elementCount);
                MDebug.Assert(elementCount > 0
                              , "Rpc"
                              , "elementCount > 0");

                int        startPoint = ArrayValue.GetOffset();
                int        endPoint   = startPoint + elementCount;
                RpcValue[] elements   = ArrayValue.GetBuffer();
                for (int iElement = startPoint; iElement < endPoint; iElement++)
                {
                    RpcValue iterElement = elements[iElement];
                    iterElement.Serialize(buffer, ref offset);
                }
            }
            break;

            default:
                throw new Exception("Not support ValueType: " + ValueType);
            }
        }