Stadium collision files

A stadium's collision is not in its model block. Each stadium directory holds a small separate collision file next to its models, and the ball, fielders and items test against it. Decoded from main.dol (US) and checked against every vanilla file, each of which parses to its last byte (2026-10-18). All values are big-endian. Nothing in the tools writes these files yet.

Which file a stadium loads

Two tables in main.dol have the same shape, {u16 dir, u16 file[3]} per stadium id, indexed by the time of day (variant 0, 1, 2): 0x806D99E0 names the collision file, 0x806D9980 the model file. Several variants can share one file.

IdDirStadiumModel files (0/1/2)Collision files (0/1/2)
07Mario Stadium0/1/23/3/3
18Bowser Castle0/1/23/3/4
29Wario City0/1/02/2/2
310Yoshi Park0/1/23/3/4
411Peach Ice Garden0/1/23/3/3
512DK Jungle0/1/23/3/3
613Luigi's Mansion0/1/02/2/2
714Daisy Cruiser0/1/23/3/3
815Bowser Jr. Playroom0/1/23/3/4
916Toy Field0/1/02/2/2

The three "file 4" collisions are tiny flat arenas (one region, ±26 to 36 units wide), most likely the minigame fields of variant 2; not verified.

Loading. fn_804B8620 loads the file through fn_80398080 and keeps its handle in the stadium object (*(r13-0x148): +0 id, +4 variant, +6 model handle, +8/+0xC/+0x10 collision handles). The completion callback fn_804B8B60 stores the data pointer at *(r13-0x138) and runs the fix-up fn_8038FB38; fn_804B8BA0 frees it.

File layout

u16 regionCount N, u8 0x43, u8 relocated      (0 in the file; the fix-up sets 1)
u32 offset[N+1]                               file-relative; the fix-up turns them into pointers
offset[0]:      N boxes, 6 x f32 each: xmin ymin zmin xmax ymax zmax
offset[i], i = 1..N:  region i's triangles, as a list of blocks:
    u8 0, u8 kind, u16 count                  kind 1: a strip of count+2 vertices
                                              kind 0: a list of count*3 vertices
    vertex: f32 x, f32 y, f32 z, u16 attr, u16 0
    ... more blocks; a block header with count 0 ends the region

Surface attributes

A triangle's attribute is the attr of its last vertex (strip vertex k+2, list vertex 3k+2); the first two vertices' values are unused. The query returns it (0 means no hit) with the hit point and normal. Its callers (about 47, among them ball flight fn_800B6184, a ground probe fn_800B71A4, fielders and items) read the low 7 bits as the surface type and bit 0x80 separately. Meanings from the data:

Low 7 bitsObserved asWhere
1Flat ground at y = 0 (grass, general field)Every stadium
6Flat ground at y ≤ 0.2 (infield dirt, mound)Mario Stadium, Yoshi Park, Bowser Jr. Playroom variant
2Vertical, 4-8 high at the fence distance (outfield fence)Mario Stadium, Bowser Castle, Yoshi Park, DK Jungle, Daisy Cruiser, Bowser Jr. Playroom
3Walls and stands beyond the fence, up to 24-36 high, mixed facingMost stadiums
4Vertical at the foul-pole corners (foul poles)Mario Stadium, Yoshi Park, Wario City
5Vertical wall pieces 4-8 high; the fence kind used instead of 2Peach Ice Garden, Wario City, Luigi's Mansion and others
0xCLow sloped ground near the fenceDK Jungle only
0xDFlat ground at a radius of about 106 (the deck beyond the fence?)Daisy Cruiser only
bit 0x80Foul territory: set on every triangle whose centroid is outside the foul lines and on none insideEvery stadium

One ball check (fn_8011688C) treats types 2, 3, 5, 7, 8 and 0xD alike (solid: the ball stops or bounces). Other checks look at 0xD, 0xB and the range 0x20-0x36, which no stadium file contains. The per-type physics (bounce, sound) are not traced; the fence distance table, not the collision, decides home runs.

Special cases

Query entry point for reference: fn_804B8424(stadium, p0, p1, outPoint, outNormal, low7Only, scaleZ, ...); the segment matrix comes from fn_8038F6C8, and the result keeps the attribute at +0x44 and the normal at +0x30.