summaryrefslogtreecommitdiff
path: root/apps
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
parente9c09d4d0e1170c6c81991c2660608854d960a77 (diff)
downloadrockbox-fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413.tar.gz
rockbox-fa3fc0c5c7e89ad6ce26e9d3563e3a064b018413.zip
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')
-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 8c0bea0b83..6811fd5f81 100644
--- a/apps/plugins/rockboy/mem.c
+++ b/apps/plugins/rockboy/mem.c
@@ -562,10 +562,3 @@ void mbc_reset(void)
562 mbc.enableram = 0; 562 mbc.enableram = 0;
563 mem_updatemap(); 563 mem_updatemap();
564} 564}
565
566
567
568
569
570
571
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
41 int loaded; 41 int loaded;
42}; 42};
43 43
44
45extern struct mbc mbc; 44extern struct mbc mbc;
46extern struct rom rom; 45extern struct rom rom;
47extern struct ram ram; 46extern 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;
12bool doneplay=1; 12bool doneplay=1;
13bool bufnum=0; 13bool bufnum=0;
14 14
15static unsigned short *buf=0; 15static unsigned short *buf=0, *hwbuf=0;
16 16
17static bool newly_started; 17static bool newly_started;
18 18
19void get_more(unsigned char** start, size_t* size) 19void get_more(unsigned char** start, size_t* size)
20{ 20{
21 *start = (unsigned char*)(&buf[pcm.len*doneplay]); 21 memcpy(hwbuf, &buf[pcm.len*doneplay], BUF_SIZE*sizeof(short));
22 *start = (unsigned char*)(hwbuf);
22 *size = BUF_SIZE*sizeof(short); 23 *size = BUF_SIZE*sizeof(short);
23 doneplay=1; 24 doneplay=1;
24} 25}
@@ -29,14 +30,20 @@ void pcm_init(void)
29 return; 30 return;
30 31
31 newly_started = true; 32 newly_started = true;
32 33
34#if defined(HW_HAVE_11) && !defined(TOSHIBA_GIGABEAT_F)
35 pcm.hz = SAMPR_11;
36#else
33 pcm.hz = SAMPR_44; 37 pcm.hz = SAMPR_44;
38#endif
39
34 pcm.stereo = 1; 40 pcm.stereo = 1;
35 41
36 pcm.len = BUF_SIZE; 42 pcm.len = BUF_SIZE;
37 if(!buf) 43 if(!buf)
38 { 44 {
39 buf = my_malloc(pcm.len * N_BUFS *sizeof(short)); 45 buf = my_malloc(pcm.len * N_BUFS *sizeof(short));
46 hwbuf = my_malloc(pcm.len *sizeof(short));
40 47
41 pcm.buf = buf; 48 pcm.buf = buf;
42 pcm.pos = 0; 49 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);
35int sys_elapsed(long *oldtick); 35int sys_elapsed(long *oldtick);
36int pcm_submit(void); 36int pcm_submit(void);
37void pcm_init(void); 37void pcm_init(void);
38void sound_dirty(void);
39void doevents(void) ICODE_ATTR; 38void doevents(void) ICODE_ATTR;
40void ev_poll(void); 39void ev_poll(void);
41int do_user_menu(void); 40int 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[] =
89 89
90 I4("S1on", &snd.ch[0].on), 90 I4("S1on", &snd.ch[0].on),
91 I4("S1p ", &snd.ch[0].pos), 91 I4("S1p ", &snd.ch[0].pos),
92 I4("S1c ", &snd.ch[0].cnt), 92 I4("S1c ", &snd.ch[0].len),
93 I4("S1ec", &snd.ch[0].encnt), 93 I4("S1ec", &snd.ch[0].enlen),
94 I4("S1sc", &snd.ch[0].swcnt), 94 I4("S1sc", &snd.ch[0].swlen),
95 95
96 I4("S2on", &snd.ch[1].on), 96 I4("S2on", &snd.ch[1].on),
97 I4("S2p ", &snd.ch[1].pos), 97 I4("S2p ", &snd.ch[1].pos),
98 I4("S2c ", &snd.ch[1].cnt), 98 I4("S2c ", &snd.ch[1].len),
99 I4("S2ec", &snd.ch[1].encnt), 99 I4("S2ec", &snd.ch[1].enlen),
100 100
101 I4("S3on", &snd.ch[2].on), 101 I4("S3on", &snd.ch[2].on),
102 I4("S3p ", &snd.ch[2].pos), 102 I4("S3p ", &snd.ch[2].pos),
103 I4("S3c ", &snd.ch[2].cnt), 103 I4("S3c ", &snd.ch[2].len),
104 104
105 I4("S4on", &snd.ch[3].on), 105 I4("S4on", &snd.ch[3].on),
106 I4("S4p ", &snd.ch[3].pos), 106 I4("S4p ", &snd.ch[3].pos),
107 I4("S4c ", &snd.ch[3].cnt), 107 I4("S4c ", &snd.ch[3].len),
108 I4("S4ec", &snd.ch[3].encnt), 108 I4("S4ec", &snd.ch[3].enlen),
109 109
110 I4("hdma", &hw.hdma), 110 I4("hdma", &hw.hdma),
111 111
112 I4("sram", &sramblock), 112 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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
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
13 *
14 * VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
15 * Copyright (C) 1999-2003 Forgotten
16 * Copyright (C) 2004 Forgotten and the VBA development team
17 *
18 * VisualBoyAdvance conversion from C++ to C by Karl Kurbjun July, 2007
19 *
20 * All files in this archive are subject to the GNU General Public License.
21 * See the file COPYING in the source tree root for full license agreement.
22 *
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24 * KIND, either express or implied.
25 *
26 */
27
1#include "rockmacros.h" 28#include "rockmacros.h"
2#include "defs.h" 29#include "defs.h"
3#include "pcm.h" 30#include "pcm.h"
@@ -5,31 +32,71 @@
5#include "cpu-gb.h" 32#include "cpu-gb.h"
6#include "hw.h" 33#include "hw.h"
7#include "regs.h" 34#include "regs.h"
8#include "noise.h"
9
10static const byte dmgwave[16] =
11{
12 0xac, 0xdd, 0xda, 0x48,
13 0x36, 0x02, 0xcf, 0x16,
14 0x2c, 0x04, 0xe5, 0x2c,
15 0xac, 0xdd, 0xda, 0x48
16};
17 35
18static const byte cgbwave[16] = 36static const byte soundWavePattern[4][32] = {
19{ 37 {0x01,0x01,0x01,0x01,
20 0x00, 0xff, 0x00, 0xff, 38 0xff,0xff,0xff,0xff,
21 0x00, 0xff, 0x00, 0xff, 39 0xff,0xff,0xff,0xff,
22 0x00, 0xff, 0x00, 0xff, 40 0xff,0xff,0xff,0xff,
23 0x00, 0xff, 0x00, 0xff, 41 0xff,0xff,0xff,0xff,
24}; 42 0xff,0xff,0xff,0xff,
25 43 0xff,0xff,0xff,0xff,
26static const byte sqwave[4][8] = 44 0xff,0xff,0xff,0xff},
27{ 45 {0x01,0x01,0x01,0x01,
28 { 0, 0,-1, 0, 0, 0, 0, 0 }, 46 0x01,0x01,0x01,0x01,
29 { 0,-1,-1, 0, 0, 0, 0, 0 }, 47 0xff,0xff,0xff,0xff,
30 { -1,-1,-1,-1, 0, 0, 0, 0 }, 48 0xff,0xff,0xff,0xff,
31 { -1, 0, 0,-1,-1,-1,-1,-1 } 49 0xff,0xff,0xff,0xff,
32}; 50 0xff,0xff,0xff,0xff,
51 0xff,0xff,0xff,0xff,
52 0xff,0xff,0xff,0xff},
53 {0x01,0x01,0x01,0x01,
54 0x01,0x01,0x01,0x01,
55 0x01,0x01,0x01,0x01,
56 0x01,0x01,0x01,0x01,
57 0xff,0xff,0xff,0xff,
58 0xff,0xff,0xff,0xff,
59 0xff,0xff,0xff,0xff,
60 0xff,0xff,0xff,0xff},
61 {0x01,0x01,0x01,0x01,
62 0x01,0x01,0x01,0x01,
63 0x01,0x01,0x01,0x01,
64 0x01,0x01,0x01,0x01,
65 0x01,0x01,0x01,0x01,
66 0x01,0x01,0x01,0x01,
67 0xff,0xff,0xff,0xff,
68 0xff,0xff,0xff,0xff}
69} ICONST_ATTR;
70
71int soundFreqRatio[8] = {
72 1048576, // 0
73 524288, // 1
74 262144, // 2
75 174763, // 3
76 131072, // 4
77 104858, // 5
78 87381, // 6
79 74898 // 7
80} ICONST_ATTR;
81
82int soundShiftClock[16]= {
83 2, // 0
84 4, // 1
85 8, // 2
86 16, // 3
87 32, // 4
88 64, // 5
89 128, // 6
90 256, // 7
91 512, // 8
92 1024, // 9
93 2048, // 10
94 4096, // 11
95 8192, // 12
96 16384, // 13
97 1, // 14
98 1 // 15
99} ICONST_ATTR;
33 100
34static const int freqtab[8] = 101static const int freqtab[8] =
35{ 102{
@@ -41,7 +108,7 @@ static const int freqtab[8] =
41 (1<<14)/5, 108 (1<<14)/5,
42 (1<<14)/6, 109 (1<<14)/6,
43 (1<<14)/7 110 (1<<14)/7
44}; 111} ICONST_ATTR;
45 112
46struct snd snd IBSS_ATTR; 113struct snd snd IBSS_ATTR;
47 114
@@ -52,209 +119,315 @@ struct snd snd IBSS_ATTR;
52#define S3 (snd.ch[2]) 119#define S3 (snd.ch[2])
53#define S4 (snd.ch[3]) 120#define S4 (snd.ch[3])
54 121
55static void s1_freq_d(int d) 122#define SOUND_MAGIC 0x60000000
56{ 123#define SOUND_MAGIC_2 0x30000000
57 if (RATE > (d<<4)) S1.freq = 0; 124#define NOISE_MAGIC 5
58 else S1.freq = (RATE << 17)/d;
59}
60
61static void s1_freq(void)
62{
63 s1_freq_d(2048 - (((R_NR14&7)<<8) + R_NR13));
64}
65
66static void s2_freq(void)
67{
68 int d = 2048 - (((R_NR24&7)<<8) + R_NR23);
69 if (RATE > (d<<4)) S2.freq = 0;
70 else S2.freq = (RATE << 17)/d;
71}
72
73static void s3_freq(void)
74{
75 int d = 2048 - (((R_NR34&7)<<8) + R_NR33);
76 if (RATE > (d<<3)) S3.freq = 0;
77 else S3.freq = (RATE << 21)/d;
78}
79 125
80static void s4_freq(void) 126static void gbSoundChannel1(int *r, int *l)
81{ 127{
82 S4.freq = (freqtab[R_NR43&7] >> (R_NR43 >> 4)) * RATE; 128 int vol = S1.envol;
83 if (S4.freq >> 18) S4.freq = 1<<18;
84}
85 129
86void sound_dirty(void) 130 int freq = 0;
87{
88 S1.swlen = ((R_NR10>>4) & 7) << 14;
89 S1.len = (64-(R_NR11&63)) << 13;
90 S1.envol = R_NR12 >> 4;
91 S1.endir = (R_NR12>>3) & 1;
92 S1.endir |= S1.endir - 1;
93 S1.enlen = (R_NR12 & 7) << 15;
94 s1_freq();
95 S2.len = (64-(R_NR21&63)) << 13;
96 S2.envol = R_NR22 >> 4;
97 S2.endir = (R_NR22>>3) & 1;
98 S2.endir |= S2.endir - 1;
99 S2.enlen = (R_NR22 & 7) << 15;
100 s2_freq();
101 S3.len = (256-R_NR31) << 20;
102 s3_freq();
103 S4.len = (64-(R_NR41&63)) << 13;
104 S4.envol = R_NR42 >> 4;
105 S4.endir = (R_NR42>>3) & 1;
106 S4.endir |= S4.endir - 1;
107 S4.enlen = (R_NR42 & 7) << 15;
108 s4_freq();
109}
110 131
111void sound_off(void) 132 int value = 0;
112{
113 memset(&snd, 0, sizeof snd);
114 if (pcm.hz) snd.rate = (1<<21) / pcm.hz;
115 else snd.rate = 0;
116 R_NR10 = 0x80;
117 R_NR11 = 0xBF;
118 R_NR12 = 0xF3;
119 R_NR14 = 0xBF;
120 R_NR21 = 0x3F;
121 R_NR22 = 0x00;
122 R_NR24 = 0xBF;
123 R_NR30 = 0x7F;
124 R_NR31 = 0xFF;
125 R_NR32 = 0x9F;
126 R_NR34 = 0xBF;
127 R_NR41 = 0xFF;
128 R_NR42 = 0x00;
129 R_NR43 = 0x00;
130 R_NR44 = 0xBF;
131 R_NR50 = 0x77;
132 R_NR51 = 0xF3;
133 R_NR52 = 0x70;
134// for (i = 0; i < 16; i++) WAVE[i] = -(i&1);
135 sound_dirty();
136}
137 133
138void sound_reset() 134 if(S1.on && (S1.len || !S1.cont))
139{ 135 {
140 memset(&snd, 0, sizeof snd); 136 S1.pos += snd.quality*S1.skip;
141 if (pcm.hz) snd.rate = (1<<21) / pcm.hz; 137 S1.pos &= 0x1fffffff;
142 else snd.rate = 0;
143 memcpy(WAVE, hw.cgb ? cgbwave : dmgwave, 16);
144 memcpy(ram.hi+0x30, WAVE, 16);
145 sound_off();
146 R_NR52 = 0xF1;
147}
148 138
149void sound_mix(void) 139 value = ((signed char)S1.wave[S1.pos>>24]) * vol;
150{ 140 }
151 int s, l, r, f, n;
152 141
153 if (!RATE || cpu.snd < RATE) return; 142 if (snd.balance & 1) *r += value;
143 if (snd.balance & 16) *l += value;
154 144
155 for (; cpu.snd >= RATE; cpu.snd -= RATE) 145 if(S1.on)
156 { 146 {
157 l = r = 0; 147 if(S1.len)
158
159 if (S1.on)
160 { 148 {
161 s = sqwave[R_NR11>>6][(S1.pos>>18)&7] & S1.envol; 149 S1.len-=snd.quality;
162 S1.pos += S1.freq; 150
163 if ((R_NR14 & 64) && ((S1.cnt += RATE) >= S1.len)) 151 if(S1.len <=0 && S1.cont)
152 {
153 R_NR52 &= 0xfe;
164 S1.on = 0; 154 S1.on = 0;
165 if (S1.enlen && (S1.encnt += RATE) >= S1.enlen) 155 }
156 }
157
158 if(S1.enlen)
159 {
160 S1.enlen-=snd.quality;
161
162 if(S1.enlen<=0)
166 { 163 {
167 S1.encnt -= S1.enlen; 164 if(S1.endir)
168 S1.envol += S1.endir; 165 {
169 if (S1.envol < 0) S1.envol = 0; 166 if(S1.envol < 15)
170 if (S1.envol > 15) S1.envol = 15; 167 S1.envol++;
168 }
169 else
170 {
171 if(S1.envol)
172 S1.envol--;
173 }
174
175 S1.enlen += S1.enlenreload;
171 } 176 }
172 if (S1.swlen && (S1.swcnt += RATE) >= S1.swlen) 177 }
178
179 if(S1.swlen)
180 {
181 S1.swlen-=snd.quality;
182
183 if(S1.swlen<=0)
173 { 184 {
174 S1.swcnt -= S1.swlen; 185 freq = (((int)(R_NR14&7) << 8) | R_NR13);
175 f = S1.swfreq; 186
176 n = (R_NR10 & 7); 187 int updown = 1;
177 if (R_NR10 & 8) f -= (f >> n); 188
178 else f += (f >> n); 189 if(S1.swdir)
179 if (f > 2047) 190 updown = -1;
180 S1.on = 0; 191
192 int newfreq = 0;
193 if(S1.swsteps)
194 {
195 newfreq = freq + updown * freq / (1 << S1.swsteps);
196 if(newfreq == freq)
197 newfreq = 0;
198 }
181 else 199 else
200 newfreq = freq;
201
202 if(newfreq < 0)
182 { 203 {
183 S1.swfreq = f; 204 S1.swlen += S1.swlenreload;
184 R_NR13 = f; 205 }
185 R_NR14 = (R_NR14 & 0xF8) | (f>>8); 206 else if(newfreq > 2047)
186 s1_freq_d(2048 - f); 207 {
208 S1.swlen = 0;
209 S1.on = 0;
210 R_NR52 &= 0xfe;
211 }
212 else
213 {
214 S1.swlen += S1.swlenreload;
215 S1.skip = SOUND_MAGIC/(2048 - newfreq);
216
217 R_NR13 = newfreq & 0xff;
218 R_NR14 = (R_NR14 & 0xf8) |((newfreq >> 8) & 7);
187 } 219 }
188 } 220 }
189 s <<= 2;
190 if (R_NR51 & 1) r += s;
191 if (R_NR51 & 16) l += s;
192 } 221 }
222 }
223}
193 224
194 if (S2.on) 225static void gbSoundChannel2(int *r, int *l)
195 { 226{
196 s = sqwave[R_NR21>>6][(S2.pos>>18)&7] & S2.envol; 227 int vol = S2.envol;
197 S2.pos += S2.freq; 228
198 if ((R_NR24 & 64) && ((S2.cnt += RATE) >= S2.len)) 229 int value = 0;
230
231 if(S2.on && (S2.len || !S2.cont))
232 {
233 S2.pos += snd.quality*S2.skip;
234 S2.pos &= 0x1fffffff;
235
236 value = ((signed char)S2.wave[S2.pos>>24]) * vol;
237 }
238
239 if (snd.balance & 2) *r += value;
240 if (snd.balance & 32) *l += value;
241
242 if(S2.on) {
243 if(S2.len) {
244 S2.len-=snd.quality;
245
246 if(S2.len <= 0 && S2.cont) {
247 R_NR52 &= 0xfd;
199 S2.on = 0; 248 S2.on = 0;
200 if (S2.enlen && (S2.encnt += RATE) >= S2.enlen)
201 {
202 S2.encnt -= S2.enlen;
203 S2.envol += S2.endir;
204 if (S2.envol < 0) S2.envol = 0;
205 if (S2.envol > 15) S2.envol = 15;
206 } 249 }
207 s <<= 2;
208 if (R_NR51 & 2) r += s;
209 if (R_NR51 & 32) l += s;
210 } 250 }
251
252 if(S2.enlen) {
253 S2.enlen-=snd.quality;
254
255 if(S2.enlen <= 0) {
256 if(S2.endir) {
257 if(S2.envol < 15)
258 S2.envol++;
259 } else {
260 if(S2.envol)
261 S2.envol--;
262 }
263 S2.enlen += S2.enlenreload;
264 }
265 }
266 }
267}
268
269static void gbSoundChannel3(int *r, int *l)
270{
271 int s;
272 if (S3.on && (S3.len || !S3.cont))
273 {
274 S3.pos += S3.skip*snd.quality;
275 S3.pos &= 0x1fffffff;
276 s=ram.hi[0x30 + (S3.pos>>25)];
277 if (S3.pos & 0x01000000)
278 s &= 0x0f;
279 else
280 s >>= 4;
281
282 s -= 8;
211 283
212 if (S3.on) 284 switch(S3.outputlevel)
213 { 285 {
214 s = WAVE[(S3.pos>>22) & 15]; 286 case 0:
215 if (S3.pos & (1<<21)) s &= 15; 287 s=0;
216 else s >>= 4; 288 break;
217 s -= 8; 289 case 1:
218 S3.pos += S3.freq; 290 break;
219 if ((R_NR34 & 64) && ((S3.cnt += RATE) >= S3.len)) 291 case 2:
220 S3.on = 0; 292 s=s>>1;
221 if (R_NR32 & 96) s <<= (3 - ((R_NR32>>5)&3)); 293 break;
222 else s = 0; 294 case 3:
223 if (R_NR51 & 4) r += s; 295 s=s>>2;
224 if (R_NR51 & 64) l += s; 296 break;
225 } 297 }
226 298
227 if (S4.on) 299 if (snd.balance & 4) *r += s;
300 if (snd.balance & 64) *l += s;
301 }
302
303 if(S3.on)
304 {
305 if(S3.len)
228 { 306 {
229 if (R_NR43 & 8) s = 1 & (noise7[ 307 S3.len-=snd.quality;
230 (S4.pos>>20)&15] >> (7-((S4.pos>>17)&7))); 308 if(S3.len<=0 && S3.cont)
231 else s = 1 & (noise15[ 309 {
232 (S4.pos>>20)&4095] >> (7-((S4.pos>>17)&7))); 310 R_NR52 &= 0xFB;
233 s = (-s) & S4.envol; 311 S3.on=0;
234 S4.pos += S4.freq; 312 }
235 if ((R_NR44 & 64) && ((S4.cnt += RATE) >= S4.len)) 313 }
314 }
315}
316
317void gbSoundChannel4(int *r, int *l)
318{
319 int vol = S4.envol;
320
321 int value = 0;
322
323 if(S4.clock <= 0x0c)
324 {
325 if(S4.on && (S4.len || !S4.cont))
326 {
327 S4.pos += snd.quality*S4.skip;
328 S4.shiftpos += snd.quality*S4.shiftskip;
329
330 if(S4.nsteps)
331 {
332 while(S4.shiftpos > 0x1fffff) {
333 S4.shiftright = (((S4.shiftright << 6) ^
334 (S4.shiftright << 5)) & 0x40) | (S4.shiftright >> 1);
335 S4.shiftpos -= 0x200000;
336 }
337 }
338 else
339 {
340 while(S4.shiftpos > 0x1fffff)
341 {
342 S4.shiftright = (((S4.shiftright << 14) ^
343 (S4.shiftright << 13)) & 0x4000) | (S4.shiftright >> 1);
344 S4.shiftpos -= 0x200000;
345 }
346 }
347
348 S4.pos &= 0x1fffff;
349 S4.shiftpos &= 0x1fffff;
350
351 value = ((S4.shiftright & 1)*2-1) * vol;
352 }
353 else
354 {
355 value = 0;
356 }
357 }
358
359 if (snd.balance & 8) *r += value;
360 if (snd.balance & 128) *l += value;
361
362 if(S4.on) {
363 if(S4.len) {
364 S4.len-=snd.quality;
365
366 if(S4.len <= 0 && S4.cont) {
367 R_NR52 &= 0xfd;
236 S4.on = 0; 368 S4.on = 0;
237 if (S4.enlen && (S4.encnt += RATE) >= S4.enlen) 369 }
370 }
371
372 if(S4.enlen) {
373 S4.enlen-=snd.quality;
374
375 if(S4.enlen <= 0)
238 { 376 {
239 S4.encnt -= S4.enlen; 377 if(S4.endir)
240 S4.envol += S4.endir; 378 {
241 if (S4.envol < 0) S4.envol = 0; 379 if(S4.envol < 15)
242 if (S4.envol > 15) S4.envol = 15; 380 S4.envol++;
381 }
382 else
383 {
384 if(S4.envol)
385 S4.envol--;
386 }
387 S4.enlen += S4.enlenreload;
243 } 388 }
244 s += s << 1;
245 if (R_NR51 & 8) r += s;
246 if (R_NR51 & 128) l += s;
247 } 389 }
390 }
391}
392
393void sound_mix(void)
394{
395 int l, r;
396
397 if (!RATE || cpu.snd < RATE) return;
398
399 for (; cpu.snd >= RATE; cpu.snd -= RATE)
400 {
401 l = r = 0;
248 402
249 l *= (R_NR50 & 0x07); 403 gbSoundChannel1(&r,&l);
250 r *= ((R_NR50 & 0x70)>>4);
251 l >>= 4;
252 r >>= 4;
253 404
254 if (l > 127) l = 127; 405 gbSoundChannel2(&r,&l);
255 else if (l < -128) l = -128; 406
256 if (r > 127) r = 127; 407 gbSoundChannel3(&r,&l);
257 else if (r < -128) r = -128; 408
409 gbSoundChannel4(&r,&l);
410
411 if(snd.gbDigitalSound)
412 {
413 l = snd.level1<<8;
414 r = snd.level2<<8;
415 }
416 else
417 {
418 l *= snd.level1*60;
419 r *= snd.level2*60;
420 }
421
422 if(l > 32767)
423 l = 32767;
424 if(l < -32768)
425 l = -32768;
426
427 if(r > 32767)
428 r = 32767;
429 if(r < -32768)
430 r = -32768;
258 431
259 if (pcm.buf) 432 if (pcm.buf)
260 { 433 {
@@ -262,17 +435,15 @@ void sound_mix(void)
262 pcm_submit(); 435 pcm_submit();
263 if (pcm.stereo) 436 if (pcm.stereo)
264 { 437 {
265 pcm.buf[pcm.pos++] = ((signed char)(l))<<7; 438 pcm.buf[pcm.pos++] = l;
266 pcm.buf[pcm.pos++] = ((signed char)(r))<<7; 439 pcm.buf[pcm.pos++] = r;
267 } 440 }
268 else pcm.buf[pcm.pos++] = ((signed char)((l+r)>>1))<<7; 441 else pcm.buf[pcm.pos++] = ((l+r)>>1);
269 } 442 }
270 } 443 }
271 R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3); 444 R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3);
272} 445}
273 446
274
275
276byte sound_read(byte r) 447byte sound_read(byte r)
277{ 448{
278 if(!options.sound) return 0; 449 if(!options.sound) return 0;
@@ -281,166 +452,327 @@ byte sound_read(byte r)
281 return REG(r); 452 return REG(r);
282} 453}
283 454
284void s1_init(void)
285{
286 S1.swcnt = 0;
287 S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
288 S1.envol = R_NR12 >> 4;
289 S1.endir = (R_NR12>>3) & 1;
290 S1.endir |= S1.endir - 1;
291 S1.enlen = (R_NR12 & 7) << 15;
292 if (!S1.on) S1.pos = 0;
293 S1.on = 1;
294 S1.cnt = 0;
295 S1.encnt = 0;
296}
297
298void s2_init(void)
299{
300 S2.envol = R_NR22 >> 4;
301 S2.endir = (R_NR22>>3) & 1;
302 S2.endir |= S2.endir - 1;
303 S2.enlen = (R_NR22 & 7) << 15;
304 if (!S2.on) S2.pos = 0;
305 S2.on = 1;
306 S2.cnt = 0;
307 S2.encnt = 0;
308}
309
310void s3_init(void)
311{
312 int i;
313 if (!S3.on) S3.pos = 0;
314 S3.cnt = 0;
315 S3.on = R_NR30 >> 7;
316 if (S3.on) for (i = 0; i < 16; i++)
317 ram.hi[i+0x30] = 0x13 ^ ram.hi[i+0x31];
318}
319
320void s4_init(void)
321{
322 S4.envol = R_NR42 >> 4;
323 S4.endir = (R_NR42>>3) & 1;
324 S4.endir |= S4.endir - 1;
325 S4.enlen = (R_NR42 & 7) << 15;
326 S4.on = 1;
327 S4.pos = 0;
328 S4.cnt = 0;
329 S4.encnt = 0;
330}
331
332
333void sound_write(byte r, byte b) 455void sound_write(byte r, byte b)
334{ 456{
335 if(!options.sound) return; 457 int freq=0;
458 ram.hi[r]=b;
336 459
337 if (!(R_NR52 & 128) && r != RI_NR52) return; 460 if(!options.sound)
338 if ((r & 0xF0) == 0x30)
339 {
340 if (S3.on) sound_mix();
341 if (!S3.on)
342 WAVE[r-0x30] = ram.hi[r] = b;
343 return; 461 return;
344 } 462
345 sound_mix(); 463 sound_mix();
464
346 switch (r) 465 switch (r)
347 { 466 {
348 case RI_NR10: 467 case RI_NR10:
349 R_NR10 = b; 468 S1.swlen = S1.swlenreload = 344 * ((b >> 4) & 7);
350 S1.swlen = ((R_NR10>>4) & 7) << 14; 469 S1.swsteps = b & 7;
351 S1.swfreq = ((R_NR14&7)<<8) + R_NR13; 470 S1.swdir = b & 0x08;
471 S1.swstep = 0;
352 break; 472 break;
353 case RI_NR11: 473 case RI_NR11:
354 R_NR11 = b; 474 S1.len = 172 * (64 - (b & 0x3f));
355 S1.len = (64-(R_NR11&63)) << 13; 475 S1.wave = soundWavePattern[b >> 6];
356 break; 476 break;
357 case RI_NR12: 477 case RI_NR12:
358 R_NR12 = b; 478 S1.envol = b >> 4;
359 S1.envol = R_NR12 >> 4; 479 S1.endir = b & 0x08;
360 S1.endir = (R_NR12>>3) & 1; 480 S1.enlenreload = S1.enlen = 689 * (b & 7);
361 S1.endir |= S1.endir - 1;
362 S1.enlen = (R_NR12 & 7) << 15;
363 break; 481 break;
364 case RI_NR13: 482 case RI_NR13:
365 R_NR13 = b; 483 freq = (((int)(R_NR14 & 7)) << 8) | b;
366 s1_freq(); 484 S1.len = 172 * (64 - (R_NR11 & 0x3f));
485 freq = 2048 - freq;
486 if(freq)
487 {
488 S1.skip = SOUND_MAGIC / freq;
489 }
490 else
491 {
492 S1.skip = 0;
493 }
367 break; 494 break;
368 case RI_NR14: 495 case RI_NR14:
369 R_NR14 = b; 496 freq = (((int)(b&7) << 8) | R_NR13);
370 s1_freq(); 497 freq = 2048 - freq;
371 if (b & 128) s1_init(); 498 S1.len = 172 * (64 - (R_NR11 & 0x3f));
499 S1.cont = b & 0x40;
500 if(freq)
501 {
502 S1.skip = SOUND_MAGIC / freq;
503 }
504 else
505 {
506 S1.skip = 0;
507 }
508 if(b & 0x80)
509 {
510 R_NR52 |= 1;
511 S1.envol = R_NR12 >> 4;
512 S1.endir = R_NR12 & 0x08;
513 S1.len = 172 * (64 - (R_NR11 & 0x3f));
514 S1.enlenreload = S1.enlen = 689 * (R_NR12 & 7);
515 S1.swlen = S1.swlenreload = 344 * ((R_NR10 >> 4) & 7);
516 S1.swsteps = R_NR10 & 7;
517 S1.swdir = R_NR10 & 0x08;
518 S1.swstep = 0;
519
520 S1.pos = 0;
521 S1.on = 1;
522 }
372 break; 523 break;
373 case RI_NR21: 524 case RI_NR21:
374 R_NR21 = b; 525 S2.wave = soundWavePattern[b >> 6];
375 S2.len = (64-(R_NR21&63)) << 13; 526 S2.len = 172 * (64 - (b & 0x3f));
376 break; 527 break;
377 case RI_NR22: 528 case RI_NR22:
378 R_NR22 = b; 529 S2.envol = b >> 4;
379 S2.envol = R_NR22 >> 4; 530 S2.endir = b & 0x08;
380 S2.endir = (R_NR22>>3) & 1; 531 S2.enlenreload = S2.enlen = 689 * (b & 7);
381 S2.endir |= S2.endir - 1;
382 S2.enlen = (R_NR22 & 7) << 15;
383 break; 532 break;
384 case RI_NR23: 533 case RI_NR23:
385 R_NR23 = b; 534 freq = (((int)(R_NR24 & 7)) << 8) | b;
386 s2_freq(); 535 S2.len = 172 * (64 - (R_NR21 & 0x3f));
536 freq = 2048 - freq;
537 if(freq)
538 {
539 S2.skip = SOUND_MAGIC / freq;
540 }
541 else
542 {
543 S2.skip = 0;
544 }
387 break; 545 break;
388 case RI_NR24: 546 case RI_NR24:
389 R_NR24 = b; 547 freq = (((int)(b&7) << 8) | R_NR23);
390 s2_freq(); 548 freq = 2048 - freq;
391 if (b & 128) s2_init(); 549 S2.len = 172 * (64 - (R_NR21 & 0x3f));
550 S2.cont = b & 0x40;
551 if(freq) {
552 S2.skip = SOUND_MAGIC / freq;
553 } else
554 S2.skip = 0;
555 if(b & 0x80) {
556 R_NR52 |= 2;
557 S2.envol = R_NR22 >> 4;
558 S2.endir = R_NR22 & 0x08;
559 S2.len = 172 * (64 - (R_NR21 & 0x3f));
560 S2.enlenreload = S2.enlen = 689 * (R_NR22 & 7);
561
562 S2.pos = 0;
563 S2.on = 1;
564 }
392 break; 565 break;
393 case RI_NR30: 566 case RI_NR30:
394 R_NR30 = b; 567 if (!(b & 0x80)){
395 if (!(b & 128)) S3.on = 0; 568 R_NR52 &= 0xfb;
569 S3.on = 0;
570 }
396 break; 571 break;
397 case RI_NR31: 572 case RI_NR31:
398 R_NR31 = b; 573 S3.len = (256-R_NR31) * 172;
399 S3.len = (256-R_NR31) << 13;
400 break; 574 break;
401 case RI_NR32: 575 case RI_NR32:
402 R_NR32 = b; 576 S3.outputlevel = (b >> 5) & 3;
403 break; 577 break;
404 case RI_NR33: 578 case RI_NR33:
405 R_NR33 = b; 579 freq = 2048 - (((int)(R_NR34&7) << 8) | b);
406 s3_freq(); 580 if(freq)
581 S3.skip = SOUND_MAGIC_2 / freq;
582 else
583 S3.skip = 0;
407 break; 584 break;
408 case RI_NR34: 585 case RI_NR34:
409 R_NR34 = b; 586 freq = 2048 - (((b&7)<<8) | R_NR33);
410 s3_freq(); 587
411 if (b & 128) s3_init(); 588 if(freq)
589 S3.skip = SOUND_MAGIC_2 / freq;
590 else
591 S3.skip = 0;
592
593 S3.cont=b & 0x40;
594 if((b & 0x80) && (R_NR30 & 0x80))
595 {
596 R_NR52 |= 4;
597 S3.len = 172 * (256 - R_NR31);
598 S3.pos = 0;
599 S3.on = 1;
600 }
412 break; 601 break;
413 case RI_NR41: 602 case RI_NR41:
414 R_NR41 = b; 603 S4.len = 172 * (64 - (b & 0x3f));
415 S4.len = (64-(R_NR41&63)) << 13;
416 break; 604 break;
417 case RI_NR42: 605 case RI_NR42:
418 R_NR42 = b; 606 S4.envol = b >> 4;
419 S4.envol = R_NR42 >> 4; 607 S4.endir = b & 0x08;
420 S4.endir = (R_NR42>>3) & 1; 608 S4.enlenreload = S4.enlen = 689 * (b & 7);
421 S4.endir |= S4.endir - 1;
422 S4.enlen = (R_NR42 & 7) << 15;
423 break; 609 break;
424 case RI_NR43: 610 case RI_NR43:
425 R_NR43 = b; 611 freq = soundFreqRatio[b & 7];
426 s4_freq(); 612
613 S4.nsteps = b & 0x08;
614 S4.skip = (freq << 8) / NOISE_MAGIC;
615 S4.clock = b >> 4;
616
617 freq = freq / soundShiftClock[S4.clock];
618 S4.shiftskip = (freq << 8) / NOISE_MAGIC;
427 break; 619 break;
428 case RI_NR44: 620 case RI_NR44:
429 R_NR44 = b; 621 S4.cont = b & 0x40;
430 if (b & 128) s4_init(); 622 if(b & 0x80)
623 {
624 R_NR52 |= 8;
625 S4.envol = R_NR42 >> 4;
626 S4.endir = R_NR42 & 0x08;
627 S4.len = 172 * (64 - (R_NR41 & 0x3f));
628 S4.enlenreload = S4.enlen = 689 * (R_NR42 & 7);
629
630 S4.on = 1;
631
632 S4.pos = 0;
633 S4.shiftpos = 0;
634
635 freq = soundFreqRatio[R_NR43 & 7];
636
637 S4.shiftpos = (freq << 8) / NOISE_MAGIC;
638
639 S4.nsteps = R_NR43 & 0x08;
640
641 freq = freq / soundShiftClock[R_NR43 >> 4];
642
643 S4.shiftskip = (freq << 8) / NOISE_MAGIC;
644 if(S4.nsteps)
645 {
646 S4.shiftright = 0x7fff;
647 }
648 else
649 {
650 S4.shiftright = 0x7f;
651 }
652 }
431 break; 653 break;
432 case RI_NR50: 654 case RI_NR50:
433 R_NR50 = b; 655 snd.level1 = b & 7;
656 snd.level2 = (b >> 4) & 7;
434 break; 657 break;
435 case RI_NR51: 658 case RI_NR51:
436 R_NR51 = b; 659 snd.balance = b;
437 break; 660 break;
438 case RI_NR52: 661 case RI_NR52:
439 R_NR52 = b; 662 if (!(b & 0x80))
440 if (!(R_NR52 & 128)) 663 {
441 sound_off(); 664 S1.on=0;
665 S2.on=0;
666 S3.on=0;
667 S4.on=0;
668 }
442 break; 669 break;
443 default:
444 return;
445 } 670 }
671
672 snd.gbDigitalSound = true;
673
674 if(S1.on && S1.envol != 0)
675 snd.gbDigitalSound = false;
676 if(S2.on && S2.envol != 0)
677 snd.gbDigitalSound = false;
678 if(S3.on && S3.outputlevel != 0)
679 snd.gbDigitalSound = false;
680 if(S4.on && S4.envol != 0)
681 snd.gbDigitalSound = false;
682}
683
684void sound_reset()
685{
686 snd.level1 = 7;
687 snd.level2 = 7;
688 S1.on = S2.on = S3.on = S4.on = 0;
689 S1.len = S2.len = S3.len = S4.len = 0;
690 S1.skip = S2.skip = S3.skip = S4.skip = 0;
691 S1.pos = S2.pos = S3.pos = S4.pos = 0;
692 S1.cont = S2.cont = S3.cont = S4.cont = 0;
693 S1.envol = S2.envol = S4.envol = 0;
694 S1.enlen = S2.enlen = S4.enlen = 0;
695 S1.endir = S2.endir = S4.endir = 0;
696 S1.enlenreload = S2.enlenreload = S4.enlenreload = 0;
697 S1.swlen = 0;
698 S1.swlenreload = 0;
699 S1.swsteps = 0;
700 S1.swdir = 0;
701 S1.swstep = 0;
702 S1.wave = S2.wave = soundWavePattern[2];
703
704 S3.outputlevel = 0;
705
706 S4.clock = 0;
707 S4.shiftright = 0x7f;
708 S4.nsteps = 0;
709
710 sound_write(0x10, 0x80);
711 sound_write(0x11, 0xbf);
712 sound_write(0x12, 0xf3);
713 sound_write(0x14, 0xbf);
714 sound_write(0x16, 0x3f);
715 sound_write(0x17, 0x00);
716 sound_write(0x19, 0xbf);
717
718 sound_write(0x1a, 0x7f);
719 sound_write(0x1b, 0xff);
720 sound_write(0x1c, 0xbf);
721 sound_write(0x1e, 0xbf);
722
723 sound_write(0x20, 0xff);
724 sound_write(0x21, 0x00);
725 sound_write(0x22, 0x00);
726 sound_write(0x23, 0xbf);
727 sound_write(0x24, 0x77);
728 sound_write(0x25, 0xf3);
729
730 sound_write(0x26, 0xf0);
731
732 S1.on = 0;
733 S2.on = 0;
734 S3.on = 0;
735 S4.on = 0;
736
737 int addr = 0x30;
738 while(addr < 0x40)
739 {
740 ram.hi[addr++] = 0x00;
741 ram.hi[addr++] = 0xff;
742 }
743
744 if (pcm.hz)
745 {
746 snd.rate = (1<<21) / pcm.hz;
747 snd.quality=44100 / pcm.hz;
748 }
749 else snd.rate = 0;
750}
751
752void sound_dirty()
753{
754 sound_write(RI_NR10, R_NR10);
755 sound_write(RI_NR11, R_NR11);
756 sound_write(RI_NR12, R_NR12);
757 sound_write(RI_NR13, R_NR13);
758 sound_write(RI_NR14, R_NR14);
759
760 sound_write(RI_NR21, R_NR21);
761 sound_write(RI_NR22, R_NR22);
762 sound_write(RI_NR23, R_NR23);
763 sound_write(RI_NR24, R_NR24);
764
765 sound_write(RI_NR30, R_NR30);
766 sound_write(RI_NR31, R_NR31);
767 sound_write(RI_NR32, R_NR32);
768 sound_write(RI_NR33, R_NR33);
769 sound_write(RI_NR34, R_NR34);
770
771 sound_write(RI_NR42, R_NR42);
772 sound_write(RI_NR43, R_NR43);
773 sound_write(RI_NR44, R_NR44);
774
775 sound_write(RI_NR50, R_NR50);
776 sound_write(RI_NR51, R_NR51);
777 sound_write(RI_NR52, R_NR52);
446} 778}
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 @@
5 5
6struct sndchan 6struct sndchan
7{ 7{
8 int on; 8 /* S1, S2, S3, S4 */
9 unsigned pos; 9 int on, len, skip, cont;
10 int cnt, encnt, swcnt; 10 unsigned int pos;
11 int len, enlen, swlen; 11
12 int swfreq; 12 /* S1, S2, S4 */
13 int freq; 13 int enlen, envol, endir, enlenreload;
14 int envol, endir; 14
15 /* S1, S2 */
16 const byte *wave;
17
18 /* S1 only */
19 int swlen, swlenreload, swsteps, swstep, swdir;
20
21 /* S3 only */
22 int outputlevel;
23
24 /* S4 only */
25 int shiftskip, shiftpos, shiftright, shiftleft;
26 int nsteps, clock;
27
15}; 28};
16 29
17struct snd 30struct snd
18{ 31{
32 int level1, level2, balance;
33 bool gbDigitalSound;
19 int rate; 34 int rate;
35 int quality;
20 struct sndchan ch[4]; 36 struct sndchan ch[4];
21}; 37};
22 38
@@ -29,12 +45,8 @@ extern struct snd snd;
29 45
30byte sound_read(byte r) ICODE_ATTR; 46byte sound_read(byte r) ICODE_ATTR;
31void sound_write(byte r, byte b) ICODE_ATTR; 47void sound_write(byte r, byte b) ICODE_ATTR;
32void sound_dirty(void) ICODE_ATTR; 48void sound_dirty(void);
33void sound_reset(void); 49void sound_reset(void);
34void sound_mix(void) ICODE_ATTR; 50void sound_mix(void) ICODE_ATTR;
35void s1_init(void);
36void s2_init(void);
37void s3_init(void);
38void s4_init(void);
39 51
40#endif 52#endif