summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/imagedev/floppy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/imagedev/floppy.cpp')
-rw-r--r--src/devices/imagedev/floppy.cpp273
1 files changed, 243 insertions, 30 deletions
diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp
index 738412f5530..7d34bfe675c 100644
--- a/src/devices/imagedev/floppy.cpp
+++ b/src/devices/imagedev/floppy.cpp
@@ -19,10 +19,12 @@
#include "formats/cqm_dsk.h"
#include "formats/dsk_dsk.h"
#include "formats/pc_dsk.h"
+#include "formats/ipf_dsk.h"
#include "formats/fs_unformatted.h"
#include "formats/fsblk_vec.h"
+#include "screen.h"
#include "speaker.h"
#include "formats/imageutl.h"
#include "zippath.h"
@@ -37,6 +39,8 @@
#define PITCH_SEEK_SAMPLES 1
+#define FLUX_SCREEN 0
+
#define FLOPSND_TAG "floppysound"
// device type definition
@@ -55,6 +59,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")
@@ -168,6 +173,7 @@ void format_registration::add_pc_formats()
add_mfm_containers();
add(FLOPPY_PC_FORMAT);
+ add(FLOPPY_IPF_FORMAT);
}
void format_registration::add(floppy_format_type format)
@@ -175,9 +181,9 @@ void format_registration::add(floppy_format_type format)
m_formats.push_back(format);
}
-void format_registration::add(filesystem_manager_type fs)
+void format_registration::add(const filesystem_manager_t &fs)
{
- m_fs.push_back(fs);
+ m_fs.push_back(&fs);
}
void floppy_image_device::default_fm_floppy_formats(format_registration &fr)
@@ -241,7 +247,6 @@ floppy_image_device::floppy_image_device(const machine_config &mconfig, device_t
input_format(nullptr),
output_format(nullptr),
image(),
- fif_list(nullptr),
index_timer(nullptr),
tracks(0),
sides(0),
@@ -256,10 +261,13 @@ floppy_image_device::floppy_image_device(const machine_config &mconfig, device_t
revolution_count(0),
cyl(0),
subcyl(0),
+ amplifier_freakout_time(attotime::from_usec(16)),
image_dirty(false),
+ track_dirty(false),
ready_counter(0),
m_make_sound(false),
- m_sound_out(nullptr)
+ m_sound_out(nullptr),
+ m_flux_screen(*this, "flux")
{
extension_list[0] = '\0';
m_err = IMAGE_ERROR_INVALIDIMAGE;
@@ -271,12 +279,8 @@ 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;
+ for(floppy_image_format_t *format : fif_list)
+ delete format;
}
void floppy_image_device::setup_load_cb(load_cb cb)
@@ -309,12 +313,12 @@ void floppy_image_device::setup_led_cb(led_cb cb)
cur_led_cb = cb;
}
-void floppy_image_device::fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description)
+void floppy_image_device::fs_enum::add(floppy_format_type type, u32 image_size, const char *name, const char *description)
{
- if(manager->can_format())
- m_fid->m_create_fs.emplace_back(fs_info(manager, type, image_size, name, description));
- if(manager->can_read())
- m_fid->m_io_fs.emplace_back(fs_info(manager, type, image_size, name, description));
+ if(m_manager->can_format())
+ m_fid->m_create_fs.emplace_back(fs_info(m_manager, type, image_size, name, description));
+ if(m_manager->can_read())
+ m_fid->m_io_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)
@@ -329,27 +333,23 @@ void floppy_image_device::register_formats()
format_registration_cb(fr);
extension_list[0] = '\0';
- fif_list = nullptr;
+ fif_list.clear();
for(floppy_format_type fft : fr.m_formats)
{
// allocate a new format
floppy_image_format_t *fif = fft();
- if(!fif_list)
- fif_list = fif;
- else
- fif_list->append(fif);
-
+ fif_list.push_back(fif);
add_format(fif->name(), fif->description(), fif->extensions(), "");
image_specify_extension( extension_list, 256, fif->extensions() );
}
fs_enum fse(this);
- for(filesystem_manager_type fmt : fr.m_fs)
+ for(const filesystem_manager_t *fmt : fr.m_fs)
{
- auto ff = fmt();
- ff->enumerate_f(fse, form_factor, variants);
- m_fs_managers.push_back(std::unique_ptr<filesystem_manager_t>(ff));
+ fse.m_manager = fmt;
+ fmt->enumerate_f(fse, form_factor, variants);
+ m_fs_managers.push_back(fmt);
}
}
@@ -358,7 +358,7 @@ void floppy_image_device::set_formats(std::function<void (format_registration &f
format_registration_cb = formats;
}
-floppy_image_format_t *floppy_image_device::get_formats() const
+const std::vector<floppy_image_format_t *> &floppy_image_device::get_formats() const
{
return fif_list;
}
@@ -387,6 +387,11 @@ void floppy_image_device::setup_write(floppy_image_format_t *_output_format)
void floppy_image_device::commit_image()
{
+ if(FLUX_SCREEN && track_dirty) {
+ flux_image_compute_for_track(((cyl << 2) | subcyl) >> (2 - image->get_resolution()), ss);
+ track_dirty = false;
+ }
+
image_dirty = false;
if(!output_format || !output_format->supports_save())
return;
@@ -473,6 +478,29 @@ void floppy_image_device::device_start()
save_item(NAME(image_dirty));
save_item(NAME(ready_counter));
save_item(NAME(phases));
+
+ if(FLUX_SCREEN) {
+ m_flux_per_pixel_infos.resize(flux_screen_sx*flux_screen_sy);
+ flux_per_pixel_info *ppi = m_flux_per_pixel_infos.data();
+ for(int y = 0; y != flux_screen_sy; y++) {
+ int head = y >= flux_screen_sy / 2 ? 1 : 0;
+ int yc = (flux_screen_sy/2-1)/2 + (flux_screen_sy/2)*head;
+ int dy = y - yc;
+ for(int x = 0; x != flux_screen_sx; x++) {
+ const int xc = (flux_screen_sx - 1)/2;
+ int dx = x - xc;
+ int r = int(sqrt(dx*dx + dy*dy) + 0.5);
+ ppi->m_r = r;
+ if(r > flux_max_r || r < flux_min_r)
+ ppi->m_position = 0xffffffff;
+ else
+ ppi->m_position = int((200e6 / 2 / M_PI) * atan2(dy, dx) + 100000000.5) % 200000000;
+ ppi->m_combined_track = 0;
+ ppi->m_color = 0;
+ ppi ++;
+ }
+ }
+ }
}
void floppy_image_device::device_reset()
@@ -514,7 +542,7 @@ floppy_image_format_t *floppy_image_device::identify(std::string filename)
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)
+ for (floppy_image_format_t *format : fif_list)
{
int score = format->identify(&io, form_factor, variants);
if(score > best) {
@@ -562,7 +590,7 @@ image_init_result floppy_image_device::call_load()
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) {
+ for (floppy_image_format_t *format : fif_list) {
int score = format->identify(&io, form_factor, variants);
if(score > best) {
best = score;
@@ -590,9 +618,147 @@ image_init_result floppy_image_device::call_load()
if (!cur_load_cb.isnull())
return cur_load_cb(this);
+ flux_image_prepare();
+
return image_init_result::PASS;
}
+void floppy_image_device::flux_image_prepare()
+{
+ if(!FLUX_SCREEN)
+ return;
+
+ int tracks = 0, heads = 0, rez = 0;
+ image->get_maximal_geometry(tracks, heads);
+ rez = image->get_resolution();
+
+ int trackm = (tracks - 1) << rez;
+ int tmask = (1 << rez) - 1;
+
+ m_flux_per_combined_track_infos.clear();
+ m_flux_per_combined_track_infos.resize(trackm+1);
+ for(int track = 0; track <= trackm; track++) {
+ int refr = 200 + (trackm - 0.5 - track) * 290 / (trackm+1) + 200;
+ int span = int((200e6 / 2 / M_PI) / refr);
+ m_flux_per_combined_track_infos[track].m_span = span;
+ m_flux_per_combined_track_infos[track].m_track = track >> rez;
+ m_flux_per_combined_track_infos[track].m_subtrack = track & tmask;
+ }
+
+ flux_per_pixel_info *ppi = m_flux_per_pixel_infos.data();
+ for(int head = 0; head != heads; head++)
+ for(unsigned int i=0; i != flux_screen_sx*flux_screen_sy/2; i++) {
+ if(ppi->m_position != 0xffffffff) {
+ int trk = (trackm + 1) * (flux_max_r - ppi->m_r) / (flux_max_r - flux_min_r + 1);
+ ppi->m_combined_track = trk;
+ m_flux_per_combined_track_infos[trk].m_pixels[head].push_back(ppi);
+ }
+ ppi++;
+ }
+
+ for(auto &t : m_flux_per_combined_track_infos) {
+ std::sort(t.m_pixels[0].begin(), t.m_pixels[0].end(), [](const flux_per_pixel_info *a, const flux_per_pixel_info *b) -> bool { return a->m_position < b->m_position; });
+ if(heads == 2)
+ std::sort(t.m_pixels[1].begin(), t.m_pixels[1].end(), [](const flux_per_pixel_info *a, const flux_per_pixel_info *b) -> bool { return a->m_position < b->m_position; });
+ }
+
+ for(int head = 0; head != heads; head++)
+ for(int track = 0; track <= trackm; track++)
+ flux_image_compute_for_track(track, head);
+}
+
+void floppy_image_device::flux_image_compute_for_track(int track, int head)
+{
+ auto *pcti = m_flux_per_combined_track_infos.data() + track;
+ const std::vector<uint32_t> &buffer = image->get_buffer(pcti->m_track, head, pcti->m_subtrack);
+ int sz = buffer.size();
+ if(!sz) {
+ for(flux_per_pixel_info *p : m_flux_per_combined_track_infos[track].m_pixels[head])
+ p->m_color = 255;
+ return;
+ }
+
+ int spos = pcti->m_pixels[head][0]->m_position - pcti->m_span + 200000000;
+ int bpos = sz;
+ while(bpos && (buffer[bpos-1] & floppy_image::TIME_MASK) < spos)
+ bpos --;
+ if(bpos == sz)
+ bpos = 0;
+
+ int pspos = spos;
+ for(flux_per_pixel_info *p : m_flux_per_combined_track_infos[track].m_pixels[head]) {
+ int spos = p->m_position - pcti->m_span;
+ int epos = p->m_position + pcti->m_span;
+ if(spos < 0)
+ spos += 200000000;
+ if(epos >= 200000000)
+ epos -= 200000000;
+
+ if(spos < pspos)
+ bpos = 0;
+ while(bpos != sz-1 && (buffer[bpos+1] & floppy_image::TIME_MASK) < spos)
+ bpos ++;
+
+ int bpos2 = spos < epos ? bpos : 0;
+ while(bpos2 != sz-1 && (buffer[bpos2+1] & floppy_image::TIME_MASK) < epos)
+ bpos2 ++;
+
+ int count;
+ if(bpos <= bpos2)
+ count = bpos2 - bpos;
+ else {
+ count = (sz - 1 - bpos) + bpos2;
+ if((buffer[0] ^ buffer[sz-1]) & floppy_image::MG_MASK)
+ count ++;
+ }
+
+ count *= 5;
+ if(count > 255)
+ count = 255;
+ p->m_color = 255 - count;
+ pspos = spos;
+ }
+}
+
+uint32_t floppy_image_device::flux_screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ if(image.get()) {
+ int ctrack = ((cyl << 2) | subcyl) >> (2 - image->get_resolution());
+ if(mon)
+ ctrack = -1;
+ for(int y = cliprect.min_y; y <= cliprect.max_y; y++) {
+ int head = y >= flux_screen_sy / 2;
+ flux_per_pixel_info *ppi = m_flux_per_pixel_infos.data() + y * flux_screen_sx + cliprect.min_x;
+ uint32_t *p = &bitmap.pix(y, cliprect.min_x);
+ for(int x = cliprect.min_x; x <= cliprect.max_x; x++) {
+ if(ppi->m_position == 0xffffffff)
+ *p++ = 0;
+ else {
+ u32 color = 0x010101 * ppi->m_color;
+ if(ppi->m_combined_track == ctrack && head == ss)
+ color &= 0x0000ff;
+ *p++ = color;
+ }
+ ppi++;
+ }
+ }
+ } else {
+ for(int y = cliprect.min_y; y <= cliprect.max_y; y++) {
+ flux_per_pixel_info *ppi = m_flux_per_pixel_infos.data() + y * flux_screen_sx + cliprect.min_x;
+ uint32_t *p = &bitmap.pix(y, cliprect.min_x);
+ for(int x = cliprect.min_x; x <= cliprect.max_x; x++) {
+ if(ppi->m_position == 0xffffffff)
+ *p++ = 0;
+ else
+ *p++ = 0x404040;
+ ppi++;
+ }
+ }
+ }
+
+ return 0;
+}
+
void floppy_image_device::call_unload()
{
cache_clear();
@@ -629,7 +795,7 @@ image_init_result floppy_image_device::call_create(int format_type, util::option
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(floppy_image_format_t *i : fif_list)
{
// only consider formats that actually support saving
if(!i->supports_save())
@@ -648,6 +814,8 @@ image_init_result floppy_image_device::call_create(int format_type, util::option
init_floppy_load(true);
+ flux_image_prepare();
+
return image_init_result::PASS;
}
@@ -881,6 +1049,11 @@ void floppy_image_device::stp_w(int state)
cache_clear();
stp = state;
if ( stp == 0 ) {
+ if(FLUX_SCREEN && track_dirty) {
+ flux_image_compute_for_track(((cyl << 2) | subcyl) >> (2 - image->get_resolution()), ss);
+ track_dirty = false;
+ }
+
int ocyl = cyl;
if ( dir ) {
if ( cyl ) cyl--;
@@ -936,6 +1109,12 @@ void floppy_image_device::seek_phase_w(int _phases)
next_pos = 0;
else if(next_pos > (tracks-1)*4)
next_pos = (tracks-1)*4;
+
+ if(FLUX_SCREEN && track_dirty) {
+ flux_image_compute_for_track(((cyl << 2) | subcyl) >> (2 - image->get_resolution()), ss);
+ track_dirty = false;
+ }
+
cyl = next_pos >> 2;
subcyl = next_pos & 3;
@@ -1094,7 +1273,7 @@ void floppy_image_device::cache_weakness_setup()
return;
}
- cache_weak = cache_end_time.is_never() || (cache_end_time - cache_start_time >= attotime::from_usec(16));
+ cache_weak = cache_end_time.is_never() || (cache_end_time - cache_start_time >= amplifier_freakout_time);
if(!cache_weak) {
cache_weak_start = attotime::never;
return;
@@ -1145,6 +1324,7 @@ void floppy_image_device::write_flux(const attotime &start, const attotime &end,
return;
image_dirty = true;
+ track_dirty = true;
cache_clear();
attotime base;
@@ -1704,6 +1884,14 @@ void floppy_image_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, FLOPSPK).front_center();
FLOPPYSOUND(config, FLOPSND_TAG, 44100).add_route(ALL_OUTPUTS, FLOPSPK, 0.5);
+
+ if (FLUX_SCREEN)
+ {
+ SCREEN(config, m_flux_screen, SCREEN_TYPE_RASTER);
+ m_flux_screen->set_screen_update(FUNC(floppy_image_device::flux_screen_update));
+ m_flux_screen->set_raw(30*(flux_screen_sx+1)*(flux_screen_sy+1), flux_screen_sx+1, 0, flux_screen_sx, flux_screen_sy+1, 0, flux_screen_sy);
+ m_flux_screen->set_physical_aspect(1, 2);
+ }
}
@@ -1907,6 +2095,31 @@ void floppy_525_sd_35t::setup_characteristics()
set_rpm(300);
variants.push_back(floppy_image::SSSD);
+ variants.push_back(floppy_image::DSSD);
+}
+
+//-------------------------------------------------
+// 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)
+{
+ amplifier_freakout_time = attotime::from_usec(64);
+}
+
+floppy_525_vtech::~floppy_525_vtech()
+{
+}
+
+void floppy_525_vtech::setup_characteristics()
+{
+ form_factor = floppy_image::FF_525;
+ tracks = 40;
+ sides = 1;
+ set_rpm(85);
+
+ variants.push_back(floppy_image::SSSD);
}
//-------------------------------------------------