Alchemy
Loading...
Searching...
No Matches

death_plunge.c

Go to the documentation of this file.
1/// @file
2/// Death Plunge, the blade rain, the element pillar, the element burst and
3/// the shattering picture.
4/// Part of effect.c, the battle effect object, compiled only through it.
5
7
8// - Death Plunge runs the user up to the first target; both leap, turn upside
9// down, and on the hit bounce apart while a ring of flashes rises from the
10// user.
11// - The blade rain drops 16 swords, one every 4 frames, slanting in on the
12// first target and sticking in the ground. No effect table entry points at
13// it.
14// - The element pillar (BattleFx_RunElementPillar) stands a mirrored pillar
15// of light at a unit's feet while motes spiral up around it.
16// - The element burst (BattleFx_RunElementBurst) flares sparks at four corners
17// around a unit, draws motes spiralling in, then plays a burst of light
18// over it.
19// - BattleFx_RunShatteringOpening shatters a picture into 33 pieces as a
20// battle opens.
21// - The element streaks (BattleFx_StartElementStreaks) draw lines of light
22// closing in on a unit from a scheduler callback while the battle runs on.
23//
24// The element runners, the streaks and the shattering opening are reached
25// from the battle through far calls, not the handler table, and allocate
26// their own work, canvas and sheet instead of using the shared ones.
27
28#define DEATH_PLUNGE_FRAMES 96
29
30/// The user runs 9/10 of the way to the first target, then both leap and turn
31/// upside down in the air; on frame 54 the target is hit and both bounce back,
32/// while flashes burst from the user and rise in a widening ring.
33///
34/// Abilities: Death Plunge (kind 53).
36 void **slots;
37 void **cursor;
38 struct BattleEffectWork *work;
39 void *canvas;
40 /* FAKEMATCH: frame local: an unused second blitter word fills the frame's
41 * 8-byte draw slot; with draw[1], 14 instructions differ in tbs-en. */
42 BlitterPair draw;
43 struct BattleObj *first;
44 struct BattleObj *second;
45 struct MotionObject *user;
46 struct MotionObject *target;
47 s32 x;
48 s32 z;
49 s32 userHeight;
50 s32 targetHeight;
51 s32 point[3];
52 struct EffectPosition screen;
53 s32 frame;
54 s32 percent;
55
56 EFFECT_GET_SLOTS(slots, cursor, work, canvas);
57 work->effect = effect;
60 1);
62 // Trails keep 3/4 a frame.
64 work->transferValue = 75;
65 draw[0] = EFFECT_SLOT(slots, HEAP_SLOT_BLITTER);
68 // The run: the user moves to 90% of the way to the target, accelerating
69 // to 8 pixels a frame, and the effect waits 20 frames for it.
70 first = GetBattleObjectSlotFar(work->effect->actor);
71 second = GetBattleObjectSlotFar(work->effect->actors[0]);
72 user = first->object;
73 target = second->object;
74 percent = 90;
75 x = user->x + percent * (target->x - user->x) / 100;
76 z = user->z + percent * (target->z - user->z) / 100;
77 userHeight = BattleUnit_GetEffectHeightFar(work->effect->actor);
78 targetHeight = BattleUnit_GetEffectHeightFar(work->effect->actors[0]);
80 Object_SetMoveTargetFar((struct ObjectRuntime *)user, x, 0, z);
82 user->snapToTarget = 1;
83 user->autoFaceMotion = 1;
84 user->acceleration = 2 << 16;
85 user->speedLimit = 8 << 16;
86 WaitFrames(20);
87 for (frame = 0; frame != DEATH_PLUNGE_FRAMES; frame++) {
88 struct BattleCamera *camera;
89
90 camera = gCameraWork;
92
93 // Frame 0: both leap at 15 pixels a frame. Frame 11: both turn upside
94 // down, raised by their own heights so they flip about their middles.
95 // XXX: verticalMotionStrength's units (0x91eb here, 0xab85 and 0x7851 on
96 // the bounce); the object motion code that reads it would settle them.
97 if (frame == 0) {
98 target->velocityY = 15 << 16;
99 target->verticalMotionStrength = 0x91eb;
100 user->velocityY = 15 << 16;
101 user->verticalMotionStrength = 0x91eb;
102 }
103 if (frame == 11) {
104 target->scaleY = -target->scaleY;
105 user->scaleY = -user->scaleY;
106 user->y += userHeight;
107 target->y += targetHeight;
108 }
109
110 // Frame 54: the target flashes and both bounce; the user heads back
111 // towards the middle of the field.
112 if (frame == 54) {
114 POSE_DAMAGE, 0, 10);
115 target->velocityY = 8 << 16;
116 target->verticalMotionStrength = 0xab85;
117 user->velocityY = 5 << 16;
118 user->verticalMotionStrength = 0x7851;
119 user->acceleration = 1 << 16;
120 user->speedLimit = 2 << 16;
121 user->autoFaceMotion = 0;
123 Object_SetMoveTargetFar((struct ObjectRuntime *)user, 0, 0, user->z);
124 }
126 SET_VECTOR(point, user->x, user->y, user->z);
127 EffectPosition_ProjectPoint(point, &screen);
128 screen.x >>= 1;
129
130 // Frames 54 and 55: one big flash on the user. Frames 56 to 67: 16
131 // flashes in a ring that widens as it rises, through six images, two
132 // frames each (32x64, 0x800 bytes a picture).
133 if (frame == 54 || frame == 55)
134 draw[0](canvas, work->sheet, screen.x - 16, screen.y - 16, 32, 64);
135 if (frame >= 56 && frame <= 67) {
136 s32 i;
137
138 for (i = 0; i != 16; i++) {
139 s32 angle;
140 s32 rx;
141 s32 ry;
142
143 angle = i << 12; // 22.5 degrees apart
144 rx = screen.x + ((Trig_Sin(angle) * (frame - 46)) >> 16);
145 ry = ((Trig_Cos(angle) * (frame - 46)) >> 16) - frame + 100;
146 draw[0](canvas, work->sheet + (((frame - 56) / 2) << 11), rx - 16, ry,
147 32, 64);
148 }
149 }
150
151 // Frame 64: both turn right side up again.
152 if (frame == 64) {
153 target->scaleY = -target->scaleY;
154 user->scaleY = -user->scaleY;
155 user->y -= userHeight;
156 target->y -= targetHeight;
158 }
159 // The cues: the damage with a heavy impact on the hit, and a shake on
160 // the leap and on the frame before the hit.
161 if (frame == 54)
163 if (frame == 0) {
165 work->shakeFrames = 6;
166 }
167 if (frame == 53)
168 work->shakeFrames = 6;
169 Camera_ApplyShake(16, 16);
171 }
173}
174
175#define BLADE_RAIN_FRAMES 120
176
177/// Drops 16 swords, one every 4 frames, slanting in towards the first target
178/// (the middle of the canvas, x 64) and sticking in the ground, where their
179/// bottom 4 pixels are hidden.
180///
181/// Sword i falls from frame 4i + 16 and sticks at frame 4i + 25. Every 4
182/// frames from 24 to 84 the target flashes white in its damage pose for 2
183/// frames and the screen shakes; every 8 frames the hit sound plays.
184///
185/// Nothing reaches it: no handler table entry or call names it. Places 64
186/// swords in work->particles but draws only the first 16, and moves BG2X to
187/// centre the canvas on the target.
189 struct EffectPosition screenPosition;
190 BlitterPair draw;
191 void **slots;
192 void **cursor;
193 struct BattleEffectWork *work;
194 void *canvas;
195 DrawRectangle *blit;
196 struct EffectStep *blade;
197 s32 frame;
198 s32 i;
199
200 EFFECT_GET_SLOTS(slots, cursor, work, canvas);
201 work->effect = effect;
203 // Invisible to start with.
204 REG_BLDALPHA = BLEND_ALPHA(0, 16);
205
206 // Setup: [0] draws as is, [1] mirrored; both skip colour 0.
214 blit = draw;
216 1);
217 // Redraw from blank each frame.
219 // Scroll the canvas so its middle column sits on the first target.
220 EffectPosition_ProjectScaledBattler(work->effect->actors[0], &screenPosition);
221 REG_BG2X = (64 - screenPosition.x) << 8;
222
223 // Each sword starts at a random x from 16 to 111, above the canvas, and
224 // drifts towards the middle faster (in steps of 2 pixels a frame) the
225 // further out it starts.
226 for (i = 0; i != 64; i++) {
227 s32 column;
228
229 blade = &work->particles[i];
230 column = Random16() % 96 + 16;
231 blade->x = column;
232 blade->y = (24 - i / 4) << 16;
233 if (column <= 43)
234 blade->velocityX = 3;
235 else if (column <= 51)
236 blade->velocityX = 2;
237 else if (column <= 59)
238 blade->velocityX = 1;
239 else if (column <= 67)
240 blade->velocityX = 0;
241 else if (column <= 75)
242 blade->velocityX = -1;
243 else if (column <= 83)
244 blade->velocityX = -2;
245 else
246 blade->velocityX = -3;
247 blade->velocityX <<= 17;
248 blade->velocityY = 8 << 16;
249 blade->x <<= 16;
250 }
252 for (frame = 0; frame != BLADE_RAIN_FRAMES; frame++) {
253 // Frame loop. Fade in over the first 16 frames, with blending off once
254 // opaque, and out over the last 16.
255 if (frame <= 16) {
256 REG_BLDALPHA = BLEND_ALPHA(frame, 16);
257 if (frame == 16)
258 REG_BLDCNT = 0;
259 }
260 if (frame > 103) {
261 REG_BLDALPHA = BLEND_ALPHA(120 - frame, 16);
262 if (frame == 104)
264 }
265
266 // The image depends on how steeply the sword falls, and a sword
267 // drifting left is drawn mirrored (the drift's sign bit picks the
268 // blitter). Sword i falls from frame 4i + 16 and sticks in the ground
269 // at frame 4i + 25; the last drawn first, so earlier swords lie on top.
270 for (i = 15; i != -1; i--) {
271 s32 drift;
272 s32 speed;
273 s32 cell;
274
275 blade = &work->particles[i];
276 drift = blade->velocityX;
277 speed = drift;
278 if (drift < 0)
279 speed = -drift;
280 cell = speed >> 17;
281 if (frame < i * 4 + 25) {
282 u32 width;
283 u32 height;
284
285 // UB: width is assigned in one argument and read in another.
286#ifdef UBFIX
287 width = gDeathPlunge_CellWidths[cell];
288 height = gDeathPlunge_CellHeights[cell];
289 blit[(u32)drift >> 31](canvas, work->sheet + gDeathPlunge_Cells[cell],
290 (blade->x >> 16) - (width >> 1),
291 (blade->y >> 16) - (height >> 1), width, height);
292#else
293 blit[(u32)drift >> 31](
294 canvas, work->sheet + gDeathPlunge_Cells[cell],
295 (blade->x >> 16) - ((width = gDeathPlunge_CellWidths[cell]) >> 1),
296 (blade->y >> 16) - ((height = gDeathPlunge_CellHeights[cell]) >> 1),
297 width, height);
298#endif
299 if (frame >= i * 4 + 16) {
300 blade->x += blade->velocityX;
301 blade->y += blade->velocityY;
302 }
303 } else {
304 u32 width;
305 u32 height;
306
307#ifdef UBFIX
308 width = gDeathPlunge_CellWidths[cell];
309 height = gDeathPlunge_CellHeights[cell];
310 blit[(u32)drift >> 31](canvas, work->sheet + gDeathPlunge_Cells[cell],
311 (blade->x >> 16) - (width >> 1),
312 (blade->y >> 16) - (height >> 1), width,
313 height - 4);
314#else
315 blit[(u32)drift >> 31](
316 canvas, work->sheet + gDeathPlunge_Cells[cell],
317 (blade->x >> 16) - ((width = gDeathPlunge_CellWidths[cell]) >> 1),
318 (blade->y >> 16) - ((height = gDeathPlunge_CellHeights[cell]) >> 1),
319 width, height - 4);
320#endif
321 }
322 }
323
324 // Every 4 frames from 24 to 84 the target flashes white in its damage
325 // pose for 2 frames and the screen shakes; every 8 frames the hit
326 // sound plays.
327 if (frame >= 23 && frame <= 87 && (frame & 3) == 0) {
329 POSE_DAMAGE, 0, 2);
330 work->shakeFrames = 1;
331 if ((frame & 7) == 0)
333 }
334 Camera_ApplyShake(8, 8);
335 EFFECT_END_FRAME(work);
336 }
338}
339
340#define ELEMENT_PILLAR_FRAMES 56
341
342/// The glow of an element around a unit: a symmetrical pillar of light
343/// stands at the unit's feet while motes spiral up around it, for 56 frames,
344/// and the first target flashes.
345///
346/// Called through BattleFx_RunElementPillarFar by
347/// BattleFx_PlayUnitElementEffect (its mode 2) and four times in a row, one
348/// for each element, by BattlePres_RunUnitAction. Allocates and frees its
349/// own work, canvas and sheet slots; loads the element's colours over the
350/// first 64 of the background palette, fills PARTICLES 0 to 127 and moves
351/// BG2X with the unit. Increments effect->variant in place, so
352/// BattlePres_RunUnitAction's four calls draw ever larger motes.
353///
354/// effect->kind : the element, which picks the palette: 0 Venus yellow,
355/// 1 Mercury blue, 2 Mars red, others Jupiter violet.
356/// effect->variant : the mote size less one, kept to 1 to 4 after adding 1.
358 struct EffectPosition ground;
359 struct EffectPosition screenPosition;
360 s32 point[3];
361 struct BattleEffectWork *work;
362 void *canvas;
363 BlitterPair draw;
364 u8 *sheet;
365 struct BattleCamera *camera;
366 s32 frame;
367 void *palette;
368 s32 i;
369
371 HEAP_SLOT_BATTLE_EFFECT, sizeof *work);
372 canvas =
375 camera = gCameraWork;
376 work->effect = effect;
378 // Palette_StepFadeTransfer darkens the backdrop for 24 frames.
379 work->fadeFrames = 24;
380 work->fadeStep = 0;
381 // The narrow canvas, 12/16 over all of the background.
382 REG_BLDALPHA = BLEND_ALPHA(12, 16);
383 REG_BG2PA = Q_8_8(1);
386 switch (work->effect->kind) {
387 case 0:
389 break;
390 case 1:
392 break;
393 case 2:
395 break;
396 default:
398 break;
399 }
400 Iwram_CopyWords((void *)BG_PLTT, palette, 128);
401
402 // The spiral's motes: x holds the angle and z the radius in 1/16
403 // pixels; mote i waits i frames before it starts to rise.
404 for (i = 0; i != 128; i++) {
405 PARTICLES[i].y = 0;
406 PARTICLES[i].x = Random16() & 0xffff;
407 PARTICLES[i].z = (Random16() & 0x1ff) + i * 2;
408 PARTICLES[i].variant = -i;
409 }
410 /* FAKEMATCH: the cancelling pointer updates retain work's allocation
411 * priority; without them, 50 of 420 instructions differ in tbs-en. */
412 work++;
413 work--;
414 // Trails keep 3/4 a frame.
418 draw[0] = gWorkSlot[HEAP_SLOT_BLITTER];
419 // The mote size, written back into the caller's argument.
420 work->effect->variant++;
421 if (work->effect->variant <= 0)
422 work->effect->variant = 1;
423 if (work->effect->variant > 4)
424 work->effect->variant = 4;
426
427 for (frame = 0; frame != ELEMENT_PILLAR_FRAMES; frame++) {
428 // Frame loop. Keep the canvas centred on the unit's feet, fade out over
429 // the last 6 frames, and flash the first target from frame 16 for 20
430 // frames.
432 REG_BG2X = (64 - ground.x) << 8;
433 if (frame > 49)
434 REG_BLDALPHA = BLEND_ALPHA(112 - frame * 2, 16);
435 if (frame == 16)
437 0, 20);
438
439 // The pillar: its left half at x 47 and its mirrored right half at x
440 // 64, keeping the brighter pixel. The pillar (17x64) cycles through four
441 // images, two frames each; the glow at its foot (24x43) through three,
442 // four frames each.
443 if (frame <= 55) {
444 s32 n;
445 u8 *glow;
446
447 i = frame / 2;
448 n = i % 4;
452 draw[1](canvas, work->sheet + n * (17 * 64), 47, ground.y - 64, 17, 64);
453 n = frame / 4 % 3;
454 glow = work->sheet + n * 1032 + 0x1100;
455 draw[1](canvas, glow, 40, ground.y - 36, 24, 43);
460 n = i % 4;
461 draw[1](canvas, work->sheet + n * (17 * 64), 64, ground.y - 64, 17, 64);
462 draw[1](canvas, glow, 64, ground.y - 36, 24, 43);
464 }
465 // A lookup with no side effect whose result is dropped; the ROM keeps
466 // the call.
469
470 // The first 32 motes, each starting i frames in: each frame a mote
471 // turns 0x400 (about 5.6 degrees), rises 5 pixels and moves 4 pixels
472 // further out. The other 96 are placed but never drawn.
473 for (i = 0; i != 32; i++) {
474 struct EffectStep *fleck = &PARTICLES[i];
475
476 if (fleck->variant >= 0) {
477 s32 size;
478
479 point[0] = fleck->z * Trig_Sin(fleck->x) >> 4;
480 point[2] = -(fleck->z * Trig_Cos(fleck->x) >> 4);
481 point[1] = fleck->y;
482 fleck->x += 0x400;
483 fleck->y += 5 << 16;
484 fleck->z += 64;
485 EffectPosition_ProjectPoint(point, &screenPosition);
486 screenPosition.x /= 2;
487 size = (i & 1) + work->effect->variant;
488 EFFECT_DRAW_FLARE(draw[0], canvas, sheet, screenPosition.x,
489 screenPosition.y, size);
490 }
491 fleck->variant++;
492 }
493 EFFECT_END_FRAME(work);
494 }
495
496 // Finish: the blitter, the callback and the layer, then the three slots
497 // in the reverse of the order they were taken.
504 /* FAKEMATCH: cancelling frame updates preserve the allocation lifetimes;
505 * without them, 18 of 420 instructions differ in tbs-en. */
506 frame ^= 1;
507 frame ^= 1;
508}
509
510/// Sets the pixel at (x, y) of the 256x120 8bpp tile picture in
511/// Ram_MapCellBuffer (32 tiles across) to colour 2.
512#define SHATTERING_OPENING_PLOT_PIXEL(x, y) \
513 (*(Ram_MapCellBuffer + ((x) & 7) + (x) / 8 * 64 + ((y) & 7) * 8 + \
514 (y) / 8 * 2048) = 2)
515
516/// Plots the four corners (x1 or x2, y1 or y2): one point of the circle
517/// mirrored into four octants.
518#define SHATTERING_OPENING_PLOT_CORNERS(x1, x2, y1, y2) \
519 (SHATTERING_OPENING_PLOT_PIXEL(x2, y2), \
520 SHATTERING_OPENING_PLOT_PIXEL(x2, y1), \
521 SHATTERING_OPENING_PLOT_PIXEL(x1, y2), \
522 SHATTERING_OPENING_PLOT_PIXEL(x1, y1))
523
524#define SHATTERING_OPENING_FRAMES 128
525#define SHATTERING_OPENING_FLASHES 32 ///< flashes thrown as the picture breaks
526#define SHATTERING_OPENING_PIECES 33 ///< pieces the picture breaks into
527#define SHATTERING_OPENING_DISC_X 96 ///< the centre of the opening disc
528#define SHATTERING_OPENING_DISC_Y 60 ///< the centre of the opening disc
529
530/// The shattering opening of the battle on the Venus aerie storm backdrop:
531/// the screen turns white and a grey disc grows from (96, 60) by 32 pixels a
532/// frame while the TileAnimationMask picture breaks into 33 pieces that fly
533/// apart and fall; background palettes 6 to 13 then ease from white back to
534/// the battle backdrop's colours, and from frame 51 32 flashes rise. Runs
535/// for 128 frames.
536///
537/// Called through BattleFx_RunShatteringOpeningFar by
538/// BattlePres_RunEntryTransition, as a battle opens. Allocates and frees its
539/// own work, canvas and sheet slots; sets up BG2 as the canvas itself, as
540/// BattleFx_BeginCanvasLayer would; draws the disc in Ram_MapCellBuffer and
541/// copies it over 0x7800 bytes of BG character block 2; writes background
542/// colours 1 to 63 and palettes 6 to 13; reloads the battle backdrop on BG1 on
543/// frame 5, and on its way out restores gBgScroll[1], starts the battle's
544/// palette fade (mode 2) and queues a DISPCNT without BG1.
545///
546/// effect : only effect->actors[0], the unit that flashes, is read.
548 /* FAKEMATCH: never read: the native frame keeps 12 unused bytes at
549 * sp+44..55, this struct's size; without it, 4 instructions differ in
550 * tbs-en. */
551 UNUSED struct EffectPosition position;
552 struct BattleEffectWork *work;
553 void *canvas;
554 s32 frame;
555 BlitterPair draw;
556 struct BattleWork *battle;
557 struct BattleBackgroundView *view;
558 void **slots;
559 void **slotTable;
560 s32 targetRadius;
561 struct EffectStep *piece;
562 s32 radius;
563 s32 i;
564 s32 octantX;
565 s32 j;
566 s32 k;
567 s32 error;
568 s32 octantY;
569 s32 x1;
570 s32 size;
571 s32 leftX;
572 s32 innerLeftX;
573 s32 y1;
574 s32 x2;
575 s32 y2;
576 u8 *startY;
577 u8 *startX;
578 s32 centreX;
579 s32 centreY;
580
582 size = CANVAS_BYTES;
585 slots = gWorkSlot + HEAP_SLOT_BATTLE;
586 battle = slots[0];
588 work->effect = effect;
589
590 // Setup. Make BG2 the 128x128 canvas, as BattleFx_BeginCanvasLayer does
591 // but without its waits: twice the width, 16 lines down, inside both
592 // windows.
594 view->secondMode = 1;
595 gBgScroll[1].y = 32;
600 view->secondMode = 0;
606
607 // BG2's affine map, at 0x06003800 (screen block 7), shows tiles 0 to 255
608 // in order, so the canvas appears as one picture; each halfword holds two
609 // one-byte tile numbers.
610 i = 0;
611 for (k = 0; k != 16; k++) {
612 for (j = 0; j != 8; j++, i += 2) {
613 s16 entry;
614
615 entry = ((k * 16 + j * 2 + 1) << 8) | ((k * 8 + j) * 2);
616 *(volatile s16 *)(0x06003800 + i) = entry;
617 }
618 }
619
620 Iwram_ClearWords(canvas, size);
621 Iwram_ClearWords((void *)BG_CHAR_BLOCK(1), size);
623 REG_BLDALPHA = BLEND_ALPHA(16, 16);
624 REG_BLDCNT = 0;
626 work->imageStorage, 1, 1);
627 // Redraw from blank each frame.
631 slotTable = gWorkSlot;
632 draw[0] = slotTable[HEAP_SLOT_BLITTER];
635 draw[1] = slotTable[HEAP_SLOT_BLITTER_ALTERNATE];
636
637 // Each piece flies out from (32, 60) at a quarter of its distance from
638 // there a frame, in work->particles 0 to 32.
641 radius = 0;
642 piece = work->particles;
643 for (i = 0; i != SHATTERING_OPENING_PIECES; i++) {
644 s32 x, y, vx, vy;
645
646 x = *startX++ << 16;
647 y = *startY++ << 16;
648 piece->x = x;
649 piece->y = y;
650 vx = (x - 0x200000) >> 2;
651 vy = (y - 0x3c0000) >> 2;
652 piece->velocityX = vx;
653 piece->velocityY = vy;
654 piece++;
655 }
656
657 // The disc's mask in Ram_MapCellBuffer starts as colour 1 everywhere (the
658 // copy of the screen into it is overwritten at once), and background
659 // palettes 6 to 13 turn white. BG1's scroll is saved and the battle's
660 // background view marked busy while the backdrop is replaced.
662 Iwram_FillWords(Ram_MapCellBuffer, 0x7800, 0x01010101);
663 view->busy = 1;
664 work->savedBg1X = gBgScroll[1].x;
665 work->savedBg1Y = gBgScroll[1].y;
666 gBgScroll[1].x = 0;
670 0x20000);
671 Iwram_FillWords((void *)&BG_PLTT_COLOR(6, 0), 0x100, 0x7fff7fff);
674 30);
675
676 for (frame = 0; frame != SHATTERING_OPENING_FRAMES; frame++) {
677 // Frame loop. The cues: the shatter sound three times by frame 3, the
678 // unit's flash ending on frame 28, and two more sounds on 5 and 32.
679 if (frame == 2)
681 if (frame == 3)
683 if (frame == 28)
684 ObjectGroup_UpdateMembers(work->effect->actors[0], -1, 3, -1, 0);
685 if (frame == 32)
687 if (frame == 5)
689 // Frame 5: bring the battle backdrop back on BG1.
690 if (frame == 5) {
691 gBgScroll[1].x = work->savedBg1X;
692 BattleBackground_LoadFar(1, battle->background, -1);
693 }
694
695 // From frame 8, move every colour of palettes 6 to 13 one step towards
696 // the battle backdrop's colour; from white, 31 frames bring every
697 // channel home.
698 if (frame > 7) {
699 u16 *color;
700
701 color = (u16 *)&BG_PLTT_COLOR(6, 0);
702 for (i = 0; i != 128; i++) {
703 s32 red = *color & 0x1f;
704 s32 green = (*color >> 5) & 0x1f;
705 s32 blue = (*color >> 10) & 0x1f;
706 s32 goalRed = battle->palette[i] & 0x1f;
707 s32 goalGreen = (battle->palette[i] >> 5) & 0x1f;
708 s32 goalBlue = (battle->palette[i] >> 10) & 0x1f;
709
710 if (red < goalRed)
711 red++;
712 else if (red > goalRed)
713 red--;
714 if (green < goalGreen)
715 green++;
716 else if (green > goalGreen)
717 green--;
718 if (blue < goalBlue)
719 blue++;
720 else if (blue > goalBlue)
721 blue--;
722 *color++ = RGB(red, green, blue);
723 }
724 }
725
726 // Frame 4: the whole screen turns the disc's grey.
727 if (frame == 4)
728 Iwram_FillWords((void *)BG_CHAR_BLOCK(2), 0x7800, 0x02020202);
729
730 // Frames 0 to 3: grow the disc in the mask by 32 pixels of radius,
731 // brighten its grey (colour 2), and copy the mask to the screen.
732 if (frame <= 3) {
733 s32 v;
734
735 v = frame * 4 + 8;
736 targetRadius = frame * 32;
737 BG_PLTT[2] = RGB(v, v, v);
740 for (; radius != targetRadius; radius++) {
741 // The midpoint circle algorithm: one point plots all eight
742 // octants, and each is drawn twice, one pixel apart, to fill gaps.
743 // Points are clamped to the 256x120 picture; the second copy's x2
744 // is measured from SHATTERING_OPENING_DISC_X, centreX's value.
745 octantX = radius;
746 octantY = 0;
747 error = radius;
748 while (octantX >= octantY) {
749 x2 = octantX + centreX;
750 x1 = centreX - octantX;
751 leftX = x1;
752 y1 = centreY - octantY;
753 y2 = octantY + centreY;
754 if (y1 < 0)
755 y1 = 0;
756 if (y2 > 119)
757 y2 = 119;
758 if (x1 < 0)
759 x1 = 0;
760 if (x2 > 255)
761 x2 = 255;
762 SHATTERING_OPENING_PLOT_CORNERS(x1, x2, y1, y2);
763 x1 = leftX + 1;
764 x2 = octantX + SHATTERING_OPENING_DISC_X + 1;
765 if (x1 < 0)
766 x1 = 0;
767 if (x2 > 255)
768 x2 = 255;
769 SHATTERING_OPENING_PLOT_CORNERS(x1, x2, y1, y2);
770
771 x2 = octantY + centreX;
772 x1 = centreX - octantY;
773 innerLeftX = x1;
774 y2 = octantX + centreY;
775 y1 = centreY - octantX;
776 if (x1 < 0)
777 x1 = 0;
778 if (x2 > 255)
779 x2 = 255;
780 if (y1 < 0)
781 y1 = 0;
782 if (y2 > 119)
783 y2 = 119;
784 SHATTERING_OPENING_PLOT_CORNERS(x1, x2, y1, y2);
785 x1 = innerLeftX + 1;
786 x2 = octantY + SHATTERING_OPENING_DISC_X + 1;
787 if (x1 < 0)
788 x1 = 0;
789 if (x2 > 255)
790 x2 = 255;
791 SHATTERING_OPENING_PLOT_CORNERS(x1, x2, y1, y2);
792
793 error -= octantY * 2 + 1;
794 if (error < 0) {
795 error += octantX * 2 - 2;
796 octantX--;
797 }
798 octantY++;
799 }
800 }
802 }
803
804 // Draw the pieces up to frame 50; they start to fly and fall on frame
805 // 4, undamped, under a gravity of a quarter pixel a frame.
806 if (frame <= 50) {
807 for (i = 0; i != SHATTERING_OPENING_PIECES; i++) {
808 piece = &work->particles[i];
809 draw[0](canvas, work->imageStorage + gDeathPlunge_PieceCells[i],
810 Q_16_16_TO_INT(piece->x), Q_16_16_TO_INT(piece->y),
812 if (frame > 3)
813 EffectStep_AdvanceWithGravity2D(piece, 64, 0x4000);
814 }
815 }
816
817 // Frames 8 to 50: colour 1 goes from black to white, one step a frame,
818 // and is white from frame 39.
819 if (frame >= 8 && frame <= 50) {
820 s32 v;
821
822 v = frame - 8;
823 if (v > 31)
824 v = 31;
825 BG_PLTT[1] = RGB(v, v, v);
826 }
827
828 // Frame 51: load the flash images and a violet ramp into colours 1 to
829 // 63, turn blending on, and place 32 flashes at random in x 32 to 63, y
830 // 80 to 111, reusing the pieces' particles.
831 if (frame == 51) {
833 1, 0);
834 for (i = 1; i != 64; i++) {
835 s32 v;
836
837 v = i / 2;
838 if (v < 0)
839 v = 0;
840 BG_PLTT[i] = RGB(v, v / 2, v);
841 }
843 for (i = 0; i != SHATTERING_OPENING_FLASHES; i++) {
844 piece = &work->particles[i];
845 piece->x = ((Random16() & 31) + 32) << 16;
846 piece->y = ((Random16() & 31) + 80) << 16;
847 piece->velocityX = ((Random16() & 0x1ff) - 0x100) << 12;
848 piece->velocityY = 0;
849 piece->variant = 0;
850 }
851 // Trails keep half a frame.
853 work->transferValue = 50;
854 }
855
856 // Flashes: flash i appears at frame 52 + i / 4 and rises, changing
857 // image every 4 frames, for 40 frames.
858 if (frame > 52) {
859 for (i = 0; i != SHATTERING_OPENING_FLASHES; i++) {
860 piece = &work->particles[i];
861 if (frame >= i / 4 + 52 && piece->variant <= 39) {
862 s32 cell;
863
864 cell = piece->variant / 4;
865 if (cell > 5)
866 cell = 5;
867 draw[1](canvas, work->sheet + (cell << 11),
868 Q_16_16_TO_INT(piece->x) - 16, Q_16_16_TO_INT(piece->y) - 32,
869 32, 64);
870 EffectStep_AdvanceWithGravity2D(piece, 60, -0x1000);
871 piece->variant++;
872 }
873 }
874 }
875
876 EFFECT_END_FRAME(work);
877 }
878
879 // Finish: restore the unit, BG1's scroll and the backdrop's palette fade,
880 // then free the slots in the reverse of the order they were taken.
884 gBgScroll[1].x = work->savedBg1X;
885 gBgScroll[1].y = 32;
887 WaitFrames(1);
892 0x20000);
896}
897
898/// One streak of light of the element streak burst, laid over the same
899/// 28-byte records as PARTICLES: a line along a randomly turned axis from
900/// tail to head, in distance from the centre.
901struct Streak {
902 s32 head; ///< the head's distance from the centre, 48 to 63 at first
903 s32 tail; ///< the tail's distance, 8 less; both close in 4 a frame
904 s32 unused08; ///< the EffectStep's z, which the streaks leave alone
905 s32 pitch; ///< the axis's turn, a random 16-bit angle
906 s32 yaw; ///< the axis's turn, a random 16-bit angle
907 s32 roll; ///< the axis's turn, a random 16-bit angle
908 s32 unused18; ///< the EffectStep's variant, which the streaks leave alone
909};
910
911/// The burst of an element over a unit, for 56 frames: sparks flare at the
912/// four corners around the unit, motes spiral in, and from frame 28 a burst
913/// of light plays over the unit while the first target flashes.
914///
915/// Called through BattleFx_RunElementBurstFar by
916/// BattleFx_PlayUnitElementEffect (its mode 3). Allocates and frees its own
917/// work, canvas and sheet slots; loads the element's colours over the first
918/// 64 of the background palette, fills PARTICLES 0 to 127 and
919/// work->particles, and moves BG2X with the unit.
920///
921/// effect->kind : the element, which picks the palette: 0 Venus yellow,
922/// 1 Mercury blue, 2 Mars red, others Jupiter violet.
924 struct EffectPosition ground;
925 struct BattleEffectWork *work;
926 void *canvas;
927 BlitterPair draw;
928 u8 *sheet;
929 void *palette;
930 s32 frame;
931 s32 i;
932
936 work->effect = effect;
938 // Setup, as for the element pillar: the backdrop darkens for 24 frames,
939 // and the narrow canvas goes 12/16 over all of the background.
940 work->fadeFrames = 24;
941 work->fadeStep = 0;
942 REG_BLDALPHA = BLEND_ALPHA(12, 16);
943 REG_BG2PA = Q_8_8(1);
945 0);
947 switch (work->effect->kind) {
948 case 0:
950 break;
951 case 1:
953 break;
954 case 2:
956 break;
957 default:
959 break;
960 }
961 {
962 Iwram_CopyWords((void *)BG_PLTT, palette, 128);
963 }
964
965 // PARTICLES are set up as for the element pillar but never drawn here.
966 // The motes that are drawn, work->particles, start 16 to 47 pixels out
967 // (y) at a random angle (x) and close in 2 pixels a frame for 16 to 31
968 // frames (variant).
969 for (i = 0; i != 128; i++) {
970 PARTICLES[i].y = 0x800000;
971 PARTICLES[i].x = Random16() & 0xffff;
972 PARTICLES[i].z = (Random16() & 0x1ff) + 0x400;
973 PARTICLES[i].variant = -i;
974 }
975 for (i = 0; i != 64; i++) {
976 work->particles[i].x = Random16() & 0xffff;
977 work->particles[i].y = (Random16() & 31) + 16;
978 work->particles[i].variant = (i & 15) + 16;
979 }
980 // Trails keep 3/4 a frame.
986
987 for (frame = 0; frame != 56; frame++) {
988 // Frame loop. Follow the unit, fade out over the last 6 frames, and on
989 // frame 26 flash the first target for 20 frames.
991 REG_BG2X = (64 - ground.x) << 8;
992 if (frame > 49)
993 REG_BLDALPHA = BLEND_ALPHA(0x70 - frame * 2, 16);
994 if (frame == 26) {
997 0, 20);
998 }
999 // Frames 28 to 48: the burst of light (48x48), seven images, three
1000 // frames each.
1001 if (frame >= 28 && frame <= 48)
1002 draw[0](canvas, work->sheet + (frame - 28) / 3 * (48 * 48) + 0x1400, 40,
1003 ground.y - 24, 48, 48);
1004 // Frames 0 to 14: a spark (32x32) at each corner, flipped to face
1005 // outwards (gDeathPlunge_DrawFlags), five images, three frames each; a
1006 // blitter is built for each corner and freed at once.
1007 if (frame >= 0 && frame <= 14) {
1008 s32 picture = frame / 3 % 5;
1009 DrawRectangle *slot =
1011
1012 for (i = 0; i != 4; i++) {
1016 draw[1] = *slot;
1017 draw[1](canvas, work->sheet + (picture << 10), gDeathPlunge_X[i] + 32,
1018 ground.y + gDeathPlunge_Y[i] - 32, 32, 32);
1020 }
1021 }
1022 // The motes, shrinking as they close in.
1023 if (frame >= 0) {
1024 for (i = 0; i != 64; i++) {
1025 struct EffectStep *mote = &work->particles[i];
1026
1027 if (mote->variant >= 0 && mote->y > 0) {
1028 s32 size = (mote->variant >> 3) + 1;
1029 s32 x = (mote->y * Trig_Sin(mote->x) >> 16) + 64;
1030 s32 y = (mote->y * Trig_Cos(mote->x) >> 16) + ground.y;
1031
1032 if (size <= 0)
1033 size = 1;
1034 EFFECT_DRAW_FLARE(draw[0], canvas, sheet, x, y, size);
1035 mote->y -= 2;
1036 mote->variant--;
1037 }
1038 }
1039 }
1040 EFFECT_END_FRAME(work);
1041 }
1042
1043 // Finish, as for the element pillar.
1050}
1051
1052/// Draws a frame of the element streak burst: on its first frame seeds 256
1053/// streaks with random axes, then each frame draws the first 64 (streak i
1054/// from frame i / 4) as lines three pixels thick that shrink 4 pixels a
1055/// frame towards the centre of the canvas, a little below its middle.
1056///
1057/// Runs each frame as a scheduler callback added by
1058/// BattleFx_StartElementStreaks and removed by BattleFx_EndElementStreaks.
1059/// Counts work->frame, keeps the streaks in Ram_MapCellBuffer, draws into
1060/// the canvas through BattleFx_DrawClippedCanvasLine, resets the render
1061/// transform and sets work->transferPending.
1064 s32 frame;
1065 s32 i;
1066 struct Streak *streak;
1067 struct Vector3 point;
1068 struct EffectPosition head;
1069 struct EffectPosition tail;
1070
1071 frame = (work->frame)++;
1072 if (frame == 0) {
1073 for (i = 0; i != 256; i++) {
1074 struct Streak *seed = &((struct Streak *)Ram_MapCellBuffer)[i];
1075 s32 r = Random16() & 15;
1076
1077 seed->head = r + 48;
1078 seed->tail = r + 40;
1079 seed->pitch = Random16() & 0xffff;
1080 seed->yaw = Random16() & 0xffff;
1081 seed->roll = Random16() & 0xffff;
1082 }
1083 }
1084 point.y = 0;
1085 point.z = 0;
1086 i = 0;
1087 for (; i != 64; i++) {
1088 streak = &((struct Streak *)Ram_MapCellBuffer)[i];
1089 if (frame > i / 4 && streak->head > 0) {
1090 s32 fade;
1091
1096 point.x = streak->head;
1098 head.x += 64;
1099 head.y += 80;
1100 point.x = streak->tail;
1102 tail.x += 64;
1103 tail.y += 80;
1104 streak->tail -= 4;
1105 streak->head -= 4;
1106 if (streak->tail < 0)
1107 streak->tail = 0;
1108 // The tail stops at the centre, and the head goes out once it
1109 // passes it. The colour level is 48 (the outer two lines) or 56
1110 // (the middle one) less half the tail's distance, so a line
1111 // brightens as its tail closes in.
1112 fade = -streak->tail / 2;
1114 fade + 48);
1116 fade + 48);
1117 BattleFx_DrawClippedCanvasLine(tail.x, tail.y, head.x, head.y, fade + 56);
1118 }
1119 }
1120 work->transferPending = 1;
1121}
1122
1123/// Starts the element streak burst and returns at once: opens the canvas and
1124/// schedules BattleFx_DrawStreaks with a canvas that darkens each frame.
1125///
1126/// Called through BattleFx_StartElementStreaksFar by
1127/// BattleFx_PlayUnitElementEffect (its mode 1), which keeps the canvas on
1128/// its unit and ends the burst with BattleFx_EndElementStreaks. Allocates
1129/// the work and canvas slots, which the end frees; loads the element's
1130/// colours over the first 64 of the background palette; adds
1131/// BattleFx_DrawStreaks and the canvas transfer to the scheduler, beside the
1132/// backdrop fade BattleFx_BeginCanvasLayer adds.
1133///
1134/// element: the element, which picks the palette: 0 Venus yellow, 1 Mercury
1135/// blue, 2 Mars red, 3 Jupiter violet, others a dusty grey.
1137 struct BattleEffectWork *work;
1138 void *palette;
1139 s32 id;
1140
1144 work->fadeFrames = 24;
1145 REG_BG2PA = Q_8_8(1);
1146 REG_BLDALPHA = BLEND_ALPHA(16, 16);
1147 switch (element) {
1148 case 0:
1150 break;
1151 case 1:
1153 break;
1154 case 2:
1156 break;
1157 case 3:
1159 break;
1160 case 4:
1161 default:
1163 break;
1164 }
1165 palette = Resource_GetTableEntry(id);
1166 Iwram_CopyWords((void *)BG_PLTT, palette, 128);
1167 work->frame = 0;
1169 // 6 levels off every pixel each frame, four pixels a word.
1170 work->transferValue = 0x06060606;
1174}
1175
1176/// Ends the element streak burst that BattleFx_StartElementStreaks
1177/// started: stops its callbacks and the background palette fade, clears the
1178/// canvas in VRAM and frees the work and the canvas.
1179///
1180/// Called through BattleFx_EndElementStreaksFar by
1181/// BattleFx_PlayUnitElementEffect. Unlike BattleFx_EndCanvasLayer it leaves
1182/// BG2's settings and the backdrop's colours as they are.
1186 {
1188 }
1192}
1193
1194#undef DEATH_PLUNGE_FRAMES
1195#undef BLADE_RAIN_FRAMES
1196#undef ELEMENT_PILLAR_FRAMES
1197#undef SHATTERING_OPENING_PLOT_PIXEL
1198#undef SHATTERING_OPENING_PLOT_CORNERS
1199#undef SHATTERING_OPENING_FRAMES
1200#undef SHATTERING_OPENING_FLASHES
1201#undef SHATTERING_OPENING_PIECES
1202#undef SHATTERING_OPENING_DISC_X
1203#undef SHATTERING_OPENING_DISC_Y
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_STANDING
Definition battle.h:174
@ POSE_DAMAGE
taking damage
Definition battle.h:176
struct BattleCamera * gCameraWork
@ COMPOSITE_FLIP_X
@ COMPOSITE_ADDITIVE
@ COMPOSITE_TRANSPARENT
@ COMPOSITE_MAX
BattleEffectDrawRectangle DrawRectangle
void Palette_StepFadeTransfer(void)
Darkens the battle backdrop while the canvas is open: for fadeFrames frames, writes the backdrop's co...
Definition canvas.c:243
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_BeginCanvasLayer(s32 bgControl)
Opens the canvas layer: starts the background palette fade, makes BG2 the canvas, alpha-blended over ...
Definition canvas.c:314
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_ClearActorTimers(void)
Clears every target's flash timer (work->actorTimers).
Definition canvas.c:262
void BattleFx_DrawClippedCanvasLine(s32 x0, s32 y0, s32 x1, s32 y1, s32 color)
Draws a line on the 128x128 8bpp canvas (16 tiles across), keeping the brighter colour where it cross...
Definition canvas.c:632
#define SHATTERING_OPENING_DISC_X
the centre of the opening disc
#define SHATTERING_OPENING_PLOT_CORNERS(x1, x2, y1, y2)
Plots the four corners (x1 or x2, y1 or y2): one point of the circle mirrored into four octants.
void BattleFx_RunShatteringOpening(struct BattleEffectArgument *effect)
The shattering opening of the battle on the Venus aerie storm backdrop: the screen turns white and a ...
#define SHATTERING_OPENING_FLASHES
flashes thrown as the picture breaks
void BattleFx_DrawStreaks(void)
Draws a frame of the element streak burst: on its first frame seeds 256 streaks with random axes,...
#define SHATTERING_OPENING_DISC_Y
the centre of the opening disc
#define SHATTERING_OPENING_PIECES
pieces the picture breaks into
void BattleFx_RunDeathPlunge(struct BattleEffectArgument *effect)
The user runs 9/10 of the way to the first target, then both leap and turn upside down in the air; on...
#define ELEMENT_PILLAR_FRAMES
void BattleFx_EndElementStreaks(void)
Ends the element streak burst that BattleFx_StartElementStreaks started: stops its callbacks and the ...
#define SHATTERING_OPENING_FRAMES
void BattleFx_StartElementStreaks(s32 element)
Starts the element streak burst and returns at once: opens the canvas and schedules BattleFx_DrawStre...
#define DEATH_PLUNGE_FRAMES
UNUSED void BattleFx_RunBladeRain(struct BattleEffectArgument *effect)
Drops 16 swords, one every 4 frames, slanting in towards the first target (the middle of the canvas,...
#define BLADE_RAIN_FRAMES
void BattleFx_RunElementBurst(struct BattleEffectArgument *effect)
The burst of an element over a unit, for 56 frames: sparks flare at the four corners around the unit,...
void BattleFx_RunElementPillar(struct BattleEffectArgument *effect)
The glow of an element around a unit: a symmetrical pillar of light stands at the unit's feet while m...
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
What every part of the battle effect object shares: its includes, macros and frame-loop helpers.
#define EFFECT_RELEASE_BLITTERS()
Frees the two blitters, the alternate first.
#define EFFECT_PRESENT_FRAME(work)
Ends a frame of a canvas effect: marks the canvas ready for the transfer callback,...
#define EFFECT_DRAW_FLARE(draw, canvas, sheet, x, y, size)
Draws flare cell size of sheet, a square size pixels from its centre to each edge,...
@ CANVAS_COPY_AND_CLEAR
copy, then fill the canvas with transferValue
@ CANVAS_COPY_AND_DARKEN
copy, then darken the canvas by 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 MOTE_SET_BYTES
The bytes of one set of the ten mote cells: 2 * (1 + 4 + ... + 100).
#define EFFECT_SLOT(slots, slot)
A work slot read through a pointer to the effect's own slot, gWorkSlot[HEAP_SLOT_BATTLE_EFFECT].
#define EFFECT_FINISH_CANVAS()
The usual end of a canvas effect: stops the transfer callback before freeing what it reads,...
#define EFFECT_FINISH_CANVAS_ONE_BLITTER()
The same for an effect that drew through one blitter.
#define EFFECT_WINOUT
Outside the battle view: BG0 and blending only.
#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_START_TRANSFER(work, mode, value)
Sets the transfer, then starts copying the canvas to VRAM once a frame.
#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_DISPCNT
The battle screen's display mode while an effect plays: background mode 1 with BG0 to BG2,...
#define EFFECT_SET_BATTLE_WINDOWS()
Windows 0 and 1 both cover the battle view: the full width, lines 16 to.
#define EFFECT_PLAYBACK_ORDER
The order where the battle's own playback runs, which the palette fade and the element streaks take.
#define EFFECT_GET_SLOTS(slots, cursor, work, canvas)
Starts at the effect's entry in the whole work-slot array.
#define EFFECT_WIN0_LAYERS
Window 0, the battle view, shows BG0 to BG2, sprites and blending.
#define EFFECT_END_FRAME(work)
The usual end of an effect frame: counts down the targets' flash timers (ObjectGroup_TickMemberTimers...
#define EFFECT_VIEW_FROM_CAMERA(camera)
Starts a frame's 3D projection from the battle camera: resets the transform, then looks from camera->...
#define EFFECT_BEGIN_NARROW_CANVAS(bgControl)
Opens the canvas layer at the canvas's own width, one texel per pixel, where BattleFx_BeginCanvasLaye...
#define EFFECT_SET_CANVAS_AFFINE()
BG2 shows the canvas from screen line 16 down (BG2Y is -16.0), stretched to twice its width: the 128x...
u8 gDeathPlunge_PieceStartY[]
u8 gDeathPlunge_DrawFlags[]
u16 gDeathPlunge_Cells[]
u8 gDeathPlunge_CellHeights[]
s8 gDeathPlunge_X[]
u8 gDeathPlunge_PieceStartX[]
u16 gDeathPlunge_PieceCells[]
u8 gDeathPlunge_PieceHeights[]
u8 gDeathPlunge_PieceWidths[]
The 33 pieces of the TileAnimationMask picture: where each starts on the canvas, its size,...
s8 gDeathPlunge_Y[]
u8 gDeathPlunge_CellWidths[]
struct BattleObj * GetBattleObjectSlotFar(s32 objectId)
Far call to BattleObjGet.
void BattlePres_SetupTransitionSceneFar(s32 x, s32 depth, s32 y, s32 zoom)
s32 BattleUnit_GetEffectHeightFar(s32 id)
void BattleBackground_LoadFar(s32 mode, s32 resource, s32 level)
void BattlePresentation_ConfigurePaletteFadeFar(s32 mode, s32 value, s32 fade)
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void Object_SetMoveTargetFar(struct ObjectRuntime *object, s32 x, s32 y, s32 z)
void ObjectDispatch_StartIdleFar(struct DispatchObject *obj)
void AudioCommand_PlayFar(s32 id)
s32 Trig_Cos(s32 angle)
s32 Trig_Sin(s32 angle)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
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
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
Definition heap.c:47
@ 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
Definition heap_state.h:37
@ HEAP_SLOT_BATTLE_CANVAS
Definition heap_state.h:43
#define WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
Definition heap_state.h:14
#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 REG_WININ
Definition io_reg.h:81
#define BGCNT_256_COLORS
Definition io_reg.h:27
#define BGCNT_PRIORITY(n)
Definition io_reg.h:24
#define RGB(r, g, b)
A 15-bit colour from its red, green and blue levels (0 to 31 each), as the palette stores it: blue in...
Definition io_reg.h:164
#define BLDCNT_TGT1_BG2
Definition io_reg.h:125
#define BG_CHAR_BLOCK(n)
Definition io_reg.h:166
#define WININ_WIN1_BG0
Definition io_reg.h:93
#define WININ_WIN1_CLR
Definition io_reg.h:98
@ DISPCNT_OBJ_ON
Definition io_reg.h:44
@ DISPCNT_WIN0_ON
Definition io_reg.h:45
@ DISPCNT_BG0_ON
Definition io_reg.h:40
@ DISPCNT_OBJ_1D_MAP
Definition io_reg.h:39
@ DISPCNT_MODE_1
BG0 and BG1 text, BG2 affine.
Definition io_reg.h:37
@ DISPCNT_WIN1_ON
Definition io_reg.h:46
@ DISPCNT_BG2_ON
Definition io_reg.h:42
#define REG_BG2X
Definition io_reg.h:65
#define REG_DISPCNT
Definition io_reg.h:9
#define BLDCNT_EFFECT_BLEND
weighted by REG_BLDALPHA
Definition io_reg.h:131
#define BLDCNT_TGT2_ALL
Definition io_reg.h:140
#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 REG_WINOUT
Definition io_reg.h:82
#define BG_PLTT
Definition io_reg.h:157
#define WININ_WIN1_OBJ
Definition io_reg.h:97
#define REG_BG2PA
Definition io_reg.h:61
#define REG_BLDCNT
Definition io_reg.h:119
#define REG_BG1CNT
Definition io_reg.h:20
#define BG_PLTT_COLOR(palette, color)
Definition io_reg.h:158
#define WININ_WIN1_BG2
Definition io_reg.h:95
#define IO_WRITE_QUEUE_PUSH(address, value, control)
Disables interrupts to add one register write or DMA to the queue; a write to a full queue is dropped...
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
static s32 Iwram_ClearWords(void *destination, s32 size)
Definition iwram_call.h:55
#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
struct BgScroll gBgScroll[]
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 EffectPosition_ProjectBattler(s32 id, struct EffectPosition *position)
The screen position of a battler, 16 pixels higher.
Definition positions.c:100
void EffectPosition_ProjectScaledBattler(s32 id, struct EffectPosition *position)
The screen position of a battler, scaled for the battle view, 16 pixels higher.
Definition positions.c:88
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
#define Ram_MapCellBuffer
Definition ram_buffer.h:10
char ResourceId_RedPaletteA
char ResourceId_CyanSparkSheet
char ResourceId_VioletPaletteD
char ResourceId_CrystalSheet
char ResourceId_SwordSlashSheet
char ResourceId_ParticleSpritesD
char ResourceId_YellowPaletteA
char ResourceId_DustPuffSheet
char ResourceId_TileAnimationMask
char ResourceId_YellowPaletteB
char ResourceId_VioletPaletteA
char ResourceId_IceTileSheet
char ResourceId_FlashBurstSheet
char ResourceId_EmberStreakSheet
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_133
Definition songs.h:126
#define SE_136
Definition songs.h:129
#define SE_212
Definition songs.h:207
#define SE_HEAVY_IMPACT
Definition songs.h:127
#define SE_140
Definition songs.h:133
#define SE_145
Definition songs.h:138
#define SE_149
Definition songs.h:142
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
s32 secondMode
1 also sets BG1's scroll; one effect sets it
The battle camera: its eye, the focus it turns about, and its pitch, yaw and distance.
The command shared by an effect's caller, dispatcher and handlers.
s32 actor
the user's unit id
s32 kind
handler table index; 200 more for a critical hit
s16 actors[8]
the targets' unit ids, count of them
s32 variant
the ability's size, from 0 (Quake, then Earthquake)
The running battle effect's work: its canvas image, 64 particles, the display registers it stages and...
s32 fadeFrames
backdrop fade frames left (Palette_StepFadeTransfer)
s32 frame
frame counter some effects keep, from 0
s32 savedBg1Y
BG1 scroll restored when a shake ends.
s32 savedBg1X
BG1 scroll restored when a shake ends.
s32 transferPending
1 once the effect has drawn a frame (EFFECT_PRESENT_FRAME); the canvas transfer callback copies the c...
s32 fadeStep
CANVAS_FADE_STEPs the backdrop has darkened so far.
s32 shakeFrames
shake frames left; Camera_ApplyShake counts down
s32 transferMode
How the canvas transfer callbacks treat the canvas after each copy (enum CanvasTransferMode in effect...
s32 transferValue
The transfer mode's argument: the fill value, the share kept (50 or 75 percent) or the darken or brig...
struct BattleEffectArgument * effect
the command being run
struct EffectStep particles[64]
free while variant is -1
A unit's place on the battlefield: its sprite object, resources and animations, its anchor spot and s...
struct MotionObject * object
NULL once released.
The battle's own work: its enemies, units and their objects, the turn's actions, the spoils,...
Definition battle_work.h:71
u16 background
the battle background's id
u16 palette[128]
the backdrop's colours, before scaling
u16 y
pixels
Definition map_scroll.h:65
A field object as the object dispatcher's far calls take it.
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 z
16.16 fixed-point pixels
Definition effect_step.h:26
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
An effect object that moves and draws one sprite: its position, scale, velocity and target,...
Definition motobj.h:20
s32 speedLimit
16.16 fixed-point pixels per frame
Definition motobj.h:34
s32 z
16.16 fixed-point pixels
Definition motobj.h:25
u8 snapToTarget
nonzero: lands exactly on the target, else brakes in
Definition motobj.h:57
s32 y
16.16 fixed-point pixels
Definition motobj.h:24
s32 velocityY
16.16 fixed-point pixels per frame
Definition motobj.h:32
s32 acceleration
Horizontal speed gained each frame towards the target, or lost braking without one,...
Definition motobj.h:37
s32 scaleY
16.16 fixed point, 0x10000 full size
Definition motobj.h:28
s32 x
16.16 fixed-point pixels
Definition motobj.h:23
s32 verticalMotionStrength
Gravity: taken from velocityY each frame above the ground with motionFlags bit 1, in 16....
Definition motobj.h:48
u8 autoFaceMotion
bit 0 turns the object to face where it moves
Definition motobj.h:59
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
One streak of light of the element streak burst, laid over the same 28-byte records as PARTICLES: a l...
s32 tail
the tail's distance, 8 less; both close in 4 a frame
s32 yaw
the axis's turn, a random 16-bit angle
s32 unused08
the EffectStep's z, which the streaks leave alone
s32 unused18
the EffectStep's variant, which the streaks leave alone
s32 head
the head's distance from the centre, 48 to 63 at first
s32 pitch
the axis's turn, a random 16-bit angle
s32 roll
the axis's turn, a random 16-bit angle
Three coordinates, x, y and z: a position, a velocity or a direction.
Definition vector3.h:11
s32 z
Definition vector3.h:24
s32 x
Definition vector3.h:22
s32 y
Definition vector3.h:23
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
Definition system.c:150
void SceneTransform_ApplyYaw(s32 angle)
Rotates gTransform about the Y axis by angle.
Definition transform.c:113
void SceneTransform_ApplyPitch(s32 angle)
Rotates gTransform about the X axis by angle.
Definition transform.c:97
void Render_ResetTransformState(void)
Allocates the one-level save area (heap slot HEAP_SLOT_TRANSFORM_STACK), clears gTransformStackDepth ...
Definition transform.c:19
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
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
#define EFFECT_CLIP_BOUNDS
Clips overflow on all four sides.
Definition effect.h:224
#define Q_16_16_TO_INT(v)
Definition effect.h:231
#define PARTICLES
The map cell buffer (gMapCellBuffer), which the effects borrow, has two views here: Ram_MapCellBuffer...
Definition effect.h:221
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