Alchemy
Loading...
Searching...
No Matches

wave_scroll.c

Go to the documentation of this file.
1/// @file
2/// The wavy background: scanline scroll offsets fed by HBlank DMA.
3/// Part of psynergy_effects.c, compiled only through it.
4
6
7/// Scheduler callback for the wavy background: restarts DMA 0 each frame to
8/// copy the current page's BG1 to BG3 scroll offsets into the scroll registers
9/// one scanline at a time. The first line is written directly; the DMA writes
10/// three words at each HBlank from then on.
12 volatile u16 *dma;
13 struct DisplayScrollWork *state;
14 u32 *source;
15 u16 status;
16 u32 control;
17 volatile u32 *destination;
18
19 state = gHBlankScrollWork;
20 source = (u32 *)state->rows[state->page];
21
22 dma = REG_DMA0;
23 destination = (volatile u32 *)&REG_BG1HOFS;
24 status = dma[5];
25 control = status & (u16)~DMA_START_TIMING_DRQ_REPEAT;
26 dma[5] = control;
27 status = dma[5];
28 control = status & (u16)~DMA_ENABLE;
29 dma[5] = control;
30 (void)dma[5];
31
32 *destination = *source++;
33 *destination = *source++;
34 *destination = *source++;
35
36 // Enabled, at HBlank, repeating, 32-bit, destination reloaded: 3 words.
37 control = 0xa6600003;
38 Dma_Set(source, (void *)destination, control, (volatile u32 *)dma);
39}
40
41/// Scheduler callback for the wavy background: fills the hidden page with each
42/// scanline's BG3, BG2 and BG1 offsets, the scroll plus a sine wave for x and
43/// for y (an axis with no step stays flat), then shows that page.
46 s32 x3 = (s16)gBgScroll[3].x;
47 s32 y3 = (s16)gBgScroll[3].y;
48 s32 x2 = (s16)gBgScroll[2].x;
49 s32 y2 = (s16)gBgScroll[2].y;
50 s32 x1 = (s16)gBgScroll[1].x;
51 s32 y1 = (s16)gBgScroll[1].y;
52 u16 *row;
53 s32 step;
54 s32 phase;
55 s32 amplitude;
56 s32 scanline;
57 u16 wave;
58
59 row = &work->rows[work->page ^ 1][0][0].x;
60 step = work->stepX;
61 phase = (work->frame + (u16)y3) * work->freqX;
62 if (step == 0) {
63 for (scanline = 0; scanline != 160; scanline++) {
64 row[scanline * 6] = x3;
65 row[scanline * 6 + 2] = x2;
66 row[scanline * 6 + 4] = x1;
67 }
68 } else {
69 u16 a = x3;
70 u16 b = x2;
71 u16 c = x1;
72
73 amplitude = work->ampX;
74 for (scanline = 0; scanline != 160; scanline++) {
75 wave = Iwram_MulQ16(gDisplayScroll_WaveSine[(phase >> 16) & 255],
76 amplitude) /
77 256;
78 *row = a + wave;
79 row += 2;
80 *row = b + wave;
81 row += 2;
82 *row = c + wave;
83 row += 2;
84 phase += step;
85 }
86 }
87 row = &work->rows[work->page ^ 1][0][0].y;
88 step = work->stepY;
89 phase = (work->frame + (u16)y3) * work->freqY;
90 if (step == 0) {
91 for (scanline = 0; scanline != 160; scanline++) {
92 row[scanline * 6] = y3;
93 row[scanline * 6 + 2] = y2;
94 row[scanline * 6 + 4] = y1;
95 }
96 } else {
97 u16 a = y3;
98 u16 b = y2;
99 u16 c = y1;
100
101 amplitude = work->ampY;
102 for (scanline = 0; scanline != 160; scanline++) {
103 wave = Iwram_MulQ16(gDisplayScroll_WaveSine[(phase >> 16) & 255],
104 amplitude) /
105 256;
106 *row = a + wave;
107 row += 2;
108 *row = b + wave;
109 row += 2;
110 *row = c + wave;
111 row += 2;
112 phase += step;
113 }
114 }
115 work->frame++;
116 work->page ^= 1;
117}
118
119// The shared source that starts the wavy background, at its place in the ROM.
121
122/// Stops the wavy background: removes its two callbacks and stops DMA 0.
124 volatile u16 *dma0;
125
128 dma0 = REG_DMA0;
129 dma0[5] = (u16)~DMA_START_TIMING_DRQ_REPEAT & dma0[5];
130 dma0[5] = (u16)~DMA_ENABLE & dma0[5];
131 (void)dma0[5];
132}
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
const s16 gDisplayScroll_WaveSine[256]
Sine times 4096, 256 steps to a turn.
Definition fxdata.c:347
#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 REG_BG1HOFS
Definition io_reg.h:49
#define DMA_ENABLE
Definition io_reg.h:217
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
struct BgScroll gBgScroll[]
What every part of psynergy_effects.c shares: its includes and the macros and types more than one par...
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
struct DisplayScrollWork * gHBlankScrollWork
u16 y
pixels
Definition map_scroll.h:65
The wavy background's work: two pages of BG1 to BG3 scroll offsets for each of the 160 scanlines,...
Definition scroll.h:12
struct BgScroll rows[2][160][3]
per page and scanline: BG3, BG2, BG1
Definition scroll.h:13
s32 freqX
phase per frame and per BG3 row, 16.16 wave table entries
Definition scroll.h:18
u8 page
the page the HBlank DMA shows; the other is built
Definition scroll.h:14
s32 stepY
16.16 wave table entries a scanline, 256 a cycle
Definition scroll.h:21
s32 ampX
16.16 scale on the sine entry, which is then divided by 256
Definition scroll.h:22
u16 frame
frames built so far, added to BG3's y for the wave's phase
Definition scroll.h:16
s32 ampY
16.16 scale on the sine entry, which is then divided by 256
Definition scroll.h:23
s32 freqY
phase per frame and per BG3 row, 16.16 wave table entries
Definition scroll.h:19
s32 stepX
16.16 wave table entries a scanline, 256 a cycle
Definition scroll.h:20
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
void DisplayScroll_DisarmHBlankDma(void)
Stops the wavy background: removes its two callbacks and stops DMA 0.
void DisplayScroll_ArmHBlankDma(void)
Scheduler callback for the wavy background: restarts DMA 0 each frame to copy the current page's BG1 ...
Definition wave_scroll.c:11
void DisplayScroll_BuildAndSwapHBlankPage(void)
Scheduler callback for the wavy background: fills the hidden page with each scanline's BG3,...
Definition wave_scroll.c:44