configure.in: default profiling to off, as its broken
[rofl0r-VisualBoyAdvance.git] / src / Sound.cpp
blob814cd7e74f6b87d734a831c91e9032389c0f3a5d
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
4 // Copyright (C) 2004-2006 VBA development team
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2, or(at your option)
9 // any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <memory.h>
22 #include "Sound.h"
24 #include "GBA.h"
25 #include "Globals.h"
26 #include "Util.h"
28 #define USE_TICKS_AS 380
29 #define SOUND_MAGIC 0x60000000
30 #define SOUND_MAGIC_2 0x30000000
31 #define NOISE_MAGIC 5
33 extern bool stopState;
35 u8 soundWavePattern[4][32] = {
36 {0x01,0x01,0x01,0x01,
37 0xff,0xff,0xff,0xff,
38 0xff,0xff,0xff,0xff,
39 0xff,0xff,0xff,0xff,
40 0xff,0xff,0xff,0xff,
41 0xff,0xff,0xff,0xff,
42 0xff,0xff,0xff,0xff,
43 0xff,0xff,0xff,0xff},
44 {0x01,0x01,0x01,0x01,
45 0x01,0x01,0x01,0x01,
46 0xff,0xff,0xff,0xff,
47 0xff,0xff,0xff,0xff,
48 0xff,0xff,0xff,0xff,
49 0xff,0xff,0xff,0xff,
50 0xff,0xff,0xff,0xff,
51 0xff,0xff,0xff,0xff},
52 {0x01,0x01,0x01,0x01,
53 0x01,0x01,0x01,0x01,
54 0x01,0x01,0x01,0x01,
55 0x01,0x01,0x01,0x01,
56 0xff,0xff,0xff,0xff,
57 0xff,0xff,0xff,0xff,
58 0xff,0xff,0xff,0xff,
59 0xff,0xff,0xff,0xff},
60 {0x01,0x01,0x01,0x01,
61 0x01,0x01,0x01,0x01,
62 0x01,0x01,0x01,0x01,
63 0x01,0x01,0x01,0x01,
64 0x01,0x01,0x01,0x01,
65 0x01,0x01,0x01,0x01,
66 0xff,0xff,0xff,0xff,
67 0xff,0xff,0xff,0xff}
70 int soundFreqRatio[8] = {
71 1048576, // 0
72 524288, // 1
73 262144, // 2
74 174763, // 3
75 131072, // 4
76 104858, // 5
77 87381, // 6
78 74898 // 7
81 int soundShiftClock[16]= {
82 2, // 0
83 4, // 1
84 8, // 2
85 16, // 3
86 32, // 4
87 64, // 5
88 128, // 6
89 256, // 7
90 512, // 8
91 1024, // 9
92 2048, // 10
93 4096, // 11
94 8192, // 12
95 16384, // 13
96 1, // 14
97 1 // 15
100 int soundVolume = 0;
102 u8 soundBuffer[6][735];
103 u16 soundFinalWave[1470];
105 int soundBufferLen = 1470;
106 int soundBufferTotalLen = 14700;
107 int soundQuality = 2;
108 int soundPaused = 1;
109 int soundPlay = 0;
110 int soundTicks = soundQuality * USE_TICKS_AS;
111 int SOUND_CLOCK_TICKS = soundQuality * USE_TICKS_AS;
112 u32 soundNextPosition = 0;
114 int soundLevel1 = 0;
115 int soundLevel2 = 0;
116 int soundBalance = 0;
117 int soundMasterOn = 0;
118 int soundIndex = 0;
119 int soundBufferIndex = 0;
120 int soundDebug = 0;
121 bool soundOffFlag = false;
123 int sound1On = 0;
124 int sound1ATL = 0;
125 int sound1Skip = 0;
126 int sound1Index = 0;
127 int sound1Continue = 0;
128 int sound1EnvelopeVolume = 0;
129 int sound1EnvelopeATL = 0;
130 int sound1EnvelopeUpDown = 0;
131 int sound1EnvelopeATLReload = 0;
132 int sound1SweepATL = 0;
133 int sound1SweepATLReload = 0;
134 int sound1SweepSteps = 0;
135 int sound1SweepUpDown = 0;
136 int sound1SweepStep = 0;
137 u8 *sound1Wave = soundWavePattern[2];
139 int sound2On = 0;
140 int sound2ATL = 0;
141 int sound2Skip = 0;
142 int sound2Index = 0;
143 int sound2Continue = 0;
144 int sound2EnvelopeVolume = 0;
145 int sound2EnvelopeATL = 0;
146 int sound2EnvelopeUpDown = 0;
147 int sound2EnvelopeATLReload = 0;
148 u8 *sound2Wave = soundWavePattern[2];
150 int sound3On = 0;
151 int sound3ATL = 0;
152 int sound3Skip = 0;
153 int sound3Index = 0;
154 int sound3Continue = 0;
155 int sound3OutputLevel = 0;
156 int sound3Last = 0;
157 u8 sound3WaveRam[0x20];
158 int sound3Bank = 0;
159 int sound3DataSize = 0;
160 int sound3ForcedOutput = 0;
162 int sound4On = 0;
163 int sound4Clock = 0;
164 int sound4ATL = 0;
165 int sound4Skip = 0;
166 int sound4Index = 0;
167 int sound4ShiftRight = 0x7f;
168 int sound4ShiftSkip = 0;
169 int sound4ShiftIndex = 0;
170 int sound4NSteps = 0;
171 int sound4CountDown = 0;
172 int sound4Continue = 0;
173 int sound4EnvelopeVolume = 0;
174 int sound4EnvelopeATL = 0;
175 int sound4EnvelopeUpDown = 0;
176 int sound4EnvelopeATLReload = 0;
178 int soundControl = 0;
180 int soundDSFifoAIndex = 0;
181 int soundDSFifoACount = 0;
182 int soundDSFifoAWriteIndex = 0;
183 bool soundDSAEnabled = false;
184 int soundDSATimer = 0;
185 u8 soundDSFifoA[32];
186 u8 soundDSAValue = 0;
188 int soundDSFifoBIndex = 0;
189 int soundDSFifoBCount = 0;
190 int soundDSFifoBWriteIndex = 0;
191 bool soundDSBEnabled = false;
192 int soundDSBTimer = 0;
193 u8 soundDSFifoB[32];
194 u8 soundDSBValue = 0;
196 int soundEnableFlag = 0x3ff;
198 s16 soundFilter[4000];
199 s16 soundRight[5] = { 0, 0, 0, 0, 0 };
200 s16 soundLeft[5] = { 0, 0, 0, 0, 0 };
201 int soundEchoIndex = 0;
202 bool soundEcho = false;
203 bool soundLowPass = false;
204 bool soundReverse = false;
206 variable_desc soundSaveStruct[] = {
207 { &soundPaused, sizeof(int) },
208 { &soundPlay, sizeof(int) },
209 { &soundTicks, sizeof(int) },
210 { &SOUND_CLOCK_TICKS, sizeof(int) },
211 { &soundLevel1, sizeof(int) },
212 { &soundLevel2, sizeof(int) },
213 { &soundBalance, sizeof(int) },
214 { &soundMasterOn, sizeof(int) },
215 { &soundIndex, sizeof(int) },
216 { &sound1On, sizeof(int) },
217 { &sound1ATL, sizeof(int) },
218 { &sound1Skip, sizeof(int) },
219 { &sound1Index, sizeof(int) },
220 { &sound1Continue, sizeof(int) },
221 { &sound1EnvelopeVolume, sizeof(int) },
222 { &sound1EnvelopeATL, sizeof(int) },
223 { &sound1EnvelopeATLReload, sizeof(int) },
224 { &sound1EnvelopeUpDown, sizeof(int) },
225 { &sound1SweepATL, sizeof(int) },
226 { &sound1SweepATLReload, sizeof(int) },
227 { &sound1SweepSteps, sizeof(int) },
228 { &sound1SweepUpDown, sizeof(int) },
229 { &sound1SweepStep, sizeof(int) },
230 { &sound2On, sizeof(int) },
231 { &sound2ATL, sizeof(int) },
232 { &sound2Skip, sizeof(int) },
233 { &sound2Index, sizeof(int) },
234 { &sound2Continue, sizeof(int) },
235 { &sound2EnvelopeVolume, sizeof(int) },
236 { &sound2EnvelopeATL, sizeof(int) },
237 { &sound2EnvelopeATLReload, sizeof(int) },
238 { &sound2EnvelopeUpDown, sizeof(int) },
239 { &sound3On, sizeof(int) },
240 { &sound3ATL, sizeof(int) },
241 { &sound3Skip, sizeof(int) },
242 { &sound3Index, sizeof(int) },
243 { &sound3Continue, sizeof(int) },
244 { &sound3OutputLevel, sizeof(int) },
245 { &sound4On, sizeof(int) },
246 { &sound4ATL, sizeof(int) },
247 { &sound4Skip, sizeof(int) },
248 { &sound4Index, sizeof(int) },
249 { &sound4Clock, sizeof(int) },
250 { &sound4ShiftRight, sizeof(int) },
251 { &sound4ShiftSkip, sizeof(int) },
252 { &sound4ShiftIndex, sizeof(int) },
253 { &sound4NSteps, sizeof(int) },
254 { &sound4CountDown, sizeof(int) },
255 { &sound4Continue, sizeof(int) },
256 { &sound4EnvelopeVolume, sizeof(int) },
257 { &sound4EnvelopeATL, sizeof(int) },
258 { &sound4EnvelopeATLReload, sizeof(int) },
259 { &sound4EnvelopeUpDown, sizeof(int) },
260 { &soundEnableFlag, sizeof(int) },
261 { &soundControl, sizeof(int) },
262 { &soundDSFifoAIndex, sizeof(int) },
263 { &soundDSFifoACount, sizeof(int) },
264 { &soundDSFifoAWriteIndex, sizeof(int) },
265 { &soundDSAEnabled, sizeof(bool) },
266 { &soundDSATimer, sizeof(int) },
267 { &soundDSFifoA[0], 32 },
268 { &soundDSAValue, sizeof(u8) },
269 { &soundDSFifoBIndex, sizeof(int) },
270 { &soundDSFifoBCount, sizeof(int) },
271 { &soundDSFifoBWriteIndex, sizeof(int) },
272 { &soundDSBEnabled, sizeof(int) },
273 { &soundDSBTimer, sizeof(int) },
274 { &soundDSFifoB[0], 32 },
275 { &soundDSBValue, sizeof(int) },
276 { &soundBuffer[0][0], 6*735 },
277 { &soundFinalWave[0], 2*735 },
278 { NULL, 0 }
281 variable_desc soundSaveStructV2[] = {
282 { &sound3WaveRam[0], 0x20 },
283 { &sound3Bank, sizeof(int) },
284 { &sound3DataSize, sizeof(int) },
285 { &sound3ForcedOutput, sizeof(int) },
286 { NULL, 0 }
289 void soundEvent(u32 address, u8 data)
291 int freq = 0;
293 switch(address) {
294 case NR10:
295 data &= 0x7f;
296 sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7);
297 sound1SweepSteps = data & 7;
298 sound1SweepUpDown = data & 0x08;
299 sound1SweepStep = 0;
300 ioMem[address] = data;
301 break;
302 case NR11:
303 sound1Wave = soundWavePattern[data >> 6];
304 sound1ATL = 172 * (64 - (data & 0x3f));
305 ioMem[address] = data;
306 break;
307 case NR12:
308 sound1EnvelopeUpDown = data & 0x08;
309 sound1EnvelopeATLReload = 689 * (data & 7);
310 if((data & 0xF8) == 0)
311 sound1EnvelopeVolume = 0;
312 ioMem[address] = data;
313 break;
314 case NR13:
315 freq = (((int)(ioMem[NR14] & 7)) << 8) | data;
316 sound1ATL = 172 * (64 - (ioMem[NR11] & 0x3f));
317 freq = 2048 - freq;
318 if(freq) {
319 sound1Skip = SOUND_MAGIC / freq;
320 } else
321 sound1Skip = 0;
322 ioMem[address] = data;
323 break;
324 case NR14:
325 data &= 0xC7;
326 freq = (((int)(data&7) << 8) | ioMem[NR13]);
327 freq = 2048 - freq;
328 sound1ATL = 172 * (64 - (ioMem[NR11] & 0x3f));
329 sound1Continue = data & 0x40;
330 if(freq) {
331 sound1Skip = SOUND_MAGIC / freq;
332 } else
333 sound1Skip = 0;
334 if(data & 0x80) {
335 ioMem[NR52] |= 1;
336 sound1EnvelopeVolume = ioMem[NR12] >> 4;
337 sound1EnvelopeUpDown = ioMem[NR12] & 0x08;
338 sound1ATL = 172 * (64 - (ioMem[NR11] & 0x3f));
339 sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (ioMem[NR12] & 7);
340 sound1SweepATL = sound1SweepATLReload = 344 * ((ioMem[NR10] >> 4) & 7);
341 sound1SweepSteps = ioMem[NR10] & 7;
342 sound1SweepUpDown = ioMem[NR10] & 0x08;
343 sound1SweepStep = 0;
345 sound1Index = 0;
346 sound1On = 1;
348 ioMem[address] = data;
349 break;
350 case NR21:
351 sound2Wave = soundWavePattern[data >> 6];
352 sound2ATL = 172 * (64 - (data & 0x3f));
353 ioMem[address] = data;
354 break;
355 case NR22:
356 sound2EnvelopeUpDown = data & 0x08;
357 sound2EnvelopeATLReload = 689 * (data & 7);
358 if((data & 0xF8) == 0)
359 sound2EnvelopeVolume = 0;
360 ioMem[address] = data;
361 break;
362 case NR23:
363 freq = (((int)(ioMem[NR24] & 7)) << 8) | data;
364 sound2ATL = 172 * (64 - (ioMem[NR21] & 0x3f));
365 freq = 2048 - freq;
366 if(freq) {
367 sound2Skip = SOUND_MAGIC / freq;
368 } else
369 sound2Skip = 0;
370 ioMem[address] = data;
371 break;
372 case NR24:
373 data &= 0xC7;
374 freq = (((int)(data&7) << 8) | ioMem[NR23]);
375 freq = 2048 - freq;
376 sound2ATL = 172 * (64 - (ioMem[NR21] & 0x3f));
377 sound2Continue = data & 0x40;
378 if(freq) {
379 sound2Skip = SOUND_MAGIC / freq;
380 } else
381 sound2Skip = 0;
382 if(data & 0x80) {
383 ioMem[NR52] |= 2;
384 sound2EnvelopeVolume = ioMem[NR22] >> 4;
385 sound2EnvelopeUpDown = ioMem[NR22] & 0x08;
386 sound2ATL = 172 * (64 - (ioMem[NR21] & 0x3f));
387 sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (ioMem[NR22] & 7);
389 sound2Index = 0;
390 sound2On = 1;
392 ioMem[address] = data;
393 break;
394 case NR30:
395 data &= 0xe0;
396 if(!(data & 0x80)) {
397 ioMem[NR52] &= 0xfb;
398 sound3On = 0;
400 if(((data >> 6) & 1) != sound3Bank)
401 memcpy(&ioMem[0x90], &sound3WaveRam[(((data >> 6) & 1) * 0x10)^0x10],
402 0x10);
403 sound3Bank = (data >> 6) & 1;
404 sound3DataSize = (data >> 5) & 1;
405 ioMem[address] = data;
406 break;
407 case NR31:
408 sound3ATL = 172 * (256-data);
409 ioMem[address] = data;
410 break;
411 case NR32:
412 data &= 0xe0;
413 sound3OutputLevel = (data >> 5) & 3;
414 sound3ForcedOutput = (data >> 7) & 1;
415 ioMem[address] = data;
416 break;
417 case NR33:
418 freq = 2048 - (((int)(ioMem[NR34]&7) << 8) | data);
419 if(freq) {
420 sound3Skip = SOUND_MAGIC_2 / freq;
421 } else
422 sound3Skip = 0;
423 ioMem[address] = data;
424 break;
425 case NR34:
426 data &= 0xc7;
427 freq = 2048 - (((data &7) << 8) | (int)ioMem[NR33]);
428 if(freq) {
429 sound3Skip = SOUND_MAGIC_2 / freq;
430 } else {
431 sound3Skip = 0;
433 sound3Continue = data & 0x40;
434 if((data & 0x80) && (ioMem[NR30] & 0x80)) {
435 ioMem[NR52] |= 4;
436 sound3ATL = 172 * (256 - ioMem[NR31]);
437 sound3Index = 0;
438 sound3On = 1;
440 ioMem[address] = data;
441 break;
442 case NR41:
443 data &= 0x3f;
444 sound4ATL = 172 * (64 - (data & 0x3f));
445 ioMem[address] = data;
446 break;
447 case NR42:
448 sound4EnvelopeUpDown = data & 0x08;
449 sound4EnvelopeATLReload = 689 * (data & 7);
450 if((data & 0xF8) == 0)
451 sound4EnvelopeVolume = 0;
452 ioMem[address] = data;
453 break;
454 case NR43:
455 freq = soundFreqRatio[data & 7];
456 sound4NSteps = data & 0x08;
458 sound4Skip = (freq << 8) / NOISE_MAGIC;
460 sound4Clock = data >> 4;
462 freq = freq / soundShiftClock[sound4Clock];
464 sound4ShiftSkip = (freq << 8) / NOISE_MAGIC;
465 ioMem[address] = data;
466 break;
467 case NR44:
468 data &= 0xc0;
469 sound4Continue = data & 0x40;
470 if(data & 0x80) {
471 ioMem[NR52] |= 8;
472 sound4EnvelopeVolume = ioMem[NR42] >> 4;
473 sound4EnvelopeUpDown = ioMem[NR42] & 0x08;
474 sound4ATL = 172 * (64 - (ioMem[NR41] & 0x3f));
475 sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (ioMem[NR42] & 7);
477 sound4On = 1;
479 sound4Index = 0;
480 sound4ShiftIndex = 0;
482 freq = soundFreqRatio[ioMem[NR43] & 7];
484 sound4Skip = (freq << 8) / NOISE_MAGIC;
486 sound4NSteps = ioMem[NR43] & 0x08;
488 freq = freq / soundShiftClock[ioMem[NR43] >> 4];
490 sound4ShiftSkip = (freq << 8) / NOISE_MAGIC;
491 if(sound4NSteps)
492 sound4ShiftRight = 0x7fff;
493 else
494 sound4ShiftRight = 0x7f;
496 ioMem[address] = data;
497 break;
498 case NR50:
499 data &= 0x77;
500 soundLevel1 = data & 7;
501 soundLevel2 = (data >> 4) & 7;
502 ioMem[address] = data;
503 break;
504 case NR51:
505 soundBalance = (data & soundEnableFlag);
506 ioMem[address] = data;
507 break;
508 case NR52:
509 data &= 0x80;
510 data |= ioMem[NR52] & 15;
511 soundMasterOn = data & 0x80;
512 if(!(data & 0x80)) {
513 sound1On = 0;
514 sound2On = 0;
515 sound3On = 0;
516 sound4On = 0;
518 ioMem[address] = data;
519 break;
520 case 0x90:
521 case 0x91:
522 case 0x92:
523 case 0x93:
524 case 0x94:
525 case 0x95:
526 case 0x96:
527 case 0x97:
528 case 0x98:
529 case 0x99:
530 case 0x9a:
531 case 0x9b:
532 case 0x9c:
533 case 0x9d:
534 case 0x9e:
535 case 0x9f:
536 sound3WaveRam[(sound3Bank*0x10)^0x10+(address&15)] = data;
537 break;
541 void soundEvent(u32 address, u16 data)
543 switch(address) {
544 case SGCNT0_H:
545 data &= 0xFF0F;
546 soundControl = data & 0x770F;
547 if(data & 0x0800) {
548 soundDSFifoAWriteIndex = 0;
549 soundDSFifoAIndex = 0;
550 soundDSFifoACount = 0;
551 soundDSAValue = 0;
552 memset(soundDSFifoA, 0, 32);
554 soundDSAEnabled = (data & 0x0300) ? true : false;
555 soundDSATimer = (data & 0x0400) ? 1 : 0;
556 if(data & 0x8000) {
557 soundDSFifoBWriteIndex = 0;
558 soundDSFifoBIndex = 0;
559 soundDSFifoBCount = 0;
560 soundDSBValue = 0;
561 memset(soundDSFifoB, 0, 32);
563 soundDSBEnabled = (data & 0x3000) ? true : false;
564 soundDSBTimer = (data & 0x4000) ? 1 : 0;
565 *((u16 *)&ioMem[address]) = soundControl;
566 break;
567 case FIFOA_L:
568 case FIFOA_H:
569 soundDSFifoA[soundDSFifoAWriteIndex++] = data & 0xFF;
570 soundDSFifoA[soundDSFifoAWriteIndex++] = data >> 8;
571 soundDSFifoACount += 2;
572 soundDSFifoAWriteIndex &= 31;
573 *((u16 *)&ioMem[address]) = data;
574 break;
575 case FIFOB_L:
576 case FIFOB_H:
577 soundDSFifoB[soundDSFifoBWriteIndex++] = data & 0xFF;
578 soundDSFifoB[soundDSFifoBWriteIndex++] = data >> 8;
579 soundDSFifoBCount += 2;
580 soundDSFifoBWriteIndex &= 31;
581 *((u16 *)&ioMem[address]) = data;
582 break;
583 case 0x88:
584 data &= 0xC3FF;
585 *((u16 *)&ioMem[address]) = data;
586 break;
587 case 0x90:
588 case 0x92:
589 case 0x94:
590 case 0x96:
591 case 0x98:
592 case 0x9a:
593 case 0x9c:
594 case 0x9e:
595 *((u16 *)&sound3WaveRam[(sound3Bank*0x10)^0x10+(address&14)]) = data;
596 *((u16 *)&ioMem[address]) = data;
597 break;
601 void soundChannel1()
603 int vol = sound1EnvelopeVolume;
605 int freq = 0;
606 int value = 0;
608 if(sound1On && (sound1ATL || !sound1Continue)) {
609 sound1Index += soundQuality*sound1Skip;
610 sound1Index &= 0x1fffffff;
612 value = ((s8)sound1Wave[sound1Index>>24]) * vol;
615 soundBuffer[0][soundIndex] = value;
618 if(sound1On) {
619 if(sound1ATL) {
620 sound1ATL-=soundQuality;
622 if(sound1ATL <=0 && sound1Continue) {
623 ioMem[NR52] &= 0xfe;
624 sound1On = 0;
628 if(sound1EnvelopeATL) {
629 sound1EnvelopeATL-=soundQuality;
631 if(sound1EnvelopeATL<=0) {
632 if(sound1EnvelopeUpDown) {
633 if(sound1EnvelopeVolume < 15)
634 sound1EnvelopeVolume++;
635 } else {
636 if(sound1EnvelopeVolume)
637 sound1EnvelopeVolume--;
640 sound1EnvelopeATL += sound1EnvelopeATLReload;
644 if(sound1SweepATL) {
645 sound1SweepATL-=soundQuality;
647 if(sound1SweepATL<=0) {
648 freq = (((int)(ioMem[NR14]&7) << 8) | ioMem[NR13]);
650 int updown = 1;
652 if(sound1SweepUpDown)
653 updown = -1;
655 int newfreq = 0;
656 if(sound1SweepSteps) {
657 newfreq = freq + updown * freq / (1 << sound1SweepSteps);
658 if(newfreq == freq)
659 newfreq = 0;
660 } else
661 newfreq = freq;
663 if(newfreq < 0) {
664 sound1SweepATL += sound1SweepATLReload;
665 } else if(newfreq > 2047) {
666 sound1SweepATL = 0;
667 sound1On = 0;
668 ioMem[NR52] &= 0xfe;
669 } else {
670 sound1SweepATL += sound1SweepATLReload;
671 sound1Skip = SOUND_MAGIC/(2048 - newfreq);
673 ioMem[NR13] = newfreq & 0xff;
674 ioMem[NR14] = (ioMem[NR14] & 0xf8) |((newfreq >> 8) & 7);
681 void soundChannel2()
683 // int freq = 0;
684 int vol = sound2EnvelopeVolume;
686 int value = 0;
688 if(sound2On && (sound2ATL || !sound2Continue)) {
689 sound2Index += soundQuality*sound2Skip;
690 sound2Index &= 0x1fffffff;
692 value = ((s8)sound2Wave[sound2Index>>24]) * vol;
695 soundBuffer[1][soundIndex] = value;
697 if(sound2On) {
698 if(sound2ATL) {
699 sound2ATL-=soundQuality;
701 if(sound2ATL <= 0 && sound2Continue) {
702 ioMem[NR52] &= 0xfd;
703 sound2On = 0;
707 if(sound2EnvelopeATL) {
708 sound2EnvelopeATL-=soundQuality;
710 if(sound2EnvelopeATL <= 0) {
711 if(sound2EnvelopeUpDown) {
712 if(sound2EnvelopeVolume < 15)
713 sound2EnvelopeVolume++;
714 } else {
715 if(sound2EnvelopeVolume)
716 sound2EnvelopeVolume--;
718 sound2EnvelopeATL += sound2EnvelopeATLReload;
724 void soundChannel3()
726 int value = sound3Last;
728 if(sound3On && (sound3ATL || !sound3Continue)) {
729 sound3Index += soundQuality*sound3Skip;
730 if(sound3DataSize) {
731 sound3Index &= 0x3fffffff;
732 value = sound3WaveRam[sound3Index>>25];
733 } else {
734 sound3Index &= 0x1fffffff;
735 value = sound3WaveRam[sound3Bank*0x10 + (sound3Index>>25)];
738 if( (sound3Index & 0x01000000)) {
739 value &= 0x0f;
740 } else {
741 value >>= 4;
744 value -= 8;
745 value *= 2;
747 if(sound3ForcedOutput) {
748 value = ((value >> 1) + value) >> 1;
749 } else {
750 switch(sound3OutputLevel) {
751 case 0:
752 value = 0;
753 break;
754 case 1:
755 break;
756 case 2:
757 value = (value >> 1);
758 break;
759 case 3:
760 value = (value >> 2);
761 break;
764 sound3Last = value;
767 soundBuffer[2][soundIndex] = value;
769 if(sound3On) {
770 if(sound3ATL) {
771 sound3ATL-=soundQuality;
773 if(sound3ATL <= 0 && sound3Continue) {
774 ioMem[NR52] &= 0xfb;
775 sound3On = 0;
781 void soundChannel4()
783 int vol = sound4EnvelopeVolume;
785 int value = 0;
787 if(sound4Clock <= 0x0c) {
788 if(sound4On && (sound4ATL || !sound4Continue)) {
789 sound4Index += soundQuality*sound4Skip;
790 sound4ShiftIndex += soundQuality*sound4ShiftSkip;
792 if(sound4NSteps) {
793 while(sound4ShiftIndex > 0x1fffff) {
794 sound4ShiftRight = (((sound4ShiftRight << 6) ^
795 (sound4ShiftRight << 5)) & 0x40) |
796 (sound4ShiftRight >> 1);
797 sound4ShiftIndex -= 0x200000;
799 } else {
800 while(sound4ShiftIndex > 0x1fffff) {
801 sound4ShiftRight = (((sound4ShiftRight << 14) ^
802 (sound4ShiftRight << 13)) & 0x4000) |
803 (sound4ShiftRight >> 1);
805 sound4ShiftIndex -= 0x200000;
809 sound4Index &= 0x1fffff;
810 sound4ShiftIndex &= 0x1fffff;
812 value = ((sound4ShiftRight & 1)*2-1) * vol;
813 } else {
814 value = 0;
818 soundBuffer[3][soundIndex] = value;
820 if(sound4On) {
821 if(sound4ATL) {
822 sound4ATL-=soundQuality;
824 if(sound4ATL <= 0 && sound4Continue) {
825 ioMem[NR52] &= 0xfd;
826 sound4On = 0;
830 if(sound4EnvelopeATL) {
831 sound4EnvelopeATL-=soundQuality;
833 if(sound4EnvelopeATL <= 0) {
834 if(sound4EnvelopeUpDown) {
835 if(sound4EnvelopeVolume < 15)
836 sound4EnvelopeVolume++;
837 } else {
838 if(sound4EnvelopeVolume)
839 sound4EnvelopeVolume--;
841 sound4EnvelopeATL += sound4EnvelopeATLReload;
847 void soundDirectSoundA()
849 soundBuffer[4][soundIndex] = soundDSAValue;
852 void soundDirectSoundATimer()
854 if(soundDSAEnabled) {
855 if(soundDSFifoACount <= 16) {
856 CPUCheckDMA(3, 2);
857 if(soundDSFifoACount <= 16) {
858 soundEvent(FIFOA_L, (u16)0);
859 soundEvent(FIFOA_H, (u16)0);
860 soundEvent(FIFOA_L, (u16)0);
861 soundEvent(FIFOA_H, (u16)0);
862 soundEvent(FIFOA_L, (u16)0);
863 soundEvent(FIFOA_H, (u16)0);
864 soundEvent(FIFOA_L, (u16)0);
865 soundEvent(FIFOA_H, (u16)0);
869 soundDSAValue = (soundDSFifoA[soundDSFifoAIndex]);
870 soundDSFifoAIndex = (soundDSFifoAIndex + 1) & 31;
871 soundDSFifoACount--;
872 } else
873 soundDSAValue = 0;
876 void soundDirectSoundB()
878 soundBuffer[5][soundIndex] = soundDSBValue;
881 void soundDirectSoundBTimer()
883 if(soundDSBEnabled) {
884 if(soundDSFifoBCount <= 16) {
885 CPUCheckDMA(3, 4);
886 if(soundDSFifoBCount <= 16) {
887 soundEvent(FIFOB_L, (u16)0);
888 soundEvent(FIFOB_H, (u16)0);
889 soundEvent(FIFOB_L, (u16)0);
890 soundEvent(FIFOB_H, (u16)0);
891 soundEvent(FIFOB_L, (u16)0);
892 soundEvent(FIFOB_H, (u16)0);
893 soundEvent(FIFOB_L, (u16)0);
894 soundEvent(FIFOB_H, (u16)0);
898 soundDSBValue = (soundDSFifoB[soundDSFifoBIndex]);
899 soundDSFifoBIndex = (soundDSFifoBIndex + 1) & 31;
900 soundDSFifoBCount--;
901 } else {
902 soundDSBValue = 0;
906 void soundTimerOverflow(int timer)
908 if(soundDSAEnabled && (soundDSATimer == timer)) {
909 soundDirectSoundATimer();
911 if(soundDSBEnabled && (soundDSBTimer == timer)) {
912 soundDirectSoundBTimer();
916 #ifndef max
917 #define max(a,b) (a)<(b)?(b):(a)
918 #endif
920 void soundMix()
922 int res = 0;
923 int cgbRes = 0;
924 int ratio = ioMem[0x82] & 3;
925 int dsaRatio = ioMem[0x82] & 4;
926 int dsbRatio = ioMem[0x82] & 8;
928 if(soundBalance & 16) {
929 cgbRes = ((s8)soundBuffer[0][soundIndex]);
931 if(soundBalance & 32) {
932 cgbRes += ((s8)soundBuffer[1][soundIndex]);
934 if(soundBalance & 64) {
935 cgbRes += ((s8)soundBuffer[2][soundIndex]);
937 if(soundBalance & 128) {
938 cgbRes += ((s8)soundBuffer[3][soundIndex]);
941 if((soundControl & 0x0200) && (soundEnableFlag & 0x100)){
942 if(!dsaRatio)
943 res = ((s8)soundBuffer[4][soundIndex])>>1;
944 else
945 res = ((s8)soundBuffer[4][soundIndex]);
948 if((soundControl & 0x2000) && (soundEnableFlag & 0x200)){
949 if(!dsbRatio)
950 res += ((s8)soundBuffer[5][soundIndex])>>1;
951 else
952 res += ((s8)soundBuffer[5][soundIndex]);
955 res = (res * 170);
956 cgbRes = (cgbRes * 52 * soundLevel1);
958 switch(ratio) {
959 case 0:
960 case 3: // prohibited, but 25%
961 cgbRes >>= 2;
962 break;
963 case 1:
964 cgbRes >>= 1;
965 break;
966 case 2:
967 break;
970 res += cgbRes;
972 if(soundEcho) {
973 res *= 2;
974 res += soundFilter[soundEchoIndex];
975 res /= 2;
976 soundFilter[soundEchoIndex++] = res;
979 if(soundLowPass) {
980 soundLeft[4] = soundLeft[3];
981 soundLeft[3] = soundLeft[2];
982 soundLeft[2] = soundLeft[1];
983 soundLeft[1] = soundLeft[0];
984 soundLeft[0] = res;
985 res = (soundLeft[4] + 2*soundLeft[3] + 8*soundLeft[2] + 2*soundLeft[1] +
986 soundLeft[0])/14;
989 switch(soundVolume) {
990 case 0:
991 case 1:
992 case 2:
993 case 3:
994 res *= (soundVolume+1);
995 break;
996 case 4:
997 res >>= 2;
998 break;
999 case 5:
1000 res >>= 1;
1001 break;
1004 if(res > 32767)
1005 res = 32767;
1006 if(res < -32768)
1007 res = -32768;
1009 if(soundReverse)
1010 soundFinalWave[++soundBufferIndex] = res;
1011 else
1012 soundFinalWave[soundBufferIndex++] = res;
1014 res = 0;
1015 cgbRes = 0;
1017 if(soundBalance & 1) {
1018 cgbRes = ((s8)soundBuffer[0][soundIndex]);
1020 if(soundBalance & 2) {
1021 cgbRes += ((s8)soundBuffer[1][soundIndex]);
1023 if(soundBalance & 4) {
1024 cgbRes += ((s8)soundBuffer[2][soundIndex]);
1026 if(soundBalance & 8) {
1027 cgbRes += ((s8)soundBuffer[3][soundIndex]);
1030 if((soundControl & 0x0100) && (soundEnableFlag & 0x100)){
1031 if(!dsaRatio)
1032 res = ((s8)soundBuffer[4][soundIndex])>>1;
1033 else
1034 res = ((s8)soundBuffer[4][soundIndex]);
1037 if((soundControl & 0x1000) && (soundEnableFlag & 0x200)){
1038 if(!dsbRatio)
1039 res += ((s8)soundBuffer[5][soundIndex])>>1;
1040 else
1041 res += ((s8)soundBuffer[5][soundIndex]);
1044 res = (res * 170);
1045 cgbRes = (cgbRes * 52 * soundLevel1);
1047 switch(ratio) {
1048 case 0:
1049 case 3: // prohibited, but 25%
1050 cgbRes >>= 2;
1051 break;
1052 case 1:
1053 cgbRes >>= 1;
1054 break;
1055 case 2:
1056 break;
1059 res += cgbRes;
1061 if(soundEcho) {
1062 res *= 2;
1063 res += soundFilter[soundEchoIndex];
1064 res /= 2;
1065 soundFilter[soundEchoIndex++] = res;
1067 if(soundEchoIndex >= 4000)
1068 soundEchoIndex = 0;
1071 if(soundLowPass) {
1072 soundRight[4] = soundRight[3];
1073 soundRight[3] = soundRight[2];
1074 soundRight[2] = soundRight[1];
1075 soundRight[1] = soundRight[0];
1076 soundRight[0] = res;
1077 res = (soundRight[4] + 2*soundRight[3] + 8*soundRight[2] + 2*soundRight[1] +
1078 soundRight[0])/14;
1081 switch(soundVolume) {
1082 case 0:
1083 case 1:
1084 case 2:
1085 case 3:
1086 res *= (soundVolume+1);
1087 break;
1088 case 4:
1089 res >>= 2;
1090 break;
1091 case 5:
1092 res >>= 1;
1093 break;
1096 if(res > 32767)
1097 res = 32767;
1098 if(res < -32768)
1099 res = -32768;
1101 if(soundReverse)
1102 soundFinalWave[-1+soundBufferIndex++] = res;
1103 else
1104 soundFinalWave[soundBufferIndex++] = res;
1107 void soundTick()
1109 if(systemSoundOn) {
1110 if(soundMasterOn && !stopState) {
1111 soundChannel1();
1112 soundChannel2();
1113 soundChannel3();
1114 soundChannel4();
1115 soundDirectSoundA();
1116 soundDirectSoundB();
1117 soundMix();
1118 } else {
1119 soundFinalWave[soundBufferIndex++] = 0;
1120 soundFinalWave[soundBufferIndex++] = 0;
1123 soundIndex++;
1125 if(2*soundBufferIndex >= soundBufferLen) {
1126 if(systemSoundOn) {
1127 if(soundPaused) {
1128 soundResume();
1131 systemWriteDataToSoundBuffer();
1133 soundIndex = 0;
1134 soundBufferIndex = 0;
1139 void soundShutdown()
1141 systemSoundShutdown();
1144 void soundPause()
1146 systemSoundPause();
1147 soundPaused = 1;
1150 void soundResume()
1152 systemSoundResume();
1153 soundPaused = 0;
1156 void soundEnable(int channels)
1158 int c = channels & 0x0f;
1160 soundEnableFlag |= ((channels & 0x30f) |c | (c << 4));
1161 if(ioMem)
1162 soundBalance = (ioMem[NR51] & soundEnableFlag);
1165 void soundDisable(int channels)
1167 int c = channels & 0x0f;
1169 soundEnableFlag &= (~((channels & 0x30f)|c|(c<<4)));
1170 if(ioMem)
1171 soundBalance = (ioMem[NR51] & soundEnableFlag);
1174 int soundGetEnable()
1176 return (soundEnableFlag & 0x30f);
1179 void soundReset()
1181 systemSoundReset();
1183 soundPaused = 1;
1184 soundPlay = 0;
1185 SOUND_CLOCK_TICKS = soundQuality * USE_TICKS_AS;
1186 soundTicks = SOUND_CLOCK_TICKS;
1187 soundNextPosition = 0;
1188 soundMasterOn = 1;
1189 soundIndex = 0;
1190 soundBufferIndex = 0;
1191 soundLevel1 = 7;
1192 soundLevel2 = 7;
1194 sound1On = 0;
1195 sound1ATL = 0;
1196 sound1Skip = 0;
1197 sound1Index = 0;
1198 sound1Continue = 0;
1199 sound1EnvelopeVolume = 0;
1200 sound1EnvelopeATL = 0;
1201 sound1EnvelopeUpDown = 0;
1202 sound1EnvelopeATLReload = 0;
1203 sound1SweepATL = 0;
1204 sound1SweepATLReload = 0;
1205 sound1SweepSteps = 0;
1206 sound1SweepUpDown = 0;
1207 sound1SweepStep = 0;
1208 sound1Wave = soundWavePattern[2];
1210 sound2On = 0;
1211 sound2ATL = 0;
1212 sound2Skip = 0;
1213 sound2Index = 0;
1214 sound2Continue = 0;
1215 sound2EnvelopeVolume = 0;
1216 sound2EnvelopeATL = 0;
1217 sound2EnvelopeUpDown = 0;
1218 sound2EnvelopeATLReload = 0;
1219 sound2Wave = soundWavePattern[2];
1221 sound3On = 0;
1222 sound3ATL = 0;
1223 sound3Skip = 0;
1224 sound3Index = 0;
1225 sound3Continue = 0;
1226 sound3OutputLevel = 0;
1227 sound3Last = 0;
1228 sound3Bank = 0;
1229 sound3DataSize = 0;
1230 sound3ForcedOutput = 0;
1232 sound4On = 0;
1233 sound4Clock = 0;
1234 sound4ATL = 0;
1235 sound4Skip = 0;
1236 sound4Index = 0;
1237 sound4ShiftRight = 0x7f;
1238 sound4NSteps = 0;
1239 sound4CountDown = 0;
1240 sound4Continue = 0;
1241 sound4EnvelopeVolume = 0;
1242 sound4EnvelopeATL = 0;
1243 sound4EnvelopeUpDown = 0;
1244 sound4EnvelopeATLReload = 0;
1246 sound1On = 0;
1247 sound2On = 0;
1248 sound3On = 0;
1249 sound4On = 0;
1251 int addr = 0x90;
1253 while(addr < 0xA0) {
1254 ioMem[addr++] = 0x00;
1255 ioMem[addr++] = 0xff;
1258 addr = 0;
1259 while(addr < 0x20) {
1260 sound3WaveRam[addr++] = 0x00;
1261 sound3WaveRam[addr++] = 0xff;
1264 memset(soundFinalWave, 0, soundBufferLen);
1266 memset(soundFilter, 0, sizeof(soundFilter));
1267 soundEchoIndex = 0;
1270 bool soundInit()
1272 if(systemSoundInit()) {
1273 memset(soundBuffer[0], 0, 735*2);
1274 memset(soundBuffer[1], 0, 735*2);
1275 memset(soundBuffer[2], 0, 735*2);
1276 memset(soundBuffer[3], 0, 735*2);
1278 memset(soundFinalWave, 0, soundBufferLen);
1280 soundPaused = true;
1281 return true;
1283 return false;
1286 void soundSetQuality(int quality)
1288 if(soundQuality != quality && systemCanChangeSoundQuality()) {
1289 if(!soundOffFlag)
1290 soundShutdown();
1291 soundQuality = quality;
1292 soundNextPosition = 0;
1293 if(!soundOffFlag)
1294 soundInit();
1295 SOUND_CLOCK_TICKS = USE_TICKS_AS * soundQuality;
1296 soundIndex = 0;
1297 soundBufferIndex = 0;
1298 } else if(soundQuality != quality) {
1299 soundNextPosition = 0;
1300 SOUND_CLOCK_TICKS = USE_TICKS_AS * soundQuality;
1301 soundIndex = 0;
1302 soundBufferIndex = 0;
1306 void soundSaveGame(gzFile gzFile)
1308 utilWriteData(gzFile, soundSaveStruct);
1309 utilWriteData(gzFile, soundSaveStructV2);
1311 utilGzWrite(gzFile, &soundQuality, sizeof(int));
1314 void soundReadGame(gzFile gzFile, int version)
1316 utilReadData(gzFile, soundSaveStruct);
1317 if(version >= SAVE_GAME_VERSION_3) {
1318 utilReadData(gzFile, soundSaveStructV2);
1319 } else {
1320 sound3Bank = (ioMem[NR30] >> 6) & 1;
1321 sound3DataSize = (ioMem[NR30] >> 5) & 1;
1322 sound3ForcedOutput = (ioMem[NR32] >> 7) & 1;
1323 // nothing better to do here...
1324 memcpy(&sound3WaveRam[0x00], &ioMem[0x90], 0x10);
1325 memcpy(&sound3WaveRam[0x10], &ioMem[0x90], 0x10);
1327 soundBufferIndex = soundIndex * 2;
1329 int quality = 1;
1330 utilGzRead(gzFile, &quality, sizeof(int));
1331 soundSetQuality(quality);
1333 sound1Wave = soundWavePattern[ioMem[NR11] >> 6];
1334 sound2Wave = soundWavePattern[ioMem[NR21] >> 6];