public void Serialize(Stream output) { var endian = this.Endian; var names = new MemoryStream(); var directory = new MemoryStream(); foreach (var entry in this.Entries) { directory.WriteValueU32((uint)names.Position, endian); directory.WriteValueU32(0, endian); directory.WriteValueU32(entry.Offset, endian); directory.WriteValueU32(entry.Name.HashVolition(), endian); directory.WriteValueU32(entry.UncompressedSize, endian); directory.WriteValueU32(entry.CompressedSize, endian); directory.WriteValueU32(0, endian); names.WriteStringZ(entry.Name, Encoding.ASCII); } var header = new Package.HeaderV3(); header.Name = " Created using Gibbed's Volition Tools "; header.Path = " Read the Foundation Novels from Asimov. I liked them. "; header.Flags = ConvertFlags(this.Flags); if (this.ExtraFlags != 0) { header.Flags |= (Package.HeaderFlagsV3) this.ExtraFlags; } header.DirectoryCount = (uint)this.Entries.Count; header.PackageSize = this.TotalSize; header.DirectorySize = (uint)directory.Length; header.NamesSize = (uint)names.Length; header.UncompressedSize = this.UncompressedSize; header.CompressedSize = (this.Flags & Package.HeaderFlags.Compressed) != 0 ? this.CompressedSize : 0xFFFFFFFF; directory.Seek(0, SeekOrigin.Begin); directory.SetLength(directory.Length.Align(2048)); names.Seek(0, SeekOrigin.Begin); names.SetLength(names.Length.Align(2048)); output.WriteValueU32(0x51890ACE, endian); output.WriteValueU32(3, endian); header.Serialize(output, endian); output.Seek(2048, SeekOrigin.Begin); output.WriteFromStream(directory, directory.Length); output.WriteFromStream(names, names.Length); }
public void Deserialize(Stream input) { Endian endian; Package.HeaderV3 header; using (var data = input.ReadToMemoryStream(2048)) { var magic = data.ReadValueU32(Endian.Little); if (magic != 0x51890ACE && magic.Swap() != 0x51890ACE) { throw new FormatException("not a package file"); } endian = magic == 0x51890ACE ? Endian.Little : Endian.Big; var version = data.ReadValueU32(endian); if (version != 3) { throw new FormatException("unexpected package version (expected 3)"); } header = new Package.HeaderV3(); header.Deserialize(data, endian); } this.Entries.Clear(); using (var directory = input.ReadToMemoryStream(header.DirectorySize.Align(2048))) { using (var names = input.ReadToMemoryStream(header.NamesSize.Align(2048))) { for (int i = 0; i < header.DirectoryCount; i++) { var nameOffset = directory.ReadValueU32(endian); directory.Seek(4, SeekOrigin.Current); // runtime offset var offset = directory.ReadValueU32(endian); directory.Seek(4, SeekOrigin.Current); // name hash var uncompressedSize = directory.ReadValueU32(endian); var compressedSize = directory.ReadValueU32(endian); directory.Seek(4, SeekOrigin.Current); // package pointer names.Seek(nameOffset, SeekOrigin.Begin); var name = names.ReadStringZ(Encoding.ASCII); this.Entries.Add(new Package.Entry() { Name = name, Offset = offset, UncompressedSize = uncompressedSize, CompressedSize = compressedSize, }); } } } this.Endian = endian; this.Flags = ConvertFlags(header.Flags); this.UncompressedSize = header.UncompressedSize; this.CompressedSize = header.CompressedSize; this.DataOffset = input.Position; }