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

1.1.1.2   root        1:  /*
1.1       root        2:   * UAE - The Un*x Amiga Emulator
1.1.1.2   root        3:   *
1.1       root        4:   * Floppy disk emulation
                      5:   *
1.1.1.4   root        6:   * Copyright 1995 Bernd Schmidt, Hannu Rummukainen
1.1       root        7:   */
                      8: 
1.1.1.2   root        9: #include <stdio.h>
                     10: 
1.1       root       11: #include "sysconfig.h"
                     12: #include "sysdeps.h"
                     13: 
                     14: #include "config.h"
                     15: #include "options.h"
1.1.1.3   root       16: #include "threaddep/penguin.h"
1.1       root       17: #include "memory.h"
                     18: #include "events.h"
                     19: #include "custom.h"
                     20: #include "ersatz.h"
                     21: #include "disk.h"
                     22: #include "gui.h"
                     23: #include "zfile.h"
1.1.1.2   root       24: #include "autoconf.h"
                     25: #include "newcpu.h"
                     26: #include "xwin.h"
                     27: #include "osemu.h"
                     28: #include "execlib.h"
                     29: 
1.1.1.3   root       30: #define FLOPPY_GAP_LEN 360
1.1.1.7   root       31: /* writable track length with normal 2us bitcell/300RPM motor */
                     32: #define FLOPPY_WRITE_LEN 6250
                     33: /* (cycles/bitcell) << 8, normal = ((2us/280ns)<<8) = ~1830 */
                     34: #define NORMAL_FLOPPY_SPEED 1830
                     35: 
                     36: static int floppy_speed = NORMAL_FLOPPY_SPEED;
                     37: 
                     38: #undef DISK_DEBUG
                     39: 
                     40: /* UAE-1ADF (ADF_EXT2)
                     41:  * W   reserved
                     42:  * W   number of tracks (default 2*80=160)
                     43:  *
                     44:  * W   reserved
                     45:  * W   type, 0=normal AmigaDOS track, 1 = raw MFM
                     46:  * L   available space for track in bytes
                     47:  * L   track length in bits
                     48:  */
1.1       root       49: 
1.1.1.7   root       50: static int side, direction, step, writing;
1.1.1.3   root       51: static uae_u8 selected = 15;
1.1       root       52: 
1.1.1.7   root       53: static uae_u8 *writebuffer[544 * 11];
                     54: 
                     55: typedef enum { TRACK_AMIGADOS, TRACK_RAW, TRACK_RAW1 } image_tracktype;
1.1       root       56: typedef struct {
1.1.1.3   root       57:     uae_u16 len;
                     58:     uae_u32 offs;
1.1.1.7   root       59:     int bitlen;
                     60:     unsigned int sync;
                     61:     image_tracktype type;
1.1       root       62: } trackid;
                     63: 
1.1.1.2   root       64: #define MAX_TRACKS 328
                     65: 
1.1.1.7   root       66: typedef enum { ADF_NORMAL, ADF_EXT1, ADF_EXT2 } drive_filetype;
1.1       root       67: typedef struct {
                     68:     FILE *diskfile;
                     69:     drive_filetype filetype;
1.1.1.2   root       70:     trackid trackdata[MAX_TRACKS];
1.1.1.7   root       71:     int buffered_cyl, buffered_side;
                     72:     int cyl;
1.1       root       73:     int motoroff;
1.1.1.7   root       74:     int state;
                     75:     int disabled;
1.1       root       76:     int wrprot;
1.1.1.3   root       77:     uae_u16 bigmfmbuf[0x4000];
1.1       root       78:     int mfmpos;
1.1.1.7   root       79:     int mfmpos_hsync;
                     80:     int tracklen;
                     81:     int trackspeed;
                     82:     int dmalen;
                     83:     int num_tracks, num_secs;
1.1.1.3   root       84:     /* dskchange is set to a small number when a disk is removed. At a step
                     85:      * impulse, it is reset if there is a new disk in the drive or counted
                     86:      * down to 1 if the drive contains a disk. DISK_check_change will only
                     87:      * insert a new disk when dskchange is 1, or if the dskchange_time timer
                     88:      * expires. The last condition can happen if AmigaOS isn't running and a
                     89:      * game/demo doesn't use the step motor to check for a new disk.
                     90:      */
                     91:     int dskchange;
                     92:     int dskchange_time;
1.1.1.10! root       93:     int dskready;
        !            94:     int dskready_time;
1.1       root       95: } drive;
                     96: 
                     97: drive floppy[4];
                     98: 
1.1.1.7   root       99: /* code for track display */
1.1.1.8   root      100: static void update_drive_gui (int num)
1.1.1.7   root      101: {
1.1.1.8   root      102:     drive *drv = floppy + num;
                    103: 
1.1.1.7   root      104:     if (drv->state == gui_data.drive_motor[num]
                    105:        && drv->cyl == gui_data.drive_track[num]
                    106:        && ((writing && gui_data.drive_writing[num])
                    107:            || (!writing && !gui_data.drive_writing[num]))) {
                    108:        return;
                    109:     }
                    110:     gui_data.drive_motor[num] = drv->state;
                    111:     gui_data.drive_track[num] = drv->cyl;
                    112:     if (!gui_data.drive_writing[num])
                    113:        gui_data.drive_writing[num] = writing;
1.1.1.8   root      114:     gui_ledstate &= ~(2 << num);
                    115:     if (drv->state)
                    116:        gui_ledstate |= 2 << num;
1.1.1.7   root      117:     gui_led (num + 1, gui_data.drive_motor[num]);
                    118: }
                    119: 
                    120: static void drive_fill_bigbuf (drive * drv);
1.1       root      121: 
1.1.1.3   root      122: FILE *DISK_validate_filename (const char *fname, int leave_open, int *wrprot)
1.1       root      123: {
1.1.1.4   root      124:     FILE *f = zfile_open (fname, "r+b");
1.1.1.3   root      125:     if (f) {
                    126:        if (wrprot)
                    127:            *wrprot = 0;
1.1       root      128:     } else {
1.1.1.3   root      129:        if (wrprot)
                    130:            *wrprot = 1;
1.1.1.4   root      131:        f = zfile_open (fname, "rb");
1.1       root      132:     }
1.1.1.3   root      133:     if (!leave_open)
1.1.1.4   root      134:        zfile_close (f);
1.1.1.3   root      135:     return f;
                    136: }
                    137: 
