summaryrefslogtreecommitdiff
path: root/apps/plugins/rockboy/sound.c
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-03-02 23:49:38 +0000
committerJens Arnold <amiconn@rockbox.org>2005-03-02 23:49:38 +0000
commit384de102469fee4e0792df8fe38586d3206774ed (patch)
treeee5342103e17738acfb8421328ea7c57433f55e6 /apps/plugins/rockboy/sound.c
parent48dad47df98bdec632e8930b6a97359dc2c428f5 (diff)
downloadrockbox-384de102469fee4e0792df8fe38586d3206774ed.tar.gz
rockbox-384de102469fee4e0792df8fe38586d3206774ed.zip
Rockboy - gameboy emulation for rockbox, based on gnuboy. Still a bit early, but already playable on iRiver H1xx and the simulators. The archos recorder version is currently rather slow...
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6104 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/rockboy/sound.c')
-rw-r--r--apps/plugins/rockboy/sound.c466
1 files changed, 466 insertions, 0 deletions
diff --git a/apps/plugins/rockboy/sound.c b/apps/plugins/rockboy/sound.c
new file mode 100644
index 0000000000..edf31d81b7
--- /dev/null
+++ b/apps/plugins/rockboy/sound.c
@@ -0,0 +1,466 @@
1
2
3
4#include "rockmacros.h"
5#include "defs.h"
6#include "pcm.h"
7#include "sound.h"
8#include "cpu.h"
9#include "hw.h"
10#include "regs.h"
11#include "rc.h"
12#include "noise.h"
13
14
15static 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
23static 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
32static const byte sqwave[4][8] =
33 {
34 { 0, 0,-1, 0, 0, 0, 0, 0 },
35 { 0,-1,-1, 0, 0, 0, 0, 0 },
36 { -1,-1,-1,-1, 0, 0, 0, 0 },
37 { -1, 0, 0,-1,-1,-1,-1,-1 }
38 };
39
40static const int freqtab[8] =
41 {
42 (1<<14)*2,
43 (1<<14),
44 (1<<14)/2,
45 (1<<14)/3,
46 (1<<14)/4,
47 (1<<14)/5,
48 (1<<14)/6,
49 (1<<14)/7
50 };
51
52struct snd snd;
53int pcm_submit(void);
54
55#define RATE (snd.rate)
56#define WAVE (snd.wave) /* ram.hi+0x30 */
57#define S1 (snd.ch[0])
58#define S2 (snd.ch[1])
59#define S3 (snd.ch[2])
60#define S4 (snd.ch[3])
61
62rcvar_t sound_exports[] =
63 {
64 RCV_END
65 };
66
67
68static void s1_freq_d(int d)
69{
70 if (RATE > (d<<4)) S1.freq = 0;
71 else S1.freq = (RATE << 17)/d;
72}
73
74static void s1_freq(void)
75{
76 s1_freq_d(2048 - (((R_NR14&7)<<8) + R_NR13));
77}
78
79static void s2_freq(void)
80{
81 int d = 2048 - (((R_NR24&7)<<8) + R_NR23);
82 if (RATE > (d<<4)) S2.freq = 0;
83 else S2.freq = (RATE << 17)/d;
84}
85
86static void s3_freq(void)
87{
88 int d = 2048 - (((R_NR34&7)<<8) + R_NR33);
89 if (RATE > (d<<3)) S3.freq = 0;
90 else S3.freq = (RATE << 21)/d;
91}
92
93static void s4_freq(void)
94{
95 S4.freq = (freqtab[R_NR43&7] >> (R_NR43 >> 4)) * RATE;
96 if (S4.freq >> 18) S4.freq = 1<<18;
97}
98
99void sound_dirty(void)
100{
101 S1.swlen = ((R_NR10>>4) & 7) << 14;
102 S1.len = (64-(R_NR11&63)) << 13;
103 S1.envol = R_NR12 >> 4;
104 S1.endir = (R_NR12>>3) & 1;
105 S1.endir |= S1.endir - 1;
106 S1.enlen = (R_NR12 & 7) << 15;
107 s1_freq();
108 S2.len = (64-(R_NR21&63)) << 13;
109 S2.envol = R_NR22 >> 4;
110 S2.endir = (R_NR22>>3) & 1;
111 S2.endir |= S2.endir - 1;
112 S2.enlen = (R_NR22 & 7) << 15;
113 s2_freq();
114 S3.len = (256-R_NR31) << 20;
115 s3_freq();
116 S4.len = (64-(R_NR41&63)) << 13;
117 S4.envol = R_NR42 >> 4;
118 S4.endir = (R_NR42>>3) & 1;
119 S4.endir |= S4.endir - 1;
120 S4.enlen = (R_NR42 & 7) << 15;
121 s4_freq();
122}
123
124void sound_off(void)
125{
126 memset(&S1, 0, sizeof S1);
127 memset(&S2, 0, sizeof S2);
128 memset(&S3, 0, sizeof S3);
129 memset(&S4, 0, sizeof S4);
130 R_NR10 = 0x80;
131 R_NR11 = 0xBF;
132 R_NR12 = 0xF3;
133 R_NR14 = 0xBF;
134 R_NR21 = 0x3F;
135 R_NR22 = 0x00;
136 R_NR24 = 0xBF;
137 R_NR30 = 0x7F;
138 R_NR31 = 0xFF;
139 R_NR32 = 0x9F;
140 R_NR33 = 0xBF;
141 R_NR41 = 0xFF;
142 R_NR42 = 0x00;
143 R_NR43 = 0x00;
144 R_NR44 = 0xBF;
145 R_NR50 = 0x77;
146 R_NR51 = 0xF3;
147 R_NR52 = 0xF1;
148 sound_dirty();
149}
150
151void 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
162void sound_mix(void)
163{
164 int s, l, r, f, n;
165
166 if (!RATE || cpu.snd < RATE) return;
167
168 for (; cpu.snd >= RATE; cpu.snd -= RATE)
169 {
170 l = r = 0;
171
172 if (S1.on)
173 {
174 s = sqwave[R_NR11>>6][(S1.pos>>18)&7] & S1.envol;
175 S1.pos += S1.freq;
176 if ((R_NR14 & 64) && ((S1.cnt += RATE) >= S1.len))
177 S1.on = 0;
178 if (S1.enlen && (S1.encnt += RATE) >= S1.enlen)
179 {
180 S1.encnt -= S1.enlen;
181 S1.envol += S1.endir;
182 if (S1.envol < 0) S1.envol = 0;
183 if (S1.envol > 15) S1.envol = 15;
184 }
185 if (S1.swlen && (S1.swcnt += RATE) >= S1.swlen)
186 {
187 S1.swcnt -= S1.swlen;
188 f = S1.swfreq;
189 n = (R_NR10 & 7);
190 if (R_NR10 & 8) f -= (f >> n);
191 else f += (f >> n);
192 if (f > 2047)
193 S1.on = 0;
194 else
195 {
196 S1.swfreq = f;
197 R_NR13 = f;
198 R_NR14 = (R_NR14 & 0xF8) | (f>>8);
199 s1_freq_d(2048 - f);
200 }
201 }
202 s <<= 2;
203 if (R_NR51 & 1) r += s;
204 if (R_NR51 & 16) l += s;
205 }
206
207 if (S2.on)
208 {
209 s = sqwave[R_NR21>>6][(S2.pos>>18)&7] & S2.envol;
210 S2.pos += S2.freq;
211 if ((R_NR24 & 64) && ((S2.cnt += RATE) >= S2.len))
212 S2.on = 0;
213 if (S2.enlen && (S2.encnt += RATE) >= S2.enlen)
214 {
215 S2.encnt -= S2.enlen;
216 S2.envol += S2.endir;
217 if (S2.envol < 0) S2.envol = 0;
218 if (S2.envol > 15) S2.envol = 15;
219 }
220 s <<= 2;
221 if (R_NR51 & 2) r += s;
222 if (R_NR51 & 32) l += s;
223 }
224
225 if (S3.on)
226 {
227 s = WAVE[(S3.pos>>22) & 15];
228 if (S3.pos & (1<<21)) s &= 15;
229 else s >>= 4;
230 s -= 8;
231 S3.pos += S3.freq;
232 if ((R_NR34 & 64) && ((S3.cnt += RATE) >= S3.len))
233 S3.on = 0;
234 if (R_NR32 & 96) s <<= (3 - ((R_NR32>>5)&3));
235 else s = 0;
236 if (R_NR51 & 4) r += s;
237 if (R_NR51 & 64) l += s;
238 }
239
240 if (S4.on)
241 {
242 if (R_NR43 & 8) s = 1 & (noise7[
243 (S4.pos>>20)&15] >> (7-((S4.pos>>17)&7)));
244 else s = 1 & (noise15[
245 (S4.pos>>20)&4095] >> (7-((S4.pos>>17)&7)));
246 s = (-s) & S4.envol;
247 S4.pos += S4.freq;
248 if ((R_NR44 & 64) && ((S4.cnt += RATE) >= S4.len))
249 S4.on = 0;
250 if (S4.enlen && (S4.encnt += RATE) >= S4.enlen)
251 {
252 S4.encnt -= S4.enlen;
253 S4.envol += S4.endir;
254 if (S4.envol < 0) S4.envol = 0;
255 if (S4.envol > 15) S4.envol = 15;
256 }
257 s += s << 1;
258 if (R_NR51 & 8) r += s;
259 if (R_NR51 & 128) l += s;
260 }
261
262 l *= (R_NR50 & 0x07);
263 r *= ((R_NR50 & 0x70)>>4);
264 l >>= 4;
265 r >>= 4;
266
267 if (l > 127) l = 127;
268 else if (l < -128) l = -128;
269 if (r > 127) r = 127;
270 else if (r < -128) r = -128;
271
272 if (pcm.buf)
273 {
274 if (pcm.pos >= pcm.len)
275 pcm_submit();
276 if (pcm.stereo)
277 {
278 pcm.buf[pcm.pos++] = l+128;
279 pcm.buf[pcm.pos++] = r+128;
280 }
281 else pcm.buf[pcm.pos++] = ((l+r)>>1)+128;
282 }
283 }
284 R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3);
285}
286
287
288
289byte sound_read(byte r)
290{
291 sound_mix();
292 /* printf("read %02X: %02X\n", r, REG(r)); */
293 return REG(r);
294}
295
296void s1_init(void)
297{
298 S1.swcnt = 0;
299 S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
300 S1.envol = R_NR12 >> 4;
301 S1.endir = (R_NR12>>3) & 1;
302 S1.endir |= S1.endir - 1;
303 S1.enlen = (R_NR12 & 7) << 15;
304 if (!S1.on) S1.pos = 0;
305 S1.on = 1;
306 S1.cnt = 0;
307 S1.encnt = 0;
308}
309
310void s2_init(void)
311{
312 S2.envol = R_NR22 >> 4;
313 S2.endir = (R_NR22>>3) & 1;
314 S2.endir |= S2.endir - 1;
315 S2.enlen = (R_NR22 & 7) << 15;
316 if (!S2.on) S2.pos = 0;
317 S2.on = 1;
318 S2.cnt = 0;
319 S2.encnt = 0;
320}
321
322void s3_init(void)
323{
324 int i;
325 if (!S3.on) S3.pos = 0;
326 S3.cnt = 0;
327 S3.on = R_NR30 >> 7;
328 if (S3.on) for (i = 0; i < 16; i++)
329 ram.hi[i+0x30] = 0x13 ^ ram.hi[i+0x31];
330}
331
332void s4_init(void)
333{
334 S4.envol = R_NR42 >> 4;
335 S4.endir = (R_NR42>>3) & 1;
336 S4.endir |= S4.endir - 1;
337 S4.enlen = (R_NR42 & 7) << 15;
338 S4.on = 1;
339 S4.pos = 0;
340 S4.cnt = 0;
341 S4.encnt = 0;
342}
343
344
345void sound_write(byte r, byte b)
346{
347#if 0
348 static void *timer;
349 if (!timer) timer = sys_timer();
350 printf("write %02X: %02X @ %d\n", r, b, sys_elapsed(timer));
351#endif
352
353 if (!(R_NR52 & 128) && r != RI_NR52) return;
354 if ((r & 0xF0) == 0x30)
355 {
356 if (S3.on) sound_mix();
357 if (!S3.on)
358 WAVE[r-0x30] = ram.hi[r] = b;
359 return;
360 }
361 sound_mix();
362 switch (r)
363 {
364 case RI_NR10:
365 R_NR10 = b;
366 S1.swlen = ((R_NR10>>4) & 7) << 14;
367 S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
368 break;
369 case RI_NR11:
370 R_NR11 = b;
371 S1.len = (64-(R_NR11&63)) << 13;
372 break;
373 case RI_NR12:
374 R_NR12 = b;
375 S1.envol = R_NR12 >> 4;
376 S1.endir = (R_NR12>>3) & 1;
377 S1.endir |= S1.endir - 1;
378 S1.enlen = (R_NR12 & 7) << 15;
379 break;
380 case RI_NR13:
381 R_NR13 = b;
382 s1_freq();
383 break;
384 case RI_NR14:
385 R_NR14 = b;
386 s1_freq();
387 if (b & 128) s1_init();
388 break;
389 case RI_NR21:
390 R_NR21 = b;
391 S2.len = (64-(R_NR21&63)) << 13;
392 break;
393 case RI_NR22:
394 R_NR22 = b;
395 S2.envol = R_NR22 >> 4;
396 S2.endir = (R_NR22>>3) & 1;
397 S2.endir |= S2.endir - 1;
398 S2.enlen = (R_NR22 & 7) << 15;
399 break;
400 case RI_NR23:
401 R_NR23 = b;
402 s2_freq();
403 break;
404 case RI_NR24:
405 R_NR24 = b;
406 s2_freq();
407 if (b & 128) s2_init();
408 break;
409 case RI_NR30:
410 R_NR30 = b;
411 if (!(b & 128)) S3.on = 0;
412 break;
413 case RI_NR31:
414 R_NR31 = b;
415 S3.len = (256-R_NR31) << 13;
416 break;
417 case RI_NR32:
418 R_NR32 = b;
419 break;
420 case RI_NR33:
421 R_NR33 = b;
422 s3_freq();
423 break;
424 case RI_NR34:
425 R_NR34 = b;
426 s3_freq();
427 if (b & 128) s3_init();
428 break;
429 case RI_NR41:
430 R_NR41 = b;
431 S4.len = (64-(R_NR41&63)) << 13;
432 break;
433 case RI_NR42:
434 R_NR42 = b;
435 S4.envol = R_NR42 >> 4;
436 S4.endir = (R_NR42>>3) & 1;
437 S4.endir |= S4.endir - 1;
438 S4.enlen = (R_NR42 & 7) << 15;
439 break;
440 case RI_NR43:
441 R_NR43 = b;
442 s4_freq();
443 break;
444 case RI_NR44:
445 R_NR44 = b;
446 if (b & 128) s4_init();
447 break;
448 case RI_NR50:
449 R_NR50 = b;
450 break;
451 case RI_NR51:
452 R_NR51 = b;
453 break;
454 case RI_NR52:
455 R_NR52 = b;
456 if (!(R_NR52 & 128))
457 sound_off();
458 break;
459 default:
460 return;
461 }
462}
463
464
465
466