Split CoCo and Dragon FDC code, added save state support, fixed regression introduced on the Dragon FDC from 0.154 and general cleanup.

This commit is contained in:
Nathan Woods 2016-09-16 21:07:32 -04:00
parent 636a2bbbf4
commit a2daca9f9d
4 changed files with 646 additions and 586 deletions

View File

@ -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_multi.h",
MAME_DIR .. "src/devices/bus/coco/coco_dwsock.cpp", MAME_DIR .. "src/devices/bus/coco/coco_dwsock.cpp",
MAME_DIR .. "src/devices/bus/coco/coco_dwsock.h", MAME_DIR .. "src/devices/bus/coco/coco_dwsock.h",
MAME_DIR .. "src/devices/bus/coco/dragon_fdc.cpp",
} }
end end

View File

@ -2,16 +2,16 @@
// copyright-holders:Nathan Woods // 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 and Dragon both use the Western Digital floppy disk controllers.
The CoCo uses either the WD1793 or the WD1773, the Dragon uses the WD2797, 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 which mostly uses the same command set with some subtle differences, most
notably the 2797 handles disk side select internally. The Dragon Alpha also 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 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 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 on the Dragon. In addition, there is another register
@ -26,53 +26,30 @@
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
DSKREG - the control register DSKREG - the control register
CoCo ($FF40) Dragon ($FF48) CoCo ($FF40)
Bit Bit Bit
7 halt enable flag 7 not used 7 halt enable flag
6 drive select #3 6 not used 6 drive select #3
5 density (0=single, 1=double) 5 NMI enable flag 5 density (0=single, 1=double) and NMI enable flag
and NMI enable flag 4 write precompensation
4 write precompensation 4 write precompensation 3 drive motor activation
3 drive motor activation 3 single density enable 2 drive select #2
2 drive select #2 2 drive motor activation 1 drive select #1
1 drive select #1 1 drive select high bit 0 drive select #0
0 drive select #0 0 drive select low bit
Reading from $FF48-$FF4F clears bit 7 of DSKREG ($FF40) 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 "emu.h"
#include "cococart.h"
#include "coco_fdc.h" #include "coco_fdc.h"
#include "imagedev/flopdrv.h" #include "imagedev/flopdrv.h"
#include "includes/coco.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/dmk_dsk.h"
#include "formats/jvc_dsk.h" #include "formats/jvc_dsk.h"
#include "formats/vdk_dsk.h" #include "formats/vdk_dsk.h"
@ -88,15 +65,53 @@
#define DISTO_TAG "disto" #define DISTO_TAG "disto"
#define CLOUD9_TAG "cloud9" #define CLOUD9_TAG "cloud9"
/*************************************************************************** /***************************************************************************
TYPE DEFINITIONS 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<wd1773_t> m_wd17xx;
required_device<ds1315_device> m_ds1315;
required_device_array<floppy_connector, 4> m_floppies;
// Disto RTC
required_device<msm6242_device> m_disto_msm6242; // 6242 RTC on Disto interface
offs_t m_msm6242_rtc_address;
optional_ioport m_rtc;
};
/*************************************************************************** /***************************************************************************
LOCAL VARIABLES LOCAL VARIABLES
***************************************************************************/ ***************************************************************************/
FLOPPY_FORMATS_MEMBER( coco_fdc_device::floppy_formats ) FLOPPY_FORMATS_MEMBER( coco_family_fdc_device_base::floppy_formats )
FLOPPY_DMK_FORMAT, FLOPPY_DMK_FORMAT,
FLOPPY_JVC_FORMAT, FLOPPY_JVC_FORMAT,
FLOPPY_VDK_FORMAT FLOPPY_VDK_FORMAT
@ -106,166 +121,132 @@ static SLOT_INTERFACE_START( coco_fdc_floppies )
SLOT_INTERFACE("qd", FLOPPY_525_QD) SLOT_INTERFACE("qd", FLOPPY_525_QD)
SLOT_INTERFACE_END 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) static MACHINE_CONFIG_FRAGMENT(coco_fdc)
MCFG_WD1773_ADD(WD_TAG, XTAL_8MHz) MCFG_WD1773_ADD(WD_TAG, XTAL_8MHz)
MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(coco_fdc_device, fdc_intrq_w)) MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(coco_fdc_device_base, fdc_intrq_w))
MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(coco_fdc_device, fdc_drq_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 ":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::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::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::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_DEVICE_ADD(DISTO_TAG, MSM6242, XTAL_32_768kHz)
MCFG_DS1315_ADD(CLOUD9_TAG) MCFG_DS1315_ADD(CLOUD9_TAG)
MACHINE_CONFIG_END MACHINE_CONFIG_END
ROM_START( coco_fdc )
ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00)
ROM_LOAD_OPTIONAL( "disk10.rom", 0x0000, 0x2000, CRC(b4f9968e) SHA1(04115be3f97952b9d9310b52f806d04f80b40d03))
ROM_END
const device_type COCO_FDC = &device_creator<coco_fdc_device>; //***************************************************************************
// COCO 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), void coco_family_fdc_device_base::device_start()
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")
{ {
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), // coco_family_fdc_device_base::device_reset
m_wd17xx(*this, WD_TAG), //-------------------------------------------------
m_wd2797(*this, WD2797_TAG),
m_ds1315(*this, CLOUD9_TAG), void coco_family_fdc_device_base::device_reset()
m_disto_msm6242(*this, DISTO_TAG), m_msm6242_rtc_address(0), {
m_rtc(*this, ":real_time_clock") 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<cococart_slot_device *>(owner()); rtc_type result = (rtc_type) m_rtc.read_safe((ioport_value) rtc_type::NONE);
m_drq = 1;
m_dskreg = 0x00; // check to make sure we don't have any invalid values
m_intrq = 0; if (((result == rtc_type::DISTO) && (m_disto_msm6242 == nullptr))
m_msm6242_rtc_address = 0; || ((result == rtc_type::CLOUD9) && (m_ds1315 == nullptr)))
{
result = rtc_type::NONE;
}
return result;
} }
//------------------------------------------------- //-------------------------------------------------
// machine_config_additions - device-specific // machine_config_additions - device-specific
// machine configurations // 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() //-------------------------------------------------
{ // dskreg_w - function to write to CoCo dskreg
return memregion("eprom")->base(); //-------------------------------------------------
}
/*------------------------------------------------- void coco_fdc_device_base::dskreg_w(UINT8 data)
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)
{ {
UINT8 drive = 0; UINT8 drive = 0;
UINT8 head; UINT8 head;
@ -300,38 +281,34 @@ void coco_fdc_device::dskreg_w(UINT8 data)
else if (data & 0x40) else if (data & 0x40)
drive = 3; drive = 3;
floppy_image_device *floppy[4];
floppy[0] = subdevice<floppy_connector>(WD_TAG ":0")->get_device();
floppy[1] = subdevice<floppy_connector>(WD_TAG ":1")->get_device();
floppy[2] = subdevice<floppy_connector>(WD_TAG ":2")->get_device();
floppy[3] = subdevice<floppy_connector>(WD_TAG ":3")->get_device();
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
if (floppy[i]) floppy_image_device *floppy = m_floppies[i]->get_device();
floppy[i]->mon_w(i == drive ? CLEAR_LINE : ASSERT_LINE); if (floppy)
floppy->mon_w(i == drive ? CLEAR_LINE : ASSERT_LINE);
} }
head = ((data & 0x40) && (drive != 3)) ? 1 : 0; head = ((data & 0x40) && (drive != 3)) ? 1 : 0;
m_dskreg = data; set_dskreg(data);
update_lines(); 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]) if (selected_floppy)
floppy[drive]->ss_w(head); 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; UINT8 result = 0;
@ -355,22 +332,22 @@ READ8_MEMBER(coco_fdc_device::read)
switch(offset) switch(offset)
{ {
case 0x10: /* FF50 */ 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); result = m_disto_msm6242->read(space,m_msm6242_rtc_address);
break; break;
case 0x38: /* FF78 */ case 0x38: /* FF78 */
if (real_time_clock() == RTC_CLOUD9) if (real_time_clock() == rtc_type::CLOUD9)
m_ds1315->read_0(space, offset); m_ds1315->read_0(space, offset);
break; break;
case 0x39: /* FF79 */ case 0x39: /* FF79 */
if (real_time_clock() == RTC_CLOUD9) if (real_time_clock() == rtc_type::CLOUD9)
m_ds1315->read_1(space, offset); m_ds1315->read_1(space, offset);
break; break;
case 0x3C: /* FF7C */ case 0x3C: /* FF7C */
if (real_time_clock() == RTC_CLOUD9) if (real_time_clock() == rtc_type::CLOUD9)
result = m_ds1315->read_data(space, offset); result = m_ds1315->read_data(space, offset);
break; 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) switch(offset & 0x1F)
{ {
@ -410,12 +387,12 @@ WRITE8_MEMBER(coco_fdc_device::write)
switch(offset) switch(offset)
{ {
case 0x10: /* FF50 */ 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); m_disto_msm6242->write(space,m_msm6242_rtc_address, data);
break; break;
case 0x11: /* FF51 */ case 0x11: /* FF51 */
if (real_time_clock() == RTC_DISTO) if (real_time_clock() == rtc_type::DISTO)
m_msm6242_rtc_address = data & 0x0f; m_msm6242_rtc_address = data & 0x0f;
break; break;
} }
@ -423,293 +400,134 @@ WRITE8_MEMBER(coco_fdc_device::write)
//************************************************************************** //**************************************************************************
// DRAGON FDC // COCO FDC
//************************************************************************** //**************************************************************************
static MACHINE_CONFIG_FRAGMENT(dragon_fdc) ROM_START(coco_fdc)
MCFG_WD2797_ADD(WD2797_TAG, XTAL_1MHz) ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
ROM_LOAD_OPTIONAL("disk10.rom", 0x0000, 0x2000, CRC(b4f9968e) SHA1(04115be3f97952b9d9310b52f806d04f80b40d03))
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_END ROM_END
const device_type DRAGON_FDC = &device_creator<dragon_fdc_device>; namespace
//-------------------------------------------------
// 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)
{ {
} class coco_fdc_device : public coco_fdc_device_base
dragon_fdc_device::dragon_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: coco_fdc_device(mconfig, DRAGON_FDC, "Dragon FDC", tag, owner, clock, "dragon_fdc", __FILE__)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void dragon_fdc_device::device_start()
{
m_owner = dynamic_cast<cococart_slot_device *>(owner());
m_drq = 0;
m_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)
{ {
logerror("fdc_dragon_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n", public:
data & 0x80 ? 'X' : 'x', // construction/destruction
data & 0x40 ? 'X' : 'x', coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
data & 0x20 ? 'N' : 'n', : coco_fdc_device_base(mconfig, COCO_FDC, "CoCo FDC", tag, owner, clock, "coco_fdc", __FILE__)
data & 0x10 ? 'P' : 'p', {
data & 0x08 ? 'S' : 'D', }
data & 0x04 ? 'M' : 'm',
data & 0x02 ? '1' : '0',
data & 0x01 ? '1' : '0',
data);
}
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<floppy_connector>(WD2797_TAG ":0")->get_device(); break;
case 1: floppy = subdevice<floppy_connector>(WD2797_TAG ":1")->get_device(); break;
case 2: floppy = subdevice<floppy_connector>(WD2797_TAG ":2")->get_device(); break;
case 3: floppy = subdevice<floppy_connector>(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<coco_fdc_device>;
//**************************************************************************
// SDTANDY FDC
//**************************************************************************
ROM_START( sdtandy_fdc )
ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00)
ROM_LOAD_OPTIONAL( "sdtandy.rom", 0x0000, 0x2000, CRC(5d7779b7) SHA1(ca03942118f2deab2f6c8a89b8a4f41f2d0b94f1))
ROM_END
const device_type SDTANDY_FDC = &device_creator<sdtandy_fdc_device>;
//-------------------------------------------------
// sdtandy_fdc_device - constructor
//-------------------------------------------------
sdtandy_fdc_device::sdtandy_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: dragon_fdc_device(mconfig, SDTANDY_FDC, "SDTANDY FDC", tag, owner, clock, "sdtandy_fdc", __FILE__)
{
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const tiny_rom_entry *sdtandy_fdc_device::device_rom_region() const
{
return ROM_NAME( sdtandy_fdc );
}
//************************************************************************** //**************************************************************************
// COCO FDC v1.1 // COCO FDC v1.1
//************************************************************************** //**************************************************************************
ROM_START( coco_fdc_v11 ) ROM_START(coco_fdc_v11)
ROM_REGION(0x8000,"eprom",ROMREGION_ERASE00) ROM_REGION(0x8000, "eprom", ROMREGION_ERASE00)
ROM_LOAD_OPTIONAL( "disk11.rom", 0x0000, 0x2000, CRC(0b9c5415) SHA1(10bdc5aa2d7d7f205f67b47b19003a4bd89defd1)) ROM_LOAD_OPTIONAL("disk11.rom", 0x0000, 0x2000, CRC(0b9c5415) SHA1(10bdc5aa2d7d7f205f67b47b19003a4bd89defd1))
ROM_RELOAD(0x2000, 0x2000) ROM_RELOAD(0x2000, 0x2000)
ROM_RELOAD(0x4000, 0x2000) ROM_RELOAD(0x4000, 0x2000)
ROM_RELOAD(0x6000, 0x2000) ROM_RELOAD(0x6000, 0x2000)
ROM_END 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>; const device_type COCO_FDC_V11 = &device_creator<coco_fdc_v11_device>;
//-------------------------------------------------
// coco_fdc_v11_device - constructor
//-------------------------------------------------
coco_fdc_v11_device::coco_fdc_v11_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: coco_fdc_device(mconfig, COCO_FDC_V11, "CoCo FDC v1.1", tag, owner, clock, "coco_fdc_v11", __FILE__)
{
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const tiny_rom_entry *coco_fdc_v11_device::device_rom_region() const
{
return ROM_NAME( coco_fdc_v11 );
}
//************************************************************************** //**************************************************************************
// COCO-3 HDB-DOS // COCO-3 HDB-DOS
//************************************************************************** //**************************************************************************
ROM_START( coco3_hdb1 ) ROM_START(coco3_hdb1)
ROM_REGION(0x8000,"eprom",ROMREGION_ERASE00) ROM_REGION(0x8000, "eprom", ROMREGION_ERASE00)
ROM_LOAD("hdbdw3bc3.rom", 0x0000, 0x2000, CRC(309a9efd) SHA1(671605d61811953860466f771c1594bbade331f4)) ROM_LOAD("hdbdw3bc3.rom", 0x0000, 0x2000, CRC(309a9efd) SHA1(671605d61811953860466f771c1594bbade331f4))
ROM_RELOAD(0x2000, 0x2000) ROM_RELOAD(0x2000, 0x2000)
ROM_RELOAD(0x4000, 0x2000) ROM_RELOAD(0x4000, 0x2000)
ROM_RELOAD(0x6000, 0x2000) ROM_RELOAD(0x6000, 0x2000)
ROM_END 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>; const device_type COCO3_HDB1 = &device_creator<coco3_hdb1_device>;
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 // CP400 FDC
//************************************************************************** //**************************************************************************
ROM_START( cp400_fdc ) ROM_START(cp400_fdc)
ROM_REGION(0x4000,"eprom",ROMREGION_ERASE00) ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
ROM_LOAD("cp400dsk.rom", 0x0000, 0x2000, CRC(e9ad60a0) SHA1(827697fa5b755f5dc1efb054cdbbeb04e405405b)) ROM_LOAD("cp400dsk.rom", 0x0000, 0x2000, CRC(e9ad60a0) SHA1(827697fa5b755f5dc1efb054cdbbeb04e405405b))
ROM_END 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>; const device_type CP400_FDC = &device_creator<cp400_fdc_device>;
//-------------------------------------------------
// cp400_fdc_device - constructor
//-------------------------------------------------
cp400_fdc_device::cp400_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: coco_fdc_device(mconfig, CP400_FDC, "CP400 FDC", tag, owner, clock, "cp400_fdc", __FILE__)
{
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const tiny_rom_entry *cp400_fdc_device::device_rom_region() const
{
return ROM_NAME( cp400_fdc );
}

View File

@ -1,180 +1,88 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Nathan Woods // copyright-holders:Nathan Woods
#pragma once /*********************************************************************
#ifndef __COCO_FDC_H__ coco_fdc.h
#define __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 "emu.h"
#include "cococart.h" #include "cococart.h"
#include "machine/msm6242.h" #include "imagedev/floppy.h"
#include "machine/ds1315.h"
#include "machine/wd_fdc.h"
//************************************************************************** /***************************************************************************
// TYPE DEFINITIONS TYPE DEFINITIONS
//************************************************************************** ***************************************************************************/
// ======================> coco_rtc_type_t // ======================> coco_family_fdc_device_base
enum coco_rtc_type_t class coco_family_fdc_device_base :
{ public device_t,
RTC_DISTO = 0x00, public device_cococart_interface
RTC_CLOUD9 = 0x01,
RTC_NONE = 0xFF
};
// ======================> coco_fdc_device
class coco_fdc_device :
public device_t,
public device_cococart_interface
{ {
public: public:
// construction/destruction // construction/destruction
coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); 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)
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 = dynamic_cast<cococart_slot_device *>(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 DECLARE_FLOPPY_FORMATS(floppy_formats);
virtual machine_config_constructor device_mconfig_additions() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
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: protected:
// device-level overrides // device-level overrides
virtual void device_start() override; virtual void device_start() override;
virtual DECLARE_READ8_MEMBER(read) override; virtual void device_reset() override;
virtual DECLARE_WRITE8_MEMBER(write) override;
coco_rtc_type_t real_time_clock(); // FDC overrides
virtual void update_lines() = 0;
virtual UINT8* get_cart_base() override;
// internal state // wrapper for setting the cart line
cococart_slot_device *m_owner; 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; // accessors
UINT8 m_drq : 1; UINT8 dskreg() const { return m_dskreg; }
UINT8 m_intrq : 1; bool intrq() const { return m_intrq; }
bool drq() const { return m_drq; }
void set_dskreg(UINT8 data) { m_dskreg = data; }
optional_device<wd1773_t> m_wd17xx; /* WD17xx */ private:
optional_device<wd2797_t> m_wd2797; /* WD2797 */ // internal state
optional_device<ds1315_device> m_ds1315; /* DS1315 */ cococart_slot_device *m_owner;
/* Disto RTC */ // registers
optional_device<msm6242_device> m_disto_msm6242; /* 6242 RTC on Disto interface */ UINT8 m_dskreg;
bool m_intrq;
offs_t m_msm6242_rtc_address; bool m_drq;
optional_ioport m_rtc;
}; };
// device type definitions - CoCo FDC
// device type definition
extern const device_type 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; 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; 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; extern const device_type CP400_FDC;
// ======================> dragon_fdc_device // device type definitions - Dragon FDC
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
extern const device_type 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; extern const device_type SDTANDY_FDC;
#endif /* __COCO_FDC_H__ */ #endif // MAME_DEVICES_BUS_COCO_FDC_H

View File

@ -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<wd2797_t> m_wd2797;
required_device_array<floppy_connector, 4> 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<dragon_fdc_device>;
//**************************************************************************
// 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<sdtandy_fdc_device>;