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