1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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"
38 static const byte soundWavePattern
[4][32] = {
73 int soundFreqRatio
[8] ICONST_ATTR
= {
84 int soundShiftClock
[16] ICONST_ATTR
= {
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
)
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
;
141 if(S1
.len
<=0 && S1
.cont
)
150 S1
.enlen
-=snd
.quality
;
165 S1
.enlen
+= S1
.enlenreload
;
171 S1
.swlen
-=snd
.quality
;
175 freq
= (((int)(R_NR14
&7) << 8) | R_NR13
);
185 newfreq
= freq
+ updown
* freq
/ BIT_N(S1
.swsteps
);
194 S1
.swlen
+= S1
.swlenreload
;
196 else if(newfreq
> 2047)
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
)
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
;
236 if(S2
.len
<= 0 && S2
.cont
) {
243 S2
.enlen
-=snd
.quality
;
253 S2
.enlen
+= S2
.enlenreload
;
259 static void gbSoundChannel3(int *r
, int *l
)
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)
274 switch(S3
.outputlevel
)
289 if (snd
.balance
& 4) *r
+= s
;
290 if (snd
.balance
& 64) *l
+= s
;
298 if(S3
.len
<=0 && S3
.cont
)
307 static void gbSoundChannel4(int *r
, int *l
)
315 if(S4
.on
&& (S4
.len
|| !S4
.cont
))
317 S4
.pos
+= snd
.quality
*S4
.skip
;
318 S4
.shiftpos
+= snd
.quality
*S4
.shiftskip
;
322 while(S4
.shiftpos
> 0x1fffff) {
323 S4
.shiftright
= (((S4
.shiftright
<< 6) ^
324 (S4
.shiftright
<< 5)) & 0x40) | (S4
.shiftright
>> 1);
325 S4
.shiftpos
-= 0x200000;
330 while(S4
.shiftpos
> 0x1fffff)
332 S4
.shiftright
= (((S4
.shiftright
<< 14) ^
333 (S4
.shiftright
<< 13)) & 0x4000) | (S4
.shiftright
>> 1);
334 S4
.shiftpos
-= 0x200000;
339 S4
.shiftpos
&= 0x1fffff;
341 value
= ((S4
.shiftright
& 1)*2-1) * vol
;
349 if (snd
.balance
& 8) *r
+= value
;
350 if (snd
.balance
& 128) *l
+= value
;
356 if(S4
.len
<= 0 && S4
.cont
) {
363 S4
.enlen
-=snd
.quality
;
377 S4
.enlen
+= S4
.enlenreload
;
387 if (!RATE
|| cpu
.snd
< RATE
) return;
389 for (; cpu
.snd
>= RATE
; cpu
.snd
-= RATE
)
393 gbSoundChannel1(&r
,&l
);
395 gbSoundChannel2(&r
,&l
);
397 gbSoundChannel3(&r
,&l
);
399 gbSoundChannel4(&r
,&l
);
401 if(snd
.gbDigitalSound
)
424 if (pcm
.pos
>= pcm
.len
)
425 rockboy_pcm_submit();
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;
441 /* printf("read %02X: %02X\n", r, REG(r)); */
445 void sound_write(byte r
, byte b
)
458 S1
.swlen
= S1
.swlenreload
= 344 * ((b
>> 4) & 7);
464 S1
.len
= 172 * (64 - (b
& 0x3f));
465 S1
.wave
= soundWavePattern
[b
>> 6];
470 S1
.enlenreload
= S1
.enlen
= 689 * (b
& 7);
473 freq
= (((int)(R_NR14
& 7)) << 8) | b
;
474 S1
.len
= 172 * (64 - (R_NR11
& 0x3f));
478 S1
.skip
= SOUND_MAGIC
/ freq
;
486 freq
= (((int)(b
&7) << 8) | R_NR13
);
488 S1
.len
= 172 * (64 - (R_NR11
& 0x3f));
492 S1
.skip
= SOUND_MAGIC
/ freq
;
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;
515 S2
.wave
= soundWavePattern
[b
>> 6];
516 S2
.len
= 172 * (64 - (b
& 0x3f));
521 S2
.enlenreload
= S2
.enlen
= 689 * (b
& 7);
524 freq
= (((int)(R_NR24
& 7)) << 8) | b
;
525 S2
.len
= 172 * (64 - (R_NR21
& 0x3f));
529 S2
.skip
= SOUND_MAGIC
/ freq
;
537 freq
= (((int)(b
&7) << 8) | R_NR23
);
539 S2
.len
= 172 * (64 - (R_NR21
& 0x3f));
542 S2
.skip
= SOUND_MAGIC
/ freq
;
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);
563 S3
.len
= (256-R_NR31
) * 172;
566 S3
.outputlevel
= (b
>> 5) & 3;
569 freq
= 2048 - (((int)(R_NR34
&7) << 8) | b
);
571 S3
.skip
= SOUND_MAGIC_2
/ freq
;
576 freq
= 2048 - (((b
&7)<<8) | R_NR33
);
579 S3
.skip
= SOUND_MAGIC_2
/ freq
;
584 if((b
& 0x80) && (R_NR30
& 0x80))
587 S3
.len
= 172 * (256 - R_NR31
);
593 S4
.len
= 172 * (64 - (b
& 0x3f));
598 S4
.enlenreload
= S4
.enlen
= 689 * (b
& 7);
601 freq
= soundFreqRatio
[b
& 7];
603 S4
.nsteps
= b
& 0x08;
604 S4
.skip
= (freq
<< 8) / NOISE_MAGIC
;
607 freq
= freq
/ soundShiftClock
[S4
.clock
];
608 S4
.shiftskip
= (freq
<< 8) / NOISE_MAGIC
;
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);
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
;
636 S4
.shiftright
= 0x7fff;
640 S4
.shiftright
= 0x7f;
646 snd
.level2
= (b
>> 4) & 7;
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)
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;
692 S1
.wave
= S2
.wave
= soundWavePattern
[2];
697 S4
.shiftright
= 0x7f;
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);
730 ram
.hi
[addr
++] = 0x00;
731 ram
.hi
[addr
++] = 0xff;
736 snd
.rate
= (1<<21) / pcm
.hz
;
737 snd
.quality
=44100 / pcm
.hz
;
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
);