Massive refactor
This commit is contained in:
@@ -0,0 +1,797 @@
|
||||
#include "../include/sm64.h"
|
||||
|
||||
#include "geo_layout.h"
|
||||
#include "math_util.h"
|
||||
#include "../memory.h"
|
||||
#include "graph_node.h"
|
||||
#include "../shim.h"
|
||||
|
||||
static Vec3s gVec3sZero = { 0, 0, 0 };
|
||||
|
||||
typedef void (*GeoLayoutCommandProc)(void);
|
||||
|
||||
GeoLayoutCommandProc GeoLayoutJumpTable[] = {
|
||||
geo_layout_cmd_branch_and_link,
|
||||
geo_layout_cmd_end,
|
||||
geo_layout_cmd_branch,
|
||||
geo_layout_cmd_return,
|
||||
geo_layout_cmd_open_node,
|
||||
geo_layout_cmd_close_node,
|
||||
geo_layout_cmd_assign_as_view,
|
||||
geo_layout_cmd_update_node_flags,
|
||||
geo_layout_cmd_node_root,
|
||||
geo_layout_cmd_node_ortho_projection,
|
||||
geo_layout_cmd_node_perspective,
|
||||
geo_layout_cmd_node_start,
|
||||
geo_layout_cmd_node_master_list,
|
||||
geo_layout_cmd_node_level_of_detail,
|
||||
geo_layout_cmd_node_switch_case,
|
||||
geo_layout_cmd_node_camera,
|
||||
geo_layout_cmd_node_translation_rotation,
|
||||
geo_layout_cmd_node_translation,
|
||||
geo_layout_cmd_node_rotation,
|
||||
geo_layout_cmd_node_animated_part,
|
||||
geo_layout_cmd_node_billboard,
|
||||
geo_layout_cmd_node_display_list,
|
||||
geo_layout_cmd_node_shadow,
|
||||
geo_layout_cmd_node_object_parent,
|
||||
geo_layout_cmd_node_generated,
|
||||
geo_layout_cmd_node_background,
|
||||
geo_layout_cmd_nop,
|
||||
geo_layout_cmd_copy_view,
|
||||
geo_layout_cmd_node_held_obj,
|
||||
geo_layout_cmd_node_scale,
|
||||
geo_layout_cmd_nop2,
|
||||
geo_layout_cmd_nop3,
|
||||
geo_layout_cmd_node_culling_radius,
|
||||
};
|
||||
|
||||
struct GraphNode gObjParentGraphNode;
|
||||
struct AllocOnlyPool *gGraphNodePool;
|
||||
struct GraphNode *gCurRootGraphNode;
|
||||
|
||||
UNUSED s32 D_8038BCA8;
|
||||
|
||||
/* The gGeoViews array is a mysterious one. Some background:
|
||||
*
|
||||
* If there are e.g. multiple Goombas, the multiple Goomba objects share one
|
||||
* Geo node tree describing the goomba 3D model. Since every node has a single
|
||||
* parent field and not a parent array, the parent is dynamically rebinded to
|
||||
* each goomba instance just before rendering and set to null afterwards.
|
||||
* The same happens for ObjectParentNode, which has as his sharedChild a group
|
||||
* of all 240 object nodes. Why does the ObjectParentNode exist at all, if its
|
||||
* only purpose is to temporarily bind the actual group with objects? This might
|
||||
* be another remnant to Luigi.
|
||||
*
|
||||
* When creating a root node, room for (2 + cmd+0x02) pointers is allocated in
|
||||
* gGeoViews. Except for the title screen, cmd+0x02 is 10. The 2 default ones
|
||||
* might be for Mario and Luigi, and the other 10 could be different cameras for
|
||||
* different rooms / boss fights. An area might be structured like this:
|
||||
*
|
||||
* geo_camera mode_player //Mario cam
|
||||
* geo_open_node
|
||||
* geo_render_obj
|
||||
* geo_assign_as_view 1 // currently unused geo command
|
||||
* geo_close_node
|
||||
*
|
||||
* geo_camera mode_player //Luigi cam
|
||||
* geo_open_node
|
||||
* geo_render_obj
|
||||
* geo_copy_view 1 // currently unused geo command
|
||||
* geo_assign_as_view 2
|
||||
* geo_close_node
|
||||
*
|
||||
* geo_camera mode_boss //boss fight cam
|
||||
* geo_assign_as_view 3
|
||||
* ...
|
||||
*
|
||||
* There might also be specific geo nodes for Mario or Luigi only. Or a fixed camera
|
||||
* might not have display list nodes of parts of the level that are out of view.
|
||||
* In the end Luigi got scrapped and the multiple-camera design did not pan out,
|
||||
* so everything was reduced to a single ObjectParent with a single group, and
|
||||
* camera switching was all done in one node. End of speculation.
|
||||
*/
|
||||
struct GraphNode **gGeoViews;
|
||||
u16 gGeoNumViews; // length of gGeoViews array
|
||||
|
||||
uintptr_t gGeoLayoutStack[16];
|
||||
struct GraphNode *gCurGraphNodeList[32];
|
||||
s16 gCurGraphNodeIndex;
|
||||
s16 gGeoLayoutStackIndex; // similar to SP register in MIPS
|
||||
UNUSED s16 D_8038BD7C;
|
||||
s16 gGeoLayoutReturnIndex; // similar to RA register in MIPS
|
||||
u8 *gGeoLayoutCommand;
|
||||
|
||||
u32 unused_8038B894[3] = { 0 };
|
||||
|
||||
/*
|
||||
0x00: Branch and store return address
|
||||
cmd+0x04: void *branchTarget
|
||||
*/
|
||||
void geo_layout_cmd_branch_and_link(void) {
|
||||
gGeoLayoutStack[gGeoLayoutStackIndex++] = (uintptr_t) (gGeoLayoutCommand + CMD_PROCESS_OFFSET(8));
|
||||
gGeoLayoutStack[gGeoLayoutStackIndex++] = (gCurGraphNodeIndex << 16) + gGeoLayoutReturnIndex;
|
||||
gGeoLayoutReturnIndex = gGeoLayoutStackIndex;
|
||||
gGeoLayoutCommand = segmented_to_virtual(cur_geo_cmd_ptr(0x04));
|
||||
}
|
||||
|
||||
// 0x01: Terminate geo layout
|
||||
void geo_layout_cmd_end(void) {
|
||||
gGeoLayoutStackIndex = gGeoLayoutReturnIndex;
|
||||
gGeoLayoutReturnIndex = gGeoLayoutStack[--gGeoLayoutStackIndex] & 0xFFFF;
|
||||
gCurGraphNodeIndex = gGeoLayoutStack[gGeoLayoutStackIndex] >> 16;
|
||||
gGeoLayoutCommand = (u8 *) gGeoLayoutStack[--gGeoLayoutStackIndex];
|
||||
}
|
||||
|
||||
/*
|
||||
0x02: Branch
|
||||
cmd+0x04: void *branchTarget
|
||||
*/
|
||||
void geo_layout_cmd_branch(void) {
|
||||
if (cur_geo_cmd_u8(0x01) == 1) {
|
||||
gGeoLayoutStack[gGeoLayoutStackIndex++] = (uintptr_t) (gGeoLayoutCommand + CMD_PROCESS_OFFSET(8));
|
||||
}
|
||||
|
||||
gGeoLayoutCommand = segmented_to_virtual(cur_geo_cmd_ptr(0x04));
|
||||
}
|
||||
|
||||
// 0x03: Return from branch
|
||||
void geo_layout_cmd_return(void) {
|
||||
gGeoLayoutCommand = (u8 *) gGeoLayoutStack[--gGeoLayoutStackIndex];
|
||||
}
|
||||
|
||||
// 0x04: Open node
|
||||
void geo_layout_cmd_open_node(void) {
|
||||
gCurGraphNodeList[gCurGraphNodeIndex + 1] = gCurGraphNodeList[gCurGraphNodeIndex];
|
||||
gCurGraphNodeIndex++;
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
// 0x05: Close node
|
||||
void geo_layout_cmd_close_node(void) {
|
||||
gCurGraphNodeIndex--;
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x06: Register the current node as a view
|
||||
cmd+0x02: index
|
||||
|
||||
Register the current node in the gGeoViews array at the given index
|
||||
*/
|
||||
void geo_layout_cmd_assign_as_view(void) {
|
||||
u16 index = cur_geo_cmd_s16(0x02);
|
||||
|
||||
if (index < gGeoNumViews) {
|
||||
gGeoViews[index] = gCurGraphNodeList[gCurGraphNodeIndex];
|
||||
}
|
||||
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x07: Update current scene graph node flags
|
||||
cmd+0x01: u8 operation (0 = reset, 1 = set, 2 = clear)
|
||||
cmd+0x02: s16 bits
|
||||
*/
|
||||
void geo_layout_cmd_update_node_flags(void) {
|
||||
u16 operation = cur_geo_cmd_u8(0x01);
|
||||
u16 flagBits = cur_geo_cmd_s16(0x02);
|
||||
|
||||
switch (operation) {
|
||||
case GEO_CMD_FLAGS_RESET:
|
||||
gCurGraphNodeList[gCurGraphNodeIndex]->flags = flagBits;
|
||||
break;
|
||||
case GEO_CMD_FLAGS_SET:
|
||||
gCurGraphNodeList[gCurGraphNodeIndex]->flags |= flagBits;
|
||||
break;
|
||||
case GEO_CMD_FLAGS_CLEAR:
|
||||
gCurGraphNodeList[gCurGraphNodeIndex]->flags &= ~flagBits;
|
||||
break;
|
||||
}
|
||||
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x08: Create a scene graph root node that specifies the viewport
|
||||
cmd+0x02: s16 num entries (+2) to allocate for gGeoViews
|
||||
cmd+0x04: s16 x
|
||||
cmd+0x06: s16 y
|
||||
cmd+0x08: s16 width
|
||||
cmd+0x0A: s16 height
|
||||
*/
|
||||
void geo_layout_cmd_node_root(void) {
|
||||
s32 i;
|
||||
struct GraphNodeRoot *graphNode;
|
||||
|
||||
s16 x = cur_geo_cmd_s16(0x04);
|
||||
s16 y = cur_geo_cmd_s16(0x06);
|
||||
s16 width = cur_geo_cmd_s16(0x08);
|
||||
s16 height = cur_geo_cmd_s16(0x0A);
|
||||
|
||||
// number of entries to allocate for gGeoViews array
|
||||
// at least 2 are allocated by default
|
||||
// cmd+0x02 = 0x00: Mario face, 0x0A: all other levels
|
||||
gGeoNumViews = cur_geo_cmd_s16(0x02) + 2;
|
||||
|
||||
graphNode = init_graph_node_root(gGraphNodePool, NULL, 0, x, y, width, height);
|
||||
|
||||
// TODO: check type
|
||||
gGeoViews = alloc_only_pool_alloc(gGraphNodePool, gGeoNumViews * sizeof(struct GraphNode *));
|
||||
|
||||
graphNode->views = gGeoViews;
|
||||
graphNode->numViews = gGeoNumViews;
|
||||
|
||||
for (i = 0; i < gGeoNumViews; i++) {
|
||||
gGeoViews[i] = NULL;
|
||||
}
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x0C << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x09: Create orthographic projection scene graph node
|
||||
cmd+0x02: s16 scale as a percentage (usually it's 100)
|
||||
*/
|
||||
void geo_layout_cmd_node_ortho_projection(void) {
|
||||
struct GraphNodeOrthoProjection *graphNode;
|
||||
f32 scale = (f32) cur_geo_cmd_s16(0x02) / 100.0f;
|
||||
|
||||
graphNode = init_graph_node_ortho_projection(gGraphNodePool, NULL, scale);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x0A: Create camera frustum scene graph node
|
||||
cmd+0x01: u8 if nonzero, enable frustumFunc field
|
||||
cmd+0x02: s16 field of view
|
||||
cmd+0x04: s16 near
|
||||
cmd+0x06: s16 far
|
||||
[cmd+0x08: GraphNodeFunc frustumFunc]
|
||||
*/
|
||||
void geo_layout_cmd_node_perspective(void) {
|
||||
struct GraphNodePerspective *graphNode;
|
||||
GraphNodeFunc frustumFunc = NULL;
|
||||
s16 fov = cur_geo_cmd_s16(0x02);
|
||||
s16 near = cur_geo_cmd_s16(0x04);
|
||||
s16 far = cur_geo_cmd_s16(0x06);
|
||||
|
||||
if (cur_geo_cmd_u8(0x01) != 0) {
|
||||
// optional asm function
|
||||
frustumFunc = (GraphNodeFunc) cur_geo_cmd_ptr(0x08);
|
||||
gGeoLayoutCommand += 4 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
graphNode = init_graph_node_perspective(gGraphNodePool, NULL, (f32) fov, near, far, frustumFunc, 0);
|
||||
|
||||
register_scene_graph_node(&graphNode->fnNode.node);
|
||||
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x0B: Create a scene graph node that groups other nodes without any
|
||||
additional functionality
|
||||
*/
|
||||
void geo_layout_cmd_node_start(void) {
|
||||
struct GraphNodeStart *graphNode;
|
||||
|
||||
graphNode = init_graph_node_start(gGraphNodePool, NULL);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
// 0x1F: No operation
|
||||
void geo_layout_cmd_nop3(void) {
|
||||
gGeoLayoutCommand += 0x10 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x0C: Create zbuffer-toggling scene graph node
|
||||
cmd+0x01: u8 enableZBuffer (1 = on, 0 = off)
|
||||
*/
|
||||
void geo_layout_cmd_node_master_list(void) {
|
||||
struct GraphNodeMasterList *graphNode;
|
||||
|
||||
graphNode = init_graph_node_master_list(gGraphNodePool, NULL, cur_geo_cmd_u8(0x01));
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x0D: Create a level of detail graph node, which only renders at a certain
|
||||
distance interval from the camera.
|
||||
cmd+0x04: s16 minDistance
|
||||
cmd+0x06: s16 maxDistance
|
||||
*/
|
||||
void geo_layout_cmd_node_level_of_detail(void) {
|
||||
struct GraphNodeLevelOfDetail *graphNode;
|
||||
s16 minDistance = cur_geo_cmd_s16(0x04);
|
||||
s16 maxDistance = cur_geo_cmd_s16(0x06);
|
||||
|
||||
graphNode = init_graph_node_render_range(gGraphNodePool, NULL, minDistance, maxDistance);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x0E: Create switch-case scene graph node
|
||||
cmd+0x02: s16 initialSelectedCase
|
||||
cmd+0x04: GraphNodeFunc caseSelectorFunc
|
||||
|
||||
caseSelectorFunc returns an index which is used to select the child node to render.
|
||||
Used for animating coins, blinking, color selection, etc.
|
||||
*/
|
||||
void geo_layout_cmd_node_switch_case(void) {
|
||||
struct GraphNodeSwitchCase *graphNode;
|
||||
|
||||
graphNode =
|
||||
init_graph_node_switch_case(gGraphNodePool, NULL,
|
||||
cur_geo_cmd_s16(0x02), // case which is initially selected
|
||||
0,
|
||||
(GraphNodeFunc) cur_geo_cmd_ptr(0x04), // case update function
|
||||
0);
|
||||
|
||||
register_scene_graph_node(&graphNode->fnNode.node);
|
||||
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x0F: Create a camera scene graph node (GraphNodeCamera). The focus sets the Camera's areaCen position.
|
||||
cmd+0x02: s16 camera type (changes from course to course)
|
||||
cmd+0x04: s16 posX
|
||||
cmd+0x06: s16 posY
|
||||
cmd+0x08: s16 posZ
|
||||
cmd+0x0A: s16 focusX
|
||||
cmd+0x0C: s16 focusY
|
||||
cmd+0x0E: s16 focusZ
|
||||
cmd+0x10: GraphNodeFunc func
|
||||
*/
|
||||
void geo_layout_cmd_node_camera(void) {
|
||||
struct GraphNodeCamera *graphNode;
|
||||
s16 *cmdPos = (s16 *) &gGeoLayoutCommand[4];
|
||||
|
||||
Vec3f pos, focus;
|
||||
|
||||
cmdPos = read_vec3s_to_vec3f(pos, cmdPos);
|
||||
cmdPos = read_vec3s_to_vec3f(focus, cmdPos);
|
||||
|
||||
graphNode = init_graph_node_camera(gGraphNodePool, NULL, pos, focus,
|
||||
(GraphNodeFunc) cur_geo_cmd_ptr(0x10), cur_geo_cmd_s16(0x02));
|
||||
|
||||
register_scene_graph_node(&graphNode->fnNode.node);
|
||||
|
||||
gGeoViews[0] = &graphNode->fnNode.node;
|
||||
|
||||
gGeoLayoutCommand += 0x14 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x10: Create translation & rotation scene graph node with optional display list
|
||||
cmd+0x01: u8 params
|
||||
(params & 0x80): if set, enable displayList field and drawingLayer
|
||||
((params & 0x70)>>4): fieldLayout
|
||||
(params & 0x0F): drawingLayer
|
||||
|
||||
fieldLayout == 0:
|
||||
cmd+0x04: s16 xTranslation
|
||||
cmd+0x06: s16 yTranslation
|
||||
cmd+0x08: s16 zTranslation
|
||||
cmd+0x0A: s16 xRotation
|
||||
cmd+0x0C: s16 yRotation
|
||||
cmd+0x0E: s16 zRotation
|
||||
|
||||
fieldLayout == 1:
|
||||
cmd+0x02: s16 xTranslation
|
||||
cmd+0x04: s16 yTranslation
|
||||
cmd+0x06: s16 zTranslation
|
||||
(rotation gets copied from gVec3sZero)
|
||||
|
||||
fieldLayout == 2:
|
||||
cmd+0x02: s16 xRotation
|
||||
cmd+0x04: s16 yRotation
|
||||
cmd+0x06: s16 zRotation
|
||||
(translation gets copied from gVec3sZero)
|
||||
|
||||
fieldLayout == 3:
|
||||
cmd+0x02: s16 yRotation
|
||||
(translation gets copied from gVec3sZero)
|
||||
(x and z translation are set to 0)
|
||||
|
||||
[cmd+var: void *displayList]
|
||||
*/
|
||||
void geo_layout_cmd_node_translation_rotation(void) {
|
||||
struct GraphNodeTranslationRotation *graphNode;
|
||||
|
||||
Vec3s translation, rotation;
|
||||
|
||||
void *displayList = NULL;
|
||||
s16 drawingLayer = 0;
|
||||
|
||||
s16 params = cur_geo_cmd_u8(0x01);
|
||||
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
|
||||
|
||||
switch ((params & 0x70) >> 4) {
|
||||
case 0:
|
||||
cmdPos = read_vec3s(translation, &cmdPos[2]);
|
||||
cmdPos = read_vec3s_angle(rotation, cmdPos);
|
||||
break;
|
||||
case 1:
|
||||
cmdPos = read_vec3s(translation, &cmdPos[1]);
|
||||
vec3s_copy(rotation, gVec3sZero);
|
||||
break;
|
||||
case 2:
|
||||
cmdPos = read_vec3s_angle(rotation, &cmdPos[1]);
|
||||
vec3s_copy(translation, gVec3sZero);
|
||||
break;
|
||||
case 3:
|
||||
vec3s_copy(translation, gVec3sZero);
|
||||
vec3s_set(rotation, 0, (cmdPos[1] << 15) / 180, 0);
|
||||
cmdPos += 2 << CMD_SIZE_SHIFT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (params & 0x80) {
|
||||
displayList = *(void **) &cmdPos[0];
|
||||
drawingLayer = params & 0x0F;
|
||||
cmdPos += 2 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
graphNode = init_graph_node_translation_rotation(gGraphNodePool, NULL, drawingLayer, displayList,
|
||||
translation, rotation);
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand = (u8 *) cmdPos;
|
||||
}
|
||||
|
||||
/*
|
||||
0x11: Create translation scene graph node with optional display list
|
||||
cmd+0x01: u8 params
|
||||
(params & 0x80): if set, enable displayList field and drawingLayer
|
||||
(params & 0x0F): drawingLayer
|
||||
cmd+0x02: s16 xTranslation
|
||||
cmd+0x04: s16 yTranslation
|
||||
cmd+0x06: s16 zTranslation
|
||||
[cmd+0x08: void *displayList]
|
||||
*/
|
||||
void geo_layout_cmd_node_translation(void) {
|
||||
struct GraphNodeTranslation *graphNode;
|
||||
|
||||
Vec3s translation;
|
||||
|
||||
s16 drawingLayer = 0;
|
||||
s16 params = cur_geo_cmd_u8(0x01);
|
||||
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
|
||||
void *displayList = NULL;
|
||||
|
||||
cmdPos = read_vec3s(translation, &cmdPos[1]);
|
||||
|
||||
if (params & 0x80) {
|
||||
displayList = *(void **) &cmdPos[0];
|
||||
drawingLayer = params & 0x0F;
|
||||
cmdPos += 2 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
graphNode =
|
||||
init_graph_node_translation(gGraphNodePool, NULL, drawingLayer, displayList, translation);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand = (u8 *) cmdPos;
|
||||
}
|
||||
|
||||
/*
|
||||
0x12: Create ? scene graph node
|
||||
cmd+0x01: u8 params
|
||||
(params & 0x80): if set, enable displayList field and drawingLayer
|
||||
(params & 0x0F): drawingLayer
|
||||
cmd+0x02: s16 unkX
|
||||
cmd+0x04: s16 unkY
|
||||
cmd+0x06: s16 unkZ
|
||||
[cmd+0x08: void *displayList]
|
||||
*/
|
||||
void geo_layout_cmd_node_rotation(void) {
|
||||
struct GraphNodeRotation *graphNode;
|
||||
|
||||
Vec3s sp2c;
|
||||
|
||||
s16 drawingLayer = 0;
|
||||
s16 params = cur_geo_cmd_u8(0x01);
|
||||
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
|
||||
void *displayList = NULL;
|
||||
|
||||
cmdPos = read_vec3s_angle(sp2c, &cmdPos[1]);
|
||||
|
||||
if (params & 0x80) {
|
||||
displayList = *(void **) &cmdPos[0];
|
||||
drawingLayer = params & 0x0F;
|
||||
cmdPos += 2 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
graphNode = init_graph_node_rotation(gGraphNodePool, NULL, drawingLayer, displayList, sp2c);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand = (u8 *) cmdPos;
|
||||
}
|
||||
|
||||
/*
|
||||
0x1D: Create scale scene graph node with optional display list
|
||||
cmd+0x01: u8 params
|
||||
(params & 0x80): if set, enable displayList field and drawingLayer
|
||||
(params & 0x0F): drawingLayer
|
||||
cmd+0x04: u32 scale (0x10000 = 1.0)
|
||||
[cmd+0x08: void *displayList]
|
||||
*/
|
||||
void geo_layout_cmd_node_scale(void) {
|
||||
struct GraphNodeScale *graphNode;
|
||||
|
||||
s16 drawingLayer = 0;
|
||||
s16 params = cur_geo_cmd_u8(0x01);
|
||||
f32 scale = cur_geo_cmd_u32(0x04) / 65536.0f;
|
||||
void *displayList = NULL;
|
||||
|
||||
if (params & 0x80) {
|
||||
displayList = cur_geo_cmd_ptr(0x08);
|
||||
drawingLayer = params & 0x0F;
|
||||
gGeoLayoutCommand += 4 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
graphNode = init_graph_node_scale(gGraphNodePool, NULL, drawingLayer, displayList, scale);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
// 0x1E: No operation
|
||||
void geo_layout_cmd_nop2(void) {
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x13: Create a scene graph node that is rotated by the object's animation.
|
||||
cmd+0x01: u8 drawingLayer
|
||||
cmd+0x02: s16 xTranslation
|
||||
cmd+0x04: s16 yTranslation
|
||||
cmd+0x06: s16 zTranslation
|
||||
cmd+0x08: void *displayList
|
||||
*/
|
||||
void geo_layout_cmd_node_animated_part(void) {
|
||||
struct GraphNodeAnimatedPart *graphNode;
|
||||
Vec3s translation;
|
||||
s32 drawingLayer = cur_geo_cmd_u8(0x01);
|
||||
void *displayList = cur_geo_cmd_ptr(0x08);
|
||||
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
|
||||
|
||||
read_vec3s(translation, &cmdPos[1]);
|
||||
|
||||
graphNode =
|
||||
init_graph_node_animated_part(gGraphNodePool, NULL, drawingLayer, displayList, translation);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x0C << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x14: Create billboarding node with optional display list
|
||||
cmd+0x01: u8 params
|
||||
(params & 0x80): if set, enable displayList field and drawingLayer
|
||||
(params & 0x0F): drawingLayer
|
||||
cmd+0x02: s16 xTranslation
|
||||
cmd+0x04: s16 yTranslation
|
||||
cmd+0x06: s16 zTranslation
|
||||
[cmd+0x08: void *displayList]
|
||||
*/
|
||||
void geo_layout_cmd_node_billboard(void) {
|
||||
struct GraphNodeBillboard *graphNode;
|
||||
Vec3s translation;
|
||||
s16 drawingLayer = 0;
|
||||
s16 params = cur_geo_cmd_u8(0x01);
|
||||
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
|
||||
void *displayList = NULL;
|
||||
|
||||
cmdPos = read_vec3s(translation, &cmdPos[1]);
|
||||
|
||||
if (params & 0x80) {
|
||||
displayList = *(void **) &cmdPos[0];
|
||||
drawingLayer = params & 0x0F;
|
||||
cmdPos += 2 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
graphNode = init_graph_node_billboard(gGraphNodePool, NULL, drawingLayer, displayList, translation);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand = (u8 *) cmdPos;
|
||||
}
|
||||
|
||||
/*
|
||||
0x15: Create plain display list scene graph node
|
||||
cmd+0x01: u8 drawingLayer
|
||||
cmd+0x04: void *displayList
|
||||
*/
|
||||
void geo_layout_cmd_node_display_list(void) {
|
||||
struct GraphNodeDisplayList *graphNode;
|
||||
s32 drawingLayer = cur_geo_cmd_u8(0x01);
|
||||
void *displayList = cur_geo_cmd_ptr(0x04);
|
||||
|
||||
graphNode = init_graph_node_display_list(gGraphNodePool, NULL, drawingLayer, displayList);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x16: Create shadow scene graph node
|
||||
cmd+0x02: s16 shadowType
|
||||
cmd+0x04: s16 shadowSolidity
|
||||
cmd+0x06: s16 shadowScale
|
||||
*/
|
||||
void geo_layout_cmd_node_shadow(void) {
|
||||
struct GraphNodeShadow *graphNode;
|
||||
u8 shadowType = cur_geo_cmd_s16(0x02);
|
||||
u8 shadowSolidity = cur_geo_cmd_s16(0x04);
|
||||
s16 shadowScale = cur_geo_cmd_s16(0x06);
|
||||
|
||||
graphNode = init_graph_node_shadow(gGraphNodePool, NULL, shadowScale, shadowSolidity, shadowType);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
// 0x17: Create scene graph node that manages the group of all object nodes
|
||||
void geo_layout_cmd_node_object_parent(void) {
|
||||
struct GraphNodeObjectParent *graphNode;
|
||||
|
||||
graphNode = init_graph_node_object_parent(gGraphNodePool, NULL, &gObjParentGraphNode);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x18: Create dynamically generated displaylist scene graph node
|
||||
cmd+0x02: s16 parameter
|
||||
cmd+0x04: GraphNodeFunc func
|
||||
*/
|
||||
void geo_layout_cmd_node_generated(void) {
|
||||
struct GraphNodeGenerated *graphNode;
|
||||
|
||||
graphNode = init_graph_node_generated(gGraphNodePool, NULL,
|
||||
(GraphNodeFunc) cur_geo_cmd_ptr(0x04), // asm function
|
||||
cur_geo_cmd_s16(0x02)); // parameter
|
||||
|
||||
register_scene_graph_node(&graphNode->fnNode.node);
|
||||
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x19: Create background scene graph node
|
||||
cmd+0x02: s16 background // background ID, or RGBA5551 color if backgroundFunc is null
|
||||
cmd+0x04: GraphNodeFunc backgroundFunc
|
||||
*/
|
||||
void geo_layout_cmd_node_background(void) {
|
||||
struct GraphNodeBackground *graphNode;
|
||||
|
||||
graphNode = init_graph_node_background(
|
||||
gGraphNodePool, NULL,
|
||||
cur_geo_cmd_s16(0x02), // background ID, or RGBA5551 color if asm function is null
|
||||
(GraphNodeFunc) cur_geo_cmd_ptr(0x04), // asm function
|
||||
0);
|
||||
|
||||
register_scene_graph_node(&graphNode->fnNode.node);
|
||||
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
// 0x1A: No operation
|
||||
void geo_layout_cmd_nop(void) {
|
||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x1B: Copy the shared children from the object parent from a specific view
|
||||
to a newly created object parent node.
|
||||
cmd+0x02: s16 index (of gGeoViews)
|
||||
*/
|
||||
void geo_layout_cmd_copy_view(void) {
|
||||
struct GraphNodeObjectParent *graphNode;
|
||||
struct GraphNode *node = NULL;
|
||||
s16 index = cur_geo_cmd_s16(0x02);
|
||||
|
||||
if (index >= 0) {
|
||||
node = gGeoViews[index];
|
||||
|
||||
if (node->type == GRAPH_NODE_TYPE_OBJECT_PARENT) {
|
||||
node = ((struct GraphNodeObjectParent *) node)->sharedChild;
|
||||
} else {
|
||||
node = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
graphNode = init_graph_node_object_parent(gGraphNodePool, NULL, node);
|
||||
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x1C: Create a held object scene graph node
|
||||
cmd+0x01: u8 unused
|
||||
cmd+0x02: s16 offsetX
|
||||
cmd+0x04: s16 offsetY
|
||||
cmd+0x06: s16 offsetZ
|
||||
cmd+0x08: GraphNodeFunc nodeFunc
|
||||
*/
|
||||
void geo_layout_cmd_node_held_obj(void) {
|
||||
struct GraphNodeHeldObject *graphNode;
|
||||
Vec3s offset;
|
||||
|
||||
read_vec3s(offset, (s16 *) &gGeoLayoutCommand[0x02]);
|
||||
|
||||
graphNode = init_graph_node_held_object(
|
||||
gGraphNodePool, NULL, NULL, offset, (GraphNodeFunc) cur_geo_cmd_ptr(0x08), cur_geo_cmd_u8(0x01));
|
||||
|
||||
register_scene_graph_node(&graphNode->fnNode.node);
|
||||
|
||||
gGeoLayoutCommand += 0x0C << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
0x20: Create a scene graph node that specifies for an object the radius that
|
||||
is used for frustum culling.
|
||||
cmd+0x02: s16 cullingRadius
|
||||
*/
|
||||
void geo_layout_cmd_node_culling_radius(void) {
|
||||
struct GraphNodeCullingRadius *graphNode;
|
||||
graphNode = init_graph_node_culling_radius(gGraphNodePool, NULL, cur_geo_cmd_s16(0x02));
|
||||
register_scene_graph_node(&graphNode->node);
|
||||
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
struct GraphNode *process_geo_layout(struct AllocOnlyPool *pool, void *segptr) {
|
||||
// set by register_scene_graph_node when gCurGraphNodeIndex is 0
|
||||
// and gCurRootGraphNode is NULL
|
||||
gCurRootGraphNode = NULL;
|
||||
|
||||
gGeoNumViews = 0; // number of entries in gGeoViews
|
||||
|
||||
gCurGraphNodeList[0] = 0;
|
||||
gCurGraphNodeIndex = 0; // incremented by cmd_open_node, decremented by cmd_close_node
|
||||
|
||||
gGeoLayoutStackIndex = 2;
|
||||
gGeoLayoutReturnIndex = 2; // stack index is often copied here?
|
||||
|
||||
gGeoLayoutCommand = segmented_to_virtual(segptr);
|
||||
|
||||
gGraphNodePool = pool;
|
||||
|
||||
gGeoLayoutStack[0] = 0;
|
||||
gGeoLayoutStack[1] = 0;
|
||||
|
||||
while (gGeoLayoutCommand != NULL) {
|
||||
GeoLayoutJumpTable[gGeoLayoutCommand[0x00]]();
|
||||
}
|
||||
|
||||
return gCurRootGraphNode;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
#ifndef GEO_LAYOUT_H
|
||||
#define GEO_LAYOUT_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../memory.h"
|
||||
#include "../include/macros.h"
|
||||
#include "../include/types.h"
|
||||
|
||||
#define GEO_CMD_FLAGS_RESET 0
|
||||
#define GEO_CMD_FLAGS_SET 1
|
||||
#define GEO_CMD_FLAGS_CLEAR 2
|
||||
|
||||
#define CMD_SIZE_SHIFT (sizeof(void *) >> 3)
|
||||
#define CMD_PROCESS_OFFSET(offset) (((offset) & 3) | (((offset) & ~3) << CMD_SIZE_SHIFT))
|
||||
|
||||
#define cur_geo_cmd_u8(offset) \
|
||||
(gGeoLayoutCommand[CMD_PROCESS_OFFSET(offset)])
|
||||
|
||||
#define cur_geo_cmd_s16(offset) \
|
||||
(*(s16 *) &gGeoLayoutCommand[CMD_PROCESS_OFFSET(offset)])
|
||||
|
||||
#define cur_geo_cmd_s32(offset) \
|
||||
(*(s32 *) &gGeoLayoutCommand[CMD_PROCESS_OFFSET(offset)])
|
||||
|
||||
#define cur_geo_cmd_u32(offset) \
|
||||
(*(u32 *) &gGeoLayoutCommand[CMD_PROCESS_OFFSET(offset)])
|
||||
|
||||
#define cur_geo_cmd_ptr(offset) \
|
||||
(*(void **) &gGeoLayoutCommand[CMD_PROCESS_OFFSET(offset)])
|
||||
|
||||
extern struct AllocOnlyPool *gGraphNodePool;
|
||||
extern struct GraphNode *gCurRootGraphNode;
|
||||
extern UNUSED s32 D_8038BCA8;
|
||||
extern struct GraphNode **gGeoViews;
|
||||
extern u16 gGeoNumViews;
|
||||
extern uintptr_t gGeoLayoutStack[];
|
||||
extern struct GraphNode *gCurGraphNodeList[];
|
||||
extern s16 gCurGraphNodeIndex;
|
||||
extern s16 gGeoLayoutStackIndex;
|
||||
extern UNUSED s16 D_8038BD7C;
|
||||
extern s16 gGeoLayoutReturnIndex;
|
||||
extern u8 *gGeoLayoutCommand;
|
||||
extern struct GraphNode gObjParentGraphNode;
|
||||
|
||||
extern struct AllocOnlyPool *D_8038BCA0;
|
||||
extern struct GraphNode *D_8038BCA4;
|
||||
extern s16 D_8038BD78;
|
||||
extern struct GraphNode *D_8038BCF8[];
|
||||
|
||||
void geo_layout_cmd_branch_and_link(void);
|
||||
void geo_layout_cmd_end(void);
|
||||
void geo_layout_cmd_branch(void);
|
||||
void geo_layout_cmd_return(void);
|
||||
void geo_layout_cmd_open_node(void);
|
||||
void geo_layout_cmd_close_node(void);
|
||||
void geo_layout_cmd_assign_as_view(void);
|
||||
void geo_layout_cmd_update_node_flags(void);
|
||||
void geo_layout_cmd_node_root(void);
|
||||
void geo_layout_cmd_node_ortho_projection(void);
|
||||
void geo_layout_cmd_node_perspective(void);
|
||||
void geo_layout_cmd_node_start(void);
|
||||
void geo_layout_cmd_nop3(void);
|
||||
void geo_layout_cmd_node_master_list(void);
|
||||
void geo_layout_cmd_node_level_of_detail(void);
|
||||
void geo_layout_cmd_node_switch_case(void);
|
||||
void geo_layout_cmd_node_camera(void);
|
||||
void geo_layout_cmd_node_translation_rotation(void);
|
||||
void geo_layout_cmd_node_translation(void);
|
||||
void geo_layout_cmd_node_rotation(void);
|
||||
void geo_layout_cmd_node_scale(void);
|
||||
void geo_layout_cmd_nop2(void);
|
||||
void geo_layout_cmd_node_animated_part(void);
|
||||
void geo_layout_cmd_node_billboard(void);
|
||||
void geo_layout_cmd_node_display_list(void);
|
||||
void geo_layout_cmd_node_shadow(void);
|
||||
void geo_layout_cmd_node_object_parent(void);
|
||||
void geo_layout_cmd_node_generated(void);
|
||||
void geo_layout_cmd_node_background(void);
|
||||
void geo_layout_cmd_nop(void);
|
||||
void geo_layout_cmd_copy_view(void);
|
||||
void geo_layout_cmd_node_held_obj(void);
|
||||
void geo_layout_cmd_node_culling_radius(void);
|
||||
|
||||
struct GraphNode *process_geo_layout(struct AllocOnlyPool *a0, void *segptr);
|
||||
|
||||
#endif // GEO_LAYOUT_H
|
||||
@@ -0,0 +1,894 @@
|
||||
#include "../include/sm64.h"
|
||||
|
||||
#include "../game/level_update.h"
|
||||
#include "math_util.h"
|
||||
//#include "game/memory.h"
|
||||
#include "graph_node.h"
|
||||
#include "../game/rendering_graph_node.h"
|
||||
#include "../game/area.h"
|
||||
#include "geo_layout.h"
|
||||
#include "../shim.h"
|
||||
|
||||
// unused Mtx(s)
|
||||
static Vec3f gVec3fZero = { 0.0f, 0.0f, 0.0f };
|
||||
static Vec3s gVec3sZero = { 0, 0, 0 };
|
||||
static Vec3f gVec3fOne = { 1.0f, 1.0f, 1.0f };
|
||||
|
||||
/**
|
||||
* Initialize a geo node with a given type. Sets all links such that there
|
||||
* are no siblings, parent or children for this node.
|
||||
*/
|
||||
void init_scene_graph_node_links(struct GraphNode *graphNode, s32 type) {
|
||||
graphNode->type = type;
|
||||
graphNode->flags = GRAPH_RENDER_ACTIVE;
|
||||
graphNode->prev = graphNode;
|
||||
graphNode->next = graphNode;
|
||||
graphNode->parent = NULL;
|
||||
graphNode->children = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocated and returns a newly created root node
|
||||
*/
|
||||
struct GraphNodeRoot *init_graph_node_root(struct AllocOnlyPool *pool, struct GraphNodeRoot *graphNode,
|
||||
s16 areaIndex, s16 x, s16 y, s16 width, s16 height) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeRoot));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_ROOT);
|
||||
|
||||
graphNode->areaIndex = areaIndex;
|
||||
graphNode->unk15 = 0;
|
||||
graphNode->x = x;
|
||||
graphNode->y = y;
|
||||
graphNode->width = width;
|
||||
graphNode->height = height;
|
||||
graphNode->views = NULL;
|
||||
graphNode->numViews = 0;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created otrhographic projection node
|
||||
*/
|
||||
struct GraphNodeOrthoProjection *
|
||||
init_graph_node_ortho_projection(struct AllocOnlyPool *pool, struct GraphNodeOrthoProjection *graphNode,
|
||||
f32 scale) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeOrthoProjection));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_ORTHO_PROJECTION);
|
||||
graphNode->scale = scale;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created perspective node
|
||||
*/
|
||||
struct GraphNodePerspective *init_graph_node_perspective(struct AllocOnlyPool *pool,
|
||||
struct GraphNodePerspective *graphNode,
|
||||
f32 fov, s16 near, s16 far,
|
||||
GraphNodeFunc nodeFunc, s32 unused) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodePerspective));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->fnNode.node, GRAPH_NODE_TYPE_PERSPECTIVE);
|
||||
|
||||
graphNode->fov = fov;
|
||||
graphNode->near = near;
|
||||
graphNode->far = far;
|
||||
graphNode->fnNode.func = nodeFunc;
|
||||
graphNode->unused = unused;
|
||||
|
||||
if (nodeFunc != NULL) {
|
||||
nodeFunc(GEO_CONTEXT_CREATE, &graphNode->fnNode.node, pool);
|
||||
}
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created start node
|
||||
*/
|
||||
struct GraphNodeStart *init_graph_node_start(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeStart *graphNode) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeStart));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_START);
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created master list node
|
||||
*/
|
||||
struct GraphNodeMasterList *init_graph_node_master_list(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeMasterList *graphNode, s16 on) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeMasterList));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_MASTER_LIST);
|
||||
|
||||
if (on) {
|
||||
graphNode->node.flags |= GRAPH_RENDER_Z_BUFFER;
|
||||
}
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created render range node
|
||||
*/
|
||||
struct GraphNodeLevelOfDetail *init_graph_node_render_range(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeLevelOfDetail *graphNode,
|
||||
s16 minDistance, s16 maxDistance) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeLevelOfDetail));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_LEVEL_OF_DETAIL);
|
||||
graphNode->minDistance = minDistance;
|
||||
graphNode->maxDistance = maxDistance;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created switch case node
|
||||
*/
|
||||
struct GraphNodeSwitchCase *init_graph_node_switch_case(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeSwitchCase *graphNode,
|
||||
s16 numCases, s16 selectedCase,
|
||||
GraphNodeFunc nodeFunc, s32 unused) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeSwitchCase));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->fnNode.node, GRAPH_NODE_TYPE_SWITCH_CASE);
|
||||
graphNode->numCases = numCases;
|
||||
graphNode->selectedCase = selectedCase;
|
||||
graphNode->fnNode.func = nodeFunc;
|
||||
graphNode->unused = unused;
|
||||
|
||||
if (nodeFunc != NULL) {
|
||||
nodeFunc(GEO_CONTEXT_CREATE, &graphNode->fnNode.node, pool);
|
||||
}
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created camera node
|
||||
*/
|
||||
struct GraphNodeCamera *init_graph_node_camera(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeCamera *graphNode, f32 *pos,
|
||||
f32 *focus, GraphNodeFunc func, s32 mode) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeCamera));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->fnNode.node, GRAPH_NODE_TYPE_CAMERA);
|
||||
vec3f_copy(graphNode->pos, pos);
|
||||
vec3f_copy(graphNode->focus, focus);
|
||||
graphNode->fnNode.func = func;
|
||||
graphNode->config.mode = mode;
|
||||
graphNode->roll = 0;
|
||||
graphNode->rollScreen = 0;
|
||||
|
||||
if (func != NULL) {
|
||||
func(GEO_CONTEXT_CREATE, &graphNode->fnNode.node, pool);
|
||||
}
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created translation rotation node
|
||||
*/
|
||||
struct GraphNodeTranslationRotation *
|
||||
init_graph_node_translation_rotation(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeTranslationRotation *graphNode, s32 drawingLayer,
|
||||
void *displayList, Vec3s translation, Vec3s rotation) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeTranslationRotation));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_TRANSLATION_ROTATION);
|
||||
|
||||
vec3s_copy(graphNode->translation, translation);
|
||||
vec3s_copy(graphNode->rotation, rotation);
|
||||
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
||||
graphNode->displayList = displayList;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created translation node
|
||||
*/
|
||||
struct GraphNodeTranslation *init_graph_node_translation(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeTranslation *graphNode,
|
||||
s32 drawingLayer, void *displayList,
|
||||
Vec3s translation) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeTranslation));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_TRANSLATION);
|
||||
|
||||
vec3s_copy(graphNode->translation, translation);
|
||||
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
||||
graphNode->displayList = displayList;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created rotation node
|
||||
*/
|
||||
struct GraphNodeRotation *init_graph_node_rotation(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeRotation *graphNode,
|
||||
s32 drawingLayer, void *displayList,
|
||||
Vec3s rotation) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeRotation));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_ROTATION);
|
||||
vec3s_copy(graphNode->rotation, rotation);
|
||||
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
||||
graphNode->displayList = displayList;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created scaling node
|
||||
*/
|
||||
struct GraphNodeScale *init_graph_node_scale(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeScale *graphNode, s32 drawingLayer,
|
||||
void *displayList, f32 scale) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeScale));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_SCALE);
|
||||
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
||||
graphNode->scale = scale;
|
||||
graphNode->displayList = displayList;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created object node
|
||||
*/
|
||||
struct GraphNodeObject *init_graph_node_object(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeObject *graphNode,
|
||||
struct GraphNode *sharedChild, Vec3f pos, Vec3s angle,
|
||||
Vec3f scale) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeObject));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_OBJECT);
|
||||
vec3f_copy(graphNode->pos, pos);
|
||||
vec3f_copy(graphNode->scale, scale);
|
||||
vec3s_copy(graphNode->angle, angle);
|
||||
#ifdef USE_SYSTEM_MALLOC
|
||||
// To avoid uninitialised memory usage in audio code
|
||||
vec3f_copy(graphNode->cameraToObject, gVec3fZero);
|
||||
#endif
|
||||
graphNode->sharedChild = sharedChild;
|
||||
graphNode->throwMatrix = NULL;
|
||||
graphNode->animInfo.animID = 0;
|
||||
graphNode->animInfo.curAnim = NULL;
|
||||
graphNode->animInfo.animFrame = 0;
|
||||
graphNode->animInfo.animFrameAccelAssist = 0;
|
||||
graphNode->animInfo.animAccel = 0x10000;
|
||||
graphNode->animInfo.animTimer = 0;
|
||||
graphNode->node.flags |= GRAPH_RENDER_HAS_ANIMATION;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created frustum culling radius node
|
||||
*/
|
||||
struct GraphNodeCullingRadius *init_graph_node_culling_radius(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeCullingRadius *graphNode,
|
||||
s16 radius) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeCullingRadius));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_CULLING_RADIUS);
|
||||
graphNode->cullingRadius = radius;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created animated part node
|
||||
*/
|
||||
struct GraphNodeAnimatedPart *init_graph_node_animated_part(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeAnimatedPart *graphNode,
|
||||
s32 drawingLayer, void *displayList,
|
||||
Vec3s translation) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeAnimatedPart));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_ANIMATED_PART);
|
||||
vec3s_copy(graphNode->translation, translation);
|
||||
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
||||
graphNode->displayList = displayList;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created billboard node
|
||||
*/
|
||||
struct GraphNodeBillboard *init_graph_node_billboard(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeBillboard *graphNode,
|
||||
s32 drawingLayer, void *displayList,
|
||||
Vec3s translation) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeBillboard));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_BILLBOARD);
|
||||
vec3s_copy(graphNode->translation, translation);
|
||||
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
||||
graphNode->displayList = displayList;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created displaylist node
|
||||
*/
|
||||
struct GraphNodeDisplayList *init_graph_node_display_list(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeDisplayList *graphNode,
|
||||
s32 drawingLayer, void *displayList) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeDisplayList));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_DISPLAY_LIST);
|
||||
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
||||
graphNode->displayList = displayList;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created shadow node
|
||||
*/
|
||||
struct GraphNodeShadow *init_graph_node_shadow(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeShadow *graphNode, s16 shadowScale,
|
||||
u8 shadowSolidity, u8 shadowType) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeShadow));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_SHADOW);
|
||||
graphNode->shadowScale = shadowScale;
|
||||
graphNode->shadowSolidity = shadowSolidity;
|
||||
graphNode->shadowType = shadowType;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created object parent node
|
||||
*/
|
||||
struct GraphNodeObjectParent *init_graph_node_object_parent(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeObjectParent *graphNode,
|
||||
struct GraphNode *sharedChild) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeObjectParent));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_OBJECT_PARENT);
|
||||
graphNode->sharedChild = sharedChild;
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created generated node
|
||||
*/
|
||||
struct GraphNodeGenerated *init_graph_node_generated(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeGenerated *graphNode,
|
||||
GraphNodeFunc gfxFunc, s32 parameter) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeGenerated));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->fnNode.node, GRAPH_NODE_TYPE_GENERATED_LIST);
|
||||
graphNode->fnNode.func = gfxFunc;
|
||||
graphNode->parameter = parameter;
|
||||
|
||||
if (gfxFunc != NULL) {
|
||||
gfxFunc(GEO_CONTEXT_CREATE, &graphNode->fnNode.node, pool);
|
||||
}
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created background node
|
||||
*/
|
||||
struct GraphNodeBackground *init_graph_node_background(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeBackground *graphNode,
|
||||
u16 background, GraphNodeFunc backgroundFunc,
|
||||
s32 zero) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeBackground));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->fnNode.node, GRAPH_NODE_TYPE_BACKGROUND);
|
||||
|
||||
graphNode->background = (background << 16) | background;
|
||||
graphNode->fnNode.func = backgroundFunc;
|
||||
graphNode->unused = zero; // always 0, unused
|
||||
|
||||
if (backgroundFunc != NULL) {
|
||||
backgroundFunc(GEO_CONTEXT_CREATE, &graphNode->fnNode.node, pool);
|
||||
}
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and returns a newly created held object node
|
||||
*/
|
||||
struct GraphNodeHeldObject *init_graph_node_held_object(struct AllocOnlyPool *pool,
|
||||
struct GraphNodeHeldObject *graphNode,
|
||||
struct Object *objNode,
|
||||
Vec3s translation,
|
||||
GraphNodeFunc nodeFunc, s32 playerIndex) {
|
||||
if (pool != NULL) {
|
||||
graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeHeldObject));
|
||||
}
|
||||
|
||||
if (graphNode != NULL) {
|
||||
init_scene_graph_node_links(&graphNode->fnNode.node, GRAPH_NODE_TYPE_HELD_OBJ);
|
||||
vec3s_copy(graphNode->translation, translation);
|
||||
graphNode->objNode = objNode;
|
||||
graphNode->fnNode.func = nodeFunc;
|
||||
graphNode->playerIndex = playerIndex;
|
||||
|
||||
if (nodeFunc != NULL) {
|
||||
nodeFunc(GEO_CONTEXT_CREATE, &graphNode->fnNode.node, pool);
|
||||
}
|
||||
}
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds 'childNode' to the end of the list children from 'parent'
|
||||
*/
|
||||
struct GraphNode *geo_add_child(struct GraphNode *parent, struct GraphNode *childNode) {
|
||||
struct GraphNode *parentFirstChild;
|
||||
struct GraphNode *parentLastChild;
|
||||
|
||||
if (childNode != NULL) {
|
||||
childNode->parent = parent;
|
||||
parentFirstChild = parent->children;
|
||||
|
||||
if (parentFirstChild == NULL) {
|
||||
parent->children = childNode;
|
||||
childNode->prev = childNode;
|
||||
childNode->next = childNode;
|
||||
} else {
|
||||
parentLastChild = parentFirstChild->prev;
|
||||
childNode->prev = parentLastChild;
|
||||
childNode->next = parentFirstChild;
|
||||
parentFirstChild->prev = childNode;
|
||||
parentLastChild->next = childNode;
|
||||
}
|
||||
}
|
||||
|
||||
return childNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a node from the scene graph. It changes the links with its
|
||||
* siblings and with its parent, it doesn't deallocate the memory
|
||||
* since geo nodes are allocated in a pointer-bumping pool that
|
||||
* gets thrown out when changing areas.
|
||||
*/
|
||||
struct GraphNode *geo_remove_child(struct GraphNode *graphNode) {
|
||||
struct GraphNode *parent;
|
||||
struct GraphNode **firstChild;
|
||||
|
||||
parent = graphNode->parent;
|
||||
firstChild = &parent->children;
|
||||
|
||||
// Remove link with siblings
|
||||
graphNode->prev->next = graphNode->next;
|
||||
graphNode->next->prev = graphNode->prev;
|
||||
|
||||
// If this node was the first child, a new first child must be chosen
|
||||
if (*firstChild == graphNode) {
|
||||
// The list is circular, so this checks whether it was the only child
|
||||
if (graphNode->next == graphNode) {
|
||||
*firstChild = NULL; // Parent has no children anymore
|
||||
} else {
|
||||
*firstChild = graphNode->next; // Choose a new first child
|
||||
}
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorders the given node so it's the first child of its parent.
|
||||
* This is called on the Mario object when he is spawned. That's why Mario's
|
||||
* object is always drawn before any other objects. (Note that the geo order
|
||||
* is independent from processing group order, where Mario is not first.)
|
||||
*/
|
||||
struct GraphNode *geo_make_first_child(struct GraphNode *newFirstChild) {
|
||||
struct GraphNode *lastSibling;
|
||||
struct GraphNode *parent;
|
||||
struct GraphNode **firstChild;
|
||||
|
||||
parent = newFirstChild->parent;
|
||||
firstChild = &parent->children;
|
||||
|
||||
if (*firstChild != newFirstChild) {
|
||||
if ((*firstChild)->prev != newFirstChild) {
|
||||
newFirstChild->prev->next = newFirstChild->next;
|
||||
newFirstChild->next->prev = newFirstChild->prev;
|
||||
lastSibling = (*firstChild)->prev;
|
||||
newFirstChild->prev = lastSibling;
|
||||
newFirstChild->next = *firstChild;
|
||||
(*firstChild)->prev = newFirstChild;
|
||||
lastSibling->next = newFirstChild;
|
||||
}
|
||||
*firstChild = newFirstChild;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for geo_call_global_function_nodes that recursively
|
||||
* traverses the scene graph and calls the functions of global nodes.
|
||||
*/
|
||||
void geo_call_global_function_nodes_helper(struct GraphNode *graphNode, s32 callContext) {
|
||||
struct GraphNode **globalPtr;
|
||||
struct GraphNode *curNode;
|
||||
struct FnGraphNode *asFnNode;
|
||||
|
||||
curNode = graphNode;
|
||||
|
||||
do {
|
||||
asFnNode = (struct FnGraphNode *) curNode;
|
||||
|
||||
if (curNode->type & GRAPH_NODE_TYPE_FUNCTIONAL) {
|
||||
if (asFnNode->func != NULL) {
|
||||
asFnNode->func(callContext, curNode, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (curNode->children != NULL) {
|
||||
switch (curNode->type) {
|
||||
case GRAPH_NODE_TYPE_MASTER_LIST:
|
||||
globalPtr = (struct GraphNode **) &gCurGraphNodeMasterList;
|
||||
break;
|
||||
case GRAPH_NODE_TYPE_PERSPECTIVE:
|
||||
globalPtr = (struct GraphNode **) &gCurGraphNodeCamFrustum;
|
||||
break;
|
||||
case GRAPH_NODE_TYPE_CAMERA:
|
||||
globalPtr = (struct GraphNode **) &gCurGraphNodeCamera;
|
||||
break;
|
||||
case GRAPH_NODE_TYPE_OBJECT:
|
||||
globalPtr = (struct GraphNode **) &gCurGraphNodeObject;
|
||||
break;
|
||||
default:
|
||||
globalPtr = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (globalPtr != NULL) {
|
||||
*globalPtr = curNode;
|
||||
}
|
||||
|
||||
geo_call_global_function_nodes_helper(curNode->children, callContext);
|
||||
|
||||
if (globalPtr != NULL) {
|
||||
*globalPtr = NULL;
|
||||
}
|
||||
}
|
||||
} while ((curNode = curNode->next) != graphNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the update functions of geo nodes that are stored in global variables.
|
||||
* These variables include gCurGraphNodeMasterList, gCurGraphNodeCamFrustum,
|
||||
* gCurGraphNodeCamera and gCurGraphNodeObject.
|
||||
* callContext is one of the GEO_CONTEXT_ defines.
|
||||
* The graphNode argument should be of type GraphNodeRoot.
|
||||
*/
|
||||
void geo_call_global_function_nodes(struct GraphNode *graphNode, s32 callContext) {
|
||||
if (graphNode->flags & GRAPH_RENDER_ACTIVE) {
|
||||
gCurGraphNodeRoot = (struct GraphNodeRoot *) graphNode;
|
||||
|
||||
if (graphNode->children != NULL) {
|
||||
geo_call_global_function_nodes_helper(graphNode->children, callContext);
|
||||
}
|
||||
|
||||
gCurGraphNodeRoot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When objects are cleared, this is called on all object nodes (loaded or unloaded).
|
||||
*/
|
||||
void geo_reset_object_node(struct GraphNodeObject *graphNode) {
|
||||
init_graph_node_object(NULL, graphNode, 0, gVec3fZero, gVec3sZero, gVec3fOne);
|
||||
|
||||
geo_add_child(&gObjParentGraphNode, &graphNode->node);
|
||||
graphNode->node.flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an object node using the given parameters
|
||||
*/
|
||||
void geo_obj_init(struct GraphNodeObject *graphNode, void *sharedChild, Vec3f pos, Vec3s angle) {
|
||||
vec3f_set(graphNode->scale, 1.0f, 1.0f, 1.0f);
|
||||
vec3f_copy(graphNode->pos, pos);
|
||||
vec3s_copy(graphNode->angle, angle);
|
||||
|
||||
graphNode->sharedChild = sharedChild;
|
||||
graphNode->unk4C = 0;
|
||||
graphNode->throwMatrix = NULL;
|
||||
graphNode->animInfo.curAnim = NULL;
|
||||
|
||||
graphNode->node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
graphNode->node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
graphNode->node.flags |= GRAPH_RENDER_HAS_ANIMATION;
|
||||
graphNode->node.flags &= ~GRAPH_RENDER_BILLBOARD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and object node using the given SpawnInfo struct
|
||||
*/
|
||||
void geo_obj_init_spawninfo(struct GraphNodeObject *graphNode, struct SpawnInfo *spawn) {
|
||||
vec3f_set(graphNode->scale, 1.0f, 1.0f, 1.0f);
|
||||
vec3s_copy(graphNode->angle, spawn->startAngle);
|
||||
|
||||
graphNode->pos[0] = (f32) spawn->startPos[0];
|
||||
graphNode->pos[1] = (f32) spawn->startPos[1];
|
||||
graphNode->pos[2] = (f32) spawn->startPos[2];
|
||||
|
||||
graphNode->areaIndex = spawn->areaIndex;
|
||||
graphNode->activeAreaIndex = spawn->activeAreaIndex;
|
||||
graphNode->sharedChild = spawn->unk18;
|
||||
graphNode->unk4C = spawn;
|
||||
graphNode->throwMatrix = NULL;
|
||||
graphNode->animInfo.curAnim = 0;
|
||||
|
||||
graphNode->node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
graphNode->node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
graphNode->node.flags |= GRAPH_RENDER_HAS_ANIMATION;
|
||||
graphNode->node.flags &= ~GRAPH_RENDER_BILLBOARD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the animation of an object node
|
||||
*/
|
||||
void geo_obj_init_animation(struct GraphNodeObject *graphNode, struct Animation **animPtrAddr) {
|
||||
struct Animation **animSegmented = segmented_to_virtual(animPtrAddr);
|
||||
struct Animation *anim = segmented_to_virtual(*animSegmented);
|
||||
|
||||
if (graphNode->animInfo.curAnim != anim) {
|
||||
graphNode->animInfo.curAnim = anim;
|
||||
graphNode->animInfo.animFrame = anim->startFrame + ((anim->flags & ANIM_FLAG_FORWARD) ? 1 : -1);
|
||||
graphNode->animInfo.animAccel = 0;
|
||||
graphNode->animInfo.animYTrans = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the animation of an object node
|
||||
*/
|
||||
void geo_obj_init_animation_accel(struct GraphNodeObject *graphNode, struct Animation **animPtrAddr, u32 animAccel) {
|
||||
struct Animation **animSegmented = segmented_to_virtual(animPtrAddr);
|
||||
struct Animation *anim = segmented_to_virtual(*animSegmented);
|
||||
|
||||
if (graphNode->animInfo.curAnim != anim) {
|
||||
graphNode->animInfo.curAnim = anim;
|
||||
graphNode->animInfo.animYTrans = 0;
|
||||
graphNode->animInfo.animFrameAccelAssist =
|
||||
(anim->startFrame << 16) + ((anim->flags & ANIM_FLAG_FORWARD) ? animAccel : -animAccel);
|
||||
graphNode->animInfo.animFrame = graphNode->animInfo.animFrameAccelAssist >> 16;
|
||||
}
|
||||
|
||||
graphNode->animInfo.animAccel = animAccel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an index into animation data based on the attribute pointer
|
||||
* An attribute is an x-, y- or z-component of the translation / rotation for a part
|
||||
* Each attribute is a pair of s16's, where the first s16 represents the maximum frame
|
||||
* and the second s16 the actual index. This index can be used to index in the array
|
||||
* with actual animation values.
|
||||
*/
|
||||
s32 retrieve_animation_index(s32 frame, u16 **attributes) {
|
||||
s32 result;
|
||||
|
||||
if (frame < (*attributes)[0]) {
|
||||
result = (*attributes)[1] + frame;
|
||||
} else {
|
||||
result = (*attributes)[1] + (*attributes)[0] - 1;
|
||||
}
|
||||
|
||||
*attributes += 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the animation frame of an object. The animation flags determine
|
||||
* whether it plays forwards or backwards, and whether it stops or loops at
|
||||
* the end etc.
|
||||
*/
|
||||
s16 geo_update_animation_frame(struct AnimInfo *obj, s32 *accelAssist) {
|
||||
s32 result;
|
||||
struct Animation *anim;
|
||||
|
||||
anim = obj->curAnim;
|
||||
|
||||
if (obj->animTimer == gAreaUpdateCounter || anim->flags & ANIM_FLAG_2) {
|
||||
if (accelAssist != NULL) {
|
||||
accelAssist[0] = obj->animFrameAccelAssist;
|
||||
}
|
||||
|
||||
return obj->animFrame;
|
||||
}
|
||||
|
||||
if (anim->flags & ANIM_FLAG_FORWARD) {
|
||||
if (obj->animAccel) {
|
||||
result = obj->animFrameAccelAssist - obj->animAccel;
|
||||
} else {
|
||||
result = (obj->animFrame - 1) << 16;
|
||||
}
|
||||
|
||||
if (GET_HIGH_S16_OF_32(result) < anim->loopStart) {
|
||||
if (anim->flags & ANIM_FLAG_NOLOOP) {
|
||||
SET_HIGH_S16_OF_32(result, anim->loopStart);
|
||||
} else {
|
||||
SET_HIGH_S16_OF_32(result, anim->loopEnd - 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (obj->animAccel != 0) {
|
||||
result = obj->animFrameAccelAssist + obj->animAccel;
|
||||
} else {
|
||||
result = (obj->animFrame + 1) << 16;
|
||||
}
|
||||
|
||||
if (GET_HIGH_S16_OF_32(result) >= anim->loopEnd) {
|
||||
if (anim->flags & ANIM_FLAG_NOLOOP) {
|
||||
SET_HIGH_S16_OF_32(result, anim->loopEnd - 1);
|
||||
} else {
|
||||
SET_HIGH_S16_OF_32(result, anim->loopStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (accelAssist != 0) {
|
||||
accelAssist[0] = result;
|
||||
}
|
||||
|
||||
return GET_HIGH_S16_OF_32(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused function to retrieve an object's current animation translation
|
||||
* Assumes that it has x, y and z data in animations, which isn't always the
|
||||
* case since some animation types only have vertical or lateral translation.
|
||||
* This might have been used for positioning the shadow under an object, which
|
||||
* currently happens in-line in geo_process_shadow where it also accounts for
|
||||
* animations without lateral translation.
|
||||
*/
|
||||
void geo_retreive_animation_translation(struct GraphNodeObject *obj, Vec3f position) {
|
||||
struct Animation *animation = obj->animInfo.curAnim;
|
||||
u16 *attribute;
|
||||
s16 *values;
|
||||
s16 frame;
|
||||
|
||||
if (animation != NULL) {
|
||||
attribute = segmented_to_virtual((void *) animation->index);
|
||||
values = segmented_to_virtual((void *) animation->values);
|
||||
|
||||
frame = obj->animInfo.animFrame;
|
||||
|
||||
if (frame < 0) {
|
||||
frame = 0;
|
||||
}
|
||||
|
||||
if (1) // ? necessary to match
|
||||
{
|
||||
position[0] = (f32) values[retrieve_animation_index(frame, &attribute)];
|
||||
position[1] = (f32) values[retrieve_animation_index(frame, &attribute)];
|
||||
position[2] = (f32) values[retrieve_animation_index(frame, &attribute)];
|
||||
}
|
||||
} else {
|
||||
vec3f_set(position, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused function to find the root of the geo node tree, which should be a
|
||||
* GraphNodeRoot. If it is not for some reason, null is returned.
|
||||
*/
|
||||
struct GraphNodeRoot *geo_find_root(struct GraphNode *graphNode) {
|
||||
struct GraphNodeRoot *resGraphNode = NULL;
|
||||
|
||||
while (graphNode->parent != NULL) {
|
||||
graphNode = graphNode->parent;
|
||||
}
|
||||
|
||||
if (graphNode->type == GRAPH_NODE_TYPE_ROOT) {
|
||||
resGraphNode = (struct GraphNodeRoot *) graphNode;
|
||||
}
|
||||
|
||||
return resGraphNode;
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
#ifndef GRAPH_NODE_H
|
||||
#define GRAPH_NODE_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
#include "../include/PR/gbi.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
#include "../../memory.h"
|
||||
|
||||
#define GRAPH_RENDER_ACTIVE (1 << 0)
|
||||
#define GRAPH_RENDER_CHILDREN_FIRST (1 << 1)
|
||||
#define GRAPH_RENDER_BILLBOARD (1 << 2)
|
||||
#define GRAPH_RENDER_Z_BUFFER (1 << 3)
|
||||
#define GRAPH_RENDER_INVISIBLE (1 << 4)
|
||||
#define GRAPH_RENDER_HAS_ANIMATION (1 << 5)
|
||||
|
||||
// Whether the node type has a function pointer of type GraphNodeFunc
|
||||
#define GRAPH_NODE_TYPE_FUNCTIONAL 0x100
|
||||
|
||||
// Type used for Bowser and an unused geo function in obj_behaviors.c
|
||||
#define GRAPH_NODE_TYPE_400 0x400
|
||||
|
||||
// The discriminant for different types of geo nodes
|
||||
#define GRAPH_NODE_TYPE_ROOT 0x001
|
||||
#define GRAPH_NODE_TYPE_ORTHO_PROJECTION 0x002
|
||||
#define GRAPH_NODE_TYPE_PERSPECTIVE (0x003 | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_MASTER_LIST 0x004
|
||||
#define GRAPH_NODE_TYPE_START 0x00A
|
||||
#define GRAPH_NODE_TYPE_LEVEL_OF_DETAIL 0x00B
|
||||
#define GRAPH_NODE_TYPE_SWITCH_CASE (0x00C | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_CAMERA (0x014 | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_TRANSLATION_ROTATION 0x015
|
||||
#define GRAPH_NODE_TYPE_TRANSLATION 0x016
|
||||
#define GRAPH_NODE_TYPE_ROTATION 0x017
|
||||
#define GRAPH_NODE_TYPE_OBJECT 0x018
|
||||
#define GRAPH_NODE_TYPE_ANIMATED_PART 0x019
|
||||
#define GRAPH_NODE_TYPE_BILLBOARD 0x01A
|
||||
#define GRAPH_NODE_TYPE_DISPLAY_LIST 0x01B
|
||||
#define GRAPH_NODE_TYPE_SCALE 0x01C
|
||||
#define GRAPH_NODE_TYPE_SHADOW 0x028
|
||||
#define GRAPH_NODE_TYPE_OBJECT_PARENT 0x029
|
||||
#define GRAPH_NODE_TYPE_GENERATED_LIST (0x02A | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_BACKGROUND (0x02C | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_HELD_OBJ (0x02E | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_CULLING_RADIUS 0x02F
|
||||
|
||||
// The number of master lists. A master list determines the order and render
|
||||
// mode with which display lists are drawn.
|
||||
#define GFX_NUM_MASTER_LISTS 8
|
||||
|
||||
// Passed as first argument to a GraphNodeFunc to give information about in
|
||||
// which context it was called and what it is expected to do.
|
||||
#define GEO_CONTEXT_CREATE 0 // called when node is created from a geo command
|
||||
#define GEO_CONTEXT_RENDER 1 // called from rendering_graph_node.c
|
||||
#define GEO_CONTEXT_AREA_UNLOAD 2 // called when unloading an area
|
||||
#define GEO_CONTEXT_AREA_LOAD 3 // called when loading an area
|
||||
#define GEO_CONTEXT_AREA_INIT 4 // called when initializing the 8 areas
|
||||
#define GEO_CONTEXT_HELD_OBJ 5 // called when processing a GraphNodeHeldObj
|
||||
|
||||
// The signature for a function stored in a geo node
|
||||
// The context argument depends on the callContext:
|
||||
// - for GEO_CONTEXT_CREATE it is the AllocOnlyPool from which the node was allocated
|
||||
// - for GEO_CONTEXT_RENDER or GEO_CONTEXT_HELD_OBJ it is the top of the float matrix stack with type Mat4
|
||||
// - for GEO_CONTEXT_AREA_* it is the root geo node
|
||||
typedef Gfx *(*GraphNodeFunc)(s32 callContext, struct GraphNode *node, void *context);
|
||||
|
||||
/** An extension of a graph node that includes a function pointer.
|
||||
* Many graph node types have an update function that gets called
|
||||
* when they are processed.
|
||||
*/
|
||||
struct FnGraphNode
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ GraphNodeFunc func;
|
||||
};
|
||||
|
||||
/** The very root of the geo tree. Specifies the viewport.
|
||||
*/
|
||||
struct GraphNodeRoot
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ u8 areaIndex;
|
||||
/*0x15*/ s8 unk15; // ?
|
||||
/*0x16*/ s16 x;
|
||||
/*0x18*/ s16 y;
|
||||
/*0x1A*/ s16 width; // half width, 160
|
||||
/*0x1C*/ s16 height; // half height
|
||||
/*0x1E*/ s16 numViews; // number of entries in mystery array
|
||||
/*0x20*/ struct GraphNode **views;
|
||||
};
|
||||
|
||||
/** A node that sets up an orthographic projection based on the global
|
||||
* root node. Used to draw the skybox image.
|
||||
*/
|
||||
struct GraphNodeOrthoProjection
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ f32 scale;
|
||||
};
|
||||
|
||||
/** A node that sets up a perspective projection. Used for drawing the
|
||||
* game world. It does not set up the camera position, that is done by
|
||||
* the child of this node, which has type GraphNodeCamera.
|
||||
*/
|
||||
struct GraphNodePerspective
|
||||
{
|
||||
/*0x00*/ struct FnGraphNode fnNode;
|
||||
/*0x18*/ s32 unused;
|
||||
/*0x1C*/ f32 fov; // horizontal field of view in degrees
|
||||
/*0x20*/ s16 near; // near clipping plane
|
||||
/*0x22*/ s16 far; // far clipping plane
|
||||
};
|
||||
|
||||
/** An entry in the master list. It is a linked list of display lists
|
||||
* carrying a transformation matrix.
|
||||
*/
|
||||
struct DisplayListNode
|
||||
{
|
||||
Mtx *transform;
|
||||
void *displayList;
|
||||
struct DisplayListNode *next;
|
||||
};
|
||||
|
||||
/** GraphNode that manages the 8 top-level display lists that will be drawn
|
||||
* Each list has its own render mode, so for example water is drawn in a
|
||||
* different master list than opaque objects.
|
||||
* It also sets the z-buffer on before rendering and off after.
|
||||
*/
|
||||
struct GraphNodeMasterList
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ struct DisplayListNode *listHeads[GFX_NUM_MASTER_LISTS];
|
||||
/*0x34*/ struct DisplayListNode *listTails[GFX_NUM_MASTER_LISTS];
|
||||
};
|
||||
|
||||
/** Simply used as a parent to group multiple children.
|
||||
* Does not have any additional functionality.
|
||||
*/
|
||||
struct GraphNodeStart
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
};
|
||||
|
||||
/** GraphNode that only renders its children if the current transformation matrix
|
||||
* has a z-translation (in camera space) greater than minDistance and less than
|
||||
* maxDistance.
|
||||
* Usage examples: Mario has three level's of detail: Normal, low-poly arms only, and fully low-poly
|
||||
* The tower in Whomp's fortress has two levels of detail.
|
||||
*/
|
||||
struct GraphNodeLevelOfDetail
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ s16 minDistance;
|
||||
/*0x16*/ s16 maxDistance;
|
||||
};
|
||||
|
||||
/** GraphNode that renders exactly one of its children.
|
||||
* Which one is rendered is determined by the field 'selectedCase'
|
||||
* which is set in the node's function.
|
||||
* Usage examples: room visibility, coin animation, blinking, Mario's power-up / hand pose / cap
|
||||
*/
|
||||
struct GraphNodeSwitchCase
|
||||
{
|
||||
/*0x00*/ struct FnGraphNode fnNode;
|
||||
/*0x18*/ s32 unused;
|
||||
/*0x1C*/ s16 numCases;
|
||||
/*0x1E*/ s16 selectedCase;
|
||||
};
|
||||
|
||||
/**
|
||||
* GraphNode that specifies the location and aim of the camera.
|
||||
* When the roll is 0, the up vector is (0, 1, 0).
|
||||
*/
|
||||
struct GraphNodeCamera
|
||||
{
|
||||
/*0x00*/ struct FnGraphNode fnNode;
|
||||
/*0x18*/ union {
|
||||
// When the node is created, a mode is assigned to the node.
|
||||
// Later in geo_camera_main a Camera is allocated,
|
||||
// the mode is passed to the struct, and the field is overridden
|
||||
// by a pointer to the struct. Gotta save those 4 bytes.
|
||||
s32 mode;
|
||||
struct Camera *camera;
|
||||
} config;
|
||||
/*0x1C*/ Vec3f pos;
|
||||
/*0x28*/ Vec3f focus;
|
||||
/*0x34*/ Mat4 *matrixPtr; // pointer to look-at matrix of this camera as a Mat4
|
||||
/*0x38*/ s16 roll; // roll in look at matrix. Doesn't account for light direction unlike rollScreen.
|
||||
/*0x3A*/ s16 rollScreen; // rolls screen while keeping the light direction consistent
|
||||
};
|
||||
|
||||
/** GraphNode that translates and rotates its children.
|
||||
* Usage example: wing cap wings.
|
||||
* There is a dprint function that sets the translation and rotation values
|
||||
* based on the ENEMYINFO array.
|
||||
* The display list can be null, in which case it won't draw anything itself.
|
||||
*/
|
||||
struct GraphNodeTranslationRotation
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ void *displayList;
|
||||
/*0x18*/ Vec3s translation;
|
||||
/*0x1E*/ Vec3s rotation;
|
||||
};
|
||||
|
||||
/** GraphNode that translates itself and its children.
|
||||
* Usage example: SUPER MARIO logo letters in debug level select.
|
||||
* The display list can be null, in which case it won't draw anything itself.
|
||||
*/
|
||||
struct GraphNodeTranslation
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ void *displayList;
|
||||
/*0x18*/ Vec3s translation;
|
||||
u8 pad1E[2];
|
||||
};
|
||||
|
||||
/** GraphNode that rotates itself and its children.
|
||||
* Usage example: Mario torso / head rotation. Its parameters are dynamically
|
||||
* set by a parent script node in that case.
|
||||
* The display list can be null, in which case it won't draw anything itself.
|
||||
*/
|
||||
struct GraphNodeRotation
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ void *displayList;
|
||||
/*0x18*/ Vec3s rotation;
|
||||
u8 pad1E[2];
|
||||
};
|
||||
|
||||
/** GraphNode part that transforms itself and its children based on animation
|
||||
* data. This animation data is not stored in the node itself but in global
|
||||
* variables that are set when object nodes are processed if the object has
|
||||
* animation.
|
||||
* Used for Mario, enemies and anything else with animation data.
|
||||
* The display list can be null, in which case it won't draw anything itself.
|
||||
*/
|
||||
struct GraphNodeAnimatedPart
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ void *displayList;
|
||||
/*0x18*/ Vec3s translation;
|
||||
};
|
||||
|
||||
/** A GraphNode that draws a display list rotated in a way to always face the
|
||||
* camera. Note that if the entire object is a billboard (like a coin or 1-up)
|
||||
* then it simply sets the billboard flag for the entire object, this node is
|
||||
* used for billboard parts (like a chuckya or goomba body).
|
||||
*/
|
||||
struct GraphNodeBillboard
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ void *displayList;
|
||||
/*0x18*/ Vec3s translation;
|
||||
};
|
||||
|
||||
/** A GraphNode that simply draws a display list without doing any
|
||||
* transformation beforehand. It does inherit the parent's transformation.
|
||||
*/
|
||||
struct GraphNodeDisplayList
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ void *displayList;
|
||||
};
|
||||
|
||||
/** GraphNode part that scales itself and its children.
|
||||
* Usage example: Mario's fist or shoe, which grows when attacking. This can't
|
||||
* be done with an animated part sine animation data doesn't support scaling.
|
||||
* Note that many scaling animations (like a goomba getting stomped) happen on
|
||||
* the entire object. This node is only used when a single part needs to be scaled.
|
||||
* There is also a level command that scales the entire level, used for THI.
|
||||
* The display list can be null, in which case it won't draw anything itself.
|
||||
*/
|
||||
struct GraphNodeScale
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ void *displayList;
|
||||
/*0x18*/ f32 scale;
|
||||
};
|
||||
|
||||
/** GraphNode that draws a shadow under an object.
|
||||
* Every object starts with a shadow node.
|
||||
* The shadow type determines the shape (round or rectangular), vertices (4 or 9)
|
||||
* and other features.
|
||||
*/
|
||||
struct GraphNodeShadow
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ s16 shadowScale; // diameter (when a circle) or side (when a square) of shadow
|
||||
/*0x16*/ u8 shadowSolidity; // opacity of shadow, 255 = opaque
|
||||
/*0x17*/ u8 shadowType; // see ShadowType enum in shadow.h
|
||||
};
|
||||
|
||||
/** GraphNode that contains as its sharedChild a group node containing all
|
||||
* object nodes.
|
||||
*/
|
||||
struct GraphNodeObjectParent
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ struct GraphNode *sharedChild;
|
||||
};
|
||||
|
||||
/** GraphNode that draws display lists not directly in memory but generated by
|
||||
* a function.
|
||||
* Used for wobbling paintings, water, environment effects.
|
||||
* It might not draw anything, it could also just update something.
|
||||
* For example: there is a node that stops water flow when the game is paused.
|
||||
* The parameter field gives extra context info. For shifting sand or paintings,
|
||||
* it can determine which texture to use.
|
||||
*/
|
||||
struct GraphNodeGenerated
|
||||
{
|
||||
/*0x00*/ struct FnGraphNode fnNode;
|
||||
/*0x18*/ u32 parameter; // extra context for the function
|
||||
};
|
||||
|
||||
/** GraphNode that draws a background image or a rectangle of a color.
|
||||
* Drawn in an orthographic projection, used for skyboxes.
|
||||
*/
|
||||
struct GraphNodeBackground
|
||||
{
|
||||
/*0x00*/ struct FnGraphNode fnNode;
|
||||
/*0x18*/ s32 unused;
|
||||
/*0x1C*/ s32 background; // background ID, or rgba5551 color if fnNode.func is null
|
||||
};
|
||||
|
||||
/** Renders the object that Mario is holding.
|
||||
*/
|
||||
struct GraphNodeHeldObject
|
||||
{
|
||||
/*0x00*/ struct FnGraphNode fnNode;
|
||||
/*0x18*/ s32 playerIndex;
|
||||
/*0x1C*/ struct Object *objNode;
|
||||
/*0x20*/ Vec3s translation;
|
||||
};
|
||||
|
||||
/** A node that allows an object to specify a different culling radius than the
|
||||
* default one of 300. For this to work, it needs to be a direct child of the
|
||||
* object node. Used for very large objects, such as shock wave rings that Bowser
|
||||
* creates, tornadoes, the big eel.
|
||||
*/
|
||||
struct GraphNodeCullingRadius
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ s16 cullingRadius; // specifies the 'sphere radius' for purposes of frustum culling
|
||||
u8 pad1E[2];
|
||||
};
|
||||
|
||||
extern struct GraphNodeMasterList *gCurGraphNodeMasterList;
|
||||
extern struct GraphNodePerspective *gCurGraphNodeCamFrustum;
|
||||
extern struct GraphNodeCamera *gCurGraphNodeCamera;
|
||||
extern struct GraphNodeHeldObject *gCurGraphNodeHeldObject;
|
||||
extern u16 gAreaUpdateCounter;
|
||||
|
||||
extern struct GraphNode *gCurRootGraphNode;
|
||||
extern struct GraphNode *gCurGraphNodeList[];
|
||||
|
||||
extern s16 gCurGraphNodeIndex;
|
||||
|
||||
//extern Vec3f gVec3fZero;
|
||||
//extern Vec3s gVec3sZero;
|
||||
//extern Vec3f gVec3fOne;
|
||||
//extern Vec3s gVec3sOne;
|
||||
|
||||
void init_scene_graph_node_links(struct GraphNode *graphNode, s32 type);
|
||||
|
||||
struct GraphNodeRoot *init_graph_node_root(struct AllocOnlyPool *pool, struct GraphNodeRoot *graphNode,
|
||||
s16 areaIndex, s16 x, s16 y, s16 width, s16 height);
|
||||
struct GraphNodeOrthoProjection *init_graph_node_ortho_projection(struct AllocOnlyPool *pool, struct GraphNodeOrthoProjection *graphNode, f32 scale);
|
||||
struct GraphNodePerspective *init_graph_node_perspective(struct AllocOnlyPool *pool, struct GraphNodePerspective *graphNode,
|
||||
f32 fov, s16 near, s16 far, GraphNodeFunc nodeFunc, s32 unused);
|
||||
struct GraphNodeStart *init_graph_node_start(struct AllocOnlyPool *pool, struct GraphNodeStart *graphNode);
|
||||
struct GraphNodeMasterList *init_graph_node_master_list(struct AllocOnlyPool *pool, struct GraphNodeMasterList *graphNode, s16 on);
|
||||
struct GraphNodeLevelOfDetail *init_graph_node_render_range(struct AllocOnlyPool *pool, struct GraphNodeLevelOfDetail *graphNode,
|
||||
s16 minDistance, s16 maxDistance);
|
||||
struct GraphNodeSwitchCase *init_graph_node_switch_case(struct AllocOnlyPool *pool, struct GraphNodeSwitchCase *graphNode,
|
||||
s16 numCases, s16 selectedCase, GraphNodeFunc nodeFunc, s32 unused);
|
||||
struct GraphNodeCamera *init_graph_node_camera(struct AllocOnlyPool *pool, struct GraphNodeCamera *graphNode,
|
||||
f32 *pos, f32 *focus, GraphNodeFunc func, s32 mode);
|
||||
struct GraphNodeTranslationRotation *init_graph_node_translation_rotation(struct AllocOnlyPool *pool, struct GraphNodeTranslationRotation *graphNode,
|
||||
s32 drawingLayer, void *displayList, Vec3s translation, Vec3s rotation);
|
||||
struct GraphNodeTranslation *init_graph_node_translation(struct AllocOnlyPool *pool, struct GraphNodeTranslation *graphNode,
|
||||
s32 drawingLayer, void *displayList, Vec3s translation);
|
||||
struct GraphNodeRotation *init_graph_node_rotation(struct AllocOnlyPool *pool, struct GraphNodeRotation *graphNode,
|
||||
s32 drawingLayer, void *displayList, Vec3s rotation);
|
||||
struct GraphNodeScale *init_graph_node_scale(struct AllocOnlyPool *pool, struct GraphNodeScale *graphNode,
|
||||
s32 drawingLayer, void *displayList, f32 scale);
|
||||
struct GraphNodeObject *init_graph_node_object(struct AllocOnlyPool *pool, struct GraphNodeObject *graphNode,
|
||||
struct GraphNode *sharedChild, Vec3f pos, Vec3s angle, Vec3f scale);
|
||||
struct GraphNodeCullingRadius *init_graph_node_culling_radius(struct AllocOnlyPool *pool, struct GraphNodeCullingRadius *graphNode, s16 radius);
|
||||
struct GraphNodeAnimatedPart *init_graph_node_animated_part(struct AllocOnlyPool *pool, struct GraphNodeAnimatedPart *graphNode,
|
||||
s32 drawingLayer, void *displayList, Vec3s translation);
|
||||
struct GraphNodeBillboard *init_graph_node_billboard(struct AllocOnlyPool *pool, struct GraphNodeBillboard *graphNode,
|
||||
s32 drawingLayer, void *displayList, Vec3s translation);
|
||||
struct GraphNodeDisplayList *init_graph_node_display_list(struct AllocOnlyPool *pool, struct GraphNodeDisplayList *graphNode,
|
||||
s32 drawingLayer, void *displayList);
|
||||
struct GraphNodeShadow *init_graph_node_shadow(struct AllocOnlyPool *pool, struct GraphNodeShadow *graphNode,
|
||||
s16 shadowScale, u8 shadowSolidity, u8 shadowType);
|
||||
struct GraphNodeObjectParent *init_graph_node_object_parent(struct AllocOnlyPool *pool, struct GraphNodeObjectParent *sp1c,
|
||||
struct GraphNode *sharedChild);
|
||||
struct GraphNodeGenerated *init_graph_node_generated(struct AllocOnlyPool *pool, struct GraphNodeGenerated *sp1c,
|
||||
GraphNodeFunc gfxFunc, s32 parameter);
|
||||
struct GraphNodeBackground *init_graph_node_background(struct AllocOnlyPool *pool, struct GraphNodeBackground *sp1c,
|
||||
u16 background, GraphNodeFunc backgroundFunc, s32 zero);
|
||||
struct GraphNodeHeldObject *init_graph_node_held_object(struct AllocOnlyPool *pool, struct GraphNodeHeldObject *sp1c,
|
||||
struct Object *objNode, Vec3s translation,
|
||||
GraphNodeFunc nodeFunc, s32 playerIndex);
|
||||
struct GraphNode *geo_add_child(struct GraphNode *parent, struct GraphNode *childNode);
|
||||
struct GraphNode *geo_remove_child(struct GraphNode *graphNode);
|
||||
struct GraphNode *geo_make_first_child(struct GraphNode *newFirstChild);
|
||||
|
||||
void geo_call_global_function_nodes_helper(struct GraphNode *graphNode, s32 callContext);
|
||||
void geo_call_global_function_nodes(struct GraphNode *graphNode, s32 callContext);
|
||||
|
||||
void geo_reset_object_node(struct GraphNodeObject *graphNode);
|
||||
void geo_obj_init(struct GraphNodeObject *graphNode, void *sharedChild, Vec3f pos, Vec3s angle);
|
||||
void geo_obj_init_spawninfo(struct GraphNodeObject *graphNode, struct SpawnInfo *spawn);
|
||||
void geo_obj_init_animation(struct GraphNodeObject *graphNode, struct Animation **animPtrAddr);
|
||||
void geo_obj_init_animation_accel(struct GraphNodeObject *graphNode, struct Animation **animPtrAddr, u32 animAccel);
|
||||
|
||||
s32 retrieve_animation_index(s32 frame, u16 **attributes);
|
||||
|
||||
s16 geo_update_animation_frame(struct AnimInfo *obj, s32 *accelAssist);
|
||||
void geo_retreive_animation_translation(struct GraphNodeObject *obj, Vec3f position);
|
||||
|
||||
struct GraphNodeRoot *geo_find_root(struct GraphNode *graphNode);
|
||||
|
||||
// graph_node_manager
|
||||
s16 *read_vec3s_to_vec3f(Vec3f, s16 *src);
|
||||
s16 *read_vec3s(Vec3s dst, s16 *src);
|
||||
s16 *read_vec3s_angle(Vec3s dst, s16 *src);
|
||||
void register_scene_graph_node(struct GraphNode *graphNode);
|
||||
|
||||
#endif // GRAPH_NODE_H
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
#include "geo_layout.h"
|
||||
#include "graph_node.h"
|
||||
|
||||
#if IS_64_BIT
|
||||
static s16 next_s16_in_geo_script(s16 **src) {
|
||||
s16 ret;
|
||||
if (((uintptr_t)(*src) & 7) == 4) {
|
||||
*src += 2; // skip 32 bits
|
||||
}
|
||||
ret = *(*src)++;
|
||||
if (((uintptr_t)(*src) & 7) == 4) {
|
||||
*src += 2; // skip 32 bits
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#define next_s16_in_geo_script(src) (*(*src)++)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Takes a pointer to three shorts (supplied by a geo layout script) and
|
||||
* copies it to the destination float vector.
|
||||
*/
|
||||
s16 *read_vec3s_to_vec3f(Vec3f dst, s16 *src) {
|
||||
dst[0] = next_s16_in_geo_script(&src);
|
||||
dst[1] = next_s16_in_geo_script(&src);
|
||||
dst[2] = next_s16_in_geo_script(&src);
|
||||
return src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a pointer to three shorts (supplied by a geo layout script) and
|
||||
* copies it to the destination vector. It's essentially a memcpy but consistent
|
||||
* with the other two 'geo-script vector to internal vector' functions.
|
||||
*/
|
||||
s16 *read_vec3s(Vec3s dst, s16 *src) {
|
||||
dst[0] = next_s16_in_geo_script(&src);
|
||||
dst[1] = next_s16_in_geo_script(&src);
|
||||
dst[2] = next_s16_in_geo_script(&src);
|
||||
return src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a pointer to three angles in degrees (supplied by a geo layout script)
|
||||
* and converts it to a vector of three in-game angle units in [-32768, 32767]
|
||||
* range.
|
||||
*/
|
||||
s16 *read_vec3s_angle(Vec3s dst, s16 *src) {
|
||||
dst[0] = (next_s16_in_geo_script(&src) << 15) / 180;
|
||||
dst[1] = (next_s16_in_geo_script(&src) << 15) / 180;
|
||||
dst[2] = (next_s16_in_geo_script(&src) << 15) / 180;
|
||||
return src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given graph node as a child to the current top of the gfx stack:
|
||||
* 'gCurGraphNodeList'. This is called from geo_layout commands to add nodes
|
||||
* to the scene graph.
|
||||
*/
|
||||
void register_scene_graph_node(struct GraphNode *graphNode) {
|
||||
if (graphNode != NULL) {
|
||||
gCurGraphNodeList[gCurGraphNodeIndex] = graphNode;
|
||||
|
||||
if (gCurGraphNodeIndex == 0) {
|
||||
if (gCurRootGraphNode == NULL) {
|
||||
gCurRootGraphNode = graphNode;
|
||||
}
|
||||
} else {
|
||||
if (gCurGraphNodeList[gCurGraphNodeIndex - 1]->type == GRAPH_NODE_TYPE_OBJECT_PARENT) {
|
||||
((struct GraphNodeObjectParent *) gCurGraphNodeList[gCurGraphNodeIndex - 1])
|
||||
->sharedChild = graphNode;
|
||||
} else {
|
||||
geo_add_child(gCurGraphNodeList[gCurGraphNodeIndex - 1], graphNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
#ifndef MATH_UTIL_H
|
||||
#define MATH_UTIL_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
#include "../include/PR/gbi.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
/*
|
||||
* The sine and cosine tables overlap, but "#define gCosineTable (gSineTable +
|
||||
* 0x400)" doesn't give expected codegen; gSineTable and gCosineTable need to
|
||||
* be different symbols for code to match. Most likely the tables were placed
|
||||
* adjacent to each other, and gSineTable cut short, such that reads overflow
|
||||
* into gCosineTable.
|
||||
*
|
||||
* These kinds of out of bounds reads are undefined behavior, and break on
|
||||
* e.g. GCC (which doesn't place the tables next to each other, and probably
|
||||
* exploits array sizes for range analysis-based optimizations as well).
|
||||
* Thus, for non-IDO compilers we use the standard-compliant version.
|
||||
*/
|
||||
extern f32 gSineTable[];
|
||||
#ifdef AVOID_UB
|
||||
#define gCosineTable (gSineTable + 0x400)
|
||||
#else
|
||||
extern f32 gCosineTable[];
|
||||
#endif
|
||||
|
||||
#define sins(x) gSineTable[(u16) (x) >> 4]
|
||||
#define coss(x) gCosineTable[(u16) (x) >> 4]
|
||||
|
||||
#define min(a, b) ((a) <= (b) ? (a) : (b))
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define sqr(x) ((x) * (x))
|
||||
|
||||
void *vec3f_copy(Vec3f dest, Vec3f src);
|
||||
void *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z);
|
||||
void *vec3f_add(Vec3f dest, Vec3f a);
|
||||
void *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b);
|
||||
void *vec3s_copy(Vec3s dest, Vec3s src);
|
||||
void *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z);
|
||||
void *vec3s_add(Vec3s dest, Vec3s a);
|
||||
void *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b);
|
||||
void *vec3s_sub(Vec3s dest, Vec3s a);
|
||||
void *vec3s_to_vec3f(Vec3f dest, Vec3s a);
|
||||
void *vec3f_to_vec3s(Vec3s dest, Vec3f a);
|
||||
void *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c);
|
||||
void *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b);
|
||||
void *vec3f_normalize(Vec3f dest);
|
||||
void mtxf_copy(Mat4 dest, Mat4 src);
|
||||
void mtxf_identity(Mat4 mtx);
|
||||
void mtxf_translate(Mat4 dest, Vec3f b);
|
||||
void mtxf_lookat(Mat4 mtx, Vec3f from, Vec3f to, s16 roll);
|
||||
void mtxf_rotate_zxy_and_translate(Mat4 dest, Vec3f translate, Vec3s rotate);
|
||||
void mtxf_rotate_xyz_and_translate(Mat4 dest, Vec3f b, Vec3s c);
|
||||
void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle);
|
||||
void mtxf_align_terrain_normal(Mat4 dest, Vec3f upDir, Vec3f pos, s16 yaw);
|
||||
void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s16 yaw, f32 radius);
|
||||
void mtxf_mul(Mat4 dest, Mat4 a, Mat4 b);
|
||||
void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, Vec3f s);
|
||||
void mtxf_mul_vec3s(Mat4 mtx, Vec3s b);
|
||||
void mtxf_mul_vec3f(Mat4 mtx, Vec3f b);
|
||||
void mtxf_to_mtx(Mtx *dest, Mat4 src);
|
||||
void mtxf_rotate_xy(Mtx *mtx, s16 angle);
|
||||
void get_pos_from_transform_mtx(Vec3f dest, Mat4 objMtx, Mat4 camMtx);
|
||||
void vec3f_get_dist_and_angle(Vec3f from, Vec3f to, f32 *dist, s16 *pitch, s16 *yaw);
|
||||
void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s16 pitch, s16 yaw);
|
||||
s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec);
|
||||
f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec);
|
||||
s16 atan2s(f32 y, f32 x);
|
||||
f32 atan2f(f32 a, f32 b);
|
||||
void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c);
|
||||
void anim_spline_init(Vec4s *keyFrames);
|
||||
s32 anim_spline_poll(Vec3f result);
|
||||
|
||||
|
||||
// From object_helpers.c
|
||||
void linear_mtxf_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v);
|
||||
void linear_mtxf_transpose_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v);
|
||||
|
||||
|
||||
#endif // MATH_UTIL_H
|
||||
@@ -0,0 +1,415 @@
|
||||
// CUSTOM/PATCH
|
||||
|
||||
#include "../shim.h"
|
||||
#include "surface_collision.h"
|
||||
#include "../include/surface_terrains.h"
|
||||
#include "../../load_surfaces.h"
|
||||
|
||||
/**
|
||||
* Iterate through the list of ceilings and find the first ceiling over a given point.
|
||||
*/
|
||||
static struct Surface *find_ceil_from_list( s32 x, s32 y, s32 z, f32 *pheight) {
|
||||
register struct Surface *surf;
|
||||
register s32 x1, z1, x2, z2, x3, z3;
|
||||
struct Surface *ceil = NULL;
|
||||
|
||||
ceil = NULL;
|
||||
|
||||
// Stay in this loop until out of ceilings.
|
||||
int count = loaded_surface_get_count();
|
||||
for( int i = 0; i < count; ++i ) {
|
||||
surf = loaded_surface_get_at_index(i);
|
||||
|
||||
// Do the check normally done in add_surface_to_cell
|
||||
if( surf->normal.y >= -0.01f ) continue;
|
||||
|
||||
|
||||
x1 = surf->vertex1[0];
|
||||
z1 = surf->vertex1[2];
|
||||
z2 = surf->vertex2[2];
|
||||
x2 = surf->vertex2[0];
|
||||
|
||||
// Checking if point is in bounds of the triangle laterally.
|
||||
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Slight optimization by checking these later.
|
||||
x3 = surf->vertex3[0];
|
||||
z3 = surf->vertex3[2];
|
||||
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) > 0) {
|
||||
continue;
|
||||
}
|
||||
if ((z3 - z) * (x1 - x3) - (x3 - x) * (z1 - z3) > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// // Determine if checking for the camera or not.
|
||||
// if (gCheckingSurfaceCollisionsForCamera != 0) {
|
||||
// if (surf->flags & SURFACE_FLAG_NO_CAM_COLLISION) {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// // Ignore camera only surfaces.
|
||||
// else if (surf->type == SURFACE_CAMERA_BOUNDARY) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
{
|
||||
f32 nx = surf->normal.x;
|
||||
f32 ny = surf->normal.y;
|
||||
f32 nz = surf->normal.z;
|
||||
f32 oo = surf->originOffset;
|
||||
f32 height;
|
||||
|
||||
// If a wall, ignore it. Likely a remnant, should never occur.
|
||||
if (ny == 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the ceil height at the specific point.
|
||||
height = -(x * nx + nz * z + oo) / ny;
|
||||
|
||||
// Checks for ceiling interaction with a 78 unit buffer.
|
||||
//! (Exposed Ceilings) Because any point above a ceiling counts
|
||||
// as interacting with a ceiling, ceilings far below can cause
|
||||
// "invisible walls" that are really just exposed ceilings.
|
||||
if (y - (height - -78.0f) > 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if( height < *pheight )
|
||||
{
|
||||
*pheight = height;
|
||||
ceil = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! (Surface Cucking) Since only the first ceil is returned and not the lowest,
|
||||
// lower ceilings can be "cucked" by higher ceilings.
|
||||
return ceil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through the list of floors and find the first floor under a given point.
|
||||
*/
|
||||
static struct Surface *find_floor_from_list( s32 x, s32 y, s32 z, f32 *pheight) {
|
||||
register struct Surface *surf;
|
||||
register s32 x1, z1, x2, z2, x3, z3;
|
||||
f32 nx, ny, nz;
|
||||
f32 oo;
|
||||
f32 height;
|
||||
struct Surface *floor = NULL;
|
||||
|
||||
// Iterate through the list of floors until there are no more floors.
|
||||
int count = loaded_surface_get_count();
|
||||
for( int i = 0; i < count; ++i ) {
|
||||
surf = loaded_surface_get_at_index(i);
|
||||
|
||||
|
||||
// Do the check normally done in add_surface_to_cell
|
||||
if( surf->normal.y <= 0.01f ) continue;
|
||||
|
||||
|
||||
x1 = surf->vertex1[0];
|
||||
z1 = surf->vertex1[2];
|
||||
x2 = surf->vertex2[0];
|
||||
z2 = surf->vertex2[2];
|
||||
|
||||
// Check that the point is within the triangle bounds.
|
||||
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// To slightly save on computation time, set this later.
|
||||
x3 = surf->vertex3[0];
|
||||
z3 = surf->vertex3[2];
|
||||
|
||||
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) < 0) {
|
||||
continue;
|
||||
}
|
||||
if ((z3 - z) * (x1 - x3) - (x3 - x) * (z1 - z3) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// // Determine if we are checking for the camera or not.
|
||||
// if (gCheckingSurfaceCollisionsForCamera != 0) {
|
||||
// if (surf->flags & SURFACE_FLAG_NO_CAM_COLLISION) {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// // If we are not checking for the camera, ignore camera only floors.
|
||||
// else if (surf->type == SURFACE_CAMERA_BOUNDARY) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
nx = surf->normal.x;
|
||||
ny = surf->normal.y;
|
||||
nz = surf->normal.z;
|
||||
oo = surf->originOffset;
|
||||
|
||||
// If a wall, ignore it. Likely a remnant, should never occur.
|
||||
if (ny == 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the height of the floor at a given location.
|
||||
height = -(x * nx + nz * z + oo) / ny;
|
||||
// Checks for floor interaction with a 78 unit buffer.
|
||||
if (y - (height + -78.0f) < 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if( height > *pheight )
|
||||
{
|
||||
*pheight = height;
|
||||
floor = surf;
|
||||
}
|
||||
}
|
||||
|
||||
//! (Surface Cucking) Since only the first floor is returned and not the highest,
|
||||
// higher floors can be "cucked" by lower floors.
|
||||
return floor;
|
||||
}
|
||||
|
||||
static s32 find_wall_collisions_from_list( struct WallCollisionData *data) {
|
||||
register struct Surface *surf;
|
||||
register f32 offset;
|
||||
register f32 radius = data->radius;
|
||||
register f32 x = data->x;
|
||||
register f32 y = data->y + data->offsetY;
|
||||
register f32 z = data->z;
|
||||
register f32 px, pz;
|
||||
register f32 w1, w2, w3;
|
||||
register f32 y1, y2, y3;
|
||||
s32 numCols = 0;
|
||||
|
||||
// Max collision radius = 200
|
||||
if (radius > 200.0f) {
|
||||
radius = 200.0f;
|
||||
}
|
||||
|
||||
// Stay in this loop until out of walls.
|
||||
int count = loaded_surface_get_count();
|
||||
for( int i = 0; i < count; ++i ) {
|
||||
surf = loaded_surface_get_at_index(i);
|
||||
|
||||
|
||||
// Do the check normally done in add_surface_to_cell
|
||||
if( surf->normal.y < -0.01f || surf->normal.y > 0.01f ) continue;
|
||||
if( surf->normal.x < -0.707f || surf->normal.x > 0.707f ) {
|
||||
surf->flags |= SURFACE_FLAG_X_PROJECTION;
|
||||
}
|
||||
|
||||
|
||||
// Exclude a large number of walls immediately to optimize.
|
||||
if (y < surf->lowerY || y > surf->upperY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = surf->normal.x * x + surf->normal.y * y + surf->normal.z * z + surf->originOffset;
|
||||
|
||||
if (offset < -radius || offset > radius) {
|
||||
continue;
|
||||
}
|
||||
|
||||
px = x;
|
||||
pz = z;
|
||||
|
||||
//! (Quantum Tunneling) Due to issues with the vertices walls choose and
|
||||
// the fact they are floating point, certain floating point positions
|
||||
// along the seam of two walls may collide with neither wall or both walls.
|
||||
if (surf->flags & SURFACE_FLAG_X_PROJECTION) {
|
||||
w1 = -surf->vertex1[2]; w2 = -surf->vertex2[2]; w3 = -surf->vertex3[2];
|
||||
y1 = surf->vertex1[1]; y2 = surf->vertex2[1]; y3 = surf->vertex3[1];
|
||||
|
||||
if (surf->normal.x > 0.0f) {
|
||||
if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) > 0.0f) {
|
||||
continue;
|
||||
}
|
||||
if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) > 0.0f) {
|
||||
continue;
|
||||
}
|
||||
if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) > 0.0f) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) < 0.0f) {
|
||||
continue;
|
||||
}
|
||||
if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) < 0.0f) {
|
||||
continue;
|
||||
}
|
||||
if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) < 0.0f) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
w1 = surf->vertex1[0]; w2 = surf->vertex2[0]; w3 = surf->vertex3[0];
|
||||
y1 = surf->vertex1[1]; y2 = surf->vertex2[1]; y3 = surf->vertex3[1];
|
||||
|
||||
if (surf->normal.z > 0.0f) {
|
||||
if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) > 0.0f) {
|
||||
continue;
|
||||
}
|
||||
if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) > 0.0f) {
|
||||
continue;
|
||||
}
|
||||
if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) > 0.0f) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) < 0.0f) {
|
||||
continue;
|
||||
}
|
||||
if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) < 0.0f) {
|
||||
continue;
|
||||
}
|
||||
if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) < 0.0f) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if checking for the camera or not.
|
||||
// if (gCheckingSurfaceCollisionsForCamera) {
|
||||
// if (surf->flags & SURFACE_FLAG_NO_CAM_COLLISION) {
|
||||
// continue;
|
||||
// }
|
||||
// } else {
|
||||
// // Ignore camera only surfaces.
|
||||
// if (surf->type == SURFACE_CAMERA_BOUNDARY) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// // If an object can pass through a vanish cap wall, pass through.
|
||||
// if (surf->type == SURFACE_VANISH_CAP_WALLS) {
|
||||
// // If an object can pass through a vanish cap wall, pass through.
|
||||
// if (gCurrentObject != NULL
|
||||
// && (gCurrentObject->activeFlags & ACTIVE_FLAG_MOVE_THROUGH_GRATE)) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// // If Mario has a vanish cap, pass through the vanish cap wall.
|
||||
// if (gCurrentObject != NULL && gCurrentObject == gMarioObject
|
||||
// && (gMarioState->flags & MARIO_VANISH_CAP)) {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//! (Wall Overlaps) Because this doesn't update the x and z local variables,
|
||||
// multiple walls can push mario more than is required.
|
||||
data->x += surf->normal.x * (radius - offset);
|
||||
data->z += surf->normal.z * (radius - offset);
|
||||
|
||||
//! (Unreferenced Walls) Since this only returns the first four walls,
|
||||
// this can lead to wall interaction being missed. Typically unreferenced walls
|
||||
// come from only using one wall, however.
|
||||
if (data->numWalls < 4) {
|
||||
data->walls[data->numWalls++] = surf;
|
||||
}
|
||||
|
||||
numCols++;
|
||||
}
|
||||
|
||||
return numCols;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
s32 f32_find_wall_collision(f32 *xPtr, f32 *yPtr, f32 *zPtr, f32 offsetY, f32 radius)
|
||||
{
|
||||
struct WallCollisionData collision;
|
||||
s32 numCollisions = 0;
|
||||
|
||||
collision.offsetY = offsetY;
|
||||
collision.radius = radius;
|
||||
|
||||
collision.x = *xPtr;
|
||||
collision.y = *yPtr;
|
||||
collision.z = *zPtr;
|
||||
|
||||
collision.numWalls = 0;
|
||||
|
||||
numCollisions = find_wall_collisions(&collision);
|
||||
|
||||
*xPtr = collision.x;
|
||||
*yPtr = collision.y;
|
||||
*zPtr = collision.z;
|
||||
|
||||
return numCollisions;
|
||||
}
|
||||
|
||||
s32 find_wall_collisions(struct WallCollisionData *colData)
|
||||
{
|
||||
s32 numCollisions = 0;
|
||||
s16 x = colData->x;
|
||||
s16 z = colData->z;
|
||||
|
||||
colData->numWalls = 0;
|
||||
|
||||
if (x <= -LEVEL_BOUNDARY_MAX || x >= LEVEL_BOUNDARY_MAX) {
|
||||
return numCollisions;
|
||||
}
|
||||
if (z <= -LEVEL_BOUNDARY_MAX || z >= LEVEL_BOUNDARY_MAX) {
|
||||
return numCollisions;
|
||||
}
|
||||
|
||||
numCollisions += find_wall_collisions_from_list(colData);
|
||||
return numCollisions;
|
||||
}
|
||||
|
||||
f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil)
|
||||
{
|
||||
f32 height = CELL_HEIGHT_LIMIT;
|
||||
*pceil = find_ceil_from_list( posX, posY, posZ, &height );
|
||||
return height;
|
||||
}
|
||||
|
||||
struct FloorGeometry sFloorGeo;
|
||||
|
||||
f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct FloorGeometry **floorGeo)
|
||||
{
|
||||
struct Surface *floor;
|
||||
f32 floorHeight = find_floor(xPos, yPos, zPos, &floor);
|
||||
|
||||
*floorGeo = NULL;
|
||||
|
||||
if (floor != NULL) {
|
||||
sFloorGeo.normalX = floor->normal.x;
|
||||
sFloorGeo.normalY = floor->normal.y;
|
||||
sFloorGeo.normalZ = floor->normal.z;
|
||||
sFloorGeo.originOffset = floor->originOffset;
|
||||
|
||||
*floorGeo = &sFloorGeo;
|
||||
}
|
||||
return floorHeight;
|
||||
}
|
||||
|
||||
f32 find_floor_height(f32 x, f32 y, f32 z)
|
||||
{
|
||||
f32 height = FLOOR_LOWER_LIMIT;
|
||||
find_floor_from_list( x, y, z, &height );
|
||||
return height;
|
||||
}
|
||||
|
||||
f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor)
|
||||
{
|
||||
f32 height = FLOOR_LOWER_LIMIT;
|
||||
*pfloor = find_floor_from_list( xPos, yPos, zPos, &height );
|
||||
return height;
|
||||
}
|
||||
|
||||
f32 find_water_level(f32 x, f32 z)
|
||||
{
|
||||
return -10000.0f;
|
||||
}
|
||||
|
||||
f32 find_poison_gas_level(f32 x, f32 z)
|
||||
{
|
||||
return -10000.0f;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef SURFACE_COLLISION_H
|
||||
#define SURFACE_COLLISION_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
#define LEVEL_BOUNDARY_MAX 0x2000
|
||||
#define CELL_SIZE 0x400
|
||||
|
||||
#define CELL_HEIGHT_LIMIT 20000.f
|
||||
#define FLOOR_LOWER_LIMIT -11000.f
|
||||
|
||||
struct WallCollisionData
|
||||
{
|
||||
/*0x00*/ f32 x, y, z;
|
||||
/*0x0C*/ f32 offsetY;
|
||||
/*0x10*/ f32 radius;
|
||||
/*0x14*/ s16 unk14;
|
||||
/*0x16*/ s16 numWalls;
|
||||
/*0x18*/ struct Surface *walls[4];
|
||||
};
|
||||
|
||||
struct FloorGeometry
|
||||
{
|
||||
f32 unused[4]; // possibly position data?
|
||||
f32 normalX;
|
||||
f32 normalY;
|
||||
f32 normalZ;
|
||||
f32 originOffset;
|
||||
};
|
||||
|
||||
s32 f32_find_wall_collision(f32 *xPtr, f32 *yPtr, f32 *zPtr, f32 offsetY, f32 radius);
|
||||
s32 find_wall_collisions(struct WallCollisionData *colData);
|
||||
f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil);
|
||||
f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct FloorGeometry **floorGeo);
|
||||
f32 find_floor_height(f32 x, f32 y, f32 z);
|
||||
f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor);
|
||||
f32 find_water_level(f32 x, f32 z);
|
||||
f32 find_poison_gas_level(f32 x, f32 z);
|
||||
|
||||
#endif // SURFACE_COLLISION_H
|
||||
@@ -0,0 +1,157 @@
|
||||
#ifndef AREA_H
|
||||
#define AREA_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
#include "camera.h"
|
||||
//#include "engine/graph_node.h"
|
||||
|
||||
struct WarpNode
|
||||
{
|
||||
/*00*/ u8 id;
|
||||
/*01*/ u8 destLevel;
|
||||
/*02*/ u8 destArea;
|
||||
/*03*/ u8 destNode;
|
||||
};
|
||||
|
||||
struct ObjectWarpNode
|
||||
{
|
||||
/*0x00*/ struct WarpNode node;
|
||||
/*0x04*/ struct Object *object;
|
||||
/*0x08*/ struct ObjectWarpNode *next;
|
||||
};
|
||||
|
||||
// From Surface 0x1B to 0x1E
|
||||
#define INSTANT_WARP_INDEX_START 0x00 // Equal and greater than Surface 0x1B
|
||||
#define INSTANT_WARP_INDEX_STOP 0x04 // Less than Surface 0x1F
|
||||
|
||||
struct InstantWarp
|
||||
{
|
||||
/*0x00*/ u8 id; // 0 = 0x1B / 1 = 0x1C / 2 = 0x1D / 3 = 0x1E
|
||||
/*0x01*/ u8 area;
|
||||
/*0x02*/ Vec3s displacement;
|
||||
};
|
||||
|
||||
struct SpawnInfo
|
||||
{
|
||||
/*0x00*/ Vec3s startPos;
|
||||
/*0x06*/ Vec3s startAngle;
|
||||
/*0x0C*/ s8 areaIndex;
|
||||
/*0x0D*/ s8 activeAreaIndex;
|
||||
/*0x10*/ u32 behaviorArg;
|
||||
/*0x14*/ void *behaviorScript;
|
||||
/*0x18*/ struct GraphNode *unk18;
|
||||
/*0x1C*/ struct SpawnInfo *next;
|
||||
};
|
||||
|
||||
struct UnusedArea28
|
||||
{
|
||||
/*0x00*/ s16 unk00;
|
||||
/*0x02*/ s16 unk02;
|
||||
/*0x04*/ s16 unk04;
|
||||
/*0x06*/ s16 unk06;
|
||||
/*0x08*/ s16 unk08;
|
||||
};
|
||||
|
||||
struct Whirlpool
|
||||
{
|
||||
/*0x00*/ Vec3s pos;
|
||||
/*0x03*/ s16 strength;
|
||||
};
|
||||
|
||||
struct Area
|
||||
{
|
||||
/*0x00*/ s8 index;
|
||||
/*0x01*/ s8 flags; // Only has 1 flag: 0x01 = Is this the active area?
|
||||
/*0x02*/ u16 terrainType; // default terrain of the level (set from level script cmd 0x31)
|
||||
/*0x04*/ struct GraphNodeRoot *unk04; // geometry layout data
|
||||
/*0x08*/ s16 *terrainData; // collision data (set from level script cmd 0x2E)
|
||||
/*0x0C*/ s8 *surfaceRooms; // (set from level script cmd 0x2F)
|
||||
/*0x10*/ s16 *macroObjects; // Macro Objects Ptr (set from level script cmd 0x39)
|
||||
/*0x14*/ struct ObjectWarpNode *warpNodes;
|
||||
/*0x18*/ struct WarpNode *paintingWarpNodes;
|
||||
/*0x1C*/ struct InstantWarp *instantWarps;
|
||||
/*0x20*/ struct SpawnInfo *objectSpawnInfos;
|
||||
/*0x24*/ struct Camera *camera;
|
||||
/*0x28*/ struct UnusedArea28 *unused28; // Filled by level script 0x3A, but is unused.
|
||||
/*0x2C*/ struct Whirlpool *whirlpools[2];
|
||||
/*0x34*/ u8 dialog[2]; // Level start dialog number (set by level script cmd 0x30)
|
||||
/*0x36*/ u16 musicParam;
|
||||
/*0x38*/ u16 musicParam2;
|
||||
};
|
||||
|
||||
// All the transition data to be used in screen_transition.c
|
||||
struct WarpTransitionData
|
||||
{
|
||||
/*0x00*/ u8 red;
|
||||
/*0x01*/ u8 green;
|
||||
/*0x02*/ u8 blue;
|
||||
|
||||
/*0x04*/ s16 startTexRadius;
|
||||
/*0x06*/ s16 endTexRadius;
|
||||
/*0x08*/ s16 startTexX;
|
||||
/*0x0A*/ s16 startTexY;
|
||||
/*0x0C*/ s16 endTexX;
|
||||
/*0x0E*/ s16 endTexY;
|
||||
|
||||
/*0x10*/ s16 texTimer; // always 0, does seems to affect transition when disabled
|
||||
};
|
||||
|
||||
#define WARP_TRANSITION_FADE_FROM_COLOR 0x00
|
||||
#define WARP_TRANSITION_FADE_INTO_COLOR 0x01
|
||||
#define WARP_TRANSITION_FADE_FROM_STAR 0x08
|
||||
#define WARP_TRANSITION_FADE_INTO_STAR 0x09
|
||||
#define WARP_TRANSITION_FADE_FROM_CIRCLE 0x0A
|
||||
#define WARP_TRANSITION_FADE_INTO_CIRCLE 0x0B
|
||||
#define WARP_TRANSITION_FADE_FROM_MARIO 0x10
|
||||
#define WARP_TRANSITION_FADE_INTO_MARIO 0x11
|
||||
#define WARP_TRANSITION_FADE_FROM_BOWSER 0x12
|
||||
#define WARP_TRANSITION_FADE_INTO_BOWSER 0x13
|
||||
|
||||
struct WarpTransition
|
||||
{
|
||||
/*0x00*/ u8 isActive; // Is the transition active. (either TRUE or FALSE)
|
||||
/*0x01*/ u8 type; // Determines the type of transition to use (circle, star, etc.)
|
||||
/*0x02*/ u8 time; // Amount of time to complete the transition (in frames)
|
||||
/*0x03*/ u8 pauseRendering; // Should the game stop rendering. (either TRUE or FALSE)
|
||||
/*0x04*/ struct WarpTransitionData data;
|
||||
};
|
||||
|
||||
// extern struct GraphNode **gLoadedGraphNodes;
|
||||
// extern struct SpawnInfo gPlayerSpawnInfos[];
|
||||
// extern struct GraphNode *D_8033A160[];
|
||||
// extern struct Area gAreaData[];
|
||||
// extern struct WarpTransition gWarpTransition;
|
||||
// extern s16 gCurrCourseNum;
|
||||
// extern s16 gCurrActNum;
|
||||
// extern s16 gCurrAreaIndex;
|
||||
// extern s16 gSavedCourseNum;
|
||||
// extern s16 gPauseScreenMode;
|
||||
// extern s16 gSaveOptSelectIndex;
|
||||
//
|
||||
// extern struct SpawnInfo *gMarioSpawnInfo;
|
||||
//
|
||||
// extern struct Area *gAreas;
|
||||
// extern struct Area *gCurrentArea;
|
||||
//
|
||||
// extern s16 gCurrSaveFileNum;
|
||||
// extern s16 gCurrLevelNum;
|
||||
|
||||
// void override_viewport_and_clip(Vp *a, Vp *b, u8 c, u8 d, u8 e);
|
||||
// void print_intro_text(void);
|
||||
// u32 get_mario_spawn_type(struct Object *o);
|
||||
// struct ObjectWarpNode *area_get_warp_node(u8 id);
|
||||
// void clear_areas(void);
|
||||
// void clear_area_graph_nodes(void);
|
||||
// void load_area(s32 index);
|
||||
// void unload_area(void);
|
||||
// void load_mario_area(void);
|
||||
// void unload_mario_area(void);
|
||||
// void change_area(s32 index);
|
||||
// void area_update_objects(void);
|
||||
// void play_transition(s16 transType, s16 time, u8 red, u8 green, u8 blue);
|
||||
// void play_transition_after_delay(s16 transType, s16 time, u8 red, u8 green, u8 blue, s16 delay);
|
||||
// void render_game(void);
|
||||
|
||||
#endif // AREA_H
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "behavior_actions.h"
|
||||
#include "rendering_graph_node.h"
|
||||
#include "../shim.h"
|
||||
|
||||
// not sure what this is doing here. not in a behavior file.
|
||||
Gfx *geo_move_mario_part_from_parent(s32 run, UNUSED struct GraphNode *node, Mat4 mtx) {
|
||||
Mat4 sp20;
|
||||
struct Object *sp1C;
|
||||
|
||||
if (run == TRUE) {
|
||||
sp1C = (struct Object *) gCurGraphNodeObject;
|
||||
if (sp1C == gMarioObject && sp1C->prevObj != NULL) {
|
||||
create_transformation_from_matrices(sp20, mtx, *gCurGraphNodeCamera->matrixPtr);
|
||||
obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj);
|
||||
obj_set_gfx_pos_from_pos(sp1C->prevObj);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../include/types.h"
|
||||
#include "../mario/model.inc.h"
|
||||
|
||||
extern Gfx *geo_move_mario_part_from_parent(s32 run, UNUSED struct GraphNode *node, Mat4 mtx);
|
||||
@@ -0,0 +1,776 @@
|
||||
#ifndef CAMERA_H
|
||||
#define CAMERA_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
#include "area.h"
|
||||
//#include "engine/geo_layout.h"
|
||||
//#include "engine/graph_node.h"
|
||||
|
||||
//#include "level_table.h"
|
||||
|
||||
/**
|
||||
* @file camera.h
|
||||
* Constants, defines, and structs used by the camera system.
|
||||
* @see camera.c
|
||||
*/
|
||||
|
||||
#define ABS(x) ((x) > 0.f ? (x) : -(x))
|
||||
#define ABS2(x) ((x) >= 0.f ? (x) : -(x))
|
||||
|
||||
/**
|
||||
* Converts an angle in degrees to sm64's s16 angle units. For example, DEGREES(90) == 0x4000
|
||||
* This should be used mainly to make camera code clearer at first glance.
|
||||
*/
|
||||
#define DEGREES(x) ((x) * 0x10000 / 360)
|
||||
|
||||
#define LEVEL_AREA_INDEX(levelNum, areaNum) (((levelNum) << 4) + (areaNum))
|
||||
|
||||
/**
|
||||
* Helper macro for defining which areas of a level should zoom out the camera when the game is paused.
|
||||
* Because a mask is used by two levels, the pattern will repeat when more than 4 areas are used by a level.
|
||||
*/
|
||||
#define ZOOMOUT_AREA_MASK(level1Area1, level1Area2, level1Area3, level1Area4, \
|
||||
level2Area1, level2Area2, level2Area3, level2Area4) \
|
||||
((level2Area4) << 7 | \
|
||||
(level2Area3) << 6 | \
|
||||
(level2Area2) << 5 | \
|
||||
(level2Area1) << 4 | \
|
||||
(level1Area4) << 3 | \
|
||||
(level1Area3) << 2 | \
|
||||
(level1Area2) << 1 | \
|
||||
(level1Area1) << 0)
|
||||
|
||||
|
||||
#define AREA_BBH LEVEL_AREA_INDEX(LEVEL_BBH, 1)
|
||||
#define AREA_CCM_OUTSIDE LEVEL_AREA_INDEX(LEVEL_CCM, 1)
|
||||
#define AREA_CCM_SLIDE LEVEL_AREA_INDEX(LEVEL_CCM, 2)
|
||||
#define AREA_CASTLE_LOBBY LEVEL_AREA_INDEX(LEVEL_CASTLE, 1)
|
||||
#define AREA_CASTLE_TIPPY LEVEL_AREA_INDEX(LEVEL_CASTLE, 2)
|
||||
#define AREA_CASTLE_BASEMENT LEVEL_AREA_INDEX(LEVEL_CASTLE, 3)
|
||||
#define AREA_HMC LEVEL_AREA_INDEX(LEVEL_HMC, 1)
|
||||
#define AREA_SSL_OUTSIDE LEVEL_AREA_INDEX(LEVEL_SSL, 1)
|
||||
#define AREA_SSL_PYRAMID LEVEL_AREA_INDEX(LEVEL_SSL, 2)
|
||||
#define AREA_SSL_EYEROK LEVEL_AREA_INDEX(LEVEL_SSL, 3)
|
||||
#define AREA_BOB LEVEL_AREA_INDEX(LEVEL_BOB, 1)
|
||||
#define AREA_SL_OUTSIDE LEVEL_AREA_INDEX(LEVEL_SL, 1)
|
||||
#define AREA_SL_IGLOO LEVEL_AREA_INDEX(LEVEL_SL, 2)
|
||||
#define AREA_WDW_MAIN LEVEL_AREA_INDEX(LEVEL_WDW, 1)
|
||||
#define AREA_WDW_TOWN LEVEL_AREA_INDEX(LEVEL_WDW, 2)
|
||||
#define AREA_JRB_MAIN LEVEL_AREA_INDEX(LEVEL_JRB, 1)
|
||||
#define AREA_JRB_SHIP LEVEL_AREA_INDEX(LEVEL_JRB, 2)
|
||||
#define AREA_THI_HUGE LEVEL_AREA_INDEX(LEVEL_THI, 1)
|
||||
#define AREA_THI_TINY LEVEL_AREA_INDEX(LEVEL_THI, 2)
|
||||
#define AREA_THI_WIGGLER LEVEL_AREA_INDEX(LEVEL_THI, 3)
|
||||
#define AREA_TTC LEVEL_AREA_INDEX(LEVEL_TTC, 1)
|
||||
#define AREA_RR LEVEL_AREA_INDEX(LEVEL_RR, 1)
|
||||
#define AREA_CASTLE_GROUNDS LEVEL_AREA_INDEX(LEVEL_CASTLE_GROUNDS, 1)
|
||||
#define AREA_BITDW LEVEL_AREA_INDEX(LEVEL_BITDW, 1)
|
||||
#define AREA_VCUTM LEVEL_AREA_INDEX(LEVEL_VCUTM, 1)
|
||||
#define AREA_BITFS LEVEL_AREA_INDEX(LEVEL_BITFS, 1)
|
||||
#define AREA_SA LEVEL_AREA_INDEX(LEVEL_SA, 1)
|
||||
#define AREA_BITS LEVEL_AREA_INDEX(LEVEL_BITS, 1)
|
||||
#define AREA_LLL_OUTSIDE LEVEL_AREA_INDEX(LEVEL_LLL, 1)
|
||||
#define AREA_LLL_VOLCANO LEVEL_AREA_INDEX(LEVEL_LLL, 2)
|
||||
#define AREA_DDD_WHIRLPOOL LEVEL_AREA_INDEX(LEVEL_DDD, 1)
|
||||
#define AREA_DDD_SUB LEVEL_AREA_INDEX(LEVEL_DDD, 2)
|
||||
#define AREA_WF LEVEL_AREA_INDEX(LEVEL_WF, 1)
|
||||
#define AREA_ENDING LEVEL_AREA_INDEX(LEVEL_ENDING, 1)
|
||||
#define AREA_COURTYARD LEVEL_AREA_INDEX(LEVEL_CASTLE_COURTYARD, 1)
|
||||
#define AREA_PSS LEVEL_AREA_INDEX(LEVEL_PSS, 1)
|
||||
#define AREA_COTMC LEVEL_AREA_INDEX(LEVEL_COTMC, 1)
|
||||
#define AREA_TOTWC LEVEL_AREA_INDEX(LEVEL_TOTWC, 1)
|
||||
#define AREA_BOWSER_1 LEVEL_AREA_INDEX(LEVEL_BOWSER_1, 1)
|
||||
#define AREA_WMOTR LEVEL_AREA_INDEX(LEVEL_WMOTR, 1)
|
||||
#define AREA_BOWSER_2 LEVEL_AREA_INDEX(LEVEL_BOWSER_2, 1)
|
||||
#define AREA_BOWSER_3 LEVEL_AREA_INDEX(LEVEL_BOWSER_3, 1)
|
||||
#define AREA_TTM_OUTSIDE LEVEL_AREA_INDEX(LEVEL_TTM, 1)
|
||||
|
||||
#define CAM_MODE_MARIO_ACTIVE 0x01
|
||||
#define CAM_MODE_LAKITU_WAS_ZOOMED_OUT 0x02
|
||||
#define CAM_MODE_MARIO_SELECTED 0x04
|
||||
|
||||
#define CAM_SELECTION_MARIO 1
|
||||
#define CAM_SELECTION_FIXED 2
|
||||
|
||||
#define CAM_ANGLE_MARIO 1
|
||||
#define CAM_ANGLE_LAKITU 2
|
||||
|
||||
#define CAMERA_MODE_NONE 0x00
|
||||
#define CAMERA_MODE_RADIAL 0x01
|
||||
#define CAMERA_MODE_OUTWARD_RADIAL 0x02
|
||||
#define CAMERA_MODE_BEHIND_MARIO 0x03
|
||||
#define CAMERA_MODE_CLOSE 0x04 // Inside Castle / Big Boo's Haunt
|
||||
#define CAMERA_MODE_C_UP 0x06
|
||||
#define CAMERA_MODE_WATER_SURFACE 0x08
|
||||
#define CAMERA_MODE_SLIDE_HOOT 0x09
|
||||
#define CAMERA_MODE_INSIDE_CANNON 0x0A
|
||||
#define CAMERA_MODE_BOSS_FIGHT 0x0B
|
||||
#define CAMERA_MODE_PARALLEL_TRACKING 0x0C
|
||||
#define CAMERA_MODE_FIXED 0x0D
|
||||
#define CAMERA_MODE_8_DIRECTIONS 0x0E // AKA Parallel Camera, Bowser Courses & Rainbow Ride
|
||||
#define CAMERA_MODE_FREE_ROAM 0x10
|
||||
#define CAMERA_MODE_SPIRAL_STAIRS 0x11
|
||||
|
||||
#define CAM_MOVE_RETURN_TO_MIDDLE 0x0001
|
||||
#define CAM_MOVE_ZOOMED_OUT 0x0002
|
||||
#define CAM_MOVE_ROTATE_RIGHT 0x0004
|
||||
#define CAM_MOVE_ROTATE_LEFT 0x0008
|
||||
#define CAM_MOVE_ENTERED_ROTATE_SURFACE 0x0010
|
||||
#define CAM_MOVE_METAL_BELOW_WATER 0x0020
|
||||
#define CAM_MOVE_FIX_IN_PLACE 0x0040
|
||||
#define CAM_MOVE_UNKNOWN_8 0x0080
|
||||
#define CAM_MOVING_INTO_MODE 0x0100
|
||||
#define CAM_MOVE_STARTED_EXITING_C_UP 0x0200
|
||||
#define CAM_MOVE_UNKNOWN_11 0x0400
|
||||
#define CAM_MOVE_INIT_CAMERA 0x0800
|
||||
#define CAM_MOVE_ALREADY_ZOOMED_OUT 0x1000
|
||||
#define CAM_MOVE_C_UP_MODE 0x2000
|
||||
#define CAM_MOVE_SUBMERGED 0x4000
|
||||
#define CAM_MOVE_PAUSE_SCREEN 0x8000
|
||||
|
||||
#define CAM_MOVE_ROTATE /**/ (CAM_MOVE_ROTATE_RIGHT | CAM_MOVE_ROTATE_LEFT | CAM_MOVE_RETURN_TO_MIDDLE)
|
||||
/// These flags force the camera to move a certain way
|
||||
#define CAM_MOVE_RESTRICT /**/ (CAM_MOVE_ENTERED_ROTATE_SURFACE | CAM_MOVE_METAL_BELOW_WATER | CAM_MOVE_FIX_IN_PLACE | CAM_MOVE_UNKNOWN_8)
|
||||
|
||||
#define CAM_SOUND_C_UP_PLAYED 0x01
|
||||
#define CAM_SOUND_MARIO_ACTIVE 0x02
|
||||
#define CAM_SOUND_NORMAL_ACTIVE 0x04
|
||||
#define CAM_SOUND_UNUSED_SELECT_MARIO 0x08
|
||||
#define CAM_SOUND_UNUSED_SELECT_FIXED 0x10
|
||||
#define CAM_SOUND_FIXED_ACTIVE 0x20
|
||||
|
||||
#define CAM_FLAG_SMOOTH_MOVEMENT 0x0001
|
||||
#define CAM_FLAG_BLOCK_SMOOTH_MOVEMENT 0x0002
|
||||
#define CAM_FLAG_FRAME_AFTER_CAM_INIT 0x0004
|
||||
#define CAM_FLAG_CHANGED_PARTRACK_INDEX 0x0008
|
||||
#define CAM_FLAG_CCM_SLIDE_SHORTCUT 0x0010
|
||||
#define CAM_FLAG_CAM_NEAR_WALL 0x0020
|
||||
#define CAM_FLAG_SLEEPING 0x0040
|
||||
#define CAM_FLAG_UNUSED_7 0x0080
|
||||
#define CAM_FLAG_UNUSED_8 0x0100
|
||||
#define CAM_FLAG_COLLIDED_WITH_WALL 0x0200
|
||||
#define CAM_FLAG_START_TRANSITION 0x0400
|
||||
#define CAM_FLAG_TRANSITION_OUT_OF_C_UP 0x0800
|
||||
#define CAM_FLAG_BLOCK_AREA_PROCESSING 0x1000
|
||||
#define CAM_FLAG_UNUSED_13 0x2000
|
||||
#define CAM_FLAG_UNUSED_CUTSCENE_ACTIVE 0x4000
|
||||
#define CAM_FLAG_BEHIND_MARIO_POST_DOOR 0x8000
|
||||
|
||||
#define CAM_STATUS_NONE 0
|
||||
#define CAM_STATUS_MARIO 1 << 0
|
||||
#define CAM_STATUS_LAKITU 1 << 1
|
||||
#define CAM_STATUS_FIXED 1 << 2
|
||||
#define CAM_STATUS_C_DOWN 1 << 3
|
||||
#define CAM_STATUS_C_UP 1 << 4
|
||||
|
||||
#define CAM_STATUS_MODE_GROUP (CAM_STATUS_MARIO | CAM_STATUS_LAKITU | CAM_STATUS_FIXED)
|
||||
#define CAM_STATUS_C_MODE_GROUP (CAM_STATUS_C_DOWN | CAM_STATUS_C_UP)
|
||||
|
||||
#define SHAKE_ATTACK 1
|
||||
#define SHAKE_GROUND_POUND 2
|
||||
#define SHAKE_SMALL_DAMAGE 3
|
||||
#define SHAKE_MED_DAMAGE 4
|
||||
#define SHAKE_LARGE_DAMAGE 5
|
||||
#define SHAKE_HIT_FROM_BELOW 8
|
||||
#define SHAKE_FALL_DAMAGE 9
|
||||
#define SHAKE_SHOCK 10
|
||||
|
||||
#define SHAKE_ENV_EXPLOSION 1
|
||||
#define SHAKE_ENV_BOWSER_THROW_BOUNCE 2
|
||||
#define SHAKE_ENV_BOWSER_JUMP 3
|
||||
#define SHAKE_ENV_UNUSED_5 5
|
||||
#define SHAKE_ENV_UNUSED_6 6
|
||||
#define SHAKE_ENV_UNUSED_7 7
|
||||
#define SHAKE_ENV_PYRAMID_EXPLODE 8
|
||||
#define SHAKE_ENV_JRB_SHIP_DRAIN 9
|
||||
#define SHAKE_ENV_FALLING_BITS_PLAT 10
|
||||
|
||||
#define SHAKE_FOV_SMALL 1
|
||||
#define SHAKE_FOV_UNUSED 2
|
||||
#define SHAKE_FOV_MEDIUM 3
|
||||
#define SHAKE_FOV_LARGE 4
|
||||
|
||||
#define SHAKE_POS_SMALL 1
|
||||
#define SHAKE_POS_MEDIUM 2
|
||||
#define SHAKE_POS_LARGE 3
|
||||
#define SHAKE_POS_BOWLING_BALL 4
|
||||
|
||||
#define CUTSCENE_DOOR_PULL 130
|
||||
#define CUTSCENE_DOOR_PUSH 131
|
||||
#define CUTSCENE_ENTER_CANNON 133
|
||||
#define CUTSCENE_ENTER_PAINTING 134
|
||||
#define CUTSCENE_DEATH_EXIT 135
|
||||
#define CUTSCENE_DOOR_WARP 139
|
||||
#define CUTSCENE_DOOR_PULL_MODE 140
|
||||
#define CUTSCENE_DOOR_PUSH_MODE 141
|
||||
#define CUTSCENE_INTRO_PEACH 142
|
||||
#define CUTSCENE_DANCE_ROTATE 143
|
||||
#define CUTSCENE_ENTER_BOWSER_ARENA 144
|
||||
#define CUTSCENE_0F_UNUSED 145 // Never activated, stub cutscene functions
|
||||
#define CUTSCENE_UNUSED_EXIT 147 // Never activated
|
||||
#define CUTSCENE_SLIDING_DOORS_OPEN 149
|
||||
#define CUTSCENE_PREPARE_CANNON 150
|
||||
#define CUTSCENE_UNLOCK_KEY_DOOR 151
|
||||
#define CUTSCENE_STANDING_DEATH 152
|
||||
#define CUTSCENE_DEATH_ON_STOMACH 153
|
||||
#define CUTSCENE_DEATH_ON_BACK 154
|
||||
#define CUTSCENE_QUICKSAND_DEATH 155
|
||||
#define CUTSCENE_SUFFOCATION_DEATH 156
|
||||
#define CUTSCENE_EXIT_BOWSER_SUCC 157
|
||||
#define CUTSCENE_EXIT_BOWSER_DEATH 158 // Never activated
|
||||
#define CUTSCENE_WATER_DEATH 159 // Not in cutscene switch
|
||||
#define CUTSCENE_EXIT_PAINTING_SUCC 160
|
||||
#define CUTSCENE_CAP_SWITCH_PRESS 161
|
||||
#define CUTSCENE_DIALOG 162
|
||||
#define CUTSCENE_RACE_DIALOG 163
|
||||
#define CUTSCENE_ENTER_PYRAMID_TOP 164
|
||||
#define CUTSCENE_DANCE_FLY_AWAY 165
|
||||
#define CUTSCENE_DANCE_CLOSEUP 166
|
||||
#define CUTSCENE_KEY_DANCE 167
|
||||
#define CUTSCENE_SSL_PYRAMID_EXPLODE 168 // Never activated
|
||||
#define CUTSCENE_EXIT_SPECIAL_SUCC 169
|
||||
#define CUTSCENE_NONPAINTING_DEATH 170
|
||||
#define CUTSCENE_READ_MESSAGE 171
|
||||
#define CUTSCENE_ENDING 172
|
||||
#define CUTSCENE_STAR_SPAWN 173
|
||||
#define CUTSCENE_GRAND_STAR 174
|
||||
#define CUTSCENE_DANCE_DEFAULT 175
|
||||
#define CUTSCENE_RED_COIN_STAR_SPAWN 176
|
||||
#define CUTSCENE_END_WAVING 177
|
||||
#define CUTSCENE_CREDITS 178
|
||||
#define CUTSCENE_EXIT_WATERFALL 179
|
||||
#define CUTSCENE_EXIT_FALL_WMOTR 180
|
||||
#define CUTSCENE_ENTER_POOL 181
|
||||
|
||||
/**
|
||||
* Stop the cutscene.
|
||||
*/
|
||||
#define CUTSCENE_STOP 0x8000
|
||||
/**
|
||||
* Play the current cutscene shot indefinitely (until canceled).
|
||||
*/
|
||||
#define CUTSCENE_LOOP 0x7FFF
|
||||
|
||||
#define HAND_CAM_SHAKE_OFF 0
|
||||
#define HAND_CAM_SHAKE_CUTSCENE 1
|
||||
#define HAND_CAM_SHAKE_UNUSED 2
|
||||
#define HAND_CAM_SHAKE_HANG_OWL 3
|
||||
#define HAND_CAM_SHAKE_HIGH 4
|
||||
#define HAND_CAM_SHAKE_STAR_DANCE 5
|
||||
#define HAND_CAM_SHAKE_LOW 6
|
||||
|
||||
#define DOOR_DEFAULT 0
|
||||
#define DOOR_LEAVING_SPECIAL 1
|
||||
#define DOOR_ENTER_LOBBY 2
|
||||
|
||||
// Might rename these to reflect what they are used for instead "SET_45" etc.
|
||||
#define CAM_FOV_SET_45 1
|
||||
#define CAM_FOV_DEFAULT 2
|
||||
#define CAM_FOV_APP_45 4
|
||||
#define CAM_FOV_SET_30 5
|
||||
#define CAM_FOV_APP_20 6
|
||||
#define CAM_FOV_BBH 7
|
||||
#define CAM_FOV_APP_80 9
|
||||
#define CAM_FOV_APP_30 10
|
||||
#define CAM_FOV_APP_60 11
|
||||
#define CAM_FOV_ZOOM_30 12
|
||||
#define CAM_FOV_SET_29 13
|
||||
|
||||
#define CAM_EVENT_CANNON 1
|
||||
#define CAM_EVENT_SHOT_FROM_CANNON 2
|
||||
#define CAM_EVENT_UNUSED_3 3
|
||||
#define CAM_EVENT_BOWSER_INIT 4
|
||||
#define CAM_EVENT_DOOR_WARP 5
|
||||
#define CAM_EVENT_DOOR 6
|
||||
#define CAM_EVENT_BOWSER_JUMP 7
|
||||
#define CAM_EVENT_BOWSER_THROW_BOUNCE 8
|
||||
#define CAM_EVENT_START_INTRO 9
|
||||
#define CAM_EVENT_START_GRAND_STAR 10
|
||||
#define CAM_EVENT_START_ENDING 11
|
||||
#define CAM_EVENT_START_END_WAVING 12
|
||||
#define CAM_EVENT_START_CREDITS 13
|
||||
|
||||
/**
|
||||
* A copy of player information that is relevant to the camera.
|
||||
*/
|
||||
struct PlayerCameraState
|
||||
{
|
||||
/**
|
||||
* Mario's action on this frame.
|
||||
*/
|
||||
/*0x00*/ u32 action;
|
||||
/*0x04*/ Vec3f pos;
|
||||
/*0x10*/ Vec3s faceAngle;
|
||||
/*0x16*/ Vec3s headRotation;
|
||||
/*0x1C*/ s16 unused;
|
||||
/**
|
||||
* Set to nonzero when an event, such as entering a door, starting the credits, or throwing bowser,
|
||||
* has happened on this frame.
|
||||
*/
|
||||
/*0x1E*/ s16 cameraEvent;
|
||||
/*0x20*/ struct Object *usedObj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct containing info that is used when transition_next_state() is called. Stores the intermediate
|
||||
* distances and angular displacements from lakitu's goal position and focus.
|
||||
*/
|
||||
struct TransitionInfo
|
||||
{
|
||||
/*0x00*/ s16 posPitch;
|
||||
/*0x02*/ s16 posYaw;
|
||||
/*0x04*/ f32 posDist;
|
||||
/*0x08*/ s16 focPitch;
|
||||
/*0x0A*/ s16 focYaw;
|
||||
/*0x0C*/ f32 focDist;
|
||||
/*0x10*/ s32 framesLeft;
|
||||
/*0x14*/ Vec3f marioPos;
|
||||
/*0x20*/ u8 pad; // for the structs to align, there has to be an extra unused variable here. type is unknown.
|
||||
};
|
||||
|
||||
/**
|
||||
* A point that's used in a spline, controls the direction to move the camera in
|
||||
* during the shake effect.
|
||||
*/
|
||||
struct HandheldShakePoint
|
||||
{
|
||||
/*0x00*/ s8 index; // only set to -1
|
||||
/*0x04 (aligned)*/ u32 pad;
|
||||
/*0x08*/ Vec3s point;
|
||||
}; // size = 0x10
|
||||
|
||||
struct Camera;
|
||||
|
||||
/**
|
||||
* A function that is called by CameraTriggers and cutscene shots.
|
||||
* These are concurrent: multiple CameraEvents can occur on the same frame.
|
||||
*/
|
||||
typedef BAD_RETURN(s32) (*CameraEvent)(struct Camera *c);
|
||||
/**
|
||||
* The same type as a CameraEvent, but because these are generally longer, and happen in sequential
|
||||
* order, they're are called "shots," a term taken from cinematography.
|
||||
*
|
||||
* To further tell the difference: CutsceneShots usually call multiple CameraEvents at once, but only
|
||||
* one CutsceneShot is ever called on a given frame.
|
||||
*/
|
||||
typedef CameraEvent CutsceneShot;
|
||||
|
||||
/**
|
||||
* Defines a bounding box which activates an event while Mario is inside
|
||||
*/
|
||||
struct CameraTrigger
|
||||
{
|
||||
/**
|
||||
* The area this should be checked in, or -1 if it should run in every area of the level.
|
||||
*
|
||||
* Triggers with area set to -1 are run by default, they don't care if Mario is inside their bounds.
|
||||
* However, they are only active if Mario is not already inside an area-specific trigger's
|
||||
* boundaries.
|
||||
*/
|
||||
s8 area;
|
||||
/// A function that gets called while Mario is in the trigger bounds
|
||||
CameraEvent event;
|
||||
// The (x,y,z) position of the center of the bounding box
|
||||
s16 centerX;
|
||||
s16 centerY;
|
||||
s16 centerZ;
|
||||
// The max displacement in x, y, and z from the center for a point to be considered inside the
|
||||
// bounding box
|
||||
s16 boundsX;
|
||||
s16 boundsY;
|
||||
s16 boundsZ;
|
||||
/// This angle rotates Mario's offset from the box's origin, before it is checked for being inside.
|
||||
s16 boundsYaw;
|
||||
};
|
||||
|
||||
/**
|
||||
* A camera shot that is active for a number of frames.
|
||||
* Together, a sequence of shots makes up a cutscene.
|
||||
*/
|
||||
struct Cutscene
|
||||
{
|
||||
/// The function that gets called.
|
||||
CutsceneShot shot;
|
||||
/// How long the shot lasts.
|
||||
s16 duration;
|
||||
};
|
||||
|
||||
/**
|
||||
* Info for the camera's field of view and the FOV shake effect.
|
||||
*/
|
||||
struct CameraFOVStatus
|
||||
{
|
||||
/// The current function being used to set the camera's field of view (before any fov shake is applied).
|
||||
/*0x00*/ u8 fovFunc;
|
||||
/// The current field of view in degrees
|
||||
/*0x04*/ f32 fov;
|
||||
|
||||
// Fields used by shake_camera_fov()
|
||||
|
||||
/// The amount to change the current fov by in the fov shake effect.
|
||||
/*0x08*/ f32 fovOffset;
|
||||
/// A bool set in fov_default() but unused otherwise
|
||||
/*0x0C*/ u32 unusedIsSleeping;
|
||||
/// The range in degrees to shake fov
|
||||
/*0x10*/ f32 shakeAmplitude;
|
||||
/// Used to calculate fovOffset, the phase through the shake's period.
|
||||
/*0x14*/ s16 shakePhase;
|
||||
/// How much to progress through the shake period
|
||||
/*0x16*/ s16 shakeSpeed;
|
||||
/// How much to decrease shakeAmplitude each frame.
|
||||
/*0x18*/ s16 decay;
|
||||
};
|
||||
|
||||
/**
|
||||
* Information for a control point in a spline segment.
|
||||
*/
|
||||
struct CutsceneSplinePoint
|
||||
{
|
||||
/* The index of this point in the spline. Ignored except for -1, which ends the spline.
|
||||
An index of -1 should come four points after the start of the last segment. */
|
||||
s8 index;
|
||||
/* Roughly controls the number of frames it takes to progress through the spline segment.
|
||||
See move_point_along_spline() in camera.c */
|
||||
u8 speed;
|
||||
Vec3s point;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct containing the nearest floor and ceiling to the player, as well as the previous floor and
|
||||
* ceiling. It also stores their distances from the player's position.
|
||||
*/
|
||||
struct PlayerGeometry
|
||||
{
|
||||
/*0x00*/ struct Surface *currFloor;
|
||||
/*0x04*/ f32 currFloorHeight;
|
||||
/*0x08*/ s16 currFloorType;
|
||||
/*0x0C*/ struct Surface *currCeil;
|
||||
/*0x10*/ s16 currCeilType;
|
||||
/*0x14*/ f32 currCeilHeight;
|
||||
/*0x18*/ struct Surface *prevFloor;
|
||||
/*0x1C*/ f32 prevFloorHeight;
|
||||
/*0x20*/ s16 prevFloorType;
|
||||
/*0x24*/ struct Surface *prevCeil;
|
||||
/*0x28*/ f32 prevCeilHeight;
|
||||
/*0x2C*/ s16 prevCeilType;
|
||||
/// Unused, but recalculated every frame
|
||||
/*0x30*/ f32 waterHeight;
|
||||
};
|
||||
|
||||
/**
|
||||
* Point used in transitioning between camera modes and C-Up.
|
||||
*/
|
||||
struct LinearTransitionPoint
|
||||
{
|
||||
Vec3f focus;
|
||||
Vec3f pos;
|
||||
f32 dist;
|
||||
s16 pitch;
|
||||
s16 yaw;
|
||||
};
|
||||
|
||||
/**
|
||||
* Info about transitioning between camera modes.
|
||||
*/
|
||||
struct ModeTransitionInfo
|
||||
{
|
||||
s16 newMode;
|
||||
s16 lastMode;
|
||||
s16 max;
|
||||
s16 frame;
|
||||
struct LinearTransitionPoint transitionStart;
|
||||
struct LinearTransitionPoint transitionEnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* A point in a path used by update_parallel_tracking_camera
|
||||
*/
|
||||
struct ParallelTrackingPoint
|
||||
{
|
||||
/// Whether this point is the start of a path
|
||||
s16 startOfPath;
|
||||
/// Point used to define a line segment to follow
|
||||
Vec3f pos;
|
||||
/// The distance Mario can move along the line before the camera should move
|
||||
f32 distThresh;
|
||||
/// The percentage that the camera should move from the line to Mario
|
||||
f32 zoom;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores the camera's info
|
||||
*/
|
||||
struct CameraStoredInfo
|
||||
{
|
||||
/*0x00*/ Vec3f pos;
|
||||
/*0x0C*/ Vec3f focus;
|
||||
/*0x18*/ f32 panDist;
|
||||
/*0x1C*/ f32 cannonYOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct used to store cutscene info, like the camera's target position/focus.
|
||||
*
|
||||
* See the sCutsceneVars[] array in camera.c for more details.
|
||||
*/
|
||||
struct CutsceneVariable
|
||||
{
|
||||
/// Perhaps an index
|
||||
s32 unused1;
|
||||
Vec3f point;
|
||||
Vec3f unusedPoint;
|
||||
Vec3s angle;
|
||||
/// Perhaps a boolean or an extra angle
|
||||
s16 unused2;
|
||||
};
|
||||
|
||||
/**
|
||||
* The main camera struct. Gets updated by the active camera mode and the current level/area. In
|
||||
* update_lakitu, its pos and focus are used to calculate lakitu's next position and focus, which are
|
||||
* then used to render the game.
|
||||
*/
|
||||
struct Camera
|
||||
{
|
||||
/*0x00*/ u8 mode; // What type of mode the camera uses (see defines above)
|
||||
/*0x01*/ u8 defMode;
|
||||
/**
|
||||
* Determines what direction Mario moves in when the analog stick is moved.
|
||||
*
|
||||
* @warning This is NOT the camera's xz-rotation in world space. This is the angle calculated from the
|
||||
* camera's focus TO the camera's position, instead of the other way around like it should
|
||||
* be. It's effectively the opposite of the camera's actual yaw. Use
|
||||
* vec3f_get_dist_and_angle() if you need the camera's yaw.
|
||||
*/
|
||||
/*0x02*/ s16 yaw;
|
||||
/*0x04*/ Vec3f focus;
|
||||
/*0x10*/ Vec3f pos;
|
||||
/*0x1C*/ Vec3f unusedVec1;
|
||||
/// The x coordinate of the "center" of the area. The camera will rotate around this point.
|
||||
/// For example, this is what makes the camera rotate around the hill in BoB
|
||||
/*0x28*/ f32 areaCenX;
|
||||
/// The z coordinate of the "center" of the area. The camera will rotate around this point.
|
||||
/// For example, this is what makes the camera rotate around the hill in BoB
|
||||
/*0x2C*/ f32 areaCenZ;
|
||||
/*0x30*/ u8 cutscene;
|
||||
/*0x31*/ u8 filler31[0x8];
|
||||
/*0x3A*/ s16 nextYaw;
|
||||
/*0x3C*/ u8 filler3C[0x28];
|
||||
/*0x64*/ u8 doorStatus;
|
||||
/// The y coordinate of the "center" of the area. Unlike areaCenX and areaCenZ, this is only used
|
||||
/// when paused. See zoom_out_if_paused_and_outside
|
||||
/*0x68*/ f32 areaCenY;
|
||||
};
|
||||
|
||||
/**
|
||||
* A struct containing info pertaining to lakitu, such as his position and focus, and what
|
||||
* camera-related effects are happening to him, like camera shakes.
|
||||
*
|
||||
* This struct's pos and focus are what is actually used to render the game.
|
||||
*
|
||||
* @see update_lakitu()
|
||||
*/
|
||||
struct LakituState
|
||||
{
|
||||
/**
|
||||
* Lakitu's position, which (when CAM_FLAG_SMOOTH_MOVEMENT is set), approaches his goalPos every frame.
|
||||
*/
|
||||
/*0x00*/ Vec3f curFocus;
|
||||
/**
|
||||
* Lakitu's focus, which (when CAM_FLAG_SMOOTH_MOVEMENT is set), approaches his goalFocus every frame.
|
||||
*/
|
||||
/*0x0C*/ Vec3f curPos;
|
||||
/**
|
||||
* The focus point that lakitu turns towards every frame.
|
||||
* If CAM_FLAG_SMOOTH_MOVEMENT is unset, this is the same as curFocus.
|
||||
*/
|
||||
/*0x18*/ Vec3f goalFocus;
|
||||
/**
|
||||
* The point that lakitu flies towards every frame.
|
||||
* If CAM_FLAG_SMOOTH_MOVEMENT is unset, this is the same as curPos.
|
||||
*/
|
||||
/*0x24*/ Vec3f goalPos;
|
||||
|
||||
/*0x30*/ u8 filler30[12]; // extra unused Vec3f?
|
||||
|
||||
/// Copy of the active camera mode
|
||||
/*0x3C*/ u8 mode;
|
||||
/// Copy of the default camera mode
|
||||
/*0x3D*/ u8 defMode;
|
||||
|
||||
/*0x3E*/ u8 filler3E[10];
|
||||
|
||||
/*0x48*/ f32 focusDistance; // unused
|
||||
/*0x4C*/ s16 oldPitch; // unused
|
||||
/*0x4E*/ s16 oldYaw; // unused
|
||||
/*0x50*/ s16 oldRoll; // unused
|
||||
|
||||
/// The angular offsets added to lakitu's pitch, yaw, and roll
|
||||
/*0x52*/ Vec3s shakeMagnitude;
|
||||
|
||||
// shake pitch, yaw, and roll phase: The progression through the camera shake (a cosine wave).
|
||||
// shake pitch, yaw, and roll vel: The speed of the camera shake.
|
||||
// shake pitch, yaw, and roll decay: The shake's deceleration.
|
||||
/*0x58*/ s16 shakePitchPhase;
|
||||
/*0x5A*/ s16 shakePitchVel;
|
||||
/*0x5C*/ s16 shakePitchDecay;
|
||||
|
||||
/*0x60*/ Vec3f unusedVec1;
|
||||
/*0x6C*/ Vec3s unusedVec2;
|
||||
/*0x72*/ u8 filler72[8];
|
||||
|
||||
/// Used to rotate the screen when rendering.
|
||||
/*0x7A*/ s16 roll;
|
||||
/// Copy of the camera's yaw.
|
||||
/*0x7C*/ s16 yaw;
|
||||
/// Copy of the camera's next yaw.
|
||||
/*0x7E*/ s16 nextYaw;
|
||||
/// The actual focus point the game uses to render.
|
||||
/*0x80*/ Vec3f focus;
|
||||
/// The actual position the game is rendered from.
|
||||
/*0x8C*/ Vec3f pos;
|
||||
|
||||
// Shake variables: See above description
|
||||
/*0x98*/ s16 shakeRollPhase;
|
||||
/*0x9A*/ s16 shakeRollVel;
|
||||
/*0x9C*/ s16 shakeRollDecay;
|
||||
/*0x9E*/ s16 shakeYawPhase;
|
||||
/*0xA0*/ s16 shakeYawVel;
|
||||
/*0xA2*/ s16 shakeYawDecay;
|
||||
|
||||
// focH,Vspeed: how fast lakitu turns towards his goalFocus.
|
||||
/// By default HSpeed is 0.8, so lakitu turns 80% of the horz distance to his goal each frame.
|
||||
/*0xA4*/ f32 focHSpeed;
|
||||
/// By default VSpeed is 0.3, so lakitu turns 30% of the vert distance to his goal each frame.
|
||||
/*0xA8*/ f32 focVSpeed;
|
||||
|
||||
// posH,Vspeed: How fast lakitu flies towards his goalPos.
|
||||
/// By default they are 0.3, so lakitu will fly 30% of the way towards his goal each frame.
|
||||
/*0xAC*/ f32 posHSpeed;
|
||||
/*0xB0*/ f32 posVSpeed;
|
||||
|
||||
/// The roll offset applied during part of the key dance cutscene
|
||||
/*0xB4*/ s16 keyDanceRoll;
|
||||
/// Mario's action from the previous frame. Only used to determine if Mario just finished a dive.
|
||||
/*0xB8*/ u32 lastFrameAction;
|
||||
/*0xBC*/ s16 unused;
|
||||
};
|
||||
|
||||
|
||||
// // bss order hack to not affect BSS order. if possible, remove me, but it will be hard to match otherwise
|
||||
// #ifndef INCLUDED_FROM_CAMERA_C
|
||||
// // BSS
|
||||
// extern s16 sSelectionFlags;
|
||||
// extern s16 sCameraSoundFlags;
|
||||
// extern u16 sCButtonsPressed;
|
||||
// extern struct PlayerCameraState gPlayerCameraState[2];
|
||||
// extern struct LakituState gLakituState;
|
||||
// extern s16 gCameraMovementFlags;
|
||||
// extern s32 gObjCutsceneDone;
|
||||
// extern struct Camera *gCamera;
|
||||
// #endif
|
||||
//
|
||||
// extern struct Object *gCutsceneFocus;
|
||||
// extern struct Object *gSecondCameraFocus;
|
||||
// extern u8 gRecentCutscene;
|
||||
//
|
||||
// // TODO: sort all of this extremely messy shit out after the split
|
||||
//
|
||||
// void set_camera_shake_from_hit(s16 shake);
|
||||
// void set_environmental_camera_shake(s16 shake);
|
||||
// void set_camera_shake_from_point(s16 shake, f32 posX, f32 posY, f32 posZ);
|
||||
// void move_mario_head_c_up(UNUSED struct Camera *c);
|
||||
// void transition_next_state(UNUSED struct Camera *c, s16 frames);
|
||||
// void set_camera_mode(struct Camera *c, s16 mode, s16 frames);
|
||||
// void update_camera(struct Camera *c);
|
||||
// void reset_camera(struct Camera *c);
|
||||
// void init_camera(struct Camera *c);
|
||||
// void select_mario_cam_mode(void);
|
||||
// Gfx *geo_camera_main(s32 callContext, struct GraphNode *g, void *context);
|
||||
// void stub_camera_2(UNUSED struct Camera *c);
|
||||
// void stub_camera_3(UNUSED struct Camera *c);
|
||||
// void vec3f_sub(Vec3f dst, Vec3f src);
|
||||
// void object_pos_to_vec3f(Vec3f dst, struct Object *o);
|
||||
// void vec3f_to_object_pos(struct Object *o, Vec3f src);
|
||||
// s32 move_point_along_spline(Vec3f p, struct CutsceneSplinePoint spline[], s16 *splineSegment, f32 *progress);
|
||||
// s32 cam_select_alt_mode(s32 angle);
|
||||
// s32 set_cam_angle(s32 mode);
|
||||
// void set_handheld_shake(u8 mode);
|
||||
// void shake_camera_handheld(Vec3f pos, Vec3f focus);
|
||||
// s32 find_c_buttons_pressed(u16 currentState, u16 buttonsPressed, u16 buttonsDown);
|
||||
// s32 update_camera_hud_status(struct Camera *c);
|
||||
// s32 collide_with_walls(Vec3f pos, f32 offsetY, f32 radius);
|
||||
// s32 clamp_pitch(Vec3f from, Vec3f to, s16 maxPitch, s16 minPitch);
|
||||
// s32 is_within_100_units_of_mario(f32 posX, f32 posY, f32 posZ);
|
||||
// s32 set_or_approach_f32_asymptotic(f32 *dst, f32 goal, f32 scale);
|
||||
// s32 approach_f32_asymptotic_bool(f32 *current, f32 target, f32 multiplier);
|
||||
// f32 approach_f32_asymptotic(f32 current, f32 target, f32 multiplier);
|
||||
// s32 approach_s16_asymptotic_bool(s16 *current, s16 target, s16 divisor);
|
||||
// s32 approach_s16_asymptotic(s16 current, s16 target, s16 divisor);
|
||||
// void approach_vec3f_asymptotic(Vec3f current, Vec3f target, f32 xMul, f32 yMul, f32 zMul);
|
||||
// void set_or_approach_vec3f_asymptotic(Vec3f dst, Vec3f goal, f32 xMul, f32 yMul, f32 zMul);
|
||||
// s32 camera_approach_s16_symmetric_bool(s16 *current, s16 target, s16 increment);
|
||||
// s32 set_or_approach_s16_symmetric(s16 *current, s16 target, s16 increment);
|
||||
// s32 camera_approach_f32_symmetric_bool(f32 *current, f32 target, f32 increment);
|
||||
// f32 camera_approach_f32_symmetric(f32 value, f32 target, f32 increment);
|
||||
// void random_vec3s(Vec3s dst, s16 xRange, s16 yRange, s16 zRange);
|
||||
// s32 clamp_positions_and_find_yaw(Vec3f pos, Vec3f origin, f32 xMax, f32 xMin, f32 zMax, f32 zMin);
|
||||
// s32 is_range_behind_surface(Vec3f from, Vec3f to, struct Surface *surf, s16 range, s16 surfType);
|
||||
// void scale_along_line(Vec3f dest, Vec3f from, Vec3f to, f32 scale);
|
||||
// s16 calculate_pitch(Vec3f from, Vec3f to);
|
||||
// s16 calculate_yaw(Vec3f from, Vec3f to);
|
||||
// void calculate_angles(Vec3f from, Vec3f to, s16 *pitch, s16 *yaw);
|
||||
// f32 calc_abs_dist(Vec3f a, Vec3f b);
|
||||
// f32 calc_hor_dist(Vec3f a, Vec3f b);
|
||||
// void rotate_in_xz(Vec3f dst, Vec3f src, s16 yaw);
|
||||
// void rotate_in_yz(Vec3f dst, Vec3f src, s16 pitch);
|
||||
// void set_camera_pitch_shake(s16 mag, s16 decay, s16 inc);
|
||||
// void set_camera_yaw_shake(s16 mag, s16 decay, s16 inc);
|
||||
// void set_camera_roll_shake(s16 mag, s16 decay, s16 inc);
|
||||
// void set_pitch_shake_from_point(s16 mag, s16 decay, s16 inc, f32 maxDist, f32 posX, f32 posY, f32 posZ);
|
||||
// void shake_camera_pitch(Vec3f pos, Vec3f focus);
|
||||
// void shake_camera_yaw(Vec3f pos, Vec3f focus);
|
||||
// void shake_camera_roll(s16 *roll);
|
||||
// s32 offset_yaw_outward_radial(struct Camera *c, s16 areaYaw);
|
||||
// void play_camera_buzz_if_cdown(void);
|
||||
// void play_camera_buzz_if_cbutton(void);
|
||||
// void play_camera_buzz_if_c_sideways(void);
|
||||
// void play_sound_cbutton_up(void);
|
||||
// void play_sound_cbutton_down(void);
|
||||
// void play_sound_cbutton_side(void);
|
||||
// void play_sound_button_change_blocked(void);
|
||||
// void play_sound_rbutton_changed(void);
|
||||
// void play_sound_if_cam_switched_to_lakitu_or_mario(void);
|
||||
// s32 radial_camera_input(struct Camera *c, UNUSED f32 unused);
|
||||
// s32 trigger_cutscene_dialog(s32 trigger);
|
||||
// void handle_c_button_movement(struct Camera *c);
|
||||
// void start_cutscene(struct Camera *c, u8 cutscene);
|
||||
// u8 get_cutscene_from_mario_status(struct Camera *c);
|
||||
// void warp_camera(f32 displacementX, f32 displacementY, f32 displacementZ);
|
||||
// void approach_camera_height(struct Camera *c, f32 goal, f32 inc);
|
||||
// void offset_rotated(Vec3f dst, Vec3f from, Vec3f to, Vec3s rotation);
|
||||
// s16 next_lakitu_state(Vec3f newPos, Vec3f newFoc, Vec3f curPos, Vec3f curFoc, Vec3f oldPos, Vec3f oldFoc, s16 yaw);
|
||||
// void set_fixed_cam_axis_sa_lobby(UNUSED s16 preset);
|
||||
// s16 camera_course_processing(struct Camera *c);
|
||||
// void resolve_geometry_collisions(Vec3f pos, UNUSED Vec3f lastGood);
|
||||
// s32 rotate_camera_around_walls(struct Camera *c, Vec3f cPos, s16 *avoidYaw, s16 yawRange);
|
||||
// void find_mario_floor_and_ceil(struct PlayerGeometry *pg);
|
||||
// u8 start_object_cutscene_without_focus(u8 cutscene);
|
||||
// s16 cutscene_object_with_dialog(u8 cutscene, struct Object *o, s16 dialogID);
|
||||
// s16 cutscene_object_without_dialog(u8 cutscene, struct Object *o);
|
||||
// s16 cutscene_object(u8 cutscene, struct Object *o);
|
||||
// void play_cutscene(struct Camera *c);
|
||||
// s32 cutscene_event(CameraEvent event, struct Camera * c, s16 start, s16 end);
|
||||
// s32 cutscene_spawn_obj(u32 obj, s16 frame);
|
||||
// void set_fov_shake(s16 amplitude, s16 decay, s16 shakeSpeed);
|
||||
//
|
||||
// void set_fov_function(u8 func);
|
||||
// void cutscene_set_fov_shake_preset(u8 preset);
|
||||
// void set_fov_shake_from_point_preset(u8 preset, f32 posX, f32 posY, f32 posZ);
|
||||
// void obj_rotate_towards_point(struct Object *o, Vec3f point, s16 pitchOff, s16 yawOff, s16 pitchDiv, s16 yawDiv);
|
||||
//
|
||||
// Gfx *geo_camera_fov(s32 callContext, struct GraphNode *g, UNUSED void *context);
|
||||
//
|
||||
|
||||
#endif // CAMERA_H
|
||||
@@ -0,0 +1,928 @@
|
||||
// HEAVILY EDITED === Specific interaction functions removed
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
#include "../shim.h"
|
||||
|
||||
#include "area.h"
|
||||
//#include "actors/common1.h"
|
||||
//#include "audio/external.h"
|
||||
//#include "behavior_actions.h"
|
||||
//#include "behavior_data.h"
|
||||
#include "camera.h"
|
||||
//#include "course_table.h"
|
||||
//#include "dialog_ids.h"
|
||||
#include "../engine/math_util.h"
|
||||
#include "../engine/surface_collision.h"
|
||||
//#include "game_init.h"
|
||||
#include "interaction.h"
|
||||
#include "level_update.h"
|
||||
#include "mario.h"
|
||||
#include "mario_step.h"
|
||||
#include "memory.h"
|
||||
//#include "obj_behaviors.h"
|
||||
//#include "object_helpers.h"
|
||||
#include "save_file.h"
|
||||
//#include "seq_ids.h"
|
||||
#include "../include/sm64.h"
|
||||
//#include "sound_init.h"
|
||||
//#include "thread6.h"
|
||||
#include "../include/mario_animation_ids.h"
|
||||
#include "../include/object_fields.h"
|
||||
#include "../include/mario_geo_switch_case_ids.h"
|
||||
|
||||
#define INT_GROUND_POUND_OR_TWIRL (1 << 0) // 0x01
|
||||
#define INT_PUNCH (1 << 1) // 0x02
|
||||
#define INT_KICK (1 << 2) // 0x04
|
||||
#define INT_TRIP (1 << 3) // 0x08
|
||||
#define INT_SLIDE_KICK (1 << 4) // 0x10
|
||||
#define INT_FAST_ATTACK_OR_SHELL (1 << 5) // 0x20
|
||||
#define INT_HIT_FROM_ABOVE (1 << 6) // 0x40
|
||||
#define INT_HIT_FROM_BELOW (1 << 7) // 0x80
|
||||
|
||||
#define INT_ATTACK_NOT_FROM_BELOW \
|
||||
(INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_SLIDE_KICK \
|
||||
| INT_FAST_ATTACK_OR_SHELL | INT_HIT_FROM_ABOVE)
|
||||
|
||||
#define INT_ANY_ATTACK \
|
||||
(INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_SLIDE_KICK \
|
||||
| INT_FAST_ATTACK_OR_SHELL | INT_HIT_FROM_ABOVE | INT_HIT_FROM_BELOW)
|
||||
|
||||
#define INT_ATTACK_NOT_WEAK_FROM_ABOVE \
|
||||
(INT_GROUND_POUND_OR_TWIRL | INT_PUNCH | INT_KICK | INT_TRIP | INT_HIT_FROM_BELOW)
|
||||
|
||||
u8 sDelayInvincTimer;
|
||||
s16 sInvulnerable;
|
||||
|
||||
struct InteractionHandler {
|
||||
u32 interactType;
|
||||
u32 (*handler)(struct MarioState *, u32, struct Object *);
|
||||
};
|
||||
|
||||
static struct InteractionHandler sInteractionHandlers[] = { };
|
||||
|
||||
static u32 sForwardKnockbackActions[][3] = {
|
||||
{ ACT_SOFT_FORWARD_GROUND_KB, ACT_FORWARD_GROUND_KB, ACT_HARD_FORWARD_GROUND_KB },
|
||||
{ ACT_FORWARD_AIR_KB, ACT_FORWARD_AIR_KB, ACT_HARD_FORWARD_AIR_KB },
|
||||
{ ACT_FORWARD_WATER_KB, ACT_FORWARD_WATER_KB, ACT_FORWARD_WATER_KB },
|
||||
};
|
||||
|
||||
static u32 sBackwardKnockbackActions[][3] = {
|
||||
{ ACT_SOFT_BACKWARD_GROUND_KB, ACT_BACKWARD_GROUND_KB, ACT_HARD_BACKWARD_GROUND_KB },
|
||||
{ ACT_BACKWARD_AIR_KB, ACT_BACKWARD_AIR_KB, ACT_HARD_BACKWARD_AIR_KB },
|
||||
{ ACT_BACKWARD_WATER_KB, ACT_BACKWARD_WATER_KB, ACT_BACKWARD_WATER_KB },
|
||||
};
|
||||
|
||||
static u8 sDisplayingDoorText = FALSE;
|
||||
static u8 sJustTeleported = FALSE;
|
||||
static u8 sPssSlideStarted = FALSE;
|
||||
|
||||
/**
|
||||
* Returns the type of cap Mario is wearing.
|
||||
*/
|
||||
u32 get_mario_cap_flag(struct Object *capObject) {
|
||||
|
||||
return MARIO_NORMAL_CAP;
|
||||
|
||||
// const BehaviorScript *script = virtual_to_segmented(0x13, capObject->behavior);
|
||||
// if (script == bhvNormalCap) {
|
||||
// return MARIO_NORMAL_CAP;
|
||||
// } else if (script == bhvMetalCap) {
|
||||
// return MARIO_METAL_CAP;
|
||||
// } else if (script == bhvWingCap) {
|
||||
// return MARIO_WING_CAP;
|
||||
// } else if (script == bhvVanishCap) {
|
||||
// return MARIO_VANISH_CAP;
|
||||
// }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the passed in object has a moving angle yaw
|
||||
* in the angular range given towards Mario.
|
||||
*/
|
||||
u32 object_facing_mario(struct MarioState *m, struct Object *o, s16 angleRange) {
|
||||
f32 dx = m->pos[0] - o->oPosX;
|
||||
f32 dz = m->pos[2] - o->oPosZ;
|
||||
|
||||
s16 angleToMario = atan2s(dz, dx);
|
||||
s16 dAngle = angleToMario - o->oMoveAngleYaw;
|
||||
|
||||
if (-angleRange <= dAngle && dAngle <= angleRange) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s16 mario_obj_angle_to_object(struct MarioState *m, struct Object *o) {
|
||||
f32 dx = o->oPosX - m->pos[0];
|
||||
f32 dz = o->oPosZ - m->pos[2];
|
||||
|
||||
return atan2s(dz, dx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines Mario's interaction with a given object depending on their proximity,
|
||||
* action, speed, and position.
|
||||
*/
|
||||
u32 determine_interaction(struct MarioState *m, struct Object *o) {
|
||||
u32 interaction = 0;
|
||||
u32 action = m->action;
|
||||
|
||||
if (action & ACT_FLAG_ATTACKING) {
|
||||
if (action == ACT_PUNCHING || action == ACT_MOVE_PUNCHING || action == ACT_JUMP_KICK) {
|
||||
s16 dYawToObject = mario_obj_angle_to_object(m, o) - m->faceAngle[1];
|
||||
|
||||
if (m->flags & MARIO_PUNCHING) {
|
||||
// 120 degrees total, or 60 each way
|
||||
if (-0x2AAA <= dYawToObject && dYawToObject <= 0x2AAA) {
|
||||
interaction = INT_PUNCH;
|
||||
}
|
||||
}
|
||||
if (m->flags & MARIO_KICKING) {
|
||||
// 120 degrees total, or 60 each way
|
||||
if (-0x2AAA <= dYawToObject && dYawToObject <= 0x2AAA) {
|
||||
interaction = INT_KICK;
|
||||
}
|
||||
}
|
||||
if (m->flags & MARIO_TRIPPING) {
|
||||
// 180 degrees total, or 90 each way
|
||||
if (-0x4000 <= dYawToObject && dYawToObject <= 0x4000) {
|
||||
interaction = INT_TRIP;
|
||||
}
|
||||
}
|
||||
} else if (action == ACT_GROUND_POUND || action == ACT_TWIRLING) {
|
||||
if (m->vel[1] < 0.0f) {
|
||||
interaction = INT_GROUND_POUND_OR_TWIRL;
|
||||
}
|
||||
} else if (action == ACT_GROUND_POUND_LAND || action == ACT_TWIRL_LAND) {
|
||||
// Neither ground pounding nor twirling change Mario's vertical speed on landing.,
|
||||
// so the speed check is nearly always true (perhaps not if you land while going upwards?)
|
||||
// Additionally, actionState it set on each first thing in their action, so this is
|
||||
// only true prior to the very first frame (i.e. active 1 frame prior to it run).
|
||||
if (m->vel[1] < 0.0f && m->actionState == 0) {
|
||||
interaction = INT_GROUND_POUND_OR_TWIRL;
|
||||
}
|
||||
} else if (action == ACT_SLIDE_KICK || action == ACT_SLIDE_KICK_SLIDE) {
|
||||
interaction = INT_SLIDE_KICK;
|
||||
} else if (action & ACT_FLAG_RIDING_SHELL) {
|
||||
interaction = INT_FAST_ATTACK_OR_SHELL;
|
||||
} else if (m->forwardVel <= -26.0f || 26.0f <= m->forwardVel) {
|
||||
interaction = INT_FAST_ATTACK_OR_SHELL;
|
||||
}
|
||||
}
|
||||
|
||||
// Prior to this, the interaction type could be overwritten. This requires, however,
|
||||
// that the interaction not be set prior. This specifically overrides turning a ground
|
||||
// pound into just a bounce.
|
||||
if (interaction == 0 && (action & ACT_FLAG_AIR)) {
|
||||
if (m->vel[1] < 0.0f) {
|
||||
if (m->pos[1] > o->oPosY) {
|
||||
interaction = INT_HIT_FROM_ABOVE;
|
||||
}
|
||||
} else {
|
||||
if (m->pos[1] < o->oPosY) {
|
||||
interaction = INT_HIT_FROM_BELOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return interaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interaction types for INT_STATUS_INTERACTED, INT_STATUS_WAS_ATTACKED
|
||||
*/
|
||||
u32 attack_object(struct Object *o, s32 interaction) {
|
||||
u32 attackType = 0;
|
||||
|
||||
switch (interaction) {
|
||||
case INT_GROUND_POUND_OR_TWIRL:
|
||||
attackType = ATTACK_GROUND_POUND_OR_TWIRL;
|
||||
break;
|
||||
case INT_PUNCH:
|
||||
attackType = ATTACK_PUNCH;
|
||||
break;
|
||||
case INT_KICK:
|
||||
case INT_TRIP:
|
||||
attackType = ATTACK_KICK_OR_TRIP;
|
||||
break;
|
||||
case INT_SLIDE_KICK:
|
||||
case INT_FAST_ATTACK_OR_SHELL:
|
||||
attackType = ATTACK_FAST_ATTACK;
|
||||
break;
|
||||
case INT_HIT_FROM_ABOVE:
|
||||
attackType = ATTACK_FROM_ABOVE;
|
||||
break;
|
||||
case INT_HIT_FROM_BELOW:
|
||||
attackType = ATTACK_FROM_BELOW;
|
||||
break;
|
||||
}
|
||||
|
||||
o->oInteractStatus = attackType + (INT_STATUS_INTERACTED | INT_STATUS_WAS_ATTACKED);
|
||||
return attackType;
|
||||
}
|
||||
|
||||
void mario_stop_riding_object(struct MarioState *m) {
|
||||
if (m->riddenObj != NULL) {
|
||||
m->riddenObj->oInteractStatus = INT_STATUS_STOP_RIDING;
|
||||
stop_shell_music();
|
||||
m->riddenObj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void mario_grab_used_object(struct MarioState *m) {
|
||||
if (m->heldObj == NULL) {
|
||||
m->heldObj = m->usedObj;
|
||||
// obj_set_held_state(m->heldObj, bhvCarrySomething3);
|
||||
}
|
||||
}
|
||||
|
||||
void mario_drop_held_object(struct MarioState *m) {
|
||||
if (m->heldObj != NULL) {
|
||||
// if (m->heldObj->behavior == segmented_to_virtual(bhvKoopaShellUnderwater)) {
|
||||
// stop_shell_music();
|
||||
// }
|
||||
|
||||
// obj_set_held_state(m->heldObj, bhvCarrySomething4);
|
||||
|
||||
// ! When dropping an object instead of throwing it, it will be put at Mario's
|
||||
// y-positon instead of the HOLP's y-position. This fact is often exploited when
|
||||
// cloning objects.
|
||||
m->heldObj->oPosX = m->marioBodyState->heldObjLastPosition[0];
|
||||
m->heldObj->oPosY = m->pos[1];
|
||||
m->heldObj->oPosZ = m->marioBodyState->heldObjLastPosition[2];
|
||||
|
||||
m->heldObj->oMoveAngleYaw = m->faceAngle[1];
|
||||
|
||||
m->heldObj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void mario_throw_held_object(struct MarioState *m) {
|
||||
if (m->heldObj != NULL) {
|
||||
// if (m->heldObj->behavior == segmented_to_virtual(bhvKoopaShellUnderwater)) {
|
||||
// stop_shell_music();
|
||||
// }
|
||||
|
||||
// obj_set_held_state(m->heldObj, bhvCarrySomething5);
|
||||
|
||||
m->heldObj->oPosX = m->marioBodyState->heldObjLastPosition[0] + 32.0f * sins(m->faceAngle[1]);
|
||||
m->heldObj->oPosY = m->marioBodyState->heldObjLastPosition[1];
|
||||
m->heldObj->oPosZ = m->marioBodyState->heldObjLastPosition[2] + 32.0f * coss(m->faceAngle[1]);
|
||||
|
||||
m->heldObj->oMoveAngleYaw = m->faceAngle[1];
|
||||
|
||||
m->heldObj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void mario_stop_riding_and_holding(struct MarioState *m) {
|
||||
mario_drop_held_object(m);
|
||||
mario_stop_riding_object(m);
|
||||
|
||||
if (m->action == ACT_RIDING_HOOT) {
|
||||
m->usedObj->oInteractStatus = 0;
|
||||
m->usedObj->oHootMarioReleaseTime = gGlobalTimer;
|
||||
}
|
||||
}
|
||||
|
||||
u32 does_mario_have_normal_cap_on_head(struct MarioState *m) {
|
||||
return (m->flags & (MARIO_CAPS | MARIO_CAP_ON_HEAD)) == (MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD);
|
||||
}
|
||||
|
||||
void mario_blow_off_cap(struct MarioState *m, f32 capSpeed) {
|
||||
// struct Object *capObject;
|
||||
|
||||
// if (does_mario_have_normal_cap_on_head(m)) {
|
||||
// save_file_set_cap_pos(m->pos[0], m->pos[1], m->pos[2]);
|
||||
|
||||
// m->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD);
|
||||
|
||||
// capObject = spawn_object(m->marioObj, MODEL_MARIOS_CAP, bhvNormalCap);
|
||||
|
||||
// capObject->oPosY += (m->action & ACT_FLAG_SHORT_HITBOX) ? 120.0f : 180.0f;
|
||||
// capObject->oForwardVel = capSpeed;
|
||||
// capObject->oMoveAngleYaw = (s16)(m->faceAngle[1] + 0x400);
|
||||
|
||||
// if (m->forwardVel < 0.0f) {
|
||||
// capObject->oMoveAngleYaw = (s16)(capObject->oMoveAngleYaw + 0x8000);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
u32 mario_lose_cap_to_enemy(u32 arg) {
|
||||
u32 wasWearingCap = FALSE;
|
||||
|
||||
if (does_mario_have_normal_cap_on_head(gMarioState)) {
|
||||
save_file_set_flags(arg == 1 ? SAVE_FLAG_CAP_ON_KLEPTO : SAVE_FLAG_CAP_ON_UKIKI);
|
||||
gMarioState->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD);
|
||||
wasWearingCap = TRUE;
|
||||
}
|
||||
|
||||
return wasWearingCap;
|
||||
}
|
||||
|
||||
void mario_retrieve_cap(void) {
|
||||
mario_drop_held_object(gMarioState);
|
||||
save_file_clear_flags(SAVE_FLAG_CAP_ON_KLEPTO | SAVE_FLAG_CAP_ON_UKIKI);
|
||||
gMarioState->flags &= ~MARIO_CAP_ON_HEAD;
|
||||
gMarioState->flags |= MARIO_NORMAL_CAP | MARIO_CAP_IN_HAND;
|
||||
}
|
||||
|
||||
u32 able_to_grab_object(struct MarioState *m, UNUSED struct Object *o) {
|
||||
u32 action = m->action;
|
||||
|
||||
if (action == ACT_DIVE_SLIDE || action == ACT_DIVE) {
|
||||
if (!(o->oInteractionSubtype & INT_SUBTYPE_GRABS_MARIO)) {
|
||||
return TRUE;
|
||||
}
|
||||
} else if (action == ACT_PUNCHING || action == ACT_MOVE_PUNCHING) {
|
||||
if (m->actionArg < 2) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct Object *mario_get_collided_object(struct MarioState *m, u32 interactType) {
|
||||
s32 i;
|
||||
struct Object *object;
|
||||
|
||||
for (i = 0; i < m->marioObj->numCollidedObjs; i++) {
|
||||
object = m->marioObj->collidedObjs[i];
|
||||
|
||||
if (object->oInteractType == interactType) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u32 mario_check_object_grab(struct MarioState *m) {
|
||||
u32 result = FALSE;
|
||||
const BehaviorScript *script;
|
||||
|
||||
if (m->input & INPUT_INTERACT_OBJ_GRABBABLE) {
|
||||
script = virtual_to_segmented(0x13, m->interactObj->behavior);
|
||||
|
||||
// if (script == bhvBowser) {
|
||||
// s16 facingDYaw = m->faceAngle[1] - m->interactObj->oMoveAngleYaw;
|
||||
// if (facingDYaw >= -0x5555 && facingDYaw <= 0x5555) {
|
||||
// m->faceAngle[1] = m->interactObj->oMoveAngleYaw;
|
||||
// m->usedObj = m->interactObj;
|
||||
// result = set_mario_action(m, ACT_PICKING_UP_BOWSER, 0);
|
||||
// }
|
||||
// } else {
|
||||
s16 facingDYaw = mario_obj_angle_to_object(m, m->interactObj) - m->faceAngle[1];
|
||||
if (facingDYaw >= -0x2AAA && facingDYaw <= 0x2AAA) {
|
||||
m->usedObj = m->interactObj;
|
||||
|
||||
if (!(m->action & ACT_FLAG_AIR)) {
|
||||
set_mario_action(
|
||||
m, (m->action & ACT_FLAG_DIVING) ? ACT_DIVE_PICKING_UP : ACT_PICKING_UP, 0);
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 bully_knock_back_mario(struct MarioState *mario) {
|
||||
struct BullyCollisionData marioData;
|
||||
struct BullyCollisionData bullyData;
|
||||
s16 newMarioYaw;
|
||||
s16 newBullyYaw;
|
||||
s16 marioDYaw;
|
||||
UNUSED s16 bullyDYaw;
|
||||
|
||||
u32 bonkAction = 0;
|
||||
|
||||
struct Object *bully = mario->interactObj;
|
||||
|
||||
//! Conversion ratios multiply to more than 1 (could allow unbounded speed
|
||||
// with bonk cancel - but this isn't important for regular bully battery)
|
||||
f32 bullyToMarioRatio = bully->hitboxRadius * 3 / 53;
|
||||
f32 marioToBullyRatio = 53.0f / bully->hitboxRadius;
|
||||
|
||||
init_bully_collision_data(&marioData, mario->pos[0], mario->pos[2], mario->forwardVel,
|
||||
mario->faceAngle[1], bullyToMarioRatio, 52.0f);
|
||||
|
||||
init_bully_collision_data(&bullyData, bully->oPosX, bully->oPosZ, bully->oForwardVel,
|
||||
bully->oMoveAngleYaw, marioToBullyRatio, bully->hitboxRadius + 2.0f);
|
||||
|
||||
if (mario->forwardVel != 0.0f) {
|
||||
transfer_bully_speed(&marioData, &bullyData);
|
||||
} else {
|
||||
transfer_bully_speed(&bullyData, &marioData);
|
||||
}
|
||||
|
||||
newMarioYaw = atan2s(marioData.velZ, marioData.velX);
|
||||
newBullyYaw = atan2s(bullyData.velZ, bullyData.velX);
|
||||
|
||||
marioDYaw = newMarioYaw - mario->faceAngle[1];
|
||||
bullyDYaw = newBullyYaw - bully->oMoveAngleYaw;
|
||||
|
||||
mario->faceAngle[1] = newMarioYaw;
|
||||
mario->forwardVel = sqrtf(marioData.velX * marioData.velX + marioData.velZ * marioData.velZ);
|
||||
mario->pos[0] = marioData.posX;
|
||||
mario->pos[2] = marioData.posZ;
|
||||
|
||||
bully->oMoveAngleYaw = newBullyYaw;
|
||||
bully->oForwardVel = sqrtf(bullyData.velX * bullyData.velX + bullyData.velZ * bullyData.velZ);
|
||||
bully->oPosX = bullyData.posX;
|
||||
bully->oPosZ = bullyData.posZ;
|
||||
|
||||
if (marioDYaw < -0x4000 || marioDYaw > 0x4000) {
|
||||
mario->faceAngle[1] += 0x8000;
|
||||
mario->forwardVel *= -1.0f;
|
||||
|
||||
if (mario->action & ACT_FLAG_AIR) {
|
||||
bonkAction = ACT_BACKWARD_AIR_KB;
|
||||
} else {
|
||||
bonkAction = ACT_SOFT_BACKWARD_GROUND_KB;
|
||||
}
|
||||
} else {
|
||||
if (mario->action & ACT_FLAG_AIR) {
|
||||
bonkAction = ACT_FORWARD_AIR_KB;
|
||||
} else {
|
||||
bonkAction = ACT_SOFT_FORWARD_GROUND_KB;
|
||||
}
|
||||
}
|
||||
|
||||
return bonkAction;
|
||||
}
|
||||
|
||||
void bounce_off_object(struct MarioState *m, struct Object *o, f32 velY) {
|
||||
m->pos[1] = o->oPosY + o->hitboxHeight;
|
||||
m->vel[1] = velY;
|
||||
|
||||
m->flags &= ~MARIO_UNKNOWN_08;
|
||||
|
||||
play_sound(SOUND_ACTION_BOUNCE_OFF_OBJECT, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
|
||||
void hit_object_from_below(struct MarioState *m, UNUSED struct Object *o) {
|
||||
m->vel[1] = 0.0f;
|
||||
set_camera_shake_from_hit(SHAKE_HIT_FROM_BELOW);
|
||||
}
|
||||
|
||||
static u32 unused_determine_knockback_action(struct MarioState *m) {
|
||||
u32 bonkAction;
|
||||
s16 angleToObject = mario_obj_angle_to_object(m, m->interactObj);
|
||||
s16 facingDYaw = angleToObject - m->faceAngle[1];
|
||||
|
||||
if (m->forwardVel < 16.0f) {
|
||||
m->forwardVel = 16.0f;
|
||||
}
|
||||
|
||||
m->faceAngle[1] = angleToObject;
|
||||
|
||||
if (facingDYaw >= -0x4000 && facingDYaw <= 0x4000) {
|
||||
m->forwardVel *= -1.0f;
|
||||
if (m->action & (ACT_FLAG_AIR | ACT_FLAG_ON_POLE | ACT_FLAG_HANGING)) {
|
||||
bonkAction = ACT_BACKWARD_AIR_KB;
|
||||
} else {
|
||||
bonkAction = ACT_SOFT_BACKWARD_GROUND_KB;
|
||||
}
|
||||
} else {
|
||||
m->faceAngle[1] += 0x8000;
|
||||
if (m->action & (ACT_FLAG_AIR | ACT_FLAG_ON_POLE | ACT_FLAG_HANGING)) {
|
||||
bonkAction = ACT_FORWARD_AIR_KB;
|
||||
} else {
|
||||
bonkAction = ACT_SOFT_FORWARD_GROUND_KB;
|
||||
}
|
||||
}
|
||||
|
||||
return bonkAction;
|
||||
}
|
||||
|
||||
u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
|
||||
u32 bonkAction;
|
||||
|
||||
s16 terrainIndex = 0; // 1 = air, 2 = water, 0 = default
|
||||
s16 strengthIndex = 0;
|
||||
|
||||
s16 angleToObject = mario_obj_angle_to_object(m, m->interactObj);
|
||||
s16 facingDYaw = angleToObject - m->faceAngle[1];
|
||||
s16 remainingHealth = m->health - 0x40 * m->hurtCounter;
|
||||
|
||||
if (m->action & (ACT_FLAG_SWIMMING | ACT_FLAG_METAL_WATER)) {
|
||||
terrainIndex = 2;
|
||||
} else if (m->action & (ACT_FLAG_AIR | ACT_FLAG_ON_POLE | ACT_FLAG_HANGING)) {
|
||||
terrainIndex = 1;
|
||||
}
|
||||
|
||||
if (remainingHealth < 0x100) {
|
||||
strengthIndex = 2;
|
||||
} else if (m->interactObj->oDamageOrCoinValue >= 4) {
|
||||
strengthIndex = 2;
|
||||
} else if (m->interactObj->oDamageOrCoinValue >= 2) {
|
||||
strengthIndex = 1;
|
||||
}
|
||||
|
||||
m->faceAngle[1] = angleToObject;
|
||||
|
||||
if (terrainIndex == 2) {
|
||||
if (m->forwardVel < 28.0f) {
|
||||
mario_set_forward_vel(m, 28.0f);
|
||||
}
|
||||
|
||||
if (m->pos[1] >= m->interactObj->oPosY) {
|
||||
if (m->vel[1] < 20.0f) {
|
||||
m->vel[1] = 20.0f;
|
||||
}
|
||||
} else {
|
||||
if (m->vel[1] > 0.0f) {
|
||||
m->vel[1] = 0.0f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m->forwardVel < 16.0f) {
|
||||
mario_set_forward_vel(m, 16.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (-0x4000 <= facingDYaw && facingDYaw <= 0x4000) {
|
||||
m->forwardVel *= -1.0f;
|
||||
bonkAction = sBackwardKnockbackActions[terrainIndex][strengthIndex];
|
||||
} else {
|
||||
m->faceAngle[1] += 0x8000;
|
||||
bonkAction = sForwardKnockbackActions[terrainIndex][strengthIndex];
|
||||
}
|
||||
|
||||
return bonkAction;
|
||||
}
|
||||
|
||||
void push_mario_out_of_object(struct MarioState *m, struct Object *o, f32 padding) {
|
||||
f32 minDistance = o->hitboxRadius + m->marioObj->hitboxRadius + padding;
|
||||
|
||||
f32 offsetX = m->pos[0] - o->oPosX;
|
||||
f32 offsetZ = m->pos[2] - o->oPosZ;
|
||||
f32 distance = sqrtf(offsetX * offsetX + offsetZ * offsetZ);
|
||||
|
||||
if (distance < minDistance) {
|
||||
struct Surface *floor;
|
||||
s16 pushAngle;
|
||||
f32 newMarioX;
|
||||
f32 newMarioZ;
|
||||
|
||||
if (distance == 0.0f) {
|
||||
pushAngle = m->faceAngle[1];
|
||||
} else {
|
||||
pushAngle = atan2s(offsetZ, offsetX);
|
||||
}
|
||||
|
||||
newMarioX = o->oPosX + minDistance * sins(pushAngle);
|
||||
newMarioZ = o->oPosZ + minDistance * coss(pushAngle);
|
||||
|
||||
f32_find_wall_collision(&newMarioX, &m->pos[1], &newMarioZ, 60.0f, 50.0f);
|
||||
|
||||
find_floor(newMarioX, m->pos[1], newMarioZ, &floor);
|
||||
if (floor != NULL) {
|
||||
//! Doesn't update Mario's referenced floor (allows oob death when
|
||||
// an object pushes you into a steep slope while in a ground action)
|
||||
m->pos[0] = newMarioX;
|
||||
m->pos[2] = newMarioZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bounce_back_from_attack(struct MarioState *m, u32 interaction) {
|
||||
if (interaction & (INT_PUNCH | INT_KICK | INT_TRIP)) {
|
||||
if (m->action == ACT_PUNCHING) {
|
||||
m->action = ACT_MOVE_PUNCHING;
|
||||
}
|
||||
|
||||
if (m->action & ACT_FLAG_AIR) {
|
||||
mario_set_forward_vel(m, -16.0f);
|
||||
} else {
|
||||
mario_set_forward_vel(m, -48.0f);
|
||||
}
|
||||
|
||||
set_camera_shake_from_hit(SHAKE_ATTACK);
|
||||
m->particleFlags |= PARTICLE_TRIANGLE;
|
||||
}
|
||||
|
||||
if (interaction & (INT_PUNCH | INT_KICK | INT_TRIP | INT_FAST_ATTACK_OR_SHELL)) {
|
||||
play_sound(SOUND_ACTION_HIT_2, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
}
|
||||
|
||||
u32 should_push_or_pull_door(struct MarioState *m, struct Object *o) {
|
||||
f32 dx = o->oPosX - m->pos[0];
|
||||
f32 dz = o->oPosZ - m->pos[2];
|
||||
|
||||
s16 dYaw = o->oMoveAngleYaw - atan2s(dz, dx);
|
||||
|
||||
return (dYaw >= -0x4000 && dYaw <= 0x4000) ? 0x00000001 : 0x00000002;
|
||||
}
|
||||
|
||||
u32 take_damage_from_interact_object(struct MarioState *m) {
|
||||
s32 shake;
|
||||
s32 damage = m->interactObj->oDamageOrCoinValue;
|
||||
|
||||
if (damage >= 4) {
|
||||
shake = SHAKE_LARGE_DAMAGE;
|
||||
} else if (damage >= 2) {
|
||||
shake = SHAKE_MED_DAMAGE;
|
||||
} else {
|
||||
shake = SHAKE_SMALL_DAMAGE;
|
||||
}
|
||||
|
||||
if (!(m->flags & MARIO_CAP_ON_HEAD)) {
|
||||
damage += (damage + 1) / 2;
|
||||
}
|
||||
|
||||
if (m->flags & MARIO_METAL_CAP) {
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
m->hurtCounter += 4 * damage;
|
||||
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
set_camera_shake_from_hit(shake);
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
u32 take_damage_and_knock_back(struct MarioState *m, struct Object *o) {
|
||||
u32 damage;
|
||||
|
||||
if (!sInvulnerable && !(m->flags & MARIO_VANISH_CAP)
|
||||
&& !(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) {
|
||||
o->oInteractStatus = INT_STATUS_INTERACTED | INT_STATUS_ATTACKED_MARIO;
|
||||
m->interactObj = o;
|
||||
|
||||
damage = take_damage_from_interact_object(m);
|
||||
|
||||
if (o->oInteractionSubtype & INT_SUBTYPE_BIG_KNOCKBACK) {
|
||||
m->forwardVel = 40.0f;
|
||||
}
|
||||
|
||||
if (o->oDamageOrCoinValue > 0) {
|
||||
play_sound(SOUND_MARIO_ATTACKED, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
|
||||
update_mario_sound_and_camera(m);
|
||||
return drop_and_set_mario_action(m, determine_knockback_action(m, o->oDamageOrCoinValue),
|
||||
damage);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void reset_mario_pitch(struct MarioState *m) {
|
||||
if (m->action == ACT_WATER_JUMP || m->action == ACT_SHOT_FROM_CANNON || m->action == ACT_FLYING) {
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
m->faceAngle[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if ((!(m->action & (ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ATTACKING)) || !sInvulnerable)
|
||||
&& (o->oInteractionSubtype & INT_SUBTYPE_GRABS_MARIO)) {
|
||||
if (object_facing_mario(m, o, 0x2AAA)) {
|
||||
mario_stop_riding_and_holding(m);
|
||||
o->oInteractStatus = INT_STATUS_INTERACTED | INT_STATUS_GRABBED_MARIO;
|
||||
|
||||
m->faceAngle[1] = o->oMoveAngleYaw;
|
||||
m->interactObj = o;
|
||||
m->usedObj = o;
|
||||
|
||||
update_mario_sound_and_camera(m);
|
||||
play_sound(SOUND_MARIO_OOOF, m->marioObj->header.gfx.cameraToObject);
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
return set_mario_action(m, ACT_GRABBED, 0);
|
||||
}
|
||||
}
|
||||
|
||||
push_mario_out_of_object(m, o, -5.0f);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
u32 mario_can_talk(struct MarioState *m, u32 arg) {
|
||||
s16 val6;
|
||||
|
||||
if ((m->action & ACT_FLAG_IDLE) != 0x00000000) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (m->action == ACT_WALKING) {
|
||||
if (arg) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
val6 = m->marioObj->header.gfx.animInfo.animID;
|
||||
|
||||
if (val6 == 0x0080 || val6 == 0x007F || val6 == 0x006C) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef VERSION_JP
|
||||
#define READ_MASK (INPUT_B_PRESSED)
|
||||
#else
|
||||
#define READ_MASK (INPUT_B_PRESSED | INPUT_A_PRESSED)
|
||||
#endif
|
||||
|
||||
#ifdef VERSION_JP
|
||||
#define SIGN_RANGE 0x38E3
|
||||
#else
|
||||
#define SIGN_RANGE 0x4000
|
||||
#endif
|
||||
|
||||
u32 check_read_sign(struct MarioState *m, struct Object *o) {
|
||||
if ((m->input & READ_MASK) && mario_can_talk(m, 0) && object_facing_mario(m, o, SIGN_RANGE)) {
|
||||
s16 facingDYaw = (s16)(o->oMoveAngleYaw + 0x8000) - m->faceAngle[1];
|
||||
if (facingDYaw >= -SIGN_RANGE && facingDYaw <= SIGN_RANGE) {
|
||||
f32 targetX = o->oPosX + 105.0f * sins(o->oMoveAngleYaw);
|
||||
f32 targetZ = o->oPosZ + 105.0f * coss(o->oMoveAngleYaw);
|
||||
|
||||
m->marioObj->oMarioReadingSignDYaw = facingDYaw;
|
||||
m->marioObj->oMarioReadingSignDPosX = targetX - m->pos[0];
|
||||
m->marioObj->oMarioReadingSignDPosZ = targetZ - m->pos[2];
|
||||
|
||||
m->interactObj = o;
|
||||
m->usedObj = o;
|
||||
return set_mario_action(m, ACT_READING_SIGN, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
u32 check_npc_talk(struct MarioState *m, struct Object *o) {
|
||||
if ((m->input & READ_MASK) && mario_can_talk(m, 1)) {
|
||||
s16 facingDYaw = mario_obj_angle_to_object(m, o) - m->faceAngle[1];
|
||||
if (facingDYaw >= -0x4000 && facingDYaw <= 0x4000) {
|
||||
o->oInteractStatus = INT_STATUS_INTERACTED;
|
||||
|
||||
m->interactObj = o;
|
||||
m->usedObj = o;
|
||||
|
||||
push_mario_out_of_object(m, o, -10.0f);
|
||||
return set_mario_action(m, ACT_WAITING_FOR_DIALOG, 0);
|
||||
}
|
||||
}
|
||||
|
||||
push_mario_out_of_object(m, o, -10.0f);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void check_kick_or_punch_wall(struct MarioState *m) {
|
||||
if (m->flags & (MARIO_PUNCHING | MARIO_KICKING | MARIO_TRIPPING)) {
|
||||
Vec3f detector;
|
||||
detector[0] = m->pos[0] + 50.0f * sins(m->faceAngle[1]);
|
||||
detector[2] = m->pos[2] + 50.0f * coss(m->faceAngle[1]);
|
||||
detector[1] = m->pos[1];
|
||||
|
||||
if (resolve_and_return_wall_collisions(detector, 80.0f, 5.0f) != NULL) {
|
||||
if (m->action != ACT_MOVE_PUNCHING || m->forwardVel >= 0.0f) {
|
||||
if (m->action == ACT_PUNCHING) {
|
||||
m->action = ACT_MOVE_PUNCHING;
|
||||
}
|
||||
|
||||
mario_set_forward_vel(m, -48.0f);
|
||||
play_sound(SOUND_ACTION_HIT_2, m->marioObj->header.gfx.cameraToObject);
|
||||
m->particleFlags |= PARTICLE_TRIANGLE;
|
||||
} else if (m->action & ACT_FLAG_AIR) {
|
||||
mario_set_forward_vel(m, -16.0f);
|
||||
play_sound(SOUND_ACTION_HIT_2, m->marioObj->header.gfx.cameraToObject);
|
||||
m->particleFlags |= PARTICLE_TRIANGLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mario_process_interactions(struct MarioState *m) {
|
||||
sDelayInvincTimer = FALSE;
|
||||
sInvulnerable = (m->action & ACT_FLAG_INVULNERABLE) || m->invincTimer != 0;
|
||||
|
||||
if (!(m->action & ACT_FLAG_INTANGIBLE) && m->collidedObjInteractTypes != 0) {
|
||||
s32 i;
|
||||
for (i = 0; i < 31; i++) {
|
||||
u32 interactType = sInteractionHandlers[i].interactType;
|
||||
if (m->collidedObjInteractTypes & interactType) {
|
||||
struct Object *object = mario_get_collided_object(m, interactType);
|
||||
|
||||
m->collidedObjInteractTypes &= ~interactType;
|
||||
|
||||
if (!(object->oInteractStatus & INT_STATUS_INTERACTED)) {
|
||||
if (sInteractionHandlers[i].handler(m, interactType, object)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m->invincTimer > 0 && !sDelayInvincTimer) {
|
||||
m->invincTimer -= 1;
|
||||
}
|
||||
|
||||
//! If the kick/punch flags are set and an object collision changes Mario's
|
||||
// action, he will get the kick/punch wall speed anyway.
|
||||
check_kick_or_punch_wall(m);
|
||||
m->flags &= ~MARIO_PUNCHING & ~MARIO_KICKING & ~MARIO_TRIPPING;
|
||||
|
||||
if (!(m->marioObj->collidedObjInteractTypes & (INTERACT_WARP_DOOR | INTERACT_DOOR))) {
|
||||
sDisplayingDoorText = FALSE;
|
||||
}
|
||||
if (!(m->marioObj->collidedObjInteractTypes & INTERACT_WARP)) {
|
||||
sJustTeleported = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void check_death_barrier(struct MarioState *m) {
|
||||
if (m->pos[1] < m->floorHeight + 2048.0f) {
|
||||
if (level_trigger_warp(m, WARP_OP_WARP_FLOOR) == 20 && !(m->flags & MARIO_UNKNOWN_18)) {
|
||||
play_sound(SOUND_MARIO_WAAAOOOW, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void check_lava_boost(struct MarioState *m) {
|
||||
if (!(m->action & ACT_FLAG_RIDING_SHELL) && m->pos[1] < m->floorHeight + 10.0f) {
|
||||
if (!(m->flags & MARIO_METAL_CAP)) {
|
||||
m->hurtCounter += (m->flags & MARIO_CAP_ON_HEAD) ? 12 : 18;
|
||||
}
|
||||
|
||||
update_mario_sound_and_camera(m);
|
||||
drop_and_set_mario_action(m, ACT_LAVA_BOOST, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void pss_begin_slide(UNUSED struct MarioState *m) {
|
||||
// if (!(gHudDisplay.flags & HUD_DISPLAY_FLAG_TIMER)) {
|
||||
// level_control_timer(TIMER_CONTROL_SHOW);
|
||||
// level_control_timer(TIMER_CONTROL_START);
|
||||
// sPssSlideStarted = TRUE;
|
||||
// }
|
||||
}
|
||||
|
||||
void pss_end_slide(struct MarioState *m) {
|
||||
//! This flag isn't set on death or level entry, allowing double star spawn
|
||||
if (sPssSlideStarted) {
|
||||
u16 slideTime = level_control_timer(TIMER_CONTROL_STOP);
|
||||
if (slideTime < 630) {
|
||||
m->marioObj->oBehParams = (1 << 24);
|
||||
spawn_default_star(-6358.0f, -4300.0f, 4700.0f);
|
||||
}
|
||||
sPssSlideStarted = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void mario_handle_special_floors(struct MarioState *m) {
|
||||
if ((m->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m->floor != NULL) {
|
||||
s32 floorType = m->floor->type;
|
||||
|
||||
switch (floorType) {
|
||||
case SURFACE_DEATH_PLANE:
|
||||
case SURFACE_VERTICAL_WIND:
|
||||
check_death_barrier(m);
|
||||
break;
|
||||
|
||||
case SURFACE_WARP:
|
||||
level_trigger_warp(m, WARP_OP_WARP_FLOOR);
|
||||
break;
|
||||
|
||||
case SURFACE_TIMER_START:
|
||||
pss_begin_slide(m);
|
||||
break;
|
||||
|
||||
case SURFACE_TIMER_END:
|
||||
pss_end_slide(m);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(m->action & ACT_FLAG_AIR) && !(m->action & ACT_FLAG_SWIMMING)) {
|
||||
switch (floorType) {
|
||||
case SURFACE_BURNING:
|
||||
check_lava_boost(m);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
#ifndef INTERACTION_H
|
||||
#define INTERACTION_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
#define INTERACT_HOOT /* 0x00000001 */ (1 << 0)
|
||||
#define INTERACT_GRABBABLE /* 0x00000002 */ (1 << 1)
|
||||
#define INTERACT_DOOR /* 0x00000004 */ (1 << 2)
|
||||
#define INTERACT_DAMAGE /* 0x00000008 */ (1 << 3)
|
||||
#define INTERACT_COIN /* 0x00000010 */ (1 << 4)
|
||||
#define INTERACT_CAP /* 0x00000020 */ (1 << 5)
|
||||
#define INTERACT_POLE /* 0x00000040 */ (1 << 6)
|
||||
#define INTERACT_KOOPA /* 0x00000080 */ (1 << 7)
|
||||
#define INTERACT_UNKNOWN_08 /* 0x00000100 */ (1 << 8)
|
||||
#define INTERACT_BREAKABLE /* 0x00000200 */ (1 << 9)
|
||||
#define INTERACT_STRONG_WIND /* 0x00000400 */ (1 << 10)
|
||||
#define INTERACT_WARP_DOOR /* 0x00000800 */ (1 << 11)
|
||||
#define INTERACT_STAR_OR_KEY /* 0x00001000 */ (1 << 12)
|
||||
#define INTERACT_WARP /* 0x00002000 */ (1 << 13)
|
||||
#define INTERACT_CANNON_BASE /* 0x00004000 */ (1 << 14)
|
||||
#define INTERACT_BOUNCE_TOP /* 0x00008000 */ (1 << 15)
|
||||
#define INTERACT_WATER_RING /* 0x00010000 */ (1 << 16)
|
||||
#define INTERACT_BULLY /* 0x00020000 */ (1 << 17)
|
||||
#define INTERACT_FLAME /* 0x00040000 */ (1 << 18)
|
||||
#define INTERACT_KOOPA_SHELL /* 0x00080000 */ (1 << 19)
|
||||
#define INTERACT_BOUNCE_TOP2 /* 0x00100000 */ (1 << 20)
|
||||
#define INTERACT_MR_BLIZZARD /* 0x00200000 */ (1 << 21)
|
||||
#define INTERACT_HIT_FROM_BELOW /* 0x00400000 */ (1 << 22)
|
||||
#define INTERACT_TEXT /* 0x00800000 */ (1 << 23)
|
||||
#define INTERACT_TORNADO /* 0x01000000 */ (1 << 24)
|
||||
#define INTERACT_WHIRLPOOL /* 0x02000000 */ (1 << 25)
|
||||
#define INTERACT_CLAM_OR_BUBBA /* 0x04000000 */ (1 << 26)
|
||||
#define INTERACT_BBH_ENTRANCE /* 0x08000000 */ (1 << 27)
|
||||
#define INTERACT_SNUFIT_BULLET /* 0x10000000 */ (1 << 28)
|
||||
#define INTERACT_SHOCK /* 0x20000000 */ (1 << 29)
|
||||
#define INTERACT_IGLOO_BARRIER /* 0x40000000 */ (1 << 30)
|
||||
#define INTERACT_UNKNOWN_31 /* 0x80000000 */ (1 << 31)
|
||||
|
||||
|
||||
// INTERACT_WARP
|
||||
#define INT_SUBTYPE_FADING_WARP 0x00000001
|
||||
|
||||
// Damaging interactions
|
||||
#define INT_SUBTYPE_DELAY_INVINCIBILITY 0x00000002
|
||||
#define INT_SUBTYPE_BIG_KNOCKBACK 0x00000008 /* Used by Bowser, sets Mario's forward velocity to 40 on hit */
|
||||
|
||||
// INTERACT_GRABBABLE
|
||||
#define INT_SUBTYPE_GRABS_MARIO 0x00000004 /* Also makes the object heavy */
|
||||
#define INT_SUBTYPE_HOLDABLE_NPC 0x00000010 /* Allows the object to be gently dropped, and sets vertical speed to 0 when dropped with no forwards velocity */
|
||||
#define INT_SUBTYPE_DROP_IMMEDIATELY 0x00000040 /* This gets set by grabbable NPCs that talk to Mario to make him drop them after the dialog is finished */
|
||||
#define INT_SUBTYPE_KICKABLE 0x00000100
|
||||
#define INT_SUBTYPE_NOT_GRABBABLE 0x00000200 /* Used by Heavy-Ho to allow it to throw Mario, without Mario being able to pick it up */
|
||||
|
||||
// INTERACT_DOOR
|
||||
#define INT_SUBTYPE_STAR_DOOR 0x00000020
|
||||
|
||||
//INTERACT_BOUNCE_TOP
|
||||
#define INT_SUBTYPE_TWIRL_BOUNCE 0x00000080
|
||||
|
||||
// INTERACT_STAR_OR_KEY
|
||||
#define INT_SUBTYPE_NO_EXIT 0x00000400
|
||||
#define INT_SUBTYPE_GRAND_STAR 0x00000800
|
||||
|
||||
// INTERACT_TEXT
|
||||
#define INT_SUBTYPE_SIGN 0x00001000
|
||||
#define INT_SUBTYPE_NPC 0x00004000
|
||||
|
||||
// INTERACT_CLAM_OR_BUBBA
|
||||
#define INT_SUBTYPE_EATS_MARIO 0x00002000
|
||||
|
||||
|
||||
#define ATTACK_PUNCH 1
|
||||
#define ATTACK_KICK_OR_TRIP 2
|
||||
#define ATTACK_FROM_ABOVE 3
|
||||
#define ATTACK_GROUND_POUND_OR_TWIRL 4
|
||||
#define ATTACK_FAST_ATTACK 5
|
||||
#define ATTACK_FROM_BELOW 6
|
||||
|
||||
#define INT_STATUS_ATTACK_MASK 0x000000FF
|
||||
|
||||
#define INT_STATUS_HOOT_GRABBED_BY_MARIO (1 << 0) /* 0x00000001 */
|
||||
#define INT_STATUS_MARIO_UNK1 (1 << 1) /* 0x00000002 */
|
||||
#define INT_STATUS_MARIO_UNK2 (1 << 2) /* 0x00000004 */
|
||||
#define INT_STATUS_MARIO_DROP_OBJECT (1 << 3) /* 0x00000008 */
|
||||
#define INT_STATUS_HIT_BY_SHOCKWAVE (1 << 4) /* 0x00000010 */
|
||||
#define INT_STATUS_MARIO_UNK5 (1 << 5) /* 0x00000020 */
|
||||
#define INT_STATUS_MARIO_UNK6 (1 << 6) /* 0x00000040 */
|
||||
#define INT_STATUS_MARIO_UNK7 (1 << 7) /* 0x00000080 */
|
||||
#define INT_STATUS_GRABBED_MARIO (1 << 11) /* 0x00000800 */
|
||||
#define INT_STATUS_ATTACKED_MARIO (1 << 13) /* 0x00002000 */
|
||||
#define INT_STATUS_WAS_ATTACKED (1 << 14) /* 0x00004000 */
|
||||
#define INT_STATUS_INTERACTED (1 << 15) /* 0x00008000 */
|
||||
#define INT_STATUS_TRAP_TURN (1 << 20) /* 0x00100000 */
|
||||
#define INT_STATUS_HIT_MINE (1 << 21) /* 0x00200000 */
|
||||
#define INT_STATUS_STOP_RIDING (1 << 22) /* 0x00400000 */
|
||||
#define INT_STATUS_TOUCHED_BOB_OMB (1 << 23) /* 0x00800000 */
|
||||
|
||||
|
||||
s16 mario_obj_angle_to_object(struct MarioState *m, struct Object *o);
|
||||
void mario_stop_riding_object(struct MarioState *m);
|
||||
void mario_grab_used_object(struct MarioState *m);
|
||||
void mario_drop_held_object(struct MarioState *m);
|
||||
void mario_throw_held_object(struct MarioState *m);
|
||||
void mario_stop_riding_and_holding(struct MarioState *m);
|
||||
u32 does_mario_have_normal_cap_on_head(struct MarioState *m);
|
||||
void mario_blow_off_cap(struct MarioState *m, f32 capSpeed);
|
||||
u32 mario_lose_cap_to_enemy(u32 arg);
|
||||
void mario_retrieve_cap(void);
|
||||
struct Object *mario_get_collided_object(struct MarioState *m, u32 interactType);
|
||||
u32 mario_check_object_grab(struct MarioState *m);
|
||||
u32 get_door_save_file_flag(struct Object *door);
|
||||
void mario_process_interactions(struct MarioState *m);
|
||||
void mario_handle_special_floors(struct MarioState *m);
|
||||
|
||||
#endif // INTERACTION_H
|
||||
@@ -0,0 +1,132 @@
|
||||
#ifndef LEVEL_UPDATE_H
|
||||
#define LEVEL_UPDATE_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
|
||||
#define TIMER_CONTROL_SHOW 0
|
||||
#define TIMER_CONTROL_START 1
|
||||
#define TIMER_CONTROL_STOP 2
|
||||
#define TIMER_CONTROL_HIDE 3
|
||||
|
||||
#define WARP_OP_NONE 0x00
|
||||
#define WARP_OP_UNKNOWN_01 0x01
|
||||
#define WARP_OP_UNKNOWN_02 0x02
|
||||
#define WARP_OP_WARP_DOOR 0x03
|
||||
#define WARP_OP_WARP_OBJECT 0x04
|
||||
#define WARP_OP_TELEPORT 0x05
|
||||
#define WARP_OP_STAR_EXIT 0x11
|
||||
#define WARP_OP_DEATH 0x12
|
||||
#define WARP_OP_WARP_FLOOR 0x13
|
||||
#define WARP_OP_GAME_OVER 0x14
|
||||
#define WARP_OP_CREDITS_END 0x15
|
||||
#define WARP_OP_DEMO_NEXT 0x16
|
||||
#define WARP_OP_CREDITS_START 0x17
|
||||
#define WARP_OP_CREDITS_NEXT 0x18
|
||||
#define WARP_OP_DEMO_END 0x19
|
||||
|
||||
#define WARP_OP_TRIGGERS_LEVEL_SELECT 0x10
|
||||
|
||||
#define MARIO_SPAWN_DOOR_WARP 0x01
|
||||
#define MARIO_SPAWN_UNKNOWN_02 0x02
|
||||
#define MARIO_SPAWN_UNKNOWN_03 0x03
|
||||
#define MARIO_SPAWN_TELEPORT 0x04
|
||||
#define MARIO_SPAWN_INSTANT_ACTIVE 0x10
|
||||
#define MARIO_SPAWN_SWIMMING 0x11
|
||||
#define MARIO_SPAWN_AIRBORNE 0x12
|
||||
#define MARIO_SPAWN_HARD_AIR_KNOCKBACK 0x13
|
||||
#define MARIO_SPAWN_SPIN_AIRBORNE_CIRCLE 0x14
|
||||
#define MARIO_SPAWN_DEATH 0x15
|
||||
#define MARIO_SPAWN_SPIN_AIRBORNE 0x16
|
||||
#define MARIO_SPAWN_FLYING 0x17
|
||||
#define MARIO_SPAWN_PAINTING_STAR_COLLECT 0x20
|
||||
#define MARIO_SPAWN_PAINTING_DEATH 0x21
|
||||
#define MARIO_SPAWN_AIRBORNE_STAR_COLLECT 0x22
|
||||
#define MARIO_SPAWN_AIRBORNE_DEATH 0x23
|
||||
#define MARIO_SPAWN_LAUNCH_STAR_COLLECT 0x24
|
||||
#define MARIO_SPAWN_LAUNCH_DEATH 0x25
|
||||
#define MARIO_SPAWN_UNKNOWN_27 0x27
|
||||
|
||||
|
||||
// struct CreditsEntry
|
||||
// {
|
||||
// /*0x00*/ u8 levelNum;
|
||||
// /*0x01*/ u8 areaIndex;
|
||||
// /*0x02*/ u8 unk02;
|
||||
// /*0x03*/ s8 marioAngle;
|
||||
// /*0x04*/ Vec3s marioPos;
|
||||
// /*0x0C*/ const char **unk0C;
|
||||
// };
|
||||
//
|
||||
// extern struct CreditsEntry *gCurrCreditsEntry;
|
||||
//
|
||||
// extern struct MarioState gMarioStates[];
|
||||
// extern struct MarioState *gMarioState;
|
||||
//
|
||||
// extern s16 sCurrPlayMode;
|
||||
// extern u16 D_80339ECA;
|
||||
// extern s16 sTransitionTimer;
|
||||
// extern void (*sTransitionUpdate)(s16 *);
|
||||
// extern u8 unused3[4];
|
||||
//
|
||||
// struct WarpDest {
|
||||
// u8 type;
|
||||
// u8 levelNum;
|
||||
// u8 areaIdx;
|
||||
// u8 nodeId;
|
||||
// u32 arg;
|
||||
// };
|
||||
//
|
||||
// extern struct WarpDest sWarpDest;
|
||||
//
|
||||
// extern s16 D_80339EE0;
|
||||
// extern s16 sDelayedWarpOp;
|
||||
// extern s16 sDelayedWarpTimer;
|
||||
// extern s16 sSourceWarpNodeId;
|
||||
// extern s32 sDelayedWarpArg;
|
||||
// extern u8 unused4[2];
|
||||
// extern s8 sTimerRunning;
|
||||
|
||||
struct HudDisplay {
|
||||
/*0x00*/ s16 lives;
|
||||
/*0x02*/ s16 coins;
|
||||
/*0x04*/ s16 stars;
|
||||
/*0x06*/ s16 wedges;
|
||||
/*0x08*/ s16 keys;
|
||||
/*0x0A*/ s16 flags;
|
||||
/*0x0C*/ u16 timer;
|
||||
};
|
||||
|
||||
// extern struct HudDisplay gHudDisplay;
|
||||
// extern s8 gNeverEnteredCastle;
|
||||
|
||||
enum HUDDisplayFlag {
|
||||
HUD_DISPLAY_FLAG_LIVES = 0x0001,
|
||||
HUD_DISPLAY_FLAG_COIN_COUNT = 0x0002,
|
||||
HUD_DISPLAY_FLAG_STAR_COUNT = 0x0004,
|
||||
HUD_DISPLAY_FLAG_CAMERA_AND_POWER = 0x0008,
|
||||
HUD_DISPLAY_FLAG_KEYS = 0x0010,
|
||||
HUD_DISPLAY_FLAG_UNKNOWN_0020 = 0x0020,
|
||||
HUD_DISPLAY_FLAG_TIMER = 0x0040,
|
||||
HUD_DISPLAY_FLAG_EMPHASIZE_POWER = 0x8000,
|
||||
|
||||
HUD_DISPLAY_NONE = 0x0000,
|
||||
HUD_DISPLAY_DEFAULT = HUD_DISPLAY_FLAG_LIVES | HUD_DISPLAY_FLAG_COIN_COUNT | HUD_DISPLAY_FLAG_STAR_COUNT | HUD_DISPLAY_FLAG_CAMERA_AND_POWER | HUD_DISPLAY_FLAG_KEYS | HUD_DISPLAY_FLAG_UNKNOWN_0020
|
||||
};
|
||||
//
|
||||
//
|
||||
// u16 level_control_timer(s32 timerOp);
|
||||
// void fade_into_special_warp(u32 arg, u32 color);
|
||||
// void load_level_init_text(u32 arg);
|
||||
// s16 level_trigger_warp(struct MarioState *m, s32 warpOp);
|
||||
// void level_set_transition(s16 length, void (*updateFunction)(s16 *));
|
||||
//
|
||||
// s32 lvl_init_or_update(s16 initOrUpdate, UNUSED s32 unused);
|
||||
// s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum);
|
||||
// s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum);
|
||||
// s32 lvl_play_the_end_screen_sound(UNUSED s16 arg0, UNUSED s32 arg1);
|
||||
// void basic_update(UNUSED s16 *arg);
|
||||
|
||||
#endif // LEVEL_UPDATE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
#ifndef MARIO_H
|
||||
#define MARIO_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/macros.h"
|
||||
#include "../include/types.h"
|
||||
|
||||
s32 is_anim_at_end(struct MarioState *m);
|
||||
s32 is_anim_past_end(struct MarioState *m);
|
||||
s16 set_mario_animation(struct MarioState *m, s32 targetAnimID);
|
||||
s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel);
|
||||
void set_anim_to_frame(struct MarioState *m, s16 animFrame);
|
||||
s32 is_anim_past_frame(struct MarioState *m, s16 animFrame);
|
||||
s16 find_mario_anim_flags_and_translation(struct Object *o, s32 yaw, Vec3s translation);
|
||||
void update_mario_pos_for_anim(struct MarioState *m);
|
||||
s16 return_mario_anim_y_translation(struct MarioState *m);
|
||||
void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags);
|
||||
void play_mario_jump_sound(struct MarioState *m);
|
||||
void adjust_sound_for_speed(struct MarioState *m);
|
||||
void play_sound_and_spawn_particles(struct MarioState *m, u32 soundBits, u32 waveParticleType);
|
||||
void play_mario_action_sound(struct MarioState *m, u32 soundBits, u32 waveParticleType);
|
||||
void play_mario_landing_sound(struct MarioState *m, u32 soundBits);
|
||||
void play_mario_landing_sound_once(struct MarioState *m, u32 soundBits);
|
||||
void play_mario_heavy_landing_sound(struct MarioState *m, u32 soundBits);
|
||||
void play_mario_heavy_landing_sound_once(struct MarioState *m, u32 soundBits);
|
||||
void play_mario_sound(struct MarioState *m, s32 primarySoundBits, s32 scondarySoundBits);
|
||||
void mario_set_forward_vel(struct MarioState *m, f32 speed);
|
||||
s32 mario_get_floor_class(struct MarioState *m);
|
||||
u32 mario_get_terrain_sound_addend(struct MarioState *m);
|
||||
struct Surface *resolve_and_return_wall_collisions(Vec3f pos, f32 offset, f32 radius);
|
||||
f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil);
|
||||
s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw);
|
||||
u32 mario_floor_is_slippery(struct MarioState *m);
|
||||
s32 mario_floor_is_slope(struct MarioState *m);
|
||||
s32 mario_floor_is_steep(struct MarioState *m);
|
||||
f32 find_floor_height_relative_polar(struct MarioState *m, s16 angleFromMario, f32 distFromMario);
|
||||
s16 find_floor_slope(struct MarioState *m, s16 yawOffset);
|
||||
void update_mario_sound_and_camera(struct MarioState *m);
|
||||
void set_steep_jump_action(struct MarioState *m);
|
||||
u32 set_mario_action(struct MarioState *, u32 action, u32 actionArg);
|
||||
s32 set_jump_from_landing(struct MarioState *m);
|
||||
s32 set_jumping_action(struct MarioState *m, u32 action, u32 actionArg);
|
||||
s32 drop_and_set_mario_action(struct MarioState *m, u32 action, u32 actionArg);
|
||||
s32 hurt_and_set_mario_action(struct MarioState *m, u32 action, u32 actionArg, s16 hurtCounter);
|
||||
s32 check_common_action_exits(struct MarioState *m);
|
||||
s32 check_common_hold_action_exits(struct MarioState *m);
|
||||
s32 transition_submerged_to_walking(struct MarioState *m);
|
||||
s32 set_water_plunge_action(struct MarioState *m);
|
||||
s32 execute_mario_action(UNUSED struct Object *o);
|
||||
void init_mario(void);
|
||||
void init_mario_from_save_file(void);
|
||||
|
||||
#endif // MARIO_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
#ifndef MARIO_ACTIONS_AIRBORNE_H
|
||||
#define MARIO_ACTIONS_AIRBORNE_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
s32 mario_execute_airborne_action(struct MarioState *m);
|
||||
|
||||
#endif // MARIO_ACTIONS_AIRBORNE_H
|
||||
@@ -0,0 +1,896 @@
|
||||
#include "../include/PR/ultratypes.h"
|
||||
#include "../shim.h"
|
||||
|
||||
#include "../include/sm64.h"
|
||||
//#include "behavior_data.h"
|
||||
#include "mario_actions_automatic.h"
|
||||
//#include "audio/external.h"
|
||||
#include "area.h"
|
||||
#include "mario.h"
|
||||
#include "mario_step.h"
|
||||
#include "../engine/math_util.h"
|
||||
#include "memory.h"
|
||||
#include "../engine/graph_node.h"
|
||||
#include "save_file.h"
|
||||
#include "../engine/surface_collision.h"
|
||||
#include "interaction.h"
|
||||
#include "camera.h"
|
||||
//#include "level_table.h"
|
||||
//#include "thread6.h"
|
||||
#include "../include/mario_animation_ids.h"
|
||||
#include "../include/object_fields.h"
|
||||
#include "../include/mario_geo_switch_case_ids.h"
|
||||
|
||||
static Vec3f gVec3fZero = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
#define POLE_NONE 0
|
||||
#define POLE_TOUCHED_FLOOR 1
|
||||
#define POLE_FELL_OFF 2
|
||||
|
||||
#define HANG_NONE 0
|
||||
#define HANG_HIT_CEIL_OR_OOB 1
|
||||
#define HANG_LEFT_CEIL 2
|
||||
|
||||
void add_tree_leaf_particles(struct MarioState *m) {
|
||||
// f32 leafHeight;
|
||||
|
||||
// if (m->usedObj->behavior == segmented_to_virtual(bhvTree)) {
|
||||
// // make leaf effect spawn higher on the Shifting Sand Land palm tree
|
||||
// if (gCurrLevelNum == LEVEL_SSL) {
|
||||
// leafHeight = 250.0f;
|
||||
// } else {
|
||||
// leafHeight = 100.0f;
|
||||
// }
|
||||
// if (m->pos[1] - m->floorHeight > leafHeight) {
|
||||
// m->particleFlags |= PARTICLE_LEAF;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void play_climbing_sounds(struct MarioState *m, s32 b) {
|
||||
// s32 isOnTree = (m->usedObj->behavior == segmented_to_virtual(bhvTree));
|
||||
s32 isOnTree = FALSE;
|
||||
|
||||
if (b == 1) {
|
||||
if (is_anim_past_frame(m, 1)) {
|
||||
play_sound(isOnTree ? SOUND_ACTION_CLIMB_UP_TREE : SOUND_ACTION_CLIMB_UP_POLE,
|
||||
m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
} else {
|
||||
play_sound(isOnTree ? SOUND_MOVING_SLIDE_DOWN_TREE : SOUND_MOVING_SLIDE_DOWN_POLE,
|
||||
m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
}
|
||||
|
||||
s32 set_pole_position(struct MarioState *m, f32 offsetY) {
|
||||
UNUSED s32 unused1;
|
||||
UNUSED s32 unused2;
|
||||
UNUSED s32 unused3;
|
||||
struct Surface *floor;
|
||||
struct Surface *ceil;
|
||||
f32 floorHeight;
|
||||
f32 ceilHeight;
|
||||
s32 collided;
|
||||
s32 result = POLE_NONE;
|
||||
f32 poleTop = m->usedObj->hitboxHeight - 100.0f;
|
||||
struct Object *marioObj = m->marioObj;
|
||||
|
||||
if (marioObj->oMarioPolePos > poleTop) {
|
||||
marioObj->oMarioPolePos = poleTop;
|
||||
}
|
||||
|
||||
m->pos[0] = m->usedObj->oPosX;
|
||||
m->pos[2] = m->usedObj->oPosZ;
|
||||
m->pos[1] = m->usedObj->oPosY + marioObj->oMarioPolePos + offsetY;
|
||||
|
||||
collided = f32_find_wall_collision(&m->pos[0], &m->pos[1], &m->pos[2], 60.0f, 50.0f);
|
||||
collided |= f32_find_wall_collision(&m->pos[0], &m->pos[1], &m->pos[2], 30.0f, 24.0f);
|
||||
|
||||
ceilHeight = vec3f_find_ceil(m->pos, m->pos[1], &ceil);
|
||||
if (m->pos[1] > ceilHeight - 160.0f) {
|
||||
m->pos[1] = ceilHeight - 160.0f;
|
||||
marioObj->oMarioPolePos = m->pos[1] - m->usedObj->oPosY;
|
||||
}
|
||||
|
||||
floorHeight = find_floor(m->pos[0], m->pos[1], m->pos[2], &floor);
|
||||
if (m->pos[1] < floorHeight) {
|
||||
m->pos[1] = floorHeight;
|
||||
set_mario_action(m, ACT_IDLE, 0);
|
||||
result = POLE_TOUCHED_FLOOR;
|
||||
} else if (marioObj->oMarioPolePos < -m->usedObj->hitboxDownOffset) {
|
||||
m->pos[1] = m->usedObj->oPosY - m->usedObj->hitboxDownOffset;
|
||||
set_mario_action(m, ACT_FREEFALL, 0);
|
||||
result = POLE_FELL_OFF;
|
||||
} else if (collided) {
|
||||
if (m->pos[1] > floorHeight + 20.0f) {
|
||||
m->forwardVel = -2.0f;
|
||||
set_mario_action(m, ACT_SOFT_BONK, 0);
|
||||
result = POLE_FELL_OFF;
|
||||
} else {
|
||||
set_mario_action(m, ACT_IDLE, 0);
|
||||
result = POLE_TOUCHED_FLOOR;
|
||||
}
|
||||
}
|
||||
|
||||
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
|
||||
vec3s_set(m->marioObj->header.gfx.angle, m->usedObj->oMoveAnglePitch, m->faceAngle[1],
|
||||
m->usedObj->oMoveAngleRoll);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 act_holding_pole(struct MarioState *m) {
|
||||
struct Object *marioObj = m->marioObj;
|
||||
|
||||
#ifdef VERSION_JP
|
||||
if (m->input & INPUT_A_PRESSED) {
|
||||
add_tree_leaf_particles(m);
|
||||
m->faceAngle[1] += 0x8000;
|
||||
return set_mario_action(m, ACT_WALL_KICK_AIR, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_Z_PRESSED) {
|
||||
add_tree_leaf_particles(m);
|
||||
m->forwardVel = -2.0f;
|
||||
return set_mario_action(m, ACT_SOFT_BONK, 0);
|
||||
}
|
||||
#else
|
||||
if ((m->input & INPUT_Z_PRESSED) || m->health < 0x100) {
|
||||
add_tree_leaf_particles(m);
|
||||
m->forwardVel = -2.0f;
|
||||
return set_mario_action(m, ACT_SOFT_BONK, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_A_PRESSED) {
|
||||
add_tree_leaf_particles(m);
|
||||
m->faceAngle[1] += 0x8000;
|
||||
return set_mario_action(m, ACT_WALL_KICK_AIR, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m->controller->stickY > 16.0f) {
|
||||
f32 poleTop = m->usedObj->hitboxHeight - 100.0f;
|
||||
const BehaviorScript *poleBehavior = virtual_to_segmented(0x13, m->usedObj->behavior);
|
||||
|
||||
if (marioObj->oMarioPolePos < poleTop - 0.4f) {
|
||||
return set_mario_action(m, ACT_CLIMBING_POLE, 0);
|
||||
}
|
||||
|
||||
// if (poleBehavior != bhvGiantPole && m->controller->stickY > 50.0f) {
|
||||
if (m->controller->stickY > 50.0f) {
|
||||
return set_mario_action(m, ACT_TOP_OF_POLE_TRANSITION, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (m->controller->stickY < -16.0f) {
|
||||
marioObj->oMarioPoleYawVel -= m->controller->stickY * 2;
|
||||
if (marioObj->oMarioPoleYawVel > 0x1000) {
|
||||
marioObj->oMarioPoleYawVel = 0x1000;
|
||||
}
|
||||
|
||||
m->faceAngle[1] += marioObj->oMarioPoleYawVel;
|
||||
marioObj->oMarioPolePos -= marioObj->oMarioPoleYawVel / 0x100;
|
||||
|
||||
// if (m->usedObj->behavior == segmented_to_virtual(bhvTree)) {
|
||||
// //! The Shifting Sand Land palm tree check is done climbing up in
|
||||
// // add_tree_leaf_particles, but not here, when climbing down.
|
||||
// if (m->pos[1] - m->floorHeight > 100.0f) {
|
||||
// m->particleFlags |= PARTICLE_LEAF;
|
||||
// }
|
||||
// }
|
||||
play_climbing_sounds(m, 2);
|
||||
#ifdef VERSION_SH
|
||||
reset_rumble_timers();
|
||||
#endif
|
||||
func_80320A4C(1, marioObj->oMarioPoleYawVel / 0x100 * 2);
|
||||
} else {
|
||||
marioObj->oMarioPoleYawVel = 0;
|
||||
m->faceAngle[1] -= m->controller->stickX * 16.0f;
|
||||
}
|
||||
|
||||
if (set_pole_position(m, 0.0f) == POLE_NONE) {
|
||||
set_mario_animation(m, MARIO_ANIM_IDLE_ON_POLE);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_climbing_pole(struct MarioState *m) {
|
||||
s32 sp24;
|
||||
struct Object *marioObj = m->marioObj;
|
||||
s16 cameraAngle = m->area->camera->yaw;
|
||||
|
||||
#ifndef VERSION_JP
|
||||
if (m->health < 0x100) {
|
||||
add_tree_leaf_particles(m);
|
||||
m->forwardVel = -2.0f;
|
||||
return set_mario_action(m, ACT_SOFT_BONK, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m->input & INPUT_A_PRESSED) {
|
||||
add_tree_leaf_particles(m);
|
||||
m->faceAngle[1] += 0x8000;
|
||||
return set_mario_action(m, ACT_WALL_KICK_AIR, 0);
|
||||
}
|
||||
|
||||
if (m->controller->stickY < 8.0f) {
|
||||
return set_mario_action(m, ACT_HOLDING_POLE, 0);
|
||||
}
|
||||
|
||||
marioObj->oMarioPolePos += m->controller->stickY / 8.0f;
|
||||
marioObj->oMarioPoleYawVel = 0;
|
||||
m->faceAngle[1] = cameraAngle - approach_s32((s16)(cameraAngle - m->faceAngle[1]), 0, 0x400, 0x400);
|
||||
|
||||
if (set_pole_position(m, 0.0f) == POLE_NONE) {
|
||||
sp24 = m->controller->stickY / 4.0f * 0x10000;
|
||||
set_mario_anim_with_accel(m, MARIO_ANIM_CLIMB_UP_POLE, sp24);
|
||||
add_tree_leaf_particles(m);
|
||||
play_climbing_sounds(m, 1);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_grab_pole_slow(struct MarioState *m) {
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_WHOA, MARIO_MARIO_SOUND_PLAYED);
|
||||
|
||||
if (set_pole_position(m, 0.0f) == POLE_NONE) {
|
||||
set_mario_animation(m, MARIO_ANIM_GRAB_POLE_SHORT);
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, ACT_HOLDING_POLE, 0);
|
||||
}
|
||||
add_tree_leaf_particles(m);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_grab_pole_fast(struct MarioState *m) {
|
||||
struct Object *marioObj = m->marioObj;
|
||||
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_WHOA, MARIO_MARIO_SOUND_PLAYED);
|
||||
m->faceAngle[1] += marioObj->oMarioPoleYawVel;
|
||||
marioObj->oMarioPoleYawVel = marioObj->oMarioPoleYawVel * 8 / 10;
|
||||
|
||||
if (set_pole_position(m, 0.0f) == POLE_NONE) {
|
||||
if (marioObj->oMarioPoleYawVel > 0x800) {
|
||||
set_mario_animation(m, MARIO_ANIM_GRAB_POLE_SWING_PART1);
|
||||
} else {
|
||||
set_mario_animation(m, MARIO_ANIM_GRAB_POLE_SWING_PART2);
|
||||
if (is_anim_at_end(m)) {
|
||||
marioObj->oMarioPoleYawVel = 0;
|
||||
set_mario_action(m, ACT_HOLDING_POLE, 0);
|
||||
}
|
||||
}
|
||||
add_tree_leaf_particles(m);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_top_of_pole_transition(struct MarioState *m) {
|
||||
struct Object *marioObj = m->marioObj;
|
||||
|
||||
marioObj->oMarioPoleYawVel = 0;
|
||||
if (m->actionArg == 0) {
|
||||
set_mario_animation(m, MARIO_ANIM_START_HANDSTAND);
|
||||
if (is_anim_at_end(m)) {
|
||||
return set_mario_action(m, ACT_TOP_OF_POLE, 0);
|
||||
}
|
||||
} else {
|
||||
set_mario_animation(m, MARIO_ANIM_RETURN_FROM_HANDSTAND);
|
||||
if (m->marioObj->header.gfx.animInfo.animFrame == 0) {
|
||||
return set_mario_action(m, ACT_HOLDING_POLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
set_pole_position(m, return_mario_anim_y_translation(m));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_top_of_pole(struct MarioState *m) {
|
||||
UNUSED struct Object *marioObj = m->marioObj;
|
||||
|
||||
if (m->input & INPUT_A_PRESSED) {
|
||||
return set_mario_action(m, ACT_TOP_OF_POLE_JUMP, 0);
|
||||
}
|
||||
if (m->controller->stickY < -16.0f) {
|
||||
return set_mario_action(m, ACT_TOP_OF_POLE_TRANSITION, 1);
|
||||
}
|
||||
|
||||
m->faceAngle[1] -= m->controller->stickX * 16.0f;
|
||||
|
||||
set_mario_animation(m, MARIO_ANIM_HANDSTAND_IDLE);
|
||||
set_pole_position(m, return_mario_anim_y_translation(m));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 perform_hanging_step(struct MarioState *m, Vec3f nextPos) {
|
||||
UNUSED s32 unused;
|
||||
struct Surface *ceil;
|
||||
struct Surface *floor;
|
||||
f32 ceilHeight;
|
||||
f32 floorHeight;
|
||||
f32 ceilOffset;
|
||||
|
||||
m->wall = resolve_and_return_wall_collisions(nextPos, 50.0f, 50.0f);
|
||||
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
|
||||
ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil);
|
||||
|
||||
if (floor == NULL) {
|
||||
return HANG_HIT_CEIL_OR_OOB;
|
||||
}
|
||||
if (ceil == NULL) {
|
||||
return HANG_LEFT_CEIL;
|
||||
}
|
||||
if (ceilHeight - floorHeight <= 160.0f) {
|
||||
return HANG_HIT_CEIL_OR_OOB;
|
||||
}
|
||||
if (ceil->type != SURFACE_HANGABLE) {
|
||||
return HANG_LEFT_CEIL;
|
||||
}
|
||||
|
||||
ceilOffset = ceilHeight - (nextPos[1] + 160.0f);
|
||||
if (ceilOffset < -30.0f) {
|
||||
return HANG_HIT_CEIL_OR_OOB;
|
||||
}
|
||||
if (ceilOffset > 30.0f) {
|
||||
return HANG_LEFT_CEIL;
|
||||
}
|
||||
|
||||
nextPos[1] = m->ceilHeight - 160.0f;
|
||||
vec3f_copy(m->pos, nextPos);
|
||||
|
||||
m->floor = floor;
|
||||
m->floorHeight = floorHeight;
|
||||
m->ceil = ceil;
|
||||
m->ceilHeight = ceilHeight;
|
||||
|
||||
return HANG_NONE;
|
||||
}
|
||||
|
||||
s32 update_hang_moving(struct MarioState *m) {
|
||||
s32 stepResult;
|
||||
Vec3f nextPos;
|
||||
f32 maxSpeed = 4.0f;
|
||||
|
||||
m->forwardVel += 1.0f;
|
||||
if (m->forwardVel > maxSpeed) {
|
||||
m->forwardVel = maxSpeed;
|
||||
}
|
||||
|
||||
m->faceAngle[1] =
|
||||
m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800);
|
||||
|
||||
m->slideYaw = m->faceAngle[1];
|
||||
m->slideVelX = m->forwardVel * sins(m->faceAngle[1]);
|
||||
m->slideVelZ = m->forwardVel * coss(m->faceAngle[1]);
|
||||
|
||||
m->vel[0] = m->slideVelX;
|
||||
m->vel[1] = 0.0f;
|
||||
m->vel[2] = m->slideVelZ;
|
||||
|
||||
nextPos[0] = m->pos[0] - m->ceil->normal.y * m->vel[0];
|
||||
nextPos[2] = m->pos[2] - m->ceil->normal.y * m->vel[2];
|
||||
nextPos[1] = m->pos[1];
|
||||
|
||||
stepResult = perform_hanging_step(m, nextPos);
|
||||
|
||||
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
|
||||
vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
|
||||
return stepResult;
|
||||
}
|
||||
|
||||
void update_hang_stationary(struct MarioState *m) {
|
||||
m->forwardVel = 0.0f;
|
||||
m->slideVelX = 0.0f;
|
||||
m->slideVelZ = 0.0f;
|
||||
|
||||
m->pos[1] = m->ceilHeight - 160.0f;
|
||||
vec3f_copy(m->vel, gVec3fZero);
|
||||
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
|
||||
}
|
||||
|
||||
s32 act_start_hanging(struct MarioState *m) {
|
||||
#ifdef VERSION_SH
|
||||
if (m->actionTimer++ == 0) {
|
||||
queue_rumble_data(5, 80);
|
||||
}
|
||||
#else
|
||||
m->actionTimer++;
|
||||
#endif
|
||||
|
||||
if ((m->input & INPUT_NONZERO_ANALOG) && m->actionTimer >= 31) {
|
||||
return set_mario_action(m, ACT_HANGING, 0);
|
||||
}
|
||||
|
||||
if (!(m->input & INPUT_A_DOWN)) {
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_Z_PRESSED) {
|
||||
return set_mario_action(m, ACT_GROUND_POUND, 0);
|
||||
}
|
||||
|
||||
//! Crash if Mario's referenced ceiling is NULL (same for other hanging actions)
|
||||
if (m->ceil->type != SURFACE_HANGABLE) {
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
set_mario_animation(m, MARIO_ANIM_HANG_ON_CEILING);
|
||||
play_sound_if_no_flag(m, SOUND_ACTION_HANGING_STEP, MARIO_ACTION_SOUND_PLAYED);
|
||||
update_hang_stationary(m);
|
||||
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, ACT_HANGING, 0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_hanging(struct MarioState *m) {
|
||||
if (m->input & INPUT_NONZERO_ANALOG) {
|
||||
return set_mario_action(m, ACT_HANG_MOVING, m->actionArg);
|
||||
}
|
||||
|
||||
if (!(m->input & INPUT_A_DOWN)) {
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_Z_PRESSED) {
|
||||
return set_mario_action(m, ACT_GROUND_POUND, 0);
|
||||
}
|
||||
|
||||
if (m->ceil->type != SURFACE_HANGABLE) {
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (m->actionArg & 1) {
|
||||
set_mario_animation(m, MARIO_ANIM_HANDSTAND_LEFT);
|
||||
} else {
|
||||
set_mario_animation(m, MARIO_ANIM_HANDSTAND_RIGHT);
|
||||
}
|
||||
|
||||
update_hang_stationary(m);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_hang_moving(struct MarioState *m) {
|
||||
if (!(m->input & INPUT_A_DOWN)) {
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_Z_PRESSED) {
|
||||
return set_mario_action(m, ACT_GROUND_POUND, 0);
|
||||
}
|
||||
|
||||
if (m->ceil->type != SURFACE_HANGABLE) {
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (m->actionArg & 1) {
|
||||
set_mario_animation(m, MARIO_ANIM_MOVE_ON_WIRE_NET_RIGHT);
|
||||
} else {
|
||||
set_mario_animation(m, MARIO_ANIM_MOVE_ON_WIRE_NET_LEFT);
|
||||
}
|
||||
|
||||
if (m->marioObj->header.gfx.animInfo.animFrame == 12) {
|
||||
play_sound(SOUND_ACTION_HANGING_STEP, m->marioObj->header.gfx.cameraToObject);
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 30);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (is_anim_past_end(m)) {
|
||||
m->actionArg ^= 1;
|
||||
if (m->input & INPUT_UNKNOWN_5) {
|
||||
return set_mario_action(m, ACT_HANGING, m->actionArg);
|
||||
}
|
||||
}
|
||||
|
||||
if (update_hang_moving(m) == HANG_LEFT_CEIL) {
|
||||
set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 let_go_of_ledge(struct MarioState *m) {
|
||||
f32 floorHeight;
|
||||
struct Surface *floor;
|
||||
|
||||
m->vel[1] = 0.0f;
|
||||
m->forwardVel = -8.0f;
|
||||
m->pos[0] -= 60.0f * sins(m->faceAngle[1]);
|
||||
m->pos[2] -= 60.0f * coss(m->faceAngle[1]);
|
||||
|
||||
floorHeight = find_floor(m->pos[0], m->pos[1], m->pos[2], &floor);
|
||||
if (floorHeight < m->pos[1] - 100.0f) {
|
||||
m->pos[1] -= 100.0f;
|
||||
} else {
|
||||
m->pos[1] = floorHeight;
|
||||
}
|
||||
|
||||
return set_mario_action(m, ACT_SOFT_BONK, 0);
|
||||
}
|
||||
|
||||
void climb_up_ledge(struct MarioState *m) {
|
||||
set_mario_animation(m, MARIO_ANIM_IDLE_HEAD_LEFT);
|
||||
m->pos[0] += 14.0f * sins(m->faceAngle[1]);
|
||||
m->pos[2] += 14.0f * coss(m->faceAngle[1]);
|
||||
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
|
||||
}
|
||||
|
||||
void update_ledge_climb_camera(struct MarioState *m) {
|
||||
// f32 sp4;
|
||||
|
||||
// if (m->actionTimer < 14) {
|
||||
// sp4 = m->actionTimer;
|
||||
// } else {
|
||||
// sp4 = 14.0f;
|
||||
// }
|
||||
// m->statusForCamera->pos[0] = m->pos[0] + sp4 * sins(m->faceAngle[1]);
|
||||
// m->statusForCamera->pos[2] = m->pos[2] + sp4 * coss(m->faceAngle[1]);
|
||||
// m->statusForCamera->pos[1] = m->pos[1];
|
||||
// m->actionTimer++;
|
||||
// m->flags |= MARIO_UNKNOWN_25;
|
||||
}
|
||||
|
||||
void update_ledge_climb(struct MarioState *m, s32 animation, u32 endAction) {
|
||||
stop_and_set_height_to_floor(m);
|
||||
|
||||
set_mario_animation(m, animation);
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, endAction, 0);
|
||||
if (endAction == ACT_IDLE) {
|
||||
climb_up_ledge(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 act_ledge_grab(struct MarioState *m) {
|
||||
f32 heightAboveFloor;
|
||||
s16 intendedDYaw = m->intendedYaw - m->faceAngle[1];
|
||||
s32 hasSpaceForMario = (m->ceilHeight - m->floorHeight >= 160.0f);
|
||||
|
||||
if (m->actionTimer < 10) {
|
||||
m->actionTimer++;
|
||||
}
|
||||
|
||||
if (m->floor->normal.y < 0.9063078f) {
|
||||
return let_go_of_ledge(m);
|
||||
}
|
||||
|
||||
if (m->input & (INPUT_Z_PRESSED | INPUT_OFF_FLOOR)) {
|
||||
return let_go_of_ledge(m);
|
||||
}
|
||||
|
||||
if ((m->input & INPUT_A_PRESSED) && hasSpaceForMario) {
|
||||
return set_mario_action(m, ACT_LEDGE_CLIMB_FAST, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_UNKNOWN_10) {
|
||||
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_UNK1) {
|
||||
m->hurtCounter += (m->flags & MARIO_CAP_ON_HEAD) ? 12 : 18;
|
||||
}
|
||||
return let_go_of_ledge(m);
|
||||
}
|
||||
#ifdef VERSION_EU
|
||||
// On EU, you can't slow climb up ledges while holding A.
|
||||
if (m->actionTimer == 10 && (m->input & INPUT_NONZERO_ANALOG) && !(m->input & INPUT_A_DOWN))
|
||||
#else
|
||||
if (m->actionTimer == 10 && (m->input & INPUT_NONZERO_ANALOG))
|
||||
#endif
|
||||
{
|
||||
if (intendedDYaw >= -0x4000 && intendedDYaw <= 0x4000) {
|
||||
if (hasSpaceForMario) {
|
||||
return set_mario_action(m, ACT_LEDGE_CLIMB_SLOW_1, 0);
|
||||
}
|
||||
} else {
|
||||
return let_go_of_ledge(m);
|
||||
}
|
||||
}
|
||||
|
||||
heightAboveFloor = m->pos[1] - find_floor_height_relative_polar(m, -0x8000, 30.0f);
|
||||
if (hasSpaceForMario && heightAboveFloor < 100.0f) {
|
||||
return set_mario_action(m, ACT_LEDGE_CLIMB_FAST, 0);
|
||||
}
|
||||
|
||||
if (m->actionArg == 0) {
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_WHOA, MARIO_MARIO_SOUND_PLAYED);
|
||||
}
|
||||
|
||||
stop_and_set_height_to_floor(m);
|
||||
set_mario_animation(m, MARIO_ANIM_IDLE_ON_LEDGE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_ledge_climb_slow(struct MarioState *m) {
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return let_go_of_ledge(m);
|
||||
}
|
||||
|
||||
if (m->actionTimer >= 28
|
||||
&& (m->input
|
||||
& (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE))) {
|
||||
climb_up_ledge(m);
|
||||
return check_common_action_exits(m);
|
||||
}
|
||||
|
||||
if (m->actionTimer == 10) {
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_EEUH, MARIO_MARIO_SOUND_PLAYED);
|
||||
}
|
||||
|
||||
update_ledge_climb(m, MARIO_ANIM_SLOW_LEDGE_GRAB, ACT_IDLE);
|
||||
|
||||
update_ledge_climb_camera(m);
|
||||
if (m->marioObj->header.gfx.animInfo.animFrame == 17) {
|
||||
m->action = ACT_LEDGE_CLIMB_SLOW_2;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_ledge_climb_down(struct MarioState *m) {
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return let_go_of_ledge(m);
|
||||
}
|
||||
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_WHOA, MARIO_MARIO_SOUND_PLAYED);
|
||||
|
||||
update_ledge_climb(m, MARIO_ANIM_CLIMB_DOWN_LEDGE, ACT_LEDGE_GRAB);
|
||||
m->actionArg = 1;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_ledge_climb_fast(struct MarioState *m) {
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return let_go_of_ledge(m);
|
||||
}
|
||||
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_UH2, MARIO_MARIO_SOUND_PLAYED);
|
||||
|
||||
update_ledge_climb(m, MARIO_ANIM_FAST_LEDGE_GRAB, ACT_IDLE);
|
||||
|
||||
if (m->marioObj->header.gfx.animInfo.animFrame == 8) {
|
||||
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
|
||||
}
|
||||
update_ledge_climb_camera(m);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_grabbed(struct MarioState *m) {
|
||||
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_UNK2) {
|
||||
s32 thrown = (m->marioObj->oInteractStatus & INT_STATUS_MARIO_UNK6) == 0;
|
||||
|
||||
m->faceAngle[1] = m->usedObj->oMoveAngleYaw;
|
||||
vec3f_copy(m->pos, m->marioObj->header.gfx.pos);
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 60);
|
||||
#endif
|
||||
|
||||
return set_mario_action(m, (m->forwardVel >= 0.0f) ? ACT_THROWN_FORWARD : ACT_THROWN_BACKWARD,
|
||||
thrown);
|
||||
}
|
||||
|
||||
set_mario_animation(m, MARIO_ANIM_BEING_GRABBED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_in_cannon(struct MarioState *m) {
|
||||
struct Object *marioObj = m->marioObj;
|
||||
s16 startFacePitch = m->faceAngle[0];
|
||||
s16 startFaceYaw = m->faceAngle[1];
|
||||
|
||||
switch (m->actionState) {
|
||||
case 0:
|
||||
m->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
m->usedObj->oInteractStatus = INT_STATUS_INTERACTED;
|
||||
|
||||
// m->statusForCamera->cameraEvent = CAM_EVENT_CANNON;
|
||||
// m->statusForCamera->usedObj = m->usedObj;
|
||||
|
||||
vec3f_set(m->vel, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
m->pos[0] = m->usedObj->oPosX;
|
||||
m->pos[1] = m->usedObj->oPosY + 350.0f;
|
||||
m->pos[2] = m->usedObj->oPosZ;
|
||||
|
||||
m->forwardVel = 0.0f;
|
||||
|
||||
m->actionState = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (m->usedObj->oAction == 1) {
|
||||
m->faceAngle[0] = m->usedObj->oMoveAnglePitch;
|
||||
m->faceAngle[1] = m->usedObj->oMoveAngleYaw;
|
||||
|
||||
marioObj->oMarioCannonObjectYaw = m->usedObj->oMoveAngleYaw;
|
||||
marioObj->oMarioCannonInputYaw = 0;
|
||||
|
||||
m->actionState = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m->faceAngle[0] -= (s16)(m->controller->stickY * 10.0f);
|
||||
marioObj->oMarioCannonInputYaw -= (s16)(m->controller->stickX * 10.0f);
|
||||
|
||||
if (m->faceAngle[0] > 0x38E3) {
|
||||
m->faceAngle[0] = 0x38E3;
|
||||
}
|
||||
if (m->faceAngle[0] < 0) {
|
||||
m->faceAngle[0] = 0;
|
||||
}
|
||||
|
||||
if (marioObj->oMarioCannonInputYaw > 0x4000) {
|
||||
marioObj->oMarioCannonInputYaw = 0x4000;
|
||||
}
|
||||
if (marioObj->oMarioCannonInputYaw < -0x4000) {
|
||||
marioObj->oMarioCannonInputYaw = -0x4000;
|
||||
}
|
||||
|
||||
m->faceAngle[1] = marioObj->oMarioCannonObjectYaw + marioObj->oMarioCannonInputYaw;
|
||||
if (m->input & INPUT_A_PRESSED) {
|
||||
m->forwardVel = 100.0f * coss(m->faceAngle[0]);
|
||||
|
||||
m->vel[1] = 100.0f * sins(m->faceAngle[0]);
|
||||
|
||||
m->pos[0] += 120.0f * coss(m->faceAngle[0]) * sins(m->faceAngle[1]);
|
||||
m->pos[1] += 120.0f * sins(m->faceAngle[0]);
|
||||
m->pos[2] += 120.0f * coss(m->faceAngle[0]) * coss(m->faceAngle[1]);
|
||||
|
||||
play_sound(SOUND_ACTION_FLYING_FAST, m->marioObj->header.gfx.cameraToObject);
|
||||
play_sound(SOUND_OBJ_POUNDING_CANNON, m->marioObj->header.gfx.cameraToObject);
|
||||
|
||||
m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
|
||||
set_mario_action(m, ACT_SHOT_FROM_CANNON, 0);
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(60, 70);
|
||||
#endif
|
||||
m->usedObj->oAction = 2;
|
||||
return FALSE;
|
||||
} else if (m->faceAngle[0] != startFacePitch || m->faceAngle[1] != startFaceYaw) {
|
||||
play_sound(SOUND_MOVING_AIM_CANNON, m->marioObj->header.gfx.cameraToObject);
|
||||
#ifdef VERSION_SH
|
||||
reset_rumble_timers_2(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
|
||||
vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
|
||||
set_mario_animation(m, MARIO_ANIM_DIVE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_tornado_twirling(struct MarioState *m) {
|
||||
struct Surface *floor;
|
||||
Vec3f nextPos;
|
||||
f32 sinAngleVel;
|
||||
f32 cosAngleVel;
|
||||
f32 floorHeight;
|
||||
struct Object *marioObj = m->marioObj;
|
||||
struct Object *usedObj = m->usedObj;
|
||||
s16 prevTwirlYaw = m->twirlYaw;
|
||||
|
||||
f32 dx = (m->pos[0] - usedObj->oPosX) * 0.95f;
|
||||
f32 dz = (m->pos[2] - usedObj->oPosZ) * 0.95f;
|
||||
|
||||
if (m->vel[1] < 60.0f) {
|
||||
m->vel[1] += 1.0f;
|
||||
}
|
||||
|
||||
if ((marioObj->oMarioTornadoPosY += m->vel[1]) < 0.0f) {
|
||||
marioObj->oMarioTornadoPosY = 0.0f;
|
||||
}
|
||||
if (marioObj->oMarioTornadoPosY > usedObj->hitboxHeight) {
|
||||
if (m->vel[1] < 20.0f) {
|
||||
m->vel[1] = 20.0f;
|
||||
}
|
||||
return set_mario_action(m, ACT_TWIRLING, 1);
|
||||
}
|
||||
|
||||
if (m->angleVel[1] < 0x3000) {
|
||||
m->angleVel[1] += 0x100;
|
||||
}
|
||||
|
||||
if (marioObj->oMarioTornadoYawVel < 0x1000) {
|
||||
marioObj->oMarioTornadoYawVel += 0x100;
|
||||
}
|
||||
|
||||
m->twirlYaw += m->angleVel[1];
|
||||
|
||||
sinAngleVel = sins(marioObj->oMarioTornadoYawVel);
|
||||
cosAngleVel = coss(marioObj->oMarioTornadoYawVel);
|
||||
|
||||
nextPos[0] = usedObj->oPosX + dx * cosAngleVel + dz * sinAngleVel;
|
||||
nextPos[2] = usedObj->oPosZ - dx * sinAngleVel + dz * cosAngleVel;
|
||||
nextPos[1] = usedObj->oPosY + marioObj->oMarioTornadoPosY;
|
||||
|
||||
f32_find_wall_collision(&nextPos[0], &nextPos[1], &nextPos[2], 60.0f, 50.0f);
|
||||
|
||||
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
|
||||
if (floor != NULL) {
|
||||
m->floor = floor;
|
||||
m->floorHeight = floorHeight;
|
||||
vec3f_copy(m->pos, nextPos);
|
||||
} else {
|
||||
if (nextPos[1] >= m->floorHeight) {
|
||||
m->pos[1] = nextPos[1];
|
||||
} else {
|
||||
m->pos[1] = m->floorHeight;
|
||||
}
|
||||
}
|
||||
|
||||
m->actionTimer++;
|
||||
|
||||
set_mario_animation(m, (m->actionArg == 0) ? MARIO_ANIM_START_TWIRL : MARIO_ANIM_TWIRL);
|
||||
|
||||
if (is_anim_past_end(m)) {
|
||||
m->actionArg = 1;
|
||||
}
|
||||
|
||||
// Play sound on angle overflow
|
||||
if (prevTwirlYaw > m->twirlYaw) {
|
||||
play_sound(SOUND_ACTION_TWIRL, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
|
||||
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
|
||||
vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1] + m->twirlYaw, 0);
|
||||
#ifdef VERSION_SH
|
||||
reset_rumble_timers();
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 check_common_automatic_cancels(struct MarioState *m) {
|
||||
if (m->pos[1] < m->waterLevel - 100) {
|
||||
return set_water_plunge_action(m);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 mario_execute_automatic_action(struct MarioState *m) {
|
||||
s32 cancel;
|
||||
|
||||
if (check_common_automatic_cancels(m)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
m->quicksandDepth = 0.0f;
|
||||
|
||||
/* clang-format off */
|
||||
switch (m->action) {
|
||||
case ACT_HOLDING_POLE: cancel = act_holding_pole(m); break;
|
||||
case ACT_GRAB_POLE_SLOW: cancel = act_grab_pole_slow(m); break;
|
||||
case ACT_GRAB_POLE_FAST: cancel = act_grab_pole_fast(m); break;
|
||||
case ACT_CLIMBING_POLE: cancel = act_climbing_pole(m); break;
|
||||
case ACT_TOP_OF_POLE_TRANSITION: cancel = act_top_of_pole_transition(m); break;
|
||||
case ACT_TOP_OF_POLE: cancel = act_top_of_pole(m); break;
|
||||
case ACT_START_HANGING: cancel = act_start_hanging(m); break;
|
||||
case ACT_HANGING: cancel = act_hanging(m); break;
|
||||
case ACT_HANG_MOVING: cancel = act_hang_moving(m); break;
|
||||
case ACT_LEDGE_GRAB: cancel = act_ledge_grab(m); break;
|
||||
case ACT_LEDGE_CLIMB_SLOW_1: cancel = act_ledge_climb_slow(m); break;
|
||||
case ACT_LEDGE_CLIMB_SLOW_2: cancel = act_ledge_climb_slow(m); break;
|
||||
case ACT_LEDGE_CLIMB_DOWN: cancel = act_ledge_climb_down(m); break;
|
||||
case ACT_LEDGE_CLIMB_FAST: cancel = act_ledge_climb_fast(m); break;
|
||||
case ACT_GRABBED: cancel = act_grabbed(m); break;
|
||||
case ACT_IN_CANNON: cancel = act_in_cannon(m); break;
|
||||
case ACT_TORNADO_TWIRLING: cancel = act_tornado_twirling(m); break;
|
||||
}
|
||||
/* clang-format on */
|
||||
|
||||
return cancel;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef MARIO_ACTIONS_AUTOMATIC_H
|
||||
#define MARIO_ACTIONS_AUTOMATIC_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
s32 mario_execute_automatic_action(struct MarioState *m);
|
||||
|
||||
#endif // MARIO_ACTIONS_AUTOMATIC_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
#ifndef MARIO_ACTIONS_CUTSCENE_H
|
||||
#define MARIO_ACTIONS_CUTSCENE_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/macros.h"
|
||||
#include "../include/types.h"
|
||||
|
||||
void print_displaying_credits_entry(void);
|
||||
void bhv_end_peach_loop(void);
|
||||
void bhv_end_toad_loop(void);
|
||||
s32 geo_switch_peach_eyes(s32 run, struct GraphNode *node, UNUSED s32 a2);
|
||||
s32 mario_ready_to_speak(void);
|
||||
s32 set_mario_npc_dialog(s32 actionArg);
|
||||
s32 mario_execute_cutscene_action(struct MarioState *m);
|
||||
|
||||
#endif // MARIO_ACTIONS_CUTSCENE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
#ifndef MARIO_ACTIONS_MOVING
|
||||
#define MARIO_ACTIONS_MOVING
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
void play_step_sound(struct MarioState *m, s16 frame1, s16 frame2);
|
||||
s32 mario_execute_moving_action(struct MarioState *m);
|
||||
|
||||
#endif // MARIO_ACTIONS_MOVING
|
||||
@@ -0,0 +1,496 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
#include "../shim.h"
|
||||
|
||||
#include "../include/sm64.h"
|
||||
#include "mario_actions_object.h"
|
||||
#include "../include/types.h"
|
||||
#include "mario_step.h"
|
||||
#include "mario.h"
|
||||
//#include "audio/external.h"
|
||||
#include "interaction.h"
|
||||
//#include "audio_defines.h"
|
||||
#include "../engine/math_util.h"
|
||||
//#include "thread6.h"
|
||||
#include "../include/mario_animation_ids.h"
|
||||
#include "../include/object_fields.h"
|
||||
#include "../include/mario_geo_switch_case_ids.h"
|
||||
|
||||
/**
|
||||
* Used by act_punching() to determine Mario's forward velocity during each
|
||||
* animation frame.
|
||||
*/
|
||||
s8 sPunchingForwardVelocities[8] = { 0, 1, 1, 2, 3, 5, 7, 10 };
|
||||
|
||||
void animated_stationary_ground_step(struct MarioState *m, s32 animation, u32 endAction) {
|
||||
stationary_ground_step(m);
|
||||
set_mario_animation(m, animation);
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, endAction, 0);
|
||||
}
|
||||
}
|
||||
|
||||
s32 mario_update_punch_sequence(struct MarioState *m) {
|
||||
u32 endAction, crouchEndAction;
|
||||
s32 animFrame;
|
||||
|
||||
if (m->action & ACT_FLAG_MOVING) {
|
||||
endAction = ACT_WALKING, crouchEndAction = ACT_CROUCH_SLIDE;
|
||||
} else {
|
||||
endAction = ACT_IDLE, crouchEndAction = ACT_CROUCHING;
|
||||
}
|
||||
|
||||
switch (m->actionArg) {
|
||||
case 0:
|
||||
play_sound(SOUND_MARIO_PUNCH_YAH, m->marioObj->header.gfx.cameraToObject);
|
||||
// Fall-through:
|
||||
case 1:
|
||||
set_mario_animation(m, MARIO_ANIM_FIRST_PUNCH);
|
||||
if (is_anim_past_end(m)) {
|
||||
m->actionArg = 2;
|
||||
} else {
|
||||
m->actionArg = 1;
|
||||
}
|
||||
|
||||
if (m->marioObj->header.gfx.animInfo.animFrame >= 2) {
|
||||
if (mario_check_object_grab(m)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
m->flags |= MARIO_PUNCHING;
|
||||
}
|
||||
|
||||
if (m->actionArg == 2) {
|
||||
m->marioBodyState->punchState = (0 << 6) | 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
set_mario_animation(m, MARIO_ANIM_FIRST_PUNCH_FAST);
|
||||
|
||||
if (m->marioObj->header.gfx.animInfo.animFrame <= 0) {
|
||||
m->flags |= MARIO_PUNCHING;
|
||||
}
|
||||
|
||||
if (m->input & INPUT_B_PRESSED) {
|
||||
m->actionArg = 3;
|
||||
}
|
||||
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, endAction, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
play_sound(SOUND_MARIO_PUNCH_WAH, m->marioObj->header.gfx.cameraToObject);
|
||||
// Fall-through:
|
||||
case 4:
|
||||
set_mario_animation(m, MARIO_ANIM_SECOND_PUNCH);
|
||||
if (is_anim_past_end(m)) {
|
||||
m->actionArg = 5;
|
||||
} else {
|
||||
m->actionArg = 4;
|
||||
}
|
||||
|
||||
if (m->marioObj->header.gfx.animInfo.animFrame > 0) {
|
||||
m->flags |= MARIO_PUNCHING;
|
||||
}
|
||||
|
||||
if (m->actionArg == 5) {
|
||||
m->marioBodyState->punchState = (1 << 6) | 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
set_mario_animation(m, MARIO_ANIM_SECOND_PUNCH_FAST);
|
||||
if (m->marioObj->header.gfx.animInfo.animFrame <= 0) {
|
||||
m->flags |= MARIO_PUNCHING;
|
||||
}
|
||||
|
||||
if (m->input & INPUT_B_PRESSED) {
|
||||
m->actionArg = 6;
|
||||
}
|
||||
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, endAction, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
play_mario_action_sound(m, SOUND_MARIO_PUNCH_HOO, 1);
|
||||
animFrame = set_mario_animation(m, MARIO_ANIM_GROUND_KICK);
|
||||
if (animFrame == 0) {
|
||||
m->marioBodyState->punchState = (2 << 6) | 6;
|
||||
}
|
||||
|
||||
if (animFrame >= 0 && animFrame < 8) {
|
||||
m->flags |= MARIO_KICKING;
|
||||
}
|
||||
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, endAction, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
play_mario_action_sound(m, SOUND_MARIO_PUNCH_HOO, 1);
|
||||
set_mario_animation(m, MARIO_ANIM_BREAKDANCE);
|
||||
animFrame = m->marioObj->header.gfx.animInfo.animFrame;
|
||||
|
||||
if (animFrame >= 2 && animFrame < 8) {
|
||||
m->flags |= MARIO_TRIPPING;
|
||||
}
|
||||
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, crouchEndAction, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_punching(struct MarioState *m) {
|
||||
if (m->input & INPUT_UNKNOWN_10) {
|
||||
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
|
||||
}
|
||||
|
||||
if (m->input & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE)) {
|
||||
return check_common_action_exits(m);
|
||||
}
|
||||
|
||||
if (m->actionState == 0 && (m->input & INPUT_A_DOWN)) {
|
||||
return set_mario_action(m, ACT_JUMP_KICK, 0);
|
||||
}
|
||||
|
||||
m->actionState = 1;
|
||||
if (m->actionArg == 0) {
|
||||
m->actionTimer = 7;
|
||||
}
|
||||
|
||||
mario_set_forward_vel(m, sPunchingForwardVelocities[m->actionTimer]);
|
||||
if (m->actionTimer > 0) {
|
||||
m->actionTimer--;
|
||||
}
|
||||
|
||||
mario_update_punch_sequence(m);
|
||||
perform_ground_step(m);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_picking_up(struct MarioState *m) {
|
||||
if (m->input & INPUT_UNKNOWN_10) {
|
||||
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (m->actionState == 0 && is_anim_at_end(m)) {
|
||||
//! While the animation is playing, it is possible for the used object
|
||||
// to unload. This allows you to pick up a vacant or newly loaded object
|
||||
// slot (cloning via fake object).
|
||||
mario_grab_used_object(m);
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_HRMM, MARIO_MARIO_SOUND_PLAYED);
|
||||
m->actionState = 1;
|
||||
}
|
||||
|
||||
if (m->actionState == 1) {
|
||||
if (m->heldObj->oInteractionSubtype & INT_SUBTYPE_GRABS_MARIO) {
|
||||
m->marioBodyState->grabPos = GRAB_POS_HEAVY_OBJ;
|
||||
set_mario_animation(m, MARIO_ANIM_GRAB_HEAVY_OBJECT);
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, ACT_HOLD_HEAVY_IDLE, 0);
|
||||
}
|
||||
} else {
|
||||
m->marioBodyState->grabPos = GRAB_POS_LIGHT_OBJ;
|
||||
set_mario_animation(m, MARIO_ANIM_PICK_UP_LIGHT_OBJ);
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, ACT_HOLD_IDLE, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stationary_ground_step(m);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_dive_picking_up(struct MarioState *m) {
|
||||
if (m->input & INPUT_UNKNOWN_10) {
|
||||
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
|
||||
}
|
||||
|
||||
//! Hands-free holding. Landing on a slope or being pushed off a ledge while
|
||||
// landing from a dive grab sets Mario's action to a non-holding action
|
||||
// without dropping the object, causing the hands-free holding glitch.
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_ABOVE_SLIDE) {
|
||||
return set_mario_action(m, ACT_BEGIN_SLIDING, 0);
|
||||
}
|
||||
|
||||
animated_stationary_ground_step(m, MARIO_ANIM_STOP_SLIDE_LIGHT_OBJ, ACT_HOLD_IDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_placing_down(struct MarioState *m) {
|
||||
if (m->input & INPUT_UNKNOWN_10) {
|
||||
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (++m->actionTimer == 8) {
|
||||
mario_drop_held_object(m);
|
||||
}
|
||||
|
||||
animated_stationary_ground_step(m, MARIO_ANIM_PLACE_LIGHT_OBJ, ACT_IDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_throwing(struct MarioState *m) {
|
||||
if (m->heldObj && (m->heldObj->oInteractionSubtype & INT_SUBTYPE_HOLDABLE_NPC)) {
|
||||
return set_mario_action(m, ACT_PLACING_DOWN, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_UNKNOWN_10) {
|
||||
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (++m->actionTimer == 7) {
|
||||
mario_throw_held_object(m);
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_WAH2, MARIO_MARIO_SOUND_PLAYED);
|
||||
play_sound_if_no_flag(m, SOUND_ACTION_THROW, MARIO_ACTION_SOUND_PLAYED);
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(3, 50);
|
||||
#endif
|
||||
}
|
||||
|
||||
animated_stationary_ground_step(m, MARIO_ANIM_GROUND_THROW, ACT_IDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_heavy_throw(struct MarioState *m) {
|
||||
if (m->input & INPUT_UNKNOWN_10) {
|
||||
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (++m->actionTimer == 13) {
|
||||
mario_drop_held_object(m);
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_WAH2, MARIO_MARIO_SOUND_PLAYED);
|
||||
play_sound_if_no_flag(m, SOUND_ACTION_THROW, MARIO_ACTION_SOUND_PLAYED);
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(3, 50);
|
||||
#endif
|
||||
}
|
||||
|
||||
animated_stationary_ground_step(m, MARIO_ANIM_HEAVY_THROW, ACT_IDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_stomach_slide_stop(struct MarioState *m) {
|
||||
if (m->input & INPUT_UNKNOWN_10) {
|
||||
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_ABOVE_SLIDE) {
|
||||
return set_mario_action(m, ACT_BEGIN_SLIDING, 0);
|
||||
}
|
||||
|
||||
animated_stationary_ground_step(m, MARIO_ANIM_SLOW_LAND_FROM_DIVE, ACT_IDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_picking_up_bowser(struct MarioState *m) {
|
||||
if (m->actionState == 0) {
|
||||
m->actionState = 1;
|
||||
m->angleVel[1] = 0;
|
||||
m->marioBodyState->grabPos = GRAB_POS_BOWSER;
|
||||
mario_grab_used_object(m);
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
play_sound(SOUND_MARIO_HRMM, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
|
||||
set_mario_animation(m, MARIO_ANIM_GRAB_BOWSER);
|
||||
if (is_anim_at_end(m)) {
|
||||
set_mario_action(m, ACT_HOLDING_BOWSER, 0);
|
||||
}
|
||||
|
||||
stationary_ground_step(m);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_holding_bowser(struct MarioState *m) {
|
||||
s16 spin;
|
||||
|
||||
if (m->input & INPUT_B_PRESSED) {
|
||||
#ifndef VERSION_JP
|
||||
if (m->angleVel[1] <= -0xE00 || m->angleVel[1] >= 0xE00) {
|
||||
play_sound(SOUND_MARIO_SO_LONGA_BOWSER, m->marioObj->header.gfx.cameraToObject);
|
||||
} else {
|
||||
play_sound(SOUND_MARIO_HERE_WE_GO, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
#else
|
||||
play_sound(SOUND_MARIO_HERE_WE_GO, m->marioObj->header.gfx.cameraToObject);
|
||||
#endif
|
||||
return set_mario_action(m, ACT_RELEASING_BOWSER, 0);
|
||||
}
|
||||
|
||||
if (m->angleVel[1] == 0) {
|
||||
if (m->actionTimer++ > 120) {
|
||||
return set_mario_action(m, ACT_RELEASING_BOWSER, 1);
|
||||
}
|
||||
|
||||
set_mario_animation(m, MARIO_ANIM_HOLDING_BOWSER);
|
||||
} else {
|
||||
m->actionTimer = 0;
|
||||
set_mario_animation(m, MARIO_ANIM_SWINGING_BOWSER);
|
||||
}
|
||||
|
||||
if (m->intendedMag > 20.0f) {
|
||||
if (m->actionArg == 0) {
|
||||
m->actionArg = 1;
|
||||
m->twirlYaw = m->intendedYaw;
|
||||
} else {
|
||||
// spin = acceleration
|
||||
spin = (s16)(m->intendedYaw - m->twirlYaw) / 0x80;
|
||||
|
||||
if (spin < -0x80) {
|
||||
spin = -0x80;
|
||||
}
|
||||
if (spin > 0x80) {
|
||||
spin = 0x80;
|
||||
}
|
||||
|
||||
m->twirlYaw = m->intendedYaw;
|
||||
m->angleVel[1] += spin;
|
||||
|
||||
if (m->angleVel[1] > 0x1000) {
|
||||
m->angleVel[1] = 0x1000;
|
||||
}
|
||||
if (m->angleVel[1] < -0x1000) {
|
||||
m->angleVel[1] = -0x1000;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m->actionArg = 0;
|
||||
m->angleVel[1] = approach_s32(m->angleVel[1], 0, 64, 64);
|
||||
}
|
||||
|
||||
// spin = starting yaw
|
||||
spin = m->faceAngle[1];
|
||||
m->faceAngle[1] += m->angleVel[1];
|
||||
|
||||
// play sound on overflow
|
||||
if (m->angleVel[1] <= -0x100 && spin < m->faceAngle[1]) {
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(4, 20);
|
||||
#endif
|
||||
play_sound(SOUND_OBJ_BOWSER_SPINNING, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
if (m->angleVel[1] >= 0x100 && spin > m->faceAngle[1]) {
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(4, 20);
|
||||
#endif
|
||||
play_sound(SOUND_OBJ_BOWSER_SPINNING, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
|
||||
stationary_ground_step(m);
|
||||
if (m->angleVel[1] >= 0) {
|
||||
m->marioObj->header.gfx.angle[0] = -m->angleVel[1];
|
||||
} else {
|
||||
m->marioObj->header.gfx.angle[0] = m->angleVel[1];
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_releasing_bowser(struct MarioState *m) {
|
||||
if (++m->actionTimer == 1) {
|
||||
if (m->actionArg == 0) {
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(4, 50);
|
||||
#endif
|
||||
mario_throw_held_object(m);
|
||||
} else {
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(4, 50);
|
||||
#endif
|
||||
mario_drop_held_object(m);
|
||||
}
|
||||
}
|
||||
|
||||
m->angleVel[1] = 0;
|
||||
animated_stationary_ground_step(m, MARIO_ANIM_RELEASE_BOWSER, ACT_IDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 check_common_object_cancels(struct MarioState *m) {
|
||||
f32 waterSurface = m->waterLevel - 100;
|
||||
if (m->pos[1] < waterSurface) {
|
||||
return set_water_plunge_action(m);
|
||||
}
|
||||
|
||||
if (m->input & INPUT_SQUISHED) {
|
||||
return drop_and_set_mario_action(m, ACT_SQUISHED, 0);
|
||||
}
|
||||
|
||||
if (m->health < 0x100) {
|
||||
return drop_and_set_mario_action(m, ACT_STANDING_DEATH, 0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 mario_execute_object_action(struct MarioState *m) {
|
||||
s32 cancel;
|
||||
|
||||
if (check_common_object_cancels(m)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (mario_update_quicksand(m, 0.5f)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
switch (m->action) {
|
||||
case ACT_PUNCHING: cancel = act_punching(m); break;
|
||||
case ACT_PICKING_UP: cancel = act_picking_up(m); break;
|
||||
case ACT_DIVE_PICKING_UP: cancel = act_dive_picking_up(m); break;
|
||||
case ACT_STOMACH_SLIDE_STOP: cancel = act_stomach_slide_stop(m); break;
|
||||
case ACT_PLACING_DOWN: cancel = act_placing_down(m); break;
|
||||
case ACT_THROWING: cancel = act_throwing(m); break;
|
||||
case ACT_HEAVY_THROW: cancel = act_heavy_throw(m); break;
|
||||
case ACT_PICKING_UP_BOWSER: cancel = act_picking_up_bowser(m); break;
|
||||
case ACT_HOLDING_BOWSER: cancel = act_holding_bowser(m); break;
|
||||
case ACT_RELEASING_BOWSER: cancel = act_releasing_bowser(m); break;
|
||||
}
|
||||
/* clang-format on */
|
||||
|
||||
if (!cancel && (m->input & INPUT_IN_WATER)) {
|
||||
m->particleFlags |= PARTICLE_IDLE_WATER_WAVE;
|
||||
}
|
||||
|
||||
return cancel;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef MARIO_ACTIONS_OBJECT_H
|
||||
#define MARIO_ACTIONS_OBJECT_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
s32 mario_update_punch_sequence(struct MarioState *m);
|
||||
s32 mario_execute_object_action(struct MarioState *m);
|
||||
|
||||
#endif // MARIO_ACTIONS_OBJECT_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
#ifndef MARIO_ACTIONS_STATIONARY
|
||||
#define MARIO_ACTIONS_STATIONARY
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
s32 check_common_idle_cancels(struct MarioState *m);
|
||||
s32 check_common_hold_idle_cancels(struct MarioState *m);
|
||||
s32 act_idle(struct MarioState *m);
|
||||
void play_anim_sound(struct MarioState *m, u32 actionState, s32 animFrame, u32 sound);
|
||||
s32 act_start_sleeping(struct MarioState *m);
|
||||
s32 act_sleeping(struct MarioState *m);
|
||||
s32 act_waking_up(struct MarioState *m);
|
||||
s32 act_shivering(struct MarioState *m);
|
||||
s32 act_coughing(struct MarioState *m);
|
||||
s32 act_standing_against_wall(struct MarioState *m);
|
||||
s32 act_in_quicksand(struct MarioState *m);
|
||||
s32 act_crouching(struct MarioState *m);
|
||||
s32 act_panting(struct MarioState *m);
|
||||
void stopping_step(struct MarioState *m, s32 animID, u32 action);
|
||||
s32 act_braking_stop(struct MarioState *m);
|
||||
s32 act_butt_slide_stop(struct MarioState *m);
|
||||
s32 act_hold_butt_slide_stop(struct MarioState *m);
|
||||
s32 act_slide_kick_slide_stop(struct MarioState *m);
|
||||
s32 act_start_crouching(struct MarioState *m);
|
||||
s32 act_stop_crouching(struct MarioState *m);
|
||||
s32 act_start_crawling(struct MarioState *m);
|
||||
s32 act_stop_crawling(struct MarioState *m);
|
||||
s32 act_shockwave_bounce(struct MarioState *m);
|
||||
s32 landing_step(struct MarioState *m, s32 arg1, u32 action);
|
||||
s32 check_common_landing_cancels(struct MarioState *m, u32 action);
|
||||
s32 act_jump_land_stop(struct MarioState *m);
|
||||
s32 act_double_jump_land_stop(struct MarioState *m);
|
||||
s32 act_side_flip_land_stop(struct MarioState *m);
|
||||
s32 act_freefall_land_stop(struct MarioState *m);
|
||||
s32 act_triple_jump_land_stop(struct MarioState *m);
|
||||
s32 act_backflip_land_stop(struct MarioState *m);
|
||||
s32 act_lava_boost_land(struct MarioState *m);
|
||||
s32 act_long_jump_land_stop(struct MarioState *m);
|
||||
s32 act_hold_jump_land_stop(struct MarioState *m);
|
||||
s32 act_hold_freefall_land_stop(struct MarioState *m);
|
||||
s32 act_air_throw_land(struct MarioState *m);
|
||||
s32 act_twirl_land(struct MarioState *m);
|
||||
s32 act_ground_pound_land(struct MarioState *m);
|
||||
s32 act_first_person(struct MarioState *m);
|
||||
s32 check_common_stationary_cancels(struct MarioState *m);
|
||||
s32 mario_execute_stationary_action(struct MarioState *m);
|
||||
|
||||
#endif // MARIO_ACTIONS_STATIONARY
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
#ifndef MARIO_ACTIONS_SUBMERGED_H
|
||||
#define MARIO_ACTIONS_SUBMERGED_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
s32 mario_execute_submerged_action(struct MarioState *m);
|
||||
|
||||
#endif // MARIO_ACTIONS_SUBMERGED_H
|
||||
@@ -0,0 +1,657 @@
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/sm64.h"
|
||||
#include "area.h"
|
||||
//#include "audio/external.h"
|
||||
//#include "behavior_actions.h"
|
||||
//#include "behavior_data.h"
|
||||
#include "camera.h"
|
||||
//#include "dialog_ids.h"
|
||||
//#include "engine/behavior_script.h"
|
||||
#include "../engine/graph_node.h"
|
||||
#include "../engine/math_util.h"
|
||||
//#include "envfx_snow.h"
|
||||
//#include "game_init.h"
|
||||
//#include "goddard/renderer.h"
|
||||
#include "interaction.h"
|
||||
#include "level_update.h"
|
||||
#include "mario_misc.h"
|
||||
#include "../memory.h"
|
||||
//#include "object_helpers.h"
|
||||
//#include "object_list_processor.h"
|
||||
#include "rendering_graph_node.h"
|
||||
#include "save_file.h"
|
||||
//#include "skybox.h"
|
||||
//#include "sound_init.h"
|
||||
#include "../shim.h"
|
||||
#include "../include/mario_animation_ids.h"
|
||||
#include "../include/object_fields.h"
|
||||
#include "../include/mario_geo_switch_case_ids.h"
|
||||
|
||||
|
||||
static Vec3f gVec3fZero = {0,0,0};
|
||||
static Vec3s gVec3sZero = {0,0,0};
|
||||
static Vec3f gVec3fOne = {1,1,1};
|
||||
|
||||
#define TOAD_STAR_1_REQUIREMENT 12
|
||||
#define TOAD_STAR_2_REQUIREMENT 25
|
||||
#define TOAD_STAR_3_REQUIREMENT 35
|
||||
|
||||
#define TOAD_STAR_1_DIALOG 90 // DIALOG_082
|
||||
#define TOAD_STAR_2_DIALOG 91 // DIALOG_076
|
||||
#define TOAD_STAR_3_DIALOG 92 // DIALOG_083
|
||||
|
||||
#define TOAD_STAR_1_DIALOG_AFTER 90 // DIALOG_154
|
||||
#define TOAD_STAR_2_DIALOG_AFTER 91 // DIALOG_155
|
||||
#define TOAD_STAR_3_DIALOG_AFTER 92 // DIALOG_156
|
||||
|
||||
enum ToadMessageStates {
|
||||
TOAD_MESSAGE_FADED,
|
||||
TOAD_MESSAGE_OPAQUE,
|
||||
TOAD_MESSAGE_OPACIFYING,
|
||||
TOAD_MESSAGE_FADING,
|
||||
TOAD_MESSAGE_TALKING
|
||||
};
|
||||
|
||||
enum UnlockDoorStarStates {
|
||||
UNLOCK_DOOR_STAR_RISING,
|
||||
UNLOCK_DOOR_STAR_WAITING,
|
||||
UNLOCK_DOOR_STAR_SPAWNING_PARTICLES,
|
||||
UNLOCK_DOOR_STAR_DONE
|
||||
};
|
||||
|
||||
/**
|
||||
* The eye texture on succesive frames of Mario's blink animation.
|
||||
* He intentionally blinks twice each time.
|
||||
*/
|
||||
static s8 gMarioBlinkAnimation[7] = { 1, 2, 1, 0, 1, 2, 1 };
|
||||
|
||||
/**
|
||||
* The scale values per frame for Mario's foot/hand for his attack animation
|
||||
* There are 3 scale animations in groups of 6 frames.
|
||||
* The first animation starts at frame index 3 and goes down, the others start at frame index 5.
|
||||
* The values get divided by 10 before assigning, so e.g. 12 gives a scale factor 1.2.
|
||||
* All combined, this means e.g. the first animation scales Mario's fist by {2.4, 1.6, 1.2, 1.0} on
|
||||
* successive frames.
|
||||
*/
|
||||
static s8 gMarioAttackScaleAnimation[3 * 6] = {
|
||||
10, 12, 16, 24, 10, 10, 10, 14, 20, 30, 10, 10, 10, 16, 20, 26, 26, 20,
|
||||
};
|
||||
|
||||
struct MarioBodyState gBodyStates[2]; // 2nd is never accessed in practice, most likely Luigi related
|
||||
//struct GraphNodeObject gMirrorMario; // copy of Mario's geo node for drawing mirror Mario
|
||||
|
||||
// This whole file is weirdly organized. It has to be the same file due
|
||||
// to rodata boundaries and function aligns, which means the programmer
|
||||
// treated this like a "misc" file for vaguely Mario related things
|
||||
// (message NPC related things, the Mario head geo, and Mario geo
|
||||
// functions)
|
||||
|
||||
/**
|
||||
* Geo node script that draws Mario's head on the title screen.
|
||||
*/
|
||||
// Gfx *geo_draw_mario_head_goddard(s32 callContext, struct GraphNode *node, Mat4 *c) {
|
||||
// Gfx *gfx = NULL;
|
||||
// s16 sfx = 0;
|
||||
// struct GraphNodeGenerated *asGenerated = (struct GraphNodeGenerated *) node;
|
||||
// UNUSED Mat4 *transform = c;
|
||||
//
|
||||
// if (callContext == GEO_CONTEXT_RENDER) {
|
||||
// if (gPlayerController->controllerData != NULL && !gWarpTransition.isActive) {
|
||||
// gd_copy_p1_contpad(gPlayer1Controller->controllerData);
|
||||
// }
|
||||
// gfx = (Gfx *) PHYSICAL_TO_VIRTUAL(gdm_gettestdl(asGenerated->parameter));
|
||||
// D_8032C6A0 = gd_vblank;
|
||||
// sfx = gd_sfx_to_play();
|
||||
// play_menu_sounds(sfx);
|
||||
// }
|
||||
// return gfx;
|
||||
// }
|
||||
|
||||
static void toad_message_faded(void) {
|
||||
// if (gCurrentObject->oDistanceToMario > 700.0f) {
|
||||
// gCurrentObject->oToadMessageRecentlyTalked = FALSE;
|
||||
// }
|
||||
// if (!gCurrentObject->oToadMessageRecentlyTalked && gCurrentObject->oDistanceToMario < 600.0f) {
|
||||
// gCurrentObject->oToadMessageState = TOAD_MESSAGE_OPACIFYING;
|
||||
// }
|
||||
}
|
||||
|
||||
static void toad_message_opaque(void) {
|
||||
// if (gCurrentObject->oDistanceToMario > 700.0f) {
|
||||
// gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING;
|
||||
// } else if (!gCurrentObject->oToadMessageRecentlyTalked) {
|
||||
// gCurrentObject->oInteractionSubtype = INT_SUBTYPE_NPC;
|
||||
// if (gCurrentObject->oInteractStatus & INT_STATUS_INTERACTED) {
|
||||
// gCurrentObject->oInteractStatus = 0;
|
||||
// gCurrentObject->oToadMessageState = TOAD_MESSAGE_TALKING;
|
||||
// play_toads_jingle();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
static void toad_message_talking(void) {
|
||||
// if (cur_obj_update_dialog_with_cutscene(3, 1, CUTSCENE_DIALOG, gCurrentObject->oToadMessageDialogId)
|
||||
// != 0) {
|
||||
// gCurrentObject->oToadMessageRecentlyTalked = TRUE;
|
||||
// gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING;
|
||||
// switch (gCurrentObject->oToadMessageDialogId) {
|
||||
// case TOAD_STAR_1_DIALOG:
|
||||
// gCurrentObject->oToadMessageDialogId = TOAD_STAR_1_DIALOG_AFTER;
|
||||
// bhv_spawn_star_no_level_exit(0);
|
||||
// break;
|
||||
// case TOAD_STAR_2_DIALOG:
|
||||
// gCurrentObject->oToadMessageDialogId = TOAD_STAR_2_DIALOG_AFTER;
|
||||
// bhv_spawn_star_no_level_exit(1);
|
||||
// break;
|
||||
// case TOAD_STAR_3_DIALOG:
|
||||
// gCurrentObject->oToadMessageDialogId = TOAD_STAR_3_DIALOG_AFTER;
|
||||
// bhv_spawn_star_no_level_exit(2);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
static void toad_message_opacifying(void) {
|
||||
if ((gCurrentObject->oOpacity += 6) == 255) {
|
||||
gCurrentObject->oToadMessageState = TOAD_MESSAGE_OPAQUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void toad_message_fading(void) {
|
||||
if ((gCurrentObject->oOpacity -= 6) == 81) {
|
||||
gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADED;
|
||||
}
|
||||
}
|
||||
|
||||
void bhv_toad_message_loop(void) {
|
||||
if (gCurrentObject->header.gfx.node.flags & GRAPH_RENDER_ACTIVE) {
|
||||
gCurrentObject->oInteractionSubtype = 0;
|
||||
switch (gCurrentObject->oToadMessageState) {
|
||||
case TOAD_MESSAGE_FADED:
|
||||
toad_message_faded();
|
||||
break;
|
||||
case TOAD_MESSAGE_OPAQUE:
|
||||
toad_message_opaque();
|
||||
break;
|
||||
case TOAD_MESSAGE_OPACIFYING:
|
||||
toad_message_opacifying();
|
||||
break;
|
||||
case TOAD_MESSAGE_FADING:
|
||||
toad_message_fading();
|
||||
break;
|
||||
case TOAD_MESSAGE_TALKING:
|
||||
toad_message_talking();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bhv_toad_message_init(void) {
|
||||
// s32 saveFlags = save_file_get_flags();
|
||||
// s32 starCount = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
|
||||
// s32 dialogId = (gCurrentObject->oBehParams >> 24) & 0xFF;
|
||||
// s32 enoughStars = TRUE;
|
||||
//
|
||||
// switch (dialogId) {
|
||||
// case TOAD_STAR_1_DIALOG:
|
||||
// enoughStars = (starCount >= TOAD_STAR_1_REQUIREMENT);
|
||||
// if (saveFlags & SAVE_FLAG_COLLECTED_TOAD_STAR_1) {
|
||||
// dialogId = TOAD_STAR_1_DIALOG_AFTER;
|
||||
// }
|
||||
// break;
|
||||
// case TOAD_STAR_2_DIALOG:
|
||||
// enoughStars = (starCount >= TOAD_STAR_2_REQUIREMENT);
|
||||
// if (saveFlags & SAVE_FLAG_COLLECTED_TOAD_STAR_2) {
|
||||
// dialogId = TOAD_STAR_2_DIALOG_AFTER;
|
||||
// }
|
||||
// break;
|
||||
// case TOAD_STAR_3_DIALOG:
|
||||
// enoughStars = (starCount >= TOAD_STAR_3_REQUIREMENT);
|
||||
// if (saveFlags & SAVE_FLAG_COLLECTED_TOAD_STAR_3) {
|
||||
// dialogId = TOAD_STAR_3_DIALOG_AFTER;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// if (enoughStars) {
|
||||
// gCurrentObject->oToadMessageDialogId = dialogId;
|
||||
// gCurrentObject->oToadMessageRecentlyTalked = FALSE;
|
||||
// gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADED;
|
||||
// gCurrentObject->oOpacity = 81;
|
||||
// } else {
|
||||
// obj_mark_for_deletion(gCurrentObject);
|
||||
// }
|
||||
}
|
||||
|
||||
//static void star_door_unlock_spawn_particles(s16 angleOffset) {
|
||||
// struct Object *sparkleParticle = spawn_object(gCurrentObject, 0, bhvSparkleSpawn);
|
||||
//
|
||||
// sparkleParticle->oPosX +=
|
||||
// 100.0f * sins((gCurrentObject->oUnlockDoorStarTimer * 0x2800) + angleOffset);
|
||||
// sparkleParticle->oPosZ +=
|
||||
// 100.0f * coss((gCurrentObject->oUnlockDoorStarTimer * 0x2800) + angleOffset);
|
||||
// // Particles are spawned lower each frame
|
||||
// sparkleParticle->oPosY -= gCurrentObject->oUnlockDoorStarTimer * 10.0f;
|
||||
//}
|
||||
|
||||
void bhv_unlock_door_star_init(void) {
|
||||
// gCurrentObject->oUnlockDoorStarState = UNLOCK_DOOR_STAR_RISING;
|
||||
// gCurrentObject->oUnlockDoorStarTimer = 0;
|
||||
// gCurrentObject->oUnlockDoorStarYawVel = 0x1000;
|
||||
// gCurrentObject->oPosX += 30.0f * sins(gMarioState->faceAngle[1] - 0x4000);
|
||||
// gCurrentObject->oPosY += 160.0f;
|
||||
// gCurrentObject->oPosZ += 30.0f * coss(gMarioState->faceAngle[1] - 0x4000);
|
||||
// gCurrentObject->oMoveAngleYaw = 0x7800;
|
||||
// obj_scale(gCurrentObject, 0.5f);
|
||||
}
|
||||
|
||||
void bhv_unlock_door_star_loop(void) {
|
||||
// UNUSED u8 unused1[4];
|
||||
// s16 prevYaw = gCurrentObject->oMoveAngleYaw;
|
||||
// UNUSED u8 unused2[4];
|
||||
//
|
||||
// // Speed up the star every frame
|
||||
// if (gCurrentObject->oUnlockDoorStarYawVel < 0x2400) {
|
||||
// gCurrentObject->oUnlockDoorStarYawVel += 0x60;
|
||||
// }
|
||||
// switch (gCurrentObject->oUnlockDoorStarState) {
|
||||
// case UNLOCK_DOOR_STAR_RISING:
|
||||
// gCurrentObject->oPosY += 3.4f; // Raise the star up in the air
|
||||
// gCurrentObject->oMoveAngleYaw +=
|
||||
// gCurrentObject->oUnlockDoorStarYawVel; // Apply yaw velocity
|
||||
// obj_scale(gCurrentObject, gCurrentObject->oUnlockDoorStarTimer / 50.0f
|
||||
// + 0.5f); // Scale the star to be bigger
|
||||
// if (++gCurrentObject->oUnlockDoorStarTimer == 30) {
|
||||
// gCurrentObject->oUnlockDoorStarTimer = 0;
|
||||
// gCurrentObject->oUnlockDoorStarState++; // Sets state to UNLOCK_DOOR_STAR_WAITING
|
||||
// }
|
||||
// break;
|
||||
// case UNLOCK_DOOR_STAR_WAITING:
|
||||
// gCurrentObject->oMoveAngleYaw +=
|
||||
// gCurrentObject->oUnlockDoorStarYawVel; // Apply yaw velocity
|
||||
// if (++gCurrentObject->oUnlockDoorStarTimer == 30) {
|
||||
// play_sound(SOUND_MENU_STAR_SOUND,
|
||||
// gCurrentObject->header.gfx.cameraToObject); // Play final sound
|
||||
// cur_obj_hide(); // Hide the object
|
||||
// gCurrentObject->oUnlockDoorStarTimer = 0;
|
||||
// gCurrentObject
|
||||
// ->oUnlockDoorStarState++; // Sets state to UNLOCK_DOOR_STAR_SPAWNING_PARTICLES
|
||||
// }
|
||||
// break;
|
||||
// case UNLOCK_DOOR_STAR_SPAWNING_PARTICLES:
|
||||
// // Spawn two particles, opposite sides of the star.
|
||||
// star_door_unlock_spawn_particles(0);
|
||||
// star_door_unlock_spawn_particles(0x8000);
|
||||
// if (gCurrentObject->oUnlockDoorStarTimer++ == 20) {
|
||||
// gCurrentObject->oUnlockDoorStarTimer = 0;
|
||||
// gCurrentObject->oUnlockDoorStarState++; // Sets state to UNLOCK_DOOR_STAR_DONE
|
||||
// }
|
||||
// break;
|
||||
// case UNLOCK_DOOR_STAR_DONE: // The object stays loaded for an additional 50 frames so that the
|
||||
// // sound doesn't immediately stop.
|
||||
// if (gCurrentObject->oUnlockDoorStarTimer++ == 50) {
|
||||
// obj_mark_for_deletion(gCurrentObject);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// // Checks if the angle has cycled back to 0.
|
||||
// // This means that the code will execute when the star completes a full revolution.
|
||||
// if (prevYaw > (s16) gCurrentObject->oMoveAngleYaw) {
|
||||
// play_sound(
|
||||
// SOUND_GENERAL_SHORT_STAR,
|
||||
// gCurrentObject->header.gfx.cameraToObject); // Play a sound every time the star spins once
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a display list that sets the correct blend mode and color for mirror Mario.
|
||||
*/
|
||||
static Gfx *make_gfx_mario_alpha(struct GraphNodeGenerated *node, s16 alpha) {
|
||||
Gfx *gfx;
|
||||
Gfx *gfxHead = NULL;
|
||||
|
||||
if (alpha == 255) {
|
||||
node->fnNode.node.flags = (node->fnNode.node.flags & 0xFF) | (LAYER_OPAQUE << 8);
|
||||
gfxHead = alloc_display_list(2 * sizeof(*gfxHead));
|
||||
gfx = gfxHead;
|
||||
} else {
|
||||
node->fnNode.node.flags = (node->fnNode.node.flags & 0xFF) | (LAYER_TRANSPARENT << 8);
|
||||
gfxHead = alloc_display_list(3 * sizeof(*gfxHead));
|
||||
gfx = gfxHead;
|
||||
gDPSetAlphaCompare(gfx++, G_AC_DITHER);
|
||||
}
|
||||
gDPSetEnvColor(gfx++, 255, 255, 255, alpha);
|
||||
gSPEndDisplayList(gfx);
|
||||
return gfxHead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the correct blend mode and color for mirror Mario.
|
||||
*/
|
||||
Gfx *geo_mirror_mario_set_alpha(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
UNUSED u8 unused1[4];
|
||||
Gfx *gfx = NULL;
|
||||
struct GraphNodeGenerated *asGenerated = (struct GraphNodeGenerated *) node;
|
||||
struct MarioBodyState *bodyState = &gBodyStates[asGenerated->parameter];
|
||||
s16 alpha;
|
||||
UNUSED u8 unused2[4];
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
alpha = (bodyState->modelState & 0x100) ? (bodyState->modelState & 0xFF) : 255;
|
||||
gfx = make_gfx_mario_alpha(asGenerated, alpha);
|
||||
}
|
||||
return gfx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if Mario is standing or running for the level of detail of his model.
|
||||
* If Mario is standing still, he is always high poly. If he is running,
|
||||
* his level of detail depends on the distance to the camera.
|
||||
*/
|
||||
Gfx *geo_switch_mario_stand_run(s32 callContext, struct GraphNode *node, UNUSED Mat4 *mtx) {
|
||||
struct GraphNodeSwitchCase *switchCase = (struct GraphNodeSwitchCase *) node;
|
||||
struct MarioBodyState *bodyState = &gBodyStates[switchCase->numCases];
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
// assign result. 0 if moving, 1 if stationary.
|
||||
switchCase->selectedCase = ((bodyState->action & ACT_FLAG_STATIONARY) == 0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Geo node script that makes Mario blink
|
||||
*/
|
||||
Gfx *geo_switch_mario_eyes(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
struct GraphNodeSwitchCase *switchCase = (struct GraphNodeSwitchCase *) node;
|
||||
struct MarioBodyState *bodyState = &gBodyStates[switchCase->numCases];
|
||||
s16 blinkFrame;
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
if (bodyState->eyeState == 0) {
|
||||
blinkFrame = ((switchCase->numCases * 32 + gAreaUpdateCounter) >> 1) & 0x1F;
|
||||
if (blinkFrame < 7) {
|
||||
switchCase->selectedCase = gMarioBlinkAnimation[blinkFrame];
|
||||
} else {
|
||||
switchCase->selectedCase = 0;
|
||||
}
|
||||
} else {
|
||||
switchCase->selectedCase = bodyState->eyeState - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes Mario's upper body tilt depending on the rotation stored in his bodyState
|
||||
*/
|
||||
Gfx *geo_mario_tilt_torso(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
struct GraphNodeGenerated *asGenerated = (struct GraphNodeGenerated *) node;
|
||||
struct MarioBodyState *bodyState = &gBodyStates[asGenerated->parameter];
|
||||
s32 action = bodyState->action;
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
struct GraphNodeRotation *rotNode = (struct GraphNodeRotation *) node->next;
|
||||
|
||||
if (action != ACT_BUTT_SLIDE && action != ACT_HOLD_BUTT_SLIDE && action != ACT_WALKING
|
||||
&& action != ACT_RIDING_SHELL_GROUND) {
|
||||
vec3s_copy(bodyState->torsoAngle, gVec3sZero);
|
||||
}
|
||||
rotNode->rotation[0] = bodyState->torsoAngle[1];
|
||||
rotNode->rotation[1] = bodyState->torsoAngle[2];
|
||||
rotNode->rotation[2] = bodyState->torsoAngle[0];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes Mario's head rotate with the camera angle when in C-up mode
|
||||
*/
|
||||
Gfx *geo_mario_head_rotation(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
struct GraphNodeGenerated *asGenerated = (struct GraphNodeGenerated *) node;
|
||||
struct MarioBodyState *bodyState = &gBodyStates[asGenerated->parameter];
|
||||
// s32 action = bodyState->action;
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
struct GraphNodeRotation *rotNode = (struct GraphNodeRotation *) node->next;
|
||||
// struct Camera *camera = gCurGraphNodeCamera->config.camera;
|
||||
|
||||
// if (camera->mode == CAMERA_MODE_C_UP) {
|
||||
// rotNode->rotation[0] = 0; // gPlayerCameraState->headRotation[1]; // PATCH
|
||||
// rotNode->rotation[2] = 0; // gPlayerCameraState->headRotation[0];
|
||||
// } else if (action & ACT_FLAG_WATER_OR_TEXT) {
|
||||
// rotNode->rotation[0] = bodyState->headAngle[1];
|
||||
// rotNode->rotation[1] = bodyState->headAngle[2];
|
||||
// rotNode->rotation[2] = bodyState->headAngle[0];
|
||||
// } else {
|
||||
vec3s_set(bodyState->headAngle, 0, 0, 0);
|
||||
vec3s_set(rotNode->rotation, 0, 0, 0);
|
||||
// }
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch between hand models.
|
||||
* Possible options are described in the MarioHandGSCId enum.
|
||||
*/
|
||||
Gfx *geo_switch_mario_hand(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
struct GraphNodeSwitchCase *switchCase = (struct GraphNodeSwitchCase *) node;
|
||||
struct MarioBodyState *bodyState = &gBodyStates[0];
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
if (bodyState->handState == MARIO_HAND_FISTS) {
|
||||
// switch between fists (0) and open (1)
|
||||
switchCase->selectedCase = ((bodyState->action & ACT_FLAG_SWIMMING_OR_FLYING) != 0);
|
||||
} else {
|
||||
if (switchCase->numCases == 0) {
|
||||
switchCase->selectedCase =
|
||||
(bodyState->handState < 5) ? bodyState->handState : MARIO_HAND_OPEN;
|
||||
} else {
|
||||
switchCase->selectedCase =
|
||||
(bodyState->handState < 2) ? bodyState->handState : MARIO_HAND_FISTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase Mario's hand / foot size when he punches / kicks.
|
||||
* Since animation geo nodes only support rotation, this scaling animation
|
||||
* was scripted separately. The node with this script should be placed before
|
||||
* a scaling node containing the hand / foot geo layout.
|
||||
* ! Since the animation gets updated in GEO_CONTEXT_RENDER, drawing Mario multiple times
|
||||
* (such as in the mirror room) results in a faster and desynced punch / kick animation.
|
||||
*/
|
||||
Gfx *geo_mario_hand_foot_scaler(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
static s16 sMarioAttackAnimCounter = 0;
|
||||
struct GraphNodeGenerated *asGenerated = (struct GraphNodeGenerated *) node;
|
||||
struct GraphNodeScale *scaleNode = (struct GraphNodeScale *) node->next;
|
||||
struct MarioBodyState *bodyState = &gBodyStates[0];
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
scaleNode->scale = 1.0f;
|
||||
if (asGenerated->parameter == bodyState->punchState >> 6) {
|
||||
if (sMarioAttackAnimCounter != gAreaUpdateCounter && (bodyState->punchState & 0x3F) > 0) {
|
||||
bodyState->punchState -= 1;
|
||||
sMarioAttackAnimCounter = gAreaUpdateCounter;
|
||||
}
|
||||
scaleNode->scale =
|
||||
gMarioAttackScaleAnimation[asGenerated->parameter * 6 + (bodyState->punchState & 0x3F)]
|
||||
/ 10.0f;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch between normal cap, wing cap, vanish cap and metal cap.
|
||||
*/
|
||||
Gfx *geo_switch_mario_cap_effect(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
struct GraphNodeSwitchCase *switchCase = (struct GraphNodeSwitchCase *) node;
|
||||
struct MarioBodyState *bodyState = &gBodyStates[switchCase->numCases];
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
switchCase->selectedCase = bodyState->modelState >> 8;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether Mario's head is drawn with or without a cap on.
|
||||
* Also sets the visibility of the wing cap wings on or off.
|
||||
*/
|
||||
Gfx *geo_switch_mario_cap_on_off(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
struct GraphNode *next = node->next;
|
||||
struct GraphNodeSwitchCase *switchCase = (struct GraphNodeSwitchCase *) node;
|
||||
struct MarioBodyState *bodyState = &gBodyStates[switchCase->numCases];
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
switchCase->selectedCase = bodyState->capState & 1;
|
||||
while (next != node) {
|
||||
if (next->type == GRAPH_NODE_TYPE_TRANSLATION_ROTATION) {
|
||||
if (bodyState->capState & 2) {
|
||||
next->flags |= GRAPH_RENDER_ACTIVE;
|
||||
} else {
|
||||
next->flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
}
|
||||
}
|
||||
next = next->next;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Geo node script that makes the wings on Mario's wing cap flap.
|
||||
* Should be placed before a rotation node.
|
||||
*/
|
||||
Gfx *geo_mario_rotate_wing_cap_wings(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
s16 rotX;
|
||||
struct GraphNodeGenerated *asGenerated = (struct GraphNodeGenerated *) node;
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
struct GraphNodeRotation *rotNode = (struct GraphNodeRotation *) node->next;
|
||||
|
||||
if (!gBodyStates[asGenerated->parameter >> 1].wingFlutter) {
|
||||
rotX = (coss((gAreaUpdateCounter & 0xF) << 12) + 1.0f) * 4096.0f;
|
||||
} else {
|
||||
rotX = (coss((gAreaUpdateCounter & 7) << 13) + 1.0f) * 6144.0f;
|
||||
}
|
||||
if (!(asGenerated->parameter & 1)) {
|
||||
rotNode->rotation[0] = -rotX;
|
||||
} else {
|
||||
rotNode->rotation[0] = rotX;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Geo node that updates the held object node and the HOLP.
|
||||
*/
|
||||
Gfx *geo_switch_mario_hand_grab_pos(s32 callContext, struct GraphNode *b, Mat4 *mtx) {
|
||||
struct GraphNodeHeldObject *asHeldObj = (struct GraphNodeHeldObject *) b;
|
||||
Mat4 *curTransform = mtx;
|
||||
struct MarioState *marioState = gMarioState; // &gMarioStates[asHeldObj->playerIndex]; // PATCH
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
asHeldObj->objNode = NULL;
|
||||
if (marioState->heldObj != NULL) {
|
||||
asHeldObj->objNode = marioState->heldObj;
|
||||
switch (marioState->marioBodyState->grabPos) {
|
||||
case GRAB_POS_LIGHT_OBJ:
|
||||
if (marioState->action & ACT_FLAG_THROWING) {
|
||||
vec3s_set(asHeldObj->translation, 50, 0, 0);
|
||||
} else {
|
||||
vec3s_set(asHeldObj->translation, 50, 0, 110);
|
||||
}
|
||||
break;
|
||||
case GRAB_POS_HEAVY_OBJ:
|
||||
vec3s_set(asHeldObj->translation, 145, -173, 180);
|
||||
break;
|
||||
case GRAB_POS_BOWSER:
|
||||
vec3s_set(asHeldObj->translation, 80, -270, 1260);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (callContext == GEO_CONTEXT_HELD_OBJ) {
|
||||
// ! The HOLP is set here, which is why it only updates when the held object is drawn.
|
||||
// This is why it won't update during a pause buffered hitstun or when the camera is very far
|
||||
// away.
|
||||
get_pos_from_transform_mtx(marioState->marioBodyState->heldObjLastPosition, *curTransform,
|
||||
*gCurGraphNodeCamera->matrixPtr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// X position of the mirror
|
||||
#define MIRROR_X 4331.53
|
||||
|
||||
/**
|
||||
* Geo node that creates a clone of Mario's geo node and updates it to becomes
|
||||
* a mirror image of the player.
|
||||
*/
|
||||
Gfx *geo_render_mirror_mario(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
// f32 mirroredX;
|
||||
// struct Object *mario = gMarioState->marioObj; // PATCH gMarioStates[0].marioObj;
|
||||
|
||||
// switch (callContext) {
|
||||
// case GEO_CONTEXT_CREATE:
|
||||
// init_graph_node_object(NULL, &gMirrorMario, NULL, gVec3fZero, gVec3sZero, gVec3fOne);
|
||||
// break;
|
||||
// case GEO_CONTEXT_AREA_LOAD:
|
||||
// geo_add_child(node, &gMirrorMario.node);
|
||||
// break;
|
||||
// case GEO_CONTEXT_AREA_UNLOAD:
|
||||
// geo_remove_child(&gMirrorMario.node);
|
||||
// break;
|
||||
// case GEO_CONTEXT_RENDER:
|
||||
// if (mario->header.gfx.pos[0] > 1700.0f) {
|
||||
// // TODO: Is this a geo layout copy or a graph node copy?
|
||||
// gMirrorMario.sharedChild = mario->header.gfx.sharedChild;
|
||||
// gMirrorMario.areaIndex = mario->header.gfx.areaIndex;
|
||||
// vec3s_copy(gMirrorMario.angle, mario->header.gfx.angle);
|
||||
// vec3f_copy(gMirrorMario.pos, mario->header.gfx.pos);
|
||||
// vec3f_copy(gMirrorMario.scale, mario->header.gfx.scale);
|
||||
|
||||
// gMirrorMario.animInfo = mario->header.gfx.animInfo;
|
||||
// mirroredX = MIRROR_X - gMirrorMario.pos[0];
|
||||
// gMirrorMario.pos[0] = mirroredX + MIRROR_X;
|
||||
// gMirrorMario.angle[1] = -gMirrorMario.angle[1];
|
||||
// gMirrorMario.scale[0] *= -1.0f;
|
||||
// ((struct GraphNode *) &gMirrorMario)->flags |= 1;
|
||||
// } else {
|
||||
// ((struct GraphNode *) &gMirrorMario)->flags &= ~1;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since Mirror Mario has an x scale of -1, the mesh becomes inside out.
|
||||
* This node corrects that by changing the culling mode accordingly.
|
||||
*/
|
||||
Gfx *geo_mirror_mario_backface_culling(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) {
|
||||
// struct GraphNodeGenerated *asGenerated = (struct GraphNodeGenerated *) node;
|
||||
// Gfx *gfx = NULL;
|
||||
|
||||
// if (callContext == GEO_CONTEXT_RENDER && gCurGraphNodeObject == &gMirrorMario) {
|
||||
// gfx = alloc_display_list(3 * sizeof(*gfx));
|
||||
|
||||
// if (asGenerated->parameter == 0) {
|
||||
// gSPClearGeometryMode(&gfx[0], G_CULL_BACK);
|
||||
// gSPSetGeometryMode(&gfx[1], G_CULL_FRONT);
|
||||
// gSPEndDisplayList(&gfx[2]);
|
||||
// } else {
|
||||
// gSPClearGeometryMode(&gfx[0], G_CULL_FRONT);
|
||||
// gSPSetGeometryMode(&gfx[1], G_CULL_BACK);
|
||||
// gSPEndDisplayList(&gfx[2]);
|
||||
// }
|
||||
// asGenerated->fnNode.node.flags = (asGenerated->fnNode.node.flags & 0xFF) | (LAYER_OPAQUE << 8);
|
||||
// }
|
||||
// return gfx;
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef MARIO_MISC_H
|
||||
#define MARIO_MISC_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/macros.h"
|
||||
#include "../include/types.h"
|
||||
|
||||
extern struct GraphNodeObject gMirrorMario;
|
||||
extern struct MarioBodyState gBodyStates[2];
|
||||
|
||||
// Gfx *geo_draw_mario_head_goddard(s32 callContext, struct GraphNode *node, Mat4 *c);
|
||||
void bhv_toad_message_loop(void);
|
||||
void bhv_toad_message_init(void);
|
||||
void bhv_unlock_door_star_init(void);
|
||||
void bhv_unlock_door_star_loop(void);
|
||||
Gfx *geo_mirror_mario_set_alpha(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_switch_mario_stand_run(s32 callContext, struct GraphNode *node, UNUSED Mat4 *mtx);
|
||||
Gfx *geo_switch_mario_eyes(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_mario_tilt_torso(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_mario_head_rotation(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_switch_mario_hand(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_mario_hand_foot_scaler(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_switch_mario_cap_effect(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_switch_mario_cap_on_off(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_mario_rotate_wing_cap_wings(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_switch_mario_hand_grab_pos(s32 callContext, struct GraphNode *b, Mat4 *mtx);
|
||||
Gfx *geo_render_mirror_mario(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
Gfx *geo_mirror_mario_backface_culling(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
|
||||
|
||||
#endif // MARIO_MISC_H
|
||||
@@ -0,0 +1,668 @@
|
||||
#include "../shim.h"
|
||||
#include "../include/sm64.h"
|
||||
#include "../engine/math_util.h"
|
||||
#include "../engine/surface_collision.h"
|
||||
#include "mario.h"
|
||||
//#include "audio/external.h"
|
||||
//#include "game_init.h"
|
||||
#include "interaction.h"
|
||||
#include "mario_step.h"
|
||||
|
||||
static s16 sMovingSandSpeeds[] = { 12, 8, 4, 0 };
|
||||
|
||||
struct Surface gWaterSurfacePseudoFloor = {
|
||||
SURFACE_VERY_SLIPPERY, 0, 0, 0, 0, 0, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
|
||||
{ 0.0f, 1.0f, 0.0f }, 0.0f, NULL,
|
||||
};
|
||||
|
||||
/**
|
||||
* Always returns zero. This may have been intended
|
||||
* to be used for the beta trampoline. Its return value
|
||||
* is used by set_mario_y_vel_based_on_fspeed as a constant
|
||||
* addition to Mario's Y velocity. Given the closeness of
|
||||
* this function to stub_mario_step_2, it is probable that this
|
||||
* was intended to check whether a trampoline had made itself
|
||||
* known through stub_mario_step_2 and whether Mario was on it,
|
||||
* and if so return a higher value than 0.
|
||||
*/
|
||||
f32 get_additive_y_vel_for_jumps(void) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing, but takes in a MarioState. This is only ever
|
||||
* called by update_mario_inputs, which is called as part of Mario's
|
||||
* update routine. Due to its proximity to stub_mario_step_2, an
|
||||
* incomplete trampoline function, and get_additive_y_vel_for_jumps,
|
||||
* a potentially trampoline-related function, it is plausible that
|
||||
* this could be used for checking if Mario was on the trampoline.
|
||||
* It could, for example, make him bounce.
|
||||
*/
|
||||
void stub_mario_step_1(UNUSED struct MarioState *x) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing. This is only called by the beta trampoline.
|
||||
* Due to its proximity to get_additive_y_vel_for_jumps, another
|
||||
* currently-pointless function, it is probable that this was used
|
||||
* by the trampoline to make itself known to get_additive_y_vel_for_jumps,
|
||||
* or to set a variable with its intended additive Y vel.
|
||||
*/
|
||||
void stub_mario_step_2(void) {
|
||||
}
|
||||
|
||||
void transfer_bully_speed(struct BullyCollisionData *obj1, struct BullyCollisionData *obj2) {
|
||||
f32 rx = obj2->posX - obj1->posX;
|
||||
f32 rz = obj2->posZ - obj1->posZ;
|
||||
|
||||
//! Bully NaN crash
|
||||
f32 projectedV1 = (rx * obj1->velX + rz * obj1->velZ) / (rx * rx + rz * rz);
|
||||
f32 projectedV2 = (-rx * obj2->velX - rz * obj2->velZ) / (rx * rx + rz * rz);
|
||||
|
||||
// Kill speed along r. Convert one object's speed along r and transfer it to
|
||||
// the other object.
|
||||
obj2->velX += obj2->conversionRatio * projectedV1 * rx - projectedV2 * -rx;
|
||||
obj2->velZ += obj2->conversionRatio * projectedV1 * rz - projectedV2 * -rz;
|
||||
|
||||
obj1->velX += -projectedV1 * rx + obj1->conversionRatio * projectedV2 * -rx;
|
||||
obj1->velZ += -projectedV1 * rz + obj1->conversionRatio * projectedV2 * -rz;
|
||||
|
||||
//! Bully battery
|
||||
}
|
||||
|
||||
BAD_RETURN(s32) init_bully_collision_data(struct BullyCollisionData *data, f32 posX, f32 posZ,
|
||||
f32 forwardVel, s16 yaw, f32 conversionRatio, f32 radius) {
|
||||
if (forwardVel < 0.0f) {
|
||||
forwardVel *= -1.0f;
|
||||
yaw += 0x8000;
|
||||
}
|
||||
|
||||
data->radius = radius;
|
||||
data->conversionRatio = conversionRatio;
|
||||
data->posX = posX;
|
||||
data->posZ = posZ;
|
||||
data->velX = forwardVel * sins(yaw);
|
||||
data->velZ = forwardVel * coss(yaw);
|
||||
}
|
||||
|
||||
void mario_bonk_reflection(struct MarioState *m, u32 negateSpeed) {
|
||||
if (m->wall != NULL) {
|
||||
s16 wallAngle = atan2s(m->wall->normal.z, m->wall->normal.x);
|
||||
m->faceAngle[1] = wallAngle - (s16)(m->faceAngle[1] - wallAngle);
|
||||
|
||||
play_sound((m->flags & MARIO_METAL_CAP) ? SOUND_ACTION_METAL_BONK : SOUND_ACTION_BONK,
|
||||
m->marioObj->header.gfx.cameraToObject);
|
||||
} else {
|
||||
play_sound(SOUND_ACTION_HIT, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
|
||||
if (negateSpeed) {
|
||||
mario_set_forward_vel(m, -m->forwardVel);
|
||||
} else {
|
||||
m->faceAngle[1] += 0x8000;
|
||||
}
|
||||
}
|
||||
|
||||
u32 mario_update_quicksand(struct MarioState *m, f32 sinkingSpeed) {
|
||||
if (m->action & ACT_FLAG_RIDING_SHELL) {
|
||||
m->quicksandDepth = 0.0f;
|
||||
} else {
|
||||
if (m->quicksandDepth < 1.1f) {
|
||||
m->quicksandDepth = 1.1f;
|
||||
}
|
||||
|
||||
switch (m->floor->type) {
|
||||
case SURFACE_SHALLOW_QUICKSAND:
|
||||
if ((m->quicksandDepth += sinkingSpeed) >= 10.0f) {
|
||||
m->quicksandDepth = 10.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
case SURFACE_SHALLOW_MOVING_QUICKSAND:
|
||||
if ((m->quicksandDepth += sinkingSpeed) >= 25.0f) {
|
||||
m->quicksandDepth = 25.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
case SURFACE_QUICKSAND:
|
||||
case SURFACE_MOVING_QUICKSAND:
|
||||
if ((m->quicksandDepth += sinkingSpeed) >= 60.0f) {
|
||||
m->quicksandDepth = 60.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
case SURFACE_DEEP_QUICKSAND:
|
||||
case SURFACE_DEEP_MOVING_QUICKSAND:
|
||||
if ((m->quicksandDepth += sinkingSpeed) >= 160.0f) {
|
||||
update_mario_sound_and_camera(m);
|
||||
return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SURFACE_INSTANT_QUICKSAND:
|
||||
case SURFACE_INSTANT_MOVING_QUICKSAND:
|
||||
update_mario_sound_and_camera(m);
|
||||
return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
m->quicksandDepth = 0.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
u32 mario_push_off_steep_floor(struct MarioState *m, u32 action, u32 actionArg) {
|
||||
s16 floorDYaw = m->floorAngle - m->faceAngle[1];
|
||||
|
||||
if (floorDYaw > -0x4000 && floorDYaw < 0x4000) {
|
||||
m->forwardVel = 16.0f;
|
||||
m->faceAngle[1] = m->floorAngle;
|
||||
} else {
|
||||
m->forwardVel = -16.0f;
|
||||
m->faceAngle[1] = m->floorAngle + 0x8000;
|
||||
}
|
||||
|
||||
return set_mario_action(m, action, actionArg);
|
||||
}
|
||||
|
||||
u32 mario_update_moving_sand(struct MarioState *m) {
|
||||
struct Surface *floor = m->floor;
|
||||
s32 floorType = floor->type;
|
||||
|
||||
if (floorType == SURFACE_DEEP_MOVING_QUICKSAND || floorType == SURFACE_SHALLOW_MOVING_QUICKSAND
|
||||
|| floorType == SURFACE_MOVING_QUICKSAND || floorType == SURFACE_INSTANT_MOVING_QUICKSAND) {
|
||||
s16 pushAngle = floor->force << 8;
|
||||
f32 pushSpeed = sMovingSandSpeeds[floor->force >> 8];
|
||||
|
||||
m->vel[0] += pushSpeed * sins(pushAngle);
|
||||
m->vel[2] += pushSpeed * coss(pushAngle);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
u32 mario_update_windy_ground(struct MarioState *m) {
|
||||
struct Surface *floor = m->floor;
|
||||
|
||||
if (floor->type == SURFACE_HORIZONTAL_WIND) {
|
||||
f32 pushSpeed;
|
||||
s16 pushAngle = floor->force << 8;
|
||||
|
||||
if (m->action & ACT_FLAG_MOVING) {
|
||||
s16 pushDYaw = m->faceAngle[1] - pushAngle;
|
||||
|
||||
pushSpeed = m->forwardVel > 0.0f ? -m->forwardVel * 0.5f : -8.0f;
|
||||
|
||||
if (pushDYaw > -0x4000 && pushDYaw < 0x4000) {
|
||||
pushSpeed *= -1.0f;
|
||||
}
|
||||
|
||||
pushSpeed *= coss(pushDYaw);
|
||||
} else {
|
||||
pushSpeed = 3.2f + (gGlobalTimer % 4);
|
||||
}
|
||||
|
||||
m->vel[0] += pushSpeed * sins(pushAngle);
|
||||
m->vel[2] += pushSpeed * coss(pushAngle);
|
||||
|
||||
#if VERSION_JP
|
||||
play_sound(SOUND_ENV_WIND2, m->marioObj->header.gfx.cameraToObject);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void stop_and_set_height_to_floor(struct MarioState *m) {
|
||||
struct Object *marioObj = m->marioObj;
|
||||
|
||||
mario_set_forward_vel(m, 0.0f);
|
||||
m->vel[1] = 0.0f;
|
||||
|
||||
//! This is responsible for some downwarps.
|
||||
m->pos[1] = m->floorHeight;
|
||||
|
||||
vec3f_copy(marioObj->header.gfx.pos, m->pos);
|
||||
vec3s_set(marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
|
||||
}
|
||||
|
||||
s32 stationary_ground_step(struct MarioState *m) {
|
||||
u32 takeStep;
|
||||
struct Object *marioObj = m->marioObj;
|
||||
u32 stepResult = GROUND_STEP_NONE;
|
||||
|
||||
mario_set_forward_vel(m, 0.0f);
|
||||
|
||||
takeStep = mario_update_moving_sand(m);
|
||||
takeStep |= mario_update_windy_ground(m);
|
||||
if (takeStep) {
|
||||
stepResult = perform_ground_step(m);
|
||||
} else {
|
||||
//! This is responsible for several stationary downwarps.
|
||||
m->pos[1] = m->floorHeight;
|
||||
|
||||
vec3f_copy(marioObj->header.gfx.pos, m->pos);
|
||||
vec3s_set(marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
|
||||
}
|
||||
|
||||
return stepResult;
|
||||
}
|
||||
|
||||
static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) {
|
||||
UNUSED struct Surface *lowerWall;
|
||||
struct Surface *upperWall;
|
||||
struct Surface *ceil;
|
||||
struct Surface *floor;
|
||||
f32 ceilHeight;
|
||||
f32 floorHeight;
|
||||
f32 waterLevel;
|
||||
|
||||
lowerWall = resolve_and_return_wall_collisions(nextPos, 30.0f, 24.0f);
|
||||
upperWall = resolve_and_return_wall_collisions(nextPos, 60.0f, 50.0f);
|
||||
|
||||
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
|
||||
ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil);
|
||||
|
||||
waterLevel = find_water_level(nextPos[0], nextPos[2]);
|
||||
|
||||
m->wall = upperWall;
|
||||
|
||||
if (floor == NULL) {
|
||||
return GROUND_STEP_HIT_WALL_STOP_QSTEPS;
|
||||
}
|
||||
|
||||
if ((m->action & ACT_FLAG_RIDING_SHELL) && floorHeight < waterLevel) {
|
||||
floorHeight = waterLevel;
|
||||
floor = &gWaterSurfacePseudoFloor;
|
||||
floor->originOffset = floorHeight; //! Wrong origin offset (no effect)
|
||||
}
|
||||
|
||||
if (nextPos[1] > floorHeight + 100.0f) {
|
||||
if (nextPos[1] + 160.0f >= ceilHeight) {
|
||||
return GROUND_STEP_HIT_WALL_STOP_QSTEPS;
|
||||
}
|
||||
|
||||
vec3f_copy(m->pos, nextPos);
|
||||
m->floor = floor;
|
||||
m->floorHeight = floorHeight;
|
||||
return GROUND_STEP_LEFT_GROUND;
|
||||
}
|
||||
|
||||
if (floorHeight + 160.0f >= ceilHeight) {
|
||||
return GROUND_STEP_HIT_WALL_STOP_QSTEPS;
|
||||
}
|
||||
|
||||
vec3f_set(m->pos, nextPos[0], floorHeight, nextPos[2]);
|
||||
m->floor = floor;
|
||||
m->floorHeight = floorHeight;
|
||||
|
||||
if (upperWall != NULL) {
|
||||
s16 wallDYaw = atan2s(upperWall->normal.z, upperWall->normal.x) - m->faceAngle[1];
|
||||
|
||||
if (wallDYaw >= 0x2AAA && wallDYaw <= 0x5555) {
|
||||
return GROUND_STEP_NONE;
|
||||
}
|
||||
if (wallDYaw <= -0x2AAA && wallDYaw >= -0x5555) {
|
||||
return GROUND_STEP_NONE;
|
||||
}
|
||||
|
||||
return GROUND_STEP_HIT_WALL_CONTINUE_QSTEPS;
|
||||
}
|
||||
|
||||
return GROUND_STEP_NONE;
|
||||
}
|
||||
|
||||
s32 perform_ground_step(struct MarioState *m) {
|
||||
s32 i;
|
||||
u32 stepResult;
|
||||
Vec3f intendedPos;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
intendedPos[0] = m->pos[0] + m->floor->normal.y * (m->vel[0] / 4.0f);
|
||||
intendedPos[2] = m->pos[2] + m->floor->normal.y * (m->vel[2] / 4.0f);
|
||||
intendedPos[1] = m->pos[1];
|
||||
|
||||
stepResult = perform_ground_quarter_step(m, intendedPos);
|
||||
if (stepResult == GROUND_STEP_LEFT_GROUND || stepResult == GROUND_STEP_HIT_WALL_STOP_QSTEPS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m->terrainSoundAddend = mario_get_terrain_sound_addend(m);
|
||||
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
|
||||
vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
|
||||
|
||||
if (stepResult == GROUND_STEP_HIT_WALL_CONTINUE_QSTEPS) {
|
||||
stepResult = GROUND_STEP_HIT_WALL;
|
||||
}
|
||||
return stepResult;
|
||||
}
|
||||
|
||||
u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedPos, Vec3f nextPos) {
|
||||
struct Surface *ledgeFloor;
|
||||
Vec3f ledgePos;
|
||||
f32 displacementX;
|
||||
f32 displacementZ;
|
||||
|
||||
if (m->vel[1] > 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
displacementX = nextPos[0] - intendedPos[0];
|
||||
displacementZ = nextPos[2] - intendedPos[2];
|
||||
|
||||
// Only ledge grab if the wall displaced Mario in the opposite direction of
|
||||
// his velocity.
|
||||
if (displacementX * m->vel[0] + displacementZ * m->vel[2] > 0.0f) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//! Since the search for floors starts at y + 160, we will sometimes grab
|
||||
// a higher ledge than expected (glitchy ledge grab)
|
||||
ledgePos[0] = nextPos[0] - wall->normal.x * 60.0f;
|
||||
ledgePos[2] = nextPos[2] - wall->normal.z * 60.0f;
|
||||
ledgePos[1] = find_floor(ledgePos[0], nextPos[1] + 160.0f, ledgePos[2], &ledgeFloor);
|
||||
|
||||
if (ledgePos[1] - nextPos[1] <= 100.0f) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
vec3f_copy(m->pos, ledgePos);
|
||||
m->floor = ledgeFloor;
|
||||
m->floorHeight = ledgePos[1];
|
||||
|
||||
m->floorAngle = atan2s(ledgeFloor->normal.z, ledgeFloor->normal.x);
|
||||
|
||||
m->faceAngle[0] = 0;
|
||||
m->faceAngle[1] = atan2s(wall->normal.z, wall->normal.x) + 0x8000;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepArg) {
|
||||
s16 wallDYaw;
|
||||
Vec3f nextPos;
|
||||
struct Surface *upperWall;
|
||||
struct Surface *lowerWall;
|
||||
struct Surface *ceil;
|
||||
struct Surface *floor;
|
||||
f32 ceilHeight;
|
||||
f32 floorHeight;
|
||||
f32 waterLevel;
|
||||
|
||||
vec3f_copy(nextPos, intendedPos);
|
||||
|
||||
upperWall = resolve_and_return_wall_collisions(nextPos, 150.0f, 50.0f);
|
||||
lowerWall = resolve_and_return_wall_collisions(nextPos, 30.0f, 50.0f);
|
||||
|
||||
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
|
||||
ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil);
|
||||
|
||||
waterLevel = find_water_level(nextPos[0], nextPos[2]);
|
||||
|
||||
m->wall = NULL;
|
||||
|
||||
//! The water pseudo floor is not referenced when your intended qstep is
|
||||
// out of bounds, so it won't detect you as landing.
|
||||
|
||||
if (floor == NULL) {
|
||||
if (nextPos[1] <= m->floorHeight) {
|
||||
m->pos[1] = m->floorHeight;
|
||||
return AIR_STEP_LANDED;
|
||||
}
|
||||
|
||||
m->pos[1] = nextPos[1];
|
||||
return AIR_STEP_HIT_WALL;
|
||||
}
|
||||
|
||||
if ((m->action & ACT_FLAG_RIDING_SHELL) && floorHeight < waterLevel) {
|
||||
floorHeight = waterLevel;
|
||||
floor = &gWaterSurfacePseudoFloor;
|
||||
floor->originOffset = floorHeight; //! Incorrect origin offset (no effect)
|
||||
}
|
||||
|
||||
//! This check uses f32, but findFloor uses short (overflow jumps)
|
||||
if (nextPos[1] <= floorHeight) {
|
||||
if (ceilHeight - floorHeight > 160.0f) {
|
||||
m->pos[0] = nextPos[0];
|
||||
m->pos[2] = nextPos[2];
|
||||
m->floor = floor;
|
||||
m->floorHeight = floorHeight;
|
||||
}
|
||||
|
||||
//! When ceilHeight - floorHeight <= 160, the step result says that
|
||||
// Mario landed, but his movement is cancelled and his referenced floor
|
||||
// isn't updated (pedro spots)
|
||||
m->pos[1] = floorHeight;
|
||||
return AIR_STEP_LANDED;
|
||||
}
|
||||
|
||||
if (nextPos[1] + 160.0f > ceilHeight) {
|
||||
if (m->vel[1] >= 0.0f) {
|
||||
m->vel[1] = 0.0f;
|
||||
|
||||
//! Uses referenced ceiling instead of ceil (ceiling hang upwarp)
|
||||
if ((stepArg & AIR_STEP_CHECK_HANG) && m->ceil != NULL
|
||||
&& m->ceil->type == SURFACE_HANGABLE) {
|
||||
return AIR_STEP_GRABBED_CEILING;
|
||||
}
|
||||
|
||||
return AIR_STEP_NONE;
|
||||
}
|
||||
|
||||
//! Potential subframe downwarp->upwarp?
|
||||
if (nextPos[1] <= m->floorHeight) {
|
||||
m->pos[1] = m->floorHeight;
|
||||
return AIR_STEP_LANDED;
|
||||
}
|
||||
|
||||
m->pos[1] = nextPos[1];
|
||||
return AIR_STEP_HIT_WALL;
|
||||
}
|
||||
|
||||
//! When the wall is not completely vertical or there is a slight wall
|
||||
// misalignment, you can activate these conditions in unexpected situations
|
||||
if ((stepArg & AIR_STEP_CHECK_LEDGE_GRAB) && upperWall == NULL && lowerWall != NULL) {
|
||||
if (check_ledge_grab(m, lowerWall, intendedPos, nextPos)) {
|
||||
return AIR_STEP_GRABBED_LEDGE;
|
||||
}
|
||||
|
||||
vec3f_copy(m->pos, nextPos);
|
||||
m->floor = floor;
|
||||
m->floorHeight = floorHeight;
|
||||
return AIR_STEP_NONE;
|
||||
}
|
||||
|
||||
vec3f_copy(m->pos, nextPos);
|
||||
m->floor = floor;
|
||||
m->floorHeight = floorHeight;
|
||||
|
||||
if (upperWall != NULL || lowerWall != NULL) {
|
||||
m->wall = upperWall != NULL ? upperWall : lowerWall;
|
||||
wallDYaw = atan2s(m->wall->normal.z, m->wall->normal.x) - m->faceAngle[1];
|
||||
|
||||
if (m->wall->type == SURFACE_BURNING) {
|
||||
return AIR_STEP_HIT_LAVA_WALL;
|
||||
}
|
||||
|
||||
if (wallDYaw < -0x6000 || wallDYaw > 0x6000) {
|
||||
m->flags |= MARIO_UNKNOWN_30;
|
||||
return AIR_STEP_HIT_WALL;
|
||||
}
|
||||
}
|
||||
|
||||
return AIR_STEP_NONE;
|
||||
}
|
||||
|
||||
void apply_twirl_gravity(struct MarioState *m) {
|
||||
f32 terminalVelocity;
|
||||
f32 heaviness = 1.0f;
|
||||
|
||||
if (m->angleVel[1] > 1024) {
|
||||
heaviness = 1024.0f / m->angleVel[1];
|
||||
}
|
||||
|
||||
terminalVelocity = -75.0f * heaviness;
|
||||
|
||||
m->vel[1] -= 4.0f * heaviness;
|
||||
if (m->vel[1] < terminalVelocity) {
|
||||
m->vel[1] = terminalVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
u32 should_strengthen_gravity_for_jump_ascent(struct MarioState *m) {
|
||||
if (!(m->flags & MARIO_UNKNOWN_08)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m->action & (ACT_FLAG_INTANGIBLE | ACT_FLAG_INVULNERABLE)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(m->input & INPUT_A_DOWN) && m->vel[1] > 20.0f) {
|
||||
return (m->action & ACT_FLAG_CONTROL_JUMP_HEIGHT) != 0;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void apply_gravity(struct MarioState *m) {
|
||||
if (m->action == ACT_TWIRLING && m->vel[1] < 0.0f) {
|
||||
apply_twirl_gravity(m);
|
||||
} else if (m->action == ACT_SHOT_FROM_CANNON) {
|
||||
m->vel[1] -= 1.0f;
|
||||
if (m->vel[1] < -75.0f) {
|
||||
m->vel[1] = -75.0f;
|
||||
}
|
||||
} else if (m->action == ACT_LONG_JUMP || m->action == ACT_SLIDE_KICK
|
||||
|| m->action == ACT_BBH_ENTER_SPIN) {
|
||||
m->vel[1] -= 2.0f;
|
||||
if (m->vel[1] < -75.0f) {
|
||||
m->vel[1] = -75.0f;
|
||||
}
|
||||
} else if (m->action == ACT_LAVA_BOOST || m->action == ACT_FALL_AFTER_STAR_GRAB) {
|
||||
m->vel[1] -= 3.2f;
|
||||
if (m->vel[1] < -65.0f) {
|
||||
m->vel[1] = -65.0f;
|
||||
}
|
||||
} else if (m->action == ACT_GETTING_BLOWN) {
|
||||
m->vel[1] -= m->unkC4;
|
||||
if (m->vel[1] < -75.0f) {
|
||||
m->vel[1] = -75.0f;
|
||||
}
|
||||
} else if (should_strengthen_gravity_for_jump_ascent(m)) {
|
||||
m->vel[1] /= 4.0f;
|
||||
} else if (m->action & ACT_FLAG_METAL_WATER) {
|
||||
m->vel[1] -= 1.6f;
|
||||
if (m->vel[1] < -16.0f) {
|
||||
m->vel[1] = -16.0f;
|
||||
}
|
||||
} else if ((m->flags & MARIO_WING_CAP) && m->vel[1] < 0.0f && (m->input & INPUT_A_DOWN)) {
|
||||
m->marioBodyState->wingFlutter = TRUE;
|
||||
|
||||
m->vel[1] -= 2.0f;
|
||||
if (m->vel[1] < -37.5f) {
|
||||
if ((m->vel[1] += 4.0f) > -37.5f) {
|
||||
m->vel[1] = -37.5f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m->vel[1] -= 4.0f;
|
||||
if (m->vel[1] < -75.0f) {
|
||||
m->vel[1] = -75.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void apply_vertical_wind(struct MarioState *m) {
|
||||
f32 maxVelY;
|
||||
f32 offsetY;
|
||||
|
||||
if (m->action != ACT_GROUND_POUND) {
|
||||
offsetY = m->pos[1] - -1500.0f;
|
||||
|
||||
if (m->floor->type == SURFACE_VERTICAL_WIND && -3000.0f < offsetY && offsetY < 2000.0f) {
|
||||
if (offsetY >= 0.0f) {
|
||||
maxVelY = 10000.0f / (offsetY + 200.0f);
|
||||
} else {
|
||||
maxVelY = 50.0f;
|
||||
}
|
||||
|
||||
if (m->vel[1] < maxVelY) {
|
||||
if ((m->vel[1] += maxVelY / 8.0f) > maxVelY) {
|
||||
m->vel[1] = maxVelY;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VERSION_JP
|
||||
play_sound(SOUND_ENV_WIND2, m->marioObj->header.gfx.cameraToObject);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 perform_air_step(struct MarioState *m, u32 stepArg) {
|
||||
Vec3f intendedPos;
|
||||
s32 i;
|
||||
s32 quarterStepResult;
|
||||
s32 stepResult = AIR_STEP_NONE;
|
||||
|
||||
m->wall = NULL;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
intendedPos[0] = m->pos[0] + m->vel[0] / 4.0f;
|
||||
intendedPos[1] = m->pos[1] + m->vel[1] / 4.0f;
|
||||
intendedPos[2] = m->pos[2] + m->vel[2] / 4.0f;
|
||||
|
||||
quarterStepResult = perform_air_quarter_step(m, intendedPos, stepArg);
|
||||
|
||||
//! On one qf, hit OOB/ceil/wall to store the 2 return value, and continue
|
||||
// getting 0s until your last qf. Graze a wall on your last qf, and it will
|
||||
// return the stored 2 with a sharply angled reference wall. (some gwks)
|
||||
|
||||
if (quarterStepResult != AIR_STEP_NONE) {
|
||||
stepResult = quarterStepResult;
|
||||
}
|
||||
|
||||
if (quarterStepResult == AIR_STEP_LANDED || quarterStepResult == AIR_STEP_GRABBED_LEDGE
|
||||
|| quarterStepResult == AIR_STEP_GRABBED_CEILING
|
||||
|| quarterStepResult == AIR_STEP_HIT_LAVA_WALL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m->vel[1] >= 0.0f) {
|
||||
m->peakHeight = m->pos[1];
|
||||
}
|
||||
|
||||
m->terrainSoundAddend = mario_get_terrain_sound_addend(m);
|
||||
|
||||
if (m->action != ACT_FLYING) {
|
||||
apply_gravity(m);
|
||||
}
|
||||
apply_vertical_wind(m);
|
||||
|
||||
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
|
||||
vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
|
||||
|
||||
return stepResult;
|
||||
}
|
||||
|
||||
// They had these functions the whole time and never used them? Lol
|
||||
|
||||
void set_vel_from_pitch_and_yaw(struct MarioState *m) {
|
||||
m->vel[0] = m->forwardVel * coss(m->faceAngle[0]) * sins(m->faceAngle[1]);
|
||||
m->vel[1] = m->forwardVel * sins(m->faceAngle[0]);
|
||||
m->vel[2] = m->forwardVel * coss(m->faceAngle[0]) * coss(m->faceAngle[1]);
|
||||
}
|
||||
|
||||
void set_vel_from_yaw(struct MarioState *m) {
|
||||
m->vel[0] = m->slideVelX = m->forwardVel * sins(m->faceAngle[1]);
|
||||
m->vel[1] = 0.0f;
|
||||
m->vel[2] = m->slideVelZ = m->forwardVel * coss(m->faceAngle[1]);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef MARIO_STEP_H
|
||||
#define MARIO_STEP_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
struct BullyCollisionData {
|
||||
/*0x00*/ f32 conversionRatio;
|
||||
/*0x04*/ f32 radius;
|
||||
/*0x08*/ f32 posX;
|
||||
/*0x0C*/ f32 posZ;
|
||||
/*0x10*/ f32 velX;
|
||||
/*0x14*/ f32 velZ;
|
||||
};
|
||||
|
||||
extern struct Surface gWaterSurfacePseudoFloor;
|
||||
|
||||
f32 get_additive_y_vel_for_jumps(void);
|
||||
void stub_mario_step_1(struct MarioState *);
|
||||
void stub_mario_step_2(void);
|
||||
|
||||
void mario_bonk_reflection(struct MarioState *, u32);
|
||||
void transfer_bully_speed(struct BullyCollisionData *obj1, struct BullyCollisionData *obj2);
|
||||
BAD_RETURN(s32) init_bully_collision_data(struct BullyCollisionData *data, f32 posX, f32 posZ,
|
||||
f32 forwardVel, s16 yaw, f32 conversionRatio, f32 radius);
|
||||
u32 mario_update_quicksand(struct MarioState *, f32);
|
||||
u32 mario_push_off_steep_floor(struct MarioState *, u32, u32);
|
||||
u32 mario_update_moving_sand(struct MarioState *);
|
||||
u32 mario_update_windy_ground(struct MarioState *);
|
||||
void stop_and_set_height_to_floor(struct MarioState *);
|
||||
s32 stationary_ground_step(struct MarioState *);
|
||||
s32 perform_ground_step(struct MarioState *);
|
||||
s32 perform_air_step(struct MarioState *, u32);
|
||||
|
||||
#endif // MARIO_STEP_H
|
||||
@@ -0,0 +1,308 @@
|
||||
/**
|
||||
* This file just hacks a bunch of stuff together to get a valid Object and GraphNode for Mario
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "mario.h"
|
||||
#include "../shim.h"
|
||||
#include "../engine/math_util.h"
|
||||
#include "../include/object_fields.h"
|
||||
|
||||
/* activeFlags */
|
||||
#define ACTIVE_FLAG_DEACTIVATED 0 // 0x0000
|
||||
#define ACTIVE_FLAG_ACTIVE (1 << 0) // 0x0001
|
||||
#define ACTIVE_FLAG_FAR_AWAY (1 << 1) // 0x0002
|
||||
#define ACTIVE_FLAG_UNK2 (1 << 2) // 0x0004
|
||||
#define ACTIVE_FLAG_IN_DIFFERENT_ROOM (1 << 3) // 0x0008
|
||||
#define ACTIVE_FLAG_UNIMPORTANT (1 << 4) // 0x0010
|
||||
#define ACTIVE_FLAG_INITIATED_TIME_STOP (1 << 5) // 0x0020
|
||||
#define ACTIVE_FLAG_MOVE_THROUGH_GRATE (1 << 6) // 0x0040
|
||||
#define ACTIVE_FLAG_DITHERED_ALPHA (1 << 7) // 0x0080
|
||||
#define ACTIVE_FLAG_UNK8 (1 << 8) // 0x0100
|
||||
#define ACTIVE_FLAG_UNK9 (1 << 9) // 0x0200
|
||||
#define ACTIVE_FLAG_UNK10 (1 << 10) // 0x0400
|
||||
|
||||
// The discriminant for different types of geo nodes
|
||||
#define GRAPH_NODE_TYPE_ROOT 0x001
|
||||
#define GRAPH_NODE_TYPE_ORTHO_PROJECTION 0x002
|
||||
#define GRAPH_NODE_TYPE_PERSPECTIVE (0x003 | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_MASTER_LIST 0x004
|
||||
#define GRAPH_NODE_TYPE_START 0x00A
|
||||
#define GRAPH_NODE_TYPE_LEVEL_OF_DETAIL 0x00B
|
||||
#define GRAPH_NODE_TYPE_SWITCH_CASE (0x00C | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_CAMERA (0x014 | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_TRANSLATION_ROTATION 0x015
|
||||
#define GRAPH_NODE_TYPE_TRANSLATION 0x016
|
||||
#define GRAPH_NODE_TYPE_ROTATION 0x017
|
||||
#define GRAPH_NODE_TYPE_OBJECT 0x018
|
||||
#define GRAPH_NODE_TYPE_ANIMATED_PART 0x019
|
||||
#define GRAPH_NODE_TYPE_BILLBOARD 0x01A
|
||||
#define GRAPH_NODE_TYPE_DISPLAY_LIST 0x01B
|
||||
#define GRAPH_NODE_TYPE_SCALE 0x01C
|
||||
#define GRAPH_NODE_TYPE_SHADOW 0x028
|
||||
#define GRAPH_NODE_TYPE_OBJECT_PARENT 0x029
|
||||
#define GRAPH_NODE_TYPE_GENERATED_LIST (0x02A | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_BACKGROUND (0x02C | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_HELD_OBJ (0x02E | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||
#define GRAPH_NODE_TYPE_CULLING_RADIUS 0x02F
|
||||
|
||||
/* respawnInfoType */
|
||||
#define RESPAWN_INFO_TYPE_NULL 0
|
||||
#define RESPAWN_INFO_TYPE_32 1
|
||||
#define RESPAWN_INFO_TYPE_16 2
|
||||
|
||||
#define GRAPH_RENDER_ACTIVE (1 << 0)
|
||||
#define GRAPH_RENDER_CHILDREN_FIRST (1 << 1)
|
||||
#define GRAPH_RENDER_BILLBOARD (1 << 2)
|
||||
#define GRAPH_RENDER_Z_BUFFER (1 << 3)
|
||||
#define GRAPH_RENDER_INVISIBLE (1 << 4)
|
||||
#define GRAPH_RENDER_HAS_ANIMATION (1 << 5)
|
||||
|
||||
static Vec3f gVec3fZero = { 0.0f, 0.0f, 0.0f };
|
||||
static Vec3s gVec3sZero = { 0, 0, 0 };
|
||||
static Vec3f gVec3fOne = { 1.0f, 1.0f, 1.0f };
|
||||
|
||||
static struct GraphNodeObject *init_graph_node_object( Vec3f pos, Vec3s angle, Vec3f scale) {
|
||||
struct GraphNodeObject *graphNode = malloc(sizeof(struct GraphNodeObject));
|
||||
|
||||
//init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_OBJECT);
|
||||
|
||||
graphNode->node.type = GRAPH_NODE_TYPE_OBJECT;
|
||||
graphNode->node.flags = GRAPH_RENDER_ACTIVE;
|
||||
graphNode->node.prev = &graphNode->node;
|
||||
graphNode->node.next = &graphNode->node;
|
||||
graphNode->node.parent = NULL;
|
||||
graphNode->node.children = NULL;
|
||||
|
||||
vec3f_copy(graphNode->pos, pos);
|
||||
vec3f_copy(graphNode->scale, scale);
|
||||
vec3s_copy(graphNode->angle, angle);
|
||||
vec3f_copy(graphNode->cameraToObject, gVec3fZero);
|
||||
|
||||
graphNode->sharedChild = NULL;
|
||||
graphNode->throwMatrix = NULL;
|
||||
graphNode->animInfo.animID = 0;
|
||||
graphNode->animInfo.curAnim = NULL;
|
||||
graphNode->animInfo.animFrame = 0;
|
||||
graphNode->animInfo.animFrameAccelAssist = 0;
|
||||
graphNode->animInfo.animAccel = 0x10000;
|
||||
graphNode->animInfo.animTimer = 0;
|
||||
graphNode->node.flags |= GRAPH_RENDER_HAS_ANIMATION;
|
||||
|
||||
return graphNode;
|
||||
}
|
||||
|
||||
static struct Object *try_allocate_object(void) {
|
||||
struct ObjectNode *nextObj;
|
||||
nextObj = (struct ObjectNode *) malloc(sizeof(struct Object));
|
||||
nextObj->prev = NULL;
|
||||
nextObj->next = NULL;
|
||||
|
||||
init_graph_node_object(gVec3fZero, gVec3sZero, gVec3fOne);
|
||||
|
||||
return (struct Object *) nextObj;
|
||||
}
|
||||
|
||||
static struct Object *allocate_object(void) {
|
||||
s32 i;
|
||||
struct Object *obj = try_allocate_object();
|
||||
|
||||
// Initialize object fields
|
||||
|
||||
obj->activeFlags = ACTIVE_FLAG_ACTIVE | ACTIVE_FLAG_UNK8;
|
||||
obj->parentObj = obj;
|
||||
obj->prevObj = NULL;
|
||||
obj->collidedObjInteractTypes = 0;
|
||||
obj->numCollidedObjs = 0;
|
||||
|
||||
for (i = 0; i < 0x50; i++) {
|
||||
obj->rawData.asS32[i] = 0;
|
||||
obj->ptrData.asVoidPtr[i] = NULL;
|
||||
}
|
||||
|
||||
obj->unused1 = 0;
|
||||
obj->bhvStackIndex = 0;
|
||||
obj->bhvDelayTimer = 0;
|
||||
|
||||
obj->hitboxRadius = 37.0f; // Override directly for Mario
|
||||
obj->hitboxHeight = 160.0f; //
|
||||
obj->hurtboxRadius = 0.0f;
|
||||
obj->hurtboxHeight = 0.0f;
|
||||
obj->hitboxDownOffset = 0.0f;
|
||||
obj->unused2 = 0;
|
||||
|
||||
obj->platform = NULL;
|
||||
obj->collisionData = NULL;
|
||||
obj->oIntangibleTimer = -1;
|
||||
obj->oDamageOrCoinValue = 0;
|
||||
obj->oHealth = 2048;
|
||||
|
||||
obj->oCollisionDistance = 1000.0f;
|
||||
if (gCurrLevelNum == LEVEL_TTC) {
|
||||
obj->oDrawingDistance = 2000.0f;
|
||||
} else {
|
||||
obj->oDrawingDistance = 4000.0f;
|
||||
}
|
||||
|
||||
mtxf_identity(obj->transform);
|
||||
|
||||
obj->respawnInfoType = RESPAWN_INFO_TYPE_NULL;
|
||||
obj->respawnInfo = NULL;
|
||||
|
||||
obj->oDistanceToMario = 19000.0f;
|
||||
obj->oRoom = -1;
|
||||
|
||||
obj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
obj->header.gfx.pos[0] = -10000.0f;
|
||||
obj->header.gfx.pos[1] = -10000.0f;
|
||||
obj->header.gfx.pos[2] = -10000.0f;
|
||||
obj->header.gfx.throwMatrix = NULL;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static struct Object *create_object(void) {
|
||||
struct Object *obj;
|
||||
obj = allocate_object();
|
||||
obj->curBhvCommand = NULL;
|
||||
obj->behavior = NULL;
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void geo_obj_init(struct GraphNodeObject *graphNode, void *sharedChild, Vec3f pos, Vec3s angle) {
|
||||
vec3f_set(graphNode->scale, 1.0f, 1.0f, 1.0f);
|
||||
vec3f_copy(graphNode->pos, pos);
|
||||
vec3s_copy(graphNode->angle, angle);
|
||||
|
||||
graphNode->sharedChild = sharedChild;
|
||||
graphNode->unk4C = 0;
|
||||
graphNode->throwMatrix = NULL;
|
||||
graphNode->animInfo.curAnim = NULL;
|
||||
|
||||
graphNode->node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
graphNode->node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
graphNode->node.flags |= GRAPH_RENDER_HAS_ANIMATION;
|
||||
graphNode->node.flags &= ~GRAPH_RENDER_BILLBOARD;
|
||||
}
|
||||
|
||||
static struct Object *spawn_object_at_origin(void) {
|
||||
struct Object *obj;
|
||||
obj = create_object();
|
||||
|
||||
obj->parentObj = NULL;
|
||||
obj->header.gfx.areaIndex = 0;
|
||||
obj->header.gfx.activeAreaIndex = 0;
|
||||
// geo_obj_init((struct GraphNodeObject *) &obj->header.gfx, gLoadedGraphNodes[model], gVec3fZero, gVec3sZero);
|
||||
geo_obj_init((struct GraphNodeObject *) &obj->header.gfx, NULL, gVec3fZero, gVec3sZero);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy position, velocity, and angle variables from MarioState to the Mario
|
||||
* object.
|
||||
*/
|
||||
static void copy_mario_state_to_object(void) {
|
||||
s32 i = 0;
|
||||
// L is real
|
||||
if (gCurrentObject != gMarioObject) {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
gCurrentObject->oVelX = gMarioState->vel[0];
|
||||
gCurrentObject->oVelY = gMarioState->vel[1];
|
||||
gCurrentObject->oVelZ = gMarioState->vel[2];
|
||||
|
||||
gCurrentObject->oPosX = gMarioState->pos[0];
|
||||
gCurrentObject->oPosY = gMarioState->pos[1];
|
||||
gCurrentObject->oPosZ = gMarioState->pos[2];
|
||||
|
||||
gCurrentObject->oMoveAnglePitch = gCurrentObject->header.gfx.angle[0];
|
||||
gCurrentObject->oMoveAngleYaw = gCurrentObject->header.gfx.angle[1];
|
||||
gCurrentObject->oMoveAngleRoll = gCurrentObject->header.gfx.angle[2];
|
||||
|
||||
gCurrentObject->oFaceAnglePitch = gCurrentObject->header.gfx.angle[0];
|
||||
gCurrentObject->oFaceAngleYaw = gCurrentObject->header.gfx.angle[1];
|
||||
gCurrentObject->oFaceAngleRoll = gCurrentObject->header.gfx.angle[2];
|
||||
|
||||
gCurrentObject->oAngleVelPitch = gMarioState->angleVel[0];
|
||||
gCurrentObject->oAngleVelYaw = gMarioState->angleVel[1];
|
||||
gCurrentObject->oAngleVelRoll = gMarioState->angleVel[2];
|
||||
}
|
||||
|
||||
struct Object *hack_allocate_mario(void)
|
||||
{
|
||||
return spawn_object_at_origin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mario's primary behavior update function.
|
||||
*/
|
||||
void bhv_mario_update(void) {
|
||||
u32 particleFlags = 0;
|
||||
// s32 i;
|
||||
|
||||
gCurrentObject = gMarioObject;
|
||||
particleFlags = execute_mario_action(gCurrentObject);
|
||||
gCurrentObject->oMarioParticleFlags = particleFlags;
|
||||
|
||||
// Mario code updates MarioState's versions of position etc, so we need
|
||||
// to sync it with the Mario object
|
||||
copy_mario_state_to_object();
|
||||
|
||||
// i = 0;
|
||||
// while (sParticleTypes[i].particleFlag != 0) {
|
||||
// if (particleFlags & sParticleTypes[i].particleFlag) {
|
||||
// spawn_particle(sParticleTypes[i].activeParticleFlag, sParticleTypes[i].model,
|
||||
// sParticleTypes[i].behavior);
|
||||
// }
|
||||
|
||||
// i++;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void create_transformation_from_matrices(Mat4 a0, Mat4 a1, Mat4 a2) {
|
||||
f32 spC, sp8, sp4;
|
||||
|
||||
spC = a2[3][0] * a2[0][0] + a2[3][1] * a2[0][1] + a2[3][2] * a2[0][2];
|
||||
sp8 = a2[3][0] * a2[1][0] + a2[3][1] * a2[1][1] + a2[3][2] * a2[1][2];
|
||||
sp4 = a2[3][0] * a2[2][0] + a2[3][1] * a2[2][1] + a2[3][2] * a2[2][2];
|
||||
|
||||
a0[0][0] = a1[0][0] * a2[0][0] + a1[0][1] * a2[0][1] + a1[0][2] * a2[0][2];
|
||||
a0[0][1] = a1[0][0] * a2[1][0] + a1[0][1] * a2[1][1] + a1[0][2] * a2[1][2];
|
||||
a0[0][2] = a1[0][0] * a2[2][0] + a1[0][1] * a2[2][1] + a1[0][2] * a2[2][2];
|
||||
|
||||
a0[1][0] = a1[1][0] * a2[0][0] + a1[1][1] * a2[0][1] + a1[1][2] * a2[0][2];
|
||||
a0[1][1] = a1[1][0] * a2[1][0] + a1[1][1] * a2[1][1] + a1[1][2] * a2[1][2];
|
||||
a0[1][2] = a1[1][0] * a2[2][0] + a1[1][1] * a2[2][1] + a1[1][2] * a2[2][2];
|
||||
|
||||
a0[2][0] = a1[2][0] * a2[0][0] + a1[2][1] * a2[0][1] + a1[2][2] * a2[0][2];
|
||||
a0[2][1] = a1[2][0] * a2[1][0] + a1[2][1] * a2[1][1] + a1[2][2] * a2[1][2];
|
||||
a0[2][2] = a1[2][0] * a2[2][0] + a1[2][1] * a2[2][1] + a1[2][2] * a2[2][2];
|
||||
|
||||
a0[3][0] = a1[3][0] * a2[0][0] + a1[3][1] * a2[0][1] + a1[3][2] * a2[0][2] - spC;
|
||||
a0[3][1] = a1[3][0] * a2[1][0] + a1[3][1] * a2[1][1] + a1[3][2] * a2[1][2] - sp8;
|
||||
a0[3][2] = a1[3][0] * a2[2][0] + a1[3][1] * a2[2][1] + a1[3][2] * a2[2][2] - sp4;
|
||||
|
||||
a0[0][3] = 0;
|
||||
a0[1][3] = 0;
|
||||
a0[2][3] = 0;
|
||||
a0[3][3] = 1.0f;
|
||||
}
|
||||
void obj_update_pos_from_parent_transformation(Mat4 a0, struct Object *a1) {
|
||||
f32 spC = a1->oParentRelativePosX;
|
||||
f32 sp8 = a1->oParentRelativePosY;
|
||||
f32 sp4 = a1->oParentRelativePosZ;
|
||||
|
||||
a1->oPosX = spC * a0[0][0] + sp8 * a0[1][0] + sp4 * a0[2][0] + a0[3][0];
|
||||
a1->oPosY = spC * a0[0][1] + sp8 * a0[1][1] + sp4 * a0[2][1] + a0[3][1];
|
||||
a1->oPosZ = spC * a0[0][2] + sp8 * a0[1][2] + sp4 * a0[2][2] + a0[3][2];
|
||||
}
|
||||
void obj_set_gfx_pos_from_pos(struct Object *obj) {
|
||||
obj->header.gfx.pos[0] = obj->oPosX;
|
||||
obj->header.gfx.pos[1] = obj->oPosY;
|
||||
obj->header.gfx.pos[2] = obj->oPosZ;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../include/types.h"
|
||||
|
||||
struct Object *hack_allocate_mario(void);
|
||||
void bhv_mario_update(void);
|
||||
void create_transformation_from_matrices(Mat4 a0, Mat4 a1, Mat4 a2);
|
||||
void obj_update_pos_from_parent_transformation(Mat4 a0, struct Object *a1);
|
||||
void obj_set_gfx_pos_from_pos(struct Object *obj);
|
||||
@@ -0,0 +1,181 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "../engine/math_util.h"
|
||||
#include "../engine/surface_collision.h"
|
||||
#include "level_update.h"
|
||||
#include "../include/object_fields.h"
|
||||
#include "object_stuff.h"
|
||||
#include "platform_displacement.h"
|
||||
#include "../shim.h"
|
||||
|
||||
struct SurfaceObjectTransform *gMarioPlatform = NULL;
|
||||
|
||||
#define absfx( x ) ( (x) < 0.0f ? -(x) : (x) )
|
||||
|
||||
/**
|
||||
* Determine if Mario is standing on a platform object, meaning that he is
|
||||
* within 4 units of the floor. Set his referenced platform object accordingly.
|
||||
*/
|
||||
void update_mario_platform(void) {
|
||||
struct Surface *floor;
|
||||
UNUSED u32 unused;
|
||||
f32 marioX;
|
||||
f32 marioY;
|
||||
f32 marioZ;
|
||||
f32 floorHeight;
|
||||
u32 awayFromFloor;
|
||||
|
||||
if (gMarioObject == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//! If Mario moves onto a rotating platform in a PU, the find_floor call
|
||||
// will detect the platform and he will end up receiving a large amount
|
||||
// of displacement since he is considered to be far from the platform's
|
||||
// axis of rotation.
|
||||
|
||||
marioX = gMarioObject->oPosX;
|
||||
marioY = gMarioObject->oPosY;
|
||||
marioZ = gMarioObject->oPosZ;
|
||||
floorHeight = find_floor(marioX, marioY, marioZ, &floor);
|
||||
|
||||
if (absfx(marioY - floorHeight) < 4.0f) {
|
||||
awayFromFloor = 0;
|
||||
} else {
|
||||
awayFromFloor = 1;
|
||||
}
|
||||
|
||||
switch (awayFromFloor) {
|
||||
case 1:
|
||||
gMarioPlatform = NULL;
|
||||
gMarioObject->platform = NULL;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (floor != NULL && floor->object != NULL) {
|
||||
gMarioPlatform = (struct SurfaceObjectTransform *)floor->object;
|
||||
gMarioObject->platform = floor->object;
|
||||
} else {
|
||||
gMarioPlatform = NULL;
|
||||
gMarioObject->platform = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Mario's position and store it in x, y, and z.
|
||||
*/
|
||||
static void get_mario_pos(f32 *x, f32 *y, f32 *z) {
|
||||
*x = gMarioState->pos[0];
|
||||
*y = gMarioState->pos[1];
|
||||
*z = gMarioState->pos[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Mario's position.
|
||||
*/
|
||||
static void set_mario_pos(f32 x, f32 y, f32 z) {
|
||||
gMarioState->pos[0] = x;
|
||||
gMarioState->pos[1] = y;
|
||||
gMarioState->pos[2] = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply one frame of platform rotation to Mario or an object using the given
|
||||
* platform. If isMario is false, use gCurrentObject.
|
||||
*/
|
||||
void apply_platform_displacement(u32 isMario, struct SurfaceObjectTransform *platform) {
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 z;
|
||||
f32 platformPosX;
|
||||
f32 platformPosY;
|
||||
f32 platformPosZ;
|
||||
Vec3f currentObjectOffset;
|
||||
Vec3f relativeOffset;
|
||||
Vec3f newObjectOffset;
|
||||
Vec3s rotation;
|
||||
UNUSED s16 unused1;
|
||||
UNUSED s16 unused2;
|
||||
UNUSED s16 unused3;
|
||||
f32 displaceMatrix[4][4];
|
||||
|
||||
rotation[0] = platform->aAngleVelPitch;
|
||||
rotation[1] = platform->aAngleVelYaw;
|
||||
rotation[2] = platform->aAngleVelRoll;
|
||||
|
||||
// if (isMario) {
|
||||
// D_8032FEC0 = 0;
|
||||
get_mario_pos(&x, &y, &z);
|
||||
// } else {
|
||||
// x = gCurrentObject->aPosX;
|
||||
// y = gCurrentObject->aPosY;
|
||||
// z = gCurrentObject->aPosZ;
|
||||
// }
|
||||
|
||||
x += platform->aVelX;
|
||||
z += platform->aVelZ;
|
||||
|
||||
if (rotation[0] != 0 || rotation[1] != 0 || rotation[2] != 0) {
|
||||
unused1 = rotation[0];
|
||||
unused2 = rotation[2];
|
||||
unused3 = platform->aFaceAngleYaw;
|
||||
|
||||
if (isMario) {
|
||||
gMarioState->faceAngle[1] += rotation[1];
|
||||
}
|
||||
|
||||
platformPosX = platform->aPosX;
|
||||
platformPosY = platform->aPosY;
|
||||
platformPosZ = platform->aPosZ;
|
||||
|
||||
currentObjectOffset[0] = x - platformPosX;
|
||||
currentObjectOffset[1] = y - platformPosY;
|
||||
currentObjectOffset[2] = z - platformPosZ;
|
||||
|
||||
rotation[0] = platform->aFaceAnglePitch - platform->aAngleVelPitch;
|
||||
rotation[1] = platform->aFaceAngleYaw - platform->aAngleVelYaw;
|
||||
rotation[2] = platform->aFaceAngleRoll - platform->aAngleVelRoll;
|
||||
|
||||
mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation);
|
||||
linear_mtxf_transpose_mul_vec3f(displaceMatrix, relativeOffset, currentObjectOffset);
|
||||
|
||||
rotation[0] = platform->aFaceAnglePitch;
|
||||
rotation[1] = platform->aFaceAngleYaw;
|
||||
rotation[2] = platform->aFaceAngleRoll;
|
||||
|
||||
mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation);
|
||||
linear_mtxf_mul_vec3f(displaceMatrix, newObjectOffset, relativeOffset);
|
||||
|
||||
x = platformPosX + newObjectOffset[0];
|
||||
y = platformPosY + newObjectOffset[1];
|
||||
z = platformPosZ + newObjectOffset[2];
|
||||
}
|
||||
|
||||
// if (isMario) {
|
||||
set_mario_pos(x, y, z);
|
||||
// } else {
|
||||
// gCurrentObject->oPosX = x;
|
||||
// gCurrentObject->oPosY = y;
|
||||
// gCurrentObject->oPosZ = z;
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* If Mario's platform is not null, apply platform displacement.
|
||||
*/
|
||||
void apply_mario_platform_displacement(void) {
|
||||
struct SurfaceObjectTransform *platform = gMarioPlatform;
|
||||
|
||||
if (gMarioObject != NULL && platform != NULL) {
|
||||
apply_platform_displacement(TRUE, platform);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Mario's platform to NULL.
|
||||
*/
|
||||
void clear_mario_platform(void) {
|
||||
gMarioPlatform = NULL;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef PLATFORM_DISPLACEMENT_H
|
||||
#define PLATFORM_DISPLACEMENT_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
#include "../include/types.h"
|
||||
|
||||
void update_mario_platform(void);
|
||||
void apply_mario_platform_displacement(void);
|
||||
void clear_mario_platform(void);
|
||||
|
||||
#endif // PLATFORM_DISPLACEMENT_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
||||
#ifndef RENDERING_GRAPH_NODE_H
|
||||
#define RENDERING_GRAPH_NODE_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../engine/graph_node.h"
|
||||
|
||||
extern struct GraphNodeRoot *gCurGraphNodeRoot;
|
||||
extern struct GraphNodeMasterList *gCurGraphNodeMasterList;
|
||||
extern struct GraphNodePerspective *gCurGraphNodeCamFrustum;
|
||||
extern struct GraphNodeCamera *gCurGraphNodeCamera;
|
||||
extern struct GraphNodeObject *gCurGraphNodeObject;
|
||||
extern struct GraphNodeHeldObject *gCurGraphNodeHeldObject;
|
||||
extern u16 gAreaUpdateCounter;
|
||||
|
||||
// after processing an object, the type is reset to this
|
||||
#define ANIM_TYPE_NONE 0
|
||||
|
||||
// Not all parts have full animation: to save space, some animations only
|
||||
// have xz, y, or no translation at all. All animations have rotations though
|
||||
#define ANIM_TYPE_TRANSLATION 1
|
||||
#define ANIM_TYPE_VERTICAL_TRANSLATION 2
|
||||
#define ANIM_TYPE_LATERAL_TRANSLATION 3
|
||||
#define ANIM_TYPE_NO_TRANSLATION 4
|
||||
|
||||
// Every animation includes rotation, after processing any of the above
|
||||
// translation types the type is set to this
|
||||
#define ANIM_TYPE_ROTATION 5
|
||||
|
||||
void geo_process_node_and_siblings(struct GraphNode *firstNode);
|
||||
//void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor);
|
||||
void geo_process_root_hack_single_node(struct GraphNode *node);
|
||||
|
||||
#endif // RENDERING_GRAPH_NODE_H
|
||||
@@ -0,0 +1,175 @@
|
||||
#ifndef SAVE_FILE_H
|
||||
#define SAVE_FILE_H
|
||||
|
||||
#include "../include/PR/ultratypes.h"
|
||||
|
||||
#include "../include/types.h"
|
||||
#include "area.h"
|
||||
|
||||
// #include "course_table.h"
|
||||
// ===== PATCH =====
|
||||
#define COURSE_COUNT 120
|
||||
#define COURSE_STAGES_COUNT 15
|
||||
// =================
|
||||
|
||||
#define EEPROM_SIZE 0x200
|
||||
#define NUM_SAVE_FILES 4
|
||||
|
||||
struct SaveBlockSignature
|
||||
{
|
||||
u16 magic;
|
||||
u16 chksum;
|
||||
};
|
||||
|
||||
struct SaveFile
|
||||
{
|
||||
// Location of lost cap.
|
||||
// Note: the coordinates get set, but are never actually used, since the
|
||||
// cap can always be found in a fixed spot within the course
|
||||
u8 capLevel;
|
||||
u8 capArea;
|
||||
Vec3s capPos;
|
||||
|
||||
u32 flags;
|
||||
|
||||
// Star flags for each course.
|
||||
// The most significant bit of the byte *following* each course is set if the
|
||||
// cannon is open.
|
||||
u8 courseStars[COURSE_COUNT];
|
||||
|
||||
u8 courseCoinScores[COURSE_STAGES_COUNT];
|
||||
|
||||
struct SaveBlockSignature signature;
|
||||
};
|
||||
|
||||
enum SaveFileIndex {
|
||||
SAVE_FILE_A,
|
||||
SAVE_FILE_B,
|
||||
SAVE_FILE_C,
|
||||
SAVE_FILE_D
|
||||
};
|
||||
|
||||
struct MainMenuSaveData
|
||||
{
|
||||
// Each save file has a 2 bit "age" for each course. The higher this value,
|
||||
// the older the high score is. This is used for tie-breaking when displaying
|
||||
// on the high score screen.
|
||||
u32 coinScoreAges[NUM_SAVE_FILES];
|
||||
u16 soundMode;
|
||||
|
||||
#ifdef VERSION_EU
|
||||
u16 language;
|
||||
#define SUBTRAHEND 8
|
||||
#else
|
||||
#define SUBTRAHEND 6
|
||||
#endif
|
||||
|
||||
// Pad to match the EEPROM size of 0x200 (10 bytes on JP/US, 8 bytes on EU)
|
||||
u8 filler[ 128 ]; // EEPROM_SIZE / 2 - SUBTRAHEND - NUM_SAVE_FILES * (4 + sizeof(struct SaveFile))];
|
||||
|
||||
struct SaveBlockSignature signature;
|
||||
};
|
||||
|
||||
struct SaveBuffer
|
||||
{
|
||||
// Each of the four save files has two copies. If one is bad, the other is used as a backup.
|
||||
struct SaveFile files[NUM_SAVE_FILES][2];
|
||||
// The main menu data has two copies. If one is bad, the other is used as a backup.
|
||||
// struct MainMenuSaveData menuData[0];
|
||||
};
|
||||
|
||||
extern u8 gLastCompletedCourseNum;
|
||||
extern u8 gLastCompletedStarNum;
|
||||
extern s8 sUnusedGotGlobalCoinHiScore;
|
||||
extern u8 gGotFileCoinHiScore;
|
||||
extern u8 gCurrCourseStarFlags;
|
||||
extern u8 gSpecialTripleJump;
|
||||
extern s8 gLevelToCourseNumTable[];
|
||||
|
||||
// game progress flags
|
||||
#define SAVE_FLAG_FILE_EXISTS /* 0x00000001 */ (1 << 0)
|
||||
#define SAVE_FLAG_HAVE_WING_CAP /* 0x00000002 */ (1 << 1)
|
||||
#define SAVE_FLAG_HAVE_METAL_CAP /* 0x00000004 */ (1 << 2)
|
||||
#define SAVE_FLAG_HAVE_VANISH_CAP /* 0x00000008 */ (1 << 3)
|
||||
#define SAVE_FLAG_HAVE_KEY_1 /* 0x00000010 */ (1 << 4)
|
||||
#define SAVE_FLAG_HAVE_KEY_2 /* 0x00000020 */ (1 << 5)
|
||||
#define SAVE_FLAG_UNLOCKED_BASEMENT_DOOR /* 0x00000040 */ (1 << 6)
|
||||
#define SAVE_FLAG_UNLOCKED_UPSTAIRS_DOOR /* 0x00000080 */ (1 << 7)
|
||||
#define SAVE_FLAG_DDD_MOVED_BACK /* 0x00000100 */ (1 << 8)
|
||||
#define SAVE_FLAG_MOAT_DRAINED /* 0x00000200 */ (1 << 9)
|
||||
#define SAVE_FLAG_UNLOCKED_PSS_DOOR /* 0x00000400 */ (1 << 10)
|
||||
#define SAVE_FLAG_UNLOCKED_WF_DOOR /* 0x00000800 */ (1 << 11)
|
||||
#define SAVE_FLAG_UNLOCKED_CCM_DOOR /* 0x00001000 */ (1 << 12)
|
||||
#define SAVE_FLAG_UNLOCKED_JRB_DOOR /* 0x00002000 */ (1 << 13)
|
||||
#define SAVE_FLAG_UNLOCKED_BITDW_DOOR /* 0x00004000 */ (1 << 14)
|
||||
#define SAVE_FLAG_UNLOCKED_BITFS_DOOR /* 0x00008000 */ (1 << 15)
|
||||
#define SAVE_FLAG_CAP_ON_GROUND /* 0x00010000 */ (1 << 16)
|
||||
#define SAVE_FLAG_CAP_ON_KLEPTO /* 0x00020000 */ (1 << 17)
|
||||
#define SAVE_FLAG_CAP_ON_UKIKI /* 0x00040000 */ (1 << 18)
|
||||
#define SAVE_FLAG_CAP_ON_MR_BLIZZARD /* 0x00080000 */ (1 << 19)
|
||||
#define SAVE_FLAG_UNLOCKED_50_STAR_DOOR /* 0x00100000 */ (1 << 20)
|
||||
#define SAVE_FLAG_COLLECTED_TOAD_STAR_1 /* 0x01000000 */ (1 << 24)
|
||||
#define SAVE_FLAG_COLLECTED_TOAD_STAR_2 /* 0x02000000 */ (1 << 25)
|
||||
#define SAVE_FLAG_COLLECTED_TOAD_STAR_3 /* 0x04000000 */ (1 << 26)
|
||||
#define SAVE_FLAG_COLLECTED_MIPS_STAR_1 /* 0x08000000 */ (1 << 27)
|
||||
#define SAVE_FLAG_COLLECTED_MIPS_STAR_2 /* 0x10000000 */ (1 << 28)
|
||||
|
||||
#define SAVE_FLAG_TO_STAR_FLAG(cmd) (((cmd) >> 24) & 0x7F)
|
||||
#define STAR_FLAG_TO_SAVE_FLAG(cmd) ((cmd) << 24)
|
||||
|
||||
// Variable for setting a warp checkpoint.
|
||||
|
||||
// possibly a WarpDest struct where arg is a union. TODO: Check?
|
||||
struct WarpCheckpoint {
|
||||
/*0x00*/ u8 actNum;
|
||||
/*0x01*/ u8 courseNum;
|
||||
/*0x02*/ u8 levelID;
|
||||
/*0x03*/ u8 areaNum;
|
||||
/*0x04*/ u8 warpNode;
|
||||
};
|
||||
|
||||
extern struct WarpCheckpoint gWarpCheckpoint;
|
||||
|
||||
extern s8 gMainMenuDataModified;
|
||||
extern s8 gSaveFileModified;
|
||||
|
||||
void save_file_do_save(s32 fileIndex);
|
||||
void save_file_erase(s32 fileIndex);
|
||||
BAD_RETURN(s32) save_file_copy(s32 srcFileIndex, s32 destFileIndex);
|
||||
void save_file_load_all(void);
|
||||
void save_file_reload(void);
|
||||
void save_file_collect_star_or_key(s16 coinScore, s16 starIndex);
|
||||
s32 save_file_exists(s32 fileIndex);
|
||||
u32 save_file_get_max_coin_score(s32 courseIndex);
|
||||
s32 save_file_get_course_star_count(s32 fileIndex, s32 courseIndex);
|
||||
s32 save_file_get_total_star_count(s32 fileIndex, s32 minCourse, s32 maxCourse);
|
||||
void save_file_set_flags(u32 flags);
|
||||
void save_file_clear_flags(u32 flags);
|
||||
u32 save_file_get_flags(void);
|
||||
u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex);
|
||||
void save_file_set_star_flags(s32 fileIndex, s32 courseIndex, u32 starFlags);
|
||||
s32 save_file_get_course_coin_score(s32 fileIndex, s32 courseIndex);
|
||||
s32 save_file_is_cannon_unlocked(void);
|
||||
void save_file_set_cannon_unlocked(void);
|
||||
void save_file_set_cap_pos(s16 x, s16 y, s16 z);
|
||||
s32 save_file_get_cap_pos(Vec3s capPos);
|
||||
void save_file_set_sound_mode(u16 mode);
|
||||
u16 save_file_get_sound_mode(void);
|
||||
void save_file_move_cap_to_default_location(void);
|
||||
|
||||
void disable_warp_checkpoint(void);
|
||||
void check_if_should_set_warp_checkpoint(struct WarpNode *warpNode);
|
||||
s32 check_warp_checkpoint(struct WarpNode *warpNode);
|
||||
|
||||
#ifdef VERSION_EU
|
||||
enum EuLanguages {
|
||||
LANGUAGE_ENGLISH,
|
||||
LANGUAGE_FRENCH,
|
||||
LANGUAGE_GERMAN
|
||||
};
|
||||
|
||||
void eu_set_language(u16 language);
|
||||
u16 eu_get_language(void);
|
||||
#endif
|
||||
|
||||
#endif // SAVE_FILE_H
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "global_state.h"
|
||||
|
||||
struct GlobalState *gState = 0;
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "include/types.h"
|
||||
#include "game/area.h"
|
||||
|
||||
struct GlobalState
|
||||
{
|
||||
// interaction.c
|
||||
u8 sDelayInvincTimer;
|
||||
s16 sInvulnerable;
|
||||
|
||||
// mario_actions_moving.c
|
||||
Mat4 sFloorAlignMatrix;
|
||||
|
||||
// mario_actions_submerged.c
|
||||
s16 sWasAtSurface;
|
||||
s16 sSwimStrength;
|
||||
s16 D_80339FD0;
|
||||
s16 D_80339FD2;
|
||||
f32 D_80339FD4;
|
||||
|
||||
// mario_misc.c
|
||||
struct MarioBodyState gBodyStates[2];
|
||||
|
||||
// platform_displacement.c
|
||||
void *gMarioPlatform;
|
||||
|
||||
// misc
|
||||
u32 gGlobalTimer;
|
||||
u8 gSpecialTripleJump;
|
||||
s16 gCurrLevelNum;
|
||||
s16 gCameraMovementFlags;
|
||||
u32 gAudioRandom;
|
||||
s8 gShowDebugText;
|
||||
s8 gDebugLevelSelect;
|
||||
s16 gCurrSaveFileNum;
|
||||
struct Controller gController;
|
||||
struct SpawnInfo gMarioSpawnInfoVal;
|
||||
struct SpawnInfo *gMarioSpawnInfo;
|
||||
struct Area *gCurrentArea;
|
||||
struct Object *gCurrentObject;
|
||||
struct Object *gMarioObject;
|
||||
struct MarioAnimation D_80339D10;
|
||||
struct MarioState gMarioStateVal;
|
||||
struct MarioState *gMarioState;
|
||||
};
|
||||
|
||||
extern struct GlobalState *gState;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,207 @@
|
||||
|
||||
/*====================================================================
|
||||
* os_cont.h
|
||||
*
|
||||
* Copyright 1995, Silicon Graphics, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
|
||||
* Inc.; the contents of this file may not be disclosed to third
|
||||
* parties, copied or duplicated in any form, in whole or in part,
|
||||
* without the prior written permission of Silicon Graphics, Inc.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND:
|
||||
* Use, duplication or disclosure by the Government is subject to
|
||||
* restrictions as set forth in subdivision (c)(1)(ii) of the Rights
|
||||
* in Technical Data and Computer Software clause at DFARS
|
||||
* 252.227-7013, and/or in similar or successor clauses in the FAR,
|
||||
* DOD or NASA FAR Supplement. Unpublished - rights reserved under the
|
||||
* Copyright Laws of the United States.
|
||||
*====================================================================*/
|
||||
|
||||
/*---------------------------------------------------------------------*
|
||||
Copyright (C) 1998 Nintendo. (Originated by SGI)
|
||||
|
||||
$RCSfile: os_cont.h,v $
|
||||
$Revision: 1.1 $
|
||||
$Date: 1998/10/09 08:01:05 $
|
||||
*---------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _OS_CONT_H_
|
||||
#define _OS_CONT_H_
|
||||
|
||||
#ifdef _LANGUAGE_C_PLUS_PLUS
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ultratypes.h"
|
||||
//#include "os_message.h"
|
||||
|
||||
|
||||
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Type definitions
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Structure for controllers
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
u16 type; /* Controller Type */
|
||||
u8 status; /* Controller status */
|
||||
u8 errnum;
|
||||
}OSContStatus;
|
||||
|
||||
typedef struct {
|
||||
u16 button;
|
||||
s8 stick_x; /* -80 <= stick_x <= 80 */
|
||||
s8 stick_y; /* -80 <= stick_y <= 80 */
|
||||
u8 errnum;
|
||||
} OSContPad;
|
||||
|
||||
typedef struct {
|
||||
void *address; /* Ram pad Address: 11 bits */
|
||||
u8 databuffer[32]; /* address of the data buffer */
|
||||
u8 addressCrc; /* CRC code for address */
|
||||
u8 dataCrc; /* CRC code for data */
|
||||
u8 errnum;
|
||||
} OSContRamIo;
|
||||
|
||||
|
||||
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Global definitions
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Controllers number
|
||||
*/
|
||||
|
||||
#ifndef _HW_VERSION_1
|
||||
#define MAXCONTROLLERS 4
|
||||
#else
|
||||
#define MAXCONTROLLERS 6
|
||||
#endif
|
||||
|
||||
/* controller errors */
|
||||
#define CONT_NO_RESPONSE_ERROR 0x8
|
||||
#define CONT_OVERRUN_ERROR 0x4
|
||||
#ifdef _HW_VERSION_1
|
||||
#define CONT_FRAME_ERROR 0x2
|
||||
#define CONT_COLLISION_ERROR 0x1
|
||||
#endif
|
||||
|
||||
/* Controller type */
|
||||
|
||||
#define CONT_ABSOLUTE 0x0001
|
||||
#define CONT_RELATIVE 0x0002
|
||||
#define CONT_JOYPORT 0x0004
|
||||
#define CONT_EEPROM 0x8000
|
||||
#define CONT_EEP16K 0x4000
|
||||
#define CONT_TYPE_MASK 0x1f07
|
||||
#define CONT_TYPE_NORMAL 0x0005
|
||||
#define CONT_TYPE_MOUSE 0x0002
|
||||
#define CONT_TYPE_VOICE 0x0100
|
||||
|
||||
/* Controller status */
|
||||
|
||||
#define CONT_CARD_ON 0x01
|
||||
#define CONT_CARD_PULL 0x02
|
||||
#define CONT_ADDR_CRC_ER 0x04
|
||||
#define CONT_EEPROM_BUSY 0x80
|
||||
|
||||
/* Buttons */
|
||||
|
||||
#define CONT_A 0x8000
|
||||
#define CONT_B 0x4000
|
||||
#define CONT_G 0x2000
|
||||
#define CONT_START 0x1000
|
||||
#define CONT_UP 0x0800
|
||||
#define CONT_DOWN 0x0400
|
||||
#define CONT_LEFT 0x0200
|
||||
#define CONT_RIGHT 0x0100
|
||||
#define CONT_L 0x0020
|
||||
#define CONT_R 0x0010
|
||||
#define CONT_E 0x0008
|
||||
#define CONT_D 0x0004
|
||||
#define CONT_C 0x0002
|
||||
#define CONT_F 0x0001
|
||||
|
||||
/* Nintendo's official button names */
|
||||
|
||||
#define A_BUTTON CONT_A
|
||||
#define B_BUTTON CONT_B
|
||||
#define L_TRIG CONT_L
|
||||
#define R_TRIG CONT_R
|
||||
#define Z_TRIG CONT_G
|
||||
#define START_BUTTON CONT_START
|
||||
#define U_JPAD CONT_UP
|
||||
#define L_JPAD CONT_LEFT
|
||||
#define R_JPAD CONT_RIGHT
|
||||
#define D_JPAD CONT_DOWN
|
||||
#define U_CBUTTONS CONT_E
|
||||
#define L_CBUTTONS CONT_C
|
||||
#define R_CBUTTONS CONT_F
|
||||
#define D_CBUTTONS CONT_D
|
||||
|
||||
/* Controller error number */
|
||||
|
||||
#define CONT_ERR_NO_CONTROLLER PFS_ERR_NOPACK /* 1 */
|
||||
#define CONT_ERR_CONTRFAIL CONT_OVERRUN_ERROR /* 4 */
|
||||
#define CONT_ERR_INVALID PFS_ERR_INVALID /* 5 */
|
||||
#define CONT_ERR_DEVICE PFS_ERR_DEVICE /* 11 */
|
||||
#define CONT_ERR_NOT_READY 12
|
||||
#define CONT_ERR_VOICE_MEMORY 13
|
||||
#define CONT_ERR_VOICE_WORD 14
|
||||
#define CONT_ERR_VOICE_NO_RESPONSE 15
|
||||
|
||||
//
|
||||
// #if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
|
||||
//
|
||||
// /**************************************************************************
|
||||
// *
|
||||
// * Macro definitions
|
||||
// *
|
||||
// */
|
||||
//
|
||||
//
|
||||
// /**************************************************************************
|
||||
// *
|
||||
// * Extern variables
|
||||
// *
|
||||
// */
|
||||
//
|
||||
//
|
||||
// /**************************************************************************
|
||||
// *
|
||||
// * Function prototypes
|
||||
// *
|
||||
// */
|
||||
//
|
||||
// /* Controller interface */
|
||||
//
|
||||
// extern s32 osContInit(OSMesgQueue *, u8 *, OSContStatus *);
|
||||
// extern s32 osContReset(OSMesgQueue *, OSContStatus *);
|
||||
// extern s32 osContStartQuery(OSMesgQueue *);
|
||||
// extern s32 osContStartReadData(OSMesgQueue *);
|
||||
// #ifndef _HW_VERSION_1
|
||||
// extern s32 osContSetCh(u8);
|
||||
// #endif
|
||||
// extern void osContGetQuery(OSContStatus *);
|
||||
// extern void osContGetReadData(OSContPad *);
|
||||
//
|
||||
//
|
||||
// #endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */
|
||||
//
|
||||
// #ifdef _LANGUAGE_C_PLUS_PLUS
|
||||
// }
|
||||
// #endif
|
||||
|
||||
#endif /* !_OS_CONT_H_ */
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef _ULTRA64_TYPES_H_
|
||||
#define _ULTRA64_TYPES_H_
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
typedef signed char s8;
|
||||
typedef unsigned char u8;
|
||||
typedef signed short int s16;
|
||||
typedef unsigned short int u16;
|
||||
typedef signed int s32;
|
||||
typedef unsigned int u32;
|
||||
typedef signed long long int s64;
|
||||
typedef unsigned long long int u64;
|
||||
|
||||
typedef volatile u8 vu8;
|
||||
typedef volatile u16 vu16;
|
||||
typedef volatile u32 vu32;
|
||||
typedef volatile u64 vu64;
|
||||
typedef volatile s8 vs8;
|
||||
typedef volatile s16 vs16;
|
||||
typedef volatile s32 vs32;
|
||||
typedef volatile s64 vs64;
|
||||
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#ifdef TARGET_N64
|
||||
typedef u32 size_t;
|
||||
typedef s32 ssize_t;
|
||||
typedef u32 uintptr_t;
|
||||
typedef s32 intptr_t;
|
||||
typedef s32 ptrdiff_t;
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
typedef ptrdiff_t ssize_t;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,561 @@
|
||||
#ifndef AUDIO_DEFINES_H
|
||||
#define AUDIO_DEFINES_H
|
||||
|
||||
// Sound Magic Definition:
|
||||
// First Byte (Upper Nibble): Sound Bank (not the same as audio bank!)
|
||||
// First Byte (Lower Nibble): Bitflags for audio playback?
|
||||
// Second Byte: Sound ID
|
||||
// Third Byte: Priority
|
||||
// Fourth Byte (Upper Nibble): More bitflags
|
||||
// Fourth Byte (Lower Nibble): Sound Status (this is set to SOUND_STATUS_PLAYING when passed to the audio driver.)
|
||||
#define SOUND_ARG_LOAD(bank, playFlags, soundID, priority, flags2) (((u32) (bank) << 28) | \
|
||||
((u32) (playFlags) << 24) | ((u32) (soundID) << 16) | ((u32) (priority) << 8) | \
|
||||
((u32) (flags2) << 4) | SOUND_STATUS_STARTING)
|
||||
|
||||
#define SOUNDARGS_MASK_BANK 0xF0000000
|
||||
#define SOUNDARGS_MASK_SOUNDID 0x00FF0000
|
||||
#define SOUNDARGS_MASK_PRIORITY 0x0000FF00
|
||||
#define SOUNDARGS_MASK_STATUS 0x0000000F
|
||||
|
||||
#define SOUNDARGS_SHIFT_BANK 28
|
||||
#define SOUNDARGS_SHIFT_SOUNDID 16
|
||||
#define SOUNDARGS_SHIFT_PRIORITY 8
|
||||
|
||||
/* Audio Status */
|
||||
#define SOUND_STATUS_STOPPED 0
|
||||
#define SOUND_STATUS_STARTING 1
|
||||
#define SOUND_STATUS_PLAYING 2
|
||||
|
||||
/* Audio lower bitflags. TODO: Figure out what these mean and use them below. */
|
||||
#define SOUND_LO_BITFLAG_UNK1 0x10 // fade in?
|
||||
#define SOUND_NO_ECHO 0x20 // not in JP
|
||||
#define SOUND_LO_BITFLAG_UNK8 0x80 // restart playing on each play_sound call?
|
||||
|
||||
/* Audio playback bitflags. */
|
||||
#define SOUND_NO_VOLUME_LOSS 0x1000000 // No volume loss with distance
|
||||
#define SOUND_VIBRATO 0x2000000 // Randomly alter frequency each audio frame
|
||||
#define SOUND_NO_PRIORITY_LOSS 0x4000000 // Do not prioritize closer sounds
|
||||
#define SOUND_NO_FREQUENCY_LOSS 0x8000000 // Frequency scale does not change with distance
|
||||
|
||||
// silence
|
||||
#define NO_SOUND 0
|
||||
|
||||
/**
|
||||
* The table below defines all sounds that exist in the game, and which flags
|
||||
* they are used with. If a sound is used with multiple sets of flags (e.g.
|
||||
* different priorities), they are gives distinguishing suffixes.
|
||||
* A _2 suffix means the sound is the same despite a different sound ID.
|
||||
* Some sounds are unused by the game, and given as hexadecimal literals rather
|
||||
* than SOUND_ARG_LOAD calls.
|
||||
*/
|
||||
|
||||
/* Terrain sounds */
|
||||
|
||||
/**
|
||||
* Terrain-dependent action sounds. mario_get_terrain_sound_addend computes a
|
||||
* sound terrain type between 0 and 7, depending on the terrain type of the
|
||||
* level and the floor type that Mario is standing on. That value is then added
|
||||
* to the sound ID for the TERRAIN_* sounds.
|
||||
*/
|
||||
#define SOUND_TERRAIN_DEFAULT 0 // e.g. air
|
||||
#define SOUND_TERRAIN_GRASS 1
|
||||
#define SOUND_TERRAIN_WATER 2
|
||||
#define SOUND_TERRAIN_STONE 3
|
||||
#define SOUND_TERRAIN_SPOOKY 4 // squeaky floor
|
||||
#define SOUND_TERRAIN_SNOW 5
|
||||
#define SOUND_TERRAIN_ICE 6
|
||||
#define SOUND_TERRAIN_SAND 7
|
||||
|
||||
#define SOUND_ACTION_TERRAIN_JUMP SOUND_ARG_LOAD(0, 4, 0x00, 0x80, 8)
|
||||
#define SOUND_ACTION_TERRAIN_LANDING SOUND_ARG_LOAD(0, 4, 0x08, 0x80, 8)
|
||||
#define SOUND_ACTION_TERRAIN_STEP SOUND_ARG_LOAD(0, 6, 0x10, 0x80, 8)
|
||||
#define SOUND_ACTION_TERRAIN_BODY_HIT_GROUND SOUND_ARG_LOAD(0, 4, 0x18, 0x80, 8)
|
||||
#define SOUND_ACTION_TERRAIN_STEP_TIPTOE SOUND_ARG_LOAD(0, 6, 0x20, 0x80, 8)
|
||||
#define SOUND_ACTION_TERRAIN_STUCK_IN_GROUND SOUND_ARG_LOAD(0, 4, 0x48, 0x80, 8)
|
||||
#define SOUND_ACTION_TERRAIN_HEAVY_LANDING SOUND_ARG_LOAD(0, 4, 0x60, 0x80, 8)
|
||||
|
||||
#define SOUND_ACTION_METAL_JUMP SOUND_ARG_LOAD(0, 4, 0x28, 0x90, 8)
|
||||
#define SOUND_ACTION_METAL_LANDING SOUND_ARG_LOAD(0, 4, 0x29, 0x90, 8)
|
||||
#define SOUND_ACTION_METAL_STEP SOUND_ARG_LOAD(0, 4, 0x2A, 0x90, 8)
|
||||
#define SOUND_ACTION_METAL_HEAVY_LANDING SOUND_ARG_LOAD(0, 4, 0x2B, 0x90, 8)
|
||||
#define SOUND_ACTION_CLAP_HANDS_COLD SOUND_ARG_LOAD(0, 6, 0x2C, 0x00, 8)
|
||||
#define SOUND_ACTION_HANGING_STEP SOUND_ARG_LOAD(0, 4, 0x2D, 0xA0, 8)
|
||||
#define SOUND_ACTION_QUICKSAND_STEP SOUND_ARG_LOAD(0, 4, 0x2E, 0x00, 8)
|
||||
#define SOUND_ACTION_METAL_STEP_TIPTOE SOUND_ARG_LOAD(0, 4, 0x2F, 0x90, 8)
|
||||
/* not verified */ #define SOUND_ACTION_UNKNOWN430 SOUND_ARG_LOAD(0, 4, 0x30, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_ACTION_UNKNOWN431 SOUND_ARG_LOAD(0, 4, 0x31, 0x60, 8)
|
||||
/* not verified */ #define SOUND_ACTION_UNKNOWN432 SOUND_ARG_LOAD(0, 4, 0x32, 0x80, 8)
|
||||
#define SOUND_ACTION_SWIM SOUND_ARG_LOAD(0, 4, 0x33, 0x80, 8)
|
||||
/* not verified */ #define SOUND_ACTION_UNKNOWN434 SOUND_ARG_LOAD(0, 4, 0x34, 0x80, 8)
|
||||
#define SOUND_ACTION_THROW SOUND_ARG_LOAD(0, 4, 0x35, 0x80, 8)
|
||||
#define SOUND_ACTION_KEY_SWISH SOUND_ARG_LOAD(0, 4, 0x36, 0x80, 8)
|
||||
#define SOUND_ACTION_SPIN SOUND_ARG_LOAD(0, 4, 0x37, 0x80, 8)
|
||||
#define SOUND_ACTION_TWIRL SOUND_ARG_LOAD(0, 4, 0x38, 0x80, 8) // same sound as spin
|
||||
/* not verified */ #define SOUND_ACTION_CLIMB_UP_TREE SOUND_ARG_LOAD(0, 4, 0x3A, 0x80, 8)
|
||||
/* not verified */ #define SOUND_ACTION_CLIMB_DOWN_TREE 0x003B
|
||||
/* not verified */ #define SOUND_ACTION_UNK3C 0x003C
|
||||
/* not verified */ #define SOUND_ACTION_UNKNOWN43D SOUND_ARG_LOAD(0, 4, 0x3D, 0x80, 8)
|
||||
/* not verified */ #define SOUND_ACTION_UNKNOWN43E SOUND_ARG_LOAD(0, 4, 0x3E, 0x80, 8)
|
||||
/* not verified */ #define SOUND_ACTION_PAT_BACK SOUND_ARG_LOAD(0, 4, 0x3F, 0x80, 8)
|
||||
#define SOUND_ACTION_BRUSH_HAIR SOUND_ARG_LOAD(0, 4, 0x40, 0x80, 8)
|
||||
/* not verified */ #define SOUND_ACTION_CLIMB_UP_POLE SOUND_ARG_LOAD(0, 4, 0x41, 0x80, 8)
|
||||
#define SOUND_ACTION_METAL_BONK SOUND_ARG_LOAD(0, 4, 0x42, 0x80, 8)
|
||||
#define SOUND_ACTION_UNSTUCK_FROM_GROUND SOUND_ARG_LOAD(0, 4, 0x43, 0x80, 8)
|
||||
/* not verified */ #define SOUND_ACTION_HIT SOUND_ARG_LOAD(0, 4, 0x44, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_ACTION_HIT_2 SOUND_ARG_LOAD(0, 4, 0x44, 0xB0, 8)
|
||||
/* not verified */ #define SOUND_ACTION_HIT_3 SOUND_ARG_LOAD(0, 4, 0x44, 0xA0, 8)
|
||||
#define SOUND_ACTION_BONK SOUND_ARG_LOAD(0, 4, 0x45, 0xA0, 8)
|
||||
#define SOUND_ACTION_SHRINK_INTO_BBH SOUND_ARG_LOAD(0, 4, 0x46, 0xA0, 8)
|
||||
#define SOUND_ACTION_SWIM_FAST SOUND_ARG_LOAD(0, 4, 0x47, 0xA0, 8)
|
||||
#define SOUND_ACTION_METAL_JUMP_WATER SOUND_ARG_LOAD(0, 4, 0x50, 0x90, 8)
|
||||
#define SOUND_ACTION_METAL_LAND_WATER SOUND_ARG_LOAD(0, 4, 0x51, 0x90, 8)
|
||||
#define SOUND_ACTION_METAL_STEP_WATER SOUND_ARG_LOAD(0, 4, 0x52, 0x90, 8)
|
||||
/* not verified */ #define SOUND_ACTION_UNK53 0x0053
|
||||
/* not verified */ #define SOUND_ACTION_UNK54 0x0054
|
||||
/* not verified */ #define SOUND_ACTION_UNK55 0x0055
|
||||
/* not verified */ #define SOUND_ACTION_FLYING_FAST SOUND_ARG_LOAD(0, 4, 0x56, 0x80, 8) // "swoop"?
|
||||
#define SOUND_ACTION_TELEPORT SOUND_ARG_LOAD(0, 4, 0x57, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_ACTION_UNKNOWN458 SOUND_ARG_LOAD(0, 4, 0x58, 0xA0, 8)
|
||||
/* not verified */ #define SOUND_ACTION_BOUNCE_OFF_OBJECT SOUND_ARG_LOAD(0, 4, 0x59, 0xB0, 8)
|
||||
/* not verified */ #define SOUND_ACTION_SIDE_FLIP_UNK SOUND_ARG_LOAD(0, 4, 0x5A, 0x80, 8)
|
||||
#define SOUND_ACTION_READ_SIGN SOUND_ARG_LOAD(0, 4, 0x5B, 0xFF, 8)
|
||||
/* not verified */ #define SOUND_ACTION_UNKNOWN45C SOUND_ARG_LOAD(0, 4, 0x5C, 0x80, 8)
|
||||
/* not verified */ #define SOUND_ACTION_UNK5D 0x005D
|
||||
/* not verified */ #define SOUND_ACTION_INTRO_UNK45E SOUND_ARG_LOAD(0, 4, 0x5E, 0x80, 8)
|
||||
/* not verified */ #define SOUND_ACTION_INTRO_UNK45F SOUND_ARG_LOAD(0, 4, 0x5F, 0x80, 8)
|
||||
|
||||
/* Moving Sound Effects */
|
||||
|
||||
// Terrain-dependent moving sounds; a value 0-7 is added to the sound ID before
|
||||
// playing. See higher up for the different terrain types.
|
||||
#define SOUND_MOVING_TERRAIN_SLIDE SOUND_ARG_LOAD(1, 4, 0x00, 0x00, 0)
|
||||
#define SOUND_MOVING_TERRAIN_RIDING_SHELL SOUND_ARG_LOAD(1, 4, 0x20, 0x00, 0)
|
||||
|
||||
#define SOUND_MOVING_LAVA_BURN SOUND_ARG_LOAD(1, 4, 0x10, 0x00, 0) // ?
|
||||
#define SOUND_MOVING_SLIDE_DOWN_POLE SOUND_ARG_LOAD(1, 4, 0x11, 0x00, 0) // ?
|
||||
#define SOUND_MOVING_SLIDE_DOWN_TREE SOUND_ARG_LOAD(1, 4, 0x12, 0x80, 0)
|
||||
#define SOUND_MOVING_QUICKSAND_DEATH SOUND_ARG_LOAD(1, 4, 0x14, 0x00, 0)
|
||||
#define SOUND_MOVING_SHOCKED SOUND_ARG_LOAD(1, 4, 0x16, 0x00, 0)
|
||||
#define SOUND_MOVING_FLYING SOUND_ARG_LOAD(1, 4, 0x17, 0x00, 0)
|
||||
#define SOUND_MOVING_ALMOST_DROWNING SOUND_ARG_LOAD(1, 0xC, 0x18, 0x00, 0)
|
||||
#define SOUND_MOVING_AIM_CANNON SOUND_ARG_LOAD(1, 0xD, 0x19, 0x20, 0)
|
||||
#define SOUND_MOVING_UNK1A 0x101A // ?
|
||||
#define SOUND_MOVING_RIDING_SHELL_LAVA SOUND_ARG_LOAD(1, 4, 0x28, 0x00, 0)
|
||||
|
||||
/* Mario Sound Effects */
|
||||
// A random number 0-2 is added to the sound ID before playing, producing Yah/Wah/Hoo
|
||||
#define SOUND_MARIO_YAH_WAH_HOO SOUND_ARG_LOAD(2, 4, 0x00, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_HOOHOO SOUND_ARG_LOAD(2, 4, 0x03, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_YAHOO SOUND_ARG_LOAD(2, 4, 0x04, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_UH SOUND_ARG_LOAD(2, 4, 0x05, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_HRMM SOUND_ARG_LOAD(2, 4, 0x06, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_WAH2 SOUND_ARG_LOAD(2, 4, 0x07, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_WHOA SOUND_ARG_LOAD(2, 4, 0x08, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_MARIO_EEUH SOUND_ARG_LOAD(2, 4, 0x09, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_ATTACKED SOUND_ARG_LOAD(2, 4, 0x0A, 0xFF, 8)
|
||||
/* not verified */ #define SOUND_MARIO_OOOF SOUND_ARG_LOAD(2, 4, 0x0B, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_OOOF2 SOUND_ARG_LOAD(2, 4, 0x0B, 0xD0, 8)
|
||||
#define SOUND_MARIO_HERE_WE_GO SOUND_ARG_LOAD(2, 4, 0x0C, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_YAWNING SOUND_ARG_LOAD(2, 4, 0x0D, 0x80, 8)
|
||||
#define SOUND_MARIO_SNORING1 SOUND_ARG_LOAD(2, 4, 0x0E, 0x80, 8)
|
||||
#define SOUND_MARIO_SNORING2 SOUND_ARG_LOAD(2, 4, 0x0F, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_WAAAOOOW SOUND_ARG_LOAD(2, 4, 0x10, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_MARIO_HAHA SOUND_ARG_LOAD(2, 4, 0x11, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_HAHA_2 SOUND_ARG_LOAD(2, 4, 0x11, 0xF0, 8)
|
||||
/* not verified */ #define SOUND_MARIO_UH2 SOUND_ARG_LOAD(2, 4, 0x13, 0xD0, 8)
|
||||
/* not verified */ #define SOUND_MARIO_UH2_2 SOUND_ARG_LOAD(2, 4, 0x13, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MARIO_ON_FIRE SOUND_ARG_LOAD(2, 4, 0x14, 0xA0, 8)
|
||||
/* not verified */ #define SOUND_MARIO_DYING SOUND_ARG_LOAD(2, 4, 0x15, 0xFF, 8)
|
||||
#define SOUND_MARIO_PANTING_COLD SOUND_ARG_LOAD(2, 4, 0x16, 0x80, 8)
|
||||
|
||||
// A random number 0-2 is added to the sound ID before playing
|
||||
#define SOUND_MARIO_PANTING SOUND_ARG_LOAD(2, 4, 0x18, 0x80, 8)
|
||||
|
||||
#define SOUND_MARIO_COUGHING1 SOUND_ARG_LOAD(2, 4, 0x1B, 0x80, 8)
|
||||
#define SOUND_MARIO_COUGHING2 SOUND_ARG_LOAD(2, 4, 0x1C, 0x80, 8)
|
||||
#define SOUND_MARIO_COUGHING3 SOUND_ARG_LOAD(2, 4, 0x1D, 0x80, 8)
|
||||
#define SOUND_MARIO_PUNCH_YAH SOUND_ARG_LOAD(2, 4, 0x1E, 0x80, 8)
|
||||
#define SOUND_MARIO_PUNCH_HOO SOUND_ARG_LOAD(2, 4, 0x1F, 0x80, 8)
|
||||
#define SOUND_MARIO_MAMA_MIA SOUND_ARG_LOAD(2, 4, 0x20, 0x80, 8)
|
||||
#define SOUND_MARIO_OKEY_DOKEY 0x2021
|
||||
#define SOUND_MARIO_GROUND_POUND_WAH SOUND_ARG_LOAD(2, 4, 0x22, 0x80, 8)
|
||||
#define SOUND_MARIO_DROWNING SOUND_ARG_LOAD(2, 4, 0x23, 0xF0, 8)
|
||||
#define SOUND_MARIO_PUNCH_WAH SOUND_ARG_LOAD(2, 4, 0x24, 0x80, 8)
|
||||
|
||||
/* Mario Sound Effects (US/EU only) */
|
||||
#define SOUND_PEACH_DEAR_MARIO SOUND_ARG_LOAD(2, 4, 0x28, 0xFF, 8)
|
||||
|
||||
// A random number 0-4 is added to the sound ID before playing, producing one of
|
||||
// Yahoo! (60% chance), Waha! (20%), or Yippee! (20%).
|
||||
#define SOUND_MARIO_YAHOO_WAHA_YIPPEE SOUND_ARG_LOAD(2, 4, 0x2B, 0x80, 8)
|
||||
|
||||
#define SOUND_MARIO_DOH SOUND_ARG_LOAD(2, 4, 0x30, 0x80, 8)
|
||||
#define SOUND_MARIO_GAME_OVER SOUND_ARG_LOAD(2, 4, 0x31, 0xFF, 8)
|
||||
#define SOUND_MARIO_HELLO SOUND_ARG_LOAD(2, 4, 0x32, 0xFF, 8)
|
||||
#define SOUND_MARIO_PRESS_START_TO_PLAY SOUND_ARG_LOAD(2, 4, 0x33, 0xFF, 0xA)
|
||||
#define SOUND_MARIO_TWIRL_BOUNCE SOUND_ARG_LOAD(2, 4, 0x34, 0x80, 8)
|
||||
#define SOUND_MARIO_SNORING3 SOUND_ARG_LOAD(2, 4, 0x35, 0xFF, 8)
|
||||
#define SOUND_MARIO_SO_LONGA_BOWSER SOUND_ARG_LOAD(2, 4, 0x36, 0x80, 8)
|
||||
#define SOUND_MARIO_IMA_TIRED SOUND_ARG_LOAD(2, 4, 0x37, 0x80, 8)
|
||||
|
||||
/* Princess Peach Sound Effects (US/EU only) */
|
||||
#define SOUND_PEACH_MARIO SOUND_ARG_LOAD(2, 4, 0x38, 0xFF, 8)
|
||||
#define SOUND_PEACH_POWER_OF_THE_STARS SOUND_ARG_LOAD(2, 4, 0x39, 0xFF, 8)
|
||||
#define SOUND_PEACH_THANKS_TO_YOU SOUND_ARG_LOAD(2, 4, 0x3A, 0xFF, 8)
|
||||
#define SOUND_PEACH_THANK_YOU_MARIO SOUND_ARG_LOAD(2, 4, 0x3B, 0xFF, 8)
|
||||
#define SOUND_PEACH_SOMETHING_SPECIAL SOUND_ARG_LOAD(2, 4, 0x3C, 0xFF, 8)
|
||||
#define SOUND_PEACH_BAKE_A_CAKE SOUND_ARG_LOAD(2, 4, 0x3D, 0xFF, 8)
|
||||
#define SOUND_PEACH_FOR_MARIO SOUND_ARG_LOAD(2, 4, 0x3E, 0xFF, 8)
|
||||
#define SOUND_PEACH_MARIO2 SOUND_ARG_LOAD(2, 4, 0x3F, 0xFF, 8)
|
||||
|
||||
/* General Sound Effects */
|
||||
#define SOUND_GENERAL_ACTIVATE_CAP_SWITCH SOUND_ARG_LOAD(3, 0, 0x00, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_FLAME_OUT SOUND_ARG_LOAD(3, 0, 0x03, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_OPEN_WOOD_DOOR SOUND_ARG_LOAD(3, 0, 0x04, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_CLOSE_WOOD_DOOR SOUND_ARG_LOAD(3, 0, 0x05, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_OPEN_IRON_DOOR SOUND_ARG_LOAD(3, 0, 0x06, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_CLOSE_IRON_DOOR SOUND_ARG_LOAD(3, 0, 0x07, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BUBBLES 0x3008
|
||||
/* not verified */ #define SOUND_GENERAL_MOVING_WATER SOUND_ARG_LOAD(3, 0, 0x09, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_SWISH_WATER SOUND_ARG_LOAD(3, 0, 0x0A, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_QUIET_BUBBLE SOUND_ARG_LOAD(3, 0, 0x0B, 0x00, 8)
|
||||
#define SOUND_GENERAL_VOLCANO_EXPLOSION SOUND_ARG_LOAD(3, 0, 0x0C, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_QUIET_BUBBLE2 SOUND_ARG_LOAD(3, 0, 0x0D, 0x00, 8)
|
||||
#define SOUND_GENERAL_CASTLE_TRAP_OPEN SOUND_ARG_LOAD(3, 0, 0x0E, 0x80, 8)
|
||||
#define SOUND_GENERAL_WALL_EXPLOSION SOUND_ARG_LOAD(3, 0, 0x0F, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_COIN SOUND_ARG_LOAD(3, 8, 0x11, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_COIN_WATER SOUND_ARG_LOAD(3, 8, 0x12, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_SHORT_STAR SOUND_ARG_LOAD(3, 0, 0x16, 0x00, 9)
|
||||
/* not verified */ #define SOUND_GENERAL_BIG_CLOCK SOUND_ARG_LOAD(3, 0, 0x17, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_LOUD_POUND 0x3018 // _TERRAIN?
|
||||
/* not verified */ #define SOUND_GENERAL_LOUD_POUND2 0x3019
|
||||
/* not verified */ #define SOUND_GENERAL_SHORT_POUND1 0x301A
|
||||
/* not verified */ #define SOUND_GENERAL_SHORT_POUND2 0x301B
|
||||
/* not verified */ #define SOUND_GENERAL_SHORT_POUND3 0x301C
|
||||
/* not verified */ #define SOUND_GENERAL_SHORT_POUND4 0x301D
|
||||
/* not verified */ #define SOUND_GENERAL_SHORT_POUND5 0x301E
|
||||
/* not verified */ #define SOUND_GENERAL_SHORT_POUND6 0x301F
|
||||
#define SOUND_GENERAL_OPEN_CHEST SOUND_ARG_LOAD(3, 1, 0x20, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_CLAM_SHELL1 SOUND_ARG_LOAD(3, 1, 0x22, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOX_LANDING SOUND_ARG_LOAD(3, 0, 0x24, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOX_LANDING_2 SOUND_ARG_LOAD(3, 2, 0x24, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNKNOWN1 SOUND_ARG_LOAD(3, 0, 0x25, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNKNOWN1_2 SOUND_ARG_LOAD(3, 2, 0x25, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_CLAM_SHELL2 SOUND_ARG_LOAD(3, 0, 0x26, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_CLAM_SHELL3 SOUND_ARG_LOAD(3, 0, 0x27, 0x40, 8)
|
||||
#ifdef VERSION_JP
|
||||
#define SOUND_GENERAL_PAINTING_EJECT SOUND_ARG_LOAD(3, 8, 0x28, 0x00, 8)
|
||||
#else
|
||||
#define SOUND_GENERAL_PAINTING_EJECT SOUND_ARG_LOAD(3, 9, 0x28, 0x00, 8)
|
||||
#endif
|
||||
#define SOUND_GENERAL_LEVEL_SELECT_CHANGE SOUND_ARG_LOAD(3, 0, 0x2B, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_PLATFORM SOUND_ARG_LOAD(3, 0, 0x2D, 0x80, 8)
|
||||
#define SOUND_GENERAL_DONUT_PLATFORM_EXPLOSION SOUND_ARG_LOAD(3, 0, 0x2E, 0x20, 8)
|
||||
#define SOUND_GENERAL_BOWSER_BOMB_EXPLOSION SOUND_ARG_LOAD(3, 1, 0x2F, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_COIN_SPURT SOUND_ARG_LOAD(3, 0, 0x30, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_COIN_SPURT_2 SOUND_ARG_LOAD(3, 8, 0x30, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_COIN_SPURT_EU SOUND_ARG_LOAD(3, 8, 0x30, 0x20, 8)
|
||||
|
||||
/* not verified */ #define SOUND_GENERAL_EXPLOSION6 0x3031
|
||||
/* not verified */ #define SOUND_GENERAL_UNK32 0x3032
|
||||
/* not verified */ #define SOUND_GENERAL_BOAT_TILT1 SOUND_ARG_LOAD(3, 0, 0x34, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOAT_TILT2 SOUND_ARG_LOAD(3, 0, 0x35, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_COIN_DROP SOUND_ARG_LOAD(3, 0, 0x36, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNKNOWN3_LOWPRIO SOUND_ARG_LOAD(3, 0, 0x37, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNKNOWN3 SOUND_ARG_LOAD(3, 0, 0x37, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNKNOWN3_2 SOUND_ARG_LOAD(3, 8, 0x37, 0x80, 8)
|
||||
#define SOUND_GENERAL_PENDULUM_SWING SOUND_ARG_LOAD(3, 0, 0x38, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_CHAIN_CHOMP1 SOUND_ARG_LOAD(3, 0, 0x39, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_CHAIN_CHOMP2 SOUND_ARG_LOAD(3, 0, 0x3A, 0x00, 8)
|
||||
#define SOUND_GENERAL_DOOR_TURN_KEY SOUND_ARG_LOAD(3, 0, 0x3B, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_MOVING_IN_SAND SOUND_ARG_LOAD(3, 0, 0x3C, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNKNOWN4_LOWPRIO SOUND_ARG_LOAD(3, 0, 0x3D, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNKNOWN4 SOUND_ARG_LOAD(3, 0, 0x3D, 0x80, 8)
|
||||
#define SOUND_GENERAL_MOVING_PLATFORM_SWITCH SOUND_ARG_LOAD(3, 0, 0x3E, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_CAGE_OPEN SOUND_ARG_LOAD(3, 0, 0x3F, 0xA0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_QUIET_POUND1_LOWPRIO SOUND_ARG_LOAD(3, 0, 0x40, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_QUIET_POUND1 SOUND_ARG_LOAD(3, 0, 0x40, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BREAK_BOX SOUND_ARG_LOAD(3, 0, 0x41, 0xC0, 8)
|
||||
#define SOUND_GENERAL_DOOR_INSERT_KEY SOUND_ARG_LOAD(3, 0, 0x42, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_QUIET_POUND2 SOUND_ARG_LOAD(3, 0, 0x43, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BIG_POUND SOUND_ARG_LOAD(3, 0, 0x44, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNK45 SOUND_ARG_LOAD(3, 0, 0x45, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNK46_LOWPRIO SOUND_ARG_LOAD(3, 0, 0x46, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_UNK46 SOUND_ARG_LOAD(3, 0, 0x46, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_CANNON_UP SOUND_ARG_LOAD(3, 0, 0x47, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_GRINDEL_ROLL SOUND_ARG_LOAD(3, 0, 0x48, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_EXPLOSION7 0x3049
|
||||
/* not verified */ #define SOUND_GENERAL_SHAKE_COFFIN 0x304A
|
||||
/* not verified */ #define SOUND_GENERAL_RACE_GUN_SHOT SOUND_ARG_LOAD(3, 1, 0x4D, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_STAR_DOOR_OPEN SOUND_ARG_LOAD(3, 0, 0x4E, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_STAR_DOOR_CLOSE SOUND_ARG_LOAD(3, 0, 0x4F, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_POUND_ROCK SOUND_ARG_LOAD(3, 0, 0x56, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_STAR_APPEARS SOUND_ARG_LOAD(3, 0, 0x57, 0xFF, 9)
|
||||
#define SOUND_GENERAL_COLLECT_1UP SOUND_ARG_LOAD(3, 0, 0x58, 0xFF, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BUTTON_PRESS_LOWPRIO SOUND_ARG_LOAD(3, 0, 0x5A, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BUTTON_PRESS SOUND_ARG_LOAD(3, 0, 0x5A, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BUTTON_PRESS_2_LOWPRIO SOUND_ARG_LOAD(3, 1, 0x5A, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BUTTON_PRESS_2 SOUND_ARG_LOAD(3, 1, 0x5A, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_ELEVATOR_MOVE SOUND_ARG_LOAD(3, 0, 0x5B, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_ELEVATOR_MOVE_2 SOUND_ARG_LOAD(3, 1, 0x5B, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_SWISH_AIR SOUND_ARG_LOAD(3, 0, 0x5C, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_SWISH_AIR_2 SOUND_ARG_LOAD(3, 1, 0x5C, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_HAUNTED_CHAIR SOUND_ARG_LOAD(3, 0, 0x5D, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_SOFT_LANDING SOUND_ARG_LOAD(3, 0, 0x5E, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_HAUNTED_CHAIR_MOVE SOUND_ARG_LOAD(3, 0, 0x5F, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOWSER_PLATFORM SOUND_ARG_LOAD(3, 0, 0x62, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOWSER_PLATFORM_2 SOUND_ARG_LOAD(3, 1, 0x62, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_HEART_SPIN SOUND_ARG_LOAD(3, 0, 0x64, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_POUND_WOOD_POST SOUND_ARG_LOAD(3, 0, 0x65, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_WATER_LEVEL_TRIG SOUND_ARG_LOAD(3, 0, 0x66, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_SWITCH_DOOR_OPEN SOUND_ARG_LOAD(3, 0, 0x67, 0xA0, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_RED_COIN SOUND_ARG_LOAD(3, 0, 0x68, 0x90, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BIRDS_FLY_AWAY SOUND_ARG_LOAD(3, 0, 0x69, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_METAL_POUND SOUND_ARG_LOAD(3, 0, 0x6B, 0x80, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOING1 SOUND_ARG_LOAD(3, 0, 0x6C, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOING2_LOWPRIO SOUND_ARG_LOAD(3, 0, 0x6D, 0x20, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOING2 SOUND_ARG_LOAD(3, 0, 0x6D, 0x40, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_YOSHI_WALK SOUND_ARG_LOAD(3, 0, 0x6E, 0x20, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_ENEMY_ALERT1 SOUND_ARG_LOAD(3, 0, 0x6F, 0x30, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_YOSHI_TALK SOUND_ARG_LOAD(3, 0, 0x70, 0x30, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_SPLATTERING SOUND_ARG_LOAD(3, 0, 0x71, 0x30, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOING3 0x3072
|
||||
/* not verified */ #define SOUND_GENERAL_GRAND_STAR SOUND_ARG_LOAD(3, 0, 0x73, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_GRAND_STAR_JUMP SOUND_ARG_LOAD(3, 0, 0x74, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_BOAT_ROCK SOUND_ARG_LOAD(3, 0, 0x75, 0x00, 8)
|
||||
/* not verified */ #define SOUND_GENERAL_VANISH_SFX SOUND_ARG_LOAD(3, 0, 0x76, 0x20, 8)
|
||||
|
||||
/* Environment Sound Effects */
|
||||
/* not verified */ #define SOUND_ENV_WATERFALL1 SOUND_ARG_LOAD(4, 0, 0x00, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_WATERFALL2 SOUND_ARG_LOAD(4, 0, 0x01, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_ELEVATOR1 SOUND_ARG_LOAD(4, 0, 0x02, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_DRONING1 SOUND_ARG_LOAD(4, 1, 0x03, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_DRONING2 SOUND_ARG_LOAD(4, 0, 0x04, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_WIND1 SOUND_ARG_LOAD(4, 0, 0x05, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_MOVING_SAND_SNOW 0x4006
|
||||
/* not verified */ #define SOUND_ENV_UNK07 0x4007
|
||||
/* not verified */ #define SOUND_ENV_ELEVATOR2 SOUND_ARG_LOAD(4, 0, 0x08, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_WATER SOUND_ARG_LOAD(4, 0, 0x09, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_UNKNOWN2 SOUND_ARG_LOAD(4, 0, 0x0A, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_BOAT_ROCKING1 SOUND_ARG_LOAD(4, 0, 0x0B, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_ELEVATOR3 SOUND_ARG_LOAD(4, 0, 0x0C, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_ELEVATOR4 SOUND_ARG_LOAD(4, 0, 0x0D, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_ELEVATOR4_2 SOUND_ARG_LOAD(4, 1, 0x0D, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_MOVINGSAND SOUND_ARG_LOAD(4, 0, 0x0E, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_MERRY_GO_ROUND_CREAKING SOUND_ARG_LOAD(4, 0, 0x0F, 0x40, 0)
|
||||
/* not verified */ #define SOUND_ENV_WIND2 SOUND_ARG_LOAD(4, 0, 0x10, 0x80, 0)
|
||||
/* not verified */ #define SOUND_ENV_UNK12 0x4012
|
||||
/* not verified */ #define SOUND_ENV_SLIDING SOUND_ARG_LOAD(4, 0, 0x13, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_STAR SOUND_ARG_LOAD(4, 0, 0x14, 0x00, 1)
|
||||
/* not verified */ #define SOUND_ENV_UNKNOWN4 SOUND_ARG_LOAD(4, 1, 0x15, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_WATER_DRAIN SOUND_ARG_LOAD(4, 1, 0x16, 0x00, 0)
|
||||
/* not verified */ #define SOUND_ENV_METAL_BOX_PUSH SOUND_ARG_LOAD(4, 0, 0x17, 0x80, 0)
|
||||
/* not verified */ #define SOUND_ENV_SINK_QUICKSAND SOUND_ARG_LOAD(4, 0, 0x18, 0x80, 0)
|
||||
|
||||
/* Object Sound Effects */
|
||||
#define SOUND_OBJ_SUSHI_SHARK_WATER_SOUND SOUND_ARG_LOAD(5, 0, 0x00, 0x80, 8)
|
||||
#define SOUND_OBJ_MRI_SHOOT SOUND_ARG_LOAD(5, 0, 0x01, 0x00, 8)
|
||||
#define SOUND_OBJ_BABY_PENGUIN_WALK SOUND_ARG_LOAD(5, 0, 0x02, 0x00, 8)
|
||||
#define SOUND_OBJ_BOWSER_WALK SOUND_ARG_LOAD(5, 0, 0x03, 0x00, 8)
|
||||
#define SOUND_OBJ_BOWSER_TAIL_PICKUP SOUND_ARG_LOAD(5, 0, 0x05, 0x00, 8)
|
||||
#define SOUND_OBJ_BOWSER_DEFEATED SOUND_ARG_LOAD(5, 0, 0x06, 0x00, 8)
|
||||
#define SOUND_OBJ_BOWSER_SPINNING SOUND_ARG_LOAD(5, 0, 0x07, 0x00, 8)
|
||||
#define SOUND_OBJ_BOWSER_INHALING SOUND_ARG_LOAD(5, 0, 0x08, 0x00, 8)
|
||||
#define SOUND_OBJ_BIG_PENGUIN_WALK SOUND_ARG_LOAD(5, 0, 0x09, 0x80, 8)
|
||||
#define SOUND_OBJ_BOO_BOUNCE_TOP SOUND_ARG_LOAD(5, 0, 0x0A, 0x00, 8)
|
||||
#define SOUND_OBJ_BOO_LAUGH_SHORT SOUND_ARG_LOAD(5, 0, 0x0B, 0x00, 8)
|
||||
#define SOUND_OBJ_THWOMP SOUND_ARG_LOAD(5, 0, 0x0C, 0xA0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_CANNON1 SOUND_ARG_LOAD(5, 0, 0x0D, 0xF0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_CANNON2 SOUND_ARG_LOAD(5, 0, 0x0E, 0xF0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_CANNON3 SOUND_ARG_LOAD(5, 0, 0x0F, 0xF0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_JUMP_WALK_WATER 0x5012
|
||||
/* not verified */ #define SOUND_OBJ_UNKNOWN2 SOUND_ARG_LOAD(5, 0, 0x13, 0x00, 8)
|
||||
#define SOUND_OBJ_MRI_DEATH SOUND_ARG_LOAD(5, 0, 0x14, 0x00, 8)
|
||||
/* not verified */ #define SOUND_OBJ_POUNDING1 SOUND_ARG_LOAD(5, 0, 0x15, 0x50, 8)
|
||||
/* not verified */ #define SOUND_OBJ_POUNDING1_HIGHPRIO SOUND_ARG_LOAD(5, 0, 0x15, 0x80, 8)
|
||||
#define SOUND_OBJ_WHOMP_LOWPRIO SOUND_ARG_LOAD(5, 0, 0x16, 0x60, 8)
|
||||
#define SOUND_OBJ_KING_BOBOMB SOUND_ARG_LOAD(5, 0, 0x16, 0x80, 8)
|
||||
/* not verified */ #define SOUND_OBJ_BULLY_METAL SOUND_ARG_LOAD(5, 0, 0x17, 0x80, 8)
|
||||
/* not verified */ #define SOUND_OBJ_BULLY_EXPLODE SOUND_ARG_LOAD(5, 0, 0x18, 0xA0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_BULLY_EXPLODE_2 SOUND_ARG_LOAD(5, 1, 0x18, 0xA0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_POUNDING_CANNON SOUND_ARG_LOAD(5, 0, 0x1A, 0x50, 8)
|
||||
/* not verified */ #define SOUND_OBJ_BULLY_WALK SOUND_ARG_LOAD(5, 0, 0x1B, 0x30, 8)
|
||||
/* not verified */ #define SOUND_OBJ_UNKNOWN3 SOUND_ARG_LOAD(5, 0, 0x1D, 0x80, 8)
|
||||
/* not verified */ #define SOUND_OBJ_UNKNOWN4 SOUND_ARG_LOAD(5, 0, 0x1E, 0xA0, 8)
|
||||
#define SOUND_OBJ_BABY_PENGUIN_DIVE SOUND_ARG_LOAD(5, 0, 0x1F, 0x40, 8)
|
||||
#define SOUND_OBJ_GOOMBA_WALK SOUND_ARG_LOAD(5, 0, 0x20, 0x00, 8)
|
||||
#define SOUND_OBJ_UKIKI_CHATTER_LONG SOUND_ARG_LOAD(5, 0, 0x21, 0x00, 8)
|
||||
#define SOUND_OBJ_MONTY_MOLE_ATTACK SOUND_ARG_LOAD(5, 0, 0x22, 0x00, 8)
|
||||
#define SOUND_OBJ_EVIL_LAKITU_THROW SOUND_ARG_LOAD(5, 0, 0x22, 0x20, 8)
|
||||
/* not verified */ #define SOUND_OBJ_UNK23 0x5023
|
||||
#define SOUND_OBJ_DYING_ENEMY1 SOUND_ARG_LOAD(5, 0, 0x24, 0x40, 8)
|
||||
/* not verified */ #define SOUND_OBJ_CANNON4 SOUND_ARG_LOAD(5, 0, 0x25, 0x40, 8)
|
||||
/* not verified */ #define SOUND_OBJ_DYING_ENEMY2 0x5026
|
||||
#define SOUND_OBJ_BOBOMB_WALK SOUND_ARG_LOAD(5, 0, 0x27, 0x00, 8)
|
||||
/* not verified */ #define SOUND_OBJ_SOMETHING_LANDING SOUND_ARG_LOAD(5, 0, 0x28, 0x80, 8)
|
||||
/* not verified */ #define SOUND_OBJ_DIVING_IN_WATER SOUND_ARG_LOAD(5, 0, 0x29, 0xA0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_SNOW_SAND1 SOUND_ARG_LOAD(5, 0, 0x2A, 0x00, 8)
|
||||
/* not verified */ #define SOUND_OBJ_SNOW_SAND2 SOUND_ARG_LOAD(5, 0, 0x2B, 0x00, 8)
|
||||
#define SOUND_OBJ_DEFAULT_DEATH SOUND_ARG_LOAD(5, 0, 0x2C, 0x80, 8)
|
||||
#define SOUND_OBJ_BIG_PENGUIN_YELL SOUND_ARG_LOAD(5, 0, 0x2D, 0x00, 8)
|
||||
#define SOUND_OBJ_WATER_BOMB_BOUNCING SOUND_ARG_LOAD(5, 0, 0x2E, 0x80, 8)
|
||||
#define SOUND_OBJ_GOOMBA_ALERT SOUND_ARG_LOAD(5, 0, 0x2F, 0x00, 8)
|
||||
#define SOUND_OBJ_WIGGLER_JUMP SOUND_ARG_LOAD(5, 0, 0x2F, 0x60, 8)
|
||||
/* not verified */ #define SOUND_OBJ_STOMPED SOUND_ARG_LOAD(5, 0, 0x30, 0x80, 8)
|
||||
/* not verified */ #define SOUND_OBJ_UNKNOWN6 SOUND_ARG_LOAD(5, 0, 0x31, 0x00, 8)
|
||||
/* not verified */ #define SOUND_OBJ_DIVING_INTO_WATER SOUND_ARG_LOAD(5, 0, 0x32, 0x40, 8)
|
||||
#define SOUND_OBJ_PIRANHA_PLANT_SHRINK SOUND_ARG_LOAD(5, 0, 0x33, 0x40, 8)
|
||||
#define SOUND_OBJ_KOOPA_THE_QUICK_WALK SOUND_ARG_LOAD(5, 0, 0x34, 0x20, 8)
|
||||
#define SOUND_OBJ_KOOPA_WALK SOUND_ARG_LOAD(5, 0, 0x35, 0x00, 8)
|
||||
#define SOUND_OBJ_BULLY_WALKING SOUND_ARG_LOAD(5, 0, 0x36, 0x60, 8)
|
||||
#define SOUND_OBJ_DORRIE SOUND_ARG_LOAD(5, 0, 0x37, 0x60, 8)
|
||||
#define SOUND_OBJ_BOWSER_LAUGH SOUND_ARG_LOAD(5, 0, 0x38, 0x80, 8)
|
||||
#define SOUND_OBJ_UKIKI_CHATTER_SHORT SOUND_ARG_LOAD(5, 0, 0x39, 0x00, 8)
|
||||
#define SOUND_OBJ_UKIKI_CHATTER_IDLE SOUND_ARG_LOAD(5, 0, 0x3A, 0x00, 8)
|
||||
#define SOUND_OBJ_UKIKI_STEP_DEFAULT SOUND_ARG_LOAD(5, 0, 0x3B, 0x00, 8)
|
||||
#define SOUND_OBJ_UKIKI_STEP_LEAVES SOUND_ARG_LOAD(5, 0, 0x3C, 0x00, 8)
|
||||
#define SOUND_OBJ_KOOPA_TALK SOUND_ARG_LOAD(5, 0, 0x3D, 0xA0, 8)
|
||||
#define SOUND_OBJ_KOOPA_DAMAGE SOUND_ARG_LOAD(5, 0, 0x3E, 0xA0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_KLEPTO1 SOUND_ARG_LOAD(5, 0, 0x3F, 0x40, 8)
|
||||
/* not verified */ #define SOUND_OBJ_KLEPTO2 SOUND_ARG_LOAD(5, 0, 0x40, 0x60, 8)
|
||||
#define SOUND_OBJ_KING_BOBOMB_TALK SOUND_ARG_LOAD(5, 0, 0x41, 0x00, 8)
|
||||
#define SOUND_OBJ_KING_BOBOMB_JUMP SOUND_ARG_LOAD(5, 0, 0x46, 0x80, 8)
|
||||
#define SOUND_OBJ_KING_WHOMP_DEATH SOUND_ARG_LOAD(5, 1, 0x47, 0xC0, 8)
|
||||
#define SOUND_OBJ_BOO_LAUGH_LONG SOUND_ARG_LOAD(5, 0, 0x48, 0x00, 8)
|
||||
/* not verified */ #define SOUND_OBJ_EEL SOUND_ARG_LOAD(5, 0, 0x4A, 0x00, 8)
|
||||
/* not verified */ #define SOUND_OBJ_EEL_2 SOUND_ARG_LOAD(5, 2, 0x4A, 0x00, 8)
|
||||
#define SOUND_OBJ_EYEROK_SHOW_EYE SOUND_ARG_LOAD(5, 2, 0x4B, 0x00, 8)
|
||||
#define SOUND_OBJ_MR_BLIZZARD_ALERT SOUND_ARG_LOAD(5, 0, 0x4C, 0x00, 8)
|
||||
#define SOUND_OBJ_SNUFIT_SHOOT SOUND_ARG_LOAD(5, 0, 0x4D, 0x00, 8)
|
||||
#define SOUND_OBJ_SKEETER_WALK SOUND_ARG_LOAD(5, 0, 0x4E, 0x00, 8)
|
||||
/* not verified */ #define SOUND_OBJ_WALKING_WATER SOUND_ARG_LOAD(5, 0, 0x4F, 0x00, 8)
|
||||
#define SOUND_OBJ_BIRD_CHIRP3 SOUND_ARG_LOAD(5, 0, 0x51, 0x40, 0)
|
||||
#define SOUND_OBJ_PIRANHA_PLANT_APPEAR SOUND_ARG_LOAD(5, 0, 0x54, 0x20, 8)
|
||||
#define SOUND_OBJ_FLAME_BLOWN SOUND_ARG_LOAD(5, 0, 0x55, 0x80, 8)
|
||||
#define SOUND_OBJ_MAD_PIANO_CHOMPING SOUND_ARG_LOAD(5, 2, 0x56, 0x40, 8)
|
||||
#define SOUND_OBJ_BOBOMB_BUDDY_TALK SOUND_ARG_LOAD(5, 0, 0x58, 0x40, 8)
|
||||
/* not verified */ #define SOUND_OBJ_SPINY_UNK59 SOUND_ARG_LOAD(5, 0, 0x59, 0x10, 8)
|
||||
#define SOUND_OBJ_WIGGLER_HIGH_PITCH SOUND_ARG_LOAD(5, 0, 0x5C, 0x40, 8)
|
||||
#define SOUND_OBJ_HEAVEHO_TOSSED SOUND_ARG_LOAD(5, 0, 0x5D, 0x40, 8)
|
||||
/* not verified */ #define SOUND_OBJ_WIGGLER_DEATH 0x505E
|
||||
#define SOUND_OBJ_BOWSER_INTRO_LAUGH SOUND_ARG_LOAD(5, 0, 0x5F, 0x80, 9)
|
||||
/* not verified */ #define SOUND_OBJ_ENEMY_DEATH_HIGH SOUND_ARG_LOAD(5, 0, 0x60, 0xB0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_ENEMY_DEATH_LOW SOUND_ARG_LOAD(5, 0, 0x61, 0xB0, 8)
|
||||
#define SOUND_OBJ_SWOOP_DEATH SOUND_ARG_LOAD(5, 0, 0x62, 0xB0, 8)
|
||||
#define SOUND_OBJ_KOOPA_FLYGUY_DEATH SOUND_ARG_LOAD(5, 0, 0x63, 0xB0, 8)
|
||||
#define SOUND_OBJ_POKEY_DEATH SOUND_ARG_LOAD(5, 0, 0x63, 0xC0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_SNOWMAN_BOUNCE SOUND_ARG_LOAD(5, 0, 0x64, 0xC0, 8)
|
||||
#define SOUND_OBJ_SNOWMAN_EXPLODE SOUND_ARG_LOAD(5, 0, 0x65, 0xD0, 8)
|
||||
/* not verified */ #define SOUND_OBJ_POUNDING_LOUD SOUND_ARG_LOAD(5, 0, 0x68, 0x40, 8)
|
||||
/* not verified */ #define SOUND_OBJ_MIPS_RABBIT SOUND_ARG_LOAD(5, 0, 0x6A, 0x00, 8)
|
||||
/* not verified */ #define SOUND_OBJ_MIPS_RABBIT_WATER SOUND_ARG_LOAD(5, 0, 0x6C, 0x00, 8)
|
||||
#define SOUND_OBJ_EYEROK_EXPLODE SOUND_ARG_LOAD(5, 0, 0x6D, 0x00, 8)
|
||||
#define SOUND_OBJ_CHUCKYA_DEATH SOUND_ARG_LOAD(5, 1, 0x6E, 0x00, 8)
|
||||
#define SOUND_OBJ_WIGGLER_TALK SOUND_ARG_LOAD(5, 0, 0x6F, 0x00, 8)
|
||||
#define SOUND_OBJ_WIGGLER_ATTACKED SOUND_ARG_LOAD(5, 0, 0x70, 0x60, 8)
|
||||
#define SOUND_OBJ_WIGGLER_LOW_PITCH SOUND_ARG_LOAD(5, 0, 0x71, 0x20, 8)
|
||||
#define SOUND_OBJ_SNUFIT_SKEETER_DEATH SOUND_ARG_LOAD(5, 0, 0x72, 0xC0, 8)
|
||||
#define SOUND_OBJ_BUBBA_CHOMP SOUND_ARG_LOAD(5, 0, 0x73, 0x40, 8)
|
||||
#define SOUND_OBJ_ENEMY_DEFEAT_SHRINK SOUND_ARG_LOAD(5, 0, 0x74, 0x40, 8)
|
||||
|
||||
#define SOUND_AIR_BOWSER_SPIT_FIRE SOUND_ARG_LOAD(6, 0, 0x00, 0x00, 0)
|
||||
#define SOUND_AIR_UNK01 0x6001 // ?
|
||||
#define SOUND_AIR_LAKITU_FLY SOUND_ARG_LOAD(6, 0, 0x02, 0x80, 0)
|
||||
#define SOUND_AIR_LAKITU_FLY_HIGHPRIO SOUND_ARG_LOAD(6, 0, 0x02, 0xFF, 0)
|
||||
#define SOUND_AIR_AMP_BUZZ SOUND_ARG_LOAD(6, 0, 0x03, 0x40, 0)
|
||||
#define SOUND_AIR_BLOW_FIRE SOUND_ARG_LOAD(6, 0, 0x04, 0x80, 0)
|
||||
#define SOUND_AIR_BLOW_WIND SOUND_ARG_LOAD(6, 0, 0x04, 0x40, 0)
|
||||
#define SOUND_AIR_ROUGH_SLIDE SOUND_ARG_LOAD(6, 0, 0x05, 0x00, 0)
|
||||
#define SOUND_AIR_HEAVEHO_MOVE SOUND_ARG_LOAD(6, 0, 0x06, 0x40, 0)
|
||||
#define SOUND_AIR_UNK07 0x6007 // ?
|
||||
#define SOUND_AIR_BOBOMB_LIT_FUSE SOUND_ARG_LOAD(6, 0, 0x08, 0x60, 0)
|
||||
#define SOUND_AIR_HOWLING_WIND SOUND_ARG_LOAD(6, 0, 0x09, 0x80, 0)
|
||||
#define SOUND_AIR_CHUCKYA_MOVE SOUND_ARG_LOAD(6, 0, 0x0A, 0x40, 0)
|
||||
#define SOUND_AIR_PEACH_TWINKLE SOUND_ARG_LOAD(6, 0, 0x0B, 0x40, 0)
|
||||
#define SOUND_AIR_CASTLE_OUTDOORS_AMBIENT SOUND_ARG_LOAD(6, 0, 0x10, 0x40, 0)
|
||||
|
||||
/* Menu Sound Effects */
|
||||
#define SOUND_MENU_CHANGE_SELECT SOUND_ARG_LOAD(7, 0, 0x00, 0xF8, 8)
|
||||
/* not verified */ #define SOUND_MENU_REVERSE_PAUSE 0x7001
|
||||
#define SOUND_MENU_PAUSE SOUND_ARG_LOAD(7, 0, 0x02, 0xF0, 8)
|
||||
#define SOUND_MENU_PAUSE_HIGHPRIO SOUND_ARG_LOAD(7, 0, 0x02, 0xFF, 8)
|
||||
#define SOUND_MENU_PAUSE_2 SOUND_ARG_LOAD(7, 0, 0x03, 0xFF, 8)
|
||||
#define SOUND_MENU_MESSAGE_APPEAR SOUND_ARG_LOAD(7, 0, 0x04, 0x00, 8)
|
||||
#define SOUND_MENU_MESSAGE_DISAPPEAR SOUND_ARG_LOAD(7, 0, 0x05, 0x00, 8)
|
||||
#define SOUND_MENU_CAMERA_ZOOM_IN SOUND_ARG_LOAD(7, 0, 0x06, 0x00, 8)
|
||||
#define SOUND_MENU_CAMERA_ZOOM_OUT SOUND_ARG_LOAD(7, 0, 0x07, 0x00, 8)
|
||||
#define SOUND_MENU_PINCH_MARIO_FACE SOUND_ARG_LOAD(7, 0, 0x08, 0x00, 8)
|
||||
#define SOUND_MENU_LET_GO_MARIO_FACE SOUND_ARG_LOAD(7, 0, 0x09, 0x00, 8)
|
||||
#define SOUND_MENU_HAND_APPEAR SOUND_ARG_LOAD(7, 0, 0x0A, 0x00, 8)
|
||||
#define SOUND_MENU_HAND_DISAPPEAR SOUND_ARG_LOAD(7, 0, 0x0B, 0x00, 8)
|
||||
/* not verified */ #define SOUND_MENU_UNK0C SOUND_ARG_LOAD(7, 0, 0x0C, 0x00, 8)
|
||||
/* not verified */ #define SOUND_MENU_POWER_METER SOUND_ARG_LOAD(7, 0, 0x0D, 0x00, 8)
|
||||
#define SOUND_MENU_CAMERA_BUZZ SOUND_ARG_LOAD(7, 0, 0x0E, 0x00, 8)
|
||||
#define SOUND_MENU_CAMERA_TURN SOUND_ARG_LOAD(7, 0, 0x0F, 0x00, 8)
|
||||
/* not verified */ #define SOUND_MENU_UNK10 0x7010
|
||||
#define SOUND_MENU_CLICK_FILE_SELECT SOUND_ARG_LOAD(7, 0, 0x11, 0x00, 8)
|
||||
/* not verified */ #define SOUND_MENU_MESSAGE_NEXT_PAGE SOUND_ARG_LOAD(7, 0, 0x13, 0x00, 8)
|
||||
#define SOUND_MENU_COIN_ITS_A_ME_MARIO SOUND_ARG_LOAD(7, 0, 0x14, 0x00, 8)
|
||||
#define SOUND_MENU_YOSHI_GAIN_LIVES SOUND_ARG_LOAD(7, 0, 0x15, 0x00, 8)
|
||||
#define SOUND_MENU_ENTER_PIPE SOUND_ARG_LOAD(7, 0, 0x16, 0xA0, 8)
|
||||
#define SOUND_MENU_EXIT_PIPE SOUND_ARG_LOAD(7, 0, 0x17, 0xA0, 8)
|
||||
#define SOUND_MENU_BOWSER_LAUGH SOUND_ARG_LOAD(7, 0, 0x18, 0x80, 8)
|
||||
#define SOUND_MENU_ENTER_HOLE SOUND_ARG_LOAD(7, 1, 0x19, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MENU_CLICK_CHANGE_VIEW SOUND_ARG_LOAD(7, 0, 0x1A, 0x80, 8)
|
||||
/* not verified */ #define SOUND_MENU_CAMERA_UNUSED1 0x701B
|
||||
/* not verified */ #define SOUND_MENU_CAMERA_UNUSED2 0x701C
|
||||
/* not verified */ #define SOUND_MENU_MARIO_CASTLE_WARP SOUND_ARG_LOAD(7, 0, 0x1D, 0xB0, 8)
|
||||
#define SOUND_MENU_STAR_SOUND SOUND_ARG_LOAD(7, 0, 0x1E, 0xFF, 8)
|
||||
#define SOUND_MENU_THANK_YOU_PLAYING_MY_GAME SOUND_ARG_LOAD(7, 0, 0x1F, 0xFF, 8)
|
||||
/* not verified */ #define SOUND_MENU_READ_A_SIGN 0x7020
|
||||
/* not verified */ #define SOUND_MENU_EXIT_A_SIGN 0x7021
|
||||
/* not verified */ #define SOUND_MENU_MARIO_CASTLE_WARP2 SOUND_ARG_LOAD(7, 0, 0x22, 0x20, 8)
|
||||
#define SOUND_MENU_STAR_SOUND_OKEY_DOKEY SOUND_ARG_LOAD(7, 0, 0x23, 0xFF, 8)
|
||||
#define SOUND_MENU_STAR_SOUND_LETS_A_GO SOUND_ARG_LOAD(7, 0, 0x24, 0xFF, 8)
|
||||
|
||||
// US/EU only; an index between 0-7 or 0-4 is added to the sound ID before
|
||||
// playing, producing the same sound with different pitch.
|
||||
#define SOUND_MENU_COLLECT_RED_COIN SOUND_ARG_LOAD(7, 8, 0x28, 0x90, 8)
|
||||
#define SOUND_MENU_COLLECT_SECRET SOUND_ARG_LOAD(7, 0, 0x30, 0x20, 8)
|
||||
|
||||
// Channel 8 loads sounds from the same place as channel 3, making it possible
|
||||
// to play two channel 3 sounds at once (since just one sound from each channel
|
||||
// can play at a given time).
|
||||
#define SOUND_GENERAL2_BOBOMB_EXPLOSION SOUND_ARG_LOAD(8, 0, 0x2E, 0x20, 8)
|
||||
#define SOUND_GENERAL2_PURPLE_SWITCH SOUND_ARG_LOAD(8, 0, 0x3E, 0xC0, 8)
|
||||
#define SOUND_GENERAL2_ROTATING_BLOCK_CLICK SOUND_ARG_LOAD(8, 0, 0x40, 0x00, 8)
|
||||
#define SOUND_GENERAL2_SPINDEL_ROLL SOUND_ARG_LOAD(8, 0, 0x48, 0x20, 8)
|
||||
#define SOUND_GENERAL2_PYRAMID_TOP_SPIN SOUND_ARG_LOAD(8, 1, 0x4B, 0xE0, 8)
|
||||
#define SOUND_GENERAL2_PYRAMID_TOP_EXPLOSION SOUND_ARG_LOAD(8, 1, 0x4C, 0xF0, 8)
|
||||
#define SOUND_GENERAL2_BIRD_CHIRP2 SOUND_ARG_LOAD(8, 0, 0x50, 0x40, 0)
|
||||
#define SOUND_GENERAL2_SWITCH_TICK_FAST SOUND_ARG_LOAD(8, 0, 0x54, 0xF0, 1)
|
||||
#define SOUND_GENERAL2_SWITCH_TICK_SLOW SOUND_ARG_LOAD(8, 0, 0x55, 0xF0, 1)
|
||||
#define SOUND_GENERAL2_STAR_APPEARS SOUND_ARG_LOAD(8, 0, 0x57, 0xFF, 9)
|
||||
#define SOUND_GENERAL2_ROTATING_BLOCK_ALERT SOUND_ARG_LOAD(8, 0, 0x59, 0x00, 8)
|
||||
#define SOUND_GENERAL2_BOWSER_EXPLODE SOUND_ARG_LOAD(8, 0, 0x60, 0x00, 8)
|
||||
#define SOUND_GENERAL2_BOWSER_KEY SOUND_ARG_LOAD(8, 0, 0x61, 0x00, 8)
|
||||
#define SOUND_GENERAL2_1UP_APPEAR SOUND_ARG_LOAD(8, 0, 0x63, 0xD0, 8)
|
||||
#define SOUND_GENERAL2_RIGHT_ANSWER SOUND_ARG_LOAD(8, 0, 0x6A, 0xA0, 8)
|
||||
|
||||
// Channel 9 loads sounds from the same place as channel 5.
|
||||
#define SOUND_OBJ2_BOWSER_ROAR SOUND_ARG_LOAD(9, 0, 0x04, 0x00, 8)
|
||||
#define SOUND_OBJ2_PIRANHA_PLANT_BITE SOUND_ARG_LOAD(9, 0, 0x10, 0x50, 8)
|
||||
#define SOUND_OBJ2_PIRANHA_PLANT_DYING SOUND_ARG_LOAD(9, 0, 0x11, 0x60, 8)
|
||||
#define SOUND_OBJ2_BOWSER_PUZZLE_PIECE_MOVE SOUND_ARG_LOAD(9, 0, 0x19, 0x20, 8)
|
||||
#define SOUND_OBJ2_BULLY_ATTACKED SOUND_ARG_LOAD(9, 0, 0x1C, 0x00, 8)
|
||||
#define SOUND_OBJ2_KING_BOBOMB_DAMAGE SOUND_ARG_LOAD(9, 1, 0x42, 0x40, 8)
|
||||
#define SOUND_OBJ2_SCUTTLEBUG_WALK SOUND_ARG_LOAD(9, 0, 0x43, 0x40, 8)
|
||||
#define SOUND_OBJ2_SCUTTLEBUG_ALERT SOUND_ARG_LOAD(9, 0, 0x44, 0x40, 8)
|
||||
#define SOUND_OBJ2_BABY_PENGUIN_YELL SOUND_ARG_LOAD(9, 0, 0x45, 0x00, 8)
|
||||
#define SOUND_OBJ2_SWOOP SOUND_ARG_LOAD(9, 0, 0x49, 0x00, 8)
|
||||
#define SOUND_OBJ2_BIRD_CHIRP1 SOUND_ARG_LOAD(9, 0, 0x52, 0x40, 0)
|
||||
#define SOUND_OBJ2_LARGE_BULLY_ATTACKED SOUND_ARG_LOAD(9, 0, 0x57, 0x00, 8)
|
||||
#define SOUND_OBJ2_EYEROK_SOUND_SHORT SOUND_ARG_LOAD(9, 3, 0x5A, 0x00, 8)
|
||||
#define SOUND_OBJ2_WHOMP_SOUND_SHORT SOUND_ARG_LOAD(9, 3, 0x5A, 0xC0, 8)
|
||||
#define SOUND_OBJ2_EYEROK_SOUND_LONG SOUND_ARG_LOAD(9, 2, 0x5B, 0x00, 8)
|
||||
#define SOUND_OBJ2_BOWSER_TELEPORT SOUND_ARG_LOAD(9, 0, 0x66, 0x80, 8)
|
||||
#define SOUND_OBJ2_MONTY_MOLE_APPEAR SOUND_ARG_LOAD(9, 0, 0x67, 0x80, 8)
|
||||
#define SOUND_OBJ2_BOSS_DIALOG_GRUNT SOUND_ARG_LOAD(9, 0, 0x69, 0x40, 8)
|
||||
#define SOUND_OBJ2_MRI_SPINNING SOUND_ARG_LOAD(9, 0, 0x6B, 0x00, 8)
|
||||
|
||||
#endif // AUDIO_DEFINES_H
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef COMMAND_MACROS_BASE_H
|
||||
#define COMMAND_MACROS_BASE_H
|
||||
|
||||
#include "PR/gbi.h"
|
||||
|
||||
#if IS_BIG_ENDIAN
|
||||
#if IS_64_BIT
|
||||
#define CMD_BBBB(a, b, c, d) ((uintptr_t)(_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 8, 8) | _SHIFTL(d, 0, 8)) << 32)
|
||||
#define CMD_BBH(a, b, c) ((uintptr_t)(_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 0, 16)) << 32)
|
||||
#define CMD_HH(a, b) ((uintptr_t)(_SHIFTL(a, 16, 16) | _SHIFTL(b, 0, 16)) << 32)
|
||||
#define CMD_W(a) ((uintptr_t)(a) << 32)
|
||||
#else
|
||||
#define CMD_BBBB(a, b, c, d) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 8, 8) | _SHIFTL(d, 0, 8))
|
||||
#define CMD_BBH(a, b, c) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 0, 16))
|
||||
#define CMD_HH(a, b) (_SHIFTL(a, 16, 16) | _SHIFTL(b, 0, 16))
|
||||
#define CMD_W(a) (a)
|
||||
#endif
|
||||
#else
|
||||
#define CMD_BBBB(a, b, c, d) (_SHIFTL(a, 0, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 16, 8) | _SHIFTL(d, 24, 8))
|
||||
#define CMD_BBH(a, b, c) (_SHIFTL(a, 0, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 16, 16))
|
||||
#define CMD_HH(a, b) (_SHIFTL(a, 0, 16) | _SHIFTL(b, 16, 16))
|
||||
#define CMD_W(a) (a)
|
||||
#endif
|
||||
#define CMD_PTR(a) ((uintptr_t)(a))
|
||||
|
||||
#define CMD_HHHHHH(a, b, c, d, e, f) CMD_HH(a, b), CMD_HH(c, d), CMD_HH(e, f)
|
||||
|
||||
#endif // COMMAND_MACROS_BASE_H
|
||||
@@ -0,0 +1,432 @@
|
||||
#ifndef GEO_COMMANDS_H
|
||||
#define GEO_COMMANDS_H
|
||||
|
||||
#include "command_macros_base.h"
|
||||
|
||||
//#include "game/shadow.h"
|
||||
//#include "game/object_helpers.h"
|
||||
//#include "game/behavior_actions.h"
|
||||
//#include "game/segment2.h"
|
||||
#include "../game/mario_misc.h"
|
||||
#include "../game/mario_actions_cutscene.h"
|
||||
|
||||
// sky background params
|
||||
#define BACKGROUND_OCEAN_SKY 0
|
||||
#define BACKGROUND_FLAMING_SKY 1
|
||||
#define BACKGROUND_UNDERWATER_CITY 2
|
||||
#define BACKGROUND_BELOW_CLOUDS 3
|
||||
#define BACKGROUND_SNOW_MOUNTAINS 4
|
||||
#define BACKGROUND_DESERT 5
|
||||
#define BACKGROUND_HAUNTED 6
|
||||
#define BACKGROUND_GREEN_SKY 7
|
||||
#define BACKGROUND_ABOVE_CLOUDS 8
|
||||
#define BACKGROUND_PURPLE_SKY 9
|
||||
|
||||
// geo layout macros
|
||||
|
||||
/**
|
||||
* 0x00: Branch and store return address
|
||||
* 0x04: scriptTarget, segment address of geo layout
|
||||
*/
|
||||
#define GEO_BRANCH_AND_LINK(scriptTarget) \
|
||||
CMD_BBH(0x00, 0x00, 0x0000), \
|
||||
CMD_PTR(scriptTarget)
|
||||
|
||||
/**
|
||||
* 0x01: Terminate geo layout
|
||||
* 0x01-0x03: unused
|
||||
*/
|
||||
#define GEO_END() \
|
||||
CMD_BBH(0x01, 0x00, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x02: Branch
|
||||
* 0x01: if 1, store next geo layout address on stack
|
||||
* 0x02-0x03: unused
|
||||
* 0x04: scriptTarget, segment address of geo layout
|
||||
*/
|
||||
#define GEO_BRANCH(type, scriptTarget) \
|
||||
CMD_BBH(0x02, type, 0x0000), \
|
||||
CMD_PTR(scriptTarget)
|
||||
|
||||
/**
|
||||
* 0x03: Return from branch
|
||||
* 0x01-0x03: unused
|
||||
*/
|
||||
#define GEO_RETURN() \
|
||||
CMD_BBH(0x03, 0x00, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x04: Open node
|
||||
* 0x01-0x03: unused
|
||||
*/
|
||||
#define GEO_OPEN_NODE() \
|
||||
CMD_BBH(0x04, 0x00, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x05: Close node
|
||||
* 0x01-0x03: unused
|
||||
*/
|
||||
#define GEO_CLOSE_NODE() \
|
||||
CMD_BBH(0x05, 0x00, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x06: Register the current node at the given index in the gGeoViews array
|
||||
* 0x01: unused
|
||||
* 0x02: s16 index
|
||||
*/
|
||||
#define GEO_ASSIGN_AS_VIEW(index) \
|
||||
CMD_BBH(0x06, 0x00, index)
|
||||
|
||||
/**
|
||||
* 0x07: Update current scene graph node flags
|
||||
* 0x01: u8 operation (0 = reset, 1 = set, 2 = clear)
|
||||
* 0x02: s16 bits
|
||||
*/
|
||||
#define GEO_UPDATE_NODE_FLAGS(operation, flagBits) \
|
||||
CMD_BBH(0x07, operation, flagBits)
|
||||
|
||||
/**
|
||||
* 0x08: Create screen area scene graph node
|
||||
* 0x01: unused
|
||||
* 0x02: s16 num entries (+2) to allocate
|
||||
* 0x04: s16 x
|
||||
* 0x06: s16 y
|
||||
* 0x08: s16 width
|
||||
* 0x0A: s16 height
|
||||
*/
|
||||
#define GEO_NODE_SCREEN_AREA(numEntries, x, y, width, height) \
|
||||
CMD_BBH(0x08, 0x00, numEntries), \
|
||||
CMD_HH(x, y), \
|
||||
CMD_HH(width, height)
|
||||
|
||||
/**
|
||||
* 0x09: Create orthographic projection scene graph node
|
||||
* 0x02: s16 scale as percentage
|
||||
*/
|
||||
#define GEO_NODE_ORTHO(scale) \
|
||||
CMD_BBH(0x09, 0x00, scale)
|
||||
|
||||
/**
|
||||
* 0x0A: Create camera frustum scene graph node
|
||||
* 0x01: u8 if nonzero, enable function field
|
||||
* 0x02: s16 field of view
|
||||
* 0x04: s16 near
|
||||
* 0x06: s16 far
|
||||
* 0x08: [GraphNodeFunc function]
|
||||
*/
|
||||
#define GEO_CAMERA_FRUSTUM(fov, near, far) \
|
||||
CMD_BBH(0x0A, 0x00, fov), \
|
||||
CMD_HH(near, far)
|
||||
#define GEO_CAMERA_FRUSTUM_WITH_FUNC(fov, near, far, func) \
|
||||
CMD_BBH(0x0A, 0x01, fov), \
|
||||
CMD_HH(near, far), \
|
||||
CMD_PTR(func)
|
||||
|
||||
/**
|
||||
* 0x0B: Create a root scene graph node
|
||||
* 0x01-0x03: unused
|
||||
*/
|
||||
#define GEO_NODE_START() \
|
||||
CMD_BBH(0x0B, 0x00, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x0C: Create zbuffer-toggling scene graph node
|
||||
* 0x01: u8 enableZBuffer (1 = on, 0 = off)
|
||||
* 0x02-0x03: unused
|
||||
*/
|
||||
#define GEO_ZBUFFER(enable) \
|
||||
CMD_BBH(0x0C, enable, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x0D: Create render range scene graph node
|
||||
* 0x01-0x03: unused
|
||||
* 0x04: s16 minDistance
|
||||
* 0x06: s16 maxDistance
|
||||
*/
|
||||
#define GEO_RENDER_RANGE(minDistance, maxDistance) \
|
||||
CMD_BBH(0x0D, 0x00, 0x0000), \
|
||||
CMD_HH(minDistance, maxDistance)
|
||||
|
||||
/**
|
||||
* 0x0E: Create switch-case scene graph node
|
||||
* 0x01: unused
|
||||
* 0x02: s16 numCases
|
||||
* 0x04: GraphNodeFunc caseSelectorFunc
|
||||
*/
|
||||
#define GEO_SWITCH_CASE(count, function) \
|
||||
CMD_BBH(0x0E, 0x00, count), \
|
||||
CMD_PTR(function)
|
||||
|
||||
/**
|
||||
* 0x0F: Create a camera scene graph node.
|
||||
* 0x01: unused
|
||||
* 0x02: s16 camera type
|
||||
* 0x04: s16 posX
|
||||
* 0x06: s16 posY
|
||||
* 0x08: s16 posZ
|
||||
* 0x0A: s16 focusX
|
||||
* 0x0C: s16 focusY
|
||||
* 0x0E: s16 focusZ
|
||||
* 0x10: GraphNodeFunc function
|
||||
*/
|
||||
#define GEO_CAMERA(type, x1, y1, z1, x2, y2, z2, function) \
|
||||
CMD_BBH(0x0F, 0x00, type), \
|
||||
CMD_HHHHHH(x1, y1, z1, x2, y2, z2), \
|
||||
CMD_PTR(function)
|
||||
|
||||
/**
|
||||
* 0x10: Create translation & rotation scene graph node with optional display list
|
||||
* Four different versions of 0x10
|
||||
* cmd+0x01: u8 params
|
||||
* 0b1000_0000: if set, enable displayList field and drawingLayer
|
||||
* 0b0111_0000: fieldLayout (determines how rest of data is formatted
|
||||
* 0b0000_1111: drawingLayer
|
||||
*
|
||||
* fieldLayout = 0: Translate & Rotate
|
||||
* 0x04: s16 xTranslation
|
||||
* 0x06: s16 yTranslation
|
||||
* 0x08: s16 zTranslation
|
||||
* 0x0A: s16 xRotation
|
||||
* 0x0C: s16 yRotation
|
||||
* 0x0E: s16 zRotation
|
||||
* 0x10: [u32 displayList: if MSbit of params set, display list segmented address]
|
||||
*/
|
||||
#define GEO_TRANSLATE_ROTATE(layer, tx, ty, tz, rx, ry, rz) \
|
||||
CMD_BBH(0x10, (0x00 | layer), 0x0000), \
|
||||
CMD_HHHHHH(tx, ty, tz, rx, ry, rz)
|
||||
#define GEO_TRANSLATE_ROTATE_WITH_DL(layer, tx, ty, tz, rx, ry, rz, displayList) \
|
||||
CMD_BBH(0x10, (0x00 | layer | 0x80), 0x0000), \
|
||||
CMD_HHHHHH(tx, ty, tz, rx, ry, rz), \
|
||||
CMD_PTR(displayList)
|
||||
|
||||
/**
|
||||
* fieldLayout = 1: Translate
|
||||
* 0x02: s16 xTranslation
|
||||
* 0x04: s16 yTranslation
|
||||
* 0x06: s16 zTranslation
|
||||
* 0x08: [u32 displayList: if MSbit of params set, display list segmented address]
|
||||
*/
|
||||
#define GEO_TRANSLATE(layer, tx, ty, tz) \
|
||||
CMD_BBH(0x10, (0x10 | layer), tx), \
|
||||
CMD_HH(ty, tz)
|
||||
#define GEO_TRANSLATE_WITH_DL(layer, tx, ty, tz, displayList) \
|
||||
CMD_BBH(0x10, (0x10 | layer | 0x80), tx), \
|
||||
CMD_HH(ty, tz), \
|
||||
CMD_PTR(displayList)
|
||||
|
||||
/**
|
||||
* fieldLayout = 2: Rotate
|
||||
* 0x02: s16 xRotation
|
||||
* 0x04: s16 yRotation
|
||||
* 0x06: s16 zRotation
|
||||
* 0x08: [u32 displayList: if MSbit of params set, display list segmented address]
|
||||
*/
|
||||
#define GEO_ROTATE(layer, rx, ry, rz) \
|
||||
CMD_BBH(0x10, (0x20 | layer), rx), \
|
||||
CMD_HH(ry, rz)
|
||||
#define GEO_ROTATE_WITH_DL(layer, rx, ry, rz, displayList) \
|
||||
CMD_BBH(0x10, (0x20 | layer | 0x80), rx), \
|
||||
CMD_HH(ry, rz), \
|
||||
CMD_PTR(displayList)
|
||||
|
||||
/**
|
||||
* fieldLayout = 3: Rotate Y
|
||||
* 0x02: s16 yRotation
|
||||
* 0x04: [u32 displayList: if MSbit of params set, display list segmented address]
|
||||
*/
|
||||
#define GEO_ROTATE_Y(layer, ry) \
|
||||
CMD_BBH(0x10, (0x30 | layer), ry)
|
||||
#define GEO_ROTATE_Y_WITH_DL(layer, ry, displayList) \
|
||||
CMD_BBH(0x10, (0x30 | layer | 0x80), ry), \
|
||||
CMD_PTR(displayList)
|
||||
|
||||
/**
|
||||
* 0x11: Create translation scene graph node with optional display list
|
||||
* 0x01: u8 params
|
||||
* 0b1000_0000: if set, enable displayList field and drawingLayer
|
||||
* 0b0000_1111: drawingLayer
|
||||
* 0x02: s16 translationX
|
||||
* 0x04: s16 translationY
|
||||
* 0x06: s16 translationZ
|
||||
* 0x08: [u32 displayList: if MSbit of params set, display list segmented address]
|
||||
*/
|
||||
#define GEO_TRANSLATE_NODE(layer, ux, uy, uz) \
|
||||
CMD_BBH(0x11, layer, ux), \
|
||||
CMD_HH(uy, uz)
|
||||
#define GEO_TRANSLATE_NODE_WITH_DL(layer, ux, uy, uz, displayList) \
|
||||
CMD_BBH(0x11, (layer | 0x80), ux), \
|
||||
CMD_HH(uy, uz), \
|
||||
CMD_PTR(displayList)
|
||||
|
||||
/**
|
||||
* 0x12: Create rotation scene graph node with optional display list
|
||||
* 0x01: u8 params
|
||||
* 0b1000_0000: if set, enable displayList field and drawingLayer
|
||||
* 0b0000_1111: drawingLayer
|
||||
* 0x02: s16 rotationX
|
||||
* 0x04: s16 rotationY
|
||||
* 0x06: s16 rotationZ
|
||||
* 0x08: [u32 displayList: if MSbit of params set, display list segmented address]
|
||||
*/
|
||||
#define GEO_ROTATION_NODE(layer, ux, uy, uz) \
|
||||
CMD_BBH(0x12, layer, ux), \
|
||||
CMD_HH(uy, uz)
|
||||
#define GEO_ROTATION_NODE_WITH_DL(layer, ux, uy, uz, displayList) \
|
||||
CMD_BBH(0x12, (layer | 0x80), ux), \
|
||||
CMD_HH(uy, uz), \
|
||||
CMD_PTR(displayList)
|
||||
|
||||
/**
|
||||
* 0x13: Create a scene graph node that is rotated by the object's animation.
|
||||
* 0x01: u8 drawingLayer
|
||||
* 0x02: s16 xTranslation
|
||||
* 0x04: s16 yTranslation
|
||||
* 0x06: s16 zTranslation
|
||||
* 0x08: u32 displayList: dislay list segmented address
|
||||
*/
|
||||
#define GEO_ANIMATED_PART(layer, x, y, z, displayList) \
|
||||
CMD_BBH(0x13, layer, x), \
|
||||
CMD_HH(y, z), \
|
||||
CMD_PTR(displayList)
|
||||
|
||||
/**
|
||||
* 0x14: Create billboarding node with optional display list
|
||||
* 0x01: u8 params
|
||||
* 0b1000_0000: if set, enable displayList field and drawingLayer
|
||||
* 0b0000_1111: drawingLayer
|
||||
* 0x02: s16 xTranslation
|
||||
* 0x04: s16 yTranslation
|
||||
* 0x06: s16 zTranslation
|
||||
* 0x08: [u32 displayList: if MSbit of params is set, display list segmented address]
|
||||
*/
|
||||
#define GEO_BILLBOARD_WITH_PARAMS(layer, tx, ty, tz) \
|
||||
CMD_BBH(0x14, layer, tx), \
|
||||
CMD_HH(ty, tz)
|
||||
#define GEO_BILLBOARD_WITH_PARAMS_AND_DL(layer, tx, ty, tz, displayList) \
|
||||
CMD_BBH(0x14, (layer | 0x80), tx), \
|
||||
CMD_HH(ty, tz), \
|
||||
CMD_PTR(displayList)
|
||||
#define GEO_BILLBOARD() \
|
||||
GEO_BILLBOARD_WITH_PARAMS(0, 0, 0, 0)
|
||||
|
||||
/**
|
||||
* 0x15: Create plain display list scene graph node
|
||||
* 0x01: u8 drawingLayer
|
||||
* 0x02-0x03: unused
|
||||
* 0x04: u32 displayList: display list segmented address
|
||||
*/
|
||||
#define GEO_DISPLAY_LIST(layer, displayList) \
|
||||
CMD_BBH(0x15, layer, 0x0000), \
|
||||
CMD_PTR(displayList)
|
||||
|
||||
/**
|
||||
* 0x16: Create shadow scene graph node
|
||||
* 0x01: unused
|
||||
* 0x02: s16 shadowType (cast to u8)
|
||||
* 0x04: s16 shadowSolidity (cast to u8)
|
||||
* 0x06: s16 shadowScale
|
||||
*/
|
||||
#define GEO_SHADOW(type, solidity, scale) \
|
||||
CMD_BBH(0x16, 0x00, type), \
|
||||
CMD_HH(solidity, scale)
|
||||
|
||||
/**
|
||||
* 0x17: Create render object scene graph node
|
||||
* 0x01-0x03: unused
|
||||
*/
|
||||
#define GEO_RENDER_OBJ() \
|
||||
CMD_BBH(0x17, 0x00, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x18: Create dynamically generated displaylist scene graph node
|
||||
* 0x01: unused
|
||||
* 0x02: s16 parameter
|
||||
* 0x04: GraphNodeFunc function
|
||||
*/
|
||||
#define GEO_ASM(param, function) \
|
||||
CMD_BBH(0x18, 0x00, param), \
|
||||
CMD_PTR(function)
|
||||
|
||||
/**
|
||||
* 0x19: Create background scene graph node
|
||||
* 0x02: s16 background: background ID, or RGBA5551 color if backgroundFunc is null
|
||||
* 0x04: GraphNodeFunc backgroundFunc
|
||||
*/
|
||||
#define GEO_BACKGROUND(background, function) \
|
||||
CMD_BBH(0x19, 0x00, background), \
|
||||
CMD_PTR(function)
|
||||
#define GEO_BACKGROUND_COLOR(background) \
|
||||
GEO_BACKGROUND(background, NULL)
|
||||
|
||||
/**
|
||||
* 0x1A: No operation
|
||||
*/
|
||||
#define GEO_NOP_1A() \
|
||||
CMD_BBH(0x1A, 0x00, 0x0000), \
|
||||
CMD_HH(0x0000, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x1B: Copy the shared children from an object parent node from a specific view
|
||||
* to a newly created object parent.
|
||||
* 0x02: s16 index of array
|
||||
*/
|
||||
#define GEO_COPY_VIEW(index) \
|
||||
CMD_BBH(0x1B, 0x00, index)
|
||||
|
||||
/**
|
||||
* 0x1C: Create a held object scene graph node
|
||||
* cmd+0x01: u8 unused
|
||||
* cmd+0x02: s16 offsetX
|
||||
* cmd+0x04: s16 offsetY
|
||||
* cmd+0x06: s16 offsetZ
|
||||
* cmd+0x08: GraphNodeFunc nodeFunc
|
||||
*/
|
||||
#define GEO_HELD_OBJECT(param, ux, uy, uz, nodeFunc) \
|
||||
CMD_BBH(0x1C, param, ux), \
|
||||
CMD_HH(uy, uz), \
|
||||
CMD_PTR(nodeFunc)
|
||||
|
||||
/**
|
||||
* 0x1D: Create scale scene graph node with optional display list
|
||||
* 0x01: u8 params
|
||||
* 0b1000_0000: if set, enable displayList field and drawingLayer
|
||||
* 0b0000_1111: drawingLayer
|
||||
* 0x02-0x03: unused
|
||||
* 0x04: u32 scale (0x10000 = 1.0)
|
||||
* 0x08: [u32 displayList: if MSbit of params is set, display list segment address]
|
||||
*/
|
||||
#define GEO_SCALE(layer, scale) \
|
||||
CMD_BBH(0x1D, layer, 0x0000), \
|
||||
CMD_W(scale)
|
||||
#define GEO_SCALE_WITH_DL(layer, scale, displayList) \
|
||||
CMD_BBH(0x1D, (layer | 0x80), 0x0000), \
|
||||
CMD_W(scale), \
|
||||
CMD_PTR(displayList)
|
||||
|
||||
/**
|
||||
* 0x1E: No operation
|
||||
*/
|
||||
#define GEO_NOP_1E() \
|
||||
CMD_BBH(0x1E, 0x00, 0x0000), \
|
||||
CMD_HH(0x0000, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x1F: No operation
|
||||
*/
|
||||
#define GEO_NOP_1F() \
|
||||
CMD_BBH(0x1F, 0x00, 0x0000), \
|
||||
CMD_HH(0x0000, 0x0000), \
|
||||
CMD_HH(0x0000, 0x0000), \
|
||||
CMD_HH(0x0000, 0x0000)
|
||||
|
||||
/**
|
||||
* 0x20: Create a scene graph node that specifies for an object the radius that
|
||||
* is used for frustum culling.
|
||||
* 0x01: unused
|
||||
* 0x02: s16 cullingRadius
|
||||
*/
|
||||
#define GEO_CULLING_RADIUS(cullingRadius) \
|
||||
CMD_BBH(0x20, 0x00, cullingRadius)
|
||||
|
||||
#endif // GEO_COMMANDS_H
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef LEVEL_MISC_MACROS_H
|
||||
#define LEVEL_MISC_MACROS_H
|
||||
|
||||
#define MACRO_OBJECT_WITH_BEH_PARAM(preset, yaw, posX, posY, posZ, behParam) \
|
||||
((s16)((yaw * 0x10 / 45) << 9) | (preset + 0x1F)), posX, posY, posZ, behParam
|
||||
|
||||
#define MACRO_OBJECT(preset, yaw, posX, posY, posZ) \
|
||||
MACRO_OBJECT_WITH_BEH_PARAM(preset, yaw, posX, posY, posZ, 0)
|
||||
|
||||
#define MACRO_OBJECT_END() \
|
||||
0x001E
|
||||
|
||||
#define SPECIAL_OBJECT(preset, posX, posY, posZ) \
|
||||
preset, posX, posY, posZ
|
||||
|
||||
#define SPECIAL_OBJECT_WITH_YAW(preset, posX, posY, posZ, yaw) \
|
||||
preset, posX, posY, posZ, yaw
|
||||
|
||||
#define SPECIAL_OBJECT_WITH_YAW_AND_PARAM(preset, posX, posY, posZ, yaw, param) \
|
||||
preset, posX, posY, posZ, yaw, param
|
||||
|
||||
#define TRAJECTORY_POS(trajId, x, y, z) \
|
||||
trajId, x, y, z
|
||||
|
||||
#define TRAJECTORY_END() \
|
||||
-1
|
||||
|
||||
#endif // LEVEL_MISC_MACROS_H
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef MACROS_H
|
||||
#define MACROS_H
|
||||
|
||||
#include "platform_info.h"
|
||||
|
||||
#ifndef __sgi
|
||||
#define GLOBAL_ASM(...)
|
||||
#endif
|
||||
|
||||
// ===== PATCH =====
|
||||
#define NON_MATCHING 1
|
||||
#define AVOID_UB 1
|
||||
// =================
|
||||
|
||||
#if !defined(__sgi) && (!defined(NON_MATCHING) || !defined(AVOID_UB))
|
||||
// asm-process isn't supported outside of IDO, and undefined behavior causes
|
||||
// crashes.
|
||||
#error Matching build is only possible on IDO; please build with NON_MATCHING=1.
|
||||
#endif
|
||||
|
||||
#define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
#define GLUE(a, b) a ## b
|
||||
#define GLUE2(a, b) GLUE(a, b)
|
||||
|
||||
// Avoid compiler warnings for unused variables
|
||||
#ifdef __GNUC__
|
||||
#define UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define UNUSED
|
||||
#endif
|
||||
|
||||
// Avoid undefined behaviour for non-returning functions
|
||||
#ifdef __GNUC__
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#else
|
||||
#define NORETURN
|
||||
#endif
|
||||
|
||||
// Static assertions
|
||||
#ifdef __GNUC__
|
||||
#define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
|
||||
#else
|
||||
#define STATIC_ASSERT(cond, msg) typedef char GLUE2(static_assertion_failed, __LINE__)[(cond) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
// Align to 8-byte boundary for DMA requirements
|
||||
#ifdef __GNUC__
|
||||
#define ALIGNED8 __attribute__((aligned(8)))
|
||||
#else
|
||||
#define ALIGNED8
|
||||
#endif
|
||||
|
||||
// Align to 16-byte boundary for audio lib requirements
|
||||
#ifdef __GNUC__
|
||||
#define ALIGNED16 __attribute__((aligned(16)))
|
||||
#else
|
||||
#define ALIGNED16
|
||||
#endif
|
||||
|
||||
#ifndef NO_SEGMENTED_MEMORY
|
||||
// convert a virtual address to physical.
|
||||
#define VIRTUAL_TO_PHYSICAL(addr) ((uintptr_t)(addr) & 0x1FFFFFFF)
|
||||
|
||||
// convert a physical address to virtual.
|
||||
#define PHYSICAL_TO_VIRTUAL(addr) ((uintptr_t)(addr) | 0x80000000)
|
||||
|
||||
// another way of converting virtual to physical
|
||||
#define VIRTUAL_TO_PHYSICAL2(addr) ((u8 *)(addr) - 0x80000000U)
|
||||
#else
|
||||
// no conversion needed other than cast
|
||||
#define VIRTUAL_TO_PHYSICAL(addr) ((addr))
|
||||
#define PHYSICAL_TO_VIRTUAL(addr) ((addr))
|
||||
#define VIRTUAL_TO_PHYSICAL2(addr) ((void *)(addr))
|
||||
#endif
|
||||
|
||||
#endif // MACROS_H
|
||||
@@ -0,0 +1,219 @@
|
||||
#ifndef MARIO_ANIMATION_IDS_H
|
||||
#define MARIO_ANIMATION_IDS_H
|
||||
|
||||
/* Mario Animation IDs */
|
||||
|
||||
enum MarioAnimID
|
||||
{
|
||||
/* 0x00 */ MARIO_ANIM_SLOW_LEDGE_GRAB,
|
||||
/* 0x01 */ MARIO_ANIM_FALL_OVER_BACKWARDS,
|
||||
/* 0x02 */ MARIO_ANIM_BACKWARD_AIR_KB,
|
||||
/* 0x03 */ MARIO_ANIM_DYING_ON_BACK,
|
||||
/* 0x04 */ MARIO_ANIM_BACKFLIP,
|
||||
/* 0x05 */ MARIO_ANIM_CLIMB_UP_POLE,
|
||||
/* 0x06 */ MARIO_ANIM_GRAB_POLE_SHORT,
|
||||
/* 0x07 */ MARIO_ANIM_GRAB_POLE_SWING_PART1,
|
||||
/* 0x08 */ MARIO_ANIM_GRAB_POLE_SWING_PART2,
|
||||
/* 0x09 */ MARIO_ANIM_HANDSTAND_IDLE,
|
||||
/* 0x0A */ MARIO_ANIM_HANDSTAND_JUMP,
|
||||
/* 0x0B */ MARIO_ANIM_START_HANDSTAND,
|
||||
/* 0x0C */ MARIO_ANIM_RETURN_FROM_HANDSTAND,
|
||||
/* 0x0D */ MARIO_ANIM_IDLE_ON_POLE,
|
||||
/* 0x0E */ MARIO_ANIM_A_POSE,
|
||||
/* 0x0F */ MARIO_ANIM_SKID_ON_GROUND,
|
||||
/* 0x10 */ MARIO_ANIM_STOP_SKID,
|
||||
/* 0x11 */ MARIO_ANIM_CROUCH_FROM_FAST_LONGJUMP,
|
||||
/* 0x12 */ MARIO_ANIM_CROUCH_FROM_SLOW_LONGJUMP,
|
||||
/* 0x13 */ MARIO_ANIM_FAST_LONGJUMP,
|
||||
/* 0x14 */ MARIO_ANIM_SLOW_LONGJUMP,
|
||||
/* 0x15 */ MARIO_ANIM_AIRBORNE_ON_STOMACH,
|
||||
/* 0x16 */ MARIO_ANIM_WALK_WITH_LIGHT_OBJ,
|
||||
/* 0x17 */ MARIO_ANIM_RUN_WITH_LIGHT_OBJ,
|
||||
/* 0x18 */ MARIO_ANIM_SLOW_WALK_WITH_LIGHT_OBJ,
|
||||
/* 0x19 */ MARIO_ANIM_SHIVERING_WARMING_HAND,
|
||||
/* 0x1A */ MARIO_ANIM_SHIVERING_RETURN_TO_IDLE,
|
||||
/* 0x1B */ MARIO_ANIM_SHIVERING,
|
||||
/* 0x1C */ MARIO_ANIM_CLIMB_DOWN_LEDGE,
|
||||
/* 0x1D */ MARIO_ANIM_CREDITS_WAVING,
|
||||
/* 0x1E */ MARIO_ANIM_CREDITS_LOOK_UP,
|
||||
/* 0x1F */ MARIO_ANIM_CREDITS_RETURN_FROM_LOOK_UP,
|
||||
/* 0x20 */ MARIO_ANIM_CREDITS_RAISE_HAND,
|
||||
/* 0x21 */ MARIO_ANIM_CREDITS_LOWER_HAND,
|
||||
/* 0x22 */ MARIO_ANIM_CREDITS_TAKE_OFF_CAP,
|
||||
/* 0x23 */ MARIO_ANIM_CREDITS_START_WALK_LOOK_UP,
|
||||
/* 0x24 */ MARIO_ANIM_CREDITS_LOOK_BACK_THEN_RUN,
|
||||
/* 0x25 */ MARIO_ANIM_FINAL_BOWSER_RAISE_HAND_SPIN,
|
||||
/* 0x26 */ MARIO_ANIM_FINAL_BOWSER_WING_CAP_TAKE_OFF,
|
||||
/* 0x27 */ MARIO_ANIM_CREDITS_PEACE_SIGN,
|
||||
/* 0x28 */ MARIO_ANIM_STAND_UP_FROM_LAVA_BOOST,
|
||||
/* 0x29 */ MARIO_ANIM_FIRE_LAVA_BURN,
|
||||
/* 0x2A */ MARIO_ANIM_WING_CAP_FLY,
|
||||
/* 0x2B */ MARIO_ANIM_HANG_ON_OWL,
|
||||
/* 0x2C */ MARIO_ANIM_LAND_ON_STOMACH,
|
||||
/* 0x2D */ MARIO_ANIM_AIR_FORWARD_KB,
|
||||
/* 0x2E */ MARIO_ANIM_DYING_ON_STOMACH,
|
||||
/* 0x2F */ MARIO_ANIM_SUFFOCATING,
|
||||
/* 0x30 */ MARIO_ANIM_COUGHING,
|
||||
/* 0x31 */ MARIO_ANIM_THROW_CATCH_KEY,
|
||||
/* 0x32 */ MARIO_ANIM_DYING_FALL_OVER,
|
||||
/* 0x33 */ MARIO_ANIM_IDLE_ON_LEDGE,
|
||||
/* 0x34 */ MARIO_ANIM_FAST_LEDGE_GRAB,
|
||||
/* 0x35 */ MARIO_ANIM_HANG_ON_CEILING,
|
||||
/* 0x36 */ MARIO_ANIM_PUT_CAP_ON,
|
||||
/* 0x37 */ MARIO_ANIM_TAKE_CAP_OFF_THEN_ON,
|
||||
/* 0x38 */ MARIO_ANIM_QUICKLY_PUT_CAP_ON, // unused
|
||||
/* 0x39 */ MARIO_ANIM_HEAD_STUCK_IN_GROUND,
|
||||
/* 0x3A */ MARIO_ANIM_GROUND_POUND_LANDING,
|
||||
/* 0x3B */ MARIO_ANIM_TRIPLE_JUMP_GROUND_POUND,
|
||||
/* 0x3C */ MARIO_ANIM_START_GROUND_POUND,
|
||||
/* 0x3D */ MARIO_ANIM_GROUND_POUND,
|
||||
/* 0x3E */ MARIO_ANIM_BOTTOM_STUCK_IN_GROUND,
|
||||
/* 0x3F */ MARIO_ANIM_IDLE_WITH_LIGHT_OBJ,
|
||||
/* 0x40 */ MARIO_ANIM_JUMP_LAND_WITH_LIGHT_OBJ,
|
||||
/* 0x41 */ MARIO_ANIM_JUMP_WITH_LIGHT_OBJ,
|
||||
/* 0x42 */ MARIO_ANIM_FALL_LAND_WITH_LIGHT_OBJ,
|
||||
/* 0x43 */ MARIO_ANIM_FALL_WITH_LIGHT_OBJ,
|
||||
/* 0x44 */ MARIO_ANIM_FALL_FROM_SLIDING_WITH_LIGHT_OBJ,
|
||||
/* 0x45 */ MARIO_ANIM_SLIDING_ON_BOTTOM_WITH_LIGHT_OBJ,
|
||||
/* 0x46 */ MARIO_ANIM_STAND_UP_FROM_SLIDING_WITH_LIGHT_OBJ,
|
||||
/* 0x47 */ MARIO_ANIM_RIDING_SHELL,
|
||||
/* 0x48 */ MARIO_ANIM_WALKING,
|
||||
/* 0x49 */ MARIO_ANIM_FORWARD_FLIP, // unused
|
||||
/* 0x4A */ MARIO_ANIM_JUMP_RIDING_SHELL,
|
||||
/* 0x4B */ MARIO_ANIM_LAND_FROM_DOUBLE_JUMP,
|
||||
/* 0x4C */ MARIO_ANIM_DOUBLE_JUMP_FALL,
|
||||
/* 0x4D */ MARIO_ANIM_SINGLE_JUMP,
|
||||
/* 0x4E */ MARIO_ANIM_LAND_FROM_SINGLE_JUMP,
|
||||
/* 0x4F */ MARIO_ANIM_AIR_KICK,
|
||||
/* 0x50 */ MARIO_ANIM_DOUBLE_JUMP_RISE,
|
||||
/* 0x51 */ MARIO_ANIM_START_FORWARD_SPINNING, // unused
|
||||
/* 0x52 */ MARIO_ANIM_THROW_LIGHT_OBJECT,
|
||||
/* 0x53 */ MARIO_ANIM_FALL_FROM_SLIDE_KICK,
|
||||
/* 0x54 */ MARIO_ANIM_BEND_KNESS_RIDING_SHELL, // unused
|
||||
/* 0x55 */ MARIO_ANIM_LEGS_STUCK_IN_GROUND,
|
||||
/* 0x56 */ MARIO_ANIM_GENERAL_FALL,
|
||||
/* 0x57 */ MARIO_ANIM_GENERAL_LAND,
|
||||
/* 0x58 */ MARIO_ANIM_BEING_GRABBED,
|
||||
/* 0x59 */ MARIO_ANIM_GRAB_HEAVY_OBJECT,
|
||||
/* 0x5A */ MARIO_ANIM_SLOW_LAND_FROM_DIVE,
|
||||
/* 0x5B */ MARIO_ANIM_FLY_FROM_CANNON,
|
||||
/* 0x5C */ MARIO_ANIM_MOVE_ON_WIRE_NET_RIGHT,
|
||||
/* 0x5D */ MARIO_ANIM_MOVE_ON_WIRE_NET_LEFT,
|
||||
/* 0x5E */ MARIO_ANIM_MISSING_CAP,
|
||||
/* 0x5F */ MARIO_ANIM_PULL_DOOR_WALK_IN,
|
||||
/* 0x60 */ MARIO_ANIM_PUSH_DOOR_WALK_IN,
|
||||
/* 0x61 */ MARIO_ANIM_UNLOCK_DOOR,
|
||||
/* 0x62 */ MARIO_ANIM_START_REACH_POCKET, // unused, reaching keys maybe?
|
||||
/* 0x63 */ MARIO_ANIM_REACH_POCKET, // unused
|
||||
/* 0x64 */ MARIO_ANIM_STOP_REACH_POCKET, // unused
|
||||
/* 0x65 */ MARIO_ANIM_GROUND_THROW,
|
||||
/* 0x66 */ MARIO_ANIM_GROUND_KICK,
|
||||
/* 0x67 */ MARIO_ANIM_FIRST_PUNCH,
|
||||
/* 0x68 */ MARIO_ANIM_SECOND_PUNCH,
|
||||
/* 0x69 */ MARIO_ANIM_FIRST_PUNCH_FAST,
|
||||
/* 0x6A */ MARIO_ANIM_SECOND_PUNCH_FAST,
|
||||
/* 0x6B */ MARIO_ANIM_PICK_UP_LIGHT_OBJ,
|
||||
/* 0x6C */ MARIO_ANIM_PUSHING,
|
||||
/* 0x6D */ MARIO_ANIM_START_RIDING_SHELL,
|
||||
/* 0x6E */ MARIO_ANIM_PLACE_LIGHT_OBJ,
|
||||
/* 0x6F */ MARIO_ANIM_FORWARD_SPINNING,
|
||||
/* 0x70 */ MARIO_ANIM_BACKWARD_SPINNING,
|
||||
/* 0x71 */ MARIO_ANIM_BREAKDANCE,
|
||||
/* 0x72 */ MARIO_ANIM_RUNNING,
|
||||
/* 0x73 */ MARIO_ANIM_RUNNING_UNUSED, // unused duplicate, originally part 2?
|
||||
/* 0x74 */ MARIO_ANIM_SOFT_BACK_KB,
|
||||
/* 0x75 */ MARIO_ANIM_SOFT_FRONT_KB,
|
||||
/* 0x76 */ MARIO_ANIM_DYING_IN_QUICKSAND,
|
||||
/* 0x77 */ MARIO_ANIM_IDLE_IN_QUICKSAND,
|
||||
/* 0x78 */ MARIO_ANIM_MOVE_IN_QUICKSAND,
|
||||
/* 0x79 */ MARIO_ANIM_ELECTROCUTION,
|
||||
/* 0x7A */ MARIO_ANIM_SHOCKED,
|
||||
/* 0x7B */ MARIO_ANIM_BACKWARD_KB,
|
||||
/* 0x7C */ MARIO_ANIM_FORWARD_KB,
|
||||
/* 0x7D */ MARIO_ANIM_IDLE_HEAVY_OBJ,
|
||||
/* 0x7E */ MARIO_ANIM_STAND_AGAINST_WALL,
|
||||
/* 0x7F */ MARIO_ANIM_SIDESTEP_LEFT,
|
||||
/* 0x80 */ MARIO_ANIM_SIDESTEP_RIGHT,
|
||||
/* 0x81 */ MARIO_ANIM_START_SLEEP_IDLE,
|
||||
/* 0x82 */ MARIO_ANIM_START_SLEEP_SCRATCH,
|
||||
/* 0x83 */ MARIO_ANIM_START_SLEEP_YAWN,
|
||||
/* 0x84 */ MARIO_ANIM_START_SLEEP_SITTING,
|
||||
/* 0x85 */ MARIO_ANIM_SLEEP_IDLE,
|
||||
/* 0x86 */ MARIO_ANIM_SLEEP_START_LYING,
|
||||
/* 0x87 */ MARIO_ANIM_SLEEP_LYING,
|
||||
/* 0x88 */ MARIO_ANIM_DIVE,
|
||||
/* 0x89 */ MARIO_ANIM_SLIDE_DIVE,
|
||||
/* 0x8A */ MARIO_ANIM_GROUND_BONK,
|
||||
/* 0x8B */ MARIO_ANIM_STOP_SLIDE_LIGHT_OBJ,
|
||||
/* 0x8C */ MARIO_ANIM_SLIDE_KICK,
|
||||
/* 0x8D */ MARIO_ANIM_CROUCH_FROM_SLIDE_KICK,
|
||||
/* 0x8E */ MARIO_ANIM_SLIDE_MOTIONLESS, // unused
|
||||
/* 0x8F */ MARIO_ANIM_STOP_SLIDE,
|
||||
/* 0x90 */ MARIO_ANIM_FALL_FROM_SLIDE,
|
||||
/* 0x91 */ MARIO_ANIM_SLIDE,
|
||||
/* 0x92 */ MARIO_ANIM_TIPTOE,
|
||||
/* 0x93 */ MARIO_ANIM_TWIRL_LAND,
|
||||
/* 0x94 */ MARIO_ANIM_TWIRL,
|
||||
/* 0x95 */ MARIO_ANIM_START_TWIRL,
|
||||
/* 0x96 */ MARIO_ANIM_STOP_CROUCHING,
|
||||
/* 0x97 */ MARIO_ANIM_START_CROUCHING,
|
||||
/* 0x98 */ MARIO_ANIM_CROUCHING,
|
||||
/* 0x99 */ MARIO_ANIM_CRAWLING,
|
||||
/* 0x9A */ MARIO_ANIM_STOP_CRAWLING,
|
||||
/* 0x9B */ MARIO_ANIM_START_CRAWLING,
|
||||
/* 0x9C */ MARIO_ANIM_SUMMON_STAR,
|
||||
/* 0x9D */ MARIO_ANIM_RETURN_STAR_APPROACH_DOOR,
|
||||
/* 0x9E */ MARIO_ANIM_BACKWARDS_WATER_KB,
|
||||
/* 0x9F */ MARIO_ANIM_SWIM_WITH_OBJ_PART1,
|
||||
/* 0xA0 */ MARIO_ANIM_SWIM_WITH_OBJ_PART2,
|
||||
/* 0xA1 */ MARIO_ANIM_FLUTTERKICK_WITH_OBJ,
|
||||
/* 0xA2 */ MARIO_ANIM_WATER_ACTION_END_WITH_OBJ, // either swimming or flutterkicking
|
||||
/* 0xA3 */ MARIO_ANIM_STOP_GRAB_OBJ_WATER,
|
||||
/* 0xA4 */ MARIO_ANIM_WATER_IDLE_WITH_OBJ,
|
||||
/* 0xA5 */ MARIO_ANIM_DROWNING_PART1,
|
||||
/* 0xA6 */ MARIO_ANIM_DROWNING_PART2,
|
||||
/* 0xA7 */ MARIO_ANIM_WATER_DYING,
|
||||
/* 0xA8 */ MARIO_ANIM_WATER_FORWARD_KB,
|
||||
/* 0xA9 */ MARIO_ANIM_FALL_FROM_WATER,
|
||||
/* 0xAA */ MARIO_ANIM_SWIM_PART1,
|
||||
/* 0xAB */ MARIO_ANIM_SWIM_PART2,
|
||||
/* 0xAC */ MARIO_ANIM_FLUTTERKICK,
|
||||
/* 0xAD */ MARIO_ANIM_WATER_ACTION_END, // either swimming or flutterkicking
|
||||
/* 0xAE */ MARIO_ANIM_WATER_PICK_UP_OBJ,
|
||||
/* 0xAF */ MARIO_ANIM_WATER_GRAB_OBJ_PART2,
|
||||
/* 0xB0 */ MARIO_ANIM_WATER_GRAB_OBJ_PART1,
|
||||
/* 0xB1 */ MARIO_ANIM_WATER_THROW_OBJ,
|
||||
/* 0xB2 */ MARIO_ANIM_WATER_IDLE,
|
||||
/* 0xB3 */ MARIO_ANIM_WATER_STAR_DANCE,
|
||||
/* 0xB4 */ MARIO_ANIM_RETURN_FROM_WATER_STAR_DANCE,
|
||||
/* 0xB5 */ MARIO_ANIM_GRAB_BOWSER,
|
||||
/* 0xB6 */ MARIO_ANIM_SWINGING_BOWSER,
|
||||
/* 0xB7 */ MARIO_ANIM_RELEASE_BOWSER,
|
||||
/* 0xB8 */ MARIO_ANIM_HOLDING_BOWSER,
|
||||
/* 0xB9 */ MARIO_ANIM_HEAVY_THROW,
|
||||
/* 0xBA */ MARIO_ANIM_WALK_PANTING,
|
||||
/* 0xBB */ MARIO_ANIM_WALK_WITH_HEAVY_OBJ,
|
||||
/* 0xBC */ MARIO_ANIM_TURNING_PART1,
|
||||
/* 0xBD */ MARIO_ANIM_TURNING_PART2,
|
||||
/* 0xBE */ MARIO_ANIM_SLIDEFLIP_LAND,
|
||||
/* 0XBF */ MARIO_ANIM_SLIDEFLIP,
|
||||
/* 0xC0 */ MARIO_ANIM_TRIPLE_JUMP_LAND,
|
||||
/* 0xC1 */ MARIO_ANIM_TRIPLE_JUMP,
|
||||
/* 0xC2 */ MARIO_ANIM_FIRST_PERSON,
|
||||
/* 0xC3 */ MARIO_ANIM_IDLE_HEAD_LEFT,
|
||||
/* 0xC4 */ MARIO_ANIM_IDLE_HEAD_RIGHT,
|
||||
/* 0xC5 */ MARIO_ANIM_IDLE_HEAD_CENTER,
|
||||
/* 0xC6 */ MARIO_ANIM_HANDSTAND_LEFT,
|
||||
/* 0xC7 */ MARIO_ANIM_HANDSTAND_RIGHT,
|
||||
/* 0xC8 */ MARIO_ANIM_WAKE_FROM_SLEEP,
|
||||
/* 0xC9 */ MARIO_ANIM_WAKE_FROM_LYING,
|
||||
/* 0xCA */ MARIO_ANIM_START_TIPTOE,
|
||||
/* 0xCB */ MARIO_ANIM_SLIDEJUMP, // pole jump and wall kick
|
||||
/* 0xCC */ MARIO_ANIM_START_WALLKICK,
|
||||
/* 0xCD */ MARIO_ANIM_STAR_DANCE,
|
||||
/* 0xCE */ MARIO_ANIM_RETURN_FROM_STAR_DANCE,
|
||||
/* 0xCF */ MARIO_ANIM_FORWARD_SPINNING_FLIP,
|
||||
/* 0xD0 */ MARIO_ANIM_TRIPLE_JUMP_FLY
|
||||
};
|
||||
|
||||
#endif // MARIO_ANIMATION_IDS_H
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef MARIO_GEO_SWITCH_CASE_IDS_H
|
||||
#define MARIO_GEO_SWITCH_CASE_IDS_H
|
||||
|
||||
/* Mario Geo-Switch-Case IDs */
|
||||
|
||||
enum MarioEyesGSCId
|
||||
{
|
||||
/*0x00*/ MARIO_EYES_BLINK,
|
||||
/*0x01*/ MARIO_EYES_OPEN,
|
||||
/*0x02*/ MARIO_EYES_HALF_CLOSED,
|
||||
/*0x03*/ MARIO_EYES_CLOSED,
|
||||
/*0x04*/ MARIO_EYES_LOOK_LEFT, // unused
|
||||
/*0x05*/ MARIO_EYES_LOOK_RIGHT, // unused
|
||||
/*0x06*/ MARIO_EYES_LOOK_UP, // unused
|
||||
/*0x07*/ MARIO_EYES_LOOK_DOWN, // unused
|
||||
/*0x08*/ MARIO_EYES_DEAD
|
||||
};
|
||||
|
||||
enum MarioHandGSCId
|
||||
{
|
||||
/*0x00*/ MARIO_HAND_FISTS,
|
||||
/*0x01*/ MARIO_HAND_OPEN,
|
||||
/*0x02*/ MARIO_HAND_PEACE_SIGN,
|
||||
/*0x03*/ MARIO_HAND_HOLDING_CAP,
|
||||
/*0x04*/ MARIO_HAND_HOLDING_WING_CAP,
|
||||
/*0x05*/ MARIO_HAND_RIGHT_OPEN
|
||||
};
|
||||
|
||||
enum MarioCapGSCId
|
||||
{
|
||||
/*0x00*/ MARIO_HAS_DEFAULT_CAP_ON,
|
||||
/*0x01*/ MARIO_HAS_DEFAULT_CAP_OFF,
|
||||
/*0x02*/ MARIO_HAS_WING_CAP_ON,
|
||||
/*0x03*/ MARIO_HAS_WING_CAP_OFF // unused
|
||||
};
|
||||
|
||||
enum MarioGrabPosGSCId
|
||||
{
|
||||
/*0x00*/ GRAB_POS_NULL,
|
||||
/*0x01*/ GRAB_POS_LIGHT_OBJ,
|
||||
/*0x02*/ GRAB_POS_HEAVY_OBJ,
|
||||
/*0x03*/ GRAB_POS_BOWSER
|
||||
};
|
||||
|
||||
#endif // MARIO_GEO_SWITCH_CASE_IDS_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
#ifndef PLATFORM_INFO_H
|
||||
#define PLATFORM_INFO_H
|
||||
|
||||
#ifdef TARGET_N64
|
||||
#define IS_64_BIT 0
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#define IS_64_BIT (UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFU)
|
||||
#define IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#endif
|
||||
|
||||
#define DOUBLE_SIZE_ON_64_BIT(size) ((size) * (sizeof(void *) / 4))
|
||||
|
||||
#endif // PLATFORM_INFO_H
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef SEQ_IDS_H
|
||||
#define SEQ_IDS_H
|
||||
|
||||
#define SEQ_VARIATION 0x80
|
||||
|
||||
enum SeqId {
|
||||
SEQ_SOUND_PLAYER, // 0x00
|
||||
SEQ_EVENT_CUTSCENE_COLLECT_STAR, // 0x01
|
||||
SEQ_MENU_TITLE_SCREEN, // 0x02
|
||||
SEQ_LEVEL_GRASS, // 0x03
|
||||
SEQ_LEVEL_INSIDE_CASTLE, // 0x04
|
||||
SEQ_LEVEL_WATER, // 0x05
|
||||
SEQ_LEVEL_HOT, // 0x06
|
||||
SEQ_LEVEL_BOSS_KOOPA, // 0x07
|
||||
SEQ_LEVEL_SNOW, // 0x08
|
||||
SEQ_LEVEL_SLIDE, // 0x09
|
||||
SEQ_LEVEL_SPOOKY, // 0x0A
|
||||
SEQ_EVENT_PIRANHA_PLANT, // 0x0B
|
||||
SEQ_LEVEL_UNDERGROUND, // 0x0C
|
||||
SEQ_MENU_STAR_SELECT, // 0x0D
|
||||
SEQ_EVENT_POWERUP, // 0x0E
|
||||
SEQ_EVENT_METAL_CAP, // 0x0F
|
||||
SEQ_EVENT_KOOPA_MESSAGE, // 0x10
|
||||
SEQ_LEVEL_KOOPA_ROAD, // 0x11
|
||||
SEQ_EVENT_HIGH_SCORE, // 0x12
|
||||
SEQ_EVENT_MERRY_GO_ROUND, // 0x13
|
||||
SEQ_EVENT_RACE, // 0x14
|
||||
SEQ_EVENT_CUTSCENE_STAR_SPAWN, // 0x15
|
||||
SEQ_EVENT_BOSS, // 0x16
|
||||
SEQ_EVENT_CUTSCENE_COLLECT_KEY, // 0x17
|
||||
SEQ_EVENT_ENDLESS_STAIRS, // 0x18
|
||||
SEQ_LEVEL_BOSS_KOOPA_FINAL, // 0x19
|
||||
SEQ_EVENT_CUTSCENE_CREDITS, // 0x1A
|
||||
SEQ_EVENT_SOLVE_PUZZLE, // 0x1B
|
||||
SEQ_EVENT_TOAD_MESSAGE, // 0x1C
|
||||
SEQ_EVENT_PEACH_MESSAGE, // 0x1D
|
||||
SEQ_EVENT_CUTSCENE_INTRO, // 0x1E
|
||||
SEQ_EVENT_CUTSCENE_VICTORY, // 0x1F
|
||||
SEQ_EVENT_CUTSCENE_ENDING, // 0x20
|
||||
SEQ_MENU_FILE_SELECT, // 0x21
|
||||
SEQ_EVENT_CUTSCENE_LAKITU, // 0x22 (not in JP)
|
||||
SEQ_COUNT
|
||||
};
|
||||
|
||||
#endif // SEQ_IDS_H
|
||||
@@ -0,0 +1,435 @@
|
||||
#ifndef SM64_H
|
||||
#define SM64_H
|
||||
|
||||
// Global header for Super Mario 64
|
||||
|
||||
#include "types.h"
|
||||
// #include "config.h"
|
||||
// #include "object_fields.h"
|
||||
// #include "object_constants.h"
|
||||
#include "audio_defines.h"
|
||||
// #include "model_ids.h"
|
||||
// #include "mario_animation_ids.h"
|
||||
// #include "mario_geo_switch_case_ids.h"
|
||||
#include "surface_terrains.h"
|
||||
#include "macros.h"
|
||||
|
||||
// Crash handler enhancement
|
||||
#ifdef CRASH_SCREEN_INCLUDED
|
||||
#define DEBUG_ASSERT(exp) do { if (!(exp)) _n64_assert(__FILE__, __LINE__, #exp, 1); } while (0)
|
||||
#else
|
||||
#define DEBUG_ASSERT(exp)
|
||||
#endif
|
||||
|
||||
// Pointer casting is technically UB, and avoiding it gets rid of endian issues
|
||||
// as well as a nice side effect.
|
||||
#ifdef AVOID_UB
|
||||
#define GET_HIGH_U16_OF_32(var) ((u16)((var) >> 16))
|
||||
#define GET_HIGH_S16_OF_32(var) ((s16)((var) >> 16))
|
||||
#define GET_LOW_U16_OF_32(var) ((u16)((var) & 0xFFFF))
|
||||
#define GET_LOW_S16_OF_32(var) ((s16)((var) & 0xFFFF))
|
||||
#define SET_HIGH_U16_OF_32(var, x) ((var) = ((var) & 0xFFFF) | ((x) << 16))
|
||||
#define SET_HIGH_S16_OF_32(var, x) ((var) = ((var) & 0xFFFF) | ((x) << 16))
|
||||
#else
|
||||
#define GET_HIGH_U16_OF_32(var) (((u16 *)&(var))[0])
|
||||
#define GET_HIGH_S16_OF_32(var) (((s16 *)&(var))[0])
|
||||
#define GET_LOW_U16_OF_32(var) (((u16 *)&(var))[1])
|
||||
#define GET_LOW_S16_OF_32(var) (((s16 *)&(var))[1])
|
||||
#define SET_HIGH_U16_OF_32(var, x) ((((u16 *)&(var))[0]) = (x))
|
||||
#define SET_HIGH_S16_OF_32(var, x) ((((s16 *)&(var))[0]) = (x))
|
||||
#endif
|
||||
|
||||
// Layers
|
||||
#define LAYER_FORCE 0
|
||||
#define LAYER_OPAQUE 1
|
||||
#define LAYER_OPAQUE_DECAL 2
|
||||
#define LAYER_OPAQUE_INTER 3
|
||||
#define LAYER_ALPHA 4
|
||||
#define LAYER_TRANSPARENT 5
|
||||
#define LAYER_TRANSPARENT_DECAL 6
|
||||
#define LAYER_TRANSPARENT_INTER 7
|
||||
|
||||
#define INPUT_NONZERO_ANALOG 0x0001
|
||||
#define INPUT_A_PRESSED 0x0002
|
||||
#define INPUT_OFF_FLOOR 0x0004
|
||||
#define INPUT_ABOVE_SLIDE 0x0008
|
||||
#define INPUT_FIRST_PERSON 0x0010
|
||||
#define INPUT_UNKNOWN_5 0x0020
|
||||
#define INPUT_SQUISHED 0x0040
|
||||
#define INPUT_A_DOWN 0x0080
|
||||
#define INPUT_IN_POISON_GAS 0x0100
|
||||
#define INPUT_IN_WATER 0x0200
|
||||
#define INPUT_UNKNOWN_10 0x0400
|
||||
#define INPUT_INTERACT_OBJ_GRABBABLE 0x0800
|
||||
#define INPUT_UNKNOWN_12 0x1000
|
||||
#define INPUT_B_PRESSED 0x2000
|
||||
#define INPUT_Z_DOWN 0x4000
|
||||
#define INPUT_Z_PRESSED 0x8000
|
||||
|
||||
#define GROUND_STEP_LEFT_GROUND 0
|
||||
#define GROUND_STEP_NONE 1
|
||||
#define GROUND_STEP_HIT_WALL 2
|
||||
#define GROUND_STEP_HIT_WALL_STOP_QSTEPS 2
|
||||
#define GROUND_STEP_HIT_WALL_CONTINUE_QSTEPS 3
|
||||
|
||||
#define AIR_STEP_CHECK_LEDGE_GRAB 0x00000001
|
||||
#define AIR_STEP_CHECK_HANG 0x00000002
|
||||
|
||||
#define AIR_STEP_NONE 0
|
||||
#define AIR_STEP_LANDED 1
|
||||
#define AIR_STEP_HIT_WALL 2
|
||||
#define AIR_STEP_GRABBED_LEDGE 3
|
||||
#define AIR_STEP_GRABBED_CEILING 4
|
||||
#define AIR_STEP_HIT_LAVA_WALL 6
|
||||
|
||||
#define WATER_STEP_NONE 0
|
||||
#define WATER_STEP_HIT_FLOOR 1
|
||||
#define WATER_STEP_HIT_CEILING 2
|
||||
#define WATER_STEP_CANCELLED 3
|
||||
#define WATER_STEP_HIT_WALL 4
|
||||
|
||||
#define PARTICLE_DUST /* 0x00000001 */ (1 << 0)
|
||||
#define PARTICLE_VERTICAL_STAR /* 0x00000002 */ (1 << 1)
|
||||
#define PARTICLE_2 /* 0x00000004 */ (1 << 2)
|
||||
#define PARTICLE_SPARKLES /* 0x00000008 */ (1 << 3)
|
||||
#define PARTICLE_HORIZONTAL_STAR /* 0x00000010 */ (1 << 4)
|
||||
#define PARTICLE_BUBBLE /* 0x00000020 */ (1 << 5)
|
||||
#define PARTICLE_WATER_SPLASH /* 0x00000040 */ (1 << 6)
|
||||
#define PARTICLE_IDLE_WATER_WAVE /* 0x00000080 */ (1 << 7)
|
||||
#define PARTICLE_SHALLOW_WATER_WAVE /* 0x00000100 */ (1 << 8)
|
||||
#define PARTICLE_PLUNGE_BUBBLE /* 0x00000200 */ (1 << 9)
|
||||
#define PARTICLE_WAVE_TRAIL /* 0x00000400 */ (1 << 10)
|
||||
#define PARTICLE_FIRE /* 0x00000800 */ (1 << 11)
|
||||
#define PARTICLE_SHALLOW_WATER_SPLASH /* 0x00001000 */ (1 << 12)
|
||||
#define PARTICLE_LEAF /* 0x00002000 */ (1 << 13)
|
||||
#define PARTICLE_SNOW /* 0x00004000 */ (1 << 14)
|
||||
#define PARTICLE_DIRT /* 0x00008000 */ (1 << 15)
|
||||
#define PARTICLE_MIST_CIRCLE /* 0x00010000 */ (1 << 16)
|
||||
#define PARTICLE_BREATH /* 0x00020000 */ (1 << 17)
|
||||
#define PARTICLE_TRIANGLE /* 0x00040000 */ (1 << 18)
|
||||
#define PARTICLE_19 /* 0x00080000 */ (1 << 19)
|
||||
|
||||
#define MODEL_STATE_NOISE_ALPHA 0x180
|
||||
#define MODEL_STATE_METAL 0x200
|
||||
|
||||
#define MARIO_NORMAL_CAP 0x00000001
|
||||
#define MARIO_VANISH_CAP 0x00000002
|
||||
#define MARIO_METAL_CAP 0x00000004
|
||||
#define MARIO_WING_CAP 0x00000008
|
||||
#define MARIO_CAP_ON_HEAD 0x00000010
|
||||
#define MARIO_CAP_IN_HAND 0x00000020
|
||||
#define MARIO_METAL_SHOCK 0x00000040
|
||||
#define MARIO_TELEPORTING 0x00000080
|
||||
#define MARIO_UNKNOWN_08 0x00000100
|
||||
#define MARIO_UNKNOWN_13 0x00002000
|
||||
#define MARIO_ACTION_SOUND_PLAYED 0x00010000
|
||||
#define MARIO_MARIO_SOUND_PLAYED 0x00020000
|
||||
#define MARIO_UNKNOWN_18 0x00040000
|
||||
#define MARIO_PUNCHING 0x00100000
|
||||
#define MARIO_KICKING 0x00200000
|
||||
#define MARIO_TRIPPING 0x00400000
|
||||
#define MARIO_UNKNOWN_25 0x02000000
|
||||
#define MARIO_UNKNOWN_30 0x40000000
|
||||
#define MARIO_UNKNOWN_31 0x80000000
|
||||
|
||||
#define MARIO_SPECIAL_CAPS (MARIO_VANISH_CAP | MARIO_METAL_CAP | MARIO_WING_CAP)
|
||||
#define MARIO_CAPS (MARIO_NORMAL_CAP | MARIO_SPECIAL_CAPS)
|
||||
|
||||
#define ACT_ID_MASK 0x000001FF
|
||||
|
||||
#define ACT_GROUP_MASK 0x000001C0
|
||||
#define ACT_GROUP_STATIONARY /* 0x00000000 */ (0 << 6)
|
||||
#define ACT_GROUP_MOVING /* 0x00000040 */ (1 << 6)
|
||||
#define ACT_GROUP_AIRBORNE /* 0x00000080 */ (2 << 6)
|
||||
#define ACT_GROUP_SUBMERGED /* 0x000000C0 */ (3 << 6)
|
||||
#define ACT_GROUP_CUTSCENE /* 0x00000100 */ (4 << 6)
|
||||
#define ACT_GROUP_AUTOMATIC /* 0x00000140 */ (5 << 6)
|
||||
#define ACT_GROUP_OBJECT /* 0x00000180 */ (6 << 6)
|
||||
|
||||
#define ACT_FLAG_STATIONARY /* 0x00000200 */ (1 << 9)
|
||||
#define ACT_FLAG_MOVING /* 0x00000400 */ (1 << 10)
|
||||
#define ACT_FLAG_AIR /* 0x00000800 */ (1 << 11)
|
||||
#define ACT_FLAG_INTANGIBLE /* 0x00001000 */ (1 << 12)
|
||||
#define ACT_FLAG_SWIMMING /* 0x00002000 */ (1 << 13)
|
||||
#define ACT_FLAG_METAL_WATER /* 0x00004000 */ (1 << 14)
|
||||
#define ACT_FLAG_SHORT_HITBOX /* 0x00008000 */ (1 << 15)
|
||||
#define ACT_FLAG_RIDING_SHELL /* 0x00010000 */ (1 << 16)
|
||||
#define ACT_FLAG_INVULNERABLE /* 0x00020000 */ (1 << 17)
|
||||
#define ACT_FLAG_BUTT_OR_STOMACH_SLIDE /* 0x00040000 */ (1 << 18)
|
||||
#define ACT_FLAG_DIVING /* 0x00080000 */ (1 << 19)
|
||||
#define ACT_FLAG_ON_POLE /* 0x00100000 */ (1 << 20)
|
||||
#define ACT_FLAG_HANGING /* 0x00200000 */ (1 << 21)
|
||||
#define ACT_FLAG_IDLE /* 0x00400000 */ (1 << 22)
|
||||
#define ACT_FLAG_ATTACKING /* 0x00800000 */ (1 << 23)
|
||||
#define ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION /* 0x01000000 */ (1 << 24)
|
||||
#define ACT_FLAG_CONTROL_JUMP_HEIGHT /* 0x02000000 */ (1 << 25)
|
||||
#define ACT_FLAG_ALLOW_FIRST_PERSON /* 0x04000000 */ (1 << 26)
|
||||
#define ACT_FLAG_PAUSE_EXIT /* 0x08000000 */ (1 << 27)
|
||||
#define ACT_FLAG_SWIMMING_OR_FLYING /* 0x10000000 */ (1 << 28)
|
||||
#define ACT_FLAG_WATER_OR_TEXT /* 0x20000000 */ (1 << 29)
|
||||
#define ACT_FLAG_THROWING /* 0x80000000 */ (1 << 31)
|
||||
|
||||
#define ACT_UNINITIALIZED 0x00000000 // (0x000)
|
||||
|
||||
// group 0x000: stationary actions
|
||||
#define ACT_IDLE 0x0C400201 // (0x001 | ACT_FLAG_STATIONARY | ACT_FLAG_IDLE | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_START_SLEEPING 0x0C400202 // (0x002 | ACT_FLAG_STATIONARY | ACT_FLAG_IDLE | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_SLEEPING 0x0C000203 // (0x003 | ACT_FLAG_STATIONARY | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_WAKING_UP 0x0C000204 // (0x004 | ACT_FLAG_STATIONARY | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_PANTING 0x0C400205 // (0x005 | ACT_FLAG_STATIONARY | ACT_FLAG_IDLE | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_HOLD_PANTING_UNUSED 0x08000206 // (0x006 | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_HOLD_IDLE 0x08000207 // (0x007 | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_HOLD_HEAVY_IDLE 0x08000208 // (0x008 | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_STANDING_AGAINST_WALL 0x0C400209 // (0x009 | ACT_FLAG_STATIONARY | ACT_FLAG_IDLE | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_COUGHING 0x0C40020A // (0x00A | ACT_FLAG_STATIONARY | ACT_FLAG_IDLE | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_SHIVERING 0x0C40020B // (0x00B | ACT_FLAG_STATIONARY | ACT_FLAG_IDLE | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_IN_QUICKSAND 0x0002020D // (0x00D | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_UNKNOWN_0002020E 0x0002020E // (0x00E | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_CROUCHING 0x0C008220 // (0x020 | ACT_FLAG_STATIONARY | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_START_CROUCHING 0x0C008221 // (0x021 | ACT_FLAG_STATIONARY | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_STOP_CROUCHING 0x0C008222 // (0x022 | ACT_FLAG_STATIONARY | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_START_CRAWLING 0x0C008223 // (0x023 | ACT_FLAG_STATIONARY | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_STOP_CRAWLING 0x0C008224 // (0x024 | ACT_FLAG_STATIONARY | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_SLIDE_KICK_SLIDE_STOP 0x08000225 // (0x025 | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_SHOCKWAVE_BOUNCE 0x00020226 // (0x026 | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_FIRST_PERSON 0x0C000227 // (0x027 | ACT_FLAG_STATIONARY | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_BACKFLIP_LAND_STOP 0x0800022F // (0x02F | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_JUMP_LAND_STOP 0x0C000230 // (0x030 | ACT_FLAG_STATIONARY | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_DOUBLE_JUMP_LAND_STOP 0x0C000231 // (0x031 | ACT_FLAG_STATIONARY | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_FREEFALL_LAND_STOP 0x0C000232 // (0x032 | ACT_FLAG_STATIONARY | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_SIDE_FLIP_LAND_STOP 0x0C000233 // (0x033 | ACT_FLAG_STATIONARY | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_HOLD_JUMP_LAND_STOP 0x08000234 // (0x034 | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_HOLD_FREEFALL_LAND_STOP 0x08000235 // (0x035 | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_AIR_THROW_LAND 0x80000A36 // (0x036 | ACT_FLAG_STATIONARY | ACT_FLAG_AIR | ACT_FLAG_THROWING)
|
||||
#define ACT_TWIRL_LAND 0x18800238 // (0x038 | ACT_FLAG_STATIONARY | ACT_FLAG_ATTACKING | ACT_FLAG_PAUSE_EXIT | ACT_FLAG_SWIMMING_OR_FLYING)
|
||||
#define ACT_LAVA_BOOST_LAND 0x08000239 // (0x039 | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_TRIPLE_JUMP_LAND_STOP 0x0800023A // (0x03A | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_LONG_JUMP_LAND_STOP 0x0800023B // (0x03B | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_GROUND_POUND_LAND 0x0080023C // (0x03C | ACT_FLAG_STATIONARY | ACT_FLAG_ATTACKING)
|
||||
#define ACT_BRAKING_STOP 0x0C00023D // (0x03D | ACT_FLAG_STATIONARY | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_BUTT_SLIDE_STOP 0x0C00023E // (0x03E | ACT_FLAG_STATIONARY | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_HOLD_BUTT_SLIDE_STOP 0x0800043F // (0x03F | ACT_FLAG_MOVING | ACT_FLAG_PAUSE_EXIT)
|
||||
|
||||
// group 0x040: moving (ground) actions
|
||||
#define ACT_WALKING 0x04000440 // (0x040 | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_HOLD_WALKING 0x00000442 // (0x042 | ACT_FLAG_MOVING)
|
||||
#define ACT_TURNING_AROUND 0x00000443 // (0x043 | ACT_FLAG_MOVING)
|
||||
#define ACT_FINISH_TURNING_AROUND 0x00000444 // (0x044 | ACT_FLAG_MOVING)
|
||||
#define ACT_BRAKING 0x04000445 // (0x045 | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_RIDING_SHELL_GROUND 0x20810446 // (0x046 | ACT_FLAG_MOVING | ACT_FLAG_RIDING_SHELL | ACT_FLAG_ATTACKING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_HOLD_HEAVY_WALKING 0x00000447 // (0x047 | ACT_FLAG_MOVING)
|
||||
#define ACT_CRAWLING 0x04008448 // (0x048 | ACT_FLAG_MOVING | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_BURNING_GROUND 0x00020449 // (0x049 | ACT_FLAG_MOVING | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_DECELERATING 0x0400044A // (0x04A | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_HOLD_DECELERATING 0x0000044B // (0x04B | ACT_FLAG_MOVING)
|
||||
#define ACT_BEGIN_SLIDING 0x00000050 // (0x050)
|
||||
#define ACT_HOLD_BEGIN_SLIDING 0x00000051 // (0x051)
|
||||
#define ACT_BUTT_SLIDE 0x00840452 // (0x052 | ACT_FLAG_MOVING | ACT_FLAG_BUTT_OR_STOMACH_SLIDE | ACT_FLAG_ATTACKING)
|
||||
#define ACT_STOMACH_SLIDE 0x008C0453 // (0x053 | ACT_FLAG_MOVING | ACT_FLAG_BUTT_OR_STOMACH_SLIDE | ACT_FLAG_DIVING | ACT_FLAG_ATTACKING)
|
||||
#define ACT_HOLD_BUTT_SLIDE 0x00840454 // (0x054 | ACT_FLAG_MOVING | ACT_FLAG_BUTT_OR_STOMACH_SLIDE | ACT_FLAG_ATTACKING)
|
||||
#define ACT_HOLD_STOMACH_SLIDE 0x008C0455 // (0x055 | ACT_FLAG_MOVING | ACT_FLAG_BUTT_OR_STOMACH_SLIDE | ACT_FLAG_DIVING | ACT_FLAG_ATTACKING)
|
||||
#define ACT_DIVE_SLIDE 0x00880456 // (0x056 | ACT_FLAG_MOVING | ACT_FLAG_DIVING | ACT_FLAG_ATTACKING)
|
||||
#define ACT_MOVE_PUNCHING 0x00800457 // (0x057 | ACT_FLAG_MOVING | ACT_FLAG_ATTACKING)
|
||||
#define ACT_CROUCH_SLIDE 0x04808459 // (0x059 | ACT_FLAG_MOVING | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ATTACKING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_SLIDE_KICK_SLIDE 0x0080045A // (0x05A | ACT_FLAG_MOVING | ACT_FLAG_ATTACKING)
|
||||
#define ACT_HARD_BACKWARD_GROUND_KB 0x00020460 // (0x060 | ACT_FLAG_MOVING | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_HARD_FORWARD_GROUND_KB 0x00020461 // (0x061 | ACT_FLAG_MOVING | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_BACKWARD_GROUND_KB 0x00020462 // (0x062 | ACT_FLAG_MOVING | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_FORWARD_GROUND_KB 0x00020463 // (0x063 | ACT_FLAG_MOVING | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_SOFT_BACKWARD_GROUND_KB 0x00020464 // (0x064 | ACT_FLAG_MOVING | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_SOFT_FORWARD_GROUND_KB 0x00020465 // (0x065 | ACT_FLAG_MOVING | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_GROUND_BONK 0x00020466 // (0x066 | ACT_FLAG_MOVING | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_DEATH_EXIT_LAND 0x00020467 // (0x067 | ACT_FLAG_MOVING | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_JUMP_LAND 0x04000470 // (0x070 | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_FREEFALL_LAND 0x04000471 // (0x071 | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_DOUBLE_JUMP_LAND 0x04000472 // (0x072 | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_SIDE_FLIP_LAND 0x04000473 // (0x073 | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_HOLD_JUMP_LAND 0x00000474 // (0x074 | ACT_FLAG_MOVING)
|
||||
#define ACT_HOLD_FREEFALL_LAND 0x00000475 // (0x075 | ACT_FLAG_MOVING)
|
||||
#define ACT_QUICKSAND_JUMP_LAND 0x00000476 // (0x076 | ACT_FLAG_MOVING)
|
||||
#define ACT_HOLD_QUICKSAND_JUMP_LAND 0x00000477 // (0x077 | ACT_FLAG_MOVING)
|
||||
#define ACT_TRIPLE_JUMP_LAND 0x04000478 // (0x078 | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_LONG_JUMP_LAND 0x00000479 // (0x079 | ACT_FLAG_MOVING)
|
||||
#define ACT_BACKFLIP_LAND 0x0400047A // (0x07A | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
|
||||
// group 0x080: airborne actions
|
||||
#define ACT_JUMP 0x03000880 // (0x080 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_DOUBLE_JUMP 0x03000881 // (0x081 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_TRIPLE_JUMP 0x01000882 // (0x082 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_BACKFLIP 0x01000883 // (0x083 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_STEEP_JUMP 0x03000885 // (0x085 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_WALL_KICK_AIR 0x03000886 // (0x086 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_SIDE_FLIP 0x01000887 // (0x087 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_LONG_JUMP 0x03000888 // (0x088 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_WATER_JUMP 0x01000889 // (0x089 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_DIVE 0x0188088A // (0x08A | ACT_FLAG_AIR | ACT_FLAG_DIVING | ACT_FLAG_ATTACKING | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_FREEFALL 0x0100088C // (0x08C | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_TOP_OF_POLE_JUMP 0x0300088D // (0x08D | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_BUTT_SLIDE_AIR 0x0300088E // (0x08E | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_FLYING_TRIPLE_JUMP 0x03000894 // (0x094 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_SHOT_FROM_CANNON 0x00880898 // (0x098 | ACT_FLAG_AIR | ACT_FLAG_DIVING | ACT_FLAG_ATTACKING)
|
||||
#define ACT_FLYING 0x10880899 // (0x099 | ACT_FLAG_AIR | ACT_FLAG_DIVING | ACT_FLAG_ATTACKING | ACT_FLAG_SWIMMING_OR_FLYING)
|
||||
#define ACT_RIDING_SHELL_JUMP 0x0281089A // (0x09A | ACT_FLAG_AIR | ACT_FLAG_RIDING_SHELL | ACT_FLAG_ATTACKING | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_RIDING_SHELL_FALL 0x0081089B // (0x09B | ACT_FLAG_AIR | ACT_FLAG_RIDING_SHELL | ACT_FLAG_ATTACKING)
|
||||
#define ACT_VERTICAL_WIND 0x1008089C // (0x09C | ACT_FLAG_AIR | ACT_FLAG_DIVING | ACT_FLAG_SWIMMING_OR_FLYING)
|
||||
#define ACT_HOLD_JUMP 0x030008A0 // (0x0A0 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_HOLD_FREEFALL 0x010008A1 // (0x0A1 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_HOLD_BUTT_SLIDE_AIR 0x010008A2 // (0x0A2 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_HOLD_WATER_JUMP 0x010008A3 // (0x0A3 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_TWIRLING 0x108008A4 // (0x0A4 | ACT_FLAG_AIR | ACT_FLAG_ATTACKING | ACT_FLAG_SWIMMING_OR_FLYING)
|
||||
#define ACT_FORWARD_ROLLOUT 0x010008A6 // (0x0A6 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_AIR_HIT_WALL 0x000008A7 // (0x0A7 | ACT_FLAG_AIR)
|
||||
#define ACT_RIDING_HOOT 0x000004A8 // (0x0A8 | ACT_FLAG_MOVING)
|
||||
#define ACT_GROUND_POUND 0x008008A9 // (0x0A9 | ACT_FLAG_AIR | ACT_FLAG_ATTACKING)
|
||||
#define ACT_SLIDE_KICK 0x018008AA // (0x0AA | ACT_FLAG_AIR | ACT_FLAG_ATTACKING | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_AIR_THROW 0x830008AB // (0x0AB | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT | ACT_FLAG_THROWING)
|
||||
#define ACT_JUMP_KICK 0x018008AC // (0x0AC | ACT_FLAG_AIR | ACT_FLAG_ATTACKING | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_BACKWARD_ROLLOUT 0x010008AD // (0x0AD | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_CRAZY_BOX_BOUNCE 0x000008AE // (0x0AE | ACT_FLAG_AIR)
|
||||
#define ACT_SPECIAL_TRIPLE_JUMP 0x030008AF // (0x0AF | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION | ACT_FLAG_CONTROL_JUMP_HEIGHT)
|
||||
#define ACT_BACKWARD_AIR_KB 0x010208B0 // (0x0B0 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_FORWARD_AIR_KB 0x010208B1 // (0x0B1 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_HARD_FORWARD_AIR_KB 0x010208B2 // (0x0B2 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_HARD_BACKWARD_AIR_KB 0x010208B3 // (0x0B3 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_BURNING_JUMP 0x010208B4 // (0x0B4 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_BURNING_FALL 0x010208B5 // (0x0B5 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_SOFT_BONK 0x010208B6 // (0x0B6 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_LAVA_BOOST 0x010208B7 // (0x0B7 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_GETTING_BLOWN 0x010208B8 // (0x0B8 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_THROWN_FORWARD 0x010208BD // (0x0BD | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_THROWN_BACKWARD 0x010208BE // (0x0BE | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
|
||||
// group 0x0C0: submerged actions
|
||||
#define ACT_WATER_IDLE 0x380022C0 // (0x0C0 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_PAUSE_EXIT | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_HOLD_WATER_IDLE 0x380022C1 // (0x0C1 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_PAUSE_EXIT | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_WATER_ACTION_END 0x300022C2 // (0x0C2 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_HOLD_WATER_ACTION_END 0x300022C3 // (0x0C3 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_DROWNING 0x300032C4 // (0x0C4 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_BACKWARD_WATER_KB 0x300222C5 // (0x0C5 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_INVULNERABLE | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_FORWARD_WATER_KB 0x300222C6 // (0x0C6 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_INVULNERABLE | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_WATER_DEATH 0x300032C7 // (0x0C7 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_WATER_SHOCKED 0x300222C8 // (0x0C8 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_INVULNERABLE | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_BREASTSTROKE 0x300024D0 // (0x0D0 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_SWIMMING_END 0x300024D1 // (0x0D1 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_FLUTTER_KICK 0x300024D2 // (0x0D2 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_HOLD_BREASTSTROKE 0x300024D3 // (0x0D3 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_HOLD_SWIMMING_END 0x300024D4 // (0x0D4 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_HOLD_FLUTTER_KICK 0x300024D5 // (0x0D5 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_WATER_SHELL_SWIMMING 0x300024D6 // (0x0D6 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_WATER_THROW 0x300024E0 // (0x0E0 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_WATER_PUNCH 0x300024E1 // (0x0E1 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_WATER_PLUNGE 0x300022E2 // (0x0E2 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_CAUGHT_IN_WHIRLPOOL 0x300222E3 // (0x0E3 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_INVULNERABLE | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_METAL_WATER_STANDING 0x080042F0 // (0x0F0 | ACT_FLAG_STATIONARY | ACT_FLAG_METAL_WATER | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_HOLD_METAL_WATER_STANDING 0x080042F1 // (0x0F1 | ACT_FLAG_STATIONARY | ACT_FLAG_METAL_WATER | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_METAL_WATER_WALKING 0x000044F2 // (0x0F2 | ACT_FLAG_MOVING | ACT_FLAG_METAL_WATER)
|
||||
#define ACT_HOLD_METAL_WATER_WALKING 0x000044F3 // (0x0F3 | ACT_FLAG_MOVING | ACT_FLAG_METAL_WATER)
|
||||
#define ACT_METAL_WATER_FALLING 0x000042F4 // (0x0F4 | ACT_FLAG_STATIONARY | ACT_FLAG_METAL_WATER)
|
||||
#define ACT_HOLD_METAL_WATER_FALLING 0x000042F5 // (0x0F5 | ACT_FLAG_STATIONARY | ACT_FLAG_METAL_WATER)
|
||||
#define ACT_METAL_WATER_FALL_LAND 0x000042F6 // (0x0F6 | ACT_FLAG_STATIONARY | ACT_FLAG_METAL_WATER)
|
||||
#define ACT_HOLD_METAL_WATER_FALL_LAND 0x000042F7 // (0x0F7 | ACT_FLAG_STATIONARY | ACT_FLAG_METAL_WATER)
|
||||
#define ACT_METAL_WATER_JUMP 0x000044F8 // (0x0F8 | ACT_FLAG_MOVING | ACT_FLAG_METAL_WATER)
|
||||
#define ACT_HOLD_METAL_WATER_JUMP 0x000044F9 // (0x0F9 | ACT_FLAG_MOVING | ACT_FLAG_METAL_WATER)
|
||||
#define ACT_METAL_WATER_JUMP_LAND 0x000044FA // (0x0FA | ACT_FLAG_MOVING | ACT_FLAG_METAL_WATER)
|
||||
#define ACT_HOLD_METAL_WATER_JUMP_LAND 0x000044FB // (0x0FB | ACT_FLAG_MOVING | ACT_FLAG_METAL_WATER)
|
||||
|
||||
// group 0x100: cutscene actions
|
||||
#define ACT_DISAPPEARED 0x00001300 // (0x100 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_INTRO_CUTSCENE 0x04001301 // (0x101 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_ALLOW_FIRST_PERSON)
|
||||
#define ACT_STAR_DANCE_EXIT 0x00001302 // (0x102 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_STAR_DANCE_WATER 0x00001303 // (0x103 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_FALL_AFTER_STAR_GRAB 0x00001904 // (0x104 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_READING_AUTOMATIC_DIALOG 0x20001305 // (0x105 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_READING_NPC_DIALOG 0x20001306 // (0x106 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_WATER_OR_TEXT)
|
||||
#define ACT_STAR_DANCE_NO_EXIT 0x00001307 // (0x107 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_READING_SIGN 0x00001308 // (0x108 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_JUMBO_STAR_CUTSCENE 0x00001909 // (0x109 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_WAITING_FOR_DIALOG 0x0000130A // (0x10A | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_DEBUG_FREE_MOVE 0x0000130F // (0x10F | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_STANDING_DEATH 0x00021311 // (0x111 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_QUICKSAND_DEATH 0x00021312 // (0x112 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_ELECTROCUTION 0x00021313 // (0x113 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_SUFFOCATION 0x00021314 // (0x114 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_DEATH_ON_STOMACH 0x00021315 // (0x115 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_DEATH_ON_BACK 0x00021316 // (0x116 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_EATEN_BY_BUBBA 0x00021317 // (0x117 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_END_PEACH_CUTSCENE 0x00001918 // (0x118 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_CREDITS_CUTSCENE 0x00001319 // (0x119 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_END_WAVING_CUTSCENE 0x0000131A // (0x11A | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_PULLING_DOOR 0x00001320 // (0x120 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_PUSHING_DOOR 0x00001321 // (0x121 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_WARP_DOOR_SPAWN 0x00001322 // (0x122 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_EMERGE_FROM_PIPE 0x00001923 // (0x123 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_SPAWN_SPIN_AIRBORNE 0x00001924 // (0x124 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_SPAWN_SPIN_LANDING 0x00001325 // (0x125 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_EXIT_AIRBORNE 0x00001926 // (0x126 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_EXIT_LAND_SAVE_DIALOG 0x00001327 // (0x127 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_DEATH_EXIT 0x00001928 // (0x128 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_UNUSED_DEATH_EXIT 0x00001929 // (0x129 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_FALLING_DEATH_EXIT 0x0000192A // (0x12A | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_SPECIAL_EXIT_AIRBORNE 0x0000192B // (0x12B | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_SPECIAL_DEATH_EXIT 0x0000192C // (0x12C | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_FALLING_EXIT_AIRBORNE 0x0000192D // (0x12D | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_UNLOCKING_KEY_DOOR 0x0000132E // (0x12E | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_UNLOCKING_STAR_DOOR 0x0000132F // (0x12F | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_ENTERING_STAR_DOOR 0x00001331 // (0x131 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_SPAWN_NO_SPIN_AIRBORNE 0x00001932 // (0x132 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_SPAWN_NO_SPIN_LANDING 0x00001333 // (0x133 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_BBH_ENTER_JUMP 0x00001934 // (0x134 | ACT_FLAG_AIR | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_BBH_ENTER_SPIN 0x00001535 // (0x135 | ACT_FLAG_MOVING | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_TELEPORT_FADE_OUT 0x00001336 // (0x136 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_TELEPORT_FADE_IN 0x00001337 // (0x137 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_SHOCKED 0x00020338 // (0x138 | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_SQUISHED 0x00020339 // (0x139 | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_HEAD_STUCK_IN_GROUND 0x0002033A // (0x13A | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_BUTT_STUCK_IN_GROUND 0x0002033B // (0x13B | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_FEET_STUCK_IN_GROUND 0x0002033C // (0x13C | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_PUTTING_ON_CAP 0x0000133D // (0x13D | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
|
||||
// group 0x140: "automatic" actions
|
||||
#define ACT_HOLDING_POLE 0x08100340 // (0x140 | ACT_FLAG_STATIONARY | ACT_FLAG_ON_POLE | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_GRAB_POLE_SLOW 0x00100341 // (0x141 | ACT_FLAG_STATIONARY | ACT_FLAG_ON_POLE)
|
||||
#define ACT_GRAB_POLE_FAST 0x00100342 // (0x142 | ACT_FLAG_STATIONARY | ACT_FLAG_ON_POLE)
|
||||
#define ACT_CLIMBING_POLE 0x00100343 // (0x143 | ACT_FLAG_STATIONARY | ACT_FLAG_ON_POLE)
|
||||
#define ACT_TOP_OF_POLE_TRANSITION 0x00100344 // (0x144 | ACT_FLAG_STATIONARY | ACT_FLAG_ON_POLE)
|
||||
#define ACT_TOP_OF_POLE 0x00100345 // (0x145 | ACT_FLAG_STATIONARY | ACT_FLAG_ON_POLE)
|
||||
#define ACT_START_HANGING 0x08200348 // (0x148 | ACT_FLAG_STATIONARY | ACT_FLAG_HANGING | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_HANGING 0x00200349 // (0x149 | ACT_FLAG_STATIONARY | ACT_FLAG_HANGING)
|
||||
#define ACT_HANG_MOVING 0x0020054A // (0x14A | ACT_FLAG_MOVING | ACT_FLAG_HANGING)
|
||||
#define ACT_LEDGE_GRAB 0x0800034B // (0x14B | ACT_FLAG_STATIONARY | ACT_FLAG_PAUSE_EXIT)
|
||||
#define ACT_LEDGE_CLIMB_SLOW_1 0x0000054C // (0x14C | ACT_FLAG_MOVING)
|
||||
#define ACT_LEDGE_CLIMB_SLOW_2 0x0000054D // (0x14D | ACT_FLAG_MOVING)
|
||||
#define ACT_LEDGE_CLIMB_DOWN 0x0000054E // (0x14E | ACT_FLAG_MOVING)
|
||||
#define ACT_LEDGE_CLIMB_FAST 0x0000054F // (0x14F | ACT_FLAG_MOVING)
|
||||
#define ACT_GRABBED 0x00020370 // (0x170 | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_IN_CANNON 0x00001371 // (0x171 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_TORNADO_TWIRLING 0x10020372 // (0x172 | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE | ACT_FLAG_SWIMMING_OR_FLYING)
|
||||
|
||||
// group 0x180: object actions
|
||||
#define ACT_PUNCHING 0x00800380 // (0x180 | ACT_FLAG_STATIONARY | ACT_FLAG_ATTACKING)
|
||||
#define ACT_PICKING_UP 0x00000383 // (0x183 | ACT_FLAG_STATIONARY)
|
||||
#define ACT_DIVE_PICKING_UP 0x00000385 // (0x185 | ACT_FLAG_STATIONARY)
|
||||
#define ACT_STOMACH_SLIDE_STOP 0x00000386 // (0x186 | ACT_FLAG_STATIONARY)
|
||||
#define ACT_PLACING_DOWN 0x00000387 // (0x187 | ACT_FLAG_STATIONARY)
|
||||
#define ACT_THROWING 0x80000588 // (0x188 | ACT_FLAG_MOVING | ACT_FLAG_THROWING)
|
||||
#define ACT_HEAVY_THROW 0x80000589 // (0x189 | ACT_FLAG_MOVING | ACT_FLAG_THROWING)
|
||||
#define ACT_PICKING_UP_BOWSER 0x00000390 // (0x190 | ACT_FLAG_STATIONARY)
|
||||
#define ACT_HOLDING_BOWSER 0x00000391 // (0x191 | ACT_FLAG_STATIONARY)
|
||||
#define ACT_RELEASING_BOWSER 0x00000392 // (0x192 | ACT_FLAG_STATIONARY)
|
||||
|
||||
/*
|
||||
this input mask is unused by the controller,
|
||||
but END_DEMO is used internally to signal
|
||||
the demo to end. This button cannot
|
||||
be pressed normally by a controller.
|
||||
*/
|
||||
#define END_DEMO (1 << 7)
|
||||
|
||||
#define VALID_BUTTONS (A_BUTTON | B_BUTTON | Z_TRIG | START_BUTTON | \
|
||||
U_JPAD | D_JPAD | L_JPAD | R_JPAD | \
|
||||
L_TRIG | R_TRIG | \
|
||||
U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS )
|
||||
|
||||
#define C_BUTTONS (U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS )
|
||||
|
||||
#endif // SM64_H
|
||||
@@ -0,0 +1,93 @@
|
||||
#ifndef SPECIAL_PRESET_NAMES_H
|
||||
#define SPECIAL_PRESET_NAMES_H
|
||||
|
||||
enum SpecialPresets {
|
||||
special_null_start,
|
||||
special_yellow_coin,
|
||||
special_yellow_coin_2,
|
||||
special_unknown_3,
|
||||
special_boo,
|
||||
special_unknown_5,
|
||||
special_lll_moving_octagonal_mesh_platform,
|
||||
special_snow_ball,
|
||||
special_lll_drawbridge_spawner,
|
||||
special_empty_9,
|
||||
special_lll_rotating_block_with_fire_bars,
|
||||
special_lll_floating_wood_bridge,
|
||||
special_tumbling_platform,
|
||||
special_lll_rotating_hexagonal_ring,
|
||||
special_lll_sinking_rectangular_platform,
|
||||
special_lll_sinking_square_platforms,
|
||||
special_lll_tilting_square_platform,
|
||||
special_lll_bowser_puzzle,
|
||||
special_mr_i,
|
||||
special_small_bully,
|
||||
special_big_bully,
|
||||
special_empty_21,
|
||||
special_empty_22,
|
||||
special_empty_23,
|
||||
special_empty_24,
|
||||
special_empty_25,
|
||||
special_moving_blue_coin,
|
||||
special_jrb_chest,
|
||||
special_water_ring,
|
||||
special_mine,
|
||||
special_empty_30,
|
||||
special_empty_31,
|
||||
special_butterfly,
|
||||
special_bowser,
|
||||
special_wf_rotating_wooden_platform,
|
||||
special_small_bomp,
|
||||
special_wf_sliding_platform,
|
||||
special_tower_platform_group,
|
||||
special_rotating_counter_clockwise,
|
||||
special_wf_tumbling_bridge,
|
||||
special_large_bomp,
|
||||
|
||||
special_level_geo_03 = 0x65,
|
||||
special_level_geo_04,
|
||||
special_level_geo_05,
|
||||
special_level_geo_06,
|
||||
special_level_geo_07,
|
||||
special_level_geo_08,
|
||||
special_level_geo_09,
|
||||
special_level_geo_0A,
|
||||
special_level_geo_0B,
|
||||
special_level_geo_0C,
|
||||
special_level_geo_0D,
|
||||
special_level_geo_0E,
|
||||
special_level_geo_0F,
|
||||
special_level_geo_10,
|
||||
special_level_geo_11,
|
||||
special_level_geo_12,
|
||||
special_level_geo_13,
|
||||
special_level_geo_14,
|
||||
special_level_geo_15,
|
||||
special_level_geo_16,
|
||||
special_bubble_tree,
|
||||
special_spiky_tree,
|
||||
special_snow_tree,
|
||||
special_unknown_tree,
|
||||
special_palm_tree,
|
||||
special_wooden_door,
|
||||
special_haunted_door = special_wooden_door,
|
||||
special_unknown_door,
|
||||
special_metal_door,
|
||||
special_hmc_door,
|
||||
special_unknown2_door,
|
||||
special_wooden_door_warp,
|
||||
special_unknown1_door_warp,
|
||||
special_metal_door_warp,
|
||||
special_unknown2_door_warp,
|
||||
special_unknown3_door_warp,
|
||||
special_castle_door_warp,
|
||||
special_castle_door,
|
||||
special_0stars_door,
|
||||
special_1star_door,
|
||||
special_3star_door,
|
||||
special_key_door,
|
||||
|
||||
special_null_end = 0xFF
|
||||
};
|
||||
|
||||
#endif // SPECIAL_PRESET_NAMES_H
|
||||
@@ -0,0 +1,223 @@
|
||||
#ifndef SURFACE_TERRAINS_H
|
||||
#define SURFACE_TERRAINS_H
|
||||
|
||||
// Surface Types
|
||||
#define SURFACE_DEFAULT 0x0000 // Environment default
|
||||
#define SURFACE_BURNING 0x0001 // Lava / Frostbite (in SL), but is used mostly for Lava
|
||||
#define SURFACE_0004 0x0004 // Unused, has no function and has parameters
|
||||
#define SURFACE_HANGABLE 0x0005 // Ceiling that Mario can climb on
|
||||
#define SURFACE_SLOW 0x0009 // Slow down Mario, unused
|
||||
#define SURFACE_DEATH_PLANE 0x000A // Death floor
|
||||
#define SURFACE_CLOSE_CAMERA 0x000B // Close camera
|
||||
#define SURFACE_WATER 0x000D // Water, has no action, used on some waterboxes below
|
||||
#define SURFACE_FLOWING_WATER 0x000E // Water (flowing), has parameters
|
||||
#define SURFACE_INTANGIBLE 0x0012 // Intangible (Separates BBH mansion from merry-go-round, for room usage)
|
||||
#define SURFACE_VERY_SLIPPERY 0x0013 // Very slippery, mostly used for slides
|
||||
#define SURFACE_SLIPPERY 0x0014 // Slippery
|
||||
#define SURFACE_NOT_SLIPPERY 0x0015 // Non-slippery, climbable
|
||||
#define SURFACE_TTM_VINES 0x0016 // TTM vines, has no action defined
|
||||
#define SURFACE_MGR_MUSIC 0x001A // Plays the Merry go round music, see handle_merry_go_round_music in bbh_merry_go_round.inc.c for more details
|
||||
#define SURFACE_INSTANT_WARP_1B 0x001B // Instant warp to another area, used to warp between areas in WDW and the endless stairs to warp back
|
||||
#define SURFACE_INSTANT_WARP_1C 0x001C // Instant warp to another area, used to warp between areas in WDW
|
||||
#define SURFACE_INSTANT_WARP_1D 0x001D // Instant warp to another area, used to warp between areas in DDD, SSL and TTM
|
||||
#define SURFACE_INSTANT_WARP_1E 0x001E // Instant warp to another area, used to warp between areas in DDD, SSL and TTM
|
||||
#define SURFACE_SHALLOW_QUICKSAND 0x0021 // Shallow Quicksand (depth of 10 units)
|
||||
#define SURFACE_DEEP_QUICKSAND 0x0022 // Quicksand (lethal, slow, depth of 160 units)
|
||||
#define SURFACE_INSTANT_QUICKSAND 0x0023 // Quicksand (lethal, instant)
|
||||
#define SURFACE_DEEP_MOVING_QUICKSAND 0x0024 // Moving quicksand (flowing, depth of 160 units)
|
||||
#define SURFACE_SHALLOW_MOVING_QUICKSAND 0x0025 // Moving quicksand (flowing, depth of 25 units)
|
||||
#define SURFACE_QUICKSAND 0x0026 // Moving quicksand (60 units)
|
||||
#define SURFACE_MOVING_QUICKSAND 0x0027 // Moving quicksand (flowing, depth of 60 units)
|
||||
#define SURFACE_WALL_MISC 0x0028 // Used for some walls, Cannon to adjust the camera, and some objects like Warp Pipe
|
||||
#define SURFACE_NOISE_DEFAULT 0x0029 // Default floor with noise
|
||||
#define SURFACE_NOISE_SLIPPERY 0x002A // Slippery floor with noise
|
||||
#define SURFACE_HORIZONTAL_WIND 0x002C // Horizontal wind, has parameters
|
||||
#define SURFACE_INSTANT_MOVING_QUICKSAND 0x002D // Quicksand (lethal, flowing)
|
||||
#define SURFACE_ICE 0x002E // Slippery Ice, in snow levels and THI's water floor
|
||||
#define SURFACE_LOOK_UP_WARP 0x002F // Look up and warp (Wing cap entrance)
|
||||
#define SURFACE_HARD 0x0030 // Hard floor (Always has fall damage)
|
||||
#define SURFACE_WARP 0x0032 // Surface warp
|
||||
#define SURFACE_TIMER_START 0x0033 // Timer start (Peach's secret slide)
|
||||
#define SURFACE_TIMER_END 0x0034 // Timer stop (Peach's secret slide)
|
||||
#define SURFACE_HARD_SLIPPERY 0x0035 // Hard and slippery (Always has fall damage)
|
||||
#define SURFACE_HARD_VERY_SLIPPERY 0x0036 // Hard and very slippery (Always has fall damage)
|
||||
#define SURFACE_HARD_NOT_SLIPPERY 0x0037 // Hard and Non-slippery (Always has fall damage)
|
||||
#define SURFACE_VERTICAL_WIND 0x0038 // Death at bottom with vertical wind
|
||||
#define SURFACE_BOSS_FIGHT_CAMERA 0x0065 // Wide camera for BOB and WF bosses
|
||||
#define SURFACE_CAMERA_FREE_ROAM 0x0066 // Free roam camera for THI and TTC
|
||||
#define SURFACE_THI3_WALLKICK 0x0068 // Surface where there's a wall kick section in THI 3rd area, has no action defined
|
||||
#define SURFACE_CAMERA_8_DIR 0x0069 // Surface that enables far camera for platforms, used in THI
|
||||
#define SURFACE_CAMERA_MIDDLE 0x006E // Surface camera that returns to the middle, used on the 4 pillars of SSL
|
||||
#define SURFACE_CAMERA_ROTATE_RIGHT 0x006F // Surface camera that rotates to the right (Bowser 1 & THI)
|
||||
#define SURFACE_CAMERA_ROTATE_LEFT 0x0070 // Surface camera that rotates to the left (BOB & TTM)
|
||||
#define SURFACE_CAMERA_BOUNDARY 0x0072 // Intangible Area, only used to restrict camera movement
|
||||
#define SURFACE_NOISE_VERY_SLIPPERY_73 0x0073 // Very slippery floor with noise, unused
|
||||
#define SURFACE_NOISE_VERY_SLIPPERY_74 0x0074 // Very slippery floor with noise, unused
|
||||
#define SURFACE_NOISE_VERY_SLIPPERY 0x0075 // Very slippery floor with noise, used in CCM
|
||||
#define SURFACE_NO_CAM_COLLISION 0x0076 // Surface with no cam collision flag
|
||||
#define SURFACE_NO_CAM_COLLISION_77 0x0077 // Surface with no cam collision flag, unused
|
||||
#define SURFACE_NO_CAM_COL_VERY_SLIPPERY 0x0078 // Surface with no cam collision flag, very slippery with noise (THI)
|
||||
#define SURFACE_NO_CAM_COL_SLIPPERY 0x0079 // Surface with no cam collision flag, slippery with noise (CCM, PSS and TTM slides)
|
||||
#define SURFACE_SWITCH 0x007A // Surface with no cam collision flag, non-slippery with noise, used by switches and Dorrie
|
||||
#define SURFACE_VANISH_CAP_WALLS 0x007B // Vanish cap walls, pass through them with Vanish Cap
|
||||
#define SURFACE_PAINTING_WOBBLE_A6 0x00A6 // Painting wobble (BOB Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_A7 0x00A7 // Painting wobble (BOB Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_A8 0x00A8 // Painting wobble (BOB Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_A9 0x00A9 // Painting wobble (CCM Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_AA 0x00AA // Painting wobble (CCM Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_AB 0x00AB // Painting wobble (CCM Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_AC 0x00AC // Painting wobble (WF Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_AD 0x00AD // Painting wobble (WF Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_AE 0x00AE // Painting wobble (WF Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_AF 0x00AF // Painting wobble (JRB Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_B0 0x00B0 // Painting wobble (JRB Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_B1 0x00B1 // Painting wobble (JRB Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_B2 0x00B2 // Painting wobble (LLL Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_B3 0x00B3 // Painting wobble (LLL Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_B4 0x00B4 // Painting wobble (LLL Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_B5 0x00B5 // Painting wobble (SSL Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_B6 0x00B6 // Painting wobble (SSL Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_B7 0x00B7 // Painting wobble (SSL Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_B8 0x00B8 // Painting wobble (Unused - Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_B9 0x00B9 // Painting wobble (Unused - Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_BA 0x00BA // Painting wobble (Unused - Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_BB 0x00BB // Painting wobble (DDD - Left), makes the painting wobble if touched
|
||||
#define SURFACE_PAINTING_WOBBLE_BC 0x00BC // Painting wobble (Unused, DDD - Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_BD 0x00BD // Painting wobble (Unused, DDD - Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_BE 0x00BE // Painting wobble (WDW Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_BF 0x00BF // Painting wobble (WDW Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_C0 0x00C0 // Painting wobble (WDW Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_C1 0x00C1 // Painting wobble (THI Tiny - Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_C2 0x00C2 // Painting wobble (THI Tiny - Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_C3 0x00C3 // Painting wobble (THI Tiny - Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_C4 0x00C4 // Painting wobble (TTM Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_C5 0x00C5 // Painting wobble (TTM Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_C6 0x00C6 // Painting wobble (TTM Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_C7 0x00C7 // Painting wobble (Unused, TTC - Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_C8 0x00C8 // Painting wobble (Unused, TTC - Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_C9 0x00C9 // Painting wobble (Unused, TTC - Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_CA 0x00CA // Painting wobble (Unused, SL - Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_CB 0x00CB // Painting wobble (Unused, SL - Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_CC 0x00CC // Painting wobble (Unused, SL - Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_CD 0x00CD // Painting wobble (THI Huge - Left)
|
||||
#define SURFACE_PAINTING_WOBBLE_CE 0x00CE // Painting wobble (THI Huge - Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_CF 0x00CF // Painting wobble (THI Huge - Right)
|
||||
#define SURFACE_PAINTING_WOBBLE_D0 0x00D0 // Painting wobble (HMC & COTMC - Left), makes the painting wobble if touched
|
||||
#define SURFACE_PAINTING_WOBBLE_D1 0x00D1 // Painting wobble (Unused, HMC & COTMC - Middle)
|
||||
#define SURFACE_PAINTING_WOBBLE_D2 0x00D2 // Painting wobble (Unused, HMC & COTMC - Right)
|
||||
#define SURFACE_PAINTING_WARP_D3 0x00D3 // Painting warp (BOB Left)
|
||||
#define SURFACE_PAINTING_WARP_D4 0x00D4 // Painting warp (BOB Middle)
|
||||
#define SURFACE_PAINTING_WARP_D5 0x00D5 // Painting warp (BOB Right)
|
||||
#define SURFACE_PAINTING_WARP_D6 0x00D6 // Painting warp (CCM Left)
|
||||
#define SURFACE_PAINTING_WARP_D7 0x00D7 // Painting warp (CCM Middle)
|
||||
#define SURFACE_PAINTING_WARP_D8 0x00D8 // Painting warp (CCM Right)
|
||||
#define SURFACE_PAINTING_WARP_D9 0x00D9 // Painting warp (WF Left)
|
||||
#define SURFACE_PAINTING_WARP_DA 0x00DA // Painting warp (WF Middle)
|
||||
#define SURFACE_PAINTING_WARP_DB 0x00DB // Painting warp (WF Right)
|
||||
#define SURFACE_PAINTING_WARP_DC 0x00DC // Painting warp (JRB Left)
|
||||
#define SURFACE_PAINTING_WARP_DD 0x00DD // Painting warp (JRB Middle)
|
||||
#define SURFACE_PAINTING_WARP_DE 0x00DE // Painting warp (JRB Right)
|
||||
#define SURFACE_PAINTING_WARP_DF 0x00DF // Painting warp (LLL Left)
|
||||
#define SURFACE_PAINTING_WARP_E0 0x00E0 // Painting warp (LLL Middle)
|
||||
#define SURFACE_PAINTING_WARP_E1 0x00E1 // Painting warp (LLL Right)
|
||||
#define SURFACE_PAINTING_WARP_E2 0x00E2 // Painting warp (SSL Left)
|
||||
#define SURFACE_PAINTING_WARP_E3 0x00E3 // Painting warp (SSL Medium)
|
||||
#define SURFACE_PAINTING_WARP_E4 0x00E4 // Painting warp (SSL Right)
|
||||
#define SURFACE_PAINTING_WARP_E5 0x00E5 // Painting warp (Unused - Left)
|
||||
#define SURFACE_PAINTING_WARP_E6 0x00E6 // Painting warp (Unused - Medium)
|
||||
#define SURFACE_PAINTING_WARP_E7 0x00E7 // Painting warp (Unused - Right)
|
||||
#define SURFACE_PAINTING_WARP_E8 0x00E8 // Painting warp (DDD - Left)
|
||||
#define SURFACE_PAINTING_WARP_E9 0x00E9 // Painting warp (DDD - Middle)
|
||||
#define SURFACE_PAINTING_WARP_EA 0x00EA // Painting warp (DDD - Right)
|
||||
#define SURFACE_PAINTING_WARP_EB 0x00EB // Painting warp (WDW Left)
|
||||
#define SURFACE_PAINTING_WARP_EC 0x00EC // Painting warp (WDW Middle)
|
||||
#define SURFACE_PAINTING_WARP_ED 0x00ED // Painting warp (WDW Right)
|
||||
#define SURFACE_PAINTING_WARP_EE 0x00EE // Painting warp (THI Tiny - Left)
|
||||
#define SURFACE_PAINTING_WARP_EF 0x00EF // Painting warp (THI Tiny - Middle)
|
||||
#define SURFACE_PAINTING_WARP_F0 0x00F0 // Painting warp (THI Tiny - Right)
|
||||
#define SURFACE_PAINTING_WARP_F1 0x00F1 // Painting warp (TTM Left)
|
||||
#define SURFACE_PAINTING_WARP_F2 0x00F2 // Painting warp (TTM Middle)
|
||||
#define SURFACE_PAINTING_WARP_F3 0x00F3 // Painting warp (TTM Right)
|
||||
#define SURFACE_TTC_PAINTING_1 0x00F4 // Painting warp (TTC Left)
|
||||
#define SURFACE_TTC_PAINTING_2 0x00F5 // Painting warp (TTC Medium)
|
||||
#define SURFACE_TTC_PAINTING_3 0x00F6 // Painting warp (TTC Right)
|
||||
#define SURFACE_PAINTING_WARP_F7 0x00F7 // Painting warp (SL Left)
|
||||
#define SURFACE_PAINTING_WARP_F8 0x00F8 // Painting warp (SL Middle)
|
||||
#define SURFACE_PAINTING_WARP_F9 0x00F9 // Painting warp (SL Right)
|
||||
#define SURFACE_PAINTING_WARP_FA 0x00FA // Painting warp (THI Tiny - Left)
|
||||
#define SURFACE_PAINTING_WARP_FB 0x00FB // Painting warp (THI Tiny - Middle)
|
||||
#define SURFACE_PAINTING_WARP_FC 0x00FC // Painting warp (THI Tiny - Right)
|
||||
#define SURFACE_WOBBLING_WARP 0x00FD // Pool warp (HMC & DDD)
|
||||
#define SURFACE_TRAPDOOR 0x00FF // Bowser Left trapdoor, has no action defined
|
||||
|
||||
#define SURFACE_IS_QUICKSAND(cmd) (cmd >= 0x21 && cmd < 0x28) // Doesn't include SURFACE_INSTANT_MOVING_QUICKSAND
|
||||
#define SURFACE_IS_NOT_HARD(cmd) (cmd != SURFACE_HARD && \
|
||||
!(cmd >= 0x35 && cmd <= 0x37))
|
||||
#define SURFACE_IS_PAINTING_WARP(cmd) (cmd >= 0xD3 && cmd < 0xFD)
|
||||
|
||||
#define SURFACE_CLASS_DEFAULT 0x0000
|
||||
#define SURFACE_CLASS_VERY_SLIPPERY 0x0013
|
||||
#define SURFACE_CLASS_SLIPPERY 0x0014
|
||||
#define SURFACE_CLASS_NOT_SLIPPERY 0x0015
|
||||
|
||||
#define SURFACE_FLAG_DYNAMIC (1 << 0)
|
||||
#define SURFACE_FLAG_NO_CAM_COLLISION (1 << 1)
|
||||
#define SURFACE_FLAG_X_PROJECTION (1 << 3)
|
||||
|
||||
// These are effectively unique "surface" types like those defined higher
|
||||
// And they are used as collision commands to load certain functions
|
||||
#define TERRAIN_LOAD_VERTICES 0x0040 // Begins vertices list for collision triangles
|
||||
#define TERRAIN_LOAD_CONTINUE 0x0041 // Stop loading vertices but continues to load other collision commands
|
||||
#define TERRAIN_LOAD_END 0x0042 // End the collision list
|
||||
#define TERRAIN_LOAD_OBJECTS 0x0043 // Loads in certain objects for level start
|
||||
#define TERRAIN_LOAD_ENVIRONMENT 0x0044 // Loads water/HMC gas
|
||||
|
||||
#define TERRAIN_LOAD_IS_SURFACE_TYPE_LOW(cmd) (cmd < 0x40)
|
||||
#define TERRAIN_LOAD_IS_SURFACE_TYPE_HIGH(cmd) (cmd >= 0x65)
|
||||
|
||||
// Terrain types defined by the level script command terrain_type (cmd_31)
|
||||
#define TERRAIN_GRASS 0x0000
|
||||
#define TERRAIN_STONE 0x0001
|
||||
#define TERRAIN_SNOW 0x0002
|
||||
#define TERRAIN_SAND 0x0003
|
||||
#define TERRAIN_SPOOKY 0x0004
|
||||
#define TERRAIN_WATER 0x0005
|
||||
#define TERRAIN_SLIDE 0x0006
|
||||
#define TERRAIN_MASK 0x0007
|
||||
|
||||
// These collision commands are unique "surface" types like those defined higher
|
||||
|
||||
// Collision Data Routine Initiate
|
||||
#define COL_INIT() TERRAIN_LOAD_VERTICES
|
||||
|
||||
// Collision Vertices Read Initiate
|
||||
#define COL_VERTEX_INIT(vtxNum) vtxNum
|
||||
|
||||
// Collision Vertex
|
||||
#define COL_VERTEX(x, y, z) x, y, z
|
||||
|
||||
// Collision Tris Initiate
|
||||
#define COL_TRI_INIT(surfType, triNum) surfType, triNum
|
||||
|
||||
// Collision Tri
|
||||
#define COL_TRI(v1, v2, v3) v1, v2, v3
|
||||
|
||||
// Collision Tri With Special Params
|
||||
#define COL_TRI_SPECIAL(v1, v2, v3, param) v1, v2, v3, param
|
||||
|
||||
// Collision Tris Stop Loading
|
||||
#define COL_TRI_STOP() TERRAIN_LOAD_CONTINUE
|
||||
|
||||
// End Collision Data
|
||||
#define COL_END() TERRAIN_LOAD_END
|
||||
|
||||
// Special Object Initiate
|
||||
#define COL_SPECIAL_INIT(num) TERRAIN_LOAD_OBJECTS, num
|
||||
|
||||
// Water Boxes Initiate
|
||||
#define COL_WATER_BOX_INIT(num) TERRAIN_LOAD_ENVIRONMENT, num
|
||||
|
||||
// Water Box
|
||||
#define COL_WATER_BOX(id, x1, z1, x2, z2, y) id, x1, z1, x2, z2, y
|
||||
|
||||
#endif // SURFACE_TERRAINS_H
|
||||
@@ -0,0 +1,348 @@
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
// This file contains various data types used in Super Mario 64 that don't yet
|
||||
// have an appropriate header.
|
||||
|
||||
// #include <ultra64.h>
|
||||
#include "macros.h"
|
||||
#include "PR/ultratypes.h"
|
||||
|
||||
// Certain functions are marked as having return values, but do not
|
||||
// actually return a value. This causes undefined behavior, which we'd rather
|
||||
// avoid on modern GCC. This only impacts -O2 and can matter for both the function
|
||||
// itself and functions that call it.
|
||||
#ifdef AVOID_UB
|
||||
#define BAD_RETURN(cmd) void
|
||||
#else
|
||||
#define BAD_RETURN(cmd) cmd
|
||||
#endif
|
||||
|
||||
|
||||
struct Controller
|
||||
{
|
||||
/*0x00*/ s16 rawStickX; //
|
||||
/*0x02*/ s16 rawStickY; //
|
||||
/*0x04*/ float stickX; // [-64, 64] positive is right
|
||||
/*0x08*/ float stickY; // [-64, 64] positive is up
|
||||
/*0x0C*/ float stickMag; // distance from center [0, 64]
|
||||
/*0x10*/ u16 buttonDown;
|
||||
/*0x12*/ u16 buttonPressed;
|
||||
///*0x14*/ OSContStatus *statusData;
|
||||
///*0x18*/ OSContPad *controllerData;
|
||||
#ifdef VERSION_SH
|
||||
/*0x1C*/ int port;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef f32 Vec2f[2];
|
||||
typedef f32 Vec3f[3]; // X, Y, Z, where Y is up
|
||||
typedef s16 Vec3s[3];
|
||||
typedef s32 Vec3i[3];
|
||||
typedef f32 Vec4f[4];
|
||||
typedef s16 Vec4s[4];
|
||||
|
||||
typedef f32 Mat4[4][4];
|
||||
|
||||
typedef uintptr_t GeoLayout;
|
||||
typedef uintptr_t LevelScript;
|
||||
typedef s16 Movtex;
|
||||
typedef s16 MacroObject;
|
||||
typedef s16 Collision;
|
||||
typedef s16 Trajectory;
|
||||
typedef s16 PaintingData;
|
||||
typedef uintptr_t BehaviorScript;
|
||||
|
||||
enum SpTaskState {
|
||||
SPTASK_STATE_NOT_STARTED,
|
||||
SPTASK_STATE_RUNNING,
|
||||
SPTASK_STATE_INTERRUPTED,
|
||||
SPTASK_STATE_FINISHED,
|
||||
SPTASK_STATE_FINISHED_DP
|
||||
};
|
||||
|
||||
// struct SPTask
|
||||
// {
|
||||
// /*0x00*/ OSTask task;
|
||||
// /*0x40*/ OSMesgQueue *msgqueue;
|
||||
// /*0x44*/ OSMesg msg;
|
||||
// /*0x48*/ enum SpTaskState state;
|
||||
// }; // size = 0x4C, align = 0x8
|
||||
//
|
||||
// struct VblankHandler
|
||||
// {
|
||||
// OSMesgQueue *queue;
|
||||
// OSMesg msg;
|
||||
// };
|
||||
|
||||
#define ANIM_FLAG_NOLOOP (1 << 0) // 0x01
|
||||
#define ANIM_FLAG_FORWARD (1 << 1) // 0x02
|
||||
#define ANIM_FLAG_2 (1 << 2) // 0x04
|
||||
#define ANIM_FLAG_HOR_TRANS (1 << 3) // 0x08
|
||||
#define ANIM_FLAG_VERT_TRANS (1 << 4) // 0x10
|
||||
#define ANIM_FLAG_5 (1 << 5) // 0x20
|
||||
#define ANIM_FLAG_6 (1 << 6) // 0x40
|
||||
#define ANIM_FLAG_7 (1 << 7) // 0x80
|
||||
|
||||
struct Animation {
|
||||
/*0x00*/ s16 flags;
|
||||
/*0x02*/ s16 animYTransDivisor;
|
||||
/*0x04*/ s16 startFrame;
|
||||
/*0x06*/ s16 loopStart;
|
||||
/*0x08*/ s16 loopEnd;
|
||||
/*0x0A*/ s16 unusedBoneCount;
|
||||
/*0x0C*/ s16 *values;
|
||||
/*0x10*/ u16 *index;
|
||||
/*0x14*/ u32 length; // only used with Mario animations to determine how much to load. 0 otherwise.
|
||||
};
|
||||
|
||||
#define ANIMINDEX_NUMPARTS(animindex) (sizeof(animindex) / sizeof(u16) / 6 - 1)
|
||||
|
||||
struct GraphNode
|
||||
{
|
||||
/*0x00*/ s16 type; // structure type
|
||||
/*0x02*/ s16 flags; // hi = drawing layer, lo = rendering modes
|
||||
/*0x04*/ struct GraphNode *prev;
|
||||
/*0x08*/ struct GraphNode *next;
|
||||
/*0x0C*/ struct GraphNode *parent;
|
||||
/*0x10*/ struct GraphNode *children;
|
||||
};
|
||||
|
||||
struct AnimInfo
|
||||
{
|
||||
/*0x00 0x38*/ s16 animID;
|
||||
/*0x02 0x3A*/ s16 animYTrans;
|
||||
/*0x04 0x3C*/ struct Animation *curAnim;
|
||||
/*0x08 0x40*/ s16 animFrame;
|
||||
/*0x0A 0x42*/ u16 animTimer;
|
||||
/*0x0C 0x44*/ s32 animFrameAccelAssist;
|
||||
/*0x10 0x48*/ s32 animAccel;
|
||||
};
|
||||
|
||||
struct GraphNodeObject
|
||||
{
|
||||
/*0x00*/ struct GraphNode node;
|
||||
/*0x14*/ struct GraphNode *sharedChild;
|
||||
/*0x18*/ s8 areaIndex;
|
||||
/*0x19*/ s8 activeAreaIndex;
|
||||
/*0x1A*/ Vec3s angle;
|
||||
/*0x20*/ Vec3f pos;
|
||||
/*0x2C*/ Vec3f scale;
|
||||
/*0x38*/ struct AnimInfo animInfo;
|
||||
/*0x4C*/ struct SpawnInfo *unk4C;
|
||||
/*0x50*/ Mat4 *throwMatrix; // matrix ptr
|
||||
/*0x54*/ Vec3f cameraToObject;
|
||||
};
|
||||
|
||||
struct ObjectNode
|
||||
{
|
||||
struct GraphNodeObject gfx;
|
||||
struct ObjectNode *next;
|
||||
struct ObjectNode *prev;
|
||||
};
|
||||
|
||||
// NOTE: Since ObjectNode is the first member of Object, it is difficult to determine
|
||||
// whether some of these pointers point to ObjectNode or Object.
|
||||
|
||||
struct Object
|
||||
{
|
||||
/*0x000*/ struct ObjectNode header;
|
||||
/*0x068*/ struct Object *parentObj;
|
||||
/*0x06C*/ struct Object *prevObj;
|
||||
/*0x070*/ u32 collidedObjInteractTypes;
|
||||
/*0x074*/ s16 activeFlags;
|
||||
/*0x076*/ s16 numCollidedObjs;
|
||||
/*0x078*/ struct Object *collidedObjs[4];
|
||||
/*0x088*/
|
||||
union
|
||||
{
|
||||
// Object fields. See object_fields.h.
|
||||
u32 asU32[0x50];
|
||||
s32 asS32[0x50];
|
||||
s16 asS16[0x50][2];
|
||||
f32 asF32[0x50];
|
||||
#if !IS_64_BIT
|
||||
s16 *asS16P[0x50];
|
||||
s32 *asS32P[0x50];
|
||||
struct Animation **asAnims[0x50];
|
||||
struct Waypoint *asWaypoint[0x50];
|
||||
struct ChainSegment *asChainSegment[0x50];
|
||||
struct Object *asObject[0x50];
|
||||
struct Surface *asSurface[0x50];
|
||||
void *asVoidPtr[0x50];
|
||||
const void *asConstVoidPtr[0x50];
|
||||
#endif
|
||||
} rawData;
|
||||
#if IS_64_BIT
|
||||
union {
|
||||
s16 *asS16P[0x50];
|
||||
s32 *asS32P[0x50];
|
||||
struct Animation **asAnims[0x50];
|
||||
struct Waypoint *asWaypoint[0x50];
|
||||
struct ChainSegment *asChainSegment[0x50];
|
||||
struct Object *asObject[0x50];
|
||||
struct Surface *asSurface[0x50];
|
||||
void *asVoidPtr[0x50];
|
||||
const void *asConstVoidPtr[0x50];
|
||||
} ptrData;
|
||||
#endif
|
||||
/*0x1C8*/ u32 unused1;
|
||||
/*0x1CC*/ const BehaviorScript *curBhvCommand;
|
||||
/*0x1D0*/ u32 bhvStackIndex;
|
||||
/*0x1D4*/ uintptr_t bhvStack[8];
|
||||
/*0x1F4*/ s16 bhvDelayTimer;
|
||||
/*0x1F6*/ s16 respawnInfoType;
|
||||
/*0x1F8*/ f32 hitboxRadius;
|
||||
/*0x1FC*/ f32 hitboxHeight;
|
||||
/*0x200*/ f32 hurtboxRadius;
|
||||
/*0x204*/ f32 hurtboxHeight;
|
||||
/*0x208*/ f32 hitboxDownOffset;
|
||||
/*0x20C*/ const BehaviorScript *behavior;
|
||||
/*0x210*/ u32 unused2;
|
||||
/*0x214*/ struct Object *platform;
|
||||
/*0x218*/ void *collisionData;
|
||||
/*0x21C*/ Mat4 transform;
|
||||
/*0x25C*/ void *respawnInfo;
|
||||
};
|
||||
|
||||
struct ObjectHitbox
|
||||
{
|
||||
/*0x00*/ u32 interactType;
|
||||
/*0x04*/ u8 downOffset;
|
||||
/*0x05*/ s8 damageOrCoinValue;
|
||||
/*0x06*/ s8 health;
|
||||
/*0x07*/ s8 numLootCoins;
|
||||
/*0x08*/ s16 radius;
|
||||
/*0x0A*/ s16 height;
|
||||
/*0x0C*/ s16 hurtboxRadius;
|
||||
/*0x0E*/ s16 hurtboxHeight;
|
||||
};
|
||||
|
||||
struct Waypoint
|
||||
{
|
||||
s16 flags;
|
||||
Vec3s pos;
|
||||
};
|
||||
|
||||
struct Surface
|
||||
{
|
||||
/*0x00*/ s16 type;
|
||||
/*0x02*/ s16 force;
|
||||
/*0x04*/ s8 flags;
|
||||
/*0x05*/ s8 room;
|
||||
/*0x06*/ s16 lowerY;
|
||||
/*0x08*/ s16 upperY;
|
||||
/*0x0A*/ Vec3s vertex1;
|
||||
/*0x10*/ Vec3s vertex2;
|
||||
/*0x16*/ Vec3s vertex3;
|
||||
/*0x1C*/ struct {
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 z;
|
||||
} normal;
|
||||
/*0x28*/ f32 originOffset;
|
||||
/*0x2C*/ struct Object *object;
|
||||
};
|
||||
|
||||
struct MarioBodyState
|
||||
{
|
||||
/*0x00*/ u32 action;
|
||||
/*0x04*/ s8 capState; /// see MarioCapGSCId
|
||||
/*0x05*/ s8 eyeState;
|
||||
/*0x06*/ s8 handState;
|
||||
/*0x07*/ s8 wingFlutter; /// whether Mario's wing cap wings are fluttering
|
||||
/*0x08*/ s16 modelState;
|
||||
/*0x0A*/ s8 grabPos;
|
||||
/*0x0B*/ u8 punchState; /// 2 bits for type of punch, 6 bits for punch animation timer
|
||||
/*0x0C*/ Vec3s torsoAngle;
|
||||
/*0x12*/ Vec3s headAngle;
|
||||
/*0x18*/ Vec3f heldObjLastPosition; /// also known as HOLP
|
||||
u8 padding[4];
|
||||
};
|
||||
|
||||
struct OffsetSizePair
|
||||
{
|
||||
u32 offset;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct MarioAnimDmaRelatedThing
|
||||
{
|
||||
u32 count;
|
||||
u8 *srcAddr;
|
||||
struct OffsetSizePair anim[1]; // dynamic size
|
||||
};
|
||||
|
||||
struct MarioAnimation
|
||||
{
|
||||
struct MarioAnimDmaRelatedThing *animDmaTable;
|
||||
u8 *currentAnimAddr;
|
||||
struct Animation *targetAnim;
|
||||
u8 padding[4];
|
||||
};
|
||||
|
||||
struct MarioState
|
||||
{
|
||||
/*0x00*/ u16 unk00;
|
||||
/*0x02*/ u16 input;
|
||||
/*0x04*/ u32 flags;
|
||||
/*0x08*/ u32 particleFlags;
|
||||
/*0x0C*/ u32 action;
|
||||
/*0x10*/ u32 prevAction;
|
||||
/*0x14*/ u32 terrainSoundAddend;
|
||||
/*0x18*/ u16 actionState;
|
||||
/*0x1A*/ u16 actionTimer;
|
||||
/*0x1C*/ u32 actionArg;
|
||||
/*0x20*/ f32 intendedMag;
|
||||
/*0x24*/ s16 intendedYaw;
|
||||
/*0x26*/ s16 invincTimer;
|
||||
/*0x28*/ u8 framesSinceA;
|
||||
/*0x29*/ u8 framesSinceB;
|
||||
/*0x2A*/ u8 wallKickTimer;
|
||||
/*0x2B*/ u8 doubleJumpTimer;
|
||||
/*0x2C*/ Vec3s faceAngle;
|
||||
/*0x32*/ Vec3s angleVel;
|
||||
/*0x38*/ s16 slideYaw;
|
||||
/*0x3A*/ s16 twirlYaw;
|
||||
/*0x3C*/ Vec3f pos;
|
||||
/*0x48*/ Vec3f vel;
|
||||
/*0x54*/ f32 forwardVel;
|
||||
/*0x58*/ f32 slideVelX;
|
||||
/*0x5C*/ f32 slideVelZ;
|
||||
/*0x60*/ struct Surface *wall;
|
||||
/*0x64*/ struct Surface *ceil;
|
||||
/*0x68*/ struct Surface *floor;
|
||||
/*0x6C*/ f32 ceilHeight;
|
||||
/*0x70*/ f32 floorHeight;
|
||||
/*0x74*/ s16 floorAngle;
|
||||
/*0x76*/ s16 waterLevel;
|
||||
/*0x78*/ struct Object *interactObj;
|
||||
/*0x7C*/ struct Object *heldObj;
|
||||
/*0x80*/ struct Object *usedObj;
|
||||
/*0x84*/ struct Object *riddenObj;
|
||||
/*0x88*/ struct Object *marioObj;
|
||||
/*0x8C*/ struct SpawnInfo *spawnInfo;
|
||||
/*0x90*/ struct Area *area;
|
||||
// /*0x94*/ struct PlayerCameraState *statusForCamera;
|
||||
/*0x98*/ struct MarioBodyState *marioBodyState;
|
||||
/*0x9C*/ struct Controller *controller;
|
||||
/*0xA0*/ struct MarioAnimation *animation;
|
||||
/*0xA4*/ u32 collidedObjInteractTypes;
|
||||
/*0xA8*/ s16 numCoins;
|
||||
/*0xAA*/ s16 numStars;
|
||||
/*0xAC*/ s8 numKeys; // Unused key mechanic
|
||||
/*0xAD*/ s8 numLives;
|
||||
/*0xAE*/ s16 health;
|
||||
/*0xB0*/ s16 unkB0;
|
||||
/*0xB2*/ u8 hurtCounter;
|
||||
/*0xB3*/ u8 healCounter;
|
||||
/*0xB4*/ u8 squishTimer;
|
||||
/*0xB5*/ u8 fadeWarpOpacity;
|
||||
/*0xB6*/ u16 capTimer;
|
||||
/*0xB8*/ s16 prevNumStarsForDialog;
|
||||
/*0xBC*/ f32 peakHeight;
|
||||
/*0xC0*/ f32 quicksandDepth;
|
||||
/*0xC4*/ f32 unkC4;
|
||||
};
|
||||
|
||||
#endif // TYPES_H
|
||||
@@ -0,0 +1,153 @@
|
||||
#include <string.h>
|
||||
#include "shim.h"
|
||||
#include "../load_anim_data.h"
|
||||
|
||||
u32 gGlobalTimer = 0;
|
||||
u8 gSpecialTripleJump = FALSE;
|
||||
s16 gCurrLevelNum = 0;
|
||||
s16 gCameraMovementFlags = 0;
|
||||
u32 gAudioRandom = 0;
|
||||
s8 gShowDebugText = 0;
|
||||
s8 gDebugLevelSelect = 0;
|
||||
s16 gCurrSaveFileNum = 1;
|
||||
struct Controller gController;
|
||||
struct SpawnInfo gMarioSpawnInfoVal;
|
||||
struct SpawnInfo *gMarioSpawnInfo = &gMarioSpawnInfoVal;
|
||||
struct Area *gCurrentArea = NULL;
|
||||
struct Object *gCurrentObject;
|
||||
struct Object *gMarioObject = NULL;
|
||||
struct PlayerCameraState gPlayerCameraState;
|
||||
struct MarioAnimation D_80339D10;
|
||||
struct MarioState gMarioStateVal;
|
||||
struct MarioState *gMarioState = &gMarioStateVal;
|
||||
SM64DebugPrintFunctionPtr gDebugPrint = NULL;
|
||||
|
||||
void hack_load_mario_animation_ex(struct MarioAnimation *a, u32 index)
|
||||
{
|
||||
if ((u32)a->currentAnimAddr == 1 + index)
|
||||
return;
|
||||
|
||||
a->currentAnimAddr = (u8*)(1 + index);
|
||||
a->targetAnim = &gLibSm64MarioAnimations[index];
|
||||
}
|
||||
|
||||
void hack_load_mario_animation(struct MarioAnimation *a, u32 index)
|
||||
{
|
||||
// struct MarioAnimDmaRelatedThing *sp20 = a->animDmaTable;
|
||||
// u8 *addr;
|
||||
// u32 size;
|
||||
//
|
||||
// if (index < sp20->count) {
|
||||
// addr = sp20->srcAddr + sp20->anim[index].offset;
|
||||
// size = sp20->anim[index].size;
|
||||
//
|
||||
// if (a->currentAnimAddr != addr) {
|
||||
// u32 a0 = sp20->anim[index].offset;
|
||||
// u32 b0 = sp20->anim[index].size;
|
||||
//
|
||||
// memcpy( (u8*)a->targetAnim, (u8*)sp20 + a0, b0 );
|
||||
// a->currentAnimAddr = addr;
|
||||
//
|
||||
// struct Animation *targetAnim = a->targetAnim;
|
||||
// targetAnim->values =(void*)( (u8 *)targetAnim + (uintptr_t)targetAnim->values );
|
||||
// targetAnim->index = (void*)( (u8 *)targetAnim + (uintptr_t)targetAnim->index );
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void *segmented_to_virtual(const void *addr)
|
||||
{
|
||||
return (void*)addr;
|
||||
}
|
||||
|
||||
void *virtual_to_segmented(u32 segment, const void *addr)
|
||||
{
|
||||
return (void*)addr;
|
||||
}
|
||||
|
||||
void func_80320A4C(u8 bankIndex, u8 arg1)
|
||||
{
|
||||
}
|
||||
|
||||
void lower_background_noise(s32 a)
|
||||
{
|
||||
}
|
||||
|
||||
void raise_background_noise(s32 a)
|
||||
{
|
||||
}
|
||||
|
||||
void set_camera_mode(struct Camera *c, s16 mode, s16 frames)
|
||||
{
|
||||
}
|
||||
|
||||
void print_text_fmt_int(s32 x, s32 y, const char *str, s32 n)
|
||||
{
|
||||
}
|
||||
|
||||
s16 level_trigger_warp(struct MarioState *m, s32 warpOp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void play_cap_music(u16 seqArgs)
|
||||
{
|
||||
}
|
||||
|
||||
void fadeout_cap_music(void)
|
||||
{
|
||||
}
|
||||
|
||||
void stop_cap_music(void)
|
||||
{
|
||||
}
|
||||
|
||||
void play_infinite_stairs_music(void)
|
||||
{
|
||||
}
|
||||
|
||||
s32 save_file_get_total_star_count(s32 fileIndex, s32 minCourse, s32 maxCourse)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 save_file_get_flags(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void save_file_set_flags(u32 flags)
|
||||
{
|
||||
}
|
||||
|
||||
void save_file_clear_flags(u32 flags)
|
||||
{
|
||||
}
|
||||
|
||||
void spawn_wind_particles(s16 pitch, s16 yaw)
|
||||
{
|
||||
}
|
||||
|
||||
void set_camera_shake_from_hit(s16 shake)
|
||||
{
|
||||
}
|
||||
|
||||
void load_level_init_text(u32 arg)
|
||||
{
|
||||
}
|
||||
|
||||
void spawn_default_star(f32 sp20, f32 sp24, f32 sp28)
|
||||
{
|
||||
}
|
||||
|
||||
void play_shell_music(void)
|
||||
{
|
||||
}
|
||||
|
||||
void stop_shell_music(void)
|
||||
{
|
||||
}
|
||||
|
||||
u16 level_control_timer(s32 timerOp)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include "include/types.h"
|
||||
#include "game/area.h"
|
||||
#include "game/level_update.h"
|
||||
#include "../libsm64.h"
|
||||
|
||||
#define COURSE_MIN 0
|
||||
#define COURSE_MAX 14
|
||||
#define LEVEL_LLL 99
|
||||
#define LEVEL_SSL 98
|
||||
#define LEVEL_DDD 97
|
||||
#define LEVEL_TTC 96
|
||||
#define LEVEL_CASTLE 95
|
||||
#define LEVEL_THI 94
|
||||
|
||||
// From graph_node.h, trying not to pull that in yet
|
||||
#define GRAPH_RENDER_INVISIBLE (1 << 4)
|
||||
|
||||
#define play_sound(a,b) ({})
|
||||
#define enable_time_stop() ({})
|
||||
#define disable_time_stop() ({})
|
||||
#define play_cutscene_music(a) ({})
|
||||
|
||||
struct SurfaceObjectTransform
|
||||
{
|
||||
float aPosX, aPosY, aPosZ;
|
||||
float aVelX, aVelY, aVelZ;
|
||||
|
||||
s16 aFaceAnglePitch;
|
||||
s16 aFaceAngleYaw;
|
||||
s16 aFaceAngleRoll;
|
||||
|
||||
s16 aAngleVelPitch;
|
||||
s16 aAngleVelYaw;
|
||||
s16 aAngleVelRoll;
|
||||
};
|
||||
|
||||
struct SurfaceNode
|
||||
{
|
||||
struct SurfaceNode *next;
|
||||
struct Surface *surface;
|
||||
};
|
||||
|
||||
extern u32 gGlobalTimer;
|
||||
extern u8 gSpecialTripleJump;
|
||||
extern s16 gCurrLevelNum;
|
||||
extern s16 gCameraMovementFlags;
|
||||
extern u32 gAudioRandom;
|
||||
extern s8 gShowDebugText;
|
||||
extern s8 gDebugLevelSelect;
|
||||
extern s16 gCurrSaveFileNum;
|
||||
extern struct Controller gController;
|
||||
extern struct SpawnInfo gMarioSpawnInfoVal;
|
||||
extern struct SpawnInfo *gMarioSpawnInfo;
|
||||
extern struct Area *gCurrentArea;
|
||||
extern struct Object *gCurrentObject;
|
||||
extern struct Object *gMarioObject;
|
||||
extern struct PlayerCameraState gPlayerCameraState;
|
||||
extern struct MarioAnimation D_80339D10;
|
||||
extern struct MarioState *gMarioState;
|
||||
extern SM64DebugPrintFunctionPtr gDebugPrint;
|
||||
|
||||
#define DEBUG_LOG( ... ) do { \
|
||||
if( gDebugPrint ) { \
|
||||
char debugStr[1024]; \
|
||||
sprintf( debugStr, __VA_ARGS__ ); \
|
||||
gDebugPrint( debugStr ); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
extern void hack_load_mario_animation_ex(struct MarioAnimation *a, u32 index);
|
||||
extern void hack_load_mario_animation(struct MarioAnimation *a, u32 index);
|
||||
extern void *segmented_to_virtual(const void *addr);
|
||||
extern void *virtual_to_segmented(u32 segment, const void *addr);
|
||||
extern void func_80320A4C(u8 bankIndex, u8 arg1);
|
||||
extern void raise_background_noise(s32 a);
|
||||
extern void lower_background_noise(s32 a);
|
||||
extern void set_camera_mode(struct Camera *c, s16 mode, s16 frames);
|
||||
extern void print_text_fmt_int(s32 x, s32 y, const char *str, s32 n);
|
||||
extern s16 level_trigger_warp(struct MarioState *m, s32 warpOp);
|
||||
extern void play_cap_music(u16 seqArgs);
|
||||
extern void fadeout_cap_music(void);
|
||||
extern void stop_cap_music(void);
|
||||
extern void play_infinite_stairs_music(void);
|
||||
extern s32 save_file_get_total_star_count(s32 fileIndex, s32 minCourse, s32 maxCourse);
|
||||
extern u32 save_file_get_flags(void);
|
||||
extern void save_file_set_flags(u32 flags);
|
||||
extern void save_file_clear_flags(u32 flags);
|
||||
extern void spawn_wind_particles(s16 pitch, s16 yaw);
|
||||
extern void set_camera_shake_from_hit(s16 shake);
|
||||
extern void load_level_init_text(u32 arg);
|
||||
extern void spawn_default_star(f32 sp20, f32 sp24, f32 sp28);
|
||||
extern void play_shell_music(void);
|
||||
extern void stop_shell_music(void);
|
||||
extern u16 level_control_timer(s32 timerOp);
|
||||
@@ -0,0 +1,575 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "libmio0.h"
|
||||
#include "utils.h"
|
||||
|
||||
// defines
|
||||
|
||||
#define MIO0_VERSION "0.1"
|
||||
|
||||
#define GET_BIT(buf, bit) ((buf)[(bit) / 8] & (1 << (7 - ((bit) % 8))))
|
||||
|
||||
// types
|
||||
typedef struct
|
||||
{
|
||||
int *indexes;
|
||||
int allocated;
|
||||
int count;
|
||||
int start;
|
||||
} lookback;
|
||||
|
||||
// functions
|
||||
#define LOOKBACK_COUNT 256
|
||||
#define LOOKBACK_INIT_SIZE 128
|
||||
static lookback *lookback_init(void)
|
||||
{
|
||||
lookback *lb = malloc(LOOKBACK_COUNT * sizeof(*lb));
|
||||
for (int i = 0; i < LOOKBACK_COUNT; i++) {
|
||||
lb[i].allocated = LOOKBACK_INIT_SIZE;
|
||||
lb[i].indexes = malloc(lb[i].allocated * sizeof(*lb[i].indexes));
|
||||
lb[i].count = 0;
|
||||
lb[i].start = 0;
|
||||
}
|
||||
return lb;
|
||||
}
|
||||
|
||||
static void lookback_free(lookback *lb)
|
||||
{
|
||||
for (int i = 0; i < LOOKBACK_COUNT; i++) {
|
||||
free(lb[i].indexes);
|
||||
}
|
||||
free(lb);
|
||||
}
|
||||
|
||||
static inline void lookback_push(lookback *lkbk, unsigned char val, int index)
|
||||
{
|
||||
lookback *lb = &lkbk[val];
|
||||
if (lb->count == lb->allocated) {
|
||||
lb->allocated *= 4;
|
||||
lb->indexes = realloc(lb->indexes, lb->allocated * sizeof(*lb->indexes));
|
||||
}
|
||||
lb->indexes[lb->count++] = index;
|
||||
}
|
||||
|
||||
static void PUT_BIT(unsigned char *buf, int bit, int val)
|
||||
{
|
||||
unsigned char mask = 1 << (7 - (bit % 8));
|
||||
unsigned int offset = bit / 8;
|
||||
buf[offset] = (buf[offset] & ~(mask)) | (val ? mask : 0);
|
||||
}
|
||||
|
||||
// used to find longest matching stream in buffer
|
||||
// buf: buffer
|
||||
// start_offset: offset in buf to look back from
|
||||
// max_search: max number of bytes to find
|
||||
// found_offset: returned offset found (0 if none found)
|
||||
// returns max length of matching stream (0 if none found)
|
||||
static int find_longest(const unsigned char *buf, int start_offset, int max_search, int *found_offset, lookback *lkbk)
|
||||
{
|
||||
int best_length = 0;
|
||||
int best_offset = 0;
|
||||
int cur_length;
|
||||
int search_len;
|
||||
int farthest, off, i;
|
||||
int lb_idx;
|
||||
const unsigned char first = buf[start_offset];
|
||||
lookback *lb = &lkbk[first];
|
||||
|
||||
// buf
|
||||
// | off start max
|
||||
// V |+i-> |+i-> |
|
||||
// |--------------raw-data-----------------|
|
||||
// |+i-> | |+i->
|
||||
// +cur_length
|
||||
|
||||
// check at most the past 4096 values
|
||||
farthest = MAX(start_offset - 4096, 0);
|
||||
// find starting index
|
||||
for (lb_idx = lb->start; lb_idx < lb->count && lb->indexes[lb_idx] < farthest; lb_idx++) {}
|
||||
lb->start = lb_idx;
|
||||
for ( ; lb_idx < lb->count && lb->indexes[lb_idx] < start_offset; lb_idx++) {
|
||||
off = lb->indexes[lb_idx];
|
||||
// check at most requested max or up until start
|
||||
search_len = MIN(max_search, start_offset - off);
|
||||
for (i = 0; i < search_len; i++) {
|
||||
if (buf[start_offset + i] != buf[off + i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cur_length = i;
|
||||
// if matched up until start, continue matching in already matched parts
|
||||
if (cur_length == search_len) {
|
||||
// check at most requested max less current length
|
||||
search_len = max_search - cur_length;
|
||||
for (i = 0; i < search_len; i++) {
|
||||
if (buf[start_offset + cur_length + i] != buf[off + i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cur_length += i;
|
||||
}
|
||||
if (cur_length > best_length) {
|
||||
best_offset = start_offset - off;
|
||||
best_length = cur_length;
|
||||
}
|
||||
}
|
||||
|
||||
// return best reverse offset and length (may be 0)
|
||||
*found_offset = best_offset;
|
||||
return best_length;
|
||||
}
|
||||
|
||||
// decode MIO0 header
|
||||
// returns 1 if valid header, 0 otherwise
|
||||
int mio0_decode_header(const unsigned char *buf, mio0_header_t *head)
|
||||
{
|
||||
if (!memcmp(buf, "MIO0", 4)) {
|
||||
head->dest_size = read_u32_be(&buf[4]);
|
||||
head->comp_offset = read_u32_be(&buf[8]);
|
||||
head->uncomp_offset = read_u32_be(&buf[12]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mio0_encode_header(unsigned char *buf, const mio0_header_t *head)
|
||||
{
|
||||
memcpy(buf, "MIO0", 4);
|
||||
write_u32_be(&buf[4], head->dest_size);
|
||||
write_u32_be(&buf[8], head->comp_offset);
|
||||
write_u32_be(&buf[12], head->uncomp_offset);
|
||||
}
|
||||
|
||||
int mio0_decode(const unsigned char *in, unsigned char *out, unsigned int *end)
|
||||
{
|
||||
mio0_header_t head;
|
||||
unsigned int bytes_written = 0;
|
||||
int bit_idx = 0;
|
||||
int comp_idx = 0;
|
||||
int uncomp_idx = 0;
|
||||
int valid;
|
||||
|
||||
// extract header
|
||||
valid = mio0_decode_header(in, &head);
|
||||
// verify MIO0 header
|
||||
if (!valid) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
// decode data
|
||||
while (bytes_written < head.dest_size) {
|
||||
if (GET_BIT(&in[MIO0_HEADER_LENGTH], bit_idx)) {
|
||||
// 1 - pull uncompressed data
|
||||
out[bytes_written] = in[head.uncomp_offset + uncomp_idx];
|
||||
bytes_written++;
|
||||
uncomp_idx++;
|
||||
} else {
|
||||
// 0 - read compressed data
|
||||
int idx;
|
||||
int length;
|
||||
int i;
|
||||
const unsigned char *vals = &in[head.comp_offset + comp_idx];
|
||||
comp_idx += 2;
|
||||
length = ((vals[0] & 0xF0) >> 4) + 3;
|
||||
idx = ((vals[0] & 0x0F) << 8) + vals[1] + 1;
|
||||
for (i = 0; i < length; i++) {
|
||||
out[bytes_written] = out[bytes_written - idx];
|
||||
bytes_written++;
|
||||
}
|
||||
}
|
||||
bit_idx++;
|
||||
}
|
||||
|
||||
if (end) {
|
||||
*end = head.uncomp_offset + uncomp_idx;
|
||||
}
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
int mio0_encode(const unsigned char *in, unsigned int length, unsigned char *out)
|
||||
{
|
||||
unsigned char *bit_buf;
|
||||
unsigned char *comp_buf;
|
||||
unsigned char *uncomp_buf;
|
||||
unsigned int bit_length;
|
||||
unsigned int comp_offset;
|
||||
unsigned int uncomp_offset;
|
||||
unsigned int bytes_proc = 0;
|
||||
int bytes_written;
|
||||
int bit_idx = 0;
|
||||
int comp_idx = 0;
|
||||
int uncomp_idx = 0;
|
||||
lookback *lookbacks;
|
||||
|
||||
// initialize lookback buffer
|
||||
lookbacks = lookback_init();
|
||||
|
||||
// allocate some temporary buffers worst case size
|
||||
bit_buf = malloc((length + 7) / 8); // 1-bit/byte
|
||||
comp_buf = malloc(length); // 16-bits/2bytes
|
||||
uncomp_buf = malloc(length); // all uncompressed
|
||||
memset(bit_buf, 0, (length + 7) / 8);
|
||||
|
||||
// encode data
|
||||
// special case for first byte
|
||||
lookback_push(lookbacks, in[0], 0);
|
||||
uncomp_buf[uncomp_idx] = in[0];
|
||||
uncomp_idx += 1;
|
||||
bytes_proc += 1;
|
||||
PUT_BIT(bit_buf, bit_idx++, 1);
|
||||
while (bytes_proc < length) {
|
||||
int offset;
|
||||
int max_length = MIN(length - bytes_proc, 18);
|
||||
int longest_match = find_longest(in, bytes_proc, max_length, &offset, lookbacks);
|
||||
// push current byte before checking next longer match
|
||||
lookback_push(lookbacks, in[bytes_proc], bytes_proc);
|
||||
if (longest_match > 2) {
|
||||
int lookahead_offset;
|
||||
// lookahead to next byte to see if longer match
|
||||
int lookahead_length = MIN(length - bytes_proc - 1, 18);
|
||||
int lookahead_match = find_longest(in, bytes_proc + 1, lookahead_length, &lookahead_offset, lookbacks);
|
||||
// better match found, use uncompressed + lookahead compressed
|
||||
if ((longest_match + 1) < lookahead_match) {
|
||||
// uncompressed byte
|
||||
uncomp_buf[uncomp_idx] = in[bytes_proc];
|
||||
uncomp_idx++;
|
||||
PUT_BIT(bit_buf, bit_idx, 1);
|
||||
bytes_proc++;
|
||||
longest_match = lookahead_match;
|
||||
offset = lookahead_offset;
|
||||
bit_idx++;
|
||||
lookback_push(lookbacks, in[bytes_proc], bytes_proc);
|
||||
}
|
||||
// first byte already pushed above
|
||||
for (int i = 1; i < longest_match; i++) {
|
||||
lookback_push(lookbacks, in[bytes_proc + i], bytes_proc + i);
|
||||
}
|
||||
// compressed block
|
||||
comp_buf[comp_idx] = (((longest_match - 3) & 0x0F) << 4) |
|
||||
(((offset - 1) >> 8) & 0x0F);
|
||||
comp_buf[comp_idx + 1] = (offset - 1) & 0xFF;
|
||||
comp_idx += 2;
|
||||
PUT_BIT(bit_buf, bit_idx, 0);
|
||||
bytes_proc += longest_match;
|
||||
} else {
|
||||
// uncompressed byte
|
||||
uncomp_buf[uncomp_idx] = in[bytes_proc];
|
||||
uncomp_idx++;
|
||||
PUT_BIT(bit_buf, bit_idx, 1);
|
||||
bytes_proc++;
|
||||
}
|
||||
bit_idx++;
|
||||
}
|
||||
|
||||
// compute final sizes and offsets
|
||||
// +7 so int division accounts for all bits
|
||||
bit_length = ((bit_idx + 7) / 8);
|
||||
// compressed data after control bits and aligned to 4-byte boundary
|
||||
comp_offset = ALIGN(MIO0_HEADER_LENGTH + bit_length, 4);
|
||||
uncomp_offset = comp_offset + comp_idx;
|
||||
bytes_written = uncomp_offset + uncomp_idx;
|
||||
|
||||
// output header
|
||||
memcpy(out, "MIO0", 4);
|
||||
write_u32_be(&out[4], length);
|
||||
write_u32_be(&out[8], comp_offset);
|
||||
write_u32_be(&out[12], uncomp_offset);
|
||||
// output data
|
||||
memcpy(&out[MIO0_HEADER_LENGTH], bit_buf, bit_length);
|
||||
memcpy(&out[comp_offset], comp_buf, comp_idx);
|
||||
memcpy(&out[uncomp_offset], uncomp_buf, uncomp_idx);
|
||||
|
||||
// free allocated buffers
|
||||
free(bit_buf);
|
||||
free(comp_buf);
|
||||
free(uncomp_buf);
|
||||
lookback_free(lookbacks);
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
static FILE *mio0_open_out_file(const char *out_file) {
|
||||
if (strcmp(out_file, "-") == 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
return stdout;
|
||||
} else {
|
||||
return fopen(out_file, "wb");
|
||||
}
|
||||
}
|
||||
|
||||
int mio0_decode_file(const char *in_file, unsigned long offset, const char *out_file)
|
||||
{
|
||||
mio0_header_t head;
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
unsigned char *in_buf = NULL;
|
||||
unsigned char *out_buf = NULL;
|
||||
long file_size;
|
||||
int ret_val = 0;
|
||||
size_t bytes_read;
|
||||
int bytes_decoded;
|
||||
int bytes_written;
|
||||
int valid;
|
||||
|
||||
in = fopen(in_file, "rb");
|
||||
if (in == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// allocate buffer to read from offset to end of file
|
||||
fseek(in, 0, SEEK_END);
|
||||
file_size = ftell(in);
|
||||
in_buf = malloc(file_size - offset);
|
||||
fseek(in, offset, SEEK_SET);
|
||||
|
||||
// read bytes
|
||||
bytes_read = fread(in_buf, 1, file_size - offset, in);
|
||||
if (bytes_read != file_size - offset) {
|
||||
ret_val = 2;
|
||||
goto free_all;
|
||||
}
|
||||
|
||||
// verify header
|
||||
valid = mio0_decode_header(in_buf, &head);
|
||||
if (!valid) {
|
||||
ret_val = 3;
|
||||
goto free_all;
|
||||
}
|
||||
out_buf = malloc(head.dest_size);
|
||||
|
||||
// decompress MIO0 encoded data
|
||||
bytes_decoded = mio0_decode(in_buf, out_buf, NULL);
|
||||
if (bytes_decoded < 0) {
|
||||
ret_val = 3;
|
||||
goto free_all;
|
||||
}
|
||||
|
||||
// open output file
|
||||
out = mio0_open_out_file(out_file);
|
||||
if (out == NULL) {
|
||||
ret_val = 4;
|
||||
goto free_all;
|
||||
}
|
||||
|
||||
// write data to file
|
||||
bytes_written = fwrite(out_buf, 1, bytes_decoded, out);
|
||||
if (bytes_written != bytes_decoded) {
|
||||
ret_val = 5;
|
||||
}
|
||||
|
||||
// clean up
|
||||
if (out != stdout) {
|
||||
fclose(out);
|
||||
}
|
||||
free_all:
|
||||
if (out_buf) {
|
||||
free(out_buf);
|
||||
}
|
||||
if (in_buf) {
|
||||
free(in_buf);
|
||||
}
|
||||
fclose(in);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int mio0_encode_file(const char *in_file, const char *out_file)
|
||||
{
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
unsigned char *in_buf = NULL;
|
||||
unsigned char *out_buf = NULL;
|
||||
size_t file_size;
|
||||
size_t bytes_read;
|
||||
int bytes_encoded;
|
||||
int bytes_written;
|
||||
int ret_val = 0;
|
||||
|
||||
in = fopen(in_file, "rb");
|
||||
if (in == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// allocate buffer to read entire contents of files
|
||||
fseek(in, 0, SEEK_END);
|
||||
file_size = ftell(in);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
in_buf = malloc(file_size);
|
||||
|
||||
// read bytes
|
||||
bytes_read = fread(in_buf, 1, file_size, in);
|
||||
if (bytes_read != file_size) {
|
||||
ret_val = 2;
|
||||
goto free_all;
|
||||
}
|
||||
|
||||
// allocate worst case length
|
||||
out_buf = malloc(MIO0_HEADER_LENGTH + ((file_size+7)/8) + file_size);
|
||||
|
||||
// compress data in MIO0 format
|
||||
bytes_encoded = mio0_encode(in_buf, file_size, out_buf);
|
||||
|
||||
// open output file
|
||||
out = mio0_open_out_file(out_file);
|
||||
if (out == NULL) {
|
||||
ret_val = 4;
|
||||
goto free_all;
|
||||
}
|
||||
|
||||
// write data to file
|
||||
bytes_written = fwrite(out_buf, 1, bytes_encoded, out);
|
||||
if (bytes_written != bytes_encoded) {
|
||||
ret_val = 5;
|
||||
}
|
||||
|
||||
// clean up
|
||||
if (out != stdout) {
|
||||
fclose(out);
|
||||
}
|
||||
free_all:
|
||||
if (out_buf) {
|
||||
free(out_buf);
|
||||
}
|
||||
if (in_buf) {
|
||||
free(in_buf);
|
||||
}
|
||||
fclose(in);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
// mio0 standalone executable
|
||||
#ifdef MIO0_STANDALONE
|
||||
typedef struct
|
||||
{
|
||||
char *in_filename;
|
||||
char *out_filename;
|
||||
unsigned int offset;
|
||||
int compress;
|
||||
} arg_config;
|
||||
|
||||
static arg_config default_config =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
1
|
||||
};
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
ERROR("Usage: mio0 [-c / -d] [-o OFFSET] FILE [OUTPUT]\n"
|
||||
"\n"
|
||||
"mio0 v" MIO0_VERSION ": MIO0 compression and decompression tool\n"
|
||||
"\n"
|
||||
"Optional arguments:\n"
|
||||
" -c compress raw data into MIO0 (default: compress)\n"
|
||||
" -d decompress MIO0 into raw data\n"
|
||||
" -o OFFSET starting offset in FILE (default: 0)\n"
|
||||
"\n"
|
||||
"File arguments:\n"
|
||||
" FILE input file\n"
|
||||
" [OUTPUT] output file (default: FILE.out), \"-\" for stdout\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// parse command line arguments
|
||||
static void parse_arguments(int argc, char *argv[], arg_config *config)
|
||||
{
|
||||
int i;
|
||||
int file_count = 0;
|
||||
if (argc < 2) {
|
||||
print_usage();
|
||||
exit(1);
|
||||
}
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-' && argv[i][1] != '\0') {
|
||||
switch (argv[i][1]) {
|
||||
case 'c':
|
||||
config->compress = 1;
|
||||
break;
|
||||
case 'd':
|
||||
config->compress = 0;
|
||||
break;
|
||||
case 'o':
|
||||
if (++i >= argc) {
|
||||
print_usage();
|
||||
}
|
||||
config->offset = strtoul(argv[i], NULL, 0);
|
||||
break;
|
||||
default:
|
||||
print_usage();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (file_count) {
|
||||
case 0:
|
||||
config->in_filename = argv[i];
|
||||
break;
|
||||
case 1:
|
||||
config->out_filename = argv[i];
|
||||
break;
|
||||
default: // too many
|
||||
print_usage();
|
||||
break;
|
||||
}
|
||||
file_count++;
|
||||
}
|
||||
}
|
||||
if (file_count < 1) {
|
||||
print_usage();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char out_filename[FILENAME_MAX];
|
||||
arg_config config;
|
||||
int ret_val;
|
||||
|
||||
// get configuration from arguments
|
||||
config = default_config;
|
||||
parse_arguments(argc, argv, &config);
|
||||
if (config.out_filename == NULL) {
|
||||
config.out_filename = out_filename;
|
||||
sprintf(config.out_filename, "%s.out", config.in_filename);
|
||||
}
|
||||
|
||||
// operation
|
||||
if (config.compress) {
|
||||
ret_val = mio0_encode_file(config.in_filename, config.out_filename);
|
||||
} else {
|
||||
ret_val = mio0_decode_file(config.in_filename, config.offset, config.out_filename);
|
||||
}
|
||||
|
||||
switch (ret_val) {
|
||||
case 1:
|
||||
ERROR("Error opening input file \"%s\"\n", config.in_filename);
|
||||
break;
|
||||
case 2:
|
||||
ERROR("Error reading from input file \"%s\"\n", config.in_filename);
|
||||
break;
|
||||
case 3:
|
||||
ERROR("Error decoding MIO0 data. Wrong offset (0x%X)?\n", config.offset);
|
||||
break;
|
||||
case 4:
|
||||
ERROR("Error opening output file \"%s\"\n", config.out_filename);
|
||||
break;
|
||||
case 5:
|
||||
ERROR("Error writing bytes to output file \"%s\"\n", config.out_filename);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
#endif // MIO0_STANDALONE
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef LIBMIO0_H_
|
||||
#define LIBMIO0_H_
|
||||
|
||||
// defines
|
||||
|
||||
#define MIO0_HEADER_LENGTH 16
|
||||
|
||||
// typedefs
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int dest_size;
|
||||
unsigned int comp_offset;
|
||||
unsigned int uncomp_offset;
|
||||
} mio0_header_t;
|
||||
|
||||
// function prototypes
|
||||
|
||||
// decode MIO0 header
|
||||
// returns 1 if valid header, 0 otherwise
|
||||
int mio0_decode_header(const unsigned char *buf, mio0_header_t *head);
|
||||
|
||||
// encode MIO0 header from struct
|
||||
void mio0_encode_header(unsigned char *buf, const mio0_header_t *head);
|
||||
|
||||
// decode MIO0 data in memory
|
||||
// in: buffer containing MIO0 data
|
||||
// out: buffer for output data
|
||||
// end: output offset of the last byte decoded from in (set to NULL if unwanted)
|
||||
// returns bytes extracted to 'out' or negative value on failure
|
||||
int mio0_decode(const unsigned char *in, unsigned char *out, unsigned int *end);
|
||||
|
||||
// encode MIO0 data in memory
|
||||
// in: buffer containing raw data
|
||||
// out: buffer for MIO0 data
|
||||
// returns size of compressed data in 'out' including MIO0 header
|
||||
int mio0_encode(const unsigned char *in, unsigned int length, unsigned char *out);
|
||||
|
||||
// decode an entire MIO0 block at an offset from file to output file
|
||||
// in_file: input filename
|
||||
// offset: offset to start decoding from in_file
|
||||
// out_file: output filename
|
||||
int mio0_decode_file(const char *in_file, unsigned long offset, const char *out_file);
|
||||
|
||||
// encode an entire file
|
||||
// in_file: input filename containing raw data to be encoded
|
||||
// out_file: output filename to write MIO0 compressed data to
|
||||
int mio0_encode_file(const char *in_file, const char *out_file);
|
||||
|
||||
#endif // LIBMIO0_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,100 @@
|
||||
#ifndef N64GRAPHICS_H_
|
||||
#define N64GRAPHICS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// intermediate formats
|
||||
typedef struct _rgba
|
||||
{
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
uint8_t alpha;
|
||||
} rgba;
|
||||
|
||||
typedef struct _ia
|
||||
{
|
||||
uint8_t intensity;
|
||||
uint8_t alpha;
|
||||
} ia;
|
||||
|
||||
// CI palette
|
||||
typedef struct
|
||||
{
|
||||
uint16_t data[256];
|
||||
int max; // max number of entries
|
||||
int used; // number of entries used
|
||||
} palette_t;
|
||||
|
||||
//---------------------------------------------------------
|
||||
// N64 RGBA/IA/I/CI -> intermediate RGBA/IA
|
||||
//---------------------------------------------------------
|
||||
|
||||
// N64 raw RGBA16/RGBA32 -> intermediate RGBA
|
||||
rgba *raw2rgba(const uint8_t *raw, int width, int height, int depth);
|
||||
|
||||
// N64 raw IA1/IA4/IA8/IA16 -> intermediate IA
|
||||
ia *raw2ia(const uint8_t *raw, int width, int height, int depth);
|
||||
|
||||
// N64 raw I4/I8 -> intermediate IA
|
||||
ia *raw2i(const uint8_t *raw, int width, int height, int depth);
|
||||
|
||||
//---------------------------------------------------------
|
||||
// intermediate RGBA/IA -> N64 RGBA/IA/I/CI
|
||||
// returns length written to 'raw' used or -1 on error
|
||||
//---------------------------------------------------------
|
||||
|
||||
// intermediate RGBA -> N64 raw RGBA16/RGBA32
|
||||
int rgba2raw(uint8_t *raw, const rgba *img, int width, int height, int depth);
|
||||
|
||||
// intermediate IA -> N64 raw IA1/IA4/IA8/IA16
|
||||
int ia2raw(uint8_t *raw, const ia *img, int width, int height, int depth);
|
||||
|
||||
// intermediate IA -> N64 raw I4/I8
|
||||
int i2raw(uint8_t *raw, const ia *img, int width, int height, int depth);
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// N64 CI <-> N64 RGBA16/IA16
|
||||
//---------------------------------------------------------
|
||||
|
||||
// N64 CI raw data and palette to raw data (either RGBA16 or IA16)
|
||||
uint8_t *ci2raw(const uint8_t *rawci, const uint8_t *palette, int width, int height, int ci_depth);
|
||||
|
||||
// convert from raw (RGBA16 or IA16) format to CI + palette
|
||||
int raw2ci(uint8_t *rawci, palette_t *pal, const uint8_t *raw, int raw_len, int ci_depth);
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// intermediate RGBA/IA -> PNG
|
||||
//---------------------------------------------------------
|
||||
|
||||
// intermediate RGBA write to PNG file
|
||||
int rgba2png(const char *png_filename, const rgba *img, int width, int height);
|
||||
|
||||
// intermediate IA write to grayscale PNG file
|
||||
int ia2png(const char *png_filename, const ia *img, int width, int height);
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// PNG -> intermediate RGBA/IA
|
||||
//---------------------------------------------------------
|
||||
|
||||
// PNG file -> intermediate RGBA
|
||||
rgba *png2rgba(const char *png_filename, int *width, int *height);
|
||||
|
||||
// PNG file -> intermediate IA
|
||||
ia *png2ia(const char *png_filename, int *width, int *height);
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// version
|
||||
//---------------------------------------------------------
|
||||
|
||||
// get version of underlying graphics reading library
|
||||
const char *n64graphics_get_read_version(void);
|
||||
|
||||
// get version of underlying graphics writing library
|
||||
const char *n64graphics_get_write_version(void);
|
||||
|
||||
#endif // N64GRAPHICS_H_
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,276 @@
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#include <io.h>
|
||||
#include <sys/utime.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
// global verbosity setting
|
||||
int g_verbosity = 0;
|
||||
|
||||
int read_s16_be(unsigned char *buf)
|
||||
{
|
||||
unsigned tmp = read_u16_be(buf);
|
||||
int ret;
|
||||
if (tmp > 0x7FFF) {
|
||||
ret = -((int)0x10000 - (int)tmp);
|
||||
} else {
|
||||
ret = (int)tmp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
float read_f32_be(unsigned char *buf)
|
||||
{
|
||||
union {uint32_t i; float f;} ret;
|
||||
ret.i = read_u32_be(buf);
|
||||
return ret.f;
|
||||
}
|
||||
|
||||
int is_power2(unsigned int val)
|
||||
{
|
||||
while (((val & 1) == 0) && (val > 1)) {
|
||||
val >>= 1;
|
||||
}
|
||||
return (val == 1);
|
||||
}
|
||||
|
||||
void fprint_hex(FILE *fp, const unsigned char *buf, int length)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
fprint_byte(fp, buf[i]);
|
||||
fputc(' ', fp);
|
||||
}
|
||||
}
|
||||
|
||||
void fprint_hex_source(FILE *fp, const unsigned char *buf, int length)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
if (i > 0) fputs(", ", fp);
|
||||
fputs("0x", fp);
|
||||
fprint_byte(fp, buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void print_hex(const unsigned char *buf, int length)
|
||||
{
|
||||
fprint_hex(stdout, buf, length);
|
||||
}
|
||||
|
||||
void swap_bytes(unsigned char *data, long length)
|
||||
{
|
||||
long i;
|
||||
unsigned char tmp;
|
||||
for (i = 0; i < length; i += 2) {
|
||||
tmp = data[i];
|
||||
data[i] = data[i+1];
|
||||
data[i+1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void reverse_endian(unsigned char *data, long length)
|
||||
{
|
||||
long i;
|
||||
unsigned char tmp;
|
||||
for (i = 0; i < length; i += 4) {
|
||||
tmp = data[i];
|
||||
data[i] = data[i+3];
|
||||
data[i+3] = tmp;
|
||||
tmp = data[i+1];
|
||||
data[i+1] = data[i+2];
|
||||
data[i+2] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
long filesize(const char *filename)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(filename, &st) == 0) {
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void touch_file(const char *filename)
|
||||
{
|
||||
int fd;
|
||||
//fd = open(filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666);
|
||||
fd = open(filename, O_WRONLY|O_CREAT, 0666);
|
||||
if (fd >= 0) {
|
||||
utime(filename, NULL);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
long read_file(const char *file_name, unsigned char **data)
|
||||
{
|
||||
FILE *in;
|
||||
unsigned char *in_buf = NULL;
|
||||
long file_size;
|
||||
long bytes_read;
|
||||
in = fopen(file_name, "rb");
|
||||
if (in == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// allocate buffer to read from offset to end of file
|
||||
fseek(in, 0, SEEK_END);
|
||||
file_size = ftell(in);
|
||||
|
||||
// sanity check
|
||||
if (file_size > 256*MB) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
in_buf = malloc(file_size);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
// read bytes
|
||||
bytes_read = fread(in_buf, 1, file_size, in);
|
||||
if (bytes_read != file_size) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
*data = in_buf;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
long write_file(const char *file_name, unsigned char *data, long length)
|
||||
{
|
||||
FILE *out;
|
||||
long bytes_written;
|
||||
// open output file
|
||||
out = fopen(file_name, "wb");
|
||||
if (out == NULL) {
|
||||
perror(file_name);
|
||||
return -1;
|
||||
}
|
||||
bytes_written = fwrite(data, 1, length, out);
|
||||
fclose(out);
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
void generate_filename(const char *in_name, char *out_name, char *extension)
|
||||
{
|
||||
char tmp_name[FILENAME_MAX];
|
||||
int len;
|
||||
int i;
|
||||
strcpy(tmp_name, in_name);
|
||||
len = strlen(tmp_name);
|
||||
for (i = len - 1; i > 0; i--) {
|
||||
if (tmp_name[i] == '.') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i <= 0) {
|
||||
i = len;
|
||||
}
|
||||
tmp_name[i] = '\0';
|
||||
sprintf(out_name, "%s.%s", tmp_name, extension);
|
||||
}
|
||||
|
||||
char *basename(const char *name)
|
||||
{
|
||||
const char *base = name;
|
||||
while (*name) {
|
||||
if (*name++ == '/') {
|
||||
base = name;
|
||||
}
|
||||
}
|
||||
return (char *)base;
|
||||
}
|
||||
|
||||
void make_dir(const char *dir_name)
|
||||
{
|
||||
struct stat st = {0};
|
||||
if (stat(dir_name, &st) == -1) {
|
||||
mkdir(dir_name, 0755);
|
||||
}
|
||||
}
|
||||
|
||||
long copy_file(const char *src_name, const char *dst_name)
|
||||
{
|
||||
unsigned char *buf;
|
||||
long bytes_written;
|
||||
long bytes_read;
|
||||
|
||||
bytes_read = read_file(src_name, &buf);
|
||||
|
||||
if (bytes_read > 0) {
|
||||
bytes_written = write_file(dst_name, buf, bytes_read);
|
||||
if (bytes_written != bytes_read) {
|
||||
bytes_read = -1;
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
void dir_list_ext(const char *dir, const char *extension, dir_list *list)
|
||||
{
|
||||
char *pool;
|
||||
char *pool_ptr;
|
||||
struct dirent *entry;
|
||||
DIR *dfd;
|
||||
int idx;
|
||||
|
||||
dfd = opendir(dir);
|
||||
if (dfd == NULL) {
|
||||
ERROR("Can't open '%s'\n", dir);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pool = malloc(FILENAME_MAX * MAX_DIR_FILES);
|
||||
pool_ptr = pool;
|
||||
|
||||
idx = 0;
|
||||
while ((entry = readdir(dfd)) != NULL && idx < MAX_DIR_FILES) {
|
||||
if (!extension || str_ends_with(entry->d_name, extension)) {
|
||||
sprintf(pool_ptr, "%s/%s", dir, entry->d_name);
|
||||
list->files[idx] = pool_ptr;
|
||||
pool_ptr += strlen(pool_ptr) + 1;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
list->count = idx;
|
||||
|
||||
closedir(dfd);
|
||||
}
|
||||
|
||||
void dir_list_free(dir_list *list)
|
||||
{
|
||||
// assume first entry in array is allocated
|
||||
if (list->files[0]) {
|
||||
free(list->files[0]);
|
||||
list->files[0] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int str_ends_with(const char *str, const char *suffix)
|
||||
{
|
||||
if (!str || !suffix) {
|
||||
return 0;
|
||||
}
|
||||
size_t len_str = strlen(str);
|
||||
size_t len_suffix = strlen(suffix);
|
||||
if (len_suffix > len_str) {
|
||||
return 0;
|
||||
}
|
||||
return (0 == strncmp(str + len_str - len_suffix, suffix, len_suffix));
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
#ifndef UTILS_H_
|
||||
#define UTILS_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// defines
|
||||
|
||||
// printing size_t varies by compiler
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#define SIZE_T_FORMAT "%Iu"
|
||||
#else
|
||||
#define SIZE_T_FORMAT "%zu"
|
||||
#endif
|
||||
|
||||
#define KB 1024
|
||||
#define MB (1024 * KB)
|
||||
|
||||
// number of elements in statically declared array
|
||||
#define DIM(S_ARR_) (sizeof(S_ARR_) / sizeof(S_ARR_[0]))
|
||||
|
||||
#define MIN(A_, B_) ((A_) < (B_) ? (A_) : (B_))
|
||||
#define MAX(A_, B_) ((A_) > (B_) ? (A_) : (B_))
|
||||
|
||||
// align value to N-byte boundary
|
||||
#define ALIGN(VAL_, ALIGNMENT_) (((VAL_) + ((ALIGNMENT_) - 1)) & ~((ALIGNMENT_) - 1))
|
||||
|
||||
// read/write u32/16 big/little endian
|
||||
#define read_u32_be(buf) (unsigned int)(((buf)[0] << 24) + ((buf)[1] << 16) + ((buf)[2] << 8) + ((buf)[3]))
|
||||
#define read_u32_le(buf) (unsigned int)(((buf)[1] << 24) + ((buf)[0] << 16) + ((buf)[3] << 8) + ((buf)[2]))
|
||||
#define write_u32_be(buf, val) do { \
|
||||
(buf)[0] = ((val) >> 24) & 0xFF; \
|
||||
(buf)[1] = ((val) >> 16) & 0xFF; \
|
||||
(buf)[2] = ((val) >> 8) & 0xFF; \
|
||||
(buf)[3] = (val) & 0xFF; \
|
||||
} while(0)
|
||||
#define read_u16_be(buf) (((buf)[0] << 8) + ((buf)[1]))
|
||||
#define write_u16_be(buf, val) do { \
|
||||
(buf)[0] = ((val) >> 8) & 0xFF; \
|
||||
(buf)[1] = ((val)) & 0xFF; \
|
||||
} while(0)
|
||||
|
||||
// print nibbles and bytes
|
||||
#define fprint_nibble(FP, NIB_) fputc((NIB_) < 10 ? ('0' + (NIB_)) : ('A' + (NIB_) - 0xA), FP)
|
||||
#define fprint_byte(FP, BYTE_) do { \
|
||||
fprint_nibble(FP, (BYTE_) >> 4); \
|
||||
fprint_nibble(FP, (BYTE_) & 0x0F); \
|
||||
} while(0)
|
||||
#define print_nibble(NIB_) fprint_nibble(stdout, NIB_)
|
||||
#define print_byte(BYTE_) fprint_byte(stdout, BYTE_)
|
||||
|
||||
// Windows compatibility
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#include <direct.h>
|
||||
#define mkdir(DIR_, PERM_) _mkdir(DIR_)
|
||||
#ifndef strcasecmp
|
||||
#define strcasecmp(A, B) stricmp(A, B)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// typedefs
|
||||
|
||||
#define MAX_DIR_FILES 128
|
||||
typedef struct
|
||||
{
|
||||
char *files[MAX_DIR_FILES];
|
||||
int count;
|
||||
} dir_list;
|
||||
|
||||
// global verbosity setting
|
||||
extern int g_verbosity;
|
||||
|
||||
#define ERROR(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define INFO(...) if (g_verbosity) printf(__VA_ARGS__)
|
||||
#define INFO_HEX(...) if (g_verbosity) print_hex(__VA_ARGS__)
|
||||
|
||||
// functions
|
||||
|
||||
// convert two bytes in big-endian to signed int
|
||||
int read_s16_be(unsigned char *buf);
|
||||
|
||||
// convert four bytes in big-endian to float
|
||||
float read_f32_be(unsigned char *buf);
|
||||
|
||||
// determine if value is power of 2
|
||||
// returns 1 if val is power of 2, 0 otherwise
|
||||
int is_power2(unsigned int val);
|
||||
|
||||
// print buffer as hex bytes
|
||||
// fp: file pointer
|
||||
// buf: buffer to read bytes from
|
||||
// length: length of buffer to print
|
||||
void fprint_hex(FILE *fp, const unsigned char *buf, int length);
|
||||
void fprint_hex_source(FILE *fp, const unsigned char *buf, int length);
|
||||
void print_hex(const unsigned char *buf, int length);
|
||||
|
||||
// perform byteswapping to convert from v64 to z64 ordering
|
||||
void swap_bytes(unsigned char *data, long length);
|
||||
|
||||
// reverse endian to convert from n64 to z64 ordering
|
||||
void reverse_endian(unsigned char *data, long length);
|
||||
|
||||
// get size of file without opening it;
|
||||
// returns file size or negative on error
|
||||
long filesize(const char *file_name);
|
||||
|
||||
// update file timestamp to now, creating it if it doesn't exist
|
||||
void touch_file(const char *filename);
|
||||
|
||||
// read entire contents of file into buffer
|
||||
// returns file size or negative on error
|
||||
long read_file(const char *file_name, unsigned char **data);
|
||||
|
||||
// write buffer to file
|
||||
// returns number of bytes written out or -1 on failure
|
||||
long write_file(const char *file_name, unsigned char *data, long length);
|
||||
|
||||
// generate an output file name from input name by replacing file extension
|
||||
// in_name: input file name
|
||||
// out_name: buffer to write output name in
|
||||
// extension: new file extension to use
|
||||
void generate_filename(const char *in_name, char *out_name, char *extension);
|
||||
|
||||
// extract base filename from file path
|
||||
// name: path to file
|
||||
// returns just the file name after the last '/'
|
||||
char *basename(const char *name);
|
||||
|
||||
// make a directory if it doesn't exist
|
||||
// dir_name: name of the directory
|
||||
void make_dir(const char *dir_name);
|
||||
|
||||
// copy a file from src_name to dst_name. will not make directories
|
||||
// src_name: source file name
|
||||
// dst_name: destination file name
|
||||
long copy_file(const char *src_name, const char *dst_name);
|
||||
|
||||
// list a directory, optionally filtering files by extension
|
||||
// dir: directory to list files in
|
||||
// extension: extension to filter files by (NULL if no filtering)
|
||||
// list: output list and count
|
||||
void dir_list_ext(const char *dir, const char *extension, dir_list *list);
|
||||
|
||||
// free associated date from a directory list
|
||||
// list: directory list filled in by dir_list_ext() call
|
||||
void dir_list_free(dir_list *list);
|
||||
|
||||
// determine if a string ends with another string
|
||||
// str: string to check if ends with 'suffix'
|
||||
// suffix: string to see if 'str' ends with
|
||||
// returns 1 if 'str' ends with 'suffix'
|
||||
int str_ends_with(const char *str, const char *suffix);
|
||||
|
||||
#endif // UTILS_H_
|
||||
Reference in New Issue
Block a user