public void Save(Stream output) { using (var bw = new BinaryWriterX(output)) { //Header bw.WriteASCII("XBB"); bw.Write((byte)1); bw.Write(Files.Count()); bw.BaseStream.Position = 0x20; var offset = 0x20 + Files.Sum(e => e.FileName.Length + 1 + 0x18); offset = offset + 0x7f & ~0x7f; var nameOffset = 0x20 + Files.Count() * 0x18; //FileEntries foreach (var file in Files) { bw.Write(offset); bw.Write((uint)file.FileSize); bw.Write(nameOffset); bw.Write(XbbHash.Create(file.FileName)); offset += (int)file.FileSize; offset = offset + 0x7f & ~0x7f; nameOffset += file.FileName.Length + 1; } //Hash table var files = Files.OrderBy(e => XbbHash.Create(e.FileName)).ToList(); for (int i = 0; i < files.Count(); i++) { var hash = XbbHash.Create(files[i].FileName); bw.Write(hash); bw.Write(Files.FindIndex(e => XbbHash.Create(e.FileName) == hash)); } //nameList foreach (var file in Files) { bw.WriteASCII(file.FileName); bw.Write((byte)0); } //FileData foreach (var file in Files) { bw.WriteAlignment(0x80); file.FileData.CopyTo(bw.BaseStream); } bw.WriteAlignment(0x80); } }
public void Save(Stream output, IList <IArchiveFileInfo> files) { var entryPosition = _headerSize; var hashEntryPosition = entryPosition + files.Count * _entrySize; var namePosition = hashEntryPosition + files.Count * _hashEntrySize; using var bw = new BinaryWriterX(output); // Write names bw.BaseStream.Position = namePosition; var nameDictionary = new Dictionary <UPath, int>(); foreach (var file in files) { if (!nameDictionary.ContainsKey(file.FilePath)) { nameDictionary.Add(file.FilePath, (int)bw.BaseStream.Position); } bw.WriteString(file.FilePath.ToRelative().FullName, Encoding.ASCII, false); } var dataPosition = (bw.BaseStream.Position + 0x7F) & ~0x7F; // Write files bw.BaseStream.Position = dataPosition; var xbbHash = new XbbHash(); var fileEntries = new List <XbbFileEntry>(); var hashEntries = new List <XbbHashEntry>(); foreach (var file in files.Cast <ArchiveFileInfo>()) { var offset = bw.BaseStream.Position; var writtenSize = file.SaveFileData(bw.BaseStream, null); bw.WriteAlignment(0x80); var hash = xbbHash.ComputeValue(file.FilePath.ToRelative().FullName); fileEntries.Add(new XbbFileEntry { offset = (int)offset, size = (int)writtenSize, nameOffset = nameDictionary[file.FilePath], hash = hash }); hashEntries.Add(new XbbHashEntry { hash = hash, index = fileEntries.Count - 1 }); } // Write file entries bw.BaseStream.Position = entryPosition; bw.WriteMultiple(fileEntries); // Write hash entries bw.BaseStream.Position = hashEntryPosition; bw.WriteMultiple(hashEntries.OrderBy(x => x.hash)); // Write header bw.BaseStream.Position = 0; bw.WriteType(new XbbHeader { entryCount = files.Count }); }