summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/mame/drivers/guab.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/mame/drivers/guab.c')
-rw-r--r--trunk/src/mame/drivers/guab.c965
1 files changed, 965 insertions, 0 deletions
diff --git a/trunk/src/mame/drivers/guab.c b/trunk/src/mame/drivers/guab.c
new file mode 100644
index 00000000000..6e09d7a56da
--- /dev/null
+++ b/trunk/src/mame/drivers/guab.c
@@ -0,0 +1,965 @@
+/***************************************************************************
+
+ JPM Give us a Break hardware
+
+ preliminary driver by Phil Bennett
+
+ Games supported:
+ * Give us a Break [8 sets]
+ * Criss Cross (Sweden) [non-working - need disk image]
+ * Ten Up [2 sets]
+
+ Looking for:
+ * Numbers Game
+ * Pac Quiz
+ * Suit Pursuit
+ * Treasure Trail?
+
+ Known issues:
+ * Neither game registers coins and I can't find where the credit
+ count gets updated in the code. Each game requires a unique
+ security PAL - maybe this is related? I'm poking the coin values
+ directly into RAM for now.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/6840ptm.h"
+#include "video/tms34061.h"
+#include "sound/sn76496.h"
+
+
+/*************************************
+ *
+ * Defines
+ *
+ *************************************/
+
+#define LOG_FDC_COMMANDS 0
+#define FDC_LOG(x) do { if (LOG_FDC_COMMANDS) mame_printf_debug x; } while(0)
+
+
+enum int_levels
+{
+ INT_UNKNOWN1 = 1,
+ INT_UNKNOWN2 = 2,
+ INT_6840PTM = 3,
+ INT_6850ACIA = 4,
+ INT_TMS34061 = 5,
+ INT_FLOPPYCTRL = 6,
+ INT_WATCHDOG_INT = 7,
+};
+
+
+struct ef9369
+{
+ UINT32 addr;
+ UINT16 clut[16]; /* 13-bits - a marking bit and a 444 color */
+};
+
+
+struct wd1770
+{
+ UINT32 status;
+ UINT8 cmd;
+ UINT8 data;
+
+ UINT32 side;
+ INT32 track;
+ INT32 sector;
+ UINT32 sptr;
+};
+
+
+class guab_state : public driver_device
+{
+public:
+ guab_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag) { }
+
+ struct ef9369 m_pal;
+ emu_timer *m_fdc_timer;
+ struct wd1770 m_fdc;
+ DECLARE_WRITE16_MEMBER(guab_tms34061_w);
+ DECLARE_READ16_MEMBER(guab_tms34061_r);
+ DECLARE_WRITE16_MEMBER(ef9369_w);
+ DECLARE_READ16_MEMBER(ef9369_r);
+ DECLARE_WRITE16_MEMBER(wd1770_w);
+ DECLARE_READ16_MEMBER(wd1770_r);
+ DECLARE_READ16_MEMBER(io_r);
+ DECLARE_WRITE16_MEMBER(io_w);
+ DECLARE_INPUT_CHANGED_MEMBER(coin_inserted);
+};
+
+
+/*************************************
+ *
+ * 6840 PTM
+ *
+ *************************************/
+
+static WRITE_LINE_DEVICE_HANDLER( ptm_irq )
+{
+ cputag_set_input_line(device->machine(), "maincpu", INT_6840PTM, state);
+}
+
+static const ptm6840_interface ptm_intf =
+{
+ 1000000,
+ { 0, 0, 0 },
+ { DEVCB_NULL, DEVCB_NULL, DEVCB_NULL },
+ DEVCB_LINE(ptm_irq)
+};
+
+
+/*************************************
+ *
+ * Video hardware
+ *
+ *************************************/
+
+/*****************
+ * TMS34061 CRTC
+ *****************/
+
+static void tms_interrupt(running_machine &machine, int state)
+{
+ cputag_set_input_line(machine, "maincpu", INT_TMS34061, state);
+}
+
+static const struct tms34061_interface tms34061intf =
+{
+ "screen", /* The screen we are acting on */
+ 8, /* VRAM address is (row << rowshift) | col */
+ 0x40000, /* Size of video RAM */
+ tms_interrupt /* Interrupt gen callback */
+};
+
+
+WRITE16_MEMBER(guab_state::guab_tms34061_w)
+{
+ int func = (offset >> 19) & 3;
+ int row = (offset >> 7) & 0xff;
+ int col;
+
+ if (func == 0 || func == 2)
+ col = offset & 0xff;
+ else
+ col = offset <<= 1;
+
+ if (ACCESSING_BITS_8_15)
+ tms34061_w(&space, col, row, func, data >> 8);
+
+ if (ACCESSING_BITS_0_7)
+ tms34061_w(&space, col | 1, row, func, data & 0xff);
+}
+
+
+READ16_MEMBER(guab_state::guab_tms34061_r)
+{
+ UINT16 data = 0;
+ int func = (offset >> 19) & 3;
+ int row = (offset >> 7) & 0xff;
+ int col;
+
+ if (func == 0 || func == 2)
+ col = offset & 0xff;
+ else
+ col = offset <<= 1;
+
+ if (ACCESSING_BITS_8_15)
+ data |= tms34061_r(&space, col, row, func) << 8;
+
+ if (ACCESSING_BITS_0_7)
+ data |= tms34061_r(&space, col | 1, row, func);
+
+ return data;
+}
+
+
+/****************************
+ * EF9369 color palette IC
+ * (16 colors from 4096)
+ ****************************/
+
+/* Non-multiplexed mode */
+WRITE16_MEMBER(guab_state::ef9369_w)
+{
+ struct ef9369 &pal = m_pal;
+ data &= 0x00ff;
+
+ /* Address register */
+ if (offset & 1)
+ {
+ pal.addr = data & 0x1f;
+ }
+ /* Data register */
+ else
+ {
+ UINT32 entry = pal.addr >> 1;
+
+ if ((pal.addr & 1) == 0)
+ {
+ pal.clut[entry] &= ~0x00ff;
+ pal.clut[entry] |= data;
+ }
+ else
+ {
+ UINT16 col;
+
+ pal.clut[entry] &= ~0x1f00;
+ pal.clut[entry] |= (data & 0x1f) << 8;
+
+ /* Remove the marking bit */
+ col = pal.clut[entry] & 0xfff;
+
+ /* Update the MAME palette */
+ palette_set_color_rgb(machine(), entry, pal4bit(col >> 0), pal4bit(col >> 4), pal4bit(col >> 8));
+ }
+
+ /* Address register auto-increment */
+ if (++pal.addr == 32)
+ pal.addr = 0;
+ }
+}
+
+READ16_MEMBER(guab_state::ef9369_r)
+{
+ struct ef9369 &pal = m_pal;
+ if ((offset & 1) == 0)
+ {
+ UINT16 col = pal.clut[pal.addr >> 1];
+
+ if ((pal.addr & 1) == 0)
+ return col & 0xff;
+ else
+ return col >> 8;
+ }
+ else
+ {
+ /* Address register is write only */
+ return 0xffff;
+ }
+}
+
+
+static VIDEO_START( guab )
+{
+ tms34061_start(machine, &tms34061intf);
+}
+
+
+static SCREEN_UPDATE_IND16( guab )
+{
+ int x, y;
+ struct tms34061_display state;
+
+ tms34061_get_display_state(&state);
+
+ /* If blanked, fill with black */
+ if (state.blanked)
+ {
+ bitmap.fill(get_black_pen(screen.machine()), cliprect);
+ return 0;
+ }
+
+ for (y = cliprect.min_y; y <= cliprect.max_y; ++y)
+ {
+ UINT8 *src = &state.vram[256 * y];
+ UINT16 *dest = &bitmap.pix16(y);
+
+ for (x = cliprect.min_x; x <= cliprect.max_x; x += 2)
+ {
+ UINT8 pen = src[x >> 1];
+
+ /* Draw two 4-bit pixels */
+ *dest++ = screen.machine().pens[pen >> 4];
+ *dest++ = screen.machine().pens[pen & 0x0f];
+ }
+ }
+
+ return 0;
+}
+
+
+/*************************************
+ *
+ * WD1770 floppy disk controller
+ * (just enough to get by...)
+ *
+ *************************************/
+
+#define USEC_DELAY 40
+#define DISK_SIDES 2
+#define DISK_TRACKS 80
+#define DISK_SECTORS 18
+
+#define DISK_SECTOR_SIZE 256
+#define DISK_TRACK_SIZE (DISK_SECTOR_SIZE * DISK_SECTORS)
+#define DISK_SIDE_SIZE (DISK_TRACK_SIZE * DISK_TRACKS)
+
+enum wd1770_status
+{
+ BUSY = 1 << 0,
+ DATA_REQUEST = 1 << 1,
+ INDEX = 1 << 1,
+ LOST_DATA = 1 << 2,
+ TRACK_00 = 1 << 2,
+ CRC_ERROR = 1 << 3,
+ RECORD_NOT_FOUND = 1 << 4,
+ RECORD_TYPE = 1 << 5,
+ SPIN_UP = 1 << 5,
+ WRITE_PROTECT = 1 << 6,
+ MOTOR_ON = 1 << 7
+};
+
+
+static TIMER_CALLBACK( fdc_data_callback )
+{
+ guab_state *state = machine.driver_data<guab_state>();
+ struct wd1770 &fdc = state->m_fdc;
+ UINT8* disk = (UINT8*)state->memregion("user1")->base();
+ int more_data = 0;
+
+ /*
+ Disk dumps are organised as:
+
+ Side 0, Track 0: Sectors 0 - 17
+ Side 1, Track 0: Sectors 0 - 17
+ Side 0, Track 1: Sectors 0 - 17
+ Side 1, Track 1: Sectors 0 - 17
+ etc.
+ */
+
+ int idx = 2 * fdc.track * (DISK_TRACK_SIZE) + (fdc.side ? DISK_TRACK_SIZE : 0)+
+ fdc.sector * (DISK_SECTOR_SIZE) +
+ fdc.sptr;
+
+ /* Write or read? */
+ if (fdc.cmd & 0x20)
+ disk[idx] = fdc.data;
+ else
+ fdc.data = disk[idx];
+
+ fdc.sptr++;
+
+ if (fdc.sptr < DISK_SECTOR_SIZE)
+ {
+ more_data = 1;
+ }
+ else
+ {
+ fdc.sptr = 0;
+
+ /* Multi-sector read */
+ if (fdc.cmd & 0x10)
+ {
+ ++fdc.sector;
+
+ /* Keep going */
+ if (fdc.sector < DISK_SECTORS)
+ more_data = 1;
+ }
+ }
+
+ if (more_data)
+ {
+ state->m_fdc_timer->adjust(attotime::from_usec(USEC_DELAY));
+ }
+ else
+ {
+ /* Hack!*/
+ fdc.cmd = 0;
+ fdc.status &= ~BUSY;
+ }
+
+ fdc.status |= DATA_REQUEST;
+ cputag_set_input_line(machine, "maincpu", INT_FLOPPYCTRL, ASSERT_LINE);
+}
+
+
+WRITE16_MEMBER(guab_state::wd1770_w)
+{
+ struct wd1770 &fdc = m_fdc;
+ data &= 0xff;
+
+ switch (offset)
+ {
+ case 0:
+ {
+ UINT8 cmd = (data >> 4) & 0xf;
+
+ FDC_LOG(("Command: %x:: ", data));
+
+ switch (cmd)
+ {
+ /**** Type I ****/
+ case 0:
+ {
+ FDC_LOG(("Restore\n"));
+ fdc.track = 0;
+ break;
+ }
+
+ case 1:
+ {
+ FDC_LOG(("Seek to track %d\n", fdc.data));
+ fdc.track = fdc.data;
+ break;
+ }
+
+ /* Step */
+ case 2:
+ case 3:
+ {
+ FDC_LOG(("Step (not implemented)\n"));
+ break;
+ }
+
+ case 4: case 5:
+ {
+ if (++fdc.track >= DISK_TRACKS)
+ fdc.track = DISK_TRACKS - 1;
+
+ FDC_LOG(("Step-in to track %d\n", fdc.track));
+ break;
+ }
+
+ case 6: case 7:
+ {
+ if (--fdc.track > 0)
+ fdc.track = 0;
+
+ FDC_LOG(("Step-out to track %d\n", fdc.track));
+ break;
+ }
+
+
+ /**** Type II ****/
+ case 8:
+ case 9:
+ {
+ fdc.cmd = data;
+ fdc.status |= BUSY;
+
+ if (data & 0x10)
+ FDC_LOG(("Multi "));
+
+ FDC_LOG(("Sector read: H%d T%d S%d\n", fdc.side,
+ fdc.track,
+ fdc.sector));
+
+ /* Set the data read timer */
+ m_fdc_timer->adjust(attotime::from_usec(USEC_DELAY));
+
+ break;
+ }
+
+ case 10:
+ case 11:
+ {
+ fdc.cmd = data;
+ fdc.status |= BUSY;
+
+ if (data & 0x10)
+ FDC_LOG(("Multi "));
+
+ FDC_LOG(("Sector write: H%d T%d S%d\n", fdc.side,
+ fdc.track,
+ fdc.sector));
+
+ /* Trigger a DRQ interrupt on the CPU */
+ cputag_set_input_line(machine(), "maincpu", INT_FLOPPYCTRL, ASSERT_LINE);
+ fdc.status |= DATA_REQUEST;
+ break;
+ }
+
+ /**** Type III ****/
+ case 12: /* Read address */
+ case 14: /* Read track */
+ case 15: /* Write track */
+ {
+ FDC_LOG(("Unsupported TYPE III operation\n"));
+ break;
+ }
+
+ /**** Type IV ****/
+ case 13:
+ {
+ /* Stop any operation in progress */
+ m_fdc_timer->reset();
+ fdc.status &= ~BUSY;
+ FDC_LOG(("Force Interrupt\n"));
+ break;
+ }
+ }
+
+ break;
+ }
+ case 1:
+ {
+ FDC_LOG(("Set track: %d\n", data));
+ fdc.track = data;
+ break;
+ }
+ case 2:
+ {
+ FDC_LOG(("Set sector: %d\n", data));
+ fdc.sector = data;
+ fdc.sptr = 0;
+ break;
+ }
+ case 3:
+ {
+ fdc.data = data;
+
+ /* Clear the DRQ */
+ cputag_set_input_line(machine(), "maincpu", INT_FLOPPYCTRL, CLEAR_LINE);
+
+ /* Queue an event to write the data if write command was specified */
+ if (fdc.cmd & 0x20)
+ m_fdc_timer->adjust(attotime::from_usec(USEC_DELAY));
+
+ break;
+ }
+ }
+}
+
+READ16_MEMBER(guab_state::wd1770_r)
+{
+ struct wd1770 &fdc = m_fdc;
+ UINT16 retval = 0;
+
+ switch (offset)
+ {
+ case 0:
+ {
+ retval = fdc.status;
+ break;
+ }
+ case 1:
+ {
+ retval = fdc.track;
+ break;
+ }
+ case 2:
+ {
+ retval = fdc.sector;
+ break;
+ }
+ case 3:
+ {
+ retval = fdc.data;
+
+ /* Clear the DRQ */
+ cputag_set_input_line(machine(), "maincpu", INT_FLOPPYCTRL, CLEAR_LINE);
+ fdc.status &= ~DATA_REQUEST;
+ break;
+ }
+ }
+
+ return retval;
+}
+
+
+/****************************************
+ *
+ * Hardware inputs (coins, buttons etc)
+ *
+ ****************************************/
+
+READ16_MEMBER(guab_state::io_r)
+{
+ static const char *const portnames[] = { "IN0", "IN1", "IN2" };
+
+ switch (offset)
+ {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ {
+ return ioport(portnames[offset])->read();
+ }
+ case 0x30:
+ {
+ /* Whatever it is, bit 7 must be 0 */
+ return 0x7f;
+ }
+ default:
+ {
+ mame_printf_debug("Unknown IO R:0x%x\n", 0xc0000 + (offset * 2));
+ return 0;
+ }
+ }
+}
+
+INPUT_CHANGED_MEMBER(guab_state::coin_inserted)
+{
+ if (newval == 0)
+ {
+ UINT32 credit;
+ address_space *space = machine().device("maincpu")->memory().space(AS_PROGRAM);
+
+ /* Get the current credit value and add the new coin value */
+ credit = space->read_dword(0x8002c) + (UINT32)(FPTR)param;
+ space->write_dword(0x8002c, credit);
+ }
+}
+
+/****************************************
+ *
+ * Hardware outputs (lamps, meters etc)
+ *
+ ****************************************/
+
+WRITE16_MEMBER(guab_state::io_w)
+{
+ struct wd1770 &fdc = m_fdc;
+ switch (offset)
+ {
+ case 0x10:
+ {
+ /* Outputs 0 - 7 */
+ break;
+ }
+ case 0x11:
+ {
+ /* Outputs 8 - 15 */
+ break;
+ }
+ case 0x12:
+ {
+ /* Outputs 16 - 23 */
+ break;
+ }
+ case 0x20:
+ {
+ /* Outputs 24 - 31 */
+ break;
+ }
+ case 0x21:
+ {
+ /* Outputs 32 - 39 */
+ break;
+ }
+ case 0x22:
+ {
+ /* Outputs 40 - 47 */
+ break;
+ }
+ case 0x30:
+ {
+ sn76496_w(machine().device("snsnd"), 0, data & 0xff);
+ break;
+ }
+ case 0x31:
+ {
+ /* Only JPM knows about the other bits... */
+ fdc.side = (data >> 3) & 1;
+ break;
+ }
+ case 0x32:
+ {
+ /* Watchdog? */
+ break;
+ }
+ case 0x33:
+ {
+ /* Dunno */
+ break;
+ }
+ default:
+ {
+ mame_printf_debug("Unknown IO W:0x%x with %x\n", 0xc0000 + (offset * 2), data);
+ }
+ }
+}
+
+
+/*************************************
+ *
+ * 68000 CPU memory handlers
+ *
+ *************************************/
+
+static ADDRESS_MAP_START( guab_map, AS_PROGRAM, 16, guab_state )
+ AM_RANGE(0x000000, 0x00ffff) AM_ROM
+ AM_RANGE(0x040000, 0x04ffff) AM_ROM AM_REGION("maincpu", 0x10000)
+ AM_RANGE(0x0c0000, 0x0c007f) AM_READWRITE(io_r, io_w)
+ AM_RANGE(0x0c0080, 0x0c0083) AM_NOP /* ACIA 1 */
+ AM_RANGE(0x0c00a0, 0x0c00a3) AM_NOP /* ACIA 2 */
+ AM_RANGE(0x0c00c0, 0x0c00cf) AM_DEVREADWRITE8("6840ptm", ptm6840_device, read, write, 0xff)
+ AM_RANGE(0x0c00e0, 0x0c00e7) AM_READWRITE(wd1770_r, wd1770_w)
+ AM_RANGE(0x080000, 0x080fff) AM_RAM
+ AM_RANGE(0x100000, 0x100003) AM_READWRITE(ef9369_r, ef9369_w)
+ AM_RANGE(0x800000, 0xb0ffff) AM_READWRITE(guab_tms34061_r, guab_tms34061_w)
+ AM_RANGE(0xb10000, 0xb1ffff) AM_RAM
+ AM_RANGE(0xb80000, 0xb8ffff) AM_RAM
+ AM_RANGE(0xb90000, 0xb9ffff) AM_RAM
+ADDRESS_MAP_END
+
+
+/*************************************
+ *
+ * Port definitions
+ *
+ *************************************/
+
+static INPUT_PORTS_START( guab )
+ PORT_START("IN0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN3 ) PORT_NAME("50p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)50)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN4 ) PORT_NAME("100p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)100)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Back door") PORT_CODE(KEYCODE_R) PORT_TOGGLE
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Cash door") PORT_CODE(KEYCODE_T) PORT_TOGGLE
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Key switch") PORT_CODE(KEYCODE_Y) PORT_TOGGLE
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH,IPT_UNUSED ) PORT_NAME("50p level")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH,IPT_UNUSED ) PORT_NAME("100p level")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH,IPT_UNUSED )
+
+ PORT_START("IN1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B")
+
+ PORT_START("IN2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Select")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("D")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_NAME("10p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)10)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_NAME("20p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)20)
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( tenup )
+ PORT_START("IN0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN3 ) PORT_NAME("50p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)50)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN4 ) PORT_NAME("100p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)100)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Back door") PORT_CODE(KEYCODE_R) PORT_TOGGLE
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Cash door") PORT_CODE(KEYCODE_T) PORT_TOGGLE
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Key switch") PORT_CODE(KEYCODE_Y) PORT_TOGGLE
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH,IPT_UNUSED ) PORT_NAME("10p level")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH,IPT_UNUSED ) PORT_NAME("100p level")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH,IPT_UNUSED )
+
+ PORT_START("IN1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Pass")
+
+ PORT_START("IN2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Collect")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_NAME("10p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)10)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_NAME("20p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)20)
+INPUT_PORTS_END
+
+
+/*************************************
+ *
+ * Machine driver
+ *
+ *************************************/
+
+ static MACHINE_START( guab )
+{
+ guab_state *state = machine.driver_data<guab_state>();
+ state->m_fdc_timer = machine.scheduler().timer_alloc(FUNC(fdc_data_callback));
+}
+
+static MACHINE_RESET( guab )
+{
+ guab_state *state = machine.driver_data<guab_state>();
+ memset(&state->m_fdc, 0, sizeof(state->m_fdc));
+}
+
+static MACHINE_CONFIG_START( guab, guab_state )
+ /* TODO: Verify clock */
+ MCFG_CPU_ADD("maincpu", M68000, 8000000)
+ MCFG_CPU_PROGRAM_MAP(guab_map)
+
+ MCFG_MACHINE_START(guab)
+ MCFG_MACHINE_RESET(guab)
+
+ /* TODO: Use real video timings */
+ MCFG_SCREEN_ADD("screen", RASTER)
+ MCFG_SCREEN_REFRESH_RATE(60)
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
+ MCFG_SCREEN_SIZE(64*8, 32*8)
+ MCFG_SCREEN_VISIBLE_AREA(0, 64*8-1, 0, 32*8-1)
+ MCFG_SCREEN_UPDATE_STATIC(guab)
+
+ MCFG_PALETTE_LENGTH(16)
+
+ MCFG_VIDEO_START(guab)
+
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+
+ /* TODO: Verify clock */
+ MCFG_SOUND_ADD("snsnd", SN76489, 2000000)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+ /* 6840 PTM */
+ MCFG_PTM6840_ADD("6840ptm", ptm_intf)
+MACHINE_CONFIG_END
+
+
+/*************************************
+ *
+ * ROM definition(s)
+ *
+ *************************************/
+
+ROM_START( guab )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "guab1a1.rom", 0x00000, 0x8000, CRC(f23a9d7d) SHA1(f933e131bdcf21cfa6001c8e20fd11d94c7a9450) )
+ ROM_LOAD16_BYTE( "guab1b1.rom", 0x00001, 0x8000, CRC(af3b5492) SHA1(6fd7f29e6ed2fadccc9246f1ebd049c3f9aeff13) )
+ ROM_LOAD16_BYTE( "guab2a1.rom", 0x10000, 0x8000, CRC(ae7a162c) SHA1(d69721818b8e4daba776a678b62bc7f44f371a3f) )
+ ROM_LOAD16_BYTE( "guab2b1.rom", 0x10001, 0x8000, CRC(29aa26a0) SHA1(8d425ad845ccfcd8995dbf6adc1ca17989a5d3ea) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "guab3.dsk", 0x00000, 0xb4000, CRC(ecb41e06) SHA1(2900a95046b38312c6035ea394b04b62c1d29f42) )
+ROM_END
+
+ROM_START( guab3a )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "guab1a1.rom", 0x00000, 0x8000, CRC(f23a9d7d) SHA1(f933e131bdcf21cfa6001c8e20fd11d94c7a9450) )
+ ROM_LOAD16_BYTE( "guab1b1.rom", 0x00001, 0x8000, CRC(af3b5492) SHA1(6fd7f29e6ed2fadccc9246f1ebd049c3f9aeff13) )
+ ROM_LOAD16_BYTE( "guab2a1.rom", 0x10000, 0x8000, CRC(ae7a162c) SHA1(d69721818b8e4daba776a678b62bc7f44f371a3f) )
+ ROM_LOAD16_BYTE( "guab2b1.rom", 0x10001, 0x8000, CRC(29aa26a0) SHA1(8d425ad845ccfcd8995dbf6adc1ca17989a5d3ea) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "guab7c.dsk", 0x00000, 0xb4000, CRC(f5f10f87) SHA1(80e540339efbfe59b656d6cd4f466a17df84c123) )
+ROM_END
+
+ROM_START( guab4 )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "guab1a1.rom", 0x00000, 0x8000, CRC(f23a9d7d) SHA1(f933e131bdcf21cfa6001c8e20fd11d94c7a9450) )
+ ROM_LOAD16_BYTE( "guab1b1.rom", 0x00001, 0x8000, CRC(af3b5492) SHA1(6fd7f29e6ed2fadccc9246f1ebd049c3f9aeff13) )
+ ROM_LOAD16_BYTE( "guab2a1.rom", 0x10000, 0x8000, CRC(ae7a162c) SHA1(d69721818b8e4daba776a678b62bc7f44f371a3f) )
+ ROM_LOAD16_BYTE( "guab2b1.rom", 0x10001, 0x8000, CRC(29aa26a0) SHA1(8d425ad845ccfcd8995dbf6adc1ca17989a5d3ea) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "guab8d.dsk", 0x00000, 0xb4000, CRC(b87c55ce) SHA1(20debbefae194276b0813518634cf52bed093e73) )
+ROM_END
+
+ROM_START( guab6 )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "guab1a1.rom", 0x00000, 0x8000, CRC(f23a9d7d) SHA1(f933e131bdcf21cfa6001c8e20fd11d94c7a9450) )
+ ROM_LOAD16_BYTE( "guab1b1.rom", 0x00001, 0x8000, CRC(af3b5492) SHA1(6fd7f29e6ed2fadccc9246f1ebd049c3f9aeff13) )
+ ROM_LOAD16_BYTE( "guab2a1.rom", 0x10000, 0x8000, CRC(ae7a162c) SHA1(d69721818b8e4daba776a678b62bc7f44f371a3f) )
+ ROM_LOAD16_BYTE( "guab2b1.rom", 0x10001, 0x8000, CRC(29aa26a0) SHA1(8d425ad845ccfcd8995dbf6adc1ca17989a5d3ea) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "guabf6.dsk", 0x00000, 0xb4000, CRC(08804c28) SHA1(608d89d598b7acb133814540dba98cea29c6cad6) )
+ROM_END
+
+ROM_START( guab6a )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "guab1a1.rom", 0x00000, 0x8000, CRC(f23a9d7d) SHA1(f933e131bdcf21cfa6001c8e20fd11d94c7a9450) )
+ ROM_LOAD16_BYTE( "guab1b1.rom", 0x00001, 0x8000, CRC(af3b5492) SHA1(6fd7f29e6ed2fadccc9246f1ebd049c3f9aeff13) )
+ ROM_LOAD16_BYTE( "guab2a1.rom", 0x10000, 0x8000, CRC(ae7a162c) SHA1(d69721818b8e4daba776a678b62bc7f44f371a3f) )
+ ROM_LOAD16_BYTE( "guab2b1.rom", 0x10001, 0x8000, CRC(29aa26a0) SHA1(8d425ad845ccfcd8995dbf6adc1ca17989a5d3ea) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "guab9f.dsk", 0x00000, 0xb4000, CRC(85329fe9) SHA1(f5ca1956c37b786fa0a4f8f0607a0a2b19d3fbb0) )
+ROM_END
+
+ROM_START( guab7 )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "guab1a1.rom", 0x00000, 0x8000, CRC(f23a9d7d) SHA1(f933e131bdcf21cfa6001c8e20fd11d94c7a9450) )
+ ROM_LOAD16_BYTE( "guab1b1.rom", 0x00001, 0x8000, CRC(af3b5492) SHA1(6fd7f29e6ed2fadccc9246f1ebd049c3f9aeff13) )
+ ROM_LOAD16_BYTE( "guab2a1.rom", 0x10000, 0x8000, CRC(ae7a162c) SHA1(d69721818b8e4daba776a678b62bc7f44f371a3f) )
+ ROM_LOAD16_BYTE( "guab2b1.rom", 0x10001, 0x8000, CRC(29aa26a0) SHA1(8d425ad845ccfcd8995dbf6adc1ca17989a5d3ea) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "guab9g.dsk", 0x00000, 0xb4000, CRC(6b8c36f9) SHA1(1d9f4d943f2962603bbe39e5b58befe15954a6d6) )
+ROM_END
+
+ROM_START( guab21 )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "guab1a1.rom", 0x00000, 0x8000, CRC(f23a9d7d) SHA1(f933e131bdcf21cfa6001c8e20fd11d94c7a9450) )
+ ROM_LOAD16_BYTE( "guab1b1.rom", 0x00001, 0x8000, CRC(af3b5492) SHA1(6fd7f29e6ed2fadccc9246f1ebd049c3f9aeff13) )
+ ROM_LOAD16_BYTE( "guab2a1.rom", 0x10000, 0x8000, CRC(ae7a162c) SHA1(d69721818b8e4daba776a678b62bc7f44f371a3f) )
+ ROM_LOAD16_BYTE( "guab2b1.rom", 0x10001, 0x8000, CRC(29aa26a0) SHA1(8d425ad845ccfcd8995dbf6adc1ca17989a5d3ea) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "guab21.dsk", 0x00000, 0xb4000, CRC(558ee009) SHA1(d2a02662216e10f80a215044f1929df7255b6136) )
+ROM_END
+
+ROM_START( guab43 )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "guab1a1.rom", 0x00000, 0x8000, CRC(f23a9d7d) SHA1(f933e131bdcf21cfa6001c8e20fd11d94c7a9450) )
+ ROM_LOAD16_BYTE( "guab1b1.rom", 0x00001, 0x8000, CRC(af3b5492) SHA1(6fd7f29e6ed2fadccc9246f1ebd049c3f9aeff13) )
+ ROM_LOAD16_BYTE( "guab2a1.rom", 0x10000, 0x8000, CRC(ae7a162c) SHA1(d69721818b8e4daba776a678b62bc7f44f371a3f) )
+ ROM_LOAD16_BYTE( "guab2b1.rom", 0x10001, 0x8000, CRC(29aa26a0) SHA1(8d425ad845ccfcd8995dbf6adc1ca17989a5d3ea) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "guab43.dsk", 0x00000, 0xb3f00, CRC(96167357) SHA1(9d5f66e05ed1086be9699c4149071038f6986e0c) )
+ROM_END
+
+ROM_START( crisscrs )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "crisscross_swe_2a1.ic49", 0x00000, 0x8000, CRC(a7ca8828) SHA1(a28482bb2bc1248a9b5c0b57904c382246a632cc) )
+ ROM_LOAD16_BYTE( "crisscross_swe_2b1.ic48", 0x00001, 0x8000, CRC(7e280cae) SHA1(18c76459e39549ddba5f0cd7921013ef4f816826) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "crisscrs.dsk", 0x00000, 0xb4000, NO_DUMP )
+ROM_END
+
+ROM_START( tenup )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "tu-11.bin", 0x00000, 0x8000, CRC(01843086) SHA1(106a226900e8cf929f89edf801c627f02e4afce3) )
+ ROM_LOAD16_BYTE( "tu-12.bin", 0x00001, 0x8000, CRC(1c7f32b1) SHA1(2b14e2206695ae53909ae838a5c036248d9ab940) )
+ ROM_LOAD16_BYTE( "tu-13.bin", 0x10000, 0x8000, CRC(d19e2bf7) SHA1(76a9cbd4f604ad39eb0e319a9a6d5a6739b0ed8c) )
+ ROM_LOAD16_BYTE( "tu-14.bin", 0x10001, 0x8000, CRC(fd8a0c3c) SHA1(f87289ce6f0d2bc9b7d3a0b6deff38ba3aadf391) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "10up17.dsk", 0x00000, 0xb4000, CRC(7bc328df) SHA1(5f8e40d8ffc370fb19be9e386befa5fcd1f35a75) )
+ROM_END
+
+ROM_START( tenup3 )
+ ROM_REGION( 0x20000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "tu-11.bin", 0x00000, 0x8000, CRC(01843086) SHA1(106a226900e8cf929f89edf801c627f02e4afce3) )
+ ROM_LOAD16_BYTE( "tu-12.bin", 0x00001, 0x8000, CRC(1c7f32b1) SHA1(2b14e2206695ae53909ae838a5c036248d9ab940) )
+ ROM_LOAD16_BYTE( "tu-13.bin", 0x10000, 0x8000, CRC(d19e2bf7) SHA1(76a9cbd4f604ad39eb0e319a9a6d5a6739b0ed8c) )
+ ROM_LOAD16_BYTE( "tu-14.bin", 0x10001, 0x8000, CRC(fd8a0c3c) SHA1(f87289ce6f0d2bc9b7d3a0b6deff38ba3aadf391) )
+
+ ROM_REGION( 0xb4000, "user1", 0 )
+ ROM_LOAD( "10up3.dsk", 0x00000, 0xb4000, CRC(2767f017) SHA1(1c6551b089c3e3df48e0c03bd502b91fd88f0e94) )
+ROM_END
+
+
+/*************************************
+ *
+ * Game driver(s)
+ *
+ *************************************/
+
+GAME( 1986, guab, 0, guab, guab, 0, ROT0, "JPM", "Give us a Break (3rd edition)", 0 )
+GAME( 1986, guab3a, guab, guab, guab, 0, ROT0, "JPM", "Give us a Break (3rd edition alt?)", 0 )
+GAME( 1986, guab4, guab, guab, guab, 0, ROT0, "JPM", "Give us a Break (4th edition)", 0 )
+GAME( 1986, guab6, guab, guab, guab, 0, ROT0, "JPM", "Give us a Break (6th edition)", 0 )
+GAME( 1986, guab6a, guab, guab, guab, 0, ROT0, "JPM", "Give us a Break (6th edition alt?)", 0 )
+GAME( 1986, guab7, guab, guab, guab, 0, ROT0, "JPM", "Give us a Break (7th edition)", 0 )
+GAME( 1986, guab21, guab, guab, guab, 0, ROT0, "JPM", "Give us a Break (21st edition)", 0 )
+GAME( 1986, guab43, guab, guab, guab, 0, ROT0, "JPM", "Give us a Break (43rd edition)", 0 )
+GAME( 1986, crisscrs, 0, guab, guab, 0, ROT0, "JPM", "Criss Cross (Sweden)", GAME_NOT_WORKING )
+GAME( 1988, tenup, 0, guab, tenup, 0, ROT0, "JPM", "Ten Up (compendium 17)", 0 )
+GAME( 1988, tenup3, tenup, guab, tenup, 0, ROT0, "JPM", "Ten Up (compendium 3)", 0 )