Actors

From CloudModding OoT Wiki
Jump to: navigation, search
See also: Category:Actors

Actors are the various interactive pieces in the Zelda 64 engine, from enemies to static scenery.

There are three major components to an actor:

  • The actor's overlay, a file that contains the code for an actor
  • Actor instances, or an in memory representation of our actor.
  • Object files, one or more files that contain pre-generated microcode, animations, and graphical assets for an actor. These can be shared by multiple actors.

Actor Overlay Table

For a list of the data within this table, see Actor List.
code (File)
Actor Overlay Table
VersionOffsetVRomVRam
Debug0F944000B8D44000B90F20801162A080119D80
NTSC 1.00D749000B5E49000B61F70800E8530800EC010
PAL MQ0D448000B5C48000B5FF60800E5380800E8E60

The actor table manages the actor files (overlays). It defines an actor's number, maps the actor to a virtual address, and during gameplay is used to find the overlay in ram.

Format

xxxxxxxx yyyyyyyy aaaaaaaa bbbbbbbb
rrrrrrrr iiiiiiii nnnnnnnn vvvvcc00

This breaks down into-
x y: Start/End Virtual Rom addresses of the actor file
a b: Start/End Virtual Ram addresses of the actor file
r: Ram address of actor file (00000000 if overlay isn't loaded, or if in ROM)
i: Virtual Ram address of the start of the actor instance initialization variables, located within the file
n: Address of actor filename (Debug ROM only, value is 0 in commercial releases)
v: Allocation Type, affects how overlay is allocated. See below for values
c: Number of actor instances of this type currently loaded (ram only)

Allocation Type Values

00 performs a "low to high" address allocation (high address volatility), unloading the overlay if no instances of that actor exist
01 performs a "high to low" address allocation (low address volatility), reserving a fixed space for all overlays of this type until the scene is destructed. Only one overlay of this type can ever be loaded at once. The pointer to this space is located at Global Context + 0x1C60
02 performs a "high to low" address allocation (low address volatility), keeping the overlay in ram until the scene is destructed

Note: The record for Link's actor in rom (the first record in the table) only sets the vram address that points to the start of the variable info for Link's actor, and the actor file name pointer if it's the Debug Rom.

Overlay File

See Overlays for more information on the overlay format.

Initialization Variables

The actor's initialization variables are pointed to via the 6th word in the Actor Overlay Table.

/* 0x00 */ s16 ActorNumber //value does not always match the instance's real actor number
/* 0x02 */ u8  ActorType //See Below
/* 0x03 */ u8  RoomNumber //Room instance was spawned in. If value set to FF in rom, instance does not despawn when swapping rooms

/* 0x04 */ s32 Flags //unknown, but seems to have an effect on the ability to Z-Target an actor. 
/* 0x08 */ s16 ObjectNumber //possibly it's primary object dependency
/* 0x0A */ //Padding

/* 0x0C */ int InstanceSize
/* 0x10 */ int* Constructor
/* 0x14 */ int* Destructor 
/* 0x18 */ int* Main
/* 0x1C */ int* Draw

Some notes on the "Flags" variable:

  • If it's set to 0x10, the actor seems to not be targetable when initialized.
  • If it's set to 0x9, it is targetable.

Common Data Structures

Actor Instances

Structure

For Ocarina of Time, the allocated actor structure is as follows. Alternate (better) versions here. The Majora's Mask actor structure is similar but not interchangeable.

typedef struct {
    f32 x, y, z;
} Coord;

typedef struct {
    s16 x, y, z;
} Rotation;

typedef struct
{
    /* 0x00 */ u16 actorNo;
    /* 0x02 */ u8 actorType;
    /* 0x03 */ u8 roomNo; //Room number the actor is part of. FF denotes that the actor won't despawn on a room change
    /* 0x04 */ s32 unk_0x004; //flags used for drawing stuff?
    /* 0x08 */ Coord Pos1; //Related to collision detection routine
    /* 0x14 */ Rotation initRot; //Initial Rotation when spawned
    /* 0x1A */ u16 unk_0x01A;
    /* 0x1C */ u16 actorVariable;
    /* 0x1E */ s8 objAllocTableIndex; //index to table at Global Context + 0x117A4 
    /* 0x1F */ u8 unk_0x01F;
    /* 0x20 */ u16 soundEffect; //Plays sound effect (relative to actor's location, if within range of camera?) 
    /* 0x22 */ u16 unk_0x022;
    /* 0x24 */ Coord Pos2; //Current coordinate
    /* 0x30 */ u16 unk_0x030;
    /* 0x32 */ s16 SpeedXZ_YRot; //sets what direction the 0x68 SpeedXZ variable is moving the actor
    /* 0x34 */ 
    /* 0x38 */ Coord Pos3; //Related to camera
    /* 0x44 */ Rotation rot_1;
    /* 0x4A */ u16 unk_0x04A;
    /* 0x4C */ f32 unk_0x04C; /* I know this is a float from breakpointing it */
    /* 0x50 */ Coord Scale; //sets x,y,z scaling factor. Typically, a factor of 0.01 is used for each axis
    /* 0x5C */ float velocityX;
    /* 0x60 */ float velocityY;
    /* 0x64 */ float velocityZ;
    /* 0x68 */ float SpeedXZ; //Always positive, stores how fast the actor is traveling along the XZ plane
    /* 0x6C */ float gravity; //acceleration due to gravity; value is added to Y velocity every frame
    /* 0x70 */ float minVelocityY; //sets the lower bounds cap on velocity along the Y axis
    /* 0x74 */ int* unk_0x074; //unknown
    /* 0x78 */ int* unk_0x078; //unknown
    /* 0x7C */ u8 unk_0x07C;
    /* 0x7D */ u8 unk_0x07D; //unknown, related to 0x80/88
    /* 0x80 */ float unk_0x080;
    /* 0x84 */ float unk_0x084;
    /* 0x88 */ u16 unk_0x088; //unknown
    /* 0x8A */ s16 unk_roty; //rotation y (give item, possibly next facing dir?/face toward link?)
    /* 0x8C */ float unk_0x08C;
    /* 0x90 */ float distanceFromLink; // (item giving routine)
    /* 0x94 */ float unk_0x094; //related to above
    /* 8-10-2012 : Addition made by Jason777 */
    /* For actors which contain a damage chart (example: Stalfos)... */
    struct 
    {
    /* 0x98 */ u32 DamageChart;  /* Pointer to the actor's Damage Chart in RAM. */
    /* 0x9C */ Coord velocity2; //secondary x,y,z vector for positioning (probably platform actors), added to 0x5C vector
    /* 0xA8 */ s16 unk_0x0A8; 
    /* 0xAA */ s16 unk_0x0AA; 
    /* 0xAC */ u16 unk_0x0AC; //unk
    /* 0xAE */ u8 unkn_00AE; // Collision related?, Set to 0xFD by bottled blue fire
    /* 0xAF */ u8 Health; 
    /* 0xB0 */ u8 Damage; //amount to decrement health by
    /* 0xB1 */ u8 DamageEffect; //Stores what effect should occur when hit by a weapon
    /* 0xB2 */ u8 ImpactEffect; //Maybe? set on deku nut when deku nut collides with gossip stone
    /* 0xB3 */ u8 unk_0x0B3; //?
    }; /* end damage chart data */
    
    struct {
    /* 0xB4 */ Rotation rot_2; //updating this value changes an actor's rotation immediately
    /* 0xBA */ 
    /* 0xBB */ u8 unk_0x0BB; //unknown byte?
    /* 0xBC */ float unk_0x0BC; //unknown
    /* 0xC0 */ int* unk_0x0C0; //unknown func ptr. if not null, called after draw function for actor
    /* 0xC4 */ float unk_0x0C4;
    /* 0xC8 */ u8 unk_0x0C8;
    }; //NTSC 1.0 initializes with 8001EC20
    /* 0xCC */ Coord unk_0x0CC; //used in Link, not Deku Babas 
    /* 0xD8 */ Coord unk_0x0D8; //used in Link, not Deku Babas
    /* 0xE4 */ Coord unk_0x0E4; //stores result of some vector transformation involving
                        // actor xyz vector, and a matrix at Global Context + 11D60
    /* 0xF0 */ float unk_0x0F0; //related to above
    /* 0xF4 */ float unk_0x0F4; //unknown
    /* 0xF8 */ float unk_0x0F8; //unknown
    /* 0x100 */ Coord Pos4;
    /* 0x10C */ s8 unk_0x10C; //Z-Target related
    /* 0x10D */ s8 unk_0x10D; //Z-Target related
    /* 0x10E */ u16 textId; //text id to pass to link/display when interacting with an actor (navi text, probably others)
    /* 0x110 */ s16 freezeActor; //Used for the "Redead Freeze" attack
    /* 0x114 */ u8 unk_0x114; //Deku Nut Stun Timer?, decremented toward 0 every frame
    /* 0x115 */ u8 runActor; // Determines if actor instance should be processed. 01 for yes, 00 for no.
    /* 0x116 */ u8 unknown; //set within a routine that deals with collision
    /* 0x117 */ u8 naviEnemyId; //sets what 0600 dialog to display when talking to navi. Default 0xFF
    /* 0x118 */ struct z_Actor* attachedA; //Interfacing? (e.g. Link holding chu, Chu instance stores ptr to Link instance... or Anju having Link's ptr when giving an item
    /* 0x11C */ struct z_Actor* attachedB; //Attached to Actor (e.g. Link holding chu, Link instance stores ptr to Bombchu instance)
    /* 0x120 */ struct z_Actor* actor_prev; /* Previous z_Actor of this type */
    /* 0x124 */ struct z_Actor* actor_next; /* Next z_Actor of this type */
    /* 0x128 */ u32 ActorInit; //Initialization Routine
    /* 0x12C */ u32 ActorDest; //Actor destructor 
    /* 0x130 */ u32 ActorMain; //Main Update function, called every frame the actor is to be updated
    /* 0x134 */ u32 ActorDraw; //Draw Routine, writes necessary display lists
    /* 0x138 */ u32 CodeEntry; //Address to source overlay file's reference in code (file)
    /* From here on, the structure and size varies for each actor */
} z_Actor;
//actors with a poly-type collision mesh will always set this variable
    /* 0x13C */ s32 PolyActorId; //Index for poly mesh

Categories

Global Context
Actor Category Table
VersionOffsetVRam
Debug001C3080213C5080213CB0
NTSC 1.0001C30801CA0D0801CA130
NTSC 1.1001C30??
NTSC 1.2001C30??
PAL 1.0001C30??
PAL 1.1001C30??
PAL MQ001C3000001C3000001C90

Actor instances are added into a doubly-linked list based on a category id. Ids can be set in the overlay file, but can also be pro grammatically modified (ex. Skulltula/Gold Skulltula actor). There are 12 categories total. Majora's Mask may use 16 different categories.

char * actor_types[12] = {
    "Switch",	"Prop (1)",	"Player",	"Bomb",
    "NPC",	"Enemy",	"Prop (2)",	"Item/Action",
    "Misc",	"Boss",		"Door",		"Chests"
};
Id Description Usage
0 Switches Step-on switches, Anubis enemy, Death Mountain Crater Smoke Cone
1 Prop (1) Typically larger, more complex set pieces
2 Player
3 Bomb Bombs, Bombchus
4 NPC
5 Enemy Used for triggering room clear state.
6 Prop
7 Item/Action
8 Misc
9 Boss
10 Door
11 Chests

Loading Actors

What is currently known about the loading and execution of code from actors in Zelda 64 is that:

  • The first time an actor is loaded (spawned), its overlay file is transferred to RAM
    • The transferred file has its offsets relocated to a real address space in RAM
    • The actor file remains allocated in ram until all instances of that actor have despawned
  • The game begins to create an instance of the actor
  • For each actor instance, actors are given a certain amount of memory as defined in the actor file. However, the minimum space required by the game's engine is 0x128 bytes in OoT (MM may vary).
    • Within this given memory is information such as
      • Location
      • Rotation
      • Scale
      • Pointer to damage chart (if the actor has one)
      • Pointers to actor functions
        • Initialization - run when actor instance is loaded.
        • Main - always run during gameplay.
        • Drawing - to be run when actor is close enough to the camera.
      • Pointer to Next/Previous actor(s) of this actor's category
      • Whatever else that actor needs (ex. instanced variables).

At Global Context + 0x1C30 (80213C50 in the Debug Rom's RAM) is a list of actor categories (see above), each entry being an integer and a pointer. The pointer points to the first allocated entry for an actor. The integer is the number of actors of that category, the first entry being type 0, and the last last being type 11 (chests). Actors after the first actor are pointed to through the next/previous pointers within each allocated actor.

Compact Instance Initialization Format

Some actors use a "compact" format in order to initialize instance variables to a default value other than 0. The parser function is located at NTSC 1.0 80063F7C, accepting an Actor Instance pointer (plus possibly an offset divisible by 0x800) followed by a pointer to the "compact" format to parse.

The format is as follows:

(v >> 0x1F) & 1  == Continue Parsing
(v >> 0x1C) & 7  == Type
(v >> 8) & 0x7FF == Offset from start of instance to write initial value
v & 0xFFFF       == Value. 

As implied, the "compact" format is continuously parsed until a 0 Continue Parsing bit is encountered.

The following types are supported. Note that duplicates exist due to signed/unsigned types having the same initialization logic.

  • 0, Set Byte
  • 1, Set Byte
  • 2, Set Halfword
  • 3, Set Halfword
  • 4, Set Word
  • 5, Set Word
  • 6, Set Float (int to float)
  • 7, Set Float (int to float / 1000)
  • 8, Set Vector3D<float> (int to float)
  • 9, Set Vector3D<float> (int to float)/1000)
  • A, Set Vector3D<short>

Custom Actors

A number of custom actors have been created. For more information, see Overlays.

Examples

Every actor in Debug MQ disassembled

Credits

Cendamos - Actor table information, misc stuff that got the ball rolling
Euler - Actor file structure
JayTheHam - His early work with Cendamos on actor information
ZZT32 - Explained some actor table stuff to me
spinout - Writing this article