diff options
Diffstat (limited to 'apps/plugins/rockboy/sound.c')
-rw-r--r-- | apps/plugins/rockboy/sound.c | 140 |
1 files changed, 45 insertions, 95 deletions
diff --git a/apps/plugins/rockboy/sound.c b/apps/plugins/rockboy/sound.c index deeacc7bbf..707bb6b956 100644 --- a/apps/plugins/rockboy/sound.c +++ b/apps/plugins/rockboy/sound.c | |||
@@ -8,63 +8,38 @@ | |||
8 | #include "cpu-gb.h" | 8 | #include "cpu-gb.h" |
9 | #include "hw.h" | 9 | #include "hw.h" |
10 | #include "regs.h" | 10 | #include "regs.h" |
11 | #include "rc.h" | ||
12 | #include "noise.h" | 11 | #include "noise.h" |
13 | 12 | ||
14 | 13 | ||
15 | static const byte dmgwave[16] = | ||
16 | { | ||
17 | 0xac, 0xdd, 0xda, 0x48, | ||
18 | 0x36, 0x02, 0xcf, 0x16, | ||
19 | 0x2c, 0x04, 0xe5, 0x2c, | ||
20 | 0xac, 0xdd, 0xda, 0x48 | ||
21 | }; | ||
22 | |||
23 | static const byte cgbwave[16] = | ||
24 | { | ||
25 | 0x00, 0xff, 0x00, 0xff, | ||
26 | 0x00, 0xff, 0x00, 0xff, | ||
27 | 0x00, 0xff, 0x00, 0xff, | ||
28 | 0x00, 0xff, 0x00, 0xff, | ||
29 | }; | ||
30 | |||
31 | |||
32 | static const byte sqwave[4][8] = | 14 | static const byte sqwave[4][8] = |
33 | { | 15 | { |
34 | { 0, 0,-1, 0, 0, 0, 0, 0 }, | 16 | { 0, 0,-1, 0, 0, 0, 0, 0 }, |
35 | { 0,-1,-1, 0, 0, 0, 0, 0 }, | 17 | { 0,-1,-1, 0, 0, 0, 0, 0 }, |
36 | { -1,-1,-1,-1, 0, 0, 0, 0 }, | 18 | { 0,-1,-1,-1,-1, 0, 0, 0 }, |
37 | { -1, 0, 0,-1,-1,-1,-1,-1 } | 19 | { -1, 0, 0,-1,-1,-1,-1,-1 } |
38 | }; | 20 | }; |
39 | 21 | ||
40 | static const int freqtab[8] = | 22 | static const int freqtab[8] = |
41 | { | 23 | { |
42 | (1<<14)*2, | 24 | (1<<18)*2, |
43 | (1<<14), | 25 | (1<<18), |
44 | (1<<14)/2, | 26 | (1<<18)/2, |
45 | (1<<14)/3, | 27 | (1<<18)/3, |
46 | (1<<14)/4, | 28 | (1<<18)/4, |
47 | (1<<14)/5, | 29 | (1<<18)/5, |
48 | (1<<14)/6, | 30 | (1<<18)/6, |
49 | (1<<14)/7 | 31 | (1<<18)/7 |
50 | }; | 32 | }; |
51 | 33 | ||
52 | struct snd snd IBSS_ATTR; | 34 | struct snd snd IBSS_ATTR; |
53 | int pcm_submit(void); | ||
54 | 35 | ||
55 | #define RATE (snd.rate) | 36 | #define RATE (snd.rate) |
56 | #define WAVE (snd.wave) /* ram.hi+0x30 */ | 37 | #define WAVE (ram.hi+0x30) |
57 | #define S1 (snd.ch[0]) | 38 | #define S1 (snd.ch[0]) |
58 | #define S2 (snd.ch[1]) | 39 | #define S2 (snd.ch[1]) |
59 | #define S3 (snd.ch[2]) | 40 | #define S3 (snd.ch[2]) |
60 | #define S4 (snd.ch[3]) | 41 | #define S4 (snd.ch[3]) |
61 | 42 | ||
62 | rcvar_t sound_exports[] = | ||
63 | { | ||
64 | RCV_END | ||
65 | }; | ||
66 | |||
67 | |||
68 | static void s1_freq_d(int d) | 43 | static void s1_freq_d(int d) |
69 | { | 44 | { |
70 | if (RATE > (d<<4)) S1.freq = 0; | 45 | if (RATE > (d<<4)) S1.freq = 0; |
@@ -86,14 +61,13 @@ static void s2_freq(void) | |||
86 | static void s3_freq(void) | 61 | static void s3_freq(void) |
87 | { | 62 | { |
88 | int d = 2048 - (((R_NR34&7)<<8) + R_NR33); | 63 | int d = 2048 - (((R_NR34&7)<<8) + R_NR33); |
89 | if (RATE > (d<<3)) S3.freq = 0; | 64 | if (RATE > d) S3.freq = 0; |
90 | else S3.freq = (RATE << 21)/d; | 65 | else S3.freq = (RATE << 21)/d; |
91 | } | 66 | } |
92 | 67 | ||
93 | static void s4_freq(void) | 68 | static void s4_freq(void) |
94 | { | 69 | { |
95 | S4.freq = (freqtab[R_NR43&7] >> (R_NR43 >> 4)) * RATE; | 70 | S4.freq = (freqtab[R_NR43&7] >> (R_NR43 >> 4)) * RATE; |
96 | if (S4.freq >> 18) S4.freq = 1<<18; | ||
97 | } | 71 | } |
98 | 72 | ||
99 | void sound_dirty(void) | 73 | void sound_dirty(void) |
@@ -103,13 +77,13 @@ void sound_dirty(void) | |||
103 | S1.envol = R_NR12 >> 4; | 77 | S1.envol = R_NR12 >> 4; |
104 | S1.endir = (R_NR12>>3) & 1; | 78 | S1.endir = (R_NR12>>3) & 1; |
105 | S1.endir |= S1.endir - 1; | 79 | S1.endir |= S1.endir - 1; |
106 | S1.enlen = (R_NR12 & 7) << 15; | 80 | S1.enlen = (R_NR12 & 3) << 15; |
107 | s1_freq(); | 81 | s1_freq(); |
108 | S2.len = (64-(R_NR21&63)) << 13; | 82 | S2.len = (64-(R_NR21&63)) << 13; |
109 | S2.envol = R_NR22 >> 4; | 83 | S2.envol = R_NR22 >> 4; |
110 | S2.endir = (R_NR22>>3) & 1; | 84 | S2.endir = (R_NR22>>3) & 1; |
111 | S2.endir |= S2.endir - 1; | 85 | S2.endir |= S2.endir - 1; |
112 | S2.enlen = (R_NR22 & 7) << 15; | 86 | S2.enlen = (R_NR22 & 3) << 15; |
113 | s2_freq(); | 87 | s2_freq(); |
114 | S3.len = (256-R_NR31) << 20; | 88 | S3.len = (256-R_NR31) << 20; |
115 | s3_freq(); | 89 | s3_freq(); |
@@ -117,16 +91,16 @@ void sound_dirty(void) | |||
117 | S4.envol = R_NR42 >> 4; | 91 | S4.envol = R_NR42 >> 4; |
118 | S4.endir = (R_NR42>>3) & 1; | 92 | S4.endir = (R_NR42>>3) & 1; |
119 | S4.endir |= S4.endir - 1; | 93 | S4.endir |= S4.endir - 1; |
120 | S4.enlen = (R_NR42 & 7) << 15; | 94 | S4.enlen = (R_NR42 & 3) << 15; |
121 | s4_freq(); | 95 | s4_freq(); |
122 | } | 96 | } |
123 | 97 | ||
124 | void sound_off(void) | 98 | void sound_reset(void) |
125 | { | 99 | { |
126 | memset(&S1, 0, sizeof S1); | 100 | int i; |
127 | memset(&S2, 0, sizeof S2); | 101 | memset(&snd, 0, sizeof snd); |
128 | memset(&S3, 0, sizeof S3); | 102 | if (pcm.hz) snd.rate = (1<<21) / pcm.hz; |
129 | memset(&S4, 0, sizeof S4); | 103 | else snd.rate = 0; |
130 | R_NR10 = 0x80; | 104 | R_NR10 = 0x80; |
131 | R_NR11 = 0xBF; | 105 | R_NR11 = 0xBF; |
132 | R_NR12 = 0xF3; | 106 | R_NR12 = 0xF3; |
@@ -137,7 +111,7 @@ void sound_off(void) | |||
137 | R_NR30 = 0x7F; | 111 | R_NR30 = 0x7F; |
138 | R_NR31 = 0xFF; | 112 | R_NR31 = 0xFF; |
139 | R_NR32 = 0x9F; | 113 | R_NR32 = 0x9F; |
140 | R_NR33 = 0xBF; | 114 | R_NR34 = 0xBF; |
141 | R_NR41 = 0xFF; | 115 | R_NR41 = 0xFF; |
142 | R_NR42 = 0x00; | 116 | R_NR42 = 0x00; |
143 | R_NR43 = 0x00; | 117 | R_NR43 = 0x00; |
@@ -145,23 +119,13 @@ void sound_off(void) | |||
145 | R_NR50 = 0x77; | 119 | R_NR50 = 0x77; |
146 | R_NR51 = 0xF3; | 120 | R_NR51 = 0xF3; |
147 | R_NR52 = 0xF1; | 121 | R_NR52 = 0xF1; |
122 | for (i = 0; i < 16; i++) WAVE[i] = -(i&1); | ||
148 | sound_dirty(); | 123 | sound_dirty(); |
149 | } | 124 | } |
150 | 125 | ||
151 | void sound_reset(void) | ||
152 | { | ||
153 | memset(&snd, 0, sizeof snd); | ||
154 | if (pcm.hz) snd.rate = (1<<21) / pcm.hz; | ||
155 | else snd.rate = 0; | ||
156 | memcpy(WAVE, hw.cgb ? cgbwave : dmgwave, 16); | ||
157 | memcpy(ram.hi+0x30, WAVE, 16); | ||
158 | sound_off(); | ||
159 | } | ||
160 | |||
161 | void sound_mix(void) | 126 | void sound_mix(void) |
162 | { | 127 | { |
163 | 128 | if(!options.sound) return; | |
164 | if (!options.sound) return; | ||
165 | int s, l, r, f, n; | 129 | int s, l, r, f, n; |
166 | 130 | ||
167 | if (!RATE || cpu.snd < RATE) return; | 131 | if (!RATE || cpu.snd < RATE) return; |
@@ -185,8 +149,7 @@ void sound_mix(void) | |||
185 | } | 149 | } |
186 | if (S1.swlen && (S1.swcnt += RATE) >= S1.swlen) | 150 | if (S1.swlen && (S1.swcnt += RATE) >= S1.swlen) |
187 | { | 151 | { |
188 | S1.swcnt -= S1.swlen; | 152 | f = ((R_NR14 & 7) << 8) + R_NR13; |
189 | f = S1.swfreq; | ||
190 | n = (R_NR10 & 7); | 153 | n = (R_NR10 & 7); |
191 | if (R_NR10 & 8) f -= (f >> n); | 154 | if (R_NR10 & 8) f -= (f >> n); |
192 | else f += (f >> n); | 155 | else f += (f >> n); |
@@ -194,15 +157,14 @@ void sound_mix(void) | |||
194 | S1.on = 0; | 157 | S1.on = 0; |
195 | else | 158 | else |
196 | { | 159 | { |
197 | S1.swfreq = f; | ||
198 | R_NR13 = f; | 160 | R_NR13 = f; |
199 | R_NR14 = (R_NR14 & 0xF8) | (f>>8); | 161 | R_NR14 = (R_NR14 & 0xF8) | (f>>8); |
200 | s1_freq_d(2048 - f); | 162 | s1_freq_d(2048 - f); |
201 | } | 163 | } |
202 | } | 164 | } |
203 | s <<= 2; | 165 | s <<= 2; |
204 | if (R_NR51 & 1) r += s; | 166 | if (R_NR51 & 1) l += s; |
205 | if (R_NR51 & 16) l += s; | 167 | if (R_NR51 & 16) r += s; |
206 | } | 168 | } |
207 | 169 | ||
208 | if (S2.on) | 170 | if (S2.on) |
@@ -219,8 +181,8 @@ void sound_mix(void) | |||
219 | if (S2.envol > 15) S2.envol = 15; | 181 | if (S2.envol > 15) S2.envol = 15; |
220 | } | 182 | } |
221 | s <<= 2; | 183 | s <<= 2; |
222 | if (R_NR51 & 2) r += s; | 184 | if (R_NR51 & 2) l += s; |
223 | if (R_NR51 & 32) l += s; | 185 | if (R_NR51 & 32) r += s; |
224 | } | 186 | } |
225 | 187 | ||
226 | if (S3.on) | 188 | if (S3.on) |
@@ -234,16 +196,16 @@ void sound_mix(void) | |||
234 | S3.on = 0; | 196 | S3.on = 0; |
235 | if (R_NR32 & 96) s <<= (3 - ((R_NR32>>5)&3)); | 197 | if (R_NR32 & 96) s <<= (3 - ((R_NR32>>5)&3)); |
236 | else s = 0; | 198 | else s = 0; |
237 | if (R_NR51 & 4) r += s; | 199 | if (R_NR51 & 4) l += s; |
238 | if (R_NR51 & 64) l += s; | 200 | if (R_NR51 & 64) r += s; |
239 | } | 201 | } |
240 | 202 | ||
241 | if (S4.on) | 203 | if (S4.on) |
242 | { | 204 | { |
243 | if (R_NR43 & 8) s = 1 & (noise7[ | 205 | if (R_NR43 & 8) s = 1 & (noise7[ |
244 | (S4.pos>>20)&15] >> (7-((S4.pos>>17)&7))); | 206 | (S4.pos>>24)&15] >> ((S4.pos>>21)&7)); |
245 | else s = 1 & (noise15[ | 207 | else s = 1 & (noise15[ |
246 | (S4.pos>>20)&4095] >> (7-((S4.pos>>17)&7))); | 208 | (S4.pos>>24)&4095] >> ((S4.pos>>21)&7)); |
247 | s = (-s) & S4.envol; | 209 | s = (-s) & S4.envol; |
248 | S4.pos += S4.freq; | 210 | S4.pos += S4.freq; |
249 | if ((R_NR44 & 64) && ((S4.cnt += RATE) >= S4.len)) | 211 | if ((R_NR44 & 64) && ((S4.cnt += RATE) >= S4.len)) |
@@ -255,9 +217,9 @@ void sound_mix(void) | |||
255 | if (S4.envol < 0) S4.envol = 0; | 217 | if (S4.envol < 0) S4.envol = 0; |
256 | if (S4.envol > 15) S4.envol = 15; | 218 | if (S4.envol > 15) S4.envol = 15; |
257 | } | 219 | } |
258 | s += s << 1; | 220 | s <<= 2; |
259 | if (R_NR51 & 8) r += s; | 221 | if (R_NR51 & 8) l += s; |
260 | if (R_NR51 & 128) l += s; | 222 | if (R_NR51 & 128) r += s; |
261 | } | 223 | } |
262 | 224 | ||
263 | l *= (R_NR50 & 0x07); | 225 | l *= (R_NR50 & 0x07); |
@@ -276,10 +238,10 @@ void sound_mix(void) | |||
276 | pcm_submit(); | 238 | pcm_submit(); |
277 | if (pcm.stereo) | 239 | if (pcm.stereo) |
278 | { | 240 | { |
279 | pcm.buf[pcm.pos++] = l+128; | 241 | pcm.buf[pcm.pos++] = l+128; |
280 | pcm.buf[pcm.pos++] = r+128; | 242 | pcm.buf[pcm.pos++] = r+128; |
281 | } | 243 | } |
282 | else pcm.buf[pcm.pos++] = ((l+r)>>1)+128; | 244 | else pcm.buf[pcm.pos++] = ((l+r)>>1)+128; |
283 | } | 245 | } |
284 | } | 246 | } |
285 | R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3); | 247 | R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3); |
@@ -289,7 +251,7 @@ void sound_mix(void) | |||
289 | 251 | ||
290 | byte sound_read(byte r) | 252 | byte sound_read(byte r) |
291 | { | 253 | { |
292 | if(!options.sound) return 0; | 254 | if(!options.sound) return 0; |
293 | sound_mix(); | 255 | sound_mix(); |
294 | /* printf("read %02X: %02X\n", r, REG(r)); */ | 256 | /* printf("read %02X: %02X\n", r, REG(r)); */ |
295 | return REG(r); | 257 | return REG(r); |
@@ -298,13 +260,12 @@ byte sound_read(byte r) | |||
298 | void s1_init(void) | 260 | void s1_init(void) |
299 | { | 261 | { |
300 | S1.swcnt = 0; | 262 | S1.swcnt = 0; |
301 | S1.swfreq = ((R_NR14&7)<<8) + R_NR13; | ||
302 | S1.envol = R_NR12 >> 4; | 263 | S1.envol = R_NR12 >> 4; |
303 | S1.endir = (R_NR12>>3) & 1; | 264 | S1.endir = (R_NR12>>3) & 1; |
304 | S1.endir |= S1.endir - 1; | 265 | S1.endir |= S1.endir - 1; |
305 | S1.enlen = (R_NR12 & 7) << 15; | 266 | S1.enlen = (R_NR12 & 7) << 15; |
306 | if (!S1.on) S1.pos = 0; | ||
307 | S1.on = 1; | 267 | S1.on = 1; |
268 | S1.pos = 0; | ||
308 | S1.cnt = 0; | 269 | S1.cnt = 0; |
309 | S1.encnt = 0; | 270 | S1.encnt = 0; |
310 | } | 271 | } |
@@ -315,20 +276,17 @@ void s2_init(void) | |||
315 | S2.endir = (R_NR22>>3) & 1; | 276 | S2.endir = (R_NR22>>3) & 1; |
316 | S2.endir |= S2.endir - 1; | 277 | S2.endir |= S2.endir - 1; |
317 | S2.enlen = (R_NR22 & 7) << 15; | 278 | S2.enlen = (R_NR22 & 7) << 15; |
318 | if (!S2.on) S2.pos = 0; | ||
319 | S2.on = 1; | 279 | S2.on = 1; |
280 | S2.pos = 0; | ||
320 | S2.cnt = 0; | 281 | S2.cnt = 0; |
321 | S2.encnt = 0; | 282 | S2.encnt = 0; |
322 | } | 283 | } |
323 | 284 | ||
324 | void s3_init(void) | 285 | void s3_init(void) |
325 | { | 286 | { |
326 | int i; | 287 | S3.pos = 0; |
327 | if (!S3.on) S3.pos = 0; | ||
328 | S3.cnt = 0; | 288 | S3.cnt = 0; |
329 | S3.on = R_NR30 >> 7; | 289 | S3.on = R_NR30 >> 7; |
330 | if (S3.on) for (i = 0; i < 16; i++) | ||
331 | ram.hi[i+0x30] = 0x13 ^ ram.hi[i+0x31]; | ||
332 | } | 290 | } |
333 | 291 | ||
334 | void s4_init(void) | 292 | void s4_init(void) |
@@ -346,19 +304,13 @@ void s4_init(void) | |||
346 | 304 | ||
347 | void sound_write(byte r, byte b) | 305 | void sound_write(byte r, byte b) |
348 | { | 306 | { |
349 | if(!options.sound) return; | 307 | if(!options.sound) return; |
350 | #if 0 | ||
351 | static void *timer; | ||
352 | if (!timer) timer = sys_timer(); | ||
353 | printf("write %02X: %02X @ %d\n", r, b, sys_elapsed(timer)); | ||
354 | #endif | ||
355 | 308 | ||
356 | if (!(R_NR52 & 128) && r != RI_NR52) return; | 309 | if (!(R_NR52 & 128) && r != RI_NR52) return; |
357 | if ((r & 0xF0) == 0x30) | 310 | if ((r & 0xF0) == 0x30) |
358 | { | 311 | { |
359 | if (S3.on) sound_mix(); | 312 | if (S3.on) sound_mix(); |
360 | if (!S3.on) | 313 | if (!S3.on) WAVE[r - 0x30] = b; |
361 | WAVE[r-0x30] = ram.hi[r] = b; | ||
362 | return; | 314 | return; |
363 | } | 315 | } |
364 | sound_mix(); | 316 | sound_mix(); |
@@ -366,8 +318,6 @@ void sound_write(byte r, byte b) | |||
366 | { | 318 | { |
367 | case RI_NR10: | 319 | case RI_NR10: |
368 | R_NR10 = b; | 320 | R_NR10 = b; |
369 | S1.swlen = ((R_NR10>>4) & 7) << 14; | ||
370 | S1.swfreq = ((R_NR14&7)<<8) + R_NR13; | ||
371 | break; | 321 | break; |
372 | case RI_NR11: | 322 | case RI_NR11: |
373 | R_NR11 = b; | 323 | R_NR11 = b; |
@@ -415,7 +365,7 @@ void sound_write(byte r, byte b) | |||
415 | break; | 365 | break; |
416 | case RI_NR31: | 366 | case RI_NR31: |
417 | R_NR31 = b; | 367 | R_NR31 = b; |
418 | S3.len = (256-R_NR31) << 13; | 368 | S3.len = (256-R_NR31) << 20; |
419 | break; | 369 | break; |
420 | case RI_NR32: | 370 | case RI_NR32: |
421 | R_NR32 = b; | 371 | R_NR32 = b; |
@@ -457,7 +407,7 @@ void sound_write(byte r, byte b) | |||
457 | case RI_NR52: | 407 | case RI_NR52: |
458 | R_NR52 = b; | 408 | R_NR52 = b; |
459 | if (!(R_NR52 & 128)) | 409 | if (!(R_NR52 & 128)) |
460 | sound_off(); | 410 | sound_reset(); |
461 | break; | 411 | break; |
462 | default: | 412 | default: |
463 | return; | 413 | return; |