1.1.1.7   root      138: static int drive_insert (drive * drv, int dnum, const char *fname)
1.1.1.3   root      139: {
1.1.1.7   root      140:     unsigned char buffer[2 + 2 + 4 + 4];
                    141:     trackid *tid;
1.1.1.3   root      142: 
                    143:     drv->diskfile = DISK_validate_filename (fname, 1, &drv->wrprot);
1.1.1.6   root      144:     if (drv->diskfile == 0) {
1.1.1.7   root      145:        drv->tracklen = FLOPPY_WRITE_LEN * 2 * 8;
                    146:        drv->trackspeed = floppy_speed;
1.1.1.3   root      147:        return 0;
1.1.1.6   root      148:     }
1.1.1.3   root      149:     strncpy (currprefs.df[dnum], fname, 255);
                    150:     currprefs.df[dnum][255] = 0;
                    151:     strncpy (changed_prefs.df[dnum], fname, 255);
                    152:     changed_prefs.df[dnum][255] = 0;
1.1.1.7   root      153:     gui_filename (dnum, fname);
1.1.1.3   root      154: 
1.1.1.7   root      155:     fread (buffer, sizeof (char), 8, drv->diskfile);
                    156:     if (strncmp ((char *) buffer, "UAE-1ADF", 8) == 0) {
                    157:        int offs;
                    158:        int i;
                    159: 
                    160:        fread (buffer, 1, 4, drv->diskfile);
                    161:        drv->num_tracks = buffer[2] * 256 + buffer[3];
                    162:        drv->filetype = ADF_EXT2;
                    163:        drv->num_secs = 11;
1.1.1.10! root      164:        offs = 8 + 2 + 2 + drv->num_tracks * (2 + 2 + 4 + 4);
1.1.1.7   root      165: 
                    166:        for (i = 0; i < drv->num_tracks; i++) {
                    167:            tid = &drv->trackdata[i];
                    168:            fread (buffer, 2 + 2 + 4 + 4, 1, drv->diskfile);
                    169:            tid->type = buffer[2] * 256 + buffer[3];
                    170:            tid->len = buffer[5] * 65536 + buffer[6] * 256 + buffer[7];
                    171:            tid->bitlen = buffer[9] * 65536 + buffer[10] * 256 + buffer[11];
                    172:            tid->offs = offs;
                    173:            if (tid->type == TRACK_AMIGADOS) {
                    174:                if (tid->len > 20000)
                    175:                    drv->num_secs = 22;
                    176:            }
                    177:            offs += tid->len;
                    178:        }
                    179:     } else if (strncmp ((char *) buffer, "UAE--ADF", 8) == 0) {
                    180:        int offs = 160 * 4 + 8;
1.1       root      181:        int i;
1.1.1.3   root      182: 
                    183:        drv->filetype = ADF_EXT1;
1.1.1.2   root      184:        drv->num_tracks = 160;
                    185:        drv->num_secs = 11;
1.1.1.3   root      186: 
1.1.1.7   root      187:        drv->wrprot = 1;        /* write to adf_ext1 not implemented */
                    188:        for (i = 0; i < 160; i++) {
                    189:            tid = &drv->trackdata[i];
                    190:            fread (buffer, 4, 1, drv->diskfile);
                    191:            tid->sync = buffer[0] * 256 + buffer[1];
                    192:            tid->len = buffer[2] * 256 + buffer[3];
                    193:            tid->offs = offs;
                    194:            if (tid->sync == 0) {
                    195:                tid->type = TRACK_AMIGADOS;
                    196:                tid->bitlen = 0;
                    197:            } else {
                    198:                tid->type = TRACK_RAW1;
                    199:                tid->bitlen = tid->len * 8;
                    200:            }
                    201:            offs += tid->len;
1.1       root      202:        }
                    203:     } else {
1.1.1.7   root      204:        int i;
1.1.1.3   root      205: 
                    206:        drv->filetype = ADF_NORMAL;
1.1.1.2   root      207: 
1.1.1.7   root      208:        fseek (drv->diskfile, 0, SEEK_END);
1.1.1.4   root      209:        i = ftell (drv->diskfile);
1.1.1.7   root      210:        fseek (drv->diskfile, 0, SEEK_SET);
1.1.1.3   root      211: 
1.1.1.2   root      212:        /* High-density disk? */
1.1.1.7   root      213:        if (i >= 160 * 22 * 512)
                    214:            drv->num_tracks = i / (512 * (drv->num_secs = 22));
1.1.1.2   root      215:        else
1.1.1.7   root      216:            drv->num_tracks = i / (512 * (drv->num_secs = 11));
1.1.1.3   root      217: 
1.1.1.2   root      218:        if (drv->num_tracks > MAX_TRACKS)
1.1.1.3   root      219:            write_log ("Your diskfile is too big!\n");
1.1.1.7   root      220:        for (i = 0; i < drv->num_tracks; i++) {
                    221:            tid = &drv->trackdata[i];
                    222:            tid->type = TRACK_AMIGADOS;
                    223:            tid->len = 512 * drv->num_secs;
                    224:            tid->bitlen = 0;
                    225:            tid->offs = i * 512 * drv->num_secs;
1.1       root      226:        }
                    227:     }
1.1.1.7   root      228:     drv->buffered_side = 2;    /* will force read */
1.1.1.6   root      229:     drive_fill_bigbuf (drv);
1.1.1.3   root      230:     return 1;
1.1       root      231: }
                    232: 
1.1.1.7   root      233: static int drive_empty (drive * drv)
1.1.1.2   root      234: {
1.1.1.3   root      235:     return drv->diskfile == 0;
1.1.1.2   root      236: }
                    237: 
1.1.1.7   root      238: static void drive_step (drive * drv)
1.1       root      239: {
1.1.1.7   root      240:     if (!drive_empty (drv))
1.1.1.3   root      241:        drv->dskchange = 0;
                    242:     else if (drv->dskchange > 1) {
                    243: /*     printf("Stepping...\n");
                    244:        drv->dskchange--;*/
                    245:     }
1.1       root      246:     if (direction) {
1.1.1.7   root      247:        if (drv->cyl)
                    248:            drv->cyl--;
1.1       root      249:     } else {
1.1.1.7   root      250:        if (drv->cyl < 83)
                    251:            drv->cyl++;
1.1       root      252:     }
                    253: 
1.1.1.7   root      254: #if 0 && defined DISK_DEBUG
                    255:     write_log ("track %d\n", drv->cyl);
                    256: #endif
                    257: }
1.1       root      258: 
1.1.1.7   root      259: static int drive_track0 (drive * drv)
1.1       root      260: {
1.1.1.3   root      261:     return drv->cyl == 0;
1.1       root      262: }
                    263: 
1.1.1.7   root      264: static int drive_writeprotected (drive * drv)
1.1       root      265: {
1.1.1.3   root      266:     return drv->wrprot || drv->diskfile == NULL;
1.1       root      267: }
                    268: 
1.1.1.7   root      269: static int drive_running (drive * drv)
1.1       root      270: {
1.1.1.3   root      271:     return !drv->motoroff;
1.1       root      272: }
                    273: 
1.1.1.7   root      274: static void drive_motor (drive * drv, int off)
1.1       root      275: {
1.1.1.10! root      276:     if (drv->disabled)
        !           277:        off = 1;
        !           278:     /* A value of 2 works out to a guaranteed delay of 1/10 of a second
        !           279:        (which is the frequency with which DISK_check_change is called).
        !           280:        Higher values are dangerous, e.g. a value of 8 breaks the RSI
        !           281:        demo.  */
        !           282:     if (drv->motoroff && !off)
        !           283:        drv->dskready_time = 2;
1.1       root      284:     drv->motoroff = off;
1.1.1.10! root      285:     if (drv->motoroff) {
        !           286:        drv->dskready = 0;
        !           287:        drv->dskready_time = 0;
        !           288:     }
1.1       root      289: }
                    290: 
