AINB: Difference between revisions

From EPD Wiki
Jump to navigation Jump to search
Aster (talk | contribs)
Specified that only the first version of the NSO Playtest Program uses 0x407
Watertoon (talk | contribs)
Renaming pass, rewrite parameter tables.
Line 1: Line 1:
'''AINB''' ('''AI''' '''N'''ode '''B'''inary) is a file format implementing behavior trees for game-specific code. At time of writing it has only appeared in titles on the ModuleSystem game engine. This article is primarily aimed at the version that appears in ''Tears of the Kingdom,'' ''Super Mario Bros. Wonder, Mario vs Donkey Kong,'' and the original October 2024 version of ''Nintendo Switch Online: Playtest Program'' (v0x407). An older version appears in ''Nintendo Switch Sports'' and ''Splatoon 3'' (v0x404). ModuleSystem provides 3 built-in file categories that appear in their own dedicated folders in a title's romfs, being "AI" for actor behavior, "Logic" for actor ai group behavior, and "Sequence" for scene behavior, individual games are free to create their own file categories.
'''AINB''' ('''AI''' '''N'''ode '''B'''inary) is a file format implementing behavior trees for game-specific code. At time of writing it has only appeared in titles on the ModuleSystem game engine. This article is primarily aimed at the version that appears in ''Tears of the Kingdom,'' ''Super Mario Bros. Wonder, Mario vs Donkey Kong,'' and the original October 2024 version of ''Nintendo Switch Online: Playtest Program'' (v0x407). ModuleSystem provides 3 built-in file categories that appear in their own dedicated folders in a title's romfs, being "AI" for actor behavior, "Logic" for actor ai group behavior, and "Sequence" for scene behavior, individual games are free to create their own file categories.


=== File Structure ===
=== Version Table ===
AINB is little endian. An AINB file defines a set of commands to evaluate a tree of built-in or game-specific node classes. The built-in "Element_ModuleCaller" node and supporting structures allow a "root" AINB file to call out to an external "module" AINB file, module's can call further modules, allowing AINB files to form a tree of tree's. An AINB's file extension typically designates whether it is a root <code>.root.ainb</code> or module <code>.module.ainb</code>. For AI and Sequence files, the file's entry point is one or more commands which is linked to one or two child nodes. All nodes are accessed by their index (references to query nodes will use their query node index which is local to the amount of query nodes in the file).
{| class="wikitable"
|+
!Version
!Applications
!Differences From Previous
|-
|0x404
|''Nintendo Switch Sports, Splatoon 3''
|
|-
|0x407
|''The Legend of Zelda: Tears of the Kingdom, Super Mario Bros. Wonder, Mario Vs Donkey Kong, Nintendo Switch Online: Playtest Program (010)''
|
|-
|0x408
|''Nintendo Switch Online: Playtest Program (021)''
|>Now uses exb version 3 (u32 support)
>Added u32 type to blackboard
|}
 
== File Structure ==
AINB assumes little endian. Hashes can be assumed to be 32-bit Murmur3 unless otherwise specified.
 
An AINB file defines a set of commands to evaluate a tree of built-in or game-specific node classes. The built-in "Element_ModuleCaller" node and supporting structures allow a "root" AINB file to call out to an external "module" AINB file, module's can call further modules, allowing AINB files to form a tree of tree's. An AINB's file extension typically designates whether it is a root <code>.root.ainb</code> or module <code>.module.ainb</code>. For AI and Sequence files, the file's entry point is one or more commands which is linked to one or two child nodes. All nodes are accessed by their index (references to query nodes will use their query node index which is local to the amount of query nodes in the file).


All string offsets in the file are relative to the beginning of the string pool and name hashes are 32-bit murmur3 hashes. There are six possible data types for AINB parameters: int (signed 32-bit integer), bool, float (32-bit), vector3f, and pointer. Pointer parameters are pointers to objects.
All string offsets in the file are relative to the beginning of the string pool and name hashes are 32-bit murmur3 hashes. There are six possible data types for AINB parameters: int (signed 32-bit integer), bool, float (32-bit), vector3f, and pointer. Pointer parameters are pointers to objects.


==== Section Order ====
=== Section Order ===


# 0x74-Byte File Header
==== Version 0x407 ====
# Commands
# File Header (0x74)
# Nodes
# Command Array
# Local Blackboard Parameters
# Element Array
# Node Bodies
# Blackboard
# Element Param Region
# Attachment Parameters
# Attachment Parameters
# Property Parameters
# Property Parameters
# Input/Output Parameters
# Input/Output Parameters
# Multi-Parameters
# Multi-Parameters
# Active Node Update Array
# Jump Array
# 0x50 Section (Unused in ''TotK'')
# 0x50 Section (Unused in ''TotK'')
# Query Node Array
# Query Id Array
# Expression Binary
# Expression Binary
# AINB Modules
# AINB Modules
Line 29: Line 53:
# String Pool
# String Pool


=== Sections ===
== Structures ==
 
=== Helpers ===
 
==== AinbString ====
Represents a u32 offset relative to a null-terminated string from the start of the file's string pool.
 
==== AinbPtr<T> ====
Represents a u32 absolute offset from the start of the file to the struct of type "T" enclosed by <>.
 
==== AinbArray<T> ====
Represents a u32 absolute offset from the start of the file to:
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|0x0
|0x4
|u32
|Count
|-
|0x4
|
|T[Count]
|Array of struct of type T. Note; asb files only use 32-bit aligned types.
|}


==== File Header ====
=== File Header ===
AINB files begin with a 0x74 byte header. If the offset for a given section is empty, that section is not present in the file.
AINB files begin with a 0x74 byte header. If the offset for a given section is empty, that section is not present in the file.
{| class="wikitable"
{| class="wikitable"
Line 48: Line 100:
|0x04
|0x04
|u32
|u32
|Version (0x0407 in ''TotK'', 0x0404 in ''S3'' and ''NSS'')
|Version
|-
|-
|0x08
|0x08
Line 63: Line 115:
|0x04
|0x04
|u32
|u32
|Node Count
|Element Count
|-
|-
|0x14
|0x14
|0x04
|0x04
|u32
|u32
|Query Node Count
|Query Element Count
|-
|-
|0x18
|0x18
|0x04
|0x04
|u32
|u32
|Attachment Parameter Count
|Attachment Count
|-
|-
|0x1C
|0x1C
|0x04
|0x04
|u32
|u32
|Output Node Count
|Output Element Count
|-
|-
|0x20
|0x20
|0x04
|0x04
|u32
|AinbPtr<Blackboard>
|Local Blackboard Parameters Offset
|Blackboard
|-
|-
|0x24
|0x24
|0x04
|0x04
|u32
|AinbPtr<char>
|String Pool Offset
|String Pool
|-
|-
|0x28
|0x28
|0x04
|0x04
|u32
|AinbPtr<AinbArray<Enum Relocation>>
|Enum Resolve Array Offset
|Enum Relocation Array
|-
|-
|0x2C
|0x2C
|0x04
|0x04
|u32
|AinbPtr<Property Table>
|Property Parameters Offset
|Property Table
|-
|-
|0x30
|0x30
|0x04
|0x04
|u32
|AinbPtr<Jump[]>
|Active Node Update Array Offset
|Jump Table
|-
|-
|0x34
|0x34
|0x04
|0x04
|u32
|AinbPtr<Input Output Table>
|Input/Output Parameters Offset
|Input/Output Table
|-
|-
|0x38
|0x38
|0x04
|0x04
|u32
|AinbPtr<Multi Input[]>
|Multi-Parameters Array Offset
|Multi-Input Array
|-
|-
|0x3C
|0x3C
|0x04
|0x04
|u32
|AinbPtr<Attachment[Attachment Count]>
|Attachment Parameters Offset
|Attachment Array
|-
|-
|0x40
|0x40
|0x04
|0x04
|u32
|AinbPtr<u32[]>
|Attachment Parameters Index Array Offset
|Attachment Id Array
|-
|-
|0x44
|0x44
|0x04
|0x04
|u32
|AinbPtr<Exb>
|Expression Binary Section Offset
|Expression Binary
|-
|-
|0x48
|0x48
|0x04
|0x04
|u32
|u32
|Child Replacement Table Offset
|Child Replacement Table
|-
|-
|0x4C
|0x4C
|0x04
|0x04
|u32
|AinbPtr<u32[]>
|Query Node Array Offset
|Query Element Id Array
|-
|-
|0x50
|0x50
Line 157: Line 209:
|0x5C
|0x5C
|0x04
|0x04
|u32
|AinbPtr<AinbArray<Module Caller>>
|AINB Modules Array Offset
|Module Caller Array
|-
|-
|0x60
|0x60
|0x04
|0x04
|u32
|AinbString
|File Category Name Offset
|File Category Name
|-
|-
|0x64
|0x64
|0x04
|0x04
|u32
|u32
|File Category (0 = AI, 1 = Logic, 2 = Sequence) (''Splatoon 3'' game specific, 3 = UniqueSequenceSPL)
|File Category? (0 = AI, 1 = Logic, 2 = Sequence) (''Splatoon 3'' game specific, 3 = UniqueSequenceSPL)
|-
|-
|0x68
|0x68
|0x04
|0x04
|u32
|AinbPtr<AinbArray<External Action>>
|External Action Array Offset
|External Action Array Offset
|-
|-
Line 182: Line 234:
|0x70
|0x70
|0x04
|0x04
|u32
|AinbPtr<Module Caller Link>
|File Identification Hashes Offset (Purpose Unknown)
|Module Caller Link
|}
|}


==== Command Array ====
=== Command Array ===
The command array immediately follows the file header and is an array of all commands in the file.
The command array immediately follows the file header and is an array of all commands in the file.
{| class="wikitable"
{| class="wikitable"
Line 197: Line 249:
|0x00
|0x00
|0x04
|0x04
|u32
|AinbString
|Command Name Offset
|Name
|-
|-
| rowspan="5" |0x04
|0x04
| rowspan="5" |0x10
|0x10
|u32
|Guid
| rowspan="5" |GUID
|Guid
|-
|u16
|-
|u16
|-
|u16
|-
|u8[6]
|-
|-
|0x14
|0x14
|0x02
|0x02
|u16
|u16
|Main Node Index
|Main Element Id
|-
|-
|0x16
|0x16
|0x02
|0x02
|u16
|u16
|Secondary Node Index (value offset by 1, 0 is reserved)
|Secondary Element Id (value offset by 1, 0 is reserved for invalid)
|}
|}
Command GUIDs are only used for debug messages. Right Node Index will be -1 if the command only has one child node.
Unlike asb, command GUIDs only appear to be used for debug messages. Secondary Element Id will be -1 if the command only has one child element.


