Example #1
0
        private void WriteFileTable(Stream output, IList <IArchiveFileInfo> files)
        {
            var crc16       = Crc16.X25;
            var fileEntries = new List <GfsaFileEntry>();

            var fileOffset = 0;

            foreach (var fileGroup in OrderFiles(files).Cast <GfsaArchiveFileInfo>().GroupBy(x => x.FilePath.GetDirectory().ToRelative() + "/"))
            {
                var localGroup = fileGroup.Select(file =>
                {
                    var entry = new GfsaFileEntry
                    {
                        hash   = BinaryPrimitives.ReadUInt16BigEndian(crc16.Compute(Encoding.ASCII.GetBytes(file.FilePath.GetName()))),
                        Offset = fileOffset,
                        Size   = (int)file.CompressedSize
                    };

                    fileOffset += (int)((file.CompressedSize + 3) & ~3);

                    return(entry);
                });

                fileEntries.AddRange(localGroup.OrderBy(x => x.hash));
            }

            XfsaSupport.WriteCompressedTableEntries(output, fileEntries);

            while (output.Position % 4 > 0)
            {
                output.WriteByte(0);
            }
        }
Example #2
0
        private void WriteDirectoryTable(Stream output, IList <IArchiveFileInfo> files)
        {
            var crc16            = Crc16.X25;
            var directoryEntries = new List <GfsaDirectoryEntry>();

            var fileIndex = 0;

            foreach (var group in OrderFiles(files).GroupBy(x => x.FilePath.GetDirectory().ToRelative() + "/"))
            {
                directoryEntries.Add(new GfsaDirectoryEntry
                {
                    hash      = BinaryPrimitives.ReadUInt16BigEndian(crc16.Compute(Encoding.ASCII.GetBytes(group.Key))),
                    fileIndex = fileIndex,
                    fileCount = (short)group.Count()
                });

                fileIndex += directoryEntries.Last().fileCount;
            }

            XfsaSupport.WriteCompressedTableEntries(output, directoryEntries.OrderBy(x => x.hash));

            while (output.Position % 4 > 0)
            {
                output.WriteByte(0);
            }
        }
Example #3
0
        public void Save(Stream output, IList <IArchiveFileInfo> files, IProgressContext progress)
        {
            // Group files by directory
            var castedFiles = files.Cast <XfsaArchiveFileInfo <Xfsa2FileEntry> >();

            // Build directory, file, and name tables
            BuildTables(castedFiles, out var directoryEntries, out var directoryHashes, out var fileEntries, out var nameStream);

            // -- Write file --

            using var bw           = new BinaryWriterX(output);
            bw.BaseStream.Position = _headerSize;

            // Write directory entries
            _header.directoryEntriesCount  = (short)directoryEntries.Count;
            _header.directoryEntriesOffset = _headerSize;

            XfsaSupport.WriteCompressedTableEntries(bw.BaseStream, directoryEntries);
            bw.WriteAlignment(4);

            // Write directory hashes
            _header.directoryHashCount  = (short)directoryHashes.Count;
            _header.directoryHashOffset = (int)bw.BaseStream.Position;

            XfsaSupport.WriteCompressedTableEntries(bw.BaseStream, directoryHashes);
            bw.WriteAlignment(4);

            // Write file entry hashes
            _header.fileEntriesCount  = fileEntries.Count;
            _header.fileEntriesOffset = (int)bw.BaseStream.Position;

            XfsaSupport.WriteCompressedTableEntries(bw.BaseStream, fileEntries.Select(x => x.Entry));
            bw.WriteAlignment(4);

            // Write name table
            _header.nameOffset = (int)bw.BaseStream.Position;

            var nameStreamComp = new MemoryStream();

            XfsaSupport.Compress(nameStream, nameStreamComp, Level5CompressionMethod.Lz10);
            nameStreamComp.CopyTo(bw.BaseStream);
            bw.WriteAlignment(4);

            // Write file data
            _header.dataOffset = (int)bw.BaseStream.Position;

            foreach (var fileEntry in fileEntries)
            {
                bw.BaseStream.Position = _header.dataOffset + fileEntry.Entry.FileOffset;
                fileEntry.SaveFileData(bw.BaseStream, null);
            }

            // Write header
            bw.BaseStream.Position = 0;
            bw.WriteType(_header);
        }