--- uae/src/disk.c 2018/04/24 16:39:50 1.1.1.3 +++ uae/src/disk.c 2018/04/24 16:48:34 1.1.1.6 @@ -3,7 +3,7 @@ * * Floppy disk emulation * - * (c) 1995 Bernd Schmidt, Hannu Rummukainen + * Copyright 1995 Bernd Schmidt, Hannu Rummukainen */ #include @@ -15,8 +15,6 @@ #include "options.h" #include "threaddep/penguin.h" #include "memory.h" -#include "gensound.h" -#include "sounddep/sound.h" #include "events.h" #include "custom.h" #include "ersatz.h" @@ -32,7 +30,7 @@ #define FLOPPY_GAP_LEN 360 -#define FLOPPY_SPEED 4 +#define FLOPPY_SPEED 50 uae_u16* mfmwrite; static uae_u16 mfmwrbuffer[16384]; /* space for maximum disk DMA transfer */ @@ -60,6 +58,7 @@ typedef struct { int motoroff; int wrprot; uae_u16 bigmfmbuf[0x4000]; + int mfmbufpos; int tracklen; unsigned long last_cycles; int mfmpos; @@ -77,39 +76,40 @@ typedef struct { drive floppy[4]; -static void drive_fill_bigbuf(drive *drv); +static void drive_fill_bigbuf (drive *drv); FILE *DISK_validate_filename (const char *fname, int leave_open, int *wrprot) { - FILE *f = zfile_open(fname, "r+b"); + FILE *f = zfile_open (fname, "r+b"); if (f) { if (wrprot) *wrprot = 0; } else { if (wrprot) *wrprot = 1; - f = zfile_open(fname, "rb"); + f = zfile_open (fname, "rb"); } if (!leave_open) - fclose (f); + zfile_close (f); return f; } -static int drive_insert(drive *drv, int dnum, const char *fname) +static int drive_insert (drive *drv, int dnum, const char *fname) { unsigned char buffer[10]; drv->diskfile = DISK_validate_filename (fname, 1, &drv->wrprot); - if (drv->diskfile == 0) + if (drv->diskfile == 0) { + drv->tracklen = 2000; return 0; - + } strncpy (currprefs.df[dnum], fname, 255); currprefs.df[dnum][255] = 0; strncpy (changed_prefs.df[dnum], fname, 255); changed_prefs.df[dnum][255] = 0; gui_filename(dnum, fname); - fread(buffer, sizeof(char), 8, drv->diskfile); + fread (buffer, sizeof(char), 8, drv->diskfile); if (strncmp((char *)buffer,"UAE--ADF",8) == 0) { int offs = 160*4+8; int i; @@ -131,9 +131,9 @@ static int drive_insert(drive *drv, int drv->filetype = ADF_NORMAL; - fseek(drv->diskfile,0,SEEK_END); - i = ftell(drv->diskfile); - fseek(drv->diskfile,0,SEEK_SET); + fseek (drv->diskfile,0,SEEK_END); + i = ftell (drv->diskfile); + fseek (drv->diskfile,0,SEEK_SET); /* High-density disk? */ if (i >= 160*22*512) @@ -150,15 +150,16 @@ static int drive_insert(drive *drv, int } } drv->buffered_side = 2; /* will force read */ + drive_fill_bigbuf (drv); return 1; } -static int drive_empty(drive *drv) +static int drive_empty (drive *drv) { return drv->diskfile == 0; } -static void drive_step(drive *drv) +static void drive_step (drive *drv) { if (!drive_empty(drv)) drv->dskchange = 0; @@ -174,22 +175,22 @@ static void drive_step(drive *drv) } -static int drive_track0(drive *drv) +static int drive_track0 (drive *drv) { return drv->cyl == 0; } -static int drive_writeprotected(drive *drv) +static int drive_writeprotected (drive *drv) { return drv->wrprot || drv->diskfile == NULL; } -static int drive_running(drive *drv) +static int drive_running (drive *drv) { return !drv->motoroff; } -static void drive_motor(drive *drv, int off) +static void drive_motor (drive *drv, int off) { if (drv->motoroff && !off) { drv->last_cycles = cycles; @@ -203,7 +204,7 @@ static void drive_motor(drive *drv, int } else if (off) eventtab[ev_diskindex].active = 0; drv->motoroff = off; - events_schedule(); + events_schedule (); } static void drive_fill_bigbuf(drive *drv) @@ -211,7 +212,7 @@ static void drive_fill_bigbuf(drive *drv int tr = drv->cyl*2 + side; if (!drv->diskfile) { - drv->tracklen = 10; + drv->tracklen = 2000; memset (drv->bigmfmbuf,0xaa,drv->tracklen*2); return; } @@ -226,7 +227,7 @@ static void drive_fill_bigbuf(drive *drv /* Normal AmigaDOS format track */ unsigned int sec; drv->tracklen = drv->num_secs*544 + FLOPPY_GAP_LEN; - memset(drv->bigmfmbuf,0xaa,FLOPPY_GAP_LEN*2); + memset (drv->bigmfmbuf,0xaa,FLOPPY_GAP_LEN*2); for (sec = 0; sec < drv->num_secs; sec++) { uae_u8 secbuf[544]; @@ -245,10 +246,10 @@ static void drive_fill_bigbuf(drive *drv for(i = 8; i < 24; i++) secbuf[i] = 0; - fseek(drv->diskfile, - drv->trackdata[tr].offs + sec*512, - SEEK_SET); - fread(&secbuf[32],1,512,drv->diskfile); + fseek (drv->diskfile, + drv->trackdata[tr].offs + sec*512, + SEEK_SET); + fread (&secbuf[32],1,512,drv->diskfile); mfmbuf[0] = mfmbuf[1] = 0xaaaa; mfmbuf[2] = mfmbuf[3] = 0x4489; @@ -264,16 +265,16 @@ static void drive_fill_bigbuf(drive *drv mfmbuf[7] = deven; for (i = 8; i < 48; i++) - mfmbuf[i] = 0; + mfmbuf[i] = 0xaaaa; for (i = 0; i < 512; i += 4){ deven = ((secbuf[i+32] << 24) | (secbuf[i+33] << 16) | (secbuf[i+34] << 8) | (secbuf[i+35])); dodd = deven >> 1; deven &= 0x55555555; dodd &= 0x55555555; - mfmbuf[(i>>1)+32] = dodd >> 16; - mfmbuf[(i>>1)+33] = dodd; - mfmbuf[(i>>1)+256+32] = deven >> 16; - mfmbuf[(i>>1)+256+33] = deven; + mfmbuf[(i>>1) + 32] = dodd >> 16; + mfmbuf[(i>>1) + 33] = dodd; + mfmbuf[(i>>1) + 256 + 32] = deven >> 16; + mfmbuf[(i>>1) + 256 + 33] = deven; } for(i = 4; i < 24; i += 2) @@ -281,14 +282,14 @@ static void drive_fill_bigbuf(drive *drv deven = dodd = hck; dodd >>= 1; mfmbuf[24] = dodd >> 16; mfmbuf[25] = dodd; - mfmbuf[26] = deven>> 16; mfmbuf[27] = deven; + mfmbuf[26] = deven >> 16; mfmbuf[27] = deven; for(i = 32; i < 544; i += 2) dck ^= (mfmbuf[i] << 16) | mfmbuf[i+1]; deven = dodd = dck; dodd >>= 1; mfmbuf[28] = dodd >> 16; mfmbuf[29] = dodd; - mfmbuf[30] = deven>> 16; mfmbuf[31] = deven; + mfmbuf[30] = deven >> 16; mfmbuf[31] = deven; } } else { int i; @@ -309,26 +310,60 @@ static void drive_fill_bigbuf(drive *drv drv->mfmpos = 0; } -static int drive_get_data(drive *drv, uae_u16 *mfm, uae_u16 *byt) +/* Perform DMA for the time interval since the last call. */ +static int drive_update_reads (drive *drv, uaecptr *ptr, int *length, int *syncfound, int sync) { - int offset,mfmpos; + unsigned long maxbytes = (cycles - drv->last_cycles) * 2 / FLOPPY_SPEED; + unsigned long maxcount = maxbytes >> 1; + drv->last_cycles += maxcount * FLOPPY_SPEED; drive_fill_bigbuf(drv); - offset = (cycles - drv->last_cycles) / FLOPPY_SPEED; - mfmpos = (drv->mfmpos + offset) % drv->tracklen; - drv->last_cycles += offset*FLOPPY_SPEED; - drv->mfmpos = mfmpos; - *mfm = drv->bigmfmbuf[mfmpos]; - return offset > 0; + + if (! ptr) { + if (! drv->motoroff) + drv->mfmpos += maxcount; + drv->mfmpos %= drv->tracklen; + } else { + while (maxcount-- > 0 && *length > 0) { + unsigned int word; + if (drv->mfmpos > drv->tracklen) { + write_log ("Bug in disk code - mfmpos too large\n"); + drv->mfmpos = 0; + } + word = drv->bigmfmbuf[drv->mfmpos]; + if (*syncfound) { + put_word (*ptr, word); + (*ptr) += 2; + (*length)--; + } + if (word == sync) + *syncfound = 1; + if (! drv->motoroff) + drv->mfmpos++; + if (drv->mfmpos > drv->tracklen) + drv->mfmpos = 0; + } + } + return ! drv->motoroff && maxbytes >= 1; +} + +/* We assume that drive_update_reads has already been called. */ +static void drive_get_data (drive *drv, uae_u16 *mfm, uae_u16 *byt) +{ + *mfm = drv->bigmfmbuf[drv->mfmpos]; + if (cycles - drv->last_cycles > (FLOPPY_SPEED / 2)) + *byt = *mfm & 0xff; + else + *byt = (*mfm >> 8) & 0xff; } #define MFMMASK 0x55555555 -static __inline__ uae_u32 getmfmlong(uae_u16* mbuf) +STATIC_INLINE uae_u32 getmfmlong (uae_u16* mbuf) { return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK; } -static void drive_write_data(drive *drv, uae_u16 *mbuf, int length) +static void drive_write_data (drive *drv, uae_u16 *mbuf, int length) { int i, secwritten = 0; uae_u32 odd, even, chksum, id, dlong; @@ -336,44 +371,47 @@ static void drive_write_data(drive *drv, uae_u8 secbuf[544]; uae_u16 *mend = mbuf + length; - if (drive_writeprotected(drv)) + if (drive_writeprotected (drv)) return; - drive_fill_bigbuf(drv); + drive_fill_bigbuf (drv); mend -= (4 + 16 + 8 + 512); while (length > 0) { int trackoffs; do { while (*mbuf++ != 0x4489) { - if (mbuf >= mend) return; + if (mbuf >= mend) + return; } } while (*mbuf++ != 0x4489); - odd = getmfmlong(mbuf); - even = getmfmlong(mbuf+2); + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 2); mbuf += 4; id = (odd << 1) | even; trackoffs = (id & 0xff00) >> 8; if (trackoffs > 10) { - printf("Disk write: weird sector number %d\n", trackoffs); + write_log ("Disk write: weird sector number %d\n", trackoffs); continue; } chksum = odd ^ even; - for (i=0; i<4; i++) { + for (i = 0; i < 4; i++) { odd = getmfmlong(mbuf); even = getmfmlong(mbuf+8); mbuf += 2; dlong = (odd << 1) | even; - if (dlong) secwritten = -200; + if (dlong) + secwritten = -200; chksum ^= odd ^ even; } /* could check here if the label is nonstandard */ mbuf += 8; - odd = getmfmlong(mbuf); even = getmfmlong(mbuf+2); mbuf += 4; - if ((((odd << 1) | even) != chksum) || - (((id & 0x00ff0000) >> 16) != drv->cyl*2 + side)) { + odd = getmfmlong (mbuf); even = getmfmlong (mbuf+2); mbuf += 4; + if (((odd << 1) | even) != chksum + || ((id & 0x00ff0000) >> 16) != drv->cyl*2 + side) + { write_log ("Disk write: checksum error on sector header\n"); continue; } @@ -393,10 +431,10 @@ static void drive_write_data(drive *drv, continue; } secwritten++; - fseek(drv->diskfile, - drv->trackdata[drv->cyl*2 + side].offs + trackoffs*512, - SEEK_SET); - fwrite(secbuf+32, sizeof(uae_u8), 512, drv->diskfile); + fseek (drv->diskfile, + drv->trackdata[drv->cyl*2 + side].offs + trackoffs*512, + SEEK_SET); + fwrite (secbuf+32, sizeof (uae_u8), 512, drv->diskfile); } drv->buffered_side = 2; /* will force read */ @@ -407,10 +445,10 @@ static void drive_write_data(drive *drv, } -static void drive_eject(drive *drv) +static void drive_eject (drive *drv) { - if (!drive_empty(drv)) - zfile_close(drv->diskfile); + if (! drive_empty (drv)) + zfile_close (drv->diskfile); drv->dskchange = 4; drv->dskchange_time = 20; @@ -422,24 +460,23 @@ static void drive_eject(drive *drv) * No error checking - we trust our luck. */ void DISK_ersatz_read (int tr, int sec, uaecptr dest) { - int i; uae_u8 *dptr = get_real_address(dest); fseek (floppy[0].diskfile, floppy[0].trackdata[tr].offs + sec*512, SEEK_SET); fread (dptr, 1, 512, floppy[0].diskfile); } -void disk_eject(int num) +void disk_eject (int num) { gui_filename(num, ""); drive_eject(floppy + num); *currprefs.df[num] = *changed_prefs.df[num] = 0; } -void disk_insert(int num, const char *name) +void disk_insert (int num, const char *name) { /* just to be sure */ - drive_eject(floppy + num); - drive_insert(floppy + num, num, name); + drive_eject (floppy + num); + drive_insert (floppy + num, num, name); } void DISK_check_change (void) @@ -468,12 +505,12 @@ void DISK_check_change (void) } } -int disk_empty(int num) +int disk_empty (int num) { - return drive_empty(floppy + num); + return drive_empty (floppy + num); } -void DISK_init() +void DISK_init (void) { int i; for (i = 0; i < 4; i++) @@ -486,7 +523,7 @@ void DISK_init() static int ledstate[] = { 0,0,0,0 }; -void DISK_select(uae_u8 data) +void DISK_select (uae_u8 data) { int step_pulse; int dr; @@ -503,7 +540,7 @@ void DISK_select(uae_u8 data) if (step == 0){ for (dr = 0; dr < 4; dr++){ if (!(selected & (1 << dr))) { - drive_step(floppy + dr); + drive_step (floppy + dr); } } } @@ -524,7 +561,7 @@ void DISK_select(uae_u8 data) } } -uae_u8 DISK_status() +uae_u8 DISK_status (void) { uae_u8 st = 0x3c; int dr; @@ -552,21 +589,18 @@ uae_u8 DISK_status() return st; } -int DISK_GetData(uae_u16 *mfm,uae_u16 *byt) +void DISK_GetData (uae_u16 *mfm, uae_u16 *byt) { int dr; for (dr = 0; dr < 4; dr++){ if (!(selected & (1<last_cycles) / FLOPPY_SPEED; mfmpos = (drv->mfmpos + offset) % drv->tracklen; @@ -609,7 +643,7 @@ int DISK_PrepareReadMFM(int length, uae_ return 0; } -int DISK_ReadMFM(uaecptr target) +int DISK_ReadMFM (uaecptr target) { int i; uae_u8 *mfmp = get_real_address(target); @@ -625,18 +659,80 @@ int DISK_ReadMFM(uaecptr target) } return 1; } +#endif -void DISK_InitWrite() +void DISK_InitWrite (void) { mfmwrite = mfmwrbuffer; } -void DISK_WriteData(int length) +int DISK_update_reads (uaecptr *ptr, int *length, int *syncfound, int sync) { int dr; - for (dr=0;dr<4;dr++){ + for (dr = 0; dr < 4; dr++) { + if (!(selected & (1<mfmpos; + unsigned long missing = FLOPPY_SPEED - (cycles - drv->last_cycles); + unsigned long count = 0; + if (missing == 0) { + write_log ("bug in disk code: missing == 0\n"); + return; + } + + while (missing < cycle_limit) { + count += missing; + cycle_limit -= missing; + missing = FLOPPY_SPEED; + if (drv->bigmfmbuf[offs] == sync) { + eventtab[ev_disksync].active = 1; + eventtab[ev_disksync].oldcycles = cycles; + eventtab[ev_disksync].evtime = cycles + count; + events_schedule (); + } + offs++; + } + } + } +} + +/* Called when DMA gets restarted, so that we don't do DMA for the + parts of the track that went past us while DMA was off. */ +void DISK_reset_cycles (void) +{ + int dr; + for (dr = 0; dr < 4; dr++) { + drive *drv = floppy + dr; + unsigned long count = (cycles - drv->last_cycles) / FLOPPY_SPEED; + drv->mfmpos += count; + drv->mfmpos %= drv->tracklen; + drv->last_cycles += count * FLOPPY_SPEED; + } +} + +void DISK_StartRead () +{ + DISK_reset_cycles (); +} +