==== Node Array ====
=== Property Table ===
The node array immediately follows the command array and is an array of all nodes in the file.
{| class="wikitable"
{| class="wikitable"
|+Node Entry
|+
!Offset
!Offset
!Size
!Size
Line 235: Line 278:
|-
|-
|0x00
|0x00
|0x02
|0x04
|u16
|AsbPtr<Property<s32>[]>
|Node Type Enum (see below)
|Property Array
|-
|0x02
|0x02
|u16
|Node Index
|-
|-
|0x04
|0x04
|0x02
|0x04
|u16
|AsbPtr<Property<bool>[]>
|Attachment Parameters Count
|Property Array
|-
|0x06
|0x01
|bitfield
|Node Flags
|-
|0x07
|0x01
|u8
|
|-
|-
|0x08
|0x08
|0x04
|0x04
|u32
|AsbPtr<Property<float>[]>
|Node Type Name Offset (for UserDefined nodes)
|Property Array
|-
|-
|0x0C
|0x0c
|0x04
|0x04
|u32
|AsbPtr<Property<AinbString>[]>
|Name Hash (version 0x407 only)
|Property Array
|-
|-
|0x10
|0x10
|0x04
|0x04
|u32
|AsbPtr<Property<Vector3f>[]>
|
|Property Array
|-
|-
|0x14
|0x14
|0x04
|0x04
|u32
|AsbPtr<PropertyPointer[]>
|Node Body Offset (relative to the start of the file)
|Property Array
|}
 
==== Property<T> ====
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|-
|0x18
|0x0
|0x02
|0x4
|u16
|AinbString
|EXB Function Count
|Name
|-
|-
|0x1A
|0x4
|0x02
|0x4
|u16
|Property Flags
|EXB Input/Output Field Size
|Flags
|-
|-
|0x1C
|0x8
|0x02
|0x4, or 0xc
|u16
|T
|Multi-Param Count
|Immediate Value
|-
|}
|0x1E
 
|0x02
===== Property Flags =====
|u16
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|0x0
|0x4
|u32 : 16
|Index
|-
|
|
|
|u32 : 1
|Is Use Index
|-
|-
|0x20
|
|0x04
|
|u32
|u32 : 1
|Base Attachment Parameter Index
|Is Not Local Blackboard Index
|-
|-
|0x24
|
|0x02
|
|u16
|u32 : 1
|Base Query Node
|
|-
|-
|0x26
|
|0x02
|
|u16
|u32 : 1
|Query Node Count
|
|-
|0x28
|0x02
|u16
|0x58 Section Entry Offset (relative to the start of the file)
|-
|-
|0x2A
|
|0x02
|
|u16
|u32 : 1
|
|
|-
|-
| rowspan="5" |0x2C
|
| rowspan="5" |0x10
|
|u32
|u32 : 1
| rowspan="5" |GUID
|
|-
|-
|u16
|
|
|u32 : 1
|Is EXB Index
|-
|-
|u16
|
|
|u32 : 1
|Pulse Thread Local Storage
|-
|-
|u16
|
|
|u32 : 1
|Set Pointer Flag Bit Zero
|-
|-
|u8[6]
|
|
|u32 : 7
|
|}
|}
Just like with commands, node GUIDs are only used for debug messages. The 0x58 section entry offset will be empty if unused.
 
==== PropertyPointer ====
{| class="wikitable"
{| class="wikitable"
|+Node Types
|+
!Value (Hex)
!Offset
!Value (Dec)
!Size
!Node Type
!Type
!Description
|-
|-
|0x00
|0x0
|0
|0x4
|UserDefined
|AinbString
|Name
|-
|-
|0x01
|0x4
|1
|0x4
|Element_S32Selector
|AinbString
|Class Name
|-
|-
|0x02
|0x8
|2
|0x4
|Element_Sequential
|Property Flags
|-
|Flags
|0x03
|}
|3
 
|Element_Simultaneous
==== Property Entries ====
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|-
|0x04
|0x0
|4
|0x8
|Element_F32Selector
|Property Type Entry
|S32 Entries
|-
|-
|0x05
|0x8
|5
|0x8
|Element_StringSelector
|Property Type Entry
|Bool Entries
|-
|-
|0x06
|0x10
|6
|0x8
|Element_RandomSelector
|Property Type Entry
|Float Entries
|-
|-
|0x07
|0x18
|7
|0x8
|Element_BoolSelector
|Property Type Entry
|String Entries
|-
|-
|0x08
|0x20
|8
|0x8
|Element_Fork
|Property Type Entry
|Vector3f Entries
|-
|-
|0x09
|0x28
|9
|0x8
|Element_Join
|Property Type Entry
|Pointer Entries
|}
 
===== Property Type Entry =====
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|-
|0x0A
|0x0
|10
|0x4
|Element_Alert
|u32
|Base Index - base index into the Property Table's Property Array for the specified type
|-
|-
|0x14
|0x4
|20
|0x4
|Element_Expression
|u32
|Count
|}
 
=== Input Output Table ===
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|-
|0x64
|0x00
|100
|0x04
|Element_ModuleIF_Input_S32
|AsbPtr<Input<s32>[]>
|Input Array
|-
|-
|0x65
|0x04
|101
|0x04
|Element_ModuleIF_Input_F32
|AsbPtr<Output<s32>[]>
|Output Array
|-
|-
|0x66
|0x08
|102
|0x04
|Element_ModuleIF_Input_Vec3f
|AsbPtr<Input<bool>[]>
|Input Array
|-
|-
|0x67
|0x0c
|103
|0x04
|Element_ModuleIF_Input_String
|AsbPtr<Output<bool[]>
|Output Array
|-
|-
|0x68
|0x10
|104
|0x04
|Element_ModuleIF_Input_Bool
|AsbPtr<Input<float>[]>
|Input Array
|-
|-
|0x69
|0x14
|105
|0x04
|Element_ModuleIF_Input_Ptr
|AsbPtr<Output<float>[]>
|Output Array
|-
|-
|0xC8
|0x18
|200
|0x04
|Element_ModuleIF_Output_S32
|AsbPtr<Input<AinbString>[]>
|Input Array
|-
|-
|0xC9
|0x1c
|201
|0x04
|Element_ModuleIF_Output_F32
|AsbPtr<Output<AinbString>[]>
|Output Array
|-
|-
|0xCA
|0x20
|202
|0x04
|Element_ModuleIF_Output_Vec3f
|AsbPtr<Input<Vector3f>[]>
|Input Array
|-
|-
|0xCB
|0x24
|203
|0x04
|Element_ModuleIF_Output_String
|AsbPtr<Output<Vector3f>[]>
|Output Array
|-
|-
|0xCC
|0x28
|204
|0x04
|Element_ModuleIF_Output_Bool
|AsbPtr<InputPointer[]>
|Input Array
|-
|-
|0xCD
|0x2c
|205
|0x04
|Element_ModuleIF_Output_Ptr
|AsbPtr<OutputPointer[]>
|Output Array
|}
 
==== Input<T> ====
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|0x0
|0x4
|AinbString
|Name
|-
|0x4
|0x2
|s16
|Input Element Id or Base Multi-Input Id
|-
|-
|0x012C
|0x6
|300
|0x2
|Element_ModuleIF_Child
|s16
|Input Element Output Plug Id or Multi-Input Count
|-
|-
|0x0190
|0x8
|400
|0x4
|Element_StateEnd
|Property Flags
|Flags
|-
|-
|0x01F4
|0xc
|500
|0x4, or 0xc
|Element_SplitTiming
|T
|Immediate Value
|}
|}
Node type names are official. For UserDefined nodes, node definitions can be found in a node definition files. This file is located at <code>NodeDefinition/Node.Product.[ver].aidefn.byml.zs</code> in the corresponding file category folder.
If the input element id is between -32768 and -100, then the input uses a multi-input. The multi-input id can be calculated as follows: <code>BaseMultiInputIndex = -100 - Index</code>.
 
==== InputPointer ====
{| class="wikitable"
{| class="wikitable"
|+Node Type Descriptions
|+
!Offset
!Size
!Type
!Type
!Description
!Description
|-
|-
|UserDefined
|0x0
|Custom node type, definition in NodeDefinition
|0x4
|AinbString
|Name
|-
|-
|Element_S32Selector
|0x4
|Conditionally links to a node depending on the value of a signed int
|0x4
|AinbString
|Class Name
|-
|-
|Element_Sequential
|0x8
|Links to nodes sequentially in the order listed
|0x2
|s16
|Input Element Id or Base Multi-Input Id
|-
|-
|Element_Simultaneous
|0xa
|Links simultaneously to multiple nodes
|0x2
|s16
|Input Element Output Plug Id or Multi-Input Count
|-
|-
|Element_F32Selector
|0xc
|Conditionally links to a node depending on the value of 32-bit float
|0x4
|Property Flags
|Flags
|-
|-
|Element_StringSelector
|0x10
|Conditionally links to a node depending on the value of a string
|0x4
|u32
|
|}
 
==== Output<T> ====
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|-
|Element_RandomSelector
|0x0
|Links to a node randomly
|0x4
|AinbString : 31
|Name
|-
|-
|Element_BoolSelector
|
|Conditionally links to a node depending on the value of a bool
|
|u32 : 1
|
|}
 
==== OutputPointer ====
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|-
|Element_Fork
|0x0
|See Active Node Update Array
|0x4
|AinbString : 31
|Name
|-
|-
|Element_Join
|
|See Active Node Update Array
|
|u32 : 1
|
|-
|-
|Element_Alert
|0x4
|Displays a debug message
|0x4
|AinbString
|Class Name
|}
 
==== Input Output Entries ====
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|-
|Element_Expression
|0x0
|Passes values to and from EXB commands
|0x10
|Input Output Type Entry
|S32 Entries
|-
|-
|Element_ModuleIF_Input_S32
|0x10
|Receives a signed int input from the calling AINB file
|0x10
|Input Output Type Entry
|Bool Entries
|-
|-
|Element_ModuleIF_Input_F32
|0x20
|Receives a 32-bit float input from the calling AINB file
|0x10
|Input Output Type Entry
|Float Entries
|-
|-
|Element_ModuleIF_Input_Vec3f
|0x30
|Receives a vector3f input from the calling AINB file
|0x10
|Input Output Type Entry
|String Entries
|-
|-
|Element_ModuleIF_Input_String
|0x40
|Receives a string input from the calling AINB file
|0x10
|Input Output Type Entry
|Vector3f Entries
|-
|-
|Element_ModuleIF_Input_Bool
|0x50
|Receives a bool input from the calling AINB file
|0x10
|Input Output Type Entry
|Pointer Entries
|}
 
===== Input Output Type Entry =====
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|-
|Element_ModuleIF_Input_Ptr
|0x0
|Receives an object pointer input from the calling AINB file
|0x4
|u32
|Input Base Index - base index into the Input Output Table's Input<T> array for the specified type
|-
|-
|Element_ModuleIF_Output_S32
|0x4
|Returns a signed int output from the module to the calling AINB file
|0x4
|u32
|Input Count
|-
|-
|Element_ModuleIF_Output_F32
|0x8
|Returns a 32-bit float output from the module to the calling AINB file
|0x4
|u32
|Output Base Index  - base index into the Input Output Table's Output<T> array for the specified type
|-
|-
|Element_ModuleIF_Output_Vec3f
|0x10
|Returns a vector3f output from the module to the calling AINB file
|0x4
|-
|u32
|Element_ModuleIF_Output_String
|Output Count
|Returns a string output from the module to the calling AINB file
|}
 