1.1.1.7   root      291: static void read_floppy_data (drive * drv, int track, int offset, unsigned char *dst, int len)
                    292: {
                    293:     trackid *ti;
                    294: 
                    295:     ti = &drv->trackdata[track];
                    296:     fseek (drv->diskfile, ti->offs + offset, SEEK_SET);
                    297:     fread (dst, 1, len, drv->diskfile);
                    298: }
                    299: 
                    300: /* Megalomania does not like zero MFM words... */
                    301: static void mfmcode (uae_u16 * mfm, int words)
                    302: {
1.1.1.8   root      303:     uae_u32 lastword = 0;
1.1.1.7   root      304: 
                    305:     while (words--) {
1.1.1.8   root      306:        uae_u32 v = *mfm;
                    307:        uae_u32 lv = (lastword << 16) | v;
                    308:        uae_u32 nlv = 0x55555555 & ~lv;
                    309:        uae_u32 mfmbits = (nlv << 1) & (nlv >> 1);
                    310: 
                    311:        *mfm++ = v | mfmbits;
                    312:        lastword = v;
1.1.1.7   root      313:     }
                    314: }
                    315: 
                    316: static void drive_fill_bigbuf (drive * drv)
1.1       root      317: {
1.1.1.7   root      318:     int tr = drv->cyl * 2 + side;
                    319:     trackid *ti = drv->trackdata + tr;
1.1.1.3   root      320: 
1.1.1.7   root      321:     if (!drv->diskfile || tr >= drv->num_tracks) {
                    322:        drv->tracklen = FLOPPY_WRITE_LEN * 2 * 8;
                    323:        drv->trackspeed = floppy_speed;
                    324:        memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2);
1.1.1.2   root      325:        return;
                    326:     }
1.1.1.3   root      327:     if (drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
                    328:        return;
                    329: 
1.1.1.7   root      330:     if (ti->type == TRACK_AMIGADOS) {
1.1       root      331:        /* Normal AmigaDOS format track */
1.1.1.7   root      332:        int sec;
                    333:        drv->tracklen = (drv->num_secs * 544 + FLOPPY_GAP_LEN) * 2 * 8;
                    334:        memset (drv->bigmfmbuf, 0xaa, FLOPPY_GAP_LEN * 2);
1.1.1.2   root      335: 
                    336:        for (sec = 0; sec < drv->num_secs; sec++) {
1.1.1.3   root      337:            uae_u8 secbuf[544];
1.1       root      338:            int i;
1.1.1.7   root      339:            uae_u16 *mfmbuf = drv->bigmfmbuf + 544 * sec + FLOPPY_GAP_LEN;
                    340:            uae_u32 deven, dodd;
                    341:            uae_u32 hck = 0, dck = 0;
1.1.1.3   root      342: 
1.1       root      343:            secbuf[0] = secbuf[1] = 0x00;
                    344:            secbuf[2] = secbuf[3] = 0xa1;
                    345:            secbuf[4] = 0xff;
                    346:            secbuf[5] = tr;
                    347:            secbuf[6] = sec;
1.1.1.7   root      348:            secbuf[7] = drv->num_secs - sec;
1.1       root      349: 
1.1.1.7   root      350:            for (i = 8; i < 24; i++)
1.1       root      351:                secbuf[i] = 0;
1.1.1.3   root      352: 
1.1.1.7   root      353:            read_floppy_data (drv, tr, sec * 512, &secbuf[32], 512);
1.1.1.3   root      354: 
1.1       root      355:            mfmbuf[0] = mfmbuf[1] = 0xaaaa;
                    356:            mfmbuf[2] = mfmbuf[3] = 0x4489;
1.1.1.3   root      357: 
                    358:            deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
1.1       root      359:                     | (secbuf[6] << 8) | (secbuf[7]));
                    360:            dodd = deven >> 1;
1.1.1.7   root      361:            deven &= 0x55555555;
                    362:            dodd &= 0x55555555;
1.1.1.3   root      363: 
1.1       root      364:            mfmbuf[4] = dodd >> 16;
                    365:            mfmbuf[5] = dodd;
1.1.1.7   root      366:            mfmbuf[6] = deven >> 16;
1.1       root      367:            mfmbuf[7] = deven;
1.1.1.3   root      368: 
1.1       root      369:            for (i = 8; i < 48; i++)
1.1.1.6   root      370:                mfmbuf[i] = 0xaaaa;
1.1.1.7   root      371:            for (i = 0; i < 512; i += 4) {
                    372:                deven = ((secbuf[i + 32] << 24) | (secbuf[i + 33] << 16)
                    373:                         | (secbuf[i + 34] << 8) | (secbuf[i + 35]));
1.1       root      374:                dodd = deven >> 1;
1.1.1.7   root      375:                deven &= 0x55555555;
                    376:                dodd &= 0x55555555;
                    377:                mfmbuf[(i >> 1) + 32] = dodd >> 16;
                    378:                mfmbuf[(i >> 1) + 33] = dodd;
                    379:                mfmbuf[(i >> 1) + 256 + 32] = deven >> 16;
                    380:                mfmbuf[(i >> 1) + 256 + 33] = deven;
                    381:            }
                    382: 
                    383:            for (i = 4; i < 24; i += 2)
                    384:                hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
                    385: 
                    386:            deven = dodd = hck;
                    387:            dodd >>= 1;
                    388:            mfmbuf[24] = dodd >> 16;
                    389:            mfmbuf[25] = dodd;
                    390:            mfmbuf[26] = deven >> 16;
                    391:            mfmbuf[27] = deven;
                    392: 
                    393:            for (i = 32; i < 544; i += 2)
                    394:                dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
                    395: 
                    396:            deven = dodd = dck;
                    397:            dodd >>= 1;
                    398:            mfmbuf[28] = dodd >> 16;
                    399:            mfmbuf[29] = dodd;
                    400:            mfmbuf[30] = deven >> 16;
                    401:            mfmbuf[31] = deven;
                    402:            mfmcode (mfmbuf + 4, 544 - 4);
1.1       root      403:        }
1.1.1.7   root      404: #ifdef DISK_DEBUG
                    405:        write_log ("amigados read track %d\n", tr);
                    406: #endif
1.1       root      407:     } else {
                    408:        int i;
1.1.1.7   root      409:        int base_offset = ti->type == TRACK_RAW ? 0 : 1;
                    410:        drv->tracklen = ti->bitlen + 16 * base_offset;
                    411:        drv->bigmfmbuf[0] = ti->sync;
1.1.1.10! root      412:        read_floppy_data (drv, tr, 0, (char *) (drv->bigmfmbuf + base_offset), (ti->bitlen + 7) / 8);
        !           413:        for (i = base_offset; i < (drv->tracklen + 15) / 16; i++) {
1.1.1.7   root      414:            uae_u16 *mfm = drv->bigmfmbuf + i;
                    415:            uae_u8 *data = (uae_u8 *) mfm;
                    416:            *mfm = 256 * *data + *(data + 1);
1.1       root      417:        }
1.1.1.7   root      418: #if 0 && defined DISK_DEBUG
                    419:        write_log ("rawtrack %d\n", tr);
                    420: #endif
1.1       root      421:     }
1.1.1.3   root      422:     drv->buffered_side = side;
                    423:     drv->buffered_cyl = drv->cyl;
