summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorKarl Kurbjun <kkurbjun@gmail.com>2007-07-21 04:00:58 +0000
committerKarl Kurbjun <kkurbjun@gmail.com>2007-07-21 04:00:58 +0000
commitfa3fc0c5c7e89ad6ce26e9d3563e3a064b018413 (patch)
tree6f7a0f73c8bf25ced6286614e01af7983b59070a /apps/plugins
parente9c09d4d0e1170c6c81991c2660608854d960a77 (diff)
downloadrockbox-fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413.zip
rockbox-fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413.tar.gz
rockbox-fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413.tar.bz2
rockbox-fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413.tar.xz
Commit FS #7379 - This patch fixes most of the sound problems from the previous version. This is a complete rewrite of VisualBoyAdvance's sound code from C++ to C. This patch also eliminates the need for some large tables giving more room in IRAM and the plugin buffer.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13947 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/rockboy/mem.c7
-rw-r--r--apps/plugins/rockboy/mem.h1
-rw-r--r--apps/plugins/rockboy/rbsound.c13
-rw-r--r--apps/plugins/rockboy/rockmacros.h1
-rw-r--r--apps/plugins/rockboy/save.c22
-rw-r--r--apps/plugins/rockboy/sound.c954
-rw-r--r--apps/plugins/rockboy/sound.h36
7 files changed, 688 insertions, 346 deletions
diff --git a/apps/plugins/rockboy/mem.c b/apps/plugins/rockboy/mem.c
index 8c0bea0..6811fd5 100644
--- a/apps/plugins/rockboy/mem.c
+++ b/apps/plugins/rockboy/mem.c
@@ -562,10 +562,3 @@ void mbc_reset(void)
mbc.enableram = 0;
mem_updatemap();
}
-
-
-
-
-
-
-
diff --git a/apps/plugins/rockboy/mem.h b/apps/plugins/rockboy/mem.h
index 005c495..338fd98 100644
--- a/apps/plugins/rockboy/mem.h
+++ b/apps/plugins/rockboy/mem.h
@@ -41,7 +41,6 @@ struct ram
int loaded;
};
-
extern struct mbc mbc;
extern struct rom rom;
extern struct ram ram;
diff --git a/apps/plugins/rockboy/rbsound.c b/apps/plugins/rockboy/rbsound.c
index fe2c27a..b5cfc96 100644
--- a/apps/plugins/rockboy/rbsound.c
+++ b/apps/plugins/rockboy/rbsound.c
@@ -12,13 +12,14 @@ struct pcm pcm IBSS_ATTR;
bool doneplay=1;
bool bufnum=0;
-static unsigned short *buf=0;
+static unsigned short *buf=0, *hwbuf=0;
static bool newly_started;
void get_more(unsigned char** start, size_t* size)
{
- *start = (unsigned char*)(&buf[pcm.len*doneplay]);
+ memcpy(hwbuf, &buf[pcm.len*doneplay], BUF_SIZE*sizeof(short));
+ *start = (unsigned char*)(hwbuf);
*size = BUF_SIZE*sizeof(short);
doneplay=1;
}
@@ -29,14 +30,20 @@ void pcm_init(void)
return;
newly_started = true;
-
+
+#if defined(HW_HAVE_11) && !defined(TOSHIBA_GIGABEAT_F)
+ pcm.hz = SAMPR_11;
+#else
pcm.hz = SAMPR_44;
+#endif
+
pcm.stereo = 1;
pcm.len = BUF_SIZE;
if(!buf)
{
buf = my_malloc(pcm.len * N_BUFS *sizeof(short));
+ hwbuf = my_malloc(pcm.len *sizeof(short));
pcm.buf = buf;
pcm.pos = 0;
diff --git a/apps/plugins/rockboy/rockmacros.h b/apps/plugins/rockboy/rockmacros.h
index 5d60d3f..f5223b0 100644
--- a/apps/plugins/rockboy/rockmacros.h
+++ b/apps/plugins/rockboy/rockmacros.h
@@ -35,7 +35,6 @@ void *sys_timer(void);
int sys_elapsed(long *oldtick);
int pcm_submit(void);
void pcm_init(void);
-void sound_dirty(void);
void doevents(void) ICODE_ATTR;
void ev_poll(void);
int do_user_menu(void);
diff --git a/apps/plugins/rockboy/save.c b/apps/plugins/rockboy/save.c
index 794579d..3f6c179 100644
--- a/apps/plugins/rockboy/save.c
+++ b/apps/plugins/rockboy/save.c
@@ -89,24 +89,24 @@ struct svar svars[] =
I4("S1on", &snd.ch[0].on),
I4("S1p ", &snd.ch[0].pos),
- I4("S1c ", &snd.ch[0].cnt),
- I4("S1ec", &snd.ch[0].encnt),
- I4("S1sc", &snd.ch[0].swcnt),
+ I4("S1c ", &snd.ch[0].len),
+ I4("S1ec", &snd.ch[0].enlen),
+ I4("S1sc", &snd.ch[0].swlen),
I4("S2on", &snd.ch[1].on),
I4("S2p ", &snd.ch[1].pos),
- I4("S2c ", &snd.ch[1].cnt),
- I4("S2ec", &snd.ch[1].encnt),
-
+ I4("S2c ", &snd.ch[1].len),
+ I4("S2ec", &snd.ch[1].enlen),
+
I4("S3on", &snd.ch[2].on),
I4("S3p ", &snd.ch[2].pos),
- I4("S3c ", &snd.ch[2].cnt),
-
+ I4("S3c ", &snd.ch[2].len),
+
I4("S4on", &snd.ch[3].on),
I4("S4p ", &snd.ch[3].pos),
- I4("S4c ", &snd.ch[3].cnt),
- I4("S4ec", &snd.ch[3].encnt),
-
+ I4("S4c ", &snd.ch[3].len),
+ I4("S4ec", &snd.ch[3].enlen),
+
I4("hdma", &hw.hdma),
I4("sram", &sramblock),
diff --git a/apps/plugins/rockboy/sound.c b/apps/plugins/rockboy/sound.c
index aba7f92..036a05a 100644
--- a/apps/plugins/rockboy/sound.c
+++ b/apps/plugins/rockboy/sound.c
@@ -1,3 +1,30 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ */
+
#include "rockmacros.h"
#include "defs.h"
#include "pcm.h"
@@ -5,31 +32,71 @@
#include "cpu-gb.h"
#include "hw.h"
#include "regs.h"
-#include "noise.h"
-
-static const byte dmgwave[16] =
-{
- 0xac, 0xdd, 0xda, 0x48,
- 0x36, 0x02, 0xcf, 0x16,
- 0x2c, 0x04, 0xe5, 0x2c,
- 0xac, 0xdd, 0xda, 0x48
-};
-static const byte cgbwave[16] =
-{
- 0x00, 0xff, 0x00, 0xff,
- 0x00, 0xff, 0x00, 0xff,
- 0x00, 0xff, 0x00, 0xff,
- 0x00, 0xff, 0x00, 0xff,
-};
-
-static const byte sqwave[4][8] =
-{
- { 0, 0,-1, 0, 0, 0, 0, 0 },
- { 0,-1,-1, 0, 0, 0, 0, 0 },
- { -1,-1,-1,-1, 0, 0, 0, 0 },
- { -1, 0, 0,-1,-1,-1,-1,-1 }
-};
+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}
+} ICONST_ATTR;
+
+int soundFreqRatio[8] = {
+ 1048576, // 0
+ 524288, // 1
+ 262144, // 2
+ 174763, // 3
+ 131072, // 4
+ 104858, // 5
+ 87381, // 6
+ 74898 // 7
+} ICONST_ATTR;
+
+int soundShiftClock[16]= {
+ 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
+} ICONST_ATTR;
static const int freqtab[8] =
{
@@ -41,7 +108,7 @@ static const int freqtab[8] =
(1<<14)/5,
(1<<14)/6,
(1<<14)/7
-};
+} ICONST_ATTR;
struct snd snd IBSS_ATTR;
@@ -52,209 +119,315 @@ struct snd snd IBSS_ATTR;
#define S3 (snd.ch[2])
#define S4 (snd.ch[3])
-static void s1_freq_d(int d)
-{
- if (RATE > (d<<4)) S1.freq = 0;
- else S1.freq = (RATE << 17)/d;
-}
-
-static void s1_freq(void)
-{
- s1_freq_d(2048 - (((R_NR14&7)<<8) + R_NR13));
-}
-
-static void s2_freq(void)
-{
- int d = 2048 - (((R_NR24&7)<<8) + R_NR23);
- if (RATE > (d<<4)) S2.freq = 0;
- else S2.freq = (RATE << 17)/d;
-}
-
-static void s3_freq(void)
-{
- int d = 2048 - (((R_NR34&7)<<8) + R_NR33);
- if (RATE > (d<<3)) S3.freq = 0;
- else S3.freq = (RATE << 21)/d;
-}
+#define SOUND_MAGIC 0x60000000
+#define SOUND_MAGIC_2 0x30000000
+#define NOISE_MAGIC 5
-static void s4_freq(void)
+static void gbSoundChannel1(int *r, int *l)
{
- S4.freq = (freqtab[R_NR43&7] >> (R_NR43 >> 4)) * RATE;
- if (S4.freq >> 18) S4.freq = 1<<18;
-}
+ int vol = S1.envol;
-void sound_dirty(void)
-{
- S1.swlen = ((R_NR10>>4) & 7) << 14;
- S1.len = (64-(R_NR11&63)) << 13;
- S1.envol = R_NR12 >> 4;
- S1.endir = (R_NR12>>3) & 1;
- S1.endir |= S1.endir - 1;
- S1.enlen = (R_NR12 & 7) << 15;
- s1_freq();
- S2.len = (64-(R_NR21&63)) << 13;
- S2.envol = R_NR22 >> 4;
- S2.endir = (R_NR22>>3) & 1;
- S2.endir |= S2.endir - 1;
- S2.enlen = (R_NR22 & 7) << 15;
- s2_freq();
- S3.len = (256-R_NR31) << 20;
- s3_freq();
- S4.len = (64-(R_NR41&63)) << 13;
- S4.envol = R_NR42 >> 4;
- S4.endir = (R_NR42>>3) & 1;
- S4.endir |= S4.endir - 1;
- S4.enlen = (R_NR42 & 7) << 15;
- s4_freq();
-}
+ int freq = 0;
-void sound_off(void)
-{
- memset(&snd, 0, sizeof snd);
- if (pcm.hz) snd.rate = (1<<21) / pcm.hz;
- else snd.rate = 0;
- R_NR10 = 0x80;
- R_NR11 = 0xBF;
- R_NR12 = 0xF3;
- R_NR14 = 0xBF;
- R_NR21 = 0x3F;
- R_NR22 = 0x00;
- R_NR24 = 0xBF;
- R_NR30 = 0x7F;
- R_NR31 = 0xFF;
- R_NR32 = 0x9F;
- R_NR34 = 0xBF;
- R_NR41 = 0xFF;
- R_NR42 = 0x00;
- R_NR43 = 0x00;
- R_NR44 = 0xBF;
- R_NR50 = 0x77;
- R_NR51 = 0xF3;
- R_NR52 = 0x70;
-// for (i = 0; i < 16; i++) WAVE[i] = -(i&1);
- sound_dirty();
-}
+ int value = 0;
-void sound_reset()
-{
- memset(&snd, 0, sizeof snd);
- if (pcm.hz) snd.rate = (1<<21) / pcm.hz;
- else snd.rate = 0;
- memcpy(WAVE, hw.cgb ? cgbwave : dmgwave, 16);
- memcpy(ram.hi+0x30, WAVE, 16);
- sound_off();
- R_NR52 = 0xF1;
-}
+ if(S1.on && (S1.len || !S1.cont))
+ {
+ S1.pos += snd.quality*S1.skip;
+ S1.pos &= 0x1fffffff;
-void sound_mix(void)
-{
- int s, l, r, f, n;
+ value = ((signed char)S1.wave[S1.pos>>24]) * vol;
+ }
- if (!RATE || cpu.snd < RATE) return;
+ if (snd.balance & 1) *r += value;
+ if (snd.balance & 16) *l += value;
- for (; cpu.snd >= RATE; cpu.snd -= RATE)
+ if(S1.on)
{
- l = r = 0;
-
- if (S1.on)
+ if(S1.len)
{
- s = sqwave[R_NR11>>6][(S1.pos>>18)&7] & S1.envol;
- S1.pos += S1.freq;
- if ((R_NR14 & 64) && ((S1.cnt += RATE) >= S1.len))
+ S1.len-=snd.quality;
+
+ if(S1.len <=0 && S1.cont)
+ {
+ R_NR52 &= 0xfe;
S1.on = 0;
- if (S1.enlen && (S1.encnt += RATE) >= S1.enlen)
+ }
+ }
+
+ if(S1.enlen)
+ {
+ S1.enlen-=snd.quality;
+
+ if(S1.enlen<=0)
{
- S1.encnt -= S1.enlen;
- S1.envol += S1.endir;
- if (S1.envol < 0) S1.envol = 0;
- if (S1.envol > 15) S1.envol = 15;
+ if(S1.endir)
+ {
+ if(S1.envol < 15)
+ S1.envol++;
+ }
+ else
+ {
+ if(S1.envol)
+ S1.envol--;
+ }
+
+ S1.enlen += S1.enlenreload;
}
- if (S1.swlen && (S1.swcnt += RATE) >= S1.swlen)
+ }
+
+ if(S1.swlen)
+ {
+ S1.swlen-=snd.quality;
+
+ if(S1.swlen<=0)
{
- S1.swcnt -= S1.swlen;
- f = S1.swfreq;
- n = (R_NR10 & 7);
- if (R_NR10 & 8) f -= (f >> n);
- else f += (f >> n);
- if (f > 2047)
- S1.on = 0;
+ freq = (((int)(R_NR14&7) << 8) | R_NR13);
+
+ 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;
+ }
else
+ newfreq = freq;
+
+ if(newfreq < 0)
{
- S1.swfreq = f;
- R_NR13 = f;
- R_NR14 = (R_NR14 & 0xF8) | (f>>8);
- s1_freq_d(2048 - f);
+ 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);
}
}
- s <<= 2;
- if (R_NR51 & 1) r += s;
- if (R_NR51 & 16) l += s;
}
+ }
+}
- if (S2.on)
- {
- s = sqwave[R_NR21>>6][(S2.pos>>18)&7] & S2.envol;
- S2.pos += S2.freq;
- if ((R_NR24 & 64) && ((S2.cnt += RATE) >= S2.len))
+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;
S2.on = 0;
- if (S2.enlen && (S2.encnt += RATE) >= S2.enlen)
- {
- S2.encnt -= S2.enlen;
- S2.envol += S2.endir;
- if (S2.envol < 0) S2.envol = 0;
- if (S2.envol > 15) S2.envol = 15;
}
- s <<= 2;
- if (R_NR51 & 2) r += s;
- if (R_NR51 & 32) l += s;
}
+
+ 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;
- if (S3.on)
+ switch(S3.outputlevel)
{
- s = WAVE[(S3.pos>>22) & 15];
- if (S3.pos & (1<<21)) s &= 15;
- else s >>= 4;
- s -= 8;
- S3.pos += S3.freq;
- if ((R_NR34 & 64) && ((S3.cnt += RATE) >= S3.len))
- S3.on = 0;
- if (R_NR32 & 96) s <<= (3 - ((R_NR32>>5)&3));
- else s = 0;
- if (R_NR51 & 4) r += s;
- if (R_NR51 & 64) l += s;
+ case 0:
+ s=0;
+ break;
+ case 1:
+ break;
+ case 2:
+ s=s>>1;
+ break;
+ case 3:
+ s=s>>2;
+ break;
}
- if (S4.on)
+ if (snd.balance & 4) *r += s;
+ if (snd.balance & 64) *l += s;
+ }
+
+ if(S3.on)
+ {
+ if(S3.len)
{
- if (R_NR43 & 8) s = 1 & (noise7[
- (S4.pos>>20)&15] >> (7-((S4.pos>>17)&7)));
- else s = 1 & (noise15[
- (S4.pos>>20)&4095] >> (7-((S4.pos>>17)&7)));
- s = (-s) & S4.envol;
- S4.pos += S4.freq;
- if ((R_NR44 & 64) && ((S4.cnt += RATE) >= S4.len))
+ S3.len-=snd.quality;
+ if(S3.len<=0 && S3.cont)
+ {
+ R_NR52 &= 0xFB;
+ S3.on=0;
+ }
+ }
+ }
+}
+
+void gbSoundChannel4(int *r, int *l)
+{
+ 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;
S4.on = 0;
- if (S4.enlen && (S4.encnt += RATE) >= S4.enlen)
+ }
+ }
+
+ if(S4.enlen) {
+ S4.enlen-=snd.quality;
+
+ if(S4.enlen <= 0)
{
- S4.encnt -= S4.enlen;
- S4.envol += S4.endir;
- if (S4.envol < 0) S4.envol = 0;
- if (S4.envol > 15) S4.envol = 15;
+ if(S4.endir)
+ {
+ if(S4.envol < 15)
+ S4.envol++;
+ }
+ else
+ {
+ if(S4.envol)
+ S4.envol--;
+ }
+ S4.enlen += S4.enlenreload;
}
- s += s << 1;
- if (R_NR51 & 8) r += s;
- if (R_NR51 & 128) l += s;
}
+ }
+}
+
+void sound_mix(void)
+{
+ int l, r;
+
+ if (!RATE || cpu.snd < RATE) return;
+
+ for (; cpu.snd >= RATE; cpu.snd -= RATE)
+ {
+ l = r = 0;
- l *= (R_NR50 & 0x07);
- r *= ((R_NR50 & 0x70)>>4);
- l >>= 4;
- r >>= 4;
+ gbSoundChannel1(&r,&l);
- if (l > 127) l = 127;
- else if (l < -128) l = -128;
- if (r > 127) r = 127;
- else if (r < -128) r = -128;
+ 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;
if (pcm.buf)
{
@@ -262,17 +435,15 @@ void sound_mix(void)
pcm_submit();
if (pcm.stereo)
{
- pcm.buf[pcm.pos++] = ((signed char)(l))<<7;
- pcm.buf[pcm.pos++] = ((signed char)(r))<<7;
+ pcm.buf[pcm.pos++] = l;
+ pcm.buf[pcm.pos++] = r;
}
- else pcm.buf[pcm.pos++] = ((signed char)((l+r)>>1))<<7;
+ else pcm.buf[pcm.pos++] = ((l+r)>>1);
}
}
R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3);
}
-
-
byte sound_read(byte r)
{
if(!options.sound) return 0;
@@ -281,166 +452,327 @@ byte sound_read(byte r)
return REG(r);
}
-void s1_init(void)
-{
- S1.swcnt = 0;
- S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
- S1.envol = R_NR12 >> 4;
- S1.endir = (R_NR12>>3) & 1;
- S1.endir |= S1.endir - 1;
- S1.enlen = (R_NR12 & 7) << 15;
- if (!S1.on) S1.pos = 0;
- S1.on = 1;
- S1.cnt = 0;
- S1.encnt = 0;
-}
-
-void s2_init(void)
-{
- S2.envol = R_NR22 >> 4;
- S2.endir = (R_NR22>>3) & 1;
- S2.endir |= S2.endir - 1;
- S2.enlen = (R_NR22 & 7) << 15;
- if (!S2.on) S2.pos = 0;
- S2.on = 1;
- S2.cnt = 0;
- S2.encnt = 0;
-}
-
-void s3_init(void)
-{
- int i;
- if (!S3.on) S3.pos = 0;
- S3.cnt = 0;
- S3.on = R_NR30 >> 7;
- if (S3.on) for (i = 0; i < 16; i++)
- ram.hi[i+0x30] = 0x13 ^ ram.hi[i+0x31];
-}
-
-void s4_init(void)
-{
- S4.envol = R_NR42 >> 4;
- S4.endir = (R_NR42>>3) & 1;
- S4.endir |= S4.endir - 1;
- S4.enlen = (R_NR42 & 7) << 15;
- S4.on = 1;
- S4.pos = 0;
- S4.cnt = 0;
- S4.encnt = 0;
-}
-
-
void sound_write(byte r, byte b)
{
- if(!options.sound) return;
+ int freq=0;
+ ram.hi[r]=b;
- if (!(R_NR52 & 128) && r != RI_NR52) return;
- if ((r & 0xF0) == 0x30)
- {
- if (S3.on) sound_mix();
- if (!S3.on)
- WAVE[r-0x30] = ram.hi[r] = b;
+ if(!options.sound)
return;
- }
+
sound_mix();
+
switch (r)
{
case RI_NR10:
- R_NR10 = b;
- S1.swlen = ((R_NR10>>4) & 7) << 14;
- S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
+ S1.swlen = S1.swlenreload = 344 * ((b >> 4) & 7);
+ S1.swsteps = b & 7;
+ S1.swdir = b & 0x08;
+ S1.swstep = 0;
break;
case RI_NR11:
- R_NR11 = b;
- S1.len = (64-(R_NR11&63)) << 13;
+ S1.len = 172 * (64 - (b & 0x3f));
+ S1.wave = soundWavePattern[b >> 6];
break;
case RI_NR12:
- R_NR12 = b;
- S1.envol = R_NR12 >> 4;
- S1.endir = (R_NR12>>3) & 1;
- S1.endir |= S1.endir - 1;
- S1.enlen = (R_NR12 & 7) << 15;
+ S1.envol = b >> 4;
+ S1.endir = b & 0x08;
+ S1.enlenreload = S1.enlen = 689 * (b & 7);
break;
case RI_NR13:
- R_NR13 = b;
- s1_freq();
+ 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;
+ }
break;
case RI_NR14:
- R_NR14 = b;
- s1_freq();
- if (b & 128) s1_init();
+ 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;
+ }
break;
case RI_NR21:
- R_NR21 = b;
- S2.len = (64-(R_NR21&63)) << 13;
+ S2.wave = soundWavePattern[b >> 6];
+ S2.len = 172 * (64 - (b & 0x3f));
break;
case RI_NR22:
- R_NR22 = b;
- S2.envol = R_NR22 >> 4;
- S2.endir = (R_NR22>>3) & 1;
- S2.endir |= S2.endir - 1;
- S2.enlen = (R_NR22 & 7) << 15;
+ S2.envol = b >> 4;
+ S2.endir = b & 0x08;
+ S2.enlenreload = S2.enlen = 689 * (b & 7);
break;
case RI_NR23:
- R_NR23 = b;
- s2_freq();
+ 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;
+ }
break;
case RI_NR24:
- R_NR24 = b;
- s2_freq();
- if (b & 128) s2_init();
+ 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;
+ }
break;
case RI_NR30:
- R_NR30 = b;
- if (!(b & 128)) S3.on = 0;
+ if (!(b & 0x80)){
+ R_NR52 &= 0xfb;
+ S3.on = 0;
+ }
break;
case RI_NR31:
- R_NR31 = b;
- S3.len = (256-R_NR31) << 13;
+ S3.len = (256-R_NR31) * 172;
break;
case RI_NR32:
- R_NR32 = b;
+ S3.outputlevel = (b >> 5) & 3;
break;
case RI_NR33:
- R_NR33 = b;
- s3_freq();
+ freq = 2048 - (((int)(R_NR34&7) << 8) | b);
+ if(freq)
+ S3.skip = SOUND_MAGIC_2 / freq;
+ else
+ S3.skip = 0;
break;
case RI_NR34:
- R_NR34 = b;
- s3_freq();
- if (b & 128) s3_init();
+ 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;
+ }
break;
case RI_NR41:
- R_NR41 = b;
- S4.len = (64-(R_NR41&63)) << 13;
+ S4.len = 172 * (64 - (b & 0x3f));
break;
case RI_NR42:
- R_NR42 = b;
- S4.envol = R_NR42 >> 4;
- S4.endir = (R_NR42>>3) & 1;
- S4.endir |= S4.endir - 1;
- S4.enlen = (R_NR42 & 7) << 15;
+ S4.envol = b >> 4;
+ S4.endir = b & 0x08;
+ S4.enlenreload = S4.enlen = 689 * (b & 7);
break;
case RI_NR43:
- R_NR43 = b;
- s4_freq();
+ 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;
break;
case RI_NR44:
- R_NR44 = b;
- if (b & 128) s4_init();
+ 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;
+ }
+ }
break;
case RI_NR50:
- R_NR50 = b;
+ snd.level1 = b & 7;
+ snd.level2 = (b >> 4) & 7;
break;
case RI_NR51:
- R_NR51 = b;
+ snd.balance = b;
break;
case RI_NR52:
- R_NR52 = b;
- if (!(R_NR52 & 128))
- sound_off();
+ if (!(b & 0x80))
+ {
+ S1.on=0;
+ S2.on=0;
+ S3.on=0;
+ S4.on=0;
+ }
break;
- default:
- return;
}
+
+ 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;
+}
+
+void sound_reset()
+{
+ 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;
+}
+
+void sound_dirty()
+{
+ 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);
}
diff --git a/apps/plugins/rockboy/sound.h b/apps/plugins/rockboy/sound.h
index 88897ef..e40fbad 100644
--- a/apps/plugins/rockboy/sound.h
+++ b/apps/plugins/rockboy/sound.h
@@ -5,18 +5,34 @@
struct sndchan
{
- int on;
- unsigned pos;
- int cnt, encnt, swcnt;
- int len, enlen, swlen;
- int swfreq;
- int freq;
- int envol, endir;
+ /* S1, S2, S3, S4 */
+ int on, len, skip, cont;
+ unsigned int pos;
+
+ /* S1, S2, S4 */
+ int enlen, envol, endir, enlenreload;
+
+ /* S1, S2 */
+ const byte *wave;
+
+ /* S1 only */
+ int swlen, swlenreload, swsteps, swstep, swdir;
+
+ /* S3 only */
+ int outputlevel;
+
+ /* S4 only */
+ int shiftskip, shiftpos, shiftright, shiftleft;
+ int nsteps, clock;
+
};
struct snd
{
+ int level1, level2, balance;
+ bool gbDigitalSound;
int rate;
+ int quality;
struct sndchan ch[4];
};
@@ -29,12 +45,8 @@ extern struct snd snd;
byte sound_read(byte r) ICODE_ATTR;
void sound_write(byte r, byte b) ICODE_ATTR;
-void sound_dirty(void) ICODE_ATTR;
+void sound_dirty(void);
void sound_reset(void);
void sound_mix(void) ICODE_ATTR;
-void s1_init(void);
-void s2_init(void);
-void s3_init(void);
-void s4_init(void);
#endif