The geo layout system is SM64’s mechanism for describing the 3-D scene graph used during rendering. Every level area, actor, and UI element is represented as a tree of GraphNode structures. That tree is built at load time by interpreting a static array 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.
uintptr_t values — the geo layout — through a jump table of command handlers in src/engine/geo_layout.c.
The command interpreter
process_geo_layout() in geo_layout.c is the entry point. It takes a pool allocator and a segmented pointer to a geo layout array, then walks the array one command at a time, dispatching each opcode through GeoLayoutJumpTable:
gGeoLayoutCommand pointer advances through the array, and a 32-entry stack (gGeoLayoutStack) supports branching and subroutine calls between multiple geo layout arrays.
Key global state
| Variable | Type | Purpose |
|---|---|---|
gCurRootGraphNode | struct GraphNode * | Root of the currently processed scene graph |
gGraphNodePool | struct AllocOnlyPool * | Memory pool used for all graph node allocations |
gGeoViews | struct GraphNode ** | Array of registered camera view nodes |
gGeoLayoutStack | uintptr_t[] | Call/return stack for GEO_BRANCH_AND_LINK / GEO_RETURN |
gCurGraphNodeList | struct GraphNode *[] | Stack of currently open nodes (parent chain) |
The GraphNode hierarchy
Every object in the scene tree is astruct GraphNode or a struct that embeds one. The base node carries the doubly-linked sibling list and the parent/child pointers that form the tree:
flags. It controls which of the 8 GraphNodeMasterList buckets a display list lands in, and therefore its render mode and draw order.Node type constants
GRAPH_NODE_TYPE_FUNCTIONAL set embed a GraphNodeFunc callback that is invoked during rendering, area load/unload, and held-object processing.
Functional nodes
callContext argument tells the function in which phase it was called:
Specialized node structs
GraphNodeRoot — viewport definition
GraphNodeRoot — viewport definition
GraphNodePerspective — 3-D projection frustum
GraphNodePerspective — 3-D projection frustum
GraphNodeCamera — camera position and aim
GraphNodeCamera — camera position and aim
GraphNodeMasterList — 8 rendering buckets
GraphNodeMasterList — 8 rendering buckets
GraphNodeSwitchCase — conditional child selection
GraphNodeSwitchCase — conditional child selection
GraphNodeLevelOfDetail — distance culling
GraphNodeLevelOfDetail — distance culling
minDistance and maxDistance.GraphNodeAnimatedPart — skeletal animation
GraphNodeAnimatedPart — skeletal animation
GraphNodeShadow
GraphNodeShadow
GraphNodeCullingRadius — frustum cull override
GraphNodeCullingRadius — frustum cull override
Rendering layers
The drawing layer is encoded in the high byte of a node’sflags field and is passed as layer in many geo macros. Layers map to the 8 master-list buckets, each with a distinct RDP render mode:
| Layer constant | Value | Usage |
|---|---|---|
LAYER_FORCE | 0 | Always rendered, no z-buffer |
LAYER_OPAQUE | 1 | Fully opaque surfaces |
LAYER_OPAQUE_DECAL | 2 | Opaque with polygon offset |
LAYER_OPAQUE_INTER | 3 | Opaque inter-objects |
LAYER_ALPHA | 4 | Alpha-tested (cutout) textures |
LAYER_TRANSPARENT | 5 | Blended transparency |
LAYER_TRANSPARENT_DECAL | 6 | Transparent with polygon offset |
LAYER_TRANSPARENT_INTER | 7 | Transparent inter-objects |
Geo command macros
The macros ininclude/geo_commands.h expand to packed uintptr_t words. Every command starts with an opcode byte, a parameter byte, and a 16-bit field, optionally followed by more words or pointer-sized values.
Flow control
Flow control
Scene structure nodes
Scene structure nodes
Transform and display list nodes
Transform and display list nodes
Real example: Bob-omb Battlefield area 1
The complete area geo layout fromlevels/bob/areas/1/geo.inc.c:
- A screen-area root node allocates 12 view slots.
- The skybox renders first with z-buffer off and an orthographic projection.
- The z-buffer is then turned on for the 3-D world.
- A perspective frustum (45° FOV, near=100, far=30000) sets up the 3-D projection;
geo_camera_fovadjusts FOV dynamically. - The camera node positions the view;
geo_camera_mainhands it off to the camera system. - Static level display lists are drawn per layer, then
GEO_RENDER_OBJ()inserts all active objects, andgeo_envfx_maindraws environment effects (snow, bubbles, etc.). - The cannon HUD circle is drawn at the end with z-buffer off again.
Real example: Chain Chomp Gate actor
Fromlevels/bob/chain_chomp_gate/geo.inc.c:
Real example: Mario face and wings
Fromactors/mario/geo.inc.c — showing GEO_SWITCH_CASE and GEO_ANIMATED_PART in use:
GEO_RETURN() at the end means this layout was called via GEO_BRANCH_AND_LINK from a parent layout and execution returns to it after this block.
How actors reference geo layouts
Actors (enemies, items, interactive objects) store a pointer to their geo layout in their model data. WhenLOAD_MODEL_FROM_GEO is called in a level script, process_geo_layout() interprets that layout to build a shared GraphNode tree. Each live object instance temporarily re-parents that shared tree to its own GraphNodeObject for rendering, then unparents it — this is the gGeoViews / sharedChild mechanism described in the comments at the top of geo_layout.c.