/***************************************************************************

	Bally/Sente SAC-1 system

	Currently implemented:
		* Chicken Shift
		* Gimme a Break
		* Goalie Ghost
		* Hat Trick
		* Mini Golf
		* Night Stocker
		* Off the Wall
		* Rescue Raider
		* Sente Diagnostic Cartridge
		* Snacks'n Jaxson
		* Stocker
		* Street Football
		* Toggle
		* Trivial Pursuit (Genus I)
		* Trivial Pursuit (All Sports Edition)

	Currently implemented, but no good dumps known to exist:
		* Snake Pit

	Looking for ROMs for these:
		* Euro Stocker
		* Name that Tune
		* Spiker
		* Stompin'
		* Strike Avenger
		* Team Hat Trick
		* Trick Shot
		* Trivial Pursuit (Genus II)
		* Trivial Pursuit (Spanish)
		* Trivial Pursuit (Young Player's Edition)
		* Trivial Pursuit (Baby Boomer Series)

	Unknowns:
		* Snack Attack (may be another name for Snacks'n Jaxson)

****************************************************************************

	Memory map

****************************************************************************

	========================================================================
	CPU #1
	========================================================================
	0000-007F   R/W   xxxxxxxx    Sprite RAM (32 entries x 4 bytes)
	            R/W   x-------       (0: Vertical flip)
	            R/W   -x------       (0: Horizontal flip)
	            R/W   ------xx       (0: Upper 2 bits of image number)
	            R/W   xxxxxxxx       (1: Lower 8 bits of image number)
	            R/W   xxxxxxxx       (2: Y position, offset by 17 pixels)
	            R/W   xxxxxxxx       (3: X position)
	0080-00DF   R/W   xxxxxxxx    Program RAM
	00E0-00FF   R/W   xxxxxxxx    Additional sprite RAM (8 entries x 4 bytes)
	0100-07FF   R/W   xxxxxxxx    Program RAM
	0800-7FFF   R/W   xxxxxxxx    Video RAM (256x240 pixels)
	            R/W   xxxx----       (left pixel)
	            R/W   ----xxxx       (right pixel)
	8000-8FFF   R/W   ----xxxx    Palette RAM (1024 entries x 4 bytes)
	            R/W   ----xxxx       (0: red entry)
	            R/W   ----xxxx       (1: green entry)
	            R/W   ----xxxx       (2: blue entry)
	9000-9007     W   --------    ADC start trigger, inputs 0-7
	9400        R     xxxxxxxx    ADC data read
	9800-9801     W   x-------    External output #0
	9802-9803     W   x-------    External output #1
	9804-9805     W   x-------    External output #2
	9806-9807     W   x-------    External output #3
	9808-9809     W   x-------    External output #4
	980A-980B     W   x-------    External output #5
	980C-980D     W   x-------    External output #6
	980E-980F     W   x-------    NVRAM recall
	9880          W   --------    Random number generator reset
	98A0          W   -xxx----    A000-DFFF bank select
	98C0          W   ------xx    Palette bank select
	98E0          W   --------    Watchdog reset
	9900        R     xxxxxxxx    DIP switch bank 1 (G) (active low)
	9901        R     xxxxxxxx    DIP switch bank 2 (H) (active low)
	9902        R     x-------    Self test (active low)
	            R     -x------    Left coin (active low)
	            R     --xxxxxx    External inputs (active low)
	9903        R     x-------    VBLANK state (active high)
	            R     -x------    Right coin (active low)
	            R     --xxxx--    External inputs (active low)
	            R     ------x-    Player 2 start (active low)
	            R     -------x    Player 1 start (active low)
	9A00        R     xxxxxxxx    Random number generator
	9A04-9A05   R/W   xxxxxxxx    6850 UART I/O (to sound board)
	9B00-9CFF   R/W   xxxxxxxx    NOVRAM
	9F00          W   --x--xxx    Independent bank select (Night Stocker only?)
	A000-BFFF   R     xxxxxxxx    Banked A/B ROM
	C000-DFFF   R     xxxxxxxx    Banked C/D ROM
	E000-FFFF   R     xxxxxxxx    Fixed program ROM
	========================================================================
	Interrupts:
		NMI not connected
		IRQ generated by 32L
		FIRQ generated by 6850 UART
	========================================================================


	========================================================================
	CPU #2
	========================================================================
	0000-1FFF   R     xxxxxxxx    Program ROM
	2000-3FFF   R/W   xxxxxxxx    Option RAM/ROM (assumed to be RAM for now)
	4000-5FFF   R/W   xxxxxxxx    Program RAM
	6000-6001     W   xxxxxxxx    6850 UART output (to main board)
	E000-E001   R     xxxxxxxx    6850 UART input (from main board)
	========================================================================
    0000-0003   R/W   xxxxxxxx    8253 counter chip I/O
    0008        R     ------xx    Counter state
                R     ------x-    State of counter #0 OUT signal (active high)
                R     -------x    State of flip-flop feeding counter #0 (active low)
    0008          W   --xxxxxx    Counter control
                  W   --x-----    NMI enable (1=enabled, 0=disabled/clear)
                  W   ---x----    CLEAR on flip-flop feeding counter #0 (active low)
                  W   ----x---    Input of flip-flop feeding counter #0
                  W   -----x--    PRESET on flip-flop feeding counter #0 (active low)
                  W   ------x-    GATE signal for counter #0 (active high)
                  W   -------x    Audio enable
    000A          W   --xxxxxx    DAC data latch (upper 6 bits)
    000B          W   xxxxxx--    DAC data latch (lower 6 bits)
    000C          W   -----xxx    CEM3394 register select
    000E          W   --xxxxxx    CEM3394 chip enable (active high)
                  W   --x-----    CEM3394 chip 0 enable
                  W   ---x----    CEM3394 chip 1 enable
                  W   ----x---    CEM3394 chip 2 enable
                  W   -----x--    CEM3394 chip 3 enable
                  W   ------x-    CEM3394 chip 4 enable
                  W   -------x    CEM3394 chip 5 enable
	========================================================================
	Interrupts:
		INT generated by counter #2 OUT signal on 8253
		NMI generated by 6850 UART
	========================================================================

***************************************************************************/


#include "driver.h"
#include "cpu/m6809/m6809.h"
#include "vidhrdw/generic.h"
#include <math.h>



/* video driver data & functions */
int balsente_vh_start(void);
void balsente_vh_stop(void);
void balsente_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh);

void balsente_videoram_w(int offset, int data);
void balsente_paletteram_w(int offset, int data);
void balsente_palette_select_w(int offset, int data);


/* local prototypes */
static void poly17_init(void);
static void counter_set_out(int which, int gate);
static void m6850_w(int offset, int data);
static void m6850_sound_w(int offset, int data);
static void counter_callback(int param);


/* global data */
UINT8 balsente_shooter;
UINT8 balsente_shooter_x;
UINT8 balsente_shooter_y;


/* 8253 counter state */
struct counter_state
{
	void *timer;
	INT32 initial;
	INT32 count;
	UINT8 gate;
	UINT8 out;
	UINT8 mode;
	UINT8 readbyte;
	UINT8 writebyte;
};

static struct counter_state counter[3];

/* manually clocked counter 0 states */
static UINT8 counter_control;
static UINT8 counter_0_ff;
static void *counter_0_timer;

/* random number generator states */
static UINT8 *poly17 = NULL;
static UINT8 *rand17 = NULL;

/* ADC I/O states */
static INT8 analog_input_data[4];
static UINT8 adc_value;
static UINT8 adc_shift;

/* CEM3394 DAC control states */
static UINT16 dac_value;
static UINT8 dac_register;
static UINT8 chip_select;

/* main CPU 6850 states */
static UINT8 m6850_status;
static UINT8 m6850_control;
static UINT8 m6850_input;
static UINT8 m6850_output;
static UINT8 m6850_data_ready;

/* sound CPU 6850 states */
static UINT8 m6850_sound_status;
static UINT8 m6850_sound_control;
static UINT8 m6850_sound_input;
static UINT8 m6850_sound_output;

/* noise generator states */
static UINT32 noise_position[6];

/* game-specific states */
static UINT8 nstocker_bits;



/*************************************
 *
 *	Interrupt handling
 *
 *************************************/

static void irq_off(int param)
{
	cpu_set_irq_line(0, M6809_IRQ_LINE, CLEAR_LINE);
}


static void interrupt_timer(int param)
{
	/* next interrupt after scanline 256 is scanline 64 */
	if (param == 256)
		timer_set(cpu_getscanlinetime(64), 64, interrupt_timer);
	else
		timer_set(cpu_getscanlinetime(param + 64), param + 64, interrupt_timer);

	/* IRQ starts on scanline 0, 64, 128, etc. */
	cpu_set_irq_line(0, M6809_IRQ_LINE, ASSERT_LINE);

	/* it will turn off on the next HBLANK */
	timer_set(cpu_getscanlineperiod() * 0.9, 0, irq_off);

	/* if we're a shooter, we do a little more work */
	if (balsente_shooter)
	{
		UINT8 tempx, tempy;

		/* we latch the beam values on the first interrupt after VBLANK */
		if (param == 64 && balsente_shooter)
		{
			balsente_shooter_x = input_port_8_r(0);
			balsente_shooter_y = input_port_9_r(0);
		}

		/* which bits get returned depends on which scanline we're at */
		tempx = balsente_shooter_x << ((param - 64) / 64);
		tempy = balsente_shooter_y << ((param - 64) / 64);
		nstocker_bits = ((tempx >> 4) & 0x08) | ((tempx >> 1) & 0x04) |
						((tempy >> 6) & 0x02) | ((tempy >> 3) & 0x01);
	}
}


static void init_machine(void)
{
	/* create the polynomial tables */
	poly17_init();

	/* reset counters; counter 2's gate is tied high */
	memset(counter, 0, sizeof(counter));
	counter[2].gate = 1;

	/* reset the manual counter 0 clock */
	counter_control = 0x00;
	counter_0_ff = 0;
	counter_0_timer = NULL;

	/* reset the ADC states */
	adc_value = 0;

	/* reset the CEM3394 I/O states */
	dac_value = 0;
	dac_register = 0;
	chip_select = 0x3f;

	/* reset the 6850 chips */
	m6850_w(0, 3);
	m6850_sound_w(0, 3);

	/* reset the noise generator */
	memset(noise_position, 0, sizeof(noise_position));

	/* point the banks to bank 0 */
	cpu_setbank(1, &Machine->memory_region[0][0x10000]);
	cpu_setbank(2, &Machine->memory_region[0][0x12000]);

	/* start a timer to generate interrupts */
	timer_set(cpu_getscanlinetime(0), 0, interrupt_timer);
}



/*************************************
 *
 *	MM5837 noise generator
 *
 *	NOTE: this is stolen straight from
 *			POKEY.c
 *
 *************************************/

#define POLY17_BITS 17
#define POLY17_SIZE ((1 << POLY17_BITS) - 1)
#define POLY17_SHL	7
#define POLY17_SHR	10
#define POLY17_ADD	0x18000

