1 /*
2 * gbsplay is a Gameboy sound player
3 *
4 * 2003-2006,2008,2018 (C) by Tobias Diedrich <ranma+gbsplay@tdiedrich.de>
5 * Christian Garbs <mitch@cgarbs.de>
6 * Licensed under GNU GPL v1 or, at your option, any later version.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <limits.h>
14 #include <assert.h>
15 #include <math.h>
16
17 #include "gbcpu.h"
18 #include "gbhw.h"
19 #include "impulse.h"
20
21 #define REG_TIMA 0x05
22 #define REG_TMA 0x06
23 #define REG_TAC 0x07
24 #define REG_IF 0x0f
25 #define REG_IE 0x7f /* Nominally 0xff, but we remap it to 0x7f internally. */
26
27 static uint8_t *rom;
28 static uint8_t intram[0x2000];
29 static uint8_t extram[0x2000];
30 static uint8_t ioregs[0x80];
31 static uint8_t hiram[0x80];
32 static long rombank = 1;
33 static long lastbank;
34 static long apu_on = 1;
35 static long io_written = 0;
36
37 static const uint8_t ioregs_ormask[sizeof(ioregs)] = {
38 /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 /* 0x10 */ 0x80, 0x3f, 0x00, 0xff, 0xbf,
40 /* 0x15 */ 0xff, 0x3f, 0x00, 0xff, 0xbf,
41 /* 0x1a */ 0x7f, 0xff, 0x9f, 0xff, 0xbf,
42 /* 0x1f */ 0xff, 0xff, 0x00, 0x00, 0xbf,
43 /* 0x24 */ 0x00, 0x00, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
44 };
45 static const uint8_t ioregs_initdata[sizeof(ioregs)] = {
46 /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 /* sound registers */
48 /* 0x10 */ 0x80, 0xbf, 0x00, 0x00, 0xbf,
49 /* 0x15 */ 0x00, 0x3f, 0x00, 0x00, 0xbf,
50 /* 0x1a */ 0x7f, 0xff, 0x9f, 0x00, 0xbf,
51 /* 0x1f */ 0x00, 0xff, 0x00, 0x00, 0xbf,
52 /* 0x24 */ 0x77, 0xf3, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 /* wave pattern memory, taken from gbsound.txt v0.99.19 (12/31/2002) */
54 /* 0x30 */ 0xac, 0xdd, 0xda, 0x48, 0x36, 0x02, 0xcf, 0x16, 0x2c, 0x04, 0xe5, 0x2c, 0xac, 0xdd, 0xda, 0x48,
55 };
56
57 static uint8_t boot_rom[256];
58
59 static const char dutylookup[4] = {
60 1, 2, 4, 6
61 };
62 static const long len_mask[4] = {
63 0x3f, 0x3f, 0xff, 0x3f
64 };
65
66 struct gbhw_channel gbhw_ch[4];
67
68 static long lminval, lmaxval, rminval, rmaxval;
69 static double filter_constant = GBHW_FILTER_CONST_DMG;
70 static int filter_enabled = 1;
71 static long cap_factor = 0x10000;
72
73 #define MASTER_VOL_MIN 0
74 #define MASTER_VOL_MAX (256*256)
75 static long master_volume;
76 static long master_fade;
77 static long master_dstvol;
78 static long sample_rate;
79 static long update_level = 0;
80 static long sequence_ctr = 0;
81 static long halted_noirq_cycles = 0;
82
83 static const long vblanktc = 70224; /* ~59.73 Hz (vblankctr)*/
84 static const long vblankclocks = 4560;
85 static long vblankctr;
86 static long timertc = 16;
87 static long timerctr;
88
89 static const long msec_cycles = GBHW_CLOCK/1000;
90
91 static long sum_cycles;
92
93 static long pause_output = 0;
94 static long rom_lockout = 1;
95
96 static gbhw_callback_fn callback;
97 static /*@null@*/ /*@dependent@*/ void *callbackpriv;
98 static /*@null@*/ /*@dependent@*/ struct gbhw_buffer *soundbuf = NULL; /* externally visible output buffer */
99 static /*@null@*/ /*@only@*/ struct gbhw_buffer *impbuf = NULL; /* internal impulse output buffer */
100
101 static gbhw_iocallback_fn iocallback;
102 static /*@null@*/ /*@dependent@*/ void *iocallback_priv;
103
104 static gbhw_stepcallback_fn stepcallback;
105 static /*@null@*/ /*@dependent@*/ void *stepcallback_priv;
106
107 #define TAP1_15 0x4000;
108 #define TAP2_15 0x2000;
109 #define TAP1_7 0x0040;
110 #define TAP2_7 0x0020;
111
112 static uint32_t tap1 = TAP1_15;
113 static uint32_t tap2 = TAP2_15;
114 static uint32_t lfsr = 0xffffffff;
115
116 #define SOUND_DIV_MULT 0x10000LL
117
118 static long long sound_div_tc = 0;
119 static const long main_div_tc = 32;
120 static long main_div;
121 static const long sweep_div_tc = 256;
122 static long sweep_div;
123
124 static long ch3pos;
125 static long last_l_value = 0, last_r_value = 0;
126 static long ch3_next_nibble = 0;
127
128 #define IMPULSE_WIDTH (1 << IMPULSE_W_SHIFT)
129 #define IMPULSE_N (1 << IMPULSE_N_SHIFT)
130 #define IMPULSE_N_MASK (IMPULSE_N - 1)
131
rom_get(uint32_t addr)132 static regparm uint32_t rom_get(uint32_t addr)
133 {
134 if ((addr >> 8) == 0 && rom_lockout == 0) {
135 return boot_rom[addr & 0xff];
136 }
137 // DPRINTF("rom_get(%04x)\n", addr);
138 return rom[addr & 0x3fff];
139 }
140
rombank_get(uint32_t addr)141 static regparm uint32_t rombank_get(uint32_t addr)
142 {
143 // DPRINTF("rombank_get(%04x)\n", addr);
144 return rom[(addr & 0x3fff) + 0x4000*rombank];
145 }
146
io_get(uint32_t addr)147 static regparm uint32_t io_get(uint32_t addr)
148 {
149 if (addr >= 0xff80 && addr <= 0xfffe) {
150 return hiram[addr & 0x7f];
151 }
152 if (addr >= 0xff10 &&
153 addr <= 0xff3f) {
154 uint8_t val = ioregs[addr & 0x7f];
155 if (addr == 0xff26) {
156 long i;
157 val &= 0xf0;
158 for (i=0; i<4; i++) {
159 if (gbhw_ch[i].running) {
160 val |= (1 << i);
161 }
162 }
163 }
164 val |= ioregs_ormask[addr & 0x7f];
165 DPRINTF("io_get(%04x): %02x\n", addr, val);
166 return val;
167 }
168 switch (addr) {
169 case 0xff00: // P1
170 return 0;
171 case 0xff05: // TIMA
172 case 0xff06: // TMA
173 case 0xff07: // TAC
174 case 0xff0f: // IF
175 return ioregs[addr & 0x7f];
176 case 0xff41: /* LCDC Status */
177 if (vblankctr > vblanktc - vblankclocks) {
178 return 0x01; /* vblank */
179 } else {
180 /* ~108.7uS per line */
181 long t = (2 * vblanktc - vblankctr) % 456;
182 if (t < 204) {
183 /* 48.6uS in hblank (201-207 clks) */
184 return 0x00;
185 } else if (t < 284) {
186 /* 19uS in OAM scan (77-83 clks) */
187 return 0x02;
188 }
189 }
190 return 0x03; /* both OAM and display RAM busy */
191 case 0xff44: /* LCD Y-coordinate */
192 return ((2 * vblanktc - vblankclocks - vblankctr) / 456) % 154;
193 case 0xff70: // CGB ram bank switch
194 WARN_ONCE("ioread from SVBK (CGB mode) ignored.\n");
195 return 0xff;
196 case 0xffff:
197 return ioregs[0x7f];
198 default:
199 WARN_ONCE("ioread from 0x%04x unimplemented.\n", (unsigned int)addr);
200 DPRINTF("io_get(%04x)\n", addr);
201 return 0xff;
202 }
203 }
204
intram_get(uint32_t addr)205 static regparm uint32_t intram_get(uint32_t addr)
206 {
207 // DPRINTF("intram_get(%04x)\n", addr);
208 return intram[addr & 0x1fff];
209 }
210
extram_get(uint32_t addr)211 static regparm uint32_t extram_get(uint32_t addr)
212 {
213 // DPRINTF("extram_get(%04x)\n", addr);
214 return extram[addr & 0x1fff];
215 }
216
rom_put(uint32_t addr,uint8_t val)217 static regparm void rom_put(uint32_t addr, uint8_t val)
218 {
219 if (addr >= 0x2000 && addr <= 0x3fff) {
220 val &= 0x1f;
221 rombank = val + (val == 0);
222 if (rombank > lastbank) {
223 WARN_ONCE("Bank %ld out of range (0-%ld)!\n", rombank, lastbank);
224 rombank = lastbank;
225 }
226 } else {
227 WARN_ONCE("rom write of %02x to %04x ignored\n", val, addr);
228 }
229 }
230
apu_reset(void)231 static regparm void apu_reset(void)
232 {
233 long i;
234 int mute_tmp[4];
235
236 for (i = 0; i < 4; i++) {
237 mute_tmp[i] = gbhw_ch[i].mute;
238 }
239 memset(gbhw_ch, 0, sizeof(gbhw_ch));
240 for (i = 0xff10; i < 0xff26; i++) {
241 ioregs[i & 0x7f] = 0;
242 }
243 for (i = 0; i < 4; i++) {
244 gbhw_ch[i].len = 0;
245 gbhw_ch[i].len_gate = 0;
246 gbhw_ch[i].volume = 0;
247 gbhw_ch[i].duty_ctr = 4;
248 gbhw_ch[i].div_tc = 1;
249 gbhw_ch[i].master = 1;
250 gbhw_ch[i].running = 0;
251 gbhw_ch[i].mute = mute_tmp[i];
252 }
253 sequence_ctr = 0;
254 }
255
256 static void linkport_atexit(void);
257
linkport_write(long c)258 static regparm void linkport_write(long c)
259 {
260 static char buf[256];
261 static long idx = 0;
262 static long exit_handler_set = 0;
263 static long enabled = 1;
264
265 if (!enabled) {
266 return;
267 }
268 if (!(c == -1 || c == '\r' || c == '\n' || (c >= 0x20 && c <= 0x7f))) {
269 enabled = 0;
270 fprintf(stderr, "Link port output %02lx ignored.\n", c);
271 return;
272 }
273 if (c != -1 && idx < (sizeof(buf) - 1)) {
274 buf[idx++] = c;
275 buf[idx] = 0;
276 }
277 if (c == '\n' || (c == -1 && idx > 0)) {
278 fprintf(stderr, "Link port text: %s", buf);
279 idx = 0;
280 if (!exit_handler_set) {
281 atexit(linkport_atexit);
282 }
283 }
284 }
285
linkport_atexit(void)286 static void linkport_atexit(void)
287 {
288 linkport_write(-1);
289 }
290
sequencer_update_len(long chn)291 static regparm void sequencer_update_len(long chn)
292 {
293 if (gbhw_ch[chn].len_enable && gbhw_ch[chn].len_gate) {
294 gbhw_ch[chn].len++;
295 gbhw_ch[chn].len &= len_mask[chn];
296 if (gbhw_ch[chn].len == 0) {
297 gbhw_ch[chn].volume = 0;
298 gbhw_ch[chn].env_tc = 0;
299 gbhw_ch[chn].running = 0;
300 gbhw_ch[chn].len_gate = 0;
301 }
302 }
303 }
304
sweep_check_overflow(void)305 static regparm long sweep_check_overflow(void)
306 {
307 long val = (2048 - gbhw_ch[0].div_tc_shadow) >> gbhw_ch[0].sweep_shift;
308
309 if (gbhw_ch[0].sweep_shift == 0) {
310 return 1;
311 }
312
313 if (!gbhw_ch[0].sweep_dir) {
314 if (gbhw_ch[0].div_tc_shadow <= val) {
315 gbhw_ch[0].running = 0;
316 return 0;
317 }
318 }
319 return 1;
320 }
321
io_put(uint32_t addr,uint8_t val)322 static regparm void io_put(uint32_t addr, uint8_t val)
323 {
324 long chn = (addr - 0xff10)/5;
325
326 if (addr >= 0xff80 && addr <= 0xfffe) {
327 hiram[addr & 0x7f] = val;
328 return;
329 }
330
331 io_written = 1;
332
333 if (iocallback)
334 iocallback(sum_cycles, addr, val, iocallback_priv);
335
336 if (apu_on == 0 && addr >= 0xff10 && addr < 0xff26) {
337 return;
338 }
339 ioregs[addr & 0x7f] = val;
340 DPRINTF(" ([0x%04x]=%02x) ", addr, val);
341 switch (addr) {
342 case 0xff02:
343 if (val & 0x80) {
344 linkport_write(ioregs[1]);
345 }
346 break;
347 case 0xff05: // TIMA
348 case 0xff06: // TMA
349 break;
350 case 0xff07: // TAC
351 timertc = 16 << (((val+3) & 3) << 1);
352 if ((val & 0xf0) == 0x80) timertc /= 2;
353 if (timerctr > timertc) {
354 timerctr = 0;
355 }
356 break;
357 case 0xff0f: // IF
358 break;
359 case 0xff10:
360 gbhw_ch[0].sweep_ctr = gbhw_ch[0].sweep_tc = ((val >> 4) & 7);
361 gbhw_ch[0].sweep_dir = (val >> 3) & 1;
362 gbhw_ch[0].sweep_shift = val & 7;
363
364 break;
365 case 0xff11:
366 case 0xff16:
367 case 0xff20:
368 {
369 long duty_ctr = val >> 6;
370 long len = val & 0x3f;
371
372 gbhw_ch[chn].duty_ctr = dutylookup[duty_ctr];
373 gbhw_ch[chn].duty_tc = gbhw_ch[chn].div_tc*gbhw_ch[chn].duty_ctr/8;
374 gbhw_ch[chn].len = len;
375 gbhw_ch[chn].len_gate = 1;
376
377 break;
378 }
379 case 0xff12:
380 case 0xff17:
381 case 0xff21:
382 {
383 long vol = val >> 4;
384 long envdir = (val >> 3) & 1;
385 long envspd = val & 7;
386
387 gbhw_ch[chn].volume = vol;
388 gbhw_ch[chn].env_dir = envdir;
389 gbhw_ch[chn].env_ctr = gbhw_ch[chn].env_tc = envspd;
390
391 gbhw_ch[chn].master = (val & 0xf8) != 0;
392 if (!gbhw_ch[chn].master) {
393 gbhw_ch[chn].running = 0;
394 }
395 }
396 break;
397 case 0xff13:
398 case 0xff14:
399 case 0xff18:
400 case 0xff19:
401 case 0xff1d:
402 case 0xff1e:
403 {
404 long div = ioregs[0x13 + 5*chn];
405 long old_len_enable = gbhw_ch[chn].len_enable;
406
407 div |= ((long)ioregs[0x14 + 5*chn] & 7) << 8;
408 gbhw_ch[chn].div_tc = 2048 - div;
409 gbhw_ch[chn].duty_tc = gbhw_ch[chn].div_tc*gbhw_ch[chn].duty_ctr/8;
410
411 if (addr == 0xff13 ||
412 addr == 0xff18 ||
413 addr == 0xff1d) break;
414
415 gbhw_ch[chn].len_enable = (ioregs[0x14 + 5*chn] & 0x40) > 0;
416 if ((val & 0x80) == 0x80) {
417 if (!gbhw_ch[chn].len_gate) {
418 gbhw_ch[chn].len_gate = 1;
419 if (old_len_enable == 1 &&
420 gbhw_ch[chn].len_enable == 1 &&
421 (sequence_ctr & 1) == 1) {
422 // Trigger that un-freezes enabled length should clock it
423 sequencer_update_len(chn);
424 }
425 }
426 if (gbhw_ch[chn].master) {
427 gbhw_ch[chn].running = 1;
428 }
429 if (addr == 0xff1e) {
430 ch3pos = 0;
431 }
432 if (addr == 0xff14) {
433 gbhw_ch[0].div_tc_shadow = gbhw_ch[0].div_tc;
434 sweep_check_overflow();
435 }
436 }
437 if (old_len_enable == 0 &&
438 gbhw_ch[chn].len_enable == 1 &&
439 (sequence_ctr & 1) == 1) {
440 // Enabling in first half of length period should clock length
441 sequencer_update_len(chn);
442 }
443 }
444
445 // printf(" ch%ld: vol=%02d envd=%ld envspd=%ld duty_ctr=%ld len=%03d len_en=%ld key=%04d gate=%ld%ld\n", chn, gbhw_ch[chn].volume, gbhw_ch[chn].env_dir, gbhw_ch[chn].env_tc, gbhw_ch[chn].duty_ctr, gbhw_ch[chn].len, gbhw_ch[chn].len_enable, gbhw_ch[chn].div_tc, gbhw_ch[chn].leftgate, gbhw_ch[chn].rightgate);
446 break;
447 case 0xff15:
448 break;
449 case 0xff1a:
450 gbhw_ch[2].master = (ioregs[0x1a] & 0x80) > 0;
451 if (!gbhw_ch[2].master) {
452 gbhw_ch[2].running = 0;
453 }
454 break;
455 case 0xff1b:
456 gbhw_ch[2].len = val;
457 gbhw_ch[2].len_gate = 1;
458 break;
459 case 0xff1c:
460 {
461 long vol = (ioregs[0x1c] >> 5) & 3;
462 gbhw_ch[2].volume = vol;
463 break;
464 }
465 case 0xff1f:
466 break;
467 case 0xff22:
468 case 0xff23:
469 {
470 long reg = ioregs[0x22];
471 long shift = reg >> 4;
472 long rate = reg & 7;
473 long old_len_enable = gbhw_ch[chn].len_enable;
474 gbhw_ch[3].div_ctr = 0;
475 gbhw_ch[3].div_tc = 16 << shift;
476 if (reg & 8) {
477 tap1 = TAP1_7;
478 tap2 = TAP2_7;
479 } else {
480 tap1 = TAP1_15;
481 tap2 = TAP2_15;
482 }
483 if (rate) gbhw_ch[3].div_tc *= rate;
484 else gbhw_ch[3].div_tc /= 2;
485 gbhw_ch[chn].len_enable = (ioregs[0x23] & 0x40) > 0;
486 if (addr == 0xff22) break;
487
488 if (val & 0x80) { /* trigger */
489 lfsr = 0xffffffff;
490 if (!gbhw_ch[chn].len_gate) {
491 gbhw_ch[chn].len_gate = 1;
492 if (old_len_enable == 1 &&
493 gbhw_ch[chn].len_enable == 1 &&
494 (sequence_ctr & 1) == 1) {
495 // Trigger that un-freezes enabled length should clock it
496 sequencer_update_len(chn);
497 }
498 }
499 if (gbhw_ch[3].master) {
500 gbhw_ch[3].running = 1;
501 }
502 }
503 if (old_len_enable == 0 &&
504 gbhw_ch[chn].len_enable == 1 &&
505 (sequence_ctr & 1) == 1) {
506 // Enabling in first half of length period should clock length
507 sequencer_update_len(chn);
508 }
509 // printf(" ch4: vol=%02d envd=%ld envspd=%ld duty_ctr=%ld len=%03d len_en=%ld key=%04d gate=%ld%ld\n", gbhw_ch[3].volume, gbhw_ch[3].env_dir, gbhw_ch[3].env_ctr, gbhw_ch[3].duty_ctr, gbhw_ch[3].len, gbhw_ch[3].len_enable, gbhw_ch[3].div_tc, gbhw_ch[3].leftgate, gbhw_ch[3].rightgate);
510 }
511 break;
512 case 0xff25:
513 gbhw_ch[0].leftgate = (val & 0x10) > 0;
514 gbhw_ch[0].rightgate = (val & 0x01) > 0;
515 gbhw_ch[1].leftgate = (val & 0x20) > 0;
516 gbhw_ch[1].rightgate = (val & 0x02) > 0;
517 gbhw_ch[2].leftgate = (val & 0x40) > 0;
518 gbhw_ch[2].rightgate = (val & 0x04) > 0;
519 gbhw_ch[3].leftgate = (val & 0x80) > 0;
520 gbhw_ch[3].rightgate = (val & 0x08) > 0;
521 update_level = 1;
522 break;
523 case 0xff26:
524 if (val & 0x80) {
525 ioregs[0x26] = 0x80;
526 apu_on = 1;
527 } else {
528 apu_reset();
529 apu_on = 0;
530 }
531 break;
532 case 0xff70:
533 WARN_ONCE("iowrite to SVBK (CGB mode) ignored.\n");
534 break;
535 case 0xff00:
536 case 0xff24:
537 case 0xff27:
538 case 0xff28:
539 case 0xff29:
540 case 0xff2a:
541 case 0xff2b:
542 case 0xff2c:
543 case 0xff2d:
544 case 0xff2e:
545 case 0xff2f:
546 case 0xff30:
547 case 0xff31:
548 case 0xff32:
549 case 0xff33:
550 case 0xff34:
551 case 0xff35:
552 case 0xff36:
553 case 0xff37:
554 case 0xff38:
555 case 0xff39:
556 case 0xff3a:
557 case 0xff3b:
558 case 0xff3c:
559 case 0xff3d:
560 case 0xff3e:
561 case 0xff3f:
562 case 0xff50: /* bootrom lockout reg */
563 if (val == 0x01) {
564 rom_lockout = 1;
565 }
566 break;
567 case 0xffff:
568 break;
569 default:
570 WARN_ONCE("iowrite to 0x%04x unimplemented (val=%02x).\n", addr, val);
571 break;
572 }
573 }
574
intram_put(uint32_t addr,uint8_t val)575 static regparm void intram_put(uint32_t addr, uint8_t val)
576 {
577 intram[addr & 0x1fff] = val;
578 }
579
extram_put(uint32_t addr,uint8_t val)580 static regparm void extram_put(uint32_t addr, uint8_t val)
581 {
582 extram[addr & 0x1fff] = val;
583 }
584
sequencer_step(void)585 static regparm void sequencer_step(void)
586 {
587 long i;
588 long clock_len = 0;
589 long clock_env = 0;
590 long clock_sweep = 0;
591
592 switch (sequence_ctr & 7) {
593 case 0: clock_len = 1; break;
594 case 1: break;
595 case 2: clock_len = 1; clock_sweep = 1; break;
596 case 3: break;
597 case 4: clock_len = 1; break;
598 case 5: break;
599 case 6: clock_len = 1; clock_sweep = 1; break;
600 case 7: clock_env = 1; break;
601 }
602
603 sequence_ctr++;
604
605 if (clock_sweep && gbhw_ch[0].sweep_tc) {
606 gbhw_ch[0].sweep_ctr--;
607 if (gbhw_ch[0].sweep_ctr < 0) {
608 long val = (2048 - gbhw_ch[0].div_tc_shadow) >> gbhw_ch[0].sweep_shift;
609
610 gbhw_ch[0].sweep_ctr = gbhw_ch[0].sweep_tc;
611 if (sweep_check_overflow()) {
612 if (gbhw_ch[0].sweep_dir) {
613 gbhw_ch[0].div_tc_shadow += val;
614 } else {
615 gbhw_ch[0].div_tc_shadow -= val;
616 }
617 gbhw_ch[0].div_tc = gbhw_ch[0].div_tc_shadow;
618 }
619 gbhw_ch[0].duty_tc = gbhw_ch[0].div_tc*gbhw_ch[0].duty_ctr/8;
620 }
621 }
622 for (i=0; clock_len && i<4; i++) {
623 sequencer_update_len(i);
624 }
625 for (i=0; clock_env && i<4; i++) {
626 if (gbhw_ch[i].env_tc) {
627 gbhw_ch[i].env_ctr--;
628 if (gbhw_ch[i].env_ctr <=0 ) {
629 gbhw_ch[i].env_ctr = gbhw_ch[i].env_tc;
630 if (gbhw_ch[i].running) {
631 if (!gbhw_ch[i].env_dir) {
632 if (gbhw_ch[i].volume > 0)
633 gbhw_ch[i].volume--;
634 } else {
635 if (gbhw_ch[i].volume < 15)
636 gbhw_ch[i].volume++;
637 }
638 }
639 }
640 }
641 }
642 if (master_fade) {
643 master_volume += master_fade;
644 if ((master_fade > 0 &&
645 master_volume >= master_dstvol) ||
646 (master_fade < 0 &&
647 master_volume <= master_dstvol)) {
648 master_fade = 0;
649 master_volume = master_dstvol;
650 }
651 }
652 }
653
gbhw_master_fade(long speed,long dstvol)654 regparm void gbhw_master_fade(long speed, long dstvol)
655 {
656 if (dstvol < MASTER_VOL_MIN) dstvol = MASTER_VOL_MIN;
657 if (dstvol > MASTER_VOL_MAX) dstvol = MASTER_VOL_MAX;
658 master_dstvol = dstvol;
659 if (dstvol > master_volume)
660 master_fade = speed;
661 else master_fade = -speed;
662 }
663
664 #define GET_NIBBLE(p, n) ({ \
665 long index = ((n) >> 1) & 0xf; \
666 long shift = (~(n) & 1) << 2; \
667 (((p)[index] >> shift) & 0xf); })
668
gb_flush_buffer(void)669 static regparm void gb_flush_buffer(void)
670 {
671 long i;
672 long overlap;
673 long l_smpl, r_smpl;
674 long l_cap, r_cap;
675
676 assert(soundbuf != NULL);
677 assert(impbuf != NULL);
678
679 /* integrate buffer */
680 l_smpl = soundbuf->l_lvl;
681 r_smpl = soundbuf->r_lvl;
682 l_cap = soundbuf->l_cap;
683 r_cap = soundbuf->r_cap;
684 for (i=0; i<soundbuf->samples; i++) {
685 long l_out, r_out;
686 l_smpl = l_smpl + impbuf->data[i*2 ];
687 r_smpl = r_smpl + impbuf->data[i*2+1];
688 if (filter_enabled && cap_factor <= 0x10000) {
689 /*
690 * RC High-pass & DC decoupling filter. Gameboy
691 * Classic uses 1uF and 510 Ohms in series,
692 * followed by 10K Ohms pot to ground between
693 * CPU output and amplifier input, which gives a
694 * cutoff frequency of 15.14Hz.
695 */
696 l_out = l_smpl - (l_cap >> 16);
697 r_out = r_smpl - (r_cap >> 16);
698 /* cap factor is 0x10000 for a factor of 1.0 */
699 l_cap = (l_smpl << 16) - l_out * cap_factor;
700 r_cap = (r_smpl << 16) - r_out * cap_factor;
701 } else {
702 l_out = l_smpl;
703 r_out = r_smpl;
704 }
705 soundbuf->data[i*2 ] = l_out * master_volume / MASTER_VOL_MAX;
706 soundbuf->data[i*2+1] = r_out * master_volume / MASTER_VOL_MAX;
707 if (l_out > lmaxval) lmaxval = l_out;
708 if (l_out < lminval) lminval = l_out;
709 if (r_out > rmaxval) rmaxval = r_out;
710 if (r_out < rminval) rminval = r_out;
711 }
712 soundbuf->pos = soundbuf->samples;
713 soundbuf->l_lvl = l_smpl;
714 soundbuf->r_lvl = r_smpl;
715 soundbuf->l_cap = l_cap;
716 soundbuf->r_cap = r_cap;
717
718 if (callback != NULL) callback(soundbuf, callbackpriv);
719
720 overlap = impbuf->samples - soundbuf->samples;
721 memmove(impbuf->data, impbuf->data+(2*soundbuf->samples), 4*overlap);
722 memset(impbuf->data + 2*overlap, 0, impbuf->bytes - 4*overlap);
723 assert(impbuf->bytes == impbuf->samples*4);
724 assert(soundbuf->bytes == soundbuf->samples*4);
725 memset(soundbuf->data, 0, soundbuf->bytes);
726 soundbuf->pos = 0;
727
728 impbuf->cycles -= (sound_div_tc * soundbuf->samples) / SOUND_DIV_MULT;
729 }
730
gb_change_level(long l_ofs,long r_ofs)731 static regparm void gb_change_level(long l_ofs, long r_ofs)
732 {
733 long pos;
734 long imp_idx;
735 long imp_l = -IMPULSE_WIDTH/2;
736 long imp_r = IMPULSE_WIDTH/2;
737 long i;
738 const short *ptr = base_impulse;
739
740 assert(impbuf != NULL);
741 pos = (long)(impbuf->cycles * SOUND_DIV_MULT / sound_div_tc);
742 imp_idx = (long)((impbuf->cycles << IMPULSE_N_SHIFT)*SOUND_DIV_MULT / sound_div_tc) & IMPULSE_N_MASK;
743 assert(pos + imp_r < impbuf->samples);
744 assert(pos + imp_l >= 0);
745
746 ptr += imp_idx * IMPULSE_WIDTH;
747
748 for (i=imp_l; i<imp_r; i++) {
749 long bufi = pos + i;
750 long impi = i + IMPULSE_WIDTH/2;
751 impbuf->data[bufi*2 ] += ptr[impi] * l_ofs;
752 impbuf->data[bufi*2+1] += ptr[impi] * r_ofs;
753 }
754
755 impbuf->l_lvl += l_ofs*256;
756 impbuf->r_lvl += r_ofs*256;
757 }
758
gb_sound(long cycles)759 static regparm void gb_sound(long cycles)
760 {
761 long i, j;
762 long l_lvl = 0, r_lvl = 0;
763
764 assert(impbuf != NULL);
765
766 for (j=0; j<cycles; j++) {
767 main_div++;
768 impbuf->cycles++;
769 if (impbuf->cycles*SOUND_DIV_MULT >= sound_div_tc*(impbuf->samples - IMPULSE_WIDTH/2))
770 gb_flush_buffer();
771
772 if (gbhw_ch[2].running) {
773 gbhw_ch[2].div_ctr--;
774 if (gbhw_ch[2].div_ctr <= 0) {
775 long val = ch3_next_nibble;
776 long pos = ch3pos++;
777 ch3_next_nibble = GET_NIBBLE(&ioregs[0x30], pos) * 2;
778 gbhw_ch[2].div_ctr = gbhw_ch[2].div_tc*2;
779 if (gbhw_ch[2].volume) {
780 val = val >> (gbhw_ch[2].volume-1);
781 } else val = 0;
782 gbhw_ch[2].lvl = val - 15;
783 update_level = 1;
784 }
785 }
786
787 if (gbhw_ch[3].running) {
788 gbhw_ch[3].div_ctr--;
789 if (gbhw_ch[3].div_ctr <= 0) {
790 long val;
791 gbhw_ch[3].div_ctr = gbhw_ch[3].div_tc;
792 lfsr = (lfsr << 1) | (((lfsr & tap1) > 0) ^ ((lfsr & tap2) > 0));
793 val = gbhw_ch[3].volume * 2 * (!(lfsr & tap1));
794 gbhw_ch[3].lvl = val - 15;
795 update_level = 1;
796 }
797 }
798
799 if (main_div > main_div_tc) {
800 main_div -= main_div_tc;
801
802 for (i=0; i<2; i++) if (gbhw_ch[i].running) {
803 long val = 2 * gbhw_ch[i].volume;
804 if (gbhw_ch[i].div_ctr > gbhw_ch[i].duty_tc) {
805 val = 0;
806 }
807 gbhw_ch[i].lvl = val - 15;
808 gbhw_ch[i].div_ctr--;
809 if (gbhw_ch[i].div_ctr <= 0) {
810 gbhw_ch[i].div_ctr = gbhw_ch[i].div_tc;
811 }
812 }
813
814 sweep_div += 1;
815 if (sweep_div >= sweep_div_tc) {
816 sweep_div = 0;
817 sequencer_step();
818 }
819 update_level = 1;
820 }
821
822 if (update_level) {
823 update_level = 0;
824 l_lvl = 0;
825 r_lvl = 0;
826 for (i=0; i<4; i++) {
827 if (gbhw_ch[i].mute)
828 continue;
829 if (gbhw_ch[i].leftgate)
830 l_lvl += gbhw_ch[i].lvl;
831 if (gbhw_ch[i].rightgate)
832 r_lvl += gbhw_ch[i].lvl;
833 }
834
835 if (l_lvl != last_l_value || r_lvl != last_r_value) {
836 gb_change_level(l_lvl - last_l_value, r_lvl - last_r_value);
837 last_l_value = l_lvl;
838 last_r_value = r_lvl;
839 }
840 }
841 }
842 }
843
gbhw_setcallback(gbhw_callback_fn fn,void * priv)844 regparm void gbhw_setcallback(gbhw_callback_fn fn, void *priv)
845 {
846 callback = fn;
847 callbackpriv = priv;
848 }
849
gbhw_setiocallback(gbhw_iocallback_fn fn,void * priv)850 regparm void gbhw_setiocallback(gbhw_iocallback_fn fn, void *priv)
851 {
852 iocallback = fn;
853 iocallback_priv = priv;
854 }
855
gbhw_setstepcallback(gbhw_stepcallback_fn fn,void * priv)856 regparm void gbhw_setstepcallback(gbhw_stepcallback_fn fn, void *priv)
857 {
858 stepcallback = fn;
859 stepcallback_priv = priv;
860 }
861
gbhw_impbuf_reset(struct gbhw_buffer * impbuf)862 static regparm void gbhw_impbuf_reset(struct gbhw_buffer *impbuf)
863 {
864 assert(sound_div_tc != 0);
865 impbuf->cycles = (long)(sound_div_tc * IMPULSE_WIDTH/2 / SOUND_DIV_MULT);
866 impbuf->l_lvl = 0;
867 impbuf->r_lvl = 0;
868 memset(impbuf->data, 0, impbuf->bytes);
869 }
870
gbhw_setbuffer(struct gbhw_buffer * buffer)871 regparm void gbhw_setbuffer(struct gbhw_buffer *buffer)
872 {
873 soundbuf = buffer;
874 soundbuf->samples = soundbuf->bytes / 4;
875
876 if (impbuf) free(impbuf);
877 impbuf = malloc(sizeof(*impbuf) + (soundbuf->samples + IMPULSE_WIDTH + 1) * 4);
878 if (impbuf == NULL) {
879 fprintf(stderr, "%s", _("Memory allocation failed!\n"));
880 return;
881 }
882 memset(impbuf, 0, sizeof(*impbuf));
883 impbuf->data = (void*)(impbuf+1);
884 impbuf->samples = soundbuf->samples + IMPULSE_WIDTH + 1;
885 impbuf->bytes = impbuf->samples * 4;
886 gbhw_impbuf_reset(impbuf);
887 }
888
gbhw_update_filter()889 static void gbhw_update_filter()
890 {
891 double cap_constant = pow(filter_constant, (double)GBHW_CLOCK / sample_rate);
892 cap_factor = round(65536.0 * cap_constant);
893 }
894
gbhw_setfilter(const char * type)895 regparm long gbhw_setfilter(const char *type)
896 {
897 if (strcasecmp(type, GBHW_CFG_FILTER_OFF) == 0) {
898 filter_enabled = 0;
899 filter_constant = GBHW_FILTER_CONST_OFF;
900 } else if (strcasecmp(type, GBHW_CFG_FILTER_DMG) == 0) {
901 filter_enabled = 1;
902 filter_constant = GBHW_FILTER_CONST_DMG;
903 } else if (strcasecmp(type, GBHW_CFG_FILTER_CGB) == 0) {
904 filter_enabled = 1;
905 filter_constant = GBHW_FILTER_CONST_CGB;
906 } else {
907 return 0;
908 }
909
910 gbhw_update_filter();
911
912 return 1;
913 }
914
gbhw_setrate(long rate)915 regparm void gbhw_setrate(long rate)
916 {
917 sample_rate = rate;
918 sound_div_tc = GBHW_CLOCK*SOUND_DIV_MULT/rate;
919 gbhw_update_filter();
920 }
921
gbhw_getminmax(int16_t * lmin,int16_t * lmax,int16_t * rmin,int16_t * rmax)922 regparm void gbhw_getminmax(int16_t *lmin, int16_t *lmax, int16_t *rmin, int16_t *rmax)
923 {
924 if (lminval == INT_MAX) return;
925 *lmin = lminval;
926 *lmax = lmaxval;
927 *rmin = rminval;
928 *rmax = rmaxval;
929 lminval = rminval = INT_MAX;
930 lmaxval = rmaxval = INT_MIN;
931 }
932
933 /*
934 * Initialize Gameboy hardware emulation.
935 * The size should be a multiple of 0x4000,
936 * so we don't need range checking in rom_get and
937 * rombank_get.
938 */
gbhw_init(uint8_t * rombuf,uint32_t size)939 regparm void gbhw_init(uint8_t *rombuf, uint32_t size)
940 {
941 long i;
942
943 vblankctr = vblanktc;
944 timerctr = 0;
945
946 if (impbuf)
947 gbhw_impbuf_reset(impbuf);
948 rom = rombuf;
949 lastbank = ((size + 0x3fff) / 0x4000) - 1;
950 rombank = 1;
951 master_volume = MASTER_VOL_MAX;
952 master_fade = 0;
953 apu_on = 1;
954 if (soundbuf) {
955 soundbuf->pos = 0;
956 soundbuf->l_lvl = 0;
957 soundbuf->r_lvl = 0;
958 soundbuf->l_cap = 0;
959 soundbuf->r_cap = 0;
960 }
961 lminval = rminval = INT_MAX;
962 lmaxval = rmaxval = INT_MIN;
963 apu_reset();
964 memset(extram, 0, sizeof(extram));
965 memset(intram, 0, sizeof(intram));
966 memset(hiram, 0, sizeof(hiram));
967 memset(ioregs, 0, sizeof(ioregs));
968 for (i=0x10; i<0x40; i++) {
969 io_put(0xff00 + i, ioregs_initdata[i]);
970 }
971
972 sum_cycles = 0;
973 halted_noirq_cycles = 0;
974 ch3pos = 0;
975 ch3_next_nibble = 0;
976 last_l_value = 0;
977 last_r_value = 0;
978
979 gbcpu_init();
980 gbcpu_addmem(0x00, 0x3f, rom_put, rom_get);
981 gbcpu_addmem(0x40, 0x7f, rom_put, rombank_get);
982 gbcpu_addmem(0xa0, 0xbf, extram_put, extram_get);
983 gbcpu_addmem(0xc0, 0xfe, intram_put, intram_get);
984 gbcpu_addmem(0xff, 0xff, io_put, io_get);
985 }
986
gbhw_enable_bootrom(const uint8_t * rombuf)987 regparm void gbhw_enable_bootrom(const uint8_t *rombuf)
988 {
989 memcpy(boot_rom, rombuf, sizeof(boot_rom));
990 rom_lockout = 0;
991 }
992
993 /* internal for gbs.c, not exported from libgbs */
gbhw_io_put(uint16_t addr,uint8_t val)994 regparm void gbhw_io_put(uint16_t addr, uint8_t val) {
995 if (addr != 0xffff && (addr < 0xff00 || addr > 0xff7f))
996 return;
997 io_put(addr, val);
998 }
999
1000 /* unmasked peek used by gbsplay.c to print regs */
gbhw_io_peek(uint16_t addr)1001 regparm uint8_t gbhw_io_peek(uint16_t addr)
1002 {
1003 if (addr >= 0xff10 && addr <= 0xff3e) {
1004 return ioregs[addr & 0x7f];
1005 }
1006 return 0xff;
1007 }
1008
1009
gbhw_check_if(void)1010 regparm void gbhw_check_if(void)
1011 {
1012 uint8_t mask = 0x01; /* lowest bit is highest priority irq */
1013 uint8_t vec = 0x40;
1014 if (!gbcpu_if) {
1015 /* interrupts disabled */
1016 if (ioregs[REG_IF] & ioregs[REG_IE]) {
1017 /* but will still exit halt */
1018 gbcpu_halted = 0;
1019 }
1020 return;
1021 }
1022 while (mask <= 0x10) {
1023 if (ioregs[REG_IF] & ioregs[REG_IE] & mask) {
1024 ioregs[REG_IF] &= ~mask;
1025 gbcpu_halted = 0;
1026 gbcpu_intr(vec);
1027 break;
1028 }
1029 vec += 0x08;
1030 mask <<= 1;
1031 }
1032 }
1033
blargg_debug(void)1034 static regparm void blargg_debug(void)
1035 {
1036 long i;
1037
1038 /* Blargg GB debug output signature. */
1039 if (gbcpu_mem_get(0xa001) != 0xde ||
1040 gbcpu_mem_get(0xa002) != 0xb0 ||
1041 gbcpu_mem_get(0xa003) != 0x61) {
1042 return;
1043 }
1044
1045 fprintf(stderr, "\nBlargg debug output:\n");
1046
1047 for (i = 0xa004; i < 0xb000; i++) {
1048 uint8_t c = gbcpu_mem_get(i);
1049 if (c == 0 || c >= 128) {
1050 return;
1051 }
1052 if (c < 32 && c != 10 && c != 13) {
1053 return;
1054 }
1055 fputc(c, stderr);
1056 }
1057 }
1058
1059 /**
1060 * @param time_to_work emulated time in milliseconds
1061 * @return elapsed cpu cycles
1062 */
gbhw_step(long time_to_work)1063 regparm long gbhw_step(long time_to_work)
1064 {
1065 long cycles_total = 0;
1066
1067 if (pause_output) {
1068 (void)usleep(time_to_work*1000);
1069 return 0;
1070 }
1071
1072 time_to_work *= msec_cycles;
1073
1074 while (cycles_total < time_to_work) {
1075 long maxcycles = time_to_work - cycles_total;
1076 long cycles = 0;
1077
1078 if (vblankctr > 0 && vblankctr < maxcycles) maxcycles = vblankctr;
1079 if (timerctr > 0 && timerctr < maxcycles) maxcycles = timerctr;
1080
1081 io_written = 0;
1082 while (cycles < maxcycles && !io_written) {
1083 long step;
1084 gbhw_check_if();
1085 step = gbcpu_step();
1086 if (gbcpu_halted) {
1087 halted_noirq_cycles += step;
1088 if (gbcpu_if == 0 &&
1089 (ioregs[REG_IE] == 0 ||
1090 halted_noirq_cycles > GBHW_CLOCK/10)) {
1091 fprintf(stderr, "CPU locked up (halt with interrupts disabled).\n");
1092 blargg_debug();
1093 return -1;
1094 }
1095 } else {
1096 halted_noirq_cycles = 0;
1097 }
1098 if (step < 0) return step;
1099 cycles += step;
1100 sum_cycles += step;
1101 vblankctr -= step;
1102 if (vblankctr <= 0) {
1103 vblankctr += vblanktc;
1104 ioregs[REG_IF] |= 0x01;
1105 DPRINTF("vblank_interrupt\n");
1106 }
1107 gb_sound(step);
1108 if (stepcallback)
1109 stepcallback(sum_cycles, gbhw_ch, stepcallback_priv);
1110 }
1111
1112 if (ioregs[REG_TAC] & 4) {
1113 if (timerctr > 0) timerctr -= cycles;
1114 while (timerctr <= 0) {
1115 timerctr += timertc;
1116 ioregs[REG_TIMA]++;
1117 //DPRINTF("TIMA=%02x\n", ioregs[REG_TIMA]);
1118 if (ioregs[REG_TIMA] == 0) {
1119 ioregs[REG_TIMA] = ioregs[REG_TMA];
1120 ioregs[REG_IF] |= 0x04;
1121 DPRINTF("timer_interrupt\n");
1122 }
1123 }
1124 }
1125 cycles_total += cycles;
1126 }
1127
1128 return cycles_total;
1129 }
1130
gbhw_pause(long new_pause)1131 regparm void gbhw_pause(long new_pause)
1132 {
1133 pause_output = new_pause != 0;
1134 }
1135