ti99: ST225 emulation

This commit is contained in:
Michael Zapf 2015-04-19 23:09:05 +02:00
parent 0aebc8e54e
commit 1ad65b58ff
12 changed files with 629 additions and 174 deletions

View File

@ -11,7 +11,7 @@
#include "emu.h"
#include "emuopts.h"
#include "audit.h"
#include "harddisk.h"
#include "chd.h"
#include "sound/samples.h"

View File

@ -74,12 +74,12 @@
#define CLK_ADDR 0x0fe0
#define RAM_ADDR 0x1000
#define TRACE_EMU 0
#define TRACE_EMU 1
#define TRACE_CRU 0
#define TRACE_COMP 0
#define TRACE_RAM 0
#define TRACE_ROM 0
#define TRACE_LINES 0
#define TRACE_LINES 1
#define TRACE_MOTOR 0
#define TRACE_DMA 0
#define TRACE_INT 0
@ -499,12 +499,32 @@ void myarc_hfdc_device::device_timer(emu_timer &timer, device_timer_id id, int p
*/
void myarc_hfdc_device::floppy_index_callback(floppy_image_device *floppy, int state)
{
if (TRACE_LINES) if (state==1) logerror("%s: Index pulse\n", tag());
if (TRACE_LINES) if (state==1) logerror("%s: Floppy index pulse\n", tag());
// m_status_latch = (state==ASSERT_LINE)? (m_status_latch | HDC_DS_INDEX) : (m_status_latch & ~HDC_DS_INDEX);
set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE));
signal_drive_status();
}
/*
This is called back from the hard disk when an index hole is passing by.
*/
void myarc_hfdc_device::harddisk_index_callback(mfm_harddisk_device *harddisk, int state)
{
/* if (TRACE_LINES) */ if (state==1) logerror("%s: HD seek complete\n", tag());
set_bits(m_status_latch, HDC_DS_SKCOM, (state==ASSERT_LINE));
signal_drive_status();
}
/*
This is called back from the hard disk when seek_complete becomes asserted.
*/
void myarc_hfdc_device::harddisk_skcom_callback(mfm_harddisk_device *harddisk, int state)
{
/* if (TRACE_LINES) */ if (state==1) logerror("%s: HD index pulse\n", tag());
set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE));
signal_drive_status();
}
void myarc_hfdc_device::set_bits(UINT8& byte, int mask, bool set)
{
if (set) byte |= mask;
@ -512,18 +532,16 @@ void myarc_hfdc_device::set_bits(UINT8& byte, int mask, bool set)
}
/*
Calculate the logarithm. This is needed to determine the index of a drive.
Returns -1 for value=0
Maps the set bit to an index. The rightmost 1 bit is significant. When no
bit is set, returns -1.
*/
int myarc_hfdc_device::slog2(int value)
int myarc_hfdc_device::bit_to_index(int value)
{
int i=-1;
while (value!=0)
{
value >>= 1;
i++;
}
return i;
if (value & 0x01) return 0;
if (value & 0x02) return 1;
if (value & 0x04) return 2;
if (value & 0x08) return 3;
return -1;
}
/*
@ -554,7 +572,19 @@ void myarc_hfdc_device::signal_drive_status()
// Check for TRK00*
if ((m_current_floppy != NULL) && (!m_current_floppy->trk00_r()))
reply |= 0x10;
reply |= HDC_DS_TRK00;
}
else
{
if ((m_output1_latch & 0xe0)!=0)
{
if (m_current_harddisk->ready_r()==ASSERT_LINE)
{
m_status_latch |= HDC_DS_READY;
set_bits(m_status_latch, HDC_DS_SKCOM, m_current_harddisk->seek_complete_r()==ASSERT_LINE);
set_bits(m_status_latch, HDC_DS_TRK00, m_current_harddisk->trk00_r()==ASSERT_LINE);
}
}
}
// If WDS is selected but not connected, WDS.ready* and WDS.seekComplete* are 1, so Ready=SeekComplete=0
@ -598,27 +628,18 @@ WRITE8_MEMBER( myarc_hfdc_device::auxbus_out )
m_output1_latch = data;
if ((data & 0x10) != 0)
{
// Floppy selected
connect_floppy_unit(slog2(data & 0x0f));
}
if ((data & 0x10) != 0) connect_floppy_unit(bit_to_index(data & 0x0f)); // Floppy selected
else
{
index = slog2((data>>4) & 0x0f);
if (index == -1)
{
if (TRACE_LINES) logerror("%s: Unselect all HD drives\n", tag());
connect_floppy_unit(index);
}
else
{
// HD selected
if (TRACE_LINES) logerror("%s: Select hard disk WDS%d\n", tag(), index);
// if (index>=0) m_hdc9234->connect_hard_drive(m_harddisk_unit[index-1]);
}
if (m_current_harddisk==NULL)
index = bit_to_index((data>>4) & 0x0f);
if (index > 0) connect_harddisk_unit(index-1); // HD selected; index >= 1
else
{
disconnect_floppy_drives();
disconnect_hard_drives();
// Turn off READY and SEEK COMPLETE
set_bits(m_status_latch, HDC_DS_READY | HDC_DS_SKCOM, false);
}
}
@ -643,6 +664,13 @@ WRITE8_MEMBER( myarc_hfdc_device::auxbus_out )
m_current_floppy->dir_w((data & 0x20)==0);
m_current_floppy->stp_w((data & 0x10)==0);
}
if (m_current_harddisk != NULL)
{
// Dir = 0 -> outward
m_current_harddisk->direction_in_w((data & 0x20)? ASSERT_LINE : CLEAR_LINE);
m_current_harddisk->step_w((data & 0x10)? ASSERT_LINE : CLEAR_LINE);
}
// We are pushing the drive status after OUTPUT2
signal_drive_status();
@ -659,52 +687,74 @@ enum
void myarc_hfdc_device::connect_floppy_unit(int index)
{
// Check if we have a new floppy
if (index>=0)
if (m_floppy_unit[index] != m_current_floppy)
{
if (m_floppy_unit[index] != m_current_floppy)
{
if (TRACE_LINES) logerror("%s: Select floppy drive DSK%d\n", tag(), index+1);
if (m_current_floppy != NULL)
{
// Disconnect old drive from index line
if (TRACE_LINES) logerror("%s: Disconnect previous index callback DSK%d\n", tag(), index+1);
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
}
// Connect new drive
m_current_floppy = m_floppy_unit[index];
// We don't use the READY line of floppy drives.
// READY is asserted when DSKx = 1
// The controller fetches the state with the auxbus access
if (TRACE_LINES) logerror("%s: Connect index callback DSK%d\n", tag(), index+1);
if (m_current_floppy != NULL)
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(myarc_hfdc_device::floppy_index_callback), this));
else
logerror("%s: Connection to DSK%d failed because no drive is connected\n", tag(), index+1);
m_hdc9234->connect_floppy_drive(m_floppy_unit[index]);
}
}
else
{
if (TRACE_LINES) logerror("%s: Unselect all floppy drives\n", tag());
// Disconnect current floppy
disconnect_floppy_drives();
if (TRACE_LINES) logerror("%s: Select floppy drive DSK%d\n", tag(), index+1);
// Connect new drive
m_current_floppy = m_floppy_unit[index];
// We don't use the READY line of floppy drives.
// READY is asserted when DSKx = 1
// The controller fetches the state with the auxbus access
if (TRACE_LINES) logerror("%s: Connect index callback DSK%d\n", tag(), index+1);
if (m_current_floppy != NULL)
{
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
m_current_floppy = NULL;
}
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(myarc_hfdc_device::floppy_index_callback), this));
else
logerror("%s: Connection to DSK%d failed because no drive is connected\n", tag(), index+1);
m_hdc9234->connect_floppy_drive(m_floppy_unit[index]);
}
// The drive status is supposed to be sampled after OUTPUT2
// signal_drive_status();
// We can only run a floppy or a harddisk at a time, not both
disconnect_hard_drives();
}
void myarc_hfdc_device::connect_harddisk_unit(int index)
{
// if (index < 0)
// {
if (m_harddisk_unit[index] != m_current_harddisk)
{
disconnect_hard_drives();
if (TRACE_LINES) logerror("%s: Select hard disk WDS%d\n", tag(), index+1);
// Connect new drive
m_current_harddisk = m_harddisk_unit[index];
if (TRACE_LINES) logerror("%s: Connect index callback WDS%d\n", tag(), index+1);
if (m_current_harddisk != NULL)
{
m_current_harddisk->setup_index_pulse_cb(mfm_harddisk_device::index_pulse_cb(FUNC(myarc_hfdc_device::harddisk_index_callback), this));
m_current_harddisk->setup_seek_complete_cb(mfm_harddisk_device::seek_complete_cb(FUNC(myarc_hfdc_device::harddisk_skcom_callback), this));
}
else
logerror("%s: Connection to WDS%d failed because no drive is connected\n", tag(), index+1);
m_hdc9234->connect_hard_drive(m_current_harddisk);
}
// We can only run a floppy or a harddisk at a time, not both
disconnect_floppy_drives();
}
void myarc_hfdc_device::disconnect_floppy_drives()
{
if (TRACE_LINES) logerror("%s: Unselect floppy drives\n", tag());
// Disconnect current floppy
if (m_current_floppy != NULL)
{
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
m_current_floppy = NULL;
}
}
void myarc_hfdc_device::disconnect_hard_drives()
{
if (TRACE_LINES) logerror("%s: Unselect hard drives\n", tag());
if (m_current_harddisk != NULL)
{
m_current_harddisk->setup_index_pulse_cb(mfm_harddisk_device::index_pulse_cb());
m_current_harddisk->setup_seek_complete_cb(mfm_harddisk_device::seek_complete_cb());
m_current_harddisk = NULL;
// }
// signal_drive_status();
}
}
/*
@ -836,26 +886,45 @@ void myarc_hfdc_device::device_reset()
for (int i=0; i < 4; i++)
{
if (m_floppy_unit[i] != NULL)
logerror("%s: Connector %d with %s\n", tag(), i, m_floppy_unit[i]->name());
logerror("%s: FD connector %d with %s\n", tag(), i+1, m_floppy_unit[i]->name());
else
logerror("%s: Connector %d has no floppy attached\n", tag(), i);
logerror("%s: FD connector %d has no floppy attached\n", tag(), i+1);
}
for (int i=0; i < 3; i++)
{
if (m_harddisk_unit[i] != NULL)
logerror("%s: HD connector %d with %s\n", tag(), i+1, m_harddisk_unit[i]->name());
else
logerror("%s: HD connector %d has no drive attached\n", tag(), i+1);
}
// Disconnect all units
connect_floppy_unit(-1);
connect_harddisk_unit(-1);
disconnect_floppy_drives();
disconnect_hard_drives();
}
void myarc_hfdc_device::device_config_complete()
{
for (int i=0; i < 4; i++)
for (int i=0; i < 3; i++)
{
m_floppy_unit[i] = NULL;
m_harddisk_unit[i] = NULL;
}
m_floppy_unit[3] = NULL;
// Seems to be null when doing a "-listslots"
if (subdevice("f0")!=NULL) m_floppy_unit[0] = static_cast<floppy_image_device*>(subdevice("f0")->first_subdevice());
if (subdevice("f1")!=NULL) m_floppy_unit[1] = static_cast<floppy_image_device*>(subdevice("f1")->first_subdevice());
if (subdevice("f2")!=NULL) m_floppy_unit[2] = static_cast<floppy_image_device*>(subdevice("f2")->first_subdevice());
if (subdevice("f3")!=NULL) m_floppy_unit[3] = static_cast<floppy_image_device*>(subdevice("f3")->first_subdevice());
if (subdevice("f1")!=NULL)
{
m_floppy_unit[0] = static_cast<floppy_connector*>(subdevice("f1"))->get_device();
m_floppy_unit[1] = static_cast<floppy_connector*>(subdevice("f2"))->get_device();
m_floppy_unit[2] = static_cast<floppy_connector*>(subdevice("f3"))->get_device();
m_floppy_unit[3] = static_cast<floppy_connector*>(subdevice("f4"))->get_device();
m_harddisk_unit[0] = static_cast<mfm_harddisk_connector*>(subdevice("h1"))->get_device();
m_harddisk_unit[1] = static_cast<mfm_harddisk_connector*>(subdevice("h2"))->get_device();
m_harddisk_unit[2] = static_cast<mfm_harddisk_connector*>(subdevice("h3"))->get_device();
}
}
/*
@ -918,6 +987,11 @@ static SLOT_INTERFACE_START( hfdc_floppies )
SLOT_INTERFACE( "35hd", FLOPPY_35_HD ) // 80 tracks 1.4 MiB
SLOT_INTERFACE_END
static SLOT_INTERFACE_START( hfdc_harddisks )
SLOT_INTERFACE( "generic", MFM_HD_GENERIC ) // Generic high-level emulation
// SLOT_INTERFACE( "seagatemfm", MFM_HD_SEAGATE ) // Seagate ST-225 and others
SLOT_INTERFACE_END
MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
MCFG_DEVICE_ADD(FDC_TAG, HDC9234, 0)
MCFG_HDC9234_INTRQ_CALLBACK(WRITELINE(myarc_hfdc_device, intrq_w))
@ -927,11 +1001,16 @@ MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
MCFG_HDC9234_DMA_IN_CALLBACK(READ8(myarc_hfdc_device, read_buffer))
MCFG_HDC9234_DMA_OUT_CALLBACK(WRITE8(myarc_hfdc_device, write_buffer))
MCFG_FLOPPY_DRIVE_ADD("f0", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("f1", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("f2", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("f2", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("f3", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("f4", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
// NB: Hard disks don't go without image (other than floppy drives)
MCFG_MFM_HARDDISK_ADD("h1", hfdc_harddisks, NULL)
MCFG_MFM_HARDDISK_ADD("h2", hfdc_harddisks, NULL)
MCFG_MFM_HARDDISK_ADD("h3", hfdc_harddisks, NULL)
MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
MCFG_MM58274C_MODE24(1) // 24 hour
MCFG_MM58274C_DAY1(0) // sunday
@ -962,6 +1041,27 @@ ioport_constructor myarc_hfdc_device::device_input_ports() const
const device_type TI99_HFDC = &device_creator<myarc_hfdc_device>;
mfm_harddisk_connector::mfm_harddisk_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock):
device_t(mconfig, MFM_HD_CONNECTOR, "MFM hard disk connector", tag, owner, clock, "mfm_hd_connector", __FILE__),
device_slot_interface(mconfig, *this)
{
}
mfm_harddisk_connector::~mfm_harddisk_connector()
{
}
mfm_harddisk_device *mfm_harddisk_connector::get_device()
{
return dynamic_cast<mfm_harddisk_device *>(get_card_device());
}
void mfm_harddisk_connector::device_start()
{
}
const device_type MFM_HD_CONNECTOR = &device_creator<mfm_harddisk_connector>;
// =========================================================================
/*
@ -1252,7 +1352,7 @@ READ8_MEMBER( myarc_hfdc_legacy_device::auxbus_in )
{
UINT8 state;
index = slog2((m_output1_latch>>4) & 0x0f)-1;
mfm_harddisk_device *hd = m_harddisk_unit[index];
mfm_harddisk_legacy_device *hd = m_harddisk_unit[index];
state = hd->get_status();
if (state & MFMHD_TRACK00) reply |= DS_TRK00;
@ -1373,6 +1473,8 @@ MACHINE_CONFIG_FRAGMENT( ti99_hfdc_legacy )
MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
MCFG_MM58274C_MODE24(1) // 24 hour
MCFG_MM58274C_DAY1(0) // sunday
MCFG_MFMHD_3_DRIVES_ADD() // add hard disks
MACHINE_CONFIG_END
ROM_START( ti99_hfdc_legacy )
@ -1461,9 +1563,9 @@ void myarc_hfdc_legacy_device::device_reset()
m_floppy_unit[2] = static_cast<legacy_floppy_image_device *>(m_slot->get_drive(FLOPPY_2));
m_floppy_unit[3] = static_cast<legacy_floppy_image_device *>(m_slot->get_drive(FLOPPY_3));
m_harddisk_unit[0] = static_cast<mfm_harddisk_device *>(m_slot->get_drive(MFMHD_0));
m_harddisk_unit[1] = static_cast<mfm_harddisk_device *>(m_slot->get_drive(MFMHD_1));
m_harddisk_unit[2] = static_cast<mfm_harddisk_device *>(m_slot->get_drive(MFMHD_2));
m_harddisk_unit[0] = static_cast<mfm_harddisk_legacy_device *>(subdevice(MFMHD_0));
m_harddisk_unit[1] = static_cast<mfm_harddisk_legacy_device *>(subdevice(MFMHD_1));
m_harddisk_unit[2] = static_cast<mfm_harddisk_legacy_device *>(subdevice(MFMHD_2));
if (ioport("HFDCDIP")->read()&0x55)
ti99_set_80_track_drives(TRUE);

View File

@ -18,11 +18,12 @@
#define __HFDC__
#define HFDC_MAX_FLOPPY 4
#define HFDC_MAX_HARD 4
#define HFDC_MAX_HARD 3
#include "imagedev/floppy.h"
#include "machine/mm58274c.h"
#include "machine/hdc9234.h"
#include "machine/ti99_hd.h"
extern const device_type TI99_HFDC;
@ -49,11 +50,13 @@ public:
DECLARE_FLOPPY_FORMATS( floppy_formats );
protected:
void device_config_complete();
private:
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
void device_start();
void device_reset();
void device_config_complete();
const rom_entry *device_rom_region() const;
machine_config_constructor device_mconfig_additions() const;
@ -63,18 +66,24 @@ private:
void debug_read(offs_t offset, UINT8* value);
void debug_write(offs_t offset, UINT8 data);
// Callback for the index hole
// Callbacks for the index hole and seek complete
void floppy_index_callback(floppy_image_device *floppy, int state);
void harddisk_index_callback(mfm_harddisk_device *harddisk, int state);
void harddisk_skcom_callback(mfm_harddisk_device *harddisk, int state);
// Operate the floppy motors
void set_floppy_motors_running(bool run);
// Connect or disconnect floppy drives
// Connect floppy drives
void connect_floppy_unit(int index);
// Connect or disconnect harddisk drives
// Connect harddisk drives
void connect_harddisk_unit(int index);
// Disconnect drives
void disconnect_floppy_drives();
void disconnect_hard_drives();
// Pushes the drive status to the HDC
void signal_drive_status();
@ -90,11 +99,14 @@ private:
// Link to the attached floppy drives
floppy_image_device* m_floppy_unit[4];
// Link to the attached hard disks
mfm_harddisk_device* m_harddisk_unit[3];
// Currently selected floppy drive
floppy_image_device* m_current_floppy;
// Currently selected hard drive
void* m_current_harddisk;
mfm_harddisk_device* m_current_harddisk;
// True: Access to DIP switch settings, false: access to line states
bool m_see_switches;
@ -159,8 +171,8 @@ private:
// Signal motor_on. When TRUE, makes all drives turning.
line_state m_MOTOR_ON;
// Calculates a simple version of a binary logarithm
int slog2(int value);
// Calculates the index from the bit
int bit_to_index(int value);
// Utility function to set or unset bits in a byte
void set_bits(UINT8& byte, int mask, bool set);
@ -170,6 +182,26 @@ private:
int m_readyflags;
};
/* Connector for a MFM hard disk. See also floppy.c */
class mfm_harddisk_connector : public device_t,
public device_slot_interface
{
public:
mfm_harddisk_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~mfm_harddisk_connector();
mfm_harddisk_device *get_device();
protected:
void device_start();
};
extern const device_type MFM_HD_CONNECTOR;
#define MCFG_MFM_HARDDISK_ADD(_tag, _slot_intf, _def_slot) \
MCFG_DEVICE_ADD(_tag, MFM_HD_CONNECTOR, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false);
// =========================================================================
/*
@ -250,7 +282,7 @@ private:
legacy_floppy_image_device* m_floppy_unit[HFDC_MAX_FLOPPY];
/* Connected harddisk drives. */
mfm_harddisk_device* m_harddisk_unit[HFDC_MAX_HARD];
mfm_harddisk_legacy_device* m_harddisk_unit[HFDC_MAX_HARD];
/* DMA address latch */
UINT32 m_dma_address;

