Language…
18 users online: Alex No, ben15420, DanMario24YT, gcrackaaa, GiraffeKiller, Gmario37, Gorry, Green, Hidincuzimsmokin, JudithPrietht, Metal-Yoshi94, MorrieTheMagpie, rafaelfutbal, Ray Hamilton, ShoopDaWhoop, Sniwott, VoidCrypt, wayht - Guests: 285 - Bots: 457
Users: 64,795 (2,371 active)
Latest user: mathew

SM64 Behavior scripts ~95% decoded

I used the last 2 days of my life to decode all behavior script functions, that are in the game. i also gave a small instruction, how they work. If there are any mistakes, tell me. Look at the bottom for some examples of new usage!
nearly completed behavior script list(by Vltone (50%), Dudaw (20%) and me(30%), i put the information together:
http://rapidshare.com/files/217684940/Behavior%20Scripts.txt



i think 3/4 of these commands aren't necessary and could be replaced for something useful. if anyone has an idea, tell me.

0x00: marks start, if behavior =4FD4, 5024, it executes 2A4120. if it is 32E0, it sets 0x194 to 43160000 (float)
[1] command
[2] ignored, priority?
[3,4] 00 00
------------------------------------------------------------------------
0x01 used by some small effects, writes 1 to 0x1F4 of object, if [3,4]>current 0x1F4. otherwise 0
[1] command
[2] gets ignored
[3,4] see above

----------------------------------------------------------
0x02: jumps into another behavior and changes obj->0x1D0
[1] command
[2,3,4] ignored
[5] bank id
[6,7,8] jump destination
-------------------------------------------------------------
0x03 writes something to 0x1D0. jumps into behavior at object->0x1d4
[1] command
[2-4] ignored
------------------------------------------------------------
0x04: Jump command
[1] command
[2-4] ignored
[5] bank id
[6-8] jump destination
------------------------------------------------------------
0x05: Loop specified amount of times (does this rly work?...)
[1] command
[2]ignored
[3,4] amount
-------------------------------------------
0x06: End 0x05 loop
[1] command
[2-4] ignored
------------------------------------------------------------
0x07 jumps back 4 Bytes (results in infintie loop normally)
[1]command
[2-4] ignored
384554
--------------------------------------------
0x08: Loop start
[1] command
[2-4] ignored
----------------------------------------------
0x09: End loop (warning, behavior ends normally at this, if it's not set, it will go into the next behavior)
[1] command
[2-4] ignored
------------------------------------------
0x0A: Empty command
[1] command
[2-4] ignored
----------------------------------------------
0x0B: empty command
[1] command
[2-4] ignored
----------------------------------------------------
0x0C: calls function
[1]command
[2-4] ignored
[5-8] virtual memory address
----------------------------------------------------------
0x0D mostly used to offset x,y or z position a bit, it's useless except for dorrie
[1]command
[2]*4+88:=address
object->address:=<content of address>+[3-4 converted to float]
(special cases are 06, 07 and 08. 06 is X-, 07 is Y- and 08 is Z-position
[3-4] see above
--------------------------------------------------------
0x0E mostly used for sight distance, does nearly the same than above
[1] command
[2]*4+88:=address
object->address:=[3-4 converted to float]
(special cases is 45 for sight distance)
[3-4] see above

-------------------------------------------------
0x0F: mostly used as texture animation rate; same than 0x0D, but without float
[1] command
[2]*4+88:= address
object->address:=[3-4]
(special case is 1A for texture animation rate)
[3-4] see above
------------------------------------------------------
0x10: special parameter
[1] command
[2]*4+88:= address
object->address:=<content of address> +[3-4]
(special case is 2A for interaction or 2F for Bparam2 rate)
[3-4] see above
------------------------------------------------------
0x11 Loads and ORs
[1] command
[2]*4+88:= address
object->address:=<content of address> or(bitwise/logical) [3-4]
[3-4] see above
-------------------------------------------------------
0x12 Loads and ANDs
[1] command
[2]*4+88:= address
object->address:=<content of address> AND(bitwise/logical) <FFFF xor(bitwise/logical) [3-4]>
[3-4] see above
-------------------------------------------------------
0x13 unused, 8038eee0 related.
[1] command
[2]*4+88:=address
object->address:=the result of the addition below
[3-4] gets added to the result of the rightshift from [5-6]
[5-6] shifts the value of 8038eee0 (contains a random generated number) this amount
[7-8] ignored
------------------------------------------------------------
0x14 mostly used for object type, one time for yspeed?
[1] command
[2]*4+88:= address
object->address:=[3-4]*[5-6]
[3-4] gets converted to float 0x20
[5-6] converted to float 0x1C
-----------------------------------------
0x15 haven't done this at all
[1] command
[2]*4+88:= address
[3-4] ?
--------------------------------------------
0x16 haven't done this at all
[1] command
[2]*4+88:= address
[3-4] ?
[5,6,7,8] ?
--------------------------------------------
0x17 haven't done this at all
[1] command
[2]*4+88:= address
[3-4] ?
[5,6,7,8] ?
--------------------------------------------
0x18 does absolutely nothing
[1] command
[2] trolling around
[3-4] ignored
---------------------------------------
0x19 exactly the same than 0x18, but located somewhere else
[1] command
[2] trolling around
[3-4] ignored
-----------------------------------------------------
0x1A exactly the same than 0x18, but located somewhere else
[1] command
[2] trolling around
[3-4] ignored
-----------------------------------------------------
0x1B: changes the model ID of current behavior
[1] command
[2]ignored
[3-4] model ID
----------------------------------------------------
0x1C: Load child object and saves child object pointer to 0x6C (automatically follows?)
[1] command
[2-4] ignored
[5-8] model ID
[9-12] behavior+bank ID
------------------------------------------------------------------------
0x1D deactivates object
[1] command
[2-4] ignored
--------------------------------------------------------------------------
0x1E: DROP TO GROUND(not sure) and saves 2 to object->0xEC?
[1] command
[2-4] ignored
------------------------------------------------------------------
0x1F used for waves
[1] command
[2]*4+88:= address1
object->address1 := <content of address 2> +(floating point addition) <content of address3>
[3]*4:= address2 0x08
[4]*4:= address3 0x04
---------------------------------------------------------------------------
0x20 unused?
[1] command
[2]*4+88:= address1
object->address1 := <content of address 2> + <content of address3>
[3]*4+ object pointer:= address2
[4]*4+ object pointer:= address3
------------------------------------------------------------------------------
0x21: Set billboarding (ORs graph flags with 0x4)
[1] command
[2-4] ignored
-------------------------------------------------------------------------------
0x22: Unknown; Ors graph flags with 0x10 (=executes "unhide object" - function)
[1] command
[2-4]
----------------------------------------------------------------------------------
0x23: Collision sphere size
[1] command
[2-4] ignored
[5-6] x and z sphere
[7-8] y sphere
----------------------------------------------------------------------------------
0x24 does absolutely nothing
[1] command
[2] trolling around
[3-4] trolling around
----------------------------------------------------------------------------------
0x25 unused?
[1] command
[2]*4+88 + object pointer:= address
if <<content of address>-1> smaller than <object->0x1F4{
object->0x1F4:=object->0x1F4+1}
else
object->0x1F4 :=0
[3-4]ignored
------------------------------------------------------------------------------
0x26 unused. Is a bit useless and can destroy the reader.
[1] command
[2] gets saved to <content of object->0x1D0>*4 (will mostly be 1D0, 1D4 or 1D8)
[3-4] ignored
-------------------------------------------------------------------------------
0x27: Animation command
[1] command
[2]*4+88:= address
object->address:= <content of [5-8]>
(special case: 26 for animation)
[3-4] ignored
[5-8] see above
--------------------------------------------------------------------------------
0x28: animates object
[1] command
[2] animation number (gets multiplyed by 4, because every address is 4 bytes)
[3-4] ignored
--------------------------------------------------------------------------------
0x29: Load child Object [7 is model id]
[1] command
[2] ignored
[3-4] Bparam for child object
[5-8] model ID 0x20
[9-12] 0x1C
----------------------------------------------------------------------------
0x2A set collision
[1] command
[3-4] ignored
[5-8] segmented collision pointer (get's interpreted to virtual in the 0x2A function)
------------------------------------------------------------------------------
0x2B set collision sphere (second one - used at 1ups)
[1] command
[2-4] ignored
[5-6] x/z sphere as int
[7-8] y sphere as int
[9-10] converted to float; saved to 0x208
[11-12] ignored
--------------------------------------------------------------------------------------
0x2C spawns object; same than 0x1C, but without storing child object pointer
[1] command
[2-4] ignored
[5-8] 0x24
[9-12] 0x20
---------------------------------------------------------------------------------------
0x2D: Declare initial position; saves positions to 0x164,0x168 and 0x16C (used for things like dorrie, fly guys, so they know, in which range they can move)
[1] command
[2-4] ignored
----------------------------------------------------------------------------------------
0x2E uselessly long version of 0F
[1] command
[2-4] ignored
[5-6] converted to float; saved to 0x200
[7-8] converted to float; saved to 0x204
-----------------------------------------------------------------------------
0x2F: Set Interaction (27 2A would do too)
[1] command
[2-4] ignored
[5-8] Interaction
------------------------------------------------------------------------------
0x30 set gravity
[1] command
[2-4] ignored
[5-6] saved to 0x128 converted to floating point
[7-8] <converted to float> /100 ; saved to 0xE8
[9-10] <converted to float> / 100 ; saved to 0x158
[11-12] <converted to float> /100 ; saved to 0x12C
[13-14] <converted to float> /100 ; saved to 0x170
[15-16] <converted to float> /100 ; saved to 0x174
[17-18] <converted to float> /100 and then ignored
[19-20] <converted to float> /100 and then ignored
-----------------------------------------------------------------------------------
0x31
[1] command
[2-4] ignored
[5-8] gets saved to object->190
-------------------------------------------------------------------------------------
0x32: Scale object uniformly
[1] command
[2] trolling around
[3-4] scaling (in percent)
------------------------------------------------------------------------------------------
0x33 child object change command
[1] command
[2]*4+88 + child object pointer:=address
<content of address> AND (logical/bitwise) [3-4] := <content of address>
[3-4] see above
---------------------------------------------------------------------------------------------
0x34: Texture animation rate?
[1] command
[2]*4:=address
object->address:= <content of address> + 1 0x07
(special case is 1A for texture animation rate)

WARNING! NON-FLOATING POINT DIVISION
if [3-4]/<content of 8032d5d4 (whats this?)> 1 {do nothing}
if [3-4]/content of 8032d5d4<1 and [3-4]>1 0x04
-----------------------------------------------------------------------
0x35 sets last byte of graph flags to 0
[1] command
[2-4] ignored
---------------------------------------------------------------------------------
0x36
[1] command
[2]*4:=address
object->address := [7-8] 0x07
[3-6] ignored
[7-8] 0x00

------------------------------------------------------------------------------------
0x37 spawns something
[1] Command
[2-4] ignored
[5-8] virtual memory address for spawn function;
reads the next 8 bytes from this address:

can't tell, what happens to byte 1 and 2 exactly, but it affects rotation
byte 3 and 4=model ID
byte 5 bank ID for behavior
byte 6-8 behavior ID




annotation:
trolling around means, that it does nothing, but gets loaded at least once
floating points/floats are a special form of numbers, google them or you won't understand them.

10 2B 00 00 => enable collission
10 05 00 00 => enable interaction


80385CEC:
LUI T4, $8036
LW T4, $1164 (T4) <-loads reader position
LUI T8, $8039
LW T5, $0000 (T4) <-loads current behavior command first 4 bytes
SRL T6, T5, $18 <- rightshift 18 bits; only first byte stays
SLL T7, T6, $2 <-T6:= T6*4
ADDU T8, T8, T7 <-to get the right function (see below)
LW T8, $B9B0 (T8) <-function table is at 8038B9B0; with the addition of the first byte, it gets the right function
SW T8, $0020 (SP) <-saving in stack, because compilers suck
LW T9, $0020 (SP) <-loading same value from stack, because compilers suck
JALR RA, T9 <-executing function



8038B9B0(can be found through setting a BP on a behavior script line, which start at 800EB180) :
80 38 54 CC - 80 38 42 5C - 80 38 41 B8 - 80 38 42 24 /03
80 38 43 8C - 80 38 44 50 - 80 38 44 C0 - 80 38 45 54 /07
80 38 45 E8 - 80 38 46 34 - 80 38 41 88 - 80 38 41 A0 /0B
80 38 46 78 - 80 38 4C 5C - 80 38 46 D0 - 80 38 4C F0 /0F
80 38 47 5C - 80 38 4D 70 - 80 38 4E 04 - 80 38 49 F8 /13
80 38 48 54 - 80 38 49 28 - 80 38 4A B4 - 80 38 4B 90 /17
80 38 50 3C - 80 38 50 CC - 80 38 50 84 - 80 38 3F 24 /1b
80 38 3F 94 - 80 38 41 64 - 80 38 4F 8C - 80 38 51 14 /1f
80 38 51 D0 - 80 38 3E E4 - 80 38 3E 5C - 80 38 52 8C /23
80 38 54 6C - 80 38 42 E4 - 80 38 43 E0 - 80 38 4E 9C /27
80 38 4F 08 - 80 38 40 B4 - 80 38 56 A0 - 80 38 53 AC /2b
80 38 40 1C - 80 38 57 00 - 80 38 53 1C - 80 38 57 5C /2f
80 38 58 6C - 80 38 57 A0 - 80 38 57 E4 - 80 38 5A 60 /33
80 38 5B 4C - 80 38 3E A0 - 80 38 47 D4 - 80 38 5A F0 /37

8038531C is at ROM 10209C. the rest can be calculated through this.




Object struct, by messiaen mostly:
typedef struct object_struct /* Regular objects, Mario also has its own struct like this */
{
u16 graph_node_type; /* 0x00 */
u16 graph_flags;
struct object_struct *prev; /* previous linked list object */
struct object_struct *next; /* next linked list object */
u32 graph_parent;
u32 graph_child; /* 0x10 */
u32 geo_layout_ptr; /* 0x14 */
u32 _0x18;
u32 _0x1c;
float _0x20; /* 0x20 */
float _0x24;
float _0x28;
float x_scaling; /* 0x2c */
float y_scaling; /* 0x30 */
float z_scaling;
u16 _0x38;
u16 _0x3a;
u32 animation; /* 0x3c - current animation */
u16 anim_current_frame; /* 0x40 */
u16 anim_timer; /* timer, animation related? */
u16 anim_current_frame_copy;
u16 _0x46;
u32 _0x48;
u32 _0x4c;
u32 matrix_ptr; /* 0x50 */
float float_0x54;
float float_0x58;
float float_0x5c;
struct object_struct *next_object_ptr; /* 0x60: re-check this */
u32 _0x64;
struct object_struct *next_object_ptr2; /* 0x68: re-check this (child_obj) */
u32 _0x6c;
u32 _0x70; /* 0x70 */
u16 active; /* 0x0000 = inactive, 0x0101 = active */
u16 _0x76; /* collision flag according to YE */
struct object_struct *collided_obj_ptr; /* according to YE, pointer to object collided with */
u32 _0x7c;
u32 _0x80; /* 0x80 */
u32 _0x84;
u32 _0x88;
u32 obj_flags;
u32 _0x90; /* 0x90 */
u32 _0x94;
u32 _0x98;
u32 _0x9c; /*points to controller (for mario) enables interaction*/
float x_pos; /* 0xa0 (defined at 80254FB4) */
float y_pos;
float z_pos;
float x_speed; /* x increment? */
float y_speed; /* 0xb0 */
float z_speed; /* z_increment? */
float speed;
u32 _0xbc;
u32 _0xc0; /* 0xc0 */
u32 x_rotation; /* 0xc4 - rotation triplet */
u32 y_rotation; /* 0xc8 */
u32 z_rotation;
u32 x_rotation2; /* rotation copy (collision?) 0xd0 */
u32 y_rotation2; /* 0xd4 */
u32 z_rotation2;
u32 _0xdc;
u32 _0xe0; /* 0xe0 */
float _0xe4; /* gravity related? y_speed - 0xe4 ? */
u32 _0xe8;
u32 _0xec;
u32 _0xf0; /* 0xf0 - texutre animation rate? */
u32 _0xf4; /* messiaen: obj type for some behaviors (ie, ice bully), for AMPS, radius of rotation
kaze: related to xposition for waves*/
u32 _0xf8; /* related to Y position for waves */
u32 _0xfc; /* related to Z position for waves */
u32 _0x100; /* 0x100 */
u32 _0x104;
u32 _0x108; /*bparam 2 copy (at least for toad) ? */
u32 _0x10c;
u32 _0x110; /* 0x110 */
u32 _0x114;
u32 _0x118;
u32 _0x11c;
u32 animation_ptr; /* 0x120 = (set by 0x27 26 behavior command) entry for animation? */
u32 _0x124; /* in some behaviors, action related? */
float _0x128; /* gravity? */
float _0x12c; /*movement/gravity related*/
u32 interaction; /* 0x130
00 = Something Solid. Can't grab. Mario walks around, Can jump over.
01 = Crashed when jumping at it, Used by Hoot.
02 = Grabbing
04 = Going through door
08 = Knocks mario back and dissappears. No damage.
10 = Something Solid, Can't grab, Mario walks around, Can't jump over, Seems somewhat thin..
40 = Climbing
*/
u32 _0x134; /* has to be 0 to have an interaction*/
u32 _0x138;
u32 _0x13c;
u32 _0x140; /* 0x140 */
u32 behav_param2; /* behav param 2*/
u32 _0x148;
u32 action;
u32 _0x150; /* 0x150 = also reset when action changes */
u32 timer; /* always incremented. When action changes, it's set to 0 */
float _0x158; /*movement/gravity related */
float distance_from_mario;
u32 _0x160; /* 0x160 */
float _0x164_x; /*set by 0x2d behavior script command*/
float _0x168_y; /*set by 0x2d behavior script command*/
float _0x16c_z; /*set by 0x2d behavior script command*/
float _0x170; /* movement/gravity related */
float _0x174; /*movement/gravity related?*/
u32 _0x178;
u32 transparency;
u32 damage_to_mario; /* According to YE, "How many segments of damage to do to Mario for objects that cause him harm" */
u32 health; /* Health (ie, for King bob-omb and whomp */
u32 behav_param; /* strange thing */
u32 previous_action; /* used to reset the 0x154 timer */
u32 _0x190; /* 0x190 */
float collision_distance; /* NOTE: if collision_distance < disappear_distance then disappear_distance = collision_distance */
u32 _0x198;
float drawing_distance;
u32 _0x1a0; /* 0x1a0 set at mad piano and haunted chair? */
u32 _0x1a4;
u32 _0x1a8;
u32 _0x1ac;
u32 _0x1b0; /* 0x1b0 */
u32 _0x1b4;
u32 _0x1b8;
u32 _0x1bc;
u32 _0x1c0; /* 0x1c0 */
u32 _0x1c4;
u32 _0x1c8;
u32 script_ptr; /*maybe a reader for the pointer*/
u32 stack_index; /* 0x1d0 */
u32 stack;
u32 _0x1d8;
u32 _0x1dc;
u32 _0x1e0; /* 0x1e0 */
u32 _0x1e4;
u32 _0x1e8;
u32 _0x1ec;
u32 _0x1f0; /* 0x1f0 */
u16 _0x1f4;
u16 _0x1f6;
float col_sphere_xz;
float col_sphere_y;
float _0x200; /* 0x200 */
float _0x204;
float _0x208;
u32 behavior_script_entry;
u32 _0x210; /* 0x210 */
u32 collide_obj_ptr; /* pointer to another object (collision happening)?.
Can be used to detect if Mario is on top of the object by comparing
value with Mario's pointer */
u32 collision_ptr; /* set by behavior script (0x2A command) or hardcoded*/
u32 _0x21c;
u32 _0x220; /* 0x220 */
u32 _0x224;
u32 _0x228;
u32 _0x22c;
u32 _0x230; /* 0x230 */
u32 _0x234;
u32 _0x238;
u32 _0x23c;
u32 _0x240; /* 0x240 */
u32 _0x244;
u32 _0x248;
u32 _0x24c;
u32 _0x250; /* 0x250 */
u32 _0x254;
u32 _0x258;
u32 behav_param_copy_ptr;
} Object;

there may be mistakes and some unused/unknown values.


What can be done with this knowledge?

Code
Piranha Plant, attacking everytime:
00 04 00 00 
27 26 00 00 06 01 C3 1C <-sets animation stack pointer
28 00 00 00 <-sets animation from stack; change the second byte for sleeping or smth
10 2A 00 08 <- sets interaction; could also be 2F 00 00 00 00 00 00 08, but this is shorter
0E 5C 00 64 <-x/z sphere
0E 5D 00 C8 <-y sphere  (you could exchange these commands for a 0x23 command, but i wanted to demonstrate it)
10 3E 00 03 <-sets damage to mario
08 00 00 00 <-loopstart
10 05 00 00 <-enables interaction
10 2B 00 00 <-reset interaction
09 00 00 00 <-loopend


Code
elevator thwomp/moving objects in general:
00 09 00 00
2A 00 00 00 05 00 B9 2C <-collision pointer, has to be changed for other objects
0E 43 4B FF <-giant collision distance, don't know, if it's necessary
08 00 00 00 <-loopstart
0D 07 00 01 <-changed Y coordinate every frame
0C 00 00 00 80 38 39 CC <-processes solidity
09 00 00 00 <-loopend


you could do other funny stuff to, like letting an object rotate through just 0x0D commands.

[Restored for anyone curious about this information]
TL;DR but I noticed a few things:

- you stated that the 0A command was empty, well maybe the function is but everyone should know that this command is used to terminate a non-looping behavior; it's used quite often so "empty" maybe, but "free to use" certainly not!

- the second byte of 0x00 command is used to define the TYPE of object so that it is placed in the right linked list ( for various processing reasons ). I've discovered that when I was trying to solve the BIG problem of the RAM object chain ( linked list ) overflow.

- 0x1E does instantly edit the Y position so that the object lays directly on a collision triangle THAT BELONGS TO THE LEVEL COLLISION DATA. You cannot make an object stand on something with its own collision data like a breakable box or a floating rotating island. This gave me trouble to figure out when I had to place a pink Bob-Omb on one of those islands.
Uber Mario 64 Demo released, 16 awesomely challenging stars awaits YOU!
I've spotted another mistake:

In the command 0x30, the half-word at [7-8] is actually stored in the offset 0xE4, not 0xE8.
Uber Mario 64 Demo released, 16 awesomely challenging stars awaits YOU!