public static void WriteStructProperty(this Stream stream, IMEPackage pcc, string propName, string structName, MemoryStream value) { stream.WritePropHeader(pcc, propName, PropertyType.StructProperty, (int)value.Length); stream.WriteValueS32(pcc.FindNameOrAdd(structName)); stream.WriteValueS32(0); stream.WriteStream(value); }
private void WriteHeader(Stream s) { s.WriteValueS32(_unknown1, Endianness); s.WriteValueS32(_itemCount, Endianness); s.WriteValueS32(_unknown2, Endianness); s.WriteValueS32(_unknown3, Endianness); }
public static void Write(Stream output, RawItem instance, Endian endian) { output.WriteValueU32(instance.Name, endian); output.WriteValueU32(instance.BaseName, endian); output.WriteValueS32(instance.Type, endian); output.WriteValueS32(instance.Purchasable, endian); output.WriteValueS32(instance.Consumable, endian); output.WriteValueS32(instance.Rewardable, endian); output.WriteValueS32(instance.Collectable, endian); output.Seek(4, SeekOrigin.Current); output.WriteValueS64(instance.FeatOffset, endian); output.WriteValueS64(instance.FeatCount, endian); output.WriteValueU32(instance.Region, endian); output.WriteValueS32(instance.RebelDropTimer, endian); output.WriteValueS32(instance.MaxInventory, endian); output.WriteValueS32(instance.UIType, endian); output.WriteValueS32(instance.UIFlag, endian); output.WriteValueS32(instance.UIDisplayOrder, endian); output.WriteValueU32(instance.UIName, endian); output.WriteValueU32(instance.UIDescription, endian); output.WriteValueU32(instance.UITypeDescription, endian); output.WriteValueU32(instance.UIFlagDescription, endian); output.WriteValueS64(instance.UIImagePathOffset, endian); output.WriteValueS64(instance.UIVideoPathOffset, endian); output.WriteValueF32(instance.UIPar0, endian); output.WriteValueF32(instance.UIPar1, endian); output.WriteValueF32(instance.UIPar2, endian); output.WriteValueF32(instance.UIPar3, endian); output.WriteValueF32(instance.UIPar4, endian); output.WriteValueU32(0, endian); // TODO(rick): proper pad }
public void Serialize(Stream output, Endian endian) { output.WriteValueU32(this.Unknown2, endian); output.WriteValueU32(this.Unknown3, endian); output.WriteValueU32(this.Unknown4, endian); output.WriteValueU64(this.Unknown5, endian); output.WriteValueS32(this.Creator.Length, endian); output.WriteString(this.Creator, Encoding.UTF8); output.WriteValueU64(this.Unknown7, endian); output.WriteValueS32(this.Author.Length, endian); output.WriteString(this.Author, Encoding.UTF8); output.WriteValueS32(this.Name.Length, endian); output.WriteString(this.Name, Encoding.UTF8); output.WriteValueU64(this.Unknown10, endian); output.Write(this.Unknown11, 0, 36); output.Write(this.Unknown12, 0, 36); output.WriteValueU32((uint)this.Size, endian); output.WriteValueU32((uint)this.Players, endian); output.WriteValueU32(this.Unknown15, endian); }
public static void WriteNoneProperty(this Stream stream, IMEPackage pcc) { //Debug.WriteLine("Writing none property at 0x" + stream.Position.ToString("X6")); stream.WriteValueS32(pcc.FindNameOrAdd("None")); stream.WriteValueS32(0); }
public static void WriteDelegateProperty(this Stream stream, IMEPackage pcc, string propName, int unk, NameReference value) { stream.WritePropHeader(pcc, propName, PropertyType.DelegateProperty, 12); stream.WriteValueS32(unk); stream.WriteValueS32(pcc.FindNameOrAdd(value.Name)); stream.WriteValueS32(value.Number); }
public static void WriteStringUnreal(this Stream stream, string value) { if (value == null || value.Length == 0) { stream.WriteValueS32(0); return; } bool isUnicode = false; // detect unicode for (int i = 0; i < value.Length; i++) { if (value[i] > 255) { isUnicode = true; break; } } if (isUnicode == true) { stream.WriteValueS32(-(value.Length + 1)); stream.WriteStringUTF16(value); stream.WriteValueU16(0); } else { stream.WriteValueS32(value.Length + 1); stream.WriteStringASCII(value); stream.WriteValueU8(0); } }
public void Serialize(Stream output) { var endian = this._Endian; byte[] metaHeaderBytes; using (var data = new MemoryStream()) { this._MetaHeader.Serialize(data, endian); data.Flush(); metaHeaderBytes = data.ToArray(); } byte[] dataBytes; { var writer = new BitWriter(0x10000); this._Data.Write(writer); dataBytes = writer.GetBytes(); } output.WriteValueU64(Signature, endian); output.WriteValueU16(1, endian); // version output.WriteValueS32(4 + metaHeaderBytes.Length, endian); output.WriteValueS32(4 + dataBytes.Length, endian); var metaHeaderCRC = Hashing.CRC32.Compute(metaHeaderBytes, 0, metaHeaderBytes.Length, 0x12345678); output.WriteValueU32(metaHeaderCRC, endian); output.WriteBytes(metaHeaderBytes); var dataCRC = Hashing.CRC32.Compute(dataBytes, 0, dataBytes.Length, 0x12345678); output.WriteValueU32(dataCRC, endian); output.WriteBytes(dataBytes); }
public void Serialize(Stream output) { ushort defaultIndex = 0; var nodes = new List <NodeHeader>(); if (this.Root != null) { SerializeNodes(this.Root, nodes); } if (this.Default != null && this.Default.Count > 0) { defaultIndex = (ushort)nodes.Count; SerializeNodes(this.Default, nodes); } var values = new List <string>(); foreach (var node in nodes) { if (node.Value != null && values.Contains(node.Value) == false) { values.Add(node.Value); } } values.Sort(); if (values.Count > 0xFFFF) { throw new InvalidOperationException(); } foreach (var node in nodes) { if (node.Value != null) { node.ValueIndex = (ushort)values.IndexOf(node.Value); } } output.WriteValueU32(0x44545442); output.WriteValueU32(1); output.WriteValueS32(nodes.Count); output.WriteValueS32(values.Count); output.WriteValueU16(defaultIndex); foreach (var node in nodes) { node.Serialize(output); } foreach (var value in values) { output.WriteValueS32Packed(value.Length); output.WriteString(value, Encoding.UTF8); } }
public static void WriteNameProperty(this Stream stream, IMEPackage pcc, string propName, NameReference value) { //Debug.WriteLine("Writing name property " + propName + ", value: " + value + " at 0x" + stream.Position.ToString("X6")); stream.WritePropHeader(pcc, propName, PropertyType.NameProperty, 8); stream.WriteValueS32(pcc.FindNameOrAdd(value.Name)); stream.WriteValueS32(value.Number); }
internal static void Write(Stream output, ItemReward instance, Endian endian) { output.WriteValueU32(instance.Item, endian); output.WriteValueS32(instance.Permanent, endian); output.WriteValueS32(instance.Duration, endian); output.WriteValueS32(instance.Quantity, endian); output.WriteValueS32(instance.Delivery, endian); }
public override void Serialize(Stream output) { output.WriteStringAlignedU8(this.Name); output.WriteValueS32(this.Language); output.WriteValueU32(this.Modulo); output.WriteValueU32(this.SizeOfBuffer); output.WriteValueS32(this.Buffer.Length); output.Write(this.Buffer, 0, this.Buffer.Length); }
public static void WriteStructProperty(this Stream stream, IMEPackage pcc, string propName, string structName, MemoryStream value) { //Debug.WriteLine("Writing struct property " + propName + ", value: " + value + " at 0x" + stream.Position.ToString("X6")); stream.WritePropHeader(pcc, propName, PropertyType.StructProperty, (int)value.Length); stream.WriteValueS32(pcc.FindNameOrAdd(structName)); stream.WriteValueS32(0); stream.WriteStream(value); }
public static void Write(Stream output, RawReward instance, Endian endian) { output.WriteValueS32(instance.Skillpoints, endian); output.WriteValueS32(instance.Chaos, endian); output.WriteValueS32(instance.ItemRewardSemantics, endian); output.Seek(4, SeekOrigin.Current); output.WriteValueS64(instance.ItemOffset, endian); output.WriteValueS64(instance.ItemCount, endian); }
public static void WriteByteProperty(this Stream stream, IMEPackage pcc, string propName, byte value) { stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 1); if (pcc.Game == MEGame.ME3) { stream.WriteValueS32(pcc.FindNameOrAdd("None")); stream.WriteValueS32(0); } stream.WriteByte(value); }
void PropertyContainerFile.IRawVariant.Serialize(Stream output, Endian endian) { var values = this._Values; output.WriteValueS32(values.Count, endian); foreach (int value in values) { output.WriteValueS32(value, endian); } }
private void WriteHeader(Stream s, int contentSize) { s.Seek(0, SeekOrigin.Begin); s.WriteBytes(_root.Header.Signature); s.WriteValueS32(contentSize + 0x60, Endianness); s.WriteValueS32(_root.Header.ContentOffset, Endianness); s.WriteValueS32(_root.Header.Unknown1, Endianness); s.WriteValueS32(_root.Header.Unknown2, Endianness); s.WriteValueS32(contentSize, Endianness); s.WriteValueS64(_root.Header.Unknown3, Endianness); }
public static void WriteByteProperty(this Stream stream, IMEPackage pcc, string propName, byte value) { //Debug.WriteLine("Writing byte property " + propName + ", value: " + value + " at 0x" + stream.Position.ToString("X6")); stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 1); if (pcc.Game == MEGame.ME3) { stream.WriteValueS32(pcc.FindNameOrAdd("None")); stream.WriteValueS32(0); } stream.WriteByte(value); }
public static void WriteEnumProperty(this Stream stream, IMEPackage pcc, string propName, string enumName, string enumValue, int index = 0) { stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 8); if (pcc.Game == MEGame.ME3) { stream.WriteValueS32(pcc.FindNameOrAdd(enumName)); stream.WriteValueS32(0); } stream.WriteValueS32(pcc.FindNameOrAdd(enumValue)); stream.WriteValueS32(index); }
public static void WriteEnumProperty(this Stream stream, IMEPackage pcc, string propName, NameReference enumName, NameReference enumValue) { stream.WritePropHeader(pcc, propName, PropertyType.ByteProperty, 8); if (pcc.Game == MEGame.ME3) { stream.WriteValueS32(pcc.FindNameOrAdd(enumName.Name)); stream.WriteValueS32(enumName.Number); } stream.WriteValueS32(pcc.FindNameOrAdd(enumValue.Name)); stream.WriteValueS32(enumValue.Number); }
public void Serialize(Stream output, Endian endian) { output.WriteValueU16((ushort)this.Name.Length, endian); output.WriteString(this.Name.Substring(0, (ushort)this.Name.Length), Encoding.ASCII); output.WriteValueU8(this.Type); output.WriteValueU8(this.Allocator); output.WriteValueU8(this.Unknown3); output.WriteValueU8(this.Unknown4); output.WriteValueS32(this.HeaderSize, endian); output.WriteValueS32(this.DataSize, endian); }
public static void Write(Stream output, RawDirectoryEntry instance, Endian endian) { output.WriteValueS32(instance.DirectoryCount, endian); output.WriteValueS32(instance.DirectoryIndex, endian); output.WriteValueS32(instance.FileCount, endian); output.WriteValueS32(instance.FileIndex, endian); output.WriteValueU32(instance.Unknown10, endian); output.WriteValueU32(instance.Unknown14, endian); output.WriteValueU32(instance.Unknown18, endian); output.WriteValueU32(instance.Unknown1C, endian); }
public static void WriteStringUnicode(this Stream stream, string value) { if (value.Length > 0) { stream.WriteValueS32(-(value.Length + 1)); stream.WriteStringZ(value, Encoding.Unicode); } else { stream.WriteValueS32(0); } }
public void Serialize(Stream output, Endian endian) { output.WriteValueU16((ushort)this.Name.Length, endian); output.WriteString(this.Name.Substring(0, (ushort)this.Name.Length), Encoding.ASCII); output.WriteValueU8(this.Type); output.WriteValueU8(this.Allocator); output.WriteValueU8((byte)this.Flags); output.WriteValueU8(this.SplitIndex); output.WriteValueS32(this.CPUSize, endian); output.WriteValueS32(this.GPUSize, endian); output.WriteValueU8(this.Unknown7); }
public override void WriteTo(Stream stream, IMEPackage pcc, bool valueOnly = false) { if (!valueOnly) { stream.WriteNameProperty(pcc, Name, Value); } else { stream.WriteValueS32(pcc.FindNameOrAdd(Value.Name)); stream.WriteValueS32(Value.Number); } }
public void Save(Stream s, byte[] originalContent, IList <TFString> strings, ExportOptions options) { WriteHeader(s, strings, options); var pointer1 = WriteData(s, strings, options); var newPointers = WriteRemainder(s, strings, options); s.Seek(8, SeekOrigin.Begin); s.WriteValueS32(pointer1, Endianness); s.Seek(4, SeekOrigin.Current); s.WriteValueS32(newPointers.Item1, Endianness); s.WriteValueS32(newPointers.Item2, Endianness); }
void PropertyContainerFile.IRawVariant.Serialize(Stream output, Endian endian) { var bytes = this._Value; if (bytes == null) { output.WriteValueS32(0, endian); return; } output.WriteValueS32(bytes.Length, endian); output.WriteBytes(bytes); }
public override void WriteTo(Stream stream, IMEPackage pcc, bool valueOnly = false) { if (!valueOnly) { stream.WriteDelegateProperty(pcc, Name, unk, Value); } else { stream.WriteValueS32(unk); stream.WriteValueS32(pcc.FindNameOrAdd(Value.Name)); stream.WriteValueS32(Value.count); } }
public void Serialize(Stream output) { var version = this.Version; if (version < 7 || version > 8) { throw new FormatException("unsupported version"); } var target = this._Target; var platform = this._Platform; var flags02 = this._Unknown70; if (target != Big.Target.Any && target != Big.Target.Win32 && target != Big.Target.Xbox360 && target != Big.Target.PS3 && target != Big.Target.WiiU && target != Big.Target.Win64) { throw new FormatException("unsupported or invalid platform"); } if (IsValidTargetPlatform(target, platform, flags02) == false) { throw new FormatException("invalid flags"); } var endian = this.Endian; output.WriteValueU32(_Signature, Endian.Little); output.WriteValueS32(version, Endian.Little); uint flags = 0; flags |= (uint)((byte)target & 0xFF) << 0; flags |= (uint)((byte)platform & 0xFF) << 8; flags |= (uint)(flags02 & 0xFF) << 16; output.WriteValueU32(flags, Endian.Little); var entrySerializer = this.GetEntrySerializer(); output.WriteValueS32(this.Entries.Count, Endian.Little); foreach (var entry in this.Entries) { entrySerializer.Serialize(output, entry, endian); } output.WriteValueU32(0, Endian.Little); }
public void Serialize(Stream output, Endian endian) { output.WriteValueU32(this.Size, endian); output.WriteValueEnum<HeaderFlags>(this.Flags, endian); output.WriteValueS32(this.Height, endian); output.WriteValueS32(this.Width, endian); output.WriteValueU32(this.PitchOrLinearSize, endian); output.WriteValueU32(this.Depth, endian); output.WriteValueU32(this.MipMapCount, endian); output.Write(this.Reserved1, 0, this.Reserved1.Length); this.PixelFormat.Serialize(output, endian); output.WriteValueU32(this.SurfaceFlags, endian); output.WriteValueU32(this.CubemapFlags, endian); output.Write(this.Reserved2, 0, this.Reserved2.Length); }
private void WriteFields(Stream s, IList <TFString> strings, ExportOptions options) { foreach (var dataField in _dataList) { s.WriteStringZ(dataField.Name, Encoding); var zeros = new byte[48 - (dataField.Name.GetLength(Encoding) + 1)]; s.WriteBytes(zeros); s.WriteValueS32(dataField.DataType, Endianness); s.WriteValueS32(dataField.DataCount, Endianness); if (dataField.DataType > 0x02) { s.WriteValueS32(dataField.DataLength, Endianness); } else { var size = 0; if (dataField.DataRemainder != null) { size += dataField.DataRemainder.Length; } foreach (var tfString in strings.Where(x => x.Section == dataField.Name)) { var writeStr = tfString.Translation; if (tfString.Original.Equals(tfString.Translation)) { writeStr = Yakuza0Project.WritingReplacements(writeStr); size += writeStr.GetLength(Encoding) + 1; } else { writeStr = Yakuza0Project.WritingReplacements(writeStr); size += writeStr.GetLength(options.SelectedEncoding) + 1; } } if (dataField.DataType == 0x02) { size += 2 * dataField.DataCount; } s.WriteValueS32(size, Endianness); } s.WriteValueS32(0); } }
public void Serialize(Stream output) { if (this.Version < 1 || this.Version > 2) { throw new InvalidOperationException("unsupported blob version"); } output.WriteValueU32(this.Version); output.WriteValueS32(this.Entries.Count); var nameLength = this.Version == 2 ? 32 : 14; foreach (var entry in this.Entries) { var name = entry.Name; if (name.Length + 1 > nameLength) { throw new InvalidOperationException(); } output.WriteString(name.PadRight(nameLength, '\0')); output.WriteValueU32((uint)entry.Offset); output.WriteValueU32(entry.Size); } }
public void Serialize(Stream output) { output.WriteValueU32(0x42494748, false); output.WriteValueU32(this.TotalFileSize, true); output.WriteValueS32(this.Entries.Count, false); output.WriteValueS32(16 + (this.Entries.Count * 12) + 8, false); foreach (var entry in this.Entries) { output.WriteValueU32(entry.Offset, false); output.WriteValueU32(entry.Size, false); output.WriteValueU32(entry.Name, false); } output.WriteValueU32(0x4C323833, false); output.WriteValueU32(0x15050000, false); }
public static void Serialize(Stream output, FieldType type, object value, bool littleEndian) { switch (type) { case FieldType.UInt8: output.WriteValueU8((byte)value); break; case FieldType.Int8: output.WriteValueS8((sbyte)value); break; case FieldType.UInt16: output.WriteValueU16((ushort)value); break; case FieldType.Int16: output.WriteValueS16((short)value); break; case FieldType.UInt32: output.WriteValueU32((uint)value); break; case FieldType.Int32: output.WriteValueS32((int)value); break; case FieldType.UInt64: output.WriteValueU64((ulong)value); break; case FieldType.Int64: output.WriteValueS64((long)value); break; case FieldType.Single: output.WriteValueF32((float)value); break; case FieldType.Double: output.WriteValueF64((double)value); break; case FieldType.Vector3: { if (value == null) { throw new ArgumentNullException(); } ((Builtins.Vector3)value).Serialize(output, littleEndian); break; } case FieldType.Vector4: { if (value == null) { throw new ArgumentNullException(); } ((Builtins.Vector4)value).Serialize(output, littleEndian); break; } case FieldType.Quaternion: { if (value == null) { throw new ArgumentNullException(); } ((Builtins.Quaternion)value).Serialize(output, littleEndian); break; } case FieldType.String: { throw new NotSupportedException("cannot serialize strings via Builtin"); } case FieldType.Color: { if (value == null) { throw new ArgumentNullException(); } ((Builtins.Color)value).Serialize(output, littleEndian); break; } case FieldType.Matrix4x4: { if (value == null) { throw new ArgumentNullException(); } ((Builtins.Matrix4x4)value).Serialize(output, littleEndian); break; } default: { throw new NotSupportedException("unsupported builtin type"); } } }
public void Serialize(Stream output) { output.WriteValueU32(0x47464620u, false); output.WriteValueU32(0x56342E30u + this.FileVersion, false); output.WriteValueEnum<GFF.FilePlatform>(this.FilePlatform, false); output.WriteValueEnum<GFF.FormatType>(this.FormatType, false); output.WriteValueU32(this.FormatVersion, false); var littleEndian = this.FilePlatform == GFF.FilePlatform.PC; output.WriteValueS32(this.Structures.Count, littleEndian); int structuresOffset = (int)output.Position + 4; int fieldsOffset = structuresOffset + (this.Structures.Count * 16); int dataOffset = fieldsOffset + (this.Structures.Sum(s => s.Fields.Count) * 12); dataOffset = dataOffset.Align(16); output.WriteValueS32(dataOffset, littleEndian); int runningFieldCount = 0; foreach (var structDef in this.Structures) { output.WriteValueU32(structDef.Id, false); output.WriteValueS32(structDef.Fields.Count, littleEndian); output.WriteValueS32(fieldsOffset + (runningFieldCount * 12), littleEndian); output.WriteValueU32(structDef.DataSize, littleEndian); runningFieldCount += structDef.Fields.Count; } foreach (var structDef in this.Structures) { foreach (var fieldDef in structDef.Fields) { output.WriteValueS32(fieldDef.Id, littleEndian); var flags = fieldDef.Flags; ushort type; if (fieldDef.Type == GFF.FieldType.Structure) { flags |= GFF.FieldFlags.IsStructure; type = fieldDef.StructureId; } else { type = (ushort)fieldDef.Type; } uint rawFlags = 0; rawFlags |= type; rawFlags |= (uint)flags << 16; output.WriteValueU32(rawFlags, littleEndian); output.WriteValueU32(fieldDef.Offset, littleEndian); } } this.Data.Position = 0; output.Seek(dataOffset, SeekOrigin.Begin); output.WriteFromStream(this.Data, this.Data.Length); }
public void Serialize(Stream output) { output.WriteValueU32(this.FileAlignment, this.LittleEndian); output.WriteString(this.BasePath, 64, Encoding.ASCII); output.WriteValueS32(this.Entries.Count, this.LittleEndian); var entries = this.Entries .OrderBy(e => e.UncompressedSize) .OrderBy(e => e.NameHash); foreach (var entry in entries) { output.WriteValueU32(entry.NameHash, this.LittleEndian); } foreach (var entry in entries) { output.WriteValueU32(entry.UncompressedSize, this.LittleEndian); output.WriteValueU32(entry.Offset, this.LittleEndian); output.WriteValueU32(entry.Locale, this.LittleEndian); output.WriteValueU32(entry.CompressedSize, this.LittleEndian); } }
public void Serialize(Stream output) { output.WriteValueU32(0x54414653, this.LittleEndian); output.WriteValueU32(this.Unknown04, this.LittleEndian); output.WriteValueU32(this.NumberOfFiles, this.LittleEndian); output.WriteValueS32(this.Entries.Count, this.LittleEndian); output.WriteValueU32(this.Unknown10, this.LittleEndian); output.WriteString(this.BasePath, 32, Encoding.ASCII); foreach (var e in this.Entries.OrderBy(e => e.NameHash)) { output.WriteValueU32(e.NameHash, this.LittleEndian); output.WriteValueU32(e.Locale, this.LittleEndian); output.WriteValueU32(e.Size, this.LittleEndian); output.WriteValueU32(e.File | e.Offset, this.LittleEndian); } }
public void Serialize(Stream output) { if (this.Version == 1) { throw new NotSupportedException(); } else if (this.Version == 2) { throw new NotSupportedException(); } else if (this.Version == 3) { output.WriteString("ERF V3.0", Encoding.Unicode); var strings = new List<string>(); foreach (var entry in this.Entries) { if (entry.Name != null && strings.Contains(entry.Name) == false) { strings.Add(entry.Name); } } strings.Sort(); var stringOffsets = new Dictionary<string, uint>(); var stringTable = new MemoryStream(); foreach (var str in strings) { stringOffsets[str] = (uint)stringTable.Length; stringTable.WriteStringZ(str, Encoding.UTF8); } stringTable.SetLength(stringTable.Length.Align(16)); stringTable.Position = 0; output.WriteValueU32((uint)stringTable.Length); output.WriteValueS32(this.Entries.Count); if (this.Encryption != EncryptionScheme.None || this.Compression != CompressionScheme.None) { throw new NotSupportedException(); } uint flags = 0; flags |= ((uint)this.Encryption) << 4; flags |= ((uint)this.Compression) << 29; output.WriteValueU32(flags); output.WriteValueU32(this.ContentId); if (this.PasswordDigest == null) { output.Write(new byte[16], 0, 16); } else { output.Write(this.PasswordDigest, 0, 16); } output.WriteFromStream(stringTable, stringTable.Length, 0x00100000); foreach (var entry in this.Entries) { if (entry.Name != null) { entry.CalculateHashes(); output.WriteValueU32(stringOffsets[entry.Name]); } else { output.WriteValueU32(0xFFFFFFFF); } output.WriteValueU64(entry.NameHash); output.WriteValueU32(entry.TypeHash); output.WriteValueU32((uint)entry.Offset); output.WriteValueU32(entry.CompressedSize); output.WriteValueU32(entry.UncompressedSize); } } else { throw new InvalidOperationException(); } }
public void Serialize(Stream output) { var endian = this.Endian; const uint headerSize = 32; output.WriteValueU32(0x42424947, endian); output.WriteValueU32(this.Version, endian); var keys = new List<string>() {""}; int maxValueLength = 0; var blob = new StringBuilder(); foreach (var file in this.Files) { keys.Add(file.Name); foreach (var section in file.Sections) { keys.Add(section.Key); foreach (var value in section.Value) { keys.Add(value.Key); foreach (var item in value.Value) { if (item.Value != null) { blob.Append(item.Value + '\0'); maxValueLength = Math.Max(maxValueLength, item.Value.Length); } } } } } var huffmanEncoder = new Huffman.Encoder(); huffmanEncoder.Build(blob.ToString()); keys = keys.Distinct().OrderBy(k => k.HashCrc32()).ToList(); int maxKeyLength = keys.Max(k => k.Length); uint stringTableSize; using (var data = new MemoryStream()) { data.Position = 4; data.WriteValueS32(keys.Count, endian); data.Position = 4 + 4 + (8 * keys.Count); var offsets = new List<KeyValuePair<uint, uint>>(); foreach (var key in keys) { var offset = (uint)data.Position; data.WriteValueU16((ushort)key.Length, endian); data.WriteString(key, Encoding.UTF8); offsets.Add(new KeyValuePair<uint, uint>(key.HashCrc32(), offset)); } data.Position = 8; foreach (var kv in offsets) { data.WriteValueU32(kv.Key, endian); data.WriteValueU32(kv.Value - 8, endian); } data.Position = 0; data.WriteValueU32((uint)data.Length, endian); data.Position = 0; stringTableSize = (uint)data.Length; output.Seek(headerSize, SeekOrigin.Begin); output.WriteFromStream(data, data.Length); } uint huffmanSize; using (var data = new MemoryStream()) { var pairs = huffmanEncoder.GetPairs(); data.WriteValueU16((ushort)pairs.Length, endian); foreach (var pair in pairs) { data.WriteValueS32(pair.Left, endian); data.WriteValueS32(pair.Right, endian); } data.Position = 0; huffmanSize = (uint)data.Length; output.Seek(headerSize + stringTableSize, SeekOrigin.Begin); output.WriteFromStream(data, data.Length); } var bits = new BitArray(huffmanEncoder.TotalBits); var bitOffset = 0; uint indexSize; using (var index = new MemoryStream()) { var fileDataOffset = 2 + (this.Files.Count * 6); var files = new List<KeyValuePair<ushort, int>>(); foreach (var file in this.Files.OrderBy(f => keys.IndexOf(f.Name))) { files.Add(new KeyValuePair<ushort, int>( (ushort)keys.IndexOf(file.Name), fileDataOffset)); var sectionDataOffset = 2 + (file.Sections.Count * 6); var sections = new List<KeyValuePair<ushort, int>>(); foreach (var section in file.Sections.OrderBy(s => keys.IndexOf(s.Key))) { sections.Add(new KeyValuePair<ushort, int>( (ushort)keys.IndexOf(section.Key), sectionDataOffset)); var valueDataOffset = 2 + (section.Value.Count * 6); var values = new List<KeyValuePair<ushort, int>>(); foreach (var value in section.Value.OrderBy(v => keys.IndexOf(v.Key))) { index.Position = fileDataOffset + sectionDataOffset + valueDataOffset; values.Add(new KeyValuePair<ushort, int>( (ushort)keys.IndexOf(value.Key), valueDataOffset)); index.WriteValueU16((ushort)value.Value.Count, endian); valueDataOffset += 2; foreach (var item in value.Value) { if (item.Type == 1) { index.WriteValueS32((1 << 29) | bitOffset, endian); } else if (item.Type == 0 || item.Type == 2 || item.Type == 3 || item.Type == 4) { index.WriteValueS32((item.Type << 29) | bitOffset, endian); bitOffset += huffmanEncoder.Encode((item.Value ?? "") + '\0', bits, bitOffset); } valueDataOffset += 4; } } index.Position = fileDataOffset + sectionDataOffset; index.WriteValueU16((ushort)values.Count, endian); sectionDataOffset += 2; foreach (var value in values) { index.WriteValueU16(value.Key, endian); index.WriteValueS32(value.Value, endian); sectionDataOffset += 6; } sectionDataOffset += valueDataOffset; } index.Position = fileDataOffset; index.WriteValueU16((ushort)sections.Count, endian); fileDataOffset += 2; foreach (var section in sections) { index.WriteValueU16(section.Key, endian); index.WriteValueS32(section.Value, endian); fileDataOffset += 6; } fileDataOffset += sectionDataOffset; } index.Position = 0; index.WriteValueU16((ushort)files.Count, endian); foreach (var file in files) { index.WriteValueU16(file.Key, endian); index.WriteValueS32(file.Value, endian); } index.Position = 0; indexSize = (uint)index.Length; output.Seek(headerSize + stringTableSize + huffmanSize, SeekOrigin.Begin); output.WriteFromStream(index, index.Length); } output.Seek(headerSize + stringTableSize + huffmanSize + indexSize, SeekOrigin.Begin); output.WriteValueS32(bits.Length, endian); var bytes = new byte[(bits.Length - 1) / 8 + 1]; bits.CopyTo(bytes, 0); output.WriteBytes(bytes); output.Seek(8, SeekOrigin.Begin); output.WriteValueS32(maxKeyLength, endian); output.WriteValueS32(maxValueLength, endian); output.WriteValueU32(stringTableSize, endian); output.WriteValueU32(huffmanSize, endian); output.WriteValueU32(indexSize, endian); output.WriteValueS32(bytes.Length, endian); output.Seek(0, SeekOrigin.Begin); output.WriteValueU32(0x666D726D, endian); }