diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index eb3da56b646..7e0408caa1a 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2396,6 +2396,7 @@ if (BUSES["COCO"]~=null) then MAME_DIR .. "src/devices/bus/coco/coco_multi.h", MAME_DIR .. "src/devices/bus/coco/coco_dwsock.cpp", MAME_DIR .. "src/devices/bus/coco/coco_dwsock.h", + MAME_DIR .. "src/devices/bus/coco/dragon_fdc.cpp", } end diff --git a/src/devices/bus/coco/coco_fdc.cpp b/src/devices/bus/coco/coco_fdc.cpp index 52c31c0d71d..ba14e70470d 100644 --- a/src/devices/bus/coco/coco_fdc.cpp +++ b/src/devices/bus/coco/coco_fdc.cpp @@ -2,16 +2,16 @@ // copyright-holders:Nathan Woods /********************************************************************* - coco_fdc.c + coco_fdc.cpp - CoCo/Dragon FDC + CoCo Floppy Disk Controller The CoCo and Dragon both use the Western Digital floppy disk controllers. The CoCo uses either the WD1793 or the WD1773, the Dragon uses the WD2797, which mostly uses the same command set with some subtle differences, most notably the 2797 handles disk side select internally. The Dragon Alpha also uses the WD2797, however as this is a built in interface and not an external - cartrige, it is dealt with in the main coco.c file. + cartrige, it is dealt with in the main coco.cpp file. The wd's variables are mapped to $FF48-$FF4B on the CoCo and on $FF40-$FF43 on the Dragon. In addition, there is another register @@ -26,53 +26,30 @@ --------------------------------------------------------------------------- DSKREG - the control register - CoCo ($FF40) Dragon ($FF48) + CoCo ($FF40) - Bit Bit - 7 halt enable flag 7 not used - 6 drive select #3 6 not used - 5 density (0=single, 1=double) 5 NMI enable flag - and NMI enable flag - 4 write precompensation 4 write precompensation - 3 drive motor activation 3 single density enable - 2 drive select #2 2 drive motor activation - 1 drive select #1 1 drive select high bit - 0 drive select #0 0 drive select low bit + Bit + 7 halt enable flag + 6 drive select #3 + 5 density (0=single, 1=double) and NMI enable flag + 4 write precompensation + 3 drive motor activation + 2 drive select #2 + 1 drive select #1 + 0 drive select #0 Reading from $FF48-$FF4F clears bit 7 of DSKREG ($FF40) - --------------------------------------------------------------------------- - - 2007-02-22, P.Harvey-Smith - - Began implementing the Dragon Delta Dos controller, this was actually the first - Dragon disk controller to market, beating Dragon Data's by a couple of months, - it is based around the WD2791 FDC, which is compatible with the WD1793/WD2797 used - by the standard CoCo and Dragon disk controllers except that it used an inverted - data bus, which is the reason the read/write handlers invert the data. This - controller like, the DragonDos WD2797 is mapped at $FF40-$FF43, in the normal - register order. - - The Delta cart also has a register (74LS174 hex flipflop) at $FF44 encoded as - follows :- - - Bit - 7 not used - 6 not used - 5 not used - 4 Single (0) / Double (1) density select - 3 5.25"(0) / 8"(1) Clock select - 2 Side select - 1 Drive select ms bit - 0 Drive select ls bit - *********************************************************************/ #include "emu.h" +#include "cococart.h" #include "coco_fdc.h" #include "imagedev/flopdrv.h" #include "includes/coco.h" -#include "imagedev/flopdrv.h" +#include "machine/msm6242.h" +#include "machine/ds1315.h" +#include "machine/wd_fdc.h" #include "formats/dmk_dsk.h" #include "formats/jvc_dsk.h" #include "formats/vdk_dsk.h" @@ -88,15 +65,53 @@ #define DISTO_TAG "disto" #define CLOUD9_TAG "cloud9" + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ +class coco_fdc_device_base : public coco_family_fdc_device_base +{ +public: + // construction/destruction + coco_fdc_device_base(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + +protected: + enum class rtc_type + { + DISTO = 0x00, + CLOUD9 = 0x01, + NONE = 0xFF + }; + + // device-level overrides + virtual DECLARE_READ8_MEMBER(read) override; + virtual DECLARE_WRITE8_MEMBER(write) override; + virtual machine_config_constructor device_mconfig_additions() const override; + + // methods + virtual void update_lines() override; + void dskreg_w(UINT8 data); + rtc_type real_time_clock(); + + // devices + required_device m_wd17xx; + required_device m_ds1315; + required_device_array m_floppies; + + // Disto RTC + required_device m_disto_msm6242; // 6242 RTC on Disto interface + offs_t m_msm6242_rtc_address; + optional_ioport m_rtc; +}; + + + /*************************************************************************** LOCAL VARIABLES ***************************************************************************/ -FLOPPY_FORMATS_MEMBER( coco_fdc_device::floppy_formats ) +FLOPPY_FORMATS_MEMBER( coco_family_fdc_device_base::floppy_formats ) FLOPPY_DMK_FORMAT, FLOPPY_JVC_FORMAT, FLOPPY_VDK_FORMAT @@ -106,166 +121,132 @@ static SLOT_INTERFACE_START( coco_fdc_floppies ) SLOT_INTERFACE("qd", FLOPPY_525_QD) SLOT_INTERFACE_END - -/*************************************************************************** - IMPLEMENTATION -***************************************************************************/ -/*------------------------------------------------- - real_time_clock --------------------------------------------------*/ - -coco_rtc_type_t coco_fdc_device::real_time_clock() -{ - coco_rtc_type_t result = coco_rtc_type_t(m_rtc.read_safe(RTC_NONE)); - - /* check to make sure we don't have any invalid values */ - if (((result == RTC_DISTO) && (m_disto_msm6242 == nullptr)) - || ((result == RTC_CLOUD9) && (m_ds1315 == nullptr))) - { - result = RTC_NONE; - } - - return result; -} -/*------------------------------------------------- - fdc_intrq_w - callback from the FDC --------------------------------------------------*/ - -WRITE_LINE_MEMBER( coco_fdc_device::fdc_intrq_w ) -{ - set_intrq(state); - update_lines(); -} - - -/*------------------------------------------------- - fdc_drq_w - callback from the FDC --------------------------------------------------*/ - -WRITE_LINE_MEMBER( coco_fdc_device::fdc_drq_w ) -{ - set_drq(state); - update_lines(); -} - - -//************************************************************************** -// COCO FDC -//************************************************************************** - static MACHINE_CONFIG_FRAGMENT(coco_fdc) MCFG_WD1773_ADD(WD_TAG, XTAL_8MHz) - MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(coco_fdc_device, fdc_intrq_w)) - MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(coco_fdc_device, fdc_drq_w)) + MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(coco_fdc_device_base, fdc_intrq_w)) + MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(coco_fdc_device_base, fdc_drq_w)) - MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":0", coco_fdc_floppies, "qd", coco_fdc_device::floppy_formats) - MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":1", coco_fdc_floppies, "qd", coco_fdc_device::floppy_formats) - MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":2", coco_fdc_floppies, "", coco_fdc_device::floppy_formats) - MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":3", coco_fdc_floppies, "", coco_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":0", coco_fdc_floppies, "qd", coco_fdc_device_base::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":1", coco_fdc_floppies, "qd", coco_fdc_device_base::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":2", coco_fdc_floppies, "", coco_fdc_device_base::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":3", coco_fdc_floppies, "", coco_fdc_device_base::floppy_formats) MCFG_DEVICE_ADD(DISTO_TAG, MSM6242, XTAL_32_768kHz) MCFG_DS1315_ADD(CLOUD9_TAG) MACHINE_CONFIG_END -ROM_START( coco_fdc ) - ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00) - ROM_LOAD_OPTIONAL( "disk10.rom", 0x0000, 0x2000, CRC(b4f9968e) SHA1(04115be3f97952b9d9310b52f806d04f80b40d03)) -ROM_END -const device_type COCO_FDC = &device_creator; +//*************************************************************************** +// COCO FAMILY FDCs - base class for CoCo/Dragon +//*************************************************************************** //------------------------------------------------- -// coco_fdc_device - constructor +// coco_family_fdc_device_base::device_start //------------------------------------------------- -coco_fdc_device::coco_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : device_t(mconfig, type, name, tag, owner, clock, shortname, source), - device_cococart_interface( mconfig, *this ), m_owner(nullptr), m_dskreg(0), m_drq(0), m_intrq(0), - m_wd17xx(*this, WD_TAG), - m_wd2797(*this, WD2797_TAG), - m_ds1315(*this, CLOUD9_TAG), - m_disto_msm6242(*this, DISTO_TAG), m_msm6242_rtc_address(0), - m_rtc(*this, ":real_time_clock") + +void coco_family_fdc_device_base::device_start() { + save_item(NAME(m_dskreg)); + save_item(NAME(m_intrq)); + save_item(NAME(m_drq)); } -coco_fdc_device::coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, COCO_FDC, "CoCo FDC", tag, owner, clock, "coco_fdc", __FILE__), - device_cococart_interface( mconfig, *this ), m_owner(nullptr), m_dskreg(0), m_drq(0), m_intrq(0), - m_wd17xx(*this, WD_TAG), - m_wd2797(*this, WD2797_TAG), - m_ds1315(*this, CLOUD9_TAG), - m_disto_msm6242(*this, DISTO_TAG), m_msm6242_rtc_address(0), - m_rtc(*this, ":real_time_clock") + +//------------------------------------------------- +// coco_family_fdc_device_base::device_reset +//------------------------------------------------- + +void coco_family_fdc_device_base::device_reset() +{ + m_dskreg = 0x00; + m_intrq = false; + m_drq = true; +} + + +//------------------------------------------------- +// coco_family_fdc_device_base::get_cart_base +//------------------------------------------------- + +UINT8* coco_family_fdc_device_base::get_cart_base() +{ + return memregion("eprom")->base(); +} + + +//*************************************************************************** +// COCO FDCs +//*************************************************************************** + +//------------------------------------------------- +// coco_fdc_device_base - constructor +//------------------------------------------------- + +coco_fdc_device_base::coco_fdc_device_base(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : coco_family_fdc_device_base(mconfig, type, name, tag, owner, clock, shortname, source) + , m_wd17xx(*this, WD_TAG) + , m_ds1315(*this, CLOUD9_TAG) + , m_floppies(*this, WD_TAG ":%u", 0) + , m_disto_msm6242(*this, DISTO_TAG) + , m_msm6242_rtc_address(0) + , m_rtc(*this, ":real_time_clock") { } //------------------------------------------------- -// device_start - device-specific startup +// real_time_clock //------------------------------------------------- -void coco_fdc_device::device_start() +coco_fdc_device_base::rtc_type coco_fdc_device_base::real_time_clock() { - m_owner = dynamic_cast(owner()); - m_drq = 1; - m_dskreg = 0x00; - m_intrq = 0; - m_msm6242_rtc_address = 0; + rtc_type result = (rtc_type) m_rtc.read_safe((ioport_value) rtc_type::NONE); + + // check to make sure we don't have any invalid values + if (((result == rtc_type::DISTO) && (m_disto_msm6242 == nullptr)) + || ((result == rtc_type::CLOUD9) && (m_ds1315 == nullptr))) + { + result = rtc_type::NONE; + } + + return result; } + //------------------------------------------------- // machine_config_additions - device-specific // machine configurations //------------------------------------------------- -machine_config_constructor coco_fdc_device::device_mconfig_additions() const +machine_config_constructor coco_fdc_device_base::device_mconfig_additions() const { - return MACHINE_CONFIG_NAME( coco_fdc ); + return MACHINE_CONFIG_NAME(coco_fdc); } + //------------------------------------------------- -// rom_region - device-specific ROM region +// update_lines - CoCo specific disk +// controller lines //------------------------------------------------- -const tiny_rom_entry *coco_fdc_device::device_rom_region() const +void coco_fdc_device_base::update_lines() { - return ROM_NAME( coco_fdc ); + // clear HALT enable under certain circumstances + if (intrq() && (dskreg() & 0x20)) + set_dskreg(dskreg() & ~0x80); // clear halt enable + + // set the NMI line + cart_set_line(cococart_slot_device::line::NMI, intrq() && (dskreg() & 0x20)); + + // set the HALT line + cart_set_line(cococart_slot_device::line::HALT, !drq() && (dskreg() & 0x80)); } -/*------------------------------------------------- - get_cart_base --------------------------------------------------*/ -UINT8* coco_fdc_device::get_cart_base() -{ - return memregion("eprom")->base(); -} +//------------------------------------------------- +// dskreg_w - function to write to CoCo dskreg +//------------------------------------------------- -/*------------------------------------------------- - update_lines - CoCo specific disk - controller lines --------------------------------------------------*/ - -void coco_fdc_device::update_lines() -{ - /* clear HALT enable under certain circumstances */ - if ((m_intrq != 0) && (m_dskreg & 0x20)) - m_dskreg &= ~0x80; /* clear halt enable */ - - /* set the NMI line */ - m_owner->cart_set_line(cococart_slot_device::line::NMI, - ((m_intrq != 0) && (m_dskreg & 0x20)) ? cococart_slot_device::line_value::ASSERT : cococart_slot_device::line_value::CLEAR); - - /* set the HALT line */ - m_owner->cart_set_line(cococart_slot_device::line::HALT, - ((m_drq == 0) && (m_dskreg & 0x80)) ? cococart_slot_device::line_value::ASSERT : cococart_slot_device::line_value::CLEAR); -} - -/*------------------------------------------------- - dskreg_w - function to write to CoCo - dskreg --------------------------------------------------*/ - -void coco_fdc_device::dskreg_w(UINT8 data) +void coco_fdc_device_base::dskreg_w(UINT8 data) { UINT8 drive = 0; UINT8 head; @@ -300,38 +281,34 @@ void coco_fdc_device::dskreg_w(UINT8 data) else if (data & 0x40) drive = 3; - floppy_image_device *floppy[4]; - - floppy[0] = subdevice(WD_TAG ":0")->get_device(); - floppy[1] = subdevice(WD_TAG ":1")->get_device(); - floppy[2] = subdevice(WD_TAG ":2")->get_device(); - floppy[3] = subdevice(WD_TAG ":3")->get_device(); - for (int i = 0; i < 4; i++) { - if (floppy[i]) - floppy[i]->mon_w(i == drive ? CLEAR_LINE : ASSERT_LINE); + floppy_image_device *floppy = m_floppies[i]->get_device(); + if (floppy) + floppy->mon_w(i == drive ? CLEAR_LINE : ASSERT_LINE); } head = ((data & 0x40) && (drive != 3)) ? 1 : 0; - m_dskreg = data; + set_dskreg(data); update_lines(); - m_wd17xx->set_floppy(floppy[drive]); + floppy_image_device *selected_floppy = m_floppies[drive]->get_device(); + m_wd17xx->set_floppy(selected_floppy); - if (floppy[drive]) - floppy[drive]->ss_w(head); + if (selected_floppy) + selected_floppy->ss_w(head); - m_wd17xx->dden_w(!BIT(m_dskreg, 5)); + m_wd17xx->dden_w(!BIT(dskreg(), 5)); } -/*------------------------------------------------- - read --------------------------------------------------*/ -READ8_MEMBER(coco_fdc_device::read) +//------------------------------------------------- +// read +//------------------------------------------------- + +READ8_MEMBER(coco_fdc_device_base::read) { UINT8 result = 0; @@ -355,22 +332,22 @@ READ8_MEMBER(coco_fdc_device::read) switch(offset) { case 0x10: /* FF50 */ - if (real_time_clock() == RTC_DISTO) + if (real_time_clock() == rtc_type::DISTO) result = m_disto_msm6242->read(space,m_msm6242_rtc_address); break; case 0x38: /* FF78 */ - if (real_time_clock() == RTC_CLOUD9) + if (real_time_clock() == rtc_type::CLOUD9) m_ds1315->read_0(space, offset); break; case 0x39: /* FF79 */ - if (real_time_clock() == RTC_CLOUD9) + if (real_time_clock() == rtc_type::CLOUD9) m_ds1315->read_1(space, offset); break; case 0x3C: /* FF7C */ - if (real_time_clock() == RTC_CLOUD9) + if (real_time_clock() == rtc_type::CLOUD9) result = m_ds1315->read_data(space, offset); break; } @@ -379,11 +356,11 @@ READ8_MEMBER(coco_fdc_device::read) -/*------------------------------------------------- - write --------------------------------------------------*/ +//------------------------------------------------- +// write +//------------------------------------------------- -WRITE8_MEMBER(coco_fdc_device::write) +WRITE8_MEMBER(coco_fdc_device_base::write) { switch(offset & 0x1F) { @@ -410,12 +387,12 @@ WRITE8_MEMBER(coco_fdc_device::write) switch(offset) { case 0x10: /* FF50 */ - if (real_time_clock() == RTC_DISTO) + if (real_time_clock() == rtc_type::DISTO) m_disto_msm6242->write(space,m_msm6242_rtc_address, data); break; case 0x11: /* FF51 */ - if (real_time_clock() == RTC_DISTO) + if (real_time_clock() == rtc_type::DISTO) m_msm6242_rtc_address = data & 0x0f; break; } @@ -423,293 +400,134 @@ WRITE8_MEMBER(coco_fdc_device::write) //************************************************************************** -// DRAGON FDC +// COCO FDC //************************************************************************** -static MACHINE_CONFIG_FRAGMENT(dragon_fdc) - MCFG_WD2797_ADD(WD2797_TAG, XTAL_1MHz) - - MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":0", coco_fdc_floppies, "qd", coco_fdc_device::floppy_formats) - MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":1", coco_fdc_floppies, "qd", coco_fdc_device::floppy_formats) - MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":2", coco_fdc_floppies, "", coco_fdc_device::floppy_formats) - MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":3", coco_fdc_floppies, "", coco_fdc_device::floppy_formats) -MACHINE_CONFIG_END - - -ROM_START( dragon_fdc ) - ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00) - ROM_LOAD_OPTIONAL( "ddos10.rom", 0x0000, 0x2000, CRC(b44536f6) SHA1(a8918c71d319237c1e3155bb38620acb114a80bc)) +ROM_START(coco_fdc) + ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00) + ROM_LOAD_OPTIONAL("disk10.rom", 0x0000, 0x2000, CRC(b4f9968e) SHA1(04115be3f97952b9d9310b52f806d04f80b40d03)) ROM_END -const device_type DRAGON_FDC = &device_creator; - -//------------------------------------------------- -// dragon_fdc_device - constructor -//------------------------------------------------- -dragon_fdc_device::dragon_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : coco_fdc_device(mconfig, type, name, tag, owner, clock, shortname, source) +namespace { -} -dragon_fdc_device::dragon_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : coco_fdc_device(mconfig, DRAGON_FDC, "Dragon FDC", tag, owner, clock, "dragon_fdc", __FILE__) -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void dragon_fdc_device::device_start() -{ - m_owner = dynamic_cast(owner()); - m_drq = 0; - m_dskreg = 0x00; - m_intrq = 0; - m_msm6242_rtc_address = 0; -} - -//------------------------------------------------- -// machine_config_additions - device-specific -// machine configurations -//------------------------------------------------- - -machine_config_constructor dragon_fdc_device::device_mconfig_additions() const -{ - return MACHINE_CONFIG_NAME( dragon_fdc ); -} - -//------------------------------------------------- -// rom_region - device-specific ROM region -//------------------------------------------------- - -const tiny_rom_entry *dragon_fdc_device::device_rom_region() const -{ - return ROM_NAME( dragon_fdc ); -} - - - -/*------------------------------------------------- - update_lines - Dragon specific disk - controller lines --------------------------------------------------*/ - -void dragon_fdc_device::update_lines() -{ - /* set the NMI line */ - m_owner->cart_set_line(cococart_slot_device::line::NMI, - ((m_intrq != 0) && (m_dskreg & 0x20)) ? cococart_slot_device::line_value::ASSERT : cococart_slot_device::line_value::CLEAR); - - /* set the CART line */ - m_owner->cart_set_line(cococart_slot_device::line::CART, - (m_drq != 0) ? cococart_slot_device::line_value::ASSERT : cococart_slot_device::line_value::CLEAR); -} - - -/*------------------------------------------------- - dskreg_w - function to write to - Dragon dskreg --------------------------------------------------*/ - -void dragon_fdc_device::dskreg_w(UINT8 data) -{ - if (LOG_FDC) + class coco_fdc_device : public coco_fdc_device_base { - logerror("fdc_dragon_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n", - data & 0x80 ? 'X' : 'x', - data & 0x40 ? 'X' : 'x', - data & 0x20 ? 'N' : 'n', - data & 0x10 ? 'P' : 'p', - data & 0x08 ? 'S' : 'D', - data & 0x04 ? 'M' : 'm', - data & 0x02 ? '1' : '0', - data & 0x01 ? '1' : '0', - data); - } + public: + // construction/destruction + coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : coco_fdc_device_base(mconfig, COCO_FDC, "CoCo FDC", tag, owner, clock, "coco_fdc", __FILE__) + { + } - floppy_image_device *floppy = nullptr; + protected: + // optional information overrides + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME(coco_fdc); + } - switch (data & 0x03) - { - case 0: floppy = subdevice(WD2797_TAG ":0")->get_device(); break; - case 1: floppy = subdevice(WD2797_TAG ":1")->get_device(); break; - case 2: floppy = subdevice(WD2797_TAG ":2")->get_device(); break; - case 3: floppy = subdevice(WD2797_TAG ":3")->get_device(); break; - } - - m_wd2797->set_floppy(floppy); - - m_wd2797->dden_w(BIT(data, 3)); - - m_dskreg = data; -} - - - -/*------------------------------------------------- - read --------------------------------------------------*/ - -READ8_MEMBER(dragon_fdc_device::read) -{ - UINT8 result = 0; - switch(offset & 0xEF) - { - case 0: - result = m_wd2797->status_r(space, 0); - break; - case 1: - result = m_wd2797->track_r(space, 0); - break; - case 2: - result = m_wd2797->sector_r(space, 0); - break; - case 3: - result = m_wd2797->data_r(space, 0); - break; - } - return result; -} - - - -/*------------------------------------------------- - write --------------------------------------------------*/ - -WRITE8_MEMBER(dragon_fdc_device::write) -{ - switch(offset & 0xEF) - { - case 0: - m_wd2797->cmd_w(space, 0, data); - break; - case 1: - m_wd2797->track_w(space, 0, data); - break; - case 2: - m_wd2797->sector_w(space, 0, data); - break; - case 3: - m_wd2797->data_w(space, 0, data); - break; - case 8: case 9: case 10: case 11: - case 12: case 13: case 14: case 15: - dskreg_w(data); - break; }; + } +const device_type COCO_FDC = &device_creator; -//************************************************************************** -// SDTANDY FDC -//************************************************************************** - -ROM_START( sdtandy_fdc ) - ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00) - ROM_LOAD_OPTIONAL( "sdtandy.rom", 0x0000, 0x2000, CRC(5d7779b7) SHA1(ca03942118f2deab2f6c8a89b8a4f41f2d0b94f1)) -ROM_END - -const device_type SDTANDY_FDC = &device_creator; - -//------------------------------------------------- -// sdtandy_fdc_device - constructor -//------------------------------------------------- - -sdtandy_fdc_device::sdtandy_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : dragon_fdc_device(mconfig, SDTANDY_FDC, "SDTANDY FDC", tag, owner, clock, "sdtandy_fdc", __FILE__) -{ -} - -//------------------------------------------------- -// rom_region - device-specific ROM region -//------------------------------------------------- - -const tiny_rom_entry *sdtandy_fdc_device::device_rom_region() const -{ - return ROM_NAME( sdtandy_fdc ); -} //************************************************************************** // COCO FDC v1.1 //************************************************************************** -ROM_START( coco_fdc_v11 ) - ROM_REGION(0x8000,"eprom",ROMREGION_ERASE00) - ROM_LOAD_OPTIONAL( "disk11.rom", 0x0000, 0x2000, CRC(0b9c5415) SHA1(10bdc5aa2d7d7f205f67b47b19003a4bd89defd1)) +ROM_START(coco_fdc_v11) + ROM_REGION(0x8000, "eprom", ROMREGION_ERASE00) + ROM_LOAD_OPTIONAL("disk11.rom", 0x0000, 0x2000, CRC(0b9c5415) SHA1(10bdc5aa2d7d7f205f67b47b19003a4bd89defd1)) ROM_RELOAD(0x2000, 0x2000) ROM_RELOAD(0x4000, 0x2000) ROM_RELOAD(0x6000, 0x2000) ROM_END +namespace +{ + class coco_fdc_v11_device : public coco_fdc_device_base + { + public: + // construction/destruction + coco_fdc_v11_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : coco_fdc_device_base(mconfig, COCO_FDC_V11, "CoCo FDC v1.1", tag, owner, clock, "coco_fdc_v11", __FILE__) + { + } + + protected: + // optional information overrides + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME(coco_fdc_v11); + } + }; +}; + const device_type COCO_FDC_V11 = &device_creator; -//------------------------------------------------- -// coco_fdc_v11_device - constructor -//------------------------------------------------- - -coco_fdc_v11_device::coco_fdc_v11_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : coco_fdc_device(mconfig, COCO_FDC_V11, "CoCo FDC v1.1", tag, owner, clock, "coco_fdc_v11", __FILE__) -{ -} - -//------------------------------------------------- -// rom_region - device-specific ROM region -//------------------------------------------------- - -const tiny_rom_entry *coco_fdc_v11_device::device_rom_region() const -{ - return ROM_NAME( coco_fdc_v11 ); -} //************************************************************************** // COCO-3 HDB-DOS //************************************************************************** -ROM_START( coco3_hdb1 ) - ROM_REGION(0x8000,"eprom",ROMREGION_ERASE00) - ROM_LOAD("hdbdw3bc3.rom", 0x0000, 0x2000, CRC(309a9efd) SHA1(671605d61811953860466f771c1594bbade331f4)) +ROM_START(coco3_hdb1) + ROM_REGION(0x8000, "eprom", ROMREGION_ERASE00) + ROM_LOAD("hdbdw3bc3.rom", 0x0000, 0x2000, CRC(309a9efd) SHA1(671605d61811953860466f771c1594bbade331f4)) ROM_RELOAD(0x2000, 0x2000) ROM_RELOAD(0x4000, 0x2000) ROM_RELOAD(0x6000, 0x2000) ROM_END +namespace +{ + class coco3_hdb1_device : public coco_fdc_device_base + { + public: + // construction/destruction + coco3_hdb1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : coco_fdc_device_base(mconfig, COCO3_HDB1, "CoCo3 HDB-DOS", tag, owner, clock, "coco3_hdb1", __FILE__) + { + } + + protected: + // optional information overrides + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME(coco3_hdb1); + } + }; +}; + const device_type COCO3_HDB1 = &device_creator; -coco3_hdb1_device::coco3_hdb1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : coco_fdc_device(mconfig, COCO3_HDB1, "CoCo3 HDB-DOS", tag, owner, clock, "coco3_hdb1", __FILE__) -{ -} - -const tiny_rom_entry *coco3_hdb1_device::device_rom_region() const -{ - return ROM_NAME( coco3_hdb1 ); -} - //************************************************************************** // CP400 FDC //************************************************************************** -ROM_START( cp400_fdc ) - ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00) - ROM_LOAD("cp400dsk.rom", 0x0000, 0x2000, CRC(e9ad60a0) SHA1(827697fa5b755f5dc1efb054cdbbeb04e405405b)) +ROM_START(cp400_fdc) + ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00) + ROM_LOAD("cp400dsk.rom", 0x0000, 0x2000, CRC(e9ad60a0) SHA1(827697fa5b755f5dc1efb054cdbbeb04e405405b)) ROM_END +namespace +{ + class cp400_fdc_device : public coco_fdc_device_base + { + public: + // construction/destruction + cp400_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : coco_fdc_device_base(mconfig, CP400_FDC, "CP400 FDC", tag, owner, clock, "cp400_fdc", __FILE__) + { + } + + protected: + // optional information overrides + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME(cp400_fdc); + } + }; +}; + const device_type CP400_FDC = &device_creator; - -//------------------------------------------------- -// cp400_fdc_device - constructor -//------------------------------------------------- - -cp400_fdc_device::cp400_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : coco_fdc_device(mconfig, CP400_FDC, "CP400 FDC", tag, owner, clock, "cp400_fdc", __FILE__) -{ -} - -//------------------------------------------------- -// rom_region - device-specific ROM region -//------------------------------------------------- - -const tiny_rom_entry *cp400_fdc_device::device_rom_region() const -{ - return ROM_NAME( cp400_fdc ); -} diff --git a/src/devices/bus/coco/coco_fdc.h b/src/devices/bus/coco/coco_fdc.h index f1f4db0226e..f394355e25a 100644 --- a/src/devices/bus/coco/coco_fdc.h +++ b/src/devices/bus/coco/coco_fdc.h @@ -1,180 +1,88 @@ // license:BSD-3-Clause // copyright-holders:Nathan Woods -#pragma once +/********************************************************************* -#ifndef __COCO_FDC_H__ -#define __COCO_FDC_H__ + coco_fdc.h + + CoCo/Dragon Floppy Disk Controller + +*********************************************************************/ + +#ifndef MAME_DEVICES_BUS_COCO_FDC_H +#define MAME_DEVICES_BUS_COCO_FDC_H #include "emu.h" #include "cococart.h" -#include "machine/msm6242.h" -#include "machine/ds1315.h" -#include "machine/wd_fdc.h" +#include "imagedev/floppy.h" -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ -// ======================> coco_rtc_type_t +// ======================> coco_family_fdc_device_base -enum coco_rtc_type_t -{ - RTC_DISTO = 0x00, - RTC_CLOUD9 = 0x01, - - RTC_NONE = 0xFF -}; - -// ======================> coco_fdc_device - -class coco_fdc_device : - public device_t, - public device_cococart_interface +class coco_family_fdc_device_base : + public device_t, + public device_cococart_interface { public: - // construction/destruction - coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - coco_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + // construction/destruction + coco_family_fdc_device_base(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source) + , device_cococart_interface(mconfig, *this) + { + m_owner = dynamic_cast(owner); + }; - DECLARE_FLOPPY_FORMATS(floppy_formats); + DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w) { m_intrq = state; update_lines(); } + DECLARE_WRITE_LINE_MEMBER(fdc_drq_w) { m_drq = state; update_lines(); } - // optional information overrides - virtual machine_config_constructor device_mconfig_additions() const override; - virtual const tiny_rom_entry *device_rom_region() const override; + DECLARE_FLOPPY_FORMATS(floppy_formats); - virtual UINT8* get_cart_base() override; - - virtual void update_lines(); - virtual void dskreg_w(UINT8 data); - - void set_intrq(UINT8 val) { m_intrq = val; } - void set_drq(UINT8 val) { m_drq = val; } - - DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w); - DECLARE_WRITE_LINE_MEMBER(fdc_drq_w); protected: - // device-level overrides - virtual void device_start() override; - virtual DECLARE_READ8_MEMBER(read) override; - virtual DECLARE_WRITE8_MEMBER(write) override; + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; - coco_rtc_type_t real_time_clock(); + // FDC overrides + virtual void update_lines() = 0; + virtual UINT8* get_cart_base() override; - // internal state - cococart_slot_device *m_owner; + // wrapper for setting the cart line + void cart_set_line(cococart_slot_device::line which, cococart_slot_device::line_value value) + { + m_owner->cart_set_line(which, value); + } + void cart_set_line(cococart_slot_device::line which, bool value) + { + cart_set_line(which, value ? cococart_slot_device::line_value::ASSERT : cococart_slot_device::line_value::CLEAR); + } - UINT8 m_dskreg; - UINT8 m_drq : 1; - UINT8 m_intrq : 1; + // accessors + UINT8 dskreg() const { return m_dskreg; } + bool intrq() const { return m_intrq; } + bool drq() const { return m_drq; } + void set_dskreg(UINT8 data) { m_dskreg = data; } - optional_device m_wd17xx; /* WD17xx */ - optional_device m_wd2797; /* WD2797 */ - optional_device m_ds1315; /* DS1315 */ +private: + // internal state + cococart_slot_device *m_owner; - /* Disto RTC */ - optional_device m_disto_msm6242; /* 6242 RTC on Disto interface */ - - offs_t m_msm6242_rtc_address; - optional_ioport m_rtc; + // registers + UINT8 m_dskreg; + bool m_intrq; + bool m_drq; }; - -// device type definition +// device type definitions - CoCo FDC extern const device_type COCO_FDC; - -// ======================> coco_fdc_v11_device - -class coco_fdc_v11_device : - public coco_fdc_device -{ -public: - // construction/destruction - coco_fdc_v11_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - - // optional information overrides - virtual const tiny_rom_entry *device_rom_region() const override; -}; - - -// device type definition extern const device_type COCO_FDC_V11; - -// ======================> coco3_hdb1_device - -class coco3_hdb1_device : - public coco_fdc_device -{ -public: - // construction/destruction - coco3_hdb1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - - // optional information overrides - virtual const tiny_rom_entry *device_rom_region() const override; -}; - - -// device type definition extern const device_type COCO3_HDB1; - -// ======================> cp400_fdc_device - -class cp400_fdc_device : - public coco_fdc_device -{ -public: - // construction/destruction - cp400_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - - // optional information overrides - virtual const tiny_rom_entry *device_rom_region() const override; -}; - - -// device type definition extern const device_type CP400_FDC; -// ======================> dragon_fdc_device - -class dragon_fdc_device : - public coco_fdc_device -{ -public: - // construction/destruction - dragon_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - dragon_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); - - // optional information overrides - virtual machine_config_constructor device_mconfig_additions() const override; - virtual const tiny_rom_entry *device_rom_region() const override; - virtual void update_lines() override; - virtual void dskreg_w(UINT8 data) override; -protected: - // device-level overrides - virtual void device_start() override; - virtual DECLARE_READ8_MEMBER(read) override; - virtual DECLARE_WRITE8_MEMBER(write) override; -}; - - -// device type definition +// device type definitions - Dragon FDC extern const device_type DRAGON_FDC; - -// ======================> sdtandy_fdc_device - -class sdtandy_fdc_device : - public dragon_fdc_device -{ -public: - // construction/destruction - sdtandy_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - - // optional information overrides - virtual const tiny_rom_entry *device_rom_region() const override; -}; - - -// device type definition extern const device_type SDTANDY_FDC; -#endif /* __COCO_FDC_H__ */ +#endif // MAME_DEVICES_BUS_COCO_FDC_H diff --git a/src/devices/bus/coco/dragon_fdc.cpp b/src/devices/bus/coco/dragon_fdc.cpp new file mode 100644 index 00000000000..d8a147110aa --- /dev/null +++ b/src/devices/bus/coco/dragon_fdc.cpp @@ -0,0 +1,333 @@ +// license:BSD-3-Clause +// copyright-holders:Nathan Woods +/********************************************************************* + + dragon_fdc.cpp + + Dragon Floppy Disk Controller + + The CoCo and Dragon both use the Western Digital floppy disk controllers. + The CoCo uses either the WD1793 or the WD1773, the Dragon uses the WD2797, + which mostly uses the same command set with some subtle differences, most + notably the 2797 handles disk side select internally. The Dragon Alpha also + uses the WD2797, however as this is a built in interface and not an external + cartrige, it is dealt with in the main coco.cpp file. + + The wd's variables are mapped to $FF48-$FF4B on the CoCo and on $FF40-$FF43 + on the Dragon. In addition, there is another register + called DSKREG that controls the interface with the wd1793. DSKREG is + detailed below: But they appear to be + + References: + CoCo: Disk Basic Unravelled + Dragon: Inferences from the PC-Dragon source code + DragonDos Controller, Disk and File Formats by Graham E Kinns + + --------------------------------------------------------------------------- + + DSKREG - the control register + Dragon ($FF48) + + Bit + 7 not used + 6 not used + 5 NMI enable flag + 4 write precompensation + 3 single density enable + 2 drive motor activation + 1 drive select high bit + 0 drive select low bit + + --------------------------------------------------------------------------- + + 2007-02-22, P.Harvey-Smith + + Began implementing the Dragon Delta Dos controller, this was actually the first + Dragon disk controller to market, beating Dragon Data's by a couple of months, + it is based around the WD2791 FDC, which is compatible with the WD1793/WD2797 used + by the standard CoCo and Dragon disk controllers except that it used an inverted + data bus, which is the reason the read/write handlers invert the data. This + controller like, the DragonDos WD2797 is mapped at $FF40-$FF43, in the normal + register order. + + The Delta cart also has a register (74LS174 hex flipflop) at $FF44 encoded as + follows :- + + Bit + 7 not used + 6 not used + 5 not used + 4 Single (0) / Double (1) density select + 3 5.25"(0) / 8"(1) Clock select + 2 Side select + 1 Drive select ms bit + 0 Drive select ls bit + +*********************************************************************/ + +#include "emu.h" +#include "cococart.h" +#include "coco_fdc.h" +#include "imagedev/flopdrv.h" +#include "includes/coco.h" +#include "machine/wd_fdc.h" +#include "formats/dmk_dsk.h" +#include "formats/jvc_dsk.h" +#include "formats/vdk_dsk.h" + + +/*************************************************************************** + PARAMETERS +***************************************************************************/ + +#define LOG_FDC 0 +#define WD2797_TAG "wd2797" + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +namespace +{ + class dragon_fdc_device_base : public coco_family_fdc_device_base + { + public: + // construction/destruction + dragon_fdc_device_base(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + + protected: + // device-level overrides + virtual DECLARE_READ8_MEMBER(read) override; + virtual DECLARE_WRITE8_MEMBER(write) override; + virtual machine_config_constructor device_mconfig_additions() const override; + virtual void update_lines() override; + + private: + // device references + required_device m_wd2797; + required_device_array m_floppies; + + // methods + void dskreg_w(UINT8 data); + }; +}; + +/*************************************************************************** + LOCAL VARIABLES +***************************************************************************/ + +static SLOT_INTERFACE_START(dragon_fdc_device_base) + SLOT_INTERFACE("qd", FLOPPY_525_QD) +SLOT_INTERFACE_END + + +static MACHINE_CONFIG_FRAGMENT(dragon_fdc) + MCFG_WD2797_ADD(WD2797_TAG, XTAL_1MHz) + MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(dragon_fdc_device_base, fdc_intrq_w)) + MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(dragon_fdc_device_base, fdc_drq_w)) + + MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":0", dragon_fdc_device_base, "qd", dragon_fdc_device_base::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":1", dragon_fdc_device_base, "qd", dragon_fdc_device_base::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":2", dragon_fdc_device_base, "", dragon_fdc_device_base::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":3", dragon_fdc_device_base, "", dragon_fdc_device_base::floppy_formats) +MACHINE_CONFIG_END + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +//------------------------------------------------- +// dragon_fdc_device_base - constructor +//------------------------------------------------- +dragon_fdc_device_base::dragon_fdc_device_base(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : coco_family_fdc_device_base(mconfig, type, name, tag, owner, clock, shortname, source) + , m_wd2797(*this, WD2797_TAG) + , m_floppies(*this, WD2797_TAG ":%u", 0) +{ +} + + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor dragon_fdc_device_base::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME(dragon_fdc); +} + + +//------------------------------------------------- +// update_lines - Dragon specific disk +// controller lines +//------------------------------------------------- + +void dragon_fdc_device_base::update_lines() +{ + // set the NMI line + cart_set_line(cococart_slot_device::line::NMI, intrq() && (dskreg() & 0x20)); + + // set the CART line + cart_set_line(cococart_slot_device::line::CART, drq()); +} + + +//------------------------------------------------- +// dskreg_w - function to write to +// Dragon dskreg +//------------------------------------------------- + +void dragon_fdc_device_base::dskreg_w(UINT8 data) +{ + if (LOG_FDC) + { + logerror("fdc_dragon_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n", + data & 0x80 ? 'X' : 'x', + data & 0x40 ? 'X' : 'x', + data & 0x20 ? 'N' : 'n', + data & 0x10 ? 'P' : 'p', + data & 0x08 ? 'S' : 'D', + data & 0x04 ? 'M' : 'm', + data & 0x02 ? '1' : '0', + data & 0x01 ? '1' : '0', + data); + } + + // update the motor on each floppy + for (int i = 0; i < 4; i++) + { + floppy_image_device *floppy = m_floppies[i]->get_device(); + if (floppy) + floppy->mon_w((data && 0x04) && (i == (data & 0x03)) ? CLEAR_LINE : ASSERT_LINE); + } + + // manipulate the WD2797 + m_wd2797->set_floppy(m_floppies[data & 0x03]->get_device()); + m_wd2797->dden_w(BIT(data, 3)); + + set_dskreg(data); +} + + +//------------------------------------------------- +// read +//------------------------------------------------- + +READ8_MEMBER(dragon_fdc_device_base::read) +{ + UINT8 result = 0; + switch (offset & 0xEF) + { + case 0: + result = m_wd2797->status_r(space, 0); + break; + case 1: + result = m_wd2797->track_r(space, 0); + break; + case 2: + result = m_wd2797->sector_r(space, 0); + break; + case 3: + result = m_wd2797->data_r(space, 0); + break; + } + return result; +} + + + +//------------------------------------------------- +// write +//------------------------------------------------- + +WRITE8_MEMBER(dragon_fdc_device_base::write) +{ + switch (offset & 0xEF) + { + case 0: + m_wd2797->cmd_w(space, 0, data); + break; + case 1: + m_wd2797->track_w(space, 0, data); + break; + case 2: + m_wd2797->sector_w(space, 0, data); + break; + case 3: + m_wd2797->data_w(space, 0, data); + break; + case 8: case 9: case 10: case 11: + case 12: case 13: case 14: case 15: + dskreg_w(data); + break; + }; +} + + + + +//************************************************************************** +// DRAGON FDC +//************************************************************************** + +ROM_START(dragon_fdc) + ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00) + ROM_LOAD_OPTIONAL("ddos10.rom", 0x0000, 0x2000, CRC(b44536f6) SHA1(a8918c71d319237c1e3155bb38620acb114a80bc)) +ROM_END + +namespace +{ + class dragon_fdc_device : public dragon_fdc_device_base + { + public: + // construction/destruction + dragon_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : dragon_fdc_device_base(mconfig, DRAGON_FDC, "Dragon FDC", tag, owner, clock, "dragon_fdc", __FILE__) + { + } + + protected: + // optional information overrides + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME(dragon_fdc); + } + }; +}; + +const device_type DRAGON_FDC = &device_creator; + + +//************************************************************************** +// SDTANDY FDC +//************************************************************************** + +ROM_START(sdtandy_fdc) + ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00) + ROM_LOAD_OPTIONAL("sdtandy.rom", 0x0000, 0x2000, CRC(5d7779b7) SHA1(ca03942118f2deab2f6c8a89b8a4f41f2d0b94f1)) +ROM_END + +namespace +{ + class sdtandy_fdc_device : public dragon_fdc_device_base + { + public: + // construction/destruction + sdtandy_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : dragon_fdc_device_base(mconfig, SDTANDY_FDC, "SDTANDY FDC", tag, owner, clock, "sdtandy_fdc", __FILE__) + { + } + + protected: + // optional information overrides + virtual const tiny_rom_entry *device_rom_region() const override + { + return ROM_NAME(sdtandy_fdc); + } + }; +}; + +const device_type SDTANDY_FDC = &device_creator;