1 // license:BSD-3-Clause
2 // copyright-holders:Nathan Woods, Olivier Galibert, Miodrag Milanovic
3 /*********************************************************************
4
5
6
7 *********************************************************************/
8
9 #include "emu.h"
10 #include "floppy.h"
11
12 #include "speaker.h"
13 #include "formats/imageutl.h"
14 #include "zippath.h"
15
16 /*
17 Debugging flags. Set to 0 or 1.
18 */
19
20 // Show step operation
21 #define TRACE_STEP 0
22 #define TRACE_AUDIO 0
23
24 #define PITCH_SEEK_SAMPLES 1
25
26 #define FLOPSND_TAG "floppysound"
27
28 // device type definition
29 DEFINE_DEVICE_TYPE(FLOPPY_CONNECTOR, floppy_connector, "floppy_connector", "Floppy drive connector abstraction")
30
31 // generic 3" drives
32 DEFINE_DEVICE_TYPE(FLOPPY_3_SSDD, floppy_3_ssdd, "floppy_3_ssdd", "3\" single-sided floppy drive")
33 DEFINE_DEVICE_TYPE(FLOPPY_3_DSDD, floppy_3_dsdd, "floppy_3_dsdd", "3\" double-sided floppy drive")
34
35 // generic 3.5" drives
36 DEFINE_DEVICE_TYPE(FLOPPY_35_SSDD, floppy_35_ssdd, "floppy_35_ssdd", "3.5\" single-sided double density floppy drive")
37 DEFINE_DEVICE_TYPE(FLOPPY_35_DD, floppy_35_dd, "floppy_35_dd", "3.5\" double density floppy drive")
38 DEFINE_DEVICE_TYPE(FLOPPY_35_HD, floppy_35_hd, "floppy_35_hd", "3.5\" high density floppy drive")
39 DEFINE_DEVICE_TYPE(FLOPPY_35_ED, floppy_35_ed, "floppy_35_ed", "3.5\" extended density floppy drive")
40
41 // generic 5.25" drives
42 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")
43 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")
44 DEFINE_DEVICE_TYPE(FLOPPY_525_SSSD, floppy_525_sssd, "floppy_525_sssd", "5.25\" single-sided single density floppy drive")
45 DEFINE_DEVICE_TYPE(FLOPPY_525_SD, floppy_525_sd, "floppy_525_sd", "5.25\" single density floppy drive")
46 DEFINE_DEVICE_TYPE(FLOPPY_525_SSDD, floppy_525_ssdd, "floppy_525_ssdd", "5.25\" single-sided double density floppy drive")
47 DEFINE_DEVICE_TYPE(FLOPPY_525_DD, floppy_525_dd, "floppy_525_dd", "5.25\" double density floppy drive")
48 DEFINE_DEVICE_TYPE(FLOPPY_525_SSQD, floppy_525_ssqd, "floppy_525_ssqd", "5.25\" single-sided quad density floppy drive")
49 DEFINE_DEVICE_TYPE(FLOPPY_525_QD, floppy_525_qd, "floppy_525_qd", "5.25\" quad density floppy drive")
50 DEFINE_DEVICE_TYPE(FLOPPY_525_HD, floppy_525_hd, "floppy_525_hd", "5.25\" high density floppy drive")
51
52 // generic 8" drives
53 DEFINE_DEVICE_TYPE(FLOPPY_8_SSSD, floppy_8_sssd, "floppy_8_sssd", "8\" single-sided single density floppy drive")
54 DEFINE_DEVICE_TYPE(FLOPPY_8_DSSD, floppy_8_dssd, "floppy_8_dssd", "8\" double-sided single density floppy drive")
55 DEFINE_DEVICE_TYPE(FLOPPY_8_SSDD, floppy_8_ssdd, "floppy_8_ssdd", "8\" single-sided double density floppy drive")
56 DEFINE_DEVICE_TYPE(FLOPPY_8_DSDD, floppy_8_dsdd, "floppy_8_dsdd", "8\" double-sided double density floppy drive")
57
58 // Epson 3.5" drives
59 #if 0
60 DEFINE_DEVICE_TYPE(EPSON_SMD_110, epson_smd_110, "epson_smd_110", "EPSON SMD-110 Floppy Disk Drive")
61 DEFINE_DEVICE_TYPE(EPSON_SMD_120, epson_smd_120, "epson_smd_120", "EPSON SMD-120 Floppy Disk Drive")
62 DEFINE_DEVICE_TYPE(EPSON_SMD_125, epson_smd_125, "epson_smd_125", "EPSON SMD-125 Floppy Disk Drive")
63 DEFINE_DEVICE_TYPE(EPSON_SMD_130, epson_smd_130, "epson_smd_130", "EPSON SMD-130 Floppy Disk Drive")
64 DEFINE_DEVICE_TYPE(EPSON_SMD_140, epson_smd_140, "epson_smd_140", "EPSON SMD-140 Floppy Disk Drive")
65 DEFINE_DEVICE_TYPE(EPSON_SMD_150, epson_smd_150, "epson_smd_150", "EPSON SMD-150 Floppy Disk Drive")
66 DEFINE_DEVICE_TYPE(EPSON_SMD_160, epson_smd_160, "epson_smd_160", "EPSON SMD-160 Floppy Disk Drive")
67 #endif
68 DEFINE_DEVICE_TYPE(EPSON_SMD_165, epson_smd_165, "epson_smd_165", "EPSON SMD-165 Floppy Disk Drive")
69 #if 0
70 DEFINE_DEVICE_TYPE(EPSON_SMD_170, epson_smd_170, "epson_smd_170", "EPSON SMD-170 Floppy Disk Drive")
71 DEFINE_DEVICE_TYPE(EPSON_SMD_180, epson_smd_180, "epson_smd_180", "EPSON SMD-180 Floppy Disk Drive")
72 DEFINE_DEVICE_TYPE(EPSON_SMD_240L, epson_smd_240l, "epson_smd_240l", "EPSON SMD-240L Floppy Disk Drive")
73 DEFINE_DEVICE_TYPE(EPSON_SMD_280HL, epson_smd_280hl, "epson_smd_280hl", "EPSON SMD-280HL Floppy Disk Drive")
74 DEFINE_DEVICE_TYPE(EPSON_SMD_440L, epson_smd_440l, "epson_smd_440l", "EPSON SMD-440L Floppy Disk Drive")
75 DEFINE_DEVICE_TYPE(EPSON_SMD_449L, epson_smd_449l, "epson_smd_449l", "EPSON SMD-449L Floppy Disk Drive")
76 DEFINE_DEVICE_TYPE(EPSON_SMD_480LM, epson_smd_480lm, "epson_smd_480lm", "EPSON SMD-480LM Floppy Disk Drive")
77 DEFINE_DEVICE_TYPE(EPSON_SMD_489M, epson_smd_489m, "epson_smd_489m", "EPSON SMD-489M Floppy Disk Drive")
78 #endif
79
80 // Epson 5.25" drives
81 #if 0
82 DEFINE_DEVICE_TYPE(EPSON_SD_311, epson_sd_311, "epson_sd_311", "EPSON SD-311 Mini-Floppy Disk Drive")
83 #endif
84 DEFINE_DEVICE_TYPE(EPSON_SD_320, epson_sd_320, "epson_sd_320", "EPSON SD-320 Mini-Floppy Disk Drive")
85 DEFINE_DEVICE_TYPE(EPSON_SD_321, epson_sd_321, "epson_sd_321", "EPSON SD-321 Mini-Floppy Disk Drive")
86 #if 0
87 DEFINE_DEVICE_TYPE(EPSON_SD_521L, epson_sd_531l, "epson_sd_531l", "EPSON SD-531L Mini-Floppy Disk Drive")
88 DEFINE_DEVICE_TYPE(EPSON_SD_525, epson_sd_525, "epson_sd_525", "EPSON SD-525 Mini-Floppy Disk Drive")
89 DEFINE_DEVICE_TYPE(EPSON_SD_543, epson_sd_543, "epson_sd_543", "EPSON SD-543 Mini-Floppy Disk Drive")
90 DEFINE_DEVICE_TYPE(EPSON_SD_545, epson_sd_545, "epson_sd_545", "EPSON SD-545 Mini-Floppy Disk Drive")
91 DEFINE_DEVICE_TYPE(EPSON_SD_560, epson_sd_560, "epson_sd_560", "EPSON SD-560 Mini-Floppy Disk Drive")
92 DEFINE_DEVICE_TYPE(EPSON_SD_580L, epson_sd_580l, "epson_sd_580l", "EPSON SD-580L Mini-Floppy Disk Drive")
93 DEFINE_DEVICE_TYPE(EPSON_SD_581L, epson_sd_581l, "epson_sd_581l", "EPSON SD-581L Mini-Floppy Disk Drive")
94 DEFINE_DEVICE_TYPE(EPSON_SD_621L, epson_sd_621l, "epson_sd_621l", "EPSON SD-621L Mini-Floppy Disk Drive")
95 DEFINE_DEVICE_TYPE(EPSON_SD_680L, epson_sd_680l, "epson_sd_680l", "EPSON SD-680L Mini-Floppy Disk Drive")
96 #endif
97
98 // Sony 3.5" drives
99 DEFINE_DEVICE_TYPE(SONY_OA_D31V, sony_oa_d31v, "sony_oa_d31v", "Sony OA-D31V Micro Floppydisk Drive")
100 DEFINE_DEVICE_TYPE(SONY_OA_D32W, sony_oa_d32w, "sony_oa_d32w", "Sony OA-D32W Micro Floppydisk Drive")
101 DEFINE_DEVICE_TYPE(SONY_OA_D32V, sony_oa_d32v, "sony_oa_d32v", "Sony OA-D32V Micro Floppydisk Drive")
102
103 // TEAC 3" drives
104 DEFINE_DEVICE_TYPE(TEAC_FD_30A, teac_fd_30a, "teac_fd_30a", "TEAC FD-30A FDD")
105
106 // TEAC 5.25" drives
107 #if 0
108 DEFINE_DEVICE_TYPE(TEAC_FD_55A, teac_fd_55a, "teac_fd_55a", "TEAC FD-55A FDD")
109 DEFINE_DEVICE_TYPE(TEAC_FD_55B, teac_fd_55b, "teac_fd_55b", "TEAC FD-55B FDD")
110 #endif
111 DEFINE_DEVICE_TYPE(TEAC_FD_55E, teac_fd_55e, "teac_fd_55e", "TEAC FD-55E FDD")
112 DEFINE_DEVICE_TYPE(TEAC_FD_55F, teac_fd_55f, "teac_fd_55f", "TEAC FD-55F FDD")
113 DEFINE_DEVICE_TYPE(TEAC_FD_55G, teac_fd_55g, "teac_fd_55g", "TEAC FD-55G FDD")
114
115 // ALPS 5.25" drives
116 DEFINE_DEVICE_TYPE(ALPS_3255190X, alps_3255190x, "alps_3255190x", "ALPS 32551901/32551902 Floppy Drive")
117
118 // IBM 8" drives
119 DEFINE_DEVICE_TYPE(IBM_6360, ibm_6360, "ibm_6360", "IBM 6360 8\" single-sided single density floppy drive")
120
121
122 const floppy_format_type floppy_image_device::default_floppy_formats[] = {
123 FLOPPY_D88_FORMAT,
124 FLOPPY_DFI_FORMAT,
125 FLOPPY_HFE_FORMAT,
126 FLOPPY_IMD_FORMAT,
127 FLOPPY_IPF_FORMAT,
128 FLOPPY_MFI_FORMAT,
129 FLOPPY_MFM_FORMAT,
130 FLOPPY_TD0_FORMAT,
131 FLOPPY_CQM_FORMAT,
132 FLOPPY_DSK_FORMAT,
133 nullptr
134 };
135
floppy_connector(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)136 floppy_connector::floppy_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
137 device_t(mconfig, FLOPPY_CONNECTOR, tag, owner, clock),
138 device_slot_interface(mconfig, *this),
139 formats(nullptr),
140 m_enable_sound(false)
141 {
142 }
143
~floppy_connector()144 floppy_connector::~floppy_connector()
145 {
146 }
147
set_formats(const floppy_format_type _formats[])148 void floppy_connector::set_formats(const floppy_format_type _formats[])
149 {
150 formats = _formats;
151 }
152
device_start()153 void floppy_connector::device_start()
154 {
155 }
156
device_config_complete()157 void floppy_connector::device_config_complete()
158 {
159 floppy_image_device *dev = dynamic_cast<floppy_image_device *>(get_card_device());
160 if(dev)
161 {
162 dev->set_formats(formats);
163 dev->enable_sound(m_enable_sound);
164 }
165 }
166
get_device()167 floppy_image_device *floppy_connector::get_device()
168 {
169 return dynamic_cast<floppy_image_device *>(get_card_device());
170 }
171
172 //-------------------------------------------------
173 // floppy_image_device - constructor
174 //-------------------------------------------------
175
floppy_image_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)176 floppy_image_device::floppy_image_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
177 : device_t(mconfig, type, tag, owner, clock),
178 device_image_interface(mconfig, *this),
179 input_format(nullptr),
180 output_format(nullptr),
181 image(),
182 fif_list(nullptr),
183 index_timer(nullptr),
184 tracks(0),
185 sides(0),
186 form_factor(0),
187 motor_always_on(false),
188 dskchg_writable(false),
189 has_trk00_sensor(true),
190 dir(0), stp(0), wtg(0), mon(0), ss(0), ds(-1), idx(0), wpt(0), rdy(0), dskchg(0),
191 ready(false),
192 rpm(0),
193 floppy_ratio_1(0),
194 revolution_count(0),
195 cyl(0),
196 subcyl(0),
197 image_dirty(false),
198 ready_counter(0),
199 m_make_sound(false),
200 m_sound_out(nullptr)
201 {
202 extension_list[0] = '\0';
203 m_err = IMAGE_ERROR_INVALIDIMAGE;
204 }
205
206 //-------------------------------------------------
207 // floppy_image_device - destructor
208 //-------------------------------------------------
209
~floppy_image_device()210 floppy_image_device::~floppy_image_device()
211 {
212 for(floppy_image_format_t *format = fif_list; format; ) {
213 floppy_image_format_t* tmp_format = format;
214 format = format->next;
215 delete tmp_format;
216 }
217 fif_list = nullptr;
218 }
219
setup_load_cb(load_cb cb)220 void floppy_image_device::setup_load_cb(load_cb cb)
221 {
222 cur_load_cb = cb;
223 }
224
setup_unload_cb(unload_cb cb)225 void floppy_image_device::setup_unload_cb(unload_cb cb)
226 {
227 cur_unload_cb = cb;
228 }
229
setup_index_pulse_cb(index_pulse_cb cb)230 void floppy_image_device::setup_index_pulse_cb(index_pulse_cb cb)
231 {
232 cur_index_pulse_cb = cb;
233 }
234
setup_ready_cb(ready_cb cb)235 void floppy_image_device::setup_ready_cb(ready_cb cb)
236 {
237 cur_ready_cb = cb;
238 }
239
setup_wpt_cb(wpt_cb cb)240 void floppy_image_device::setup_wpt_cb(wpt_cb cb)
241 {
242 cur_wpt_cb = cb;
243 }
244
setup_led_cb(led_cb cb)245 void floppy_image_device::setup_led_cb(led_cb cb)
246 {
247 cur_led_cb = cb;
248 }
249
set_formats(const floppy_format_type * formats)250 void floppy_image_device::set_formats(const floppy_format_type *formats)
251 {
252 extension_list[0] = '\0';
253 fif_list = nullptr;
254 for(int cnt=0; formats[cnt]; cnt++)
255 {
256 // allocate a new format
257 floppy_image_format_t *fif = formats[cnt]();
258 if(!fif_list)
259 fif_list = fif;
260 else
261 fif_list->append(fif);
262
263 add_format(fif->name(), fif->description(), fif->extensions(), "");
264
265 image_specify_extension( extension_list, 256, fif->extensions() );
266 }
267 }
268
get_formats() const269 floppy_image_format_t *floppy_image_device::get_formats() const
270 {
271 return fif_list;
272 }
273
get_load_format() const274 floppy_image_format_t *floppy_image_device::get_load_format() const
275 {
276 return input_format;
277 }
278
set_rpm(float _rpm)279 void floppy_image_device::set_rpm(float _rpm)
280 {
281 if(rpm == _rpm)
282 return;
283
284 rpm = _rpm;
285 rev_time = attotime::from_double(60/rpm);
286 floppy_ratio_1 = int(1000.0f*rpm/300.0f+0.5f);
287 }
288
setup_write(floppy_image_format_t * _output_format)289 void floppy_image_device::setup_write(floppy_image_format_t *_output_format)
290 {
291 output_format = _output_format;
292 commit_image();
293 }
294
commit_image()295 void floppy_image_device::commit_image()
296 {
297 image_dirty = false;
298 if(!output_format || !output_format->supports_save())
299 return;
300 io_generic io;
301 // Do _not_ remove this cast otherwise the pointer will be incorrect when used by the ioprocs.
302 io.file = (device_image_interface *)this;
303 io.procs = &image_ioprocs;
304 io.filler = 0xff;
305
306 osd_file::error err = image_core_file().truncate(0);
307 if (err != osd_file::error::NONE)
308 popmessage("Error, unable to truncate image: %d", int(err));
309
310 output_format->save(&io, image.get());
311 }
312
313 //-------------------------------------------------
314 // device_start - device-specific startup
315 //-------------------------------------------------
316
device_start()317 void floppy_image_device::device_start()
318 {
319 rpm = 0;
320 motor_always_on = false;
321 dskchg_writable = false;
322 has_trk00_sensor = true;
323
324 // better would be an extra parameter in the MCFG macro
325 drive_index = atoi(owner()->basetag());
326
327 idx = 0;
328
329 /* motor off */
330 mon = 1;
331
332 cyl = 0;
333 subcyl = 0;
334 ss = 0;
335 ds = -1;
336 stp = 1;
337 wpt = 0;
338 dskchg = exists() ? 1 : 0;
339 index_timer = timer_alloc(0);
340 image_dirty = false;
341 ready = true;
342 ready_counter = 0;
343
344 setup_characteristics();
345
346 if (m_make_sound) m_sound_out = subdevice<floppy_sound_device>(FLOPSND_TAG);
347
348 save_item(NAME(dir));
349 save_item(NAME(stp));
350 save_item(NAME(wtg));
351 save_item(NAME(mon));
352 save_item(NAME(ss));
353 save_item(NAME(ds));
354 save_item(NAME(idx));
355 save_item(NAME(wpt));
356 save_item(NAME(rdy));
357 save_item(NAME(dskchg));
358 save_item(NAME(ready));
359 save_item(NAME(rpm));
360 save_item(NAME(floppy_ratio_1));
361 save_item(NAME(revolution_start_time));
362 save_item(NAME(rev_time));
363 save_item(NAME(revolution_count));
364 save_item(NAME(cyl));
365 save_item(NAME(subcyl));
366 save_item(NAME(cache_start_time));
367 save_item(NAME(cache_end_time));
368 save_item(NAME(cache_index));
369 save_item(NAME(cache_entry));
370 save_item(NAME(cache_weak));
371 save_item(NAME(image_dirty));
372 save_item(NAME(ready_counter));
373 }
374
device_reset()375 void floppy_image_device::device_reset()
376 {
377 if (m_make_sound)
378 {
379 // Have we loaded all samples? Otherwise mute the floppy.
380 m_make_sound = m_sound_out->samples_loaded();
381 }
382
383 revolution_start_time = attotime::never;
384 revolution_count = 0;
385 mon = 1;
386 set_ready(true);
387 if(motor_always_on && image)
388 mon_w(0);
389 cache_clear();
390 }
391
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)392 void floppy_image_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
393 {
394 index_resync();
395 }
396
identify(std::string filename)397 floppy_image_format_t *floppy_image_device::identify(std::string filename)
398 {
399 util::core_file::ptr fd;
400 std::string revised_path;
401
402 osd_file::error err = util::zippath_fopen(filename, OPEN_FLAG_READ, fd, revised_path);
403 if(err != osd_file::error::NONE) {
404 seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to open the image file");
405 return nullptr;
406 }
407
408 io_generic io;
409 io.file = fd.get();
410 io.procs = &corefile_ioprocs_noclose;
411 io.filler = 0xff;
412 int best = 0;
413 floppy_image_format_t *best_format = nullptr;
414 for (floppy_image_format_t *format = fif_list; format; format = format->next)
415 {
416 int score = format->identify(&io, form_factor);
417 if(score > best) {
418 best = score;
419 best_format = format;
420 }
421 }
422 fd.reset();
423 return best_format;
424 }
425
init_floppy_load(bool write_supported)426 void floppy_image_device::init_floppy_load(bool write_supported)
427 {
428 cache_clear();
429 revolution_start_time = mon ? attotime::never : machine().time();
430 revolution_count = 0;
431
432 index_resync();
433
434 wpt = 1; // disk sleeve is covering the sensor
435 if (!cur_wpt_cb.isnull())
436 cur_wpt_cb(this, wpt);
437
438 wpt = is_readonly() || (!write_supported);
439 if (!cur_wpt_cb.isnull())
440 cur_wpt_cb(this, wpt);
441
442 if (motor_always_on) {
443 // When disk is inserted, start motor
444 mon_w(0);
445 } else if(!mon)
446 ready_counter = 2;
447
448 if (dskchg_writable)
449 dskchg = 1;
450 }
451
call_load()452 image_init_result floppy_image_device::call_load()
453 {
454 io_generic io;
455
456 // Do _not_ remove this cast otherwise the pointer will be incorrect when used by the ioprocs.
457 io.file = (device_image_interface *)this;
458 io.procs = &image_ioprocs;
459 io.filler = 0xff;
460 int best = 0;
461 floppy_image_format_t *best_format = nullptr;
462 for (floppy_image_format_t *format = fif_list; format; format = format->next) {
463 int score = format->identify(&io, form_factor);
464 if(score > best) {
465 best = score;
466 best_format = format;
467 }
468 }
469
470 if (!best_format) {
471 seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to identify the image format");
472 return image_init_result::FAIL;
473 }
474
475 image = std::make_unique<floppy_image>(tracks, sides, form_factor);
476 if (!best_format->load(&io, form_factor, image.get())) {
477 seterror(IMAGE_ERROR_UNSUPPORTED, "Incompatible image format or corrupted data");
478 image.reset();
479 return image_init_result::FAIL;
480 }
481 output_format = is_readonly() ? nullptr : best_format;
482
483 image_dirty = false;
484
485 init_floppy_load(output_format != nullptr);
486
487 if (!cur_load_cb.isnull())
488 return cur_load_cb(this);
489
490 return image_init_result::PASS;
491 }
492
call_unload()493 void floppy_image_device::call_unload()
494 {
495 cache_clear();
496 dskchg = 0;
497
498 if (image) {
499 if(image_dirty)
500 commit_image();
501 image.reset();
502 }
503
504 wpt = 1; // disk sleeve is covering the sensor
505 if (!cur_wpt_cb.isnull())
506 cur_wpt_cb(this, wpt);
507
508 wpt = 0; // sensor is uncovered
509 if (!cur_wpt_cb.isnull())
510 cur_wpt_cb(this, wpt);
511
512 if (!cur_unload_cb.isnull())
513 cur_unload_cb(this);
514
515 if (motor_always_on) {
516 // When disk is removed, stop motor
517 mon_w(1);
518 }
519
520 set_ready(true);
521 }
522
call_create(int format_type,util::option_resolution * format_options)523 image_init_result floppy_image_device::call_create(int format_type, util::option_resolution *format_options)
524 {
525 image = std::make_unique<floppy_image>(tracks, sides, form_factor);
526 output_format = nullptr;
527
528 // search for a suitable format based on the extension
529 for(floppy_image_format_t *i = fif_list; i; i = i->next)
530 {
531 // only consider formats that actually support saving
532 if(!i->supports_save())
533 continue;
534
535 if (i->extension_matches(basename()))
536 {
537 output_format = i;
538 break;
539 }
540 }
541
542 // did we find a suitable format?
543 if (output_format == nullptr)
544 {
545 seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to identify the image format");
546 return image_init_result::FAIL;
547 }
548
549 init_floppy_load(output_format != nullptr);
550
551 return image_init_result::PASS;
552 }
553
554 /* motor on, active low */
mon_w(int state)555 void floppy_image_device::mon_w(int state)
556 {
557 if(mon == state)
558 return;
559
560 mon = state;
561
562 /* off -> on */
563 if (!mon && image)
564 {
565 revolution_start_time = machine().time();
566 cache_clear();
567 if (motor_always_on) {
568 // Drives with motor that is always spinning are immediately ready when a disk is loaded
569 // because there is no spin-up time
570 set_ready(false);
571 } else {
572 ready_counter = 2;
573 }
574 index_resync();
575 }
576
577 /* on -> off */
578 else {
579 if(image_dirty)
580 commit_image();
581 cache_clear();
582 revolution_start_time = attotime::never;
583 index_timer->adjust(attotime::zero);
584 set_ready(true);
585 }
586
587 // Create a motor sound (loaded or empty)
588 if (m_make_sound) m_sound_out->motor(state==0, exists());
589 }
590
time_next_index()591 attotime floppy_image_device::time_next_index()
592 {
593 if(revolution_start_time.is_never())
594 return attotime::never;
595 return revolution_start_time + rev_time;
596 }
597
598 /* index pulses at rpm/60 Hz, and stays high for ~2ms at 300rpm */
index_resync()599 void floppy_image_device::index_resync()
600 {
601 if(revolution_start_time.is_never()) {
602 if(idx) {
603 idx = 0;
604 if (!cur_index_pulse_cb.isnull())
605 cur_index_pulse_cb(this, idx);
606 }
607 return;
608 }
609
610 attotime delta = machine().time() - revolution_start_time;
611 while(delta >= rev_time) {
612 delta -= rev_time;
613 revolution_start_time += rev_time;
614 revolution_count++;
615 }
616 int position = (delta*floppy_ratio_1).as_ticks(1000000000/1000);
617
618 int new_idx = position < 20000;
619
620 if(new_idx) {
621 attotime index_up_time = attotime::from_nsec((2000000*1000)/floppy_ratio_1);
622 index_timer->adjust(index_up_time - delta);
623 } else
624 index_timer->adjust(rev_time - delta);
625
626 if(new_idx != idx) {
627 idx = new_idx;
628 if(idx && ready) {
629 ready_counter--;
630 if(!ready_counter) {
631 // logerror("Drive spun up\n");
632 set_ready(false);
633 }
634 }
635 if (!cur_index_pulse_cb.isnull())
636 cur_index_pulse_cb(this, idx);
637 }
638 }
639
ready_r()640 bool floppy_image_device::ready_r()
641 {
642 return ready;
643 }
644
set_ready(bool state)645 void floppy_image_device::set_ready(bool state)
646 {
647 if (state != ready)
648 {
649 ready = state;
650 check_led();
651 if (!cur_ready_cb.isnull())
652 cur_ready_cb(this, ready);
653 }
654 }
655
check_led()656 void floppy_image_device::check_led()
657 {
658 if(!cur_led_cb.isnull())
659 cur_led_cb(this, (ds == drive_index) && !ready ? 1 : 0);
660 }
661
get_pos()662 double floppy_image_device::get_pos()
663 {
664 return index_timer->elapsed().as_double();
665 }
666
twosid_r()667 bool floppy_image_device::twosid_r()
668 {
669 int tracks = 0, heads = 0;
670
671 if (image) image->get_actual_geometry(tracks, heads);
672
673 return heads == 1;
674 }
675
stp_w(int state)676 void floppy_image_device::stp_w(int state)
677 {
678 // Before spin-up is done, ignore step pulses
679 // TODO: There are reports about drives supporting step operation with
680 // stopped spindle. Need to check that on real drives.
681 // if (ready_counter > 0) return;
682
683 if ( stp != state ) {
684 cache_clear();
685 stp = state;
686 if ( stp == 0 ) {
687 int ocyl = cyl;
688 if ( dir ) {
689 if ( cyl ) cyl--;
690 } else {
691 if ( cyl < tracks-1 ) cyl++;
692 }
693 if(ocyl != cyl)
694 {
695 if (TRACE_STEP) logerror("track %d\n", cyl);
696 // Do we want a stepper sound?
697 // We plan for 5 zones with possibly specific sounds
698 if (m_make_sound) m_sound_out->step(cyl*5/tracks);
699 }
700 /* Update disk detection if applicable */
701 if (exists() && !dskchg_writable)
702 {
703 if (dskchg==0) dskchg = 1;
704 }
705 }
706 subcyl = 0;
707 }
708 }
709
seek_phase_w(int phases)710 void floppy_image_device::seek_phase_w(int phases)
711 {
712 int cur_pos = (cyl << 2) | subcyl;
713 int req_pos;
714 switch(phases) {
715 case 0x1: req_pos = 0; break;
716 case 0x3: req_pos = 1; break;
717 case 0x2: req_pos = 2; break;
718 case 0x6: req_pos = 3; break;
719 case 0x4: req_pos = 4; break;
720 case 0xc: req_pos = 5; break;
721 case 0x8: req_pos = 6; break;
722 case 0x9: req_pos = 7; break;
723 default: return;
724 }
725
726 // Opposite phase, don't move
727 if(((cur_pos ^ req_pos) & 7) == 4)
728 return;
729
730 int next_pos = (cur_pos & ~7) | req_pos;
731 if(next_pos < cur_pos-4)
732 next_pos += 8;
733 else if(next_pos > cur_pos+4)
734 next_pos -= 8;
735 if(next_pos < 0)
736 next_pos = 0;
737 else if(next_pos > (tracks-1)*4)
738 next_pos = (tracks-1)*4;
739 cyl = next_pos >> 2;
740 subcyl = next_pos & 3;
741
742 cache_clear();
743
744 if(TRACE_STEP && (next_pos != cur_pos))
745 logerror("track %d.%d\n", cyl, subcyl);
746
747 /* Update disk detection if applicable */
748 if (exists() && !dskchg_writable)
749 if (dskchg==0)
750 dskchg = 1;
751 }
752
753 // From http://burtleburtle.net/bob/hash/integer.html
hash32(uint32_t a) const754 uint32_t floppy_image_device::hash32(uint32_t a) const
755 {
756 a = (a+0x7ed55d16) + (a<<12);
757 a = (a^0xc761c23c) ^ (a>>19);
758 a = (a+0x165667b1) + (a<<5);
759 a = (a+0xd3a2646c) ^ (a<<9);
760 a = (a+0xfd7046c5) + (a<<3);
761 a = (a^0xb55a4f09) ^ (a>>16);
762 return a;
763 }
764
find_index(uint32_t position,const std::vector<uint32_t> & buf) const765 int floppy_image_device::find_index(uint32_t position, const std::vector<uint32_t> &buf)const
766 {
767 int spos = (buf.size() >> 1)-1;
768 int step;
769 for(step=1; step<buf.size()+1; step<<=1) { }
770 step >>= 1;
771
772 for(;;) {
773 if(spos >= int(buf.size()) || (spos > 0 && (buf[spos] & floppy_image::TIME_MASK) > position)) {
774 spos -= step;
775 step >>= 1;
776 } else if(spos < 0 || (spos < int(buf.size())-1 && (buf[spos+1] & floppy_image::TIME_MASK) <= position)) {
777 spos += step;
778 step >>= 1;
779 } else
780 return spos;
781 }
782 }
783
find_position(attotime & base,const attotime & when)784 uint32_t floppy_image_device::find_position(attotime &base, const attotime &when)
785 {
786 base = revolution_start_time;
787 attotime delta = when - base;
788
789 while(delta >= rev_time) {
790 delta -= rev_time;
791 base += rev_time;
792 }
793 while(delta < attotime::zero) {
794 delta += rev_time;
795 base -= rev_time;
796 }
797
798 uint32_t res = (delta*floppy_ratio_1).as_ticks(1000000000/1000);
799 if (res >= 200000000) {
800 // Due to rounding errors in the previous operation,
801 // 'res' sometimes overflows 2E+8
802 res -= 200000000;
803 base += rev_time;
804 }
805 return res;
806 }
807
test_track_last_entry_warps(const std::vector<uint32_t> & buf) const808 bool floppy_image_device::test_track_last_entry_warps(const std::vector<uint32_t> &buf) const
809 {
810 return !((buf[buf.size() - 1]^buf[0]) & floppy_image::MG_MASK);
811 }
812
position_to_time(const attotime & base,int position) const813 attotime floppy_image_device::position_to_time(const attotime &base, int position) const
814 {
815 return base + attotime::from_nsec((int64_t(position)*2000/floppy_ratio_1+1)/2);
816 }
817
cache_fill_index(const std::vector<uint32_t> & buf,int & index,attotime & base)818 void floppy_image_device::cache_fill_index(const std::vector<uint32_t> &buf, int &index, attotime &base)
819 {
820 int cells = buf.size();
821
822 if(index != 0 || !test_track_last_entry_warps(buf)) {
823 cache_index = index;
824 cache_start_time = position_to_time(base, buf[index] & floppy_image::TIME_MASK);
825 } else {
826 cache_index = cells - 1;
827 cache_start_time = position_to_time(base - rev_time, buf[cache_index] & floppy_image::TIME_MASK);
828 }
829
830 cache_entry = buf[cache_index];
831
832 index ++;
833 if(index >= cells) {
834 index = test_track_last_entry_warps(buf) ? 1 : 0;
835 base += rev_time;
836 }
837
838 cache_end_time = position_to_time(base, buf[index] & floppy_image::TIME_MASK);
839 }
840
cache_clear()841 void floppy_image_device::cache_clear()
842 {
843 cache_start_time = cache_end_time = cache_weak_start = attotime::zero;
844 cache_index = 0;
845 cache_entry = 0;
846 cache_weak = false;
847 }
848
cache_fill(const attotime & when)849 void floppy_image_device::cache_fill(const attotime &when)
850 {
851 std::vector<uint32_t> &buf = image->get_buffer(cyl, ss, subcyl);
852 uint32_t cells = buf.size();
853 if(cells <= 1) {
854 cache_start_time = attotime::zero;
855 cache_end_time = attotime::never;
856 cache_index = 0;
857 cache_entry = cells == 1 ? buf[0] : floppy_image::MG_N;
858 cache_weakness_setup();
859 return;
860 }
861
862 attotime base;
863 uint32_t position = find_position(base, when);
864
865 int index = find_index(position, buf);
866
867 if(index == -1) {
868 // I suspect this should be an abort(), to check...
869 cache_start_time = attotime::zero;
870 cache_end_time = attotime::never;
871 cache_index = 0;
872 cache_entry = buf[0];
873 cache_weakness_setup();
874 return;
875 }
876
877 for(;;) {
878 cache_fill_index(buf, index, base);
879 if(cache_end_time > when) {
880 cache_weakness_setup();
881 return;
882 }
883 }
884 }
885
cache_weakness_setup()886 void floppy_image_device::cache_weakness_setup()
887 {
888 u32 type = cache_entry & floppy_image::MG_MASK;
889 if(type == floppy_image::MG_N || type == floppy_image::MG_D) {
890 cache_weak = true;
891 cache_weak_start = cache_start_time;
892 return;
893 }
894
895 cache_weak = cache_end_time.is_never() || (cache_end_time - cache_start_time >= attotime::from_usec(16));
896 if(!cache_weak) {
897 cache_weak_start = attotime::never;
898 return;
899 }
900 cache_weak_start = cache_start_time + attotime::from_usec(16);
901 }
902
get_next_transition(const attotime & from_when)903 attotime floppy_image_device::get_next_transition(const attotime &from_when)
904 {
905 if(!image || mon)
906 return attotime::never;
907
908 if(from_when < cache_start_time || (!cache_end_time.is_never() && from_when >= cache_end_time))
909 cache_fill(from_when);
910
911 if(!cache_weak)
912 return cache_end_time;
913
914 // Put a flux transition in the middle of a 4us interval with a 50% probability
915 int interval_index = (from_when - cache_weak_start).as_ticks(250000);
916 if(interval_index < 0)
917 interval_index = 0;
918 attotime weak_time = cache_weak_start + attotime::from_ticks(interval_index*2+1, 500000);
919 for(;;) {
920 if(weak_time >= cache_end_time)
921 return cache_end_time;
922 if(weak_time > from_when) {
923 u32 test = hash32(hash32(hash32(hash32(revolution_count) ^ 0x4242) + cache_index) + interval_index);
924 if(test & 1)
925 return weak_time;
926 }
927 weak_time += attotime::from_usec(4);
928 interval_index ++;
929 }
930 }
931
write_flux(const attotime & start,const attotime & end,int transition_count,const attotime * transitions)932 void floppy_image_device::write_flux(const attotime &start, const attotime &end, int transition_count, const attotime *transitions)
933 {
934 if(!image || mon)
935 return;
936 image_dirty = true;
937
938 attotime base;
939 int start_pos = find_position(base, start);
940 int end_pos = find_position(base, end);
941
942 std::vector<int> trans_pos(transition_count);
943 for(int i=0; i != transition_count; i++)
944 trans_pos[i] = find_position(base, transitions[i]);
945
946 std::vector<uint32_t> &buf = image->get_buffer(cyl, ss, subcyl);
947
948 int index;
949 if(!buf.empty())
950 index = find_index(start_pos, buf);
951 else {
952 index = 0;
953 buf.push_back(floppy_image::MG_N);
954 }
955
956 if(index && (buf[index] & floppy_image::TIME_MASK) == start_pos)
957 index--;
958
959 uint32_t cur_mg = buf[index] & floppy_image::MG_MASK;
960 if(cur_mg == floppy_image::MG_N || cur_mg == floppy_image::MG_D)
961 cur_mg = floppy_image::MG_A;
962
963 uint32_t pos = start_pos;
964 int ti = 0;
965 int cells = buf.size();
966 while(pos != end_pos) {
967 if(buf.size() < cells+10)
968 buf.resize(cells+200);
969 uint32_t next_pos;
970 if(ti != transition_count)
971 next_pos = trans_pos[ti++];
972 else
973 next_pos = end_pos;
974 if(next_pos > pos)
975 write_zone(&buf[0], cells, index, pos, next_pos, cur_mg);
976 else {
977 write_zone(&buf[0], cells, index, pos, 200000000, cur_mg);
978 index = 0;
979 write_zone(&buf[0], cells, index, 0, next_pos, cur_mg);
980 }
981 pos = next_pos;
982 cur_mg = cur_mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
983 }
984
985 buf.resize(cells);
986 }
987
write_zone(uint32_t * buf,int & cells,int & index,uint32_t spos,uint32_t epos,uint32_t mg)988 void floppy_image_device::write_zone(uint32_t *buf, int &cells, int &index, uint32_t spos, uint32_t epos, uint32_t mg)
989 {
990 cache_clear();
991 while(spos < epos) {
992 while(index != cells-1 && (buf[index+1] & floppy_image::TIME_MASK) <= spos)
993 index++;
994
995 uint32_t ref_start = buf[index] & floppy_image::TIME_MASK;
996 uint32_t ref_end = index == cells-1 ? 200000000 : buf[index+1] & floppy_image::TIME_MASK;
997 uint32_t ref_mg = buf[index] & floppy_image::MG_MASK;
998
999 // Can't overwrite a damaged zone
1000 if(ref_mg == floppy_image::MG_D) {
1001 spos = ref_end;
1002 continue;
1003 }
1004
1005 // If the zone is of the type we want, we don't need to touch it
1006 if(ref_mg == mg) {
1007 spos = ref_end;
1008 continue;
1009 }
1010
1011 // Check the overlaps, act accordingly
1012 if(spos == ref_start) {
1013 if(epos >= ref_end) {
1014 // Full overlap, that cell is dead, we need to see which ones we can extend
1015 uint32_t prev_mg = index != 0 ? buf[index-1] & floppy_image::MG_MASK : ~0;
1016 uint32_t next_mg = index != cells-1 ? buf[index+1] & floppy_image::MG_MASK : ~0;
1017 if(prev_mg == mg) {
1018 if(next_mg == mg) {
1019 // Both match, merge all three in one
1020 memmove(buf+index, buf+index+2, (cells-index-2)*sizeof(uint32_t));
1021 cells -= 2;
1022 index--;
1023
1024 } else {
1025 // Previous matches, drop the current cell
1026 memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(uint32_t));
1027 cells --;
1028 }
1029
1030 } else {
1031 if(next_mg == mg) {
1032 // Following matches, extend it
1033 memmove(buf+index, buf+index+1, (cells-index-1)*sizeof(uint32_t));
1034 cells --;
1035 buf[index] = mg | spos;
1036 } else {
1037 // None match, convert the current cell
1038 buf[index] = mg | spos;
1039 index++;
1040 }
1041 }
1042 spos = ref_end;
1043
1044 } else {
1045 // Overlap at the start only
1046 // Check if we can just extend the previous cell
1047 if(index != 0 && (buf[index-1] & floppy_image::MG_MASK) == mg)
1048 buf[index] = ref_mg | epos;
1049 else {
1050 // Otherwise we need to insert a new cell
1051 if(index != cells-1)
1052 memmove(buf+index+1, buf+index, (cells-index)*sizeof(uint32_t));
1053 cells++;
1054 buf[index] = mg | spos;
1055 buf[index+1] = ref_mg | epos;
1056 }
1057 spos = epos;
1058 }
1059
1060 } else {
1061 if(epos >= ref_end) {
1062 // Overlap at the end only
1063 // If we can't just extend the following cell, we need to insert a new one
1064 if(index == cells-1 || (buf[index+1] & floppy_image::MG_MASK) != mg) {
1065 if(index != cells-1)
1066 memmove(buf+index+2, buf+index+1, (cells-index-1)*sizeof(uint32_t));
1067 cells++;
1068 }
1069 buf[index+1] = mg | spos;
1070 index++;
1071 spos = ref_end;
1072
1073 } else {
1074 // Full inclusion
1075 // We need to split the zone in 3
1076 if(index != cells-1)
1077 memmove(buf+index+3, buf+index+1, (cells-index-1)*sizeof(uint32_t));
1078 cells += 2;
1079 buf[index+1] = mg | spos;
1080 buf[index+2] = ref_mg | epos;
1081 spos = epos;
1082 }
1083 }
1084
1085 }
1086 }
1087
set_write_splice(const attotime & when)1088 void floppy_image_device::set_write_splice(const attotime &when)
1089 {
1090 if(image) {
1091 image_dirty = true;
1092 attotime base;
1093 int splice_pos = find_position(base, when);
1094 image->set_write_splice_position(cyl, ss, splice_pos, subcyl);
1095 }
1096 }
1097
get_form_factor() const1098 uint32_t floppy_image_device::get_form_factor() const
1099 {
1100 return form_factor;
1101 }
1102
get_variant() const1103 uint32_t floppy_image_device::get_variant() const
1104 {
1105 return image ? image->get_variant() : 0;
1106 }
1107
1108 //===================================================================
1109 // Floppy sound
1110 //
1111 // In order to enable floppy sound you must call
1112 // enable_sound(true)
1113 // and you must put audio samples (44100Hz, mono) with names as
1114 // shown in floppy_sample_names into the directory samples/floppy
1115 // Sound will be disabled when these samples are missing.
1116 //
1117 // MZ, Aug 2015
1118 //===================================================================
1119
1120 enum
1121 {
1122 QUIET=-1,
1123 SPIN_START_EMPTY=0,
1124 SPIN_START_LOADED,
1125 SPIN_EMPTY,
1126 SPIN_LOADED,
1127 SPIN_END
1128 };
1129
1130 enum
1131 {
1132 STEP_SINGLE=0,
1133 STEP_SEEK2,
1134 STEP_SEEK6,
1135 STEP_SEEK12,
1136 STEP_SEEK20
1137 };
1138
1139 /*
1140 Unless labeled "constructed", all samples were recorded from real floppy drives.
1141 The 3.5" floppy drive is a Sony MPF420-1.
1142 The 5.25" floppy drive is a Chinon FZ502.
1143 */
1144 static const char *const floppy35_sample_names[] =
1145 {
1146 // Subdirectory
1147 "*floppy",
1148 // Spinning sounds
1149 "35_spin_start_empty",
1150 "35_spin_start_loaded",
1151 "35_spin_empty",
1152 "35_spin_loaded",
1153 "35_spin_end",
1154 // Stepping sounds
1155 "35_step_1_1",
1156 // Seeking sounds
1157 "35_seek_2ms", // constructed
1158 "35_seek_6ms",
1159 "35_seek_12ms",
1160 "35_seek_20ms",
1161 nullptr
1162 };
1163
1164 static const char *const floppy525_sample_names[] =
1165 {
1166 // Subdirectory
1167 "*floppy",
1168 // Spinning sounds
1169 "525_spin_start_empty",
1170 "525_spin_start_loaded",
1171 "525_spin_empty",
1172 "525_spin_loaded",
1173 "525_spin_end",
1174 // Stepping sounds
1175 "525_step_1_1",
1176 // Seeking sounds
1177 "525_seek_2ms", // unrealistically fast, but needed for 3.5 (constructed)
1178 "525_seek_6ms",
1179 "525_seek_12ms",
1180 "525_seek_20ms",
1181 nullptr
1182 };
1183
floppy_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1184 floppy_sound_device::floppy_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1185 : samples_device(mconfig, FLOPPYSOUND, tag, owner, clock),
1186 m_sound(nullptr),
1187 m_step_base(0),
1188 m_spin_samples(0),
1189 m_step_samples(0),
1190 m_spin_samplepos(0),
1191 m_step_samplepos(0),
1192 m_seek_sound_timeout(0),
1193 m_zones(0),
1194 m_spin_playback_sample(QUIET),
1195 m_step_playback_sample(QUIET),
1196 m_seek_playback_sample(QUIET),
1197 m_motor_on(false),
1198 m_with_disk(false),
1199 m_loaded(false),
1200 m_seek_pitch(1.0),
1201 m_seek_samplepos(0.0)
1202 {
1203 }
1204
register_for_save_states()1205 void floppy_sound_device::register_for_save_states()
1206 {
1207 save_item(NAME(m_step_base));
1208 save_item(NAME(m_spin_samples));
1209 save_item(NAME(m_step_samples));
1210 save_item(NAME(m_spin_samplepos));
1211 save_item(NAME(m_step_samplepos));
1212 save_item(NAME(m_seek_samplepos));
1213 save_item(NAME(m_seek_sound_timeout));
1214 save_item(NAME(m_zones));
1215 save_item(NAME(m_spin_playback_sample));
1216 save_item(NAME(m_step_playback_sample));
1217 save_item(NAME(m_seek_playback_sample));
1218 save_item(NAME(m_motor_on));
1219 save_item(NAME(m_with_disk));
1220 save_item(NAME(m_loaded));
1221 save_item(NAME(m_seek_pitch));
1222 }
1223
device_start()1224 void floppy_sound_device::device_start()
1225 {
1226 // What kind of drive do we have?
1227 bool is525 = strstr(tag(), "525") != nullptr;
1228 set_samples_names(is525? floppy525_sample_names : floppy35_sample_names);
1229
1230 m_motor_on = false;
1231
1232 // Offsets in the sample collection
1233 m_spin_samples = 5;
1234 m_step_base = 5;
1235 m_step_samples = 1;
1236 m_zones = 1; // > 1 needs more than one step sample
1237
1238 m_spin_samplepos = m_step_samplepos = m_seek_samplepos = 0;
1239 m_spin_playback_sample = m_step_playback_sample = QUIET;
1240
1241 // Read audio samples. The samples are stored in the list m_samples.
1242 m_loaded = load_samples();
1243
1244 // If we don't have all samples, don't allocate a stream or access sample data.
1245 if (m_loaded)
1246 {
1247 m_sound = stream_alloc(0, 1, clock()); // per-floppy stream
1248 }
1249 register_for_save_states();
1250 }
1251
1252 /*
1253 Motor sound. Select appropriate sound sample, depending on whether the
1254 motor is started or keeps running. Motor samples are always fully
1255 played.
1256 */
motor(bool running,bool withdisk)1257 void floppy_sound_device::motor(bool running, bool withdisk)
1258 {
1259 if (samples_loaded())
1260 {
1261 m_sound->update(); // required
1262
1263 if ((m_spin_playback_sample==QUIET || m_spin_playback_sample==SPIN_END) && running) // motor was either off or already spinning down
1264 {
1265 m_spin_samplepos = 0;
1266 m_spin_playback_sample = withdisk? SPIN_START_LOADED : SPIN_START_EMPTY; // (re)start the motor sound
1267 }
1268 else
1269 {
1270 // Motor has been running and is turned off now
1271 if ((m_spin_playback_sample == SPIN_EMPTY || m_spin_playback_sample == SPIN_LOADED) && !running)
1272 m_spin_playback_sample = SPIN_END; // go to spin down sound when loop is finished
1273 }
1274 }
1275 m_motor_on = running;
1276 m_with_disk = withdisk;
1277 }
1278
1279 /*
1280 Activate the step sound.
1281 The zone parameter should be used to select specific samples for the
1282 current head position (if available). Its value should range from 0 to 4.
1283 */
step(int zone)1284 void floppy_sound_device::step(int zone)
1285 {
1286 if (samples_loaded())
1287 {
1288 m_sound->update(); // required
1289
1290 // Pick one of the step samples
1291 // TODO: This is only preliminary, need to complete that.
1292 if (zone >= m_zones) zone = m_zones-1;
1293 m_step_playback_sample = (zone * m_step_samples) + (machine().rand() % m_step_samples);
1294
1295 if (m_step_samplepos > 0)
1296 {
1297 if (m_seek_playback_sample == QUIET)
1298 {
1299 // The last step sample was not completed;
1300 // we need to find out the step rate
1301 // With a sample rate of 44100 Hz we can calculate the
1302 // rate from the sample position
1303 // 2ms = 88
1304 // 6ms = 265
1305 // 12ms = 529
1306 // 20ms = 882
1307
1308 if (m_step_samplepos < 100)
1309 {
1310 // Should only used for 3.5 drives
1311 m_seek_playback_sample = STEP_SEEK2;
1312 m_seek_pitch = 1.0; // don't use a pitch
1313 }
1314 else
1315 {
1316 if (m_step_samplepos < 400) // Use this for 8 ms also
1317 {
1318 m_seek_playback_sample = STEP_SEEK6;
1319 m_seek_pitch = 265.0 / m_step_samplepos;
1320 }
1321 else
1322 {
1323 if (m_step_samplepos < 600)
1324 {
1325 m_seek_playback_sample = STEP_SEEK12;
1326 m_seek_pitch = 529.0 / m_step_samplepos;
1327 }
1328 else
1329 {
1330 if (m_step_samplepos < 1200)
1331 {
1332 m_seek_playback_sample = STEP_SEEK20;
1333 m_seek_pitch = 882.0 / m_step_samplepos;
1334 }
1335 else
1336 // For 30ms and longer we replay the step sound
1337 m_seek_playback_sample = QUIET;
1338 }
1339 }
1340 }
1341 }
1342
1343 // Changing the pitch does not always sound convincing
1344 if (!PITCH_SEEK_SAMPLES) m_seek_pitch = 1;
1345
1346 if (TRACE_AUDIO) logerror("Seek sample = %d, pitch = %f\n", m_seek_playback_sample, m_seek_pitch);
1347
1348 // Set the timeout for the seek sound. When it expires,
1349 // we assume that the seek process is over, and we'll play the
1350 // rest of the step sound.
1351 // This will be retriggered with each step pulse.
1352 m_seek_sound_timeout = m_step_samplepos * 2;
1353 }
1354 else
1355 {
1356 // Last step sample was completed, this is not a seek process
1357 m_seek_playback_sample = QUIET;
1358 }
1359
1360 // If we switch to the seek sample, let's keep the position of the
1361 // step sample; else reset the step sample position.
1362 if (m_seek_playback_sample == QUIET)
1363 m_step_samplepos = 0;
1364 }
1365 }
1366
1367 //-------------------------------------------------
1368 // sound_stream_update - update the sound stream
1369 //-------------------------------------------------
1370
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)1371 void floppy_sound_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
1372 {
1373 // We are using only one stream, unlike the parent class
1374 // Also, there is no need for interpolation, as we only expect
1375 // one sample rate of 44100 for all samples
1376
1377 int16_t out;
1378 auto &samplebuffer = outputs[0];
1379 int idx = 0;
1380 int sampleend = 0;
1381
1382 for (int sampindex = 0; sampindex < samplebuffer.samples(); sampindex++)
1383 {
1384 out = 0;
1385
1386 // Motor sound
1387 if (m_spin_playback_sample != QUIET)
1388 {
1389 idx = m_spin_playback_sample;
1390 sampleend = m_sample[idx].data.size();
1391 out = m_sample[idx].data[m_spin_samplepos++];
1392
1393 if (m_spin_samplepos >= sampleend)
1394 {
1395 // Motor sample has completed
1396 switch (m_spin_playback_sample)
1397 {
1398 case SPIN_START_EMPTY:
1399 // After start, switch to the continued spinning sound
1400 m_spin_playback_sample = SPIN_EMPTY; // move to looping sound
1401 break;
1402 case SPIN_START_LOADED:
1403 // After start, switch to the continued spinning sound
1404 m_spin_playback_sample = SPIN_LOADED; // move to looping sound
1405 break;
1406 case SPIN_EMPTY:
1407 // As long as the motor pin is asserted, restart the sample
1408 // play the spindown sample
1409 if (!m_motor_on) m_spin_playback_sample = SPIN_END; // motor was turned off already (during spin-up maybe) -> spin down
1410 break;
1411 case SPIN_LOADED:
1412 if (!m_motor_on) m_spin_playback_sample = SPIN_END; // motor was turned off already (during spin-up maybe) -> spin down
1413 break;
1414 case SPIN_END:
1415 // Spindown sample over, be quiet or restart if the
1416 // motor has been restarted
1417 if (m_motor_on)
1418 m_spin_playback_sample = m_with_disk? SPIN_START_LOADED : SPIN_START_EMPTY;
1419 else
1420 m_spin_playback_sample = QUIET;
1421 break;
1422 }
1423 // Restart the selected sample
1424 m_spin_samplepos = 0;
1425 }
1426 }
1427
1428 // Seek sound
1429 // As long as we have a seek sound, there is no step sound
1430 if (m_seek_sound_timeout == 1)
1431 {
1432 // Not retriggered; switch back to the last step sound
1433 m_seek_playback_sample = QUIET;
1434 m_seek_sound_timeout = 0;
1435 // Skip 1/100 sec to dampen the loudest pulse
1436 // yep, a somewhat dirty trick; we don't have to record yet another sample
1437 m_step_samplepos += 441;
1438 }
1439
1440 if (m_seek_playback_sample != QUIET)
1441 {
1442 m_seek_sound_timeout--;
1443
1444 idx = m_step_base + m_seek_playback_sample;
1445 sampleend = m_sample[idx].data.size();
1446 // Mix it into the stream value
1447 out += m_sample[idx].data[(int)m_seek_samplepos];
1448 // By adding different values than 1, we can change the playback speed
1449 // This will be used to adjust the seek sound
1450 m_seek_samplepos += m_seek_pitch;
1451
1452 // The seek sample will be replayed without interrupt
1453 if (m_seek_samplepos >= sampleend)
1454 m_seek_samplepos = 0;
1455 }
1456 else
1457 {
1458 // Stepper sound
1459 if (m_step_playback_sample != QUIET)
1460 {
1461 idx = m_step_base + m_step_playback_sample;
1462 sampleend = m_sample[idx].data.size();
1463
1464 // Mix it into the stream value
1465 out += m_sample[idx].data[m_step_samplepos++];
1466 if (m_step_samplepos >= sampleend)
1467 {
1468 // Step sample done
1469 m_step_samplepos = 0;
1470 m_step_playback_sample = QUIET;
1471 }
1472 }
1473 }
1474
1475 // Write to the stream buffer
1476 samplebuffer.put_int(sampindex, out, 32768);
1477 }
1478 }
1479
1480 #define FLOPSPK "flopsndout"
1481
device_add_mconfig(machine_config & config)1482 void floppy_image_device::device_add_mconfig(machine_config &config)
1483 {
1484 SPEAKER(config, FLOPSPK).front_center();
1485 FLOPPYSOUND(config, FLOPSND_TAG, 44100).add_route(ALL_OUTPUTS, FLOPSPK, 0.5);
1486 }
1487
1488
1489 DEFINE_DEVICE_TYPE(FLOPPYSOUND, floppy_sound_device, "flopsnd", "Floppy sound")
1490
1491
1492 //**************************************************************************
1493 // GENERIC FLOPPY DRIVE DEFINITIONS
1494 //**************************************************************************
1495
1496 //-------------------------------------------------
1497 // 3" single-sided double density
1498 //-------------------------------------------------
1499
floppy_3_ssdd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1500 floppy_3_ssdd::floppy_3_ssdd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1501 floppy_image_device(mconfig, FLOPPY_3_SSDD, tag, owner, clock)
1502 {
1503 }
1504
~floppy_3_ssdd()1505 floppy_3_ssdd::~floppy_3_ssdd()
1506 {
1507 }
1508
setup_characteristics()1509 void floppy_3_ssdd::setup_characteristics()
1510 {
1511 form_factor = floppy_image::FF_3;
1512 tracks = 42;
1513 sides = 1;
1514 set_rpm(300);
1515 }
1516
handled_variants(uint32_t * variants,int & var_count) const1517 void floppy_3_ssdd::handled_variants(uint32_t *variants, int &var_count) const
1518 {
1519 var_count = 0;
1520 variants[var_count++] = floppy_image::SSDD;
1521 }
1522
1523 //-------------------------------------------------
1524 // 3" double-sided double density
1525 //-------------------------------------------------
1526
floppy_3_dsdd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1527 floppy_3_dsdd::floppy_3_dsdd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1528 floppy_image_device(mconfig, FLOPPY_3_DSDD, tag, owner, clock)
1529 {
1530 }
1531
~floppy_3_dsdd()1532 floppy_3_dsdd::~floppy_3_dsdd()
1533 {
1534 }
1535
setup_characteristics()1536 void floppy_3_dsdd::setup_characteristics()
1537 {
1538 form_factor = floppy_image::FF_3;
1539 tracks = 42;
1540 sides = 2;
1541 set_rpm(300);
1542 }
1543
handled_variants(uint32_t * variants,int & var_count) const1544 void floppy_3_dsdd::handled_variants(uint32_t *variants, int &var_count) const
1545 {
1546 var_count = 0;
1547 variants[var_count++] = floppy_image::SSDD;
1548 variants[var_count++] = floppy_image::DSDD;
1549 }
1550
1551 //-------------------------------------------------
1552 // 3.5" single-sided double density
1553 //-------------------------------------------------
1554
floppy_35_ssdd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1555 floppy_35_ssdd::floppy_35_ssdd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1556 floppy_image_device(mconfig, FLOPPY_35_SSDD, tag, owner, clock)
1557 {
1558 }
1559
~floppy_35_ssdd()1560 floppy_35_ssdd::~floppy_35_ssdd()
1561 {
1562 }
1563
setup_characteristics()1564 void floppy_35_ssdd::setup_characteristics()
1565 {
1566 form_factor = floppy_image::FF_35;
1567 tracks = 84;
1568 sides = 1;
1569 set_rpm(300);
1570 }
1571
handled_variants(uint32_t * variants,int & var_count) const1572 void floppy_35_ssdd::handled_variants(uint32_t *variants, int &var_count) const
1573 {
1574 var_count = 0;
1575 variants[var_count++] = floppy_image::SSSD;
1576 variants[var_count++] = floppy_image::SSDD;
1577 }
1578
1579 //-------------------------------------------------
1580 // 3.5" double-sided double density
1581 //-------------------------------------------------
1582
floppy_35_dd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1583 floppy_35_dd::floppy_35_dd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1584 floppy_image_device(mconfig, FLOPPY_35_DD, tag, owner, clock)
1585 {
1586 }
1587
~floppy_35_dd()1588 floppy_35_dd::~floppy_35_dd()
1589 {
1590 }
1591
setup_characteristics()1592 void floppy_35_dd::setup_characteristics()
1593 {
1594 form_factor = floppy_image::FF_35;
1595 tracks = 84;
1596 sides = 2;
1597 set_rpm(300);
1598 }
1599
handled_variants(uint32_t * variants,int & var_count) const1600 void floppy_35_dd::handled_variants(uint32_t *variants, int &var_count) const
1601 {
1602 var_count = 0;
1603 variants[var_count++] = floppy_image::SSSD;
1604 variants[var_count++] = floppy_image::SSDD;
1605 variants[var_count++] = floppy_image::DSDD;
1606 }
1607
1608 //-------------------------------------------------
1609 // 3.5" high density
1610 //-------------------------------------------------
1611
floppy_35_hd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1612 floppy_35_hd::floppy_35_hd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1613 floppy_image_device(mconfig, FLOPPY_35_HD, tag, owner, clock)
1614 {
1615 }
1616
~floppy_35_hd()1617 floppy_35_hd::~floppy_35_hd()
1618 {
1619 }
1620
setup_characteristics()1621 void floppy_35_hd::setup_characteristics()
1622 {
1623 form_factor = floppy_image::FF_35;
1624 tracks = 84;
1625 sides = 2;
1626 set_rpm(300);
1627 }
1628
handled_variants(uint32_t * variants,int & var_count) const1629 void floppy_35_hd::handled_variants(uint32_t *variants, int &var_count) const
1630 {
1631 var_count = 0;
1632 variants[var_count++] = floppy_image::SSSD;
1633 variants[var_count++] = floppy_image::SSDD;
1634 variants[var_count++] = floppy_image::DSDD;
1635 variants[var_count++] = floppy_image::DSHD;
1636 }
1637
1638 //-------------------------------------------------
1639 // 3.5" extended density
1640 //-------------------------------------------------
1641
floppy_35_ed(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1642 floppy_35_ed::floppy_35_ed(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1643 floppy_image_device(mconfig, FLOPPY_35_ED, tag, owner, clock)
1644 {
1645 }
1646
~floppy_35_ed()1647 floppy_35_ed::~floppy_35_ed()
1648 {
1649 }
1650
setup_characteristics()1651 void floppy_35_ed::setup_characteristics()
1652 {
1653 form_factor = floppy_image::FF_35;
1654 tracks = 84;
1655 sides = 2;
1656 set_rpm(300);
1657 }
1658
handled_variants(uint32_t * variants,int & var_count) const1659 void floppy_35_ed::handled_variants(uint32_t *variants, int &var_count) const
1660 {
1661 var_count = 0;
1662 variants[var_count++] = floppy_image::SSSD;
1663 variants[var_count++] = floppy_image::SSDD;
1664 variants[var_count++] = floppy_image::DSDD;
1665 variants[var_count++] = floppy_image::DSHD;
1666 variants[var_count++] = floppy_image::DSED;
1667 }
1668
1669 //-------------------------------------------------
1670 // 5.25" single-sided single density 35 tracks
1671 //-------------------------------------------------
1672
floppy_525_sssd_35t(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1673 floppy_525_sssd_35t::floppy_525_sssd_35t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1674 floppy_image_device(mconfig, FLOPPY_525_SSSD_35T, tag, owner, clock)
1675 {
1676 }
1677
~floppy_525_sssd_35t()1678 floppy_525_sssd_35t::~floppy_525_sssd_35t()
1679 {
1680 }
1681
setup_characteristics()1682 void floppy_525_sssd_35t::setup_characteristics()
1683 {
1684 form_factor = floppy_image::FF_525;
1685 tracks = 35;
1686 sides = 1;
1687 set_rpm(300);
1688 }
1689
handled_variants(uint32_t * variants,int & var_count) const1690 void floppy_525_sssd_35t::handled_variants(uint32_t *variants, int &var_count) const
1691 {
1692 var_count = 0;
1693 variants[var_count++] = floppy_image::SSSD;
1694 }
1695
1696 //-------------------------------------------------
1697 // 5.25" double-sided single density 35 tracks
1698 //-------------------------------------------------
1699
floppy_525_sd_35t(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1700 floppy_525_sd_35t::floppy_525_sd_35t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1701 floppy_image_device(mconfig, FLOPPY_525_SD_35T, tag, owner, clock)
1702 {
1703 }
1704
~floppy_525_sd_35t()1705 floppy_525_sd_35t::~floppy_525_sd_35t()
1706 {
1707 }
1708
setup_characteristics()1709 void floppy_525_sd_35t::setup_characteristics()
1710 {
1711 form_factor = floppy_image::FF_525;
1712 tracks = 35;
1713 sides = 2;
1714 set_rpm(300);
1715 }
1716
handled_variants(uint32_t * variants,int & var_count) const1717 void floppy_525_sd_35t::handled_variants(uint32_t *variants, int &var_count) const
1718 {
1719 var_count = 0;
1720 variants[var_count++] = floppy_image::SSSD;
1721 }
1722
1723 //-------------------------------------------------
1724 // 5.25" single-sided single density
1725 //-------------------------------------------------
1726
floppy_525_sssd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1727 floppy_525_sssd::floppy_525_sssd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1728 floppy_image_device(mconfig, FLOPPY_525_SSSD, tag, owner, clock)
1729 {
1730 }
1731
~floppy_525_sssd()1732 floppy_525_sssd::~floppy_525_sssd()
1733 {
1734 }
1735
setup_characteristics()1736 void floppy_525_sssd::setup_characteristics()
1737 {
1738 form_factor = floppy_image::FF_525;
1739 tracks = 42;
1740 sides = 1;
1741 set_rpm(300);
1742 }
1743
handled_variants(uint32_t * variants,int & var_count) const1744 void floppy_525_sssd::handled_variants(uint32_t *variants, int &var_count) const
1745 {
1746 var_count = 0;
1747 variants[var_count++] = floppy_image::SSSD;
1748 }
1749
1750 //-------------------------------------------------
1751 // 5.25" double-sided single density
1752 //-------------------------------------------------
1753
floppy_525_sd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1754 floppy_525_sd::floppy_525_sd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1755 floppy_image_device(mconfig, FLOPPY_525_SD, tag, owner, clock)
1756 {
1757 }
1758
~floppy_525_sd()1759 floppy_525_sd::~floppy_525_sd()
1760 {
1761 }
1762
setup_characteristics()1763 void floppy_525_sd::setup_characteristics()
1764 {
1765 form_factor = floppy_image::FF_525;
1766 tracks = 42;
1767 sides = 2;
1768 set_rpm(300);
1769 }
1770
handled_variants(uint32_t * variants,int & var_count) const1771 void floppy_525_sd::handled_variants(uint32_t *variants, int &var_count) const
1772 {
1773 var_count = 0;
1774 variants[var_count++] = floppy_image::SSSD;
1775 }
1776
1777 //-------------------------------------------------
1778 // 5.25" single-sided double density
1779 //-------------------------------------------------
1780
floppy_525_ssdd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1781 floppy_525_ssdd::floppy_525_ssdd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1782 floppy_image_device(mconfig, FLOPPY_525_SSDD, tag, owner, clock)
1783 {
1784 }
1785
~floppy_525_ssdd()1786 floppy_525_ssdd::~floppy_525_ssdd()
1787 {
1788 }
1789
setup_characteristics()1790 void floppy_525_ssdd::setup_characteristics()
1791 {
1792 form_factor = floppy_image::FF_525;
1793 tracks = 42;
1794 sides = 1;
1795 set_rpm(300);
1796 }
1797
handled_variants(uint32_t * variants,int & var_count) const1798 void floppy_525_ssdd::handled_variants(uint32_t *variants, int &var_count) const
1799 {
1800 var_count = 0;
1801 variants[var_count++] = floppy_image::SSSD;
1802 variants[var_count++] = floppy_image::SSDD;
1803 }
1804
1805 //-------------------------------------------------
1806 // 5.25" double-sided double density
1807 //-------------------------------------------------
1808
floppy_525_dd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1809 floppy_525_dd::floppy_525_dd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1810 floppy_image_device(mconfig, FLOPPY_525_DD, tag, owner, clock)
1811 {
1812 }
1813
~floppy_525_dd()1814 floppy_525_dd::~floppy_525_dd()
1815 {
1816 }
1817
setup_characteristics()1818 void floppy_525_dd::setup_characteristics()
1819 {
1820 form_factor = floppy_image::FF_525;
1821 tracks = 42;
1822 sides = 2;
1823 set_rpm(300);
1824 }
1825
handled_variants(uint32_t * variants,int & var_count) const1826 void floppy_525_dd::handled_variants(uint32_t *variants, int &var_count) const
1827 {
1828 var_count = 0;
1829 variants[var_count++] = floppy_image::SSSD;
1830 variants[var_count++] = floppy_image::SSDD;
1831 variants[var_count++] = floppy_image::DSDD;
1832 }
1833
1834 //-------------------------------------------------
1835 // 5.25" single-sided quad density
1836 //-------------------------------------------------
1837
floppy_525_ssqd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1838 floppy_525_ssqd::floppy_525_ssqd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1839 floppy_image_device(mconfig, FLOPPY_525_SSQD, tag, owner, clock)
1840 {
1841 }
1842
~floppy_525_ssqd()1843 floppy_525_ssqd::~floppy_525_ssqd()
1844 {
1845 }
1846
setup_characteristics()1847 void floppy_525_ssqd::setup_characteristics()
1848 {
1849 form_factor = floppy_image::FF_525;
1850 tracks = 84;
1851 sides = 1;
1852 set_rpm(300);
1853 }
1854
handled_variants(uint32_t * variants,int & var_count) const1855 void floppy_525_ssqd::handled_variants(uint32_t *variants, int &var_count) const
1856 {
1857 var_count = 0;
1858 variants[var_count++] = floppy_image::SSSD;
1859 variants[var_count++] = floppy_image::SSDD;
1860 variants[var_count++] = floppy_image::SSQD;
1861 }
1862
1863 //-------------------------------------------------
1864 // 5.25" double-sided quad density
1865 //-------------------------------------------------
1866
floppy_525_qd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1867 floppy_525_qd::floppy_525_qd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1868 floppy_image_device(mconfig, FLOPPY_525_QD, tag, owner, clock)
1869 {
1870 }
1871
~floppy_525_qd()1872 floppy_525_qd::~floppy_525_qd()
1873 {
1874 }
1875
setup_characteristics()1876 void floppy_525_qd::setup_characteristics()
1877 {
1878 form_factor = floppy_image::FF_525;
1879 tracks = 84;
1880 sides = 2;
1881 set_rpm(300);
1882 }
1883
handled_variants(uint32_t * variants,int & var_count) const1884 void floppy_525_qd::handled_variants(uint32_t *variants, int &var_count) const
1885 {
1886 var_count = 0;
1887 variants[var_count++] = floppy_image::SSSD;
1888 variants[var_count++] = floppy_image::SSDD;
1889 variants[var_count++] = floppy_image::SSQD;
1890 variants[var_count++] = floppy_image::DSSD;
1891 variants[var_count++] = floppy_image::DSDD;
1892 variants[var_count++] = floppy_image::DSQD;
1893 }
1894
1895 //-------------------------------------------------
1896 // 5.25" high density
1897 //-------------------------------------------------
1898
floppy_525_hd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1899 floppy_525_hd::floppy_525_hd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1900 floppy_image_device(mconfig, FLOPPY_525_HD, tag, owner, clock)
1901 {
1902 }
1903
~floppy_525_hd()1904 floppy_525_hd::~floppy_525_hd()
1905 {
1906 }
1907
setup_characteristics()1908 void floppy_525_hd::setup_characteristics()
1909 {
1910 form_factor = floppy_image::FF_525;
1911 tracks = 84;
1912 sides = 2;
1913 set_rpm(360);
1914 }
1915
handled_variants(uint32_t * variants,int & var_count) const1916 void floppy_525_hd::handled_variants(uint32_t *variants, int &var_count) const
1917 {
1918 var_count = 0;
1919 variants[var_count++] = floppy_image::SSSD;
1920 variants[var_count++] = floppy_image::SSDD;
1921 variants[var_count++] = floppy_image::SSQD;
1922 variants[var_count++] = floppy_image::DSDD;
1923 variants[var_count++] = floppy_image::DSQD;
1924 variants[var_count++] = floppy_image::DSHD;
1925 }
1926
1927 //-------------------------------------------------
1928 // 8" single-sided single density
1929 //-------------------------------------------------
1930
floppy_8_sssd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1931 floppy_8_sssd::floppy_8_sssd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1932 floppy_image_device(mconfig, FLOPPY_8_SSSD, tag, owner, clock)
1933 {
1934 }
1935
~floppy_8_sssd()1936 floppy_8_sssd::~floppy_8_sssd()
1937 {
1938 }
1939
setup_characteristics()1940 void floppy_8_sssd::setup_characteristics()
1941 {
1942 form_factor = floppy_image::FF_8;
1943 tracks = 77;
1944 sides = 1;
1945 motor_always_on = true;
1946 set_rpm(360);
1947 }
1948
handled_variants(uint32_t * variants,int & var_count) const1949 void floppy_8_sssd::handled_variants(uint32_t *variants, int &var_count) const
1950 {
1951 var_count = 0;
1952 variants[var_count++] = floppy_image::SSSD;
1953 }
1954
1955 //-------------------------------------------------
1956 // 8" double-sided single density
1957 //-------------------------------------------------
1958
floppy_8_dssd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1959 floppy_8_dssd::floppy_8_dssd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1960 floppy_image_device(mconfig, FLOPPY_8_DSSD, tag, owner, clock)
1961 {
1962 }
1963
~floppy_8_dssd()1964 floppy_8_dssd::~floppy_8_dssd()
1965 {
1966 }
1967
setup_characteristics()1968 void floppy_8_dssd::setup_characteristics()
1969 {
1970 form_factor = floppy_image::FF_8;
1971 tracks = 77;
1972 sides = 2;
1973 motor_always_on = true;
1974 set_rpm(360);
1975 }
1976
handled_variants(uint32_t * variants,int & var_count) const1977 void floppy_8_dssd::handled_variants(uint32_t *variants, int &var_count) const
1978 {
1979 var_count = 0;
1980 variants[var_count++] = floppy_image::SSSD;
1981 variants[var_count++] = floppy_image::DSSD;
1982 }
1983
1984 //-------------------------------------------------
1985 // 8" single-sided double density
1986 //-------------------------------------------------
1987
floppy_8_ssdd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1988 floppy_8_ssdd::floppy_8_ssdd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1989 floppy_image_device(mconfig, FLOPPY_8_SSDD, tag, owner, clock)
1990 {
1991 }
1992
~floppy_8_ssdd()1993 floppy_8_ssdd::~floppy_8_ssdd()
1994 {
1995 }
1996
setup_characteristics()1997 void floppy_8_ssdd::setup_characteristics()
1998 {
1999 form_factor = floppy_image::FF_8;
2000 tracks = 77;
2001 sides = 1;
2002 motor_always_on = true;
2003 set_rpm(360);
2004 }
2005
handled_variants(uint32_t * variants,int & var_count) const2006 void floppy_8_ssdd::handled_variants(uint32_t *variants, int &var_count) const
2007 {
2008 var_count = 0;
2009 variants[var_count++] = floppy_image::SSSD;
2010 variants[var_count++] = floppy_image::SSDD;
2011 }
2012
2013 //-------------------------------------------------
2014 // 8" double-sided double density
2015 //-------------------------------------------------
2016
floppy_8_dsdd(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2017 floppy_8_dsdd::floppy_8_dsdd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2018 floppy_image_device(mconfig, FLOPPY_8_DSDD, tag, owner, clock)
2019 {
2020 }
2021
~floppy_8_dsdd()2022 floppy_8_dsdd::~floppy_8_dsdd()
2023 {
2024 }
2025
setup_characteristics()2026 void floppy_8_dsdd::setup_characteristics()
2027 {
2028 form_factor = floppy_image::FF_8;
2029 tracks = 77;
2030 sides = 2;
2031 motor_always_on = true;
2032 set_rpm(360);
2033 }
2034
handled_variants(uint32_t * variants,int & var_count) const2035 void floppy_8_dsdd::handled_variants(uint32_t *variants, int &var_count) const
2036 {
2037 var_count = 0;
2038 variants[var_count++] = floppy_image::SSSD;
2039 variants[var_count++] = floppy_image::SSDD;
2040 variants[var_count++] = floppy_image::DSDD;
2041 }
2042
2043
2044 //**************************************************************************
2045 // SPECIFIC FLOPPY DRIVE DEFINITIONS
2046 //**************************************************************************
2047
2048 //-------------------------------------------------
2049 // epson smd-165
2050 //
2051 // track to track: 6 ms
2052 // average: 97 ms
2053 // setting time: 15 ms
2054 // motor start time: 1 s
2055 //
2056 //-------------------------------------------------
2057
epson_smd_165(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2058 epson_smd_165::epson_smd_165(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2059 floppy_image_device(mconfig, EPSON_SMD_165, tag, owner, clock)
2060 {
2061 }
2062
~epson_smd_165()2063 epson_smd_165::~epson_smd_165()
2064 {
2065 }
2066
setup_characteristics()2067 void epson_smd_165::setup_characteristics()
2068 {
2069 form_factor = floppy_image::FF_35;
2070 tracks = 40;
2071 sides = 2;
2072 set_rpm(300);
2073 }
2074
handled_variants(uint32_t * variants,int & var_count) const2075 void epson_smd_165::handled_variants(uint32_t *variants, int &var_count) const
2076 {
2077 var_count = 0;
2078 variants[var_count++] = floppy_image::SSSD;
2079 variants[var_count++] = floppy_image::DSSD;
2080 }
2081
2082 //-------------------------------------------------
2083 // epson sd-320
2084 //
2085 // track to track: 15 ms
2086 // average: 220 ms
2087 // setting time: 15 ms
2088 // head load time: 35 ms
2089 // motor start time: 0.5 s
2090 //
2091 // dip switch ss1
2092 // 1 = drive select 0
2093 // 2 = drive select 1
2094 // 3 = drive select 2
2095 // 4 = drive select 3
2096 // 5 = head load from pin 4
2097 // 6 = head load from drive select
2098 //
2099 // dic switch ss2
2100 // hs = load controlled by head-load
2101 // ms = load controlled by motor enable
2102 //
2103 // dic switch ss3
2104 // ds = in-use led by drive select
2105 // hl = in-use led by head load
2106 //
2107 //-------------------------------------------------
2108
epson_sd_320(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2109 epson_sd_320::epson_sd_320(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2110 floppy_image_device(mconfig, EPSON_SD_320, tag, owner, clock)
2111 {
2112 }
2113
~epson_sd_320()2114 epson_sd_320::~epson_sd_320()
2115 {
2116 }
2117
setup_characteristics()2118 void epson_sd_320::setup_characteristics()
2119 {
2120 form_factor = floppy_image::FF_525;
2121 tracks = 40;
2122 sides = 2;
2123 set_rpm(300);
2124 }
2125
handled_variants(uint32_t * variants,int & var_count) const2126 void epson_sd_320::handled_variants(uint32_t *variants, int &var_count) const
2127 {
2128 var_count = 0;
2129 variants[var_count++] = floppy_image::SSSD;
2130 variants[var_count++] = floppy_image::SSDD;
2131 variants[var_count++] = floppy_image::DSDD;
2132 }
2133
2134 //-------------------------------------------------
2135 // epson sd-321
2136 //
2137 // same as sd-320, but no head-load selenoid
2138 //
2139 //-------------------------------------------------
2140
epson_sd_321(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2141 epson_sd_321::epson_sd_321(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2142 floppy_image_device(mconfig, EPSON_SD_321, tag, owner, clock)
2143 {
2144 }
2145
~epson_sd_321()2146 epson_sd_321::~epson_sd_321()
2147 {
2148 }
2149
setup_characteristics()2150 void epson_sd_321::setup_characteristics()
2151 {
2152 form_factor = floppy_image::FF_525;
2153 tracks = 40;
2154 sides = 2;
2155 set_rpm(300);
2156 }
2157
handled_variants(uint32_t * variants,int & var_count) const2158 void epson_sd_321::handled_variants(uint32_t *variants, int &var_count) const
2159 {
2160 var_count = 0;
2161 variants[var_count++] = floppy_image::SSSD;
2162 variants[var_count++] = floppy_image::SSDD;
2163 variants[var_count++] = floppy_image::DSDD;
2164 }
2165
2166 //-------------------------------------------------
2167 // Sony OA-D31V
2168 //
2169 // track to track: 15 ms
2170 // average: 365 ms
2171 // setting time: 15 ms
2172 // head load time: 60 ms
2173 //
2174 //-------------------------------------------------
2175
sony_oa_d31v(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2176 sony_oa_d31v::sony_oa_d31v(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2177 floppy_image_device(mconfig, SONY_OA_D31V, tag, owner, clock)
2178 {
2179 }
2180
~sony_oa_d31v()2181 sony_oa_d31v::~sony_oa_d31v()
2182 {
2183 }
2184
setup_characteristics()2185 void sony_oa_d31v::setup_characteristics()
2186 {
2187 form_factor = floppy_image::FF_35;
2188 tracks = 70;
2189 sides = 1;
2190 dskchg_writable = true;
2191 set_rpm(600);
2192 }
2193
handled_variants(uint32_t * variants,int & var_count) const2194 void sony_oa_d31v::handled_variants(uint32_t *variants, int &var_count) const
2195 {
2196 var_count = 0;
2197 variants[var_count++] = floppy_image::SSSD;
2198 variants[var_count++] = floppy_image::SSDD;
2199 }
2200
2201 //-------------------------------------------------
2202 // Sony OA-D32W
2203 //
2204 // track to track: 12 ms
2205 // average: 350 ms
2206 // setting time: 30 ms
2207 // head load time: 60 ms
2208 // average latency: 50 ms
2209 //
2210 //-------------------------------------------------
2211
sony_oa_d32w(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2212 sony_oa_d32w::sony_oa_d32w(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2213 floppy_image_device(mconfig, SONY_OA_D32W, tag, owner, clock)
2214 {
2215 }
2216
~sony_oa_d32w()2217 sony_oa_d32w::~sony_oa_d32w()
2218 {
2219 }
2220
setup_characteristics()2221 void sony_oa_d32w::setup_characteristics()
2222 {
2223 form_factor = floppy_image::FF_35;
2224 tracks = 80;
2225 sides = 2;
2226 dskchg_writable = true;
2227 set_rpm(600);
2228 }
2229
handled_variants(uint32_t * variants,int & var_count) const2230 void sony_oa_d32w::handled_variants(uint32_t *variants, int &var_count) const
2231 {
2232 var_count = 0;
2233 variants[var_count++] = floppy_image::SSSD;
2234 variants[var_count++] = floppy_image::SSDD;
2235 variants[var_count++] = floppy_image::DSDD;
2236 }
2237
2238 //-------------------------------------------------
2239 // Sony OA-D32V
2240 //
2241 // track to track: 12 ms
2242 // average: 350 ms
2243 // setting time: 30 ms
2244 // head load time: 60 ms
2245 // average latency: 50 ms
2246 //
2247 //-------------------------------------------------
2248
sony_oa_d32v(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2249 sony_oa_d32v::sony_oa_d32v(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2250 floppy_image_device(mconfig, SONY_OA_D32V, tag, owner, clock)
2251 {
2252 }
2253
~sony_oa_d32v()2254 sony_oa_d32v::~sony_oa_d32v()
2255 {
2256 }
2257
setup_characteristics()2258 void sony_oa_d32v::setup_characteristics()
2259 {
2260 form_factor = floppy_image::FF_35;
2261 tracks = 80;
2262 sides = 1;
2263 dskchg_writable = true;
2264 set_rpm(600);
2265 }
2266
handled_variants(uint32_t * variants,int & var_count) const2267 void sony_oa_d32v::handled_variants(uint32_t *variants, int &var_count) const
2268 {
2269 var_count = 0;
2270 variants[var_count++] = floppy_image::SSSD;
2271 variants[var_count++] = floppy_image::SSDD;
2272 }
2273
2274 //-------------------------------------------------
2275 // TEAC FD-30A
2276 //
2277 // track to track: 12 ms
2278 // average: 171 ms
2279 // setting time: 15 ms
2280 // motor start time: 400 ms
2281 //
2282 //-------------------------------------------------
2283
teac_fd_30a(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2284 teac_fd_30a::teac_fd_30a(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2285 floppy_image_device(mconfig, TEAC_FD_30A, tag, owner, clock)
2286 {
2287 }
2288
~teac_fd_30a()2289 teac_fd_30a::~teac_fd_30a()
2290 {
2291 }
2292
setup_characteristics()2293 void teac_fd_30a::setup_characteristics()
2294 {
2295 form_factor = floppy_image::FF_3;
2296 tracks = 40;
2297 sides = 1;
2298 set_rpm(300);
2299 }
2300
handled_variants(uint32_t * variants,int & var_count) const2301 void teac_fd_30a::handled_variants(uint32_t *variants, int &var_count) const
2302 {
2303 var_count = 0;
2304 variants[var_count++] = floppy_image::SSSD;
2305 }
2306
2307 //-------------------------------------------------
2308 // TEAC FD-55E
2309 //
2310 // track to track: 3 ms
2311 // average: 94 ms
2312 // setting time: 15 ms
2313 // motor start time: 400 ms
2314 //
2315 //-------------------------------------------------
2316
teac_fd_55e(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2317 teac_fd_55e::teac_fd_55e(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2318 floppy_image_device(mconfig, TEAC_FD_55E, tag, owner, clock)
2319 {
2320 }
2321
~teac_fd_55e()2322 teac_fd_55e::~teac_fd_55e()
2323 {
2324 }
2325
setup_characteristics()2326 void teac_fd_55e::setup_characteristics()
2327 {
2328 form_factor = floppy_image::FF_525;
2329 tracks = 80;
2330 sides = 1;
2331 set_rpm(300);
2332 }
2333
handled_variants(uint32_t * variants,int & var_count) const2334 void teac_fd_55e::handled_variants(uint32_t *variants, int &var_count) const
2335 {
2336 var_count = 0;
2337 variants[var_count++] = floppy_image::SSSD;
2338 variants[var_count++] = floppy_image::SSDD;
2339 variants[var_count++] = floppy_image::SSQD;
2340 }
2341
2342 //-------------------------------------------------
2343 // TEAC FD-55F
2344 //
2345 // track to track: 3 ms
2346 // average: 94 ms
2347 // setting time: 15 ms
2348 // motor start time: 400 ms
2349 //
2350 //-------------------------------------------------
2351
teac_fd_55f(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2352 teac_fd_55f::teac_fd_55f(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2353 floppy_image_device(mconfig, TEAC_FD_55F, tag, owner, clock)
2354 {
2355 }
2356
~teac_fd_55f()2357 teac_fd_55f::~teac_fd_55f()
2358 {
2359 }
2360
setup_characteristics()2361 void teac_fd_55f::setup_characteristics()
2362 {
2363 form_factor = floppy_image::FF_525;
2364 tracks = 80;
2365 sides = 2;
2366 set_rpm(300);
2367 }
2368
handled_variants(uint32_t * variants,int & var_count) const2369 void teac_fd_55f::handled_variants(uint32_t *variants, int &var_count) const
2370 {
2371 var_count = 0;
2372 variants[var_count++] = floppy_image::SSSD;
2373 variants[var_count++] = floppy_image::SSDD;
2374 variants[var_count++] = floppy_image::SSQD;
2375 variants[var_count++] = floppy_image::DSSD;
2376 variants[var_count++] = floppy_image::DSDD;
2377 variants[var_count++] = floppy_image::DSQD;
2378 }
2379
2380 //-------------------------------------------------
2381 // TEAC FD-55G
2382 //
2383 // track to track: 3 ms
2384 // average: 91 ms
2385 // setting time: 15 ms
2386 // motor start time: 400 ms
2387 //
2388 //-------------------------------------------------
2389
teac_fd_55g(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2390 teac_fd_55g::teac_fd_55g(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2391 floppy_image_device(mconfig, TEAC_FD_55G, tag, owner, clock)
2392 {
2393 }
2394
~teac_fd_55g()2395 teac_fd_55g::~teac_fd_55g()
2396 {
2397 }
2398
setup_characteristics()2399 void teac_fd_55g::setup_characteristics()
2400 {
2401 form_factor = floppy_image::FF_525;
2402 tracks = 77;
2403 sides = 2;
2404 set_rpm(360);
2405 }
2406
handled_variants(uint32_t * variants,int & var_count) const2407 void teac_fd_55g::handled_variants(uint32_t *variants, int &var_count) const
2408 {
2409 var_count = 0;
2410 variants[var_count++] = floppy_image::SSSD;
2411 variants[var_count++] = floppy_image::SSDD;
2412 variants[var_count++] = floppy_image::SSQD;
2413 variants[var_count++] = floppy_image::DSDD;
2414 variants[var_count++] = floppy_image::DSQD;
2415 variants[var_count++] = floppy_image::DSHD;
2416 }
2417
2418 //-------------------------------------------------
2419 // ALPS 32551901 (black) / 32551902 (brown)
2420 //
2421 // used in the Commodoere 1541 disk drive
2422 //-------------------------------------------------
2423
alps_3255190x(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2424 alps_3255190x::alps_3255190x(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2425 floppy_image_device(mconfig, ALPS_3255190X, tag, owner, clock)
2426 {
2427 }
2428
~alps_3255190x()2429 alps_3255190x::~alps_3255190x()
2430 {
2431 }
2432
setup_characteristics()2433 void alps_3255190x::setup_characteristics()
2434 {
2435 form_factor = floppy_image::FF_525;
2436 tracks = 84;
2437 sides = 1;
2438 set_rpm(300);
2439 cyl = 34;
2440 }
2441
handled_variants(uint32_t * variants,int & var_count) const2442 void alps_3255190x::handled_variants(uint32_t *variants, int &var_count) const
2443 {
2444 var_count = 0;
2445 variants[var_count++] = floppy_image::SSSD;
2446 }
2447
2448 //-------------------------------------------------
2449 // IBM 6360 -- 8" single-sided single density
2450 //-------------------------------------------------
2451
ibm_6360(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2452 ibm_6360::ibm_6360(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2453 floppy_image_device(mconfig, IBM_6360, tag, owner, clock)
2454 {
2455 }
2456
~ibm_6360()2457 ibm_6360::~ibm_6360()
2458 {
2459 }
2460
setup_characteristics()2461 void ibm_6360::setup_characteristics()
2462 {
2463 form_factor = floppy_image::FF_8;
2464 tracks = 77;
2465 sides = 1;
2466 motor_always_on = true;
2467 has_trk00_sensor = false;
2468 set_rpm(360);
2469 }
2470
handled_variants(uint32_t * variants,int & var_count) const2471 void ibm_6360::handled_variants(uint32_t *variants, int &var_count) const
2472 {
2473 var_count = 0;
2474 variants[var_count++] = floppy_image::SSSD;
2475 }
2476