|
|
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 "readcpu.h"
26: #include "newcpu.h"
27: #include "xwin.h"
28: #include "osemu.h"
29: #include "execlib.h"
30:
1.1.1.3 root 31: #define FLOPPY_GAP_LEN 360
1.1 root 32:
1.1.1.3 root 33: #define FLOPPY_SPEED 4
1.1 root 34:
1.1.1.3 root 35: uae_u16* mfmwrite;
36: static uae_u16 mfmwrbuffer[16384]; /* space for maximum disk DMA transfer */
1.1 root 37:
38: static int side, direction, step;
1.1.1.3 root 39: static uae_u8 selected = 15;
1.1 root 40: static int dskready;
41:
42: typedef struct {
1.1.1.3 root 43: uae_u16 sync;
44: uae_u16 len;
45: uae_u32 offs;
1.1 root 46: } trackid;
47:
1.1.1.2 root 48: #define MAX_TRACKS 328
49:
1.1 root 50: typedef enum { ADF_NORMAL, ADF_EXT1 } drive_filetype;
51: typedef struct {
52: FILE *diskfile;
53: drive_filetype filetype;
1.1.1.2 root 54: trackid trackdata[MAX_TRACKS];
1.1.1.3 root 55: unsigned int buffered_cyl, buffered_side;
56: unsigned int cyl;
57: int side;
1.1 root 58: int motoroff;
59: int wrprot;
1.1.1.3 root 60: uae_u16 bigmfmbuf[0x4000];
1.1 root 61: int tracklen;
62: unsigned long last_cycles;
63: int mfmpos;
1.1.1.2 root 64: unsigned int num_tracks, num_secs;
1.1.1.3 root 65: /* dskchange is set to a small number when a disk is removed. At a step
66: * impulse, it is reset if there is a new disk in the drive or counted
67: * down to 1 if the drive contains a disk. DISK_check_change will only
68: * insert a new disk when dskchange is 1, or if the dskchange_time timer
69: * expires. The last condition can happen if AmigaOS isn't running and a
70: * game/demo doesn't use the step motor to check for a new disk.
71: */
72: int dskchange;
73: int dskchange_time;
1.1 root 74: } drive;
75:
76: drive floppy[4];
77:
1.1.1.4 ! root 78: static void drive_fill_bigbuf (drive *drv);
1.1 root 79:
1.1.1.3 root 80: FILE *DISK_validate_filename (const char *fname, int leave_open, int *wrprot)
1.1 root 81: {
1.1.1.4 ! root 82: FILE *f = zfile_open (fname, "r+b");
1.1.1.3 root 83: if (f) {
84: if (wrprot)
85: *wrprot = 0;
1.1 root 86: } else {
1.1.1.3 root 87: if (wrprot)
88: *wrprot = 1;
1.1.1.4 ! root 89: f = zfile_open (fname, "rb");
1.1 root 90: }
1.1.1.3 root 91: if (!leave_open)
1.1.1.4 ! root 92: zfile_close (f);
1.1.1.3 root 93: return f;
94: }
95:
1.1.1.4 ! root 96: static int drive_insert (drive *drv, int dnum, const char *fname)
1.1.1.3 root 97: {
98: unsigned char buffer[10];
99:
100: drv->diskfile = DISK_validate_filename (fname, 1, &drv->wrprot);
101: if (drv->diskfile == 0)
102: return 0;
103:
104: strncpy (currprefs.df[dnum], fname, 255);
105: currprefs.df[dnum][255] = 0;
106: strncpy (changed_prefs.df[dnum], fname, 255);
107: changed_prefs.df[dnum][255] = 0;
1.1 root 108: gui_filename(dnum, fname);
1.1.1.3 root 109:
1.1.1.4 ! root 110: fread (buffer, sizeof(char), 8, drv->diskfile);
1.1.1.3 root 111: if (strncmp((char *)buffer,"UAE--ADF",8) == 0) {
1.1 root 112: int offs = 160*4+8;
113: int i;
1.1.1.3 root 114:
115: drv->filetype = ADF_EXT1;
1.1.1.2 root 116: drv->num_tracks = 160;
117: drv->num_secs = 11;
1.1.1.3 root 118:
1.1 root 119: drv->wrprot = 1; /* write to adf_ext1 not implemented */
120: for(i=0; i<160; i++) {
121: fread(buffer, 4, 1, drv->diskfile);
122: drv->trackdata[i].sync = buffer[0]*256 + buffer[1];
123: drv->trackdata[i].len = buffer[2]*256 + buffer[3];
124: drv->trackdata[i].offs = offs;
125: offs += drv->trackdata[i].len;
126: }
127: } else {
1.1.1.2 root 128: unsigned int i;
1.1.1.3 root 129:
130: drv->filetype = ADF_NORMAL;
1.1.1.2 root 131:
1.1.1.4 ! root 132: fseek (drv->diskfile,0,SEEK_END);
! 133: i = ftell (drv->diskfile);
! 134: fseek (drv->diskfile,0,SEEK_SET);
1.1.1.3 root 135:
1.1.1.2 root 136: /* High-density disk? */
137: if (i >= 160*22*512)
138: drv->num_tracks = i / (512*(drv->num_secs = 22));
139: else
140: drv->num_tracks = i / (512*(drv->num_secs = 11));
1.1.1.3 root 141:
1.1.1.2 root 142: if (drv->num_tracks > MAX_TRACKS)
1.1.1.3 root 143: write_log ("Your diskfile is too big!\n");
1.1.1.2 root 144: for(i = 0; i < drv->num_tracks; i++) {
145: drv->trackdata[i].len = 512 * drv->num_secs;
1.1 root 146: drv->trackdata[i].sync = 0;
1.1.1.2 root 147: drv->trackdata[i].offs = i * 512 * drv->num_secs;
1.1 root 148: }
149: }
1.1.1.3 root 150: drv->buffered_side = 2; /* will force read */
151: return 1;
1.1 root 152: }
153:
1.1.1.4 ! root 154: static int drive_empty (drive *drv)
1.1.1.2 root 155: {
1.1.1.3 root 156: return drv->diskfile == 0;
1.1.1.2 root 157: }
158:
1.1.1.4 ! root 159: static void drive_step (drive *drv)
1.1 root 160: {
1.1.1.3 root 161: if (!drive_empty(drv))
162: drv->dskchange = 0;
163: else if (drv->dskchange > 1) {
164: /* printf("Stepping...\n");
165: drv->dskchange--;*/
166: }
1.1 root 167: if (direction) {
1.1.1.3 root 168: if (drv->cyl) drv->cyl--;
1.1 root 169: } else {
1.1.1.3 root 170: if (drv->cyl < drv->num_tracks/2) drv->cyl++;
1.1 root 171: }
172: }
173:
174:
1.1.1.4 ! root 175: static int drive_track0 (drive *drv)
1.1 root 176: {
1.1.1.3 root 177: return drv->cyl == 0;
1.1 root 178: }
179:
1.1.1.4 ! root 180: static int drive_writeprotected (drive *drv)
1.1 root 181: {
1.1.1.3 root 182: return drv->wrprot || drv->diskfile == NULL;
1.1 root 183: }
184:
1.1.1.4 ! root 185: static int drive_running (drive *drv)
1.1 root 186: {
1.1.1.3 root 187: return !drv->motoroff;
1.1 root 188: }
189:
1.1.1.4 ! root 190: static void drive_motor (drive *drv, int off)
1.1 root 191: {
192: if (drv->motoroff && !off) {
193: drv->last_cycles = cycles;
194: drv->mfmpos = 0;
195: eventtab[ev_diskindex].active = 1;
196: if (drv->tracklen)
197: eventtab[ev_diskindex].evtime = FLOPPY_SPEED * drv->tracklen + cycles;
198: else
199: eventtab[ev_diskindex].evtime = cycles + 1000;
200: eventtab[ev_diskindex].oldcycles = cycles;
201: } else if (off)
202: eventtab[ev_diskindex].active = 0;
203: drv->motoroff = off;
1.1.1.4 ! root 204: events_schedule ();
1.1 root 205: }
206:
207: static void drive_fill_bigbuf(drive *drv)
208: {
1.1.1.3 root 209: int tr = drv->cyl*2 + side;
210:
1.1.1.2 root 211: if (!drv->diskfile) {
212: drv->tracklen = 10;
213: memset (drv->bigmfmbuf,0xaa,drv->tracklen*2);
214: return;
215: }
1.1.1.3 root 216: if (drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
217: return;
218:
219: /* if (drv->num_tracks <= tr) {
220: write_log ("Access beyond end of floppy image!\n");
221: }*/
1.1 root 222:
223: if (drv->trackdata[tr].sync == 0) {
224: /* Normal AmigaDOS format track */
1.1.1.2 root 225: unsigned int sec;
226: drv->tracklen = drv->num_secs*544 + FLOPPY_GAP_LEN;
227: memset(drv->bigmfmbuf,0xaa,FLOPPY_GAP_LEN*2);
228:
229: for (sec = 0; sec < drv->num_secs; sec++) {
1.1.1.3 root 230: uae_u8 secbuf[544];
1.1 root 231: int i;
1.1.1.3 root 232: uae_u16 *mfmbuf = drv->bigmfmbuf + 544*sec + FLOPPY_GAP_LEN;
233: uae_u32 deven,dodd;
234: uae_u32 hck=0,dck=0;
235:
1.1 root 236: secbuf[0] = secbuf[1] = 0x00;
237: secbuf[2] = secbuf[3] = 0xa1;
238: secbuf[4] = 0xff;
239: secbuf[5] = tr;
240: secbuf[6] = sec;
1.1.1.2 root 241: secbuf[7] = drv->num_secs-sec;
1.1 root 242:
243: for(i = 8; i < 24; i++)
244: secbuf[i] = 0;
1.1.1.3 root 245:
1.1.1.4 ! root 246: fseek (drv->diskfile,
! 247: drv->trackdata[tr].offs + sec*512,
! 248: SEEK_SET);
! 249: fread (&secbuf[32],1,512,drv->diskfile);
1.1.1.3 root 250:
1.1 root 251: mfmbuf[0] = mfmbuf[1] = 0xaaaa;
252: mfmbuf[2] = mfmbuf[3] = 0x4489;
1.1.1.3 root 253:
254: deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
1.1 root 255: | (secbuf[6] << 8) | (secbuf[7]));
256: dodd = deven >> 1;
257: deven &= 0x55555555; dodd &= 0x55555555;
1.1.1.3 root 258:
1.1 root 259: mfmbuf[4] = dodd >> 16;
260: mfmbuf[5] = dodd;
1.1.1.3 root 261: mfmbuf[6] = deven>> 16;
1.1 root 262: mfmbuf[7] = deven;
1.1.1.3 root 263:
1.1 root 264: for (i = 8; i < 48; i++)
265: mfmbuf[i] = 0;
266: for (i = 0; i < 512; i += 4){
267: deven = ((secbuf[i+32] << 24) | (secbuf[i+33] << 16)
268: | (secbuf[i+34] << 8) | (secbuf[i+35]));
269: dodd = deven >> 1;
270: deven &= 0x55555555; dodd &= 0x55555555;
1.1.1.4 ! root 271: mfmbuf[(i>>1) + 32] = dodd >> 16;
! 272: mfmbuf[(i>>1) + 33] = dodd;
! 273: mfmbuf[(i>>1) + 256 + 32] = deven >> 16;
! 274: mfmbuf[(i>>1) + 256 + 33] = deven;
1.1 root 275: }
1.1.1.3 root 276:
1.1 root 277: for(i = 4; i < 24; i += 2)
278: hck ^= (mfmbuf[i] << 16) | mfmbuf[i+1];
1.1.1.3 root 279:
1.1 root 280: deven = dodd = hck; dodd >>= 1;
281: mfmbuf[24] = dodd >> 16; mfmbuf[25] = dodd;
1.1.1.4 ! root 282: mfmbuf[26] = deven >> 16; mfmbuf[27] = deven;
1.1.1.3 root 283:
1.1 root 284: for(i = 32; i < 544; i += 2)
285: dck ^= (mfmbuf[i] << 16) | mfmbuf[i+1];
1.1.1.3 root 286:
1.1 root 287: deven = dodd = dck; dodd >>= 1;
288: mfmbuf[28] = dodd >> 16; mfmbuf[29] = dodd;
1.1.1.4 ! root 289: mfmbuf[30] = deven >> 16; mfmbuf[31] = deven;
1.1 root 290: }
291: } else {
292: int i;
293: drv->tracklen = drv->trackdata[tr].len/2 + 1;
294: drv->bigmfmbuf[0] = drv->trackdata[tr].sync;
295: fseek(drv->diskfile, drv->trackdata[tr].offs, SEEK_SET);
1.1.1.3 root 296: fread((char *)(drv->bigmfmbuf + 1), 1, drv->trackdata[tr].len, drv->diskfile);
1.1 root 297: for (i = 0; i < drv->trackdata[tr].len/2; i++) {
1.1.1.3 root 298: uae_u16 *mfm = drv->bigmfmbuf + i + 1;
299: uae_u8 *data = (uae_u8 *)mfm;
300:
1.1 root 301: *mfm = 256 * *data + *(data+1);
302: }
303: }
1.1.1.3 root 304: drv->buffered_side = side;
305: drv->buffered_cyl = drv->cyl;
1.1 root 306: drv->last_cycles = cycles;
307: drv->mfmpos = 0;
308: }
309:
1.1.1.4 ! root 310: static int drive_get_data (drive *drv, uae_u16 *mfm, uae_u16 *byt)
1.1 root 311: {
312: int offset,mfmpos;
1.1.1.3 root 313:
314: drive_fill_bigbuf(drv);
1.1 root 315: offset = (cycles - drv->last_cycles) / FLOPPY_SPEED;
316: mfmpos = (drv->mfmpos + offset) % drv->tracklen;
317: drv->last_cycles += offset*FLOPPY_SPEED;
318: drv->mfmpos = mfmpos;
319: *mfm = drv->bigmfmbuf[mfmpos];
320: return offset > 0;
321: }
322:
323: #define MFMMASK 0x55555555
1.1.1.4 ! root 324: static __inline__ uae_u32 getmfmlong (uae_u16* mbuf)
1.1 root 325: {
326: return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK;
327: }
328:
1.1.1.4 ! root 329: static void drive_write_data (drive *drv, uae_u16 *mbuf, int length)
1.1 root 330: {
331: int i, secwritten = 0;
1.1.1.3 root 332: uae_u32 odd, even, chksum, id, dlong;
333: uae_u8* secdata;
334: uae_u8 secbuf[544];
335: uae_u16 *mend = mbuf + length;
336:
1.1.1.4 ! root 337: if (drive_writeprotected (drv))
1.1.1.3 root 338: return;
339:
1.1.1.4 ! root 340: drive_fill_bigbuf (drv);
1.1 root 341: mend -= (4 + 16 + 8 + 512);
342: while (length > 0) {
343: int trackoffs;
1.1.1.3 root 344:
1.1 root 345: do {
346: while (*mbuf++ != 0x4489) {
1.1.1.4 ! root 347: if (mbuf >= mend)
! 348: return;
1.1 root 349: }
350: } while (*mbuf++ != 0x4489);
1.1.1.3 root 351:
1.1.1.4 ! root 352: odd = getmfmlong (mbuf);
! 353: even = getmfmlong (mbuf + 2);
1.1.1.3 root 354: mbuf += 4;
1.1 root 355: id = (odd << 1) | even;
1.1.1.3 root 356:
1.1 root 357: trackoffs = (id & 0xff00) >> 8;
358: if (trackoffs > 10) {
1.1.1.4 ! root 359: printf ("Disk write: weird sector number %d\n", trackoffs);
1.1 root 360: continue;
361: }
362: chksum = odd ^ even;
1.1.1.4 ! root 363: for (i = 0; i < 4; i++) {
1.1 root 364: odd = getmfmlong(mbuf);
365: even = getmfmlong(mbuf+8);
366: mbuf += 2;
1.1.1.3 root 367:
1.1 root 368: dlong = (odd << 1) | even;
1.1.1.4 ! root 369: if (dlong)
! 370: secwritten = -200;
1.1 root 371: chksum ^= odd ^ even;
372: } /* could check here if the label is nonstandard */
373: mbuf += 8;
1.1.1.4 ! root 374: odd = getmfmlong (mbuf); even = getmfmlong (mbuf+2); mbuf += 4;
! 375: if (((odd << 1) | even) != chksum
! 376: || ((id & 0x00ff0000) >> 16) != drv->cyl*2 + side)
! 377: {
1.1.1.3 root 378: write_log ("Disk write: checksum error on sector header\n");
1.1 root 379: continue;
380: }
381: odd = getmfmlong(mbuf); even = getmfmlong(mbuf+2); mbuf += 4;
382: chksum = (odd << 1) | even;
383: secdata = secbuf + 32;
384: for (i=0; i<128; i++) {
385: odd = getmfmlong(mbuf); even = getmfmlong(mbuf+256); mbuf += 2;
386: dlong = (odd << 1) | even;
387: *secdata++ = dlong >> 24; *secdata++ = (dlong >> 16) & 0xff;
388: *secdata++ = dlong >> 8; *secdata++ = dlong;
389: chksum ^= odd ^ even;
390: }
391: mbuf += 256;
392: if (chksum) {
1.1.1.3 root 393: write_log ("Disk write: data checksum error\n");
1.1 root 394: continue;
395: }
396: secwritten++;
1.1.1.4 ! root 397: fseek (drv->diskfile,
! 398: drv->trackdata[drv->cyl*2 + side].offs + trackoffs*512,
! 399: SEEK_SET);
! 400: fwrite (secbuf+32, sizeof (uae_u8), 512, drv->diskfile);
1.1 root 401: }
1.1.1.3 root 402: drv->buffered_side = 2; /* will force read */
403:
404: if (secwritten == 0)
405: write_log ("Disk write in unsupported format\n");
1.1 root 406: if (secwritten < 0)
1.1.1.3 root 407: write_log ("Disk write: sector labels ignored\n");
1.1 root 408: }
409:
410:
1.1.1.4 ! root 411: static void drive_eject (drive *drv)
1.1 root 412: {
1.1.1.4 ! root 413: if (! drive_empty (drv))
! 414: zfile_close (drv->diskfile);
1.1.1.3 root 415:
416: drv->dskchange = 4;
417: drv->dskchange_time = 20;
418: /* printf("setting changed bit %d\n", drv-floppy);*/
1.1 root 419: drv->diskfile = 0;
420: }
421:
1.1.1.3 root 422: /* We use this function if we have no Kickstart ROM.
1.1 root 423: * No error checking - we trust our luck. */
1.1.1.3 root 424: void DISK_ersatz_read (int tr, int sec, uaecptr dest)
1.1 root 425: {
1.1.1.3 root 426: uae_u8 *dptr = get_real_address(dest);
427: fseek (floppy[0].diskfile, floppy[0].trackdata[tr].offs + sec*512, SEEK_SET);
428: fread (dptr, 1, 512, floppy[0].diskfile);
1.1 root 429: }
430:
1.1.1.4 ! root 431: void disk_eject (int num)
1.1 root 432: {
433: gui_filename(num, "");
434: drive_eject(floppy + num);
1.1.1.3 root 435: *currprefs.df[num] = *changed_prefs.df[num] = 0;
1.1 root 436: }
437:
1.1.1.4 ! root 438: void disk_insert (int num, const char *name)
1.1 root 439: {
440: /* just to be sure */
1.1.1.4 ! root 441: drive_eject (floppy + num);
! 442: drive_insert (floppy + num, num, name);
1.1 root 443: }
444:
1.1.1.3 root 445: void DISK_check_change (void)
446: {
447: int i;
448: static int count = 0;
449: count++;
450:
451: for (i = 0; i < 4; i++) {
452: if (strcmp (currprefs.df[i], changed_prefs.df[i]) != 0) {
453: if (currprefs.df[i][0] != '\0') {
454: drive_eject(floppy + i);
455: currprefs.df[i][0] = '\0';
456: gui_filename(i, "");
457: } else if (floppy[i].dskchange == 1) {
458: /* In theory, it should work without the dskchange test.
459: * In practice, it doesn't. */
460: drive_insert (floppy + i, i, changed_prefs.df[i]);
461: } else if (floppy[i].dskchange > 1 && floppy[i].dskchange_time > 0) {
462: /* Force the dskchange bit to go to 1 after a given timeout */
463: if (--floppy[i].dskchange_time == 0) {
464: floppy[i].dskchange = 1;
465: }
466: }
467: }
468: }
469: }
470:
1.1.1.4 ! root 471: int disk_empty (int num)
1.1 root 472: {
1.1.1.4 ! root 473: return drive_empty (floppy + num);
1.1 root 474: }
475:
1.1.1.4 ! root 476: void DISK_init (void)
1.1 root 477: {
1.1.1.3 root 478: int i;
479: for (i = 0; i < 4; i++)
480: if (!drive_insert (floppy+i, i, currprefs.df[i]))
481: disk_eject (i);
482:
483: if (disk_empty (0))
484: write_log ("No disk in drive 0.\n");
1.1 root 485: }
486:
487: static int ledstate[] = { 0,0,0,0 };
488:
1.1.1.4 ! root 489: void DISK_select (uae_u8 data)
1.1 root 490: {
491: int step_pulse;
492: int dr;
1.1.1.3 root 493:
494: if (selected != ((data >> 3) & 15))
1.1 root 495: dskready = 0;
496: selected = (data >> 3) & 15;
1.1.1.3 root 497: side = 1 - ((data >> 2) & 1);
498:
1.1 root 499: direction = (data >> 1) & 1;
500: step_pulse = data & 1;
501: if (step != step_pulse) {
502: step = step_pulse;
503: if (step == 0){
504: for (dr = 0; dr < 4; dr++){
505: if (!(selected & (1 << dr))) {
1.1.1.4 ! root 506: drive_step (floppy + dr);
1.1 root 507: }
508: }
509: }
510: }
511: for (dr = 0; dr < 4; dr++){
512: if (!(selected & (1<<dr))) {
513: drive_motor(floppy + dr, data >> 7);
514: }
515: }
516: for (dr = 0; dr < 4; dr++) {
517: int state = (!(selected & (1<<dr))) | !floppy[dr].motoroff;
1.1.1.3 root 518: if (state == ledstate[dr])
519: continue;
520: gui_led (dr + 1, state);
1.1 root 521: ledstate[dr] = state;
1.1.1.3 root 522: gui_ledstate &= ~(1 << (dr + 1));
523: gui_ledstate |= state << (dr + 1);
1.1 root 524: }
525: }
526:
1.1.1.4 ! root 527: uae_u8 DISK_status (void)
1.1 root 528: {
1.1.1.3 root 529: uae_u8 st = 0x3c;
1.1 root 530: int dr;
1.1.1.3 root 531:
1.1 root 532: for (dr = 0; dr < 4; dr++){
1.1.1.3 root 533: drive *drv = floppy + dr;
1.1 root 534: if (!(selected & (1 << dr))) {
1.1.1.3 root 535: if (drive_running(drv)){
1.1 root 536: if (dskready) st &= ~0x20;
537: dskready = 1;
538: } else {
539: st &= ~0x20; /* report drive ID */
540: }
1.1.1.3 root 541:
542: if (drive_track0 (drv)) { st &= ~0x10; }
543: if (drive_writeprotected (drv)) { st &= ~8; }
544: if (drv->dskchange) {
545: /*printf("changed bit set: %d\n",dr); */
546: st &= ~0x4;
547: if (drv->dskchange > 1)
548: drv->dskchange--;
549: }
1.1 root 550: }
551: }
552: return st;
553: }
554:
1.1.1.4 ! root 555: int DISK_GetData (uae_u16 *mfm, uae_u16 *byt)
1.1 root 556: {
557: int dr;
558: for (dr = 0; dr < 4; dr++){
559: if (!(selected & (1<<dr))) {
560: return drive_get_data (floppy + dr, mfm, byt);
561: }
562: }
563: return 0;
564: }
565:
1.1.1.3 root 566: static uae_u16 mfm_read_buffer[0x4000];
1.1 root 567: static int mfm_read_length;
568:
1.1.1.4 ! root 569: int DISK_PrepareReadMFM (int length, uae_u16 sync, int use_sync)
1.1 root 570: {
571: int dr;
1.1.1.3 root 572:
1.1 root 573: mfm_read_length = 0;
1.1.1.3 root 574:
1.1 root 575: for (dr = 0; dr < 4; dr++) {
576: if (!(selected & (1<<dr))) {
577: int time = 0;
1.1.1.3 root 578: uae_u16 *mfmp = mfm_read_buffer;
1.1 root 579: drive *drv = floppy + dr;
580: int offset,mfmpos;
581:
1.1.1.4 ! root 582: drive_fill_bigbuf (drv);
1.1.1.2 root 583:
1.1 root 584: offset = (cycles - drv->last_cycles) / FLOPPY_SPEED;
585: mfmpos = (drv->mfmpos + offset) % drv->tracklen;
586: drv->last_cycles += offset*FLOPPY_SPEED;
587: drv->mfmpos = mfmpos;
588: mfmpos++; mfmpos %= drv->tracklen;
589: while (drv->bigmfmbuf[mfmpos] != sync && mfmpos != drv->mfmpos && use_sync)
590: mfmpos = (mfmpos + 1) % drv->tracklen, time++;
1.1.1.2 root 591:
1.1 root 592: if (drv->bigmfmbuf[mfmpos] != sync && use_sync) {
1.1.1.3 root 593: write_log ("warning: sync not found on disk read\n");
1.1 root 594: return 0;
595: } else
596: mfmpos++;
1.1.1.2 root 597:
1.1 root 598: mfm_read_length = length;
599:
600: while (length--) {
601: *mfmp++ = drv->bigmfmbuf[mfmpos];
602: mfmpos = (mfmpos + 1) % drv->tracklen;
603: time++;
604: }
605:
606: return time*FLOPPY_SPEED;
607: }
608: }
1.1.1.3 root 609: return 0;
1.1 root 610: }
611:
1.1.1.4 ! root 612: int DISK_ReadMFM (uaecptr target)
1.1 root 613: {
614: int i;
1.1.1.3 root 615: uae_u8 *mfmp = get_real_address(target);
616:
1.1 root 617: if (!chipmem_bank.check(target, mfm_read_length * 2)) {
1.1.1.3 root 618: write_log ("warning: Bad disk DMA read pointer\n");
1.1 root 619: return 0;
620: }
621:
622: for (i = 0; i < mfm_read_length; i++) {
623: *mfmp++ = mfm_read_buffer[i] >> 8;
624: *mfmp++ = mfm_read_buffer[i];
625: }
626: return 1;
627: }
628:
1.1.1.4 ! root 629: void DISK_InitWrite (void)
1.1 root 630: {
631: mfmwrite = mfmwrbuffer;
632: }
633:
1.1.1.4 ! root 634: void DISK_WriteData (int length)
1.1 root 635: {
636: int dr;
1.1.1.4 ! root 637: for (dr = 0; dr < 4; dr++){
1.1 root 638: if (!(selected & (1<<dr))) {
639: drive_write_data(floppy + dr, mfmwrbuffer, length);
640: }
641: }
642: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.