1.1.1.7   root      424:     drv->trackspeed = floppy_speed * drv->tracklen / (2 * 8 * FLOPPY_WRITE_LEN);
1.1       root      425: }
                    426: 
1.1.1.7   root      427: /* Update ADF_EXT2 track header */
                    428: static void diskfile_update (drive * drv, int len, uae_u8 type)
1.1       root      429: {
1.1.1.7   root      430:     trackid *ti;
                    431:     int track;
                    432:     uae_u8 buf[2 + 2 + 4 + 4], *zerobuf;
1.1.1.3   root      433: 
1.1.1.7   root      434:     if (drv->filetype != ADF_EXT2)
                    435:        return;
1.1.1.6   root      436: 
1.1.1.7   root      437:     track = drv->cyl * 2 + side;
                    438:     ti = &drv->trackdata[track];
                    439:     ti->bitlen = len;
                    440:     fseek (drv->diskfile, 8 + 4 + (2 + 2 + 4 + 4) * track, SEEK_SET);
                    441:     memset (buf, 0, sizeof buf);
                    442:     ti->type = type;
                    443:     buf[3] = ti->type;
                    444:     do_put_mem_long ((uae_u32 *) (buf + 4), ti->len);
                    445:     do_put_mem_long ((uae_u32 *) (buf + 8), ti->bitlen);
                    446:     fwrite (buf, sizeof (buf), 1, drv->diskfile);
                    447:     if (ti->len > (len + 7) / 8) {
                    448:        zerobuf = malloc (ti->len);
                    449:        memset (zerobuf, 0, ti->len);
                    450:        fseek (drv->diskfile, ti->offs, SEEK_SET);
                    451:        fwrite (zerobuf, 1, ti->len, drv->diskfile);
                    452:        free (zerobuf);
                    453:     }
                    454: #ifdef DISK_DEBUG
                    455:     write_log ("track %d, raw track length %d written (total size %d)\n", track, (ti->bitlen + 7) / 8, ti->len);
                    456: #endif
1.1       root      457: }
                    458: 
                    459: #define MFMMASK 0x55555555
1.1.1.7   root      460: static uae_u32 getmfmlong (uae_u16 * mbuf)
1.1       root      461: {
                    462:     return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK;
                    463: }
                    464: 
1.1.1.7   root      465: static int drive_write_adf_amigados (drive * drv)
1.1       root      466: {
                    467:     int i, secwritten = 0;
1.1.1.7   root      468:     int length = 2 * FLOPPY_WRITE_LEN;
1.1.1.3   root      469:     uae_u32 odd, even, chksum, id, dlong;
1.1.1.7   root      470:     uae_u8 *secdata;
1.1.1.3   root      471:     uae_u8 secbuf[544];
1.1.1.7   root      472:     uae_u16 *mbuf = drv->bigmfmbuf;
1.1.1.3   root      473:     uae_u16 *mend = mbuf + length;
1.1.1.7   root      474:     char sectable[11];
1.1.1.3   root      475: 
1.1.1.7   root      476:     memset (sectable, 0, sizeof (sectable));
                    477:     memcpy (mbuf + FLOPPY_WRITE_LEN, mbuf, FLOPPY_WRITE_LEN * sizeof (uae_u16));
1.1       root      478:     mend -= (4 + 16 + 8 + 512);
1.1.1.7   root      479:     while (secwritten < 11) {
1.1       root      480:        int trackoffs;
1.1.1.3   root      481: 
1.1       root      482:        do {
                    483:            while (*mbuf++ != 0x4489) {
1.1.1.4   root      484:                if (mbuf >= mend)
1.1.1.7   root      485:                    return 1;
1.1       root      486:            }
                    487:        } while (*mbuf++ != 0x4489);
1.1.1.3   root      488: 
1.1.1.4   root      489:        odd = getmfmlong (mbuf);
                    490:        even = getmfmlong (mbuf + 2);
1.1.1.3   root      491:        mbuf += 4;
1.1       root      492:        id = (odd << 1) | even;
1.1.1.3   root      493: 
1.1       root      494:        trackoffs = (id & 0xff00) >> 8;
                    495:        if (trackoffs > 10) {
1.1.1.7   root      496:            if (drv->filetype == ADF_EXT2)
                    497:                return 2;
1.1.1.5   root      498:            write_log ("Disk write: weird sector number %d\n", trackoffs);
1.1       root      499:            continue;
                    500:        }
                    501:        chksum = odd ^ even;
1.1.1.4   root      502:        for (i = 0; i < 4; i++) {
1.1.1.7   root      503:            odd = getmfmlong (mbuf);
                    504:            even = getmfmlong (mbuf + 8);
1.1       root      505:            mbuf += 2;
1.1.1.3   root      506: 
1.1       root      507:            dlong = (odd << 1) | even;
1.1.1.7   root      508:            if (dlong) {
                    509:                if (drv->filetype == ADF_EXT2)
                    510:                    return 6;
1.1.1.4   root      511:                secwritten = -200;
1.1.1.7   root      512:            }
1.1       root      513:            chksum ^= odd ^ even;
1.1.1.7   root      514:        }                       /* could check here if the label is nonstandard */
1.1       root      515:        mbuf += 8;
1.1.1.7   root      516:        odd = getmfmlong (mbuf);
                    517:        even = getmfmlong (mbuf + 2);
                    518:        mbuf += 4;
                    519:        if (((odd << 1) | even) != chksum || ((id & 0x00ff0000) >> 16) != drv->cyl * 2 + side) {
                    520:            if (drv->filetype == ADF_EXT2)
                    521:                return 3;
                    522:            write_log ("Disk write: checksum error on sector %d header\n", trackoffs);
1.1       root      523:            continue;
                    524:        }
1.1.1.7   root      525:        odd = getmfmlong (mbuf);
                    526:        even = getmfmlong (mbuf + 2);
                    527:        mbuf += 4;
1.1       root      528:        chksum = (odd << 1) | even;
                    529:        secdata = secbuf + 32;
1.1.1.7   root      530:        for (i = 0; i < 128; i++) {
                    531:            odd = getmfmlong (mbuf);
                    532:            even = getmfmlong (mbuf + 256);
                    533:            mbuf += 2;
1.1       root      534:            dlong = (odd << 1) | even;
1.1.1.7   root      535:            *secdata++ = dlong >> 24;
                    536:            *secdata++ = dlong >> 16;
                    537:            *secdata++ = dlong >> 8;
                    538:            *secdata++ = dlong;
1.1       root      539:            chksum ^= odd ^ even;
                    540:        }
                    541:        mbuf += 256;
                    542:        if (chksum) {
1.1.1.7   root      543:            if (drv->filetype == ADF_EXT2)
                    544:                return 4;
                    545:            write_log ("Disk write: sector %d, data checksum error\n", trackoffs);
1.1       root      546:            continue;
                    547:        }
1.1.1.7   root      548:        sectable[trackoffs] = 1;
1.1       root      549:        secwritten++;
1.1.1.7   root      550:        memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
1.1       root      551:     }
1.1.1.7   root      552:     if (drv->filetype == ADF_EXT2 && (secwritten == 0 || secwritten < 0))
                    553:        return 5;
1.1.1.3   root      554:     if (secwritten == 0)
                    555:        write_log ("Disk write in unsupported format\n");
1.1       root      556:     if (secwritten < 0)
1.1.1.3   root      557:        write_log ("Disk write: sector labels ignored\n");
1.1.1.7   root      558: 
                    559:     diskfile_update (drv, 11 * 512 * 8, TRACK_AMIGADOS);
                    560:     for (i = 0; i < 11; i++) {
                    561:        fseek (drv->diskfile, drv->trackdata[drv->cyl * 2 + side].offs + i * 512, SEEK_SET);
                    562:        fwrite (writebuffer + i * 512, sizeof (uae_u8), 512, drv->diskfile);
                    563:     }
                    564: 
                    565:     return 0;
1.1       root      566: }
                    567: 
