private ArchiveFileInfo CreateAfi(Stream file, string name, HpiFileEntry entry) { var magic = HpiHpbSupport.PeekString(file, 4); if (magic != "ACMP") { return(new HpiHpbArchiveFileInfo(file, name, entry)); } var compressedStream = new SubStream(file, 0x20, file.Length - 0x20); return(new HpiHpbArchiveFileInfo(compressedStream, name, entry, Kompression.Implementations.Compressions.Nintendo.BackwardLz77, entry.decompSize)); }
public void Save(Stream hpiStream, Stream hpbStream, IList <IArchiveFileInfo> files) { var sjis = Encoding.GetEncoding("SJIS"); using var hpiBw = new BinaryWriterX(hpiStream); // Calculate offsets var fileOffset = 0; var hashOffset = HeaderSize; var entryOffset = hashOffset + HashSlotCount_ * HashEntrySize; var stringOffset = entryOffset + files.Count * FileEntrySize; // Group files var fileLookup = files.ToLookup(x => HpiHpbSupport.CreateHash(x.FilePath.ToRelative().FullName) % HashSlotCount_); // Write files and strings hpiStream.Position = stringOffset; hpbStream.Position = fileOffset; foreach (var file in files.Cast <HpiHpbArchiveFileInfo>().OrderBy(x => x.FilePath, new SlashFirstStringComparer())) { fileOffset = (int)hpbStream.Position; var nameOffset = (int)hpiStream.Position; var writtenSize = file.SaveFileData(hpbStream); hpiBw.WriteString(file.FilePath.ToRelative().FullName, sjis, false); file.Entry.offset = fileOffset; file.Entry.stringOffset = nameOffset - stringOffset; file.Entry.compSize = (int)writtenSize; file.Entry.decompSize = file.UsesCompression ? (int)file.FileSize : 0; } // Write entries var hashes = new List <HpiHashEntry>(); hpiStream.Position = entryOffset; for (uint i = 0, offset = 0; i < HashSlotCount_; i++) { var hashEntry = new HpiHashEntry { entryOffset = (short)offset, entryCount = (short)fileLookup[i].Count() }; hashes.Add(hashEntry); offset += (uint)hashEntry.entryCount; foreach (var file in fileLookup[i].Cast <HpiHpbArchiveFileInfo>()) { hpiBw.WriteType(file.Entry); } } // Write hash entries hpiStream.Position = hashOffset; hpiBw.WriteMultiple(hashes); // Write header hpiStream.Position = 0; hpiBw.WriteType(new HpiHeader { hashCount = (short)hashes.Count, entryCount = files.Count }); }