summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/imagedev/flopdrv.h
blob: de01485ba97a28cec8390b51edf7065315a2e0c0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// license:BSD-3-Clause
// copyright-holders:Nathan Woods, Miodrag Milanovic
/* flopdrv provides simple emulation of a disc drive */
/* the 8271, upd765 and wd179x use this */

#ifndef __FLOPDRV_H__
#define __FLOPDRV_H__

#include "formats/flopimg.h"

#define FLOPPY_TYPE_REGULAR 0
#define FLOPPY_TYPE_APPLE   1
#define FLOPPY_TYPE_SONY    2

#define FLOPPY_DRIVE_2_8_INCH   1
#define FLOPPY_DRIVE_3_INCH     2
#define FLOPPY_DRIVE_3_5_INCH   3
#define FLOPPY_DRIVE_5_25_INCH  4
#define FLOPPY_DRIVE_8_INCH     5

// Maximum supported density
#define FLOPPY_DRIVE_SD 1
#define FLOPPY_DRIVE_DD 2
#define FLOPPY_DRIVE_QD 3
#define FLOPPY_DRIVE_HD 4
#define FLOPPY_DRIVE_ED 5

#define FLOPPY_STANDARD_3_SSDD       { FLOPPY_DRIVE_3_INCH,    1, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_3_DSDD       { FLOPPY_DRIVE_3_INCH,    2, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_3_5_SSDD     { FLOPPY_DRIVE_3_5_INCH,  1, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_3_5_DSDD     { FLOPPY_DRIVE_3_5_INCH,  2, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_3_5_DSHD     { FLOPPY_DRIVE_3_5_INCH,  2, 83, FLOPPY_DRIVE_HD }
#define FLOPPY_STANDARD_3_5_DSED     { FLOPPY_DRIVE_3_5_INCH,  2, 83, FLOPPY_DRIVE_ED }
#define FLOPPY_STANDARD_5_25_SSSD_35 { FLOPPY_DRIVE_5_25_INCH, 1, 37, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_DSSD_35 { FLOPPY_DRIVE_5_25_INCH, 2, 37, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_SSSD    { FLOPPY_DRIVE_5_25_INCH, 1, 42, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_DSSD    { FLOPPY_DRIVE_5_25_INCH, 2, 42, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_SSDD_40 { FLOPPY_DRIVE_5_25_INCH, 1, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_SSDD_80 { FLOPPY_DRIVE_5_25_INCH, 1, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_DSDD_40 { FLOPPY_DRIVE_5_25_INCH, 2, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_SSDD    { FLOPPY_DRIVE_5_25_INCH, 1, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_DSDD    { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_DSQD    { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_QD }
#define FLOPPY_STANDARD_5_25_DSHD    { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_HD }
#define FLOPPY_STANDARD_8_SSSD       { FLOPPY_DRIVE_8_INCH,    1, 77, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_8_DSSD       { FLOPPY_DRIVE_8_INCH,    2, 77, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_8_DSDD       { FLOPPY_DRIVE_8_INCH,    2, 77, FLOPPY_DRIVE_DD }

/***************************************************************************
    TYPE DEFINITIONS
***************************************************************************/

// ======================> floppy_type_t

struct floppy_type_t
{
	UINT8 media_size;
	UINT8 head_number;
	UINT8 max_track_number;
	UINT8 max_density;
};

// ======================> floppy_interface

struct floppy_interface
{
	floppy_type_t floppy_type;
	const struct FloppyFormat *formats;
	const char *interface;
};

struct chrn_id
{
	unsigned char C;
	unsigned char H;
	unsigned char R;
	unsigned char N;
	int data_id;            // id for read/write data command
	unsigned long flags;
};

/* set if drive is ready */
#define FLOPPY_DRIVE_READY                      0x0010
/* set if index has just occurred */
#define FLOPPY_DRIVE_INDEX                      0x0020

