screen_transition.c (14354B)
1 #include <PR/ultratypes.h> 2 #include <PR/gbi.h> 3 4 #include "area.h" 5 #include "camera.h" 6 #include "engine/graph_node.h" 7 #include "engine/math_util.h" 8 #include "game/game_init.h" 9 #include "geo_misc.h" 10 #include "gfx_dimensions.h" 11 #include "memory.h" 12 #include "screen_transition.h" 13 #include "segment2.h" 14 #include "sm64.h" 15 16 u8 sTransitionColorFadeCount[4] = { 0 }; 17 u16 sTransitionTextureFadeCount[2] = { 0 }; 18 19 s32 set_and_reset_transition_fade_timer(s8 fadeTimer, u8 transTime) { 20 s32 reset = FALSE; 21 22 sTransitionColorFadeCount[fadeTimer]++; 23 24 if (sTransitionColorFadeCount[fadeTimer] == transTime) { 25 sTransitionColorFadeCount[fadeTimer] = 0; 26 sTransitionTextureFadeCount[fadeTimer] = 0; 27 reset = TRUE; 28 } 29 return reset; 30 } 31 32 u8 set_transition_color_fade_alpha(s8 fadeType, s8 fadeTimer, u8 transTime) { 33 u8 time; 34 35 switch (fadeType) { 36 case 0: 37 time = (f32) sTransitionColorFadeCount[fadeTimer] * 255.0 / (f32)(transTime - 1) + 0.5; // fade in 38 break; 39 case 1: 40 time = (1.0 - sTransitionColorFadeCount[fadeTimer] / (f32)(transTime - 1)) * 255.0 + 0.5; // fade out 41 break; 42 } 43 return time; 44 } 45 46 Vtx *vertex_transition_color(struct WarpTransitionData *transData, u8 alpha) { 47 Vtx *verts = alloc_display_list(4 * sizeof(*verts)); 48 u8 r = transData->red; 49 u8 g = transData->green; 50 u8 b = transData->blue; 51 52 if (verts != NULL) { 53 make_vertex(verts, 0, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, r, g, b, alpha); 54 make_vertex(verts, 1, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, r, g, b, alpha); 55 make_vertex(verts, 2, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, r, g, b, alpha); 56 make_vertex(verts, 3, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, r, g, b, alpha); 57 } else { 58 } 59 return verts; 60 } 61 62 s32 dl_transition_color(s8 fadeTimer, u8 transTime, struct WarpTransitionData *transData, u8 alpha) { 63 Vtx *verts = vertex_transition_color(transData, alpha); 64 65 if (verts != NULL) { 66 gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen); 67 gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); 68 gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); 69 gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 4, 0); 70 gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123); 71 gSPDisplayList(gDisplayListHead++, dl_screen_transition_end); 72 } 73 return set_and_reset_transition_fade_timer(fadeTimer, transTime); 74 } 75 76 s32 render_fade_transition_from_color(s8 fadeTimer, u8 transTime, struct WarpTransitionData *transData) { 77 u8 alpha = set_transition_color_fade_alpha(1, fadeTimer, transTime); 78 79 return dl_transition_color(fadeTimer, transTime, transData, alpha); 80 } 81 82 s32 render_fade_transition_into_color(s8 fadeTimer, u8 transTime, struct WarpTransitionData *transData) { 83 u8 alpha = set_transition_color_fade_alpha(0, fadeTimer, transTime); 84 85 return dl_transition_color(fadeTimer, transTime, transData, alpha); 86 } 87 88 s16 calc_tex_transition_radius(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) { 89 f32 texRadius = transData->endTexRadius - transData->startTexRadius; 90 f32 radiusTime = sTransitionColorFadeCount[fadeTimer] * texRadius / (f32)(transTime - 1); 91 f32 result = transData->startTexRadius + radiusTime; 92 93 return (s16)(result + 0.5); 94 } 95 96 f32 calc_tex_transition_time(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) { 97 f32 startX = transData->startTexX; 98 f32 startY = transData->startTexY; 99 f32 endX = transData->endTexX; 100 f32 endY = transData->endTexY; 101 f32 sqrtfXY = sqrtf((startX - endX) * (startX - endX) + (startY - endY) * (startY - endY)); 102 f32 result = (f32) sTransitionColorFadeCount[fadeTimer] * sqrtfXY / (f32)(transTime - 1); 103 104 return result; 105 } 106 107 u16 convert_tex_transition_angle_to_pos(struct WarpTransitionData *transData) { 108 f32 x = transData->endTexX - transData->startTexX; 109 f32 y = transData->endTexY - transData->startTexY; 110 111 return atan2s(x, y); 112 } 113 114 s16 center_tex_transition_x(struct WarpTransitionData *transData, f32 texTransTime, u16 texTransPos) { 115 f32 x = transData->startTexX + coss(texTransPos) * texTransTime; 116 117 return (s16)(x + 0.5); 118 } 119 120 s16 center_tex_transition_y(struct WarpTransitionData *transData, f32 texTransTime, u16 texTransPos) { 121 f32 y = transData->startTexY + sins(texTransPos) * texTransTime; 122 123 return (s16)(y + 0.5); 124 } 125 126 void make_tex_transition_vertex(Vtx *verts, s32 n, s8 fadeTimer, struct WarpTransitionData *transData, s16 centerTransX, s16 centerTransY, 127 s16 texRadius1, s16 texRadius2, s16 tx, s16 ty) { 128 u8 r = transData->red; 129 u8 g = transData->green; 130 u8 b = transData->blue; 131 u16 zeroTimer = sTransitionTextureFadeCount[fadeTimer]; 132 f32 centerX = texRadius1 * coss(zeroTimer) - texRadius2 * sins(zeroTimer) + centerTransX; 133 f32 centerY = texRadius1 * sins(zeroTimer) + texRadius2 * coss(zeroTimer) + centerTransY; 134 s16 x = round_float(centerX); 135 s16 y = round_float(centerY); 136 137 make_vertex(verts, n, x, y, -1, tx * 32, ty * 32, r, g, b, 255); 138 } 139 140 void load_tex_transition_vertex(Vtx *verts, s8 fadeTimer, struct WarpTransitionData *transData, s16 centerTransX, s16 centerTransY, 141 s16 texTransRadius, s8 transTexType) { 142 switch (transTexType) { 143 case TRANS_TYPE_MIRROR: 144 make_tex_transition_vertex(verts, 0, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, -texTransRadius, -31, 63); 145 make_tex_transition_vertex(verts, 1, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, -texTransRadius, 31, 63); 146 make_tex_transition_vertex(verts, 2, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, texTransRadius, 31, 0); 147 make_tex_transition_vertex(verts, 3, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, texTransRadius, -31, 0); 148 break; 149 case TRANS_TYPE_CLAMP: 150 make_tex_transition_vertex(verts, 0, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, -texTransRadius, 0, 63); 151 make_tex_transition_vertex(verts, 1, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, -texTransRadius, 63, 63); 152 make_tex_transition_vertex(verts, 2, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, texTransRadius, 63, 0); 153 make_tex_transition_vertex(verts, 3, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, texTransRadius, 0, 0); 154 break; 155 } 156 make_tex_transition_vertex(verts, 4, fadeTimer, transData, centerTransX, centerTransY, -2000, -2000, 0, 0); 157 make_tex_transition_vertex(verts, 5, fadeTimer, transData, centerTransX, centerTransY, 2000, -2000, 0, 0); 158 make_tex_transition_vertex(verts, 6, fadeTimer, transData, centerTransX, centerTransY, 2000, 2000, 0, 0); 159 make_tex_transition_vertex(verts, 7, fadeTimer, transData, centerTransX, centerTransY, -2000, 2000, 0, 0); 160 } 161 162 void *sTextureTransitionID[] = { 163 texture_transition_star_half, 164 texture_transition_circle_half, 165 texture_transition_mario, 166 texture_transition_bowser_half, 167 }; 168 169 s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData, s8 texID, s8 transTexType) { 170 f32 texTransTime = calc_tex_transition_time(fadeTimer, transTime, transData); 171 u16 texTransPos = convert_tex_transition_angle_to_pos(transData); 172 s16 centerTransX = center_tex_transition_x(transData, texTransTime, texTransPos); 173 s16 centerTransY = center_tex_transition_y(transData, texTransTime, texTransPos); 174 s16 texTransRadius = calc_tex_transition_radius(fadeTimer, transTime, transData); 175 Vtx *verts = alloc_display_list(8 * sizeof(*verts)); 176 177 if (verts != NULL) { 178 load_tex_transition_vertex(verts, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, transTexType); 179 gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen) 180 gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); 181 gDPSetRenderMode(gDisplayListHead++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2); 182 gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 8, 0); 183 gSPDisplayList(gDisplayListHead++, dl_transition_draw_filled_region); 184 gDPPipeSync(gDisplayListHead++); 185 gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA); 186 gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); 187 gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP); 188 switch (transTexType) { 189 case TRANS_TYPE_MIRROR: 190 gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], G_IM_FMT_IA, G_IM_SIZ_8b, 32, 64, 0, 191 G_TX_WRAP | G_TX_MIRROR, G_TX_WRAP | G_TX_MIRROR, 5, 6, G_TX_NOLOD, G_TX_NOLOD); 192 break; 193 case TRANS_TYPE_CLAMP: 194 gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], G_IM_FMT_IA, G_IM_SIZ_8b, 64, 64, 0, 195 G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD); 196 break; 197 } 198 gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); 199 gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 4, 0); 200 gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123); 201 gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF); 202 gSPDisplayList(gDisplayListHead++, dl_screen_transition_end); 203 sTransitionTextureFadeCount[fadeTimer] += transData->texTimer; 204 } else { 205 } 206 return set_and_reset_transition_fade_timer(fadeTimer, transTime); 207 } 208 209 s32 render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData) { 210 switch (transType) { 211 case WARP_TRANSITION_FADE_FROM_COLOR: 212 return render_fade_transition_from_color(fadeTimer, transTime, transData); 213 break; 214 case WARP_TRANSITION_FADE_INTO_COLOR: 215 return render_fade_transition_into_color(fadeTimer, transTime, transData); 216 break; 217 case WARP_TRANSITION_FADE_FROM_STAR: 218 return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR); 219 break; 220 case WARP_TRANSITION_FADE_INTO_STAR: 221 return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR); 222 break; 223 case WARP_TRANSITION_FADE_FROM_CIRCLE: 224 return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR); 225 break; 226 case WARP_TRANSITION_FADE_INTO_CIRCLE: 227 return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR); 228 break; 229 case WARP_TRANSITION_FADE_FROM_MARIO: 230 return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP); 231 break; 232 case WARP_TRANSITION_FADE_INTO_MARIO: 233 return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP); 234 break; 235 case WARP_TRANSITION_FADE_FROM_BOWSER: 236 return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR); 237 break; 238 case WARP_TRANSITION_FADE_INTO_BOWSER: 239 return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR); 240 break; 241 } 242 #ifdef AVOID_UB 243 return 0; 244 #endif 245 } 246 247 Gfx *render_cannon_circle_base(void) { 248 #ifdef WIDESCREEN 249 Vtx *verts = alloc_display_list(8 * sizeof(*verts)); 250 Gfx *dlist = alloc_display_list(20 * sizeof(*dlist)); 251 #else 252 Vtx *verts = alloc_display_list(4 * sizeof(*verts)); 253 Gfx *dlist = alloc_display_list(16 * sizeof(*dlist)); 254 #endif 255 Gfx *g = dlist; 256 257 if (verts != NULL && dlist != NULL) { 258 make_vertex(verts, 0, 0, 0, -1, -1152, 1824, 0, 0, 0, 255); 259 make_vertex(verts, 1, SCREEN_WIDTH, 0, -1, 1152, 1824, 0, 0, 0, 255); 260 make_vertex(verts, 2, SCREEN_WIDTH, SCREEN_HEIGHT, -1, 1152, 192, 0, 0, 0, 255); 261 make_vertex(verts, 3, 0, SCREEN_HEIGHT, -1, -1152, 192, 0, 0, 0, 255); 262 263 #ifdef WIDESCREEN 264 // Render black rectangles outside the 4:3 area. 265 make_vertex(verts, 4, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255); 266 make_vertex(verts, 5, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255); 267 make_vertex(verts, 6, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255); 268 make_vertex(verts, 7, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255); 269 #endif 270 271 gSPDisplayList(g++, dl_proj_mtx_fullscreen); 272 gDPSetCombineMode(g++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA); 273 gDPSetTextureFilter(g++, G_TF_BILERP); 274 gDPLoadTextureBlock(g++, sTextureTransitionID[TEX_TRANS_CIRCLE], G_IM_FMT_IA, G_IM_SIZ_8b, 32, 64, 0, 275 G_TX_WRAP | G_TX_MIRROR, G_TX_WRAP | G_TX_MIRROR, 5, 6, G_TX_NOLOD, G_TX_NOLOD); 276 gSPTexture(g++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); 277 gSPVertex(g++, VIRTUAL_TO_PHYSICAL(verts), 4, 0); 278 gSPDisplayList(g++, dl_draw_quad_verts_0123); 279 gSPTexture(g++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF); 280 #ifdef WIDESCREEN 281 gDPSetCombineMode(g++, G_CC_SHADE, G_CC_SHADE); 282 gSPVertex(g++, VIRTUAL_TO_PHYSICAL(verts + 4), 4, 4); 283 gSP2Triangles(g++, 4, 0, 3, 0, 4, 3, 7, 0); 284 gSP2Triangles(g++, 1, 5, 6, 0, 1, 6, 2, 0); 285 #endif 286 gSPDisplayList(g++, dl_screen_transition_end); 287 gSPEndDisplayList(g); 288 } else { 289 return NULL; 290 } 291 return dlist; 292 } 293 294 Gfx *geo_cannon_circle_base(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx) { 295 struct GraphNodeGenerated *graphNode = (struct GraphNodeGenerated *) node; 296 Gfx *dlist = NULL; 297 298 if (callContext == GEO_CONTEXT_RENDER && gCurrentArea != NULL 299 && gCurrentArea->camera->mode == CAMERA_MODE_INSIDE_CANNON) { 300 graphNode->fnNode.node.flags = (graphNode->fnNode.node.flags & 0xFF) | 0x500; 301 dlist = render_cannon_circle_base(); 302 } 303 return dlist; 304 }