summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/cinemat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/audio/cinemat.c')
-rw-r--r--src/mame/audio/cinemat.c1608
1 files changed, 1608 insertions, 0 deletions
diff --git a/src/mame/audio/cinemat.c b/src/mame/audio/cinemat.c
new file mode 100644
index 00000000000..3e0f1e70783
--- /dev/null
+++ b/src/mame/audio/cinemat.c
@@ -0,0 +1,1608 @@
+/***************************************************************************
+
+ Cinematronics vector hardware
+
+ Special thanks to Neil Bradley, Zonn Moore, and Jeff Mitchell of the
+ Retrocade Alliance
+
+ Update:
+ 6/27/99 Jim Hernandez -- 1st Attempt at Fixing Drone Star Castle sound and
+ pitch adjustments.
+ 6/30/99 MLR added Rip Off, Solar Quest, Armor Attack (no samples yet)
+
+ Bugs: Sometimes the death explosion (small explosion) does not trigger.
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/ccpu/ccpu.h"
+#include "cpu/z80/z80daisy.h"
+#include "machine/z80ctc.h"
+#include "cinemat.h"
+#include "sound/samples.h"
+#include "sound/ay8910.h"
+
+
+/*************************************
+ *
+ * Macros
+ *
+ *************************************/
+
+#define RISING_EDGE(bit, changed, val) (((changed) & (bit)) && ((val) & (bit)))
+#define FALLING_EDGE(bit, changed, val) (((changed) & (bit)) && !((val) & (bit)))
+
+#define SOUNDVAL_RISING_EDGE(bit) RISING_EDGE(bit, bits_changed, sound_val)
+#define SOUNDVAL_FALLING_EDGE(bit) FALLING_EDGE(bit, bits_changed, sound_val)
+
+#define SHIFTREG_RISING_EDGE(bit) RISING_EDGE(bit, (last_shift ^ current_shift), current_shift)
+#define SHIFTREG_FALLING_EDGE(bit) FALLING_EDGE(bit, (last_shift ^ current_shift), current_shift)
+
+#define SHIFTREG2_RISING_EDGE(bit) RISING_EDGE(bit, (last_shift2 ^ current_shift), current_shift)
+#define SHIFTREG2_FALLING_EDGE(bit) FALLING_EDGE(bit, (last_shift2 ^ current_shift), current_shift)
+
+
+
+/*************************************
+ *
+ * Global variables
+ *
+ *************************************/
+
+static void (*sound_handler)(UINT8 sound_val, UINT8 bits_changed);
+static UINT8 sound_control;
+
+/* general shift register variables */
+static UINT32 current_shift;
+static UINT32 last_shift;
+static UINT32 last_shift2;
+static UINT32 current_pitch;
+static UINT32 last_frame;
+
+/* Rockola sound variables */
+static UINT8 sound_fifo[16];
+static UINT8 sound_fifo_in;
+static UINT8 sound_fifo_out;
+static UINT8 last_portb_write;
+
+
+
+/*************************************
+ *
+ * Generic sound write
+ *
+ *************************************/
+
+WRITE8_HANDLER( cinemat_sound_control_w )
+{
+ UINT8 oldval = sound_control;
+
+ /* form an 8-bit value with the new bit */
+ sound_control = (sound_control & ~(1 << offset)) | ((data & 1) << offset);
+
+ /* if something changed, call the sound subroutine */
+ if ((sound_control != oldval) && sound_handler)
+ (*sound_handler)(sound_control, sound_control ^ oldval);
+}
+
+
+
+/*************************************
+ *
+ * Generic sound init
+ *
+ *************************************/
+
+static void generic_init(running_machine *machine, void (*callback)(UINT8, UINT8))
+{
+ /* call the standard init */
+ machine_reset_cinemat(machine);
+
+ /* set the sound handler */
+ sound_handler = callback;
+
+ /* reset sound control */
+ sound_control = 0x9f;
+
+ /* reset shift register values */
+ current_shift = 0xffff;
+ last_shift = 0xffff;
+ last_shift2 = 0xffff;
+
+ /* reset frame counters */
+ last_frame = 0;
+
+ /* reset Star Castle pitch */
+ current_pitch = 0x20000;
+
+ /* register for save states */
+ state_save_register_global(sound_control);
+ state_save_register_global(current_shift);
+ state_save_register_global(last_shift);
+ state_save_register_global(last_shift2);
+ state_save_register_global(current_pitch);
+ state_save_register_global(last_frame);
+ state_save_register_global_array(sound_fifo);
+ state_save_register_global(sound_fifo_in);
+ state_save_register_global(sound_fifo_out);
+ state_save_register_global(last_portb_write);
+}
+
+
+
+/*************************************
+ *
+ * Space Wars
+ *
+ *************************************/
+
+static const char *spacewar_sample_names[] =
+{
+ "*spacewar",
+ "explode1.wav",
+ "fire1.wav",
+ "idle.wav",
+ "thrust1.wav",
+ "thrust2.wav",
+ "pop.wav",
+ "explode2.wav",
+ "fire2.wav",
+ 0
+};
+
+static struct Samplesinterface spacewar_samples_interface =
+{
+ 8,
+ spacewar_sample_names
+};
+
+static void spacewar_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* Explosion - rising edge */
+ if (SOUNDVAL_RISING_EDGE(0x01))
+ sample_start(0, (mame_rand(Machine) & 1) ? 0 : 6, 0);
+
+ /* Fire sound - rising edge */
+ if (SOUNDVAL_RISING_EDGE(0x02))
+ sample_start(1, (mame_rand(Machine) & 1) ? 1 : 7, 0);
+
+ /* Player 1 thrust - 0=on, 1=off */
+ if (SOUNDVAL_FALLING_EDGE(0x04))
+ sample_start(3, 3, 1);
+ if (SOUNDVAL_RISING_EDGE(0x04))
+ sample_stop(3);
+
+ /* Player 2 thrust - 0=on, 1-off */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ sample_start(4, 4, 1);
+ if (SOUNDVAL_RISING_EDGE(0x08))
+ sample_stop(4);
+
+ /* Mute - 0=off, 1=on */
+ if (SOUNDVAL_FALLING_EDGE(0x10))
+ sample_start(2, 2, 1); /* play idle sound */
+ if (SOUNDVAL_RISING_EDGE(0x10))
+ {
+ int i;
+
+ /* turn off all but the idle sound */
+ for (i = 0; i < 5; i++)
+ if (i != 2)
+ sample_stop(i);
+
+ /* Pop when board is shut off */
+ sample_start(2, 5, 0);
+ }
+}
+
+static MACHINE_RESET( spacewar )
+{
+ generic_init(machine, spacewar_sound_w);
+}
+
+MACHINE_DRIVER_START( spacewar_sound )
+ MDRV_MACHINE_RESET(spacewar)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(spacewar_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Barrier
+ *
+ *************************************/
+
+static const char *barrier_sample_names[] =
+{
+ "*barrier",
+ "playrdie.wav",
+ "playmove.wav",
+ "enemmove.wav",
+ 0
+};
+
+static struct Samplesinterface barrier_samples_interface =
+{
+ 3,
+ barrier_sample_names
+};
+
+static void barrier_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* Player die - rising edge */
+ if (SOUNDVAL_RISING_EDGE(0x01))
+ sample_start(0, 0, 0);
+
+ /* Player move - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x02))
+ sample_start(1, 1, 0);
+
+ /* Enemy move - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x04))
+ sample_start(2, 2, 0);
+}
+
+static MACHINE_RESET( barrier )
+{
+ generic_init(machine, barrier_sound_w);
+}
+
+MACHINE_DRIVER_START( barrier_sound )
+ MDRV_MACHINE_RESET(barrier)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(barrier_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Speed Freak
+ *
+ *************************************/
+
+static const char *speedfrk_sample_names[] =
+{
+ "*speedfrk",
+ "offroad.wav",
+ NULL
+};
+
+static struct Samplesinterface speedfrk_samples_interface =
+{
+ 1,
+ speedfrk_sample_names
+};
+
+static void speedfrk_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* on the falling edge of bit 0x08, clock the inverse of bit 0x04 into the top of the shiftreg */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ {
+ current_shift = ((current_shift >> 1) & 0x7fff) | ((~sound_val << 13) & 1);
+ /* high 12 bits control the frequency - counts from value to $FFF, carry triggers */
+ /* another counter */
+
+ /* low 4 bits control the volume of the noise output (explosion?) */
+ }
+
+ /* off-road - 1=on, 0=off */
+ if (SOUNDVAL_RISING_EDGE(0x10))
+ sample_start(0, 0, 1);
+ if (SOUNDVAL_FALLING_EDGE(0x10))
+ sample_stop(0);
+
+ /* start LED is controlled by bit 0x02 */
+ set_led_status(0, ~sound_val & 0x02);
+}
+
+static MACHINE_RESET( speedfrk )
+{
+ generic_init(machine, speedfrk_sound_w);
+}
+
+MACHINE_DRIVER_START( speedfrk_sound )
+ MDRV_MACHINE_RESET(speedfrk)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(speedfrk_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Star Hawk
+ *
+ *************************************/
+
+static const char *starhawk_sample_names[] =
+{
+ "*starhawk",
+ "explode.wav",
+ "rlaser.wav",
+ "llaser.wav",
+ "k.wav",
+ "master.wav",
+ "kexit.wav",
+ NULL
+};
+
+static struct Samplesinterface starhawk_samples_interface =
+{
+ 5,
+ starhawk_sample_names
+};
+
+static void starhawk_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x01))
+ sample_start(0, 0, 0);
+
+ /* right laser - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x02))
+ sample_start(1, 1, 0);
+
+ /* left laser - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x04))
+ sample_start(2, 2, 0);
+
+ /* K - 0=on, 1=off */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ sample_start(3, 3, 1);
+ if (SOUNDVAL_RISING_EDGE(0x08))
+ sample_stop(3);
+
+ /* master - 0=on, 1=off */
+ if (SOUNDVAL_FALLING_EDGE(0x10))
+ sample_start(4, 4, 1);
+ if (SOUNDVAL_RISING_EDGE(0x10))
+ sample_stop(4);
+
+ /* K exit - 1=on, 0=off */
+ if (SOUNDVAL_RISING_EDGE(0x80))
+ sample_start(3, 5, 1);
+ if (SOUNDVAL_FALLING_EDGE(0x80))
+ sample_stop(3);
+}
+
+static MACHINE_RESET( starhawk )
+{
+ generic_init(machine, starhawk_sound_w);
+}
+
+MACHINE_DRIVER_START( starhawk_sound )
+ MDRV_MACHINE_RESET(starhawk)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(starhawk_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Sundance
+ *
+ *************************************/
+
+static const char *sundance_sample_names[] =
+{
+ "*sundance",
+ "bong.wav",
+ "whoosh.wav",
+ "explsion.wav",
+ "ping1.wav",
+ "ping2.wav",
+ "hatch.wav",
+ 0
+};
+
+static struct Samplesinterface sundance_samples_interface =
+{
+ 6,
+ sundance_sample_names
+};
+
+static void sundance_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* bong - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x01))
+ sample_start(0, 0, 0);
+
+ /* whoosh - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x02))
+ sample_start(1, 1, 0);
+
+ /* explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x04))
+ sample_start(2, 2, 0);
+
+ /* ping - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ sample_start(3, 3, 0);
+
+ /* ping - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x10))
+ sample_start(4, 4, 0);
+
+ /* hatch - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x80))
+ sample_start(5, 5, 0);
+}
+
+static MACHINE_RESET( sundance )
+{
+ generic_init(machine, sundance_sound_w);
+}
+
+MACHINE_DRIVER_START( sundance_sound )
+ MDRV_MACHINE_RESET(sundance)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(sundance_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Tail Gunner
+ *
+ *************************************/
+
+static const char *tailg_sample_names[] =
+{
+ "*tailg",
+ "sexplode.wav",
+ "thrust1.wav",
+ "slaser.wav",
+ "shield.wav",
+ "bounce.wav",
+ "hypersp.wav",
+ NULL
+};
+
+static struct Samplesinterface tailg_samples_interface =
+{
+ 6,
+ tailg_sample_names
+};
+
+static void tailg_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* the falling edge of bit 0x10 clocks bit 0x08 into the mux selected by bits 0x07 */
+ if (SOUNDVAL_FALLING_EDGE(0x10))
+ {
+ /* update the shift register (actually just a simple mux) */
+ current_shift = (current_shift & ~(1 << (sound_val & 7))) | (((sound_val >> 3) & 1) << (sound_val & 7));
+
+ /* explosion - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x01))
+ sample_start(0, 0, 0);
+
+ /* rumble - 0=on, 1=off */
+ if (SHIFTREG_FALLING_EDGE(0x02))
+ sample_start(1, 1, 1);
+ if (SHIFTREG_RISING_EDGE(0x02))
+ sample_stop(1);
+
+ /* laser - 0=on, 1=off */
+ if (SHIFTREG_FALLING_EDGE(0x04))
+ sample_start(2, 2, 1);
+ if (SHIFTREG_RISING_EDGE(0x04))
+ sample_stop(2);
+
+ /* shield - 0=on, 1=off */
+ if (SHIFTREG_FALLING_EDGE(0x08))
+ sample_start(3, 3, 1);
+ if (SHIFTREG_RISING_EDGE(0x08))
+ sample_stop(3);
+
+ /* bounce - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x10))
+ sample_start(4, 4, 0);
+
+ /* hyperspace - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x20))
+ sample_start(5, 5, 0);
+
+ /* LED */
+ set_led_status(0, current_shift & 0x40);
+
+ /* remember the previous value */
+ last_shift = current_shift;
+ }
+}
+
+static MACHINE_RESET( tailg )
+{
+ generic_init(machine, tailg_sound_w);
+}
+
+MACHINE_DRIVER_START( tailg_sound )
+ MDRV_MACHINE_RESET(tailg)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(tailg_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Warrior
+ *
+ *************************************/
+
+static const char *warrior_sample_names[] =
+{
+ "*warrior",
+ "bgmhum1.wav",
+ "bgmhum2.wav",
+ "killed.wav",
+ "fall.wav",
+ "appear.wav",
+ NULL
+};
+
+static struct Samplesinterface warrior_samples_interface =
+{
+ 5,
+ warrior_sample_names
+};
+
+static void warrior_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* normal level - 0=on, 1=off */
+ if (SOUNDVAL_FALLING_EDGE(0x01))
+ sample_start(0, 0, 1);
+ if (SOUNDVAL_RISING_EDGE(0x01))
+ sample_stop(0);
+
+ /* hi level - 0=on, 1=off */
+ if (SOUNDVAL_FALLING_EDGE(0x02))
+ sample_start(1, 1, 1);
+ if (SOUNDVAL_RISING_EDGE(0x02))
+ sample_stop(1);
+
+ /* explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x04))
+ sample_start(2, 2, 0);
+
+ /* fall - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ sample_start(3, 3, 0);
+
+ /* appear - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x10))
+ sample_start(4, 4, 0);
+}
+
+static MACHINE_RESET( warrior )
+{
+ generic_init(machine, warrior_sound_w);
+}
+
+MACHINE_DRIVER_START( warrior_sound )
+ MDRV_MACHINE_RESET(warrior)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(warrior_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Armor Attack
+ *
+ *************************************/
+
+static const char *armora_sample_names[] =
+{
+ "*armora",
+ "loexp.wav",
+ "jeepfire.wav",
+ "hiexp.wav",
+ "tankfire.wav",
+ "tankeng.wav",
+ "beep.wav",
+ "chopper.wav",
+ NULL
+};
+
+static struct Samplesinterface armora_samples_interface =
+{
+ 7,
+ armora_sample_names
+};
+
+static void armora_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* on the rising edge of bit 0x10, clock bit 0x80 into the shift register */
+ if (SOUNDVAL_RISING_EDGE(0x10))
+ current_shift = ((current_shift >> 1) & 0x7f) | (sound_val & 0x80);
+
+ /* execute on the rising edge of bit 0x01 */
+ if (SOUNDVAL_RISING_EDGE(0x01))
+ {
+ /* bits 0-4 control the tank sound speed */
+
+ /* lo explosion - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x10))
+ sample_start(0, 0, 0);
+
+ /* jeep fire - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x20))
+ sample_start(1, 1, 0);
+
+ /* hi explosion - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x40))
+ sample_start(2, 2, 0);
+
+ /* tank fire - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x80))
+ sample_start(3, 3, 0);
+
+ /* remember the previous value */
+ last_shift = current_shift;
+ }
+
+ /* tank sound - 0=on, 1=off */
+ /* still not totally correct - should be multiple speeds based on remaining bits in shift reg */
+ if (SOUNDVAL_FALLING_EDGE(0x02))
+ sample_start(4, 4, 1);
+ if (SOUNDVAL_RISING_EDGE(0x02))
+ sample_stop(4);
+
+ /* beep sound - 0=on, 1=off */
+ if (SOUNDVAL_FALLING_EDGE(0x04))
+ sample_start(5, 5, 1);
+ if (SOUNDVAL_RISING_EDGE(0x04))
+ sample_stop(5);
+
+ /* chopper sound - 0=on, 1=off */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ sample_start(6, 6, 1);
+ if (SOUNDVAL_RISING_EDGE(0x08))
+ sample_stop(6);
+}
+
+static MACHINE_RESET( armora )
+{
+ generic_init(machine, armora_sound_w);
+}
+
+MACHINE_DRIVER_START( armora_sound )
+ MDRV_MACHINE_RESET(armora)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(armora_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Ripoff
+ *
+ *************************************/
+
+static const char *ripoff_sample_names[] =
+{
+ "*ripoff",
+ "bonuslvl.wav",
+ "eattack.wav",
+ "shipfire.wav",
+ "efire.wav",
+ "explosn.wav",
+ "bg1.wav",
+ "bg2.wav",
+ "bg3.wav",
+ "bg4.wav",
+ "bg5.wav",
+ "bg6.wav",
+ "bg7.wav",
+ "bg8.wav",
+ NULL
+};
+
+static struct Samplesinterface ripoff_samples_interface =
+{
+ 6,
+ ripoff_sample_names
+};
+
+static void ripoff_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* on the rising edge of bit 0x02, clock bit 0x01 into the shift register */
+ if (SOUNDVAL_RISING_EDGE(0x02))
+ current_shift = ((current_shift >> 1) & 0x7f) | ((sound_val << 7) & 0x80);
+
+ /* execute on the rising edge of bit 0x04 */
+ if (SOUNDVAL_RISING_EDGE(0x04))
+ {
+ /* background - 0=on, 1=off, selected by bits 0x38 */
+ if ((((current_shift ^ last_shift) & 0x38) && !(current_shift & 0x04)) || SHIFTREG_FALLING_EDGE(0x04))
+ sample_start(5, 5 + ((current_shift >> 5) & 7), 1);
+ if (SHIFTREG_RISING_EDGE(0x04))
+ sample_stop(5);
+
+ /* beep - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x02))
+ sample_start(0, 0, 0);
+
+ /* motor - 0=on, 1=off */
+ if (SHIFTREG_FALLING_EDGE(0x01))
+ sample_start(1, 1, 1);
+ if (SHIFTREG_RISING_EDGE(0x01))
+ sample_stop(1);
+
+ /* remember the previous value */
+ last_shift = current_shift;
+ }
+
+ /* torpedo - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ sample_start(2, 2, 0);
+
+ /* laser - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x10))
+ sample_start(3, 3, 0);
+
+ /* explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x80))
+ sample_start(4, 4, 0);
+}
+
+static MACHINE_RESET( ripoff )
+{
+ generic_init(machine, ripoff_sound_w);
+}
+
+MACHINE_DRIVER_START( ripoff_sound )
+ MDRV_MACHINE_RESET(ripoff)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(ripoff_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Star Castle
+ *
+ *************************************/
+
+static const char *starcas_sample_names[] =
+{
+ "*starcas",
+ "cfire.wav",
+ "shield.wav",
+ "star.wav",
+ "thrust.wav",
+ "drone.wav",
+ "lexplode.wav",
+ "sexplode.wav",
+ "pfire.wav",
+ 0
+};
+
+static struct Samplesinterface starcas_samples_interface =
+{
+ 8,
+ starcas_sample_names
+};
+
+static void starcas_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ UINT32 target_pitch;
+
+ /* on the rising edge of bit 0x10, clock bit 0x80 into the shift register */
+ if (SOUNDVAL_RISING_EDGE(0x10))
+ current_shift = ((current_shift >> 1) & 0x7f) | (sound_val & 0x80);
+
+ /* execute on the rising edge of bit 0x01 */
+ if (SOUNDVAL_RISING_EDGE(0x01))
+ {
+ /* fireball - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x80))
+ sample_start(0, 0, 0);
+
+ /* shield hit - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x40))
+ sample_start(1, 1, 0);
+
+ /* star sound - 0=off, 1=on */
+ if (SHIFTREG_RISING_EDGE(0x20))
+ sample_start(2, 2, 1);
+ if (SHIFTREG_FALLING_EDGE(0x20))
+ sample_stop(2);
+
+ /* thrust sound - 1=off, 0=on*/
+ if (SHIFTREG_FALLING_EDGE(0x10))
+ sample_start(3, 3, 1);
+ if (SHIFTREG_RISING_EDGE(0x10))
+ sample_stop(3);
+
+ /* drone - 1=off, 0=on */
+ if (SHIFTREG_FALLING_EDGE(0x08))
+ sample_start(4, 4, 1);
+ if (SHIFTREG_RISING_EDGE(0x08))
+ sample_stop(4);
+
+ /* latch the drone pitch */
+ target_pitch = (current_shift & 7) + ((current_shift & 2) << 2);
+ target_pitch = 0x10000 + (target_pitch << 12);
+
+ /* once per frame slide the pitch toward the target */
+ if (cpu_getcurrentframe() > last_frame)
+ {
+ if (current_pitch > target_pitch)
+ current_pitch -= 300;
+ if (current_pitch < target_pitch)
+ current_pitch += 200;
+ sample_set_freq(4, current_pitch);
+ last_frame = cpu_getcurrentframe();
+ }
+
+ /* remember the previous value */
+ last_shift = current_shift;
+ }
+
+ /* loud explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x02))
+ sample_start(5, 5, 0);
+
+ /* soft explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x04))
+ sample_start(6, 6, 0);
+
+ /* player fire - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ sample_start(7, 7, 0);
+}
+
+static MACHINE_RESET( starcas )
+{
+ generic_init(machine, starcas_sound_w);
+}
+
+MACHINE_DRIVER_START( starcas_sound )
+ MDRV_MACHINE_RESET(starcas)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(starcas_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Solar Quest
+ *
+ *************************************/
+
+static const char *solarq_sample_names[] =
+{
+ "*solarq",
+ "bigexpl.wav",
+ "smexpl.wav",
+ "lthrust.wav",
+ "slaser.wav",
+ "pickup.wav",
+ "nuke2.wav",
+ "nuke1.wav",
+ "music.wav",
+ NULL
+};
+
+static struct Samplesinterface solarq_samples_interface =
+{
+ 8,
+ solarq_sample_names
+};
+
+static void solarq_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ static float target_volume, current_volume;
+
+ /* on the rising edge of bit 0x10, clock bit 0x80 into the shift register */
+ if (SOUNDVAL_RISING_EDGE(0x10))
+ current_shift = ((current_shift >> 1) & 0x7fff) | ((sound_val << 8) & 0x8000);
+
+ /* execute on the rising edge of bit 0x02 */
+ if (SOUNDVAL_RISING_EDGE(0x02))
+ {
+ /* only the upper 8 bits matter */
+ current_shift >>= 8;
+
+ /* loud explosion - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x80))
+ sample_start(0, 0, 0);
+
+ /* soft explosion - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x40))
+ sample_start(1, 1, 0);
+
+ /* thrust - 0=on, 1=off */
+ if (SHIFTREG_FALLING_EDGE(0x20))
+ {
+ target_volume = 1.0;
+ if (!sample_playing(2))
+ sample_start(2, 2, 1);
+ }
+ if (SHIFTREG_RISING_EDGE(0x20))
+ target_volume = 0;
+
+ /* ramp the thrust volume */
+ if (sample_playing(2) && cpu_getcurrentframe() > last_frame)
+ {
+ if (current_volume > target_volume)
+ current_volume -= 0.078;
+ if (current_volume < target_volume)
+ current_volume += 0.078;
+ if (current_volume > 0)
+ sample_set_volume(2, current_volume);
+ else
+ sample_stop(2);
+ last_frame = cpu_getcurrentframe();
+ }
+
+ /* fire - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x10))
+ sample_start(3, 3, 0);
+
+ /* capture - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x08))
+ sample_start(4, 4, 0);
+
+ /* nuke - 1=on, 0=off */
+ if (SHIFTREG_RISING_EDGE(0x04))
+ sample_start(5, 5, 1);
+ if (SHIFTREG_FALLING_EDGE(0x04))
+ sample_stop(5);
+
+ /* photon - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x02))
+ sample_start(6, 6, 0);
+
+ /* remember the previous value */
+ last_shift = current_shift;
+ }
+
+ /* clock music data on the rising edge of bit 0x01 */
+ if (SOUNDVAL_RISING_EDGE(0x01))
+ {
+ int freq, vol;
+
+ /* start/stop the music sample on the high bit */
+ if (SHIFTREG2_RISING_EDGE(0x8000))
+ sample_start(7, 7, 1);
+ if (SHIFTREG2_FALLING_EDGE(0x8000))
+ sample_stop(7);
+
+ /* set the frequency */
+ freq = 56818.181818 / (4096 - (current_shift & 0xfff));
+ sample_set_freq(7, 44100 * freq / 1050);
+
+ /* set the volume */
+ vol = (~current_shift >> 12) & 7;
+ sample_set_volume(7, vol / 7.0);
+
+ /* remember the previous value */
+ last_shift2 = current_shift;
+ }
+}
+
+static MACHINE_RESET( solarq )
+{
+ generic_init(machine, solarq_sound_w);
+}
+
+MACHINE_DRIVER_START( solarq_sound )
+ MDRV_MACHINE_RESET(solarq)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(solarq_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Boxing Bugs
+ *
+ *************************************/
+
+static const char *boxingb_sample_names[] =
+{
+ "*boxingb",
+ "softexpl.wav",
+ "loudexpl.wav",
+ "chirp.wav",
+ "eggcrack.wav",
+ "bugpusha.wav",
+ "bugpushb.wav",
+ "bugdie.wav",
+ "beetle.wav",
+ "music.wav",
+ "cannon.wav",
+ "bounce.wav",
+ "bell.wav",
+ NULL
+};
+
+static struct Samplesinterface boxingb_samples_interface =
+{
+ 12,
+ boxingb_sample_names
+};
+
+static void boxingb_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* on the rising edge of bit 0x10, clock bit 0x80 into the shift register */
+ if (SOUNDVAL_RISING_EDGE(0x10))
+ current_shift = ((current_shift >> 1) & 0x7fff) | ((sound_val << 8) & 0x8000);
+
+ /* execute on the rising edge of bit 0x02 */
+ if (SOUNDVAL_RISING_EDGE(0x02))
+ {
+ /* only the upper 8 bits matter */
+ current_shift >>= 8;
+
+ /* soft explosion - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x80))
+ sample_start(0, 0, 0);
+
+ /* loud explosion - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x40))
+ sample_start(1, 1, 0);
+
+ /* chirping birds - 0=on, 1=off */
+ if (SHIFTREG_FALLING_EDGE(0x20))
+ sample_start(2, 2, 0);
+ if (SHIFTREG_RISING_EDGE(0x20))
+ sample_stop(2);
+
+ /* egg cracking - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x10))
+ sample_start(3, 3, 0);
+
+ /* bug pushing A - rising edge */
+ if (SHIFTREG_RISING_EDGE(0x08))
+ sample_start(4, 4, 0);
+
+ /* bug pushing B - rising edge */
+ if (SHIFTREG_RISING_EDGE(0x04))
+ sample_start(5, 5, 0);
+
+ /* bug dying - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x02))
+ sample_start(6, 6, 0);
+
+ /* beetle on screen - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x01))
+ sample_start(7, 7, 0);
+
+ /* remember the previous value */
+ last_shift = current_shift;
+ }
+
+ /* clock music data on the rising edge of bit 0x01 */
+ if (SOUNDVAL_RISING_EDGE(0x01))
+ {
+ int freq, vol;
+
+ /* start/stop the music sample on the high bit */
+ if (SHIFTREG2_RISING_EDGE(0x8000))
+ sample_start(8, 8, 1);
+ if (SHIFTREG2_FALLING_EDGE(0x8000))
+ sample_stop(8);
+
+ /* set the frequency */
+ freq = 56818.181818 / (4096 - (current_shift & 0xfff));
+ sample_set_freq(8, 44100 * freq / 1050);
+
+ /* set the volume */
+ vol = (~current_shift >> 12) & 3;
+ sample_set_volume(8, vol / 3.0);
+
+ /* cannon - falling edge */
+ if (SHIFTREG2_RISING_EDGE(0x4000))
+ sample_start(9, 9, 0);
+
+ /* remember the previous value */
+ last_shift2 = current_shift;
+ }
+
+ /* bounce - rising edge */
+ if (SOUNDVAL_RISING_EDGE(0x04))
+ sample_start(10, 10, 0);
+
+ /* bell - falling edge */
+ if (SOUNDVAL_RISING_EDGE(0x08))
+ sample_start(11, 11, 0);
+}
+
+static MACHINE_RESET( boxingb )
+{
+ generic_init(machine, boxingb_sound_w);
+}
+
+MACHINE_DRIVER_START( boxingb_sound )
+ MDRV_MACHINE_RESET(boxingb)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(boxingb_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * War of the Worlds (B&W)
+ *
+ *************************************/
+
+static const char *wotw_sample_names[] =
+{
+ "*wotw",
+ "cfire.wav",
+ "shield.wav",
+ "star.wav",
+ "thrust.wav",
+ "drone.wav",
+ "lexplode.wav",
+ "sexplode.wav",
+ "pfire.wav",
+ 0
+};
+
+static struct Samplesinterface wotw_samples_interface =
+{
+ 8,
+ wotw_sample_names
+};
+
+static void wotw_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ UINT32 target_pitch;
+
+ /* on the rising edge of bit 0x10, clock bit 0x80 into the shift register */
+ if (SOUNDVAL_RISING_EDGE(0x10))
+ current_shift = ((current_shift >> 1) & 0x7f) | (sound_val & 0x80);
+
+ /* execute on the rising edge of bit 0x01 */
+ if (SOUNDVAL_RISING_EDGE(0x01))
+ {
+ /* fireball - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x80))
+ sample_start(0, 0, 0);
+
+ /* shield hit - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x40))
+ sample_start(1, 1, 0);
+
+ /* star sound - 0=off, 1=on */
+ if (SHIFTREG_RISING_EDGE(0x20))
+ sample_start(2, 2, 1);
+ if (SHIFTREG_FALLING_EDGE(0x20))
+ sample_stop(2);
+
+ /* thrust sound - 1=off, 0=on*/
+ if (SHIFTREG_FALLING_EDGE(0x10))
+ sample_start(3, 3, 1);
+ if (SHIFTREG_RISING_EDGE(0x10))
+ sample_stop(3);
+
+ /* drone - 1=off, 0=on */
+ if (SHIFTREG_FALLING_EDGE(0x08))
+ sample_start(4, 4, 1);
+ if (SHIFTREG_RISING_EDGE(0x08))
+ sample_stop(4);
+
+ /* latch the drone pitch */
+ target_pitch = (current_shift & 7) + ((current_shift & 2) << 2);
+ target_pitch = 0x10000 + (target_pitch << 12);
+
+ /* once per frame slide the pitch toward the target */
+ if (cpu_getcurrentframe() > last_frame)
+ {
+ if (current_pitch > target_pitch)
+ current_pitch -= 300;
+ if (current_pitch < target_pitch)
+ current_pitch += 200;
+ sample_set_freq(4, current_pitch);
+ last_frame = cpu_getcurrentframe();
+ }
+
+ /* remember the previous value */
+ last_shift = current_shift;
+ }
+
+ /* loud explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x02))
+ sample_start(5, 5, 0);
+
+ /* soft explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x04))
+ sample_start(6, 6, 0);
+
+ /* player fire - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ sample_start(7, 7, 0);
+}
+
+static MACHINE_RESET( wotw )
+{
+ generic_init(machine, wotw_sound_w);
+}
+
+MACHINE_DRIVER_START( wotw_sound )
+ MDRV_MACHINE_RESET(wotw)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(wotw_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * War of the Worlds (color)
+ *
+ *************************************/
+
+static const char *wotwc_sample_names[] =
+{
+ "*wotwc",
+ "cfire.wav",
+ "shield.wav",
+ "star.wav",
+ "thrust.wav",
+ "drone.wav",
+ "lexplode.wav",
+ "sexplode.wav",
+ "pfire.wav",
+ 0
+};
+
+static struct Samplesinterface wotwc_samples_interface =
+{
+ 8,
+ wotwc_sample_names
+};
+
+static void wotwc_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ UINT32 target_pitch;
+
+ /* on the rising edge of bit 0x10, clock bit 0x80 into the shift register */
+ if (SOUNDVAL_RISING_EDGE(0x10))
+ current_shift = ((current_shift >> 1) & 0x7f) | (sound_val & 0x80);
+
+ /* execute on the rising edge of bit 0x01 */
+ if (SOUNDVAL_RISING_EDGE(0x01))
+ {
+ /* fireball - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x80))
+ sample_start(0, 0, 0);
+
+ /* shield hit - falling edge */
+ if (SHIFTREG_FALLING_EDGE(0x40))
+ sample_start(1, 1, 0);
+
+ /* star sound - 0=off, 1=on */
+ if (SHIFTREG_RISING_EDGE(0x20))
+ sample_start(2, 2, 1);
+ if (SHIFTREG_FALLING_EDGE(0x20))
+ sample_stop(2);
+
+ /* thrust sound - 1=off, 0=on*/
+ if (SHIFTREG_FALLING_EDGE(0x10))
+ sample_start(3, 3, 1);
+ if (SHIFTREG_RISING_EDGE(0x10))
+ sample_stop(3);
+
+ /* drone - 1=off, 0=on */
+ if (SHIFTREG_FALLING_EDGE(0x08))
+ sample_start(4, 4, 1);
+ if (SHIFTREG_RISING_EDGE(0x08))
+ sample_stop(4);
+
+ /* latch the drone pitch */
+ target_pitch = (current_shift & 7) + ((current_shift & 2) << 2);
+ target_pitch = 0x10000 + (target_pitch << 12);
+
+ /* once per frame slide the pitch toward the target */
+ if (cpu_getcurrentframe() > last_frame)
+ {
+ if (current_pitch > target_pitch)
+ current_pitch -= 300;
+ if (current_pitch < target_pitch)
+ current_pitch += 200;
+ sample_set_freq(4, current_pitch);
+ last_frame = cpu_getcurrentframe();
+ }
+
+ /* remember the previous value */
+ last_shift = current_shift;
+ }
+
+ /* loud explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x02))
+ sample_start(5, 5, 0);
+
+ /* soft explosion - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x04))
+ sample_start(6, 6, 0);
+
+ /* player fire - falling edge */
+ if (SOUNDVAL_FALLING_EDGE(0x08))
+ sample_start(7, 7, 0);
+}
+
+static MACHINE_RESET( wotwc )
+{
+ generic_init(machine, wotwc_sound_w);
+}
+
+MACHINE_DRIVER_START( wotwc_sound )
+ MDRV_MACHINE_RESET(wotwc)
+
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(SAMPLES, 0)
+ MDRV_SOUND_CONFIG(wotwc_samples_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * Demon
+ *
+ *************************************/
+
+static TIMER_CALLBACK( synced_sound_w )
+{
+ sound_fifo[sound_fifo_in] = param;
+ sound_fifo_in = (sound_fifo_in + 1) % 16;
+}
+
+
+static void demon_sound_w(UINT8 sound_val, UINT8 bits_changed)
+{
+ /* all inputs are inverted */
+ sound_val = ~sound_val;
+
+ /* watch for a 0->1 edge on bit 4 ("shift in") to clock in the new data */
+ if ((bits_changed & 0x10) && (sound_val & 0x10))
+ timer_call_after_resynch(sound_val & 0x0f, synced_sound_w);
+}
+
+
+static READ8_HANDLER( sound_porta_r )
+{
+ /* bits 0-3 are the sound data; bit 4 is the data ready */
+ return sound_fifo[sound_fifo_out] | ((sound_fifo_in != sound_fifo_out) << 4);
+}
+
+
+static READ8_HANDLER( sound_portb_r )
+{
+ return last_portb_write;
+}
+
+
+static WRITE8_HANDLER( sound_portb_w )
+{
+ /* watch for a 0->1 edge on bit 0 ("shift out") to advance the data pointer */
+ if ((data & 1) != (last_portb_write & 1) && (data & 1) != 0)
+ sound_fifo_out = (sound_fifo_out + 1) % 16;
+
+ /* watch for a 0->1 edge of bit 1 ("hard reset") to reset the FIFO */
+ if ((data & 2) != (last_portb_write & 2) && (data & 2) != 0)
+ sound_fifo_in = sound_fifo_out = 0;
+
+ /* bit 2 controls the global mute */
+ if ((data & 4) != (last_portb_write & 4))
+ sound_global_enable(!(data & 4));
+
+ /* remember the last value written */
+ last_portb_write = data;
+}
+
+
+static WRITE8_HANDLER( sound_output_w )
+{
+ logerror("sound_output = %02X\n", data);
+}
+
+
+static struct AY8910interface demon_ay8910_interface_1 =
+{
+ sound_porta_r,
+ sound_portb_r,
+ 0,
+ sound_portb_w
+};
+
+static struct AY8910interface demon_ay8910_interface_3 =
+{
+ 0,
+ 0,
+ 0,
+ sound_output_w
+};
+
+
+static void ctc_interrupt(int state)
+{
+ cpunum_set_input_line(1, 0, state);
+}
+
+
+static z80ctc_interface demon_z80ctc_interface =
+{
+ 0, /* clock (filled in from the CPU clock) */
+ 0, /* timer disables */
+ ctc_interrupt, /* interrupt handler */
+ 0, /* ZC/TO0 callback */
+ 0, /* ZC/TO1 callback */
+ 0 /* ZC/TO2 callback */
+};
+
+
+static MACHINE_RESET( demon_sound )
+{
+ /* generic init */
+ generic_init(machine, demon_sound_w);
+
+ /* initialize the CTC interface */
+ demon_z80ctc_interface.baseclock = machine->drv->cpu[1].clock;
+ z80ctc_init(0, &demon_z80ctc_interface);
+
+ /* reset the FIFO */
+ sound_fifo_in = sound_fifo_out = 0;
+ last_portb_write = 0xff;
+
+ /* turn off channel A on AY8910 #0 because it is used as a low-pass filter */
+ AY8910_set_volume(0, 0, 0);
+}
+
+
+static ADDRESS_MAP_START( demon_sound_map, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x1fff) AM_ROM
+ AM_RANGE(0x3000, 0x33ff) AM_RAM
+ AM_RANGE(0x4001, 0x4001) AM_READ(AY8910_read_port_0_r)
+ AM_RANGE(0x4002, 0x4002) AM_WRITE(AY8910_write_port_0_w)
+ AM_RANGE(0x4003, 0x4003) AM_WRITE(AY8910_control_port_0_w)
+ AM_RANGE(0x5001, 0x5001) AM_READ(AY8910_read_port_1_r)
+ AM_RANGE(0x5002, 0x5002) AM_WRITE(AY8910_write_port_1_w)
+ AM_RANGE(0x5003, 0x5003) AM_WRITE(AY8910_control_port_1_w)
+ AM_RANGE(0x6001, 0x6001) AM_READ(AY8910_read_port_2_r)
+ AM_RANGE(0x6002, 0x6002) AM_WRITE(AY8910_write_port_2_w)
+ AM_RANGE(0x6003, 0x6003) AM_WRITE(AY8910_control_port_2_w)
+ AM_RANGE(0x7000, 0x7000) AM_WRITE(MWA8_NOP) /* watchdog? */
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START( demon_sound_ports, ADDRESS_SPACE_IO, 8 )
+ ADDRESS_MAP_FLAGS( AMEF_ABITS(8) )
+ AM_RANGE(0x00, 0x03) AM_WRITE(z80ctc_0_w)
+ AM_RANGE(0x1c, 0x1f) AM_WRITE(z80ctc_0_w)
+ADDRESS_MAP_END
+
+
+static struct z80_irq_daisy_chain daisy_chain[] =
+{
+ { z80ctc_reset, z80ctc_irq_state, z80ctc_irq_ack, z80ctc_irq_reti, 0 },
+ { 0,0,0,0,-1 }
+};
+
+
+MACHINE_DRIVER_START( demon_sound )
+
+ /* basic machine hardware */
+ MDRV_CPU_ADD(Z80, 3579545)
+ /* audio CPU */
+ MDRV_CPU_CONFIG(daisy_chain)
+ MDRV_CPU_PROGRAM_MAP(demon_sound_map,0)
+ MDRV_CPU_IO_MAP(demon_sound_ports,0)
+
+ MDRV_MACHINE_RESET(demon_sound)
+
+ /* sound hardware */
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(AY8910, 3579545)
+ MDRV_SOUND_CONFIG(demon_ay8910_interface_1)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+
+ MDRV_SOUND_ADD(AY8910, 3579545)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+
+ MDRV_SOUND_ADD(AY8910, 3579545)
+ MDRV_SOUND_CONFIG(demon_ay8910_interface_3)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+MACHINE_DRIVER_END
+
+
+
+/*************************************
+ *
+ * QB3
+ *
+ *************************************/
+
+static WRITE8_HANDLER( qb3_sound_w )
+{
+ UINT16 rega = cpunum_get_reg(0, CCPU_A);
+ demon_sound_w(0x00 | (~rega & 0x0f), 0x10);
+}
+
+
+static MACHINE_RESET( qb3_sound )
+{
+ machine_reset_demon_sound(machine);
+ memory_install_write8_handler(0, ADDRESS_SPACE_IO, 0x04, 0x04, 0, 0, qb3_sound_w);
+
+ /* this patch prevents the sound ROM from eating itself when command $0A is sent */
+ /* on a cube rotate */
+ memory_region(REGION_CPU2)[0x11dc] = 0x09;
+}
+
+
+MACHINE_DRIVER_START( qb3_sound )
+ MDRV_IMPORT_FROM(demon_sound)
+ MDRV_MACHINE_RESET(qb3_sound)
+MACHINE_DRIVER_END