1.1.1.7   root      568: /* write raw track to disk file */
                    569: static int drive_write_ext2 (drive * drv)
                    570: {
                    571:     trackid *ti;
                    572:     int len, track, i;
1.1       root      573: 
1.1.1.7   root      574:     track = drv->cyl * 2 + side;
                    575:     ti = &drv->trackdata[track];
                    576:     len = (drv->tracklen + 7) / 8;
                    577:     if (len > ti->len) {
                    578:        write_log ("disk raw write: image file's track %d is too small (%d < %d)!\n", track, ti->len, len);
                    579:        return 0;
                    580:     }
                    581:     diskfile_update (drv, drv->tracklen, TRACK_RAW);
                    582:     for (i = 0; i < drv->trackdata[track].len / 2; i++) {
                    583:        uae_u16 *mfm = drv->bigmfmbuf + i;
                    584:        uae_u8 *data = (uae_u8 *) mfm;
                    585:        *mfm = 256 * *data + *(data + 1);
                    586:     }
                    587:     fseek (drv->diskfile, ti->offs, SEEK_SET);
                    588:     fwrite (drv->bigmfmbuf, 1, len, drv->diskfile);
                    589:     return 1;
                    590: }
                    591: 
                    592: static void drive_write_data (drive * drv)
1.1       root      593: {
1.1.1.7   root      594:     int ret;
                    595:     if (drive_writeprotected (drv))
                    596:        return;
                    597:     switch (drv->filetype) {
                    598:     case ADF_NORMAL:
                    599:        drive_write_adf_amigados (drv);
                    600:        break;
                    601:     case ADF_EXT1:
                    602:        write_log ("writing to ADF_EXT1 not supported\n");
                    603:        return;
                    604:     case ADF_EXT2:
                    605:        ret = drive_write_adf_amigados (drv);
                    606:        if (ret) {
                    607:            /*write_log("not an amigados track (error %d), writing as raw track\n",ret); */
                    608:            drive_write_ext2 (drv);
                    609:        }
                    610:        break;
                    611:     }
                    612:     drv->buffered_side = 2;    /* will force read */
                    613: }
                    614: 
                    615: static void drive_eject (drive * drv)
                    616: {
                    617:     if (!drive_empty (drv))
1.1.1.4   root      618:        zfile_close (drv->diskfile);
1.1.1.3   root      619: 
                    620:     drv->dskchange = 4;
                    621:     drv->dskchange_time = 20;
                    622: /*    printf("setting changed bit %d\n", drv-floppy);*/
1.1       root      623:     drv->diskfile = 0;
                    624: }
                    625: 
1.1.1.3   root      626: /* We use this function if we have no Kickstart ROM.
1.1       root      627:  * No error checking - we trust our luck. */
1.1.1.3   root      628: void DISK_ersatz_read (int tr, int sec, uaecptr dest)
1.1       root      629: {
1.1.1.7   root      630:     uae_u8 *dptr = get_real_address (dest);
                    631:     fseek (floppy[0].diskfile, floppy[0].trackdata[tr].offs + sec * 512, SEEK_SET);
1.1.1.3   root      632:     fread (dptr, 1, 512, floppy[0].diskfile);
1.1       root      633: }
                    634: 
1.1.1.4   root      635: void disk_eject (int num)
1.1       root      636: {
1.1.1.7   root      637:     gui_filename (num, "");
                    638:     drive_eject (floppy + num);
1.1.1.3   root      639:     *currprefs.df[num] = *changed_prefs.df[num] = 0;
1.1       root      640: }
                    641: 
1.1.1.4   root      642: void disk_insert (int num, const char *name)
1.1       root      643: {
                    644:     /* just to be sure */
1.1.1.4   root      645:     drive_eject (floppy + num);
                    646:     drive_insert (floppy + num, num, name);
1.1       root      647: }
                    648: 
1.1.1.3   root      649: void DISK_check_change (void)
                    650: {
                    651:     int i;
                    652:     static int count = 0;
                    653:     count++;
                    654: 
                    655:     for (i = 0; i < 4; i++) {
1.1.1.10! root      656:         /* emulate drive motor turn on time */
        !           657:         if (floppy[i].dskready_time) {
        !           658:            floppy[i].dskready_time--;
        !           659:            if (floppy[i].dskready_time == 0) {
        !           660:                floppy[i].dskready = 1;
        !           661:            }
        !           662:        }
1.1.1.3   root      663:        if (strcmp (currprefs.df[i], changed_prefs.df[i]) != 0) {
                    664:            if (currprefs.df[i][0] != '\0') {
1.1.1.7   root      665:                drive_eject (floppy + i);
1.1.1.3   root      666:                currprefs.df[i][0] = '\0';
1.1.1.7   root      667:                gui_filename (i, "");
1.1.1.3   root      668:            } else if (floppy[i].dskchange == 1) {
                    669:                /* In theory, it should work without the dskchange test.
                    670:                 * In practice, it doesn't. */
                    671:                drive_insert (floppy + i, i, changed_prefs.df[i]);
                    672:            } else if (floppy[i].dskchange > 1 && floppy[i].dskchange_time > 0) {
                    673:                /* Force the dskchange bit to go to 1 after a given timeout */
                    674:                if (--floppy[i].dskchange_time == 0) {
                    675:                    floppy[i].dskchange = 1;
                    676:                }
                    677:            }
                    678:        }
                    679:     }
                    680: }
                    681: 
1.1.1.4   root      682: int disk_empty (int num)
1.1       root      683: {
1.1.1.4   root      684:     return drive_empty (floppy + num);
1.1       root      685: }
                    686: 
1.1.1.10! root      687: static int not_ready = 0;
        !           688: 
