summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/audio/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/audio/generic.c')
-rw-r--r--trunk/src/emu/audio/generic.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/trunk/src/emu/audio/generic.c b/trunk/src/emu/audio/generic.c
new file mode 100644
index 00000000000..a40474d9da2
--- /dev/null
+++ b/trunk/src/emu/audio/generic.c
@@ -0,0 +1,168 @@
+/***************************************************************************
+
+ generic.c
+
+ Generic simple sound functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+struct _generic_audio_private
+{
+ UINT16 latch_clear_value;
+ UINT16 latched_value[4];
+ UINT8 latch_read[4];
+};
+
+
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generic_sound_init - initialize globals and
+ register for save states
+-------------------------------------------------*/
+
+int generic_sound_init(running_machine &machine)
+{
+ generic_audio_private *state;
+
+ state = machine.generic_audio_data = auto_alloc_clear(machine, generic_audio_private);
+
+ /* register globals with the save state system */
+ state_save_register_global_array(machine, state->latched_value);
+ state_save_register_global_array(machine, state->latch_read);
+
+ return 0;
+}
+
+
+
+/***************************************************************************
+
+ Many games use a master-slave CPU setup. Typically, the main CPU writes
+ a command to some register, and then writes to another register to trigger
+ an interrupt on the slave CPU (the interrupt might also be triggered by
+ the first write). The slave CPU, notified by the interrupt, goes and reads
+ the command.
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ latch_callback - time-delayed callback to
+ set a latch value
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( latch_callback )
+{
+ generic_audio_private *state = machine.generic_audio_data;
+ UINT16 value = param >> 8;
+ int which = param & 0xff;
+
+ /* if the latch hasn't been read and the value is changed, log a warning */
+ if (!state->latch_read[which] && state->latched_value[which] != value)
+ logerror("Warning: sound latch %d written before being read. Previous: %02x, new: %02x\n", which, state->latched_value[which], value);
+
+ /* store the new value and mark it not read */
+ state->latched_value[which] = value;
+ state->latch_read[which] = 0;
+}
+
+
+/*-------------------------------------------------
+ latch_w - handle a write to a given latch
+-------------------------------------------------*/
+
+INLINE void latch_w(address_space *space, int which, UINT16 value)
+{
+ space->machine().scheduler().synchronize(FUNC(latch_callback), which | (value << 8));
+}
+
+
+/*-------------------------------------------------
+ latch_r - handle a read from a given latch
+-------------------------------------------------*/
+
+INLINE UINT16 latch_r(address_space *space, int which)
+{
+ generic_audio_private *state = space->machine().generic_audio_data;
+ state->latch_read[which] = 1;
+ return state->latched_value[which];
+}
+
+
+/*-------------------------------------------------
+ latch_clear - clear a given latch
+-------------------------------------------------*/
+
+INLINE void latch_clear(address_space *space, int which)
+{
+ generic_audio_private *state = space->machine().generic_audio_data;
+ state->latched_value[which] = state->latch_clear_value;
+}
+
+
+/*-------------------------------------------------
+ soundlatch_w - global write handlers for
+ writing to sound latches
+-------------------------------------------------*/
+
+WRITE8_HANDLER( soundlatch_w ) { latch_w(space, 0, data); }
+WRITE16_HANDLER( soundlatch_word_w ) { latch_w(space, 0, data); }
+WRITE8_HANDLER( soundlatch2_w ) { latch_w(space, 1, data); }
+WRITE16_HANDLER( soundlatch2_word_w ) { latch_w(space, 1, data); }
+WRITE8_HANDLER( soundlatch3_w ) { latch_w(space, 2, data); }
+WRITE16_HANDLER( soundlatch3_word_w ) { latch_w(space, 2, data); }
+WRITE8_HANDLER( soundlatch4_w ) { latch_w(space, 3, data); }
+WRITE16_HANDLER( soundlatch4_word_w ) { latch_w(space, 3, data); }
+
+
+/*-------------------------------------------------
+ soundlatch_r - global read handlers for
+ reading from sound latches
+-------------------------------------------------*/
+
+READ8_HANDLER( soundlatch_r ) { return latch_r(space, 0); }
+READ16_HANDLER( soundlatch_word_r ) { return latch_r(space, 0); }
+READ8_HANDLER( soundlatch2_r ) { return latch_r(space, 1); }
+READ16_HANDLER( soundlatch2_word_r ) { return latch_r(space, 1); }
+READ8_HANDLER( soundlatch3_r ) { return latch_r(space, 2); }
+READ16_HANDLER( soundlatch3_word_r ) { return latch_r(space, 2); }
+READ8_HANDLER( soundlatch4_r ) { return latch_r(space, 3); }
+READ16_HANDLER( soundlatch4_word_r ) { return latch_r(space, 3); }
+
+
+/*-------------------------------------------------
+ soundlatch_clear_w - global write handlers
+ for clearing sound latches
+-------------------------------------------------*/
+
+WRITE8_HANDLER( soundlatch_clear_w ) { latch_clear(space, 0); }
+WRITE8_HANDLER( soundlatch2_clear_w ) { latch_clear(space, 1); }
+WRITE8_HANDLER( soundlatch3_clear_w ) { latch_clear(space, 2); }
+WRITE8_HANDLER( soundlatch4_clear_w ) { latch_clear(space, 3); }
+
+
+/*-------------------------------------------------
+ soundlatch_setclearedvalue - set the "clear"
+ value for all sound latches
+-------------------------------------------------*/
+
+void soundlatch_setclearedvalue(running_machine &machine, int value)
+{
+ generic_audio_private *state = machine.generic_audio_data;
+ assert_always(machine.phase() == MACHINE_PHASE_INIT, "Can only call soundlatch_setclearedvalue at init time!");
+ state->latch_clear_value = value;
+}