2007-07-21 04:00:58 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* The following code is rewrite of the C++ code provided in VisualBoyAdvance.
|
|
|
|
* There are also portions of the original GNUboy code.
|
|
|
|
* Copyright (C) 2001 the GNUboy development team
|
|
|
|
*
|
|
|
|
* VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
|
|
|
* Copyright (C) 1999-2003 Forgotten
|
|
|
|
* Copyright (C) 2004 Forgotten and the VBA development team
|
|
|
|
*
|
|
|
|
* VisualBoyAdvance conversion from C++ to C by Karl Kurbjun July, 2007
|
|
|
|
*
|
2008-06-28 18:10:04 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2007-07-21 04:00:58 +00:00
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2005-03-02 23:49:38 +00:00
|
|
|
#include "rockmacros.h"
|
|
|
|
#include "defs.h"
|
|
|
|
#include "pcm.h"
|
|
|
|
#include "sound.h"
|
2005-07-03 14:05:12 +00:00
|
|
|
#include "cpu-gb.h"
|
2005-03-02 23:49:38 +00:00
|
|
|
#include "hw.h"
|
|
|
|
#include "regs.h"
|
2007-06-24 16:00:55 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
static const byte soundWavePattern[4][32] = {
|
|
|
|
{0x01,0x01,0x01,0x01,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff},
|
|
|
|
{0x01,0x01,0x01,0x01,
|
|
|
|
0x01,0x01,0x01,0x01,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff},
|
|
|
|
{0x01,0x01,0x01,0x01,
|
|
|
|
0x01,0x01,0x01,0x01,
|
|
|
|
0x01,0x01,0x01,0x01,
|
|
|
|
0x01,0x01,0x01,0x01,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff},
|
|
|
|
{0x01,0x01,0x01,0x01,
|
|
|
|
0x01,0x01,0x01,0x01,
|
|
|
|
0x01,0x01,0x01,0x01,
|
|
|
|
0x01,0x01,0x01,0x01,
|
|
|
|
0x01,0x01,0x01,0x01,
|
|
|
|
0x01,0x01,0x01,0x01,
|
|
|
|
0xff,0xff,0xff,0xff,
|
|
|
|
0xff,0xff,0xff,0xff}
|
2007-07-21 04:23:15 +00:00
|
|
|
};
|
2007-07-21 04:00:58 +00:00
|
|
|
|
2007-07-21 04:23:15 +00:00
|
|
|
int soundFreqRatio[8] ICONST_ATTR= {
|
2007-07-21 04:00:58 +00:00
|
|
|
1048576, // 0
|
|
|
|
524288, // 1
|
|
|
|
262144, // 2
|
|
|
|
174763, // 3
|
|
|
|
131072, // 4
|
|
|
|
104858, // 5
|
|
|
|
87381, // 6
|
|
|
|
74898 // 7
|
2007-07-21 04:23:15 +00:00
|
|
|
};
|
2007-07-21 04:00:58 +00:00
|
|
|
|
2007-07-21 04:23:15 +00:00
|
|
|
int soundShiftClock[16] ICONST_ATTR= {
|
2007-07-21 04:00:58 +00:00
|
|
|
2, // 0
|
|
|
|
4, // 1
|
|
|
|
8, // 2
|
|
|
|
16, // 3
|
|
|
|
32, // 4
|
|
|
|
64, // 5
|
|
|
|
128, // 6
|
|
|
|
256, // 7
|
|
|
|
512, // 8
|
|
|
|
1024, // 9
|
|
|
|
2048, // 10
|
|
|
|
4096, // 11
|
|
|
|
8192, // 12
|
|
|
|
16384, // 13
|
|
|
|
1, // 14
|
|
|
|
1 // 15
|
2007-07-21 04:23:15 +00:00
|
|
|
};
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2006-01-20 13:05:52 +00:00
|
|
|
struct snd snd IBSS_ATTR;
|
2005-03-02 23:49:38 +00:00
|
|
|
|
|
|
|
#define RATE (snd.rate)
|
2007-02-06 21:41:08 +00:00
|
|
|
#define WAVE (ram.hi+0x30)
|
2005-03-02 23:49:38 +00:00
|
|
|
#define S1 (snd.ch[0])
|
|
|
|
#define S2 (snd.ch[1])
|
|
|
|
#define S3 (snd.ch[2])
|
|
|
|
#define S4 (snd.ch[3])
|
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
#define SOUND_MAGIC 0x60000000
|
|
|
|
#define SOUND_MAGIC_2 0x30000000
|
|
|
|
#define NOISE_MAGIC 5
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
static void gbSoundChannel1(int *r, int *l)
|
2005-03-02 23:49:38 +00:00
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
int vol = S1.envol;
|
2008-11-12 04:15:34 +00:00
|
|
|
|
|
|
|
int freq = 0;
|
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
int value = 0;
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
if(S1.on && (S1.len || !S1.cont))
|
|
|
|
{
|
|
|
|
S1.pos += snd.quality*S1.skip;
|
|
|
|
S1.pos &= 0x1fffffff;
|
2007-06-24 16:00:55 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
value = ((signed char)S1.wave[S1.pos>>24]) * vol;
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
if (snd.balance & 1) *r += value;
|
|
|
|
if (snd.balance & 16) *l += value;
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
if(S1.on)
|
2005-03-02 23:49:38 +00:00
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
if(S1.len)
|
2005-03-02 23:49:38 +00:00
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
S1.len-=snd.quality;
|
|
|
|
|
|
|
|
if(S1.len <=0 && S1.cont)
|
|
|
|
{
|
|
|
|
R_NR52 &= 0xfe;
|
2005-03-02 23:49:38 +00:00
|
|
|
S1.on = 0;
|
2007-07-21 04:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(S1.enlen)
|
|
|
|
{
|
|
|
|
S1.enlen-=snd.quality;
|
|
|
|
|
|
|
|
if(S1.enlen<=0)
|
2005-03-02 23:49:38 +00:00
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
if(S1.endir)
|
|
|
|
{
|
|
|
|
if(S1.envol < 15)
|
|
|
|
S1.envol++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(S1.envol)
|
|
|
|
S1.envol--;
|
|
|
|
}
|
|
|
|
|
|
|
|
S1.enlen += S1.enlenreload;
|
2005-03-02 23:49:38 +00:00
|
|
|
}
|
2007-07-21 04:00:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(S1.swlen)
|
|
|
|
{
|
|
|
|
S1.swlen-=snd.quality;
|
|
|
|
|
|
|
|
if(S1.swlen<=0)
|
2005-03-02 23:49:38 +00:00
|
|
|
{
|
2008-11-12 04:15:34 +00:00
|
|
|
freq = (((int)(R_NR14&7) << 8) | R_NR13);
|
2007-07-21 04:00:58 +00:00
|
|
|
|
|
|
|
int updown = 1;
|
|
|
|
|
|
|
|
if(S1.swdir)
|
|
|
|
updown = -1;
|
|
|
|
|
|
|
|
int newfreq = 0;
|
|
|
|
if(S1.swsteps)
|
|
|
|
{
|
|
|
|
newfreq = freq + updown * freq / (1 << S1.swsteps);
|
|
|
|
if(newfreq == freq)
|
|
|
|
newfreq = 0;
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
else
|
2007-07-21 04:00:58 +00:00
|
|
|
newfreq = freq;
|
|
|
|
|
|
|
|
if(newfreq < 0)
|
2005-03-02 23:49:38 +00:00
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
S1.swlen += S1.swlenreload;
|
|
|
|
}
|
|
|
|
else if(newfreq > 2047)
|
|
|
|
{
|
|
|
|
S1.swlen = 0;
|
|
|
|
S1.on = 0;
|
|
|
|
R_NR52 &= 0xfe;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
S1.swlen += S1.swlenreload;
|
|
|
|
S1.skip = SOUND_MAGIC/(2048 - newfreq);
|
|
|
|
|
|
|
|
R_NR13 = newfreq & 0xff;
|
|
|
|
R_NR14 = (R_NR14 & 0xf8) |((newfreq >> 8) & 7);
|
2005-03-02 23:49:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-07-21 04:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
static void gbSoundChannel2(int *r, int *l)
|
|
|
|
{
|
|
|
|
int vol = S2.envol;
|
|
|
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
if(S2.on && (S2.len || !S2.cont))
|
|
|
|
{
|
|
|
|
S2.pos += snd.quality*S2.skip;
|
|
|
|
S2.pos &= 0x1fffffff;
|
|
|
|
|
|
|
|
value = ((signed char)S2.wave[S2.pos>>24]) * vol;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (snd.balance & 2) *r += value;
|
|
|
|
if (snd.balance & 32) *l += value;
|
|
|
|
|
|
|
|
if(S2.on) {
|
|
|
|
if(S2.len) {
|
|
|
|
S2.len-=snd.quality;
|
|
|
|
|
|
|
|
if(S2.len <= 0 && S2.cont) {
|
|
|
|
R_NR52 &= 0xfd;
|
2005-03-02 23:49:38 +00:00
|
|
|
S2.on = 0;
|
|
|
|
}
|
|
|
|
}
|
2007-07-21 04:00:58 +00:00
|
|
|
|
|
|
|
if(S2.enlen) {
|
|
|
|
S2.enlen-=snd.quality;
|
|
|
|
|
|
|
|
if(S2.enlen <= 0) {
|
|
|
|
if(S2.endir) {
|
|
|
|
if(S2.envol < 15)
|
|
|
|
S2.envol++;
|
|
|
|
} else {
|
|
|
|
if(S2.envol)
|
|
|
|
S2.envol--;
|
|
|
|
}
|
|
|
|
S2.enlen += S2.enlenreload;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gbSoundChannel3(int *r, int *l)
|
|
|
|
{
|
|
|
|
int s;
|
|
|
|
if (S3.on && (S3.len || !S3.cont))
|
|
|
|
{
|
|
|
|
S3.pos += S3.skip*snd.quality;
|
|
|
|
S3.pos &= 0x1fffffff;
|
|
|
|
s=ram.hi[0x30 + (S3.pos>>25)];
|
|
|
|
if (S3.pos & 0x01000000)
|
|
|
|
s &= 0x0f;
|
|
|
|
else
|
|
|
|
s >>= 4;
|
|
|
|
|
|
|
|
s -= 8;
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
switch(S3.outputlevel)
|
2005-03-02 23:49:38 +00:00
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
case 0:
|
|
|
|
s=0;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
s=s>>1;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
s=s>>2;
|
|
|
|
break;
|
2005-03-02 23:49:38 +00:00
|
|
|
}
|
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
if (snd.balance & 4) *r += s;
|
|
|
|
if (snd.balance & 64) *l += s;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(S3.on)
|
|
|
|
{
|
|
|
|
if(S3.len)
|
2005-03-02 23:49:38 +00:00
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
S3.len-=snd.quality;
|
|
|
|
if(S3.len<=0 && S3.cont)
|
|
|
|
{
|
|
|
|
R_NR52 &= 0xFB;
|
|
|
|
S3.on=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-16 18:16:22 +00:00
|
|
|
static void gbSoundChannel4(int *r, int *l)
|
2007-07-21 04:00:58 +00:00
|
|
|
{
|
|
|
|
int vol = S4.envol;
|
|
|
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
if(S4.clock <= 0x0c)
|
|
|
|
{
|
|
|
|
if(S4.on && (S4.len || !S4.cont))
|
|
|
|
{
|
|
|
|
S4.pos += snd.quality*S4.skip;
|
|
|
|
S4.shiftpos += snd.quality*S4.shiftskip;
|
|
|
|
|
|
|
|
if(S4.nsteps)
|
|
|
|
{
|
|
|
|
while(S4.shiftpos > 0x1fffff) {
|
|
|
|
S4.shiftright = (((S4.shiftright << 6) ^
|
|
|
|
(S4.shiftright << 5)) & 0x40) | (S4.shiftright >> 1);
|
|
|
|
S4.shiftpos -= 0x200000;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while(S4.shiftpos > 0x1fffff)
|
|
|
|
{
|
|
|
|
S4.shiftright = (((S4.shiftright << 14) ^
|
|
|
|
(S4.shiftright << 13)) & 0x4000) | (S4.shiftright >> 1);
|
|
|
|
S4.shiftpos -= 0x200000;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
S4.pos &= 0x1fffff;
|
|
|
|
S4.shiftpos &= 0x1fffff;
|
|
|
|
|
|
|
|
value = ((S4.shiftright & 1)*2-1) * vol;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (snd.balance & 8) *r += value;
|
|
|
|
if (snd.balance & 128) *l += value;
|
|
|
|
|
|
|
|
if(S4.on) {
|
|
|
|
if(S4.len) {
|
|
|
|
S4.len-=snd.quality;
|
|
|
|
|
|
|
|
if(S4.len <= 0 && S4.cont) {
|
|
|
|
R_NR52 &= 0xfd;
|
2005-03-02 23:49:38 +00:00
|
|
|
S4.on = 0;
|
2007-07-21 04:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(S4.enlen) {
|
|
|
|
S4.enlen-=snd.quality;
|
|
|
|
|
|
|
|
if(S4.enlen <= 0)
|
2005-03-02 23:49:38 +00:00
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
if(S4.endir)
|
|
|
|
{
|
|
|
|
if(S4.envol < 15)
|
|
|
|
S4.envol++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(S4.envol)
|
|
|
|
S4.envol--;
|
|
|
|
}
|
|
|
|
S4.enlen += S4.enlenreload;
|
2005-03-02 23:49:38 +00:00
|
|
|
}
|
|
|
|
}
|
2007-07-21 04:00:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sound_mix(void)
|
|
|
|
{
|
|
|
|
int l, r;
|
|
|
|
|
|
|
|
if (!RATE || cpu.snd < RATE) return;
|
|
|
|
|
|
|
|
for (; cpu.snd >= RATE; cpu.snd -= RATE)
|
|
|
|
{
|
|
|
|
l = r = 0;
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
gbSoundChannel1(&r,&l);
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
gbSoundChannel2(&r,&l);
|
|
|
|
|
|
|
|
gbSoundChannel3(&r,&l);
|
|
|
|
|
|
|
|
gbSoundChannel4(&r,&l);
|
|
|
|
|
|
|
|
if(snd.gbDigitalSound)
|
|
|
|
{
|
|
|
|
l = snd.level1<<8;
|
|
|
|
r = snd.level2<<8;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l *= snd.level1*60;
|
|
|
|
r *= snd.level2*60;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(l > 32767)
|
|
|
|
l = 32767;
|
|
|
|
if(l < -32768)
|
|
|
|
l = -32768;
|
|
|
|
|
|
|
|
if(r > 32767)
|
|
|
|
r = 32767;
|
|
|
|
if(r < -32768)
|
|
|
|
r = -32768;
|
2005-03-02 23:49:38 +00:00
|
|
|
|
|
|
|
if (pcm.buf)
|
|
|
|
{
|
|
|
|
if (pcm.pos >= pcm.len)
|
|
|
|
pcm_submit();
|
|
|
|
if (pcm.stereo)
|
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
pcm.buf[pcm.pos++] = l;
|
|
|
|
pcm.buf[pcm.pos++] = r;
|
2005-03-02 23:49:38 +00:00
|
|
|
}
|
2007-07-21 04:00:58 +00:00
|
|
|
else pcm.buf[pcm.pos++] = ((l+r)>>1);
|
2005-03-02 23:49:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3);
|
|
|
|
}
|
|
|
|
|
|
|
|
byte sound_read(byte r)
|
|
|
|
{
|
2007-02-06 21:41:08 +00:00
|
|
|
if(!options.sound) return 0;
|
2005-03-02 23:49:38 +00:00
|
|
|
sound_mix();
|
|
|
|
/* printf("read %02X: %02X\n", r, REG(r)); */
|
|
|
|
return REG(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
void sound_write(byte r, byte b)
|
|
|
|
{
|
2007-07-21 04:00:58 +00:00
|
|
|
int freq=0;
|
|
|
|
ram.hi[r]=b;
|
2005-03-02 23:49:38 +00:00
|
|
|
|
2007-07-21 04:00:58 +00:00
|
|
|
if(!options.sound)
|
2005-03-02 23:49:38 +00:00
|
|
|
return;
|
2007-07-21 04:00:58 +00:00
|
|
|
|
2005-03-02 23:49:38 +00:00
|
|
|
sound_mix();
|
2007-07-21 04:00:58 +00:00
|
|
|
|
2005-03-02 23:49:38 +00:00
|
|
|
switch (r)
|
|
|
|
{
|
|
|
|
case RI_NR10:
|
2007-07-21 04:00:58 +00:00
|
|
|
S1.swlen = S1.swlenreload = 344 * ((b >> 4) & 7);
|
|
|
|
S1.swsteps = b & 7;
|
|
|
|
S1.swdir = b & 0x08;
|
|
|
|
S1.swstep = 0;
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR11:
|
2007-07-21 04:00:58 +00:00
|
|
|
S1.len = 172 * (64 - (b & 0x3f));
|
|
|
|
S1.wave = soundWavePattern[b >> 6];
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR12:
|
2007-07-21 04:00:58 +00:00
|
|
|
S1.envol = b >> 4;
|
|
|
|
S1.endir = b & 0x08;
|
|
|
|
S1.enlenreload = S1.enlen = 689 * (b & 7);
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR13:
|
2007-07-21 04:00:58 +00:00
|
|
|
freq = (((int)(R_NR14 & 7)) << 8) | b;
|
|
|
|
S1.len = 172 * (64 - (R_NR11 & 0x3f));
|
|
|
|
freq = 2048 - freq;
|
|
|
|
if(freq)
|
|
|
|
{
|
|
|
|
S1.skip = SOUND_MAGIC / freq;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
S1.skip = 0;
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR14:
|
2007-07-21 04:00:58 +00:00
|
|
|
freq = (((int)(b&7) << 8) | R_NR13);
|
|
|
|
freq = 2048 - freq;
|
|
|
|
S1.len = 172 * (64 - (R_NR11 & 0x3f));
|
|
|
|
S1.cont = b & 0x40;
|
|
|
|
if(freq)
|
|
|
|
{
|
|
|
|
S1.skip = SOUND_MAGIC / freq;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
S1.skip = 0;
|
|
|
|
}
|
|
|
|
if(b & 0x80)
|
|
|
|
{
|
|
|
|
R_NR52 |= 1;
|
|
|
|
S1.envol = R_NR12 >> 4;
|
|
|
|
S1.endir = R_NR12 & 0x08;
|
|
|
|
S1.len = 172 * (64 - (R_NR11 & 0x3f));
|
|
|
|
S1.enlenreload = S1.enlen = 689 * (R_NR12 & 7);
|
|
|
|
S1.swlen = S1.swlenreload = 344 * ((R_NR10 >> 4) & 7);
|
|
|
|
S1.swsteps = R_NR10 & 7;
|
|
|
|
S1.swdir = R_NR10 & 0x08;
|
|
|
|
S1.swstep = 0;
|
|
|
|
|
|
|
|
S1.pos = 0;
|
|
|
|
S1.on = 1;
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR21:
|
2007-07-21 04:00:58 +00:00
|
|
|
S2.wave = soundWavePattern[b >> 6];
|
|
|
|
S2.len = 172 * (64 - (b & 0x3f));
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR22:
|
2007-07-21 04:00:58 +00:00
|
|
|
S2.envol = b >> 4;
|
|
|
|
S2.endir = b & 0x08;
|
|
|
|
S2.enlenreload = S2.enlen = 689 * (b & 7);
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR23:
|
2007-07-21 04:00:58 +00:00
|
|
|
freq = (((int)(R_NR24 & 7)) << 8) | b;
|
|
|
|
S2.len = 172 * (64 - (R_NR21 & 0x3f));
|
|
|
|
freq = 2048 - freq;
|
|
|
|
if(freq)
|
|
|
|
{
|
|
|
|
S2.skip = SOUND_MAGIC / freq;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
S2.skip = 0;
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR24:
|
2007-07-21 04:00:58 +00:00
|
|
|
freq = (((int)(b&7) << 8) | R_NR23);
|
|
|
|
freq = 2048 - freq;
|
|
|
|
S2.len = 172 * (64 - (R_NR21 & 0x3f));
|
|
|
|
S2.cont = b & 0x40;
|
|
|
|
if(freq) {
|
|
|
|
S2.skip = SOUND_MAGIC / freq;
|
|
|
|
} else
|
|
|
|
S2.skip = 0;
|
|
|
|
if(b & 0x80) {
|
|
|
|
R_NR52 |= 2;
|
|
|
|
S2.envol = R_NR22 >> 4;
|
|
|
|
S2.endir = R_NR22 & 0x08;
|
|
|
|
S2.len = 172 * (64 - (R_NR21 & 0x3f));
|
|
|
|
S2.enlenreload = S2.enlen = 689 * (R_NR22 & 7);
|
|
|
|
|
|
|
|
S2.pos = 0;
|
|
|
|
S2.on = 1;
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR30:
|
2007-07-21 04:00:58 +00:00
|
|
|
if (!(b & 0x80)){
|
|
|
|
R_NR52 &= 0xfb;
|
|
|
|
S3.on = 0;
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR31:
|
2007-07-21 04:00:58 +00:00
|
|
|
S3.len = (256-R_NR31) * 172;
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR32:
|
2007-07-21 04:00:58 +00:00
|
|
|
S3.outputlevel = (b >> 5) & 3;
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR33:
|
2007-07-21 04:00:58 +00:00
|
|
|
freq = 2048 - (((int)(R_NR34&7) << 8) | b);
|
|
|
|
if(freq)
|
|
|
|
S3.skip = SOUND_MAGIC_2 / freq;
|
|
|
|
else
|
|
|
|
S3.skip = 0;
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR34:
|
2007-07-21 04:00:58 +00:00
|
|
|
freq = 2048 - (((b&7)<<8) | R_NR33);
|
|
|
|
|
|
|
|
if(freq)
|
|
|
|
S3.skip = SOUND_MAGIC_2 / freq;
|
|
|
|
else
|
|
|
|
S3.skip = 0;
|
|
|
|
|
|
|
|
S3.cont=b & 0x40;
|
|
|
|
if((b & 0x80) && (R_NR30 & 0x80))
|
|
|
|
{
|
|
|
|
R_NR52 |= 4;
|
|
|
|
S3.len = 172 * (256 - R_NR31);
|
|
|
|
S3.pos = 0;
|
|
|
|
S3.on = 1;
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR41:
|
2007-07-21 04:00:58 +00:00
|
|
|
S4.len = 172 * (64 - (b & 0x3f));
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR42:
|
2007-07-21 04:00:58 +00:00
|
|
|
S4.envol = b >> 4;
|
|
|
|
S4.endir = b & 0x08;
|
|
|
|
S4.enlenreload = S4.enlen = 689 * (b & 7);
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR43:
|
2007-07-21 04:00:58 +00:00
|
|
|
freq = soundFreqRatio[b & 7];
|
|
|
|
|
|
|
|
S4.nsteps = b & 0x08;
|
|
|
|
S4.skip = (freq << 8) / NOISE_MAGIC;
|
|
|
|
S4.clock = b >> 4;
|
|
|
|
|
|
|
|
freq = freq / soundShiftClock[S4.clock];
|
|
|
|
S4.shiftskip = (freq << 8) / NOISE_MAGIC;
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR44:
|
2007-07-21 04:00:58 +00:00
|
|
|
S4.cont = b & 0x40;
|
|
|
|
if(b & 0x80)
|
|
|
|
{
|
|
|
|
R_NR52 |= 8;
|
|
|
|
S4.envol = R_NR42 >> 4;
|
|
|
|
S4.endir = R_NR42 & 0x08;
|
|
|
|
S4.len = 172 * (64 - (R_NR41 & 0x3f));
|
|
|
|
S4.enlenreload = S4.enlen = 689 * (R_NR42 & 7);
|
|
|
|
|
|
|
|
S4.on = 1;
|
|
|
|
|
|
|
|
S4.pos = 0;
|
|
|
|
S4.shiftpos = 0;
|
|
|
|
|
|
|
|
freq = soundFreqRatio[R_NR43 & 7];
|
|
|
|
|
|
|
|
S4.shiftpos = (freq << 8) / NOISE_MAGIC;
|
|
|
|
|
|
|
|
S4.nsteps = R_NR43 & 0x08;
|
|
|
|
|
|
|
|
freq = freq / soundShiftClock[R_NR43 >> 4];
|
|
|
|
|
|
|
|
S4.shiftskip = (freq << 8) / NOISE_MAGIC;
|
|
|
|
if(S4.nsteps)
|
|
|
|
{
|
|
|
|
S4.shiftright = 0x7fff;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
S4.shiftright = 0x7f;
|
|
|
|
}
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR50:
|
2007-07-21 04:00:58 +00:00
|
|
|
snd.level1 = b & 7;
|
|
|
|
snd.level2 = (b >> 4) & 7;
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR51:
|
2007-07-21 04:00:58 +00:00
|
|
|
snd.balance = b;
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
case RI_NR52:
|
2007-07-21 04:00:58 +00:00
|
|
|
if (!(b & 0x80))
|
|
|
|
{
|
|
|
|
S1.on=0;
|
|
|
|
S2.on=0;
|
|
|
|
S3.on=0;
|
|
|
|
S4.on=0;
|
|
|
|
}
|
2005-03-02 23:49:38 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-07-21 04:00:58 +00:00
|
|
|
|
|
|
|
snd.gbDigitalSound = true;
|
|
|
|
|
|
|
|
if(S1.on && S1.envol != 0)
|
|
|
|
snd.gbDigitalSound = false;
|
|
|
|
if(S2.on && S2.envol != 0)
|
|
|
|
snd.gbDigitalSound = false;
|
|
|
|
if(S3.on && S3.outputlevel != 0)
|
|
|
|
snd.gbDigitalSound = false;
|
|
|
|
if(S4.on && S4.envol != 0)
|
|
|
|
snd.gbDigitalSound = false;
|
|
|
|
}
|
|
|
|
|
2007-10-16 18:16:22 +00:00
|
|
|
void sound_reset(void)
|
2007-07-21 04:00:58 +00:00
|
|
|
{
|
|
|
|
snd.level1 = 7;
|
|
|
|
snd.level2 = 7;
|
|
|
|
S1.on = S2.on = S3.on = S4.on = 0;
|
|
|
|
S1.len = S2.len = S3.len = S4.len = 0;
|
|
|
|
S1.skip = S2.skip = S3.skip = S4.skip = 0;
|
|
|
|
S1.pos = S2.pos = S3.pos = S4.pos = 0;
|
|
|
|
S1.cont = S2.cont = S3.cont = S4.cont = 0;
|
|
|
|
S1.envol = S2.envol = S4.envol = 0;
|
|
|
|
S1.enlen = S2.enlen = S4.enlen = 0;
|
|
|
|
S1.endir = S2.endir = S4.endir = 0;
|
|
|
|
S1.enlenreload = S2.enlenreload = S4.enlenreload = 0;
|
|
|
|
S1.swlen = 0;
|
|
|
|
S1.swlenreload = 0;
|
|
|
|
S1.swsteps = 0;
|
|
|
|
S1.swdir = 0;
|
|
|
|
S1.swstep = 0;
|
|
|
|
S1.wave = S2.wave = soundWavePattern[2];
|
|
|
|
|
|
|
|
S3.outputlevel = 0;
|
|
|
|
|
|
|
|
S4.clock = 0;
|
|
|
|
S4.shiftright = 0x7f;
|
|
|
|
S4.nsteps = 0;
|
|
|
|
|
|
|
|
sound_write(0x10, 0x80);
|
|
|
|
sound_write(0x11, 0xbf);
|
|
|
|
sound_write(0x12, 0xf3);
|
|
|
|
sound_write(0x14, 0xbf);
|
|
|
|
sound_write(0x16, 0x3f);
|
|
|
|
sound_write(0x17, 0x00);
|
|
|
|
sound_write(0x19, 0xbf);
|
|
|
|
|
|
|
|
sound_write(0x1a, 0x7f);
|
|
|
|
sound_write(0x1b, 0xff);
|
|
|
|
sound_write(0x1c, 0xbf);
|
|
|
|
sound_write(0x1e, 0xbf);
|
|
|
|
|
|
|
|
sound_write(0x20, 0xff);
|
|
|
|
sound_write(0x21, 0x00);
|
|
|
|
sound_write(0x22, 0x00);
|
|
|
|
sound_write(0x23, 0xbf);
|
|
|
|
sound_write(0x24, 0x77);
|
|
|
|
sound_write(0x25, 0xf3);
|
|
|
|
|
|
|
|
sound_write(0x26, 0xf0);
|
|
|
|
|
|
|
|
S1.on = 0;
|
|
|
|
S2.on = 0;
|
|
|
|
S3.on = 0;
|
|
|
|
S4.on = 0;
|
|
|
|
|
|
|
|
int addr = 0x30;
|
|
|
|
while(addr < 0x40)
|
|
|
|
{
|
|
|
|
ram.hi[addr++] = 0x00;
|
|
|
|
ram.hi[addr++] = 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pcm.hz)
|
|
|
|
{
|
|
|
|
snd.rate = (1<<21) / pcm.hz;
|
|
|
|
snd.quality=44100 / pcm.hz;
|
|
|
|
}
|
|
|
|
else snd.rate = 0;
|
|
|
|
}
|
|
|
|
|
2007-10-16 18:16:22 +00:00
|
|
|
void sound_dirty(void)
|
2007-07-21 04:00:58 +00:00
|
|
|
{
|
|
|
|
sound_write(RI_NR10, R_NR10);
|
|
|
|
sound_write(RI_NR11, R_NR11);
|
|
|
|
sound_write(RI_NR12, R_NR12);
|
|
|
|
sound_write(RI_NR13, R_NR13);
|
|
|
|
sound_write(RI_NR14, R_NR14);
|
|
|
|
|
|
|
|
sound_write(RI_NR21, R_NR21);
|
|
|
|
sound_write(RI_NR22, R_NR22);
|
|
|
|
sound_write(RI_NR23, R_NR23);
|
|
|
|
sound_write(RI_NR24, R_NR24);
|
|
|
|
|
|
|
|
sound_write(RI_NR30, R_NR30);
|
|
|
|
sound_write(RI_NR31, R_NR31);
|
|
|
|
sound_write(RI_NR32, R_NR32);
|
|
|
|
sound_write(RI_NR33, R_NR33);
|
|
|
|
sound_write(RI_NR34, R_NR34);
|
|
|
|
|
|
|
|
sound_write(RI_NR42, R_NR42);
|
|
|
|
sound_write(RI_NR43, R_NR43);
|
|
|
|
sound_write(RI_NR44, R_NR44);
|
|
|
|
|
|
|
|
sound_write(RI_NR50, R_NR50);
|
|
|
|
sound_write(RI_NR51, R_NR51);
|
|
|
|
sound_write(RI_NR52, R_NR52);
|
2005-03-02 23:49:38 +00:00
|
|
|
}
|