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