1 // license:GPL-2.0+
2 // copyright-holders:Juergen Buchmueller
3 /***************************************************************************
4 
5     Atari 400/800
6 
7     Floppy Disk Controller code
8 
9     Juergen Buchmueller, June 1998
10 
11 ***************************************************************************/
12 
13 #include "emu.h"
14 #include "atarifdc.h"
15 
16 #include "formats/atari_dsk.h"
17 
18 #include <cctype>
19 
20 
21 #define VERBOSE_SERIAL  0
22 #define VERBOSE_CHKSUM  0
23 
24 /*************************************
25  *
26  *  Disk stuff
27  *
28  *************************************/
29 
30 #define FORMAT_XFD  0
31 #define FORMAT_ATR  1
32 #define FORMAT_DSK  2
33 
34 /*****************************************************************************
35  * This is the structure I used in my own Atari 800 emulator some years ago
36  * Though it's a bit overloaded, I used it as it is the maximum of all
37  * supported formats:
38  * XFD no header at all
39  * ATR 16 bytes header
40  * DSK this struct
41  * It is used to determine the format of a XFD image by it's size only
42  *****************************************************************************/
43 
44 struct atari_dsk_format
45 {
46 	uint8_t density;
47 	uint8_t tracks;
48 	uint8_t door;
49 	uint8_t sta1;
50 	uint8_t spt;
51 	uint8_t doublesided;
52 	uint8_t highdensity;
53 	uint8_t seclen_hi;
54 	uint8_t seclen_lo;
55 	uint8_t status;
56 	uint8_t sta2;
57 	uint8_t sta3;
58 	uint8_t sta4;
59 	uint8_t cr;
60 	uint8_t info[65+1];
61 };
62 
63 /* combined with the size the image should have */
64 struct xfd_format
65 {
66 	int size;
67 	atari_dsk_format dsk;
68 };
69 
70 /* here's a table of known xfd formats */
71 static const xfd_format xfd_formats[] =
72 {
73 	{35 * 18 * 1 * 128,                 {0,35,1,0,18,0,0,0,128,255,0,0,0,13,"35 SS/SD"}},
74 	{35 * 26 * 1 * 128,                 {1,35,1,0,26,0,4,0,128,255,0,0,0,13,"35 SS/MD"}},
75 	{(35 * 18 * 1 - 3) * 256 + 3 * 128, {2,35,1,0,18,0,4,1,  0,255,0,0,0,13,"35 SS/DD"}},
76 	{40 * 18 * 1 * 128,                 {0,40,1,0,18,0,0,0,128,255,0,0,0,13,"40 SS/SD"}},
77 	{40 * 26 * 1 * 128,                 {1,40,1,0,26,0,4,0,128,255,0,0,0,13,"40 SS/MD"}},
78 	{(40 * 18 * 1 - 3) * 256 + 3 * 128, {2,40,1,0,18,0,4,1,  0,255,0,0,0,13,"40 SS/DD"}},
79 	{40 * 18 * 2 * 128,                 {0,40,1,0,18,1,0,0,128,255,0,0,0,13,"40 DS/SD"}},
80 	{40 * 26 * 2 * 128,                 {1,40,1,0,26,1,4,0,128,255,0,0,0,13,"40 DS/MD"}},
81 	{(40 * 18 * 2 - 3) * 256 + 3 * 128, {2,40,1,0,18,1,4,1,  0,255,0,0,0,13,"40 DS/DD"}},
82 	{77 * 18 * 1 * 128,                 {0,77,1,0,18,0,0,0,128,255,0,0,0,13,"77 SS/SD"}},
83 	{77 * 26 * 1 * 128,                 {1,77,1,0,26,0,4,0,128,255,0,0,0,13,"77 SS/MD"}},
84 	{(77 * 18 * 1 - 3) * 256 + 3 * 128, {2,77,1,0,18,0,4,1,  0,255,0,0,0,13,"77 SS/DD"}},
85 	{77 * 18 * 2 * 128,                 {0,77,1,0,18,1,0,0,128,255,0,0,0,13,"77 DS/SD"}},
86 	{77 * 26 * 2 * 128,                 {1,77,1,0,26,1,4,0,128,255,0,0,0,13,"77 DS/MD"}},
87 	{(77 * 18 * 2 - 3) * 256 + 3 * 128, {2,77,1,0,18,1,4,1,  0,255,0,0,0,13,"77 DS/DD"}},
88 	{80 * 18 * 2 * 128,                 {0,80,1,0,18,1,0,0,128,255,0,0,0,13,"80 DS/SD"}},
89 	{80 * 26 * 2 * 128,                 {1,80,1,0,26,1,4,0,128,255,0,0,0,13,"80 DS/MD"}},
90 	{(80 * 18 * 2 - 3) * 256 + 3 * 128, {2,80,1,0,18,1,4,1,  0,255,0,0,0,13,"80 DS/DD"}},
91 	{0, {0,}}
92 };
93 
94 /*****************************************************************************
95  *
96  * Open a floppy image for drive 'drive' if it is not yet openend
97  * and a name was given. Determine the image geometry depending on the
98  * type of image and store the results into the global drv[] structure
99  *
100  *****************************************************************************/
101 
102 #define MAXSIZE 5760 * 256 + 80
_atari_load_proc(device_image_interface & image,bool is_created)103 static void _atari_load_proc(device_image_interface &image, bool is_created)
104 {
105 	atari_fdc_device *atarifdc = static_cast<atari_fdc_device *>(image.device().owner());
106 	atarifdc->atari_load_proc(image, is_created);
107 }
108 
atari_load_proc(device_image_interface & image,bool is_created)109 void atari_fdc_device::atari_load_proc(device_image_interface &image, bool is_created)
110 {
111 	int id = -1;
112 
113 	for (int i = 0; i < 4; i++)
114 	{
115 		if (&image.device() == m_floppy[i].target())
116 		{
117 			id = i;
118 			break;
119 		}
120 	}
121 
122 	if (id == -1)
123 		return;
124 
125 	m_drv[id].image = std::make_unique<uint8_t[]>(MAXSIZE);
126 	if (!m_drv[id].image)
127 		return;
128 
129 	/* tell whether the image is writable */
130 	m_drv[id].mode = !image.is_readonly();
131 	/* set up image if it has been created */
132 	if (is_created)
133 	{
134 		int sector;
135 		char buff[256];
136 		memset(buff, 0, sizeof(buff));
137 		/* default to 720 sectors */
138 		for( sector = 0; sector < 720; sector++ )
139 			image.fwrite(buff, 256);
140 		image.fseek(0, SEEK_SET);
141 	}
142 
143 	int size = image.fread(m_drv[id].image.get(), MAXSIZE);
144 
145 	if( size <= 0 )
146 	{
147 		m_drv[id].image = nullptr;
148 		return;
149 	}
150 
151 
152 	/* re allocate the buffer; we don't want to be too lazy ;) */
153 	//m_drv[id].image = (uint8_t*)image.image_realloc(m_drv[id].image, size);
154 
155 	// hack alert, this means we can only load ATR via the softlist at the moment, image.filetype returns "" :/
156 	bool is_softlist_entry = image.loaded_through_softlist();
157 
158 	/* no extension: assume XFD format (no header) */
159 	if (image.is_filetype("") && !is_softlist_entry)
160 	{
161 		m_drv[id].type = FORMAT_XFD;
162 		m_drv[id].header_skip = 0;
163 	}
164 	else
165 	/* XFD extension */
166 	if( image.is_filetype("xfd") )
167 	{
168 		m_drv[id].type = FORMAT_XFD;
169 		m_drv[id].header_skip = 0;
170 	}
171 	else
172 	/* ATR extension */
173 	if( image.is_filetype("atr") || is_softlist_entry)
174 	{
175 		m_drv[id].type = FORMAT_ATR;
176 		m_drv[id].header_skip = 16;
177 	}
178 	else
179 	/* DSK extension */
180 	if( image.is_filetype("dsk") )
181 	{
182 		m_drv[id].type = FORMAT_DSK;
183 		m_drv[id].header_skip = sizeof(atari_dsk_format);
184 	}
185 	else
186 	{
187 		m_drv[id].type = FORMAT_XFD;
188 		m_drv[id].header_skip = 0;
189 	}
190 
191 	if( m_drv[id].type == FORMAT_ATR &&
192 		(m_drv[id].image[0] != 0x96 || m_drv[id].image[1] != 0x02) )
193 	{
194 		m_drv[id].type = FORMAT_XFD;
195 		m_drv[id].header_skip = 0;
196 	}
197 
198 
199 	int i;
200 	switch (m_drv[id].type)
201 	{
202 	/* XFD or unknown format: find a matching size from the table */
203 	case FORMAT_XFD:
204 		for( i = 0; xfd_formats[i].size; i++ )
205 		{
206 			if( size == xfd_formats[i].size )
207 			{
208 				m_drv[id].density = xfd_formats[i].dsk.density;
209 				m_drv[id].tracks = xfd_formats[i].dsk.tracks;
210 				m_drv[id].spt = xfd_formats[i].dsk.spt;
211 				m_drv[id].heads = (xfd_formats[i].dsk.doublesided) ? 2 : 1;
212 				m_drv[id].bseclen = 128;
213 				m_drv[id].seclen = 256 * xfd_formats[i].dsk.seclen_hi + xfd_formats[i].dsk.seclen_lo;
214 				m_drv[id].sectors = m_drv[id].tracks * m_drv[id].heads * m_drv[id].spt;
215 				break;
216 			}
217 		}
218 		break;
219 	/* ATR format: find a size including the 16 bytes header */
220 	case FORMAT_ATR:
221 		{
222 			int s;
223 			m_drv[id].bseclen = 128;
224 			/* get sectors from ATR header */
225 			s = (size - 16) / 128;
226 			/* 3 + odd number of sectors ? */
227 			if ( m_drv[id].image[4] == 128 || (s % 18) == 0 || (s % 26) == 0 || ((s - 3) % 1) != 0 )
228 			{
229 				m_drv[id].sectors = s;
230 				m_drv[id].seclen = 128;
231 				/* sector size 128 or count not evenly dividable by 26 ? */
232 				if( m_drv[id].seclen == 128 || (s % 26) != 0 )
233 				{
234 					/* yup! single density */
235 					m_drv[id].density = 0;
236 					m_drv[id].spt = 18;
237 					m_drv[id].heads = 1;
238 					m_drv[id].tracks = s / 18;
239 					if( s % 18 != 0 )
240 						m_drv[id].tracks += 1;
241 					if( m_drv[id].tracks % 2 == 0 && m_drv[id].tracks > 80 )
242 					{
243 						m_drv[id].heads = 2;
244 						m_drv[id].tracks /= 2;
245 					}
246 				}
247 				else
248 				{
249 					/* yes: medium density */
250 					m_drv[id].density = 0;
251 					m_drv[id].spt = 26;
252 					m_drv[id].heads = 1;
253 					m_drv[id].tracks = s / 26;
254 					if( s % 26 != 0 )
255 						m_drv[id].tracks += 1;
256 					if( m_drv[id].tracks % 2 == 0 && m_drv[id].tracks > 80 )
257 					{
258 						m_drv[id].heads = 2;
259 						m_drv[id].tracks /= 2;
260 					}
261 				}
262 			}
263 			else
264 			{
265 				/* it's double density */
266 				s = (s - 3) / 2 + 3;
267 				m_drv[id].sectors = s;
268 				m_drv[id].density = 2;
269 				m_drv[id].seclen = 256;
270 				m_drv[id].spt = 18;
271 				m_drv[id].heads = 1;
272 				m_drv[id].tracks = s / 18;
273 				if( s % 18 != 0 )
274 					m_drv[id].tracks += 1;
275 				if( m_drv[id].tracks % 2 == 0 && m_drv[id].tracks > 80 )
276 				{
277 					m_drv[id].heads = 2;
278 					m_drv[id].tracks /= 2;
279 				}
280 			}
281 		}
282 		break;
283 	/* DSK format: it's all in the header */
284 	case FORMAT_DSK:
285 		{
286 			atari_dsk_format *dsk = (atari_dsk_format *) m_drv[id].image.get();
287 
288 			m_drv[id].tracks = dsk->tracks;
289 			m_drv[id].spt = dsk->spt;
290 			m_drv[id].heads = (dsk->doublesided) ? 2 : 1;
291 			m_drv[id].seclen = 256 * dsk->seclen_hi + dsk->seclen_lo;
292 			m_drv[id].bseclen = m_drv[id].seclen;
293 			m_drv[id].sectors = m_drv[id].tracks * m_drv[id].heads * m_drv[id].spt;
294 		}
295 		break;
296 	}
297 	logerror("atari opened floppy '%s', %d sectors (%d %s%s) %d bytes/sector\n",
298 			image.filename(),
299 			m_drv[id].sectors,
300 			m_drv[id].tracks,
301 			(m_drv[id].heads == 1) ? "SS" : "DS",
302 			(m_drv[id].density == 0) ? "SD" : (m_drv[id].density == 1) ? "MD" : "DD",
303 			m_drv[id].seclen);
304 }
305 
306 
307 
308 /*****************************************************************************
309  *
310  * This is a description of the data flow between Atari (A) and the
311  * Floppy (F) for the supported commands.
312  *
313  * A->F     DEV  CMD  AUX1 AUX2 CKS
314  *          '1'  'S'  00   00                 get status
315  * F->A     ACK  CPL  04   FF   E0   00   CKS
316  *                     ^    ^
317  *                     |    |
318  *                     |    bit 7 : door closed
319  *                     |
320  *                     bit7  : MD 128 bytes/sector, 26 sectors/track
321  *                     bit5  : DD 256 bytes/sector, 18 sectors/track
322  *                     else  : SD 128 bytes/sector, 18 sectors/track
323  *
324  * A->F     DEV  CMD  AUX1 AUX2 CKS
325  *          '1'  'R'  SECL SECH               read sector
326  * F->A     ACK                               command acknowledge
327  *               ***                          now read the sector
328  * F->A              CPL                      complete: sector read
329  * F->A                  128/256 byte CKS
330  *
331  * A->F     DEV  CMD  AUX1 AUX2 CKS
332  *          '1'  'W'  SECL SECH               write with verify
333  * F->A     ACK                               command acknowledge
334  * A->F          128/256 data CKS
335  * F->A                            CPL        complete: CKS okay
336  *          execute writing the sector
337  * F->A                                 CPL   complete: sector written
338  *
339  * A->F     DEV  CMD  AUX1 AUX2 CKS
340  *          '1'  'P'  SECL SECH               put sector
341  * F->A     ACK                               command acknowledge
342  * A->F          128/256 data CKS
343  * F->A                            CPL        complete: CKS okay
344  *          execute writing the sector
345  * F->A                                 CPL   complete: sector written
346  *
347  * A->F     DEV  CMD  AUX1 AUX2 CKS
348  *           '1' '!'  xx   xx                 single density format
349  * F->A     ACK                               command acknowledge
350  *          execute formatting
351  * F->A               CPL                     complete: format
352  * F->A                    128/256 byte CKS   bad sector table
353  *
354  *
355  * A->F     DEV  CMD  AUX1 AUX2 CKS
356  *          '1'  '"'  xx   xx                 double density format
357  * F->A     ACK                               command acknowledge
358  *          execute formatting
359  * F->A               CPL                     complete: format
360  * F->A                    128/256 byte CKS   bad sector table
361  *
362  *****************************************************************************/
make_chksum(device_t * device,uint8_t * chksum,uint8_t data)363 static void make_chksum(device_t *device,uint8_t * chksum, uint8_t data)
364 {
365 	uint8_t newone;
366 	newone= *chksum + data;
367 	if (newone < *chksum)
368 		newone++;
369 
370 	if (VERBOSE_CHKSUM)
371 		device->logerror("atari chksum old $%02x + data $%02x -> new $%02x\n", *chksum, data, newone);
372 
373 	*chksum = newone;
374 }
375 
clr_serout(int expect_data)376 void atari_fdc_device::clr_serout(int expect_data)
377 {
378 	m_serout_chksum = 0;
379 	m_serout_offs = 0;
380 	m_serout_count = expect_data + 1;
381 }
382 
add_serout(int expect_data)383 void atari_fdc_device::add_serout(int expect_data)
384 {
385 	m_serout_chksum = 0;
386 	m_serout_count = expect_data + 1;
387 }
388 
clr_serin(int ser_delay)389 void atari_fdc_device::clr_serin(int ser_delay)
390 {
391 	m_serin_chksum = 0;
392 	m_serin_offs = 0;
393 	m_serin_count = 0;
394 	m_pokey->serin_ready(ser_delay * 40);
395 }
396 
add_serin(uint8_t data,int with_checksum)397 void atari_fdc_device::add_serin(uint8_t data, int with_checksum)
398 {
399 	m_serin_buff[m_serin_count++] = data;
400 	if (with_checksum)
401 		make_chksum(this,&m_serin_chksum, data);
402 }
403 
atari_set_frame_message(const char * fmt,...)404 static void ATTR_PRINTF(1,2) atari_set_frame_message(const char *fmt, ...)
405 {
406 	//va_list arg;
407 	//va_start(arg, fmt);
408 
409 	//vsprintf(atari_frame_message, fmt, arg);
410 	//atari_frame_counter = 30; /* FIXME */
411 
412 	//va_end(arg);
413 }
414 
a800_serial_command()415 void atari_fdc_device::a800_serial_command()
416 {
417 	int i, drive, sector, offset;
418 
419 	if( !m_serout_offs )
420 	{
421 		if (VERBOSE_SERIAL)
422 			logerror("atari serout command offset = 0\n");
423 		return;
424 	}
425 	clr_serin(10);
426 
427 	if (VERBOSE_SERIAL)
428 	{
429 		logerror("atari serout command %d: %02X %02X %02X %02X %02X : %02X ",
430 			m_serout_offs,
431 			m_serout_buff[0], m_serout_buff[1], m_serout_buff[2],
432 			m_serout_buff[3], m_serout_buff[4], m_serout_chksum);
433 	}
434 
435 	if (m_serout_chksum == 0)
436 	{
437 		if (VERBOSE_SERIAL)
438 			logerror("OK\n");
439 
440 		drive = m_serout_buff[0] - '1';   /* drive # */
441 		/* sector # */
442 		if (drive < 0 || drive > 3)             /* ignore unknown drives */
443 		{
444 			logerror("atari unsupported drive #%d\n", drive+1);
445 			atari_set_frame_message("DRIVE #%d not supported", drive+1);
446 			return;
447 		}
448 
449 		/* extract sector number from the command buffer */
450 		sector = m_serout_buff[2] + 256 * m_serout_buff[3];
451 
452 		switch (m_serout_buff[1]) /* command ? */
453 		{
454 			case 'S':   /* status */
455 				atari_set_frame_message("DRIVE #%d STATUS", drive+1);
456 
457 				if (VERBOSE_SERIAL)
458 					logerror("atari status\n");
459 
460 				add_serin('A',0);
461 				add_serin('C',0);
462 				if (!m_drv[drive].mode) /* read only mode ? */
463 				{
464 					if (m_drv[drive].spt == 26)
465 						add_serin(0x80,1);   /* MD: 0x80 */
466 					else
467 					if (m_drv[drive].seclen == 128)
468 						add_serin(0x00,1);   /* SD: 0x00 */
469 					else
470 						add_serin(0x20,1);   /* DD: 0x20 */
471 				}
472 				else
473 				{
474 					if (m_drv[drive].spt == 26)
475 						add_serin(0x84,1);   /* MD: 0x84 */
476 					else
477 					if (m_drv[drive].seclen == 128)
478 						add_serin(0x04,1);   /* SD: 0x04 */
479 					else
480 						add_serin(0x24,1);   /* DD: 0x24 */
481 				}
482 				if (m_drv[drive].image)
483 					add_serin(0xff,1);   /* door closed: 0xff */
484 				else
485 					add_serin(0x7f,1);   /* door open: 0x7f */
486 				add_serin(0xe0,1);   /* dunno */
487 				add_serin(0x00,1);   /* dunno */
488 				add_serin(m_serin_chksum,0);
489 				break;
490 
491 			case 'R':   /* read sector */
492 				if (VERBOSE_SERIAL)
493 					logerror("atari read sector #%d\n", sector);
494 
495 				if( sector < 1 || sector > m_drv[drive].sectors )
496 				{
497 					atari_set_frame_message("DRIVE #%d READ SECTOR #%3d - ERR", drive+1, sector);
498 
499 					if (VERBOSE_SERIAL)
500 						logerror("atari bad sector #\n");
501 
502 					add_serin('E',0);
503 					break;
504 				}
505 				add_serin('A',0);   /* acknowledge */
506 				add_serin('C',0);   /* completed */
507 				if (sector < 4)     /* sector 1 .. 3 might be different length */
508 				{
509 					atari_set_frame_message("DRIVE #%d READ SECTOR #%3d - SD", drive+1, sector);
510 					offset = (sector - 1) * m_drv[drive].bseclen + m_drv[drive].header_skip;
511 					for (i = 0; i < 128; i++)
512 						add_serin(m_drv[drive].image[offset++],1);
513 				}
514 				else
515 				{
516 					atari_set_frame_message("DRIVE #%d READ SECTOR #%3d - %cD", drive+1, sector, (m_drv[drive].seclen == 128) ? 'S' : 'D');
517 					offset = (sector - 1) * m_drv[drive].seclen + m_drv[drive].header_skip;
518 					for (i = 0; i < m_drv[drive].seclen; i++)
519 						add_serin(m_drv[drive].image[offset++],1);
520 				}
521 				add_serin(m_serin_chksum,0);
522 				break;
523 
524 			case 'W':   /* write sector with verify */
525 				if (VERBOSE_SERIAL)
526 					logerror("atari write sector #%d\n", sector);
527 
528 				add_serin('A',0);
529 				if (sector < 4)     /* sector 1 .. 3 might be different length */
530 				{
531 					add_serout(m_drv[drive].bseclen);
532 					atari_set_frame_message("DRIVE #%d WRITE SECTOR #%3d - SD", drive+1, sector);
533 				}
534 				else
535 				{
536 					add_serout(m_drv[drive].seclen);
537 					atari_set_frame_message("DRIVE #%d WRITE SECTOR #%3d - %cD", drive+1, sector, (m_drv[drive].seclen == 128) ? 'S' : 'D');
538 				}
539 				break;
540 
541 			case 'P':   /* put sector (no verify) */
542 				if (VERBOSE_SERIAL)
543 					logerror("atari put sector #%d\n", sector);
544 
545 				add_serin('A',0);
546 				if (sector < 4)     /* sector 1 .. 3 might be different length */
547 				{
548 					add_serout(m_drv[drive].bseclen);
549 					atari_set_frame_message("DRIVE #%d PUT SECTOR #%3d - SD", drive+1, sector);
550 				}
551 				else
552 				{
553 					add_serout(m_drv[drive].seclen);
554 					atari_set_frame_message("DRIVE #%d PUT SECTOR #%3d - %cD", drive+1, sector, (m_drv[drive].seclen == 128) ? 'S' : 'D');
555 				}
556 				break;
557 
558 			case '!':   /* SD format */
559 				if (VERBOSE_SERIAL)
560 					logerror("atari format SD drive #%d\n", drive+1);
561 
562 				atari_set_frame_message("DRIVE #%d FORMAT SD", drive+1);
563 				add_serin('A',0);   /* acknowledge */
564 				add_serin('C',0);   /* completed */
565 				for (i = 0; i < 128; i++)
566 					add_serin(0,1);
567 				add_serin(m_serin_chksum,0);
568 				break;
569 
570 			case '"':   /* DD format */
571 				if (VERBOSE_SERIAL)
572 					logerror("atari format DD drive #%d\n", drive+1);
573 
574 				atari_set_frame_message("DRIVE #%d FORMAT DD", drive+1);
575 				add_serin('A',0);   /* acknowledge */
576 				add_serin('C',0);   /* completed */
577 				for (i = 0; i < 256; i++)
578 					add_serin(0,1);
579 				add_serin(m_serin_chksum,0);
580 				break;
581 
582 			default:
583 				if (VERBOSE_SERIAL)
584 					logerror("atari unknown command #%c\n", m_serout_buff[1]);
585 
586 				atari_set_frame_message("DRIVE #%d UNKNOWN CMD '%c'", drive+1, m_serout_buff[1]);
587 				add_serin('N',0);   /* negative acknowledge */
588 		}
589 	}
590 	else
591 	{
592 		atari_set_frame_message("serial cmd chksum error");
593 		if (VERBOSE_SERIAL)
594 			logerror("BAD\n");
595 
596 		add_serin('E',0);
597 	}
598 	if (VERBOSE_SERIAL)
599 		logerror("atari %d bytes to read\n", m_serin_count);
600 }
601 
a800_serial_write()602 void atari_fdc_device::a800_serial_write()
603 {
604 	int i, drive, sector, offset;
605 
606 	if (VERBOSE_SERIAL)
607 	{
608 		logerror("atari serout %d bytes written : %02X ",
609 			m_serout_offs, m_serout_chksum);
610 	}
611 
612 	clr_serin(80);
613 	if (m_serout_chksum == 0)
614 	{
615 		if (VERBOSE_SERIAL)
616 			logerror("OK\n");
617 
618 		add_serin('C',0);
619 		/* write the sector */
620 		drive = m_serout_buff[0] - '1';   /* drive # */
621 		/* not write protected and image available ? */
622 		if (m_drv[drive].mode && m_drv[drive].image)
623 		{
624 			/* extract sector number from the command buffer */
625 			sector = m_serout_buff[2] + 256 * m_serout_buff[3];
626 			if (sector < 4)     /* sector 1 .. 3 might be different length */
627 			{
628 				offset = (sector - 1) * m_drv[drive].bseclen + m_drv[drive].header_skip;
629 
630 				if (VERBOSE_SERIAL)
631 					logerror("atari storing 128 byte sector %d at offset 0x%08X", sector, offset );
632 
633 				for (i = 0; i < 128; i++)
634 					m_drv[drive].image[offset++] = m_serout_buff[5+i];
635 				atari_set_frame_message("DRIVE #%d WROTE SECTOR #%3d - SD", drive+1, sector);
636 			}
637 			else
638 			{
639 				offset = (sector - 1) * m_drv[drive].seclen + m_drv[drive].header_skip;
640 
641 				if (VERBOSE_SERIAL)
642 					logerror("atari storing %d byte sector %d at offset 0x%08X", m_drv[drive].seclen, sector, offset );
643 
644 				for (i = 0; i < m_drv[drive].seclen; i++)
645 					m_drv[drive].image[offset++] = m_serout_buff[5+i];
646 				atari_set_frame_message("DRIVE #%d WROTE SECTOR #%3d - %cD", drive+1, sector, (m_drv[drive].seclen == 128) ? 'S' : 'D');
647 			}
648 			add_serin('C',0);
649 		}
650 		else
651 		{
652 			add_serin('E',0);
653 		}
654 	}
655 	else
656 	{
657 		if (VERBOSE_SERIAL)
658 			logerror("BAD\n");
659 
660 		add_serin('E',0);
661 	}
662 }
663 
serin_r()664 uint8_t atari_fdc_device::serin_r()
665 {
666 	int data = 0x00;
667 	int ser_delay = 0;
668 
669 	if (m_serin_count)
670 	{
671 		data = m_serin_buff[m_serin_offs];
672 		ser_delay = 2 * 40;
673 		if (m_serin_offs < 3)
674 		{
675 			ser_delay = 4 * 40;
676 			if (m_serin_offs < 2)
677 				ser_delay = 200 * 40;
678 		}
679 		m_serin_offs++;
680 		if (--m_serin_count == 0)
681 			m_serin_offs = 0;
682 		else
683 			m_pokey->serin_ready(ser_delay);
684 	}
685 
686 	if (VERBOSE_SERIAL)
687 		logerror("atari serin[$%04x] -> $%02x; delay %d\n", m_serin_offs, data, ser_delay);
688 
689 	return data;
690 }
691 
serout_w(uint8_t data)692 void atari_fdc_device::serout_w(uint8_t data)
693 {
694 	/* ignore serial commands if no floppy image is specified */
695 	if( !m_drv[0].image )
696 		return;
697 	if (m_serout_count)
698 	{
699 		/* store data */
700 		m_serout_buff[m_serout_offs] = data;
701 
702 		if (VERBOSE_SERIAL)
703 			logerror("atari serout[$%04x] <- $%02x; count %d\n", m_serout_offs, data, m_serout_count);
704 
705 		m_serout_offs++;
706 		if (--m_serout_count == 0)
707 		{
708 			/* exclusive or written checksum with calculated */
709 			m_serout_chksum ^= data;
710 			/* if the attention line is high, this should be data */
711 			if (m_pia->irq_b_state())
712 				a800_serial_write();
713 		}
714 		else
715 		{
716 			make_chksum(this,&m_serout_chksum, data);
717 		}
718 	}
719 }
720 
WRITE_LINE_MEMBER(atari_fdc_device::pia_cb2_w)721 WRITE_LINE_MEMBER(atari_fdc_device::pia_cb2_w)
722 {
723 	if (!state)
724 	{
725 		clr_serout(4); /* expect 4 command bytes + checksum */
726 	}
727 	else
728 	{
729 		m_serin_delay = 0;
730 		a800_serial_command();
731 	}
732 }
733 
734 static const floppy_interface atari_floppy_interface =
735 {
736 	FLOPPY_STANDARD_5_25_DSHD,
737 	LEGACY_FLOPPY_OPTIONS_NAME(atari_only),
738 	"floppy_5_25"
739 };
740 
741 DEFINE_DEVICE_TYPE(ATARI_FDC, atari_fdc_device, "atari_fdc", "Atari FDC")
742 
atari_fdc_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)743 atari_fdc_device::atari_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
744 	: device_t(mconfig, ATARI_FDC, tag, owner, clock),
745 	m_floppy(*this, "floppy%u", 0U),
746 	m_pokey(*this, "^pokey"),
747 	m_pia(*this, "^pia"),
748 	m_serout_count(0),
749 	m_serout_offs(0),
750 	m_serout_chksum(0),
751 //  m_serout_delay(0),
752 	m_serin_count(0),
753 	m_serin_offs(0),
754 	m_serin_chksum(0),
755 	m_serin_delay(0)
756 {
757 }
758 
759 //-------------------------------------------------
760 //  device_start - device-specific startup
761 //-------------------------------------------------
762 
device_start()763 void atari_fdc_device::device_start()
764 {
765 	memset(m_serout_buff, 0, sizeof(m_serout_buff));
766 	memset(m_serin_buff, 0, sizeof(m_serin_buff));
767 	memset(m_drv, 0, sizeof(m_drv));
768 
769 	for (auto &floppy : m_floppy)
770 		floppy->floppy_install_load_proc(_atari_load_proc);
771 }
772 
773 //-------------------------------------------------
774 //  device_add_mconfig - add device configuration
775 //-------------------------------------------------
776 
device_add_mconfig(machine_config & config)777 void atari_fdc_device::device_add_mconfig(machine_config &config)
778 {
779 	for (auto &floppy : m_floppy)
780 		LEGACY_FLOPPY(config, floppy, 0, &atari_floppy_interface);
781 }
782