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