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

1.1     ! root        1:  /* 
        !             2:   * UAE - The Un*x Amiga Emulator
        !             3:   * 
        !             4:   * Floppy disk emulation
        !             5:   *
        !             6:   * (c) 1995 Bernd Schmidt, Hannu Rummukainen
        !             7:   */
        !             8: 
        !             9: #include "sysconfig.h"
        !            10: #include "sysdeps.h"
        !            11: 
        !            12: #include "config.h"
        !            13: #include "options.h"
        !            14: #include "memory.h"
        !            15: #include "events.h"
        !            16: #include "custom.h"
        !            17: #include "ersatz.h"
        !            18: #include "disk.h"
        !            19: #include "gui.h"
        !            20: #include "zfile.h"
        !            21: 
        !            22: #define FLOPPY_SPEED 5
        !            23: 
        !            24: UWORD* mfmwrite;
        !            25: static UWORD mfmwrbuffer[16384]; /* space for maximum disk DMA transfer */
        !            26: 
        !            27: static int side, direction, step;
        !            28: static UBYTE selected = 15;
        !            29: static int dskready;
        !            30: static int need_read = 0;
        !            31: 
        !            32: typedef struct {
        !            33:     UWORD sync;
        !            34:     UWORD len;
        !            35:     ULONG offs;
        !            36: } trackid;
        !            37: 
        !            38: typedef enum { ADF_NORMAL, ADF_EXT1 } drive_filetype;
        !            39: typedef struct {
        !            40:     FILE *diskfile;
        !            41:     drive_filetype filetype;
        !            42:     trackid trackdata[164];
        !            43:     unsigned int track;
        !            44:     int motoroff;
        !            45:     int wrprot;
        !            46:     UWORD bigmfmbuf[0x2000];
        !            47:     int tracklen;
        !            48:     unsigned long last_cycles;
        !            49:     int mfmpos;
        !            50: } drive;
        !            51: 
        !            52: drive floppy[4];
        !            53: 
        !            54: static void drive_fill_bigbuf(drive *drv);
        !            55: 
        !            56: static void drive_insert(drive *drv, int dnum, char *fname)
        !            57: {
        !            58:     unsigned char buffer[10];
        !            59:     
        !            60:     drv->diskfile = zfile_open(fname,"r+b");
        !            61:     if (drv->diskfile) {
        !            62:        drv->wrprot = 0;
        !            63:     } else {
        !            64:        drv->wrprot = 1;
        !            65:        drv->diskfile = zfile_open(fname, "rb");
        !            66:        if (!drv->diskfile) {
        !            67:            gui_filename(dnum, "");
        !            68:            return;
        !            69:        }
        !            70:     }
        !            71:     switch (dnum) {
        !            72:      case 0: strcpy((char *)df0, fname); break;
        !            73:      case 1: strcpy((char *)df1, fname); break;
        !            74:      case 2: strcpy((char *)df2, fname); break;
        !            75:      case 3: strcpy((char *)df3, fname); break;
        !            76:      case 4: break;
        !            77:     }
        !            78:     gui_filename(dnum, fname);
        !            79:     fread(buffer,sizeof(char),8,drv->diskfile);
        !            80:     if (strncmp((char *)buffer,"UAE--ADF",8) == 0) {   
        !            81:        int offs = 160*4+8;
        !            82:        int i;
        !            83:        
        !            84:        drv->filetype = ADF_EXT1;
        !            85:        drv->wrprot = 1; /* write to adf_ext1 not implemented */
        !            86:        for(i=0; i<160; i++) {
        !            87:            fread(buffer, 4, 1, drv->diskfile);
        !            88:            drv->trackdata[i].sync = buffer[0]*256 + buffer[1];
        !            89:            drv->trackdata[i].len = buffer[2]*256 + buffer[3];
        !            90:            drv->trackdata[i].offs = offs;
        !            91:            offs += drv->trackdata[i].len;
        !            92:        }
        !            93:     } else {
        !            94:        int i;
        !            95:        drv->filetype = ADF_NORMAL;
        !            96:        for(i=0; i<160; i++) {
        !            97:            drv->trackdata[i].len = 512 * 11;
        !            98:            drv->trackdata[i].sync = 0;
        !            99:            drv->trackdata[i].offs = i*512*11;
        !           100:        }
        !           101:     }
        !           102:     drive_fill_bigbuf(drv);
        !           103: }
        !           104: 
        !           105: static void drive_step(drive *drv)
        !           106: {
        !           107:     if (direction) {
        !           108:        if (drv->track) drv->track--;
        !           109:     } else {
        !           110:        if (drv->track < 85) drv->track++;
        !           111:     }
        !           112:     drive_fill_bigbuf(drv);
        !           113: }
        !           114: 
        !           115: 
        !           116: static int drive_track0(drive *drv) 
        !           117: {
        !           118:     return drv->track == 0; 
        !           119: }
        !           120: 
        !           121: static int drive_writeprotected(drive *drv) 
        !           122: {
        !           123:     return drv->wrprot || drv->diskfile == NULL; 
        !           124: }
        !           125: 
        !           126: static int drive_empty(drive *drv)
        !           127: {
        !           128:     return drv->diskfile == 0; 
        !           129: }
        !           130: 
        !           131: static int drive_running(drive *drv)
        !           132: {
        !           133:     return !drv->motoroff; 
        !           134: }
        !           135: 
        !           136: static void drive_motor(drive *drv, int off)
        !           137: {
        !           138:     if (drv->motoroff && !off) {
        !           139:        drv->last_cycles = cycles;
        !           140:        drv->mfmpos = 0;
        !           141:        eventtab[ev_diskindex].active = 1;
        !           142:        if (drv->tracklen)
        !           143:            eventtab[ev_diskindex].evtime = FLOPPY_SPEED * drv->tracklen + cycles;
        !           144:        else
        !           145:            eventtab[ev_diskindex].evtime = cycles + 1000;
        !           146:        eventtab[ev_diskindex].oldcycles = cycles;
        !           147:     } else if (off)
        !           148:        eventtab[ev_diskindex].active = 0;
        !           149:     drv->motoroff = off;
        !           150:     events_schedule();
        !           151:        
        !           152: }
        !           153: 
        !           154: static void drive_fill_bigbuf(drive *drv)
        !           155: {
        !           156:     int tr = drv->track*2 + side;
        !           157:     
        !           158:     if (!drv->diskfile) return;
        !           159:     
        !           160:     if (drv->trackdata[tr].sync == 0) {
        !           161:        /* Normal AmigaDOS format track */
        !           162:        int sec;
        !           163:        drv->tracklen = 11*544 + 300;
        !           164:        memset(drv->bigmfmbuf,0xaa,300*2);
        !           165:            
        !           166:        for (sec = 0; sec < 11; sec++) {
        !           167:            UBYTE secbuf[544];
        !           168:            int i;
        !           169:            UWORD *mfmbuf = drv->bigmfmbuf + 544*sec + 300;
        !           170:            ULONG deven,dodd;
        !           171:            ULONG hck=0,dck=0;
        !           172:            
        !           173:            secbuf[0] = secbuf[1] = 0x00;
        !           174:            secbuf[2] = secbuf[3] = 0xa1;
        !           175:            secbuf[4] = 0xff;
        !           176:            secbuf[5] = tr;
        !           177:            secbuf[6] = sec;
        !           178:            secbuf[7] = 11-sec;
        !           179: 
        !           180:            for(i = 8; i < 24; i++)
        !           181:                secbuf[i] = 0;
        !           182:     
        !           183:            fseek(drv->diskfile,
        !           184:                  drv->trackdata[tr].offs + sec*512, 
        !           185:                  SEEK_SET);
        !           186:            fread(&secbuf[32],1,512,drv->diskfile);
        !           187:     
        !           188:            mfmbuf[0] = mfmbuf[1] = 0xaaaa;
        !           189:            mfmbuf[2] = mfmbuf[3] = 0x4489;
        !           190:     
        !           191:            deven = ((secbuf[4] << 24) | (secbuf[5] << 16) 
        !           192:                     | (secbuf[6] << 8) | (secbuf[7]));
        !           193:            dodd = deven >> 1;
        !           194:            deven &= 0x55555555; dodd &= 0x55555555;
        !           195:     
        !           196:            mfmbuf[4] = dodd >> 16;
        !           197:            mfmbuf[5] = dodd;
        !           198:            mfmbuf[6] = deven>> 16; 
        !           199:            mfmbuf[7] = deven;
        !           200:     
        !           201:            for (i = 8; i < 48; i++)
        !           202:                mfmbuf[i] = 0;
        !           203:            for (i = 0; i < 512; i += 4){
        !           204:                deven = ((secbuf[i+32] << 24) | (secbuf[i+33] << 16)
        !           205:                         | (secbuf[i+34] << 8) | (secbuf[i+35]));
        !           206:                dodd = deven >> 1;
        !           207:                deven &= 0x55555555; dodd &= 0x55555555;
        !           208:                mfmbuf[(i>>1)+32] = dodd >> 16;
        !           209:                mfmbuf[(i>>1)+33] = dodd;
        !           210:                mfmbuf[(i>>1)+256+32] = deven >> 16;
        !           211:                mfmbuf[(i>>1)+256+33] = deven;
        !           212:            }
        !           213:     
        !           214:            for(i = 4; i < 24; i += 2)
        !           215:                hck ^= (mfmbuf[i] << 16) | mfmbuf[i+1];
        !           216:     
        !           217:            deven = dodd = hck; dodd >>= 1;
        !           218:            mfmbuf[24] = dodd >> 16; mfmbuf[25] = dodd;
        !           219:            mfmbuf[26] = deven>> 16; mfmbuf[27] = deven;
        !           220:     
        !           221:            for(i = 32; i < 544; i += 2)
        !           222:                dck ^= (mfmbuf[i] << 16) | mfmbuf[i+1];
        !           223:     
        !           224:            deven = dodd = dck; dodd >>= 1;
        !           225:            mfmbuf[28] = dodd >> 16; mfmbuf[29] = dodd;
        !           226:            mfmbuf[30] = deven>> 16; mfmbuf[31] = deven;
        !           227:        }
        !           228:     } else {
        !           229:        int i;
        !           230:        drv->tracklen = drv->trackdata[tr].len/2 + 1;
        !           231:        drv->bigmfmbuf[0] = drv->trackdata[tr].sync;
        !           232:        fseek(drv->diskfile, drv->trackdata[tr].offs, SEEK_SET);
        !           233:        fread(drv->bigmfmbuf+1, 1, drv->trackdata[tr].len, drv->diskfile);
        !           234:        for (i = 0; i < drv->trackdata[tr].len/2; i++) {
        !           235:            UWORD *mfm = drv->bigmfmbuf + i + 1;
        !           236:            UBYTE *data = (UBYTE *)mfm;
        !           237:            
        !           238:            *mfm = 256 * *data + *(data+1);
        !           239:        }
        !           240:     }
        !           241:     need_read = 0;
        !           242:     drv->last_cycles = cycles;
        !           243:     drv->mfmpos = 0;
        !           244: }
        !           245: 
        !           246: static int drive_get_data(drive *drv, UWORD *mfm, UWORD *byt)
        !           247: {
        !           248:     int offset,mfmpos;
        !           249:     if (need_read) {
        !           250:        drive_fill_bigbuf(drv);
        !           251:     }
        !           252:     offset = (cycles - drv->last_cycles) / FLOPPY_SPEED;
        !           253:     mfmpos = (drv->mfmpos + offset) % drv->tracklen;
        !           254:     drv->last_cycles += offset*FLOPPY_SPEED;
        !           255:     drv->mfmpos = mfmpos;
        !           256:     *mfm = drv->bigmfmbuf[mfmpos];
        !           257:     return offset > 0;
        !           258: }
        !           259: 
        !           260: #define MFMMASK 0x55555555
        !           261: static __inline__ ULONG getmfmlong(UWORD* mbuf) 
        !           262: {
        !           263:     return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK;
        !           264: }
        !           265: 
        !           266: static void drive_write_data(drive *drv, UWORD *mbuf, int length)
        !           267: {
        !           268:     int i, secwritten = 0;
        !           269:     ULONG odd, even, chksum, id, dlong;
        !           270:     UBYTE* secdata;
        !           271:     UBYTE secbuf[544];
        !           272:     UWORD *mend = mbuf + length;
        !           273:     
        !           274:     if (drive_writeprotected(drv)) return;
        !           275:     mend -= (4 + 16 + 8 + 512);
        !           276:     while (length > 0) {
        !           277:        int trackoffs;
        !           278:        
        !           279:        do {
        !           280:            while (*mbuf++ != 0x4489) {
        !           281:                if (mbuf >= mend) return;
        !           282:            }
        !           283:        } while (*mbuf++ != 0x4489);
        !           284:        
        !           285:        odd = getmfmlong(mbuf);
        !           286:        even = getmfmlong(mbuf+2);
        !           287:        mbuf += 4;      
        !           288:        id = (odd << 1) | even;
        !           289:        
        !           290:        trackoffs = (id & 0xff00) >> 8;
        !           291:        if (trackoffs > 10) {
        !           292:            printf("Disk write: weird sector number %d\n", trackoffs);
        !           293:            continue;
        !           294:        }
        !           295:        chksum = odd ^ even;
        !           296:        for (i=0; i<4; i++) {
        !           297:            odd = getmfmlong(mbuf);
        !           298:            even = getmfmlong(mbuf+8);
        !           299:            mbuf += 2;
        !           300:            
        !           301:            dlong = (odd << 1) | even;
        !           302:            if (dlong)  secwritten = -200;
        !           303:            chksum ^= odd ^ even;
        !           304:        }  /* could check here if the label is nonstandard */
        !           305:        mbuf += 8;
        !           306:        odd = getmfmlong(mbuf); even = getmfmlong(mbuf+2); mbuf += 4;
        !           307:        if ((((odd << 1) | even) != chksum) || 
        !           308:            (((id & 0x00ff0000) >> 16) != drv->track*2 + side)) {
        !           309:            printf("Disk write: checksum error on sector header\n");
        !           310:            continue;
        !           311:        }
        !           312:        odd = getmfmlong(mbuf); even = getmfmlong(mbuf+2); mbuf += 4;
        !           313:        chksum = (odd << 1) | even;
        !           314:        secdata = secbuf + 32;
        !           315:        for (i=0; i<128; i++) {
        !           316:            odd = getmfmlong(mbuf); even = getmfmlong(mbuf+256); mbuf += 2;
        !           317:            dlong = (odd << 1) | even;
        !           318:            *secdata++ = dlong >> 24; *secdata++ = (dlong >> 16) & 0xff;
        !           319:            *secdata++ = dlong >> 8; *secdata++ = dlong;
        !           320:            chksum ^= odd ^ even;
        !           321:        }
        !           322:        mbuf += 256;
        !           323:        if (chksum) {
        !           324:            printf("Disk write: data checksum error\n");
        !           325:            continue;
        !           326:        }
        !           327:        secwritten++;
        !           328:        fseek(drv->diskfile, 
        !           329:              drv->trackdata[drv->track*2 + side].offs + trackoffs*512,
        !           330:              SEEK_SET);
        !           331:        fwrite(secbuf+32, sizeof(UBYTE), 512, drv->diskfile);
        !           332:     }
        !           333:     need_read = 1;
        !           334:     
        !           335:     if (secwritten == 0) 
        !           336:        printf("Disk write in unsupported format\n");
        !           337:     if (secwritten < 0)
        !           338:        printf("Disk write: sector labels ignored\n");
        !           339: }
        !           340: 
        !           341: 
        !           342: static void drive_eject(drive *drv)
        !           343: {
        !           344:     if (!drive_empty(drv)) zfile_close(drv->diskfile);
        !           345:     drv->diskfile = 0;
        !           346: }
        !           347: 
        !           348: /* We use this function if we have no Kickstart ROM. 
        !           349:  * No error checking - we trust our luck. */
        !           350: void DISK_ersatz_read (int tr, int sec, CPTR dest)
        !           351: {
        !           352:     int i;
        !           353:     UBYTE *dptr = get_real_address(dest);
        !           354:     fseek(floppy[0].diskfile, floppy[0].trackdata[tr].offs + sec*512, SEEK_SET);
        !           355:     fread(dptr,1,512,floppy[0].diskfile);
        !           356: }
        !           357: 
        !           358: void disk_eject(int num)
        !           359: {
        !           360:     gui_filename(num, "");
        !           361:     drive_eject(floppy + num);
        !           362: }
        !           363: 
        !           364: void disk_insert(int num, char *name)
        !           365: {
        !           366:     /* just to be sure */
        !           367:     drive_eject(floppy + num);
        !           368:     drive_insert(floppy + num, num, name);
        !           369: }
        !           370: 
        !           371: int disk_empty(int num)
        !           372: {
        !           373:     return drive_empty(floppy + num);
        !           374: }
        !           375: 
        !           376: void DISK_init()
        !           377: {
        !           378:     drive_insert(floppy, 0, df0);
        !           379:     if (disk_empty(0))
        !           380:        fprintf(stderr, "No floppy in drive 0.\n");
        !           381:     drive_insert(floppy + 1, 1, df1);
        !           382:     drive_insert(floppy + 2, 2, df2);
        !           383:     drive_insert(floppy + 3, 3, df3);
        !           384: }
        !           385: 
        !           386: static int ledstate[] = { 0,0,0,0 };
        !           387: 
        !           388: void DISK_select(UBYTE data)
        !           389: {
        !           390:     int step_pulse;
        !           391:     int dr;
        !           392:     
        !           393:     if (selected != ((data >> 3) & 15)) 
        !           394:        dskready = 0;
        !           395:     selected = (data >> 3) & 15;
        !           396:     if (side != 1 - ((data >> 2) & 1)) {
        !           397:        side = 1 - ((data >> 2) & 1);
        !           398:        need_read = 1;
        !           399:     }
        !           400:     direction = (data >> 1) & 1;
        !           401:     step_pulse = data & 1;
        !           402:     if (step != step_pulse) {
        !           403:        step = step_pulse;
        !           404:        if (step == 0){
        !           405:            for (dr = 0; dr < 4; dr++){
        !           406:                if (!(selected & (1 << dr))) {
        !           407:                    drive_step(floppy + dr);
        !           408:                }
        !           409:            }
        !           410:        }
        !           411:     }
        !           412:     for (dr = 0; dr < 4; dr++){
        !           413:        if (!(selected & (1<<dr))) {
        !           414:            drive_motor(floppy + dr, data >> 7);
        !           415:        }
        !           416:     }
        !           417:     for (dr = 0; dr < 4; dr++) {
        !           418:        int state = (!(selected & (1<<dr))) | !floppy[dr].motoroff;
        !           419:        if (state != ledstate[dr])
        !           420:            gui_led (dr+1, state);
        !           421:        ledstate[dr] = state;
        !           422:     }
        !           423: }
        !           424: 
        !           425: UBYTE DISK_status()
        !           426: {
        !           427:     UBYTE st = 0x3c;
        !           428:     int dr;
        !           429:     
        !           430:     for (dr = 0; dr < 4; dr++){
        !           431:        if (!(selected & (1 << dr))) {
        !           432:            if (drive_running(floppy + dr)){
        !           433:                if (dskready) st &= ~0x20;
        !           434:                dskready = 1;
        !           435:            } else {
        !           436:                st &= ~0x20; /* report drive ID */
        !           437:            }
        !           438:                
        !           439:            if (drive_track0(floppy + dr)) { st &= ~0x10; }
        !           440:            if (drive_writeprotected(floppy + dr)) { st &= ~8; }
        !           441:            if (drive_empty(floppy + dr)) { st &= ~0x4; }
        !           442:        }
        !           443:     }
        !           444:     return st;
        !           445: }
        !           446: 
        !           447: int DISK_GetData(UWORD *mfm,UWORD *byt)
        !           448: {
        !           449:     int dr;
        !           450:     for (dr = 0; dr < 4; dr++){
        !           451:        if (!(selected & (1<<dr))) {
        !           452:            return drive_get_data (floppy + dr, mfm, byt);
        !           453:        }
        !           454:     }
        !           455:     return 0;
        !           456: }
        !           457: 
        !           458: static UWORD mfm_read_buffer[0x4000];
        !           459: static int mfm_read_length;
        !           460: 
        !           461: int DISK_PrepareReadMFM(int length, UWORD sync, int use_sync)
        !           462: {
        !           463:     int dr;
        !           464:     
        !           465:     mfm_read_length = 0;
        !           466:     
        !           467:     for (dr = 0; dr < 4; dr++) {
        !           468:        if (!(selected & (1<<dr))) {
        !           469:            int time = 0;
        !           470:            UWORD *mfmp = mfm_read_buffer;
        !           471:            drive *drv = floppy + dr;
        !           472:            int offset,mfmpos;
        !           473: 
        !           474:            if (need_read) {
        !           475:                drive_fill_bigbuf(drv);
        !           476:            }
        !           477:            
        !           478:            offset = (cycles - drv->last_cycles) / FLOPPY_SPEED;
        !           479:            mfmpos = (drv->mfmpos + offset) % drv->tracklen;
        !           480:            drv->last_cycles += offset*FLOPPY_SPEED;
        !           481:            drv->mfmpos = mfmpos;
        !           482:            mfmpos++; mfmpos %= drv->tracklen;
        !           483:            while (drv->bigmfmbuf[mfmpos] != sync && mfmpos != drv->mfmpos && use_sync)
        !           484:                mfmpos = (mfmpos + 1) % drv->tracklen, time++;
        !           485:            
        !           486:            if (drv->bigmfmbuf[mfmpos] != sync && use_sync) {
        !           487:                fprintf(stderr, "warning: sync not found on disk read\n");
        !           488:                return 0;
        !           489:            } else
        !           490:                mfmpos++;
        !           491:            
        !           492:            mfm_read_length = length;
        !           493: 
        !           494:            while (length--) {
        !           495:                *mfmp++ = drv->bigmfmbuf[mfmpos];
        !           496:                mfmpos = (mfmpos + 1) % drv->tracklen;
        !           497:                time++;
        !           498:            }
        !           499: 
        !           500:            return time*FLOPPY_SPEED;
        !           501:        }
        !           502:     }
        !           503:     return 0;    
        !           504: }
        !           505: 
        !           506: int DISK_ReadMFM(CPTR target)
        !           507: {
        !           508:     int i;
        !           509:     UBYTE *mfmp = get_real_address(target);
        !           510:     
        !           511:     if (!chipmem_bank.check(target, mfm_read_length * 2)) {
        !           512:        fprintf(stderr, "warning: Bad disk DMA read pointer\n");
        !           513:        return 0;
        !           514:     }
        !           515: 
        !           516:     for (i = 0; i < mfm_read_length; i++) {
        !           517:        *mfmp++ = mfm_read_buffer[i] >> 8;
        !           518:        *mfmp++ = mfm_read_buffer[i];
        !           519:     }
        !           520:     return 1;
        !           521: }
        !           522: 
        !           523: void DISK_InitWrite()
        !           524: {
        !           525:     mfmwrite = mfmwrbuffer;
        !           526: }
        !           527: 
        !           528: void DISK_WriteData(int length)
        !           529: {
        !           530:     int dr;
        !           531:     for (dr=0;dr<4;dr++){
        !           532:        if (!(selected & (1<<dr))) {
        !           533:            drive_write_data(floppy + dr, mfmwrbuffer, length);
        !           534:        }
        !           535:     }
        !           536: }

unix.superglobalmegacorp.com

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