diff --git a/enhancements/60fps_alpha.patch b/enhancements/60fps_alpha.patch index ee23c7d3..e7d0547a 100644 --- a/enhancements/60fps_alpha.patch +++ b/enhancements/60fps_alpha.patch @@ -2,17 +2,14 @@ diff --git a/include/types.h b/include/types.h index b3dc27e2..c46bdf01 100644 --- a/include/types.h +++ b/include/types.h -@@ -119,4 +119,8 @@ struct GraphNodeObject_sub - /*0x0C 0x44*/ s32 animFrameAccelAssist; +@@ -120,2 +120,6 @@ struct GraphNodeObject_sub /*0x10 0x48*/ s32 animAccel; + s16 prevAnimFrame; + s16 prevAnimID; + u32 prevAnimFrameTimestamp; + struct Animation *prevAnimPtr; }; - -@@ -129,9 +133,20 @@ struct GraphNodeObject - /*0x1A*/ Vec3s angle; +@@ -130,3 +134,10 @@ struct GraphNodeObject /*0x20*/ Vec3f pos; + Vec3s prevAngle; + Vec3f prevPos; @@ -23,7 +20,7 @@ index b3dc27e2..c46bdf01 100644 + Vec3f prevScale; + u32 prevScaleTimestamp; /*0x38*/ struct GraphNodeObject_sub unk38; - /*0x4C*/ struct SpawnInfo *unk4C; +@@ -134,3 +145,7 @@ struct GraphNodeObject /*0x50*/ Mat4 *throwMatrix; // matrix ptr + Mat4 prevThrowMatrix; + u32 prevThrowMatrixTimestamp; @@ -31,37 +28,29 @@ index b3dc27e2..c46bdf01 100644 /*0x54*/ Vec3f cameraToObject; + u32 skipInterpolationTimestamp; }; - -@@ -244,4 +259,8 @@ struct Surface - /*0x28*/ f32 originOffset; +@@ -245,2 +260,6 @@ struct Surface /*0x2C*/ struct Object *object; + Vec3s prevVertex1; + Vec3s prevVertex2; + Vec3s prevVertex3; + u32 modifiedTimestamp; }; - diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index 802d97a8..1b0d6772 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h -@@ -111,4 +111,6 @@ struct GraphNodePerspective - /*0x20*/ s16 near; // near clipping plane +@@ -112,2 +112,4 @@ struct GraphNodePerspective /*0x22*/ s16 far; // far clipping plane + f32 prevFov; + f32 prevTimestamp; }; - -@@ -119,5 +121,7 @@ struct DisplayListNode - { +@@ -120,3 +122,5 @@ struct DisplayListNode Mtx *transform; + void *transformInterpolated; void *displayList; + void *displayListInterpolated; struct DisplayListNode *next; - }; -@@ -186,5 +190,9 @@ struct GraphNodeCamera - /*0x1C*/ Vec3f pos; +@@ -187,3 +191,7 @@ struct GraphNodeCamera /*0x28*/ Vec3f focus; + Vec3f prevPos; + Vec3f prevFocus; @@ -69,67 +58,50 @@ index 802d97a8..1b0d6772 100644 /*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 -@@ -227,5 +235,6 @@ struct GraphNodeRotation - /*0x14*/ void *displayList; +@@ -228,3 +236,4 @@ struct GraphNodeRotation /*0x18*/ Vec3s rotation; - u8 pad1E[2]; + Vec3s prevRotation; + u32 prevTimestamp; }; - -@@ -324,4 +333,7 @@ struct GraphNodeBackground - /*0x18*/ s32 unused; +@@ -325,2 +334,5 @@ struct GraphNodeBackground /*0x1C*/ s32 background; // background ID, or rgba5551 color if fnNode.func is null + Vec3f prevCameraPos; + Vec3f prevCameraFocus; + u32 prevCameraTimestamp; }; - -@@ -334,4 +346,6 @@ struct GraphNodeHeldObject - /*0x1C*/ struct Object *objNode; +@@ -335,2 +347,4 @@ struct GraphNodeHeldObject /*0x20*/ Vec3s translation; + Vec3f prevShadowPos; + u32 prevShadowPosTimestamp; }; - diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 5b6775fe..2c11e254 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c -@@ -9,4 +9,5 @@ - #include "surface_load.h" +@@ -10,2 +10,3 @@ #include "math_util.h" +#include "game/game_init.h" - /************************************************** -@@ -395,4 +396,6 @@ f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct FloorGeometr - } +@@ -396,2 +397,4 @@ f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct FloorGeometr +u8 gInterpolatingSurfaces; + /** - * Iterate through the list of floors and find the first floor under a given point. -@@ -400,9 +403,10 @@ f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct FloorGeometr - static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 x, s32 y, s32 z, f32 *pheight) { +@@ -401,3 +404,3 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 register struct Surface *surf; - register s32 x1, z1, x2, z2, x3, z3; + register f32 x1, z1, x2, z2, x3, z3; f32 nx, ny, nz; - f32 oo; - f32 height; +@@ -406,2 +409,3 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 struct Surface *floor = NULL; + s32 interpolate; - // Iterate through the list of floors until there are no more floors. -@@ -410,4 +414,5 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 - surf = surfaceNode->surface; +@@ -411,2 +415,3 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 surfaceNode = surfaceNode->next; + interpolate = gInterpolatingSurfaces && surf->modifiedTimestamp == gGlobalTimer; - x1 = surf->vertex1[0]; -@@ -415,4 +420,18 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 - x2 = surf->vertex2[0]; +@@ -416,2 +421,16 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 z2 = surf->vertex2[2]; + if (interpolate) { + f32 diff = (surf->prevVertex1[0] - x1) * (surf->prevVertex1[0] - x1); @@ -146,18 +118,14 @@ index 5b6775fe..2c11e254 100644 + } + } - // Check that the point is within the triangle bounds. -@@ -424,4 +443,8 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 - x3 = surf->vertex3[0]; +@@ -425,2 +444,6 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 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) { -@@ -443,8 +466,28 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 - } +@@ -444,6 +467,26 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 - nx = surf->normal.x; - ny = surf->normal.y; @@ -188,9 +156,7 @@ index 5b6775fe..2c11e254 100644 + oo = surf->originOffset; + } - // If a wall, ignore it. Likely a remnant, should never occur. -@@ -461,4 +504,13 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 - +@@ -462,2 +505,11 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 *pheight = height; + if (interpolate) { + static struct Surface s; @@ -202,19 +168,15 @@ index 5b6775fe..2c11e254 100644 + return &s; + } floor = surf; - break; diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index ac2ee50c..323b7d05 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c -@@ -15,4 +15,5 @@ - #include "game/object_list_processor.h" +@@ -16,2 +16,3 @@ #include "surface_load.h" +#include "game/game_init.h" - s32 unused8038BE90; -@@ -360,4 +361,9 @@ static struct Surface *read_surface_data(s16 *vertexData, s16 **vertexIndices) { - surface = alloc_surface(); +@@ -361,2 +362,7 @@ static struct Surface *read_surface_data(s16 *vertexData, s16 **vertexIndices) { + vec3s_copy(surface->prevVertex1, surface->vertex1); + vec3s_copy(surface->prevVertex2, surface->vertex2); @@ -222,115 +184,83 @@ index ac2ee50c..323b7d05 100644 + surface->modifiedTimestamp = gGlobalTimer; + surface->vertex1[0] = x1; - surface->vertex2[0] = x2; diff --git a/src/game/camera.c b/src/game/camera.c index bde06626..9351dea4 100644 --- a/src/game/camera.c +++ b/src/game/camera.c -@@ -485,4 +485,8 @@ extern u8 sDanceCutsceneIndexTable[][4]; - extern u8 sZoomOutAreaMasks[]; +@@ -486,2 +486,6 @@ extern u8 sZoomOutAreaMasks[]; +static void skip_camera_interpolation(void) { + gLakituState.skipCameraInterpolationTimestamp = gGlobalTimer; +} + /** - * Starts a camera shake triggered by an interaction -@@ -5553,4 +5557,5 @@ s32 set_camera_mode_fixed(struct Camera *c, s16 x, s16 y, s16 z) { - vec3f_set(c->pos, sFixedModeBasePosition[0], sMarioCamState->pos[1], +@@ -5554,2 +5558,3 @@ s32 set_camera_mode_fixed(struct Camera *c, s16 x, s16 y, s16 z) { sFixedModeBasePosition[2]); + skip_camera_interpolation(); } - return basePosSet; -@@ -5715,4 +5720,5 @@ BAD_RETURN(s32) cam_rr_enter_building_side(struct Camera *c) { - sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT; +@@ -5716,2 +5721,3 @@ BAD_RETURN(s32) cam_rr_enter_building_side(struct Camera *c) { c->mode = CAMERA_MODE_FIXED; + skip_camera_interpolation(); } - } -@@ -5910,4 +5916,5 @@ BAD_RETURN(s32) cam_castle_enter_lobby(struct Camera *c) { - set_fixed_cam_axis_sa_lobby(c->mode); +@@ -5911,2 +5917,3 @@ BAD_RETURN(s32) cam_castle_enter_lobby(struct Camera *c) { c->mode = CAMERA_MODE_FIXED; + skip_camera_interpolation(); } - } -@@ -7280,4 +7287,5 @@ BAD_RETURN(s32) cutscene_ending_mario_fall_start(struct Camera *c) { - vec3f_set(c->focus, -26.f, 0.f, -137.f); +@@ -7281,2 +7288,3 @@ BAD_RETURN(s32) cutscene_ending_mario_fall_start(struct Camera *c) { vec3f_set(c->pos, 165.f, 4725.f, 324.f); + skip_camera_interpolation(); } - -@@ -7312,4 +7320,5 @@ BAD_RETURN(s32) cutscene_ending_mario_land_closeup(struct Camera *c) { - vec3f_set(c->focus, 85.f, 826.f, 250.f); +@@ -7313,2 +7321,3 @@ BAD_RETURN(s32) cutscene_ending_mario_land_closeup(struct Camera *c) { vec3f_set(c->pos, -51.f, 988.f, -202.f); + skip_camera_interpolation(); player2_rotate_cam(c, -0x2000, 0x2000, -0x2000, 0x2000); - } -@@ -7321,4 +7330,5 @@ BAD_RETURN(s32) cutscene_ending_reset_spline(UNUSED struct Camera *c) { - sCutsceneVars[9].point[0] = 0.f; +@@ -7322,2 +7331,3 @@ BAD_RETURN(s32) cutscene_ending_reset_spline(UNUSED struct Camera *c) { cutscene_reset_spline(); + skip_camera_interpolation(); } - -@@ -7356,4 +7366,5 @@ BAD_RETURN(s32) cutscene_ending_peach_appear_closeup(struct Camera *c) { - c->pos[1] = gCutsceneFocus->oPosY + 35.f; +@@ -7357,2 +7367,3 @@ BAD_RETURN(s32) cutscene_ending_peach_appear_closeup(struct Camera *c) { vec3f_set(c->focus, gCutsceneFocus->oPosX, gCutsceneFocus->oPosY + 125.f, gCutsceneFocus->oPosZ); + skip_camera_interpolation(); } - -@@ -7374,4 +7385,5 @@ BAD_RETURN(s32) cutscene_ending_peach_descends_start(UNUSED struct Camera *c) { - cutscene_reset_spline(); +@@ -7375,2 +7386,3 @@ BAD_RETURN(s32) cutscene_ending_peach_descends_start(UNUSED struct Camera *c) { sCutsceneVars[2].point[1] = 150.f; + skip_camera_interpolation(); } - -@@ -7460,4 +7472,5 @@ BAD_RETURN(s32) cutscene_ending_dialog(struct Camera *c) { - vec3f_set(c->focus, 11.f, 983.f, -1273.f); +@@ -7461,2 +7473,3 @@ BAD_RETURN(s32) cutscene_ending_dialog(struct Camera *c) { vec3f_set(c->pos, -473.f, 970.f, -1152.f); + skip_camera_interpolation(); player2_rotate_cam(c, -0x800, 0x2000, -0x2000, 0x2000); - } -@@ -7470,4 +7483,5 @@ BAD_RETURN(s32) cutscene_ending_kiss_closeup(struct Camera *c) { - vec3f_set(c->focus, 350.f, 1034.f, -1216.f); +@@ -7471,2 +7484,3 @@ BAD_RETURN(s32) cutscene_ending_kiss_closeup(struct Camera *c) { vec3f_set(c->pos, -149.f, 1021.f, -1216.f); + skip_camera_interpolation(); } - -@@ -7505,4 +7519,5 @@ BAD_RETURN(s32) cutscene_ending_look_at_sky(struct Camera *c) { - move_point_along_spline(c->focus, sEndingLookAtSkyFocus, &sCutsceneSplineSegment, &sCutsceneSplineSegmentProgress); +@@ -7506,2 +7520,3 @@ BAD_RETURN(s32) cutscene_ending_look_at_sky(struct Camera *c) { vec3f_set(c->pos, 699.f, 1680.f, -703.f); + skip_camera_interpolation(); } - -@@ -10341,4 +10356,5 @@ BAD_RETURN(s32) cutscene_door_fix_cam(struct Camera *c) { - vec3f_copy(c->pos, sCutsceneVars[0].point); +@@ -10342,2 +10357,3 @@ BAD_RETURN(s32) cutscene_door_fix_cam(struct Camera *c) { vec3f_copy(c->focus, sCutsceneVars[1].point); + skip_camera_interpolation(); } - -@@ -10374,4 +10390,5 @@ BAD_RETURN(s32) cutscene_door_move_behind_mario(struct Camera *c) { - +@@ -10375,2 +10391,3 @@ BAD_RETURN(s32) cutscene_door_move_behind_mario(struct Camera *c) { offset_rotated(c->pos, sMarioCamState->pos, camOffset, sCutsceneVars[0].angle); + skip_camera_interpolation(); } - diff --git a/src/game/camera.h b/src/game/camera.h index 173ab8a7..b1abdc4f 100644 --- a/src/game/camera.h +++ b/src/game/camera.h -@@ -658,4 +658,6 @@ struct LakituState - /*0xB8*/ u32 lastFrameAction; +@@ -659,2 +659,4 @@ struct LakituState /*0xBC*/ s16 unused; + + u32 skipCameraInterpolationTimestamp; }; - diff --git a/src/game/envfx_bubbles.c b/src/game/envfx_bubbles.c index 16a92720..ee1b029d 100644 --- a/src/game/envfx_bubbles.c +++ b/src/game/envfx_bubbles.c -@@ -36,4 +36,18 @@ Vtx_t gBubbleTempVtx[3] = { - }; +@@ -37,2 +37,16 @@ Vtx_t gBubbleTempVtx[3] = { +static Gfx sGfxSaved[60 / 5]; +static Gfx *sBubbleInterpolatedDisplayListPos[60 / 5]; @@ -347,21 +277,15 @@ index 16a92720..ee1b029d 100644 +} + /** - * Check whether the particle with the given index is -@@ -242,4 +256,5 @@ void envfx_update_whirlpool(void) { - (gEnvFxBuffer + i)->unusedBubbleVar = 0; +@@ -243,2 +257,3 @@ void envfx_update_whirlpool(void) { (gEnvFxBuffer + i)->isAlive = 1; + (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; - envfx_rotate_around_whirlpool(&(gEnvFxBuffer + i)->xPos, &(gEnvFxBuffer + i)->yPos, -@@ -300,4 +315,5 @@ void envfx_update_jetstream(void) { - (gEnvFxBuffer + i)->yPos = +@@ -301,2 +316,3 @@ void envfx_update_jetstream(void) { gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + (random_float() * 400.0f - 200.0f); + (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; } else { - (gEnvFxBuffer + i)->angleAndDist[1] += 10; -@@ -507,4 +523,10 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro - Vec3s vertex2; +@@ -508,2 +524,8 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro Vec3s vertex3; + Vec3s interpolatedVertices[3]; + @@ -370,9 +294,7 @@ index 16a92720..ee1b029d 100644 + static Vec3s prevVertex3; + static u32 prevTimestamp; - Gfx *gfxStart; -@@ -522,10 +544,39 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro - rotate_triangle_vertices(vertex1, vertex2, vertex3, pitch, yaw); +@@ -523,2 +545,12 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro + if (gGlobalTimer == prevTimestamp + 1) { + interpolate_vectors_s16(interpolatedVertices[0], prevVertex1, vertex1); @@ -385,7 +307,7 @@ index 16a92720..ee1b029d 100644 + prevTimestamp = gGlobalTimer; + gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006D38); - +@@ -526,5 +558,24 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro for (i = 0; i < sBubbleParticleMaxCount; i += 5) { + Vtx *interpolatedVertBuf = alloc_display_list(15 * sizeof(Vtx)); + s32 j, k; @@ -411,9 +333,7 @@ index 16a92720..ee1b029d 100644 + gSPVertex(sGfxCursor++, VIRTUAL_TO_PHYSICAL(interpolatedVertBuf), 15, 0); + append_bubble_vertex_buffer(&sGfxSaved[i / 5], i, vertex1, vertex2, vertex3, (Vtx *) gBubbleTempVtx); gSP1Triangle(sGfxCursor++, 0, 1, 2, 0); - gSP1Triangle(sGfxCursor++, 3, 4, 5, 0); -@@ -534,4 +585,9 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro - gSP1Triangle(sGfxCursor++, 12, 13, 14, 0); +@@ -535,2 +586,7 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro } + for (i = 0; i < sBubbleParticleMaxCount; i++) { + sPrevBubblePositions[i][0] = gEnvFxBuffer[i].xPos; @@ -421,13 +341,11 @@ index 16a92720..ee1b029d 100644 + sPrevBubblePositions[i][2] = gEnvFxBuffer[i].zPos; + } - gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006AB0); diff --git a/src/game/envfx_snow.c b/src/game/envfx_snow.c index c3c14a5c..d2212ef6 100644 --- a/src/game/envfx_snow.c +++ b/src/game/envfx_snow.c -@@ -55,4 +55,24 @@ extern void *tiny_bubble_dl_0B006A50; - extern void *tiny_bubble_dl_0B006CD8; +@@ -56,2 +56,22 @@ extern void *tiny_bubble_dl_0B006CD8; +static struct { + Gfx *pos; @@ -450,34 +368,24 @@ index c3c14a5c..d2212ef6 100644 +} + /** - * Initialize snow particles by allocating a buffer for storing their state -@@ -218,4 +238,5 @@ void envfx_update_snow_normal(s32 snowCylinderX, s32 snowCylinderY, s32 snowCyli - (gEnvFxBuffer + i)->yPos = 200.0f * random_float() + snowCylinderY; +@@ -219,2 +239,3 @@ void envfx_update_snow_normal(s32 snowCylinderX, s32 snowCylinderY, s32 snowCyli (gEnvFxBuffer + i)->isAlive = 1; + (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; } else { - (gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2); -@@ -252,4 +273,5 @@ void envfx_update_snow_blizzard(s32 snowCylinderX, s32 snowCylinderY, s32 snowCy - (gEnvFxBuffer + i)->yPos = 400.0f * random_float() - 200.0f + snowCylinderY; +@@ -253,2 +274,3 @@ void envfx_update_snow_blizzard(s32 snowCylinderX, s32 snowCylinderY, s32 snowCy (gEnvFxBuffer + i)->isAlive = 1; + (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; } else { - (gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2) + 20.0f; -@@ -295,4 +317,5 @@ void envfx_update_snow_water(s32 snowCylinderX, s32 snowCylinderY, s32 snowCylin - (gEnvFxBuffer + i)->yPos = 400.0f * random_float() - 200.0f + snowCylinderY; +@@ -296,2 +318,3 @@ void envfx_update_snow_water(s32 snowCylinderX, s32 snowCylinderY, s32 snowCylin (gEnvFxBuffer + i)->isAlive = 1; + (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; } - } -@@ -347,4 +370,6 @@ void append_snowflake_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s ve - s32 i = 0; +@@ -348,2 +371,4 @@ void append_snowflake_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s ve Vtx *vertBuf = (Vtx *) alloc_display_list(15 * sizeof(Vtx)); + Vtx *vertBufInterpolated = (Vtx *) alloc_display_list(15 * sizeof(Vtx)); + Vtx *v; #ifdef VERSION_EU - Vtx *p; -@@ -396,5 +421,21 @@ void append_snowflake_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s ve - } +@@ -397,3 +422,19 @@ void append_snowflake_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s ve - gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBuf), 15, 0); + for (i = 0; i < 15; i++) { @@ -498,32 +406,26 @@ index c3c14a5c..d2212ef6 100644 + sPrevSnowVertices[index / 5].pos = gfx; + gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBufInterpolated), 15, 0); } - -@@ -480,4 +521,6 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo) - gSP1Triangle(gfx++, 12, 13, 14, 0); +@@ -481,2 +522,4 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo) } + sPrevSnowParticleCount = gSnowParticleCount; + sPrevSnowTimestamp = gGlobalTimer; - gSPDisplayList(gfx++, &tiny_bubble_dl_0B006AB0) gSPEndDisplayList(gfx++); diff --git a/src/game/envfx_snow.h b/src/game/envfx_snow.h index 7a83b536..f4acc2de 100644 --- a/src/game/envfx_snow.h +++ b/src/game/envfx_snow.h -@@ -26,5 +26,6 @@ struct EnvFxParticle { - s32 unusedBubbleVar; // set to zero for bubbles when respawning, never used elsewhere +@@ -27,3 +27,4 @@ struct EnvFxParticle { s32 bubbleY; // for Bubbles, yPos is always set to this - s8 filler20[56 - 0x20]; + //s8 filler20[56 - 0x20]; + u32 spawnTimestamp; }; - diff --git a/src/game/hud.c b/src/game/hud.c index 1540b675..0de6e0bb 100644 --- a/src/game/hud.c +++ b/src/game/hud.c -@@ -60,4 +60,18 @@ static struct UnusedHUDStruct sUnusedHUDValues = { 0x00, 0x0A, 0x00 }; - static struct CameraHUD sCameraHUD = { CAM_STATUS_NONE }; +@@ -61,2 +61,16 @@ static struct CameraHUD sCameraHUD = { CAM_STATUS_NONE }; +static u32 sPowerMeterLastRenderTimestamp; +static s16 sPowerMeterLastY; @@ -540,15 +442,11 @@ index 1540b675..0de6e0bb 100644 +} + /** - * Renders a rgba16 16x16 glyph texture from a table list. -@@ -112,4 +126,5 @@ void render_power_meter_health_segment(s16 numHealthWedges) { - void render_dl_power_meter(s16 numHealthWedges) { +@@ -113,2 +127,3 @@ void render_dl_power_meter(s16 numHealthWedges) { Mtx *mtx; + f32 interpolatedY; - mtx = alloc_display_list(sizeof(Mtx)); -@@ -119,5 +134,13 @@ void render_dl_power_meter(s16 numHealthWedges) { - } +@@ -120,3 +135,11 @@ void render_dl_power_meter(s16 numHealthWedges) { - guTranslate(mtx, (f32) sPowerMeterHUD.x, (f32) sPowerMeterHUD.y, 0); + if (gGlobalTimer == sPowerMeterLastRenderTimestamp + 1) { @@ -561,13 +459,11 @@ index 1540b675..0de6e0bb 100644 + sPowerMeterLastRenderTimestamp = gGlobalTimer; + sPowerMeterDisplayListPos = gDisplayListHead; - gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx++), diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 3f02281a..d7d0aced 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c -@@ -117,4 +117,45 @@ u8 gMenuHoldKeyIndex = 0; - u8 gMenuHoldKeyTimer = 0; +@@ -118,2 +118,43 @@ u8 gMenuHoldKeyTimer = 0; s32 gDialogResponse = 0; +static Gfx *sInterpolatedDialogOffsetPos; +static f32 sInterpolatedDialogOffset; @@ -611,9 +507,7 @@ index 3f02281a..d7d0aced 100644 + } +} - void create_dl_identity_matrix(void) { -@@ -939,4 +980,12 @@ void render_dialog_box_type(struct DialogEntry *dialog, s8 linesPerBox) { - case DIALOG_TYPE_ROTATE: // Renders a dialog black box with zoom and rotation +@@ -940,2 +981,10 @@ void render_dialog_box_type(struct DialogEntry *dialog, s8 linesPerBox) { if (gDialogBoxState == DIALOG_STATE_OPENING || gDialogBoxState == DIALOG_STATE_CLOSING) { + sInterpolatedDialogRotationPos = gDisplayListHead; + if (gDialogBoxState == DIALOG_STATE_OPENING) { @@ -624,9 +518,7 @@ index 3f02281a..d7d0aced 100644 + 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 -@@ -947,4 +996,10 @@ void render_dialog_box_type(struct DialogEntry *dialog, s8 linesPerBox) { - case DIALOG_TYPE_ZOOM: // Renders a dialog white box with zoom +@@ -948,2 +997,8 @@ void render_dialog_box_type(struct DialogEntry *dialog, s8 linesPerBox) { if (gDialogBoxState == DIALOG_STATE_OPENING || gDialogBoxState == DIALOG_STATE_CLOSING) { + sInterpolatedDialogZoomPos = gDisplayListHead; + if (gDialogBoxState == DIALOG_STATE_OPENING) { @@ -635,48 +527,38 @@ index 3f02281a..d7d0aced 100644 + sInterpolatedDialogScale = gDialogBoxScale + 2 / 2; + } create_dl_translation_matrix(MENU_MTX_NOPUSH, 65.0 - (65.0 / gDialogBoxScale), - (40.0 / gDialogBoxScale) - 40, 0); -@@ -1229,4 +1284,6 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l - gDialogY -= gDialogScrollOffsetY; +@@ -1230,2 +1285,4 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l #else + sInterpolatedDialogOffset = gDialogScrollOffsetY + dialog->linesPerBox; + sInterpolatedDialogOffsetPos = gDisplayListHead; create_dl_translation_matrix(MENU_MTX_NOPUSH, 0, (f32) gDialogScrollOffsetY, 0); - #endif diff --git a/src/game/level_geo.c b/src/game/level_geo.c index 4c98e705..abc51213 100644 --- a/src/game/level_geo.c +++ b/src/game/level_geo.c -@@ -35,4 +35,5 @@ Gfx *geo_envfx_main(s32 callContext, struct GraphNode *node, Mat4 mtxf) { - particleList = envfx_update_particles(snowMode, marioPos, camTo, camFrom); +@@ -36,2 +36,3 @@ Gfx *geo_envfx_main(s32 callContext, struct GraphNode *node, Mat4 mtxf) { if (particleList != NULL) { +#if 0 Mtx *mtx = alloc_display_list(sizeof(*mtx)); - -@@ -41,4 +42,7 @@ Gfx *geo_envfx_main(s32 callContext, struct GraphNode *node, Mat4 mtxf) { - gSPMatrix(&gfx[0], VIRTUAL_TO_PHYSICAL(mtx), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); +@@ -42,2 +43,5 @@ Gfx *geo_envfx_main(s32 callContext, struct GraphNode *node, Mat4 mtxf) { gSPBranchList(&gfx[1], VIRTUAL_TO_PHYSICAL(particleList)); +#else + gfx = particleList; +#endif execNode->fnNode.node.flags = (execNode->fnNode.node.flags & 0xFF) | 0x400; - } diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index 22b45b32..109d7f74 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c -@@ -1555,4 +1555,5 @@ void cur_obj_set_pos_to_home(void) { - o->oPosY = o->oHomeY; +@@ -1556,2 +1556,3 @@ void cur_obj_set_pos_to_home(void) { o->oPosZ = o->oHomeZ; + o->header.gfx.skipInterpolationTimestamp = gGlobalTimer; } - diff --git a/src/game/paintings.c b/src/game/paintings.c index 6cae19c0..a304d4ae 100644 --- a/src/game/paintings.c +++ b/src/game/paintings.c -@@ -190,4 +190,30 @@ s16 gPaintingUpdateCounter = 1; - s16 gLastPaintingUpdateCounter = 0; +@@ -191,2 +191,28 @@ s16 gLastPaintingUpdateCounter = 0; +static Vtx sLastVertices[2 * 264 * 3]; +static u32 sLastVerticesTimestamp; @@ -705,9 +587,7 @@ index 6cae19c0..a304d4ae 100644 +} + /** - * Stop paintings in paintingGroup from rippling if their id is different from *idptr. -@@ -891,4 +917,21 @@ Gfx *render_painting(u8 *img, s16 tWidth, s16 tHeight, s16 *textureMap, s16 mapV - } +@@ -892,2 +918,19 @@ Gfx *render_painting(u8 *img, s16 tWidth, s16 tHeight, s16 *textureMap, s16 mapV + if (sVerticesCount >= numVtx * 2) { + sVerticesCount = 0; @@ -727,44 +607,32 @@ index 6cae19c0..a304d4ae 100644 + sVerticesCount += numVtx; + gSPEndDisplayList(gfx); - return dlist; -@@ -955,4 +998,5 @@ Gfx *painting_ripple_image(struct Painting *painting) { - gSPDisplayList(gfx++, render_painting(textures[i], tWidth, tHeight, textureMap, meshVerts, meshTris, painting->alpha)); +@@ -956,2 +999,3 @@ Gfx *painting_ripple_image(struct Painting *painting) { } + sLastVerticesTimestamp = gGlobalTimer; - // Update the ripple, may automatically reset the painting's state. -@@ -992,4 +1036,5 @@ Gfx *painting_ripple_env_mapped(struct Painting *painting) { - meshTris = textureMap[meshVerts * 3 + 1]; +@@ -993,2 +1037,3 @@ Gfx *painting_ripple_env_mapped(struct Painting *painting) { 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. diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c -index d5bf5778..143e2032 100644 +index d5bf5778..71656b49 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c -@@ -40,4 +40,6 @@ s16 gMatStackIndex; - Mat4 gMatStack[32]; +@@ -41,2 +41,4 @@ Mat4 gMatStack[32]; Mtx *gMatStackFixed[32]; +Mat4 gMatStackInterpolated[32]; +Mtx *gMatStackInterpolatedFixed[32]; - /** -@@ -53,4 +55,5 @@ struct GeoAnimState { - /*0x08*/ u16 *attribute; +@@ -54,2 +56,3 @@ struct GeoAnimState { /*0x0C*/ s16 *data; + s16 prevFrame; }; - -@@ -62,4 +65,5 @@ u8 gCurAnimType; - u8 gCurAnimEnabled; +@@ -63,2 +66,3 @@ u8 gCurAnimEnabled; s16 gCurrAnimFrame; +s16 gPrevAnimFrame; f32 gCurAnimTranslationMultiplier; - u16 *gCurrAnimAttribute; -@@ -130,4 +134,17 @@ LookAt lookAt; - #endif +@@ -131,2 +135,42 @@ LookAt lookAt; +static Gfx *sPerspectivePos; +static Mtx *sPerspectiveMtx; @@ -778,11 +646,36 @@ index d5bf5778..143e2032 100644 + +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. -@@ -157,7 +174,12 @@ static void geo_process_master_list_sub(struct GraphNodeMasterList *node) { - gDPSetRenderMode(gDisplayListHead++, modeList->modes[i], mode2List->modes[i]); +@@ -158,5 +202,10 @@ static void geo_process_master_list_sub(struct GraphNodeMasterList *node) { while (currList != NULL) { - gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(currList->transform), + if ((u32) gMtxTblSize < sizeof(gMtxTbl) / sizeof(gMtxTbl[0])) { @@ -795,41 +688,31 @@ index d5bf5778..143e2032 100644 - gSPDisplayList(gDisplayListHead++, currList->displayList); + gSPDisplayList(gDisplayListHead++, currList->displayListInterpolated); currList = currList->next; - } -@@ -175,5 +197,5 @@ static void geo_process_master_list_sub(struct GraphNodeMasterList *node) { - * render modes of layers. +@@ -176,3 +225,3 @@ static void geo_process_master_list_sub(struct GraphNodeMasterList *node) { */ -static void geo_append_display_list(void *displayList, s16 layer) { +static void geo_append_display_list2(void *displayList, void *displayListInterpolated, s16 layer) { - #ifdef F3DEX_GBI_2 -@@ -185,5 +207,7 @@ static void geo_append_display_list(void *displayList, s16 layer) { - +@@ -186,3 +235,5 @@ static void geo_append_display_list(void *displayList, s16 layer) { listNode->transform = gMatStackFixed[gMatStackIndex]; + listNode->transformInterpolated = gMatStackInterpolatedFixed[gMatStackIndex]; listNode->displayList = displayList; + listNode->displayListInterpolated = displayListInterpolated; listNode->next = 0; - if (gCurGraphNodeMasterList->listHeads[layer] == 0) { -@@ -196,4 +220,8 @@ static void geo_append_display_list(void *displayList, s16 layer) { - } +@@ -197,2 +248,6 @@ static void geo_append_display_list(void *displayList, s16 layer) { +static void geo_append_display_list(void *displayList, s16 layer) { + geo_append_display_list2(displayList, displayList, layer); +} + /** - * Process the master list node. -@@ -242,5 +270,7 @@ static void geo_process_perspective(struct GraphNodePerspective *node) { - if (node->fnNode.node.children != NULL) { +@@ -243,3 +298,5 @@ static void geo_process_perspective(struct GraphNodePerspective *node) { u16 perspNorm; + Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated)); Mtx *mtx = alloc_display_list(sizeof(*mtx)); + f32 fovInterpolated; - #ifdef VERSION_EU -@@ -251,7 +281,21 @@ static void geo_process_perspective(struct GraphNodePerspective *node) { - +@@ -252,5 +309,19 @@ static void geo_process_perspective(struct GraphNodePerspective *node) { guPerspective(mtx, &perspNorm, node->fov, aspect, node->near, node->far, 1.0f); - gSPPerspNormalize(gDisplayListHead++, perspNorm); @@ -851,9 +734,7 @@ index d5bf5778..143e2032 100644 + node->prevFov = node->fov; + node->prevTimestamp = gGlobalTimer; - gCurGraphNodeCamFrustum = node; -@@ -298,4 +342,37 @@ static void geo_process_switch(struct GraphNodeSwitchCase *node) { - } +@@ -299,2 +370,35 @@ 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; @@ -889,17 +770,13 @@ index d5bf5778..143e2032 100644 +} + /** - * Process a camera node. -@@ -305,4 +382,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) { - Mtx *rollMtx = alloc_display_list(sizeof(*rollMtx)); +@@ -306,2 +410,5 @@ static void geo_process_camera(struct GraphNodeCamera *node) { Mtx *mtx = alloc_display_list(sizeof(*mtx)); + Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated)); + Vec3f posInterpolated; + Vec3f focusInterpolated; - if (node->fnNode.func != NULL) { -@@ -315,10 +395,38 @@ static void geo_process_camera(struct GraphNodeCamera *node) { - mtxf_lookat(cameraTransform, node->pos, node->focus, node->roll); +@@ -316,2 +423,27 @@ static void geo_process_camera(struct GraphNodeCamera *node) { mtxf_mul(gMatStack[gMatStackIndex + 1], cameraTransform, gMatStack[gMatStackIndex]); + + if (gGlobalTimer == node->prevTimestamp + 1 && gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) { @@ -927,55 +804,47 @@ index d5bf5778..143e2032 100644 + mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], cameraTransform, gMatStackInterpolated[gMatStackIndex]); + gMatStackIndex++; - mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); +@@ -319,2 +451,4 @@ static void geo_process_camera(struct GraphNodeCamera *node) { gMatStackFixed[gMatStackIndex] = mtx; + mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]); + gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated; if (node->fnNode.node.children != 0) { - gCurGraphNodeCamera = node; +@@ -322,2 +456,3 @@ static void geo_process_camera(struct GraphNodeCamera *node) { node->matrixPtr = &gMatStack[gMatStackIndex]; + node->matrixPtrInterpolated = &gMatStackInterpolated[gMatStackIndex]; geo_process_node_and_siblings(node->fnNode.node.children); - gCurGraphNodeCamera = NULL; -@@ -337,11 +445,15 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation - Vec3f translation; +@@ -338,2 +473,3 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation 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); +@@ -342,2 +478,3 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); + mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]); gMatStackIndex++; - mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); +@@ -345,2 +482,4 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation 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); -@@ -362,11 +474,15 @@ static void geo_process_translation(struct GraphNodeTranslation *node) { - Vec3f translation; +@@ -363,2 +502,3 @@ static void geo_process_translation(struct GraphNodeTranslation *node) { 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); +@@ -367,2 +507,3 @@ static void geo_process_translation(struct GraphNodeTranslation *node) { mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); + mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]); gMatStackIndex++; - mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); +@@ -370,2 +511,4 @@ static void geo_process_translation(struct GraphNodeTranslation *node) { 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); -@@ -386,10 +502,21 @@ static void geo_process_rotation(struct GraphNodeRotation *node) { - Mat4 mtxf; +@@ -387,2 +530,4 @@ static void geo_process_rotation(struct GraphNodeRotation *node) { 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); +@@ -390,2 +535,9 @@ static void geo_process_rotation(struct GraphNodeRotation *node) { mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); + if (gGlobalTimer == node->prevTimestamp + 1) { + interpolate_angles(rotationInterpolated, node->prevRotation, node->rotation); @@ -985,58 +854,49 @@ index d5bf5778..143e2032 100644 + node->prevTimestamp = gGlobalTimer; + mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]); gMatStackIndex++; - mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); +@@ -393,2 +545,4 @@ static void geo_process_rotation(struct GraphNodeRotation *node) { 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); -@@ -410,10 +537,14 @@ static void geo_process_scale(struct GraphNodeScale *node) { - Vec3f scaleVec; +@@ -411,2 +565,3 @@ static void geo_process_scale(struct GraphNodeScale *node) { Mtx *mtx = alloc_display_list(sizeof(*mtx)); + Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated)); - vec3f_set(scaleVec, node->scale, node->scale, node->scale); +@@ -414,2 +569,3 @@ static void geo_process_scale(struct GraphNodeScale *node) { 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]); +@@ -417,2 +573,4 @@ static void geo_process_scale(struct GraphNodeScale *node) { 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); -@@ -434,4 +565,5 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) { - Vec3f translation; +@@ -435,2 +593,3 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) { Mtx *mtx = alloc_display_list(sizeof(*mtx)); + Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated)); - gMatStackIndex++; -@@ -439,14 +571,22 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) { - mtxf_billboard(gMatStack[gMatStackIndex], gMatStack[gMatStackIndex - 1], translation, +@@ -440,2 +599,4 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) { gCurGraphNodeCamera->roll); + mtxf_billboard(gMatStackInterpolated[gMatStackIndex], gMatStackInterpolated[gMatStackIndex - 1], translation, + gCurGraphNodeCamera->roll); if (gCurGraphNodeHeldObject != NULL) { - mtxf_scale_vec3f(gMatStack[gMatStackIndex], gMatStack[gMatStackIndex], +@@ -443,2 +604,4 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) { 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], +@@ -446,2 +609,4 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) { gCurGraphNodeObject->scale); + mtxf_scale_vec3f(gMatStackInterpolated[gMatStackIndex], gMatStackInterpolated[gMatStackIndex], + gCurGraphNodeObject->scale); } - - mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); +@@ -450,2 +615,4 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) { 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); -@@ -497,11 +637,37 @@ static void geo_process_generated_list(struct GraphNodeGenerated *node) { - static void geo_process_background(struct GraphNodeBackground *node) { +@@ -498,9 +665,35 @@ static void geo_process_background(struct GraphNodeBackground *node) { Gfx *list = NULL; + Gfx *listInterpolated = NULL; @@ -1073,9 +933,7 @@ index d5bf5778..143e2032 100644 + geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(list), + (void *) VIRTUAL_TO_PHYSICAL(listInterpolated), node->fnNode.node.flags >> 8); } else if (gCurGraphNodeMasterList != NULL) { - #ifndef F3DEX_GBI_2E -@@ -528,59 +694,79 @@ static void geo_process_background(struct GraphNodeBackground *node) { - } +@@ -529,43 +722,32 @@ static void geo_process_background(struct GraphNodeBackground *node) { -/** - * Render an animated part. The current animation state is not part of the node @@ -1138,8 +996,7 @@ index d5bf5778..143e2032 100644 + *animAttribute += 6; + *animType = ANIM_TYPE_ROTATION; } - } - } +@@ -574,9 +756,38 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) { - if (gCurAnimType == ANIM_TYPE_ROTATION) { - rotation[0] = gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]; @@ -1182,14 +1039,12 @@ index d5bf5778..143e2032 100644 + mtxf_rotate_xyz_and_translate(matrix, translationInterpolated, rotationInterpolated); + mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], matrix, gMatStackInterpolated[gMatStackIndex]); gMatStackIndex++; - mtxf_to_mtx(matrixPtr, gMatStack[gMatStackIndex]); +@@ -584,2 +795,4 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) { 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); -@@ -614,4 +800,15 @@ void geo_set_animation_globals(struct GraphNodeObject_sub *node, s32 hasAnimatio - +@@ -615,2 +828,13 @@ 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) { @@ -1203,24 +1058,18 @@ index d5bf5778..143e2032 100644 + node->prevAnimFrameTimestamp = gGlobalTimer; + gCurAnimEnabled = (anim->flags & ANIM_FLAG_5) == 0; - gCurrAnimAttribute = segmented_to_virtual((void *) anim->index); -@@ -632,6 +829,8 @@ void geo_set_animation_globals(struct GraphNodeObject_sub *node, s32 hasAnimatio - static void geo_process_shadow(struct GraphNodeShadow *node) { +@@ -633,4 +857,6 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { Gfx *shadowList; + Gfx *shadowListInterpolated; Mat4 mtxf; Vec3f shadowPos; + Vec3f shadowPosInterpolated; Vec3f animOffset; - f32 objScale; -@@ -641,4 +840,5 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { - struct GraphNode *geo; +@@ -642,2 +868,3 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { Mtx *mtx; + Mtx *mtxInterpolated; - if (gCurGraphNodeCamera != NULL && gCurGraphNodeObject != NULL) { -@@ -679,19 +879,55 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { - } +@@ -680,7 +907,34 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { + if (gCurGraphNodeHeldObject != NULL) { + if (gGlobalTimer == gCurGraphNodeHeldObject->prevShadowPosTimestamp + 1) { @@ -1256,8 +1105,7 @@ index d5bf5778..143e2032 100644 gMatStackIndex++; + mtxf_translate(mtxf, shadowPos); - mtxf_mul(gMatStack[gMatStackIndex], mtxf, *gCurGraphNodeCamera->matrixPtr); - mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); +@@ -689,8 +943,17 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { gMatStackFixed[gMatStackIndex] = mtx; + + mtxf_translate(mtxf, shadowPosInterpolated); @@ -1278,9 +1126,7 @@ index d5bf5778..143e2032 100644 + geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList), + (void *) VIRTUAL_TO_PHYSICAL(shadowListInterpolated), 6); } - gMatStackIndex--; -@@ -790,4 +1026,13 @@ static int obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) { - } +@@ -791,2 +1054,11 @@ static int obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) { +static void interpolate_matrix(Mat4 result, Mat4 a, Mat4 b) { + s32 i, j; @@ -1292,15 +1138,11 @@ index d5bf5778..143e2032 100644 +} + /** - * Process an object node. -@@ -796,4 +1041,5 @@ static void geo_process_object(struct Object *node) { - Mat4 mtxf; +@@ -797,2 +1069,3 @@ static void geo_process_object(struct Object *node) { s32 hasAnimation = (node->header.gfx.node.flags & GRAPH_RENDER_HAS_ANIMATION) != 0; + Vec3f scaleInterpolated; - if (node->header.gfx.unk18 == gCurGraphNodeRoot->areaIndex) { -@@ -801,18 +1047,78 @@ static void geo_process_object(struct Object *node) { - mtxf_mul(gMatStack[gMatStackIndex + 1], *node->header.gfx.throwMatrix, +@@ -802,12 +1075,69 @@ static void geo_process_object(struct Object *node) { gMatStack[gMatStackIndex]); + if (gGlobalTimer == node->header.gfx.prevThrowMatrixTimestamp + 1 && + gGlobalTimer != node->header.gfx.skipInterpolationTimestamp) { @@ -1359,60 +1201,50 @@ index d5bf5778..143e2032 100644 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], + +@@ -815,3 +1145,6 @@ static void geo_process_object(struct Object *node) { 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]; -@@ -825,7 +1131,10 @@ static void geo_process_object(struct Object *node) { - if (obj_is_in_view(&node->header.gfx, gMatStack[gMatStackIndex])) { +@@ -826,2 +1159,3 @@ static void geo_process_object(struct Object *node) { Mtx *mtx = alloc_display_list(sizeof(*mtx)); + Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated)); - mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); +@@ -829,2 +1163,4 @@ static void geo_process_object(struct Object *node) { gMatStackFixed[gMatStackIndex] = mtx; + mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]); + gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated; if (node->header.gfx.sharedChild != NULL) { - gCurGraphNodeObject = (struct GraphNodeObject *) node; -@@ -838,4 +1147,8 @@ static void geo_process_object(struct Object *node) { - geo_process_node_and_siblings(node->header.gfx.node.children); +@@ -839,2 +1175,6 @@ static void geo_process_object(struct Object *node) { } + } else { + node->header.gfx.prevThrowMatrixTimestamp = 0; + node->header.gfx.prevTimestamp = 0; + node->header.gfx.prevScaleTimestamp = 0; } - -@@ -843,4 +1156,5 @@ static void geo_process_object(struct Object *node) { - gCurAnimType = ANIM_TYPE_NONE; +@@ -844,2 +1184,3 @@ static void geo_process_object(struct Object *node) { node->header.gfx.throwMatrix = NULL; + node->header.gfx.throwMatrixInterpolated = NULL; } - } -@@ -869,4 +1183,6 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { - Vec3f translation; +@@ -870,2 +1211,4 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { Mtx *mtx = alloc_display_list(sizeof(*mtx)); + Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated)); + Vec3f scaleInterpolated; - #ifdef F3DEX_GBI_2 -@@ -884,4 +1200,12 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { - translation[2] = node->translation[2] / 4.0f; +@@ -885,2 +1228,10 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { + if (gGlobalTimer == node->objNode->header.gfx.prevScaleTimestamp + 1) { + interpolate_vectors(scaleInterpolated, node->objNode->header.gfx.prevScale, node->objNode->header.gfx.scale); @@ -1423,9 +1255,7 @@ index d5bf5778..143e2032 100644 + node->objNode->header.gfx.prevScaleTimestamp = gGlobalTimer; + mtxf_translate(mat, translation); - mtxf_copy(gMatStack[gMatStackIndex + 1], *gCurGraphNodeObject->throwMatrix); -@@ -892,4 +1216,11 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { - mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1], +@@ -893,2 +1244,9 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { node->objNode->header.gfx.scale); + mtxf_copy(gMatStackInterpolated[gMatStackIndex + 1], (void *) gCurGraphNodeObject->throwMatrixInterpolated); + gMatStackInterpolated[gMatStackIndex + 1][3][0] = gMatStackInterpolated[gMatStackIndex][3][0]; @@ -1435,34 +1265,24 @@ index d5bf5778..143e2032 100644 + 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, -@@ -899,4 +1230,6 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { - mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); +@@ -900,2 +1258,4 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { gMatStackFixed[gMatStackIndex] = mtx; + mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]); + gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated; gGeoTempState.type = gCurAnimType; - gGeoTempState.enabled = gCurAnimEnabled; -@@ -905,4 +1238,5 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { - gGeoTempState.attribute = gCurrAnimAttribute; +@@ -906,2 +1266,3 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { gGeoTempState.data = gCurAnimData; + gGeoTempState.prevFrame = gPrevAnimFrame; gCurAnimType = 0; - gCurGraphNodeHeldObject = (void *) node; -@@ -919,4 +1253,5 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { - gCurrAnimAttribute = gGeoTempState.attribute; +@@ -920,2 +1281,3 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { gCurAnimData = gGeoTempState.data; + gPrevAnimFrame = gGeoTempState.prevFrame; gMatStackIndex--; - } -@@ -1040,4 +1375,5 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) - Mtx *initialMatrix; +@@ -1041,2 +1403,3 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) Vp *viewport = alloc_display_list(sizeof(*viewport)); + Vp *viewportInterpolated = viewport; - gDisplayListHeap = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool), -@@ -1050,5 +1386,10 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) - if (b != NULL) { +@@ -1051,3 +1414,8 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) clear_frame_buffer(clearColor); - make_viewport_clip_rect(b); + viewportInterpolated = alloc_display_list(sizeof(*viewportInterpolated)); @@ -1472,14 +1292,11 @@ index d5bf5778..143e2032 100644 + sViewportPos = gDisplayListHead; + make_viewport_clip_rect(viewportInterpolated); *viewport = *b; - } -@@ -1058,9 +1399,14 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) - make_viewport_clip_rect(c); +@@ -1059,2 +1427,3 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) } + sPrevViewport = *viewport; - mtxf_identity(gMatStack[gMatStackIndex]); - mtxf_to_mtx(initialMatrix, gMatStack[gMatStackIndex]); +@@ -1063,3 +1432,7 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) gMatStackFixed[gMatStackIndex] = initialMatrix; - gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(viewport)); + @@ -1488,13 +1305,11 @@ index d5bf5778..143e2032 100644 + + gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(viewportInterpolated)); gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(gMatStackFixed[gMatStackIndex]), - G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); diff --git a/src/game/screen_transition.c b/src/game/screen_transition.c index b49ddaf5..d6656af2 100644 --- a/src/game/screen_transition.c +++ b/src/game/screen_transition.c -@@ -17,4 +17,17 @@ u8 sTransitionColorFadeCount[4] = { 0 }; - u16 sTransitionTextureFadeCount[2] = { 0 }; +@@ -18,2 +18,15 @@ u16 sTransitionTextureFadeCount[2] = { 0 }; +static Gfx *sScreenTransitionVerticesPos[2]; +static Vtx *sScreenTransitionVertices; @@ -1510,16 +1325,12 @@ index b49ddaf5..d6656af2 100644 +} + s32 set_and_reset_transition_fade_timer(s8 fadeTimer, u8 transTime) { - s32 reset = FALSE; -@@ -86,4 +99,6 @@ s32 render_fade_transition_into_color(s8 fadeTimer, u8 transTime, struct WarpTra - } +@@ -87,2 +100,4 @@ s32 render_fade_transition_into_color(s8 fadeTimer, u8 transTime, struct WarpTra +#if 0 + s16 calc_tex_transition_radius(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) { - f32 texRadius = transData->endTexRadius - transData->startTexRadius; -@@ -91,7 +106,20 @@ s16 calc_tex_transition_radius(s8 fadeTimer, s8 transTime, struct WarpTransition - f32 result = transData->startTexRadius + radiusTime; +@@ -92,5 +107,18 @@ s16 calc_tex_transition_radius(s8 fadeTimer, s8 transTime, struct WarpTransition - return (s16)(result + 0.5);; + return (s16)(result + 0.5); @@ -1539,16 +1350,12 @@ index b49ddaf5..d6656af2 100644 +#endif + f32 calc_tex_transition_time(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) { - f32 startX = transData->startTexX; -@@ -167,4 +195,6 @@ void *sTextureTransitionID[] = { - }; +@@ -168,2 +196,4 @@ void *sTextureTransitionID[] = { +#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); -@@ -207,4 +237,54 @@ s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransition - } +@@ -208,2 +238,52 @@ s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransition +#else + @@ -1601,19 +1408,24 @@ index b49ddaf5..d6656af2 100644 +#endif + int render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData) { - switch (transType) { +diff --git a/src/game/skybox.c b/src/game/skybox.c +index 258ef0a3..bf92d0d5 100644 +--- a/src/game/skybox.c ++++ b/src/game/skybox.c +@@ -253,3 +253,3 @@ void *create_skybox_ortho_matrix(s8 player) { + Gfx *init_skybox_display_list(s8 player, s8 background, s8 colorIndex) { +- s32 dlCommandCount = 7 + (3 * 3) * 7; // 5 for the start and end, plus 9 skybox tiles ++ s32 dlCommandCount = 124; // 5 for the start and end, plus 9 skybox tiles + void *skybox = alloc_display_list(dlCommandCount * sizeof(Gfx)); diff --git a/src/menu/intro_geo.c b/src/menu/intro_geo.c index 1d3be071..01c5ad61 100644 --- a/src/menu/intro_geo.c +++ b/src/menu/intro_geo.c -@@ -1,4 +1,5 @@ - #include +@@ -2,2 +2,3 @@ +#include "engine/math_util.h" #include "game/memory.h" - #include "game/segment2.h" -@@ -71,4 +72,16 @@ s8 gameOverBackgroundFlipOrder[] = { 0x00, 0x01, 0x02, 0x03, 0x07, 0x0B, - 0x0a, 0x09, 0x08, 0x04, 0x05, 0x06 }; +@@ -72,2 +73,14 @@ s8 gameOverBackgroundFlipOrder[] = { 0x00, 0x01, 0x02, 0x03, 0x07, 0x0B, +static Gfx *sIntroScalePos; +static Vec3f sIntroScale; @@ -1628,16 +1440,12 @@ index 1d3be071..01c5ad61 100644 +} + Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) { - struct GraphNode *graphNode; // sp4c -@@ -81,4 +94,6 @@ Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) { - f32 scaleY; // sp30 +@@ -82,2 +95,4 @@ Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) { f32 scaleZ; // sp2c + Vec3f scale; + Vec3f scaleInterpolated; graphNode = sp54; - displayList = NULL; -@@ -112,4 +127,9 @@ Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) { - } +@@ -113,2 +128,7 @@ Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) { guScale(scaleMat, scaleX, scaleY, scaleZ); + vec3f_set(scale, scaleX, scaleY, scaleZ); + interpolate_vectors(scaleInterpolated, sIntroScale, scale); @@ -1645,13 +1453,11 @@ index 1d3be071..01c5ad61 100644 + guScale(scaleMat, scaleInterpolated[0], scaleInterpolated[1], scaleInterpolated[2]); + sIntroScalePos = displayListIter; gSPMatrix(displayListIter++, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH); - gSPDisplayList(displayListIter++, &titletest_test_mesh); diff --git a/src/pc/gfx/gfx_dxgi.cpp b/src/pc/gfx/gfx_dxgi.cpp index 04674952..fa4eb33c 100644 --- a/src/pc/gfx/gfx_dxgi.cpp +++ b/src/pc/gfx/gfx_dxgi.cpp -@@ -37,8 +37,8 @@ - #ifdef VERSION_EU +@@ -38,6 +38,6 @@ #define FRAME_INTERVAL_US_NUMERATOR 40000 -#define FRAME_INTERVAL_US_DENOMINATOR 1 +#define FRAME_INTERVAL_US_DENOMINATOR 2 @@ -1660,20 +1466,16 @@ index 04674952..fa4eb33c 100644 -#define FRAME_INTERVAL_US_DENOMINATOR 3 +#define FRAME_INTERVAL_US_DENOMINATOR 6 #endif - diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 4d907893..0b21e230 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c -@@ -54,5 +54,5 @@ static void (*kb_all_keys_up)(void) = NULL; - static bool use_timer = true; +@@ -55,3 +55,3 @@ static bool use_timer = true; // time between consequtive game frames -static const int frame_time = 1000 / FRAMERATE; +static const int frame_time = 1000 / (2 * FRAMERATE); - const SDL_Scancode windows_scancode_table[] = { -@@ -143,5 +143,9 @@ static inline void gfx_sdl_set_vsync(const bool enabled) { - // try to detect refresh rate +@@ -144,3 +144,7 @@ static inline void gfx_sdl_set_vsync(const bool enabled) { SDL_GL_SetSwapInterval(1); - const int vblanks = test_vsync(); + int vblanks = test_vsync(); @@ -1682,15 +1484,14 @@ index 4d907893..0b21e230 100644 + else + vblanks /= 2; if (vblanks) { - printf("determined swap interval: %d\n", vblanks); diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c -index 3a725c03..4da6aec5 100644 +index 3a725c03..7bff83d5 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c -@@ -86,4 +86,21 @@ void send_display_list(struct SPTask *spTask) { - #endif +@@ -87,2 +87,21 @@ void send_display_list(struct SPTask *spTask) { +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); @@ -1698,6 +1499,7 @@ index 3a725c03..4da6aec5 100644 + 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(); @@ -1708,9 +1510,7 @@ index 3a725c03..4da6aec5 100644 +} + void produce_one_frame(void) { - gfx_start_frame(); -@@ -113,4 +130,9 @@ void produce_one_frame(void) { - +@@ -114,2 +133,7 @@ void produce_one_frame(void) { gfx_end_frame(); + + gfx_start_frame(); @@ -1718,4 +1518,3 @@ index 3a725c03..4da6aec5 100644 + send_display_list(gGfxSPTask); + gfx_end_frame(); } -