summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ieee488
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
committer Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
commitf88cefad27a1737c76e09d99c9fb43e173506081 (patch)
tree2d8167d03579c46e226471747eb4407bd00ed6fa /src/devices/bus/ieee488
parente92ac9e0fa8e99869894bea00589bbb526be30aa (diff)
Move all devices into separate part of src tree (nw)
Diffstat (limited to 'src/devices/bus/ieee488')
-rw-r--r--src/devices/bus/ieee488/c2031.c482
-rw-r--r--src/devices/bus/ieee488/c2031.h87
-rw-r--r--src/devices/bus/ieee488/c2040.c802
-rw-r--r--src/devices/bus/ieee488/c2040.h133
-rw-r--r--src/devices/bus/ieee488/c2040fdc.c623
-rw-r--r--src/devices/bus/ieee488/c2040fdc.h168
-rw-r--r--src/devices/bus/ieee488/c8050.c950
-rw-r--r--src/devices/bus/ieee488/c8050.h140
-rw-r--r--src/devices/bus/ieee488/c8050fdc.c634
-rw-r--r--src/devices/bus/ieee488/c8050fdc.h170
-rw-r--r--src/devices/bus/ieee488/c8280.c527
-rw-r--r--src/devices/bus/ieee488/c8280.h90
-rw-r--r--src/devices/bus/ieee488/d9060.c578
-rw-r--r--src/devices/bus/ieee488/d9060.h122
-rw-r--r--src/devices/bus/ieee488/hardbox.c401
-rw-r--r--src/devices/bus/ieee488/hardbox.h77
-rw-r--r--src/devices/bus/ieee488/ieee488.c396
-rw-r--r--src/devices/bus/ieee488/ieee488.h253
-rw-r--r--src/devices/bus/ieee488/shark.c144
-rw-r--r--src/devices/bus/ieee488/shark.h52
-rw-r--r--src/devices/bus/ieee488/softbox.c393
-rw-r--r--src/devices/bus/ieee488/softbox.h82
22 files changed, 7304 insertions, 0 deletions
diff --git a/src/devices/bus/ieee488/c2031.c b/src/devices/bus/ieee488/c2031.c
new file mode 100644
index 00000000000..b26c27c2ff6
--- /dev/null
+++ b/src/devices/bus/ieee488/c2031.c
@@ -0,0 +1,482 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 2031 Single Disk Drive emulation
+
+**********************************************************************/
+
+#include "c2031.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define M6502_TAG "ucd5"
+#define M6522_0_TAG "uab1"
+#define M6522_1_TAG "ucd4"
+#define C64H156_TAG "64h156"
+
+
+enum
+{
+ LED_POWER = 0,
+ LED_ACT
+};
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type C2031 = &device_creator<c2031_device>;
+
+
+//-------------------------------------------------
+// ROM( c2031 )
+//-------------------------------------------------
+
+ROM_START( c2031 )
+ ROM_REGION( 0x4000, M6502_TAG, 0 )
+ ROM_LOAD( "901484-03.u5f", 0x0000, 0x2000, CRC(ee4b893b) SHA1(54d608f7f07860f24186749f21c96724dd48bc50) )
+ ROM_LOAD( "901484-05.u5h", 0x2000, 0x2000, CRC(6a629054) SHA1(ec6b75ecfdd4744e5d57979ef6af990444c11ae1) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c2031_device::device_rom_region() const
+{
+ return ROM_NAME( c2031 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c2031_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c2031_mem, AS_PROGRAM, 8, c2031_device )
+ AM_RANGE(0x0000, 0x07ff) AM_MIRROR(0x6000) AM_RAM
+ AM_RANGE(0x1800, 0x180f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_0_TAG, via6522_device, read, write)
+ AM_RANGE(0x1c00, 0x1c0f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_1_TAG, via6522_device, read, write)
+ AM_RANGE(0x8000, 0xbfff) AM_MIRROR(0x4000) AM_ROM AM_REGION(M6502_TAG, 0)
+ADDRESS_MAP_END
+
+
+WRITE_LINE_MEMBER( c2031_device::via0_irq_w )
+{
+ m_via0_irq = state;
+
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+READ8_MEMBER( c2031_device::via0_pa_r )
+{
+ /*
+
+ bit description
+
+ PA0 DI0
+ PA1 DI1
+ PA2 DI2
+ PA3 DI3
+ PA4 DI4
+ PA5 DI5
+ PA6 DI6
+ PA7 DI7
+
+ */
+
+ return m_bus->dio_r();
+}
+
+WRITE8_MEMBER( c2031_device::via0_pa_w )
+{
+ /*
+
+ bit description
+
+ PA0 DI0
+ PA1 DI1
+ PA2 DI2
+ PA3 DI3
+ PA4 DI4
+ PA5 DI5
+ PA6 DI6
+ PA7 DI7
+
+ */
+
+ m_bus->dio_w(this, data);
+}
+
+READ8_MEMBER( c2031_device::via0_pb_r )
+{
+ /*
+
+ bit description
+
+ PB0 ATNA
+ PB1 NRFD
+ PB2 NDAC
+ PB3 EOI
+ PB4 T/_R
+ PB5 HD SEL
+ PB6 DAV
+ PB7 _ATN
+
+ */
+
+ UINT8 data = 0;
+
+ // not ready for data
+ data |= m_bus->nrfd_r() << 1;
+
+ // not data accepted
+ data |= m_bus->ndac_r() << 2;
+
+ // end or identify
+ data |= m_bus->eoi_r() << 3;
+
+ // data valid
+ data |= m_bus->dav_r() << 6;
+
+ // attention
+ data |= !m_bus->atn_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c2031_device::via0_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0 ATNA
+ PB1 NRFD
+ PB2 NDAC
+ PB3 EOI
+ PB4 T/_R
+ PB5 HD SEL
+ PB6 DAV
+ PB7 _ATN
+
+ */
+
+ int atna = BIT(data, 0);
+ int nrfd = BIT(data, 1);
+ int ndac = BIT(data, 2);
+
+ // not ready for data
+ m_nrfd_out = nrfd;
+
+ // not data accepted
+ m_ndac_out = ndac;
+
+ // end or identify
+ m_bus->eoi_w(this, BIT(data, 3));
+
+ // data valid
+ m_bus->dav_w(this, BIT(data, 6));
+
+ // attention acknowledge
+ m_atna = atna;
+
+ if ((!m_bus->atn_r()) ^ atna)
+ {
+ nrfd = ndac = 0;
+ }
+
+ m_bus->nrfd_w(this, nrfd);
+ m_bus->ndac_w(this, ndac);
+
+ m_via0->write_ca2(get_device_number());
+}
+
+
+WRITE_LINE_MEMBER( c2031_device::via1_irq_w )
+{
+ m_via1_irq = state;
+
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+READ8_MEMBER( c2031_device::via1_pb_r )
+{
+ /*
+
+ bit signal description
+
+ PB0
+ PB1
+ PB2
+ PB3
+ PB4 WPS write protect sense
+ PB5
+ PB6
+ PB7 SYNC SYNC detect line
+
+ */
+
+ UINT8 data = 0;
+
+ // write protect sense
+ data |= !m_floppy->wpt_r() << 4;
+
+ // SYNC detect line
+ data |= m_ga->sync_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c2031_device::via1_pb_w )
+{
+ /*
+
+ bit signal description
+
+ PB0 STP0 stepping motor bit 0
+ PB1 STP1 stepping motor bit 1
+ PB2 MTR motor ON/OFF
+ PB3 ACT drive 0 LED
+ PB4
+ PB5 DS0 density select 0
+ PB6 DS1 density select 1
+ PB7 SYNC SYNC detect line
+
+ */
+
+ // spindle motor
+ m_ga->mtr_w(BIT(data, 2));
+
+ // stepper motor
+ m_ga->stp_w(data & 0x03);
+
+ // activity LED
+ output_set_led_value(LED_ACT, BIT(data, 3));
+
+ // density select
+ m_ga->ds_w((data >> 5) & 0x03);
+}
+
+
+//-------------------------------------------------
+// C64H156_INTERFACE( ga_intf )
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( c2031_device::byte_w )
+{
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, state);
+
+ m_via1->write_ca1(state);
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( c2031_floppies )
+//-------------------------------------------------
+
+static SLOT_INTERFACE_START( c2031_floppies )
+ SLOT_INTERFACE( "525ssqd", FLOPPY_525_SSQD )
+SLOT_INTERFACE_END
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( c2031_device::floppy_formats )
+ FLOPPY_D64_FORMAT,
+ FLOPPY_G64_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( c2031 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c2031 )
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c2031_mem)
+ MCFG_QUANTUM_PERFECT_CPU(M6502_TAG)
+
+ MCFG_DEVICE_ADD(M6522_0_TAG, VIA6522, XTAL_16MHz/16)
+ MCFG_VIA6522_READPA_HANDLER(READ8(c2031_device, via0_pa_r))
+ MCFG_VIA6522_READPB_HANDLER(READ8(c2031_device, via0_pb_r))
+ MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(c2031_device, via0_pa_w))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(c2031_device, via0_pb_w))
+ MCFG_VIA6522_IRQ_HANDLER(WRITELINE(c2031_device, via0_irq_w))
+
+ MCFG_DEVICE_ADD(M6522_1_TAG, VIA6522, XTAL_16MHz/16)
+ MCFG_VIA6522_READPA_HANDLER(DEVREAD8(C64H156_TAG, c64h156_device, yb_r))
+ MCFG_VIA6522_READPB_HANDLER(READ8(c2031_device, via1_pb_r))
+ MCFG_VIA6522_WRITEPA_HANDLER(DEVWRITE8(C64H156_TAG, c64h156_device, yb_w))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(c2031_device, via1_pb_w))
+ MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE(C64H156_TAG, c64h156_device, soe_w))
+ MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE(C64H156_TAG, c64h156_device, oe_w))
+ MCFG_VIA6522_IRQ_HANDLER(WRITELINE(c2031_device, via1_irq_w))
+
+ MCFG_DEVICE_ADD(C64H156_TAG, C64H156, XTAL_16MHz)
+ MCFG_64H156_BYTE_CALLBACK(WRITELINE(c2031_device, byte_w))
+ MCFG_FLOPPY_DRIVE_ADD(C64H156_TAG":0", c2031_floppies, "525ssqd", c2031_device::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor c2031_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( c2031 );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( c2031 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( c2031 )
+ PORT_START("ADDRESS")
+ PORT_DIPNAME( 0x03, 0x00, "Device Address" )
+ PORT_DIPSETTING( 0x00, "8" )
+ PORT_DIPSETTING( 0x01, "9" )
+ PORT_DIPSETTING( 0x02, "10" )
+ PORT_DIPSETTING( 0x03, "11" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor c2031_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( c2031 );
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// get_device_number -
+//-------------------------------------------------
+
+inline int c2031_device::get_device_number()
+{
+ int state = 1;
+
+ switch ((m_slot->get_address() - 8) & 0x03)
+ {
+ case 0: state = (m_atna && m_nrfd_out); break;
+ case 1: state = m_nrfd_out; break;
+ case 2: state = m_atna; break;
+ case 3: state = 1; break;
+ }
+
+ return state;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c2031_device - constructor
+//-------------------------------------------------
+
+c2031_device::c2031_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, C2031, "C2031", tag, owner, clock, "c2031", __FILE__),
+ device_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, M6502_TAG),
+ m_via0(*this, M6522_0_TAG),
+ m_via1(*this, M6522_1_TAG),
+ m_ga(*this, C64H156_TAG),
+ m_floppy(*this, C64H156_TAG":0:525ssqd"),
+ m_address(*this, "ADDRESS"),
+ m_nrfd_out(1),
+ m_ndac_out(1),
+ m_atna(1),
+ m_via0_irq(0),
+ m_via1_irq(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void c2031_device::device_start()
+{
+ // install image callbacks
+ m_ga->set_floppy(m_floppy);
+
+ // register for state saving
+ save_item(NAME(m_nrfd_out));
+ save_item(NAME(m_ndac_out));
+ save_item(NAME(m_atna));
+ save_item(NAME(m_via0_irq));
+ save_item(NAME(m_via1_irq));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void c2031_device::device_reset()
+{
+ m_maincpu->reset();
+
+ m_via0->reset();
+ m_via1->reset();
+}
+
+
+//-------------------------------------------------
+// ieee488_atn_w -
+//-------------------------------------------------
+
+void c2031_device::ieee488_atn(int state)
+{
+ int nrfd = m_nrfd_out;
+ int ndac = m_ndac_out;
+
+ m_via0->write_ca1(!state);
+
+ if ((!state) ^ m_atna)
+ {
+ nrfd = ndac = 0;
+ }
+
+ m_bus->nrfd_w(this, nrfd);
+ m_bus->ndac_w(this, ndac);
+}
+
+
+//-------------------------------------------------
+// ieee488_ifc_w -
+//-------------------------------------------------
+
+void c2031_device::ieee488_ifc(int state)
+{
+ if (!m_ifc && state)
+ {
+ device_reset();
+ }
+
+ m_ifc = state;
+}
diff --git a/src/devices/bus/ieee488/c2031.h b/src/devices/bus/ieee488/c2031.h
new file mode 100644
index 00000000000..8423a8c1c95
--- /dev/null
+++ b/src/devices/bus/ieee488/c2031.h
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 2031 Single Disk Drive emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __C2031__
+#define __C2031__
+
+#include "emu.h"
+#include "ieee488.h"
+#include "cpu/m6502/m6502.h"
+#include "machine/64h156.h"
+#include "machine/6522via.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> c2031_device
+
+class c2031_device : public device_t,
+ public device_ieee488_interface
+{
+public:
+ // construction/destruction
+ c2031_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;
+
+ DECLARE_WRITE_LINE_MEMBER( via0_irq_w );
+ DECLARE_READ8_MEMBER( via0_pa_r );
+ DECLARE_WRITE8_MEMBER( via0_pa_w );
+ DECLARE_READ8_MEMBER( via0_pb_r );
+ DECLARE_WRITE8_MEMBER( via0_pb_w );
+ DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
+ DECLARE_READ8_MEMBER( via1_pb_r );
+ DECLARE_WRITE8_MEMBER( via1_pb_w );
+ DECLARE_WRITE_LINE_MEMBER( byte_w );
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_ieee488_interface overrides
+ virtual void ieee488_atn(int state);
+ virtual void ieee488_ifc(int state);
+
+ inline int get_device_number();
+
+ required_device<cpu_device> m_maincpu;
+ required_device<via6522_device> m_via0;
+ required_device<via6522_device> m_via1;
+ required_device<c64h156_device> m_ga;
+ required_device<floppy_image_device> m_floppy;
+ required_ioport m_address;
+
+ // IEEE-488 bus
+ int m_nrfd_out; // not ready for data
+ int m_ndac_out; // not data accepted
+ int m_atna; // attention acknowledge
+ int m_ifc;
+
+ // interrupts
+ int m_via0_irq; // VIA #0 interrupt request
+ int m_via1_irq; // VIA #1 interrupt request
+};
+
+
+// device type definition
+extern const device_type C2031;
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/c2040.c b/src/devices/bus/ieee488/c2040.c
new file mode 100644
index 00000000000..8ce2856e371
--- /dev/null
+++ b/src/devices/bus/ieee488/c2040.c
@@ -0,0 +1,802 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 2040/3040/4040 Disk Drive emulation
+
+**********************************************************************/
+
+/*
+
+ 2040/3040 disk initialization
+ -----------------------------
+ You need to initialize each diskette before trying to access it
+ or you will get a DISK ID MISMATCH error upon disk commands.
+ On the 4040 this is done automatically by the DOS.
+
+ open 15,8,15:print 15,"i":close 15
+
+ List directory
+ --------------
+ directory / diR
+
+ Format disk
+ -----------
+ header "label,id",d0,i01
+
+ Load file
+ ---------
+ dload "name" / dL"name
+
+ Save file
+ ---------
+ dsave "name" / dS"name
+
+*/
+
+/*
+
+ TODO:
+
+ - 2040/3040/4040 have a Shugart SA390 drive (FLOPPY_525_SSSD_35T)
+
+ - 2040 DOS 1 FDC rom (jumps to 104d while getting block header)
+
+ FE70: jsr $104D
+ 104D: m6502_brk#$00
+
+*/
+
+#include "c2040.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define M6502_TAG "un1"
+#define M6532_0_TAG "uc1"
+#define M6532_1_TAG "ue1"
+#define M6504_TAG "uh3"
+#define M6522_TAG "um3"
+#define M6530_TAG "uk3"
+#define FDC_TAG "fdc"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type C2040 = &device_creator<c2040_t>;
+const device_type C3040 = &device_creator<c3040_t>;
+const device_type C4040 = &device_creator<c4040_t>;
+
+
+//-------------------------------------------------
+// ROM( c2040 )
+//-------------------------------------------------
+
+ROM_START( c2040 ) // schematic 320806, DOS 1.0
+ ROM_REGION( 0x3000, M6502_TAG, 0 )
+ ROM_DEFAULT_BIOS("dos12")
+ ROM_LOAD( "901468-xx.ul1", 0x1000, 0x1000, NO_DUMP )
+ ROM_LOAD( "901468-xx.uh1", 0x2000, 0x1000, NO_DUMP )
+
+ ROM_REGION( 0x400, M6504_TAG, 0 )
+ ROM_LOAD( "901466-01.uk3", 0x000, 0x400, CRC(9d1e25ce) SHA1(d539858f839f96393f218307df7394362a84a26a) )
+
+ ROM_REGION( 0x800, "gcr", 0)
+ ROM_LOAD( "901467.uk6", 0x000, 0x800, CRC(a23337eb) SHA1(97df576397608455616331f8e837cb3404363fa2) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c2040_t::device_rom_region() const
+{
+ return ROM_NAME( c2040 );
+}
+
+
+//-------------------------------------------------
+// ROM( c3040 )
+//-------------------------------------------------
+
+ROM_START( c3040 ) // schematic 320806, DOS 1.2
+ ROM_REGION( 0x3000, M6502_TAG, 0 )
+ ROM_LOAD( "901468-06.ul1", 0x1000, 0x1000, CRC(25b5eed5) SHA1(4d9658f2e6ff3276e5c6e224611a66ce44b16fc7) )
+ ROM_LOAD( "901468-07.uh1", 0x2000, 0x1000, CRC(9b09ae83) SHA1(6a51c7954938439ca8342fc295bda050c06e1791) )
+
+ ROM_REGION( 0x400, M6504_TAG, 0 )
+ ROM_LOAD( "901466-02.uk3", 0x000, 0x400, CRC(9d1e25ce) SHA1(d539858f839f96393f218307df7394362a84a26a) )
+
+ ROM_REGION( 0x800, "gcr", 0)
+ ROM_LOAD( "901467.uk6", 0x000, 0x800, CRC(a23337eb) SHA1(97df576397608455616331f8e837cb3404363fa2) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c3040_t::device_rom_region() const
+{
+ return ROM_NAME( c3040 );
+}
+
+
+//-------------------------------------------------
+// ROM( c4040 )
+//-------------------------------------------------
+
+ROM_START( c4040 ) // schematic ?
+ ROM_REGION( 0x3000, M6502_TAG, 0 )
+ ROM_DEFAULT_BIOS("dos20r2")
+ ROM_SYSTEM_BIOS( 0, "dos20r1", "DOS 2.0 Revision 1" )
+ ROMX_LOAD( "901468-11.uj1", 0x0000, 0x1000, CRC(b7157458) SHA1(8415f3159dea73161e0cef7960afa6c76953b6f8), ROM_BIOS(1) )
+ ROMX_LOAD( "901468-12.ul1", 0x1000, 0x1000, CRC(02c44ff9) SHA1(e8a94f239082d45f64f01b2d8e488d18fe659cbb), ROM_BIOS(1) )
+ ROMX_LOAD( "901468-13.uh1", 0x2000, 0x1000, CRC(cbd785b3) SHA1(6ada7904ac9d13c3f1c0a8715f9c4be1aa6eb0bb), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "dos20r2", "DOS 2.0 Revision 2" )
+ ROMX_LOAD( "901468-14.uj1", 0x0000, 0x1000, CRC(bc4d4872) SHA1(ffb992b82ec913ddff7be964d7527aca3e21580c), ROM_BIOS(2) )
+ ROMX_LOAD( "901468-15.ul1", 0x1000, 0x1000, CRC(b6970533) SHA1(f702d6917fe8a798740ba4d467b500944ae7b70a), ROM_BIOS(2) )
+ ROMX_LOAD( "901468-16.uh1", 0x2000, 0x1000, CRC(1f5eefb7) SHA1(04b918cf4adeee8015b43383d3cea7288a7d0aa8), ROM_BIOS(2) )
+
+ ROM_REGION( 0x400, M6504_TAG, 0 )
+ // RIOT DOS 2
+ ROM_LOAD( "901466-04.uk3", 0x000, 0x400, CRC(0ab338dc) SHA1(6645fa40b81be1ff7d1384e9b52df06a26ab0bfb) )
+
+ ROM_REGION( 0x800, "gcr", 0)
+ ROM_LOAD( "901467.uk6", 0x000, 0x800, CRC(a23337eb) SHA1(97df576397608455616331f8e837cb3404363fa2) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c4040_t::device_rom_region() const
+{
+ return ROM_NAME( c4040 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c2040_main_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c2040_main_mem, AS_PROGRAM, 8, c2040_t )
+ ADDRESS_MAP_GLOBAL_MASK(0x7fff)
+ AM_RANGE(0x0000, 0x007f) AM_MIRROR(0x0100) AM_DEVICE(M6532_0_TAG, mos6532_t, ram_map)
+ AM_RANGE(0x0080, 0x00ff) AM_MIRROR(0x0100) AM_DEVICE(M6532_1_TAG, mos6532_t, ram_map)
+ AM_RANGE(0x0200, 0x021f) AM_MIRROR(0x0d60) AM_DEVICE(M6532_0_TAG, mos6532_t, io_map)
+ AM_RANGE(0x0280, 0x029f) AM_MIRROR(0x0d60) AM_DEVICE(M6532_1_TAG, mos6532_t, io_map)
+ AM_RANGE(0x1000, 0x13ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x2000, 0x23ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x3000, 0x33ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x4000, 0x43ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0x5000, 0x7fff) AM_ROM AM_REGION(M6502_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c2040_fdc_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c2040_fdc_mem, AS_PROGRAM, 8, c2040_t )
+ ADDRESS_MAP_GLOBAL_MASK(0x1fff)
+ AM_RANGE(0x0000, 0x003f) AM_MIRROR(0x0300) AM_DEVICE(M6530_TAG, mos6530_t, ram_map)
+ AM_RANGE(0x0040, 0x004f) AM_MIRROR(0x0330) AM_DEVICE(M6522_TAG, via6522_device, map)
+ AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVICE(M6530_TAG, mos6530_t, io_map)
+ AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x1000, 0x13ff) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0x1c00, 0x1fff) AM_ROM AM_REGION(M6504_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// riot6532 uc1
+//-------------------------------------------------
+
+READ8_MEMBER( c2040_t::dio_r )
+{
+ /*
+
+ bit description
+
+ PA0 DI0
+ PA1 DI1
+ PA2 DI2
+ PA3 DI3
+ PA4 DI4
+ PA5 DI5
+ PA6 DI6
+ PA7 DI7
+
+ */
+
+ return m_bus->dio_r();
+}
+
+WRITE8_MEMBER( c2040_t::dio_w )
+{
+ /*
+
+ bit description
+
+ PB0 DO0
+ PB1 DO1
+ PB2 DO2
+ PB3 DO3
+ PB4 DO4
+ PB5 DO5
+ PB6 DO6
+ PB7 DO7
+
+ */
+
+ m_bus->dio_w(this, data);
+}
+
+
+//-------------------------------------------------
+// riot6532 ue1
+//-------------------------------------------------
+
+READ8_MEMBER( c2040_t::riot1_pa_r )
+{
+ /*
+
+ bit description
+
+ PA0 ATNA
+ PA1 DACO
+ PA2 RFDO
+ PA3 EOIO
+ PA4 DAVO
+ PA5 EOII
+ PA6 DAVI
+ PA7 _ATN
+
+ */
+
+ UINT8 data = 0;
+
+ // end or identify in
+ data |= m_bus->eoi_r() << 5;
+
+ // data valid in
+ data |= m_bus->dav_r() << 6;
+
+ // attention
+ data |= !m_bus->atn_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c2040_t::riot1_pa_w )
+{
+ /*
+
+ bit description
+
+ PA0 ATNA
+ PA1 DACO
+ PA2 RFDO
+ PA3 EOIO
+ PA4 DAVO
+ PA5 EOII
+ PA6 DAVI
+ PA7 _ATN
+
+ */
+
+ // attention acknowledge
+ m_atna = BIT(data, 0);
+
+ // data accepted out
+ m_daco = BIT(data, 1);
+
+ // not ready for data out
+ m_rfdo = BIT(data, 2);
+
+ // end or identify out
+ m_bus->eoi_w(this, BIT(data, 3));
+
+ // data valid out
+ m_bus->dav_w(this, BIT(data, 4));
+
+ update_ieee_signals();
+}
+
+READ8_MEMBER( c2040_t::riot1_pb_r )
+{
+ /*
+
+ bit description
+
+ PB0 DEVICE NUMBER SELECTION
+ PB1 DEVICE NUMBER SELECTION
+ PB2 DEVICE NUMBER SELECTION
+ PB3
+ PB4
+ PB5
+ PB6 DACI
+ PB7 RFDI
+
+ */
+
+ UINT8 data = 0;
+
+ // device number selection
+ data |= m_slot->get_address() - 8;
+
+ // data accepted in
+ data |= m_bus->ndac_r() << 6;
+
+ // ready for data in
+ data |= m_bus->nrfd_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c2040_t::riot1_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0
+ PB1
+ PB2
+ PB3 ACT LED 1
+ PB4 ACT LED 0
+ PB5 ERR LED
+ PB6
+ PB7
+
+ */
+
+ // activity led 1
+ output_set_led_value(LED_ACT1, BIT(data, 3));
+
+ // activity led 0
+ output_set_led_value(LED_ACT0, BIT(data, 4));
+
+ // error led
+ output_set_led_value(LED_ERR, BIT(data, 5));
+}
+
+
+WRITE8_MEMBER( c2040_t::via_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0 S1A
+ PB1 S1B
+ PB2 S0A
+ PB3 S0B
+ PB4 MTR1
+ PB5 MTR0
+ PB6
+ PB7
+
+ */
+
+ // spindle motor 1
+ m_fdc->mtr1_w(BIT(data, 4));
+
+ // spindle motor 0
+ m_fdc->mtr0_w(BIT(data, 5));
+
+ // stepper motor 1
+ m_fdc->stp1_w(data & 0x03);
+
+ // stepper motor 0
+ m_fdc->stp0_w((data >> 2) & 0x03);
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( c2040_floppies )
+//-------------------------------------------------
+
+static SLOT_INTERFACE_START( c2040_floppies )
+ SLOT_INTERFACE( "525ssqd", FLOPPY_525_SSQD )
+SLOT_INTERFACE_END
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( c2040_t::floppy_formats )
+ FLOPPY_C3040_FORMAT,
+ FLOPPY_G64_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( c3040_t::floppy_formats )
+ FLOPPY_C3040_FORMAT,
+ FLOPPY_G64_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( c4040_t::floppy_formats )
+ FLOPPY_C4040_FORMAT,
+ FLOPPY_G64_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( c2040 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c2040 )
+ // DOS
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c2040_main_mem)
+
+ MCFG_DEVICE_ADD(M6532_0_TAG, MOS6532n, XTAL_16MHz/16)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c2040_t, dio_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c2040_t, dio_w))
+
+ MCFG_DEVICE_ADD(M6532_1_TAG, MOS6532n, XTAL_16MHz/16)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c2040_t, riot1_pa_r))
+ MCFG_MOS6530n_OUT_PA_CB(WRITE8(c2040_t, riot1_pa_w))
+ MCFG_MOS6530n_IN_PB_CB(READ8(c2040_t, riot1_pb_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c2040_t, riot1_pb_w))
+ MCFG_MOS6530n_IRQ_CB(INPUTLINE(M6502_TAG, INPUT_LINE_IRQ0))
+
+ // controller
+ MCFG_CPU_ADD(M6504_TAG, M6504, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c2040_fdc_mem)
+
+ MCFG_DEVICE_ADD(M6522_TAG, VIA6522, XTAL_16MHz/16)
+ MCFG_VIA6522_READPA_HANDLER(DEVREAD8(FDC_TAG, c2040_fdc_t, read))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(c2040_t, via_pb_w))
+ MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE(FDC_TAG, c2040_fdc_t, mode_sel_w))
+ MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE(FDC_TAG, c2040_fdc_t, rw_sel_w))
+
+ MCFG_DEVICE_ADD(M6530_TAG, MOS6530n, XTAL_16MHz/16)
+ MCFG_MOS6530n_OUT_PA_CB(DEVWRITE8(FDC_TAG, c2040_fdc_t, write))
+ MCFG_MOS6530n_OUT_PB0_CB(DEVWRITELINE(FDC_TAG, c2040_fdc_t, drv_sel_w))
+ MCFG_MOS6530n_OUT_PB1_CB(DEVWRITELINE(FDC_TAG, c2040_fdc_t, ds0_w))
+ MCFG_MOS6530n_OUT_PB2_CB(DEVWRITELINE(FDC_TAG, c2040_fdc_t, ds1_w))
+ MCFG_MOS6530n_OUT_PB7_CB(INPUTLINE(M6504_TAG, M6502_IRQ_LINE))
+ MCFG_MOS6530n_IN_PB3_CB(DEVREADLINE(FDC_TAG, c2040_fdc_t, wps_r))
+
+ MCFG_DEVICE_ADD(FDC_TAG, C2040_FDC, XTAL_16MHz)
+ MCFG_C2040_SYNC_CALLBACK(DEVWRITELINE(M6530_TAG, mos6530_t, pb6_w))
+ MCFG_C2040_READY_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_ca1))
+ MCFG_C2040_ERROR_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_cb1))
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG":0", c2040_floppies, "525ssqd", c2040_t::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG":1", c2040_floppies, "525ssqd", c2040_t::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor c2040_t::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( c2040 );
+}
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( c3040 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c3040 )
+ // DOS
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c2040_main_mem)
+
+ MCFG_DEVICE_ADD(M6532_0_TAG, MOS6532n, XTAL_16MHz/16)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c2040_t, dio_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c2040_t, dio_w))
+
+ MCFG_DEVICE_ADD(M6532_1_TAG, MOS6532n, XTAL_16MHz/16)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c2040_t, riot1_pa_r))
+ MCFG_MOS6530n_OUT_PA_CB(WRITE8(c2040_t, riot1_pa_w))
+ MCFG_MOS6530n_IN_PB_CB(READ8(c2040_t, riot1_pb_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c2040_t, riot1_pb_w))
+ MCFG_MOS6530n_IRQ_CB(INPUTLINE(M6502_TAG, INPUT_LINE_IRQ0))
+
+ // controller
+ MCFG_CPU_ADD(M6504_TAG, M6504, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c2040_fdc_mem)
+
+ MCFG_DEVICE_ADD(M6522_TAG, VIA6522, XTAL_16MHz/16)
+ MCFG_VIA6522_READPA_HANDLER(DEVREAD8(FDC_TAG, c2040_fdc_t, read))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(c2040_t, via_pb_w))
+ MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE(FDC_TAG, c2040_fdc_t, mode_sel_w))
+ MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE(FDC_TAG, c2040_fdc_t, rw_sel_w))
+
+ MCFG_DEVICE_ADD(M6530_TAG, MOS6530n, XTAL_16MHz/16)
+ MCFG_MOS6530n_OUT_PA_CB(DEVWRITE8(FDC_TAG, c2040_fdc_t, write))
+ MCFG_MOS6530n_OUT_PB0_CB(DEVWRITELINE(FDC_TAG, c2040_fdc_t, drv_sel_w))
+ MCFG_MOS6530n_OUT_PB1_CB(DEVWRITELINE(FDC_TAG, c2040_fdc_t, ds0_w))
+ MCFG_MOS6530n_OUT_PB2_CB(DEVWRITELINE(FDC_TAG, c2040_fdc_t, ds1_w))
+ MCFG_MOS6530n_IN_PB3_CB(DEVREADLINE(FDC_TAG, c2040_fdc_t, wps_r))
+ MCFG_MOS6530n_OUT_PB7_CB(INPUTLINE(M6504_TAG, M6502_IRQ_LINE))
+
+ MCFG_DEVICE_ADD(FDC_TAG, C2040_FDC, XTAL_16MHz)
+ MCFG_C2040_SYNC_CALLBACK(DEVWRITELINE(M6530_TAG, mos6530_t, pb6_w))
+ MCFG_C2040_READY_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_ca1))
+ MCFG_C2040_ERROR_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_cb1))
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG":0", c2040_floppies, "525ssqd", c3040_t::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG":1", c2040_floppies, "525ssqd", c3040_t::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor c3040_t::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( c3040 );
+}
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( c4040 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c4040 )
+ // DOS
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c2040_main_mem)
+
+ MCFG_DEVICE_ADD(M6532_0_TAG, MOS6532n, XTAL_16MHz/16)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c2040_t, dio_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c2040_t, dio_w))
+
+ MCFG_DEVICE_ADD(M6532_1_TAG, MOS6532n, XTAL_16MHz/16)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c2040_t, riot1_pa_r))
+ MCFG_MOS6530n_OUT_PA_CB(WRITE8(c2040_t, riot1_pa_w))
+ MCFG_MOS6530n_IN_PB_CB(READ8(c2040_t, riot1_pb_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c2040_t, riot1_pb_w))
+ MCFG_MOS6530n_IRQ_CB(INPUTLINE(M6502_TAG, INPUT_LINE_IRQ0))
+
+ // controller
+ MCFG_CPU_ADD(M6504_TAG, M6504, XTAL_16MHz/16)
+ MCFG_CPU_PROGRAM_MAP(c2040_fdc_mem)
+
+ MCFG_DEVICE_ADD(M6522_TAG, VIA6522, XTAL_16MHz/16)
+ MCFG_VIA6522_READPA_HANDLER(DEVREAD8(FDC_TAG, c2040_fdc_t, read))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(c2040_t, via_pb_w))
+ MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE(FDC_TAG, c2040_fdc_t, mode_sel_w))
+ MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE(FDC_TAG, c2040_fdc_t, rw_sel_w))
+
+ MCFG_DEVICE_ADD(M6530_TAG, MOS6530n, XTAL_16MHz/16)
+ MCFG_MOS6530n_OUT_PA_CB(DEVWRITE8(FDC_TAG, c2040_fdc_t, write))
+ MCFG_MOS6530n_OUT_PB0_CB(DEVWRITELINE(FDC_TAG, c2040_fdc_t, drv_sel_w))
+ MCFG_MOS6530n_OUT_PB1_CB(DEVWRITELINE(FDC_TAG, c2040_fdc_t, ds0_w))
+ MCFG_MOS6530n_OUT_PB2_CB(DEVWRITELINE(FDC_TAG, c2040_fdc_t, ds1_w))
+ MCFG_MOS6530n_IN_PB3_CB(DEVREADLINE(FDC_TAG, c2040_fdc_t, wps_r))
+ MCFG_MOS6530n_OUT_PB7_CB(INPUTLINE(M6504_TAG, M6502_IRQ_LINE))
+
+ MCFG_DEVICE_ADD(FDC_TAG, C2040_FDC, XTAL_16MHz)
+ MCFG_C2040_SYNC_CALLBACK(DEVWRITELINE(M6530_TAG, mos6530_t, pb6_w))
+ MCFG_C2040_READY_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_ca1))
+ MCFG_C2040_ERROR_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_cb1))
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG":0", c2040_floppies, "525ssqd", c4040_t::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG":1", c2040_floppies, "525ssqd", c4040_t::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor c4040_t::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( c4040 );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( c2040 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( c2040 )
+ PORT_START("ADDRESS")
+ PORT_DIPNAME( 0x07, 0x00, "Device Address" )
+ PORT_DIPSETTING( 0x00, "8" )
+ PORT_DIPSETTING( 0x01, "9" )
+ PORT_DIPSETTING( 0x02, "10" )
+ PORT_DIPSETTING( 0x03, "11" )
+ PORT_DIPSETTING( 0x04, "12" )
+ PORT_DIPSETTING( 0x05, "13" )
+ PORT_DIPSETTING( 0x06, "14" )
+ PORT_DIPSETTING( 0x07, "15" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor c2040_t::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( c2040 );
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// update_ieee_signals -
+//-------------------------------------------------
+
+inline void c2040_t::update_ieee_signals()
+{
+ int atn = m_bus->atn_r();
+ int nrfd = !(!(!(atn && m_atna) && m_rfdo) || !(atn || m_atna));
+ int ndac = !(m_daco || !(atn || m_atna));
+
+ m_bus->nrfd_w(this, nrfd);
+ m_bus->ndac_w(this, ndac);
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c2040_t - constructor
+//-------------------------------------------------
+
+c2040_t::c2040_t(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_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, M6502_TAG),
+ m_fdccpu(*this, M6504_TAG),
+ m_riot0(*this, M6532_0_TAG),
+ m_riot1(*this, M6532_1_TAG),
+ m_miot(*this, M6530_TAG),
+ m_via(*this, M6522_TAG),
+ m_floppy0(*this, FDC_TAG":0:525ssqd"),
+ m_floppy1(*this, FDC_TAG":1:525ssqd"),
+ m_fdc(*this, FDC_TAG),
+ m_gcr(*this, "gcr"),
+ m_address(*this, "ADDRESS"),
+ m_rfdo(1),
+ m_daco(1),
+ m_atna(1)
+{
+}
+
+c2040_t::c2040_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, C2040, "C2040", tag, owner, clock, "c2040", __FILE__),
+ device_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, M6502_TAG),
+ m_fdccpu(*this, M6504_TAG),
+ m_riot0(*this, M6532_0_TAG),
+ m_riot1(*this, M6532_1_TAG),
+ m_miot(*this, M6530_TAG),
+ m_via(*this, M6522_TAG),
+ m_floppy0(*this, FDC_TAG":0:525ssqd"),
+ m_floppy1(*this, FDC_TAG":1:525ssqd"),
+ m_fdc(*this, FDC_TAG),
+ m_gcr(*this, "gcr"),
+ m_address(*this, "ADDRESS"),
+ m_rfdo(1),
+ m_daco(1),
+ m_atna(1)
+{
+}
+
+
+//-------------------------------------------------
+// c3040_t - constructor
+//-------------------------------------------------
+
+c3040_t::c3040_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ c2040_t(mconfig, C3040, "C3040", tag, owner, clock, "c3040", __FILE__) { }
+
+
+//-------------------------------------------------
+// c4040_t - constructor
+//-------------------------------------------------
+
+c4040_t::c4040_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ c2040_t(mconfig, C4040, "C4040", tag, owner, clock, "c4040", __FILE__) { }
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void c2040_t::device_start()
+{
+ // install image callbacks
+ m_fdc->set_floppy(m_floppy0, m_floppy1);
+
+ // register for state saving
+ save_item(NAME(m_rfdo));
+ save_item(NAME(m_daco));
+ save_item(NAME(m_atna));
+ save_item(NAME(m_ifc));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void c2040_t::device_reset()
+{
+ m_maincpu->reset();
+
+ // toggle M6502 SO
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, ASSERT_LINE);
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, CLEAR_LINE);
+
+ m_fdccpu->reset();
+
+ m_riot0->reset();
+ m_riot1->reset();
+ m_miot->reset();
+ m_via->reset();
+
+ m_riot1->pa7_w(0);
+
+ // turn off spindle motors
+ m_fdc->mtr0_w(1);
+ m_fdc->mtr1_w(1);
+}
+
+
+//-------------------------------------------------
+// ieee488_atn -
+//-------------------------------------------------
+
+void c2040_t::ieee488_atn(int state)
+{
+ update_ieee_signals();
+
+ m_riot1->pa7_w(!state);
+}
+
+
+//-------------------------------------------------
+// ieee488_ifc -
+//-------------------------------------------------
+
+void c2040_t::ieee488_ifc(int state)
+{
+ if (!m_ifc && state)
+ {
+ device_reset();
+ }
+
+ m_ifc = state;
+}
diff --git a/src/devices/bus/ieee488/c2040.h b/src/devices/bus/ieee488/c2040.h
new file mode 100644
index 00000000000..1618a46599f
--- /dev/null
+++ b/src/devices/bus/ieee488/c2040.h
@@ -0,0 +1,133 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 2040/3040/4040 Disk Drive emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __C2040__
+#define __C2040__
+
+#include "emu.h"
+#include "ieee488.h"
+#include "c2040fdc.h"
+#include "cpu/m6502/m6502.h"
+#include "cpu/m6502/m6504.h"
+#include "machine/6522via.h"
+#include "machine/mos6530n.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> c2040_t
+
+class c2040_t : public device_t,
+ public device_ieee488_interface
+{
+public:
+ // construction/destruction
+ c2040_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ c2040_t(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;
+
+ DECLARE_READ8_MEMBER( dio_r );
+ DECLARE_WRITE8_MEMBER( dio_w );
+ DECLARE_READ8_MEMBER( riot1_pa_r );
+ DECLARE_WRITE8_MEMBER( riot1_pa_w );
+ DECLARE_READ8_MEMBER( riot1_pb_r );
+ DECLARE_WRITE8_MEMBER( riot1_pb_w );
+ DECLARE_WRITE8_MEMBER( via_pb_w );
+ DECLARE_WRITE_LINE_MEMBER( mode_sel_w );
+ DECLARE_WRITE_LINE_MEMBER( rw_sel_w );
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_ieee488_interface overrides
+ virtual void ieee488_atn(int state);
+ virtual void ieee488_ifc(int state);
+
+ enum
+ {
+ LED_POWER = 0,
+ LED_ACT0,
+ LED_ACT1,
+ LED_ERR
+ };
+
+ inline void update_ieee_signals();
+
+ required_device<m6502_device> m_maincpu;
+ required_device<m6504_device> m_fdccpu;
+ required_device<mos6532_t> m_riot0;
+ required_device<mos6532_t> m_riot1;
+ required_device<mos6530_t> m_miot;
+ required_device<via6522_device> m_via;
+ required_device<floppy_image_device> m_floppy0;
+ optional_device<floppy_image_device> m_floppy1;
+ required_device<c2040_fdc_t> m_fdc;
+ required_memory_region m_gcr;
+ required_ioport m_address;
+
+ // IEEE-488 bus
+ int m_rfdo; // not ready for data output
+ int m_daco; // not data accepted output
+ int m_atna; // attention acknowledge
+ int m_ifc;
+};
+
+
+// ======================> c3040_t
+
+class c3040_t : public c2040_t
+{
+public:
+ // construction/destruction
+ c3040_t(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;
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+};
+
+
+// ======================> c4040_t
+
+class c4040_t : public c2040_t
+{
+public:
+ // construction/destruction
+ c4040_t(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;
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+};
+
+
+// device type definition
+extern const device_type C2040;
+extern const device_type C3040;
+extern const device_type C4040;
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/c2040fdc.c b/src/devices/bus/ieee488/c2040fdc.c
new file mode 100644
index 00000000000..4dfccbde366
--- /dev/null
+++ b/src/devices/bus/ieee488/c2040fdc.c
@@ -0,0 +1,623 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 2040 floppy disk controller emulation
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - write protect
+ - separate read/write methods
+
+*/
+
+#include "c2040fdc.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+#define GCR_DECODE(_e, _i) \
+ ((BIT(_e, 6) << 7) | (BIT(_i, 7) << 6) | (_e & 0x33) | (BIT(_e, 2) << 3) | (_i & 0x04))
+
+#define GCR_ENCODE(_e, _i) \
+ ((_e & 0xc0) << 2 | (_i & 0x80) | (_e & 0x3c) << 1 | (_i & 0x04) | (_e & 0x03))
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type C2040_FDC = &device_creator<c2040_fdc_t>;
+
+
+//-------------------------------------------------
+// ROM( c2040_fdc )
+//-------------------------------------------------
+
+ROM_START( c2040_fdc )
+ ROM_REGION( 0x800, "gcr", 0)
+ ROM_LOAD( "901467.uk6", 0x000, 0x800, CRC(a23337eb) SHA1(97df576397608455616331f8e837cb3404363fa2) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c2040_fdc_t::device_rom_region() const
+{
+ return ROM_NAME( c2040_fdc );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c2040_fdc_t - constructor
+//-------------------------------------------------
+
+c2040_fdc_t::c2040_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, C2040_FDC, "C2040 FDC", tag, owner, clock, "c2040fdc", __FILE__),
+ m_write_sync(*this),
+ m_write_ready(*this),
+ m_write_error(*this),
+ m_gcr_rom(*this, "gcr"),
+ m_floppy0(NULL),
+ m_floppy1(NULL),
+ m_mtr0(1),
+ m_mtr1(1),
+ m_stp0(0),
+ m_stp1(0),
+ m_ds(0),
+ m_ds0(0),
+ m_ds1(0),
+ m_drv_sel(0),
+ m_mode_sel(0),
+ m_rw_sel(0),
+ m_period(attotime::from_hz(clock))
+{
+ cur_live.tm = attotime::never;
+ cur_live.state = IDLE;
+ cur_live.next_state = -1;
+ cur_live.write_position = 0;
+ cur_live.write_start_time = attotime::never;
+ cur_live.drv_sel = m_drv_sel;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void c2040_fdc_t::device_start()
+{
+ // resolve callbacks
+ m_write_sync.resolve_safe();
+ m_write_ready.resolve_safe();
+ m_write_error.resolve_safe();
+
+ // allocate timer
+ t_gen = timer_alloc(0);
+
+ // register for state saving
+ save_item(NAME(m_mtr0));
+ save_item(NAME(m_mtr1));
+ save_item(NAME(m_stp0));
+ save_item(NAME(m_stp1));
+ save_item(NAME(m_ds));
+ save_item(NAME(m_ds0));
+ save_item(NAME(m_ds1));
+ save_item(NAME(m_drv_sel));
+ save_item(NAME(m_mode_sel));
+ save_item(NAME(m_rw_sel));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void c2040_fdc_t::device_reset()
+{
+ live_abort();
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void c2040_fdc_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ live_sync();
+ live_run();
+}
+
+floppy_image_device* c2040_fdc_t::get_floppy()
+{
+ return cur_live.drv_sel ? m_floppy1 : m_floppy0;
+}
+
+void c2040_fdc_t::live_start()
+{
+ cur_live.tm = machine().time();
+ cur_live.state = RUNNING;
+ cur_live.next_state = -1;
+
+ cur_live.shift_reg = 0;
+ cur_live.shift_reg_write = 0;
+ cur_live.cycle_counter = 0;
+ cur_live.cell_counter = 0;
+ cur_live.bit_counter = 0;
+ cur_live.ds = m_ds;
+ cur_live.drv_sel = m_drv_sel;
+ cur_live.mode_sel = m_mode_sel;
+ cur_live.rw_sel = m_rw_sel;
+ cur_live.pi = m_pi;
+
+ checkpoint_live = cur_live;
+
+ live_run();
+}
+
+void c2040_fdc_t::checkpoint()
+{
+ get_next_edge(machine().time());
+ checkpoint_live = cur_live;
+}
+
+void c2040_fdc_t::rollback()
+{
+ cur_live = checkpoint_live;
+ get_next_edge(cur_live.tm);
+}
+
+void c2040_fdc_t::start_writing(const attotime &tm)
+{
+ cur_live.write_start_time = tm;
+ cur_live.write_position = 0;
+}
+
+void c2040_fdc_t::stop_writing(const attotime &tm)
+{
+ commit(tm);
+ cur_live.write_start_time = attotime::never;
+}
+
+bool c2040_fdc_t::write_next_bit(bool bit, const attotime &limit)
+{
+ if(cur_live.write_start_time.is_never()) {
+ cur_live.write_start_time = cur_live.tm;
+ cur_live.write_position = 0;
+ }
+
+ attotime etime = cur_live.tm + m_period;
+ if(etime > limit)
+ return true;
+
+ if(bit && cur_live.write_position < ARRAY_LENGTH(cur_live.write_buffer))
+ cur_live.write_buffer[cur_live.write_position++] = cur_live.tm - m_period;
+
+ if (LOG) logerror("%s write bit %u (%u)\n", cur_live.tm.as_string(), cur_live.bit_counter, bit);
+
+ return false;
+}
+
+void c2040_fdc_t::commit(const attotime &tm)
+{
+ if(cur_live.write_start_time.is_never() || tm == cur_live.write_start_time || !cur_live.write_position)
+ return;
+
+ if (LOG) logerror("%s committing %u transitions since %s\n", tm.as_string(), cur_live.write_position, cur_live.write_start_time.as_string());
+
+ if(get_floppy())
+ get_floppy()->write_flux(cur_live.write_start_time, tm, cur_live.write_position, cur_live.write_buffer);
+
+ cur_live.write_start_time = tm;
+ cur_live.write_position = 0;
+}
+
+void c2040_fdc_t::live_delay(int state)
+{
+ cur_live.next_state = state;
+ if(cur_live.tm != machine().time())
+ t_gen->adjust(cur_live.tm - machine().time());
+ else
+ live_sync();
+}
+
+void c2040_fdc_t::live_sync()
+{
+ if(!cur_live.tm.is_never()) {
+ if(cur_live.tm > machine().time()) {
+ rollback();
+ live_run(machine().time());
+ commit(cur_live.tm);
+ } else {
+ commit(cur_live.tm);
+ if(cur_live.next_state != -1) {
+ cur_live.state = cur_live.next_state;
+ cur_live.next_state = -1;
+ }
+ if(cur_live.state == IDLE) {
+ stop_writing(cur_live.tm);
+ cur_live.tm = attotime::never;
+ }
+ }
+ cur_live.next_state = -1;
+ checkpoint();
+ }
+}
+
+void c2040_fdc_t::live_abort()
+{
+ if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) {
+ rollback();
+ live_run(machine().time());
+ }
+
+ stop_writing(cur_live.tm);
+
+ cur_live.tm = attotime::never;
+ cur_live.state = IDLE;
+ cur_live.next_state = -1;
+ cur_live.write_position = 0;
+ cur_live.write_start_time = attotime::never;
+
+ cur_live.ready = 1;
+ cur_live.sync = 1;
+ cur_live.error = 1;
+}
+
+void c2040_fdc_t::live_run(const attotime &limit)
+{
+ if(cur_live.state == IDLE || cur_live.next_state != -1)
+ return;
+
+ for(;;) {
+ switch(cur_live.state) {
+ case RUNNING: {
+ bool syncpoint = false;
+
+ if (cur_live.tm > limit)
+ return;
+
+ int bit = get_next_bit(cur_live.tm, limit);
+ if(bit < 0)
+ return;
+
+ int cell_counter = cur_live.cell_counter;
+
+ if (bit) {
+ cur_live.cycle_counter = cur_live.ds;
+ cur_live.cell_counter = 0;
+ } else {
+ cur_live.cycle_counter++;
+ }
+
+ if (cur_live.cycle_counter == 16) {
+ cur_live.cycle_counter = cur_live.ds;
+
+ cur_live.cell_counter++;
+ cur_live.cell_counter &= 0xf;
+ }
+
+ if (!BIT(cell_counter, 1) && BIT(cur_live.cell_counter, 1)) {
+ // read bit
+ cur_live.shift_reg <<= 1;
+ cur_live.shift_reg |= !(BIT(cur_live.cell_counter, 3) || BIT(cur_live.cell_counter, 2));
+ cur_live.shift_reg &= 0x3ff;
+
+ if (LOG) logerror("%s read bit %u (%u) >> %03x, rw=%u mode=%u\n", cur_live.tm.as_string(), cur_live.bit_counter,
+ !(BIT(cur_live.cell_counter, 3) || BIT(cur_live.cell_counter, 2)), cur_live.shift_reg, cur_live.rw_sel, cur_live.mode_sel);
+
+ // write bit
+ if (!cur_live.rw_sel) { // TODO WPS
+ write_next_bit(BIT(cur_live.shift_reg_write, 9), limit);
+ }
+
+ syncpoint = true;
+ }
+
+ int sync = !((cur_live.shift_reg == 0x3ff) && cur_live.rw_sel);
+
+ if (!sync) {
+ cur_live.bit_counter = 0;
+ } else if (!BIT(cell_counter, 1) && BIT(cur_live.cell_counter, 1) && cur_live.sync) {
+ cur_live.bit_counter++;
+ if (cur_live.bit_counter == 10) {
+ cur_live.bit_counter = 0;
+ }
+ }
+
+ // update GCR
+ if (cur_live.rw_sel) {
+ cur_live.i = (cur_live.rw_sel << 10) | cur_live.shift_reg;
+ } else {
+ cur_live.i = (cur_live.rw_sel << 10) | ((cur_live.pi & 0xf0) << 1) | (cur_live.mode_sel << 4) | (cur_live.pi & 0x0f);
+ }
+
+ cur_live.e = m_gcr_rom->base()[cur_live.i];
+
+ int ready = !(BIT(cell_counter, 1) && !BIT(cur_live.cell_counter, 1) && (cur_live.bit_counter == 9));
+
+ if (!ready) {
+ // load write shift register
+ cur_live.shift_reg_write = GCR_ENCODE(cur_live.e, cur_live.i);
+
+ if (LOG) logerror("%s load write shift register %03x\n",cur_live.tm.as_string(),cur_live.shift_reg_write);
+ } else if (BIT(cell_counter, 1) && !BIT(cur_live.cell_counter, 1)) {
+ // clock write shift register
+ cur_live.shift_reg_write <<= 1;
+ cur_live.shift_reg_write &= 0x3ff;
+
+ if (LOG) logerror("%s write shift << %03x\n",cur_live.tm.as_string(),cur_live.shift_reg_write);
+ }
+
+ int error = !(BIT(cur_live.e, 3) || ready);
+
+ if (ready != cur_live.ready) {
+ if (LOG) logerror("%s READY %u\n", cur_live.tm.as_string(),ready);
+ cur_live.ready = ready;
+ syncpoint = true;
+ }
+
+ if (sync != cur_live.sync) {
+ if (LOG) logerror("%s SYNC %u\n", cur_live.tm.as_string(),sync);
+ cur_live.sync = sync;
+ syncpoint = true;
+ }
+
+ if (error != cur_live.error) {
+ cur_live.error = error;
+ syncpoint = true;
+ }
+
+ if (syncpoint) {
+ commit(cur_live.tm);
+
+ cur_live.tm += m_period;
+ live_delay(RUNNING_SYNCPOINT);
+ return;
+ }
+
+ cur_live.tm += m_period;
+ break;
+ }
+
+ case RUNNING_SYNCPOINT: {
+ m_write_ready(cur_live.ready);
+ m_write_sync(cur_live.sync);
+ m_write_error(cur_live.error);
+
+ cur_live.state = RUNNING;
+ checkpoint();
+ break;
+ }
+ }
+ }
+}
+
+void c2040_fdc_t::get_next_edge(const attotime &when)
+{
+ floppy_image_device *floppy = get_floppy();
+
+ cur_live.edge = floppy ? floppy->get_next_transition(when) : attotime::never;
+}
+
+int c2040_fdc_t::get_next_bit(attotime &tm, const attotime &limit)
+{
+ attotime next = tm + m_period;
+
+ int bit = (cur_live.edge.is_never() || cur_live.edge >= next) ? 0 : 1;
+
+ if (bit) {
+ get_next_edge(next);
+ }
+
+ return bit && cur_live.rw_sel;
+}
+
+READ8_MEMBER( c2040_fdc_t::read )
+{
+ UINT8 e = checkpoint_live.e;
+ offs_t i = checkpoint_live.i;
+
+ UINT8 data = GCR_DECODE(e, i);
+
+ if (LOG) logerror("%s %s VIA reads data %02x (%03x)\n", machine().time().as_string(), machine().describe_context(), data, checkpoint_live.shift_reg);
+
+ return data;
+}
+
+WRITE8_MEMBER( c2040_fdc_t::write )
+{
+ if (m_pi != data)
+ {
+ live_sync();
+ m_pi = cur_live.pi = data;
+ checkpoint();
+ if (LOG) logerror("%s %s PI %02x\n", machine().time().as_string(), machine().describe_context(), data);
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c2040_fdc_t::ds0_w )
+{
+ m_ds0 = state;
+}
+
+WRITE_LINE_MEMBER( c2040_fdc_t::ds1_w )
+{
+ m_ds1 = state;
+
+ ds_w(m_ds1 << 1 | m_ds0);
+}
+
+WRITE_LINE_MEMBER( c2040_fdc_t::drv_sel_w )
+{
+ if (m_drv_sel != state)
+ {
+ live_sync();
+ m_drv_sel = cur_live.drv_sel = state;
+ checkpoint();
+ if (LOG) logerror("%s %s DRV SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c2040_fdc_t::mode_sel_w )
+{
+ if (m_mode_sel != state)
+ {
+ live_sync();
+ m_mode_sel = cur_live.mode_sel = state;
+ checkpoint();
+ if (LOG) logerror("%s %s MODE SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c2040_fdc_t::rw_sel_w )
+{
+ if (m_rw_sel != state)
+ {
+ live_sync();
+ m_rw_sel = cur_live.rw_sel = state;
+ checkpoint();
+ if (LOG) logerror("%s %s RW SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
+ if (m_rw_sel) {
+ stop_writing(machine().time());
+ } else {
+ start_writing(machine().time());
+ }
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c2040_fdc_t::mtr0_w )
+{
+ if (m_mtr0 != state)
+ {
+ live_sync();
+ m_mtr0 = state;
+ if (LOG) logerror("%s %s MTR0 %u\n", machine().time().as_string(), machine().describe_context(), state);
+ m_floppy0->mon_w(state);
+ checkpoint();
+
+ if (!m_mtr0 || !m_mtr1) {
+ if(cur_live.state == IDLE) {
+ live_start();
+ }
+ } else {
+ live_abort();
+ }
+
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c2040_fdc_t::mtr1_w )
+{
+ if (m_mtr1 != state)
+ {
+ live_sync();
+ m_mtr1 = state;
+ if (LOG) logerror("%s %s MTR1 %u\n", machine().time().as_string(), machine().describe_context(), state);
+ if (m_floppy1) m_floppy1->mon_w(state);
+ checkpoint();
+
+ if (!m_mtr0 || !m_mtr1) {
+ if(cur_live.state == IDLE) {
+ live_start();
+ }
+ } else {
+ live_abort();
+ }
+
+ live_run();
+ }
+}
+
+void c2040_fdc_t::stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp)
+{
+ if (mtr) return;
+
+ int tracks = 0;
+
+ switch (old_stp)
+ {
+ case 0: if (stp == 1) tracks++; else if (stp == 3) tracks--; break;
+ case 1: if (stp == 2) tracks++; else if (stp == 0) tracks--; break;
+ case 2: if (stp == 3) tracks++; else if (stp == 1) tracks--; break;
+ case 3: if (stp == 0) tracks++; else if (stp == 2) tracks--; break;
+ }
+
+ if (tracks == -1)
+ {
+ floppy->dir_w(1);
+ floppy->stp_w(1);
+ floppy->stp_w(0);
+ }
+ else if (tracks == 1)
+ {
+ floppy->dir_w(0);
+ floppy->stp_w(1);
+ floppy->stp_w(0);
+ }
+
+ old_stp = stp;
+}
+
+void c2040_fdc_t::stp0_w(int stp)
+{
+ if (m_stp0 != stp)
+ {
+ live_sync();
+ this->stp_w(m_floppy0, m_mtr0, m_stp0, stp);
+ checkpoint();
+ live_run();
+ }
+}
+
+void c2040_fdc_t::stp1_w(int stp)
+{
+ if (m_stp1 != stp)
+ {
+ live_sync();
+ if (m_floppy1) this->stp_w(m_floppy1, m_mtr1, m_stp1, stp);
+ checkpoint();
+ live_run();
+ }
+}
+
+void c2040_fdc_t::ds_w(int ds)
+{
+ if (m_ds != ds)
+ {
+ live_sync();
+ m_ds = cur_live.ds = ds;
+ if (LOG) logerror("%s %s DS %u\n", machine().time().as_string(), machine().describe_context(), ds);
+ checkpoint();
+ live_run();
+ }
+}
+
+void c2040_fdc_t::set_floppy(floppy_image_device *floppy0, floppy_image_device *floppy1)
+{
+ m_floppy0 = floppy0;
+ m_floppy1 = floppy1;
+}
diff --git a/src/devices/bus/ieee488/c2040fdc.h b/src/devices/bus/ieee488/c2040fdc.h
new file mode 100644
index 00000000000..178e81240a2
--- /dev/null
+++ b/src/devices/bus/ieee488/c2040fdc.h
@@ -0,0 +1,168 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 2040 floppy disk controller emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __C2040_FLOPPY__
+#define __C2040_FLOPPY__
+
+#include "emu.h"
+#include "formats/c3040_dsk.h"
+#include "formats/c4040_dsk.h"
+#include "formats/d64_dsk.h"
+#include "formats/g64_dsk.h"
+#include "imagedev/floppy.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_C2040_SYNC_CALLBACK(_write) \
+ devcb = &c2040_fdc_t::set_sync_wr_callback(*device, DEVCB_##_write);
+
+#define MCFG_C2040_READY_CALLBACK(_write) \
+ devcb = &c2040_fdc_t::set_ready_wr_callback(*device, DEVCB_##_write);
+
+#define MCFG_C2040_ERROR_CALLBACK(_write) \
+ devcb = &c2040_fdc_t::set_error_wr_callback(*device, DEVCB_##_write);
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> c2040_fdc_t
+
+class c2040_fdc_t : public device_t
+{
+public:
+ // construction/destruction
+ c2040_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ template<class _Object> static devcb_base &set_sync_wr_callback(device_t &device, _Object object) { return downcast<c2040_fdc_t &>(device).m_write_sync.set_callback(object); }
+ template<class _Object> static devcb_base &set_ready_wr_callback(device_t &device, _Object object) { return downcast<c2040_fdc_t &>(device).m_write_ready.set_callback(object); }
+ template<class _Object> static devcb_base &set_error_wr_callback(device_t &device, _Object object) { return downcast<c2040_fdc_t &>(device).m_write_error.set_callback(object); }
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ DECLARE_WRITE_LINE_MEMBER( ds0_w );
+ DECLARE_WRITE_LINE_MEMBER( ds1_w );
+ DECLARE_WRITE_LINE_MEMBER( drv_sel_w );
+ DECLARE_WRITE_LINE_MEMBER( mode_sel_w );
+ DECLARE_WRITE_LINE_MEMBER( rw_sel_w );
+ DECLARE_WRITE_LINE_MEMBER( mtr0_w );
+ DECLARE_WRITE_LINE_MEMBER( mtr1_w );
+
+ DECLARE_READ_LINE_MEMBER( wps_r ) { return checkpoint_live.drv_sel ? m_floppy1->wpt_r() : m_floppy0->wpt_r(); }
+ DECLARE_READ_LINE_MEMBER( sync_r ) { return checkpoint_live.sync; }
+
+ void stp0_w(int stp);
+ void stp1_w(int stp);
+ void ds_w(int ds);
+
+ void set_floppy(floppy_image_device *floppy0, floppy_image_device *floppy1);
+
+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);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+
+ void stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp);
+
+ enum {
+ IDLE,
+ RUNNING,
+ RUNNING_SYNCPOINT
+ };
+
+ struct live_info {
+ attotime tm;
+ int state, next_state;
+ int sync;
+ int ready;
+ int error;
+ int ds;
+ int drv_sel;
+ int mode_sel;
+ int rw_sel;
+ int odd_hd;
+
+ attotime edge;
+ UINT16 shift_reg;
+ int cycle_counter;
+ int cell_counter;
+ int bit_counter;
+ UINT8 e;
+ offs_t i;
+
+ UINT8 pi;
+ UINT16 shift_reg_write;
+ attotime write_start_time;
+ attotime write_buffer[32];
+ int write_position;
+ };
+
+ devcb_write_line m_write_sync;
+ devcb_write_line m_write_ready;
+ devcb_write_line m_write_error;
+
+ required_memory_region m_gcr_rom;
+
+ floppy_image_device *m_floppy0;
+ floppy_image_device *m_floppy1;
+
+ int m_mtr0;
+ int m_mtr1;
+ int m_stp0;
+ int m_stp1;
+ int m_ds;
+ int m_ds0;
+ int m_ds1;
+ int m_drv_sel;
+ int m_mode_sel;
+ int m_rw_sel;
+ int m_odd_hd;
+ UINT8 m_pi;
+
+ attotime m_period;
+
+ live_info cur_live, checkpoint_live;
+ emu_timer *t_gen;
+
+ floppy_image_device* get_floppy();
+
+ void live_start();
+ void checkpoint();
+ void rollback();
+ bool write_next_bit(bool bit, const attotime &limit);
+ void start_writing(const attotime &tm);
+ void commit(const attotime &tm);
+ void stop_writing(const attotime &tm);
+ void live_delay(int state);
+ void live_sync();
+ void live_abort();
+ void live_run(const attotime &limit = attotime::never);
+ void get_next_edge(const attotime &when);
+ int get_next_bit(attotime &tm, const attotime &limit);
+};
+
+
+// device type definition
+extern const device_type C2040_FDC;
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/c8050.c b/src/devices/bus/ieee488/c8050.c
new file mode 100644
index 00000000000..e60386db689
--- /dev/null
+++ b/src/devices/bus/ieee488/c8050.c
@@ -0,0 +1,950 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 8050/8250/SFD-1001 Disk Drive emulation
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - Micropolis 8x50 stepper motor is same as 4040, except it takes 4 pulses to step a track instead of 1
+
+ - BASIC program to set 8250/SFD-1001 to 8050 mode:
+
+ 10 OPEN 15,8,15
+ 20 PRINT#15,"M-W"CHR$(172)CHR$(16)CHR$(1)CHR$(1)
+ 30 PRINT#15,"M-W"CHR$(195)CHR$(16)CHR$(1)CHR$(0)
+ 40 PRINT#15,"U9"
+ 50 CLOSE 15
+
+*/
+
+#include "c8050.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define M6502_TAG "un1"
+#define M6532_0_TAG "uc1"
+#define M6532_1_TAG "ue1"
+#define M6504_TAG "uh3"
+#define M6522_TAG "um3"
+#define M6530_TAG "uk3"
+#define FDC_TAG "fdc"
+
+
+enum
+{
+ LED_POWER = 0,
+ LED_ACT0,
+ LED_ACT1,
+ LED_ERR
+};
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type C8050 = &device_creator<c8050_t>;
+const device_type C8250 = &device_creator<c8250_t>;
+const device_type C8250LP = &device_creator<c8250lp_t>;
+const device_type SFD1001 = &device_creator<sfd1001_t>;
+
+
+//-------------------------------------------------
+// ROM( c8050 )
+//-------------------------------------------------
+
+/*
+
+ DOS/CONTROLLER ROMS FOR DIGITAL PCB #8050002
+
+ DESCRIPTION PCB PART NO. UL1 UH1 UK3
+
+ 2.5 Micropolis 8050002-01 901482-07 901482-06 901483-03
+ 2.5 Tandon 8050002-02 901482-07 901482-06 901483-04
+ 2.7 Tandon 8050002-03 901887-01 901888-01 901884-01
+ 2.7 Micropolis 8050002-04 901887-01 901888-01 901885-04
+ 2.7 MPI 8050 8050002-05 901887-01 901888-01 901869-01
+ 2.7 MPI 8250 8050002-06 901887-01 901888-01 901869-01
+
+*/
+
+ROM_START( c8050 ) // schematic 8050001
+ ROM_REGION( 0x4000, M6502_TAG, 0 )
+ ROM_DEFAULT_BIOS("dos27")
+ ROM_SYSTEM_BIOS( 0, "dos25r1", "DOS 2.5 Revision 1" )
+ ROMX_LOAD( "901482-01.ul1", 0x0000, 0x2000, NO_DUMP, ROM_BIOS(1) )
+ ROMX_LOAD( "901482-02.uh1", 0x2000, 0x2000, NO_DUMP, ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "dos25r2", "DOS 2.5 Revision 2" )
+ ROMX_LOAD( "901482-03.ul1", 0x0000, 0x2000, CRC(09a609b9) SHA1(166d8bfaaa9c4767f9b17ad63fc7ae77c199a64e), ROM_BIOS(2) )
+ ROMX_LOAD( "901482-04.uh1", 0x2000, 0x2000, CRC(1bcf9df9) SHA1(217f4a8b348658bb365f4a1de21ecbaa6402b1c0), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 2, "dos25r3", "DOS 2.5 Revision 3" )
+ ROMX_LOAD( "901482-06.ul1", 0x0000, 0x2000, CRC(3cbd2756) SHA1(7f5fbed0cddb95138dd99b8fe84fddab900e3650), ROM_BIOS(3) )
+ ROMX_LOAD( "901482-07.uh1", 0x2000, 0x2000, CRC(c7532d90) SHA1(0b6d1e55afea612516df5f07f4a6dccd3bd73963), ROM_BIOS(3) )
+ ROM_SYSTEM_BIOS( 3, "dos27", "DOS 2.7" )// 2364 ROM DOS 2.7
+ ROMX_LOAD( "901887-01.ul1", 0x0000, 0x2000, CRC(0073b8b2) SHA1(b10603195f240118fe5fb6c6dfe5c5097463d890), ROM_BIOS(4) )
+ ROMX_LOAD( "901888-01.uh1", 0x2000, 0x2000, CRC(de9b6132) SHA1(2e6c2d7ca934e5c550ad14bd5e9e7749686b7af4), ROM_BIOS(4) )
+
+ ROM_REGION( 0x400, M6530_TAG, 0 )
+ ROM_LOAD_OPTIONAL( "901483-02.uk3", 0x000, 0x400, CRC(d7277f95) SHA1(7607f9357f3a08f2a9f20931058d60d9e3c17d39) ) // 6530-036
+ ROM_LOAD_OPTIONAL( "901483-03.uk3", 0x000, 0x400, CRC(9e83fa70) SHA1(e367ea8a5ddbd47f13570088427293138a10784b) ) // 6530-038 RIOT DOS 2.5 Micropolis
+ ROM_LOAD_OPTIONAL( "901483-04.uk3", 0x000, 0x400, CRC(ae1c7866) SHA1(13bdf0bb387159167534c07a4554964734373f11) ) // 6530-039 RIOT DOS 2.5 Tandon
+ ROM_LOAD_OPTIONAL( "901884-01.uk3", 0x000, 0x400, CRC(9e9a9f90) SHA1(39498d7369a31ea7527b5044071acf35a84ea2ac) ) // 6530-40 RIOT DOS 2.7 Tandon
+ ROM_LOAD_OPTIONAL( "901885-01.uk3", 0x000, 0x400, NO_DUMP ) // 6530-044
+ ROM_LOAD_OPTIONAL( "901885-04.uk3", 0x000, 0x400, CRC(bab998c9) SHA1(0dc9a3b60f1b866c63eebd882403532fc59fe57f) ) // 6530-47 RIOT DOS 2.7 Micropolis
+ ROM_LOAD( "901869-01.uk3", 0x000, 0x400, CRC(2915327a) SHA1(3a9a80f72ce76e5f5c72513f8ef7553212912ae3) ) // 6530-48 RIOT DOS 2.7 MPI
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c8050_t::device_rom_region() const
+{
+ return ROM_NAME( c8050 );
+}
+
+
+//-------------------------------------------------
+// ROM( c8250lp )
+//-------------------------------------------------
+
+ROM_START( c8250lp )
+ ROM_REGION( 0x4000, M6502_TAG, 0 )
+ ROM_DEFAULT_BIOS("dos27")
+ ROM_SYSTEM_BIOS( 0, "dos27", "DOS 2.7" )
+ ROMX_LOAD( "251165-01.ua11", 0x0000, 0x2000, NO_DUMP, ROM_BIOS(1) )
+ ROMX_LOAD( "251166-01.ua13", 0x2000, 0x2000, NO_DUMP, ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "dos27b", "DOS 2.7B" )
+ ROMX_LOAD( "dos-2.7b.bin", 0x0000, 0x4000, CRC(96e3b209) SHA1(9849300be9f2e0143c2ed2564d26a4ba3b27526c), ROM_BIOS(2) ) // CBM DOS 2.7B from the 8250LP inside 8296D
+ ROM_SYSTEM_BIOS( 2, "speeddos", "SpeedDOS" )
+ ROMX_LOAD( "speeddos-c000.ua11", 0x0000, 0x2000, CRC(46cc260f) SHA1(e9838635d6868e35ec9c161b6e5c1ad92a4a241a), ROM_BIOS(3) )
+ ROMX_LOAD( "speeddos-e000.ua13", 0x2000, 0x2000, CRC(88cfd505) SHA1(0fb570b180504cd1fcb7d203d8d37ea3d7e72ab4), ROM_BIOS(3) )
+
+ ROM_REGION( 0x800, M6504_TAG, 0 )
+ ROMX_LOAD( "251256-02", 0x000, 0x400, NO_DUMP, ROM_BIOS(1) ) // 6530-050
+ ROMX_LOAD( "251474-01b", 0x000, 0x400, CRC(9e9a9f90) SHA1(39498d7369a31ea7527b5044071acf35a84ea2ac), ROM_BIOS(1) ) // Matsushita
+ ROMX_LOAD( "fdc-2.7b.bin", 0x000, 0x800, CRC(13a24482) SHA1(1cfa52d2ed245a95e6369b46a36c6c7aa3929931), ROM_BIOS(2) ) // CBM DOS 2.7B FDC ROM from the 8250LP inside 8296D
+ ROMX_LOAD( "speeddos-fdc-f800.bin", 0x000, 0x800, CRC(253e760f) SHA1(3f7892a9bab84b633f45686bbbbe66bc2948c8e5), ROM_BIOS(3) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c8250lp_t::device_rom_region() const
+{
+ return ROM_NAME( c8250lp );
+}
+
+
+//-------------------------------------------------
+// ROM( sfd1001 )
+//-------------------------------------------------
+
+ROM_START( sfd1001 ) // schematic 251406
+ ROM_REGION( 0x4000, M6502_TAG, 0 )
+ ROM_LOAD( "901887-01.1j", 0x0000, 0x2000, CRC(0073b8b2) SHA1(b10603195f240118fe5fb6c6dfe5c5097463d890) )
+ ROM_LOAD( "901888-01.3j", 0x2000, 0x2000, CRC(de9b6132) SHA1(2e6c2d7ca934e5c550ad14bd5e9e7749686b7af4) )
+
+ ROM_REGION( 0x400, M6530_TAG, 0 )
+ ROM_LOAD( "901885-04.u1", 0x000, 0x400, CRC(bab998c9) SHA1(0dc9a3b60f1b866c63eebd882403532fc59fe57f) )
+
+ ROM_REGION( 0x800, M6504_TAG, 0 )
+ ROM_LOAD( "251257-02a.u2", 0x000, 0x800, CRC(b51150de) SHA1(3b954eb34f7ea088eed1d33ebc6d6e83a3e9be15) )
+
+ ROM_REGION( 0x800, "gcr", 0)
+ ROM_LOAD( "901467-01.5c", 0x000, 0x800, CRC(a23337eb) SHA1(97df576397608455616331f8e837cb3404363fa2) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *sfd1001_t::device_rom_region() const
+{
+ return ROM_NAME( sfd1001 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c8050_main_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c8050_main_mem, AS_PROGRAM, 8, c8050_t )
+ AM_RANGE(0x0000, 0x007f) AM_MIRROR(0x0100) AM_DEVICE(M6532_0_TAG, mos6532_t, ram_map)
+ AM_RANGE(0x0080, 0x00ff) AM_MIRROR(0x0100) AM_DEVICE(M6532_1_TAG, mos6532_t, ram_map)
+ AM_RANGE(0x0200, 0x021f) AM_MIRROR(0x0d60) AM_DEVICE(M6532_0_TAG, mos6532_t, io_map)
+ AM_RANGE(0x0280, 0x029f) AM_MIRROR(0x0d60) AM_DEVICE(M6532_1_TAG, mos6532_t, io_map)
+ AM_RANGE(0x1000, 0x13ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x2000, 0x23ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x3000, 0x33ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x4000, 0x43ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0xc000, 0xffff) AM_ROM AM_REGION(M6502_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c8050_fdc_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c8050_fdc_mem, AS_PROGRAM, 8, c8050_t )
+ ADDRESS_MAP_GLOBAL_MASK(0x1fff)
+ AM_RANGE(0x0000, 0x003f) AM_MIRROR(0x0300) AM_DEVICE(M6530_TAG, mos6530_t, ram_map)
+ AM_RANGE(0x0040, 0x004f) AM_MIRROR(0x0330) AM_DEVICE(M6522_TAG, via6522_device, map)
+ AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVICE(M6530_TAG, mos6530_t, io_map)
+ AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x1000, 0x13ff) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0x1c00, 0x1fff) AM_DEVICE(M6530_TAG, mos6530_t, rom_map)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c8250lp_fdc_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c8250lp_fdc_mem, AS_PROGRAM, 8, c8050_t )
+ ADDRESS_MAP_GLOBAL_MASK(0x1fff)
+ AM_RANGE(0x0000, 0x003f) AM_MIRROR(0x0300) AM_DEVICE(M6530_TAG, mos6530_t, ram_map)
+ AM_RANGE(0x0040, 0x004f) AM_MIRROR(0x0330) AM_DEVICE(M6522_TAG, via6522_device, map)
+ AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVICE(M6530_TAG, mos6530_t, io_map)
+ AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x1000, 0x13ff) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0x1800, 0x1fff) AM_ROM AM_REGION(M6504_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( sfd1001_fdc_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( sfd1001_fdc_mem, AS_PROGRAM, 8, c8050_t )
+ ADDRESS_MAP_GLOBAL_MASK(0x1fff)
+ AM_RANGE(0x0000, 0x003f) AM_MIRROR(0x0300) AM_DEVICE(M6530_TAG, mos6530_t, ram_map)
+ AM_RANGE(0x0040, 0x004f) AM_MIRROR(0x0330) AM_DEVICE(M6522_TAG, via6522_device, map)
+ AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVICE(M6530_TAG, mos6530_t, io_map)
+ AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x1000, 0x13ff) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0x1800, 0x1fff) AM_ROM AM_REGION(M6504_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// riot6532 uc1
+//-------------------------------------------------
+
+READ8_MEMBER( c8050_t::dio_r )
+{
+ /*
+
+ bit description
+
+ PA0 DI0
+ PA1 DI1
+ PA2 DI2
+ PA3 DI3
+ PA4 DI4
+ PA5 DI5
+ PA6 DI6
+ PA7 DI7
+
+ */
+
+ return m_bus->dio_r();
+}
+
+WRITE8_MEMBER( c8050_t::dio_w )
+{
+ /*
+
+ bit description
+
+ PB0 DO0
+ PB1 DO1
+ PB2 DO2
+ PB3 DO3
+ PB4 DO4
+ PB5 DO5
+ PB6 DO6
+ PB7 DO7
+
+ */
+
+ m_bus->dio_w(this, data);
+}
+
+//-------------------------------------------------
+// riot6532 ue1
+//-------------------------------------------------
+
+READ8_MEMBER( c8050_t::riot1_pa_r )
+{
+ /*
+
+ bit description
+
+ PA0 ATNA
+ PA1 DACO
+ PA2 RFDO
+ PA3 EOIO
+ PA4 DAVO
+ PA5 EOII
+ PA6 DAVI
+ PA7 _ATN
+
+ */
+
+ UINT8 data = 0;
+
+ // end or identify in
+ data |= m_bus->eoi_r() << 5;
+
+ // data valid in
+ data |= m_bus->dav_r() << 6;
+
+ // attention
+ data |= !m_bus->atn_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c8050_t::riot1_pa_w )
+{
+ /*
+
+ bit description
+
+ PA0 ATNA
+ PA1 DACO
+ PA2 RFDO
+ PA3 EOIO
+ PA4 DAVO
+ PA5 EOII
+ PA6 DAVI
+ PA7 _ATN
+
+ */
+
+ // attention acknowledge
+ m_atna = BIT(data, 0);
+
+ // data accepted out
+ m_daco = BIT(data, 1);
+
+ // not ready for data out
+ m_rfdo = BIT(data, 2);
+
+ // end or identify out
+ m_bus->eoi_w(this, BIT(data, 3));
+
+ // data valid out
+ m_bus->dav_w(this, BIT(data, 4));
+
+ update_ieee_signals();
+}
+
+READ8_MEMBER( c8050_t::riot1_pb_r )
+{
+ /*
+
+ bit description
+
+ PB0 DEVICE NUMBER SELECTION
+ PB1 DEVICE NUMBER SELECTION
+ PB2 DEVICE NUMBER SELECTION
+ PB3
+ PB4
+ PB5
+ PB6 DACI
+ PB7 RFDI
+
+ */
+
+ UINT8 data = 0;
+
+ // device number selection
+ data |= m_slot->get_address() - 8;
+
+ // data accepted in
+ data |= m_bus->ndac_r() << 6;
+
+ // ready for data in
+ data |= m_bus->nrfd_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c8050_t::riot1_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0
+ PB1
+ PB2
+ PB3 ACT LED 1
+ PB4 ACT LED 0
+ PB5 ERR LED
+ PB6
+ PB7
+
+ */
+
+ // activity led 1
+ output_set_led_value(LED_ACT1, BIT(data, 3));
+
+ // activity led 0
+ output_set_led_value(LED_ACT0, BIT(data, 4));
+
+ // error led
+ output_set_led_value(LED_ERR, BIT(data, 5));
+}
+
+WRITE8_MEMBER( c8050_t::via_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0 S1A
+ PB1 S1B
+ PB2 S0A
+ PB3 S0B
+ PB4 MTR1
+ PB5 MTR0
+ PB6 PULL SYNC
+ PB7
+
+ */
+
+ // spindle motor 1
+ m_fdc->mtr1_w(BIT(data, 4));
+
+ // spindle motor 0
+ m_fdc->mtr0_w(BIT(data, 5));
+
+ // stepper motor 1
+ m_fdc->stp1_w(data & 0x03);
+
+ // stepper motor 0
+ m_fdc->stp0_w((data >> 2) & 0x03);
+
+ // PLL sync
+ m_fdc->pull_sync_w(!BIT(data, 6));
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( c8050_floppies )
+//-------------------------------------------------
+
+static SLOT_INTERFACE_START( c8050_floppies )
+ SLOT_INTERFACE( "525ssqd", FLOPPY_525_SSQD )
+SLOT_INTERFACE_END
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( c8050_t::floppy_formats )
+ FLOPPY_D80_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( c8250_floppies )
+//-------------------------------------------------
+
+static SLOT_INTERFACE_START( c8250_floppies )
+ SLOT_INTERFACE( "525qd", FLOPPY_525_QD )
+SLOT_INTERFACE_END
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( sfd1001_floppies )
+//-------------------------------------------------
+
+static SLOT_INTERFACE_START( sfd1001_floppies )
+ SLOT_INTERFACE( "525qd", FLOPPY_525_QD ) // Matsushita JU-570 / JU-570-2
+SLOT_INTERFACE_END
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( c8250_t::floppy_formats )
+ FLOPPY_D80_FORMAT,
+ FLOPPY_D82_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( c8250lp_t::floppy_formats )
+ FLOPPY_D80_FORMAT,
+ FLOPPY_D82_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+FLOPPY_FORMATS_MEMBER( sfd1001_t::floppy_formats )
+ FLOPPY_D80_FORMAT,
+ FLOPPY_D82_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( c8050 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c8050 )
+ // DOS
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_12MHz/12)
+ MCFG_CPU_PROGRAM_MAP(c8050_main_mem)
+
+ MCFG_DEVICE_ADD(M6532_0_TAG, MOS6532n, XTAL_12MHz/12)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8050_t, dio_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8050_t, dio_w))
+
+ MCFG_DEVICE_ADD(M6532_1_TAG, MOS6532n, XTAL_12MHz/12)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8050_t, riot1_pa_r))
+ MCFG_MOS6530n_OUT_PA_CB(WRITE8(c8050_t, riot1_pa_w))
+ MCFG_MOS6530n_IN_PB_CB(READ8(c8050_t, riot1_pb_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8050_t, riot1_pb_w))
+ MCFG_MOS6530n_IRQ_CB(INPUTLINE(M6502_TAG, INPUT_LINE_IRQ0))
+
+ // controller
+ MCFG_CPU_ADD(M6504_TAG, M6504, XTAL_12MHz/12)
+ MCFG_CPU_PROGRAM_MAP(c8050_fdc_mem)
+
+ MCFG_DEVICE_ADD(M6522_TAG, VIA6522, XTAL_12MHz/12)
+ MCFG_VIA6522_READPA_HANDLER(DEVREAD8(FDC_TAG, c8050_fdc_t, read))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(c8050_t, via_pb_w))
+ MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE(FDC_TAG, c8050_fdc_t, mode_sel_w))
+ MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE(FDC_TAG, c8050_fdc_t, rw_sel_w))
+
+ MCFG_DEVICE_ADD(M6530_TAG, MOS6530n, XTAL_12MHz/12)
+ MCFG_MOS6530n_OUT_PA_CB(DEVWRITE8(FDC_TAG, c8050_fdc_t, write))
+ MCFG_MOS6530n_OUT_PB0_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, drv_sel_w))
+ MCFG_MOS6530n_OUT_PB1_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, ds0_w))
+ MCFG_MOS6530n_OUT_PB2_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, ds1_w))
+ MCFG_MOS6530n_IN_PB3_CB(DEVREADLINE(FDC_TAG, c8050_fdc_t, wps_r))
+ MCFG_MOS6530n_IN_PB6_CB(VCC) // SINGLE SIDED
+ MCFG_MOS6530n_OUT_PB7_CB(INPUTLINE(M6504_TAG, M6502_IRQ_LINE))
+
+ MCFG_DEVICE_ADD(FDC_TAG, C8050_FDC, XTAL_12MHz/2)
+ MCFG_C8050_SYNC_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_pb7))
+ MCFG_C8050_READY_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_ca1))
+ MCFG_C8050_BRDY_CALLBACK(INPUTLINE(M6504_TAG, M6502_SET_OVERFLOW)) MCFG_DEVCB_XOR(1)
+ MCFG_C8050_ERROR_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_cb1))
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG ":0", c8050_floppies, "525ssqd", c8050_t::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG ":1", c8050_floppies, "525ssqd", c8050_t::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor c8050_t::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( c8050 );
+}
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( c8250 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c8250 )
+ // DOS
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_12MHz/12)
+ MCFG_CPU_PROGRAM_MAP(c8050_main_mem)
+
+ MCFG_DEVICE_ADD(M6532_0_TAG, MOS6532n, XTAL_12MHz/12)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8050_t, dio_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8050_t, dio_w))
+
+ MCFG_DEVICE_ADD(M6532_1_TAG, MOS6532n, XTAL_12MHz/12)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8050_t, riot1_pa_r))
+ MCFG_MOS6530n_OUT_PA_CB(WRITE8(c8050_t, riot1_pa_w))
+ MCFG_MOS6530n_IN_PB_CB(READ8(c8050_t, riot1_pb_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8050_t, riot1_pb_w))
+ MCFG_MOS6530n_IRQ_CB(INPUTLINE(M6502_TAG, INPUT_LINE_IRQ0))
+
+ // controller
+ MCFG_CPU_ADD(M6504_TAG, M6504, XTAL_12MHz/12)
+ MCFG_CPU_PROGRAM_MAP(c8050_fdc_mem)
+
+ MCFG_DEVICE_ADD(M6522_TAG, VIA6522, XTAL_12MHz/12)
+ MCFG_VIA6522_READPA_HANDLER(DEVREAD8(FDC_TAG, c8050_fdc_t, read))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(c8050_t, via_pb_w))
+ MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE(FDC_TAG, c8050_fdc_t, mode_sel_w))
+ MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE(FDC_TAG, c8050_fdc_t, rw_sel_w))
+
+ MCFG_DEVICE_ADD(M6530_TAG, MOS6530n, XTAL_12MHz/12)
+ MCFG_MOS6530n_OUT_PA_CB(DEVWRITE8(FDC_TAG, c8050_fdc_t, write))
+ MCFG_MOS6530n_OUT_PB0_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, drv_sel_w))
+ MCFG_MOS6530n_OUT_PB1_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, ds0_w))
+ MCFG_MOS6530n_OUT_PB2_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, ds1_w))
+ MCFG_MOS6530n_IN_PB3_CB(DEVREADLINE(FDC_TAG, c8050_fdc_t, wps_r))
+ MCFG_MOS6530n_OUT_PB4_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, odd_hd_w))
+ MCFG_MOS6530n_IN_PB6_CB(GND) // DOUBLE SIDED
+ MCFG_MOS6530n_OUT_PB7_CB(INPUTLINE(M6504_TAG, M6502_IRQ_LINE))
+
+ MCFG_DEVICE_ADD(FDC_TAG, C8050_FDC, XTAL_12MHz/2)
+ MCFG_C8050_SYNC_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_pb7))
+ MCFG_C8050_READY_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_ca1))
+ MCFG_C8050_BRDY_CALLBACK(INPUTLINE(M6504_TAG, M6502_SET_OVERFLOW)) MCFG_DEVCB_XOR(1)
+ MCFG_C8050_ERROR_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_cb1))
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG ":0", c8250_floppies, "525qd", c8250_t::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG ":1", c8250_floppies, "525qd", c8250_t::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor c8250_t::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( c8250 );
+}
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( c8250lp )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c8250lp )
+ // DOS
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_12MHz/12)
+ MCFG_CPU_PROGRAM_MAP(c8050_main_mem)
+
+ MCFG_DEVICE_ADD(M6532_0_TAG, MOS6532n, XTAL_12MHz/12)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8050_t, dio_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8050_t, dio_w))
+
+ MCFG_DEVICE_ADD(M6532_1_TAG, MOS6532n, XTAL_12MHz/12)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8050_t, riot1_pa_r))
+ MCFG_MOS6530n_OUT_PA_CB(WRITE8(c8050_t, riot1_pa_w))
+ MCFG_MOS6530n_IN_PB_CB(READ8(c8050_t, riot1_pb_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8050_t, riot1_pb_w))
+ MCFG_MOS6530n_IRQ_CB(INPUTLINE(M6502_TAG, INPUT_LINE_IRQ0))
+
+ // controller
+ MCFG_CPU_ADD(M6504_TAG, M6504, XTAL_12MHz/12)
+ MCFG_CPU_PROGRAM_MAP(c8250lp_fdc_mem)
+
+ MCFG_DEVICE_ADD(M6522_TAG, VIA6522, XTAL_12MHz/12)
+ MCFG_VIA6522_READPA_HANDLER(DEVREAD8(FDC_TAG, c8050_fdc_t, read))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(c8050_t, via_pb_w))
+ MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE(FDC_TAG, c8050_fdc_t, mode_sel_w))
+ MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE(FDC_TAG, c8050_fdc_t, rw_sel_w))
+
+ MCFG_DEVICE_ADD(M6530_TAG, MOS6530n, XTAL_12MHz/12)
+ MCFG_MOS6530n_OUT_PA_CB(DEVWRITE8(FDC_TAG, c8050_fdc_t, write))
+ MCFG_MOS6530n_OUT_PB0_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, drv_sel_w))
+ MCFG_MOS6530n_OUT_PB1_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, ds0_w))
+ MCFG_MOS6530n_OUT_PB2_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, ds1_w))
+ MCFG_MOS6530n_IN_PB3_CB(DEVREADLINE(FDC_TAG, c8050_fdc_t, wps_r))
+ MCFG_MOS6530n_OUT_PB4_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, odd_hd_w))
+ MCFG_MOS6530n_IN_PB6_CB(GND) // DOUBLE SIDED
+ MCFG_MOS6530n_OUT_PB7_CB(INPUTLINE(M6504_TAG, M6502_IRQ_LINE))
+
+ MCFG_DEVICE_ADD(FDC_TAG, C8050_FDC, XTAL_12MHz/2)
+ MCFG_C8050_SYNC_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_pb7))
+ MCFG_C8050_READY_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_ca1))
+ MCFG_C8050_BRDY_CALLBACK(INPUTLINE(M6504_TAG, M6502_SET_OVERFLOW)) MCFG_DEVCB_XOR(1)
+ MCFG_C8050_ERROR_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_cb1))
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG ":0", c8250_floppies, "525qd", c8250lp_t::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG ":1", c8250_floppies, "525qd", c8250lp_t::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor c8250lp_t::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( c8250lp );
+}
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( sfd1001 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( sfd1001 )
+ // DOS
+ MCFG_CPU_ADD(M6502_TAG, M6502, XTAL_12MHz/12)
+ MCFG_CPU_PROGRAM_MAP(c8050_main_mem)
+
+ MCFG_DEVICE_ADD(M6532_0_TAG, MOS6532n, XTAL_12MHz/12)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8050_t, dio_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8050_t, dio_w))
+
+ MCFG_DEVICE_ADD(M6532_1_TAG, MOS6532n, XTAL_12MHz/12)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8050_t, riot1_pa_r))
+ MCFG_MOS6530n_OUT_PA_CB(WRITE8(c8050_t, riot1_pa_w))
+ MCFG_MOS6530n_IN_PB_CB(READ8(c8050_t, riot1_pb_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8050_t, riot1_pb_w))
+ MCFG_MOS6530n_IRQ_CB(INPUTLINE(M6502_TAG, INPUT_LINE_IRQ0))
+
+ // controller
+ MCFG_CPU_ADD(M6504_TAG, M6504, XTAL_12MHz/12)
+ MCFG_CPU_PROGRAM_MAP(sfd1001_fdc_mem)
+
+ MCFG_DEVICE_ADD(M6522_TAG, VIA6522, XTAL_12MHz/12)
+ MCFG_VIA6522_READPA_HANDLER(DEVREAD8(FDC_TAG, c8050_fdc_t, read))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(c8050_t, via_pb_w))
+ MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE(FDC_TAG, c8050_fdc_t, mode_sel_w))
+ MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE(FDC_TAG, c8050_fdc_t, rw_sel_w))
+
+ MCFG_DEVICE_ADD(M6530_TAG, MOS6530n, XTAL_12MHz/12)
+ MCFG_MOS6530n_OUT_PA_CB(DEVWRITE8(FDC_TAG, c8050_fdc_t, write))
+ MCFG_MOS6530n_OUT_PB1_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, ds0_w))
+ MCFG_MOS6530n_OUT_PB2_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, ds1_w))
+ MCFG_MOS6530n_IN_PB3_CB(DEVREADLINE(FDC_TAG, c8050_fdc_t, wps_r))
+ MCFG_MOS6530n_OUT_PB4_CB(DEVWRITELINE(FDC_TAG, c8050_fdc_t, odd_hd_w))
+ MCFG_MOS6530n_IN_PB6_CB(GND) // DOUBLE SIDED
+ MCFG_MOS6530n_OUT_PB7_CB(INPUTLINE(M6504_TAG, M6502_IRQ_LINE))
+
+ MCFG_DEVICE_ADD(FDC_TAG, C8050_FDC, XTAL_12MHz/2)
+ MCFG_C8050_SYNC_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_pb7))
+ MCFG_C8050_READY_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_ca1))
+ MCFG_C8050_BRDY_CALLBACK(INPUTLINE(M6504_TAG, M6502_SET_OVERFLOW)) MCFG_DEVCB_XOR(1)
+ MCFG_C8050_ERROR_CALLBACK(DEVWRITELINE(M6522_TAG, via6522_device, write_cb1))
+ MCFG_FLOPPY_DRIVE_ADD(FDC_TAG ":0", sfd1001_floppies, "525qd", sfd1001_t::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor sfd1001_t::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( sfd1001 );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( c8050 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( c8050 )
+ PORT_START("ADDRESS")
+ PORT_DIPNAME( 0x07, 0x00, "Device Address" )
+ PORT_DIPSETTING( 0x00, "8" )
+ PORT_DIPSETTING( 0x01, "9" )
+ PORT_DIPSETTING( 0x02, "10" )
+ PORT_DIPSETTING( 0x03, "11" )
+ PORT_DIPSETTING( 0x04, "12" )
+ PORT_DIPSETTING( 0x05, "13" )
+ PORT_DIPSETTING( 0x06, "14" )
+ PORT_DIPSETTING( 0x07, "15" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor c8050_t::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( c8050 );
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// update_ieee_signals -
+//-------------------------------------------------
+
+inline void c8050_t::update_ieee_signals()
+{
+ int atn = m_bus->atn_r();
+ int nrfd = !(!(!(atn && m_atna) && m_rfdo) || !(atn || m_atna));
+ int ndac = !(m_daco || !(atn || m_atna));
+
+ m_bus->nrfd_w(this, nrfd);
+ m_bus->ndac_w(this, ndac);
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c8050_t - constructor
+//-------------------------------------------------
+
+c8050_t::c8050_t(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_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, M6502_TAG),
+ m_fdccpu(*this, M6504_TAG),
+ m_riot0(*this, M6532_0_TAG),
+ m_riot1(*this, M6532_1_TAG),
+ m_miot(*this, M6530_TAG),
+ m_via(*this, M6522_TAG),
+ m_floppy0(*this, FDC_TAG ":0"),
+ m_floppy1(*this, FDC_TAG ":1"),
+ m_fdc(*this, FDC_TAG),
+ m_address(*this, "ADDRESS"),
+ m_rfdo(1),
+ m_daco(1),
+ m_atna(1)
+{
+}
+
+c8050_t::c8050_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, C8050, "C8050", tag, owner, clock, "c8050", __FILE__),
+ device_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, M6502_TAG),
+ m_fdccpu(*this, M6504_TAG),
+ m_riot0(*this, M6532_0_TAG),
+ m_riot1(*this, M6532_1_TAG),
+ m_miot(*this, M6530_TAG),
+ m_via(*this, M6522_TAG),
+ m_floppy0(*this, FDC_TAG ":0"),
+ m_floppy1(*this, FDC_TAG ":1"),
+ m_fdc(*this, FDC_TAG),
+ m_address(*this, "ADDRESS"),
+ m_rfdo(1),
+ m_daco(1),
+ m_atna(1)
+{
+}
+
+
+//-------------------------------------------------
+// c8250_t - constructor
+//-------------------------------------------------
+
+c8250_t::c8250_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ c8050_t(mconfig, C8250, "C8250", tag, owner, clock, "c8250", __FILE__) { }
+
+
+//-------------------------------------------------
+// c8250lp_t - constructor
+//-------------------------------------------------
+
+c8250lp_t::c8250lp_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ c8050_t(mconfig, C8250LP, "C8250LP", tag, owner, clock, "c8250lp", __FILE__) { }
+
+
+//-------------------------------------------------
+// sfd1001_t - constructor
+//-------------------------------------------------
+
+sfd1001_t::sfd1001_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ c8050_t(mconfig, SFD1001, "SFD1001", tag, owner, clock, "sfd1001", __FILE__) { }
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void c8050_t::device_start()
+{
+ // install image callbacks
+ m_fdc->set_floppy(m_floppy0, m_floppy1);
+
+ // register for state saving
+ save_item(NAME(m_rfdo));
+ save_item(NAME(m_daco));
+ save_item(NAME(m_atna));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void c8050_t::device_reset()
+{
+ m_maincpu->reset();
+
+ // toggle M6502 SO
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, ASSERT_LINE);
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, CLEAR_LINE);
+
+ m_fdccpu->reset();
+
+ m_riot0->reset();
+ m_riot1->reset();
+ m_miot->reset();
+ m_via->reset();
+
+ m_riot1->pa7_w(1);
+
+ // turn off spindle motors
+ m_fdc->mtr0_w(1);
+ m_fdc->mtr1_w(1);
+}
+
+
+//-------------------------------------------------
+// ieee488_atn -
+//-------------------------------------------------
+
+void c8050_t::ieee488_atn(int state)
+{
+ update_ieee_signals();
+
+ m_riot1->pa7_w(state);
+}
+
+
+//-------------------------------------------------
+// ieee488_ifc -
+//-------------------------------------------------
+
+void c8050_t::ieee488_ifc(int state)
+{
+ if (!m_ifc && state)
+ {
+ device_reset();
+ }
+
+ m_ifc = state;
+}
diff --git a/src/devices/bus/ieee488/c8050.h b/src/devices/bus/ieee488/c8050.h
new file mode 100644
index 00000000000..3d5904dd6cb
--- /dev/null
+++ b/src/devices/bus/ieee488/c8050.h
@@ -0,0 +1,140 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 8050/8250/SFD-1001 Disk Drive emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __C8050__
+#define __C8050__
+
+#include "emu.h"
+#include "ieee488.h"
+#include "c8050fdc.h"
+#include "cpu/m6502/m6502.h"
+#include "cpu/m6502/m6504.h"
+#include "machine/6522via.h"
+#include "machine/mos6530n.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> c8050_t
+
+class c8050_t : public device_t,
+ public device_ieee488_interface
+{
+public:
+ // construction/destruction
+ c8050_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ c8050_t(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;
+
+ DECLARE_READ8_MEMBER( dio_r );
+ DECLARE_WRITE8_MEMBER( dio_w );
+ DECLARE_READ8_MEMBER( riot1_pa_r );
+ DECLARE_WRITE8_MEMBER( riot1_pa_w );
+ DECLARE_READ8_MEMBER( riot1_pb_r );
+ DECLARE_WRITE8_MEMBER( riot1_pb_w );
+ DECLARE_WRITE8_MEMBER( via_pb_w );
+ DECLARE_READ8_MEMBER( pi_r );
+ DECLARE_WRITE8_MEMBER( pi_w );
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_ieee488_interface overrides
+ virtual void ieee488_atn(int state);
+ virtual void ieee488_ifc(int state);
+
+ inline void update_ieee_signals();
+
+ required_device<m6502_device> m_maincpu;
+ required_device<m6504_device> m_fdccpu;
+ required_device<mos6532_t> m_riot0;
+ required_device<mos6532_t> m_riot1;
+ required_device<mos6530_t> m_miot;
+ required_device<via6522_device> m_via;
+ required_device<floppy_connector> m_floppy0;
+ optional_device<floppy_connector> m_floppy1;
+ required_device<c8050_fdc_t> m_fdc;
+ required_ioport m_address;
+
+ // IEEE-488 bus
+ int m_rfdo; // not ready for data output
+ int m_daco; // not data accepted output
+ int m_atna; // attention acknowledge
+ int m_ifc;
+};
+
+
+// ======================> c8250_t
+
+class c8250_t : public c8050_t
+{
+public:
+ // construction/destruction
+ c8250_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+};
+
+
+// ======================> c8250lp_t
+
+class c8250lp_t : public c8050_t
+{
+public:
+ // construction/destruction
+ c8250lp_t(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;
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+};
+
+
+// ======================> sfd1001_t
+
+class sfd1001_t : public c8050_t
+{
+public:
+ // construction/destruction
+ sfd1001_t(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;
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+};
+
+
+// device type definition
+extern const device_type C8050;
+extern const device_type C8250;
+extern const device_type C8250LP;
+extern const device_type SFD1001;
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/c8050fdc.c b/src/devices/bus/ieee488/c8050fdc.c
new file mode 100644
index 00000000000..02bceb80328
--- /dev/null
+++ b/src/devices/bus/ieee488/c8050fdc.c
@@ -0,0 +1,634 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 8050 floppy disk controller emulation
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - write protect
+ - 75,format speed error,01,00,0
+
+*/
+
+#include "c8050fdc.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+#define LOG_MORE 0
+#define LOG_BITS 0
+
+#define GCR_DECODE(_e, _i) \
+ ((BIT(_e, 6) << 7) | (BIT(_i, 7) << 6) | (_e & 0x33) | (BIT(_e, 2) << 3) | (_i & 0x04))
+
+#define GCR_ENCODE(_e, _i) \
+ ((_e & 0xc0) << 2 | (_i & 0x80) | (_e & 0x3c) << 1 | (_i & 0x04) | (_e & 0x03))
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type C8050_FDC = &device_creator<c8050_fdc_t>;
+
+
+//-------------------------------------------------
+// ROM( c8050_fdc )
+//-------------------------------------------------
+
+ROM_START( c8050_fdc )
+ ROM_REGION( 0x800, "gcr", 0)
+ ROM_LOAD( "901467.uk6", 0x000, 0x800, CRC(a23337eb) SHA1(97df576397608455616331f8e837cb3404363fa2) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c8050_fdc_t::device_rom_region() const
+{
+ return ROM_NAME( c8050_fdc );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c8050_fdc_t - constructor
+//-------------------------------------------------
+
+c8050_fdc_t::c8050_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, C8050_FDC, "Commodore 8050 FDC", tag, owner, clock, "c8050fdc", __FILE__),
+ m_write_sync(*this),
+ m_write_ready(*this),
+ m_write_brdy(*this),
+ m_write_error(*this),
+ m_gcr_rom(*this, "gcr"),
+ m_floppy0(NULL),
+ m_floppy1(NULL),
+ m_mtr0(1),
+ m_mtr1(1),
+ m_stp0(0),
+ m_stp1(0),
+ m_ds(0),
+ m_ds0(0),
+ m_ds1(0),
+ m_drv_sel(0),
+ m_mode_sel(0),
+ m_rw_sel(1)
+{
+ cur_live.tm = attotime::never;
+ cur_live.state = IDLE;
+ cur_live.next_state = -1;
+ cur_live.drv_sel = m_drv_sel;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void c8050_fdc_t::device_start()
+{
+ // resolve callbacks
+ m_write_sync.resolve_safe();
+ m_write_ready.resolve_safe();
+ m_write_brdy.resolve_safe();
+ m_write_error.resolve_safe();
+
+ // allocate timer
+ t_gen = timer_alloc(0);
+
+ // register for state saving
+ save_item(NAME(m_mtr0));
+ save_item(NAME(m_mtr1));
+ save_item(NAME(m_stp0));
+ save_item(NAME(m_stp1));
+ save_item(NAME(m_ds));
+ save_item(NAME(m_ds0));
+ save_item(NAME(m_ds1));
+ save_item(NAME(m_drv_sel));
+ save_item(NAME(m_mode_sel));
+ save_item(NAME(m_rw_sel));
+ save_item(NAME(m_odd_hd));
+ save_item(NAME(m_pi));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void c8050_fdc_t::device_reset()
+{
+ live_abort();
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void c8050_fdc_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ live_sync();
+ live_run();
+}
+
+floppy_image_device* c8050_fdc_t::get_floppy()
+{
+ return cur_live.drv_sel ? m_floppy1 : m_floppy0;
+}
+
+void c8050_fdc_t::stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp)
+{
+ if (mtr) return;
+
+ int tracks = 0;
+
+ switch (old_stp)
+ {
+ case 0: if (stp == 1) tracks++; else if (stp == 2) tracks--; break;
+ case 1: if (stp == 3) tracks++; else if (stp == 0) tracks--; break;
+ case 2: if (stp == 0) tracks++; else if (stp == 3) tracks--; break;
+ case 3: if (stp == 2) tracks++; else if (stp == 1) tracks--; break;
+ }
+
+ if (tracks == -1)
+ {
+ floppy->dir_w(1);
+ floppy->stp_w(1);
+ floppy->stp_w(0);
+ }
+ else if (tracks == 1)
+ {
+ floppy->dir_w(0);
+ floppy->stp_w(1);
+ floppy->stp_w(0);
+ }
+
+ old_stp = stp;
+}
+
+void c8050_fdc_t::stp0_w(int stp)
+{
+ if (m_stp0 != stp)
+ {
+ live_sync();
+ stp_w(m_floppy0, m_mtr0, m_stp0, stp);
+ checkpoint();
+ live_run();
+ }
+}
+
+void c8050_fdc_t::stp1_w(int stp)
+{
+ if (m_stp1 != stp)
+ {
+ live_sync();
+ if (m_floppy1) stp_w(m_floppy1, m_mtr1, m_stp1, stp);
+ checkpoint();
+ live_run();
+ }
+}
+
+void c8050_fdc_t::ds_w(int ds)
+{
+ if (m_ds != ds)
+ {
+ live_sync();
+ m_ds = cur_live.ds = ds;
+ pll_reset(cur_live.tm);
+ if (LOG) logerror("%s %s DS %u\n", machine().time().as_string(), machine().describe_context(), ds);
+ checkpoint();
+ live_run();
+ }
+}
+
+void c8050_fdc_t::set_floppy(floppy_connector *floppy0, floppy_connector *floppy1)
+{
+ m_floppy0 = floppy0->get_device();
+
+ if (floppy1) {
+ m_floppy1 = floppy1->get_device();
+ }
+}
+
+void c8050_fdc_t::live_start()
+{
+ cur_live.tm = machine().time();
+ cur_live.state = RUNNING;
+ cur_live.next_state = -1;
+
+ cur_live.shift_reg = 0;
+ cur_live.shift_reg_write = 0;
+ cur_live.bit_counter = 0;
+ cur_live.ds = m_ds;
+ cur_live.drv_sel = m_drv_sel;
+ cur_live.mode_sel = m_mode_sel;
+ cur_live.rw_sel = m_rw_sel;
+ cur_live.pi = m_pi;
+
+ pll_reset(cur_live.tm);
+ checkpoint_live = cur_live;
+ pll_save_checkpoint();
+
+ live_run();
+}
+
+void c8050_fdc_t::pll_reset(const attotime &when)
+{
+ cur_pll.reset(when);
+ cur_pll.set_clock(attotime::from_hz(clock() / (16 - m_ds)));
+}
+
+void c8050_fdc_t::pll_start_writing(const attotime &tm)
+{
+ cur_pll.start_writing(tm);
+ pll_reset(cur_live.tm);
+}
+
+void c8050_fdc_t::pll_commit(floppy_image_device *floppy, const attotime &tm)
+{
+ cur_pll.commit(floppy, tm);
+}
+
+void c8050_fdc_t::pll_stop_writing(floppy_image_device *floppy, const attotime &tm)
+{
+ cur_pll.stop_writing(floppy, tm);
+ pll_reset(cur_live.tm);
+}
+
+void c8050_fdc_t::pll_save_checkpoint()
+{
+ checkpoint_pll = cur_pll;
+}
+
+void c8050_fdc_t::pll_retrieve_checkpoint()
+{
+ cur_pll = checkpoint_pll;
+}
+
+int c8050_fdc_t::pll_get_next_bit(attotime &tm, floppy_image_device *floppy, const attotime &limit)
+{
+ return cur_pll.get_next_bit(tm, floppy, limit);
+}
+
+bool c8050_fdc_t::pll_write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit)
+{
+ return cur_pll.write_next_bit(bit, tm, floppy, limit);
+}
+
+void c8050_fdc_t::checkpoint()
+{
+ pll_commit(get_floppy(), cur_live.tm);
+ checkpoint_live = cur_live;
+ pll_save_checkpoint();
+}
+
+void c8050_fdc_t::rollback()
+{
+ cur_live = checkpoint_live;
+ pll_retrieve_checkpoint();
+}
+
+void c8050_fdc_t::live_delay(int state)
+{
+ cur_live.next_state = state;
+ if(cur_live.tm != machine().time())
+ t_gen->adjust(cur_live.tm - machine().time());
+ else
+ live_sync();
+}
+
+void c8050_fdc_t::live_sync()
+{
+ if(!cur_live.tm.is_never()) {
+ if(cur_live.tm > machine().time()) {
+ rollback();
+ live_run(machine().time());
+ pll_commit(get_floppy(), cur_live.tm);
+ } else {
+ pll_commit(get_floppy(), cur_live.tm);
+ if(cur_live.next_state != -1) {
+ cur_live.state = cur_live.next_state;
+ cur_live.next_state = -1;
+ }
+ if(cur_live.state == IDLE) {
+ pll_stop_writing(get_floppy(), cur_live.tm);
+ cur_live.tm = attotime::never;
+ }
+ }
+ cur_live.next_state = -1;
+ checkpoint();
+ }
+}
+
+void c8050_fdc_t::live_abort()
+{
+ if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) {
+ rollback();
+ live_run(machine().time());
+ }
+
+ pll_stop_writing(get_floppy(), cur_live.tm);
+
+ cur_live.tm = attotime::never;
+ cur_live.state = IDLE;
+ cur_live.next_state = -1;
+
+ cur_live.ready = 1;
+ cur_live.brdy = 1;
+ cur_live.sync = 1;
+ cur_live.error = 1;
+}
+
+void c8050_fdc_t::live_run(const attotime &limit)
+{
+ if(cur_live.state == IDLE || cur_live.next_state != -1)
+ return;
+
+ for(;;) {
+ switch(cur_live.state) {
+ case RUNNING: {
+ bool syncpoint = false;
+
+ if (cur_live.tm > limit)
+ return;
+
+ // read bit
+ int bit = 0;
+ if (cur_live.rw_sel) {
+ bit = pll_get_next_bit(cur_live.tm, get_floppy(), limit);
+ if(bit < 0)
+ return;
+ }
+
+ // write bit
+ int write_bit = BIT(cur_live.shift_reg_write, 9);
+ if (!cur_live.rw_sel) { // TODO WPS
+ /*
+ write precompensation
+
+ UA5.A = UM6.Qc
+ UA5.B = !(!(!BRDY && UM6.Qa) && !(BRDY && E7))
+ UA5.C0 = UA4.Qb = bit clock delayed 333ns
+ UA5.C1 = UA4.Qa = bit clock delayed 166ns
+ UA5.C2 = UA4.Qc = bit clock delayed 499ns
+ UA5.C3 = UA5.Qb = bit clock delayed 333ns
+
+ DATA OUT = !(!BITCLK || !(UA5.Y && !(WRITE_ENABLE && !UM6.Qb)))
+ */
+ if (pll_write_next_bit(write_bit, cur_live.tm, get_floppy(), limit))
+ return;
+ }
+
+ // clock read shift register
+ cur_live.shift_reg <<= 1;
+ cur_live.shift_reg |= bit;
+ cur_live.shift_reg &= 0x3ff;
+
+ // sync
+ int sync = !((cur_live.shift_reg == 0x3ff) && cur_live.rw_sel);
+
+ // bit counter
+ if (!sync) {
+ cur_live.bit_counter = 0;
+ } else if (cur_live.sync) {
+ cur_live.bit_counter++;
+ if (cur_live.bit_counter == 10) {
+ cur_live.bit_counter = 0;
+ }
+ }
+
+ // GCR decoder
+ if (cur_live.rw_sel) {
+ cur_live.i = (cur_live.rw_sel << 10) | cur_live.shift_reg;
+ } else {
+ cur_live.i = (cur_live.rw_sel << 10) | ((cur_live.pi & 0xf0) << 1) | (cur_live.mode_sel << 4) | (cur_live.pi & 0x0f);
+ }
+
+ cur_live.e = m_gcr_rom->base()[cur_live.i];
+
+ // byte ready
+ int ready = !(cur_live.bit_counter == 9); // 74190 _RC, should be triggered on the falling edge of the clock
+ int brdy = ready; // 74190 TC
+
+ // GCR error
+ int error = !(ready || BIT(cur_live.e, 3));
+
+ if (LOG_BITS) {
+ if (cur_live.rw_sel) {
+ logerror("%s cyl %u bit %u sync %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),bit,sync,cur_live.bit_counter,cur_live.shift_reg,cur_live.i,cur_live.e);
+ } else {
+ logerror("%s cyl %u writing bit %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),write_bit,cur_live.bit_counter,cur_live.shift_reg_write,cur_live.i,cur_live.e);
+ }
+ }
+
+ if (!ready) {
+ // load write shift register
+ cur_live.shift_reg_write = GCR_ENCODE(cur_live.e, cur_live.i);
+
+ if (LOG_BITS) logerror("%s load write shift register %03x\n",cur_live.tm.as_string(),cur_live.shift_reg_write);
+ } else {
+ // clock write shift register
+ cur_live.shift_reg_write <<= 1;
+ cur_live.shift_reg_write &= 0x3ff;
+ }
+
+ if (ready != cur_live.ready) {
+ if (cur_live.rw_sel && !ready)
+ if (LOG) logerror("%s READY %u : %02x\n", cur_live.tm.as_string(),ready,GCR_DECODE(cur_live.e, cur_live.i));
+ cur_live.ready = ready;
+ syncpoint = true;
+ }
+
+ if (brdy != cur_live.brdy) {
+ if (LOG_MORE) logerror("%s BRDY %u\n", cur_live.tm.as_string(), brdy);
+ cur_live.brdy = brdy;
+ syncpoint = true;
+ }
+
+ if (sync != cur_live.sync) {
+ if (LOG) logerror("%s SYNC %u\n", cur_live.tm.as_string(), sync);
+ cur_live.sync = sync;
+ syncpoint = true;
+ }
+
+ if (error != cur_live.error) {
+ if (LOG_MORE) logerror("%s ERROR %u\n", cur_live.tm.as_string(), error);
+ cur_live.error = error;
+ syncpoint = true;
+ }
+
+ if (syncpoint) {
+ live_delay(RUNNING_SYNCPOINT);
+ return;
+ }
+ break;
+ }
+
+ case RUNNING_SYNCPOINT: {
+ m_write_ready(cur_live.ready);
+ m_write_brdy(cur_live.brdy);
+ m_write_sync(cur_live.sync);
+ m_write_error(cur_live.error);
+
+ cur_live.state = RUNNING;
+ checkpoint();
+ break;
+ }
+ }
+ }
+}
+
+READ8_MEMBER( c8050_fdc_t::read )
+{
+ UINT8 e = checkpoint_live.e;
+ offs_t i = checkpoint_live.i;
+
+ return GCR_DECODE(e, i);
+}
+
+WRITE8_MEMBER( c8050_fdc_t::write )
+{
+ if (LOG) logerror("%s %s PI %02x\n", machine().time().as_string(), machine().describe_context(), data);
+
+ if (m_pi != data)
+ {
+ live_sync();
+ m_pi = cur_live.pi = data;
+ checkpoint();
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c8050_fdc_t::ds0_w )
+{
+ m_ds0 = state;
+}
+
+WRITE_LINE_MEMBER( c8050_fdc_t::ds1_w )
+{
+ m_ds1 = state;
+
+ ds_w(m_ds1 << 1 | m_ds0);
+}
+
+WRITE_LINE_MEMBER( c8050_fdc_t::drv_sel_w )
+{
+ if (m_drv_sel != state)
+ {
+ live_sync();
+ m_drv_sel = cur_live.drv_sel = state;
+ checkpoint();
+ if (LOG) logerror("%s %s DRV SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c8050_fdc_t::mode_sel_w )
+{
+ if (m_mode_sel != state)
+ {
+ live_sync();
+ m_mode_sel = cur_live.mode_sel = state;
+ checkpoint();
+ if (LOG) logerror("%s %s MODE SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c8050_fdc_t::rw_sel_w )
+{
+ if (m_rw_sel != state)
+ {
+ live_sync();
+ m_rw_sel = cur_live.rw_sel = state;
+ checkpoint();
+ if (LOG) logerror("%s %s RW SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
+ if (m_rw_sel) {
+ pll_stop_writing(get_floppy(), cur_live.tm);
+ } else {
+ pll_start_writing(cur_live.tm);
+ }
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c8050_fdc_t::mtr0_w )
+{
+ if (m_mtr0 != state)
+ {
+ live_sync();
+ m_mtr0 = state;
+ if (LOG) logerror("%s %s MTR0 %u\n", machine().time().as_string(), machine().describe_context(), state);
+ m_floppy0->mon_w(state);
+ checkpoint();
+
+ if (!m_mtr0 || !m_mtr1) {
+ if(cur_live.state == IDLE) {
+ live_start();
+ }
+ } else {
+ live_abort();
+ }
+
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c8050_fdc_t::mtr1_w )
+{
+ if (m_mtr1 != state)
+ {
+ live_sync();
+ m_mtr1 = state;
+ if (LOG) logerror("%s %s MTR1 %u\n", machine().time().as_string(), machine().describe_context(), state);
+ if (m_floppy1) m_floppy1->mon_w(state);
+ checkpoint();
+
+ if (!m_mtr0 || !m_mtr1) {
+ if(cur_live.state == IDLE) {
+ live_start();
+ }
+ } else {
+ live_abort();
+ }
+
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c8050_fdc_t::odd_hd_w )
+{
+ if (m_odd_hd != state)
+ {
+ live_sync();
+ m_odd_hd = cur_live.odd_hd = state;
+ if (LOG) logerror("%s %s ODD HD %u\n", machine().time().as_string(), machine().describe_context(), state);
+ m_floppy0->ss_w(!state);
+ if (m_floppy1) m_floppy1->ss_w(!state);
+ checkpoint();
+ live_run();
+ }
+}
+
+WRITE_LINE_MEMBER( c8050_fdc_t::pull_sync_w )
+{
+ if (LOG_MORE) logerror("%s %s PULL SYNC %u\n", machine().time().as_string(), machine().describe_context(), state);
+}
diff --git a/src/devices/bus/ieee488/c8050fdc.h b/src/devices/bus/ieee488/c8050fdc.h
new file mode 100644
index 00000000000..8228c9660d0
--- /dev/null
+++ b/src/devices/bus/ieee488/c8050fdc.h
@@ -0,0 +1,170 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 8050 floppy disk controller emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __C8050_FLOPPY__
+#define __C8050_FLOPPY__
+
+#include "emu.h"
+#include "formats/d80_dsk.h"
+#include "formats/d82_dsk.h"
+#include "imagedev/floppy.h"
+#include "machine/fdc_pll.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_C8050_SYNC_CALLBACK(_write) \
+ devcb = &c8050_fdc_t::set_sync_wr_callback(*device, DEVCB_##_write);
+
+#define MCFG_C8050_READY_CALLBACK(_write) \
+ devcb = &c8050_fdc_t::set_ready_wr_callback(*device, DEVCB_##_write);
+
+#define MCFG_C8050_BRDY_CALLBACK(_write) \
+ devcb = &c8050_fdc_t::set_brdy_wr_callback(*device, DEVCB_##_write);
+
+#define MCFG_C8050_ERROR_CALLBACK(_write) \
+ devcb = &c8050_fdc_t::set_error_wr_callback(*device, DEVCB_##_write);
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> c8050_fdc_t
+
+class c8050_fdc_t : public device_t
+{
+public:
+ // construction/destruction
+ c8050_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ template<class _Object> static devcb_base &set_sync_wr_callback(device_t &device, _Object object) { return downcast<c8050_fdc_t &>(device).m_write_sync.set_callback(object); }
+ template<class _Object> static devcb_base &set_ready_wr_callback(device_t &device, _Object object) { return downcast<c8050_fdc_t &>(device).m_write_ready.set_callback(object); }
+ template<class _Object> static devcb_base &set_brdy_wr_callback(device_t &device, _Object object) { return downcast<c8050_fdc_t &>(device).m_write_brdy.set_callback(object); }
+ template<class _Object> static devcb_base &set_error_wr_callback(device_t &device, _Object object) { return downcast<c8050_fdc_t &>(device).m_write_error.set_callback(object); }
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ DECLARE_WRITE_LINE_MEMBER( ds0_w );
+ DECLARE_WRITE_LINE_MEMBER( ds1_w );
+ DECLARE_WRITE_LINE_MEMBER( drv_sel_w );
+ DECLARE_WRITE_LINE_MEMBER( mode_sel_w );
+ DECLARE_WRITE_LINE_MEMBER( rw_sel_w );
+ DECLARE_WRITE_LINE_MEMBER( mtr0_w );
+ DECLARE_WRITE_LINE_MEMBER( mtr1_w );
+ DECLARE_WRITE_LINE_MEMBER( odd_hd_w );
+ DECLARE_WRITE_LINE_MEMBER( pull_sync_w );
+
+ DECLARE_READ_LINE_MEMBER( wps_r ) { return checkpoint_live.drv_sel ? m_floppy1->wpt_r() : m_floppy0->wpt_r(); }
+
+ void stp0_w(int stp);
+ void stp1_w(int stp);
+ void ds_w(int ds);
+
+ void set_floppy(floppy_connector *floppy0, floppy_connector *floppy1);
+
+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);
+
+ // optional information overrides
+ virtual const rom_entry *device_rom_region() const;
+
+ void stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp);
+
+ enum {
+ IDLE,
+ RUNNING,
+ RUNNING_SYNCPOINT
+ };
+
+ struct live_info {
+ attotime tm;
+ int state, next_state;
+ int sync;
+ int ready;
+ int brdy;
+ int error;
+ int ds;
+ int drv_sel;
+ int mode_sel;
+ int rw_sel;
+ int odd_hd;
+
+ attotime edge;
+ UINT16 shift_reg;
+ int bit_counter;
+ UINT8 e;
+ offs_t i;
+
+ UINT8 pi;
+ UINT16 shift_reg_write;
+ };
+
+ devcb_write_line m_write_sync;
+ devcb_write_line m_write_ready;
+ devcb_write_line m_write_brdy;
+ devcb_write_line m_write_error;
+
+ required_memory_region m_gcr_rom;
+
+ floppy_image_device *m_floppy0;
+ floppy_image_device *m_floppy1;
+
+ int m_mtr0;
+ int m_mtr1;
+ int m_stp0;
+ int m_stp1;
+ int m_ds;
+ int m_ds0;
+ int m_ds1;
+ int m_drv_sel;
+ int m_mode_sel;
+ int m_rw_sel;
+ int m_odd_hd;
+ UINT8 m_pi;
+
+ live_info cur_live, checkpoint_live;
+ fdc_pll_t cur_pll, checkpoint_pll;
+ emu_timer *t_gen;
+
+ floppy_image_device* get_floppy();
+
+ void live_start();
+ void checkpoint();
+ void rollback();
+ void pll_reset(const attotime &when);
+ void pll_start_writing(const attotime &tm);
+ void pll_commit(floppy_image_device *floppy, const attotime &tm);
+ void pll_stop_writing(floppy_image_device *floppy, const attotime &tm);
+ int pll_get_next_bit(attotime &tm, floppy_image_device *floppy, const attotime &limit);
+ bool pll_write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit);
+ void pll_save_checkpoint();
+ void pll_retrieve_checkpoint();
+ void live_delay(int state);
+ void live_sync();
+ void live_abort();
+ void live_run(const attotime &limit = attotime::never);
+};
+
+
+// device type definition
+extern const device_type C8050_FDC;
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/c8280.c b/src/devices/bus/ieee488/c8280.c
new file mode 100644
index 00000000000..1dd1c679c5d
--- /dev/null
+++ b/src/devices/bus/ieee488/c8280.c
@@ -0,0 +1,527 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 8280 Dual 8" Disk Drive emulation
+
+**********************************************************************/
+
+#include "c8280.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define M6502_DOS_TAG "5c"
+#define M6502_FDC_TAG "9e"
+#define M6532_0_TAG "9f"
+#define M6532_1_TAG "9g"
+#define WD1797_TAG "5e"
+
+
+enum
+{
+ LED_POWER = 0,
+ LED_ACT0,
+ LED_ACT1,
+ LED_ERR
+};
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type C8280 = &device_creator<c8280_t>;
+
+
+//-------------------------------------------------
+// ROM( c8280 )
+//-------------------------------------------------
+
+ROM_START( c8280 )
+ ROM_REGION( 0x4000, M6502_DOS_TAG, 0 )
+ ROM_DEFAULT_BIOS("r2")
+ ROM_SYSTEM_BIOS( 0, "r1", "Revision 1" )
+ ROMX_LOAD( "300542-001.10c", 0x0000, 0x2000, CRC(3c6eee1e) SHA1(0726f6ab4de4fc9c18707fe87780ffd9f5ed72ab), ROM_BIOS(1) )
+ ROMX_LOAD( "300543-001.10d", 0x2000, 0x2000, CRC(f58e665e) SHA1(9e58b47c686c91efc6ef1a27f72dbb5e26c485ec), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "r2", "Revision 2" )
+ ROMX_LOAD( "300542-reva.10c", 0x0000, 0x2000, CRC(6f32ccfb) SHA1(6926c049f1635e6769ec69891de8c92941ff880e), ROM_BIOS(2) )
+ ROMX_LOAD( "300543-reva.10d", 0x2000, 0x2000, CRC(1af93f2c) SHA1(ad197b1d5dfa273487b33f473403ebd20dd15b2b), ROM_BIOS(2) )
+
+ ROM_REGION( 0x800, M6502_FDC_TAG, 0 )
+ ROMX_LOAD( "300541-001.3c", 0x000, 0x800, BAD_DUMP CRC(cb07b2db) SHA1(a1f9c5a7bd3798f5a97dc0b465c3bf5e3513e148), ROM_BIOS(1) )
+ ROMX_LOAD( "300541-revb.3c", 0x000, 0x800, CRC(403e632c) SHA1(a0994c80025240d2b49ffd209dbfe8a4de3975b0), ROM_BIOS(2) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *c8280_t::device_rom_region() const
+{
+ return ROM_NAME( c8280 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c8280_main_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c8280_main_mem, AS_PROGRAM, 8, c8280_t )
+ AM_RANGE(0x0000, 0x007f) AM_MIRROR(0x100) AM_DEVICE(M6532_0_TAG, mos6532_t, ram_map)
+ AM_RANGE(0x0080, 0x00ff) AM_MIRROR(0x100) AM_DEVICE(M6532_1_TAG, mos6532_t, ram_map)
+ AM_RANGE(0x0200, 0x021f) AM_MIRROR(0xd60) AM_DEVICE(M6532_0_TAG, mos6532_t, io_map)
+ AM_RANGE(0x0280, 0x029f) AM_MIRROR(0xd60) AM_DEVICE(M6532_1_TAG, mos6532_t, io_map)
+ AM_RANGE(0x1000, 0x13ff) AM_MIRROR(0xc00) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x2000, 0x23ff) AM_MIRROR(0xc00) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x3000, 0x33ff) AM_MIRROR(0xc00) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x4000, 0x43ff) AM_MIRROR(0xc00) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0xc000, 0xffff) AM_ROM AM_REGION(M6502_DOS_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( c8280_fdc_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( c8280_fdc_mem, AS_PROGRAM, 8, c8280_t )
+ ADDRESS_MAP_GLOBAL_MASK(0x1fff)
+ AM_RANGE(0x0000, 0x007f) AM_MIRROR(0x300) AM_RAM
+ AM_RANGE(0x0080, 0x0083) AM_MIRROR(0x37c) AM_DEVREADWRITE(WD1797_TAG, fd1797_t, read, write)
+ AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x1000, 0x13ff) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0x1400, 0x1400) AM_MIRROR(0x3ff) AM_READWRITE(fk5_r, fk5_w)
+ AM_RANGE(0x1800, 0x1fff) AM_ROM AM_REGION(M6502_FDC_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// riot6532 0
+//-------------------------------------------------
+
+READ8_MEMBER( c8280_t::dio_r )
+{
+ /*
+
+ bit description
+
+ PA0 DI0
+ PA1 DI1
+ PA2 DI2
+ PA3 DI3
+ PA4 DI4
+ PA5 DI5
+ PA6 DI6
+ PA7 DI7
+
+ */
+
+ return m_bus->dio_r();
+}
+
+WRITE8_MEMBER( c8280_t::dio_w )
+{
+ /*
+
+ bit description
+
+ PB0 DO0
+ PB1 DO1
+ PB2 DO2
+ PB3 DO3
+ PB4 DO4
+ PB5 DO5
+ PB6 DO6
+ PB7 DO7
+
+ */
+
+ m_bus->dio_w(this, data);
+}
+
+
+//-------------------------------------------------
+// riot6532 1
+//-------------------------------------------------
+
+READ8_MEMBER( c8280_t::riot1_pa_r )
+{
+ /*
+
+ bit description
+
+ PA0
+ PA1
+ PA2
+ PA3
+ PA4
+ PA5 EOII
+ PA6 DAVI
+ PA7 _ATN
+
+ */
+
+ UINT8 data = 0;
+
+ // end or identify in
+ data |= m_bus->eoi_r() << 5;
+
+ // data valid in
+ data |= m_bus->dav_r() << 6;
+
+ // attention
+ data |= !m_bus->atn_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c8280_t::riot1_pa_w )
+{
+ /*
+
+ bit description
+
+ PA0 ATNA
+ PA1 DACO
+ PA2 RFDO
+ PA3 EOIO
+ PA4 DAVO
+ PA5
+ PA6
+ PA7
+
+ */
+
+ // attention acknowledge
+ m_atna = BIT(data, 0);
+
+ // data accepted out
+ m_daco = BIT(data, 1);
+
+ // not ready for data out
+ m_rfdo = BIT(data, 2);
+
+ // end or identify out
+ m_bus->eoi_w(this, BIT(data, 3));
+
+ // data valid out
+ m_bus->dav_w(this, BIT(data, 4));
+
+ update_ieee_signals();
+}
+
+READ8_MEMBER( c8280_t::riot1_pb_r )
+{
+ /*
+
+ bit description
+
+ PB0 DEVICE NUMBER SELECTION
+ PB1 DEVICE NUMBER SELECTION
+ PB2 DEVICE NUMBER SELECTION
+ PB3
+ PB4
+ PB5
+ PB6 DACI
+ PB7 RFDI
+
+ */
+
+ UINT8 data = 0;
+
+ // device number selection
+ data |= m_slot->get_address() - 8;
+
+ // data accepted in
+ data |= m_bus->ndac_r() << 6;
+
+ // ready for data in
+ data |= m_bus->nrfd_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( c8280_t::riot1_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0
+ PB1
+ PB2
+ PB3 ACT LED 1
+ PB4 ACT LED 0
+ PB5 ERR LED
+ PB6
+ PB7
+
+ */
+
+ // activity led 1
+ output_set_led_value(LED_ACT1, BIT(data, 3));
+
+ // activity led 0
+ output_set_led_value(LED_ACT0, BIT(data, 4));
+
+ // error led
+ output_set_led_value(LED_ERR, BIT(data, 5));
+}
+
+static SLOT_INTERFACE_START( c8280_floppies )
+ SLOT_INTERFACE( "8dsdd", FLOPPY_8_DSDD )
+SLOT_INTERFACE_END
+
+FLOPPY_FORMATS_MEMBER( c8280_t::floppy_formats )
+ FLOPPY_C8280_FORMAT
+FLOPPY_FORMATS_END
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( c8280 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( c8280 )
+ MCFG_CPU_ADD(M6502_DOS_TAG, M6502, XTAL_12MHz/8)
+ MCFG_CPU_PROGRAM_MAP(c8280_main_mem)
+
+ MCFG_DEVICE_ADD(M6532_0_TAG, MOS6532n, XTAL_12MHz/8)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8280_t, dio_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8280_t, dio_w))
+
+ MCFG_DEVICE_ADD(M6532_1_TAG, MOS6532n, XTAL_12MHz/8)
+ MCFG_MOS6530n_IN_PA_CB(READ8(c8280_t, riot1_pa_r))
+ MCFG_MOS6530n_OUT_PA_CB(WRITE8(c8280_t, riot1_pa_w))
+ MCFG_MOS6530n_IN_PB_CB(READ8(c8280_t, riot1_pb_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(c8280_t, riot1_pb_w))
+ MCFG_MOS6530n_IRQ_CB(INPUTLINE(M6502_DOS_TAG, INPUT_LINE_IRQ0))
+
+ MCFG_CPU_ADD(M6502_FDC_TAG, M6502, XTAL_12MHz/8)
+ MCFG_CPU_PROGRAM_MAP(c8280_fdc_mem)
+
+ MCFG_FD1797_ADD(WD1797_TAG, XTAL_12MHz/6)
+ MCFG_WD_FDC_INTRQ_CALLBACK(INPUTLINE(M6502_FDC_TAG, M6502_IRQ_LINE))
+ MCFG_WD_FDC_DRQ_CALLBACK(INPUTLINE(M6502_FDC_TAG, M6502_SET_OVERFLOW))
+ MCFG_FLOPPY_DRIVE_ADD(WD1797_TAG ":0", c8280_floppies, "8dsdd", c8280_t::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(WD1797_TAG ":1", c8280_floppies, "8dsdd", c8280_t::floppy_formats)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor c8280_t::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( c8280 );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( c8280 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( c8280 )
+ PORT_START("ADDRESS")
+ PORT_DIPNAME( 0x07, 0x00, "Device Address" )
+ PORT_DIPSETTING( 0x00, "8" )
+ PORT_DIPSETTING( 0x01, "9" )
+ PORT_DIPSETTING( 0x02, "10" )
+ PORT_DIPSETTING( 0x03, "11" )
+ PORT_DIPSETTING( 0x04, "12" )
+ PORT_DIPSETTING( 0x05, "13" )
+ PORT_DIPSETTING( 0x06, "14" )
+ PORT_DIPSETTING( 0x07, "15" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor c8280_t::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( c8280 );
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// update_ieee_signals -
+//-------------------------------------------------
+
+inline void c8280_t::update_ieee_signals()
+{
+ int atn = m_bus->atn_r();
+ int nrfd = !(!(!(atn && m_atna) && m_rfdo) || !(atn || m_atna));
+ int ndac = !(m_daco || !(atn || m_atna));
+
+ m_bus->nrfd_w(this, nrfd);
+ m_bus->ndac_w(this, ndac);
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c8280_t - constructor
+//-------------------------------------------------
+
+c8280_t::c8280_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, C8280, "C8280", tag, owner, clock, "c8280", __FILE__),
+ device_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, M6502_DOS_TAG),
+ m_fdccpu(*this, M6502_FDC_TAG),
+ m_riot0(*this, M6532_0_TAG),
+ m_riot1(*this, M6532_1_TAG),
+ m_fdc(*this, WD1797_TAG),
+ m_floppy0(*this, WD1797_TAG ":0"),
+ m_floppy1(*this, WD1797_TAG ":1"),
+ m_address(*this, "ADDRESS"),
+ m_rfdo(1),
+ m_daco(1),
+ m_atna(1)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void c8280_t::device_start()
+{
+ // state saving
+ save_item(NAME(m_rfdo));
+ save_item(NAME(m_daco));
+ save_item(NAME(m_atna));
+ save_item(NAME(m_ifc));
+ save_item(NAME(m_fk5));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void c8280_t::device_reset()
+{
+ m_maincpu->reset();
+
+ // toggle M6502 SO
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, ASSERT_LINE);
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, CLEAR_LINE);
+
+ m_fdccpu->reset();
+
+ m_riot0->reset();
+ m_riot1->reset();
+ m_fdc->reset();
+
+ m_riot1->pa7_w(1);
+
+ m_fk5 = 0;
+ m_floppy = NULL;
+ m_fdc->set_floppy(m_floppy);
+ m_fdc->dden_w(0);
+}
+
+
+//-------------------------------------------------
+// ieee488_atn -
+//-------------------------------------------------
+
+void c8280_t::ieee488_atn(int state)
+{
+ update_ieee_signals();
+
+ m_riot1->pa7_w(state);
+}
+
+
+//-------------------------------------------------
+// ieee488_ifc -
+//-------------------------------------------------
+
+void c8280_t::ieee488_ifc(int state)
+{
+ if (!m_ifc && state)
+ {
+ device_reset();
+ }
+
+ m_ifc = state;
+}
+
+READ8_MEMBER( c8280_t::fk5_r )
+{
+ /*
+
+ bit description
+
+ 0
+ 1
+ 2
+ 3 DCHG
+ 4 TSID
+ 5
+ 6 0
+ 7 0
+
+ */
+
+ UINT8 data = m_fk5;
+
+ data |= (m_floppy ? m_floppy->dskchg_r() : 1) << 3;
+ data |= (m_floppy ? m_floppy->twosid_r() : 1) << 4;
+
+ return data;
+}
+
+WRITE8_MEMBER( c8280_t::fk5_w )
+{
+ /*
+
+ bit description
+
+ 0 DS1
+ 1 DS2
+ 2 _DDEN
+ 3
+ 4
+ 5 MOTOR ENABLE
+ 6
+ 7
+
+ */
+
+ m_fk5 = data & 0x27;
+
+ // drive select
+ m_floppy = NULL;
+
+ if (BIT(data, 0)) m_floppy = m_floppy0->get_device();
+ if (BIT(data, 1)) m_floppy = m_floppy1->get_device();
+
+ m_fdc->set_floppy(m_floppy);
+
+ if (m_floppy) m_floppy->mon_w(!BIT(data, 5));
+
+ // density select
+ m_fdc->dden_w(BIT(data, 2));
+}
diff --git a/src/devices/bus/ieee488/c8280.h b/src/devices/bus/ieee488/c8280.h
new file mode 100644
index 00000000000..076edcd736c
--- /dev/null
+++ b/src/devices/bus/ieee488/c8280.h
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 8280 Dual 8" Disk Drive emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __C8280__
+#define __C8280__
+
+#include "emu.h"
+#include "ieee488.h"
+#include "cpu/m6502/m6502.h"
+#include "formats/c8280_dsk.h"
+#include "machine/mos6530n.h"
+#include "machine/wd_fdc.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> c8280_t
+
+class c8280_t : public device_t,
+ public device_ieee488_interface
+{
+public:
+ // construction/destruction
+ c8280_t(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( dio_r );
+ DECLARE_WRITE8_MEMBER( dio_w );
+ DECLARE_READ8_MEMBER( riot1_pa_r );
+ DECLARE_WRITE8_MEMBER( riot1_pa_w );
+ DECLARE_READ8_MEMBER( riot1_pb_r );
+ DECLARE_WRITE8_MEMBER( riot1_pb_w );
+ DECLARE_READ8_MEMBER( fk5_r );
+ DECLARE_WRITE8_MEMBER( fk5_w );
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_ieee488_interface overrides
+ void ieee488_atn(int state);
+ void ieee488_ifc(int state);
+
+private:
+ inline void update_ieee_signals();
+
+ required_device<cpu_device> m_maincpu;
+ required_device<cpu_device> m_fdccpu;
+ required_device<mos6532_t> m_riot0;
+ required_device<mos6532_t> m_riot1;
+ required_device<fd1797_t> m_fdc;
+ required_device<floppy_connector> m_floppy0;
+ required_device<floppy_connector> m_floppy1;
+ required_ioport m_address;
+ floppy_image_device *m_floppy;
+
+ // IEEE-488 bus
+ int m_rfdo; // not ready for data output
+ int m_daco; // not data accepted output
+ int m_atna; // attention acknowledge
+ int m_ifc;
+
+ UINT8 m_fk5;
+};
+
+
+// device type definition
+extern const device_type C8280;
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/d9060.c b/src/devices/bus/ieee488/d9060.c
new file mode 100644
index 00000000000..f21653efb09
--- /dev/null
+++ b/src/devices/bus/ieee488/d9060.c
@@ -0,0 +1,578 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore 9060/9090 Hard Disk Drive emulation
+
+**********************************************************************/
+
+/*
+
+ Use the CHDMAN utility to create a 5MB image for D9060:
+
+ $ chdman createhd -o tm602s.chd -chs 153,4,32 -ss 256
+
+ or a 10MB image for D9090:
+
+ $ chdman createhd -o tm603s.chd -chs 153,6,32 -ss 256
+
+ Start the PET emulator with the D9060 attached on the IEEE-488 bus,
+ with the new CHD mounted:
+
+ $ mess pet8032 -ieee8 d9060 -hard tm602s.chd
+ $ mess pet8032 -ieee8 d9090 -hard tm603s.chd
+
+ Enter 'HEADER "LABEL",D0,I01' to format the hard drive.
+ Wait up to 1 hour and 20 minutes.
+
+*/
+
+#include "d9060.h"
+#include "bus/scsi/d9060hd.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define M6502_DOS_TAG "7e"
+#define M6532_0_TAG "7f"
+#define M6532_1_TAG "7g"
+
+#define M6502_HDC_TAG "4a"
+#define M6522_TAG "4b"
+
+#define AM2910_TAG "9d"
+
+#define SASIBUS_TAG "sasi"
+
+enum
+{
+ LED_POWER = 0,
+ LED_READY,
+ LED_ERROR
+};
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type D9060 = &device_creator<d9060_t>;
+const device_type D9090 = &device_creator<d9090_t>;
+
+
+//-------------------------------------------------
+// ROM( d9060 )
+//-------------------------------------------------
+
+ROM_START( d9060 )
+ ROM_REGION( 0x4000, M6502_DOS_TAG, 0 )
+ ROM_DEFAULT_BIOS("rc")
+ ROM_SYSTEM_BIOS( 0, "ra", "Revision A" )
+ ROMX_LOAD( "300516-001.7c", 0x0000, 0x2000, NO_DUMP, ROM_BIOS(1) )
+ ROMX_LOAD( "300517-001.7d", 0x2000, 0x2000, CRC(566df630) SHA1(b1602dfff408b165ee52a6a4ca3e2ec27e689ba9), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "rb", "Revision B" )
+ ROMX_LOAD( "300516-002.7c", 0x0000, 0x2000, CRC(2d758a14) SHA1(c959cc9dde84fc3d64e95e58a0a096a26d8107fd), ROM_BIOS(2) )
+ ROMX_LOAD( "300517-002.7d", 0x2000, 0x2000, CRC(f0382bc3) SHA1(0b0a8dc520f5b41ffa832e4a636b3d226ccbb7f1), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 2, "rc", "Revision C" )
+ ROMX_LOAD( "300516-003.7c", 0x0000, 0x2000, CRC(d6a3e88f) SHA1(bb1ddb5da94a86266012eca54818aa21dc4cef6a), ROM_BIOS(3) )
+ ROMX_LOAD( "300517-003.7d", 0x2000, 0x2000, CRC(2a9ad4ad) SHA1(4c17d014de48c906871b9b6c7d037d8736b1fd52), ROM_BIOS(3) )
+
+ ROM_REGION( 0x800, M6502_HDC_TAG, 0 )
+ ROM_LOAD( "300515-001.4c", 0x000, 0x800, CRC(99e096f7) SHA1(a3d1deb27bf5918b62b89c27fa3e488eb8f717a4) ) // Revision A
+ ROM_LOAD( "300515-002.4c", 0x000, 0x800, CRC(49adf4fb) SHA1(59dafbd4855083074ba8dc96a04d4daa5b76e0d6) ) // Revision B
+
+ ROM_REGION( 0x5000, AM2910_TAG, 0 )
+ ROM_LOAD( "441.5b", 0x0000, 0x1000, NO_DUMP ) // 82S137
+ ROM_LOAD( "442.6b", 0x1000, 0x1000, NO_DUMP ) // 82S137
+ ROM_LOAD( "573.7b", 0x2000, 0x1000, NO_DUMP ) // 82S137
+ ROM_LOAD( "444.8b", 0x3000, 0x1000, NO_DUMP ) // 82S137
+ ROM_LOAD( "445.9b", 0x4000, 0x1000, NO_DUMP ) // 82S137
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *d9060_base_t::device_rom_region() const
+{
+ return ROM_NAME( d9060 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( d9060_main_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( d9060_main_mem, AS_PROGRAM, 8, d9060_base_t )
+ AM_RANGE(0x0000, 0x007f) AM_MIRROR(0x0100) AM_DEVICE(M6532_0_TAG, mos6532_t, ram_map)
+ AM_RANGE(0x0080, 0x00ff) AM_MIRROR(0x0100) AM_DEVICE(M6532_1_TAG, mos6532_t, ram_map)
+ AM_RANGE(0x0200, 0x021f) AM_MIRROR(0x0d60) AM_DEVICE(M6532_0_TAG, mos6532_t, io_map)
+ AM_RANGE(0x0280, 0x029f) AM_MIRROR(0x0d60) AM_DEVICE(M6532_1_TAG, mos6532_t, io_map)
+ AM_RANGE(0x1000, 0x13ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x2000, 0x23ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x3000, 0x33ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x4000, 0x43ff) AM_MIRROR(0x0c00) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0xc000, 0xffff) AM_ROM AM_REGION(M6502_DOS_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( d9060_hdc_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( d9060_hdc_mem, AS_PROGRAM, 8, d9060_base_t )
+ ADDRESS_MAP_GLOBAL_MASK(0x1fff)
+ AM_RANGE(0x0000, 0x007f) AM_MIRROR(0x300) AM_RAM
+ AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x380) AM_DEVREADWRITE(M6522_TAG, via6522_device, read, write)
+ AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
+ AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
+ AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
+ AM_RANGE(0x1000, 0x13ff) AM_RAM AM_SHARE("share4")
+ AM_RANGE(0x1800, 0x1fff) AM_ROM AM_REGION(M6502_HDC_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// riot6532 0
+//-------------------------------------------------
+
+READ8_MEMBER( d9060_base_t::dio_r )
+{
+ /*
+
+ bit description
+
+ PA0 DI0
+ PA1 DI1
+ PA2 DI2
+ PA3 DI3
+ PA4 DI4
+ PA5 DI5
+ PA6 DI6
+ PA7 DI7
+
+ */
+
+ return m_bus->dio_r();
+}
+
+
+WRITE8_MEMBER( d9060_base_t::dio_w )
+{
+ /*
+
+ bit description
+
+ PB0 DO0
+ PB1 DO1
+ PB2 DO2
+ PB3 DO3
+ PB4 DO4
+ PB5 DO5
+ PB6 DO6
+ PB7 DO7
+
+ */
+
+ m_bus->dio_w(this, data);
+}
+
+
+//-------------------------------------------------
+// riot6532 1
+//-------------------------------------------------
+
+READ8_MEMBER( d9060_base_t::riot1_pa_r )
+{
+ /*
+
+ bit description
+
+ PA0
+ PA1
+ PA2
+ PA3
+ PA4
+ PA5 EOII
+ PA6 DAVI
+ PA7 _ATN
+
+ */
+
+ UINT8 data = 0;
+
+ // end or identify in
+ data |= m_bus->eoi_r() << 5;
+
+ // data valid in
+ data |= m_bus->dav_r() << 6;
+
+ // attention
+ data |= !m_bus->atn_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( d9060_base_t::riot1_pa_w )
+{
+ /*
+
+ bit description
+
+ PA0 ATNA
+ PA1 DACO
+ PA2 RFDO
+ PA3 EOIO
+ PA4 DAVO
+ PA5
+ PA6
+ PA7
+
+ */
+
+ // attention acknowledge
+ m_atna = BIT(data, 0);
+
+ // data accepted out
+ m_daco = BIT(data, 1);
+
+ // not ready for data out
+ m_rfdo = BIT(data, 2);
+
+ // end or identify out
+ m_bus->eoi_w(this, BIT(data, 3));
+
+ // data valid out
+ m_bus->dav_w(this, BIT(data, 4));
+
+ update_ieee_signals();
+}
+
+READ8_MEMBER( d9060_base_t::riot1_pb_r )
+{
+ /*
+
+ bit description
+
+ PB0 device #
+ PB1 device #
+ PB2 device #
+ PB3
+ PB4
+ PB5
+ PB6 DACI
+ PB7 RFDI
+
+ */
+
+ UINT8 data = 0;
+
+ // device number selection
+ data |= m_slot->get_address() - 8;
+
+ // data accepted in
+ data |= m_bus->ndac_r() << 6;
+
+ // ready for data in
+ data |= m_bus->nrfd_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( d9060_base_t::riot1_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0
+ PB1
+ PB2
+ PB3
+ PB4 DRIVE RDY
+ PB5 PWR ON AND NO ERRORS
+ PB6
+ PB7
+
+ */
+
+ // ready led
+ output_set_led_value(LED_READY, BIT(data, 4));
+
+ // power led
+ output_set_led_value(LED_POWER, BIT(data, 5));
+
+ // error led
+ output_set_led_value(LED_ERROR, !BIT(data, 5));
+}
+
+
+WRITE8_MEMBER( d9060_base_t::via_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0 SEL
+ PB1 RST
+ PB2 C/D
+ PB3 BUSY
+ PB4 J14 (1=9060, 0=9090)
+ PB5 J13
+ PB6 I/O
+ PB7 MSG
+
+ */
+
+ m_sasibus->write_sel(BIT(data, 0));
+ m_sasibus->write_rst(BIT(data, 1));
+}
+
+WRITE_LINE_MEMBER( d9060_base_t::ack_w )
+{
+ m_sasibus->write_ack(!state);
+}
+
+WRITE_LINE_MEMBER( d9060_base_t::enable_w )
+{
+ m_enable = state;
+
+ if( !m_enable )
+ {
+ m_sasi_data_out->write( m_data );
+ }
+ else
+ {
+ m_sasi_data_out->write( 0 );
+ }
+}
+
+WRITE8_MEMBER( d9060_base_t::scsi_data_w )
+{
+ m_data = data;
+
+ if( !m_enable )
+ {
+ m_sasi_data_out->write( m_data );
+ }
+}
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( d9060 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( d9060 )
+ // DOS
+ MCFG_CPU_ADD(M6502_DOS_TAG, M6502, XTAL_4MHz/4)
+ MCFG_CPU_PROGRAM_MAP(d9060_main_mem)
+
+ MCFG_DEVICE_ADD(M6532_0_TAG, MOS6532n, XTAL_4MHz/4)
+ MCFG_MOS6530n_IN_PA_CB(READ8(d9060_base_t, dio_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(d9060_base_t, dio_w))
+
+ MCFG_DEVICE_ADD(M6532_1_TAG, MOS6532n, XTAL_4MHz/4)
+ MCFG_MOS6530n_IN_PA_CB(READ8(d9060_base_t, riot1_pa_r))
+ MCFG_MOS6530n_OUT_PA_CB(WRITE8(d9060_base_t, riot1_pa_w))
+ MCFG_MOS6530n_IN_PB_CB(READ8(d9060_base_t, riot1_pb_r))
+ MCFG_MOS6530n_OUT_PB_CB(WRITE8(d9060_base_t, riot1_pb_w))
+ MCFG_MOS6530n_IRQ_CB(INPUTLINE(M6502_DOS_TAG, INPUT_LINE_IRQ0))
+
+ // controller
+ MCFG_CPU_ADD(M6502_HDC_TAG, M6502, XTAL_4MHz/4)
+ MCFG_CPU_PROGRAM_MAP(d9060_hdc_mem)
+
+ MCFG_DEVICE_ADD(M6522_TAG, VIA6522, XTAL_4MHz/4)
+ MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(d9060_base_t, scsi_data_w))
+ MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(d9060_base_t, via_pb_w))
+ MCFG_VIA6522_CA2_HANDLER(WRITELINE(d9060_base_t, ack_w))
+ MCFG_VIA6522_CB2_HANDLER(WRITELINE(d9060_base_t, enable_w))
+ MCFG_VIA6522_IRQ_HANDLER(DEVWRITELINE(M6502_HDC_TAG, m6502_device, irq_line))
+
+ MCFG_DEVICE_ADD(SASIBUS_TAG, SCSI_PORT, 0)
+ MCFG_SCSI_REQ_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_ca1))
+ MCFG_SCSI_CD_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pb2))
+ MCFG_SCSI_BSY_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pb3))
+ MCFG_SCSI_IO_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pb6))
+ MCFG_SCSI_MSG_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pb7))
+ MCFG_SCSI_DATA0_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pa0))
+ MCFG_SCSI_DATA1_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pa1))
+ MCFG_SCSI_DATA2_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pa2))
+ MCFG_SCSI_DATA3_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pa3))
+ MCFG_SCSI_DATA4_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pa4))
+ MCFG_SCSI_DATA5_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pa5))
+ MCFG_SCSI_DATA6_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pa6))
+ MCFG_SCSI_DATA7_HANDLER(DEVWRITELINE(M6522_TAG, via6522_device, write_pa7))
+
+ MCFG_SCSI_OUTPUT_LATCH_ADD("sasi_data_out", SASIBUS_TAG)
+
+ MCFG_SCSIDEV_ADD(SASIBUS_TAG ":" SCSI_PORT_DEVICE1, "harddisk", D9060HD, SCSI_ID_0)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor d9060_base_t::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( d9060 );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( d9060 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( d9060 )
+ PORT_START("ADDRESS")
+ PORT_DIPNAME( 0x07, 0x01, "Device Address" )
+ PORT_DIPSETTING( 0x00, "8" )
+ PORT_DIPSETTING( 0x01, "9" )
+ PORT_DIPSETTING( 0x02, "10" )
+ PORT_DIPSETTING( 0x03, "11" )
+ PORT_DIPSETTING( 0x04, "12" )
+ PORT_DIPSETTING( 0x05, "13" )
+ PORT_DIPSETTING( 0x06, "14" )
+ PORT_DIPSETTING( 0x07, "15" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor d9060_base_t::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( d9060 );
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// update_ieee_signals -
+//-------------------------------------------------
+
+inline void d9060_base_t::update_ieee_signals()
+{
+ int atn = m_bus->atn_r();
+ int nrfd = !(!(!(atn && m_atna) && m_rfdo) || !(atn || m_atna));
+ int ndac = !(m_daco || !(atn || m_atna));
+
+ m_bus->nrfd_w(this, nrfd);
+ m_bus->ndac_w(this, ndac);
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// d9060_base_t - constructor
+//-------------------------------------------------
+
+d9060_base_t::d9060_base_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, M6502_DOS_TAG),
+ m_hdccpu(*this, M6502_HDC_TAG),
+ m_riot0(*this, M6532_0_TAG),
+ m_riot1(*this, M6532_1_TAG),
+ m_via(*this, M6522_TAG),
+ m_sasibus(*this, SASIBUS_TAG),
+ m_sasi_data_out(*this, "sasi_data_out"),
+ m_address(*this, "ADDRESS"),
+ m_rfdo(1),
+ m_daco(1),
+ m_atna(1),
+ m_enable(0),
+ m_variant(variant)
+{
+}
+
+
+//-------------------------------------------------
+// d9060_t - constructor
+//-------------------------------------------------
+
+d9060_t::d9060_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : d9060_base_t(mconfig, D9060, "D9060", tag, owner, clock, TYPE_9060, "d9060", __FILE__) { }
+
+
+//-------------------------------------------------
+// d9090_t - constructor
+//-------------------------------------------------
+
+d9090_t::d9090_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : d9060_base_t(mconfig, D9090, "D9090", tag, owner, clock, TYPE_9090, "d9090", __FILE__) { }
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void d9060_base_t::device_start()
+{
+ // state saving
+ save_item(NAME(m_rfdo));
+ save_item(NAME(m_daco));
+ save_item(NAME(m_atna));
+ save_item(NAME(m_enable));
+
+ m_via->write_pb4(!(m_variant == TYPE_9090)); // J14 (6 HEADS)
+ m_via->write_pb5(!(m_variant == TYPE_9060)); // J13 (4 HEADS)
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void d9060_base_t::device_reset()
+{
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, ASSERT_LINE);
+ m_maincpu->set_input_line(M6502_SET_OVERFLOW, CLEAR_LINE);
+
+ m_hdccpu->set_input_line(M6502_SET_OVERFLOW, ASSERT_LINE);
+
+ m_riot1->pa7_w(1);
+}
+
+
+//-------------------------------------------------
+// ieee488_atn - attention
+//-------------------------------------------------
+
+void d9060_base_t::ieee488_atn(int state)
+{
+ update_ieee_signals();
+
+ m_riot1->pa7_w(state);
+}
+
+
+//-------------------------------------------------
+// ieee488_ifc - interface clear
+//-------------------------------------------------
+
+void d9060_base_t::ieee488_ifc(int state)
+{
+ if (!m_ifc && state)
+ {
+ device_reset();
+ }
+
+ m_ifc = state;
+}
diff --git a/src/devices/bus/ieee488/d9060.h b/src/devices/bus/ieee488/d9060.h
new file mode 100644
index 00000000000..7efc20006cf
--- /dev/null
+++ b/src/devices/bus/ieee488/d9060.h
@@ -0,0 +1,122 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Commodore D9060/D9090 Hard Disk Drive emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __D9060__
+#define __D9060__
+
+#include "emu.h"
+#include "ieee488.h"
+#include "cpu/m6502/m6502.h"
+#include "machine/6522via.h"
+#include "machine/mos6530n.h"
+#include "bus/scsi/scsi.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> d9060_base_t
+
+class d9060_base_t : public device_t,
+ public device_ieee488_interface
+{
+public:
+ enum
+ {
+ TYPE_9060,
+ TYPE_9090
+ };
+
+ // construction/destruction
+ d9060_base_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant, const char *shortname, const char *source);
+
+ // 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( dio_r );
+ DECLARE_WRITE8_MEMBER( dio_w );
+ DECLARE_READ8_MEMBER( riot1_pa_r );
+ DECLARE_WRITE8_MEMBER( riot1_pa_w );
+ DECLARE_READ8_MEMBER( riot1_pb_r );
+ DECLARE_WRITE8_MEMBER( riot1_pb_w );
+ DECLARE_READ8_MEMBER( via_pb_r );
+ DECLARE_WRITE8_MEMBER( via_pb_w );
+ DECLARE_WRITE_LINE_MEMBER( ack_w );
+ DECLARE_WRITE_LINE_MEMBER( enable_w );
+ DECLARE_WRITE8_MEMBER( scsi_data_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_ieee488_interface overrides
+ void ieee488_atn(int state);
+ void ieee488_ifc(int state);
+
+private:
+ inline void update_ieee_signals();
+
+ required_device<cpu_device> m_maincpu;
+ required_device<cpu_device> m_hdccpu;
+ required_device<mos6532_t> m_riot0;
+ required_device<mos6532_t> m_riot1;
+ required_device<via6522_device> m_via;
+ required_device<SCSI_PORT_DEVICE> m_sasibus;
+ required_device<output_latch_device> m_sasi_data_out;
+ required_ioport m_address;
+
+ // IEEE-488 bus
+ int m_rfdo; // not ready for data output
+ int m_daco; // not data accepted output
+ int m_atna; // attention acknowledge
+ int m_ifc;
+
+ // SASI bus
+ int m_enable;
+ UINT8 m_data;
+
+ int m_variant;
+};
+
+
+// ======================> d9060_t
+
+class d9060_t : public d9060_base_t
+{
+public:
+ // construction/destruction
+ d9060_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+
+// ======================> d9090_t
+
+class d9090_t : public d9060_base_t
+{
+public:
+ // construction/destruction
+ d9090_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+
+// device type definition
+extern const device_type D9060;
+extern const device_type D9090;
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/hardbox.c b/src/devices/bus/ieee488/hardbox.c
new file mode 100644
index 00000000000..4a2a0c16dae
--- /dev/null
+++ b/src/devices/bus/ieee488/hardbox.c
@@ -0,0 +1,401 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder, Mike Naberezny
+/****************************************************************************
+
+ SSE HardBox emulation
+
+****************************************************************************/
+
+/*
+ http://mikenaberezny.com/hardware/pet-cbm/sse-hardbox-corvus-interface/
+
+ The HardBox provides a CBM DOS interface for a Corvus hard disk. Before
+ it can be used, a hard disk image must first be created and formatted.
+ Use the CHDMAN utility to create a 20MB image:
+
+ $ chdman createhd -o /path/to/corvus20mb.chd -chs 388,5,20 -ss 512
+
+ Start the pet8032 emulator with the HardBox attached as device 9,
+ with the new CHD and the utilities floppy mounted:
+
+ $ mess pet8032 -ieee9 hardbox \
+ -hard1 /path/to/corvus20mb.chd \
+ -flop1 /path/to/hardbox-utils.d80
+
+ Load and run the "configure" program from the floppy. When prompted
+ for the HardBox device number, enter "9".
+
+ Select "q" for quick configure at the menu. It will present a default
+ drive size and ask if you want to alter it. If the size is not 20,
+ change it to 20.
+
+ After accepting the drive size, it will prompt if you want to perform
+ a format check. This is optional. If you enter "y" to proceed with
+ the format check, it will always report no bad sectors.
+
+ Enter "y" to proceed with the format. After it has completed, the
+ program will exit back to BASIC. The drive should now be usable.
+*/
+
+
+#include "hardbox.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define Z80_TAG "z80"
+#define I8255_0_TAG "ic17"
+#define I8255_1_TAG "ic16"
+#define CORVUS_HDC_TAG "corvus"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type HARDBOX = &device_creator<hardbox_device>;
+
+
+//-------------------------------------------------
+// ROM( hardbox )
+//-------------------------------------------------
+
+ROM_START( hardbox )
+ ROM_REGION( 0x2000, Z80_TAG, 0 )
+ ROM_DEFAULT_BIOS("v2.4")
+
+ ROM_SYSTEM_BIOS( 0, "v2.3", "Version 2.3 (Corvus)" )
+ ROMX_LOAD( "295-2.3.ic3", 0x0000, 0x1000, CRC(a3eb5fc2) SHA1(39941b45b0696db928615c41c7eae18d951d9ada), ROM_BIOS(1) )
+ ROMX_LOAD( "296-2.3.ic4", 0x1000, 0x1000, CRC(fb55b058) SHA1(8f9ec313ec6beaf7b513edf39d9628e6abcc7bc3), ROM_BIOS(1) )
+
+ ROM_SYSTEM_BIOS( 1, "v2.4", "Version 2.4 (Corvus)" )
+ ROMX_LOAD( "289.ic3", 0x0000, 0x1000, CRC(c39e058f) SHA1(45b390d7125a40f84c7b411a479218baff079746), ROM_BIOS(2) )
+ ROMX_LOAD( "290.ic4", 0x1000, 0x1000, CRC(62f51405) SHA1(fdfa0d7b7e8d0182f2df0aa8163c790506104dcf), ROM_BIOS(2) )
+
+ ROM_SYSTEM_BIOS( 2, "v3.1", "Version 3.1 (Sunol)" )
+ ROMX_LOAD( "295-3.1.ic3", 0x0000, 0x1000, CRC(654a5db1) SHA1(c40859526921e3d8bfd58fc28cc9cc64e59ec638), ROM_BIOS(3) )
+ ROMX_LOAD( "296-3.1.ic4", 0x1000, 0x1000, CRC(4c62ddc0) SHA1(151f99dc554d3762b805fc8383cf1b3e1455784f), ROM_BIOS(3) )
+
+ /* Note: Two sets of EPROMs were found marked only "295" and "296" but they have different contents.
+ The version numbers listed are the ROM version reported by the HardBox diagnostics program.
+ Disassembling the ROMs showed that v2.3 and v2.4 are for Corvus Systems drives but v3.1 is
+ for Sunol Systems drives. Both types use the Corvus flat cable interface but there may be
+ some programming differences, e.g. the v3.1 firmware for Sunol does not have the park heads
+ routine in the Corvus versions. MESS emulates a Corvus drive so we default to the last
+ known HardBox firmware for Corvus (v2.4). */
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *hardbox_device::device_rom_region() const
+{
+ return ROM_NAME( hardbox );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( hardbox_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( hardbox_mem, AS_PROGRAM, 8, hardbox_device )
+ AM_RANGE(0x0000, 0x3fff) AM_RAM
+ AM_RANGE(0xe000, 0xffff) AM_ROM AM_REGION(Z80_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( hardbox_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( hardbox_io, AS_IO, 8, hardbox_device )
+ ADDRESS_MAP_GLOBAL_MASK(0xff)
+ AM_RANGE(0x10, 0x13) AM_DEVREADWRITE(I8255_0_TAG, i8255_device, read, write)
+ AM_RANGE(0x14, 0x17) AM_DEVREADWRITE(I8255_1_TAG, i8255_device, read, write)
+ AM_RANGE(0x18, 0x18) AM_DEVREADWRITE(CORVUS_HDC_TAG, corvus_hdc_t, read, write)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// I8255A 0 interface
+//-------------------------------------------------
+
+READ8_MEMBER( hardbox_device::ppi0_pa_r )
+{
+ return m_bus->dio_r() ^ 0xff;
+}
+
+WRITE8_MEMBER( hardbox_device::ppi0_pb_w )
+{
+ m_bus->dio_w(this, data ^ 0xff);
+}
+
+READ8_MEMBER( hardbox_device::ppi0_pc_r )
+{
+ UINT8 data = ioport("SW1")->read();
+
+ /* DIP switches on PC1,PC2,PC3 configure the IEEE-488 primary address.
+ We get the address from the slot instead. */
+ data |= ((m_slot->get_address() - 8) << 1) ^ 0xff;
+
+ return data;
+}
+
+//-------------------------------------------------
+// I8255A 1 interface
+//-------------------------------------------------
+
+READ8_MEMBER( hardbox_device::ppi1_pa_r )
+{
+ /*
+
+ bit description
+
+ PA0 ATN
+ PA1 DAV
+ PA2 NDAC
+ PA3 NRFD
+ PA4 EOI
+ PA5 SRQ
+ PA6 REN
+ PA7 IFC
+
+ */
+
+ UINT8 data = 0;
+
+ data |= !m_bus->atn_r();
+ data |= !m_bus->dav_r() << 1;
+ data |= !m_bus->ndac_r() << 2;
+ data |= !m_bus->nrfd_r() << 3;
+ data |= !m_bus->eoi_r() << 4;
+ data |= !m_bus->srq_r() << 5;
+ data |= !m_bus->ren_r() << 6;
+ data |= !m_bus->ifc_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( hardbox_device::ppi1_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0 ATN
+ PB1 DAV
+ PB2 NDAC
+ PB3 NRFD
+ PB4 EOI
+ PB5 SRQ
+ PB6 REN
+ PB7 IFC
+
+ Note: When the PCB is configured as a HardBox instead of a SoftBox,
+ IFC is read only. Do not connect IFC for output here.
+
+ */
+
+ m_bus->atn_w(this, !BIT(data, 0));
+ m_bus->dav_w(this, !BIT(data, 1));
+ m_bus->ndac_w(this, !BIT(data, 2));
+ m_bus->nrfd_w(this, !BIT(data, 3));
+ m_bus->eoi_w(this, !BIT(data, 4));
+ m_bus->srq_w(this, !BIT(data, 5));
+ m_bus->ren_w(this, !BIT(data, 6));
+}
+
+READ8_MEMBER( hardbox_device::ppi1_pc_r )
+{
+ /*
+
+ bit description
+
+ PC0
+ PC1
+ PC2
+ PC3
+ PC4 Corvus READY
+ PC5 Corvus DIRC
+ PC6
+ PC7
+
+ */
+
+ UINT8 status = m_hdc->status_r(space, 0);
+ UINT8 data = 0;
+
+ data |= (status & CONTROLLER_BUSY) ? 0 : 0x10;
+ data |= (status & CONTROLLER_DIRECTION) ? 0 : 0x20;
+
+ return data;
+}
+
+WRITE8_MEMBER( hardbox_device::ppi1_pc_w )
+{
+ /*
+
+ bit description
+
+ PC0 LED "A"
+ PC1 LED "B"
+ PC2 LED "READY"
+ PC3
+ PC4
+ PC5
+ PC6
+ PC7
+
+ */
+
+ output_set_led_value(LED_A, !BIT(data, 0));
+ output_set_led_value(LED_B, !BIT(data, 1));
+ output_set_led_value(LED_READY, !BIT(data, 2));
+}
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( hardbox )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( hardbox )
+ // basic machine hardware
+ MCFG_CPU_ADD(Z80_TAG, Z80, XTAL_8MHz/2)
+ MCFG_CPU_PROGRAM_MAP(hardbox_mem)
+ MCFG_CPU_IO_MAP(hardbox_io)
+
+ // devices
+ MCFG_DEVICE_ADD(I8255_0_TAG, I8255A, 0)
+ MCFG_I8255_IN_PORTA_CB(READ8(hardbox_device, ppi0_pa_r))
+ MCFG_I8255_OUT_PORTB_CB(WRITE8(hardbox_device, ppi0_pb_w))
+ MCFG_I8255_IN_PORTC_CB(READ8(hardbox_device, ppi0_pc_r))
+
+ MCFG_DEVICE_ADD(I8255_1_TAG, I8255A, 0)
+ MCFG_I8255_IN_PORTA_CB(READ8(hardbox_device, ppi1_pa_r))
+ MCFG_I8255_OUT_PORTB_CB(WRITE8(hardbox_device, ppi1_pb_w))
+ MCFG_I8255_IN_PORTC_CB(READ8(hardbox_device, ppi1_pc_r))
+ MCFG_I8255_OUT_PORTC_CB(WRITE8(hardbox_device, ppi1_pc_w))
+
+ MCFG_DEVICE_ADD(CORVUS_HDC_TAG, CORVUS_HDC, 0)
+ MCFG_HARDDISK_ADD("harddisk1")
+ MCFG_HARDDISK_INTERFACE("corvus_hdd")
+ MCFG_HARDDISK_ADD("harddisk2")
+ MCFG_HARDDISK_INTERFACE("corvus_hdd")
+ MCFG_HARDDISK_ADD("harddisk3")
+ MCFG_HARDDISK_INTERFACE("corvus_hdd")
+ MCFG_HARDDISK_ADD("harddisk4")
+ MCFG_HARDDISK_INTERFACE("corvus_hdd")
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor hardbox_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( hardbox );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( hardbox )
+//-------------------------------------------------
+
+INPUT_PORTS_START( hardbox )
+ PORT_START("SW1")
+ PORT_DIPUNKNOWN_DIPLOC( 0x01, IP_ACTIVE_LOW, "SW1:1" )
+ PORT_DIPNAME( 0x0e, 0x0c, "Device Address" ) PORT_DIPLOCATION("SW1:2,3,4")
+ PORT_DIPSETTING( 0x0e, "8" )
+ PORT_DIPSETTING( 0x0c, "9" )
+ PORT_DIPSETTING( 0x0a, "10" )
+ PORT_DIPSETTING( 0x08, "11" )
+ PORT_DIPSETTING( 0x06, "12" )
+ PORT_DIPSETTING( 0x04, "13" )
+ PORT_DIPSETTING( 0x02, "14" )
+ PORT_DIPSETTING( 0x00, "15" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x10, IP_ACTIVE_LOW, "SW1:5" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x20, IP_ACTIVE_LOW, "SW1:6" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x40, IP_ACTIVE_LOW, "SW1:7" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x80, IP_ACTIVE_LOW, "SW1:8" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor hardbox_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( hardbox );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// hardbox_device - constructor
+//-------------------------------------------------
+
+hardbox_device::hardbox_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, HARDBOX, "HardBox", tag, owner, clock, "hardbox", __FILE__),
+ device_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, Z80_TAG),
+ m_hdc(*this, CORVUS_HDC_TAG)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void hardbox_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset_after_children - device-specific
+// reset that must happen after child devices
+// have performed their resets
+//-------------------------------------------------
+
+void hardbox_device::device_reset_after_children()
+{
+ /* The Z80 starts at address 0x0000 but the HardBox has RAM there and
+ needs to start from the BIOS at 0xe000. The PCB has logic and a
+ 74S287 PROM that temporarily changes the memory map so that the
+ IC3 EPROM at 0xe000 is mapped to 0x0000 for the first instruction
+ fetch only. The instruction normally at 0xe000 is an absolute jump
+ into the ROM. On reset, the Z80 will fetch it from 0x0000 and set
+ its PC, then the normal map will be restored before the next
+ instruction fetch. Here we just set the PC to 0xe000 after the Z80
+ resets, which has the same effect. */
+
+ m_maincpu->set_state_int(Z80_PC, 0xe000);
+}
+
+
+//-------------------------------------------------
+// ieee488_ifc - interface clear (reset)
+//-------------------------------------------------
+
+void hardbox_device::ieee488_ifc(int state)
+{
+ if (!m_ifc && state)
+ {
+ device_reset();
+ }
+
+ m_ifc = state;
+}
diff --git a/src/devices/bus/ieee488/hardbox.h b/src/devices/bus/ieee488/hardbox.h
new file mode 100644
index 00000000000..77cbd23fb07
--- /dev/null
+++ b/src/devices/bus/ieee488/hardbox.h
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder, Mike Naberezny
+/**********************************************************************
+
+ SSE HardBox emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __PET_HARDBOX__
+#define __PET_HARDBOX__
+
+#include "ieee488.h"
+#include "cpu/z80/z80.h"
+#include "machine/i8251.h"
+#include "machine/i8255.h"
+#include "imagedev/harddriv.h"
+#include "machine/corvushd.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> hardbox_device
+
+class hardbox_device : public device_t,
+ public device_ieee488_interface
+{
+public:
+ // construction/destruction
+ hardbox_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;
+
+ DECLARE_READ8_MEMBER( ppi0_pa_r );
+ DECLARE_WRITE8_MEMBER( ppi0_pb_w );
+ DECLARE_READ8_MEMBER( ppi0_pc_r );
+
+ DECLARE_READ8_MEMBER( ppi1_pa_r );
+ DECLARE_WRITE8_MEMBER( ppi1_pb_w );
+ DECLARE_READ8_MEMBER( ppi1_pc_r );
+ DECLARE_WRITE8_MEMBER( ppi1_pc_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset_after_children();
+
+ // device_ieee488_interface overrides
+ virtual void ieee488_ifc(int state);
+
+private:
+ enum
+ {
+ LED_A,
+ LED_B,
+ LED_READY
+ };
+
+ required_device<cpu_device> m_maincpu;
+ required_device<corvus_hdc_t> m_hdc;
+
+ int m_ifc; // Tracks previous state of IEEE-488 IFC line
+};
+
+// device type definition
+extern const device_type HARDBOX;
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/ieee488.c b/src/devices/bus/ieee488/ieee488.c
new file mode 100644
index 00000000000..f3d61fa539a
--- /dev/null
+++ b/src/devices/bus/ieee488/ieee488.c
@@ -0,0 +1,396 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ IEEE-488.1 General Purpose Interface Bus emulation
+ (aka HP-IB, GPIB, CBM IEEE)
+
+**********************************************************************/
+
+#include "ieee488.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+static const char *const SIGNAL_NAME[] = { "EOI", "DAV", "NRFD", "NDAC", "IFC", "SRQ", "ATN", "REN" };
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type IEEE488 = &device_creator<ieee488_device>;
+const device_type IEEE488_SLOT = &device_creator<ieee488_slot_device>;
+
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_ieee488_interface - constructor
+//-------------------------------------------------
+
+device_ieee488_interface::device_ieee488_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_ieee488_interface - destructor
+//-------------------------------------------------
+
+device_ieee488_interface::~device_ieee488_interface()
+{
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// ieee488_slot_device - constructor
+//-------------------------------------------------
+
+ieee488_slot_device::ieee488_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, IEEE488_SLOT, "IEEE-488 slot", tag, owner, clock, "ieee488_slot", __FILE__),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ieee488_slot_device::device_start()
+{
+ ieee488_device* bus = NULL;
+
+ for (device_t *device = owner(); device != NULL; device = device->owner())
+ {
+ bus = device->subdevice<ieee488_device>(IEEE488_TAG);
+ if (bus != NULL) break;
+ }
+
+ assert(bus);
+
+ device_ieee488_interface *dev = dynamic_cast<device_ieee488_interface *>(get_card_device());
+ if (dev) bus->add_device(this, get_card_device());
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// ieee488_device - constructor
+//-------------------------------------------------
+
+ieee488_device::ieee488_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, IEEE488, "IEEE-488 bus", tag, owner, clock, "ieee488", __FILE__),
+ m_write_eoi(*this),
+ m_write_dav(*this),
+ m_write_nrfd(*this),
+ m_write_ndac(*this),
+ m_write_ifc(*this),
+ m_write_srq(*this),
+ m_write_atn(*this),
+ m_write_ren(*this),
+ m_dio(0xff)
+{
+ for (int i = 0; i < SIGNAL_COUNT; i++)
+ {
+ m_line[i] = 1;
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ieee488_device::device_start()
+{
+ // resolve callbacks
+ m_write_eoi.resolve_safe();
+ m_write_dav.resolve_safe();
+ m_write_nrfd.resolve_safe();
+ m_write_ndac.resolve_safe();
+ m_write_ifc.resolve_safe();
+ m_write_srq.resolve_safe();
+ m_write_atn.resolve_safe();
+ m_write_ren.resolve_safe();
+}
+
+
+//-------------------------------------------------
+// device_stop - device-specific stop
+//-------------------------------------------------
+
+void ieee488_device::device_stop()
+{
+ m_device_list.reset();
+}
+
+
+//-------------------------------------------------
+// add_device -
+//-------------------------------------------------
+
+void ieee488_device::add_device(ieee488_slot_device *slot, device_t *target)
+{
+ daisy_entry *entry = global_alloc(daisy_entry(target));
+
+ entry->m_interface->m_bus = this;
+ entry->m_interface->m_slot = slot;
+
+ m_device_list.append(*entry);
+}
+
+
+//-------------------------------------------------
+// daisy_entry - constructor
+//-------------------------------------------------
+
+ieee488_device::daisy_entry::daisy_entry(device_t *device)
+ : m_next(NULL),
+ m_device(device),
+ m_interface(NULL),
+ m_dio(0xff)
+{
+ for (int i = 0; i < SIGNAL_COUNT; i++)
+ {
+ m_line[i] = 1;
+ }
+
+ device->interface(m_interface);
+}
+
+
+//-------------------------------------------------
+// set_signal -
+//-------------------------------------------------
+
+void ieee488_device::set_signal(device_t *device, int signal, int state)
+{
+ bool changed = false;
+
+ if (device == this)
+ {
+ if (m_line[signal] != state)
+ {
+ if (LOG) logerror("%s IEEE488: '%s' %s %u\n", machine().describe_context(), tag(), SIGNAL_NAME[signal], state);
+ m_line[signal] = state;
+ changed = true;
+ }
+ }
+ else
+ {
+ daisy_entry *entry = m_device_list.first();
+
+ while (entry)
+ {
+ if (!strcmp(entry->m_device->tag(), device->tag()))
+ {
+ if (entry->m_line[signal] != state)
+ {
+ if (LOG) logerror("%s IEEE488: '%s' %s %u\n", machine().describe_context(), device->tag(), SIGNAL_NAME[signal], state);
+ entry->m_line[signal] = state;
+ changed = true;
+ }
+ }
+
+ entry = entry->next();
+ }
+ }
+
+ if (changed)
+ {
+ switch (signal)
+ {
+ case EOI: m_write_eoi(state); break;
+ case DAV: m_write_dav(state); break;
+ case NRFD: m_write_nrfd(state); break;
+ case NDAC: m_write_ndac(state); break;
+ case IFC: m_write_ifc(state); break;
+ case SRQ: m_write_srq(state); break;
+ case ATN: m_write_atn(state); break;
+ case REN: m_write_ren(state); break;
+ }
+
+ daisy_entry *entry = m_device_list.first();
+
+ while (entry)
+ {
+ switch (signal)
+ {
+ case EOI:
+ entry->m_interface->ieee488_eoi(state);
+ break;
+
+ case DAV:
+ entry->m_interface->ieee488_dav(state);
+ break;
+
+ case NRFD:
+ entry->m_interface->ieee488_nrfd(state);
+ break;
+
+ case NDAC:
+ entry->m_interface->ieee488_ndac(state);
+ break;
+
+ case IFC:
+ entry->m_interface->ieee488_ifc(state);
+ break;
+
+ case SRQ:
+ entry->m_interface->ieee488_srq(state);
+ break;
+
+ case ATN:
+ entry->m_interface->ieee488_atn(state);
+ break;
+
+ case REN:
+ entry->m_interface->ieee488_ren(state);
+ break;
+ }
+
+ entry = entry->next();
+ }
+
+ if (LOG) logerror("IEEE488: EOI %u DAV %u NRFD %u NDAC %u IFC %u SRQ %u ATN %u REN %u DIO %02x\n",
+ get_signal(EOI), get_signal(DAV), get_signal(NRFD), get_signal(NDAC),
+ get_signal(IFC), get_signal(SRQ), get_signal(ATN), get_signal(REN), get_data());
+ }
+}
+
+
+//-------------------------------------------------
+// get_signal -
+//-------------------------------------------------
+
+int ieee488_device::get_signal(int signal)
+{
+ int state = m_line[signal];
+
+ if (state)
+ {
+ daisy_entry *entry = m_device_list.first();
+
+ while (entry)
+ {
+ if (!entry->m_line[signal])
+ {
+ state = 0;
+ break;
+ }
+
+ entry = entry->next();
+ }
+ }
+
+ return state;
+}
+
+
+//-------------------------------------------------
+// set_data -
+//-------------------------------------------------
+
+void ieee488_device::set_data(device_t *device, UINT8 data)
+{
+ if (device == this)
+ {
+ if (LOG) logerror("%s IEEE488: '%s' DIO %02x\n", machine().describe_context(), tag(), data);
+
+ m_dio = data;
+ }
+ else
+ {
+ daisy_entry *entry = m_device_list.first();
+
+ while (entry)
+ {
+ if (!strcmp(entry->m_device->tag(), device->tag()))
+ {
+ if (entry->m_dio != data)
+ {
+ if (LOG) logerror("%s IEEE488: '%s' DIO %02x\n", machine().describe_context(), device->tag(), data);
+ entry->m_dio = data;
+ }
+ }
+
+ entry = entry->next();
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// get_data -
+//-------------------------------------------------
+
+UINT8 ieee488_device::get_data()
+{
+ UINT8 data = m_dio;
+
+ daisy_entry *entry = m_device_list.first();
+
+ while (entry)
+ {
+ data &= entry->m_dio;
+
+ entry = entry->next();
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( cbm_ieee488_devices )
+//-------------------------------------------------
+
+// slot devices
+#include "bus/cbmiec/c1526.h"
+#include "c2031.h"
+#include "c2040.h"
+#include "c8050.h"
+#include "c8280.h"
+#include "d9060.h"
+#include "hardbox.h"
+#include "shark.h"
+#include "softbox.h"
+
+SLOT_INTERFACE_START( cbm_ieee488_devices )
+ SLOT_INTERFACE("c2040", C2040)
+ SLOT_INTERFACE("c3040", C3040)
+ SLOT_INTERFACE("c4040", C4040)
+ SLOT_INTERFACE("c8050", C8050)
+ SLOT_INTERFACE("c8250", C8250)
+ SLOT_INTERFACE("sfd1001", SFD1001)
+ SLOT_INTERFACE("c2031", C2031)
+ SLOT_INTERFACE("c8280", C8280)
+ SLOT_INTERFACE("d9060", D9060)
+ SLOT_INTERFACE("d9090", D9090)
+ SLOT_INTERFACE("softbox", SOFTBOX)
+ SLOT_INTERFACE("hardbox", HARDBOX)
+ SLOT_INTERFACE("shark", SHARK)
+ SLOT_INTERFACE("c4023", C4023)
+SLOT_INTERFACE_END
diff --git a/src/devices/bus/ieee488/ieee488.h b/src/devices/bus/ieee488/ieee488.h
new file mode 100644
index 00000000000..3a6c53966f1
--- /dev/null
+++ b/src/devices/bus/ieee488/ieee488.h
@@ -0,0 +1,253 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ IEEE-488.1 General Purpose Interface Bus emulation
+ (aka HP-IB, GPIB, CBM IEEE)
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __IEEE488__
+#define __IEEE488__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define IEEE488_TAG "ieee_bus"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_IEEE488_BUS_ADD() \
+ MCFG_DEVICE_ADD(IEEE488_TAG, IEEE488, 0)
+
+
+#define MCFG_IEEE488_EOI_CALLBACK(_write) \
+ downcast<ieee488_device *>(device)->set_eoi_callback(DEVCB_##_write);
+
+#define MCFG_IEEE488_DAV_CALLBACK(_write) \
+ downcast<ieee488_device *>(device)->set_dav_callback(DEVCB_##_write);
+
+#define MCFG_IEEE488_NRFD_CALLBACK(_write) \
+ downcast<ieee488_device *>(device)->set_nrfd_callback(DEVCB_##_write);
+
+#define MCFG_IEEE488_NDAC_CALLBACK(_write) \
+ downcast<ieee488_device *>(device)->set_ndac_callback(DEVCB_##_write);
+
+#define MCFG_IEEE488_IFC_CALLBACK(_write) \
+ downcast<ieee488_device *>(device)->set_ifc_callback(DEVCB_##_write);
+
+#define MCFG_IEEE488_SRQ_CALLBACK(_write) \
+ downcast<ieee488_device *>(device)->set_srq_callback(DEVCB_##_write);
+
+#define MCFG_IEEE488_ATN_CALLBACK(_write) \
+ downcast<ieee488_device *>(device)->set_atn_callback(DEVCB_##_write);
+
+#define MCFG_IEEE488_REN_CALLBACK(_write) \
+ downcast<ieee488_device *>(device)->set_ren_callback(DEVCB_##_write);
+
+
+#define MCFG_IEEE488_SLOT_ADD(_tag, _address, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, IEEE488_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
+ downcast<ieee488_slot_device *>(device)->set_address(_address);
+
+
+#define MCFG_CBM_IEEE488_ADD(_default_drive) \
+ MCFG_IEEE488_SLOT_ADD("ieee4", 4, cbm_ieee488_devices, NULL) \
+ MCFG_IEEE488_SLOT_ADD("ieee8", 8, cbm_ieee488_devices, _default_drive) \
+ MCFG_IEEE488_SLOT_ADD("ieee9", 9, cbm_ieee488_devices, NULL) \
+ MCFG_IEEE488_SLOT_ADD("ieee10", 10, cbm_ieee488_devices, NULL) \
+ MCFG_IEEE488_SLOT_ADD("ieee11", 11, cbm_ieee488_devices, NULL) \
+ MCFG_IEEE488_SLOT_ADD("ieee12", 12, cbm_ieee488_devices, NULL) \
+ MCFG_IEEE488_SLOT_ADD("ieee13", 13, cbm_ieee488_devices, NULL) \
+ MCFG_IEEE488_SLOT_ADD("ieee14", 14, cbm_ieee488_devices, NULL) \
+ MCFG_IEEE488_SLOT_ADD("ieee15", 15, cbm_ieee488_devices, NULL) \
+ MCFG_IEEE488_BUS_ADD()
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> ieee488_device
+
+class ieee488_slot_device;
+class device_ieee488_interface;
+
+class ieee488_device : public device_t
+{
+public:
+ // construction/destruction
+ ieee488_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ template<class _write> void set_eoi_callback(_write wr) { m_write_eoi.set_callback(wr); }
+ template<class _write> void set_dav_callback(_write wr) { m_write_dav.set_callback(wr); }
+ template<class _write> void set_nrfd_callback(_write wr) { m_write_nrfd.set_callback(wr); }
+ template<class _write> void set_ndac_callback(_write wr) { m_write_ndac.set_callback(wr); }
+ template<class _write> void set_ifc_callback(_write wr) { m_write_ifc.set_callback(wr); }
+ template<class _write> void set_srq_callback(_write wr) { m_write_srq.set_callback(wr); }
+ template<class _write> void set_atn_callback(_write wr) { m_write_atn.set_callback(wr); }
+ template<class _write> void set_ren_callback(_write wr) { m_write_ren.set_callback(wr); }
+
+ void add_device(ieee488_slot_device *slot, device_t *target);
+
+ // reads for both host and peripherals
+ UINT8 dio_r() { return get_data(); }
+ DECLARE_READ8_MEMBER( dio_r ) { return get_data(); }
+ DECLARE_READ_LINE_MEMBER( eoi_r ) { return get_signal(EOI); }
+ DECLARE_READ_LINE_MEMBER( dav_r ) { return get_signal(DAV); }
+ DECLARE_READ_LINE_MEMBER( nrfd_r ) { return get_signal(NRFD); }
+ DECLARE_READ_LINE_MEMBER( ndac_r ) { return get_signal(NDAC); }
+ DECLARE_READ_LINE_MEMBER( ifc_r ) { return get_signal(IFC); }
+ DECLARE_READ_LINE_MEMBER( srq_r ) { return get_signal(SRQ); }
+ DECLARE_READ_LINE_MEMBER( atn_r ) { return get_signal(ATN); }
+ DECLARE_READ_LINE_MEMBER( ren_r ) { return get_signal(REN); }
+
+ // writes for host (driver_device)
+ void dio_w(UINT8 data) { return set_data(this, data); }
+ DECLARE_WRITE8_MEMBER( dio_w ) { set_data(this, data); }
+ DECLARE_WRITE_LINE_MEMBER( eoi_w ) { set_signal(this, EOI, state); }
+ DECLARE_WRITE_LINE_MEMBER( dav_w ) { set_signal(this, DAV, state); }
+ DECLARE_WRITE_LINE_MEMBER( nrfd_w ) { set_signal(this, NRFD, state); }
+ DECLARE_WRITE_LINE_MEMBER( ndac_w ) { set_signal(this, NDAC, state); }
+ DECLARE_WRITE_LINE_MEMBER( ifc_w ) { set_signal(this, IFC, state); }
+ DECLARE_WRITE_LINE_MEMBER( srq_w ) { set_signal(this, SRQ, state); }
+ DECLARE_WRITE_LINE_MEMBER( atn_w ) { set_signal(this, ATN, state); }
+ DECLARE_WRITE_LINE_MEMBER( ren_w ) { set_signal(this, REN, state); }
+
+ // writes for peripherals (device_t)
+ void dio_w(device_t *device, UINT8 data) { set_data(device, data); }
+ void eoi_w(device_t *device, int state) { set_signal(device, EOI, state); }
+ void dav_w(device_t *device, int state) { set_signal(device, DAV, state); }
+ void nrfd_w(device_t *device, int state) { set_signal(device, NRFD, state); }
+ void ndac_w(device_t *device, int state) { set_signal(device, NDAC, state); }
+ void ifc_w(device_t *device, int state) { set_signal(device, IFC, state); }
+ void srq_w(device_t *device, int state) { set_signal(device, SRQ, state); }
+ void atn_w(device_t *device, int state) { set_signal(device, ATN, state); }
+ void ren_w(device_t *device, int state) { set_signal(device, REN, state); }
+
+protected:
+ enum
+ {
+ EOI = 0,
+ DAV,
+ NRFD,
+ NDAC,
+ IFC,
+ SRQ,
+ ATN,
+ REN,
+ SIGNAL_COUNT
+ };
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_stop();
+
+ class daisy_entry
+ {
+ public:
+ daisy_entry(device_t *device);
+ daisy_entry *next() const { return m_next; }
+
+ daisy_entry * m_next; // next device
+ device_t * m_device; // associated device
+ device_ieee488_interface * m_interface; // associated device's daisy interface
+
+ int m_line[SIGNAL_COUNT];
+ UINT8 m_dio;
+ };
+
+ simple_list<daisy_entry> m_device_list;
+
+private:
+ devcb_write_line m_write_eoi;
+ devcb_write_line m_write_dav;
+ devcb_write_line m_write_nrfd;
+ devcb_write_line m_write_ndac;
+ devcb_write_line m_write_ifc;
+ devcb_write_line m_write_srq;
+ devcb_write_line m_write_atn;
+ devcb_write_line m_write_ren;
+
+ void set_signal(device_t *device, int signal, int state);
+ int get_signal(int signal);
+ void set_data(device_t *device, UINT8 data);
+ UINT8 get_data();
+
+ int m_line[SIGNAL_COUNT];
+ UINT8 m_dio;
+};
+
+
+// ======================> ieee488_slot_device
+
+class ieee488_slot_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ ieee488_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ void set_address(int address) { m_address = address; }
+ int get_address() { return m_address; }
+
+ // device-level overrides
+ virtual void device_start();
+
+protected:
+ int m_address;
+};
+
+
+// ======================> device_ieee488_interface
+
+class device_ieee488_interface : public device_slot_card_interface
+{
+ friend class ieee488_device;
+
+public:
+ // construction/destruction
+ device_ieee488_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_ieee488_interface();
+
+ device_ieee488_interface *next() const { return m_next; }
+ device_ieee488_interface *m_next;
+
+ // optional operation overrides
+ virtual void ieee488_eoi(int state) { };
+ virtual void ieee488_dav(int state) { };
+ virtual void ieee488_nrfd(int state) { };
+ virtual void ieee488_ndac(int state) { };
+ virtual void ieee488_ifc(int state) { };
+ virtual void ieee488_srq(int state) { };
+ virtual void ieee488_atn(int state) { };
+ virtual void ieee488_ren(int state) { };
+
+ ieee488_device *m_bus;
+ ieee488_slot_device *m_slot;
+};
+
+
+// device type definition
+extern const device_type IEEE488;
+extern const device_type IEEE488_SLOT;
+
+
+SLOT_INTERFACE_EXTERN( cbm_ieee488_devices );
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/shark.c b/src/devices/bus/ieee488/shark.c
new file mode 100644
index 00000000000..47582aa42b8
--- /dev/null
+++ b/src/devices/bus/ieee488/shark.c
@@ -0,0 +1,144 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Mator Systems SHARK Intelligent Winchester Disc Subsystem emulation
+
+**********************************************************************/
+
+#include "shark.h"
+#include "bus/rs232/rs232.h"
+#include "cpu/i8085/i8085.h"
+#include "imagedev/harddriv.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define I8085_TAG "i8085"
+#define RS232_TAG "rs232"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type SHARK = &device_creator<mshark_device>;
+
+
+//-------------------------------------------------
+// ROM( mshark )
+//-------------------------------------------------
+
+ROM_START( mshark )
+ ROM_REGION( 0x5000, I8085_TAG, 0 )
+ ROM_LOAD( "pch488 3450 v22.1 #1", 0x0000, 0x1000, CRC(03bff9d7) SHA1(ac506df6509e1b2185a69f9f8f44b8b456aa9834) )
+ ROM_LOAD( "pch488 3450 v22.1 #2", 0x1000, 0x1000, CRC(c14fa5fe) SHA1(bcfd1dd65d692c76b90e6134b85f22c39c049430) )
+ ROM_LOAD( "pch488 3450 v22.1 #3", 0x2000, 0x1000, CRC(4dfaa482) SHA1(fe2c44bb650572616c8bdad6358032fe64b1e363) )
+ ROM_LOAD( "pch488 3450 v22.1 #4", 0x3000, 0x1000, CRC(aef665e9) SHA1(80a4c00b717100b4e22fa3704e34060fffce2bc3) )
+ ROM_LOAD( "pch488 3450 v22.1 #5", 0x4000, 0x1000, CRC(f30adf60) SHA1(96c15264d5a9b52e1d238921880c48a797a6da1e) )
+
+ ROM_REGION( 0x800, "micro", 0 ) // address decoder
+ ROM_LOAD( "micro p3450 v1.3", 0x000, 0x800, CRC(0e69202e) SHA1(3b384951ff54c4b45a3a778a88966d13e2c9d57a) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *mshark_device::device_rom_region() const
+{
+ return ROM_NAME( mshark );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( mshark_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( mshark_mem, AS_PROGRAM, 8, mshark_device )
+ AM_RANGE(0x0000, 0x4fff) AM_ROM AM_REGION(I8085_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( mshark_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( mshark_io, AS_IO, 8, mshark_device )
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( mshark )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( mshark )
+ // basic machine hardware
+ MCFG_CPU_ADD(I8085_TAG, I8085A, 1000000)
+ MCFG_CPU_PROGRAM_MAP(mshark_mem)
+ MCFG_CPU_IO_MAP(mshark_io)
+
+ // devices
+ MCFG_HARDDISK_ADD("harddisk1")
+ MCFG_RS232_PORT_ADD(RS232_TAG, default_rs232_devices, NULL)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor mshark_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( mshark );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( mshark )
+//-------------------------------------------------
+
+INPUT_PORTS_START( mshark )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor mshark_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( mshark );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mshark_device - constructor
+//-------------------------------------------------
+
+mshark_device::mshark_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, SHARK, "Mator SHARK", tag, owner, clock, "mshark", __FILE__),
+ device_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, I8085_TAG)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mshark_device::device_start()
+{
+}
diff --git a/src/devices/bus/ieee488/shark.h b/src/devices/bus/ieee488/shark.h
new file mode 100644
index 00000000000..d5e2f1fe1f8
--- /dev/null
+++ b/src/devices/bus/ieee488/shark.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Mator Systems SHARK Intelligent Winchester Disc Subsystem emulation
+
+ 35MB PRIAM DISKOS 3450 8" Winchester Hard Disk (-chs 525,5,? -ss ?)
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __SHARK__
+#define __SHARK__
+
+#include "ieee488.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mshark_device
+
+class mshark_device : public device_t,
+ public device_ieee488_interface
+{
+public:
+ // construction/destruction
+ mshark_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;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+
+private:
+ required_device<cpu_device> m_maincpu;
+};
+
+
+// device type definition
+extern const device_type SHARK;
+
+
+
+#endif
diff --git a/src/devices/bus/ieee488/softbox.c b/src/devices/bus/ieee488/softbox.c
new file mode 100644
index 00000000000..7f1dfe64b9d
--- /dev/null
+++ b/src/devices/bus/ieee488/softbox.c
@@ -0,0 +1,393 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder, Mike Naberezny
+/**********************************************************************
+
+ SSE SoftBox emulation
+
+**********************************************************************/
+
+/*
+ This is an emulation of the SoftBox as a PET/CBM peripheral, where
+ the PET is used as a terminal over IEEE-488. For the standalone
+ mode where an RS-232 terminal is used, and also information on
+ how to set up the Corvus drive, see: src/mess/drivers/softbox.c.
+*/
+
+
+#include "softbox.h"
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define Z80_TAG "z80"
+#define I8251_TAG "ic15"
+#define I8255_0_TAG "ic17"
+#define I8255_1_TAG "ic16"
+#define COM8116_TAG "ic14"
+#define RS232_TAG "rs232"
+#define CORVUS_HDC_TAG "corvus"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type SOFTBOX = &device_creator<softbox_device>;
+
+
+//-------------------------------------------------
+// ROM( softbox )
+//-------------------------------------------------
+
+ROM_START( softbox )
+ ROM_REGION( 0x1000, Z80_TAG, 0 )
+ ROM_DEFAULT_BIOS("19830609")
+ ROM_SYSTEM_BIOS( 0, "19810908", "8/9/81" )
+ ROMX_LOAD( "375.ic3", 0x000, 0x800, CRC(177580e7) SHA1(af6a97495de825b80cdc9fbf72329d5440826177), ROM_BIOS(1) )
+ ROMX_LOAD( "376.ic4", 0x800, 0x800, CRC(edfee5be) SHA1(5662e9071cc622a1c071d89b00272fc6ba122b9a), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "19811027", "27-Oct-81" )
+ ROMX_LOAD( "379.ic3", 0x000, 0x800, CRC(7b5a737c) SHA1(2348590884b026b7647f6864af8c9ba1c6f8746b), ROM_BIOS(2) )
+ ROMX_LOAD( "380.ic4", 0x800, 0x800, CRC(65a13029) SHA1(46de02e6f04be298047efeb412e00a5714dc21b3), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 2, "19830609", "09-June-1983" )
+ ROMX_LOAD( "389.ic3", 0x000, 0x800, CRC(d66e581a) SHA1(2403e25c140c41b0e6d6975d39c9cd9d6f335048), ROM_BIOS(3) )
+ ROMX_LOAD( "390.ic4", 0x800, 0x800, CRC(abe6cb30) SHA1(4b26d5db36f828e01268f718799f145d09b449ad), ROM_BIOS(3) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *softbox_device::device_rom_region() const
+{
+ return ROM_NAME( softbox );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( softbox_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( softbox_mem, AS_PROGRAM, 8, softbox_device )
+ AM_RANGE(0x0000, 0xefff) AM_RAM
+ AM_RANGE(0xf000, 0xffff) AM_ROM AM_REGION(Z80_TAG, 0)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( softbox_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( softbox_io, AS_IO, 8, softbox_device )
+ ADDRESS_MAP_GLOBAL_MASK(0xff)
+ AM_RANGE(0x08, 0x08) AM_DEVREADWRITE(I8251_TAG, i8251_device, data_r, data_w)
+ AM_RANGE(0x09, 0x09) AM_DEVREADWRITE(I8251_TAG, i8251_device, status_r, control_w)
+ AM_RANGE(0x0c, 0x0c) AM_WRITE(dbrg_w)
+ AM_RANGE(0x10, 0x13) AM_DEVREADWRITE(I8255_0_TAG, i8255_device, read, write)
+ AM_RANGE(0x14, 0x17) AM_DEVREADWRITE(I8255_1_TAG, i8255_device, read, write)
+ AM_RANGE(0x18, 0x18) AM_DEVREADWRITE(CORVUS_HDC_TAG, corvus_hdc_t, read, write)
+ADDRESS_MAP_END
+
+
+
+//-------------------------------------------------
+// I8255A 0 Interface
+//-------------------------------------------------
+
+READ8_MEMBER( softbox_device::ppi0_pa_r )
+{
+ return m_bus->dio_r() ^ 0xff;
+}
+
+WRITE8_MEMBER( softbox_device::ppi0_pb_w )
+{
+ m_bus->dio_w(this, data ^ 0xff);
+}
+
+//-------------------------------------------------
+// I8255A 1 Interface
+//-------------------------------------------------
+
+READ8_MEMBER( softbox_device::ppi1_pa_r )
+{
+ /*
+
+ bit description
+
+ PA0 ATN
+ PA1 DAV
+ PA2 NDAC
+ PA3 NRFD
+ PA4 EOI
+ PA5 SRQ
+ PA6 REN
+ PA7 IFC
+
+ */
+
+ UINT8 data = 0;
+
+ data |= !m_bus->atn_r();
+ data |= !m_bus->dav_r() << 1;
+ data |= !m_bus->ndac_r() << 2;
+ data |= !m_bus->nrfd_r() << 3;
+ data |= !m_bus->eoi_r() << 4;
+ data |= !m_bus->srq_r() << 5;
+ data |= !m_bus->ren_r() << 6;
+ data |= !m_bus->ifc_r() << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( softbox_device::ppi1_pb_w )
+{
+ /*
+
+ bit description
+
+ PB0 ATN
+ PB1 DAV
+ PB2 NDAC
+ PB3 NRFD
+ PB4 EOI
+ PB5 SRQ
+ PB6 REN
+ PB7 IFC
+
+ */
+
+ m_bus->atn_w(this, !BIT(data, 0));
+ m_bus->dav_w(this, !BIT(data, 1));
+ m_bus->ndac_w(this, !BIT(data, 2));
+ m_bus->nrfd_w(this, !BIT(data, 3));
+ m_bus->eoi_w(this, !BIT(data, 4));
+ m_bus->srq_w(this, !BIT(data, 5));
+ m_bus->ren_w(this, !BIT(data, 6));
+ m_bus->ifc_w(this, !BIT(data, 7));
+}
+
+READ8_MEMBER( softbox_device::ppi1_pc_r )
+{
+ /*
+
+ bit description
+
+ PC0
+ PC1
+ PC2
+ PC3
+ PC4 Corvus READY
+ PC5 Corvus DIRC
+ PC6
+ PC7
+
+ */
+
+ UINT8 status = m_hdc->status_r(space, 0);
+ UINT8 data = 0;
+
+ data |= (status & CONTROLLER_BUSY) ? 0 : 0x10;
+ data |= (status & CONTROLLER_DIRECTION) ? 0 : 0x20;
+
+ return data;
+}
+
+WRITE8_MEMBER( softbox_device::ppi1_pc_w )
+{
+ /*
+
+ bit description
+
+ PC0 LED "A"
+ PC1 LED "B"
+ PC2 LED "READY"
+ PC3
+ PC4
+ PC5
+ PC6
+ PC7
+
+ */
+
+ output_set_led_value(LED_A, !BIT(data, 0));
+ output_set_led_value(LED_B, !BIT(data, 1));
+ output_set_led_value(LED_READY, !BIT(data, 2));
+}
+
+static DEVICE_INPUT_DEFAULTS_START( terminal )
+ DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 )
+ DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 )
+ DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
+ DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_7 )
+ DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_EVEN )
+ DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
+DEVICE_INPUT_DEFAULTS_END
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( softbox )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( softbox )
+ // basic machine hardware
+ MCFG_CPU_ADD(Z80_TAG, Z80, XTAL_8MHz/2)
+ MCFG_CPU_PROGRAM_MAP(softbox_mem)
+ MCFG_CPU_IO_MAP(softbox_io)
+
+ // devices
+ MCFG_DEVICE_ADD(I8251_TAG, I8251, 0)
+ MCFG_I8251_TXD_HANDLER(DEVWRITELINE(RS232_TAG, rs232_port_device, write_txd))
+ MCFG_I8251_DTR_HANDLER(DEVWRITELINE(RS232_TAG, rs232_port_device, write_dtr))
+ MCFG_I8251_RTS_HANDLER(DEVWRITELINE(RS232_TAG, rs232_port_device, write_rts))
+
+ MCFG_RS232_PORT_ADD(RS232_TAG, default_rs232_devices, NULL)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_rxd))
+ MCFG_RS232_DSR_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_dsr))
+ MCFG_DEVICE_CARD_DEVICE_INPUT_DEFAULTS("terminal", terminal)
+
+ MCFG_DEVICE_ADD(I8255_0_TAG, I8255A, 0)
+ MCFG_I8255_IN_PORTA_CB(READ8(softbox_device, ppi0_pa_r))
+ MCFG_I8255_OUT_PORTB_CB(WRITE8(softbox_device, ppi0_pb_w))
+ MCFG_I8255_IN_PORTC_CB(IOPORT("SW1"))
+
+ MCFG_DEVICE_ADD(I8255_1_TAG, I8255A, 0)
+ MCFG_I8255_IN_PORTA_CB(READ8(softbox_device, ppi1_pa_r))
+ MCFG_I8255_OUT_PORTB_CB(WRITE8(softbox_device, ppi1_pb_w))
+ MCFG_I8255_IN_PORTC_CB(READ8(softbox_device, ppi1_pc_r))
+ MCFG_I8255_OUT_PORTC_CB(WRITE8(softbox_device, ppi1_pc_w))
+
+ MCFG_DEVICE_ADD(COM8116_TAG, COM8116, XTAL_5_0688MHz)
+ MCFG_COM8116_FR_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_rxc))
+ MCFG_COM8116_FT_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_txc))
+
+ MCFG_DEVICE_ADD(CORVUS_HDC_TAG, CORVUS_HDC, 0)
+ MCFG_HARDDISK_ADD("harddisk1")
+ MCFG_HARDDISK_INTERFACE("corvus_hdd")
+ MCFG_HARDDISK_ADD("harddisk2")
+ MCFG_HARDDISK_INTERFACE("corvus_hdd")
+ MCFG_HARDDISK_ADD("harddisk3")
+ MCFG_HARDDISK_INTERFACE("corvus_hdd")
+ MCFG_HARDDISK_ADD("harddisk4")
+ MCFG_HARDDISK_INTERFACE("corvus_hdd")
+ //MCFG_IMI7000_BUS_ADD("imi5000h", NULL, NULL, NULL)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor softbox_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( softbox );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( softbox )
+//-------------------------------------------------
+
+INPUT_PORTS_START( softbox )
+ /* An 8-position DIP switch may be installed at SW1. Some
+ SoftBox units have it and some do not. The switches are
+ not used by the SoftBox BIOS. */
+ PORT_START("SW1")
+ PORT_DIPUNUSED_DIPLOC( 0x01, IP_ACTIVE_LOW, "SW1:1" )
+ PORT_DIPUNUSED_DIPLOC( 0x02, IP_ACTIVE_LOW, "SW1:2" )
+ PORT_DIPUNUSED_DIPLOC( 0x04, IP_ACTIVE_LOW, "SW1:3" )
+ PORT_DIPUNUSED_DIPLOC( 0x08, IP_ACTIVE_LOW, "SW1:4" )
+ PORT_DIPUNUSED_DIPLOC( 0x10, IP_ACTIVE_LOW, "SW1:5" )
+ PORT_DIPUNUSED_DIPLOC( 0x20, IP_ACTIVE_LOW, "SW1:6" )
+ PORT_DIPUNUSED_DIPLOC( 0x40, IP_ACTIVE_LOW, "SW1:7" )
+ PORT_DIPUNUSED_DIPLOC( 0x80, IP_ACTIVE_LOW, "SW1:8" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor softbox_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( softbox );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// softbox_device - constructor
+//-------------------------------------------------
+
+softbox_device::softbox_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, SOFTBOX, "PET SoftBox", tag, owner, clock, "pet_softbox", __FILE__),
+ device_ieee488_interface(mconfig, *this),
+ m_maincpu(*this, Z80_TAG),
+ m_dbrg(*this, COM8116_TAG),
+ m_hdc(*this, CORVUS_HDC_TAG)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void softbox_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset_after_children - device-specific
+// reset that must happen after child devices
+// have performed their resets
+//-------------------------------------------------
+
+void softbox_device::device_reset_after_children()
+{
+ /* The Z80 starts at address 0x0000 but the SoftBox has RAM there and
+ needs to start from the BIOS at 0xf000. The PCB has logic and a
+ 74S287 PROM that temporarily changes the memory map so that the
+ IC3 EPROM at 0xf000 is mapped to 0x0000 for the first instruction
+ fetch only. The instruction normally at 0xf000 is an absolute jump
+ into the BIOS. On reset, the Z80 will fetch it from 0x0000 and set
+ its PC, then the normal map will be restored before the next
+ instruction fetch. Here we just set the PC to 0xf000 after the Z80
+ resets, which has the same effect. */
+
+ m_maincpu->set_state_int(Z80_PC, 0xf000);
+}
+
+
+//-------------------------------------------------
+// ieee488_ifc - interface clear (reset)
+//-------------------------------------------------
+
+void softbox_device::ieee488_ifc(int state)
+{
+ if (!m_ifc && state)
+ {
+ device_reset();
+ }
+
+ m_ifc = state;
+}
+
+
+//-------------------------------------------------
+// dbrg_w - baud rate selection
+//-------------------------------------------------
+
+WRITE8_MEMBER( softbox_device::dbrg_w )
+{
+ m_dbrg->str_w(data & 0x0f);
+ m_dbrg->stt_w(data >> 4);
+}
diff --git a/src/devices/bus/ieee488/softbox.h b/src/devices/bus/ieee488/softbox.h
new file mode 100644
index 00000000000..97e729fcc8d
--- /dev/null
+++ b/src/devices/bus/ieee488/softbox.h
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder, Mike Naberezny
+/**********************************************************************
+
+ SSE SoftBox emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __PET_SOFTBOX__
+#define __PET_SOFTBOX__
+
+#include "ieee488.h"
+#include "bus/rs232/rs232.h"
+#include "cpu/z80/z80.h"
+#include "imagedev/harddriv.h"
+#include "machine/corvushd.h"
+#include "machine/com8116.h"
+#include "machine/i8251.h"
+#include "machine/i8255.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> softbox_device
+
+class softbox_device : public device_t,
+ public device_ieee488_interface
+{
+public:
+ // construction/destruction
+ softbox_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;
+
+ DECLARE_WRITE8_MEMBER( dbrg_w );
+
+ DECLARE_READ8_MEMBER( ppi0_pa_r );
+ DECLARE_WRITE8_MEMBER( ppi0_pb_w );
+
+ DECLARE_READ8_MEMBER( ppi1_pa_r );
+ DECLARE_WRITE8_MEMBER( ppi1_pb_w );
+ DECLARE_READ8_MEMBER( ppi1_pc_r );
+ DECLARE_WRITE8_MEMBER( ppi1_pc_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset_after_children();
+
+ // device_ieee488_interface overrides
+ virtual void ieee488_ifc(int state);
+
+private:
+ enum
+ {
+ LED_A,
+ LED_B,
+ LED_READY
+ };
+
+ required_device<cpu_device> m_maincpu;
+ required_device<com8116_device> m_dbrg;
+ required_device<corvus_hdc_t> m_hdc;
+
+ int m_ifc; // Tracks previous state of IEEE-488 IFC line
+};
+
+
+// device type definition
+extern const device_type SOFTBOX;
+
+
+
+#endif