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

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.11  root        6:   * Copyright 1995 Hannu Rummukainen
                      7:   * Copyright 1995-2001 Bernd Schmidt
                      8:   * Copyright 2000, 2001 Toni Wilen
                      9:   *
                     10:   * High Density Drive Handling by Dr. Adil Temel (C) 2001 [[email protected]]
                     11:   *
1.1       root       12:   */
                     13: 
1.1.1.2   root       14: #include <stdio.h>
                     15: 
1.1       root       16: #include "sysconfig.h"
                     17: #include "sysdeps.h"
                     18: 
                     19: #include "options.h"
1.1.1.12  root       20: #include "threaddep/thread.h"
1.1       root       21: #include "memory.h"
                     22: #include "events.h"
                     23: #include "custom.h"
                     24: #include "ersatz.h"
                     25: #include "disk.h"
                     26: #include "gui.h"
                     27: #include "zfile.h"
1.1.1.2   root       28: #include "autoconf.h"
                     29: #include "newcpu.h"
                     30: #include "xwin.h"
                     31: #include "osemu.h"
                     32: #include "execlib.h"
1.1.1.11  root       33: #include "savestate.h"
1.1.1.20! root       34: #include "crc32.h"
1.1.1.2   root       35: 
1.1.1.20! root       36: /* support HD floppies */
        !            37: #define FLOPPY_DRIVE_HD
1.1.1.7   root       38: /* writable track length with normal 2us bitcell/300RPM motor */
1.1.1.13  root       39: #define FLOPPY_WRITE_LEN (12650 / 2)
                     40: /* This works out to 341 */
                     41: #define FLOPPY_GAP_LEN (FLOPPY_WRITE_LEN - 11 * 544)
1.1.1.7   root       42: /* (cycles/bitcell) << 8, normal = ((2us/280ns)<<8) = ~1830 */
                     43: #define NORMAL_FLOPPY_SPEED 1830
                     44: 
1.1.1.20! root       45: #ifdef FLOPPY_DRIVE_HD
        !            46: #define DDHDMULT 2
        !            47: #else
        !            48: #define DDHDMULT 1
        !            49: #endif
        !            50: 
1.1.1.7   root       51: static int floppy_speed = NORMAL_FLOPPY_SPEED;
                     52: 
                     53: #undef DISK_DEBUG
1.1.1.11  root       54: #undef DEBUG_DRIVE_ID
1.1.1.7   root       55: 
                     56: /* UAE-1ADF (ADF_EXT2)
                     57:  * W   reserved
                     58:  * W   number of tracks (default 2*80=160)
                     59:  *
                     60:  * W   reserved
                     61:  * W   type, 0=normal AmigaDOS track, 1 = raw MFM
                     62:  * L   available space for track in bytes
                     63:  * L   track length in bits
                     64:  */
1.1       root       65: 
1.1.1.11  root       66: static int side, direction, writing;
1.1.1.12  root       67: static uae_u8 selected = 15, disabled;
1.1       root       68: 
1.1.1.20! root       69: static uae_u8 writebuffer[544 * 22 * DDHDMULT];
1.1.1.7   root       70: 
1.1.1.20! root       71: typedef enum { TRACK_AMIGADOS, TRACK_RAW, TRACK_RAW1, TRACK_PCDOS } image_tracktype;
1.1       root       72: typedef struct {
1.1.1.3   root       73:     uae_u32 offs;
1.1.1.20! root       74:     int bitlen, track;
1.1.1.7   root       75:     unsigned int sync;
                     76:     image_tracktype type;
1.1.1.20! root       77:     uae_u16 len;
1.1       root       78: } trackid;
                     79: 
1.1.1.2   root       80: #define MAX_TRACKS 328
                     81: 
1.1.1.20! root       82: /* We have three kinds of Amiga floppy drives
        !            83:  * - internal A500/A2000 drive:
        !            84:  *   ID is always DRIVE_ID_NONE (S.T.A.G expects this)
        !            85:  * - HD drive (A3000/A4000):
        !            86:  *   ID is DRIVE_ID_35DD if DD floppy is inserted or drive is empty
        !            87:  *   ID is DRIVE_ID_35HD if HD floppy is inserted
        !            88:  * - regular external drive:
        !            89:  *   ID is always DRIVE_ID_35DD
        !            90:  */
        !            91: 
        !            92: #define DRIVE_ID_NONE  0x00000000
        !            93: #define DRIVE_ID_35DD  0xFFFFFFFF
1.1.1.11  root       94: #define DRIVE_ID_35HD  0xAAAAAAAA
1.1.1.20! root       95: #define DRIVE_ID_525SD 0x55555555 /* 40 track 5.25 drive , kickstart does not recognize this */
1.1.1.11  root       96: 
1.1.1.7   root       97: typedef enum { ADF_NORMAL, ADF_EXT1, ADF_EXT2 } drive_filetype;
1.1       root       98: typedef struct {
1.1.1.20! root       99:     drive_type type;
        !           100:     struct zfile *diskfile;
1.1       root      101:     drive_filetype filetype;
1.1.1.2   root      102:     trackid trackdata[MAX_TRACKS];
1.1.1.7   root      103:     int buffered_cyl, buffered_side;
                    104:     int cyl;
1.1       root      105:     int motoroff;
1.1.1.7   root      106:     int state;
1.1       root      107:     int wrprot;
1.1.1.11  root      108:     uae_u16 bigmfmbuf[0x8000];
1.1       root      109:     int mfmpos;
1.1.1.7   root      110:     int tracklen;
                    111:     int trackspeed;
                    112:     int dmalen;
                    113:     int num_tracks, num_secs;
1.1.1.20! root      114:     int hard_num_cyls;
1.1.1.3   root      115:     int dskchange;
                    116:     int dskchange_time;
1.1.1.10  root      117:     int dskready;
                    118:     int dskready_time;
1.1.1.11  root      119:     int steplimit;
                    120:     int ddhd; /* 1=DD 2=HD */
                    121:     int drive_id_scnt; /* drive id shift counter */
1.1.1.20! root      122:     int idbit;
1.1.1.11  root      123:     unsigned long drive_id; /* drive id to be reported */
1.1.1.12  root      124:     char newname[256]; /* storage space for new filename during eject delay */
1.1       root      125: } drive;
                    126: 
1.1.1.11  root      127: static drive floppy[4];
                    128: 
                    129: /* Keeps track of whether the Amiga program seems to be using the data coming
                    130:    in from the disk; if this remains 0 for several seconds, we stop calling
                    131:    disk_doupdate_read, even if the motor is still on.  This is a rather large
                    132:    performance win.  This contains the number of frames since we last accessed
                    133:    the disk.  */
                    134: static int disk_data_used;
                    135: 
                    136: #ifdef DEBUG_DRIVE_ID
1.1.1.20! root      137: static char *drive_id_name (drive *drv)
1.1.1.11  root      138: {
1.1.1.20! root      139:     switch (drv->drive_id)
1.1.1.11  root      140:     {
                    141:     case DRIVE_ID_35HD : return "3.5HD";
                    142:     case DRIVE_ID_525DD: return "5.25DD";
                    143:     case DRIVE_ID_35DD : return "3.5DD";
                    144:     }
1.1.1.18  root      145:     return "UNKNOWN";
1.1.1.11  root      146: }
                    147: #endif
                    148: 
1.1.1.18  root      149: /* Simulate exact behaviour of an A3000T 3.5 HD disk drive.
1.1.1.11  root      150:  * The drive reports to be a 3.5 DD drive whenever there is no
                    151:  * disk or a 3.5 DD disk is inserted. Only 3.5 HD drive id is reported
                    152:  * when a real 3.5 HD disk is inserted. -Adil
                    153:  */
1.1.1.20! root      154: static void drive_settype_id (drive *drv)
1.1.1.11  root      155: {
1.1.1.20! root      156:     int t = drv->type;
        !           157: 
        !           158:     switch (t)
        !           159:     {
        !           160:     case DRV_35_HD:
        !           161: #ifdef FLOPPY_DRIVE_HD
        !           162:        if (!drv->diskfile || drv->ddhd <= 1)
        !           163:            drv->drive_id = DRIVE_ID_35DD;
        !           164:        else
        !           165:            drv->drive_id = DRIVE_ID_35HD;
        !           166: #else
1.1.1.11  root      167:        drv->drive_id = DRIVE_ID_35DD;
1.1.1.20! root      168: #endif
        !           169:        break;
        !           170:     case DRV_35_DD_ESCOM:
        !           171:     case DRV_35_DD:
        !           172:     default:
        !           173:        drv->drive_id = DRIVE_ID_35DD;
        !           174:        break;
        !           175:     case DRV_525_SD:
        !           176:        drv->drive_id = DRIVE_ID_525SD;
        !           177:        break;
        !           178:     case DRV_NONE:
        !           179:        drv->drive_id = DRIVE_ID_NONE;
        !           180:        break;
1.1.1.11  root      181:     }
                    182: #ifdef DEBUG_DRIVE_ID
1.1.1.20! root      183:     write_log ("drive_settype_id: DF%d: set to %s\n", drv-floppy, drive_id_name (drv));
        !           184: #endif
        !           185: #ifdef DEBUG_DRIVE_ID
        !           186:     write_log ("drive_settype_id: DF%d: set to %s\n", drv-floppy, drive_id_name (drv));
1.1.1.11  root      187: #endif
                    188: }
1.1       root      189: 
1.1.1.7   root      190: /* code for track display */
1.1.1.8   root      191: static void update_drive_gui (int num)
1.1.1.7   root      192: {
1.1.1.8   root      193:     drive *drv = floppy + num;
                    194: 
1.1.1.7   root      195:     if (drv->state == gui_data.drive_motor[num]
                    196:        && drv->cyl == gui_data.drive_track[num]
                    197:        && ((writing && gui_data.drive_writing[num])
                    198:            || (!writing && !gui_data.drive_writing[num]))) {
                    199:        return;
                    200:     }
                    201:     gui_data.drive_motor[num] = drv->state;
                    202:     gui_data.drive_track[num] = drv->cyl;
                    203:     if (!gui_data.drive_writing[num])
                    204:        gui_data.drive_writing[num] = writing;
1.1.1.8   root      205:     gui_ledstate &= ~(2 << num);
                    206:     if (drv->state)
                    207:        gui_ledstate |= 2 << num;
1.1.1.7   root      208:     gui_led (num + 1, gui_data.drive_motor[num]);
                    209: }
                    210: 