#define MCFG_LEGACY_FLOPPY_IDX_CB(_devcb) \
	devcb = &legacy_floppy_image_device::set_out_idx_func(*device, DEVCB_##_devcb);

class legacy_floppy_image_device :  public device_t,
									public device_image_interface
{
public:
	// construction/destruction
	legacy_floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
	legacy_floppy_image_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
	~legacy_floppy_image_device();

	static void static_set_floppy_config(device_t &device, const floppy_interface *config) { downcast<legacy_floppy_image_device &>(device).m_config = config; }
	template<class _Object> static devcb_base &set_out_idx_func(device_t &device, _Object object) { return downcast<legacy_floppy_image_device &>(device).m_out_idx_func.set_callback(object); }

	virtual bool call_load() override;
	virtual bool call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry) override {   return load_software(swlist, swname, start_entry); }
	virtual bool call_create(int format_type, option_resolution *format_options) override;
	virtual void call_unload() override;

	virtual iodevice_t image_type() const override { return IO_FLOPPY; }

	virtual bool is_readable()  const override { return 1; }
	virtual bool is_writeable() const override { return 1; }
	virtual bool is_creatable() const override;
	virtual bool must_be_loaded() const override { return 0; }
	virtual bool is_reset_on_load() const override { return 0; }
	virtual const char *image_interface() const override;
	virtual const char *file_extensions() const override { return m_extension_list; }
	virtual const option_guide *create_option_guide() const override { return floppy_option_guide; }

	floppy_image_legacy *flopimg_get_image();
	void floppy_drive_set_geometry(floppy_type_t type);
	void floppy_drive_set_flag_state(int flag, int state);
	void floppy_drive_set_ready_state(int state, int flag);
	int floppy_drive_get_flag_state(int flag);
	void floppy_drive_seek(signed int signed_tracks);
	int floppy_drive_get_next_id(int side, chrn_id *id);
	void floppy_drive_read_track_data_info_buffer(int side, void *ptr, int *length );
	void floppy_drive_write_track_data_info_buffer(int side, const void *ptr, int *length );
	void floppy_drive_format_sector(int side, int sector_index,int c,int h, int r, int n, int filler);
	void floppy_drive_read_sector_data(int side, int index1, void *ptr, int length);
	void floppy_drive_write_sector_data(int side, int index1, const void *ptr,int length, int ddam);
	void floppy_install_load_proc(void (*proc)(device_image_interface &image));
	void floppy_install_unload_proc(void (*proc)(device_image_interface &image));
	void floppy_drive_set_index_pulse_callback(void (*callback)(device_t *controller,device_t *image, int state));
	int floppy_drive_get_current_track();
	UINT64 floppy_drive_get_current_track_size(int head);
	void floppy_drive_set_rpm(float rpm);
	void floppy_drive_set_controller(device_t *controller);
	int floppy_get_drive_type();
	void floppy_set_type(int ftype);
	WRITE_LINE_MEMBER( floppy_ds0_w );
	WRITE_LINE_MEMBER( floppy_ds1_w );
	WRITE_LINE_MEMBER( floppy_ds2_w );
	WRITE_LINE_MEMBER( floppy_ds3_w );
	WRITE8_MEMBER( floppy_ds_w );
	WRITE_LINE_MEMBER( floppy_mon_w );
	WRITE_LINE_MEMBER( floppy_drtn_w );
	WRITE_LINE_MEMBER( floppy_wtd_w );
	WRITE_LINE_MEMBER( floppy_stp_w );
	WRITE_LINE_MEMBER( floppy_wtg_w );
	READ_LINE_MEMBER( floppy_wpt_r );
	READ_LINE_MEMBER( floppy_tk00_r );
	READ_LINE_MEMBER( floppy_dskchg_r );
	READ_LINE_MEMBER( floppy_twosid_r );
	READ_LINE_MEMBER( floppy_index_r );
	READ_LINE_MEMBER( floppy_ready_r );


private:
	int flopimg_get_sectors_per_track(int side);
	void flopimg_get_id_callback(chrn_id *id, int id_index, int side);
	void log_readwrite(const char *name, int head, int track, int sector, const char *buf, int length);
	void floppy_drive_set_geometry_absolute(int tracks, int sides);
	TIMER_CALLBACK_MEMBER(floppy_drive_index_callback);
	void floppy_drive_init();
	void floppy_drive_index_func();
	int internal_floppy_device_load(int create_format, option_resolution *create_args);
	TIMER_CALLBACK_MEMBER( set_wpt );

protected:
	// device overrides
	virtual void device_config_complete() override;
	virtual void device_start() override;

	/* callbacks */
	devcb_write_line m_out_idx_func;

	/* state of input lines */
	int m_drtn; /* direction */
	int m_stp;  /* step */
	int m_wtg;  /* write gate */
	int m_mon;  /* motor on */

	/* state of output lines */
	int m_idx;  /* index pulse */
	int m_tk00; /* track 00 */
	int m_wpt;  /* write protect */
	int m_rdy;  /* ready */
	int m_dskchg;     /* disk changed */

	/* drive select logic */
	int m_drive_id;
	int m_active;

	const floppy_interface  *m_config;

	/* flags */
	int m_flags;
	/* maximum track allowed */
	int m_max_track;
	/* num sides */
	int m_num_sides;
	/* current track - this may or may not relate to the present cylinder number
	stored by the fdc */
	int m_current_track;

	/* index pulse timer */
	emu_timer   *m_index_timer;
	/* index pulse callback */
	void    (*m_index_pulse_callback)(device_t *controller,device_t *image, int state);
	/* rotation per minute => gives index pulse frequency */
	float m_rpm;

	int m_id_index;

	device_t *m_controller;

	floppy_image_legacy *m_floppy;
	int m_track;
	void (*m_load_proc)(device_image_interface &image);
	void (*m_unload_proc)(device_image_interface &image);
	int m_floppy_drive_type;

	char            m_extension_list[256];
};

