Abrir menu principal

UESPWiki β

Morrowind Mod:BSA File Format

< Modding

Overview

BSA files are the archive format used by Morrowind, its expansions, and modders. It is a relatively simple container format compared to the Oblivion BSA format. Several tools have been written to open and create them.

The information presented here has been pulled from ghostwheel's site and Timeslip's BSA code for NifSkope.

Limitations

Because files in a BSA do not store timestamps, they cannot be used as a "replacer"; Wrye Mash handles this excellently with it's "Bain for Mash" installer features.

Sound, Music, Fonts and Splash screens are not recognized inside a BSA.

Files in a BSA must have unique filename hashes.

The format

A Morrowind BSA is broken into 6 sections:

Name Size (bytes) Info
Header 12 Stores a magic number, lookup pointer, and the total number of files
File size/offset 8 * number of files
Name offsets 4 * number of files
Names hashOffset - (12 * number of files)
Hashes 8 * number of files Used as the sort key for all records except raw file data
Raw data (blob) Sorted by filename?

Header

Name Type/Size Info
version byte[4] 0x00000100
hashOffset ulong Offset of the hash table in the file, minus the header size (12). Add 8 * fileCount to find the offset of the data section.
fileCount ulong Number of files in the BSA, and number of records for every other section.

File sizes/offsets

Name Type/Size Info
fileSize ulong Size of the file
fileOffset ulong Offset of the file in the data section

Archive directory/name offsets

Name Type/Size Info
filenameOffset ulong Relative offset of the filename in the records section.

Filename records

Name Type/Size Info
filenameRecord zstring Lowercase ASCII, null-terminated. Offset given by corresponding filenameOffset.

Hash table

Name Type/Size Info
filenameHash hash Hashes of the filenames.

File data

Name Type/Size Info
Raw data blob Uncompressed and unseparated. The offset of each file is given by the corresponding fileOffset.

Sorting

All records except File Data are sorted by hash; file data appears to be sorted by the alphabetical order of file names.

Hash calculation

From the source of bsapack:

unsigned l = (len>>1);
unsigned sum, off, temp, i, n;

for(sum = off = i = 0; i < l; i++) {
        sum ^= (((unsigned)(name[i]))<<(off&0x1F));
        off += 8;
}
hash.value1 = sum;

for(sum = off = 0; i < len; i++) {
        temp = (((unsigned)(name[i]))<<(off&0x1F));
        sum ^= temp;
        n = temp & 0x1F;
        sum = (sum << (32-n)) | (sum >> n);  // binary "rotate right"
        off += 8;
}
hash.value2 = sum;