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 offset = reader.ReadUInt32() - 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 (int 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 (int 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;
}
}