Fix free camera, add game languages, overall buttons toggle

This commit is contained in:
Llennpie 2021-10-28 17:11:45 -04:00
parent 9ede17dc0e
commit 7ad78dd09e
29 changed files with 300 additions and 976 deletions

View File

@ -118,10 +118,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
@ -132,22 +128,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
@ -258,10 +243,6 @@ struct Surface
} normal;
/*0x28*/ f32 originOffset;
/*0x2C*/ struct Object *object;
Vec3s prevVertex1;
Vec3s prevVertex2;
Vec3s prevVertex3;
u32 modifiedTimestamp;
};
struct MarioBodyState

View File

@ -67,6 +67,8 @@
"valarray": "cpp",
"compare": "cpp",
"concepts": "cpp",
"ranges": "cpp"
"ranges": "cpp",
"surface_collision.h": "c",
"math_util.h": "c"
}
}

View File

@ -110,8 +110,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 +118,7 @@ struct GraphNodePerspective
struct DisplayListNode
{
Mtx *transform;
void *transformInterpolated;
void *displayList;
void *displayListInterpolated;
struct DisplayListNode *next;
};
@ -189,11 +185,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 +226,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 +323,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 +333,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

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;
@ -355,11 +354,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

@ -33,6 +33,9 @@
#define CBUTTON_MASK (U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS)
u8 machinimaMode = 0;
f32 camVelSpeed = 1.0f;
/**
* @file camera.c
* Implements the camera system, including C-button input, camera modes, camera triggers, and cutscenes.
@ -2577,6 +2580,8 @@ s32 exit_c_up(struct Camera *c) {
vec3f_copy(curPos, c->pos);
curDist = 80.f;
/*
// Search for an open direction to zoom out in, if the camera is changing to close, free roam,
// or spiral-stairs mode
if (sModeInfo.lastMode == CAMERA_MODE_SPIRAL_STAIRS || sModeInfo.lastMode == CAMERA_MODE_CLOSE
@ -2642,7 +2647,12 @@ s32 exit_c_up(struct Camera *c) {
gCameraMovementFlags &= ~(CAM_MOVE_STARTED_EXITING_C_UP | CAM_MOVE_C_UP_MODE);
vec3f_set_dist_and_angle(checkFoc, c->pos, curDist, curPitch, curYaw + checkYaw);
}
play_sound_cbutton_down();
*/
gCameraMovementFlags &= ~(CAM_MOVE_STARTED_EXITING_C_UP | CAM_MOVE_C_UP_MODE);
if (machinimaMode == 0)
play_sound_cbutton_down();
}
return 0;
}
@ -3018,6 +3028,9 @@ void update_lakitu(struct Camera *c) {
gLakituState.defMode = c->defMode;
}
#include "engine/math_util.h"
f32 camVelY = 0.0f;
s16 yarSpeed = 0;
/**
* The main camera update function.
@ -3035,7 +3048,7 @@ void update_camera(struct Camera *c) {
&& c->mode != CAMERA_MODE_NEWCAM
#endif
) {
if (gPlayer1Controller->buttonPressed & R_TRIG) {
if (gPlayer1Controller->buttonPressed & R_TRIG && !machinimaMode) {
if (set_cam_angle(0) == CAM_ANGLE_LAKITU) {
set_cam_angle(CAM_ANGLE_MARIO);
} else {
@ -3135,67 +3148,135 @@ void update_camera(struct Camera *c) {
mode_mario_camera(c);
}
} else {
switch (c->mode) {
case CAMERA_MODE_BEHIND_MARIO:
mode_behind_mario_camera(c);
break;
if (machinimaMode) {
if (gPlayer1Controller->buttonDown & L_TRIG) {
if (gPlayer1Controller->buttonDown & U_CBUTTONS) {
camVelY += 5.f * camVelSpeed;
}
if (gPlayer1Controller->buttonDown & D_CBUTTONS) {
camVelY -= 5.f * camVelSpeed;
}
} else if (gPlayer1Controller->buttonDown & R_TRIG) {
if (gPlayer1Controller->buttonDown & U_CBUTTONS) {
c->pos[0] += sins(c->yaw + atan2s(-127, 0)) * 16 * camVelSpeed;
c->pos[2] += coss(c->yaw + atan2s(-127, 0)) * 16 * camVelSpeed;
c->focus[0] += sins(c->yaw + atan2s(-127, 0)) * 16 * camVelSpeed;
c->focus[2] += coss(c->yaw + atan2s(-127, 0)) * 16 * camVelSpeed;
}
if (gPlayer1Controller->buttonDown & D_CBUTTONS) {
c->pos[0] -= sins(c->yaw + atan2s(-127, 0)) * 16 * camVelSpeed;
c->pos[2] -= coss(c->yaw + atan2s(-127, 0)) * 16 * camVelSpeed;
c->focus[0] -= sins(c->yaw + atan2s(-127, 0)) * 16 * camVelSpeed;
c->focus[2] -= coss(c->yaw + atan2s(-127, 0)) * 16 * camVelSpeed;
}
if (gPlayer1Controller->buttonDown & R_CBUTTONS) {
c->pos[0] += sins(c->yaw + atan2s(0, 127)) * 16 * camVelSpeed;
c->pos[2] += coss(c->yaw + atan2s(0, 127)) * 16 * camVelSpeed;
c->focus[0] += sins(c->yaw + atan2s(0, 127)) * 16 * camVelSpeed;
c->focus[2] += coss(c->yaw + atan2s(0, 127)) * 16 * camVelSpeed;
}
if (gPlayer1Controller->buttonDown & L_CBUTTONS) {
c->pos[0] -= sins(c->yaw + atan2s(0, 127)) * 16 * camVelSpeed;
c->pos[2] -= coss(c->yaw + atan2s(0, 127)) * 16 * camVelSpeed;
c->focus[0] -= sins(c->yaw + atan2s(0, 127)) * 16 * camVelSpeed;
c->focus[2] -= coss(c->yaw + atan2s(0, 127)) * 16 * camVelSpeed;
}
} else {
// Zoom in / enter C-Up
if (gPlayer1Controller->buttonPressed & U_CBUTTONS) {
if (gCameraMovementFlags & CAM_MOVE_ZOOMED_OUT) {
gCameraMovementFlags &= ~CAM_MOVE_ZOOMED_OUT;
//play_sound_cbutton_up();
} else {
set_mode_c_up(c);
}
}
// Zoom out
if (gPlayer1Controller->buttonPressed & D_CBUTTONS) {
if ((gCameraMovementFlags & CAM_MOVE_ZOOMED_OUT) == 0) {
exit_c_up(c);
//gCameraMovementFlags |= CAM_MOVE_ZOOMED_OUT;
//play_sound_cbutton_down();
}
}
case CAMERA_MODE_C_UP:
mode_c_up_camera(c);
break;
if (c->mode == CAMERA_MODE_C_UP) {
move_mario_head_c_up(c);
}
case CAMERA_MODE_WATER_SURFACE:
mode_water_surface_camera(c);
break;
c->nextYaw = calculate_yaw(gLakituState.focus, gLakituState.pos);
c->yaw = gCamera->nextYaw;
//gCameraMovementFlags &= ~CAM_MOVE_FIX_IN_PLACE;
}
case CAMERA_MODE_INSIDE_CANNON:
mode_cannon_camera(c);
break;
c->pos[1] += camVelY;
c->focus[1] += camVelY;
camVelY = approach_f32_symmetric(camVelY, 0.f, 2.f);
camVelY = approach_f32_asymptotic(camVelY, 0.f, 0.1f);
case CAMERA_MODE_8_DIRECTIONS:
mode_8_directions_camera(c);
break;
} else {
switch (c->mode) {
case CAMERA_MODE_BEHIND_MARIO:
mode_behind_mario_camera(c);
break;
case CAMERA_MODE_RADIAL:
mode_radial_camera(c);
break;
case CAMERA_MODE_C_UP:
mode_c_up_camera(c);
break;
case CAMERA_MODE_OUTWARD_RADIAL:
mode_outward_radial_camera(c);
break;
case CAMERA_MODE_WATER_SURFACE:
mode_water_surface_camera(c);
break;
case CAMERA_MODE_CLOSE:
mode_lakitu_camera(c);
break;
case CAMERA_MODE_INSIDE_CANNON:
mode_cannon_camera(c);
break;
case CAMERA_MODE_FREE_ROAM:
mode_lakitu_camera(c);
break;
case CAMERA_MODE_BOSS_FIGHT:
mode_boss_fight_camera(c);
break;
case CAMERA_MODE_8_DIRECTIONS:
mode_8_directions_camera(c);
break;
case CAMERA_MODE_PARALLEL_TRACKING:
mode_parallel_tracking_camera(c);
break;
case CAMERA_MODE_RADIAL:
mode_radial_camera(c);
break;
case CAMERA_MODE_SLIDE_HOOT:
mode_slide_camera(c);
break;
case CAMERA_MODE_OUTWARD_RADIAL:
mode_outward_radial_camera(c);
break;
case CAMERA_MODE_FIXED:
mode_fixed_camera(c);
break;
case CAMERA_MODE_CLOSE:
mode_lakitu_camera(c);
break;
case CAMERA_MODE_SPIRAL_STAIRS:
mode_spiral_stairs_camera(c);
break;
case CAMERA_MODE_FREE_ROAM:
mode_lakitu_camera(c);
break;
case CAMERA_MODE_BOSS_FIGHT:
mode_boss_fight_camera(c);
break;
case CAMERA_MODE_PARALLEL_TRACKING:
mode_parallel_tracking_camera(c);
break;
case CAMERA_MODE_SLIDE_HOOT:
mode_slide_camera(c);
break;
case CAMERA_MODE_FIXED:
mode_fixed_camera(c);
break;
case CAMERA_MODE_SPIRAL_STAIRS:
mode_spiral_stairs_camera(c);
break;
#ifdef BETTERCAMERA
case CAMERA_MODE_NEWCAM:
newcam_loop(c);
break;
case CAMERA_MODE_NEWCAM:
newcam_loop(c);
break;
#endif
}
}
}
}
@ -3927,7 +4008,7 @@ s32 find_c_buttons_pressed(u16 currentState, u16 buttonsPressed, u16 buttonsDown
s32 update_camera_hud_status(struct Camera *c) {
s16 status = CAM_STATUS_NONE;
if (c->cutscene != 0
if (c->cutscene != 0 || machinimaMode == 1
|| ((gPlayer1Controller->buttonDown & R_TRIG) && cam_select_alt_mode(0) == CAM_SELECTION_FIXED)) {
status |= CAM_STATUS_FIXED;
} else if (set_cam_angle(0) == CAM_ANGLE_MARIO) {
@ -11617,4 +11698,4 @@ void obj_rotate_towards_point(struct Object *o, Vec3f point, s16 pitchOff, s16 y
#include "behaviors/intro_lakitu.inc.c"
#include "behaviors/end_birds_1.inc.c"
#include "behaviors/end_birds_2.inc.c"
#include "behaviors/intro_scene.inc.c"
#include "behaviors/intro_scene.inc.c"

View File

@ -657,8 +657,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

@ -54,26 +54,6 @@ extern void *tiny_bubble_dl_0B006AB0;
extern void *tiny_bubble_dl_0B006A50;
extern void *tiny_bubble_dl_0B006CD8;
static struct {
Gfx *pos;
Vtx vertices[15];
} sPrevSnowVertices[140 / 5];
static s16 sPrevSnowParticleCount;
static u32 sPrevSnowTimestamp;
void patch_interpolated_snow_particles(void) {
int i;
if (gGlobalTimer != sPrevSnowTimestamp + 1) {
return;
}
for (i = 0; i < sPrevSnowParticleCount; i += 5) {
gSPVertex(sPrevSnowVertices[i / 5].pos,
VIRTUAL_TO_PHYSICAL(sPrevSnowVertices[i / 5].vertices), 15, 0);
}
}
/**
* Initialize snow particles by allocating a buffer for storing their state
* and setting a start amount.
@ -237,7 +217,6 @@ void envfx_update_snow_normal(s32 snowCylinderX, s32 snowCylinderY, s32 snowCyli
400.0f * random_float() - 200.0f + snowCylinderZ + (s16)(deltaZ * 2);
(gEnvFxBuffer + i)->yPos = 200.0f * random_float() + snowCylinderY;
(gEnvFxBuffer + i)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
} else {
(gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2);
(gEnvFxBuffer + i)->yPos -= 2 -(s16)(deltaY * 0.8);
@ -272,7 +251,6 @@ void envfx_update_snow_blizzard(s32 snowCylinderX, s32 snowCylinderY, s32 snowCy
400.0f * random_float() - 200.0f + snowCylinderZ + (s16)(deltaZ * 2);
(gEnvFxBuffer + i)->yPos = 400.0f * random_float() - 200.0f + snowCylinderY;
(gEnvFxBuffer + i)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
} else {
(gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2) + 20.0f;
(gEnvFxBuffer + i)->yPos -= 5 -(s16)(deltaY * 0.8);
@ -316,7 +294,6 @@ void envfx_update_snow_water(s32 snowCylinderX, s32 snowCylinderY, s32 snowCylin
(gEnvFxBuffer + i)->zPos = 400.0f * random_float() - 200.0f + snowCylinderZ;
(gEnvFxBuffer + i)->yPos = 400.0f * random_float() - 200.0f + snowCylinderY;
(gEnvFxBuffer + i)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
}
}
}
@ -369,8 +346,6 @@ void rotate_triangle_vertices(Vec3s vertex1, Vec3s vertex2, Vec3s vertex3, s16 p
void append_snowflake_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3) {
s32 i = 0;
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;
#endif
@ -420,23 +395,7 @@ void append_snowflake_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s ve
#endif
}
for (i = 0; i < 15; i++) {
v = &sPrevSnowVertices[index / 5].vertices[i];
vertBufInterpolated[i] = gSnowTempVtx[i % 3];
if (index < sPrevSnowParticleCount && gGlobalTimer == sPrevSnowTimestamp + 1 &&
gGlobalTimer != gEnvFxBuffer[index + i / 3].spawnTimestamp) {
vertBufInterpolated[i].v.ob[0] = (v->v.ob[0] + vertBuf[i].v.ob[0]) / 2;
vertBufInterpolated[i].v.ob[1] = (v->v.ob[1] + vertBuf[i].v.ob[1]) / 2;
vertBufInterpolated[i].v.ob[2] = (v->v.ob[2] + vertBuf[i].v.ob[2]) / 2;
} else {
vertBufInterpolated[i].v.ob[0] = vertBuf[i].v.ob[0];
vertBufInterpolated[i].v.ob[1] = vertBuf[i].v.ob[1];
vertBufInterpolated[i].v.ob[2] = vertBuf[i].v.ob[2];
}
*v = vertBuf[i];
}
sPrevSnowVertices[index / 5].pos = gfx;
gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBufInterpolated), 15, 0);
gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBuf), 15, 0);
}
/**
@ -520,8 +479,6 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo)
gSP1Triangle(gfx++, 9, 10, 11, 0);
gSP1Triangle(gfx++, 12, 13, 14, 0);
}
sPrevSnowParticleCount = gSnowParticleCount;
sPrevSnowTimestamp = gGlobalTimer;
gSPDisplayList(gfx++, &tiny_bubble_dl_0B006AB0) gSPEndDisplayList(gfx++);

View File

@ -25,8 +25,7 @@ struct EnvFxParticle {
s32 angleAndDist[2]; // for whirpools, [0] = angle from center, [1] = distance from center
s32 unusedBubbleVar; // set to zero for bubbles when respawning, never used elsewhere
s32 bubbleY; // for Bubbles, yPos is always set to this
//s8 filler20[56 - 0x20];
u32 spawnTimestamp;
s8 filler20[56 - 0x20];
};
extern s8 gEnvFxMode;

View File

@ -82,20 +82,6 @@ void render_hud_texture(s32 x, s32 y, u32 w, u32 h, u8 *texture) {
gSPDisplayList(gDisplayListHead++, dl_hud_img_end);
}
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.
*/
@ -148,7 +134,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));
@ -156,15 +141,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

