|
|
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.4 root 6: * Copyright 1995 Bernd Schmidt, Hannu Rummukainen
1.1 root 7: */
8:
1.1.1.2 root 9: #include <stdio.h>
10:
1.1 root 11: #include "sysconfig.h"
12: #include "sysdeps.h"
13:
14: #include "config.h"
15: #include "options.h"
1.1.1.3 root 16: #include "threaddep/penguin.h"
1.1 root 17: #include "memory.h"
18: #include "events.h"
19: #include "custom.h"
20: #include "ersatz.h"
21: #include "disk.h"
22: #include "gui.h"
23: #include "zfile.h"
1.1.1.2 root 24: #include "autoconf.h"
25: #include "newcpu.h"
26: #include "xwin.h"
27: #include "osemu.h"
28: #include "execlib.h"
29:
1.1.1.3 root 30: #define FLOPPY_GAP_LEN 360
1.1.1.7 root 31: /* writable track length with normal 2us bitcell/300RPM motor */
32: #define FLOPPY_WRITE_LEN 6250
33: /* (cycles/bitcell) << 8, normal = ((2us/280ns)<<8) = ~1830 */
34: #define NORMAL_FLOPPY_SPEED 1830
35:
36: static int floppy_speed = NORMAL_FLOPPY_SPEED;
37:
38: #undef DISK_DEBUG
39:
40: /* UAE-1ADF (ADF_EXT2)
41: * W reserved
42: * W number of tracks (default 2*80=160)
43: *
44: * W reserved
45: * W type, 0=normal AmigaDOS track, 1 = raw MFM
46: * L available space for track in bytes
47: * L track length in bits
48: */
1.1 root 49:
1.1.1.7 root 50: static int side, direction, step, writing;
1.1.1.3 root 51: static uae_u8 selected = 15;
1.1 root 52:
1.1.1.7 root 53: static uae_u8 *writebuffer[544 * 11];
54:
55: typedef enum { TRACK_AMIGADOS, TRACK_RAW, TRACK_RAW1 } image_tracktype;
1.1 root 56: typedef struct {
1.1.1.3 root 57: uae_u16 len;
58: uae_u32 offs;
1.1.1.7 root 59: int bitlen;
60: unsigned int sync;
61: image_tracktype type;
1.1 root 62: } trackid;
63:
1.1.1.2 root 64: #define MAX_TRACKS 328
65:
1.1.1.7 root 66: typedef enum { ADF_NORMAL, ADF_EXT1, ADF_EXT2 } drive_filetype;
1.1 root 67: typedef struct {
68: FILE *diskfile;
69: drive_filetype filetype;
1.1.1.2 root 70: trackid trackdata[MAX_TRACKS];
1.1.1.7 root 71: int buffered_cyl, buffered_side;
72: int cyl;
1.1 root 73: int motoroff;
1.1.1.7 root 74: int state;
75: int disabled;
1.1 root 76: int wrprot;
1.1.1.3 root 77: uae_u16 bigmfmbuf[0x4000];
1.1 root 78: int mfmpos;
1.1.1.7 root 79: int mfmpos_hsync;
80: int tracklen;
81: int trackspeed;
82: int dmalen;
83: int num_tracks, num_secs;
1.1.1.3 root 84: /* dskchange is set to a small number when a disk is removed. At a step
85: * impulse, it is reset if there is a new disk in the drive or counted
86: * down to 1 if the drive contains a disk. DISK_check_change will only
87: * insert a new disk when dskchange is 1, or if the dskchange_time timer
88: * expires. The last condition can happen if AmigaOS isn't running and a
89: * game/demo doesn't use the step motor to check for a new disk.
90: */
91: int dskchange;
92: int dskchange_time;
1.1.1.10! root 93: int dskready;
! 94: int dskready_time;
1.1 root 95: } drive;
96:
97: drive floppy[4];
98:
1.1.1.7 root 99: /* code for track display */
1.1.1.8 root 100: static void update_drive_gui (int num)
1.1.1.7 root 101: {
1.1.1.8 root 102: drive *drv = floppy + num;
103:
1.1.1.7 root 104: if (drv->state == gui_data.drive_motor[num]
105: && drv->cyl == gui_data.drive_track[num]
106: && ((writing && gui_data.drive_writing[num])
107: || (!writing && !gui_data.drive_writing[num]))) {
108: return;
109: }
110: gui_data.drive_motor[num] = drv->state;
111: gui_data.drive_track[num] = drv->cyl;
112: if (!gui_data.drive_writing[num])
113: gui_data.drive_writing[num] = writing;
1.1.1.8 root 114: gui_ledstate &= ~(2 << num);
115: if (drv->state)
116: gui_ledstate |= 2 << num;
1.1.1.7 root 117: gui_led (num + 1, gui_data.drive_motor[num]);
118: }
119:
120: static void drive_fill_bigbuf (drive * drv);
1.1 root 121:
1.1.1.3 root 122: FILE *DISK_validate_filename (const char *fname, int leave_open, int *wrprot)
1.1 root 123: {
1.1.1.4 root 124: FILE *f = zfile_open (fname, "r+b");
1.1.1.3 root 125: if (f) {
126: if (wrprot)
127: *wrprot = 0;
1.1 root 128: } else {
1.1.1.3 root 129: if (wrprot)
130: *wrprot = 1;
1.1.1.4 root 131: f = zfile_open (fname, "rb");
1.1 root 132: }
1.1.1.3 root 133: if (!leave_open)
1.1.1.4 root 134: zfile_close (f);
1.1.1.3 root 135: return f;
136: }
137:
1.1.1.7 root 138: static int drive_insert (drive * drv, int dnum, const char *fname)
1.1.1.3 root 139: {
1.1.1.7 root 140: unsigned char buffer[2 + 2 + 4 + 4];
141: trackid *tid;
1.1.1.3 root 142:
143: drv->diskfile = DISK_validate_filename (fname, 1, &drv->wrprot);
1.1.1.6 root 144: if (drv->diskfile == 0) {
1.1.1.7 root 145: drv->tracklen = FLOPPY_WRITE_LEN * 2 * 8;
146: drv->trackspeed = floppy_speed;
1.1.1.3 root 147: return 0;
1.1.1.6 root 148: }
1.1.1.3 root 149: strncpy (currprefs.df[dnum], fname, 255);
150: currprefs.df[dnum][255] = 0;
151: strncpy (changed_prefs.df[dnum], fname, 255);
152: changed_prefs.df[dnum][255] = 0;
1.1.1.7 root 153: gui_filename (dnum, fname);
1.1.1.3 root 154:
1.1.1.7 root 155: fread (buffer, sizeof (char), 8, drv->diskfile);
156: if (strncmp ((char *) buffer, "UAE-1ADF", 8) == 0) {
157: int offs;
158: int i;
159:
160: fread (buffer, 1, 4, drv->diskfile);
161: drv->num_tracks = buffer[2] * 256 + buffer[3];
162: drv->filetype = ADF_EXT2;
163: drv->num_secs = 11;
1.1.1.10! root 164: offs = 8 + 2 + 2 + drv->num_tracks * (2 + 2 + 4 + 4);
1.1.1.7 root 165:
166: for (i = 0; i < drv->num_tracks; i++) {
167: tid = &drv->trackdata[i];
168: fread (buffer, 2 + 2 + 4 + 4, 1, drv->diskfile);
169: tid->type = buffer[2] * 256 + buffer[3];
170: tid->len = buffer[5] * 65536 + buffer[6] * 256 + buffer[7];
171: tid->bitlen = buffer[9] * 65536 + buffer[10] * 256 + buffer[11];
172: tid->offs = offs;
173: if (tid->type == TRACK_AMIGADOS) {
174: if (tid->len > 20000)
175: drv->num_secs = 22;
176: }
177: offs += tid->len;
178: }
179: } else if (strncmp ((char *) buffer, "UAE--ADF", 8) == 0) {
180: int offs = 160 * 4 + 8;
1.1 root 181: int i;
1.1.1.3 root 182:
183: drv->filetype = ADF_EXT1;
1.1.1.2 root 184: drv->num_tracks = 160;
185: drv->num_secs = 11;
1.1.1.3 root 186:
1.1.1.7 root 187: drv->wrprot = 1; /* write to adf_ext1 not implemented */
188: for (i = 0; i < 160; i++) {
189: tid = &drv->trackdata[i];
190: fread (buffer, 4, 1, drv->diskfile);
191: tid->sync = buffer[0] * 256 + buffer[1];
192: tid->len = buffer[2] * 256 + buffer[3];
193: tid->offs = offs;
194: if (tid->sync == 0) {
195: tid->type = TRACK_AMIGADOS;
196: tid->bitlen = 0;
197: } else {
198: tid->type = TRACK_RAW1;
199: tid->bitlen = tid->len * 8;
200: }
201: offs += tid->len;
1.1 root 202: }
203: } else {
1.1.1.7 root 204: int i;
1.1.1.3 root 205:
206: drv->filetype = ADF_NORMAL;
1.1.1.2 root 207:
1.1.1.7 root 208: fseek (drv->diskfile, 0, SEEK_END);
1.1.1.4 root 209: i = ftell (drv->diskfile);
1.1.1.7 root 210: fseek (drv->diskfile, 0, SEEK_SET);
1.1.1.3 root 211:
1.1.1.2 root 212: /* High-density disk? */
1.1.1.7 root 213: if (i >= 160 * 22 * 512)
214: drv->num_tracks = i / (512 * (drv->num_secs = 22));
1.1.1.2 root 215: else
1.1.1.7 root 216: drv->num_tracks = i / (512 * (drv->num_secs = 11));
1.1.1.3 root 217:
1.1.1.2 root 218: if (drv->num_tracks > MAX_TRACKS)
1.1.1.3 root 219: write_log ("Your diskfile is too big!\n");
1.1.1.7 root 220: for (i = 0; i < drv->num_tracks; i++) {
221: tid = &drv->trackdata[i];
222: tid->type = TRACK_AMIGADOS;
223: tid->len = 512 * drv->num_secs;
224: tid->bitlen = 0;
225: tid->offs = i * 512 * drv->num_secs;
1.1 root 226: }
227: }
1.1.1.7 root 228: drv->buffered_side = 2; /* will force read */
1.1.1.6 root 229: drive_fill_bigbuf (drv);
1.1.1.3 root 230: return 1;
1.1 root 231: }
232:
1.1.1.7 root 233: static int drive_empty (drive * drv)
1.1.1.2 root 234: {
1.1.1.3 root 235: return drv->diskfile == 0;
1.1.1.2 root 236: }
237:
1.1.1.7 root 238: static void drive_step (drive * drv)
1.1 root 239: {
1.1.1.7 root 240: if (!drive_empty (drv))
1.1.1.3 root 241: drv->dskchange = 0;
242: else if (drv->dskchange > 1) {
243: /* printf("Stepping...\n");
244: drv->dskchange--;*/
245: }
1.1 root 246: if (direction) {
1.1.1.7 root 247: if (drv->cyl)
248: drv->cyl--;
1.1 root 249: } else {
1.1.1.7 root 250: if (drv->cyl < 83)
251: drv->cyl++;
1.1 root 252: }
253:
1.1.1.7 root 254: #if 0 && defined DISK_DEBUG
255: write_log ("track %d\n", drv->cyl);
256: #endif
257: }
1.1 root 258:
1.1.1.7 root 259: static int drive_track0 (drive * drv)
1.1 root 260: {
1.1.1.3 root 261: return drv->cyl == 0;
1.1 root 262: }
263:
1.1.1.7 root 264: static int drive_writeprotected (drive * drv)
1.1 root 265: {
1.1.1.3 root 266: return drv->wrprot || drv->diskfile == NULL;
1.1 root 267: }
268:
1.1.1.7 root 269: static int drive_running (drive * drv)
1.1 root 270: {
1.1.1.3 root 271: return !drv->motoroff;
1.1 root 272: }
273:
1.1.1.7 root 274: static void drive_motor (drive * drv, int off)
1.1 root 275: {
1.1.1.10! root 276: if (drv->disabled)
! 277: off = 1;
! 278: /* A value of 2 works out to a guaranteed delay of 1/10 of a second
! 279: (which is the frequency with which DISK_check_change is called).
! 280: Higher values are dangerous, e.g. a value of 8 breaks the RSI
! 281: demo. */
! 282: if (drv->motoroff && !off)
! 283: drv->dskready_time = 2;
1.1 root 284: drv->motoroff = off;
1.1.1.10! root 285: if (drv->motoroff) {
! 286: drv->dskready = 0;
! 287: drv->dskready_time = 0;
! 288: }
1.1 root 289: }
290:
1.1.1.7 root 291: static void read_floppy_data (drive * drv, int track, int offset, unsigned char *dst, int len)
292: {
293: trackid *ti;
294:
295: ti = &drv->trackdata[track];
296: fseek (drv->diskfile, ti->offs + offset, SEEK_SET);
297: fread (dst, 1, len, drv->diskfile);
298: }
299:
300: /* Megalomania does not like zero MFM words... */
301: static void mfmcode (uae_u16 * mfm, int words)
302: {
1.1.1.8 root 303: uae_u32 lastword = 0;
1.1.1.7 root 304:
305: while (words--) {
1.1.1.8 root 306: uae_u32 v = *mfm;
307: uae_u32 lv = (lastword << 16) | v;
308: uae_u32 nlv = 0x55555555 & ~lv;
309: uae_u32 mfmbits = (nlv << 1) & (nlv >> 1);
310:
311: *mfm++ = v | mfmbits;
312: lastword = v;
1.1.1.7 root 313: }
314: }
315:
316: static void drive_fill_bigbuf (drive * drv)
1.1 root 317: {
1.1.1.7 root 318: int tr = drv->cyl * 2 + side;
319: trackid *ti = drv->trackdata + tr;
1.1.1.3 root 320:
1.1.1.7 root 321: if (!drv->diskfile || tr >= drv->num_tracks) {
322: drv->tracklen = FLOPPY_WRITE_LEN * 2 * 8;
323: drv->trackspeed = floppy_speed;
324: memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2);
1.1.1.2 root 325: return;
326: }
1.1.1.3 root 327: if (drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
328: return;
329:
1.1.1.7 root 330: if (ti->type == TRACK_AMIGADOS) {
1.1 root 331: /* Normal AmigaDOS format track */
1.1.1.7 root 332: int sec;
333: drv->tracklen = (drv->num_secs * 544 + FLOPPY_GAP_LEN) * 2 * 8;
334: memset (drv->bigmfmbuf, 0xaa, FLOPPY_GAP_LEN * 2);
1.1.1.2 root 335:
336: for (sec = 0; sec < drv->num_secs; sec++) {
1.1.1.3 root 337: uae_u8 secbuf[544];
1.1 root 338: int i;
1.1.1.7 root 339: uae_u16 *mfmbuf = drv->bigmfmbuf + 544 * sec + FLOPPY_GAP_LEN;
340: uae_u32 deven, dodd;
341: uae_u32 hck = 0, dck = 0;
1.1.1.3 root 342:
1.1 root 343: secbuf[0] = secbuf[1] = 0x00;
344: secbuf[2] = secbuf[3] = 0xa1;
345: secbuf[4] = 0xff;
346: secbuf[5] = tr;
347: secbuf[6] = sec;
1.1.1.7 root 348: secbuf[7] = drv->num_secs - sec;
1.1 root 349:
1.1.1.7 root 350: for (i = 8; i < 24; i++)
1.1 root 351: secbuf[i] = 0;
1.1.1.3 root 352:
1.1.1.7 root 353: read_floppy_data (drv, tr, sec * 512, &secbuf[32], 512);
1.1.1.3 root 354:
1.1 root 355: mfmbuf[0] = mfmbuf[1] = 0xaaaa;
356: mfmbuf[2] = mfmbuf[3] = 0x4489;
1.1.1.3 root 357:
358: deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
1.1 root 359: | (secbuf[6] << 8) | (secbuf[7]));
360: dodd = deven >> 1;
1.1.1.7 root 361: deven &= 0x55555555;
362: dodd &= 0x55555555;
1.1.1.3 root 363:
1.1 root 364: mfmbuf[4] = dodd >> 16;
365: mfmbuf[5] = dodd;
1.1.1.7 root 366: mfmbuf[6] = deven >> 16;
1.1 root 367: mfmbuf[7] = deven;
1.1.1.3 root 368:
1.1 root 369: for (i = 8; i < 48; i++)
1.1.1.6 root 370: mfmbuf[i] = 0xaaaa;
1.1.1.7 root 371: for (i = 0; i < 512; i += 4) {
372: deven = ((secbuf[i + 32] << 24) | (secbuf[i + 33] << 16)
373: | (secbuf[i + 34] << 8) | (secbuf[i + 35]));
1.1 root 374: dodd = deven >> 1;
1.1.1.7 root 375: deven &= 0x55555555;
376: dodd &= 0x55555555;
377: mfmbuf[(i >> 1) + 32] = dodd >> 16;
378: mfmbuf[(i >> 1) + 33] = dodd;
379: mfmbuf[(i >> 1) + 256 + 32] = deven >> 16;
380: mfmbuf[(i >> 1) + 256 + 33] = deven;
381: }
382:
383: for (i = 4; i < 24; i += 2)
384: hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
385:
386: deven = dodd = hck;
387: dodd >>= 1;
388: mfmbuf[24] = dodd >> 16;
389: mfmbuf[25] = dodd;
390: mfmbuf[26] = deven >> 16;
391: mfmbuf[27] = deven;
392:
393: for (i = 32; i < 544; i += 2)
394: dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
395:
396: deven = dodd = dck;
397: dodd >>= 1;
398: mfmbuf[28] = dodd >> 16;
399: mfmbuf[29] = dodd;
400: mfmbuf[30] = deven >> 16;
401: mfmbuf[31] = deven;
402: mfmcode (mfmbuf + 4, 544 - 4);
1.1 root 403: }
1.1.1.7 root 404: #ifdef DISK_DEBUG
405: write_log ("amigados read track %d\n", tr);
406: #endif
1.1 root 407: } else {
408: int i;
1.1.1.7 root 409: int base_offset = ti->type == TRACK_RAW ? 0 : 1;
410: drv->tracklen = ti->bitlen + 16 * base_offset;
411: drv->bigmfmbuf[0] = ti->sync;
1.1.1.10! root 412: read_floppy_data (drv, tr, 0, (char *) (drv->bigmfmbuf + base_offset), (ti->bitlen + 7) / 8);
! 413: for (i = base_offset; i < (drv->tracklen + 15) / 16; i++) {
1.1.1.7 root 414: uae_u16 *mfm = drv->bigmfmbuf + i;
415: uae_u8 *data = (uae_u8 *) mfm;
416: *mfm = 256 * *data + *(data + 1);
1.1 root 417: }
1.1.1.7 root 418: #if 0 && defined DISK_DEBUG
419: write_log ("rawtrack %d\n", tr);
420: #endif
1.1 root 421: }
1.1.1.3 root 422: drv->buffered_side = side;
423: drv->buffered_cyl = drv->cyl;
1.1.1.7 root 424: drv->trackspeed = floppy_speed * drv->tracklen / (2 * 8 * FLOPPY_WRITE_LEN);
1.1 root 425: }
426:
1.1.1.7 root 427: /* Update ADF_EXT2 track header */
428: static void diskfile_update (drive * drv, int len, uae_u8 type)
1.1 root 429: {
1.1.1.7 root 430: trackid *ti;
431: int track;
432: uae_u8 buf[2 + 2 + 4 + 4], *zerobuf;
1.1.1.3 root 433:
1.1.1.7 root 434: if (drv->filetype != ADF_EXT2)
435: return;
1.1.1.6 root 436:
1.1.1.7 root 437: track = drv->cyl * 2 + side;
438: ti = &drv->trackdata[track];
439: ti->bitlen = len;
440: fseek (drv->diskfile, 8 + 4 + (2 + 2 + 4 + 4) * track, SEEK_SET);
441: memset (buf, 0, sizeof buf);
442: ti->type = type;
443: buf[3] = ti->type;
444: do_put_mem_long ((uae_u32 *) (buf + 4), ti->len);
445: do_put_mem_long ((uae_u32 *) (buf + 8), ti->bitlen);
446: fwrite (buf, sizeof (buf), 1, drv->diskfile);
447: if (ti->len > (len + 7) / 8) {
448: zerobuf = malloc (ti->len);
449: memset (zerobuf, 0, ti->len);
450: fseek (drv->diskfile, ti->offs, SEEK_SET);
451: fwrite (zerobuf, 1, ti->len, drv->diskfile);
452: free (zerobuf);
453: }
454: #ifdef DISK_DEBUG
455: write_log ("track %d, raw track length %d written (total size %d)\n", track, (ti->bitlen + 7) / 8, ti->len);
456: #endif
1.1 root 457: }
458:
459: #define MFMMASK 0x55555555
1.1.1.7 root 460: static uae_u32 getmfmlong (uae_u16 * mbuf)
1.1 root 461: {
462: return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK;
463: }
464:
1.1.1.7 root 465: static int drive_write_adf_amigados (drive * drv)
1.1 root 466: {
467: int i, secwritten = 0;
1.1.1.7 root 468: int length = 2 * FLOPPY_WRITE_LEN;
1.1.1.3 root 469: uae_u32 odd, even, chksum, id, dlong;
1.1.1.7 root 470: uae_u8 *secdata;
1.1.1.3 root 471: uae_u8 secbuf[544];
1.1.1.7 root 472: uae_u16 *mbuf = drv->bigmfmbuf;
1.1.1.3 root 473: uae_u16 *mend = mbuf + length;
1.1.1.7 root 474: char sectable[11];
1.1.1.3 root 475:
1.1.1.7 root 476: memset (sectable, 0, sizeof (sectable));
477: memcpy (mbuf + FLOPPY_WRITE_LEN, mbuf, FLOPPY_WRITE_LEN * sizeof (uae_u16));
1.1 root 478: mend -= (4 + 16 + 8 + 512);
1.1.1.7 root 479: while (secwritten < 11) {
1.1 root 480: int trackoffs;
1.1.1.3 root 481:
1.1 root 482: do {
483: while (*mbuf++ != 0x4489) {
1.1.1.4 root 484: if (mbuf >= mend)
1.1.1.7 root 485: return 1;
1.1 root 486: }
487: } while (*mbuf++ != 0x4489);
1.1.1.3 root 488:
1.1.1.4 root 489: odd = getmfmlong (mbuf);
490: even = getmfmlong (mbuf + 2);
1.1.1.3 root 491: mbuf += 4;
1.1 root 492: id = (odd << 1) | even;
1.1.1.3 root 493:
1.1 root 494: trackoffs = (id & 0xff00) >> 8;
495: if (trackoffs > 10) {
1.1.1.7 root 496: if (drv->filetype == ADF_EXT2)
497: return 2;
1.1.1.5 root 498: write_log ("Disk write: weird sector number %d\n", trackoffs);
1.1 root 499: continue;
500: }
501: chksum = odd ^ even;
1.1.1.4 root 502: for (i = 0; i < 4; i++) {
1.1.1.7 root 503: odd = getmfmlong (mbuf);
504: even = getmfmlong (mbuf + 8);
1.1 root 505: mbuf += 2;
1.1.1.3 root 506:
1.1 root 507: dlong = (odd << 1) | even;
1.1.1.7 root 508: if (dlong) {
509: if (drv->filetype == ADF_EXT2)
510: return 6;
1.1.1.4 root 511: secwritten = -200;
1.1.1.7 root 512: }
1.1 root 513: chksum ^= odd ^ even;
1.1.1.7 root 514: } /* could check here if the label is nonstandard */
1.1 root 515: mbuf += 8;
1.1.1.7 root 516: odd = getmfmlong (mbuf);
517: even = getmfmlong (mbuf + 2);
518: mbuf += 4;
519: if (((odd << 1) | even) != chksum || ((id & 0x00ff0000) >> 16) != drv->cyl * 2 + side) {
520: if (drv->filetype == ADF_EXT2)
521: return 3;
522: write_log ("Disk write: checksum error on sector %d header\n", trackoffs);
1.1 root 523: continue;
524: }
1.1.1.7 root 525: odd = getmfmlong (mbuf);
526: even = getmfmlong (mbuf + 2);
527: mbuf += 4;
1.1 root 528: chksum = (odd << 1) | even;
529: secdata = secbuf + 32;
1.1.1.7 root 530: for (i = 0; i < 128; i++) {
531: odd = getmfmlong (mbuf);
532: even = getmfmlong (mbuf + 256);
533: mbuf += 2;
1.1 root 534: dlong = (odd << 1) | even;
1.1.1.7 root 535: *secdata++ = dlong >> 24;
536: *secdata++ = dlong >> 16;
537: *secdata++ = dlong >> 8;
538: *secdata++ = dlong;
1.1 root 539: chksum ^= odd ^ even;
540: }
541: mbuf += 256;
542: if (chksum) {
1.1.1.7 root 543: if (drv->filetype == ADF_EXT2)
544: return 4;
545: write_log ("Disk write: sector %d, data checksum error\n", trackoffs);
1.1 root 546: continue;
547: }
1.1.1.7 root 548: sectable[trackoffs] = 1;
1.1 root 549: secwritten++;
1.1.1.7 root 550: memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
1.1 root 551: }
1.1.1.7 root 552: if (drv->filetype == ADF_EXT2 && (secwritten == 0 || secwritten < 0))
553: return 5;
1.1.1.3 root 554: if (secwritten == 0)
555: write_log ("Disk write in unsupported format\n");
1.1 root 556: if (secwritten < 0)
1.1.1.3 root 557: write_log ("Disk write: sector labels ignored\n");
1.1.1.7 root 558:
559: diskfile_update (drv, 11 * 512 * 8, TRACK_AMIGADOS);
560: for (i = 0; i < 11; i++) {
561: fseek (drv->diskfile, drv->trackdata[drv->cyl * 2 + side].offs + i * 512, SEEK_SET);
562: fwrite (writebuffer + i * 512, sizeof (uae_u8), 512, drv->diskfile);
563: }
564:
565: return 0;
1.1 root 566: }
567:
1.1.1.7 root 568: /* write raw track to disk file */
569: static int drive_write_ext2 (drive * drv)
570: {
571: trackid *ti;
572: int len, track, i;
1.1 root 573:
1.1.1.7 root 574: track = drv->cyl * 2 + side;
575: ti = &drv->trackdata[track];
576: len = (drv->tracklen + 7) / 8;
577: if (len > ti->len) {
578: write_log ("disk raw write: image file's track %d is too small (%d < %d)!\n", track, ti->len, len);
579: return 0;
580: }
581: diskfile_update (drv, drv->tracklen, TRACK_RAW);
582: for (i = 0; i < drv->trackdata[track].len / 2; i++) {
583: uae_u16 *mfm = drv->bigmfmbuf + i;
584: uae_u8 *data = (uae_u8 *) mfm;
585: *mfm = 256 * *data + *(data + 1);
586: }
587: fseek (drv->diskfile, ti->offs, SEEK_SET);
588: fwrite (drv->bigmfmbuf, 1, len, drv->diskfile);
589: return 1;
590: }
591:
592: static void drive_write_data (drive * drv)
1.1 root 593: {
1.1.1.7 root 594: int ret;
595: if (drive_writeprotected (drv))
596: return;
597: switch (drv->filetype) {
598: case ADF_NORMAL:
599: drive_write_adf_amigados (drv);
600: break;
601: case ADF_EXT1:
602: write_log ("writing to ADF_EXT1 not supported\n");
603: return;
604: case ADF_EXT2:
605: ret = drive_write_adf_amigados (drv);
606: if (ret) {
607: /*write_log("not an amigados track (error %d), writing as raw track\n",ret); */
608: drive_write_ext2 (drv);
609: }
610: break;
611: }
612: drv->buffered_side = 2; /* will force read */
613: }
614:
615: static void drive_eject (drive * drv)
616: {
617: if (!drive_empty (drv))
1.1.1.4 root 618: zfile_close (drv->diskfile);
1.1.1.3 root 619:
620: drv->dskchange = 4;
621: drv->dskchange_time = 20;
622: /* printf("setting changed bit %d\n", drv-floppy);*/
1.1 root 623: drv->diskfile = 0;
624: }
625:
1.1.1.3 root 626: /* We use this function if we have no Kickstart ROM.
1.1 root 627: * No error checking - we trust our luck. */
1.1.1.3 root 628: void DISK_ersatz_read (int tr, int sec, uaecptr dest)
1.1 root 629: {
1.1.1.7 root 630: uae_u8 *dptr = get_real_address (dest);
631: fseek (floppy[0].diskfile, floppy[0].trackdata[tr].offs + sec * 512, SEEK_SET);
1.1.1.3 root 632: fread (dptr, 1, 512, floppy[0].diskfile);
1.1 root 633: }
634:
1.1.1.4 root 635: void disk_eject (int num)
1.1 root 636: {
1.1.1.7 root 637: gui_filename (num, "");
638: drive_eject (floppy + num);
1.1.1.3 root 639: *currprefs.df[num] = *changed_prefs.df[num] = 0;
1.1 root 640: }
641:
1.1.1.4 root 642: void disk_insert (int num, const char *name)
1.1 root 643: {
644: /* just to be sure */
1.1.1.4 root 645: drive_eject (floppy + num);
646: drive_insert (floppy + num, num, name);
1.1 root 647: }
648:
1.1.1.3 root 649: void DISK_check_change (void)
650: {
651: int i;
652: static int count = 0;
653: count++;
654:
655: for (i = 0; i < 4; i++) {
1.1.1.10! root 656: /* emulate drive motor turn on time */
! 657: if (floppy[i].dskready_time) {
! 658: floppy[i].dskready_time--;
! 659: if (floppy[i].dskready_time == 0) {
! 660: floppy[i].dskready = 1;
! 661: }
! 662: }
1.1.1.3 root 663: if (strcmp (currprefs.df[i], changed_prefs.df[i]) != 0) {
664: if (currprefs.df[i][0] != '\0') {
1.1.1.7 root 665: drive_eject (floppy + i);
1.1.1.3 root 666: currprefs.df[i][0] = '\0';
1.1.1.7 root 667: gui_filename (i, "");
1.1.1.3 root 668: } else if (floppy[i].dskchange == 1) {
669: /* In theory, it should work without the dskchange test.
670: * In practice, it doesn't. */
671: drive_insert (floppy + i, i, changed_prefs.df[i]);
672: } else if (floppy[i].dskchange > 1 && floppy[i].dskchange_time > 0) {
673: /* Force the dskchange bit to go to 1 after a given timeout */
674: if (--floppy[i].dskchange_time == 0) {
675: floppy[i].dskchange = 1;
676: }
677: }
678: }
679: }
680: }
681:
1.1.1.4 root 682: int disk_empty (int num)
1.1 root 683: {
1.1.1.4 root 684: return drive_empty (floppy + num);
1.1 root 685: }
686:
1.1.1.10! root 687: static int not_ready = 0;
! 688:
1.1.1.4 root 689: void DISK_select (uae_u8 data)
1.1 root 690: {
1.1.1.10! root 691: static int lastselected;
1.1 root 692: int step_pulse;
693: int dr;
1.1.1.3 root 694:
1.1.1.10! root 695: lastselected = selected;
1.1 root 696: selected = (data >> 3) & 15;
1.1.1.10! root 697: if (selected != lastselected)
! 698: not_ready = 1;
1.1.1.3 root 699: side = 1 - ((data >> 2) & 1);
700:
1.1 root 701: direction = (data >> 1) & 1;
702: step_pulse = data & 1;
703: if (step != step_pulse) {
704: step = step_pulse;
1.1.1.7 root 705: if (step == 0) {
706: for (dr = 0; dr < 4; dr++) {
1.1 root 707: if (!(selected & (1 << dr))) {
1.1.1.4 root 708: drive_step (floppy + dr);
1.1 root 709: }
710: }
711: }
712: }
1.1.1.7 root 713: for (dr = 0; dr < 4; dr++) {
1.1.1.10! root 714: if (!(selected & (1 << dr)) && (lastselected & (1 << dr))) {
1.1.1.7 root 715: drive_motor (floppy + dr, data >> 7);
1.1 root 716: }
717: }
718: for (dr = 0; dr < 4; dr++) {
1.1.1.7 root 719: floppy[dr].state = (!(selected & (1 << dr))) | !floppy[dr].motoroff;
1.1.1.8 root 720: update_drive_gui (dr);
1.1 root 721: }
722: }
723:
1.1.1.4 root 724: uae_u8 DISK_status (void)
1.1 root 725: {
1.1.1.3 root 726: uae_u8 st = 0x3c;
1.1 root 727: int dr;
1.1.1.3 root 728:
1.1.1.7 root 729: for (dr = 0; dr < 4; dr++) {
1.1.1.3 root 730: drive *drv = floppy + dr;
1.1 root 731: if (!(selected & (1 << dr))) {
1.1.1.7 root 732: if (drive_running (drv)) {
1.1.1.10! root 733: if (drv->dskready && ! not_ready)
1.1.1.7 root 734: st &= ~0x20;
1.1.1.10! root 735: not_ready = 0;
1.1.1.7 root 736: } else if (!drv->disabled) {
737: st &= ~0x20; /* report drive ID */
1.1 root 738: }
1.1.1.3 root 739:
1.1.1.7 root 740: if (drive_track0 (drv)) {
741: st &= ~0x10;
742: }
743: if (drive_writeprotected (drv)) {
744: st &= ~8;
745: }
1.1.1.3 root 746: if (drv->dskchange) {
747: /*printf("changed bit set: %d\n",dr); */
748: st &= ~0x4;
749: if (drv->dskchange > 1)
750: drv->dskchange--;
751: }
1.1 root 752: }
753: }
754: return st;
755: }
756:
1.1.1.7 root 757: #define MAX_DISK_WORDS_PER_LINE 50 /* depends on floppy_speed */
758:
759: #define DISK_INDEXSYNC 1
760: #define DISK_WORDSYNC 2
761:
762: static uae_u16 dskbytr_tab[MAX_DISK_WORDS_PER_LINE * 2 + 1];
763: static uae_u8 dskbytr_cycle[MAX_DISK_WORDS_PER_LINE * 2 + 1];
764: static uae_u16 dskdatr_tab[MAX_DISK_WORDS_PER_LINE + 1];
765: static uae_u8 dskdatr_cycle[MAX_DISK_WORDS_PER_LINE + 1];
766: static uae_u32 dma_tab[MAX_DISK_WORDS_PER_LINE + 1];
767: static uae_u8 disk_sync[MAXHPOS];
768: static int disk_sync_cycle;
769: static int indexsync_last_cycle;
770: static int dskdmaen, dsklength;
771: static uae_u16 dsksync;
772: static uae_u32 dskpt;
773:
774: static void disk_dmafinished (void)
775: {
776: INTREQ (0x8002);
777: dskdmaen = 0;
778: }
779:
780: static void disk_events (int last)
781: {
782: eventtab[ev_disk].active = 0;
783: for (disk_sync_cycle = last; disk_sync_cycle < MAXHPOS; disk_sync_cycle++) {
784: if (disk_sync[disk_sync_cycle]) {
1.1.1.10! root 785: eventtab[ev_disk].oldcycles = get_cycles ();
! 786: eventtab[ev_disk].evtime = get_cycles () + (disk_sync_cycle - last) * CYCLE_UNIT;
1.1.1.7 root 787: eventtab[ev_disk].active = 1;
788: events_schedule ();
789: return;
1.1 root 790: }
791: }
792: }
793:
1.1.1.7 root 794: extern void cia_diskindex (void);
1.1.1.3 root 795:
1.1.1.7 root 796: void DISK_handler (void)
797: {
798: eventtab[ev_disk].active = 0;
799: if (disk_sync[disk_sync_cycle] & DISK_WORDSYNC) {
800: INTREQ (0x9000);
801: indexsync_last_cycle = disk_sync_cycle + ((floppy_speed + 255) >> 8);
802: }
803: if (disk_sync[disk_sync_cycle] & DISK_INDEXSYNC) {
804: cia_diskindex ();
805: }
806: disk_sync[disk_sync_cycle] = 0;
807: disk_events (disk_sync_cycle);
808: }
1.1.1.3 root 809:
1.1.1.7 root 810: static int syncfound, dmaon, word, bitoffset;
1.1 root 811:
1.1.1.7 root 812: /* Always carried through to the next line. */
813: static int disk_hpos;
1.1.1.2 root 814:
1.1.1.7 root 815: /* emulate disk write dma for full horizontal line */
816: static void disk_doupdate_write (drive * drv)
817: {
818: int hpos = disk_hpos;
819: while (hpos < (MAXHPOS << 8)) {
820: drv->mfmpos++;
821: drv->mfmpos %= drv->tracklen;
822: if (!drv->mfmpos) {
823: disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
824: disk_events (0);
825: }
826: if ((dmacon & 0x210) == 0x210 && dskdmaen == 3) {
827: bitoffset++;
828: bitoffset &= 15;
829: if (!bitoffset) {
830: drv->bigmfmbuf[drv->mfmpos >> 4] = get_word (dskpt);
831: dskpt += 2;
832: dsklength--;
833: if (dsklength == 0) {
834: disk_dmafinished ();
835: drive_write_data (drv);
836: }
1.1 root 837: }
838: }
1.1.1.7 root 839: hpos += drv->trackspeed;
1.1 root 840: }
1.1.1.7 root 841: disk_hpos = hpos - (MAXHPOS << 8);
1.1 root 842: }
843:
1.1.1.7 root 844: /* get one bit from MFM bit stream */
845: static uae_u16 getonebit (uae_u16 * mfmbuf, int mfmpos, uae_u16 word)
1.1 root 846: {
1.1.1.7 root 847: uae_u16 *buf;
1.1 root 848:
1.1.1.7 root 849: buf = &mfmbuf[mfmpos >> 4];
850: word <<= 1;
851: word |= (buf[0] & (1 << (15 - (mfmpos & 15)))) ? 1 : 0;
852: return word;
1.1 root 853: }
854:
1.1.1.7 root 855: /* emulate disk read dma for full horizontal line */
856: static void disk_doupdate_read (drive * drv)
857: {
858: int hpos = disk_hpos;
859: int is_sync = 0, dmaon;
860: int j = 0, l = 0, k = 0;
861:
862: while (hpos < (MAXHPOS << 8)) {
863: word = getonebit (drv->bigmfmbuf, drv->mfmpos, word);
864: drv->mfmpos++;
865: drv->mfmpos %= drv->tracklen;
866: if (!drv->mfmpos) {
867: disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
868: is_sync = 1;
869: }
870: bitoffset++;
871: bitoffset &= 15;
872: if (bitoffset == 0 && (!(adkcon & 0x400) || syncfound))
873: dmaon = 1;
874: else
875: dmaon = 0;
876: if (word == dsksync) {
877: if ((adkcon & 0x400) == 0x400 && ! syncfound) {
878: syncfound = 1;
879: bitoffset = 0;
880: }
881: disk_sync[hpos >> 8] |= DISK_WORDSYNC;
882: is_sync = 1;
883: }
884: if (dmaon) {
885: dma_tab[j++] = word;
886: if (j == MAX_DISK_WORDS_PER_LINE - 1) {
887: write_log ("Bug: Disk DMA buffer overflow!\n");
888: j--;
889: }
890: }
891: if (bitoffset == 0 || bitoffset == 8) {
892: dskbytr_tab[k] = (word & 0xff) | 0x8000;
893: dskbytr_cycle[k++] = hpos >> 8;
894: if (bitoffset == 0) {
895: dskdatr_tab[l] = word;
896: dskdatr_cycle[l++] = hpos >> 8;
897: }
898: }
899: hpos += drv->trackspeed;
900: }
901: dma_tab[j] = 0xffffffff;
902: if (is_sync)
903: disk_events (0);
904: dskbytr_cycle[k] = 255;
905: dskdatr_cycle[l] = 255;
906:
907: disk_hpos = hpos - (MAXHPOS << 8);
908: }
909:
910: /* disk DMA fetch happens on real Amiga at the beginning of next horizontal line
911: (cycles 9, 11 and 13 according to hardware manual) We transfer all DMA'd
912: data at cycle 0. I don't think any program cares about this small difference.
913: */
914: static void dodmafetch (void)
1.1 root 915: {
1.1.1.7 root 916: int i;
917:
918: i = 0;
919: while (dma_tab[i] != 0xffffffff && dskdmaen == 2 && (dmacon & 0x210) == 0x210) {
920: put_word (dskpt, dma_tab[i]);
921: dskpt += 2;
922: dsklength--;
923: if (dsklength == 0) {
924: disk_dmafinished ();
925: break;
926: }
927: i++;
928: }
929: dma_tab[0] = 0xffffffff;
1.1 root 930: }
931:
1.1.1.7 root 932: static void DISK_start (void)
1.1.1.6 root 933: {
934: int dr;
1.1.1.7 root 935:
1.1.1.6 root 936: for (dr = 0; dr < 4; dr++) {
1.1.1.7 root 937: drive *drv = &floppy[dr];
938: if (!(selected & (1 << dr))) {
939: int tr = drv->cyl * 2 + side;
940: trackid *ti = drv->trackdata + tr;
941:
942: drive_fill_bigbuf (drv);
943: if (dskdmaen == 3) {
944: drv->tracklen = FLOPPY_WRITE_LEN * 8 * 2;
945: drv->trackspeed = floppy_speed;
946: }
947: /* Ugh. A nasty hack. Assume ADF_EXT1 tracks are always read
948: from the start. */
949: if (ti->type == TRACK_RAW1)
950: drv->mfmpos = 0;
951: drv->mfmpos %= drv->tracklen;
1.1.1.6 root 952: }
953: }
1.1.1.7 root 954: syncfound = 0;
955: dmaon = 0;
956: word = 0;
957: bitoffset = 0;
958: dma_tab[0] = 0xffffffff;
1.1.1.6 root 959: }
960:
1.1.1.7 root 961: static int linecounter;
962:
963: void DISK_update (void)
1.1 root 964: {
965: int dr;
1.1.1.7 root 966:
1.1.1.6 root 967: for (dr = 0; dr < 4; dr++) {
1.1.1.7 root 968: drive *drv = &floppy[dr];
969: drv->mfmpos_hsync = drv->mfmpos;
970: }
971: if (linecounter) {
972: linecounter--;
973: if (! linecounter)
974: disk_dmafinished ();
975: return;
976: }
977:
978: dodmafetch ();
979: indexsync_last_cycle = -1;
980:
981: for (dr = 0; dr < 4; dr++) {
982: drive *drv = &floppy[dr];
983: if (drv->motoroff)
984: continue;
985: if (selected & (1 << dr)) {
986: drv->mfmpos += (MAXHPOS << 8) / drv->trackspeed;
987: drv->mfmpos %= drv->tracklen;
988: continue;
1.1 root 989: }
1.1.1.7 root 990: if (dskdmaen == 3)
991: disk_doupdate_write (drv);
992: else
993: disk_doupdate_read (drv);
994: return;
1.1 root 995: }
996: }
1.1.1.6 root 997:
1.1.1.7 root 998: void DSKLEN (uae_u16 v, int hpos)
1.1.1.6 root 999: {
1.1.1.7 root 1000: if (v & 0x8000) {
1001: dskdmaen = dskdmaen == 1 ? 2 : 1;
1002: } else {
1003: /* Megalomania does this */
1004: #if 0
1005: if (dskdmaen == 2)
1006: write_log ("warning: Disk read DMA aborted, %d words left\n", dsklength);
1007: #endif
1008: if (dskdmaen == 3)
1009: write_log ("warning: Disk write DMA aborted, %d words left\n", dsklength);
1010: dskdmaen = 0;
1011: }
1012: dsklength = v & 0x3fff;
1013: if (dskdmaen <= 1)
1014: return;
1015: if (v & 0x4000)
1016: dskdmaen = 3;
1017: #ifdef DISK_DEBUG
1018: {
1019: int dr;
1020: for (dr = 0; dr < 4; dr++) {
1021: drive *drv = &floppy[dr];
1022: if (drv->motoroff)
1023: continue;
1024: if ((selected & (1 << dr)) == 0)
1025: break;
1026: }
1027: if (dr == 4)
1028: write_log ("disk DMA started, but no drive ready!\n");
1029: else
1030: write_log ("disk %s DMA started for %d words (%08.8X) sync=%04.4X track %d\n",
1031: dskdmaen == 3 ? "write" : "read", dsklength, dskpt,
1032: (adkcon & 0x400) ? dsksync : 0xffff,
1033: floppy[dr].cyl * 2 + side);
1034: }
1035: #endif
1036: /* Megalomania does not work if DSKLEN write is delayed to next horizontal line,
1037: also it seems some copy protections require this fix */
1038: DISK_start ();
1.1.1.6 root 1039:
1.1.1.7 root 1040: /* Try to make floppy access from Kickstart faster. */
1041: if (dskdmaen != 2)
1042: return;
1043: {
1044: int dr;
1045: uaecptr pc = m68k_getpc ();
1046: if ((pc & 0xF80000) != 0xF80000)
1047: return;
1048: for (dr = 0; dr < 4; dr++) {
1049: drive *drv = &floppy[dr];
1050: if (drv->motoroff)
1051: continue;
1052: if ((selected & (1 << dr)) == 0) {
1053: int pos = drv->mfmpos & ~15;
1054: int i;
1055:
1056: if (adkcon & 0x400) {
1057: for (i = 0; i < drv->tracklen; i += 16) {
1058: pos += 16;
1059: pos %= drv->tracklen;
1060: if (drv->bigmfmbuf[pos >> 4] == dsksync)
1061: break;
1062: }
1063: if (i >= drv->tracklen)
1064: return;
1065: }
1066: while (dsklength-- > 0) {
1067: put_word (dskpt, drv->bigmfmbuf[pos >> 4]);
1068: dskpt += 2;
1069: pos += 16;
1070: pos %= drv->tracklen;
1.1.1.6 root 1071: }
1.1.1.7 root 1072: INTREQ (0x9000);
1073: linecounter = 2;
1074: dskdmaen = 0;
1075: return;
1.1.1.6 root 1076: }
1077: }
1.1.1.7 root 1078: }
1.1.1.6 root 1079: }
1080:
1.1.1.7 root 1081: /* this unoptimized code should be enough (DSKBYTR and DSKDATR are used very rarely) */
1082:
1083: uae_u16 DSKBYTR (int hpos)
1.1.1.6 root 1084: {
1.1.1.7 root 1085: uae_u16 v;
1086: int i;
1087:
1088: i = 0;
1089: while (hpos > dskbytr_cycle[i])
1090: i++;
1091: v = dskbytr_tab[i];
1092: if (indexsync_last_cycle >= 0 && indexsync_last_cycle <= hpos)
1093: v |= 0x1000;
1094: dskbytr_tab[i] &= ~0x8000;
1095: if (dskdmaen && (dmacon & 0x210) == 0x210)
1096: v |= 0x4000;
1097: if (dskdmaen == 3)
1098: v |= 0x2000;
1099: return v;
1100: }
1101:
1102: uae_u16 DSKDATR (int hpos)
1103: {
1104: int i;
1105:
1106: i = 0;
1107: while (hpos > dskdatr_cycle[i])
1108: i++;
1109: return dskdatr_tab[i];
1110: }
1111:
1112: void DSKSYNC (uae_u16 v)
1113: {
1114: dsksync = v;
1115: }
1116:
1117: void DSKDAT (uae_u16 v)
1118: {
1119: static int count = 0;
1120: if (count < 5) {
1121: count++;
1122: write_log ("DSKDAT written. Not good.");
1123: if (count == 5)
1124: write_log ("(further messages suppressed)");
1125:
1126: write_log ("\n");
1.1.1.6 root 1127: }
1128: }
1.1.1.7 root 1129: void DSKPTH (uae_u16 v)
1130: {
1131: dskpt = (dskpt & 0xffff) | ((uae_u32) v << 16);
1132: }
1.1.1.6 root 1133:
1.1.1.7 root 1134: void DSKPTL (uae_u16 v)
1.1.1.6 root 1135: {
1.1.1.7 root 1136: dskpt = (dskpt & ~0xffff) | (v);
1.1.1.6 root 1137: }
1138:
1.1.1.7 root 1139: void DISK_init (void)
1140: {
1141: int i;
1142:
1143: dma_tab[0] = 0xffffffff;
1144: dskbytr_cycle[0] = 255;
1145: dskdatr_cycle[0] = 255;
1146: indexsync_last_cycle = -1;
1147:
1.1.1.8 root 1148: for (i = 0; i < 4; i++) {
1.1.1.7 root 1149: if (!drive_insert (floppy + i, i, currprefs.df[i]))
1150: disk_eject (i);
1.1.1.8 root 1151: }
1.1.1.7 root 1152: if (disk_empty (0))
1153: write_log ("No disk in drive 0.\n");
1154: }
1155:
1.1.1.8 root 1156: void DISK_reset (void)
1157: {
1158: int i;
1159: disk_hpos = 0;
1160: for (i = 0; i < 4; i++) {
1161: floppy[i].disabled = 0;
1162: if (i >= currprefs.nr_floppies)
1163: floppy[i].disabled = 1;
1164: }
1165: }
1166:
1.1.1.7 root 1167: void dumpdisk (void)
1168: {
1169: int i;
1170: for (i = 0; i < 4; i++) {
1171: drive *drv = &floppy[i];
1172: printf ("Drive %d: motor %s cylinder %2d selected %d\n", i, drv->motoroff ? "off" : " on", drv->cyl, selected & (1 << i));
1173: }
1174: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.