Beispiel #1
0
        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));
        }
Beispiel #2
0
        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
            });
        }