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