summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/imagedev/floppy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/imagedev/floppy.c')
-rw-r--r--src/emu/imagedev/floppy.c288
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);
+}