public IList <Vault> Load(BinaryReader br, Database database, PackLoadingOptions loadingOptions) { ByteOrder byteOrder = loadingOptions?.ByteOrder ?? ByteOrder.Little; // check for VPAK header AttribVaultPackImage vaultPackImage = new AttribVaultPackImage(); vaultPackImage.Read(null, br); br.BaseStream.Position = vaultPackImage.Header.StringBlockOffset; List <Vault> vaults = new List <Vault>(); foreach (AttribVaultPackEntry attribVaultPackEntry in vaultPackImage.Entries) { br.BaseStream.Position = vaultPackImage.Header.StringBlockOffset + attribVaultPackEntry.VaultNameOffset; Vault vault = new Vault(NullTerminatedString.Read(br)); br.BaseStream.Seek(attribVaultPackEntry.BinOffset, SeekOrigin.Begin); byte[] binData = new byte[attribVaultPackEntry.BinSize]; if (br.Read(binData, 0, binData.Length) != binData.Length) { throw new Exception($"Failed to read {binData.Length} bytes of BIN data"); } br.BaseStream.Seek(attribVaultPackEntry.VltOffset, SeekOrigin.Begin); byte[] vltData = new byte[attribVaultPackEntry.VltSize]; if (br.Read(vltData, 0, vltData.Length) != vltData.Length) { throw new Exception($"Failed to read {vltData.Length} bytes of VLT data"); } vault.BinStream = new MemoryStream(binData); vault.VltStream = new MemoryStream(vltData); using (VaultLoadingWrapper loadingWrapper = new VaultLoadingWrapper(vault, byteOrder)) { database.LoadVault(vault, loadingWrapper); } vaults.Add(vault); } return(vaults); }
public void Save(BinaryWriter bw, IList <Vault> vaults, PackSavingOptions savingOptions = null) { Dictionary <string, VaultStreamInfo> streamDictionary = new Dictionary <string, VaultStreamInfo>(); foreach (var vault in vaults) { VaultWriter vaultWriter = new VaultWriter(vault, new VaultSaveOptions()); streamDictionary[vault.Name] = vaultWriter.BuildVault(); } // empty header for now bw.Write(new byte[16]); Dictionary <string, int> nameOffsets = new Dictionary <string, int>(); int nameOffset = 0; foreach (var databaseVault in vaults) { nameOffsets[databaseVault.Name] = nameOffset; nameOffset += databaseVault.Name.Length + 1; } bw.Write(nameOffset); bw.Write(new byte[20 * vaults.Count]); bw.AlignWriter(0x40); var nameTablePos = bw.BaseStream.Position; foreach (var databaseVault in vaults) { NullTerminatedString.Write(bw, databaseVault.Name); } bw.AlignWriter(0x80); List <long> binOffsets = new List <long>(); List <long> vltOffsets = new List <long>(); foreach (var vault in vaults) { bw.AlignWriter(0x80); var streamInfo = streamDictionary[vault.Name]; binOffsets.Add(bw.BaseStream.Position); streamInfo.BinStream.CopyTo(bw.BaseStream); bw.AlignWriter(0x80); vltOffsets.Add(bw.BaseStream.Position); streamInfo.VltStream.CopyTo(bw.BaseStream); } bw.BaseStream.Position = 0; // write header AttribVaultPackImage vpi = new AttribVaultPackImage(); AttribVaultPackHeader header = new AttribVaultPackHeader { NumEntries = (uint)vaults.Count, StringBlockOffset = (uint)nameTablePos, StringBlockSize = (uint)nameOffset }; vpi.Header = header; vpi.Entries = new List <AttribVaultPackEntry>(); for (int i = 0; i < vaults.Count; i++) { Vault vault = vaults[i]; var streamInfo = streamDictionary[vault.Name]; AttribVaultPackEntry entry = new AttribVaultPackEntry { BinOffset = (uint)binOffsets[i], VltOffset = (uint)vltOffsets[i], BinSize = (uint)streamInfo.BinStream.Length, VltSize = (uint)streamInfo.VltStream.Length, VaultNameOffset = (uint)nameOffsets[vault.Name] }; vpi.Entries.Add(entry); } vpi.Write(null, bw); }