static void poly17_init(void)
{
	UINT32 i, x = 0;
	UINT8 *p, *r;

	/* free stale memory */
	if (poly17)
		free(poly17);
	poly17 = rand17 = NULL;

	/* allocate memory */
	p = poly17 = malloc(2 * (POLY17_SIZE + 1));
	if (!poly17)
		return;
	r = rand17 = poly17 + POLY17_SIZE + 1;

	/* generate the polynomial */
	for (i = 0; i < POLY17_SIZE; i++)
	{
        /* store new values */
		*p++ = x & 1;
		*r++ = x >> 3;

        /* calculate next bit */
		x = ((x << POLY17_SHL) + (x >> POLY17_SHR) + POLY17_ADD) & POLY17_SIZE;
	}
}


static void noise_gen(int chip, int count, short *buffer)
{
	if (Machine->sample_rate)
	{
		/* noise generator runs at 100kHz */
		UINT32 step = (100000 << 14) / Machine->sample_rate;
		UINT32 noise_counter = noise_position[chip];

		/* try to use the poly17 if we can */
		if (poly17)
		{
			while (count--)
			{
				*buffer++ = poly17[(noise_counter >> 14) & POLY17_SIZE] << 12;
				noise_counter += step;
			}
		}

		/* otherwise just use random numbers */
		else
		{
			while (count--)
				*buffer++ = rand() & 0x1000;
		}

		/* remember the noise position */
		noise_position[chip] = noise_counter;
	}
}



/*************************************
 *
 *	Hardware random numbers
 *
 *************************************/

static void random_reset_w(int offset, int data)
{
	/* reset random number generator */
}

#ifdef __BEOS__
static int beos_random_r(int offset)
#else
static int random_r(int offset)
#endif
{
	unsigned int cc;

	/* CPU runs at 1.25MHz, noise source at 100kHz --> multiply by 12.5 */
	cc = cpu_gettotalcycles();

	/* 12.5 = 8 + 4 + 0.5 */
	cc = (cc << 3) + (cc << 2) + (cc >> 1);
	return rand17[cc & POLY17_SIZE];
}



/*************************************
 *
 *	ROM banking
 *
 *************************************/

static void rombank_select_w(int offset, int data)
{
	int bank_offset = 0x6000 * ((data >> 4) & 7);

//if (errorlog) fprintf(errorlog, "%04X:rombank_select_w(%02X)\n", cpu_getpreviouspc(), data);

	/* the bank number comes from bits 4-6 */
	cpu_setbank(1, &Machine->memory_region[0][0x10000 + bank_offset]);
	cpu_setbank(2, &Machine->memory_region[0][0x12000 + bank_offset]);
}


static void rombank2_select_w(int offset, int data)
{
	/* night stocker only? */

//if (errorlog) fprintf(errorlog, "%04X:rombank2_select_w(%02X)\n", cpu_getpreviouspc(), data);

	/* when they set the AB bank, it appears as though the CD bank is reset */
	if (data & 0x20)
	{
		cpu_setbank(1, &Machine->memory_region[0][0x10000 + 0x6000 * (data & 7)]);
		cpu_setbank(2, &Machine->memory_region[0][0x12000 + 0x6000 * 6]);
	}

	/* set the CD bank */
	else
	{
		cpu_setbank(2, &Machine->memory_region[0][0x12000 + 0x6000 * (data & 7)]);
	}
}



/*************************************
 *
 *	Special outputs
 *
 *************************************/

static void misc_output_w(int offset, int data)
{
	offset = (offset / 4) % 8;
	data >>= 7;

	/* these are generally used to control the various lamps */
	/* special case is offset 7, which recalls the NVRAM data */
	if (offset == 7)
	{
		if (errorlog) fprintf(errorlog, "nvrecall_w=%d\n", data);
	}
	else
	{
//		osd_led_w(offset, data);
	}
}



/*************************************
 *
 *	6850 UART communications
 *
 *************************************/

static void m6850_update_io(void)
{
	UINT8 new_state;

	/* sound -> main CPU communications */
	if (!(m6850_sound_status & 0x02))
	{
		/* set the overrun bit if the data in the destination hasn't been read yet */
		if (m6850_status & 0x01)
			m6850_status |= 0x20;

		/* copy the sound's output to our input */
		m6850_input = m6850_sound_output;

		/* set the receive register full bit */
		m6850_status |= 0x01;

		/* set the sound's trasmitter register empty bit */
		m6850_sound_status |= 0x02;
	}

	/* main -> sound CPU communications */
	if (m6850_data_ready)
	{
		/* set the overrun bit if the data in the destination hasn't been read yet */
		if (m6850_sound_status & 0x01)
			m6850_sound_status |= 0x20;

		/* copy the main CPU's output to our input */
		m6850_sound_input = m6850_output;

		/* set the receive register full bit */
		m6850_sound_status |= 0x01;

		/* set the main CPU's trasmitter register empty bit */
		m6850_status |= 0x02;
		m6850_data_ready = 0;
	}

	/* check for reset states */
	if ((m6850_control & 3) == 3)
	{
		m6850_status = 0x02;
		m6850_data_ready = 0;
	}
	if ((m6850_sound_control & 3) == 3)
		m6850_sound_status = 0x02;

	/* check for transmit/receive IRQs on the main CPU */
	new_state = 0;
	if ((m6850_control & 0x80) && (m6850_status & 0x21)) new_state = 1;
	if ((m6850_control & 0x60) == 0x20 && (m6850_status & 0x02)) new_state = 1;

	/* apply the change */
	if (new_state && !(m6850_status & 0x80))
	{
		cpu_set_irq_line(0, M6809_FIRQ_LINE, ASSERT_LINE);
		m6850_status |= 0x80;
	}
	else if (!new_state && (m6850_status & 0x80))
	{
		cpu_set_irq_line(0, M6809_FIRQ_LINE, CLEAR_LINE);
		m6850_status &= ~0x80;
	}

	/* check for transmit/receive IRQs on the sound CPU */
	new_state = 0;
	if ((m6850_sound_control & 0x80) && (m6850_sound_status & 0x21)) new_state = 1;
	if ((m6850_sound_control & 0x60) == 0x20 && (m6850_sound_status & 0x02)) new_state = 1;
	if (!(counter_control & 0x20)) new_state = 0;

	/* apply the change */
	if (new_state && !(m6850_sound_status & 0x80))
	{
		cpu_set_nmi_line(1, ASSERT_LINE);
		m6850_sound_status |= 0x80;
	}
	else if (!new_state && (m6850_sound_status & 0x80))
	{
		cpu_set_nmi_line(1, CLEAR_LINE);
		m6850_sound_status &= ~0x80;
	}
}



/*************************************
 *
 *	6850 UART (main CPU)
 *
 *************************************/

static int m6850_r(int offset)
{
	int result;

	/* status register is at offset 0 */
	if (offset == 0)
	{
		result = m6850_status;
	}

	/* input register is at offset 1 */
	else
	{
		result = m6850_input;

		/* clear the overrun and receive buffer full bits */
		m6850_status &= ~0x21;
		m6850_update_io();
	}

	return result;
}


static void m6850_data_ready_callback(int param)
{
	/* set the output data byte and indicate that we're ready to go */
	m6850_output = param;
	m6850_data_ready = 1;
	m6850_update_io();
}


static void m6850_w_callback(int param)
{
	/* indicate that the transmit buffer is no longer empty and update the I/O state */
	m6850_status &= ~0x02;
	m6850_update_io();

	/* set a timer for 500usec later to actually transmit the data */
	/* (this is very important for several games, esp Snacks'n Jaxson) */
	timer_set(TIME_IN_USEC(500), param, m6850_data_ready_callback);
}


static void m6850_w(int offset, int data)
{
	/* control register is at offset 0 */
	if (offset == 0)
	{
		m6850_control = data;

		/* re-update since interrupt enables could have been modified */
		m6850_update_io();
	}

	/* output register is at offset 1; set a timer to synchronize the CPUs */
	else
		timer_set(TIME_NOW, data, m6850_w_callback);
}



/*************************************
 *
 *	6850 UART (sound CPU)
 *
 *************************************/

static int m6850_sound_r(int offset)
{
	int result;

	/* status register is at offset 0 */
	if (offset == 0)
	{
		result = m6850_sound_status;
	}

	/* input register is at offset 1 */
	else
	{
		result = m6850_sound_input;

		/* clear the overrun and receive buffer full bits */
		m6850_sound_status &= ~0x21;
		m6850_update_io();
	}

	return result;
}


static void m6850_sound_w(int offset, int data)
{
	/* control register is at offset 0 */
	if (offset == 0)
		m6850_sound_control = data;

	/* output register is at offset 1 */
	else
	{
		m6850_sound_output = data;
		m6850_sound_status &= ~0x02;
	}

	/* re-update since interrupt enables could have been modified */
	m6850_update_io();
}



/*************************************
 *
 *	ADC handlers
 *
 *************************************/

static int update_analog_inputs(void)
{
	int i;

	/* the analog input system helpfully scales the value read by the percentage of time */
	/* into the current frame we are; unfortunately, this is bad for us, since the analog */
	/* ports are read once a frame, just at varying intervals. To get around this, we */
	/* read all the analog inputs at VBLANK time and just return the cached values. */
	for (i = 0; i < 4; i++)
		analog_input_data[i] = readinputport(4 + i);

	/* don't actually generate an interrupt here */
	return ignore_interrupt();
}


static void adc_finished(int which)
{
	/* analog controls are read in two pieces; the lower port returns the sign */
	/* and the upper port returns the absolute value of the magnitude */
	int val = analog_input_data[which / 2] << adc_shift;

	/* push everything out a little bit extra; most games seem to have a dead */
	/* zone in the middle that feels unnatural with the mouse */
	if (val < 0) val -= 8;
	else if (val > 0) val += 8;

	/* clip to 0xff maximum magnitude */
	if (val < -0xff) val = -0xff;
	else if (val > 0xff) val = 0xff;

	/* return the sign */
	if (!(which & 1))
		adc_value = (val < 0) ? 0xff : 0x00;

	/* return the magnitude */
	else
		adc_value = (val < 0) ? -val : val;
}


static int adc_data_r(int offset)
{
	/* just return the last value read */
	return adc_value;
}


static void adc_select_w(int offset, int data)
{
	/* set a timer to go off and read the value after 50us */
	/* it's important that we do this for Mini Golf */
	timer_set(TIME_IN_USEC(50), offset & 7, adc_finished);
}



/*************************************
 *
 *	8253-5 timer utilities
 *
 *	NOTE: this is far from complete!
 *
 *************************************/

INLINE void counter_start(int which)
{
	/* don't start a timer for channel 0; it is clocked manually */
	if (which != 0)
	{
		/* only start a timer if we're gated and there is none already */
		if (counter[which].gate && !counter[which].timer)
			counter[which].timer = timer_set(TIME_IN_HZ(2000000) * (double)counter[which].count, which, counter_callback);
	}
}


INLINE void counter_stop(int which)
{
	/* only stop the timer if it exists */
	if (counter[which].timer)
		timer_remove(counter[which].timer);
	counter[which].timer = NULL;
}


INLINE void counter_update_count(int which)
{
	/* only update if the timer is running */
	if (counter[which].timer)
	{
		/* determine how many 2MHz cycles are remaining */
		int count = (int)(timer_timeleft(counter[which].timer) / TIME_IN_HZ(2000000));
		counter[which].count = (count < 0) ? 0 : count;
	}
}



/*************************************
 *
 *	8253-5 timer internals
 *
 *	NOTE: this is far from complete!
 *
 *************************************/

