Alchemy
Loading...
Searching...
No Matches

effect_internal.h

Go to the documentation of this file.
1#ifndef ALCHEMY_EFFECT_INTERNAL_H
2#define ALCHEMY_EFFECT_INTERNAL_H
3
4/// @file
5/// What every part of the battle effect object shares: its includes, macros
6/// and frame-loop helpers. effect.c includes it before the parts, and each
7/// part includes it too, so that a part read on its own still resolves.
8
10#include "unit/effect/effect.h"
11#include "unit/object/object.h"
14#include "battle.h"
15#include "debug.h"
16#include "field.h"
17#include "game.h"
18#include "graphics.h"
19#include "menu.h"
20#include "minigame.h"
21#include "sound.h"
22#include "system.h"
23#include "mem.h"
24#include "canvas.h"
25#include "map_scroll.h"
26#include "heap_state.h"
27#include "menu_list.h"
28#include "types.h"
29#include "io_write_queue.h"
30#include "io_reg.h"
31#include "scene.h"
32#include "global_cells.h"
33#include "dma.h"
34#include "resource_ids.h"
35#include "songs.h"
36#include "battle_effect.h"
37#include "fixed_math.h"
38#include "callback_scheduler.h"
39#include "effect_step.h"
40#include "battle_effect_work.h"
41#include "battle_display.h"
42#include "ram_buffer.h"
43#include "resource.h"
44#include "b5_context.h"
45#include "motobj.h"
46#include "iwram_call.h"
47#include "transform.h"
48#include "battle_work.h"
49#include "project.h"
50#include "field_event.h"
51#include "keystate.h"
52#include "battle_type.h"
53#include "battle_system.h"
54#include "battle_session.h"
55#include "animspr.h"
56#include "battle_unit.h"
58#include "irq.h"
60#include "call.h"
61#include "macros.h"
62
63// Display, palette and scanline effects.
64//
65// Effects change the screen around their drawing in three ways:
66//
67// - Display state: the windows that frame the battle view (lines 16 to
68// 135), the blend and display registers, and the set-up every effect
69// starts and ends with (BattleFx_ConfigureEffectDisplay, below).
70// - Per-frame callbacks the runner schedules: background scrolling, the
71// camera shake and the backdrop palette fades that make the canvas stand
72// out.
73// - Per-scanline work: HBlank DMA that feeds a window edge, BG2's affine
74// reference or a palette row to the hardware line by line
75// (BattleFx_ArmWin0HBlankDma, BattleFx_ArmBg2AffineHBlankDma and
76// BattleFx_ArmPaletteHBlankDma), and the tables those transfers read.
77//
78// The callbacks read the current effect's work block, so the runner that
79// schedules them must remove them before that block is released.
80
81/// The battle screen's display mode while an effect plays: background mode 1
82/// with BG0 to BG2, sprites and both windows on.
83#define EFFECT_DISPCNT \
84 (DISPCNT_MODE_1 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG1_ON | \
85 DISPCNT_BG2_ON | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_WIN1_ON)
86
87/// Window 0, the battle view, shows BG0 to BG2, sprites and blending. Effects
88/// pick window 1's layers themselves.
89#define EFFECT_WIN0_LAYERS \
90 (WININ_WIN0_BG0 | WININ_WIN0_BG1 | WININ_WIN0_BG2 | WININ_WIN0_OBJ | \
91 WININ_WIN0_CLR)
92
93/// Outside the battle view: BG0 and blending only.
94#define EFFECT_WINOUT (WINOUT_WIN01_BG0 | WINOUT_WIN01_CLR | WINOUT_WINOBJ_ALL)
95
96/// A work slot read through a pointer to the effect's own slot,
97/// gWorkSlot[HEAP_SLOT_BATTLE_EFFECT].
98#define EFFECT_SLOT(slots, slot) ((slots)[(slot) - HEAP_SLOT_BATTLE_EFFECT])
99/// A work slot read through a pointer to the canvas slot,
100/// gWorkSlot[HEAP_SLOT_BATTLE_CANVAS], just after the effect's own.
101#define CANVAS_SLOT(slots, slot) ((slots)[(slot) - HEAP_SLOT_BATTLE_CANVAS])
102
103/// Index of DMAxCNT_H, the control half, in a channel's 16-bit registers.
104#define DMA_CONTROL_HALF 5
105
106/// DMA control word that fills n words from one fixed source word.
107#define DMA_FILL_WORDS(n) ((DMA_ENABLE | DMA_32BIT | DMA_SRC_FIXED) << 16 | (n))
108
109/// Stops a DMA channel: clears its repeat and start timing bits, then its
110/// enable bit, and reads the control register back so the stop takes effect
111/// before the channel is set up again. The HBlank DMA arms in display.c,
112/// dispatch.c, burst_shower.c and particle_streams.c call it first.
113static inline void Dma_Stop(volatile u16 *channel) {
115 channel[DMA_CONTROL_HALF] &= (u16)~DMA_ENABLE;
116 (void)channel[DMA_CONTROL_HALF];
117}
118
119/// How BattleFx_ProcessPendingGraphicsTransfer moves the effect's
120/// 128x128 canvas into VRAM once a frame (work->transferMode); the canvas
121/// pixels are indices into a palette ramp, so scaling them fades a trail.
123 CANVAS_COPY, ///< copy as drawn
124 CANVAS_COPY_AND_CLEAR, ///< copy, then fill the canvas with transferValue
125 CANVAS_COPY_AND_FADE, ///< copy, keeping 50% or 75% (transferValue) of each
126 ///< pixel in the canvas for the next frame
127 CANVAS_COPY_AND_DARKEN, ///< copy, then darken the canvas by transferValue
128 CANVAS_COPY_AND_BRIGHTEN ///< copy, then brighten the canvas by transferValue
129};
130
131/// The work block and canvas occupy adjacent slots, starting at
132/// HEAP_SLOT_BATTLE_EFFECT. A cursor reads them in that order.
133#define EFFECT_GET_WORK_AND_CANVAS(cursor, work, canvas) \
134 ((work) = *(cursor)++, (canvas) = *(cursor))
135
136/// Starts at the effect's entry in the whole work-slot array. Earlier slots,
137/// such as the camera, then stay within that array while cursor walks ahead.
138#define EFFECT_GET_SLOTS(slots, cursor, work, canvas) \
139 ((slots) = &gWorkSlot[HEAP_SLOT_BATTLE_EFFECT], (cursor) = (slots), \
140 EFFECT_GET_WORK_AND_CANVAS(cursor, work, canvas))
141
142/// Marks particles[0] to particles[count - 1] free: a particle whose variant
143/// is -1 is not drawn or moved until an effect gives it a life.
144#define EFFECT_FREE_PARTICLES(i, particles, count) \
145 for ((i) = 0; (i) != (count); (i)++) \
146 (particles)[i].variant = -1
147
148/// Starts a frame's 3D projection from the battle camera: resets the
149/// transform, then looks from camera->eye towards camera->pos. Effects that
150/// place pictures at battle positions do this before projecting them.
151#define EFFECT_VIEW_FROM_CAMERA(camera) \
152 (Render_ResetTransformState(), \
153 Transform_SetLookAt((camera)->eye, (camera)->pos))
154
155/// Strikes target `i`: it flashes white in its damage pose for `frames`
156/// frames and plays battle motion `motion`
157/// (BattleMotion_ApplyVariantMotionFar).
158#define EFFECT_STRIKE_TARGET(effect, i, frames, motion) \
159 (ObjectGroup_UpdateMembers((effect)->actors[i], SPRITE_COLOR_WHITE, \
160 POSE_DAMAGE, i, frames), \
161 BattleMotion_ApplyVariantMotionFar((effect)->actors[i], motion))
162
163// The canvas life cycle, shared by every canvas effect. The statement macros
164// are comma expressions, not do { } while (0) blocks: agscc compiles a
165// do-while (0) in an effect's frame loop differently at some sites, and the
166// comma form matches at all of them.
167
168/// Lets the battle show the damage: resumes its paused playback, which plays
169/// hitSound (an SE_ id; 0 keeps the one already queued) as the targets react.
170#define EFFECT_SHOW_DAMAGE(hitSound) BattleEventRuntime_BeginPhaseFar(hitSound)
171
172/// The canvas: 128x128 pixels, one byte each, in its heap slot and in VRAM at
173/// BG_CHAR_BLOCK(1).
174#define CANVAS_BYTES (128 * 128)
175
176/// Opens the canvas layer at the canvas's own width, one texel per pixel,
177/// where BattleFx_BeginCanvasLayer stretches it to twice the width.
178#define EFFECT_BEGIN_NARROW_CANVAS(bgControl) \
179 (BattleFx_BeginCanvasLayer(bgControl), REG_BG2PA = Q_8_8(1))
180
181/// Builds a blitter for the 128x128 canvas (1 << 7 pixels each way) in work
182/// slot `slot`: BattleFx_BuildBlitter's drawing routine for one clip, mirror
183/// and blend mode. Every canvas effect draws through one or two of these.
184#define EFFECT_LOAD_BLITTER(slot, flags, mode) \
185 BattleFx_BuildBlitter(slot, 7, 7, flags, mode)
186
187/// Sets how the canvas transfer treats what is left in the canvas after each
188/// copy: `mode` with `value` (see enum CanvasTransferMode).
189#define EFFECT_SET_TRANSFER(work, mode, value) \
190 ((work)->transferMode = (mode), (work)->transferValue = (value))
191
192/// Sets the transfer, then starts copying the canvas to VRAM once a frame.
193#define EFFECT_START_TRANSFER(work, mode, value) \
194 (EFFECT_SET_TRANSFER(work, mode, value), \
195 Scheduler_AddOrUpdateCallback(BattleFx_ProcessPendingGraphicsTransfer, \
196 EFFECT_CALLBACK_ORDER))
197
198/// Ends a frame of a canvas effect: marks the canvas ready for the transfer
199/// callback, then waits for the next frame. Nearly every effect loop ends so.
200#define EFFECT_PRESENT_FRAME(work) ((work)->transferPending = 1, WaitFrames(1))
201
202/// The usual end of an effect frame: counts down the targets' flash timers
203/// (ObjectGroup_TickMemberTimers), then presents the canvas.
204#define EFFECT_END_FRAME(work) \
205 (ObjectGroup_TickMemberTimers(), EFFECT_PRESENT_FRAME(work))
206
207/// Frees the two blitters, the alternate first.
208#define EFFECT_RELEASE_BLITTERS() \
209 (Runtime_ReleaseHeapBlock(HEAP_SLOT_BLITTER_ALTERNATE), \
210 Runtime_ReleaseHeapBlock(HEAP_SLOT_BLITTER))
211
212/// The usual end of a canvas effect: stops the transfer callback before
213/// freeing what it reads, then the blitters, then the canvas layer.
214#define EFFECT_FINISH_CANVAS() \
215 (Scheduler_RemoveCallback(BattleFx_ProcessPendingGraphicsTransfer), \
216 EFFECT_RELEASE_BLITTERS(), BattleFx_EndCanvasLayer())
217
218/// The same for an effect that drew through one blitter.
219#define EFFECT_FINISH_CANVAS_ONE_BLITTER() \
220 (Scheduler_RemoveCallback(BattleFx_ProcessPendingGraphicsTransfer), \
221 Runtime_ReleaseHeapBlock(HEAP_SLOT_BLITTER), BattleFx_EndCanvasLayer())
222
223/// The bytes of one set of the ten mote cells: 2 * (1 + 4 + ... + 100).
224#define MOTE_SET_BYTES 770
225
226/// Particle sheets hold ten mote cells, 1x2 to 10x20 pixels. Draws mote cell
227/// `size` (size pixels wide, twice that tall) of `sheet` through blitter
228/// `draw`, centred across x and standing on y: the motes, sparks and dust of
229/// 32 effects, from the mote fountain to the summons.
230#define EFFECT_DRAW_MOTE(draw, canvas, sheet, x, y, size) \
231 (draw)(canvas, (sheet) + gBattleFx_MoteCells[(size) - 1], (x) - (size) / 2, \
232 (y) - (size), size, (size) * 2)
233
234/// Draws flare cell `size` of `sheet`, a square `size` pixels from its centre
235/// to each edge, centred on (x, y): Douse's sparks and the glowing points of
236/// the element pillar and burst, stat boosts, beams and rings.
237#define EFFECT_DRAW_FLARE(draw, canvas, sheet, x, y, size) \
238 (draw)(canvas, (sheet) + gBattleFx_FlareCells[(size) - 1], (x) - (size), \
239 (y) - (size), (size) * 2, (size) * 2)
240
241/// Shows the canvas: the effect display mode, BG2 stretched to twice its width
242/// (the 128-pixel canvas shown 256 pixels wide) and blended over everything
243/// below: `top` sixteenths of the canvas's colour are added to all of what
244/// lies under it, so the canvas brightens what it covers.
245#define EFFECT_SHOW_WIDE_CANVAS(top) \
246 (REG_DISPCNT = EFFECT_DISPCNT, REG_BG2PA = Q_8_8(0.5), \
247 REG_BLDALPHA = BLEND_ALPHA(top, 16), \
248 REG_BLDCNT = BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)
249
250/// A WIN0H value whose left edge is past its right edge. The hardware then
251/// takes the right edge as 240, so the span is not empty in itself; the
252/// effects write it only on lines outside window 0's vertical range.
253#define WINDOW_SPAN_INVERTED WIN_RANGE(1, 0)
254
255/// The scheduler order of every per-frame effect callback
256/// (Scheduler_AddOrUpdateCallback sorts the frame's callbacks by order).
257#define EFFECT_CALLBACK_ORDER 0x480
258/// The order where the battle's own playback runs, which the palette fade and
259/// the element streaks take.
260#define EFFECT_PLAYBACK_ORDER 0xc80
261
262/// The full-screen picture Graphics_ConvertBackgroundToBlueRamp (bind.c)
263/// works on, which Condemn draws too.
264#define BLUE_RAMP_PIXELS Ram_MapCellBuffer
265
266/// Caps a colour level at cap, and at 0 from below. Fades draw from darker
267/// copies of a picture built before the first frame, copy i capped at
268/// 64 - 7i.
269#define EFFECT_CAP_LEVEL(level, cap) \
270 { \
271 if ((level) > (cap)) \
272 (level) = (cap); \
273 if ((level) < 0) \
274 (level) = 0; \
275 }
276
277/// Closing bolts and lightning columns use the same 24x120 picture cells.
278#define LIGHTNING_BOLT_CELL_BYTES 2880
279
280/// Windows 0 and 1 both cover the battle view: the full width, lines 16 to
281/// 135.
282#define EFFECT_SET_BATTLE_WINDOWS() \
283 (REG_WIN0H = WIN_RANGE(0, 240), REG_WIN0V = WIN_RANGE(16, 136), \
284 REG_WIN1H = WIN_RANGE(0, 240), REG_WIN1V = WIN_RANGE(16, 136))
285
286/// BG2 shows the canvas from screen line 16 down (BG2Y is -16.0), stretched to
287/// twice its width: the 128x128 canvas across the battle view.
288#define EFFECT_SET_CANVAS_AFFINE() \
289 (REG_BG2X = 0, REG_BG2Y = -0x1000, REG_BG2PA = Q_8_8(0.5), REG_BG2PB = 0, \
290 REG_BG2PC = 0, REG_BG2PD = Q_8_8(1))
291
292/// Writes one row of BG2's map for the canvas: its 16 tiles of row `row` in
293/// order. An affine map has one byte per tile, so they are written two at a
294/// time, eight halfwords from `offset` on.
295#define EFFECT_WRITE_CANVAS_MAP_ROW(row, column, offset) \
296 for ((column) = 0; (column) != 8; (column)++, (offset) += 2) { \
297 s32 tileIndex; \
298 s16 pair; \
299 \
300 tileIndex = (row) * 16 + (column) * 2; \
301 pair = ((tileIndex + 1) << 8) | tileIndex; \
302 *(volatile s16 *)((u8 *)BG_CANVAS_MAP + (offset)) = pair; \
303 }
304
305#endif // ALCHEMY_EFFECT_INTERNAL_H
Animated sprites: their layers, frames and colour modes, and the resource slots they draw from.
B5Context, the object context a battle routine reads; most of its fields are still unnamed.
The battle camera and the presentation's transition, background and affine work.
The battle effect argument and the rectangle-drawing routines effects call.
BattleEffectWork, the running battle effect's work, and its animation objects.
A battle's objects and sprites, each unit's command and action record, and the spoils.
BattleUnit_Recalculate, which recalculates a unit's stats.
BattlePlan, an action planned for its targets: the hits, criticals and multipliers rolled.
BattleUnit, a party member's or enemy's battle state, with the elements, abilities and actions it use...
BattleWork, the battle's own work, and the battle display work.
Calls through a function pointer, by argument count.
The task scheduler: tasks, their order and the scheduler's state.
Declares nothing of its own: it only includes types.h and battle_effect.h.
The engine calls the debug menus import, and their palette swatch tiles.
DMA channel registers, and the DMA and CPU fills.
CanvasTransferMode
How BattleFx_ProcessPendingGraphicsTransfer moves the effect's 128x128 canvas into VRAM once a frame ...
@ CANVAS_COPY
copy as drawn
@ CANVAS_COPY_AND_BRIGHTEN
copy, then brighten the canvas by transferValue
@ 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
static void Dma_Stop(volatile u16 *channel)
Stops a DMA channel: clears its repeat and start timing bits, then its enable bit,...
#define DMA_CONTROL_HALF
Index of DMAxCNT_H, the control half, in a channel's 16-bit registers.
EffectStep and EffectPosition, the positions effects move through.
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
16.16 fixed-point constants, sine and cosine, and the library division.
FixedPointPosition, a position in 16.16 fixed point.
The work slots of gWorkSlot, read through their own names.
The screen blend's globals and the graphics routines.
The heap's work slots and HeapState.
The hardware's I/O registers and their bits, as pret names them.
#define DMA_START_TIMING_DRQ_REPEAT
A DMA control's start timing (bits 12 and 13), cartridge request (bit 11) and repeat (bit 9): the bit...
Definition io_reg.h:220
#define DMA_ENABLE
Definition io_reg.h:217
The register write queue that VBlank carries out after each finished frame.
The hardware's interrupt sources and the interrupt handler table.
The IWRAM call layer: the routines the game keeps resident in IWRAM, each at its fixed address,...
The keypad state the VBlank interrupt keeps.
Small statement macros both games use for positions, velocities and bounds.
The map layers' scroll work and the background scroll values.
The heaps: allocating and freeing blocks.
Menu lists: sprites, cursors, the party status window and paged selections.
The reel game's title lettering.
MotionObject, an effect object that moves and draws one sprite.
The 3D projection.
The work pointers in the gWorkSlot table, by name.
Resource numbers, named where their contents are known.
FIELD_AT_OFFSET and the entity and camera views older scene code reads.
Song and sound effect ids, indices into gSound_SongTable.
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
The 3D transform and its stack.
The integer types, TRUE, UNUSED and the fixed-address macros.
unsigned short u16
Definition types.h:13