summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/generic.c')
-rw-r--r--trunk/src/emu/machine/generic.c769
1 files changed, 769 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/generic.c b/trunk/src/emu/machine/generic.c
new file mode 100644
index 00000000000..b2d2f6ee15e
--- /dev/null
+++ b/trunk/src/emu/machine/generic.c
@@ -0,0 +1,769 @@
+/*********************************************************************
+
+ generic.c
+
+ Generic simple machine functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "config.h"
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void counters_load(running_machine &machine, int config_type, xml_data_node *parentnode);
+static void counters_save(running_machine &machine, int config_type, xml_data_node *parentnode);
+static void interrupt_reset(running_machine &machine);
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+struct _generic_machine_private
+{
+ /* tickets and coin counters */
+ UINT32 dispensed_tickets;
+ UINT32 coin_count[COIN_COUNTERS];
+ UINT32 coinlockedout[COIN_COUNTERS];
+ UINT32 lastcoin[COIN_COUNTERS];
+
+ /* memory card status */
+ int memcard_inserted;
+
+ /* interrupt status for up to 8 CPUs */
+ device_t * interrupt_device[8];
+ UINT8 interrupt_enable[8];
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ interrupt_enabled - return true if interrupts
+ are enabled for the given CPU
+-------------------------------------------------*/
+
+INLINE int interrupt_enabled(device_t *device)
+{
+ generic_machine_private *state = device->machine().generic_machine_data;
+ for (int index = 0; index < ARRAY_LENGTH(state->interrupt_device); index++)
+ if (state->interrupt_device[index] == device)
+ return state->interrupt_enable[index];
+ return TRUE;
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generic_machine_init - initialize globals and
+ register for save states
+-------------------------------------------------*/
+
+void generic_machine_init(running_machine &machine)
+{
+ generic_machine_private *state;
+ int counternum;
+
+ /* allocate our state */
+ machine.generic_machine_data = auto_alloc_clear(machine, generic_machine_private);
+ state = machine.generic_machine_data;
+
+ /* reset coin counters */
+ for (counternum = 0; counternum < COIN_COUNTERS; counternum++)
+ {
+ state->lastcoin[counternum] = 0;
+ state->coinlockedout[counternum] = 0;
+ }
+
+ // map devices to the interrupt state
+ memset(state->interrupt_device, 0, sizeof(state->interrupt_device));
+ device_execute_interface *exec = NULL;
+ int index = 0;
+ for (bool gotone = machine.devicelist().first(exec); gotone && index < ARRAY_LENGTH(state->interrupt_device); gotone = exec->next(exec))
+ state->interrupt_device[index++] = &exec->device();
+
+ /* register coin save state */
+ machine.save().save_item(NAME(state->coin_count));
+ machine.save().save_item(NAME(state->coinlockedout));
+ machine.save().save_item(NAME(state->lastcoin));
+
+ /* reset memory card info */
+ state->memcard_inserted = -1;
+
+ /* register a reset callback and save state for interrupt enable */
+ machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(interrupt_reset), &machine));
+ machine.save().save_item(NAME(state->interrupt_enable));
+
+ /* register for configuration */
+ config_register(machine, "counters", config_saveload_delegate(FUNC(counters_load), &machine), config_saveload_delegate(FUNC(counters_save), &machine));
+
+ /* for memory cards, request save state and an exit callback */
+ if (machine.config().m_memcard_handler != NULL)
+ {
+ state_save_register_global(machine, state->memcard_inserted);
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(memcard_eject), &machine));
+ }
+}
+
+
+
+/***************************************************************************
+ TICKETS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_dispensed_tickets - return the number of
+ tickets dispensed
+-------------------------------------------------*/
+
+int get_dispensed_tickets(running_machine &machine)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ return state->dispensed_tickets;
+}
+
+
+/*-------------------------------------------------
+ increment_dispensed_tickets - increment the
+ number of dispensed tickets
+-------------------------------------------------*/
+
+void increment_dispensed_tickets(running_machine &machine, int delta)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ state->dispensed_tickets += delta;
+}
+
+
+
+/***************************************************************************
+ COIN COUNTERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ counters_load - load the state of the counters
+ and tickets
+-------------------------------------------------*/
+
+static void counters_load(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ xml_data_node *coinnode, *ticketnode;
+
+ /* on init, reset the counters */
+ if (config_type == CONFIG_TYPE_INIT)
+ {
+ memset(state->coin_count, 0, sizeof(state->coin_count));
+ state->dispensed_tickets = 0;
+ }
+
+ /* only care about game-specific data */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ /* might not have any data */
+ if (parentnode == NULL)
+ return;
+
+ /* iterate over coins nodes */
+ for (coinnode = xml_get_sibling(parentnode->child, "coins"); coinnode; coinnode = xml_get_sibling(coinnode->next, "coins"))
+ {
+ int index = xml_get_attribute_int(coinnode, "index", -1);
+ if (index >= 0 && index < COIN_COUNTERS)
+ state->coin_count[index] = xml_get_attribute_int(coinnode, "number", 0);
+ }
+
+ /* get the single tickets node */
+ ticketnode = xml_get_sibling(parentnode->child, "tickets");
+ if (ticketnode != NULL)
+ state->dispensed_tickets = xml_get_attribute_int(ticketnode, "number", 0);
+}
+
+
+/*-------------------------------------------------
+ counters_save - save the state of the counters
+ and tickets
+-------------------------------------------------*/
+
+static void counters_save(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ int i;
+
+ /* only care about game-specific data */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ /* iterate over coin counters */
+ for (i = 0; i < COIN_COUNTERS; i++)
+ if (state->coin_count[i] != 0)
+ {
+ xml_data_node *coinnode = xml_add_child(parentnode, "coins", NULL);
+ if (coinnode != NULL)
+ {
+ xml_set_attribute_int(coinnode, "index", i);
+ xml_set_attribute_int(coinnode, "number", state->coin_count[i]);
+ }
+ }
+
+ /* output tickets */
+ if (state->dispensed_tickets != 0)
+ {
+ xml_data_node *tickets = xml_add_child(parentnode, "tickets", NULL);
+ if (tickets != NULL)
+ xml_set_attribute_int(tickets, "number", state->dispensed_tickets);
+ }
+}
+
+
+/*-------------------------------------------------
+ coin_counter_w - sets input for coin counter
+-------------------------------------------------*/
+
+void coin_counter_w(running_machine &machine, int num, int on)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ if (num >= ARRAY_LENGTH(state->coin_count))
+ return;
+
+ /* Count it only if the data has changed from 0 to non-zero */
+ if (on && (state->lastcoin[num] == 0))
+ state->coin_count[num]++;
+ state->lastcoin[num] = on;
+}
+
+
+/*-------------------------------------------------
+ coin_counter_get_count - return the coin count
+ for a given coin
+-------------------------------------------------*/
+
+int coin_counter_get_count(running_machine &machine, int num)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ if (num >= ARRAY_LENGTH(state->coin_count))
+ return 0;
+ return state->coin_count[num];
+}
+
+
+/*-------------------------------------------------
+ coin_lockout_w - locks out one coin input
+-------------------------------------------------*/
+
+void coin_lockout_w(running_machine &machine, int num,int on)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ if (num >= ARRAY_LENGTH(state->coinlockedout))
+ return;
+ state->coinlockedout[num] = on;
+}
+
+
+/*-------------------------------------------------
+ coin_lockout_get_state - return current lockout
+ state for a particular coin
+-------------------------------------------------*/
+
+int coin_lockout_get_state(running_machine &machine, int num)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ if (num >= ARRAY_LENGTH(state->coinlockedout))
+ return FALSE;
+ return state->coinlockedout[num];
+}
+
+
+/*-------------------------------------------------
+ coin_lockout_global_w - locks out all the coin
+ inputs
+-------------------------------------------------*/
+
+void coin_lockout_global_w(running_machine &machine, int on)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ int i;
+
+ for (i = 0; i < ARRAY_LENGTH(state->coinlockedout); i++)
+ coin_lockout_w(machine, i, on);
+}
+
+
+
+/***************************************************************************
+ NVRAM MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ nvram_filename - returns filename of system's
+ NVRAM depending of selected BIOS
+-------------------------------------------------*/
+
+static astring nvram_filename(running_machine &machine, astring &result)
+{
+ if (rom_system_bios(machine) == 0 || rom_default_bios(machine) == rom_system_bios(machine)) {
+ result.printf("%s",machine.basename());
+ } else {
+ result.printf("%s_%d",machine.basename(),rom_system_bios(machine) - 1);
+ }
+ return result;
+}
+
+/*-------------------------------------------------
+ nvram_load - load a system's NVRAM
+-------------------------------------------------*/
+
+void nvram_load(running_machine &machine)
+{
+ // only need to do something if we have an NVRAM device or an nvram_handler
+ device_nvram_interface *nvram = NULL;
+ if (!machine.devicelist().first(nvram) && machine.config().m_nvram_handler == NULL)
+ return;
+
+ // open the file; if it exists, call everyone to read from it
+ astring filename;
+ emu_file file(machine.options().nvram_directory(), OPEN_FLAG_READ);
+ if (file.open(nvram_filename(machine,filename), ".nv") == FILERR_NONE)
+ {
+ // read data from general NVRAM handler first
+ if (machine.config().m_nvram_handler != NULL)
+ (*machine.config().m_nvram_handler)(machine, &file, FALSE);
+
+ // find all devices with NVRAM handlers, and read from them next
+ for (bool gotone = (nvram != NULL); gotone; gotone = nvram->next(nvram))
+ nvram->nvram_load(file);
+ }
+
+ // otherwise, tell everyone to initialize their NVRAM areas
+ else
+ {
+ // initialize via the general NVRAM handler first
+ if (machine.config().m_nvram_handler != NULL)
+ (*machine.config().m_nvram_handler)(machine, NULL, FALSE);
+
+ // find all devices with NVRAM handlers, and read from them next
+ for (bool gotone = (nvram != NULL); gotone; gotone = nvram->next(nvram))
+ nvram->nvram_reset();
+ }
+}
+
+
+/*-------------------------------------------------
+ nvram_save - save a system's NVRAM
+-------------------------------------------------*/
+
+void nvram_save(running_machine &machine)
+{
+ // only need to do something if we have an NVRAM device or an nvram_handler
+ device_nvram_interface *nvram = NULL;
+ if (!machine.devicelist().first(nvram) && machine.config().m_nvram_handler == NULL)
+ return;
+
+ // open the file; if it exists, call everyone to read from it
+ astring filename;
+ emu_file file(machine.options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(nvram_filename(machine,filename), ".nv") == FILERR_NONE)
+ {
+ // write data via general NVRAM handler first
+ if (machine.config().m_nvram_handler != NULL)
+ (*machine.config().m_nvram_handler)(machine, &file, TRUE);
+
+ // find all devices with NVRAM handlers, and tell them to write next
+ for (bool gotone = (nvram != NULL); gotone; gotone = nvram->next(nvram))
+ nvram->nvram_save(file);
+ }
+}
+
+
+
+/***************************************************************************
+ MEMORY CARD MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ memcard_name - determine the name of a memcard
+ file
+-------------------------------------------------*/
+
+INLINE void memcard_name(int index, char *buffer)
+{
+ sprintf(buffer, "memcard.%03d", index);
+}
+
+
+/*-------------------------------------------------
+ memcard_create - create a new memory card with
+ the given index
+-------------------------------------------------*/
+
+int memcard_create(running_machine &machine, int index, int overwrite)
+{
+ char name[16];
+
+ /* create a name */
+ memcard_name(index, name);
+
+ /* if we can't overwrite, fail if the file already exists */
+ astring fname(machine.basename(), PATH_SEPARATOR, name);
+ if (!overwrite)
+ {
+ emu_file testfile(machine.options().memcard_directory(), OPEN_FLAG_READ);
+ if (testfile.open(fname) == FILERR_NONE)
+ return 1;
+ }
+
+ /* create a new file */
+ emu_file file(machine.options().memcard_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = file.open(fname);
+ if (filerr != FILERR_NONE)
+ return 1;
+
+ /* initialize and then save the card */
+ if (machine.config().m_memcard_handler)
+ (*machine.config().m_memcard_handler)(machine, file, MEMCARD_CREATE);
+
+ /* close the file */
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ memcard_insert - insert an existing memory card
+ with the given index
+-------------------------------------------------*/
+
+int memcard_insert(running_machine &machine, int index)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ char name[16];
+
+ /* if a card is already inserted, eject it first */
+ if (state->memcard_inserted != -1)
+ memcard_eject(machine);
+ assert(state->memcard_inserted == -1);
+
+ /* create a name */
+ memcard_name(index, name);
+
+ /* open the file; if we can't, it's an error */
+ emu_file file(machine.options().memcard_directory(), OPEN_FLAG_READ);
+ file_error filerr = file.open(machine.basename(), PATH_SEPARATOR, name);
+ if (filerr != FILERR_NONE)
+ return 1;
+
+ /* initialize and then load the card */
+ if (machine.config().m_memcard_handler)
+ (*machine.config().m_memcard_handler)(machine, file, MEMCARD_INSERT);
+
+ /* close the file */
+ state->memcard_inserted = index;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ memcard_eject - eject a memory card, saving
+ its contents along the way
+-------------------------------------------------*/
+
+void memcard_eject(running_machine &machine)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ char name[16];
+
+ /* if no card is preset, just ignore */
+ if (state->memcard_inserted == -1)
+ return;
+
+ /* create a name */
+ memcard_name(state->memcard_inserted, name);
+
+ /* open the file; if we can't, it's an error */
+ emu_file file(machine.options().memcard_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = file.open(machine.basename(), PATH_SEPARATOR, name);
+ if (filerr != FILERR_NONE)
+ return;
+
+ /* initialize and then load the card */
+ if (machine.config().m_memcard_handler)
+ (*machine.config().m_memcard_handler)(machine, file, MEMCARD_EJECT);
+
+ /* close the file */
+ state->memcard_inserted = -1;
+}
+
+
+/*-------------------------------------------------
+ memcard_present - return the currently loaded
+ card index, or -1 if none
+-------------------------------------------------*/
+
+int memcard_present(running_machine &machine)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ return state->memcard_inserted;
+}
+
+
+
+/***************************************************************************
+ LED CODE
+***************************************************************************/
+
+/*-------------------------------------------------
+ set_led_status - set the state of a given LED
+-------------------------------------------------*/
+
+void set_led_status(running_machine &machine, int num, int on)
+{
+ output_set_led_value(num, on);
+}
+
+
+
+/***************************************************************************
+ INTERRUPT ENABLE AND VECTOR HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ interrupt_reset - reset the interrupt enable
+ states on a reset
+-------------------------------------------------*/
+
+static void interrupt_reset(running_machine &machine)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ int cpunum;
+
+ /* on a reset, enable all interrupts */
+ for (cpunum = 0; cpunum < ARRAY_LENGTH(state->interrupt_enable); cpunum++)
+ state->interrupt_enable[cpunum] = 1;
+}
+
+
+/*-------------------------------------------------
+ clear_all_lines - sets the state of all input
+ lines and the NMI line to clear
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( clear_all_lines )
+{
+ cpu_device *cpudevice = reinterpret_cast<cpu_device *>(ptr);
+
+ // clear NMI
+ cpudevice->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
+
+ // clear all other inputs
+ int inputcount = cpudevice->input_lines();
+ for (int line = 0; line < inputcount; line++)
+ cpudevice->set_input_line(line, CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ irq_pulse_clear - clear a "pulsed" IRQ line
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( irq_pulse_clear )
+{
+ device_t *device = (device_t *)ptr;
+ int irqline = param;
+ device_set_input_line(device, irqline, CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ generic_pulse_irq_line - "pulse" an IRQ line by
+ asserting it and then clearing it 1 cycle
+ later
+-------------------------------------------------*/
+
+void generic_pulse_irq_line(device_t *device, int irqline)
+{
+ assert(irqline != INPUT_LINE_NMI && irqline != INPUT_LINE_RESET);
+ device_set_input_line(device, irqline, ASSERT_LINE);
+
+ cpu_device *cpudevice = downcast<cpu_device *>(device);
+ attotime target_time = cpudevice->local_time() + cpudevice->cycles_to_attotime(cpudevice->min_cycles());
+ device->machine().scheduler().timer_set(target_time - device->machine().time(), FUNC(irq_pulse_clear), irqline, (void *)device);
+}
+
+
+/*-------------------------------------------------
+ generic_pulse_irq_line_and_vector - "pulse" an
+ IRQ line by asserting it and then clearing it
+ 1 cycle later, specifying a vector
+-------------------------------------------------*/
+
+void generic_pulse_irq_line_and_vector(device_t *device, int irqline, int vector)
+{
+ assert(irqline != INPUT_LINE_NMI && irqline != INPUT_LINE_RESET);
+ device_set_input_line_and_vector(device, irqline, ASSERT_LINE, vector);
+
+ cpu_device *cpudevice = downcast<cpu_device *>(device);
+ attotime target_time = cpudevice->local_time() + cpudevice->cycles_to_attotime(cpudevice->min_cycles());
+ device->machine().scheduler().timer_set(target_time - device->machine().time(), FUNC(irq_pulse_clear), irqline, (void *)device);
+}
+
+
+/*-------------------------------------------------
+ cpu_interrupt_enable - controls the enable/
+ disable value for global interrupts
+-------------------------------------------------*/
+
+void cpu_interrupt_enable(device_t *device, int enabled)
+{
+ cpu_device *cpudevice = downcast<cpu_device *>(device);
+
+ generic_machine_private *state = device->machine().generic_machine_data;
+ int index;
+ for (index = 0; index < ARRAY_LENGTH(state->interrupt_device); index++)
+ if (state->interrupt_device[index] == device)
+ break;
+ assert_always(index < ARRAY_LENGTH(state->interrupt_enable), "cpu_interrupt_enable() called for invalid CPU!");
+
+ /* set the new state */
+ if (index < ARRAY_LENGTH(state->interrupt_enable))
+ state->interrupt_enable[index] = enabled;
+
+ /* make sure there are no queued interrupts */
+ if (enabled == 0)
+ device->machine().scheduler().synchronize(FUNC(clear_all_lines), 0, (void *)cpudevice);
+}
+
+
+/*-------------------------------------------------
+ interrupt_enable_w - set the global interrupt
+ enable
+-------------------------------------------------*/
+
+WRITE8_HANDLER( interrupt_enable_w )
+{
+ cpu_interrupt_enable(&space->device(), data);
+}
+
+
+/*-------------------------------------------------
+ interrupt_enable_r - read the global interrupt
+ enable
+-------------------------------------------------*/
+
+READ8_HANDLER( interrupt_enable_r )
+{
+ return interrupt_enabled(&space->device());
+}
+
+
+
+/***************************************************************************
+ INTERRUPT GENERATION CALLBACK HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ NMI callbacks
+-------------------------------------------------*/
+
+INTERRUPT_GEN( nmi_line_pulse ) { if (interrupt_enabled(device)) device_set_input_line(device, INPUT_LINE_NMI, PULSE_LINE); }
+INTERRUPT_GEN( nmi_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, INPUT_LINE_NMI, ASSERT_LINE); }
+
+
+/*-------------------------------------------------
+ IRQn callbacks
+-------------------------------------------------*/
+
+INTERRUPT_GEN( irq0_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 0, HOLD_LINE); }
+INTERRUPT_GEN( irq0_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 0); }
+INTERRUPT_GEN( irq0_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 0, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq1_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 1, HOLD_LINE); }
+INTERRUPT_GEN( irq1_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 1); }
+INTERRUPT_GEN( irq1_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 1, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq2_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 2, HOLD_LINE); }
+INTERRUPT_GEN( irq2_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 2); }
+INTERRUPT_GEN( irq2_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 2, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq3_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 3, HOLD_LINE); }
+INTERRUPT_GEN( irq3_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 3); }
+INTERRUPT_GEN( irq3_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 3, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq4_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 4, HOLD_LINE); }
+INTERRUPT_GEN( irq4_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 4); }
+INTERRUPT_GEN( irq4_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 4, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq5_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 5, HOLD_LINE); }
+INTERRUPT_GEN( irq5_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 5); }
+INTERRUPT_GEN( irq5_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 5, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq6_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 6, HOLD_LINE); }
+INTERRUPT_GEN( irq6_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 6); }
+INTERRUPT_GEN( irq6_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 6, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq7_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 7, HOLD_LINE); }
+INTERRUPT_GEN( irq7_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 7); }
+INTERRUPT_GEN( irq7_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 7, ASSERT_LINE); }
+
+
+
+/***************************************************************************
+ WATCHDOG READ/WRITE HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ 8-bit reset read/write handlers
+-------------------------------------------------*/
+
+WRITE8_HANDLER( watchdog_reset_w ) { watchdog_reset(space->machine()); }
+READ8_HANDLER( watchdog_reset_r ) { watchdog_reset(space->machine()); return space->unmap(); }
+
+
+/*-------------------------------------------------
+ 16-bit reset read/write handlers
+-------------------------------------------------*/
+
+WRITE16_HANDLER( watchdog_reset16_w ) { watchdog_reset(space->machine()); }
+READ16_HANDLER( watchdog_reset16_r ) { watchdog_reset(space->machine()); return space->unmap(); }
+
+
+/*-------------------------------------------------
+ 32-bit reset read/write handlers
+-------------------------------------------------*/
+
+WRITE32_HANDLER( watchdog_reset32_w ) { watchdog_reset(space->machine()); }
+READ32_HANDLER( watchdog_reset32_r ) { watchdog_reset(space->machine()); return space->unmap(); }
+
+
+
+/***************************************************************************
+ PORT READING HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ custom_port_read - act like input_port_read
+ but it is a custom port, it is useful for
+ e.g. input ports which expect the same port
+ repeated both in the upper and lower half
+-------------------------------------------------*/
+
+CUSTOM_INPUT( custom_port_read )
+{
+ const char *tag = (const char *)param;
+ return input_port_read(field.machine(), tag);
+}