From fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413 Mon Sep 17 00:00:00 2001 From: Karl Kurbjun Date: Sat, 21 Jul 2007 04:00:58 +0000 Subject: 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 --- apps/plugins/rockboy/mem.c | 7 - apps/plugins/rockboy/mem.h | 1 - apps/plugins/rockboy/rbsound.c | 13 +- apps/plugins/rockboy/rockmacros.h | 1 - apps/plugins/rockboy/save.c | 22 +- apps/plugins/rockboy/sound.c | 954 +++++++++++++++++++++++++------------- apps/plugins/rockboy/sound.h | 36 +- 7 files changed, 688 insertions(+), 346 deletions(-) (limited to 'apps') diff --git a/apps/plugins/rockboy/mem.c b/apps/plugins/rockboy/mem.c index 8c0bea0b83..6811fd5f81 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 005c495f31..338fd98bf0 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 fe2c27af67..b5cfc96fa4 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 5d60d3f3e3..f5223b01df 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 794579d8fa..3f6c179beb 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 aba7f924b4..036a05a058 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 88897ef9ce..e40fbad2d5 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 -- cgit v1.2.3