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