View File

@ -467,8 +467,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_device::device_mconfig_additions() const
@ -536,7 +534,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_gen_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_gen_device::device_mconfig_additions() const
@ -589,7 +586,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_998_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_998_device::device_mconfig_additions() const
@ -643,7 +639,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_sg_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_sg_device::device_mconfig_additions() const
@ -651,7 +646,6 @@ machine_config_constructor peribox_sg_device::device_mconfig_additions() const
return MACHINE_CONFIG_NAME( peribox_sg_device );
}
/****************************************************************************
Another variant of the box; used for the TI with EVPC. The EVPC is
obviously required.
@ -684,7 +678,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_ev_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_ev_device::device_mconfig_additions() const

View File

@ -47,6 +47,20 @@ harddisk_image_device::harddisk_image_device(const machine_config &mconfig, cons
{
}
//-------------------------------------------------
// harddisk_image_device - constructor for subclasses
//-------------------------------------------------
harddisk_image_device::harddisk_image_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_image_interface(mconfig, *this),
m_chd(NULL),
m_hard_disk_handle(NULL),
m_device_image_load(device_image_load_delegate()),
m_device_image_unload(device_image_func_delegate()),
m_interface(NULL)
{
}
//-------------------------------------------------
// harddisk_image_device - destructor
//-------------------------------------------------

View File

@ -51,6 +51,8 @@ public:
chd_file *get_chd_file();
protected:
harddisk_image_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
// device-level overrides
virtual void device_config_complete();
virtual void device_start();

View File

@ -24,37 +24,37 @@
#include "hdc9234.h"
// Per-command debugging
#define TRACE_SELECT 0
#define TRACE_STEP 0
#define TRACE_RESTORE 0
#define TRACE_SUBSTATES 0
#define TRACE_READ 0
#define TRACE_WRITE 0
#define TRACE_READREG 0
#define TRACE_SETREG 0
#define TRACE_SETPTR 0
#define TRACE_FORMAT 0
#define TRACE_READTRACK 0
#define TRACE_SELECT 1
#define TRACE_STEP 1
#define TRACE_RESTORE 1
#define TRACE_SUBSTATES 1
#define TRACE_READ 1
#define TRACE_WRITE 1
#define TRACE_READREG 1
#define TRACE_SETREG 1
#define TRACE_SETPTR 1
#define TRACE_FORMAT 1
#define TRACE_READTRACK 1
// Common states
#define TRACE_READID 0
#define TRACE_VERIFY 0
#define TRACE_TRANSFER 0
#define TRACE_READID 1
#define TRACE_VERIFY 1
#define TRACE_TRANSFER 1
// Live states debugging
#define TRACE_LIVE 0
#define TRACE_SHIFT 0
#define TRACE_SYNC 0
#define TRACE_LIVE 1
#define TRACE_SHIFT 1
#define TRACE_SYNC 1
// Misc debugging
#define TRACE_DELAY 0
#define TRACE_INT 0
#define TRACE_LINES 0
#define TRACE_INDEX 0
#define TRACE_DMA 0
#define TRACE_DONE 0
#define TRACE_FAIL 0
#define TRACE_AUXBUS 0
#define TRACE_INT 1
#define TRACE_LINES 1
#define TRACE_INDEX 1
#define TRACE_DMA 1
#define TRACE_DONE 1
#define TRACE_FAIL 1
#define TRACE_AUXBUS 1
#define TRACE_DETAIL 0
@ -239,8 +239,8 @@ enum
enum
{
GEN_TIMER = 1,
COM_TIMER,
LIVE_TIMER
COM_TIMER /*,
LIVE_TIMER */
};
/*
@ -1027,6 +1027,7 @@ void hdc9234_device::drive_deselect()
{
if (TRACE_SELECT) logerror("%s: DESELECT command\n", tag());
m_selected_drive_number = NODRIVE;
m_output1 = 0x00;
set_command_done(TC_SUCCESS);
}
@ -1066,7 +1067,7 @@ void hdc9234_device::restore_drive()
// Track 0 has not been reached yet
if ((m_register_r[DRIVE_STATUS] & HDC_DS_READY)==0)
{
if (TRACE_RESTORE) logerror("%s: restore command: drive not ready\n", tag());
if (TRACE_RESTORE) logerror("%s: restore command: Drive not ready\n", tag());
// Does not look like a success, but this takes into account
// that if a drive is not connected we do not want an error message
cont = SUCCESS;
@ -1081,6 +1082,7 @@ void hdc9234_device::restore_drive()
// When we have buffered steps, the seek limit will be reached
// before TRK00 is asserted. In that case we have to wait for
// SEEK_COMPLETE. We also wait as soon as TRK00 is asserted.
if (TRACE_RESTORE) logerror("%s: restore using buffered steps\n", tag());
wait_line(SEEKCOMP_LINE, ASSERT_LINE, SEEK_COMPLETE, false);
cont = WAIT;
}
@ -1809,7 +1811,8 @@ void hdc9234_device::live_start(int state)
void hdc9234_device::live_run()
{
live_run_until(attotime::never);
if (using_floppy()) live_run_until(attotime::never);
else live_run_hd_until(attotime::never);
}
/*
@ -1817,6 +1820,8 @@ void hdc9234_device::live_run()
the requested data are read.
limit: if unlimited (attotime::never), run up to the end of the track and wait there
otherwise, used to replay the read/write operation up to the point where the event happened
THIS IS THE FLOPPY-ONLY LIVE_RUN
*/
void hdc9234_device::live_run_until(attotime limit)
{
@ -2622,6 +2627,40 @@ void hdc9234_device::live_run_until(attotime limit)
m_last_live_state = UNDEF;
}
/*
The main method of the live state machine. We stay in this method until
the requested data are read.
limit: if unlimited (attotime::never), run up to the end of the track and wait there
otherwise, used to replay the read/write operation up to the point where the event happened
THIS IS THE HARDDISK-ONLY LIVE_RUN
*/
void hdc9234_device::live_run_hd_until(attotime limit)
{
int slot = 0;
logerror("%s: live_run_hd\n", tag());
if (m_live_state.state == IDLE || m_live_state.next_state != -1)
return;
if (TRACE_LIVE)
{
if (limit == attotime::never)
logerror("%s: [%s] live_run_hd, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).cstr(), m_live_state.state, fm_mode()? "FM":"MFM");
else
logerror("%s: [%s] live_run_hd until %s, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).cstr(), tts(limit).cstr(), m_live_state.state, fm_mode()? "FM":"MFM");
}
while (true)
{
switch (m_live_state.state)
{
case SEARCH_IDAM:
break;
}
return;
}
}
/*
Synchronize the live position on the track with the real time.
Results in a new checkpoint and a live position at machine time or behind.
@ -3269,7 +3308,7 @@ void hdc9234_device::auxbus_out()
m_output2 = (m_output2 & 0xb0) | desired_head();
if (m_reduced_write_current) m_output2 |= OUT2_REDWRT;
if (TRACE_AUXBUS) logerror("%s: Setting OUTPUT2 to %02x\n", tag(), m_output2);
if (TRACE_AUXBUS) logerror("%s: [%s] Setting OUTPUT1=%02x, OUTPUT2=%02x\n", tag(), ttsn().cstr(), m_output1, m_output2);
if (m_output1 != m_output1_old || m_output2 != m_output2_old)
{
@ -3337,6 +3376,14 @@ void hdc9234_device::connect_floppy_drive(floppy_image_device* floppy)
m_floppy = floppy;
}
/*
Connect the current hard drive.
*/
void hdc9234_device::connect_hard_drive(mfm_harddisk_device* harddisk)
{
m_harddisk = harddisk;
}
/*
Clock divider. This input line actually belongs to the data separator which
is a separate circuit. Maybe we will take it out of this implementation
@ -3363,9 +3410,9 @@ void hdc9234_device::device_timer(emu_timer &timer, device_timer_id id, int para
case COM_TIMER:
process_command();
break;
case LIVE_TIMER:
/* case LIVE_TIMER:
live_run();
break;
break; */
}
}
@ -3393,7 +3440,7 @@ void hdc9234_device::device_start()
// allocate timers
m_timer = timer_alloc(GEN_TIMER);
m_cmd_timer = timer_alloc(COM_TIMER);
m_live_timer = timer_alloc(LIVE_TIMER);
// m_live_timer = timer_alloc(LIVE_TIMER);
m_live_state.state = IDLE;
}