1.1.1.20! root      211: static void drive_fill_bigbuf (drive *drv);
1.1       root      212: 
1.1.1.20! root      213: static void drive_image_free (drive *drv)
1.1       root      214: {
1.1.1.20! root      215:     drv->filetype = -1;
        !           216:     if (!drv->diskfile)
        !           217:        return;
        !           218:     zfile_fclose (drv->diskfile);
        !           219:     drv->diskfile = 0;
        !           220: }
        !           221: 
        !           222: struct zfile *DISK_validate_filename (const char *fname, int leave_open, int *wrprot)
        !           223: {
        !           224:     struct zfile *f = zfile_open (fname, "r+b");
1.1.1.3   root      225:     if (f) {
                    226:        if (wrprot)
                    227:            *wrprot = 0;
1.1       root      228:     } else {
1.1.1.3   root      229:        if (wrprot)
                    230:            *wrprot = 1;
1.1.1.4   root      231:        f = zfile_open (fname, "rb");
1.1       root      232:     }
1.1.1.3   root      233:     if (!leave_open)
1.1.1.20! root      234:        zfile_fclose (f);
1.1.1.3   root      235:     return f;
                    236: }
                    237: 
1.1.1.20! root      238: static void track_reset (drive *drv)
        !           239: {
        !           240:     drv->tracklen = FLOPPY_WRITE_LEN * 2 * 8;
        !           241:     drv->trackspeed = floppy_speed;
        !           242:     drv->buffered_side = -1;
        !           243:     memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
        !           244: }
        !           245: 
        !           246: static int read_header_ext2 (struct zfile *diskfile, trackid *trackdata, int *num_tracks, int *ddhd)
        !           247: {
        !           248:     uae_u8 buffer[2 + 2 + 4 + 4];
        !           249:     int offs;
        !           250:     int i;
        !           251: 
        !           252:     zfile_fseek (diskfile, 0, SEEK_SET);
        !           253:     zfile_fread (buffer, 1, 8, diskfile);
        !           254:     if (strncmp ((char *)buffer, "UAE-1ADF", 8))
        !           255:        return 0;
        !           256: 
        !           257:     zfile_fread (buffer, 1, 4, diskfile);
        !           258:     *num_tracks = buffer[2] * 256 + buffer[3];
        !           259:     offs = 8 + 2 + 2 + *num_tracks * (2 + 2 + 4 + 4);
        !           260: 
        !           261:     for (i = 0; i < *num_tracks; i++) {
        !           262:        trackid *tid = trackdata + i;
        !           263:        zfile_fread (buffer, 2 + 2 + 4 + 4, 1, diskfile);
        !           264:        tid->type = buffer[2] * 256 + buffer[3];
        !           265:        tid->len = buffer[5] * 65536 + buffer[6] * 256 + buffer[7];
        !           266:        tid->bitlen = buffer[9] * 65536 + buffer[10] * 256 + buffer[11];
        !           267:        tid->offs = offs;
        !           268:        if (tid->len > 20000 && ddhd)
        !           269:            *ddhd = 2;
        !           270:        tid->track = i;
        !           271:        offs += tid->len;
        !           272:     }
        !           273:     return 1;
        !           274: }
        !           275: 
        !           276: static int drive_insert (drive *drv, int dnum, const char *fname)
1.1.1.3   root      277: {
1.1.1.7   root      278:     unsigned char buffer[2 + 2 + 4 + 4];
                    279:     trackid *tid;
1.1.1.20! root      280:     int size;
1.1.1.3   root      281: 
1.1.1.20! root      282:     drive_image_free (drv);
1.1.1.3   root      283:     drv->diskfile = DISK_validate_filename (fname, 1, &drv->wrprot);
1.1.1.20! root      284:     drv->ddhd = 1;
        !           285:     drv->num_secs = 0;
        !           286:     drv->hard_num_cyls = drv->type == DRV_525_SD ? 40 : 80;
        !           287: 
1.1.1.6   root      288:     if (drv->diskfile == 0) {
1.1.1.20! root      289:        track_reset (drv);
1.1.1.3   root      290:        return 0;
1.1.1.6   root      291:     }
1.1.1.3   root      292:     strncpy (currprefs.df[dnum], fname, 255);
                    293:     currprefs.df[dnum][255] = 0;
                    294:     strncpy (changed_prefs.df[dnum], fname, 255);
                    295:     changed_prefs.df[dnum][255] = 0;
1.1.1.7   root      296:     gui_filename (dnum, fname);
1.1.1.3   root      297: 
1.1.1.20! root      298:     memset (buffer, 0, sizeof (buffer));
        !           299:     size = 0;
        !           300:     if (drv->diskfile) {
        !           301:        zfile_fread (buffer, sizeof (char), 8, drv->diskfile);
        !           302:        zfile_fseek (drv->diskfile, 0, SEEK_END);
        !           303:        size = zfile_ftell (drv->diskfile);
        !           304:        zfile_fseek (drv->diskfile, 0, SEEK_SET);
        !           305:     }
        !           306: 
1.1.1.7   root      307:     if (strncmp ((char *) buffer, "UAE-1ADF", 8) == 0) {
1.1.1.20! root      308:        read_header_ext2 (drv->diskfile, drv->trackdata, &drv->num_tracks, &drv->ddhd);
1.1.1.7   root      309: 
                    310:        drv->filetype = ADF_EXT2;
                    311:        drv->num_secs = 11;
1.1.1.20! root      312:        if (drv->ddhd > 1)
        !           313:            drv->num_secs = 22;
1.1.1.7   root      314:     } else if (strncmp ((char *) buffer, "UAE--ADF", 8) == 0) {
                    315:        int offs = 160 * 4 + 8;
1.1       root      316:        int i;
1.1.1.3   root      317: 
                    318:        drv->filetype = ADF_EXT1;
1.1.1.2   root      319:        drv->num_tracks = 160;
                    320:        drv->num_secs = 11;
1.1.1.3   root      321: 
1.1.1.20! root      322:        zfile_fseek (drv->diskfile, 8, SEEK_SET);
        !           323: 
1.1.1.7   root      324:        drv->wrprot = 1;        /* write to adf_ext1 not implemented */
                    325:        for (i = 0; i < 160; i++) {
                    326:            tid = &drv->trackdata[i];
1.1.1.20! root      327:            zfile_fread (buffer, 4, 1, drv->diskfile);
1.1.1.7   root      328:            tid->sync = buffer[0] * 256 + buffer[1];
                    329:            tid->len = buffer[2] * 256 + buffer[3];
                    330:            tid->offs = offs;
                    331:            if (tid->sync == 0) {
                    332:                tid->type = TRACK_AMIGADOS;
                    333:                tid->bitlen = 0;
                    334:            } else {
                    335:                tid->type = TRACK_RAW1;
                    336:                tid->bitlen = tid->len * 8;
                    337:            }
                    338:            offs += tid->len;
1.1       root      339:        }
                    340:     } else {
1.1.1.7   root      341:        int i;
1.1.1.3   root      342:        drv->filetype = ADF_NORMAL;
1.1.1.2   root      343: 
                    344:        /* High-density disk? */
1.1.1.20! root      345:        if (size >= 160 * 22 * 512) {
        !           346:            drv->num_tracks = size / (512 * (drv->num_secs = 22));
        !           347:            drv->ddhd = 2;
        !           348:        } else
        !           349:            drv->num_tracks = size / (512 * (drv->num_secs = 11));
1.1.1.3   root      350: 
1.1.1.2   root      351:        if (drv->num_tracks > MAX_TRACKS)
1.1.1.3   root      352:            write_log ("Your diskfile is too big!\n");
1.1.1.7   root      353:        for (i = 0; i < drv->num_tracks; i++) {
                    354:            tid = &drv->trackdata[i];
                    355:            tid->type = TRACK_AMIGADOS;
                    356:            tid->len = 512 * drv->num_secs;
                    357:            tid->bitlen = 0;
                    358:            tid->offs = i * 512 * drv->num_secs;
1.1       root      359:        }
                    360:     }
1.1.1.20! root      361:     drive_settype_id (drv);    /* Set DD or HD drive */
1.1.1.7   root      362:     drv->buffered_side = 2;    /* will force read */
1.1.1.6   root      363:     drive_fill_bigbuf (drv);
1.1.1.3   root      364:     return 1;
1.1       root      365: }
                    366: 
1.1.1.7   root      367: static int drive_empty (drive * drv)
1.1.1.2   root      368: {
1.1.1.3   root      369:     return drv->diskfile == 0;
1.1.1.2   root      370: }
                    371: 
1.1.1.7   root      372: static void drive_step (drive * drv)
1.1       root      373: {
1.1.1.11  root      374:     if (drv->steplimit)
                    375:        return;
                    376:     /* A1200's floppy drive needs at least 30 raster lines between steps
                    377:      * but we'll use very small value for better compatibility with faster CPU emulation
                    378:      * (stupid trackloaders with CPU delay loops)
                    379:      */
                    380:     drv->steplimit = 2;
1.1.1.12  root      381:     if (!drive_empty (drv))
                    382:        drv->dskchange = 0;
1.1       root      383:     if (direction) {
1.1.1.7   root      384:        if (drv->cyl)
                    385:            drv->cyl--;
1.1.1.11  root      386: /*     else
1.1.1.20! root      387:            write_log ("program tried to step beyond track zero\n");
1.1.1.11  root      388:            "no-click" programs does that
                    389: */
                    390:   } else {
1.1.1.7   root      391:        if (drv->cyl < 83)
                    392:            drv->cyl++;
1.1.1.11  root      393:        else
1.1.1.20! root      394:            write_log ("program tried to step over track 83\n");
1.1       root      395:     }
                    396: 
1.1.1.7   root      397: #if 0 && defined DISK_DEBUG
                    398:     write_log ("track %d\n", drv->cyl);
                    399: #endif
                    400: }
1.1       root      401: 
1.1.1.7   root      402: static int drive_track0 (drive * drv)
1.1       root      403: {
1.1.1.3   root      404:     return drv->cyl == 0;
1.1       root      405: }
                    406: 
1.1.1.7   root      407: static int drive_writeprotected (drive * drv)
1.1       root      408: {
1.1.1.3   root      409:     return drv->wrprot || drv->diskfile == NULL;
1.1       root      410: }
                    411: 
1.1.1.7   root      412: static int drive_running (drive * drv)
1.1       root      413: {
1.1.1.3   root      414:     return !drv->motoroff;
1.1       root      415: }
                    416: 
