Alchemy
Loading...
Searching...
No Matches

mind_read.c

Go to the documentation of this file.
1/// @file
2/// Mind Read: scanline waves, shifting colours and flowing particles.
3/// Part of psynergy_effects.c, compiled only through it.
4
6
7/// Work slot 22 of the wave effect, 0x298 bytes (RunSceneTransitionEffect).
8struct WaveFxWork {
9 u16 lines[2][162]; ///< each scanline's offset, two pages written in turn
10 u16 phase; ///< the wave's phase
11 u8 page; ///< the page being written
12 s8 red; ///< the hue as a colour (red, green, blue, 4 to 11 each)
15 u16 hue; ///< hue, 0 to 359 degrees
16 u16 sourceId; ///< the caster
17 u16 targetId; ///< the target
18 u8 delay; ///< frames before it starts
19 u8 counter; ///< particle spawn cycle (0 to 60)
20};
21
22/// Starts the wave effect of caster sourceId on target targetId: fades the
23/// palettes toward a hue that shifts with the frame counter, and starts its
24/// per-frame update (FieldFx_UpdateMindReadWave) after 8 frames.
25///
26/// Abilities: Mind Read (field kind 2).
28 struct WaveFxWork *work;
29
30 work = Runtime_AllocateBlock(22, 0x298);
32 Dma_Fill32(0, work, 0x298);
33 work->hue = ((u32)(gFrameCount << 1) % (u32)360);
36 RGB(work->red, work->green, work->blue) | 0x200000, 1);
38 work->sourceId = x;
39 work->targetId = y;
40 work->delay = 8;
43}
44
45/// Stops the wave effect: restores the caster's colours and the palettes and
46/// releases the effect's work.
48 void *work;
49
50 work = *(void **)((u32)&gBattleBgFxWork);
54 ((struct WaveFxWork *)work)->sourceId),
55 1);
58}
59
60/// Scheduler callback of the wave effect: once its delay has run out, writes
61/// the next page of scanline offsets (a sine wave of 4 pixels either way),
62/// steps the colour fade and the hue, keeps the caster's colours lit, and
63/// every 60 frames sends three particles (object 281) from the target to the
64/// caster, with sound 130.
66 struct WaveFxWork *work = gBattleBgFxWork;
67 u16 *line;
68 u32 scanline;
69 struct FieldActor *caster;
70 struct FieldActor *target;
71 struct FieldActor *particle;
72 struct WaveFxSprite *sprite;
73 struct EffectVector from;
74 struct EffectVector to;
75 struct AnimationMetadata *meta;
76
77 if (work->delay != 0) {
78 work->delay--;
79 return;
80 }
81
82 // The 160 scanlines' offsets, a sine wave of 4 pixels either way, on the
83 // hidden page; then show that page.
84 line = work->lines[work->page ^ 1];
85 for (scanline = 0; scanline < 160; scanline++)
86 *line++ =
87 Trig_Sin(((u32)((work->phase + scanline * 8) << 16) / (u32)160)) >> 14;
88 work->phase += 4;
89 work->page ^= 1;
90 if (work->page != 0) {
92 RGB(work->red, work->green, work->blue) | 0x200000, 1);
95 }
97 (struct MotionObject *)Object_GetById(work->sourceId), 0);
98
99 // At steps 0, 8 and 16 of the cycle, a particle from the target to the
100 // caster.
101 if (work->counter == 0 || work->counter == 8 || work->counter == 16) {
102 caster = Object_GetById(work->sourceId);
103 target = Object_GetById(work->targetId);
104 if (caster != 0 && target != 0) {
105 // From 2 pixels below each one's sprite height (its metadata's boxX).
106 from.x = caster->x.fixed;
109 from.y = caster->y.fixed + ((s8)meta->boxX << 16) - (2 << 16);
110 from.z = caster->z.fixed;
111 to.x = target->x.fixed;
114 to.y = target->y.fixed + ((s8)meta->boxX << 16) - (2 << 16);
115 to.z = target->z.fixed;
116 particle = (struct FieldActor *)Object_CreateFar(281, to.x, to.y, to.z);
117 if (particle != 0) {
118 sprite = (struct WaveFxSprite *)particle->sprite;
119 particle->motionFlags = 0;
120 particle->speed = 0xa3d7; // 0.64 pixels a frame
121 particle->acceleration = 0xa3d7;
122 particle->facing = ArcTan2(from.z - to.z, from.x - to.x);
124 sprite->palette = 0;
125 sprite->mode = 1;
126 Object_SetMoveTargetFar((struct ObjectRuntime *)particle, from.x,
127 from.y, from.z);
128 }
129 }
130 }
131
132 if (work->counter == 0)
134 if (++work->counter > 60)
135 work->counter = 0;
136}
137
138// What Mind Read's wave uses: BG0's scanline scroll, the hue cycle and BG
139// palette 15.
140
141#define MIND_READ_GREY RGB(28, 28, 28)
142
143/// Scheduler callback: restarts the HBlank DMA that writes BG0's horizontal
144/// scroll for each scanline from the wave's shown page.
146 struct WaveFxWork *work = gBattleBgFxWork;
147 if (!work->delay) {
148 u16 *line = work->lines[work->page];
149 volatile u16 *dma = REG_DMA0;
151 dma[5] &= ~DMA_ENABLE;
152 (void)dma[5];
153 // One halfword at each HBlank (repeating, destination reloaded).
155 (volatile u32 *)dma);
156 }
157}
158
159/// Moves the wave's hue on 4 degrees and works out its colour, each channel
160/// 4 to 11.
162 struct WaveFxWork *work = gBattleBgFxWork;
163 s32 r = 0;
164 s32 g = 0;
165 s32 b = 0;
166 s32 offset;
167 u8 *pr;
168 u8 *pg;
169 u8 *pb;
170
171 FieldFx_ComputeHueChannels(work->hue << 16, &r, &g, &b);
172
173 // Squeeze 0 to 31 into 4 to 11; offset walks red, green and blue (0x28b).
174 offset = 0x28b;
175 pr = (u8 *)work + offset;
176 *pr = (r >> 18) + 4;
177 offset += 1;
178 pg = (u8 *)work + offset;
179 *pg = (g >> 18) + 4;
180 offset += 1;
181 pb = (u8 *)work + offset;
182 *pb = (b >> 18) + 4;
183
184 work->hue += 4;
185
186 *pr &= 0x1f;
187 *pg &= 0x1f;
188 *pb &= 0x1f;
189
190 if (work->hue >= 360) {
191 work->hue = 0;
192 }
193}
194
195/// Works out red, green and blue (0 to 31 each, 16.16) for a hue in degrees
196/// (16.16).
198 *r = BattleFx_HueChannelRamp(hue + (120 << 16), 0, 31 << 16);
199 *g = BattleFx_HueChannelRamp(hue, 0, 31 << 16);
200 *b = BattleFx_HueChannelRamp(hue - (120 << 16), 0, 31 << 16);
201}
202
203/// One colour channel's strength at a hue angle: rising from 0 to 60 degrees,
204/// high from 60 to 180, falling from 180 to 240, low elsewhere.
206 angle = Fixed_Remainder(angle, 360 << 16);
207 if (angle < 60 << 16)
208 return Iwram_RatioMulQ14(60 << 16, Iwram_MulQ16(high, angle));
209 if (angle >= 60 << 16 && angle < 180 << 16)
210 return high;
211 if (angle >= 180 << 16 && angle < 240 << 16)
212 return Iwram_RatioMulQ14(60 << 16, Iwram_MulQ16(high, (240 << 16) - angle));
213 return low;
214}
215
216/// The 16.16 remainder of value divided by divisor (0 for a zero divisor).
217s32 Fixed_Remainder(s32 value, s32 divisor) {
218 s32 quot;
219
220 if (divisor == 0)
221 return 0;
222 if (divisor & 0xf0000000)
223 divisor = -divisor;
224 quot = Iwram_RatioMulQ14(divisor, value);
225 // Less the quotient's whole part times divisor.
226 return value - Iwram_MulQ16(quot & 0xffff0000, divisor);
227}
228
229/// Per-frame update: once the object has arrived (no destination left), runs
230/// the script for untargeted objects.
232 struct ObjectRuntime *object = (struct ObjectRuntime *)fieldObject;
233 s32 targetY;
234 s32 targetX;
235
236 targetX = object->targetX;
237 if (targetX == 0x80000000) // no destination
238 {
239 targetY = object->targetY;
240 if ((targetY == targetX) && (object->targetZ == targetY)) {
243 }
244 }
245}
246
247/// Turns colours 1 and 3 to 12 of BG palette 15 grey and starts the BG0
248/// scanline scroll (BattleFx_ArmBg0HBlankDma).
250 volatile u16 *p;
251
252 ((struct UiRenderWork *)gWindowWork[0])->mode = 1;
253 p = &BG_PLTT_COLOR(15, 1);
254 *p = MIND_READ_GREY;
255 p += 2;
256 *p = MIND_READ_GREY;
257 p += 1;
258 *p = MIND_READ_GREY;
259 p += 1;
260 *p = MIND_READ_GREY;
261 p += 1;
262 *p = MIND_READ_GREY;
263 p += 1;
264 *p = MIND_READ_GREY;
265 p += 1;
266 *p = MIND_READ_GREY;
267 p += 1;
268 *p = MIND_READ_GREY;
269 p += 1;
270 *p = MIND_READ_GREY;
271 p += 1;
272 *p = MIND_READ_GREY;
273 p += 1;
274 *p = MIND_READ_GREY;
276}
277
278/// Stops the BG0 scanline scroll and restores BG palette 15.
280 void *work;
281
282 work = gWindowWork[0];
284 // Palette 15's white, black and two greys.
285 BG_PLTT_COLOR(15, 1) = RGB(31, 31, 31);
286 BG_PLTT_COLOR(15, 3) = 0;
287 BG_PLTT_COLOR(15, 11) = RGB(10, 10, 10);
288 BG_PLTT_COLOR(15, 12) = RGB(20, 20, 20);
290 ((struct UiRenderWork *)work)->mode = 0;
291}
292
293#undef MIND_READ_GREY
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
struct WaveFxWork * gBattleBgFxWork
const s32 gBattleFx_UntargetedObjectScript[]
void BattleFx_ApplyColorToTargetBuffer(s32 mode, s32 half)
Sets the colours the buffer moves toward (see BattleFx_BuildBuffer); does nothing without a colour bu...
Definition color.c:398
void BattleFx_StartBufferInterpolation(s32 frames)
Starts moving the shown colours to the target colours over frames frames: sets work->duration,...
Definition color.c:431
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...
Definition dma.h:62
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
Definition dma.h:30
struct ObjectRuntime * Object_CreateFar(s32 id, s32 x, s32 y, s32 z)
Far call to FieldObject_Create.
void ObjectDispatch_InitializeFar(struct DispatchObject *obj, const s32 *script)
void Object_SetMoveTargetFar(struct ObjectRuntime *object, s32 x, s32 y, s32 z)
struct AnimationMetadata * Resource_GetMetadataRecordFar(u32 number)
void AudioCommand_PlayFar(s32 id)
void PaletteGlow_UpdateFar(s32 phase, s32 brightness)
s32 Trig_Sin(s32 angle)
volatile u32 gFrameCount
Frames WaitFrames has finished.
struct GameState gGameState
void * Runtime_AllocateBlock(s32 kind, s32 size)
As Runtime_AllocateHeapBlock, but tries EWRAM first, for blocks that need room more than speed: the b...
Definition heap.c:80
#define REG_BG0HOFS
Definition io_reg.h:149
#define DMA_HBLANK_HALFWORD_PER_LINE
Definition io_reg.h:228
#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 REG_DMA0
Definition io_reg.h:151
#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 BG_PLTT_COLOR(palette, color)
Definition io_reg.h:158
#define DMA_ENABLE
Definition io_reg.h:217
static s32 Iwram_RatioMulQ14(s32 divisor, s32 value)
All calls go through this layer.
Definition iwram_call.h:51
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
s32 ArcTan2(s32 x, s32 y)
Returns the angle of the vector (x, y), in 1/65536 turns, measured from the y axis: 0 along +y,...
Definition math.c:36
void Runtime_ReleaseHeapBlock(s32 slot)
void BattleFx_SetCallbackWhenTargetUnset(union FieldObject *fieldObject)
Per-frame update: once the object has arrived (no destination left), runs the script for untargeted o...
Definition mind_read.c:231
s32 Fixed_Remainder(s32 value, s32 divisor)
The 16.16 remainder of value divided by divisor (0 for a zero divisor).
Definition mind_read.c:217
void FieldFx_ComputeHueChannels(s32 hue, s32 *r, s32 *g, s32 *b)
Works out red, green and blue (0 to 31 each, 16.16) for a hue in degrees (16.16).
Definition mind_read.c:197
void BattleFx_ArmBg0HBlankDma(void)
Scheduler callback: restarts the HBlank DMA that writes BG0's horizontal scroll for each scanline fro...
Definition mind_read.c:145
void Ui_SetBank15PaletteAndClearRenderMode(void)
Stops the BG0 scanline scroll and restores BG palette 15.
Definition mind_read.c:279
void Ui_FillBank15PaletteGrey(void)
Turns colours 1 and 3 to 12 of BG palette 15 grey and starts the BG0 scanline scroll (BattleFx_ArmBg0...
Definition mind_read.c:249
void RunSceneTransitionEffect(s32 x, s32 y)
Starts the wave effect of caster sourceId on target targetId: fades the palettes toward a hue that sh...
Definition mind_read.c:27
s32 BattleFx_HueChannelRamp(s32 angle, s32 low, s32 high)
One colour channel's strength at a hue angle: rising from 0 to 60 degrees, high from 60 to 180,...
Definition mind_read.c:205
void FieldFx_UpdateMindReadWave(void)
Scheduler callback of the wave effect: once its delay has run out, writes the next page of scanline o...
Definition mind_read.c:65
void BattleFx_AdvanceHueCycle(void)
Moves the wave's hue on 4 degrees and works out its colour, each channel 4 to 11.
Definition mind_read.c:161
void BattleFx_FinishSceneAndReleaseHeapBlock(void)
Stops the wave effect: restores the caster's colours and the palettes and releases the effect's work.
Definition mind_read.c:47
#define MIND_READ_GREY
Definition mind_read.c:141
struct ScenePlacement * Scene_FindActorPlacement(s32 id)
Returns the placement of actor id in the scene's placement tables, or NULL: for a party character (0 ...
Definition events.c:14
void Animation_ApplyChildPalette(struct MotionObject *object, s32 palette)
Gives every part of a motion object's sprite (but those at palette 15) palette - 1,...
Definition targets.c:227
void BattleEffect_InitializeSharedScene(void)
Saves the palettes for the effect (once, unless an effect is already shown) and fades them toward one...
Definition setup.c:236
void BattleFx_PrepareBufferInterpolation(void)
Fades the palettes back from an effect's colours to the saved ones (or to palette 0x10001 while an ef...
Definition setup.c:275
What every part of psynergy_effects.c shares: its includes and the macros and types more than one par...
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_130
Definition songs.h:123
u8 gWindowWork[]
An animation's metadata: the sprite's size, scale and offsets, how its frames are drawn and decoded,...
A field object as the object dispatcher's far calls take it.
A world position, as Camera_WorldToScreen converts it to the screen.
Definition battle.h:73
s32 y
16.16 fixed-point pixels
Definition battle.h:75
s32 z
16.16 fixed-point pixels
Definition battle.h:76
s32 x
16.16 fixed-point pixels
Definition battle.h:74
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
s32 speed
speed limit, 16.16 fixed-point pixels per frame
Definition field_obj.h:55
u8 motionFlags
ActorMotionFlag bits; zero is free flight in 3D, and 3 is set on creation.
Definition field_obj.h:83
union FieldCoordinate x
16.16 fixed-point pixels
Definition field_obj.h:35
union FieldCoordinate y
16.16 fixed-point pixels
Definition field_obj.h:36
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
Definition field_obj.h:58
void(*) update(union FieldObject *object)
Called each frame before the object's script, while the object is live.
Definition field_obj.h:116
u8 paletteGlow[2]
window hue (0 to 24), brightness
Definition game_state.h:62
An effect object that moves and draws one sprite: its position, scale, velocity and target,...
Definition motobj.h:20
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
s32 targetZ
16.16 fixed-point pixels; 0x80000000 when unset
s32 targetY
16.16 fixed-point pixels; 0x80000000 when unset
s32 targetX
16.16 fixed-point pixels; 0x80000000 when unset
s16 sprite
The actor's sprite; 0 to 7 are the party's characters, each in its own actor slot,...
Definition field_scene.h:84
The window system's work: the windows' tilemap, the windows, the three text channels,...
Definition window.h:19
u8 mode
Set while Mind Read shows thoughts: round frame corners, colour 8 text with no shadow,...
Definition window.h:35
A particle's sprite, seen as the two fields Douse and Mind Read set on it.
Work slot 22 of the wave effect, 0x298 bytes (RunSceneTransitionEffect).
Definition mind_read.c:8
u16 sourceId
the caster
Definition mind_read.c:16
u8 counter
particle spawn cycle (0 to 60)
Definition mind_read.c:19
s8 red
the hue as a colour (red, green, blue, 4 to 11 each)
Definition mind_read.c:12
u8 page
the page being written
Definition mind_read.c:11
u16 lines[2][162]
each scanline's offset, two pages written in turn
Definition mind_read.c:9
u16 phase
the wave's phase
Definition mind_read.c:10
u16 targetId
the target
Definition mind_read.c:17
u8 delay
frames before it starts
Definition mind_read.c:18
u16 hue
hue, 0 to 359 degrees
Definition mind_read.c:15
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed char s8
Definition types.h:10
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
s32 fixed
16.16 fixed-point pixels
An object on the field, read as an actor or as an effect.