Revert 60 fps, add as optional patch

This commit is contained in:
Llennpie 2022-09-21 14:05:54 -04:00
parent 0dc19187f0
commit fb4f45871e
20 changed files with 175 additions and 922 deletions

View file

@ -1,8 +1,8 @@
diff --git a/include/types.h b/include/types.h
index b3dc27e..c46bdf0 100644
index 61e99fe4..536b3556 100644
--- a/include/types.h
+++ b/include/types.h
@@ -118,6 +118,10 @@ struct GraphNodeObject_sub
@@ -120,6 +120,10 @@ struct GraphNodeObject_sub
/*0x0A 0x42*/ u16 animTimer;
/*0x0C 0x44*/ s32 animFrameAccelAssist;
/*0x10 0x48*/ s32 animAccel;
@ -13,7 +13,7 @@ index b3dc27e..c46bdf0 100644
};
struct GraphNodeObject
@@ -128,11 +132,22 @@ struct GraphNodeObject
@@ -130,11 +134,22 @@ struct GraphNodeObject
/*0x19*/ s8 unk19;
/*0x1A*/ Vec3s angle;
/*0x20*/ Vec3f pos;
@ -36,7 +36,7 @@ index b3dc27e..c46bdf0 100644
};
struct ObjectNode
@@ -243,6 +258,10 @@ struct Surface
@@ -245,6 +260,10 @@ struct Surface
} normal;
/*0x28*/ f32 originOffset;
/*0x2C*/ struct Object *object;
@ -48,7 +48,7 @@ index b3dc27e..c46bdf0 100644
struct MarioBodyState
diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h
index 802d97a..1b0d677 100644
index 802d97a8..1b0d6772 100644
--- a/src/engine/graph_node.h
+++ b/src/engine/graph_node.h
@@ -110,6 +110,8 @@ struct GraphNodePerspective
@ -112,7 +112,7 @@ index 802d97a..1b0d677 100644
/** A node that allows an object to specify a different culling radius than the
diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c
index 1da535b..49a5c03 100644
index 1da535b9..49a5c03d 100644
--- a/src/engine/surface_collision.c
+++ b/src/engine/surface_collision.c
@@ -8,6 +8,7 @@
@ -232,7 +232,7 @@ index 1da535b..49a5c03 100644
break;
}
diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c
index ac2ee50..323b7d0 100644
index ac2ee50c..323b7d05 100644
--- a/src/engine/surface_load.c
+++ b/src/engine/surface_load.c
@@ -14,6 +14,7 @@
@ -256,10 +256,10 @@ index ac2ee50..323b7d0 100644
surface->vertex2[0] = x2;
surface->vertex3[0] = x3;
diff --git a/src/game/camera.c b/src/game/camera.c
index bde0662..9351dea 100644
index 178f17ec..f0847aa3 100644
--- a/src/game/camera.c
+++ b/src/game/camera.c
@@ -484,6 +484,10 @@ CameraTransition sModeTransitions[] = {
@@ -487,6 +487,10 @@ CameraTransition sModeTransitions[] = {
extern u8 sDanceCutsceneIndexTable[][4];
extern u8 sZoomOutAreaMasks[];
@ -270,7 +270,7 @@ index bde0662..9351dea 100644
/**
* Starts a camera shake triggered by an interaction
*/
@@ -5552,6 +5556,7 @@ s32 set_camera_mode_fixed(struct Camera *c, s16 x, s16 y, s16 z) {
@@ -5782,6 +5786,7 @@ s32 set_camera_mode_fixed(struct Camera *c, s16 x, s16 y, s16 z) {
c->mode = CAMERA_MODE_FIXED;
vec3f_set(c->pos, sFixedModeBasePosition[0], sMarioCamState->pos[1],
sFixedModeBasePosition[2]);
@ -278,7 +278,7 @@ index bde0662..9351dea 100644
}
return basePosSet;
}
@@ -5714,6 +5719,7 @@ BAD_RETURN(s32) cam_rr_enter_building_side(struct Camera *c) {
@@ -5944,6 +5949,7 @@ BAD_RETURN(s32) cam_rr_enter_building_side(struct Camera *c) {
if (c->mode != CAMERA_MODE_FIXED) {
sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT;
c->mode = CAMERA_MODE_FIXED;
@ -286,7 +286,7 @@ index bde0662..9351dea 100644
}
}
@@ -5909,6 +5915,7 @@ BAD_RETURN(s32) cam_castle_enter_lobby(struct Camera *c) {
@@ -6139,6 +6145,7 @@ BAD_RETURN(s32) cam_castle_enter_lobby(struct Camera *c) {
sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT;
set_fixed_cam_axis_sa_lobby(c->mode);
c->mode = CAMERA_MODE_FIXED;
@ -294,7 +294,7 @@ index bde0662..9351dea 100644
}
}
@@ -7279,6 +7286,7 @@ BAD_RETURN(s32) cutscene_unused_loop(UNUSED struct Camera *c) {
@@ -7512,6 +7519,7 @@ BAD_RETURN(s32) cutscene_unused_loop(UNUSED struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_mario_fall_start(struct Camera *c) {
vec3f_set(c->focus, -26.f, 0.f, -137.f);
vec3f_set(c->pos, 165.f, 4725.f, 324.f);
@ -302,7 +302,7 @@ index bde0662..9351dea 100644
}
/**
@@ -7311,6 +7319,7 @@ BAD_RETURN(s32) cutscene_ending_mario_fall(struct Camera *c) {
@@ -7544,6 +7552,7 @@ BAD_RETURN(s32) cutscene_ending_mario_fall(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_mario_land_closeup(struct Camera *c) {
vec3f_set(c->focus, 85.f, 826.f, 250.f);
vec3f_set(c->pos, -51.f, 988.f, -202.f);
@ -310,7 +310,7 @@ index bde0662..9351dea 100644
player2_rotate_cam(c, -0x2000, 0x2000, -0x2000, 0x2000);
}
@@ -7320,6 +7329,7 @@ BAD_RETURN(s32) cutscene_ending_mario_land_closeup(struct Camera *c) {
@@ -7553,6 +7562,7 @@ BAD_RETURN(s32) cutscene_ending_mario_land_closeup(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_reset_spline(UNUSED struct Camera *c) {
sCutsceneVars[9].point[0] = 0.f;
cutscene_reset_spline();
@ -318,7 +318,7 @@ index bde0662..9351dea 100644
}
/**
@@ -7355,6 +7365,7 @@ BAD_RETURN(s32) cutscene_ending_peach_appear_closeup(struct Camera *c) {
@@ -7588,6 +7598,7 @@ BAD_RETURN(s32) cutscene_ending_peach_appear_closeup(struct Camera *c) {
vec3f_set(c->pos, 179.f, 2463.f, -1216.f);
c->pos[1] = gCutsceneFocus->oPosY + 35.f;
vec3f_set(c->focus, gCutsceneFocus->oPosX, gCutsceneFocus->oPosY + 125.f, gCutsceneFocus->oPosZ);
@ -326,7 +326,7 @@ index bde0662..9351dea 100644
}
/**
@@ -7373,6 +7384,7 @@ BAD_RETURN(s32) cutscene_ending_peach_appears(struct Camera *c) {
@@ -7606,6 +7617,7 @@ BAD_RETURN(s32) cutscene_ending_peach_appears(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_peach_descends_start(UNUSED struct Camera *c) {
cutscene_reset_spline();
sCutsceneVars[2].point[1] = 150.f;
@ -334,7 +334,7 @@ index bde0662..9351dea 100644
}
/**
@@ -7459,6 +7471,7 @@ BAD_RETURN(s32) cutscene_ending_peach_wakeup(struct Camera *c) {
@@ -7692,6 +7704,7 @@ BAD_RETURN(s32) cutscene_ending_peach_wakeup(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_dialog(struct Camera *c) {
vec3f_set(c->focus, 11.f, 983.f, -1273.f);
vec3f_set(c->pos, -473.f, 970.f, -1152.f);
@ -342,7 +342,7 @@ index bde0662..9351dea 100644
player2_rotate_cam(c, -0x800, 0x2000, -0x2000, 0x2000);
}
@@ -7469,6 +7482,7 @@ BAD_RETURN(s32) cutscene_ending_kiss_closeup(struct Camera *c) {
@@ -7702,6 +7715,7 @@ BAD_RETURN(s32) cutscene_ending_kiss_closeup(struct Camera *c) {
set_fov_function(CAM_FOV_SET_29);
vec3f_set(c->focus, 350.f, 1034.f, -1216.f);
vec3f_set(c->pos, -149.f, 1021.f, -1216.f);
@ -350,7 +350,7 @@ index bde0662..9351dea 100644
}
/**
@@ -7504,6 +7518,7 @@ BAD_RETURN(s32) cutscene_ending_kiss(struct Camera *c) {
@@ -7737,6 +7751,7 @@ BAD_RETURN(s32) cutscene_ending_kiss(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_look_at_sky(struct Camera *c) {
move_point_along_spline(c->focus, sEndingLookAtSkyFocus, &sCutsceneSplineSegment, &sCutsceneSplineSegmentProgress);
vec3f_set(c->pos, 699.f, 1680.f, -703.f);
@ -358,7 +358,7 @@ index bde0662..9351dea 100644
}
/**
@@ -10340,6 +10355,7 @@ BAD_RETURN(s32) cutscene_door_start(struct Camera *c) {
@@ -10573,6 +10588,7 @@ BAD_RETURN(s32) cutscene_door_start(struct Camera *c) {
BAD_RETURN(s32) cutscene_door_fix_cam(struct Camera *c) {
vec3f_copy(c->pos, sCutsceneVars[0].point);
vec3f_copy(c->focus, sCutsceneVars[1].point);
@ -366,7 +366,7 @@ index bde0662..9351dea 100644
}
/**
@@ -10373,6 +10389,7 @@ BAD_RETURN(s32) cutscene_door_move_behind_mario(struct Camera *c) {
@@ -10606,6 +10622,7 @@ BAD_RETURN(s32) cutscene_door_move_behind_mario(struct Camera *c) {
}
offset_rotated(c->pos, sMarioCamState->pos, camOffset, sCutsceneVars[0].angle);
@ -375,10 +375,10 @@ index bde0662..9351dea 100644
/**
diff --git a/src/game/camera.h b/src/game/camera.h
index 173ab8a..b1abdc4 100644
index 056b8ec6..98bf5f0f 100644
--- a/src/game/camera.h
+++ b/src/game/camera.h
@@ -657,6 +657,8 @@ struct LakituState
@@ -659,6 +659,8 @@ struct LakituState
/// Mario's action from the previous frame. Only used to determine if Mario just finished a dive.
/*0xB8*/ u32 lastFrameAction;
/*0xBC*/ s16 unused;
@ -388,7 +388,7 @@ index 173ab8a..b1abdc4 100644
// bss order hack to not affect BSS order. if possible, remove me, but it will be hard to match otherwise
diff --git a/src/game/envfx_bubbles.c b/src/game/envfx_bubbles.c
index 16a9272..ee1b029 100644
index 16a92720..ee1b029d 100644
--- a/src/game/envfx_bubbles.c
+++ b/src/game/envfx_bubbles.c
@@ -35,6 +35,20 @@ Vtx_t gBubbleTempVtx[3] = {
@ -496,7 +496,7 @@ index 16a9272..ee1b029 100644
gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006AB0);
gSPEndDisplayList(sGfxCursor++);
diff --git a/src/game/envfx_snow.c b/src/game/envfx_snow.c
index c3c14a5..d2212ef 100644
index c3c14a5c..d2212ef6 100644
--- a/src/game/envfx_snow.c
+++ b/src/game/envfx_snow.c
@@ -54,6 +54,26 @@ extern void *tiny_bubble_dl_0B006AB0;
@ -594,7 +594,7 @@ index c3c14a5..d2212ef 100644
gSPDisplayList(gfx++, &tiny_bubble_dl_0B006AB0) gSPEndDisplayList(gfx++);
diff --git a/src/game/envfx_snow.h b/src/game/envfx_snow.h
index 7a83b53..f4acc2d 100644
index 7a83b536..f4acc2de 100644
--- a/src/game/envfx_snow.h
+++ b/src/game/envfx_snow.h
@@ -25,7 +25,8 @@ struct EnvFxParticle {
@ -608,7 +608,7 @@ index 7a83b53..f4acc2d 100644
extern s8 gEnvFxMode;
diff --git a/src/game/hud.c b/src/game/hud.c
index 1540b67..0de6e0b 100644
index 1540b675..0de6e0bb 100644
--- a/src/game/hud.c
+++ b/src/game/hud.c
@@ -59,6 +59,20 @@ static struct UnusedHUDStruct sUnusedHUDValues = { 0x00, 0x0A, 0x00 };
@ -658,7 +658,7 @@ index 1540b67..0de6e0b 100644
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx++),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c
index 7ae9f1e..1c23c96 100644
index 7ae9f1e7..1c23c966 100644
--- a/src/game/ingame_menu.c
+++ b/src/game/ingame_menu.c
@@ -130,6 +130,42 @@ s32 gDialogResponse = 0;
@ -742,7 +742,7 @@ index 7ae9f1e..1c23c96 100644
#endif
}
diff --git a/src/game/level_geo.c b/src/game/level_geo.c
index 4c98e70..abc5121 100644
index 4c98e705..abc51213 100644
--- a/src/game/level_geo.c
+++ b/src/game/level_geo.c
@@ -34,12 +34,16 @@ Gfx *geo_envfx_main(s32 callContext, struct GraphNode *node, Mat4 mtxf) {
@ -763,7 +763,7 @@ index 4c98e70..abc5121 100644
}
SET_HIGH_U16_OF_32(*params, gAreaUpdateCounter);
diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c
index 22b45b3..109d7f7 100644
index 4586cd93..d2084ee5 100644
--- a/src/game/object_helpers.c
+++ b/src/game/object_helpers.c
@@ -1554,6 +1554,7 @@ void cur_obj_set_pos_to_home(void) {
@ -775,7 +775,7 @@ index 22b45b3..109d7f7 100644
void cur_obj_set_pos_to_home_and_stop(void) {
diff --git a/src/game/paintings.c b/src/game/paintings.c
index 6cae19c..a304d4a 100644
index 6cae19c0..a304d4ae 100644
--- a/src/game/paintings.c
+++ b/src/game/paintings.c
@@ -189,6 +189,32 @@ struct Painting **sPaintingGroups[] = {
@ -852,7 +852,7 @@ index 6cae19c..a304d4a 100644
// Update the ripple, may automatically reset the painting's state.
painting_update_ripple_state(painting);
diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c
index d5bf577..71656b4 100644
index c9b5dbb4..5e431c07 100644
--- a/src/game/rendering_graph_node.c
+++ b/src/game/rendering_graph_node.c
@@ -39,6 +39,8 @@
@ -1567,7 +1567,7 @@ index d5bf577..71656b4 100644
node->header.gfx.cameraToObject[0] = gMatStack[gMatStackIndex][3][0];
node->header.gfx.cameraToObject[1] = gMatStack[gMatStackIndex][3][1];
node->header.gfx.cameraToObject[2] = gMatStack[gMatStackIndex][3][2];
@@ -824,9 +1157,12 @@ static void geo_process_object(struct Object *node) {
@@ -826,9 +1159,12 @@ static void geo_process_object(struct Object *node) {
}
if (obj_is_in_view(&node->header.gfx, gMatStack[gMatStackIndex])) {
Mtx *mtx = alloc_display_list(sizeof(*mtx));
@ -1580,7 +1580,7 @@ index d5bf577..71656b4 100644
if (node->header.gfx.sharedChild != NULL) {
gCurGraphNodeObject = (struct GraphNodeObject *) node;
node->header.gfx.sharedChild->parent = &node->header.gfx.node;
@@ -837,11 +1173,16 @@ static void geo_process_object(struct Object *node) {
@@ -839,11 +1175,16 @@ static void geo_process_object(struct Object *node) {
if (node->header.gfx.node.children != NULL) {
geo_process_node_and_siblings(node->header.gfx.node.children);
}
@ -1597,7 +1597,7 @@ index d5bf577..71656b4 100644
}
}
@@ -868,6 +1209,8 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
@@ -870,6 +1211,8 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
Mat4 mat;
Vec3f translation;
Mtx *mtx = alloc_display_list(sizeof(*mtx));
@ -1606,7 +1606,7 @@ index d5bf577..71656b4 100644
#ifdef F3DEX_GBI_2
gSPLookAt(gDisplayListHead++, &lookAt);
@@ -883,6 +1226,14 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
@@ -885,6 +1228,14 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
translation[1] = node->translation[1] / 4.0f;
translation[2] = node->translation[2] / 4.0f;
@ -1621,7 +1621,7 @@ index d5bf577..71656b4 100644
mtxf_translate(mat, translation);
mtxf_copy(gMatStack[gMatStackIndex + 1], *gCurGraphNodeObject->throwMatrix);
gMatStack[gMatStackIndex + 1][3][0] = gMatStack[gMatStackIndex][3][0];
@@ -891,6 +1242,13 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
@@ -893,6 +1244,13 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
mtxf_mul(gMatStack[gMatStackIndex + 1], mat, gMatStack[gMatStackIndex + 1]);
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1],
node->objNode->header.gfx.scale);
@ -1635,7 +1635,7 @@ index d5bf577..71656b4 100644
if (node->fnNode.func != NULL) {
node->fnNode.func(GEO_CONTEXT_HELD_OBJ, &node->fnNode.node,
(struct AllocOnlyPool *) gMatStack[gMatStackIndex + 1]);
@@ -898,12 +1256,15 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
@@ -900,12 +1258,15 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
gMatStackIndex++;
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
@ -1651,7 +1651,7 @@ index d5bf577..71656b4 100644
gCurAnimType = 0;
gCurGraphNodeHeldObject = (void *) node;
if (node->objNode->header.gfx.unk38.curAnim != NULL) {
@@ -918,6 +1279,7 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
@@ -922,6 +1283,7 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
gCurAnimTranslationMultiplier = gGeoTempState.translationMultiplier;
gCurrAnimAttribute = gGeoTempState.attribute;
gCurAnimData = gGeoTempState.data;
@ -1659,7 +1659,7 @@ index d5bf577..71656b4 100644
gMatStackIndex--;
}
@@ -1039,6 +1401,7 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
@@ -1043,6 +1405,7 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
if (node->node.flags & GRAPH_RENDER_ACTIVE) {
Mtx *initialMatrix;
Vp *viewport = alloc_display_list(sizeof(*viewport));
@ -1667,7 +1667,7 @@ index d5bf577..71656b4 100644
gDisplayListHeap = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool),
MEMORY_POOL_LEFT);
@@ -1049,7 +1412,12 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
@@ -1053,7 +1416,12 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
vec3s_set(viewport->vp.vscale, node->width * 4, node->height * 4, 511);
if (b != NULL) {
clear_frame_buffer(clearColor);
@ -1681,7 +1681,7 @@ index d5bf577..71656b4 100644
*viewport = *b;
}
@@ -1057,11 +1425,16 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
@@ -1061,11 +1429,16 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
clear_frame_buffer(clearColor);
make_viewport_clip_rect(c);
}
@ -1700,7 +1700,7 @@ index d5bf577..71656b4 100644
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gCurGraphNodeRoot = node;
diff --git a/src/game/screen_transition.c b/src/game/screen_transition.c
index b49ddaf..d6656af 100644
index b49ddaf5..d6656af2 100644
--- a/src/game/screen_transition.c
+++ b/src/game/screen_transition.c
@@ -16,6 +16,19 @@
@ -1821,7 +1821,7 @@ index b49ddaf..d6656af 100644
switch (transType) {
case WARP_TRANSITION_FADE_FROM_COLOR:
diff --git a/src/menu/intro_geo.c b/src/menu/intro_geo.c
index 37c6752..d823d40 100644
index 37c6752a..d823d40f 100644
--- a/src/menu/intro_geo.c
+++ b/src/menu/intro_geo.c
@@ -1,5 +1,6 @@
@ -1873,7 +1873,7 @@ index 37c6752..d823d40 100644
gSPDisplayList(displayListIter++, &intro_seg7_dl_0700B3A0);
gSPPopMatrix(displayListIter++, G_MTX_MODELVIEW);
diff --git a/src/pc/gfx/gfx_dxgi.cpp b/src/pc/gfx/gfx_dxgi.cpp
index 0467495..fa4eb33 100644
index 04674952..fa4eb33c 100644
--- a/src/pc/gfx/gfx_dxgi.cpp
+++ b/src/pc/gfx/gfx_dxgi.cpp
@@ -36,10 +36,10 @@
@ -1889,11 +1889,33 @@ index 0467495..fa4eb33 100644
#endif
using namespace Microsoft::WRL; // For ComPtr
diff --git a/src/pc/gfx/gfx_opengl.c b/src/pc/gfx/gfx_opengl.c
index 32ccd45e..a656fa59 100644
--- a/src/pc/gfx/gfx_opengl.c
+++ b/src/pc/gfx/gfx_opengl.c
@@ -660,12 +660,12 @@ static void gfx_opengl_on_resize(void) {
u8 frameBreak = 0;
static void gfx_opengl_start_frame(void) {
- //if (frameBreak == 0) {
+ if (frameBreak == 0) {
saturn_update();
- // frameBreak = 1;
- //} else {
- // frameBreak = 0;
- //}
+ frameBreak = 1;
+ } else {
+ frameBreak = 0;
+ }
frame_count++;
diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c
index 0108ca9..28d56ac 100644
index a44a9e70..55454030 100644
--- a/src/pc/gfx/gfx_sdl2.c
+++ b/src/pc/gfx/gfx_sdl2.c
@@ -150,7 +150,11 @@ static inline void gfx_sdl_set_vsync(const bool enabled) {
@@ -153,7 +153,11 @@ static inline void gfx_sdl_set_vsync(const bool enabled) {
if (enabled) {
// try to detect refresh rate
SDL_GL_SetSwapInterval(1);
@ -1906,7 +1928,7 @@ index 0108ca9..28d56ac 100644
if (vblanks) {
printf("determined swap interval: %d\n", vblanks);
SDL_GL_SetSwapInterval(vblanks);
@@ -233,7 +237,7 @@ static void gfx_sdl_init(const char *window_title) {
@@ -240,7 +244,7 @@ static void gfx_sdl_init(const char *window_title) {
gfx_sdl_set_fullscreen();
perf_freq = SDL_GetPerformanceFrequency();
@ -1916,10 +1938,10 @@ index 0108ca9..28d56ac 100644
for (size_t i = 0; i < sizeof(windows_scancode_table) / sizeof(SDL_Scancode); i++) {
inverted_scancode_table[windows_scancode_table[i]] = i;
diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c
index 923e7ea..4fe6161 100644
index 3fa1f790..9785164c 100644
--- a/src/pc/pc_main.c
+++ b/src/pc/pc_main.c
@@ -83,6 +83,25 @@ void send_display_list(struct SPTask *spTask) {
@@ -86,6 +86,25 @@ void send_display_list(struct SPTask *spTask) {
#define SAMPLES_LOW 528
#endif
@ -1945,14 +1967,15 @@ index 923e7ea..4fe6161 100644
void produce_one_frame(void) {
gfx_start_frame();
@@ -110,6 +129,11 @@ void produce_one_frame(void) {
@@ -113,6 +132,12 @@ void produce_one_frame(void) {
audio_api->play((u8 *)audio_buffer, 2 * num_audio_samples * 4);
gfx_end_frame();
+
+ gfx_start_frame();
+ patch_interpolations();
+ send_display_list(gGfxSPTask);
+ if (limit_fps)
+ send_display_list(gGfxSPTask);
+ gfx_end_frame();
}

View file

@ -1,25 +1,19 @@
# Super Mario 64 Enhancements
# Enhancements
This directory contains unofficial patches to the source code that provide various features
and enhancements.
To apply a patch, run `tools/apply_patch.sh [patch]` where `[patch]` is the name of the
.patch file you wish to apply. This will perform all of the patch's changes
to the source code.
To apply a patch, run `git apply [patch]` where `[patch]` is the name of the .patch file you wish to apply. This will perform all of the patch's changes to the source code.
Likewise, to undo the changes from a patch you applied, run
`tools/revert_patch.sh` with the name of the .patch file you wish to undo.
Likewise, to undo the changes from a patch you applied, run `git apply -R` with the name of the .patch file you wish to undo.
To create your own enhancement patch, switch to the `nightly` Git
branch, make your changes to the code (but do not commit), then run `tools/create_patch.sh`.
To create your own enhancement patch, make changes to the source code and run `git diff > my_patch.patch`.
Your changes will be stored in the .patch file you specify.
The following enhancements are included in this directory:
## 60 FPS - `60fps_ex.patch`
## 60 FPS - `60fps_saturn.patch`
This allows the game to be rendered at 60 FPS instead of 30 FPS by interpolation (game logic still runs at 30 FPS).
The Mario head intro is the only exception which is still rendered at 30 FPS.
This is the 60fps patch from [sm64-port](https://github.com/sm64-port/sm64-port/tree/master/enhancements) adapted for sm64ex.
This is the 60fps patch from [sm64ex](https://github.com/sm64pc/sm64ex/tree/nightly/enhancements) adapted for Saturn.

View file

@ -120,10 +120,6 @@ struct GraphNodeObject_sub
/*0x0A 0x42*/ u16 animTimer;
/*0x0C 0x44*/ s32 animFrameAccelAssist;
/*0x10 0x48*/ s32 animAccel;
s16 prevAnimFrame;
s16 prevAnimID;
u32 prevAnimFrameTimestamp;
struct Animation *prevAnimPtr;
};
struct GraphNodeObject
@ -134,22 +130,11 @@ struct GraphNodeObject
/*0x19*/ s8 unk19;
/*0x1A*/ Vec3s angle;
/*0x20*/ Vec3f pos;
Vec3s prevAngle;
Vec3f prevPos;
u32 prevTimestamp;
Vec3f prevShadowPos;
u32 prevShadowPosTimestamp;
/*0x2C*/ Vec3f scale;
Vec3f prevScale;
u32 prevScaleTimestamp;
/*0x38*/ struct GraphNodeObject_sub unk38;
/*0x4C*/ struct SpawnInfo *unk4C;
/*0x50*/ Mat4 *throwMatrix; // matrix ptr
Mat4 prevThrowMatrix;
u32 prevThrowMatrixTimestamp;
Mat4 *throwMatrixInterpolated;
/*0x54*/ Vec3f cameraToObject;
u32 skipInterpolationTimestamp;
};
struct ObjectNode
@ -260,10 +245,6 @@ struct Surface
} normal;
/*0x28*/ f32 originOffset;
/*0x2C*/ struct Object *object;
Vec3s prevVertex1;
Vec3s prevVertex2;
Vec3s prevVertex3;
u32 modifiedTimestamp;
};
struct MarioBodyState

View file

@ -35,6 +35,7 @@
#define GRAPH_NODE_TYPE_ROTATION 0x017
#define GRAPH_NODE_TYPE_OBJECT 0x018
#define GRAPH_NODE_TYPE_ANIMATED_PART 0x019
#define GRAPH_NODE_TYPE_MCOMP_EXTRA 0x022
#define GRAPH_NODE_TYPE_BILLBOARD 0x01A
#define GRAPH_NODE_TYPE_DISPLAY_LIST 0x01B
#define GRAPH_NODE_TYPE_SCALE 0x01C
@ -110,8 +111,6 @@ struct GraphNodePerspective
/*0x1C*/ f32 fov; // horizontal field of view in degrees
/*0x20*/ s16 near; // near clipping plane
/*0x22*/ s16 far; // far clipping plane
f32 prevFov;
f32 prevTimestamp;
};
/** An entry in the master list. It is a linked list of display lists
@ -120,9 +119,7 @@ struct GraphNodePerspective
struct DisplayListNode
{
Mtx *transform;
void *transformInterpolated;
void *displayList;
void *displayListInterpolated;
struct DisplayListNode *next;
};
@ -189,11 +186,7 @@ struct GraphNodeCamera
} config;
/*0x1C*/ Vec3f pos;
/*0x28*/ Vec3f focus;
Vec3f prevPos;
Vec3f prevFocus;
u32 prevTimestamp;
/*0x34*/ Mat4 *matrixPtr; // pointer to look-at matrix of this camera as a Mat4
Mat4 *matrixPtrInterpolated;
/*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
};
@ -234,8 +227,7 @@ struct GraphNodeRotation
/*0x00*/ struct GraphNode node;
/*0x14*/ void *displayList;
/*0x18*/ Vec3s rotation;
Vec3s prevRotation;
u32 prevTimestamp;
u8 pad1E[2];
};
/** GraphNode part that transforms itself and its children based on animation
@ -332,9 +324,6 @@ struct GraphNodeBackground
/*0x00*/ struct FnGraphNode fnNode;
/*0x18*/ s32 unused;
/*0x1C*/ s32 background; // background ID, or rgba5551 color if fnNode.func is null
Vec3f prevCameraPos;
Vec3f prevCameraFocus;
u32 prevCameraTimestamp;
};
/** Renders the object that Mario is holding.
@ -345,8 +334,6 @@ struct GraphNodeHeldObject
/*0x18*/ s32 playerIndex;
/*0x1C*/ struct Object *objNode;
/*0x20*/ Vec3s translation;
Vec3f prevShadowPos;
u32 prevShadowPosTimestamp;
};
/** A node that allows an object to specify a different culling radius than the
@ -405,6 +392,8 @@ struct GraphNodeObject *init_graph_node_object(struct AllocOnlyPool *pool, struc
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 GraphNodeAnimatedPart *init_graph_node_mcomp_extra(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,

View file

@ -8,7 +8,6 @@
#include "surface_collision.h"
#include "surface_load.h"
#include "math_util.h"
#include "game/game_init.h"
/**************************************************
* WALLS *
@ -395,44 +394,26 @@ f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct FloorGeometr
return floorHeight;
}
u8 gInterpolatingSurfaces;
/**
* Iterate through the list of floors and find the first floor under a given point.
*/
static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 x, s32 y, s32 z, f32 *pheight) {
register struct Surface *surf;
register f32 x1, z1, x2, z2, x3, z3;
register s32 x1, z1, x2, z2, x3, z3;
f32 nx, ny, nz;
f32 oo;
f32 height;
struct Surface *floor = NULL;
s32 interpolate;
// Iterate through the list of floors until there are no more floors.
while (surfaceNode != NULL) {
surf = surfaceNode->surface;
surfaceNode = surfaceNode->next;
interpolate = gInterpolatingSurfaces && surf->modifiedTimestamp == gGlobalTimer;
x1 = surf->vertex1[0];
z1 = surf->vertex1[2];
x2 = surf->vertex2[0];
z2 = surf->vertex2[2];
if (interpolate) {
f32 diff = (surf->prevVertex1[0] - x1) * (surf->prevVertex1[0] - x1);
diff += (surf->prevVertex1[1] - surf->vertex1[1]) * (surf->prevVertex1[1] - surf->vertex1[1]);
diff += (surf->prevVertex1[2] - z1) * (surf->prevVertex1[2] - z1);
//printf("%f\n", sqrtf(diff));
if (diff > 10000) {
interpolate = FALSE;
} else {
x1 = (surf->prevVertex1[0] + x1) / 2;
z1 = (surf->prevVertex1[2] + z1) / 2;
x2 = (surf->prevVertex2[0] + x2) / 2;
z2 = (surf->prevVertex2[2] + z2) / 2;
}
}
// Check that the point is within the triangle bounds.
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) < 0) {
@ -442,10 +423,6 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
// To slightly save on computation time, set this later.
x3 = surf->vertex3[0];
z3 = surf->vertex3[2];
if (interpolate) {
x3 = (surf->prevVertex3[0] + x3) / 2;
z3 = (surf->prevVertex3[2] + z3) / 2;
}
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) < 0) {
continue;
@ -465,30 +442,10 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
continue;
}
if (interpolate) {
f32 y1, y2, y3;
f32 mag;
y1 = (surf->prevVertex1[1] + surf->vertex1[1]) / 2;
y2 = (surf->prevVertex2[1] + surf->vertex2[1]) / 2;
y3 = (surf->prevVertex3[1] + surf->vertex3[1]) / 2;
nx = (y2 - y1) * (z3 - z2) - (z2 - z1) * (y3 - y2);
ny = (z2 - z1) * (x3 - x2) - (x2 - x1) * (z3 - z2);
nz = (x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2);
mag = sqrtf(nx * nx + ny * ny + nz * nz);
if (mag < 0.0001) {
continue;
}
mag = (f32)(1.0 / mag);
nx *= mag;
ny *= mag;
nz *= mag;
oo = -(nx * x1 + ny * y1 + nz * z1);
} else {
nx = surf->normal.x;
ny = surf->normal.y;
nz = surf->normal.z;
oo = surf->originOffset;
}
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) {
@ -503,15 +460,6 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
}
*pheight = height;
if (interpolate) {
static struct Surface s;
s.type = surf->type;
s.normal.x = nx;
s.normal.y = ny;
s.normal.z = nz;
s.originOffset = oo;
return &s;
}
floor = surf;
break;
}

View file

@ -14,7 +14,6 @@
#include "game/mario.h"
#include "game/object_list_processor.h"
#include "surface_load.h"
#include "game/game_init.h"
s32 unused8038BE90;
@ -360,11 +359,6 @@ static struct Surface *read_surface_data(s16 *vertexData, s16 **vertexIndices) {
surface = alloc_surface();
vec3s_copy(surface->prevVertex1, surface->vertex1);
vec3s_copy(surface->prevVertex2, surface->vertex2);
vec3s_copy(surface->prevVertex3, surface->vertex3);
surface->modifiedTimestamp = gGlobalTimer;
surface->vertex1[0] = x1;
surface->vertex2[0] = x2;
surface->vertex3[0] = x3;

View file

@ -487,10 +487,6 @@ CameraTransition sModeTransitions[] = {
extern u8 sDanceCutsceneIndexTable[][4];
extern u8 sZoomOutAreaMasks[];
static void skip_camera_interpolation(void) {
gLakituState.skipCameraInterpolationTimestamp = gGlobalTimer;
}
/**
* Starts a camera shake triggered by an interaction
*/
@ -5786,7 +5782,6 @@ s32 set_camera_mode_fixed(struct Camera *c, s16 x, s16 y, s16 z) {
c->mode = CAMERA_MODE_FIXED;
vec3f_set(c->pos, sFixedModeBasePosition[0], sMarioCamState->pos[1],
sFixedModeBasePosition[2]);
skip_camera_interpolation();
}
return basePosSet;
}
@ -5949,7 +5944,6 @@ BAD_RETURN(s32) cam_rr_enter_building_side(struct Camera *c) {
if (c->mode != CAMERA_MODE_FIXED) {
sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT;
c->mode = CAMERA_MODE_FIXED;
skip_camera_interpolation();
}
}
@ -6145,7 +6139,6 @@ BAD_RETURN(s32) cam_castle_enter_lobby(struct Camera *c) {
sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT;
set_fixed_cam_axis_sa_lobby(c->mode);
c->mode = CAMERA_MODE_FIXED;
skip_camera_interpolation();
}
}
@ -7519,7 +7512,6 @@ BAD_RETURN(s32) cutscene_unused_loop(UNUSED struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_mario_fall_start(struct Camera *c) {
vec3f_set(c->focus, -26.f, 0.f, -137.f);
vec3f_set(c->pos, 165.f, 4725.f, 324.f);
skip_camera_interpolation();
}
/**
@ -7552,7 +7544,6 @@ BAD_RETURN(s32) cutscene_ending_mario_fall(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_mario_land_closeup(struct Camera *c) {
vec3f_set(c->focus, 85.f, 826.f, 250.f);
vec3f_set(c->pos, -51.f, 988.f, -202.f);
skip_camera_interpolation();
player2_rotate_cam(c, -0x2000, 0x2000, -0x2000, 0x2000);
}
@ -7562,7 +7553,6 @@ BAD_RETURN(s32) cutscene_ending_mario_land_closeup(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_reset_spline(UNUSED struct Camera *c) {
sCutsceneVars[9].point[0] = 0.f;
cutscene_reset_spline();
skip_camera_interpolation();
}
/**
@ -7598,7 +7588,6 @@ BAD_RETURN(s32) cutscene_ending_peach_appear_closeup(struct Camera *c) {
vec3f_set(c->pos, 179.f, 2463.f, -1216.f);
c->pos[1] = gCutsceneFocus->oPosY + 35.f;
vec3f_set(c->focus, gCutsceneFocus->oPosX, gCutsceneFocus->oPosY + 125.f, gCutsceneFocus->oPosZ);
skip_camera_interpolation();
}
/**
@ -7617,7 +7606,6 @@ BAD_RETURN(s32) cutscene_ending_peach_appears(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_peach_descends_start(UNUSED struct Camera *c) {
cutscene_reset_spline();
sCutsceneVars[2].point[1] = 150.f;
skip_camera_interpolation();
}
/**
@ -7704,7 +7692,6 @@ BAD_RETURN(s32) cutscene_ending_peach_wakeup(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_dialog(struct Camera *c) {
vec3f_set(c->focus, 11.f, 983.f, -1273.f);
vec3f_set(c->pos, -473.f, 970.f, -1152.f);
skip_camera_interpolation();
player2_rotate_cam(c, -0x800, 0x2000, -0x2000, 0x2000);
}
@ -7715,7 +7702,6 @@ BAD_RETURN(s32) cutscene_ending_kiss_closeup(struct Camera *c) {
set_fov_function(CAM_FOV_SET_29);
vec3f_set(c->focus, 350.f, 1034.f, -1216.f);
vec3f_set(c->pos, -149.f, 1021.f, -1216.f);
skip_camera_interpolation();
}
/**
@ -7751,7 +7737,6 @@ BAD_RETURN(s32) cutscene_ending_kiss(struct Camera *c) {
BAD_RETURN(s32) cutscene_ending_look_at_sky(struct Camera *c) {
move_point_along_spline(c->focus, sEndingLookAtSkyFocus, &sCutsceneSplineSegment, &sCutsceneSplineSegmentProgress);
vec3f_set(c->pos, 699.f, 1680.f, -703.f);
skip_camera_interpolation();
}
/**
@ -10588,7 +10573,6 @@ BAD_RETURN(s32) cutscene_door_start(struct Camera *c) {
BAD_RETURN(s32) cutscene_door_fix_cam(struct Camera *c) {
vec3f_copy(c->pos, sCutsceneVars[0].point);
vec3f_copy(c->focus, sCutsceneVars[1].point);
skip_camera_interpolation();
}
/**
@ -10622,7 +10606,6 @@ BAD_RETURN(s32) cutscene_door_move_behind_mario(struct Camera *c) {
}
offset_rotated(c->pos, sMarioCamState->pos, camOffset, sCutsceneVars[0].angle);
skip_camera_interpolation();
}
/**

View file

@ -659,8 +659,6 @@ struct LakituState
/// Mario's action from the previous frame. Only used to determine if Mario just finished a dive.
/*0xB8*/ u32 lastFrameAction;
/*0xBC*/ s16 unused;
u32 skipCameraInterpolationTimestamp;
};
// bss order hack to not affect BSS order. if possible, remove me, but it will be hard to match otherwise

View file

@ -35,20 +35,6 @@ Vtx_t gBubbleTempVtx[3] = {
{ { 0, 0, 0 }, 0, { -498, 964 }, { 0xFF, 0xFF, 0xFF, 0xFF } },
};
static Gfx sGfxSaved[60 / 5];
static Gfx *sBubbleInterpolatedDisplayListPos[60 / 5];
static Vec3s sPrevBubblePositions[60];
void patch_interpolated_bubble_particles(void) {
s32 i;
for (i = 0; i < 60 / 5; i++) {
if (sBubbleInterpolatedDisplayListPos[i] != NULL) {
*sBubbleInterpolatedDisplayListPos[i] = sGfxSaved[i];
sBubbleInterpolatedDisplayListPos[i] = NULL;
}
}
}
/**
* Check whether the particle with the given index is
* laterally within distance of point (x, z). Used to
@ -255,7 +241,6 @@ void envfx_update_whirlpool(void) {
(gEnvFxBuffer + i)->yPos = (i + gEnvFxBuffer)->bubbleY;
(gEnvFxBuffer + i)->unusedBubbleVar = 0;
(gEnvFxBuffer + i)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
envfx_rotate_around_whirlpool(&(gEnvFxBuffer + i)->xPos, &(gEnvFxBuffer + i)->yPos,
&(gEnvFxBuffer + i)->zPos);
@ -314,7 +299,6 @@ void envfx_update_jetstream(void) {
+ coss((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
(gEnvFxBuffer + i)->yPos =
gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + (random_float() * 400.0f - 200.0f);
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
} else {
(gEnvFxBuffer + i)->angleAndDist[1] += 10;
(gEnvFxBuffer + i)->xPos += sins((gEnvFxBuffer + i)->angleAndDist[0]) * 10.0f;
@ -522,12 +506,6 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro
Vec3s vertex1;
Vec3s vertex2;
Vec3s vertex3;
Vec3s interpolatedVertices[3];
static Vec3s prevVertex1;
static Vec3s prevVertex2;
static Vec3s prevVertex3;
static u32 prevTimestamp;
Gfx *gfxStart;
@ -543,52 +521,18 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro
envfx_bubbles_update_switch(mode, camTo, vertex1, vertex2, vertex3);
rotate_triangle_vertices(vertex1, vertex2, vertex3, pitch, yaw);
if (gGlobalTimer == prevTimestamp + 1) {
interpolate_vectors_s16(interpolatedVertices[0], prevVertex1, vertex1);
interpolate_vectors_s16(interpolatedVertices[1], prevVertex2, vertex2);
interpolate_vectors_s16(interpolatedVertices[2], prevVertex3, vertex3);
}
vec3s_copy(prevVertex1, vertex1);
vec3s_copy(prevVertex2, vertex2);
vec3s_copy(prevVertex3, vertex3);
prevTimestamp = gGlobalTimer;
gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006D38);
for (i = 0; i < sBubbleParticleMaxCount; i += 5) {
Vtx *interpolatedVertBuf = alloc_display_list(15 * sizeof(Vtx));
s32 j, k;
gDPPipeSync(sGfxCursor++);
envfx_set_bubble_texture(mode, i);
sBubbleInterpolatedDisplayListPos[i / 5] = sGfxCursor;
for (j = 0; j < 5; j++) {
for (k = 0; k < 3; k++) {
Vtx *v = &interpolatedVertBuf[j * 3 + k];
v->v = gBubbleTempVtx[k];
if (gGlobalTimer != gEnvFxBuffer[i + j].spawnTimestamp && mode != ENVFX_LAVA_BUBBLES) {
v->v.ob[0] = (sPrevBubblePositions[i + j][0] + gEnvFxBuffer[i + j].xPos) / 2.0f + interpolatedVertices[k][0];
v->v.ob[1] = (sPrevBubblePositions[i + j][1] + gEnvFxBuffer[i + j].yPos) / 2.0f + interpolatedVertices[k][1];
v->v.ob[2] = (sPrevBubblePositions[i + j][2] + gEnvFxBuffer[i + j].zPos) / 2.0f + interpolatedVertices[k][2];
} else {
v->v.ob[0] = gEnvFxBuffer[i + j].xPos + interpolatedVertices[k][0];
v->v.ob[1] = gEnvFxBuffer[i + j].yPos + interpolatedVertices[k][1];
v->v.ob[2] = gEnvFxBuffer[i + j].zPos + interpolatedVertices[k][2];
}
}
}
gSPVertex(sGfxCursor++, VIRTUAL_TO_PHYSICAL(interpolatedVertBuf), 15, 0);
append_bubble_vertex_buffer(&sGfxSaved[i / 5], i, vertex1, vertex2, vertex3, (Vtx *) gBubbleTempVtx);
append_bubble_vertex_buffer(sGfxCursor++, i, vertex1, vertex2, vertex3, (Vtx *) gBubbleTempVtx);
gSP1Triangle(sGfxCursor++, 0, 1, 2, 0);
gSP1Triangle(sGfxCursor++, 3, 4, 5, 0);
gSP1Triangle(sGfxCursor++, 6, 7, 8, 0);
gSP1Triangle(sGfxCursor++, 9, 10, 11, 0);
gSP1Triangle(sGfxCursor++, 12, 13, 14, 0);
}
for (i = 0; i < sBubbleParticleMaxCount; i++) {
sPrevBubblePositions[i][0] = gEnvFxBuffer[i].xPos;
sPrevBubblePositions[i][1] = gEnvFxBuffer[i].yPos;
sPrevBubblePositions[i][2] = gEnvFxBuffer[i].zPos;
}
gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006AB0);
gSPEndDisplayList(sGfxCursor++);

View file

@ -59,20 +59,6 @@ static struct UnusedHUDStruct sUnusedHUDValues = { 0x00, 0x0A, 0x00 };
static struct CameraHUD sCameraHUD = { CAM_STATUS_NONE };
static u32 sPowerMeterLastRenderTimestamp;
static s16 sPowerMeterLastY;
static Gfx *sPowerMeterDisplayListPos;
void patch_interpolated_hud(void) {
if (sPowerMeterDisplayListPos != NULL) {
Mtx *mtx = alloc_display_list(sizeof(Mtx));
guTranslate(mtx, (f32) sPowerMeterHUD.x, (f32) sPowerMeterHUD.y, 0);
gSPMatrix(sPowerMeterDisplayListPos, VIRTUAL_TO_PHYSICAL(mtx),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
sPowerMeterDisplayListPos = NULL;
}
}
/**
* Renders a rgba16 16x16 glyph texture from a table list.
*/
@ -125,7 +111,6 @@ void render_power_meter_health_segment(s16 numHealthWedges) {
*/
void render_dl_power_meter(s16 numHealthWedges) {
Mtx *mtx;
f32 interpolatedY;
mtx = alloc_display_list(sizeof(Mtx));
@ -133,15 +118,7 @@ void render_dl_power_meter(s16 numHealthWedges) {
return;
}
if (gGlobalTimer == sPowerMeterLastRenderTimestamp + 1) {
interpolatedY = (sPowerMeterLastY + sPowerMeterHUD.y) / 2.0f;
} else {
interpolatedY = sPowerMeterHUD.y;
}
guTranslate(mtx, (f32) sPowerMeterHUD.x, interpolatedY, 0);
sPowerMeterLastY = sPowerMeterHUD.y;
sPowerMeterLastRenderTimestamp = gGlobalTimer;
sPowerMeterDisplayListPos = gDisplayListHead;
guTranslate(mtx, (f32) sPowerMeterHUD.x, (f32) sPowerMeterHUD.y, 0);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx++),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);

View file

@ -130,42 +130,6 @@ s32 gDialogResponse = 0;
static struct CachedChar { u8 used; u8 data[CHCACHE_BUFLEN]; } charCache[256];
#endif // VERSION
static Gfx *sInterpolatedDialogOffsetPos;
static f32 sInterpolatedDialogOffset;
static Gfx *sInterpolatedDialogRotationPos;
static f32 sInterpolatedDialogScale;
static f32 sInterpolatedDialogRotation;
static Gfx *sInterpolatedDialogZoomPos;
void patch_interpolated_dialog(void) {
Mtx *matrix;
if (sInterpolatedDialogOffsetPos != NULL) {
matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
guTranslate(matrix, 0, sInterpolatedDialogOffset, 0);
gSPMatrix(sInterpolatedDialogOffsetPos, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
sInterpolatedDialogOffsetPos = NULL;
}
if (sInterpolatedDialogRotationPos != NULL) {
matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
guScale(matrix, 1.0 / sInterpolatedDialogScale, 1.0 / sInterpolatedDialogScale, 1.0f);
gSPMatrix(sInterpolatedDialogRotationPos++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
guRotate(matrix, sInterpolatedDialogRotation * 4.0f, 0, 0, 1.0f);
gSPMatrix(sInterpolatedDialogRotationPos, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
sInterpolatedDialogRotationPos = NULL;
}
if (sInterpolatedDialogZoomPos != NULL) {
matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
guTranslate(matrix, 65.0 - (65.0 / sInterpolatedDialogScale), (40.0 / sInterpolatedDialogScale) - 40, 0);
gSPMatrix(sInterpolatedDialogZoomPos++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
guScale(matrix, 1.0 / sInterpolatedDialogScale, 1.0 / sInterpolatedDialogScale, 1.0f);
gSPMatrix(sInterpolatedDialogZoomPos, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
sInterpolatedDialogZoomPos = NULL;
}
}
void create_dl_identity_matrix(void) {
Mtx *matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
@ -1005,14 +969,6 @@ void render_dialog_box_type(struct DialogEntry *dialog, s8 linesPerBox) {
switch (gDialogBoxType) {
case DIALOG_TYPE_ROTATE: // Renders a dialog black box with zoom and rotation
if (gDialogBoxState == DIALOG_STATE_OPENING || gDialogBoxState == DIALOG_STATE_CLOSING) {
sInterpolatedDialogRotationPos = gDisplayListHead;
if (gDialogBoxState == DIALOG_STATE_OPENING) {
sInterpolatedDialogScale = gDialogBoxScale - 2 / 2;
sInterpolatedDialogRotation = gDialogBoxOpenTimer - 7.5f / 2;
} else {
sInterpolatedDialogScale = gDialogBoxScale + 2 / 2;
sInterpolatedDialogRotation = gDialogBoxOpenTimer + 7.5f / 2;
}
create_dl_scale_matrix(MENU_MTX_NOPUSH, 1.0 / gDialogBoxScale, 1.0 / gDialogBoxScale, 1.0f);
// convert the speed into angle
create_dl_rotation_matrix(MENU_MTX_NOPUSH, gDialogBoxOpenTimer * 4.0f, 0, 0, 1.0f);
@ -1021,12 +977,6 @@ void render_dialog_box_type(struct DialogEntry *dialog, s8 linesPerBox) {
break;
case DIALOG_TYPE_ZOOM: // Renders a dialog white box with zoom
if (gDialogBoxState == DIALOG_STATE_OPENING || gDialogBoxState == DIALOG_STATE_CLOSING) {
sInterpolatedDialogZoomPos = gDisplayListHead;
if (gDialogBoxState == DIALOG_STATE_OPENING) {
sInterpolatedDialogScale = gDialogBoxScale - 2 / 2;
} else {
sInterpolatedDialogScale = gDialogBoxScale + 2 / 2;
}
create_dl_translation_matrix(MENU_MTX_NOPUSH, 65.0 - (65.0 / gDialogBoxScale),
(40.0 / gDialogBoxScale) - 40, 0);
create_dl_scale_matrix(MENU_MTX_NOPUSH, 1.0 / gDialogBoxScale, 1.0 / gDialogBoxScale, 1.0f);
@ -1309,8 +1259,6 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l
#ifdef VERSION_EU
gDialogY -= gDialogScrollOffsetY;
#else
sInterpolatedDialogOffset = gDialogScrollOffsetY + dialog->linesPerBox;
sInterpolatedDialogOffsetPos = gDisplayListHead;
create_dl_translation_matrix(MENU_MTX_NOPUSH, 0, (f32) gDialogScrollOffsetY, 0);
#endif
}

View file

@ -1554,7 +1554,6 @@ void cur_obj_set_pos_to_home(void) {
o->oPosX = o->oHomeX;
o->oPosY = o->oHomeY;
o->oPosZ = o->oHomeZ;
o->header.gfx.skipInterpolationTimestamp = gGlobalTimer;
}
void cur_obj_set_pos_to_home_and_stop(void) {

View file

@ -189,32 +189,6 @@ struct Painting **sPaintingGroups[] = {
s16 gPaintingUpdateCounter = 1;
s16 gLastPaintingUpdateCounter = 0;
static Vtx sLastVertices[2 * 264 * 3];
static u32 sLastVerticesTimestamp;
static Vtx *sVerticesPtr[2];
static s32 sVerticesCount;
void patch_interpolated_paintings(void) {
if (sVerticesPtr[0] != NULL) {
s32 i;
if (sVerticesPtr[1] != NULL) {
for (i = 0; i < sVerticesCount / 2; i++) {
sVerticesPtr[0][i] = sLastVertices[i];
}
for (; i < sVerticesCount; i++) {
sVerticesPtr[1][i - sVerticesCount / 2] = sLastVertices[i];
}
} else {
for (i = 0; i < sVerticesCount; i++) {
sVerticesPtr[0][i] = sLastVertices[i];
}
}
sVerticesPtr[0] = NULL;
sVerticesPtr[1] = NULL;
sVerticesCount = 0;
}
}
/**
* Stop paintings in paintingGroup from rippling if their id is different from *idptr.
*/
@ -916,23 +890,6 @@ Gfx *render_painting(u8 *img, s16 tWidth, s16 tHeight, s16 *textureMap, s16 mapV
gSP1Triangle(gfx++, group * 3, group * 3 + 1, group * 3 + 2, 0);
}
if (sVerticesCount >= numVtx * 2) {
sVerticesCount = 0;
}
for (map = 0; map < numVtx; map++) {
Vtx v = verts[map];
if (gGlobalTimer == sLastVerticesTimestamp + 1) {
s32 i;
for (i = 0; i < 3; i++) {
verts[map].n.ob[i] = (v.n.ob[i] + sLastVertices[sVerticesCount + map].n.ob[i]) / 2;
verts[map].n.n[i] = (v.n.n[i] + sLastVertices[sVerticesCount + map].n.n[i]) / 2;
}
}
sLastVertices[sVerticesCount + map] = v;
}
sVerticesPtr[sVerticesCount / numVtx] = verts;
sVerticesCount += numVtx;
gSPEndDisplayList(gfx);
return dlist;
}
@ -997,7 +954,6 @@ Gfx *painting_ripple_image(struct Painting *painting) {
meshTris = textureMap[meshVerts * 3 + 1];
gSPDisplayList(gfx++, render_painting(textures[i], tWidth, tHeight, textureMap, meshVerts, meshTris, painting->alpha));
}
sLastVerticesTimestamp = gGlobalTimer;
// Update the ripple, may automatically reset the painting's state.
painting_update_ripple_state(painting);
@ -1035,7 +991,6 @@ Gfx *painting_ripple_env_mapped(struct Painting *painting) {
meshVerts = textureMap[0];
meshTris = textureMap[meshVerts * 3 + 1];
gSPDisplayList(gfx++, render_painting(tArray[0], tWidth, tHeight, textureMap, meshVerts, meshTris, painting->alpha));
sLastVerticesTimestamp = gGlobalTimer;
// Update the ripple, may automatically reset the painting's state.
painting_update_ripple_state(painting);

View file

@ -10,6 +10,7 @@
#include "rendering_graph_node.h"
#include "shadow.h"
#include "sm64.h"
#include "saturn/saturn.h"
/**
* This file contains the code that processes the scene graph for rendering.
@ -39,8 +40,6 @@
s16 gMatStackIndex;
Mat4 gMatStack[32];
Mtx *gMatStackFixed[32];
Mat4 gMatStackInterpolated[32];
Mtx *gMatStackInterpolatedFixed[32];
/**
* Animation nodes have state in global variables, so this struct captures
@ -54,7 +53,6 @@ struct GeoAnimState {
/*0x04*/ f32 translationMultiplier;
/*0x08*/ u16 *attribute;
/*0x0C*/ s16 *data;
s16 prevFrame;
};
// For some reason, this is a GeoAnimState struct, but the current state consists
@ -64,7 +62,6 @@ struct GeoAnimState gGeoTempState;
u8 gCurAnimType;
u8 gCurAnimEnabled;
s16 gCurrAnimFrame;
s16 gPrevAnimFrame;
f32 gCurAnimTranslationMultiplier;
u16 *gCurrAnimAttribute;
s16 *gCurAnimData;
@ -133,46 +130,6 @@ u16 gAreaUpdateCounter = 0;
LookAt lookAt;
#endif
static Gfx *sPerspectivePos;
static Mtx *sPerspectiveMtx;
struct {
Gfx *pos;
void *mtx;
void *displayList;
} gMtxTbl[6400];
s32 gMtxTblSize;
static Gfx *sViewportPos;
static Vp sPrevViewport;
void mtx_patch_interpolated(void) {
s32 i;
if (sPerspectivePos != NULL) {
gSPMatrix(sPerspectivePos, VIRTUAL_TO_PHYSICAL(sPerspectiveMtx), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
}
for (i = 0; i < gMtxTblSize; i++) {
Gfx *pos = gMtxTbl[i].pos;
gSPMatrix(pos++, VIRTUAL_TO_PHYSICAL(gMtxTbl[i].mtx),
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gSPDisplayList(pos++, gMtxTbl[i].displayList);
}
if (sViewportPos != NULL) {
Gfx *saved = gDisplayListHead;
gDisplayListHead = sViewportPos;
make_viewport_clip_rect(&sPrevViewport);
gSPViewport(gDisplayListHead, VIRTUAL_TO_PHYSICAL(&sPrevViewport));
gDisplayListHead = saved;
}
gMtxTblSize = 0;
sPerspectivePos = NULL;
sViewportPos = NULL;
}
/**
* Process a master list node.
*/
@ -200,14 +157,9 @@ static void geo_process_master_list_sub(struct GraphNodeMasterList *node) {
if ((currList = node->listHeads[i]) != NULL) {
gDPSetRenderMode(gDisplayListHead++, modeList->modes[i], mode2List->modes[i]);
while (currList != NULL) {
if ((u32) gMtxTblSize < sizeof(gMtxTbl) / sizeof(gMtxTbl[0])) {
gMtxTbl[gMtxTblSize].pos = gDisplayListHead;
gMtxTbl[gMtxTblSize].mtx = currList->transform;
gMtxTbl[gMtxTblSize++].displayList = currList->displayList;
}
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(currList->transformInterpolated),
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(currList->transform),
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gSPDisplayList(gDisplayListHead++, currList->displayListInterpolated);
gSPDisplayList(gDisplayListHead++, currList->displayList);
currList = currList->next;
}
}
@ -223,7 +175,7 @@ static void geo_process_master_list_sub(struct GraphNodeMasterList *node) {
* parameter. Look at the RenderModeContainer struct to see the corresponding
* render modes of layers.
*/
static void geo_append_display_list2(void *displayList, void *displayListInterpolated, s16 layer) {
static void geo_append_display_list(void *displayList, s16 layer) {
#ifdef F3DEX_GBI_2
gSPLookAt(gDisplayListHead++, &lookAt);
@ -233,9 +185,7 @@ static void geo_append_display_list2(void *displayList, void *displayListInterpo
alloc_only_pool_alloc(gDisplayListHeap, sizeof(struct DisplayListNode));
listNode->transform = gMatStackFixed[gMatStackIndex];
listNode->transformInterpolated = gMatStackInterpolatedFixed[gMatStackIndex];
listNode->displayList = displayList;
listNode->displayListInterpolated = displayListInterpolated;
listNode->next = 0;
if (gCurGraphNodeMasterList->listHeads[layer] == 0) {
gCurGraphNodeMasterList->listHeads[layer] = listNode;
@ -246,10 +196,6 @@ static void geo_append_display_list2(void *displayList, void *displayListInterpo
}
}
static void geo_append_display_list(void *displayList, s16 layer) {
geo_append_display_list2(displayList, displayList, layer);
}
/**
* Process the master list node.
*/
@ -296,9 +242,7 @@ static void geo_process_perspective(struct GraphNodePerspective *node) {
}
if (node->fnNode.node.children != NULL) {
u16 perspNorm;
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
Mtx *mtx = alloc_display_list(sizeof(*mtx));
f32 fovInterpolated;
#ifdef VERSION_EU
f32 aspect = ((f32) gCurGraphNodeRoot->width / (f32) gCurGraphNodeRoot->height) * 1.1f;
@ -307,23 +251,9 @@ static void geo_process_perspective(struct GraphNodePerspective *node) {
#endif
guPerspective(mtx, &perspNorm, node->fov, aspect, node->near, node->far, 1.0f);
gSPPerspNormalize(gDisplayListHead++, perspNorm);
if (gGlobalTimer == node->prevTimestamp + 1 && gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
fovInterpolated = (node->prevFov + node->fov) / 2.0f;
guPerspective(mtxInterpolated, &perspNorm, fovInterpolated, aspect, node->near, node->far, 1.0f);
gSPPerspNormalize(gDisplayListHead++, perspNorm);
sPerspectivePos = gDisplayListHead;
sPerspectiveMtx = mtx;
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtxInterpolated),
G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
} else {
gSPPerspNormalize(gDisplayListHead++, perspNorm);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
}
node->prevFov = node->fov;
node->prevTimestamp = gGlobalTimer;
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
gCurGraphNodeCamFrustum = node;
geo_process_node_and_siblings(node->fnNode.node.children);
@ -368,39 +298,6 @@ static void geo_process_switch(struct GraphNodeSwitchCase *node) {
}
}
void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b) {
res[0] = (a[0] + b[0]) / 2.0f;
res[1] = (a[1] + b[1]) / 2.0f;
res[2] = (a[2] + b[2]) / 2.0f;
}
void interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b) {
res[0] = (a[0] + b[0]) / 2;
res[1] = (a[1] + b[1]) / 2;
res[2] = (a[2] + b[2]) / 2;
}
static s16 interpolate_angle(s16 a, s16 b) {
s32 absDiff = b - a;
if (absDiff < 0) {
absDiff = -absDiff;
}
if (absDiff >= 0x4000 && absDiff <= 0xC000) {
return b;
}
if (absDiff <= 0x8000) {
return (a + b) / 2;
} else {
return (a + b) / 2 + 0x8000;
}
}
static void interpolate_angles(Vec3s res, Vec3s a, Vec3s b) {
res[0] = interpolate_angle(a[0], b[0]);
res[1] = interpolate_angle(a[1], b[1]);
res[2] = interpolate_angle(a[2], b[2]);
}
/**
* Process a camera node.
*/
@ -408,9 +305,6 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
Mat4 cameraTransform;
Mtx *rollMtx = alloc_display_list(sizeof(*rollMtx));
Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
Vec3f posInterpolated;
Vec3f focusInterpolated;
if (node->fnNode.func != NULL) {
node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, gMatStack[gMatStackIndex]);
@ -421,40 +315,12 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
mtxf_lookat(cameraTransform, node->pos, node->focus, node->roll);
mtxf_mul(gMatStack[gMatStackIndex + 1], cameraTransform, gMatStack[gMatStackIndex]);
if (gGlobalTimer == node->prevTimestamp + 1 && gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->prevPos, node->pos);
interpolate_vectors(focusInterpolated, node->prevFocus, node->focus);
float magnitude = 0;
for (int i = 0; i < 3; i++) {
float diff = node->pos[i] - node->prevPos[i];
magnitude += diff * diff;
}
if (magnitude > 500000) {
// Observed ~479000 in BBH when toggling R camera
// Can get over 3 million in VCUTM though...
vec3f_copy(posInterpolated, node->pos);
vec3f_copy(focusInterpolated, node->focus);
}
} else {
vec3f_copy(posInterpolated, node->pos);
vec3f_copy(focusInterpolated, node->focus);
}
vec3f_copy(node->prevPos, node->pos);
vec3f_copy(node->prevFocus, node->focus);
node->prevTimestamp = gGlobalTimer;
mtxf_lookat(cameraTransform, posInterpolated, focusInterpolated, node->roll);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], cameraTransform, gMatStackInterpolated[gMatStackIndex]);
gMatStackIndex++;
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
if (node->fnNode.node.children != 0) {
gCurGraphNodeCamera = node;
node->matrixPtr = &gMatStack[gMatStackIndex];
node->matrixPtrInterpolated = &gMatStackInterpolated[gMatStackIndex];
geo_process_node_and_siblings(node->fnNode.node.children);
gCurGraphNodeCamera = NULL;
}
@ -471,17 +337,13 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation
Mat4 mtxf;
Vec3f translation;
Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
vec3s_to_vec3f(translation, node->translation);
mtxf_rotate_zxy_and_translate(mtxf, translation, node->rotation);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]);
gMatStackIndex++;
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8);
}
@ -500,17 +362,13 @@ static void geo_process_translation(struct GraphNodeTranslation *node) {
Mat4 mtxf;
Vec3f translation;
Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
vec3s_to_vec3f(translation, node->translation);
mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]);
gMatStackIndex++;
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8);
}
@ -528,23 +386,12 @@ static void geo_process_translation(struct GraphNodeTranslation *node) {
static void geo_process_rotation(struct GraphNodeRotation *node) {
Mat4 mtxf;
Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
Vec3s rotationInterpolated;
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->rotation);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
if (gGlobalTimer == node->prevTimestamp + 1) {
interpolate_angles(rotationInterpolated, node->prevRotation, node->rotation);
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, rotationInterpolated);
}
vec3s_copy(node->prevRotation, node->rotation);
node->prevTimestamp = gGlobalTimer;
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]);
gMatStackIndex++;
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8);
}
@ -563,16 +410,12 @@ static void geo_process_scale(struct GraphNodeScale *node) {
UNUSED Mat4 transform;
Vec3f scaleVec;
Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
vec3f_set(scaleVec, node->scale, node->scale, node->scale);
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], scaleVec);
mtxf_scale_vec3f(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex], scaleVec);
gMatStackIndex++;
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8);
}
@ -591,30 +434,21 @@ static void geo_process_scale(struct GraphNodeScale *node) {
static void geo_process_billboard(struct GraphNodeBillboard *node) {
Vec3f translation;
Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
gMatStackIndex++;
vec3s_to_vec3f(translation, node->translation);
mtxf_billboard(gMatStack[gMatStackIndex], gMatStack[gMatStackIndex - 1], translation,
gCurGraphNodeCamera->roll);
mtxf_billboard(gMatStackInterpolated[gMatStackIndex], gMatStackInterpolated[gMatStackIndex - 1], translation,
gCurGraphNodeCamera->roll);
if (gCurGraphNodeHeldObject != NULL) {
mtxf_scale_vec3f(gMatStack[gMatStackIndex], gMatStack[gMatStackIndex],
gCurGraphNodeHeldObject->objNode->header.gfx.scale);
mtxf_scale_vec3f(gMatStackInterpolated[gMatStackIndex], gMatStackInterpolated[gMatStackIndex],
gCurGraphNodeHeldObject->objNode->header.gfx.scale);
} else if (gCurGraphNodeObject != NULL) {
mtxf_scale_vec3f(gMatStack[gMatStackIndex], gMatStack[gMatStackIndex],
gCurGraphNodeObject->scale);
mtxf_scale_vec3f(gMatStackInterpolated[gMatStackIndex], gMatStackInterpolated[gMatStackIndex],
gCurGraphNodeObject->scale);
}
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8);
}
@ -663,39 +497,13 @@ static void geo_process_generated_list(struct GraphNodeGenerated *node) {
*/
static void geo_process_background(struct GraphNodeBackground *node) {
Gfx *list = NULL;
Gfx *listInterpolated = NULL;
if (node->fnNode.func != NULL) {
Vec3f posCopy;
Vec3f focusCopy;
Vec3f posInterpolated;
Vec3f focusInterpolated;
if (gGlobalTimer == node->prevCameraTimestamp + 1 &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->prevCameraPos, gLakituState.pos);
interpolate_vectors(focusInterpolated, node->prevCameraFocus, gLakituState.focus);
} else {
vec3f_copy(posInterpolated, gLakituState.pos);
vec3f_copy(focusInterpolated, gLakituState.focus);
}
vec3f_copy(node->prevCameraPos, gLakituState.pos);
vec3f_copy(node->prevCameraFocus, gLakituState.focus);
node->prevCameraTimestamp = gGlobalTimer;
list = node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node,
(struct AllocOnlyPool *) gMatStack[gMatStackIndex]);
vec3f_copy(posCopy, gLakituState.pos);
vec3f_copy(focusCopy, gLakituState.focus);
vec3f_copy(gLakituState.pos, posInterpolated);
vec3f_copy(gLakituState.focus, focusInterpolated);
listInterpolated = node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, NULL);
vec3f_copy(gLakituState.pos, posCopy);
vec3f_copy(gLakituState.focus, focusCopy);
}
if (list != 0) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(list),
(void *) VIRTUAL_TO_PHYSICAL(listInterpolated), node->fnNode.node.flags >> 8);
geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(list), node->fnNode.node.flags >> 8);
} else if (gCurGraphNodeMasterList != NULL) {
#ifndef F3DEX_GBI_2E
Gfx *gfxStart = alloc_display_list(sizeof(Gfx) * 7);
@ -720,47 +528,6 @@ static void geo_process_background(struct GraphNodeBackground *node) {
}
}
static void anim_process(Vec3f translation, Vec3s rotation, u8 *animType, s16 animFrame, u16 **animAttribute) {
if (*animType == ANIM_TYPE_TRANSLATION) {
translation[0] += gCurAnimData[retrieve_animation_index(animFrame, animAttribute)]
* gCurAnimTranslationMultiplier;
translation[1] += gCurAnimData[retrieve_animation_index(animFrame, animAttribute)]
* gCurAnimTranslationMultiplier;
translation[2] += gCurAnimData[retrieve_animation_index(animFrame, animAttribute)]
* gCurAnimTranslationMultiplier;
*animType = ANIM_TYPE_ROTATION;
} else {
if (*animType == ANIM_TYPE_LATERAL_TRANSLATION) {
translation[0] +=
gCurAnimData[retrieve_animation_index(animFrame, animAttribute)]
* gCurAnimTranslationMultiplier;
*animAttribute += 2;
translation[2] +=
gCurAnimData[retrieve_animation_index(animFrame, animAttribute)]
* gCurAnimTranslationMultiplier;
*animType = ANIM_TYPE_ROTATION;
} else {
if (*animType == ANIM_TYPE_VERTICAL_TRANSLATION) {
*animAttribute += 2;
translation[1] +=
gCurAnimData[retrieve_animation_index(animFrame, animAttribute)]
* gCurAnimTranslationMultiplier;
*animAttribute += 2;
*animType = ANIM_TYPE_ROTATION;
} else if (*animType == ANIM_TYPE_NO_TRANSLATION) {
*animAttribute += 6;
*animType = ANIM_TYPE_ROTATION;
}
}
}
if (*animType == ANIM_TYPE_ROTATION) {
rotation[0] = gCurAnimData[retrieve_animation_index(animFrame, animAttribute)];
rotation[1] = gCurAnimData[retrieve_animation_index(animFrame, animAttribute)];
rotation[2] = gCurAnimData[retrieve_animation_index(animFrame, animAttribute)];
}
}
/**
* Render an animated part. The current animation state is not part of the node
* but set in global variables. If an animated part is skipped, everything afterwards desyncs.
@ -769,32 +536,53 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
Mat4 matrix;
Vec3s rotation;
Vec3f translation;
Vec3s rotationInterpolated;
Vec3f translationInterpolated;
Mtx *matrixPtr = alloc_display_list(sizeof(*matrixPtr));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
u16 *animAttribute = gCurrAnimAttribute;
u8 animType = gCurAnimType;
vec3s_copy(rotation, gVec3sZero);
vec3f_set(translation, node->translation[0], node->translation[1], node->translation[2]);
vec3s_copy(rotationInterpolated, rotation);
vec3f_copy(translationInterpolated, translation);
anim_process(translationInterpolated, rotationInterpolated, &animType, gPrevAnimFrame, &animAttribute);
anim_process(translation, rotation, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
interpolate_vectors(translationInterpolated, translationInterpolated, translation);
interpolate_angles(rotationInterpolated, rotationInterpolated, rotation);
if (gCurAnimType == ANIM_TYPE_TRANSLATION) {
translation[0] += gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]
* gCurAnimTranslationMultiplier;
translation[1] += gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]
* gCurAnimTranslationMultiplier;
translation[2] += gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]
* gCurAnimTranslationMultiplier;
gCurAnimType = ANIM_TYPE_ROTATION;
} else {
if (gCurAnimType == ANIM_TYPE_LATERAL_TRANSLATION) {
translation[0] +=
gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]
* gCurAnimTranslationMultiplier;
gCurrAnimAttribute += 2;
translation[2] +=
gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]
* gCurAnimTranslationMultiplier;
gCurAnimType = ANIM_TYPE_ROTATION;
} else {
if (gCurAnimType == ANIM_TYPE_VERTICAL_TRANSLATION) {
gCurrAnimAttribute += 2;
translation[1] +=
gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]
* gCurAnimTranslationMultiplier;
gCurrAnimAttribute += 2;
gCurAnimType = ANIM_TYPE_ROTATION;
} else if (gCurAnimType == ANIM_TYPE_NO_TRANSLATION) {
gCurrAnimAttribute += 6;
gCurAnimType = ANIM_TYPE_ROTATION;
}
}
}
if (gCurAnimType == ANIM_TYPE_ROTATION) {
rotation[0] = gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)];
rotation[1] = gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)];
rotation[2] = gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)];
}
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]);
mtxf_rotate_xyz_and_translate(matrix, translationInterpolated, rotationInterpolated);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], matrix, gMatStackInterpolated[gMatStackIndex]);
gMatStackIndex++;
mtxf_to_mtx(matrixPtr, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = matrixPtr;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8);
}
@ -804,6 +592,23 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
gMatStackIndex--;
}
/**
* Render an animated part. The current animation state is not part of the node
* but set in global variables. If an animated part is skipped, everything afterwards desyncs.
*/
static void geo_process_mcomp_extra(struct GraphNodeAnimatedPart *node) {
if (is_anim_playing && is_custom_anim) {
geo_process_animated_part(node);
} else {
if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8);
}
if (node->node.children != NULL) {
geo_process_node_and_siblings(node->node.children);
}
}
}
/**
* Initialize the animation-related global variables for the currently drawn
* object's animation.
@ -826,17 +631,6 @@ void geo_set_animation_globals(struct GraphNodeObject_sub *node, s32 hasAnimatio
}
gCurrAnimFrame = node->animFrame;
if (node->prevAnimPtr == anim && node->prevAnimID == node->animID &&
gGlobalTimer == node->prevAnimFrameTimestamp + 1) {
gPrevAnimFrame = node->prevAnimFrame;
} else {
gPrevAnimFrame = node->animFrame;
}
node->prevAnimPtr = anim;
node->prevAnimID = node->animID;
node->prevAnimFrame = node->animFrame;
node->prevAnimFrameTimestamp = gGlobalTimer;
gCurAnimEnabled = (anim->flags & ANIM_FLAG_5) == 0;
gCurrAnimAttribute = segmented_to_virtual((void *) anim->index);
gCurAnimData = segmented_to_virtual((void *) anim->values);
@ -855,10 +649,8 @@ void geo_set_animation_globals(struct GraphNodeObject_sub *node, s32 hasAnimatio
*/
static void geo_process_shadow(struct GraphNodeShadow *node) {
Gfx *shadowList;
Gfx *shadowListInterpolated;
Mat4 mtxf;
Vec3f shadowPos;
Vec3f shadowPosInterpolated;
Vec3f animOffset;
f32 objScale;
f32 shadowScale;
@ -866,7 +658,6 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
f32 cosAng;
struct GraphNode *geo;
Mtx *mtx;
Mtx *mtxInterpolated;
if (gCurGraphNodeCamera != NULL && gCurGraphNodeObject != NULL) {
if (gCurGraphNodeHeldObject != NULL) {
@ -905,57 +696,21 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
}
}
if (gCurGraphNodeHeldObject != NULL) {
if (gGlobalTimer == gCurGraphNodeHeldObject->prevShadowPosTimestamp + 1) {
interpolate_vectors(shadowPosInterpolated, gCurGraphNodeHeldObject->prevShadowPos, shadowPos);
} else {
vec3f_copy(shadowPosInterpolated, shadowPos);
}
vec3f_copy(gCurGraphNodeHeldObject->prevShadowPos, shadowPos);
gCurGraphNodeHeldObject->prevShadowPosTimestamp = gGlobalTimer;
} else {
if (gGlobalTimer == gCurGraphNodeObject->prevShadowPosTimestamp + 1 &&
gGlobalTimer != gCurGraphNodeObject->skipInterpolationTimestamp) {
interpolate_vectors(shadowPosInterpolated, gCurGraphNodeObject->prevShadowPos, shadowPos);
} else {
vec3f_copy(shadowPosInterpolated, shadowPos);
}
vec3f_copy(gCurGraphNodeObject->prevShadowPos, shadowPos);
gCurGraphNodeObject->prevShadowPosTimestamp = gGlobalTimer;
}
extern u8 gInterpolatingSurfaces;
gInterpolatingSurfaces = TRUE;
shadowListInterpolated = create_shadow_below_xyz(shadowPosInterpolated[0], shadowPosInterpolated[1],
shadowPosInterpolated[2], shadowScale,
node->shadowSolidity, node->shadowType);
gInterpolatingSurfaces = FALSE;
shadowList = create_shadow_below_xyz(shadowPos[0], shadowPos[1], shadowPos[2], shadowScale,
node->shadowSolidity, node->shadowType);
if (shadowListInterpolated != NULL && shadowList != NULL) {
if (shadowList != NULL) {
mtx = alloc_display_list(sizeof(*mtx));
mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
gMatStackIndex++;
mtxf_translate(mtxf, shadowPos);
mtxf_mul(gMatStack[gMatStackIndex], mtxf, *gCurGraphNodeCamera->matrixPtr);
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_translate(mtxf, shadowPosInterpolated);
mtxf_mul(gMatStackInterpolated[gMatStackIndex], mtxf, *gCurGraphNodeCamera->matrixPtrInterpolated);
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
if (gShadowAboveWaterOrLava == 1) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList),
(void *) VIRTUAL_TO_PHYSICAL(shadowListInterpolated), 4);
geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), 4);
} else if (gMarioOnIceOrCarpet == 1) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList),
(void *) VIRTUAL_TO_PHYSICAL(shadowListInterpolated), 5);
geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), 5);
} else {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList),
(void *) VIRTUAL_TO_PHYSICAL(shadowListInterpolated), 6);
geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), 6);
}
gMatStackIndex--;
}
@ -1052,101 +807,31 @@ static int obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) {
return TRUE;
}
static void interpolate_matrix(Mat4 result, Mat4 a, Mat4 b) {
s32 i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
result[i][j] = (a[i][j] + b[i][j]) / 2.0f;
}
}
}
/**
* Process an object node.
*/
static void geo_process_object(struct Object *node) {
Mat4 mtxf;
s32 hasAnimation = (node->header.gfx.node.flags & GRAPH_RENDER_HAS_ANIMATION) != 0;
Vec3f scaleInterpolated;
if (node->header.gfx.unk18 == gCurGraphNodeRoot->areaIndex) {
if (node->header.gfx.throwMatrix != NULL) {
mtxf_mul(gMatStack[gMatStackIndex + 1], *node->header.gfx.throwMatrix,
gMatStack[gMatStackIndex]);
if (gGlobalTimer == node->header.gfx.prevThrowMatrixTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp) {
interpolate_matrix(mtxf, *node->header.gfx.throwMatrix, node->header.gfx.prevThrowMatrix);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf,
gMatStackInterpolated[gMatStackIndex]);
} else {
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], (void *) node->header.gfx.throwMatrix,
gMatStackInterpolated[gMatStackIndex]);
}
mtxf_copy(node->header.gfx.prevThrowMatrix, *node->header.gfx.throwMatrix);
node->header.gfx.prevThrowMatrixTimestamp = gGlobalTimer;
} else if (node->header.gfx.node.flags & GRAPH_RENDER_CYLBOARD) {
Vec3f posInterpolated;
if (gGlobalTimer == node->header.gfx.prevTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->header.gfx.prevPos, node->header.gfx.pos);
} else {
vec3f_copy(posInterpolated, node->header.gfx.pos);
}
vec3f_copy(node->header.gfx.prevPos, node->header.gfx.pos);
node->header.gfx.prevTimestamp = gGlobalTimer;
mtxf_cylboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex],
node->header.gfx.pos, gCurGraphNodeCamera->roll);
mtxf_cylboard(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex],
posInterpolated, gCurGraphNodeCamera->roll);
} else if (node->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) {
Vec3f posInterpolated;
if (gGlobalTimer == node->header.gfx.prevTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->header.gfx.prevPos, node->header.gfx.pos);
} else {
vec3f_copy(posInterpolated, node->header.gfx.pos);
}
vec3f_copy(node->header.gfx.prevPos, node->header.gfx.pos);
node->header.gfx.prevTimestamp = gGlobalTimer;
mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex],
node->header.gfx.pos, gCurGraphNodeCamera->roll);
mtxf_billboard(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex],
posInterpolated, gCurGraphNodeCamera->roll);
} else {
Vec3f posInterpolated;
Vec3s angleInterpolated;
if (gGlobalTimer == node->header.gfx.prevTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->header.gfx.prevPos, node->header.gfx.pos);
interpolate_angles(angleInterpolated, node->header.gfx.prevAngle, node->header.gfx.angle);
} else {
vec3f_copy(posInterpolated, node->header.gfx.pos);
vec3s_copy(angleInterpolated, node->header.gfx.angle);
}
vec3f_copy(node->header.gfx.prevPos, node->header.gfx.pos);
vec3s_copy(node->header.gfx.prevAngle, node->header.gfx.angle);
node->header.gfx.prevTimestamp = gGlobalTimer;
mtxf_rotate_zxy_and_translate(mtxf, node->header.gfx.pos, node->header.gfx.angle);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
mtxf_rotate_zxy_and_translate(mtxf, posInterpolated, angleInterpolated);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]);
}
if (gGlobalTimer == node->header.gfx.prevScaleTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp) {
interpolate_vectors(scaleInterpolated, node->header.gfx.prevScale, node->header.gfx.scale);
} else {
vec3f_copy(scaleInterpolated, node->header.gfx.scale);
}
vec3f_copy(node->header.gfx.prevScale, node->header.gfx.scale);
node->header.gfx.prevScaleTimestamp = gGlobalTimer;
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1],
node->header.gfx.scale);
mtxf_scale_vec3f(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex + 1],
scaleInterpolated);
node->header.gfx.throwMatrix = &gMatStack[++gMatStackIndex];
node->header.gfx.throwMatrixInterpolated = &gMatStackInterpolated[gMatStackIndex];
node->header.gfx.cameraToObject[0] = gMatStack[gMatStackIndex][3][0];
node->header.gfx.cameraToObject[1] = gMatStack[gMatStackIndex][3][1];
node->header.gfx.cameraToObject[2] = gMatStack[gMatStackIndex][3][2];
@ -1159,12 +844,9 @@ static void geo_process_object(struct Object *node) {
}
if (obj_is_in_view(&node->header.gfx, gMatStack[gMatStackIndex])) {
Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
if (node->header.gfx.sharedChild != NULL) {
gCurGraphNodeObject = (struct GraphNodeObject *) node;
node->header.gfx.sharedChild->parent = &node->header.gfx.node;
@ -1175,16 +857,11 @@ static void geo_process_object(struct Object *node) {
if (node->header.gfx.node.children != NULL) {
geo_process_node_and_siblings(node->header.gfx.node.children);
}
} else {
node->header.gfx.prevThrowMatrixTimestamp = 0;
node->header.gfx.prevTimestamp = 0;
node->header.gfx.prevScaleTimestamp = 0;
}
gMatStackIndex--;
gCurAnimType = ANIM_TYPE_NONE;
node->header.gfx.throwMatrix = NULL;
node->header.gfx.throwMatrixInterpolated = NULL;
}
}
@ -1211,8 +888,6 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
Mat4 mat;
Vec3f translation;
Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
Vec3f scaleInterpolated;
#ifdef F3DEX_GBI_2
gSPLookAt(gDisplayListHead++, &lookAt);
@ -1228,14 +903,6 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
translation[1] = node->translation[1] / 4.0f;
translation[2] = node->translation[2] / 4.0f;
if (gGlobalTimer == node->objNode->header.gfx.prevScaleTimestamp + 1) {
interpolate_vectors(scaleInterpolated, node->objNode->header.gfx.prevScale, node->objNode->header.gfx.scale);
} else {
vec3f_copy(scaleInterpolated, node->objNode->header.gfx.scale);
}
vec3f_copy(node->objNode->header.gfx.prevScale, node->objNode->header.gfx.scale);
node->objNode->header.gfx.prevScaleTimestamp = gGlobalTimer;
mtxf_translate(mat, translation);
mtxf_copy(gMatStack[gMatStackIndex + 1], *gCurGraphNodeObject->throwMatrix);
gMatStack[gMatStackIndex + 1][3][0] = gMatStack[gMatStackIndex][3][0];
@ -1244,13 +911,6 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
mtxf_mul(gMatStack[gMatStackIndex + 1], mat, gMatStack[gMatStackIndex + 1]);
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1],
node->objNode->header.gfx.scale);
mtxf_copy(gMatStackInterpolated[gMatStackIndex + 1], (void *) gCurGraphNodeObject->throwMatrixInterpolated);
gMatStackInterpolated[gMatStackIndex + 1][3][0] = gMatStackInterpolated[gMatStackIndex][3][0];
gMatStackInterpolated[gMatStackIndex + 1][3][1] = gMatStackInterpolated[gMatStackIndex][3][1];
gMatStackInterpolated[gMatStackIndex + 1][3][2] = gMatStackInterpolated[gMatStackIndex][3][2];
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mat, gMatStackInterpolated[gMatStackIndex + 1]);
mtxf_scale_vec3f(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex + 1],
scaleInterpolated);
if (node->fnNode.func != NULL) {
node->fnNode.func(GEO_CONTEXT_HELD_OBJ, &node->fnNode.node,
(struct AllocOnlyPool *) gMatStack[gMatStackIndex + 1]);
@ -1258,15 +918,12 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
gMatStackIndex++;
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated;
gGeoTempState.type = gCurAnimType;
gGeoTempState.enabled = gCurAnimEnabled;
gGeoTempState.frame = gCurrAnimFrame;
gGeoTempState.translationMultiplier = gCurAnimTranslationMultiplier;
gGeoTempState.attribute = gCurrAnimAttribute;
gGeoTempState.data = gCurAnimData;
gGeoTempState.prevFrame = gPrevAnimFrame;
gCurAnimType = 0;
gCurGraphNodeHeldObject = (void *) node;
if (node->objNode->header.gfx.unk38.curAnim != NULL) {
@ -1283,7 +940,6 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
gCurAnimTranslationMultiplier = gGeoTempState.translationMultiplier;
gCurrAnimAttribute = gGeoTempState.attribute;
gCurAnimData = gGeoTempState.data;
gPrevAnimFrame = gGeoTempState.prevFrame;
gMatStackIndex--;
}
@ -1357,6 +1013,9 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) {
case GRAPH_NODE_TYPE_ANIMATED_PART:
geo_process_animated_part((struct GraphNodeAnimatedPart *) curGraphNode);
break;
case GRAPH_NODE_TYPE_MCOMP_EXTRA:
geo_process_mcomp_extra((struct GraphNodeAnimatedPart *) curGraphNode);
break;
case GRAPH_NODE_TYPE_BILLBOARD:
geo_process_billboard((struct GraphNodeBillboard *) curGraphNode);
break;
@ -1405,7 +1064,6 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
if (node->node.flags & GRAPH_RENDER_ACTIVE) {
Mtx *initialMatrix;
Vp *viewport = alloc_display_list(sizeof(*viewport));
Vp *viewportInterpolated = viewport;
gDisplayListHeap = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool),
MEMORY_POOL_LEFT);
@ -1416,12 +1074,7 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
vec3s_set(viewport->vp.vscale, node->width * 4, node->height * 4, 511);
if (b != NULL) {
clear_frame_buffer(clearColor);
viewportInterpolated = alloc_display_list(sizeof(*viewportInterpolated));
interpolate_vectors_s16(viewportInterpolated->vp.vtrans, sPrevViewport.vp.vtrans, b->vp.vtrans);
interpolate_vectors_s16(viewportInterpolated->vp.vscale, sPrevViewport.vp.vscale, b->vp.vscale);
sViewportPos = gDisplayListHead;
make_viewport_clip_rect(viewportInterpolated);
make_viewport_clip_rect(b);
*viewport = *b;
}
@ -1429,16 +1082,11 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
clear_frame_buffer(clearColor);
make_viewport_clip_rect(c);
}
sPrevViewport = *viewport;
mtxf_identity(gMatStack[gMatStackIndex]);
mtxf_to_mtx(initialMatrix, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = initialMatrix;
mtxf_identity(gMatStackInterpolated[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = initialMatrix;
gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(viewportInterpolated));
gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(viewport));
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(gMatStackFixed[gMatStackIndex]),
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gCurGraphNodeRoot = node;

View file

@ -16,19 +16,6 @@
u8 sTransitionColorFadeCount[4] = { 0 };
u16 sTransitionTextureFadeCount[2] = { 0 };
static Gfx *sScreenTransitionVerticesPos[2];
static Vtx *sScreenTransitionVertices;
void patch_screen_transition_interpolated(void) {
if (sScreenTransitionVerticesPos[0] != NULL) {
gSPVertex(sScreenTransitionVerticesPos[0], VIRTUAL_TO_PHYSICAL(sScreenTransitionVertices), 8, 0);
gSPVertex(sScreenTransitionVerticesPos[1], VIRTUAL_TO_PHYSICAL(sScreenTransitionVertices), 4, 0);
sScreenTransitionVerticesPos[0] = NULL;
sScreenTransitionVerticesPos[1] = NULL;
sScreenTransitionVertices = NULL;
}
}
s32 set_and_reset_transition_fade_timer(s8 fadeTimer, u8 transTime) {
s32 reset = FALSE;
@ -98,29 +85,14 @@ s32 render_fade_transition_into_color(s8 fadeTimer, u8 transTime, struct WarpTra
return dl_transition_color(fadeTimer, transTime, transData, alpha);
}
#if 0
s16 calc_tex_transition_radius(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) {
f32 texRadius = transData->endTexRadius - transData->startTexRadius;
f32 radiusTime = sTransitionColorFadeCount[fadeTimer] * texRadius / (f32)(transTime - 1);
f32 result = transData->startTexRadius + radiusTime;
return (s16)(result + 0.5);
return (s16)(result + 0.5);;
}
#else
s16 calc_tex_transition_radius(s8 fadeTimer, f32 interpolationFraction, s8 transTime, struct WarpTransitionData *transData) {
f32 texRadius = transData->endTexRadius - transData->startTexRadius;
f32 radiusTime = (sTransitionColorFadeCount[fadeTimer] == 0 ? 0 :
sTransitionColorFadeCount[fadeTimer] - 1 + interpolationFraction) * texRadius / (f32)(transTime - 1);
f32 result = transData->startTexRadius + radiusTime;
return (s16)(result + 0.5);
}
#endif
f32 calc_tex_transition_time(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) {
f32 startX = transData->startTexX;
f32 startY = transData->startTexY;
@ -194,8 +166,6 @@ void *sTextureTransitionID[] = {
texture_transition_bowser_half,
};
#if 0
s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData, s8 texID, s8 transTexType) {
f32 texTransTime = calc_tex_transition_time(fadeTimer, transTime, transData);
u16 texTransPos = convert_tex_transition_angle_to_pos(transData);
@ -236,56 +206,6 @@ s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransition
return set_and_reset_transition_fade_timer(fadeTimer, transTime);
}
#else
s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData, s8 texID, s8 transTexType) {
f32 texTransTime = calc_tex_transition_time(fadeTimer, transTime, transData);
u16 texTransPos = convert_tex_transition_angle_to_pos(transData);
s16 centerTransX = center_tex_transition_x(transData, texTransTime, texTransPos);
s16 centerTransY = center_tex_transition_y(transData, texTransTime, texTransPos);
s16 texTransRadius = calc_tex_transition_radius(fadeTimer, 1.0f, transTime, transData);
s16 texTransRadiusInterpolated = calc_tex_transition_radius(fadeTimer, 0.5f, transTime, transData);
Vtx *verts = alloc_display_list(8 * sizeof(*verts));
Vtx *vertsInterpolated = alloc_display_list(8 * sizeof(*vertsInterpolated));
if (verts != NULL && vertsInterpolated != NULL) {
load_tex_transition_vertex(verts, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, transTexType);
load_tex_transition_vertex(vertsInterpolated, fadeTimer, transData, centerTransX, centerTransY, texTransRadiusInterpolated, transTexType);
sScreenTransitionVertices = verts;
gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen)
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2);
sScreenTransitionVerticesPos[0] = gDisplayListHead;
gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(vertsInterpolated), 8, 0);
gSPDisplayList(gDisplayListHead++, dl_transition_draw_filled_region);
gDPPipeSync(gDisplayListHead++);
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2);
gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
switch (transTexType) {
case TRANS_TYPE_MIRROR:
gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], G_IM_FMT_IA, G_IM_SIZ_8b, 32, 64, 0,
G_TX_WRAP | G_TX_MIRROR, G_TX_WRAP | G_TX_MIRROR, 5, 6, G_TX_NOLOD, G_TX_NOLOD);
break;
case TRANS_TYPE_CLAMP:
gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], G_IM_FMT_IA, G_IM_SIZ_8b, 64, 64, 0,
G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD);
break;
}
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
sScreenTransitionVerticesPos[1] = gDisplayListHead;
gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(vertsInterpolated), 4, 0);
gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF);
gSPDisplayList(gDisplayListHead++, dl_screen_transition_end);
sTransitionTextureFadeCount[fadeTimer] += transData->texTimer;
} else {
}
return set_and_reset_transition_fade_timer(fadeTimer, transTime);
}
#endif
int render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData) {
switch (transType) {
case WARP_TRANSITION_FADE_FROM_COLOR:

View file

@ -1,6 +1,5 @@
#include <PR/ultratypes.h>
#include "engine/math_util.h"
#include "game/memory.h"
#include "game/segment2.h"
#include "game/segment7.h"
@ -71,18 +70,6 @@ s8 gameOverBackgroundTable[] = {
s8 gameOverBackgroundFlipOrder[] = { 0x00, 0x01, 0x02, 0x03, 0x07, 0x0B,
0x0a, 0x09, 0x08, 0x04, 0x05, 0x06 };
static Gfx *sIntroScalePos;
static Vec3f sIntroScale;
void patch_title_screen_scales(void) {
if (sIntroScalePos != NULL) {
Mtx *scaleMat = alloc_display_list(sizeof(*scaleMat));
guScale(scaleMat, sIntroScale[0], sIntroScale[1], sIntroScale[2]);
gSPMatrix(sIntroScalePos, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
sIntroScalePos = NULL;
}
}
Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) {
struct GraphNode *graphNode; // sp4c
Gfx *displayList; // sp48
@ -93,8 +80,6 @@ Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) {
f32 scaleX; // sp34
f32 scaleY; // sp30
f32 scaleZ; // sp2c
Vec3f scale;
Vec3f scaleInterpolated;
graphNode = sp54;
displayList = NULL;
displayListIter = NULL;
@ -125,11 +110,7 @@ Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) {
scaleY = 0.0f;
scaleZ = 0.0f;
}
vec3f_set(scale, scaleX, scaleY, scaleZ);
interpolate_vectors(scaleInterpolated, sIntroScale, scale);
vec3f_set(sIntroScale, scaleX, scaleY, scaleZ);
guScale(scaleMat, scaleInterpolated[0], scaleInterpolated[1], scaleInterpolated[2]);
sIntroScalePos = displayListIter;
guScale(scaleMat, scaleX, scaleY, scaleZ);
gSPMatrix(displayListIter++, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
gSPDisplayList(displayListIter++, &intro_seg7_dl_0700B3A0);
gSPPopMatrix(displayListIter++, G_MTX_MODELVIEW);

View file

@ -36,10 +36,10 @@
#ifdef VERSION_EU
#define FRAME_INTERVAL_US_NUMERATOR 40000
#define FRAME_INTERVAL_US_DENOMINATOR 2
#define FRAME_INTERVAL_US_DENOMINATOR 1
#else
#define FRAME_INTERVAL_US_NUMERATOR 100000
#define FRAME_INTERVAL_US_DENOMINATOR 6
#define FRAME_INTERVAL_US_DENOMINATOR 3
#endif
using namespace Microsoft::WRL; // For ComPtr

View file

@ -660,12 +660,12 @@ static void gfx_opengl_on_resize(void) {
u8 frameBreak = 0;
static void gfx_opengl_start_frame(void) {
if (frameBreak == 0) {
//if (frameBreak == 0) {
saturn_update();
frameBreak = 1;
} else {
frameBreak = 0;
}
// frameBreak = 1;
//} else {
// frameBreak = 0;
//}
frame_count++;

View file

@ -153,11 +153,7 @@ static inline void gfx_sdl_set_vsync(const bool enabled) {
if (enabled) {
// try to detect refresh rate
SDL_GL_SetSwapInterval(1);
int vblanks = test_vsync();
if (vblanks & 1)
vblanks = 0; // not divisible by 60, fuck that
else
vblanks /= 2;
const int vblanks = gCLIOpts.SyncFrames ? (int)gCLIOpts.SyncFrames : test_vsync();
if (vblanks) {
printf("determined swap interval: %d\n", vblanks);
SDL_GL_SetSwapInterval(vblanks);
@ -205,7 +201,7 @@ static void gfx_sdl_reset_dimension_and_pos(void) {
int ypos = (configWindow.y == WAPI_WIN_CENTERPOS) ? SDL_WINDOWPOS_CENTERED : configWindow.y;
SDL_SetWindowSize(wnd, configWindow.w, configWindow.h);
SDL_SetWindowPosition(wnd, xpos, ypos);
SDL_SetWindowPosition(wnd, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
// in case vsync changed
gfx_sdl_set_vsync(configWindow.vsync);
}
@ -244,7 +240,7 @@ static void gfx_sdl_init(const char *window_title) {
gfx_sdl_set_fullscreen();
perf_freq = SDL_GetPerformanceFrequency();
frame_time = perf_freq / (2 * FRAMERATE);
frame_time = perf_freq / FRAMERATE;
for (size_t i = 0; i < sizeof(windows_scancode_table) / sizeof(SDL_Scancode); i++) {
inverted_scancode_table[windows_scancode_table[i]] = i;

View file

@ -86,25 +86,6 @@ void send_display_list(struct SPTask *spTask) {
#define SAMPLES_LOW 528
#endif
static inline void patch_interpolations(void) {
extern void mtx_patch_interpolated(void);
extern void patch_screen_transition_interpolated(void);
extern void patch_title_screen_scales(void);
extern void patch_interpolated_dialog(void);
extern void patch_interpolated_hud(void);
extern void patch_interpolated_paintings(void);
extern void patch_interpolated_bubble_particles(void);
extern void patch_interpolated_snow_particles(void);
mtx_patch_interpolated();
patch_screen_transition_interpolated();
patch_title_screen_scales();
patch_interpolated_dialog();
patch_interpolated_hud();
patch_interpolated_paintings();
patch_interpolated_bubble_particles();
patch_interpolated_snow_particles();
}
void produce_one_frame(void) {
gfx_start_frame();
@ -132,12 +113,6 @@ void produce_one_frame(void) {
audio_api->play((u8 *)audio_buffer, 2 * num_audio_samples * 4);
gfx_end_frame();
gfx_start_frame();
patch_interpolations();
if (limit_fps)
send_display_list(gGfxSPTask);
gfx_end_frame();
}
void audio_shutdown(void) {