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); }
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)); } }
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); }
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); }
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); }
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); }
// 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); } }
/// <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); } }