1.1.1.7   root      417: static void drive_motor (drive * drv, int off)
1.1       root      418: {
1.1.1.12  root      419:     /* A value of 5 works out to a guaranteed delay of 1/2 of a second
1.1.1.10  root      420:        Higher values are dangerous, e.g. a value of 8 breaks the RSI
                    421:        demo.  */
1.1.1.11  root      422:     if (drv->motoroff && !off) {
1.1.1.12  root      423:        drv->dskready_time = 5;
1.1.1.11  root      424:        disk_data_used = 0;
                    425: #ifdef DEBUG_DRIVE_ID
1.1.1.20! root      426:        write_log ("drive_motor: Selected DF%d: reset id shift reg.\n", drv-floppy);
1.1.1.11  root      427: #endif
                    428:     }
1.1.1.20! root      429:     if (!drv->motoroff && off) {
        !           430:        drv->drive_id_scnt = 0; /* Reset id shift reg counter */
        !           431:     }
1.1       root      432:     drv->motoroff = off;
1.1.1.10  root      433:     if (drv->motoroff) {
                    434:        drv->dskready = 0;
                    435:        drv->dskready_time = 0;
                    436:     }
1.1       root      437: }
                    438: 
1.1.1.20! root      439: static void read_floppy_data (struct zfile *diskfile, trackid *ti, int offset, unsigned char *dst, int len)
1.1.1.7   root      440: {
1.1.1.20! root      441:     zfile_fseek (diskfile, ti->offs + offset, SEEK_SET);
        !           442:     zfile_fread (dst, 1, len, diskfile);
        !           443: }
1.1.1.7   root      444: 
1.1.1.20! root      445: static void reset_drive (int i)
        !           446: {
        !           447:     drive *drv = &floppy[i];
        !           448:     drive_image_free (drv);
        !           449:     drv->motoroff = 1;
        !           450:     disabled &= ~(1 << i);
        !           451:     if (currprefs.dfxtype[i] < 0)
        !           452:        disabled |= 1 << i;
        !           453: 
        !           454:     drv->dskchange_time = 0;
        !           455:     drv->buffered_cyl = -1;
        !           456:     drv->buffered_side = -1;
        !           457:     gui_led (i + 1, 0);
        !           458:     drive_settype_id (drv);
        !           459:     strcpy (currprefs.df[i], changed_prefs.df[i]);
        !           460:     drv->newname[0] = 0;
        !           461:     if (!drive_insert (drv, i, currprefs.df[i]))
        !           462:        disk_eject (i);
        !           463: }
        !           464: 
        !           465: static uae_u8 mfmencodetable[16] = {
        !           466:     0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15,
        !           467:     0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55
        !           468: };
        !           469: 
        !           470: 
        !           471: static uae_u16 dos_encode_byte (uae_u8 byte)
        !           472: {           
        !           473:     uae_u8 b2, b1;        
        !           474:     uae_u16 word;
        !           475: 
        !           476:     b1 = byte;
        !           477:     b2 = b1 >> 4;
        !           478:     b1 &= 15;
        !           479:     word = mfmencodetable[b2] <<8 | mfmencodetable[b1];
        !           480:     return (word | ((word & (256 | 64)) ? 0 : 128));
        !           481: }
        !           482: 
        !           483: static uae_u16 *mfmcoder (uae_u8 *src, uae_u16 *dest, int len) 
        !           484: {
        !           485:     int i;
        !           486: 
        !           487:     for (i = 0; i < len; i++) {
        !           488:        *dest = dos_encode_byte (*src++);
        !           489:        *dest |= ((dest[-1] & 1)|| (*dest & 0x4000)) ? 0: 0x8000;            
        !           490:        dest++;
        !           491:     }
        !           492:     return dest;
        !           493: }
        !           494: 
        !           495: static void decode_pcdos (drive *drv)
        !           496: {
        !           497:     int i;
        !           498:     int tr = drv->cyl * 2 + side;
        !           499:     uae_u16 *dstmfmbuf, *mfm2;
        !           500:     uae_u8 secbuf[700];
        !           501:     uae_u16 crc16;
        !           502:     trackid *ti = drv->trackdata + tr;
        !           503: 
        !           504:     mfm2 = drv->bigmfmbuf;
        !           505:     *mfm2++ = 0x9254;
        !           506:     memset (secbuf, 0x4e, 80); // 94
        !           507:     memset (secbuf + 80, 0x00, 12); // 12
        !           508:     secbuf[92] = 0xc2;
        !           509:     secbuf[93] = 0xc2;
        !           510:     secbuf[94] = 0xc2;
        !           511:     secbuf[95] = 0xfc;
        !           512:     memset (secbuf + 96, 0x4e, 50); // 50
        !           513:     dstmfmbuf = mfmcoder (secbuf, mfm2, 146);
        !           514:     mfm2[92] = 0x5224;
        !           515:     mfm2[93] = 0x5224;
        !           516:     mfm2[94] = 0x5224;
        !           517:     for (i = 0; i < drv->num_secs; i++) {
        !           518:        mfm2 = dstmfmbuf;
        !           519:        memset (secbuf, 0x00, 12);
        !           520:        secbuf[12] = 0xa1;
        !           521:        secbuf[13] = 0xa1;
        !           522:        secbuf[14] = 0xa1;
        !           523:        secbuf[15] = 0xfe;
        !           524:        secbuf[16] = drv->cyl;
        !           525:        secbuf[17] = side;
        !           526:        secbuf[18] = 1 + i;
        !           527:        secbuf[19] = 2; // 128 << 2 = 512
        !           528:        crc16 = get_crc16 (secbuf + 12, 3 + 1 + 4);
        !           529:        secbuf[20] = crc16 >> 8;
        !           530:        secbuf[21] = crc16 & 0xff;
        !           531:        memset (secbuf + 22, 0x4e, 22);
        !           532:        memset (secbuf + 44, 0x00, 12);
        !           533:        secbuf[56] = 0xa1;
        !           534:        secbuf[57] = 0xa1;
        !           535:        secbuf[58] = 0xa1;
        !           536:        secbuf[59] = 0xfb;
        !           537:        read_floppy_data (drv->diskfile, ti, i * 512, &secbuf[60], 512);
        !           538:        crc16 = get_crc16 (secbuf + 56, 3 + 1 + 512);
        !           539:        secbuf[60 + 512] = crc16 >> 8;
        !           540:        secbuf[61 + 512] = crc16 & 0xff;
        !           541:        memset (secbuf + 512 + 62, 0x4e, 76 / drv->ddhd);
        !           542:        dstmfmbuf = mfmcoder (secbuf, mfm2, 60 + 512 + 2 + 76 / drv->ddhd);
        !           543:        mfm2[12] = 0x4489;
        !           544:        mfm2[13] = 0x4489;
        !           545:        mfm2[14] = 0x4489;
        !           546:        mfm2[56] = 0x4489;
        !           547:        mfm2[57] = 0x4489;
        !           548:        mfm2[58] = 0x4489;
        !           549:     }
        !           550:     for (i = 0; i < 200; i++)
        !           551:        *dstmfmbuf++ = 0x9254;
        !           552:     drv->tracklen = (dstmfmbuf - drv->bigmfmbuf) * 16;
1.1.1.7   root      553: }
                    554: 
                    555: /* Megalomania does not like zero MFM words... */
                    556: static void mfmcode (uae_u16 * mfm, int words)
                    557: {
1.1.1.8   root      558:     uae_u32 lastword = 0;
1.1.1.7   root      559: 
                    560:     while (words--) {
1.1.1.8   root      561:        uae_u32 v = *mfm;
                    562:        uae_u32 lv = (lastword << 16) | v;
                    563:        uae_u32 nlv = 0x55555555 & ~lv;
                    564:        uae_u32 mfmbits = (nlv << 1) & (nlv >> 1);
                    565: 
                    566:        *mfm++ = v | mfmbits;
                    567:        lastword = v;
1.1.1.7   root      568:     }
                    569: }
                    570: 
1.1.1.20! root      571: static void decode_amigados (drive *drv)
        !           572: {
        !           573:     /* Normal AmigaDOS format track */
        !           574:     int tr = drv->cyl * 2 + side;
        !           575:     int sec;
        !           576:     int dstmfmoffset = 0;
        !           577:     uae_u16 *dstmfmbuf = drv->bigmfmbuf;
        !           578:     int len = drv->num_secs * 544 + FLOPPY_GAP_LEN;
        !           579:     trackid *ti = drv->trackdata + tr;
        !           580: 
        !           581:     memset (dstmfmbuf, 0xaa, len * 2);
        !           582:     dstmfmoffset += FLOPPY_GAP_LEN;
        !           583:     drv->tracklen = len * 2 * 8;
        !           584: 
        !           585:     for (sec = 0; sec < drv->num_secs; sec++) {
        !           586:        uae_u8 secbuf[544];
        !           587:        uae_u16 mfmbuf[544];
        !           588:        int i;
        !           589:        uae_u32 deven, dodd;
        !           590:        uae_u32 hck = 0, dck = 0;
        !           591: 
        !           592:        secbuf[0] = secbuf[1] = 0x00;
        !           593:        secbuf[2] = secbuf[3] = 0xa1;
        !           594:        secbuf[4] = 0xff;
        !           595:        secbuf[5] = tr;
        !           596:        secbuf[6] = sec;
        !           597:        secbuf[7] = drv->num_secs - sec;
        !           598: 
        !           599:        for (i = 8; i < 24; i++)
        !           600:            secbuf[i] = 0;
        !           601: 
        !           602:        read_floppy_data (drv->diskfile, ti, sec * 512, &secbuf[32], 512);
        !           603: 
        !           604:        mfmbuf[0] = mfmbuf[1] = 0xaaaa;
        !           605:        mfmbuf[2] = mfmbuf[3] = 0x4489;
        !           606: 
        !           607:        deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
        !           608:                 | (secbuf[6] << 8) | (secbuf[7]));
        !           609:        dodd = deven >> 1;
        !           610:        deven &= 0x55555555;
        !           611:        dodd &= 0x55555555;
        !           612: 
        !           613:        mfmbuf[4] = dodd >> 16;
        !           614:        mfmbuf[5] = dodd;
        !           615:        mfmbuf[6] = deven >> 16;
        !           616:        mfmbuf[7] = deven;
        !           617: 
        !           618:        for (i = 8; i < 48; i++)
        !           619:            mfmbuf[i] = 0xaaaa;
        !           620:        for (i = 0; i < 512; i += 4) {
        !           621:            deven = ((secbuf[i + 32] << 24) | (secbuf[i + 33] << 16)
        !           622:                     | (secbuf[i + 34] << 8) | (secbuf[i + 35]));
        !           623:            dodd = deven >> 1;
        !           624:            deven &= 0x55555555;
        !           625:            dodd &= 0x55555555;
        !           626:            mfmbuf[(i >> 1) + 32] = dodd >> 16;
        !           627:            mfmbuf[(i >> 1) + 33] = dodd;
        !           628:            mfmbuf[(i >> 1) + 256 + 32] = deven >> 16;
        !           629:            mfmbuf[(i >> 1) + 256 + 33] = deven;
        !           630:        }
        !           631: 
        !           632:        for (i = 4; i < 24; i += 2)
        !           633:            hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
        !           634: 
        !           635:        deven = dodd = hck;
        !           636:        dodd >>= 1;
        !           637:        mfmbuf[24] = dodd >> 16;
        !           638:        mfmbuf[25] = dodd;
        !           639:        mfmbuf[26] = deven >> 16;
        !           640:        mfmbuf[27] = deven;
        !           641: 
        !           642:        for (i = 32; i < 544; i += 2)
        !           643:            dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
        !           644: 
        !           645:        deven = dodd = dck;
        !           646:        dodd >>= 1;
        !           647:        mfmbuf[28] = dodd >> 16;
        !           648:        mfmbuf[29] = dodd;
        !           649:        mfmbuf[30] = deven >> 16;
        !           650:        mfmbuf[31] = deven;
        !           651:        mfmcode (mfmbuf + 4, 544 - 4);
        !           652: 
        !           653:        for (i = 0; i < 544; i++) {
        !           654:            dstmfmbuf[dstmfmoffset % len] = mfmbuf[i];
        !           655:            dstmfmoffset++;
        !           656:        }
        !           657:     }
        !           658: #ifdef DISK_DEBUG
        !           659:     write_log ("amigados read track %d\n", tr);
        !           660: #endif
        !           661: }
        !           662: 
