~ubuntu-branches/debian/sid/mame/sid

« back to all changes in this revision

Viewing changes to mess/src/emu/sound/ymz280b.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 
3
 
 Yamaha YMZ280B driver
4
 
  by Aaron Giles
5
 
 
6
 
  YMZ280B 8-Channel PCMD8 PCM/ADPCM Decoder
7
 
 
8
 
 Features as listed in LSI-4MZ280B3 data sheet:
9
 
  Voice data stored in external memory can be played back simultaneously for up to eight voices
10
 
  Voice data format can be selected from 4-bit ADPCM, 8-bit PCM and 16-bit PCM
11
 
  Control of voice data external memory
12
 
   Up to 16M bytes of ROM or SRAM (x 8 bits, access time 150ms max) can be connected
13
 
   Continuous access is possible
14
 
   Loop playback between selective addresses is possible
15
 
  Voice data playback frequency control
16
 
   4-bit ADPCM ................ 0.172 to 44.1kHz in 256 steps
17
 
   8-bit PCM, 16-bit PCM ...... 0.172 to 88.2kHz in 512 steps
18
 
  256 steps total level and 16 steps panpot can be set
19
 
  Voice signal is output in stereo 16-bit 2's complement MSB-first format
20
 
 
21
 
*/
22
 
 
23
 
 
24
 
#include "emu.h"
25
 
#include "ymz280b.h"
26
 
 
27
 
 
28
 
#define MAX_SAMPLE_CHUNK        10000
29
 
#define MAKE_WAVS                       0
30
 
 
31
 
#define FRAC_BITS                       14
32
 
#define FRAC_ONE                        (1 << FRAC_BITS)
33
 
#define FRAC_MASK                       (FRAC_ONE - 1)
34
 
 
35
 
#define INTERNAL_BUFFER_SIZE    (1 << 15)
36
 
#define INTERNAL_SAMPLE_RATE    (chip->master_clock * 2.0)
37
 
 
38
 
#if MAKE_WAVS
39
 
#include "wavwrite.h"
40
 
#endif
41
 
 
42
 
 
43
 
/* struct describing a single playing ADPCM voice */
44
 
struct YMZ280BVoice
45
 
{
46
 
        UINT8 playing;                  /* 1 if we are actively playing */
47
 
 
48
 
        UINT8 keyon;                    /* 1 if the key is on */
49
 
        UINT8 looping;                  /* 1 if looping is enabled */
50
 
        UINT8 mode;                             /* current playback mode */
51
 
        UINT16 fnum;                    /* frequency */
52
 
        UINT8 level;                    /* output level */
53
 
        UINT8 pan;                              /* panning */
54
 
 
55
 
        UINT32 start;                   /* start address, in nibbles */
56
 
        UINT32 stop;                    /* stop address, in nibbles */
57
 
        UINT32 loop_start;              /* loop start address, in nibbles */
58
 
        UINT32 loop_end;                /* loop end address, in nibbles */
59
 
        UINT32 position;                /* current position, in nibbles */
60
 
 
61
 
        INT32 signal;                   /* current ADPCM signal */
62
 
        INT32 step;                             /* current ADPCM step */
63
 
 
64
 
        INT32 loop_signal;              /* signal at loop start */
65
 
        INT32 loop_step;                /* step at loop start */
66
 
        UINT32 loop_count;              /* number of loops so far */
67
 
 
68
 
        INT32 output_left;              /* output volume (left) */
69
 
        INT32 output_right;             /* output volume (right) */
70
 
        INT32 output_step;              /* step value for frequency conversion */
71
 
        INT32 output_pos;               /* current fractional position */
72
 
        INT16 last_sample;              /* last sample output */
73
 
        INT16 curr_sample;              /* current sample target */
74
 
        UINT8 irq_schedule;             /* 1 if the IRQ state is updated by timer */
75
 
};
76
 
 
77
 
typedef struct _ymz280b_state ymz280b_state;
78
 
struct _ymz280b_state
79
 
{
80
 
        sound_stream * stream;                  /* which stream are we using */
81
 
        UINT8 *region_base;                             /* pointer to the base of the region */
82
 
        UINT8 current_register;                 /* currently accessible register */
83
 
        UINT8 status_register;                  /* current status register */
84
 
        UINT8 irq_state;                                /* current IRQ state */
85
 
        UINT8 irq_mask;                                 /* current IRQ mask */
86
 
        UINT8 irq_enable;                               /* current IRQ enable */
87
 
        UINT8 keyon_enable;                             /* key on enable */
88
 
        double master_clock;                    /* master clock frequency */
89
 
        void (*irq_callback)(device_t *, int);          /* IRQ callback */
90
 
        struct YMZ280BVoice     voice[8];       /* the 8 voices */
91
 
        UINT32 rom_readback_addr;               /* where the CPU can read the ROM */
92
 
        devcb_resolved_read8 ext_ram_read;              /* external RAM read handler */
93
 
        devcb_resolved_write8 ext_ram_write;    /* external RAM write handler */
94
 
 
95
 
#if MAKE_WAVS
96
 
        void *          wavresample;                    /* resampled waveform */
97
 
#endif
98
 
 
99
 
        INT16 *scratch;
100
 
        device_t *device;
101
 
};
102
 
 
103
 
