Alchemy
Loading...
Searching...
No Matches

orbiting.c

Go to the documentation of this file.
1/// @file
2/// Swirling stars, orbiting skulls and target bursts.
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7// None of the three effects here is called, or held in any table: they are
8// in the ROM but unreachable. XXX: whether they are leftovers or reached by
9// some path not yet read; a pointer to one in data outside the effect
10// tables would settle it.
11
12#define SWIRLING_STARS_FRAMES 160
13#define SWIRLING_STARS_COUNT 64 ///< stars that swirl
14
15/// Swirling stars: 64 stars scattered around a point 80 pixels up spin
16/// about it, each on its own axis, appearing four a frame; 30 frames after
17/// it appears, each star is drawn back towards the centre. Stars are drawn
18/// smaller the further away they are. The scene runs for 160 frames. All
19/// 256 stars of the pool are seeded, at rest in a cube 255 pixels across,
20/// though only 64 are drawn.
21///
22/// Nothing calls it. Draws through the side's blitters mirrored (side ^ 1),
23/// and ends with the transfer callback removed, the blitters freed and the
24/// canvas layer closed.
26 void **slots;
27 void **cursor;
28 struct BattleEffectWork *work;
29 void *canvas;
30 s32 center[3];
31 struct EffectPosition screen;
32 BlitterPair draw;
33 struct EffectStep *star;
34 s32 i;
35 s32 frame;
36
37 EFFECT_GET_SLOTS(slots, cursor, work, canvas);
38 work->effect = effect;
42 for (i = 0; i != 256; i++) {
43 star = &PARTICLES[i];
44 SET_POSITION(star, ((Random16() & 0xff) - 127) << 16,
45 ((Random16() & 0xff) - 127) << 16,
46 ((Random16() & 0xff) - 127) << 16);
47 SET_VELOCITY(star, 0, 0, 0);
48 star->variant = 0;
49 }
51 // The stars turn about a point 80 pixels up.
52 SET_VECTOR(center, 0, 160 << 15, 0);
53 for (frame = 0; frame != SWIRLING_STARS_FRAMES; frame++) {
54 struct BattleCamera *camera;
55
56 camera = gCameraWork;
59 star = PARTICLES;
60 // Star i appears after frame i / 4; variant stays 0, so none is retired.
61 for (i = 0; i != SWIRLING_STARS_COUNT; i++, star++) {
62 if (frame > i / 4 && star->variant == 0) {
63 s32 size;
64
65 // Turn the star about one of four axes, picked by its index, faster
66 // for later stars.
68 switch (i & 3) {
69 case 0:
70 SceneTransform_ApplyYaw(frame * (i + 32) * 8);
71 break;
72 case 1:
73 SceneTransform_ApplyPitch(-frame * (i + 32) * 8);
74 break;
75 case 2:
76 SceneTransform_ApplyRoll(-frame * (i + 32) * 8);
77 break;
78 case 3:
79 SceneTransform_ApplyPitch(-frame * (i + 32) * 8);
80 SceneTransform_ApplyRoll(-frame * (i + 32) * 8);
81 break;
82 }
83 EffectPosition_ProjectPoint(star, &screen);
84 screen.x >>= 1;
86 // Size 9 to 3 over depths 250 to 634, from the star's own mote set
87 // (i & 3).
88 CLAMP(screen.depth, 250, 0x27a);
89 size = 9 - (screen.depth - 250) / 64;
90 draw[0](canvas,
91 work->sheet +
92 ((i & 3) * MOTE_SET_BYTES + gBattleFx_MoteCells[size - 1]),
93 screen.x - size / 2, screen.y - size, size, size * 2);
95 // From 30 frames after it appears, pull it towards the centre by
96 // 1/256 of its distance a frame.
97 if (frame > i / 4 + 30) {
98 s32 dx = -star->x >> 8;
99 s32 dy = -star->y >> 8;
100 s32 dz = -star->z >> 8;
101
102 star->velocityX += dx;
103 star->velocityY += dy;
104 star->velocityZ += dz;
105 }
106 }
107 }
109 }
111}
112
113/// Orbiting skulls: three skulls circle each target in turn, 16 frames
114/// apart, for 64 frames each, a third of a turn apart on a circle of 8
115/// pixels around the target. Runs with the effect already in
116/// gBattleFxWork.
117///
118/// Nothing calls it. Copies the skull palette over the first 128 bytes of BG
119/// palette RAM; writes REG_BG2PA, REG_BG2X and REG_BLDALPHA; keeps each
120/// skull's angle in velocityX of work->particles, three to a target. Ends
121/// with the transfer callback removed, the blitter freed and the canvas
122/// layer closed.
124 struct BattleEffectWork *work;
125 void *canvas;
126 s32 point[3];
127 struct EffectPosition center;
128 struct EffectPosition screen;
129 s32 frame;
130 /* FAKEMATCH: only draw[0] is used: the second word fills
131 * four bytes of the frame */
132 BlitterPair draw;
133 s32 member;
134 struct BattleCamera *camera;
135 u8 *skulls;
136 s32 xOffset;
137 s32 i;
138
141 camera = WORK_SLOT(HEAP_SLOT_CAMERA);
143 REG_BLDALPHA = BLEND_ALPHA(16, 16);
145 Iwram_CopyWords((void *)BG_PLTT, skulls, 128);
146 Resource_DecodeType01(skulls + 128, work->sheet);
148 // The first transfer mode is overwritten at once.
154 // Put the canvas on the targets' side of the screen.
155 if (work->effect->side == 0)
156 xOffset = 0;
157 else
158 xOffset = -112;
159 /* FAKEMATCH: a one-pass block sets the seed counter before its pointer; as
160 * a plain store, 2 instructions differ in tbs-en. */
161 do {
162 REG_BG2X = xOffset << 8;
163 } while (0);
164 // velocityX holds each skull's angle on its orbit; x, y and z are set but
165 // never read.
166 for (i = 0; i != 64; i++) {
167 struct EffectStep *step = &work->particles[i];
168
169 step->x = 0;
170 step->y = 0;
171 step->velocityX = 0;
172 step->z = 4;
173 }
174 for (frame = 0; frame != work->effect->count * 16 + 64; frame++) {
175 EFFECT_FOR_EACH_TARGET(member, work->effect) {
176 struct MotionObject *object;
177 u32 memberFrame;
178
179 object = GetBattleObjectSlotFar(work->effect->actors[member])->object;
181 &screen);
182 memberFrame = frame - member * 16;
183 screen.x += xOffset;
184 // Unsigned, so the frames before this target's turn are skipped too.
185 if (memberFrame < 64) {
186 /* FAKEMATCH: pins rec to r0 so loop.c cannot hoist the point's address
187 * into fp; as an ordinary pointer, 118 of 265 instructions differ in
188 * tbs-en. */
189 register s32 *rec asm("r0");
190
191 // The object's projection is computed, but nothing reads it.
193 rec = point;
194 SET_VECTOR(rec, object->x, object->y, object->z);
195 EffectPosition_ProjectPoint(rec, &center);
196 /* FAKEMATCH: a one-pass block puts this store before the spark
197 * counter's movs r4, #0; as a plain store, 2 instructions differ in
198 * tbs-en. */
199 do {
200 center.x += xOffset;
201 } while (0);
202 // Three skulls a third of a turn apart, each turning 1/128 of a turn
203 // a frame; skull i is the i-th 24x24 picture.
204 for (i = 0; i != 3; i++) {
205 struct EffectStep *spark = &work->particles[member * 3 + i];
206 s32 x;
207 s32 y;
208
209 x = screen.x +
210 (((Trig_Sin(spark->velocityX + i * 0x5555) * 8)) >> 16);
211 y = screen.y +
212 (((Trig_Cos(spark->velocityX + i * 0x5555) * 8)) >> 16);
213 spark->velocityX += 0x200;
214 draw[0](canvas, work->sheet + i * 0x240, x - 12, y - 28, 24, 24);
215 }
216 }
217 }
219 }
221}
222
223/// The burst picture in the sheet, after the smoke.
224#define TARGET_BURSTS_CELLS 0x1b00
225
226#define TARGET_BURSTS_FRAMES 96
227
228/// Target bursts: on each target in turn, 8 frames apart, a burst flares up
229/// in the middle while five puffs of smoke scatter around it, for 40
230/// frames.
231///
232/// Nothing calls it. Copies the pink burst palette over the first 128 bytes
233/// of BG palette RAM, uses work->particles six to a target, and ends with the
234/// transfer callback removed, the blitters freed and the canvas layer closed.
236 void **slots;
237 void **cursor;
238 struct BattleEffectWork *work;
239 void *canvas;
240 void *palette;
241 s32 frame;
242 DrawRectangle drawSmoke;
243 DrawRectangle drawBurst;
244 struct EffectStep *puff;
245 s32 i;
246 struct EffectPosition screen;
247 s32 point[3];
248
249 EFFECT_GET_SLOTS(slots, cursor, work, canvas);
250 work->effect = effect;
254 work->sheet + TARGET_BURSTS_CELLS, 0, 0);
256 Iwram_CopyWords((void *)BG_PLTT, palette, 128);
259 drawBurst = EFFECT_SLOT(slots, HEAP_SLOT_BLITTER);
262 drawSmoke = EFFECT_SLOT(slots, HEAP_SLOT_BLITTER_ALTERNATE);
263
264 // Six puffs for each target: five scatter at random, the sixth (the
265 // burst) stays in the middle. The burst draws its two random numbers
266 // too, unused.
267 for (i = 0; i != 64; i++) {
268 s32 angle;
269 s32 speed;
270
271 puff = &work->particles[i];
272 angle = Random16() & 0xffff;
273 speed = Random16() & 0xff;
274 SET_POSITION(puff, 0, 0, 0);
275 if (i % 6 == 5) {
276 puff->velocityX = 0;
277 puff->velocityY = 0;
278 } else {
279 puff->velocityX = (Trig_Sin(angle) * speed) >> 7;
280 puff->velocityY = (Trig_Cos(angle) * speed) >> 9;
281 }
282 puff->velocityZ = 0;
283 puff->variant = 0;
284 }
285
287
288 for (frame = 0; frame != TARGET_BURSTS_FRAMES; frame++) {
289 s32 member;
290 struct BattleCamera *camera;
291
292 camera = gCameraWork;
293 EFFECT_FOR_EACH_TARGET(member, work->effect) {
294 struct MotionObject *effect;
295
296 effect = GetBattleObjectSlotFar(work->effect->actors[member])->object;
298 // Centred 20 pixels above the target's feet.
299 SET_VECTOR(point, effect->x, 160 << 13, effect->z);
301 if (frame >= member * 8 && frame < member * 8 + 40) {
302 struct EffectStep *puff;
303
304 // The target's five puffs and its burst, each through six pictures
305 // of six frames, holding the last; the burst rises faster.
306 for (i = 0; i != 6; i++) {
307 s32 cell;
308
309 puff = &work->particles[member * 6 + i];
310 cell = puff->variant / 6;
311 if (cell > 5)
312 cell = 5;
313 EffectPosition_ProjectPoint(puff, &screen);
314 screen.x >>= 1;
315 if (i == 5) {
316 EffectStep_AdvanceWithGravity3D(puff, 62, 0x800);
317 drawBurst(canvas, work->sheet + cell * 0x480 + TARGET_BURSTS_CELLS,
318 screen.x - 12, screen.y - 36, 24, 48);
319 } else {
320 EffectStep_AdvanceWithGravity3D(puff, 60, 0x200);
321 drawSmoke(canvas, work->sheet + cell * 0x480, screen.x - 12,
322 screen.y - 36, 24, 48);
323 }
324 puff->variant += 1;
325 }
326 }
327 }
329 }
331}
332
333#undef SWIRLING_STARS_FRAMES
334#undef SWIRLING_STARS_COUNT
335#undef TARGET_BURSTS_CELLS
336#undef TARGET_BURSTS_FRAMES
struct BattleCamera * gCameraWork
@ 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_BeginCanvasLayer(s32 bgControl)
Opens the canvas layer: starts the background palette fade, makes BG2 the canvas, alpha-blended over ...
Definition canvas.c:314
void Resource_LoadAndDecompress(s32 id, void *dst, s32 skipPalette, s32 copyPalette)
Decompresses a resource whose first 128 bytes may be a palette.
What every part of the battle effect object shares: its includes, macros and frame-loop helpers.
#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_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 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_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_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 gBattleFx_MoteCells[]
Mote cells: particle sheets hold ten, cell n (from 0) n + 1 pixels wide and twice that tall.
struct BattleObj * GetBattleObjectSlotFar(s32 objectId)
Far call to BattleObjGet.
s32 Trig_Cos(s32 angle)
s32 Trig_Sin(s32 angle)
@ HEAP_SLOT_BATTLE_EFFECT
Definition heap_state.h:42
@ HEAP_SLOT_BLITTER_ALTERNATE
Definition heap_state.h:47
@ HEAP_SLOT_CAMERA
Definition heap_state.h:38
@ HEAP_SLOT_BLITTER
Definition heap_state.h:46
@ 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 REG_BG2X
Definition io_reg.h:65
#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 REG_BLDALPHA
Definition io_reg.h:142
#define BG_PLTT
Definition io_reg.h:157
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 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
#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
void BattleFx_FetchRectangleBlitters(s32 flip, BlitterPair out)
Builds the two usual routines that draw onto the 128x128 canvas, both clipped on both axes.
UNUSED void BattleFx_RunTargetBursts(struct BattleEffectArgument *effect)
Target bursts: on each target in turn, 8 frames apart, a burst flares up in the middle while five puf...
Definition orbiting.c:235
#define TARGET_BURSTS_CELLS
The burst picture in the sheet, after the smoke.
Definition orbiting.c:224
UNUSED void BattleFx_RunOrbitingSkulls(void)
Orbiting skulls: three skulls circle each target in turn, 16 frames apart, for 64 frames each,...
Definition orbiting.c:123
#define SWIRLING_STARS_COUNT
stars that swirl
Definition orbiting.c:13
#define SWIRLING_STARS_FRAMES
Definition orbiting.c:12
UNUSED void BattleFx_RunSwirlingStars(struct BattleEffectArgument *effect)
Swirling stars: 64 stars scattered around a point 80 pixels up spin about it, each on its own axis,...
Definition orbiting.c:25
#define TARGET_BURSTS_FRAMES
Definition orbiting.c:226
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_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...
Definition positions.c:29
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
char ResourceId_PinkBurstSheet
char ResourceId_TargetBurstImage
char ResourceId_SkullSheet
char ResourceId_SmokeSheet
char ResourceId_StarDotSheet
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
Definition decompress.c:31
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
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 side
1 when the targets are the party, 0 for enemies
s16 actors[8]
the targets' unit ids, count of them
s32 count
targets in actors, at least 1
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
struct BattleEffectArgument * effect
the command being run
struct EffectStep particles[64]
free while variant is -1
struct MotionObject * object
NULL once released.
A point projected onto the screen, with its depth.
Definition effect_step.h:46
s32 y
screen pixels
Definition effect_step.h:59
s32 depth
projected depth, larger further away
Definition effect_step.h:60
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
s32 velocityZ
16.16 fixed-point pixels per frame
Definition effect_step.h:30
An effect object that moves and draws one sprite: its position, scale, velocity and target,...
Definition motobj.h:20
s32 z
16.16 fixed-point pixels
Definition motobj.h:25
s32 y
16.16 fixed-point pixels
Definition motobj.h:24
s32 x
16.16 fixed-point pixels
Definition motobj.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 Transform_Pop(void)
Restores gTransform from the save area, if Transform_Push saved it.
Definition transform.c:49
void SceneTransform_ApplyPosition(const s32 *position)
Translates gTransform by position (x, y, z in 16.16).
Definition transform.c:145
void Transform_Push(void)
Saves gTransform into the save area (one level deep; a second save is ignored).
Definition transform.c:30
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
#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 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