1.1.1.7   root      663: static void drive_fill_bigbuf (drive * drv)
1.1       root      664: {
1.1.1.7   root      665:     int tr = drv->cyl * 2 + side;
                    666:     trackid *ti = drv->trackdata + tr;
1.1.1.3   root      667: 
1.1.1.7   root      668:     if (!drv->diskfile || tr >= drv->num_tracks) {
1.1.1.11  root      669:        drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 2 * 8;
1.1.1.7   root      670:        drv->trackspeed = floppy_speed;
1.1.1.11  root      671:        memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
1.1.1.2   root      672:        return;
                    673:     }
1.1.1.3   root      674:     if (drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
                    675:        return;
                    676: 
1.1.1.20! root      677:     if (ti->type == TRACK_PCDOS) {
        !           678:        decode_pcdos (drv);
1.1.1.7   root      679: 
1.1.1.20! root      680:     } else if (ti->type == TRACK_AMIGADOS) {
        !           681:        decode_amigados (drv);
1.1       root      682:     } else {
                    683:        int i;
1.1.1.7   root      684:        int base_offset = ti->type == TRACK_RAW ? 0 : 1;
                    685:        drv->tracklen = ti->bitlen + 16 * base_offset;
                    686:        drv->bigmfmbuf[0] = ti->sync;
1.1.1.20! root      687:        read_floppy_data (drv->diskfile, ti, 0, (unsigned char *) (drv->bigmfmbuf + base_offset), (ti->bitlen + 7) / 8);
1.1.1.10  root      688:        for (i = base_offset; i < (drv->tracklen + 15) / 16; i++) {
1.1.1.7   root      689:            uae_u16 *mfm = drv->bigmfmbuf + i;
                    690:            uae_u8 *data = (uae_u8 *) mfm;
                    691:            *mfm = 256 * *data + *(data + 1);
1.1       root      692:        }
1.1.1.7   root      693: #if 0 && defined DISK_DEBUG
                    694:        write_log ("rawtrack %d\n", tr);
                    695: #endif
1.1       root      696:     }
1.1.1.3   root      697:     drv->buffered_side = side;
                    698:     drv->buffered_cyl = drv->cyl;
1.1.1.7   root      699:     drv->trackspeed = floppy_speed * drv->tracklen / (2 * 8 * FLOPPY_WRITE_LEN);
1.1       root      700: }
                    701: 
1.1.1.7   root      702: /* Update ADF_EXT2 track header */
                    703: static void diskfile_update (drive * drv, int len, uae_u8 type)
1.1       root      704: {
1.1.1.7   root      705:     trackid *ti;
                    706:     int track;
                    707:     uae_u8 buf[2 + 2 + 4 + 4], *zerobuf;
1.1.1.3   root      708: 
1.1.1.7   root      709:     if (drv->filetype != ADF_EXT2)
                    710:        return;
1.1.1.6   root      711: 
1.1.1.7   root      712:     track = drv->cyl * 2 + side;
                    713:     ti = &drv->trackdata[track];
                    714:     ti->bitlen = len;
1.1.1.20! root      715:     zfile_fseek (drv->diskfile, 8 + 4 + (2 + 2 + 4 + 4) * track, SEEK_SET);
1.1.1.7   root      716:     memset (buf, 0, sizeof buf);
                    717:     ti->type = type;
                    718:     buf[3] = ti->type;
                    719:     do_put_mem_long ((uae_u32 *) (buf + 4), ti->len);
                    720:     do_put_mem_long ((uae_u32 *) (buf + 8), ti->bitlen);
1.1.1.20! root      721:     zfile_fwrite (buf, sizeof (buf), 1, drv->diskfile);
1.1.1.7   root      722:     if (ti->len > (len + 7) / 8) {
                    723:        zerobuf = malloc (ti->len);
                    724:        memset (zerobuf, 0, ti->len);
1.1.1.20! root      725:        zfile_fseek (drv->diskfile, ti->offs, SEEK_SET);
        !           726:        zfile_fwrite (zerobuf, 1, ti->len, drv->diskfile);
1.1.1.7   root      727:        free (zerobuf);
                    728:     }
                    729: #ifdef DISK_DEBUG
                    730:     write_log ("track %d, raw track length %d written (total size %d)\n", track, (ti->bitlen + 7) / 8, ti->len);
                    731: #endif
1.1       root      732: }
                    733: 
                    734: #define MFMMASK 0x55555555
1.1.1.7   root      735: static uae_u32 getmfmlong (uae_u16 * mbuf)
1.1       root      736: {
                    737:     return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK;
                    738: }
                    739: 
1.1.1.7   root      740: static int drive_write_adf_amigados (drive * drv)
1.1       root      741: {
                    742:     int i, secwritten = 0;
1.1.1.11  root      743:     int fwlen = FLOPPY_WRITE_LEN * drv->ddhd;
                    744:     int length = 2 * fwlen;
                    745:     int drvsec= drv->num_secs;
1.1.1.3   root      746:     uae_u32 odd, even, chksum, id, dlong;
1.1.1.7   root      747:     uae_u8 *secdata;
1.1.1.3   root      748:     uae_u8 secbuf[544];
1.1.1.7   root      749:     uae_u16 *mbuf = drv->bigmfmbuf;
1.1.1.3   root      750:     uae_u16 *mend = mbuf + length;
1.1.1.11  root      751:     char sectable[22];
1.1.1.7   root      752:     memset (sectable, 0, sizeof (sectable));
1.1.1.11  root      753:     memcpy (mbuf + fwlen, mbuf, fwlen * sizeof (uae_u16));
1.1       root      754:     mend -= (4 + 16 + 8 + 512);
1.1.1.11  root      755:     while (secwritten < drvsec) {
1.1       root      756:        int trackoffs;
1.1.1.3   root      757: 
1.1       root      758:        do {
                    759:            while (*mbuf++ != 0x4489) {
1.1.1.4   root      760:                if (mbuf >= mend)
1.1.1.7   root      761:                    return 1;
1.1       root      762:            }
                    763:        } while (*mbuf++ != 0x4489);
1.1.1.3   root      764: 
1.1.1.4   root      765:        odd = getmfmlong (mbuf);
                    766:        even = getmfmlong (mbuf + 2);
1.1.1.3   root      767:        mbuf += 4;
1.1       root      768:        id = (odd << 1) | even;
1.1.1.3   root      769: 
1.1       root      770:        trackoffs = (id & 0xff00) >> 8;
1.1.1.11  root      771:        if (trackoffs + 1 > drvsec) {
1.1.1.7   root      772:            if (drv->filetype == ADF_EXT2)
                    773:                return 2;
1.1.1.5   root      774:            write_log ("Disk write: weird sector number %d\n", trackoffs);
1.1       root      775:            continue;
                    776:        }
                    777:        chksum = odd ^ even;
1.1.1.4   root      778:        for (i = 0; i < 4; i++) {
1.1.1.7   root      779:            odd = getmfmlong (mbuf);
                    780:            even = getmfmlong (mbuf + 8);
1.1       root      781:            mbuf += 2;
1.1.1.3   root      782: 
1.1       root      783:            dlong = (odd << 1) | even;
1.1.1.7   root      784:            if (dlong) {
                    785:                if (drv->filetype == ADF_EXT2)
                    786:                    return 6;
1.1.1.4   root      787:                secwritten = -200;
1.1.1.7   root      788:            }
1.1       root      789:            chksum ^= odd ^ even;
1.1.1.7   root      790:        }                       /* could check here if the label is nonstandard */
1.1       root      791:        mbuf += 8;
1.1.1.7   root      792:        odd = getmfmlong (mbuf);
                    793:        even = getmfmlong (mbuf + 2);
                    794:        mbuf += 4;
                    795:        if (((odd << 1) | even) != chksum || ((id & 0x00ff0000) >> 16) != drv->cyl * 2 + side) {
                    796:            if (drv->filetype == ADF_EXT2)
                    797:                return 3;
                    798:            write_log ("Disk write: checksum error on sector %d header\n", trackoffs);
1.1       root      799:            continue;
                    800:        }
1.1.1.7   root      801:        odd = getmfmlong (mbuf);
                    802:        even = getmfmlong (mbuf + 2);
                    803:        mbuf += 4;
1.1       root      804:        chksum = (odd << 1) | even;
                    805:        secdata = secbuf + 32;
1.1.1.7   root      806:        for (i = 0; i < 128; i++) {
                    807:            odd = getmfmlong (mbuf);
                    808:            even = getmfmlong (mbuf + 256);
                    809:            mbuf += 2;
1.1       root      810:            dlong = (odd << 1) | even;
1.1.1.7   root      811:            *secdata++ = dlong >> 24;
                    812:            *secdata++ = dlong >> 16;
                    813:            *secdata++ = dlong >> 8;
                    814:            *secdata++ = dlong;
1.1       root      815:            chksum ^= odd ^ even;
                    816:        }
                    817:        mbuf += 256;
                    818:        if (chksum) {
1.1.1.7   root      819:            if (drv->filetype == ADF_EXT2)
                    820:                return 4;
                    821:            write_log ("Disk write: sector %d, data checksum error\n", trackoffs);
1.1       root      822:            continue;
                    823:        }
1.1.1.7   root      824:        sectable[trackoffs] = 1;
1.1       root      825:        secwritten++;
1.1.1.7   root      826:        memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
1.1       root      827:     }
1.1.1.7   root      828:     if (drv->filetype == ADF_EXT2 && (secwritten == 0 || secwritten < 0))
                    829:        return 5;
1.1.1.3   root      830:     if (secwritten == 0)
                    831:        write_log ("Disk write in unsupported format\n");
1.1       root      832:     if (secwritten < 0)
1.1.1.3   root      833:        write_log ("Disk write: sector labels ignored\n");
1.1.1.7   root      834: 
1.1.1.11  root      835:     diskfile_update (drv, drvsec * 512 * 8, TRACK_AMIGADOS);
                    836:     for (i = 0; i < drvsec; i++) {
1.1.1.20! root      837:        zfile_fseek (drv->diskfile, drv->trackdata[drv->cyl * 2 + side].offs + i * 512, SEEK_SET);
        !           838:        zfile_fwrite (writebuffer + i * 512, sizeof (uae_u8), 512, drv->diskfile);
1.1.1.7   root      839:     }
                    840: 
                    841:     return 0;
1.1       root      842: }
                    843: 
1.1.1.7   root      844: /* write raw track to disk file */
                    845: static int drive_write_ext2 (drive * drv)
                    846: {
                    847:     trackid *ti;
                    848:     int len, track, i;
1.1       root      849: 
1.1.1.7   root      850:     track = drv->cyl * 2 + side;
                    851:     ti = &drv->trackdata[track];
                    852:     len = (drv->tracklen + 7) / 8;
                    853:     if (len > ti->len) {
                    854:        write_log ("disk raw write: image file's track %d is too small (%d < %d)!\n", track, ti->len, len);
                    855:        return 0;
                    856:     }
                    857:     diskfile_update (drv, drv->tracklen, TRACK_RAW);
                    858:     for (i = 0; i < drv->trackdata[track].len / 2; i++) {
                    859:        uae_u16 *mfm = drv->bigmfmbuf + i;
                    860:        uae_u8 *data = (uae_u8 *) mfm;
                    861:        *mfm = 256 * *data + *(data + 1);
                    862:     }
1.1.1.20! root      863:     zfile_fseek (drv->diskfile, ti->offs, SEEK_SET);
        !           864:     zfile_fwrite (drv->bigmfmbuf, 1, len, drv->diskfile);
1.1.1.7   root      865:     return 1;
                    866: }
                    867: 
                    868: static void drive_write_data (drive * drv)
1.1       root      869: {
1.1.1.7   root      870:     int ret;
                    871:     if (drive_writeprotected (drv))
                    872:        return;
                    873:     switch (drv->filetype) {
                    874:     case ADF_NORMAL:
                    875:        drive_write_adf_amigados (drv);
                    876:        break;
                    877:     case ADF_EXT1:
                    878:        write_log ("writing to ADF_EXT1 not supported\n");
                    879:        return;
                    880:     case ADF_EXT2:
                    881:        ret = drive_write_adf_amigados (drv);
                    882:        if (ret) {
1.1.1.20! root      883:            /*write_log ("not an amigados track (error %d), writing as raw track\n", ret); */
1.1.1.7   root      884:            drive_write_ext2 (drv);
                    885:        }
                    886:        break;
                    887:     }
                    888:     drv->buffered_side = 2;    /* will force read */
                    889: }
                    890: 
                    891: static void drive_eject (drive * drv)
                    892: {
1.1.1.20! root      893:     drive_image_free (drv);
1.1.1.12  root      894:     drv->dskchange = 1;
1.1.1.20! root      895:     drv->ddhd = 1;
        !           896:     drv->dskchange_time = 0;
        !           897:     drv->dskready = 0;
        !           898:     drv->dskready_time = 0;
        !           899:     drive_settype_id (drv); /* Back to 35 DD */
1.1.1.12  root      900: #ifdef DISK_DEBUG
                    901:     write_log ("eject drive %d\n", drv - &floppy[0]);
                    902: #endif
1.1       root      903: }
                    904: 
1.1.1.3   root      905: /* We use this function if we have no Kickstart ROM.
1.1       root      906:  * No error checking - we trust our luck. */
1.1.1.3   root      907: void DISK_ersatz_read (int tr, int sec, uaecptr dest)
1.1       root      908: {
1.1.1.7   root      909:     uae_u8 *dptr = get_real_address (dest);
1.1.1.20! root      910:     zfile_fseek (floppy[0].diskfile, floppy[0].trackdata[tr].offs + sec * 512, SEEK_SET);
        !           911:     zfile_fread (dptr, 1, 512, floppy[0].diskfile);
1.1       root      912: }
                    913: 
1.1.1.4   root      914: void disk_eject (int num)
1.1       root      915: {
1.1.1.7   root      916:     gui_filename (num, "");
                    917:     drive_eject (floppy + num);
1.1.1.3   root      918:     *currprefs.df[num] = *changed_prefs.df[num] = 0;
1.1.1.12  root      919:     floppy[num].newname[0] = 0;
1.1       root      920: }
                    921: 
1.1.1.4   root      922: void disk_insert (int num, const char *name)
1.1       root      923: {
1.1.1.12  root      924:     drive *drv = floppy + num;
1.1.1.20! root      925: 
        !           926:     if (!strcmp (currprefs.df[num], name))
        !           927:        return;
        !           928:     strcpy (drv->newname, name);
        !           929:     strcpy (currprefs.df[num], name);
        !           930: 
1.1.1.12  root      931:     if (name[0] == 0) {
                    932:        disk_eject (num);
1.1.1.20! root      933:     } else if (!drive_empty (drv) || drv->dskchange_time > 0) {
1.1.1.12  root      934:        drive_eject (drv);
1.1.1.20! root      935:        /* set dskchange_time, disk_insert () will be
        !           936:         * called from DISK_check_change () after 1 second delay
1.1.1.12  root      937:         * this makes sure that all programs detect disk change correctly
                    938:         */
                    939:        drv->dskchange_time = 10; /* 1 second disk change delay */
                    940:     } else {
1.1.1.20! root      941:        drv->dskchange_time = 1;
1.1.1.12  root      942:     }
1.1       root      943: }
                    944: 
1.1.1.3   root      945: void DISK_check_change (void)
                    946: {
                    947:     int i;
                    948: 
                    949:     for (i = 0; i < 4; i++) {
1.1.1.12  root      950:        drive *drv = floppy + i;
1.1.1.14  root      951:        gui_lock ();
1.1.1.20! root      952:        if (currprefs.dfxtype[i] != changed_prefs.dfxtype[i]) {
        !           953:            drv->type = currprefs.dfxtype[i] = changed_prefs.dfxtype[i];
        !           954:            reset_drive (i);
1.1.1.12  root      955:        }
1.1.1.20! root      956:        if (drv->dskchange_time == 0 && strcmp (currprefs.df[i], changed_prefs.df[i]))
        !           957:            disk_insert (i, changed_prefs.df[i]);
1.1.1.14  root      958:        gui_unlock ();
1.1.1.12  root      959:        /* emulate drive motor turn on time */
1.1.1.20! root      960:        if (drv->dskready_time && !drive_empty (drv)) {
1.1.1.12  root      961:            drv->dskready_time--;
                    962:            if (drv->dskready_time == 0)
                    963:                drv->dskready = 1;
                    964:        }
                    965:        /* delay until new disk image is inserted */
                    966:        if (drv->dskchange_time) {
                    967:            drv->dskchange_time--;
                    968:            if (drv->dskchange_time == 0) {
                    969:                drive_insert (drv, i, drv->newname);
                    970: #ifdef DISK_DEBUG
                    971:                write_log ("delayed insert, drive %d, image '%s'\n", i, drv->newname);
                    972: #endif
                    973:                drv->newname[0] = 0;
1.1.1.3   root      974:            }
                    975:        }
                    976:     }
                    977: }
                    978: 
1.1.1.4   root      979: int disk_empty (int num)
1.1       root      980: {
1.1.1.4   root      981:     return drive_empty (floppy + num);
1.1       root      982: }
                    983: 
1.1.1.11  root      984: static int step;
1.1.1.10  root      985: 
1.1.1.4   root      986: void DISK_select (uae_u8 data)
1.1       root      987: {
1.1.1.11  root      988:     int step_pulse, lastselected;
1.1       root      989:     int dr;
1.1.1.11  root      990:     static uae_u8 prevdata;
1.1.1.3   root      991: 
1.1.1.10  root      992:     lastselected = selected;
1.1       root      993:     selected = (data >> 3) & 15;
1.1.1.12  root      994:     selected |= disabled;
                    995:     if (selected != lastselected)
                    996:        disk_data_used = 1;
1.1.1.3   root      997:     side = 1 - ((data >> 2) & 1);
                    998: 
1.1       root      999:     direction = (data >> 1) & 1;
                   1000:     step_pulse = data & 1;
                   1001:     if (step != step_pulse) {
                   1002:        step = step_pulse;
1.1.1.11  root     1003:        if (step) {
1.1.1.7   root     1004:            for (dr = 0; dr < 4; dr++) {
1.1.1.20! root     1005:                if (!((selected | disabled) & (1 << dr))) {
1.1.1.4   root     1006:                    drive_step (floppy + dr);
1.1       root     1007:                }
                   1008:            }
                   1009:        }
                   1010:     }
1.1.1.20! root     1011:     if (!savestate_state) {
        !          1012:        for (dr = 0; dr < 4; dr++) {
        !          1013:            drive *drv = floppy + dr;
        !          1014:            /* motor on/off workings tested with small assembler code on real Amiga 1200. */
        !          1015:            /* motor/id flipflop is set only when drive select goes from high to low */
        !          1016:            if (!(selected & (1 << dr)) && (lastselected & (1 << dr)) ) {
        !          1017:                drv->drive_id_scnt++;
        !          1018:                drv->drive_id_scnt &= 31;
        !          1019:                drv->idbit = (drv->drive_id & (1L << (31 - drv->drive_id_scnt))) ? 1 : 0;
        !          1020:                if (!(disabled & (1 << dr))) {
        !          1021:                    if ((prevdata & 0x80) == 0 || (data & 0x80) == 0) {
        !          1022:                        /* motor off: if motor bit = 0 in prevdata or data -> turn motor on */
        !          1023:                        drive_motor (drv, 0);
        !          1024:                    } else if (prevdata & 0x80) {
        !          1025:                        /* motor on: if motor bit = 1 in prevdata only (motor flag state in data has no effect)
        !          1026:                           -> turn motor off */
        !          1027:                        drive_motor (drv, 1);
        !          1028:                    }
        !          1029:                }
1.1.1.11  root     1030:            }
1.1       root     1031:        }
                   1032:     }
                   1033:     for (dr = 0; dr < 4; dr++) {
1.1.1.7   root     1034:        floppy[dr].state = (!(selected & (1 << dr))) | !floppy[dr].motoroff;
1.1.1.8   root     1035:        update_drive_gui (dr);
1.1       root     1036:     }
1.1.1.11  root     1037:     prevdata = data;
1.1       root     1038: }
                   1039: 
1.1.1.4   root     1040: uae_u8 DISK_status (void)
1.1       root     1041: {
1.1.1.3   root     1042:     uae_u8 st = 0x3c;
1.1       root     1043:     int dr;
1.1.1.3   root     1044: 
1.1.1.7   root     1045:     for (dr = 0; dr < 4; dr++) {
1.1.1.3   root     1046:        drive *drv = floppy + dr;
1.1.1.20! root     1047:        if (!((selected | disabled) & (1 << dr))) {
1.1.1.7   root     1048:            if (drive_running (drv)) {
1.1.1.11  root     1049:                if (drv->dskready)
1.1.1.7   root     1050:                    st &= ~0x20;
1.1.1.12  root     1051:            } else {
1.1.1.11  root     1052:                /* report drive ID */
1.1.1.20! root     1053:                if (drv->idbit && currprefs.dfxtype[dr] != DRV_35_DD_ESCOM)
1.1.1.11  root     1054:                    st &= ~0x20;
1.1.1.18  root     1055: #ifdef DEBUG_DRIVE_ID
1.1.1.20! root     1056:                write_log ("DISK_status: sel %d id %s [0x%08lx, bit #%02d: %d]\n",
        !          1057:                           dr, drive_id_name (drv), drv->drive_id << drv->drive_id_scnt, 31 - drv->drive_id_scnt, st & 0x20 ? 1:0);
1.1.1.12  root     1058: #endif
1.1       root     1059:            }
1.1.1.12  root     1060:            if (drive_track0 (drv))
1.1.1.7   root     1061:                st &= ~0x10;
1.1.1.12  root     1062:            if (drive_writeprotected (drv))
1.1.1.7   root     1063:                st &= ~8;
1.1.1.12  root     1064:            if (drv->dskchange)
                   1065:                st &= ~4;
1.1.1.20! root     1066:        } else if (!(selected & (1 << dr))) {
        !          1067:            if (drv->idbit)
        !          1068:                st &= ~0x20;
1.1.1.18  root     1069:        }
1.1       root     1070:     }
                   1071:     return st;
                   1072: }
                   1073: 
1.1.1.7   root     1074: #define MAX_DISK_WORDS_PER_LINE 50     /* depends on floppy_speed */
                   1075: 
                   1076: #define DISK_INDEXSYNC 1
                   1077: #define DISK_WORDSYNC 2
                   1078: 
                   1079: static uae_u16 dskbytr_tab[MAX_DISK_WORDS_PER_LINE * 2 + 1];
                   1080: static uae_u8 dskbytr_cycle[MAX_DISK_WORDS_PER_LINE * 2 + 1];
1.1.1.11  root     1081: static short wordsync_cycle[MAX_DISK_WORDS_PER_LINE * 2 + 1];
1.1.1.7   root     1082: static uae_u32 dma_tab[MAX_DISK_WORDS_PER_LINE + 1];
                   1083: static uae_u8 disk_sync[MAXHPOS];
                   1084: static int disk_sync_cycle;
                   1085: static int dskdmaen, dsklength;
                   1086: static uae_u16 dsksync;
                   1087: static uae_u32 dskpt;
                   1088: 
                   1089: static void disk_dmafinished (void)
                   1090: {
                   1091:     INTREQ (0x8002);
1.1.1.15  root     1092:     dskdmaen = 0; /* ??? */
1.1.1.11  root     1093: #ifdef DISK_DEBUG
1.1.1.20! root     1094:     write_log ("disk dma finished %08.8X\n", dskpt);
1.1.1.11  root     1095: #endif
1.1.1.18  root     1096: }
1.1.1.7   root     1097: 
                   1098: static void disk_events (int last)
                   1099: {
                   1100:     eventtab[ev_disk].active = 0;
1.1.1.11  root     1101:     for (disk_sync_cycle = last; disk_sync_cycle < maxhpos; disk_sync_cycle++) {
1.1.1.7   root     1102:        if (disk_sync[disk_sync_cycle]) {
1.1.1.10  root     1103:            eventtab[ev_disk].oldcycles = get_cycles ();
                   1104:            eventtab[ev_disk].evtime = get_cycles () + (disk_sync_cycle - last) * CYCLE_UNIT;
1.1.1.7   root     1105:            eventtab[ev_disk].active = 1;
                   1106:            events_schedule ();
                   1107:            return;
1.1       root     1108:        }
                   1109:     }
                   1110: }
                   1111: 
1.1.1.7   root     1112: extern void cia_diskindex (void);
1.1.1.3   root     1113: 
1.1.1.7   root     1114: void DISK_handler (void)
                   1115: {
                   1116:     eventtab[ev_disk].active = 0;
1.1.1.11  root     1117:     if (disk_sync[disk_sync_cycle] & DISK_WORDSYNC)
1.1.1.7   root     1118:        INTREQ (0x9000);
1.1.1.11  root     1119:     if (disk_sync[disk_sync_cycle] & DISK_INDEXSYNC)
1.1.1.7   root     1120:        cia_diskindex ();
                   1121:     disk_sync[disk_sync_cycle] = 0;
                   1122:     disk_events (disk_sync_cycle);
                   1123: }
1.1.1.3   root     1124: 
1.1.1.12  root     1125: static int dma_enable, bitoffset;
                   1126: static uae_u32 word;
1.1       root     1127: 
1.1.1.7   root     1128: /* Always carried through to the next line.  */
                   1129: static int disk_hpos;
1.1.1.2   root     1130: 
1.1.1.7   root     1131: /* emulate disk write dma for full horizontal line */
                   1132: static void disk_doupdate_write (drive * drv)
                   1133: {
                   1134:     int hpos = disk_hpos;
1.1.1.11  root     1135:     while (hpos < (maxhpos << 8)) {
1.1.1.7   root     1136:        drv->mfmpos++;
                   1137:        drv->mfmpos %= drv->tracklen;
                   1138:        if (!drv->mfmpos) {
                   1139:            disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
                   1140:            disk_events (0);
                   1141:        }
                   1142:        if ((dmacon & 0x210) == 0x210 && dskdmaen == 3) {
                   1143:            bitoffset++;
                   1144:            bitoffset &= 15;
                   1145:            if (!bitoffset) {
                   1146:                drv->bigmfmbuf[drv->mfmpos >> 4] = get_word (dskpt);
                   1147:                dskpt += 2;
                   1148:                dsklength--;
                   1149:                if (dsklength == 0) {
                   1150:                    disk_dmafinished ();
                   1151:                    drive_write_data (drv);
                   1152:                }
1.1       root     1153:            }
                   1154:        }
1.1.1.7   root     1155:        hpos += drv->trackspeed;
1.1       root     1156:     }
1.1.1.11  root     1157:     disk_hpos = hpos - (maxhpos << 8);
1.1       root     1158: }
                   1159: 
1.1.1.7   root     1160: /* get one bit from MFM bit stream */
1.1.1.12  root     1161: static uae_u32 getonebit (uae_u16 * mfmbuf, int mfmpos, uae_u32 word)
1.1       root     1162: {
1.1.1.7   root     1163:     uae_u16 *buf;
1.1       root     1164: 
1.1.1.7   root     1165:     buf = &mfmbuf[mfmpos >> 4];
                   1166:     word <<= 1;
                   1167:     word |= (buf[0] & (1 << (15 - (mfmpos & 15)))) ? 1 : 0;
                   1168:     return word;
1.1       root     1169: }
                   1170: 
1.1.1.11  root     1171: #define WORDSYNC_CYCLES 7 /* (~7 * 280ns = 2us) */
                   1172: 
1.1.1.7   root     1173: /* emulate disk read dma for full horizontal line */
                   1174: static void disk_doupdate_read (drive * drv)
                   1175: {
                   1176:     int hpos = disk_hpos;
1.1.1.12  root     1177:     int is_sync = 0;
1.1.1.11  root     1178:     int j = 0, k = 1, l = 0;
1.1.1.12  root     1179:     uae_u16 synccheck;
1.1.1.11  root     1180:     static int dskbytr_last = 0, wordsync_last = -1;
1.1.1.7   root     1181: 
1.1.1.11  root     1182:     dskbytr_tab[0] = dskbytr_tab[dskbytr_last];
                   1183: 
                   1184:     if (wordsync_last >= 0 && maxhpos - wordsync_cycle[wordsync_last] < WORDSYNC_CYCLES)
                   1185:        wordsync_cycle[l++] = (maxhpos - wordsync_cycle[wordsync_last]) - WORDSYNC_CYCLES;
                   1186:     wordsync_last = -1;
                   1187: 
                   1188:     while (hpos < (maxhpos << 8)) {
                   1189:        if (drv->dskready)
                   1190:            word = getonebit (drv->bigmfmbuf, drv->mfmpos, word);
                   1191:        else
                   1192:            word <<= 1;
1.1.1.7   root     1193:        drv->mfmpos++;
                   1194:        drv->mfmpos %= drv->tracklen;
1.1.1.12  root     1195:        if (!drv->mfmpos) {
1.1.1.7   root     1196:            disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
                   1197:            is_sync = 1;
                   1198:        }
1.1.1.12  root     1199:        if (bitoffset == 31 && dma_enable) {
                   1200:            dma_tab[j++] = (word >> 16) & 0xffff;
1.1.1.7   root     1201:            if (j == MAX_DISK_WORDS_PER_LINE - 1) {
                   1202:                write_log ("Bug: Disk DMA buffer overflow!\n");
                   1203:                j--;
                   1204:            }
                   1205:        }
1.1.1.12  root     1206:        if (bitoffset == 15 || bitoffset == 23 || bitoffset == 31) {
                   1207:            dskbytr_tab[k] = (word >> 8) & 0xff;
1.1.1.11  root     1208:            dskbytr_tab[k] |= 0x8000;
                   1209:            dskbytr_last = k;
1.1.1.7   root     1210:            dskbytr_cycle[k++] = hpos >> 8;
                   1211:        }
1.1.1.12  root     1212:        synccheck = (word >> 8) & 0xffff;
                   1213:        if (synccheck == dsksync) {
                   1214:            if (adkcon & 0x400) {
                   1215:                if (bitoffset != 23 || !dma_enable)
                   1216:                    bitoffset = 7;
                   1217:                dma_enable = 1;
                   1218:            }
                   1219:            wordsync_last = l;
                   1220:            wordsync_cycle[l++] = hpos >> 8;
                   1221:            disk_sync[hpos >> 8] |= DISK_WORDSYNC;
                   1222:            is_sync = 1;
                   1223:        }
1.1.1.11  root     1224:        bitoffset++;
1.1.1.12  root     1225:        if (bitoffset == 32) bitoffset = 16;
1.1.1.7   root     1226:        hpos += drv->trackspeed;
                   1227:     }
                   1228:     dma_tab[j] = 0xffffffff;
1.1.1.11  root     1229:     dskbytr_cycle[k] = 255;
                   1230:     wordsync_cycle[l] = 255;
1.1.1.7   root     1231:     if (is_sync)
                   1232:        disk_events (0);
                   1233: 
1.1.1.11  root     1234:     disk_hpos = hpos - (maxhpos << 8);
1.1.1.7   root     1235: }
                   1236: 
                   1237: /* disk DMA fetch happens on real Amiga at the beginning of next horizontal line
                   1238:    (cycles 9, 11 and 13 according to hardware manual) We transfer all DMA'd
                   1239:    data at cycle 0. I don't think any program cares about this small difference.
1.1.1.12  root     1240: 
                   1241:    We must handle dsklength = 0 because some copy protections use it to detect
                   1242:    wordsync without transferring any data.
1.1.1.7   root     1243: */
                   1244: static void dodmafetch (void)
1.1       root     1245: {
1.1.1.7   root     1246:     int i;
                   1247: 
                   1248:     i = 0;
                   1249:     while (dma_tab[i] != 0xffffffff && dskdmaen == 2 && (dmacon & 0x210) == 0x210) {
1.1.1.12  root     1250:        if (dsklength > 0) {
                   1251:            put_word (dskpt, dma_tab[i++]);
                   1252:            dskpt += 2;
                   1253:            dsklength--;
                   1254:        }
1.1.1.7   root     1255:        if (dsklength == 0) {
                   1256:            disk_dmafinished ();
                   1257:            break;
                   1258:        }
                   1259:     }
                   1260:     dma_tab[0] = 0xffffffff;
1.1       root     1261: }
                   1262: 
1.1.1.17  root     1263: /* this is very unoptimized. DSKBYTR is used very rarely, so it should not matter. */
                   1264: 
                   1265: uae_u16 DSKBYTR (int hpos)
                   1266: {
                   1267:     uae_u16 v;
                   1268:     int i;
                   1269: 
                   1270:     i = 0;
                   1271:     while (hpos > dskbytr_cycle[i + 1])
                   1272:        i++;
                   1273:     v = dskbytr_tab[i];
                   1274:     dskbytr_tab[i] &= ~0x8000;
                   1275:     if (wordsync_cycle[0] != 255) {
                   1276:        i = 0;
                   1277:        while (hpos < wordsync_cycle[i])
                   1278:            i++;
                   1279:        if (hpos - wordsync_cycle[i] <= WORDSYNC_CYCLES)
                   1280:            v |= 0x1000;
                   1281:     }
                   1282:     if (dskdmaen && (dmacon & 0x210) == 0x210)
                   1283:        v |= 0x4000;
                   1284:     if (dskdmaen == 3)
                   1285:        v |= 0x2000;
                   1286: 
                   1287:     disk_data_used = 0;
                   1288: 
                   1289:     return v;
                   1290: }
                   1291: 
1.1.1.7   root     1292: static void DISK_start (void)
1.1.1.6   root     1293: {
                   1294:     int dr;
1.1.1.7   root     1295: 
1.1.1.6   root     1296:     for (dr = 0; dr < 4; dr++) {
1.1.1.7   root     1297:        drive *drv = &floppy[dr];
                   1298:        if (!(selected & (1 << dr))) {
                   1299:            int tr = drv->cyl * 2 + side;
                   1300:            trackid *ti = drv->trackdata + tr;
                   1301: 
                   1302:            if (dskdmaen == 3) {
1.1.1.11  root     1303:                drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 8 * 2;
1.1.1.7   root     1304:                drv->trackspeed = floppy_speed;
                   1305:            }
                   1306:            /* Ugh.  A nasty hack.  Assume ADF_EXT1 tracks are always read
                   1307:               from the start.  */
                   1308:            if (ti->type == TRACK_RAW1)
1.1.1.12  root     1309:                drv->mfmpos = 0;
1.1.1.6   root     1310:        }
                   1311:     }
1.1.1.12  root     1312:     dma_enable = (adkcon & 0x400) ? 0 : 1;
1.1.1.7   root     1313:     word = 0;
                   1314:     bitoffset = 0;
                   1315:     dma_tab[0] = 0xffffffff;
1.1.1.6   root     1316: }
                   1317: 
1.1.1.7   root     1318: static int linecounter;
                   1319: 
                   1320: void DISK_update (void)
1.1       root     1321: {
                   1322:     int dr;
1.1.1.18  root     1323: 
1.1.1.6   root     1324:     for (dr = 0; dr < 4; dr++) {
1.1.1.7   root     1325:        drive *drv = &floppy[dr];
1.1.1.11  root     1326:        if (drv->steplimit)
                   1327:            drv->steplimit--;
1.1.1.7   root     1328:     }
                   1329:     if (linecounter) {
                   1330:        linecounter--;
                   1331:        if (! linecounter)
                   1332:            disk_dmafinished ();
                   1333:        return;
                   1334:     }
                   1335: 
                   1336:     dodmafetch ();
                   1337: 
                   1338:     for (dr = 0; dr < 4; dr++) {
                   1339:        drive *drv = &floppy[dr];
                   1340:        if (drv->motoroff)
                   1341:            continue;
                   1342:        if (selected & (1 << dr)) {
1.1.1.11  root     1343:            drv->mfmpos += (maxhpos << 8) / drv->trackspeed;
1.1.1.7   root     1344:            drv->mfmpos %= drv->tracklen;
                   1345:            continue;
1.1       root     1346:        }
1.1.1.11  root     1347:        drive_fill_bigbuf (drv);
                   1348:        drv->mfmpos %= drv->tracklen;
                   1349:        if (dskdmaen > 1)
                   1350:            disk_data_used = 0;
                   1351: 
1.1.1.7   root     1352:        if (dskdmaen == 3)
                   1353:            disk_doupdate_write (drv);
1.1.1.12  root     1354:        else if (1 || disk_data_used < MAXVPOS * 50 * 2) {
1.1.1.11  root     1355:            disk_data_used++;
1.1.1.7   root     1356:            disk_doupdate_read (drv);
1.1.1.11  root     1357:        }
1.1.1.7   root     1358:        return;
1.1       root     1359:     }
                   1360: }
1.1.1.6   root     1361: 
1.1.1.7   root     1362: void DSKLEN (uae_u16 v, int hpos)
1.1.1.6   root     1363: {
1.1.1.7   root     1364:     if (v & 0x8000) {
                   1365:        dskdmaen = dskdmaen == 1 ? 2 : 1;
                   1366:     } else {
                   1367:        /* Megalomania does this */
                   1368: #if 0
                   1369:        if (dskdmaen == 2)
                   1370:            write_log ("warning: Disk read DMA aborted, %d words left\n", dsklength);
                   1371: #endif
                   1372:        if (dskdmaen == 3)
                   1373:            write_log ("warning: Disk write DMA aborted, %d words left\n", dsklength);
                   1374:        dskdmaen = 0;
                   1375:     }
1.1.1.12  root     1376:     dsklength = v & 0x3ffe;
1.1.1.7   root     1377:     if (dskdmaen <= 1)
                   1378:        return;
                   1379:     if (v & 0x4000)
                   1380:        dskdmaen = 3;
                   1381: #ifdef DISK_DEBUG
                   1382:     {
                   1383:        int dr;
                   1384:        for (dr = 0; dr < 4; dr++) {
                   1385:            drive *drv = &floppy[dr];
                   1386:            if (drv->motoroff)
                   1387:                continue;
                   1388:            if ((selected & (1 << dr)) == 0)
                   1389:                break;
                   1390:        }
                   1391:        if (dr == 4)
                   1392:            write_log ("disk DMA started, but no drive ready!\n");
                   1393:        else
                   1394:            write_log ("disk %s DMA started for %d words (%08.8X) sync=%04.4X track %d\n",
                   1395:                       dskdmaen == 3 ? "write" : "read", dsklength, dskpt,
                   1396:                       (adkcon & 0x400) ? dsksync : 0xffff,
                   1397:                       floppy[dr].cyl * 2 + side);
                   1398:     }
                   1399: #endif
                   1400:     /* Megalomania does not work if DSKLEN write is delayed to next horizontal line,
                   1401:        also it seems some copy protections require this fix */
                   1402:     DISK_start ();
1.1.1.6   root     1403: 
1.1.1.7   root     1404:     /* Try to make floppy access from Kickstart faster.  */
                   1405:     if (dskdmaen != 2)
                   1406:        return;
                   1407:     {
                   1408:        int dr;
                   1409:        uaecptr pc = m68k_getpc ();
                   1410:        if ((pc & 0xF80000) != 0xF80000)
                   1411:            return;
                   1412:        for (dr = 0; dr < 4; dr++) {
                   1413:            drive *drv = &floppy[dr];
                   1414:            if (drv->motoroff)
                   1415:                continue;
                   1416:            if ((selected & (1 << dr)) == 0) {
                   1417:                int pos = drv->mfmpos & ~15;
                   1418:                int i;
                   1419: 
1.1.1.11  root     1420:                drive_fill_bigbuf (drv);
1.1.1.7   root     1421:                if (adkcon & 0x400) {
                   1422:                    for (i = 0; i < drv->tracklen; i += 16) {
                   1423:                        pos += 16;
                   1424:                        pos %= drv->tracklen;
1.1.1.11  root     1425:                        if (drv->bigmfmbuf[pos >> 4] == dsksync) {
                   1426:                            /* must skip first disk sync marker */
1.1.1.12  root     1427:                            pos += 16;
1.1.1.11  root     1428:                            pos %= drv->tracklen;
1.1.1.7   root     1429:                            break;
1.1.1.11  root     1430:                        }
1.1.1.7   root     1431:                    }
                   1432:                    if (i >= drv->tracklen)
                   1433:                        return;
                   1434:                }
                   1435:                while (dsklength-- > 0) {
                   1436:                    put_word (dskpt, drv->bigmfmbuf[pos >> 4]);
                   1437:                    dskpt += 2;
                   1438:                    pos += 16;
                   1439:                    pos %= drv->tracklen;
1.1.1.6   root     1440:                }
1.1.1.7   root     1441:                INTREQ (0x9000);
                   1442:                linecounter = 2;
                   1443:                dskdmaen = 0;
                   1444:                return;
1.1.1.6   root     1445:            }
                   1446:        }
1.1.1.7   root     1447:     }
1.1.1.6   root     1448: }
                   1449: 
1.1.1.11  root     1450: /* not a real hardware register */
1.1.1.7   root     1451: uae_u16 DSKDATR (int hpos)
                   1452: {
1.1.1.11  root     1453:     return 0;
1.1.1.7   root     1454: }
                   1455: 
                   1456: void DSKSYNC (uae_u16 v)
                   1457: {
                   1458:     dsksync = v;
                   1459: }
                   1460: 
                   1461: void DSKDAT (uae_u16 v)
                   1462: {
                   1463:     static int count = 0;
                   1464:     if (count < 5) {
                   1465:        count++;
                   1466:        write_log ("DSKDAT written. Not good.");
                   1467:        if (count == 5)
                   1468:            write_log ("(further messages suppressed)");
                   1469: 
                   1470:        write_log ("\n");
1.1.1.6   root     1471:     }
                   1472: }
1.1.1.7   root     1473: void DSKPTH (uae_u16 v)
                   1474: {
                   1475:     dskpt = (dskpt & 0xffff) | ((uae_u32) v << 16);
                   1476: }
1.1.1.6   root     1477: 
1.1.1.7   root     1478: void DSKPTL (uae_u16 v)
1.1.1.6   root     1479: {
1.1.1.7   root     1480:     dskpt = (dskpt & ~0xffff) | (v);
1.1.1.6   root     1481: }
                   1482: 
1.1.1.7   root     1483: void DISK_init (void)
                   1484: {
1.1.1.11  root     1485:     int dr;
1.1.1.7   root     1486: 
                   1487:     dma_tab[0] = 0xffffffff;
1.1.1.11  root     1488:     dskbytr_cycle[0] = 0;
                   1489:     dskbytr_cycle[1] = 255;
                   1490:     wordsync_cycle[0] = 255;
1.1.1.7   root     1491: 
1.1.1.11  root     1492:     for (dr = 0; dr < 4; dr++) {
1.1.1.20! root     1493:        drive *drv = floppy + dr;
        !          1494:        drv->type = currprefs.dfxtype[dr];
        !          1495:        reset_drive (dr);
1.1.1.8   root     1496:     }
1.1.1.7   root     1497:     if (disk_empty (0))
                   1498:        write_log ("No disk in drive 0.\n");
                   1499: }
                   1500: 
1.1.1.8   root     1501: void DISK_reset (void)
                   1502: {
                   1503:     int i;
1.1.1.13  root     1504: 
                   1505:     if (savestate_state)
                   1506:        return;
                   1507: 
1.1.1.8   root     1508:     disk_hpos = 0;
1.1.1.11  root     1509:     disk_data_used = 0;
1.1.1.20! root     1510:     dskdmaen = 0;
1.1.1.12  root     1511:     disabled = 0;
1.1.1.8   root     1512:     for (i = 0; i < 4; i++) {
1.1.1.20! root     1513:        reset_drive (i);
1.1.1.8   root     1514:     }
                   1515: }
                   1516: 
1.1.1.7   root     1517: void dumpdisk (void)
                   1518: {
                   1519:     int i;
                   1520:     for (i = 0; i < 4; i++) {
                   1521:        drive *drv = &floppy[i];
                   1522:        printf ("Drive %d: motor %s cylinder %2d selected %d\n", i, drv->motoroff ? "off" : " on", drv->cyl, selected & (1 << i));
                   1523:     }
                   1524: }
1.1.1.11  root     1525: 
                   1526: /* Disk save/restore code */
                   1527: 
                   1528: void DISK_save_custom (uae_u32 *pdskpt, uae_u16 *pdsklength, uae_u16 *pdsksync, uae_u16 *pdskdatr, uae_u16 *pdskbytr)
                   1529: {
1.1.1.20! root     1530:     if (pdskpt) *pdskpt = dskpt;
        !          1531:     if (pdsklength) *pdsklength = dsklength;
        !          1532:     if (pdsksync) *pdsksync = dsksync;
        !          1533:     if (pdskdatr) *pdskdatr = 0;
        !          1534:     if (pdskbytr) *pdskbytr = dskbytr_tab[0];
1.1.1.11  root     1535: }
                   1536: 
                   1537: void DISK_restore_custom (uae_u32 pdskpt, uae_u16 pdsklength, uae_u16 pdskdatr, uae_u16 pdskbytr)
                   1538: {
                   1539:     dskpt = pdskpt;
                   1540:     dsklength = pdsklength;
                   1541:     dskbytr_tab[0] = pdskbytr;
                   1542: }
                   1543: 
1.1.1.19  root     1544: const uae_u8 *restore_disk (int num, const uae_u8 *src)
1.1.1.11  root     1545: {
                   1546:     drive *drv;
1.1.1.13  root     1547:     int state;
1.1.1.20! root     1548:     int newis;
1.1.1.11  root     1549: 
                   1550:     drv = &floppy[num];
1.1.1.13  root     1551:     disabled &= ~(1 << num);
1.1.1.11  root     1552:     drv->drive_id = restore_u32 ();
1.1.1.20! root     1553:     drv->motoroff = 1;
        !          1554:     drv->idbit = 0;
1.1.1.13  root     1555:     state = restore_u8 ();
1.1.1.20! root     1556:     if (state & 2) {
        !          1557:        disabled |= 1 << num;
        !          1558:        if (changed_prefs.nr_floppies > num)
        !          1559:            changed_prefs.nr_floppies = num;
        !          1560:        changed_prefs.dfxtype[num] = -1;
        !          1561:     } else {
        !          1562:        drive_type dfxtype;
        !          1563:        drv->motoroff = (state & 1) ? 0 : 1;
        !          1564:        drv->idbit = (state & 4) ? 1 : 0;
        !          1565:        if (changed_prefs.nr_floppies < num)
        !          1566:            changed_prefs.nr_floppies = num;
        !          1567:        switch (drv->drive_id)
        !          1568:        {
        !          1569:        case DRIVE_ID_35HD:
        !          1570:            dfxtype = DRV_35_HD;
        !          1571:            break;
        !          1572:        case DRIVE_ID_525SD:
        !          1573:            dfxtype = DRV_525_SD;
        !          1574:            break;
        !          1575:        default:
        !          1576:            dfxtype = DRV_35_DD;
        !          1577:            break;
        !          1578:        }
        !          1579:        changed_prefs.dfxtype[num] = dfxtype;
        !          1580:     }
        !          1581:     drv->type = changed_prefs.dfxtype[num];
        !          1582:     drv->buffered_cyl = -1;
        !          1583:     drv->buffered_side = -1;
1.1.1.11  root     1584:     drv->cyl = restore_u8 ();
                   1585:     drv->dskready = restore_u8 ();
                   1586:     drv->drive_id_scnt = restore_u8 ();
                   1587:     drv->mfmpos = restore_u32 ();
1.1.1.20! root     1588:     drv->dskchange = 0;
        !          1589:     drv->dskchange_time = 0;
1.1.1.11  root     1590:     restore_u32 ();
1.1.1.20! root     1591:     strncpy (changed_prefs.df[num], src, 255);
1.1.1.16  root     1592:     changed_prefs.df[num][255] = 0;
1.1.1.20! root     1593:     newis = changed_prefs.df[num][0] ? 1 : 0;
        !          1594:     src += strlen (src) + 1;
        !          1595: 
        !          1596:     if (!(disabled & (1 << num))) {
        !          1597:        if (!newis) {
        !          1598:            drv->dskchange = 1;
        !          1599:        } else {
        !          1600:            drive_insert (floppy + num, num, changed_prefs.df[num]);
        !          1601:        }
        !          1602:     }
1.1.1.11  root     1603: 
                   1604:     return src;
                   1605: }
                   1606: 
1.1.1.19  root     1607: uae_u8 *save_disk (int num, int *len, uae_u8 *dstptr)
1.1.1.11  root     1608: {
                   1609:     uae_u8 *dstbak,*dst;
                   1610:     drive *drv;
                   1611: 
                   1612:     drv = &floppy[num];
1.1.1.18  root     1613:     if (dstptr)
                   1614:        dstbak = dst = dstptr;
                   1615:     else
                   1616:        dstbak = dst = malloc (2+1+1+1+1+4+4+256);
1.1.1.11  root     1617:     save_u32 (drv->drive_id);      /* drive type ID */
1.1.1.20! root     1618:     save_u8 ((drv->motoroff ? 0:1) | ((disabled & (1 << num)) ? 2 : 0) | (drv->idbit ? 4 : 0) | (drv->dskchange ? 8 : 0));
1.1.1.11  root     1619:     save_u8 (drv->cyl);                    /* cylinder */
                   1620:     save_u8 (drv->dskready);       /* dskready */
                   1621:     save_u8 (drv->drive_id_scnt);   /* id mode position */
                   1622:     save_u32 (drv->mfmpos);        /* disk position */
                   1623:     save_u32 (0);                  /* CRC of disk image */
                   1624:     strcpy (dst, currprefs.df[num]);/* image name */
1.1.1.20! root     1625:     dst += strlen (dst) + 1;
1.1.1.11  root     1626: 
                   1627:     *len = dst - dstbak;
                   1628:     return dstbak;
                   1629: }
                   1630: 
                   1631: /* internal floppy controller variables */
                   1632: 
1.1.1.19  root     1633: const uae_u8 *restore_floppy (const uae_u8 *src)
1.1.1.11  root     1634: {
1.1.1.20! root     1635:     word = restore_u16 ();
        !          1636:     bitoffset = restore_u8 ();
        !          1637:     dma_enable = restore_u8 ();
        !          1638:     disk_hpos = restore_u8 ();
        !          1639:     dskdmaen = restore_u8 ();
        !          1640:     word |= restore_u16 () << 16;
1.1.1.11  root     1641: 
                   1642:     return src;
                   1643: }
                   1644: 
1.1.1.19  root     1645: uae_u8 *save_floppy (int *len, uae_u8 *dstptr)
1.1.1.11  root     1646: {
                   1647:     uae_u8 *dstbak, *dst;
                   1648: 
                   1649:     /* flush dma buffer before saving */
1.1.1.20! root     1650:     dodmafetch ();
1.1.1.11  root     1651: 
1.1.1.18  root     1652:     if (dstptr)
                   1653:        dstbak = dst = dstptr;
                   1654:     else
1.1.1.20! root     1655:        dstbak = dst = malloc (2+1+1+1+1+2);
1.1.1.12  root     1656:     save_u16 (word);           /* current fifo (low word) */
1.1.1.11  root     1657:     save_u8 (bitoffset);       /* dma bit offset */
1.1.1.12  root     1658:     save_u8 (dma_enable);      /* disk sync found */
1.1.1.11  root     1659:     save_u8 (disk_hpos);       /* next bit read position */
                   1660:     save_u8 (dskdmaen);                /* dma status */
1.1.1.12  root     1661:     save_u16 (word >> 16);     /* current fifo (high word) */
1.1.1.11  root     1662: 
                   1663:     *len = dst - dstbak;
                   1664:     return dstbak;
                   1665: }

unix.superglobalmegacorp.com

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