/* step size index shift table */
104
 
static const int index_scale[8] = { 0x0e6, 0x0e6, 0x0e6, 0x0e6, 0x133, 0x199, 0x200, 0x266 };
105
 
 
106
 
/* lookup table for the precomputed difference */
107
 
static int diff_lookup[16];
108
 
 
109
 
/* timer callback */
110
 
static TIMER_CALLBACK( update_irq_state_timer_0 );
111
 
static TIMER_CALLBACK( update_irq_state_timer_1 );
112
 
static TIMER_CALLBACK( update_irq_state_timer_2 );
113
 
static TIMER_CALLBACK( update_irq_state_timer_3 );
114
 
static TIMER_CALLBACK( update_irq_state_timer_4 );
115
 
static TIMER_CALLBACK( update_irq_state_timer_5 );
116
 
static TIMER_CALLBACK( update_irq_state_timer_6 );
117
 
static TIMER_CALLBACK( update_irq_state_timer_7 );
118
 
 
119
 
static const struct { timer_expired_func func; const char *name; } update_irq_state_cb[] =
120
 
{
121
 
        { FUNC(update_irq_state_timer_0) },
122
 
        { FUNC(update_irq_state_timer_1) },
123
 
        { FUNC(update_irq_state_timer_2) },
124
 
        { FUNC(update_irq_state_timer_3) },
125
 
        { FUNC(update_irq_state_timer_4) },
126
 
        { FUNC(update_irq_state_timer_5) },
127
 
        { FUNC(update_irq_state_timer_6) },
128
 
        { FUNC(update_irq_state_timer_7) }
129
 
};
130
 
 
131
 
 
132
 
INLINE ymz280b_state *get_safe_token(device_t *device)
133
 
{
134
 
        assert(device != NULL);
135
 
        assert(device->type() == YMZ280B);
136
 
        return (ymz280b_state *)downcast<legacy_device_base *>(device)->token();
137
 
}
138
 
 
139
 
 
140
 
INLINE void update_irq_state(ymz280b_state *chip)
141
 
{
142
 
        int irq_bits = chip->status_register & chip->irq_mask;
143
 
 
144
 
        /* always off if the enable is off */
145
 
        if (!chip->irq_enable)
146
 
                irq_bits = 0;
147
 
 
148
 
        /* update the state if changed */
149
 
        if (irq_bits && !chip->irq_state)
150
 
        {
151
 
                chip->irq_state = 1;
152
 
                if (chip->irq_callback)
153
 
                        (*chip->irq_callback)(chip->device, 1);
154
 
                else logerror("YMZ280B: IRQ generated, but no callback specified!");
155
 
        }
156
 
        else if (!irq_bits && chip->irq_state)
157
 
        {
158
 
                chip->irq_state = 0;
159
 
                if (chip->irq_callback)
160
 
                        (*chip->irq_callback)(chip->device, 0);
161
 
                else logerror("YMZ280B: IRQ generated, but no callback specified!");
162
 
        }
163
 
}
164
 
 
165
 
 
166
 
INLINE void update_step(ymz280b_state *chip, struct YMZ280BVoice *voice)
167
 
{
168
 
        double frequency;
169
 
 
170
 
        /* compute the frequency */
171
 
        if (voice->mode == 1)
172
 
                frequency = chip->master_clock * (double)((voice->fnum & 0x0ff) + 1) * (1.0 / 256.0);
173
 
        else
174
 
                frequency = chip->master_clock * (double)((voice->fnum & 0x1ff) + 1) * (1.0 / 256.0);
175
 
        voice->output_step = (UINT32)(frequency * (double)FRAC_ONE / INTERNAL_SAMPLE_RATE);
176
 
}
177
 
 
178
 
 
179
 
INLINE void update_volumes(struct YMZ280BVoice *voice)
180
 
{
181
 
        if (voice->pan == 8)
182
 
        {
183
 
                voice->output_left = voice->level;
184
 
                voice->output_right = voice->level;
185
 
        }
186
 
        else if (voice->pan < 8)
187
 
        {
188
 
                voice->output_left = voice->level;
189
 
                voice->output_right = voice->level * voice->pan / 8;
190
 
        }
191
 
        else
192
 
        {
193
 
                voice->output_left = voice->level * (15 - voice->pan) / 8;
194
 
                voice->output_right = voice->level;
195
 
        }
196
 
}
197
 
 
198
 
 
199
 
static void YMZ280B_state_save_update_step(ymz280b_state *chip)
200
 
{
201
 
        int j;
202
 
        for (j = 0; j < 8; j++)
203
 
        {
204
 
                struct YMZ280BVoice *voice = &chip->voice[j];
205
 
                update_step(chip, voice);
206
 
                if(voice->irq_schedule)
207
 
                        chip->device->machine().scheduler().timer_set(attotime::zero, update_irq_state_cb[j].func, update_irq_state_cb[j].name, 0, chip);
208
 
        }
209
 
}
210
 
 
211
 
 
212
 
static void update_irq_state_timer_common(void *param, int voicenum)
213
 
{
214
 
        ymz280b_state *chip = (ymz280b_state *)param;
215
 
        struct YMZ280BVoice *voice = &chip->voice[voicenum];
216
 
 
217
 
        if(!voice->irq_schedule) return;
218
 
 
219
 
        voice->playing = 0;
220
 
        chip->status_register |= 1 << voicenum;
221
 
        update_irq_state(chip);
222
 
        voice->irq_schedule = 0;
223
 
}
224
 
 
225
 
