AttribSys vault resources act as a database which holds attributes for stadium resources, gameplay, configs. They are split into the vault, which holds information needed to access the data, and the bin, which holds the actual attribute data. Vaults work with the
AttribSys schema found in the executable.
Structures
CgsResource::AttribSysVaultResource
32-bit
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x4 | uint8_t* | mpau8VltData | | |
| 0x4 | 0x4 | uint32_t | muVltSizeInBytes | | |
| 0x8 | 0x4 | uint8_t* | mpau8BinData | | |
| 0xC | 0x4 | uint32_t | muBinSizeInBytes | | |
64-bit
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | uint8_t* | mpau8VltData | | |
| 0x8 | 0x4 | uint32_t | muVltSizeInBytes | | |
| 0xC | 0x4 | | | Padding | |
| 0x10 | 0x8 | uint8_t* | mpau8BinData | | |
| 0x18 | 0x4 | uint32_t | muBinSizeInBytes | | |
Common substructures
Attrib::Array
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x2 | uint16_t | mAlloc | Number of entries allocated | |
| 0x2 | 0x2 | uint16_t | mCount | Number of entries used | |
| 0x4 | 0x2 | uint16_t | mSize | The length of each entry | |
| 0x6 | 0x2 | uint16_t | mEncodedTypePad | Padding | |
Attrib::RefSpec
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | Key | mClassKey | | |
| 0x8 | 0x8 | Key | mCollectionKey | | |
| 0x10 | 0x4 | Collection* | mCollectionPtr | | Always nullptr in resource |
| 0x14 | 0x4 | | | Padding | |
Vault
The vault is a set of structures with
ChunkBlocks which are read sequentially. In FIFA, these are:
- Vers: The version
- DepN: The dependency node
- StrN: The start node
- DatN: The data node
- ExpN: The export node
- PtrN: The pointer node
Attrib::Vault::ChunkBlock
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x4 | uint32_t | mType | A type ID similar in form to a magic number | |
| 0x4 | 0x4 | uint32_t | mSize | The total size of the chunk | |
Version
Attrib::Vault::VersionNode
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | ChunkBlock | | Base class | |
| 0x8 | 0x8 | uint64_t | mVersion | Version hash | |
Dependency node
Attrib::Vault:
ependencyNode
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | ChunkBlock | | Base class | |
| 0x8 | 0x8 | HashInt | mCount | Number of dependencies | |
This structure is immediately followed by the
hashes of the dependency strings, then the offsets of the strings relative to the start of the first string, then the strings themselves.
Start node
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | ChunkBlock | | Base class | |
| ??? | | | | | |
Size is 16 bytes, but the final 8 bytes is always null. This node appears to not be read by the game.
Data node
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | ChunkBlock | | Base class | |
This is followed by several
collections.
This node is not read directly. Pointers in other nodes read the data that lies in this node.
Attrib::CollectionLoadData
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | Key | mKey | | |
| 0x8 | 0x8 | Key | mClass | | |
| 0x10 | 0x8 | Key | mParent | | |
| 0x18 | 0x4 | uint32_t | mTableReserve | Amount allocated for entries | |
| 0x1C | 0x4 | uint32_t | mTableKeyShift | | |
| 0x20 | 0x4 | uint32_t | mNumEntries | Number of entries | |
| 0x24 | 0x2 | uint16_t | mNumTypes | Number of types | |
| 0x26 | 0x2 | uint16_t | mTypesLen | Amount allocated for types | |
| 0x28 | 0x4 | void* | mLayout | | Always nullptr in resource |
| 0x2C | 0x4 | | | Padding | |
This is always followed by the types, then the
entries.
Attrib::CollectionLoadData::AttribEntry
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | Key | mKey | | |
| 0x8 | 0x4 | void* | mData | | |
| 0xC | 0x2 | uint16_t | mType | | |
| 0xE | 0x1 | uint8_t | mNodeFlags | | |
| 0xF | 0x1 | uint8_t | mEntryFlags | | |
Export node
Attrib::Vault::ExportNode
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | ChunkBlock | | Base class | |
| 0x8 | 0x8 | HashInt | mCount | Number of exports | |
Followed by
export entries of an amount defined by mCount.
Attrib::Vault::ExportEntry
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | ExportID | mID | | |
| 0x8 | 0x8 | TypeID | mType | | |
| 0x10 | 0x4 | uint32_t | mDataBytes | Size of the data node entry | |
| 0x14 | 0x4 | uint32_t | mDataOffset | Offset of the entry in the data node | Relative to vlt start |
Pointer node
Attrib::Vault:
ointerNode
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x8 | ChunkBlock | | Base class | |
Followed by several
PtrRefs.
Attrib:
trRef
| Offset | Length | Type | Name | Description | Comments |
|---|
| 0x0 | 0x4 | uint32_t | mFixupOffset | The offset at which to write the offset | Relative to the beginning of the dependency.
The area pointed to is normally null and allocated specifically for this |
| 0x4 | 0x2 | uint16_t | mPtrType | Pointer type | See type. |
| 0x6 | 0x2 | uint16_t | mIndex | Which dependency the value is relative to | 0 is normally the vault
1 is normally the bin |
| 0x8 | 0x8 | anon_union_0 | field_3 | Value | |
Attrib:
trRef::anon_union_0
Bin
The bin is entirely made up of data. The individual structures within are pointed to by the vault.
In general attribdb, there is one ChunkBlock at the beginning of the bin, StrE (string exports), which contains a list of null-terminated strings. Each individual string is pointed to by the vault. The ChunkBlock itself is not read and likely only exists as a byproduct of how the AttribSys is created.
In gameplay attribdb the strings are included in the exe, so is hard to determine the references.