Annotation of uae/src/disk.c, revision 1.1.1.6

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.