static TIMER_CALLBACK( update_irq_state_timer_0 ) { update_irq_state_timer_common(ptr, 0); }
226
 
static TIMER_CALLBACK( update_irq_state_timer_1 ) { update_irq_state_timer_common(ptr, 1); }
227
 
static TIMER_CALLBACK( update_irq_state_timer_2 ) { update_irq_state_timer_common(ptr, 2); }
228
 
static TIMER_CALLBACK( update_irq_state_timer_3 ) { update_irq_state_timer_common(ptr, 3); }
229
 
static TIMER_CALLBACK( update_irq_state_timer_4 ) { update_irq_state_timer_common(ptr, 4); }
230
 
static TIMER_CALLBACK( update_irq_state_timer_5 ) { update_irq_state_timer_common(ptr, 5); }
231
 
static TIMER_CALLBACK( update_irq_state_timer_6 ) { update_irq_state_timer_common(ptr, 6); }
232
 
static TIMER_CALLBACK( update_irq_state_timer_7 ) { update_irq_state_timer_common(ptr, 7); }
233
 
 
234
 
 
235
 
/**********************************************************************************************
236
 
 
237
 
     compute_tables -- compute the difference tables
238
 
 
239
 
***********************************************************************************************/
240
 
 
241
 
static void compute_tables(void)
242
 
{
243
 
        int nib;
244
 
 
245
 
        /* loop over all nibbles and compute the difference */
246
 
        for (nib = 0; nib < 16; nib++)
247
 
        {
248
 
                int value = (nib & 0x07) * 2 + 1;
249
 
                diff_lookup[nib] = (nib & 0x08) ? -value : value;
250
 
        }
251
 
}
252
 
 
253
 
 
254
 
 
255
 
/**********************************************************************************************
256
 
 
257
 
     generate_adpcm -- general ADPCM decoding routine
258
 
 
259
 
***********************************************************************************************/
260
 
 
261
 
static int generate_adpcm(struct YMZ280BVoice *voice, UINT8 *base, INT16 *buffer, int samples)
262
 
{
263
 
        int position = voice->position;
264
 
        int signal = voice->signal;
265
 
        int step = voice->step;
266
 
        int val;
267
 
 
268
 
        /* two cases: first cases is non-looping */
269
 
        if (!voice->looping)
270
 
        {
271
 
                /* loop while we still have samples to generate */
272
 
                while (samples)
273
 
                {
274
 
                        /* compute the new amplitude and update the current step */
275
 
                        val = base[position / 2] >> ((~position & 1) << 2);
276
 
                        signal += (step * diff_lookup[val & 15]) / 8;
277
 
 
278
 
                        /* clamp to the maximum */
279
 
                        if (signal > 32767)
280
 
                                signal = 32767;
281
 
                        else if (signal < -32768)
282
 
                                signal = -32768;
283
 
 
284
 
                        /* adjust the step size and clamp */
285
 
                        step = (step * index_scale[val & 7]) >> 8;
286
 
                        if (step > 0x6000)
287
 
                                step = 0x6000;
288
 
                        else if (step < 0x7f)
289
 
                                step = 0x7f;
290
 
 
291
 
                        /* output to the buffer, scaling by the volume */
292
 
                        *buffer++ = signal;
293
 
                        samples--;
294
 
 
295
 
                        /* next! */
296
 
                        position++;
297
 
                        if (position >= voice->stop)
298
 
                                break;
299
 
                }
300
 
        }
301
 
 
302
 
        /* second case: looping */
303
 
        else
304
 
        {
305
 
                /* loop while we still have samples to generate */
306
 
                while (samples)
307
 
                {
308
 
                        /* compute the new amplitude and update the current step */
309
 
                        val = base[position / 2] >> ((~position & 1) << 2);
310
 
                        signal += (step * diff_lookup[val & 15]) / 8;
311
 
 
312
 
                        /* clamp to the maximum */
313
 
                        if (signal > 32767)
314
 
                                signal = 32767;
315
 
                        else if (signal < -32768)
316
 
                                signal = -32768;
317
 
 
318
 
                        /* adjust the step size and clamp */
319
 
                        step = (step * index_scale[val & 7]) >> 8;
320
 
                        if (step > 0x6000)
321
 
                                step = 0x6000;
322
 
                        else if (step < 0x7f)
323
 
                                step = 0x7f;
324
 
 
325
 
                        /* output to the buffer, scaling by the volume */
326
 
                        *buffer++ = signal;
327
 
                        samples--;
328
 
 
329
 
                        /* next! */
330
 
                        position++;
331
 
                        if (position == voice->loop_start && voice->loop_count == 0)
332
 
                        {
333
 
                                voice->loop_signal = signal;
334
 
                                voice->loop_step = step;
335
 
                        }
336
 
                        if (position >= voice->loop_end)
337
 
                        {
338
 
                                if (voice->keyon)
339
 
                                {
340
 
                                        position = voice->loop_start;
341
 
                                        signal = voice->loop_signal;
342
 
                                        step = voice->loop_step;
343
 
                                        voice->loop_count++;
344
 
                                }
345
 
                        }
346
 
                        if (position >= voice->stop)
347
 
                                break;
348
 
                }
349
 
        }
350
 
 
351
 
        /* update the parameters */
352
 
        voice->position = position;
353
 
        voice->signal = signal;
354
 
        voice->step = step;
355
 
 
356
 
        return samples;
357
 
}
358
 
 
359
 
 
360
 
 
361
 
