10#define JUDGMENT_SHEET_BYTES 0x2710
25#define JUDGMENT_SPARKS (&PARTICLES[128])
27#define JUDGMENT_GATHER_FRAMES 160
28#define JUDGMENT_SWEEP_FRAMES 320
29#define JUDGMENT_SHEET_FLARE_B 0x4240
30#define JUDGMENT_FORMATION_OBJECTS 16
31#define JUDGMENT_DEBRIS_OBJECTS 16
32#define JUDGMENT_SHEET_BURST 0x600
35#define JUDGMENT_SHEET_TORNADO 0x95c
38#define JUDGMENT_SHEET_EXPLOSION 0x4000
40#define JUDGMENT_SHEET_FLARE_A 0x4000
42#define JUDGMENT_SHEET_FLASH_SMALL 0x6000
44#define JUDGMENT_SHEET_FLASH_LARGE 0x6110
46#define JUDGMENT_SHEET_FLASH_STREAK 0x64e8
47#define JUDGMENT_EXPLOSION_CELL_BYTES 1728
48#define JUDGMENT_WAVE_SIZE 120
50#define JUDGMENT_DMA_FILL_CANVAS DMA_FILL_WORDS(0x1000)
52#define JUDGMENT_DMA_FILL_WAVE DMA_FILL_WORDS(0xe10)
64 static struct SpriteScale unitScale = {{{0x10000, 0x10000}}};
132 minimumDepth = 0xffff;
145 for (i = 0; i != 8; i++) {
158 for (i = 0; i != 128; i++) {
167 for (i = 0; i != 128; i++) {
210 for (i = 0; i != 128; i++) {
216 projectedPosition.
x >>= 1;
217 projectedPosition.
y -= 120;
218 if (projectedPosition.
depth < 100) {
219 projectedPosition.
depth = 100;
221 if (projectedPosition.
depth > 900) {
222 projectedPosition.
depth = 900;
224 z = projectedPosition.
depth - 100;
225 projectedPosition.
depth = z;
226 size = (z / 100) + 1;
227 if (minimumDepth > z) {
230 if (maximumDepth < z) {
234 projectedPosition.
y, size);
256 for (i = 0; i != 64; i++) {
257 if (frame > i / 4 + 80 &&
PARTICLES[i].x > 0) {
270 if (projectedPosition.
depth < -60) {
271 projectedPosition.
depth = -60;
273 if (projectedPosition.
depth > 60) {
274 projectedPosition.
depth = 60;
276 projectedPosition.
depth += 60;
277 size = projectedPosition.
depth / 20 + 2;
278 projectedPosition.
x += 60;
279 projectedPosition.
y += 80;
281 projectedPosition.
y, size);
293 place.
x = ((i % 4) << 21) + (152 << 15);
294 place.
y = ((i / 4) << 21) + depth;
303 zoom = zoom * 60 / 64;
326 if (frame >= 116 && frame < 144) {
329 s32 n = (frame - 116) / 4;
341 canvas, work->sheet + cell, 60 - high, 80 - high * 2, high, high * 2);
346 canvas, work->sheet + cell, 60, 80 - high * 2, high, high * 2);
351 canvas, work->sheet + cell, 60 - high, 80, high, high * 2);
358 canvas, work->sheet + cell, 60, 80, high, high * 2);
361 for (i = 0; i != 6; i++) {
376 s32 top = (frame << 4) - 2272;
391 n = (frame - 144) / 2;
392 r = frame * 10 - 1424;
405 for (i = 0; i != 128; i++) {
409 blit(canvas, work->sheet + cell, x + 60, y + 72, high, high * 2);
450 }
else if (*c != 0) {
511 if (frame >= 5 && frame < 150) {
518 }
else if (frame >= 155 && frame < 214) {
520 }
else if (frame >= 219 && frame < 280) {
543 for (i = 0; i != 128; i++, pal++) {
586 particle->
x = ((
Random16() & 63) + 32) << 16;
587 particle->
y = ((
Random16() & 31) + 96) << 16;
589 particle->
z = 0x8000 - (particle->
x >> 7);
607 particle->
x = ((
Random16() & 63) + 256) << 16;
608 particle->
y = ((
Random16() & 31) + 96) << 16;
622 volatile u16 *pal = (
volatile u16 *)0x05000002;
623 for (i = 0; i != 63; i++, pal++) {
625 s32 b = ((
u16)c >> 10) & 31;
626 s32 g = ((
u16)c >> 5) & 31;
654 if ((frame & 7) < 4) {
662 canvas, sheet, 36, top - 24, 24, 24);
667 canvas, sheet, 59, top - 24, 24, 24);
672 canvas, sheet, 36, top - 1, 24, 24);
679 canvas, sheet, 59, top - 1, 24, 24);
685 if (frame >= 64 && frame < 66) {
688 if (frame >= 66 && frame < 68) {
691 if (frame >= 68 && frame < 76) {
702 if (frame >= 78 && frame < 80) {
705 if (frame >= 80 && frame < 82) {
708 if (frame >= 82 && frame < 86) {
709 s32 d = frame * 2 - 164;
721 if (frame >= 72 && frame < 76) {
722 s32 r2 = (frame << 4) - 1136;
726 for (i = 0; i != 256; i++) {
728 s32 x = ((
Trig_Sin(angle) * r2) >> 16) - (size >> 1);
739 for (i = 0; i != rings; i++, ring++) {
747 while (radius >= slope) {
757 dx = (half * sx) / 8;
766 bottom = cy + (slope * squash) / 8;
767 top = cy - (slope * sx) / 8;
784 right = cx + half + 1;
785 left = cx - half + 1;
797 halfSlope = slope / 2;
798 dx = (halfSlope * sx) / 8;
807 bottom = cy + (radius * squash) / 8;
808 top = cy - (radius * sx) / 8;
825 right = cx + halfSlope + 1;
826 left = cx - halfSlope + 1;
838 err = err - slope * 2 - 1;
840 err = err + radius * 2 - 2;
851 if (frame >= 86 && frame < 150) {
853 for (i = 0; i != 9; i++, angle += 0x1000) {
860 x + 44, y + 17, 32, 54);
894 if (frame >= 214 && frame < 280) {
898 if (frame >= 246 && frame < 280) {
915 scale.x = particle->
z + (particle->
y >> 7);
916 if (
scale.x < 0x800) {
920 debrisPlace.
x = particle->
x;
921 debrisPlace.
height = 0xff0000;
922 debrisPlace.
y = particle->
y + 0xff0000;
926 if (particle->
y < 0x100000) {
928 particle->
x = ((
Random16() & 63) + shift + 32) << 16;
930 particle->
x = ((
Random16() & 63) + shift - 32) << 16;
934 }
else if (frame > 245) {
935 particle->
y = 0x600000;
937 particle->
y = 0xc00000 - particle->
x;
944 for (i = 0; i != 8; i++) {
946 (i & 1) * 20 - (
Random16() & 15) + (i / 2) * 4 + shift / 2 - 16;
955 for (i = 0; i != 8; i++) {
957 (i & 1) * 20 + (
Random16() & 15) - (i / 2) * 4 + shift / 2 - 16;
991#undef JUDGMENT_SHEET_BYTES
992#undef JUDGMENT_SPARKS
993#undef JUDGMENT_SHEET_TORNADO
994#undef JUDGMENT_GATHER_FRAMES
995#undef JUDGMENT_SWEEP_FRAMES
996#undef JUDGMENT_SHEET_FLARE_B
997#undef JUDGMENT_FORMATION_OBJECTS
998#undef JUDGMENT_DEBRIS_OBJECTS
999#undef JUDGMENT_SHEET_BURST
1000#undef JUDGMENT_SHEET_EXPLOSION
1001#undef JUDGMENT_SHEET_FLARE_A
1002#undef JUDGMENT_SHEET_FLASH_SMALL
1003#undef JUDGMENT_SHEET_FLASH_LARGE
1004#undef JUDGMENT_SHEET_FLASH_STREAK
1005#undef JUDGMENT_EXPLOSION_CELL_BYTES
1006#undef JUDGMENT_WAVE_SIZE
1007#undef JUDGMENT_DMA_FILL_CANVAS
1008#undef JUDGMENT_DMA_FILL_WAVE
@ SPRITE_COLOR_BLACK
solid colour 1, black
@ POSE_DAMAGE
taking damage
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...
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...
void BattleFx_ConfigureEffectDisplay(void)
Puts the battle screen back into the display state every effect starts from and ends with: no blendin...
void Resource_LoadAndDecompress(s32 id, void *dst, s32 skipPalette, s32 copyPalette)
Decompresses a resource whose first 128 bytes may be a palette.
static __inline__ void Dma_Set(const volatile void *source, volatile void *destination, u32 control, volatile u32 *channel)
Starts a DMA transfer: stores the source, destination and control words into channel's registers with...
void ObjectGroup_UpdateMembers(s32 actorId, s32 palette, s32 animation, s32 timerSlot, s32 timerFrames)
Updates every animation group of one battler's object.
void BattleFx_SetupBlendedDisplay(void)
Shows the BG1 battle background behind a cleared canvas: clears the canvas buffer and the 16 KiB of V...
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...
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_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_FINISH_CANVAS_ONE_BLITTER()
The same for an effect that drew through one blitter.
#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 CANVAS_SLOT(slots, slot)
A work slot read through a pointer to the canvas slot, gWorkSlot[HEAP_SLOT_BATTLE_CANVAS],...
#define EFFECT_CAP_LEVEL(level, cap)
Caps a colour level at cap, and at 0 from below.
#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...
u16 gJudgment_ShardCells[]
u8 gJudgment_ShardWidths[]
u16 gBattleFx_MoteCells[]
Mote cells: particle sheets hold ten, cell n (from 0) n + 1 pixels wide and twice that tall.
u8 gJudgment_BurstHeights[]
u16 gJudgment_BurstCells[]
u8 gJudgment_ShardHeights[]
void BattleFx_SpawnObjects(s32 entryCount, s32 source, u32 priority)
Creates the effect's animation objects in gBattleFxWork's objects.
void BattleBackground_LoadFar(s32 mode, s32 resource, s32 level)
void BattlePresentation_ConfigurePaletteFadeFar(s32 mode, s32 value, s32 fade)
s32 AnimationObjects_SelectAnimationFar(struct AnimationObject *state, s32 flags)
struct AnimationObject * ResourceObject_CreateFar(s32 id)
void Object_ApplyProjectedPlacementFar(struct AnimationObject *sprite, const struct SpritePlacement *position, const struct SpriteScale *scale, s32 facing)
Far call to Render_ApplyProjectedPlacement.
void ResourceObject_ReleaseFar(struct AnimationObject *sprite)
void AudioCommand_PlayFar(s32 id)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
@ HEAP_SLOT_BATTLE_EFFECT
@ HEAP_SLOT_BLITTER_ALTERNATE
@ HEAP_SLOT_BATTLE_BACKGROUND
@ HEAP_SLOT_BATTLE_CANVAS
#define Q_8_8(n)
The BG2/BG3 affine matrix entries are signed 8.8 fixed point: texels stepped per screen pixel.
#define BGCNT_CHAR_BASE(block)
#define BGCNT_PRIORITY(n)
#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...
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
#define BGCNT_SCREEN_BASE(block)
#define BG_PLTT_COLOR(palette, color)
#define BGCNT_WRAP
Affine backgrounds only: wrap around instead of showing the backdrop.
#define IO_WRITE_QUEUE_PUSH_IME(ime, address, value, control)
Like IO_WRITE_QUEUE_PUSH, but keeps IME's address in the caller's ime variable while disabling and re...
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
static s32 Iwram_FillWords(void *destination, s32 size, u32 value)
#define JUDGMENT_SHEET_FLARE_A
The first 24x24 flare picture, from the crescent sheet the sweep loads.
#define JUDGMENT_GATHER_FRAMES
frames of the gathering
#define JUDGMENT_WAVE_SIZE
the wave picture is 120x120
#define JUDGMENT_SHEET_FLASH_LARGE
The 24x41 large flash picture.
#define JUDGMENT_SHEET_BURST
the burst's quarter pictures
#define JUDGMENT_SWEEP_FRAMES
frames of the sweep
#define JUDGMENT_DMA_FILL_CANVAS
DMA word that fills the 128x128 canvas.
#define JUDGMENT_SHEET_FLARE_B
the second 24x24 flare picture
#define JUDGMENT_DEBRIS_OBJECTS
debris objects of the sweep
#define JUDGMENT_SHEET_TORNADO
The tornado sheet, whose six glint pictures are the burst's shards (gJudgment_ShardCells counts from ...
#define JUDGMENT_SHEET_EXPLOSION
The explosion's four 32x54 pictures, loaded over the flares on the sweep's frame 64.
#define JUDGMENT_SHEET_BYTES
The bytes of Judgment's work block before its dimmed mote copies.
#define JUDGMENT_SPARKS
The gathering's 128 sparks, after its 128 motes in PARTICLES.
#define JUDGMENT_DMA_FILL_WAVE
DMA word that fills the 120x120 wave picture.
void BattleFx_RunJudgment(struct BattleEffectArgument *effect)
The battle wipes away to a violet sky where a formation flies forward while motes gather into it,...
#define JUDGMENT_SHEET_FLASH_SMALL
The 16x17 small flash, the first of OverlayImageA's three pictures.
#define JUDGMENT_SHEET_FLASH_STREAK
The 22x44 flash streak picture.
#define JUDGMENT_EXPLOSION_CELL_BYTES
bytes in each explosion picture
#define JUDGMENT_FORMATION_OBJECTS
objects in the formation, 4x4
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
void Runtime_ReleaseHeapBlock(s32 slot)
void EffectStep_AdvanceWithGravity3D(struct EffectStep *step, s32 damping, s32 gravity)
Moves a particle one frame in three dimensions: adds its velocity, then gravity to its vertical speed...
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...
struct Projection gProjection
char ResourceId_PinkBurstSheet
char ResourceId_TornadoSheet
char ResourceId_ForestBackdrop
char ResourceId_AerialViewBackdrop
char ResourceId_VioletSkyBackdrop
char ResourceId_OverlayImageA
char ResourceId_ExplosionSheet
char ResourceId_BeachBackdrop
char ResourceId_OverlayImageB
char ResourceId_ParticleSpritesA
char ResourceId_BlueCrescentSheet
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...
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
struct AnimationSpritePart image
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
s32 scale
16.16 fixed point, 0x10000 full size
u16 priority
2 when created
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.
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 fadeFrames
backdrop fade frames left (Palette_StepFadeTransfer)
s32 fadeStep
CANVAS_FADE_STEPs the backdrop has darkened so far.
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 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
The battle background's work slot as the camera reads it: the yaw the camera eases toward and the fra...
s32 active
BattleBackgroundView's busy, at the same offset.
A point projected onto the screen, with its depth.
s32 depth
projected depth, larger further away
A moving point of an effect: its position, its velocity and a value each effect uses its own way (a s...
s32 z
16.16 fixed-point pixels
s32 variant
each effect's own: a size, a countdown, -1 for idle
s32 x
16.16 fixed-point pixels
s32 y
16.16 fixed-point pixels
s32 velocityY
16.16 fixed-point pixels per frame
Judgment's work block, laid over struct BattleEffectWork from its start.
u8 sheet[JUDGMENT_SHEET_BYTES]
The gathering's pictures: the pink burst, the burst's quarters and the tornado sheet.
u8 ramp[8][MOTE_SET_BYTES]
Eight copies of the mote sheet, copy i with every level capped at 64 - 7i; the gathering's ring of mo...
A sprite's screen position and its two vertical offsets, in 16.16 pixels.
s32 x
screen x of the sprite's centre
s32 y
screen y at the ground; sets the depth slot
s32 groundHeight
how far the shadow is raised above y
s32 height
how far the image is raised above y
Horizontal and vertical sprite scale; 0x10000 is the original size.
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
#define EFFECT_CLIP_BOUNDS
Clips overflow on all four sides.
#define PARTICLES
The map cell buffer (gMapCellBuffer), which the effects borrow, has two views here: Ram_MapCellBuffer...