Annotation of uae/src/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 "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.