1.1.1.4   root      689: void DISK_select (uae_u8 data)
1.1       root      690: {
1.1.1.10! root      691:     static int lastselected;
1.1       root      692:     int step_pulse;
                    693:     int dr;
1.1.1.3   root      694: 
1.1.1.10! root      695:     lastselected = selected;
1.1       root      696:     selected = (data >> 3) & 15;
1.1.1.10! root      697:     if (selected != lastselected)
        !           698:        not_ready = 1;
1.1.1.3   root      699:     side = 1 - ((data >> 2) & 1);
                    700: 
1.1       root      701:     direction = (data >> 1) & 1;
                    702:     step_pulse = data & 1;
                    703:     if (step != step_pulse) {
                    704:        step = step_pulse;
1.1.1.7   root      705:        if (step == 0) {
                    706:            for (dr = 0; dr < 4; dr++) {
1.1       root      707:                if (!(selected & (1 << dr))) {
1.1.1.4   root      708:                    drive_step (floppy + dr);
1.1       root      709:                }
                    710:            }
                    711:        }
                    712:     }
1.1.1.7   root      713:     for (dr = 0; dr < 4; dr++) {
1.1.1.10! root      714:        if (!(selected & (1 << dr)) && (lastselected & (1 << dr))) {
1.1.1.7   root      715:            drive_motor (floppy + dr, data >> 7);
1.1       root      716:        }
                    717:     }
                    718:     for (dr = 0; dr < 4; dr++) {
1.1.1.7   root      719:        floppy[dr].state = (!(selected & (1 << dr))) | !floppy[dr].motoroff;
1.1.1.8   root      720:        update_drive_gui (dr);
1.1       root      721:     }
                    722: }
                    723: 
1.1.1.4   root      724: uae_u8 DISK_status (void)
1.1       root      725: {
1.1.1.3   root      726:     uae_u8 st = 0x3c;
1.1       root      727:     int dr;
1.1.1.3   root      728: 
1.1.1.7   root      729:     for (dr = 0; dr < 4; dr++) {
1.1.1.3   root      730:        drive *drv = floppy + dr;
1.1       root      731:        if (!(selected & (1 << dr))) {
1.1.1.7   root      732:            if (drive_running (drv)) {
1.1.1.10! root      733:                if (drv->dskready && ! not_ready)
1.1.1.7   root      734:                    st &= ~0x20;
1.1.1.10! root      735:                not_ready = 0;
1.1.1.7   root      736:            } else if (!drv->disabled) {
                    737:                st &= ~0x20;    /* report drive ID */
1.1       root      738:            }
1.1.1.3   root      739: 
1.1.1.7   root      740:            if (drive_track0 (drv)) {
                    741:                st &= ~0x10;
                    742:            }
                    743:            if (drive_writeprotected (drv)) {
                    744:                st &= ~8;
                    745:            }
1.1.1.3   root      746:            if (drv->dskchange) {
                    747:                /*printf("changed bit set: %d\n",dr); */
                    748:                st &= ~0x4;
                    749:                if (drv->dskchange > 1)
                    750:                    drv->dskchange--;
                    751:            }
1.1       root      752:        }
                    753:     }
                    754:     return st;
                    755: }
                    756: 
1.1.1.7   root      757: #define MAX_DISK_WORDS_PER_LINE 50     /* depends on floppy_speed */
                    758: 
                    759: #define DISK_INDEXSYNC 1
                    760: #define DISK_WORDSYNC 2
                    761: 
                    762: static uae_u16 dskbytr_tab[MAX_DISK_WORDS_PER_LINE * 2 + 1];
                    763: static uae_u8 dskbytr_cycle[MAX_DISK_WORDS_PER_LINE * 2 + 1];
                    764: static uae_u16 dskdatr_tab[MAX_DISK_WORDS_PER_LINE + 1];
                    765: static uae_u8 dskdatr_cycle[MAX_DISK_WORDS_PER_LINE + 1];
                    766: static uae_u32 dma_tab[MAX_DISK_WORDS_PER_LINE + 1];
                    767: static uae_u8 disk_sync[MAXHPOS];
                    768: static int disk_sync_cycle;
                    769: static int indexsync_last_cycle;
                    770: static int dskdmaen, dsklength;
                    771: static uae_u16 dsksync;
                    772: static uae_u32 dskpt;
                    773: 
                    774: static void disk_dmafinished (void)
                    775: {
                    776:     INTREQ (0x8002);
                    777:     dskdmaen = 0;
                    778: }
                    779: 
                    780: static void disk_events (int last)
                    781: {
                    782:     eventtab[ev_disk].active = 0;
                    783:     for (disk_sync_cycle = last; disk_sync_cycle < MAXHPOS; disk_sync_cycle++) {
                    784:        if (disk_sync[disk_sync_cycle]) {
1.1.1.10! root      785:            eventtab[ev_disk].oldcycles = get_cycles ();
        !           786:            eventtab[ev_disk].evtime = get_cycles () + (disk_sync_cycle - last) * CYCLE_UNIT;
1.1.1.7   root      787:            eventtab[ev_disk].active = 1;
                    788:            events_schedule ();
                    789:            return;
1.1       root      790:        }
                    791:     }
                    792: }
                    793: 
1.1.1.7   root      794: extern void cia_diskindex (void);
1.1.1.3   root      795: 
1.1.1.7   root      796: void DISK_handler (void)
                    797: {
                    798:     eventtab[ev_disk].active = 0;
                    799:     if (disk_sync[disk_sync_cycle] & DISK_WORDSYNC) {
                    800:        INTREQ (0x9000);
                    801:        indexsync_last_cycle = disk_sync_cycle + ((floppy_speed + 255) >> 8);
                    802:     }
                    803:     if (disk_sync[disk_sync_cycle] & DISK_INDEXSYNC) {
                    804:        cia_diskindex ();
                    805:     }
                    806:     disk_sync[disk_sync_cycle] = 0;
                    807:     disk_events (disk_sync_cycle);
                    808: }
1.1.1.3   root      809: 
1.1.1.7   root      810: static int syncfound, dmaon, word, bitoffset;
1.1       root      811: 
1.1.1.7   root      812: /* Always carried through to the next line.  */
                    813: static int disk_hpos;
1.1.1.2   root      814: 
1.1.1.7   root      815: /* emulate disk write dma for full horizontal line */
                    816: static void disk_doupdate_write (drive * drv)
                    817: {
                    818:     int hpos = disk_hpos;
                    819:     while (hpos < (MAXHPOS << 8)) {
                    820:        drv->mfmpos++;
                    821:        drv->mfmpos %= drv->tracklen;
                    822:        if (!drv->mfmpos) {
                    823:            disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
                    824:            disk_events (0);
                    825:        }
                    826:        if ((dmacon & 0x210) == 0x210 && dskdmaen == 3) {
                    827:            bitoffset++;
                    828:            bitoffset &= 15;
                    829:            if (!bitoffset) {
                    830:                drv->bigmfmbuf[drv->mfmpos >> 4] = get_word (dskpt);
                    831:                dskpt += 2;
                    832:                dsklength--;
                    833:                if (dsklength == 0) {
                    834:                    disk_dmafinished ();
                    835:                    drive_write_data (drv);
                    836:                }
1.1       root      837:            }
                    838:        }
1.1.1.7   root      839:        hpos += drv->trackspeed;
1.1       root      840:     }
1.1.1.7   root      841:     disk_hpos = hpos - (MAXHPOS << 8);
1.1       root      842: }
                    843: 
1.1.1.7   root      844: /* get one bit from MFM bit stream */
                    845: static uae_u16 getonebit (uae_u16 * mfmbuf, int mfmpos, uae_u16 word)
