annotate src/dssound7.c @ 0:c84446dfb3f5

initial add
author paulo@localhost
date Fri, 13 Mar 2009 00:39:12 -0700
parents
children
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 }