View File

@ -10,6 +10,7 @@
#include "emu.h"
#include "imagedev/floppy.h"
#include "fdc_pll.h"
#include "ti99_hd.h"
extern const device_type HDC9234;
@ -109,6 +110,9 @@ public:
// is changed outside of the controller, and by this way we let it know.
void connect_floppy_drive(floppy_image_device *floppy);
// Used to reconfigure the drive connections. See connect_floppy_drive.
void connect_hard_drive(mfm_harddisk_device *harddisk);
protected:
void device_start();
void device_reset();
@ -134,6 +138,9 @@ private:
// Currently connected floppy
floppy_image_device* m_floppy;
// Currently connected harddisk
mfm_harddisk_device* m_harddisk;
// internal register OUTPUT1
UINT8 m_output1, m_output1_old;
@ -220,6 +227,9 @@ private:
// Analyses the track until the given time
void live_run_until(attotime limit);
// Same for hard disks
void live_run_hd_until(attotime limit);
// Live run until next index pulse
void live_run();

View File

@ -1991,7 +1991,7 @@ void smc92x4_device::connect_floppy_drive(legacy_floppy_image_device *drive)
else LOG("smc92x4: Connect drive %s\n", drive->tag());
}
}
void smc92x4_device::connect_hard_drive(mfm_harddisk_device *drive)
void smc92x4_device::connect_hard_drive(mfm_harddisk_legacy_device *drive)
{
m_harddisk = drive;
if (VERBOSE>3)

View File

@ -99,7 +99,7 @@ public:
// Used to reconfigure the drive connections. Drive selection is done
// using the select lines and maybe also the user-programmable outputs.
void connect_floppy_drive(legacy_floppy_image_device *drive);
void connect_hard_drive(mfm_harddisk_device *drive);
void connect_hard_drive(mfm_harddisk_legacy_device *drive);
void reset();
@ -223,7 +223,7 @@ private:
// We expect the embedding board to replace the drive according to the
// select lines.
legacy_floppy_image_device *m_drive;
mfm_harddisk_device *m_harddisk;
mfm_harddisk_legacy_device *m_harddisk;
};
#endif

