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

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

unix.superglobalmegacorp.com

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