static void counter_set_gate(int which, int gate)
{
	int oldgate = counter[which].gate;

	/* remember the gate state */
	counter[which].gate = gate;

	/* if the counter is being halted, update the count and remove the system timer */
	if (!gate && oldgate)
	{
		counter_update_count(which);
		counter_stop(which);
	}

	/* if the counter is being started, create the timer */
	else if (gate && !oldgate)
	{
		/* mode 1 waits for the gate to trigger the counter */
		if (counter[which].mode == 1)
		{
			counter_set_out(which, 0);

			/* add one to the count; technically, OUT goes low on the next clock pulse */
			/* and then starts counting down; it's important that we don't count the first one */
			counter[which].count = counter[which].initial + 1;
		}

		/* start the counter */
		counter_start(which);
	}
}


static void counter_set_out(int which, int out)
{
	/* OUT on counter 2 is hooked to the /INT line on the Z80 */
	if (which == 2)
		cpu_set_irq_line(1, 0, out ? ASSERT_LINE : CLEAR_LINE);

	/* OUT on counter 0 is hooked to the GATE line on counter 1 */
	else if (which == 0)
		counter_set_gate(1, !out);

	/* remember the out state */
	counter[which].out = out;
}


static void counter_callback(int param)
{
	/* reset the counter and the count */
	counter[param].timer = NULL;
	counter[param].count = 0;

	/* set the state of the OUT line */
	/* mode 0 and 1: when firing, transition OUT to high */
	if (counter[param].mode == 0 || counter[param].mode == 1)
		counter_set_out(param, 1);

	/* no other modes handled currently */
}



/*************************************
 *
 *	8253-5 timer handlers
 *
 *	NOTE: this is far from complete!
 *
 *************************************/

static int counter_8253_r(int offset)
{
	int which;

	switch (offset & 3)
	{
		case 0:
		case 1:
		case 2:
			/* warning: assumes LSB/MSB addressing and no latching! */
			which = offset & 3;

			/* update the count */
			counter_update_count(which);

			/* return the LSB */
			if (counter[which].readbyte == 0)
			{
				counter[which].readbyte = 1;
				return counter[which].count & 0xff;
			}

			/* write the MSB and reset the counter */
			else
			{
				counter[which].readbyte = 0;
				return (counter[which].count >> 8) & 0xff;
			}
			break;
	}
	return 0;
}


static void counter_8253_w(int offset, int data)
{
	int which;

	switch (offset & 3)
	{
		case 0:
		case 1:
		case 2:
			/* warning: assumes LSB/MSB addressing and no latching! */
			which = offset & 3;

			/* if the counter is in mode 0, a write here will reset the OUT state */
			if (counter[which].mode == 0)
				counter_set_out(which, 0);

			/* write the LSB */
			if (counter[which].writebyte == 0)
			{
				counter[which].count = (counter[which].count & 0xff00) | (data & 0x00ff);
				counter[which].initial = (counter[which].initial & 0xff00) | (data & 0x00ff);
				counter[which].writebyte = 1;
			}

			/* write the MSB and reset the counter */
			else
			{
				counter[which].count = (counter[which].count & 0x00ff) | ((data << 8) & 0xff00);
				counter[which].initial = (counter[which].initial & 0x00ff) | ((data << 8) & 0xff00);
				counter[which].writebyte = 0;

				/* treat 0 as $10000 */
				if (counter[which].count == 0) counter[which].count = counter[which].initial = 0x10000;

				/* remove any old timer and set a new one */
				counter_stop(which);

				/* note that in mode 1, we have to wait for a rising edge of a gate */
				if (counter[which].mode == 0)
					counter_start(which);

				/* if the counter is in mode 1, a write here will set the OUT state */
				if (counter[which].mode == 1)
					counter_set_out(which, 1);
			}
			break;

		case 3:
			/* determine which counter */
			which = data >> 6;
			if (which == 3) break;

			/* if the counter was in mode 0, a write here will reset the OUT state */
			if (((counter[which].mode >> 1) & 7) == 0)
				counter_set_out(which, 0);

			/* set the mode */
			counter[which].mode = (data >> 1) & 7;

			/* if the counter is in mode 0, a write here will reset the OUT state */
			if (counter[which].mode == 0)
				counter_set_out(which, 0);
			break;
	}
}



/*************************************
 *
 *	Sound CPU counter 0 emulation
 *
 *************************************/

static void set_counter_0_ff(int newstate)
{
	/* the flip/flop output is inverted, so if we went high to low, that's a clock */
	if (counter_0_ff && !newstate)
	{
		/* only count if gated and non-zero */
		if (counter[0].count > 0 && counter[0].gate)
		{
			counter[0].count--;
			if (counter[0].count == 0)
				counter_callback(0);
		}
	}

	/* remember the new state */
	counter_0_ff = newstate;
}


static void clock_counter_0_ff(int param)
{
	/* clock the D value through the flip-flop */
	set_counter_0_ff((counter_control >> 3) & 1);
}


static void update_counter_0_timer(void)
{
	double maxfreq = 0.0;
	int i;

	/* if there's already a timer, remove it */
	if (counter_0_timer)
		timer_remove(counter_0_timer);
	counter_0_timer = NULL;

	/* find the counter with the maximum frequency */
	/* this is used to calibrate the timers at startup */
	for (i = 0; i < 6; i++)
		if (cem3394_get_parameter(i, CEM3394_FINAL_GAIN) < 10.0)
		{
			double tempfreq;

			/* if the filter resonance is high, then they're calibrating the filter frequency */
			if (cem3394_get_parameter(i, CEM3394_FILTER_RESONANCE) > 0.9)
				tempfreq = cem3394_get_parameter(i, CEM3394_FILTER_FREQENCY);

			/* otherwise, they're calibrating the VCO frequency */
			else
				tempfreq = cem3394_get_parameter(i, CEM3394_VCO_FREQUENCY);

			if (tempfreq > maxfreq) maxfreq = tempfreq;
		}

	/* reprime the timer */
	if (maxfreq > 0.0)
		counter_0_timer = timer_pulse(TIME_IN_HZ(maxfreq), 0, clock_counter_0_ff);
}



/*************************************
 *
 *	Sound CPU counter handlers
 *
 *************************************/

static int counter_state_r(int offset)
{
	/* bit D0 is the inverse of the flip-flop state */
	int result = !counter_0_ff;

	/* bit D1 is the OUT value from counter 0 */
	if (counter[0].out) result |= 0x02;

	return result;
}


static void counter_control_w(int offset, int data)
{
	UINT8 diff_counter_control = counter_control ^ data;

	/* set the new global value */
	counter_control = data;

	/* bit D0 enables/disables audio */
	if (diff_counter_control & 0x01)
	{
		int ch;
		for (ch = 0; ch < MIXER_MAX_CHANNELS; ch++)
		{
			const char *name = mixer_get_name(ch);
			if (name && strstr(name, "3394"))
				mixer_set_volume(ch, (data & 0x01) ? 100 : 0);
		}
	}

	/* bit D1 is hooked to counter 0's gate */
	/* if we gate on, start a pulsing timer to clock it */
	if (!counter[0].gate && (data & 0x02) && !counter_0_timer)
	{
		update_counter_0_timer();
	}

	/* if we gate off, remove the timer */
	else if (counter[0].gate && !(data & 0x02) && counter_0_timer)
	{
		timer_remove(counter_0_timer);
		counter_0_timer = NULL;
	}

	/* set the actual gate afterwards, since we need to know the old value above */
	counter_set_gate(0, (data >> 1) & 1);

	/* bits D2 and D4 control the clear/reset flags on the flip-flop that feeds counter 0 */
	if (!(data & 0x04)) set_counter_0_ff(1);
	if (!(data & 0x10)) set_counter_0_ff(0);

	/* bit 5 clears the NMI interrupt; recompute the I/O state now */
	m6850_update_io();
}



/*************************************
 *
 *	Game-specific handlers
 *
 *************************************/

static int nstocker_port2_r(int offset)
{
	return (input_port_2_r(offset) & 0xf0) | nstocker_bits;
}



/*************************************
 *
 *	CEM3394 Interfaces
 *
 *************************************/

static void chip_select_w(int offset, int data)
{
	static const UINT8 register_map[8] =
	{
		CEM3394_VCO_FREQUENCY,
		CEM3394_FINAL_GAIN,
		CEM3394_FILTER_RESONANCE,
		CEM3394_FILTER_FREQENCY,
		CEM3394_MIXER_BALANCE,
		CEM3394_MODULATION_AMOUNT,
		CEM3394_PULSE_WIDTH,
		CEM3394_WAVE_SELECT
	};

	static const char *names[] =
	{
		"VCO_FREQUENCY",
		"FINAL_GAIN",
		"FILTER_RESONANCE",
		"FILTER_FREQENCY",
		"MIXER_BALANCE",
		"MODULATION_AMOUNT",
		"PULSE_WIDTH",
		"WAVE_SELECT"
	};

	double voltage = (double)dac_value * (8.0 / 4096.0) - 4.0;
	int diffchip = data ^ chip_select, i;
	int reg = register_map[dac_register];

	/* remember the new select value */
	chip_select = data;

	/* check all six chip enables */
	for (i = 0; i < 6; i++)
		if ((diffchip & (1 << i)) && (data & (1 << i)))
		{
			double temp = 0;

			/* remember the previous value */
			if (errorlog) temp = cem3394_get_parameter(i, reg);

			/* set the voltage */
			cem3394_set_voltage(i, reg, voltage);

			/* only log changes */
			if (errorlog && temp != cem3394_get_parameter(i, reg))
				fprintf(errorlog, "s%04X:   CEM#%d:%s=%f\n", cpu_getpreviouspc(), i, names[dac_register], voltage);
		}

	/* if a timer for counter 0 is running, recompute */
	if (counter_0_timer)
		update_counter_0_timer();
}



static void dac_data_w(int offset, int data)
{
	/* LSB or MSB? */
	if (offset & 1)
		dac_value = (dac_value & 0xfc0) | ((data >> 2) & 0x03f);
	else
		dac_value = (dac_value & 0x03f) | ((data << 6) & 0xfc0);

	/* if there are open channels, force the values in */
	if ((chip_select & 0x3f) != 0x3f)
	{
		UINT8 temp = chip_select;
		chip_select_w(0, 0x3f);
		chip_select_w(0, temp);
	}
}


static void register_addr_w(int offset, int data)
{
	dac_register = data & 7;
}



/*************************************
 *
 *	Main CPU memory handlers
 *
 *************************************/

/* CPU 1 read addresses */
static struct MemoryReadAddress readmem_cpu1[] =
{
	{ 0x0000, 0x8fff, MRA_RAM },
	{ 0x9400, 0x9400, adc_data_r },
	{ 0x9900, 0x9900, input_port_0_r },
	{ 0x9901, 0x9901, input_port_1_r },
	{ 0x9902, 0x9902, input_port_2_r },
	{ 0x9903, 0x9903, input_port_3_r },
#ifdef __BEOS__
	{ 0x9a00, 0x9a03, beos_random_r },
#else
	{ 0x9a00, 0x9a03, random_r },
#endif
	{ 0x9a04, 0x9a05, m6850_r },
	{ 0x9b00, 0x9bff, MRA_RAM },		/* system NOVRAM */
	{ 0x9c00, 0x9cff, MRA_RAM },		/* cart NOVRAM */
	{ 0xa000, 0xbfff, MRA_BANK1 },
	{ 0xc000, 0xffff, MRA_BANK2 },
	{ -1 }  /* end of table */
};