// device type definition
extern const device_type LEGACY_FLOPPY;



legacy_floppy_image_device *floppy_get_device(running_machine &machine,int drive);
legacy_floppy_image_device *floppy_get_device_by_type(running_machine &machine,int ftype,int drive);
int floppy_get_drive(device_t *image);
int floppy_get_drive_by_type(legacy_floppy_image_device *image,int ftype);
int floppy_get_count(running_machine &machine);


/***************************************************************************
    DEVICE CONFIGURATION MACROS
***************************************************************************/
#define FLOPPY_0 "floppy0"
#define FLOPPY_1 "floppy1"
#define FLOPPY_2 "floppy2"
#define FLOPPY_3 "floppy3"


#define MCFG_LEGACY_FLOPPY_CONFIG(_config) \
	legacy_floppy_image_device::static_set_floppy_config(*device, &(_config));

#define MCFG_LEGACY_FLOPPY_DRIVE_ADD(_tag, _config) \
	MCFG_DEVICE_ADD(_tag, LEGACY_FLOPPY, 0)         \
	MCFG_LEGACY_FLOPPY_CONFIG(_config)

#define MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(_config)    \
	MCFG_DEVICE_ADD(FLOPPY_0, LEGACY_FLOPPY, 0)     \
	MCFG_LEGACY_FLOPPY_CONFIG(_config) \
	MCFG_DEVICE_ADD(FLOPPY_1, LEGACY_FLOPPY, 0)     \
	MCFG_LEGACY_FLOPPY_CONFIG(_config) \
	MCFG_DEVICE_ADD(FLOPPY_2, LEGACY_FLOPPY, 0)     \
	MCFG_LEGACY_FLOPPY_CONFIG(_config) \
	MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)     \
	MCFG_LEGACY_FLOPPY_CONFIG(_config)

#define MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(_config)    \
	MCFG_DEVICE_ADD(FLOPPY_0, LEGACY_FLOPPY, 0)     \
	MCFG_LEGACY_FLOPPY_CONFIG(_config) \
	MCFG_DEVICE_ADD(FLOPPY_1, LEGACY_FLOPPY, 0)     \
	MCFG_LEGACY_FLOPPY_CONFIG(_config)

#endif /* __FLOPDRV_H__ */