diff options
Diffstat (limited to 'src/devices/imagedev/floppy.cpp')
-rw-r--r-- | src/devices/imagedev/floppy.cpp | 2274 |
1 files changed, 1435 insertions, 839 deletions
diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp index 60058681549..b6f3e2b69b5 100644 --- a/src/devices/imagedev/floppy.cpp +++ b/src/devices/imagedev/floppy.cpp @@ -9,9 +9,32 @@ #include "emu.h" #include "floppy.h" +#include "formats/d88_dsk.h" +#include "formats/dfi_dsk.h" +#include "formats/hxchfe_dsk.h" +#include "formats/hxcmfm_dsk.h" +#include "formats/imd_dsk.h" +#include "formats/mfi_dsk.h" +#include "formats/td0_dsk.h" +#include "formats/cqm_dsk.h" +#include "formats/dsk_dsk.h" +#include "formats/pc_dsk.h" +#include "formats/ipf_dsk.h" +#include "formats/86f_dsk.h" + +#include "formats/fs_unformatted.h" +#include "formats/fsblk_vec.h" + +#include "softlist_dev.h" #include "speaker.h" + #include "formats/imageutl.h" -#include "zippath.h" + +#include "util/ioprocs.h" +#include "util/ioprocsfilter.h" +#include "util/zippath.h" + +#include <algorithm> /* Debugging flags. Set to 0 or 1. @@ -29,8 +52,11 @@ DEFINE_DEVICE_TYPE(FLOPPY_CONNECTOR, floppy_connector, "floppy_connector", "Floppy drive connector abstraction") // generic 3" drives -DEFINE_DEVICE_TYPE(FLOPPY_3_SSDD, floppy_3_ssdd, "floppy_3_ssdd", "3\" single-sided floppy drive") -DEFINE_DEVICE_TYPE(FLOPPY_3_DSDD, floppy_3_dsdd, "floppy_3_dsdd", "3\" double-sided floppy drive") +DEFINE_DEVICE_TYPE(FLOPPY_3_SSSD, floppy_3_sssd, "floppy_3_sssd", "3\" single-sided single density floppy drive") +DEFINE_DEVICE_TYPE(FLOPPY_3_DSSD, floppy_3_dssd, "floppy_3_dssd", "3\" double-sided single density floppy drive") +DEFINE_DEVICE_TYPE(FLOPPY_3_SSDD, floppy_3_ssdd, "floppy_3_ssdd", "3\" single-sided double density floppy drive") +DEFINE_DEVICE_TYPE(FLOPPY_3_DSDD, floppy_3_dsdd, "floppy_3_dsdd", "3\" double-sided double density floppy drive") +DEFINE_DEVICE_TYPE(FLOPPY_3_DSQD, floppy_3_dsqd, "floppy_3_dsqd", "3\" double-sided quad density floppy drive") // generic 3.5" drives DEFINE_DEVICE_TYPE(FLOPPY_35_SSDD, floppy_35_ssdd, "floppy_35_ssdd", "3.5\" single-sided double density floppy drive") @@ -41,6 +67,7 @@ DEFINE_DEVICE_TYPE(FLOPPY_35_ED, floppy_35_ed, "floppy_35_ed", "3.5\" exte // generic 5.25" drives DEFINE_DEVICE_TYPE(FLOPPY_525_SSSD_35T, floppy_525_sssd_35t, "floppy_525_sssd_35t", "5.25\" single-sided single density 35-track floppy drive") DEFINE_DEVICE_TYPE(FLOPPY_525_SD_35T, floppy_525_sd_35t, "floppy_525_sd_35t", "5.25\" double-sided single density 35-track floppy drive") +DEFINE_DEVICE_TYPE(FLOPPY_525_VTECH, floppy_525_vtech, "floppy_525_vtech", "5.25\" single-sided single density VTECH floppy drive") DEFINE_DEVICE_TYPE(FLOPPY_525_SSSD, floppy_525_sssd, "floppy_525_sssd", "5.25\" single-sided single density floppy drive") DEFINE_DEVICE_TYPE(FLOPPY_525_SD, floppy_525_sd, "floppy_525_sd", "5.25\" single density floppy drive") DEFINE_DEVICE_TYPE(FLOPPY_525_SSDD, floppy_525_ssdd, "floppy_525_ssdd", "5.25\" single-sided double density floppy drive") @@ -95,6 +122,9 @@ DEFINE_DEVICE_TYPE(EPSON_SD_621L, epson_sd_621l, "epson_sd_621l", "EPSON SD-621L DEFINE_DEVICE_TYPE(EPSON_SD_680L, epson_sd_680l, "epson_sd_680l", "EPSON SD-680L Mini-Floppy Disk Drive") #endif +// Panasonic 3.5" drive +DEFINE_DEVICE_TYPE(PANA_JU_363, pana_ju_363, "pana_ju_363", "Panasonic JU-363 Flexible Disk Drive") + // Sony 3.5" drives DEFINE_DEVICE_TYPE(SONY_OA_D31V, sony_oa_d31v, "sony_oa_d31v", "Sony OA-D31V Micro Floppydisk Drive") DEFINE_DEVICE_TYPE(SONY_OA_D32W, sony_oa_d32w, "sony_oa_d32w", "Sony OA-D32W Micro Floppydisk Drive") @@ -104,10 +134,8 @@ DEFINE_DEVICE_TYPE(SONY_OA_D32V, sony_oa_d32v, "sony_oa_d32v", "Sony OA-D32V Mic DEFINE_DEVICE_TYPE(TEAC_FD_30A, teac_fd_30a, "teac_fd_30a", "TEAC FD-30A FDD") // TEAC 5.25" drives -#if 0 DEFINE_DEVICE_TYPE(TEAC_FD_55A, teac_fd_55a, "teac_fd_55a", "TEAC FD-55A FDD") DEFINE_DEVICE_TYPE(TEAC_FD_55B, teac_fd_55b, "teac_fd_55b", "TEAC FD-55B FDD") -#endif DEFINE_DEVICE_TYPE(TEAC_FD_55E, teac_fd_55e, "teac_fd_55e", "TEAC FD-55E FDD") DEFINE_DEVICE_TYPE(TEAC_FD_55F, teac_fd_55f, "teac_fd_55f", "TEAC FD-55F FDD") DEFINE_DEVICE_TYPE(TEAC_FD_55G, teac_fd_55g, "teac_fd_55g", "TEAC FD-55G FDD") @@ -118,26 +146,76 @@ DEFINE_DEVICE_TYPE(ALPS_3255190X, alps_3255190x, "alps_3255190x", "ALPS 32551901 // IBM 8" drives DEFINE_DEVICE_TYPE(IBM_6360, ibm_6360, "ibm_6360", "IBM 6360 8\" single-sided single density floppy drive") +// Mac 3.5" drives +DEFINE_DEVICE_TYPE(OAD34V, oa_d34v_device, "oa_d34v", "Apple/Sony 3.5 SD (400K GCR)") +DEFINE_DEVICE_TYPE(MFD51W, mfd51w_device, "mfd51w", "Apple/Sony 3.5 DD (400/800K GCR)") +DEFINE_DEVICE_TYPE(MFD75W, mfd75w_device, "mfd75w", "Apple/Sony 3.5 HD (Superdrive)") -const floppy_format_type floppy_image_device::default_floppy_formats[] = { - FLOPPY_D88_FORMAT, - FLOPPY_DFI_FORMAT, - FLOPPY_HFE_FORMAT, - FLOPPY_IMD_FORMAT, - FLOPPY_IPF_FORMAT, - FLOPPY_MFI_FORMAT, - FLOPPY_MFM_FORMAT, - FLOPPY_TD0_FORMAT, - FLOPPY_CQM_FORMAT, - FLOPPY_DSK_FORMAT, - nullptr -}; + +format_registration::format_registration() +{ + add(FLOPPY_MFI_FORMAT); // Our generic format + add(FLOPPY_DFI_FORMAT); // Flux format, dying + + add(fs::UNFORMATTED); +} + +void format_registration::add_fm_containers() +{ + add(FLOPPY_MFM_FORMAT); + add(FLOPPY_TD0_FORMAT); + add(FLOPPY_IMD_FORMAT); + add(FLOPPY_86F_FORMAT); +} + +void format_registration::add_mfm_containers() +{ + add_fm_containers(); + + add(FLOPPY_D88_FORMAT); + add(FLOPPY_CQM_FORMAT); + add(FLOPPY_DSK_FORMAT); +} + +void format_registration::add_pc_formats() +{ + add_mfm_containers(); + + add(FLOPPY_PC_FORMAT); + add(FLOPPY_IPF_FORMAT); +} + +void format_registration::add(const floppy_image_format_t &format) +{ + m_formats.push_back(&format); +} + +void format_registration::add(const fs::manager_t &fs) +{ + m_fs.push_back(&fs); +} + +void floppy_image_device::default_fm_floppy_formats(format_registration &fr) +{ + fr.add_fm_containers(); +} + +void floppy_image_device::default_mfm_floppy_formats(format_registration &fr) +{ + fr.add_mfm_containers(); +} + +void floppy_image_device::default_pc_floppy_formats(format_registration &fr) +{ + fr.add_pc_formats(); +} floppy_connector::floppy_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, FLOPPY_CONNECTOR, tag, owner, clock), device_slot_interface(mconfig, *this), formats(nullptr), - m_enable_sound(false) + m_enable_sound(false), + m_sectoring_type(floppy_image::SOFT) { } @@ -145,11 +223,6 @@ floppy_connector::~floppy_connector() { } -void floppy_connector::set_formats(const floppy_format_type _formats[]) -{ - formats = _formats; -} - void floppy_connector::device_start() { } @@ -161,6 +234,7 @@ void floppy_connector::device_config_complete() { dev->set_formats(formats); dev->enable_sound(m_enable_sound); + dev->set_sectoring_type(m_sectoring_type); } } @@ -176,32 +250,32 @@ floppy_image_device *floppy_connector::get_device() floppy_image_device::floppy_image_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock), device_image_interface(mconfig, *this), - device_slot_card_interface(mconfig, *this), - input_format(nullptr), - output_format(nullptr), - image(nullptr), - fif_list(nullptr), - index_timer(nullptr), - tracks(0), - sides(0), - form_factor(0), - motor_always_on(false), - dskchg_writable(false), - has_trk00_sensor(true), - dir(0), stp(0), wtg(0), mon(0), ss(0), ds(-1), idx(0), wpt(0), rdy(0), dskchg(0), - ready(false), - rpm(0), - floppy_ratio_1(0), - revolution_count(0), - cyl(0), - subcyl(0), - image_dirty(false), - ready_counter(0), + m_input_format(nullptr), + m_output_format(nullptr), + m_image(), + m_index_timer(nullptr), + m_tracks(0), + m_sides(0), + m_form_factor(0), + m_sectoring_type(floppy_image::SOFT), + m_motor_always_on(false), + m_dskchg_writable(false), + m_has_trk00_sensor(true), + m_dir(0), m_stp(0), m_wtg(0), m_mon(0), m_ss(0), m_ds(-1), m_idx(0), m_wpt(0), m_rdy(0), m_dskchg(0), + m_ready(false), + m_rpm(0), + m_angular_speed(0), + m_revolution_count(0), + m_cyl(0), + m_subcyl(0), + m_amplifier_freakout_time(attotime::from_usec(16)), + m_image_dirty(false), + m_track_dirty(false), + m_ready_counter(0), m_make_sound(false), m_sound_out(nullptr) { - extension_list[0] = '\0'; - m_err = IMAGE_ERROR_INVALIDIMAGE; + m_extension_list[0] = '\0'; } //------------------------------------------------- @@ -210,167 +284,291 @@ floppy_image_device::floppy_image_device(const machine_config &mconfig, device_t floppy_image_device::~floppy_image_device() { - for(floppy_image_format_t *format = fif_list; format; ) { - floppy_image_format_t* tmp_format = format; - format = format->next; - delete tmp_format; - } - fif_list = nullptr; } void floppy_image_device::setup_load_cb(load_cb cb) { - cur_load_cb = cb; + m_cur_load_cb = cb; } void floppy_image_device::setup_unload_cb(unload_cb cb) { - cur_unload_cb = cb; + m_cur_unload_cb = cb; } void floppy_image_device::setup_index_pulse_cb(index_pulse_cb cb) { - cur_index_pulse_cb = cb; + m_cur_index_pulse_cb = cb; } void floppy_image_device::setup_ready_cb(ready_cb cb) { - cur_ready_cb = cb; + m_cur_ready_cb = cb; } void floppy_image_device::setup_wpt_cb(wpt_cb cb) { - cur_wpt_cb = cb; + m_cur_wpt_cb = cb; } void floppy_image_device::setup_led_cb(led_cb cb) { - cur_led_cb = cb; + m_cur_led_cb = cb; +} + +struct floppy_image_device::fs_enum : public fs::manager_t::floppy_enumerator { + floppy_image_device *m_fid; + const fs::manager_t *m_manager; + + fs_enum(floppy_image_device *fid); + + virtual void add_raw(const char *name, u32 key, const char *description) override; +protected: + virtual void add_format(const floppy_image_format_t &type, u32 image_size, const char *name, const char *description) override; +}; + +floppy_image_device::fs_enum::fs_enum(floppy_image_device *fid) + : fs::manager_t::floppy_enumerator(fid->m_form_factor, fid->m_variants) + , m_fid(fid) +{ } -void floppy_image_device::set_formats(const floppy_format_type *formats) +void floppy_image_device::fs_enum::add_format(const floppy_image_format_t &type, u32 image_size, const char *name, const char *description) { - extension_list[0] = '\0'; - fif_list = nullptr; - for(int cnt=0; formats[cnt]; cnt++) - { - // allocate a new format - floppy_image_format_t *fif = formats[cnt](); - if(!fif_list) - fif_list = fif; - else - fif_list->append(fif); + m_fid->m_fs.emplace_back(fs_info(m_manager, &type, image_size, name, description)); +} +void floppy_image_device::fs_enum::add_raw(const char *name, u32 key, const char *description) +{ + m_fid->m_fs.emplace_back(fs_info(name, key, description)); +} + +void floppy_image_device::register_formats() +{ + format_registration fr; + if(m_format_registration_cb) + m_format_registration_cb(fr); + + m_extension_list[0] = '\0'; + m_fif_list = std::move(fr.m_formats); + for(const floppy_image_format_t *fif : m_fif_list) + { add_format(fif->name(), fif->description(), fif->extensions(), ""); + image_specify_extension( m_extension_list, 256, fif->extensions() ); + } + + fs_enum fse(this); + for(const fs::manager_t *fmt : fr.m_fs) + { + fse.m_manager = fmt; + fmt->enumerate_f(fse); + m_fs_managers.push_back(fmt); + } +} + +void floppy_image_device::add_variant(uint32_t variant) +{ + uint32_t actual_variant = variant; - image_specify_extension( extension_list, 256, fif->extensions() ); + if (m_sectoring_type == floppy_image::H10) { + switch (variant) { + case floppy_image::SSSD: + actual_variant = floppy_image::SSSD10; + break; + case floppy_image::SSDD: + actual_variant = floppy_image::SSDD10; + break; + case floppy_image::SSQD: + actual_variant = floppy_image::SSQD10; + break; + case floppy_image::DSSD: + actual_variant = floppy_image::DSSD10; + break; + case floppy_image::DSDD: + actual_variant = floppy_image::DSDD10; + break; + case floppy_image::DSQD: + actual_variant = floppy_image::DSQD10; + break; + } + } else if (m_sectoring_type == floppy_image::H16) { + switch (variant) { + case floppy_image::SSSD: + actual_variant = floppy_image::SSDD16; + break; + case floppy_image::SSDD: + actual_variant = floppy_image::SSSD16; + break; + case floppy_image::SSQD: + actual_variant = floppy_image::SSQD16; + break; + case floppy_image::DSSD: + actual_variant = floppy_image::DSSD16; + break; + case floppy_image::DSDD: + actual_variant = floppy_image::DSDD16; + break; + case floppy_image::DSQD: + actual_variant = floppy_image::DSQD16; + break; + } + } else if (m_sectoring_type == floppy_image::H32) { + switch (variant) { + case floppy_image::SSSD: + actual_variant = floppy_image::SSSD32; + break; + case floppy_image::SSDD: + actual_variant = floppy_image::SSDD32; + break; + case floppy_image::DSSD: + actual_variant = floppy_image::DSSD32; + break; + case floppy_image::DSDD: + actual_variant = floppy_image::DSDD32; + break; + } } + + m_variants.push_back(actual_variant); } -floppy_image_format_t *floppy_image_device::get_formats() const +void floppy_image_device::set_formats(std::function<void (format_registration &fr)> formats) { - return fif_list; + m_format_registration_cb = formats; } -floppy_image_format_t *floppy_image_device::get_load_format() const +const std::vector<const floppy_image_format_t *> &floppy_image_device::get_formats() const { - return input_format; + return m_fif_list; +} + +const floppy_image_format_t *floppy_image_device::get_load_format() const +{ + return m_input_format; } void floppy_image_device::set_rpm(float _rpm) { - if(rpm == _rpm) + if(m_rpm == _rpm) return; - rpm = _rpm; - rev_time = attotime::from_double(60/rpm); - floppy_ratio_1 = int(1000.0f*rpm/300.0f+0.5f); + m_rpm = _rpm; + m_rev_time = attotime::from_double(60/m_rpm); + m_angular_speed = m_rpm/60.0*2e8; } -void floppy_image_device::setup_write(floppy_image_format_t *_output_format) +void floppy_image_device::set_sectoring_type(uint32_t sectoring_type) { - output_format = _output_format; - commit_image(); + m_sectoring_type = sectoring_type; +} + +uint32_t floppy_image_device::get_sectoring_type() +{ + return m_sectoring_type; +} + +void floppy_image_device::setup_write(const floppy_image_format_t *_output_format) +{ + m_output_format = _output_format; + if(m_image) + commit_image(); } void floppy_image_device::commit_image() { - image_dirty = false; - if(!output_format || !output_format->supports_save()) + m_image_dirty = false; + if(!m_output_format || !m_output_format->supports_save()) + return; + + check_for_file(); + auto io = util::random_read_write_fill(image_core_file(), 0xff); + if(!io) { + popmessage("Error, out of memory"); return; - io_generic io; - // Do _not_ remove this cast otherwise the pointer will be incorrect when used by the ioprocs. - io.file = (device_image_interface *)this; - io.procs = &image_ioprocs; - io.filler = 0xff; + } - osd_file::error err = image_core_file().truncate(0); - if (err != osd_file::error::NONE) - popmessage("Error, unable to truncate image: %d", int(err)); + std::error_condition const err = image_core_file().truncate(0); + if (err) + popmessage("Error, unable to truncate image: %s", err.message()); - output_format->save(&io, image); + m_output_format->save(*io, m_variants, *m_image); } +void floppy_image_device::device_config_complete() +{ + m_rpm = 0; + m_motor_always_on = false; + m_dskchg_writable = false; + m_has_trk00_sensor = true; + + setup_characteristics(); + register_formats(); +} + +const software_list_loader &floppy_image_device::get_software_list_loader() const +{ + return image_software_list_loader::instance(); +} + + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void floppy_image_device::device_start() { - rpm = 0; - motor_always_on = false; - dskchg_writable = false; - has_trk00_sensor = true; - // better would be an extra parameter in the MCFG macro - drive_index = atoi(owner()->basetag()); + m_drive_index = atoi(owner()->basetag()); - idx = 0; + m_idx = 0; /* motor off */ - mon = 1; - - cyl = 0; - subcyl = 0; - ss = 0; - ds = -1; - stp = 1; - wpt = 0; - dskchg = exists() ? 1 : 0; - index_timer = timer_alloc(0); - image_dirty = false; - ready = true; - ready_counter = 0; + m_mon = 1; + + m_cyl = 0; + m_subcyl = 0; + m_ss = 0; + m_actual_ss = 0; + m_ds = -1; + m_stp = 1; + m_wpt = 0; + m_dskchg = exists() ? 1 : 0; + m_index_timer = timer_alloc(FUNC(floppy_image_device::index_resync), this); + m_image_dirty = false; + m_ready = true; + m_ready_counter = 0; + m_phases = 0; - setup_characteristics(); if (m_make_sound) m_sound_out = subdevice<floppy_sound_device>(FLOPSND_TAG); - save_item(NAME(dir)); - save_item(NAME(stp)); - save_item(NAME(wtg)); - save_item(NAME(mon)); - save_item(NAME(ss)); - save_item(NAME(ds)); - save_item(NAME(idx)); - save_item(NAME(wpt)); - save_item(NAME(rdy)); - save_item(NAME(dskchg)); - save_item(NAME(ready)); - save_item(NAME(rpm)); - save_item(NAME(floppy_ratio_1)); - save_item(NAME(revolution_start_time)); - save_item(NAME(rev_time)); - save_item(NAME(revolution_count)); - save_item(NAME(cyl)); - save_item(NAME(subcyl)); - save_item(NAME(cache_start_time)); - save_item(NAME(cache_end_time)); - save_item(NAME(cache_index)); - save_item(NAME(cache_entry)); - save_item(NAME(cache_weak)); - save_item(NAME(image_dirty)); - save_item(NAME(ready_counter)); + save_item(NAME(m_dir)); + save_item(NAME(m_stp)); + save_item(NAME(m_wtg)); + save_item(NAME(m_mon)); + save_item(NAME(m_ss)); + save_item(NAME(m_actual_ss)); + save_item(NAME(m_ds)); + save_item(NAME(m_idx)); + save_item(NAME(m_wpt)); + save_item(NAME(m_rdy)); + save_item(NAME(m_dskchg)); + save_item(NAME(m_ready)); + save_item(NAME(m_rpm)); + save_item(NAME(m_angular_speed)); + save_item(NAME(m_revolution_start_time)); + save_item(NAME(m_rev_time)); + save_item(NAME(m_revolution_count)); + save_item(NAME(m_cyl)); + save_item(NAME(m_subcyl)); + save_item(NAME(m_cache_start_time)); + save_item(NAME(m_cache_end_time)); + save_item(NAME(m_cache_index)); + save_item(NAME(m_cache_entry)); + save_item(NAME(m_cache_weak)); + save_item(NAME(m_image_dirty)); + save_item(NAME(m_ready_counter)); + save_item(NAME(m_phases)); } void floppy_image_device::device_reset() @@ -381,143 +579,133 @@ void floppy_image_device::device_reset() m_make_sound = m_sound_out->samples_loaded(); } - revolution_start_time = attotime::never; - revolution_count = 0; - mon = 1; + m_revolution_start_time = attotime::never; + m_revolution_count = 0; + m_mon = 1; set_ready(true); - if(motor_always_on && image) + if(m_motor_always_on && m_image) mon_w(0); cache_clear(); } -void floppy_image_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - index_resync(); -} - -floppy_image_format_t *floppy_image_device::identify(std::string filename) +std::pair<std::error_condition, const floppy_image_format_t *> floppy_image_device::identify(std::string_view filename) { util::core_file::ptr fd; std::string revised_path; + std::error_condition err = util::zippath_fopen(filename, OPEN_FLAG_READ, fd, revised_path); + if(err) + return{ err, nullptr }; - osd_file::error err = util::zippath_fopen(filename, OPEN_FLAG_READ, fd, revised_path); - if(err != osd_file::error::NONE) { - seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to open the image file"); - return nullptr; - } + auto io = util::random_read_fill(std::move(fd), 0xff); + if(!io) + return{ std::errc::not_enough_memory, nullptr }; - io_generic io; - io.file = fd.get(); - io.procs = &corefile_ioprocs_noclose; - io.filler = 0xff; int best = 0; - floppy_image_format_t *best_format = nullptr; - for (floppy_image_format_t *format = fif_list; format; format = format->next) - { - int score = format->identify(&io, form_factor); + const floppy_image_format_t *best_format = nullptr; + for(const floppy_image_format_t *format : m_fif_list) { + int score = format->identify(*io, m_form_factor, m_variants); if(score > best) { best = score; best_format = format; } } - fd.reset(); - return best_format; + + if(best_format) + return{ std::error_condition(), best_format }; + else + return{ image_error::INVALIDIMAGE, nullptr }; } void floppy_image_device::init_floppy_load(bool write_supported) { cache_clear(); - revolution_start_time = mon ? attotime::never : machine().time(); - revolution_count = 0; + m_revolution_start_time = m_mon ? attotime::never : machine().time(); + m_revolution_count = 0; - index_resync(); + index_resync(0); - wpt = 1; // disk sleeve is covering the sensor - if (!cur_wpt_cb.isnull()) - cur_wpt_cb(this, wpt); + m_wpt = 1; // disk sleeve is covering the sensor + if (!m_cur_wpt_cb.isnull()) + m_cur_wpt_cb(this, m_wpt); - wpt = is_readonly() || (!write_supported); - if (!cur_wpt_cb.isnull()) - cur_wpt_cb(this, wpt); + m_wpt = is_readonly() || (!write_supported); + if (!m_cur_wpt_cb.isnull()) + m_cur_wpt_cb(this, m_wpt); - if (motor_always_on) { + if (m_motor_always_on) { // When disk is inserted, start motor mon_w(0); - } else if(!mon) - ready_counter = 2; + m_ready_counter = 2; + + } else if(!m_mon) + m_ready_counter = 2; - if (dskchg_writable) - dskchg = 1; + if (m_dskchg_writable) + m_dskchg = 1; } -image_init_result floppy_image_device::call_load() +std::pair<std::error_condition, std::string> floppy_image_device::call_load() { - io_generic io; + check_for_file(); + auto io = util::random_read_fill(image_core_file(), 0xff); + if(!io) + return std::make_pair(std::errc::not_enough_memory, std::string()); - // Do _not_ remove this cast otherwise the pointer will be incorrect when used by the ioprocs. - io.file = (device_image_interface *)this; - io.procs = &image_ioprocs; - io.filler = 0xff; int best = 0; - floppy_image_format_t *best_format = nullptr; - for(floppy_image_format_t *format = fif_list; format; format = format->next) { - int score = format->identify(&io, form_factor); + const floppy_image_format_t *best_format = nullptr; + for (const floppy_image_format_t *format : m_fif_list) { + int score = format->identify(*io, m_form_factor, m_variants); + if(score && format->extension_matches(filename())) + score |= floppy_image_format_t::FIFID_EXT; if(score > best) { best = score; best_format = format; } } - if(!best_format) - { - seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to identify the image format"); - return image_init_result::FAIL; - } + if (!best_format) + return std::make_pair(image_error::INVALIDIMAGE, "Unable to identify image file format"); - image = global_alloc(floppy_image(tracks, sides, form_factor)); - if (!best_format->load(&io, form_factor, image)) - { - seterror(IMAGE_ERROR_UNSUPPORTED, "Incompatible image format or corrupted data"); - global_free(image); - image = nullptr; - return image_init_result::FAIL; + m_image = std::make_unique<floppy_image>(m_tracks, m_sides, m_form_factor); + if (!best_format->load(*io, m_form_factor, m_variants, *m_image)) { + m_image.reset(); + return std::make_pair(image_error::INVALIDIMAGE, "Incompatible image file format or corrupted data"); } - output_format = is_readonly() ? nullptr : best_format; + m_output_format = is_readonly() ? nullptr : best_format; - image_dirty = false; + m_image_dirty = false; - init_floppy_load(output_format != nullptr); + init_floppy_load(m_output_format != nullptr); - if (!cur_load_cb.isnull()) - return cur_load_cb(this); + if (!m_cur_load_cb.isnull()) + m_cur_load_cb(this); - return image_init_result::PASS; + return std::make_pair(std::error_condition(), std::string()); } void floppy_image_device::call_unload() { cache_clear(); - dskchg = 0; + m_dskchg = 0; - if (image) { - if(image_dirty) + if (m_image) { + if(m_image_dirty) commit_image(); - global_free(image); - image = nullptr; + m_image.reset(); } - wpt = 1; // disk sleeve is covering the sensor - if (!cur_wpt_cb.isnull()) - cur_wpt_cb(this, wpt); + m_wpt = 1; // disk sleeve is covering the sensor + if (!m_cur_wpt_cb.isnull()) + m_cur_wpt_cb(this, m_wpt); - wpt = 0; // sensor is uncovered - if (!cur_wpt_cb.isnull()) - cur_wpt_cb(this, wpt); + m_wpt = 0; // sensor is uncovered + if (!m_cur_wpt_cb.isnull()) + m_cur_wpt_cb(this, m_wpt); - if (!cur_unload_cb.isnull()) - cur_unload_cb(this); + if (!m_cur_unload_cb.isnull()) + m_cur_unload_cb(this); - if (motor_always_on) { + if (m_motor_always_on) { // When disk is removed, stop motor mon_w(1); } @@ -525,13 +713,13 @@ void floppy_image_device::call_unload() set_ready(true); } -image_init_result floppy_image_device::call_create(int format_type, util::option_resolution *format_options) +std::pair<std::error_condition, std::string> floppy_image_device::call_create(int format_type, util::option_resolution *format_options) { - image = global_alloc(floppy_image(tracks, sides, form_factor)); - output_format = nullptr; + m_image = std::make_unique<floppy_image>(m_tracks, m_sides, m_form_factor); + m_output_format = nullptr; // search for a suitable format based on the extension - for(floppy_image_format_t *i = fif_list; i; i = i->next) + for(const floppy_image_format_t *i : m_fif_list) { // only consider formats that actually support saving if(!i->supports_save()) @@ -539,53 +727,78 @@ image_init_result floppy_image_device::call_create(int format_type, util::option if (i->extension_matches(basename())) { - output_format = i; + m_output_format = i; break; } + + // Use MFI as a default. + if (!strcmp(i->name(), "mfi")) + m_output_format = i; } - // did we find a suitable format? - if (output_format == nullptr) - { - seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to identify the image format"); - return image_init_result::FAIL; + init_floppy_load(true); + + return std::make_pair(std::error_condition(), std::string()); +} + +void floppy_image_device::init_fs(const fs_info *fs, const fs::meta_data &meta) +{ + assert(m_image); + if (fs->m_type) { + std::vector<u8> img(fs->m_image_size); + fs::fsblk_vec_t blockdev(img); + auto cfs = fs->m_manager->mount(blockdev); + cfs->format(meta); + + auto io = util::ram_read(img.data(), img.size(), 0xff); + fs->m_type->load(*io, floppy_image::FF_UNKNOWN, m_variants, *m_image); + } else { + fs::unformatted_image::format(fs->m_key, m_image.get()); } - init_floppy_load(output_format != nullptr); + // intializing a file system makes the floppy dirty + m_image_dirty = true; +} - return image_init_result::PASS; +/* write protect, active high + phase 1 can force it to 1 for drive detection + on the rare drives that actually use m_phases. + */ +bool floppy_image_device::wpt_r() +{ + return m_wpt || (m_phases & 2); } /* motor on, active low */ void floppy_image_device::mon_w(int state) { - if(mon == state) + if(m_mon == state) return; - mon = state; + m_mon = state; /* off -> on */ - if (!mon && image) + if (!m_mon && m_image) { - revolution_start_time = machine().time(); + m_revolution_start_time = machine().time(); cache_clear(); - if (motor_always_on) { + if (m_motor_always_on) { // Drives with motor that is always spinning are immediately ready when a disk is loaded // because there is no spin-up time set_ready(false); } else { - ready_counter = 2; + m_ready_counter = 2; } - index_resync(); + index_resync(0); } /* on -> off */ else { - if(image_dirty) + if(m_image_dirty) commit_image(); cache_clear(); - revolution_start_time = attotime::never; - index_timer->adjust(attotime::zero); + m_revolution_start_time = attotime::never; + m_index_timer->adjust(attotime::zero); set_ready(true); } @@ -595,128 +808,153 @@ void floppy_image_device::mon_w(int state) attotime floppy_image_device::time_next_index() { - if(revolution_start_time.is_never()) + if(m_revolution_start_time.is_never()) return attotime::never; - return revolution_start_time + rev_time; + return m_revolution_start_time + m_rev_time; } -/* index pulses at rpm/60 Hz, and stays high for ~2ms at 300rpm */ -void floppy_image_device::index_resync() +/* index pulses at m_rpm/60 Hz, and stays high for ~2ms at 300rpm */ +TIMER_CALLBACK_MEMBER(floppy_image_device::index_resync) { - if(revolution_start_time.is_never()) { - if(idx) { - idx = 0; - if (!cur_index_pulse_cb.isnull()) - cur_index_pulse_cb(this, idx); + if(m_revolution_start_time.is_never()) { + if(m_idx) { + m_idx = 0; + if (!m_cur_index_pulse_cb.isnull()) + m_cur_index_pulse_cb(this, m_idx); } return; } - attotime delta = machine().time() - revolution_start_time; - while(delta >= rev_time) { - delta -= rev_time; - revolution_start_time += rev_time; - revolution_count++; + attotime delta = machine().time() - m_revolution_start_time; + while(delta >= m_rev_time) { + delta -= m_rev_time; + m_revolution_start_time += m_rev_time; + m_revolution_count++; } - int position = (delta*floppy_ratio_1).as_ticks(1000000000/1000); + int position = int(delta.as_double()*m_angular_speed + 0.5); - int new_idx = position < 20000; + uint32_t last_index = 0, next_index = 200000000; + // if hard-sectored floppy, has extra IDX pulses + if(m_image) + m_image->find_index_hole(position, last_index, next_index); + int new_idx = position - last_index < 2000000; if(new_idx) { - attotime index_up_time = attotime::from_nsec((2000000*1000)/floppy_ratio_1); - index_timer->adjust(index_up_time - delta); - } else - index_timer->adjust(rev_time - delta); - - if(new_idx != idx) { - idx = new_idx; - if(idx && ready) { - ready_counter--; - if(!ready_counter) { + uint32_t index_up = last_index + 2000000; + attotime index_up_time = attotime::from_double(index_up/m_angular_speed); + m_index_timer->adjust(index_up_time - delta); + } else { + attotime next_index_time = next_index >= 200000000 ? m_rev_time : attotime::from_double(next_index/m_angular_speed); + m_index_timer->adjust(next_index_time - delta); + } + + if(new_idx != m_idx) { + m_idx = new_idx; + if(m_idx && m_ready) { + m_ready_counter--; + if(!m_ready_counter) { // logerror("Drive spun up\n"); set_ready(false); } } - if (!cur_index_pulse_cb.isnull()) - cur_index_pulse_cb(this, idx); + if (!m_cur_index_pulse_cb.isnull()) + m_cur_index_pulse_cb(this, m_idx); } } bool floppy_image_device::ready_r() { - return ready; + return m_ready; } void floppy_image_device::set_ready(bool state) { - if (state != ready) + if (state != m_ready) { - ready = state; + m_ready = state; check_led(); - if (!cur_ready_cb.isnull()) - cur_ready_cb(this, ready); + if (!m_cur_ready_cb.isnull()) + m_cur_ready_cb(this, m_ready); } } void floppy_image_device::check_led() { - if(!cur_led_cb.isnull()) - cur_led_cb(this, (ds == drive_index) && !ready ? 1 : 0); -} - -double floppy_image_device::get_pos() -{ - return index_timer->elapsed().as_double(); + if(!m_cur_led_cb.isnull()) + m_cur_led_cb(this, (m_ds == m_drive_index) && !m_ready ? 1 : 0); } bool floppy_image_device::twosid_r() { int tracks = 0, heads = 0; - if (image) image->get_actual_geometry(tracks, heads); + if (m_image) m_image->get_actual_geometry(tracks, heads); return heads == 1; } +bool floppy_image_device::floppy_is_hd() +{ + if (!m_image) + return false; + u32 const variant = m_image->get_variant(); + return variant == floppy_image::DSHD; +} + +bool floppy_image_device::floppy_is_ed() +{ + if (!m_image) + return false; + u32 const variant = m_image->get_variant(); + return variant == floppy_image::DSED; +} + +void floppy_image_device::track_changed() +{ +} + void floppy_image_device::stp_w(int state) { // Before spin-up is done, ignore step pulses // TODO: There are reports about drives supporting step operation with // stopped spindle. Need to check that on real drives. - // if (ready_counter > 0) return; + // if (m_ready_counter > 0) return; - if ( stp != state ) { + if ( m_stp != state ) { cache_clear(); - stp = state; - if ( stp == 0 ) { - int ocyl = cyl; - if ( dir ) { - if ( cyl ) cyl--; + m_stp = state; + if ( m_stp == 0 ) { + int ocyl = m_cyl; + if ( m_dir ) { + if ( m_cyl ) m_cyl--; } else { - if ( cyl < tracks-1 ) cyl++; + if ( m_cyl < m_tracks-1 ) m_cyl++; } - if(ocyl != cyl) + if(ocyl != m_cyl) { - if (TRACE_STEP) logerror("track %d\n", cyl); + if (TRACE_STEP) logerror("track %d\n", m_cyl); // Do we want a stepper sound? // We plan for 5 zones with possibly specific sounds - if (m_make_sound) m_sound_out->step(cyl*5/tracks); + if (m_make_sound) m_sound_out->step(m_cyl*5/m_tracks); + track_changed(); } /* Update disk detection if applicable */ - if (exists() && !dskchg_writable) + if (exists() && !m_dskchg_writable) { - if (dskchg==0) dskchg = 1; + if (m_dskchg==0) m_dskchg = 1; } } - subcyl = 0; + m_subcyl = 0; } } -void floppy_image_device::seek_phase_w(int phases) +void floppy_image_device::seek_phase_w(int _phases) { - int cur_pos = (cyl << 2) | subcyl; + m_phases = _phases; + + int cur_pos = (m_cyl << 2) | m_subcyl; int req_pos; - switch(phases) { + switch(m_phases) { case 0x1: req_pos = 0; break; case 0x3: req_pos = 1; break; case 0x2: req_pos = 2; break; @@ -739,20 +977,23 @@ void floppy_image_device::seek_phase_w(int phases) next_pos -= 8; if(next_pos < 0) next_pos = 0; - else if(next_pos > (tracks-1)*4) - next_pos = (tracks-1)*4; - cyl = next_pos >> 2; - subcyl = next_pos & 3; + else if(next_pos > (m_tracks-1)*4) + next_pos = (m_tracks-1)*4; + + m_cyl = next_pos >> 2; + m_subcyl = next_pos & 3; cache_clear(); - if(TRACE_STEP && (next_pos != cur_pos)) - logerror("track %d.%d\n", cyl, subcyl); + if(next_pos != cur_pos) { + if (TRACE_STEP) logerror("track %d.%d\n", m_cyl, m_subcyl); + if (m_make_sound) m_sound_out->step(m_subcyl); + } /* Update disk detection if applicable */ - if (exists() && !dskchg_writable) - if (dskchg==0) - dskchg = 1; + if (exists() && !m_dskchg_writable) + if (m_dskchg==0) + m_dskchg = 1; } // From http://burtleburtle.net/bob/hash/integer.html @@ -767,99 +1008,69 @@ uint32_t floppy_image_device::hash32(uint32_t a) const return a; } -int floppy_image_device::find_index(uint32_t position, const std::vector<uint32_t> &buf)const -{ - int spos = (buf.size() >> 1)-1; - int step; - for(step=1; step<buf.size()+1; step<<=1) { } - step >>= 1; - - for(;;) { - if(spos >= int(buf.size()) || (spos > 0 && (buf[spos] & floppy_image::TIME_MASK) > position)) { - spos -= step; - step >>= 1; - } else if(spos < 0 || (spos < int(buf.size())-1 && (buf[spos+1] & floppy_image::TIME_MASK) <= position)) { - spos += step; - step >>= 1; - } else - return spos; - } -} - uint32_t floppy_image_device::find_position(attotime &base, const attotime &when) { - base = revolution_start_time; + base = m_revolution_start_time; attotime delta = when - base; - while(delta >= rev_time) { - delta -= rev_time; - base += rev_time; + while(delta >= m_rev_time) { + delta -= m_rev_time; + base += m_rev_time; } while(delta < attotime::zero) { - delta += rev_time; - base -= rev_time; + delta += m_rev_time; + base -= m_rev_time; } - uint32_t res = (delta*floppy_ratio_1).as_ticks(1000000000/1000); + uint32_t res = uint32_t(delta.as_double()*m_angular_speed+0.5); if (res >= 200000000) { // Due to rounding errors in the previous operation, // 'res' sometimes overflows 2E+8 res -= 200000000; - base += rev_time; + base += m_rev_time; } return res; } -bool floppy_image_device::test_track_last_entry_warps(const std::vector<uint32_t> &buf) const -{ - return !((buf[buf.size() - 1]^buf[0]) & floppy_image::MG_MASK); -} - attotime floppy_image_device::position_to_time(const attotime &base, int position) const { - return base + attotime::from_nsec((int64_t(position)*2000/floppy_ratio_1+1)/2); + return base + attotime::from_double(position/m_angular_speed); } void floppy_image_device::cache_fill_index(const std::vector<uint32_t> &buf, int &index, attotime &base) { int cells = buf.size(); - if(index != 0 || !test_track_last_entry_warps(buf)) { - cache_index = index; - cache_start_time = position_to_time(base, buf[index] & floppy_image::TIME_MASK); - } else { - cache_index = cells - 1; - cache_start_time = position_to_time(base - rev_time, buf[cache_index] & floppy_image::TIME_MASK); - } - - cache_entry = buf[cache_index]; + m_cache_index = index; + m_cache_start_time = position_to_time(base, buf[index] & floppy_image::TIME_MASK); + m_cache_entry = buf[m_cache_index]; index ++; if(index >= cells) { - index = test_track_last_entry_warps(buf) ? 1 : 0; - base += rev_time; + index = 0; + base += m_rev_time; } - cache_end_time = position_to_time(base, buf[index] & floppy_image::TIME_MASK); + m_cache_end_time = position_to_time(base, buf[index] & floppy_image::TIME_MASK); } void floppy_image_device::cache_clear() { - cache_start_time = cache_end_time = cache_weak_start = attotime::zero; - cache_index = 0; - cache_entry = 0; - cache_weak = false; + m_cache_start_time = m_cache_end_time = m_cache_weak_start = attotime::zero; + m_cache_index = 0; + m_cache_entry = 0; + m_cache_weak = false; } void floppy_image_device::cache_fill(const attotime &when) { - std::vector<uint32_t> &buf = image->get_buffer(cyl, ss, subcyl); - uint32_t cells = buf.size(); + std::vector<uint32_t> &buf = m_image->get_buffer(m_cyl, m_ss, m_subcyl); + uint32_t const cells = buf.size(); if(cells <= 1) { - cache_start_time = attotime::zero; - cache_end_time = attotime::never; - cache_index = 0; - cache_entry = cells == 1 ? buf[0] : floppy_image::MG_N; + m_cache_start_time = attotime::zero; + m_cache_end_time = attotime::never; + m_cache_index = 0; + m_cache_entry = (cells == 1) ? buf[0] : floppy_image::MG_N; cache_weakness_setup(); return; } @@ -867,65 +1078,63 @@ void floppy_image_device::cache_fill(const attotime &when) attotime base; uint32_t position = find_position(base, when); - int index = find_index(position, buf); + auto const it = std::upper_bound( + buf.begin(), buf.end(), position, + [] (uint32_t a, uint32_t b) { return a < (b & floppy_image::TIME_MASK); }); - if(index == -1) { - // I suspect this should be an abort(), to check... - cache_start_time = attotime::zero; - cache_end_time = attotime::never; - cache_index = 0; - cache_entry = buf[0]; - cache_weakness_setup(); - return; + int index; + if(buf.begin() == it) { + base -= m_rev_time; + index = buf.size() - 1; + } else { + index = int(it - buf.begin()) - 1; } for(;;) { cache_fill_index(buf, index, base); - if(cache_end_time > when) { + if(m_cache_end_time > when) { cache_weakness_setup(); - return; + break; } } } void floppy_image_device::cache_weakness_setup() { - u32 type = cache_entry & floppy_image::MG_MASK; + u32 type = m_cache_entry & floppy_image::MG_MASK; if(type == floppy_image::MG_N || type == floppy_image::MG_D) { - cache_weak = true; - cache_weak_start = cache_start_time; + m_cache_weak = true; + m_cache_weak_start = m_cache_start_time; return; } - cache_weak = cache_end_time.is_never() || (cache_end_time - cache_start_time >= attotime::from_usec(16)); - if(!cache_weak) { - cache_weak_start = attotime::never; + m_cache_weak = m_cache_end_time.is_never() || (m_cache_end_time - m_cache_start_time >= m_amplifier_freakout_time); + if(!m_cache_weak) { + m_cache_weak_start = attotime::never; return; } - cache_weak_start = cache_start_time + attotime::from_usec(16); + m_cache_weak_start = m_cache_start_time + attotime::from_usec(16); } attotime floppy_image_device::get_next_transition(const attotime &from_when) { - if(!image || mon) + if(!m_image || m_mon) return attotime::never; - if(from_when < cache_start_time || (!cache_end_time.is_never() && from_when >= cache_end_time)) + if(from_when < m_cache_start_time || m_cache_start_time.is_zero() || (!m_cache_end_time.is_never() && from_when >= m_cache_end_time)) cache_fill(from_when); - if(!cache_weak) - return cache_end_time; + if(!m_cache_weak) + return m_cache_end_time; // Put a flux transition in the middle of a 4us interval with a 50% probability - int interval_index = (from_when - cache_weak_start).as_ticks(250000); - if(interval_index < 0) - interval_index = 0; - attotime weak_time = cache_weak_start + attotime::from_ticks(interval_index*2+1, 500000); + uint64_t interval_index = (from_when < m_cache_weak_start) ? 0 : (from_when - m_cache_weak_start).as_ticks(250000); + attotime weak_time = m_cache_weak_start + attotime::from_ticks(interval_index*2+1, 500000); for(;;) { - if(weak_time >= cache_end_time) - return cache_end_time; + if(weak_time >= m_cache_end_time) + return m_cache_end_time; if(weak_time > from_when) { - u32 test = hash32(hash32(hash32(hash32(revolution_count) ^ 0x4242) + cache_index) + interval_index); + u32 test = hash32(hash32(hash32(hash32(m_revolution_count) ^ 0x4242) + m_cache_index) + interval_index); if(test & 1) return weak_time; } @@ -934,180 +1143,187 @@ attotime floppy_image_device::get_next_transition(const attotime &from_when) } } +bool floppy_image_device::writing_disabled() const +{ + // Disable writing when write protect is on or when, in the diskii + // case, phase 1 is 1 + return m_wpt || (m_phases & 2); +} + void floppy_image_device::write_flux(const attotime &start, const attotime &end, int transition_count, const attotime *transitions) { - if(!image || mon) + if(!m_image || m_mon) return; - image_dirty = true; - attotime base; - int start_pos = find_position(base, start); - int end_pos = find_position(base, end); + if(writing_disabled()) + return; - std::vector<int> trans_pos(transition_count); - for(int i=0; i != transition_count; i++) - trans_pos[i] = find_position(base, transitions[i]); + m_image_dirty = true; + m_track_dirty = true; + cache_clear(); - std::vector<uint32_t> &buf = image->get_buffer(cyl, ss, subcyl); + std::vector<wspan> wspans(1); - int index; - if(!buf.empty()) - index = find_index(start_pos, buf); - else { - index = 0; - buf.push_back(floppy_image::MG_N); - } + attotime base; + wspans[0].start = find_position(base, start); + wspans[0].end = find_position(base, end); - if(index && (buf[index] & floppy_image::TIME_MASK) == start_pos) - index--; + for(int i=0; i != transition_count; i++) + wspans[0].flux_change_positions.push_back(find_position(base, transitions[i])); - uint32_t 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; + wspan_split_on_wrap(wspans); - uint32_t pos = start_pos; - int ti = 0; - int cells = buf.size(); - while(pos != end_pos) { - if(buf.size() < cells+10) - buf.resize(cells+200); - uint32_t next_pos; - if(ti != transition_count) - next_pos = trans_pos[ti++]; - else - next_pos = end_pos; - if(next_pos > pos) - write_zone(&buf[0], cells, index, pos, next_pos, cur_mg); - else { - write_zone(&buf[0], cells, index, pos, 200000000, cur_mg); - index = 0; - write_zone(&buf[0], 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; + std::vector<uint32_t> &buf = m_image->get_buffer(m_cyl, m_ss, m_subcyl); + + if(buf.empty()) { + buf.push_back(floppy_image::MG_N); + buf.push_back(floppy_image::MG_E | 199999999); } - buf.resize(cells); -} + wspan_remove_damaged(wspans, buf); + wspan_write(wspans, buf); -void floppy_image_device::write_zone(uint32_t *buf, int &cells, int &index, uint32_t spos, uint32_t epos, uint32_t mg) -{ cache_clear(); - while(spos < epos) { - while(index != cells-1 && (buf[index+1] & floppy_image::TIME_MASK) <= spos) - index++; - - uint32_t ref_start = buf[index] & floppy_image::TIME_MASK; - uint32_t ref_end = index == cells-1 ? 200000000 : buf[index+1] & floppy_image::TIME_MASK; - uint32_t 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; - } +void floppy_image_device::wspan_split_on_wrap(std::vector<wspan> &wspans) +{ + int ne = wspans.size(); + for(int i=0; i != ne; i++) + if(wspans[i].end < wspans[i].start) { + wspans.resize(wspans.size()+1); + auto &ws = wspans[i]; + auto &we = wspans.back(); + we.start = 0; + we.end = ws.end; + ws.end = 200000000; + int start = ws.start; + int split_index; + for(split_index = 0; split_index != ws.flux_change_positions.size(); split_index++) + if(ws.flux_change_positions[split_index] < start) + break; + if(split_index == 0) + std::swap(ws.flux_change_positions, we.flux_change_positions); - // If the zone is of the type we want, we don't need to touch it - if(ref_mg == mg) { - spos = ref_end; - continue; + else { + we.flux_change_positions.resize(ws.flux_change_positions.size() - split_index); + std::copy(ws.flux_change_positions.begin() + split_index, ws.flux_change_positions.end(), we.flux_change_positions.begin()); + ws.flux_change_positions.erase(ws.flux_change_positions.begin() + split_index, ws.flux_change_positions.end()); + } } +} - // 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_t prev_mg = index != 0 ? buf[index-1] & floppy_image::MG_MASK : ~0; - uint32_t 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_t)); - cells -= 2; - index--; - - } else { - // Previous matches, drop the current cell - memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(uint32_t)); - cells --; - } - - } else { - if(next_mg == mg) { - // Following matches, extend it - memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(uint32_t)); - cells --; - buf[index] = mg | spos; - } else { - // None match, convert the current cell - buf[index] = mg | spos; - index++; - } +void floppy_image_device::wspan_remove_damaged(std::vector<wspan> &wspans, const std::vector<uint32_t> &track) +{ + for(size_t pos = 0; pos != track.size(); pos++) + if((track[pos] & floppy_image::MG_MASK) == floppy_image::MG_D) { + int start = track[pos] & floppy_image::TIME_MASK; + int end = track[pos+1] & floppy_image::TIME_MASK; + int ne = wspans.size(); + for(int i=0; i != ne; i++) { + // D range outside of span range + if(wspans[i].start > end || wspans[i].end <= start) + continue; + + // D range covers span range + if(wspans[i].start >= start && wspans[i].end-1 <= end) { + wspans.erase(wspans.begin() + i); + i --; + ne --; + continue; } - 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_t)); - cells++; - buf[index] = mg | spos; - buf[index+1] = ref_mg | epos; + // D range covers the start of the span range + if(wspans[i].start >= start && wspans[i].end-1 > end) { + wspans[i].start = end+1; + while(!wspans[i].flux_change_positions.empty() && wspans[i].flux_change_positions[0] <= end) + wspans[i].flux_change_positions.erase(wspans[i].flux_change_positions.begin()); + continue; } - 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_t)); - cells++; + // D range covers the end of the span range + if(wspans[i].start < start && wspans[i].end-1 <= end) { + wspans[i].end = start; + while(!wspans[i].flux_change_positions.empty() && wspans[i].flux_change_positions[wspans[i].flux_change_positions.size()-1] >= start) + wspans[i].flux_change_positions.erase(wspans[i].flux_change_positions.end()-1); + continue; } - buf[index+1] = mg | spos; - index++; - spos = ref_end; + // D range is inside the span range, need to split + int id = wspans.size(); + wspans.resize(id+1); + wspans[id].start = end+1; + wspans[id].end = wspans[i].end; + wspans[id].flux_change_positions = wspans[i].flux_change_positions; + wspans[i].end = start; + while(!wspans[i].flux_change_positions.empty() && wspans[i].flux_change_positions[wspans[i].flux_change_positions.size()-1] >= start) + wspans[i].flux_change_positions.erase(wspans[i].flux_change_positions.end()-1); + while(!wspans[id].flux_change_positions.empty() && wspans[id].flux_change_positions[0] <= end) + wspans[id].flux_change_positions.erase(wspans[id].flux_change_positions.begin()); + } + } +} + +void floppy_image_device::wspan_write(const std::vector<wspan> &wspans, std::vector<uint32_t> &track) +{ + for(const auto &ws : wspans) { + unsigned si, ei; + for(si = 0; si != track.size(); si++) + if((track[si] & floppy_image::TIME_MASK) >= ws.start) + break; + for(ei = si; ei != track.size(); ei++) + if((track[ei] & floppy_image::TIME_MASK) >= ws.end) + break; + + // Reduce neutral zone at the start, if there's one + if(si != track.size() && (track[si] & floppy_image::MG_MASK) == floppy_image::MG_E) { + // Neutral zone is over the whole range, split it and adapt si/ei + if(si == ei) { + track.insert(track.begin() + si, floppy_image::MG_E | (ws.start-1)); + track.insert(track.begin() + si + 1, (track[si-1] & floppy_image::MG_MASK) | ws.end); + si = ei = si+1; } 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_t)); - cells += 2; - buf[index+1] = mg | spos; - buf[index+2] = ref_mg | epos; - spos = epos; + // Reduce the zone size + track[si] = floppy_image::MG_E | (ws.start-1); + si ++; } } + // Check for a neutral zone at the end and reduce it if needed + if(ei != track.size() && (track[ei] & floppy_image::MG_MASK) == floppy_image::MG_E) { + track[ei-1] = floppy_image::MG_N | ws.end; + ei --; + } + + // Clear the covered zone + track.erase(track.begin() + si, track.begin() + ei); + + // Insert the flux changes + for(auto f : ws.flux_change_positions) { + track.insert(track.begin() + si, floppy_image::MG_F | f); + si ++; + } } } void floppy_image_device::set_write_splice(const attotime &when) { - if(image) { - image_dirty = true; + if(m_image && !m_mon) { + m_image_dirty = true; attotime base; int splice_pos = find_position(base, when); - image->set_write_splice_position(cyl, ss, splice_pos, subcyl); + m_image->set_write_splice_position(m_cyl, m_ss, splice_pos, m_subcyl); } } uint32_t floppy_image_device::get_form_factor() const { - return form_factor; + return m_form_factor; } uint32_t floppy_image_device::get_variant() const { - return image ? image->get_variant() : 0; + return m_image ? m_image->get_variant() : 0; } //=================================================================== @@ -1230,7 +1446,7 @@ void floppy_sound_device::device_start() { // What kind of drive do we have? bool is525 = strstr(tag(), "525") != nullptr; - set_samples_names(is525? floppy525_sample_names : floppy35_sample_names); + set_samples_names(is525 ? floppy525_sample_names : floppy35_sample_names); m_motor_on = false; @@ -1249,7 +1465,7 @@ void floppy_sound_device::device_start() // If we don't have all samples, don't allocate a stream or access sample data. if (m_loaded) { - m_sound = machine().sound().stream_alloc(*this, 0, 1, clock()); // per-floppy stream + m_sound = stream_alloc(0, 1, clock()); // per-floppy stream } register_for_save_states(); } @@ -1268,13 +1484,16 @@ void floppy_sound_device::motor(bool running, bool withdisk) if ((m_spin_playback_sample==QUIET || m_spin_playback_sample==SPIN_END) && running) // motor was either off or already spinning down { m_spin_samplepos = 0; - m_spin_playback_sample = withdisk? SPIN_START_LOADED : SPIN_START_EMPTY; // (re)start the motor sound + m_spin_playback_sample = withdisk ? SPIN_START_LOADED : SPIN_START_EMPTY; // (re)start the motor sound } else { // Motor has been running and is turned off now if ((m_spin_playback_sample == SPIN_EMPTY || m_spin_playback_sample == SPIN_LOADED) && !running) + { + m_spin_samplepos = 0; m_spin_playback_sample = SPIN_END; // go to spin down sound when loop is finished + } } } m_motor_on = running; @@ -1343,6 +1562,9 @@ void floppy_sound_device::step(int zone) } } } + + // Start the new seek sound from the beginning. + m_seek_samplepos = 0; } // Changing the pitch does not always sound convincing @@ -1373,27 +1595,26 @@ void floppy_sound_device::step(int zone) // sound_stream_update - update the sound stream //------------------------------------------------- -void floppy_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +void floppy_sound_device::sound_stream_update(sound_stream &stream) { // We are using only one stream, unlike the parent class // Also, there is no need for interpolation, as we only expect // one sample rate of 44100 for all samples int16_t out; - stream_sample_t *samplebuffer = outputs[0]; - int idx = 0; + int m_idx = 0; int sampleend = 0; - while (samples-- > 0) + for (int sampindex = 0; sampindex < stream.samples(); sampindex++) { out = 0; // Motor sound if (m_spin_playback_sample != QUIET) { - idx = m_spin_playback_sample; - sampleend = m_sample[idx].data.size(); - out = m_sample[idx].data[m_spin_samplepos++]; + m_idx = m_spin_playback_sample; + sampleend = m_sample[m_idx].data.size(); + out = m_sample[m_idx].data[m_spin_samplepos++]; if (m_spin_samplepos >= sampleend) { @@ -1420,7 +1641,7 @@ void floppy_sound_device::sound_stream_update(sound_stream &stream, stream_sampl // Spindown sample over, be quiet or restart if the // motor has been restarted if (m_motor_on) - m_spin_playback_sample = m_with_disk? SPIN_START_LOADED : SPIN_START_EMPTY; + m_spin_playback_sample = m_with_disk ? SPIN_START_LOADED : SPIN_START_EMPTY; else m_spin_playback_sample = QUIET; break; @@ -1446,10 +1667,10 @@ void floppy_sound_device::sound_stream_update(sound_stream &stream, stream_sampl { m_seek_sound_timeout--; - idx = m_step_base + m_seek_playback_sample; - sampleend = m_sample[idx].data.size(); + m_idx = m_step_base + m_seek_playback_sample; + sampleend = m_sample[m_idx].data.size(); // Mix it into the stream value - out += m_sample[idx].data[(int)m_seek_samplepos]; + out += m_sample[m_idx].data[(int)m_seek_samplepos]; // By adding different values than 1, we can change the playback speed // This will be used to adjust the seek sound m_seek_samplepos += m_seek_pitch; @@ -1463,11 +1684,11 @@ void floppy_sound_device::sound_stream_update(sound_stream &stream, stream_sampl // Stepper sound if (m_step_playback_sample != QUIET) { - idx = m_step_base + m_step_playback_sample; - sampleend = m_sample[idx].data.size(); + m_idx = m_step_base + m_step_playback_sample; + sampleend = m_sample[m_idx].data.size(); // Mix it into the stream value - out += m_sample[idx].data[m_step_samplepos++]; + out += m_sample[m_idx].data[m_step_samplepos++]; if (m_step_samplepos >= sampleend) { // Step sample done @@ -1478,7 +1699,7 @@ void floppy_sound_device::sound_stream_update(sound_stream &stream, stream_sampl } // Write to the stream buffer - *(samplebuffer++) = out; + stream.put_int(0, sampindex, out, 32768); } } @@ -1499,6 +1720,53 @@ DEFINE_DEVICE_TYPE(FLOPPYSOUND, floppy_sound_device, "flopsnd", "Floppy sound") //************************************************************************** //------------------------------------------------- +// 3" single-sided single density +//------------------------------------------------- + +floppy_3_sssd::floppy_3_sssd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + floppy_image_device(mconfig, FLOPPY_3_SSSD, tag, owner, clock) +{ +} + +floppy_3_sssd::~floppy_3_sssd() +{ +} + +void floppy_3_sssd::setup_characteristics() +{ + m_form_factor = floppy_image::FF_3; + m_tracks = 42; + m_sides = 1; + set_rpm(300); + + add_variant(floppy_image::SSSD); +} + +//------------------------------------------------- +// 3" double-sided single density +//------------------------------------------------- + +floppy_3_dssd::floppy_3_dssd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + floppy_image_device(mconfig, FLOPPY_3_DSSD, tag, owner, clock) +{ +} + +floppy_3_dssd::~floppy_3_dssd() +{ +} + +void floppy_3_dssd::setup_characteristics() +{ + m_form_factor = floppy_image::FF_3; + m_tracks = 42; + m_sides = 2; + set_rpm(300); + + add_variant(floppy_image::SSSD); + add_variant(floppy_image::DSSD); +} + +//------------------------------------------------- // 3" single-sided double density //------------------------------------------------- @@ -1513,16 +1781,13 @@ floppy_3_ssdd::~floppy_3_ssdd() void floppy_3_ssdd::setup_characteristics() { - form_factor = floppy_image::FF_3; - tracks = 42; - sides = 1; + m_form_factor = floppy_image::FF_3; + m_tracks = 42; + m_sides = 1; set_rpm(300); -} -void floppy_3_ssdd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); } //------------------------------------------------- @@ -1540,17 +1805,42 @@ floppy_3_dsdd::~floppy_3_dsdd() void floppy_3_dsdd::setup_characteristics() { - form_factor = floppy_image::FF_3; - tracks = 42; - sides = 2; + m_form_factor = floppy_image::FF_3; + m_tracks = 42; + m_sides = 2; set_rpm(300); + + add_variant(floppy_image::SSSD); + add_variant(floppy_image::DSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); +} + +//------------------------------------------------- +// 3" double-sided quad density +//------------------------------------------------- + +floppy_3_dsqd::floppy_3_dsqd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + floppy_image_device(mconfig, FLOPPY_3_DSQD, tag, owner, clock) +{ +} + +floppy_3_dsqd::~floppy_3_dsqd() +{ } -void floppy_3_dsdd::handled_variants(uint32_t *variants, int &var_count) const +void floppy_3_dsqd::setup_characteristics() { - var_count = 0; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::DSDD; + m_form_factor = floppy_image::FF_3; + m_tracks = 84; + m_sides = 2; + set_rpm(300); + + add_variant(floppy_image::SSSD); + add_variant(floppy_image::DSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); + add_variant(floppy_image::DSQD); } //------------------------------------------------- @@ -1568,17 +1858,13 @@ floppy_35_ssdd::~floppy_35_ssdd() void floppy_35_ssdd::setup_characteristics() { - form_factor = floppy_image::FF_35; - tracks = 84; - sides = 1; + m_form_factor = floppy_image::FF_35; + m_tracks = 84; + m_sides = 1; set_rpm(300); -} -void floppy_35_ssdd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); } //------------------------------------------------- @@ -1596,18 +1882,14 @@ floppy_35_dd::~floppy_35_dd() void floppy_35_dd::setup_characteristics() { - form_factor = floppy_image::FF_35; - tracks = 84; - sides = 2; + m_form_factor = floppy_image::FF_35; + m_tracks = 84; + m_sides = 2; set_rpm(300); -} -void floppy_35_dd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::DSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); } //------------------------------------------------- @@ -1625,19 +1907,15 @@ floppy_35_hd::~floppy_35_hd() void floppy_35_hd::setup_characteristics() { - form_factor = floppy_image::FF_35; - tracks = 84; - sides = 2; + m_form_factor = floppy_image::FF_35; + m_tracks = 84; + m_sides = 2; set_rpm(300); -} -void floppy_35_hd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::DSDD; - variants[var_count++] = floppy_image::DSHD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); + add_variant(floppy_image::DSHD); } //------------------------------------------------- @@ -1655,20 +1933,16 @@ floppy_35_ed::~floppy_35_ed() void floppy_35_ed::setup_characteristics() { - form_factor = floppy_image::FF_35; - tracks = 84; - sides = 2; + m_form_factor = floppy_image::FF_35; + m_tracks = 84; + m_sides = 2; set_rpm(300); -} -void floppy_35_ed::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::DSDD; - variants[var_count++] = floppy_image::DSHD; - variants[var_count++] = floppy_image::DSED; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); + add_variant(floppy_image::DSHD); + add_variant(floppy_image::DSED); } //------------------------------------------------- @@ -1686,16 +1960,12 @@ floppy_525_sssd_35t::~floppy_525_sssd_35t() void floppy_525_sssd_35t::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 35; - sides = 1; + m_form_factor = floppy_image::FF_525; + m_tracks = 35; + m_sides = 1; set_rpm(300); -} -void floppy_525_sssd_35t::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; + add_variant(floppy_image::SSSD); } //------------------------------------------------- @@ -1713,16 +1983,37 @@ floppy_525_sd_35t::~floppy_525_sd_35t() void floppy_525_sd_35t::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 35; - sides = 2; + m_form_factor = floppy_image::FF_525; + m_tracks = 35; + m_sides = 2; set_rpm(300); + + add_variant(floppy_image::SSSD); + add_variant(floppy_image::DSSD); } -void floppy_525_sd_35t::handled_variants(uint32_t *variants, int &var_count) const +//------------------------------------------------- +// 5.25" single-sided single density, VTECH edition +//------------------------------------------------- + +floppy_525_vtech::floppy_525_vtech(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + floppy_image_device(mconfig, FLOPPY_525_VTECH, tag, owner, clock) { - var_count = 0; - variants[var_count++] = floppy_image::SSSD; + m_amplifier_freakout_time = attotime::from_usec(64); +} + +floppy_525_vtech::~floppy_525_vtech() +{ +} + +void floppy_525_vtech::setup_characteristics() +{ + m_form_factor = floppy_image::FF_525; + m_tracks = 40; + m_sides = 1; + set_rpm(85); + + add_variant(floppy_image::SSSD); } //------------------------------------------------- @@ -1740,16 +2031,12 @@ floppy_525_sssd::~floppy_525_sssd() void floppy_525_sssd::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 42; - sides = 1; + m_form_factor = floppy_image::FF_525; + m_tracks = 42; + m_sides = 1; set_rpm(300); -} -void floppy_525_sssd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; + add_variant(floppy_image::SSSD); } //------------------------------------------------- @@ -1767,16 +2054,12 @@ floppy_525_sd::~floppy_525_sd() void floppy_525_sd::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 42; - sides = 2; + m_form_factor = floppy_image::FF_525; + m_tracks = 42; + m_sides = 2; set_rpm(300); -} -void floppy_525_sd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; + add_variant(floppy_image::SSSD); } //------------------------------------------------- @@ -1794,17 +2077,13 @@ floppy_525_ssdd::~floppy_525_ssdd() void floppy_525_ssdd::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 42; - sides = 1; + m_form_factor = floppy_image::FF_525; + m_tracks = 42; + m_sides = 1; set_rpm(300); -} -void floppy_525_ssdd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); } //------------------------------------------------- @@ -1822,18 +2101,14 @@ floppy_525_dd::~floppy_525_dd() void floppy_525_dd::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 42; - sides = 2; + m_form_factor = floppy_image::FF_525; + m_tracks = 42; + m_sides = 2; set_rpm(300); -} -void floppy_525_dd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::DSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); } //------------------------------------------------- @@ -1851,18 +2126,14 @@ floppy_525_ssqd::~floppy_525_ssqd() void floppy_525_ssqd::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 84; - sides = 1; + m_form_factor = floppy_image::FF_525; + m_tracks = 84; + m_sides = 1; set_rpm(300); -} -void floppy_525_ssqd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::SSQD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::SSQD); } //------------------------------------------------- @@ -1880,21 +2151,17 @@ floppy_525_qd::~floppy_525_qd() void floppy_525_qd::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 84; - sides = 2; + m_form_factor = floppy_image::FF_525; + m_tracks = 84; + m_sides = 2; set_rpm(300); -} -void floppy_525_qd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::SSQD; - variants[var_count++] = floppy_image::DSSD; - variants[var_count++] = floppy_image::DSDD; - variants[var_count++] = floppy_image::DSQD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::SSQD); + add_variant(floppy_image::DSSD); + add_variant(floppy_image::DSDD); + add_variant(floppy_image::DSQD); } //------------------------------------------------- @@ -1912,21 +2179,17 @@ floppy_525_hd::~floppy_525_hd() void floppy_525_hd::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 84; - sides = 2; + m_form_factor = floppy_image::FF_525; + m_tracks = 84; + m_sides = 2; set_rpm(360); -} -void floppy_525_hd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::SSQD; - variants[var_count++] = floppy_image::DSDD; - variants[var_count++] = floppy_image::DSQD; - variants[var_count++] = floppy_image::DSHD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::SSQD); + add_variant(floppy_image::DSDD); + add_variant(floppy_image::DSQD); + add_variant(floppy_image::DSHD); } //------------------------------------------------- @@ -1944,17 +2207,13 @@ floppy_8_sssd::~floppy_8_sssd() void floppy_8_sssd::setup_characteristics() { - form_factor = floppy_image::FF_8; - tracks = 77; - sides = 1; - motor_always_on = true; + m_form_factor = floppy_image::FF_8; + m_tracks = 77; + m_sides = 1; + m_motor_always_on = true; set_rpm(360); -} -void floppy_8_sssd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; + add_variant(floppy_image::SSSD); } //------------------------------------------------- @@ -1972,18 +2231,14 @@ floppy_8_dssd::~floppy_8_dssd() void floppy_8_dssd::setup_characteristics() { - form_factor = floppy_image::FF_8; - tracks = 77; - sides = 2; - motor_always_on = true; + m_form_factor = floppy_image::FF_8; + m_tracks = 77; + m_sides = 2; + m_motor_always_on = true; set_rpm(360); -} -void floppy_8_dssd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::DSSD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::DSSD); } //------------------------------------------------- @@ -2001,18 +2256,14 @@ floppy_8_ssdd::~floppy_8_ssdd() void floppy_8_ssdd::setup_characteristics() { - form_factor = floppy_image::FF_8; - tracks = 77; - sides = 1; - motor_always_on = true; + m_form_factor = floppy_image::FF_8; + m_tracks = 77; + m_sides = 1; + m_motor_always_on = true; set_rpm(360); -} -void floppy_8_ssdd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); } //------------------------------------------------- @@ -2030,19 +2281,15 @@ floppy_8_dsdd::~floppy_8_dsdd() void floppy_8_dsdd::setup_characteristics() { - form_factor = floppy_image::FF_8; - tracks = 77; - sides = 2; - motor_always_on = true; + m_form_factor = floppy_image::FF_8; + m_tracks = 77; + m_sides = 2; + m_motor_always_on = true; set_rpm(360); -} -void floppy_8_dsdd::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::DSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); } @@ -2071,17 +2318,13 @@ epson_smd_165::~epson_smd_165() void epson_smd_165::setup_characteristics() { - form_factor = floppy_image::FF_35; - tracks = 40; - sides = 2; + m_form_factor = floppy_image::FF_35; + m_tracks = 40; + m_sides = 2; set_rpm(300); -} -void epson_smd_165::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::DSSD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::DSSD); } //------------------------------------------------- @@ -2122,18 +2365,14 @@ epson_sd_320::~epson_sd_320() void epson_sd_320::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 40; - sides = 2; + m_form_factor = floppy_image::FF_525; + m_tracks = 40; + m_sides = 2; set_rpm(300); -} -void epson_sd_320::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::DSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); } //------------------------------------------------- @@ -2154,18 +2393,47 @@ epson_sd_321::~epson_sd_321() void epson_sd_321::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 40; - sides = 2; + m_form_factor = floppy_image::FF_525; + m_tracks = 40; + m_sides = 2; set_rpm(300); + + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); +} + + +//------------------------------------------------- +// 3.5" Panasonic Flexible Disk Drive JU-363 +// +// track to track: 3 ms +// settling time: 15 ms +// motor start time: 500 ms +// transfer rate: 250 Kbits/s +// +//------------------------------------------------- + +pana_ju_363::pana_ju_363(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + floppy_image_device(mconfig, PANA_JU_363, tag, owner, clock) +{ +} + +pana_ju_363::~pana_ju_363() +{ } -void epson_sd_321::handled_variants(uint32_t *variants, int &var_count) const +void pana_ju_363::setup_characteristics() { - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::DSDD; + m_form_factor = floppy_image::FF_35; + m_tracks = 84; + m_sides = 2; + m_dskchg_writable = true; + set_rpm(300); + + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); } //------------------------------------------------- @@ -2189,18 +2457,14 @@ sony_oa_d31v::~sony_oa_d31v() void sony_oa_d31v::setup_characteristics() { - form_factor = floppy_image::FF_35; - tracks = 70; - sides = 1; - dskchg_writable = true; + m_form_factor = floppy_image::FF_35; + m_tracks = 70; + m_sides = 1; + m_dskchg_writable = true; set_rpm(600); -} -void sony_oa_d31v::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); } //------------------------------------------------- @@ -2225,19 +2489,15 @@ sony_oa_d32w::~sony_oa_d32w() void sony_oa_d32w::setup_characteristics() { - form_factor = floppy_image::FF_35; - tracks = 80; - sides = 2; - dskchg_writable = true; + m_form_factor = floppy_image::FF_35; + m_tracks = 80; + m_sides = 2; + m_dskchg_writable = true; set_rpm(600); -} -void sony_oa_d32w::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::DSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); } //------------------------------------------------- @@ -2262,18 +2522,14 @@ sony_oa_d32v::~sony_oa_d32v() void sony_oa_d32v::setup_characteristics() { - form_factor = floppy_image::FF_35; - tracks = 80; - sides = 1; - dskchg_writable = true; + m_form_factor = floppy_image::FF_35; + m_tracks = 80; + m_sides = 1; + m_dskchg_writable = true; set_rpm(600); -} -void sony_oa_d32v::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); } //------------------------------------------------- @@ -2297,16 +2553,74 @@ teac_fd_30a::~teac_fd_30a() void teac_fd_30a::setup_characteristics() { - form_factor = floppy_image::FF_3; - tracks = 40; - sides = 1; + m_form_factor = floppy_image::FF_3; + m_tracks = 40; + m_sides = 1; set_rpm(300); + + add_variant(floppy_image::SSDD); } -void teac_fd_30a::handled_variants(uint32_t *variants, int &var_count) const +//------------------------------------------------- +// TEAC FD-55A +// +// track to track: 6 ms +// average: 93 ms +// setting time: 15 ms +// motor start time: 400 ms +// +//------------------------------------------------- + +teac_fd_55a::teac_fd_55a(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : floppy_image_device(mconfig, TEAC_FD_55A, tag, owner, clock) { - var_count = 0; - variants[var_count++] = floppy_image::SSSD; +} + +teac_fd_55a::~teac_fd_55a() +{ +} + +void teac_fd_55a::setup_characteristics() +{ + m_form_factor = floppy_image::FF_525; + m_tracks = 40; + m_sides = 1; + set_rpm(300); + + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); +} + +//------------------------------------------------- +// TEAC FD-55B +// +// track to track: 6 ms +// average: 93 ms +// setting time: 15 ms +// motor start time: 400 ms +// +//------------------------------------------------- + +teac_fd_55b::teac_fd_55b(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : floppy_image_device(mconfig, TEAC_FD_55B, tag, owner, clock) +{ +} + +teac_fd_55b::~teac_fd_55b() +{ +} + +void teac_fd_55b::setup_characteristics() +{ + m_form_factor = floppy_image::FF_525; + m_tracks = 40; + m_sides = 2; + set_rpm(300); + + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSSD); + add_variant(floppy_image::DSDD); } //------------------------------------------------- @@ -2330,18 +2644,14 @@ teac_fd_55e::~teac_fd_55e() void teac_fd_55e::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 80; - sides = 1; + m_form_factor = floppy_image::FF_525; + m_tracks = 80; + m_sides = 1; set_rpm(300); -} -void teac_fd_55e::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::SSQD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::SSQD); } //------------------------------------------------- @@ -2365,21 +2675,17 @@ teac_fd_55f::~teac_fd_55f() void teac_fd_55f::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 80; - sides = 2; + m_form_factor = floppy_image::FF_525; + m_tracks = 80; + m_sides = 2; set_rpm(300); -} -void teac_fd_55f::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::SSQD; - variants[var_count++] = floppy_image::DSSD; - variants[var_count++] = floppy_image::DSDD; - variants[var_count++] = floppy_image::DSQD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::SSQD); + add_variant(floppy_image::DSSD); + add_variant(floppy_image::DSDD); + add_variant(floppy_image::DSQD); } //------------------------------------------------- @@ -2403,21 +2709,17 @@ teac_fd_55g::~teac_fd_55g() void teac_fd_55g::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 77; - sides = 2; + m_form_factor = floppy_image::FF_525; + m_tracks = 77; + m_sides = 2; set_rpm(360); -} -void teac_fd_55g::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; - variants[var_count++] = floppy_image::SSDD; - variants[var_count++] = floppy_image::SSQD; - variants[var_count++] = floppy_image::DSDD; - variants[var_count++] = floppy_image::DSQD; - variants[var_count++] = floppy_image::DSHD; + add_variant(floppy_image::SSSD); + add_variant(floppy_image::SSDD); + add_variant(floppy_image::SSQD); + add_variant(floppy_image::DSDD); + add_variant(floppy_image::DSQD); + add_variant(floppy_image::DSHD); } //------------------------------------------------- @@ -2437,17 +2739,13 @@ alps_3255190x::~alps_3255190x() void alps_3255190x::setup_characteristics() { - form_factor = floppy_image::FF_525; - tracks = 84; - sides = 1; + m_form_factor = floppy_image::FF_525; + m_tracks = 84; + m_sides = 1; set_rpm(300); - cyl = 34; -} + m_cyl = 34; -void alps_3255190x::handled_variants(uint32_t *variants, int &var_count) const -{ - var_count = 0; - variants[var_count++] = floppy_image::SSSD; + add_variant(floppy_image::SSSD); } //------------------------------------------------- @@ -2465,16 +2763,314 @@ ibm_6360::~ibm_6360() void ibm_6360::setup_characteristics() { - form_factor = floppy_image::FF_8; - tracks = 77; - sides = 1; - motor_always_on = true; - has_trk00_sensor = false; + m_form_factor = floppy_image::FF_8; + m_tracks = 77; + m_sides = 1; + m_motor_always_on = true; + m_has_trk00_sensor = false; set_rpm(360); + + add_variant(floppy_image::SSSD); +} + + +//------------------------------------------------- +// Variable-speed Macintosh drives +//------------------------------------------------- + +mac_floppy_device::mac_floppy_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : floppy_image_device(mconfig, type, tag, owner, clock) +{ + m_has_mfm = false; + m_dskchg_writable = true; +} + +void mac_floppy_device::device_start() +{ + floppy_image_device::device_start(); + save_item(NAME(m_reg)); + save_item(NAME(m_strb)); } -void ibm_6360::handled_variants(uint32_t *variants, int &var_count) const +void mac_floppy_device::device_reset() { - var_count = 0; - variants[var_count++] = floppy_image::SSSD; + floppy_image_device::device_reset(); + m_reg = 0; + m_strb = 0; + m_mfm = m_has_mfm; +} + +// Initial state of bits f-c (2M, ready, MFM, rd1): +// 0000 - 400K GCR drive +// 0001 - 4MB Typhoon drive +// x011 - Superdrive (x depends on the HD hole of the inserted disk, if any) +// 1010 - 800K GCR drive +// 1110 - HD-20 drive +// 1111 - No drive (pull-up on the sense line) + +bool mac_floppy_device::writing_disabled() const +{ + return m_wpt; +} + +bool mac_floppy_device::wpt_r() +{ + static const char *const regnames[16] = { + "Dir", "Step", "Motor", "Eject", + "RdData0", "Superdrive", "DoubleSide", "NoDrive", + "NoDiskInPl", "NoWrProtect", "NotTrack0", "NoTachPulse", + "RdData1", "MFMModeOn", "NoReady", "HD" + }; + + // m_actual_ss may have changed after the m_phases were set + m_reg = (m_reg & 7) | (m_actual_ss ? 8 : 0); + + if(0 && (m_reg != 4 && m_reg != 12 && m_reg != 5 && m_reg != 13)) + logerror("fdc disk sense reg %x %s %p\n", m_reg, regnames[m_reg], m_image.get()); + + switch(m_reg) { + case 0x0: // Step direction + return m_dir; + + case 0x1: // Step signal + // We don't do the delay + return true; + + case 0x2: // Is the motor on? + return m_mon; + + case 0x3: // Disk change signal + return !m_dskchg; + + case 0x4: + case 0xc: // Index pulse, probably only in mfm mode and while writing though + return !m_has_mfm ? false : !m_image || m_mon ? true : !m_idx; + + case 0x5: // Is it a superdrive (supports 1.4M MFM) ? + return m_has_mfm; + + case 0x6: // Is the drive double-sided? + return m_sides == 2; + + case 0x7: // Does the drive exist? + return false; + + case 0x8: // Is there a disk in the drive? + return m_image.get() == nullptr; + + case 0x9: // Is the disk write-protected? + return !m_wpt; + + case 0xa: // Not on track 0? + return m_cyl != 0; + + case 0xb:{// Tachometer, 60 pulses/rotation + if(m_image.get() != nullptr && !m_mon) { + attotime base; + uint32_t pos = find_position(base, machine().time()); + uint32_t subpos = pos % 3333334; + return subpos < 20000; + } else + return false; + } + + case 0xd: // Is the current mode GCR or MFM? + return m_mfm; + + case 0xe: // Is the floppy ready? + return m_ready; + + case 0xf: // Does it implement the new interface *or* is the current disk is 1.4M MFM (superdrive only) + return is_2m(); + + default: + return false; + } +} + +void mac_floppy_device::seek_phase_w(int phases) +{ + static const char *const regnames[16] = { + "DirNext", "StepOn", "MotorOn", "EjectOff", + "DirPrev", "StepOff", "MotorOff", "EjectOn", + "-", "MFMModeOn", "-", "-", + "DskchgClear", "GCRModeOn", "-", "-" + }; + + bool prev_strb = m_strb; + + m_reg = (phases & 7) | (m_actual_ss ? 8 : 0); + m_strb = (phases >> 3) & 1; + + if(m_strb && !prev_strb) { + switch(m_reg) { + case 0x0: // Step to cylinder + 1 + logerror("cmd step dir +1\n"); + dir_w(0); + break; + + case 0x1: // Step on + logerror("cmd step on\n"); + stp_w(0); + // There should be a delay, but it's not necessary + stp_w(1); + break; + + case 0x2: // Motor on + logerror("cmd motor on\n"); + floppy_image_device::mon_w(0); + break; + + case 0x3: // End eject + logerror("cmd end eject\n"); + break; + + case 0x4: // Step to cylinder - 1 + logerror("cmd step dir -1\n"); + dir_w(1); + break; + + case 0x6: // Motor off + logerror("cmd motor off\n"); + floppy_image_device::mon_w(1); + break; + + case 0x7: // Start eject + logerror("cmd start eject\n"); + unload(); + break; + + case 0x9: // MFM mode on + logerror("cmd mfm on\n"); + if(m_has_mfm) { + m_mfm = true; + track_changed(); + } + break; + + case 0xc: // Clear m_dskchg + logerror("cmd clear m_dskchg\n"); + m_dskchg = 1; + break; + + case 0xd: // GCR mode on + logerror("cmd gcr on\n"); + m_mfm = false; + track_changed(); + break; + + default: + logerror("cmd reg %x %s\n", m_reg, regnames[m_reg]); + break; + } + } +} + +void mac_floppy_device::track_changed() +{ + floppy_image_device::track_changed(); + + float new_rpm; + if(m_mfm) + new_rpm = is_2m() ? 600 : 300; + else if(m_cyl <= 15) + new_rpm = 394; + else if(m_cyl <= 31) + new_rpm = 429; + else if(m_cyl <= 47) + new_rpm = 472; + else if(m_cyl <= 63) + new_rpm = 525; + else + new_rpm = 590; + + if(m_rpm != new_rpm) + set_rpm(new_rpm); +} + +void mac_floppy_device::mon_w(int) +{ + // Motor control is through commands +} + +void mac_floppy_device::tfsel_w(int state) +{ + // if 35SEL line is clear and the motor is on, turn off the motor + if ((state == CLEAR_LINE) && (!floppy_image_device::mon_r())) + { + floppy_image_device::mon_w(1); + } +} + +oa_d34v_device::oa_d34v_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : mac_floppy_device(mconfig, OAD34V, tag, owner, clock) +{ +} + +void oa_d34v_device::setup_characteristics() +{ + m_form_factor = floppy_image::FF_35; + m_tracks = 80; + m_sides = 1; + set_rpm(394); + + add_variant(floppy_image::SSDD); +} + +bool oa_d34v_device::is_2m() const +{ + return false; +} + +void oa_d34v_device::track_changed() +{ + // Skip the m_rpm-setting mac generic version, the single-sided + // drive's m_rpm is externally controlled through a PWM signal. + + floppy_image_device::track_changed(); +} + +mfd51w_device::mfd51w_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : mac_floppy_device(mconfig, MFD51W, tag, owner, clock) +{ +} +void mfd51w_device::setup_characteristics() +{ + m_form_factor = floppy_image::FF_35; + m_tracks = 80; + m_sides = 2; + set_rpm(394); + + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); +} + +bool mfd51w_device::is_2m() const +{ + return true; +} + +mfd75w_device::mfd75w_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : mac_floppy_device(mconfig, MFD75W, tag, owner, clock) +{ + m_has_mfm = true; +} + +void mfd75w_device::setup_characteristics() +{ + m_form_factor = floppy_image::FF_35; + m_tracks = 80; + m_sides = 2; + set_rpm(300); + + add_variant(floppy_image::SSDD); + add_variant(floppy_image::DSDD); + add_variant(floppy_image::DSHD); +} + +bool mfd75w_device::is_2m() const +{ + if(!m_image) + return false; + + if(m_image->get_variant() == floppy_image::SSDD || m_image->get_variant() == floppy_image::DSDD) + return true; + + return false; } |