Alchemy
Loading...
Searching...
No Matches

thor.c

Go to the documentation of this file.
1/// @file
2/// The Thor summon.
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7/// 910 sparks from Ram_MapCellBuffer + 0xc58; the smoke pictures come
8/// before them.
9#define THOR_PARTICLES ((struct EffectStep *)(Ram_MapCellBuffer + 0xc58))
10
11/// The particle sprites, after the light fan pictures.
12#define THOR_SPRITES_CELLS 0x1800
13
14/// The violet mote in the second part's sheet.
15#define THOR_MOTE_CELLS 0x6000
16
17#define THOR_PARTICLE_COUNT 910 ///< particles in THOR_PARTICLES
18#define THOR_DIMMED_DOTS 10000 ///< the darker copies of the dot pictures
19#define THOR_DIMMED_DOT_BYTES MOTE_SET_BYTES ///< bytes in each darker copy
20#define THOR_DUSK_FRAMES 170 ///< frames, at most, of the dusk part
21#define THOR_LIGHTNING_FRAMES 192 ///< frames of the lightning part
22#define THOR_BOLTS 30 ///< violet bolts after the pillar
23#define THOR_BOLT_SIZE 72 ///< each of the three bolt pictures is 72x72
24#define THOR_BOLT_BYTES (THOR_BOLT_SIZE * THOR_BOLT_SIZE)
25
26/// Launches up to max sparks from (px, py), 16.16, into the free slots
27/// (variant 0) of THOR_PARTICLES, walking them with spark and counting with
28/// index. Each flies at angle at a random speed of 32 to 1054 (128ths of a
29/// pixel a frame) and lives 32 to 39 frames. Used for the pillar's 512
30/// sparks and each bolt's 16; the mote's sparks are launched inline.
31#define THOR_LAUNCH_SPARKS(spark, index, px, py, angleExpr, max) \
32 { \
33 s32 spawned = 0; \
34 for (index = 0, spark = THOR_PARTICLES; index != THOR_PARTICLE_COUNT; \
35 index++, spark++) { \
36 if (spark->variant == 0) { \
37 /* FAKEMATCH: the mask set before the Random16() call it masks; as \
38 * Random16() & 0x3ff, 14 lines of tbs-en effect.s differ. */ \
39 s32 speed = 0x3ff; \
40 s32 angle; \
41 speed &= Random16(); \
42 angle = angleExpr; \
43 spark->x = px; \
44 spark->y = py; \
45 speed += 32; \
46 spark->velocityX = (Trig_Sin(angle) * speed) >> 7; \
47 spark->velocityY = -((Trig_Cos(angle) * speed) << 1) >> 7; \
48 spark->variant = (Random16() & 7) + 32; \
49 if (++spawned == (max)) { \
50 break; \
51 } \
52 } \
53 } \
54 }
55
56/// The scene plays in two parts on the effect canvas.
57///
58/// Abilities: Thor (scene kind 12).
59///
60/// In the dusk part (THOR_DUSK_FRAMES, which A or B cuts short) a circle of 128
61/// dots and three lines across it form over scrolling dusk clouds; the circle
62/// turns, sinks into the sky and a beam of light falls from it. In the
63/// lightning part (THOR_LIGHTNING_FRAMES) a pillar of lightning strikes the
64/// formation and throws sparks, THOR_BOLTS violet bolts follow while a violet
65/// mote sways above, and the formation is pushed back in smoke until an impact
66/// burst ends the effect. The sparks live in THOR_PARTICLES; a spark whose
67/// variant is 0 is free, and a positive variant counts the frames it has left.
69 static s16 points[6][2] = {
70 {8, 135}, {184, 135}, {128, 135}, {96, 32}, {96, 32}, {64, 135},
71 };
72 u8 ramp[32];
73 s32 point[3];
74 struct EffectPosition screen[11];
75 s32 position[3];
76 s32 scale[3];
77 void **slots;
78 struct BattleBackgroundView *view;
79 struct BattleEffectWork *work;
80 void *canvas;
81 u8 *sprites;
82 s32 frame;
83 /* FAKEMATCH: frame local: the unused second blitter word fills four bytes of
84 * the frame; as one DrawRectangle, 202 instructions differ in tbs-en. */
85 BlitterPair blit;
86 s32 size;
87 s32 count;
88 s32 i;
89 s32 j;
90 s32 dotCount;
91 struct EffectStep *spark;
92 DrawRectangle *blitters; // the work slots read as blitters
93 s32 dimmedOffset = THOR_DIMMED_DOTS;
94
96 view = slots[0];
100 work->effect = effect;
101 // Open the canvas and load the pictures. The light fan sheet is loaded
102 // twice, to the same place; the second load changes nothing.
107 work->sheet + THOR_SPRITES_CELLS, 0, 0);
109
110 // Eight copies of the dot pictures, each with its colour levels capped 7
111 // lower than the one before.
112 {
113 s32 offset;
114 for (i = 0, offset = 0; i != 8; i++) {
115 u8 *src;
116 for (j = 0, src = sprites; j != THOR_DIMMED_DOT_BYTES; j++) {
117 s32 v = *src++;
118
119 EFFECT_CAP_LEVEL(v, 64 - i * 7);
120 (work->sheet + THOR_DIMMED_DOTS)[offset + j] = v;
121 }
122 offset += j;
123 }
124 }
125
127 PLTT_BACKDROP = 0;
128 *(u16 *)&BG_PLTT[1] = 0; // background palette 0, colour 1
131 work->scrollTimer = 0;
132 work->scrollInterval = 2;
133 work->scrollStepX = 1;
134 work->scrollStepY = 0;
135 // The dusk clouds scroll a pixel every other frame; busy keeps the battle
136 // camera off BG1's scroll meanwhile.
137 view->busy = 1;
145 // The projection centre moves down to line 240 for the dusk part;
146 // BattleFx_SetupBlendedDisplay puts it back.
147 gProjection.centerY = 240;
149 REG_BG2PA = Q_8_8(0.5);
152 blitters = (DrawRectangle *)gWorkSlot;
153 blit[0] = blitters[HEAP_SLOT_BLITTER];
156
157 // One row of the beam: brightest in the middle, darker to each side,
158 // capped at level 63.
159 for (i = 0; i != 16; i++) {
160 ramp[i] = i * 8 + 3;
161 ramp[31 - i] = i * 8 + 3;
162 if (ramp[i] > 63) {
163 ramp[i] = 63;
164 }
165 if (ramp[31 - i] > 63) {
166 ramp[31 - i] = 63;
167 }
168 }
171
172 // First part, 170 frames (A or B skips it): a circle of dots and
173 // three lines across it form and turn over dusk clouds, the circle shrinks
174 // into the sky, and a beam of light falls from it.
175 for (frame = 0; frame != THOR_DUSK_FRAMES; frame++) {
176 size = 2;
177 count = frame * 2;
178 if (frame == 16) {
180 }
181 if (frame == 132) {
183 }
184 if (frame == 151) {
186 }
187 if (gKeysRepeat & (KEY_A | KEY_B)) {
188 break;
189 }
190 // Red, green and blue sway a third of a turn apart, so the canvas
191 // colours cycle through the hues.
192 Graphics_UpdatePhasePalette(frame * 2, 0xaaab, 0x5555, 0);
193 // The frame before the beam clears the canvas instead of fading it.
194 if (frame == 150) {
196 } else {
198 }
199 // Place the circle and lines: they turn over the clouds until frame
200 // 128, then sink and shrink into the sky with growing dots (past 22
201 // frames the sink holds at 20, not 22); after frame 150 they grow
202 // again, with dots of size 5.
203 Projection_Set(0x1fe0000, Iwram_RatioMulQ14(0x1fe0000, 0xc000), 0x7fff0000);
205 if (frame > 128) {
206 s32 sinkFrame = frame - 128;
207 if (sinkFrame > 22) {
208 sinkFrame = 20;
209 }
210 SET_VECTOR(position, 0, -sinkFrame << 17, 0x2000000);
211 size = (sinkFrame >> 2) + 2;
212 if (size > 8) {
213 size = 8;
214 }
219 SceneTransform_ApplyYaw(sinkFrame << 12);
220 if (frame > 150) {
221 SET_VECTOR(scale, frame * 0x1800 - 0xd9400, scale[0], scale[0]);
222 size = 5;
223 } else {
224 SET_VECTOR(scale, 0x10000 - sinkFrame * 3 * 0x400, scale[0], scale[0]);
225 }
227 } else {
228 SET_VECTOR(position, 0, 0, 0x1000000);
231 SceneTransform_ApplyRoll(frame << 8);
232 SceneTransform_ApplyPitch(frame << 8);
233 }
234
235 // The three lines, drawn dot by dot between pairs of points: line i
236 // appears from frame 64 + 12 * i and grows 4 dots a frame, up to 48.
237 // Each point is projected and halved in x for the double-width canvas.
238 if (frame <= 149) {
239 for (i = 0; i != 6; i++) {
240 SET_VECTOR(point, (points[i][0] - 96) << 16, 0,
241 (points[i][1] - 96) << 16);
242 EffectPosition_ProjectPoint(point, &screen[i]);
243 screen[i].x = (screen[i].x >> 17) + 64;
244 screen[i].y = (screen[i].y >> 16) + 60;
245 }
246 for (i = 0; i != 3; i++) {
247 dotCount = count * 2 - i * 48 - 256;
248 if (dotCount > 48) {
249 dotCount = 48;
250 }
251 if (dotCount >= 0) {
252 for (j = 0; j != dotCount; j++) {
253 s32 x = screen[i * 2].x +
254 Iwram_MulQ16(j * (screen[i * 2 + 1].x - screen[i * 2].x),
255 0x555);
256 s32 y = screen[i * 2].y +
257 Iwram_MulQ16(j * (screen[i * 2 + 1].y - screen[i * 2].y),
258 0x555);
259 EFFECT_DRAW_MOTE(blit[0], canvas, sprites, x, y, size);
260 }
261 }
262 }
263 }
264
265 // The circle of up to 128 dots, two more each frame, darkening once
266 // the beam has fallen: from frame 140 it takes the brighter pixel
267 // instead of adding, and from frame 157 each frame draws it with a
268 // darker copy of the dots, down to the seventh. The test on frame 179
269 // always holds, as the part has 170 frames.
270 if (frame <= 179) {
271 DrawRectangle drawAlt;
272 s32 level = 0;
273
274 if (frame > 155) {
275 level = frame - 156;
276 }
277 if (level > 7) {
278 level = 7;
279 }
280 if (frame <= 139) {
284 } else {
288 }
289 dotCount = count;
290 if (dotCount > 128) {
291 dotCount = 128;
292 }
293 for (i = 0; i != dotCount; i++) {
294 s32 dotSize = size + 1;
295 point[0] = Trig_Sin(i << 9) * 96;
296 point[2] = -(Trig_Cos(i << 9) * 96);
297 EffectPosition_ProjectPoint(point, &screen[0]);
298 screen[0].x = (screen[0].x >> 17) + 64;
299 screen[0].y = (screen[0].y >> 16) + 60;
300 drawAlt(canvas,
301 work->sheet +
302 (level * THOR_DIMMED_DOT_BYTES +
303 gBattleFx_MoteCells[dotSize - 1]) +
304 dimmedOffset,
305 screen[0].x - dotSize / 2, screen[0].y - dotSize, dotSize,
306 dotSize * 2);
307 }
309 }
310
311 // The beam, frames 151 to 167: rows of the ramp narrowing at its top,
312 // a column of full rows growing 20 pixels a frame and narrowing a
313 // pixel each side a frame from frame 152, and the light fan falling
314 // down it in two mirrored halves.
315 if ((u32)(frame - 151) <= 16) {
316 s32 inset = 0;
317 s32 beamHeight = (frame - 151) * 20 + 44;
318 if (frame > 151) {
319 inset = frame - 152;
320 }
321 if (inset > 15) {
322 inset = 15;
323 }
324 for (i = 1; i != 10; i++) {
325 if (inset + i <= 15) {
326 blit[0](canvas, &ramp[inset + i], inset + 48 + i, 16 - i,
327 32 - inset * 2 - i * 2, 1);
328 }
329 }
330 for (i = 0; i != beamHeight; i++) {
331 s32 fullWidth = 32;
332 // loop.c matches this 32 with the smoke calls' 32 and hoists it out of
333 // the frame loop, where it loses its register and later reloads rotate:
334 // after an earlier move its threshold is 12, and savings 2 x life 19 x
335 // 12 = 456 reaches the loop's 448 insns.
336 /* FAKEMATCH: the barrier keeps fullWidth's 32 in this loop's
337 * preheader, as native, and lengthens i's life so that dotCount ranks
338 * before i and takes r9. */
339 asm("" : "+r"(fullWidth));
340 blit[0](canvas, ramp + inset, inset + 48, i + 16, fullWidth - inset * 2,
341 1);
342 }
346 canvas, work->sheet, 32, (frame - 151) * 20 - 12, 32, 96);
351 canvas, work->sheet, 64, (frame - 151) * 20 - 12, 32, 96);
353 }
355 }
356
357 // Second part, 192 frames: a pillar of lightning strikes the
358 // formation, throwing sparks, then violet bolts strike again and again while
359 // the formation is pushed back in smoke, ending in an impact burst.
360 view->busy = 0;
364 // Nine objects of resource 0x173, the formation (formation 0 of
365 // BattleFx_PlaceFormationObjects), released at the end.
366 BattleFx_SpawnObjects(9, 0x173, 1);
368 1, 0);
370 1, 1);
372 work->sheet + THOR_MOTE_CELLS, 1, 0);
373 Iwram_CopyWords((void *)BG_PLTT,
376 REG_BLDALPHA = BLEND_ALPHA(16, 16);
377 {
378 s32 formationX;
379 s32 formationY;
380 s32 formationSpeedX;
381 s32 formationSpeedY;
382 s32 pillarX;
383 s32 pillarY;
384
385 formationX = 0x500000;
386 formationY = 0x400000;
387 formationSpeedX = 0;
388 formationSpeedY = 0;
389 for (i = 0; i != THOR_PARTICLE_COUNT; i++) {
390 THOR_PARTICLES[i].variant = 0;
391 }
392 // XXX: nothing in Thor reads these 16 particles, and
393 // BattleFx_RunImpactBurst overwrites them; what they were for is open,
394 // and the Lost Age's twin of this scene may show it.
395 for (i = 0; i != 16; i++) {
396 work->particles[i].x = (Random16() & 31) - 16;
397 work->particles[i].y = Random16() & 63;
398 work->particles[i].variant = -(Random16() & 15);
399 }
402 pillarX = 60;
403 pillarY = 112;
404
405 for (frame = 0; frame != THOR_LIGHTNING_FRAMES; frame++) {
406 s32 stormFrame;
407 if (frame == 20) {
409 work->sheet, 1, 0);
410 }
411 stormFrame = frame - 80;
412 if ((u32)stormFrame <= 59 && !(frame & 7)) {
414 }
415 if (frame == 140) {
417 }
418 // The pillar of lightning, frames 8 to 16: its body on frames 9 to
419 // 11, its top on 12 to 15, and on frame 10 up to 512 sparks thrown
420 // up from its foot. The loop runs once.
421 for (j = 0; j != 1; j++) {
422 s32 start = j * 128 + 8;
423 if (frame >= start && frame < j * 128 + 17) {
424 if (frame >= j * 128 + 9 && frame < j * 128 + 12) {
425 blit[0](canvas, work->sheet, 36, 0, 48, pillarY);
426 }
427 if (frame >= j * 128 + 12 && frame < start + 8) {
428 blit[0](canvas, work->sheet + (48 * 112), 36, 0, 48, 112);
429 }
430 if (frame == start + 2) {
431 THOR_LAUNCH_SPARKS(spark, i, pillarX << 16, pillarY << 16,
432 (Random16() & 0x7fff) - 0x4000, 512);
433 work->shakeFrames = 8;
434 }
435 }
436 }
437 // The pillar strikes every target on frame 10.
438 if (frame == 10) {
441 POSE_DAMAGE, i, 8);
443 }
444 }
445 // Frames 80 to 143: thirty violet bolts, 2 frames apart, each shown
446 // for 2 frames with a jitter, throwing 16 sparks and striking every
447 // target in a random colour; the canvas flashes every 8 frames for
448 // the first six; and the violet mote sways in four mirrored copies,
449 // shedding 4 sparks a frame.
450 if ((u32)stormFrame <= 63) {
451 s32 moteX;
452 s32 moteY;
453 s32 mirrorX;
454 for (i = 0; i != 6; i++) {
455 if (frame == i * 8 + 80) {
456 Iwram_FillWords(canvas, CANVAS_BYTES, 0x10101010);
457 }
458 }
459 for (i = 0; i != THOR_BOLTS; i++) {
460 if (frame >= i * 2 + 80) {
461 if (frame < i * 2 + 82) {
462 s32 boltX = (Random16() & 3) - 3;
463 s32 boltY = (Random16() & 3) + 32;
467 canvas, work->sheet + i % 3 * THOR_BOLT_BYTES, boltX, boltY,
470 }
471 if (frame == i * 2 + 80) {
472 THOR_LAUNCH_SPARKS(spark, j, 0x100000, 0x500000,
473 Random16() & 0xffff, 16);
474 work->shakeFrames = 8;
478 POSE_DAMAGE, j, 4);
480 }
481 }
482 }
483 }
484 {
485 // The mote: a random offset 8 to 15 pixels from where it rests.
486 s32 radius = 7;
487 s32 angle;
488 radius &= Random16();
489 angle = Random16() & 0xffff;
490 moteX = (Trig_Sin(angle) * (radius + 8)) >> 16;
491 mirrorX = moteX + 72;
492 moteY = 32 - ((Trig_Cos(angle) * (radius + 8)) >> 16);
493 }
497 canvas, work->sheet + THOR_MOTE_CELLS, moteX + 60, moteY - 24, 12,
498 24);
504 canvas, work->sheet + THOR_MOTE_CELLS, mirrorX, moteY - 24, 12, 24);
510 canvas, work->sheet + THOR_MOTE_CELLS, moteX + 60, moteY, 12, 24);
517 canvas, work->sheet + THOR_MOTE_CELLS, mirrorX, moteY, 12, 24);
519 j = 0;
520 for (i = 0, spark = THOR_PARTICLES; i != THOR_PARTICLE_COUNT;
521 i++, spark++) {
522 if (spark->variant == 0) {
523 s32 speed = 63;
524 s32 angle;
525 speed &= Random16();
526 angle = Random16() & 0xffff;
527 spark->x = mirrorX << 16;
528 spark->y = moteY << 16;
529 speed += 64;
530 spark->velocityX = (Trig_Sin(angle) * speed) >> 7;
531 spark->velocityY = -((Trig_Cos(angle) * speed) << 1) >> 7;
532 spark->variant = (Random16() & 7) + 16;
533 if (++j == 4) {
534 break;
535 }
536 }
537 }
538 }
539
544 {
545 // Live sparks fall under gravity and bounce at half speed off the
546 // ground (y 120); those on the canvas shrink as their life runs
547 // out.
549 struct EffectStep *spark;
550 for (i = 0, spark = THOR_PARTICLES; i != THOR_PARTICLE_COUNT;
551 i++, spark++) {
552 if (spark->variant > 0) {
553 spark->variant--;
555 if (spark->y > 0x780000) {
556 spark->velocityY = -spark->velocityY / 2;
557 } else if ((u32)spark->x <= 0x7effff && spark->y >= 0) {
558 s32 x = spark->x >> 16;
559 s32 y = spark->y >> 16;
560 s32 dotSize = spark->variant / 16 + 1;
561 EFFECT_DRAW_MOTE(draw, canvas, sprites, x, y, dotSize);
562 }
563 }
564 }
565 }
567
568 // The formation is placed from frame 16 and pushed back from frame
569 // 32, the push slowing by 1/16 each frame.
570 if (frame > 15) {
571 if (frame == 32) {
572 formationSpeedX = 0x40000;
573 formationSpeedY = -0x4000;
574 }
575 if (frame > 31) {
576 formationX += formationSpeedX;
577 formationY += formationSpeedY;
578 formationSpeedX = formationSpeedX * 60 / 64;
579 formationSpeedY = formationSpeedY * 60 / 64;
580 }
581 BattleFx_PlaceFormationObjects(0, formationX, formationY);
582 }
583 // Frames 16 to 143: three puffs of smoke a frame around the
584 // formation, from the first three glint cells, placed and flipped at
585 // random.
586 if ((u32)(frame - 16) <= 127) {
587 s32 formationScreenX;
588 for (i = 0, formationScreenX = formationX >> 17; i != 3; i++) {
589 s32 glint = i & 3;
590 s32 angle = Random16() & 0xffff;
591 s32 x = (((Trig_Sin(angle) * 8)) >> 16) + formationScreenX -
592 (gBattleFx_GlintCellWidths[glint] >> 1);
593 s32 y = ((Trig_Cos(angle) * 40) >> 16) -
594 (gBattleFx_GlintCellHeights[glint] >> 1);
596 3 | gThor_SmokeFlips[Random16() & 3], 2);
598 canvas, Ram_MapCellBuffer + gBattleFx_GlintCells[glint], x,
599 y + 56, gBattleFx_GlintCellWidths[glint],
602 }
603 }
604 if (frame <= 31) {
605 Camera_ApplyShake(8, 16);
606 } else {
607 Camera_ApplyShake(4, 4);
608 }
609 EFFECT_END_FRAME(work);
610 }
611
614 BattleFx_RunImpactBurst(0, formationX, formationY);
615 }
616 for (i = 0; i != 9; i++) {
618 }
620}
621
622#undef THOR_PARTICLES
623#undef THOR_MOTE_CELLS
624#undef THOR_PARTICLE_COUNT
625#undef THOR_DIMMED_DOTS
626#undef THOR_DIMMED_DOT_BYTES
627#undef THOR_DUSK_FRAMES
628#undef THOR_LIGHTNING_FRAMES
629#undef THOR_BOLTS
630#undef THOR_BOLT_SIZE
631#undef THOR_BOLT_BYTES
632#undef THOR_LAUNCH_SPARKS
633#undef THOR_SPRITES_CELLS
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_DAMAGE
taking damage
Definition battle.h:176
@ COMPOSITE_FLIP_X
@ COMPOSITE_FLIP_Y
@ COMPOSITE_ADDITIVE
@ COMPOSITE_MAX
BattleEffectDrawRectangle DrawRectangle
#define EFFECT_FOR_EACH_TARGET(i, effect)
Loops i over the effect's targets, effect->actors[0] to effect->actors[effect->count - 1]: the loops ...
void BattleFx_ProcessPendingGraphicsTransfer(void)
Copies the canvas to VRAM once the effect has finished drawing a frame (transferPending): the 128x128...
Definition canvas.c:103
void BattleFx_EndCanvasLayer(void)
Closes the canvas layer: plays the closing sound, restores BG1's scroll and the projection centre,...
Definition canvas.c:490
void BattleFx_WipeCanvas(s32 mode, s32 value)
Wipes the whole canvas to one colour with a ragged edge: each row (or column) lags a random 0 to 63 p...
Definition canvas.c:27
void BattleFx_ConfigureEffectDisplay(void)
Puts the battle screen back into the display state every effect starts from and ends with: no blendin...
Definition display.c:16
void BattleFx_AdvanceScrollOnInterval(void)
Scrolls BG1 by (scrollStepX, scrollStepY) once every scrollInterval frames.
Definition display.c:37
void Resource_LoadAndDecompress(s32 id, void *dst, s32 skipPalette, s32 copyPalette)
Decompresses a resource whose first 128 bytes may be a palette.
void ObjectGroup_UpdateMembers(s32 actorId, s32 palette, s32 animation, s32 timerSlot, s32 timerFrames)
Updates every animation group of one battler's object.
Definition dispatch.c:254
void BattleFx_SetupBlendedDisplay(void)
Shows the BG1 battle background behind a cleared canvas: clears the canvas buffer and the 16 KiB of V...
Definition dispatch.c:217
void BattleFx_SelectLivingTargets(struct BattleEffectArgument *effect)
Shows the battle objects of every unit with HP left on the targets' side: the enemies (units 128 to 1...
Definition dispatch.c:184
What every part of the battle effect object shares: its includes, macros and frame-loop helpers.
#define EFFECT_SHOW_WIDE_CANVAS(top)
Shows the canvas: the effect display mode, BG2 stretched to twice its width (the 128-pixel canvas sho...
#define EFFECT_DRAW_MOTE(draw, canvas, sheet, x, y, size)
Particle sheets hold ten mote cells, 1x2 to 10x20 pixels.
#define EFFECT_PRESENT_FRAME(work)
Ends a frame of a canvas effect: marks the canvas ready for the transfer callback,...
#define EFFECT_SET_TRANSFER(work, mode, value)
Sets how the canvas transfer treats what is left in the canvas after each copy: mode with value (see ...
@ CANVAS_COPY
copy as drawn
@ CANVAS_COPY_AND_CLEAR
copy, then fill the canvas with transferValue
@ CANVAS_COPY_AND_FADE
copy, keeping 50% or 75% (transferValue) of each pixel in the canvas for the next frame
#define CANVAS_BYTES
The canvas: 128x128 pixels, one byte each, in its heap slot and in VRAM at BG_CHAR_BLOCK(1).
#define EFFECT_CALLBACK_ORDER
The scheduler order of every per-frame effect callback (Scheduler_AddOrUpdateCallback sorts the frame...
#define EFFECT_SHOW_DAMAGE(hitSound)
Lets the battle show the damage: resumes its paused playback, which plays hitSound (an SE_ id; 0 keep...
#define EFFECT_LOAD_BLITTER(slot, flags, mode)
Builds a blitter for the 128x128 canvas (1 << 7 pixels each way) in work slot slot: BattleFx_BuildBli...
#define EFFECT_CAP_LEVEL(level, cap)
Caps a colour level at cap, and at 0 from below.
#define EFFECT_END_FRAME(work)
The usual end of an effect frame: counts down the targets' flash timers (ObjectGroup_TickMemberTimers...
#define EFFECT_BEGIN_NARROW_CANVAS(bgControl)
Opens the canvas layer at the canvas's own width, one texel per pixel, where BattleFx_BeginCanvasLaye...
u8 gBattleFx_GlintCellHeights[]
u16 gBattleFx_MoteCells[]
Mote cells: particle sheets hold ten, cell n (from 0) n + 1 pixels wide and twice that tall.
u16 gBattleFx_GlintCells[]
u8 gThor_TargetPalettes[]
The colours a target flashes when a bolt strikes it, chosen at random: white, black,...
u8 gBattleFx_GlintCellWidths[]
u8 gThor_SmokeFlips[]
Flip flags for the smoke puffs, chosen at random.
void BattleFx_SpawnObjects(s32 entryCount, s32 source, u32 priority)
Creates the effect's animation objects in gBattleFxWork's objects.
Definition eruption.c:220
void BattleMotion_ApplyVariantMotionFar(s32 id, s32 variant)
void BattleBackground_LoadFar(s32 mode, s32 resource, s32 level)
void ResourceObject_ReleaseFar(struct AnimationObject *sprite)
void AudioCommand_PlayFar(s32 id)
s32 Trig_Cos(s32 angle)
s32 Trig_Sin(s32 angle)
void Camera_ApplyShake(s32 rangeX, u32 rangeY)
Shakes the battle view while gBattleFxWork's shakeFrames lasts, moving BG1 and the projection centre ...
Definition hail.c:364
@ HEAP_SLOT_BATTLE_EFFECT
Definition heap_state.h:42
@ HEAP_SLOT_BLITTER_ALTERNATE
Definition heap_state.h:47
@ HEAP_SLOT_BATTLE_BACKGROUND
Definition heap_state.h:45
@ HEAP_SLOT_BATTLE_SHEET
Definition heap_state.h:44
@ HEAP_SLOT_BLITTER
Definition heap_state.h:46
@ HEAP_SLOT_BATTLE_CANVAS
Definition heap_state.h:43
void BattleFx_RunImpactBurst(s32 formation, s32 x, s32 y)
Opens an impact flash and scatters sparks and fragments, keeping the effect's objects in formation fo...
void BattleFx_PlaceFormationObjects(s32 formation, s32 x, s32 z)
Arranges work->objects in a formation; x and z are its origin in 16.16 pixels.
#define Q_8_8(n)
The BG2/BG3 affine matrix entries are signed 8.8 fixed point: texels stepped per screen pixel.
Definition io_reg.h:59
#define BGCNT_CHAR_BASE(block)
Definition io_reg.h:25
#define BGCNT_256_COLORS
Definition io_reg.h:27
#define BGCNT_PRIORITY(n)
Definition io_reg.h:24
@ KEY_B
Definition io_reg.h:244
@ KEY_A
Definition io_reg.h:243
#define PLTT_BACKDROP
Definition io_reg.h:155
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
Definition io_reg.h:145
#define BGCNT_SCREEN_BASE(block)
Definition io_reg.h:28
#define REG_BG2CNT
Definition io_reg.h:21
#define REG_BLDALPHA
Definition io_reg.h:142
#define BG_PLTT
Definition io_reg.h:157
#define REG_BG2PA
Definition io_reg.h:61
#define BGCNT_WRAP
Affine backgrounds only: wrap around instead of showing the backdrop.
Definition io_reg.h:30
static s32 Iwram_RatioMulQ14(s32 divisor, s32 value)
All calls go through this layer.
Definition iwram_call.h:51
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
Definition iwram_call.h:85
static s32 Iwram_FillWords(void *destination, s32 size, u32 value)
Definition iwram_call.h:59
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
#define SET_VECTOR(v, x, y, z)
Sets the x, y and z of a three-part vector: a position about to be projected, a per-frame step,...
Definition macros.h:12
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
void Runtime_ReleaseHeapBlock(s32 slot)
void EffectStep_AdvanceWithGravity2D(struct EffectStep *step, s32 damping, s32 gravity)
Moves a particle one frame on the screen: adds its velocity, then gravity to its vertical speed,...
Definition positions.c:46
s32 EffectPosition_ProjectPoint(const void *point, struct EffectPosition *position)
Projects a point in the current transform onto the screen, 16 pixels higher, and returns the projecti...
Definition positions.c:64
void Graphics_UpdatePhasePalette(s32 frame, s32 redPhase, s32 greenPhase, s32 bluePhase)
Rebuilds the background palette's first ramp as a grey ramp whose red, green and blue each sway with ...
Definition prism.c:183
struct Projection gProjection
#define Ram_MapCellBuffer
Definition ram_buffer.h:10
char ResourceId_TornadoSheet
char ResourceId_ParticleSpritesB
char ResourceId_CrystalSheet
char ResourceId_ParticleSpritesC
char ResourceId_LightFanSheet
char ResourceId_VioletLightningSheetB
char ResourceId_DuskCloudsBackdrop
char ResourceId_VioletMoteSheet
char ResourceId_ParticleSpritesA
char ResourceId_LightningPillarSheet
s32 Scheduler_AddOrUpdateCallback(SchedulerCallback callback, s32 order)
Schedules callback with order, or gives a task already running it the new order, and re-sorts the tab...
Definition scheduler.c:102
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
#define SE_131
Definition songs.h:124
#define SE_HEAVY_IMPACT
Definition songs.h:127
#define SE_140
Definition songs.h:133
#define SE_145
Definition songs.h:138
void * gWorkSlot[]
The battle background's work slot as the background code reads it: its display mode (2 draws it as an...
s32 busy
while set, BattleCamera_SetRange leaves BG1's scroll
The command shared by an effect's caller, dispatcher and handlers.
s16 actors[8]
the targets' unit ids, count of them
The running battle effect's work: its canvas image, 64 particles, the display registers it stages and...
s32 frame
frame counter some effects keep, from 0
s32 shakeFrames
shake frames left; Camera_ApplyShake counts down
struct AnimationObject * objects[16]
the effect's animation objects
s32 transferMode
How the canvas transfer callbacks treat the canvas after each copy (enum CanvasTransferMode in effect...
s32 scrollStepY
added to BG1 or BG2 y at each step
s32 scrollTimer
frames since the last interval scroll step
struct BattleEffectArgument * effect
the command being run
s32 scrollStepX
added to BG1 or BG2 x at each step
s32 scrollInterval
frames between interval scroll steps
struct EffectStep particles[64]
free while variant is -1
A point projected onto the screen, with its depth.
Definition effect_step.h:46
s32 y
screen pixels
Definition effect_step.h:59
s32 x
screen pixels
Definition effect_step.h:58
A moving point of an effect: its position, its velocity and a value each effect uses its own way (a s...
Definition effect_step.h:13
s32 velocityX
16.16 fixed-point pixels per frame
Definition effect_step.h:28
s32 variant
each effect's own: a size, a countdown, -1 for idle
Definition effect_step.h:31
s32 x
16.16 fixed-point pixels
Definition effect_step.h:24
s32 y
16.16 fixed-point pixels
Definition effect_step.h:25
s32 velocityY
16.16 fixed-point pixels per frame
Definition effect_step.h:29
s32 centerY
screen pixels
Definition project.h:17
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
Definition system.c:150
#define THOR_DIMMED_DOTS
the darker copies of the dot pictures
Definition thor.c:18
#define THOR_PARTICLE_COUNT
particles in THOR_PARTICLES
Definition thor.c:17
#define THOR_LAUNCH_SPARKS(spark, index, px, py, angleExpr, max)
Launches up to max sparks from (px, py), 16.16, into the free slots (variant 0) of THOR_PARTICLES,...
Definition thor.c:31
void BattleFx_RunThor(struct BattleEffectArgument *effect)
The scene plays in two parts on the effect canvas.
Definition thor.c:68
#define THOR_BOLT_BYTES
Definition thor.c:24
#define THOR_LIGHTNING_FRAMES
frames of the lightning part
Definition thor.c:21
#define THOR_BOLTS
violet bolts after the pillar
Definition thor.c:22
#define THOR_MOTE_CELLS
The violet mote in the second part's sheet.
Definition thor.c:15
#define THOR_DUSK_FRAMES
frames, at most, of the dusk part
Definition thor.c:20
#define THOR_BOLT_SIZE
each of the three bolt pictures is 72x72
Definition thor.c:23
#define THOR_DIMMED_DOT_BYTES
bytes in each darker copy
Definition thor.c:19
#define THOR_PARTICLES
910 sparks from Ram_MapCellBuffer + 0xc58; the smoke pictures come before them.
Definition thor.c:9
#define THOR_SPRITES_CELLS
The particle sprites, after the light fan pictures.
Definition thor.c:12
void SceneTransform_ApplyYaw(s32 angle)
Rotates gTransform about the Y axis by angle.
Definition transform.c:113
void Projection_Set(u32 focal, u32 nearDepth, u32 farDepth)
Sets gProjection's focal length and depth range directly.
Definition transform.c:350
void SceneTransform_ApplyPitch(s32 angle)
Rotates gTransform about the X axis by angle.
Definition transform.c:97
void SceneTransform_ApplyPosition(const s32 *position)
Translates gTransform by position (x, y, z in 16.16).
Definition transform.c:145
void Render_ResetTransformState(void)
Allocates the one-level save area (heap slot HEAP_SLOT_TRANSFORM_STACK), clears gTransformStackDepth ...
Definition transform.c:19
void SceneTransform_ApplyScale(const s32 *scale)
Scales gTransform by scale (x, y, z factors in 16.16).
Definition transform.c:158
void SceneTransform_ApplyRoll(s32 angle)
Rotates gTransform about the Z axis by angle.
Definition transform.c:129
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
#define EFFECT_BLITTERS
The work slots read as blitters: EFFECT_BLITTERS[HEAP_SLOT_BLITTER] and EFFECT_BLITTERS[HEAP_SLOT_BLI...
Definition effect.h:248
#define EFFECT_CLIP_BOUNDS
Clips overflow on all four sides.
Definition effect.h:224
DrawRectangle BlitterPair[2]
A blitter pair: [0] built in HEAP_SLOT_BLITTER and [1] in HEAP_SLOT_BLITTER_ALTERNATE (BattleFx_Fetch...
Definition effect.h:244