Annotation of uae/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 <string.h>
        !            10: #include <stdio.h>
        !            11: 
        !            12: #include "config.h"
        !            13: #include "amiga.h"
        !            14: #include "options.h"
        !            15: #include "memory.h"
        !            16: #include "ersatz.h"
        !            17: #include "disk.h"
        !            18: 
        !            19: int indexpulse = 0;
        !            20: 
        !            21: UWORD* mfmwrite;
        !            22: static UWORD mfmwrbuffer[16384]; /* space for maximum disk DMA transfer */
        !            23: 
        !            24: static int side, direction, step;
        !            25: static UBYTE selected = 15;
        !            26: static bool dskready;
        !            27: static bool need_read = false;
        !            28: 
        !            29: typedef struct {
        !            30:     UWORD sync;
        !            31:     UWORD len;
        !            32:     ULONG offs;
        !            33: } trackid;
        !            34: 
        !            35: typedef enum { ADF_NORMAL, ADF_EXT1 } drive_filetype;
        !            36: typedef struct {
        !            37:     FILE *diskfile;
        !            38:     drive_filetype filetype;
        !            39:     trackid trackdata[164];
        !            40:     unsigned int track;
        !            41:     bool motoroff;
        !            42:     bool wrprot;
        !            43:     unsigned int trackoffs,insecpos;
        !            44:     bool secok;
        !            45:     UBYTE secbuf[544];
        !            46:     UWORD mfmbuf[544];
        !            47: } drive;
        !            48: 
        !            49: drive floppy[4];
        !            50: 
        !            51: static void drive_insert(drive *drv, char *fname)
        !            52: {
        !            53:     unsigned char buffer[10];
        !            54:     
        !            55:     drv->diskfile = fopen(fname,"r+b");
        !            56:     if (drv->diskfile) {
        !            57:        drv->wrprot = false;
        !            58:     } else {
        !            59:        drv->wrprot = true;
        !            60:        drv->diskfile = fopen(fname, "rb");
        !            61:        if (!drv->diskfile) return;
        !            62:     }
        !            63:     fread(buffer,sizeof(char),8,drv->diskfile);
        !            64:     if (strncmp((char *)buffer,"UAE--ADF",8) == 0) {   
        !            65:        int offs = 160*4+8;
        !            66:        int i;
        !            67:        
        !            68:        drv->filetype = ADF_EXT1;
        !            69:        drv->wrprot = true; /* write to adf_ext1 not implemented */
        !            70:        for(i=0; i<160; i++) {
        !            71:            fread(buffer, 4, 1, drv->diskfile);
        !            72:            drv->trackdata[i].sync = buffer[0]*256 + buffer[1];
        !            73:            drv->trackdata[i].len = buffer[2]*256 + buffer[3];
        !            74:            drv->trackdata[i].offs = offs;
        !            75:            offs += drv->trackdata[i].len;
        !            76:        }
        !            77:     } else {
        !            78:        int i;
        !            79:        drv->filetype = ADF_NORMAL;
        !            80:        for(i=0; i<160; i++) {
        !            81:            drv->trackdata[i].len = 512 * 11;
        !            82:            drv->trackdata[i].sync = 0;
        !            83:            drv->trackdata[i].offs = i*512*11;
        !            84:        }
        !            85:     }
        !            86: }
        !            87: 
        !            88: 
        !            89: static void drive_step(drive *drv)
        !            90: {
        !            91:     if (direction) {
        !            92:        if (drv->track) drv->track--;
        !            93:     } else {
        !            94:        if (drv->track < 85) drv->track++;
        !            95:     }
        !            96: }
        !            97: 
        !            98: 
        !            99: static bool drive_track0(drive *drv) 
        !           100: {
        !           101:     return drv->track == 0; 
        !           102: }
        !           103: 
        !           104: static bool drive_writeprotected(drive *drv) 
        !           105: {
        !           106:     return drv->wrprot || drv->diskfile == NULL; 
        !           107: }
        !           108: 
        !           109: static bool drive_empty(drive *drv)
        !           110: {
        !           111:     return drv->diskfile == 0; 
        !           112: }
        !           113: 
        !           114: static bool drive_running(drive *drv)
        !           115: {
        !           116:     return !drv->motoroff; 
        !           117: }
        !           118: 
        !           119: static void drive_index(drive *drv)
        !           120: {
        !           121:     drv->trackoffs = 0;
        !           122:     drv->insecpos = 0;
        !           123: }
        !           124: 
        !           125: static void drive_motor(drive *drv, bool off)
        !           126: {
        !           127:     if (drv->motoroff && !off) { 
        !           128:        drv->trackoffs = 0;
        !           129:        drv->insecpos = 0; 
        !           130:        drv->secok = false; 
        !           131:     }
        !           132:     drv->motoroff = off;
        !           133: }
        !           134: 
        !           135: static ULONG drive_getmfmulong(drive *drv, unsigned int offs)
        !           136: {
        !           137:     return (drv->mfmbuf[offs] << 16) | drv->mfmbuf[offs+1];
        !           138: }
        !           139: 
        !           140: static ULONG drive_getseculong(drive *drv, unsigned int offs)
        !           141: {
        !           142:     return ((drv->secbuf[offs] << 24) | (drv->secbuf[offs+1] << 16) 
        !           143:            | (drv->secbuf[offs+2] << 8) | (drv->secbuf[offs+3]));
        !           144: }
        !           145: 
        !           146: static void drive_readsec(drive *drv)
        !           147: {
        !           148:     ULONG deven,dodd;
        !           149:     ULONG hck=0,dck=0;
        !           150:     int i;
        !           151: 
        !           152:     if (!drv->diskfile) return;
        !           153:     
        !           154:     drv->secbuf[0] = drv->secbuf[1] = 0x00;
        !           155:     drv->secbuf[2] = drv->secbuf[3] = 0xa1;
        !           156:     drv->secbuf[4] = 0xff;
        !           157:     drv->secbuf[5] = drv->track*2 + side;
        !           158:     drv->secbuf[6] = drv->trackoffs;
        !           159:     drv->secbuf[7] = 11-drv->trackoffs;
        !           160:     
        !           161:     for(i = 8; i < 24; i++)
        !           162:        drv->secbuf[i] = 0;
        !           163:     
        !           164:     fseek(drv->diskfile, 
        !           165:          drv->trackdata[drv->track*2 + side].offs + drv->trackoffs*512, 
        !           166:          SEEK_SET);
        !           167:     fread(&drv->secbuf[32],sizeof(UBYTE),512,drv->diskfile);
        !           168:     
        !           169:     drv->mfmbuf[0] = drv->mfmbuf[1] = 0xaaaa;
        !           170:     drv->mfmbuf[2] = drv->mfmbuf[3] = 0x4489;
        !           171:     
        !           172:     deven = drive_getseculong(drv, 4); dodd = deven >> 1;
        !           173:     deven &= 0x55555555; dodd &= 0x55555555;
        !           174:     
        !           175:     drv->mfmbuf[4] = dodd >> 16;
        !           176:     drv->mfmbuf[5] = dodd;
        !           177:     drv->mfmbuf[6] = deven>> 16; 
        !           178:     drv->mfmbuf[7] = deven;
        !           179:     
        !           180:     for (i = 8; i < 48; i++)
        !           181:        drv->mfmbuf[i] = 0;
        !           182:     for (i = 0; i < 512; i += 4){
        !           183:        deven = drive_getseculong(drv, i + 32);
        !           184:        dodd = deven >> 1;
        !           185:        deven &= 0x55555555; dodd &= 0x55555555;
        !           186:        drv->mfmbuf[(i>>1)+32] = dodd >> 16;
        !           187:        drv->mfmbuf[(i>>1)+33] = dodd;
        !           188:        drv->mfmbuf[(i>>1)+256+32] = deven>> 16;
        !           189:        drv->mfmbuf[(i>>1)+256+33] = deven;
        !           190:     }
        !           191:     
        !           192:     for(i = 4; i < 24; i += 2)
        !           193:        hck ^= drive_getmfmulong(drv, i);
        !           194:     
        !           195:     deven = dodd = hck; dodd >>= 1;
        !           196:     drv->mfmbuf[24] = dodd >> 16; drv->mfmbuf[25] = dodd;
        !           197:     drv->mfmbuf[26] = deven>> 16; drv->mfmbuf[27] = deven;
        !           198:     
        !           199:     for(i = 32; i < 544; i += 2)
        !           200:        dck ^= drive_getmfmulong(drv, i);
        !           201:     
        !           202:     deven = dodd = dck; dodd >>= 1;
        !           203:     drv->mfmbuf[28] = dodd >> 16; drv->mfmbuf[29] = dodd;
        !           204:     drv->mfmbuf[30] = deven>> 16; drv->mfmbuf[31] = deven;
        !           205:     
        !           206:     drv->secok = true;
        !           207:     need_read = false;
        !           208:     drv->insecpos = 0;
        !           209: }
        !           210: 
        !           211: static void drive_get_data(drive *drv, UWORD *mfm, UWORD *byt)
        !           212: {
        !           213:     if (drv->trackdata[drv->track*2 + side].sync == 0) {
        !           214:        /* Normal AmigaDOS format track */
        !           215:        if (!drv->secok || need_read)
        !           216:            drive_readsec(drv);
        !           217:        *mfm = drv->mfmbuf[drv->insecpos]; 
        !           218:        *byt = drv->secbuf[drv->insecpos++];
        !           219:        
        !           220:        if (drv->insecpos == 544){
        !           221:            drv->insecpos = 0;
        !           222:            drv->secok = false;
        !           223:            if (++drv->trackoffs == 11)
        !           224:                drv->trackoffs = 0;
        !           225:        }
        !           226:     } else {
        !           227:        /* Raw MFM track */
        !           228:        if (drv->insecpos > drv->trackdata[drv->track*2+side].len) 
        !           229:            drv->insecpos = 0;
        !           230:        if (drv->insecpos == 0) {
        !           231:            *mfm = drv->trackdata[drv->track*2 + side].sync;
        !           232:        } else  {           
        !           233:            unsigned char data[2];
        !           234:            fseek(drv->diskfile, 
        !           235:                  drv->insecpos*2 - 2 + drv->trackdata[drv->track*2+side].offs, 
        !           236:                  SEEK_SET);
        !           237:            fread(data, 2, 1, drv->diskfile);
        !           238:            *mfm = data[0]*256 + data[1];
        !           239:            /* ??? how does this work? */
        !           240:            *byt = (data[0] & 0x55) | ((data[1] & 0x55)*2);
        !           241:        }
        !           242:        drv->insecpos++;
        !           243:     }
        !           244: }
        !           245: 
        !           246: #define MFMMASK 0x55555555
        !           247: static __inline__ ULONG getmfmlong(UWORD* mbuf) 
        !           248: {
        !           249:     return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK;
        !           250: }
        !           251: 
        !           252: static void drive_write_data(drive *drv, UWORD *mbuf, UWORD *mend)
        !           253: {
        !           254:     int i, secwritten = 0;
        !           255:     ULONG odd, even, chksum, id, dlong;
        !           256:     UBYTE* secdata;
        !           257:     
        !           258:     if (drive_writeprotected(drv)) return;
        !           259:     mend -= (4 + 16 + 8 + 512);
        !           260:     while (mbuf < mend) {
        !           261:        do {
        !           262:            while (*mbuf++ != 0x4489) {
        !           263:                if (mbuf >= mend) return;
        !           264:            }
        !           265:        } while (*mbuf++ != 0x4489);
        !           266:        
        !           267:        odd = getmfmlong(mbuf);
        !           268:        even = getmfmlong(mbuf+2);
        !           269:        mbuf += 4;      
        !           270:        id = (odd << 1) | even;
        !           271:        
        !           272:        drv->trackoffs = (id & 0xff00) >> 8;
        !           273:        if (drv->trackoffs > 10) {
        !           274:            printf("Disk write: weird sector number %d\n", drv->trackoffs);
        !           275:            continue;
        !           276:        }
        !           277:        chksum = odd ^ even;
        !           278:        for (i=0; i<4; i++) {
        !           279:            odd = getmfmlong(mbuf);
        !           280:            even = getmfmlong(mbuf+8);
        !           281:            mbuf += 2;
        !           282:            
        !           283:            dlong = (odd << 1) | even;
        !           284:            if (dlong)  secwritten = -200;
        !           285:            chksum ^= odd ^ even;
        !           286:        }  /* could check here if the label is nonstandard */
        !           287:        mbuf += 8;
        !           288:        odd = getmfmlong(mbuf); even = getmfmlong(mbuf+2); mbuf += 4;
        !           289:        if ((((odd << 1) | even) != chksum) || 
        !           290:            (((id & 0x00ff0000) >> 16) != drv->track*2 + side)) {
        !           291:            printf("Disk write: checksum error on sector header\n");
        !           292:            continue;
        !           293:        }
        !           294:        odd = getmfmlong(mbuf); even = getmfmlong(mbuf+2); mbuf += 4;
        !           295:        chksum = (odd << 1) | even;
        !           296:        secdata = drv->secbuf + 32;
        !           297:        for (i=0; i<128; i++) {
        !           298:            odd = getmfmlong(mbuf); even = getmfmlong(mbuf+256); mbuf += 2;
        !           299:            dlong = (odd << 1) | even;
        !           300:            *secdata++ = dlong >> 24; *secdata++ = (dlong >> 16) & 0xff;
        !           301:            *secdata++ = dlong >> 8; *secdata++ = dlong;
        !           302:            chksum ^= odd ^ even;
        !           303:        }
        !           304:        mbuf += 256;
        !           305:        if (chksum) {
        !           306:            printf("Disk write: data checksum error\n");
        !           307:            continue;
        !           308:        }
        !           309:        secwritten++;
        !           310:        fseek(drv->diskfile, 
        !           311:              drv->trackdata[drv->track*2 + side].offs + drv->trackoffs*512,
        !           312:              SEEK_SET);
        !           313:        fwrite(drv->secbuf+32, sizeof(UBYTE), 512, drv->diskfile);
        !           314:     }
        !           315:     if (++drv->trackoffs == 11) drv->trackoffs = 0;
        !           316:     drv->insecpos = 0;
        !           317:     drv->secok = false;
        !           318:     
        !           319:     if (secwritten == 0) 
        !           320:        printf("Disk write in unsupported format\n");
        !           321:     if (secwritten < 0)
        !           322:        printf("Disk write: sector labels ignored\n");
        !           323: }
        !           324: 
        !           325: static void drive_init(drive *drv, char *fname)
        !           326: {
        !           327:     drv->diskfile = 0;
        !           328:     if (fname != 0) drive_insert(drv, fname);
        !           329:     drv->track = 0;
        !           330:     drv->motoroff = true;
        !           331: }
        !           332: 
        !           333: static void drive_eject(drive *drv)
        !           334: {
        !           335:     if (!drive_empty(drv)) fclose(drv->diskfile);
        !           336:     drv->diskfile = 0;
        !           337: }
        !           338: 
        !           339: /* We use this function if we have no Kickstart ROM. */
        !           340: void DISK_ersatz_read (int tr, int sec, CPTR dest)
        !           341: {
        !           342:     int i;
        !           343: 
        !           344:     floppy[0].trackoffs = sec;
        !           345:     floppy[0].insecpos = 0;
        !           346:     
        !           347:     side = tr & 1;
        !           348:     floppy[0].track = tr >> 1;
        !           349:     drive_readsec(floppy);
        !           350:     for (i = 0; i < 512; i++) {
        !           351:        put_byte (dest + i, floppy[0].secbuf[32+i]);
        !           352:     }
        !           353:     
        !           354: }
        !           355: 
        !           356: void DISK_init()
        !           357: {
        !           358:     drive_insert(floppy, "df0.adf");
        !           359:     drive_insert(floppy + 1, "df1.adf");
        !           360:     drive_insert(floppy + 2, "df2.adf");
        !           361:     drive_insert(floppy + 3, "df3.adf");
        !           362: }
        !           363: 
        !           364: void DISK_Index()
        !           365: {
        !           366:     int i;
        !           367:     for(i=0; i<4; i++) {       
        !           368:        drive_index(floppy + i);
        !           369:     }
        !           370: }
        !           371: 
        !           372: void DISK_select(UBYTE data)
        !           373: {
        !           374:     int step_pulse;
        !           375:     int dr;
        !           376:     
        !           377:     if (selected != ((data >> 3) & 15)) dskready = false;
        !           378:     selected = (data >> 3) & 15;
        !           379:     if (side != 1 - ((data >> 2) & 1)) {
        !           380:        side = 1 - ((data >> 2) & 1);
        !           381:        need_read = true;
        !           382:     }
        !           383:     direction = (data >> 1) & 1;
        !           384:     step_pulse = data & 1;
        !           385:     if (step != step_pulse) {
        !           386:        step = step_pulse;
        !           387:        if (step == 0){
        !           388:            for (dr = 0; dr < 4; dr++){
        !           389:                if (!(selected & (1 << dr))) {
        !           390:                    drive_step(floppy + dr);
        !           391:                }
        !           392:            }
        !           393:        }
        !           394:     }
        !           395:     for (dr = 0; dr < 4; dr++){
        !           396:        if (!(selected & (1<<dr))) {
        !           397:            drive_motor(floppy + dr, data >> 7);
        !           398:        }
        !           399:     }
        !           400: }
        !           401: 
        !           402: UBYTE DISK_status()
        !           403: {
        !           404:     UBYTE st = 0x3c;
        !           405:     int dr;
        !           406:     
        !           407:     for (dr = 0; dr < 4; dr++){
        !           408:        if (!(selected & (1 << dr))) {
        !           409:            if (drive_running(floppy + dr)){
        !           410:                if (dskready) st &= ~0x20;
        !           411:                dskready = true;
        !           412:            } else {
        !           413:                st &= ~0x20; /* report drive ID */
        !           414:            }
        !           415:                
        !           416:            if (drive_track0(floppy + dr)) { st &= ~0x10; }
        !           417:            if (drive_writeprotected(floppy + dr)) { st &= ~8; }
        !           418:            if (drive_empty(floppy + dr)) { st &= ~0x4; }
        !           419:        }
        !           420:     }
        !           421:     return st;
        !           422: }
        !           423: 
        !           424: void DISK_GetData(UWORD *mfm,UWORD *byt)
        !           425: {
        !           426:     int dr;
        !           427:     for (dr = 0; dr < 4; dr++){
        !           428:        if (!(selected & (1<<dr))) {
        !           429:            drive_get_data (floppy + dr, mfm, byt);
        !           430:        }
        !           431:     }
        !           432: }
        !           433: 
        !           434: void DISK_InitWrite()
        !           435: {
        !           436:     mfmwrite = mfmwrbuffer;
        !           437: }
        !           438: 
        !           439: void DISK_WriteData()
        !           440: {
        !           441:     int dr;
        !           442:     for (dr=0;dr<4;dr++){
        !           443:        if (!(selected & (1<<dr))) {
        !           444:            drive_write_data(floppy + dr, mfmwrbuffer, mfmwrite);
        !           445:        }
        !           446:     }
        !           447: }

unix.superglobalmegacorp.com

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