/* CPU 1 write addresses */
static struct MemoryWriteAddress writemem_cpu1[] =
{
	{ 0x0000, 0x07ff, MWA_RAM, &spriteram },
	{ 0x0800, 0x7fff, balsente_videoram_w, &videoram, &videoram_size },
	{ 0x8000, 0x8fff, balsente_paletteram_w, &paletteram },
	{ 0x9000, 0x9007, adc_select_w },
	{ 0x9800, 0x987f, misc_output_w },
	{ 0x9880, 0x989f, random_reset_w },
	{ 0x98a0, 0x98bf, rombank_select_w },
	{ 0x98c0, 0x98df, balsente_palette_select_w },
	{ 0x98e0, 0x98ff, watchdog_reset_w },
	{ 0x9903, 0x9903, MWA_NOP },
	{ 0x9a04, 0x9a05, m6850_w },
	{ 0x9b00, 0x9bff, MWA_RAM },		/* system NOVRAM */
	{ 0x9c00, 0x9cff, MWA_RAM },		/* cart NOVRAM */
	{ 0x9f00, 0x9f00, rombank2_select_w },
	{ 0xa000, 0xffff, MWA_ROM },
	{ -1 }  /* end of table */
};



/*************************************
 *
 *	Sound CPU memory handlers
 *
 *************************************/

static struct MemoryReadAddress readmem_cpu2[] =
{
	{ 0x0000, 0x1fff, MRA_ROM },
	{ 0x2000, 0x5fff, MRA_RAM },
	{ 0xe000, 0xffff, m6850_sound_r },
	{ -1 }  /* end of table */
};


static struct MemoryWriteAddress writemem_cpu2[] =
{
	{ 0x0000, 0x1fff, MWA_ROM },
	{ 0x2000, 0x5fff, MWA_RAM },
	{ 0x6000, 0x7fff, m6850_sound_w },
	{ -1 }  /* end of table */
};


static struct IOReadPort readport_cpu2[] =
{
	{ 0x00, 0x03, counter_8253_r },
	{ 0x08, 0x0f, counter_state_r },
	{ -1 }  /* end of table */
};


static struct IOWritePort writeport_cpu2[] =
{
	{ 0x00, 0x03, counter_8253_w },
	{ 0x08, 0x09, counter_control_w },
	{ 0x0a, 0x0b, dac_data_w },
	{ 0x0c, 0x0d, register_addr_w },
	{ 0x0e, 0x0f, chip_select_w },
	{ -1 }  /* end of table */
};



/*************************************
 *
 *	Port definitions
 *
 *************************************/

#define UNUSED_ANALOG \
	PORT_START\
	PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
#define UNUSED_ANALOG_X2 UNUSED_ANALOG UNUSED_ANALOG
#define UNUSED_ANALOG_X3 UNUSED_ANALOG_X2 UNUSED_ANALOG
#define UNUSED_ANALOG_X4 UNUSED_ANALOG_X2 UNUSED_ANALOG_X2

#define PLAYER1_ANALOG_JOYSTICK \
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_AD_STICK_Y | IPF_PLAYER1, 100, 20, 0x7f, 0x80, 0x7f )\
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_AD_STICK_X | IPF_REVERSE | IPF_PLAYER1, 100, 20, 0x7f, 0x80, 0x7f )

#define PLAYER2_ANALOG_JOYSTICK \
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_AD_STICK_Y | IPF_PLAYER2, 100, 20, 0x7f, 0x80, 0x7f )\
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_AD_STICK_X | IPF_REVERSE | IPF_PLAYER2, 100, 20, 0x7f, 0x80, 0x7f )

#define PLAYER1_TRACKBALL \
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_TRACKBALL_Y | IPF_PLAYER1 | IPF_CENTER, 100, 20, 0x7f, 0, 0 )\
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_TRACKBALL_X | IPF_REVERSE | IPF_PLAYER1 | IPF_CENTER, 100, 20, 0x7f, 0, 0 )

#define PLAYER2_TRACKBALL \
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_TRACKBALL_Y | IPF_PLAYER2 | IPF_CENTER, 100, 20, 0x7f, 0, 0 )\
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_TRACKBALL_X | IPF_REVERSE | IPF_PLAYER2 | IPF_CENTER, 100, 20, 0x7f, 0, 0 )

#define PLAYER1_DIAL \
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_DIAL | IPF_PLAYER1 | IPF_REVERSE | IPF_CENTER, 100, 20, 0x7f, 0, 0 )

#define PLAYER2_DIAL \
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_DIAL | IPF_PLAYER2 | IPF_REVERSE | IPF_CENTER, 100, 20, 0x7f, 0, 0 )

#define PLAYER1_WHEEL \
	PORT_START\
    PORT_ANALOG( 0xff, 0, IPT_DIAL | IPF_PLAYER1 | IPF_CENTER, 100, 20, 0x7f, 0, 0 )

#define PLAYER1_CROSSHAIRS \
	PORT_START				/* fake analog X */\
	PORT_ANALOG ( 0xff, 0x80, IPT_AD_STICK_X, 50, 10, 0, 0, 255 )\
	PORT_START				/* fake analog Y */\
	PORT_ANALOG ( 0xff, 0x80, IPT_AD_STICK_Y, 70, 10, 0, 0, 255 )


INPUT_PORTS_START( sentetst_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_BIT( 0x7c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x80, "High Scores" )
	PORT_DIPSETTING(    0x80, "Keep Top 5" )
	PORT_DIPSETTING(    0x00, "Keep All" )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x03, 0x00, DEF_STR( Bonus_Life ))
	PORT_DIPSETTING(    0x00, "Every 10,000" )
	PORT_DIPSETTING(    0x01, "Every 15,000" )
	PORT_DIPSETTING(    0x02, "Every 20,000" )
	PORT_DIPSETTING(    0x03, "Every 25,000" )
	PORT_DIPNAME( 0x0c, 0x08, DEF_STR( Lives ))
	PORT_DIPSETTING(    0x00, "2" )
	PORT_DIPSETTING(    0x04, "3" )
	PORT_DIPSETTING(    0x08, "4" )
	PORT_DIPSETTING(    0x0c, "5" )
	PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Difficulty ))
	PORT_DIPSETTING(    0x40, "Easy" )
	PORT_DIPSETTING(    0x00, "Hard" )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x38, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X2
	PLAYER1_TRACKBALL
INPUT_PORTS_END


