|
|
1.1.1.2 root 1: /*
1.1 root 2: * UAE - The Un*x Amiga Emulator
1.1.1.2 root 3: *
1.1 root 4: * Floppy disk emulation
5: *
1.1.1.11 root 6: * Copyright 1995 Hannu Rummukainen
7: * Copyright 1995-2001 Bernd Schmidt
8: * Copyright 2000, 2001 Toni Wilen
9: *
10: * High Density Drive Handling by Dr. Adil Temel (C) 2001 [[email protected]]
11: *
1.1 root 12: */
13:
1.1.1.2 root 14: #include <stdio.h>
15:
1.1 root 16: #include "sysconfig.h"
17: #include "sysdeps.h"
18:
19: #include "options.h"
1.1.1.12 root 20: #include "threaddep/thread.h"
1.1 root 21: #include "memory.h"
22: #include "events.h"
23: #include "custom.h"
24: #include "ersatz.h"
25: #include "disk.h"
26: #include "gui.h"
27: #include "zfile.h"
1.1.1.2 root 28: #include "autoconf.h"
29: #include "newcpu.h"
30: #include "xwin.h"
31: #include "osemu.h"
32: #include "execlib.h"
1.1.1.11 root 33: #include "savestate.h"
1.1.1.20! root 34: #include "crc32.h"
1.1.1.2 root 35:
1.1.1.20! root 36: /* support HD floppies */
! 37: #define FLOPPY_DRIVE_HD
1.1.1.7 root 38: /* writable track length with normal 2us bitcell/300RPM motor */
1.1.1.13 root 39: #define FLOPPY_WRITE_LEN (12650 / 2)
40: /* This works out to 341 */
41: #define FLOPPY_GAP_LEN (FLOPPY_WRITE_LEN - 11 * 544)
1.1.1.7 root 42: /* (cycles/bitcell) << 8, normal = ((2us/280ns)<<8) = ~1830 */
43: #define NORMAL_FLOPPY_SPEED 1830
44:
1.1.1.20! root 45: #ifdef FLOPPY_DRIVE_HD
! 46: #define DDHDMULT 2
! 47: #else
! 48: #define DDHDMULT 1
! 49: #endif
! 50:
1.1.1.7 root 51: static int floppy_speed = NORMAL_FLOPPY_SPEED;
52:
53: #undef DISK_DEBUG
1.1.1.11 root 54: #undef DEBUG_DRIVE_ID
1.1.1.7 root 55:
56: /* UAE-1ADF (ADF_EXT2)
57: * W reserved
58: * W number of tracks (default 2*80=160)
59: *
60: * W reserved
61: * W type, 0=normal AmigaDOS track, 1 = raw MFM
62: * L available space for track in bytes
63: * L track length in bits
64: */
1.1 root 65:
1.1.1.11 root 66: static int side, direction, writing;
1.1.1.12 root 67: static uae_u8 selected = 15, disabled;
1.1 root 68:
1.1.1.20! root 69: static uae_u8 writebuffer[544 * 22 * DDHDMULT];
1.1.1.7 root 70:
1.1.1.20! root 71: typedef enum { TRACK_AMIGADOS, TRACK_RAW, TRACK_RAW1, TRACK_PCDOS } image_tracktype;
1.1 root 72: typedef struct {
1.1.1.3 root 73: uae_u32 offs;
1.1.1.20! root 74: int bitlen, track;
1.1.1.7 root 75: unsigned int sync;
76: image_tracktype type;
1.1.1.20! root 77: uae_u16 len;
1.1 root 78: } trackid;
79:
1.1.1.2 root 80: #define MAX_TRACKS 328
81:
1.1.1.20! root 82: /* We have three kinds of Amiga floppy drives
! 83: * - internal A500/A2000 drive:
! 84: * ID is always DRIVE_ID_NONE (S.T.A.G expects this)
! 85: * - HD drive (A3000/A4000):
! 86: * ID is DRIVE_ID_35DD if DD floppy is inserted or drive is empty
! 87: * ID is DRIVE_ID_35HD if HD floppy is inserted
! 88: * - regular external drive:
! 89: * ID is always DRIVE_ID_35DD
! 90: */
! 91:
! 92: #define DRIVE_ID_NONE 0x00000000
! 93: #define DRIVE_ID_35DD 0xFFFFFFFF
1.1.1.11 root 94: #define DRIVE_ID_35HD 0xAAAAAAAA
1.1.1.20! root 95: #define DRIVE_ID_525SD 0x55555555 /* 40 track 5.25 drive , kickstart does not recognize this */
1.1.1.11 root 96:
1.1.1.7 root 97: typedef enum { ADF_NORMAL, ADF_EXT1, ADF_EXT2 } drive_filetype;
1.1 root 98: typedef struct {
1.1.1.20! root 99: drive_type type;
! 100: struct zfile *diskfile;
1.1 root 101: drive_filetype filetype;
1.1.1.2 root 102: trackid trackdata[MAX_TRACKS];
1.1.1.7 root 103: int buffered_cyl, buffered_side;
104: int cyl;
1.1 root 105: int motoroff;
1.1.1.7 root 106: int state;
1.1 root 107: int wrprot;
1.1.1.11 root 108: uae_u16 bigmfmbuf[0x8000];
1.1 root 109: int mfmpos;
1.1.1.7 root 110: int tracklen;
111: int trackspeed;
112: int dmalen;
113: int num_tracks, num_secs;
1.1.1.20! root 114: int hard_num_cyls;
1.1.1.3 root 115: int dskchange;
116: int dskchange_time;
1.1.1.10 root 117: int dskready;
118: int dskready_time;
1.1.1.11 root 119: int steplimit;
120: int ddhd; /* 1=DD 2=HD */
121: int drive_id_scnt; /* drive id shift counter */
1.1.1.20! root 122: int idbit;
1.1.1.11 root 123: unsigned long drive_id; /* drive id to be reported */
1.1.1.12 root 124: char newname[256]; /* storage space for new filename during eject delay */
1.1 root 125: } drive;
126:
1.1.1.11 root 127: static drive floppy[4];
128:
129: /* Keeps track of whether the Amiga program seems to be using the data coming
130: in from the disk; if this remains 0 for several seconds, we stop calling
131: disk_doupdate_read, even if the motor is still on. This is a rather large
132: performance win. This contains the number of frames since we last accessed
133: the disk. */
134: static int disk_data_used;
135:
136: #ifdef DEBUG_DRIVE_ID
1.1.1.20! root 137: static char *drive_id_name (drive *drv)
1.1.1.11 root 138: {
1.1.1.20! root 139: switch (drv->drive_id)
1.1.1.11 root 140: {
141: case DRIVE_ID_35HD : return "3.5HD";
142: case DRIVE_ID_525DD: return "5.25DD";
143: case DRIVE_ID_35DD : return "3.5DD";
144: }
1.1.1.18 root 145: return "UNKNOWN";
1.1.1.11 root 146: }
147: #endif
148:
1.1.1.18 root 149: /* Simulate exact behaviour of an A3000T 3.5 HD disk drive.
1.1.1.11 root 150: * The drive reports to be a 3.5 DD drive whenever there is no
151: * disk or a 3.5 DD disk is inserted. Only 3.5 HD drive id is reported
152: * when a real 3.5 HD disk is inserted. -Adil
153: */
1.1.1.20! root 154: static void drive_settype_id (drive *drv)
1.1.1.11 root 155: {
1.1.1.20! root 156: int t = drv->type;
! 157:
! 158: switch (t)
! 159: {
! 160: case DRV_35_HD:
! 161: #ifdef FLOPPY_DRIVE_HD
! 162: if (!drv->diskfile || drv->ddhd <= 1)
! 163: drv->drive_id = DRIVE_ID_35DD;
! 164: else
! 165: drv->drive_id = DRIVE_ID_35HD;
! 166: #else
1.1.1.11 root 167: drv->drive_id = DRIVE_ID_35DD;
1.1.1.20! root 168: #endif
! 169: break;
! 170: case DRV_35_DD_ESCOM:
! 171: case DRV_35_DD:
! 172: default:
! 173: drv->drive_id = DRIVE_ID_35DD;
! 174: break;
! 175: case DRV_525_SD:
! 176: drv->drive_id = DRIVE_ID_525SD;
! 177: break;
! 178: case DRV_NONE:
! 179: drv->drive_id = DRIVE_ID_NONE;
! 180: break;
1.1.1.11 root 181: }
182: #ifdef DEBUG_DRIVE_ID
1.1.1.20! root 183: write_log ("drive_settype_id: DF%d: set to %s\n", drv-floppy, drive_id_name (drv));
! 184: #endif
! 185: #ifdef DEBUG_DRIVE_ID
! 186: write_log ("drive_settype_id: DF%d: set to %s\n", drv-floppy, drive_id_name (drv));
1.1.1.11 root 187: #endif
188: }
1.1 root 189:
1.1.1.7 root 190: /* code for track display */
1.1.1.8 root 191: static void update_drive_gui (int num)
1.1.1.7 root 192: {
1.1.1.8 root 193: drive *drv = floppy + num;
194:
1.1.1.7 root 195: if (drv->state == gui_data.drive_motor[num]
196: && drv->cyl == gui_data.drive_track[num]
197: && ((writing && gui_data.drive_writing[num])
198: || (!writing && !gui_data.drive_writing[num]))) {
199: return;
200: }
201: gui_data.drive_motor[num] = drv->state;
202: gui_data.drive_track[num] = drv->cyl;
203: if (!gui_data.drive_writing[num])
204: gui_data.drive_writing[num] = writing;
1.1.1.8 root 205: gui_ledstate &= ~(2 << num);
206: if (drv->state)
207: gui_ledstate |= 2 << num;
1.1.1.7 root 208: gui_led (num + 1, gui_data.drive_motor[num]);
209: }
210:
1.1.1.20! root 211: static void drive_fill_bigbuf (drive *drv);
1.1 root 212:
1.1.1.20! root 213: static void drive_image_free (drive *drv)
1.1 root 214: {
1.1.1.20! root 215: drv->filetype = -1;
! 216: if (!drv->diskfile)
! 217: return;
! 218: zfile_fclose (drv->diskfile);
! 219: drv->diskfile = 0;
! 220: }
! 221:
! 222: struct zfile *DISK_validate_filename (const char *fname, int leave_open, int *wrprot)
! 223: {
! 224: struct zfile *f = zfile_open (fname, "r+b");
1.1.1.3 root 225: if (f) {
226: if (wrprot)
227: *wrprot = 0;
1.1 root 228: } else {
1.1.1.3 root 229: if (wrprot)
230: *wrprot = 1;
1.1.1.4 root 231: f = zfile_open (fname, "rb");
1.1 root 232: }
1.1.1.3 root 233: if (!leave_open)
1.1.1.20! root 234: zfile_fclose (f);
1.1.1.3 root 235: return f;
236: }
237:
1.1.1.20! root 238: static void track_reset (drive *drv)
! 239: {
! 240: drv->tracklen = FLOPPY_WRITE_LEN * 2 * 8;
! 241: drv->trackspeed = floppy_speed;
! 242: drv->buffered_side = -1;
! 243: memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
! 244: }
! 245:
! 246: static int read_header_ext2 (struct zfile *diskfile, trackid *trackdata, int *num_tracks, int *ddhd)
! 247: {
! 248: uae_u8 buffer[2 + 2 + 4 + 4];
! 249: int offs;
! 250: int i;
! 251:
! 252: zfile_fseek (diskfile, 0, SEEK_SET);
! 253: zfile_fread (buffer, 1, 8, diskfile);
! 254: if (strncmp ((char *)buffer, "UAE-1ADF", 8))
! 255: return 0;
! 256:
! 257: zfile_fread (buffer, 1, 4, diskfile);
! 258: *num_tracks = buffer[2] * 256 + buffer[3];
! 259: offs = 8 + 2 + 2 + *num_tracks * (2 + 2 + 4 + 4);
! 260:
! 261: for (i = 0; i < *num_tracks; i++) {
! 262: trackid *tid = trackdata + i;
! 263: zfile_fread (buffer, 2 + 2 + 4 + 4, 1, diskfile);
! 264: tid->type = buffer[2] * 256 + buffer[3];
! 265: tid->len = buffer[5] * 65536 + buffer[6] * 256 + buffer[7];
! 266: tid->bitlen = buffer[9] * 65536 + buffer[10] * 256 + buffer[11];
! 267: tid->offs = offs;
! 268: if (tid->len > 20000 && ddhd)
! 269: *ddhd = 2;
! 270: tid->track = i;
! 271: offs += tid->len;
! 272: }
! 273: return 1;
! 274: }
! 275:
! 276: static int drive_insert (drive *drv, int dnum, const char *fname)
1.1.1.3 root 277: {
1.1.1.7 root 278: unsigned char buffer[2 + 2 + 4 + 4];
279: trackid *tid;
1.1.1.20! root 280: int size;
1.1.1.3 root 281:
1.1.1.20! root 282: drive_image_free (drv);
1.1.1.3 root 283: drv->diskfile = DISK_validate_filename (fname, 1, &drv->wrprot);
1.1.1.20! root 284: drv->ddhd = 1;
! 285: drv->num_secs = 0;
! 286: drv->hard_num_cyls = drv->type == DRV_525_SD ? 40 : 80;
! 287:
1.1.1.6 root 288: if (drv->diskfile == 0) {
1.1.1.20! root 289: track_reset (drv);
1.1.1.3 root 290: return 0;
1.1.1.6 root 291: }
1.1.1.3 root 292: strncpy (currprefs.df[dnum], fname, 255);
293: currprefs.df[dnum][255] = 0;
294: strncpy (changed_prefs.df[dnum], fname, 255);
295: changed_prefs.df[dnum][255] = 0;
1.1.1.7 root 296: gui_filename (dnum, fname);
1.1.1.3 root 297:
1.1.1.20! root 298: memset (buffer, 0, sizeof (buffer));
! 299: size = 0;
! 300: if (drv->diskfile) {
! 301: zfile_fread (buffer, sizeof (char), 8, drv->diskfile);
! 302: zfile_fseek (drv->diskfile, 0, SEEK_END);
! 303: size = zfile_ftell (drv->diskfile);
! 304: zfile_fseek (drv->diskfile, 0, SEEK_SET);
! 305: }
! 306:
1.1.1.7 root 307: if (strncmp ((char *) buffer, "UAE-1ADF", 8) == 0) {
1.1.1.20! root 308: read_header_ext2 (drv->diskfile, drv->trackdata, &drv->num_tracks, &drv->ddhd);
1.1.1.7 root 309:
310: drv->filetype = ADF_EXT2;
311: drv->num_secs = 11;
1.1.1.20! root 312: if (drv->ddhd > 1)
! 313: drv->num_secs = 22;
1.1.1.7 root 314: } else if (strncmp ((char *) buffer, "UAE--ADF", 8) == 0) {
315: int offs = 160 * 4 + 8;
1.1 root 316: int i;
1.1.1.3 root 317:
318: drv->filetype = ADF_EXT1;
1.1.1.2 root 319: drv->num_tracks = 160;
320: drv->num_secs = 11;
1.1.1.3 root 321:
1.1.1.20! root 322: zfile_fseek (drv->diskfile, 8, SEEK_SET);
! 323:
1.1.1.7 root 324: drv->wrprot = 1; /* write to adf_ext1 not implemented */
325: for (i = 0; i < 160; i++) {
326: tid = &drv->trackdata[i];
1.1.1.20! root 327: zfile_fread (buffer, 4, 1, drv->diskfile);
1.1.1.7 root 328: tid->sync = buffer[0] * 256 + buffer[1];
329: tid->len = buffer[2] * 256 + buffer[3];
330: tid->offs = offs;
331: if (tid->sync == 0) {
332: tid->type = TRACK_AMIGADOS;
333: tid->bitlen = 0;
334: } else {
335: tid->type = TRACK_RAW1;
336: tid->bitlen = tid->len * 8;
337: }
338: offs += tid->len;
1.1 root 339: }
340: } else {
1.1.1.7 root 341: int i;
1.1.1.3 root 342: drv->filetype = ADF_NORMAL;
1.1.1.2 root 343:
344: /* High-density disk? */
1.1.1.20! root 345: if (size >= 160 * 22 * 512) {
! 346: drv->num_tracks = size / (512 * (drv->num_secs = 22));
! 347: drv->ddhd = 2;
! 348: } else
! 349: drv->num_tracks = size / (512 * (drv->num_secs = 11));
1.1.1.3 root 350:
1.1.1.2 root 351: if (drv->num_tracks > MAX_TRACKS)
1.1.1.3 root 352: write_log ("Your diskfile is too big!\n");
1.1.1.7 root 353: for (i = 0; i < drv->num_tracks; i++) {
354: tid = &drv->trackdata[i];
355: tid->type = TRACK_AMIGADOS;
356: tid->len = 512 * drv->num_secs;
357: tid->bitlen = 0;
358: tid->offs = i * 512 * drv->num_secs;
1.1 root 359: }
360: }
1.1.1.20! root 361: drive_settype_id (drv); /* Set DD or HD drive */
1.1.1.7 root 362: drv->buffered_side = 2; /* will force read */
1.1.1.6 root 363: drive_fill_bigbuf (drv);
1.1.1.3 root 364: return 1;
1.1 root 365: }
366:
1.1.1.7 root 367: static int drive_empty (drive * drv)
1.1.1.2 root 368: {
1.1.1.3 root 369: return drv->diskfile == 0;
1.1.1.2 root 370: }
371:
1.1.1.7 root 372: static void drive_step (drive * drv)
1.1 root 373: {
1.1.1.11 root 374: if (drv->steplimit)
375: return;
376: /* A1200's floppy drive needs at least 30 raster lines between steps
377: * but we'll use very small value for better compatibility with faster CPU emulation
378: * (stupid trackloaders with CPU delay loops)
379: */
380: drv->steplimit = 2;
1.1.1.12 root 381: if (!drive_empty (drv))
382: drv->dskchange = 0;
1.1 root 383: if (direction) {
1.1.1.7 root 384: if (drv->cyl)
385: drv->cyl--;
1.1.1.11 root 386: /* else
1.1.1.20! root 387: write_log ("program tried to step beyond track zero\n");
1.1.1.11 root 388: "no-click" programs does that
389: */
390: } else {
1.1.1.7 root 391: if (drv->cyl < 83)
392: drv->cyl++;
1.1.1.11 root 393: else
1.1.1.20! root 394: write_log ("program tried to step over track 83\n");
1.1 root 395: }
396:
1.1.1.7 root 397: #if 0 && defined DISK_DEBUG
398: write_log ("track %d\n", drv->cyl);
399: #endif
400: }
1.1 root 401:
1.1.1.7 root 402: static int drive_track0 (drive * drv)
1.1 root 403: {
1.1.1.3 root 404: return drv->cyl == 0;
1.1 root 405: }
406:
1.1.1.7 root 407: static int drive_writeprotected (drive * drv)
1.1 root 408: {
1.1.1.3 root 409: return drv->wrprot || drv->diskfile == NULL;
1.1 root 410: }
411:
1.1.1.7 root 412: static int drive_running (drive * drv)
1.1 root 413: {
1.1.1.3 root 414: return !drv->motoroff;
1.1 root 415: }
416:
1.1.1.7 root 417: static void drive_motor (drive * drv, int off)
1.1 root 418: {
1.1.1.12 root 419: /* A value of 5 works out to a guaranteed delay of 1/2 of a second
1.1.1.10 root 420: Higher values are dangerous, e.g. a value of 8 breaks the RSI
421: demo. */
1.1.1.11 root 422: if (drv->motoroff && !off) {
1.1.1.12 root 423: drv->dskready_time = 5;
1.1.1.11 root 424: disk_data_used = 0;
425: #ifdef DEBUG_DRIVE_ID
1.1.1.20! root 426: write_log ("drive_motor: Selected DF%d: reset id shift reg.\n", drv-floppy);
1.1.1.11 root 427: #endif
428: }
1.1.1.20! root 429: if (!drv->motoroff && off) {
! 430: drv->drive_id_scnt = 0; /* Reset id shift reg counter */
! 431: }
1.1 root 432: drv->motoroff = off;
1.1.1.10 root 433: if (drv->motoroff) {
434: drv->dskready = 0;
435: drv->dskready_time = 0;
436: }
1.1 root 437: }
438:
1.1.1.20! root 439: static void read_floppy_data (struct zfile *diskfile, trackid *ti, int offset, unsigned char *dst, int len)
1.1.1.7 root 440: {
1.1.1.20! root 441: zfile_fseek (diskfile, ti->offs + offset, SEEK_SET);
! 442: zfile_fread (dst, 1, len, diskfile);
! 443: }
1.1.1.7 root 444:
1.1.1.20! root 445: static void reset_drive (int i)
! 446: {
! 447: drive *drv = &floppy[i];
! 448: drive_image_free (drv);
! 449: drv->motoroff = 1;
! 450: disabled &= ~(1 << i);
! 451: if (currprefs.dfxtype[i] < 0)
! 452: disabled |= 1 << i;
! 453:
! 454: drv->dskchange_time = 0;
! 455: drv->buffered_cyl = -1;
! 456: drv->buffered_side = -1;
! 457: gui_led (i + 1, 0);
! 458: drive_settype_id (drv);
! 459: strcpy (currprefs.df[i], changed_prefs.df[i]);
! 460: drv->newname[0] = 0;
! 461: if (!drive_insert (drv, i, currprefs.df[i]))
! 462: disk_eject (i);
! 463: }
! 464:
! 465: static uae_u8 mfmencodetable[16] = {
! 466: 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15,
! 467: 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55
! 468: };
! 469:
! 470:
! 471: static uae_u16 dos_encode_byte (uae_u8 byte)
! 472: {
! 473: uae_u8 b2, b1;
! 474: uae_u16 word;
! 475:
! 476: b1 = byte;
! 477: b2 = b1 >> 4;
! 478: b1 &= 15;
! 479: word = mfmencodetable[b2] <<8 | mfmencodetable[b1];
! 480: return (word | ((word & (256 | 64)) ? 0 : 128));
! 481: }
! 482:
! 483: static uae_u16 *mfmcoder (uae_u8 *src, uae_u16 *dest, int len)
! 484: {
! 485: int i;
! 486:
! 487: for (i = 0; i < len; i++) {
! 488: *dest = dos_encode_byte (*src++);
! 489: *dest |= ((dest[-1] & 1)|| (*dest & 0x4000)) ? 0: 0x8000;
! 490: dest++;
! 491: }
! 492: return dest;
! 493: }
! 494:
! 495: static void decode_pcdos (drive *drv)
! 496: {
! 497: int i;
! 498: int tr = drv->cyl * 2 + side;
! 499: uae_u16 *dstmfmbuf, *mfm2;
! 500: uae_u8 secbuf[700];
! 501: uae_u16 crc16;
! 502: trackid *ti = drv->trackdata + tr;
! 503:
! 504: mfm2 = drv->bigmfmbuf;
! 505: *mfm2++ = 0x9254;
! 506: memset (secbuf, 0x4e, 80); // 94
! 507: memset (secbuf + 80, 0x00, 12); // 12
! 508: secbuf[92] = 0xc2;
! 509: secbuf[93] = 0xc2;
! 510: secbuf[94] = 0xc2;
! 511: secbuf[95] = 0xfc;
! 512: memset (secbuf + 96, 0x4e, 50); // 50
! 513: dstmfmbuf = mfmcoder (secbuf, mfm2, 146);
! 514: mfm2[92] = 0x5224;
! 515: mfm2[93] = 0x5224;
! 516: mfm2[94] = 0x5224;
! 517: for (i = 0; i < drv->num_secs; i++) {
! 518: mfm2 = dstmfmbuf;
! 519: memset (secbuf, 0x00, 12);
! 520: secbuf[12] = 0xa1;
! 521: secbuf[13] = 0xa1;
! 522: secbuf[14] = 0xa1;
! 523: secbuf[15] = 0xfe;
! 524: secbuf[16] = drv->cyl;
! 525: secbuf[17] = side;
! 526: secbuf[18] = 1 + i;
! 527: secbuf[19] = 2; // 128 << 2 = 512
! 528: crc16 = get_crc16 (secbuf + 12, 3 + 1 + 4);
! 529: secbuf[20] = crc16 >> 8;
! 530: secbuf[21] = crc16 & 0xff;
! 531: memset (secbuf + 22, 0x4e, 22);
! 532: memset (secbuf + 44, 0x00, 12);
! 533: secbuf[56] = 0xa1;
! 534: secbuf[57] = 0xa1;
! 535: secbuf[58] = 0xa1;
! 536: secbuf[59] = 0xfb;
! 537: read_floppy_data (drv->diskfile, ti, i * 512, &secbuf[60], 512);
! 538: crc16 = get_crc16 (secbuf + 56, 3 + 1 + 512);
! 539: secbuf[60 + 512] = crc16 >> 8;
! 540: secbuf[61 + 512] = crc16 & 0xff;
! 541: memset (secbuf + 512 + 62, 0x4e, 76 / drv->ddhd);
! 542: dstmfmbuf = mfmcoder (secbuf, mfm2, 60 + 512 + 2 + 76 / drv->ddhd);
! 543: mfm2[12] = 0x4489;
! 544: mfm2[13] = 0x4489;
! 545: mfm2[14] = 0x4489;
! 546: mfm2[56] = 0x4489;
! 547: mfm2[57] = 0x4489;
! 548: mfm2[58] = 0x4489;
! 549: }
! 550: for (i = 0; i < 200; i++)
! 551: *dstmfmbuf++ = 0x9254;
! 552: drv->tracklen = (dstmfmbuf - drv->bigmfmbuf) * 16;
1.1.1.7 root 553: }
554:
555: /* Megalomania does not like zero MFM words... */
556: static void mfmcode (uae_u16 * mfm, int words)
557: {
1.1.1.8 root 558: uae_u32 lastword = 0;
1.1.1.7 root 559:
560: while (words--) {
1.1.1.8 root 561: uae_u32 v = *mfm;
562: uae_u32 lv = (lastword << 16) | v;
563: uae_u32 nlv = 0x55555555 & ~lv;
564: uae_u32 mfmbits = (nlv << 1) & (nlv >> 1);
565:
566: *mfm++ = v | mfmbits;
567: lastword = v;
1.1.1.7 root 568: }
569: }
570:
1.1.1.20! root 571: static void decode_amigados (drive *drv)
! 572: {
! 573: /* Normal AmigaDOS format track */
! 574: int tr = drv->cyl * 2 + side;
! 575: int sec;
! 576: int dstmfmoffset = 0;
! 577: uae_u16 *dstmfmbuf = drv->bigmfmbuf;
! 578: int len = drv->num_secs * 544 + FLOPPY_GAP_LEN;
! 579: trackid *ti = drv->trackdata + tr;
! 580:
! 581: memset (dstmfmbuf, 0xaa, len * 2);
! 582: dstmfmoffset += FLOPPY_GAP_LEN;
! 583: drv->tracklen = len * 2 * 8;
! 584:
! 585: for (sec = 0; sec < drv->num_secs; sec++) {
! 586: uae_u8 secbuf[544];
! 587: uae_u16 mfmbuf[544];
! 588: int i;
! 589: uae_u32 deven, dodd;
! 590: uae_u32 hck = 0, dck = 0;
! 591:
! 592: secbuf[0] = secbuf[1] = 0x00;
! 593: secbuf[2] = secbuf[3] = 0xa1;
! 594: secbuf[4] = 0xff;
! 595: secbuf[5] = tr;
! 596: secbuf[6] = sec;
! 597: secbuf[7] = drv->num_secs - sec;
! 598:
! 599: for (i = 8; i < 24; i++)
! 600: secbuf[i] = 0;
! 601:
! 602: read_floppy_data (drv->diskfile, ti, sec * 512, &secbuf[32], 512);
! 603:
! 604: mfmbuf[0] = mfmbuf[1] = 0xaaaa;
! 605: mfmbuf[2] = mfmbuf[3] = 0x4489;
! 606:
! 607: deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
! 608: | (secbuf[6] << 8) | (secbuf[7]));
! 609: dodd = deven >> 1;
! 610: deven &= 0x55555555;
! 611: dodd &= 0x55555555;
! 612:
! 613: mfmbuf[4] = dodd >> 16;
! 614: mfmbuf[5] = dodd;
! 615: mfmbuf[6] = deven >> 16;
! 616: mfmbuf[7] = deven;
! 617:
! 618: for (i = 8; i < 48; i++)
! 619: mfmbuf[i] = 0xaaaa;
! 620: for (i = 0; i < 512; i += 4) {
! 621: deven = ((secbuf[i + 32] << 24) | (secbuf[i + 33] << 16)
! 622: | (secbuf[i + 34] << 8) | (secbuf[i + 35]));
! 623: dodd = deven >> 1;
! 624: deven &= 0x55555555;
! 625: dodd &= 0x55555555;
! 626: mfmbuf[(i >> 1) + 32] = dodd >> 16;
! 627: mfmbuf[(i >> 1) + 33] = dodd;
! 628: mfmbuf[(i >> 1) + 256 + 32] = deven >> 16;
! 629: mfmbuf[(i >> 1) + 256 + 33] = deven;
! 630: }
! 631:
! 632: for (i = 4; i < 24; i += 2)
! 633: hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
! 634:
! 635: deven = dodd = hck;
! 636: dodd >>= 1;
! 637: mfmbuf[24] = dodd >> 16;
! 638: mfmbuf[25] = dodd;
! 639: mfmbuf[26] = deven >> 16;
! 640: mfmbuf[27] = deven;
! 641:
! 642: for (i = 32; i < 544; i += 2)
! 643: dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
! 644:
! 645: deven = dodd = dck;
! 646: dodd >>= 1;
! 647: mfmbuf[28] = dodd >> 16;
! 648: mfmbuf[29] = dodd;
! 649: mfmbuf[30] = deven >> 16;
! 650: mfmbuf[31] = deven;
! 651: mfmcode (mfmbuf + 4, 544 - 4);
! 652:
! 653: for (i = 0; i < 544; i++) {
! 654: dstmfmbuf[dstmfmoffset % len] = mfmbuf[i];
! 655: dstmfmoffset++;
! 656: }
! 657: }
! 658: #ifdef DISK_DEBUG
! 659: write_log ("amigados read track %d\n", tr);
! 660: #endif
! 661: }
! 662:
1.1.1.7 root 663: static void drive_fill_bigbuf (drive * drv)
1.1 root 664: {
1.1.1.7 root 665: int tr = drv->cyl * 2 + side;
666: trackid *ti = drv->trackdata + tr;
1.1.1.3 root 667:
1.1.1.7 root 668: if (!drv->diskfile || tr >= drv->num_tracks) {
1.1.1.11 root 669: drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 2 * 8;
1.1.1.7 root 670: drv->trackspeed = floppy_speed;
1.1.1.11 root 671: memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
1.1.1.2 root 672: return;
673: }
1.1.1.3 root 674: if (drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
675: return;
676:
1.1.1.20! root 677: if (ti->type == TRACK_PCDOS) {
! 678: decode_pcdos (drv);
1.1.1.7 root 679:
1.1.1.20! root 680: } else if (ti->type == TRACK_AMIGADOS) {
! 681: decode_amigados (drv);
1.1 root 682: } else {
683: int i;
1.1.1.7 root 684: int base_offset = ti->type == TRACK_RAW ? 0 : 1;
685: drv->tracklen = ti->bitlen + 16 * base_offset;
686: drv->bigmfmbuf[0] = ti->sync;
1.1.1.20! root 687: read_floppy_data (drv->diskfile, ti, 0, (unsigned char *) (drv->bigmfmbuf + base_offset), (ti->bitlen + 7) / 8);
1.1.1.10 root 688: for (i = base_offset; i < (drv->tracklen + 15) / 16; i++) {
1.1.1.7 root 689: uae_u16 *mfm = drv->bigmfmbuf + i;
690: uae_u8 *data = (uae_u8 *) mfm;
691: *mfm = 256 * *data + *(data + 1);
1.1 root 692: }
1.1.1.7 root 693: #if 0 && defined DISK_DEBUG
694: write_log ("rawtrack %d\n", tr);
695: #endif
1.1 root 696: }
1.1.1.3 root 697: drv->buffered_side = side;
698: drv->buffered_cyl = drv->cyl;
1.1.1.7 root 699: drv->trackspeed = floppy_speed * drv->tracklen / (2 * 8 * FLOPPY_WRITE_LEN);
1.1 root 700: }
701:
1.1.1.7 root 702: /* Update ADF_EXT2 track header */
703: static void diskfile_update (drive * drv, int len, uae_u8 type)
1.1 root 704: {
1.1.1.7 root 705: trackid *ti;
706: int track;
707: uae_u8 buf[2 + 2 + 4 + 4], *zerobuf;
1.1.1.3 root 708:
1.1.1.7 root 709: if (drv->filetype != ADF_EXT2)
710: return;
1.1.1.6 root 711:
1.1.1.7 root 712: track = drv->cyl * 2 + side;
713: ti = &drv->trackdata[track];
714: ti->bitlen = len;
1.1.1.20! root 715: zfile_fseek (drv->diskfile, 8 + 4 + (2 + 2 + 4 + 4) * track, SEEK_SET);
1.1.1.7 root 716: memset (buf, 0, sizeof buf);
717: ti->type = type;
718: buf[3] = ti->type;
719: do_put_mem_long ((uae_u32 *) (buf + 4), ti->len);
720: do_put_mem_long ((uae_u32 *) (buf + 8), ti->bitlen);
1.1.1.20! root 721: zfile_fwrite (buf, sizeof (buf), 1, drv->diskfile);
1.1.1.7 root 722: if (ti->len > (len + 7) / 8) {
723: zerobuf = malloc (ti->len);
724: memset (zerobuf, 0, ti->len);
1.1.1.20! root 725: zfile_fseek (drv->diskfile, ti->offs, SEEK_SET);
! 726: zfile_fwrite (zerobuf, 1, ti->len, drv->diskfile);
1.1.1.7 root 727: free (zerobuf);
728: }
729: #ifdef DISK_DEBUG
730: write_log ("track %d, raw track length %d written (total size %d)\n", track, (ti->bitlen + 7) / 8, ti->len);
731: #endif
1.1 root 732: }
733:
734: #define MFMMASK 0x55555555
1.1.1.7 root 735: static uae_u32 getmfmlong (uae_u16 * mbuf)
1.1 root 736: {
737: return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK;
738: }
739:
1.1.1.7 root 740: static int drive_write_adf_amigados (drive * drv)
1.1 root 741: {
742: int i, secwritten = 0;
1.1.1.11 root 743: int fwlen = FLOPPY_WRITE_LEN * drv->ddhd;
744: int length = 2 * fwlen;
745: int drvsec= drv->num_secs;
1.1.1.3 root 746: uae_u32 odd, even, chksum, id, dlong;
1.1.1.7 root 747: uae_u8 *secdata;
1.1.1.3 root 748: uae_u8 secbuf[544];
1.1.1.7 root 749: uae_u16 *mbuf = drv->bigmfmbuf;
1.1.1.3 root 750: uae_u16 *mend = mbuf + length;
1.1.1.11 root 751: char sectable[22];
1.1.1.7 root 752: memset (sectable, 0, sizeof (sectable));
1.1.1.11 root 753: memcpy (mbuf + fwlen, mbuf, fwlen * sizeof (uae_u16));
1.1 root 754: mend -= (4 + 16 + 8 + 512);
1.1.1.11 root 755: while (secwritten < drvsec) {
1.1 root 756: int trackoffs;
1.1.1.3 root 757:
1.1 root 758: do {
759: while (*mbuf++ != 0x4489) {
1.1.1.4 root 760: if (mbuf >= mend)
1.1.1.7 root 761: return 1;
1.1 root 762: }
763: } while (*mbuf++ != 0x4489);
1.1.1.3 root 764:
1.1.1.4 root 765: odd = getmfmlong (mbuf);
766: even = getmfmlong (mbuf + 2);
1.1.1.3 root 767: mbuf += 4;
1.1 root 768: id = (odd << 1) | even;
1.1.1.3 root 769:
1.1 root 770: trackoffs = (id & 0xff00) >> 8;
1.1.1.11 root 771: if (trackoffs + 1 > drvsec) {
1.1.1.7 root 772: if (drv->filetype == ADF_EXT2)
773: return 2;
1.1.1.5 root 774: write_log ("Disk write: weird sector number %d\n", trackoffs);
1.1 root 775: continue;
776: }
777: chksum = odd ^ even;
1.1.1.4 root 778: for (i = 0; i < 4; i++) {
1.1.1.7 root 779: odd = getmfmlong (mbuf);
780: even = getmfmlong (mbuf + 8);
1.1 root 781: mbuf += 2;
1.1.1.3 root 782:
1.1 root 783: dlong = (odd << 1) | even;
1.1.1.7 root 784: if (dlong) {
785: if (drv->filetype == ADF_EXT2)
786: return 6;
1.1.1.4 root 787: secwritten = -200;
1.1.1.7 root 788: }
1.1 root 789: chksum ^= odd ^ even;
1.1.1.7 root 790: } /* could check here if the label is nonstandard */
1.1 root 791: mbuf += 8;
1.1.1.7 root 792: odd = getmfmlong (mbuf);
793: even = getmfmlong (mbuf + 2);
794: mbuf += 4;
795: if (((odd << 1) | even) != chksum || ((id & 0x00ff0000) >> 16) != drv->cyl * 2 + side) {
796: if (drv->filetype == ADF_EXT2)
797: return 3;
798: write_log ("Disk write: checksum error on sector %d header\n", trackoffs);
1.1 root 799: continue;
800: }
1.1.1.7 root 801: odd = getmfmlong (mbuf);
802: even = getmfmlong (mbuf + 2);
803: mbuf += 4;
1.1 root 804: chksum = (odd << 1) | even;
805: secdata = secbuf + 32;
1.1.1.7 root 806: for (i = 0; i < 128; i++) {
807: odd = getmfmlong (mbuf);
808: even = getmfmlong (mbuf + 256);
809: mbuf += 2;
1.1 root 810: dlong = (odd << 1) | even;
1.1.1.7 root 811: *secdata++ = dlong >> 24;
812: *secdata++ = dlong >> 16;
813: *secdata++ = dlong >> 8;
814: *secdata++ = dlong;
1.1 root 815: chksum ^= odd ^ even;
816: }
817: mbuf += 256;
818: if (chksum) {
1.1.1.7 root 819: if (drv->filetype == ADF_EXT2)
820: return 4;
821: write_log ("Disk write: sector %d, data checksum error\n", trackoffs);
1.1 root 822: continue;
823: }
1.1.1.7 root 824: sectable[trackoffs] = 1;
1.1 root 825: secwritten++;
1.1.1.7 root 826: memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
1.1 root 827: }
1.1.1.7 root 828: if (drv->filetype == ADF_EXT2 && (secwritten == 0 || secwritten < 0))
829: return 5;
1.1.1.3 root 830: if (secwritten == 0)
831: write_log ("Disk write in unsupported format\n");
1.1 root 832: if (secwritten < 0)
1.1.1.3 root 833: write_log ("Disk write: sector labels ignored\n");
1.1.1.7 root 834:
1.1.1.11 root 835: diskfile_update (drv, drvsec * 512 * 8, TRACK_AMIGADOS);
836: for (i = 0; i < drvsec; i++) {
1.1.1.20! root 837: zfile_fseek (drv->diskfile, drv->trackdata[drv->cyl * 2 + side].offs + i * 512, SEEK_SET);
! 838: zfile_fwrite (writebuffer + i * 512, sizeof (uae_u8), 512, drv->diskfile);
1.1.1.7 root 839: }
840:
841: return 0;
1.1 root 842: }
843:
1.1.1.7 root 844: /* write raw track to disk file */
845: static int drive_write_ext2 (drive * drv)
846: {
847: trackid *ti;
848: int len, track, i;
1.1 root 849:
1.1.1.7 root 850: track = drv->cyl * 2 + side;
851: ti = &drv->trackdata[track];
852: len = (drv->tracklen + 7) / 8;
853: if (len > ti->len) {
854: write_log ("disk raw write: image file's track %d is too small (%d < %d)!\n", track, ti->len, len);
855: return 0;
856: }
857: diskfile_update (drv, drv->tracklen, TRACK_RAW);
858: for (i = 0; i < drv->trackdata[track].len / 2; i++) {
859: uae_u16 *mfm = drv->bigmfmbuf + i;
860: uae_u8 *data = (uae_u8 *) mfm;
861: *mfm = 256 * *data + *(data + 1);
862: }
1.1.1.20! root 863: zfile_fseek (drv->diskfile, ti->offs, SEEK_SET);
! 864: zfile_fwrite (drv->bigmfmbuf, 1, len, drv->diskfile);
1.1.1.7 root 865: return 1;
866: }
867:
868: static void drive_write_data (drive * drv)
1.1 root 869: {
1.1.1.7 root 870: int ret;
871: if (drive_writeprotected (drv))
872: return;
873: switch (drv->filetype) {
874: case ADF_NORMAL:
875: drive_write_adf_amigados (drv);
876: break;
877: case ADF_EXT1:
878: write_log ("writing to ADF_EXT1 not supported\n");
879: return;
880: case ADF_EXT2:
881: ret = drive_write_adf_amigados (drv);
882: if (ret) {
1.1.1.20! root 883: /*write_log ("not an amigados track (error %d), writing as raw track\n", ret); */
1.1.1.7 root 884: drive_write_ext2 (drv);
885: }
886: break;
887: }
888: drv->buffered_side = 2; /* will force read */
889: }
890:
891: static void drive_eject (drive * drv)
892: {
1.1.1.20! root 893: drive_image_free (drv);
1.1.1.12 root 894: drv->dskchange = 1;
1.1.1.20! root 895: drv->ddhd = 1;
! 896: drv->dskchange_time = 0;
! 897: drv->dskready = 0;
! 898: drv->dskready_time = 0;
! 899: drive_settype_id (drv); /* Back to 35 DD */
1.1.1.12 root 900: #ifdef DISK_DEBUG
901: write_log ("eject drive %d\n", drv - &floppy[0]);
902: #endif
1.1 root 903: }
904:
1.1.1.3 root 905: /* We use this function if we have no Kickstart ROM.
1.1 root 906: * No error checking - we trust our luck. */
1.1.1.3 root 907: void DISK_ersatz_read (int tr, int sec, uaecptr dest)
1.1 root 908: {
1.1.1.7 root 909: uae_u8 *dptr = get_real_address (dest);
1.1.1.20! root 910: zfile_fseek (floppy[0].diskfile, floppy[0].trackdata[tr].offs + sec * 512, SEEK_SET);
! 911: zfile_fread (dptr, 1, 512, floppy[0].diskfile);
1.1 root 912: }
913:
1.1.1.4 root 914: void disk_eject (int num)
1.1 root 915: {
1.1.1.7 root 916: gui_filename (num, "");
917: drive_eject (floppy + num);
1.1.1.3 root 918: *currprefs.df[num] = *changed_prefs.df[num] = 0;
1.1.1.12 root 919: floppy[num].newname[0] = 0;
1.1 root 920: }
921:
1.1.1.4 root 922: void disk_insert (int num, const char *name)
1.1 root 923: {
1.1.1.12 root 924: drive *drv = floppy + num;
1.1.1.20! root 925:
! 926: if (!strcmp (currprefs.df[num], name))
! 927: return;
! 928: strcpy (drv->newname, name);
! 929: strcpy (currprefs.df[num], name);
! 930:
1.1.1.12 root 931: if (name[0] == 0) {
932: disk_eject (num);
1.1.1.20! root 933: } else if (!drive_empty (drv) || drv->dskchange_time > 0) {
1.1.1.12 root 934: drive_eject (drv);
1.1.1.20! root 935: /* set dskchange_time, disk_insert () will be
! 936: * called from DISK_check_change () after 1 second delay
1.1.1.12 root 937: * this makes sure that all programs detect disk change correctly
938: */
939: drv->dskchange_time = 10; /* 1 second disk change delay */
940: } else {
1.1.1.20! root 941: drv->dskchange_time = 1;
1.1.1.12 root 942: }
1.1 root 943: }
944:
1.1.1.3 root 945: void DISK_check_change (void)
946: {
947: int i;
948:
949: for (i = 0; i < 4; i++) {
1.1.1.12 root 950: drive *drv = floppy + i;
1.1.1.14 root 951: gui_lock ();
1.1.1.20! root 952: if (currprefs.dfxtype[i] != changed_prefs.dfxtype[i]) {
! 953: drv->type = currprefs.dfxtype[i] = changed_prefs.dfxtype[i];
! 954: reset_drive (i);
1.1.1.12 root 955: }
1.1.1.20! root 956: if (drv->dskchange_time == 0 && strcmp (currprefs.df[i], changed_prefs.df[i]))
! 957: disk_insert (i, changed_prefs.df[i]);
1.1.1.14 root 958: gui_unlock ();
1.1.1.12 root 959: /* emulate drive motor turn on time */
1.1.1.20! root 960: if (drv->dskready_time && !drive_empty (drv)) {
1.1.1.12 root 961: drv->dskready_time--;
962: if (drv->dskready_time == 0)
963: drv->dskready = 1;
964: }
965: /* delay until new disk image is inserted */
966: if (drv->dskchange_time) {
967: drv->dskchange_time--;
968: if (drv->dskchange_time == 0) {
969: drive_insert (drv, i, drv->newname);
970: #ifdef DISK_DEBUG
971: write_log ("delayed insert, drive %d, image '%s'\n", i, drv->newname);
972: #endif
973: drv->newname[0] = 0;
1.1.1.3 root 974: }
975: }
976: }
977: }
978:
1.1.1.4 root 979: int disk_empty (int num)
1.1 root 980: {
1.1.1.4 root 981: return drive_empty (floppy + num);
1.1 root 982: }
983:
1.1.1.11 root 984: static int step;
1.1.1.10 root 985:
1.1.1.4 root 986: void DISK_select (uae_u8 data)
1.1 root 987: {
1.1.1.11 root 988: int step_pulse, lastselected;
1.1 root 989: int dr;
1.1.1.11 root 990: static uae_u8 prevdata;
1.1.1.3 root 991:
1.1.1.10 root 992: lastselected = selected;
1.1 root 993: selected = (data >> 3) & 15;
1.1.1.12 root 994: selected |= disabled;
995: if (selected != lastselected)
996: disk_data_used = 1;
1.1.1.3 root 997: side = 1 - ((data >> 2) & 1);
998:
1.1 root 999: direction = (data >> 1) & 1;
1000: step_pulse = data & 1;
1001: if (step != step_pulse) {
1002: step = step_pulse;
1.1.1.11 root 1003: if (step) {
1.1.1.7 root 1004: for (dr = 0; dr < 4; dr++) {
1.1.1.20! root 1005: if (!((selected | disabled) & (1 << dr))) {
1.1.1.4 root 1006: drive_step (floppy + dr);
1.1 root 1007: }
1008: }
1009: }
1010: }
1.1.1.20! root 1011: if (!savestate_state) {
! 1012: for (dr = 0; dr < 4; dr++) {
! 1013: drive *drv = floppy + dr;
! 1014: /* motor on/off workings tested with small assembler code on real Amiga 1200. */
! 1015: /* motor/id flipflop is set only when drive select goes from high to low */
! 1016: if (!(selected & (1 << dr)) && (lastselected & (1 << dr)) ) {
! 1017: drv->drive_id_scnt++;
! 1018: drv->drive_id_scnt &= 31;
! 1019: drv->idbit = (drv->drive_id & (1L << (31 - drv->drive_id_scnt))) ? 1 : 0;
! 1020: if (!(disabled & (1 << dr))) {
! 1021: if ((prevdata & 0x80) == 0 || (data & 0x80) == 0) {
! 1022: /* motor off: if motor bit = 0 in prevdata or data -> turn motor on */
! 1023: drive_motor (drv, 0);
! 1024: } else if (prevdata & 0x80) {
! 1025: /* motor on: if motor bit = 1 in prevdata only (motor flag state in data has no effect)
! 1026: -> turn motor off */
! 1027: drive_motor (drv, 1);
! 1028: }
! 1029: }
1.1.1.11 root 1030: }
1.1 root 1031: }
1032: }
1033: for (dr = 0; dr < 4; dr++) {
1.1.1.7 root 1034: floppy[dr].state = (!(selected & (1 << dr))) | !floppy[dr].motoroff;
1.1.1.8 root 1035: update_drive_gui (dr);
1.1 root 1036: }
1.1.1.11 root 1037: prevdata = data;
1.1 root 1038: }
1039:
1.1.1.4 root 1040: uae_u8 DISK_status (void)
1.1 root 1041: {
1.1.1.3 root 1042: uae_u8 st = 0x3c;
1.1 root 1043: int dr;
1.1.1.3 root 1044:
1.1.1.7 root 1045: for (dr = 0; dr < 4; dr++) {
1.1.1.3 root 1046: drive *drv = floppy + dr;
1.1.1.20! root 1047: if (!((selected | disabled) & (1 << dr))) {
1.1.1.7 root 1048: if (drive_running (drv)) {
1.1.1.11 root 1049: if (drv->dskready)
1.1.1.7 root 1050: st &= ~0x20;
1.1.1.12 root 1051: } else {
1.1.1.11 root 1052: /* report drive ID */
1.1.1.20! root 1053: if (drv->idbit && currprefs.dfxtype[dr] != DRV_35_DD_ESCOM)
1.1.1.11 root 1054: st &= ~0x20;
1.1.1.18 root 1055: #ifdef DEBUG_DRIVE_ID
1.1.1.20! root 1056: write_log ("DISK_status: sel %d id %s [0x%08lx, bit #%02d: %d]\n",
! 1057: dr, drive_id_name (drv), drv->drive_id << drv->drive_id_scnt, 31 - drv->drive_id_scnt, st & 0x20 ? 1:0);
1.1.1.12 root 1058: #endif
1.1 root 1059: }
1.1.1.12 root 1060: if (drive_track0 (drv))
1.1.1.7 root 1061: st &= ~0x10;
1.1.1.12 root 1062: if (drive_writeprotected (drv))
1.1.1.7 root 1063: st &= ~8;
1.1.1.12 root 1064: if (drv->dskchange)
1065: st &= ~4;
1.1.1.20! root 1066: } else if (!(selected & (1 << dr))) {
! 1067: if (drv->idbit)
! 1068: st &= ~0x20;
1.1.1.18 root 1069: }
1.1 root 1070: }
1071: return st;
1072: }
1073:
1.1.1.7 root 1074: #define MAX_DISK_WORDS_PER_LINE 50 /* depends on floppy_speed */
1075:
1076: #define DISK_INDEXSYNC 1
1077: #define DISK_WORDSYNC 2
1078:
1079: static uae_u16 dskbytr_tab[MAX_DISK_WORDS_PER_LINE * 2 + 1];
1080: static uae_u8 dskbytr_cycle[MAX_DISK_WORDS_PER_LINE * 2 + 1];
1.1.1.11 root 1081: static short wordsync_cycle[MAX_DISK_WORDS_PER_LINE * 2 + 1];
1.1.1.7 root 1082: static uae_u32 dma_tab[MAX_DISK_WORDS_PER_LINE + 1];
1083: static uae_u8 disk_sync[MAXHPOS];
1084: static int disk_sync_cycle;
1085: static int dskdmaen, dsklength;
1086: static uae_u16 dsksync;
1087: static uae_u32 dskpt;
1088:
1089: static void disk_dmafinished (void)
1090: {
1091: INTREQ (0x8002);
1.1.1.15 root 1092: dskdmaen = 0; /* ??? */
1.1.1.11 root 1093: #ifdef DISK_DEBUG
1.1.1.20! root 1094: write_log ("disk dma finished %08.8X\n", dskpt);
1.1.1.11 root 1095: #endif
1.1.1.18 root 1096: }
1.1.1.7 root 1097:
1098: static void disk_events (int last)
1099: {
1100: eventtab[ev_disk].active = 0;
1.1.1.11 root 1101: for (disk_sync_cycle = last; disk_sync_cycle < maxhpos; disk_sync_cycle++) {
1.1.1.7 root 1102: if (disk_sync[disk_sync_cycle]) {
1.1.1.10 root 1103: eventtab[ev_disk].oldcycles = get_cycles ();
1104: eventtab[ev_disk].evtime = get_cycles () + (disk_sync_cycle - last) * CYCLE_UNIT;
1.1.1.7 root 1105: eventtab[ev_disk].active = 1;
1106: events_schedule ();
1107: return;
1.1 root 1108: }
1109: }
1110: }
1111:
1.1.1.7 root 1112: extern void cia_diskindex (void);
1.1.1.3 root 1113:
1.1.1.7 root 1114: void DISK_handler (void)
1115: {
1116: eventtab[ev_disk].active = 0;
1.1.1.11 root 1117: if (disk_sync[disk_sync_cycle] & DISK_WORDSYNC)
1.1.1.7 root 1118: INTREQ (0x9000);
1.1.1.11 root 1119: if (disk_sync[disk_sync_cycle] & DISK_INDEXSYNC)
1.1.1.7 root 1120: cia_diskindex ();
1121: disk_sync[disk_sync_cycle] = 0;
1122: disk_events (disk_sync_cycle);
1123: }
1.1.1.3 root 1124:
1.1.1.12 root 1125: static int dma_enable, bitoffset;
1126: static uae_u32 word;
1.1 root 1127:
1.1.1.7 root 1128: /* Always carried through to the next line. */
1129: static int disk_hpos;
1.1.1.2 root 1130:
1.1.1.7 root 1131: /* emulate disk write dma for full horizontal line */
1132: static void disk_doupdate_write (drive * drv)
1133: {
1134: int hpos = disk_hpos;
1.1.1.11 root 1135: while (hpos < (maxhpos << 8)) {
1.1.1.7 root 1136: drv->mfmpos++;
1137: drv->mfmpos %= drv->tracklen;
1138: if (!drv->mfmpos) {
1139: disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
1140: disk_events (0);
1141: }
1142: if ((dmacon & 0x210) == 0x210 && dskdmaen == 3) {
1143: bitoffset++;
1144: bitoffset &= 15;
1145: if (!bitoffset) {
1146: drv->bigmfmbuf[drv->mfmpos >> 4] = get_word (dskpt);
1147: dskpt += 2;
1148: dsklength--;
1149: if (dsklength == 0) {
1150: disk_dmafinished ();
1151: drive_write_data (drv);
1152: }
1.1 root 1153: }
1154: }
1.1.1.7 root 1155: hpos += drv->trackspeed;
1.1 root 1156: }
1.1.1.11 root 1157: disk_hpos = hpos - (maxhpos << 8);
1.1 root 1158: }
1159:
1.1.1.7 root 1160: /* get one bit from MFM bit stream */
1.1.1.12 root 1161: static uae_u32 getonebit (uae_u16 * mfmbuf, int mfmpos, uae_u32 word)
1.1 root 1162: {
1.1.1.7 root 1163: uae_u16 *buf;
1.1 root 1164:
1.1.1.7 root 1165: buf = &mfmbuf[mfmpos >> 4];
1166: word <<= 1;
1167: word |= (buf[0] & (1 << (15 - (mfmpos & 15)))) ? 1 : 0;
1168: return word;
1.1 root 1169: }
1170:
1.1.1.11 root 1171: #define WORDSYNC_CYCLES 7 /* (~7 * 280ns = 2us) */
1172:
1.1.1.7 root 1173: /* emulate disk read dma for full horizontal line */
1174: static void disk_doupdate_read (drive * drv)
1175: {
1176: int hpos = disk_hpos;
1.1.1.12 root 1177: int is_sync = 0;
1.1.1.11 root 1178: int j = 0, k = 1, l = 0;
1.1.1.12 root 1179: uae_u16 synccheck;
1.1.1.11 root 1180: static int dskbytr_last = 0, wordsync_last = -1;
1.1.1.7 root 1181:
1.1.1.11 root 1182: dskbytr_tab[0] = dskbytr_tab[dskbytr_last];
1183:
1184: if (wordsync_last >= 0 && maxhpos - wordsync_cycle[wordsync_last] < WORDSYNC_CYCLES)
1185: wordsync_cycle[l++] = (maxhpos - wordsync_cycle[wordsync_last]) - WORDSYNC_CYCLES;
1186: wordsync_last = -1;
1187:
1188: while (hpos < (maxhpos << 8)) {
1189: if (drv->dskready)
1190: word = getonebit (drv->bigmfmbuf, drv->mfmpos, word);
1191: else
1192: word <<= 1;
1.1.1.7 root 1193: drv->mfmpos++;
1194: drv->mfmpos %= drv->tracklen;
1.1.1.12 root 1195: if (!drv->mfmpos) {
1.1.1.7 root 1196: disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
1197: is_sync = 1;
1198: }
1.1.1.12 root 1199: if (bitoffset == 31 && dma_enable) {
1200: dma_tab[j++] = (word >> 16) & 0xffff;
1.1.1.7 root 1201: if (j == MAX_DISK_WORDS_PER_LINE - 1) {
1202: write_log ("Bug: Disk DMA buffer overflow!\n");
1203: j--;
1204: }
1205: }
1.1.1.12 root 1206: if (bitoffset == 15 || bitoffset == 23 || bitoffset == 31) {
1207: dskbytr_tab[k] = (word >> 8) & 0xff;
1.1.1.11 root 1208: dskbytr_tab[k] |= 0x8000;
1209: dskbytr_last = k;
1.1.1.7 root 1210: dskbytr_cycle[k++] = hpos >> 8;
1211: }
1.1.1.12 root 1212: synccheck = (word >> 8) & 0xffff;
1213: if (synccheck == dsksync) {
1214: if (adkcon & 0x400) {
1215: if (bitoffset != 23 || !dma_enable)
1216: bitoffset = 7;
1217: dma_enable = 1;
1218: }
1219: wordsync_last = l;
1220: wordsync_cycle[l++] = hpos >> 8;
1221: disk_sync[hpos >> 8] |= DISK_WORDSYNC;
1222: is_sync = 1;
1223: }
1.1.1.11 root 1224: bitoffset++;
1.1.1.12 root 1225: if (bitoffset == 32) bitoffset = 16;
1.1.1.7 root 1226: hpos += drv->trackspeed;
1227: }
1228: dma_tab[j] = 0xffffffff;
1.1.1.11 root 1229: dskbytr_cycle[k] = 255;
1230: wordsync_cycle[l] = 255;
1.1.1.7 root 1231: if (is_sync)
1232: disk_events (0);
1233:
1.1.1.11 root 1234: disk_hpos = hpos - (maxhpos << 8);
1.1.1.7 root 1235: }
1236:
1237: /* disk DMA fetch happens on real Amiga at the beginning of next horizontal line
1238: (cycles 9, 11 and 13 according to hardware manual) We transfer all DMA'd
1239: data at cycle 0. I don't think any program cares about this small difference.
1.1.1.12 root 1240:
1241: We must handle dsklength = 0 because some copy protections use it to detect
1242: wordsync without transferring any data.
1.1.1.7 root 1243: */
1244: static void dodmafetch (void)
1.1 root 1245: {
1.1.1.7 root 1246: int i;
1247:
1248: i = 0;
1249: while (dma_tab[i] != 0xffffffff && dskdmaen == 2 && (dmacon & 0x210) == 0x210) {
1.1.1.12 root 1250: if (dsklength > 0) {
1251: put_word (dskpt, dma_tab[i++]);
1252: dskpt += 2;
1253: dsklength--;
1254: }
1.1.1.7 root 1255: if (dsklength == 0) {
1256: disk_dmafinished ();
1257: break;
1258: }
1259: }
1260: dma_tab[0] = 0xffffffff;
1.1 root 1261: }
1262:
1.1.1.17 root 1263: /* this is very unoptimized. DSKBYTR is used very rarely, so it should not matter. */
1264:
1265: uae_u16 DSKBYTR (int hpos)
1266: {
1267: uae_u16 v;
1268: int i;
1269:
1270: i = 0;
1271: while (hpos > dskbytr_cycle[i + 1])
1272: i++;
1273: v = dskbytr_tab[i];
1274: dskbytr_tab[i] &= ~0x8000;
1275: if (wordsync_cycle[0] != 255) {
1276: i = 0;
1277: while (hpos < wordsync_cycle[i])
1278: i++;
1279: if (hpos - wordsync_cycle[i] <= WORDSYNC_CYCLES)
1280: v |= 0x1000;
1281: }
1282: if (dskdmaen && (dmacon & 0x210) == 0x210)
1283: v |= 0x4000;
1284: if (dskdmaen == 3)
1285: v |= 0x2000;
1286:
1287: disk_data_used = 0;
1288:
1289: return v;
1290: }
1291:
1.1.1.7 root 1292: static void DISK_start (void)
1.1.1.6 root 1293: {
1294: int dr;
1.1.1.7 root 1295:
1.1.1.6 root 1296: for (dr = 0; dr < 4; dr++) {
1.1.1.7 root 1297: drive *drv = &floppy[dr];
1298: if (!(selected & (1 << dr))) {
1299: int tr = drv->cyl * 2 + side;
1300: trackid *ti = drv->trackdata + tr;
1301:
1302: if (dskdmaen == 3) {
1.1.1.11 root 1303: drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 8 * 2;
1.1.1.7 root 1304: drv->trackspeed = floppy_speed;
1305: }
1306: /* Ugh. A nasty hack. Assume ADF_EXT1 tracks are always read
1307: from the start. */
1308: if (ti->type == TRACK_RAW1)
1.1.1.12 root 1309: drv->mfmpos = 0;
1.1.1.6 root 1310: }
1311: }
1.1.1.12 root 1312: dma_enable = (adkcon & 0x400) ? 0 : 1;
1.1.1.7 root 1313: word = 0;
1314: bitoffset = 0;
1315: dma_tab[0] = 0xffffffff;
1.1.1.6 root 1316: }
1317:
1.1.1.7 root 1318: static int linecounter;
1319:
1320: void DISK_update (void)
1.1 root 1321: {
1322: int dr;
1.1.1.18 root 1323:
1.1.1.6 root 1324: for (dr = 0; dr < 4; dr++) {
1.1.1.7 root 1325: drive *drv = &floppy[dr];
1.1.1.11 root 1326: if (drv->steplimit)
1327: drv->steplimit--;
1.1.1.7 root 1328: }
1329: if (linecounter) {
1330: linecounter--;
1331: if (! linecounter)
1332: disk_dmafinished ();
1333: return;
1334: }
1335:
1336: dodmafetch ();
1337:
1338: for (dr = 0; dr < 4; dr++) {
1339: drive *drv = &floppy[dr];
1340: if (drv->motoroff)
1341: continue;
1342: if (selected & (1 << dr)) {
1.1.1.11 root 1343: drv->mfmpos += (maxhpos << 8) / drv->trackspeed;
1.1.1.7 root 1344: drv->mfmpos %= drv->tracklen;
1345: continue;
1.1 root 1346: }
1.1.1.11 root 1347: drive_fill_bigbuf (drv);
1348: drv->mfmpos %= drv->tracklen;
1349: if (dskdmaen > 1)
1350: disk_data_used = 0;
1351:
1.1.1.7 root 1352: if (dskdmaen == 3)
1353: disk_doupdate_write (drv);
1.1.1.12 root 1354: else if (1 || disk_data_used < MAXVPOS * 50 * 2) {
1.1.1.11 root 1355: disk_data_used++;
1.1.1.7 root 1356: disk_doupdate_read (drv);
1.1.1.11 root 1357: }
1.1.1.7 root 1358: return;
1.1 root 1359: }
1360: }
1.1.1.6 root 1361:
1.1.1.7 root 1362: void DSKLEN (uae_u16 v, int hpos)
1.1.1.6 root 1363: {
1.1.1.7 root 1364: if (v & 0x8000) {
1365: dskdmaen = dskdmaen == 1 ? 2 : 1;
1366: } else {
1367: /* Megalomania does this */
1368: #if 0
1369: if (dskdmaen == 2)
1370: write_log ("warning: Disk read DMA aborted, %d words left\n", dsklength);
1371: #endif
1372: if (dskdmaen == 3)
1373: write_log ("warning: Disk write DMA aborted, %d words left\n", dsklength);
1374: dskdmaen = 0;
1375: }
1.1.1.12 root 1376: dsklength = v & 0x3ffe;
1.1.1.7 root 1377: if (dskdmaen <= 1)
1378: return;
1379: if (v & 0x4000)
1380: dskdmaen = 3;
1381: #ifdef DISK_DEBUG
1382: {
1383: int dr;
1384: for (dr = 0; dr < 4; dr++) {
1385: drive *drv = &floppy[dr];
1386: if (drv->motoroff)
1387: continue;
1388: if ((selected & (1 << dr)) == 0)
1389: break;
1390: }
1391: if (dr == 4)
1392: write_log ("disk DMA started, but no drive ready!\n");
1393: else
1394: write_log ("disk %s DMA started for %d words (%08.8X) sync=%04.4X track %d\n",
1395: dskdmaen == 3 ? "write" : "read", dsklength, dskpt,
1396: (adkcon & 0x400) ? dsksync : 0xffff,
1397: floppy[dr].cyl * 2 + side);
1398: }
1399: #endif
1400: /* Megalomania does not work if DSKLEN write is delayed to next horizontal line,
1401: also it seems some copy protections require this fix */
1402: DISK_start ();
1.1.1.6 root 1403:
1.1.1.7 root 1404: /* Try to make floppy access from Kickstart faster. */
1405: if (dskdmaen != 2)
1406: return;
1407: {
1408: int dr;
1409: uaecptr pc = m68k_getpc ();
1410: if ((pc & 0xF80000) != 0xF80000)
1411: return;
1412: for (dr = 0; dr < 4; dr++) {
1413: drive *drv = &floppy[dr];
1414: if (drv->motoroff)
1415: continue;
1416: if ((selected & (1 << dr)) == 0) {
1417: int pos = drv->mfmpos & ~15;
1418: int i;
1419:
1.1.1.11 root 1420: drive_fill_bigbuf (drv);
1.1.1.7 root 1421: if (adkcon & 0x400) {
1422: for (i = 0; i < drv->tracklen; i += 16) {
1423: pos += 16;
1424: pos %= drv->tracklen;
1.1.1.11 root 1425: if (drv->bigmfmbuf[pos >> 4] == dsksync) {
1426: /* must skip first disk sync marker */
1.1.1.12 root 1427: pos += 16;
1.1.1.11 root 1428: pos %= drv->tracklen;
1.1.1.7 root 1429: break;
1.1.1.11 root 1430: }
1.1.1.7 root 1431: }
1432: if (i >= drv->tracklen)
1433: return;
1434: }
1435: while (dsklength-- > 0) {
1436: put_word (dskpt, drv->bigmfmbuf[pos >> 4]);
1437: dskpt += 2;
1438: pos += 16;
1439: pos %= drv->tracklen;
1.1.1.6 root 1440: }
1.1.1.7 root 1441: INTREQ (0x9000);
1442: linecounter = 2;
1443: dskdmaen = 0;
1444: return;
1.1.1.6 root 1445: }
1446: }
1.1.1.7 root 1447: }
1.1.1.6 root 1448: }
1449:
1.1.1.11 root 1450: /* not a real hardware register */
1.1.1.7 root 1451: uae_u16 DSKDATR (int hpos)
1452: {
1.1.1.11 root 1453: return 0;
1.1.1.7 root 1454: }
1455:
1456: void DSKSYNC (uae_u16 v)
1457: {
1458: dsksync = v;
1459: }
1460:
1461: void DSKDAT (uae_u16 v)
1462: {
1463: static int count = 0;
1464: if (count < 5) {
1465: count++;
1466: write_log ("DSKDAT written. Not good.");
1467: if (count == 5)
1468: write_log ("(further messages suppressed)");
1469:
1470: write_log ("\n");
1.1.1.6 root 1471: }
1472: }
1.1.1.7 root 1473: void DSKPTH (uae_u16 v)
1474: {
1475: dskpt = (dskpt & 0xffff) | ((uae_u32) v << 16);
1476: }
1.1.1.6 root 1477:
1.1.1.7 root 1478: void DSKPTL (uae_u16 v)
1.1.1.6 root 1479: {
1.1.1.7 root 1480: dskpt = (dskpt & ~0xffff) | (v);
1.1.1.6 root 1481: }
1482:
1.1.1.7 root 1483: void DISK_init (void)
1484: {
1.1.1.11 root 1485: int dr;
1.1.1.7 root 1486:
1487: dma_tab[0] = 0xffffffff;
1.1.1.11 root 1488: dskbytr_cycle[0] = 0;
1489: dskbytr_cycle[1] = 255;
1490: wordsync_cycle[0] = 255;
1.1.1.7 root 1491:
1.1.1.11 root 1492: for (dr = 0; dr < 4; dr++) {
1.1.1.20! root 1493: drive *drv = floppy + dr;
! 1494: drv->type = currprefs.dfxtype[dr];
! 1495: reset_drive (dr);
1.1.1.8 root 1496: }
1.1.1.7 root 1497: if (disk_empty (0))
1498: write_log ("No disk in drive 0.\n");
1499: }
1500:
1.1.1.8 root 1501: void DISK_reset (void)
1502: {
1503: int i;
1.1.1.13 root 1504:
1505: if (savestate_state)
1506: return;
1507:
1.1.1.8 root 1508: disk_hpos = 0;
1.1.1.11 root 1509: disk_data_used = 0;
1.1.1.20! root 1510: dskdmaen = 0;
1.1.1.12 root 1511: disabled = 0;
1.1.1.8 root 1512: for (i = 0; i < 4; i++) {
1.1.1.20! root 1513: reset_drive (i);
1.1.1.8 root 1514: }
1515: }
1516:
1.1.1.7 root 1517: void dumpdisk (void)
1518: {
1519: int i;
1520: for (i = 0; i < 4; i++) {
1521: drive *drv = &floppy[i];
1522: printf ("Drive %d: motor %s cylinder %2d selected %d\n", i, drv->motoroff ? "off" : " on", drv->cyl, selected & (1 << i));
1523: }
1524: }
1.1.1.11 root 1525:
1526: /* Disk save/restore code */
1527:
1528: void DISK_save_custom (uae_u32 *pdskpt, uae_u16 *pdsklength, uae_u16 *pdsksync, uae_u16 *pdskdatr, uae_u16 *pdskbytr)
1529: {
1.1.1.20! root 1530: if (pdskpt) *pdskpt = dskpt;
! 1531: if (pdsklength) *pdsklength = dsklength;
! 1532: if (pdsksync) *pdsksync = dsksync;
! 1533: if (pdskdatr) *pdskdatr = 0;
! 1534: if (pdskbytr) *pdskbytr = dskbytr_tab[0];
1.1.1.11 root 1535: }
1536:
1537: void DISK_restore_custom (uae_u32 pdskpt, uae_u16 pdsklength, uae_u16 pdskdatr, uae_u16 pdskbytr)
1538: {
1539: dskpt = pdskpt;
1540: dsklength = pdsklength;
1541: dskbytr_tab[0] = pdskbytr;
1542: }
1543:
1.1.1.19 root 1544: const uae_u8 *restore_disk (int num, const uae_u8 *src)
1.1.1.11 root 1545: {
1546: drive *drv;
1.1.1.13 root 1547: int state;
1.1.1.20! root 1548: int newis;
1.1.1.11 root 1549:
1550: drv = &floppy[num];
1.1.1.13 root 1551: disabled &= ~(1 << num);
1.1.1.11 root 1552: drv->drive_id = restore_u32 ();
1.1.1.20! root 1553: drv->motoroff = 1;
! 1554: drv->idbit = 0;
1.1.1.13 root 1555: state = restore_u8 ();
1.1.1.20! root 1556: if (state & 2) {
! 1557: disabled |= 1 << num;
! 1558: if (changed_prefs.nr_floppies > num)
! 1559: changed_prefs.nr_floppies = num;
! 1560: changed_prefs.dfxtype[num] = -1;
! 1561: } else {
! 1562: drive_type dfxtype;
! 1563: drv->motoroff = (state & 1) ? 0 : 1;
! 1564: drv->idbit = (state & 4) ? 1 : 0;
! 1565: if (changed_prefs.nr_floppies < num)
! 1566: changed_prefs.nr_floppies = num;
! 1567: switch (drv->drive_id)
! 1568: {
! 1569: case DRIVE_ID_35HD:
! 1570: dfxtype = DRV_35_HD;
! 1571: break;
! 1572: case DRIVE_ID_525SD:
! 1573: dfxtype = DRV_525_SD;
! 1574: break;
! 1575: default:
! 1576: dfxtype = DRV_35_DD;
! 1577: break;
! 1578: }
! 1579: changed_prefs.dfxtype[num] = dfxtype;
! 1580: }
! 1581: drv->type = changed_prefs.dfxtype[num];
! 1582: drv->buffered_cyl = -1;
! 1583: drv->buffered_side = -1;
1.1.1.11 root 1584: drv->cyl = restore_u8 ();
1585: drv->dskready = restore_u8 ();
1586: drv->drive_id_scnt = restore_u8 ();
1587: drv->mfmpos = restore_u32 ();
1.1.1.20! root 1588: drv->dskchange = 0;
! 1589: drv->dskchange_time = 0;
1.1.1.11 root 1590: restore_u32 ();
1.1.1.20! root 1591: strncpy (changed_prefs.df[num], src, 255);
1.1.1.16 root 1592: changed_prefs.df[num][255] = 0;
1.1.1.20! root 1593: newis = changed_prefs.df[num][0] ? 1 : 0;
! 1594: src += strlen (src) + 1;
! 1595:
! 1596: if (!(disabled & (1 << num))) {
! 1597: if (!newis) {
! 1598: drv->dskchange = 1;
! 1599: } else {
! 1600: drive_insert (floppy + num, num, changed_prefs.df[num]);
! 1601: }
! 1602: }
1.1.1.11 root 1603:
1604: return src;
1605: }
1606:
1.1.1.19 root 1607: uae_u8 *save_disk (int num, int *len, uae_u8 *dstptr)
1.1.1.11 root 1608: {
1609: uae_u8 *dstbak,*dst;
1610: drive *drv;
1611:
1612: drv = &floppy[num];
1.1.1.18 root 1613: if (dstptr)
1614: dstbak = dst = dstptr;
1615: else
1616: dstbak = dst = malloc (2+1+1+1+1+4+4+256);
1.1.1.11 root 1617: save_u32 (drv->drive_id); /* drive type ID */
1.1.1.20! root 1618: save_u8 ((drv->motoroff ? 0:1) | ((disabled & (1 << num)) ? 2 : 0) | (drv->idbit ? 4 : 0) | (drv->dskchange ? 8 : 0));
1.1.1.11 root 1619: save_u8 (drv->cyl); /* cylinder */
1620: save_u8 (drv->dskready); /* dskready */
1621: save_u8 (drv->drive_id_scnt); /* id mode position */
1622: save_u32 (drv->mfmpos); /* disk position */
1623: save_u32 (0); /* CRC of disk image */
1624: strcpy (dst, currprefs.df[num]);/* image name */
1.1.1.20! root 1625: dst += strlen (dst) + 1;
1.1.1.11 root 1626:
1627: *len = dst - dstbak;
1628: return dstbak;
1629: }
1630:
1631: /* internal floppy controller variables */
1632:
1.1.1.19 root 1633: const uae_u8 *restore_floppy (const uae_u8 *src)
1.1.1.11 root 1634: {
1.1.1.20! root 1635: word = restore_u16 ();
! 1636: bitoffset = restore_u8 ();
! 1637: dma_enable = restore_u8 ();
! 1638: disk_hpos = restore_u8 ();
! 1639: dskdmaen = restore_u8 ();
! 1640: word |= restore_u16 () << 16;
1.1.1.11 root 1641:
1642: return src;
1643: }
1644:
1.1.1.19 root 1645: uae_u8 *save_floppy (int *len, uae_u8 *dstptr)
1.1.1.11 root 1646: {
1647: uae_u8 *dstbak, *dst;
1648:
1649: /* flush dma buffer before saving */
1.1.1.20! root 1650: dodmafetch ();
1.1.1.11 root 1651:
1.1.1.18 root 1652: if (dstptr)
1653: dstbak = dst = dstptr;
1654: else
1.1.1.20! root 1655: dstbak = dst = malloc (2+1+1+1+1+2);
1.1.1.12 root 1656: save_u16 (word); /* current fifo (low word) */
1.1.1.11 root 1657: save_u8 (bitoffset); /* dma bit offset */
1.1.1.12 root 1658: save_u8 (dma_enable); /* disk sync found */
1.1.1.11 root 1659: save_u8 (disk_hpos); /* next bit read position */
1660: save_u8 (dskdmaen); /* dma status */
1.1.1.12 root 1661: save_u16 (word >> 16); /* current fifo (high word) */
1.1.1.11 root 1662:
1663: *len = dst - dstbak;
1664: return dstbak;
1665: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.