1.1       root      846: {
1.1.1.7   root      847:     uae_u16 *buf;
1.1       root      848: 
1.1.1.7   root      849:     buf = &mfmbuf[mfmpos >> 4];
                    850:     word <<= 1;
                    851:     word |= (buf[0] & (1 << (15 - (mfmpos & 15)))) ? 1 : 0;
                    852:     return word;
1.1       root      853: }
                    854: 
1.1.1.7   root      855: /* emulate disk read dma for full horizontal line */
                    856: static void disk_doupdate_read (drive * drv)
                    857: {
                    858:     int hpos = disk_hpos;
                    859:     int is_sync = 0, dmaon;
                    860:     int j = 0, l = 0, k = 0;
                    861: 
                    862:     while (hpos < (MAXHPOS << 8)) {
                    863:        word = getonebit (drv->bigmfmbuf, drv->mfmpos, word);
                    864:        drv->mfmpos++;
                    865:        drv->mfmpos %= drv->tracklen;
                    866:        if (!drv->mfmpos) {
                    867:            disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
                    868:            is_sync = 1;
                    869:        }
                    870:        bitoffset++;
                    871:        bitoffset &= 15;
                    872:        if (bitoffset == 0 && (!(adkcon & 0x400) || syncfound))
                    873:            dmaon = 1;
                    874:        else
                    875:            dmaon = 0;
                    876:        if (word == dsksync) {
                    877:            if ((adkcon & 0x400) == 0x400 && ! syncfound) {
                    878:                syncfound = 1;
                    879:                bitoffset = 0;
                    880:            }
                    881:            disk_sync[hpos >> 8] |= DISK_WORDSYNC;
                    882:            is_sync = 1;
                    883:        }
                    884:        if (dmaon) {
                    885:            dma_tab[j++] = word;
                    886:            if (j == MAX_DISK_WORDS_PER_LINE - 1) {
                    887:                write_log ("Bug: Disk DMA buffer overflow!\n");
                    888:                j--;
                    889:            }
                    890:        }
                    891:        if (bitoffset == 0 || bitoffset == 8) {
                    892:            dskbytr_tab[k] = (word & 0xff) | 0x8000;
                    893:            dskbytr_cycle[k++] = hpos >> 8;
                    894:            if (bitoffset == 0) {
                    895:                dskdatr_tab[l] = word;
                    896:                dskdatr_cycle[l++] = hpos >> 8;
                    897:            }
                    898:        }
                    899:        hpos += drv->trackspeed;
                    900:     }
                    901:     dma_tab[j] = 0xffffffff;
                    902:     if (is_sync)
                    903:        disk_events (0);
                    904:     dskbytr_cycle[k] = 255;
                    905:     dskdatr_cycle[l] = 255;
                    906: 
                    907:     disk_hpos = hpos - (MAXHPOS << 8);
                    908: }
                    909: 
                    910: /* disk DMA fetch happens on real Amiga at the beginning of next horizontal line
                    911:    (cycles 9, 11 and 13 according to hardware manual) We transfer all DMA'd
                    912:    data at cycle 0. I don't think any program cares about this small difference.
                    913: */
                    914: static void dodmafetch (void)
1.1       root      915: {
1.1.1.7   root      916:     int i;
                    917: 
                    918:     i = 0;
                    919:     while (dma_tab[i] != 0xffffffff && dskdmaen == 2 && (dmacon & 0x210) == 0x210) {
                    920:        put_word (dskpt, dma_tab[i]);
                    921:        dskpt += 2;
                    922:        dsklength--;
                    923:        if (dsklength == 0) {
                    924:            disk_dmafinished ();
                    925:            break;
                    926:        }
                    927:        i++;
                    928:     }
                    929:     dma_tab[0] = 0xffffffff;
1.1       root      930: }
                    931: 
1.1.1.7   root      932: static void DISK_start (void)
1.1.1.6   root      933: {
                    934:     int dr;
1.1.1.7   root      935: 
1.1.1.6   root      936:     for (dr = 0; dr < 4; dr++) {
1.1.1.7   root      937:        drive *drv = &floppy[dr];
                    938:        if (!(selected & (1 << dr))) {
                    939:            int tr = drv->cyl * 2 + side;
                    940:            trackid *ti = drv->trackdata + tr;
                    941: 
                    942:            drive_fill_bigbuf (drv);
                    943:            if (dskdmaen == 3) {
                    944:                drv->tracklen = FLOPPY_WRITE_LEN * 8 * 2;
                    945:                drv->trackspeed = floppy_speed;
                    946:            }
                    947:            /* Ugh.  A nasty hack.  Assume ADF_EXT1 tracks are always read
                    948:               from the start.  */
                    949:            if (ti->type == TRACK_RAW1)
                    950:                drv->mfmpos = 0;
                    951:            drv->mfmpos %= drv->tracklen;
1.1.1.6   root      952:        }
                    953:     }
1.1.1.7   root      954:     syncfound = 0;
                    955:     dmaon = 0;
                    956:     word = 0;
                    957:     bitoffset = 0;
                    958:     dma_tab[0] = 0xffffffff;
1.1.1.6   root      959: }
                    960: 
1.1.1.7   root      961: static int linecounter;
                    962: 
                    963: void DISK_update (void)
1.1       root      964: {
                    965:     int dr;
1.1.1.7   root      966:     
1.1.1.6   root      967:     for (dr = 0; dr < 4; dr++) {
1.1.1.7   root      968:        drive *drv = &floppy[dr];
                    969:        drv->mfmpos_hsync = drv->mfmpos;
                    970:     }
                    971:     if (linecounter) {
                    972:        linecounter--;
                    973:        if (! linecounter)
                    974:            disk_dmafinished ();
                    975:        return;
                    976:     }
                    977: 
                    978:     dodmafetch ();
                    979:     indexsync_last_cycle = -1;
                    980: 
                    981:     for (dr = 0; dr < 4; dr++) {
                    982:        drive *drv = &floppy[dr];
                    983:        if (drv->motoroff)
                    984:            continue;
                    985:        if (selected & (1 << dr)) {
                    986:            drv->mfmpos += (MAXHPOS << 8) / drv->trackspeed;
                    987:            drv->mfmpos %= drv->tracklen;
                    988:            continue;
1.1       root      989:        }
1.1.1.7   root      990:        if (dskdmaen == 3)
                    991:            disk_doupdate_write (drv);
                    992:        else
                    993:            disk_doupdate_read (drv);
                    994:        return;
1.1       root      995:     }
                    996: }
