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