]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Floppy emulation updates to support DraCo polled flux change timed Amiga disk reads.
authorToni Wilen <twilen@winuae.net>
Sat, 13 Jan 2024 14:58:30 +0000 (16:58 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 13 Jan 2024 14:58:30 +0000 (16:58 +0200)
disk.cpp
include/disk.h
include/x86.h
x86.cpp

index 20e053140e62bb50025999461b8bc0aa9ab8b2b8..7c4f96eee8082ef65f58138e0df9d0570e14d238 100644 (file)
--- a/disk.cpp
+++ b/disk.cpp
@@ -928,7 +928,7 @@ static void update_drive_gui(int num, bool force)
        gui_led (num + LED_DF0, (gid->drive_motor ? 1 : 0) | (gid->drive_writing ? 2 : 0), -1);
 }
 
-static void drive_fill_bigbuf (drive * drv,int);
+static void drive_fill_bigbuf(drive *drv, int, int);
 
 void DISK_get_path_text(struct uae_prefs *p, int n, TCHAR *text)
 {
@@ -1440,7 +1440,7 @@ static int drive_insert (drive *drv, struct uae_prefs *p, int dnum, const TCHAR
                drive_settype_id(drv); /* Set DD or HD drive */
                update_drive_gui(drv->drvnum, false);
                update_disk_statusline(drv->drvnum);
-               drive_fill_bigbuf(drv, fake ? -1 : 1);
+               drive_fill_bigbuf(drv, side, fake ? -1 : 1);
 
                return 1;
 #endif
@@ -1737,7 +1737,7 @@ static int drive_insert (drive *drv, struct uae_prefs *p, int dnum, const TCHAR
        }
        openwritefile(p, drv, 0);
        drive_settype_id(drv); /* Set DD or HD drive */
-       drive_fill_bigbuf(drv, 1);
+       drive_fill_bigbuf(drv, side, 1);
        drv->mfmpos = uaerand();
        drv->mfmpos |= uaerand() << 16;
        drv->mfmpos &= 0xffffff;
@@ -2077,10 +2077,10 @@ static uae_u16 *mfmcoder (uae_u8 *src, uae_u16 *dest, int len)
        return dest;
 }
 
-static void decode_pcdos (drive *drv)
+static void decode_pcdos (drive *drv, int tside)
 {
        int i, len;
-       int tr = drv->cyl * 2 + side;
+       int tr = drv->cyl * 2 + tside;
        uae_u16 *dstmfmbuf, *mfm2;
        uae_u8 secbuf[1000];
        uae_u16 crc16;
@@ -2143,10 +2143,10 @@ static void decode_pcdos (drive *drv)
                write_log (_T("pcdos read track %d\n"), tr);
 }
 
-static void decode_amigados (drive *drv)
+static void decode_amigados(drive *drv, int tside)
 {
        /* Normal AmigaDOS format track */
-       int tr = drv->cyl * 2 + side;
+       int tr = drv->cyl * 2 + tside;
        int sec;
        int dstmfmoffset = 0;
        uae_u16 *dstmfmbuf = drv->bigmfmbuf;
@@ -2265,9 +2265,9 @@ static void decode_amigados (drive *drv)
 *
 */
 
-static void decode_diskspare (drive *drv)
+static void decode_diskspare(drive *drv, int tside)
 {
-       int tr = drv->cyl * 2 + side;
+       int tr = drv->cyl * 2 + tside;
        int sec;
        int dstmfmoffset = 0;
        int size = 512 + 8;
@@ -2341,9 +2341,9 @@ static void decode_diskspare (drive *drv)
                write_log (_T("diskspare read track %d\n"), tr);
 }
 
-static void drive_fill_bigbuf (drive * drv, int force)
+static void drive_fill_bigbuf(drive *drv, int tside, int force)
 {
-       int tr = drv->cyl * 2 + side;
+       int tr = drv->cyl * 2 + tside;
        trackid *ti = drv->trackdata + tr;
        bool retrytrack;
        int rev = -1;
@@ -2362,17 +2362,17 @@ static void drive_fill_bigbuf (drive * drv, int force)
                return;
        }
 
-       if (!force && drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
+       if (!force && drv->buffered_cyl == drv->cyl && drv->buffered_side == tside)
                return;
        drv->indexoffset = 0;
        drv->multi_revolution = 0;
        drv->tracktiming[0] = 0;
        drv->skipoffset = -1;
        drv->revolutions = 1;
-       retrytrack = drv->lastdataacesstrack == drv->cyl * 2 + side;
+       retrytrack = drv->lastdataacesstrack == drv->cyl * 2 + tside;
        if (!dskdmaen && !retrytrack)
                drv->track_access_done = false;
-       //write_log (_T("%d:%d %d\n"), drv->cyl, side, retrytrack);
+       //write_log (_T("%d:%d %d\n"), drv->cyl, tside, retrytrack);
 
        if (drv->writediskfile && drv->writetrackdata[tr].bitlen > 0) {
                int i;
@@ -2392,7 +2392,7 @@ static void drive_fill_bigbuf (drive * drv, int force)
                if (drv->bridge) {
                        drv->multi_revolution = 1;
                        drv->skipoffset = -1;
-                       drv->bridge->setSurface(side); // force the correct disk side to be selected
+                       drv->bridge->setSurface(tside); // force the correct disk side to be selected
                        drv->tracklen = drv->bridge->maxMFMBitPosition();
                        drv->tracktiming[0] = drv->bridge->getMFMSpeed(drv->mfmpos % drv->tracklen);
                        if (force < 0) {
@@ -2404,7 +2404,7 @@ static void drive_fill_bigbuf (drive * drv, int force)
 #ifdef CATWEASEL
                drv->tracklen = 0;
                if (!catweasel_disk_changed (drv->catweasel)) {
-                       drv->tracklen = catweasel_fillmfm (drv->catweasel, drv->bigmfmbuf, side, drv->ddhd, 0);
+                       drv->tracklen = catweasel_fillmfm (drv->catweasel, drv->bigmfmbuf, tside, drv->ddhd, 0);
                }
                drv->buffered_cyl = -1;
                if (!drv->tracklen) {
@@ -2432,15 +2432,15 @@ static void drive_fill_bigbuf (drive * drv, int force)
 
        } else if (ti->type == TRACK_PCDOS) {
 
-               decode_pcdos(drv);
+               decode_pcdos(drv, tside);
 
        } else if (ti->type == TRACK_AMIGADOS) {
 
-               decode_amigados(drv);
+               decode_amigados(drv, tside);
 
        } else if (ti->type == TRACK_DISKSPARE) {
 
-               decode_diskspare(drv);
+               decode_diskspare(drv, tside);
 
        } else if (ti->type == TRACK_NONE) {
 
@@ -2460,7 +2460,7 @@ static void drive_fill_bigbuf (drive * drv, int force)
                if (disk_debug_logging > 2)
                        write_log (_T("rawtrack %d image offset=%x\n"), tr, ti->offs);
        }
-       drv->buffered_side = side;
+       drv->buffered_side = tside;
        drv->buffered_cyl = drv->cyl;
        if (drv->tracklen == 0) {
                drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 2 * 8;
@@ -2885,7 +2885,7 @@ static bool convert_adf_to_ext2 (drive *drv, int mode)
 #ifdef RETROPLATFORM
        rp_disk_image_change(drv->drvnum, name, false);
 #endif
-       drive_fill_bigbuf(drv, 1);
+       drive_fill_bigbuf(drv, side, 1);
 
        return true;
 }
@@ -4493,6 +4493,36 @@ static void disk_dma_debugmsg (void)
                dsklength, dsklength, (adkcon & 0x400) ? dsksync : 0xffff, dskpt, adkcon, intreq, M68K_GETPC);
 }
 
+// fake raw read for draco
+uae_u16 DSKBYTR_fake(int num)
+{
+       drive *drv = &floppy[num];
+       uae_u16 ret;
+       uae_u16 ac = adkcon;
+       
+       adkcon |= 0x100;
+       int mfmpos = drv->mfmpos;
+       bool isempty = drive_empty(drv);
+       bool isunformatted = unformatted(drv);
+       int inc = 1;
+       int fword = 0;
+       for (int i = 0; i < 8; i++) {
+               fword <<= 1;
+               if (!isempty) {
+                       if (isunformatted)
+                               fword |= (uaerand() & 0x1000) ? 1 : 0;
+                       else
+                               fword |= getonebit(drv, drv->bigmfmbuf, mfmpos, &inc);
+               }
+               mfmpos += inc;
+               mfmpos %= drv->tracklen;
+       }
+       drv->mfmpos = mfmpos;
+       ret = 0x8000 | (fword & 0xff);
+       adkcon = ac;
+       return ret;
+}
+
 /* this is very unoptimized. DSKBYTR is used very rarely, so it should not matter. */
 
 uae_u16 DSKBYTR(int hpos)
@@ -4603,13 +4633,13 @@ static void DISK_start(void)
 #ifdef CATWEASEL
                        if (drv->catweasel) {
                                word = 0;
-                               drive_fill_bigbuf (drv, 1);
+                               drive_fill_bigbuf (drv, side, 1);
                        }
 #endif
 #ifdef FLOPPYBRIDGE
                        if (drv->bridge && dskdmaen != DSKDMA_WRITE) {
                                word = 0;
-                               drive_fill_bigbuf(drv, 1);
+                               drive_fill_bigbuf(drv, side, 1);
                        }
 #endif
                }
@@ -4728,11 +4758,11 @@ void DISK_update (int tohpos)
                        continue;
                }
                if (drv->diskfile) {
-                       drive_fill_bigbuf(drv, 0);
+                       drive_fill_bigbuf(drv, side, 0);
                }
 #ifdef FLOPPYBRIDGE
                if (drv->bridge) {
-                       drive_fill_bigbuf(drv, 0);
+                       drive_fill_bigbuf(drv, side, 0);
                }
 #endif
                drv->mfmpos %= drv->tracklen;
@@ -4962,7 +4992,7 @@ static void DSKLEN_2(uae_u16 v, int hpos)
                                continue;
 
                        pos = drv->mfmpos & ~15;
-                       drive_fill_bigbuf (drv, 0);
+                       drive_fill_bigbuf (drv, side, 0);
 
                        if (dskdmaen == DSKDMA_READ) { /* TURBO read */
 
@@ -5443,7 +5473,7 @@ static void load_track (int num, int cyl, int dside, int *sectable)
        drv->cyl = cyl;
        side = dside;
        drv->buffered_cyl = -1;
-       drive_fill_bigbuf (drv, -1);
+       drive_fill_bigbuf (drv, side, -1);
        decode_buffer (drv, drv->bigmfmbuf, drv->cyl, 11, drv->ddhd, drv->filetype, &drvsec, sectable, 1);
        drv->cyl = oldcyl;
        side = oldside;
@@ -6244,6 +6274,12 @@ void disk_reserved_setinfo(int num, int cyl, int head, int motor)
                drv->cyl = cyl;
                drv->state = motor != 0;
                update_drive_gui(i, false);
+               drive_fill_bigbuf(drv, head, 0);
+               // for some reason draco does not like it if data read starts from beginning of gap
+               drv->mfmpos = 8 * 16;
+               while ((drv->bigmfmbuf[drv->mfmpos / 16] == 0xaaaa || drv->bigmfmbuf[drv->mfmpos / 16] == 0x5555) && drv->mfmpos < 2048 && drv->mfmpos < drv->tracklen / 4) {
+                       drv->mfmpos += 16;
+               }
        }
 }
 
@@ -6262,7 +6298,7 @@ bool disk_reserved_getinfo(int num, struct floppy_reserved *fr)
                        if (z) {
                                bool ok = false;
                                drv->num_secs = 21; // max possible
-                               drive_fill_bigbuf(drv, true);
+                               drive_fill_bigbuf(drv, side, true);
                                int secs = drive_write_pcdos(drv, z, 1);
                                if (secs >= 8) {
                                        ok = true;
@@ -6270,7 +6306,7 @@ bool disk_reserved_getinfo(int num, struct floppy_reserved *fr)
                                        for (int i = 0; i < drv->num_tracks; i++) {
                                                drv->cyl = i / 2;
                                                side = i & 1;
-                                               drive_fill_bigbuf(drv, true);
+                                               drive_fill_bigbuf(drv, side, true);
                                                drive_write_pcdos(drv, z, 0);
                                        }
                                }
index 7da217fd62d8118c43d5457461a65c0deb69402a..bfffae0009655f0e22338fb49cdd617222af6e9c 100644 (file)
@@ -109,6 +109,7 @@ extern uae_u16 DSKDATR (int);
 extern uae_u16 disk_dmal (void);
 extern uaecptr disk_getpt (void);
 extern int disk_fifostatus (void);
+extern uae_u16 DSKBYTR_fake(int);
 
 extern int disk_debug_logging;
 extern int disk_debug_mode;
index d153e22811fabdacc605c7a1a4d5b99ebf352ec6..62c3d18d2cfe1fe599cc3e92fe4e583f5e762b52 100644 (file)
@@ -23,5 +23,6 @@ uae_u8 x86_infloppy(int portnum);
 void x86_outfloppy(int portnum, uae_u8 v);
 void x86_initfloppy(X86_INTERRUPT_CALLBACK);
 void x86_floppy_run(void);
+uae_u16 floppy_get_raw_data(void);
 
 #endif /* UAE_X86_H */
diff --git a/x86.cpp b/x86.cpp
index dcbf3dc876624022faf445573e362340d2df7bee..92d945981245b684a3a80e8bfb99b420feceeb07 100644 (file)
--- a/x86.cpp
+++ b/x86.cpp
@@ -554,6 +554,7 @@ struct pc_floppy
        int cyl;
        uae_u8 sector;
        uae_u8 head;
+       bool disk_changed;
 };
 
 static struct pc_floppy floppy_pc[4];
@@ -625,13 +626,21 @@ static void do_floppy_irq(void)
 
 static void do_floppy_seek(int num, int error)
 {
-       struct pc_floppy *pcf = &floppy_pc[floppy_num];
+       struct pc_floppy *pcf = &floppy_pc[num];
 
        disk_reserved_reset_disk_change(num);
        if (!error) {
                struct floppy_reserved fr = { 0 };
-               bool valid_floppy = disk_reserved_getinfo(floppy_num, &fr);
+               bool valid_floppy = disk_reserved_getinfo(num, &fr);
                if (floppy_seekcyl[num] != pcf->phys_cyl) {
+
+                       if (!valid_floppy || !fr.img) {
+                               error = 1;
+                               goto done;
+                       }
+
+                       pcf->disk_changed = false;
+
                        if (floppy_seekcyl[num] > pcf->phys_cyl)
                                pcf->phys_cyl++;
                        else if (pcf->phys_cyl > 0)
@@ -642,14 +651,14 @@ static void do_floppy_seek(int num, int error)
                                driveclick_click(fr.num, pcf->phys_cyl);
 #endif
 #if FLOPPY_DEBUG
-                       write_log(_T("Floppy%d seeking.. %d\n"), floppy_num, pcf->phys_cyl);
+                       write_log(_T("Floppy%d seeking.. %d\n"), num, pcf->phys_cyl);
 #endif
                        if (pcf->phys_cyl - pcf->seek_offset <= 0) {
                                pcf->phys_cyl = 0;
                                if (pcf->seek_offset) {
                                        floppy_seekcyl[num] = 0;
 #if FLOPPY_DEBUG
-                                       write_log(_T("Floppy%d early track zero\n"), floppy_num);
+                                       write_log(_T("Floppy%d early track zero\n"), num);
 #endif
                                        pcf->seek_offset = 0;
                                }
@@ -661,7 +670,7 @@ static void do_floppy_seek(int num, int error)
                                pcf->cyl = pcf->phys_cyl;
 
                        floppy_seeking[num] = PC_SEEK_DELAY;
-                       disk_reserved_setinfo(floppy_num, pcf->cyl, pcf->head, 1);
+                       disk_reserved_setinfo(num, pcf->cyl, pcf->head, 1);
                        return;
                }
 
@@ -682,7 +691,7 @@ static void do_floppy_seek(int num, int error)
 
 done:
 #if FLOPPY_DEBUG
-       write_log(_T("Floppy%d seek done err=%d. pcyl=%d cyl=%d h=%d\n"), floppy_num, error, pcf->phys_cyl,pcf->cyl, pcf->head);
+       write_log(_T("Floppy%d seek done err=%d. pcyl=%d cyl=%d h=%d\n"), num, error, pcf->phys_cyl,pcf->cyl, pcf->head);
 #endif
        floppy_status[0] = 0;
        floppy_status[0] |= 0x20; // seek end
@@ -716,6 +725,21 @@ static int floppy_selected(void)
        return -1;
 }
 
+static void floppy_clear_irq(void)
+{
+       if (floppy_irq) {
+               x86_clearirq(6);
+               floppy_irq = false;
+       }
+}
+
+static bool floppy_valid_format(struct floppy_reserved *fr)
+{
+       if (fr->secs == 11 || fr->secs == 22)
+               return false;
+       return true;
+}
+
 static bool floppy_valid_rate(struct floppy_reserved *fr)
 {
        struct x86_bridge *xb = bridges[0];
@@ -763,8 +787,7 @@ static void floppy_do_cmd(struct x86_bridge *xb)
                        // 0xc0 status after reset.
                        floppy_status[0] = 0xc0;
                }
-               x86_clearirq(6);
-               floppy_irq = false;
+               floppy_clear_irq();
                floppy_result[0] = floppy_status[0];
                floppy_result[1] = pcf->phys_cyl;
                floppy_status[0] = 0;
@@ -833,16 +856,20 @@ static void floppy_do_cmd(struct x86_bridge *xb)
                                        while (!end && !fr.wrprot) {
                                                int len = 128 << floppy_cmd[5];
                                                uae_u8 buf[512] = { 0 };
-                                               for (int i = 0; i < 512 && i < len; i++) {
-                                                       int v = dma_channel_read(2);
-                                                       if (v < 0) {
-                                                               end = -1;
-                                                               break;
-                                                       }
-                                                       buf[i] = v;
-                                                       if (v >= 0x10000) {
-                                                               end = 1;
-                                                               break;
+                                               if (floppy_specify_pio) {
+                                                       end = -1;
+                                               } else {
+                                                       for (int i = 0; i < 512 && i < len; i++) {
+                                                               int v = dma_channel_read(2);
+                                                               if (v < 0) {
+                                                                       end = -1;
+                                                                       break;
+                                                               }
+                                                               buf[i] = v;
+                                                               if (v >= 0x10000) {
+                                                                       end = 1;
+                                                                       break;
+                                                               }
                                                        }
                                                }
 #if FLOPPY_DEBUG
@@ -907,7 +934,7 @@ static void floppy_do_cmd(struct x86_bridge *xb)
                        int cyl = pcf->cyl;
                        bool nodata = false;
                        if (valid_floppy) {
-                               if (!floppy_valid_rate(&fr)) {
+                               if (!floppy_valid_rate(&fr) || !floppy_valid_format(&fr)) {
                                        nodata = true;
                                } else if (pcf->head && fr.heads == 1) {
                                        nodata = true;
@@ -991,7 +1018,7 @@ static void floppy_do_cmd(struct x86_bridge *xb)
 #if FLOPPY_DEBUG
                write_log(_T("Floppy read ID\n"));
 #endif
-               if (!valid_floppy || !fr.img || !floppy_valid_rate(&fr) || (pcf->head && fr.heads == 1)) {
+               if (!valid_floppy || !fr.img || !floppy_valid_rate(&fr) || (pcf->head && fr.heads == 1) || !floppy_valid_format(&fr)) {
                        floppy_status[0] |= 0x40; // abnormal termination
                        floppy_status[1] |= 0x04; // no data
                }
@@ -1107,6 +1134,10 @@ static int draco_force_irq;
 
 static void outfloppy(struct x86_bridge *xb, int portnum, uae_u8 v)
 {
+#if FLOPPY_IO_DEBUG
+       write_log(_T("out floppy port %04x %02x\n"), portnum, v);
+#endif
+
        switch (portnum)
        {
                case 0x3f2: // dpc
@@ -1129,12 +1160,12 @@ static void outfloppy(struct x86_bridge *xb, int portnum, uae_u8 v)
                }
 #endif
                floppy_dpc = v;
-               if (xb->type < 0 && 1) {
+               if (xb->type < 0) {
                        floppy_dpc |= 8;
                }
                floppy_num = v & 3;
                for (int i = 0; i < 2; i++) {
-                       disk_reserved_setinfo(0, floppy_pc[i].cyl, floppy_pc[i].head, floppy_selected() == i);
+                       disk_reserved_setinfo(i, floppy_pc[i].cyl, floppy_pc[i].head, floppy_selected() == i);
                }
                break;
                case 0x3f5: // data reg
@@ -1210,9 +1241,6 @@ static void outfloppy(struct x86_bridge *xb, int portnum, uae_u8 v)
                write_log(_T("Unknown FDC %04x write %02x\n"), portnum, v);
                break;
        }
-#if FLOPPY_IO_DEBUG
-       write_log(_T("out floppy port %04x %02x\n"), portnum, v);
-#endif
 }
 
 static uae_u8 infloppy(struct x86_bridge *xb, int portnum)
@@ -1265,6 +1293,8 @@ static uae_u8 infloppy(struct x86_bridge *xb, int portnum)
                        v = floppy_pio_buffer[floppy_pio_cnt++];
                        if (floppy_pio_cnt >= floppy_pio_len) {
                                floppy_pio_len = 0;
+                               floppy_clear_irq();
+                               floppy_delay_hsync = 50;
                        }
                } else if (floppy_cmd_len && floppy_dir) {
                        int idx = (-floppy_idx) - 1;
@@ -1276,23 +1306,23 @@ static uae_u8 infloppy(struct x86_bridge *xb, int portnum)
                                        floppy_cmd_len = 0;
                                        floppy_dir = 0;
                                        floppy_idx = 0;
+                                       floppy_clear_irq();
                                }
                        }
                }
                break;
                case 0x3f7: // digital input register
-               if (xb->type >= TYPE_2286) {
+               if (xb->type >= TYPE_2286 || xb->type < 0) {
+                       struct pc_floppy *pcf = &floppy_pc[floppy_num];
                        struct floppy_reserved fr = { 0 };
                        bool valid_floppy = disk_reserved_getinfo(floppy_num, &fr);
                        v = 0x00;
-                       if (valid_floppy && fr.disk_changed)
-                               v = 0x80;
-               } else if (xb->type < 0) {
-                       struct floppy_reserved fr = { 0 };
-                       bool valid_floppy = disk_reserved_getinfo(floppy_num, &fr);
-                       v = 0x00;
-                       if (fr.disk_changed)
+                       if (valid_floppy && fr.disk_changed && (floppy_dpc >> 4) & (1 << floppy_num)) {
+                               pcf->disk_changed = true;
+                       }
+                       if (pcf->disk_changed) {
                                v = 0x80;
+                       }
                }
                break;
                default:
@@ -1305,6 +1335,16 @@ static uae_u8 infloppy(struct x86_bridge *xb, int portnum)
        return v;
 }
 
+uae_u16 floppy_get_raw_data(void)
+{
+       struct floppy_reserved fr = { 0 };
+       bool valid_floppy = disk_reserved_getinfo(floppy_num, &fr);
+       if (valid_floppy) {
+               return DSKBYTR_fake(fr.num);
+       }
+       return 0x8000;
+}
+
 static void set_cpu_turbo(struct x86_bridge *xb)
 {
        cpu_multiplier = (int)currprefs.x86_speed_throttle;