Annotation of uae/disk.c, revision 1.1.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.