Bump version numbers for 3.13
[maemo-rb.git] / apps / plugins / rockboy / sound.c
blobe8b8c6924c34b53f6f66d1ba076ead10a1696af7
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * The following code is rewrite of the C++ code provided in VisualBoyAdvance.
11 * There are also portions of the original GNUboy code.
12 * Copyright (C) 2001 the GNUboy development team
14 * VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
15 * Copyright (C) 1999-2003 Forgotten
16 * Copyright (C) 2004 Forgotten and the VBA development team
18 * VisualBoyAdvance conversion from C++ to C by Karl Kurbjun July, 2007
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
26 * KIND, either express or implied.
30 #include "rockmacros.h"
31 #include "defs.h"
32 #include "pcm.h"
33 #include "sound.h"
34 #include "cpu-gb.h"
35 #include "hw.h"
36 #include "regs.h"
38 static const byte soundWavePattern[4][32] = {
39 {0x01,0x01,0x01,0x01,
40 0xff,0xff,0xff,0xff,
41 0xff,0xff,0xff,0xff,
42 0xff,0xff,0xff,0xff,
43 0xff,0xff,0xff,0xff,
44 0xff,0xff,0xff,0xff,
45 0xff,0xff,0xff,0xff,
46 0xff,0xff,0xff,0xff},
47 {0x01,0x01,0x01,0x01,
48 0x01,0x01,0x01,0x01,
49 0xff,0xff,0xff,0xff,
50 0xff,0xff,0xff,0xff,
51 0xff,0xff,0xff,0xff,
52 0xff,0xff,0xff,0xff,
53 0xff,0xff,0xff,0xff,
54 0xff,0xff,0xff,0xff},
55 {0x01,0x01,0x01,0x01,
56 0x01,0x01,0x01,0x01,
57 0x01,0x01,0x01,0x01,
58 0x01,0x01,0x01,0x01,
59 0xff,0xff,0xff,0xff,
60 0xff,0xff,0xff,0xff,
61 0xff,0xff,0xff,0xff,
62 0xff,0xff,0xff,0xff},
63 {0x01,0x01,0x01,0x01,
64 0x01,0x01,0x01,0x01,
65 0x01,0x01,0x01,0x01,
66 0x01,0x01,0x01,0x01,
67 0x01,0x01,0x01,0x01,
68 0x01,0x01,0x01,0x01,
69 0xff,0xff,0xff,0xff,
70 0xff,0xff,0xff,0xff}
73 int soundFreqRatio[8] ICONST_ATTR= {
74 1048576, // 0
75 524288, // 1
76 262144, // 2
77 174763, // 3
78 131072, // 4
79 104858, // 5
80 87381, // 6
81 74898 // 7
84 int soundShiftClock[16] ICONST_ATTR= {
85 2, // 0
86 4, // 1
87 8, // 2
88 16, // 3
89 32, // 4
90 64, // 5
91 128, // 6
92 256, // 7
93 512, // 8
94 1024, // 9
95 2048, // 10
96 4096, // 11
97 8192, // 12
98 16384, // 13
99 1, // 14
100 1 // 15
103 struct snd snd IBSS_ATTR;
105 #define RATE (snd.rate)
106 #define WAVE (ram.hi+0x30)
107 #define S1 (snd.ch[0])
108 #define S2 (snd.ch[1])
109 #define S3 (snd.ch[2])
110 #define S4 (snd.ch[3])
112 #define SOUND_MAGIC 0x60000000
113 #define SOUND_MAGIC_2 0x30000000
114 #define NOISE_MAGIC 5
116 static void gbSoundChannel1(int *r, int *l)
118 int vol = S1.envol;
120 int freq = 0;
122 int value = 0;
124 if(S1.on && (S1.len || !S1.cont))
126 S1.pos += snd.quality*S1.skip;
127 S1.pos &= 0x1fffffff;
129 value = ((signed char)S1.wave[S1.pos>>24]) * vol;
132 if (snd.balance & 1) *r += value;
133 if (snd.balance & 16) *l += value;
135 if(S1.on)
137 if(S1.len)
139 S1.len-=snd.quality;
141 if(S1.len <=0 && S1.cont)
143 R_NR52 &= 0xfe;
144 S1.on = 0;
148 if(S1.enlen)
150 S1.enlen-=snd.quality;
152 if(S1.enlen<=0)
154 if(S1.endir)
156 if(S1.envol < 15)
157 S1.envol++;
159 else
161 if(S1.envol)
162 S1.envol--;
165 S1.enlen += S1.enlenreload;
169 if(S1.swlen)
171 S1.swlen-=snd.quality;
173 if(S1.swlen<=0)
175 freq = (((int)(R_NR14&7) << 8) | R_NR13);
177 int updown = 1;
179 if(S1.swdir)
180 updown = -1;
182 int newfreq = 0;
183 if(S1.swsteps)
185 newfreq = freq + updown * freq / BIT_N(S1.swsteps);
186 if(newfreq == freq)
187 newfreq = 0;
189 else
190 newfreq = freq;
192 if(newfreq < 0)
194 S1.swlen += S1.swlenreload;
196 else if(newfreq > 2047)
198 S1.swlen = 0;
199 S1.on = 0;
200 R_NR52 &= 0xfe;
202 else
204 S1.swlen += S1.swlenreload;
205 S1.skip = SOUND_MAGIC/(2048 - newfreq);
207 R_NR13 = newfreq & 0xff;
208 R_NR14 = (R_NR14 & 0xf8) |((newfreq >> 8) & 7);
215 static void gbSoundChannel2(int *r, int *l)
217 int vol = S2.envol;
219 int value = 0;
221 if(S2.on && (S2.len || !S2.cont))
223 S2.pos += snd.quality*S2.skip;
224 S2.pos &= 0x1fffffff;
226 value = ((signed char)S2.wave[S2.pos>>24]) * vol;
229 if (snd.balance & 2) *r += value;
230 if (snd.balance & 32) *l += value;
232 if(S2.on) {
233 if(S2.len) {
234 S2.len-=snd.quality;
236 if(S2.len <= 0 && S2.cont) {
237 R_NR52 &= 0xfd;
238 S2.on = 0;
242 if(S2.enlen) {
243 S2.enlen-=snd.quality;
245 if(S2.enlen <= 0) {
246 if(S2.endir) {
247 if(S2.envol < 15)
248 S2.envol++;
249 } else {
250 if(S2.envol)
251 S2.envol--;
253 S2.enlen += S2.enlenreload;
259 static void gbSoundChannel3(int *r, int *l)
261 int s;
262 if (S3.on && (S3.len || !S3.cont))
264 S3.pos += S3.skip*snd.quality;
265 S3.pos &= 0x1fffffff;
266 s=ram.hi[0x30 + (S3.pos>>25)];
267 if (S3.pos & 0x01000000)
268 s &= 0x0f;
269 else
270 s >>= 4;
272 s -= 8;
274 switch(S3.outputlevel)
276 case 0:
277 s=0;
278 break;
279 case 1:
280 break;
281 case 2:
282 s=s>>1;
283 break;
284 case 3:
285 s=s>>2;
286 break;
289 if (snd.balance & 4) *r += s;
290 if (snd.balance & 64) *l += s;
293 if(S3.on)
295 if(S3.len)
297 S3.len-=snd.quality;
298 if(S3.len<=0 && S3.cont)
300 R_NR52 &= 0xFB;
301 S3.on=0;
307 static void gbSoundChannel4(int *r, int *l)
309 int vol = S4.envol;
311 int value = 0;
313 if(S4.clock <= 0x0c)
315 if(S4.on && (S4.len || !S4.cont))
317 S4.pos += snd.quality*S4.skip;
318 S4.shiftpos += snd.quality*S4.shiftskip;
320 if(S4.nsteps)
322 while(S4.shiftpos > 0x1fffff) {
323 S4.shiftright = (((S4.shiftright << 6) ^
324 (S4.shiftright << 5)) & 0x40) | (S4.shiftright >> 1);
325 S4.shiftpos -= 0x200000;
328 else
330 while(S4.shiftpos > 0x1fffff)
332 S4.shiftright = (((S4.shiftright << 14) ^
333 (S4.shiftright << 13)) & 0x4000) | (S4.shiftright >> 1);
334 S4.shiftpos -= 0x200000;
338 S4.pos &= 0x1fffff;
339 S4.shiftpos &= 0x1fffff;
341 value = ((S4.shiftright & 1)*2-1) * vol;
343 else
345 value = 0;
349 if (snd.balance & 8) *r += value;
350 if (snd.balance & 128) *l += value;
352 if(S4.on) {
353 if(S4.len) {
354 S4.len-=snd.quality;
356 if(S4.len <= 0 && S4.cont) {
357 R_NR52 &= 0xfd;
358 S4.on = 0;
362 if(S4.enlen) {
363 S4.enlen-=snd.quality;
365 if(S4.enlen <= 0)
367 if(S4.endir)
369 if(S4.envol < 15)
370 S4.envol++;
372 else
374 if(S4.envol)
375 S4.envol--;
377 S4.enlen += S4.enlenreload;
383 void sound_mix(void)
385 int l, r;
387 if (!RATE || cpu.snd < RATE) return;
389 for (; cpu.snd >= RATE; cpu.snd -= RATE)
391 l = r = 0;
393 gbSoundChannel1(&r,&l);
395 gbSoundChannel2(&r,&l);
397 gbSoundChannel3(&r,&l);
399 gbSoundChannel4(&r,&l);
401 if(snd.gbDigitalSound)
403 l = snd.level1<<8;
404 r = snd.level2<<8;
406 else
408 l *= snd.level1*60;
409 r *= snd.level2*60;
412 if(l > 32767)
413 l = 32767;
414 if(l < -32768)
415 l = -32768;
417 if(r > 32767)
418 r = 32767;
419 if(r < -32768)
420 r = -32768;
422 if (pcm.buf)
424 if (pcm.pos >= pcm.len)
425 rockboy_pcm_submit();
426 if (pcm.stereo)
428 pcm.buf[pcm.pos++] = l;
429 pcm.buf[pcm.pos++] = r;
431 else pcm.buf[pcm.pos++] = ((l+r)>>1);
434 R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3);
437 byte sound_read(byte r)
439 if(!options.sound) return 0;
440 sound_mix();
441 /* printf("read %02X: %02X\n", r, REG(r)); */
442 return REG(r);
445 void sound_write(byte r, byte b)
447 int freq=0;
448 ram.hi[r]=b;
450 if(!options.sound)
451 return;
453 sound_mix();
455 switch (r)
457 case RI_NR10:
458 S1.swlen = S1.swlenreload = 344 * ((b >> 4) & 7);
459 S1.swsteps = b & 7;
460 S1.swdir = b & 0x08;
461 S1.swstep = 0;
462 break;
463 case RI_NR11:
464 S1.len = 172 * (64 - (b & 0x3f));
465 S1.wave = soundWavePattern[b >> 6];
466 break;
467 case RI_NR12:
468 S1.envol = b >> 4;
469 S1.endir = b & 0x08;
470 S1.enlenreload = S1.enlen = 689 * (b & 7);
471 break;
472 case RI_NR13:
473 freq = (((int)(R_NR14 & 7)) << 8) | b;
474 S1.len = 172 * (64 - (R_NR11 & 0x3f));
475 freq = 2048 - freq;
476 if(freq)
478 S1.skip = SOUND_MAGIC / freq;
480 else
482 S1.skip = 0;
484 break;
485 case RI_NR14:
486 freq = (((int)(b&7) << 8) | R_NR13);
487 freq = 2048 - freq;
488 S1.len = 172 * (64 - (R_NR11 & 0x3f));
489 S1.cont = b & 0x40;
490 if(freq)
492 S1.skip = SOUND_MAGIC / freq;
494 else
496 S1.skip = 0;
498 if(b & 0x80)
500 R_NR52 |= 1;
501 S1.envol = R_NR12 >> 4;
502 S1.endir = R_NR12 & 0x08;
503 S1.len = 172 * (64 - (R_NR11 & 0x3f));
504 S1.enlenreload = S1.enlen = 689 * (R_NR12 & 7);
505 S1.swlen = S1.swlenreload = 344 * ((R_NR10 >> 4) & 7);
506 S1.swsteps = R_NR10 & 7;
507 S1.swdir = R_NR10 & 0x08;
508 S1.swstep = 0;
510 S1.pos = 0;
511 S1.on = 1;
513 break;
514 case RI_NR21:
515 S2.wave = soundWavePattern[b >> 6];
516 S2.len = 172 * (64 - (b & 0x3f));
517 break;
518 case RI_NR22:
519 S2.envol = b >> 4;
520 S2.endir = b & 0x08;
521 S2.enlenreload = S2.enlen = 689 * (b & 7);
522 break;
523 case RI_NR23:
524 freq = (((int)(R_NR24 & 7)) << 8) | b;
525 S2.len = 172 * (64 - (R_NR21 & 0x3f));
526 freq = 2048 - freq;
527 if(freq)
529 S2.skip = SOUND_MAGIC / freq;
531 else
533 S2.skip = 0;
535 break;
536 case RI_NR24:
537 freq = (((int)(b&7) << 8) | R_NR23);
538 freq = 2048 - freq;
539 S2.len = 172 * (64 - (R_NR21 & 0x3f));
540 S2.cont = b & 0x40;
541 if(freq) {
542 S2.skip = SOUND_MAGIC / freq;
543 } else
544 S2.skip = 0;
545 if(b & 0x80) {
546 R_NR52 |= 2;
547 S2.envol = R_NR22 >> 4;
548 S2.endir = R_NR22 & 0x08;
549 S2.len = 172 * (64 - (R_NR21 & 0x3f));
550 S2.enlenreload = S2.enlen = 689 * (R_NR22 & 7);
552 S2.pos = 0;
553 S2.on = 1;
555 break;
556 case RI_NR30:
557 if (!(b & 0x80)){
558 R_NR52 &= 0xfb;
559 S3.on = 0;
561 break;
562 case RI_NR31:
563 S3.len = (256-R_NR31) * 172;
564 break;
565 case RI_NR32:
566 S3.outputlevel = (b >> 5) & 3;
567 break;
568 case RI_NR33:
569 freq = 2048 - (((int)(R_NR34&7) << 8) | b);
570 if(freq)
571 S3.skip = SOUND_MAGIC_2 / freq;
572 else
573 S3.skip = 0;
574 break;
575 case RI_NR34:
576 freq = 2048 - (((b&7)<<8) | R_NR33);
578 if(freq)
579 S3.skip = SOUND_MAGIC_2 / freq;
580 else
581 S3.skip = 0;
583 S3.cont=b & 0x40;
584 if((b & 0x80) && (R_NR30 & 0x80))
586 R_NR52 |= 4;
587 S3.len = 172 * (256 - R_NR31);
588 S3.pos = 0;
589 S3.on = 1;
591 break;
592 case RI_NR41:
593 S4.len = 172 * (64 - (b & 0x3f));
594 break;
595 case RI_NR42:
596 S4.envol = b >> 4;
597 S4.endir = b & 0x08;
598 S4.enlenreload = S4.enlen = 689 * (b & 7);
599 break;
600 case RI_NR43:
601 freq = soundFreqRatio[b & 7];
603 S4.nsteps = b & 0x08;
604 S4.skip = (freq << 8) / NOISE_MAGIC;
605 S4.clock = b >> 4;
607 freq = freq / soundShiftClock[S4.clock];
608 S4.shiftskip = (freq << 8) / NOISE_MAGIC;
609 break;
610 case RI_NR44:
611 S4.cont = b & 0x40;
612 if(b & 0x80)
614 R_NR52 |= 8;
615 S4.envol = R_NR42 >> 4;
616 S4.endir = R_NR42 & 0x08;
617 S4.len = 172 * (64 - (R_NR41 & 0x3f));
618 S4.enlenreload = S4.enlen = 689 * (R_NR42 & 7);
620 S4.on = 1;
622 S4.pos = 0;
623 S4.shiftpos = 0;
625 freq = soundFreqRatio[R_NR43 & 7];
627 S4.shiftpos = (freq << 8) / NOISE_MAGIC;
629 S4.nsteps = R_NR43 & 0x08;
631 freq = freq / soundShiftClock[R_NR43 >> 4];
633 S4.shiftskip = (freq << 8) / NOISE_MAGIC;
634 if(S4.nsteps)
636 S4.shiftright = 0x7fff;
638 else
640 S4.shiftright = 0x7f;
643 break;
644 case RI_NR50:
645 snd.level1 = b & 7;
646 snd.level2 = (b >> 4) & 7;
647 break;
648 case RI_NR51:
649 snd.balance = b;
650 break;
651 case RI_NR52:
652 if (!(b & 0x80))
654 S1.on=0;
655 S2.on=0;
656 S3.on=0;
657 S4.on=0;
659 break;
662 snd.gbDigitalSound = true;
664 if(S1.on && S1.envol != 0)
665 snd.gbDigitalSound = false;
666 if(S2.on && S2.envol != 0)
667 snd.gbDigitalSound = false;
668 if(S3.on && S3.outputlevel != 0)
669 snd.gbDigitalSound = false;
670 if(S4.on && S4.envol != 0)
671 snd.gbDigitalSound = false;
674 void sound_reset(void)
676 snd.level1 = 7;
677 snd.level2 = 7;
678 S1.on = S2.on = S3.on = S4.on = 0;
679 S1.len = S2.len = S3.len = S4.len = 0;
680 S1.skip = S2.skip = S3.skip = S4.skip = 0;
681 S1.pos = S2.pos = S3.pos = S4.pos = 0;
682 S1.cont = S2.cont = S3.cont = S4.cont = 0;
683 S1.envol = S2.envol = S4.envol = 0;
684 S1.enlen = S2.enlen = S4.enlen = 0;
685 S1.endir = S2.endir = S4.endir = 0;
686 S1.enlenreload = S2.enlenreload = S4.enlenreload = 0;
687 S1.swlen = 0;
688 S1.swlenreload = 0;
689 S1.swsteps = 0;
690 S1.swdir = 0;
691 S1.swstep = 0;
692 S1.wave = S2.wave = soundWavePattern[2];
694 S3.outputlevel = 0;
696 S4.clock = 0;
697 S4.shiftright = 0x7f;
698 S4.nsteps = 0;
700 sound_write(0x10, 0x80);
701 sound_write(0x11, 0xbf);
702 sound_write(0x12, 0xf3);
703 sound_write(0x14, 0xbf);
704 sound_write(0x16, 0x3f);
705 sound_write(0x17, 0x00);
706 sound_write(0x19, 0xbf);
708 sound_write(0x1a, 0x7f);
709 sound_write(0x1b, 0xff);
710 sound_write(0x1c, 0xbf);
711 sound_write(0x1e, 0xbf);
713 sound_write(0x20, 0xff);
714 sound_write(0x21, 0x00);
715 sound_write(0x22, 0x00);
716 sound_write(0x23, 0xbf);
717 sound_write(0x24, 0x77);
718 sound_write(0x25, 0xf3);
720 sound_write(0x26, 0xf0);
722 S1.on = 0;
723 S2.on = 0;
724 S3.on = 0;
725 S4.on = 0;
727 int addr = 0x30;
728 while(addr < 0x40)
730 ram.hi[addr++] = 0x00;
731 ram.hi[addr++] = 0xff;
734 if (pcm.hz)
736 snd.rate = (1<<21) / pcm.hz;
737 snd.quality=44100 / pcm.hz;
739 else snd.rate = 0;
742 void sound_dirty(void)
744 sound_write(RI_NR10, R_NR10);
745 sound_write(RI_NR11, R_NR11);
746 sound_write(RI_NR12, R_NR12);
747 sound_write(RI_NR13, R_NR13);
748 sound_write(RI_NR14, R_NR14);
750 sound_write(RI_NR21, R_NR21);
751 sound_write(RI_NR22, R_NR22);
752 sound_write(RI_NR23, R_NR23);
753 sound_write(RI_NR24, R_NR24);
755 sound_write(RI_NR30, R_NR30);
756 sound_write(RI_NR31, R_NR31);
757 sound_write(RI_NR32, R_NR32);
758 sound_write(RI_NR33, R_NR33);
759 sound_write(RI_NR34, R_NR34);
761 sound_write(RI_NR42, R_NR42);
762 sound_write(RI_NR43, R_NR43);
763 sound_write(RI_NR44, R_NR44);
765 sound_write(RI_NR50, R_NR50);
766 sound_write(RI_NR51, R_NR51);
767 sound_write(RI_NR52, R_NR52);