1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * Floppy disk emulation
5 *
6 * Copyright 1995 Hannu Rummukainen
7 * Copyright 1995-2001 Bernd Schmidt
8 * Copyright 2000-2003 Toni Wilen
9 *
10 * Original High Density Drive Handling by Dr. Adil Temel (C) 2001 [atemel1@hotmail.com]
11 *
12 */
13
14 #include "sysconfig.h"
15 #include "sysdeps.h"
16
17 #if defined(__CELLOS_LV2__) || defined(_WIN32) || defined(WIIU) || defined(__SWITCH__) || defined(VITA)
18 #define tzset()
19 #define timezone 0
20 #define daylight 0
21 #endif
22
23 int disk_debug_logging = 0;
24 int disk_debug_mode = 0;
25 int disk_debug_track = -1;
26
27 #define MFM_VALIDATOR 0
28
29 #include "uae.h"
30 #include "options.h"
31 #include "memory_uae.h"
32 #include "events.h"
33 #include "custom.h"
34 #include "ersatz.h"
35 #include "disk.h"
36 #include "gui.h"
37 #include "zfile.h"
38 #include "newcpu.h"
39 #include "osemu.h"
40 #include "execlib.h"
41 #include "savestate.h"
42 #include "cia.h"
43 #include "debug.h"
44 #ifdef FDI2RAW
45 #include "fdi2raw.h"
46 #endif
47 #include "catweasel.h"
48 #include "driveclick.h"
49 #ifdef CAPS
50 #include "caps.h"
51 #endif
52 #include "crc32.h"
53 #include "inputdevice.h"
54 #include "amax.h"
55 #ifdef RETROPLATFORM
56 #include "rp.h"
57 #endif
58 #include "misc.h"
59 #include "inputrecord.h"
60 #include <ctype.h>
61
62 #undef CATWEASEL
63
64 /* external prototypes */
65 extern uae_u32 uaerand (void);
66
67 /* internal members */
68 static int longwritemode = 0;
69
70 /* support HD floppies */
71 #define FLOPPY_DRIVE_HD
72 /* writable track length with normal 2us bitcell/300RPM motor, 12667 PAL, 12797 NTSC */
73 #define FLOPPY_WRITE_LEN (currprefs.floppy_write_length > 256 ? currprefs.floppy_write_length / 2 : (currprefs.ntscmode ? (12798 / 2) : (12668 / 2)))
74 #define FLOPPY_WRITE_MAXLEN 0x3800
75 /* This works out to 350 */
76 #define FLOPPY_GAP_LEN (FLOPPY_WRITE_LEN - 11 * 544)
77 /* (cycles/bitcell) << 8, normal = ((2us/280ns)<<8) = ~1828.5714 */
78 #define NORMAL_FLOPPY_SPEED (currprefs.ntscmode ? 1812 : 1829)
79 /* max supported floppy drives, for small memory systems */
80 #define MAX_FLOPPY_DRIVES 4
81
82 #ifdef FLOPPY_DRIVE_HD
83 #define DDHDMULT 2
84 #else
85 #define DDHDMULT 1
86 #endif
87 #define MAX_SECTORS (DDHDMULT * 11)
88
89 #undef DEBUG_DRIVE_ID
90
91 /* UAE-1ADF (ADF_EXT2)
92 * W reserved
93 * W number of tracks (default 2*80=160)
94 *
95 * W reserved
96 * W type, 0=normal AmigaDOS track, 1 = raw MFM (upper byte = disk revolutions - 1)
97 * L available space for track in bytes (must be even)
98 * L track length in bits
99 */
100
101 static int side, direction;
102 static uae_u8 selected = 15, disabled;
103
104 static uae_u8 writebuffer[544 * MAX_SECTORS];
105
106 #define DISK_INDEXSYNC 1
107 #define DISK_WORDSYNC 2
108 #define DISK_REVOLUTION 4 /* 8,16,32,64 */
109
110 #define DSKREADY_UP_TIME 20
111 #define DSKREADY_DOWN_TIME 50
112
113 #define DSKDMA_OFF 0
114 #define DSKDMA_INIT 1
115 #define DSKDMA_READ 2
116 #define DSKDMA_WRITE 3
117
118 static int dskdmaen, dsklength, dsklength2, dsklen;
119 static uae_u16 dskbytr_val;
120 static uae_u32 dskpt;
121 static bool fifo_filled;
122 static uae_u16 fifo[3];
123 static int fifo_inuse[3];
124 static int dma_enable, bitoffset; //, syncoffset;
125 static uae_u16 word, dsksync;
126 static unsigned long dsksync_cycles;
127 #define WORDSYNC_TIME 11
128 /* Always carried through to the next line. */
129 int disk_hpos;
130 static int disk_jitter;
131 static int indexdecay;
132
133 static uae_u8 prev_data;
134 static int prev_step;
135
136 typedef enum { TRACK_AMIGADOS, TRACK_RAW, TRACK_RAW1, TRACK_PCDOS, TRACK_DISKSPARE, TRACK_NONE } image_tracktype;
137 typedef struct {
138 uae_u16 len;
139 uae_u32 offs;
140 int bitlen, track;
141 uae_u16 sync;
142 image_tracktype type;
143 int revolutions;
144 } trackid;
145
146 #define MAX_TRACKS (2 * 83)
147
148 /* We have three kinds of Amiga floppy drives
149 * - internal A500/A2000 drive:
150 * ID is always DRIVE_ID_NONE (S.T.A.G expects this)
151 * - HD drive (A3000/A4000):
152 * ID is DRIVE_ID_35DD if DD floppy is inserted or drive is empty
153 * ID is DRIVE_ID_35HD if HD floppy is inserted
154 * - regular external drive:
155 * ID is always DRIVE_ID_35DD
156 */
157
158 #define DRIVE_ID_NONE 0x00000000
159 #define DRIVE_ID_35DD 0xFFFFFFFF
160 #define DRIVE_ID_35HD 0xAAAAAAAA
161 #define DRIVE_ID_525SD 0x55555555 /* 40 track 5.25 drive , kickstart does not recognize this */
162
163 typedef enum { ADF_NONE = -1, ADF_NORMAL, ADF_EXT1, ADF_EXT2, ADF_FDI, ADF_IPF, ADF_CATWEASEL, ADF_PCDOS } drive_filetype;
164 typedef struct {
165 struct zfile *diskfile;
166 struct zfile *writediskfile;
167 drive_filetype filetype;
168 trackid trackdata[MAX_TRACKS];
169 trackid writetrackdata[MAX_TRACKS];
170 int buffered_cyl, buffered_side;
171 int cyl;
172 bool motoroff;
173 int motordelay; /* dskrdy needs some clock cycles before it changes after switching off motor */
174 bool state;
175 bool wrprot;
176 bool forcedwrprot;
177 uae_u16 bigmfmbuf[0x4000 * DDHDMULT];
178 uae_u16 tracktiming[0x4000 * DDHDMULT];
179 int multi_revolution;
180 int skipoffset;
181 int mfmpos;
182 int indexoffset;
183 int tracklen;
184 int revolutions;
185 int prevtracklen;
186 int trackspeed;
187 int num_tracks, write_num_tracks, num_secs;
188 int hard_num_cyls;
189 bool dskchange;
190 int dskchange_time;
191 bool dskready;
192 int dskready_up_time;
193 int dskready_down_time;
194 int writtento;
195 int steplimit;
196 frame_time_t steplimitcycle;
197 int indexhack, indexhackmode;
198 int ddhd; /* 1=DD 2=HD */
199 int drive_id_scnt; /* drive id shift counter */
200 int idbit;
201 unsigned long drive_id; /* drive id to be reported */
202 TCHAR newname[256]; /* storage space for new filename during eject delay */
203 bool newnamewriteprotected;
204 uae_u32 crc32;
205 #ifdef FDI2RAW
206 FDI *fdi;
207 #endif
208 int useturbo;
209 int floppybitcounter; /* number of bits left */
210 #ifdef CATWEASEL
211 catweasel_drive *catweasel;
212 #else
213 int catweasel;
214 int amax;
215 #endif
216 } drive;
217
218 #define MIN_STEPLIMIT_CYCLE (CYCLE_UNIT * 210)
219
220 static uae_u16 bigmfmbufw[0x4000 * DDHDMULT];
221 static drive floppy[MAX_FLOPPY_DRIVES];
222 static TCHAR dfxhistory[2][MAX_PREVIOUS_FLOPPIES][MAX_DPATH];
223
224 static uae_u8 exeheader[]={0x00,0x00,0x03,0xf3,0x00,0x00,0x00,0x00};
225 static uae_u8 bootblock_ofs[]={
226 0x44,0x4f,0x53,0x00,0xc0,0x20,0x0f,0x19,0x00,0x00,0x03,0x70,0x43,0xfa,0x00,0x18,
227 0x4e,0xae,0xff,0xa0,0x4a,0x80,0x67,0x0a,0x20,0x40,0x20,0x68,0x00,0x16,0x70,0x00,
228 0x4e,0x75,0x70,0xff,0x60,0xfa,0x64,0x6f,0x73,0x2e,0x6c,0x69,0x62,0x72,0x61,0x72,
229 0x79
230 };
231 static uae_u8 bootblock_ffs[]={
232 0x44, 0x4F, 0x53, 0x01, 0xE3, 0x3D, 0x0E, 0x72, 0x00, 0x00, 0x03, 0x70, 0x43, 0xFA, 0x00, 0x3E,
233 0x70, 0x25, 0x4E, 0xAE, 0xFD, 0xD8, 0x4A, 0x80, 0x67, 0x0C, 0x22, 0x40, 0x08, 0xE9, 0x00, 0x06,
234 0x00, 0x22, 0x4E, 0xAE, 0xFE, 0x62, 0x43, 0xFA, 0x00, 0x18, 0x4E, 0xAE, 0xFF, 0xA0, 0x4A, 0x80,
235 0x67, 0x0A, 0x20, 0x40, 0x20, 0x68, 0x00, 0x16, 0x70, 0x00, 0x4E, 0x75, 0x70, 0xFF, 0x4E, 0x75,
236 0x64, 0x6F, 0x73, 0x2E, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x65, 0x78, 0x70, 0x61,
237 0x6E, 0x73, 0x69, 0x6F, 0x6E, 0x2E, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
238 };
239
240 #define FS_OFS_DATABLOCKSIZE 488
241 #define FS_FLOPPY_BLOCKSIZE 512
242 #define FS_EXTENSION_BLOCKS 72
243 #define FS_FLOPPY_TOTALBLOCKS 1760
244 #define FS_FLOPPY_RESERVED 2
245
writeimageblock(struct zfile * dst,uae_u8 * sector,int offset)246 static void writeimageblock (struct zfile *dst, uae_u8 *sector, int offset)
247 {
248 zfile_fseek (dst, offset, SEEK_SET);
249 zfile_fwrite (sector, FS_FLOPPY_BLOCKSIZE, 1, dst);
250 }
251
disk_checksum(uae_u8 * p,uae_u8 * c)252 static void disk_checksum (uae_u8 *p, uae_u8 *c)
253 {
254 uae_u32 cs = 0;
255 int i;
256 for (i = 0; i < FS_FLOPPY_BLOCKSIZE; i+= 4)
257 cs += (p[i] << 24) | (p[i+1] << 16) | (p[i+2] << 8) | (p[i+3] << 0);
258 cs = -cs;
259 c[0] = cs >> 24; c[1] = cs >> 16; c[2] = cs >> 8; c[3] = cs >> 0;
260 }
261
dirhash(const uae_char * name)262 static int dirhash (const uae_char *name)
263 {
264 unsigned long hash;
265 uae_u32 i = 0;
266
267 hash = strlen (name);
268 for( ; i < strlen (name); i++) {
269 hash = hash * 13;
270 hash = hash + toupper (name[i]);
271 hash = hash & 0x7ff;
272 }
273 hash = hash % ((FS_FLOPPY_BLOCKSIZE / 4) - 56);
274 return hash;
275 }
276
disk_date(uae_u8 * p)277 static void disk_date (uae_u8 *p)
278 {
279 static int pdays, pmins, pticks;
280 int days, mins, ticks;
281 struct timeval tv;
282 struct mytimeval mtv;
283
284 gettimeofday (&tv, NULL);
285 mtv.tv_sec = tv.tv_sec;
286 mtv.tv_usec = tv.tv_usec;
287 timeval_to_amiga (&mtv, &days, &mins, &ticks);
288 if (days == pdays && mins == pmins && ticks == pticks) {
289 ticks++;
290 if (ticks >= 50 * 60) {
291 ticks = 0;
292 mins++;
293 if (mins >= 24 * 60)
294 days++;
295 }
296 }
297 pdays = days;
298 pmins = mins;
299 pticks = ticks;
300 p[0] = days >> 24; p[1] = days >> 16; p[2] = days >> 8; p[3] = days >> 0;
301 p[4] = mins >> 24; p[5] = mins >> 16; p[6] = mins >> 8; p[7] = mins >> 0;
302 p[8] = ticks >> 24; p[9] = ticks >> 16; p[10] = ticks >> 8; p[11] = ticks >> 0;
303 }
304
createbootblock(uae_u8 * sector,int bootable)305 static void createbootblock (uae_u8 *sector, int bootable)
306 {
307 memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
308 memcpy (sector, "DOS", 3);
309 if (bootable)
310 memcpy (sector, bootblock_ofs, sizeof (bootblock_ofs));
311 }
312
createrootblock(uae_u8 * sector,const char * disk_name)313 static void createrootblock (uae_u8 *sector, const char *disk_name)
314 {
315 char *dn = ua (disk_name);
316 char *dn2 = dn;
317 if (strlen (dn2) >= 30)
318 dn2[30] = 0;
319 if (dn2[0] == 0)
320 dn2 = "empty";
321 memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
322 sector[0+3] = 2;
323 sector[12+3] = 0x48;
324 sector[312] = sector[313] = sector[314] = sector[315] = (uae_u8)0xff;
325 sector[316+2] = 881 >> 8; sector[316+3] = 881 & 255;
326 sector[432] = strlen (dn2);
327 strcpy ((char*)sector + 433, dn2);
328 sector[508 + 3] = 1;
329 disk_date (sector + 420);
330 memcpy (sector + 472, sector + 420, 3 * 4);
331 memcpy (sector + 484, sector + 420, 3 * 4);
332 xfree (dn);
333 }
334
getblock(uae_u8 * bitmap,int * prev)335 static int getblock (uae_u8 *bitmap, int *prev)
336 {
337 int i = *prev;
338 while (bitmap[i] != 0xff) {
339 if (bitmap[i] == 0) {
340 bitmap[i] = 1;
341 *prev = i;
342 return i;
343 }
344 i++;
345 }
346 i = 0;
347 while (bitmap[i] != 0xff) {
348 if (bitmap[i] == 0) {
349 bitmap[i] = 1;
350 *prev = i;
351 return i;
352 }
353 i++;
354 }
355 return -1;
356 }
357
pl(uae_u8 * sector,int offset,uae_u32 v)358 static void pl (uae_u8 *sector, int offset, uae_u32 v)
359 {
360 sector[offset + 0] = v >> 24;
361 sector[offset + 1] = v >> 16;
362 sector[offset + 2] = v >> 8;
363 sector[offset + 3] = v >> 0;
364 }
365
createdirheaderblock(uae_u8 * sector,int parent,const char * filename,uae_u8 * bitmap,int * prevblock)366 static int createdirheaderblock (uae_u8 *sector, int parent, const char *filename, uae_u8 *bitmap, int *prevblock)
367 {
368 int block = getblock (bitmap, prevblock);
369
370 memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
371 pl (sector, 0, 2);
372 pl (sector, 4, block);
373 disk_date (sector + 512 - 92);
374 sector[512 - 80] = strlen (filename);
375 strcpy ((char*)sector + 512 - 79, filename);
376 pl (sector, 512 - 12, parent);
377 pl (sector, 512 - 4, 2);
378 return block;
379 }
380
createfileheaderblock(struct zfile * z,uae_u8 * sector,int parent,const char * filename,struct zfile * src,uae_u8 * bitmap,int * prevblock)381 static int createfileheaderblock (struct zfile *z,uae_u8 *sector, int parent, const char *filename, struct zfile *src, uae_u8 *bitmap, int *prevblock)
382 {
383 uae_u8 sector2[FS_FLOPPY_BLOCKSIZE];
384 uae_u8 sector3[FS_FLOPPY_BLOCKSIZE];
385 int block = getblock (bitmap, prevblock);
386 int datablock = getblock (bitmap, prevblock);
387 int datasec = 1;
388 int extensions;
389 int extensionblock, extensioncounter;
390 /* REMOVEME:
391 * nowhere used
392 */
393 #if 0
394 int headerextension = 1;
395 #endif
396 int size;
397
398 zfile_fseek (src, 0, SEEK_END);
399 size = zfile_ftell (src);
400 zfile_fseek (src, 0, SEEK_SET);
401 extensions = (size + FS_OFS_DATABLOCKSIZE - 1) / FS_OFS_DATABLOCKSIZE;
402
403 memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
404 pl (sector, 0, 2);
405 pl (sector, 4, block);
406 pl (sector, 8, extensions > FS_EXTENSION_BLOCKS ? FS_EXTENSION_BLOCKS : extensions);
407 pl (sector, 16, datablock);
408 pl (sector, FS_FLOPPY_BLOCKSIZE - 188, size);
409 disk_date (sector + FS_FLOPPY_BLOCKSIZE - 92);
410 sector[FS_FLOPPY_BLOCKSIZE - 80] = strlen (filename);
411 strcpy ((char*)sector + FS_FLOPPY_BLOCKSIZE - 79, filename);
412 pl (sector, FS_FLOPPY_BLOCKSIZE - 12, parent);
413 pl (sector, FS_FLOPPY_BLOCKSIZE - 4, -3);
414 extensioncounter = 0;
415 extensionblock = 0;
416
417 while (size > 0) {
418 int datablock2 = datablock;
419 int extensionblock2 = extensionblock;
420 if (extensioncounter == FS_EXTENSION_BLOCKS) {
421 extensioncounter = 0;
422 extensionblock = getblock (bitmap, prevblock);
423 if (datasec > FS_EXTENSION_BLOCKS + 1) {
424 pl (sector3, 8, FS_EXTENSION_BLOCKS);
425 pl (sector3, FS_FLOPPY_BLOCKSIZE - 8, extensionblock);
426 pl (sector3, 4, extensionblock2);
427 disk_checksum(sector3, sector3 + 20);
428 writeimageblock (z, sector3, extensionblock2 * FS_FLOPPY_BLOCKSIZE);
429 } else {
430 pl (sector, 512 - 8, extensionblock);
431 }
432 memset (sector3, 0, FS_FLOPPY_BLOCKSIZE);
433 pl (sector3, 0, 16);
434 pl (sector3, FS_FLOPPY_BLOCKSIZE - 12, block);
435 pl (sector3, FS_FLOPPY_BLOCKSIZE - 4, -3);
436 }
437 memset (sector2, 0, FS_FLOPPY_BLOCKSIZE);
438 pl (sector2, 0, 8);
439 pl (sector2, 4, block);
440 pl (sector2, 8, datasec++);
441 pl (sector2, 12, size > FS_OFS_DATABLOCKSIZE ? FS_OFS_DATABLOCKSIZE : size);
442 zfile_fread (sector2 + 24, size > FS_OFS_DATABLOCKSIZE ? FS_OFS_DATABLOCKSIZE : size, 1, src);
443 size -= FS_OFS_DATABLOCKSIZE;
444 datablock = 0;
445 if (size > 0) datablock = getblock (bitmap, prevblock);
446 pl (sector2, 16, datablock);
447 disk_checksum(sector2, sector2 + 20);
448 writeimageblock (z, sector2, datablock2 * FS_FLOPPY_BLOCKSIZE);
449 if (datasec <= FS_EXTENSION_BLOCKS + 1)
450 pl (sector, 512 - 204 - extensioncounter * 4, datablock2);
451 else
452 pl (sector3, 512 - 204 - extensioncounter * 4, datablock2);
453 extensioncounter++;
454 }
455 if (datasec > FS_EXTENSION_BLOCKS) {
456 pl (sector3, 8, extensioncounter);
457 disk_checksum(sector3, sector3 + 20);
458 writeimageblock (z, sector3, extensionblock * FS_FLOPPY_BLOCKSIZE);
459 }
460 disk_checksum(sector, sector + 20);
461 writeimageblock (z, sector, block * FS_FLOPPY_BLOCKSIZE);
462 return block;
463 }
464
createbitmapblock(uae_u8 * sector,uae_u8 * bitmap)465 static void createbitmapblock (uae_u8 *sector, uae_u8 *bitmap)
466 {
467 int i, j;
468 memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
469 i = 0;
470 for (;;) {
471 uae_u32 mask = 0;
472 for (j = 0; j < 32; j++) {
473 if (bitmap[2 + i * 32 + j] == 0xff)
474 break;
475 if (!bitmap[2 + i * 32 + j])
476 mask |= 1 << j;
477 }
478 sector[4 + i * 4 + 0] = mask >> 24;
479 sector[4 + i * 4 + 1] = mask >> 16;
480 sector[4 + i * 4 + 2] = mask >> 8;
481 sector[4 + i * 4 + 3] = mask >> 0;
482 if (bitmap[2 + i * 32 + j] == 0xff)
483 break;
484 i++;
485
486 }
487 disk_checksum(sector, sector + 0);
488 }
489
createimagefromexe(struct zfile * src,struct zfile * dst)490 static int createimagefromexe (struct zfile *src, struct zfile *dst)
491 {
492 uae_u8 sector1[FS_FLOPPY_BLOCKSIZE], sector2[FS_FLOPPY_BLOCKSIZE];
493 uae_u8 bitmap[FS_FLOPPY_TOTALBLOCKS + 8];
494 int exesize;
495 int blocksize = FS_OFS_DATABLOCKSIZE;
496 int blocks, extensionblocks;
497 int totalblocks;
498 int fblock1, dblock1;
499 char *fname1 = "runme.exe";
500 TCHAR *fname1b = _T("runme.adf");
501 char *fname2 = "startup-sequence";
502 char *dirname1 = "s";
503 struct zfile *ss;
504 int prevblock;
505
506 memset (bitmap, 0, sizeof (bitmap));
507 zfile_fseek (src, 0, SEEK_END);
508 exesize = zfile_ftell (src);
509 blocks = (exesize + blocksize - 1) / blocksize;
510 extensionblocks = (blocks + FS_EXTENSION_BLOCKS - 1) / FS_EXTENSION_BLOCKS;
511 /* bootblock=2, root=1, bitmap=1, startup-sequence=1+1, exefileheader=1 */
512 totalblocks = 2 + 1 + 1 + 2 + 1 + blocks + extensionblocks;
513 if (totalblocks > FS_FLOPPY_TOTALBLOCKS)
514 return 0;
515
516 bitmap[880] = 1;
517 bitmap[881] = 1;
518 bitmap[0] = 1;
519 bitmap[1] = 1;
520 bitmap[1760] = -1;
521 prevblock = 880;
522
523 dblock1 = createdirheaderblock (sector2, 880, dirname1, bitmap, &prevblock);
524 ss = zfile_fopen_empty (src, fname1b, strlen (fname1));
525 zfile_fwrite (fname1, strlen(fname1), 1, ss);
526 fblock1 = createfileheaderblock (dst, sector1, dblock1, fname2, ss, bitmap, &prevblock);
527 zfile_fclose (ss);
528 pl (sector2, 24 + dirhash (fname2) * 4, fblock1);
529 disk_checksum(sector2, sector2 + 20);
530 writeimageblock (dst, sector2, dblock1 * FS_FLOPPY_BLOCKSIZE);
531
532 fblock1 = createfileheaderblock (dst, sector1, 880, fname1, src, bitmap, &prevblock);
533
534 createrootblock (sector1, zfile_getfilename (src));
535 pl (sector1, 24 + dirhash (fname1) * 4, fblock1);
536 pl (sector1, 24 + dirhash (dirname1) * 4, dblock1);
537 disk_checksum(sector1, sector1 + 20);
538 writeimageblock (dst, sector1, 880 * FS_FLOPPY_BLOCKSIZE);
539
540 createbitmapblock (sector1, bitmap);
541 writeimageblock (dst, sector1, 881 * FS_FLOPPY_BLOCKSIZE);
542
543 createbootblock (sector1, 1);
544 writeimageblock (dst, sector1, 0 * FS_FLOPPY_BLOCKSIZE);
545
546 return 1;
547 }
548
isfloppysound(drive * drv)549 static bool isfloppysound (drive *drv)
550 {
551 return drv->useturbo == 0;
552 }
553
get_floppy_speed(void)554 static int get_floppy_speed (void)
555 {
556 int m = currprefs.floppy_speed;
557 if (m <= 10)
558 m = 100;
559 m = NORMAL_FLOPPY_SPEED * 100 / m;
560 return m;
561 }
562
get_floppy_speed2(drive * drv)563 static int get_floppy_speed2 (drive *drv)
564 {
565 int m = get_floppy_speed () * drv->tracklen / (2 * 8 * FLOPPY_WRITE_LEN * drv->ddhd);
566 if (m <= 0)
567 m = 1;
568 return m;
569 }
570
571 #ifdef DEBUG_DRIVE_ID
drive_id_name(drive * drv)572 static TCHAR *drive_id_name(drive *drv)
573 {
574 switch(drv->drive_id)
575 {
576 case DRIVE_ID_35HD : return _T("3.5HD");
577 case DRIVE_ID_525SD: return _T("5.25SD");
578 case DRIVE_ID_35DD : return _T("3.5DD");
579 case DRIVE_ID_NONE : return _T("NONE");
580 }
581 return _T("UNKNOWN");
582 }
583 #endif
584
585 /* Simulate exact behaviour of an A3000T 3.5 HD disk drive.
586 * The drive reports to be a 3.5 DD drive whenever there is no
587 * disk or a 3.5 DD disk is inserted. Only 3.5 HD drive id is reported
588 * when a real 3.5 HD disk is inserted. -Adil
589 */
drive_settype_id(drive * drv)590 static void drive_settype_id (drive *drv)
591 {
592 int t = currprefs.floppyslots[drv - &floppy[0]].dfxtype;
593
594 switch (t)
595 {
596 case DRV_35_HD:
597 #ifdef FLOPPY_DRIVE_HD
598 if (!drv->diskfile || drv->ddhd <= 1)
599 drv->drive_id = DRIVE_ID_35DD;
600 else
601 drv->drive_id = DRIVE_ID_35HD;
602 #else
603 drv->drive_id = DRIVE_ID_35DD;
604 #endif
605 break;
606 case DRV_35_DD_ESCOM:
607 case DRV_35_DD:
608 default:
609 drv->drive_id = DRIVE_ID_35DD;
610 break;
611 case DRV_525_SD:
612 drv->drive_id = DRIVE_ID_525SD;
613 break;
614 case DRV_NONE:
615 drv->drive_id = DRIVE_ID_NONE;
616 break;
617 }
618 #ifdef DEBUG_DRIVE_ID
619 write_log (_T("drive_settype_id: DF%d: set to %s\n"), drv-floppy, drive_id_name(drv));
620 #endif
621 }
622
drive_image_free(drive * drv)623 static void drive_image_free (drive *drv)
624 {
625 switch (drv->filetype)
626 {
627 case ADF_IPF:
628 #ifdef CAPS
629 caps_unloadimage (drv - floppy);
630 #endif
631 break;
632 case ADF_FDI:
633 #ifdef FDI2RAW
634 fdi2raw_header_free (drv->fdi);
635 drv->fdi = 0;
636 #endif
637 break;
638 case ADF_NONE:
639 case ADF_NORMAL:
640 case ADF_EXT1:
641 case ADF_EXT2:
642 case ADF_CATWEASEL:
643 case ADF_PCDOS:
644 break;
645 }
646 drv->filetype = ADF_NONE;
647 zfile_fclose (drv->diskfile);
648 drv->diskfile = 0;
649 zfile_fclose (drv->writediskfile);
650 drv->writediskfile = 0;
651 }
652
653 static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR *fname, bool fake, bool writeprotected);
654
reset_drive_gui(int num)655 static void reset_drive_gui (int num)
656 {
657 gui_data.drive_disabled[num] = 0;
658 gui_data.df[num][0] = 0;
659 gui_data.crc32[num] = 0;
660 if (currprefs.floppyslots[num].dfxtype < 0)
661 gui_data.drive_disabled[num] = 1;
662 }
663
setamax(void)664 static void setamax (void)
665 {
666 #ifdef AMAX
667 if (currprefs.amaxromfile[0]) {
668 /* Put A-Max as last drive in drive chain */
669 int j;
670 for (j = 0; j < MAX_FLOPPY_DRIVES; j++)
671 if (floppy[j].amax)
672 return;
673 for (j = 0; j < MAX_FLOPPY_DRIVES; j++) {
674 if ((1 << j) & disabled) {
675 floppy[j].amax = 1;
676 write_log (_T("AMAX: drive %d\n"), j);
677 return;
678 }
679 }
680 }
681 #endif
682 }
683
reset_drive(int num)684 static void reset_drive (int num)
685 {
686 drive *drv = &floppy[num];
687
688 drv->amax = 0;
689 drive_image_free (drv);
690 drv->motoroff = 1;
691 drv->idbit = 0;
692 drv->drive_id = 0;
693 drv->drive_id_scnt = 0;
694 disabled &= ~(1 << num);
695 if (currprefs.floppyslots[num].dfxtype < 0)
696 disabled |= 1 << num;
697 reset_drive_gui (num);
698 /* most internal Amiga floppy drives won't enable
699 * diskready until motor is running at full speed
700 * and next indexsync has been passed
701 */
702 drv->indexhackmode = 0;
703 if (num == 0 && currprefs.floppyslots[num].dfxtype == 0)
704 drv->indexhackmode = 1;
705 drv->dskchange_time = 0;
706 drv->dskchange = false;
707 drv->dskready_down_time = 0;
708 drv->dskready_up_time = 0;
709 drv->buffered_cyl = -1;
710 drv->buffered_side = -1;
711 gui_led (num + LED_DF0, 0);
712 drive_settype_id (drv);
713 _tcscpy (currprefs.floppyslots[num].df, changed_prefs.floppyslots[num].df);
714
715 drv->newname[0] = 0;
716 drv->newnamewriteprotected = false;
717 if (!drive_insert (drv, &currprefs, num, currprefs.floppyslots[num].df, false, false))
718 disk_eject (num);
719 }
720
721 /* code for track display */
update_drive_gui(int num,bool force)722 static void update_drive_gui (int num, bool force)
723 {
724 drive *drv = floppy + num;
725 bool writ = dskdmaen == DSKDMA_WRITE && drv->state && !((selected | disabled) & (1 << num));
726
727 if (!force && drv->state == gui_data.drive_motor[num]
728 && drv->cyl == gui_data.drive_track[num]
729 && side == gui_data.drive_side
730 && drv->crc32 == gui_data.crc32[num]
731 && writ == gui_data.drive_writing[num]
732 && !_tcscmp (gui_data.df[num], currprefs.floppyslots[num].df))
733 return;
734 _tcscpy (gui_data.df[num], currprefs.floppyslots[num].df);
735 gui_data.crc32[num] = drv->crc32;
736 gui_data.drive_motor[num] = drv->state;
737 gui_data.drive_track[num] = drv->cyl;
738 gui_data.drive_side = side;
739 gui_data.drive_writing[num] = writ;
740 gui_led (num + LED_DF0, (gui_data.drive_motor[num] ? 1 : 0) | (gui_data.drive_writing[num] ? 2 : 0));
741 }
742
743 static void drive_fill_bigbuf (drive * drv,int);
744
DISK_validate_filename(struct uae_prefs * p,const TCHAR * fname,int leave_open,bool * wrprot,uae_u32 * crc32,struct zfile ** zf)745 int DISK_validate_filename (struct uae_prefs *p, const TCHAR *fname, int leave_open, bool *wrprot, uae_u32 *crc32, struct zfile **zf)
746 {
747 if (zf)
748 *zf = NULL;
749 if (crc32)
750 *crc32 = 0;
751 if (wrprot)
752 *wrprot = p->floppy_read_only ? 1 : 0;
753 if (leave_open || !zf) {
754 struct zfile *f = zfile_fopen (fname, _T("r+b"), ZFD_NORMAL | ZFD_DISKHISTORY);
755 if (!f) {
756 if (wrprot)
757 *wrprot = 1;
758 f = zfile_fopen (fname, _T("rb"), ZFD_NORMAL | ZFD_DISKHISTORY);
759 }
760 if (f && crc32)
761 *crc32 = zfile_crc32 (f);
762 if (!zf)
763 zfile_fclose (f);
764 else
765 *zf = f;
766 return f ? 1 : 0;
767 } else {
768 if (zfile_exists (fname)) {
769 if (wrprot && !p->floppy_read_only)
770 *wrprot = 0;
771 if (crc32) {
772 struct zfile *f = zfile_fopen (fname, _T("rb"), ZFD_NORMAL | ZFD_DISKHISTORY);
773 if (f)
774 *crc32 = zfile_crc32 (f);
775 zfile_fclose (f);
776 }
777 return 1;
778 } else {
779 if (wrprot)
780 *wrprot = 1;
781 return 0;
782 }
783 }
784 }
785
updatemfmpos(drive * drv)786 static void updatemfmpos (drive *drv)
787 {
788 if (drv->prevtracklen)
789 drv->mfmpos = drv->mfmpos * (drv->tracklen * 1000 / drv->prevtracklen) / 1000;
790 drv->mfmpos %= drv->tracklen;
791 drv->prevtracklen = drv->tracklen;
792 }
793
track_reset(drive * drv)794 static void track_reset (drive *drv)
795 {
796 drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 2 * 8;
797 drv->revolutions = 1;
798 drv->trackspeed = get_floppy_speed ();
799 drv->buffered_side = -1;
800 drv->skipoffset = -1;
801 drv->tracktiming[0] = 0;
802 memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
803 updatemfmpos (drv);
804 }
805
read_header_ext2(struct zfile * diskfile,trackid * trackdata,int * num_tracks,int * ddhd)806 static int read_header_ext2 (struct zfile *diskfile, trackid *trackdata, int *num_tracks, int *ddhd)
807 {
808 uae_u8 buffer[2 + 2 + 4 + 4];
809 trackid *tid;
810 int offs;
811 int i;
812
813 zfile_fseek (diskfile, 0, SEEK_SET);
814 zfile_fread (buffer, 1, 8, diskfile);
815 if (strncmp ((char*)buffer, "UAE-1ADF", 8))
816 return 0;
817 zfile_fread (buffer, 1, 4, diskfile);
818 *num_tracks = buffer[2] * 256 + buffer[3];
819 offs = 8 + 2 + 2 + (*num_tracks) * (2 + 2 + 4 + 4);
820
821 for (i = 0; i < (*num_tracks); i++) {
822 tid = trackdata + i;
823 zfile_fread (buffer, 2 + 2 + 4 + 4, 1, diskfile);
824 tid->type = (image_tracktype)buffer[3];
825 tid->revolutions = buffer[2] + 1;
826 tid->len = buffer[5] * 65536 + buffer[6] * 256 + buffer[7];
827 tid->bitlen = buffer[9] * 65536 + buffer[10] * 256 + buffer[11];
828 tid->offs = offs;
829 if (tid->len > 20000 && ddhd)
830 *ddhd = 2;
831 tid->track = i;
832 offs += tid->len;
833 }
834 return 1;
835 }
836
DISK_get_saveimagepath(const TCHAR * name)837 TCHAR *DISK_get_saveimagepath (const TCHAR *name)
838 {
839 static TCHAR name1[MAX_DPATH];
840 TCHAR name2[MAX_DPATH];
841 TCHAR path[MAX_DPATH];
842 int i;
843
844 _tcscpy (name2, name);
845 i = _tcslen (name2) - 1;
846 while (i > 0) {
847 if (name2[i] == '.') {
848 name2[i] = 0;
849 break;
850 }
851 i--;
852 }
853 while (i > 0) {
854 if (name2[i] == '/' || name2[i] == '\\'
855 #ifdef TARGET_AMIGAOS
856 || name2[i] == ':'
857 #endif
858 ) {
859 i++;
860 break;
861 }
862 i--;
863 }
864 fetch_saveimagepath (path, sizeof path / sizeof (TCHAR), 1);
865 _stprintf (name1, _T("%s%s_save.adf"), path, name2 + i);
866 return name1;
867 }
868
getwritefile(struct uae_prefs * p,const TCHAR * name,bool * wrprot)869 static struct zfile *getwritefile (struct uae_prefs *p, const TCHAR *name, bool *wrprot)
870 {
871 struct zfile *zf;
872 DISK_validate_filename (p, DISK_get_saveimagepath (name), 1, wrprot, NULL, &zf);
873 return zf;
874 }
875
iswritefileempty(struct uae_prefs * p,const TCHAR * name)876 static int iswritefileempty (struct uae_prefs *p, const TCHAR *name)
877 {
878 struct zfile *zf;
879 bool wrprot;
880 uae_char buffer[8];
881 trackid td[MAX_TRACKS];
882 int tracks, ddhd, i, ret;
883
884 zf = getwritefile (p, name, &wrprot);
885 if (!zf) return 1;
886 zfile_fread (buffer, sizeof (char), 8, zf);
887 if (strncmp ((uae_char*)buffer, "UAE-1ADF", 8))
888 return 0;
889 ret = read_header_ext2 (zf, td, &tracks, &ddhd);
890 zfile_fclose (zf);
891 if (!ret)
892 return 1;
893 for (i = 0; i < tracks; i++) {
894 if (td[i].bitlen) return 0;
895 }
896 return 1;
897 }
898
openwritefile(struct uae_prefs * p,drive * drv,int create)899 static int openwritefile (struct uae_prefs *p, drive *drv, int create)
900 {
901 bool wrprot = 0;
902
903 drv->writediskfile = getwritefile (p, currprefs.floppyslots[drv - &floppy[0]].df, &wrprot);
904 if (drv->writediskfile) {
905 drv->wrprot = wrprot;
906 if (!read_header_ext2 (drv->writediskfile, drv->writetrackdata, &drv->write_num_tracks, 0)) {
907 zfile_fclose (drv->writediskfile);
908 drv->writediskfile = 0;
909 drv->wrprot = 1;
910 } else {
911 if (drv->write_num_tracks > drv->num_tracks)
912 drv->num_tracks = drv->write_num_tracks;
913 }
914 } else if (zfile_iscompressed (drv->diskfile)) {
915 drv->wrprot = 1;
916 }
917 return drv->writediskfile ? 1 : 0;
918 }
919
diskfile_iswriteprotect(struct uae_prefs * p,const TCHAR * fname,int * needwritefile,drive_type * drvtype)920 static bool diskfile_iswriteprotect (struct uae_prefs *p, const TCHAR *fname, int *needwritefile, drive_type *drvtype)
921 {
922 struct zfile *zf1, *zf2;
923 bool wrprot1 = 0, wrprot2 = 1;
924 uae_char buffer[25];
925
926 *needwritefile = 0;
927 *drvtype = DRV_35_DD;
928 DISK_validate_filename (p, fname, 1, &wrprot1, NULL, &zf1);
929 if (!zf1)
930 return 1;
931 if (zfile_iscompressed (zf1)) {
932 wrprot1 = 1;
933 *needwritefile = 1;
934 }
935 zf2 = getwritefile (p, fname, &wrprot2);
936 zfile_fclose (zf2);
937 zfile_fread (buffer, sizeof (char), 25, zf1);
938 zfile_fclose (zf1);
939 if (strncmp ((uae_char*) buffer, "CAPS", 4) == 0) {
940 *needwritefile = 1;
941 return wrprot2;
942 }
943 if (strncmp ((uae_char*) buffer, "Formatted Disk Image file", 25) == 0) {
944 *needwritefile = 1;
945 return wrprot2;
946 }
947 if (strncmp ((uae_char*) buffer, "UAE-1ADF", 8) == 0) {
948 if (wrprot1)
949 return wrprot2;
950 return wrprot1;
951 }
952 if (strncmp ((uae_char*) buffer, "UAE--ADF", 8) == 0) {
953 *needwritefile = 1;
954 return wrprot2;
955 }
956 if (memcmp (exeheader, buffer, sizeof (exeheader)) == 0)
957 return 0;
958 if (wrprot1)
959 return wrprot2;
960 return wrprot1;
961 }
962
drive_insert(drive * drv,struct uae_prefs * p,int dnum,const TCHAR * fname,bool fake,bool forcedwriteprotect)963 static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR *fname, bool fake, bool forcedwriteprotect)
964 {
965 uae_u8 buffer[2 + 2 + 4 + 4];
966 trackid *tid;
967 #ifdef CAPS
968 int num_tracks;
969 #endif
970 int size;
971 int canauto;
972 const TCHAR *ext;
973
974 drive_image_free (drv);
975 DISK_validate_filename (p, fname, 1, &drv->wrprot, &drv->crc32, &drv->diskfile);
976 drv->forcedwrprot = forcedwriteprotect;
977 if (drv->forcedwrprot)
978 drv->wrprot = true;
979 drv->ddhd = 1;
980 drv->num_secs = 0;
981 drv->hard_num_cyls = p->floppyslots[dnum].dfxtype == DRV_525_SD ? 40 : 80;
982 drv->tracktiming[0] = 0;
983 drv->useturbo = 0;
984 drv->indexoffset = 0;
985
986 gui_disk_image_change (dnum, fname, drv->wrprot);
987
988 canauto = 0;
989 ext = _tcsrchr (fname, '.');
990 if (ext) {
991 if (!_tcsicmp (ext + 1, _T("adf")) || !_tcsicmp (ext + 1, _T("adz")) || !_tcsicmp (ext + 1, _T("st")) || !_tcsicmp (ext + 1, _T("ima")) || !_tcsicmp (ext + 1, _T("img")))
992 canauto = 1;
993 }
994
995 if (!drv->motoroff) {
996 drv->dskready_up_time = DSKREADY_UP_TIME;
997 drv->dskready_down_time = 0;
998 }
999
1000 if (drv->diskfile == 0 && !drv->catweasel) {
1001 track_reset (drv);
1002 return 0;
1003 }
1004
1005 if (!fake)
1006 inprec_recorddiskchange (dnum, fname, drv->wrprot);
1007
1008 _tcsncpy (currprefs.floppyslots[dnum].df, fname, 255);
1009 currprefs.floppyslots[dnum].df[255] = 0;
1010 currprefs.floppyslots[dnum].forcedwriteprotect = forcedwriteprotect;
1011 _tcsncpy (changed_prefs.floppyslots[dnum].df, fname, 255);
1012 changed_prefs.floppyslots[dnum].df[255] = 0;
1013 changed_prefs.floppyslots[dnum].forcedwriteprotect = forcedwriteprotect;
1014 if (drv->newname != fname)
1015 _tcscpy (drv->newname, fname);
1016 drv->newnamewriteprotected = forcedwriteprotect;
1017 gui_filename (dnum, fname);
1018
1019 memset (buffer, 0, sizeof buffer);
1020 size = 0;
1021 if (drv->diskfile) {
1022 zfile_fread (buffer, sizeof (char), 8, drv->diskfile);
1023 zfile_fseek (drv->diskfile, 0, SEEK_END);
1024 size = zfile_ftell (drv->diskfile);
1025 zfile_fseek (drv->diskfile, 0, SEEK_SET);
1026 }
1027
1028 if (drv->catweasel) {
1029
1030 drv->wrprot = true;
1031 drv->filetype = ADF_CATWEASEL;
1032 drv->num_tracks = 80;
1033 drv->ddhd = 1;
1034
1035 #ifdef CAPS
1036 } else if (strncmp ((char*)buffer, "CAPS", 4) == 0) {
1037
1038 drv->wrprot = true;
1039 if (!caps_loadimage (drv->diskfile, drv - floppy, &num_tracks)) {
1040 zfile_fclose (drv->diskfile);
1041 drv->diskfile = 0;
1042 return 0;
1043 }
1044 drv->num_tracks = num_tracks;
1045 drv->filetype = ADF_IPF;
1046 #endif
1047 #ifdef FDI2RAW
1048 } else if ( (drv->fdi = fdi2raw_header (drv->diskfile)) ) {
1049
1050 drv->wrprot = true;
1051 drv->num_tracks = fdi2raw_get_last_track (drv->fdi);
1052 drv->num_secs = fdi2raw_get_num_sector (drv->fdi);
1053 drv->filetype = ADF_FDI;
1054 #endif
1055 } else if (strncmp ((char*)buffer, "UAE-1ADF", 8) == 0) {
1056
1057 read_header_ext2 (drv->diskfile, drv->trackdata, &drv->num_tracks, &drv->ddhd);
1058 drv->filetype = ADF_EXT2;
1059 drv->num_secs = 11;
1060 if (drv->ddhd > 1)
1061 drv->num_secs = 22;
1062
1063 } else if (strncmp ((char*)buffer, "UAE--ADF", 8) == 0) {
1064 int offs = 160 * 4 + 8;
1065 int i;
1066
1067 drv->wrprot = true;
1068 drv->filetype = ADF_EXT1;
1069 drv->num_tracks = 160;
1070 drv->num_secs = 11;
1071
1072 zfile_fseek (drv->diskfile, 8, SEEK_SET);
1073 for (i = 0; i < 160; i++) {
1074 tid = &drv->trackdata[i];
1075 zfile_fread (buffer, 4, 1, drv->diskfile);
1076 tid->sync = buffer[0] * 256 + buffer[1];
1077 tid->len = buffer[2] * 256 + buffer[3];
1078 tid->offs = offs;
1079 tid->revolutions = 1;
1080 if (tid->sync == 0) {
1081 tid->type = TRACK_AMIGADOS;
1082 tid->bitlen = 0;
1083 } else {
1084 tid->type = TRACK_RAW1;
1085 tid->bitlen = tid->len * 8;
1086 }
1087 offs += tid->len;
1088 }
1089
1090 } else if (memcmp (exeheader, buffer, sizeof (exeheader)) == 0) {
1091 int i;
1092 struct zfile *z = zfile_fopen_empty (NULL, _T(""), 512 * 1760);
1093 createimagefromexe (drv->diskfile, z);
1094 drv->filetype = ADF_NORMAL;
1095 zfile_fclose (drv->diskfile);
1096 drv->diskfile = z;
1097 drv->num_tracks = 160;
1098 drv->num_secs = 11;
1099 for (i = 0; i < drv->num_tracks; i++) {
1100 tid = &drv->trackdata[i];
1101 tid->type = TRACK_AMIGADOS;
1102 tid->len = 512 * drv->num_secs;
1103 tid->bitlen = 0;
1104 tid->offs = i * 512 * drv->num_secs;
1105 tid->revolutions = 1;
1106 }
1107 drv->useturbo = 1;
1108
1109 } else if (canauto && (
1110
1111 // double sided
1112 size == 9 * 80 * 2 * 512 || size == 18 * 80 * 2 * 512 || size == 10 * 80 * 2 * 512 || size == 20 * 80 * 2 * 512 ||
1113 size == 9 * 81 * 2 * 512 || size == 18 * 81 * 2 * 512 || size == 10 * 81 * 2 * 512 || size == 20 * 81 * 2 * 512 ||
1114 size == 9 * 82 * 2 * 512 || size == 18 * 82 * 2 * 512 || size == 10 * 82 * 2 * 512 || size == 20 * 82 * 2 * 512 ||
1115 // single sided
1116 size == 9 * 80 * 1 * 512 || size == 18 * 80 * 1 * 512 || size == 10 * 80 * 1 * 512 || size == 20 * 80 * 1 * 512 ||
1117 size == 9 * 81 * 1 * 512 || size == 18 * 81 * 1 * 512 || size == 10 * 81 * 1 * 512 || size == 20 * 81 * 1 * 512 ||
1118 size == 9 * 82 * 1 * 512 || size == 18 * 82 * 1 * 512 || size == 10 * 82 * 1 * 512 || size == 20 * 82 * 1 * 512)) {
1119 /* PC formatted image */
1120 int i, side;
1121
1122 for (side = 2; side > 0; side--) {
1123 if ( size == 9 * 80 * side * 512 || size == 9 * 81 * side * 512 || size == 9 * 82 * side * 512) {
1124 drv->num_secs = 9;
1125 drv->ddhd = 1;
1126 break;
1127 } else if (size == 18 * 80 * side * 512 || size == 18 * 81 * side * 512 || size == 18 * 82 * side * 512) {
1128 drv->num_secs = 18;
1129 drv->ddhd = 2;
1130 break;
1131 } else if (size == 10 * 80 * side * 512 || size == 10 * 81 * side * 512 || size == 10 * 82 * side * 512) {
1132 drv->num_secs = 10;
1133 drv->ddhd = 1;
1134 break;
1135 } else if (size == 20 * 80 * side * 512 || size == 20 * 81 * side * 512 || size == 20 * 82 * side * 512) {
1136 drv->num_secs = 20;
1137 drv->ddhd = 2;
1138 break;
1139 }
1140 }
1141 drv->num_tracks = size / (drv->num_secs * 512);
1142
1143 drv->filetype = ADF_PCDOS;
1144 tid = &drv->trackdata[0];
1145 for (i = 0; i < drv->num_tracks; i++) {
1146 tid->type = TRACK_PCDOS;
1147 tid->len = 512 * drv->num_secs;
1148 tid->bitlen = 0;
1149 tid->offs = i * 512 * drv->num_secs;
1150 if (side == 1) {
1151 tid++;
1152 tid->type = TRACK_NONE;
1153 tid->len = 512 * drv->num_secs;
1154 }
1155 tid->revolutions = 1;
1156 tid++;
1157
1158 }
1159 if (side == 1)
1160 drv->num_tracks *= 2;
1161
1162 } else {
1163 int i, ds;
1164
1165 ds = 0;
1166 drv->filetype = ADF_NORMAL;
1167
1168 /* High-density or diskspare disk? */
1169 drv->num_tracks = 0;
1170 if (size > 160 * 11 * 512 + 511) { // larger than standard adf?
1171 for (i = 80; i <= 83; i++) {
1172 if (size == i * 22 * 512 * 2) { // HD
1173 drv->ddhd = 2;
1174 drv->num_tracks = size / (512 * (drv->num_secs = 22));
1175 break;
1176 }
1177 if (size == i * 11 * 512 * 2) { // >80 cyl DD
1178 drv->num_tracks = size / (512 * (drv->num_secs = 11));
1179 break;
1180 }
1181 if (size == i * 12 * 512 * 2) { // ds 12 sectors
1182 drv->num_tracks = size / (512 * (drv->num_secs = 12));
1183 ds = 1;
1184 break;
1185 }
1186 if (size == i * 24 * 512 * 2) { // ds 24 sectors
1187 drv->num_tracks = size / (512 * (drv->num_secs = 24));
1188 drv->ddhd = 2;
1189 ds = 1;
1190 break;
1191 }
1192 }
1193 if (drv->num_tracks == 0) {
1194 drv->num_tracks = size / (512 * (drv->num_secs = 22));
1195 drv->ddhd = 2;
1196 }
1197 } else {
1198 drv->num_tracks = size / (512 * (drv->num_secs = 11));
1199 }
1200
1201 if (!ds && drv->num_tracks > MAX_TRACKS)
1202 write_log (_T("Your diskfile is too big, %d bytes!\n"), size);
1203 for (i = 0; i < drv->num_tracks; i++) {
1204 tid = &drv->trackdata[i];
1205 tid->type = ds ? TRACK_DISKSPARE : TRACK_AMIGADOS;
1206 tid->len = 512 * drv->num_secs;
1207 tid->bitlen = 0;
1208 tid->offs = i * 512 * drv->num_secs;
1209 tid->revolutions = 1;
1210 }
1211 }
1212 openwritefile (p, drv, 0);
1213 drive_settype_id (drv); /* Set DD or HD drive */
1214 drive_fill_bigbuf (drv, 1);
1215 drv->mfmpos = uaerand ();
1216 drv->mfmpos |= (uaerand () << 16);
1217 drv->mfmpos %= drv->tracklen;
1218 drv->prevtracklen = 0;
1219 #ifdef DRIVESOUND
1220 if (isfloppysound (drv))
1221 driveclick_insert (drv - floppy, 0);
1222 #endif
1223 update_drive_gui (drv - floppy, false);
1224 return 1;
1225 }
1226
rand_shifter(void)1227 static void rand_shifter (void)
1228 {
1229 int r = ((uaerand () >> 4) & 7) + 1;
1230 while (r-- > 0) {
1231 word <<= 1;
1232 word |= (uaerand () & 0x1000) ? 1 : 0;
1233 bitoffset++;
1234 bitoffset &= 15;
1235 }
1236 }
1237
set_steplimit(drive * drv)1238 static void set_steplimit (drive *drv)
1239 {
1240 // emulate step limit only if cycle-exact or approximate CPU speed
1241 if (currprefs.m68k_speed != 0)
1242 return;
1243 drv->steplimit = 4;
1244 drv->steplimitcycle = get_cycles ();
1245 }
1246
drive_empty(drive * drv)1247 static int drive_empty (drive * drv)
1248 {
1249 #ifdef CATWEASEL
1250 if (drv->catweasel)
1251 return catweasel_disk_changed (drv->catweasel) == 0;
1252 #endif
1253 return drv->diskfile == 0 && drv->dskchange_time >= 0;
1254 }
1255
drive_step(drive * drv,int step_direction)1256 static void drive_step (drive * drv, int step_direction)
1257 {
1258 #ifdef CATWEASEL
1259 if (drv->catweasel) {
1260 int dir = direction ? -1 : 1;
1261 catweasel_step (drv->catweasel, dir);
1262 drv->cyl += dir;
1263 if (drv->cyl < 0)
1264 drv->cyl = 0;
1265 write_log (_T("%d -> %d\n"), dir, drv->cyl);
1266 return;
1267 }
1268 #endif
1269 if (!drive_empty (drv))
1270 drv->dskchange = 0;
1271 if (drv->steplimit && get_cycles() - drv->steplimitcycle < MIN_STEPLIMIT_CYCLE) {
1272 if (disk_debug_logging > 1)
1273 write_log (_T(" step ignored drive %d, %d"),
1274 drv - floppy, (get_cycles() - drv->steplimitcycle) / CYCLE_UNIT);
1275 return;
1276 }
1277 /* A1200's floppy drive needs at least 30 raster lines between steps
1278 * but we'll use very small value for better compatibility with faster CPU emulation
1279 * (stupid trackloaders with CPU delay loops)
1280 */
1281 set_steplimit (drv);
1282 if (step_direction) {
1283 if (drv->cyl) {
1284 drv->cyl--;
1285 #ifdef DRIVESOUND
1286 if (isfloppysound (drv))
1287 driveclick_click (drv - floppy, drv->cyl);
1288 #endif
1289 }
1290 /* else
1291 write_log (_T("program tried to step beyond track zero\n"));
1292 "no-click" programs does that
1293 */
1294 } else {
1295 int maxtrack = drv->hard_num_cyls;
1296 if (drv->cyl < maxtrack + 3) {
1297 drv->cyl++;
1298 #ifdef CATWEASEL
1299 if (drv->catweasel)
1300 catweasel_step (drv->catweasel, 1);
1301 #endif
1302 }
1303 if (drv->cyl >= maxtrack)
1304 write_log (_T("program tried to step over track %d\n"), maxtrack);
1305 #ifdef DRIVESOUND
1306 if (isfloppysound (drv))
1307 driveclick_click (drv - floppy, drv->cyl);
1308 #endif
1309 }
1310 rand_shifter ();
1311 if (disk_debug_logging > 1)
1312 write_log (_T(" ->step %d"), drv->cyl);
1313 }
1314
drive_track0(drive * drv)1315 static int drive_track0 (drive * drv)
1316 {
1317 #ifdef CATWEASEL
1318 if (drv->catweasel)
1319 return catweasel_track0 (drv->catweasel);
1320 #endif
1321 return drv->cyl == 0;
1322 }
1323
drive_writeprotected(drive * drv)1324 static int drive_writeprotected (drive * drv)
1325 {
1326 #ifdef CATWEASEL
1327 if (drv->catweasel)
1328 return 1;
1329 #endif
1330 return currprefs.floppy_read_only || drv->wrprot || drv->forcedwrprot || drv->diskfile == NULL;
1331 }
1332
drive_running(drive * drv)1333 static int drive_running (drive * drv)
1334 {
1335 return !drv->motoroff;
1336 }
1337
motordelay_func(uae_u32 v)1338 static void motordelay_func (uae_u32 v)
1339 {
1340 floppy[v].motordelay = 0;
1341 }
1342
drive_motor(drive * drv,bool off)1343 static void drive_motor (drive * drv, bool off)
1344 {
1345 if (drv->motoroff && !off) {
1346 drv->dskready_up_time = DSKREADY_UP_TIME;
1347 rand_shifter ();
1348 #ifdef DRIVESOUND
1349 if (isfloppysound (drv))
1350 driveclick_motor (drv - floppy, drv->dskready_down_time == 0 ? 2 : 1);
1351 #endif
1352 if (disk_debug_logging > 1)
1353 write_log (_T(" ->motor on"));
1354 }
1355 if (!drv->motoroff && off) {
1356 drv->drive_id_scnt = 0; /* Reset id shift reg counter */
1357 drv->dskready_down_time = DSKREADY_DOWN_TIME;
1358 #ifdef DRIVESOUND
1359 driveclick_motor (drv - floppy, 0);
1360 #endif
1361 #ifdef DEBUG_DRIVE_ID
1362 write_log (_T("drive_motor: Selected DF%d: reset id shift reg.\n"),drv-floppy);
1363 #endif
1364 if (disk_debug_logging > 1)
1365 write_log (_T(" ->motor off"));
1366 if (currprefs.cpu_model <= 68010 && currprefs.m68k_speed == 0) {
1367 drv->motordelay = 1;
1368 event2_newevent2 (30, drv - floppy, motordelay_func);
1369 }
1370 }
1371 drv->motoroff = off;
1372 if (drv->motoroff) {
1373 drv->dskready = 0;
1374 drv->dskready_up_time = 0;
1375 } else {
1376 drv->dskready_down_time = 0;
1377 }
1378 #ifdef CATWEASEL
1379 if (drv->catweasel)
1380 catweasel_set_motor (drv->catweasel, !drv->motoroff);
1381 #endif
1382 }
1383
read_floppy_data(struct zfile * diskfile,trackid * tid,int offset,uae_u8 * dst,int len)1384 static void read_floppy_data (struct zfile *diskfile, trackid *tid, int offset, uae_u8 *dst, int len)
1385 {
1386 if (len == 0)
1387 return;
1388 zfile_fseek (diskfile, tid->offs + offset, SEEK_SET);
1389 zfile_fread (dst, 1, len, diskfile);
1390 }
1391
1392 /* Megalomania does not like zero MFM words... */
mfmcode(uae_u16 * mfm,int words)1393 static void mfmcode (uae_u16 * mfm, int words)
1394 {
1395 uae_u32 lastword = 0;
1396 while (words--) {
1397 uae_u32 v = (*mfm) & 0x55555555;
1398 uae_u32 lv = (lastword << 16) | v;
1399 uae_u32 nlv = 0x55555555 & ~lv;
1400 uae_u32 mfmbits = (nlv << 1) & (nlv >> 1);
1401 *mfm++ = v | mfmbits;
1402 lastword = v;
1403 }
1404 }
1405
1406 static uae_u8 mfmencodetable[16] = {
1407 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15,
1408 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55
1409 };
1410
1411
dos_encode_byte(uae_u8 byte)1412 static uae_u16 dos_encode_byte (uae_u8 byte)
1413 {
1414 uae_u8 b2, b1;
1415 uae_u16 word;
1416
1417 b1 = byte;
1418 b2 = b1 >> 4;
1419 b1 &= 15;
1420 word = mfmencodetable[b2] <<8 | mfmencodetable[b1];
1421 return (word | ((word & (256 | 64)) ? 0 : 128));
1422 }
1423
mfmcoder(uae_u8 * src,uae_u16 * dest,int len)1424 static uae_u16 *mfmcoder (uae_u8 *src, uae_u16 *dest, int len)
1425 {
1426 int i;
1427
1428 for (i = 0; i < len; i++) {
1429 *dest = dos_encode_byte (*src++);
1430 *dest |= ((dest[-1] & 1)||(*dest & 0x4000)) ? 0: 0x8000;
1431 dest++;
1432 }
1433 return dest;
1434 }
1435
decode_pcdos(drive * drv)1436 static void decode_pcdos (drive *drv)
1437 {
1438 int i, len;
1439 int tr = drv->cyl * 2 + side;
1440 uae_u16 *dstmfmbuf, *mfm2;
1441 uae_u8 secbuf[1000];
1442 uae_u16 crc16;
1443 trackid *ti = drv->trackdata + tr;
1444 int tracklen = 12500;
1445
1446 mfm2 = drv->bigmfmbuf;
1447 *mfm2++ = 0x9254;
1448 memset (secbuf, 0x4e, 40);
1449 memset (secbuf + 40, 0x00, 12);
1450 secbuf[52] = 0xc2;
1451 secbuf[53] = 0xc2;
1452 secbuf[54] = 0xc2;
1453 secbuf[55] = 0xfc;
1454 memset (secbuf + 56, 0x4e, 40);
1455 dstmfmbuf = mfmcoder (secbuf, mfm2, 96);
1456 mfm2[52] = 0x5224;
1457 mfm2[53] = 0x5224;
1458 mfm2[54] = 0x5224;
1459 for (i = 0; i < drv->num_secs; i++) {
1460 mfm2 = dstmfmbuf;
1461 memset (secbuf, 0x00, 12);
1462 secbuf[12] = 0xa1;
1463 secbuf[13] = 0xa1;
1464 secbuf[14] = 0xa1;
1465 secbuf[15] = 0xfe;
1466 secbuf[16] = drv->cyl;
1467 secbuf[17] = side;
1468 secbuf[18] = 1 + i;
1469 secbuf[19] = 2; // 128 << 2 = 512
1470 crc16 = get_crc16(secbuf + 12, 3 + 1 + 4);
1471 secbuf[20] = crc16 >> 8;
1472 secbuf[21] = crc16 & 0xff;
1473 memset(secbuf + 22, 0x4e, 22);
1474 memset(secbuf + 44, 0x00, 12);
1475 secbuf[56] = 0xa1;
1476 secbuf[57] = 0xa1;
1477 secbuf[58] = 0xa1;
1478 secbuf[59] = 0xfb;
1479 read_floppy_data (drv->diskfile, ti, i * 512, &secbuf[60], 512);
1480 crc16 = get_crc16 (secbuf + 56, 3 + 1 + 512);
1481 secbuf[60 + 512] = crc16 >> 8;
1482 secbuf[61 + 512] = crc16 & 0xff;
1483 len = (tracklen / 2 - 96) / drv->num_secs - 574 / drv->ddhd;
1484 if (len > 0)
1485 memset(secbuf + 512 + 62, 0x4e, len);
1486 dstmfmbuf = mfmcoder (secbuf, mfm2, 60 + 512 + 2 + 76 / drv->ddhd);
1487 mfm2[12] = 0x4489;
1488 mfm2[13] = 0x4489;
1489 mfm2[14] = 0x4489;
1490 mfm2[56] = 0x4489;
1491 mfm2[57] = 0x4489;
1492 mfm2[58] = 0x4489;
1493 }
1494 while (dstmfmbuf - drv->bigmfmbuf < tracklen / 2)
1495 *dstmfmbuf++ = 0x9254;
1496 drv->skipoffset = 0;
1497 drv->tracklen = (dstmfmbuf - drv->bigmfmbuf) * 16;
1498 if (disk_debug_logging > 0)
1499 write_log (_T("pcdos read track %d\n"), tr);
1500 }
1501
decode_amigados(drive * drv)1502 static void decode_amigados (drive *drv)
1503 {
1504 /* Normal AmigaDOS format track */
1505 int tr = drv->cyl * 2 + side;
1506 int sec;
1507 int dstmfmoffset = 0;
1508 uae_u16 *dstmfmbuf = drv->bigmfmbuf;
1509 int len = drv->num_secs * 544 + FLOPPY_GAP_LEN;
1510 int prevbit;
1511
1512 trackid *ti = drv->trackdata + tr;
1513 memset (dstmfmbuf, 0xaa, len * 2);
1514 dstmfmoffset += FLOPPY_GAP_LEN;
1515 drv->skipoffset = (FLOPPY_GAP_LEN * 8) / 3 * 2;
1516 drv->tracklen = len * 2 * 8;
1517
1518 prevbit = 0;
1519 for (sec = 0; sec < drv->num_secs; sec++) {
1520 uae_u8 secbuf[544];
1521 uae_u16 mfmbuf[544 + 1];
1522 int i;
1523 uae_u32 deven, dodd;
1524 uae_u32 hck = 0, dck = 0;
1525
1526 secbuf[0] = secbuf[1] = 0x00;
1527 secbuf[2] = secbuf[3] = 0xa1;
1528 secbuf[4] = 0xff;
1529 secbuf[5] = tr;
1530 secbuf[6] = sec;
1531 secbuf[7] = drv->num_secs - sec;
1532
1533 for (i = 8; i < 24; i++)
1534 secbuf[i] = 0;
1535
1536 read_floppy_data (drv->diskfile, ti, sec * 512, &secbuf[32], 512);
1537
1538 mfmbuf[0] = prevbit ? 0x2aaa : 0xaaaa;
1539 mfmbuf[1] = 0xaaaa;
1540 mfmbuf[2] = mfmbuf[3] = 0x4489;
1541
1542 deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
1543 | (secbuf[6] << 8) | (secbuf[7]));
1544 dodd = deven >> 1;
1545 deven &= 0x55555555;
1546 dodd &= 0x55555555;
1547
1548 mfmbuf[4] = dodd >> 16;
1549 mfmbuf[5] = dodd;
1550 mfmbuf[6] = deven >> 16;
1551 mfmbuf[7] = deven;
1552
1553 for (i = 8; i < 48; i++)
1554 mfmbuf[i] = 0xaaaa;
1555 for (i = 0; i < 512; i += 4) {
1556 deven = ((secbuf[i + 32] << 24) | (secbuf[i + 33] << 16)
1557 | (secbuf[i + 34] << 8) | (secbuf[i + 35]));
1558 dodd = deven >> 1;
1559 deven &= 0x55555555;
1560 dodd &= 0x55555555;
1561 mfmbuf[(i >> 1) + 32] = dodd >> 16;
1562 mfmbuf[(i >> 1) + 33] = dodd;
1563 mfmbuf[(i >> 1) + 256 + 32] = deven >> 16;
1564 mfmbuf[(i >> 1) + 256 + 33] = deven;
1565 }
1566
1567 for (i = 4; i < 24; i += 2)
1568 hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
1569
1570 deven = dodd = hck;
1571 dodd >>= 1;
1572 mfmbuf[24] = dodd >> 16;
1573 mfmbuf[25] = dodd;
1574 mfmbuf[26] = deven >> 16;
1575 mfmbuf[27] = deven;
1576
1577 for (i = 32; i < 544; i += 2)
1578 dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
1579
1580 deven = dodd = dck;
1581 dodd >>= 1;
1582 mfmbuf[28] = dodd >> 16;
1583 mfmbuf[29] = dodd;
1584 mfmbuf[30] = deven >> 16;
1585 mfmbuf[31] = deven;
1586
1587 mfmbuf[544] = 0;
1588
1589 mfmcode (mfmbuf + 4, 544 - 4 + 1);
1590
1591 for (i = 0; i < 544; i++) {
1592 dstmfmbuf[dstmfmoffset % len] = mfmbuf[i];
1593 dstmfmoffset++;
1594 }
1595 prevbit = mfmbuf[i - 1] & 1;
1596 // so that final word has correct MFM encoding
1597 dstmfmbuf[dstmfmoffset % len] = mfmbuf[i];
1598 }
1599
1600 if (disk_debug_logging > 0)
1601 write_log (_T("amigados read track %d\n"), tr);
1602 }
1603
1604 /*
1605 * diskspare format
1606 *
1607 * 0 <4489> <4489> 0 track sector crchi, crclo, data[512] (520 bytes per sector)
1608 *
1609 * 0xAAAA 0x4489 0x4489 0x2AAA oddhi, oddlo, evenhi, evenlo, ...
1610 *
1611 * NOTE: data is MFM encoded using same method as ADOS header, not like ADOS data!
1612 *
1613 */
1614
decode_diskspare(drive * drv)1615 static void decode_diskspare (drive *drv)
1616 {
1617 int tr = drv->cyl * 2 + side;
1618 int sec;
1619 int dstmfmoffset = 0;
1620 int size = 512 + 8;
1621 uae_u16 *dstmfmbuf = drv->bigmfmbuf;
1622 int len = drv->num_secs * size + FLOPPY_GAP_LEN;
1623
1624 trackid *ti = drv->trackdata + tr;
1625 memset (dstmfmbuf, 0xaa, len * 2);
1626 dstmfmoffset += FLOPPY_GAP_LEN;
1627 drv->skipoffset = (FLOPPY_GAP_LEN * 8) / 3 * 2;
1628 drv->tracklen = len * 2 * 8;
1629
1630 for (sec = 0; sec < drv->num_secs; sec++) {
1631 uae_u8 secbuf[512 + 8];
1632 uae_u16 mfmbuf[512 + 8];
1633 int i;
1634 uae_u32 deven, dodd;
1635 uae_u16 chk;
1636
1637 secbuf[0] = tr;
1638 secbuf[1] = sec;
1639 secbuf[2] = 0;
1640 secbuf[3] = 0;
1641
1642 read_floppy_data (drv->diskfile, ti, sec * 512, &secbuf[4], 512);
1643
1644 mfmbuf[0] = 0xaaaa;
1645 mfmbuf[1] = 0x4489;
1646 mfmbuf[2] = 0x4489;
1647 mfmbuf[3] = 0x2aaa;
1648
1649 for (i = 0; i < 512; i += 4) {
1650 deven = ((secbuf[i + 4] << 24) | (secbuf[i + 5] << 16)
1651 | (secbuf[i + 6] << 8) | (secbuf[i + 7]));
1652 dodd = deven >> 1;
1653 deven &= 0x55555555;
1654 dodd &= 0x55555555;
1655 mfmbuf[i + 8 + 0] = dodd >> 16;
1656 mfmbuf[i + 8 + 1] = dodd;
1657 mfmbuf[i + 8 + 2] = deven >> 16;
1658 mfmbuf[i + 8 + 3] = deven;
1659 }
1660 mfmcode (mfmbuf + 8, 512);
1661
1662 i = 8;
1663 chk = mfmbuf[i++] & 0x7fff;
1664 while (i < 512 + 8)
1665 chk ^= mfmbuf[i++];
1666 secbuf[2] = chk >> 8;
1667 secbuf[3] = chk;
1668
1669 deven = ((secbuf[0] << 24) | (secbuf[1] << 16)
1670 | (secbuf[2] << 8) | (secbuf[3]));
1671 dodd = deven >> 1;
1672 deven &= 0x55555555;
1673 dodd &= 0x55555555;
1674
1675 mfmbuf[4] = dodd >> 16;
1676 mfmbuf[5] = dodd;
1677 mfmbuf[6] = deven >> 16;
1678 mfmbuf[7] = deven;
1679 mfmcode (mfmbuf + 4, 4);
1680
1681 for (i = 0; i < 512 + 8; i++) {
1682 dstmfmbuf[dstmfmoffset % len] = mfmbuf[i];
1683 dstmfmoffset++;
1684 }
1685 }
1686
1687 if (disk_debug_logging > 0)
1688 write_log (_T("diskspare read track %d\n"), tr);
1689 }
1690
drive_fill_bigbuf(drive * drv,int force)1691 static void drive_fill_bigbuf (drive * drv, int force)
1692 {
1693 int tr = drv->cyl * 2 + side;
1694 trackid *ti = drv->trackdata + tr;
1695
1696 if ((!drv->diskfile && !drv->catweasel) || tr >= drv->num_tracks) {
1697 track_reset (drv);
1698 return;
1699 }
1700
1701 if (!force && drv->catweasel) {
1702 drv->buffered_cyl = -1;
1703 return;
1704 }
1705
1706 if (!force && drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
1707 return;
1708 drv->indexoffset = 0;
1709 drv->multi_revolution = 0;
1710 drv->tracktiming[0] = 0;
1711 drv->skipoffset = -1;
1712 drv->revolutions = 1;
1713
1714 if (drv->writediskfile && drv->writetrackdata[tr].bitlen > 0) {
1715 int i;
1716 trackid *wti = &drv->writetrackdata[tr];
1717 drv->tracklen = wti->bitlen;
1718 drv->revolutions = wti->revolutions;
1719 read_floppy_data (drv->writediskfile, wti, 0, (uae_u8*)drv->bigmfmbuf, (wti->bitlen + 7) / 8);
1720 for (i = 0; i < (drv->tracklen + 15) / 16; i++) {
1721 uae_u16 *mfm = drv->bigmfmbuf + i;
1722 uae_u8 *data = (uae_u8 *) mfm;
1723 *mfm = 256 * *data + *(data + 1);
1724 }
1725 if (disk_debug_logging > 0)
1726 write_log (_T("track %d, length %d read from \"saveimage\"\n"), tr, drv->tracklen);
1727 } else if (drv->filetype == ADF_CATWEASEL) {
1728 #ifdef CATWEASEL
1729 drv->tracklen = 0;
1730 if (!catweasel_disk_changed (drv->catweasel)) {
1731 drv->tracklen = catweasel_fillmfm (drv->catweasel, drv->bigmfmbuf, side, drv->ddhd, 0);
1732 }
1733 drv->buffered_cyl = -1;
1734 if (!drv->tracklen) {
1735 track_reset (drv);
1736 return;
1737 }
1738 #endif
1739 } else if (drv->filetype == ADF_IPF) {
1740
1741 #ifdef CAPS
1742 caps_loadtrack (drv->bigmfmbuf, drv->tracktiming, drv - floppy, tr, &drv->tracklen, &drv->multi_revolution, &drv->skipoffset);
1743 #endif
1744
1745 } else if (drv->filetype == ADF_FDI) {
1746
1747 #ifdef FDI2RAW
1748 fdi2raw_loadtrack (drv->fdi, drv->bigmfmbuf, drv->tracktiming, tr, &drv->tracklen, &drv->indexoffset, &drv->multi_revolution, 1);
1749 #endif
1750
1751 } else if (ti->type == TRACK_PCDOS) {
1752
1753 decode_pcdos (drv);
1754
1755 } else if (ti->type == TRACK_AMIGADOS) {
1756
1757 decode_amigados (drv);
1758
1759 } else if (ti->type == TRACK_DISKSPARE) {
1760
1761 decode_diskspare (drv);
1762
1763 } else if (ti->type == TRACK_NONE) {
1764
1765 ;
1766
1767 } else {
1768 int i;
1769 int base_offset = ti->type == TRACK_RAW ? 0 : 1;
1770 drv->tracklen = ti->bitlen + 16 * base_offset;
1771 drv->bigmfmbuf[0] = ti->sync;
1772 read_floppy_data (drv->diskfile, ti, 0, (uae_u8*)(drv->bigmfmbuf + base_offset), (ti->bitlen + 7) / 8);
1773 for (i = base_offset; i < (drv->tracklen + 15) / 16; i++) {
1774 uae_u16 *mfm = drv->bigmfmbuf + i;
1775 uae_u8 *data = (uae_u8 *) mfm;
1776 *mfm = 256 * *data + *(data + 1);
1777 }
1778 if (disk_debug_logging > 1)
1779 write_log (_T("rawtrack %d image offset=%x\n"), tr, ti->offs);
1780 }
1781 drv->buffered_side = side;
1782 drv->buffered_cyl = drv->cyl;
1783 if (drv->tracklen == 0) {
1784 drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 2 * 8;
1785 memset (drv->bigmfmbuf, 0, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
1786 }
1787
1788 drv->trackspeed = get_floppy_speed2 (drv);
1789 updatemfmpos (drv);
1790 }
1791
1792 /* Update ADF_EXT2 track header */
diskfile_update(struct zfile * diskfile,trackid * ti,int len,image_tracktype type)1793 static void diskfile_update (struct zfile *diskfile, trackid *ti, int len, image_tracktype type)
1794 {
1795 uae_u8 buf[2 + 2 + 4 + 4], *zerobuf;
1796
1797 ti->revolutions = 1;
1798 ti->bitlen = len;
1799 zfile_fseek (diskfile, 8 + 4 + (2 + 2 + 4 + 4) * ti->track, SEEK_SET);
1800 memset (buf, 0, sizeof buf);
1801 ti->type = type;
1802 buf[2] = 0;
1803 buf[3] = ti->type;
1804 do_put_mem_long ((uae_u32 *) (buf + 4), ti->len);
1805 do_put_mem_long ((uae_u32 *) (buf + 8), ti->bitlen);
1806 zfile_fwrite (buf, sizeof (buf), 1, diskfile);
1807 if (ti->len > (len + 7) / 8) {
1808 zerobuf = xmalloc (uae_u8, ti->len);
1809 memset (zerobuf, 0, ti->len);
1810 zfile_fseek (diskfile, ti->offs, SEEK_SET);
1811 zfile_fwrite (zerobuf, 1, ti->len, diskfile);
1812 xfree (zerobuf);
1813 }
1814 if (disk_debug_logging > 0)
1815 write_log (_T("track %d, raw track length %d written (total size %d)\n"), ti->track, (ti->bitlen + 7) / 8, ti->len);
1816 }
1817
1818 #define MFMMASK 0x55555555
getmfmword(uae_u16 * mbuf,int shift)1819 static uae_u16 getmfmword (uae_u16 *mbuf, int shift)
1820 {
1821 return (mbuf[0] << shift) | (mbuf[1] >> (16 - shift));
1822 }
1823
getmfmlong(uae_u16 * mbuf,int shift)1824 static uae_u32 getmfmlong (uae_u16 *mbuf, int shift)
1825 {
1826 return ((getmfmword (mbuf, shift) << 16) | getmfmword (mbuf + 1, shift)) & MFMMASK;
1827 }
1828
1829 #if MFM_VALIDATOR
check_valid_mfm(uae_u16 * mbuf,int words,int sector)1830 static void check_valid_mfm (uae_u16 *mbuf, int words, int sector)
1831 {
1832 int prevbit = 0;
1833 for (int i = 0; i < words * 8; i++) {
1834 int wordoffset = i / 8;
1835 uae_u16 w = mbuf[wordoffset];
1836 uae_u16 wp = mbuf[wordoffset - 1];
1837 int bitoffset = (7 - (i & 7)) * 2;
1838 int clockbit = w & (1 << (bitoffset + 1));
1839 int databit = w & (1 << (bitoffset + 0));
1840
1841 if ((clockbit && databit) || (clockbit && !databit && prevbit) || (!clockbit && !databit && !prevbit)) {
1842 write_log (_T("illegal mfm sector %d data %04x %04x, bit %d:%d\n"), sector, wp, w, wordoffset, bitoffset);
1843 }
1844 prevbit = databit;
1845 }
1846 }
1847 #endif
1848
decode_buffer(uae_u16 * mbuf,int cyl,int drvsec,int ddhd,int filetype,int * drvsecp,int * sectable,int checkmode)1849 static int decode_buffer (uae_u16 *mbuf, int cyl, int drvsec, int ddhd, int filetype, int *drvsecp, int *sectable, int checkmode)
1850 {
1851 int i, secwritten = 0;
1852 int fwlen = FLOPPY_WRITE_LEN * ddhd;
1853 int length = 2 * fwlen;
1854 uae_u32 odd, even, chksum, id, dlong;
1855 uae_u8 *secdata;
1856 uae_u8 secbuf[544];
1857 uae_u16 *mend = mbuf + length, *mstart;
1858 int shift = 0;
1859
1860 memset (sectable, 0, MAX_SECTORS * sizeof (int));
1861 mstart = mbuf;
1862 memcpy (mbuf + fwlen, mbuf, fwlen * sizeof (uae_u16));
1863 mend -= (4 + 16 + 8 + 512);
1864 while (secwritten < drvsec) {
1865 int trackoffs;
1866
1867 while (getmfmword (mbuf, shift) != 0x4489) {
1868 if (mbuf >= mend)
1869 return 1;
1870 shift++;
1871 if (shift == 16) {
1872 shift = 0;
1873 mbuf++;
1874 }
1875 }
1876 while (getmfmword (mbuf, shift) == 0x4489) {
1877 if (mbuf >= mend)
1878 return 1;
1879 mbuf++;
1880 }
1881
1882 odd = getmfmlong (mbuf, shift);
1883 even = getmfmlong (mbuf + 2, shift);
1884 mbuf += 4;
1885 id = (odd << 1) | even;
1886
1887 trackoffs = (id & 0xff00) >> 8;
1888 if (trackoffs + 1 > drvsec) {
1889 write_log (_T("Disk decode: weird sector number %d (%08X, %d)\n"), trackoffs, id, mbuf - mstart);
1890 if (filetype == ADF_EXT2)
1891 return 2;
1892 continue;
1893 }
1894 #if MFM_VALIDATOR
1895 check_valid_mfm (mbuf - 4, 544 - 4 + 1, trackoffs);
1896 #endif
1897 chksum = odd ^ even;
1898 for (i = 0; i < 4; i++) {
1899 odd = getmfmlong (mbuf, shift);
1900 even = getmfmlong (mbuf + 8, shift);
1901 mbuf += 2;
1902
1903 dlong = (odd << 1) | even;
1904 if (dlong && !checkmode) {
1905 if (filetype == ADF_EXT2)
1906 return 6;
1907 secwritten = -200;
1908 }
1909 chksum ^= odd ^ even;
1910 } /* could check here if the label is nonstandard */
1911 mbuf += 8;
1912 odd = getmfmlong (mbuf, shift);
1913 even = getmfmlong (mbuf + 2, shift);
1914 mbuf += 4;
1915 if (((odd << 1) | even) != chksum) {
1916 write_log (_T("Disk decode: checksum error on sector %d header\n"), trackoffs);
1917 if (filetype == ADF_EXT2)
1918 return 3;
1919 continue;
1920 }
1921 if (((id & 0x00ff0000) >> 16) != (uae_u32)(cyl * 2 + side) ) {
1922 write_log (_T("Disk decode: mismatched track (%d <> %d) on sector %d header\n"), (id & 0x00ff0000) >> 16, cyl * 2 + side, trackoffs);
1923 if (filetype == ADF_EXT2)
1924 return 3;
1925 continue;
1926 }
1927 odd = getmfmlong (mbuf, shift);
1928 even = getmfmlong (mbuf + 2, shift);
1929 mbuf += 4;
1930 chksum = (odd << 1) | even;
1931 secdata = secbuf + 32;
1932 for (i = 0; i < 128; i++) {
1933 odd = getmfmlong (mbuf, shift);
1934 even = getmfmlong (mbuf + 256, shift);
1935 mbuf += 2;
1936 dlong = (odd << 1) | even;
1937 *secdata++ = dlong >> 24;
1938 *secdata++ = dlong >> 16;
1939 *secdata++ = dlong >> 8;
1940 *secdata++ = dlong;
1941 chksum ^= odd ^ even;
1942 }
1943 if (chksum) {
1944 write_log (_T("Disk decode: sector %d, data checksum error\n"), trackoffs);
1945 if (filetype == ADF_EXT2)
1946 return 4;
1947 continue;
1948 }
1949 mbuf += 256;
1950 //write_log (_T("Sector %d ok\n"), trackoffs);
1951 sectable[trackoffs] = 1;
1952 secwritten++;
1953 memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
1954 }
1955 if (filetype == ADF_EXT2 && (secwritten == 0 || secwritten < 0))
1956 return 5;
1957 if (secwritten == 0)
1958 write_log (_T("Disk decode: unsupported format\n"));
1959 if (secwritten < 0)
1960 write_log (_T("Disk decode: sector labels ignored\n"));
1961 *drvsecp = drvsec;
1962 return 0;
1963 }
1964
mfmdecode(uae_u16 ** mfmp,int shift)1965 static uae_u8 mfmdecode (uae_u16 **mfmp, int shift)
1966 {
1967 uae_u16 mfm = getmfmword (*mfmp, shift);
1968 uae_u8 out = 0;
1969 int i;
1970
1971 (*mfmp)++;
1972 mfm &= 0x5555;
1973 for (i = 0; i < 8; i++) {
1974 out >>= 1;
1975 if (mfm & 1)
1976 out |= 0x80;
1977 mfm >>= 2;
1978 }
1979 return out;
1980 }
1981
drive_write_pcdos(drive * drv)1982 static int drive_write_pcdos (drive *drv)
1983 {
1984 int i;
1985 int drvsec = drv->num_secs;
1986 int fwlen = FLOPPY_WRITE_LEN * drv->ddhd;
1987 int length = 2 * fwlen;
1988 uae_u16 *mbuf = drv->bigmfmbuf;
1989 uae_u16 *mend = mbuf + length;
1990 int secwritten = 0, shift = 0, sector = -1;
1991 int sectable[18];
1992 uae_u8 secbuf[3 + 1 + 512];
1993 uae_u8 mark;
1994 uae_u16 crc;
1995
1996 memset (sectable, 0, sizeof (sectable));
1997 memcpy (mbuf + fwlen, mbuf, fwlen * sizeof (uae_u16));
1998 mend -= 518;
1999 secbuf[0] = secbuf[1] = secbuf[2] = 0xa1;
2000 secbuf[3] = 0xfb;
2001
2002 while (secwritten < drvsec) {
2003 int mfmcount;
2004
2005 mfmcount = 0;
2006 while (getmfmword (mbuf, shift) != 0x4489) {
2007 mfmcount++;
2008 if (mbuf >= mend)
2009 return 1;
2010 shift++;
2011 if (shift == 16) {
2012 shift = 0;
2013 mbuf++;
2014 }
2015 if (sector >= 0 && mfmcount / 16 >= 43)
2016 sector = -1;
2017 }
2018
2019 mfmcount = 0;
2020 while (getmfmword (mbuf, shift) == 0x4489) {
2021 mfmcount++;
2022 if (mbuf >= mend)
2023 return 1;
2024 mbuf++;
2025 }
2026 if (mfmcount < 3) // ignore if less than 3 sync markers
2027 continue;
2028
2029 mark = mfmdecode(&mbuf, shift);
2030 if (mark == 0xfe) {
2031 uae_u8 tmp[8];
2032 uae_u8 cyl, head, size;
2033
2034 cyl = mfmdecode (&mbuf, shift);
2035 head = mfmdecode (&mbuf, shift);
2036 sector = mfmdecode (&mbuf, shift);
2037 size = mfmdecode (&mbuf, shift);
2038 crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
2039
2040 tmp[0] = 0xa1; tmp[1] = 0xa1; tmp[2] = 0xa1; tmp[3] = mark;
2041 tmp[4] = cyl; tmp[5] = head; tmp[6] = sector; tmp[7] = size;
2042
2043 // skip 28 bytes
2044 for (i = 0; i < 28; i++)
2045 mfmdecode (&mbuf, shift);
2046
2047 if (get_crc16 (tmp, 8) != crc || cyl != drv->cyl || head != side || size != 2 || sector < 1 || sector > drv->num_secs) {
2048 write_log (_T("PCDOS: track %d, corrupted sector header\n"), drv->cyl * 2 + side);
2049 return 1;
2050 }
2051 sector--;
2052 continue;
2053 }
2054 if (mark != 0xfb && mark != 0xfa) {
2055 write_log (_T("PCDOS: track %d: unknown address mark %02X\n"), drv->cyl * 2 + side, mark);
2056 continue;
2057 }
2058 if (sector < 0)
2059 continue;
2060 for (i = 0; i < 512; i++)
2061 secbuf[i + 4] = mfmdecode (&mbuf, shift);
2062 crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
2063 if (get_crc16 (secbuf, 3 + 1 + 512) != crc) {
2064 write_log (_T("PCDOS: track %d, sector %d data checksum error\n"),
2065 drv->cyl * 2 + side, sector + 1);
2066 continue;
2067 }
2068 sectable[sector] = 1;
2069 secwritten++;
2070 zfile_fseek (drv->diskfile, drv->trackdata[drv->cyl * 2 + side].offs + sector * 512, SEEK_SET);
2071 zfile_fwrite (secbuf + 4, sizeof (uae_u8), 512, drv->diskfile);
2072 write_log (_T("PCDOS: track %d sector %d written\n"), drv->cyl * 2 + side, sector + 1);
2073 sector = -1;
2074 }
2075 if (secwritten != drv->num_secs)
2076 write_log (_T("PCDOS: track %d, %d corrupted sectors ignored\n"),
2077 drv->cyl * 2 + side, drv->num_secs - secwritten);
2078 return 0;
2079 }
2080
drive_write_adf_amigados(drive * drv)2081 static int drive_write_adf_amigados (drive *drv)
2082 {
2083 int drvsec, i;
2084 int sectable[MAX_SECTORS];
2085
2086 if (decode_buffer (drv->bigmfmbuf, drv->cyl, drv->num_secs, drv->ddhd, drv->filetype, &drvsec, sectable, 0))
2087 return 2;
2088 if (!drvsec)
2089 return 2;
2090
2091 if (drv->filetype == ADF_EXT2)
2092 diskfile_update (drv->diskfile, &drv->trackdata[drv->cyl * 2 + side], drvsec * 512 * 8, TRACK_AMIGADOS);
2093 for (i = 0; i < drvsec; i++) {
2094 zfile_fseek (drv->diskfile, drv->trackdata[drv->cyl * 2 + side].offs + i * 512, SEEK_SET);
2095 zfile_fwrite (writebuffer + i * 512, sizeof (uae_u8), 512, drv->diskfile);
2096 }
2097
2098 return 0;
2099 }
2100
2101 /* write raw track to disk file */
drive_write_ext2(uae_u16 * bigmfmbuf,struct zfile * diskfile,trackid * ti,int tracklen)2102 static int drive_write_ext2 (uae_u16 *bigmfmbuf, struct zfile *diskfile, trackid *ti, int tracklen)
2103 {
2104 int len, i;
2105
2106 len = (tracklen + 7) / 8;
2107 if (len > ti->len) {
2108 write_log (_T("disk raw write: image file's track %d is too small (%d < %d)!\n"), ti->track, ti->len, len);
2109 len = ti->len;
2110 }
2111 diskfile_update (diskfile, ti, tracklen, TRACK_RAW);
2112 for (i = 0; i < ti->len / 2; i++) {
2113 uae_u16 *mfm = bigmfmbuf + i;
2114 uae_u16 *mfmw = bigmfmbufw + i;
2115 uae_u8 *data = (uae_u8 *) mfm;
2116 *mfmw = 256 * *data + *(data + 1);
2117 }
2118 zfile_fseek (diskfile, ti->offs, SEEK_SET);
2119 zfile_fwrite (bigmfmbufw, 1, len, diskfile);
2120 return 1;
2121 }
2122
2123 static void drive_write_data (drive * drv);
2124
convert_adf_to_ext2(drive * drv,int mode)2125 static bool convert_adf_to_ext2 (drive *drv, int mode)
2126 {
2127 TCHAR name[MAX_DPATH];
2128 bool hd = drv->ddhd == 2;
2129 struct zfile *f;
2130
2131 if (drv->filetype != ADF_NORMAL)
2132 return false;
2133 _tcscpy (name, currprefs.floppyslots[drv - floppy].df);
2134 if (!name[0])
2135 return false;
2136 if (mode == 1) {
2137 TCHAR *p = _tcsrchr (name, '.');
2138 if (!p)
2139 p = name + _tcslen (name);
2140 _tcscpy (p, _T(".extended.adf"));
2141 if (!disk_creatediskfile (name, 1, hd ? DRV_35_HD : DRV_35_DD, NULL, false, false, drv->diskfile))
2142 return false;
2143 } else if (mode == 2) {
2144 struct zfile *tmp = zfile_fopen_load_zfile (drv->diskfile);
2145 if (!tmp)
2146 return false;
2147 zfile_fclose (drv->diskfile);
2148 drv->diskfile = NULL;
2149 if (!disk_creatediskfile (name, 1, hd ? DRV_35_HD : DRV_35_DD, NULL, false, false, tmp)) {
2150 zfile_fclose (tmp);
2151 return false;
2152 }
2153 } else {
2154 return false;
2155 }
2156 f = zfile_fopen (name, _T("r+b"), 0);
2157 if (!f)
2158 return false;
2159 _tcscpy (currprefs.floppyslots[drv - floppy].df, name);
2160 _tcscpy (changed_prefs.floppyslots[drv - floppy].df, name);
2161 zfile_fclose (drv->diskfile);
2162
2163 drv->diskfile = f;
2164 drv->filetype = ADF_EXT2;
2165 read_header_ext2 (drv->diskfile, drv->trackdata, &drv->num_tracks, &drv->ddhd);
2166
2167 drive_write_data (drv);
2168 #ifdef RETROPLATFORM
2169 rp_disk_image_change (drv - &floppy[0], name, false);
2170 #endif
2171 drive_fill_bigbuf (drv, 1);
2172
2173 return true;
2174 }
2175
drive_write_data(drive * drv)2176 static void drive_write_data (drive * drv)
2177 {
2178 int ret = -1;
2179 int tr = drv->cyl * 2 + side;
2180
2181 if (drive_writeprotected (drv) || drv->trackdata[tr].type == TRACK_NONE) {
2182 /* read original track back because we didn't really write anything */
2183 drv->buffered_side = 2;
2184 return;
2185 }
2186 if (drv->writediskfile) {
2187 drive_write_ext2 (drv->bigmfmbuf, drv->writediskfile, &drv->writetrackdata[tr],
2188 longwritemode ? dsklength2 * 8 : drv->tracklen);
2189 }
2190 switch (drv->filetype) {
2191 case ADF_NORMAL:
2192 if (drive_write_adf_amigados (drv)) {
2193 if (currprefs.floppy_auto_ext2) {
2194 convert_adf_to_ext2 (drv, currprefs.floppy_auto_ext2);
2195 } else {
2196 static int warned;
2197 if (!warned)
2198 notify_user (NUMSG_NEEDEXT2);
2199 warned = 1;
2200 }
2201 }
2202 return;
2203 case ADF_EXT1:
2204 break;
2205 case ADF_EXT2:
2206 if (!longwritemode)
2207 ret = drive_write_adf_amigados (drv);
2208 if (ret) {
2209 write_log (_T("not an amigados track %d (error %d), writing as raw track\n"), drv->cyl * 2 + side, ret);
2210 drive_write_ext2 (drv->bigmfmbuf, drv->diskfile, &drv->trackdata[drv->cyl * 2 + side],
2211 longwritemode ? dsklength2 * 8 : drv->tracklen);
2212 }
2213 return;
2214 case ADF_IPF:
2215 break;
2216 case ADF_PCDOS:
2217 ret = drive_write_pcdos (drv);
2218 if (ret)
2219 write_log (_T("not a PC formatted track %d (error %d)\n"), drv->cyl * 2 + side, ret);
2220 break;
2221 case ADF_NONE:
2222 case ADF_FDI:
2223 case ADF_CATWEASEL:
2224 break;
2225 }
2226 drv->tracktiming[0] = 0;
2227 }
2228
drive_eject(drive * drv)2229 static void drive_eject (drive * drv)
2230 {
2231 #ifdef DRIVESOUND
2232 if (isfloppysound (drv))
2233 driveclick_insert (drv - floppy, 1);
2234 #endif
2235 gui_disk_image_change (drv - floppy, NULL, drv->wrprot);
2236 drive_image_free (drv);
2237 drv->dskchange = true;
2238 drv->ddhd = 1;
2239 drv->dskchange_time = 0;
2240 drv->dskready = 0;
2241 drv->dskready_up_time = 0;
2242 drv->dskready_down_time = 0;
2243 drv->crc32 = 0;
2244 drive_settype_id (drv); /* Back to 35 DD */
2245 if (disk_debug_logging > 0)
2246 write_log (_T("eject drive %d\n"), drv - &floppy[0]);
2247 inprec_recorddiskchange (drv - floppy, NULL, false);
2248 }
2249
2250 /* We use this function if we have no Kickstart ROM.
2251 * No error checking - we trust our luck. */
DISK_ersatz_read(int tr,int sec,uaecptr dest)2252 void DISK_ersatz_read (int tr, int sec, uaecptr dest)
2253 {
2254 uae_u8 *dptr = get_real_address (dest);
2255 zfile_fseek (floppy[0].diskfile, floppy[0].trackdata[tr].offs + sec * 512, SEEK_SET);
2256 zfile_fread (dptr, 1, 512, floppy[0].diskfile);
2257 }
2258
floppy_get_bootblock(uae_u8 * dst,bool ffs,bool bootable)2259 static void floppy_get_bootblock (uae_u8 *dst, bool ffs, bool bootable)
2260 {
2261 strcpy ((char*)dst, "DOS");
2262 dst[3] = ffs ? 1 : 0;
2263 if (bootable)
2264 memcpy (dst, ffs ? bootblock_ffs : bootblock_ofs, ffs ? sizeof bootblock_ffs : sizeof bootblock_ofs);
2265 }
floppy_get_rootblock(uae_u8 * dst,int block,const TCHAR * disk_name,drive_type adftype)2266 static void floppy_get_rootblock (uae_u8 *dst, int block, const TCHAR *disk_name, drive_type adftype)
2267 {
2268 dst[0+3] = 2;
2269 dst[12+3] = 0x48;
2270 dst[312] = dst[313] = dst[314] = dst[315] = (uae_u8)0xff;
2271 dst[316+2] = (block + 1) >> 8; dst[316+3] = (block + 1) & 255;
2272 char *s = ua ((disk_name && _tcslen (disk_name) > 0) ? disk_name : _T("empty"));
2273 dst[432] = strlen (s);
2274 strcpy ((char*)dst + 433, s);
2275 xfree (s);
2276 dst[508 + 3] = 1;
2277 disk_date (dst + 420);
2278 memcpy (dst + 472, dst + 420, 3 * 4);
2279 memcpy (dst + 484, dst + 420, 3 * 4);
2280 disk_checksum (dst, dst + 20);
2281 /* bitmap block */
2282 memset (dst + 512 + 4, 0xff, 2 * block / 8);
2283 if (adftype == 0)
2284 dst[512 + 0x72] = 0x3f;
2285 else
2286 dst[512 + 0xdc] = 0x3f;
2287 disk_checksum (dst + 512, dst + 512);
2288 }
2289
2290 /* type: 0=regular, 1=ext2adf */
2291 /* adftype: 0=DD,1=HD,2=DD PC,3=HD PC,4=525SD */
disk_creatediskfile(const TCHAR * name,int type,drive_type adftype,const TCHAR * disk_name,bool ffs,bool bootable,struct zfile * copyfrom)2292 bool disk_creatediskfile (const TCHAR *name, int type, drive_type adftype, const TCHAR *disk_name, bool ffs, bool bootable, struct zfile *copyfrom)
2293 {
2294 int size = 32768;
2295 struct zfile *f;
2296 int i, l, file_size, tracks, track_len, sectors;
2297 uae_u8 *chunk = NULL;
2298 int ddhd = 1;
2299 bool ok = false;
2300 uae_u64 pos;
2301
2302 if (type == 1)
2303 tracks = 2 * 83;
2304 else
2305 tracks = 2 * 80;
2306 file_size = 880 * 1024;
2307 sectors = 11;
2308 if (adftype == 2 || adftype == 3) {
2309 file_size = 720 * 1024;
2310 sectors = 9;
2311 }
2312 track_len = FLOPPY_WRITE_LEN * 2;
2313 if (adftype == 1 || adftype == 3) {
2314 file_size *= 2;
2315 track_len *= 2;
2316 ddhd = 2;
2317 } else if (adftype == 4) {
2318 file_size /= 2;
2319 tracks /= 2;
2320 }
2321
2322 if (copyfrom) {
2323 pos = zfile_ftell (copyfrom);
2324 zfile_fseek (copyfrom, 0, SEEK_SET);
2325 }
2326
2327 f = zfile_fopen (name, _T("wb"), 0);
2328 chunk = xmalloc (uae_u8, size);
2329 if (f && chunk) {
2330 int cylsize = sectors * 2 * 512;
2331 memset (chunk, 0, size);
2332 if (type == 0) {
2333 for (i = 0; i < file_size; i += cylsize) {
2334 memset(chunk, 0, cylsize);
2335 if (adftype <= 1) {
2336 if (i == 0) {
2337 /* boot block */
2338 floppy_get_bootblock (chunk, ffs, bootable);
2339 } else if (i == file_size / 2) {
2340 /* root block */
2341 floppy_get_rootblock (chunk, file_size / 1024, disk_name, adftype);
2342 }
2343 }
2344 zfile_fwrite (chunk, cylsize, 1, f);
2345 }
2346 ok = true;
2347 } else {
2348 uae_u8 root[4];
2349 uae_u8 rawtrack[3 * 4], dostrack[3 * 4];
2350 l = track_len;
2351 zfile_fwrite ("UAE-1ADF", 8, 1, f);
2352 root[0] = 0; root[1] = 0; /* flags (reserved) */
2353 root[2] = 0; root[3] = tracks; /* number of tracks */
2354 zfile_fwrite (root, 4, 1, f);
2355 rawtrack[0] = 0; rawtrack[1] = 0; /* flags (reserved) */
2356 rawtrack[2] = 0; rawtrack[3] = 1; /* track type */
2357 rawtrack[4] = 0; rawtrack[5] = 0; rawtrack[6]=(uae_u8)(l >> 8); rawtrack[7] = (uae_u8)l;
2358 rawtrack[8] = 0; rawtrack[9] = 0; rawtrack[10] = 0; rawtrack[11] = 0;
2359 memcpy (dostrack, rawtrack, sizeof rawtrack);
2360 dostrack[3] = 0;
2361 dostrack[9] = (l * 8) >> 16; dostrack[10] = (l * 8) >> 8; dostrack[11] = (l * 8) >> 0;
2362 bool dodos = ffs || bootable || (disk_name && _tcslen (disk_name) > 0);
2363 for (i = 0; i < tracks; i++) {
2364 uae_u8 tmp[3 * 4];
2365 memcpy (tmp, rawtrack, sizeof rawtrack);
2366 if (dodos || copyfrom)
2367 memcpy (tmp, dostrack, sizeof dostrack);
2368 zfile_fwrite (tmp, sizeof tmp, 1, f);
2369 }
2370 for (i = 0; i < tracks; i++) {
2371 memset (chunk, 0, size);
2372 if (copyfrom) {
2373 zfile_fread (chunk, 11 * ddhd, 512, copyfrom);
2374 } else {
2375 if (dodos) {
2376 if (i == 0)
2377 floppy_get_bootblock (chunk, ffs, bootable);
2378 else if (i == 80)
2379 floppy_get_rootblock (chunk, 80 * 11 * ddhd, disk_name, adftype);
2380 }
2381 }
2382 zfile_fwrite (chunk, l, 1, f);
2383 }
2384 ok = true;
2385 }
2386 }
2387 xfree (chunk);
2388 zfile_fclose (f);
2389 if (copyfrom)
2390 zfile_fseek (copyfrom, pos, SEEK_SET);
2391 if (f)
2392 DISK_history_add (name, -1, HISTORY_FLOPPY, true);
2393 return ok;
2394 }
2395
disk_getwriteprotect(struct uae_prefs * p,const TCHAR * name)2396 int disk_getwriteprotect (struct uae_prefs *p, const TCHAR *name)
2397 {
2398 int needwritefile;
2399 drive_type drvtype;
2400 return diskfile_iswriteprotect (p, name, &needwritefile, &drvtype);
2401 }
2402
diskfile_readonly(const TCHAR * name,bool readonly)2403 static void diskfile_readonly (const TCHAR *name, bool readonly)
2404 {
2405 struct mystat st;
2406 int mode, oldmode;
2407
2408 if (!my_stat (name, &st))
2409 return;
2410 oldmode = mode = st.mode;
2411 mode &= ~FILEFLAG_WRITE;
2412 if (!readonly)
2413 mode |= FILEFLAG_WRITE;
2414 if (mode != oldmode)
2415 chmod (name, mode);
2416 }
2417
setdskchangetime(drive * drv,int dsktime)2418 static void setdskchangetime (drive *drv, int dsktime)
2419 {
2420 int i;
2421 /* prevent multiple disk insertions at the same time */
2422 if (drv->dskchange_time > 0)
2423 return;
2424 for (i = 0; i < MAX_FLOPPY_DRIVES; i++) {
2425 if (&floppy[i] != drv && floppy[i].dskchange_time > 0 && floppy[i].dskchange_time + 1 >= dsktime) {
2426 dsktime = floppy[i].dskchange_time + 1;
2427 }
2428 }
2429 drv->dskchange_time = dsktime;
2430 if (disk_debug_logging > 0)
2431 write_log (_T("delayed insert enable %d\n"), dsktime);
2432 }
2433
DISK_reinsert(int num)2434 void DISK_reinsert (int num)
2435 {
2436 drive_eject (&floppy[num]);
2437 setdskchangetime (&floppy[num], 100);
2438 }
2439
disk_setwriteprotect(struct uae_prefs * p,int num,const TCHAR * name,bool writeprotected)2440 int disk_setwriteprotect (struct uae_prefs *p, int num, const TCHAR *name, bool writeprotected)
2441 {
2442 int needwritefile = 0, oldprotect;
2443 struct zfile *zf1, *zf2;
2444 bool wrprot1, wrprot2;
2445 int i;
2446 TCHAR *name2;
2447 drive_type drvtype = DRV_NONE;
2448
2449 oldprotect = diskfile_iswriteprotect (p, name, &needwritefile, &drvtype);
2450 DISK_validate_filename (p, name, 1, &wrprot1, NULL, &zf1);
2451 if (!zf1)
2452 return 0;
2453 if (wrprot1 && p->floppy_read_only)
2454 return 0;
2455 if (zfile_iscompressed (zf1))
2456 wrprot1 = 1;
2457 zfile_fclose (zf1);
2458 zf2 = getwritefile (p, name, &wrprot2);
2459 name2 = DISK_get_saveimagepath (name);
2460
2461 if (needwritefile && zf2 == 0)
2462 disk_creatediskfile (name2, 1, drvtype, NULL, false, false, NULL);
2463 zfile_fclose (zf2);
2464 if (writeprotected && iswritefileempty (p, name)) {
2465 for (i = 0; i < MAX_FLOPPY_DRIVES; i++) {
2466 if (!_tcscmp (name, floppy[i].newname))
2467 drive_eject (&floppy[i]);
2468 }
2469 _wunlink (name2);
2470 }
2471
2472 if (!needwritefile)
2473 diskfile_readonly (name, writeprotected);
2474 diskfile_readonly (name2, writeprotected);
2475 DISK_reinsert (num);
2476 return 1;
2477 }
2478
disk_eject(int num)2479 void disk_eject (int num)
2480 {
2481 config_changed = 1;
2482 gui_filename (num, _T(""));
2483 drive_eject (floppy + num);
2484 *currprefs.floppyslots[num].df = *changed_prefs.floppyslots[num].df = 0;
2485 floppy[num].newname[0] = 0;
2486 update_drive_gui (num, true);
2487 }
2488
DISK_history_add(const TCHAR * name,int idx,int type,int donotcheck)2489 int DISK_history_add (const TCHAR *name, int idx, int type, int donotcheck)
2490 {
2491 int i;
2492
2493 if (idx >= MAX_PREVIOUS_FLOPPIES)
2494 return 0;
2495 if (name == NULL) {
2496 dfxhistory[type][idx][0] = 0;
2497 return 1;
2498 }
2499 if (name[0] == 0)
2500 return 0;
2501 if (!donotcheck) {
2502 if (!zfile_exists (name)) {
2503 for (i = 0; i < MAX_PREVIOUS_FLOPPIES; i++) {
2504 if (!_tcsicmp (dfxhistory[type][i], name)) {
2505 while (i < MAX_PREVIOUS_FLOPPIES - 1) {
2506 _tcscpy (dfxhistory[type][i], dfxhistory[type][i + 1]);
2507 i++;
2508 }
2509 dfxhistory[type][MAX_PREVIOUS_FLOPPIES - 1][0] = 0;
2510 break;
2511 }
2512 }
2513 return 0;
2514 }
2515 }
2516 if (idx >= 0) {
2517 if (idx >= MAX_PREVIOUS_FLOPPIES)
2518 return 0;
2519 dfxhistory[type][idx][0] = 0;
2520 for (i = 0; i < MAX_PREVIOUS_FLOPPIES; i++) {
2521 if (!_tcsicmp (dfxhistory[type][i], name))
2522 return 0;
2523 }
2524 _tcscpy (dfxhistory[type][idx], name);
2525 return 1;
2526 }
2527 for (i = 0; i < MAX_PREVIOUS_FLOPPIES; i++) {
2528 if (!_tcscmp (dfxhistory[type][i], name)) {
2529 while (i < MAX_PREVIOUS_FLOPPIES - 1) {
2530 _tcscpy (dfxhistory[type][i], dfxhistory[type][i + 1]);
2531 i++;
2532 }
2533 dfxhistory[type][MAX_PREVIOUS_FLOPPIES - 1][0] = 0;
2534 break;
2535 }
2536 }
2537 for (i = MAX_PREVIOUS_FLOPPIES - 2; i >= 0; i--)
2538 _tcscpy (dfxhistory[type][i + 1], dfxhistory[type][i]);
2539 _tcscpy (dfxhistory[type][0], name);
2540 return 1;
2541 }
2542
DISK_history_get(int idx,int type)2543 TCHAR *DISK_history_get (int idx, int type)
2544 {
2545 if (idx >= MAX_PREVIOUS_FLOPPIES)
2546 return NULL;
2547 return dfxhistory[type][idx];
2548 }
2549
disk_insert_2(int num,const TCHAR * name,bool forced,bool forcedwriteprotect)2550 static void disk_insert_2 (int num, const TCHAR *name, bool forced, bool forcedwriteprotect)
2551 {
2552 drive *drv = floppy + num;
2553
2554 if (forced) {
2555 drive_insert (drv, &currprefs, num, name, false, forcedwriteprotect);
2556 return;
2557 }
2558 if (!_tcscmp (currprefs.floppyslots[num].df, name))
2559 return;
2560 _tcscpy (drv->newname, name);
2561 drv->newnamewriteprotected = forcedwriteprotect;
2562 _tcscpy (currprefs.floppyslots[num].df, name);
2563 currprefs.floppyslots[num].forcedwriteprotect = forcedwriteprotect;
2564 DISK_history_add (name, -1, HISTORY_FLOPPY, 0);
2565 if (name[0] == 0) {
2566 disk_eject (num);
2567 } else if (!drive_empty(drv) || drv->dskchange_time > 0) {
2568 drive_eject (drv);
2569 /* set dskchange_time, disk_insert() will be
2570 * called from DISK_check_change() after 2 second delay
2571 * this makes sure that all programs detect disk change correctly
2572 */
2573 setdskchangetime (drv, 100);
2574 } else {
2575 setdskchangetime (drv, 1);
2576 }
2577 }
2578
disk_insert(int num,const TCHAR * name,bool forcedwriteprotect)2579 void disk_insert (int num, const TCHAR *name, bool forcedwriteprotect)
2580 {
2581 config_changed = 1;
2582 //target_addtorecent (name, 0);
2583 disk_insert_2 (num, name, 0, forcedwriteprotect);
2584 }
2585
disk_insert_force(int num,const TCHAR * name,bool forcedwriteprotect)2586 void disk_insert_force (int num, const TCHAR *name, bool forcedwriteprotect)
2587 {
2588 disk_insert_2 (num, name, 1, forcedwriteprotect);
2589 }
2590 #ifdef __LIBRETRO__
DISK_check_change(void)2591 void DISK_check_change (void)
2592 #else
2593 static void DISK_check_change (void)
2594 #endif
2595 {
2596 if (currprefs.floppy_speed != changed_prefs.floppy_speed)
2597 currprefs.floppy_speed = changed_prefs.floppy_speed;
2598 for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
2599 /* REMOVEME:
2600 * nowhere used
2601 */
2602 #if 0
2603 drive *drv = floppy + i;
2604 #endif
2605
2606 if (currprefs.floppyslots[i].dfxtype != changed_prefs.floppyslots[i].dfxtype) {
2607
2608 currprefs.floppyslots[i].dfxtype = changed_prefs.floppyslots[i].dfxtype;
2609 reset_drive (i);
2610 #ifdef RETROPLATFORM
2611 rp_floppy_device_enable (i, currprefs.floppyslots[i].dfxtype >= 0);
2612 #endif
2613 }
2614 }
2615 }
2616
DISK_vsync(void)2617 void DISK_vsync (void)
2618 {
2619 DISK_check_change ();
2620 for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
2621 drive *drv = floppy + i;
2622 if (drv->dskchange_time == 0 && _tcscmp (currprefs.floppyslots[i].df, changed_prefs.floppyslots[i].df))
2623 disk_insert (i, changed_prefs.floppyslots[i].df, changed_prefs.floppyslots[i].forcedwriteprotect);
2624 if (drv->dskready_down_time > 0)
2625 drv->dskready_down_time--;
2626 /* emulate drive motor turn on time */
2627 if (drv->dskready_up_time > 0 && !drive_empty (drv)) {
2628 drv->dskready_up_time--;
2629 if (drv->dskready_up_time == 0 && !drv->motoroff)
2630 drv->dskready = true;
2631 }
2632 /* delay until new disk image is inserted */
2633 if (drv->dskchange_time > 0) {
2634 drv->dskchange_time--;
2635 if (drv->dskchange_time == 0) {
2636 drive_insert (drv, &currprefs, i, drv->newname, false, drv->newnamewriteprotected);
2637 if (disk_debug_logging > 0)
2638 write_log (_T("delayed insert, drive %d, image '%s'\n"), i, drv->newname);
2639 update_drive_gui (i, false);
2640 }
2641 }
2642 }
2643 }
2644
disk_empty(int num)2645 int disk_empty (int num)
2646 {
2647 return drive_empty (floppy + num);
2648 }
2649
tobin(uae_u8 v)2650 static TCHAR *tobin (uae_u8 v)
2651 {
2652 int i;
2653 static TCHAR buf[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2654 for( i = 7; i >= 0; i--)
2655 buf[7 - i] = v & (1 << i) ? '1' : '0';
2656 // buf[-1] is invalid! buf[i] = 0;
2657 return buf;
2658 }
2659
fetch_DISK_select(uae_u8 data)2660 static void fetch_DISK_select(uae_u8 data)
2661 {
2662 selected = (data >> 3) & 15;
2663 side = 1 - ((data >> 2) & 1);
2664 direction = (data >> 1) & 1;
2665 }
2666
DISK_select_set(uae_u8 data)2667 void DISK_select_set (uae_u8 data)
2668 {
2669 prev_data = data;
2670 prev_step = data & 1;
2671
2672 fetch_DISK_select (data);
2673 }
2674
DISK_select(uae_u8 data)2675 void DISK_select (uae_u8 data)
2676 {
2677 int step_pulse, prev_selected, dr;
2678
2679 prev_selected = selected;
2680
2681 fetch_DISK_select (data);
2682 step_pulse = data & 1;
2683
2684 if (disk_debug_logging > 1)
2685 write_log (_T("%08X %02X->%02X %s drvmask=%x"), M68K_GETPC, prev_data, data, tobin(data), selected ^ 15);
2686
2687 #ifdef AMAX
2688 if (currprefs.amaxromfile[0])
2689 amax_disk_select (data, prev_data);
2690 #endif
2691
2692 if ((prev_data & 0x80) != (data & 0x80)) {
2693 for (dr = 0; dr < 4; dr++) {
2694 if (floppy[dr].indexhackmode > 1 && !(selected & (1 << dr))) {
2695 floppy[dr].indexhack = 1;
2696 if (disk_debug_logging > 1)
2697 write_log (_T(" indexhack!"));
2698 }
2699 }
2700 }
2701
2702 if (disk_debug_logging > 1) {
2703 write_log (_T(" %d%d%d%d% "), (selected & 1) ? 0 : 1, (selected & 2) ? 0 : 1, (selected & 4) ? 0 : 1, (selected & 8) ? 0 : 1);
2704 if ((prev_data & 0x80) != (data & 0x80))
2705 write_log (_T(" dskmotor %d "), (data & 0x80) ? 1 : 0);
2706 if ((prev_data & 0x02) != (data & 0x02))
2707 write_log (_T(" direct %d "), (data & 0x02) ? 1 : 0);
2708 if ((prev_data & 0x04) != (data & 0x04))
2709 write_log (_T(" side %d "), (data & 0x04) ? 1 : 0);
2710 }
2711
2712 // step goes high and drive was selected when step pulse changes: step
2713 if (prev_step != step_pulse) {
2714 if (disk_debug_logging > 1)
2715 write_log (_T(" dskstep %d "), step_pulse);
2716 prev_step = step_pulse;
2717 if (prev_step && !savestate_state) {
2718 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
2719 if (!((prev_selected | disabled) & (1 << dr))) {
2720 drive_step (floppy + dr, direction);
2721 if (floppy[dr].indexhackmode > 1 && (data & 0x80))
2722 floppy[dr].indexhack = 1;
2723 }
2724 }
2725 }
2726 }
2727
2728 if (!savestate_state) {
2729 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
2730 drive *drv = floppy + dr;
2731 /* motor on/off workings tested with small assembler code on real Amiga 1200. */
2732 /* motor/id flipflop is set only when drive select goes from high to low */
2733 if (!(selected & (1 << dr)) && (prev_selected & (1 << dr)) ) {
2734 drv->drive_id_scnt++;
2735 drv->drive_id_scnt &= 31;
2736 drv->idbit = (drv->drive_id & (1L << (31 - drv->drive_id_scnt))) ? 1 : 0;
2737 if (!(disabled & (1 << dr))) {
2738 if ((prev_data & 0x80) == 0 || (data & 0x80) == 0) {
2739 /* motor off: if motor bit = 0 in prevdata or data -> turn motor on */
2740 drive_motor (drv, 0);
2741 } else if (prev_data & 0x80) {
2742 /* motor on: if motor bit = 1 in prevdata only (motor flag state in data has no effect)
2743 -> turn motor off */
2744 drive_motor (drv, 1);
2745 }
2746 }
2747 if (!currprefs.cs_df0idhw && dr == 0)
2748 drv->idbit = 0;
2749 #ifdef DEBUG_DRIVE_ID
2750 write_log (_T("DISK_status: sel %d id %s (%08X) [0x%08lx, bit #%02d: %d]\n"),
2751 dr, drive_id_name(drv), drv->drive_id, drv->drive_id << drv->drive_id_scnt, 31 - drv->drive_id_scnt, drv->idbit);
2752 #endif
2753 }
2754 }
2755 }
2756
2757 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
2758 floppy[dr].state = (!(selected & (1 << dr))) | !floppy[dr].motoroff;
2759 update_drive_gui (dr, false);
2760 }
2761 prev_data = data;
2762 if (disk_debug_logging > 1)
2763 write_log (_T("\n"));
2764 }
2765
DISK_status(void)2766 uae_u8 DISK_status (void)
2767 {
2768 uae_u8 st = 0x3c;
2769 int dr;
2770
2771 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
2772 drive *drv = floppy + dr;
2773 #ifdef AMAX
2774 if (drv->amax) {
2775 st = amax_disk_status ();
2776 } else
2777 #endif
2778 if (!((selected | disabled) & (1 << dr))) {
2779 if (drive_running (drv)) {
2780 if (drv->catweasel) {
2781 #ifdef CATWEASEL
2782 if (catweasel_diskready (drv->catweasel))
2783 st &= ~0x20;
2784 #endif
2785 } else {
2786 if (drv->dskready && !drv->indexhack && currprefs.floppyslots[dr].dfxtype != DRV_35_DD_ESCOM)
2787 st &= ~0x20;
2788 }
2789 } else {
2790 if (currprefs.cs_df0idhw || dr > 0) {
2791 /* report drive ID */
2792 if (drv->idbit && currprefs.floppyslots[dr].dfxtype != DRV_35_DD_ESCOM)
2793 st &= ~0x20;
2794 } else {
2795 /* non-ID internal drive: mirror real dskready */
2796 if (drv->dskready)
2797 st &= ~0x20;
2798 }
2799 /* dskrdy needs some cycles after switching the motor off.. (Pro Tennis Tour) */
2800 if (!currprefs.cs_df0idhw && dr == 0 && drv->motordelay)
2801 st &= ~0x20;
2802 }
2803 if (drive_track0 (drv))
2804 st &= ~0x10;
2805 if (drive_writeprotected (drv))
2806 st &= ~8;
2807 if (drv->catweasel) {
2808 #ifdef CATWEASEL
2809 if (catweasel_disk_changed (drv->catweasel))
2810 st &= ~4;
2811 #endif
2812 } else if (drv->dskchange && currprefs.floppyslots[dr].dfxtype != DRV_525_SD) {
2813 st &= ~4;
2814 }
2815 } else if (!(selected & (1 << dr))) {
2816 if (drv->idbit)
2817 st &= ~0x20;
2818 }
2819 }
2820 return st;
2821 }
2822
unformatted(drive * drv)2823 static bool unformatted (drive *drv)
2824 {
2825 int tr = drv->cyl * 2 + side;
2826 if (tr >= drv->num_tracks)
2827 return true;
2828 if (drv->filetype == ADF_EXT2 && drv->trackdata[tr].bitlen == 0 && drv->trackdata[tr].type != TRACK_AMIGADOS)
2829 return true;
2830 if (drv->trackdata[tr].type == TRACK_NONE)
2831 return true;
2832 return false;
2833 }
2834
2835 /* get one bit from MFM bit stream */
getonebit(uae_u16 * mfmbuf,int mfmpos)2836 STATIC_INLINE uae_u32 getonebit (uae_u16 * mfmbuf, int mfmpos)
2837 {
2838 uae_u16 *buf;
2839
2840 buf = &mfmbuf[mfmpos >> 4];
2841 return (buf[0] & (1 << (15 - (mfmpos & 15)))) ? 1 : 0;
2842 }
2843
dumpdisk(void)2844 void dumpdisk (void)
2845 {
2846 int i, j, k;
2847 uae_u16 w;
2848
2849 for (i = 0; i < MAX_FLOPPY_DRIVES; i++) {
2850 drive *drv = &floppy[i];
2851 if (!(disabled & (1 << i))) {
2852 write_log (_T("Drive %d: motor %s cylinder %2d sel %s %s mfmpos %d/%d\n"),
2853 i, drv->motoroff ? _T("off") : _T(" on"), drv->cyl, (selected & (1 << i)) ? _T("no") : _T("yes"),
2854 drive_writeprotected (drv) ? _T("ro") : _T("rw"), drv->mfmpos, drv->tracklen);
2855 if (drv->motoroff == 0) {
2856 w = word;
2857 for (j = 0; j < 15; j++) {
2858 write_log (_T("%04X "), w);
2859 for (k = 0; k < 16; k++) {
2860 w <<= 1;
2861 w |= getonebit (drv->bigmfmbuf, drv->mfmpos + j * 16 + k);
2862 }
2863 }
2864 write_log (_T("\n"));
2865 }
2866 }
2867 }
2868 write_log (_T("side %d dma %d off %d word %04X pt %08X len %04X bytr %04X adk %04X sync %04X\n"),
2869 side, dskdmaen, bitoffset, word, dskpt, dsklen, dskbytr_val, adkcon, dsksync);
2870 }
2871
disk_dmafinished(void)2872 static void disk_dmafinished (void)
2873 {
2874 INTREQ (0x8000 | 0x0002);
2875 longwritemode = 0;
2876 dskdmaen = DSKDMA_OFF;
2877 dsklength = 0;
2878 if (disk_debug_logging > 0) {
2879 int dr;
2880 /* REMOVEME:
2881 * nowhere used
2882 */
2883 #if 0
2884 int mfmpos = -1;
2885 #endif
2886 write_log (_T("disk dma finished %08X MFMpos="), dskpt);
2887 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++)
2888 write_log (_T("%d%s"), floppy[dr].mfmpos, dr < MAX_FLOPPY_DRIVES - 1 ? _T(",") : _T(""));
2889 write_log (_T("\n"));
2890 }
2891 }
2892
fetchnextrevolution(drive * drv)2893 static void fetchnextrevolution (drive *drv)
2894 {
2895 drv->trackspeed = get_floppy_speed2 (drv);
2896 if (!drv->multi_revolution)
2897 return;
2898 switch (drv->filetype)
2899 {
2900 case ADF_IPF:
2901 #ifdef CAPS
2902 caps_loadrevolution (drv->bigmfmbuf, drv - floppy, drv->cyl * 2 + side, &drv->tracklen);
2903 #endif
2904 break;
2905 case ADF_FDI:
2906 #ifdef FDI2RAW
2907 fdi2raw_loadrevolution (drv->fdi, drv->bigmfmbuf, drv->tracktiming, drv->cyl * 2 + side, &drv->tracklen, 1);
2908 #endif
2909 break;
2910 case ADF_NONE:
2911 case ADF_NORMAL:
2912 case ADF_EXT1:
2913 case ADF_EXT2:
2914 case ADF_CATWEASEL:
2915 case ADF_PCDOS:
2916 break;
2917 }
2918 }
2919
DISK_handler(uae_u32 data)2920 void DISK_handler (uae_u32 data)
2921 {
2922 int flag = data & 255;
2923 int disk_sync_cycle = data >> 8;
2924 /* REMOVEME:
2925 * nowhere used
2926 */
2927 #if 0
2928 int hpos = current_hpos ();
2929 #endif
2930
2931 event2_remevent (ev2_disk);
2932 DISK_update (disk_sync_cycle);
2933 if (flag & (DISK_REVOLUTION << 0))
2934 fetchnextrevolution (&floppy[0]);
2935 if (flag & (DISK_REVOLUTION << 1))
2936 fetchnextrevolution (&floppy[1]);
2937 if (flag & (DISK_REVOLUTION << 2))
2938 fetchnextrevolution (&floppy[2]);
2939 if (flag & (DISK_REVOLUTION << 3))
2940 fetchnextrevolution (&floppy[3]);
2941 if (flag & DISK_WORDSYNC)
2942 INTREQ (0x8000 | 0x1000);
2943 if (flag & DISK_INDEXSYNC) {
2944 if (!indexdecay) {
2945 indexdecay = 2;
2946 cia_diskindex ();
2947 }
2948 }
2949 }
2950
disk_doupdate_write(drive * drv,int floppybits)2951 static void disk_doupdate_write (drive * drv, int floppybits)
2952 {
2953 int dr;
2954 int drives[4];
2955
2956 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
2957 drive *drv2 = &floppy[dr];
2958 drives[dr] = 0;
2959 if (drv2->motoroff)
2960 continue;
2961 if (selected & (1 << dr))
2962 continue;
2963 drives[dr] = 1;
2964 }
2965
2966 while (floppybits >= drv->trackspeed) {
2967 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
2968 if (drives[dr]) {
2969 floppy[dr].mfmpos++;
2970 floppy[dr].mfmpos %= drv->tracklen;
2971 }
2972 }
2973 if (dmaen (DMA_DISK) && dskdmaen == DSKDMA_WRITE && dsklength > 0 && fifo_filled) {
2974 bitoffset++;
2975 bitoffset &= 15;
2976 if (!bitoffset) {
2977 // fast disk modes, fill the fifo instantly
2978 if (currprefs.floppy_speed > 100 && !fifo_inuse[0] && !fifo_inuse[1] && !fifo_inuse[2]) {
2979 while (!fifo_inuse[2]) {
2980 uae_u16 w = chipmem_wget_indirect (dskpt);
2981 DSKDAT (w);
2982 dskpt += 2;
2983 }
2984 }
2985 if (disk_fifostatus () >= 0) {
2986 uae_u16 w = DSKDATR ();
2987 for (dr = 0; dr < MAX_FLOPPY_DRIVES ; dr++) {
2988 drive *drv2 = &floppy[dr];
2989 if (drives[dr]) {
2990 drv2->bigmfmbuf[drv2->mfmpos >> 4] = w;
2991 drv2->bigmfmbuf[(drv2->mfmpos >> 4) + 1] = 0x5555;
2992 drv2->writtento = 1;
2993 }
2994 #ifdef AMAX
2995 if (currprefs.amaxromfile[0])
2996 amax_diskwrite (w);
2997 #endif
2998 }
2999 dsklength--;
3000 if (dsklength <= 0) {
3001 disk_dmafinished ();
3002 for (int dr = 0; dr < MAX_FLOPPY_DRIVES ; dr++) {
3003 drive *drv = &floppy[dr];
3004 drv->writtento = 0;
3005 if (drv->motoroff)
3006 continue;
3007 if (selected & (1 << dr))
3008 continue;
3009 drive_write_data (drv);
3010 }
3011 }
3012 }
3013 }
3014 }
3015 floppybits -= drv->trackspeed;
3016 }
3017 }
3018
update_jitter(void)3019 static void update_jitter (void)
3020 {
3021 if (currprefs.floppy_random_bits_max > 0)
3022 disk_jitter = ((uaerand () >> 4) % (currprefs.floppy_random_bits_max - currprefs.floppy_random_bits_min + 1)) + currprefs.floppy_random_bits_min;
3023 else
3024 disk_jitter = 0;
3025 }
3026
updatetrackspeed(drive * drv,int mfmpos)3027 static void updatetrackspeed (drive *drv, int mfmpos)
3028 {
3029 if (dskdmaen < DSKDMA_WRITE) {
3030 int t = drv->tracktiming[mfmpos / 8];
3031 drv->trackspeed = get_floppy_speed2 (drv) * t / 1000;
3032 if (drv->trackspeed < 700 || drv->trackspeed > 3000) {
3033 static int warned;
3034 warned++;
3035 if (warned < 50)
3036 write_log (_T("corrupted trackspeed value %d\n"), drv->trackspeed);
3037 drv->trackspeed = 1000;
3038 }
3039 }
3040 }
3041
disk_doupdate_predict(int startcycle)3042 static void disk_doupdate_predict (int startcycle)
3043 {
3044 int finaleventcycle = maxhpos << 8;
3045 int finaleventflag = 0;
3046
3047 for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3048 drive *drv = &floppy[dr];
3049 if (drv->motoroff)
3050 continue;
3051 if (drv->motoroff || !drv->trackspeed)
3052 continue;
3053 if (selected & (1 << dr))
3054 continue;
3055 int diskevent_flag = 0;
3056 uae_u32 tword = word;
3057 int countcycle = startcycle + (drv->floppybitcounter % drv->trackspeed);
3058 int mfmpos = drv->mfmpos;
3059 while (countcycle < (maxhpos << 8)) {
3060 if (drv->tracktiming[0])
3061 updatetrackspeed (drv, mfmpos);
3062 if (dskdmaen != DSKDMA_WRITE || (dskdmaen == DSKDMA_WRITE && !dma_enable)) {
3063 tword <<= 1;
3064 if (!drive_empty (drv)) {
3065 if (unformatted (drv))
3066 tword |= (uaerand () & 0x1000) ? 1 : 0;
3067 else
3068 tword |= getonebit (drv->bigmfmbuf, mfmpos);
3069 }
3070 if ((tword & 0xffff) == dsksync && dsksync != 0)
3071 diskevent_flag |= DISK_WORDSYNC;
3072 }
3073 mfmpos++;
3074 mfmpos %= drv->tracklen;
3075 if (mfmpos == 0)
3076 diskevent_flag |= DISK_REVOLUTION << (drv - floppy);
3077 if (mfmpos == drv->indexoffset)
3078 diskevent_flag |= DISK_INDEXSYNC;
3079 if (dskdmaen != DSKDMA_WRITE && mfmpos == drv->skipoffset) {
3080 update_jitter ();
3081 int skipcnt = disk_jitter;
3082 while (skipcnt-- > 0) {
3083 mfmpos++;
3084 mfmpos %= drv->tracklen;
3085 if (mfmpos == 0)
3086 diskevent_flag |= DISK_REVOLUTION << (drv - floppy);
3087 if (mfmpos == drv->indexoffset)
3088 diskevent_flag |= DISK_INDEXSYNC;
3089 }
3090 }
3091 if (diskevent_flag)
3092 break;
3093 countcycle += drv->trackspeed;
3094 }
3095 if (drv->tracktiming[0])
3096 updatetrackspeed (drv, drv->mfmpos);
3097 if (diskevent_flag && countcycle < finaleventcycle) {
3098 finaleventcycle = countcycle;
3099 finaleventflag = diskevent_flag;
3100 }
3101 }
3102 if (finaleventflag && (finaleventcycle >> 8) < maxhpos) {
3103 event2_newevent (ev2_disk, (finaleventcycle - startcycle) >> 8, ((finaleventcycle >> 8) << 8) | finaleventflag);
3104 }
3105 }
3106
disk_fifostatus(void)3107 int disk_fifostatus (void)
3108 {
3109 if (fifo_inuse[0] && fifo_inuse[1] && fifo_inuse[2])
3110 return 1;
3111 if (!fifo_inuse[0] && !fifo_inuse[1] && !fifo_inuse[2])
3112 return -1;
3113 return 0;
3114 }
3115
doreaddma(void)3116 static int doreaddma (void)
3117 {
3118 if (dmaen (DMA_DISK) && bitoffset == 15 && dma_enable && dskdmaen == DSKDMA_READ && dsklength >= 0) {
3119 if (dsklength > 0) {
3120 // DSKLEN == 1: finish without DMA transfer.
3121 if (dsklength == 1 && dsklength2 == 1) {
3122 disk_dmafinished ();
3123 return 0;
3124 }
3125 // fast disk modes, just flush the fifo
3126 if (currprefs.floppy_speed > 100 && fifo_inuse[0] && fifo_inuse[1] && fifo_inuse[2]) {
3127 while (fifo_inuse[0]) {
3128 uae_u16 w = DSKDATR ();
3129 chipmem_wput_indirect (dskpt, w);
3130 dskpt += 2;
3131 }
3132 }
3133 if (disk_fifostatus () > 0) {
3134 write_log (_T("doreaddma() fifo overflow detected, retrying..\n"));
3135 return -1;
3136 } else {
3137 DSKDAT (word);
3138 dsklength--;
3139 }
3140 }
3141 return 1;
3142 }
3143 return 0;
3144 }
3145
disk_doupdate_read_nothing(int floppybits)3146 static void disk_doupdate_read_nothing (int floppybits)
3147 {
3148 /* REMOVEME:
3149 * nowhere used
3150 */
3151 #if 0
3152 int j = 0, k = 1, l = 0;
3153 #endif
3154
3155 while (floppybits >= get_floppy_speed ()) {
3156 word <<= 1;
3157 doreaddma ();
3158 if ((bitoffset & 7) == 7) {
3159 dskbytr_val = word & 0xff;
3160 dskbytr_val |= 0x8000;
3161 }
3162 bitoffset++;
3163 bitoffset &= 15;
3164 floppybits -= get_floppy_speed ();
3165 }
3166 }
3167
disk_doupdate_read(drive * drv,int floppybits)3168 static void disk_doupdate_read (drive * drv, int floppybits)
3169 {
3170 // int j = 0, k = 1, l = 0;
3171
3172 /*
3173 uae_u16 *mfmbuf = drv->bigmfmbuf;
3174 dsksync = 0x4444;
3175 adkcon |= 0x400;
3176 drv->mfmpos = 0;
3177 memset (mfmbuf, 0, 1000);
3178 cycles = 0x1000000;
3179 // 4444 4444 4444 aaaa aaaaa 4444 4444 4444
3180 // 4444 aaaa aaaa 4444
3181 mfmbuf[0] = 0x4444;
3182 mfmbuf[1] = 0x4444;
3183 mfmbuf[2] = 0x4444;
3184 mfmbuf[3] = 0xaaaa;
3185 mfmbuf[4] = 0xaaaa;
3186 mfmbuf[5] = 0x4444;
3187 mfmbuf[6] = 0x4444;
3188 mfmbuf[7] = 0x4444;
3189 */
3190 while (floppybits >= drv->trackspeed) {
3191 int oldmfmpos = drv->mfmpos;
3192 if (drv->tracktiming[0])
3193 updatetrackspeed (drv, drv->mfmpos);
3194 word <<= 1;
3195 if (!drive_empty (drv)) {
3196 if (unformatted (drv))
3197 word |= (uaerand () & 0x1000) ? 1 : 0;
3198 else
3199 word |= getonebit (drv->bigmfmbuf, drv->mfmpos);
3200 }
3201 //write_log (_T("%08X bo=%d so=%d mfmpos=%d dma=%d\n"), (word & 0xffffff), bitoffset, syncoffset, drv->mfmpos, dma_enable);
3202 drv->mfmpos++;
3203 drv->mfmpos %= drv->tracklen;
3204 if (drv->mfmpos == drv->indexoffset) {
3205 if (disk_debug_logging > 1 && drv->indexhack)
3206 write_log (_T("indexhack cleared\n"));
3207 drv->indexhack = 0;
3208 }
3209 if (drv->mfmpos == drv->skipoffset) {
3210 update_jitter ();
3211 drv->mfmpos += disk_jitter;
3212 drv->mfmpos %= drv->tracklen;
3213 }
3214 if (doreaddma () < 0) {
3215 drv->mfmpos = oldmfmpos;
3216 return;
3217 }
3218 if ((bitoffset & 7) == 7) {
3219 dskbytr_val = word & 0xff;
3220 dskbytr_val |= 0x8000;
3221 }
3222 if (word == dsksync) {
3223 dsksync_cycles = get_cycles () + WORDSYNC_TIME * CYCLE_UNIT;
3224 if (dskdmaen != DSKDMA_OFF) {
3225 if (disk_debug_logging && dma_enable == 0)
3226 write_log (_T("Sync match, DMA started at %d PC=%08x\n"), drv->mfmpos, M68K_GETPC);
3227 dma_enable = 1;
3228 }
3229 if (adkcon & 0x400) {
3230 bitoffset = 15;
3231 }
3232 }
3233 bitoffset++;
3234 bitoffset &= 15;
3235 floppybits -= drv->trackspeed;
3236
3237 }
3238 }
3239
disk_dma_debugmsg(void)3240 static void disk_dma_debugmsg (void)
3241 {
3242 write_log (_T("LEN=%04X (%d) SYNC=%04X PT=%08X ADKCON=%04X PC=%08X\n"),
3243 dsklength, dsklength, (adkcon & 0x400) ? dsksync : 0xffff, dskpt, adkcon, M68K_GETPC);
3244 }
3245
3246 /* this is very unoptimized. DSKBYTR is used very rarely, so it should not matter. */
3247
DSKBYTR(int hpos)3248 uae_u16 DSKBYTR (int hpos)
3249 {
3250 uae_u16 v;
3251
3252 DISK_update (hpos);
3253 v = dskbytr_val;
3254 dskbytr_val &= ~0x8000;
3255 if (word == dsksync && cycles_in_range (dsksync_cycles))
3256 v |= 0x1000;
3257 if (dskdmaen != DSKDMA_OFF && dmaen (DMA_DISK))
3258 v |= 0x4000;
3259 if (dsklen & 0x4000)
3260 v |= 0x2000;
3261 if (disk_debug_logging > 1)
3262 write_log (_T("DSKBYTR=%04X hpos=%d\n"), v, hpos);
3263 #ifdef DEBUGGER
3264 if (disk_debug_mode & DISK_DEBUG_PIO) {
3265 int dr;
3266 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3267 drive *drv = &floppy[dr];
3268 if (drv->motoroff)
3269 continue;
3270 if (!(selected & (1 << dr))) {
3271 if (disk_debug_track < 0 || disk_debug_track == 2 * drv->cyl + side) {
3272 disk_dma_debugmsg ();
3273 write_log (_T("DSKBYTR=%04X\n"), v);
3274 activate_debugger ();
3275 break;
3276 }
3277 }
3278 }
3279 }
3280 #endif
3281 return v;
3282 }
3283
DISK_start(void)3284 static void DISK_start (void)
3285 {
3286 unsigned int dr;
3287
3288 for (unsigned int i = 0; i < 3; i++)
3289 fifo_inuse[i] = false;
3290 fifo_filled = 0;
3291 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3292 drive *drv = &floppy[dr];
3293 if (!(selected & (1 << dr))) {
3294 int tr = drv->cyl * 2 + side;
3295 trackid *ti = drv->trackdata + tr;
3296
3297 if (dskdmaen == DSKDMA_WRITE) {
3298 drv->tracklen = longwritemode ? FLOPPY_WRITE_MAXLEN : FLOPPY_WRITE_LEN * drv->ddhd * 8 * 2;
3299 drv->trackspeed = get_floppy_speed ();
3300 drv->skipoffset = -1;
3301 updatemfmpos (drv);
3302 }
3303 /* Ugh. A nasty hack. Assume ADF_EXT1 tracks are always read
3304 from the start. */
3305 if (ti->type == TRACK_RAW1) {
3306 drv->mfmpos = 0;
3307 bitoffset = 0;
3308 }
3309 if (drv->catweasel)
3310 drive_fill_bigbuf (drv, 1);
3311 }
3312 drv->floppybitcounter = 0;
3313 }
3314 dma_enable = (adkcon & 0x400) ? 0 : 1;
3315 }
3316
3317 static int linecounter;
3318
DISK_hsync(void)3319 void DISK_hsync (void)
3320 {
3321 int dr;
3322
3323 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3324 drive *drv = &floppy[dr];
3325 if (drv->steplimit)
3326 drv->steplimit--;
3327 }
3328 if (indexdecay)
3329 indexdecay--;
3330 if (linecounter) {
3331 linecounter--;
3332 if (! linecounter)
3333 disk_dmafinished ();
3334 return;
3335 }
3336 DISK_update (maxhpos);
3337 }
3338
DISK_update(int tohpos)3339 void DISK_update (int tohpos)
3340 {
3341 int dr;
3342 int cycles;
3343 /* REMOVEME:
3344 * nowhere used
3345 */
3346 #if 0
3347 int startcycle = disk_hpos;
3348 #endif
3349
3350 if (disk_hpos < 0) {
3351 disk_hpos = - disk_hpos;
3352 return;
3353 }
3354
3355 cycles = (tohpos << 8) - disk_hpos;
3356 #if 0
3357 if (tohpos == 228)
3358 write_log (_T("x"));
3359 if (tohpos != maxhpos || cycles / 256 != maxhpos)
3360 write_log (_T("%d %d %d\n"), tohpos, cycles / 256, disk_hpos / 256);
3361 #endif
3362 if (cycles <= 0)
3363 return;
3364 disk_hpos += cycles;
3365 if (disk_hpos >= (maxhpos << 8))
3366 disk_hpos %= 1 << 8;
3367
3368 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3369 drive *drv = &floppy[dr];
3370
3371 if (drv->motoroff || !drv->tracklen || !drv->trackspeed)
3372 continue;
3373 drv->floppybitcounter += cycles;
3374 if (selected & (1 << dr)) {
3375 drv->mfmpos += drv->floppybitcounter / drv->trackspeed;
3376 drv->mfmpos %= drv->tracklen;
3377 drv->floppybitcounter %= drv->trackspeed;
3378 continue;
3379 }
3380 if (drv->diskfile)
3381 drive_fill_bigbuf (drv, 0);
3382 drv->mfmpos %= drv->tracklen;
3383 }
3384 int didaccess = 0;
3385 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3386 drive *drv = &floppy[dr];
3387 if (drv->motoroff || !drv->trackspeed)
3388 continue;
3389 if (selected & (1 << dr))
3390 continue;
3391 /* write dma and wordsync enabled: read until wordsync match found */
3392 if (dskdmaen == DSKDMA_WRITE && dma_enable)
3393 disk_doupdate_write (drv, drv->floppybitcounter);
3394 else
3395 disk_doupdate_read (drv, drv->floppybitcounter);
3396
3397 drv->floppybitcounter %= drv->trackspeed;
3398 didaccess = 1;
3399 }
3400 /* no floppy selected but read dma */
3401 if (!didaccess && dskdmaen == DSKDMA_READ) {
3402 disk_doupdate_read_nothing (cycles);
3403 }
3404
3405 /* instantly finish dma if dsklen==0 and wordsync detected */
3406 if (dskdmaen != DSKDMA_OFF && dma_enable && dsklength2 == 0 && dsklength == 0)
3407 disk_dmafinished ();
3408
3409 disk_doupdate_predict (disk_hpos);
3410 }
3411
DSKLEN(uae_u16 v,int hpos)3412 void DSKLEN (uae_u16 v, int hpos)
3413 {
3414 int dr, prev = dsklen;
3415 int noselected = 0;
3416 int motormask;
3417
3418 DISK_update (hpos);
3419
3420 if ((v & 0x8000) && (dsklen & 0x8000)) {
3421 dskdmaen = DSKDMA_READ;
3422 DISK_start ();
3423 }
3424 if (!(v & 0x8000)) {
3425 if (dskdmaen != DSKDMA_OFF) {
3426 /* Megalomania and Knightmare does this */
3427 if (disk_debug_logging > 0 && dskdmaen == DSKDMA_READ)
3428 write_log (_T("warning: Disk read DMA aborted, %d words left PC=%x\n"), dsklength, M68K_GETPC);
3429 if (dskdmaen == DSKDMA_WRITE) {
3430 write_log (_T("warning: Disk write DMA aborted, %d words left PC=%x\n"), dsklength, M68K_GETPC);
3431 // did program write something that needs to be stored to file?
3432 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3433 drive *drv2 = &floppy[dr];
3434 if (!drv2->writtento)
3435 continue;
3436 drive_write_data (drv2);
3437 }
3438 }
3439 dskdmaen = DSKDMA_OFF;
3440 }
3441 }
3442 dsklen = v;
3443 dsklength2 = dsklength = dsklen & 0x3fff;
3444
3445 if (dskdmaen == DSKDMA_OFF)
3446 return;
3447
3448 if (dsklength == 0 && dma_enable) {
3449 disk_dmafinished ();
3450 return;
3451 }
3452
3453 if ((v & 0x4000) && (prev & 0x4000)) {
3454 if (dsklength == 0)
3455 return;
3456 if (dsklength == 1) {
3457 disk_dmafinished ();
3458 return;
3459 }
3460 dskdmaen = DSKDMA_WRITE;
3461 DISK_start ();
3462 }
3463
3464 #ifdef DEBUGGER
3465 if (((disk_debug_mode & DISK_DEBUG_DMA_READ) && dskdmaen == DSKDMA_READ) ||
3466 ((disk_debug_mode & DISK_DEBUG_DMA_WRITE) && dskdmaen == DSKDMA_WRITE))
3467 {
3468 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3469 drive *drv = &floppy[dr];
3470 if (drv->motoroff)
3471 continue;
3472 if (!(selected & (1 << dr))) {
3473 if (disk_debug_track < 0 || disk_debug_track == 2 * drv->cyl + side) {
3474 disk_dma_debugmsg ();
3475 activate_debugger ();
3476 break;
3477 }
3478 }
3479 }
3480 }
3481 #endif
3482
3483 motormask = 0;
3484 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3485 drive *drv = &floppy[dr];
3486 drv->writtento = 0;
3487 if (drv->motoroff)
3488 continue;
3489 motormask |= 1 << dr;
3490 if ((selected & (1 << dr)) == 0)
3491 break;
3492 }
3493 if (dr == 4) {
3494 write_log (_T("disk %s DMA started, drvmask=%x motormask=%x PC=%08x\n"),
3495 dskdmaen == DSKDMA_WRITE ? _T("write") : _T("read"), selected ^ 15, motormask, M68K_GETPC);
3496 noselected = 1;
3497 } else {
3498 if (disk_debug_logging > 0) {
3499 write_log (_T("disk %s DMA started, drvmask=%x track %d mfmpos %d dmaen=%d PC=%08X\n"),
3500 dskdmaen == DSKDMA_WRITE ? _T("write") : _T("read"), selected ^ 15,
3501 floppy[dr].cyl * 2 + side, floppy[dr].mfmpos, dma_enable, M68K_GETPC);
3502 disk_dma_debugmsg ();
3503 }
3504 }
3505
3506 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++)
3507 update_drive_gui (dr, false);
3508
3509 /* Try to make floppy access from Kickstart faster. */
3510 if (dskdmaen != DSKDMA_READ && dskdmaen != DSKDMA_WRITE)
3511 return;
3512
3513 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3514 drive *drv = &floppy[dr];
3515 if (selected & (1 << dr))
3516 continue;
3517 if (drv->filetype != ADF_NORMAL)
3518 break;
3519 }
3520 if (dr < MAX_FLOPPY_DRIVES) /* no turbo mode if any selected drive has non-standard ADF */
3521 return;
3522 {
3523 int done = 0;
3524 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3525 drive *drv = &floppy[dr];
3526 int pos, i;
3527
3528 if (drv->motoroff)
3529 continue;
3530 if (!drv->useturbo && currprefs.floppy_speed > 0)
3531 continue;
3532 if (selected & (1 << dr))
3533 continue;
3534
3535 pos = drv->mfmpos & ~15;
3536 drive_fill_bigbuf (drv, 0);
3537
3538 if (dskdmaen == DSKDMA_READ) { /* TURBO read */
3539
3540 if (adkcon & 0x400) {
3541 for (i = 0; i < drv->tracklen; i += 16) {
3542 pos += 16;
3543 pos %= drv->tracklen;
3544 if (drv->bigmfmbuf[pos >> 4] == dsksync) {
3545 /* must skip first disk sync marker */
3546 pos += 16;
3547 pos %= drv->tracklen;
3548 break;
3549 }
3550 }
3551 if (i >= drv->tracklen)
3552 return;
3553 }
3554 while (dsklength-- > 0) {
3555 chipmem_wput_indirect (dskpt, drv->bigmfmbuf[pos >> 4]);
3556 dskpt += 2;
3557 pos += 16;
3558 pos %= drv->tracklen;
3559 }
3560 drv->mfmpos = pos;
3561 INTREQ (0x8000 | 0x1000);
3562 done = 1;
3563
3564 } else if (dskdmaen == DSKDMA_WRITE) { /* TURBO write */
3565
3566 for (i = 0; i < dsklength; i++) {
3567 uae_u16 w = chipmem_wget_indirect (dskpt + i * 2);
3568 drv->bigmfmbuf[pos >> 4] = w;
3569 #ifdef AMAX
3570 if (currprefs.amaxromfile[0])
3571 amax_diskwrite (w);
3572 #endif
3573 pos += 16;
3574 pos %= drv->tracklen;
3575 }
3576 drv->mfmpos = pos;
3577 drive_write_data (drv);
3578 done = 1;
3579 }
3580 }
3581 if (!done && noselected) {
3582 while (dsklength-- > 0) {
3583 if (dskdmaen == DSKDMA_WRITE) {
3584 uae_u16 w = chipmem_wget_indirect (dskpt);
3585 #ifdef AMAX
3586 if (currprefs.amaxromfile[0])
3587 amax_diskwrite (w);
3588 #endif
3589 } else {
3590 chipmem_wput_indirect (dskpt, 0);
3591 }
3592 dskpt += 2;
3593 }
3594 INTREQ (0x8000 | 0x1000);
3595 done = 1;
3596 }
3597
3598 if (done) {
3599 linecounter = 2;
3600 dskdmaen = DSKDMA_OFF;
3601 return;
3602 }
3603 }
3604 }
3605
DISK_update_adkcon(int hpos,uae_u16 v)3606 void DISK_update_adkcon (int hpos, uae_u16 v)
3607 {
3608 uae_u16 vold = adkcon;
3609 uae_u16 vnew = adkcon;
3610 if (v & 0x8000)
3611 vnew |= v & 0x7FFF;
3612 else
3613 vnew &= ~v;
3614 if ((vnew & 0x400) && !(vold & 0x400))
3615 bitoffset = 0;
3616 }
3617
DSKSYNC(int hpos,uae_u16 v)3618 void DSKSYNC (int hpos, uae_u16 v)
3619 {
3620 if (v == dsksync)
3621 return;
3622 DISK_update (hpos);
3623 dsksync = v;
3624 }
3625
iswrite(void)3626 STATIC_INLINE bool iswrite (void)
3627 {
3628 return dskdmaen == 3;
3629 }
3630
DSKDAT(uae_u16 v)3631 void DSKDAT (uae_u16 v)
3632 {
3633 if (fifo_inuse[2]) {
3634 write_log (_T("DSKDAT: FIFO overflow!\n"));
3635 return;
3636 }
3637 fifo_inuse[2] = fifo_inuse[1];
3638 fifo[2] = fifo[1];
3639 fifo_inuse[1] = fifo_inuse[0];
3640 fifo[1] = fifo[0];
3641 fifo_inuse[0] = iswrite () ? 2 : 1;
3642 fifo[0] = v;
3643 fifo_filled = 1;
3644 }
DSKDATR(void)3645 uae_u16 DSKDATR (void)
3646 {
3647 int i;
3648 uae_u16 v = 0;
3649 for (i = 2; i >= 0; i--) {
3650 if (fifo_inuse[i]) {
3651 fifo_inuse[i] = 0;
3652 v = fifo[i];
3653 break;
3654 }
3655 }
3656 if (i < 0) {
3657 write_log (_T("DSKDATR: FIFO underflow!\n"));
3658 } else if (dskdmaen > 0 && dskdmaen < 3 && dsklength <= 0 && disk_fifostatus () < 0) {
3659 disk_dmafinished ();
3660 }
3661 return v;
3662 }
3663
disk_dmal(void)3664 uae_u16 disk_dmal (void)
3665 {
3666 uae_u16 dmal = 0;
3667 if (dskdmaen) {
3668 if (dskdmaen == 3) {
3669 dmal = (1 + 2) * (fifo_inuse[0] ? 1 : 0) + (4 + 8) * (fifo_inuse[1] ? 1 : 0) + (16 + 32) * (fifo_inuse[2] ? 1 : 0);
3670 dmal ^= 63;
3671 if (dsklength == 2)
3672 dmal &= ~(16 + 32);
3673 if (dsklength == 1)
3674 dmal &= ~(16 + 32 + 4 + 8);
3675 } else {
3676 dmal = 16 * (fifo_inuse[0] ? 1 : 0) + 4 * (fifo_inuse[1] ? 1 : 0) + 1 * (fifo_inuse[2] ? 1 : 0);
3677 }
3678 }
3679 return dmal;
3680 }
disk_getpt(void)3681 uaecptr disk_getpt (void)
3682 {
3683 uaecptr pt = dskpt;
3684 dskpt += 2;
3685 return pt;
3686 }
DSKPTH(uae_u16 v)3687 void DSKPTH (uae_u16 v)
3688 {
3689 dskpt = (dskpt & 0xffff) | ((uae_u32) v << 16);
3690 }
3691
DSKPTL(uae_u16 v)3692 void DSKPTL (uae_u16 v)
3693 {
3694 dskpt = (dskpt & ~0xffff) | (v);
3695 }
3696
DISK_free(void)3697 void DISK_free (void)
3698 {
3699 int dr;
3700 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3701 drive *drv = &floppy[dr];
3702 drive_image_free (drv);
3703 }
3704 }
3705
DISK_init(void)3706 void DISK_init (void)
3707 {
3708 int dr;
3709
3710 for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
3711 drive *drv = &floppy[dr];
3712 /* reset all drive types to 3.5 DD */
3713 drive_settype_id (drv);
3714 if (!drive_insert (drv, &currprefs, dr, currprefs.floppyslots[dr].df, false, currprefs.floppyslots[dr].forcedwriteprotect))
3715 disk_eject (dr);
3716 }
3717 if (disk_empty (0))
3718 write_log (_T("No disk in drive 0.\n"));
3719 #ifdef AMAX
3720 amax_init ();
3721 #endif
3722 }
3723
DISK_reset(void)3724 void DISK_reset (void)
3725 {
3726 int i;
3727
3728 if (savestate_state)
3729 return;
3730
3731 //floppy[0].catweasel = &cwc.drives[0];
3732 disk_hpos = 0;
3733 dskdmaen = 0;
3734 disabled = 0;
3735 for (i = 0; i < MAX_FLOPPY_DRIVES; i++)
3736 reset_drive (i);
3737 #ifdef AMAX
3738 setamax ();
3739 #endif
3740 }
3741
DISK_examine_image(struct uae_prefs * p,int num,uae_u32 * crc32)3742 int DISK_examine_image (struct uae_prefs *p, int num, uae_u32 *crc32)
3743 {
3744 int drvsec;
3745 int ret, i;
3746 drive *drv = &floppy[num];
3747 uae_u32 dos, crc, crc2;
3748 int wasdelayed = drv->dskchange_time;
3749 int sectable[MAX_SECTORS];
3750 int oldcyl, oldside;
3751
3752 ret = 0;
3753 *crc32 = 0;
3754 oldcyl = drv->cyl;
3755 oldside = side;
3756 drv->cyl = 0;
3757 side = 0;
3758 if (!drive_insert (drv, p, num, p->floppyslots[num].df, true, true) || !drv->diskfile) {
3759 drv->cyl = oldcyl;
3760 side = oldside;
3761 return 1;
3762 }
3763 *crc32 = zfile_crc32 (drv->diskfile);
3764 decode_buffer (drv->bigmfmbuf, drv->cyl, 11, drv->ddhd, drv->filetype, &drvsec, sectable, 1);
3765 drv->cyl = oldcyl;
3766 side = oldside;
3767 if (sectable[0] == 0 || sectable[1] == 0) {
3768 ret = 2;
3769 goto end;
3770 }
3771 crc = crc2 = 0;
3772 for (i = 0; i < 1024; i += 4) {
3773 uae_u32 v = (writebuffer[i] << 24) | (writebuffer[i + 1] << 16) | (writebuffer[i + 2] << 8) | writebuffer[i + 3];
3774 if (i == 0)
3775 dos = v;
3776 if (i == 4) {
3777 crc2 = v;
3778 v = 0;
3779 }
3780 if (crc + v < crc)
3781 crc++;
3782 crc += v;
3783 }
3784 if (dos == 0x4b49434b) { /* KICK */
3785 ret = 10;
3786 goto end;
3787 }
3788 crc ^= 0xffffffff;
3789 if (crc != crc2) {
3790 ret = 3;
3791 goto end;
3792 }
3793 if (dos == 0x444f5300)
3794 ret = 10;
3795 else if (dos == 0x444f5301 || dos == 0x444f5302 || dos == 0x444f5303)
3796 ret = 11;
3797 else if (dos == 0x444f5304 || dos == 0x444f5305 || dos == 0x444f5306 || dos == 0x444f5307)
3798 ret = 12;
3799 else
3800 ret = 4;
3801 end:
3802 drive_image_free (drv);
3803 if (wasdelayed > 1) {
3804 drive_eject (drv);
3805 currprefs.floppyslots[num].df[0] = 0;
3806 drv->dskchange_time = wasdelayed;
3807 disk_insert (num, drv->newname, false);
3808 }
3809 return ret;
3810 }
3811
3812
3813 /* Disk save/restore code */
3814
3815 #if defined SAVESTATE || defined DEBUGGER
3816
DISK_save_custom(uae_u32 * pdskpt,uae_u16 * pdsklength,uae_u16 * pdsksync,uae_u16 * pdskbytr)3817 void DISK_save_custom (uae_u32 *pdskpt, uae_u16 *pdsklength, uae_u16 *pdsksync, uae_u16 *pdskbytr)
3818 {
3819 if (pdskpt)
3820 *pdskpt = dskpt;
3821 if (pdsklength)
3822 *pdsklength = dsklen;
3823 if (pdsksync)
3824 *pdsksync = dsksync;
3825 if (pdskbytr)
3826 *pdskbytr = dskbytr_val;
3827 }
3828
3829 #endif /* SAVESTATE || DEBUGGER */
3830
getadfcrc(drive * drv)3831 static uae_u32 getadfcrc (drive *drv)
3832 {
3833 uae_u8 *b;
3834 uae_u32 crc32;
3835 int size;
3836
3837 if (!drv->diskfile)
3838 return 0;
3839 zfile_fseek (drv->diskfile, 0, SEEK_END);
3840 size = zfile_ftell (drv->diskfile);
3841 b = xmalloc (uae_u8, size);
3842 if (!b)
3843 return 0;
3844 zfile_fseek (drv->diskfile, 0, SEEK_SET);
3845 zfile_fread (b, 1, size, drv->diskfile);
3846 crc32 = get_crc32 (b, size);
3847 xfree (b);
3848 return crc32;
3849 }
3850
3851 #ifdef SAVESTATE
3852
DISK_restore_custom(uae_u32 pdskpt,uae_u16 pdsklength,uae_u16 pdskbytr)3853 void DISK_restore_custom (uae_u32 pdskpt, uae_u16 pdsklength, uae_u16 pdskbytr)
3854 {
3855 dskpt = pdskpt;
3856 dsklen = pdsklength;
3857 dskbytr_val = pdskbytr;
3858 }
3859
restore_disk_finish(void)3860 void restore_disk_finish (void)
3861 {
3862 int cnt = 0;
3863 for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
3864 if (currprefs.floppyslots[i].dfxtype >= 0) {
3865 update_drive_gui (i, true);
3866 cnt++;
3867 }
3868 }
3869 currprefs.nr_floppies = changed_prefs.nr_floppies = cnt;
3870 DISK_check_change ();
3871 setamax ();
3872 #if 0
3873 if (dskdmaen)
3874 dumpdisk ();
3875 #endif
3876 }
3877
restore_disk(int num,uae_u8 * src)3878 uae_u8 *restore_disk (int num,uae_u8 *src)
3879 {
3880 drive *drv;
3881 int state, dfxtype;
3882 TCHAR old[MAX_DPATH];
3883 TCHAR *s;
3884 int newis;
3885
3886 drv = &floppy[num];
3887 disabled &= ~(1 << num);
3888 drv->drive_id = restore_u32 ();
3889 drv->motoroff = 1;
3890 drv->idbit = 0;
3891 state = restore_u8 ();
3892 if (state & 2) {
3893 disabled |= 1 << num;
3894 if (changed_prefs.nr_floppies > num)
3895 changed_prefs.nr_floppies = num;
3896 changed_prefs.floppyslots[num].dfxtype = -1;
3897 } else {
3898 drv->motoroff = (state & 1) ? 0 : 1;
3899 drv->idbit = (state & 4) ? 1 : 0;
3900 switch (drv->drive_id)
3901 {
3902 case DRIVE_ID_35HD:
3903 dfxtype = DRV_35_HD;
3904 break;
3905 case DRIVE_ID_525SD:
3906 dfxtype = DRV_525_SD;
3907 break;
3908 default:
3909 dfxtype = DRV_35_DD;
3910 break;
3911 }
3912 currprefs.floppyslots[num].dfxtype = changed_prefs.floppyslots[num].dfxtype = dfxtype;
3913 }
3914 drv->dskchange = (state & 8) != 0;
3915 side = (state & 16) ? 1 : 0;
3916 drv->indexhackmode = 0;
3917 if (num == 0 && currprefs.floppyslots[num].dfxtype == 0)
3918 drv->indexhackmode = 1;
3919 drv->buffered_cyl = -1;
3920 drv->buffered_side = -1;
3921 drv->cyl = restore_u8 ();
3922 drv->dskready = restore_u8 () != 0;
3923 drv->drive_id_scnt = restore_u8 ();
3924 int mfmpos = restore_u32 ();
3925 drv->dskchange_time = 0;
3926 restore_u32 ();
3927 s = restore_path (SAVESTATE_PATH_FLOPPY);
3928 if (s && s[0])
3929 write_log (_T("-> '%s'\n"), s);
3930 _tcscpy (old, currprefs.floppyslots[num].df);
3931 _tcsncpy (changed_prefs.floppyslots[num].df, s, 255);
3932 xfree (s);
3933 int dskready_up_time = restore_u16 ();
3934 int dskready_down_time = restore_u16 ();
3935 newis = changed_prefs.floppyslots[num].df[0] ? 1 : 0;
3936 if (!(disabled & (1 << num))) {
3937 if (!newis && old[0]) {
3938 *currprefs.floppyslots[num].df = *changed_prefs.floppyslots[num].df = 0;
3939 drv->dskchange = false;
3940 } else if (newis) {
3941 drive_insert (floppy + num, &currprefs, num, changed_prefs.floppyslots[num].df, false, false);
3942 if (drive_empty (floppy + num)) {
3943 if (newis && old[0]) {
3944 _tcscpy (changed_prefs.floppyslots[num].df, old);
3945 drive_insert (floppy + num, &currprefs, num, changed_prefs.floppyslots[num].df, false, false);
3946 if (drive_empty (floppy + num))
3947 drv->dskchange = true;
3948 } else {
3949 drv->dskchange_time = -1;
3950 }
3951 }
3952 }
3953 }
3954 drv->mfmpos = mfmpos;
3955 drv->prevtracklen = drv->tracklen;
3956 drv->dskready_up_time = dskready_up_time;
3957 drv->dskready_down_time = dskready_down_time;
3958 reset_drive_gui (num);
3959 return src;
3960 }
3961
restore_disk2(int num,uae_u8 * src)3962 uae_u8 *restore_disk2 (int num,uae_u8 *src)
3963 {
3964 drive *drv = &floppy[num];
3965 uae_u32 m = restore_u32 ();
3966 if (m) {
3967 drv->floppybitcounter = restore_u16 ();
3968 drv->tracklen = restore_u32 ();
3969 drv->trackspeed = restore_u16 ();
3970 drv->skipoffset = restore_u32 ();
3971 drv->indexoffset = restore_u32 ();
3972 drv->buffered_cyl = drv->cyl;
3973 drv->buffered_side = side;
3974 for (int j = 0; j < (drv->tracklen + 15) / 16; j++) {
3975 drv->bigmfmbuf[j] = restore_u16 ();
3976 if (m & 2)
3977 drv->tracktiming[j] = restore_u16 ();
3978 }
3979 }
3980 return src;
3981 }
3982
save_disk(int num,int * len,uae_u8 * dstptr,bool usepath)3983 uae_u8 *save_disk (int num, int *len, uae_u8 *dstptr, bool usepath)
3984 {
3985 uae_u8 *dstbak,*dst;
3986 drive *drv = &floppy[num];
3987
3988 if (dstptr)
3989 dstbak = dst = dstptr;
3990 else
3991 dstbak = dst = xmalloc (uae_u8, 2 + 1 + 1 + 1 + 1 + 4 + 4 + 256);
3992 save_u32 (drv->drive_id); /* drive type ID */
3993 save_u8 ((drv->motoroff ? 0 : 1) | ((disabled & (1 << num)) ? 2 : 0) | (drv->idbit ? 4 : 0) | (drv->dskchange ? 8 : 0) | (side ? 16 : 0) | (drv->wrprot ? 32 : 0));
3994 save_u8 (drv->cyl); /* cylinder */
3995 save_u8 (drv->dskready); /* dskready */
3996 save_u8 (drv->drive_id_scnt); /* id mode position */
3997 save_u32 (drv->mfmpos); /* disk position */
3998 save_u32 (getadfcrc (drv)); /* CRC of disk image */
3999 save_path (usepath ? currprefs.floppyslots[num].df : _T(""), SAVESTATE_PATH_FLOPPY);/* image name */
4000 save_u16 (drv->dskready_up_time);
4001 save_u16 (drv->dskready_down_time);
4002 *len = dst - dstbak;
4003 return dstbak;
4004 }
4005
save_disk2(int num,int * len,uae_u8 * dstptr)4006 uae_u8 *save_disk2 (int num, int *len, uae_u8 *dstptr)
4007 {
4008 uae_u8 *dstbak,*dst;
4009 drive *drv = &floppy[num];
4010
4011 int m = 0;
4012 int size = 0;
4013 if (drv->motoroff == 0 && drv->buffered_side >= 0 && drv->tracklen > 0) {
4014 m = 1;
4015 if (drv->tracktiming[0])
4016 m |= 2;
4017 size += ((drv->tracklen + 15) * 2) / 8;
4018 }
4019 if (!m)
4020 return NULL;
4021
4022 if (dstptr)
4023 dstbak = dst = dstptr;
4024 else
4025 dstbak = dst = xmalloc (uae_u8, 2 + 4 + 2 + 4 + 4 + size);
4026
4027 save_u32 (m);
4028 save_u16 (drv->floppybitcounter);
4029 save_u32 (drv->tracklen);
4030 save_u16 (drv->trackspeed);
4031 save_u32 (drv->skipoffset);
4032 save_u32 (drv->indexoffset);
4033 for (int j = 0; j < (drv->tracklen + 15) / 16; j++) {
4034 save_u16 (drv->bigmfmbuf[j]);
4035 if (drv->tracktiming[0])
4036 save_u16 (drv->tracktiming[j]);
4037 }
4038
4039 *len = dst - dstbak;
4040 return dstbak;
4041 }
4042
4043 /* internal floppy controller variables */
4044
restore_floppy(uae_u8 * src)4045 uae_u8 *restore_floppy (uae_u8 *src)
4046 {
4047 word = restore_u16 ();
4048 bitoffset = restore_u8 ();
4049 dma_enable = restore_u8 ();
4050 disk_hpos = restore_u8 () & 0xff;
4051 dskdmaen = restore_u8 ();
4052 for (int i = 0; i < 3; i++) {
4053 fifo[i] = restore_u16 ();
4054 fifo_inuse[i] = restore_u8 ();
4055 if (dskdmaen == 0)
4056 fifo_inuse[i] = false;
4057 }
4058 fifo_filled = fifo_inuse[0] || fifo_inuse[1] || fifo_inuse[2];
4059 dsklength = restore_u16 ();
4060 return src;
4061 }
4062
save_floppy(int * len,uae_u8 * dstptr)4063 uae_u8 *save_floppy (int *len, uae_u8 *dstptr)
4064 {
4065 uae_u8 *dstbak, *dst;
4066
4067 if (dstptr)
4068 dstbak = dst = dstptr;
4069 else
4070 dstbak = dst = xmalloc (uae_u8, 100);
4071
4072 save_u16 (word); /* shift register */
4073 save_u8 (bitoffset); /* dma bit offset */
4074 save_u8 (dma_enable); /* disk sync found */
4075 save_u8 (disk_hpos & 0xff); /* next bit read position */
4076 save_u8 (dskdmaen); /* dma status */
4077 for (int i = 0; i < 3; i++) {
4078 save_u16 (fifo[i]);
4079 save_u8 (fifo_inuse[i]);
4080 }
4081 save_u16 (dsklength);
4082 *len = dst - dstbak;
4083 return dstbak;
4084 }
4085
4086 #endif /* SAVESTATE */
4087
4088 #define MAX_DISKENTRIES 4
disk_prevnext_name(TCHAR * imgp,int dir)4089 int disk_prevnext_name (TCHAR *imgp, int dir)
4090 {
4091 TCHAR img[MAX_DPATH], *ext, *p, *p2, *ps, *dst[MAX_DISKENTRIES];
4092 int num = -1;
4093 int cnt, i;
4094 TCHAR imgl[MAX_DPATH];
4095 int ret, gotone, wrapped;
4096 TCHAR *old;
4097
4098 old = my_strdup (imgp);
4099
4100 struct zfile *zf = zfile_fopen (imgp, _T("rb"), ZFD_NORMAL);
4101 if (zf) {
4102 _tcscpy (img, zfile_getname (zf));
4103 zfile_fclose (zf);
4104 zf = zfile_fopen (img, _T("rb"), ZFD_NORMAL);
4105 if (!zf) // oops, no directory support in this archive type
4106 _tcscpy (img, imgp);
4107 zfile_fclose (zf);
4108 } else {
4109 _tcscpy (img, imgp);
4110 }
4111
4112 wrapped = 0;
4113 retry:
4114 _tcscpy (imgl, img);
4115 for (i = 0; i < (int)_tcslen(imgl); ++i)
4116 imgl[i] = tolower (imgl[i]);
4117 gotone = 0;
4118 ret = 0;
4119 ps = imgl;
4120 cnt = 0;
4121 dst[cnt] = NULL;
4122 for (;;) {
4123 // disk x of y
4124 p = _tcsstr (ps, _T("(disk "));
4125 if (p && _istdigit (p[6])) {
4126 p2 = p - imgl + img;
4127 num = _tstoi (p + 6);
4128 dst[cnt++] = p2 + 6;
4129 if (cnt >= MAX_DISKENTRIES - 1)
4130 break;
4131 gotone = 1;
4132 ps = p + 6;
4133 continue;
4134 }
4135 if (gotone)
4136 break;
4137 p = _tcsstr (ps, _T("disk"));
4138 if (p && _istdigit (p[4])) {
4139 p2 = p - imgl + img;
4140 num = _tstoi (p + 4);
4141 dst[cnt++] = p2 + 4;
4142 if (cnt >= MAX_DISKENTRIES - 1)
4143 break;
4144 gotone = 1;
4145 ps = p + 4;
4146 continue;
4147 }
4148 if (gotone)
4149 break;
4150 ext = _tcsrchr (ps, '.');
4151 if (!ext || ext - ps < 4)
4152 break;
4153 TCHAR *ext2 = ext - imgl + img;
4154 // name_<non numeric character>x.ext
4155 if (ext[-3] == '_' && !_istdigit (ext[-2]) && _istdigit (ext[-1])) {
4156 num = _tstoi (ext - 1);
4157 dst[cnt++] = ext2 - 1;
4158 // name_x.ext, name-x.ext, name x.ext
4159 } else if ((ext[-2] == '_' || ext[-2] == '-' || ext[-2] == ' ') && _istdigit (ext[-1])) {
4160 num = _tstoi (ext - 1);
4161 dst[cnt++] = ext2 - 1;
4162 // name_a.ext, name-a.ext, name a .ext
4163 } else if ((ext[-2] == '_' || ext[-2] == '-' || ext[-2] == ' ') && ext[-1] >= 'a' && ext[-1] <= 'z') {
4164 num = ext[-1] - 'a' + 1;
4165 dst[cnt++] = ext2 - 1;
4166 // nameA.ext
4167 } else if (ext2[-2] >= 'a' && ext2[-2] <= 'z' && ext2[-1] >= 'A' && ext2[-1] <= 'Z') {
4168 num = ext[-1] - 'a' + 1;
4169 dst[cnt++] = ext2 - 1;
4170 // namex.ext
4171 } else if (!_istdigit (ext2[-2]) && _istdigit (ext[-1])) {
4172 num = ext[-1] - '0';
4173 dst[cnt++] = ext2 - 1;
4174 }
4175 break;
4176 }
4177 dst[cnt] = NULL;
4178 if (num <= 0 || num >= 19)
4179 goto end;
4180 num += dir;
4181 if (num > 9)
4182 goto end;
4183 if (num == 9)
4184 num = 1;
4185 else if (num == 0)
4186 num = 9;
4187 for (i = 0; i < cnt; i++) {
4188 if (!_istdigit (dst[i][0])) {
4189 int capital = dst[i][0] >= 'A' && dst[i][0] <= 'Z';
4190 dst[i][0] = (num - 1) + (capital ? 'A' : 'a');
4191 } else {
4192 dst[i][0] = num + '0';
4193 }
4194 }
4195 if (zfile_exists (img)) {
4196 ret = 1;
4197 goto end;
4198 }
4199 if (gotone) { // was (disk x but no match, perhaps there are extra tags..
4200 TCHAR *old2 = my_strdup (img);
4201 for (;;) {
4202 ext = _tcsrchr (img, '.');
4203 if (!ext)
4204 break;
4205 if (ext == img)
4206 break;
4207 if (ext[-1] != ']')
4208 break;
4209 TCHAR *t = _tcsrchr (img, '[');
4210 if (!t)
4211 break;
4212 t[0] = 0;
4213 if (zfile_exists (img)) {
4214 ret = 1;
4215 goto end;
4216 }
4217 }
4218 _tcscpy (img, old2);
4219 xfree (old2);
4220 }
4221 if (!wrapped) {
4222 for (i = 0; i < cnt; i++) {
4223 if (!_istdigit (dst[i][0]))
4224 dst[i][0] = dst[i][0] >= 'A' && dst[i][0] <= 'Z' ? 'A' : 'a';
4225 else
4226 dst[i][0] = '1';
4227 if (dir < 0)
4228 dst[i][0] += 8;
4229 }
4230 wrapped++;
4231 }
4232 if (zfile_exists (img)) {
4233 ret = -1;
4234 goto end;
4235 }
4236 if (dir < 0 && wrapped < 2)
4237 goto retry;
4238 _tcscpy (img, old);
4239
4240 end:
4241 _tcscpy (imgp, img);
4242 xfree (old);
4243 return ret;
4244 }
4245
disk_prevnext(int drive,int dir)4246 int disk_prevnext (int drive, int dir)
4247 {
4248 TCHAR img[MAX_DPATH];
4249
4250 _tcscpy (img, currprefs.floppyslots[drive].df);
4251
4252 if (!img[0])
4253 return 0;
4254 disk_prevnext_name (img, dir);
4255 _tcscpy (changed_prefs.floppyslots[drive].df, img);
4256 return 1;
4257 }
4258
4259 /// REMOVEME: nowhere used
4260 #if 0
4261 int getdebug(void)
4262 {
4263 return floppy[0].mfmpos;
4264 }
4265 #endif
4266