/**********************************************************************************************
362
 
 
363
 
     generate_pcm8 -- general 8-bit PCM decoding routine
364
 
 
365
 
***********************************************************************************************/
366
 
 
367
 
static int generate_pcm8(struct YMZ280BVoice *voice, UINT8 *base, INT16 *buffer, int samples)
368
 
{
369
 
        int position = voice->position;
370
 
        int val;
371
 
 
372
 
        /* two cases: first cases is non-looping */
373
 
        if (!voice->looping)
374
 
        {
375
 
                /* loop while we still have samples to generate */
376
 
                while (samples)
377
 
                {
378
 
                        /* fetch the current value */
379
 
                        val = base[position / 2];
380
 
 
381
 
                        /* output to the buffer, scaling by the volume */
382
 
                        *buffer++ = (INT8)val * 256;
383
 
                        samples--;
384
 
 
385
 
                        /* next! */
386
 
                        position += 2;
387
 
                        if (position >= voice->stop)
388
 
                                break;
389
 
                }
390
 
        }
391
 
 
392
 
        /* second case: looping */
393
 
        else
394
 
        {
395
 
                /* loop while we still have samples to generate */
396
 
                while (samples)
397
 
                {
398
 
                        /* fetch the current value */
399
 
                        val = base[position / 2];
400
 
 
401
 
                        /* output to the buffer, scaling by the volume */
402
 
                        *buffer++ = (INT8)val * 256;
403
 
                        samples--;
404
 
 
405
 
                        /* next! */
406
 
                        position += 2;
407
 
                        if (position >= voice->loop_end)
408
 
                        {
409
 
                                if (voice->keyon)
410
 
                                        position = voice->loop_start;
411
 
                        }
412
 
                        if (position >= voice->stop)
413
 
                                break;
414
 
                }
415
 
        }
416
 
 
417
 
        /* update the parameters */
418
 
        voice->position = position;
419
 
 
420
 
        return samples;
421
 
}
422
 
 
423
 
 
424
 
 
425
 
/**********************************************************************************************
426
 
 
427
 
     generate_pcm16 -- general 16-bit PCM decoding routine
428
 
 
429
 
***********************************************************************************************/
430
 
 
431
 
static int generate_pcm16(struct YMZ280BVoice *voice, UINT8 *base, INT16 *buffer, int samples)
432
 
{
433
 
        int position = voice->position;
434
 
        int val;
435
 
 
436
 
        /* two cases: first cases is non-looping */
437
 
        if (!voice->looping)
438
 
        {
439
 
                /* loop while we still have samples to generate */
440
 
                while (samples)
441
 
                {
442
 
                        /* fetch the current value */
443
 
                        val = (INT16)((base[position / 2 + 1] << 8) + base[position / 2]);
444
 
 
445
 
                        /* output to the buffer, scaling by the volume */
446
 
                        *buffer++ = val;
447
 
                        samples--;
448
 
 
449
 
                        /* next! */
450
 
                        position += 4;
451
 
                        if (position >= voice->stop)
452
 
                                break;
453
 
                }
454
 
        }
455
 
 
456
 
        /* second case: looping */
457
 
        else
458
 
        {
459
 
                /* loop while we still have samples to generate */
460
 
                while (samples)
461
 
                {
462
 
                        /* fetch the current value */
463
 
                        val = (INT16)((base[position / 2 + 1] << 8) + base[position / 2]);
464
 
 
465
 
                        /* output to the buffer, scaling by the volume */
466
 
                        *buffer++ = val;
467
 
                        samples--;
468
 
 
469
 
                        /* next! */
470
 
                        position += 4;
471
 
                        if (position >= voice->loop_end)
472
 
                        {
473
 
                                if (voice->keyon)
474
 
                                        position = voice->loop_start;
475
 
                        }
476
 
                        if (position >= voice->stop)
477
 
                                break;
478
 
                }
479
 
        }
480
 
 
481
 
        /* update the parameters */
482
 
        voice->position = position;
483
 
 
484
 
        return samples;
485
 
}
486
 
 
487
 
 
488
 
 
489
 
/**********************************************************************************************
490
 
 
491
 
     ymz280b_update -- update the sound chip so that it is in sync with CPU execution
492
 
 
493
 
***********************************************************************************************/
494
 
 
495
 
static STREAM_UPDATE( ymz280b_update )
496
 