@ -78,47 +78,6 @@ s8 gLastDialogResponse = 0;
u8 gMenuHoldKeyIndex = 0;
u8 gMenuHoldKeyTimer = 0;
s32 gDialogResponse = 0;
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));
@ -582,14 +541,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);
@ -598,12 +549,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);
@ -714,8 +659,7 @@ u32 ensure_nonnegative(s16 value) {
return value;
}
void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 lowerBound)
{
void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 lowerBound) {
UNUSED s32 pad[2];
u8 strChar;
@ -745,11 +689,9 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
strIdx = gDialogTextPos;
if (gDialogBoxState == DIALOG_STATE_HORIZONTAL) {
sInterpolatedDialogOffset = gDialogScrollOffsetY + dialog->linesPerBox;
sInterpolatedDialogOffsetPos = gDisplayListHead;
if (gDialogBoxState == DIALOG_STATE_HORIZONTAL)
create_dl_translation_matrix(MENU_MTX_NOPUSH, 0, (f32) gDialogScrollOffsetY, 0);
}
create_dl_translation_matrix(MENU_MTX_PUSH, X_VAL3, 2 - lineNum * Y_VAL3, 0);
while (pageState == DIALOG_PAGE_STATE_NONE) {
@ -774,6 +716,7 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l
case DIALOG_CHAR_SPACE:
xMatrix++;
linePos++;
break;
case DIALOG_CHAR_SLASH:
xMatrix += 2;
@ -805,6 +748,7 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l
}
strIdx++;
}
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
if (gDialogBoxState == DIALOG_STATE_VERTICAL) {

View File

@ -34,16 +34,12 @@ Gfx *geo_envfx_main(s32 callContext, struct GraphNode *node, Mat4 mtxf) {
vec3f_to_vec3s(marioPos, gPlayerCameraState->pos);
particleList = envfx_update_particles(snowMode, marioPos, camTo, camFrom);
if (particleList != NULL) {
#if 0
Mtx *mtx = alloc_display_list(sizeof(*mtx));
gfx = alloc_display_list(2 * sizeof(*gfx));
mtxf_to_mtx(mtx, mtxf);
gSPMatrix(&gfx[0], VIRTUAL_TO_PHYSICAL(mtx), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gSPBranchList(&gfx[1], VIRTUAL_TO_PHYSICAL(particleList));
#else
gfx = particleList;
#endif
execNode->fnNode.node.flags = (execNode->fnNode.node.flags & 0xFF) | 0x400;
}
SET_HIGH_U16_OF_32(*params, gAreaUpdateCounter);

View File

@ -1550,7 +1550,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

@ -40,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
@ -55,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
@ -65,7 +62,6 @@ struct GeoAnimState gGeoTempState;
u8 gCurAnimType;
u8 gCurAnimEnabled;
s16 gCurrAnimFrame;
s16 gPrevAnimFrame;
f32 gCurAnimTranslationMultiplier;
u16 *gCurrAnimAttribute;
s16 *gCurAnimData;
@ -134,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.
*/
@ -201,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;
}
}
@ -224,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);
@ -234,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;
@ -247,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.
*/
@ -297,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;
@ -308,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);
@ -376,39 +305,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.
*/
@ -416,9 +312,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]);
@ -429,40 +322,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;
}
@ -479,17 +344,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);
}
@ -508,17 +369,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);
}
@ -536,23 +393,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);
}
@ -571,16 +417,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);
}
@ -599,30 +441,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);
}
@ -671,39 +504,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);
@ -728,47 +535,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.
@ -777,32 +543,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);
}
@ -834,17 +621,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);
@ -863,10 +639,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;
@ -874,7 +648,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) {
@ -913,57 +686,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--;
}
@ -1060,101 +797,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];
@ -1165,12 +832,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;
@ -1181,16 +845,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;
}
}
@ -1217,8 +876,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);
@ -1234,14 +891,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];
@ -1250,13 +899,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]);
@ -1264,15 +906,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) {
@ -1287,7 +926,6 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
gCurAnimTranslationMultiplier = gGeoTempState.translationMultiplier;
gCurrAnimAttribute = gGeoTempState.attribute;
gCurAnimData = gGeoTempState.data;
gPrevAnimFrame = gGeoTempState.prevFrame;
gMatStackIndex--;
}
@ -1409,7 +1047,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();
initialMatrix = alloc_display_list(sizeof(*initialMatrix));
@ -1419,12 +1056,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;
}
@ -1432,16 +1064,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"
@ -147,18 +146,6 @@ Gfx *geo_n64_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) {
}
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
@ -169,8 +156,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;
@ -202,11 +187,6 @@ Gfx *geo_title_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) {
scaleZ = 0.0f;
}
guScale(scaleMat, scaleX, scaleY, scaleZ);
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;
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

