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