=== Element Array ===
The node array immediately follows the command array and is an array of all nodes in the file.
{| class="wikitable"
|+Node Entry
!Offset
!Size
!Type
!Description
|-
|-
|Element_ModuleIF_Output_Bool
|0x00
|Returns a bool output from the module to the calling AINB file
|0x02
|u16
|Element Type
|-
|-
|Element_ModuleIF_Output_Ptr
|0x02
|Returns an object pointer output from the module to the calling AINB file
|0x02
|u16
|Element Id - Index of this element within the element array
|-
|-
|Element_ModuleIF_Child
|0x04
|Returns the node connection name from the module to the calling AINB file
|0x02
|u16
|Attachment Count
|-
|-
|Element_StateEnd
|0x06
|Termination node, specifies what resident node to return to in the calling AINB file
|0x01
|bitfield
|Element Flags
|-
|-
|Element_SplitTiming
|0x07
|Changes when child nodes are run (Enter - first time visiting a node, Update - every frame, Leave - ran upon leaving the node)
|0x01
|}
|u8
{| class="wikitable"
|
|+Node Flags
!Bits
!Description
|-
|-
|1
|0x08
|Is Query Node
|0x04
|AinbString
|Element Type Name (for ApplicationDefined nodes)
|-
|-
|1
|0x0C
|Is Module
|0x04
|u32
|Name Hash (version 0x407+)
|-
|-
|1
|0x10
|Is Resident Node
|0x04
|u32
|
|-
|-
|1
|0x14
|MultiParam Type 2
|0x04
|AinbPtr<ElementParam<Element Type>>
|Element Param
|-
|-
|4
|0x18
|
|0x02
|}
|u16
 
|EXB Function Count
==== Local Blackboard Parameters ====
This section contains an array of the Blackboard parameters used by file. These parameters may be sourced from external Blackboards or parameter files. The section begins with a 0x30 byte section header followed by the array of parameters, an array of default values of said parameters, and an array of file references if applicable. The order of parameters is in the order of string, int, float, bool, vector3f, and pointer. The section header contains six entries, one for each type.
{| class="wikitable"
|+Section Header Entry
!Offset
!Size
!Type
!Description
|-
|-
|0x00
|0x1A
|0x02
|0x02
|u16
|u16
|Number of Entries of the Corresponding Data Type
|EXB Input/Output Field Size
|-
|-
|0x1C
|0x02
|0x02
|u16
|Multi-Param Count
|-
|0x1E
|0x02
|0x02
|u16
|u16
|Parameter Index of the First Entry of the Corresponding Data Type
|
|-
|-
|0x20
|0x04
|0x04
|u32
|Base Attachment Id
|-
|0x24
|0x02
|0x02
|u16
|u16
|Relative Offset of the First Entry of the Corresponding Data Type
|Base Query Element Id
|-
|-
|0x06
|0x26
|0x02
|u16
|Query Element Count
|-
|0x28
|0x02
|u16
|0x58 Section Entry Offset (relative to the start of the file)
|-
|0x2A
|0x02
|0x02
|u16
|u16
|
|
|-
|0x2C
|0x10
|Guid
|Guid
|}
|}
Just like with commands, node GUIDs are only used for debug messages. The 0x58 section entry offset will be empty if unused.
==== Element Type ====
{| class="wikitable"
{| class="wikitable"
|+Local Blackboard Parameter Entry
|+Element Types
!Offset
!Value (Hex)
!Size
!Value (Dec)
!Type
!Node Type
!Description
|-
|-
|0x00
|0x00
|0x04
|0
|bitfield
|Application Defined
|Name Offset and Flags
|-
|0x04
|0x04
|u32
|String Offset (Notes)
|}
{| class="wikitable"
|+Name Offset Flags
!Bits
!Description
|-
|22
|Name Offset
|-
|-
|0x01
|1
|1
|
|Element_S32Selector
|-
|-
|1
|0x02
|Does Not Have File Reference
|2
|Element_Sequential
|-
|-
|7
|0x03
|File Reference Index
|3
|Element_Simultaneous
|-
|-
|1
|0x04
|Is File Reference Valid
|4
|}
|Element_F32Selector
The default value entries vary based on the parameter's data type. For int, float, and bool parameters, the entry is a four byte immediate value. String entries are a four byte string value offset. Vector3f entries are 12 bytes. Note that pointer parameters do not have default value entries and do not have default values.
|-
{| class="wikitable"
|0x05
|+File Reference Entry
|5
!Offset
|Element_StringSelector
!Size
!Type
!Description
|-
|-
|0x00
|0x06
|0x04
|6
|u32
|Element_RandomSelector
|File Path Offset
|-
|-
|0x04
|0x07
|0x04
|7
|u32
|Element_BoolSelector
|File Path Hash
|-
|-
|0x08
|0x08
|0x04
|8
|u32
|Element_Fork
|Filename Hash (no extension)
|-
|-
|0x0C
|0x09
|0x04
|9
|u32
|Element_Join
|File Extension Hash (no .)
|}
 
==== Node Bodies ====
Each node body is composed of two parts: a 0x90 byte parameter section and a 0x14 child node section header followed by said section if applicable. The child node section contains information about the child node and specific connection types. The following parameter indices are indices into the parameter array for that specific type and data type.
{| class="wikitable"
!Offset
!Size
!Type
!Description
|-
|-
|0x00
|0x0A
|0x04
|10
|u32
|Element_Alert
|Int Property Parameter Base Index
|-
|-
|0x04
|0x14
|0x04
|20
|u32
|Element_Expression
|Int Property Parameter Count
|-
|-
|0x08
|0x64
|0x04
|100
|u32
|Element_ModuleIF_Input_S32
|Bool Property Parameter Base Index
|-
|-
|0x0C
|0x65
|0x04
|101
|u32
|Element_ModuleIF_Input_F32
|Bool Property Parameter Count
|-
|-
|0x10
|0x66
|0x04
|102
|u32
|Element_ModuleIF_Input_Vec3f
|Float Property Parameter Base Index
|-
|-
|0x14
|0x67
|0x04
|103
|u32
|Element_ModuleIF_Input_String
|Float Property Parameter Count
|-
|-
|0x18
|0x68
|0x04
|104
|u32
|Element_ModuleIF_Input_Bool
|String Property Parameter Base Index
|-
|-
|0x1C
|0x69
|0x04
|105
|u32
|Element_ModuleIF_Input_Ptr
|String Property Parameter Count
|-
|-
|0x20
|0xC8
|0x04
|200
|u32
|Element_ModuleIF_Output_S32
|Vector3f Property Parameter Base Index
|-
|-
|0x24
|0xC9
|0x04
|201
|u32
|Element_ModuleIF_Output_F32
|Vector3f Property Parameter Count
|-
|-
|0x28
|0xCA
|0x04
|202
|u32
|Element_ModuleIF_Output_Vec3f
|Pointer Property Parameter Base Index
|-
|-
|0x2C
|0xCB
|0x04
|203
|u32
|Element_ModuleIF_Output_String
|Pointer Property Parameter Count
|-
|-
|0x30
|0xCC
|0x04
|204
|u32
|Element_ModuleIF_Output_Bool
|Int Input Parameter Base Index
|-
|-
|0x34
|0xCD
|0x04
|205
|u32
|Element_ModuleIF_Output_Ptr
|Int Input Parameter Count
|-
|-
|0x38
|0x012C
|0x04
|300
|u32
|Element_ModuleIF_Child
|Int Output Parameter Base Index
|-
|-
|0x3C
|0x0190
|0x04
|400
|u32
|Element_StateEnd
|Int Output Parameter Count
|-
|-
|0x40
|0x01F4
|0x04
|500
|u32
|Element_SplitTiming
|Bool Input Parameter Base Index
|}
Element type names are official (outside ApplicationDefined). For ApplicationDefined elements, definitions can be found in a node definition file for the respective file category. This file is located at <code>NodeDefinition/Node.Product.[ver].aidefn.byml.zs</code> in the corresponding file category folder.
{| class="wikitable"
|+Node Type Descriptions
!Type
!Description
|-
|-
|0x44
|UserDefined
|0x04
|Custom node type, definition in NodeDefinition
|u32
|Bool Input Parameter Count
|-
|-
|0x48
|Element_S32Selector
|0x04
|Conditionally links to a node depending on the value of a signed int
|u32
|Bool Output Parameter Base Index
|-
|-
|0x4C
|Element_Sequential
|0x04
|Links to nodes sequentially in the order listed
|u32
|Bool Output Parameter Count
|-
|-
|0x50
|Element_Simultaneous
|0x04
|Links simultaneously to multiple nodes
|u32
|Float Input Parameter Base Index
|-
|-
|0x54
|Element_F32Selector
|0x04
|Conditionally links to a node depending on the value of 32-bit float
|u32
|Float Input Parameter Count
|-
|-
|0x58
|Element_StringSelector
|0x04
|Conditionally links to a node depending on the value of a string
|u32
|Float Output Parameter Base Index
|-
|-
|0x5C
|Element_RandomSelector
|0x04
|Links to a node randomly
|u32
|Float Output Parameter Count
|-
|-
|0x60
|Element_BoolSelector
|0x04
|Conditionally links to a node depending on the value of a bool
|u32
|String Input Parameter Base Index
|-
|-
|0x64
|Element_Fork
|0x04
|See Active Node Update Array
|u32
|String Input Parameter Count
|-
|-
|0x68
|Element_Join
|0x04
|See Active Node Update Array
|u32
|String Output Parameter Base Index
|-
|-
|0x6C
|Element_Alert
|0x04
|Displays a debug message
|u32
|String Output Parameter Count
|-
|-
|0x70
|Element_Expression
|0x04
|Passes values to and from EXB commands
|u32
|Vector3f Input Parameter Base Index
|-
|-
|0x74
|Element_ModuleIF_Input_S32
|0x04
|Receives a signed int input from the calling AINB file
|u32
|Vector3f Input Parameter Count
|-
|-
|0x78
|Element_ModuleIF_Input_F32
|0x04
|Receives a 32-bit float input from the calling AINB file
|u32
|Vector3f Output Parameter Base Index
|-
|-
|0x7C
|Element_ModuleIF_Input_Vec3f
|0x04
|Receives a vector3f input from the calling AINB file
|u32
|Vector3f Output Parameter Count
|-
|-
|0x80
|Element_ModuleIF_Input_String
|0x04
|Receives a string input from the calling AINB file
|u32
|Pointer Input Parameter Base Index
|-
|-
|0x84
|Element_ModuleIF_Input_Bool
|0x04
|Receives a bool input from the calling AINB file
|u32
|Pointer Input Parameter Count
|-
|-
|0x88
|Element_ModuleIF_Input_Ptr
|0x04
|Receives an object pointer input from the calling AINB file
|u32
|Pointer Output Parameter Base Index
|-
|-
|0x8C
|Element_ModuleIF_Output_S32
|0x04
|Returns a signed int output from the module to the calling AINB file
|u32
|Pointer Output Parameter Count
|}
{| class="wikitable"
|+Child Node Section Header
!Offset
!Size
!Type
!Description
|-
|-
|0x00
|Element_ModuleIF_Output_F32
|0x01
|Returns a 32-bit float output from the module to the calling AINB file
|u8
|Bool/float Input Source Node/Output Source Node Count
|-
|-
|0x01
|Element_ModuleIF_Output_Vec3f
|0x01
|Returns a vector3f output from the module to the calling AINB file
|u8
|Bool/float Input Source Node/Output Source Node Base Index
|-
|-
|0x02
|Element_ModuleIF_Output_String
|0x01
|Returns a string output from the module to the calling AINB file
|u8
|Unknown Connection Type Count (Unused in ''TotK'')
|-
|-
|0x03
|Element_ModuleIF_Output_Bool
|0x01
|Returns a bool output from the module to the calling AINB file
|u8
|Unknown Connection Type Base Index (Unused ''TotK'')
|-
|-
|0x04
|Element_ModuleIF_Output_Ptr
|0x01
|Returns an object pointer output from the module to the calling AINB file
|u8
|Standard Child Node Count
|-
|-
|0x05
|Element_ModuleIF_Child
|0x01
|Returns the node connection name from the module to the calling AINB file
|u8
|Standard Child Node Base Index
|-
|-
|0x06
|Element_StateEnd
|0x01
|Termination node, specifies what resident node to return to in the calling AINB file
|u8
|-
|Active Node Update Count
|Element_SplitTiming
|Changes when child nodes are run (Enter - first time visiting a node, Update - every frame, Leave - ran upon leaving the node)
|}
 
==== Element Flags ====
{| class="wikitable"
|+Element Flags
!Bits
!Description
|-
|-
|0x07
|1
|0x01
|Is Query Element
|u8
|Active Node Update Base Index
|-
|-
|0x08
|1
|0x01
|Is Module Caller
|u8
|String Input Source Node Count
|-
|-
|0x09
|1
|0x01
|Is Resident Initialized
|u8
|String Input Source Node Base Index
|-
|-
|0x0A
|1
|0x01
|Is Query Multi-Param
|u8
|Int Input Source Node Count
|-
|-
|0x0B
|4
|0x01
|
|u8
|}
|Int Input Source Node Base Index
 
==== ElementParam<T> ====
Each element contains a table into the 4 parameter types, properties, inputs, outputs, and plugs. The child plugs inform the structure of the element tree.
{| class="wikitable"
|+
!Offset
!Size
!Type
!Description
|-
|-
|0x0C
|0x0
|0x01
|0x30
|u8
|Property Entries
|Unknown Connection Type Count (Unused in ''TotK'')
|Entries into the Property Table.
|-
|-
|0x0D
|0x30
|0x01
|0x60
|u8
|Input Output Entries
|Unknown Connection Type Base Index (Unused ''TotK'')
|Entries into the Input Output Table.
|-
|-
|0x0E
|0x90
|0x01
|0x14
|u8
|Plug Entries
|Unknown Connection Type Count (Unused in ''TotK'')
|Entries into the following plug pointer array.
|-
|-
|0x0F
|0xa4
|0x01
|AsbPtr<>[Total Plug Count]
|u8
|Plug Data
|Unknown Connection Type Base Index (Unused ''TotK'')
|Plug Data Pointer Array.
|-
|}
|0x10
 
|0x01
===== Plug Entries =====
|u8
|Unknown Connection Type Count (Unused in ''TotK'')
|-
|0x11
|0x01
|u8
|Unknown Connection Type Base Index (Unused ''TotK'')
|-
|0x12
|0x01
|u8
|Unknown Connection Type Count (Unused in ''TotK'')
|-
|0x13
|0x01
|u8
|Unknown Connection Type Base Index (Unused ''TotK'')
|}
If the node has any child nodes, the section header is followed by an array of u32 offsets to each of the child node entries. For most nodes, each entry is eight bytes.
{| class="wikitable"
{| class="wikitable"
|+Child Node Entry
|+
!Offset
!Offset
!Size
!Size
Line 958: Line 1,101:
!Description
!Description
|-
|-
|0x00
|0x0
|0x04
|0x2
|u32
|Plug Type Entry
|Child Node Index
|Bool/float Input Source/Output Source
|-
|0x2
|0x2
|Plug Type Entry
|
|-
|-
|0x04
|0x4
|0x04
|0x2
|u32
|Plug Type Entry
|Value
|Child Plugs
|-
|0x6
|0x2
|Plug Type Entry
|Jump Plugs
|-
|0x8
|0x2
|Plug Type Entry
|String Input Source
|-
|0xa
|0x2
|Plug Type Entry
|Int Input Source
|-
|0xc
|0x2
|Plug Type Entry
|
|-
|0xe
|0x2
|Plug Type Entry
|
|-
|0x10
|0x2
|Plug Type Entry
|
|-
|0x12
|0x2
|Plug Type Entry
|
|}
|}
The interpretation of the value depends on the connection type. For input or output connections, the value is a string offset to the parameter name. For standard connections, the value is a string offset to the connection name. For active node update connections, the value is an index into the active node update array. Certain node/connection types will also extend the entry length. Selector-type nodes excluding <code>Element_BoolSelector</code> and <code>Element_F32Selector</code> will have an extra four bytes which stores the condition for to link to the child node. For <code>Element_S32Selector</code>, this is an immediate value. For <code>Element_RandomSelector</code>, this is a weight and for <code>Element_StringSelector</code> it is a u32 string offset. The condition for  <code>Element_BoolSelector</code> is the entry's value string. <code>Element_F32Selector</code> adds 24 bytes to each entry, consisting of four eight-byte sub-entries.
 
