fix crash when specifying --source on command line
[rofl0r-gnuboy.git] / sound.c
blobc441ff180625e8ecaed4555f317afccb6d8eff7d
1 #include <string.h>
4 #include "defs.h"
5 #include "pcm.h"
6 #include "sound.h"
7 #include "cpu.h"
8 #include "hw.h"
9 #include "regs.h"
10 #include "rc.h"
11 #include "noise.h"
12 #include "sys.h"
14 const static byte dmgwave[16] =
16 0xac, 0xdd, 0xda, 0x48,
17 0x36, 0x02, 0xcf, 0x16,
18 0x2c, 0x04, 0xe5, 0x2c,
19 0xac, 0xdd, 0xda, 0x48
22 const static byte cgbwave[16] =
24 0x00, 0xff, 0x00, 0xff,
25 0x00, 0xff, 0x00, 0xff,
26 0x00, 0xff, 0x00, 0xff,
27 0x00, 0xff, 0x00, 0xff,
30 const static byte sqwave[4][8] =
32 { 0, 0,-1, 0, 0, 0, 0, 0 },
33 { 0,-1,-1, 0, 0, 0, 0, 0 },
34 { -1,-1,-1,-1, 0, 0, 0, 0 },
35 { -1, 0, 0,-1,-1,-1,-1,-1 }
38 const static int freqtab[8] =
40 (1<<14)*2,
41 (1<<14),
42 (1<<14)/2,
43 (1<<14)/3,
44 (1<<14)/4,
45 (1<<14)/5,
46 (1<<14)/6,
47 (1<<14)/7
50 struct snd snd;
52 #define RATE (snd.rate)
53 #define WAVE (snd.wave) /* ram.hi+0x30 */
54 #define S1 (snd.ch[0])
55 #define S2 (snd.ch[1])
56 #define S3 (snd.ch[2])
57 #define S4 (snd.ch[3])
59 rcvar_t sound_exports[] =
61 RCV_END
65 static void s1_freq_d(int d)
67 if (RATE > (d<<4)) S1.freq = 0;
68 else S1.freq = (RATE << 17)/d;
71 static void s1_freq()
73 s1_freq_d(2048 - (((R_NR14&7)<<8) + R_NR13));
76 static void s2_freq()
78 int d = 2048 - (((R_NR24&7)<<8) + R_NR23);
79 if (RATE > (d<<4)) S2.freq = 0;
80 else S2.freq = (RATE << 17)/d;
83 static void s3_freq()
85 int d = 2048 - (((R_NR34&7)<<8) + R_NR33);
86 if (RATE > (d<<3)) S3.freq = 0;
87 else S3.freq = (RATE << 21)/d;
90 static void s4_freq()
92 S4.freq = (freqtab[R_NR43&7] >> (R_NR43 >> 4)) * RATE;
93 if (S4.freq >> 18) S4.freq = 1<<18;
96 void sound_dirty()
98 S1.swlen = ((R_NR10>>4) & 7) << 14;
99 S1.len = (64-(R_NR11&63)) << 13;
100 S1.envol = R_NR12 >> 4;
101 S1.endir = (R_NR12>>3) & 1;
102 S1.endir |= S1.endir - 1;
103 S1.enlen = (R_NR12 & 7) << 15;
104 s1_freq();
105 S2.len = (64-(R_NR21&63)) << 13;
106 S2.envol = R_NR22 >> 4;
107 S2.endir = (R_NR22>>3) & 1;
108 S2.endir |= S2.endir - 1;
109 S2.enlen = (R_NR22 & 7) << 15;
110 s2_freq();
111 S3.len = (256-R_NR31) << 20;
112 s3_freq();
113 S4.len = (64-(R_NR41&63)) << 13;
114 S4.envol = R_NR42 >> 4;
115 S4.endir = (R_NR42>>3) & 1;
116 S4.endir |= S4.endir - 1;
117 S4.enlen = (R_NR42 & 7) << 15;
118 s4_freq();
121 void sound_off()
123 memset(&S1, 0, sizeof S1);
124 memset(&S2, 0, sizeof S2);
125 memset(&S3, 0, sizeof S3);
126 memset(&S4, 0, sizeof S4);
127 R_NR10 = 0x80;
128 R_NR11 = 0xBF;
129 R_NR12 = 0xF3;
130 R_NR14 = 0xBF;
131 R_NR21 = 0x3F;
132 R_NR22 = 0x00;
133 R_NR24 = 0xBF;
134 R_NR30 = 0x7F;
135 R_NR31 = 0xFF;
136 R_NR32 = 0x9F;
137 R_NR34 = 0xBF;
138 R_NR41 = 0xFF;
139 R_NR42 = 0x00;
140 R_NR43 = 0x00;
141 R_NR44 = 0xBF;
142 R_NR50 = 0x77;
143 R_NR51 = 0xF3;
144 R_NR52 = 0x70;
145 sound_dirty();
148 void sound_reset()
150 memset(&snd, 0, sizeof snd);
151 if (pcm.hz) snd.rate = (1<<21) / pcm.hz;
152 else snd.rate = 0;
153 memcpy(WAVE, hw.cgb ? cgbwave : dmgwave, 16);
154 memcpy(ram.hi+0x30, WAVE, 16);
155 sound_off();
156 R_NR52 = 0xF1;
160 void sound_mix()
162 int s, l, r, f, n;
164 if (!RATE || cpu.snd < RATE) return;
166 for (; cpu.snd >= RATE; cpu.snd -= RATE)
168 l = r = 0;
170 if (S1.on)
172 s = sqwave[R_NR11>>6][(S1.pos>>18)&7] & S1.envol;
173 S1.pos += S1.freq;
174 if ((R_NR14 & 64) && ((S1.cnt += RATE) >= S1.len))
175 S1.on = 0;
176 if (S1.enlen && (S1.encnt += RATE) >= S1.enlen)
178 S1.encnt -= S1.enlen;
179 S1.envol += S1.endir;
180 if (S1.envol < 0) S1.envol = 0;
181 if (S1.envol > 15) S1.envol = 15;
183 if (S1.swlen && (S1.swcnt += RATE) >= S1.swlen)
185 S1.swcnt -= S1.swlen;
186 f = S1.swfreq;
187 n = (R_NR10 & 7);
188 if (R_NR10 & 8) f -= (f >> n);
189 else f += (f >> n);
190 if (f > 2047)
191 S1.on = 0;
192 else
194 S1.swfreq = f;
195 R_NR13 = f;
196 R_NR14 = (R_NR14 & 0xF8) | (f>>8);
197 s1_freq_d(2048 - f);
200 s <<= 2;
201 if (R_NR51 & 1) r += s;
202 if (R_NR51 & 16) l += s;
205 if (S2.on)
207 s = sqwave[R_NR21>>6][(S2.pos>>18)&7] & S2.envol;
208 S2.pos += S2.freq;
209 if ((R_NR24 & 64) && ((S2.cnt += RATE) >= S2.len))
210 S2.on = 0;
211 if (S2.enlen && (S2.encnt += RATE) >= S2.enlen)
213 S2.encnt -= S2.enlen;
214 S2.envol += S2.endir;
215 if (S2.envol < 0) S2.envol = 0;
216 if (S2.envol > 15) S2.envol = 15;
218 s <<= 2;
219 if (R_NR51 & 2) r += s;
220 if (R_NR51 & 32) l += s;
223 if (S3.on)
225 s = WAVE[(S3.pos>>22) & 15];
226 if (S3.pos & (1<<21)) s &= 15;
227 else s >>= 4;
228 s -= 8;
229 S3.pos += S3.freq;
230 if ((R_NR34 & 64) && ((S3.cnt += RATE) >= S3.len))
231 S3.on = 0;
232 if (R_NR32 & 96) s <<= (3 - ((R_NR32>>5)&3));
233 else s = 0;
234 if (R_NR51 & 4) r += s;
235 if (R_NR51 & 64) l += s;
238 if (S4.on)
240 if (R_NR43 & 8) s = 1 & (noise7[
241 (S4.pos>>20)&15] >> (7-((S4.pos>>17)&7)));
242 else s = 1 & (noise15[
243 (S4.pos>>20)&4095] >> (7-((S4.pos>>17)&7)));
244 s = (-s) & S4.envol;
245 S4.pos += S4.freq;
246 if ((R_NR44 & 64) && ((S4.cnt += RATE) >= S4.len))
247 S4.on = 0;
248 if (S4.enlen && (S4.encnt += RATE) >= S4.enlen)
250 S4.encnt -= S4.enlen;
251 S4.envol += S4.endir;
252 if (S4.envol < 0) S4.envol = 0;
253 if (S4.envol > 15) S4.envol = 15;
255 s += s << 1;
256 if (R_NR51 & 8) r += s;
257 if (R_NR51 & 128) l += s;
260 l *= (R_NR50 & 0x07);
261 r *= ((R_NR50 & 0x70)>>4);
262 l >>= 4;
263 r >>= 4;
265 if (l > 127) l = 127;
266 else if (l < -128) l = -128;
267 if (r > 127) r = 127;
268 else if (r < -128) r = -128;
270 if (pcm.buf)
272 if (pcm.pos >= pcm.len)
273 pcm_submit();
274 if (pcm.stereo)
276 pcm.buf[pcm.pos++] = l+128;
277 pcm.buf[pcm.pos++] = r+128;
279 else pcm.buf[pcm.pos++] = ((l+r)>>1)+128;
282 R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3);
287 byte sound_read(byte r)
289 sound_mix();
290 /* printf("read %02X: %02X\n", r, REG(r)); */
291 return REG(r);
294 void s1_init()
296 S1.swcnt = 0;
297 S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
298 S1.envol = R_NR12 >> 4;
299 S1.endir = (R_NR12>>3) & 1;
300 S1.endir |= S1.endir - 1;
301 S1.enlen = (R_NR12 & 7) << 15;
302 if (!S1.on) S1.pos = 0;
303 S1.on = 1;
304 S1.cnt = 0;
305 S1.encnt = 0;
308 void s2_init()
310 S2.envol = R_NR22 >> 4;
311 S2.endir = (R_NR22>>3) & 1;
312 S2.endir |= S2.endir - 1;
313 S2.enlen = (R_NR22 & 7) << 15;
314 if (!S2.on) S2.pos = 0;
315 S2.on = 1;
316 S2.cnt = 0;
317 S2.encnt = 0;
320 void s3_init()
322 int i;
323 if (!S3.on) S3.pos = 0;
324 S3.cnt = 0;
325 S3.on = R_NR30 >> 7;
326 if (S3.on) for (i = 0; i < 16; i++)
327 ram.hi[i+0x30] = 0x13 ^ ram.hi[i+0x31];
330 void s4_init()
332 S4.envol = R_NR42 >> 4;
333 S4.endir = (R_NR42>>3) & 1;
334 S4.endir |= S4.endir - 1;
335 S4.enlen = (R_NR42 & 7) << 15;
336 S4.on = 1;
337 S4.pos = 0;
338 S4.cnt = 0;
339 S4.encnt = 0;
343 void sound_write(byte r, byte b)
345 #if 0
346 static void *timer;
347 if (!timer) timer = sys_timer();
348 printf("write %02X: %02X @ %d\n", r, b, sys_elapsed(timer));
349 #endif
351 if (!(R_NR52 & 128) && r != RI_NR52) return;
352 if ((r & 0xF0) == 0x30)
354 if (S3.on) sound_mix();
355 if (!S3.on)
356 WAVE[r-0x30] = ram.hi[r] = b;
357 return;
359 sound_mix();
360 switch (r)
362 case RI_NR10:
363 R_NR10 = b;
364 S1.swlen = ((R_NR10>>4) & 7) << 14;
365 S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
366 break;
367 case RI_NR11:
368 R_NR11 = b;
369 S1.len = (64-(R_NR11&63)) << 13;
370 break;
371 case RI_NR12:
372 R_NR12 = b;
373 S1.envol = R_NR12 >> 4;
374 S1.endir = (R_NR12>>3) & 1;
375 S1.endir |= S1.endir - 1;
376 S1.enlen = (R_NR12 & 7) << 15;
377 break;
378 case RI_NR13:
379 R_NR13 = b;
380 s1_freq();
381 break;
382 case RI_NR14:
383 R_NR14 = b;
384 s1_freq();
385 if (b & 128) s1_init();
386 break;
387 case RI_NR21:
388 R_NR21 = b;
389 S2.len = (64-(R_NR21&63)) << 13;
390 break;
391 case RI_NR22:
392 R_NR22 = b;
393 S2.envol = R_NR22 >> 4;
394 S2.endir = (R_NR22>>3) & 1;
395 S2.endir |= S2.endir - 1;
396 S2.enlen = (R_NR22 & 7) << 15;
397 break;
398 case RI_NR23:
399 R_NR23 = b;
400 s2_freq();
401 break;
402 case RI_NR24:
403 R_NR24 = b;
404 s2_freq();
405 if (b & 128) s2_init();
406 break;
407 case RI_NR30:
408 R_NR30 = b;
409 if (!(b & 128)) S3.on = 0;
410 break;
411 case RI_NR31:
412 R_NR31 = b;
413 S3.len = (256-R_NR31) << 13;
414 break;
415 case RI_NR32:
416 R_NR32 = b;
417 break;
418 case RI_NR33:
419 R_NR33 = b;
420 s3_freq();
421 break;
422 case RI_NR34:
423 R_NR34 = b;
424 s3_freq();
425 if (b & 128) s3_init();
426 break;
427 case RI_NR41:
428 R_NR41 = b;
429 S4.len = (64-(R_NR41&63)) << 13;
430 break;
431 case RI_NR42:
432 R_NR42 = b;
433 S4.envol = R_NR42 >> 4;
434 S4.endir = (R_NR42>>3) & 1;
435 S4.endir |= S4.endir - 1;
436 S4.enlen = (R_NR42 & 7) << 15;
437 break;
438 case RI_NR43:
439 R_NR43 = b;
440 s4_freq();
441 break;
442 case RI_NR44:
443 R_NR44 = b;
444 if (b & 128) s4_init();
445 break;
446 case RI_NR50:
447 R_NR50 = b;
448 break;
449 case RI_NR51:
450 R_NR51 = b;
451 break;
452 case RI_NR52:
453 R_NR52 = b;
454 if (!(R_NR52 & 128))
455 sound_off();
456 break;
457 default:
458 return;