"Fossies" - the Fresh Open Source Software Archive

Member "uae-0.8.29/src/disk.c" (30 Nov 2008, 41598 Bytes) of package /linux/misc/old/uae-0.8.29.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "disk.c" see the Fossies "Dox" file reference documentation.

    1  /*
    2   * UAE - The Un*x Amiga Emulator
    3   *
    4   * Floppy disk emulation
    5   *
    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 [atemel1@hotmail.com]
   11   *
   12   */
   13 
   14 #include <stdio.h>
   15 
   16 #include "sysconfig.h"
   17 #include "sysdeps.h"
   18 
   19 #include "options.h"
   20 #include "threaddep/thread.h"
   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"
   28 #include "autoconf.h"
   29 #include "newcpu.h"
   30 #include "xwin.h"
   31 #include "osemu.h"
   32 #include "execlib.h"
   33 #include "savestate.h"
   34 #include "crc32.h"
   35 
   36 /* support HD floppies */
   37 #define FLOPPY_DRIVE_HD
   38 /* writable track length with normal 2us bitcell/300RPM motor */
   39 #define FLOPPY_WRITE_LEN (12650 / 2)
   40 /* This works out to 341 */
   41 #define FLOPPY_GAP_LEN (FLOPPY_WRITE_LEN - 11 * 544)
   42 /* (cycles/bitcell) << 8, normal = ((2us/280ns)<<8) = ~1830 */
   43 #define NORMAL_FLOPPY_SPEED 1830
   44 
   45 #ifdef FLOPPY_DRIVE_HD
   46 #define DDHDMULT 2
   47 #else
   48 #define DDHDMULT 1
   49 #endif
   50 
   51 static int floppy_speed = NORMAL_FLOPPY_SPEED;
   52 
   53 #undef DISK_DEBUG
   54 #undef DEBUG_DRIVE_ID
   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  */
   65 
   66 static int side, direction, writing;
   67 static uae_u8 selected = 15, disabled;
   68 
   69 static uae_u8 writebuffer[544 * 22 * DDHDMULT];
   70 
   71 typedef enum { TRACK_AMIGADOS, TRACK_RAW, TRACK_RAW1, TRACK_PCDOS } image_tracktype;
   72 typedef struct {
   73     uae_u32 offs;
   74     int bitlen, track;
   75     unsigned int sync;
   76     image_tracktype type;
   77     uae_u16 len;
   78 } trackid;
   79 
   80 #define MAX_TRACKS 328
   81 
   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
   94 #define DRIVE_ID_35HD  0xAAAAAAAA
   95 #define DRIVE_ID_525SD 0x55555555 /* 40 track 5.25 drive , kickstart does not recognize this */
   96 
   97 typedef enum { ADF_NORMAL, ADF_EXT1, ADF_EXT2 } drive_filetype;
   98 typedef struct {
   99     drive_type type;
  100     struct zfile *diskfile;
  101     drive_filetype filetype;
  102     trackid trackdata[MAX_TRACKS];
  103     int buffered_cyl, buffered_side;
  104     int cyl;
  105     int motoroff;
  106     int state;
  107     int wrprot;
  108     uae_u16 bigmfmbuf[0x8000];
  109     int mfmpos;
  110     int tracklen;
  111     int trackspeed;
  112     int dmalen;
  113     int num_tracks, num_secs;
  114     int hard_num_cyls;
  115     int dskchange;
  116     int dskchange_time;
  117     int dskready;
  118     int dskready_time;
  119     int steplimit;
  120     int ddhd; /* 1=DD 2=HD */
  121     int drive_id_scnt; /* drive id shift counter */
  122     int idbit;
  123     unsigned long drive_id; /* drive id to be reported */
  124     char newname[256]; /* storage space for new filename during eject delay */
  125 } drive;
  126 
  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
  137 static char *drive_id_name (drive *drv)
  138 {
  139     switch (drv->drive_id)
  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     }
  145     return "UNKNOWN";
  146 }
  147 #endif
  148 
  149 /* Simulate exact behaviour of an A3000T 3.5 HD disk drive.
  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  */
  154 static void drive_settype_id (drive *drv)
  155 {
  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
  167     drv->drive_id = DRIVE_ID_35DD;
  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;
  181     }
  182 #ifdef DEBUG_DRIVE_ID
  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));
  187 #endif
  188 }
  189 
  190 /* code for track display */
  191 static void update_drive_gui (int num)
  192 {
  193     drive *drv = floppy + num;
  194 
  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;
  205     gui_ledstate &= ~(2 << num);
  206     if (drv->state)
  207     gui_ledstate |= 2 << num;
  208     gui_led (num + 1, gui_data.drive_motor[num]);
  209 }
  210 
  211 static void drive_fill_bigbuf (drive *drv);
  212 
  213 static void drive_image_free (drive *drv)
  214 {
  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");
  225     if (f) {
  226     if (wrprot)
  227         *wrprot = 0;
  228     } else {
  229     if (wrprot)
  230         *wrprot = 1;
  231     f = zfile_open (fname, "rb");
  232     }
  233     if (!leave_open)
  234     zfile_fclose (f);
  235     return f;
  236 }
  237 
  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)
  277 {
  278     unsigned char buffer[2 + 2 + 4 + 4];
  279     trackid *tid;
  280     int size;
  281 
  282     drive_image_free (drv);
  283     drv->diskfile = DISK_validate_filename (fname, 1, &drv->wrprot);
  284     drv->ddhd = 1;
  285     drv->num_secs = 0;
  286     drv->hard_num_cyls = drv->type == DRV_525_SD ? 40 : 80;
  287 
  288     if (drv->diskfile == 0) {
  289     track_reset (drv);
  290     return 0;
  291     }
  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;
  296     gui_filename (dnum, fname);
  297 
  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 
  307     if (strncmp ((char *) buffer, "UAE-1ADF", 8) == 0) {
  308     read_header_ext2 (drv->diskfile, drv->trackdata, &drv->num_tracks, &drv->ddhd);
  309 
  310     drv->filetype = ADF_EXT2;
  311     drv->num_secs = 11;
  312     if (drv->ddhd > 1)
  313         drv->num_secs = 22;
  314     } else if (strncmp ((char *) buffer, "UAE--ADF", 8) == 0) {
  315     int offs = 160 * 4 + 8;
  316     int i;
  317 
  318     drv->filetype = ADF_EXT1;
  319     drv->num_tracks = 160;
  320     drv->num_secs = 11;
  321 
  322     zfile_fseek (drv->diskfile, 8, SEEK_SET);
  323 
  324     drv->wrprot = 1;    /* write to adf_ext1 not implemented */
  325     for (i = 0; i < 160; i++) {
  326         tid = &drv->trackdata[i];
  327         zfile_fread (buffer, 4, 1, drv->diskfile);
  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;
  339     }
  340     } else {
  341     int i;
  342     drv->filetype = ADF_NORMAL;
  343 
  344     /* High-density disk? */
  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));
  350 
  351     if (drv->num_tracks > MAX_TRACKS)
  352         write_log ("Your diskfile is too big!\n");
  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;
  359     }
  360     }
  361     drive_settype_id (drv); /* Set DD or HD drive */
  362     drv->buffered_side = 2; /* will force read */
  363     drive_fill_bigbuf (drv);
  364     return 1;
  365 }
  366 
  367 static int drive_empty (drive * drv)
  368 {
  369     return drv->diskfile == 0;
  370 }
  371 
  372 static void drive_step (drive * drv)
  373 {
  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;
  381     if (!drive_empty (drv))
  382     drv->dskchange = 0;
  383     if (direction) {
  384     if (drv->cyl)
  385         drv->cyl--;
  386 /*  else
  387         write_log ("program tried to step beyond track zero\n");
  388         "no-click" programs does that
  389 */
  390   } else {
  391     if (drv->cyl < 83)
  392         drv->cyl++;
  393     else
  394         write_log ("program tried to step over track 83\n");
  395     }
  396 
  397 #if 0 && defined DISK_DEBUG
  398     write_log ("track %d\n", drv->cyl);
  399 #endif
  400 }
  401 
  402 static int drive_track0 (drive * drv)
  403 {
  404     return drv->cyl == 0;
  405 }
  406 
  407 static int drive_writeprotected (drive * drv)
  408 {
  409     return drv->wrprot || drv->diskfile == NULL;
  410 }
  411 
  412 static int drive_running (drive * drv)
  413 {
  414     return !drv->motoroff;
  415 }
  416 
  417 static void drive_motor (drive * drv, int off)
  418 {
  419     /* A value of 5 works out to a guaranteed delay of 1/2 of a second
  420        Higher values are dangerous, e.g. a value of 8 breaks the RSI
  421        demo.  */
  422     if (drv->motoroff && !off) {
  423     drv->dskready_time = 5;
  424     disk_data_used = 0;
  425 #ifdef DEBUG_DRIVE_ID
  426     write_log ("drive_motor: Selected DF%d: reset id shift reg.\n", drv-floppy);
  427 #endif
  428     }
  429     if (!drv->motoroff && off) {
  430     drv->drive_id_scnt = 0; /* Reset id shift reg counter */
  431     }
  432     drv->motoroff = off;
  433     if (drv->motoroff) {
  434     drv->dskready = 0;
  435     drv->dskready_time = 0;
  436     }
  437 }
  438 
  439 static void read_floppy_data (struct zfile *diskfile, trackid *ti, int offset, unsigned char *dst, int len)
  440 {
  441     zfile_fseek (diskfile, ti->offs + offset, SEEK_SET);
  442     zfile_fread (dst, 1, len, diskfile);
  443 }
  444 
  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;
  553 }
  554 
  555 /* Megalomania does not like zero MFM words... */
  556 static void mfmcode (uae_u16 * mfm, int words)
  557 {
  558     uae_u32 lastword = 0;
  559 
  560     while (words--) {
  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;
  568     }
  569 }
  570 
  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 
  663 static void drive_fill_bigbuf (drive * drv)
  664 {
  665     int tr = drv->cyl * 2 + side;
  666     trackid *ti = drv->trackdata + tr;
  667 
  668     if (!drv->diskfile || tr >= drv->num_tracks) {
  669     drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 2 * 8;
  670     drv->trackspeed = floppy_speed;
  671     memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
  672     return;
  673     }
  674     if (drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
  675     return;
  676 
  677     if (ti->type == TRACK_PCDOS) {
  678     decode_pcdos (drv);
  679 
  680     } else if (ti->type == TRACK_AMIGADOS) {
  681     decode_amigados (drv);
  682     } else {
  683     int i;
  684     int base_offset = ti->type == TRACK_RAW ? 0 : 1;
  685     drv->tracklen = ti->bitlen + 16 * base_offset;
  686     drv->bigmfmbuf[0] = ti->sync;
  687     read_floppy_data (drv->diskfile, ti, 0, (unsigned char *) (drv->bigmfmbuf + base_offset), (ti->bitlen + 7) / 8);
  688     for (i = base_offset; i < (drv->tracklen + 15) / 16; i++) {
  689         uae_u16 *mfm = drv->bigmfmbuf + i;
  690         uae_u8 *data = (uae_u8 *) mfm;
  691         *mfm = 256 * *data + *(data + 1);
  692     }
  693 #if 0 && defined DISK_DEBUG
  694     write_log ("rawtrack %d\n", tr);
  695 #endif
  696     }
  697     drv->buffered_side = side;
  698     drv->buffered_cyl = drv->cyl;
  699     drv->trackspeed = floppy_speed * drv->tracklen / (2 * 8 * FLOPPY_WRITE_LEN);
  700 }
  701 
  702 /* Update ADF_EXT2 track header */
  703 static void diskfile_update (drive * drv, int len, uae_u8 type)
  704 {
  705     trackid *ti;
  706     int track;
  707     uae_u8 buf[2 + 2 + 4 + 4], *zerobuf;
  708 
  709     if (drv->filetype != ADF_EXT2)
  710     return;
  711 
  712     track = drv->cyl * 2 + side;
  713     ti = &drv->trackdata[track];
  714     ti->bitlen = len;
  715     zfile_fseek (drv->diskfile, 8 + 4 + (2 + 2 + 4 + 4) * track, SEEK_SET);
  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);
  721     zfile_fwrite (buf, sizeof (buf), 1, drv->diskfile);
  722     if (ti->len > (len + 7) / 8) {
  723     zerobuf = malloc (ti->len);
  724     memset (zerobuf, 0, ti->len);
  725     zfile_fseek (drv->diskfile, ti->offs, SEEK_SET);
  726     zfile_fwrite (zerobuf, 1, ti->len, drv->diskfile);
  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
  732 }
  733 
  734 #define MFMMASK 0x55555555
  735 static uae_u32 getmfmlong (uae_u16 * mbuf)
  736 {
  737     return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK;
  738 }
  739 
  740 static int drive_write_adf_amigados (drive * drv)
  741 {
  742     int i, secwritten = 0;
  743     int fwlen = FLOPPY_WRITE_LEN * drv->ddhd;
  744     int length = 2 * fwlen;
  745     int drvsec= drv->num_secs;
  746     uae_u32 odd, even, chksum, id, dlong;
  747     uae_u8 *secdata;
  748     uae_u8 secbuf[544];
  749     uae_u16 *mbuf = drv->bigmfmbuf;
  750     uae_u16 *mend = mbuf + length;
  751     char sectable[22];
  752     memset (sectable, 0, sizeof (sectable));
  753     memcpy (mbuf + fwlen, mbuf, fwlen * sizeof (uae_u16));
  754     mend -= (4 + 16 + 8 + 512);
  755     while (secwritten < drvsec) {
  756     int trackoffs;
  757 
  758     do {
  759         while (*mbuf++ != 0x4489) {
  760         if (mbuf >= mend)
  761             return 1;
  762         }
  763     } while (*mbuf++ != 0x4489);
  764 
  765     odd = getmfmlong (mbuf);
  766     even = getmfmlong (mbuf + 2);
  767     mbuf += 4;
  768     id = (odd << 1) | even;
  769 
  770     trackoffs = (id & 0xff00) >> 8;
  771     if (trackoffs + 1 > drvsec) {
  772         if (drv->filetype == ADF_EXT2)
  773         return 2;
  774         write_log ("Disk write: weird sector number %d\n", trackoffs);
  775         continue;
  776     }
  777     chksum = odd ^ even;
  778     for (i = 0; i < 4; i++) {
  779         odd = getmfmlong (mbuf);
  780         even = getmfmlong (mbuf + 8);
  781         mbuf += 2;
  782 
  783         dlong = (odd << 1) | even;
  784         if (dlong) {
  785         if (drv->filetype == ADF_EXT2)
  786             return 6;
  787         secwritten = -200;
  788         }
  789         chksum ^= odd ^ even;
  790     }           /* could check here if the label is nonstandard */
  791     mbuf += 8;
  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);
  799         continue;
  800     }
  801     odd = getmfmlong (mbuf);
  802     even = getmfmlong (mbuf + 2);
  803     mbuf += 4;
  804     chksum = (odd << 1) | even;
  805     secdata = secbuf + 32;
  806     for (i = 0; i < 128; i++) {
  807         odd = getmfmlong (mbuf);
  808         even = getmfmlong (mbuf + 256);
  809         mbuf += 2;
  810         dlong = (odd << 1) | even;
  811         *secdata++ = dlong >> 24;
  812         *secdata++ = dlong >> 16;
  813         *secdata++ = dlong >> 8;
  814         *secdata++ = dlong;
  815         chksum ^= odd ^ even;
  816     }
  817     mbuf += 256;
  818     if (chksum) {
  819         if (drv->filetype == ADF_EXT2)
  820         return 4;
  821         write_log ("Disk write: sector %d, data checksum error\n", trackoffs);
  822         continue;
  823     }
  824     sectable[trackoffs] = 1;
  825     secwritten++;
  826     memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
  827     }
  828     if (drv->filetype == ADF_EXT2 && (secwritten == 0 || secwritten < 0))
  829     return 5;
  830     if (secwritten == 0)
  831     write_log ("Disk write in unsupported format\n");
  832     if (secwritten < 0)
  833     write_log ("Disk write: sector labels ignored\n");
  834 
  835     diskfile_update (drv, drvsec * 512 * 8, TRACK_AMIGADOS);
  836     for (i = 0; i < drvsec; i++) {
  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);
  839     }
  840 
  841     return 0;
  842 }
  843 
  844 /* write raw track to disk file */
  845 static int drive_write_ext2 (drive * drv)
  846 {
  847     trackid *ti;
  848     int len, track, i;
  849 
  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     }
  863     zfile_fseek (drv->diskfile, ti->offs, SEEK_SET);
  864     zfile_fwrite (drv->bigmfmbuf, 1, len, drv->diskfile);
  865     return 1;
  866 }
  867 
  868 static void drive_write_data (drive * drv)
  869 {
  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) {
  883         /*write_log ("not an amigados track (error %d), writing as raw track\n", ret); */
  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 {
  893     drive_image_free (drv);
  894     drv->dskchange = 1;
  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 */
  900 #ifdef DISK_DEBUG
  901     write_log ("eject drive %d\n", drv - &floppy[0]);
  902 #endif
  903 }
  904 
  905 /* We use this function if we have no Kickstart ROM.
  906  * No error checking - we trust our luck. */
  907 void DISK_ersatz_read (int tr, int sec, uaecptr dest)
  908 {
  909     uae_u8 *dptr = get_real_address (dest);
  910     zfile_fseek (floppy[0].diskfile, floppy[0].trackdata[tr].offs + sec * 512, SEEK_SET);
  911     zfile_fread (dptr, 1, 512, floppy[0].diskfile);
  912 }
  913 
  914 void disk_eject (int num)
  915 {
  916     gui_filename (num, "");
  917     drive_eject (floppy + num);
  918     *currprefs.df[num] = *changed_prefs.df[num] = 0;
  919     floppy[num].newname[0] = 0;
  920 }
  921 
  922 void disk_insert (int num, const char *name)
  923 {
  924     drive *drv = floppy + num;
  925 
  926     if (!strcmp (currprefs.df[num], name))
  927     return;
  928     strcpy (drv->newname, name);
  929     strcpy (currprefs.df[num], name);
  930 
  931     if (name[0] == 0) {
  932     disk_eject (num);
  933     } else if (!drive_empty (drv) || drv->dskchange_time > 0) {
  934     drive_eject (drv);
  935     /* set dskchange_time, disk_insert () will be
  936      * called from DISK_check_change () after 1 second delay
  937      * this makes sure that all programs detect disk change correctly
  938      */
  939     drv->dskchange_time = 10; /* 1 second disk change delay */
  940     } else {
  941     drv->dskchange_time = 1;
  942     }
  943 }
  944 
  945 void DISK_check_change (void)
  946 {
  947     int i;
  948 
  949     for (i = 0; i < 4; i++) {
  950     drive *drv = floppy + i;
  951     gui_lock ();
  952     if (currprefs.dfxtype[i] != changed_prefs.dfxtype[i]) {
  953         drv->type = currprefs.dfxtype[i] = changed_prefs.dfxtype[i];
  954         reset_drive (i);
  955     }
  956     if (drv->dskchange_time == 0 && strcmp (currprefs.df[i], changed_prefs.df[i]))
  957         disk_insert (i, changed_prefs.df[i]);
  958     gui_unlock ();
  959     /* emulate drive motor turn on time */
  960     if (drv->dskready_time && !drive_empty (drv)) {
  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;
  974         }
  975     }
  976     }
  977 }
  978 
  979 int disk_empty (int num)
  980 {
  981     return drive_empty (floppy + num);
  982 }
  983 
  984 static int step;
  985 
  986 void DISK_select (uae_u8 data)
  987 {
  988     int step_pulse, lastselected;
  989     int dr;
  990     static uae_u8 prevdata;
  991 
  992     lastselected = selected;
  993     selected = (data >> 3) & 15;
  994     selected |= disabled;
  995     if (selected != lastselected)
  996     disk_data_used = 1;
  997     side = 1 - ((data >> 2) & 1);
  998 
  999     direction = (data >> 1) & 1;
 1000     step_pulse = data & 1;
 1001     if (step != step_pulse) {
 1002     step = step_pulse;
 1003     if (step) {
 1004         for (dr = 0; dr < 4; dr++) {
 1005         if (!((selected | disabled) & (1 << dr))) {
 1006             drive_step (floppy + dr);
 1007         }
 1008         }
 1009     }
 1010     }
 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         }
 1030         }
 1031     }
 1032     }
 1033     for (dr = 0; dr < 4; dr++) {
 1034     floppy[dr].state = (!(selected & (1 << dr))) | !floppy[dr].motoroff;
 1035     update_drive_gui (dr);
 1036     }
 1037     prevdata = data;
 1038 }
 1039 
 1040 uae_u8 DISK_status (void)
 1041 {
 1042     uae_u8 st = 0x3c;
 1043     int dr;
 1044 
 1045     for (dr = 0; dr < 4; dr++) {
 1046     drive *drv = floppy + dr;
 1047     if (!((selected | disabled) & (1 << dr))) {
 1048         if (drive_running (drv)) {
 1049         if (drv->dskready)
 1050             st &= ~0x20;
 1051         } else {
 1052         /* report drive ID */
 1053         if (drv->idbit && currprefs.dfxtype[dr] != DRV_35_DD_ESCOM)
 1054             st &= ~0x20;
 1055 #ifdef DEBUG_DRIVE_ID
 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);
 1058 #endif
 1059         }
 1060         if (drive_track0 (drv))
 1061         st &= ~0x10;
 1062         if (drive_writeprotected (drv))
 1063         st &= ~8;
 1064         if (drv->dskchange)
 1065         st &= ~4;
 1066     } else if (!(selected & (1 << dr))) {
 1067         if (drv->idbit)
 1068         st &= ~0x20;
 1069     }
 1070     }
 1071     return st;
 1072 }
 1073 
 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];
 1081 static short wordsync_cycle[MAX_DISK_WORDS_PER_LINE * 2 + 1];
 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);
 1092     dskdmaen = 0; /* ??? */
 1093 #ifdef DISK_DEBUG
 1094     write_log ("disk dma finished %08.8X\n", dskpt);
 1095 #endif
 1096 }
 1097 
 1098 static void disk_events (int last)
 1099 {
 1100     eventtab[ev_disk].active = 0;
 1101     for (disk_sync_cycle = last; disk_sync_cycle < maxhpos; disk_sync_cycle++) {
 1102     if (disk_sync[disk_sync_cycle]) {
 1103         eventtab[ev_disk].oldcycles = get_cycles ();
 1104         eventtab[ev_disk].evtime = get_cycles () + (disk_sync_cycle - last) * CYCLE_UNIT;
 1105         eventtab[ev_disk].active = 1;
 1106         events_schedule ();
 1107         return;
 1108     }
 1109     }
 1110 }
 1111 
 1112 void DISK_handler (void)
 1113 {
 1114     eventtab[ev_disk].active = 0;
 1115     if (disk_sync[disk_sync_cycle] & DISK_WORDSYNC)
 1116     INTREQ (0x9000);
 1117     if (disk_sync[disk_sync_cycle] & DISK_INDEXSYNC)
 1118     cia_diskindex ();
 1119     disk_sync[disk_sync_cycle] = 0;
 1120     disk_events (disk_sync_cycle);
 1121 }
 1122 
 1123 static int dma_enable, bitoffset;
 1124 static uae_u32 word;
 1125 
 1126 /* Always carried through to the next line.  */
 1127 static int disk_hpos;
 1128 
 1129 /* emulate disk write dma for full horizontal line */
 1130 static void disk_doupdate_write (drive * drv)
 1131 {
 1132     int hpos = disk_hpos;
 1133     while (hpos < (maxhpos << 8)) {
 1134     drv->mfmpos++;
 1135     drv->mfmpos %= drv->tracklen;
 1136     if (!drv->mfmpos) {
 1137         disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
 1138         disk_events (0);
 1139     }
 1140     if ((dmacon & 0x210) == 0x210 && dskdmaen == 3) {
 1141         bitoffset++;
 1142         bitoffset &= 15;
 1143         if (!bitoffset) {
 1144         drv->bigmfmbuf[drv->mfmpos >> 4] = get_word (dskpt);
 1145         dskpt += 2;
 1146         dsklength--;
 1147         if (dsklength == 0) {
 1148             disk_dmafinished ();
 1149             drive_write_data (drv);
 1150         }
 1151         }
 1152     }
 1153     hpos += drv->trackspeed;
 1154     }
 1155     disk_hpos = hpos - (maxhpos << 8);
 1156 }
 1157 
 1158 /* get one bit from MFM bit stream */
 1159 static uae_u32 getonebit (uae_u16 * mfmbuf, int mfmpos, uae_u32 word)
 1160 {
 1161     uae_u16 *buf;
 1162 
 1163     buf = &mfmbuf[mfmpos >> 4];
 1164     word <<= 1;
 1165     word |= (buf[0] & (1 << (15 - (mfmpos & 15)))) ? 1 : 0;
 1166     return word;
 1167 }
 1168 
 1169 #define WORDSYNC_CYCLES 7 /* (~7 * 280ns = 2us) */
 1170 
 1171 /* emulate disk read dma for full horizontal line */
 1172 static void disk_doupdate_read (drive * drv)
 1173 {
 1174     int hpos = disk_hpos;
 1175     int is_sync = 0;
 1176     int j = 0, k = 1, l = 0;
 1177     uae_u16 synccheck;
 1178     static int dskbytr_last = 0, wordsync_last = -1;
 1179 
 1180     dskbytr_tab[0] = dskbytr_tab[dskbytr_last];
 1181 
 1182     if (wordsync_last >= 0 && maxhpos - wordsync_cycle[wordsync_last] < WORDSYNC_CYCLES)
 1183     wordsync_cycle[l++] = (maxhpos - wordsync_cycle[wordsync_last]) - WORDSYNC_CYCLES;
 1184     wordsync_last = -1;
 1185 
 1186     while (hpos < (maxhpos << 8)) {
 1187     if (drv->dskready)
 1188         word = getonebit (drv->bigmfmbuf, drv->mfmpos, word);
 1189     else
 1190         word <<= 1;
 1191     drv->mfmpos++;
 1192     drv->mfmpos %= drv->tracklen;
 1193     if (!drv->mfmpos) {
 1194         disk_sync[hpos >> 8] |= DISK_INDEXSYNC;
 1195         is_sync = 1;
 1196     }
 1197     if (bitoffset == 31 && dma_enable) {
 1198         dma_tab[j++] = (word >> 16) & 0xffff;
 1199         if (j == MAX_DISK_WORDS_PER_LINE - 1) {
 1200         write_log ("Bug: Disk DMA buffer overflow!\n");
 1201         j--;
 1202         }
 1203     }
 1204     if (bitoffset == 15 || bitoffset == 23 || bitoffset == 31) {
 1205         dskbytr_tab[k] = (word >> 8) & 0xff;
 1206         dskbytr_tab[k] |= 0x8000;
 1207         dskbytr_last = k;
 1208         dskbytr_cycle[k++] = hpos >> 8;
 1209     }
 1210     synccheck = (word >> 8) & 0xffff;
 1211     if (synccheck == dsksync) {
 1212         if (adkcon & 0x400) {
 1213         if (bitoffset != 23 || !dma_enable)
 1214             bitoffset = 7;
 1215         dma_enable = 1;
 1216         }
 1217         wordsync_last = l;
 1218         wordsync_cycle[l++] = hpos >> 8;
 1219         disk_sync[hpos >> 8] |= DISK_WORDSYNC;
 1220         is_sync = 1;
 1221     }
 1222     bitoffset++;
 1223     if (bitoffset == 32) bitoffset = 16;
 1224     hpos += drv->trackspeed;
 1225     }
 1226     dma_tab[j] = 0xffffffff;
 1227     dskbytr_cycle[k] = 255;
 1228     wordsync_cycle[l] = 255;
 1229     if (is_sync)
 1230     disk_events (0);
 1231 
 1232     disk_hpos = hpos - (maxhpos << 8);
 1233 }
 1234 
 1235 /* disk DMA fetch happens on real Amiga at the beginning of next horizontal line
 1236    (cycles 9, 11 and 13 according to hardware manual) We transfer all DMA'd
 1237    data at cycle 0. I don't think any program cares about this small difference.
 1238 
 1239    We must handle dsklength = 0 because some copy protections use it to detect
 1240    wordsync without transferring any data.
 1241 */
 1242 static void dodmafetch (void)
 1243 {
 1244     int i;
 1245 
 1246     i = 0;
 1247     while (dma_tab[i] != 0xffffffff && dskdmaen == 2 && (dmacon & 0x210) == 0x210) {
 1248     if (dsklength > 0) {
 1249         put_word (dskpt, dma_tab[i++]);
 1250         dskpt += 2;
 1251         dsklength--;
 1252     }
 1253     if (dsklength == 0) {
 1254         disk_dmafinished ();
 1255         break;
 1256     }
 1257     }
 1258     dma_tab[0] = 0xffffffff;
 1259 }
 1260 
 1261 /* this is very unoptimized. DSKBYTR is used very rarely, so it should not matter. */
 1262 
 1263 uae_u16 DSKBYTR (int hpos)
 1264 {
 1265     uae_u16 v;
 1266     int i;
 1267 
 1268     i = 0;
 1269     while (hpos > dskbytr_cycle[i + 1])
 1270     i++;
 1271     v = dskbytr_tab[i];
 1272     dskbytr_tab[i] &= ~0x8000;
 1273     if (wordsync_cycle[0] != 255) {
 1274     i = 0;
 1275     while (hpos < wordsync_cycle[i])
 1276         i++;
 1277     if (hpos - wordsync_cycle[i] <= WORDSYNC_CYCLES)
 1278         v |= 0x1000;
 1279     }
 1280     if (dskdmaen && (dmacon & 0x210) == 0x210)
 1281     v |= 0x4000;
 1282     if (dskdmaen == 3)
 1283     v |= 0x2000;
 1284 
 1285     disk_data_used = 0;
 1286 
 1287     return v;
 1288 }
 1289 
 1290 static void DISK_start (void)
 1291 {
 1292     int dr;
 1293 
 1294     for (dr = 0; dr < 4; dr++) {
 1295     drive *drv = &floppy[dr];
 1296     if (!(selected & (1 << dr))) {
 1297         int tr = drv->cyl * 2 + side;
 1298         trackid *ti = drv->trackdata + tr;
 1299 
 1300         if (dskdmaen == 3) {
 1301         drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 8 * 2;
 1302         drv->trackspeed = floppy_speed;
 1303         }
 1304         /* Ugh.  A nasty hack.  Assume ADF_EXT1 tracks are always read
 1305            from the start.  */
 1306         if (ti->type == TRACK_RAW1)
 1307         drv->mfmpos = 0;
 1308     }
 1309     }
 1310     dma_enable = (adkcon & 0x400) ? 0 : 1;
 1311     word = 0;
 1312     bitoffset = 0;
 1313     dma_tab[0] = 0xffffffff;
 1314 }
 1315 
 1316 static int linecounter;
 1317 
 1318 void DISK_update (void)
 1319 {
 1320     int dr;
 1321 
 1322     for (dr = 0; dr < 4; dr++) {
 1323     drive *drv = &floppy[dr];
 1324     if (drv->steplimit)
 1325         drv->steplimit--;
 1326     }
 1327     if (linecounter) {
 1328     linecounter--;
 1329     if (! linecounter)
 1330         disk_dmafinished ();
 1331     return;
 1332     }
 1333 
 1334     dodmafetch ();
 1335 
 1336     for (dr = 0; dr < 4; dr++) {
 1337     drive *drv = &floppy[dr];
 1338     if (drv->motoroff)
 1339         continue;
 1340     if (selected & (1 << dr)) {
 1341         drv->mfmpos += (maxhpos << 8) / drv->trackspeed;
 1342         drv->mfmpos %= drv->tracklen;
 1343         continue;
 1344     }
 1345     drive_fill_bigbuf (drv);
 1346     drv->mfmpos %= drv->tracklen;
 1347     if (dskdmaen > 1)
 1348         disk_data_used = 0;
 1349 
 1350     if (dskdmaen == 3)
 1351         disk_doupdate_write (drv);
 1352     else if (1 || disk_data_used < MAXVPOS * 50 * 2) {
 1353         disk_data_used++;
 1354         disk_doupdate_read (drv);
 1355     }
 1356     return;
 1357     }
 1358 }
 1359 
 1360 void DSKLEN (uae_u16 v, int hpos)
 1361 {
 1362     if (v & 0x8000) {
 1363     dskdmaen = dskdmaen == 1 ? 2 : 1;
 1364     } else {
 1365     /* Megalomania does this */
 1366 #if 0
 1367     if (dskdmaen == 2)
 1368         write_log ("warning: Disk read DMA aborted, %d words left\n", dsklength);
 1369 #endif
 1370     if (dskdmaen == 3)
 1371         write_log ("warning: Disk write DMA aborted, %d words left\n", dsklength);
 1372     dskdmaen = 0;
 1373     }
 1374     dsklength = v & 0x3ffe;
 1375     if (dskdmaen <= 1)
 1376     return;
 1377     if (v & 0x4000)
 1378     dskdmaen = 3;
 1379 #ifdef DISK_DEBUG
 1380     {
 1381     int dr;
 1382     for (dr = 0; dr < 4; dr++) {
 1383         drive *drv = &floppy[dr];
 1384         if (drv->motoroff)
 1385         continue;
 1386         if ((selected & (1 << dr)) == 0)
 1387         break;
 1388     }
 1389     if (dr == 4)
 1390         write_log ("disk DMA started, but no drive ready!\n");
 1391     else
 1392         write_log ("disk %s DMA started for %d words (%08.8X) sync=%04.4X track %d\n",
 1393                dskdmaen == 3 ? "write" : "read", dsklength, dskpt,
 1394                (adkcon & 0x400) ? dsksync : 0xffff,
 1395                floppy[dr].cyl * 2 + side);
 1396     }
 1397 #endif
 1398     /* Megalomania does not work if DSKLEN write is delayed to next horizontal line,
 1399        also it seems some copy protections require this fix */
 1400     DISK_start ();
 1401 
 1402     /* Try to make floppy access from Kickstart faster.  */
 1403     if (dskdmaen != 2)
 1404     return;
 1405     {
 1406     int dr;
 1407     uaecptr pc = m68k_getpc ();
 1408     if ((pc & 0xF80000) != 0xF80000)
 1409         return;
 1410     for (dr = 0; dr < 4; dr++) {
 1411         drive *drv = &floppy[dr];
 1412         if (drv->motoroff)
 1413         continue;
 1414         if ((selected & (1 << dr)) == 0) {
 1415         int pos = drv->mfmpos & ~15;
 1416         int i;
 1417 
 1418         drive_fill_bigbuf (drv);
 1419         if (adkcon & 0x400) {
 1420             for (i = 0; i < drv->tracklen; i += 16) {
 1421             pos += 16;
 1422             pos %= drv->tracklen;
 1423             if (drv->bigmfmbuf[pos >> 4] == dsksync) {
 1424                 /* must skip first disk sync marker */
 1425                 pos += 16;
 1426                 pos %= drv->tracklen;
 1427                 break;
 1428             }
 1429             }
 1430             if (i >= drv->tracklen)
 1431             return;
 1432         }
 1433         while (dsklength-- > 0) {
 1434             put_word (dskpt, drv->bigmfmbuf[pos >> 4]);
 1435             dskpt += 2;
 1436             pos += 16;
 1437             pos %= drv->tracklen;
 1438         }
 1439         INTREQ (0x9000);
 1440         linecounter = 2;
 1441         dskdmaen = 0;
 1442         return;
 1443         }
 1444     }
 1445     }
 1446 }
 1447 
 1448 /* not a real hardware register */
 1449 uae_u16 DSKDATR (int hpos)
 1450 {
 1451     return 0;
 1452 }
 1453 
 1454 void DSKSYNC (uae_u16 v)
 1455 {
 1456     dsksync = v;
 1457 }
 1458 
 1459 void DSKDAT (uae_u16 v)
 1460 {
 1461     static int count = 0;
 1462     if (count < 5) {
 1463     count++;
 1464     write_log ("DSKDAT written. Not good.");
 1465     if (count == 5)
 1466         write_log ("(further messages suppressed)");
 1467 
 1468     write_log ("\n");
 1469     }
 1470 }
 1471 void DSKPTH (uae_u16 v)
 1472 {
 1473     dskpt = (dskpt & 0xffff) | ((uae_u32) v << 16);
 1474 }
 1475 
 1476 void DSKPTL (uae_u16 v)
 1477 {
 1478     dskpt = (dskpt & ~0xffff) | (v);
 1479 }
 1480 
 1481 void DISK_init (void)
 1482 {
 1483     int dr;
 1484 
 1485     dma_tab[0] = 0xffffffff;
 1486     dskbytr_cycle[0] = 0;
 1487     dskbytr_cycle[1] = 255;
 1488     wordsync_cycle[0] = 255;
 1489 
 1490     for (dr = 0; dr < 4; dr++) {
 1491     drive *drv = floppy + dr;
 1492     drv->type = currprefs.dfxtype[dr];
 1493     reset_drive (dr);
 1494     }
 1495     if (disk_empty (0))
 1496     write_log ("No disk in drive 0.\n");
 1497 }
 1498 
 1499 void DISK_reset (void)
 1500 {
 1501     int i;
 1502 
 1503     if (savestate_state)
 1504     return;
 1505 
 1506     disk_hpos = 0;
 1507     disk_data_used = 0;
 1508     dskdmaen = 0;
 1509     disabled = 0;
 1510     for (i = 0; i < 4; i++) {
 1511     reset_drive (i);
 1512     }
 1513 }
 1514 
 1515 void dumpdisk (void)
 1516 {
 1517     int i;
 1518     for (i = 0; i < 4; i++) {
 1519     drive *drv = &floppy[i];
 1520     printf ("Drive %d: motor %s cylinder %2d selected %d\n", i, drv->motoroff ? "off" : " on", drv->cyl, selected & (1 << i));
 1521     }
 1522 }
 1523 
 1524 /* Disk save/restore code */
 1525 
 1526 void DISK_save_custom (uae_u32 *pdskpt, uae_u16 *pdsklength, uae_u16 *pdsksync, uae_u16 *pdskdatr, uae_u16 *pdskbytr)
 1527 {
 1528     if (pdskpt) *pdskpt = dskpt;
 1529     if (pdsklength) *pdsklength = dsklength;
 1530     if (pdsksync) *pdsksync = dsksync;
 1531     if (pdskdatr) *pdskdatr = 0;
 1532     if (pdskbytr) *pdskbytr = dskbytr_tab[0];
 1533 }
 1534 
 1535 void DISK_restore_custom (uae_u32 pdskpt, uae_u16 pdsklength, uae_u16 pdskdatr, uae_u16 pdskbytr)
 1536 {
 1537     dskpt = pdskpt;
 1538     dsklength = pdsklength;
 1539     dskbytr_tab[0] = pdskbytr;
 1540 }
 1541 
 1542 const uae_u8 *restore_disk (int num, const uae_u8 *src)
 1543 {
 1544     drive *drv;
 1545     int state;
 1546     int newis;
 1547 
 1548     drv = &floppy[num];
 1549     disabled &= ~(1 << num);
 1550     drv->drive_id = restore_u32 ();
 1551     drv->motoroff = 1;
 1552     drv->idbit = 0;
 1553     state = restore_u8 ();
 1554     if (state & 2) {
 1555     disabled |= 1 << num;
 1556     if (changed_prefs.nr_floppies > num)
 1557         changed_prefs.nr_floppies = num;
 1558     changed_prefs.dfxtype[num] = -1;
 1559     } else {
 1560     drive_type dfxtype;
 1561     drv->motoroff = (state & 1) ? 0 : 1;
 1562     drv->idbit = (state & 4) ? 1 : 0;
 1563     if (changed_prefs.nr_floppies < num)
 1564         changed_prefs.nr_floppies = num;
 1565     switch (drv->drive_id)
 1566     {
 1567     case DRIVE_ID_35HD:
 1568         dfxtype = DRV_35_HD;
 1569         break;
 1570     case DRIVE_ID_525SD:
 1571         dfxtype = DRV_525_SD;
 1572         break;
 1573     default:
 1574         dfxtype = DRV_35_DD;
 1575         break;
 1576     }
 1577     changed_prefs.dfxtype[num] = dfxtype;
 1578     }
 1579     drv->type = changed_prefs.dfxtype[num];
 1580     drv->buffered_cyl = -1;
 1581     drv->buffered_side = -1;
 1582     drv->cyl = restore_u8 ();
 1583     drv->dskready = restore_u8 ();
 1584     drv->drive_id_scnt = restore_u8 ();
 1585     drv->mfmpos = restore_u32 ();
 1586     drv->dskchange = 0;
 1587     drv->dskchange_time = 0;
 1588     restore_u32 ();
 1589     strncpy (changed_prefs.df[num], src, 255);
 1590     changed_prefs.df[num][255] = 0;
 1591     newis = changed_prefs.df[num][0] ? 1 : 0;
 1592     src += strlen (src) + 1;
 1593 
 1594     if (!(disabled & (1 << num))) {
 1595     if (!newis) {
 1596         drv->dskchange = 1;
 1597     } else {
 1598         drive_insert (floppy + num, num, changed_prefs.df[num]);
 1599     }
 1600     }
 1601 
 1602     return src;
 1603 }
 1604 
 1605 uae_u8 *save_disk (int num, int *len, uae_u8 *dstptr)
 1606 {
 1607     uae_u8 *dstbak,*dst;
 1608     drive *drv;
 1609 
 1610     drv = &floppy[num];
 1611     if (dstptr)
 1612     dstbak = dst = dstptr;
 1613     else
 1614     dstbak = dst = malloc (2+1+1+1+1+4+4+256);
 1615     save_u32 (drv->drive_id);       /* drive type ID */
 1616     save_u8 ((drv->motoroff ? 0:1) | ((disabled & (1 << num)) ? 2 : 0) | (drv->idbit ? 4 : 0) | (drv->dskchange ? 8 : 0));
 1617     save_u8 (drv->cyl);         /* cylinder */
 1618     save_u8 (drv->dskready);        /* dskready */
 1619     save_u8 (drv->drive_id_scnt);   /* id mode position */
 1620     save_u32 (drv->mfmpos);     /* disk position */
 1621     save_u32 (0);           /* CRC of disk image */
 1622     strcpy (dst, currprefs.df[num]);/* image name */
 1623     dst += strlen (dst) + 1;
 1624 
 1625     *len = dst - dstbak;
 1626     return dstbak;
 1627 }
 1628 
 1629 /* internal floppy controller variables */
 1630 
 1631 const uae_u8 *restore_floppy (const uae_u8 *src)
 1632 {
 1633     word = restore_u16 ();
 1634     bitoffset = restore_u8 ();
 1635     dma_enable = restore_u8 ();
 1636     disk_hpos = restore_u8 ();
 1637     dskdmaen = restore_u8 ();
 1638     word |= restore_u16 () << 16;
 1639 
 1640     return src;
 1641 }
 1642 
 1643 uae_u8 *save_floppy (int *len, uae_u8 *dstptr)
 1644 {
 1645     uae_u8 *dstbak, *dst;
 1646 
 1647     /* flush dma buffer before saving */
 1648     dodmafetch ();
 1649 
 1650     if (dstptr)
 1651     dstbak = dst = dstptr;
 1652     else
 1653     dstbak = dst = malloc (2+1+1+1+1+2);
 1654     save_u16 (word);        /* current fifo (low word) */
 1655     save_u8 (bitoffset);    /* dma bit offset */
 1656     save_u8 (dma_enable);   /* disk sync found */
 1657     save_u8 (disk_hpos);    /* next bit read position */
 1658     save_u8 (dskdmaen);     /* dma status */
 1659     save_u16 (word >> 16);  /* current fifo (high word) */
 1660 
 1661     *len = dst - dstbak;
 1662     return dstbak;
 1663 }