1 /*
2 ** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com)
3 **
4 **
5 ** This program is free software; you can redistribute it and/or
6 ** modify it under the terms of version 2 of the GNU Library General
7 ** Public License as published by the Free Software Foundation.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Library General Public License for more details. To obtain a
13 ** copy of the GNU Library General Public License, write to the Free
14 ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 **
16 ** Any permitted reproduction of these routines, in whole or in part,
17 ** must bear this legend.
18 **
19 **
20 ** nes_apu.c
21 **
22 ** NES APU emulation
23 ** $Id: nes_apu.c,v 1.2 2003/04/09 14:50:32 ben Exp $
24 */
25
26 #include <string.h>
27 #include "types.h"
28 #include "log.h"
29 #include "nes_apu.h"
30 #include "nes6502.h"
31
32 #ifdef NSF_PLAYER
33 #include "nsf.h"
34 #else
35 #include "nes.h"
36 #include "nes_ppu.h"
37 #include "nes_mmc.h"
38 #include "nesinput.h"
39 #endif /* !NSF_PLAYER */
40
41
42 #define APU_OVERSAMPLE
43 #define APU_VOLUME_DECAY(x) ((x) -= ((x) >> 7))
44
45
46 /* pointer to active APU */
47 static apu_t *apu;
48
49 /* look up table madness */
50 static int32 decay_lut[16];
51 static int vbl_lut[32];
52 static int trilength_lut[128];
53
54 /* noise lookups for both modes */
55 #ifndef REALTIME_NOISE
56 static int8 noise_long_lut[APU_NOISE_32K];
57 static int8 noise_short_lut[APU_NOISE_93];
58 #endif /* !REALTIME_NOISE */
59
60 /* $$$ ben : last error */
61 #define SET_APU_ERROR(APU,X) \
62 if (APU) (APU)->errstr = "apu: " X; else
63
64 #define APU_MIX_ENABLE(BIT) (apu->mix_enable&(1<<(BIT)))
65
66 /* vblank length table used for rectangles, triangle, noise */
67 static const uint8 vbl_length[32] =
68 {
69 5, 127,
70 10, 1,
71 19, 2,
72 40, 3,
73 80, 4,
74 30, 5,
75 7, 6,
76 13, 7,
77 6, 8,
78 12, 9,
79 24, 10,
80 48, 11,
81 96, 12,
82 36, 13,
83 8, 14,
84 16, 15
85 };
86
87 /* frequency limit of rectangle channels */
88 static const int freq_limit[8] =
89 {
90 0x3FF, 0x555, 0x666, 0x71C, 0x787, 0x7C1, 0x7E0, 0x7F0
91 };
92
93 /* noise frequency lookup table */
94 static const int noise_freq[16] =
95 {
96 4, 8, 16, 32, 64, 96, 128, 160,
97 202, 254, 380, 508, 762, 1016, 2034, 4068
98 };
99
100 /* DMC transfer freqs */
101 const int dmc_clocks[16] =
102 {
103 428, 380, 340, 320, 286, 254, 226, 214,
104 190, 160, 142, 128, 106, 85, 72, 54
105 };
106
107 /* ratios of pos/neg pulse for rectangle waves */
108 static const int duty_lut[4] = { 2, 4, 8, 12 };
109
110
apu_setcontext(apu_t * src_apu)111 void apu_setcontext(apu_t *src_apu)
112 {
113 apu = src_apu;
114 /* $$$ ben reset eoor string here. */
115 SET_APU_ERROR(apu,"no error");
116 }
117
118 /*
119 ** Simple queue routines
120 */
121 #define APU_QEMPTY() (apu->q_head == apu->q_tail)
122
apu_enqueue(apudata_t * d)123 static int apu_enqueue(apudata_t *d)
124 {
125 ASSERT(apu);
126 apu->queue[apu->q_head] = *d;
127
128 apu->q_head = (apu->q_head + 1) & APUQUEUE_MASK;
129
130 if (APU_QEMPTY()) {
131 log_printf("apu: queue overflow\n");
132 SET_APU_ERROR(apu,"queue overflow");
133 return -1;
134 }
135 return 0;
136 }
137
apu_dequeue(void)138 static apudata_t *apu_dequeue(void)
139 {
140 int loc;
141
142 ASSERT(apu);
143
144 if (APU_QEMPTY()) {
145 log_printf("apu: queue empty\n");
146 SET_APU_ERROR(apu,"queue empty");
147 /* $$$ ben : should return 0 ??? */
148 }
149 loc = apu->q_tail;
150 apu->q_tail = (apu->q_tail + 1) & APUQUEUE_MASK;
151
152 return &apu->queue[loc];
153 }
154
apu_setchan(int chan,boolean enabled)155 int apu_setchan(int chan, boolean enabled)
156 {
157 const unsigned int max = 6;
158 int old;
159
160 ASSERT(apu);
161 if ((unsigned int)chan >= max) {
162 SET_APU_ERROR(apu,"channel out of range");
163 return -1;
164 }
165 old = (apu->mix_enable>>chan) & 1;
166 if (enabled != (boolean)-1) {
167 apu->mix_enable = (apu->mix_enable & ~(1<<chan)) | ((!!enabled)<<chan);
168 }
169 return old;
170 }
171
172 /* emulation of the 15-bit shift register the
173 ** NES uses to generate pseudo-random series
174 ** for the white noise channel
175 */
176 #ifdef REALTIME_NOISE
shift_register15(uint8 xor_tap)177 INLINE int8 shift_register15(uint8 xor_tap)
178 {
179 static int sreg = 0x4000;
180 int bit0, tap, bit14;
181
182 bit0 = sreg & 1;
183 tap = (sreg & xor_tap) ? 1 : 0;
184 bit14 = (bit0 ^ tap);
185 sreg >>= 1;
186 sreg |= (bit14 << 14);
187 return (bit0 ^ 1);
188 }
189 #else
shift_register15(int8 * buf,int count)190 static void shift_register15(int8 *buf, int count)
191 {
192 static int sreg = 0x4000;
193 int bit0, bit1, bit6, bit14;
194
195 if (count == APU_NOISE_93)
196 {
197 while (count--)
198 {
199 bit0 = sreg & 1;
200 bit6 = (sreg & 0x40) >> 6;
201 bit14 = (bit0 ^ bit6);
202 sreg >>= 1;
203 sreg |= (bit14 << 14);
204 *buf++ = bit0 ^ 1;
205 }
206 }
207 else /* 32K noise */
208 {
209 while (count--)
210 {
211 bit0 = sreg & 1;
212 bit1 = (sreg & 2) >> 1;
213 bit14 = (bit0 ^ bit1);
214 sreg >>= 1;
215 sreg |= (bit14 << 14);
216 *buf++ = bit0 ^ 1;
217 }
218 }
219 }
220 #endif
221
222 /* RECTANGLE WAVE
223 ** ==============
224 ** reg0: 0-3=volume, 4=envelope, 5=hold, 6-7=duty cycle
225 ** reg1: 0-2=sweep shifts, 3=sweep inc/dec, 4-6=sweep length, 7=sweep on
226 ** reg2: 8 bits of freq
227 ** reg3: 0-2=high freq, 7-4=vbl length counter
228 */
229 #define APU_RECTANGLE_OUTPUT chan->output_vol
apu_rectangle(rectangle_t * chan)230 static int32 apu_rectangle(rectangle_t *chan)
231 {
232 int32 output;
233
234 #ifdef APU_OVERSAMPLE
235 int num_times;
236 int32 total;
237 #endif
238
239 APU_VOLUME_DECAY(chan->output_vol);
240
241 if (FALSE == chan->enabled || 0 == chan->vbl_length)
242 return APU_RECTANGLE_OUTPUT;
243
244 /* vbl length counter */
245 if (FALSE == chan->holdnote)
246 chan->vbl_length--;
247
248 /* envelope decay at a rate of (env_delay + 1) / 240 secs */
249 chan->env_phase -= 4; /* 240/60 */
250 while (chan->env_phase < 0)
251 {
252 chan->env_phase += chan->env_delay;
253
254 if (chan->holdnote)
255 chan->env_vol = (chan->env_vol + 1) & 0x0F;
256 else if (chan->env_vol < 0x0F)
257 chan->env_vol++;
258 }
259
260 if ((FALSE == chan->sweep_inc && chan->freq > chan->freq_limit)
261 || chan->freq < APU_TO_FIXED(4))
262 return APU_RECTANGLE_OUTPUT;
263
264 /* frequency sweeping at a rate of (sweep_delay + 1) / 120 secs */
265 if (chan->sweep_on && chan->sweep_shifts)
266 {
267 chan->sweep_phase -= 2; /* 120/60 */
268 while (chan->sweep_phase < 0)
269 {
270 chan->sweep_phase += chan->sweep_delay;
271 if (chan->sweep_inc) /* ramp up */
272 chan->freq -= chan->freq >> (chan->sweep_shifts);
273 else /* ramp down */
274 chan->freq += chan->freq >> (chan->sweep_shifts);
275 }
276 }
277
278 chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */
279 if (chan->phaseacc >= 0)
280 return APU_RECTANGLE_OUTPUT;
281
282 #ifdef APU_OVERSAMPLE
283 num_times = total = 0;
284
285 if (chan->fixed_envelope)
286 output = chan->volume << 8; /* fixed volume */
287 else
288 output = (chan->env_vol ^ 0x0F) << 8;
289 #endif
290
291 while (chan->phaseacc < 0)
292 {
293 chan->phaseacc += chan->freq;
294 chan->adder = (chan->adder + 1) & 0x0F;
295
296 #ifdef APU_OVERSAMPLE
297 if (chan->adder < chan->duty_flip)
298 total += output;
299 else
300 total -= output;
301
302 num_times++;
303 #endif
304 }
305
306 #ifdef APU_OVERSAMPLE
307 chan->output_vol = total / num_times;
308 #else
309 if (chan->fixed_envelope)
310 output = chan->volume << 8; /* fixed volume */
311 else
312 output = (chan->env_vol ^ 0x0F) << 8;
313
314 if (0 == chan->adder)
315 chan->output_vol = output;
316 else if (chan->adder == chan->duty_flip)
317 chan->output_vol = -output;
318 #endif
319
320 return APU_RECTANGLE_OUTPUT;
321 }
322
323 /* TRIANGLE WAVE
324 ** =============
325 ** reg0: 7=holdnote, 6-0=linear length counter
326 ** reg2: low 8 bits of frequency
327 ** reg3: 7-3=length counter, 2-0=high 3 bits of frequency
328 */
329 #define APU_TRIANGLE_OUTPUT (chan->output_vol + (chan->output_vol >> 2))
apu_triangle(triangle_t * chan)330 static int32 apu_triangle(triangle_t *chan)
331 {
332 APU_VOLUME_DECAY(chan->output_vol);
333
334 if (FALSE == chan->enabled || 0 == chan->vbl_length)
335 return APU_TRIANGLE_OUTPUT;
336
337 if (chan->counter_started)
338 {
339 if (chan->linear_length > 0)
340 chan->linear_length--;
341 if (chan->vbl_length && FALSE == chan->holdnote)
342 chan->vbl_length--;
343 }
344 else if (FALSE == chan->holdnote && chan->write_latency)
345 {
346 if (--chan->write_latency == 0)
347 chan->counter_started = TRUE;
348 }
349 /*
350 if (chan->countmode == COUNTMODE_COUNT)
351 {
352 if (chan->linear_length > 0)
353 chan->linear_length--;
354 if (chan->vbl_length)
355 chan->vbl_length--;
356 }
357 */
358 if (0 == chan->linear_length || chan->freq < APU_TO_FIXED(4)) /* inaudible */
359 return APU_TRIANGLE_OUTPUT;
360
361 chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */
362 while (chan->phaseacc < 0)
363 {
364 chan->phaseacc += chan->freq;
365 chan->adder = (chan->adder + 1) & 0x1F;
366
367 if (chan->adder & 0x10)
368 chan->output_vol -= (2 << 8);
369 else
370 chan->output_vol += (2 << 8);
371 }
372
373 return APU_TRIANGLE_OUTPUT;
374 }
375
376
377 /* WHITE NOISE CHANNEL
378 ** ===================
379 ** reg0: 0-3=volume, 4=envelope, 5=hold
380 ** reg2: 7=small(93 byte) sample,3-0=freq lookup
381 ** reg3: 7-4=vbl length counter
382 */
383 #define APU_NOISE_OUTPUT ((chan->output_vol + chan->output_vol + chan->output_vol) >> 2)
384
apu_noise(noise_t * chan)385 static int32 apu_noise(noise_t *chan)
386 {
387 int32 outvol;
388
389 #if defined(APU_OVERSAMPLE) && defined(REALTIME_NOISE)
390 #else
391 int32 noise_bit;
392 #endif
393 #ifdef APU_OVERSAMPLE
394 int num_times;
395 int32 total;
396 #endif
397
398 APU_VOLUME_DECAY(chan->output_vol);
399
400 if (FALSE == chan->enabled || 0 == chan->vbl_length)
401 return APU_NOISE_OUTPUT;
402
403 /* vbl length counter */
404 if (FALSE == chan->holdnote)
405 chan->vbl_length--;
406
407 /* envelope decay at a rate of (env_delay + 1) / 240 secs */
408 chan->env_phase -= 4; /* 240/60 */
409 while (chan->env_phase < 0)
410 {
411 chan->env_phase += chan->env_delay;
412
413 if (chan->holdnote)
414 chan->env_vol = (chan->env_vol + 1) & 0x0F;
415 else if (chan->env_vol < 0x0F)
416 chan->env_vol++;
417 }
418
419 chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */
420 if (chan->phaseacc >= 0)
421 return APU_NOISE_OUTPUT;
422
423 #ifdef APU_OVERSAMPLE
424 num_times = total = 0;
425
426 if (chan->fixed_envelope)
427 outvol = chan->volume << 8; /* fixed volume */
428 else
429 outvol = (chan->env_vol ^ 0x0F) << 8;
430 #endif
431
432 while (chan->phaseacc < 0)
433 {
434 chan->phaseacc += chan->freq;
435
436 #ifdef REALTIME_NOISE
437
438 #ifdef APU_OVERSAMPLE
439 if (shift_register15(chan->xor_tap))
440 total += outvol;
441 else
442 total -= outvol;
443
444 num_times++;
445 #else
446 noise_bit = shift_register15(chan->xor_tap);
447 #endif
448
449 #else
450 chan->cur_pos++;
451
452 if (chan->short_sample)
453 {
454 if (APU_NOISE_93 == chan->cur_pos)
455 chan->cur_pos = 0;
456 }
457 else
458 {
459 if (APU_NOISE_32K == chan->cur_pos)
460 chan->cur_pos = 0;
461 }
462
463 #ifdef APU_OVERSAMPLE
464 if (chan->short_sample)
465 noise_bit = noise_short_lut[chan->cur_pos];
466 else
467 noise_bit = noise_long_lut[chan->cur_pos];
468
469 if (noise_bit)
470 total += outvol;
471 else
472 total -= outvol;
473
474 num_times++;
475 #endif
476 #endif /* REALTIME_NOISE */
477 }
478
479 #ifdef APU_OVERSAMPLE
480 chan->output_vol = total / num_times;
481 #else
482 if (chan->fixed_envelope)
483 outvol = chan->volume << 8; /* fixed volume */
484 else
485 outvol = (chan->env_vol ^ 0x0F) << 8;
486
487 #ifndef REALTIME_NOISE
488 if (chan->short_sample)
489 noise_bit = noise_short_lut[chan->cur_pos];
490 else
491 noise_bit = noise_long_lut[chan->cur_pos];
492 #endif /* !REALTIME_NOISE */
493
494 if (noise_bit)
495 chan->output_vol = outvol;
496 else
497 chan->output_vol = -outvol;
498 #endif
499
500 return APU_NOISE_OUTPUT;
501 }
502
503
apu_dmcreload(dmc_t * chan)504 INLINE void apu_dmcreload(dmc_t *chan)
505 {
506 chan->address = chan->cached_addr;
507 chan->dma_length = chan->cached_dmalength;
508 chan->irq_occurred = FALSE;
509 }
510
511 /* DELTA MODULATION CHANNEL
512 ** =========================
513 ** reg0: 7=irq gen, 6=looping, 3-0=pointer to clock table
514 ** reg1: output dc level, 6 bits unsigned
515 ** reg2: 8 bits of 64-byte aligned address offset : $C000 + (value * 64)
516 ** reg3: length, (value * 16) + 1
517 */
518 #define APU_DMC_OUTPUT ((chan->output_vol + chan->output_vol + chan->output_vol) >> 2)
apu_dmc(dmc_t * chan)519 static int32 apu_dmc(dmc_t *chan)
520 {
521 int delta_bit;
522
523 APU_VOLUME_DECAY(chan->output_vol);
524
525 /* only process when channel is alive */
526 if (chan->dma_length)
527 {
528 chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */
529
530 while (chan->phaseacc < 0)
531 {
532 chan->phaseacc += chan->freq;
533
534 delta_bit = (chan->dma_length & 7) ^ 7;
535
536 if (7 == delta_bit)
537 {
538 chan->cur_byte = nes6502_getbyte(chan->address);
539
540 /* steal a cycle from CPU*/
541 nes6502_setdma(1);
542
543 if (0xFFFF == chan->address)
544 chan->address = 0x8000;
545 else
546 chan->address++;
547 }
548
549 if (--chan->dma_length == 0)
550 {
551 /* if loop bit set, we're cool to retrigger sample */
552 if (chan->looping)
553 apu_dmcreload(chan);
554 else
555 {
556 /* check to see if we should generate an irq */
557 if (chan->irq_gen)
558 {
559 chan->irq_occurred = TRUE;
560 nes6502_irq();
561 }
562
563 /* bodge for timestamp queue */
564 chan->enabled = FALSE;
565 break;
566 }
567 }
568
569 /* positive delta */
570 if (chan->cur_byte & (1 << delta_bit))
571 {
572 if (chan->regs[1] < 0x7D)
573 {
574 chan->regs[1] += 2;
575 chan->output_vol += (2 << 8);
576 }
577 /*
578 if (chan->regs[1] < 0x3F)
579 chan->regs[1]++;
580
581 chan->output_vol &= ~(0x7E << 8);
582 chan->output_vol |= ((chan->regs[1] << 1) << 8);
583 */
584 }
585 /* negative delta */
586 else
587 {
588 if (chan->regs[1] > 1)
589 {
590 chan->regs[1] -= 2;
591 chan->output_vol -= (2 << 8);
592 }
593
594 /*
595 if (chan->regs[1] > 0)
596 chan->regs[1]--;
597
598 chan->output_vol &= ~(0x7E << 8);
599 chan->output_vol |= ((chan->regs[1] << 1) << 8);
600 */
601 }
602 }
603 }
604
605 return APU_DMC_OUTPUT;
606 }
607
608
apu_regwrite(uint32 address,uint8 value)609 static void apu_regwrite(uint32 address, uint8 value)
610 {
611 int chan;
612
613 ASSERT(apu);
614 switch (address)
615 {
616 /* rectangles */
617 case APU_WRA0:
618 case APU_WRB0:
619 chan = (address & 4) ? 1 : 0;
620 apu->rectangle[chan].regs[0] = value;
621
622 apu->rectangle[chan].volume = value & 0x0F;
623 apu->rectangle[chan].env_delay = decay_lut[value & 0x0F];
624 apu->rectangle[chan].holdnote = (value & 0x20) ? TRUE : FALSE;
625 apu->rectangle[chan].fixed_envelope = (value & 0x10) ? TRUE : FALSE;
626 apu->rectangle[chan].duty_flip = duty_lut[value >> 6];
627 break;
628
629 case APU_WRA1:
630 case APU_WRB1:
631 chan = (address & 4) ? 1 : 0;
632 apu->rectangle[chan].regs[1] = value;
633 apu->rectangle[chan].sweep_on = (value & 0x80) ? TRUE : FALSE;
634 apu->rectangle[chan].sweep_shifts = value & 7;
635 apu->rectangle[chan].sweep_delay = decay_lut[(value >> 4) & 7];
636
637 apu->rectangle[chan].sweep_inc = (value & 0x08) ? TRUE : FALSE;
638 apu->rectangle[chan].freq_limit = APU_TO_FIXED(freq_limit[value & 7]);
639 break;
640
641 case APU_WRA2:
642 case APU_WRB2:
643 chan = (address & 4) ? 1 : 0;
644 apu->rectangle[chan].regs[2] = value;
645 // if (apu->rectangle[chan].enabled)
646 apu->rectangle[chan].freq = APU_TO_FIXED((((apu->rectangle[chan].regs[3] & 7) << 8) + value) + 1);
647 break;
648
649 case APU_WRA3:
650 case APU_WRB3:
651 chan = (address & 4) ? 1 : 0;
652 apu->rectangle[chan].regs[3] = value;
653
654 // if (apu->rectangle[chan].enabled)
655 {
656 apu->rectangle[chan].vbl_length = vbl_lut[value >> 3];
657 apu->rectangle[chan].env_vol = 0;
658 apu->rectangle[chan].freq = APU_TO_FIXED((((value & 7) << 8) + apu->rectangle[chan].regs[2]) + 1);
659 apu->rectangle[chan].adder = 0;
660 }
661 break;
662
663 /* triangle */
664 case APU_WRC0:
665 /*
666 if (0 == (apu->triangle.regs[0] & 0x80))
667 apu->triangle.countmode = COUNTMODE_COUNT;
668 else
669 {
670 if (apu->triangle.countmode == COUNTMODE_LOAD && apu->triangle.vbl_length)
671 apu->triangle.linear_length = trilength_lut[value & 0x7F];
672
673 if (0 == (value & 0x80))
674 apu->triangle.countmode = COUNTMODE_COUNT;
675 }
676 */
677 apu->triangle.regs[0] = value;
678
679 apu->triangle.holdnote = (value & 0x80) ? TRUE : FALSE;
680
681
682 // if (apu->triangle.enabled)
683 {
684 if (FALSE == apu->triangle.counter_started && apu->triangle.vbl_length)
685 apu->triangle.linear_length = trilength_lut[value & 0x7F];
686 }
687
688 break;
689
690 case APU_WRC2:
691
692 apu->triangle.regs[1] = value;
693
694 // if (apu->triangle.enabled)
695 apu->triangle.freq = APU_TO_FIXED((((apu->triangle.regs[2] & 7) << 8) + value) + 1);
696 break;
697
698 case APU_WRC3:
699
700 apu->triangle.regs[2] = value;
701
702 /* this is somewhat of a hack. there appears to be some latency on
703 ** the Real Thing between when trireg0 is written to and when the
704 ** linear length counter actually begins its countdown. we want to
705 ** prevent the case where the program writes to the freq regs first,
706 ** then to reg 0, and the counter accidentally starts running because
707 ** of the sound queue's timestamp processing.
708 **
709 ** set latency to a couple scanlines -- should be plenty of time for
710 ** the 6502 code to do a couple of table dereferences and load up the
711 ** other triregs
712 */
713
714 /* 06/13/00 MPC -- seems to work OK */
715 apu->triangle.write_latency = (int) (2 * NES_SCANLINE_CYCLES / APU_FROM_FIXED(apu->cycle_rate));
716 /*
717 apu->triangle.linear_length = trilength_lut[apu->triangle.regs[0] & 0x7F];
718 if (0 == (apu->triangle.regs[0] & 0x80))
719 apu->triangle.countmode = COUNTMODE_COUNT;
720 else
721 apu->triangle.countmode = COUNTMODE_LOAD;
722 */
723 // if (apu->triangle.enabled)
724 {
725 apu->triangle.freq = APU_TO_FIXED((((value & 7) << 8) + apu->triangle.regs[1]) + 1);
726 apu->triangle.vbl_length = vbl_lut[value >> 3];
727 apu->triangle.counter_started = FALSE;
728 apu->triangle.linear_length = trilength_lut[apu->triangle.regs[0] & 0x7F];
729 }
730
731 break;
732
733 /* noise */
734 case APU_WRD0:
735 apu->noise.regs[0] = value;
736 apu->noise.env_delay = decay_lut[value & 0x0F];
737 apu->noise.holdnote = (value & 0x20) ? TRUE : FALSE;
738 apu->noise.fixed_envelope = (value & 0x10) ? TRUE : FALSE;
739 apu->noise.volume = value & 0x0F;
740 break;
741
742 case APU_WRD2:
743 apu->noise.regs[1] = value;
744 apu->noise.freq = APU_TO_FIXED(noise_freq[value & 0x0F]);
745
746 #ifdef REALTIME_NOISE
747 apu->noise.xor_tap = (value & 0x80) ? 0x40: 0x02;
748 #else
749 /* detect transition from long->short sample */
750 if ((value & 0x80) && FALSE == apu->noise.short_sample)
751 {
752 /* recalculate short noise buffer */
753 shift_register15(noise_short_lut, APU_NOISE_93);
754 apu->noise.cur_pos = 0;
755 }
756 apu->noise.short_sample = (value & 0x80) ? TRUE : FALSE;
757 #endif
758 break;
759
760 case APU_WRD3:
761 apu->noise.regs[2] = value;
762
763 // if (apu->noise.enabled)
764 {
765 apu->noise.vbl_length = vbl_lut[value >> 3];
766 apu->noise.env_vol = 0; /* reset envelope */
767 }
768 break;
769
770 /* DMC */
771 case APU_WRE0:
772 apu->dmc.regs[0] = value;
773
774 apu->dmc.freq = APU_TO_FIXED(dmc_clocks[value & 0x0F]);
775 apu->dmc.looping = (value & 0x40) ? TRUE : FALSE;
776
777 if (value & 0x80)
778 apu->dmc.irq_gen = TRUE;
779 else
780 {
781 apu->dmc.irq_gen = FALSE;
782 apu->dmc.irq_occurred = FALSE;
783 }
784 break;
785
786 case APU_WRE1: /* 7-bit DAC */
787 /* add the _delta_ between written value and
788 ** current output level of the volume reg
789 */
790 value &= 0x7F; /* bit 7 ignored */
791 apu->dmc.output_vol += ((value - apu->dmc.regs[1]) << 8);
792 apu->dmc.regs[1] = value;
793 /*
794 apu->dmc.output_vol = (value & 0x7F) << 8;
795 apu->dmc.regs[1] = (value & 0x7E) >> 1;
796 */
797 break;
798
799 case APU_WRE2:
800 apu->dmc.regs[2] = value;
801 apu->dmc.cached_addr = 0xC000 + (uint16) (value << 6);
802 break;
803
804 case APU_WRE3:
805 apu->dmc.regs[3] = value;
806 apu->dmc.cached_dmalength = ((value << 4) + 1) << 3;
807 break;
808
809 case APU_SMASK:
810 /* bodge for timestamp queue */
811 apu->dmc.enabled = (value & 0x10) ? TRUE : FALSE;
812
813 apu->enable_reg = value;
814
815 for (chan = 0; chan < 2; chan++)
816 {
817 if (value & (1 << chan))
818 apu->rectangle[chan].enabled = TRUE;
819 else
820 {
821 apu->rectangle[chan].enabled = FALSE;
822 apu->rectangle[chan].vbl_length = 0;
823 }
824 }
825
826 if (value & 0x04)
827 apu->triangle.enabled = TRUE;
828 else
829 {
830 apu->triangle.enabled = FALSE;
831 apu->triangle.vbl_length = 0;
832 apu->triangle.linear_length = 0;
833 apu->triangle.counter_started = FALSE;
834 apu->triangle.write_latency = 0;
835 }
836
837 if (value & 0x08)
838 apu->noise.enabled = TRUE;
839 else
840 {
841 apu->noise.enabled = FALSE;
842 apu->noise.vbl_length = 0;
843 }
844
845 if (value & 0x10)
846 {
847 if (0 == apu->dmc.dma_length)
848 apu_dmcreload(&apu->dmc);
849 }
850 else
851 apu->dmc.dma_length = 0;
852
853 apu->dmc.irq_occurred = FALSE;
854 break;
855
856 /* unused, but they get hit in some mem-clear loops */
857 case 0x4009:
858 case 0x400D:
859 break;
860
861 default:
862 break;
863 }
864 }
865
866 /* Read from $4000-$4017 */
apu_read(uint32 address)867 uint8 apu_read(uint32 address)
868 {
869 uint8 value;
870
871 ASSERT(apu);
872
873 switch (address)
874 {
875 case APU_SMASK:
876 /* seems that bit 6 denotes vblank -- return 1 for now */
877 value = 0x40;
878
879 /* Return 1 in 0-5 bit pos if a channel is playing */
880 if (apu->rectangle[0].enabled && apu->rectangle[0].vbl_length)
881 value |= 0x01;
882 if (apu->rectangle[1].enabled && apu->rectangle[1].vbl_length)
883 value |= 0x02;
884 if (apu->triangle.enabled && apu->triangle.vbl_length)
885 value |= 0x04;
886 if (apu->noise.enabled && apu->noise.vbl_length)
887 value |= 0x08;
888
889 //if (apu->dmc.dma_length)
890 /* bodge for timestamp queue */
891 if (apu->dmc.enabled)
892 value |= 0x10;
893
894 if (apu->dmc.irq_occurred)
895 value |= 0x80;
896
897 break;
898
899 #ifndef NSF_PLAYER
900 case APU_JOY0:
901 value = input_get(INP_JOYPAD0);
902 break;
903
904 case APU_JOY1:
905 value = input_get(INP_ZAPPER | INP_JOYPAD1 /*| INP_ARKANOID*/ /*| INP_POWERPAD*/);
906 break;
907 #endif /* !NSF_PLAYER */
908
909 default:
910 value = (address >> 8); /* heavy capacitance on data bus */
911 break;
912 }
913
914 return value;
915 }
916
917
apu_write(uint32 address,uint8 value)918 void apu_write(uint32 address, uint8 value)
919 {
920 #ifndef NSF_PLAYER
921 static uint8 last_write;
922 #endif /* !NSF_PLAYER */
923 apudata_t d;
924
925 switch (address)
926 {
927 case 0x4015:
928 /* bodge for timestamp queue */
929 apu->dmc.enabled = (value & 0x10) ? TRUE : FALSE;
930
931 case 0x4000: case 0x4001: case 0x4002: case 0x4003:
932 case 0x4004: case 0x4005: case 0x4006: case 0x4007:
933 case 0x4008: case 0x4009: case 0x400A: case 0x400B:
934 case 0x400C: case 0x400D: case 0x400E: case 0x400F:
935 case 0x4010: case 0x4011: case 0x4012: case 0x4013:
936 d.timestamp = nes6502_getcycles(FALSE);
937 d.address = address;
938 d.value = value;
939 apu_enqueue(&d);
940 break;
941
942 #ifndef NSF_PLAYER
943 case APU_OAMDMA:
944 ppu_oamdma(address, value);
945 break;
946
947 case APU_JOY0:
948 /* VS system VROM switching */
949 mmc_vsvrom(value & 4);
950
951 /* see if we need to strobe them joypads */
952 value &= 1;
953 if ((0 == value) && last_write)
954 input_strobe();
955 last_write = value;
956 break;
957
958 case APU_JOY1: /* Some kind of IRQ control business */
959 break;
960
961 #endif /* !NSF_PLAYER */
962
963 default:
964 break;
965 }
966 }
967
apu_getpcmdata(void ** data,int * num_samples,int * sample_bits)968 void apu_getpcmdata(void **data, int *num_samples, int *sample_bits)
969 {
970 ASSERT(apu);
971 *data = apu->buffer;
972 *num_samples = apu->num_samples;
973 *sample_bits = apu->sample_bits;
974 }
975
976
apu_process(void * buffer,int num_samples)977 void apu_process(void *buffer, int num_samples)
978 {
979 apudata_t *d;
980 uint32 elapsed_cycles;
981 static int32 prev_sample = 0;
982 int32 next_sample, accum;
983 uint8 *buff_u8 = (uint8 *)buffer;
984 int16 *buff_16 = (int16 *)buffer;
985
986
987 ASSERT(apu);
988
989 /* grab it, keep it local for speed */
990 elapsed_cycles = (uint32) apu->elapsed_cycles;
991
992 /* BLEH */
993 apu->buffer = buffer;
994
995 while (num_samples--)
996 {
997 while ((FALSE == APU_QEMPTY()) && (apu->queue[apu->q_tail].timestamp <= elapsed_cycles))
998 {
999 d = apu_dequeue();
1000 apu_regwrite(d->address, d->value);
1001 }
1002
1003 elapsed_cycles += APU_FROM_FIXED(apu->cycle_rate);
1004
1005 accum = 0;
1006 if (APU_MIX_ENABLE(0)) accum += apu_rectangle(&apu->rectangle[0]);
1007 if (APU_MIX_ENABLE(1)) accum += apu_rectangle(&apu->rectangle[1]);
1008 if (APU_MIX_ENABLE(2)) accum += apu_triangle(&apu->triangle);
1009 if (APU_MIX_ENABLE(3)) accum += apu_noise(&apu->noise);
1010 if (APU_MIX_ENABLE(4)) accum += apu_dmc(&apu->dmc);
1011
1012 if (apu->ext && APU_MIX_ENABLE(5)) accum += apu->ext->process();
1013
1014 /* do any filtering */
1015 if (APU_FILTER_NONE != apu->filter_type)
1016 {
1017 next_sample = accum;
1018
1019 if (APU_FILTER_LOWPASS == apu->filter_type)
1020 {
1021 accum += prev_sample;
1022 accum >>= 1;
1023 }
1024 else
1025 accum = (accum + accum + accum + prev_sample) >> 2;
1026
1027 prev_sample = next_sample;
1028 }
1029
1030 /* little extra kick for the kids */
1031 accum <<= 1;
1032
1033 /* prevent clipping */
1034 if (accum > 0x7FFF)
1035 accum = 0x7FFF;
1036 else if (accum < -0x8000)
1037 accum = -0x8000;
1038
1039 /* signed 16-bit output, unsigned 8-bit */
1040 if (16 == apu->sample_bits)
1041 *buff_16++ = (int16) accum;
1042 else
1043 *buff_u8++ = (accum >> 8) ^0x80;
1044 }
1045
1046 /* resync cycle counter */
1047 apu->elapsed_cycles = nes6502_getcycles(FALSE);
1048 }
1049
1050 /* set the filter type */
1051 /* $$$ ben :
1052 * Add a get feature (filter_type == -1) and returns old filter type
1053 */
apu_setfilter(int filter_type)1054 int apu_setfilter(int filter_type)
1055 {
1056 int old;
1057 ASSERT(apu);
1058 old = apu->filter_type;
1059 if (filter_type != -1) {
1060 apu->filter_type = filter_type;
1061 }
1062 return old;
1063 }
1064
apu_reset(void)1065 void apu_reset(void)
1066 {
1067 uint32 address;
1068
1069 ASSERT(apu);
1070
1071 apu->elapsed_cycles = 0;
1072 memset(&apu->queue, 0, APUQUEUE_SIZE * sizeof(apudata_t));
1073 apu->q_head = 0;
1074 apu->q_tail = 0;
1075
1076 /* use to avoid bugs =) */
1077 for (address = 0x4000; address <= 0x4013; address++)
1078 apu_regwrite(address, 0);
1079
1080 #ifdef NSF_PLAYER
1081 apu_regwrite(0x400C, 0x10); /* silence noise channel on NSF start */
1082 apu_regwrite(0x4015, 0x0F);
1083 #else
1084 apu_regwrite(0x4015, 0);
1085 #endif /* NSF_PLAYER */
1086
1087 if (apu->ext)
1088 apu->ext->reset();
1089 }
1090
apu_build_luts(int num_samples)1091 void apu_build_luts(int num_samples)
1092 {
1093 int i;
1094
1095 /* lut used for enveloping and frequency sweeps */
1096 for (i = 0; i < 16; i++)
1097 decay_lut[i] = num_samples * (i + 1);
1098
1099 /* used for note length, based on vblanks and size of audio buffer */
1100 for (i = 0; i < 32; i++)
1101 vbl_lut[i] = vbl_length[i] * num_samples;
1102
1103 /* triangle wave channel's linear length table */
1104 for (i = 0; i < 128; i++)
1105 trilength_lut[i] = (i * num_samples) / 4;
1106
1107 #ifndef REALTIME_NOISE
1108 /* generate noise samples */
1109 shift_register15(noise_long_lut, APU_NOISE_32K);
1110 shift_register15(noise_short_lut, APU_NOISE_93);
1111 #endif /* !REALTIME_NOISE */
1112 }
1113
apu_setactive(apu_t * active)1114 static void apu_setactive(apu_t *active)
1115 {
1116 ASSERT(active);
1117 apu = active;
1118 }
1119
1120 /* Initializes emulated sound hardware, creates waveforms/voices */
apu_create(int sample_rate,int refresh_rate,int sample_bits,boolean stereo)1121 apu_t *apu_create(int sample_rate, int refresh_rate, int sample_bits, boolean stereo)
1122 {
1123 apu_t *temp_apu;
1124 /* int channel; */
1125
1126 temp_apu = malloc(sizeof(apu_t));
1127 if (NULL == temp_apu)
1128 return NULL;
1129 /* $$$ ben : safety net, in case we forgot to init something */
1130 memset(temp_apu,0,sizeof(apu_t));
1131
1132 SET_APU_ERROR(temp_apu,"no error");
1133 temp_apu->sample_rate = sample_rate;
1134 temp_apu->refresh_rate = refresh_rate;
1135 temp_apu->sample_bits = sample_bits;
1136
1137 temp_apu->num_samples = sample_rate / refresh_rate;
1138 /* turn into fixed point! */
1139 temp_apu->cycle_rate = (int32) (APU_BASEFREQ * 65536.0 / (float) sample_rate);
1140
1141 /* build various lookup tables for apu */
1142 apu_build_luts(temp_apu->num_samples);
1143
1144 /* set the update routine */
1145 temp_apu->process = apu_process;
1146 temp_apu->ext = NULL;
1147
1148 apu_setactive(temp_apu);
1149 apu_reset();
1150
1151 temp_apu->mix_enable = 0x3F;
1152 /* for (channel = 0; channel < 6; channel++) */
1153 /* apu_setchan(channel, TRUE); */
1154
1155 apu_setfilter(APU_FILTER_LOWPASS);
1156
1157 return temp_apu;
1158 }
1159
apu_getcontext(void)1160 apu_t *apu_getcontext(void)
1161 {
1162 return apu;
1163 }
1164
apu_destroy(apu_t * src_apu)1165 void apu_destroy(apu_t *src_apu)
1166 {
1167 if (src_apu)
1168 {
1169 if (src_apu->ext)
1170 src_apu->ext->shutdown();
1171 free(src_apu);
1172 }
1173 }
1174
apu_setext(apu_t * src_apu,apuext_t * ext)1175 int apu_setext(apu_t *src_apu, apuext_t *ext)
1176 {
1177 ASSERT(src_apu);
1178
1179 /* $$$ ben : seem cleaner like this */
1180 if (src_apu->ext) {
1181 src_apu->ext->shutdown();
1182 }
1183
1184 src_apu->ext = ext;
1185
1186 /* initialize it */
1187 if (src_apu->ext)
1188 src_apu->ext->init();
1189
1190 /* $$$ ben : May be one day extension int () will return error code */
1191 return 0;
1192 }
1193
1194 /* this exists for external mixing routines */
apu_getcyclerate(void)1195 int32 apu_getcyclerate(void)
1196 {
1197 ASSERT(apu);
1198 return apu->cycle_rate;
1199 }
1200
1201 /*
1202 ** $Log: nes_apu.c,v $
1203 ** Revision 1.2 2003/04/09 14:50:32 ben
1204 ** Clean NSF api.
1205 **
1206 ** Revision 1.1 2003/04/08 20:53:01 ben
1207 ** Adding more files...
1208 **
1209 ** Revision 1.19 2000/07/04 04:53:26 matt
1210 ** minor changes, sound amplification
1211 **
1212 ** Revision 1.18 2000/07/03 02:18:53 matt
1213 ** much better external module exporting
1214 **
1215 ** Revision 1.17 2000/06/26 11:01:55 matt
1216 ** made triangle a tad quieter
1217 **
1218 ** Revision 1.16 2000/06/26 05:10:33 matt
1219 ** fixed cycle rate generation accuracy
1220 **
1221 ** Revision 1.15 2000/06/26 05:00:37 matt
1222 ** cleanups
1223 **
1224 ** Revision 1.14 2000/06/23 11:06:24 matt
1225 ** more faithful mixing of channels
1226 **
1227 ** Revision 1.13 2000/06/23 03:29:27 matt
1228 ** cleaned up external sound inteface
1229 **
1230 ** Revision 1.12 2000/06/20 00:08:39 matt
1231 ** bugfix to rectangle wave
1232 **
1233 ** Revision 1.11 2000/06/13 13:48:58 matt
1234 ** fixed triangle write latency for fixed point apu cycle rate
1235 **
1236 ** Revision 1.10 2000/06/12 01:14:36 matt
1237 ** minor change to clipping extents
1238 **
1239 ** Revision 1.9 2000/06/09 20:00:56 matt
1240 ** fixed noise hiccup in NSF player mode
1241 **
1242 ** Revision 1.8 2000/06/09 16:49:02 matt
1243 ** removed all floating point from sound generation
1244 **
1245 ** Revision 1.7 2000/06/09 15:12:28 matt
1246 ** initial revision
1247 **
1248 */
1249