BA2 Archive Format¶
.ba2 is Bethesda's archive format introduced in Fallout 4, replacing the .bsa format used in
Skyrim and earlier games. It packages game assets (meshes, textures, sounds, scripts) into a
single compressed file.
Header¶
The file begins with a fixed header:
magic char[4] — "BTDX"
version uint32 — 1 for base game; ≥2 adds two unknown trailing uint32s
archive_type char[4] — "GNRL", "DX10", or "GNMF"
num_files uint32 — number of file entries
name_table_offset uint64 — byte offset to the filename string table
[unknown1] uint32 — only present if version ≥ 2
[unknown2] uint32 — only present if version ≥ 2
Archive types:
| Code | Contents |
|---|---|
GNRL |
General files — meshes, materials, audio, scripts, etc. |
DX10 |
DirectX textures — stored as raw mip chunks with a reconstructed DDS header |
GNMF |
PlayStation GNF textures (console builds) |
GNRL File Entries¶
Immediately after the header, num_files entries of 36 bytes each:
name_hash uint32 — hash of the filename
extension char[4] — file extension, zero-padded (e.g. "nif\0")
dir_hash uint32 — hash of the directory path
flags uint32
data_offset uint64 — absolute byte offset to the file data
packed_size uint32 — compressed size; 0 means uncompressed
unpacked_size uint32 — uncompressed size
align uint32 — alignment padding (always 0xBAADF00D in practice)
Compression: when packed_size != 0, the data at data_offset is DEFLATE-compressed
(zlib/RFC 1951 without header). Decompress packed_size bytes to unpacked_size bytes.
DX10 Texture Entries¶
Each DX10 entry has a fixed prefix followed by a variable-length chunk table:
name_hash uint32
extension char[4]
dir_hash uint32
unknown uint8
num_chunks uint8
chunk_header_size uint16
height uint16
width uint16
num_mips uint8
format uint8 — DXGI_FORMAT enum value
is_cubemap uint8 — 1 if cubemap
tile_mode uint8 — 8 = PC layout; other = Xbox tiled
Followed by num_chunks chunk records (24 bytes each):
data_offset uint64
packed_size uint32 — 0 = uncompressed
unpacked_size uint32
start_mip uint16
end_mip uint16
align uint32
To reconstruct the DDS file: build a DDS header from width, height, num_mips, format
(mapped to the appropriate DDSPF / DX10 extended header), then concatenate the decompressed
chunk data in order.
Xbox layout: tile_mode != 8 indicates an Xbox One tiled texture. The data layout differs
from standard PC DDS (Morton/swizzle order) and requires detiling before use on PC.
Name Table¶
Located at name_table_offset bytes from the start of the file. For each file entry in index
order:
str_length int16 — byte length of the following string
str_data char[] — file path, not null-terminated
Paths use backslashes as separators. If name_table_offset is 0, no name table exists and files
can only be identified by their name/dir hashes.
Hashing Algorithm¶
Bethesda uses two hash functions to identify files without storing full paths in the entry table:
Filename hash (applied to the filename without extension): - Sum of characters + various shift/XOR operations on specific character positions - Exact algorithm matches the BSA hash used since Oblivion
Directory hash (applied to the directory path): - Same algorithm applied to the full directory portion of the path
The hashes allow O(1) lookup by path but provide no ordering guarantee.
DXGI Format Values (common)¶
| Value | Format | Usage |
|---|---|---|
| 28 | DXGI_FORMAT_R8G8B8A8_UNORM | Uncompressed RGBA |
| 71 | DXGI_FORMAT_BC1_UNORM | DXT1 — opaque diffuse |
| 74 | DXGI_FORMAT_BC2_UNORM | DXT3 — diffuse with punch-through alpha |
| 77 | DXGI_FORMAT_BC3_UNORM | DXT5 — diffuse with smooth alpha |
| 80 | DXGI_FORMAT_BC4_UNORM | ATI1 — single-channel (grayscale/specular masks) |
| 83 | DXGI_FORMAT_BC5_UNORM | ATI2 — two-channel normal maps (X, Y) |
| 98 | DXGI_FORMAT_BC7_UNORM | High-quality RGBA |
| 99 | DXGI_FORMAT_BC7_UNORM_SRGB | BC7 with sRGB gamma |
Normal maps in FO4 are typically BC5 (two channels), with the Z component reconstructed as
sqrt(1 - X² - Y²).