rev |
line source |
paulo@0
|
1 /*---------------------------------------------------------------------------------
|
paulo@0
|
2
|
paulo@0
|
3 LOCKJAW Tetromino Game: ARM7 sound code
|
paulo@0
|
4
|
paulo@0
|
5 based on
|
paulo@0
|
6 default ARM7 core
|
paulo@0
|
7
|
paulo@0
|
8 Copyright (C) 2007
|
paulo@0
|
9 Damian Yerrick (tepples)
|
paulo@0
|
10
|
paulo@0
|
11 This software is provided 'as-is', without any express or implied
|
paulo@0
|
12 warranty. In no event will the authors be held liable for any
|
paulo@0
|
13 damages arising from the use of this software.
|
paulo@0
|
14
|
paulo@0
|
15 Permission is granted to anyone to use this software for any
|
paulo@0
|
16 purpose, including commercial applications, and to alter it and
|
paulo@0
|
17 redistribute it freely, subject to the following restrictions:
|
paulo@0
|
18
|
paulo@0
|
19 1. The origin of this software must not be misrepresented; you
|
paulo@0
|
20 must not claim that you wrote the original software. If you use
|
paulo@0
|
21 this software in a product, an acknowledgment in the product
|
paulo@0
|
22 documentation would be appreciated but is not required.
|
paulo@0
|
23 2. Altered source versions must be plainly marked as such, and
|
paulo@0
|
24 must not be misrepresented as being the original software.
|
paulo@0
|
25 3. This notice may not be removed or altered from any source
|
paulo@0
|
26 distribution.
|
paulo@0
|
27
|
paulo@0
|
28 ---------------------------------------------------------------------------------*/
|
paulo@0
|
29 #include <nds.h>
|
paulo@0
|
30 #include <sys/types.h>
|
paulo@0
|
31
|
paulo@0
|
32 extern const unsigned short midi2psgFreq[120];
|
paulo@0
|
33
|
paulo@0
|
34 #define C(octave) (octave * 12 + 0)
|
paulo@0
|
35 #define CS(octave) (octave * 12 + 1)
|
paulo@0
|
36 #define D(octave) (octave * 12 + 2)
|
paulo@0
|
37 #define DS(octave) (octave * 12 + 3)
|
paulo@0
|
38 #define E(octave) (octave * 12 + 4)
|
paulo@0
|
39 #define F(octave) (octave * 12 + 5)
|
paulo@0
|
40 #define FS(octave) (octave * 12 + 6)
|
paulo@0
|
41 #define G(octave) (octave * 12 + 7)
|
paulo@0
|
42 #define GS(octave) (octave * 12 + 8)
|
paulo@0
|
43 #define A(octave) (octave * 12 + 9)
|
paulo@0
|
44 #define AS(octave) (octave * 12 + 10)
|
paulo@0
|
45 #define B(octave) (octave * 12 + 11)
|
paulo@0
|
46
|
paulo@0
|
47
|
paulo@0
|
48 #define N_MUSIC_CHANNELS 2
|
paulo@0
|
49
|
paulo@0
|
50 static unsigned short chNote[N_MUSIC_CHANNELS];
|
paulo@0
|
51 static unsigned char chVol[N_MUSIC_CHANNELS];
|
paulo@0
|
52
|
paulo@0
|
53
|
paulo@0
|
54 static const unsigned char startVol[N_MUSIC_CHANNELS] = {32, 30};
|
paulo@0
|
55 static const unsigned char fade[N_MUSIC_CHANNELS] = {0, 1};
|
paulo@0
|
56 static const unsigned char chDuty[N_MUSIC_CHANNELS] = {0, 3};
|
paulo@0
|
57
|
paulo@0
|
58 static const signed char bassLine[64] = {
|
paulo@0
|
59 A(2), 0, A(3), 0, -1, 0, A(2), 0,
|
paulo@0
|
60 A(3), 0, -1, 0, 0, 0, 0, 0,
|
paulo@0
|
61 0, 0, 0, 0, 0, 0, 0, 0,
|
paulo@0
|
62 C(3), 0, C(4), 0, G(2), 0, G(3), 0,
|
paulo@0
|
63 A(2), 0, A(3), 0, -1, 0, A(2), 0,
|
paulo@0
|
64 A(3), 0, -1, 0, 0, 0, 0, 0,
|
paulo@0
|
65 0, 0, 0, 0, 0, 0, 0, 0,
|
paulo@0
|
66 C(3), 0, C(4), 0, G(2), 0, G(3), 0,
|
paulo@0
|
67 };
|
paulo@0
|
68
|
paulo@0
|
69 static const signed char mel1[64] = {
|
paulo@0
|
70 E(6), 0, 0, 0, B(5), 0, C(6), 0,
|
paulo@0
|
71 D(6), 0, 0, 0, C(6), 0, B(5), 0,
|
paulo@0
|
72 A(5), 0, 0, 0, A(5), 0, C(6), 0,
|
paulo@0
|
73 E(6), 0, 0, 0, D(6), 0, C(6), 0,
|
paulo@0
|
74 B(5), 0, 0, 0, 0, 0, C(6), 0,
|
paulo@0
|
75 D(6), 0, 0, 0, E(6), 0, 0, 0,
|
paulo@0
|
76 C(6), 0, 0, 0, A(5), 0, 0, 0,
|
paulo@0
|
77 A(5)
|
paulo@0
|
78 };
|
paulo@0
|
79
|
paulo@0
|
80 static const signed char mel2[64] = {
|
paulo@0
|
81 0, 0, D(6), 0, 0, 0, F(6), 0,
|
paulo@0
|
82 A(6), 0, 0, 0, G(6), 0, F(6), 0,
|
paulo@0
|
83 E(6), 0, 0, 0, 0, 0, C(6), 0,
|
paulo@0
|
84 E(6), 0, 0, 0, D(6), 0, C(6), 0,
|
paulo@0
|
85 B(5), 0, 0, 0, B(5), 0, C(6), 0,
|
paulo@0
|
86 D(6), 0, 0, 0, E(6), 0, 0, 0,
|
paulo@0
|
87 C(6), 0, 0, 0, A(5), 0, 0, 0,
|
paulo@0
|
88 A(5)
|
paulo@0
|
89 };
|
paulo@0
|
90
|
paulo@0
|
91 static const signed char *const scripts[4][N_MUSIC_CHANNELS] = {
|
paulo@0
|
92 { bassLine, mel1 },
|
paulo@0
|
93 { bassLine, mel1 },
|
paulo@0
|
94 { bassLine, mel2 },
|
paulo@0
|
95 { bassLine, mel2 }
|
paulo@0
|
96 };
|
paulo@0
|
97
|
paulo@0
|
98 int order = 0;
|
paulo@0
|
99 char ticksLeft = 1;
|
paulo@0
|
100 char row = 0;
|
paulo@0
|
101 char musicPaused = 1;
|
paulo@0
|
102
|
paulo@0
|
103 /*
|
paulo@0
|
104 * Plays a repeating drum track and bass track.
|
paulo@0
|
105 */
|
paulo@0
|
106 void ljMusic(void) {
|
paulo@0
|
107 if (musicPaused) {
|
paulo@0
|
108 for (int ch = 0; ch < N_MUSIC_CHANNELS; ++ch) {
|
paulo@0
|
109 chVol[ch] = 0;
|
paulo@0
|
110 }
|
paulo@0
|
111 } else if (--ticksLeft <= 0) {
|
paulo@0
|
112 ticksLeft += 6;
|
paulo@0
|
113 for (int ch = 0; ch < N_MUSIC_CHANNELS; ++ch) {
|
paulo@0
|
114 const signed char *script = scripts[order][ch];
|
paulo@0
|
115 int note = script ? script[(int)row] : 0;
|
paulo@0
|
116 if (note < 0) {
|
paulo@0
|
117 chVol[ch] = 0;
|
paulo@0
|
118 } else if (note > 0) {
|
paulo@0
|
119 chVol[ch] = startVol[ch];
|
paulo@0
|
120 chNote[ch] = midi2psgFreq[note];
|
paulo@0
|
121 }
|
paulo@0
|
122 }
|
paulo@0
|
123 ++row;
|
paulo@0
|
124 if (row >= 64) {
|
paulo@0
|
125 row = 0;
|
paulo@0
|
126 ++order;
|
paulo@0
|
127 if (order == 4) {
|
paulo@0
|
128 order = 0;
|
paulo@0
|
129 }
|
paulo@0
|
130 }
|
paulo@0
|
131 }
|
paulo@0
|
132
|
paulo@0
|
133
|
paulo@0
|
134 // Play notes
|
paulo@0
|
135 for (int ch = 0; ch < N_MUSIC_CHANNELS; ++ch) {
|
paulo@0
|
136 SCHANNEL_CR(8 + ch) = SCHANNEL_ENABLE | SOUND_FORMAT_PSG | SOUND_PAN(64)
|
paulo@0
|
137 | (chDuty[ch] << 24) | chVol[ch];
|
paulo@0
|
138 SCHANNEL_TIMER(8 + ch) = chNote[ch];
|
paulo@0
|
139
|
paulo@0
|
140 // update volumes
|
paulo@0
|
141 if (chVol[ch] > fade[ch]) {
|
paulo@0
|
142 chVol[ch] -= fade[ch];
|
paulo@0
|
143 } else {
|
paulo@0
|
144 chVol[ch] = 0;
|
paulo@0
|
145 }
|
paulo@0
|
146 }
|
paulo@0
|
147 }
|
paulo@0
|
148
|
paulo@0
|
149 #define FX(note, volume, duty) ((note) | ((volume) << 7) | ((duty) << 14))
|
paulo@0
|
150
|
paulo@0
|
151 static const u16 rotateEffect[] = {
|
paulo@0
|
152 0, 6,
|
paulo@0
|
153 FX(A(5), 32, 1), FX(A(5), 8, 1),
|
paulo@0
|
154 FX(D(6), 32, 1), FX(D(6), 8, 1),
|
paulo@0
|
155 FX(G(6), 32, 1), FX(G(6), 8, 1)
|
paulo@0
|
156 };
|
paulo@0
|
157
|
paulo@0
|
158 static const u16 moveEffect[] = {
|
paulo@0
|
159 0, 2,
|
paulo@0
|
160 FX(A(6), 32, 1), FX(A(6), 8, 1)
|
paulo@0
|
161 };
|
paulo@0
|
162
|
paulo@0
|
163 static const u16 landEffect[] = {
|
paulo@0
|
164 0, 8,
|
paulo@0
|
165 FX(C(4), 64, 3), FX(GS(3), 56, 3),
|
paulo@0
|
166 FX(F(3), 48, 3), FX(D(3), 40, 3),
|
paulo@0
|
167 FX(C(3), 32, 3), FX(B(2), 24, 3),
|
paulo@0
|
168 FX(C(3), 16, 3), FX(B(2), 8, 3),
|
paulo@0
|
169 };
|
paulo@0
|
170
|
paulo@0
|
171 static const u16 lockEffect[] = {
|
paulo@0
|
172 1, 2,
|
paulo@0
|
173 FX(C(8), 16, 1), FX(C(8), 4, 1)
|
paulo@0
|
174 };
|
paulo@0
|
175
|
paulo@0
|
176 static const u16 lineEffect[] = {
|
paulo@0
|
177 0, 15,
|
paulo@0
|
178 FX(C(6), 64, 2), FX(DS(6), 59, 2), FX(F(6), 54, 2),
|
paulo@0
|
179 FX(C(6), 49, 2), FX(D(6), 44, 2), FX(F(6), 39, 2),
|
paulo@0
|
180 FX(C(6), 34, 3), FX(DS(6), 29, 3), FX(F(6), 24, 3),
|
paulo@0
|
181 FX(C(6), 20, 3), FX(D(6), 16, 3), FX(F(6), 12, 3),
|
paulo@0
|
182 FX(C(6), 9, 3), FX(DS(6), 6, 3), FX(F(6), 3, 3)
|
paulo@0
|
183 };
|
paulo@0
|
184
|
paulo@0
|
185 static const u16 homerEffect[] = {
|
paulo@0
|
186 0, 25,
|
paulo@0
|
187 FX(C(6), 64, 2), FX(DS(6), 59, 2), FX(F(6), 54, 2),
|
paulo@0
|
188 FX(C(6), 49, 2), FX(D(6), 44, 2), FX(F(6), 39, 2),
|
paulo@0
|
189 FX(C(6), 34, 3), FX(DS(6), 29, 3), FX(F(6), 24, 3),
|
paulo@0
|
190 FX(C(6), 20, 3),
|
paulo@0
|
191 FX(DS(6), 64, 2), FX(FS(6), 59, 2), FX(GS(6), 54, 2),
|
paulo@0
|
192 FX(DS(6), 49, 2), FX(F(6), 44, 2), FX(GS(6), 39, 2),
|
paulo@0
|
193 FX(DS(6), 34, 3), FX(FS(6), 29, 3), FX(GS(6), 24, 3),
|
paulo@0
|
194 FX(DS(6), 20, 3), FX(F(6), 16, 3), FX(GS(6), 12, 3),
|
paulo@0
|
195 FX(DS(6), 9, 3), FX(F(6), 6, 3), FX(GS(6), 3, 3)
|
paulo@0
|
196 };
|
paulo@0
|
197
|
paulo@0
|
198 static const u16 streakEffect[] = {
|
paulo@0
|
199 0, 35,
|
paulo@0
|
200 FX(C(6), 64, 2), FX(DS(6), 59, 2), FX(F(6), 54, 2),
|
paulo@0
|
201 FX(C(6), 49, 2), FX(D(6), 44, 2), FX(F(6), 39, 2),
|
paulo@0
|
202 FX(C(6), 34, 3), FX(DS(6), 29, 3), FX(F(6), 24, 3),
|
paulo@0
|
203 FX(C(6), 20, 3),
|
paulo@0
|
204 FX(DS(6), 64, 2), FX(FS(6), 59, 2), FX(GS(6), 54, 2),
|
paulo@0
|
205 FX(DS(6), 49, 2), FX(F(6), 44, 2), FX(GS(6), 39, 2),
|
paulo@0
|
206 FX(DS(6), 34, 3), FX(FS(6), 29, 3), FX(GS(6), 24, 3),
|
paulo@0
|
207 FX(DS(6), 20, 3),
|
paulo@0
|
208 FX(FS(6), 64, 2), FX(A(6), 59, 2), FX(B(6), 54, 2),
|
paulo@0
|
209 FX(FS(6), 49, 2), FX(GS(6), 44, 2), FX(B(6), 39, 2),
|
paulo@0
|
210 FX(FS(6), 34, 3), FX(A(6), 29, 3), FX(B(6), 24, 3),
|
paulo@0
|
211 FX(FS(6), 20, 3), FX(GS(6), 16, 3), FX(B(6), 12, 3),
|
paulo@0
|
212 FX(FS(6), 9, 3), FX(GS(6), 6, 3), FX(B(6), 3, 3)
|
paulo@0
|
213 };
|
paulo@0
|
214
|
paulo@0
|
215 static const u16 holdEffect[] = {
|
paulo@0
|
216 1, 10,
|
paulo@0
|
217 FX(E(5), 20, 0), FX(G(5), 25, 0),
|
paulo@0
|
218 FX(B(5), 30, 0), FX(B(5), 30, 0),
|
paulo@0
|
219 FX(G(5), 28, 0), FX(E(5), 24, 0),
|
paulo@0
|
220 FX(D(5), 20, 0), FX(C(5), 15, 0),
|
paulo@0
|
221 FX(C(5), 10, 0), FX(C(5), 5, 0)
|
paulo@0
|
222 };
|
paulo@0
|
223
|
paulo@0
|
224
|
paulo@0
|
225 static const u16 irsEffect[] = {
|
paulo@0
|
226 0, 12,
|
paulo@0
|
227 FX(CS(7), 40, 3), FX(CS(7), 40, 3),
|
paulo@0
|
228 FX(FS(7), 40, 3), FX(FS(7), 40, 3),
|
paulo@0
|
229 FX(B(7), 40, 3), FX(B(7), 35, 3),
|
paulo@0
|
230 FX(B(7), 30, 3), FX(B(7), 25, 3),
|
paulo@0
|
231 FX(B(7), 20, 3), FX(B(7), 15, 3),
|
paulo@0
|
232 FX(B(7), 10, 3), FX(B(7), 5, 3),
|
paulo@0
|
233 };
|
paulo@0
|
234
|
paulo@0
|
235 static const u16 countEffect[] = {
|
paulo@0
|
236 0, 14,
|
paulo@0
|
237 FX(D(5), 64, 0), FX(D(5), 64, 0),
|
paulo@0
|
238 FX(CS(5), 64, 0), FX(CS(5), 64, 0),
|
paulo@0
|
239 FX(C(5), 64, 1), FX(C(5), 64, 1),
|
paulo@0
|
240 FX(B(4), 64, 1), FX(AS(4), 64, 1),
|
paulo@0
|
241 FX(A(4), 64, 2), FX(GS(4), 64, 2),
|
paulo@0
|
242 FX(GS(4), 64, 3), FX(G(4), 48, 3),
|
paulo@0
|
243 FX(G(4), 32, 3), FX(G(4), 16, 3),
|
paulo@0
|
244 };
|
paulo@0
|
245
|
paulo@0
|
246 static const u16 winEffect1[] = {
|
paulo@0
|
247 0, 54,
|
paulo@0
|
248 FX(C(6), 32, 2), FX(C(6), 48, 1), FX(C(6), 48, 1), FX(C(6), 48, 1),
|
paulo@0
|
249 FX(C(6), 32, 2), 0, 0, 0, 0,
|
paulo@0
|
250 FX(AS(5), 32, 2), FX(AS(5), 48, 1), FX(AS(5), 48, 1), FX(AS(5), 48, 1),
|
paulo@0
|
251 FX(AS(5), 32, 2), 0, 0, 0, 0,
|
paulo@0
|
252 FX(C(6), 32, 2), FX(C(6), 48, 1), FX(C(6), 48, 1), FX(C(6), 48, 1),
|
paulo@0
|
253 FX(D(6), 32, 2), 0, 0, 0, 0,
|
paulo@0
|
254
|
paulo@0
|
255 FX(D(6), 32, 2), FX(D(6), 48, 1), FX(D(6), 48, 1), FX(D(6), 48, 1),
|
paulo@0
|
256 FX(D(6), 47, 1), FX(D(6), 46, 1), FX(D(6), 45, 1), FX(D(6), 44, 1),
|
paulo@0
|
257 FX(D(6), 43, 1), FX(D(6), 42, 1), FX(D(6), 41, 1), FX(D(6), 40, 1),
|
paulo@0
|
258 FX(D(6), 39, 1), FX(D(6), 38, 1), FX(D(6), 37, 1), FX(D(6), 36, 1),
|
paulo@0
|
259 FX(D(6), 35, 1), FX(D(6), 34, 1), FX(D(6), 33, 1), FX(D(6), 32, 1),
|
paulo@0
|
260 FX(D(6), 31, 1), FX(D(6), 30, 1), FX(D(6), 29, 1), FX(D(6), 28, 1),
|
paulo@0
|
261 FX(D(6), 27, 1), FX(D(6), 26, 1), FX(D(6), 25, 1), FX(D(6), 24, 1),
|
paulo@0
|
262 FX(D(6), 18, 2), FX(D(6), 12, 2), FX(D(6), 6, 2)
|
paulo@0
|
263 };
|
paulo@0
|
264
|
paulo@0
|
265 static const u16 winEffect2[] = {
|
paulo@0
|
266 0, 54,
|
paulo@0
|
267 FX(E(6), 32, 2), FX(E(6), 48, 1), FX(E(6), 48, 1), FX(E(6), 48, 1),
|
paulo@0
|
268 FX(E(6), 32, 2), 0, 0, 0, 0,
|
paulo@0
|
269 FX(D(6), 32, 2), FX(D(6), 48, 1), FX(D(6), 48, 1), FX(D(6), 48, 1),
|
paulo@0
|
270 FX(D(6), 32, 2), 0, 0, 0, 0,
|
paulo@0
|
271 FX(E(6), 32, 2), FX(E(6), 48, 1), FX(E(6), 48, 1), FX(E(6), 48, 1),
|
paulo@0
|
272 FX(E(6), 32, 2), 0, 0, 0, 0,
|
paulo@0
|
273
|
paulo@0
|
274 FX(FS(6), 32, 2), FX(FS(6), 48, 1), FX(FS(6), 48, 1), FX(FS(6), 48, 1),
|
paulo@0
|
275 FX(FS(6), 47, 1), FX(FS(6), 46, 1), FX(FS(6), 45, 1), FX(FS(6), 44, 1),
|
paulo@0
|
276 FX(FS(6), 43, 1), FX(FS(6), 42, 1), FX(FS(6), 41, 1), FX(FS(6), 40, 1),
|
paulo@0
|
277 FX(FS(6), 39, 1), FX(FS(6), 38, 1), FX(FS(6), 37, 1), FX(FS(6), 36, 1),
|
paulo@0
|
278 FX(FS(6), 35, 1), FX(FS(6), 34, 1), FX(FS(6), 33, 1), FX(FS(6), 32, 1),
|
paulo@0
|
279 FX(FS(6), 31, 1), FX(FS(6), 30, 1), FX(FS(6), 29, 1), FX(FS(6), 28, 1),
|
paulo@0
|
280 FX(FS(6), 27, 1), FX(FS(6), 26, 1), FX(FS(6), 25, 1), FX(FS(6), 24, 1),
|
paulo@0
|
281 FX(FS(6), 18, 2), FX(FS(6), 12, 2), FX(FS(6), 6, 2)
|
paulo@0
|
282 };
|
paulo@0
|
283
|
paulo@0
|
284 static const u16 dieEffect1[] = {
|
paulo@0
|
285 0, 60,
|
paulo@0
|
286 FX(E(3), 60, 2), FX(E(3), 59, 2), FX(E(3), 58, 2), FX(E(3), 57, 2),
|
paulo@0
|
287 FX(E(3), 56, 2), FX(E(3), 55, 2), FX(E(3), 54, 2), FX(E(3), 53, 2),
|
paulo@0
|
288 FX(E(3), 52, 2), FX(E(3), 51, 2), FX(E(3), 50, 2), FX(E(3), 49, 2),
|
paulo@0
|
289 FX(E(3), 48, 2), FX(E(3), 47, 2), FX(E(3), 46, 2), FX(E(3), 45, 2),
|
paulo@0
|
290 FX(E(3), 44, 2), FX(E(3), 43, 2), FX(E(3), 42, 2), FX(E(3), 41, 2),
|
paulo@0
|
291 FX(E(3), 40, 2), FX(E(3), 39, 2), FX(E(3), 38, 2), FX(E(3), 37, 2),
|
paulo@0
|
292 FX(E(3), 36, 2), FX(E(3), 35, 2), FX(E(3), 34, 2), FX(E(3), 33, 2),
|
paulo@0
|
293 FX(E(3), 32, 2), FX(E(3), 31, 2), FX(E(3), 30, 2), FX(E(3), 29, 2),
|
paulo@0
|
294 FX(E(3), 28, 2), FX(E(3), 27, 2), FX(E(3), 26, 2), FX(E(3), 25, 2),
|
paulo@0
|
295 FX(E(3), 24, 2), FX(E(3), 23, 2), FX(E(3), 22, 2), FX(E(3), 21, 2),
|
paulo@0
|
296 FX(E(3), 20, 2), FX(E(3), 19, 2), FX(E(3), 18, 2), FX(E(3), 17, 2),
|
paulo@0
|
297 FX(E(3), 16, 2), FX(E(3), 15, 2), FX(E(3), 14, 2), FX(E(3), 13, 2),
|
paulo@0
|
298 FX(E(3), 12, 2), FX(E(3), 11, 2), FX(E(3), 10, 2), FX(E(3), 9, 2),
|
paulo@0
|
299 FX(E(3), 8, 2), FX(E(3), 7, 2), FX(E(3), 6, 2), FX(E(3), 5, 2),
|
paulo@0
|
300 FX(E(3), 4, 2), FX(E(3), 3, 2), FX(E(3), 2, 2), FX(E(3), 1, 2)
|
paulo@0
|
301 };
|
paulo@0
|
302
|
paulo@0
|
303 static const u16 dieEffect2[] = {
|
paulo@0
|
304 1, 60,
|
paulo@0
|
305 FX(E(4), 60, 2), FX(B(3), 59, 2), FX(E(3), 58, 2), FX(E(3), 57, 2),
|
paulo@0
|
306 FX(E(3), 56, 2), FX(E(3), 55, 2), FX(E(3), 54, 2), FX(E(3), 53, 2),
|
paulo@0
|
307 FX(E(3), 52, 2), FX(E(3), 51, 2), FX(E(3), 50, 2), FX(E(3), 49, 2),
|
paulo@0
|
308 FX(E(3), 48, 2), FX(E(3), 47, 2), FX(E(3), 46, 2), FX(E(3), 45, 2),
|
paulo@0
|
309 FX(E(3), 44, 2), FX(E(3), 43, 2), FX(E(3), 42, 2), FX(E(3), 41, 2),
|
paulo@0
|
310 FX(E(3), 40, 2), FX(E(3), 39, 2), FX(E(3), 38, 2), FX(E(3), 37, 2),
|
paulo@0
|
311 FX(E(3), 36, 2), FX(E(3), 35, 2), FX(E(3), 34, 2), FX(E(3), 33, 2),
|
paulo@0
|
312 FX(E(3), 32, 2), FX(E(3), 31, 2), FX(E(3), 30, 2), FX(E(3), 29, 2),
|
paulo@0
|
313 FX(E(3), 28, 2), FX(E(3), 27, 2), FX(E(3), 26, 2), FX(E(3), 25, 2),
|
paulo@0
|
314 FX(E(3), 24, 2), FX(E(3), 23, 2), FX(E(3), 22, 2), FX(E(3), 21, 2),
|
paulo@0
|
315 FX(E(3), 20, 2), FX(E(3), 19, 2), FX(E(3), 18, 2), FX(E(3), 17, 2),
|
paulo@0
|
316 FX(E(3), 16, 2), FX(E(3), 15, 2), FX(E(3), 14, 2), FX(E(3), 13, 2),
|
paulo@0
|
317 FX(E(3), 12, 2), FX(E(3), 11, 2), FX(E(3), 10, 2), FX(E(3), 9, 2),
|
paulo@0
|
318 FX(E(3), 8, 2), FX(E(3), 7, 2), FX(E(3), 6, 2), FX(E(3), 5, 2),
|
paulo@0
|
319 FX(E(3), 4, 2), FX(E(3), 3, 2), FX(E(3), 2, 2), FX(E(3), 1, 2)
|
paulo@0
|
320 };
|
paulo@0
|
321
|
paulo@0
|
322 static const u16 *effects[32] = {
|
paulo@0
|
323 rotateEffect,
|
paulo@0
|
324 moveEffect,
|
paulo@0
|
325 NULL, // drop: not used
|
paulo@0
|
326 landEffect,
|
paulo@0
|
327 lockEffect,
|
paulo@0
|
328 lineEffect,
|
paulo@0
|
329 homerEffect,
|
paulo@0
|
330 streakEffect,
|
paulo@0
|
331 NULL, // spawn
|
paulo@0
|
332 holdEffect, // hold
|
paulo@0
|
333 irsEffect, // irs
|
paulo@0
|
334 NULL, // 4x4 square
|
paulo@0
|
335 NULL, NULL, NULL, NULL, // unused
|
paulo@0
|
336 dieEffect1, dieEffect2
|
paulo@0
|
337 };
|
paulo@0
|
338
|
paulo@0
|
339
|
paulo@0
|
340
|
paulo@0
|
341 static const u16 *fxPtr[5];
|
paulo@0
|
342 static u8 fxLen[5];
|
paulo@0
|
343 static s8 lastCD;
|
paulo@0
|
344
|
paulo@0
|
345
|
paulo@0
|
346
|
paulo@0
|
347 static void startEffect(const u16 *s) {
|
paulo@0
|
348
|
paulo@0
|
349 // skip effects that lack an actual effect
|
paulo@0
|
350 if (!s) {
|
paulo@0
|
351 return;
|
paulo@0
|
352 }
|
paulo@0
|
353
|
paulo@0
|
354 unsigned int type = s[0];
|
paulo@0
|
355 unsigned int len = s[1];
|
paulo@0
|
356 unsigned int min = 0;
|
paulo@0
|
357 unsigned int max = 2;
|
paulo@0
|
358
|
paulo@0
|
359 if (type > 0) {
|
paulo@0
|
360 min = 3;
|
paulo@0
|
361 max = 4;
|
paulo@0
|
362 }
|
paulo@0
|
363
|
paulo@0
|
364 // prepare to kill the channel with the shortest time remaining
|
paulo@0
|
365 unsigned int shortestLen = fxLen[min];
|
paulo@0
|
366 unsigned int shortestCh = min;
|
paulo@0
|
367 for (int ch = min + 1; ch <= max; ++ch) {
|
paulo@0
|
368 if (fxLen[ch] < shortestLen) {
|
paulo@0
|
369 shortestLen = fxLen[ch];
|
paulo@0
|
370 shortestCh = ch;
|
paulo@0
|
371 }
|
paulo@0
|
372 }
|
paulo@0
|
373
|
paulo@0
|
374 // if the channel is suitable, kill it
|
paulo@0
|
375 if (shortestLen < len) {
|
paulo@0
|
376 fxPtr[shortestCh] = s + 2;
|
paulo@0
|
377 fxLen[shortestCh] = len;
|
paulo@0
|
378 }
|
paulo@0
|
379 }
|
paulo@0
|
380
|
paulo@0
|
381 static void pollEffects(void) {
|
paulo@0
|
382 for (int ch = 0; ch < 5; ++ch) {
|
paulo@0
|
383 unsigned int note = 36;
|
paulo@0
|
384 unsigned int vol = 0;
|
paulo@0
|
385 unsigned int duty = 0;
|
paulo@0
|
386 if (fxLen[ch] > 0) {
|
paulo@0
|
387 unsigned int data = *fxPtr[ch]++;
|
paulo@0
|
388 duty = (data >> 14) & 0x03;
|
paulo@0
|
389 vol = (data >> 7) & 0x7F;
|
paulo@0
|
390 note = data & 0x7F;
|
paulo@0
|
391 --fxLen[ch];
|
paulo@0
|
392 }
|
paulo@0
|
393 SCHANNEL_CR(11 + ch) = SCHANNEL_ENABLE | SOUND_FORMAT_PSG | SOUND_PAN(64)
|
paulo@0
|
394 | (duty << 24) | vol;
|
paulo@0
|
395 SCHANNEL_TIMER(11 + ch) = midi2psgFreq[note];
|
paulo@0
|
396 }
|
paulo@0
|
397 }
|
paulo@0
|
398
|
paulo@0
|
399 void ljSoundEffects(unsigned long int sounds,
|
paulo@0
|
400 int countdown) {
|
paulo@0
|
401
|
paulo@0
|
402 // cancel out overlapping line clear sounds
|
paulo@0
|
403 if (sounds & 0x0080) {
|
paulo@0
|
404 sounds &= ~0x0060;
|
paulo@0
|
405 } else if (sounds & 0x0040) {
|
paulo@0
|
406 sounds &= ~0x0020;
|
paulo@0
|
407 }
|
paulo@0
|
408
|
paulo@0
|
409 for (int y = 0; sounds; ++y, sounds >>= 1) {
|
paulo@0
|
410 if (sounds & 1) {
|
paulo@0
|
411 startEffect(effects[y]);
|
paulo@0
|
412 }
|
paulo@0
|
413 }
|
paulo@0
|
414 if (countdown < 0) {
|
paulo@0
|
415 countdown = 0;
|
paulo@0
|
416 } else if (countdown > 6) {
|
paulo@0
|
417 countdown = 6;
|
paulo@0
|
418 }
|
paulo@0
|
419 if (countdown < lastCD) {
|
paulo@0
|
420 if (countdown > 0) {
|
paulo@0
|
421 startEffect(countEffect);
|
paulo@0
|
422 } else {
|
paulo@0
|
423 startEffect(winEffect1);
|
paulo@0
|
424 startEffect(winEffect2);
|
paulo@0
|
425 }
|
paulo@0
|
426 }
|
paulo@0
|
427 lastCD = countdown;
|
paulo@0
|
428 pollEffects();
|
paulo@0
|
429 }
|