INPUT_PORTS_START( cshift_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_BIT( 0x7c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x80, "High Scores" )
	PORT_DIPSETTING(    0x80, "Keep Top 5" )
	PORT_DIPSETTING(    0x00, "Keep All" )

	PORT_START	/* IN1 */
	PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x04, 0x00, DEF_STR( Lives ))
	PORT_DIPSETTING(    0x00, "2" )
	PORT_DIPSETTING(    0x04, "3" )
	PORT_BIT( 0x70, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
	PORT_BIT( 0x3c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x3c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X4
INPUT_PORTS_END


INPUT_PORTS_START( gghost_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_DIPNAME( 0x04, 0x04, "Players Per Credit" )
	PORT_DIPSETTING(    0x00, "1" )
	PORT_DIPSETTING(    0x04, "1 or 2" )
	PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x07, 0x05, "Game Duration" )
	PORT_DIPSETTING(    0x00, "9 points" )
	PORT_DIPSETTING(    0x02, "11 points" )
	PORT_DIPSETTING(    0x04, "15 points" )
	PORT_DIPSETTING(    0x06, "21 points" )
	PORT_DIPSETTING(    0x01, "timed, 1:15" )
	PORT_DIPSETTING(    0x03, "timed, 1:30" )
	PORT_DIPSETTING(    0x05, "timed, 2:00" )
	PORT_DIPSETTING(    0x07, "timed, 2:30" )
	PORT_BIT( 0x78, IP_ACTIVE_HIGH, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER1 )
	PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	PLAYER2_TRACKBALL
	PLAYER1_TRACKBALL
INPUT_PORTS_END


INPUT_PORTS_START( hattrick_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_DIPNAME( 0x04, 0x04, "Players Per Credit" )
	PORT_DIPSETTING(    0x00, "1" )
	PORT_DIPSETTING(    0x04, "1 or 2" )
	PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x07, 0x02, "Game Time" )
	PORT_DIPSETTING(    0x00, "1:15" )
	PORT_DIPSETTING(    0x01, "1:30" )
	PORT_DIPSETTING(    0x02, "1:45" )
	PORT_DIPSETTING(    0x03, "2:00" )
	PORT_DIPSETTING(    0x04, "2:15" )
	PORT_DIPSETTING(    0x05, "2:30" )
	PORT_DIPSETTING(    0x06, "2:45" )
	PORT_DIPSETTING(    0x07, "3:00" )
	PORT_BIT( 0x78, IP_ACTIVE_HIGH, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER2 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER2 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER2 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER2 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X4
INPUT_PORTS_END


INPUT_PORTS_START( otwalls_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_DIPNAME( 0x04, 0x04, "Players Per Credit" )
	PORT_DIPSETTING(    0x00, "1" )
	PORT_DIPSETTING(    0x04, "1 or 2" )
	PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* IN1 */
	PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT | IPF_PLAYER2 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT | IPF_PLAYER2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x3c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X2
	PLAYER1_DIAL
	PLAYER2_DIAL
INPUT_PORTS_END


INPUT_PORTS_START( snakepit_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_BIT( 0x7c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x80, "High Scores" )
	PORT_DIPSETTING(    0x80, "Keep Top 5" )
	PORT_DIPSETTING(    0x00, "Keep All" )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x03, 0x00, DEF_STR( Bonus_Life ))
	PORT_DIPSETTING(    0x00, "Every 10,000" )
	PORT_DIPSETTING(    0x01, "Every 15,000" )
	PORT_DIPSETTING(    0x02, "Every 20,000" )
	PORT_DIPSETTING(    0x03, "Every 25,000" )
	PORT_DIPNAME( 0x0c, 0x08, DEF_STR( Lives ))
	PORT_DIPSETTING(    0x00, "2" )
	PORT_DIPSETTING(    0x04, "3" )
	PORT_DIPSETTING(    0x08, "4" )
	PORT_DIPSETTING(    0x0c, "5" )
	PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Difficulty ))
	PORT_DIPSETTING(    0x40, "Easy" )
	PORT_DIPSETTING(    0x00, "Hard" )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x38, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X2
	PLAYER1_TRACKBALL
INPUT_PORTS_END


INPUT_PORTS_START( snakjack_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_BIT( 0x7c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x80, "High Scores" )
	PORT_DIPSETTING(    0x80, "Keep Top 5" )
	PORT_DIPSETTING(    0x00, "Keep All" )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x03, 0x01, DEF_STR( Bonus_Life ))
	PORT_DIPSETTING(    0x00, "Every 15,000" )
	PORT_DIPSETTING(    0x01, "Every 20,000" )
	PORT_DIPSETTING(    0x02, "Every 25,000" )
	PORT_DIPSETTING(    0x03, "Every 30,000" )
	PORT_DIPNAME( 0x0c, 0x04, DEF_STR( Lives ))
	PORT_DIPSETTING(    0x00, "2" )
	PORT_DIPSETTING(    0x04, "3" )
	PORT_DIPSETTING(    0x08, "4" )
	PORT_DIPSETTING(    0x0c, "5" )
	PORT_BIT( 0x70, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x38, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X2
	PLAYER1_TRACKBALL
INPUT_PORTS_END


INPUT_PORTS_START( stocker_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x01, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x03, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x02, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_DIPNAME( 0x1c, 0x00, "Bonus Coins" )
	PORT_DIPSETTING(    0x00, "None" )
	PORT_DIPSETTING(    0x04, "2 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x08, "3 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x0c, "4 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x10, "4 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x14, "5 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x18, "5 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x1c, "5 Coins = 3 Bonus" )
	PORT_DIPNAME( 0x20, 0x00, "Left Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x20, "x2" )
	PORT_DIPNAME( 0xc0, 0x00, "Right Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x40, "x4" )
	PORT_DIPSETTING(    0x80, "x5" )
	PORT_DIPSETTING(    0xc0, "x6" )

	PORT_START	/* IN1 */
	PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x40, 0x40, "End of Game" )
	PORT_DIPSETTING(    0x40, "Normal" )
	PORT_DIPSETTING(    0x00, "3 Tickets" )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x3c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X3
	PLAYER1_WHEEL
INPUT_PORTS_END


INPUT_PORTS_START( triviag1_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x10, 0x10, "IN0 $10" )
	PORT_DIPSETTING(    0x00, "$00" )
	PORT_DIPSETTING(    0x10, "$10" )
	PORT_DIPNAME( 0x20, 0x00, "Sound" )
	PORT_DIPSETTING(    0x20, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))
	PORT_DIPNAME( 0x40, 0x00, "Sound Calibration" )
	PORT_DIPSETTING(    0x40, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))
	PORT_DIPNAME( 0x80, 0x80, "High Scores" )
	PORT_DIPSETTING(    0x80, "Keep Top 5" )
	PORT_DIPSETTING(    0x00, "Keep All" )

	PORT_START	/* IN1 */
	PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x0c, 0x04, "Guesses" )
	PORT_DIPSETTING(    0x00, "3" )
	PORT_DIPSETTING(    0x04, "4" )
	PORT_DIPSETTING(    0x08, "5" )
	PORT_DIPSETTING(    0x0c, "6" )
	PORT_BIT( 0x70, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START3 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START4 )
	PORT_BITX(0x10, IP_ACTIVE_LOW, IPT_BUTTON2, "Red Button", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
	PORT_BITX(0x20, IP_ACTIVE_LOW, IPT_BUTTON1, "Green Button", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X4
INPUT_PORTS_END


INPUT_PORTS_START( triviasp_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x10, 0x10, "IN0 $10" )
	PORT_DIPSETTING(    0x00, "$00" )
	PORT_DIPSETTING(    0x10, "$10" )
	PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x80, "High Scores" )
	PORT_DIPSETTING(    0x80, "Keep Top 5" )
	PORT_DIPSETTING(    0x00, "Keep All" )

	PORT_START	/* IN1 */
	PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x0c, 0x04, "Guesses" )
	PORT_DIPSETTING(    0x00, "3" )
	PORT_DIPSETTING(    0x04, "4" )
	PORT_DIPSETTING(    0x08, "5" )
	PORT_DIPSETTING(    0x0c, "6" )
	PORT_BIT( 0x70, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START3 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START4 )
	PORT_BITX(0x10, IP_ACTIVE_LOW, IPT_BUTTON2, "Red Button", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
	PORT_BITX(0x20, IP_ACTIVE_LOW, IPT_BUTTON1, "Green Button", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X4
INPUT_PORTS_END


INPUT_PORTS_START( gimeabrk_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x01, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x03, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x02, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_DIPNAME( 0x1c, 0x00, "Bonus Coins" )
	PORT_DIPSETTING(    0x00, "None" )
	PORT_DIPSETTING(    0x04, "2 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x08, "3 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x0c, "4 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x10, "4 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x14, "5 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x18, "5 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x1c, "5 Coins = 3 Bonus" )
	PORT_DIPNAME( 0x20, 0x00, "Left Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x20, "x2" )
	PORT_DIPNAME( 0xc0, 0x00, "Right Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x40, "x4" )
	PORT_DIPSETTING(    0x80, "x5" )
	PORT_DIPSETTING(    0xc0, "x6" )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x03, 0x01, "Bonus Shot" )
	PORT_DIPSETTING(    0x00, "Every 6 Balls" )
	PORT_DIPSETTING(    0x01, "Every 8 Balls" )
	PORT_DIPSETTING(    0x02, "Every 10 Balls" )
	PORT_DIPSETTING(    0x03, "Every 12 Balls" )
	PORT_DIPNAME( 0x0c, 0x08, "Initial Shots" )
	PORT_DIPSETTING(    0x00, "8" )
	PORT_DIPSETTING(    0x04, "10" )
	PORT_DIPSETTING(    0x08, "12" )
	PORT_DIPSETTING(    0x0c, "14" )
	PORT_DIPNAME( 0x10, 0x00, "Players Per Credit" )
	PORT_DIPSETTING(    0x00, "1" )
	PORT_DIPSETTING(    0x10, "1 or 2" )
	PORT_DIPNAME( 0x20, 0x20, DEF_STR( Cabinet ))
	PORT_DIPSETTING(    0x00, DEF_STR( Cocktail ))
	PORT_DIPSETTING(    0x20, DEF_STR( Upright ))
	PORT_DIPNAME( 0x40, 0x40, "High Scores" )
	PORT_DIPSETTING(    0x40, "Keep Top 5" )
	PORT_DIPSETTING(    0x00, "Keep All" )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	PLAYER1_TRACKBALL
	UNUSED_ANALOG_X2
INPUT_PORTS_END


INPUT_PORTS_START( minigolf_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x01, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x03, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x02, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_DIPNAME( 0x1c, 0x00, "Bonus Coins" )
	PORT_DIPSETTING(    0x00, "None" )
	PORT_DIPSETTING(    0x04, "2 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x08, "3 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x0c, "4 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x10, "4 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x14, "5 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x18, "5 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x1c, "5 Coins = 3 Bonus" )
	PORT_DIPNAME( 0x20, 0x00, "Left Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x20, "x2" )
	PORT_DIPNAME( 0xc0, 0x00, "Right Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x40, "x4" )
	PORT_DIPSETTING(    0x80, "x5" )
	PORT_DIPSETTING(    0xc0, "x6" )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x01, 0x01, "Add-A-Coin" )
	PORT_DIPSETTING(    0x00, DEF_STR( On ))
	PORT_DIPSETTING(    0x01, DEF_STR( Off ))
	PORT_BIT( 0x7e, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X2
	PLAYER1_TRACKBALL
INPUT_PORTS_END


INPUT_PORTS_START( minigol2_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x00, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x03, DEF_STR( 3C_1C ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x00, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPNAME( 0x1c, 0x00, "Bonus Coins" )
	PORT_DIPSETTING(    0x00, "None" )
	PORT_DIPSETTING(    0x04, "2 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x08, "3 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x0c, "4 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x10, "4 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x14, "5 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x18, "5 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x1c, "5 Coins = 3 Bonus" )
	PORT_DIPNAME( 0x20, 0x00, "Left Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x20, "x2" )
	PORT_DIPNAME( 0xc0, 0x00, "Right Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x40, "x4" )
	PORT_DIPSETTING(    0x80, "x5" )
	PORT_DIPSETTING(    0xc0, "x6" )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x01, 0x01, "Add-A-Coin" )
	PORT_DIPSETTING(    0x00, DEF_STR( On ))
	PORT_DIPSETTING(    0x01, DEF_STR( Off ))
	PORT_BIT( 0x7e, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X2
	PLAYER1_TRACKBALL
INPUT_PORTS_END


INPUT_PORTS_START( toggle_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ))
	PORT_BIT( 0x7c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x80, "High Scores" )
	PORT_DIPSETTING(    0x80, "Keep Top 5" )
	PORT_DIPSETTING(    0x00, "Keep All" )

	PORT_START	/* IN1 */
	PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x04, 0x04, DEF_STR( Lives ))
	PORT_DIPSETTING(    0x00, "2" )
	PORT_DIPSETTING(    0x04, "3" )
	PORT_BIT( 0x78, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER2 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER2 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER2 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER2 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X4
INPUT_PORTS_END


INPUT_PORTS_START( nstocker_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x00, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x03, DEF_STR( 3C_1C ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x00, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPNAME( 0x1c, 0x00, "Bonus Coins" )
	PORT_DIPSETTING(    0x00, "None" )
	PORT_DIPSETTING(    0x04, "2 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x08, "3 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x0c, "4 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x10, "4 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x14, "5 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x18, "5 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x1c, "5 Coins = 3 Bonus" )
	PORT_DIPNAME( 0x20, 0x00, "Left Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x20, "x2" )
	PORT_DIPNAME( 0xc0, 0x00, "Right Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x40, "x4" )
	PORT_DIPSETTING(    0x80, "x5" )
	PORT_DIPSETTING(    0xc0, "x6" )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x01, 0x00, DEF_STR( Difficulty ))
	PORT_DIPSETTING(    0x01, "Easy" )
	PORT_DIPSETTING(    0x00, "Hard" )
	PORT_BIT( 0x7e, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x3c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X3
	/* cheese alert -- we have to map this to player 2 so that it doesn't interfere with */
	/* the crosshair controls */
	PORT_START
    PORT_ANALOGX( 0xff, 0, IPT_DIAL | IPF_PLAYER2 | IPF_CENTER, 100, 20, 0x7f, 0, 0,
    				KEYCODE_S, KEYCODE_F, JOYCODE_1_LEFT, JOYCODE_1_RIGHT )

	/* extra ports for shooters */
	PLAYER1_CROSSHAIRS
INPUT_PORTS_END


INPUT_PORTS_START( sfootbal_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x00, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x03, DEF_STR( 3C_1C ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x00, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPNAME( 0x1c, 0x00, "Bonus Coins" )
	PORT_DIPSETTING(    0x00, "None" )
	PORT_DIPSETTING(    0x04, "2 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x08, "3 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x0c, "4 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x10, "4 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x14, "5 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x18, "5 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x1c, "5 Coins = 3 Bonus" )
	PORT_DIPNAME( 0x20, 0x00, "Left Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x20, "x2" )
	PORT_DIPNAME( 0xc0, 0x00, "Right Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x40, "x4" )
	PORT_DIPSETTING(    0x80, "x5" )
	PORT_DIPSETTING(    0xc0, "x6" )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x07, 0x03, "Game Duration" )
	PORT_DIPSETTING(    0x00, "1:30" )
	PORT_DIPSETTING(    0x01, "1:40" )
	PORT_DIPSETTING(    0x02, "1:50" )
	PORT_DIPSETTING(    0x03, "2:00" )
	PORT_DIPSETTING(    0x04, "2:20" )
	PORT_DIPSETTING(    0x05, "2:40" )
	PORT_DIPSETTING(    0x06, "3:00" )
	PORT_DIPSETTING(    0x07, "3:30" )
	PORT_DIPNAME( 0x08, 0x00, "Players Per Credit" )
	PORT_DIPSETTING(    0x00, "1" )
	PORT_DIPSETTING(    0x08, "1 or 2" )
	PORT_BIT( 0x70, IP_ACTIVE_HIGH, IPT_UNUSED )
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT( 0x3c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x3c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	PLAYER2_ANALOG_JOYSTICK
	PLAYER1_ANALOG_JOYSTICK
INPUT_PORTS_END


INPUT_PORTS_START( rescraid_input_ports )
	PORT_START	/* IN0 */
	PORT_DIPNAME( 0x03, 0x00, DEF_STR( Coinage ))
	PORT_DIPSETTING(    0x03, DEF_STR( 3C_1C ))
	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ))
	PORT_DIPSETTING(    0x00, DEF_STR( 1C_1C ))
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ))
	PORT_DIPNAME( 0x1c, 0x00, "Bonus Coins" )
	PORT_DIPSETTING(    0x00, "None" )
	PORT_DIPSETTING(    0x04, "2 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x08, "3 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x0c, "4 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x10, "4 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x14, "5 Coins = 1 Bonus" )
	PORT_DIPSETTING(    0x18, "5 Coins = 2 Bonus" )
	PORT_DIPSETTING(    0x1c, "5 Coins = 3 Bonus" )
	PORT_DIPNAME( 0x20, 0x00, "Left Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x20, "x2" )
	PORT_DIPNAME( 0xc0, 0x00, "Right Coin Mech" )
	PORT_DIPSETTING(    0x00, "x1" )
	PORT_DIPSETTING(    0x40, "x4" )
	PORT_DIPSETTING(    0x80, "x5" )
	PORT_DIPSETTING(    0xc0, "x6" )

	PORT_START	/* IN1 */
	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Lives ))
	PORT_DIPSETTING(    0x00, "4" )
	PORT_DIPSETTING(    0x01, "5" )
	PORT_DIPNAME( 0x0c, 0x04, "Minimum Game Time" )
	PORT_DIPSETTING(    0x08, "45" )
	PORT_DIPSETTING(    0x04, "60" )
	PORT_DIPSETTING(    0x00, "90" )
	PORT_DIPSETTING(    0x0c, "120" )
	PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_DIPNAME( 0x40, 0x40, "Keep High Scores" )
	PORT_DIPSETTING(    0x40, DEF_STR( No ))
	PORT_DIPSETTING(    0x00, DEF_STR( Yes ))
	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Demo_Sounds ))
	PORT_DIPSETTING(    0x80, DEF_STR( Off ))
	PORT_DIPSETTING(    0x00, DEF_STR( On ))

	PORT_START	/* IN2 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_SERVICE( 0x80, IP_ACTIVE_LOW )

	PORT_START	/* IN3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK )

	/* analog ports */
	UNUSED_ANALOG_X4
INPUT_PORTS_END



/*************************************
 *
 *	Graphics definitions
 *
 *************************************/

static struct GfxLayout spritelayout =
{
	8,16,	/* 8*16 chars */
	1024,	/* 1024 chars */
	4,		/* 4 bits per pixel */
	{ 0, 1, 2, 3 },
	{ 0, 4, 8, 12, 16, 20, 24, 28 },
	{ 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, 8*32, 9*32, 10*32, 11*32, 12*32, 13*32, 14*32, 15*32 },
	8*64	/* every char takes 64 consecutive bytes */
};


static struct GfxDecodeInfo gfxdecodeinfo[] =
{
	{ 2, 0x000000, &spritelayout, 0, 16 },
	{ -1 } /* end of array */
};



/*************************************
 *
 *	Sound definitions
 *
 *************************************/

static struct cem3394_interface cem_interface =
{
	6,
	{ 90, 90, 90, 90, 90, 90 },
	{ 431.894, 431.894, 431.894, 431.894, 431.894, 431.894 },
	{ 1300.0, 1300.0, 1300.0, 1300.0, 1300.0, 1300.0 },
	{ noise_gen, noise_gen, noise_gen, noise_gen, noise_gen, noise_gen }
};



/*************************************
 *
 *	Machine driver
 *
 *************************************/

static struct MachineDriver machine_driver =
{
	/* basic machine hardware */
	{
		{
			CPU_M6809,
			5000000/4,                     /* 5Mhz/4 */
			0,
			readmem_cpu1,writemem_cpu1,0,0,
			update_analog_inputs,1
		},
		{
			CPU_Z80 | CPU_AUDIO_CPU,
			4000000,                       /* 4Mhz */
			1,
			readmem_cpu2,writemem_cpu2,readport_cpu2,writeport_cpu2,
			ignore_interrupt,1
		}
	},
	60, DEFAULT_REAL_60HZ_VBLANK_DURATION,	/* frames per second, vblank duration */
	10,
	init_machine,

	/* video hardware */
	256, 240, { 0, 255, 0, 239 },
	gfxdecodeinfo,
	1025,1025,
	0,

	VIDEO_TYPE_RASTER | VIDEO_MODIFIES_PALETTE | VIDEO_UPDATE_BEFORE_VBLANK,
	0,
	balsente_vh_start,
	balsente_vh_stop,
	balsente_vh_screenrefresh,

	/* sound hardware */
	0,0,0,0,
	{
		{
			SOUND_CEM3394,
			&cem_interface
		}
	}
};



/*************************************
 *
 *	High score save/load
 *
 *************************************/

static int hiload(void)
{
	void *f = osd_fopen(Machine->gamedrv->name,0, OSD_FILETYPE_HIGHSCORE, 0);
	if (f)
	{
		osd_fread(f, &Machine->memory_region[0][0x9b00], 0x200);
		osd_fclose(f);
	}
	else
		memset(&Machine->memory_region[0][0x9b00], 0, 0x200);

	return 1;
}


static void hisave(void)
{
	void *f = osd_fopen(Machine->gamedrv->name, 0, OSD_FILETYPE_HIGHSCORE, 1);
	if (f)
	{
		osd_fwrite(f, &Machine->memory_region[0][0x9b00], 0x200);
		osd_fclose(f);
	}
}



/*************************************
 *
 *	Driver initialization
 *
 *************************************/

#define EXPAND_ALL		0x00
#define EXPAND_NONE		0x3f

static void expand_roms(UINT8 cd_rom_mask)
{
	/* load AB bank data from 0x10000-0x20000 */
	/* load CD bank data from 0x20000-0x2e000 */
	/* load EF           from 0x2e000-0x30000 */
	/* ROM region must be 0x40000 total */

	UINT8 *temp = malloc(0x20000);
	if (temp)
	{
		UINT8 *rom = Machine->memory_region[0];
		UINT8 *ab_base = &temp[0x00000];
		UINT8 *cd_base = &temp[0x10000];
		UINT8 *cd_common = &temp[0x1c000];
		UINT8 *ef_common = &temp[0x1e000];

		memcpy(temp, &rom[0x10000], 0x20000);

		memcpy(&rom[0x0e000], ef_common, 0x2000);

		memcpy(&rom[0x3e000], ef_common, 0x2000);
		memcpy(&rom[0x3c000], cd_common, 0x2000);
		memcpy(&rom[0x3a000], &ab_base[0xe000], 0x2000);

		memcpy(&rom[0x38000], ef_common, 0x2000);
		memcpy(&rom[0x36000], cd_common, 0x2000);
		memcpy(&rom[0x34000], &ab_base[0xc000], 0x2000);

		memcpy(&rom[0x32000], ef_common, 0x2000);
		memcpy(&rom[0x30000], (cd_rom_mask & 0x20) ? &cd_base[0xa000] : cd_common, 0x2000);
		memcpy(&rom[0x2e000], &ab_base[0xa000], 0x2000);

		memcpy(&rom[0x2c000], ef_common, 0x2000);
		memcpy(&rom[0x2a000], (cd_rom_mask & 0x10) ? &cd_base[0x8000] : cd_common, 0x2000);
		memcpy(&rom[0x28000], &ab_base[0x8000], 0x2000);

		memcpy(&rom[0x26000], ef_common, 0x2000);
		memcpy(&rom[0x24000], (cd_rom_mask & 0x08) ? &cd_base[0x6000] : cd_common, 0x2000);
		memcpy(&rom[0x22000], &ab_base[0x6000], 0x2000);

		memcpy(&rom[0x20000], ef_common, 0x2000);
		memcpy(&rom[0x1e000], (cd_rom_mask & 0x04) ? &cd_base[0x4000] : cd_common, 0x2000);
		memcpy(&rom[0x1c000], &ab_base[0x4000], 0x2000);

		memcpy(&rom[0x1a000], ef_common, 0x2000);
		memcpy(&rom[0x18000], (cd_rom_mask & 0x02) ? &cd_base[0x2000] : cd_common, 0x2000);
		memcpy(&rom[0x16000], &ab_base[0x2000], 0x2000);

		memcpy(&rom[0x14000], ef_common, 0x2000);
		memcpy(&rom[0x12000], (cd_rom_mask & 0x01) ? &cd_base[0x0000] : cd_common, 0x2000);
		memcpy(&rom[0x10000], &ab_base[0x0000], 0x2000);

		free(temp);
	}
}

static void sentetst_init(void) { expand_roms(EXPAND_ALL);  balsente_shooter = 0; /* noanalog */ }
static void cshift_init(void)   { expand_roms(EXPAND_ALL);  balsente_shooter = 0; /* noanalog */ }
static void gghost_init(void)   { expand_roms(EXPAND_ALL);  balsente_shooter = 0; adc_shift = 1; }
static void hattrick_init(void) { expand_roms(EXPAND_ALL);  balsente_shooter = 0; /* noanalog */ }
static void otwalls_init(void)  { expand_roms(EXPAND_ALL);  balsente_shooter = 0; adc_shift = 0; }
static void snakepit_init(void)
{
	/* kludge for bad ROM read */
	Machine->memory_region[0][0x2c1f7] |= 0x80;
	Machine->memory_region[0][0x2c2e7] |= 0x80;
	Machine->memory_region[0][0x2c2f7] |= 0x80;
	Machine->memory_region[0][0x2c2ff] |= 0x80;
	Machine->memory_region[0][0x2c31f] |= 0x80;
	expand_roms(EXPAND_ALL);  balsente_shooter = 0; adc_shift = 3;
}
static void snakjack_init(void) { expand_roms(EXPAND_ALL);  balsente_shooter = 0; adc_shift = 1; }
static void stocker_init(void)  { expand_roms(EXPAND_ALL);  balsente_shooter = 0; adc_shift = 0; }
static void triviag1_init(void) { expand_roms(EXPAND_ALL);  balsente_shooter = 0; /* noanalog */ }
static void triviasp_init(void)
{
	memcpy(&Machine->memory_region[0][0x20000], &Machine->memory_region[0][0x24000], 0x4000);
	memcpy(&Machine->memory_region[0][0x28000], &Machine->memory_region[0][0x24000], 0x4000);
	expand_roms(EXPAND_NONE); balsente_shooter = 0; /* noanalog */
}
static void gimeabrk_init(void) { expand_roms(EXPAND_ALL);  balsente_shooter = 0; adc_shift = 1; }
static void minigolf_init(void) { expand_roms(0x0c);        balsente_shooter = 0; adc_shift = 1; }
static void minigol2_init(void) { expand_roms(EXPAND_NONE); balsente_shooter = 0; adc_shift = 1; }
static void toggle_init(void)   { expand_roms(EXPAND_ALL);  balsente_shooter = 0; /* noanalog */ }
static void nstocker_init(void)
{
	install_mem_read_handler(0, 0x9902, 0x9902, nstocker_port2_r);
	expand_roms(EXPAND_NONE); balsente_shooter = 1; adc_shift = 1;
}
static void sfootbal_init(void) { expand_roms(EXPAND_ALL);  balsente_shooter = 0; adc_shift = 0; }
static void rescraid_init(void) { expand_roms(EXPAND_NONE); balsente_shooter = 0; /* noanalog */ }



/*************************************
 *
 *	ROM definitions
 *
 *************************************/

ROM_START( sentetst_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "sdiagef.bin",  0x2e000, 0x2000, 0x2a39fc53 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",     0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "sdiaggr0.bin", 0x00000, 0x2000, 0x5e0ff62a )
ROM_END


ROM_START( cshift_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "cs-ab0.bin", 0x10000, 0x2000, 0xd2069e75 )
	ROM_LOAD( "cs-ab1.bin", 0x12000, 0x2000, 0x198f25a8 )
	ROM_LOAD( "cs-ab2.bin", 0x14000, 0x2000, 0x2e2b2b82 )
	ROM_LOAD( "cs-ab3.bin", 0x16000, 0x2000, 0xb97fc520 )
	ROM_LOAD( "cs-ab4.bin", 0x18000, 0x2000, 0xb4f0d673 )
	ROM_LOAD( "cs-ab5.bin", 0x1a000, 0x2000, 0xb1f8e589 )
	ROM_LOAD( "cs-cd.bin",  0x2c000, 0x2000, 0xf555a0b2 )
	ROM_LOAD( "cs-ef.bin",  0x2e000, 0x2000, 0x368b1ce3 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",   0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "cs-gr0.bin", 0x00000, 0x2000, 0x67f9d3b3 )
	ROM_LOAD( "cs-gr1.bin", 0x02000, 0x2000, 0x78973d50 )
	ROM_LOAD( "cs-gr2.bin", 0x04000, 0x2000, 0x1784f939 )
	ROM_LOAD( "cs-gr3.bin", 0x06000, 0x2000, 0xb43916a2 )
	ROM_LOAD( "cs-gr4.bin", 0x08000, 0x2000, 0xa94cd35b )
ROM_END


ROM_START( gghost_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "ggh-ab0.bin", 0x10000, 0x2000, 0xed0fdeac )
	ROM_LOAD( "ggh-ab1.bin", 0x12000, 0x2000, 0x5bfbae58 )
	ROM_LOAD( "ggh-ab2.bin", 0x14000, 0x2000, 0xf0baf921 )
	ROM_LOAD( "ggh-ab3.bin", 0x16000, 0x2000, 0xed0fdeac )
	ROM_LOAD( "ggh-ab4.bin", 0x18000, 0x2000, 0x5bfbae58 )
	ROM_LOAD( "ggh-ab5.bin", 0x1a000, 0x2000, 0xf0baf921 )
	ROM_LOAD( "ggh-cd.bin",  0x2c000, 0x2000, 0xd3d75f84 )
	ROM_LOAD( "ggh-ef.bin",  0x2e000, 0x2000, 0xa02b4243 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",    0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "ggh-gr0.bin", 0x00000, 0x2000, 0x03515526 )
	ROM_LOAD( "ggh-gr1.bin", 0x02000, 0x2000, 0xb4293435 )
	ROM_LOAD( "ggh-gr2.bin", 0x04000, 0x2000, 0xece0cb97 )
	ROM_LOAD( "ggh-gr3.bin", 0x06000, 0x2000, 0xdd7e25d0 )
	ROM_LOAD( "ggh-gr4.bin", 0x08000, 0x2000, 0xb4293435 )
	ROM_LOAD( "ggh-gr5.bin", 0x0a000, 0x2000, 0xd3da0093 )
ROM_END


ROM_START( hattrick_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "rom-ab0.u9a", 0x10000, 0x2000, 0xf25c1b99 )
	ROM_LOAD( "rom-ab1.u8a", 0x12000, 0x2000, 0xc1df3d1f )
	ROM_LOAD( "rom-ab2.u7a", 0x14000, 0x2000, 0xf6c41257 )
	ROM_LOAD( "rom-cd.u3a",  0x2c000, 0x2000, 0xfc44f36c )
	ROM_LOAD( "rom-ef.u2a",  0x2e000, 0x2000, 0xd8f910fb )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",    0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "rom-gr0.u9b", 0x00000, 0x2000, 0x9f41baba )
	ROM_LOAD( "rom-gr1.u8b", 0x02000, 0x2000, 0x951f08c9 )
ROM_END


ROM_START( otwalls_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "otw-ab0.bin", 0x10000, 0x2000, 0x474441c7 )
	ROM_LOAD( "otw-ab1.bin", 0x12000, 0x2000, 0x2e9e9411 )
	ROM_LOAD( "otw-ab2.bin", 0x14000, 0x2000, 0xba092128 )
	ROM_LOAD( "otw-ab3.bin", 0x16000, 0x2000, 0x74bc479d )
	ROM_LOAD( "otw-ab4.bin", 0x18000, 0x2000, 0xf5f67619 )
	ROM_LOAD( "otw-ab5.bin", 0x1a000, 0x2000, 0xf5f67619 )
	ROM_LOAD( "otw-cd.bin",  0x2c000, 0x2000, 0x8e2d15ab )
	ROM_LOAD( "otw-ef.bin",  0x2e000, 0x2000, 0x57eab299 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",    0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "otw-gr0.bin", 0x00000, 0x2000, 0x210bad3c )
	ROM_LOAD( "otw-gr1.bin", 0x02000, 0x2000, 0x13e6aaa5 )
	ROM_LOAD( "otw-gr2.bin", 0x04000, 0x2000, 0x5cfefee5 )
	ROM_LOAD( "otw-gr3.bin", 0x06000, 0x2000, 0x6b17e4a9 )
	ROM_LOAD( "otw-gr4.bin", 0x08000, 0x2000, 0x15985c8c )
	ROM_LOAD( "otw-gr5.bin", 0x0a000, 0x2000, 0x448f7e3c )
ROM_END


ROM_START( snakepit_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "spit-ab0.bin", 0x10000, 0x2000, 0x5aa86081 )
	ROM_LOAD( "spit-ab1.bin", 0x12000, 0x2000, 0x588228b8 )
	ROM_LOAD( "spit-ab2.bin", 0x14000, 0x2000, 0x60173ab6 )
	ROM_LOAD( "spit-ab3.bin", 0x16000, 0x2000, 0x56cb51a8 )
	ROM_LOAD( "spit-ab4.bin", 0x18000, 0x2000, 0x40ba61e0 )
	ROM_LOAD( "spit-ab5.bin", 0x1a000, 0x2000, 0x2a1d9d8f )
	ROM_LOAD( "spit-cd.bin",  0x2c000, 0x2000, BADCRC( 0xc5dd5d07 ))
	ROM_LOAD( "spit-ef.bin",  0x2e000, 0x2000, 0x5f836a66 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",     0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "spit-gr0.bin", 0x00000, 0x2000, 0xf77fd85d )
	ROM_LOAD( "spit-gr1.bin", 0x02000, 0x2000, 0x3ad10334 )
	ROM_LOAD( "spit-gr2.bin", 0x04000, 0x2000, 0x24887703 )
	ROM_LOAD( "spit-gr3.bin", 0x06000, 0x2000, 0xc6703ec2 )
	ROM_LOAD( "spit-gr4.bin", 0x08000, 0x2000, 0xb4293435 )
	ROM_LOAD( "spit-gr5.bin", 0x0a000, 0x2000, 0xdc27c970 )
ROM_END


ROM_START( snakjack_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "rom-ab0.u9a", 0x10000, 0x2000, 0xda2dd119 )
	ROM_LOAD( "rom-ab1.u8a", 0x12000, 0x2000, 0x657ddf26 )
	ROM_LOAD( "rom-ab2.u7a", 0x14000, 0x2000, 0x15333dcf )
	ROM_LOAD( "rom-ab3.u6a", 0x16000, 0x2000, 0x57671f6f )
	ROM_LOAD( "rom-ab4.u5a", 0x18000, 0x2000, 0xc16c5dc0 )
	ROM_LOAD( "rom-ab5.u4a", 0x1a000, 0x2000, 0xd7019747 )
	ROM_LOAD( "rom-cd.u3a",  0x2c000, 0x2000, 0x7b44ca4c )
	ROM_LOAD( "rom-ef.u1a",  0x2e000, 0x2000, 0xf5309b38 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",    0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "rom-gr0.u9b", 0x00000, 0x2000, 0x3e64b5d5 )
	ROM_LOAD( "rom-gr1.u8b", 0x02000, 0x2000, 0xb3b8baee )
	ROM_LOAD( "rom-gr2.u7b", 0x04000, 0x2000, 0xe9d89dac )
	ROM_LOAD( "rom-gr3.u6b", 0x06000, 0x2000, 0xb6602be8 )
	ROM_LOAD( "rom-gr4.u5b", 0x08000, 0x2000, 0x3fbfa686 )
	ROM_LOAD( "rom-gr5.u4b", 0x0a000, 0x2000, 0x345f94fb )
ROM_END


ROM_START( stocker_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "stkr-ab0.bin", 0x10000, 0x2000, 0x784a00ad )
	ROM_LOAD( "stkr-ab1.bin", 0x12000, 0x2000, 0xcdae01dc )
	ROM_LOAD( "stkr-ab2.bin", 0x14000, 0x2000, 0x18527d57 )
	ROM_LOAD( "stkr-ab3.bin", 0x16000, 0x2000, 0x028f6c06 )
	ROM_LOAD( "stkr-cd.bin",  0x2c000, 0x2000, 0x53dbc4e5 )
	ROM_LOAD( "stkr-ef.bin",  0x2e000, 0x2000, 0xcdcf46bc )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",    0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "stkr-gr0.bin", 0x00000, 0x2000, 0x76d5694c )
	ROM_LOAD( "stkr-gr1.bin", 0x02000, 0x2000, 0x4a5cc00b )
	ROM_LOAD( "stkr-gr2.bin", 0x04000, 0x2000, 0x70002382 )
	ROM_LOAD( "stkr-gr3.bin", 0x06000, 0x2000, 0x68c862d8 )
ROM_END


ROM_START( triviag1_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "tpg1-ab0.bin", 0x10000, 0x2000, 0x79fd3ac3 )
	ROM_LOAD( "tpg1-ab1.bin", 0x12000, 0x2000, 0x0ff677e9 )
	ROM_LOAD( "tpg1-ab2.bin", 0x14000, 0x2000, 0x3b4d03e7 )
	ROM_LOAD( "tpg1-ab3.bin", 0x16000, 0x2000, 0x2c6c0651 )
	ROM_LOAD( "tpg1-ab4.bin", 0x18000, 0x2000, 0x397529e7 )
	ROM_LOAD( "tpg1-ab5.bin", 0x1a000, 0x2000, 0x499773a4 )
	ROM_LOAD( "tpg1-cd.bin",  0x2c000, 0x2000, 0x35c9b9c2 )
	ROM_LOAD( "tpg1-ef.bin",  0x2e000, 0x2000, 0x64878342 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",    0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "tpg1-gr0.bin", 0x00000, 0x2000, 0x20c9217a )
	ROM_LOAD( "tpg1-gr1.bin", 0x02000, 0x2000, 0xd7f44504 )
	ROM_LOAD( "tpg1-gr2.bin", 0x04000, 0x2000, 0x4e59a15d )
	ROM_LOAD( "tpg1-gr3.bin", 0x06000, 0x2000, 0x323a8640 )
	ROM_LOAD( "tpg1-gr4.bin", 0x08000, 0x2000, 0x673acf42 )
	ROM_LOAD( "tpg1-gr5.bin", 0x0a000, 0x2000, 0x067bfd66 )
ROM_END


ROM_START( triviasp_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "allsport.8a", 0x10000, 0x4000, 0x54b7ff31 )
	ROM_LOAD( "allsport.7a", 0x14000, 0x4000, 0x59fae9d2 )
	ROM_LOAD( "allsport.6a", 0x18000, 0x4000, 0x237b6b95 )
	ROM_LOAD( "allsport.5a", 0x1c000, 0x4000, 0xb64d7f61 )
	ROM_LOAD( "allsport.3a", 0x24000, 0x4000, 0xe45d09d6 )
	ROM_LOAD( "allsport.1a", 0x2c000, 0x4000, 0x8bb3e831 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",     0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "allsport.6b", 0x00000, 0x4000, 0x6829de8e )
	ROM_LOAD( "allsport.5b", 0x04000, 0x4000, 0x89398700 )
	ROM_LOAD( "allsport.3b", 0x08000, 0x4000, 0x7415a7fc )
ROM_END


ROM_START( gimeabrk_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "ab01.u8a",  0x10000, 0x4000, 0x18cc53db )
	ROM_LOAD( "ab23.u7a",  0x14000, 0x4000, 0x6bd4190a )
	ROM_LOAD( "ab45.u6a",  0x18000, 0x4000, 0x5dca4f33 )
	ROM_LOAD( "cd6ef.uia", 0x2c000, 0x4000, 0x5e2b3510 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",  0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "gr01.u6b", 0x00000, 0x4000, 0xe3cdc476 )
	ROM_LOAD( "gr23.u5b", 0x04000, 0x4000, 0x0555d9c0 )
ROM_END


ROM_START( minigolf_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "ab01.u8a",  0x10000, 0x4000, 0x348f827f )
	ROM_LOAD( "ab23.u7a",  0x14000, 0x4000, 0x19a6ff47 )
	ROM_LOAD( "ab45.u6a",  0x18000, 0x4000, 0x925d76eb )
	ROM_LOAD( "ab67.u5a",  0x1c000, 0x4000, 0x6a311c9a )
	ROM_LOAD( "cd23.u3a",  0x24000, 0x4000, 0x52279801 )
	ROM_LOAD( "cd6ef.u1a", 0x2c000, 0x4000, 0x34c64f4c )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",  0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "gr01.u6b", 0x00000, 0x4000, 0x8e24d594 )
	ROM_LOAD( "gr23.u5b", 0x04000, 0x4000, 0x3bf355ef )
	ROM_LOAD( "gr45.u4b", 0x08000, 0x4000, 0x8eb14921 )
ROM_END


ROM_START( minigol2_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "4a-ver2",  0x10000, 0x10000, 0x97d50493 )
	ROM_LOAD( "1a-ver2",  0x20000, 0x10000, 0x60b6cd58 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",  0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "6b-ver2",  0x00000, 0x8000, 0x5988f4ba )
	ROM_LOAD( "4b-ver2",  0x08000, 0x8000, 0x78a30e23 )
ROM_END


ROM_START( toggle_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "tgle-ab0.bin", 0x10000, 0x2000, 0x8c7b7fad )
	ROM_LOAD( "tgle-ab1.bin", 0x12000, 0x2000, 0x771e5434 )
	ROM_LOAD( "tgle-ab2.bin", 0x14000, 0x2000, 0x9b4baa3f )
	ROM_LOAD( "tgle-ab3.bin", 0x16000, 0x2000, 0x35308a41 )
	ROM_LOAD( "tgle-ab4.bin", 0x18000, 0x2000, 0xbaf5617b )
	ROM_LOAD( "tgle-ab5.bin", 0x1a000, 0x2000, 0x88077dad )
	ROM_LOAD( "tgle-cd.bin",  0x2c000, 0x2000, 0x0a2bb949 )
	ROM_LOAD( "tgle-ef.bin",  0x2e000, 0x2000, 0x3ec10804 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",    0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "tgle-gr0.bin", 0x00000, 0x2000, 0x0e0e5d0e )
	ROM_LOAD( "tgle-gr1.bin", 0x02000, 0x2000, 0x3b141ad2 )
ROM_END


ROM_START( nstocker_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "ab01.u8a",  0x12000, 0x2000, 0xa635f973 )
	ROM_CONTINUE(          0x10000, 0x2000 )
	ROM_LOAD( "ab23.u7a",  0x16000, 0x2000, 0x223acbb2 )
	ROM_CONTINUE(          0x14000, 0x2000 )
	ROM_LOAD( "ab45.u6a",  0x1a000, 0x2000, 0x27a728b5 )
	ROM_CONTINUE(          0x18000, 0x2000 )
	ROM_LOAD( "ab67.u5a",  0x1e000, 0x2000, 0x2999cdf2 )
	ROM_CONTINUE(          0x1c000, 0x2000 )
	ROM_LOAD( "cd01.u4a",  0x22000, 0x2000, 0x75e9b51a )
	ROM_CONTINUE(          0x20000, 0x2000 )
	ROM_LOAD( "cd23.u3a",  0x26000, 0x2000, 0x0a32e0a5 )
	ROM_CONTINUE(          0x24000, 0x2000 )
	ROM_LOAD( "cd45.u2a",  0x2a000, 0x2000, 0x9bb292fe )
	ROM_CONTINUE(          0x28000, 0x2000 )
	ROM_LOAD( "cd6ef.u1a", 0x2e000, 0x2000, 0xe77c1aea )
	ROM_CONTINUE(          0x2c000, 0x2000)

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",  0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "gr01.u4c", 0x00000, 0x4000, 0xfd0c38be )
	ROM_LOAD( "gr23.u3c", 0x04000, 0x4000, 0x35d4433e )
	ROM_LOAD( "gr45.u2c", 0x08000, 0x4000, 0x734b858a )
	ROM_LOAD( "gr67.u1c", 0x0c000, 0x4000, 0x3311f9c0 )
ROM_END


ROM_START( sfootbal_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "sfbab01.bin",  0x12000, 0x2000, 0x2a69803f )
	ROM_CONTINUE(             0x10000, 0x2000 )
	ROM_LOAD( "sfbab23.bin",  0x16000, 0x2000, 0x89f157c2 )
	ROM_CONTINUE(             0x14000, 0x2000 )
	ROM_LOAD( "sfbab45.bin",  0x1a000, 0x2000, 0x91ad42c5 )
	ROM_CONTINUE(             0x18000, 0x2000 )
	ROM_LOAD( "sfbcd6ef.bin", 0x2e000, 0x2000, 0xbf80bb1a )
	ROM_CONTINUE(             0x2c000, 0x2000 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",  0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "sfbgr01.bin", 0x00000, 0x4000, 0xe3108d35 )
	ROM_LOAD( "sfbgr23.bin", 0x04000, 0x4000, 0x5c5af726 )
	ROM_LOAD( "sfbgr45.bin", 0x08000, 0x4000, 0xe767251e )
	ROM_LOAD( "sfbgr67.bin", 0x0c000, 0x4000, 0x42452a7a )
ROM_END


ROM_START( rescraid_rom )
	ROM_REGION(0x40000)     /* 64k for code for the first CPU, plus 128k of banked ROMs */
	ROM_LOAD( "ab1.a10",   0x10000, 0x8000, 0x33a76b47 )
	ROM_LOAD( "ab12.a12",  0x18000, 0x8000, 0x7c7a9f12 )
	ROM_LOAD( "cd8.a16",   0x20000, 0x8000, 0x90917a43 )
	ROM_LOAD( "cd12.a18",  0x28000, 0x8000, 0x0450e9d7 )

	ROM_REGION(0x10000)		/* 64k for Z80 */
	ROM_LOAD( "sentesnd",  0x00000, 0x2000, 0x4dd0a525 )

	ROM_REGION_DISPOSE(0x10000)	/* up to 64k of sprites */
	ROM_LOAD( "gr0.a5",    0x00000, 0x8000, 0xe0dfc133 )
	ROM_LOAD( "gr4.a7",    0x08000, 0x8000, 0x952ade30 )
ROM_END



/*************************************
 *
 *	Game drivers
 *
 *************************************/

#define BALSENTE_DRIVER(name,year,fullname) 	\
	struct GameDriver name##_driver =			\
	{											\
		__FILE__,								\
		NULL,									\
		#name,									\
		fullname,								\
		#year,									\
		"Bally/Sente",							\
		"Aaron Giles",							\
		0,										\
		&machine_driver,						\
		name##_init,							\
												\
		name##_rom,								\
		0, 0,									\
		0,										\
		0,	/* sound_prom */					\
												\
		name##_input_ports,						\
												\
		0,0,0,									\
		ORIENTATION_DEFAULT,					\
												\
		hiload,hisave							\
	};

#define BALSENTE_CLONE_DRIVER(name,year,fullname,cloneof) \
	struct GameDriver name##_driver =			\
	{											\
		__FILE__,								\
		&cloneof##_driver,						\
		#name,									\
		fullname,								\
		#year,									\
		"Bally/Sente",							\
		"Aaron Giles",							\
		0,										\
		&machine_driver,						\
		name##_init,							\
												\
		name##_rom,								\
		0, 0,									\
		0,										\
		0,	/* sound_prom */					\
												\
		name##_input_ports,						\
												\
		0,0,0,									\
		ORIENTATION_DEFAULT,					\
												\
		hiload,hisave							\
	};


BALSENTE_DRIVER      (sentetst, 1984, "Sente Diagnostic Cartridge")
BALSENTE_DRIVER      (cshift,   1984, "Chicken Shift")
BALSENTE_DRIVER      (gghost,   1984, "Goalie Ghost")
BALSENTE_DRIVER      (hattrick, 1984, "Hat Trick")
BALSENTE_DRIVER      (otwalls,  1984, "Off the Wall (Sente)")
BALSENTE_DRIVER      (snakepit, 1984, "Snake Pit")
BALSENTE_DRIVER      (snakjack, 1984, "Snacks'n Jaxson")
BALSENTE_DRIVER      (stocker,  1984, "Stocker")
BALSENTE_DRIVER      (triviag1, 1984, "Trivial Pursuit (Genus I)")
BALSENTE_DRIVER      (triviasp, 1984, "Trivial Pursuit (All Star Sports Edition)")
BALSENTE_DRIVER      (gimeabrk, 1985, "Gimme A Break")
BALSENTE_DRIVER      (minigolf, 1985, "Mini Golf (set 1)")
BALSENTE_CLONE_DRIVER(minigol2, 1985, "Mini Golf (set 2)", minigolf)
BALSENTE_DRIVER      (toggle,   1985, "Toggle")
BALSENTE_DRIVER      (nstocker, 1986, "Night Stocker")
BALSENTE_DRIVER      (sfootbal, 1986, "Street Football")
BALSENTE_DRIVER      (rescraid, 1987, "Rescue Raider")
