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