BA2 archive format
Note: Work in progress.
There are two types of archives: general and texture. Generals may contain anything except textures. Texture archives oblivously containing textures.
Some things to note:
- Everything is encoded as little endian.
- No padding or aligning between structures or values.
All archives consist of (in order of appearance):
- Archive header
- File declaration (General / Texture) — various data about file
- File data (see offset in file declaration) — file contents
- Name table — stores file paths to files in archive
All archive types sharing same header and file declarations:
| Archive Header | ||||
|---|---|---|---|---|
| Name | Type | Size | Value | Notes |
| Magic | char[4] | 4 | BDTX | Magic for all archives |
| Version | uint32 | 4 | 1 | Archive version |
| Archive type | char[4] | 4 | GNRL or DX10 | GNRL — general archive, DX10 — texture archive |
| Total files | uint32 | 4 | ||
| Name table offset | uint64 | 8 | Offset from archive beginning to name table | |
| Struct size: 24 bytes | ||||
File declaration is defined for each file in archive (see header -> total files).
| File Declaration (General) | ||||
|---|---|---|---|---|
| Name | Type | Size | Value | Notes |
| Unknown 0 | uint32 | 4 | File hash? | |
| Extension | char[4] | 4 | File extension. Doesn't start with dot | |
| Unknown 1 | uint32 | 4 | Directory hash? | |
| Unknown 2 | uint32 | 4 | File flags? | |
| Offset | uint64 | 8 | Offset from beginning of archive to file data | |
| Packed length | uint32 | 4 | zlib packed length. Equals to 0 if not packed | |
| Unpacked length | uint32 | 4 | Original file length | |
| Unknown 3 | uint32 | 4 | 0xBAADF00D | |
| Struct size: 36 bytes | ||||
Textures are DDS without header. See ba2extract (fallout4tools).
| File Declaration (Texture) | ||||
|---|---|---|---|---|
| Name | Type | Size | Value | Notes |
| Unknown 0 | uint32 | 4 | File hash? | |
| Extension | char[4] | 4 | dds\0 | File extension. Doesn't start with dot |
| Unknown 1 | uint32 | 4 | Directory hash? | |
| Unknown 2 | uint8 | 1 | ||
| Number of chunks | uint8 | 1 | ||
| Chunk header size | uint16 | 2 | ||
| Texture height | uint16 | 2 | ||
| Texture width | uint16 | 2 | ||
| Number of mipmaps | uint8 | 1 | ||
| Format | uint8 | 1 | DXGI_FORMAT | |
| Unknown 3 | uint16 | 2 | 0x0800 | |
| Struct size: 24 bytes | ||||
Texture chunks is defined for each file declaration several times (see file declaration -> number of chunks).
| Texture Chunk | |||
|---|---|---|---|
| Name | Type | Size | Notes |
| Offset | uint64 | 8 | Offset from archive beginning to texture chunk data |
| Packed length | uint32 | 4 | zlib packed length. Equals to 0 if not packed |
| Unpacked length | uint32 | 4 | Original file length |
| Start mipmap | uint16 | 2 | |
| End mipmap | uint16 | 2 | |
| Unknown 0 | uint32 | 4 | 0xBAADFOOD |
| Struct size: 24 bytes | |||
Name table string is defined for each file in archive. Each string is null-terminated. This is basically Pascal string.
| Name Table String | |||
|---|---|---|---|
| Name | Type | Size | Notes |
| String length | uint16 | 2 | |
| Char | char[] | [String length] | Use string length to read all chars |