View File

@ -2,23 +2,21 @@
// copyright-holders:Michael Zapf
/*************************************************************************
Hard disk support
This device wraps the plain image device as that device does not allow
for internal states (like head position)
The plain device is a subdevice ("drive") of this device, so we
get names like "mfmhd0:drive"
Hard disk emulation
Michael Zapf
April 2010
February 2012: Rewritten as class
April 2015: Rewritten with deeper emulation detail
References:
[1] ST225 OEM Manual, Seagate
**************************************************************************/
#include "emu.h"
#include "formats/imageutl.h"
#include "harddisk.h"
#include "smc92x4.h"
#include "ti99_hd.h"
@ -33,8 +31,211 @@
#define GAP4 340
#define SYNC 13
mfm_harddisk_device::mfm_harddisk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, TI99_MFMHD, "MFM Harddisk", tag, owner, clock, "mfm_harddisk", __FILE__)
enum
{
INDEX_TM = 0,
SPINUP_TM,
SEEK_TM
};
enum
{
STEP_COLLECT = 0,
STEP_MOVING,
STEP_SETTLE
};
mfm_harddisk_device::mfm_harddisk_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)
: harddisk_image_device(mconfig, type, name, tag, owner, clock, shortname, source),
device_slot_card_interface(mconfig, *this)
{
}
void mfm_harddisk_device::device_start()
{
m_index_timer = timer_alloc(INDEX_TM);
m_spinup_timer = timer_alloc(SPINUP_TM);
m_seek_timer = timer_alloc(SEEK_TM);
// MFM drives have a revolution rate of 3600 rpm (i.e. 60/sec)
m_index_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
// Spinup may take up to 24 seconds
m_spinup_timer->adjust(attotime::from_msec(8000));
m_current_cylinder = 10; // for test purpose
}
void mfm_harddisk_device::device_reset()
{
m_autotruncation = false;
m_ready = false;
m_seek_complete = true;
m_seek_inward = false;
m_track_delta = 0;
m_step_line = CLEAR_LINE;
}
void mfm_harddisk_device::setup_index_pulse_cb(index_pulse_cb cb)
{
m_index_pulse_cb = cb;
}
void mfm_harddisk_device::setup_seek_complete_cb(seek_complete_cb cb)
{
m_seek_complete_cb = cb;
}
void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
case INDEX_TM:
/* Simple index hole handling. We assume that there is only a short pulse. */
if (!m_index_pulse_cb.isnull())
{
m_index_pulse_cb(this, ASSERT_LINE);
m_index_pulse_cb(this, CLEAR_LINE);
}
break;
case SPINUP_TM:
m_ready = true;
logerror("%s: Spinup complete, drive is ready\n", tag());
break;
case SEEK_TM:
switch (m_step_phase)
{
case STEP_COLLECT:
// Collect timer has expired; start moving head
head_move();
break;
case STEP_MOVING:
// Head has reached final position
// Check whether we have a new delta
if (m_track_delta == 0)
{
// Start the settle timer
m_step_phase = STEP_SETTLE;
m_seek_timer->adjust(attotime::from_usec(16800));
}
break;
case STEP_SETTLE:
// Do we have new step pulses?
if (m_track_delta != 0) head_move();
else
{
// Seek completed
m_seek_complete = true;
m_seek_complete_cb(this, ASSERT_LINE);
m_step_phase = STEP_COLLECT;
}
break;
}
}
}
void mfm_harddisk_device::head_move()
{
int disttime = m_track_delta*200;
if (disttime < 0) disttime = -disttime;
m_step_phase = STEP_MOVING;
m_seek_timer->adjust(attotime::from_usec(disttime));
// We pretend that we already arrived
// TODO: Check auto truncation?
m_current_cylinder += m_track_delta;
if (m_current_cylinder < 0) m_current_cylinder = 0;
if (m_current_cylinder > 670) m_current_cylinder = 670;
m_track_delta = 0;
}
void mfm_harddisk_device::direction_in_w(line_state line)
{
m_seek_inward = (line == ASSERT_LINE);
logerror("%s: Setting seek direction %s\n", tag(), m_seek_inward? "inward" : "outward");
}
/*
According to the specs [1]:
"4.3.1 BUFFERED SEEK: To minimize access time, pulses may be issued at an
accelerated rate and buffered in a counter. Initiation of a seek starts
immediately after the first pulse is received. Head motion occurs during
pulse accumulation, and the seek is completed following receipt of all pulses."
"8.1.3 SEEKING: Upon receiving a Step pulse, the MPU (microprocessor unit)
pauses for 250 usec to allow for additional pulses before executing the seek
operation. Every incoming pulse resets the 250 usec timer. The seek will
not begin until the last pulse is received."
WTF? Oh come on, Seagate, be consistent at least in a single document.
================================
Step behaviour:
During all waiting times, further step_w invocations increase the counter
- Leading edge increments the counter c and sets the timer to 250us (mode=collect)
- When the timer expires (mode=collect):
(1)- Calculate the stepping time: time = c*200us; save the counter
- Start the timer (mode=move)
- When the timer expires (mode=move)
- Add the track delta to the current track position
- Subtract the delta from the current counter
- When the counter is not zero (pulses arrived in the meantime), go to (1)
- When the counter is zero, set the timer to 16.8 ms (mode=settle)
- When the timer expires (mode=settle)
- When the counter is not zero, go to (1)
- When the counter is zero, signal seek_complete; done
Step timing:
per track = 20 ms max, full seek: 150 ms max (615 tracks); both including settling time
We assume t(1) = 17; t(615)=140
t(i) = s+d*i
s=(615*t(1)-t(615))/614
d=t(1)-s
s=16800 us, d=200 us
*/
void mfm_harddisk_device::step_w(line_state line)
{
// Leading edge
if (line == ASSERT_LINE && m_step_line == CLEAR_LINE)
{
if (m_seek_complete)
{
m_step_phase = STEP_COLLECT;
m_seek_complete = false;
m_seek_complete_cb(this, CLEAR_LINE);
}
logerror("%s: Got seek pulse; distance %d, direction %s\n", tag(), m_track_delta, m_seek_inward? "inward" : "outward");
// Counter will be adjusted according to the direction (+-1)
m_track_delta += (m_seek_inward)? +1 : -1;
if (m_track_delta < 0 || m_track_delta > 670)
{
logerror("%s: Excessive step pulses - doing auto-truncation\n", tag());
m_autotruncation = true;
}
m_seek_timer->adjust(attotime::from_usec(250));
}
m_step_line = line;
}
mfm_hd_generic_device::mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: mfm_harddisk_device(mconfig, MFM_HD_GENERIC, "Generic MFM hard disk (byte level)", tag, owner, clock, "mfm_harddisk", __FILE__)
{
}
const device_type MFM_HD_GENERIC = &device_creator<mfm_hd_generic_device>;
// ===========================================================================
// Legacy implementation
// ===========================================================================
#include "smc92x4.h"
mfm_harddisk_legacy_device::mfm_harddisk_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, TI99_MFMHD_LEG, "MFM Harddisk LEGACY", tag, owner, clock, "mfm_harddisk_leg", __FILE__)
{
}
@ -43,7 +244,7 @@ mfm_harddisk_device::mfm_harddisk_device(const machine_config &mconfig, const ch
define idents beyond cylinder 1023, but formatting programs seem to
continue with 0xfd for cylinders between 1024 and 2047.
*/
UINT8 mfm_harddisk_device::cylinder_to_ident(int cylinder)
UINT8 mfm_harddisk_legacy_device::cylinder_to_ident(int cylinder)
{
if (cylinder < 256) return 0xfe;
if (cylinder < 512) return 0xff;
@ -55,7 +256,7 @@ UINT8 mfm_harddisk_device::cylinder_to_ident(int cylinder)
/*
Returns the linear sector number, given the CHS data.
*/
bool mfm_harddisk_device::harddisk_chs_to_lba(hard_disk_file *hdfile, int cylinder, int head, int sector, UINT32 *lba)
bool mfm_harddisk_legacy_device::harddisk_chs_to_lba(hard_disk_file *hdfile, int cylinder, int head, int sector, UINT32 *lba)
{
const hard_disk_info *info;
@ -77,7 +278,7 @@ bool mfm_harddisk_device::harddisk_chs_to_lba(hard_disk_file *hdfile, int cylind
}
/* Accessor functions */
void mfm_harddisk_device::read_sector(int cylinder, int head, int sector, UINT8 *buf)
void mfm_harddisk_legacy_device::read_sector(int cylinder, int head, int sector, UINT8 *buf)
{
UINT32 lba;
if (VERBOSE>5) LOG("ti99_hd: read_sector(%d, %d, %d)\n", cylinder, head, sector);
@ -109,7 +310,7 @@ void mfm_harddisk_device::read_sector(int cylinder, int head, int sector, UINT8
m_status |= MFMHD_READY;
}
void mfm_harddisk_device::write_sector(int cylinder, int head, int sector, UINT8 *buf)
void mfm_harddisk_legacy_device::write_sector(int cylinder, int head, int sector, UINT8 *buf)
{
UINT32 lba;
if (VERBOSE>5) LOG("ti99_hd: write_sector(%d, %d, %d)\n", cylinder, head, sector);
@ -142,7 +343,7 @@ void mfm_harddisk_device::write_sector(int cylinder, int head, int sector, UINT8
Searches a block containing number * byte, starting at the given
position. Returns the position of the first byte of the block.
*/
int mfm_harddisk_device::find_block(const UINT8 *buffer, int start, int stop, UINT8 byte, size_t number)
int mfm_harddisk_legacy_device::find_block(const UINT8 *buffer, int start, int stop, UINT8 byte, size_t number)
{
int i = start;
size_t current = number;
@ -165,7 +366,7 @@ int mfm_harddisk_device::find_block(const UINT8 *buffer, int start, int stop, UI
return TI99HD_BLOCKNOTFOUND;
}
int mfm_harddisk_device::get_track_length()
int mfm_harddisk_legacy_device::get_track_length()
{
int count;
int size;
@ -187,7 +388,7 @@ int mfm_harddisk_device::get_track_length()
WARNING: This function is untested! We need to create a suitable
application program for the TI which makes use of it.
*/
void mfm_harddisk_device::read_track(int head, UINT8 *trackdata)
void mfm_harddisk_legacy_device::read_track(int head, UINT8 *trackdata)
{
/* We assume an interleave of 3 for 32 sectors. */
int step = 3;
@ -291,7 +492,7 @@ void mfm_harddisk_device::read_track(int head, UINT8 *trackdata)
Writes a track to the image. We need to isolate the sector contents.
This is basically done in the same way as in the SDF format in ti99_dsk.
*/
void mfm_harddisk_device::write_track(int head, UINT8 *track_image, int data_count)
void mfm_harddisk_legacy_device::write_track(int head, UINT8 *track_image, int data_count)
{
int current_pos = 0;
bool found;
@ -401,7 +602,7 @@ void mfm_harddisk_device::write_track(int head, UINT8 *track_image, int data_cou
}
}
UINT8 mfm_harddisk_device::get_status()
UINT8 mfm_harddisk_legacy_device::get_status()
{
UINT8 status = 0;
hard_disk_file *file = m_drive->get_hard_disk_file();
@ -422,7 +623,7 @@ UINT8 mfm_harddisk_device::get_status()
return status;
}
void mfm_harddisk_device::seek(int direction)
void mfm_harddisk_legacy_device::seek(int direction)
{
const hard_disk_info *info;
hard_disk_file *file = m_drive->get_hard_disk_file();
@ -449,7 +650,7 @@ void mfm_harddisk_device::seek(int direction)
m_seeking = false;
}
void mfm_harddisk_device::get_next_id(int head, chrn_id_hd *id)
void mfm_harddisk_legacy_device::get_next_id(int head, chrn_id_hd *id)
{
const hard_disk_info *info;
hard_disk_file *file;
@ -479,13 +680,13 @@ void mfm_harddisk_device::get_next_id(int head, chrn_id_hd *id)
id->flags = 0;
}
void mfm_harddisk_device::device_start()
void mfm_harddisk_legacy_device::device_start()
{
m_current_cylinder = 0;
m_current_head = 0;
}
void mfm_harddisk_device::device_reset()
void mfm_harddisk_legacy_device::device_reset()
{
m_drive = static_cast<harddisk_image_device *>(subdevice("drive"));
m_seeking = false;
@ -497,9 +698,9 @@ MACHINE_CONFIG_FRAGMENT( mfmhd )
MCFG_HARDDISK_ADD("drive")
MACHINE_CONFIG_END
machine_config_constructor mfm_harddisk_device::device_mconfig_additions() const
machine_config_constructor mfm_harddisk_legacy_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( mfmhd );
}
const device_type TI99_MFMHD = &device_creator<mfm_harddisk_device>;
const device_type TI99_MFMHD_LEG = &device_creator<mfm_harddisk_legacy_device>;

View File

@ -17,11 +17,65 @@
#include "emu.h"
#include "imagedev/harddriv.h"
class mfm_harddisk_device : public harddisk_image_device,
public device_slot_card_interface
{
public:
mfm_harddisk_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);
typedef delegate<void (mfm_harddisk_device*, int)> index_pulse_cb;
typedef delegate<void (mfm_harddisk_device*, int)> seek_complete_cb;
void setup_index_pulse_cb(index_pulse_cb cb);
void setup_seek_complete_cb(seek_complete_cb cb);
// Active low lines. We're using ASSERT=0 / CLEAR=1
line_state ready_r() { return m_ready? ASSERT_LINE : CLEAR_LINE; }
line_state seek_complete_r() { return m_seek_complete? ASSERT_LINE : CLEAR_LINE; } ;
line_state trk00_r() { return m_current_cylinder==0? ASSERT_LINE : CLEAR_LINE; }
// Step
void step_w(line_state line);
void direction_in_w(line_state line);
protected:
void device_start();
void device_reset();
emu_timer *m_index_timer, *m_spinup_timer, *m_seek_timer;
index_pulse_cb m_index_pulse_cb;
seek_complete_cb m_seek_complete_cb;
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
bool m_ready;
int m_current_cylinder;
int m_track_delta;
int m_step_phase;
bool m_seek_complete;
bool m_seek_inward;
bool m_seeking;
bool m_autotruncation;
line_state m_step_line; // keep the last state
void head_move();
};
class mfm_hd_generic_device : public mfm_harddisk_device
{
public:
mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};
extern const device_type MFM_HD_GENERIC;
// ===========================================================================
// Legacy implementation
// ===========================================================================
#define MFMHD_0 "mfmhd0"
#define MFMHD_1 "mfmhd1"
#define MFMHD_2 "mfmhd2"
extern const device_type TI99_MFMHD;
extern const device_type TI99_MFMHD_LEG;
/*
Needed to adapt to higher cylinder numbers. Floppies do not have such
@ -37,10 +91,10 @@ struct chrn_id_hd
unsigned long flags;
};
class mfm_harddisk_device : public device_t
class mfm_harddisk_legacy_device : public device_t
{
public:
mfm_harddisk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
mfm_harddisk_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
void read_sector(int cylinder, int head, int sector, UINT8 *buf);
void write_sector(int cylinder, int head, int sector, UINT8 *buf);
@ -52,9 +106,9 @@ public:
int get_track_length();
protected:
virtual void device_start();
virtual void device_reset();
virtual machine_config_constructor device_mconfig_additions() const;
void device_start();
void device_reset();
machine_config_constructor device_mconfig_additions() const;
private:
int find_block(const UINT8 *buffer, int start, int stop, UINT8 byte, size_t number);
@ -70,10 +124,10 @@ private:
harddisk_image_device *m_drive;
};
class ide_harddisk_device : public device_t
class ide_harddisk_legacy_device : public device_t
{
public:
ide_harddisk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
ide_harddisk_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
protected:
virtual void device_start() { };
virtual void device_reset() { };
@ -81,8 +135,8 @@ protected:
};
#define MCFG_MFMHD_3_DRIVES_ADD() \
MCFG_DEVICE_ADD(MFMHD_0, TI99_MFMHD, 0) \
MCFG_DEVICE_ADD(MFMHD_1, TI99_MFMHD, 0) \
MCFG_DEVICE_ADD(MFMHD_2, TI99_MFMHD, 0)
MCFG_DEVICE_ADD(MFMHD_0, TI99_MFMHD_LEG, 0) \
MCFG_DEVICE_ADD(MFMHD_1, TI99_MFMHD_LEG, 0) \
MCFG_DEVICE_ADD(MFMHD_2, TI99_MFMHD_LEG, 0)
#endif