@ -12,6 +12,7 @@
#include "moon/mod-engine/hooks/hook.h"
#include "moon/mod-engine/textures/mod-texture.h"
#include "moon/mod-engine/engine.h"
#include "moon/texts/moon-loader.h"
#include "moon/saturn/saturn.h"
#include "moon/saturn/saturn_colors.h"
#include "moon/saturn/saturn_textures.h"
@ -399,27 +400,23 @@ namespace MoonInternal {
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
ImGui::Begin("Quick Toggles", NULL, ImGuiWindowFlags_None);
if (ImGui::BeginTable("quick_toggles", 1))
{
ImGui::TableNextColumn();
ImGui::Checkbox("HUD", &configHUD);
ImGui::TableNextColumn();
ImGui::Checkbox("M Cap Logo", &enable_cap_logo);
ImGui::TableNextColumn();
ImGui::Checkbox("HUD", &configHUD);
if (ImGui::CollapsingHeader("Mario")) {
ImGui::Checkbox("Head Rotations", &enable_head_rotations);
ImGui::TableNextColumn();
ImGui::Checkbox("Shadows", &enable_shadows);
ImGui::TableNextColumn();
ImGui::Checkbox("Dust Particles", &enable_dust_particles);
ImGui::EndTable();
ImGui::Checkbox("M Cap Logo", &enable_cap_logo);
ImGui::Checkbox("M Overall Buttons", &enable_overall_buttons);
const char* capStates[] = { "Cap On", "Cap Off", "Wing Cap" }; // unused "wing cap off" not included
ImGui::Combo("Cap", &current_cap_state, capStates, IM_ARRAYSIZE(capStates));
const char* handStates[] = { "Fists", "Open", "Peace", "With Cap", "With Wing Cap", "Right Open" };
ImGui::Combo("Hands", &current_hand_state, handStates, IM_ARRAYSIZE(handStates));
ImGui::Dummy(ImVec2(0, 5));
}
ImGui::Dummy(ImVec2(0, 5));
ImGui::Checkbox("Shadows", &enable_shadows);
ImGui::Checkbox("Dust Particles", &enable_dust_particles);
const char* handStates[] = { "Fists", "Open", "Peace", "With Cap", "With Wing Cap", "Right Open" };
ImGui::Combo("Hands", &current_hand_state, handStates, IM_ARRAYSIZE(handStates));
const char* capStates[] = { "Cap On", "Cap Off", "Wing Cap" }; // unused "wing cap off" not included
ImGui::Combo("Cap", &current_cap_state, capStates, IM_ARRAYSIZE(capStates));
ImGui::Dummy(ImVec2(0, 5));
ImGui::End();
ImGui::PopStyleColor();
@ -431,7 +428,7 @@ namespace MoonInternal {
ImGui::Checkbox("Machinima Camera", &camera_frozen);
if (camera_frozen == true) {
ImGui::SliderFloat("Speed", &camera_speed, 0.0f, 0.3f);
ImGui::SliderFloat("Speed", &camera_speed, 0.2f, 0.8f);
}
ImGui::Dummy(ImVec2(0, 10));
@ -445,6 +442,15 @@ namespace MoonInternal {
if (selected_eye_item == 3) current_eye_state = 3;
if (selected_eye_item == 5) current_eye_state = 8; // dead
if (selected_eye_item == 4) {
/*
SATURN: Moon Edition uses the unused "Left" eye state for custom textures.
If you are a model author, you must manually add the switch option to your model.
You can do this in Fast64 by navigating to 000-switch.001's bone and adding a material override under Switch Option 3.
Switch Option 7 is the "Dead" eye state.
*/
current_eye_state = 4;
static int current_eye_id = 0;
string eye_name = eye_array[current_eye_id];
@ -591,7 +597,8 @@ namespace MoonInternal {
ImGui::Text("Graphics Quality");
const char* lod_modes[] = { "Auto", "Low", "High" };
ImGui::Combo("###lod_modes", (int*)&configLODMode, lod_modes, IM_ARRAYSIZE(lod_modes));
ImGui::SliderFloat("Internal Multiplier", &configWindow.multiplier, 1.0f, 4.0f);
ImGui::Text("Internal Multiplier");
ImGui::SliderFloat("###internal_multiplier", &configWindow.multiplier, 1.0f, 4.0f);
ImGui::Text("Texture Filtering");
const char* texture_filters[] = { "Nearest", "Linear", "Three-point" };
ImGui::Combo("###texture_filters", (int*)&configFiltering, texture_filters, IM_ARRAYSIZE(texture_filters));
@ -604,12 +611,40 @@ namespace MoonInternal {
ImGui::SliderInt("Environment", (int*)&configEnvVolume, 0, MAX_VOLUME);
}
if (ImGui::CollapsingHeader("Gameplay")) {
ImGui::Text("Rumble Strength");
ImGui::SliderInt("###rumble_strength", (int*)&configRumbleStrength, 0, 50);
ImGui::Checkbox("Skip Intro", &configSkipIntro);
ImGui::Text("Game Language");
char *configlangName = new char[255];
sprintf(configlangName,"%ls",Moon::languages[configLanguage]->name.c_str());
if (ImGui::BeginCombo("###game_language", configlangName))
{
for (int i = 0; i < Moon::languages.size(); i++)
{
bool langBoxSelected = (configLanguage == i);
char *langName = new char[255];
sprintf(langName,"%ls",Moon::languages[i]->name.c_str());
if (ImGui::Selectable(langName, langBoxSelected)) {
Moon::setCurrentLanguage(Moon::languages[i]);
configLanguage = i;
configlangName = langName;
}
if (langBoxSelected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
ImGui::Dummy(ImVec2(0, 5));
#ifdef DISCORDRPC
ImGui::Checkbox("Discord Activity Status", &configDiscordRPC);
ImGui::Dummy(ImVec2(0, 5));
#endif
ImGui::Text("Rumble Strength");
ImGui::SliderInt("###rumble_strength", (int*)&configRumbleStrength, 0, 50);
ImGui::Checkbox("Precache Textures", &configPrecacheRes);
ImGui::Checkbox("Skip Intro", &configSkipIntro);
}
ImGui::End();

View File

@ -33,12 +33,14 @@ bool enable_dust_particles;
bool show_menu_bar;
float camera_speed = 0.0f;
float camera_speed = 0.8f;
bool enable_cap_logo;
bool enable_overall_buttons;
// Second Check
bool has_changed_cap_logo;
bool has_changed_overall_buttons;
namespace MoonInternal {
@ -58,19 +60,22 @@ namespace MoonInternal {
if(status == "PreStartup"){
Moon::registerHookListener({.hookName = WINDOW_API_INIT, .callback = [&](HookCall call){
show_menu_bar = false;
camera_frozen = false;
enable_shadows = true;
current_eye_state = 0;
show_menu_bar = false;
enable_cap_logo = true;
enable_overall_buttons = true;
MoonInternal::load_cc_directory();
// custom textures
current_eye_state = 0;
saturn_load_eye_array();
custom_eye_name = "eyes/" + eye_array[0];
saturn_eye_swap();
saturn_toggle_m_cap();
saturn_toggle_m_buttons();
}});
Moon::registerHookListener({.hookName = WINDOW_API_HANDLE_EVENTS, .callback = [&](HookCall call){
@ -109,6 +114,11 @@ namespace MoonInternal {
Moon::registerHookListener({.hookName = GFX_PRE_START_FRAME, .callback = [&](HookCall call){
// Machinima Camera
machinimaMode = (camera_frozen) ? 1 : 0;
camVelSpeed = camera_speed;
/* OLD CAMERA...
if (camera_frozen == true) {
if (set_cam_angle(0) != CAM_ANGLE_MARIO) {
gLakituState.focVSpeed = camera_speed;
@ -120,6 +130,7 @@ namespace MoonInternal {
gCamera->yaw = gCamera->nextYaw;
gCameraMovementFlags &= ~CAM_MOVE_FIX_IN_PLACE;
}
*/
// Custom Textures
@ -127,9 +138,9 @@ namespace MoonInternal {
saturn_toggle_m_cap();
has_changed_cap_logo = true;
}
if (!enable_cap_logo && has_changed_cap_logo) {
saturn_toggle_m_cap();
has_changed_cap_logo = false;
if (!enable_overall_buttons && has_changed_overall_buttons) {
saturn_toggle_m_buttons();
has_changed_overall_buttons = false;
}
}});
}

View File

@ -16,5 +16,6 @@ extern bool show_menu_bar;
extern float camera_speed;
extern bool enable_cap_logo;
extern bool enable_overall_buttons;
#endif

View File

@ -136,6 +136,8 @@ namespace MoonInternal {
defaultColorHairGDark = 3;
defaultColorHairBLight = 0;
defaultColorHairBDark = 0;
enable_cap_logo = true;
}
void load_cc_file(string cc_filename) {
@ -262,7 +264,7 @@ namespace MoonInternal {
defaultColorHairBDark = value1;
}
//std::cout << address << std::endl;
enable_cap_logo = false;
}
}

View File

@ -65,4 +65,18 @@ void saturn_toggle_m_cap() {
}
}
}});
}
void saturn_toggle_m_buttons() {
Moon::registerHookListener({.hookName = TEXTURE_BIND, .callback = [](HookCall call) {
char* *hookTexture = reinterpret_cast<char**>(call.baseArgs["texture"]);
string texName = string(*hookTexture);
if(texName == "actors/mario/mario_overalls_button.rgba16") {
if (enable_overall_buttons) {
(*hookTexture) = const_cast<char*>("actors/mario/mario_overalls_button.rgba16");
} else {
(*hookTexture) = const_cast<char*>("blank");
}
}
}});
}

View File

@ -11,5 +11,6 @@ extern std::vector<std::string> eye_array;
void saturn_eye_swap(void);
void saturn_load_eye_array(void);
void saturn_toggle_m_cap(void);
void saturn_toggle_m_buttons(void);
#endif

View File

@ -48,8 +48,8 @@ ConfigWindow configWindow = {
.fullscreen = false,
.exiting_fullscreen = false,
.settings_changed = false,
.enable_antialias = true,
.antialias_level = 4,
.enable_antialias = false,
.antialias_level = 0,
.internal_w = DESIRED_SCREEN_WIDTH * 1.0f,
.internal_h = DESIRED_SCREEN_HEIGHT * 1.0f,
.multiplier = 1.0f

View File

@ -62,7 +62,7 @@ static void (*kb_all_keys_up)(void) = NULL;
// whether to use timer for frame control
static bool use_timer = true;
// time between consequtive game frames
static const int frame_time = 1000 / (2 * FRAMERATE);
static const int frame_time = 1000 / FRAMERATE;
const SDL_Scancode windows_scancode_table[] = {
/* 0 1 2 3 4 5 6 7 */
@ -149,17 +149,13 @@ int test_vsync(void) {
static inline void gfx_sdl_set_vsync(const bool enabled) {
#ifdef TARGET_SWITCH
SDL_GL_SetSwapInterval(1);
SDL_GL_SetSwapInterval(2);
use_timer = false;
#else
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 = test_vsync();
if (vblanks) {
printf("determined swap interval: %d\n", vblanks);
SDL_GL_SetSwapInterval(vblanks);

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) {
moon_setup("Update");
gfx_start_frame();
@ -133,11 +114,6 @@ void produce_one_frame(void) {
}
//printf("Audio samples before submitting: %d\n", audio_api->buffered());
gfx_start_frame();
patch_interpolations();
send_display_list(gGfxSPTask);
gfx_end_frame();
audio_api->play((u8 *)audio_buffer, 2 * num_audio_samples * 4);
gfx_end_frame();

View File

@ -1,6 +1,6 @@
{
"manifest": {
"langName": "Español España",
"langName": "Espanol Espana",
"langLogo": "none"
},
"dialogs": [

View File

@ -1,6 +1,6 @@
{
"manifest": {
"langName": "Español Latinoamerica",
"langName": "Espanol Latinoamerica",
"langLogo": "none"
},
"dialogs": [