Alchemy
Loading...
Searching...
No Matches

gaia.c

Go to the documentation of this file.
1/// @file
2/// Gaia.
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7/// The standing wall's top in the rebuilt sheet, 48x96 (stretched from 48x32).
8#define GAIA_WALL_TOP_CELLS 0x13c0
9/// The standing wall's foot in the rebuilt sheet, 48x21.
10#define GAIA_WALL_FOOT_CELLS 0x25c0
11#define GAIA_WALL_FOOT_BYTES (48 * 21)
12#define GAIA_FRAMES 192
13#define GAIA_ROCKS 11 ///< rocks that tumble up the wall
14
15/// Rising wall: the ground swells, a wall of rock rises from it, stands while
16/// rocks tumble up its face and the targets are battered, and sinks again.
17///
18/// Abilities: Gaia, Mother Gaia, Grand Gaia, Rockfall, Rockslide, Avalanche
19/// (kind 3).
20///
21/// The wall is symmetric: its left half is drawn, then mirrored for the right.
22/// Its centre is at canvas x 64 + wallX. The rocks are 11 animation objects,
23/// moved by particles[10] to particles[20].
24///
25/// effect: the targets; variant 0 to 2 widens the wall.
27 static struct SpriteScale unitScale = {{{0x10000, 0x10000}}};
28 void **slots;
29 void **cursor;
30 struct BattleEffectWork *work;
31 void *canvas;
32 BlitterPair draw;
33 u8 *sprites;
34 s32 wallX;
35 s32 rockX;
36 struct SpriteScale scale;
37 struct SpritePlacement position;
38 u8 *src;
39 u16 *color;
40 void *palette = (void *)BG_PLTT;
41 s32 sheetIndex;
42 s32 frame;
43 s32 i;
44 s32 j;
45 s32 k;
46
47 EFFECT_GET_SLOTS(slots, cursor, work, canvas);
48 sprites = EFFECT_SLOT(slots, HEAP_SLOT_BATTLE_SHEET);
49 work->effect = effect;
51
52 // The higher the variant, the wider the wall: BG2 stretches the canvas 1.25
53 // or 1.5 times, or twice as BattleFx_BeginCanvasLayer left it.
54 if (work->effect->variant == 0)
55 REG_BG2PA = Q_8_8(0.8);
56 else if (work->effect->variant == 1)
57 REG_BG2PA = Q_8_8(1.0 / 1.5);
58 if (work->effect->side == 1) {
59 wallX = 8;
60 if (work->effect->variant == 0)
61 rockX = 40;
62 else if (work->effect->variant == 1)
63 rockX = 36;
64 else
65 rockX = 40;
66 } else {
67 wallX = -16;
68 rockX = -12;
69 }
70 REG_BG2X = gGaia_Bg2Shifts[work->effect->side][work->effect->variant] << 8;
71
72 // Decode the EarthWall sheet into Ram_MapCellBuffer, and load the orange
73 // palette with background colours 1 to 63 each 8 steps darker a channel.
75 1, 0);
76 Iwram_CopyWords(palette,
78 color = (u16 *)&BG_PLTT[1];
79 for (i = 0; i != 63; i++) {
80 s32 entry = *color;
81 s32 blue = ((u16)entry >> 10) & 31;
82 s32 green = ((u16)entry >> 5) & 31;
83 s32 red = 31;
84
85 red &= entry;
86 blue -= 8;
87 green -= 8;
88 red -= 8;
89
90 if (blue < 0)
91 blue = 0;
92 if (green < 0)
93 green = 0;
94 if (red < 0)
95 red = 0;
96 *color++ = RGB(red, green, blue);
97 }
98
99 // Rebuild the pictures in work->sheet:
100 // the growing wall: nine one-line rows, each stretched to 32 lines;
101 // the top of the wall (GAIA_WALL_TOP_CELLS): 48x32 stretched to 48x96;
102 // the foot of the wall (GAIA_WALL_FOOT_CELLS): 48x21;
103 // the swelling ground: three frames.
104 src = Ram_MapCellBuffer;
105 sheetIndex = 0;
106 for (j = 0; j != 9; j++) {
107 for (i = 0; i != 32; i++) {
108 for (k = 0; k != gGaia_RowWidths[j]; k++, sheetIndex++)
109 work->sheet[sheetIndex] = src[k];
110 }
111 src += gGaia_RowWidths[j];
112 }
113 for (j = 0; j != 32; j++) {
114 for (i = 0; i != 3; i++) {
115 for (k = 0; k != 48; k++, sheetIndex++)
116 work->sheet[sheetIndex] = src[k];
117 }
118 src += 48;
119 }
120 for (i = 0; i != GAIA_WALL_FOOT_BYTES; i++)
121 work->sheet[sheetIndex++] = *src++;
122 for (i = 0; i != 3; i++) {
123 for (k = 0; k != gGaia_MoundWidths[i] * gGaia_MoundHeights[i]; k++)
124 work->sheet[sheetIndex++] = *src++;
125 }
127
128 // The rock objects, made from resource 390: objects 0 to 3 play animation
129 // 0, 4 to 7 animation 1 and 8 to 10 animation 2.
130 for (i = 0; i != GAIA_ROCKS; i++) {
131 struct AnimationObject *rock = ResourceObject_CreateFar(390);
132
133 work->objects[i] = rock;
134 if (rock != 0) {
135 rock->flags = 0;
137 work->objects[i]->image.priority = 1;
138 }
139 }
145 REG_BLDCNT =
147 REG_BLDALPHA = BLEND_ALPHA(16, 16);
148 // Trails: each transfer keeps 3/4 of every canvas level.
150
151 // Rocks: x is the column, y counts down from 128 by z, velocityX cycles
152 // through 1 to 12, and variant is the wait before the rock appears.
153 for (i = 0; i != GAIA_ROCKS; i++) {
154 struct EffectStep *rock = &work->particles[10 + i];
155
156 SET_POSITION(rock, (Random16() & 15) + 88, 128, (Random16() & 15) + 2);
157 SET_VELOCITY(rock, i, 1, 0x8000);
158 rock->variant = 44 - i * 4;
159 }
160 // Then particles[16] to particles[21] take the fixed columns of
161 // gGaia_LateRockColumns.
162 for (i = 0; i != 6; i++)
163 work->particles[16 + i].x = gGaia_LateRockColumns[i];
164
165 // Dust rises from the foot of the wall, half a pixel to 1.5 pixels a
166 // frame, each mote after a random wait of up to 31 frames (its variant).
167 for (i = 0; i != 256; i++) {
168 struct EffectStep *dust = &PARTICLES[i];
169
170 dust->x = ((Random16() & 63) + wallX + 32) << 16;
171 dust->y = ((Random16() & 7) + 96) << 16;
172 dust->velocityY = ((Random16() & 63) + 32) << 13;
173 dust->variant = Random16() & 31;
174 }
177 // The screen shakes throughout: 250 frames outlast the effect, and the
178 // ranges given to Camera_ApplyShake below set how hard.
179 work->shakeFrames = 250;
180 for (frame = 0; frame != GAIA_FRAMES; frame++) {
181 if (frame == 0)
183 if (frame == 40)
185 if (frame == 96)
187 if (frame == 120)
189
190 // The swelling ground (frames 0 to 81).
191 if (frame <= 81) {
192 s32 cell = frame / 4;
193
194 if (cell > 2)
195 cell = (cell & 1) + 1;
196 draw[0](canvas, work->sheet + gGaia_MoundCells[cell],
197 wallX - gGaia_MoundWidths[cell] + 64,
198 116 - gGaia_MoundHeights[cell], gGaia_MoundWidths[cell],
199 gGaia_MoundHeights[cell]);
200 draw[1](canvas, work->sheet + gGaia_MoundCells[cell], wallX + 64,
201 116 - gGaia_MoundHeights[cell], gGaia_MoundWidths[cell],
202 gGaia_MoundHeights[cell]);
203 }
204
205 // The rising wall (frames 12 to 87): its narrowest row until frame 66,
206 // then a row wider every 3 frames, the widest from frame 85.
207 if (frame >= 12 && frame <= 87) {
208 s32 row = (frame - 64) / 3;
209
210 CLAMP(row, 0, 7);
211 for (i = 0; i != 4; i++) {
212 draw[0](canvas, work->sheet + gGaia_RowCells[row],
213 wallX - gGaia_RowWidths[row] + 64, i * 32 - 12,
214 gGaia_RowWidths[row], 32);
215 draw[1](canvas, work->sheet + gGaia_RowCells[row], wallX + 64,
216 i * 32 - 12, gGaia_RowWidths[row], 32);
217 }
218 }
219
220 // The sinking wall (frames 160 to 183).
221 if (frame >= 160 && frame <= 183) {
222 s32 row = 7 - (frame - 160) / 3;
223
224 CLAMP(row, 0, 7);
225 for (i = 0; i != 4; i++) {
226 draw[0](canvas, work->sheet + gGaia_RowCells[row],
227 wallX - gGaia_RowWidths[row] + 64, i * 32 - 12,
228 gGaia_RowWidths[row], 32);
229 draw[1](canvas, work->sheet + gGaia_RowCells[row], wallX + 64,
230 i * 32 - 12, gGaia_RowWidths[row], 32);
231 }
232 }
233
234 // The standing wall (frames 88 to 159).
235 if (frame >= 88 && frame <= 159) {
236 s32 width = 48;
237
238 draw[0](canvas, &work->sheet[GAIA_WALL_TOP_CELLS], wallX + 16, 0, width,
239 96);
240 draw[1](canvas, &work->sheet[GAIA_WALL_TOP_CELLS], wallX + 64, 0, width,
241 96);
242 draw[0](canvas, &work->sheet[GAIA_WALL_FOOT_CELLS], wallX + 16, 96, width,
243 21);
244 draw[1](canvas, &work->sheet[GAIA_WALL_FOOT_CELLS], wallX + 64, 96, width,
245 21);
246 }
247
248 // Dust (from frame 88): until frame 159, dust that leaves the top
249 // returns to the foot.
250 if (frame > 87) {
251 for (i = 0; i != 64; i++) {
252 struct EffectStep *dust = &PARTICLES[i];
253
254 if (dust->variant == 0) {
255 s32 size = (i & 3) + 5;
256
257 EFFECT_DRAW_MOTE(draw[0], canvas, sprites, Q_16_16_TO_INT(dust->x),
258 Q_16_16_TO_INT(dust->y), size);
259 dust->y -= dust->velocityY;
260 if (dust->y < 0 && frame <= 159)
261 dust->y = 0x600000;
262 } else {
263 dust->variant--;
264 }
265 }
266 }
267
268 // Rocks (from frame 5): six at half size, then from frame 72 all 11, each
269 // larger than the last and larger with the variant. The objects take
270 // turns showing the rocks, moving on every 2 frames; four objects play
271 // each of animations 0 and 1, three animation 2.
272 if (frame > 4) {
273 s32 rocks = 6;
274
275 if (frame > 71)
276 rocks = GAIA_ROCKS;
277 for (k = 0; k != rocks; k++) {
278 struct EffectStep *rock = &work->particles[10 + k];
279 s32 slot;
280
281 if (rock->variant == 0) {
282 scale = unitScale;
283 if (frame > 71) {
284 scale.x = (k << 12) + 0x8000;
285 scale.x += work->effect->variant << 14;
286 } else {
287 scale.x = 0x8000;
288 }
289 scale.y = scale.x;
290 position.groundHeight = 0;
291 position.x = (rock->x + rockX * 2) << 16;
292 position.height = 0x2000000 - (rock->y << 16);
293 position.y = 0x2000000;
294 slot = (frame / 2 + k) % GAIA_ROCKS;
295 // DEAD: always true, as slot is a remainder of a positive count; the
296 // ROM keeps the test.
297 if (slot != -1)
298 Object_ApplyProjectedPlacementFar(work->objects[slot], &position,
299 &scale, 0);
300 rock->y -= rock->z;
301 rock->velocityX += rock->velocityY;
302 if (rock->velocityX > 12)
303 rock->velocityX -= 12;
304 if (rock->y < 0) {
305 // Below 0 the rock starts again at 128 (from frame 88 in a new
306 // column, at a new speed).
307 if (frame > 159) {
308 rock->variant = -1;
309 } else {
310 if (frame > 87) {
311 rock->z = (Random16() & 7) + 8;
312 if (work->effect->variant == 0)
313 rock->x = Random16() % 96 + 42;
314 else if (work->effect->variant == 1)
315 rock->x = Random16() % 112 + 34;
316 else
317 rock->x = Random16() % 160 + 10;
318 }
319 rock->y = 128;
320 rock->variant = 8;
321 }
322 }
323 } else {
324 rock->variant--;
325 }
326 }
327 }
328
329 // The targets (frames 86 to 158): a flash every 12 frames and a recoil
330 // every 4.
331 if (frame <= 158) {
333 if (frame > 85) {
334 if (frame % 12 == 0)
337 if ((frame & 3) == 0)
339 }
340 }
341 }
342 if (frame < 90 || frame > 160)
343 Camera_ApplyShake(2, 2);
344 else
345 Camera_ApplyShake(8, 8);
346 EFFECT_END_FRAME(work);
347 }
350 for (i = 0; i != GAIA_ROCKS; i++)
353}
354
355#undef GAIA_WALL_TOP_CELLS
356#undef GAIA_WALL_FOOT_CELLS
357#undef GAIA_WALL_FOOT_BYTES
358#undef GAIA_FRAMES
359#undef GAIA_ROCKS
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_DAMAGE
taking damage
Definition battle.h:176
@ COMPOSITE_FLIP_X
@ 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_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 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_DRAW_MOTE(draw, canvas, sheet, x, y, size)
Particle sheets hold ten mote cells, 1x2 to 10x20 pixels.
@ CANVAS_COPY_AND_FADE
copy, keeping 50% or 75% (transferValue) of each pixel in the canvas for the next frame
#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_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_GET_SLOTS(slots, cursor, work, canvas)
Starts at the effect's entry in the whole work-slot array.
#define EFFECT_END_FRAME(work)
The usual end of an effect frame: counts down the targets' flash timers (ObjectGroup_TickMemberTimers...
u8 gGaia_RowWidths[]
u8 gGaia_MoundWidths[]
s8 gGaia_Bg2Shifts[][3]
BG2's x shift, by side and variant.
u8 gGaia_LateRockColumns[]
The columns rock particles[16] to particles[21] take.
u16 gGaia_RowCells[]
u16 gGaia_MoundCells[]
u8 gGaia_MoundHeights[]
void BattleMotion_ApplyVariantMotionFar(s32 id, s32 variant)
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)
#define GAIA_WALL_FOOT_CELLS
The standing wall's foot in the rebuilt sheet, 48x21.
Definition gaia.c:10
#define GAIA_FRAMES
Definition gaia.c:12
#define GAIA_ROCKS
rocks that tumble up the wall
Definition gaia.c:13
void BattleFx_RunGaia(struct BattleEffectArgument *effect)
Rising wall: the ground swells, a wall of rock rises from it, stands while rocks tumble up its face a...
Definition gaia.c:26
#define GAIA_WALL_TOP_CELLS
The standing wall's top in the rebuilt sheet, 48x96 (stretched from 48x32).
Definition gaia.c:8
#define GAIA_WALL_FOOT_BYTES
Definition gaia.c:11
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_BLITTER_ALTERNATE
Definition heap_state.h:47
@ HEAP_SLOT_BATTLE_SHEET
Definition heap_state.h:44
@ HEAP_SLOT_BLITTER
Definition heap_state.h:46
#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
#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 REG_BG2X
Definition io_reg.h:65
#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 BLDCNT_TGT1_BG1
Definition io_reg.h:124
#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 REG_BLDCNT
Definition io_reg.h:119
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
Definition iwram_call.h:85
#define SET_VELOCITY(p, vx, vy, vz)
Definition macros.h:18
#define SET_POSITION(p, px, py, pz)
Sets the position or the velocity of a particle, a piece of debris or an object in one statement.
Definition macros.h:16
#define CLAMP(v, low, high)
Keeps v within low to high, the low bound tested first.
Definition macros.h:23
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
#define Ram_MapCellBuffer
Definition ram_buffer.h:10
char ResourceId_EarthWallSheet
char ResourceId_ParticleSpritesA
char ResourceId_OrangePaletteA
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
#define SE_141
Definition songs.h:134
#define SE_212
Definition songs.h:207
#define SE_HEAVY_IMPACT
Definition songs.h:127
#define SE_145
Definition songs.h:138
void * gWorkSlot[]
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
struct AnimationSpritePart image
Definition animspr.h:109
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
Definition animspr.h:128
u16 priority
2 when created
Definition animspr.h:100
The command shared by an effect's caller, dispatcher and handlers.
s32 side
1 when the targets are the party, 0 for enemies
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 shakeFrames
shake frames left; Camera_ApplyShake counts down
struct AnimationObject * objects[16]
the effect's animation objects
struct BattleEffectArgument * effect
the command being run
struct EffectStep particles[64]
free while variant is -1
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
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.
Definition system.c:150
signed int s32
Definition types.h:14
unsigned short u16
Definition types.h:13
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