コード例 #1
0
        protected override void DoOpen()
        {
            using (CustomBinaryReader reader = new CustomBinaryReader(new FileStream(ArchivePath, FileMode.Open, FileAccess.Read)))
            {
                uint signature = reader.ReadUInt32();
                if (signature != 0x415342)
                {
                    throw new InvalidDataException("File is not BSA");
                }

                uint version      = reader.ReadUInt32();
                uint folderOffset = reader.ReadUInt32();
                flags = (ArchiveFlags)reader.ReadUInt32();
                uint folderCount           = reader.ReadUInt32();
                uint fileCount             = reader.ReadUInt32();
                uint totalFolderNameLength = reader.ReadUInt32();
                uint totalFileNameLength   = reader.ReadUInt32();
                uint fileExtensions        = reader.ReadUInt32();

                FolderInfo[] folders = new FolderInfo[(int)folderCount];

                // Read folders
                reader.BaseStream.Position = folderOffset;
                for (int i = 0; i < folderCount; i++)
                {
                    ulong hash    = reader.ReadUInt64();
                    uint  count   = reader.ReadUInt32();
                    uint  unknown = reader.ReadUInt32();
                    ulong offset  = reader.ReadUInt64() - totalFileNameLength;
                    folders[i] = new FolderInfo()
                    {
                        FileCount     = count,
                        ContentOffset = offset
                    };
                }

                // Read folder content (name and files)
                foreach (var folder in folders)
                {
                    byte folderNameLength = reader.ReadByte();
                    folder.Path = Encoding.UTF8.GetString(reader.ReadBytes(folderNameLength - 1));
                    byte zero = reader.ReadByte();

                    folder.Files = new FileInfo[folder.FileCount];
                    for (ulong i = 0; i < folder.FileCount; i++)
                    {
                        ulong hash = reader.ReadUInt64();
                        uint  size = reader.ReadUInt32();

                        bool compressed = flags.HasFlag(ArchiveFlags.DefaultCompressed);
                        if ((size & 0xf0000000) != 0)
                        {
                            size      &= 0xfffffff;
                            compressed = !compressed;
                        }

                        uint offset = reader.ReadUInt32();
                        folder.Files[i] = new FileInfo()
                        {
                            Size         = size,
                            DataOffset   = offset,
                            IsCompressed = compressed
                        };
                    }
                }

                long   total    = fileCount;
                long   loaded   = 0;
                string filename = Path.GetFileName(ArchivePath);

                // Read file names
                foreach (var folder in folders)
                {
                    foreach (var file in folder.Files)
                    {
                        file.Filename = reader.ReadStringZeroTerminated();
                        loaded++;
                    }
                }

                // Convert to nested sorted dictionary for fast search
                for (int i = 0; i < folderCount; i++)
                {
                    var files = new SortedDictionary <string, FileInfo>();
                    for (ulong j = 0; j < folders[i].FileCount; j++)
                    {
                        files.Add(folders[i].Files[j].Filename, folders[i].Files[j]);
                    }
                    sorted.Add(folders[i].Path, files);
                }

                return;
            }
        }