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