mame/src/mess/machine/concept_exp.c

400 lines
10 KiB
C

/**********************************************************************
Corvus Concept expansion port emulation
Copyright MESS Team.
Visit http://mamedev.org for licensing and usage restrictions.
FIXME: Concept expansion ports should just use the Apple II Bus device!
The code below is outdated and inaccurate!
**********************************************************************/
#include "machine/concept_exp.h"
// FDC controller
#include "machine/wd17xx.h"
#include "imagedev/flopdrv.h"
#include "formats/basicdsk.h"
// HDC controller
#include "includes/corvushd.h"
#include "imagedev/harddriv.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
// device type definition
const device_type CONCEPT_EXP_PORT = &device_creator<concept_exp_port_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// concept_exp_port_device - constructor
//-------------------------------------------------
concept_exp_port_device::concept_exp_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, CONCEPT_EXP_PORT, "Corvus Concept expansion port", tag, owner, clock),
device_slot_interface(mconfig, *this)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void concept_exp_port_device::device_start()
{
m_card = dynamic_cast<concept_exp_card_device *>(get_card_device());
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void concept_exp_port_device::device_reset()
{
}
READ8_MEMBER( concept_exp_port_device::reg_r )
{
if (m_card)
return m_card->reg_r(space, offset);
return 0;
}
WRITE8_MEMBER( concept_exp_port_device::reg_w )
{
if (m_card != NULL)
m_card->reg_w(space, offset, data);
}
READ8_MEMBER( concept_exp_port_device::rom_r )
{
if (m_card)
return m_card->reg_r(space, offset);
return 0;
}
WRITE8_MEMBER( concept_exp_port_device::rom_w )
{
if (m_card != NULL)
m_card->reg_w(space, offset, data);
}
//**************************************************************************
// CARD INTERFACE
//**************************************************************************
//-------------------------------------------------
// concept_exp_card_device - constructor
//-------------------------------------------------
concept_exp_card_device::concept_exp_card_device(const machine_config &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device)
{
}
//**************************************************************************
// STUB EMULATION OF CARD DEVICES
//**************************************************************************
// FIXME: clean these up and move them in separate sources if suitable...
const device_type CONCEPT_FDC = &device_creator<concept_fdc_device>;
const device_type CONCEPT_HDC = &device_creator<concept_hdc_device>;
concept_fdc_device::concept_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, CONCEPT_FDC, "Corvus Concept FDC controller", tag, owner, clock, "concept_fdc", __FILE__),
concept_exp_card_device( mconfig, *this )
{
}
concept_hdc_device::concept_hdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, CONCEPT_HDC, "Corvus Concept HDC controller", tag, owner, clock, "concept_hdc", __FILE__),
concept_exp_card_device( mconfig, *this )
{
}
// FDC Controller
enum
{
LS_DRQ_bit = 0, // DRQ
LS_INT_bit = 1, // INT
LS_SS_bit = 4, // 1 if single-sided (floppy or drive?)
LS_8IN_bit = 5, // 1 if 8" floppy drive?
LS_DSKCHG_bit = 6, // 0 if disk changed, 1 if not
LS_SD_bit = 7, // 1 if single density
LS_DRQ_mask = (1 << LS_DRQ_bit),
LS_INT_mask = (1 << LS_INT_bit),
LS_SS_mask = (1 << LS_SS_bit),
LS_8IN_mask = (1 << LS_8IN_bit),
LS_DSKCHG_mask = (1 << LS_DSKCHG_bit),
LS_SD_mask = (1 << LS_SD_bit)
};
enum
{
LC_FLPSD1_bit = 0, // 0 if side 0 , 1 if side 1
LC_DE0_bit = 1, // drive select bit 0
LC_DE1_bit = 4, // drive select bit 1
LC_MOTOROF_bit = 5, // 1 if motor to be turned off
LC_FLP8IN_bit = 6, // 1 to select 8", 0 for 5"1/4 (which I knew what it means)
LC_FMMFM_bit = 7, // 1 to select single density, 0 for double
LC_FLPSD1_mask = (1 << LC_FLPSD1_bit),
LC_DE0_mask = (1 << LC_DE0_bit),
LC_DE1_mask = (1 << LC_DE1_bit),
LC_MOTOROF_mask = (1 << LC_MOTOROF_bit),
LC_FLP8IN_mask = (1 << LC_FLP8IN_bit),
LC_FMMFM_mask = (1 << LC_FMMFM_bit)
};
void concept_fdc_device::device_start()
{
m_wd179x = subdevice("wd179x");
save_item(NAME(m_fdc_local_status));
save_item(NAME(m_fdc_local_command));
}
void concept_fdc_device::device_reset()
{
m_fdc_local_status = 0;
m_fdc_local_command = 0;
}
WRITE_LINE_MEMBER(concept_fdc_device::intrq_w)
{
if (state)
m_fdc_local_status |= LS_INT_mask;
else
m_fdc_local_status &= ~LS_INT_mask;
}
WRITE_LINE_MEMBER(concept_fdc_device::drq_w)
{
if (state)
m_fdc_local_status |= LS_DRQ_mask;
else
m_fdc_local_status &= ~LS_DRQ_mask;
}
const wd17xx_interface concept_wd17xx_interface =
{
DEVCB_NULL,
DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, concept_fdc_device, intrq_w),
DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, concept_fdc_device, drq_w),
{FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
};
READ8_MEMBER(concept_fdc_device::reg_r)
{
switch (offset)
{
case 0: // LOCAL STATUS REG
return m_fdc_local_status;
case 8: // FDC STATUS REG
return wd17xx_status_r(m_wd179x, space, offset);
case 9: // FDC TRACK REG
return wd17xx_track_r(m_wd179x, space, offset);
case 10: // FDC SECTOR REG
return wd17xx_sector_r(m_wd179x, space, offset);
case 11: // FDC DATA REG
return wd17xx_data_r(m_wd179x, space, offset);
}
return 0;
}
WRITE8_MEMBER(concept_fdc_device::reg_w)
{
int current_drive;
switch (offset)
{
case 0: // LOCAL COMMAND REG
m_fdc_local_command = data;
wd17xx_set_side(m_wd179x, (data & LC_FLPSD1_mask) != 0);
current_drive = ((data >> LC_DE0_bit) & 1) | ((data >> (LC_DE1_bit-1)) & 2);
wd17xx_set_drive(m_wd179x, current_drive);
/*motor_on = (data & LC_MOTOROF_mask) == 0;*/
// floppy_drive_set_motor_state(floppy_get_device(machine(), current_drive), (data & LC_MOTOROF_mask) == 0 ? 1 : 0);
/*flp_8in = (data & LC_FLP8IN_mask) != 0;*/
wd17xx_dden_w(m_wd179x, BIT(data, 7));
floppy_drive_set_ready_state(floppy_get_device(machine(), current_drive), 1, 0);
break;
case 8: // FDC COMMAMD REG
wd17xx_command_w(m_wd179x, space, offset, data);
break;
case 9: // FDC TRACK REG
wd17xx_track_w(m_wd179x, space, offset, data);
break;
case 10: // FDC SECTOR REG
wd17xx_sector_w(m_wd179x, space, offset, data);
break;
case 11: // FDC DATA REG
wd17xx_data_w(m_wd179x, space, offset, data);
break;
}
}
READ8_MEMBER(concept_fdc_device::rom_r)
{
static const UINT8 data[] = "CORVUS01";
return (offset < 8) ? data[offset] : 0;
}
static LEGACY_FLOPPY_OPTIONS_START(concept)
#if 1
/* SSSD 8" */
LEGACY_FLOPPY_OPTION(concept, "img", "Corvus Concept 8\" SSSD disk image", basicdsk_identify_default, basicdsk_construct_default, NULL,
HEADS([1])
TRACKS([77])
SECTORS([26])
SECTOR_LENGTH([128])
FIRST_SECTOR_ID([1]))
#elif 0
/* SSDD 8" (according to ROMs) */
LEGACY_FLOPPY_OPTION(concept, "img", "Corvus Concept 8\" SSDD disk image", basicdsk_identify_default, basicdsk_construct_default, NULL,
HEADS([1])
TRACKS([77])
SECTORS([26])
SECTOR_LENGTH([256])
FIRST_SECTOR_ID([1]))
#elif 0
/* Apple II DSDD 5"1/4 (according to ROMs) */
LEGACY_FLOPPY_OPTION(concept, "img", "Corvus Concept Apple II 5\"1/4 DSDD disk image", basicdsk_identify_default, basicdsk_construct_default, NULL,
HEADS([2])
TRACKS([35])
SECTORS([16])
SECTOR_LENGTH([256])
FIRST_SECTOR_ID([1]))
#elif 0
/* actual formats found */
LEGACY_FLOPPY_OPTION(concept, "img", "Corvus Concept 5\"1/4 DSDD disk image (256-byte sectors)", basicdsk_identify_default, basicdsk_construct_default, NULL,
HEADS([2])
TRACKS([80])
SECTORS([16])
SECTOR_LENGTH([256])
FIRST_SECTOR_ID([1]))
#else
LEGACY_FLOPPY_OPTION(concept, "img", "Corvus Concept 5\"1/4 DSDD disk image (512-byte sectors)", basicdsk_identify_default, basicdsk_construct_default, NULL,
HEADS([2])
TRACKS([80])
SECTORS([9])
SECTOR_LENGTH([512])
FIRST_SECTOR_ID([1]))
#endif
LEGACY_FLOPPY_OPTIONS_END
static const floppy_interface concept_floppy_interface =
{
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
FLOPPY_STANDARD_5_25_DSHD,
LEGACY_FLOPPY_OPTIONS_NAME(concept),
NULL,
NULL
};
static MACHINE_CONFIG_FRAGMENT( fdc )
MCFG_FD1793_ADD("wd179x", concept_wd17xx_interface )
MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(concept_floppy_interface)
MACHINE_CONFIG_END
machine_config_constructor concept_fdc_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME(fdc);
}
// HDC Controller
void concept_hdc_device::device_start()
{
corvus_hdc_init(machine());
}
void concept_hdc_device::device_reset()
{
}
// Handle reads against the Hard Disk Controller's onboard registers
READ8_MEMBER(concept_hdc_device::reg_r)
{
switch (offset)
{
case 0: // HDC Data Register
return corvus_hdc_data_r(space, offset);
case 1: // HDC Status Register
return corvus_hdc_status_r(space, offset);
}
return 0;
}
// Handle writes against the Hard Disk Controller's onboard registers
WRITE8_MEMBER(concept_hdc_device::reg_w)
{
switch (offset)
{
case 0: // HDC Data Register
corvus_hdc_data_w(space, offset, data);
break;
}
}
// Handle reads agsint the Hard Disk Controller's onboard ROM
READ8_MEMBER(concept_hdc_device::rom_r)
{
static const UINT8 data[8] = { 0xa9, 0x20, 0xa9, 0x00, 0xa9, 0x03, 0xa9, 0x3c }; /* Same as Apple II */
return (offset < 8) ? data[offset] : 0;
}
static MACHINE_CONFIG_FRAGMENT( hdc )
MCFG_HARDDISK_ADD( "harddisk1" )
MACHINE_CONFIG_END
machine_config_constructor concept_hdc_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME(hdc);
}