Tes4Mod:BSA File Format

The UESPWiki – Your source for The Elder Scrolls since 1995
Jump to: navigation, search

Overview[edit]

BSA files are the resource archive files used by Oblivion. If you're familiar with the Morrowind BSA file format, Oblivion BSA format is similar, but not identical to it (if you're familiar with the generic IFF format, you'll find it very easy to understand --- BSA, ESM/ESP and ESS are IFF variants).

See also
Hash Calculation
Tools and Programmers for BSA unpacking tools.
Tes3 and 4 Utilities by Ghostwheel

File Structure[edit]

Name Type/Size Info
Header Header See specification of Header below.
folderRecords Folder Record[folderCount] See specification of Folder Record below.
fileRecordBlocks File Record blocks[...] See specification of File Record blocks below.
fileNameBlock File Name block A list of filenames. Each filename ends in \0. See specification of File Name block below.
files data or specification of Compressed File block Raw file data. If the file is compressed the file data will have the specification of Compressed File block.

Header[edit]

Name Type/Size Info
fileId char[4] Constant: "BSA\x00"
version ulong Currently 103 (0x67).
offset ulong Offset of beginning of folder records. All headers are the same size, therefore this value is 36 (0x24)
archiveFlags ulong List of archive flags:
Bit Description
1 (0x1) ¹ Archive has names for directories. (The game may not load a bsa without this bit set)
2 (0x2) ¹ Archive has names for files. (The game may not load a bsa without this bit set)
3 (0x4) Files are by default compressed.
4 (0x8) ² Unknown, but observed being checked for in Oblivion.exe. Possibly instructs the game to retain directory names in memory.
5 (0x10) ² Unknown, but observed being set in official BSA files containing sounds (but not voices). Possibly instructs the game to retain file names in memory.
6 (0x20) ² Unknown. Unobserved in official BSA files. In BSA v104, this bit instructs the game to 'retain file name offsets'.
7 (0x40) Xbox360 archive. Hash values and numbers after the header are encoded big-endian.
8 (0x80) ² Unknown, but observed being checked for in Oblivion.exe, related to the bInvalidateOlderFiles and bCheckRuntimeCollisions INI settings in Oblivion.ini. Also somehow related to bit 3. In BSA v104, this bit tells the game to 'retain strings during startup'.
9 (0x100) ¹ Unknown. This setting has a different meaning for BSA v104.
10 (0x200) ¹ Unknown. This setting has a different meaning for BSA v104.
11 (0x400) ¹ Unknown.

¹ This bit is set in all official BSA files.
² This bit has no effect on the file structure. Probably just instructions for the game.

folderCount ulong Count of all folders in archive.
fileCount ulong Count of all files in archive.
totalFolderNameLength ulong Total length of all folder names, including \0's but not including the prefixed length byte.
totalFileNameLength ulong Total length of all file names, including \0's.
fileFlags ulong List of flags:
Bit Description
1 (0x1) Meshes
2 (0x2) Textures
3 (0x4) Menus
4 (0x8) Sounds
5 (0x10) Voices
6 (0x20) Shaders
7 (0x40) Trees
8 (0x80) Fonts
9 (0x100) Miscellaneous

Folder Record[edit]

Name Type/Size Info
nameHash hash Hash of the folder name (eg: menus\chargen). Must be all lower case, and use backslash as directory delimiter(s).
count ulong Amount of files in this folder.
offset ulong /*Offset to file records for this folder. (Seems to include totalFileNameLength)*/

Offset to name of this folder + totalFileNameLength.

File Record blocks[edit]

If Bit 1 of archive flags is set:

Name Type/Size Info
name bzstring Name of the folder.
fileRecords variable (File Record) Many records in the amount of files specified in the associated folder record.

If Bit 1 of archive flags is not set:

Name Type/Size Info
fileRecords variable (File Record) Many records in the amount of files specified in the associated folder record.

File Record[edit]

Name Type/Size Info
nameHash hash Hash of the file name (eg: race_sex_menu.xml). Must be all lower case.
size ulong Size of the file data.

If the (1<<30) bit is set in the size:

  • If files are default compressed, this file is not compressed.
  • If files are default not compressed, this file is compressed.

If the file is compressed the file data will have the specification of Compressed File block. In addition, the size of compressed data is considered to be the ulong "original size" plus the compressed data size (4 + compressed size).

offset ulong Offset to raw file data for this folder. Note that an "offset" is offset from file byte zero

(start), NOT from this location.

File Name block[edit]

If archive flag 0x2 is not set, this block is omitted. A block of lower case file names, one after another, each ending in a \0. They are ordered in the same order as those generated with the file folder block contents in the BSA archive. These are all the files contained in the archive, such as "cuirass.nif" and "cuirass.dds", etc (no paths, just the root names).

Compressed File block[edit]

If Bit 9 of archiveFlags is not set:

Name Type/Size Info
originalSize ulong Size of uncompressed data.
data ubyte[compressedSize] File data that has been compressed with zlib.

If Bit 9 of archiveFlags is set:

Name Type/Size Info
name bstring Full path and name of the file
originalSize ulong Size of uncompressed data.
data ubyte[compressedSize] File data that has been compressed with zlib.



Uncompressed File block[edit]

If Bit 9 of archiveFlags is not set:

Name Type/Size Info
data ubyte[fileSize] File data.

If Bit 9 of archiveFlags is set:

Name Type/Size Info
name bstring Full path and name of the file
data ubyte[fileSize] File data.

Files and Dirs order[edit]

Inside bsa, folders and files in folders must be sorted by hash values. Sort all folders, then all files within the folders, keeping the folders contiguous. The 64 bit unsigned integer of hash value is used for sorting.

Encoding Numbers in the BSA[edit]

If Bit 7 of archive flags is not set, numbers are encoded low byte to high byte. A ulong of 0xABCDEF01 would have 0x01 in the first file byte, 0xEF in the second file byte, 0xCD in the third file byte, and 0xAB in the fourth and last file byte. This is true of the 64 bit (8 byte) hash value as well. If Bit 7 is set, then all numbers and 8 byte hash values are reverse order (big-endian).