Reference ยท Formats

LEVELnn.BIN, a database's rooms

CoversUS /DATA/DB00/LEVEL00.BINUS SLUS_006.50:0x8002a208US SLUS_006.50:0x800b6e98

A database's rooms, loaded by load_rooms(db) (0x8002a208). A table at 0x800b6e98, 12 bytes a database, names its three files: LEVEL (434 + db), COL (466 + db) and A.RAW (499 + db).

Layout

Little-endian. Counts are u32.

u32 n; u8 [n][56]            never used: n is 0 in every file
u32 n; quad[n]               48 bytes each
  corner[4]                  s16 x, s16 y, s16 z, u16 flags
  u8 [16]                    unknown
u32 n; u8 [n][24]            only LEVEL04 has any (63)
u32 rooms; room[rooms]       112 bytes each (kept at 0x800c4a8c, count 0x800c4a9c)
per room: u8 count; u8 [count]   each kept one less than stored
4 - (list bytes % 4) bytes   a whole word when the lists end on one
u32 size[rooms]              bytes of each room's geometry section
per room: u32 n; u32 len[n]; n blobs of len bytes
u32 m; texture[m]            the room texture table (0x800c4a74 = m, 0x800c4a98)
  u8 u0, v0; u16 clut; u8 u1, v1; u16 tpage; u8 u2, v2, u3, v3

A room record (112 bytes)

+0x00  s32 centre[3], pad     blob coordinates are relative to it
+0x10  s32 min[3], pad        the room's bounds in the world
+0x20  s32 max[3], pad
+0x30  u32 quads              its portals; pointer at +0x34 after loading
+0x38  u32 boxes              its 24-byte records; pointer at +0x3c
+0x40  list                   its geometry blobs, linked by the loader
+0x48, +0x4c  lists           objects drawn with the room (each item's
                              function at +0x40 is called)
+0x58  u32 256                in every DB22 room
+0x5e  u8 count, +0x60 list   the byte list

A geometry blob

Read by the hand-written renderer (0x80010e14):

u32  link
s16  min[3], u16 unknown_0a, s16 max[3], u16 unknown_12
u32  vertices
u32  faces_at                 from the blob's start
vertex[vertices]              s16 x, y, z, pad; u8 r, g, b, flash
at faces_at, sections:        u16 kind, u16 count, records
  0x61  quad      u8 v[4], u16 texture, u16 flags
  0x60  triangle  u8 v[3], u8 0xcd, u16 texture, u16 flags
  0xff  the end (count 1)

texture indexes the file's texture table. flags is 0 on disc; at run time the renderer ORs in the outcodes its vertices share (bits 0-4 off left, right, top, bottom, near; 0x20 all nearer than 8192, 0x40 all nearer than 4096), and 0x200 makes a face double-sided. The vertex colour's top byte is a brightening added to r, g and b once and cleared.

The renderer projects the vertices three at a time (RTPT), depth-cues the colour of any vertex beyond depth 8192 with DPCS at (z - 8192) >> 2 (toward the far colour, black: 0x8009fd38(0, 0, 0)), though in play this never happens: hooks on the DPCS branches (0x80011194, 0x800111ac) never fired in the hub, level 2 or level 12 while the room renderer (0x80010e14) ran thousands of times, so the port draws rooms without it, rejects a face whose vertices share an outcode, whose farthest depth >> 2 is 16250 or more, or (unless 0x200) whose NCLIP is not positive, and subdivides faces whose vertices are all nearer than 8192 (0x80012294) or 4096 (0x800123b8). The packets are POLY_GT3 and POLY_GT4, the texture entry's three words copied into the uv slots, linked into the depth buckets at 0x800ce238.

The loader gives each room, in file order, the next room+0x30 quads (pointer at +0x34) and the next room+0x38 24-byte records (pointer at +0x3c; it sets each record's +6 to +0x12 less +0x0a, and room flag 1 when there are any), clears +0x0c and +0x40..+0x57, and links each geometry blob into the list at room+0x40 (0x8001a1c0). The byte list's count is kept at +0x5e, its bytes (less one) at a block pointed to by +0x60.

Measured

Every LEVEL file but LEVEL08 is consumed whole by this walk, and in every one the tail is exactly 12 bytes for each of its m records. Room counts run from 1 (the golf holes 23, 24, 27, 29, 30) to 76 (DB05). Quad corners are multiples of 256 in the files looked at (LEVEL22).

Unknown

  • LEVEL08.BIN does not fit: its first quad reads as 32-bit values (0xfffe5c00, 0xfffffe80, ...) and the third count is not a count. Whether another loader reads it, or the file is stale, is open.
  • The room record's fields from +0x44 to +0x5d and +0x64 on, the portals' tails and corner flags beyond corner 1's (the room a portal leads to), the 24-byte records, the byte lists.
  • The blob header's halfwords at +0x0a and +0x12.