summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/bus/abckb/abc77.c659
-rw-r--r--src/emu/bus/abckb/abc77.h119
-rw-r--r--src/emu/bus/abckb/abc800kb.c510
-rw-r--r--src/emu/bus/abckb/abc800kb.h93
-rw-r--r--src/emu/bus/abckb/abc99.c783
-rw-r--r--src/emu/bus/abckb/abc99.h117
-rw-r--r--src/emu/bus/abckb/abckb.c139
-rw-r--r--src/emu/bus/abckb/abckb.h100
-rw-r--r--src/emu/bus/bml3/bml3bus.c257
-rw-r--r--src/emu/bus/bml3/bml3bus.h151
-rw-r--r--src/emu/bus/bml3/bml3kanji.c99
-rw-r--r--src/emu/bus/bml3/bml3kanji.h47
-rw-r--r--src/emu/bus/bml3/bml3mp1802.c155
-rw-r--r--src/emu/bus/bml3/bml3mp1802.h50
-rw-r--r--src/emu/bus/bml3/bml3mp1805.c178
-rw-r--r--src/emu/bus/bml3/bml3mp1805.h52
-rw-r--r--src/emu/bus/bus.mak92
-rw-r--r--src/emu/bus/coco/coco_232.c90
-rw-r--r--src/emu/bus/coco/coco_232.h40
-rw-r--r--src/emu/bus/coco/coco_fdc.c672
-rw-r--r--src/emu/bus/coco/coco_fdc.h155
-rw-r--r--src/emu/bus/coco/coco_multi.c266
-rw-r--r--src/emu/bus/coco/coco_multi.h67
-rw-r--r--src/emu/bus/coco/coco_orch90.c83
-rw-r--r--src/emu/bus/coco/coco_orch90.h40
-rw-r--r--src/emu/bus/coco/coco_pak.c178
-rw-r--r--src/emu/bus/coco/coco_pak.h63
-rw-r--r--src/emu/bus/coco/cococart.c459
-rw-r--r--src/emu/bus/coco/cococart.h175
-rw-r--r--src/emu/bus/compucolor/floppy.c255
-rw-r--r--src/emu/bus/compucolor/floppy.h126
-rw-r--r--src/emu/bus/cpc/cpc_pds.c87
-rw-r--r--src/emu/bus/cpc/cpc_pds.h56
-rw-r--r--src/emu/bus/cpc/cpc_rom.c136
-rw-r--r--src/emu/bus/cpc/cpc_rom.h88
-rw-r--r--src/emu/bus/cpc/cpc_ssa1.c216
-rw-r--r--src/emu/bus/cpc/cpc_ssa1.h126
-rw-r--r--src/emu/bus/cpc/cpcexp.c109
-rw-r--r--src/emu/bus/cpc/cpcexp.h131
-rw-r--r--src/emu/bus/cpc/mface2.c348
-rw-r--r--src/emu/bus/cpc/mface2.h69
-rw-r--r--src/emu/bus/epson_sio/epson_sio.c116
-rw-r--r--src/emu/bus/epson_sio/epson_sio.h97
-rw-r--r--src/emu/bus/epson_sio/pf10.c242
-rw-r--r--src/emu/bus/epson_sio/pf10.h102
-rw-r--r--src/emu/bus/epson_sio/tf20.c343
-rw-r--r--src/emu/bus/epson_sio/tf20.h92
-rw-r--r--src/emu/bus/pce/pce_rom.c124
-rw-r--r--src/emu/bus/pce/pce_rom.h83
-rw-r--r--src/emu/bus/pce/pce_slot.c384
-rw-r--r--src/emu/bus/pce/pce_slot.h126
-rw-r--r--src/emu/bus/rs232/teleprinter.c239
-rw-r--r--src/emu/bus/rs232/teleprinter.h45
-rw-r--r--src/emu/bus/x68k/x68k_neptunex.c152
-rw-r--r--src/emu/bus/x68k/x68k_neptunex.h52
-rw-r--r--src/emu/bus/x68k/x68k_scsiext.c102
-rw-r--r--src/emu/bus/x68k/x68k_scsiext.h44
-rw-r--r--src/emu/bus/x68k/x68kexp.c98
-rw-r--r--src/emu/bus/x68k/x68kexp.h149
-rw-r--r--src/emu/machine/ds1315.c218
-rw-r--r--src/emu/machine/ds1315.h67
-rw-r--r--src/emu/machine/machine.mak9
62 files changed, 10520 insertions, 0 deletions
diff --git a/src/emu/bus/abckb/abc77.c b/src/emu/bus/abckb/abc77.c
new file mode 100644
index 00000000000..8d1ad08d1d9
--- /dev/null
+++ b/src/emu/bus/abckb/abc77.c
@@ -0,0 +1,659 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor ABC-55/77 keyboard emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+/*
+
+PCB Layout
+----------
+
+KTC A65-02486-232
+
+|-----------------------------------------------------------------------|
+| SW1 CN1 LS393 |
+| 4020 7406 LS132 7407 LS02 7407 NE556 LS1 |
+| |
+| 22-950-3B XTAL CPU ROM0 ROM1 LS373 LS240 22-908-03 |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+|-----------------------------------------------------------------------|
+
+Notes:
+ All IC's shown.
+
+ CPU - Signetics SCN8035A 8035 CPU
+ ROM0 - NEC D2716D 2Kx8 ROM "-78"
+ ROM1 - not populated
+ 22-950-3B - Exar Semiconductor XR22-950-3B keyboard matrix row driver with 4 to 12 decoder/demultiplexer
+ 22-908-03 - Exar Semiconductor XR22-908-03 keyboard matrix capacitive readout latch
+ CN1 - 1x12 PCB header
+ LS1 - loudspeaker
+ SW1 - reset switch
+
+*/
+
+#include "abc77.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define I8035_TAG "z16"
+#define DISCRETE_TAG "discrete"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type ABC77 = &device_creator<abc77_device>;
+const device_type ABC55 = &device_creator<abc55_device>;
+
+
+//-------------------------------------------------
+// ROM( abc77 )
+//-------------------------------------------------
+
+ROM_START( abc77 )
+ ROM_REGION( 0x1000, I8035_TAG, 0 )
+ ROM_LOAD( "-78.z10", 0x000, 0x800, CRC(635986ce) SHA1(04a30141ac611d0544bbb786061515040c23480c) )
+// ROM_LOAD( "keyboard.z14", 0x0800, 0x0800, NO_DUMP ) // non-Swedish keyboard encoding ROM
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *abc77_device::device_rom_region() const
+{
+ return ROM_NAME( abc77 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( abc77_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( abc77_map, AS_PROGRAM, 8, abc77_device )
+ AM_RANGE(0x000, 0xfff) AM_ROM AM_REGION("z16", 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( abc77_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( abc77_io, AS_IO, 8, abc77_device )
+ AM_RANGE(0x00, 0x00) AM_MIRROR(0xff) AM_WRITE(j3_w)
+ AM_RANGE(0x00, 0x00) AM_MIRROR(0xff) AM_READ_PORT("DSW")
+ AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READ(p1_r)
+ AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_WRITE(p2_w)
+ AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_r)
+ AM_RANGE(MCS48_PORT_PROG, MCS48_PORT_PROG) AM_WRITE(prog_w)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// DISCRETE_SOUND( abc77 )
+//-------------------------------------------------
+
+static const discrete_555_desc abc77_ne556_a =
+{
+ DISC_555_OUT_SQW | DISC_555_OUT_DC,
+ 5, // B+ voltage of 555
+ DEFAULT_555_VALUES
+};
+
+
+static DISCRETE_SOUND_START( abc77 )
+ DISCRETE_INPUT_LOGIC(NODE_01)
+ DISCRETE_555_ASTABLE(NODE_02, NODE_01, RES_K(2.7), RES_K(15), CAP_N(22), &abc77_ne556_a)
+ DISCRETE_OUTPUT(NODE_02, 5000)
+DISCRETE_SOUND_END
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( abc77 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( abc77 )
+ // keyboard cpu
+ MCFG_CPU_ADD(I8035_TAG, I8035, XTAL_4_608MHz)
+ MCFG_CPU_PROGRAM_MAP(abc77_map)
+ MCFG_CPU_IO_MAP(abc77_io)
+
+ // watchdog
+ MCFG_WATCHDOG_TIME_INIT(attotime::from_hz(XTAL_4_608MHz/3/5/4096))
+
+ // discrete sound
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD(DISCRETE_TAG, DISCRETE, 0)
+ MCFG_SOUND_CONFIG_DISCRETE(abc77)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor abc77_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( abc77 );
+}
+
+
+//-------------------------------------------------
+// INPUT_CHANGED_MEMBER( keyboard_reset )
+//-------------------------------------------------
+
+INPUT_CHANGED_MEMBER( abc77_device::keyboard_reset )
+{
+ if (oldval && !newval)
+ {
+ device_reset();
+ }
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( abc55 )
+//-------------------------------------------------
+
+INPUT_PORTS_START( abc55 )
+ PORT_START("X0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+ 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_KEYBOARD ) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RIGHT SHIFT") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("LEFT SHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+
+ PORT_START("X1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+ 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_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("X2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("\xE2\x86\x90") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("\xE2\x86\x92") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+
+ PORT_START("X3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00E9) PORT_CHAR(0x00C9)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00E5) PORT_CHAR(0x00C5)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00FC) PORT_CHAR(0x00DC)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00E4) PORT_CHAR(0x00C4)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+
+ PORT_START("X4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00F6) PORT_CHAR(0x00D6)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
+
+ PORT_START("X5")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+
+ PORT_START("X6")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+
+ PORT_START("X7")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 \xC2\xA4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x00A4)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+
+ PORT_START("X8")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+
+ PORT_START("X9")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+ 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_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("X10")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+ 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_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("X11")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+
+ PORT_START("DSW")
+ PORT_DIPNAME( 0x01, 0x01, "Keyboard Program" )
+ PORT_DIPSETTING( 0x00, "Internal (8048)" )
+ PORT_DIPSETTING( 0x01, "External PROM" ) // @ Z10
+ PORT_DIPNAME( 0x02, 0x02, "Character Set" )
+ PORT_DIPSETTING( 0x02, "Swedish" )
+ PORT_DIPSETTING( 0x00, "US ASCII" )
+ PORT_DIPNAME( 0x04, 0x04, "External Encoding PROM" ) // @ Z14
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x18, 0x18, "Keyboard Language" ) PORT_CONDITION("DSW", 0x04, EQUALS, 0x00)
+ PORT_DIPSETTING( 0x00, "Danish" )
+ PORT_DIPSETTING( 0x10, DEF_STR( French ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( German ) )
+ PORT_DIPSETTING( 0x18, DEF_STR( Spanish ) )
+ PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("SW1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_NAME("Keyboard Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, abc77_device, keyboard_reset, 0)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor abc55_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( abc55 );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( abc77 )
+//-------------------------------------------------
+
+INPUT_PORTS_START( abc77 )
+ PORT_INCLUDE( abc55 )
+
+ PORT_MODIFY("X9")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad +") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad -") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad RETURN") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
+
+ PORT_MODIFY("X10")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor abc77_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( abc77 );
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// serial_output -
+//-------------------------------------------------
+
+inline void abc77_device::serial_output(int state)
+{
+ if (m_txd != state)
+ {
+ m_txd = state;
+
+ m_slot->write_rx(m_txd);
+ }
+}
+
+
+//-------------------------------------------------
+// serial_clock -
+//-------------------------------------------------
+
+inline void abc77_device::serial_clock()
+{
+ m_clock = !m_clock;
+
+ m_slot->trxc_w(!m_clock);
+}
+
+
+//-------------------------------------------------
+// keydown -
+//-------------------------------------------------
+
+inline void abc77_device::key_down(int state)
+{
+ if (m_keydown != state)
+ {
+ m_slot->keydown_w(state);
+ m_keydown = state;
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// abc77_device - constructor
+//-------------------------------------------------
+
+abc77_device::abc77_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ABC77, "Luxor ABC 77", tag, owner, clock, "abc77", __FILE__),
+ abc_keyboard_interface(mconfig, *this),
+ m_maincpu(*this, I8035_TAG),
+ m_discrete(*this, DISCRETE_TAG),
+ m_x0(*this, "X0"),
+ m_x1(*this, "X1"),
+ m_x2(*this, "X2"),
+ m_x3(*this, "X3"),
+ m_x4(*this, "X4"),
+ m_x5(*this, "X5"),
+ m_x6(*this, "X6"),
+ m_x7(*this, "X7"),
+ m_x8(*this, "X8"),
+ m_x9(*this, "X9"),
+ m_x10(*this, "X10"),
+ m_x11(*this, "X11"),
+ m_dsw(*this, "DSW"),
+ m_txd(1),
+ m_keydown(1),
+ m_clock(0),
+ m_stb(1)
+{
+}
+
+abc77_device::abc77_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ abc_keyboard_interface(mconfig, *this),
+ m_maincpu(*this, I8035_TAG),
+ m_discrete(*this, DISCRETE_TAG),
+ m_x0(*this, "X0"),
+ m_x1(*this, "X1"),
+ m_x2(*this, "X2"),
+ m_x3(*this, "X3"),
+ m_x4(*this, "X4"),
+ m_x5(*this, "X5"),
+ m_x6(*this, "X6"),
+ m_x7(*this, "X7"),
+ m_x8(*this, "X8"),
+ m_x9(*this, "X9"),
+ m_x10(*this, "X10"),
+ m_x11(*this, "X11"),
+ m_dsw(*this, "DSW"),
+ m_txd(1),
+ m_keydown(1),
+ m_clock(0),
+ m_stb(1)
+{
+}
+
+abc55_device::abc55_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : abc77_device(mconfig, ABC55, "Luxor ABC 55", tag, owner, clock, "abc55", __FILE__) { }
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void abc77_device::device_start()
+{
+ // allocate timers
+ m_serial_timer = timer_alloc(TIMER_SERIAL);
+ m_serial_timer->adjust(attotime::from_hz(19200), 0, attotime::from_hz(19200)); // ALE/32
+
+ m_reset_timer = timer_alloc(TIMER_RESET);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void abc77_device::device_reset()
+{
+ int t = 1.1 * RES_K(100) * CAP_N(100) * 1000; // t = 1.1 * R1 * C1
+ int ea = BIT(m_dsw->read(), 7);
+
+ // trigger reset
+ m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_reset_timer->adjust(attotime::from_msec(t));
+
+ m_maincpu->set_input_line(MCS48_INPUT_EA, ea ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void abc77_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_SERIAL:
+ serial_clock();
+ break;
+
+ case TIMER_RESET:
+ m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// txd_w -
+//-------------------------------------------------
+
+void abc77_device::txd_w(int state)
+{
+ m_maincpu->set_input_line(MCS48_INPUT_IRQ, state ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
+//-------------------------------------------------
+// p1_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc77_device::p1_r )
+{
+ /*
+
+ bit description
+
+ P10 Z17 Y0
+ P11 Z17 Y1
+ P12 Z17 Y2
+ P13 Z17 Y3
+ P14 Z17 Y4
+ P15 Z17 Y5
+ P16 Z17 Y6
+ P17 Z17 Y7
+
+ */
+
+ UINT8 data = 0xff;
+
+ if (m_stb)
+ {
+ switch (m_keylatch)
+ {
+ case 0: data = m_x0->read(); break;
+ case 1: data = m_x1->read(); break;
+ case 2: data = m_x2->read(); break;
+ case 3: data = m_x3->read(); break;
+ case 4: data = m_x4->read(); break;
+ case 5: data = m_x5->read(); break;
+ case 6: data = m_x6->read(); break;
+ case 7: data = m_x7->read(); break;
+ case 8: data = m_x8->read(); break;
+ case 9: data = m_x9->read(); break;
+ case 10: data = m_x10->read(); break;
+ case 11: data = m_x11->read(); break;
+ }
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// p2_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc77_device::p2_w )
+{
+ /*
+
+ bit description
+
+ P20 Z2 A0
+ P21 Z2 A1
+ P22 Z2 A2
+ P23 Z2 A3
+ P24 NE556 2,6
+ P25 TxD
+ P26 _KEYDOWN
+ P27 Z17 HYS
+
+ */
+
+ if (!m_stb)
+ {
+ m_keylatch = data & 0x0f;
+
+ if (m_keylatch == 1)
+ {
+ machine().watchdog_reset();
+ }
+ }
+
+ // beep
+ discrete_sound_w(m_discrete, space, NODE_01, BIT(data, 4));
+
+ // transmit data
+ serial_output(BIT(data, 5));
+
+ // key down
+ key_down(BIT(data, 6));
+
+ // hysteresis
+ m_hys = BIT(data, 7);
+}
+
+
+//-------------------------------------------------
+// t1_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc77_device::t1_r )
+{
+ return m_clock;
+}
+
+
+//-------------------------------------------------
+// prog_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc77_device::prog_w )
+{
+ m_stb = BIT(data, 0);
+}
+
+
+//-------------------------------------------------
+// j3_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc77_device::j3_w )
+{
+ m_j3 = data;
+}
diff --git a/src/emu/bus/abckb/abc77.h b/src/emu/bus/abckb/abc77.h
new file mode 100644
index 00000000000..71fc368fd84
--- /dev/null
+++ b/src/emu/bus/abckb/abc77.h
@@ -0,0 +1,119 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor ABC-55/77 keyboard emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __ABC77__
+#define __ABC77__
+
+#include "emu.h"
+#include "cpu/mcs48/mcs48.h"
+#include "abckb.h"
+#include "sound/discrete.h"
+#include "sound/speaker.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> abc77_device
+
+class abc77_device : public device_t,
+ public abc_keyboard_interface
+{
+public:
+ // construction/destruction
+ abc77_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ abc77_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual ioport_constructor device_input_ports() const;
+
+ // abc_keyboard_interface overrides
+ virtual void txd_w(int state);
+
+ DECLARE_INPUT_CHANGED_MEMBER( keyboard_reset );
+
+ DECLARE_READ8_MEMBER( p1_r );
+ DECLARE_WRITE8_MEMBER( p2_w );
+ DECLARE_READ8_MEMBER( t1_r );
+ DECLARE_WRITE8_MEMBER( prog_w );
+ DECLARE_WRITE8_MEMBER( j3_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ enum
+ {
+ TIMER_SERIAL,
+ TIMER_RESET
+ };
+
+ inline void serial_output(int state);
+ inline void serial_clock();
+ inline void key_down(int state);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<discrete_sound_device> m_discrete;
+ required_ioport m_x0;
+ required_ioport m_x1;
+ required_ioport m_x2;
+ required_ioport m_x3;
+ required_ioport m_x4;
+ required_ioport m_x5;
+ required_ioport m_x6;
+ required_ioport m_x7;
+ required_ioport m_x8;
+ required_ioport m_x9;
+ required_ioport m_x10;
+ required_ioport m_x11;
+ required_ioport m_dsw;
+
+ int m_txd; // transmit data
+ int m_keylatch; // keyboard row latch
+ int m_keydown; // key down
+ int m_clock; // transmit clock
+ int m_hys; // hysteresis
+ int m_reset; // reset
+ int m_stb; // strobe
+ UINT8 m_j3;
+
+ // timers
+ emu_timer *m_serial_timer;
+ emu_timer *m_reset_timer;
+};
+
+
+class abc55_device : public abc77_device
+{
+public:
+ // construction/destruction
+ abc55_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const;
+};
+
+
+// device type definition
+extern const device_type ABC77;
+extern const device_type ABC55;
+
+
+
+#endif
diff --git a/src/emu/bus/abckb/abc800kb.c b/src/emu/bus/abckb/abc800kb.c
new file mode 100644
index 00000000000..55a18604f86
--- /dev/null
+++ b/src/emu/bus/abckb/abc800kb.c
@@ -0,0 +1,510 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor ABC-800 keyboard emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+PCB Layout
+----------
+
+KTC A65-02201-201K
+
+ |---------------|
+|---| CN1 |---------------------------------------------------|
+| |
+| LS193 LS374 8048 22-008-03 |
+| LS13 LS193 22-050-3B 5.9904MHz |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+|-----------------------------------------------------------------------|
+
+Notes:
+ All IC's shown.
+
+ 8048 - National Semiconductor INS8048 MCU "8048-132"
+ 22-008-03 - Exar Semiconductor XR22-008-03 keyboard matrix capacitive readout latch
+ 22-050-3B - Exar Semiconductor XR22-050-3B keyboard matrix row driver with 4 to 12 decoder/demultiplexer
+ CN1 - keyboard data connector
+
+
+XR22-008-03 Pinout
+------------------
+ _____ _____
+ D0 1 |* \_/ | 20 Vcc
+ D1 2 | | 19 _CLR
+ D2 3 | | 18 Q0
+ D3 4 | | 17 Q1
+ HYS 5 | 22-008-03 | 16 Q2
+ D4 6 | | 15 Q3
+ D5 7 | | 14 Q4
+ D6 8 | | 13 Q5
+ D7 9 | | 12 Q6
+ GND 10 |_____________| 11 Q7
+
+
+XR22-050-3B Pinout
+------------------
+ _____ _____
+ Y8 1 |* \_/ | 20 Vcc
+ Y9 2 | | 19 Y7
+ Y10 3 | | 18 Y6
+ Y11 4 | | 17 Y5
+ _STB 5 | 22-050-3B | 16 Y4
+ A0 6 | | 15 Y3
+ A1 7 | | 14 Y2
+ A2 8 | | 13 Y1
+ A3 9 | | 12 Y0
+ GND 10 |_____________| 11 OE?
+
+*/
+
+#include "abc800kb.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define I8048_TAG "i8048"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type ABC800_KEYBOARD = &device_creator<abc800_keyboard_device>;
+
+
+//-------------------------------------------------
+// ROM( abc800_keyboard )
+//-------------------------------------------------
+
+ROM_START( abc800_keyboard )
+ ROM_REGION( 0x400, I8048_TAG, 0 )
+ ROM_LOAD( "8048-132.z9", 0x0000, 0x0400, CRC(05c4dce5) SHA1(1824c5d304bbd09f97056cfa408e1b18b5219ba2) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *abc800_keyboard_device::device_rom_region() const
+{
+ return ROM_NAME( abc800_keyboard );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( abc800_keyboard_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( abc800_keyboard_io, AS_IO, 8, abc800_keyboard_device )
+ AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(kb_p1_r, kb_p1_w)
+ AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_WRITE(kb_p2_w)
+ AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(kb_t1_r)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( abc800_keyboard )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( abc800_keyboard )
+ MCFG_CPU_ADD(I8048_TAG, I8048, XTAL_5_9904MHz)
+ MCFG_CPU_IO_MAP(abc800_keyboard_io)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor abc800_keyboard_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( abc800_keyboard );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( abc800_keyboard )
+//-------------------------------------------------
+
+INPUT_PORTS_START( abc800_keyboard )
+ PORT_START("X0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Left SHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // 80
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) // 81
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // 82
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 83
+
+ PORT_START("X1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad -") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad RETURN") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // 84
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 85
+
+ PORT_START("X2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // 18
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 86
+
+ PORT_START("X3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 \xC2\xA4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x00A4)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+
+ PORT_START("X4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
+
+ PORT_START("X5")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+
+ PORT_START("X6")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+
+ PORT_START("X7")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+
+ PORT_START("X8")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u_UMLAUT " " U_UMLAUT) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00FC) PORT_CHAR(0x00DC)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\'') PORT_CHAR('*')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(TAB))
+
+ PORT_START("X9")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(e_ACUTE " " E_ACUTE) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00E9) PORT_CHAR(0x00C9)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(a_RING " " A_RING) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00E5) PORT_CHAR(0x00C5)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(a_UMLAUT " " A_UMLAUT) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00E4) PORT_CHAR(0x00C4)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Right SHIFT") PORT_CODE(KEYCODE_RSHIFT)
+
+ PORT_START("X10")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(o_UMLAUT " " O_UMLAUT) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00F6) PORT_CHAR(0x00D6)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // 87
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) // 88
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // 89
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 8a
+
+ PORT_START("X11")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) // 03
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) // 23
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) // 96
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) // 8b
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // 8c
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) // 8d
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // 8e
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 8f
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor abc800_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( abc800_keyboard );
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// serial_output -
+//-------------------------------------------------
+
+inline void abc800_keyboard_device::serial_output(int state)
+{
+ if (m_txd != state)
+ {
+ m_txd = state;
+
+ m_slot->write_rx(m_txd);
+ }
+}
+
+
+//-------------------------------------------------
+// serial_clock -
+//-------------------------------------------------
+
+inline void abc800_keyboard_device::serial_clock()
+{
+ m_clk = !m_clk;
+
+ m_slot->trxc_w(!m_clk);
+}
+
+
+//-------------------------------------------------
+// keydown -
+//-------------------------------------------------
+
+inline void abc800_keyboard_device::key_down(int state)
+{
+ if (m_keydown != state)
+ {
+ m_keydown = state;
+
+ m_slot->keydown_w(state);
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// abc800_keyboard_device - constructor
+//-------------------------------------------------
+
+abc800_keyboard_device::abc800_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ABC800_KEYBOARD, "ABC-800 Keyboard", tag, owner, clock, "abc800kb", __FILE__),
+ abc_keyboard_interface(mconfig, *this),
+ m_maincpu(*this, I8048_TAG),
+ m_x0(*this, "X0"),
+ m_x1(*this, "X1"),
+ m_x2(*this, "X2"),
+ m_x3(*this, "X3"),
+ m_x4(*this, "X4"),
+ m_x5(*this, "X5"),
+ m_x6(*this, "X6"),
+ m_x7(*this, "X7"),
+ m_x8(*this, "X8"),
+ m_x9(*this, "X9"),
+ m_x10(*this, "X10"),
+ m_x11(*this, "X11"),
+ m_row(0),
+ m_txd(1),
+ m_clk(0),
+ m_stb(1),
+ m_keydown(1)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void abc800_keyboard_device::device_start()
+{
+ // allocate timers
+ m_serial_timer = timer_alloc();
+ m_serial_timer->adjust(attotime::from_hz(XTAL_5_9904MHz/(3*5)/20), 0, attotime::from_hz(XTAL_5_9904MHz/(3*5)/20)); // ???
+
+ // state saving
+ save_item(NAME(m_row));
+ save_item(NAME(m_clk));
+ save_item(NAME(m_txd));
+ save_item(NAME(m_stb));
+ save_item(NAME(m_keydown));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void abc800_keyboard_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void abc800_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ serial_clock();
+}
+
+
+//-------------------------------------------------
+// txd_w -
+//-------------------------------------------------
+
+void abc800_keyboard_device::txd_w(int state)
+{
+ m_maincpu->set_input_line(MCS48_INPUT_IRQ, state ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
+//-------------------------------------------------
+// kb_p1_r - keyboard column data read
+//-------------------------------------------------
+
+READ8_MEMBER( abc800_keyboard_device::kb_p1_r )
+{
+ UINT8 data = 0xff;
+
+ if (m_stb)
+ {
+ switch (m_row)
+ {
+ case 0: data = m_x0->read(); break;
+ case 1: data = m_x1->read(); break;
+ case 2: data = m_x2->read(); break;
+ case 3: data = m_x3->read(); break;
+ case 4: data = m_x4->read(); break;
+ case 5: data = m_x5->read(); break;
+ case 6: data = m_x6->read(); break;
+ case 7: data = m_x7->read(); break;
+ case 8: data = m_x8->read(); break;
+ case 9: data = m_x9->read(); break;
+ case 10: data = m_x10->read(); break;
+ case 11: data = m_x11->read(); break;
+ }
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// kb_p1_w - keyboard row write
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc800_keyboard_device::kb_p1_w )
+{
+ /*
+
+ bit description
+
+ 0 A0
+ 1 A1
+ 2 A2
+ 3 A3
+ 4 ?
+ 5 ?
+ 6
+ 7
+
+ */
+
+ // keyboard row
+ if (!m_stb)
+ {
+ m_row = data & 0x0f;
+ }
+}
+
+
+//-------------------------------------------------
+// kb_p2_w - keyboard control write
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc800_keyboard_device::kb_p2_w )
+{
+ /*
+
+ bit description
+
+ 0
+ 1
+ 2
+ 3
+ 4 TxD
+ 5 ?
+ 6 22-008-03 CLR, 22-050-3B STB
+ 7 22-008-03 HYS
+
+ */
+
+ // TxD
+ serial_output(!BIT(data, 4));
+
+ // keydown
+ key_down(!BIT(data, 5));
+
+ // strobe
+ m_stb = BIT(data, 6);
+}
+
+
+//-------------------------------------------------
+// kb_t1_r - keyboard T1 timer read
+//-------------------------------------------------
+
+READ8_MEMBER( abc800_keyboard_device::kb_t1_r )
+{
+ return m_clk;
+}
diff --git a/src/emu/bus/abckb/abc800kb.h b/src/emu/bus/abckb/abc800kb.h
new file mode 100644
index 00000000000..6428f332f6e
--- /dev/null
+++ b/src/emu/bus/abckb/abc800kb.h
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor ABC-800 keyboard emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __ABC800_KEYBOARD__
+#define __ABC800_KEYBOARD__
+
+
+#include "emu.h"
+#include "cpu/mcs48/mcs48.h"
+#include "abckb.h"
+#include "sound/discrete.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> abc800_keyboard_device
+
+class abc800_keyboard_device : public device_t,
+ public abc_keyboard_interface
+{
+public:
+ // construction/destruction
+ abc800_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual ioport_constructor device_input_ports() const;
+
+ // abc_keyboard_interface overrides
+ virtual void txd_w(int state);
+
+ // not really public
+ DECLARE_READ8_MEMBER( kb_p1_r );
+ DECLARE_WRITE8_MEMBER( kb_p1_w );
+ DECLARE_WRITE8_MEMBER( kb_p2_w );
+ DECLARE_READ8_MEMBER( kb_t1_r );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ inline void serial_output(int state);
+ inline void serial_clock();
+ inline void key_down(int state);
+
+ required_device<cpu_device> m_maincpu;
+ required_ioport m_x0;
+ required_ioport m_x1;
+ required_ioport m_x2;
+ required_ioport m_x3;
+ required_ioport m_x4;
+ required_ioport m_x5;
+ required_ioport m_x6;
+ required_ioport m_x7;
+ required_ioport m_x8;
+ required_ioport m_x9;
+ required_ioport m_x10;
+ required_ioport m_x11;
+
+ int m_row;
+ int m_txd;
+ int m_clk;
+ int m_stb;
+ int m_keydown;
+
+ // timers
+ emu_timer *m_serial_timer;
+};
+
+
+// device type definition
+extern const device_type ABC800_KEYBOARD;
+
+
+
+#endif
diff --git a/src/emu/bus/abckb/abc99.c b/src/emu/bus/abckb/abc99.c
new file mode 100644
index 00000000000..a4272a52213
--- /dev/null
+++ b/src/emu/bus/abckb/abc99.c
@@ -0,0 +1,783 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor ABC-99 keyboard and mouse emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+/*
+
+Keyboard PCB Layout
+-------------------
+
+|-----------------------------------------------------------------------|
+| CN1 CN2 CPU1 ROM1 SW1 |
+| |
+| 6MHz CPU0 ROM0 GI |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+| |
+|-----------------------------------------------------------------------|
+
+Notes:
+ Relevant IC's shown.
+
+ CPU0 - STMicro ET8035N-6 8035 CPU
+ CPU1 - STMicro ET8035N-6 8035 CPU
+ ROM0 - Texas Instruments TMS2516JL-16 2Kx8 ROM "107268-16"
+ ROM1 - STMicro ET2716Q-1 2Kx8 ROM "107268-17"
+ GI - General Instruments 321239007 keyboard chip "4=7"
+ CN1 - DB15 connector, Luxor ABC R8 (3 button mouse)
+ CN2 - 12 pin PCB header, keyboard data cable
+ SW1 - reset switch?
+
+*/
+
+/*
+
+ TODO:
+
+ - verify cursor keys
+ - language DIP
+ - mouse
+ - investigate unknown ROMs
+ - MCS-48 PC:01DC - Unimplemented opcode = 75
+ - 75 = ENT0 CLK : enable CLK (unscaled_clock/3) output on T0
+ - halt Z2 when Z5 is reset, resume Z2 when Z5 executes ENT0 CLK instruction
+
+*/
+
+#include "abc99.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define I8035_Z2_TAG "z2"
+#define I8035_Z5_TAG "z5"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type ABC99 = &device_creator<abc99_device>;
+
+
+//-------------------------------------------------
+// ROM( abc99 )
+//-------------------------------------------------
+
+ROM_START( abc99 )
+ ROM_REGION( 0x800, I8035_Z2_TAG, 0 )
+ ROM_LOAD( "107268-17.z3", 0x000, 0x800, CRC(2f60cc35) SHA1(ebc6af9cd0a49a0d01698589370e628eebb6221c) )
+
+ ROM_REGION( 0x800, I8035_Z5_TAG, 0 )
+ ROM_LOAD( "107268-16.z6", 0x000, 0x800, CRC(785ec0c6) SHA1(0b261beae20dbc06fdfccc50b19ea48b5b6e22eb) )
+
+ ROM_REGION( 0x1800, "unknown", 0)
+ ROM_LOAD( "106819-09.bin", 0x0000, 0x1000, CRC(ffe32a71) SHA1(fa2ce8e0216a433f9bbad0bdd6e3dc0b540f03b7) )
+ ROM_LOAD( "107268-64.bin", 0x1000, 0x0800, CRC(e33683ae) SHA1(0c1d9e320f82df05f4804992ef6f6f6cd20623f3) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *abc99_device::device_rom_region() const
+{
+ return ROM_NAME( abc99 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( abc99_z2_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( abc99_z2_mem, AS_PROGRAM, 8, abc99_device )
+ AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION(I8035_Z2_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( abc99_z2_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( abc99_z2_io, AS_IO, 8, abc99_device )
+ AM_RANGE(0x21, 0x21) AM_WRITE(z2_led_w)
+ AM_RANGE(0x30, 0x30) AM_READ_PORT("X0") AM_WRITENOP
+ AM_RANGE(0x31, 0x31) AM_READ_PORT("X1") AM_WRITENOP
+ AM_RANGE(0x32, 0x32) AM_READ_PORT("X2") AM_WRITENOP
+ AM_RANGE(0x33, 0x33) AM_READ_PORT("X3") AM_WRITENOP
+ AM_RANGE(0x34, 0x34) AM_READ_PORT("X4") AM_WRITENOP
+ AM_RANGE(0x35, 0x35) AM_READ_PORT("X5") AM_WRITENOP
+ AM_RANGE(0x36, 0x36) AM_READ_PORT("X6") AM_WRITENOP
+ AM_RANGE(0x37, 0x37) AM_READ_PORT("X7") AM_WRITENOP
+ AM_RANGE(0x38, 0x38) AM_READ_PORT("X8") AM_WRITENOP
+ AM_RANGE(0x39, 0x39) AM_READ_PORT("X9") AM_WRITENOP
+ AM_RANGE(0x3a, 0x3a) AM_READ_PORT("X10") AM_WRITENOP
+ AM_RANGE(0x3b, 0x3b) AM_READ_PORT("X11") AM_WRITENOP
+ AM_RANGE(0x3c, 0x3c) AM_READ_PORT("X12") AM_WRITENOP
+ AM_RANGE(0x3d, 0x3d) AM_READ_PORT("X13") AM_WRITENOP
+ AM_RANGE(0x3e, 0x3e) AM_READ_PORT("X14") AM_WRITENOP
+ AM_RANGE(0x3f, 0x3f) AM_READ_PORT("X15") AM_WRITENOP
+ AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_WRITE(z2_p1_w)
+ AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READ(z2_p2_r)
+ AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(z2_t0_r)
+ AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(z2_t1_r)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( abc99_z5_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( abc99_z5_mem, AS_PROGRAM, 8, abc99_device )
+ AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION(I8035_Z5_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( abc99_z5_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( abc99_z5_io, AS_IO, 8, abc99_device )
+/* AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READ(z5_p1_r)
+ AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_WRITE(z5_p2_w)
+ AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_WRITENOP // Z2 CLK
+ AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(z5_t1_r)*/
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( abc99 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( abc99 )
+ // keyboard CPU
+ MCFG_CPU_ADD(I8035_Z2_TAG, I8035, XTAL_6MHz/3) // from Z5 T0 output
+ MCFG_CPU_PROGRAM_MAP(abc99_z2_mem)
+ MCFG_CPU_IO_MAP(abc99_z2_io)
+
+ // mouse CPU
+ MCFG_CPU_ADD(I8035_Z5_TAG, I8035, XTAL_6MHz)
+ MCFG_CPU_PROGRAM_MAP(abc99_z5_mem)
+ MCFG_CPU_IO_MAP(abc99_z5_io)
+ MCFG_DEVICE_DISABLE() // HACK fix for broken serial I/O
+
+ // sound hardware
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor abc99_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( abc99 );
+}
+
+
+//-------------------------------------------------
+// INPUT_CHANGED_MEMBER( keyboard_reset )
+//-------------------------------------------------
+
+INPUT_CHANGED_MEMBER( abc99_device::keyboard_reset )
+{
+ if (newval)
+ {
+ m_mousecpu->reset();
+ }
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( abc99 )
+//-------------------------------------------------
+
+INPUT_PORTS_START( abc99 )
+ PORT_START("X0")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF13") PORT_CODE(KEYCODE_PRTSCR)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT"|") PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("LF") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(RCONTROL))
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("X1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("ALT") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad CE") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad RETURN") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("X2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PRINT") PORT_CODE(KEYCODE_PGUP)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Left SHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("X3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("HELP") PORT_CODE(KEYCODE_HOME)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("X4")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF15") PORT_CODE(KEYCODE_PAUSE)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) // cursor B
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) // cursor D
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("X5")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF12") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("BS") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00FC) PORT_CHAR(0x00DC)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Right SHIFT") PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+
+ PORT_START("X6")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF14") PORT_CODE(KEYCODE_SCRLOCK)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("INS") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) // cursor A
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) // cursor C
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
+
+ PORT_START("X7")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF11") PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00E9) PORT_CHAR(0x00C9)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00E5) PORT_CHAR(0x00C5)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00E4) PORT_CHAR(0x00C4)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+
+ PORT_START("X8")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("STOP") PORT_CODE(KEYCODE_END)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("|"UTF8_LEFT) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
+
+ PORT_START("X9")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00F6) PORT_CHAR(0x00D6)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+
+ PORT_START("X10")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF10") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC)
+
+ PORT_START("X11")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF9") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+
+ PORT_START("X12")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+
+ PORT_START("X13")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("4 \xC2\xA4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x00A4)
+
+ PORT_START("X14")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+
+ PORT_START("X15")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
+
+ PORT_START("Z14")
+ PORT_DIPNAME( 0x07, 0x00, DEF_STR( Language ) ) PORT_DIPLOCATION("Z14:1,2,3")
+ PORT_DIPSETTING( 0x00, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x01, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x03, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x05, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x06, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x07, DEF_STR( Unknown ) )
+ PORT_DIPNAME( 0x08, 0x08, "Keyboard Program" ) PORT_DIPLOCATION("Z14:4")
+ PORT_DIPSETTING( 0x00, "Internal (8048)" )
+ PORT_DIPSETTING( 0x08, "External PROM" )
+
+ PORT_START("MOUSEB")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_NAME("Left Mouse Button") PORT_CODE(MOUSECODE_BUTTON1)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_NAME("Middle Mouse Button") PORT_CODE(MOUSECODE_BUTTON3)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_NAME("Right Mouse Button") PORT_CODE(MOUSECODE_BUTTON2)
+
+ PORT_START("MOUSEX")
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
+
+ PORT_START("MOUSEY")
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
+
+ PORT_START("J4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_NAME("Keyboard Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, abc99_device, keyboard_reset, 0)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor abc99_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( abc99 );
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// serial_input -
+//-------------------------------------------------
+
+inline void abc99_device::serial_input()
+{
+ m_maincpu->set_input_line(MCS48_INPUT_IRQ, (m_si || m_si_en) ? CLEAR_LINE : ASSERT_LINE);
+ m_mousecpu->set_input_line(MCS48_INPUT_IRQ, m_si ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
+//-------------------------------------------------
+// serial_output -
+//-------------------------------------------------
+
+inline void abc99_device::serial_output(int state)
+{
+ if (m_txd != state)
+ {
+ m_txd = state;
+
+ m_slot->write_rx(m_txd);
+ }
+}
+
+
+//-------------------------------------------------
+// serial_clock -
+//-------------------------------------------------
+
+inline void abc99_device::serial_clock()
+{
+ m_slot->trxc_w(1);
+ m_slot->trxc_w(0);
+}
+
+
+//-------------------------------------------------
+// keydown -
+//-------------------------------------------------
+
+inline void abc99_device::key_down(int state)
+{
+ if (m_keydown != state)
+ {
+ m_slot->keydown_w(state);
+ m_keydown = state;
+ }
+}
+
+
+//-------------------------------------------------
+// scan_mouse -
+//-------------------------------------------------
+
+inline void abc99_device::scan_mouse()
+{
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// abc99_device - constructor
+//-------------------------------------------------
+
+abc99_device::abc99_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ABC99, "Luxor ABC 99", tag, owner, clock, "abc99", __FILE__),
+ abc_keyboard_interface(mconfig, *this),
+ m_maincpu(*this, I8035_Z2_TAG),
+ m_mousecpu(*this, I8035_Z5_TAG),
+ m_speaker(*this, "speaker"),
+ m_z14(*this, "Z14"),
+ m_mouseb(*this, "MOUSEB"),
+ m_si(1),
+ m_si_en(1),
+ m_so_z2(1),
+ m_so_z5(1),
+ m_keydown(0),
+ m_t1_z2(0),
+ m_t1_z5(0),
+ m_led_en(0),
+ m_reset(1),
+ m_txd(1)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void abc99_device::device_start()
+{
+ // allocate timers
+ m_serial_timer = timer_alloc(TIMER_SERIAL);
+ m_serial_timer->adjust(MCS48_ALE_CLOCK(XTAL_6MHz/3), 0, MCS48_ALE_CLOCK(XTAL_6MHz/3));
+
+ m_mouse_timer = timer_alloc(TIMER_MOUSE);
+
+ // state saving
+ save_item(NAME(m_si));
+ save_item(NAME(m_si_en));
+ save_item(NAME(m_so_z2));
+ save_item(NAME(m_so_z5));
+ save_item(NAME(m_keydown));
+ save_item(NAME(m_t1_z2));
+ save_item(NAME(m_t1_z5));
+ save_item(NAME(m_led_en));
+ save_item(NAME(m_reset));
+ save_item(NAME(m_txd));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void abc99_device::device_reset()
+{
+ // set EA lines
+ m_maincpu->set_input_line(MCS48_INPUT_EA, ASSERT_LINE);
+ m_mousecpu->set_input_line(MCS48_INPUT_EA, ASSERT_LINE);
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void abc99_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_SERIAL:
+ serial_clock();
+ break;
+
+ case TIMER_MOUSE:
+ scan_mouse();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// txd_w -
+//-------------------------------------------------
+
+void abc99_device::txd_w(int state)
+{
+ if (m_si != state)
+ {
+ m_si = state;
+ serial_input();
+ }
+}
+
+
+//-------------------------------------------------
+// z2_bus_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc99_device::z2_led_w )
+{
+ if (m_led_en) return;
+
+ output_set_led_value(LED_1, BIT(data, 0));
+ output_set_led_value(LED_2, BIT(data, 1));
+ output_set_led_value(LED_3, BIT(data, 2));
+ output_set_led_value(LED_4, BIT(data, 3));
+ output_set_led_value(LED_5, BIT(data, 4));
+ output_set_led_value(LED_6, BIT(data, 5));
+ output_set_led_value(LED_7, BIT(data, 6));
+ output_set_led_value(LED_8, BIT(data, 7));
+}
+
+
+//-------------------------------------------------
+// z2_p1_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc99_device::z2_p1_w )
+{
+ /*
+
+ bit description
+
+ P10 serial output
+ P11 KEY DOWN
+ P12 transmit -> Z5 T1
+ P13 INS led
+ P14 ALT led
+ P15 CAPS LOCK led
+ P16 speaker output
+ P17 Z8 enable
+
+ */
+
+ // serial output
+ m_so_z2 = BIT(data, 0);
+ serial_output(m_so_z2 && m_so_z5);
+
+ // key down
+ key_down(!BIT(data, 1));
+
+ // master T1
+ m_t1_z5 = BIT(data, 2);
+
+ // key LEDs
+ output_set_led_value(LED_INS, BIT(data, 3));
+ output_set_led_value(LED_ALT, BIT(data, 4));
+ output_set_led_value(LED_CAPS_LOCK, BIT(data, 5));
+
+ // speaker output
+ m_speaker->level_w(!BIT(data, 6));
+
+ // Z8 enable
+ m_led_en = BIT(data, 7);
+}
+
+
+//-------------------------------------------------
+// z2_p2_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc99_device::z2_p2_r )
+{
+ /*
+
+ bit description
+
+ P20
+ P21
+ P22
+ P23
+ P24
+ P25 DIP0
+ P26 DIP1
+ P27 DIP2
+
+ */
+
+ UINT8 data = m_z14->read() << 5;
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// z2_t0_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc99_device::z2_t0_r )
+{
+ return 1; // 0=mouse connected, 1=no mouse
+}
+
+
+//-------------------------------------------------
+// z2_t1_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc99_device::z2_t1_r )
+{
+ return m_t1_z2;
+}
+
+
+//-------------------------------------------------
+// z5_p1_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc99_device::z5_p1_r )
+{
+ /*
+
+ bit description
+
+ P10 XA
+ P11 XB
+ P12 YA
+ P13 YB
+ P14 LB
+ P15 MB
+ P16 RB
+ P17 input from host
+
+ */
+
+ UINT8 data = 0;
+
+ // mouse buttons
+ data |= (m_mouseb->read() & 0x07) << 4;
+
+ // serial input
+ data |= m_si << 7;
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// z5_p2_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc99_device::z5_p2_w )
+{
+ /*
+
+ bit description
+
+ P20
+ P21
+ P22
+ P23
+ P24 Z2 serial input enable
+ P25 Z2 RESET
+ P26 serial output
+ P27 Z2 T1
+
+ */
+
+ // serial input enable
+ int si_en = BIT(data, 4);
+
+ if (m_si_en != si_en)
+ {
+ m_si_en = si_en;
+ serial_input();
+ }
+
+ // Z2 reset
+ int reset = BIT(data, 5);
+
+ if (!m_reset && reset)
+ {
+ m_maincpu->reset();
+ }
+
+ m_reset = reset;
+
+ // serial output
+ m_so_z5 = BIT(data, 6);
+ serial_output(m_so_z2 && m_so_z5);
+
+ // keyboard CPU T1
+ m_t1_z2 = BIT(data, 7);
+}
+
+
+//-------------------------------------------------
+// z5_t1_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc99_device::z5_t1_r )
+{
+ return m_t1_z5;
+}
diff --git a/src/emu/bus/abckb/abc99.h b/src/emu/bus/abckb/abc99.h
new file mode 100644
index 00000000000..e7b01331517
--- /dev/null
+++ b/src/emu/bus/abckb/abc99.h
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor ABC-99 keyboard and mouse emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __ABC99__
+#define __ABC99__
+
+#include "emu.h"
+#include "cpu/mcs48/mcs48.h"
+#include "abckb.h"
+#include "sound/speaker.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> abc99_device
+
+class abc99_device : public device_t,
+ public abc_keyboard_interface
+{
+public:
+ // construction/destruction
+ abc99_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual ioport_constructor device_input_ports() const;
+
+ // abc_keyboard_interface overrides
+ virtual void txd_w(int state);
+
+ DECLARE_INPUT_CHANGED_MEMBER( keyboard_reset );
+
+ DECLARE_WRITE8_MEMBER( z2_led_w );
+ DECLARE_WRITE8_MEMBER( z2_p1_w );
+ DECLARE_READ8_MEMBER( z2_p2_r );
+ DECLARE_READ8_MEMBER( z2_t0_r );
+ DECLARE_READ8_MEMBER( z2_t1_r );
+ DECLARE_READ8_MEMBER( z5_p1_r );
+ DECLARE_WRITE8_MEMBER( z5_p2_w );
+ DECLARE_READ8_MEMBER( z5_t1_r );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ enum
+ {
+ TIMER_SERIAL,
+ TIMER_MOUSE
+ };
+
+ enum
+ {
+ LED_1 = 0,
+ LED_2,
+ LED_3,
+ LED_4,
+ LED_5,
+ LED_6,
+ LED_7,
+ LED_8,
+ LED_INS,
+ LED_ALT,
+ LED_CAPS_LOCK
+ };
+
+ inline void serial_input();
+ inline void serial_output(int state);
+ inline void serial_clock();
+ inline void key_down(int state);
+ inline void scan_mouse();
+
+ emu_timer *m_serial_timer;
+ emu_timer *m_mouse_timer;
+
+ required_device<cpu_device> m_maincpu;
+ required_device<cpu_device> m_mousecpu;
+ required_device<speaker_sound_device> m_speaker;
+ required_ioport m_z14;
+ required_ioport m_mouseb;
+
+ int m_si;
+ int m_si_en;
+ int m_so_z2;
+ int m_so_z5;
+ int m_keydown;
+ int m_t1_z2;
+ int m_t1_z5;
+ int m_led_en;
+ int m_reset;
+ int m_txd;
+};
+
+
+// device type definition
+extern const device_type ABC99;
+
+
+
+#endif
diff --git a/src/emu/bus/abckb/abckb.c b/src/emu/bus/abckb/abckb.c
new file mode 100644
index 00000000000..6cdf605aaf1
--- /dev/null
+++ b/src/emu/bus/abckb/abckb.c
@@ -0,0 +1,139 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor ABC 800/802/806/1600 keyboard port emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "abckb.h"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+// device type definition
+const device_type ABC_KEYBOARD_PORT = &device_creator<abc_keyboard_port_device>;
+
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// abc_keyboard_interface - constructor
+//-------------------------------------------------
+
+abc_keyboard_interface::abc_keyboard_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig,device)
+{
+ m_slot = dynamic_cast<abc_keyboard_port_device *>(device.owner());
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// abc_keyboard_port_device - constructor
+//-------------------------------------------------
+
+abc_keyboard_port_device::abc_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, ABC_KEYBOARD_PORT, "Luxor ABC keyboard port", tag, owner, clock, "abc_keyboard_port", __FILE__),
+ device_slot_interface(mconfig, *this),
+ m_out_rx_handler(*this),
+ m_out_trxc_handler(*this),
+ m_out_keydown_handler(*this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void abc_keyboard_port_device::device_start()
+{
+ m_card = dynamic_cast<abc_keyboard_interface *>(get_card_device());
+
+ // resolve callbacks
+ m_out_rx_handler.resolve_safe();
+ m_out_trxc_handler.resolve_safe();
+ m_out_keydown_handler.resolve_safe();
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void abc_keyboard_port_device::device_reset()
+{
+ if (m_card != NULL)
+ get_card_device()->reset();
+}
+
+
+//-------------------------------------------------
+// write_rx -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( abc_keyboard_port_device::write_rx )
+{
+ m_out_rx_handler(state);
+}
+
+
+//-------------------------------------------------
+// txd_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( abc_keyboard_port_device::txd_w )
+{
+ if (m_card != NULL)
+ m_card->txd_w(state);
+}
+
+
+//-------------------------------------------------
+// trxc_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( abc_keyboard_port_device::trxc_w )
+{
+ m_out_trxc_handler(state);
+}
+
+
+//-------------------------------------------------
+// keydown_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( abc_keyboard_port_device::keydown_w )
+{
+ m_out_keydown_handler(state);
+}
+
+
+
+//**************************************************************************
+// SLOT INTERFACE
+//**************************************************************************
+
+#include "abc800kb.h"
+#include "abc77.h"
+#include "abc99.h"
+
+SLOT_INTERFACE_START( abc_keyboard_devices )
+ SLOT_INTERFACE("abc800", ABC800_KEYBOARD)
+ SLOT_INTERFACE("abc55", ABC55)
+ SLOT_INTERFACE("abc77", ABC77)
+ SLOT_INTERFACE("abc99", ABC99)
+SLOT_INTERFACE_END
diff --git a/src/emu/bus/abckb/abckb.h b/src/emu/bus/abckb/abckb.h
new file mode 100644
index 00000000000..f9c050b11ed
--- /dev/null
+++ b/src/emu/bus/abckb/abckb.h
@@ -0,0 +1,100 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor ABC 800/802/806/1600 keyboard port emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __ABC_KEYBOARD_PORT__
+#define __ABC_KEYBOARD_PORT__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_ABC_KEYBOARD_PORT_ADD(_tag, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, ABC_KEYBOARD_PORT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(abc_keyboard_devices, _def_slot, false)
+
+#define MCFG_ABC_KEYBOARD_OUT_RX_HANDLER(_devcb) \
+ devcb = &abc_keyboard_port_device::set_out_rx_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_ABC_KEYBOARD_OUT_TRXC_HANDLER(_devcb) \
+ devcb = &abc_keyboard_port_device::set_out_trxc_handler(*device, DEVCB2_##_devcb);
+
+#define MCFG_ABC_KEYBOARD_OUT_KEYDOWN_HANDLER(_devcb) \
+ devcb = &abc_keyboard_port_device::set_out_keydown_handler(*device, DEVCB2_##_devcb);
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class abc_keyboard_interface;
+
+class abc_keyboard_port_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ abc_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ template<class _Object> static devcb2_base &set_out_rx_handler(device_t &device, _Object object) { return downcast<abc_keyboard_port_device &>(device).m_out_rx_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_out_trxc_handler(device_t &device, _Object object) { return downcast<abc_keyboard_port_device &>(device).m_out_trxc_handler.set_callback(object); }
+ template<class _Object> static devcb2_base &set_out_keydown_handler(device_t &device, _Object object) { return downcast<abc_keyboard_port_device &>(device).m_out_keydown_handler.set_callback(object); }
+
+ // computer interface
+ DECLARE_WRITE_LINE_MEMBER( txd_w );
+
+ // peripheral interface
+ DECLARE_WRITE_LINE_MEMBER( write_rx );
+ DECLARE_WRITE_LINE_MEMBER( trxc_w );
+ DECLARE_WRITE_LINE_MEMBER( keydown_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ devcb2_write_line m_out_rx_handler;
+ devcb2_write_line m_out_trxc_handler;
+ devcb2_write_line m_out_keydown_handler;
+
+ abc_keyboard_interface *m_card;
+};
+
+
+class abc_keyboard_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ abc_keyboard_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void txd_w(int state) { };
+
+protected:
+ abc_keyboard_port_device *m_slot;
+};
+
+
+// device type definition
+extern const device_type ABC_KEYBOARD_PORT;
+
+
+// supported devices
+SLOT_INTERFACE_EXTERN( abc_keyboard_devices );
+
+
+
+#endif
diff --git a/src/emu/bus/bml3/bml3bus.c b/src/emu/bus/bml3/bml3bus.c
new file mode 100644
index 00000000000..d864f2e4f1f
--- /dev/null
+++ b/src/emu/bus/bml3/bml3bus.c
@@ -0,0 +1,257 @@
+/***************************************************************************
+
+ bml3bus.c - Hitachi MB-6890 slot bus and card emulation
+
+ Adapted from a2bus by Jonathan Edwards
+
+ Pinout (/ indicates an inverted signal, ie, one that would have a bar over it
+ on a schematic diagram)
+
+ out <-> CPU CPU <-> out
+ ---------- -----------
+ +5V <-- 1 2 <-> GND
+ D0 <-> 3 4 <-> D1
+ D2 <-> 5 6 <-> D3
+ D4 <-> 7 8 <-> D5
+ D6 <-> 9 10 <-> D7
+ A0 <-> 11 12 <-> A1
+ A2 <-> 13 14 <-> A3
+ A4 <-> 15 16 <-> A5
+ A6 <-> 17 18 <-> A7
+ A8 <-> 19 20 <-> A9
+ A10 <-> 21 22 <-> A11
+ A12 <-> 23 24 <-> A13
+ A14 <-> 25 26 <-> A15
+ BA <-- 27 28 --> BS
+ /ROM-KIL --> 29 30 --> EXROM-KIL
+ R/W IN --> 31 32 --> /EX-I/O
+ R/W OUT <-- 33 34 --> VMA OUT
+ E <-- 35 36 --> Q
+ /RES <-- 37 38 <-- /NMI
+ /IRQ --> 39 40 <-- /FIRQ
+ /HALT --> 41 42 <-- /VMA CTRL
+ /DMA --> 43 44 --> /BANK-SW
+ HALT ACK <-- 45 46 <-- SOUND IN
+ 16MCK <-- 47 48 <-> GND
+ 2MCK <-- 49 50 <-> GND
+ -5V <-- 51 52 --> /EX-I/O2
+ -12V <-- 53 54 --> +12V
+ GND <-> 55 56 --> +5V
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "bml3bus.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type BML3BUS_SLOT = &device_creator<bml3bus_slot_device>;
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bml3bus_slot_device - constructor
+//-------------------------------------------------
+bml3bus_slot_device::bml3bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, BML3BUS_SLOT, "Hitachi MB-6890 Slot", tag, owner, clock, "bml3bus_slot", __FILE__),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+bml3bus_slot_device::bml3bus_slot_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
+ device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+void bml3bus_slot_device::static_set_bml3bus_slot(device_t &device, const char *tag, const char *slottag)
+{
+ bml3bus_slot_device &bml3bus_card = dynamic_cast<bml3bus_slot_device &>(device);
+ bml3bus_card.m_bml3bus_tag = tag;
+ bml3bus_card.m_bml3bus_slottag = slottag;
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bml3bus_slot_device::device_start()
+{
+ device_bml3bus_card_interface *dev = dynamic_cast<device_bml3bus_card_interface *>(get_card_device());
+
+ if (dev) device_bml3bus_card_interface::static_set_bml3bus_tag(*dev, m_bml3bus_tag, m_bml3bus_slottag);
+}
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type BML3BUS = &device_creator<bml3bus_device>;
+
+void bml3bus_device::static_set_cputag(device_t &device, const char *tag)
+{
+ bml3bus_device &bml3bus = downcast<bml3bus_device &>(device);
+ bml3bus.m_cputag = tag;
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void bml3bus_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const bml3bus_interface *intf = reinterpret_cast<const bml3bus_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<bml3bus_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_nmi_cb, 0, sizeof(m_out_nmi_cb));
+ memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb));
+ memset(&m_out_firq_cb, 0, sizeof(m_out_firq_cb));
+ }
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bml3bus_device - constructor
+//-------------------------------------------------
+
+bml3bus_device::bml3bus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, BML3BUS, "Hitachi MB-6890 Bus", tag, owner, clock, "bml3bus", __FILE__)
+{
+}
+
+bml3bus_device::bml3bus_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
+ device_t(mconfig, type, name, tag, owner, clock, shortname, source)
+{
+}
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bml3bus_device::device_start()
+{
+ m_maincpu = machine().device<cpu_device>(m_cputag);
+
+ // resolve callbacks
+ m_out_nmi_func.resolve(m_out_nmi_cb, *this);
+ m_out_irq_func.resolve(m_out_irq_cb, *this);
+ m_out_firq_func.resolve(m_out_firq_cb, *this);
+
+ // clear slots
+ for (int i = 0; i < BML3BUS_MAX_SLOTS; i++)
+ {
+ m_device_list[i] = NULL;
+ }
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bml3bus_device::device_reset()
+{
+}
+
+device_bml3bus_card_interface *bml3bus_device::get_bml3bus_card(int slot)
+{
+ if (slot < 0)
+ {
+ return NULL;
+ }
+
+ return m_device_list[slot];
+}
+
+void bml3bus_device::add_bml3bus_card(int slot, device_bml3bus_card_interface *card)
+{
+ m_device_list[slot] = card;
+}
+
+void bml3bus_device::set_nmi_line(int state)
+{
+ m_out_nmi_func(state);
+}
+
+void bml3bus_device::set_irq_line(int state)
+{
+ m_out_irq_func(state);
+}
+
+void bml3bus_device::set_firq_line(int state)
+{
+ m_out_firq_func(state);
+}
+
+// interrupt request from bml3bus card
+WRITE_LINE_MEMBER( bml3bus_device::nmi_w ) { m_out_nmi_func(state); }
+WRITE_LINE_MEMBER( bml3bus_device::irq_w ) { m_out_irq_func(state); }
+WRITE_LINE_MEMBER( bml3bus_device::firq_w ) { m_out_firq_func(state); }
+
+//**************************************************************************
+// DEVICE CONFIG BML3BUS CARD INTERFACE
+//**************************************************************************
+
+
+//**************************************************************************
+// DEVICE BML3BUS CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_bml3bus_card_interface - constructor
+//-------------------------------------------------
+
+device_bml3bus_card_interface::device_bml3bus_card_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device),
+ m_bml3bus(NULL),
+ m_bml3bus_tag(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_bml3bus_card_interface - destructor
+//-------------------------------------------------
+
+device_bml3bus_card_interface::~device_bml3bus_card_interface()
+{
+}
+
+void device_bml3bus_card_interface::static_set_bml3bus_tag(device_t &device, const char *tag, const char *slottag)
+{
+ device_bml3bus_card_interface &bml3bus_card = dynamic_cast<device_bml3bus_card_interface &>(device);
+ bml3bus_card.m_bml3bus_tag = tag;
+ bml3bus_card.m_bml3bus_slottag = slottag;
+}
+
+void device_bml3bus_card_interface::set_bml3bus_device()
+{
+ // extract the slot number from the last digit of the slot tag
+ int tlen = strlen(m_bml3bus_slottag);
+
+ m_slot = (m_bml3bus_slottag[tlen-1] - '1');
+
+ if (m_slot < 0 || m_slot >= BML3BUS_MAX_SLOTS)
+ {
+ fatalerror("Slot %x out of range for Hitachi MB-6890 Bus\n", m_slot);
+ }
+
+ m_bml3bus = dynamic_cast<bml3bus_device *>(device().machine().device(m_bml3bus_tag));
+ m_bml3bus->add_bml3bus_card(m_slot, this);
+}
diff --git a/src/emu/bus/bml3/bml3bus.h b/src/emu/bus/bml3/bml3bus.h
new file mode 100644
index 00000000000..66a5660bbd2
--- /dev/null
+++ b/src/emu/bus/bml3/bml3bus.h
@@ -0,0 +1,151 @@
+/***************************************************************************
+
+ bml3bus.h - Hitachi MB-6890 slot bus and card emulation
+
+ Adapted from a2bus by Jonathan Edwards
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __BML3BUS_H__
+#define __BML3BUS_H__
+
+#include "emu.h"
+
+#define BML3BUS_MAX_SLOTS 6
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_BML3BUS_BUS_ADD(_tag, _cputag, _config) \
+ MCFG_DEVICE_ADD(_tag, BML3BUS, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ bml3bus_device::static_set_cputag(*device, _cputag);
+#define MCFG_BML3BUS_SLOT_ADD(_nbtag, _tag, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, BML3BUS_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
+ bml3bus_slot_device::static_set_bml3bus_slot(*device, _nbtag, _tag);
+#define MCFG_BML3BUS_SLOT_REMOVE(_tag) \
+ MCFG_DEVICE_REMOVE(_tag)
+
+#define MCFG_BML3BUS_ONBOARD_ADD(_nbtag, _tag, _dev_type) \
+ MCFG_DEVICE_ADD(_tag, _dev_type, 0) \
+ device_bml3bus_card_interface::static_set_bml3bus_tag(*device, _nbtag, _tag);
+
+#define MCFG_BML3BUS_BUS_REMOVE(_tag) \
+ MCFG_DEVICE_REMOVE(_tag)
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bml3bus_device;
+
+class bml3bus_slot_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ bml3bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ bml3bus_slot_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+
+ // device-level overrides
+ virtual void device_start();
+
+ // inline configuration
+ static void static_set_bml3bus_slot(device_t &device, const char *tag, const char *slottag);
+protected:
+ // configuration
+ const char *m_bml3bus_tag, *m_bml3bus_slottag;
+};
+
+// device type definition
+extern const device_type BML3BUS_SLOT;
+
+// ======================> bml3bus_interface
+
+struct bml3bus_interface
+{
+ devcb_write_line m_out_nmi_cb;
+ devcb_write_line m_out_irq_cb;
+ devcb_write_line m_out_firq_cb;
+};
+
+class device_bml3bus_card_interface;
+// ======================> bml3bus_device
+class bml3bus_device : public device_t,
+ public bml3bus_interface
+{
+public:
+ // construction/destruction
+ bml3bus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ bml3bus_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ // inline configuration
+ static void static_set_cputag(device_t &device, const char *tag);
+
+ void add_bml3bus_card(int slot, device_bml3bus_card_interface *card);
+ device_bml3bus_card_interface *get_bml3bus_card(int slot);
+
+ void set_nmi_line(int state);
+ void set_irq_line(int state);
+ void set_firq_line(int state);
+
+ DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ DECLARE_WRITE_LINE_MEMBER( irq_w );
+ DECLARE_WRITE_LINE_MEMBER( firq_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_config_complete();
+
+ // internal state
+ cpu_device *m_maincpu;
+
+ devcb_resolved_write_line m_out_nmi_func;
+ devcb_resolved_write_line m_out_irq_func;
+ devcb_resolved_write_line m_out_firq_func;
+
+ device_bml3bus_card_interface *m_device_list[BML3BUS_MAX_SLOTS];
+ const char *m_cputag;
+};
+
+
+// device type definition
+extern const device_type BML3BUS;
+
+// ======================> device_bml3bus_card_interface
+
+// class representing interface-specific live bml3bus card
+class device_bml3bus_card_interface : public device_slot_card_interface
+{
+ friend class bml3bus_device;
+public:
+ // construction/destruction
+ device_bml3bus_card_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_bml3bus_card_interface();
+
+ device_bml3bus_card_interface *next() const { return m_next; }
+
+ void set_bml3bus_device();
+
+ void raise_slot_nmi() { m_bml3bus->set_nmi_line(ASSERT_LINE); }
+ void lower_slot_nmi() { m_bml3bus->set_nmi_line(CLEAR_LINE); }
+ void raise_slot_irq() { m_bml3bus->set_irq_line(ASSERT_LINE); }
+ void lower_slot_irq() { m_bml3bus->set_irq_line(CLEAR_LINE); }
+ void raise_slot_firq() { m_bml3bus->set_firq_line(ASSERT_LINE); }
+ void lower_slot_firq() { m_bml3bus->set_firq_line(CLEAR_LINE); }
+
+ // inline configuration
+ static void static_set_bml3bus_tag(device_t &device, const char *tag, const char *slottag);
+public:
+ bml3bus_device *m_bml3bus;
+ const char *m_bml3bus_tag, *m_bml3bus_slottag;
+ int m_slot;
+ device_bml3bus_card_interface *m_next;
+};
+
+#endif /* __BML3BUS_H__ */
diff --git a/src/emu/bus/bml3/bml3kanji.c b/src/emu/bus/bml3/bml3kanji.c
new file mode 100644
index 00000000000..e13f07e28ff
--- /dev/null
+++ b/src/emu/bus/bml3/bml3kanji.c
@@ -0,0 +1,99 @@
+/*********************************************************************
+
+ bml3kanji.c
+
+ Hitachi MP-9740 (?) kanji character ROM for the MB-689x
+
+*********************************************************************/
+
+#include "emu.h"
+#include "bml3kanji.h"
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type BML3BUS_KANJI = &device_creator<bml3bus_kanji_device>;
+
+#define KANJI_ROM_REGION "kanji_rom"
+
+ROM_START( kanji )
+ ROM_REGION( 0x20000, KANJI_ROM_REGION, ROMREGION_ERASEFF )
+ ROM_LOAD("kanji.rom", 0x00000, 0x20000, BAD_DUMP CRC(de99a726) SHA1(65fead5d0d779b242f6e0ac25fcc9899dc343101))
+ROM_END
+
+MACHINE_CONFIG_FRAGMENT( kanji )
+ // nothing to add
+MACHINE_CONFIG_END
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor bml3bus_kanji_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( kanji );
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *bml3bus_kanji_device::device_rom_region() const
+{
+ return ROM_NAME( kanji );
+}
+
+READ8_MEMBER( bml3bus_kanji_device::bml3_kanji_r )
+{
+ return m_rom[((UINT32)m_kanji_addr << 1) + offset];
+}
+
+WRITE8_MEMBER( bml3bus_kanji_device::bml3_kanji_w )
+{
+ m_kanji_addr &= (0xff << (offset*8));
+ m_kanji_addr |= (data << ((offset^1)*8));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+bml3bus_kanji_device::bml3bus_kanji_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, BML3BUS_KANJI, "Hitachi MP-9740 Kanji Character ROM Card", tag, owner, clock, "bml3kanji", __FILE__),
+ device_bml3bus_card_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bml3bus_kanji_device::device_start()
+{
+ // set_bml3bus_device makes m_slot valid
+ set_bml3bus_device();
+
+ m_rom = memregion(KANJI_ROM_REGION)->base();
+
+ // install into memory
+ address_space &space_prg = machine().firstcpu->space(AS_PROGRAM);
+ space_prg.install_readwrite_handler(0xff75, 0xff76, read8_delegate( FUNC(bml3bus_kanji_device::bml3_kanji_r), this), write8_delegate(FUNC(bml3bus_kanji_device::bml3_kanji_w), this) );
+}
+
+void bml3bus_kanji_device::device_reset()
+{
+ m_kanji_addr = 0;
+}
diff --git a/src/emu/bus/bml3/bml3kanji.h b/src/emu/bus/bml3/bml3kanji.h
new file mode 100644
index 00000000000..91353e001f9
--- /dev/null
+++ b/src/emu/bus/bml3/bml3kanji.h
@@ -0,0 +1,47 @@
+/*********************************************************************
+
+ bml3kanji.h
+
+ Hitachi MP-9740 (?) kanji character ROM for the MB-689x
+
+*********************************************************************/
+
+#ifndef __BML3BUS_KANJI__
+#define __BML3BUS_KANJI__
+
+#include "emu.h"
+#include "bml3bus.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bml3bus_kanji_device:
+ public device_t,
+ public device_bml3bus_card_interface
+{
+public:
+ // construction/destruction
+ bml3bus_kanji_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual const rom_entry *device_rom_region() const;
+
+ DECLARE_READ8_MEMBER(bml3_kanji_r);
+ DECLARE_WRITE8_MEMBER(bml3_kanji_w);
+
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+
+ UINT16 m_kanji_addr;
+
+private:
+ UINT8 *m_rom;
+};
+
+// device type definition
+extern const device_type BML3BUS_KANJI;
+
+#endif /* __BML3BUS_KANJI__ */
diff --git a/src/emu/bus/bml3/bml3mp1802.c b/src/emu/bus/bml3/bml3mp1802.c
new file mode 100644
index 00000000000..3d20f77f122
--- /dev/null
+++ b/src/emu/bus/bml3/bml3mp1802.c
@@ -0,0 +1,155 @@
+/*********************************************************************
+
+ bml3mp1802.c
+
+ Hitachi MP-1802 floppy disk controller card for the MB-6890
+ Hitachi MP-3550 floppy drive is attached
+
+*********************************************************************/
+
+#include "emu.h"
+#include "bml3mp1802.h"
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type BML3BUS_MP1802 = &device_creator<bml3bus_mp1802_device>;
+
+static const floppy_interface bml3_mp1802_floppy_interface =
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ FLOPPY_STANDARD_5_25_DSDD,
+ LEGACY_FLOPPY_OPTIONS_NAME(default),
+ NULL
+};
+
+WRITE_LINE_MEMBER( bml3bus_mp1802_device::bml3_wd17xx_intrq_w )
+{
+ if (state) {
+ m_bml3bus->set_nmi_line(PULSE_LINE);
+ }
+}
+
+const wd17xx_interface bml3_wd17xx_interface =
+{
+ DEVCB_NULL,
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, bml3bus_mp1802_device, bml3_wd17xx_intrq_w),
+ DEVCB_NULL,
+ {FLOPPY_0, FLOPPY_1}
+};
+
+
+#define MP1802_ROM_REGION "mp1802_rom"
+
+ROM_START( mp1802 )
+ ROM_REGION(0x10000, MP1802_ROM_REGION, 0)
+ // MP-1802 disk controller ROM, which replaces part of the system ROM
+ ROM_LOAD( "mp1802.rom", 0xf800, 0x800, BAD_DUMP CRC(8d0dc101) SHA1(92f7d1cebecafa7472e45c4999520de5c01c6dbc))
+ROM_END
+
+MACHINE_CONFIG_FRAGMENT( mp1802 )
+ MCFG_MB8866_ADD("wd17xx", bml3_wd17xx_interface )
+ MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(bml3_mp1802_floppy_interface)
+MACHINE_CONFIG_END
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor bml3bus_mp1802_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( mp1802 );
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *bml3bus_mp1802_device::device_rom_region() const
+{
+ return ROM_NAME( mp1802 );
+}
+
+READ8_MEMBER( bml3bus_mp1802_device::bml3_mp1802_r)
+{
+ return wd17xx_drq_r(m_wd17xx) ? 0x00 : 0x80;
+}
+
+WRITE8_MEMBER( bml3bus_mp1802_device::bml3_mp1802_w)
+{
+ int drive = data & 0x03;
+ int side = BIT(data, 4);
+ int motor = BIT(data, 3);
+ const char *floppy_name = NULL;
+ switch (drive) {
+ case 0:
+ floppy_name = FLOPPY_0;
+ break;
+ case 1:
+ floppy_name = FLOPPY_1;
+ break;
+ case 2:
+ floppy_name = FLOPPY_2;
+ break;
+ case 3:
+ floppy_name = FLOPPY_3;
+ break;
+ }
+ device_t *floppy = subdevice(floppy_name);
+ wd17xx_set_drive(m_wd17xx,drive);
+ floppy_mon_w(floppy, !motor);
+ floppy_drive_set_ready_state(floppy, ASSERT_LINE, 0);
+ wd17xx_set_side(m_wd17xx,side);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+bml3bus_mp1802_device::bml3bus_mp1802_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, BML3BUS_MP1802, "Hitachi MP-1802 Floppy Controller Card", tag, owner, clock, "bml3mp1802", __FILE__),
+ device_bml3bus_card_interface(mconfig, *this),
+ m_wd17xx(*this, "wd17xx")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bml3bus_mp1802_device::device_start()
+{
+ // set_bml3bus_device makes m_slot valid
+ set_bml3bus_device();
+
+ m_rom = memregion(MP1802_ROM_REGION)->base();
+
+ // install into memory
+ address_space &space_prg = machine().firstcpu->space(AS_PROGRAM);
+ space_prg.install_legacy_readwrite_handler(m_wd17xx, 0xff00, 0xff03, FUNC(wd17xx_r), FUNC(wd17xx_w));
+ space_prg.install_readwrite_handler(0xff04, 0xff04, read8_delegate( FUNC(bml3bus_mp1802_device::bml3_mp1802_r), this), write8_delegate(FUNC(bml3bus_mp1802_device::bml3_mp1802_w), this) );
+ // overwriting the main ROM (rather than using e.g. install_rom) should mean that bank switches for RAM expansion still work...
+ UINT8 *mainrom = device().machine().root_device().memregion("maincpu")->base();
+ memcpy(mainrom + 0xf800, m_rom + 0xf800, 0x800);
+}
+
+void bml3bus_mp1802_device::device_reset()
+{
+}
diff --git a/src/emu/bus/bml3/bml3mp1802.h b/src/emu/bus/bml3/bml3mp1802.h
new file mode 100644
index 00000000000..81301c79661
--- /dev/null
+++ b/src/emu/bus/bml3/bml3mp1802.h
@@ -0,0 +1,50 @@
+/*********************************************************************
+
+ bml3mp1802.h
+
+ Hitachi MP-1802 floppy disk controller card for the MB-6890
+ Hitachi MP-3550 floppy drive is attached
+
+*********************************************************************/
+
+#ifndef __BML3BUS_MP1802__
+#define __BML3BUS_MP1802__
+
+#include "emu.h"
+#include "bml3bus.h"
+#include "imagedev/flopdrv.h"
+#include "machine/wd17xx.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bml3bus_mp1802_device:
+ public device_t,
+ public device_bml3bus_card_interface
+{
+public:
+ // construction/destruction
+ bml3bus_mp1802_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual const rom_entry *device_rom_region() const;
+
+ DECLARE_READ8_MEMBER(bml3_mp1802_r);
+ DECLARE_WRITE8_MEMBER(bml3_mp1802_w);
+ DECLARE_WRITE_LINE_MEMBER(bml3_wd17xx_intrq_w);
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+
+ required_device<mb8866_device> m_wd17xx;
+
+private:
+ UINT8 *m_rom;
+};
+
+// device type definition
+extern const device_type BML3BUS_MP1802;
+
+#endif /* __BML3BUS_MP1802__ */
diff --git a/src/emu/bus/bml3/bml3mp1805.c b/src/emu/bus/bml3/bml3mp1805.c
new file mode 100644
index 00000000000..2fb71c1605a
--- /dev/null
+++ b/src/emu/bus/bml3/bml3mp1805.c
@@ -0,0 +1,178 @@
+/*********************************************************************
+
+ bml3mp1805.c
+
+ Hitachi MP-1805 floppy disk controller card for the MB-6890
+ Floppy drive is attached
+
+*********************************************************************/
+
+#include "emu.h"
+#include "bml3mp1805.h"
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type BML3BUS_MP1805 = &device_creator<bml3bus_mp1805_device>;
+
+static const floppy_interface bml3_mp1805_floppy_interface =
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ FLOPPY_STANDARD_3_SSDD,
+ LEGACY_FLOPPY_OPTIONS_NAME(default),
+ NULL
+};
+
+WRITE_LINE_MEMBER( bml3bus_mp1805_device::bml3_mc6843_intrq_w )
+{
+ if (state) {
+ m_bml3bus->set_nmi_line(PULSE_LINE);
+ }
+}
+
+const mc6843_interface bml3_6843_if =
+{
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, bml3bus_mp1805_device, bml3_mc6843_intrq_w)
+};
+
+
+#define MP1805_ROM_REGION "mp1805_rom"
+
+ROM_START( mp1805 )
+ ROM_REGION(0x10000, MP1805_ROM_REGION, 0)
+ // MP-1805 disk controller ROM, which replaces part of the system ROM
+ ROM_LOAD( "mp1805.rom", 0xf800, 0x0800, BAD_DUMP CRC(b532d8d9) SHA1(6f1160356d5bf64b5926b1fdb60db414edf65f22))
+ROM_END
+
+MACHINE_CONFIG_FRAGMENT( mp1805 )
+ MCFG_MC6843_ADD( "mc6843", bml3_6843_if )
+ MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(bml3_mp1805_floppy_interface)
+MACHINE_CONFIG_END
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor bml3bus_mp1805_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( mp1805 );
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *bml3bus_mp1805_device::device_rom_region() const
+{
+ return ROM_NAME( mp1805 );
+}
+
+READ8_MEMBER( bml3bus_mp1805_device::bml3_mp1805_r)
+{
+ // TODO: read supported or not?
+ // return mc6843_drq_r(m_mc6843) ? 0x00 : 0x80;
+ return -1;
+}
+
+WRITE8_MEMBER( bml3bus_mp1805_device::bml3_mp1805_w)
+{
+ // b7 b6 b5 b4 b3 b2 b1 b0
+ // MT ? ? ? D3 D2 D1 D0
+ // MT: 0=motor off, 1=motor on
+ // Dn: 1=select drive <n>
+ int drive_select = data & 0x0f;
+ int drive;
+ // TODO: MESS UI for flipping disk? Note that D88 images are double-sided, but the physical drive is single-sided
+ int side = 0;
+ int motor = BIT(data, 7);
+ const char *floppy_name = NULL;
+ switch (drive_select) {
+ case 1:
+ drive = 0;
+ break;
+ case 2:
+ drive = 1;
+ break;
+ case 4:
+ drive = 2;
+ break;
+ case 8:
+ drive = 3;
+ break;
+ default:
+ // TODO: what's the correct behaviour if more than one drive select bit is set? Or no bit set?
+ drive = 0;
+ break;
+ }
+ switch (drive) {
+ case 0:
+ floppy_name = FLOPPY_0;
+ break;
+ case 1:
+ floppy_name = FLOPPY_1;
+ break;
+ case 2:
+ floppy_name = FLOPPY_2;
+ break;
+ case 3:
+ floppy_name = FLOPPY_3;
+ break;
+ }
+ device_t *floppy = subdevice(floppy_name);
+ m_mc6843->set_drive(drive);
+ floppy_mon_w(floppy, motor);
+ floppy_drive_set_ready_state(floppy, ASSERT_LINE, 0);
+ m_mc6843->set_side(side);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+bml3bus_mp1805_device::bml3bus_mp1805_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, BML3BUS_MP1805, "Hitachi MP-1805 Floppy Controller Card", tag, owner, clock, "bml3mp1805", __FILE__),
+ device_bml3bus_card_interface(mconfig, *this),
+ m_mc6843(*this, "mc6843")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bml3bus_mp1805_device::device_start()
+{
+ // set_bml3bus_device makes m_slot valid
+ set_bml3bus_device();
+
+ m_rom = memregion(MP1805_ROM_REGION)->base();
+
+ // install into memory
+ address_space &space_prg = machine().firstcpu->space(AS_PROGRAM);
+ space_prg.install_readwrite_handler(0xff18, 0xff1f, read8_delegate( FUNC(mc6843_device::read), (mc6843_device*)m_mc6843), write8_delegate(FUNC(mc6843_device::write), (mc6843_device*)m_mc6843) );
+ space_prg.install_readwrite_handler(0xff20, 0xff20, read8_delegate( FUNC(bml3bus_mp1805_device::bml3_mp1805_r), this), write8_delegate(FUNC(bml3bus_mp1805_device::bml3_mp1805_w), this) );
+ // overwriting the main ROM (rather than using e.g. install_rom) should mean that bank switches for RAM expansion still work...
+ UINT8 *mainrom = device().machine().root_device().memregion("maincpu")->base();
+ memcpy(mainrom + 0xf800, m_rom + 0xf800, 0x800);
+}
+
+void bml3bus_mp1805_device::device_reset()
+{
+}
diff --git a/src/emu/bus/bml3/bml3mp1805.h b/src/emu/bus/bml3/bml3mp1805.h
new file mode 100644
index 00000000000..4f3ab58e9dd
--- /dev/null
+++ b/src/emu/bus/bml3/bml3mp1805.h
@@ -0,0 +1,52 @@
+/*********************************************************************
+
+ bml3mp1805.h
+
+ Hitachi MP-1805 floppy disk controller card for the MB-6890
+ Floppy drive is attached
+
+*********************************************************************/
+
+#ifndef __BML3BUS_MP1805__
+#define __BML3BUS_MP1805__
+
+#include "emu.h"
+#include "bml3bus.h"
+#include "imagedev/flopdrv.h"
+#include "machine/mc6843.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bml3bus_mp1805_device:
+ public device_t,
+ public device_bml3bus_card_interface
+{
+public:
+ // construction/destruction
+ bml3bus_mp1805_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual const rom_entry *device_rom_region() const;
+
+ DECLARE_READ8_MEMBER(bml3_mp1805_r);
+ DECLARE_WRITE8_MEMBER(bml3_mp1805_w);
+
+ DECLARE_WRITE_LINE_MEMBER( bml3_mc6843_intrq_w );
+
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+
+ required_device<mc6843_device> m_mc6843;
+
+private:
+ UINT8 *m_rom;
+};
+
+// device type definition
+extern const device_type BML3BUS_MP1805;
+
+#endif /* __BML3BUS_MP1805__ */
diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak
index ad7574e0e1d..5677fcf627b 100644
--- a/src/emu/bus/bus.mak
+++ b/src/emu/bus/bus.mak
@@ -705,6 +705,7 @@ BUSOBJS += $(BUSOBJ)/rs232/keyboard.o
BUSOBJS += $(BUSOBJ)/rs232/null_modem.o
BUSOBJS += $(BUSOBJ)/rs232/rs232.o
BUSOBJS += $(BUSOBJ)/rs232/ser_mouse.o
+BUSOBJS += $(BUSOBJ)/rs232/teleprinter.o
BUSOBJS += $(BUSOBJ)/rs232/terminal.o
endif
@@ -906,3 +907,94 @@ BUSOBJS += $(BUSOBJ)/gba/gba_slot.o
BUSOBJS += $(BUSOBJ)/gba/rom.o
endif
+#-------------------------------------------------
+#
+#@src/emu/bus/bml3/bml3bus.h,BUSES += BML3
+#-------------------------------------------------
+ifneq ($(filter BML3,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/bml3
+BUSOBJS += $(BUSOBJ)/bml3/bml3bus.o
+BUSOBJS += $(BUSOBJ)/bml3/bml3mp1802.o
+BUSOBJS += $(BUSOBJ)/bml3/bml3mp1805.o
+BUSOBJS += $(BUSOBJ)/bml3/bml3kanji.o
+endif
+
+#-------------------------------------------------
+#
+#@src/emu/bus/coco/cococart.h,BUSES += COCO
+#-------------------------------------------------
+ifneq ($(filter COCO,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/coco
+BUSOBJS += $(BUSOBJ)/coco/cococart.o
+BUSOBJS += $(BUSOBJ)/coco/coco_232.o
+BUSOBJS += $(BUSOBJ)/coco/coco_orch90.o
+BUSOBJS += $(BUSOBJ)/coco/coco_pak.o
+BUSOBJS += $(BUSOBJ)/coco/coco_fdc.o
+BUSOBJS += $(BUSOBJ)/coco/coco_multi.o
+endif
+
+#-------------------------------------------------
+#
+#@src/emu/bus/cpc/cpcexp.h,BUSES += CPC
+#-------------------------------------------------
+ifneq ($(filter CPC,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/cpc
+BUSOBJS += $(BUSOBJ)/cpc/cpcexp.o
+BUSOBJS += $(BUSOBJ)/cpc/cpc_ssa1.o
+BUSOBJS += $(BUSOBJ)/cpc/cpc_rom.o
+BUSOBJS += $(BUSOBJ)/cpc/cpc_pds.o
+BUSOBJS += $(BUSOBJ)/cpc/mface2.o
+endif
+
+#-------------------------------------------------
+#
+#@src/emu/bus/epson_sio/epson_sio.h,BUSES += EPSON_SIO
+#-------------------------------------------------
+ifneq ($(filter EPSON_SIO,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/epson_sio
+BUSOBJS += $(BUSOBJ)/epson_sio/epson_sio.o
+BUSOBJS += $(BUSOBJ)/epson_sio/pf10.o
+BUSOBJS += $(BUSOBJ)/epson_sio/tf20.o
+endif
+
+#-------------------------------------------------
+#
+#@src/emu/bus/pce/pce_slot.h,BUSES += PCE
+#-------------------------------------------------
+ifneq ($(filter PCE,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/pce
+BUSOBJS += $(BUSOBJ)/pce/pce_slot.o
+BUSOBJS += $(BUSOBJ)/pce/pce_rom.o
+endif
+
+#-------------------------------------------------
+#
+#@src/emu/bus/x68k/x68kexp.h,BUSES += X68K
+#-------------------------------------------------
+ifneq ($(filter X68K,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/x68k
+BUSOBJS += $(BUSOBJ)/x68k/x68kexp.o
+BUSOBJS += $(BUSOBJ)/x68k/x68k_neptunex.o
+BUSOBJS += $(BUSOBJ)/x68k/x68k_scsiext.o
+endif
+
+#-------------------------------------------------
+#
+#@src/emu/bus/abckb/abckb.h,BUSES += ABCKB
+#-------------------------------------------------
+ifneq ($(filter ABCKB,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/abckb
+BUSOBJS += $(BUSOBJ)/abckb/abckb.o
+BUSOBJS += $(BUSOBJ)/abckb/abc77.o
+BUSOBJS += $(BUSOBJ)/abckb/abc99.o
+BUSOBJS += $(BUSOBJ)/abckb/abc800kb.o
+endif
+
+#-------------------------------------------------
+#
+#@src/emu/bus/compucolor/compclr_flp.h,BUSES += COMPUCOLOR
+#-------------------------------------------------
+ifneq ($(filter COMPUCOLOR,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/compucolor
+BUSOBJS += $(BUSOBJ)/compucolor/floppy.o
+endif
diff --git a/src/emu/bus/coco/coco_232.c b/src/emu/bus/coco/coco_232.c
new file mode 100644
index 00000000000..14cc989f9cd
--- /dev/null
+++ b/src/emu/bus/coco/coco_232.c
@@ -0,0 +1,90 @@
+/***************************************************************************
+
+ coco_232.c
+
+ Code for emulating the CoCo RS-232 PAK
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_232.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define UART_TAG "uart"
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+static MACHINE_CONFIG_FRAGMENT(coco_rs232)
+ MCFG_DEVICE_ADD(UART_TAG, MOS6551, 0)
+ MCFG_MOS6551_XTAL(XTAL_1_8432MHz)
+MACHINE_CONFIG_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type COCO_232 = &device_creator<coco_232_device>;
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_232_device - constructor
+//-------------------------------------------------
+
+coco_232_device::coco_232_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, COCO_232, "CoCo RS-232 PAK", tag, owner, clock, "coco_232", __FILE__),
+ device_cococart_interface( mconfig, *this ),
+ m_uart(*this, UART_TAG)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_232_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor coco_232_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( coco_rs232 );
+}
+
+/*-------------------------------------------------
+ read
+-------------------------------------------------*/
+
+READ8_MEMBER(coco_232_device::read)
+{
+ UINT8 result = 0x00;
+
+ if ((offset >= 0x28) && (offset <= 0x2F))
+ result = m_uart->read(space, offset - 0x28);
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ write
+-------------------------------------------------*/
+
+WRITE8_MEMBER(coco_232_device::write)
+{
+ if ((offset >= 0x28) && (offset <= 0x2F))
+ m_uart->write(space, offset - 0x28, data);
+}
diff --git a/src/emu/bus/coco/coco_232.h b/src/emu/bus/coco/coco_232.h
new file mode 100644
index 00000000000..80d986a010c
--- /dev/null
+++ b/src/emu/bus/coco/coco_232.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#ifndef __COCO_232_H__
+#define __COCO_232_H__
+
+#include "emu.h"
+#include "cococart.h"
+#include "machine/mos6551.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_232_device
+
+class coco_232_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ coco_232_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual DECLARE_READ8_MEMBER(read);
+ virtual DECLARE_WRITE8_MEMBER(write);
+private:
+ // internal state
+ required_device<mos6551_device> m_uart;
+};
+
+
+// device type definition
+extern const device_type COCO_232;
+
+#endif /* __COCO_232_H__ */
diff --git a/src/emu/bus/coco/coco_fdc.c b/src/emu/bus/coco/coco_fdc.c
new file mode 100644
index 00000000000..d8e559c371a
--- /dev/null
+++ b/src/emu/bus/coco/coco_fdc.c
@@ -0,0 +1,672 @@
+/*********************************************************************
+
+ coco_fdc.c
+
+ CoCo/Dragon FDC
+
+ The CoCo and Dragon both use the Western Digital floppy disk controllers.
+ The CoCo uses either the WD1793 or the WD1773, the Dragon uses the WD2797,
+ which mostly uses the same command set with some subtle differences, most
+ notably the 2797 handles disk side select internally. The Dragon Alpha also
+ uses the WD2797, however as this is a built in interface and not an external
+ cartrige, it is dealt with in the main coco.c file.
+
+ The wd's variables are mapped to $FF48-$FF4B on the CoCo and on $FF40-$FF43
+ on the Dragon. In addition, there is another register
+ called DSKREG that controls the interface with the wd1793. DSKREG is
+ detailed below: But they appear to be
+
+ References:
+ CoCo: Disk Basic Unravelled
+ Dragon: Inferences from the PC-Dragon source code
+ DragonDos Controller, Disk and File Formats by Graham E Kinns
+
+ ---------------------------------------------------------------------------
+
+ DSKREG - the control register
+ CoCo ($FF40) Dragon ($FF48)
+
+ Bit Bit
+ 7 halt enable flag 7 not used
+ 6 drive select #3 6 not used
+ 5 density (0=single, 1=double) 5 NMI enable flag
+ and NMI enable flag
+ 4 write precompensation 4 write precompensation
+ 3 drive motor activation 3 single density enable
+ 2 drive select #2 2 drive motor activation
+ 1 drive select #1 1 drive select high bit
+ 0 drive select #0 0 drive select low bit
+
+ Reading from $FF48-$FF4F clears bit 7 of DSKREG ($FF40)
+
+ ---------------------------------------------------------------------------
+
+ 2007-02-22, P.Harvey-Smith
+
+ Began implementing the Dragon Delta Dos controler, this was actually the first
+ Dragon disk controler to market, beating Dragon Data's by a couple of months,
+ it is based around the WD2791 FDC, which is compatible with the WD1793/WD2797 used
+ by the standard CoCo and Dragon disk controlers except that it used an inverted
+ data bus, which is the reason the read/write handlers invert the data. This
+ controler like, the DragonDos WD2797 is mapped at $FF40-$FF43, in the normal
+ register order.
+
+ The Delta cart also has a register (74LS174 hex flipflop) at $FF44 encoded as
+ follows :-
+
+ Bit
+ 7 not used
+ 6 not used
+ 5 not used
+ 4 Single (0) / Double (1) density select
+ 3 5.25"(0) / 8"(1) Clock select
+ 2 Side select
+ 1 Drive select ms bit
+ 0 Drive select ls bit
+
+*********************************************************************/
+
+#include "emu.h"
+#include "coco_fdc.h"
+#include "imagedev/flopdrv.h"
+#include "includes/coco.h"
+#include "machine/wd17xx.h"
+#include "imagedev/flopdrv.h"
+#include "formats/coco_dsk.h"
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+#define LOG_FDC 0
+#define WD_TAG "wd17xx"
+#define DISTO_TAG "disto"
+#define CLOUD9_TAG "cloud9"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/***************************************************************************
+ LOCAL VARIABLES
+***************************************************************************/
+
+static const floppy_interface coco_floppy_interface =
+{
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ FLOPPY_STANDARD_5_25_DSHD,
+ LEGACY_FLOPPY_OPTIONS_NAME(coco),
+ "floppy_5_25",
+ NULL
+};
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+/*-------------------------------------------------
+ real_time_clock
+-------------------------------------------------*/
+
+coco_rtc_type_t coco_fdc_device::real_time_clock()
+{
+ coco_rtc_type_t result = (coco_rtc_type_t) machine().root_device().ioport("real_time_clock")->read_safe(RTC_NONE);
+
+ /* check to make sure we don't have any invalid values */
+ if (((result == RTC_DISTO) && (m_disto_msm6242 == NULL))
+ || ((result == RTC_CLOUD9) && (m_ds1315 == NULL)))
+ {
+ result = RTC_NONE;
+ }
+
+ return result;
+}
+/*-------------------------------------------------
+ fdc_intrq_w - callback from the FDC
+-------------------------------------------------*/
+
+WRITE_LINE_MEMBER( coco_fdc_device::fdc_intrq_w )
+{
+ set_intrq(state);
+ update_lines();
+}
+
+
+/*-------------------------------------------------
+ fdc_drq_w - callback from the FDC
+-------------------------------------------------*/
+
+WRITE_LINE_MEMBER( coco_fdc_device::fdc_drq_w )
+{
+ set_drq(state);
+ update_lines();
+}
+
+
+//**************************************************************************
+// COCO FDC
+//**************************************************************************
+
+static const wd17xx_interface coco_wd17xx_interface =
+{
+ DEVCB_NULL,
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, coco_fdc_device, fdc_intrq_w),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, coco_fdc_device, fdc_drq_w),
+ {FLOPPY_0,FLOPPY_1,FLOPPY_2,FLOPPY_3}
+};
+
+static MACHINE_CONFIG_FRAGMENT(coco_fdc)
+ MCFG_WD1773_ADD(WD_TAG, coco_wd17xx_interface)
+ MCFG_DEVICE_ADD(DISTO_TAG, MSM6242, XTAL_32_768kHz)
+ MCFG_DS1315_ADD(CLOUD9_TAG)
+
+ MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(coco_floppy_interface)
+MACHINE_CONFIG_END
+
+ROM_START( coco_fdc )
+ ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00)
+ ROM_LOAD_OPTIONAL( "disk10.rom", 0x0000, 0x2000, CRC(b4f9968e) SHA1(04115be3f97952b9d9310b52f806d04f80b40d03))
+ROM_END
+
+const device_type COCO_FDC = &device_creator<coco_fdc_device>;
+
+//-------------------------------------------------
+// coco_fdc_device - constructor
+//-------------------------------------------------
+coco_fdc_device::coco_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_cococart_interface( mconfig, *this )
+{
+}
+
+coco_fdc_device::coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, COCO_FDC, "CoCo FDC", tag, owner, clock, "coco_fdc", __FILE__),
+ device_cococart_interface( mconfig, *this )
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_fdc_device::device_start()
+{
+ m_owner = dynamic_cast<cococart_slot_device *>(owner());
+ m_drq = 1;
+ m_disto_msm6242 = subdevice<msm6242_device>(DISTO_TAG);
+ m_ds1315 = subdevice<ds1315_device>(CLOUD9_TAG);
+ m_wd17xx = subdevice(WD_TAG);
+ m_dskreg = 0x00;
+ m_intrq = 0;
+ m_msm6242_rtc_address = 0;
+}
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor coco_fdc_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( coco_fdc );
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *coco_fdc_device::device_rom_region() const
+{
+ return ROM_NAME( coco_fdc );
+}
+
+/*-------------------------------------------------
+ get_cart_base
+-------------------------------------------------*/
+
+UINT8* coco_fdc_device::get_cart_base()
+{
+ return memregion("eprom")->base();
+}
+
+/*-------------------------------------------------
+ update_lines - CoCo specific disk
+ controller lines
+-------------------------------------------------*/
+
+void coco_fdc_device::update_lines()
+{
+ /* clear HALT enable under certain circumstances */
+ if ((m_intrq != 0) && (m_dskreg & 0x20))
+ m_dskreg &= ~0x80; /* clear halt enable */
+
+ /* set the NMI line */
+ m_owner->cart_set_line(COCOCART_LINE_NMI,
+ ((m_intrq != 0) && (m_dskreg & 0x20)) ? COCOCART_LINE_VALUE_ASSERT : COCOCART_LINE_VALUE_CLEAR);
+
+ /* set the HALT line */
+ m_owner->cart_set_line(COCOCART_LINE_HALT,
+ ((m_drq == 0) && (m_dskreg & 0x80)) ? COCOCART_LINE_VALUE_ASSERT : COCOCART_LINE_VALUE_CLEAR);
+}
+
+/*-------------------------------------------------
+ dskreg_w - function to write to CoCo
+ dskreg
+-------------------------------------------------*/
+
+void coco_fdc_device::dskreg_w(UINT8 data)
+{
+ UINT8 drive = 0;
+ UINT8 head = 0;
+
+ if (LOG_FDC)
+ {
+ logerror("fdc_coco_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n",
+ data & 0x80 ? 'H' : 'h',
+ data & 0x40 ? '3' : '.',
+ data & 0x20 ? 'D' : 'S',
+ data & 0x10 ? 'P' : 'p',
+ data & 0x08 ? 'M' : 'm',
+ data & 0x04 ? '2' : '.',
+ data & 0x02 ? '1' : '.',
+ data & 0x01 ? '0' : '.',
+ data);
+ }
+
+ /* An email from John Kowalski informed me that if the DS3 is
+ * high, and one of the other drive bits is selected (DS0-DS2), then the
+ * second side of DS0, DS1, or DS2 is selected. If multiple bits are
+ * selected in other situations, then both drives are selected, and any
+ * read signals get yucky.
+ */
+
+ if (data & 0x04)
+ drive = 2;
+ else if (data & 0x02)
+ drive = 1;
+ else if (data & 0x01)
+ drive = 0;
+ else if (data & 0x40)
+ drive = 3;
+
+ device_t *floppy[4];
+
+ floppy[0] = subdevice(FLOPPY_0);
+ floppy[1] = subdevice(FLOPPY_1);
+ floppy[2] = subdevice(FLOPPY_2);
+ floppy[3] = subdevice(FLOPPY_3);
+
+ for (int i = 0; i < 4; i++)
+ {
+ floppy_mon_w(floppy[i], i == drive ? CLEAR_LINE : ASSERT_LINE);
+ }
+
+ head = ((data & 0x40) && (drive != 3)) ? 1 : 0;
+
+ m_dskreg = data;
+
+ update_lines();
+
+ wd17xx_set_drive(m_wd17xx, drive);
+ wd17xx_set_side(m_wd17xx, head);
+ wd17xx_dden_w(m_wd17xx, !BIT(m_dskreg, 5));
+}
+
+/*-------------------------------------------------
+ read
+-------------------------------------------------*/
+
+READ8_MEMBER(coco_fdc_device::read)
+{
+ UINT8 result = 0;
+
+ switch(offset & 0xEF)
+ {
+ case 8:
+ result = wd17xx_status_r(m_wd17xx, space, 0);
+ break;
+ case 9:
+ result = wd17xx_track_r(m_wd17xx, space, 0);
+ break;
+ case 10:
+ result = wd17xx_sector_r(m_wd17xx, space, 0);
+ break;
+ case 11:
+ result = wd17xx_data_r(m_wd17xx, space, 0);
+ break;
+ }
+
+ /* other stuff for RTCs */
+ switch(offset)
+ {
+ case 0x10: /* FF50 */
+ if (real_time_clock() == RTC_DISTO)
+ result = m_disto_msm6242->read(space,m_msm6242_rtc_address);
+ break;
+
+ case 0x38: /* FF78 */
+ if (real_time_clock() == RTC_CLOUD9)
+ m_ds1315->read_0(space, offset);
+ break;
+
+ case 0x39: /* FF79 */
+ if (real_time_clock() == RTC_CLOUD9)
+ m_ds1315->read_1(space, offset);
+ break;
+
+ case 0x3C: /* FF7C */
+ if (real_time_clock() == RTC_CLOUD9)
+ result = m_ds1315->read_data(space, offset);
+ break;
+ }
+ return result;
+}
+
+
+
+/*-------------------------------------------------
+ write
+-------------------------------------------------*/
+
+WRITE8_MEMBER(coco_fdc_device::write)
+{
+ switch(offset & 0x1F)
+ {
+ case 0: case 1: case 2: case 3:
+ case 4: case 5: case 6: case 7:
+ dskreg_w(data);
+ break;
+ case 8:
+ wd17xx_command_w(m_wd17xx, space, 0, data);
+ break;
+ case 9:
+ wd17xx_track_w(m_wd17xx, space, 0, data);
+ break;
+ case 10:
+ wd17xx_sector_w(m_wd17xx, space, 0, data);
+ break;
+ case 11:
+ wd17xx_data_w(m_wd17xx, space, 0, data);
+ break;
+ };
+
+ /* other stuff for RTCs */
+ switch(offset)
+ {
+ case 0x10: /* FF50 */
+ if (real_time_clock() == RTC_DISTO)
+ m_disto_msm6242->write(space,m_msm6242_rtc_address, data);
+ break;
+
+ case 0x11: /* FF51 */
+ if (real_time_clock() == RTC_DISTO)
+ m_msm6242_rtc_address = data & 0x0f;
+ break;
+ }
+}
+
+
+//**************************************************************************
+// DRAGON FDC
+//**************************************************************************
+
+static MACHINE_CONFIG_FRAGMENT(dragon_fdc)
+ MCFG_WD2797_ADD(WD_TAG, coco_wd17xx_interface)
+ MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(coco_floppy_interface)
+MACHINE_CONFIG_END
+
+
+ROM_START( dragon_fdc )
+ ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00)
+ ROM_LOAD_OPTIONAL( "ddos10.rom", 0x0000, 0x2000, CRC(b44536f6) SHA1(a8918c71d319237c1e3155bb38620acb114a80bc))
+ROM_END
+
+const device_type DRAGON_FDC = &device_creator<dragon_fdc_device>;
+
+//-------------------------------------------------
+// dragon_fdc_device - constructor
+//-------------------------------------------------
+dragon_fdc_device::dragon_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : coco_fdc_device(mconfig, type, name, tag, owner, clock, shortname, source)
+{
+}
+dragon_fdc_device::dragon_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : coco_fdc_device(mconfig, DRAGON_FDC, "Dragon FDC", tag, owner, clock, "dragon_fdc", __FILE__)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dragon_fdc_device::device_start()
+{
+ m_owner = dynamic_cast<cococart_slot_device *>(owner());
+ m_drq = 0;
+ m_wd17xx = subdevice(WD_TAG);
+ m_dskreg = 0x00;
+ m_intrq = 0;
+ m_msm6242_rtc_address = 0;
+}
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor dragon_fdc_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( dragon_fdc );
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *dragon_fdc_device::device_rom_region() const
+{
+ return ROM_NAME( dragon_fdc );
+}
+
+
+
+/*-------------------------------------------------
+ update_lines - Dragon specific disk
+ controller lines
+-------------------------------------------------*/
+
+void dragon_fdc_device::update_lines()
+{
+ /* set the NMI line */
+ m_owner->cart_set_line(COCOCART_LINE_NMI,
+ ((m_intrq != 0) && (m_dskreg & 0x20)) ? COCOCART_LINE_VALUE_ASSERT : COCOCART_LINE_VALUE_CLEAR);
+
+ /* set the CART line */
+ m_owner->cart_set_line(COCOCART_LINE_CART,
+ (m_drq != 0) ? COCOCART_LINE_VALUE_ASSERT : COCOCART_LINE_VALUE_CLEAR);
+}
+
+
+/*-------------------------------------------------
+ dskreg_w - function to write to
+ Dragon dskreg
+-------------------------------------------------*/
+
+void dragon_fdc_device::dskreg_w(UINT8 data)
+{
+ if (LOG_FDC)
+ {
+ logerror("fdc_dragon_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n",
+ data & 0x80 ? 'X' : 'x',
+ data & 0x40 ? 'X' : 'x',
+ data & 0x20 ? 'N' : 'n',
+ data & 0x10 ? 'P' : 'p',
+ data & 0x08 ? 'S' : 'D',
+ data & 0x04 ? 'M' : 'm',
+ data & 0x02 ? '1' : '0',
+ data & 0x01 ? '1' : '0',
+ data);
+ }
+
+ if (data & 0x04)
+ wd17xx_set_drive(m_wd17xx, data & 0x03);
+
+ wd17xx_dden_w(m_wd17xx, BIT(data, 3));
+ m_dskreg = data;
+}
+
+
+
+/*-------------------------------------------------
+ read
+-------------------------------------------------*/
+
+READ8_MEMBER(dragon_fdc_device::read)
+{
+ UINT8 result = 0;
+ switch(offset & 0xEF)
+ {
+ case 0:
+ result = wd17xx_status_r(m_wd17xx, space, 0);
+ break;
+ case 1:
+ result = wd17xx_track_r(m_wd17xx, space, 0);
+ break;
+ case 2:
+ result = wd17xx_sector_r(m_wd17xx, space, 0);
+ break;
+ case 3:
+ result = wd17xx_data_r(m_wd17xx, space, 0);
+ break;
+ }
+ return result;
+}
+
+
+
+/*-------------------------------------------------
+ write
+-------------------------------------------------*/
+
+WRITE8_MEMBER(dragon_fdc_device::write)
+{
+ switch(offset & 0xEF)
+ {
+ case 0:
+ wd17xx_command_w(m_wd17xx, space, 0, data);
+
+ /* disk head is encoded in the command byte */
+ /* Only for type 3 & 4 commands */
+ if (data & 0x80)
+ wd17xx_set_side(m_wd17xx, (data & 0x02) ? 1 : 0);
+ break;
+ case 1:
+ wd17xx_track_w(m_wd17xx, space, 0, data);
+ break;
+ case 2:
+ wd17xx_sector_w(m_wd17xx, space, 0, data);
+ break;
+ case 3:
+ wd17xx_data_w(m_wd17xx, space, 0, data);
+ break;
+ case 8: case 9: case 10: case 11:
+ case 12: case 13: case 14: case 15:
+ dskreg_w(data);
+ break;
+ };
+}
+
+//**************************************************************************
+// SDTANDY FDC
+//**************************************************************************
+
+ROM_START( sdtandy_fdc )
+ ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00)
+ ROM_LOAD_OPTIONAL( "sdtandy.rom", 0x0000, 0x2000, CRC(5d7779b7) SHA1(ca03942118f2deab2f6c8a89b8a4f41f2d0b94f1))
+ROM_END
+
+const device_type SDTANDY_FDC = &device_creator<sdtandy_fdc_device>;
+
+//-------------------------------------------------
+// sdtandy_fdc_device - constructor
+//-------------------------------------------------
+
+sdtandy_fdc_device::sdtandy_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : dragon_fdc_device(mconfig, SDTANDY_FDC, "SDTANDY FDC", tag, owner, clock, "sdtandy_fdc", __FILE__)
+{
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *sdtandy_fdc_device::device_rom_region() const
+{
+ return ROM_NAME( sdtandy_fdc );
+}
+
+//**************************************************************************
+// COCO FDC v1.1
+//**************************************************************************
+
+ROM_START( coco_fdc_v11 )
+ ROM_REGION(0x8000,"eprom",ROMREGION_ERASE00)
+ ROM_LOAD_OPTIONAL( "disk11.rom", 0x0000, 0x2000, CRC(0b9c5415) SHA1(10bdc5aa2d7d7f205f67b47b19003a4bd89defd1))
+ ROM_RELOAD(0x2000, 0x2000)
+ ROM_RELOAD(0x4000, 0x2000)
+ ROM_RELOAD(0x6000, 0x2000)
+ROM_END
+
+const device_type COCO_FDC_V11 = &device_creator<coco_fdc_v11_device>;
+
+//-------------------------------------------------
+// coco_fdc_v11_device - constructor
+//-------------------------------------------------
+
+coco_fdc_v11_device::coco_fdc_v11_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : coco_fdc_device(mconfig, COCO_FDC_V11, "CoCo FDC v1.1", tag, owner, clock, "coco_fdc_v11", __FILE__)
+{
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *coco_fdc_v11_device::device_rom_region() const
+{
+ return ROM_NAME( coco_fdc_v11 );
+}
+
+//**************************************************************************
+// CP400 FDC
+//**************************************************************************
+
+ROM_START( cp400_fdc )
+ ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00)
+ ROM_LOAD("cp400dsk.rom", 0x0000, 0x2000, CRC(e9ad60a0) SHA1(827697fa5b755f5dc1efb054cdbbeb04e405405b))
+ROM_END
+
+const device_type CP400_FDC = &device_creator<cp400_fdc_device>;
+
+//-------------------------------------------------
+// cp400_fdc_device - constructor
+//-------------------------------------------------
+
+cp400_fdc_device::cp400_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : coco_fdc_device(mconfig, CP400_FDC, "CP400 FDC", tag, owner, clock, "cp400_fdc", __FILE__)
+{
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *cp400_fdc_device::device_rom_region() const
+{
+ return ROM_NAME( cp400_fdc );
+}
diff --git a/src/emu/bus/coco/coco_fdc.h b/src/emu/bus/coco/coco_fdc.h
new file mode 100644
index 00000000000..6e82ca4646d
--- /dev/null
+++ b/src/emu/bus/coco/coco_fdc.h
@@ -0,0 +1,155 @@
+#pragma once
+
+#ifndef __COCO_FDC_H__
+#define __COCO_FDC_H__
+
+#include "emu.h"
+#include "cococart.h"
+#include "machine/msm6242.h"
+#include "machine/ds1315.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_rtc_type_t
+
+enum coco_rtc_type_t
+{
+ RTC_DISTO = 0x00,
+ RTC_CLOUD9 = 0x01,
+
+ RTC_NONE = 0xFF
+};
+
+// ======================> coco_fdc_device
+
+class coco_fdc_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ coco_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual const rom_entry *device_rom_region() const;
+
+ virtual UINT8* get_cart_base();
+
+ virtual void update_lines();
+ virtual void dskreg_w(UINT8 data);
+
+ void set_intrq(UINT8 val) { m_intrq = val; }
+ void set_drq(UINT8 val) { m_drq = val; }
+
+ DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
+ DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual DECLARE_READ8_MEMBER(read);
+ virtual DECLARE_WRITE8_MEMBER(write);
+
+ coco_rtc_type_t real_time_clock();
+
+ // internal state
+ cococart_slot_device *m_owner;
+
+ UINT8 m_dskreg;
+ UINT8 m_drq : 1;
+ UINT8 m_intrq : 1;
+
+ device_t *m_wd17xx; /* WD17xx */
+ ds1315_device *m_ds1315; /* DS1315 */
+
+ /* Disto RTC */
+ msm6242_device *m_disto_msm6242; /* 6242 RTC on Disto interface */
+ offs_t m_msm6242_rtc_address;
+};
+
+
+// device type definition
+extern const device_type COCO_FDC;
+
+// ======================> coco_fdc_v11_device
+
+class coco_fdc_v11_device :
+ public coco_fdc_device
+{
+public:
+ // construction/destruction
+ coco_fdc_v11_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+};
+
+
+// device type definition
+extern const device_type COCO_FDC_V11;
+
+// ======================> cp400_fdc_device
+
+class cp400_fdc_device :
+ public coco_fdc_device
+{
+public:
+ // construction/destruction
+ cp400_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+};
+
+
+// device type definition
+extern const device_type CP400_FDC;
+
+// ======================> dragon_fdc_device
+
+class dragon_fdc_device :
+ public coco_fdc_device
+{
+public:
+ // construction/destruction
+ dragon_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ dragon_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual const rom_entry *device_rom_region() const;
+ virtual void update_lines();
+ virtual void dskreg_w(UINT8 data);
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual DECLARE_READ8_MEMBER(read);
+ virtual DECLARE_WRITE8_MEMBER(write);
+private:
+};
+
+
+// device type definition
+extern const device_type DRAGON_FDC;
+
+// ======================> sdtandy_fdc_device
+
+class sdtandy_fdc_device :
+ public dragon_fdc_device
+{
+public:
+ // construction/destruction
+ sdtandy_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+};
+
+
+// device type definition
+extern const device_type SDTANDY_FDC;
+
+#endif /* __COCO_FDC_H__ */
diff --git a/src/emu/bus/coco/coco_multi.c b/src/emu/bus/coco/coco_multi.c
new file mode 100644
index 00000000000..0f71766b516
--- /dev/null
+++ b/src/emu/bus/coco/coco_multi.c
@@ -0,0 +1,266 @@
+/***************************************************************************
+
+ coco_multi.c
+
+ Code for emulating CoCo's Multi-Pak Interface
+
+ The Multi-Pak interface multiplexes all I/O lines from the Color
+ Computer's expansion port to four identical ports. All I/O lines
+ are continuously multiplexed except:
+
+ Pin 36 - *SCS
+ Pin 32 - *CTS
+ Pin 8 - *CART
+
+ These I/O lines are switched in one of two ways. First, is the front
+ panel, four position switch. When adjusted the switch will direct the
+ MPI to target these three I/O lines to the selected slot.
+
+ Second, the MPI will listen to writes to 0xff7f and respond accordingly:
+
+ bit 0 --\___ Target *SCS to this slot number
+ bit 1 --/
+ bit 2 ------ Ignore
+ bit 3 ------ Ignore
+ bit 4 --\___ Target *CTS and *CART to this slot number
+ bit 5 --/
+ bit 6 ------ Ignore
+ bit 7 ------ Ignore
+
+ After writing to 0xff7f, the position of the physical switch has no
+ effect until reset.
+
+ Reading is supported on 0xff7f. It will reflect the position of the
+ physical switch. Until data is written to 0xff7f, then it will only
+ reflect what has been written until a reset.
+
+ A common modification users of the OS-9 operating system made was to
+ tie all of the *CART pins together on the MPI motherboard. The *CART
+ line is connected to the 6809's IRQ line. This allowed any hardware
+ device in any slot to signal an IRQ to the CPU, no matter what the
+ switch position was. OS-9 was designed from the very start to poll
+ each device attached on every IRQ signal.
+
+ Because of sloppy address decoding the original MPI also responds to
+ $FF9F. No software is known to take advantage of this. After the
+ introduction of the CoCo 3, which uses $FF9F internally, Tandy provided
+ free upgrades to any MPI to fix this problem.
+
+
+***************************************************************************/
+
+#include "emu.h"
+#include "includes/coco.h"
+#include "coco_multi.h"
+#include "coco_232.h"
+#include "coco_orch90.h"
+#include "coco_pak.h"
+#include "coco_fdc.h"
+
+#define SLOT1_TAG "slot1"
+#define SLOT2_TAG "slot2"
+#define SLOT3_TAG "slot3"
+#define SLOT4_TAG "slot4"
+
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+static SLOT_INTERFACE_START(coco_cart_slot1_3)
+ SLOT_INTERFACE("rs232", COCO_232)
+ SLOT_INTERFACE("orch90", COCO_ORCH90)
+ SLOT_INTERFACE("banked_16k", COCO_PAK_BANKED)
+ SLOT_INTERFACE("pak", COCO_PAK)
+SLOT_INTERFACE_END
+static SLOT_INTERFACE_START(coco_cart_slot4)
+ SLOT_INTERFACE("fdcv11", COCO_FDC_V11)
+ SLOT_INTERFACE("rs232", COCO_232)
+ SLOT_INTERFACE("orch90", COCO_ORCH90)
+ SLOT_INTERFACE("banked_16k", COCO_PAK_BANKED)
+ SLOT_INTERFACE("pak", COCO_PAK)
+SLOT_INTERFACE_END
+
+WRITE_LINE_MEMBER(coco_multipak_device::multi_cart_w)
+{
+ cococart_slot_device *cart = dynamic_cast<cococart_slot_device *>(owner());
+ cart->m_cart_callback.writeline(this,state);
+}
+
+WRITE_LINE_MEMBER(coco_multipak_device::multi_nmi_w)
+{
+ cococart_slot_device *cart = dynamic_cast<cococart_slot_device *>(owner());
+ cart->m_nmi_callback.writeline(this,state);
+}
+
+WRITE_LINE_MEMBER(coco_multipak_device::multi_halt_w)
+{
+ cococart_slot_device *cart = dynamic_cast<cococart_slot_device *>(owner());
+ cart->m_halt_callback.writeline(this,state);
+}
+
+static const cococart_interface multi_cococart_interface =
+{
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, coco_multipak_device, multi_cart_w),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, coco_multipak_device, multi_nmi_w),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, coco_multipak_device, multi_halt_w)
+};
+
+static MACHINE_CONFIG_FRAGMENT(coco_multi)
+ MCFG_COCO_CARTRIDGE_ADD(SLOT1_TAG, multi_cococart_interface, coco_cart_slot1_3, NULL)
+ MCFG_COCO_CARTRIDGE_ADD(SLOT2_TAG, multi_cococart_interface, coco_cart_slot1_3, NULL)
+ MCFG_COCO_CARTRIDGE_ADD(SLOT3_TAG, multi_cococart_interface, coco_cart_slot1_3, NULL)
+ MCFG_COCO_CARTRIDGE_ADD(SLOT4_TAG, multi_cococart_interface, coco_cart_slot4, "fdcv11")
+MACHINE_CONFIG_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type COCO_MULTIPAK = &device_creator<coco_multipak_device>;
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_multipak_device - constructor
+//-------------------------------------------------
+
+coco_multipak_device::coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, COCO_MULTIPAK, "CoCo Multi-Pak Interface", tag, owner, clock, "coco_multipak", __FILE__),
+ device_cococart_interface( mconfig, *this )
+{
+}
+
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_multipak_device::device_start()
+{
+ // identify slots
+ m_slots[0] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT1_TAG));
+ m_slots[1] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT2_TAG));
+ m_slots[2] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT3_TAG));
+ m_slots[3] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT4_TAG));
+ m_owner = dynamic_cast<cococart_slot_device *>(owner());
+
+ // install $FF7F handler
+ write8_delegate wh = write8_delegate(FUNC(coco_multipak_device::ff7f_write), this);
+ machine().device(MAINCPU_TAG)->memory().space(AS_PROGRAM).install_write_handler(0xFF7F, 0xFF7F, wh);
+
+ // initial state
+ m_select = 0xFF;
+
+ // save state
+ save_item(NAME(m_select));
+}
+
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_multipak_device::device_reset()
+{
+ m_select = 0xFF;
+}
+
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor coco_multipak_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( coco_multi );
+}
+
+
+
+//-------------------------------------------------
+// get_cart_base
+//-------------------------------------------------
+
+UINT8* coco_multipak_device::get_cart_base()
+{
+ return active_cts_slot()->get_cart_base();
+}
+
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+READ8_MEMBER(coco_multipak_device::read)
+{
+ return active_scs_slot()->read(space,offset);
+}
+
+
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+WRITE8_MEMBER(coco_multipak_device::write)
+{
+ active_scs_slot()->write(space,offset,data);
+}
+
+
+
+//-------------------------------------------------
+// ff7f_write
+//-------------------------------------------------
+
+WRITE8_MEMBER(coco_multipak_device::ff7f_write)
+{
+ set_select(data);
+}
+
+
+
+//-------------------------------------------------
+// set_select
+//-------------------------------------------------
+
+void coco_multipak_device::set_select(UINT8 new_select)
+{
+ UINT8 xorval = m_select ^ new_select;
+ m_select = new_select;
+ if (xorval & 0x30)
+ cart_base_changed();
+}
+
+
+
+//-------------------------------------------------
+// active_scs_slot
+//-------------------------------------------------
+
+cococart_slot_device *coco_multipak_device::active_scs_slot(void)
+{
+ return m_slots[(m_select >> 0) & 0x03];
+}
+
+
+
+//-------------------------------------------------
+// active_cts_slot
+//-------------------------------------------------
+
+cococart_slot_device *coco_multipak_device::active_cts_slot(void)
+{
+ return m_slots[(m_select >> 4) & 0x03];
+}
diff --git a/src/emu/bus/coco/coco_multi.h b/src/emu/bus/coco/coco_multi.h
new file mode 100644
index 00000000000..f16ebe7cc5d
--- /dev/null
+++ b/src/emu/bus/coco/coco_multi.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+
+ coco_multi.h
+
+ Multi-Pak interface emulation
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __COCO_MULTI_H__
+#define __COCO_MULTI_H__
+
+#include "emu.h"
+#include "cococart.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_multipak_device
+
+class coco_multipak_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ virtual UINT8* get_cart_base();
+
+ DECLARE_WRITE_LINE_MEMBER(multi_cart_w);
+ DECLARE_WRITE_LINE_MEMBER(multi_nmi_w);
+ DECLARE_WRITE_LINE_MEMBER(multi_halt_w);
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual DECLARE_READ8_MEMBER(read);
+ virtual DECLARE_WRITE8_MEMBER(write);
+
+private:
+ // device references
+ cococart_slot_device *m_owner;
+ cococart_slot_device *m_slots[4];
+
+ // internal state
+ UINT8 m_select;
+
+ // methods
+ DECLARE_WRITE8_MEMBER(ff7f_write);
+ cococart_slot_device *active_scs_slot(void);
+ cococart_slot_device *active_cts_slot(void);
+ void set_select(UINT8 new_select);
+};
+
+
+// device type definition
+extern const device_type COCO_MULTIPAK;
+
+#endif /* __COCO_MULTI_H__ */
diff --git a/src/emu/bus/coco/coco_orch90.c b/src/emu/bus/coco/coco_orch90.c
new file mode 100644
index 00000000000..ba1aa29cf69
--- /dev/null
+++ b/src/emu/bus/coco/coco_orch90.c
@@ -0,0 +1,83 @@
+/***************************************************************************
+
+ orch90.c
+
+ Code for emulating the CoCo Orch-90 (Orchestra 90) sound cartridge
+
+ The Orch-90 was a simple sound cartridge; it had two 8-bit DACs
+ supporting stereo sound. The left channel was at $FF7A, and the right
+ channel was at $FF7B
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_orch90.h"
+#include "sound/dac.h"
+
+static MACHINE_CONFIG_FRAGMENT(coco_orch90)
+ MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+ MCFG_SOUND_ADD("dac_left", DAC, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0)
+ MCFG_SOUND_ADD("dac_right", DAC, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0)
+MACHINE_CONFIG_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type COCO_ORCH90 = &device_creator<coco_orch90_device>;
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_orch90_device - constructor
+//-------------------------------------------------
+
+coco_orch90_device::coco_orch90_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, COCO_ORCH90, "CoCo Orch-90 PAK", tag, owner, clock, "coco_orch90", __FILE__),
+ device_cococart_interface( mconfig, *this )
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_orch90_device::device_start()
+{
+ m_left_dac = subdevice<dac_device>("dac_left");
+ m_right_dac = subdevice<dac_device>("dac_right");
+}
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor coco_orch90_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( coco_orch90 );
+}
+
+/*-------------------------------------------------
+ write
+-------------------------------------------------*/
+
+WRITE8_MEMBER(coco_orch90_device::write)
+{
+ switch(offset)
+ {
+ case 0x3A:
+ /* left channel write */
+ m_left_dac->write_unsigned8(data);
+ break;
+
+ case 0x3B:
+ /* right channel write */
+ m_right_dac->write_unsigned8(data);
+ break;
+ }
+}
diff --git a/src/emu/bus/coco/coco_orch90.h b/src/emu/bus/coco/coco_orch90.h
new file mode 100644
index 00000000000..b7e27f43f32
--- /dev/null
+++ b/src/emu/bus/coco/coco_orch90.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#ifndef __COCO_ORCH90_H__
+#define __COCO_ORCH90_H__
+
+#include "emu.h"
+#include "sound/dac.h"
+#include "cococart.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_orch90_device
+
+class coco_orch90_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ coco_orch90_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual DECLARE_WRITE8_MEMBER(write);
+private:
+ // internal state
+ dac_device *m_left_dac;
+ dac_device *m_right_dac;
+};
+
+
+// device type definition
+extern const device_type COCO_ORCH90;
+
+#endif /* __COCO_ORCH90_H__ */
diff --git a/src/emu/bus/coco/coco_pak.c b/src/emu/bus/coco/coco_pak.c
new file mode 100644
index 00000000000..f106d7617cc
--- /dev/null
+++ b/src/emu/bus/coco/coco_pak.c
@@ -0,0 +1,178 @@
+/***************************************************************************
+
+ coco_pak.c
+
+ Code for emulating standard CoCo cartridges
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_pak.h"
+#include "includes/coco.h"
+#include "imagedev/cartslot.h"
+
+#define CARTSLOT_TAG "cart"
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+static MACHINE_CONFIG_FRAGMENT(coco_pak)
+MACHINE_CONFIG_END
+
+ROM_START( coco_pak )
+ ROM_REGION(0x8000,CARTSLOT_TAG,ROMREGION_ERASE00)
+ ROM_CART_LOAD(CARTSLOT_TAG, 0x0000, 0x8000, ROM_OPTIONAL | ROM_MIRROR)
+ROM_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type COCO_PAK = &device_creator<coco_pak_device>;
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_pak_device - constructor
+//-------------------------------------------------
+coco_pak_device::coco_pak_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_cococart_interface( mconfig, *this )
+{
+}
+
+coco_pak_device::coco_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, COCO_PAK, "CoCo Program PAK", tag, owner, clock, "cocopak", __FILE__),
+ device_cococart_interface( mconfig, *this )
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_pak_device::device_start()
+{
+ m_cart = dynamic_cast<device_image_interface *>(owner());
+ m_owner = dynamic_cast<cococart_slot_device *>(owner());
+}
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor coco_pak_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( coco_pak );
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *coco_pak_device::device_rom_region() const
+{
+ return ROM_NAME( coco_pak );
+}
+
+/*-------------------------------------------------
+ device_reset - device-specific startup
+-------------------------------------------------*/
+
+void coco_pak_device::device_reset()
+{
+ if (m_cart->exists()) {
+ cococart_line_value cart_line;
+
+ cart_line = machine().root_device().ioport(CART_AUTOSTART_TAG)->read_safe(0x01)
+ ? COCOCART_LINE_VALUE_Q
+ : COCOCART_LINE_VALUE_CLEAR;
+
+ /* normal CoCo PAKs tie their CART line to Q - the system clock */
+ m_owner->cart_set_line(COCOCART_LINE_CART,cart_line);
+ }
+}
+
+/*-------------------------------------------------
+ get_cart_base
+-------------------------------------------------*/
+
+UINT8* coco_pak_device::get_cart_base()
+{
+ return memregion(CARTSLOT_TAG)->base();
+}
+
+/***************************************************************************
+ BANKED CARTRIDGES
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type COCO_PAK_BANKED = &device_creator<coco_pak_banked_device>;
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_pak_device - constructor
+//-------------------------------------------------
+
+coco_pak_banked_device::coco_pak_banked_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : coco_pak_device(mconfig, COCO_PAK_BANKED, "CoCo Program PAK (Banked)", tag, owner, clock, "cocopak_banked", __FILE__)
+{
+}
+
+/*-------------------------------------------------
+ device_reset - device-specific startup
+-------------------------------------------------*/
+
+void coco_pak_banked_device::device_reset()
+{
+ coco_pak_device::device_reset();
+
+ banked_pak_set_bank(0);
+}
+
+/*-------------------------------------------------
+ banked_pak_set_bank - function to set the bank
+-------------------------------------------------*/
+
+void coco_pak_banked_device::banked_pak_set_bank(UINT32 bank)
+{
+ UINT64 pos;
+ UINT32 i;
+ UINT8 *rom = memregion(CARTSLOT_TAG)->base();
+ UINT32 rom_length = memregion(CARTSLOT_TAG)->bytes();
+
+ if (m_cart->exists()) {
+ pos = (bank * 0x4000) % m_cart->length();
+
+ for (i = 0; i < rom_length / 0x4000; i++)
+ {
+ m_cart->fseek(pos, SEEK_SET);
+ m_cart->fread(&rom[i * 0x4000], 0x4000);
+ }
+ }
+}
+
+/*-------------------------------------------------
+ write
+-------------------------------------------------*/
+
+WRITE8_MEMBER(coco_pak_banked_device::write)
+{
+ switch(offset)
+ {
+ case 0:
+ /* set the bank */
+ banked_pak_set_bank(data);
+ break;
+ }
+}
diff --git a/src/emu/bus/coco/coco_pak.h b/src/emu/bus/coco/coco_pak.h
new file mode 100644
index 00000000000..67f580f6daf
--- /dev/null
+++ b/src/emu/bus/coco/coco_pak.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#ifndef __COCO_PAK_H__
+#define __COCO_PAK_H__
+
+#include "emu.h"
+#include "cococart.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_pak_device
+
+class coco_pak_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ coco_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ coco_pak_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual const rom_entry *device_rom_region() const;
+
+ virtual UINT8* get_cart_base();
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // internal state
+ device_image_interface *m_cart;
+ cococart_slot_device *m_owner;
+};
+
+
+// device type definition
+extern const device_type COCO_PAK;
+
+// ======================> coco_pak_banked_device
+
+class coco_pak_banked_device :
+ public coco_pak_device
+{
+public:
+ // construction/destruction
+ coco_pak_banked_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_reset();
+ virtual DECLARE_WRITE8_MEMBER(write);
+private:
+ void banked_pak_set_bank(UINT32 bank);
+};
+
+
+// device type definition
+extern const device_type COCO_PAK_BANKED;
+#endif /* __COCO_PAK_H__ */
diff --git a/src/emu/bus/coco/cococart.c b/src/emu/bus/coco/cococart.c
new file mode 100644
index 00000000000..85c8844e0e0
--- /dev/null
+++ b/src/emu/bus/coco/cococart.c
@@ -0,0 +1,459 @@
+/*********************************************************************
+
+ cococart.c
+
+ CoCo/Dragon cartridge management
+
+*********************************************************************/
+
+#include "emu.h"
+#include "cococart.h"
+#include "emuopts.h"
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+#define LOG_LINE 0
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type COCOCART_SLOT = &device_creator<cococart_slot_device>;
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// cococart_slot_device - constructor
+//-------------------------------------------------
+cococart_slot_device::cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, COCOCART_SLOT, "CoCo Cartridge Slot", tag, owner, clock, "cococart_slot", __FILE__),
+ device_slot_interface(mconfig, *this),
+ device_image_interface(mconfig, *this)
+{
+}
+
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cococart_slot_device::device_start()
+{
+ for(int i=0; i<TIMER_POOL; i++ )
+ {
+ m_cart_line.timer[i] = timer_alloc(TIMER_CART);
+ m_nmi_line.timer[i] = timer_alloc(TIMER_NMI);
+ m_halt_line.timer[i] = timer_alloc(TIMER_HALT);
+ }
+
+ m_cart_line.timer_index = 0;
+ m_cart_line.delay = 0;
+ m_cart_line.value = COCOCART_LINE_VALUE_CLEAR;
+ m_cart_line.line = 0;
+ m_cart_line.q_count = 0;
+ m_cart_line.callback.resolve(m_cart_callback, *this);
+
+ m_nmi_line.timer_index = 0;
+ /* 12 allowed one more instruction to finished after the line is pulled */
+ m_nmi_line.delay = 12;
+ m_nmi_line.value = COCOCART_LINE_VALUE_CLEAR;
+ m_nmi_line.line = 0;
+ m_nmi_line.q_count = 0;
+ m_nmi_line.callback.resolve(m_nmi_callback, *this);
+
+ m_halt_line.timer_index = 0;
+ /* 6 allowed one more instruction to finished after the line is pulled */
+ m_halt_line.delay = 6;
+ m_halt_line.value = COCOCART_LINE_VALUE_CLEAR;
+ m_halt_line.line = 0;
+ m_halt_line.q_count = 0;
+ m_halt_line.callback.resolve(m_halt_callback, *this);
+
+ m_cart = dynamic_cast<device_cococart_interface *>(get_card_device());
+}
+
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cococart_slot_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cococart_interface *intf = reinterpret_cast<const cococart_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<cococart_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_cart_callback, 0, sizeof(m_cart_callback));
+ memset(&m_nmi_callback, 0, sizeof(m_nmi_callback));
+ memset(&m_halt_callback, 0, sizeof(m_halt_callback));
+ }
+
+ // set brief and instance name
+ update_names();
+}
+
+
+
+//-------------------------------------------------
+// device_timer - handle timer callbacks
+//-------------------------------------------------
+
+void cococart_slot_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch(id)
+ {
+ case TIMER_CART:
+ set_line("CART", m_cart_line, (cococart_line_value) param);
+ break;
+
+ case TIMER_NMI:
+ set_line("NMI", m_nmi_line, (cococart_line_value) param);
+ break;
+
+ case TIMER_HALT:
+ set_line("HALT", m_halt_line, (cococart_line_value) param);
+ break;
+ }
+}
+
+
+
+//-------------------------------------------------
+// coco_cartridge_r
+//-------------------------------------------------
+
+READ8_MEMBER(cococart_slot_device::read)
+{
+ UINT8 result = 0x00;
+ if (m_cart)
+ result = m_cart->read(space, offset);
+ return result;
+}
+
+
+//-------------------------------------------------
+// coco_cartridge_w
+//-------------------------------------------------
+
+WRITE8_MEMBER(cococart_slot_device::write)
+{
+ if (m_cart)
+ m_cart->write(space, offset, data);
+}
+
+
+
+//-------------------------------------------------
+// line_value_string
+//-------------------------------------------------
+
+static const char *line_value_string(cococart_line_value value)
+{
+ const char *s = NULL;
+ switch(value)
+ {
+ case COCOCART_LINE_VALUE_CLEAR:
+ s = "CLEAR";
+ break;
+ case COCOCART_LINE_VALUE_ASSERT:
+ s = "ASSERT";
+ break;
+ case COCOCART_LINE_VALUE_Q:
+ s = "Q";
+ break;
+ default:
+ fatalerror("Invalid value\n");
+ break;
+ }
+ return s;
+}
+
+
+
+//-------------------------------------------------
+// set_line
+//-------------------------------------------------
+
+void cococart_slot_device::set_line(const char *line_name, coco_cartridge_line &line, cococart_line_value value)
+{
+ if ((line.value != value) || (value == COCOCART_LINE_VALUE_Q))
+ {
+ line.value = value;
+
+ if (LOG_LINE)
+ logerror("[%s]: set_line(): %s <= %s\n", machine().describe_context(), line_name, line_value_string(value));
+ /* engage in a bit of gymnastics for this odious 'Q' value */
+ switch(line.value)
+ {
+ case COCOCART_LINE_VALUE_CLEAR:
+ line.line = 0x00;
+ line.q_count = 0;
+ break;
+
+ case COCOCART_LINE_VALUE_ASSERT:
+ line.line = 0x01;
+ line.q_count = 0;
+ break;
+
+ case COCOCART_LINE_VALUE_Q:
+ line.line = line.line ? 0x00 : 0x01;
+ if (line.q_count++ < 4)
+ set_line_timer(line, value);
+ break;
+ }
+
+ /* invoke the callback, if present */
+ if (!line.callback.isnull())
+ line.callback(line.line);
+ }
+}
+
+
+
+//-------------------------------------------------
+// set_line_timer()
+//-------------------------------------------------
+
+void cococart_slot_device::set_line_timer(coco_cartridge_line &line, cococart_line_value value)
+{
+ /* calculate delay; delay dependant on cycles per second */
+ attotime delay = (line.delay != 0)
+ ? machine().firstcpu->cycles_to_attotime(line.delay)
+ : attotime::zero;
+
+ line.timer[line.timer_index]->adjust(delay, (int) value);
+ line.timer_index = (line.timer_index + 1) % TIMER_POOL;
+}
+
+
+
+//-------------------------------------------------
+// twiddle_line_if_q
+//-------------------------------------------------
+
+void cococart_slot_device::twiddle_line_if_q(coco_cartridge_line &line)
+{
+ if (line.value == COCOCART_LINE_VALUE_Q)
+ {
+ line.q_count = 0;
+ set_line_timer(line, COCOCART_LINE_VALUE_Q);
+ }
+}
+
+
+
+//-------------------------------------------------
+// coco_cartridge_twiddle_q_lines - hack to
+// support twiddling the Q line
+//-------------------------------------------------
+
+void cococart_slot_device::twiddle_q_lines()
+{
+ twiddle_line_if_q(m_cart_line);
+ twiddle_line_if_q(m_nmi_line);
+ twiddle_line_if_q(m_halt_line);
+}
+
+
+//-------------------------------------------------
+// coco_cartridge_set_line
+//-------------------------------------------------
+
+void cococart_slot_device::cart_set_line(cococart_line line, cococart_line_value value)
+{
+ switch (line)
+ {
+ case COCOCART_LINE_CART:
+ set_line_timer(m_cart_line, value);
+ break;
+
+ case COCOCART_LINE_NMI:
+ set_line_timer(m_nmi_line, value);
+ break;
+
+ case COCOCART_LINE_HALT:
+ set_line_timer(m_halt_line, value);
+ break;
+
+ case COCOCART_LINE_SOUND_ENABLE:
+ // do nothing for now
+ break;
+ }
+}
+
+
+
+//-------------------------------------------------
+// get_cart_base
+//-------------------------------------------------
+
+UINT8* cococart_slot_device::get_cart_base()
+{
+ if (m_cart != NULL)
+ return m_cart->get_cart_base();
+ return NULL;
+}
+
+
+
+//-------------------------------------------------
+// set_cart_base_update
+//-------------------------------------------------
+
+void cococart_slot_device::set_cart_base_update(cococart_base_update_delegate update)
+{
+ if (m_cart != NULL)
+ m_cart->set_cart_base_update(update);
+}
+
+
+
+//-------------------------------------------------
+// call_load
+//-------------------------------------------------
+
+bool cococart_slot_device::call_load()
+{
+ if (m_cart)
+ {
+ offs_t read_length = 0;
+ if (software_entry() == NULL)
+ {
+ read_length = fread(m_cart->get_cart_base(), 0x8000);
+ }
+ else
+ {
+ read_length = get_software_region_length("rom");
+ memcpy(m_cart->get_cart_base(), get_software_region("rom"), read_length);
+ }
+ while(read_length < 0x8000)
+ {
+ offs_t len = MIN(read_length, 0x8000 - read_length);
+ memcpy(m_cart->get_cart_base() + read_length, m_cart->get_cart_base(), len);
+ read_length += len;
+ }
+ }
+ return IMAGE_INIT_PASS;
+}
+
+
+
+//-------------------------------------------------
+// call_softlist_load
+//-------------------------------------------------
+
+bool cococart_slot_device::call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry)
+{
+ load_software_part_region(*this, swlist, swname, start_entry );
+ return TRUE;
+}
+
+
+
+//-------------------------------------------------
+// get_default_card_software
+//-------------------------------------------------
+
+void cococart_slot_device::get_default_card_software(astring &result)
+{
+ software_get_default_slot(result, "pak");
+}
+
+
+
+
+//**************************************************************************
+// DEVICE COCO CART INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_cococart_interface - constructor
+//-------------------------------------------------
+
+device_cococart_interface::device_cococart_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device)
+{
+}
+
+
+
+//-------------------------------------------------
+// ~device_cococart_interface - destructor
+//-------------------------------------------------
+
+device_cococart_interface::~device_cococart_interface()
+{
+}
+
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+READ8_MEMBER(device_cococart_interface::read)
+{
+ return 0x00;
+}
+
+
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+WRITE8_MEMBER(device_cococart_interface::write)
+{
+}
+
+
+
+//-------------------------------------------------
+// get_cart_base
+//-------------------------------------------------
+
+UINT8* device_cococart_interface::get_cart_base()
+{
+ return NULL;
+}
+
+
+
+//-------------------------------------------------
+// set_cart_base_update
+//-------------------------------------------------
+
+void device_cococart_interface::set_cart_base_update(cococart_base_update_delegate update)
+{
+ m_update = update;
+}
+
+
+
+//-------------------------------------------------
+// cart_base_changed
+//-------------------------------------------------
+
+void device_cococart_interface::cart_base_changed(void)
+{
+ if (!m_update.isnull())
+ m_update(get_cart_base());
+}
diff --git a/src/emu/bus/coco/cococart.h b/src/emu/bus/coco/cococart.h
new file mode 100644
index 00000000000..e207ae26068
--- /dev/null
+++ b/src/emu/bus/coco/cococart.h
@@ -0,0 +1,175 @@
+/*********************************************************************
+
+ cococart.h
+
+ CoCo/Dragon cartridge management
+
+*********************************************************************/
+
+#ifndef __COCOCART_H__
+#define __COCOCART_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* TIMER_POOL: Must be power of two */
+#define TIMER_POOL 2
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* output lines on the CoCo cartridge slot */
+enum cococart_line
+{
+ COCOCART_LINE_CART, /* connects to PIA1 CB1 */
+ COCOCART_LINE_NMI, /* connects to NMI line on CPU */
+ COCOCART_LINE_HALT, /* connects to HALT line on CPU */
+ COCOCART_LINE_SOUND_ENABLE /* sound enable */
+};
+
+/* since we have a special value "Q" - we have to use a special enum here */
+enum cococart_line_value
+{
+ COCOCART_LINE_VALUE_CLEAR,
+ COCOCART_LINE_VALUE_ASSERT,
+ COCOCART_LINE_VALUE_Q
+};
+
+struct coco_cartridge_line
+{
+ emu_timer *timer[TIMER_POOL];
+ int timer_index;
+ int delay;
+ cococart_line_value value;
+ int line;
+ int q_count;
+ devcb_resolved_write_line callback;
+};
+
+// ======================> cococart_interface
+
+struct cococart_interface
+{
+ devcb_write_line m_cart_callback;
+ devcb_write_line m_nmi_callback;
+ devcb_write_line m_halt_callback;
+};
+
+// ======================> cococart_base_update_delegate
+
+// direct region update handler
+typedef delegate<void (UINT8 *)> cococart_base_update_delegate;
+
+
+// ======================> cococart_slot_device
+class device_cococart_interface;
+
+class cococart_slot_device : public device_t,
+ public cococart_interface,
+ public device_slot_interface,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_config_complete();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual bool call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry);
+
+ virtual iodevice_t image_type() const { return IO_CARTSLOT; }
+
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 0; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 1; }
+ virtual const char *image_interface() const { return "coco_cart"; }
+ virtual const char *file_extensions() const { return "ccc,rom"; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+
+ // slot interface overrides
+ virtual void get_default_card_software(astring &result);
+
+ // reading and writing to $FF40-$FF7F
+ DECLARE_READ8_MEMBER(read);
+ DECLARE_WRITE8_MEMBER(write);
+
+ // sets a cartridge line
+ void cart_set_line(cococart_line line, cococart_line_value value);
+
+ // hack to support twiddling the Q line
+ void twiddle_q_lines();
+
+ // cart base
+ UINT8* get_cart_base();
+ void set_cart_base_update(cococart_base_update_delegate update);
+
+private:
+ enum
+ {
+ TIMER_CART,
+ TIMER_NMI,
+ TIMER_HALT
+ };
+
+ // configuration
+ coco_cartridge_line m_cart_line;
+ coco_cartridge_line m_nmi_line;
+ coco_cartridge_line m_halt_line;
+
+ // cartridge
+ device_cococart_interface *m_cart;
+
+ // methods
+ void set_line(const char *line_name, coco_cartridge_line &line, cococart_line_value value);
+ void set_line_timer(coco_cartridge_line &line, cococart_line_value value);
+ void twiddle_line_if_q(coco_cartridge_line &line);
+};
+
+// device type definition
+extern const device_type COCOCART_SLOT;
+
+// ======================> device_cococart_interface
+
+class device_cococart_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_cococart_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_cococart_interface();
+
+ virtual DECLARE_READ8_MEMBER(read);
+ virtual DECLARE_WRITE8_MEMBER(write);
+
+ virtual UINT8* get_cart_base();
+ void set_cart_base_update(cococart_base_update_delegate update);
+
+protected:
+ void cart_base_changed(void);
+
+private:
+ cococart_base_update_delegate m_update;
+};
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_COCO_CARTRIDGE_ADD(_tag,_config,_slot_intf,_def_slot) \
+ MCFG_DEVICE_ADD(_tag, COCOCART_SLOT, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+#define MCFG_COCO_CARTRIDGE_REMOVE(_tag) \
+ MCFG_DEVICE_REMOVE(_tag)
+
+#endif /* __COCOCART_H__ */
diff --git a/src/emu/bus/compucolor/floppy.c b/src/emu/bus/compucolor/floppy.c
new file mode 100644
index 00000000000..62d8d2437b8
--- /dev/null
+++ b/src/emu/bus/compucolor/floppy.c
@@ -0,0 +1,255 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Compucolor Floppy Disk Drive emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "floppy.h"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type COMPUCOLOR_FLOPPY_PORT = &device_creator<compucolor_floppy_port_device>;
+const device_type COMPUCOLOR_FLOPPY = &device_creator<compucolor_floppy_device>;
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( compucolor_floppy_port_devices )
+//-------------------------------------------------
+
+SLOT_INTERFACE_START( compucolor_floppy_port_devices )
+ SLOT_INTERFACE("floppy", COMPUCOLOR_FLOPPY)
+SLOT_INTERFACE_END
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( compucolor_floppy_device::floppy_formats )
+ FLOPPY_CCVF_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( compucolor_floppies )
+//-------------------------------------------------
+
+static SLOT_INTERFACE_START( compucolor_floppies )
+ SLOT_INTERFACE_INTERNAL( "525sssd", FLOPPY_525_SSSD )
+SLOT_INTERFACE_END
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( compucolor_floppy )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( compucolor_floppy )
+ MCFG_FLOPPY_DRIVE_ADD("floppy", compucolor_floppies, "525sssd", compucolor_floppy_device::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor compucolor_floppy_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( compucolor_floppy );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_compucolor_floppy_port_interface - constructor
+//-------------------------------------------------
+
+device_compucolor_floppy_port_interface::device_compucolor_floppy_port_interface(const machine_config &mconfig, device_t &device)
+ : device_rs232_port_interface(mconfig, device)
+{
+}
+
+
+//-------------------------------------------------
+// compucolor_floppy_port_device - constructor
+//-------------------------------------------------
+
+compucolor_floppy_port_device::compucolor_floppy_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : rs232_port_device(mconfig, COMPUCOLOR_FLOPPY_PORT, "Compucolor Floppy Port", tag, owner, clock, "compclr_flp_port", __FILE__)
+{
+}
+
+
+//-------------------------------------------------
+// compucolor_floppy_device - constructor
+//-------------------------------------------------
+
+compucolor_floppy_device::compucolor_floppy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, COMPUCOLOR_FLOPPY, "Compucolor floppy", tag, owner, clock, "compclr_flp", __FILE__),
+ device_compucolor_floppy_port_interface(mconfig, *this),
+ m_floppy(*this, "floppy:525sssd"),
+ m_rw(1),
+ m_stp(0),
+ m_sel(1),
+ m_period(attotime::from_hz(9600*8))
+{
+ m_owner = dynamic_cast<compucolor_floppy_port_device *>(this->owner());
+}
+
+
+//-------------------------------------------------
+// device_config_complete -
+//-------------------------------------------------
+
+void compucolor_floppy_port_device::device_config_complete()
+{
+ rs232_port_device::device_config_complete();
+
+ m_dev = dynamic_cast<device_compucolor_floppy_port_interface *>(get_card_device());
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void compucolor_floppy_port_device::device_start()
+{
+ rs232_port_device::device_start();
+}
+
+
+void compucolor_floppy_device::device_start()
+{
+ // allocate timer
+ m_timer = timer_alloc();
+ m_timer->adjust(attotime::from_hz(9600*8), 0, attotime::from_hz(9600*8));
+
+ // state saving
+ save_item(NAME(m_rw));
+ save_item(NAME(m_stp));
+ save_item(NAME(m_sel));
+}
+
+
+//-------------------------------------------------
+// device_timer - handle timer events
+//-------------------------------------------------
+
+void compucolor_floppy_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (!m_sel && !m_rw)
+ {
+ output_rxd(read_bit());
+ }
+}
+
+
+//-------------------------------------------------
+// tx_w -
+//-------------------------------------------------
+
+void compucolor_floppy_device::tx(UINT8 state)
+{
+ if (!m_sel && m_rw)
+ {
+ write_bit(state);
+ }
+}
+
+
+//-------------------------------------------------
+// rw_w -
+//-------------------------------------------------
+
+void compucolor_floppy_device::rw_w(int state)
+{
+ if (!m_rw && state)
+ {
+ output_rxd(1);
+ }
+
+ m_rw = state;
+}
+
+
+//-------------------------------------------------
+// stepper_w -
+//-------------------------------------------------
+
+void compucolor_floppy_device::stepper_w(UINT8 data)
+{
+ if (!m_sel)
+ {
+ if ((m_stp == 1 && data == 4) || (m_stp == 2 && data == 1) || (m_stp == 4 && data == 2))
+ {
+ // step in
+ m_floppy->dir_w(1);
+ m_floppy->stp_w(0);
+ m_floppy->stp_w(1);
+ }
+ else if ((m_stp == 1 && data == 2) || (m_stp == 2 && data == 4) || (m_stp == 4 && data == 1))
+ {
+ // step out
+ m_floppy->dir_w(0);
+ m_floppy->stp_w(0);
+ m_floppy->stp_w(1);
+ }
+ }
+
+ m_stp = data;
+}
+
+
+//-------------------------------------------------
+// select_w -
+//-------------------------------------------------
+
+void compucolor_floppy_device::select_w(int state)
+{
+ m_floppy->mon_w(state);
+
+ if (!m_sel && state)
+ {
+ output_rxd(1);
+ }
+
+ m_sel = state;
+}
+
+
+//-------------------------------------------------
+// read_bit -
+//-------------------------------------------------
+
+bool compucolor_floppy_device::read_bit()
+{
+ attotime when = machine().time();
+ attotime edge = m_floppy->get_next_transition(when);
+ attotime next = when + m_period;
+
+ return (edge.is_never() || edge >= next) ? 0 : 1;
+}
+
+
+//-------------------------------------------------
+// write_bit -
+//-------------------------------------------------
+
+void compucolor_floppy_device::write_bit(bool bit)
+{
+ // TODO
+}
diff --git a/src/emu/bus/compucolor/floppy.h b/src/emu/bus/compucolor/floppy.h
new file mode 100644
index 00000000000..4d75e3ca923
--- /dev/null
+++ b/src/emu/bus/compucolor/floppy.h
@@ -0,0 +1,126 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Compucolor Floppy Disk Drive emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __COMPCLR_FLP__
+#define __COMPCLR_FLP__
+
+#include "bus/rs232/rs232.h"
+#include "formats/ccvf_dsk.h"
+#include "imagedev/floppy.h"
+
+
+
+//**************************************************************************
+// INTERFACE MACROS
+//**************************************************************************
+
+#define MCFG_COMPUCOLOR_FLOPPY_PORT_ADD(_tag, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, COMPUCOLOR_FLOPPY_PORT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> device_compucolor_floppy_port_interface
+
+class device_compucolor_floppy_port_interface : public device_rs232_port_interface
+{
+public:
+ device_compucolor_floppy_port_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_compucolor_floppy_port_interface() { }
+
+ virtual void rw_w(int state) = 0;
+ virtual void stepper_w(UINT8 data) = 0;
+ virtual void select_w(int state) = 0;
+};
+
+
+// ======================> compucolor_floppy_port_device
+
+class compucolor_floppy_port_device : public rs232_port_device
+{
+public:
+ compucolor_floppy_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~compucolor_floppy_port_device() { }
+
+ DECLARE_WRITE_LINE_MEMBER( rw_w ) { if (m_dev) m_dev->rw_w(state); }
+ void stepper_w(UINT8 data) { if (m_dev) m_dev->stepper_w(data); }
+ DECLARE_WRITE_LINE_MEMBER( select_w ) { if (m_dev) m_dev->select_w(state); }
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_config_complete();
+
+private:
+ device_compucolor_floppy_port_interface *m_dev;
+};
+
+
+// ======================> compucolor_floppy_device
+
+class compucolor_floppy_device : public device_t,
+ public device_compucolor_floppy_port_interface
+{
+public:
+ // construction/destruction
+ compucolor_floppy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_serial_port_interface overrides
+ virtual void tx(UINT8 state);
+
+ // device_compucolor_floppy_port_interface overrides
+ virtual void rw_w(int state);
+ virtual void stepper_w(UINT8 data);
+ virtual void select_w(int state);
+
+private:
+ required_device<floppy_image_device> m_floppy;
+
+ bool read_bit();
+ void write_bit(bool bit);
+
+ int m_rw;
+ int m_stp;
+ int m_sel;
+
+ attotime m_period;
+
+ compucolor_floppy_port_device *m_owner;
+
+ emu_timer *m_timer;
+};
+
+
+// device type definition
+extern const device_type COMPUCOLOR_FLOPPY_PORT;
+extern const device_type COMPUCOLOR_FLOPPY;
+
+
+// slot devices
+SLOT_INTERFACE_EXTERN( compucolor_floppy_port_devices );
+
+#endif
diff --git a/src/emu/bus/cpc/cpc_pds.c b/src/emu/bus/cpc/cpc_pds.c
new file mode 100644
index 00000000000..19cb0bd1031
--- /dev/null
+++ b/src/emu/bus/cpc/cpc_pds.c
@@ -0,0 +1,87 @@
+/*
+ * cpc_pds.c -- CPC interface hardware for the Programmers Development System
+ *
+ * Created on: 10/02/2014
+ */
+
+#include "emu.h"
+#include "cpc_pds.h"
+#include "includes/amstrad.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type CPC_PDS = &device_creator<cpc_pds_device>;
+
+
+static Z80PIO_INTERFACE( pio_intf )
+{
+ DEVCB_NULL, //m_out_int_cb;
+
+ DEVCB_NULL, //m_in_pa_cb;
+ DEVCB_NULL, //m_out_pa_cb;
+ DEVCB_NULL, //m_out_ardy_cb;
+
+ DEVCB_NULL, //m_in_pb_cb;
+ DEVCB_NULL, //m_out_pb_cb;
+ DEVCB_NULL, //m_out_brdy_cb;
+};
+
+static MACHINE_CONFIG_FRAGMENT( cpc_pds )
+ MCFG_Z80PIO_ADD("pio",XTAL_4MHz,pio_intf) // no clock on the PCB, so will presume that it uses the CPC's clock
+
+ // no pass-through seen on remake PCBs, unknown if actual hardware had a pass-through port or not
+MACHINE_CONFIG_END
+
+
+machine_config_constructor cpc_pds_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( cpc_pds );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+cpc_pds_device::cpc_pds_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, CPC_PDS, "Programmers Development System (CPC Target)", tag, owner, clock, "cpc_pds", __FILE__),
+ device_cpc_expansion_card_interface(mconfig, *this),
+ m_pio(*this,"pio")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cpc_pds_device::device_start()
+{
+ device_t* cpu = machine().device("maincpu");
+ address_space& space = cpu->memory().space(AS_IO);
+ m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
+
+ space.install_readwrite_handler(0xfbec,0xfbef,0,0,read8_delegate(FUNC(cpc_pds_device::pio_r),this),write8_delegate(FUNC(cpc_pds_device::pio_w),this));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void cpc_pds_device::device_reset()
+{
+ // TODO
+}
+
+
+READ8_MEMBER(cpc_pds_device::pio_r)
+{
+ return m_pio->read(space,offset);
+}
+
+WRITE8_MEMBER(cpc_pds_device::pio_w)
+{
+ m_pio->write(space,offset,data);
+}
diff --git a/src/emu/bus/cpc/cpc_pds.h b/src/emu/bus/cpc/cpc_pds.h
new file mode 100644
index 00000000000..74f79add041
--- /dev/null
+++ b/src/emu/bus/cpc/cpc_pds.h
@@ -0,0 +1,56 @@
+/*
+ * cpc_pds.h -- CPC interface hardware for the Programmers Development System
+ *
+ * Created on: 10/02/2014
+ *
+ * Contains a Z80 PIO used to communicate with PC-side hardware (8-bit ISA card containing an 8255 PPI),
+ * connected via a 16-pin cable. Although it would seem that the C64 has a different cable that directly
+ * interfaces with the user port.
+ *
+ * The Z80 PIO is mapped to the CPC at:
+ * FBEC Z80 PIO Port A Data (8bit data to/from PC)
+ * FBED Z80 PIO Port B Data (handshake to/from PC)
+ * FBEE Z80 PIO Port A Control
+ * FBEF Z80 PIO Port B Control
+ *
+ * More info: http://cpcwiki.eu/index.php/PDS_development_system
+ *
+ * TODO: Come up with some way to connect two instances of MESS, one running the PC software, the other
+ * running the target side
+ */
+
+#ifndef CPC_PDS_H_
+#define CPC_PDS_H_
+
+#include "emu.h"
+#include "cpcexp.h"
+#include "machine/z80pio.h"
+
+class cpc_pds_device : public device_t,
+ public device_cpc_expansion_card_interface
+{
+public:
+ // construction/destruction
+ cpc_pds_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ DECLARE_READ8_MEMBER(pio_r);
+ DECLARE_WRITE8_MEMBER(pio_w);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ cpc_expansion_slot_device *m_slot;
+
+ required_device<z80pio_device> m_pio;
+};
+
+// device type definition
+extern const device_type CPC_PDS;
+
+#endif /* CPC_PDS_H_ */
diff --git a/src/emu/bus/cpc/cpc_rom.c b/src/emu/bus/cpc/cpc_rom.c
new file mode 100644
index 00000000000..ddf33f318e3
--- /dev/null
+++ b/src/emu/bus/cpc/cpc_rom.c
@@ -0,0 +1,136 @@
+/*
+ * cpc_rom.c
+ * Amstrad CPC mountable ROM image device
+ *
+ */
+
+#include "emu.h"
+#include "cpc_rom.h"
+#include "includes/amstrad.h"
+
+const device_type CPC_ROM = &device_creator<cpc_rom_device>;
+
+
+//**************************************************************************
+// DEVICE CONFIG INTERFACE
+//**************************************************************************
+
+CPC_EXPANSION_INTERFACE(sub_exp_intf)
+{
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, irq_w),
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, nmi_w),
+ DEVCB_NULL, // RESET
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, romdis_w), // ROMDIS
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, romen_w) // /ROMEN
+};
+
+// device machine config
+static MACHINE_CONFIG_FRAGMENT( cpc_rom )
+ MCFG_ROMSLOT_ADD("rom1")
+ MCFG_ROMSLOT_ADD("rom2")
+ MCFG_ROMSLOT_ADD("rom3")
+ MCFG_ROMSLOT_ADD("rom4")
+ MCFG_ROMSLOT_ADD("rom5")
+ MCFG_ROMSLOT_ADD("rom6")
+
+ // pass-through
+ MCFG_CPC_EXPANSION_SLOT_ADD("exp",sub_exp_intf,cpc_exp_cards,NULL)
+
+MACHINE_CONFIG_END
+
+
+machine_config_constructor cpc_rom_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( cpc_rom );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+cpc_rom_device::cpc_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, CPC_ROM, "ROM Box", tag, owner, clock, "cpc_rom", __FILE__),
+ device_cpc_expansion_card_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cpc_rom_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void cpc_rom_device::device_reset()
+{
+}
+
+
+/*** ROM image device ***/
+
+// device type definition
+const device_type ROMSLOT = &device_creator<rom_image_device>;
+
+//-------------------------------------------------
+// rom_image_device - constructor
+//-------------------------------------------------
+
+rom_image_device::rom_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ROMSLOT, "ROM image", tag, owner, clock, "rom_image", __FILE__),
+ device_image_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// rom_image_device - destructor
+//-------------------------------------------------
+
+rom_image_device::~rom_image_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void rom_image_device::device_start()
+{
+ m_base = NULL;
+}
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_LOAD( rom )
+-------------------------------------------------*/
+bool rom_image_device::call_load()
+{
+ device_image_interface* image = this;
+ UINT64 size = image->length();
+
+ m_base = (UINT8*)malloc(16384);
+ if(size <= 16384)
+ {
+ image->fread(m_base,size);
+ }
+ else
+ {
+ image->fseek(size-16384,SEEK_SET);
+ image->fread(m_base,16384);
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_UNLOAD( rom )
+-------------------------------------------------*/
+void rom_image_device::call_unload()
+{
+ free(m_base);
+ m_base = NULL;
+}
diff --git a/src/emu/bus/cpc/cpc_rom.h b/src/emu/bus/cpc/cpc_rom.h
new file mode 100644
index 00000000000..c00f99f7f50
--- /dev/null
+++ b/src/emu/bus/cpc/cpc_rom.h
@@ -0,0 +1,88 @@
+/*
+ * cpc_rom.h
+ * Amstrad CPC mountable ROM image device
+ *
+ */
+
+#ifndef CPC_ROM_H_
+#define CPC_ROM_H_
+
+#include "emu.h"
+#include "cpcexp.h"
+
+/*** ROM image device ***/
+
+// ======================> rom_image_device
+
+class rom_image_device : public device_t,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ rom_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~rom_image_device();
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual void call_unload();
+
+ virtual iodevice_t image_type() const { return IO_ROM; }
+
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 0; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 1; }
+ virtual const char *image_interface() const { return "cpc_rom"; }
+ virtual const char *file_extensions() const { return "rom,bin"; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+
+ UINT8* base() { return m_base; }
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete() { update_names(); }
+ virtual void device_start();
+
+private:
+ UINT8* m_base;
+};
+
+
+// device type definition
+extern const device_type ROMSLOT;
+
+
+#define MCFG_ROMSLOT_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, ROMSLOT, 0)
+
+/*** ROM box device ***/
+
+class cpc_rom_device : public device_t,
+ public device_cpc_expansion_card_interface
+{
+public:
+ // construction/destruction
+ cpc_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ UINT8* base(UINT8 slot) { if(slot >=1 && slot <= 6) return m_rom[slot]->base(); else return NULL; }
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ //cpc_expansion_slot_device *m_slot;
+
+ rom_image_device* m_rom[6];
+};
+
+// device type definition
+extern const device_type CPC_ROM;
+
+
+#endif
diff --git a/src/emu/bus/cpc/cpc_ssa1.c b/src/emu/bus/cpc/cpc_ssa1.c
new file mode 100644
index 00000000000..7e855493c66
--- /dev/null
+++ b/src/emu/bus/cpc/cpc_ssa1.c
@@ -0,0 +1,216 @@
+/*
+ * cpc_ssa1.c -- Amstrad SSA-1 Speech Synthesiser, dk'Tronics Speech Synthesiser
+ *
+ * Created on: 16/07/2011
+ *
+ */
+
+
+#include "emu.h"
+#include "cpc_ssa1.h"
+#include "includes/amstrad.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type CPC_SSA1 = &device_creator<cpc_ssa1_device>;
+const device_type CPC_DKSPEECH = &device_creator<cpc_dkspeech_device>;
+
+CPC_EXPANSION_INTERFACE(sub_exp_intf)
+{
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, irq_w),
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, nmi_w),
+ DEVCB_NULL, // RESET
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, romdis_w), // ROMDIS
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, romen_w) // /ROMEN
+};
+
+//-------------------------------------------------
+// device I/O handlers
+//-------------------------------------------------
+
+READ8_MEMBER(cpc_ssa1_device::ssa1_r)
+{
+ UINT8 ret = 0xff;
+
+ if(get_sby() == 0)
+ ret &= ~0x80;
+
+ if(get_lrq() != 0)
+ ret &= ~0x40;
+
+ return ret;
+}
+
+WRITE8_MEMBER(cpc_ssa1_device::ssa1_w)
+{
+ m_sp0256_device->ald_w(space, 0, data);
+}
+
+READ8_MEMBER(cpc_dkspeech_device::dkspeech_r)
+{
+ UINT8 ret = 0xff;
+
+ // SBY is not connected
+
+ if(get_lrq() != 0)
+ ret &= ~0x80;
+
+ return ret;
+}
+
+WRITE8_MEMBER(cpc_dkspeech_device::dkspeech_w)
+{
+ m_sp0256_device->ald_w(space, 0, data & 0x3f);
+}
+
+WRITE_LINE_MEMBER(cpc_ssa1_device::lrq_cb)
+{
+ set_lrq(state);
+}
+
+WRITE_LINE_MEMBER(cpc_ssa1_device::sby_cb)
+{
+ set_sby(state);
+}
+
+WRITE_LINE_MEMBER(cpc_dkspeech_device::lrq_cb)
+{
+ set_lrq(state);
+}
+
+WRITE_LINE_MEMBER(cpc_dkspeech_device::sby_cb)
+{
+ set_sby(state);
+}
+
+//-------------------------------------------------
+// Device ROM definition
+//-------------------------------------------------
+
+// Has no actual ROM, just that internal to the SP0256
+ROM_START( cpc_ssa1 )
+ ROM_REGION( 0x10000, "sp0256", 0 )
+ ROM_LOAD( "sp0256-al2.bin", 0x1000, 0x0800, CRC(b504ac15) SHA1(e60fcb5fa16ff3f3b69d36c7a6e955744d3feafc) )
+ROM_END
+
+// Available in ROM and cassette versions. For now, we'll let the user choose to load the software via ROM (using a ROM box slot device) or cassette.
+ROM_START( cpc_dkspeech )
+ ROM_REGION( 0x10000, "sp0256", 0 )
+ ROM_LOAD( "sp0256-al2.bin", 0x1000, 0x0800, CRC(b504ac15) SHA1(e60fcb5fa16ff3f3b69d36c7a6e955744d3feafc) )
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *cpc_ssa1_device::device_rom_region() const
+{
+ return ROM_NAME( cpc_ssa1 );
+}
+
+const rom_entry *cpc_dkspeech_device::device_rom_region() const
+{
+ return ROM_NAME( cpc_dkspeech );
+}
+
+// device machine config
+static MACHINE_CONFIG_FRAGMENT( cpc_ssa1 )
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("sp0256",SP0256,XTAL_3_12MHz)
+ MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(cpc_ssa1_device, lrq_cb))
+ MCFG_SP0256_STANDBY_CB(WRITELINE(cpc_ssa1_device, sby_cb))
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
+
+ // pass-through
+ MCFG_CPC_EXPANSION_SLOT_ADD("exp",sub_exp_intf,cpc_exp_cards,NULL)
+
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_FRAGMENT( cpc_dkspeech )
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("sp0256",SP0256,XTAL_4MHz) // uses the CPC's clock from pin 50 of the expansion port
+ MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(cpc_dkspeech_device, lrq_cb))
+ MCFG_SP0256_STANDBY_CB(WRITELINE(cpc_dkspeech_device, sby_cb))
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
+
+ // pass-through
+ MCFG_CPC_EXPANSION_SLOT_ADD("exp",sub_exp_intf,cpc_exp_cards,NULL)
+
+MACHINE_CONFIG_END
+
+machine_config_constructor cpc_ssa1_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( cpc_ssa1 );
+}
+
+machine_config_constructor cpc_dkspeech_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( cpc_dkspeech );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+cpc_ssa1_device::cpc_ssa1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, CPC_SSA1, "SSA-1", tag, owner, clock, "cpc_ssa1", __FILE__),
+ device_cpc_expansion_card_interface(mconfig, *this),
+ m_lrq(1),
+ m_sp0256_device(*this,"sp0256")
+{
+}
+
+cpc_dkspeech_device::cpc_dkspeech_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, CPC_DKSPEECH, "DK'Tronics Speech Synthesiser", tag, owner, clock, "cpc_dkspeech", __FILE__),
+ device_cpc_expansion_card_interface(mconfig, *this),
+ m_lrq(1),
+ m_sp0256_device(*this,"sp0256")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cpc_ssa1_device::device_start()
+{
+ device_t* cpu = machine().device("maincpu");
+ address_space& space = cpu->memory().space(AS_IO);
+ m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
+
+ m_rom = memregion("sp0256")->base();
+
+// m_sp0256_device = subdevice("sp0256");
+
+ space.install_readwrite_handler(0xfaee,0xfaee,0,0,read8_delegate(FUNC(cpc_ssa1_device::ssa1_r),this),write8_delegate(FUNC(cpc_ssa1_device::ssa1_w),this));
+ space.install_readwrite_handler(0xfbee,0xfbee,0,0,read8_delegate(FUNC(cpc_ssa1_device::ssa1_r),this),write8_delegate(FUNC(cpc_ssa1_device::ssa1_w),this));
+}
+
+void cpc_dkspeech_device::device_start()
+{
+ device_t* cpu = machine().device("maincpu");
+ address_space& space = cpu->memory().space(AS_IO);
+ m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
+
+ m_rom = memregion("sp0256")->base();
+
+// m_sp0256_device = subdevice("sp0256");
+
+ space.install_readwrite_handler(0xfbfe,0xfbfe,0,0,read8_delegate(FUNC(cpc_dkspeech_device::dkspeech_r),this),write8_delegate(FUNC(cpc_dkspeech_device::dkspeech_w),this));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void cpc_ssa1_device::device_reset()
+{
+ m_sp0256_device->reset();
+}
+
+void cpc_dkspeech_device::device_reset()
+{
+ m_sp0256_device->reset();
+}
diff --git a/src/emu/bus/cpc/cpc_ssa1.h b/src/emu/bus/cpc/cpc_ssa1.h
new file mode 100644
index 00000000000..e3d1dd7a26a
--- /dev/null
+++ b/src/emu/bus/cpc/cpc_ssa1.h
@@ -0,0 +1,126 @@
+/*
+ * cpc_ssa1.h -- Amstrad SSA-1 Speech Synthesiser, dk'Tronics Speech Synthesiser
+ *
+ * Created on: 16/07/2011
+ *
+ * Amstrad SSA-1 - SP0256-AL2 based Speech Synthesiser and Sound Amplifier
+ *
+ * Uses on-board resonator, clocked at 3.12MHz
+ *
+ * Decodes only I/O lines A10, A4 and A0
+ * Official I/O ports:
+ * &FBEE (read)
+ * - bit 7: SP0256 Status 1 (SBY)
+ * - bit 6: SP0256 Status 2 (/LRQ)
+ *
+ * &FBEE (write)
+ * - bits 7-0: SP0256 Allophone number (must be 0x00 to 0x3f, however, all data lines are hooked up)
+ *
+ * &FAEE (write)
+ * - same as above, used because of a bug in the driver software, but still works due to the way the I/O ports are
+ * decoded on the CPC.
+ *
+ * More info and PCB pics at http://www.cpcwiki.eu/index.php/Amstrad_SSA-1_Speech_Synthesizer
+ *
+ *
+ * dk'Tronics Speech Synthesiser - SP0256-AL2 based speech synthesiser
+ *
+ * Uses the CPC's clock of 4MHz from pin 50 of the expansion port, gives faster and higher pitched voices than the SSA-1
+ *
+ * Official I/O ports:
+ * &FBFE (read)
+ * - bit 7: SP0256 Status 2 (/LRQ)
+ *
+ * &FBFE (write)
+ * - bits 5-0: SP0256 Allophone number
+ *
+ * More info and PCB pics at http://www.cpcwiki.eu/index.php/Dk%27tronics_Speech_Synthesizer
+ *
+ */
+
+#ifndef CPC_SSA1_H_
+#define CPC_SSA1_H_
+
+
+#include "emu.h"
+#include "cpcexp.h"
+#include "sound/sp0256.h"
+
+class cpc_ssa1_device : public device_t,
+ public device_cpc_expansion_card_interface
+{
+public:
+ // construction/destruction
+ cpc_ssa1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ void set_lrq(UINT8 state) { m_lrq = state; }
+ UINT8 get_lrq() { return m_lrq; }
+ void set_sby(UINT8 state) { m_sby = state; }
+ UINT8 get_sby() { return m_sby; }
+
+ DECLARE_READ8_MEMBER(ssa1_r);
+ DECLARE_WRITE8_MEMBER(ssa1_w);
+ DECLARE_WRITE_LINE_MEMBER(lrq_cb);
+ DECLARE_WRITE_LINE_MEMBER(sby_cb);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ cpc_expansion_slot_device *m_slot;
+
+ UINT8 *m_rom;
+ UINT8 m_lrq;
+ UINT8 m_sby;
+
+ required_device<sp0256_device> m_sp0256_device;
+};
+
+class cpc_dkspeech_device : public device_t,
+ public device_cpc_expansion_card_interface
+{
+public:
+ // construction/destruction
+ cpc_dkspeech_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ void set_lrq(UINT8 state) { m_lrq = state; }
+ UINT8 get_lrq() { return m_lrq; }
+ void set_sby(UINT8 state) { m_sby = state; }
+ UINT8 get_sby() { return m_sby; }
+
+ DECLARE_READ8_MEMBER(dkspeech_r);
+ DECLARE_WRITE8_MEMBER(dkspeech_w);
+ DECLARE_WRITE_LINE_MEMBER(lrq_cb);
+ DECLARE_WRITE_LINE_MEMBER(sby_cb);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ cpc_expansion_slot_device *m_slot;
+
+ UINT8 *m_rom;
+ UINT8 m_lrq;
+ UINT8 m_sby;
+
+ required_device<sp0256_device> m_sp0256_device;
+};
+
+// device type definition
+extern const device_type CPC_SSA1;
+extern const device_type CPC_DKSPEECH;
+
+
+#endif /* CPC_SSA1_H_ */
diff --git a/src/emu/bus/cpc/cpcexp.c b/src/emu/bus/cpc/cpcexp.c
new file mode 100644
index 00000000000..fc00a6248e1
--- /dev/null
+++ b/src/emu/bus/cpc/cpcexp.c
@@ -0,0 +1,109 @@
+/*
+ * cpcexp.c -- Amstrad CPC Expansion port
+ *
+ * Created on: 16/07/2011
+ *
+ */
+
+
+#include "emu.h"
+#include "emuopts.h"
+#include "cpcexp.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type CPC_EXPANSION_SLOT = &device_creator<cpc_expansion_slot_device>;
+
+
+//**************************************************************************
+// DEVICE CPC_EXPANSION CARD INTERFACE
+//**************************************************************************
+
+
+device_cpc_expansion_card_interface::device_cpc_expansion_card_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig,device)
+{
+}
+
+
+device_cpc_expansion_card_interface::~device_cpc_expansion_card_interface()
+{
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+cpc_expansion_slot_device::cpc_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, CPC_EXPANSION_SLOT, "Amstrad CPC expansion port", tag, owner, clock, "cpc_expansion_slot", __FILE__),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+cpc_expansion_slot_device::~cpc_expansion_slot_device()
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cpc_expansion_slot_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cpc_expansion_slot_interface *intf = reinterpret_cast<const cpc_expansion_slot_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<cpc_expansion_slot_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb));
+ memset(&m_out_nmi_cb, 0, sizeof(m_out_nmi_cb));
+ memset(&m_out_reset_cb, 0, sizeof(m_out_reset_cb));
+ memset(&m_out_romdis_cb, 0, sizeof(m_out_romdis_cb));
+ memset(&m_out_romen_cb, 0, sizeof(m_out_romen_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cpc_expansion_slot_device::device_start()
+{
+ m_card = dynamic_cast<device_cpc_expansion_card_interface *>(get_card_device());
+
+ // resolve callbacks
+ m_out_irq_func.resolve(m_out_irq_cb, *this);
+ m_out_nmi_func.resolve(m_out_nmi_cb, *this);
+ m_out_reset_func.resolve(m_out_reset_cb, *this);
+ m_out_romdis_func.resolve(m_out_romdis_cb, *this);
+ m_out_romen_func.resolve(m_out_romen_cb, *this);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void cpc_expansion_slot_device::device_reset()
+{
+}
+
+
+WRITE_LINE_MEMBER( cpc_expansion_slot_device::irq_w ) { m_out_irq_func(state); }
+WRITE_LINE_MEMBER( cpc_expansion_slot_device::nmi_w ) { m_out_nmi_func(state); }
+WRITE_LINE_MEMBER( cpc_expansion_slot_device::reset_w ) { m_out_reset_func(state); }
+WRITE_LINE_MEMBER( cpc_expansion_slot_device::romdis_w ) { m_out_romdis_func(state); }
+WRITE_LINE_MEMBER( cpc_expansion_slot_device::romen_w ) { m_out_romen_func(state); }
diff --git a/src/emu/bus/cpc/cpcexp.h b/src/emu/bus/cpc/cpcexp.h
new file mode 100644
index 00000000000..3e4df4f51a8
--- /dev/null
+++ b/src/emu/bus/cpc/cpcexp.h
@@ -0,0 +1,131 @@
+/*
+ * cpcexp.h -- Amstrad CPC Expansion port
+ *
+ * Created on: 16/07/2011
+ *
+ * Pinout from CPC6128 User's Manual
+ * SOUND 1 2 GND
+ * A15 3 4 A14
+ * A13 5 6 A12
+ * A11 7 8 A10
+ * A9 9 10 A8
+ * A7 11 12 A6
+ * A5 13 14 A4
+ * A3 15 16 A2
+ * A1 17 18 A0
+ * D7 19 20 D6
+ * D5 21 22 D4
+ * D3 23 24 D2
+ * D1 25 26 D0
+ * +5v 27 28 _MREQ
+ * _M1 29 30 _RFSH
+ * _IORQ 31 32 _RD
+ * _WR 33 34 _HALT
+ * _INT 35 36 _NMI
+ * _BUSR2 37 38 _BUSAK
+ * READY 39 40 _BUS RESET
+ * _RESET 41 42 _ROMEN
+ * ROMDIS 43 44 _RAMRD
+ * RAMDIS 45 46 CURSOR
+ * L.PEN 47 48 _EXP
+ * GND 49 50 CLOCK
+ */
+
+#pragma once
+
+#ifndef CPCEXP_H_
+#define CPCEXP_H_
+
+#include "emu.h"
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define CPC_EXP_SLOT_TAG "cpcexp"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define CPC_EXPANSION_INTERFACE(_name) \
+ const cpc_expansion_slot_interface (_name) =
+
+
+#define MCFG_CPC_EXPANSION_SLOT_ADD(_tag, _config, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, CPC_EXPANSION_SLOT, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// expansion slot interface
+
+struct cpc_expansion_slot_interface
+{
+ devcb_write_line m_out_irq_cb;
+ devcb_write_line m_out_nmi_cb;
+ devcb_write_line m_out_reset_cb;
+ devcb_write_line m_out_romdis_cb;
+ devcb_write_line m_out_romen_cb;
+};
+
+
+// ======================> device_cpc_expansion_card_interface
+
+// class representing interface-specific live cpc_expansion card
+class device_cpc_expansion_card_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_cpc_expansion_card_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_cpc_expansion_card_interface();
+
+ // reset
+ virtual void cpc_reset_w() { };
+};
+
+
+// ======================> cpc_expansion_slot_device
+
+class cpc_expansion_slot_device : public device_t,
+ public cpc_expansion_slot_interface,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ cpc_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~cpc_expansion_slot_device();
+
+ DECLARE_WRITE_LINE_MEMBER( irq_w );
+ DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ DECLARE_WRITE_LINE_MEMBER( reset_w );
+ DECLARE_WRITE_LINE_MEMBER( romdis_w );
+ DECLARE_WRITE_LINE_MEMBER( romen_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_config_complete();
+
+ devcb_resolved_write_line m_out_irq_func;
+ devcb_resolved_write_line m_out_nmi_func;
+ devcb_resolved_write_line m_out_reset_func;
+ devcb_resolved_write_line m_out_romdis_func;
+ devcb_resolved_write_line m_out_romen_func;
+
+ device_cpc_expansion_card_interface *m_card;
+};
+
+
+// device type definition
+extern const device_type CPC_EXPANSION_SLOT;
+
+#endif /* CPCEXP_H_ */
diff --git a/src/emu/bus/cpc/mface2.c b/src/emu/bus/cpc/mface2.c
new file mode 100644
index 00000000000..742a8365f33
--- /dev/null
+++ b/src/emu/bus/cpc/mface2.c
@@ -0,0 +1,348 @@
+/*
+ * mface2.c -- Romantic Robot Multiface II expansion device for the Amstrad CPC/CPC+
+ *
+ * Created on: 31/07/2011
+ */
+
+#include "emu.h"
+#include "mface2.h"
+#include "includes/amstrad.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type CPC_MFACE2 = &device_creator<cpc_multiface2_device>;
+
+CPC_EXPANSION_INTERFACE(sub_exp_intf)
+{
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, irq_w),
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, nmi_w),
+ DEVCB_NULL, // RESET
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, romdis_w), // ROMDIS
+ DEVCB_DEVICE_LINE_MEMBER("^^", cpc_expansion_slot_device, romen_w) // /ROMEN
+};
+
+// device machine config
+static MACHINE_CONFIG_FRAGMENT( cpc_mface2 )
+ // pass-through
+ MCFG_CPC_EXPANSION_SLOT_ADD("exp",sub_exp_intf,cpc_exp_cards,NULL)
+MACHINE_CONFIG_END
+
+DIRECT_UPDATE_MEMBER( cpc_multiface2_device::amstrad_default )
+{
+ return address;
+}
+
+/* used to setup computer if a snapshot was specified */
+DIRECT_UPDATE_MEMBER( cpc_multiface2_device::amstrad_multiface_directoverride )
+{
+ int pc;
+
+ pc = machine().device("maincpu")->safe_pc();
+ /* there are two places where CALL &0065 can be found
+ in the multiface rom. At this address there is a RET.
+
+ To disable the multiface from being detected, the multiface
+ stop button must be pressed, then the program that was stopped
+ must be returned to. When this is done, the multiface cannot
+ be detected and the out operations to page the multiface
+ ram/rom into the address space will not work! */
+
+ /* I assume that the hardware in the multiface detects
+ the PC set to 0x065 and uses this to enable/disable the multiface
+ */
+
+ /* I also use this to allow the stop button to be pressed again */
+ if (pc==0x0164)
+ {
+ /* first call? */
+ m_multiface_flags |= MULTIFACE_VISIBLE;
+ }
+ else if (pc==0x0c98)
+ {
+ /* second call */
+
+ /* no longer visible */
+ m_multiface_flags &= ~(MULTIFACE_VISIBLE|MULTIFACE_STOP_BUTTON_PRESSED);
+
+ m_romdis=0;
+ m_slot->romen_w(0);
+
+ /* clear op base override */
+ machine().device("maincpu")->memory().space(AS_PROGRAM).set_direct_update_handler(direct_update_delegate(FUNC(cpc_multiface2_device::amstrad_default),this));
+ }
+
+ return pc;
+}
+
+int cpc_multiface2_device::multiface_hardware_enabled()
+{
+ if (m_multiface_ram!=NULL)
+ {
+ if ((ioport("multiface")->read() & 0x01)!=0)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* multiface traps calls to 0x0065 when it is active.
+This address has a RET and so executes no code.
+
+It is believed that it is used to make multiface invisible to programs */
+
+/*#define MULTIFACE_0065_TOGGLE 0x0008*/
+
+
+void cpc_multiface2_device::multiface_rethink_memory()
+{
+ unsigned char *multiface_rom;
+
+ /* multiface hardware enabled? */
+ if (!multiface_hardware_enabled())
+ return;
+
+ multiface_rom = memregion("multiface")->base();
+
+ if ((m_multiface_flags & MULTIFACE_RAM_ROM_ENABLED)!=0 && m_romdis != 0)
+ {
+ /* set bank addressess */
+ machine().root_device().membank("bank1")->set_base(multiface_rom);
+ machine().root_device().membank("bank2")->set_base(m_multiface_ram);
+ machine().root_device().membank("bank9")->set_base(multiface_rom);
+ machine().root_device().membank("bank10")->set_base(m_multiface_ram);
+ }
+}
+
+machine_config_constructor cpc_multiface2_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( cpc_mface2 );
+}
+
+void cpc_multiface2_device::check_button_state()
+{
+ if(!multiface_hardware_enabled())
+ return;
+ // TODO: reset button
+ if (ioport("multiface")->read() & 0x02)
+ {
+ multiface_stop();
+ }
+}
+
+/* simulate the stop button has been pressed */
+void cpc_multiface2_device::multiface_stop()
+{
+ /* multiface hardware enabled? */
+ if (!multiface_hardware_enabled())
+ return;
+
+ /* if stop button not already pressed, do press action */
+ /* pressing stop button while multiface is running has no effect */
+ if ((m_multiface_flags & MULTIFACE_STOP_BUTTON_PRESSED)==0)
+ {
+ /* initialise 0065 toggle */
+ /*state->m_multiface_flags &= ~MULTIFACE_0065_TOGGLE;*/
+
+ m_multiface_flags |= MULTIFACE_RAM_ROM_ENABLED;
+
+ /* stop button has been pressed, furthur pressess will not issue a NMI */
+ m_multiface_flags |= MULTIFACE_STOP_BUTTON_PRESSED;
+
+ m_romdis = 1;
+ m_slot->romen_w(1);
+
+ /* page rom into memory */
+ multiface_rethink_memory();
+
+ /* pulse the nmi line */
+ m_slot->nmi_w(1);
+ m_slot->nmi_w(0);
+
+ /* initialise 0065 override to monitor calls to 0065 */
+ machine().device("maincpu")->memory().space(AS_PROGRAM).set_direct_update_handler(direct_update_delegate(FUNC(cpc_multiface2_device::amstrad_multiface_directoverride),this));
+ }
+}
+
+/* any io writes are passed through here */
+int cpc_multiface2_device::multiface_io_write(UINT16 offset, UINT8 data)
+{
+ int ret = 0;
+
+ /* multiface hardware enabled? */
+ if (!multiface_hardware_enabled())
+ return 0;
+
+ /* visible? */
+ if (m_multiface_flags & MULTIFACE_VISIBLE)
+ {
+ if (offset==0x0fee8)
+ {
+ m_multiface_flags |= MULTIFACE_RAM_ROM_ENABLED;
+ ret = 1;
+ }
+
+ if (offset==0x0feea)
+ {
+ m_multiface_flags &= ~MULTIFACE_RAM_ROM_ENABLED;
+ ret = 1;
+ }
+ }
+
+ /* update multiface ram with data */
+ /* these are decoded fully! */
+ switch ((offset>>8) & 0x0ff)
+ {
+ /* gate array */
+ case 0x07f:
+ {
+ switch (data & 0x0c0)
+ {
+ /* pen index */
+ case 0x00:
+ {
+ m_multiface_ram[0x01fcf] = data;
+ }
+ break;
+ /* pen colour */
+ case 0x040:
+ {
+ int pen_index;
+ pen_index = m_multiface_ram[0x01fcf] & 0x0f;
+ if (m_multiface_ram[0x01fcf] & 0x010)
+ {
+ m_multiface_ram[0x01fdf + pen_index] = data;
+ }
+ else
+ {
+ m_multiface_ram[0x01f90 + pen_index] = data & 0x01f;
+ }
+ }
+ break;
+ /* rom/mode selection */
+ case 0x080:
+ {
+ m_multiface_ram[0x01fef] = data;
+ }
+ break;
+ /* ram configuration */
+ case 0x0c0:
+ {
+ m_multiface_ram[0x01fff] = data;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ /* crtc register index */
+ case 0x0bc:
+ {
+ m_multiface_ram[0x01cff] = data;
+ }
+ break;
+ /* crtc register write */
+ case 0x0bd:
+ {
+ int reg_index;
+ reg_index = m_multiface_ram[0x01cff] & 0x0f;
+ m_multiface_ram[0x01db0 + reg_index] = data;
+ }
+ break;
+
+
+ /* 8255 ppi control */
+ case 0x0f7:
+ {
+ m_multiface_ram[0x017ff] = data;
+ }
+ break;
+ /* rom select */
+ case 0x0df:
+ {
+ m_multiface_ram[0x01aac] = data;
+ }
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static INPUT_PORTS_START(cpc_mface2)
+ PORT_START("multiface")
+ PORT_CONFNAME(0x01, 0x00, "Multiface Two" )
+ PORT_CONFSETTING(0x00, DEF_STR( Off) )
+ PORT_CONFSETTING(0x01, DEF_STR( On) )
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Multiface Two's Stop Button") PORT_CODE(KEYCODE_F6)
+ // PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Multiface Two's Reset Button") PORT_CODE(KEYCODE_F3) Not implemented
+INPUT_PORTS_END
+
+
+
+//-------------------------------------------------
+// Device ROM definition
+//-------------------------------------------------
+
+// Second known revision (1988)
+ROM_START( cpc_mface2 )
+ ROM_REGION( 0x2000, "multiface", 0 )
+ ROM_LOAD("multface.rom", 0x0000, 0x2000, CRC(f36086de) SHA1(1431ec628d38f000715545dd2186b684c5fe5a6f))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *cpc_multiface2_device::device_rom_region() const
+{
+ return ROM_NAME( cpc_mface2 );
+}
+
+ioport_constructor cpc_multiface2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( cpc_mface2 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+cpc_multiface2_device::cpc_multiface2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, CPC_MFACE2, "Multiface II", tag, owner, clock, "cpc_mf2", __FILE__),
+ device_cpc_expansion_card_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cpc_multiface2_device::device_start()
+{
+ m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
+
+ /* after a reset the multiface is visible */
+ m_multiface_flags = MULTIFACE_VISIBLE;
+
+ /* allocate ram */
+ m_multiface_ram = auto_alloc_array(machine(), UINT8, 8192);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void cpc_multiface2_device::device_reset()
+{
+ /* stop button not pressed and ram/rom disabled */
+ m_multiface_flags &= ~(MULTIFACE_STOP_BUTTON_PRESSED |
+ MULTIFACE_RAM_ROM_ENABLED);
+ /* as on the real hardware the multiface is visible after a reset! */
+ m_multiface_flags |= MULTIFACE_VISIBLE;
+}
diff --git a/src/emu/bus/cpc/mface2.h b/src/emu/bus/cpc/mface2.h
new file mode 100644
index 00000000000..917ddeeaeea
--- /dev/null
+++ b/src/emu/bus/cpc/mface2.h
@@ -0,0 +1,69 @@
+/*
+ * mface2.h -- Romantic Robot Multiface II expansion device for the Amstrad CPC/CPC+
+ *
+ * Created on: 31/07/2011
+ *
+ * I/O Ports:
+ * - FEE8: Enables Multiface ROM and RAM
+ * - FEEA: Disables Multiface ROM and RAM
+ *
+ * When enabled, Multiface ROM is mapped to &0000, and RAM to &2000
+ *
+ * When the Stop button is pressed, the Multiface II will generate an NMI
+ * (I guess the ROM/RAM is enabled when you do this also?)
+ *
+ * It also monitors all I/O port writes, so that it can restore them when resuming the current application.
+ */
+
+#ifndef MFACE2_H_
+#define MFACE2_H_
+
+#include "emu.h"
+#include "cpcexp.h"
+
+/* stop button has been pressed */
+#define MULTIFACE_STOP_BUTTON_PRESSED 0x0001
+/* ram/rom is paged into memory space */
+#define MULTIFACE_RAM_ROM_ENABLED 0x0002
+/* when visible OUT commands are performed! */
+#define MULTIFACE_VISIBLE 0x0004
+
+
+class cpc_multiface2_device : public device_t,
+ public device_cpc_expansion_card_interface
+{
+public:
+ // construction/destruction
+ cpc_multiface2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual ioport_constructor device_input_ports() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ int multiface_hardware_enabled();
+ void multiface_rethink_memory();
+ void multiface_stop();
+ int multiface_io_write(UINT16 offset, UINT8 data);
+ void check_button_state();
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ cpc_expansion_slot_device *m_slot;
+
+ DIRECT_UPDATE_MEMBER( amstrad_default );
+ DIRECT_UPDATE_MEMBER( amstrad_multiface_directoverride );
+
+ unsigned char *m_multiface_ram;
+ unsigned long m_multiface_flags;
+
+ UINT8 m_romdis;
+};
+
+// device type definition
+extern const device_type CPC_MFACE2;
+
+#endif /* MFACE2_H_ */
diff --git a/src/emu/bus/epson_sio/epson_sio.c b/src/emu/bus/epson_sio/epson_sio.c
new file mode 100644
index 00000000000..442e6351208
--- /dev/null
+++ b/src/emu/bus/epson_sio/epson_sio.c
@@ -0,0 +1,116 @@
+/**********************************************************************
+
+ EPSON SIO port emulation
+
+ license: MAME, GPL-2.0+
+ copyright-holders: Dirk Best
+
+**********************************************************************/
+
+#include "epson_sio.h"
+
+// supported devices
+#include "pf10.h"
+#include "tf20.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type EPSON_SIO = &device_creator<epson_sio_device>;
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_epson_sio_interface - constructor
+//-------------------------------------------------
+
+device_epson_sio_interface::device_epson_sio_interface(const machine_config &mconfig, device_t &device) :
+ device_slot_card_interface(mconfig, device)
+{
+ m_slot = dynamic_cast<epson_sio_device *>(device.owner());
+}
+
+
+//-------------------------------------------------
+// ~device_epson_sio_interface - destructor
+//-------------------------------------------------
+
+device_epson_sio_interface::~device_epson_sio_interface()
+{
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// epson_sio_device - constructor
+//-------------------------------------------------
+
+epson_sio_device::epson_sio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, EPSON_SIO, "EPSON SIO port", tag, owner, clock, "epson_sio", __FILE__),
+ device_slot_interface(mconfig, *this),
+ m_write_rx(*this),
+ m_write_pin(*this)
+{
+}
+
+
+//-------------------------------------------------
+// epson_sio_device - destructor
+//-------------------------------------------------
+
+epson_sio_device::~epson_sio_device()
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void epson_sio_device::device_start()
+{
+ m_cart = dynamic_cast<device_epson_sio_interface *>(get_card_device());
+
+ m_write_rx.resolve_safe();
+ m_write_pin.resolve_safe();
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void epson_sio_device::device_reset()
+{
+}
+
+
+WRITE_LINE_MEMBER( epson_sio_device::tx_w )
+{
+ if (m_cart != NULL)
+ m_cart->tx_w(state);
+}
+
+WRITE_LINE_MEMBER( epson_sio_device::pout_w )
+{
+ if (m_cart != NULL)
+ m_cart->pout_w(state);
+}
+
+
+//**************************************************************************
+// SLOT INTERFACE
+//**************************************************************************
+
+SLOT_INTERFACE_START( epson_sio_devices )
+ SLOT_INTERFACE("pf10", EPSON_PF10)
+ SLOT_INTERFACE("tf20", EPSON_TF20)
+SLOT_INTERFACE_END
diff --git a/src/emu/bus/epson_sio/epson_sio.h b/src/emu/bus/epson_sio/epson_sio.h
new file mode 100644
index 00000000000..f398d4d1ea1
--- /dev/null
+++ b/src/emu/bus/epson_sio/epson_sio.h
@@ -0,0 +1,97 @@
+/**********************************************************************
+
+ EPSON SIO port emulation
+
+ license: MAME, GPL-2.0+
+ copyright-holders: Dirk Best
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __EPSON_SIO_H__
+#define __EPSON_SIO_H__
+
+#include "emu.h"
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_EPSON_SIO_ADD(_tag, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, EPSON_SIO, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(epson_sio_devices, _def_slot, false)
+
+#define MCFG_EPSON_SIO_RX(_rx) \
+ downcast<epson_sio_device *>(device)->set_rx_callback(DEVCB2_##_rx);
+
+#define MCFG_EPSON_SIO_PIN(_pin) \
+ downcast<epson_sio_device *>(device)->set_pin_callback(DEVCB2_##_pin);
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class device_epson_sio_interface;
+
+
+class epson_sio_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ epson_sio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~epson_sio_device();
+
+ // callbacks
+ template<class _rx> void set_rx_callback(_rx rx) { m_write_rx.set_callback(rx); }
+ template<class _pin> void set_pin_callback(_pin pin) { m_write_pin.set_callback(pin); }
+
+ // called from owner
+ DECLARE_WRITE_LINE_MEMBER( tx_w );
+ DECLARE_WRITE_LINE_MEMBER( pout_w );
+
+ // called from subdevice
+ DECLARE_WRITE_LINE_MEMBER( rx_w ) { m_write_rx(state); }
+ DECLARE_WRITE_LINE_MEMBER( pin_w ) { m_write_pin(state); }
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ device_epson_sio_interface *m_cart;
+
+private:
+ devcb2_write_line m_write_rx;
+ devcb2_write_line m_write_pin;
+};
+
+
+// class representing interface-specific live sio device
+class device_epson_sio_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_epson_sio_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_epson_sio_interface();
+
+ virtual void tx_w(int state) { };
+ virtual void pout_w(int state) { };
+
+protected:
+ epson_sio_device *m_slot;
+};
+
+
+// device type definition
+extern const device_type EPSON_SIO;
+
+
+// supported devices
+SLOT_INTERFACE_EXTERN( epson_sio_devices );
+
+
+#endif // __EPSON_SIO_H__
diff --git a/src/emu/bus/epson_sio/pf10.c b/src/emu/bus/epson_sio/pf10.c
new file mode 100644
index 00000000000..1faf656637d
--- /dev/null
+++ b/src/emu/bus/epson_sio/pf10.c
@@ -0,0 +1,242 @@
+/**********************************************************************
+
+ EPSON PF-10
+
+ license: MAME, GPL-2.0+
+ copyright-holders: Dirk Best
+
+ Battery operated portable 3.5" floppy drive
+
+ Status: Needs lots of work.
+
+**********************************************************************/
+
+#include "pf10.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type EPSON_PF10 = &device_creator<epson_pf10_device>;
+
+
+//-------------------------------------------------
+// address maps
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( cpu_mem, AS_PROGRAM, 8, epson_pf10_device )
+ AM_RANGE(0x0000, 0x001f) AM_DEVREADWRITE("maincpu", hd6303y_cpu_device, m6801_io_r, m6801_io_w)
+ AM_RANGE(0x0040, 0x00ff) AM_RAM /* 192 bytes internal ram */
+ AM_RANGE(0x0800, 0x0fff) AM_RAM /* external 2k ram */
+ AM_RANGE(0x1000, 0x17ff) AM_READWRITE(fdc_r, fdc_w)
+ AM_RANGE(0x1800, 0x1fff) AM_WRITE(fdc_tc_w)
+ AM_RANGE(0xe000, 0xffff) AM_ROM AM_REGION("maincpu", 0)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( cpu_io, AS_IO, 8, epson_pf10_device )
+ AM_RANGE(M6801_PORT1, M6801_PORT1) AM_READWRITE(port1_r, port1_w)
+ AM_RANGE(M6801_PORT2, M6801_PORT2) AM_READWRITE(port2_r, port2_w)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( pf10 )
+ ROM_REGION(0x2000, "maincpu", 0)
+ ROM_LOAD("k3pf1.bin", 0x0000, 0x2000, CRC(eef4593a) SHA1(bb176e4baf938fe58c2d32f7c46d7bb7b0627755))
+ROM_END
+
+const rom_entry *epson_pf10_device::device_rom_region() const
+{
+ return ROM_NAME( pf10 );
+}
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+static SLOT_INTERFACE_START( pf10_floppies )
+ SLOT_INTERFACE( "smd165", EPSON_SMD_165 )
+SLOT_INTERFACE_END
+
+static MACHINE_CONFIG_FRAGMENT( pf10 )
+ MCFG_CPU_ADD("maincpu", HD6303Y, XTAL_4_9152MHz) // HD63A03XF
+ MCFG_CPU_PROGRAM_MAP(cpu_mem)
+ MCFG_CPU_IO_MAP(cpu_io)
+ MCFG_M6801_SER_TX(DEVWRITELINE(DEVICE_SELF, epson_pf10_device, hd6303_tx_w))
+
+ MCFG_UPD765A_ADD("upd765a", false, true)
+ MCFG_FLOPPY_DRIVE_ADD("upd765a:0", pf10_floppies, "smd165", floppy_image_device::default_floppy_formats)
+
+ MCFG_EPSON_SIO_ADD("sio", NULL)
+ MCFG_EPSON_SIO_RX(DEVWRITELINE(DEVICE_SELF, epson_pf10_device, rxc_w))
+ MCFG_EPSON_SIO_PIN(DEVWRITELINE(DEVICE_SELF, epson_pf10_device, pinc_w))
+MACHINE_CONFIG_END
+
+machine_config_constructor epson_pf10_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( pf10 );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// epson_pf10_device - constructor
+//-------------------------------------------------
+
+epson_pf10_device::epson_pf10_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, EPSON_PF10, "EPSON PF-10 Portable Floppy Unit", tag, owner, clock, "epson_pf10", __FILE__),
+ device_epson_sio_interface(mconfig, *this),
+ m_cpu(*this, "maincpu"),
+ m_fdc(*this, "upd765a"),
+ m_sio_output(*this, "sio"),
+ m_port1(0xff),
+ m_port2(0xff),
+ m_rxc(1)
+{
+ m_sio_input = dynamic_cast<epson_sio_device *>(owner);
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void epson_pf10_device::device_start()
+{
+ m_timer = timer_alloc(0, NULL);
+ m_floppy = subdevice<floppy_connector>("upd765a:0")->get_device();
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void epson_pf10_device::device_reset()
+{
+ m_timer->adjust(attotime::zero, 0, attotime::from_hz(38400 * 8));
+}
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void epson_pf10_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case 0:
+ m_cpu->m6801_clock_serial();
+ break;
+ }
+}
+
+
+//**************************************************************************
+// CPU
+//**************************************************************************
+
+READ8_MEMBER( epson_pf10_device::port1_r )
+{
+ logerror("%s: port1_r(%02x)\n", tag(), m_port1);
+ return m_port1;
+}
+
+WRITE8_MEMBER( epson_pf10_device::port1_w )
+{
+ logerror("%s: port1_w(%02x)\n", tag(), data);
+}
+
+READ8_MEMBER( epson_pf10_device::port2_r )
+{
+ logerror("%s: port2_r(%02x)\n", tag(), m_port2);
+ return m_port2;
+}
+
+WRITE8_MEMBER( epson_pf10_device::port2_w )
+{
+ m_floppy->mon_w(data & PORT2_MON);
+ logerror("%s: port2_w(%02x)\n", tag(), data);
+}
+
+READ8_MEMBER( epson_pf10_device::fdc_r )
+{
+ logerror("%s: fdc_r @ %04x\n", tag(), offset);
+ return 0xff;
+}
+
+WRITE8_MEMBER( epson_pf10_device::fdc_w )
+{
+ logerror("%s: fdc_w @ %04x (%02x)\n", tag(), offset, data);
+}
+
+WRITE8_MEMBER( epson_pf10_device::fdc_tc_w )
+{
+ logerror("%s: fdc_tc_w(%02x)\n", tag(), data);
+}
+
+
+//**************************************************************************
+// SIO INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// rxc_w - rx input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( epson_pf10_device::rxc_w )
+{
+ m_rxc = state;
+ m_sio_input->rx_w(m_hd6303_tx & m_rxc);
+}
+
+//-------------------------------------------------
+// pinc_w - pin input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( epson_pf10_device::pinc_w )
+{
+ m_pinc = state;
+ m_sio_input->pin_w(m_pinc);
+}
+
+//-------------------------------------------------
+// hd6303_tx_w - rx output
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( epson_pf10_device::hd6303_tx_w )
+{
+ m_hd6303_tx = state;
+ m_sio_input->rx_w(m_hd6303_tx & m_rxc);
+}
+
+//-------------------------------------------------
+// tx_w - tx input
+//-------------------------------------------------
+
+void epson_pf10_device::tx_w(int level)
+{
+ if (level)
+ m_port2 |= PORT2_RXD;
+ else
+ m_port2 &= ~PORT2_RXD;
+
+ m_sio_output->tx_w(level);
+}
+
+//-------------------------------------------------
+// pout_w - pout input
+//-------------------------------------------------
+
+void epson_pf10_device::pout_w(int level)
+{
+ m_sio_output->pout_w(level);
+}
diff --git a/src/emu/bus/epson_sio/pf10.h b/src/emu/bus/epson_sio/pf10.h
new file mode 100644
index 00000000000..df0bdc56cfa
--- /dev/null
+++ b/src/emu/bus/epson_sio/pf10.h
@@ -0,0 +1,102 @@
+/**********************************************************************
+
+ EPSON PF-10
+
+ license: MAME, GPL-2.0+
+ copyright-holders: Dirk Best
+
+ Battery operated portable 3.5" floppy drive
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __PF10_H__
+#define __PF10_H__
+
+#include "emu.h"
+#include "cpu/m6800/m6800.h"
+#include "machine/upd765.h"
+#include "epson_sio.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class epson_pf10_device : public device_t,
+ public device_epson_sio_interface
+{
+public:
+ // construction/destruction
+ epson_pf10_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ // floppy disk controller
+ DECLARE_READ8_MEMBER( fdc_r );
+ DECLARE_WRITE8_MEMBER( fdc_w );
+ DECLARE_WRITE8_MEMBER( fdc_tc_w );
+
+ // hd6303 i/o
+ DECLARE_READ8_MEMBER( port1_r );
+ DECLARE_WRITE8_MEMBER( port1_w );
+ DECLARE_READ8_MEMBER( port2_r );
+ DECLARE_WRITE8_MEMBER( port2_w );
+
+ // serial output from main cpu
+ DECLARE_WRITE_LINE_MEMBER( hd6303_tx_w );
+
+ // from sio output
+ DECLARE_WRITE_LINE_MEMBER( rxc_w );
+ DECLARE_WRITE_LINE_MEMBER( pinc_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_epson_sio_interface overrides
+ virtual void tx_w(int level);
+ virtual void pout_w(int level);
+
+private:
+ required_device<hd6303y_cpu_device> m_cpu;
+ required_device<upd765a_device> m_fdc;
+ required_device<epson_sio_device> m_sio_output;
+
+ epson_sio_device *m_sio_input;
+ floppy_image_device *m_floppy;
+
+ emu_timer *m_timer;
+
+ UINT8 m_port1;
+ UINT8 m_port2;
+
+ int m_rxc;
+ int m_hd6303_tx;
+ int m_pinc;
+
+ // port definitions
+ enum
+ {
+ PORT2_SEEK = 0x01,
+ PORT2_SWCOM = 0x02, // ?
+ PORT2_RS232ON = 0x04, // to nmi?
+ PORT2_RXD = 0x08,
+ PORT2_TXD = 0x10,
+ PORT2_FDCRST = 0x20,
+ PORT2_MON = 0x40,
+ PORT2_BATCKEN = 0x80 // ?
+ };
+};
+
+
+// device type definition
+extern const device_type EPSON_PF10;
+
+
+#endif // __PF10_H__
diff --git a/src/emu/bus/epson_sio/tf20.c b/src/emu/bus/epson_sio/tf20.c
new file mode 100644
index 00000000000..645b68365e6
--- /dev/null
+++ b/src/emu/bus/epson_sio/tf20.c
@@ -0,0 +1,343 @@
+/**********************************************************************
+
+ EPSON TF-20
+
+ license: MAME, GPL-2.0+
+ copyright-holders: Dirk Best
+
+ Dual 5.25" floppy drive with HX-20 factory option
+
+ Status: Needs testing.
+
+ http://fjkraan.home.xs4all.nl/comp/tf20/index.html
+
+**********************************************************************/
+
+#include "tf20.h"
+
+#define XTAL_CR1 XTAL_8MHz
+#define XTAL_CR2 XTAL_4_9152MHz
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type EPSON_TF20 = &device_creator<epson_tf20_device>;
+
+//-------------------------------------------------
+// address maps
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( cpu_mem, AS_PROGRAM, 8, epson_tf20_device )
+ AM_RANGE(0x0000, 0x7fff) AM_RAMBANK("bank1")
+ AM_RANGE(0x8000, 0xffff) AM_RAMBANK("bank2")
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( cpu_io, AS_IO, 8, epson_tf20_device )
+ ADDRESS_MAP_UNMAP_HIGH
+ ADDRESS_MAP_GLOBAL_MASK(0xff)
+ AM_RANGE(0xf0, 0xf3) AM_DEVREADWRITE("3a", upd7201_device, ba_cd_r, ba_cd_w)
+ AM_RANGE(0xf6, 0xf6) AM_READ(rom_disable_r)
+ AM_RANGE(0xf7, 0xf7) AM_READ_PORT("tf20_dip")
+ AM_RANGE(0xf8, 0xf8) AM_READWRITE(upd765_tc_r, fdc_control_w)
+ AM_RANGE(0xfa, 0xfb) AM_DEVICE("5a", upd765a_device, map)
+ADDRESS_MAP_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( tf20 )
+ ROM_REGION(0x0800, "rom", 0)
+ ROM_LOAD("tfx.15e", 0x0000, 0x0800, CRC(af34f084) SHA1(c9bdf393f757ba5d8f838108ceb2b079be1d616e))
+ROM_END
+
+const rom_entry *epson_tf20_device::device_rom_region() const
+{
+ return ROM_NAME( tf20 );
+}
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+INPUT_PORTS_START( tf20 )
+ PORT_START("tf20_dip")
+ PORT_DIPNAME(0x0f, 0x00, "Drive extension")
+ PORT_DIPLOCATION("TF-20:8,7,6,5")
+ PORT_DIPSETTING(0x00, "A & B Drive")
+ PORT_DIPSETTING(0x01, "C & D Drive")
+INPUT_PORTS_END
+
+ioport_constructor epson_tf20_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( tf20 );
+}
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+static UPD7201_INTERFACE( tf20_upd7201_intf )
+{
+ 0, 0, 0, 0,
+
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, epson_tf20_device, txda_w),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, epson_tf20_device, dtra_w),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+static SLOT_INTERFACE_START( tf20_floppies )
+ SLOT_INTERFACE( "sd320", EPSON_SD_320 )
+SLOT_INTERFACE_END
+
+static MACHINE_CONFIG_FRAGMENT( tf20 )
+ MCFG_CPU_ADD("19b", Z80, XTAL_CR1 / 2) /* uPD780C */
+ MCFG_CPU_PROGRAM_MAP(cpu_mem)
+ MCFG_CPU_IO_MAP(cpu_io)
+
+ // 64k internal ram
+ MCFG_RAM_ADD("ram")
+ MCFG_RAM_DEFAULT_SIZE("64k")
+
+ // upd7201 serial interface
+ MCFG_UPD7201_ADD("3a", XTAL_CR1 / 2, tf20_upd7201_intf)
+ MCFG_UPD765_INTRQ_CALLBACK(INPUTLINE("19b", INPUT_LINE_IRQ0))
+
+ // floppy disk controller
+ MCFG_UPD765A_ADD("5a", true, true)
+
+ // floppy drives
+ MCFG_FLOPPY_DRIVE_ADD("5a:0", tf20_floppies, "sd320", floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("5a:1", tf20_floppies, "sd320", floppy_image_device::default_floppy_formats)
+
+ // serial interface to another device
+ MCFG_EPSON_SIO_ADD("sio", NULL)
+ MCFG_EPSON_SIO_RX(DEVWRITELINE(DEVICE_SELF, epson_tf20_device, rxc_w))
+ MCFG_EPSON_SIO_PIN(DEVWRITELINE(DEVICE_SELF, epson_tf20_device, pinc_w))
+MACHINE_CONFIG_END
+
+machine_config_constructor epson_tf20_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( tf20 );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// epson_tf20_device - constructor
+//-------------------------------------------------
+
+epson_tf20_device::epson_tf20_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, EPSON_TF20, "EPSON TF-20 Dual Floppy Disk Drive", tag, owner, clock, "epson_tf20", __FILE__),
+ device_epson_sio_interface(mconfig, *this),
+ m_cpu(*this, "19b"),
+ m_ram(*this, "ram"),
+ m_fdc(*this, "5a"),
+ m_mpsc(*this, "3a"),
+ m_sio_output(*this, "sio"),
+ m_rxc(1)
+{
+ m_sio_input = dynamic_cast<epson_sio_device *>(owner);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void epson_tf20_device::device_start()
+{
+ // make sure the ram device is already running
+ if (!m_ram->started())
+ throw device_missing_dependencies();
+
+ m_timer_serial = timer_alloc(0, NULL);
+ m_timer_tc = timer_alloc(1, NULL);
+
+ m_cpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(epson_tf20_device::irq_callback),this));
+
+ m_fd0 = subdevice<floppy_connector>("5a:0")->get_device();
+ m_fd1 = subdevice<floppy_connector>("5a:1")->get_device();
+
+ // enable second half of ram
+ m_cpu->space(AS_PROGRAM).install_ram(0x8000, 0xffff, m_ram->pointer() + 0x8000);
+
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void epson_tf20_device::device_reset()
+{
+ // init timers
+ m_timer_serial->adjust(attotime::zero, 0, attotime::from_hz(XTAL_CR2 / 8));
+ m_timer_tc->adjust(attotime::never);
+
+ m_mpsc->rxa_w(1);
+ m_mpsc->rxb_w(1);
+
+ // enable rom
+ m_cpu->space(AS_PROGRAM).install_rom(0x0000, 0x07ff, 0, 0x7800, memregion("rom")->base());
+}
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void epson_tf20_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case 0:
+ m_mpsc->rxca_w(1);
+ m_mpsc->rxca_w(0);
+ m_mpsc->txca_w(1);
+ m_mpsc->txca_w(0);
+ m_mpsc->rxcb_w(1);
+ m_mpsc->rxcb_w(0);
+ m_mpsc->txcb_w(1);
+ m_mpsc->txcb_w(0);
+ break;
+
+ case 1:
+ logerror("%s: tc off\n", tag());
+ m_fdc->tc_w(false);
+ break;
+ }
+}
+
+
+//**************************************************************************
+// CPU & MEMORY
+//**************************************************************************
+
+//-------------------------------------------------
+// irq vector callback
+//-------------------------------------------------
+
+IRQ_CALLBACK_MEMBER( epson_tf20_device::irq_callback )
+{
+ return 0x00;
+}
+
+// a read from this location disables the rom
+READ8_MEMBER( epson_tf20_device::rom_disable_r )
+{
+ // switch in ram
+ m_cpu->space(AS_PROGRAM).install_ram(0x0000, 0x7fff, m_ram->pointer());
+ return 0xff;
+}
+
+
+//**************************************************************************
+// FLOPPY DISK CONTROLLER
+//**************************************************************************
+
+//-------------------------------------------------
+// fdc interrupt
+//-------------------------------------------------
+
+READ8_MEMBER( epson_tf20_device::upd765_tc_r )
+{
+ logerror("%s: upd765_tc_r\n", space.machine().describe_context());
+
+ // toggle tc on read
+ m_fdc->tc_w(true);
+ m_timer_tc->adjust(attotime::zero);
+
+ return 0xff;
+}
+
+WRITE8_MEMBER( epson_tf20_device::fdc_control_w )
+{
+ logerror("%s: tf20_fdc_control_w(%02x)\n", space.machine().describe_context(), data);
+
+ // bit 0, motor on signal
+ m_fd0->mon_w(!BIT(data, 0));
+ m_fd1->mon_w(!BIT(data, 0));
+}
+
+
+//**************************************************************************
+// SIO INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// rxc_w - rx input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( epson_tf20_device::rxc_w )
+{
+ m_rxc = state;
+ m_sio_input->rx_w(m_txda & m_rxc);
+}
+
+//-------------------------------------------------
+// pinc_w - pin input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( epson_tf20_device::pinc_w )
+{
+ m_pinc = state;
+ m_sio_input->pin_w(!m_dtra | m_pinc);
+}
+
+//-------------------------------------------------
+// txda_w - rx output
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( epson_tf20_device::txda_w )
+{
+ m_txda = state;
+ m_sio_input->rx_w(m_txda & m_rxc);
+}
+
+//-------------------------------------------------
+// dtra_w - pin output
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( epson_tf20_device::dtra_w )
+{
+ m_dtra = state;
+ m_sio_input->pin_w(!m_dtra | m_pinc);
+}
+
+//-------------------------------------------------
+// tx_w - tx input
+//-------------------------------------------------
+
+void epson_tf20_device::tx_w(int level)
+{
+ m_mpsc->rxa_w(level);
+ m_sio_output->tx_w(level);
+}
+
+//-------------------------------------------------
+// pout_w - pout input
+//-------------------------------------------------
+
+void epson_tf20_device::pout_w(int level)
+{
+ m_mpsc->ctsa_w(!level);
+ m_sio_output->pout_w(level);
+}
diff --git a/src/emu/bus/epson_sio/tf20.h b/src/emu/bus/epson_sio/tf20.h
new file mode 100644
index 00000000000..9aa5f2c47cb
--- /dev/null
+++ b/src/emu/bus/epson_sio/tf20.h
@@ -0,0 +1,92 @@
+/**********************************************************************
+
+ EPSON TF-20
+
+ license: MAME, GPL-2.0+
+ copyright-holders: Dirk Best
+
+ Dual 5.25" floppy drive with HX-20 factory option
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __TF20_H__
+#define __TF20_H__
+
+#include "emu.h"
+#include "cpu/z80/z80.h"
+#include "machine/ram.h"
+#include "machine/upd765.h"
+#include "machine/z80dart.h"
+#include "epson_sio.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class epson_tf20_device : public device_t,
+ public device_epson_sio_interface
+{
+public:
+ // construction/destruction
+ epson_tf20_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual ioport_constructor device_input_ports() const;
+
+ // not really public
+ DECLARE_READ8_MEMBER( rom_disable_r );
+ DECLARE_READ8_MEMBER( upd765_tc_r );
+ DECLARE_WRITE8_MEMBER( fdc_control_w );
+ IRQ_CALLBACK_MEMBER( irq_callback );
+ DECLARE_WRITE_LINE_MEMBER( txda_w );
+ DECLARE_WRITE_LINE_MEMBER( dtra_w );
+
+ // from sio output
+ DECLARE_WRITE_LINE_MEMBER( rxc_w );
+ DECLARE_WRITE_LINE_MEMBER( pinc_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_epson_sio_interface overrides
+ virtual void tx_w(int level);
+ virtual void pout_w(int level);
+
+private:
+ required_device<cpu_device> m_cpu;
+ required_device<ram_device> m_ram;
+ required_device<upd765a_device> m_fdc;
+ required_device<upd7201_device> m_mpsc;
+ required_device<epson_sio_device> m_sio_output;
+
+ floppy_image_device *m_fd0;
+ floppy_image_device *m_fd1;
+
+ emu_timer *m_timer_serial;
+ emu_timer *m_timer_tc;
+
+ int m_rxc;
+ int m_txda;
+ int m_dtra;
+ int m_pinc;
+
+ epson_sio_device *m_sio_input;
+
+ static const int XTAL_CR1 = XTAL_8MHz;
+ static const int XTAL_CR2 = XTAL_4_9152MHz;
+};
+
+
+// device type definition
+extern const device_type EPSON_TF20;
+
+
+#endif // __TF20_H__
diff --git a/src/emu/bus/pce/pce_rom.c b/src/emu/bus/pce/pce_rom.c
new file mode 100644
index 00000000000..57b7a6a76bb
--- /dev/null
+++ b/src/emu/bus/pce/pce_rom.c
@@ -0,0 +1,124 @@
+/***********************************************************************************************************
+
+
+ PC-Engine & Turbografx-16 cart emulation
+
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "pce_rom.h"
+
+
+//-------------------------------------------------
+// pce_rom_device - constructor
+//-------------------------------------------------
+
+const device_type PCE_ROM_STD = &device_creator<pce_rom_device>;
+const device_type PCE_ROM_CDSYS3 = &device_creator<pce_cdsys3_device>;
+const device_type PCE_ROM_POPULOUS = &device_creator<pce_populous_device>;
+const device_type PCE_ROM_SF2 = &device_creator<pce_sf2_device>;
+
+
+pce_rom_device::pce_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_pce_cart_interface( mconfig, *this )
+{
+}
+
+pce_rom_device::pce_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PCE_ROM_STD, "PCE & TG16 Carts", tag, owner, clock, "pce_rom", __FILE__),
+ device_pce_cart_interface( mconfig, *this )
+{
+}
+
+pce_cdsys3_device::pce_cdsys3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : pce_rom_device(mconfig, PCE_ROM_CDSYS3, "PCE & TG16 CD-System Cart v3.00", tag, owner, clock, "pce_cdsys3", __FILE__)
+{
+}
+
+pce_populous_device::pce_populous_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : pce_rom_device(mconfig, PCE_ROM_POPULOUS, "PCE Populous Cart", tag, owner, clock, "pce_populous", __FILE__)
+{
+}
+
+pce_sf2_device::pce_sf2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : pce_rom_device(mconfig, PCE_ROM_SF2, "PCE Street Fighters 2 Cart", tag, owner, clock, "pce_sf2", __FILE__)
+{
+}
+
+
+//-------------------------------------------------
+// mapper specific start/reset
+//-------------------------------------------------
+
+
+void pce_sf2_device::device_start()
+{
+ save_item(NAME(m_bank_base));
+}
+
+void pce_sf2_device::device_reset()
+{
+ m_bank_base = 0;
+}
+
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+READ8_MEMBER(pce_rom_device::read_cart)
+{
+ int bank = offset / 0x20000;
+ return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
+}
+
+
+READ8_MEMBER(pce_cdsys3_device::read_cart)
+{
+ int bank = offset / 0x20000;
+ if (m_ram && offset >= 0xd0000)
+ return m_ram[offset - 0xd0000];
+
+ return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
+}
+
+WRITE8_MEMBER(pce_cdsys3_device::write_cart)
+{
+ if (m_ram && offset >= 0xd0000)
+ m_ram[offset - 0xd0000] = data;
+}
+
+
+READ8_MEMBER(pce_populous_device::read_cart)
+{
+ int bank = offset / 0x20000;
+ if (m_ram && offset >= 0x80000 && offset < 0x88000)
+ return m_ram[offset & 0x7fff];
+
+ return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
+}
+
+WRITE8_MEMBER(pce_populous_device::write_cart)
+{
+ if (m_ram && offset >= 0x80000 && offset < 0x88000)
+ m_ram[offset & 0x7fff] = data;
+}
+
+
+READ8_MEMBER(pce_sf2_device::read_cart)
+{
+ if (offset < 0x80000)
+ return m_rom[offset];
+ else
+ return m_rom[0x80000 + m_bank_base * 0x80000 + (offset & 0x7ffff)];
+}
+
+WRITE8_MEMBER(pce_sf2_device::write_cart)
+{
+ if (offset >= 0x1ff0 && offset < 0x1ff4)
+ m_bank_base = offset & 3;
+}
diff --git a/src/emu/bus/pce/pce_rom.h b/src/emu/bus/pce/pce_rom.h
new file mode 100644
index 00000000000..1588757b96f
--- /dev/null
+++ b/src/emu/bus/pce/pce_rom.h
@@ -0,0 +1,83 @@
+#ifndef __PCE_ROM_H
+#define __PCE_ROM_H
+
+#include "pce_slot.h"
+
+
+// ======================> pce_rom_device
+
+class pce_rom_device : public device_t,
+ public device_pce_cart_interface
+{
+public:
+ // construction/destruction
+ pce_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ pce_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start() {}
+ virtual void device_reset() {}
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_cart);
+};
+
+// ======================> pce_cdsys3_device
+
+class pce_cdsys3_device : public pce_rom_device
+{
+public:
+ // construction/destruction
+ pce_cdsys3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_cart);
+ virtual DECLARE_WRITE8_MEMBER(write_cart);
+};
+
+
+// ======================> pce_populous_device
+
+class pce_populous_device : public pce_rom_device
+{
+public:
+ // construction/destruction
+ pce_populous_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_cart);
+ virtual DECLARE_WRITE8_MEMBER(write_cart);
+};
+
+
+// ======================> pce_sf2_device
+
+class pce_sf2_device : public pce_rom_device
+{
+public:
+ // construction/destruction
+ pce_sf2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_cart);
+ virtual DECLARE_WRITE8_MEMBER(write_cart);
+
+private:
+ UINT8 m_bank_base;
+};
+
+
+
+// device type definition
+extern const device_type PCE_ROM_STD;
+extern const device_type PCE_ROM_CDSYS3;
+extern const device_type PCE_ROM_POPULOUS;
+extern const device_type PCE_ROM_SF2;
+
+
+
+#endif
diff --git a/src/emu/bus/pce/pce_slot.c b/src/emu/bus/pce/pce_slot.c
new file mode 100644
index 00000000000..68fb95e28d6
--- /dev/null
+++ b/src/emu/bus/pce/pce_slot.c
@@ -0,0 +1,384 @@
+/***********************************************************************************************************
+
+
+ PC-Engine / Turbografx-16 cart emulation
+ (through slot devices)
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "pce_slot.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type PCE_CART_SLOT = &device_creator<pce_cart_slot_device>;
+
+//**************************************************************************
+// PCE cartridges Interface
+//**************************************************************************
+
+//-------------------------------------------------
+// device_pce_cart_interface - constructor
+//-------------------------------------------------
+
+device_pce_cart_interface::device_pce_cart_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device),
+ m_rom(NULL),
+ m_ram(NULL),
+ m_rom_size(0),
+ m_ram_size(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_pce_cart_interface - destructor
+//-------------------------------------------------
+
+device_pce_cart_interface::~device_pce_cart_interface()
+{
+}
+
+//-------------------------------------------------
+// rom_alloc - alloc the space for the cart
+//-------------------------------------------------
+
+void device_pce_cart_interface::rom_alloc(running_machine &machine, UINT32 size)
+{
+ if (m_rom == NULL)
+ {
+ m_rom = auto_alloc_array_clear(machine, UINT8, size);
+ m_rom_size = size;
+ }
+}
+
+
+//-------------------------------------------------
+// ram_alloc - alloc the space for the ram
+//-------------------------------------------------
+
+void device_pce_cart_interface::ram_alloc(running_machine &machine, UINT32 size)
+{
+ if (m_ram == NULL)
+ {
+ m_ram = auto_alloc_array_clear(machine, UINT8, size);
+ m_ram_size = size;
+ state_save_register_item_pointer(machine, "PCE_CART", this->device().tag(), 0, m_ram, m_ram_size);
+ }
+}
+
+//-------------------------------------------------
+// rom_map_setup - setup map of rom banks in 128K
+// blocks, so to simplify ROM access to mirror
+//-------------------------------------------------
+
+void device_pce_cart_interface::rom_map_setup(UINT32 size)
+{
+ int i;
+
+ if (size == 0x60000)
+ {
+ // HuCard 384K are mapped with mirrored pieces
+ rom_bank_map[0] = 0;
+ rom_bank_map[1] = 1;
+ rom_bank_map[2] = 0;
+ rom_bank_map[3] = 1;
+ rom_bank_map[4] = 2;
+ rom_bank_map[5] = 2;
+ rom_bank_map[6] = 2;
+ rom_bank_map[7] = 2;
+ }
+ else
+ {
+ // setup the rom_bank_map array to faster ROM read
+ for (i = 0; i < size / 0x20000 && i < 8; i++)
+ rom_bank_map[i] = i;
+
+ // fill up remaining blocks with mirrors
+ while (i % 8)
+ {
+ int j = 0, repeat_banks;
+ while ((i % (8 >> j)) && j < 3)
+ j++;
+ repeat_banks = i % (8 >> (j - 1));
+ for (int k = 0; k < repeat_banks; k++)
+ rom_bank_map[i + k] = rom_bank_map[i + k - repeat_banks];
+ i += repeat_banks;
+ }
+ }
+ // check bank map!
+// for (i = 0; i < 8; i++)
+// {
+// printf("bank %3d = %3d\t", i, rom_bank_map[i]);
+// }
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pce_cart_slot_device - constructor
+//-------------------------------------------------
+pce_cart_slot_device::pce_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, PCE_CART_SLOT, "PCE & TG16 Cartridge Slot", tag, owner, clock, "pce_cart_slot", __FILE__),
+ device_image_interface(mconfig, *this),
+ device_slot_interface(mconfig, *this),
+ m_interface("pce_cart"),
+ m_type(PCE_STD)
+{
+}
+
+
+//-------------------------------------------------
+// pce_cart_slot_device - destructor
+//-------------------------------------------------
+
+pce_cart_slot_device::~pce_cart_slot_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pce_cart_slot_device::device_start()
+{
+ m_cart = dynamic_cast<device_pce_cart_interface *>(get_card_device());
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void pce_cart_slot_device::device_config_complete()
+{
+ // set brief and instance name
+ update_names();
+}
+
+
+//-------------------------------------------------
+// PCE PCB
+//-------------------------------------------------
+
+struct pce_slot
+{
+ int pcb_id;
+ const char *slot_option;
+};
+
+// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
+static const pce_slot slot_list[] =
+{
+ { PCE_STD, "rom" },
+ { PCE_CDSYS3U, "cdsys3u" },
+ { PCE_CDSYS3J, "cdsys3j" },
+ { PCE_POPULOUS, "populous" },
+ { PCE_SF2, "sf2" },
+};
+
+static int pce_get_pcb_id(const char *slot)
+{
+ for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ {
+ if (!mame_stricmp(slot_list[i].slot_option, slot))
+ return slot_list[i].pcb_id;
+ }
+
+ return 0;
+}
+
+static const char *pce_get_slot(int type)
+{
+ for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ {
+ if (slot_list[i].pcb_id == type)
+ return slot_list[i].slot_option;
+ }
+
+ return "rom";
+}
+
+
+/*-------------------------------------------------
+ call load
+ -------------------------------------------------*/
+
+bool pce_cart_slot_device::call_load()
+{
+ if (m_cart)
+ {
+ UINT32 offset = 0;
+ UINT32 len = (software_entry() == NULL) ? length() : get_software_region_length("rom");
+ UINT8 *ROM;
+
+ // From fullpath, check for presence of a header and skip it
+ if (software_entry() == NULL && (len % 0x4000) == 512)
+ {
+ logerror("Rom-header found, skipping\n");
+ offset = 512;
+ len -= offset;
+ fseek(offset, SEEK_SET);
+ }
+
+ m_cart->rom_alloc(machine(), len);
+ ROM = m_cart->get_rom_base();
+
+ if (software_entry() == NULL)
+ fread(ROM, len);
+ else
+ memcpy(ROM, get_software_region("rom"), len);
+
+ // check for encryption (US carts)
+ if (ROM[0x1fff] < 0xe0)
+ {
+ UINT8 decrypted[256];
+
+ /* Initialize decryption table */
+ for (int i = 0; i < 256; i++)
+ decrypted[i] = ((i & 0x01) << 7) | ((i & 0x02) << 5) | ((i & 0x04) << 3) | ((i & 0x08) << 1) | ((i & 0x10) >> 1) | ((i & 0x20 ) >> 3) | ((i & 0x40) >> 5) | ((i & 0x80) >> 7);
+
+ /* Decrypt ROM image */
+ for (int i = 0; i < len; i++)
+ ROM[i] = decrypted[ROM[i]];
+ }
+
+ m_cart->rom_map_setup(len);
+
+ if (software_entry() == NULL)
+ m_type = get_cart_type(ROM, len);
+ else
+ {
+ const char *pcb_name = get_feature("slot");
+ if (pcb_name)
+ m_type = pce_get_pcb_id(pcb_name);
+ }
+ //printf("Type: %s\n", pce_get_slot(m_type));
+
+ if (m_type == PCE_POPULOUS)
+ m_cart->ram_alloc(machine(), 0x8000);
+ if (m_type == PCE_CDSYS3J || m_type == PCE_CDSYS3U)
+ m_cart->ram_alloc(machine(), 0x30000);
+
+ return IMAGE_INIT_PASS;
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+
+/*-------------------------------------------------
+ call_unload
+ -------------------------------------------------*/
+
+void pce_cart_slot_device::call_unload()
+{
+}
+
+
+/*-------------------------------------------------
+ call softlist load
+ -------------------------------------------------*/
+
+bool pce_cart_slot_device::call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry)
+{
+ load_software_part_region(*this, swlist, swname, start_entry );
+ return TRUE;
+}
+
+
+
+/*-------------------------------------------------
+ get_cart_type - code to detect NVRAM type from
+ fullpath
+ -------------------------------------------------*/
+
+int pce_cart_slot_device::get_cart_type(UINT8 *ROM, UINT32 len)
+{
+ int type = PCE_STD;
+
+ /* Check for Street fighter 2 */
+ if (len == 0x280000)
+ type = PCE_SF2;
+
+ /* Check for Populous */
+ if (len >= 0x1f26 + 8 && !memcmp(ROM + 0x1f26, "POPULOUS", 8))
+ type = PCE_POPULOUS;
+
+ // Check for CD system card v3 which adds on-cart RAM to the system
+ if (!memcmp(ROM + 0x3FFB6, "PC Engine CD-ROM SYSTEM", 23))
+ {
+ /* Check if 192KB additional system card ram should be used */
+ if(!memcmp(ROM + 0x29D1, "VER. 3.", 7)) { type = PCE_CDSYS3J; } // JP version
+ else if(!memcmp(ROM + 0x29C4, "VER. 3.", 7 )) { type = PCE_CDSYS3U; } // US version
+ }
+
+ return type;
+}
+
+
+/*-------------------------------------------------
+ get default card software
+ -------------------------------------------------*/
+
+void pce_cart_slot_device::get_default_card_software(astring &result)
+{
+ if (open_image_file(mconfig().options()))
+ {
+ const char *slot_string = "rom";
+ UINT32 len = core_fsize(m_file);
+ dynamic_buffer rom(len);
+ int type;
+
+ core_fread(m_file, rom, len);
+
+ type = get_cart_type(rom, len);
+ slot_string = pce_get_slot(type);
+
+ //printf("type: %s\n", slot_string);
+ clear();
+
+ result.cpy(slot_string);
+ return;
+ }
+
+ software_get_default_slot(result, "rom");
+}
+
+/*-------------------------------------------------
+ read
+ -------------------------------------------------*/
+
+READ8_MEMBER(pce_cart_slot_device::read_cart)
+{
+ if (m_cart)
+ return m_cart->read_cart(space, offset);
+ else
+ return 0xff;
+}
+
+/*-------------------------------------------------
+ write
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(pce_cart_slot_device::write_cart)
+{
+ if (m_cart)
+ m_cart->write_cart(space, offset, data);
+}
+
+
+/*-------------------------------------------------
+ Internal header logging
+ -------------------------------------------------*/
+
+void pce_cart_slot_device::internal_header_logging(UINT8 *ROM, UINT32 len)
+{
+}
diff --git a/src/emu/bus/pce/pce_slot.h b/src/emu/bus/pce/pce_slot.h
new file mode 100644
index 00000000000..655fffa57da
--- /dev/null
+++ b/src/emu/bus/pce/pce_slot.h
@@ -0,0 +1,126 @@
+#ifndef __PCE_SLOT_H
+#define __PCE_SLOT_H
+
+/***************************************************************************
+ TYPE DEFINITIONS
+ ***************************************************************************/
+
+
+/* PCB */
+enum
+{
+ PCE_STD = 0,
+ PCE_CDSYS3J,
+ PCE_CDSYS3U,
+ PCE_POPULOUS,
+ PCE_SF2
+};
+
+
+// ======================> device_pce_cart_interface
+
+class device_pce_cart_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_pce_cart_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_pce_cart_interface();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_cart) { return 0xff; }
+ virtual DECLARE_WRITE8_MEMBER(write_cart) {};
+
+ void rom_alloc(running_machine &machine, UINT32 size);
+ void ram_alloc(running_machine &machine, UINT32 size);
+ UINT8* get_rom_base() { return m_rom; }
+ UINT8* get_ram_base() { return m_ram; }
+ UINT32 get_rom_size() { return m_rom_size; }
+ UINT32 get_ram_size() { return m_ram_size; }
+
+ // internal state
+ UINT8 *m_rom;
+ UINT8 *m_ram;
+ UINT32 m_rom_size;
+ UINT32 m_ram_size;
+
+ void rom_map_setup(UINT32 size);
+
+ UINT8 rom_bank_map[8]; // 128K chunks of rom
+};
+
+
+// ======================> pce_cart_slot_device
+
+class pce_cart_slot_device : public device_t,
+ public device_image_interface,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ pce_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~pce_cart_slot_device();
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_config_complete();
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual void call_unload();
+ virtual bool call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry);
+
+ int get_type() { return m_type; }
+ int get_cart_type(UINT8 *ROM, UINT32 len);
+
+ void setup_ram(UINT8 banks);
+ void internal_header_logging(UINT8 *ROM, UINT32 len);
+
+ void set_intf(const char * interface) { m_interface = interface; }
+
+ virtual iodevice_t image_type() const { return IO_CARTSLOT; }
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 0; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 1; }
+ virtual bool is_reset_on_load() const { return 1; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+ virtual const char *image_interface() const { return m_interface; }
+ virtual const char *file_extensions() const { return "pce,bin"; }
+
+ // slot interface overrides
+ virtual void get_default_card_software(astring &result);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_cart);
+ virtual DECLARE_WRITE8_MEMBER(write_cart);
+
+
+protected:
+
+ const char *m_interface;
+ int m_type;
+ device_pce_cart_interface* m_cart;
+};
+
+
+
+// device type definition
+extern const device_type PCE_CART_SLOT;
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+ ***************************************************************************/
+
+#define MCFG_PCE_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot) \
+ MCFG_DEVICE_ADD(_tag, PCE_CART_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
+ static_cast<pce_cart_slot_device *>(device)->set_intf("pce_cart");
+
+#define MCFG_TG16_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot) \
+ MCFG_DEVICE_ADD(_tag, PCE_CART_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
+ static_cast<pce_cart_slot_device *>(device)->set_intf("tg16_cart");
+
+
+#endif
diff --git a/src/emu/bus/rs232/teleprinter.c b/src/emu/bus/rs232/teleprinter.c
new file mode 100644
index 00000000000..59ed867d5c4
--- /dev/null
+++ b/src/emu/bus/rs232/teleprinter.c
@@ -0,0 +1,239 @@
+#include "teleprinter.h"
+
+#define KEYBOARD_TAG "keyboard"
+
+static const UINT8 teleprinter_font[128*8] =
+{
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+ 0x38,0x38,0x38,0x38,0x00,0x00,0x00,0x00,
+ 0x3f,0x3f,0x3f,0x3f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,
+ 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+ 0x38,0x38,0x38,0x38,0x07,0x07,0x07,0x07,
+ 0x3f,0x3f,0x3f,0x3f,0x07,0x07,0x07,0x07,
+ 0x00,0x00,0x00,0x00,0x38,0x38,0x38,0x38,
+ 0x07,0x07,0x07,0x07,0x38,0x38,0x38,0x38,
+ 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,
+ 0x3f,0x3f,0x3f,0x3f,0x38,0x38,0x38,0x38,
+ 0x00,0x00,0x00,0x00,0x3f,0x3f,0x3f,0x3f,
+ 0x07,0x07,0x07,0x07,0x3f,0x3f,0x3f,0x3f,
+ 0x38,0x38,0x38,0x38,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x00,0x00,0x00,0x00,0x2a,0x15,0x2a,0x15,
+ 0x2a,0x15,0x2a,0x15,0x00,0x00,0x00,0x00,
+ 0x3f,0x3f,0x3f,0x3f,0x2a,0x15,0x2a,0x15,
+ 0x2a,0x15,0x2a,0x15,0x3f,0x3f,0x3f,0x3f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x08,0x08,0x08,0x08,0x08,0x00,0x08,0x00,
+ 0x14,0x14,0x14,0x00,0x00,0x00,0x00,0x00,
+ 0x14,0x14,0x3e,0x14,0x3e,0x14,0x14,0x00,
+ 0x08,0x3c,0x0a,0x1c,0x28,0x1e,0x08,0x00,
+ 0x06,0x26,0x10,0x08,0x04,0x32,0x30,0x00,
+ 0x08,0x14,0x14,0x0c,0x2a,0x12,0x2c,0x00,
+ 0x08,0x08,0x04,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x08,0x04,0x04,0x04,0x08,0x10,0x00,
+ 0x04,0x08,0x10,0x10,0x10,0x08,0x04,0x00,
+ 0x00,0x08,0x2a,0x1c,0x2a,0x08,0x00,0x00,
+ 0x00,0x08,0x08,0x3e,0x08,0x08,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x08,0x08,0x04,0x00,
+ 0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
+ 0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00,
+ 0x1c,0x22,0x32,0x2a,0x26,0x22,0x1c,0x00,
+ 0x08,0x0c,0x08,0x08,0x08,0x08,0x1c,0x00,
+ 0x1c,0x22,0x20,0x18,0x04,0x02,0x3e,0x00,
+ 0x3e,0x20,0x10,0x18,0x20,0x22,0x1c,0x00,
+ 0x10,0x18,0x14,0x12,0x3e,0x10,0x10,0x00,
+ 0x3e,0x02,0x1e,0x20,0x20,0x22,0x1c,0x00,
+ 0x10,0x08,0x04,0x1c,0x22,0x22,0x1c,0x00,
+ 0x3e,0x20,0x10,0x08,0x04,0x04,0x04,0x00,
+ 0x1c,0x22,0x22,0x1c,0x22,0x22,0x1c,0x00,
+ 0x1c,0x22,0x22,0x1c,0x10,0x08,0x04,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,
+ 0x00,0x00,0x08,0x00,0x08,0x08,0x04,0x00,
+ 0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x00,
+ 0x00,0x00,0x3e,0x00,0x3e,0x00,0x00,0x00,
+ 0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x00,
+ 0x1c,0x22,0x20,0x10,0x08,0x00,0x08,0x00,
+ 0x1c,0x22,0x32,0x2a,0x3a,0x02,0x3c,0x00,
+ 0x08,0x14,0x22,0x22,0x3e,0x22,0x22,0x00,
+ 0x1e,0x22,0x22,0x1e,0x22,0x22,0x1e,0x00,
+ 0x1c,0x22,0x02,0x02,0x02,0x22,0x1c,0x00,
+ 0x1e,0x24,0x24,0x24,0x24,0x24,0x1e,0x00,
+ 0x3e,0x02,0x02,0x1e,0x02,0x02,0x3e,0x00,
+ 0x3e,0x02,0x02,0x1e,0x02,0x02,0x02,0x00,
+ 0x1c,0x22,0x02,0x02,0x32,0x22,0x3c,0x00,
+ 0x22,0x22,0x22,0x3e,0x22,0x22,0x22,0x00,
+ 0x1c,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,
+ 0x38,0x10,0x10,0x10,0x10,0x12,0x0c,0x00,
+ 0x22,0x12,0x0a,0x06,0x0a,0x12,0x22,0x00,
+ 0x02,0x02,0x02,0x02,0x02,0x02,0x3e,0x00,
+ 0x22,0x36,0x2a,0x2a,0x22,0x22,0x22,0x00,
+ 0x22,0x22,0x26,0x2a,0x32,0x22,0x22,0x00,
+ 0x1c,0x22,0x22,0x22,0x22,0x22,0x1c,0x00,
+ 0x1e,0x22,0x22,0x1e,0x02,0x02,0x02,0x00,
+ 0x1c,0x22,0x22,0x22,0x2a,0x12,0x2c,0x00,
+ 0x1e,0x22,0x22,0x1e,0x0a,0x12,0x22,0x00,
+ 0x1c,0x22,0x02,0x1c,0x20,0x22,0x1c,0x00,
+ 0x3e,0x08,0x08,0x08,0x08,0x08,0x08,0x00,
+ 0x22,0x22,0x22,0x22,0x22,0x22,0x1c,0x00,
+ 0x22,0x22,0x22,0x14,0x14,0x08,0x08,0x00,
+ 0x22,0x22,0x22,0x2a,0x2a,0x2a,0x14,0x00,
+ 0x22,0x22,0x14,0x08,0x14,0x22,0x22,0x00,
+ 0x22,0x22,0x22,0x14,0x08,0x08,0x08,0x00,
+ 0x3e,0x20,0x10,0x08,0x04,0x02,0x3e,0x00,
+ 0x0e,0x02,0x02,0x02,0x02,0x02,0x0e,0x00,
+ 0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00,
+ 0x38,0x20,0x20,0x20,0x20,0x20,0x38,0x00,
+ 0x08,0x1c,0x2a,0x08,0x08,0x08,0x08,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,
+ 0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x1c,0x20,0x3c,0x22,0x3c,0x00,
+ 0x02,0x02,0x1e,0x22,0x22,0x22,0x1e,0x00,
+ 0x00,0x00,0x3c,0x02,0x02,0x02,0x3c,0x00,
+ 0x20,0x20,0x3c,0x22,0x22,0x22,0x3c,0x00,
+ 0x00,0x00,0x1c,0x22,0x3e,0x02,0x1c,0x00,
+ 0x18,0x04,0x0e,0x04,0x04,0x04,0x04,0x00,
+ 0x00,0x00,0x3c,0x22,0x22,0x3c,0x20,0x18,
+ 0x02,0x02,0x1e,0x22,0x22,0x22,0x22,0x00,
+ 0x08,0x00,0x0c,0x08,0x08,0x08,0x1c,0x00,
+ 0x10,0x00,0x18,0x10,0x10,0x10,0x12,0x0c,
+ 0x02,0x02,0x22,0x12,0x0e,0x16,0x22,0x00,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x00,
+ 0x00,0x00,0x16,0x2a,0x2a,0x2a,0x2a,0x00,
+ 0x00,0x00,0x1a,0x26,0x22,0x22,0x22,0x00,
+ 0x00,0x00,0x1c,0x22,0x22,0x22,0x1c,0x00,
+ 0x00,0x00,0x1e,0x22,0x22,0x1e,0x02,0x02,
+ 0x00,0x00,0x3c,0x22,0x22,0x3c,0x20,0x20,
+ 0x00,0x00,0x34,0x0c,0x04,0x04,0x04,0x00,
+ 0x00,0x00,0x3c,0x02,0x1c,0x20,0x1e,0x00,
+ 0x08,0x08,0x1c,0x08,0x08,0x08,0x10,0x00,
+ 0x00,0x00,0x22,0x22,0x22,0x32,0x2c,0x00,
+ 0x00,0x00,0x22,0x22,0x22,0x14,0x08,0x00,
+ 0x00,0x00,0x22,0x22,0x2a,0x2a,0x14,0x00,
+ 0x00,0x00,0x22,0x14,0x08,0x14,0x22,0x00,
+ 0x00,0x00,0x22,0x22,0x14,0x08,0x04,0x02,
+ 0x00,0x00,0x3e,0x10,0x08,0x04,0x3e,0x00,
+ 0x10,0x08,0x08,0x04,0x08,0x08,0x10,0x00,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,
+ 0x04,0x08,0x08,0x10,0x08,0x08,0x04,0x00,
+ 0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2a,0x15,0x2a,0x15,0x2a,0x15,0x2a,0x15
+};
+
+teleprinter_device::teleprinter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : generic_terminal_device(mconfig, TELEPRINTER, "Teleprinter", tag, owner, clock, "teleprinter", __FILE__)
+{
+}
+
+void teleprinter_device::scroll_line()
+{
+ memmove(m_buffer,m_buffer+TELEPRINTER_WIDTH,(TELEPRINTER_HEIGHT-1)*TELEPRINTER_WIDTH);
+ memset(m_buffer + TELEPRINTER_WIDTH*(TELEPRINTER_HEIGHT-1),0x20,TELEPRINTER_WIDTH);
+}
+
+void teleprinter_device::write_char(UINT8 data) {
+ m_buffer[(TELEPRINTER_HEIGHT-1)*TELEPRINTER_WIDTH+m_x_pos] = data;
+ m_x_pos++;
+ if (m_x_pos >= TELEPRINTER_WIDTH)
+ {
+ m_x_pos = 0;
+ scroll_line();
+ }
+}
+
+void teleprinter_device::clear() {
+ memset(m_buffer,0,TELEPRINTER_WIDTH*TELEPRINTER_HEIGHT);
+ m_x_pos = 0;
+}
+
+void teleprinter_device::term_write(UINT8 data)
+{
+ switch(data) {
+ case 10: m_x_pos = 0;
+ scroll_line();
+ break;
+ case 13: m_x_pos = 0; break;
+ case 9: m_x_pos = (m_x_pos & 0xf8) + 8;
+ if (m_x_pos >= TELEPRINTER_WIDTH)
+ m_x_pos = TELEPRINTER_WIDTH-1;
+
+ break;
+ case 16: break;
+ default: write_char(data); break;
+ }
+}
+
+/***************************************************************************
+ VIDEO HARDWARE
+***************************************************************************/
+UINT32 teleprinter_device::tp_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ UINT8 code;
+ int y, c, x, b;
+
+ for (y = 0; y < TELEPRINTER_HEIGHT; y++)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ int horpos = 0;
+ for (x = 0; x < TELEPRINTER_WIDTH; x++)
+ {
+ code = teleprinter_font[(m_buffer[y*TELEPRINTER_WIDTH + x] & 0x7f) *8 + c];
+ for (b = 0; b < 8; b++)
+ {
+ bitmap.pix32(y*8 + c, horpos++) = (code >> b) & 0x01 ? 0 : 0x00ffffff;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static ASCII_KEYBOARD_INTERFACE( keyboard_intf )
+{
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, generic_terminal_device, kbd_put)
+};
+
+/***************************************************************************
+ VIDEO HARDWARE
+***************************************************************************/
+MACHINE_CONFIG_FRAGMENT( generic_teleprinter )
+ MCFG_SCREEN_ADD(TELEPRINTER_SCREEN_TAG, RASTER)
+ MCFG_SCREEN_REFRESH_RATE(50)
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
+ MCFG_SCREEN_SIZE(TELEPRINTER_WIDTH*8, TELEPRINTER_HEIGHT*8)
+ MCFG_SCREEN_VISIBLE_AREA(0, TELEPRINTER_WIDTH*8-1, 0, TELEPRINTER_HEIGHT*8-1)
+ MCFG_SCREEN_UPDATE_DEVICE(DEVICE_SELF, teleprinter_device, tp_update)
+ MCFG_ASCII_KEYBOARD_ADD(KEYBOARD_TAG, keyboard_intf)
+MACHINE_CONFIG_END
+
+machine_config_constructor teleprinter_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME(generic_teleprinter);
+}
+
+/*-------------------------------------------------
+ device_reset - device-specific reset
+-------------------------------------------------*/
+
+void teleprinter_device::device_reset()
+{
+ clear();
+ generic_terminal_device::device_reset();
+}
+
+const device_type TELEPRINTER = &device_creator<teleprinter_device>;
diff --git a/src/emu/bus/rs232/teleprinter.h b/src/emu/bus/rs232/teleprinter.h
new file mode 100644
index 00000000000..e73e687e49f
--- /dev/null
+++ b/src/emu/bus/rs232/teleprinter.h
@@ -0,0 +1,45 @@
+#ifndef __TELEPRINTER_H__
+#define __TELEPRINTER_H__
+
+#include "machine/terminal.h"
+
+#define TELEPRINTER_WIDTH 80
+#define TELEPRINTER_HEIGHT 50
+
+#define GENERIC_TELEPRINTER_INTERFACE GENERIC_TERMINAL_INTERFACE
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+#define TELEPRINTER_TAG "teleprinter"
+#define TELEPRINTER_SCREEN_TAG "tty_screen"
+
+#define MCFG_GENERIC_TELEPRINTER_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, TELEPRINTER, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_GENERIC_TELEPRINTER_REMOVE(_tag) \
+ MCFG_DEVICE_REMOVE(_tag)
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+class teleprinter_device : public generic_terminal_device
+{
+public:
+ teleprinter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ UINT32 tp_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+protected:
+ virtual void term_write(UINT8 data);
+ virtual void device_reset();
+ virtual machine_config_constructor device_mconfig_additions() const;
+private:
+ void scroll_line();
+ void write_char(UINT8 data);
+ void clear();
+};
+
+extern const device_type TELEPRINTER;
+
+#endif /* __TELEPRINTER_H__ */
diff --git a/src/emu/bus/x68k/x68k_neptunex.c b/src/emu/bus/x68k/x68k_neptunex.c
new file mode 100644
index 00000000000..fb6fcf4bff7
--- /dev/null
+++ b/src/emu/bus/x68k/x68k_neptunex.c
@@ -0,0 +1,152 @@
+/*
+ * x68k_neptunex.c
+ */
+
+#include "emu.h"
+#include "machine/dp8390.h"
+#include "x68k_neptunex.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type X68K_NEPTUNEX = &device_creator<x68k_neptune_device>;
+
+static const dp8390_interface neptune_dp8390_interface = {
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, x68k_neptune_device, x68k_neptune_irq_w),
+ DEVCB_NULL,
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, x68k_neptune_device, x68k_neptune_mem_read),
+ DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, x68k_neptune_device, x68k_neptune_mem_write)
+};
+
+
+// device machine config
+static MACHINE_CONFIG_FRAGMENT( x68k_neptunex )
+ MCFG_DP8390D_ADD("dp8390d", neptune_dp8390_interface)
+MACHINE_CONFIG_END
+
+machine_config_constructor x68k_neptune_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( x68k_neptunex );
+}
+
+x68k_neptune_device::x68k_neptune_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, X68K_NEPTUNEX, "Neptune-X", tag, owner, clock, "x68k_neptunex", __FILE__),
+ device_x68k_expansion_card_interface(mconfig, *this),
+ m_dp8390(*this, "dp8390d")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void x68k_neptune_device::device_start()
+{
+ device_t* cpu = machine().device("maincpu");
+ char mac[7];
+ UINT32 num = rand();
+ address_space& space = cpu->memory().space(AS_PROGRAM);
+ m_slot = dynamic_cast<x68k_expansion_slot_device *>(owner());
+ memset(m_prom, 0x57, 16);
+ sprintf(mac+2, "\x1b%c%c%c", (num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff);
+ mac[0] = 0; mac[1] = 0; // avoid gcc warning
+ memcpy(m_prom, mac, 6);
+ m_dp8390->set_mac(mac);
+ space.install_readwrite_handler(0xece000,0xece3ff,read16_delegate(FUNC(x68k_neptune_device::x68k_neptune_port_r),this),write16_delegate(FUNC(x68k_neptune_device::x68k_neptune_port_w),this),0xffffffff);
+}
+
+void x68k_neptune_device::device_reset() {
+ memcpy(m_prom, m_dp8390->get_mac(), 6);
+}
+
+READ16_MEMBER(x68k_neptune_device::x68k_neptune_port_r)
+{
+ UINT16 data;
+
+ if(offset >= 0x100+32 || offset < 0x100)
+ return 0xffff;
+ if(offset < 0x100+16)
+ {
+ m_dp8390->dp8390_cs(CLEAR_LINE);
+ return (m_dp8390->dp8390_r(space, offset, 0xff) << 8)|
+ m_dp8390->dp8390_r(space, offset+1, 0xff);
+ }
+ //if(mem_mask == 0x00ff) offset++;
+ switch(offset)
+ {
+ case 0x100+16:
+ m_dp8390->dp8390_cs(ASSERT_LINE);
+ data = m_dp8390->dp8390_r(space, offset, mem_mask);
+ data = ((data & 0x00ff) << 8) | ((data & 0xff00) >> 8);
+ return data;
+ case 0x100+31:
+ m_dp8390->dp8390_reset(CLEAR_LINE);
+ return 0;
+ default:
+ logerror("ne2000: invalid register read %02X\n", offset);
+ }
+ return 0;
+}
+
+WRITE16_MEMBER(x68k_neptune_device::x68k_neptune_port_w)
+{
+ if(offset >= 0x100+32 || offset < 0x100)
+ return;
+ if(offset < 0x100+16)
+ {
+ m_dp8390->dp8390_cs(CLEAR_LINE);
+ if(mem_mask == 0x00ff)
+ {
+ data <<= 8;
+ offset++;
+ }
+ m_dp8390->dp8390_w(space, offset, data>>8, 0xff);
+ if(mem_mask == 0xffff) m_dp8390->dp8390_w(space, offset+1, data & 0xff, 0xff);
+ return;
+ }
+ //if(mem_mask == 0x00ff) offset++;
+ switch(offset)
+ {
+ case 0x100+16:
+ m_dp8390->dp8390_cs(ASSERT_LINE);
+ data = ((data & 0x00ff) << 8) | ((data & 0xff00) >> 8);
+ m_dp8390->dp8390_w(space, offset, data, mem_mask);
+ return;
+ case 0x100+31:
+ m_dp8390->dp8390_reset(ASSERT_LINE);
+ return;
+ default:
+ logerror("ne2000: invalid register write %02X\n", offset);
+ }
+ return;
+}
+
+READ8_MEMBER(x68k_neptune_device::x68k_neptune_mem_read)
+{
+ if(offset < 32) return m_prom[offset>>1];
+ if((offset < (16*1024)) || (offset >= (32*1024)))
+ {
+ logerror("ne2000: invalid memory read %04X\n", offset);
+ return 0xff;
+ }
+ return m_board_ram[offset - (16*1024)];
+}
+
+WRITE8_MEMBER(x68k_neptune_device::x68k_neptune_mem_write)
+{
+ if((offset < (16*1024)) || (offset >= (32*1024)))
+ {
+ logerror("ne2000: invalid memory write %04X\n", offset);
+ return;
+ }
+ m_board_ram[offset - (16*1024)] = data;
+}
+
+WRITE_LINE_MEMBER(x68k_neptune_device::x68k_neptune_irq_w)
+{
+ machine().device("maincpu")->execute().set_input_line_vector(2, NEPTUNE_IRQ_VECTOR);
+ m_slot->irq2_w(state);
+ logerror("Neptune: IRQ2 set to %i\n",state);
+}
diff --git a/src/emu/bus/x68k/x68k_neptunex.h b/src/emu/bus/x68k/x68k_neptunex.h
new file mode 100644
index 00000000000..277f902c74e
--- /dev/null
+++ b/src/emu/bus/x68k/x68k_neptunex.h
@@ -0,0 +1,52 @@
+/*
+ * x68k_neptunex.h
+ *
+ * Neptune-X NE2000-based ethernet board for the X68000
+ *
+ * Map:
+ * 0xECE000-0xECE3FF: "Y0"
+ * 0xECE400-0xECE7FF: "Y1"
+ */
+
+#ifndef X68K_NEPTUNEX_H_
+#define X68K_NEPTUNEX_H_
+
+#include "emu.h"
+#include "machine/dp8390.h"
+#include "x68kexp.h"
+
+#define NEPTUNE_IRQ_VECTOR 0xf9
+
+class x68k_neptune_device : public device_t,
+ public device_x68k_expansion_card_interface
+{
+public:
+ // construction/destruction
+ x68k_neptune_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ void x68k_neptune_irq_w(int state);
+ DECLARE_READ8_MEMBER(x68k_neptune_mem_read);
+ DECLARE_WRITE8_MEMBER(x68k_neptune_mem_write);
+ DECLARE_READ16_MEMBER(x68k_neptune_port_r);
+ DECLARE_WRITE16_MEMBER(x68k_neptune_port_w);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ x68k_expansion_slot_device *m_slot;
+
+ required_device<dp8390d_device> m_dp8390;
+ UINT8 m_board_ram[16*1024];
+ UINT8 m_prom[16];
+};
+
+// device type definition
+extern const device_type X68K_NEPTUNEX;
+
+#endif /* X68K_NEPTUNEX_H_ */
diff --git a/src/emu/bus/x68k/x68k_scsiext.c b/src/emu/bus/x68k/x68k_scsiext.c
new file mode 100644
index 00000000000..65c7dd01264
--- /dev/null
+++ b/src/emu/bus/x68k/x68k_scsiext.c
@@ -0,0 +1,102 @@
+/*
+ * x68k_scsiext.c
+ *
+ * Sharp CZ-6BS1 SCSI-1 controller
+ *
+ * Created on: 5/06/2012
+ */
+
+#include "emu.h"
+#include "machine/scsibus.h"
+#include "machine/scsihd.h"
+#include "machine/mb89352.h"
+#include "x68k_scsiext.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type X68K_SCSIEXT = &device_creator<x68k_scsiext_device>;
+
+static const mb89352_interface mb89352_intf =
+{
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER,x68k_scsiext_device,irq_w),
+ DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER,x68k_scsiext_device,drq_w)
+};
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( x68k_cz6bs1 )
+ ROM_REGION( 0x10000, "scsiexrom", 0 )
+ ROM_LOAD16_WORD_SWAP( "scsiexrom.bin", 0x0000, 0x2000, CRC(7be488de) SHA1(49616c09a8986ffe6a12ad600febe512f7ba8ae4) )
+ROM_END
+
+const rom_entry *x68k_scsiext_device::device_rom_region() const
+{
+ return ROM_NAME( x68k_cz6bs1 );
+}
+
+// device machine config
+static MACHINE_CONFIG_FRAGMENT( x68k_scsiext )
+ MCFG_SCSIBUS_ADD("scsi")
+ MCFG_SCSIDEV_ADD("scsi:harddisk0", SCSIHD, SCSI_ID_0)
+ MCFG_SCSIDEV_ADD("scsi:harddisk1", SCSIHD, SCSI_ID_1)
+ MCFG_SCSIDEV_ADD("scsi:harddisk2", SCSIHD, SCSI_ID_2)
+ MCFG_SCSIDEV_ADD("scsi:harddisk3", SCSIHD, SCSI_ID_3)
+ MCFG_SCSIDEV_ADD("scsi:harddisk4", SCSIHD, SCSI_ID_4)
+ MCFG_SCSIDEV_ADD("scsi:harddisk5", SCSIHD, SCSI_ID_5)
+ MCFG_SCSIDEV_ADD("scsi:harddisk6", SCSIHD, SCSI_ID_6)
+ MCFG_MB89352A_ADD("scsi:mb89352",mb89352_intf)
+MACHINE_CONFIG_END
+
+machine_config_constructor x68k_scsiext_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( x68k_scsiext );
+}
+
+x68k_scsiext_device::x68k_scsiext_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, X68K_SCSIEXT, "Sharp CZ-6BS1 SCSI-1", tag, owner, clock, "x68k_cz6bs1", __FILE__),
+ device_x68k_expansion_card_interface(mconfig, *this),
+ m_spc(*this, "scsi:mb89352")
+{
+}
+
+void x68k_scsiext_device::device_start()
+{
+ device_t* cpu = machine().device("maincpu");
+ UINT8* ROM;
+ astring temp;
+ address_space& space = cpu->memory().space(AS_PROGRAM);
+ m_slot = dynamic_cast<x68k_expansion_slot_device *>(owner());
+ space.install_read_bank(0xea0020,0xea1fff,0,0,"scsi_ext");
+ space.unmap_write(0xea0020,0xea1fff,0,0);
+ ROM = machine().root_device().memregion(subtag(temp,"scsiexrom"))->base();
+ machine().root_device().membank("scsi_ext")->set_base(ROM);
+ space.install_readwrite_handler(0xea0000,0xea001f,0,0,read8_delegate(FUNC(x68k_scsiext_device::register_r),this),write8_delegate(FUNC(x68k_scsiext_device::register_w),this),0x00ff00ff);
+}
+
+void x68k_scsiext_device::device_reset()
+{
+}
+
+void x68k_scsiext_device::irq_w(int state)
+{
+ m_slot->irq2_w(state); // correct? Or perhaps selectable?
+}
+
+void x68k_scsiext_device::drq_w(int state)
+{
+ // TODO
+}
+
+READ8_MEMBER(x68k_scsiext_device::register_r)
+{
+ return m_spc->mb89352_r(space,offset);
+}
+
+WRITE8_MEMBER(x68k_scsiext_device::register_w)
+{
+ m_spc->mb89352_w(space,offset,data);
+}
diff --git a/src/emu/bus/x68k/x68k_scsiext.h b/src/emu/bus/x68k/x68k_scsiext.h
new file mode 100644
index 00000000000..74550ff8eb1
--- /dev/null
+++ b/src/emu/bus/x68k/x68k_scsiext.h
@@ -0,0 +1,44 @@
+/*
+ * x68k_scsiext.h
+ *
+ * Created on: 5/06/2012
+ */
+
+#ifndef X68K_SCSIEXT_H_
+#define X68K_SCSIEXT_H_
+
+#include "emu.h"
+#include "machine/mb89352.h"
+#include "x68kexp.h"
+
+class x68k_scsiext_device : public device_t,
+ public device_x68k_expansion_card_interface
+{
+public:
+ // construction/destruction
+ x68k_scsiext_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual const rom_entry *device_rom_region() const;
+
+ void irq_w(int state);
+ void drq_w(int state);
+ DECLARE_READ8_MEMBER(register_r);
+ DECLARE_WRITE8_MEMBER(register_w);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+private:
+ x68k_expansion_slot_device *m_slot;
+
+ required_device<mb89352_device> m_spc;
+};
+
+// device type definition
+extern const device_type X68K_SCSIEXT;
+
+
+#endif /* X68K_SCSIEXT_H_ */
diff --git a/src/emu/bus/x68k/x68kexp.c b/src/emu/bus/x68k/x68kexp.c
new file mode 100644
index 00000000000..f84319eda81
--- /dev/null
+++ b/src/emu/bus/x68k/x68kexp.c
@@ -0,0 +1,98 @@
+/*
+ * x68kexp.c
+ */
+
+#include "emu.h"
+#include "emuopts.h"
+#include "x68kexp.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type X68K_EXPANSION_SLOT = &device_creator<x68k_expansion_slot_device>;
+
+
+//**************************************************************************
+// DEVICE CPC_EXPANSION CARD INTERFACE
+//**************************************************************************
+
+
+device_x68k_expansion_card_interface::device_x68k_expansion_card_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device)
+{
+}
+
+
+device_x68k_expansion_card_interface::~device_x68k_expansion_card_interface()
+{
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+x68k_expansion_slot_device::x68k_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, X68K_EXPANSION_SLOT, "Sharp X680x0 expansion slot", tag, owner, clock, "x68k_expansion_slot", __FILE__),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+x68k_expansion_slot_device::~x68k_expansion_slot_device()
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void x68k_expansion_slot_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const x68k_expansion_slot_interface *intf = reinterpret_cast<const x68k_expansion_slot_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<x68k_expansion_slot_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_irq2_cb, 0, sizeof(m_out_irq2_cb));
+ memset(&m_out_irq4_cb, 0, sizeof(m_out_irq4_cb));
+ memset(&m_out_nmi_cb, 0, sizeof(m_out_nmi_cb));
+ memset(&m_out_reset_cb, 0, sizeof(m_out_reset_cb));
+ }
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void x68k_expansion_slot_device::device_start()
+{
+ m_card = dynamic_cast<device_x68k_expansion_card_interface *>(get_card_device());
+
+ // resolve callbacks
+ m_out_irq2_func.resolve(m_out_irq2_cb, *this);
+ m_out_irq4_func.resolve(m_out_irq4_cb, *this);
+ m_out_nmi_func.resolve(m_out_nmi_cb, *this);
+ m_out_reset_func.resolve(m_out_reset_cb, *this);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void x68k_expansion_slot_device::device_reset()
+{
+}
+
+
+WRITE_LINE_MEMBER( x68k_expansion_slot_device::irq2_w ) { m_out_irq2_func(state); }
+WRITE_LINE_MEMBER( x68k_expansion_slot_device::irq4_w ) { m_out_irq4_func(state); }
+WRITE_LINE_MEMBER( x68k_expansion_slot_device::nmi_w ) { m_out_nmi_func(state); }
+WRITE_LINE_MEMBER( x68k_expansion_slot_device::reset_w ) { m_out_reset_func(state); }
diff --git a/src/emu/bus/x68k/x68kexp.h b/src/emu/bus/x68k/x68kexp.h
new file mode 100644
index 00000000000..05c384aae6c
--- /dev/null
+++ b/src/emu/bus/x68k/x68kexp.h
@@ -0,0 +1,149 @@
+/*
+ * x68kexp.h
+ *
+ * Expansion slots for the X680x0 series
+ *
+ * Pinout: (from http://www.amy.hi-ho.ne.jp/shimada/neptune/x68k.html)
+ +-----+
+ GND B1 |[] []| A1 GND
+ 10MHz B2 |[] []| A2 20MHz
+ #10MHz B3 |[] []| A3 GND
+ E B4 |[] []| A4 DB0
+ AB1 B5 |[] []| A5 DB1
+ AB2 B6 |[] []| A6 DB2
+ AB3 B7 |[] []| A7 DB3
+ AB4 B8 |[] []| A8 DB4
+ AB5 B9 |[] []| A9 DB5
+ AB6 B10 |[] []| A10 DB6
+ GND B11 |[] []| A11 GND
+ AB7 B12 |[] []| A12 DB7
+ AB8 B13 |[] []| A13 DB8
+ AB9 B14 |[] []| A14 DB9
+ AB10 B15 |[] []| A15 DB10
+ AB11 B16 |[] []| A16 DB11
+ AB12 B17 |[] []| A17 DB12
+ AB13 B18 |[] []| A18 DB13
+ AB14 B19 |[] []| A19 DB14
+ AB15 B20 |[] []| A20 DB15
+ GND B21 |[] []| A21 GND
+ AB16 B22 |[] []| A22 +12V
+ AB17 B23 |[] []| A23 +12V
+ AB18 B24 |[] []| A24 FC0
+ AB19 B25 |[] []| A25 FC1
+ AB20 B26 |[] []| A26 FC2
+ AB21 B27 |[] []| A27 #AS
+ AB22 B28 |[] []| A28 #LDS
+ AB23 B29 |[] []| A29 #UDS
+ IDDIR B30 |[] []| A30 R/#W
+ N.C. B31 |[] []| A31 N.C.
+ HSYNC B32 |[] []| A32 -12V
+ VSYNC B33 |[] []| A33 -12V
+ #DONE B34 |[] []| A34 #VMA
+ #DTC B35 |[] []| A35 #EXVPA
+ #EXREQ B36 |[] []| A36 #DTACK
+ #EXACK B37 |[] []| A37 #EXRESET
+ #EXPCL B38 |[] []| A38 #HALT
+ #EXOWN B39 |[] []| A39 #EXBERR
+ #EXNMI B40 |[] []| A40 #EXPWON
+ GND B41 |[] []| A41 GND
+ #IRQ2 B42 |[] []| A42 Vcc2
+ #IRQ4 B43 |[] []| A43 Vcc2
+ #IACK2 B44 |[] []| A44 SELEN
+ #IACK4 B45 |[] []| A45 CASRDEN
+ #BR B46 |[] []| A46 CASWRL
+ #BG B47 |[] []| A47 CASWRU
+ #BGACK B48 |[] []| A48 INH2
+ Vcc1 B49 |[] []| A49 Vcc1
+ Vcc1 B50 |[] []| A50 Vcc1
+ +-----+
+ *
+ */
+
+#ifndef X68KEXP_H_
+#define X68KEXP_H_
+
+#include "emu.h"
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define X68K_EXP_SLOT_TAG "x68kexp"
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define X68K_EXPANSION_INTERFACE(_name) \
+ const x68k_expansion_slot_interface (_name) =
+
+
+#define MCFG_X68K_EXPANSION_SLOT_ADD(_tag, _config, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, X68K_EXPANSION_SLOT, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// expansion slot interface
+
+struct x68k_expansion_slot_interface
+{
+ devcb_write_line m_out_irq2_cb;
+ devcb_write_line m_out_irq4_cb;
+ devcb_write_line m_out_nmi_cb;
+ devcb_write_line m_out_reset_cb;
+};
+
+// ======================> device_x68k_expansion_card_interface
+
+// class representing interface-specific live x68k_expansion card
+class device_x68k_expansion_card_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_x68k_expansion_card_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_x68k_expansion_card_interface();
+
+ // reset
+ virtual void x68k_reset_w() { };
+};
+
+
+// ======================> x68k_expansion_slot_device
+
+class x68k_expansion_slot_device : public device_t,
+ public x68k_expansion_slot_interface,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ x68k_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~x68k_expansion_slot_device();
+
+ DECLARE_WRITE_LINE_MEMBER( irq2_w );
+ DECLARE_WRITE_LINE_MEMBER( irq4_w );
+ DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ DECLARE_WRITE_LINE_MEMBER( reset_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_config_complete();
+
+ devcb_resolved_write_line m_out_irq2_func;
+ devcb_resolved_write_line m_out_irq4_func;
+ devcb_resolved_write_line m_out_nmi_func;
+ devcb_resolved_write_line m_out_reset_func;
+
+ device_x68k_expansion_card_interface *m_card;
+};
+
+
+// device type definition
+extern const device_type X68K_EXPANSION_SLOT;
+
+#endif /* X68KEXP_H_ */
diff --git a/src/emu/machine/ds1315.c b/src/emu/machine/ds1315.c
new file mode 100644
index 00000000000..c64ee315962
--- /dev/null
+++ b/src/emu/machine/ds1315.c
@@ -0,0 +1,218 @@
+/*********************************************************************
+
+ ds1315.c
+
+ Dallas Semiconductor's Phantom Time Chip DS1315.
+
+ by tim lindner, November 2001.
+
+*********************************************************************/
+
+#include "ds1315.h"
+#include "coreutil.h"
+
+
+const device_type DS1315 = &device_creator<ds1315_device>;
+
+ds1315_device::ds1315_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, DS1315, "Dallas Semiconductor DS1315", tag, owner, clock, "ds1315", __FILE__)
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void ds1315_device::device_config_complete()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ds1315_device::device_start()
+{
+ save_item(NAME(m_count));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_raw_data));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ds1315_device::device_reset()
+{
+ memset(m_raw_data, 0, sizeof(m_raw_data));
+ m_count = 0;
+ m_mode = DS_SEEK_MATCHING;
+}
+
+
+/***************************************************************************
+ LOCAL VARIABLES
+***************************************************************************/
+
+static const UINT8 ds1315_pattern[] =
+{
+ 1, 0, 1, 0, 0, 0, 1, 1,
+ 0, 1, 0, 1, 1, 1, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 1,
+ 0, 0, 1, 1, 1, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0, 1, 1,
+ 0, 1, 0, 1, 1, 1, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 1,
+ 0, 0, 1, 1, 1, 0, 1, 0
+};
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ read_0
+ -------------------------------------------------*/
+
+READ8_MEMBER( ds1315_device::read_0 )
+{
+ if (ds1315_pattern[m_count++] == 0)
+ {
+ if (m_count == 64)
+ {
+ /* entire pattern matched */
+ m_count = 0;
+ m_mode = DS_CALENDAR_IO;
+ fill_raw_data();
+ }
+
+ return 0;
+ }
+
+ m_count = 0;
+ m_mode = DS_SEEK_MATCHING;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ read_1
+-------------------------------------------------*/
+
+READ8_MEMBER( ds1315_device::read_1 )
+{
+ if (ds1315_pattern[m_count++] == 1)
+ {
+ m_count %= 64;
+ return 0;
+ }
+
+ m_count = 0;
+ m_mode = DS_SEEK_MATCHING;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ read_data
+-------------------------------------------------*/
+
+READ8_MEMBER( ds1315_device::read_data )
+{
+ UINT8 result;
+
+ if (m_mode == DS_CALENDAR_IO)
+ {
+ result = m_raw_data[m_count++];
+
+ if (m_count == 64)
+ {
+ m_mode = DS_SEEK_MATCHING;
+ m_count = 0;
+ }
+
+ return result;
+ }
+
+ m_count = 0;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ write_data
+-------------------------------------------------*/
+
+WRITE8_MEMBER( ds1315_device::write_data )
+{
+ if (m_mode == DS_CALENDAR_IO)
+ {
+ m_raw_data[m_count++] = data & 0x01;
+
+ if (m_count == 64)
+ {
+ m_mode = DS_SEEK_MATCHING;
+ m_count = 0;
+ input_raw_data();
+ }
+ return;
+ }
+
+ m_count = 0;
+}
+
+
+/*-------------------------------------------------
+ fill_raw_data
+-------------------------------------------------*/
+
+void ds1315_device::fill_raw_data()
+{
+ /* This routine will (hopefully) call a standard 'C' library routine to get the current
+ date and time and then fill in the raw data struct.
+ */
+
+ system_time systime;
+ int raw[8], i, j;
+
+ /* get the current date/time from the core */
+ machine().current_datetime(systime);
+
+ raw[0] = 0; /* tenths and hundreths of seconds are always zero */
+ raw[1] = dec_2_bcd(systime.local_time.second);
+ raw[2] = dec_2_bcd(systime.local_time.minute);
+ raw[3] = dec_2_bcd(systime.local_time.hour);
+
+ raw[4] = dec_2_bcd((systime.local_time.weekday != 0) ? systime.local_time.weekday : 7);
+ raw[5] = dec_2_bcd(systime.local_time.mday);
+ raw[6] = dec_2_bcd(systime.local_time.month + 1);
+ raw[7] = dec_2_bcd(systime.local_time.year - 1900); /* Epoch is 1900 */
+
+ /* Ok now we have the raw bcd bytes. Now we need to push them into our bit array */
+
+ for (i = 0; i < 64; i++)
+ {
+ j = i / 8;
+ m_raw_data[i] = (raw[j] & 0x0001);
+ raw[j] = raw[j] >> 1;
+ }
+}
+
+
+/*-------------------------------------------------
+ ds1315_input_raw_data
+-------------------------------------------------*/
+
+void ds1315_device::input_raw_data()
+{
+ /* This routine is called when new date and time has been written to the
+ clock chip. Currently we ignore setting the date and time in the clock
+ chip.
+
+ We always return the host's time when asked.
+ */
+}
diff --git a/src/emu/machine/ds1315.h b/src/emu/machine/ds1315.h
new file mode 100644
index 00000000000..d4ab0cfb967
--- /dev/null
+++ b/src/emu/machine/ds1315.h
@@ -0,0 +1,67 @@
+/*********************************************************************
+
+ ds1315.h
+
+ Dallas Semiconductor's Phantom Time Chip DS1315.
+
+ by tim lindner, November 2001.
+
+*********************************************************************/
+
+#ifndef __DS1315_H__
+#define __DS1315_H__
+
+#include "emu.h"
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+enum ds1315_mode_t
+{
+ DS_SEEK_MATCHING,
+ DS_CALENDAR_IO
+};
+
+ALLOW_SAVE_TYPE(ds1315_mode_t);
+
+class ds1315_device : public device_t
+{
+public:
+ ds1315_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ ~ds1315_device() {}
+
+ DECLARE_READ8_MEMBER(read_0);
+ DECLARE_READ8_MEMBER(read_1);
+ DECLARE_READ8_MEMBER(read_data);
+ DECLARE_WRITE8_MEMBER(write_data);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ // internal state
+
+ void fill_raw_data();
+ void input_raw_data();
+
+ int m_count;
+ ds1315_mode_t m_mode;
+ UINT8 m_raw_data[8*8];
+};
+
+extern const device_type DS1315;
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_DS1315_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, DS1315, 0)
+
+
+#endif /* __DS1315_H__ */
diff --git a/src/emu/machine/machine.mak b/src/emu/machine/machine.mak
index 7d0f729b890..afb6096b58f 100644
--- a/src/emu/machine/machine.mak
+++ b/src/emu/machine/machine.mak
@@ -401,6 +401,15 @@ endif
#-------------------------------------------------
#
+#@src/emu/machine/ds1315.h,MACHINES += DS1315
+#-------------------------------------------------
+
+ifneq ($(filter DS1315,$(MACHINES)),)
+MACHINEOBJS += $(MACHINEOBJ)/ds1315.o
+endif
+
+#-------------------------------------------------
+#
#@src/emu/machine/ds2401.h,MACHINES += DS2401
#-------------------------------------------------