~oah-dev/oah/gst-plugins-bad

« back to all changes in this revision

Viewing changes to gst/nsf/nes_apu.c

  • Committer: Haakon Sporsheim
  • Date: 2009-03-12 13:52:03 UTC
  • Revision ID: haakon.sporsheim@tandberg.com-20090312135203-i5k294hgkushb0mt
Initial import of git repository: git://anongit.freedesktop.org/gstreamer/gst-plugins-bad (tag: RELEASE-0_10_10)

Show diffs side-by-side

added added

removed removed

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