====== Plug Type Entry ======
{| class="wikitable"
{| class="wikitable"
|+<code>Element_F32Selector Condition Entry</code>
|+
!Offset
!Offset
!Size
!Size
Line 976: Line 1,160:
!Description
!Description
|-
|-
|0x00
|0x0
|0x04
|0x1
|u32
|u8
|Local Blackboard Parameter Index and Flags
|Count
|-
|-
|0x04
|0x1
|0x04
|0x1
|float
|u8
|Condition Value
|Base Index - base index into Plug Pointer Array
|}
|}
The first two bytes of the four bytes at offset 0x00 are the local blackboard parameter index while the last bit is whether or not the index is used or not. The first entry for <code>Element_F32Selector</code> is the minimum value condition while the second entry is the maximum value condition. The last two entries appear to be unused. The last child node entry for Selector-type nodes is the default case. The condition for this case is either a string offset to the string その他 ("Other") or 0 (in the case of <code>Element_S32Selector</code>). Input nodes that are Selector-type nodes also appear to have an additional eight bytes (purpose unknown). <code>Element_Expression</code> have an additional eight bytes per input node (16 bytes in the case of vector3f entries). The purpose of these bytes is unknown.


==== Attachment Parameters ====
====== Plugs ======
This section contains an array of attachments for nodes. This section is preceded by the attachment index array which is an array of u32 indices into the entries in this section. Nodes contain an index into the index array rather than directly into this section. The section contains an array of entries followed by an array of parameter entries.
{| class="wikitable"
{| class="wikitable"
|+Attachment Parameter Entry
|+
Typical Plug Data
!Offset
!Offset
!Size
!Size
Line 1,000: Line 1,183:
|0x04
|0x04
|u32
|u32
|Name Offset
|Element Id
|-
|-
|0x04
|0x04
|0x04
|0x04
|u32
|u32
|Parameters Entry Offset
|Value
|-
|0x08
|0x02
|u16
|EXB Function Count
|-
|0x0A
|0x02
|u16
|EXB Input/Output Field Size
|-
|0x0C
|0x04
|u32
|Name Hash (version 0x0407 only)
|}
|}
The interpretation of the value depends on the connection type. For input or output connections, the value is a string of the parameter name. For standard connections, the value is a string of the connection name. For jump connections, the value is an id into the Jump Table. Elements are free to extend the plug data with their own element specific values. For built-in element selector-types, excluding <code>Element_BoolSelector</code> and <code>Element_F32Selector</code>, an extra four bytes stores data used to select the child plug. For <code>Element_S32Selector</code>, this is an immediate value. For <code>Element_RandomSelector</code>, this is a weight and for <code>Element_StringSelector</code> it is a string. The condition for  <code>Element_BoolSelector</code> is the entry's value string. <code>Element_F32Selector</code> adds 24 bytes to each entry, consisting of four eight-byte sub-entries.
{| class="wikitable"
{| class="wikitable"
|+Parameter Entry
|+<code>Element_F32Selector Condition Entry</code>
!Offset
!Offset
!Size
!Size
Line 1,032: Line 1,201:
|0x04
|0x04
|u32
|u32
|Unknown (possibly related to debug)
|Local Blackboard Parameter Index and Flags
|-
|-
|0x04
|0x04
|0x04
|0x04
|u32
|float
|Int Property Parameter Base Index
|Condition Value
|}
The first two bytes of the four bytes at offset 0x00 are the blackboard parameter index while the last bit is whether or not the index is used or not. The first entry for <code>Element_F32Selector</code> is the minimum value condition while the second entry is the maximum value condition. The last two entries appear to be unused. The last child element entry for Selector-type nodes is the default case. The condition for this case is either the string その他 ("Other") or 0 (in the case of <code>Element_S32Selector</code>). Input elements that are Selector-type elements also appear to have an additional eight bytes (purpose unknown). <code>Element_Expression</code> has an additional eight bytes per input element (16 bytes in the case of vector3f entries). The purpose of these bytes is unknown.
 
=== Blackboard ===
This section contains an array of the Blackboard parameters used by file. These parameters may be sourced from external Blackboards or parameter files. The section begins with a 0x30 byte section header followed by the array of parameters, an array of default values of said parameters, and an array of file references if applicable. The order of parameters is in the order of string, int, float, bool, vector3f, and pointer. The section header contains six entries, one for each type.
{| class="wikitable"
|+Section Header Entry
!Offset
!Size
!Type
!Description
|-
|-
|0x08
|0x00
|0x04
|0x02
|u32
|u16
|Int Property Parameter Count
|Number of Entries of the Corresponding Data Type
|-
|-
|0x0C
|0x02
|0x04
|0x02
|u32
|u16
|Bool Property Parameter Base Index
|Parameter Index of the First Entry of the Corresponding Data Type
|-
|-
|0x10
|0x04
|0x04
|u32
|0x02
|Bool Property Parameter Count
|u16
|Relative Offset of the First Entry of the Corresponding Data Type
|-
|-
|0x14
|0x06
|0x04
|0x02
|u32
|u16
|Float Property Parameter Base Index
|
|}
{| class="wikitable"
|+Local Blackboard Parameter Entry
!Offset
!Size
!Type
!Description
|-
|-
|0x18
|0x00
|0x04
|0x04
|u32
|bitfield
|Float Property Parameter Count
|Name Offset and Flags
|-
|-
|0x1C
|0x04
|0x04
|u32
|String Property Parameter Base Index
|-
|0x20
|0x04
|0x04
|u32
|u32
|String Property Parameter Count
|String Offset (Notes)
|-
|}
|0x24
{| class="wikitable"
|0x04
|+Name Offset Flags
|u32
!Bits
|Vector3f Property Parameter Base Index
!Description
|-
|-
|0x28
|22
|0x04
|Name Offset
|u32
|Vector3f Property Parameter Count
|-
|-
|0x2C
|1
|0x04
|
|u32
|Pointer Property Parameter Base Index
|-
|-
|0x30
|1
|0x04
|Does Not Have File Reference
|u32
|Pointer Property Parameter Count
|-
|-
|0x34
|7
|0x04
|File Reference Index
|u32
|
|-
|-
|0x38
|1
|0x04
|Is File Reference Valid
|u32
|}
|Unknown (contains address to next entry)
The default value entries vary based on the parameter's data type. For int, float, and bool parameters, the entry is a four byte immediate value. String entries are a four byte string value offset. Vector3f entries are 12 bytes. Note that pointer parameters do not have default value entries and do not have default values.
{| class="wikitable"
|+File Reference Entry
!Offset
!Size
!Type
!Description
|-
|-
|0x3C
|0x00
|0x04
|0x04
|u32
|u32
|
|File Path Offset
|-
|-
|0x40
|0x04
|0x04
|u32
|Unknown (contains address to next entry)
|-
|0x44
|0x04
|0x04
|u32
|u32
|
|File Path Hash
|-
|-
|0x48
|0x08
|0x04
|0x04
|u32
|u32
|Unknown (contains address to next entry)
|Filename Hash (no extension)
|-
|-
|0x4C
|0x0C
|0x04
|0x04
|u32
|u32
|
|File Extension Hash (no .)
|-
|0x50
|0x04
|u32
|Unknown (contains address to next entry)
|-
|0x54
|0x04
|u32
|
|-
|0x58
|0x04
|u32
|Unknown (contains address to next entry)
|-
|0x5C
|0x04
|u32
|
|-
|0x60
|0x04
|u32
|Unknown (contains address to next entry)
|}
|}


