Annotation of uae/disk.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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