{
497
 
        ymz280b_state *chip = (ymz280b_state *)param;
498
 
        stream_sample_t *lacc = outputs[0];
499
 
        stream_sample_t *racc = outputs[1];
500
 
        int v;
501
 
 
502
 
        /* clear out the accumulator */
503
 
        memset(lacc, 0, samples * sizeof(lacc[0]));
504
 
        memset(racc, 0, samples * sizeof(racc[0]));
505
 
 
506
 
        /* loop over voices */
507
 
        for (v = 0; v < 8; v++)
508
 
        {
509
 
                struct YMZ280BVoice *voice = &chip->voice[v];
510
 
                INT16 prev = voice->last_sample;
511
 
                INT16 curr = voice->curr_sample;
512
 
                INT16 *curr_data = chip->scratch;
513
 
                INT32 *ldest = lacc;
514
 
                INT32 *rdest = racc;
515
 
                UINT32 new_samples, samples_left;
516
 
                UINT32 final_pos;
517
 
                int remaining = samples;
518
 
                int lvol = voice->output_left;
519
 
                int rvol = voice->output_right;
520
 
 
521
 
                /* quick out if we're not playing and we're at 0 */
522
 
                if (!voice->playing && curr == 0)
523
 
                        continue;
524
 
 
525
 
                /* finish off the current sample */
526
 
//      if (voice->output_pos > 0)
527
 
                {
528
 
                        /* interpolate */
529
 
                        while (remaining > 0 && voice->output_pos < FRAC_ONE)
530
 
                        {
531
 
                                int interp_sample = (((INT32)prev * (FRAC_ONE - voice->output_pos)) + ((INT32)curr * voice->output_pos)) >> FRAC_BITS;
532
 
                                *ldest++ += interp_sample * lvol;
533
 
                                *rdest++ += interp_sample * rvol;
534
 
                                voice->output_pos += voice->output_step;
535
 
                                remaining--;
536
 
                        }
537
 
 
538
 
                        /* if we're over, continue; otherwise, we're done */
539
 
                        if (voice->output_pos >= FRAC_ONE)
540
 
                                voice->output_pos -= FRAC_ONE;
541
 
                        else
542
 
                                continue;
543
 
                }
544
 
 
545
 
                /* compute how many new samples we need */
546
 
                final_pos = voice->output_pos + remaining * voice->output_step;
547
 
                new_samples = (final_pos + FRAC_ONE) >> FRAC_BITS;
548
 
                if (new_samples > MAX_SAMPLE_CHUNK)
549
 
                        new_samples = MAX_SAMPLE_CHUNK;
550
 
                samples_left = new_samples;
551
 
 
552
 
                /* generate them into our buffer */
553
 
                if (voice->playing)
554
 
                {
555
 
                        switch (voice->mode)
556
 
                        {
557
 
                                case 1: samples_left = generate_adpcm(voice, chip->region_base, chip->scratch, new_samples);    break;
558
 
                                case 2: samples_left = generate_pcm8(voice, chip->region_base, chip->scratch, new_samples);     break;
559
 
                                case 3: samples_left = generate_pcm16(voice, chip->region_base, chip->scratch, new_samples);    break;
560
 
                                default:
561
 
                                case 0: samples_left = 0; memset(chip->scratch, 0, new_samples * sizeof(chip->scratch[0]));                     break;
562
 
                        }
563
 
                }
564
 
 
565
 
                /* if there are leftovers, ramp back to 0 */
566
 
                if (samples_left)
567
 
                {
568
 
                        int base = new_samples - samples_left;
569
 
                        int i, t = (base == 0) ? curr : chip->scratch[base - 1];
570
 
                        for (i = 0; i < samples_left; i++)
571
 
                        {
572
 
                                if (t < 0) t = -((-t * 15) >> 4);
573
 
                                else if (t > 0) t = (t * 15) >> 4;
574
 
                                chip->scratch[base + i] = t;
575
 
                        }
576
 
 
577
 
                        /* if we hit the end and IRQs are enabled, signal it */
578
 
                        if (base != 0)
579
 
                        {
580
 
                                voice->playing = 0;
581
 
 
582
 
                                /* set update_irq_state_timer. IRQ is signaled on next CPU execution. */
583
 
                                chip->device->machine().scheduler().timer_set(attotime::zero, update_irq_state_cb[v].func, update_irq_state_cb[v].name, 0, chip);
584
 
                                voice->irq_schedule = 1;
585
 
                        }
586
 
                }
587
 
 
588
 
                /* advance forward one sample */
589
 
                prev = curr;
590
 
                curr = *curr_data++;
591
 
 
592
 
                /* then sample-rate convert with linear interpolation */
593
 
                while (remaining > 0)
594
 
                {
595
 
                        /* interpolate */
596
 
                        while (remaining > 0 && voice->output_pos < FRAC_ONE)
597
 
                        {
598
 
                                int interp_sample = (((INT32)prev * (FRAC_ONE - voice->output_pos)) + ((INT32)curr * voice->output_pos)) >> FRAC_BITS;
599
 
                                *ldest++ += interp_sample * lvol;
600
 
                                *rdest++ += interp_sample * rvol;
601
 
                                voice->output_pos += voice->output_step;
602
 
                                remaining--;
603
 
                        }
604
 
 
605
 
                        /* if we're over, grab the next samples */
606
 
                        if (voice->output_pos >= FRAC_ONE)
607
 
                        {
608
 
                                voice->output_pos -= FRAC_ONE;
609
 
                                prev = curr;
610
 
                                curr = *curr_data++;
611
 
                        }
612
 
                }
613
 
 
614
 
                /* remember the last samples */
615
 
                voice->last_sample = prev;
616
 
                voice->curr_sample = curr;
617
 
        }
618
 
 
619
 
        for (v = 0; v < samples; v++)
620
 
        {
621
 
                outputs[0][v] /= 256;
622
 
                outputs[1][v] /= 256;
623
 
        }
624
 
}
625
 
 
626
 
 
627
 
 
628
 
