1 /***************************************************************************
2 
3 	Cinematronics vector hardware
4 
5 	Special thanks to Neil Bradley, Zonn Moore, and Jeff Mitchell of the
6 	Retrocade Alliance
7 
8 	Update:
9 	6/27/99 Jim Hernandez -- 1st Attempt at Fixing Drone Star Castle sound and
10 	                         pitch adjustments.
11 	6/30/99 MLR added Rip Off, Solar Quest, Armor Attack (no samples yet)
12 
13 	Bugs: Sometimes the death explosion (small explosion) does not trigger.
14 
15 ***************************************************************************/
16 
17 #include "driver.h"
18 #include "machine/z80fmly.h"
19 #include "cinemat.h"
20 
21 
22 static UINT32 current_shift = 0;
23 static UINT32 last_shift = 0;
24 static UINT32 last_shift16= 0;
25 static UINT32 current_pitch = 0x20000;
26 static UINT32 last_frame = 0;
27 
28 static int cinemat_outputs = 0xff;
29 
30 cinemat_sound_handler_proc cinemat_sound_handler;
31 
32 
33 
34 /*************************************
35  *
36  *	General read/write handlers
37  *
38  *************************************/
39 
READ16_HANDLER(cinemat_output_port_r)40 READ16_HANDLER( cinemat_output_port_r )
41 {
42 	return cinemat_outputs;
43 }
44 
45 
WRITE16_HANDLER(cinemat_output_port_w)46 WRITE16_HANDLER( cinemat_output_port_w )
47 {
48 	if ((cinemat_outputs ^ data) & 0x9f)
49 	{
50 		if (cinemat_sound_handler)
51 			cinemat_sound_handler (data & 0x9f, (cinemat_outputs ^ data) & 0x9f);
52 	}
53 
54 	cinemat_outputs = data;
55 }
56 
57 
58 
59 /*************************************
60  *
61  *	Sound reset
62  *
63  *************************************/
64 
MACHINE_INIT(cinemat_sound)65 MACHINE_INIT( cinemat_sound )
66 {
67     current_shift = 0xffff;
68     last_shift = 0xffff;
69     last_shift16 = 0xffff;
70     current_pitch = 0x20000;
71     last_frame = 0;
72 
73 // Pitch the Drone sound will start off at
74 
75 }
76 
cinemat_shift(UINT8 sound_val,UINT8 bits_changed,UINT8 A1,UINT8 CLK)77 static void cinemat_shift(UINT8 sound_val, UINT8 bits_changed, UINT8 A1, UINT8 CLK)
78 {
79 	// See if we're latching a shift
80 
81     if ((bits_changed & CLK) && (0 == (sound_val & CLK)))
82 	{
83 		current_shift <<= 1;
84 		if (sound_val & A1)
85             current_shift |= 1;
86 	}
87 }
88 
89 
90 /*************************************
91  *
92  *	Sundance
93  *
94  *************************************/
95 
96 static const char *sundance_sample_names[] =
97 {
98 	"*sundance",
99 	"bong.wav",
100 	"whoosh.wav",
101 	"explsion.wav",
102 	"ping1.wav",
103 	"ping2.wav",
104 	"hatch.wav",
105 
106     0	/* end of array */
107 };
108 
109 struct Samplesinterface sundance_samples_interface =
110 {
111 	6,	/* 8 channels */
112 	25,	/* volume */
113 	sundance_sample_names
114 };
115 
sundance_sound_w(UINT8 sound_val,UINT8 bits_changed)116 void sundance_sound_w(UINT8 sound_val, UINT8 bits_changed)
117 {
118 
119 if (bits_changed & 0x01) //Bong
120 	{
121 		if (sound_val & 0x01)
122 		{
123 
124                 sample_start(0, 0, 0);
125 
126 		}
127 	}
128 
129 
130 if ((bits_changed & 0x02) && (0 == (sound_val & 0x02)))
131 		sample_start(1, 1, 0);
132 
133 
134 if ((bits_changed & 0x04) && (0 == (sound_val & 0x04)))
135 		sample_start(2, 2, 0);
136 
137 
138 if ((bits_changed & 0x08) && (0 == (sound_val & 0x08)))
139 	        sample_start(3, 3, 0);
140 
141 
142 if ((bits_changed & 0x10) && (0 == (sound_val & 0x10)))
143 	{
144 		sample_start(4, 4, 0);
145 	}
146 
147 
148 if ((bits_changed & 0x80) && (0 == (sound_val & 0x80)))
149 		sample_start(5, 5, 0);
150 
151 }
152 
153 
154 
155 /*************************************
156  *
157  *	Star Castle
158  *
159  *************************************/
160 
161 static const char *starcas_sample_names[] =
162 {
163 	"*starcas",
164 	"lexplode.wav",
165 	"sexplode.wav",
166 	"cfire.wav",
167 	"pfire.wav",
168 	"drone.wav",
169 	"shield.wav",
170 	"star.wav",
171 	"thrust.wav",
172     0	/* end of array */
173 };
174 
175 struct Samplesinterface starcas_samples_interface =
176 {
177 	8,	/* 8 channels */
178 	25,	/* volume */
179 	starcas_sample_names
180 };
181 
starcas_sound_w(UINT8 sound_val,UINT8 bits_changed)182 void starcas_sound_w(UINT8 sound_val, UINT8 bits_changed)
183 {
184     UINT32 target_pitch;
185 	UINT8 shift_diff;
186 
187     cinemat_shift (sound_val, bits_changed, 0x80, 0x10);
188 
189 	// Now see if it's time to act upon the shifted data
190 
191 	if ((bits_changed & 0x01) && (0 == (sound_val & 0x01)))
192 	{
193 		// Yep. Falling edge! Find out what has changed.
194 
195 		shift_diff = current_shift ^ last_shift;
196 
197 		if ((shift_diff & 1) && (0 == (current_shift & 1)))
198 			sample_start(2, 2, 0);	// Castle fire
199 
200 		if ((shift_diff & 2) && (0 == (current_shift & 2)))
201 			sample_start(5, 5, 0);	// Shield hit
202 
203 		if (shift_diff & 0x04)
204 		{
205 			if (current_shift & 0x04)
206 				sample_start(6, 6, 1);	// Star sound
207 			else
208 				sample_stop(6);	// Stop it!
209 		}
210 
211 		if (shift_diff & 0x08)
212 		{
213 			if (current_shift & 0x08)
214 				sample_stop(7);	// Stop it!
215 			else
216 				sample_start(7, 7, 1);	// Thrust sound
217 		}
218 
219 		if (shift_diff & 0x10)
220 		{
221 			if (current_shift & 0x10)
222 				sample_stop(4);
223 			else
224 				sample_start(4, 4, 1);	// Drone
225 		}
226 
227 		// Latch the drone pitch
228 
229         target_pitch = (current_shift & 0x60) >> 3;
230         target_pitch |= ((current_shift & 0x40) >> 5);
231         target_pitch |= ((current_shift & 0x80) >> 7);
232 
233         // target_pitch = (current_shift & 0x60) >> 3;
234         // is the the target drone pitch to rise and stop at.
235 
236         target_pitch = 0x10000 + (target_pitch << 12);
237 
238         // 0x10000 is lowest value the pitch will drop to
239         // Star Castle drone sound
240 
241         if (cpu_getcurrentframe() > last_frame)
242         {
243             if (current_pitch > target_pitch)
244                 current_pitch -= 300;
245             if (current_pitch < target_pitch)
246                 current_pitch += 200;
247             sample_set_freq(4, current_pitch);
248             last_frame = cpu_getcurrentframe();
249         }
250 
251 		last_shift = current_shift;
252 	}
253 
254 	if ((bits_changed & 0x08) && (0 == (sound_val & 0x08)))
255 		sample_start(3, 3, 0);			// Player fire
256 
257 	if ((bits_changed & 0x04) && (0 == (sound_val & 0x04)))
258 		sample_start(1, 1, 0);			// Soft explosion
259 
260 	if ((bits_changed & 0x02) && (0 == (sound_val & 0x02)))
261 		sample_start(0, 0, 0);			// Loud explosion
262 
263 }
264 
265 
266 /*************************************
267  *
268  *	Warrior
269  *
270  *************************************/
271 
272 static const char *warrior_sample_names[] =
273 {
274 	"*warrior",
275 	"appear.wav",
276 	"bgmhum1.wav",
277 	"bgmhum2.wav",
278 	"fall.wav",
279 	"killed.wav",
280     0	/* end of array */
281 };
282 
283 struct Samplesinterface warrior_samples_interface =
284 {
285 	5,	/* 8 channels */
286 	25,	/* volume */
287 	warrior_sample_names
288 };
289 
warrior_sound_w(UINT8 sound_val,UINT8 bits_changed)290 void warrior_sound_w(UINT8 sound_val, UINT8 bits_changed)
291 {
292 
293 	if ((bits_changed & 0x10) && (0 == (sound_val & 0x10)))
294 	{
295 		sample_start(0, 0, 0);			// appear
296 	}
297 
298 	if ((bits_changed & 0x08) && (0 == (sound_val & 0x08)))
299 		sample_start(3, 3, 0);			// fall
300 
301 	if ((bits_changed & 0x04) && (0 == (sound_val & 0x04)))
302 		sample_start(4, 4, 0);			// explosion (kill)
303 
304 	if (bits_changed & 0x02)
305 	{
306 		if ((sound_val & 0x02) == 0)
307 			sample_start(2, 2, 1);			// hi level
308 		else
309 			sample_stop(2);
310 	}
311 
312 	if (bits_changed & 0x01)
313 	{
314 		if ((sound_val & 0x01) == 0)
315 			sample_start(1, 1, 1);			// normal level
316 		else
317 			sample_stop(1);
318 	}
319 }
320 
321 
322 /*************************************
323  *
324  *	Armor Attack
325  *
326  *************************************/
327 
328 static const char *armora_sample_names[] =   //Added retrocade samples 10-27-03 Tim C.
329 {
330 	"*armora",
331 	"tankfire.wav",
332 	"hiexp.wav",
333                   "jeepfire.wav",
334                   "loexp.wav",
335 	"tankeng.wav",
336 	"beep.wav",
337 	"jeepfire.wav",
338     0	/* end of array */
339 };
340 
341 struct Samplesinterface armora_samples_interface =
342 {
343 	7,	/* 8 channels */
344 	25,	/* volume */
345 	armora_sample_names
346 };
347 
348 
armora_sound_w(UINT8 sound_val,UINT8 bits_changed)349 void armora_sound_w(UINT8 sound_val, UINT8 bits_changed)
350 {
351 	UINT8 shift_diff;
352 
353     cinemat_shift (sound_val, bits_changed, 0x80, 0x10);
354 
355 	// Now see if it's time to act upon the shifted data
356 
357 	if ((bits_changed & 0x01) && (0 == (sound_val & 0x01)))
358 	{
359 		// Yep. Falling edge! Find out what has changed.
360 
361 		shift_diff = current_shift ^ last_shift;
362 
363 		if ((shift_diff & 1) && (0 == (current_shift & 1)))
364 			sample_start(0, 0, 0);	// Tank fire
365 
366 		if ((shift_diff & 2) && (0 == (current_shift & 2)))
367 			sample_start(1, 1, 0);	// Hi explosion
368 
369 		if ((shift_diff & 4) && (0 == (current_shift & 4)))
370 			sample_start(2, 2, 0);	// Jeep fire
371 
372 		if ((shift_diff & 8) && (0 == (current_shift & 8)))
373 			sample_start(3, 3, 0);	// Lo explosion
374 
375         /* High nibble unknown */
376 		last_shift = current_shift;
377 	}
378 
379     if (bits_changed & 0x2)   // Fixed incorrect inverted triggering 10-27-03 Tim C.
380     {                         //Still not totally correct. Should be 2 speeds
381         if (sound_val & 0x2)
382            sample_stop(4);
383         else
384            sample_start(4, 4, 1);	// Tank +
385 
386     }
387     if (bits_changed & 0x4)  // Fixed incorrect inverted triggering 10-27-03 Tim C.
388     {
389         if (sound_val & 0x4)
390           sample_stop(5);
391         else
392           sample_start(5, 5, 1);	       // Beep +
393     }
394     if (bits_changed & 0x8)  // Fixed incorrect inverted triggering 10-27-03 Tim C.
395     {
396         if (sound_val & 0x8)
397            sample_stop(6);
398         else
399            sample_start(6, 6, 1);	// Chopper +
400     }
401 }
402 
403 
404 /*************************************
405  *
406  *	Ripoff
407  *
408  *************************************/
409 
410 static const char *ripoff_sample_names[] =
411 {
412 	"*ripoff",
413     "efire.wav",
414 	"eattack.wav",
415 	"bonuslvl.wav",
416 	"explosn.wav",
417 	"shipfire.wav",
418 	"bg1.wav",
419 	"bg2.wav",
420 	"bg3.wav",
421 	"bg4.wav",
422 	"bg5.wav",
423 	"bg6.wav",
424 	"bg7.wav",
425 	"bg8.wav",
426     0	/* end of array */
427 };
428 
429 struct Samplesinterface ripoff_samples_interface =
430 {
431 	8,	/* 8 channels */
432 	25,	/* volume */
433 	ripoff_sample_names
434 };
435 
ripoff_sound_w(UINT8 sound_val,UINT8 bits_changed)436 void ripoff_sound_w(UINT8 sound_val, UINT8 bits_changed)
437 {
438 	UINT8 shift_diff, current_bg_sound;
439     static UINT8 last_bg_sound;
440 
441     cinemat_shift (sound_val, bits_changed, 0x01, 0x02);
442 
443 	// Now see if it's time to act upon the shifted data
444 
445 	if ((bits_changed & 0x04) && (0 == (sound_val & 0x04)))
446 	{
447 		// Yep. Falling edge! Find out what has changed.
448 
449 		shift_diff = current_shift ^ last_shift;
450 
451         current_bg_sound = ((current_shift & 0x1) << 2) | (current_shift & 0x2) | ((current_shift & 0x4) >> 2);
452         if (current_bg_sound != last_bg_sound) // use another background sound ?
453         {
454             shift_diff |= 0x08;
455             sample_stop(4);
456             last_bg_sound = current_bg_sound;
457         }
458 
459 		if (shift_diff & 0x08)
460 		{
461 			if (current_shift & 0x08)
462 				sample_stop(5);
463 			else
464                 sample_start(5, 5+last_bg_sound, 1);	// Background
465 		}
466 
467 		if ((shift_diff & 0x10) && (0 == (current_shift & 0x10)))
468 			sample_start(2, 2, 0);	// Beep
469 
470 		if (shift_diff & 0x20)
471 		{
472 			if (current_shift & 0x20)
473 				sample_stop(1);	// Stop it!
474 			else
475 				sample_start(1, 1, 1);	// Motor
476 		}
477 
478 		last_shift = current_shift;
479 	}
480 
481 	if ((bits_changed & 0x08) && (0 == (sound_val & 0x08)))
482 		sample_start(4, 4, 0);			// Torpedo
483 
484 	if ((bits_changed & 0x10) && (0 == (sound_val & 0x10)))
485 		sample_start(0, 0, 0);			// Laser
486 
487 	if ((bits_changed & 0x80) && (0 == (sound_val & 0x80)))
488 		sample_start(3, 3, 0);			// Explosion
489 
490 }
491 
492 
493 /*************************************
494  *
495  *	Solar Quest
496  *
497  *************************************/
498 
499 static const char *solarq_sample_names[] =
500 {
501 	"*solarq",
502     "bigexpl.wav",
503 	"smexpl.wav",
504 	"lthrust.wav",
505 	"slaser.wav",
506 	"pickup.wav",
507 	"nuke1.wav",
508 	"nuke2.wav",
509 	"hypersp.wav",
510     "extra.wav",
511     "phase.wav",
512     "efire.wav",
513     0	/* end of array */
514 };
515 
516 struct Samplesinterface solarq_samples_interface =
517 {
518 	8,	/* 8 channels */
519 	25,	/* volume */
520 	solarq_sample_names
521 };
522 
523 
solarq_sound_w(UINT8 sound_val,UINT8 bits_changed)524 void solarq_sound_w(UINT8 sound_val, UINT8 bits_changed)
525 {
526 	UINT32 shift_diff, shift_diff16;
527     static int target_volume, current_volume;
528 
529     cinemat_shift (sound_val, bits_changed, 0x80, 0x10);
530 
531 	if ((bits_changed & 0x01) && (0 == (sound_val & 0x01)))
532     {
533 		shift_diff16 = current_shift ^ last_shift16;
534 
535 		if ((shift_diff16 & 0x1) && (current_shift & 0x1))
536         {
537             switch (current_shift & 0xffff)
538             {
539             case 0xceb3:
540                 sample_start(7, 7, 0);	// Hyperspace
541                 break;
542             case 0x13f3:
543                 sample_start(7, 8, 0);	// Extra
544                 break;
545             case 0xfdf3:
546                 sample_start(7, 9, 0);	// Phase
547                 break;
548             case 0x7bf3:
549                 sample_start(7, 10, 0);	// Enemy fire
550                 break;
551             default:
552                 logerror("Unknown sound starting with: %x\n", current_shift & 0xffff);
553                 break;
554             }
555         }
556 
557 		last_shift16 = current_shift;
558     }
559 
560 	// Now see if it's time to act upon the shifted data
561 
562 	if ((bits_changed & 0x02) && (0 == (sound_val & 0x02)))
563 	{
564 		// Yep. Falling edge! Find out what has changed.
565 
566 		shift_diff = current_shift ^ last_shift;
567 
568 		if ((shift_diff & 0x01) && (0 == (current_shift & 0x01)))
569 			sample_start(0, 0, 0);	// loud expl.
570 
571 		if ((shift_diff & 0x02) && (0 == (current_shift & 0x02)))
572 			sample_start(1, 1, 0);	// soft expl.
573 
574 		if (shift_diff & 0x04) // thrust
575 		{
576 			if (current_shift & 0x04)
577 				target_volume = 0;
578 			else
579             {
580                 target_volume = 255;
581                 current_volume = 0;
582 				sample_start(2, 2, 1);
583             }
584         }
585 
586         if (sample_playing(2) && (last_frame < cpu_getcurrentframe()))
587         {
588             if (current_volume > target_volume)
589                 current_volume -= 20;
590             if (current_volume < target_volume)
591                 current_volume += 20;
592             if (current_volume > 0)
593                 sample_set_volume(2, current_volume);
594             else
595                 sample_stop(2);
596             last_frame = cpu_getcurrentframe();
597         }
598 
599 		if ((shift_diff & 0x08) && (0 == (current_shift & 0x08)))
600 			sample_start(3, 3, 0);	// Fire
601 
602 		if ((shift_diff & 0x10) && (0 == (current_shift & 0x10)))
603 			sample_start(4, 4, 0);	// Capture
604 
605 		if (shift_diff & 0x20)
606 		{
607 			if (current_shift & 0x20)
608 				sample_start(6, 6, 1);	// Nuke +
609 			else
610 				sample_stop(6);
611 		}
612 
613 		if ((shift_diff & 0x40) && (0 == (current_shift & 0x40)))
614 			sample_start(5, 5, 0);	// Photon
615 
616 		last_shift = current_shift;
617 	}
618 }
619 
620 
621 /*************************************
622  *
623  *	Space Wars
624  *
625  *************************************/
626 
627 static const char *spacewar_sample_names[] =
628 {
629 	"*spacewar",
630 	"explode1.wav",
631 	"fire1.wav",
632 	"idle.wav",
633 	"thrust1.wav",
634 	"thrust2.wav",
635 	"pop.wav",
636 	"explode2.wav",
637 	"fire2.wav",
638     0	/* end of array */
639 };
640 
641 struct Samplesinterface spacewar_samples_interface =
642 {
643 	8,	/* 8 channels */
644 	25,	/* volume */
645 	spacewar_sample_names
646 };
647 
spacewar_sound_w(UINT8 sound_val,UINT8 bits_changed)648 void spacewar_sound_w(UINT8 sound_val, UINT8 bits_changed)
649 {
650 
651 	// Explosion
652 
653 	if (bits_changed & 0x01)
654 	{
655 		if (sound_val & 0x01)
656 		{
657             if (rand() & 1)
658                 sample_start(0, 0, 0);
659             else
660                 sample_start(0, 6, 0);
661 		}
662 	}
663 	// Fire sound
664 
665 	if ((sound_val & 0x02) && (bits_changed & 0x02))
666 	{
667        if (rand() & 1)
668            sample_start(1, 1, 0);
669        else
670            sample_start(1, 7, 0);
671 	}
672 
673 	// Player 1 thrust
674 
675 	if (bits_changed & 0x04)
676 	{
677 		if (sound_val & 0x04)
678 			sample_stop(3);
679 		else
680 			sample_start(3, 3, 1);
681 	}
682 
683 	// Player 2 thrust
684 
685 	if (bits_changed & 0x08)
686 	{
687 		if (sound_val & 0x08)
688 			sample_stop(4);
689 		else
690 			sample_start(4, 4, 1);
691 	}
692 
693 	// Sound board shutoff (or enable)
694 
695 	if (bits_changed & 0x10)
696 	{
697 		// This is a toggle bit. If sound is enabled, shut everything off.
698 
699 		if (sound_val & 0x10)
700 		{
701             int i;
702 
703 			for (i = 0; i < 5; i++)
704 			{
705 				if (i != 2)
706 					sample_stop(i);
707 			}
708 
709 			sample_start(2, 5, 0);	// Pop when board is shut off
710 		}
711 		else
712 			sample_start(2, 2, 1);	// Otherwise play idle sound
713 	}
714 }
715 
716 
717 /*************************************
718  *
719  *	Demon
720  *
721  *************************************/
722 
723 /* circular queue with read and write pointers */
724 #define QUEUE_ENTRY_COUNT  10
725 static int sound_latch_rp = 0;
726 static int sound_latch_wp = 0;
727 static int sound_latch[QUEUE_ENTRY_COUNT];
728 
demon_sound_w(UINT8 sound_val,UINT8 bits_changed)729 void demon_sound_w(UINT8 sound_val, UINT8 bits_changed)
730 {
731 	int pc = activecpu_get_pc();
732 
733 	if (pc == 0x0fbc ||
734 		pc == 0x1fed ||
735 		pc == 0x2ff1 ||
736 		pc == 0x3fd3)
737 	{
738 		sound_latch[sound_latch_wp] = ((sound_val & 0x07) << 3);
739 	}
740 	if (pc == 0x0fc8 ||
741 		pc == 0x1ff9 ||
742 		pc == 0x2ffd ||
743 		pc == 0x3fdf)
744 	{
745 		sound_latch[sound_latch_wp] |= (sound_val & 0x07);
746 
747 		//logerror("Writing Sound Latch %04X = %02X\n", pc, sound_latch[sound_latch_wp]);
748 
749 		sound_latch_wp++;
750 		if (sound_latch_wp == QUEUE_ENTRY_COUNT)  sound_latch_wp = 0;
751 	}
752 }
753 
READ_HANDLER(demon_sound_r)754 static READ_HANDLER( demon_sound_r )
755 {
756 	int ret;
757 
758 	if (sound_latch_rp == sound_latch_wp)	return 0x80;	/* no data in queue */
759 
760 	ret = sound_latch[sound_latch_rp];
761 
762 	sound_latch_rp++;
763 	if (sound_latch_rp == QUEUE_ENTRY_COUNT)  sound_latch_rp = 0;
764 
765 	//logerror("Reading Sound Latch %04X = %02X\n", activecpu_get_pc(), ret);
766 
767 	return ret;
768 }
769 
770 
771 struct AY8910interface demon_ay8910_interface =
772 {
773 	3,	/* 3 chips */
774 	3579545,	/* 3.579545 MHz */
775 	{ 25, 25, 25 },
776 	{ demon_sound_r },
777 	{ 0 },	/* there are sound enable bits in here, but don't know what is what */
778 	{ 0 },
779 	{ 0 }
780 };
781 
782 
ctc_interrupt(int state)783 static void ctc_interrupt(int state)
784 {
785 	cpu_set_irq_line_and_vector(1, 0, HOLD_LINE, Z80_VECTOR(0,state));
786 }
787 
788 
789 z80ctc_interface demon_z80ctc_interface =
790 {
791 	1,                   /* 1 chip */
792 	{ 0 },               /* clock (filled in from the CPU clock) */
793 	{ 0 },               /* timer disables */
794 	{ ctc_interrupt },   /* interrupt handler */
795 	{ 0 },               /* ZC/TO0 callback */
796 	{ 0 },               /* ZC/TO1 callback */
797 	{ 0 }                /* ZC/TO2 callback */
798 };
799 
800 
MACHINE_INIT(demon_sound)801 MACHINE_INIT( demon_sound )
802 {
803 	demon_z80ctc_interface.baseclock[0] = Machine->drv->cpu[1].cpu_clock;
804 	z80ctc_init(&demon_z80ctc_interface);
805 }
806 
807 
MEMORY_READ_START(demon_sound_readmem)808 MEMORY_READ_START( demon_sound_readmem )
809 	{ 0x0000, 0x0fff, MRA_ROM },
810 	{ 0x3000, 0x33ff, MRA_RAM },
811 	{ 0x4001, 0x4001, AY8910_read_port_0_r },
812 	{ 0x5001, 0x5001, AY8910_read_port_1_r },
813 	{ 0x6001, 0x6001, AY8910_read_port_2_r },
814 MEMORY_END
815 
816 
817 MEMORY_WRITE_START( demon_sound_writemem )
818 	{ 0x0000, 0x0fff, MWA_ROM },
819 	{ 0x3000, 0x33ff, MWA_RAM },
820 	{ 0x4002, 0x4002, AY8910_write_port_0_w },
821 	{ 0x4003, 0x4003, AY8910_control_port_0_w },
822 	{ 0x5002, 0x5002, AY8910_write_port_1_w },
823 	{ 0x5003, 0x5003, AY8910_control_port_1_w },
824 	{ 0x6002, 0x6002, AY8910_write_port_2_w },
825 	{ 0x6003, 0x6003, AY8910_control_port_2_w },
826 	{ 0x7000, 0x7000, MWA_NOP },  /* watchdog? */
827 MEMORY_END
828 
829 
830 PORT_WRITE_START( demon_sound_writeport )
831 	{ 0x00, 0x03, z80ctc_0_w },
832 	{ 0x1c, 0x1f, z80ctc_0_w },
833 PORT_END
834 
835 
836 static Z80_DaisyChain daisy_chain[] =
837 {
838 	{ z80ctc_reset, z80ctc_interrupt, z80ctc_reti, 0 }, /* CTC number 0 */
839 	{ 0,0,0,-1} 		/* end mark */
840 };
841 
842 
843 MACHINE_DRIVER_START( demon_sound )
844 
845 	/* basic machine hardware */
846 	MDRV_CPU_ADD(Z80, 3579545)
847 	MDRV_CPU_FLAGS(CPU_AUDIO_CPU);
848 	MDRV_CPU_CONFIG(daisy_chain)
849 	MDRV_CPU_MEMORY(demon_sound_readmem,demon_sound_writemem)
850 	MDRV_CPU_PORTS(0,demon_sound_writeport)
851 
852 	MDRV_MACHINE_INIT( demon_sound )
853 
854 	/* sound hardware */
855 	MDRV_SOUND_ADD(AY8910, demon_ay8910_interface)
856 MACHINE_DRIVER_END
857