Adding more MFM hard disk models (ST213, ST251)
This commit is contained in:
parent
ee258a156b
commit
3c7513c4e8
@ -1012,7 +1012,9 @@ SLOT_INTERFACE_END
|
|||||||
|
|
||||||
static SLOT_INTERFACE_START( hfdc_harddisks )
|
static SLOT_INTERFACE_START( hfdc_harddisks )
|
||||||
SLOT_INTERFACE( "generic", MFMHD_GENERIC ) // Generic high-level emulation
|
SLOT_INTERFACE( "generic", MFMHD_GENERIC ) // Generic high-level emulation
|
||||||
SLOT_INTERFACE( "st225", MFMHD_ST225 ) // Seagate ST-225 and others
|
SLOT_INTERFACE( "st213", MFMHD_ST213 ) // Seagate ST-213 (10 MB)
|
||||||
|
SLOT_INTERFACE( "st225", MFMHD_ST225 ) // Seagate ST-225 (20 MB)
|
||||||
|
SLOT_INTERFACE( "st251", MFMHD_ST251 ) // Seagate ST-251 (40 MB)
|
||||||
SLOT_INTERFACE_END
|
SLOT_INTERFACE_END
|
||||||
|
|
||||||
MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
|
MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#define TRACE_TIMING 0
|
#define TRACE_TIMING 0
|
||||||
#define TRACE_IMAGE 0
|
#define TRACE_IMAGE 0
|
||||||
#define TRACE_STATE 1
|
#define TRACE_STATE 1
|
||||||
|
#define TRACE_CONFIG 1
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -51,7 +52,6 @@ enum
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define TRACKSLOTS 5
|
#define TRACKSLOTS 5
|
||||||
#define TRACKIMAGE_SIZE 10416 // Provide the buffer for a complete track, including preambles and gaps
|
|
||||||
|
|
||||||
#define OFFLIMIT -1
|
#define OFFLIMIT -1
|
||||||
|
|
||||||
@ -69,8 +69,18 @@ mfm_harddisk_device::mfm_harddisk_device(const machine_config &mconfig, device_t
|
|||||||
{
|
{
|
||||||
m_spinupms = 10000;
|
m_spinupms = 10000;
|
||||||
m_cachelines = TRACKSLOTS;
|
m_cachelines = TRACKSLOTS;
|
||||||
m_max_cylinder = 0;
|
m_max_cylinders = 0;
|
||||||
|
m_phys_cylinders = 0; // We will get this value for generic drives from the image
|
||||||
m_max_heads = 0;
|
m_max_heads = 0;
|
||||||
|
m_cell_size = 100;
|
||||||
|
m_rpm = 3600; // MFM drives have a revolution rate of 3600 rpm (i.e. 60/sec)
|
||||||
|
m_trackimage_size = (int)((60000000000L / (m_rpm * m_cell_size)) / 16 + 1);
|
||||||
|
m_cache = NULL;
|
||||||
|
// We will calculate default values from the time specs later.
|
||||||
|
m_seeknext_time = 0;
|
||||||
|
m_maxseek_time = 0;
|
||||||
|
m_actual_cylinders = 0;
|
||||||
|
m_park_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mfm_harddisk_device::~mfm_harddisk_device()
|
mfm_harddisk_device::~mfm_harddisk_device()
|
||||||
@ -84,17 +94,15 @@ void mfm_harddisk_device::device_start()
|
|||||||
m_seek_timer = timer_alloc(SEEK_TM);
|
m_seek_timer = timer_alloc(SEEK_TM);
|
||||||
m_cache_timer = timer_alloc(CACHE_TM);
|
m_cache_timer = timer_alloc(CACHE_TM);
|
||||||
|
|
||||||
m_rev_time = attotime::from_hz(60);
|
m_rev_time = attotime::from_hz(m_rpm/60);
|
||||||
|
m_index_timer->adjust(attotime::from_hz(m_rpm/60), 0, attotime::from_hz(m_rpm/60));
|
||||||
|
|
||||||
// MFM drives have a revolution rate of 3600 rpm (i.e. 60/sec)
|
m_current_cylinder = m_park_pos; // Park position
|
||||||
m_index_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
|
|
||||||
|
|
||||||
m_current_cylinder = 615; // Park position
|
|
||||||
m_spinup_timer->adjust(attotime::from_msec(m_spinupms));
|
m_spinup_timer->adjust(attotime::from_msec(m_spinupms));
|
||||||
|
|
||||||
m_cache = global_alloc(mfmhd_trackimage_cache);
|
m_cache = global_alloc(mfmhd_trackimage_cache);
|
||||||
|
|
||||||
// In 5 second period, check whether the cache has dirty lines
|
// In 5 second periods, check whether the cache has dirty lines
|
||||||
m_cache_timer->adjust(attotime::from_msec(5000), 0, attotime::from_msec(5000));
|
m_cache_timer->adjust(attotime::from_msec(5000), 0, attotime::from_msec(5000));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,15 +119,41 @@ void mfm_harddisk_device::device_reset()
|
|||||||
|
|
||||||
void mfm_harddisk_device::device_stop()
|
void mfm_harddisk_device::device_stop()
|
||||||
{
|
{
|
||||||
global_free(m_cache);
|
if (m_cache!=NULL) global_free(m_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Load the image from the CHD. We also calculate the head timing here
|
||||||
|
because we need the number of cylinders, and for generic drives we get
|
||||||
|
them from the CHD.
|
||||||
|
*/
|
||||||
bool mfm_harddisk_device::call_load()
|
bool mfm_harddisk_device::call_load()
|
||||||
{
|
{
|
||||||
bool loaded = harddisk_image_device::call_load();
|
bool loaded = harddisk_image_device::call_load();
|
||||||
if (loaded==IMAGE_INIT_PASS)
|
if (loaded==IMAGE_INIT_PASS)
|
||||||
{
|
{
|
||||||
m_cache->init(get_chd_file(), tag(), m_max_cylinder, m_max_heads, m_cachelines, m_encoding);
|
m_cache->init(get_chd_file(), tag(), m_trackimage_size, m_max_cylinders, m_max_heads, m_cachelines, m_encoding);
|
||||||
|
|
||||||
|
// Head timing
|
||||||
|
// We assume that the real times are 80% of the max times
|
||||||
|
// The single-step time includes the settle time, so does the max time
|
||||||
|
// From that we calculate the actual cylinder-by-cylinder time and the settle time
|
||||||
|
|
||||||
|
m_actual_cylinders = m_cache->get_cylinders();
|
||||||
|
if (m_phys_cylinders == 0) m_phys_cylinders = m_actual_cylinders+1;
|
||||||
|
|
||||||
|
m_park_pos = m_phys_cylinders-1;
|
||||||
|
|
||||||
|
float realnext = (m_seeknext_time==0)? 10 : (m_seeknext_time * 0.8);
|
||||||
|
float realmax = (m_maxseek_time==0)? (m_actual_cylinders * 0.2) : (m_maxseek_time * 0.8);
|
||||||
|
float settle_us = ((m_actual_cylinders-1.0) * realnext - realmax) / (m_actual_cylinders-2.0) * 1000;
|
||||||
|
float step_us = realnext * 1000 - settle_us;
|
||||||
|
if (TRACE_CONFIG) logerror("%s: Calculated settle time: %0.2f ms, step: %d us\n", tag(), settle_us/1000, (int)step_us);
|
||||||
|
|
||||||
|
m_settle_time = attotime::from_usec((int)settle_us);
|
||||||
|
m_step_time = attotime::from_usec((int)step_us);
|
||||||
|
|
||||||
|
m_current_cylinder = m_park_pos;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -130,7 +164,7 @@ bool mfm_harddisk_device::call_load()
|
|||||||
|
|
||||||
void mfm_harddisk_device::call_unload()
|
void mfm_harddisk_device::call_unload()
|
||||||
{
|
{
|
||||||
m_cache->cleanup();
|
if (m_cache!=NULL) m_cache->cleanup();
|
||||||
harddisk_image_device::call_unload();
|
harddisk_image_device::call_unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +210,7 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int
|
|||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case INDEX_TM:
|
case INDEX_TM:
|
||||||
/* Simple index hole handling. We assume that there is only a short pulse. */
|
// Simple index hole handling. We assume that there is only a short pulse.
|
||||||
m_revolution_start_time = machine().time();
|
m_revolution_start_time = machine().time();
|
||||||
if (!m_index_pulse_cb.isnull())
|
if (!m_index_pulse_cb.isnull())
|
||||||
{
|
{
|
||||||
@ -207,7 +241,7 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int
|
|||||||
{
|
{
|
||||||
// Start the settle timer
|
// Start the settle timer
|
||||||
m_step_phase = STEP_SETTLE;
|
m_step_phase = STEP_SETTLE;
|
||||||
m_seek_timer->adjust(attotime::from_usec(16800));
|
m_seek_timer->adjust(m_settle_time);
|
||||||
if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Arrived at target cylinder %d, settling ...\n", tag(), m_current_cylinder);
|
if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Arrived at target cylinder %d, settling ...\n", tag(), m_current_cylinder);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -241,7 +275,7 @@ void mfm_harddisk_device::recalibrate()
|
|||||||
{
|
{
|
||||||
if (TRACE_STEPS) logerror("%s: Recalibrate to track 0\n", tag());
|
if (TRACE_STEPS) logerror("%s: Recalibrate to track 0\n", tag());
|
||||||
direction_in_w(CLEAR_LINE);
|
direction_in_w(CLEAR_LINE);
|
||||||
while (-m_track_delta < 620)
|
while (-m_track_delta < m_phys_cylinders)
|
||||||
{
|
{
|
||||||
step_w(ASSERT_LINE);
|
step_w(ASSERT_LINE);
|
||||||
step_w(CLEAR_LINE);
|
step_w(CLEAR_LINE);
|
||||||
@ -254,14 +288,16 @@ void mfm_harddisk_device::head_move()
|
|||||||
if (steps < 0) steps = -steps;
|
if (steps < 0) steps = -steps;
|
||||||
if (TRACE_STEPS) logerror("%s: Moving head by %d step(s) %s\n", tag(), steps, (m_track_delta<0)? "outward" : "inward");
|
if (TRACE_STEPS) logerror("%s: Moving head by %d step(s) %s\n", tag(), steps, (m_track_delta<0)? "outward" : "inward");
|
||||||
|
|
||||||
int disttime = steps*200;
|
// We simulate the head movement by pausing for n*step_time with n being the cylinder delta
|
||||||
m_step_phase = STEP_MOVING;
|
m_step_phase = STEP_MOVING;
|
||||||
m_seek_timer->adjust(attotime::from_usec(disttime));
|
m_seek_timer->adjust(m_step_time * steps);
|
||||||
|
|
||||||
|
if (TRACE_TIMING) logerror("%s: Head movement takes %s time\n", tag(), tts(m_step_time * steps).c_str());
|
||||||
// We pretend that we already arrived
|
// We pretend that we already arrived
|
||||||
// TODO: Check auto truncation?
|
// TODO: Check auto truncation?
|
||||||
m_current_cylinder += m_track_delta;
|
m_current_cylinder += m_track_delta;
|
||||||
if (m_current_cylinder < 0) m_current_cylinder = 0;
|
if (m_current_cylinder < 0) m_current_cylinder = 0;
|
||||||
if (m_current_cylinder > 670) m_current_cylinder = 670;
|
if (m_current_cylinder >= m_actual_cylinders) m_current_cylinder = m_actual_cylinders-1;
|
||||||
m_track_delta = 0;
|
m_track_delta = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,14 +339,6 @@ void mfm_harddisk_device::direction_in_w(line_state line)
|
|||||||
- When the timer expires (mode=settle)
|
- When the timer expires (mode=settle)
|
||||||
- When the counter is not zero, go to (1)
|
- When the counter is not zero, go to (1)
|
||||||
- When the counter is zero, signal seek_complete; done
|
- 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)
|
void mfm_harddisk_device::step_w(line_state line)
|
||||||
@ -328,12 +356,12 @@ void mfm_harddisk_device::step_w(line_state line)
|
|||||||
// Counter will be adjusted according to the direction (+-1)
|
// Counter will be adjusted according to the direction (+-1)
|
||||||
m_track_delta += (m_seek_inward)? +1 : -1;
|
m_track_delta += (m_seek_inward)? +1 : -1;
|
||||||
if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Got seek pulse; track delta %d\n", tag(), m_track_delta);
|
if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Got seek pulse; track delta %d\n", tag(), m_track_delta);
|
||||||
if (m_track_delta < -670 || m_track_delta > 670)
|
if (m_track_delta < -m_phys_cylinders || m_track_delta > m_phys_cylinders)
|
||||||
{
|
{
|
||||||
if (TRACE_STEPS) logerror("%s: Excessive step pulses - doing auto-truncation\n", tag());
|
if (TRACE_STEPS) logerror("%s: Excessive step pulses - doing auto-truncation\n", tag());
|
||||||
m_autotruncation = true;
|
m_autotruncation = true;
|
||||||
}
|
}
|
||||||
m_seek_timer->adjust(attotime::from_usec(250));
|
m_seek_timer->adjust(attotime::from_usec(250)); // Start step collect timer
|
||||||
}
|
}
|
||||||
m_step_line = line;
|
m_step_line = line;
|
||||||
}
|
}
|
||||||
@ -345,25 +373,27 @@ void mfm_harddisk_device::step_w(line_state line)
|
|||||||
*/
|
*/
|
||||||
bool mfm_harddisk_device::find_position(attotime &from_when, const attotime &limit, int &bytepos, int &bit)
|
bool mfm_harddisk_device::find_position(attotime &from_when, const attotime &limit, int &bytepos, int &bit)
|
||||||
{
|
{
|
||||||
|
// Frequency
|
||||||
|
UINT32 freq = 1000000000/m_cell_size;
|
||||||
|
|
||||||
// As we stop some few cells early each track, we adjust our position
|
// As we stop some few cells early each track, we adjust our position
|
||||||
// to the track start
|
// to the track start
|
||||||
if (from_when < m_revolution_start_time) from_when = m_revolution_start_time;
|
if (from_when < m_revolution_start_time) from_when = m_revolution_start_time;
|
||||||
|
|
||||||
// Calculate the position in the track, given the from_when time and the revolution_start_time.
|
// Calculate the position in the track, given the from_when time and the revolution_start_time.
|
||||||
// Each cell takes 100 ns (@10 MHz)
|
int cell = (from_when - m_revolution_start_time).as_ticks(freq);
|
||||||
int cell = (from_when - m_revolution_start_time).as_ticks(10000000);
|
|
||||||
|
|
||||||
from_when += attotime::from_nsec((m_encoding==MFM_BITS)? 100 : 1600);
|
from_when += attotime::from_nsec((m_encoding==MFM_BITS)? m_cell_size : (16*m_cell_size));
|
||||||
if (from_when > limit) return true;
|
if (from_when > limit) return true;
|
||||||
|
|
||||||
bytepos = cell / 16;
|
bytepos = cell / 16;
|
||||||
|
|
||||||
// Reached the end
|
// Reached the end
|
||||||
if (bytepos >= 10416)
|
if (bytepos >= m_trackimage_size)
|
||||||
{
|
{
|
||||||
if (TRACE_TIMING) logerror("%s: Reached end: rev_start = %s, live = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(from_when).c_str());
|
if (TRACE_TIMING) logerror("%s: Reached end: rev_start = %s, live = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(from_when).c_str());
|
||||||
m_revolution_start_time += m_rev_time;
|
m_revolution_start_time += m_rev_time;
|
||||||
cell = (from_when - m_revolution_start_time).as_ticks(10000000);
|
cell = (from_when - m_revolution_start_time).as_ticks(freq);
|
||||||
bytepos = cell / 16;
|
bytepos = cell / 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,15 +494,48 @@ mfm_hd_generic_device::mfm_hd_generic_device(const machine_config &mconfig, cons
|
|||||||
|
|
||||||
const device_type MFMHD_GENERIC = &device_creator<mfm_hd_generic_device>;
|
const device_type MFMHD_GENERIC = &device_creator<mfm_hd_generic_device>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Various models.
|
||||||
|
*/
|
||||||
|
mfm_hd_st213_device::mfm_hd_st213_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
|
: mfm_harddisk_device(mconfig, MFMHD_ST213, "Seagate ST-213 MFM hard disk", tag, owner, clock, "mfm_hd_st213", __FILE__)
|
||||||
|
{
|
||||||
|
m_phys_cylinders = 670;
|
||||||
|
m_max_cylinders = 615; // 0..614
|
||||||
|
m_park_pos = 620;
|
||||||
|
m_max_heads = 2;
|
||||||
|
m_seeknext_time = 20; // time for one step including settle time
|
||||||
|
m_maxseek_time = 150;
|
||||||
|
}
|
||||||
|
|
||||||
|
const device_type MFMHD_ST213 = &device_creator<mfm_hd_st213_device>;
|
||||||
|
|
||||||
mfm_hd_st225_device::mfm_hd_st225_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
mfm_hd_st225_device::mfm_hd_st225_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
: mfm_harddisk_device(mconfig, MFMHD_ST225, "Seagate ST-225 MFM hard disk", tag, owner, clock, "mfm_hd_st225", __FILE__)
|
: mfm_harddisk_device(mconfig, MFMHD_ST225, "Seagate ST-225 MFM hard disk", tag, owner, clock, "mfm_hd_st225", __FILE__)
|
||||||
{
|
{
|
||||||
m_max_cylinder = 615;
|
m_phys_cylinders = 670;
|
||||||
|
m_max_cylinders = 615;
|
||||||
|
m_park_pos = 620;
|
||||||
m_max_heads = 4;
|
m_max_heads = 4;
|
||||||
|
m_seeknext_time = 20;
|
||||||
|
m_maxseek_time = 150;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_type MFMHD_ST225 = &device_creator<mfm_hd_st225_device>;
|
const device_type MFMHD_ST225 = &device_creator<mfm_hd_st225_device>;
|
||||||
|
|
||||||
|
mfm_hd_st251_device::mfm_hd_st251_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
|
: mfm_harddisk_device(mconfig, MFMHD_ST251, "Seagate ST-251 MFM hard disk", tag, owner, clock, "mfm_hd_st251", __FILE__)
|
||||||
|
{
|
||||||
|
m_phys_cylinders = 821;
|
||||||
|
m_max_cylinders = 820;
|
||||||
|
m_park_pos = 820;
|
||||||
|
m_max_heads = 6;
|
||||||
|
m_seeknext_time = 8;
|
||||||
|
m_maxseek_time = 70;
|
||||||
|
}
|
||||||
|
|
||||||
|
const device_type MFMHD_ST251 = &device_creator<mfm_hd_st251_device>;
|
||||||
|
|
||||||
// ===========================================================
|
// ===========================================================
|
||||||
// Track cache
|
// Track cache
|
||||||
// The cache holds track images to be read by the controller.
|
// The cache holds track images to be read by the controller.
|
||||||
@ -483,6 +546,7 @@ mfmhd_trackimage_cache::mfmhd_trackimage_cache():
|
|||||||
m_tracks(NULL)
|
m_tracks(NULL)
|
||||||
{
|
{
|
||||||
m_current_crc = 0;
|
m_current_crc = 0;
|
||||||
|
m_tracksize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mfmhd_trackimage_cache::~mfmhd_trackimage_cache()
|
mfmhd_trackimage_cache::~mfmhd_trackimage_cache()
|
||||||
@ -507,8 +571,8 @@ void mfmhd_trackimage_cache::write_back_one()
|
|||||||
{
|
{
|
||||||
if (current->dirty)
|
if (current->dirty)
|
||||||
{
|
{
|
||||||
if (TRACE_CACHE) logerror("%s: MFM HD cache: write back line c=%d h=%d\n", tag(), current->cylinder, current->head);
|
write_track(m_chd, current->encdata, m_tracksize, current->cylinder, current->head);
|
||||||
write_back(current);
|
current->dirty = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mfmhd_trackimage* currenttmp = current->next;
|
mfmhd_trackimage* currenttmp = current->next;
|
||||||
@ -525,7 +589,11 @@ void mfmhd_trackimage_cache::cleanup()
|
|||||||
while (current != NULL)
|
while (current != NULL)
|
||||||
{
|
{
|
||||||
if (TRACE_CACHE) logerror("%s: MFM HD cache: evict line cylinder=%d head=%d\n", tag(), current->cylinder, current->head);
|
if (TRACE_CACHE) logerror("%s: MFM HD cache: evict line cylinder=%d head=%d\n", tag(), current->cylinder, current->head);
|
||||||
if (current->dirty) write_back(current);
|
if (current->dirty)
|
||||||
|
{
|
||||||
|
write_track(m_chd, current->encdata, m_tracksize, current->cylinder, current->head);
|
||||||
|
current->dirty = false;
|
||||||
|
}
|
||||||
mfmhd_trackimage* currenttmp = current->next;
|
mfmhd_trackimage* currenttmp = current->next;
|
||||||
current = currenttmp;
|
current = currenttmp;
|
||||||
}
|
}
|
||||||
@ -545,7 +613,7 @@ const char *encnames[] = { "MFM_BITS","MFM_BYTE","SEPARATE","SSIMPLE " };
|
|||||||
/*
|
/*
|
||||||
Initialize the cache by loading the first <trackslots> tracks.
|
Initialize the cache by loading the first <trackslots> tracks.
|
||||||
*/
|
*/
|
||||||
void mfmhd_trackimage_cache::init(chd_file* chdfile, const char* dtag, int maxcyl, int maxhead, int trackslots, mfmhd_enc_t encoding)
|
void mfmhd_trackimage_cache::init(chd_file* chdfile, const char* dtag, int tracksize, int maxcyl, int maxhead, int trackslots, mfmhd_enc_t encoding)
|
||||||
{
|
{
|
||||||
m_encoding = encoding;
|
m_encoding = encoding;
|
||||||
m_tagdev = dtag;
|
m_tagdev = dtag;
|
||||||
@ -557,6 +625,7 @@ void mfmhd_trackimage_cache::init(chd_file* chdfile, const char* dtag, int maxcy
|
|||||||
std::string metadata;
|
std::string metadata;
|
||||||
m_calc_interleave = 0;
|
m_calc_interleave = 0;
|
||||||
|
|
||||||
|
m_tracksize = tracksize;
|
||||||
m_chd = chdfile;
|
m_chd = chdfile;
|
||||||
|
|
||||||
if (chdfile==NULL)
|
if (chdfile==NULL)
|
||||||
@ -571,14 +640,16 @@ void mfmhd_trackimage_cache::init(chd_file* chdfile, const char* dtag, int maxcy
|
|||||||
{
|
{
|
||||||
throw emu_fatalerror("Failed to read CHD metadata");
|
throw emu_fatalerror("Failed to read CHD metadata");
|
||||||
}
|
}
|
||||||
|
if (TRACE_CONFIG) logerror("%s: CHD metadata: %s\n", tag(), metadata.c_str());
|
||||||
|
|
||||||
// Parse the metadata
|
// Parse the metadata
|
||||||
if (sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &m_cylinders, &m_heads, &m_sectors_per_track, &m_sectorsize) != 4)
|
if (sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &m_cylinders, &m_heads, &m_sectors_per_track, &m_sectorsize) != 4)
|
||||||
{
|
{
|
||||||
throw emu_fatalerror("Invalid metadata");
|
throw emu_fatalerror("Invalid metadata");
|
||||||
}
|
}
|
||||||
|
if (TRACE_CONFIG) logerror("%s: CHD image has geometry cyl=%d, head=%d, sect=%d, size=%d\n", tag(), m_cylinders, m_heads, m_sectors_per_track, m_sectorsize);
|
||||||
|
|
||||||
if (maxcyl != 0 && m_cylinders > maxcyl)
|
if (maxcyl != 0 && (m_cylinders != maxcyl || m_heads != maxhead))
|
||||||
{
|
{
|
||||||
throw emu_fatalerror("Image geometry does not fit this kind of hard drive: drive=(%d,%d), image=(%d,%d)", maxcyl, maxhead, m_cylinders, m_heads);
|
throw emu_fatalerror("Image geometry does not fit this kind of hard drive: drive=(%d,%d), image=(%d,%d)", maxcyl, maxhead, m_cylinders, m_heads);
|
||||||
}
|
}
|
||||||
@ -592,10 +663,13 @@ void mfmhd_trackimage_cache::init(chd_file* chdfile, const char* dtag, int maxcy
|
|||||||
if (TRACE_CACHE && TRACE_DETAIL) logerror("%s: MFM HD allocate cache slot\n", tag());
|
if (TRACE_CACHE && TRACE_DETAIL) logerror("%s: MFM HD allocate cache slot\n", tag());
|
||||||
previous = current;
|
previous = current;
|
||||||
current = global_alloc(mfmhd_trackimage);
|
current = global_alloc(mfmhd_trackimage);
|
||||||
current->encdata = global_alloc_array(UINT16, TRACKIMAGE_SIZE);
|
current->encdata = global_alloc_array(UINT16, tracksize);
|
||||||
|
|
||||||
// Load the first tracks into the slots
|
// Load the first tracks into the slots
|
||||||
state = load_track(current, cylinder, head, 32, 256, 4);
|
state = load_track(m_chd, current->encdata, m_tracksize, cylinder, head);
|
||||||
|
current->dirty = false;
|
||||||
|
current->cylinder = cylinder;
|
||||||
|
current->head = head;
|
||||||
|
|
||||||
if (state != CHDERR_NONE) throw emu_fatalerror("Cannot load (c=%d,h=%d) from hard disk", cylinder, head);
|
if (state != CHDERR_NONE) throw emu_fatalerror("Cannot load (c=%d,h=%d) from hard disk", cylinder, head);
|
||||||
|
|
||||||
@ -700,8 +774,15 @@ UINT16* mfmhd_trackimage_cache::get_trackimage(int cylinder, int head)
|
|||||||
current = previous->next;
|
current = previous->next;
|
||||||
if (TRACE_CACHE) logerror("%s: MFM HD cache: evict line (c=%d,h=%d)\n", tag(), current->cylinder, current->head);
|
if (TRACE_CACHE) logerror("%s: MFM HD cache: evict line (c=%d,h=%d)\n", tag(), current->cylinder, current->head);
|
||||||
|
|
||||||
if (current->dirty) write_back(current);
|
if (current->dirty)
|
||||||
state = load_track(current, cylinder, head, 32, 256, 4);
|
{
|
||||||
|
write_track(m_chd, current->encdata, m_tracksize, current->cylinder, current->head);
|
||||||
|
current->dirty = false;
|
||||||
|
}
|
||||||
|
state = load_track(m_chd, current->encdata, m_tracksize, cylinder, head);
|
||||||
|
current->dirty = false;
|
||||||
|
current->cylinder = cylinder;
|
||||||
|
current->head = head;
|
||||||
}
|
}
|
||||||
// If we are here we have a CHD error.
|
// If we are here we have a CHD error.
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -710,19 +791,19 @@ UINT16* mfmhd_trackimage_cache::get_trackimage(int cylinder, int head)
|
|||||||
/*
|
/*
|
||||||
Create MFM encoding.
|
Create MFM encoding.
|
||||||
*/
|
*/
|
||||||
void mfmhd_trackimage_cache::mfm_encode(mfmhd_trackimage* slot, int& position, UINT8 byte, int count)
|
void mfmhd_trackimage_cache::mfm_encode(UINT16* trackimage, int& position, UINT8 byte, int count)
|
||||||
{
|
{
|
||||||
mfm_encode_mask(slot, position, byte, count, 0x00);
|
mfm_encode_mask(trackimage, position, byte, count, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mfmhd_trackimage_cache::mfm_encode_a1(mfmhd_trackimage* slot, int& position)
|
void mfmhd_trackimage_cache::mfm_encode_a1(UINT16* trackimage, int& position)
|
||||||
{
|
{
|
||||||
m_current_crc = 0xffff;
|
m_current_crc = 0xffff;
|
||||||
mfm_encode_mask(slot, position, 0xa1, 1, 0x04);
|
mfm_encode_mask(trackimage, position, 0xa1, 1, 0x04);
|
||||||
// 0x443b; CRC for A1
|
// 0x443b; CRC for A1
|
||||||
}
|
}
|
||||||
|
|
||||||
void mfmhd_trackimage_cache::mfm_encode_mask(mfmhd_trackimage* slot, int& position, UINT8 byte, int count, int mask)
|
void mfmhd_trackimage_cache::mfm_encode_mask(UINT16* trackimage, int& position, UINT8 byte, int count, int mask)
|
||||||
{
|
{
|
||||||
UINT16 encclock = 0;
|
UINT16 encclock = 0;
|
||||||
UINT16 encdata = 0;
|
UINT16 encdata = 0;
|
||||||
@ -768,7 +849,7 @@ void mfmhd_trackimage_cache::mfm_encode_mask(mfmhd_trackimage* slot, int& positi
|
|||||||
else
|
else
|
||||||
encclock <<= 8;
|
encclock <<= 8;
|
||||||
|
|
||||||
slot->encdata[position++] = (encclock | encdata);
|
trackimage[position++] = (encclock | encdata);
|
||||||
|
|
||||||
// When we write the byte multiple times, check whether the next encoding
|
// When we write the byte multiple times, check whether the next encoding
|
||||||
// differs from the previous because of the last bit
|
// differs from the previous because of the last bit
|
||||||
@ -781,7 +862,7 @@ void mfmhd_trackimage_cache::mfm_encode_mask(mfmhd_trackimage* slot, int& positi
|
|||||||
|
|
||||||
for (int j=1; j < count; j++)
|
for (int j=1; j < count; j++)
|
||||||
{
|
{
|
||||||
slot->encdata[position++] = (encclock | encdata);
|
trackimage[position++] = (encclock | encdata);
|
||||||
m_current_crc = ccitt_crc16_one(m_current_crc, byte);
|
m_current_crc = ccitt_crc16_one(m_current_crc, byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -790,10 +871,14 @@ void mfmhd_trackimage_cache::mfm_encode_mask(mfmhd_trackimage* slot, int& positi
|
|||||||
Load a track from the CHD.
|
Load a track from the CHD.
|
||||||
TODO: Isolate the encoding into a separate format definition
|
TODO: Isolate the encoding into a separate format definition
|
||||||
*/
|
*/
|
||||||
chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinder, int head, int sectorcount, int size, int interleave)
|
chd_error mfmhd_trackimage_cache::load_track(chd_file* file, UINT16* trackimage, int tracksize, int cylinder, int head)
|
||||||
{
|
{
|
||||||
chd_error state = CHDERR_NONE;
|
chd_error state = CHDERR_NONE;
|
||||||
|
|
||||||
|
int sectorcount = 32;
|
||||||
|
int size = 256;
|
||||||
|
int interleave = 4;
|
||||||
|
|
||||||
UINT8 sector_content[1024];
|
UINT8 sector_content[1024];
|
||||||
|
|
||||||
if (TRACE_RWTRACK) logerror("%s: MFM HD cache: load track (c=%d,h=%d) from CHD\n", tag(), cylinder, head);
|
if (TRACE_RWTRACK) logerror("%s: MFM HD cache: load track (c=%d,h=%d) from CHD\n", tag(), cylinder, head);
|
||||||
@ -808,7 +893,7 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
|||||||
// both be set to the same number and loaded in the appropriate registers.
|
// both be set to the same number and loaded in the appropriate registers.
|
||||||
|
|
||||||
// Gap 1
|
// Gap 1
|
||||||
mfm_encode(slot, position, 0x4e, 16);
|
mfm_encode(trackimage, position, 0x4e, 16);
|
||||||
|
|
||||||
int sec_il_start = 0;
|
int sec_il_start = 0;
|
||||||
int sec_number = 0;
|
int sec_number = 0;
|
||||||
@ -826,43 +911,43 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
|||||||
if (TRACE_DETAIL) logerror("%02d ", sec_number);
|
if (TRACE_DETAIL) logerror("%02d ", sec_number);
|
||||||
|
|
||||||
// Sync gap
|
// Sync gap
|
||||||
mfm_encode(slot, position, 0x00, 13);
|
mfm_encode(trackimage, position, 0x00, 13);
|
||||||
|
|
||||||
// Write IDAM
|
// Write IDAM
|
||||||
mfm_encode_a1(slot, position);
|
mfm_encode_a1(trackimage, position);
|
||||||
|
|
||||||
// Write header
|
// Write header
|
||||||
identfield = cylinder_to_ident(cylinder);
|
identfield = cylinder_to_ident(cylinder);
|
||||||
cylfield = cylinder & 0xff;
|
cylfield = cylinder & 0xff;
|
||||||
headfield = ((cylinder & 0x700)>>4) | (head&0x0f);
|
headfield = ((cylinder & 0x700)>>4) | (head&0x0f);
|
||||||
|
|
||||||
mfm_encode(slot, position, identfield);
|
mfm_encode(trackimage, position, identfield);
|
||||||
mfm_encode(slot, position, cylfield);
|
mfm_encode(trackimage, position, cylfield);
|
||||||
mfm_encode(slot, position, headfield);
|
mfm_encode(trackimage, position, headfield);
|
||||||
mfm_encode(slot, position, sec_number);
|
mfm_encode(trackimage, position, sec_number);
|
||||||
mfm_encode(slot, position, sizefield);
|
mfm_encode(trackimage, position, sizefield);
|
||||||
// logerror("%s: Created header (%02x,%02x,%02x,%02x)\n", tag(), identfield, cylfield, headfield, sector);
|
// logerror("%s: Created header (%02x,%02x,%02x,%02x)\n", tag(), identfield, cylfield, headfield, sector);
|
||||||
|
|
||||||
// Write CRC for header.
|
// Write CRC for header.
|
||||||
int crc = m_current_crc;
|
int crc = m_current_crc;
|
||||||
mfm_encode(slot, position, (crc >> 8) & 0xff);
|
mfm_encode(trackimage, position, (crc >> 8) & 0xff);
|
||||||
mfm_encode(slot, position, crc & 0xff);
|
mfm_encode(trackimage, position, crc & 0xff);
|
||||||
|
|
||||||
// Gap 2
|
// Gap 2
|
||||||
mfm_encode(slot, position, 0x4e, 3);
|
mfm_encode(trackimage, position, 0x4e, 3);
|
||||||
|
|
||||||
// Sync
|
// Sync
|
||||||
mfm_encode(slot, position, 0x00, 13);
|
mfm_encode(trackimage, position, 0x00, 13);
|
||||||
|
|
||||||
// Write DAM
|
// Write DAM
|
||||||
mfm_encode_a1(slot, position);
|
mfm_encode_a1(trackimage, position);
|
||||||
mfm_encode(slot, position, 0xfb);
|
mfm_encode(trackimage, position, 0xfb);
|
||||||
|
|
||||||
// Get sector content from CHD
|
// Get sector content from CHD
|
||||||
int lbaposition = chs_to_lba(cylinder, head, sec_number);
|
int lbaposition = chs_to_lba(cylinder, head, sec_number);
|
||||||
if (lbaposition>=0)
|
if (lbaposition>=0)
|
||||||
{
|
{
|
||||||
chd_error state = m_chd->read_units(lbaposition, sector_content);
|
chd_error state = file->read_units(lbaposition, sector_content);
|
||||||
if (state != CHDERR_NONE) break;
|
if (state != CHDERR_NONE) break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -871,16 +956,16 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i < size; i++)
|
for (int i=0; i < size; i++)
|
||||||
mfm_encode(slot, position, sector_content[i]);
|
mfm_encode(trackimage, position, sector_content[i]);
|
||||||
|
|
||||||
// Write CRC for content.
|
// Write CRC for content.
|
||||||
crc = m_current_crc;
|
crc = m_current_crc;
|
||||||
mfm_encode(slot, position, (crc >> 8) & 0xff);
|
mfm_encode(trackimage, position, (crc >> 8) & 0xff);
|
||||||
mfm_encode(slot, position, crc & 0xff);
|
mfm_encode(trackimage, position, crc & 0xff);
|
||||||
|
|
||||||
// Gap 3
|
// Gap 3
|
||||||
mfm_encode(slot, position, 0x00, 3);
|
mfm_encode(trackimage, position, 0x00, 3);
|
||||||
mfm_encode(slot, position, 0x4e, 19);
|
mfm_encode(trackimage, position, 0x4e, 19);
|
||||||
|
|
||||||
// Calculate next sector number
|
// Calculate next sector number
|
||||||
sec_number += delta;
|
sec_number += delta;
|
||||||
@ -892,17 +977,12 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
|||||||
if (state == CHDERR_NONE)
|
if (state == CHDERR_NONE)
|
||||||
{
|
{
|
||||||
// Fill the rest with 0x4e
|
// Fill the rest with 0x4e
|
||||||
mfm_encode(slot, position, 0x4e, TRACKIMAGE_SIZE-position);
|
mfm_encode(trackimage, position, 0x4e, tracksize-position);
|
||||||
if (TRACE_IMAGE)
|
if (TRACE_IMAGE)
|
||||||
{
|
{
|
||||||
showtrack(slot->encdata, TRACKIMAGE_SIZE);
|
showtrack(trackimage, tracksize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->dirty = false;
|
|
||||||
slot->cylinder = cylinder;
|
|
||||||
slot->head = head;
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -932,14 +1012,12 @@ UINT8 mfmhd_trackimage_cache::mfm_decode(UINT16 raw)
|
|||||||
TODO: The CHD/track conversion should go in a separate format definition (see floppy)
|
TODO: The CHD/track conversion should go in a separate format definition (see floppy)
|
||||||
(can also handle different header formats there)
|
(can also handle different header formats there)
|
||||||
*/
|
*/
|
||||||
void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
void mfmhd_trackimage_cache::write_track(chd_file* file, UINT16* trackimage, int tracksize, int current_cylinder, int current_head)
|
||||||
{
|
{
|
||||||
if (TRACE_CACHE) logerror("%s: MFM HD cache: write back (c=%d,h=%d) to CHD\n", tag(), slot->cylinder, slot->head);
|
if (TRACE_CACHE) logerror("%s: MFM HD cache: write back (c=%d,h=%d) to CHD\n", tag(), current_cylinder, current_head);
|
||||||
|
|
||||||
UINT8 buffer[1024]; // for header or sector content
|
UINT8 buffer[1024]; // for header or sector content
|
||||||
|
|
||||||
UINT16 *track = slot->encdata;
|
|
||||||
|
|
||||||
int bytepos = 0;
|
int bytepos = 0;
|
||||||
int state = SEARCH_A1;
|
int state = SEARCH_A1;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@ -961,23 +1039,23 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
|||||||
|
|
||||||
if (TRACE_IMAGE)
|
if (TRACE_IMAGE)
|
||||||
{
|
{
|
||||||
for (int i=0; i < TRACKIMAGE_SIZE; i++)
|
for (int i=0; i < tracksize; i++)
|
||||||
{
|
{
|
||||||
if ((i % 16)==0) logerror("\n%04x: ", i);
|
if ((i % 16)==0) logerror("\n%04x: ", i);
|
||||||
logerror("%02x ", (m_encoding==MFM_BITS || m_encoding==MFM_BYTE)? mfm_decode(track[i]) : (track[i]&0xff));
|
logerror("%02x ", (m_encoding==MFM_BITS || m_encoding==MFM_BYTE)? mfm_decode(trackimage[i]) : (trackimage[i]&0xff));
|
||||||
}
|
}
|
||||||
logerror("\n");
|
logerror("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to go through the bytes of the track and save a sector as soon as one shows up
|
// We have to go through the bytes of the track and save a sector as soon as one shows up
|
||||||
while (bytepos < TRACKIMAGE_SIZE)
|
while (bytepos < tracksize)
|
||||||
{
|
{
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case SEARCH_A1:
|
case SEARCH_A1:
|
||||||
if (((m_encoding==MFM_BITS || m_encoding==MFM_BYTE) && track[bytepos]==0x4489)
|
if (((m_encoding==MFM_BITS || m_encoding==MFM_BYTE) && trackimage[bytepos]==0x4489)
|
||||||
|| (m_encoding==SEPARATED && track[bytepos]==0x0aa1)
|
|| (m_encoding==SEPARATED && trackimage[bytepos]==0x0aa1)
|
||||||
|| (m_encoding==SEPARATED_SIMPLE && track[bytepos]==0xffa1))
|
|| (m_encoding==SEPARATED_SIMPLE && trackimage[bytepos]==0xffa1))
|
||||||
{
|
{
|
||||||
state = FOUND_A1;
|
state = FOUND_A1;
|
||||||
count = search_header? 7 : 259;
|
count = search_header? 7 : 259;
|
||||||
@ -991,9 +1069,9 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
|||||||
// read next values into array
|
// read next values into array
|
||||||
if (m_encoding==MFM_BITS || m_encoding==MFM_BYTE)
|
if (m_encoding==MFM_BITS || m_encoding==MFM_BYTE)
|
||||||
{
|
{
|
||||||
byte = mfm_decode(track[bytepos]);
|
byte = mfm_decode(trackimage[bytepos]);
|
||||||
}
|
}
|
||||||
else byte = (track[bytepos] & 0xff);
|
else byte = (trackimage[bytepos] & 0xff);
|
||||||
|
|
||||||
crc = ccitt_crc16_one(crc, byte);
|
crc = ccitt_crc16_one(crc, byte);
|
||||||
// logerror("%s: MFM HD: Byte = %02x, CRC=%04x\n", tag(), byte, crc);
|
// logerror("%s: MFM HD: Byte = %02x, CRC=%04x\n", tag(), byte, crc);
|
||||||
@ -1021,6 +1099,16 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
|||||||
logerror("%s: MFM HD: Field error; ident = %02x (expected %02x) for sector chs=(%d,%d,%d)\n", tag(), ident, identexp, cylinder, head, sector);
|
logerror("%s: MFM HD: Field error; ident = %02x (expected %02x) for sector chs=(%d,%d,%d)\n", tag(), ident, identexp, cylinder, head, sector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cylinder != current_cylinder)
|
||||||
|
{
|
||||||
|
logerror("%s: MFM HD: Sector header of sector %d defines cylinder = %02x (should be %02x)\n", tag(), sector, cylinder, current_cylinder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head != current_head)
|
||||||
|
{
|
||||||
|
logerror("%s: MFM HD: Sector header of sector %d defines head = %02x (should be %02x)\n", tag(), sector, head, current_head);
|
||||||
|
}
|
||||||
|
|
||||||
// Count the sectors for the interleave
|
// Count the sectors for the interleave
|
||||||
if (check_interleave)
|
if (check_interleave)
|
||||||
{
|
{
|
||||||
@ -1045,8 +1133,8 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
|||||||
int lbaposition = chs_to_lba(cylinder, head, sector);
|
int lbaposition = chs_to_lba(cylinder, head, sector);
|
||||||
if (lbaposition>=0)
|
if (lbaposition>=0)
|
||||||
{
|
{
|
||||||
if (TRACE_DETAIL) logerror("%s: MFM HD: Writing sector chs=(%d,%d,%d) to CHD\n", tag(), cylinder, head, sector);
|
if (TRACE_DETAIL) logerror("%s: MFM HD: Writing sector chs=(%d,%d,%d) to CHD\n", tag(), current_cylinder, current_head, sector);
|
||||||
chd_error state = m_chd->write_units(chs_to_lba(cylinder, head, sector), buffer);
|
chd_error state = file->write_units(chs_to_lba(current_cylinder, current_head, sector), buffer);
|
||||||
|
|
||||||
if (state != CHDERR_NONE)
|
if (state != CHDERR_NONE)
|
||||||
{
|
{
|
||||||
@ -1079,8 +1167,6 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clear the dirty flag
|
|
||||||
slot->dirty = false;
|
|
||||||
|
|
||||||
if (check_interleave == false)
|
if (check_interleave == false)
|
||||||
{
|
{
|
||||||
@ -1090,7 +1176,7 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
|||||||
|
|
||||||
if (TRACE_CACHE)
|
if (TRACE_CACHE)
|
||||||
{
|
{
|
||||||
logerror("%s: MFM HD cache: write back complete (c=%d,h=%d), interleave = %d\n", tag(), slot->cylinder, slot->head, m_calc_interleave);
|
logerror("%s: MFM HD cache: write back complete (c=%d,h=%d), interleave = %d\n", tag(), current_cylinder, current_head, m_calc_interleave);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,20 +44,21 @@ class mfmhd_trackimage_cache
|
|||||||
public:
|
public:
|
||||||
mfmhd_trackimage_cache();
|
mfmhd_trackimage_cache();
|
||||||
~mfmhd_trackimage_cache();
|
~mfmhd_trackimage_cache();
|
||||||
void init(chd_file* chdfile, const char* tag, int maxcyl, int maxhead, int trackslots, mfmhd_enc_t encoding);
|
void init(chd_file* chdfile, const char* tag, int tracksize, int maxcyl, int maxhead, int trackslots, mfmhd_enc_t encoding);
|
||||||
UINT16* get_trackimage(int cylinder, int head);
|
UINT16* get_trackimage(int cylinder, int head);
|
||||||
void mark_current_as_dirty();
|
void mark_current_as_dirty();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
void write_back_one();
|
void write_back_one();
|
||||||
|
int get_cylinders() { return m_cylinders; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void mfm_encode(mfmhd_trackimage* slot, int& position, UINT8 byte, int count=1);
|
void mfm_encode(UINT16* trackimage, int& position, UINT8 byte, int count=1);
|
||||||
void mfm_encode_a1(mfmhd_trackimage* slot, int& position);
|
void mfm_encode_a1(UINT16* trackimage, int& position);
|
||||||
void mfm_encode_mask(mfmhd_trackimage* slot, int& position, UINT8 byte, int count, int mask);
|
void mfm_encode_mask(UINT16* trackimage, int& position, UINT8 byte, int count, int mask);
|
||||||
UINT8 mfm_decode(UINT16 raw);
|
UINT8 mfm_decode(UINT16 raw);
|
||||||
|
|
||||||
chd_error load_track(mfmhd_trackimage* slot, int cylinder, int head, int sectorcount, int size, int interleave);
|
chd_error load_track(chd_file* file, UINT16* trackimage, int tracksize, int cylinder, int head);
|
||||||
void write_back(mfmhd_trackimage* timg);
|
void write_track(chd_file* file, UINT16* trackimage, int tracksize, int cylinder, int head);
|
||||||
int chs_to_lba(int cylinder, int head, int sector);
|
int chs_to_lba(int cylinder, int head, int sector);
|
||||||
UINT8 cylinder_to_ident(int cylinder);
|
UINT8 cylinder_to_ident(int cylinder);
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ private:
|
|||||||
int m_heads;
|
int m_heads;
|
||||||
int m_sectors_per_track;
|
int m_sectors_per_track;
|
||||||
int m_sectorsize;
|
int m_sectorsize;
|
||||||
|
int m_tracksize;
|
||||||
|
|
||||||
int m_calc_interleave;
|
int m_calc_interleave;
|
||||||
void showtrack(UINT16* enctrack, int length);
|
void showtrack(UINT16* enctrack, int length);
|
||||||
@ -140,12 +142,20 @@ protected:
|
|||||||
ready_cb m_ready_cb;
|
ready_cb m_ready_cb;
|
||||||
seek_complete_cb m_seek_complete_cb;
|
seek_complete_cb m_seek_complete_cb;
|
||||||
|
|
||||||
int m_max_cylinder;
|
int m_max_cylinders;
|
||||||
int m_max_heads;
|
int m_phys_cylinders;
|
||||||
|
int m_actual_cylinders; // after reading the CHD
|
||||||
|
int m_max_heads;
|
||||||
|
int m_park_pos;
|
||||||
|
int m_maxseek_time;
|
||||||
|
int m_seeknext_time;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mfmhd_enc_t m_encoding;
|
mfmhd_enc_t m_encoding;
|
||||||
|
int m_cell_size; // nanoseconds
|
||||||
|
int m_trackimage_size; // number of 16-bit cell blocks (data bytes)
|
||||||
int m_spinupms;
|
int m_spinupms;
|
||||||
|
int m_rpm;
|
||||||
int m_cachelines;
|
int m_cachelines;
|
||||||
bool m_ready;
|
bool m_ready;
|
||||||
int m_current_cylinder;
|
int m_current_cylinder;
|
||||||
@ -163,6 +173,9 @@ private:
|
|||||||
attotime m_revolution_start_time;
|
attotime m_revolution_start_time;
|
||||||
attotime m_rev_time;
|
attotime m_rev_time;
|
||||||
|
|
||||||
|
attotime m_settle_time;
|
||||||
|
attotime m_step_time;
|
||||||
|
|
||||||
mfmhd_trackimage_cache* m_cache;
|
mfmhd_trackimage_cache* m_cache;
|
||||||
|
|
||||||
void prepare_track(int cylinder, int head);
|
void prepare_track(int cylinder, int head);
|
||||||
@ -170,6 +183,16 @@ private:
|
|||||||
void recalibrate();
|
void recalibrate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
The Generic drive is a MFM drive that has just enough heads and cylinders
|
||||||
|
to handle the CHD image.
|
||||||
|
|
||||||
|
Specific Seagate models:
|
||||||
|
|
||||||
|
ST-213: 10 MB
|
||||||
|
ST-225: 20 MB
|
||||||
|
ST-251: 40 MB
|
||||||
|
*/
|
||||||
class mfm_hd_generic_device : public mfm_harddisk_device
|
class mfm_hd_generic_device : public mfm_harddisk_device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -178,6 +201,14 @@ public:
|
|||||||
|
|
||||||
extern const device_type MFMHD_GENERIC;
|
extern const device_type MFMHD_GENERIC;
|
||||||
|
|
||||||
|
class mfm_hd_st213_device : public mfm_harddisk_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mfm_hd_st213_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type MFMHD_ST213;
|
||||||
|
|
||||||
class mfm_hd_st225_device : public mfm_harddisk_device
|
class mfm_hd_st225_device : public mfm_harddisk_device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -186,6 +217,15 @@ public:
|
|||||||
|
|
||||||
extern const device_type MFMHD_ST225;
|
extern const device_type MFMHD_ST225;
|
||||||
|
|
||||||
|
class mfm_hd_st251_device : public mfm_harddisk_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mfm_hd_st251_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type MFMHD_ST251;
|
||||||
|
|
||||||
|
|
||||||
/* Connector for a MFM hard disk. See also floppy.c */
|
/* Connector for a MFM hard disk. See also floppy.c */
|
||||||
class mfm_harddisk_connector : public device_t,
|
class mfm_harddisk_connector : public device_t,
|
||||||
public device_slot_interface
|
public device_slot_interface
|
||||||
@ -227,4 +267,21 @@ extern const device_type MFM_HD_CONNECTOR;
|
|||||||
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
|
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
|
||||||
static_cast<mfm_harddisk_connector *>(device)->configure(_enc, _spinupms, _cache);
|
static_cast<mfm_harddisk_connector *>(device)->configure(_enc, _spinupms, _cache);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Hard disk format
|
||||||
|
*/
|
||||||
|
class harddisk_image_format_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
harddisk_image_format_t();
|
||||||
|
virtual ~harddisk_image_format_t();
|
||||||
|
|
||||||
|
// Load the image.
|
||||||
|
virtual bool load() = 0;
|
||||||
|
|
||||||
|
// Save the image.
|
||||||
|
virtual bool save() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user