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