/**********************************************************************************************
629
 
 
630
 
     DEVICE_START( ymz280b ) -- start emulation of the YMZ280B
631
 
 
632
 
***********************************************************************************************/
633
 
 
634
 
static DEVICE_START( ymz280b )
635
 
{
636
 
        static const ymz280b_interface defintrf = { 0 };
637
 
        const ymz280b_interface *intf = (device->static_config() != NULL) ? (const ymz280b_interface *)device->static_config() : &defintrf;
638
 
        ymz280b_state *chip = get_safe_token(device);
639
 
 
640
 
        chip->device = device;
641
 
        chip->ext_ram_read.resolve(intf->ext_read, *device);
642
 
        chip->ext_ram_write.resolve(intf->ext_write, *device);
643
 
 
644
 
        /* compute ADPCM tables */
645
 
        compute_tables();
646
 
 
647
 
        /* initialize the rest of the structure */
648
 
        chip->master_clock = (double)device->clock() / 384.0;
649
 
        chip->region_base = *device->region();
650
 
        chip->irq_callback = intf->irq_callback;
651
 
 
652
 
        /* create the stream */
653
 
        chip->stream = device->machine().sound().stream_alloc(*device, 0, 2, INTERNAL_SAMPLE_RATE, chip, ymz280b_update);
654
 
 
655
 
        /* allocate memory */
656
 
        chip->scratch = auto_alloc_array(device->machine(), INT16, MAX_SAMPLE_CHUNK);
657
 
 
658
 
        /* state save */
659
 
        {
660
 
                int j;
661
 
                device->save_item(NAME(chip->current_register));
662
 
                device->save_item(NAME(chip->status_register));
663
 
                device->save_item(NAME(chip->irq_state));
664
 
                device->save_item(NAME(chip->irq_mask));
665
 
                device->save_item(NAME(chip->irq_enable));
666
 
                device->save_item(NAME(chip->keyon_enable));
667
 
                device->save_item(NAME(chip->rom_readback_addr));
668
 
                for (j = 0; j < 8; j++)
669
 
                {
670
 
                        device->save_item(NAME(chip->voice[j].playing), j);
671
 
                        device->save_item(NAME(chip->voice[j].keyon), j);
672
 
                        device->save_item(NAME(chip->voice[j].looping), j);
673
 
                        device->save_item(NAME(chip->voice[j].mode), j);
674
 
                        device->save_item(NAME(chip->voice[j].fnum), j);
675
 
                        device->save_item(NAME(chip->voice[j].level), j);
676
 
                        device->save_item(NAME(chip->voice[j].pan), j);
677
 
                        device->save_item(NAME(chip->voice[j].start), j);
678
 
                        device->save_item(NAME(chip->voice[j].stop), j);
679
 
                        device->save_item(NAME(chip->voice[j].loop_start), j);
680
 
                        device->save_item(NAME(chip->voice[j].loop_end), j);
681
 
                        device->save_item(NAME(chip->voice[j].position), j);
682
 
                        device->save_item(NAME(chip->voice[j].signal), j);
683
 
                        device->save_item(NAME(chip->voice[j].step), j);
684
 
                        device->save_item(NAME(chip->voice[j].loop_signal), j);
685
 
                        device->save_item(NAME(chip->voice[j].loop_step), j);
686
 
                        device->save_item(NAME(chip->voice[j].loop_count), j);
687
 
                        device->save_item(NAME(chip->voice[j].output_left), j);
688
 
                        device->save_item(NAME(chip->voice[j].output_right), j);
689
 
                        device->save_item(NAME(chip->voice[j].output_pos), j);
690
 
                        device->save_item(NAME(chip->voice[j].last_sample), j);
691
 
                        device->save_item(NAME(chip->voice[j].curr_sample), j);
692
 
                        device->save_item(NAME(chip->voice[j].irq_schedule), j);
693
 
                }
694
 
        }
695
 
 
696
 
        device->machine().save().register_postload(save_prepost_delegate(FUNC(YMZ280B_state_save_update_step), chip));
697
 
 
698
 
#if MAKE_WAVS
699
 
        chip->wavresample = wav_open("resamp.wav", INTERNAL_SAMPLE_RATE, 2);
700
 
#endif
701
 
}
702
 
 
703
 
 
704
 
 
705
 
/**********************************************************************************************
706
 
 
707
 
     write_to_register -- handle a write to the current register
708
 
 
709
 
***********************************************************************************************/
710
 
 
711
 
static void write_to_register(ymz280b_state *chip, int data)
712
 