1.1.1.6   root      997: 
1.1.1.7   root      998: void DSKLEN (uae_u16 v, int hpos)
1.1.1.6   root      999: {
1.1.1.7   root     1000:     if (v & 0x8000) {
                   1001:        dskdmaen = dskdmaen == 1 ? 2 : 1;
                   1002:     } else {
                   1003:        /* Megalomania does this */
                   1004: #if 0
                   1005:        if (dskdmaen == 2)
                   1006:            write_log ("warning: Disk read DMA aborted, %d words left\n", dsklength);
                   1007: #endif
                   1008:        if (dskdmaen == 3)
                   1009:            write_log ("warning: Disk write DMA aborted, %d words left\n", dsklength);
                   1010:        dskdmaen = 0;
                   1011:     }
                   1012:     dsklength = v & 0x3fff;
                   1013:     if (dskdmaen <= 1)
                   1014:        return;
                   1015:     if (v & 0x4000)
                   1016:        dskdmaen = 3;
                   1017: #ifdef DISK_DEBUG
                   1018:     {
                   1019:        int dr;
                   1020:        for (dr = 0; dr < 4; dr++) {
                   1021:            drive *drv = &floppy[dr];
                   1022:            if (drv->motoroff)
                   1023:                continue;
                   1024:            if ((selected & (1 << dr)) == 0)
                   1025:                break;
                   1026:        }
                   1027:        if (dr == 4)
                   1028:            write_log ("disk DMA started, but no drive ready!\n");
                   1029:        else
                   1030:            write_log ("disk %s DMA started for %d words (%08.8X) sync=%04.4X track %d\n",
                   1031:                       dskdmaen == 3 ? "write" : "read", dsklength, dskpt,
                   1032:                       (adkcon & 0x400) ? dsksync : 0xffff,
                   1033:                       floppy[dr].cyl * 2 + side);
                   1034:     }
                   1035: #endif
                   1036:     /* Megalomania does not work if DSKLEN write is delayed to next horizontal line,
                   1037:        also it seems some copy protections require this fix */
                   1038:     DISK_start ();
1.1.1.6   root     1039: 
1.1.1.7   root     1040:     /* Try to make floppy access from Kickstart faster.  */
                   1041:     if (dskdmaen != 2)
                   1042:        return;
                   1043:     {
                   1044:        int dr;
                   1045:        uaecptr pc = m68k_getpc ();
                   1046:        if ((pc & 0xF80000) != 0xF80000)
                   1047:            return;
                   1048:        for (dr = 0; dr < 4; dr++) {
                   1049:            drive *drv = &floppy[dr];
                   1050:            if (drv->motoroff)
                   1051:                continue;
                   1052:            if ((selected & (1 << dr)) == 0) {
                   1053:                int pos = drv->mfmpos & ~15;
                   1054:                int i;
                   1055: 
                   1056:                if (adkcon & 0x400) {
                   1057:                    for (i = 0; i < drv->tracklen; i += 16) {
                   1058:                        pos += 16;
                   1059:                        pos %= drv->tracklen;
                   1060:                        if (drv->bigmfmbuf[pos >> 4] == dsksync)
                   1061:                            break;
                   1062:                    }
                   1063:                    if (i >= drv->tracklen)
                   1064:                        return;
                   1065:                }
                   1066:                while (dsklength-- > 0) {
                   1067:                    put_word (dskpt, drv->bigmfmbuf[pos >> 4]);
                   1068:                    dskpt += 2;
                   1069:                    pos += 16;
                   1070:                    pos %= drv->tracklen;
1.1.1.6   root     1071:                }
1.1.1.7   root     1072:                INTREQ (0x9000);
                   1073:                linecounter = 2;
                   1074:                dskdmaen = 0;
                   1075:                return;
1.1.1.6   root     1076:            }
                   1077:        }
1.1.1.7   root     1078:     }
1.1.1.6   root     1079: }
                   1080: 
1.1.1.7   root     1081: /* this unoptimized code should be enough (DSKBYTR and DSKDATR are used very rarely) */
                   1082: 
                   1083: uae_u16 DSKBYTR (int hpos)
1.1.1.6   root     1084: {
1.1.1.7   root     1085:     uae_u16 v;
                   1086:     int i;
                   1087: 
                   1088:     i = 0;
                   1089:     while (hpos > dskbytr_cycle[i])
                   1090:        i++;
                   1091:     v = dskbytr_tab[i];
                   1092:     if (indexsync_last_cycle >= 0 && indexsync_last_cycle <= hpos)
                   1093:        v |= 0x1000;
                   1094:     dskbytr_tab[i] &= ~0x8000;
                   1095:     if (dskdmaen && (dmacon & 0x210) == 0x210)
                   1096:        v |= 0x4000;
                   1097:     if (dskdmaen == 3)
                   1098:        v |= 0x2000;
                   1099:     return v;
                   1100: }
                   1101: 
                   1102: uae_u16 DSKDATR (int hpos)
                   1103: {
                   1104:     int i;
                   1105: 
                   1106:     i = 0;
                   1107:     while (hpos > dskdatr_cycle[i])
                   1108:        i++;
                   1109:     return dskdatr_tab[i];
                   1110: }
                   1111: 
                   1112: void DSKSYNC (uae_u16 v)
                   1113: {
                   1114:     dsksync = v;
                   1115: }
                   1116: 
                   1117: void DSKDAT (uae_u16 v)
                   1118: {
                   1119:     static int count = 0;
                   1120:     if (count < 5) {
                   1121:        count++;
                   1122:        write_log ("DSKDAT written. Not good.");
                   1123:        if (count == 5)
                   1124:            write_log ("(further messages suppressed)");
                   1125: 
                   1126:        write_log ("\n");
1.1.1.6   root     1127:     }
                   1128: }
1.1.1.7   root     1129: void DSKPTH (uae_u16 v)
                   1130: {
                   1131:     dskpt = (dskpt & 0xffff) | ((uae_u32) v << 16);
                   1132: }
1.1.1.6   root     1133: 
1.1.1.7   root     1134: void DSKPTL (uae_u16 v)
1.1.1.6   root     1135: {
1.1.1.7   root     1136:     dskpt = (dskpt & ~0xffff) | (v);
1.1.1.6   root     1137: }
                   1138: 
1.1.1.7   root     1139: void DISK_init (void)
                   1140: {
                   1141:     int i;
                   1142: 
                   1143:     dma_tab[0] = 0xffffffff;
                   1144:     dskbytr_cycle[0] = 255;
                   1145:     dskdatr_cycle[0] = 255;
                   1146:     indexsync_last_cycle = -1;
                   1147: 
1.1.1.8   root     1148:     for (i = 0; i < 4; i++) {
1.1.1.7   root     1149:        if (!drive_insert (floppy + i, i, currprefs.df[i]))
                   1150:            disk_eject (i);
1.1.1.8   root     1151:     }
1.1.1.7   root     1152:     if (disk_empty (0))
                   1153:        write_log ("No disk in drive 0.\n");
                   1154: }
                   1155: 
1.1.1.8   root     1156: void DISK_reset (void)
                   1157: {
                   1158:     int i;
                   1159:     disk_hpos = 0;
                   1160:     for (i = 0; i < 4; i++) {
                   1161:        floppy[i].disabled = 0;
                   1162:        if (i >= currprefs.nr_floppies)
                   1163:            floppy[i].disabled = 1;
                   1164:     }
                   1165: }
                   1166: 
1.1.1.7   root     1167: void dumpdisk (void)
                   1168: {
                   1169:     int i;
                   1170:     for (i = 0; i < 4; i++) {
                   1171:        drive *drv = &floppy[i];
                   1172:        printf ("Drive %d: motor %s cylinder %2d selected %d\n", i, drv->motoroff ? "off" : " on", drv->cyl, selected & (1 << i));
                   1173:     }
                   1174: }

unix.superglobalmegacorp.com

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