1 // license:BSD-3-Clause
2 // copyright-holders:Nathan Woods, Olivier Galibert, Miodrag Milanovic
3 /*********************************************************************
4 
5     floppy.h
6 
7 *********************************************************************/
8 
9 #ifndef MAME_DEVICES_IMAGEDEV_FLOPPY_H
10 #define MAME_DEVICES_IMAGEDEV_FLOPPY_H
11 
12 #pragma once
13 
14 #include "formats/flopimg.h"
15 #include "formats/d88_dsk.h"
16 #include "formats/dfi_dsk.h"
17 #include "formats/hxchfe_dsk.h"
18 #include "formats/hxcmfm_dsk.h"
19 #include "formats/imd_dsk.h"
20 #include "formats/ipf_dsk.h"
21 #include "formats/mfi_dsk.h"
22 #include "formats/td0_dsk.h"
23 #include "formats/cqm_dsk.h"
24 #include "formats/dsk_dsk.h"
25 #include "sound/samples.h"
26 #include "softlist_dev.h"
27 
28 #define DECLARE_FLOPPY_FORMATS(_name) \
29 	static const floppy_format_type _name []
30 
31 #define FLOPPY_FORMATS_MEMBER(_member) \
32 	const floppy_format_type _member [] = {
33 #define FLOPPY_FORMATS_END0 \
34 		, \
35 		nullptr };
36 #define FLOPPY_FORMATS_END \
37 		, \
38 		FLOPPY_D88_FORMAT, \
39 		FLOPPY_DFI_FORMAT, \
40 		FLOPPY_HFE_FORMAT, \
41 		FLOPPY_IMD_FORMAT, \
42 		FLOPPY_IPF_FORMAT, \
43 		FLOPPY_MFI_FORMAT, \
44 		FLOPPY_MFM_FORMAT, \
45 		FLOPPY_TD0_FORMAT, \
46 		FLOPPY_CQM_FORMAT, \
47 		FLOPPY_DSK_FORMAT \
48 	FLOPPY_FORMATS_END0
49 
50 class floppy_sound_device;
51 
52 /***************************************************************************
53     TYPE DEFINITIONS
54 ***************************************************************************/
55 
56 class floppy_image_device : public device_t,
57 							public device_image_interface
58 {
59 public:
60 	typedef delegate<image_init_result (floppy_image_device *)> load_cb;
61 	typedef delegate<void (floppy_image_device *)> unload_cb;
62 	typedef delegate<void (floppy_image_device *, int)> index_pulse_cb;
63 	typedef delegate<void (floppy_image_device *, int)> ready_cb;
64 	typedef delegate<void (floppy_image_device *, int)> wpt_cb;
65 	typedef delegate<void (floppy_image_device *, int)> led_cb;
66 
67 	// construction/destruction
68 	virtual ~floppy_image_device();
69 
70 	virtual void handled_variants(uint32_t *variants, int &var_count) const = 0;
71 
72 	void set_formats(const floppy_format_type *formats);
73 	floppy_image_format_t *get_formats() const;
74 	floppy_image_format_t *get_load_format() const;
75 	floppy_image_format_t *identify(std::string filename);
76 	void set_rpm(float rpm);
77 
78 	// image-level overrides
79 	virtual image_init_result call_load() override;
80 	virtual void call_unload() override;
81 	virtual image_init_result call_create(int format_type, util::option_resolution *format_options) override;
82 	virtual const char *image_interface() const noexcept override = 0;
image_type()83 	virtual iodevice_t image_type() const noexcept override { return IO_FLOPPY; }
84 
is_readable()85 	virtual bool is_readable()  const noexcept override { return true; }
is_writeable()86 	virtual bool is_writeable() const noexcept override { return true; }
is_creatable()87 	virtual bool is_creatable() const noexcept override { return true; }
must_be_loaded()88 	virtual bool must_be_loaded() const noexcept override { return false; }
is_reset_on_load()89 	virtual bool is_reset_on_load() const noexcept override { return false; }
file_extensions()90 	virtual const char *file_extensions() const noexcept override { return extension_list; }
91 	void setup_write(floppy_image_format_t *output_format);
92 
93 	void setup_load_cb(load_cb cb);
94 	void setup_unload_cb(unload_cb cb);
95 	void setup_index_pulse_cb(index_pulse_cb cb);
96 	void setup_ready_cb(ready_cb cb);
97 	void setup_wpt_cb(wpt_cb cb);
98 	void setup_led_cb(led_cb cb);
99 
get_buffer()100 	std::vector<uint32_t> &get_buffer() { return image->get_buffer(cyl, ss, subcyl); }
get_cyl()101 	int get_cyl() { return cyl; }
102 
103 	void mon_w(int state);
104 	bool ready_r();
105 	void set_ready(bool state);
106 	double get_pos();
107 
wpt_r()108 	bool wpt_r() { return wpt; }
dskchg_r()109 	int dskchg_r() { return dskchg; }
trk00_r()110 	bool trk00_r() { return (has_trk00_sensor ? (cyl != 0) : 1); }
idx_r()111 	int idx_r() { return idx; }
mon_r()112 	int mon_r() { return mon; }
ss_r()113 	bool ss_r() { return ss; }
114 	bool twosid_r();
115 
116 	void seek_phase_w(int phases);
117 	void stp_w(int state);
dir_w(int state)118 	void dir_w(int state) { dir = state; }
ss_w(int state)119 	void ss_w(int state) { if (sides > 1) ss = state; }
inuse_w(int state)120 	void inuse_w(int state) { }
dskchg_w(int state)121 	void dskchg_w(int state) { if (dskchg_writable) dskchg = state; }
ds_w(int state)122 	void ds_w(int state) { ds = state; check_led(); }
123 
124 	void index_resync();
125 	attotime time_next_index();
126 	attotime get_next_transition(const attotime &from_when);
127 	void write_flux(const attotime &start, const attotime &end, int transition_count, const attotime *transitions);
128 	void set_write_splice(const attotime &when);
get_sides()129 	int get_sides() { return sides; }
130 	uint32_t get_form_factor() const;
131 	uint32_t get_variant() const;
132 
133 	static const floppy_format_type default_floppy_formats[];
134 
135 	// Enable sound
enable_sound(bool doit)136 	void    enable_sound(bool doit) { m_make_sound = doit; }
137 
138 protected:
139 	floppy_image_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
140 
141 	// device-level overrides
142 	virtual void device_start() override;
143 	virtual void device_reset() override;
144 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
145 
146 	virtual void device_add_mconfig(machine_config &config) override;
147 
148 	// device_image_interface implementation
get_software_list_loader()149 	virtual const software_list_loader &get_software_list_loader() const override { return image_software_list_loader::instance(); }
150 
151 	virtual void setup_characteristics() = 0;
152 
153 	void init_floppy_load(bool write_supported);
154 
155 	floppy_image_format_t *input_format;
156 	floppy_image_format_t *output_format;
157 	std::unique_ptr<floppy_image> image;
158 	char                  extension_list[256];
159 	floppy_image_format_t *fif_list;
160 	emu_timer             *index_timer;
161 
162 	/* Physical characteristics, filled by setup_characteristics */
163 	int tracks; /* addressable tracks */
164 	int sides;  /* number of heads */
165 	uint32_t form_factor; /* 3"5, 5"25, etc */
166 	bool motor_always_on;
167 	bool dskchg_writable;
168 	bool has_trk00_sensor;
169 
170 	int drive_index;
171 
172 	/* state of input lines */
173 	int dir;  /* direction */
174 	int stp;  /* step */
175 	int wtg;  /* write gate */
176 	int mon;  /* motor on */
177 	int ss; /* side select */
178 	int ds; /* drive select */
179 
180 	/* state of output lines */
181 	int idx;  /* index pulse */
182 	int wpt;  /* write protect */
183 	int rdy;  /* ready */
184 	int dskchg;     /* disk changed */
185 	bool ready;
186 
187 	/* rotation per minute => gives index pulse frequency */
188 	float rpm;
189 	int floppy_ratio_1; // rpm/300*1000
190 
191 	attotime revolution_start_time, rev_time;
192 	uint32_t revolution_count;
193 	int cyl, subcyl;
194 
195 	/* Current floppy zone cache */
196 	attotime cache_start_time, cache_end_time, cache_weak_start;
197 	int cache_index;
198 	u32 cache_entry;
199 	bool cache_weak;
200 
201 	bool image_dirty;
202 	int ready_counter;
203 
204 	load_cb cur_load_cb;
205 	unload_cb cur_unload_cb;
206 	index_pulse_cb cur_index_pulse_cb;
207 	ready_cb cur_ready_cb;
208 	wpt_cb cur_wpt_cb;
209 	led_cb cur_led_cb;
210 
211 	void check_led();
212 	uint32_t find_position(attotime &base, const attotime &when);
213 	int find_index(uint32_t position, const std::vector<uint32_t> &buf) const;
214 	bool test_track_last_entry_warps(const std::vector<uint32_t> &buf) const;
215 	attotime position_to_time(const attotime &base, int position) const;
216 
217 	void write_zone(uint32_t *buf, int &cells, int &index, uint32_t spos, uint32_t epos, uint32_t mg);
218 	void commit_image();
219 
220 	u32 hash32(u32 val) const;
221 
222 	void cache_clear();
223 	void cache_fill_index(const std::vector<uint32_t> &buf, int &index, attotime &base);
224 	void cache_fill(const attotime &when);
225 	void cache_weakness_setup();
226 
227 	// Sound
228 	bool    m_make_sound;
229 	floppy_sound_device* m_sound_out;
230 };
231 
232 #define DECLARE_FLOPPY_IMAGE_DEVICE(Type, Name, Interface) \
233 	class Name : public floppy_image_device { \
234 	public: \
235 		Name(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); \
236 		virtual ~Name(); \
237 		virtual void handled_variants(uint32_t *variants, int &var_count) const override; \
238 		virtual const char *image_interface() const noexcept override { return Interface; } \
239 	protected: \
240 		virtual void setup_characteristics() override; \
241 	}; \
242 	DECLARE_DEVICE_TYPE(Type, Name)
243 
244 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_3_SSDD,       floppy_3_ssdd,       "floppy_3")
245 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_3_DSDD,       floppy_3_dsdd,       "floppy_3")
246 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_35_SSDD,      floppy_35_ssdd,      "floppy_3_5")
247 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_35_DD,        floppy_35_dd,        "floppy_3_5")
248 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_35_HD,        floppy_35_hd,        "floppy_3_5")
249 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_35_ED,        floppy_35_ed,        "floppy_3_5")
250 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_525_SSSD_35T, floppy_525_sssd_35t, "floppy_5_25")
251 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_525_SD_35T,   floppy_525_sd_35t,   "floppy_5_25")
252 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_525_SSSD,     floppy_525_sssd,     "floppy_5_25")
253 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_525_SD,       floppy_525_sd,       "floppy_5_25")
254 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_525_SSDD,     floppy_525_ssdd,     "floppy_5_25")
255 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_525_DD,       floppy_525_dd,       "floppy_5_25")
256 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_525_SSQD,     floppy_525_ssqd,     "floppy_5_25")
257 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_525_QD,       floppy_525_qd,       "floppy_5_25")
258 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_525_HD,       floppy_525_hd,       "floppy_5_25")
259 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_8_SSSD,       floppy_8_sssd,       "floppy_8")
260 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_8_DSSD,       floppy_8_dssd,       "floppy_8")
261 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_8_SSDD,       floppy_8_ssdd,       "floppy_8")
262 DECLARE_FLOPPY_IMAGE_DEVICE(FLOPPY_8_DSDD,       floppy_8_dsdd,       "floppy_8")
263 DECLARE_FLOPPY_IMAGE_DEVICE(EPSON_SMD_165,       epson_smd_165,       "floppy_3_5")
264 DECLARE_FLOPPY_IMAGE_DEVICE(EPSON_SD_320,        epson_sd_320,        "floppy_5_25")
265 DECLARE_FLOPPY_IMAGE_DEVICE(EPSON_SD_321,        epson_sd_321,        "floppy_5_25")
266 DECLARE_FLOPPY_IMAGE_DEVICE(SONY_OA_D31V,        sony_oa_d31v,        "floppy_3_5")
267 DECLARE_FLOPPY_IMAGE_DEVICE(SONY_OA_D32W,        sony_oa_d32w,        "floppy_3_5")
268 DECLARE_FLOPPY_IMAGE_DEVICE(SONY_OA_D32V,        sony_oa_d32v,        "floppy_3_5")
269 DECLARE_FLOPPY_IMAGE_DEVICE(TEAC_FD_30A,         teac_fd_30a,         "floppy_3")
270 DECLARE_FLOPPY_IMAGE_DEVICE(TEAC_FD_55E,         teac_fd_55e,         "floppy_5_25")
271 DECLARE_FLOPPY_IMAGE_DEVICE(TEAC_FD_55F,         teac_fd_55f,         "floppy_5_25")
272 DECLARE_FLOPPY_IMAGE_DEVICE(TEAC_FD_55G,         teac_fd_55g,         "floppy_5_25")
273 DECLARE_FLOPPY_IMAGE_DEVICE(ALPS_3255190X,       alps_3255190x,       "floppy_5_25")
274 DECLARE_FLOPPY_IMAGE_DEVICE(IBM_6360,            ibm_6360,            "floppy_8")
275 
DECLARE_DEVICE_TYPE(FLOPPYSOUND,floppy_sound_device)276 DECLARE_DEVICE_TYPE(FLOPPYSOUND, floppy_sound_device)
277 
278 
279 /*
280     Floppy drive sound
281 */
282 
283 class floppy_sound_device : public samples_device
284 {
285 public:
286 	floppy_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
287 	void motor(bool on, bool withdisk);
288 	void step(int track);
289 	bool samples_loaded() { return m_loaded; }
290 	void register_for_save_states();
291 
292 protected:
293 	void device_start() override;
294 
295 private:
296 	// device_sound_interface overrides
297 	virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
298 	sound_stream*   m_sound;
299 
300 	int         m_step_base;
301 	int         m_spin_samples;
302 	int         m_step_samples;
303 	int         m_spin_samplepos;
304 	int         m_step_samplepos;
305 	int         m_seek_sound_timeout;
306 	int         m_zones;
307 	int         m_spin_playback_sample;
308 	int         m_step_playback_sample;
309 	int         m_seek_playback_sample;
310 	bool        m_motor_on;
311 	bool        m_with_disk;
312 	bool        m_loaded;
313 	double      m_seek_pitch;
314 	double      m_seek_samplepos;
315 };
316 
317 
318 class floppy_connector: public device_t,
319 						public device_slot_interface
320 {
321 public:
322 	template <typename T>
323 	floppy_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, const floppy_format_type formats[], bool fixed = false)
324 		: floppy_connector(mconfig, tag, owner, 0)
325 	{
326 		option_reset();
327 		opts(*this);
328 		set_default_option(dflt);
329 		set_fixed(fixed);
330 		set_formats(formats);
331 	}
floppy_connector(const machine_config & mconfig,const char * tag,device_t * owner,const char * option,const device_type & devtype,bool is_default,const floppy_format_type formats[])332 	floppy_connector(const machine_config &mconfig, const char *tag, device_t *owner, const char *option, const device_type &devtype, bool is_default, const floppy_format_type formats[])
333 		: floppy_connector(mconfig, tag, owner, 0)
334 	{
335 		option_reset();
336 		option_add(option, devtype);
337 		if(is_default)
338 			set_default_option(option);
339 		set_fixed(false);
340 		set_formats(formats);
341 	}
342 	floppy_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
343 	virtual ~floppy_connector();
344 
345 	void set_formats(const floppy_format_type formats[]);
346 	floppy_image_device *get_device();
enable_sound(bool doit)347 	void enable_sound(bool doit) { m_enable_sound = doit; }
348 
349 protected:
350 	virtual void device_start() override;
351 	virtual void device_config_complete() override;
352 
353 private:
354 	const floppy_format_type *formats;
355 	bool m_enable_sound;
356 };
357 
358 
359 // device type definition
360 DECLARE_DEVICE_TYPE(FLOPPY_CONNECTOR, floppy_connector)
361 
362 extern template class device_finder<floppy_connector, false>;
363 extern template class device_finder<floppy_connector, true>;
364 
365 #endif // MAME_DEVICES_IMAGEDEV_FLOPPY_H
366