From: Toni Wilen Date: Sat, 13 Jan 2024 14:58:30 +0000 (+0200) Subject: Floppy emulation updates to support DraCo polled flux change timed Amiga disk reads. X-Git-Tag: 5200~68 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=ff3f284895ec2b7fd6ce2bd928a5a86579a65c8f;p=francis%2Fwinuae.git Floppy emulation updates to support DraCo polled flux change timed Amiga disk reads. --- diff --git a/disk.cpp b/disk.cpp index 20e05314..7c4f96ee 100644 --- 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); } } diff --git a/include/disk.h b/include/disk.h index 7da217fd..bfffae00 100644 --- a/include/disk.h +++ b/include/disk.h @@ -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; diff --git a/include/x86.h b/include/x86.h index d153e228..62c3d18d 100644 --- a/include/x86.h +++ b/include/x86.h @@ -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 dcbf3dc8..92d94598 100644 --- 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;