==== Property Parameters ====
=== Attachments ===
This section contains an array of property parameters for nodes. The section begins with a six u32 relative offsets to the first entry for each data type. The data type order for this section is int, bool, float, string, vector3f, and pointer.
{| class="wikitable"
{| class="wikitable"
|+Parameter Entry
|+
!Offset
!Offset
!Size
!Size
Line 1,166: Line 1,315:
|0x00
|0x00
|0x04
|0x04
|u32
|AinbString
|Name Offset
|Name
|-
|-
|0x04
|0x04
|0x04
|0x04
|u32
|AinbPtr<Attachment Param>
|Flags
|Parameters Entry Offset
|-
|-
|0x08
|0x08
|
|0x02
|
|u16
|Value
|EXB Function Count
|-
|0x0A
|0x02
|u16
|EXB Input/Output Field Size
|-
|0x0C
|0x04
|u32
|Name Hash (version 0x407+)
|}
 
==== Attachment Param ====
{| class="wikitable"
|}
|}
The value is an immediate value for the data type (excluding string which is a string offset and pointer which doesn't store a value). Pointer entries also have an additional u32 class name offset at offset 0x04, pushing the flags to offset 0x08.
{| class="wikitable"
{| class="wikitable"
|+Parameter Flags
|+Parameter Entry
!Bits
!Offset
!Size
!Type
!Description
!Description
|-
|-
|16
|0x00
|Source Index
|0x1
|u8
|Unknown (possibly related to debug)
|-
|-
|1
|0x01
|Is Use Index
|0x3
|-
|u24
|1
|Is Not Local Blackboard Index
|-
|1
|
|
|-
|-
|1
|0x4
|
|0x30
|-
|Property Entries
|1
|Property Entries
|
|-
|1
|
|-
|1
|Is EXB Index
|-
|1
|Pulse Thread Local Storage
|-
|1
|Set Pointer Flag Bit Zero
|-
|2
|
|-
|2
|
|-
|2
|
|}
 
==== Input/Output Parameters ====
This section contains an array of input and output parameter entries. These appear to be canonically referred to as "plugs". Similarly to the property parameters section, the section begins with u32 relative offsets to the first entry of each data type. However, instead of six offsets, there are 12 - two for each data type (one input, one output). The order of parameters in this section is int input, int output, bool input, bool output, float intput, float output, string input, string output, vector3f input, vector3f output, pointer input, and pointer output.
{| class="wikitable"
|+Input Parameter Entry
!Offset
!Size
!Type
!Description
|-
|0x00
|0x04
|u32
|Name Offset
|-
|0x04
|0x02
|s16
|Input Child Node Index / Multi-Parameter Array Base Index
|-
|0x06
|0x02
|s16
|Input/Output Source Node Index / Multi-Parameter Count
|-
|0x08
|0x04
|u32
|Flags
|-
|0x0C
|
|
|Default Value
|}
The default value is an immediate value for the data type (excluding string which is a string offset and pointer which is always an empty four bytes). Pointer entries also have an additional u32 class name offset at offset 0x04, pushing the rest of the entry back by four bytes. If the input child node index is between -32768 and -100, it corresponds to a multi-parameter array index. The multi-parameter index can be calculated as follows: <code>MultiParamIndex = -100 - Index</code>.
{| class="wikitable"
|+Parameter Flags
!Bits
!Description
|-
|16
|Source Index
|-
|1
|Is Use Index
|-
|1
|Is Not Local Blackboard Index
|-
|1
|
|-
|1
|
|-
|1
|
|-
|1
|
|-
|1
|Is EXB Index
|-
|1
|Pulse Thread Local Storage
|-
|1
|Set Pointer Flag Bit Zero
|-
|2
|
|-
|2
|
|-
|2
|
|}
|}
Each output parameter entry is four bytes.
{| class="wikitable"
{| class="wikitable"
|+Output Parameter Entry
!Bits
!Description
|-
|31
|Name Offset
|-
|1
|Set Pointer Flag Bit Zero
|}
|}
==== Multi-Parameters ====
This section contains entries specifying parameters that have multiple values and the sources of those values. Each entry is eight bytes.
{| class="wikitable"
{| class="wikitable"
|+Multi-Parameter Entry
|+Multi-Input Entry
!Offset
!Offset
!Size
!Size
Line 1,340: Line 1,387:
|u32
|u32
|Flags
|Flags
|}
{| class="wikitable"
|+Parameter Flags
!Bits
!Description
|-
|16
|Source Index
|-
|1
|Is Use Index
|-
|1
|Is Not Local Blackboard Index
|-
|1
|
|-
|1
|
|-
|1
|
|-
|1
|
|-
|1
|Is EXB Index
|-
|1
|Pulse Thread Local Storage
|-
|1
|Set Pointer Flag Bit Zero
|-
|2
|
|-
|2
|
|-
|2
|
|}
|}


==== Active Node Update Array ====
=== Jump ===
This section is an array of entries for updates to the active node array. The first four bytes specify the number of entries. Each entry is four bytes.
{| class="wikitable"
{| class="wikitable"
|+
|+
Line 1,402: Line 1,404:
|Update Post Calc
|Update Post Calc
|}
|}
If the first byte of the flags is set to false, then the entry contains another four bytes with a string offset (purpose unknown). Otherwise, the entry is considered valid if the first byte equals 1. When processing a node graph, the game maintains an array of active root nodes. When a command calculated, the root node of the command is added to this array and it and its child nodes are calculated recursively. An active node update will change the current active root node to the specified node. This usually happens right before the next command's calculation occurs, but if the top bit is set, then it will occur immediately after the current command's calculation finishes (if the source node is an Element_Join nodes, it will always update the active node post current command calculation). This is primarily used for "subroutines" that run a single time then return to the main execution routine. This system is also used for Element_Fork and Element_Join nodes. An Element_Fork node, unlike normal nodes, will replace the entire current active node array with its array of active node updates (essentially forking execution into multiple different paths). The node at the end of each of these paths will optionally also have an active node update referencing a specific Element_Join node. Each of these nodes will push the Element_Join into the active node array. However, Element_Join nodes have an property parameter called InFlowNum and until it has been pushed onto the array that many times in a single calculation, it will not activate and remain dormant. However, once this threshold is reached, it will begin execution (with a guard to make sure only one of the instances added to the array will execute).
If the first byte of the flags is set to false, then the entry contains another four bytes with a string offset (purpose unknown). Otherwise, the entry is considered valid if the first byte equals 1. When evaluating the behavior trees, the game maintains an array of each root element. When a command is set, the root element of the command is set to this context. A jump will change that root element to the element specified by the jump plug's element id. This usually happens right before the next command's calculation occurs, but if the top bit is set, then it will occur immediately after the current command's calculation finishes (if the source element is an Element_Join, it will always update the root elements post current command calculation). This is primarily used for "subroutines" that run a single time then return to the main execution routine. Element_Fork and Element_Join are the main mechanism to manage multiple root elements. An Element_Fork will replace the current root elements with the element id's of it's jump plugs, possibly "forking" execution into multiple roots. The element at the end of a root element specified by an Element_Fork will optionally have a jump plug referencing a specific Element_Join. Each of these elements will push the Element_Join into the root element array. However, Element_Join has a property parameter called InFlowNum, and until that element has been pushed onto the root element array that many times in a single calculation, it will not activate and remain dormant. However, once this threshold is reached, it will begin execution (with a guard to make sure only one of the instances added to the array will execute).


==== 0x50 Section ====
=== 0x50 Section ===
This section is unused in ''Tears of the Kingdom''.
This section is unused in ''Tears of the Kingdom''.


==== Query Node Array ====
=== Query Element Id Array ===
This section is an array of entries of query nodes present in the file.
This section is an array of entries of query element ids present in the file.
{| class="wikitable"
{| class="wikitable"
|+Query Node Entry
|+Query Node Entry
Line 1,419: Line 1,421:
|0x02
|0x02
|u16
|u16
|Query Node Index (local to number of query nodes)
|Query Element Id (local to number of query nodes)
|-
|-
|0x02
|0x02
Line 1,427: Line 1,429:
|}
|}


==== Expression Binary Section ====
=== Expression Binary ===
The '''EXB''' ('''Ex'''pression '''B'''inary) section is a completely self-contained section that stores custom instructions for a simple command processor. These instructions are grouped into functions that can be called by nodes to perform calculations. Because the section is self-contained, all offsets in this section are local to the section. The EXB section is shared with ASB files ('''A'''nimation '''S'''equence '''B'''inary).
The '''EXB''' ('''Ex'''pression '''B'''inary) section is a completely self-contained section that stores custom instructions for a simple command processor. These instructions are grouped into functions that can be called by nodes to perform calculations. Because the section is self-contained, all offsets in this section are local to the section. The EXB section is shared with ASB files ('''A'''nimation '''S'''equence '''B'''inary).


Line 1,856: Line 1,858:
The string pool is an array of null-terminated strings encoded with UTF-8. All string offsets in this section are relative to the beginning of the string pool.
The string pool is an array of null-terminated strings encoded with UTF-8. All string offsets in this section are relative to the beginning of the string pool.


==== AINB Modules ====
=== Module Caller ===
This section contains an array of all AINB modules linked to the current AINB file. The first four bytes specify the entry count.
This section contains an array of all AINB modules linked to the current AINB file. The first four bytes specify the entry count.
{| class="wikitable"
{| class="wikitable"
Line 1,881: Line 1,883:
|}
|}


==== External Action Array ====
=== External Action Array ===
This section appears to interact with XLink. The first four bytes specify the entry count.
This section appears to interact with XLink. The first four bytes specify the entry count.
{| class="wikitable"
{| class="wikitable"
Line 1,906: Line 1,908:
|}
|}


==== File Hashes ====
=== Module Caller Link ===
This section contains two 32-bit file hashes. The first hash is a hash for the file itself and the second hash appears to be a hash for that file's parent file. The purpose of these hashes is unclear.
This section contains two 32-bit file hashes. The first hash is a hash for the file itself and the second hash appears to be a hash for that file's parent file. These are used by Element_ModuleCaller.


==== Child Replacement Table ====
=== Child Replacement Table ===
This section is used to remove or replace specific nodes or attachments at runtime. This is used to toggle of debug nodes/attachments for release builds. The section begins with an eight-byte section header.
This section is used to remove or replace specific elements or attachments at runtime. This is used to toggle off debug elements/attachments in release builds. The section begins with an eight-byte section header.
{| class="wikitable"
{| class="wikitable"
|+Child Replacement Section Header
|+Child Replacement Section Header
Line 1,936: Line 1,938:
|0x02
|0x02
|s16
|s16
|Override Node Count
|Override Element Count
|-
|-
|0x06
|0x06
Line 1,953: Line 1,955:
|0x01
|0x01
|u8
|u8
|Replacement Type Enum (0 = remove child node, 1 = replace child node, 2 = remove attachment)
|Replacement Type Enum (0 = remove child element, 1 = replace child element, 2 = remove attachment)
|-
|-
|0x01
|0x01
Line 1,963: Line 1,965:
|0x02
|0x02
|u16
|u16
|Node Index
|Element Id
|-
|-
|0x04
|0x04
|0x02
|0x02
|u16
|u16
|Child Node Index/Attachment Index
|Child Element Id/Attachment Id
|-
|-
|0x06
|0x06
|0x02
|0x02
|u16
|u16
|New Node Index (for child node replacements)
|New Element Id (for child element replacements)
|}
|}


==== 0x6C Section ====
=== 0x6C Section ===
This section is unused in ''Tears of the Kingdom''.
This section is unused in ''Tears of the Kingdom''.


==== Enum Resolve Array ====
=== Enum Relocation ===
This section is used to resolve enum values at runtime. This section is unused in ''Tears of the Kingdom'' as all enum values are statically present in the file. However, in ''Splatoon 3'', this section is used extensively as all enum values are stored in the main executable. The first four bytes of this section specifies the number of entries in the section.
This section is used to resolve enum values at runtime. This section is unused in ''Tears of the Kingdom'' as all enum values are statically present in the file. However, in ''Splatoon 3'', this section is used extensively as all enum values are stored in the main executable. The first four bytes of this section specifies the number of entries in the section.
{| class="wikitable"
{| class="wikitable"
Line 2,004: Line 2,006:
|}
|}


==== String Pool ====
=== String Pool ===
The string pool is an array of null-terminated strings encoded with UTF-8. All string offsets in the file are relative to the first byte of this section. Note that this section also contains some unreferenced strings which are the enums for certain parameters.
The string pool is an array of null-terminated strings encoded with UTF-8. All string offsets in the file are relative to the first byte of this section. Note that this section also contains some unreferenced strings which are the enums for certain parameters.
[[Category:File formats]]
[[Category:File formats]]

Revision as of 03:32, 8 January 2026

AINB (AI Node Binary) is a file format implementing behavior trees for game-specific code. At time of writing it has only appeared in titles on the ModuleSystem game engine. This article is primarily aimed at the version that appears in Tears of the Kingdom, Super Mario Bros. Wonder, Mario vs Donkey Kong, and the original October 2024 version of Nintendo Switch Online: Playtest Program (v0x407). ModuleSystem provides 3 built-in file categories that appear in their own dedicated folders in a title's romfs, being "AI" for actor behavior, "Logic" for actor ai group behavior, and "Sequence" for scene behavior, individual games are free to create their own file categories.

Version Table

Version Applications Differences From Previous
0x404 Nintendo Switch Sports, Splatoon 3
0x407 The Legend of Zelda: Tears of the Kingdom, Super Mario Bros. Wonder, Mario Vs Donkey Kong, Nintendo Switch Online: Playtest Program (010)
0x408 Nintendo Switch Online: Playtest Program (021) >Now uses exb version 3 (u32 support)

>Added u32 type to blackboard

File Structure

AINB assumes little endian. Hashes can be assumed to be 32-bit Murmur3 unless otherwise specified.

An AINB file defines a set of commands to evaluate a tree of built-in or game-specific node classes. The built-in "Element_ModuleCaller" node and supporting structures allow a "root" AINB file to call out to an external "module" AINB file, module's can call further modules, allowing AINB files to form a tree of tree's. An AINB's file extension typically designates whether it is a root .root.ainb or module .module.ainb. For AI and Sequence files, the file's entry point is one or more commands which is linked to one or two child nodes. All nodes are accessed by their index (references to query nodes will use their query node index which is local to the amount of query nodes in the file).

All string offsets in the file are relative to the beginning of the string pool and name hashes are 32-bit murmur3 hashes. There are six possible data types for AINB parameters: int (signed 32-bit integer), bool, float (32-bit), vector3f, and pointer. Pointer parameters are pointers to objects.

Section Order

Version 0x407

  1. File Header (0x74)
  2. Command Array
  3. Element Array
  4. Blackboard
  5. Element Param Region
  6. Attachment Parameters
  7. Property Parameters
  8. Input/Output Parameters
  9. Multi-Parameters
  10. Jump Array
  11. 0x50 Section (Unused in TotK)
  12. Query Id Array
  13. Expression Binary
  14. AINB Modules
  15. External Action Array
  16. File Hashes
  17. Child Replacement Table
  18. 0x6C Section
  19. Enum Resolve Array
  20. String Pool

Structures

Helpers

AinbString

Represents a u32 offset relative to a null-terminated string from the start of the file's string pool.

AinbPtr<T>

Represents a u32 absolute offset from the start of the file to the struct of type "T" enclosed by <>.

AinbArray<T>

Represents a u32 absolute offset from the start of the file to:

Offset Size Type Description
0x0 0x4 u32 Count
0x4 T[Count] Array of struct of type T. Note; asb files only use 32-bit aligned types.

File Header

AINB files begin with a 0x74 byte header. If the offset for a given section is empty, that section is not present in the file.

File Header
Offset Size Type Description
0x00 0x04 char[4] Magic - “AIB “
0x04 0x04 u32 Version
0x08 0x04 u32 Filename Offset
0x0C 0x04 u32 Command Count
0x10 0x04 u32 Element Count
0x14 0x04 u32 Query Element Count
0x18 0x04 u32 Attachment Count
0x1C 0x04 u32 Output Element Count
0x20 0x04 AinbPtr<Blackboard> Blackboard
0x24 0x04 AinbPtr<char> String Pool
0x28 0x04 AinbPtr<AinbArray<Enum Relocation>> Enum Relocation Array
0x2C 0x04 AinbPtr<Property Table> Property Table
0x30 0x04 AinbPtr<Jump[]> Jump Table
0x34 0x04 AinbPtr<Input Output Table> Input/Output Table
0x38 0x04 AinbPtr<Multi Input[]> Multi-Input Array
0x3C 0x04 AinbPtr<Attachment[Attachment Count]> Attachment Array
0x40 0x04 AinbPtr<u32[]> Attachment Id Array
0x44 0x04 AinbPtr<Exb> Expression Binary
0x48 0x04 u32 Child Replacement Table
0x4C 0x04 AinbPtr<u32[]> Query Element Id Array
0x50 0x04 u32 Unknown (unused in TotK, always the same as the Active Node Update Array Offset)
0x54 0x04 u32 Unknown (always 0)
0x58 0x04 u32 Unknown (always 0, used in Splatoon 3/Nintendo Switch Sports)
0x5C 0x04 AinbPtr<AinbArray<Module Caller>> Module Caller Array
0x60 0x04 AinbString File Category Name
0x64 0x04 u32 File Category? (0 = AI, 1 = Logic, 2 = Sequence) (Splatoon 3 game specific, 3 = UniqueSequenceSPL)
0x68 0x04 AinbPtr<AinbArray<External Action>> External Action Array Offset
0x6C 0x04 u32 Unknown (Unused in TotK)
0x70 0x04 AinbPtr<Module Caller Link> Module Caller Link

Command Array

The command array immediately follows the file header and is an array of all commands in the file.

Command Entry
Offset Size Type Description
0x00 0x04 AinbString Name
0x04 0x10 Guid Guid
0x14 0x02 u16 Main Element Id
0x16 0x02 u16 Secondary Element Id (value offset by 1, 0 is reserved for invalid)

Unlike asb, command GUIDs only appear to be used for debug messages. Secondary Element Id will be -1 if the command only has one child element.

Property Table

Offset Size Type Description
0x00 0x04 AsbPtr<Property<s32>[]> Property Array
0x04 0x04 AsbPtr<Property<bool>[]> Property Array
0x08 0x04 AsbPtr<Property<float>[]> Property Array
0x0c 0x04 AsbPtr<Property<AinbString>[]> Property Array
0x10 0x04 AsbPtr<Property<Vector3f>[]> Property Array
0x14 0x04 AsbPtr<PropertyPointer[]> Property Array

Property<T>

Offset Size Type Description
0x0 0x4 AinbString Name
0x4 0x4 Property Flags Flags
0x8 0x4, or 0xc T Immediate Value
Property Flags
Offset Size Type Description
0x0 0x4 u32 : 16 Index
u32 : 1 Is Use Index
u32 : 1 Is Not Local Blackboard Index
u32 : 1
u32 : 1
u32 : 1
u32 : 1
u32 : 1 Is EXB Index
u32 : 1 Pulse Thread Local Storage
u32 : 1 Set Pointer Flag Bit Zero
u32 : 7

PropertyPointer

Offset Size Type Description
0x0 0x4 AinbString Name
0x4 0x4 AinbString Class Name
0x8 0x4 Property Flags Flags

Property Entries

Offset Size Type Description
0x0 0x8 Property Type Entry S32 Entries
0x8 0x8 Property Type Entry Bool Entries
0x10 0x8 Property Type Entry Float Entries
0x18 0x8 Property Type Entry String Entries
0x20 0x8 Property Type Entry Vector3f Entries
0x28 0x8 Property Type Entry Pointer Entries
Property Type Entry
Offset Size Type Description
0x0 0x4 u32 Base Index - base index into the Property Table's Property Array for the specified type
0x4 0x4 u32 Count

Input Output Table

Offset Size Type Description
0x00 0x04 AsbPtr<Input<s32>[]> Input Array
0x04 0x04 AsbPtr<Output<s32>[]> Output Array
0x08 0x04 AsbPtr<Input<bool>[]> Input Array
0x0c 0x04 AsbPtr<Output<bool[]> Output Array
0x10 0x04 AsbPtr<Input<float>[]> Input Array
0x14 0x04 AsbPtr<Output<float>[]> Output Array
0x18 0x04 AsbPtr<Input<AinbString>[]> Input Array
0x1c 0x04 AsbPtr<Output<AinbString>[]> Output Array
0x20 0x04 AsbPtr<Input<Vector3f>[]> Input Array
0x24 0x04 AsbPtr<Output<Vector3f>[]> Output Array
0x28 0x04 AsbPtr<InputPointer[]> Input Array
0x2c 0x04 AsbPtr<OutputPointer[]> Output Array

Input<T>

Offset Size Type Description
0x0 0x4 AinbString Name
0x4 0x2 s16 Input Element Id or Base Multi-Input Id
0x6 0x2 s16 Input Element Output Plug Id or Multi-Input Count
0x8 0x4 Property Flags Flags
0xc 0x4, or 0xc T Immediate Value

If the input element id is between -32768 and -100, then the input uses a multi-input. The multi-input id can be calculated as follows: BaseMultiInputIndex = -100 - Index.

InputPointer

Offset Size Type Description
0x0 0x4 AinbString Name
0x4 0x4 AinbString Class Name
0x8 0x2 s16 Input Element Id or Base Multi-Input Id
0xa 0x2 s16 Input Element Output Plug Id or Multi-Input Count
0xc 0x4 Property Flags Flags
0x10 0x4 u32

Output<T>

Offset Size Type Description
0x0 0x4 AinbString : 31 Name
u32 : 1

OutputPointer

Offset Size Type Description
0x0 0x4 AinbString : 31 Name
u32 : 1
0x4 0x4 AinbString Class Name

Input Output Entries

Offset Size Type Description
0x0 0x10 Input Output Type Entry S32 Entries
0x10 0x10 Input Output Type Entry Bool Entries
0x20 0x10 Input Output Type Entry Float Entries
0x30 0x10 Input Output Type Entry String Entries
0x40 0x10 Input Output Type Entry Vector3f Entries
0x50 0x10 Input Output Type Entry Pointer Entries
Input Output Type Entry
Offset Size Type Description
0x0 0x4 u32 Input Base Index - base index into the Input Output Table's Input<T> array for the specified type
0x4 0x4 u32 Input Count
0x8 0x4 u32 Output Base Index - base index into the Input Output Table's Output<T> array for the specified type
0x10 0x4 u32 Output Count

Element Array

The node array immediately follows the command array and is an array of all nodes in the file.

Node Entry
Offset Size Type Description
0x00 0x02 u16 Element Type
0x02 0x02 u16 Element Id - Index of this element within the element array
0x04 0x02 u16 Attachment Count
0x06 0x01 bitfield Element Flags
0x07 0x01 u8
0x08 0x04 AinbString Element Type Name (for ApplicationDefined nodes)
0x0C 0x04 u32 Name Hash (version 0x407+)
0x10 0x04 u32
0x14 0x04 AinbPtr<ElementParam<Element Type>> Element Param
0x18 0x02 u16 EXB Function Count
0x1A 0x02 u16 EXB Input/Output Field Size
0x1C 0x02 u16 Multi-Param Count
0x1E 0x02 u16
0x20 0x04 u32 Base Attachment Id
0x24 0x02 u16 Base Query Element Id
0x26 0x02 u16 Query Element Count
0x28 0x02 u16 0x58 Section Entry Offset (relative to the start of the file)
0x2A 0x02 u16
0x2C 0x10 Guid Guid

Just like with commands, node GUIDs are only used for debug messages. The 0x58 section entry offset will be empty if unused.

Element Type

Element Types
Value (Hex) Value (Dec) Node Type
0x00 0 Application Defined
0x01 1 Element_S32Selector
0x02 2 Element_Sequential
0x03 3 Element_Simultaneous
0x04 4 Element_F32Selector
0x05 5 Element_StringSelector
0x06 6 Element_RandomSelector
0x07 7 Element_BoolSelector
0x08 8 Element_Fork
0x09 9 Element_Join
0x0A 10 Element_Alert
0x14 20 Element_Expression
0x64 100 Element_ModuleIF_Input_S32
0x65 101 Element_ModuleIF_Input_F32
0x66 102 Element_ModuleIF_Input_Vec3f
0x67 103 Element_ModuleIF_Input_String
0x68 104 Element_ModuleIF_Input_Bool
0x69 105 Element_ModuleIF_Input_Ptr
0xC8 200 Element_ModuleIF_Output_S32
0xC9 201 Element_ModuleIF_Output_F32
0xCA 202 Element_ModuleIF_Output_Vec3f
0xCB 203 Element_ModuleIF_Output_String
0xCC 204 Element_ModuleIF_Output_Bool
0xCD 205 Element_ModuleIF_Output_Ptr
0x012C 300 Element_ModuleIF_Child
0x0190 400 Element_StateEnd
0x01F4 500 Element_SplitTiming

Element type names are official (outside ApplicationDefined). For ApplicationDefined elements, definitions can be found in a node definition file for the respective file category. This file is located at NodeDefinition/Node.Product.[ver].aidefn.byml.zs in the corresponding file category folder.

Node Type Descriptions
Type Description
UserDefined Custom node type, definition in NodeDefinition
Element_S32Selector Conditionally links to a node depending on the value of a signed int
Element_Sequential Links to nodes sequentially in the order listed
Element_Simultaneous Links simultaneously to multiple nodes
Element_F32Selector Conditionally links to a node depending on the value of 32-bit float
Element_StringSelector Conditionally links to a node depending on the value of a string
Element_RandomSelector Links to a node randomly
Element_BoolSelector Conditionally links to a node depending on the value of a bool
Element_Fork See Active Node Update Array
Element_Join See Active Node Update Array
Element_Alert Displays a debug message
Element_Expression Passes values to and from EXB commands
Element_ModuleIF_Input_S32 Receives a signed int input from the calling AINB file
Element_ModuleIF_Input_F32 Receives a 32-bit float input from the calling AINB file
Element_ModuleIF_Input_Vec3f Receives a vector3f input from the calling AINB file
Element_ModuleIF_Input_String Receives a string input from the calling AINB file
Element_ModuleIF_Input_Bool Receives a bool input from the calling AINB file
Element_ModuleIF_Input_Ptr Receives an object pointer input from the calling AINB file
Element_ModuleIF_Output_S32 Returns a signed int output from the module to the calling AINB file
Element_ModuleIF_Output_F32 Returns a 32-bit float output from the module to the calling AINB file
Element_ModuleIF_Output_Vec3f Returns a vector3f output from the module to the calling AINB file
Element_ModuleIF_Output_String Returns a string output from the module to the calling AINB file
Element_ModuleIF_Output_Bool Returns a bool output from the module to the calling AINB file
Element_ModuleIF_Output_Ptr Returns an object pointer output from the module to the calling AINB file
Element_ModuleIF_Child Returns the node connection name from the module to the calling AINB file
Element_StateEnd Termination node, specifies what resident node to return to in the calling AINB file
Element_SplitTiming Changes when child nodes are run (Enter - first time visiting a node, Update - every frame, Leave - ran upon leaving the node)

Element Flags

Element Flags
Bits Description
1 Is Query Element
1 Is Module Caller
1 Is Resident Initialized
1 Is Query Multi-Param
4

ElementParam<T>

Each element contains a table into the 4 parameter types, properties, inputs, outputs, and plugs. The child plugs inform the structure of the element tree.

Offset Size Type Description
0x0 0x30 Property Entries Entries into the Property Table.
0x30 0x60 Input Output Entries Entries into the Input Output Table.
0x90 0x14 Plug Entries Entries into the following plug pointer array.
0xa4 AsbPtr<>[Total Plug Count] Plug Data Plug Data Pointer Array.
Plug Entries
Offset Size Type Description
0x0 0x2 Plug Type Entry Bool/float Input Source/Output Source
0x2 0x2 Plug Type Entry
0x4 0x2 Plug Type Entry Child Plugs
0x6 0x2 Plug Type Entry Jump Plugs
0x8 0x2 Plug Type Entry String Input Source
0xa 0x2 Plug Type Entry Int Input Source
0xc 0x2 Plug Type Entry
0xe 0x2 Plug Type Entry
0x10 0x2 Plug Type Entry
0x12 0x2 Plug Type Entry
Plug Type Entry
Offset Size Type Description
0x0 0x1 u8 Count
0x1 0x1 u8 Base Index - base index into Plug Pointer Array
Plugs
Typical Plug Data
Offset Size Type Description
0x00 0x04 u32 Element Id
0x04 0x04 u32 Value

The interpretation of the value depends on the connection type. For input or output connections, the value is a string of the parameter name. For standard connections, the value is a string of the connection name. For jump connections, the value is an id into the Jump Table. Elements are free to extend the plug data with their own element specific values. For built-in element selector-types, excluding Element_BoolSelector and Element_F32Selector, an extra four bytes stores data used to select the child plug. For Element_S32Selector, this is an immediate value. For Element_RandomSelector, this is a weight and for Element_StringSelector it is a string. The condition for Element_BoolSelector is the entry's value string. Element_F32Selector adds 24 bytes to each entry, consisting of four eight-byte sub-entries.

Element_F32Selector Condition Entry
Offset Size Type Description
0x00 0x04 u32 Local Blackboard Parameter Index and Flags
0x04 0x04 float Condition Value

The first two bytes of the four bytes at offset 0x00 are the blackboard parameter index while the last bit is whether or not the index is used or not. The first entry for Element_F32Selector is the minimum value condition while the second entry is the maximum value condition. The last two entries appear to be unused. The last child element entry for Selector-type nodes is the default case. The condition for this case is either the string その他 ("Other") or 0 (in the case of Element_S32Selector). Input elements that are Selector-type elements also appear to have an additional eight bytes (purpose unknown). Element_Expression has an additional eight bytes per input element (16 bytes in the case of vector3f entries). The purpose of these bytes is unknown.

Blackboard

This section contains an array of the Blackboard parameters used by file. These parameters may be sourced from external Blackboards or parameter files. The section begins with a 0x30 byte section header followed by the array of parameters, an array of default values of said parameters, and an array of file references if applicable. The order of parameters is in the order of string, int, float, bool, vector3f, and pointer. The section header contains six entries, one for each type.

Section Header Entry
Offset Size Type Description
0x00 0x02 u16 Number of Entries of the Corresponding Data Type
0x02 0x02 u16 Parameter Index of the First Entry of the Corresponding Data Type
0x04 0x02 u16 Relative Offset of the First Entry of the Corresponding Data Type
0x06 0x02 u16
Local Blackboard Parameter Entry
Offset Size Type Description
0x00 0x04 bitfield Name Offset and Flags
0x04 0x04 u32 String Offset (Notes)
Name Offset Flags
Bits Description
22 Name Offset
1
1 Does Not Have File Reference
7 File Reference Index
1 Is File Reference Valid

The default value entries vary based on the parameter's data type. For int, float, and bool parameters, the entry is a four byte immediate value. String entries are a four byte string value offset. Vector3f entries are 12 bytes. Note that pointer parameters do not have default value entries and do not have default values.

File Reference Entry
Offset Size Type Description
0x00 0x04 u32 File Path Offset
0x04 0x04 u32 File Path Hash
0x08 0x04 u32 Filename Hash (no extension)
0x0C 0x04 u32 File Extension Hash (no .)

Attachments

Offset Size Type Description
0x00 0x04 AinbString Name
0x04 0x04 AinbPtr<Attachment Param> Parameters Entry Offset
0x08 0x02 u16 EXB Function Count
0x0A 0x02 u16 EXB Input/Output Field Size
0x0C 0x04 u32 Name Hash (version 0x407+)

Attachment Param

Parameter Entry
Offset Size Type Description
0x00 0x1 u8 Unknown (possibly related to debug)
0x01 0x3 u24
0x4 0x30 Property Entries Property Entries
Multi-Input Entry
Offset Size Type Description
0x00 0x02 u16 Node Index
0x02 0x02 u16 Input/Output Source Parameter Index
0x04 0x04 u32 Flags

Jump

Bits Description
8 Is Valid Update
23
1 Update Post Calc

If the first byte of the flags is set to false, then the entry contains another four bytes with a string offset (purpose unknown). Otherwise, the entry is considered valid if the first byte equals 1. When evaluating the behavior trees, the game maintains an array of each root element. When a command is set, the root element of the command is set to this context. A jump will change that root element to the element specified by the jump plug's element id. This usually happens right before the next command's calculation occurs, but if the top bit is set, then it will occur immediately after the current command's calculation finishes (if the source element is an Element_Join, it will always update the root elements post current command calculation). This is primarily used for "subroutines" that run a single time then return to the main execution routine. Element_Fork and Element_Join are the main mechanism to manage multiple root elements. An Element_Fork will replace the current root elements with the element id's of it's jump plugs, possibly "forking" execution into multiple roots. The element at the end of a root element specified by an Element_Fork will optionally have a jump plug referencing a specific Element_Join. Each of these elements will push the Element_Join into the root element array. However, Element_Join has a property parameter called InFlowNum, and until that element has been pushed onto the root element array that many times in a single calculation, it will not activate and remain dormant. However, once this threshold is reached, it will begin execution (with a guard to make sure only one of the instances added to the array will execute).

0x50 Section

This section is unused in Tears of the Kingdom.

Query Element Id Array

This section is an array of entries of query element ids present in the file.

Query Node Entry
Offset Size Type Description
0x00 0x02 u16 Query Element Id (local to number of query nodes)
0x02 0x02 u16

Expression Binary

The EXB (Expression Binary) section is a completely self-contained section that stores custom instructions for a simple command processor. These instructions are grouped into functions that can be called by nodes to perform calculations. Because the section is self-contained, all offsets in this section are local to the section. The EXB section is shared with ASB files (Animation Sequence Binary).

Section Structure

EXB is essentially its own format and allows for the storage of custom functions in files.

Section Order
  1. 0x2C-Byte Header
  2. Command Info Table
  3. Instructions Table
  4. Parameter Region
  5. Signature Table
  6. String Pool
Sub-Sections
Header
EXB Header
Offset Size Type Description
0x00 0x04 char[4] Magic - “EXB “
0x04 0x04 u32 Version (0x02)
0x08 0x04 u32 Static Memory Allocation Size
0x0C 0x04 u32 Parameter EXB Field Entry Count
0x10 0x04 u32 32-bit Scratch Allocation Size
0x14 0x04 u32 64-bit Scratch Allocation Size
0x18 0x04 u32 Command Info Offset
0x1C 0x04 u32 Command Table Offset
0x20 0x04 u32 Signature Table Offset
0x24 0x04 u32 Parameter Region Offset
0x28 0x04 u32 String Pool Offset
Command Info Table

This section contains an array of command (function) info entries. The first four bytes specify the entry count.

Command Info Entry
Offset Size Type Description
0x00 0x04 s32 Base Index Pre-Command Entry
0x04 0x04 u32 Pre-Entry Static Memory Usage
0x08 0x04 u32 Instruction Base Index
0x0C 0x04 u32 Instruction Count
0x10 0x04 u32 Static Memory Size
0x14 0x02 u16 32-bit Scratch Memory Size
0x16 0x02 u16 64-bit Scratch Memory Size
0x18 0x02 u16 Output Data Type Enum
0x1A 0x02 u16 Input Data Type Enum
Data Type Enum
Value (Hex) Value (Dec) Data Type
0x0 0 No Data
0x1 1 Immediate Value/From User
0x02 2 bool
0x03 3 int
0x04 4 float
0x05 5 string
0x06 6 vector3f
Instructions Table

This section contains an array of instruction entries which are read by the EXB command processor. The first four bytes specify the entry count.

Instruction Entry
Offset Size Type Description
0x00 0x01 u8 Instruction Type
0x01 0x01 u8 Data Type Enum
0x02 0x01 u8 Left-Hand Side Parameter Source Enum
0x03 0x01 u8 Right-Hand Side Parameter Source Enum
0x04 0x02 u16 Left-Hand Side Parameter Value
0x06 0x02 u16 Right-Hand Side Parameter Value

For UserDefined type instructions, the bytes at offset 0x02-0x04 become a u16 static memory index and the bytes at 0x04-0x08 become a u32 index into the function signatures table.

Instruction Types
Value (Hex) Value (Dec) Instruction Type
0x01 1 Terminator
0x02 2 Store
0x03 3 Negate
0x04 4 NegateBool
0x05 5 Add
0x06 6 Subtract
0x07 7 Multiply
0x08 8 Divide
0x09 9 Modulus
0x0A 10 Increment
0x0B 11 Decrement
0x0C 12 ScalarMultiplyVec3f
0x0D 13 ScalarDivideVec3f
0x0E 14 LeftShift
0x0F 15 RightShift
0x10 16 LessThan
0x11 17 LessThanEqual
0x12 18 GreaterThan
0x13 19 GreaterThanEqual
0x14 20 Equal
0x15 21 NotEqual
0x16 22 AND
0x17 23 XOR
0x18 24 OR
0x19 25 LogicalAND
0x1A 26 LogicalOR
0x1B 27 UserFunction
0x1C 28 JumpIfLHSZero
0x1D 29 Jump

UserFunctions are mapped to a function in the executable by function signature. There are two types of these functions: direct and object. Direct functions are straightforward functions that take up to two arguments and are matched using the function signature. Function objects can take additional arguments and are indexed at runtime.

Data Type Enum
Value (Hex) Value (Dec) Data Type
0x0 0 No Data
0x1 1 Immediate Value/From User
0x02 2 bool
0x03 3 int
0x04 4 float
0x05 5 string
0x06 6 vector3f
Parameter Source Enum
Value (Hex) Value (Dec) Parameter Source
0x00 0 Immediate Parameters
0x01 1 Immediate Parameters (String)
0x02 2 Static Memory
0x03 3 Parameters Region
0x04 4 Parameters Region (String)
0x05 5 Output Value
0x06 6 Input Value
0x07 7 32-bit Scratch
0x08 8 64-bit Scratch
0x09 9 UserOutput
0x0A 10 UserInput

UserCallback is a class that contains virtual functions providing memory allocation. The input value is passed from the calling node and the output value is passed back.

Parameter Region

The parameter region is a region that stores the values for parameters values that are too large to fit into two bytes. Parameters that get their values from this section instead store an offset relative to the beginning of the parameter region to the start of the value.

Signatures Table

This section is an array of u32 string offsets for each function signature.

String Pool

The string pool is an array of null-terminated strings encoded with UTF-8. All string offsets in this section are relative to the beginning of the string pool.

Module Caller

This section contains an array of all AINB modules linked to the current AINB file. The first four bytes specify the entry count.

AINB Module Entry
Offset Size Type Description
0x00 0x04 u32 File Path Offset
0x04 0x04 u32 File Category Offset
0x08 0x04 u32 AINB File Count

External Action Array

This section appears to interact with XLink. The first four bytes specify the entry count.

Entry String Entry
Offset Size Type Description
0x00 0x04 u32 Node Index
0x04 0x04 u32 String 1 Offset (always メインステート ("Main State"))
0x08 0x04 u32 State Name Offset

Module Caller Link

This section contains two 32-bit file hashes. The first hash is a hash for the file itself and the second hash appears to be a hash for that file's parent file. These are used by Element_ModuleCaller.

Child Replacement Table

This section is used to remove or replace specific elements or attachments at runtime. This is used to toggle off debug elements/attachments in release builds. The section begins with an eight-byte section header.

Child Replacement Section Header
Offset Size Type Description
0x00 0x01 u8 Initialization Guard (Is Initialized)
0x01 0x01 u8
0x02 0x02 u16 Replacement Count
0x04 0x02 s16 Override Element Count
0x06 0x02 s16 Override Attachment Parameter Count
Child Replacement Table Entry
Offset Size Type Description
0x00 0x01 u8 Replacement Type Enum (0 = remove child element, 1 = replace child element, 2 = remove attachment)
0x01 0x01 u8
0x02 0x02 u16 Element Id
0x04 0x02 u16 Child Element Id/Attachment Id
0x06 0x02 u16 New Element Id (for child element replacements)

0x6C Section

This section is unused in Tears of the Kingdom.

Enum Relocation

This section is used to resolve enum values at runtime. This section is unused in Tears of the Kingdom as all enum values are statically present in the file. However, in Splatoon 3, this section is used extensively as all enum values are stored in the main executable. The first four bytes of this section specifies the number of entries in the section.

Enum Resolve Array Entry
Offset Size Type Description
0x00 0x04 u32 Enum Value Offset
0x04 0x04 u32 Enum Class Name Offset
0x08 0x04 u32 Enum Value Name Offset

String Pool

The string pool is an array of null-terminated strings encoded with UTF-8. All string offsets in the file are relative to the first byte of this section. Note that this section also contains some unreferenced strings which are the enums for certain parameters.