======== Level Commands ========
The level commands define the top-level control of the game. They are used to load levels, textures, collision data, objects, warps, etc. and determine how everything is connected. The first byte of the level command is the command type and the second byte is the length of the command in bytes.
''[CC] [LL] ...''
| C | Command type (full list below) |
| L | Length of command in bytes (including CC and LL) |
----
==== 00: Load Raw Data and Jump ====
Loads raw data to RAM segment and jumps to segment offset. Used for loading level scripts and then jumping to an offset in them
''00 10 00 [XX] [YY YY YY YY] [ZZ ZZ ZZ ZZ] [AA AA AA AA]''
| X | RAM segment number |
| Y | ROM address start |
| Z | ROM address end |
| A | Segment offset of jump target |
----
==== 01: Load Raw Data and Jump ====
Load raw data to RAM segment and jump to segment offset. The only difference between this command and 0x00 is a call to 0x80278498
''01 10 00 [XX] [YY YY YY YY] [ZZ ZZ ZZ ZZ] [AA AA AA AA]''
| X | RAM segment number |
| Y | ROM address start |
| Z | ROM address end |
| A | Segment offset of jump target |
----
==== 02: End Level Data ====
End of level layout data. Typically followed by null padding.
''02 04 00 00''
----
==== 03: Delay Frames ====
Set flag to 0, delay X frames, set flag to 1. Sets s16 flag (8038BE20) to 0 before delay and 1 after. Does not increment level script pointer until after delay.
''03 04 [XX XX]''
| X | number of delay frames |
----
==== 04: Delay Frames 2 ====
Set flag to -1, delay X frames, set flag to 1.
Identical to 0x03, except for flag set at start:
sets s16 flag (8038BE20) to -1 before delay and 1 after.
Does not increment level pointer until after delay.
''04 04 [XX XX]''
| X | number of delay frames |
----
==== 05: Jump to Address ====
Jump to level script at segmented address.
''05 08 00 00 [XX XX XX XX]''
| X | segmented address of jump |
----
==== 06: Push Stack ====
Push script stack and jump to level script at segmented address.
Similar to 05, but also pushes current place on script stack so it can be popped later.
''06 08 00 00 [XX XX XX XX]''
| X | segmented address of jump |
----
==== 07: Pop Stack ====
Pop script stack, returns to where previous 06 or 0C pushed from.
''07 04 00 00''
----
==== 08: Push Stack + 16 ====
Push script stack and 16-bit value on stack.
This command is never used in any of the level scripts.
''08 04 [XX XX]''
| X | 16 bit value pushed on script stack after current address |
----
==== 09: Pop Stack + 16 ====
Pops script stack and param (possibly from previous 08 or 0A).
This command is never used in any of the level scripts.
''09 04 00 00''
----
==== 0A: Push Script + 0x00 ====
Pushes next level command on script stack and param 0x00000000.
This command is only used once in main level scripts.
''0A 04 00 00''
----
==== 0B: Conditional Pop ====
If result of operation is true, pop stack.
This command is only used once in main level scripts.
''0B 08 [XX] 00 [YY YY YY YY]''
| X | operation, a0 to 8037E1A0 (unsigned 8) |
| Y | argument, a1 to 8037E1A0 (signed 32) |
^ Operations ^^
| 0 | script_accum & argument |
| 1 | !(script_accum & argument) |
| 2 | script_accum == argument |
| 3 | script_accum != argument |
| 4 | script_accum < argument |
| 5 | script_accum <= argument |
| 6 | script_accum > argument |
| 7 | script_accum >= argument |
----
==== 0C: Conditional Jump ====
If result of operation is true, jumps to segmented address.
''0C 0C [XX] 00 [YY YY YY YY] [ZZ ZZ ZZ ZZ]''
| X | operation, a0 to 8037E1A0 (unsigned 8). See [[#0B: Conditional Pop]] for valid operations |
| Y | argument, a1 to 8037E1A0 (signed 32) |
| Z | segment address of jump |
----
==== 0D: Conditional Push ====
If result of operation is true, pushes next command on stack and jumps to segmented address
This command is never used in any of the level scripts.
''0D 08 [XX] 00 [YY YY YY YY]''
| X | operation, a0 to 8037E1A0 (unsigned 8). See [[#0B: Conditional Pop]] for valid operations |
| Y | argument, a1 to 8037E1A0 (signed 32) |
----
==== 0E: Conditional Skip ====
If result of operation is false, skips over following 0x0F, 0x10 commands.
This command is never used in any of the level scripts.
''0E 08 [XX] 00 [YY YY YY YY]''
| X | operation, a0 to 8037E1A0 (unsigned 8). See [[#0B: Conditional Pop]] for valid operations |
| Y | argument, a1 to 8037E1A0 (signed 32) |
----
==== 0F: Skip Next ====
Skips over the following 0x10 commands.
This command is never used in any of the level scripts.
''0F 04 00 00''
----
==== 10: No Operation ====
Doesn't do anything, nop.
This command is never used in any of the level scripts.
''10 04 00 00''
----
==== 11: Set Accumulator From ASM ====
Set level accumulator (8038BE24) from assembly routine.
''11 08 [XX XX] [YY YY YY YY]''
| X | A0 value passed to function Y |
| Y | Assembly routine of format ''u32 func(u32 a0, u16 A1)'' |
Call assembly routine Y (A0 = halfword X, A1 = word from 0x8038BE24).
Store return value at 0x8038BE24.
| Game startup | 8016F5B0 |
| File select | 801766DC |
| File select -> Castle grounds | 8024BD5C |
| Other levels | 8024BE14, 8024BCD8 |
----
==== 12: Actively Set Accumulator ====
''12 08 [XX XX] [YY YY YY YY]''
| X | A0 value passed to function Y |
| Y | Assembly routine of format ''u32 func(u32 a0, u16 A1)'' |
Call assembly routine Y (A0 = halfword X, A1 = word from 0x8038BE24).
Store return value at 0x8038BE24.
If return value is 0, set upper halfword @ 0x8039BE20 = 0 and do not continue to next command.
Else, set upper halfword @ 0x8039BE20 = 1 and continue to the next command.
| Demo screen | 8016F5B0 |
| File select | 801768A0 |
| Other levels | 8024BCD8 |
----
==== 13: Set Accumulator ====
Set level accumulator (8038BE24) to constant value.
''13 04 [XX XX]''
| X | Value to set level accumulator |
----
==== 14: Push Pool State ====
Calls PushPoolState/802783E8 and returns.
This command is never used in any of the level scripts.
''14 04 00 00''
----
==== 15: Pop Pool State ====
Calls PopPoolState/80278498 and returns.
This command is never used in any of the level scripts.
''15 04 00 00''
----
==== 16: Load ROM to RAM ====
Load raw data from ROM to absolute RAM address. Call 0x802786F0 (A0 = X, A1 = Y, A2 = Z)
''16 10 00 00 [XX XX XX XX] [YY YY YY YY] [ZZ ZZ ZZ ZZ]''
| X | RAM address |
| Y | ROM address start |
| Z | ROM address end |
----
==== 17: Load ROM to Segment ====
Load raw data from ROM to RAM segment.
''17 0C 00 [XX] [YY YY YY YY] [ZZ ZZ ZZ ZZ]''
| X | RAM segment number |
| Y | ROM address start |
| Z | ROM address end |
----
==== 18: Decompress MIO0 to Segment ====
Load and decompress MIO0 data from ROM to RAM segment.
''18 0C 00 [XX] [YY YY YY YY] [ZZ ZZ ZZ ZZ]''
| X | RAM segment number |
| Y | ROM address start |
| Z | ROM address end |
----
==== 19: Create Mario Demo ====
Create Mario face for the demo screen.
''19 04 00 [XX]''
| X | Settings: 01 No face, 02 Regular face, 03 Game over face |
Call 0x80278120 (A0 = 0x000E1000, A1 = 0); allocate 0xE1000 bytes for mario face settings
If allocation was successful:
Call 0x8019C450(A0 = 0x000E1000, A1 = pointer to allocated area in ram)
Call 0x8019C418(A0 = 0x80000400, A1 = 0x00025800)
Call 0x8019C418(A0 = 0x8039F800, A1 = 0x00070800)
Call 0x8019C4EC ; data gets loaded into 80000400 and 8039F800 after this call
Call 0x8019C684(A0 = X)
----
==== 1A: Decompress MIO0 Textures ====
Load and decompress MIO0 data from ROM to RAM segment (level terrain textures)
''1A 0C 00 [XX] [YY YY YY YY] [ZZ ZZ ZZ ZZ]''
| X | RAM segment number |
| Y | ROM address start |
| Z | ROM address end |
----
==== 1B: Start Load Sequence ====
Start load sequence. Used before a chain of load commands.
''1B 04 00 00''
----
==== 1C: Level & Memory Cleanup ====
''1C 04 00 00''
* Frees data in pool allocated from level script
* Cleanups level related stuff (level objects, pointers, etc)
* Cleanups geometry layout data
* Cleanups all 8 area structs
More detailed notes can be found here: [[https://pastebin.com/raw/GjDsJYqq]]
----
==== 1D: End Load Sequence ====
Used after a chain of load commands.
''1D 04 00 00''
----
==== 1E: Allocate Level Data From Pool ====
Allocates data from the pool and reset a couple variables
''1E 04 00 00''
* Reallocates memory for the geometry layout node system.
* Allocates 0xDAC0 bytes and stores pointer to 0x8038EE98. Not sure what this is, but it is related to collision.
* Allocates memory for collision data. Vanilla SM64 allocates enough space for only 2,300 collision triangles. Newer versions of Skelux's SM64 editor allocate enough space for 32,767 triangles.
* Sets halfword at address 0x8036125C to 0. (0x8036125C seems to be just a flag that is set when Mario enters into area #2 of any level)
* Sets byte at address 0x803613FE to 0. (0x803613FE seems to be a read-only byte that tells you how many red coins Mario has collected so far)
More detailed notes can be found here: [[https://pastebin.com/raw/XkCfkFyT]]
----
==== 1F: Start Area ====
Start of an area.
''1F 08 [XX] 00 [YY YY YY YY]''
| X | Area number |
| Y | Segment offset address of geometry layout |
----
==== 20: End Area ====
End of an area.
''20 04 00 00''
----
==== 21: Load Polygon Without Geo ====
Load polygon data without geometry layout.
''21 08 [X]0 [YY] [ZZ ZZ ZZ ZZ]''
| X | Drawing layer |
| Y | ID of the model to be used with 3D objects |
| Z | Segment offset address |
----
==== 22: Load Polygon With Geo ====
Load polygon data with geometry layout.
''22 08 00 [XX] [YY YY YY YY]''
| X | ID of the model to be used with 3D objects |
| Y | Segment offset address |
----
==== 23: ?? ====
Unknown.
This command is never used in any of the level scripts.
''23 0C [A][B BB] [CC CC CC CC] [DD DD DD DD]''
| A | most significant nibble of third byte |
| B | 3 least significant nibbles of first word |
| C | word |
| D | float? |
(short)sp[0x2a] = (short)8038be28[2] & 0xFFF; // B
(short)sp[0x28] = (short)8038be28[2] >> 12; // A
sp[0x24] = (int)8038be28[4]; // C
sp[0x2C] = (int)8038be28[8]; // D
if (sp[0x2a] < 0x100) {
f4 = sp[0x2C];
v0 = 8037B940(*0x8038b8a0, 0, sp[0x28], sp[0x24], f4);
// t8 = sp[0x2a]; t7 = *0x8032ddc4; t9 = t8 << 2; t0 = t7 + t9;
t0 = *0x8032ddc4 + sp[0x2a] * 4;
*t0 = v0;
}
*0x8038be28 = *0x8038be28 + 8038be28[1]; // advance to next level command
----
==== 24: Place Object ====
Places a 3D object in the level.
''24 18 [AA] [ID] [XX XX] [YY YY] [ZZ ZZ] [RX RX] [RY RY] [RZ RZ] [BB BB BB BB] [BS BS BS BS]''
| AA | Act mask in which this object will appear in |
| ID | ID of the model to use for this object (defined by [[#21: Load Polygon Without Geo]] and [[#22: Load Polygon With Geo]]) |
| XX | X position of object (s16) |
| YY | Y position of object (s16) |
| ZZ | Z position of object (s16) |
| RX | Rotation across X axis in degrees (s16) |
| RY | Rotation across Y axis in degrees (s16) |
| RZ | Rotation across Z axis in degrees (s16) |
| BB | Behavior parameters for the object. The entire word gets stored at Object→0x188, while only the second byte gets stored at Object→0x144.|
| BS | RAM segment address for behavior script |
----
==== 25: Load Mario ====
Loads the Mario object.
''25 0C 00 [XX] [YY YY YY YY] [ZZ ZZ ZZ ZZ]''
Always: ''25 0C 00 [01] [00 00 00 01] [13 00 2E C0]''
| X | ID of the model to use for Mario (defined by [[#21: Load Polygon Without Geo]] and [[#22: Load Polygon With Geo]]) |
| Y | Behavior parameters for Mario's Object. The entire word gets stored at MarioObject->0x188, while only the second byte gets stored at MarioObject->0x144. |
| Z | RAM segment for behavior script |
----
==== 26: Connect Warps ====
Connect warps defined by previous [[#24: Place Object]] commands.
''26 08 [AA] [BB] [CC] [DD] [EE] 00''
| A | Warp ID to jump from (defined by [[#21: Load Polygon Without Geo]] and [[#22: Load Polygon With Geo]]) |
| B | Course ID number to warp to |
| C | Course area to jump to |
| D | Warp ID number in destination level area |
| E | If set to 0x80, then the game will create a checkpoint when the warp is triggered. |
----
==== 27: Painting Warp ====
Define level warps for paintings inside the Castle.
''27 08 [AA] [BB] [CC] [DD] [EE] 00''
| A | Warp ID to jump from (defined by [[#21: Load Polygon Without Geo]] and [[#22: Load Polygon With Geo]]) |
| B | Course ID number to warp to |
| C | Course area to jump to |
| D | Warp ID number in destination level area |
| E | If set to 0x80, then the game will create a checkpoint when the warp is triggered. |
----
==== 28: Setup instant area warp ====
Allows Mario to be instantly teleported to another area within the current level. The teleport to an area is triggered by the collision IDs 0x1B to 0x1E.
''28 0C [CC] [AA] [XX XX] [YY YY] [ZZ ZZ] 00 00''
| C | Determines which collision to use starting with 0x1B. (00 = 0x1B, 01 = 0x1C, etc.) |
| A | Course area # to go to |
| X | Teleport Mario by this amount on the X axis (s16) |
| Y | Teleport Mario by this amount on the Y axis (s16) |
| Z | Teleport Mario by this amount on the Z axis (s16) |
Teleporting between 4 areas example:
(In area 1 level script)
Warp to area 2 (Collision 0x1C): [ 28 0C 01 02 XX XX YY YY ZZ ZZ 00 00 ]
(In area 2 level script)
Warp to area 1 (Collision 0x1B): [ 28 0C 00 01 XX XX YY YY ZZ ZZ 00 00 ]
Warp to area 3 (Collision 0x1D): [ 28 0C 02 03 XX XX YY YY ZZ ZZ 00 00 ]
(In area 3 level script)
Warp to area 2 (Collision 0x1C): [ 28 0C 01 02 XX XX YY YY ZZ ZZ 00 00 ]
Warp to area 4 (Collision 0x1E): [ 28 0C 03 04 XX XX YY YY ZZ ZZ 00 00 ]
(In area 4 level script)
Warp to area 3 (Collision 0x1D): [ 28 0C 02 03 XX XX YY YY ZZ ZZ 00 00 ]
----
==== 29: ?? ====
''29 04 [??] 00''
| ? | Unknown |
Note: ?? is usually 01. ?? being 02 was only used once in the original game, in the Act Select level script.
----
==== 2A: ?? ====
''2A 04 00 00''
----
==== 0x2B: Set Mario's default position in the level ====
'' 2B 0C [AA] 00 [RY RY] [XX XX] [YY YY] [ZZ ZZ]''
Y = Y position of Mario (Signed 16-bits)
Z = Z position of Mario (Signed 16-bits)
| AA | Starting course area number |
| RY RY | Rotation across Y axis (Signed 16-bits)|
| X | X position of Mario (Signed 16-bits) |
| Y | Y position of Mario (Signed 16-bits) |
| Z | Z position of Mario (Signed 16-bits) |
==== 2C: ?? ====
''2C 04 00 00''
----
==== 2D: ?? ====
''2D 04 00 00''
----
==== 2E: Load Collision ====
Loads terrain collision data for level, and other special models to be placed in the level.
''2E 08 00 00 [XX XX XX XX]''
| X | Segmented address of [[sm64:collision_data]] |
----
==== 2F: Setup Render Room ====
Used in the levels Big Boo's Haunt, Hazy Maze Cave, and Inside Castle.
The segmented pointer in this command points to a byte array, with the same length as number of collision triangles in the level. Each byte in this array will be placed into offset 0x5 in the [[super_mario_64:structs#collision_triangle|collision triangle structure]].
When the ASM function 0x8029DBD4 is used with [[super_mario_64:geometry_layout_commands#eswitch_case|geometry layout switch command]], it will use that offset 0x5 byte of the collision triangle that is below Mario as an index to determine which display list to render.
''2F 08 00 00 [XX XX XX XX]''
| X | Segment offset to the byte array |
----
==== 30: Show dialog ====
Shows a dialog at the beginning of a level. Ignored if the value at 0x8038B8AC equals -1 or XX > 1.
''30 04 [XX] [YY]''
| X | Always 00? |
| Y | Dialog ID |
Examples:
[ 30 04 00 00 ] # Bob-Omb's Battlefield
[ 30 04 00 1E ] # Whomp's Fortress
[ 30 04 00 5A ] # Bowser 1 Course
[ 30 04 00 81 ] # Vanish Cap
[ 30 04 00 82 ] # Metal Cap
[ 30 04 00 83 ] # Wing Cap
----
==== 31: Set Default Terrain ====
Set default terrain.
''31 04 00 [XX]''
| X | 00 Normal A, 01 Normal B, 02 Snow, 03 Sand, 04 Haunted house, 05 Water levels, 06 Slippery Slide |
----
==== 32: No Operation 2 ====
No operation. This command is not used in any of the level scripts.
''32 [XX] ''
----
==== 33: Fade Color ====
Fade/overlay screen with color.
''33 08 [XX] [YY] [RR] [GG] [BB] 00''
| X | 01 Enable, 00 Disable |
| Y | Controls duration? usually 0x10 |
| R,G,B = red/green/blue color value |
----
==== 34: Blackout Screen ====
Calls [[http://level42.ca/projects/ultra64/Documentation/man/n64man/os/osViBlack.html|osViBlack(bool)]] (80323340), passing it X.
''34 04 [XX] 00''
| X | 1 = blackout, 0 = cancel blackout |
----
==== 35: ?? ====
''35 04 [XX] 00''
If X is 0, call 0x803733B0 (A0 = 2)
Else, call 0x803733B0 (A0 = 1)
----
==== 36: Set Music ====
Set music.
''36 08 [??] [??] [??] [XX] 00 00''
| ? | Other music parameters? |
| X | Sequence number |
----
==== 37: Set Music ====
Set music. Used only in screen levels, like select file, select star and mario face and demo screen.
''37 04 00 [XX]''
| X | Sequence number |
----
==== 38: ?? ====
''38 04 [XX XX]''
Call 0x8024922C (A0 = X)
----
==== 39: Place Macro Objects ====
Place macro objects defined in segmented address.
''39 08 00 00 [XX XX XX XX]''
| X | Segment offset pointer to object placement list |
List format: (each entry is 10 bytes)
''[BB BB] [XX XX] [YY YY] [ZZ ZZ] [?? ??]''
| B | Object type ID (references behaviour address and model id) and Y Rotation. First 7 bit are the Y-Rotation, the last 9 bit are the Object type ID. |
| X,Y,Z | Coordinates |
| ?? | Always 00 00 ? |
[[sm64:macro_objects|See here for more information]]
----
==== 3A: ?? ====
----
==== 3B: Jet Stream ====
Define jet streams in JRB or DDD that repulse or suck Mario.
''3B 0C 00 00 [XX XX] [YY YY] [ZZ ZZ] [II II]''
| X | X position |
| Y | Y position |
| Z | Z position |
| I | Intensity. negative means repulsion, positive means suction |
----
==== 3C: ?? ====
Get/put remote values? Only used in main or menu level scripts.
''3C 04 [XX] [YY]''
| X | ?? 01 in main level scripts, 00 in menu |
| Y | ?? 00, 02, 03 |
===== See Also =====
[[sm64:list_of_level_scripts]]
===== References =====
* http://origami64.net/showthread.php?tid=160
* http://qubedstudios.rustedlogic.net/Mario64_HackingDoc1.5.txt
* http://s26.photobucket.com/user/Starxxon/media/M64Diagram.gif.html