Actors
Cross-link to the Ocarina of Time wiki: Actors |
Actors are the various interactive pieces in the Zelda 64 engine, from enemies to static scenery.
Contents
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
Version | VRom | VRam | Size | ||
---|---|---|---|---|---|
Debug | DD5A50 | ? | ? | ? | 5640 |
US 1.0 | C45510 | ? | 801AEFD0 | ? | 5640 |
USA GC | C52280 | C578A0 | ? | ? | 5640 |
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
pppppppp iiiiiiii nnnnnnnn ????cc??
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
p: 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 roms)
c: Number of actor instances of this type currently loaded (ram only)
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*/ short ActorNumber //value does not always match the instance's real actor number
/*0x02*/ byte ActorType //See Below
/*0x03*/ byte RoomNumber //Room instance was spawned in. If value set to FF in rom, instance does not despawn when swapping rooms
//0x04 is unknown
/*0x08*/ short ObjectNumber //possibly it's primary object dependency
//0x0A Padding
/*0x0C*/ int InstanceSize
/*0x10*/ int* ?
/*0x14*/ int* Deconstructor
/*0x18*/ int* ?
/*0x1C*/ int* ?
Common Data Structures
Actor Instances
typedef struct {
f32 x, y, z;
} Coord;
typedef struct {
u16 x, y, z;
} rotation;
typedef struct
{
struct
{
char Damage : 4;
char Effect : 4;
} Attack[0x20];
} z2_ActorDamageTable;
typedef struct
{
/* 0x00 */ u16 id; //Actor Id.
/* 0x02 */ u8 type; //Actor Type. See Below
/* 0x03 */ u8 room; //Room number the actor is part of. FF denotes that the actor won't despawn on a room change
/* 0x04 */ s32 flags; //flags used for drawing stuff?
// & 0x0040 0000 = Affects actor lighting
// & 0x0000 1000 = ?
// & 0x0000 0040 = ?
/* 0x08 */ Coord_f pos1; //Related to collision detection routine
/* 0x14 */ Rotation initRot; //Initial Rotation when spawned
/* 0x1A */ u16 unk_0x01A;
/* 0x1C */ u16 variable; //Configurable variable set by an actor's spawn data
/* 0x1E */ s8 objTableIndex; //index to the Object Table at Game Play + ????
/* 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_f position; //Current coordinates
/* 0x30 */ Rotation speedRot; //0x32 sets what direction the 0x68 speedXZ variable is moving the actor
/* 0x36 */ u16 unk; //same as 0x1A
/* 0x38 */ int8 unk;
/* 0x39 */ uint8 unk;
/* 0x3A */ u16 unk;
/* 0x3C */ Coord_f pos3; //Related to camera
/* 0x48 */ Rotation rot1; //0x30 rotation copied into here
/* 0x4E */ u16 unk;
/* 0x50 */ int32 unk;
/* 0x54 */ float unk; /* I know this is a float from breakpointing it */
/* 0x58 */ Coord_f scale; //sets x,y,z scaling factor. Typically, a factor of 0.01 is used for each axis
/* 0x64 */ Coord_f velocity;
/* 0x70 */ float speedXZ; //Always positive, stores how fast the actor is traveling along the XZ plane
/* 0x74 */ float gravity; //acceleration due to gravity; value is added to Y velocity every frame
/* 0x78 */ float minVelocityY; //sets the lower bounds cap on velocity along the Y axis
//struct, collision related
/* 0x7C */ int* wallPoly; //Wall polygon an actor is touching
/* 0x80 */ int* floorPoly; //Floor polygon an actor is over/touching
/* 0x84 */ u8 wallPolySource; //Complex Poly Surface Source. 0x32 = Scene
/* 0x85 */ u8 floorPolySource; //Complex Poly Surface Source. 0x32 = Scene
/* 0x86 */ u16 wallrot;
/* 0x88 */ float unk; //floor poly height?
/* 0x8C */ float water_surface_dist;
/* 0x90 */ u16 bgcheck_flags; //unknown
/* 0x92 */ s16 unk_roty; //rotation y (give item, possibly next facing dir?/face toward link?)
/* 0x94 */ float unk;
/* 0x98 */ float xzDistanceFromLink;
/* 0x9C */ float yDistanceFromLink; // relative distance
/* 8-10-2012 : Addition made by Jason777 */
/* For actors which contain a damage chart (example: Stalfos)... */
typedef struct
{
/* 0xA0 */ z2_ActorDamageTable* DamageChart; /* Pointer to the actor's Damage Chart in RAM. */
/* 0xA4 */ Coord_f displacement; //amount to correct velocity (0x5C) by when colliding into a body
/* 0xB0 */ s16 unk_0x0B0;
/* 0xB2 */ s16 unk_0x0B2;
/* 0xB4 */ u16 unk_0x0B4; //unk
/* 0xB6 */ u8 mass; // Used to compute displacement, 50 is common value, 0xFF for infinite mass/unmoveable
/* 0xB7 */ u8 health;
/* 0xB8 */ u8 damage;
/* 0xB9 */ u8 damageEffect; //Stores what effect should occur when hit by a weapon
/* 0xBA */ u8 impactEffect;
/* 0xBB */ u8 unk_0x0BB;
};
/* 0xBC */ rotation rot_2; //Setting this immediately changes actor's rotation
/* ? */ char buff3[0x66];
/* 0x115 */ u8 runActor; // Determines if actor instance should be processed. 01 for yes, 00 for no.
/* 0x128 */ struct z2_Actor* actor_prev; /* Previous z_ram_actor of this type */
/* 0x12C */ struct z2_Actor* actor_next; /* Next z_ram_actor of this type */
/* 0x130 */ void* Init; //Actor Constructor?
/* 0x134 */ void* Dest; //Actor Deconstructor?
/* 0x138 */ void* Main;
/* 0x13C */ void* Draw;
/* 0x140 */ void* CodeEntry; //Address to source overlay file's reference in code (file)
/* ? */
/* From here on, the structure and size varies for each actor */
} z2_Actor;
Categories
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).
- Within this given memory is information such as
At Game Play + 0x1CB0 is a list of actor categories (see above), each element structured as follows:
int numOfActors; ptr firstActor; int unknown;
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.
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