SSBM Decomp
Loading...
Searching...
No Matches
dat_macros.h File Reference

Annotations describing how archive data is laid out, for the parts a C declaration cannot express: how many elements a pointer refers to, and which member of a union is valid. More...

Go to the source code of this file.

Macros

#define DAT_TAG(tag)
#define DAT_COUNT(count)
 The pointer refers to count elements: an expression of sibling fields and constants, which may call the functions the tool ports, e.g.
#define DAT_TERMINATED(value)
 The pointer refers to elements up to and including a terminator: the first element whose first word is value and not a relocated pointer, e.g.
#define DAT_EXTENT   DAT_TAG("extent")
 The array holds as many elements as the data does: they continue until the next symbol, the next address a pointer refers to, or an element that no longer fits the element type.
#define DAT_IF(cond)
 The union member is valid when cond holds: a C expression over the fields of the record containing the union, and macros.
#define DAT_BIND(name, value)
 name, conventionally Type::field for a value that belongs to Type but is not stored in it, is value for everything reached through the member: its own layout and every pointer followed from within it.
#define DAT_SCRIPT(table, ...)
 The pointer refers to a command script: commands of whole words, each with its opcode in the top 6 bits of its first byte, up to one with opcode 0.
#define DAT_BLOB   DAT_TAG("blob")
 On a typedef of u8: the bytes are data of one format the archive doesn't break down further, such as an animation's keyframe stream.
#define DAT_TYPE(type)
 The untyped pointer, or pointer-sized integer, refers to a type when it is relocated.
Roots

Archive symbols the game looks up by name are the roots every other part of an archive is reached from.

Loaders taking (&dst, "name") pairs wrap their calls in DAT_ROOTS, which declares one static witness per pair: its type is the type of &dst, and its dat:root annotation holds the name argument as written, a string literal or an expression.

#define DAT_ROOTS(...)

Detailed Description

Annotations describing how archive data is laid out, for the parts a C declaration cannot express: how many elements a pointer refers to, and which member of a union is valid.

They expand to nothing for every compiler except clang with DAT_ANNOTATIONS defined, where they become btf_decl_tag attributes that clang emits into DWARF as DW_TAG_LLVM_annotation. The arguments are kept as written, so constants are resolved by name through the DWARF macro table.

Union members are tested in declaration order; the first match is valid. If every member has a condition and none holds, the union is unused.

Macro Definition Documentation

◆ DAT_TAG

#define DAT_TAG ( tag)

◆ DAT_COUNT

#define DAT_COUNT ( count)
Value:
DAT_TAG("count(" #count ")")
#define DAT_TAG(tag)
Definition dat_macros.h:21

The pointer refers to count elements: an expression of sibling fields and constants, which may call the functions the tool ports, e.g.

GXGetTexBufferSize.

◆ DAT_TERMINATED

#define DAT_TERMINATED ( value)
Value:
DAT_TAG("terminated(" #value ")")

The pointer refers to elements up to and including a terminator: the first element whose first word is value and not a relocated pointer, e.g.

DAT_TERMINATED(GX_VA_NULL) for a vertex descriptor list.

◆ DAT_EXTENT

#define DAT_EXTENT   DAT_TAG("extent")

The array holds as many elements as the data does: they continue until the next symbol, the next address a pointer refers to, or an element that no longer fits the element type.

Its declared size is ignored.

Todo
This is a heuristic for arrays whose length only the code knows. Replace each use with a DAT_COUNT once counts can be read from the code's own tables (e.g. the largest anim_id in an item kind's ItemStateTable, for ItemStateArray), or from per-kind *_Count enum values where those exist.

◆ DAT_IF

#define DAT_IF ( cond)
Value:
DAT_TAG("if(" #cond ")")

The union member is valid when cond holds: a C expression over the fields of the record containing the union, and macros.

◆ DAT_BIND

#define DAT_BIND ( name,
value )
Value:
DAT_TAG("bind(" #name ", " #value ")")

name, conventionally Type::field for a value that belongs to Type but is not stored in it, is value for everything reached through the member: its own layout and every pointer followed from within it.

value is evaluated in the record containing the member; for an array or a DAT_COUNT pointer, once per element, which it can refer to as _index. Inner bindings shadow outer ones.

◆ DAT_SCRIPT

#define DAT_SCRIPT ( table,
... )
Value:
DAT_TAG("script(" #table ", " #__VA_ARGS__ ")")
static grZe_ColorEntry table[3]
Definition grzebes.c:1119

The pointer refers to a command script: commands of whole words, each with its opcode in the top 6 bits of its first byte, up to one with opcode 0.

Opcode n is as many words long as the n th of the lengths following table, or past those, as table (an array in the code) says at n minus their number. Relocated words within a command point to more script, such as a goto's target.

◆ DAT_BLOB

#define DAT_BLOB   DAT_TAG("blob")

On a typedef of u8: the bytes are data of one format the archive doesn't break down further, such as an animation's keyframe stream.

Raw u8 data is unknown; the size comes from the members that point to it, e.g. DAT_COUNT(length).

◆ DAT_TYPE

#define DAT_TYPE ( type)
Value:
DAT_TAG("type(" #type ")")

The untyped pointer, or pointer-sized integer, refers to a type when it is relocated.

◆ DAT_ROOTS

#define DAT_ROOTS ( ...)