public void Serialize(Stream output, ArchiveSerializeOptions options) { var compress = (options & ArchiveSerializeOptions.Compress) != 0; var basePosition = output.Position; var endian = this._Endian; using (var data = new MemoryStream(12)) { data.WriteValueU32(Signature, Endian.Big); data.WriteValueU32(19, endian); data.WriteValueU32((uint)this._Platform, Endian.Big); data.Flush(); output.WriteFromMemoryStreamSafe(data, endian); } var headerPosition = output.Position; Archive.FileHeader fileHeader; output.Seek(56, SeekOrigin.Current); fileHeader.ResourceTypeTableOffset = (uint)(output.Position - basePosition); output.WriteValueS32(this._ResourceTypes.Count, endian); foreach (var resourceType in this._ResourceTypes) { resourceType.Write(output, endian); } var blockAlignment = (options & ArchiveSerializeOptions.OneBlock) != 0 ? (uint)this._ResourceEntries.Sum(re => 30 + (re.Data == null ? 0 : re.Data.Length)) : 0x4000; fileHeader.BlockTableOffset = (uint)(output.Position - basePosition); fileHeader.ResourceCount = 0; var blockStream = BlockWriterStream.ToStream(output, blockAlignment, endian, compress); foreach (var resourceEntry in this._ResourceEntries) { Archive.ResourceHeader resourceHeader; resourceHeader.TypeId = (uint)resourceEntry.TypeId; resourceHeader.Size = 30 + (uint)(resourceEntry.Data == null ? 0 : resourceEntry.Data.Length); resourceHeader.Version = resourceEntry.Version; resourceHeader.SlotRamRequired = resourceEntry.SlotRamRequired; resourceHeader.SlotVramRequired = resourceEntry.SlotVramRequired; resourceHeader.OtherRamRequired = resourceEntry.OtherRamRequired; resourceHeader.OtherVramRequired = resourceEntry.OtherVramRequired; using (var data = new MemoryStream()) { resourceHeader.Write(data, endian); data.Flush(); blockStream.WriteFromMemoryStreamSafe(data, endian); } blockStream.WriteBytes(resourceEntry.Data); fileHeader.ResourceCount++; } blockStream.Flush(); blockStream.Finish(); fileHeader.XmlOffset = (uint)(output.Position - basePosition); if (string.IsNullOrEmpty(this._ResourceInfoXml) == false) { output.WriteString(this._ResourceInfoXml, Encoding.ASCII); } fileHeader.SlotRamRequired = this.SlotRamRequired; fileHeader.SlotVramRequired = this.SlotVramRequired; fileHeader.OtherRamRequired = this.OtherRamRequired; fileHeader.OtherVramRequired = this.OtherVramRequired; fileHeader.Flags = 1; fileHeader.Unknown20 = this._Unknown20 ?? new byte[16]; output.Position = headerPosition; using (var data = new MemoryStream()) { fileHeader.Write(data, endian); data.Flush(); output.WriteFromMemoryStreamSafe(data, endian); } }
public void Serialize(Stream output, ArchiveSerializeOptions options) { // If ratio isn't 0.0f, we'll try to compress. // If the user sets it to 0.0f, then we should skip any attempt to compress. var compress = (options & ArchiveSerializeOptions.Compress) > 0; compress &= ToolkitSettings.CompressionRatio != 0.0f; var basePosition = output.Position; var endian = this._Endian; using (var data = new MemoryStream(12)) { data.WriteValueU32(Signature, Endian.Big); data.WriteValueU32(Version, endian); data.WriteValueU32((uint)this._Platform, Endian.Big); data.Flush(); output.WriteFromMemoryStreamSafe(data, endian); } var headerPosition = output.Position; Archive.FileHeader fileHeader; output.Seek(56, SeekOrigin.Current); fileHeader.ResourceTypeTableOffset = (uint)(output.Position - basePosition); output.WriteValueS32(this._ResourceTypes.Count, endian); foreach (var resourceType in this._ResourceTypes) { resourceType.Write(output, endian); } uint stride = (uint)(Version == 20 ? 38 : 30); uint alignment = (uint)(Version == 20 ? 0x10000 : 0x4000); var blockAlignment = (options & ArchiveSerializeOptions.OneBlock) != ArchiveSerializeOptions.None ? (uint)this._ResourceEntries.Sum(re => stride + (re.Data == null ? 0 : re.Data.Length)) : alignment; fileHeader.BlockTableOffset = (uint)(output.Position - basePosition); fileHeader.ResourceCount = 0; var blockStream = BlockWriterStream.ToStream(output, blockAlignment, endian, compress, ChosenGameType == GamesEnumerator.MafiaI_DE); foreach (var resourceEntry in this._ResourceEntries) { Archive.ResourceHeader resourceHeader; resourceHeader.TypeId = (uint)resourceEntry.TypeId; resourceHeader.Size = stride + (uint)(resourceEntry.Data == null ? 0 : resourceEntry.Data.Length); resourceHeader.Version = resourceEntry.Version; resourceHeader.FileHash = resourceEntry.FileHash; resourceHeader.SlotRamRequired = resourceEntry.SlotRamRequired; resourceHeader.SlotVramRequired = resourceEntry.SlotVramRequired; resourceHeader.OtherRamRequired = resourceEntry.OtherRamRequired; resourceHeader.OtherVramRequired = resourceEntry.OtherVramRequired; using (var data = new MemoryStream()) { resourceHeader.Write(data, endian, Version); data.Flush(); blockStream.WriteFromMemoryStreamSafe(data, endian); } blockStream.WriteBytes(resourceEntry.Data); fileHeader.ResourceCount++; } blockStream.Flush(); blockStream.Finish(); fileHeader.XmlOffset = (uint)(output.Position - basePosition); if (string.IsNullOrEmpty(this._ResourceInfoXml) == false) { output.WriteString(this._ResourceInfoXml, Encoding.ASCII); } fileHeader.SlotRamRequired = this.SlotRamRequired; fileHeader.SlotVramRequired = this.SlotVramRequired; fileHeader.OtherRamRequired = this.OtherRamRequired; fileHeader.OtherVramRequired = this.OtherVramRequired; fileHeader.Flags = 1; fileHeader.Unknown20 = this._Unknown20 ?? new byte[16]; output.Position = headerPosition; using (var data = new MemoryStream()) { fileHeader.Write(data, endian); data.Flush(); output.WriteFromMemoryStreamSafe(data, endian); } }