{
713
 
        struct YMZ280BVoice *voice;
714
 
        int i;
715
 
 
716
 
        /* force an update */
717
 
        chip->stream->update();
718
 
 
719
 
        /* lower registers follow a pattern */
720
 
        if (chip->current_register < 0x80)
721
 
        {
722
 
                voice = &chip->voice[(chip->current_register >> 2) & 7];
723
 
 
724
 
                switch (chip->current_register & 0xe3)
725
 
                {
726
 
                        case 0x00:              /* pitch low 8 bits */
727
 
                                voice->fnum = (voice->fnum & 0x100) | (data & 0xff);
728
 
                                update_step(chip, voice);
729
 
                                break;
730
 
 
731
 
                        case 0x01:              /* pitch upper 1 bit, loop, key on, mode */
732
 
                                voice->fnum = (voice->fnum & 0xff) | ((data & 0x01) << 8);
733
 
                                voice->looping = (data & 0x10) >> 4;
734
 
                                voice->mode = (data & 0x60) >> 5;
735
 
                                if (!voice->keyon && (data & 0x80) && chip->keyon_enable)
736
 
                                {
737
 
                                        voice->playing = 1;
738
 
                                        voice->position = voice->start;
739
 
                                        voice->signal = voice->loop_signal = 0;
740
 
                                        voice->step = voice->loop_step = 0x7f;
741
 
                                        voice->loop_count = 0;
742
 
 
743
 
                                        /* if update_irq_state_timer is set, cancel it. */
744
 
                                        voice->irq_schedule = 0;
745
 
                                }
746
 
                                if (voice->keyon && !(data & 0x80) && !voice->looping)
747
 
                                {
748
 
                                        voice->playing = 0;
749
 
 
750
 
                                        /* if update_irq_state_timer is set, cancel it. */
751
 
                                        voice->irq_schedule = 0;
752
 
                                }
753
 
                                voice->keyon = (data & 0x80) >> 7;
754
 
                                update_step(chip, voice);
755
 
                                break;
756
 
 
757
 
                        case 0x02:              /* total level */
758
 
                                voice->level = data;
759
 
                                update_volumes(voice);
760
 
                                break;
761
 
 
762
 
                        case 0x03:              /* pan */
763
 
                                voice->pan = data & 0x0f;
764
 
                                update_volumes(voice);
765
 
                                break;
766
 
 
767
 
                        case 0x20:              /* start address high */
768
 
                                voice->start = (voice->start & (0x00ffff << 1)) | (data << 17);
769
 
                                break;
770
 
 
771
 
                        case 0x21:              /* loop start address high */
772
 
                                voice->loop_start = (voice->loop_start & (0x00ffff << 1)) | (data << 17);
773
 
                                break;
774
 
 
775
 
                        case 0x22:              /* loop end address high */
776
 
                                voice->loop_end = (voice->loop_end & (0x00ffff << 1)) | (data << 17);
777
 
                                break;
778
 
 
779
 
                        case 0x23:              /* stop address high */
780
 
                                voice->stop = (voice->stop & (0x00ffff << 1)) | (data << 17);
781
 
                                break;
782
 
 
783
 
                        case 0x40:              /* start address middle */
784
 
                                voice->start = (voice->start & (0xff00ff << 1)) | (data << 9);
785
 
                                break;
786
 
 
787
 
                        case 0x41:              /* loop start address middle */
788
 
                                voice->loop_start = (voice->loop_start & (0xff00ff << 1)) | (data << 9);
789
 
                                break;
790
 
 
791
 
                        case 0x42:              /* loop end address middle */
792
 
                                voice->loop_end = (voice->loop_end & (0xff00ff << 1)) | (data << 9);
793
 
                                break;
794
 
 
795
 
                        case 0x43:              /* stop address middle */
796
 
                                voice->stop = (voice->stop & (0xff00ff << 1)) | (data << 9);
797
 
                                break;
798
 
 
799
 
                        case 0x60:              /* start address low */
800
 
                                voice->start = (voice->start & (0xffff00 << 1)) | (data << 1);
801
 
                                break;
802
 
 
803
 
                        case 0x61:              /* loop start address low */
804
 
                                voice->loop_start = (voice->loop_start & (0xffff00 << 1)) | (data << 1);
805
 
                                break;
806
 
 
807
 
                        case 0x62:              /* loop end address low */
808
 
                                voice->loop_end = (voice->loop_end & (0xffff00 << 1)) | (data << 1);
809
 
                                break;
810
 
 
811
 
                        case 0x63:              /* stop address low */
812
 
                                voice->stop = (voice->stop & (0xffff00 << 1)) | (data << 1);
813
 
                                break;
814
 
 
815
 
                        default:
816
 
                                logerror("YMZ280B: unknown register write %02X = %02X\n", chip->current_register, data);
817
 
                                break;
818
 
                }
819
 
        }
820
 
 
821
 
        /* upper registers are special */
822
 
        else
823
 
        {
824
 
                switch (chip->current_register)
825
 
                {
826
 
                        case 0x84:              /* ROM readback / RAM write (high) */
827
 
                                chip->rom_readback_addr &= 0xffff;
828
 
                                chip->rom_readback_addr |= (data<<16);
829
 
                                break;
830
 
 
831
 
                        case 0x85:              /* ROM readback / RAM write (med) */
832
 
                                chip->rom_readback_addr &= 0xff00ff;
833
 
                                chip->rom_readback_addr |= (data<<8);
834
 
                                break;
835
 
 
836
 
                        case 0x86:              /* ROM readback / RAM write (low) */
837
 
                                chip->rom_readback_addr &= 0xffff00;
838
 
                                chip->rom_readback_addr |= data;
839
 
                                break;
840
 
 
841
 
                        case 0x87:              /* RAM write */
842
 
                                if (!chip->ext_ram_write.isnull())
843
 
                                        chip->ext_ram_write(chip->rom_readback_addr, data);
844
 
                                else
845
 
                                        logerror("YMZ280B attempted RAM write to %X\n", chip->rom_readback_addr);
846
 
                                break;
847
 
 
848
 
                        case 0xfe:              /* IRQ mask */
849
 
                                chip->irq_mask = data;
850
 
                                update_irq_state(chip);
851
 
                                break;
852
 
 
853
 
                        case 0xff:              /* IRQ enable, test, etc */
854
 
                                chip->irq_enable = (data & 0x10) >> 4;
855
 
                                update_irq_state(chip);
856
 
 
857
 
                                if (chip->keyon_enable && !(data & 0x80))
858
 
                                {
859
 
                                        for (i = 0; i < 8; i++)
860
 
                                        {
861
 
                                                chip->voice[i].playing = 0;
862
 
 
863
 
                                                /* if update_irq_state_timer is set, cancel it. */
864
 
                                                chip->voice[i].irq_schedule = 0;
865
 
                                        }
866
 
                                }
867
 
                                else if (!chip->keyon_enable && (data & 0x80))
868
 
                                {
869
 
                                        for (i = 0; i < 8; i++)
870
 
                                        {
871
 
                                                if (chip->voice[i].keyon && chip->voice[i].looping)
872
 
                                                        chip->voice[i].playing = 1;
873
 
                                        }
874
 
                                }
875
 
                                chip->keyon_enable = (data & 0x80) >> 7;
876
 
                                break;
877
 
 
878
 
                        default:
879
 
                                logerror("YMZ280B: unknown register write %02X = %02X\n", chip->current_register, data);
880
 
                                break;
881
 
                }
882
 
        }
883
 
}
884
 
 
885
 
 
886
 
 
887
 
