Every interactive entity in Super Mario 64—coins, enemies, platforms, stars, and Mario himself—is an instance ofDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/n64decomp/sm64/llms.txt
Use this file to discover all available pages before exploring further.
struct Object. The object system wires together graphics (via GraphNode), collision, behavior scripting, and game logic into one unified, 0x260-byte structure that is allocated from a fixed pool of 240 slots. Understanding this struct and the systems around it is the foundation for reading or modifying any object behavior in the game.
Struct hierarchy
Objects sit at the end of a four-level inheritance chain built entirely through composition (first-member embedding, not C++ inheritance).GraphNode
The root node used by the scene graph renderer.GraphNodeObject
Adds the spatial data that the renderer uses to place and orient a visible object.ObjectNode
EmbedsGraphNodeObject and adds the two linked-list pointers that chain objects together within their object list.
Object
The full game object.header is an ObjectNode, so &obj->header can be cast to struct ObjectNode * or struct GraphNodeObject * wherever the graphics subsystem expects it.
The rawData union
Bytes0x088–0x1C8 (80 slots of 4 bytes each, index 0x00–0x4F) form an untyped data region that every behavior script uses to store its own per-object variables. The union gives type-safe read/write access to the same memory:
object_fields.h provides named macros that expand to the correct union member and index:
0x1B–0x22 and 0x49–0x4A are reserved for object-specific fields that each behavior defines for itself (e.g. oGoombaWalkTimer, oBooBaseScale).
The macro
OBJECT_FIELDS_INDEX_DIRECTLY is defined in behavior_data.c to replace all OBJECT_FIELD_* macros with bare array indices. This is only valid in that translation unit, which compiles the raw bytecode tables.Object flags
Two separate flag fields control high-level object state.activeFlags (s16)
oFlags (u32, rawData slot 0x01)
OR_INT(oFlags, ...) at the top of their BEGIN(...) block.
Object lists
All 240 object slots live ingObjectPool[]. Active objects are organized into 13 doubly-linked lists that determine processing order and collision eligibility:
BEGIN(objList) command in its behavior script. Objects only perform collision checks against other objects in compatible lists.
The pool maximum is 240 objects (
OBJECT_POOL_CAPACITY). OBJ_LIST_UNIMPORTANT objects are silently removed to make room when the pool is exhausted.Spawn functions
New objects are created through a family of helpers declared insrc/game/object_helpers.h (and src/game/spawn_object.h for lower-level operations).
Lowest-level allocator. Pulls a slot from
gFreeObjectList, links it into the appropriate object list (determined by the behavior script’s BEGIN command), and returns the pointer. Declared in spawn_object.h.Creates an object, assigns the given model and behavior, and copies the parent’s position and angle. The most common call site in behavior code.
Like
spawn_object but does not copy position/angle. Used when the behavior script will set the position itself.Spawns at a position offset relative to the parent. Sets
oBhvParams2ndByte from bhvParam.Spawns only if object pool slots are available; returns
NULL otherwise.Sets
activeFlags = ACTIVE_FLAG_DEACTIVATED. The object is recycled into gFreeObjectList at the end of the current frame.ObjectHitbox struct
Rather than setting hitbox fields manually, many objects useobj_set_hitbox() with a statically initialized struct ObjectHitbox:
src/game/behaviors/coin.inc.c:
obj_set_hitbox(o, &sYellowCoinHitbox) copies these values into the object’s hitboxRadius, hitboxHeight, hurtboxRadius, hurtboxHeight, hitboxDownOffset, oInteractType, oDamageOrCoinValue, oHealth, and oNumLootCoins fields.
Object lifecycle
Allocation
create_object() pulls an entry from gFreeObjectList and zeros its fields. The object is inserted into the linked list for its object type (set by BEGIN in the behavior script).Initialization (first frame)
On the first tick, the behavior script runs its header commands (
BEGIN, OR_INT, SET_MODEL, etc.) and calls any CALL_NATIVE init function (e.g. bhv_yellow_coin_init). Initialization typically sets up the hitbox, physics parameters, and initial field values.Update loop
Every frame,
update_objects() iterates through all 13 object lists. For each active object it calls cur_obj_update(), which advances curBhvCommand through the behavior script. Infinite loops (BEGIN_LOOP / END_LOOP) keep the script running one iteration per frame. CALL_NATIVE dispatches C functions that contain the actual game logic.Collision and interaction
After behavior updates, the collision system populates each object’s
collidedObjs[] and collidedObjInteractTypes. Mario’s interaction processor reads these each frame and calls the appropriate handler.Time-stop integration
The object list processor respects thegTimeStopState flags, which selectively freeze certain lists each frame. For example, TIME_STOP_ALL_OBJECTS prevents non-Mario objects from updating, while TIME_STOP_MARIO_AND_DOORS restricts only Mario and door objects. Objects that set ACTIVE_FLAG_INITIATED_TIME_STOP are the source of the freeze (typically dialog NPCs).