diff options
Diffstat (limited to 'src/emu/imagedev/floppy.c')
-rw-r--r-- | src/emu/imagedev/floppy.c | 288 |
1 files changed, 263 insertions, 25 deletions
diff --git a/src/emu/imagedev/floppy.c b/src/emu/imagedev/floppy.c index 725e7681f9d..7348dd0a7cc 100644 --- a/src/emu/imagedev/floppy.c +++ b/src/emu/imagedev/floppy.c @@ -9,15 +9,50 @@ #include "formats/imageutl.h" // device type definition -const device_type FLOPPY = &device_creator<floppy_image_device>; +const device_type FLOPPY_CONNECTOR = &device_creator<floppy_connector>; +const device_type FLOPPY_35_DD = &device_creator<floppy_35_dd>; +const device_type FLOPPY_35_HD = &device_creator<floppy_35_hd>; +const device_type FLOPPY_525_DD = &device_creator<floppy_525_dd>; + +floppy_connector::floppy_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, FLOPPY_CONNECTOR, "Floppy drive connector abstraction", tag, owner, clock), + device_slot_interface(mconfig, *this) +{ +} + +floppy_connector::~floppy_connector() +{ +} + +void floppy_connector::set_formats(const floppy_format_type *_formats) +{ + formats = _formats; +} + +void floppy_connector::device_start() +{ +} + +void floppy_connector::device_config_complete() +{ + floppy_image_device *dev = dynamic_cast<floppy_image_device *>(get_card_device()); + if(dev) + dev->set_formats(formats); +} + +floppy_image_device *floppy_connector::get_device() +{ + return dynamic_cast<floppy_image_device *>(get_card_device()); +} //------------------------------------------------- // floppy_image_device - constructor //------------------------------------------------- -floppy_image_device::floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, FLOPPY, "Floppy drive", tag, owner, clock), +floppy_image_device::floppy_image_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, type, name, tag, owner, clock), device_image_interface(mconfig, *this), + device_slot_card_interface(mconfig, *this), image(NULL) { } @@ -45,12 +80,8 @@ void floppy_image_device::setup_index_pulse_cb(index_pulse_cb cb) cur_index_pulse_cb = cb; } -void floppy_image_device::set_info(int _type, int _tracks, int _sides, const floppy_format_type *formats) +void floppy_image_device::set_formats(const floppy_format_type *formats) { - type = _type; - tracks = _tracks; - sides = _sides; - image_device_format **formatptr; image_device_format *format; formatptr = &m_formatlist; @@ -103,6 +134,9 @@ void floppy_image_device::set_rpm(float _rpm) void floppy_image_device::device_start() { + rpm = 0; + setup_limits(); + idx = 0; /* motor off */ @@ -110,9 +144,6 @@ void floppy_image_device::device_start() /* set write protect on */ wpt = 0; - rpm = 0; - set_rpm(300); - cyl = 0; ss = 1; stp = 1; @@ -139,7 +170,6 @@ bool floppy_image_device::call_load() io.file = (device_image_interface *)this; io.procs = &image_ioprocs; io.filler = 0xff; - int best = 0; floppy_image_format_t *best_format = 0; for(floppy_image_format_t *format = fif_list; format; format = format->next) { @@ -279,7 +309,7 @@ void floppy_image_device::stp_w(int state) } } -int floppy_image_device::find_position(int position, const UINT32 *buf, int buf_size) +int floppy_image_device::find_index(UINT32 position, const UINT32 *buf, int buf_size) { int spos = (buf_size >> 1)-1; int step; @@ -298,6 +328,21 @@ int floppy_image_device::find_position(int position, const UINT32 *buf, int buf_ } } +UINT32 floppy_image_device::find_position(attotime &base, attotime when) +{ + base = revolution_start_time; + UINT32 revc = revolution_count; + attotime delta = when - base; + + while(delta >= rev_time) { + delta -= rev_time; + base += rev_time; + revc++; + } + + return (delta*(rpm/300)).as_ticks(1000000000); +} + attotime floppy_image_device::get_next_transition(attotime from_when) { if(!image || mon) @@ -307,24 +352,16 @@ attotime floppy_image_device::get_next_transition(attotime from_when) if(cells <= 1) return attotime::never; - attotime base = revolution_start_time; - UINT32 revc = revolution_count; - attotime delta = from_when - base; - - while(delta >= rev_time) { - delta -= rev_time; - base += rev_time; - revc++; - } - int position = (delta*(rpm/300)).as_ticks(1000000000); + attotime base; + UINT32 position = find_position(base, from_when); const UINT32 *buf = image->get_buffer(cyl, ss); - int index = find_position(position, buf, cells); + int index = find_index(position, buf, cells); if(index == -1) return attotime::never; - int next_position; + UINT32 next_position; if(index < cells-1) next_position = buf[index+1] & floppy_image::TIME_MASK; else if((buf[index]^buf[0]) & floppy_image::MG_MASK) @@ -332,5 +369,206 @@ attotime floppy_image_device::get_next_transition(attotime from_when) else next_position = 200000000 + (buf[1] & floppy_image::TIME_MASK); + return base + attotime::from_nsec(next_position*(300/rpm)); } + +void floppy_image_device::write_flux(attotime start, attotime end, int transition_count, const attotime *transitions) +{ + attotime base; + int start_pos = find_position(base, start); + int end_pos = find_position(base, end); + + int *trans_pos = transition_count ? global_alloc_array(int, transition_count) : 0; + for(int i=0; i != transition_count; i++) + trans_pos[i] = find_position(base, transitions[i]); + + int cells = image->get_track_size(cyl, ss); + UINT32 *buf = image->get_buffer(cyl, ss); + + int index; + if(cells) + index = find_index(start_pos, buf, cells); + else { + index = 0; + buf[cells++] = floppy_image::MG_N | 200000000; + } + + if(index && (buf[index] & floppy_image::TIME_MASK) == start_pos) + index--; + + UINT32 cur_mg = buf[index] & floppy_image::MG_MASK; + if(cur_mg == floppy_image::MG_N || cur_mg == floppy_image::MG_D) + cur_mg = floppy_image::MG_A; + + UINT32 pos = start_pos; + int ti = 0; + while(pos != end_pos) { + UINT32 next_pos; + if(ti != transition_count) + next_pos = trans_pos[ti++]; + else + next_pos = end_pos; + if(next_pos > pos) + write_zone(buf, cells, index, pos, next_pos, cur_mg); + else { + write_zone(buf, cells, index, pos, 200000000, cur_mg); + write_zone(buf, cells, index, 0, next_pos, cur_mg); + } + pos = next_pos; + cur_mg = cur_mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A; + } + + image->set_track_size(cyl, ss, cells); + + if(trans_pos) + global_free(trans_pos); +} + +void floppy_image_device::write_zone(UINT32 *buf, int &cells, int &index, UINT32 spos, UINT32 epos, UINT32 mg) +{ + while(spos < epos) { + while(index != cells-1 && (buf[index+1] & floppy_image::TIME_MASK) <= spos) + index++; + + UINT32 ref_start = buf[index] & floppy_image::TIME_MASK; + UINT32 ref_end = index == cells-1 ? 200000000 : buf[index+1] & floppy_image::TIME_MASK; + UINT32 ref_mg = buf[index] & floppy_image::MG_MASK; + + // Can't overwrite a damaged zone + if(ref_mg == floppy_image::MG_D) { + spos = ref_end; + continue; + } + + // If the zone is of the type we want, we don't need to touch it + if(ref_mg == mg) { + spos = ref_end; + continue; + } + + // Check the overlaps, act accordingly + if(spos == ref_start) { + if(epos >= ref_end) { + // Full overlap, that cell is dead, we need to see which ones we can extend + UINT32 prev_mg = index != 0 ? buf[index-1] & floppy_image::MG_MASK : ~0; + UINT32 next_mg = index != cells-1 ? buf[index+1] & floppy_image::MG_MASK : ~0; + if(prev_mg == mg) { + if(next_mg == mg) { + // Both match, merge all three in one + memmove(buf+index, buf+index+2, (cells-index-2)*sizeof(UINT32)); + cells -= 2; + index--; + + } else { + // Previous matches, drop the current cell + memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(UINT32)); + cells --; + } + + } else { + if(next_mg == mg) { + // Following matches, extend it + memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(UINT32)); + cells --; + buf[index] = mg | spos; + } else { + // None match, convert the current cell + buf[index] = mg | spos; + index++; + } + } + spos = ref_end; + + } else { + // Overlap at the start only + // Check if we can just extend the previous cell + if(index != 0 && (buf[index-1] & floppy_image::MG_MASK) == mg) + buf[index] = ref_mg | epos; + else { + // Otherwise we need to insert a new cell + if(index != cells-1) + memmove(buf+index+1, buf+index, (cells-index)*sizeof(UINT32)); + cells++; + buf[index] = mg | spos; + buf[index+1] = ref_mg | epos; + } + spos = epos; + } + + } else { + if(epos >= ref_end) { + // Overlap at the end only + // If we can't just extend the following cell, we need to insert a new one + if(index == cells-1 || (buf[index+1] & floppy_image::MG_MASK) != mg) { + if(index != cells-1) + memmove(buf+index+2, buf+index+1, (cells-index-1)*sizeof(UINT32)); + cells++; + } + buf[index+1] = mg | spos; + index++; + spos = ref_end; + + } else { + // Full inclusion + // We need to split the zone in 3 + if(index != cells-1) + memmove(buf+index+3, buf+index+1, (cells-index-1)*sizeof(UINT32)); + cells += 2; + buf[index+1] = mg | spos; + buf[index+2] = ref_mg | epos; + spos = epos; + } + } + + } +} + +floppy_35_dd::floppy_35_dd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + floppy_image_device(mconfig, FLOPPY_35_DD, "3.5\" double density floppy drive", tag, owner, clock) +{ +} + +floppy_35_dd::~floppy_35_dd() +{ +} + +void floppy_35_dd::setup_limits() +{ + tracks = 84; + sides = 2; + set_rpm(300); +} + +floppy_35_hd::floppy_35_hd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + floppy_image_device(mconfig, FLOPPY_35_HD, "3.5\" high density floppy drive", tag, owner, clock) +{ +} + +floppy_35_hd::~floppy_35_hd() +{ +} + +void floppy_35_hd::setup_limits() +{ + tracks = 84; + sides = 2; + set_rpm(300); +} + + +floppy_525_dd::floppy_525_dd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + floppy_image_device(mconfig, FLOPPY_525_DD, "3.5\" high density floppy drive", tag, owner, clock) +{ +} + +floppy_525_dd::~floppy_525_dd() +{ +} + +void floppy_525_dd::setup_limits() +{ + tracks = 42; + sides = 1; + set_rpm(300); +} |