/**********************************************************************************************
888
 
 
889
 
     compute_status -- determine the status bits
890
 
 
891
 
***********************************************************************************************/
892
 
 
893
 
static int compute_status(ymz280b_state *chip)
894
 
{
895
 
        UINT8 result;
896
 
 
897
 
        /* ROM/RAM readback? */
898
 
        if (chip->current_register == 0x86)
899
 
        {
900
 
                return chip->region_base[chip->rom_readback_addr];
901
 
        }
902
 
 
903
 
        /* force an update */
904
 
        chip->stream->update();
905
 
 
906
 
        result = chip->status_register;
907
 
 
908
 
        /* clear the IRQ state */
909
 
        chip->status_register = 0;
910
 
        update_irq_state(chip);
911
 
 
912
 
        return result;
913
 
}
914
 
 
915
 
 
916
 
 
917
 
/**********************************************************************************************
918
 
 
919
 
     ymz280b_status_0_r/ymz280b_status_1_r -- handle a read from the status register
920
 
 
921
 
***********************************************************************************************/
922
 
 
923
 
READ8_DEVICE_HANDLER( ymz280b_r )
924
 
{
925
 
        ymz280b_state *chip = get_safe_token(device);
926
 
 
927
 
        if ((offset & 1) == 0)
928
 
                return chip->ext_ram_read(chip->rom_readback_addr++ - 1);
929
 
        else
930
 
                return compute_status(chip);
931
 
}
932
 
 
933
 
 
934
 
WRITE8_DEVICE_HANDLER( ymz280b_w )
935
 
{
936
 
        ymz280b_state *chip = get_safe_token(device);
937
 
 
938
 
        if ((offset & 1) == 0)
939
 
                chip->current_register = data;
940
 
        else
941
 
                write_to_register(chip, data);
942
 
}
943
 
 
944
 
 
945
 
 
946
 
/**************************************************************************
947
 
 * Generic get_info
948
 
 **************************************************************************/
949
 
 
950
 
DEVICE_GET_INFO( ymz280b )
951
 
{
952
 
        switch (state)
953
 
        {
954
 
                /* --- the following bits of info are returned as 64-bit signed integers --- */
955
 
                case DEVINFO_INT_TOKEN_BYTES:                                   info->i = sizeof(ymz280b_state);                        break;
956
 
 
957
 
                /* --- the following bits of info are returned as pointers to data or functions --- */
958
 
                case DEVINFO_FCT_START:                                                 info->start = DEVICE_START_NAME( ymz280b );             break;
959
 
                case DEVINFO_FCT_STOP:                                                  /* Nothing */                                                                   break;
960
 
                case DEVINFO_FCT_RESET:                                                 /* Nothing */                                                                   break;
961
 
 
962
 
                /* --- the following bits of info are returned as NULL-terminated strings --- */
963
 
                case DEVINFO_STR_NAME:                                                  strcpy(info->s, "YMZ280B");                                             break;
964
 
                case DEVINFO_STR_FAMILY:                                        strcpy(info->s, "Yamaha Wavetable");                    break;
965
 
                case DEVINFO_STR_VERSION:                                       strcpy(info->s, "1.0");                                                 break;
966
 
                case DEVINFO_STR_SOURCE_FILE:                                           strcpy(info->s, __FILE__);                                              break;
967
 
                case DEVINFO_STR_CREDITS:                                       strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
968
 
        }
969
 
}
970
 
 
971
 
 
972
 
DEFINE_LEGACY_SOUND_DEVICE(YMZ280B, ymz280b);