From: Toni Wilen Date: Sat, 9 Oct 2021 18:00:23 +0000 (+0300) Subject: floppybridge integration X-Git-Tag: 4900~48 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=5f01e380725a52b75c3aa5fd0e89d148c7cea99e;p=francis%2Fwinuae.git floppybridge integration --- diff --git a/cfgfile.cpp b/cfgfile.cpp index d30f8b4c..c3722be1 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -833,6 +833,10 @@ static void cfgfile_write_str(struct zfile *f, const TCHAR *option, const TCHAR { cfg_dowrite(f, option, optionext, value, 0, 0, 0); } +static void cfgfile_write_str_escape(struct zfile *f, const TCHAR *option, const TCHAR *value) +{ + cfg_dowrite(f, option, value, 0, 0, 1); +} void cfgfile_dwrite_str(struct zfile *f, const TCHAR *option, const TCHAR *value) { cfg_dowrite(f, option, value, 1, 0, 0); @@ -1982,6 +1986,10 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) _stprintf (tmp, _T("floppy%dsoundvolume_empty"), i); cfgfile_write (f, tmp, _T("%d"), p->dfxclickvolume_empty[i]); } + if (p->floppyslots[i].config[0]) { + _stprintf(tmp, _T("floppy%dconfig"), i); + cfgfile_write_str_escape(f, tmp, p->floppyslots[i].config); + } if (p->floppyslots[i].dfxtype < 0 && p->nr_floppies > i) p->nr_floppies = i; } @@ -5922,6 +5930,10 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH p->floppyslots[i].df[0] = 0; return 1; } + _stprintf(tmpbuf, _T("floppy%dconfig"), i); + if (cfgfile_string_escape(option, value, tmpbuf, p->floppyslots[i].config, sizeof p->floppyslots[i].config / sizeof(TCHAR))) { + return 1; + } } if (cfgfile_intval (option, value, _T("chipmem_size"), &dummyint, 1)) { diff --git a/disk.cpp b/disk.cpp index 12d3f14c..2cde20e1 100644 --- a/disk.cpp +++ b/disk.cpp @@ -56,6 +56,10 @@ int disk_debug_track = -1; #include "statusline.h" #include "rommgr.h" #include "tinyxml2.h" +#ifdef FLOPPYBRIDGE +#include "floppybridge/floppybridge_abstract.h" +#include "floppybridge/floppybridge_lib.h" +#endif #undef CATWEASEL @@ -160,7 +164,7 @@ typedef struct { #define DRIVE_ID_35HD 0xAAAAAAAA #define DRIVE_ID_525SD 0x55555555 /* 40 track 5.25 drive , kickstart does not recognize this */ -typedef enum { ADF_NONE = -1, ADF_NORMAL, ADF_EXT1, ADF_EXT2, ADF_FDI, ADF_IPF, ADF_SCP, ADF_CATWEASEL, ADF_PCDOS, ADF_KICK, ADF_SKICK, ADF_NORMAL_HEADER } drive_filetype; +typedef enum { ADF_NONE = -1, ADF_NORMAL, ADF_EXT1, ADF_EXT2, ADF_FDI, ADF_IPF, ADF_SCP, ADF_CATWEASEL, ADF_PCDOS, ADF_KICK, ADF_SKICK, ADF_NORMAL_HEADER, ADF_FLOPPYBRIDGE } drive_filetype; typedef struct { struct zfile *diskfile; struct zfile *writediskfile; @@ -221,6 +225,9 @@ typedef struct { bool track_access_done; bool fourms; #endif +#ifdef FLOPPYBRIDGE + FloppyDiskBridge *bridge; +#endif } drive; #define MIN_STEPLIMIT_CYCLE (CYCLE_UNIT * 140) @@ -552,6 +559,23 @@ static int createimagefromexe (struct zfile *src, struct zfile *dst) return 1; } +#ifdef FLOPPYBRIDGE +static FloppyBridgeAPI *bridges[4]; +static int bridge_type[4]; +static const FloppyDiskBridge::BridgeDriver *bridge_driver[4]; +static bool floppybridge_available; +static FloppyBridgeAPI::BridgeInformation bridgeinfo; +static bool bridgeinfoloaded; +static std::vector bridgedriverinfo; +static void floppybridge_read_track(drive *drv); + +bool DISK_isfloppybridge(struct uae_prefs *p, int num) +{ + int v = p->floppyslots[num].dfxtype; + return v == DRV_FB_A_35_DD || v == DRV_FB_A_35_HD || v == DRV_FB_B_35_DD || v == DRV_FB_B_35_HD; +} +#endif + static bool isfloppysound (drive *drv) { return drv->useturbo == 0; @@ -570,6 +594,16 @@ static int get_floppy_speed_from_image(drive *drv) { int l, m; +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + drv->fourms = drv->bridge->getBitSpeed() == 4; + m = NORMAL_FLOPPY_SPEED; + if (drv->fourms) { + m *= 2; + } + return m; + } +#endif m = get_floppy_speed(); l = drv->tracklen; drv->fourms = false; @@ -609,6 +643,34 @@ static void drive_settype_id (drive *drv) { int t = currprefs.floppyslots[drv - &floppy[0]].dfxtype; +#ifdef FLOPPYBRIDGE + if (drv->bridge) + { + if (drv->bridge->isDiskInDrive()) { + switch (drv->bridge->getDriveTypeID()) { + case FloppyDiskBridge::DriveTypeID::dti35DD: + drv->drive_id = DRIVE_ID_35DD; + break; + case FloppyDiskBridge::DriveTypeID::dti35HD: + if (t == DRV_35_HD) { + drv->drive_id = DRIVE_ID_35HD; + } else { + drv->drive_id = DRIVE_ID_35DD; + } + break; + case FloppyDiskBridge::DriveTypeID::dti5255SD: + drv->drive_id = DRIVE_ID_525SD; + break; + } + drv->ddhd = drv->bridge->getDriveTypeID() == FloppyDiskBridge::DriveTypeID::dti35HD ? 2 : 1; + } else { + drv->drive_id = DRIVE_ID_35DD; + drv->ddhd = 1; + } + return; + } +#endif + switch (t) { case DRV_35_HD: @@ -714,6 +776,12 @@ static bool ispcbridgedrive(int num) static bool drive_writeprotected(drive *drv) { +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + bool v = drv->bridge->isWriteProtected(); + return v; + } +#endif #ifdef CATWEASEL if (drv->catweasel) return 1; @@ -757,6 +825,16 @@ static void reset_drive (int num) _tcscpy (currprefs.floppyslots[num].df, changed_prefs.floppyslots[num].df); drv->newname[0] = 0; drv->newnamewriteprotected = false; +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + drv->bridge->resetDrive(drv->cyl); + drv->indexhackmode = 0; + drv->num_tracks = drv->bridge->getMaxCylinder() * 2; + drv->filetype = ADF_FLOPPYBRIDGE; + drv->tracklen = drv->bridge->maxMFMBitPosition(); + drv->ddhd = drv->bridge->getDriveTypeID() == FloppyDiskBridge::DriveTypeID::dti35HD ? 2 : 1; + } +#endif if (!drive_insert (drv, &currprefs, num, currprefs.floppyslots[num].df, false, false)) disk_eject (num); } @@ -786,12 +864,36 @@ static void update_drive_gui (int num, bool force) gui_data.drive_side = side; gid->drive_writing = writ; gid->floppy_protected = drive_writeprotected(drv); + gid->floppy_inserted = gid->df[0] || (drv->bridge && !drv->bridge->hasDiskChanged()); gui_led (num + LED_DF0, (gid->drive_motor ? 1 : 0) | (gid->drive_writing ? 2 : 0), -1); } static void drive_fill_bigbuf (drive * drv,int); -int DISK_validate_filename (struct uae_prefs *p, const TCHAR *fname_in, TCHAR *outfname, int leave_open, bool *wrprot, uae_u32 *crc32, struct zfile **zf) +void DISK_get_path_text(struct uae_prefs *p, int n, TCHAR *text) +{ + _tcscpy(text, p->floppyslots[n].df); +#ifdef FLOPPYBRIDGE + if (DISK_isfloppybridge(p, n) && floppybridge_available) { + if (!bridgeinfoloaded) { + FloppyBridgeAPI::getBridgeDriverInformation(bridgeinfo); + } + _tcscpy(text, bridgeinfo.about); + if (bridge_driver[n]) { + _tcscat(text, _T(", ")); + TCHAR *name = au(bridge_driver[n]->name); + TCHAR *man = au(bridge_driver[n]->manufacturer); + _tcscat(text, name); + _tcscat(text, _T(", ")); + _tcscat(text, man); + xfree(man); + xfree(name); + } + } +#endif +} + +int DISK_validate_filename (struct uae_prefs *p, const TCHAR *fname_in, int num, TCHAR *outfname, int leave_open, bool *wrprot, uae_u32 *crc32, struct zfile **zf) { TCHAR outname[MAX_DPATH]; @@ -801,6 +903,14 @@ int DISK_validate_filename (struct uae_prefs *p, const TCHAR *fname_in, TCHAR *o *crc32 = 0; if (wrprot) *wrprot = p->floppy_read_only ? 1 : 0; + if (outfname) + outfname[0] = 0; + +#ifdef FLOPPYBRIDGE + if (DISK_isfloppybridge(p, num)) { + return 1; + } +#endif cfgfile_resolve_path_out_load(fname_in, outname, MAX_DPATH, PATH_FLOPPY); if (outfname) @@ -995,24 +1105,24 @@ TCHAR *DISK_get_saveimagepath(const TCHAR *name, int type) return DISK_get_saveimagepath(name, -1); } -static struct zfile *getexistingwritefile(struct uae_prefs *p, const TCHAR *name, bool *wrprot) +static struct zfile *getexistingwritefile(struct uae_prefs *p, const TCHAR *name, int num, bool *wrprot) { struct zfile *zf = NULL; TCHAR *path; TCHAR outname[MAX_DPATH]; path = DISK_get_saveimagepath(name, saveimageoriginalpath); - DISK_validate_filename (p, path, outname, 1, wrprot, NULL, &zf); + DISK_validate_filename(p, path, num, outname, 1, wrprot, NULL, &zf); xfree(path); if (zf) return zf; path = DISK_get_saveimagepath(name, !saveimageoriginalpath); - DISK_validate_filename (p, path, outname, 1, wrprot, NULL, &zf); + DISK_validate_filename(p, path, num, outname, 1, wrprot, NULL, &zf); xfree(path); return zf; } -static int iswritefileempty (struct uae_prefs *p, const TCHAR *name) +static int iswritefileempty(struct uae_prefs *p, int num, const TCHAR *name) { struct zfile *zf; bool wrprot; @@ -1020,7 +1130,7 @@ static int iswritefileempty (struct uae_prefs *p, const TCHAR *name) trackid td[MAX_TRACKS]; int tracks, ddhd, i, ret; - zf = getexistingwritefile (p, name, &wrprot); + zf = getexistingwritefile(p, name, num, &wrprot); if (!zf) return 1; zfile_fread (buffer, sizeof (char), 8, zf); @@ -1043,7 +1153,7 @@ static int openwritefile (struct uae_prefs *p, drive *drv, int create) { bool wrprot = 0; - drv->writediskfile = getexistingwritefile(p, currprefs.floppyslots[drv - &floppy[0]].df, &wrprot); + drv->writediskfile = getexistingwritefile(p, currprefs.floppyslots[drv - &floppy[0]].df, drv - &floppy[0], &wrprot); if (drv->writediskfile) { drv->wrprot = wrprot; if (!read_header_ext2 (drv->writediskfile, drv->writetrackdata, &drv->write_num_tracks, 0)) { @@ -1060,7 +1170,7 @@ static int openwritefile (struct uae_prefs *p, drive *drv, int create) return drv->writediskfile ? 1 : 0; } -static bool diskfile_iswriteprotect (struct uae_prefs *p, const TCHAR *fname_in, int *needwritefile, drive_type *drvtype) +static bool diskfile_iswriteprotect (struct uae_prefs *p, const TCHAR *fname_in, int num, int *needwritefile, drive_type *drvtype) { struct zfile *zf1, *zf2; bool wrprot1 = 0, wrprot2 = 1; @@ -1069,14 +1179,14 @@ static bool diskfile_iswriteprotect (struct uae_prefs *p, const TCHAR *fname_in, *needwritefile = 0; *drvtype = DRV_35_DD; - DISK_validate_filename (p, fname_in, outname, 1, &wrprot1, NULL, &zf1); + DISK_validate_filename (p, fname_in, num, outname, 1, &wrprot1, NULL, &zf1); if (!zf1) return 1; if (zfile_iscompressed (zf1)) { wrprot1 = 1; *needwritefile = 1; } - zf2 = getexistingwritefile(p, fname_in, &wrprot2); + zf2 = getexistingwritefile(p, fname_in, num, &wrprot2); zfile_fclose (zf2); zfile_fread (buffer, sizeof (char), 25, zf1); zfile_fclose (zf1); @@ -1123,6 +1233,15 @@ static bool isrecognizedext(const TCHAR *name) static void update_disk_statusline(int num) { drive *drv = &floppy[num]; +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + const char *name = drv->bridge->getDriverInfo()->name; + TCHAR *n = au(name); + statusline_add_message(STATUSTYPE_FLOPPY, _T("DF%d: %s"), num, n); + xfree(n); + return; + } +#endif if (!drv->diskfile) return; const TCHAR *fname = zfile_getoriginalname(drv->diskfile); @@ -1145,9 +1264,10 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR TCHAR outname[MAX_DPATH]; drive_image_free (drv); - if (!fake) - DISK_examine_image(p, dnum, &disk_info_data, false); - DISK_validate_filename (p, fname_in, outname, 1, &drv->wrprot, &drv->crc32, &drv->diskfile); + if (!fake && !drv->bridge) { + DISK_examine_image(p, dnum, &disk_info_data, false, NULL); + } + DISK_validate_filename (p, fname_in, dnum, outname, 1, &drv->wrprot, &drv->crc32, &drv->diskfile); drv->forcedwrprot = forcedwriteprotect; if (drv->forcedwrprot) drv->wrprot = true; @@ -1168,7 +1288,7 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR drv->dskready_down_time = 0; } - if (drv->diskfile == NULL && !drv->catweasel) { + if (drv->diskfile == NULL && !drv->catweasel && !drv->bridge) { track_reset (drv); return 0; } @@ -1214,6 +1334,35 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR drv->num_tracks = 80; drv->ddhd = 1; +#ifdef FLOPPYBRIDGE + } else if (drv->bridge) { + drv->ddhd = (drv->bridge->getDriveTypeID() == FloppyDiskBridge::DriveTypeID::dti35HD) ? 2 : 1; + drv->num_heads = 2; + drv->num_secs = 0; + drv->hard_num_cyls = drv->bridge->getMaxCylinder(); + drv->num_tracks = drv->bridge->getMaxCylinder() * 2; + drv->tracklen = drv->bridge->maxMFMBitPosition(); + drv->tracktiming[0] = drv->bridge->getMFMSpeed(0); + drv->multi_revolution = 1; + drv->fourms = (drv->bridge->getBitSpeed() == 4); + drv->indexoffset = 0; + drv->prevtracklen = 0; + drv->forcedwrprot = false; + drv->wrprot = drv->bridge->isWriteProtected(); + drv->filetype = ADF_FLOPPYBRIDGE; + drv->useturbo = 0; + drv->mfmpos = uaerand(); + drv->mfmpos |= (uaerand() << 16); + drv->mfmpos %= drv->tracklen; + drv->prevtracklen = 0; + + drive_settype_id(drv); /* Set DD or HD drive */ + update_drive_gui(drv - floppy, false); + update_disk_statusline(drv - floppy); + drive_fill_bigbuf(drv, fake ? -1 : 1); + + return 1; +#endif #ifdef CAPS } else if (strncmp ((char*)buffer, "CAPS", 4) == 0) { @@ -1528,8 +1677,14 @@ static void set_steplimit (drive *drv) drv->steplimitcycle = get_cycles (); } -static int drive_empty (drive * drv) +static bool drive_empty (drive * drv) { +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + bool v = drv->bridge->isDiskInDrive(); + return v == false; + } +#endif #ifdef CATWEASEL if (drv->catweasel) return catweasel_disk_changed (drv->catweasel) == 0; @@ -1537,7 +1692,7 @@ static int drive_empty (drive * drv) return drv->diskfile == 0 && drv->dskchange_time >= 0; } -static void drive_step (drive * drv, int step_direction) +static void drive_step (drive *drv, int step_direction) { #ifdef CATWEASEL if (drv->catweasel) { @@ -1552,6 +1707,24 @@ static void drive_step (drive * drv, int step_direction) #endif if (!drive_empty (drv)) drv->dskchange = 0; + +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + int dir = step_direction ? -1 : 1; + drv->cyl += dir; + if (drv->cyl < 0) { + drv->cyl = 0; + drv->bridge->handleNoClickStep(side); + } else { + if (drv->cyl >= drv->bridge->getMaxCylinder()) { + drv->cyl = drv->bridge->getMaxCylinder() - 1; + } + drv->bridge->gotoCylinder(drv->cyl, side); + } + return; + } +#endif + if (drv->steplimit && get_cycles() - drv->steplimitcycle < MIN_STEPLIMIT_CYCLE) { write_log (_T(" step ignored drive %ld, %lu\n"), drv - floppy, (get_cycles() - drv->steplimitcycle) / CYCLE_UNIT); @@ -1595,8 +1768,14 @@ static void drive_step (drive * drv, int step_direction) write_log (_T(" ->step %d"), drv->cyl); } -static int drive_track0 (drive * drv) +static bool drive_track0 (drive * drv) { +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + bool v = drv->bridge->isAtCylinder0(); + return v; + } +#endif #ifdef CATWEASEL if (drv->catweasel) return catweasel_track0 (drv->catweasel); @@ -1604,8 +1783,47 @@ static int drive_track0 (drive * drv) return drv->cyl == 0; } -static int drive_running (drive * drv) +static bool drive_diskchange(drive *drv) +{ +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + bool v = drv->bridge->hasDiskChanged(); + return v; + } +#endif + return drv->dskchange; +} + +static bool drive_diskready(drive *drv) +{ +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + bool v = drv->bridge->isReady(); + return v; + } +#endif + return drv->dskready; +} + +static bool drive_at_index(drive *drv, int mfmBitPosition) +{ +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + bool v = drv->bridge->isMFMPositionAtIndex(mfmBitPosition); + return v; + } +#endif + return mfmBitPosition == drv->indexoffset; +} + +static bool drive_running (drive * drv) { +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + bool v = drv->bridge->isMotorRunning(); + return v; + } +#endif return !drv->motoroff; } @@ -1628,6 +1846,11 @@ static void drive_motor (drive * drv, bool off) } if (!drv->motoroff && off) { drv->drive_id_scnt = 0; /* Reset id shift reg counter */ +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + drive_settype_id(drv); // allow for dynamic DD/HD switching + } +#endif drv->dskready_down_time = DSKREADY_DOWN_TIME * 312 + (uaerand() & 511); #ifdef DRIVESOUND driveclick_motor (drv - floppy, 0); @@ -1649,6 +1872,11 @@ static void drive_motor (drive * drv, bool off) } else { drv->dskready_down_time = 0; } +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + drv->bridge->setMotorStatus(side, !drv->motoroff); + } +#endif #ifdef CATWEASEL if (drv->catweasel) catweasel_set_motor (drv->catweasel, !drv->motoroff); @@ -2004,7 +2232,7 @@ static void drive_fill_bigbuf (drive * drv, int force) bool retrytrack; int rev = -1; - if ((!drv->diskfile && !drv->catweasel) || tr >= drv->num_tracks) { + if ((!drv->diskfile && !drv->catweasel && !drv->bridge) || tr >= drv->num_tracks) { track_reset (drv); return; } @@ -2031,14 +2259,27 @@ static void drive_fill_bigbuf (drive * drv, int force) trackid *wti = &drv->writetrackdata[tr]; drv->tracklen = wti->bitlen; drv->revolutions = wti->revolutions; - read_floppy_data (drv->writediskfile, drv->filetype, wti, 0, (uae_u8*)drv->bigmfmbuf, NULL, (wti->bitlen + 7) / 8); + read_floppy_data(drv->writediskfile, drv->filetype, wti, 0, (uae_u8 *)drv->bigmfmbuf, NULL, (wti->bitlen + 7) / 8); for (i = 0; i < (drv->tracklen + 15) / 16; i++) { uae_u16 *mfm = drv->bigmfmbuf + i; - uae_u8 *data = (uae_u8 *) mfm; + uae_u8 *data = (uae_u8 *)mfm; *mfm = 256 * *data + *(data + 1); } if (disk_debug_logging > 0) - write_log (_T("track %d, length %d read from \"saveimage\"\n"), tr, drv->tracklen); + write_log(_T("track %d, length %d read from \"saveimage\"\n"), tr, drv->tracklen); +#ifdef FLOPPYBRIDGE + } else if (drv->filetype == ADF_FLOPPYBRIDGE) { + if (drv->bridge) { + drv->multi_revolution = 1; + drv->skipoffset = -1; + drv->bridge->setSurface(side); // 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) { + floppybridge_read_track(drv); + } + } +#endif } else if (drv->filetype == ADF_CATWEASEL) { #ifdef CATWEASEL drv->tracklen = 0; @@ -2576,6 +2817,14 @@ static void drive_write_data (drive * drv) if (ret < 0) write_log (_T("not a PC formatted track %d (error %d)\n"), drv->cyl * 2 + side, ret); break; +#ifdef FLOPPYBRIDGE + case ADF_FLOPPYBRIDGE: + if (drv->bridge) { + // Request to commit the buffer we have collected to disk - this should hardly ever be triggered + drv->tracklen = drv->bridge->commitWriteBuffer(side, drv->cyl); + } + break; +#endif } drv->tracktiming[0] = 0; } @@ -2752,11 +3001,11 @@ bool disk_creatediskfile (struct uae_prefs *p, const TCHAR *name, int type, driv return ok; } -int disk_getwriteprotect (struct uae_prefs *p, const TCHAR *name) +int disk_getwriteprotect (struct uae_prefs *p, const TCHAR *name, int num) { int needwritefile; drive_type drvtype; - return diskfile_iswriteprotect (p, name, &needwritefile, &drvtype); + return diskfile_iswriteprotect (p, name, num, &needwritefile, &drvtype); } static void diskfile_readonly (const TCHAR *name, bool readonly) @@ -2814,8 +3063,8 @@ int disk_setwriteprotect (struct uae_prefs *p, int num, const TCHAR *fname_in, b write_log(_T("disk_setwriteprotect %d '%s' %d\n"), num, fname_in, writeprotected); - oldprotect = diskfile_iswriteprotect (p, fname_in, &needwritefile, &drvtype); - DISK_validate_filename (p, fname_in, outfname, 1, &wrprot1, NULL, &zf1); + oldprotect = diskfile_iswriteprotect (p, fname_in, num, &needwritefile, &drvtype); + DISK_validate_filename (p, fname_in, num, outfname, 1, &wrprot1, NULL, &zf1); if (!zf1) return 0; @@ -2828,13 +3077,13 @@ int disk_setwriteprotect (struct uae_prefs *p, int num, const TCHAR *fname_in, b if (zfile_iscompressed (zf1)) wrprot1 = 1; zfile_fclose (zf1); - zf2 = getexistingwritefile(p, fname_in, &wrprot2); + zf2 = getexistingwritefile(p, fname_in, num, &wrprot2); name2 = DISK_get_saveimagepath(fname_in, -2); if (needwritefile && zf2 == NULL) disk_creatediskfile (p, name2, 1, drvtype, -1, NULL, false, false, NULL); zfile_fclose (zf2); - if (writeprotected && iswritefileempty (p, fname_in)) { + if (writeprotected && iswritefileempty(p, num, fname_in)) { for (i = 0; i < MAX_FLOPPY_DRIVES; i++) { if (!_tcscmp (fname_in, floppy[i].newname)) drive_eject (&floppy[i]); @@ -3158,6 +3407,11 @@ void DISK_select (uae_u8 data) if (!((selected | disabled) & (1 << dr)) && (prev_selected & (1 << dr)) ) { drv->drive_id_scnt++; drv->drive_id_scnt &= 31; +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + drive_settype_id(drv); // allow for dynamic DD/HD switching + } +#endif drv->idbit = (drv->drive_id & (1L << (31 - drv->drive_id_scnt))) ? 1 : 0; if (!(disabled & (1 << dr))) { if ((prev_data & 0x80) == 0 || (data & 0x80) == 0) { @@ -3226,7 +3480,7 @@ uae_u8 DISK_status_ciaa(void) for (int dr = 0; dr < 2; dr++) { drive *drv = floppy + dr; if (!(((selected >> 3) | disabled) & (1 << dr))) { - if (drv->dskchange) + if (drive_diskchange(drv)) st &= ~0x20; if (drive_track0 (drv)) st &= ~0x10; @@ -3251,17 +3505,17 @@ uae_u8 DISK_status_ciaa(void) st &= ~0x20; #endif } else { - if (drv->dskready && !drv->indexhack && currprefs.floppyslots[dr].dfxtype != DRV_35_DD_ESCOM) + if (drive_diskready(drv) && !drv->indexhack && (currprefs.floppyslots[dr].dfxtype != DRV_35_DD_ESCOM || drv->bridge)) st &= ~0x20; } } else { if (currprefs.cs_df0idhw || dr > 0) { /* report drive ID */ - if (drv->idbit && currprefs.floppyslots[dr].dfxtype != DRV_35_DD_ESCOM) + if (drv->idbit && (currprefs.floppyslots[dr].dfxtype != DRV_35_DD_ESCOM || (drv->bridge->getDriveTypeID() != FloppyDiskBridge::DriveTypeID::dti35DD))) st &= ~0x20; } else { /* non-ID internal drive: mirror real dskready */ - if (drv->dskready) + if (drive_diskready(drv)) st &= ~0x20; } /* dskrdy needs some cycles after switching the motor off.. (Pro Tennis Tour) */ @@ -3277,7 +3531,7 @@ uae_u8 DISK_status_ciaa(void) if (catweasel_disk_changed (drv->catweasel)) st &= ~4; #endif - } else if (drv->dskchange && currprefs.floppyslots[dr].dfxtype != DRV_525_SD) { + } else if (drive_diskchange(drv) && (currprefs.floppyslots[dr].dfxtype != DRV_525_SD || drv->bridge)) { st &= ~4; } } else if (!((selected | disabled) & (1 << dr))) { @@ -3291,6 +3545,12 @@ uae_u8 DISK_status_ciaa(void) static bool unformatted (drive *drv) { +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + bool v = drv->bridge->isDiskInDrive(); + return v == false; + } +#endif int tr = drv->cyl * 2 + side; if (tr >= drv->num_tracks) return true; @@ -3313,6 +3573,14 @@ static uae_u32 getonebit(drive *drv, uae_u16 *mfmbuf, int mfmpos, int *inc) if (inc) *inc = 1; + +#ifdef FLOPPYBRIDGE + if (drv && drv->bridge) { + drv->tracklen = drv->bridge->maxMFMBitPosition(); // this shouldnt happen + return drv->bridge->getMFMBit(mfmpos) ? 1 : 0; + } +#endif + if (inc && nextbit(drv) == 2) { // 2us -> 4us int b1 = getonebit(NULL, mfmbuf, mfmpos, NULL); @@ -3414,6 +3682,12 @@ static void fetchnextrevolution (drive *drv) fdi2raw_loadrevolution(drv->fdi, drv->bigmfmbuf, drv->tracktiming, drv->cyl * 2 + side, &drv->tracklen, 1); #endif break; +#ifdef FLOPPYBRIDGE + case ADF_FLOPPYBRIDGE: + drv->bridge->mfmSwitchBuffer(side); + drv->trackspeed = get_floppy_speed_from_image(drv); + break; +#endif } } @@ -3473,7 +3747,7 @@ static void disk_doupdate_write(int floppybits, int trackspeed) drive *drv2 = &floppy[dr]; drv2->mfmpos++; drv2->mfmpos %= drv2->tracklen; - if (drv2->mfmpos == drv2->indexoffset) { + if (drive_at_index(drv2, drv2->mfmpos)) { do_disk_index(); } } @@ -3491,6 +3765,9 @@ static void disk_doupdate_write(int floppybits, int trackspeed) } } if (disk_fifostatus () >= 0) { +#ifdef FLOPPYBRIDGE + bool wasBridge = false; +#endif uae_u16 w = DSKDATR (); for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) { drive *drv2 = &floppy[dr]; @@ -3498,6 +3775,12 @@ static void disk_doupdate_write(int floppybits, int trackspeed) drv2->bigmfmbuf[drv2->mfmpos >> 4] = w; drv2->bigmfmbuf[(drv2->mfmpos >> 4) + 1] = 0x5555; drv2->writtento = 1; +#ifdef FLOPPYBRIDGE + if (drv2->bridge) { + wasBridge = true; + drv2->bridge->writeShortToBuffer(side, drv2->cyl, w, drv2->mfmpos); + } +#endif } #ifdef AMAX if (amax_enabled) @@ -3506,7 +3789,10 @@ static void disk_doupdate_write(int floppybits, int trackspeed) } dsklength--; if (dsklength <= 0) { - disk_dmafinished (); + // delay write DMA finished state until bridge has all pending data written + if (!wasBridge) { + disk_dmafinished(); + } for (int dr = 0; dr < MAX_FLOPPY_DRIVES ; dr++) { drive *drv = &floppy[dr]; drv->writtento = 0; @@ -3519,6 +3805,26 @@ static void disk_doupdate_write(int floppybits, int trackspeed) } } } + +#ifdef FLOPPYBRIDGE + // Bridge pass check + if (dsklength <= 0) { + for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) { + drive *drv = &floppy[dr]; + if (drv->bridge && drives[dr]) { + drv->writtento = 0; + if (drv->motoroff) + continue; + if ((selected | disabled) & (1 << dr)) + continue; + // With bridge we wait for the disk to commit the data before fireing the DMA + if (drv->bridge->isWriteComplete()) { + disk_dmafinished(); + } + } + } + } +#endif } floppybits -= trackspeed; } @@ -3535,6 +3841,12 @@ static void update_jitter (void) static void updatetrackspeed (drive *drv, int mfmpos) { if (dskdmaen < DSKDMA_WRITE) { +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + drv->trackspeed = NORMAL_FLOPPY_SPEED * drv->bridge->getMFMSpeed(mfmpos) / 1000; + return; + } +#endif int t = drv->tracktiming[mfmpos / 8]; int ts = get_floppy_speed_from_image(drv) * t / 1000; if (ts < 700 || ts > 3000) { @@ -3590,7 +3902,7 @@ static void disk_doupdate_predict (int startcycle) if (!dskdmaen) { if (mfmpos == 0) diskevent_flag |= DISK_REVOLUTION << (drv - floppy); - if (mfmpos == drv->indexoffset) + if (drive_at_index(drv, mfmpos)) diskevent_flag |= DISK_INDEXSYNC; } if (dskdmaen != DSKDMA_WRITE && mfmpos == drv->skipoffset) { @@ -3601,7 +3913,7 @@ static void disk_doupdate_predict (int startcycle) if (!dskdmaen) { if (mfmpos == 0) diskevent_flag |= DISK_REVOLUTION << (drv - floppy); - if (mfmpos == drv->indexoffset) + if (drive_at_index(drv, mfmpos)) diskevent_flag |= DISK_INDEXSYNC; } } @@ -3798,7 +4110,7 @@ static void disk_doupdate_read (drive * drv, int floppybits) } drv->mfmpos += inc; drv->mfmpos %= drv->tracklen; - if (drv->mfmpos == drv->indexoffset) { + if (drive_at_index(drv, drv->mfmpos)) { if (disk_debug_logging > 2 && drv->indexhack) write_log (_T("indexhack cleared\n")); drv->indexhack = 0; @@ -3814,7 +4126,7 @@ static void disk_doupdate_read (drive * drv, int floppybits) while (skipcnt-- > 0) { drv->mfmpos += nextbit(drv); drv->mfmpos %= drv->tracklen; - if (drv->mfmpos == drv->indexoffset) { + if (drive_at_index(drv, drv->mfmpos)) { if (disk_debug_logging > 2 && drv->indexhack) write_log (_T("indexhack cleared\n")); drv->indexhack = 0; @@ -3954,10 +4266,18 @@ static void DISK_start (void) bitoffset = 0; word = 0; } +#ifdef CATWEASEL if (drv->catweasel) { word = 0; drive_fill_bigbuf (drv, 1); } +#endif +#ifdef FLOPPYBRIDGE + if (drv->bridge && dskdmaen != DSKDMA_WRITE) { + word = 0; + drive_fill_bigbuf(drv, 1); + } +#endif } drv->floppybitcounter = 0; } @@ -4057,6 +4377,11 @@ void DISK_update (int tohpos) if (drv->diskfile) { drive_fill_bigbuf(drv, 0); } +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + drive_fill_bigbuf(drv, 0); + } +#endif drv->mfmpos %= drv->tracklen; } int didaccess = 0; @@ -4235,6 +4560,15 @@ void DSKLEN (uae_u16 v, int hpos) drive *drv = &floppy[dr]; if (selected & (1 << dr)) continue; +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + if (dskdmaen == DSKDMA_WRITE) { + // In write mode we allow a special version of 'turbo' to happen. We only complete the DMA response when we have actually written to disk + if (drv->bridge->canTurboWrite()) continue; + } + break; + } +#endif if (drv->filetype != ADF_NORMAL && drv->filetype != ADF_KICK && drv->filetype != ADF_SKICK && drv->filetype != ADF_NORMAL_HEADER) break; } @@ -4244,12 +4578,12 @@ void DSKLEN (uae_u16 v, int hpos) int done = 0; for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) { drive *drv = &floppy[dr]; - bool floppysupported = (drv->ddhd < 2) || (drv->ddhd > 1 && currprefs.floppyslots[dr].dfxtype == DRV_35_HD); + bool floppysupported = (drv->ddhd < 2) || (drv->ddhd > 1 && currprefs.floppyslots[dr].dfxtype == DRV_35_HD) || (drv->bridge); int pos, i; if (drv->motoroff) continue; - if (!drv->useturbo && currprefs.floppy_speed > 0) + if (!drv->useturbo && currprefs.floppy_speed > 0 && !drv->bridge) continue; if (selected & (1 << dr)) continue; @@ -4292,6 +4626,26 @@ void DSKLEN (uae_u16 v, int hpos) } else if (dskdmaen == DSKDMA_WRITE) { /* TURBO write */ +#ifdef FLOPPYBRIDGE + if (drv->bridge) { + if (!drv->bridge->isWritePending()) { + for (i = 0; i < dsklength; i++) { + uae_u16 w = chipmem_wget_indirect(dskpt + i * 2); + drv->bigmfmbuf[pos >> 4] = w; + drv->bridge->writeShortToBuffer(side, drv->cyl, w, drv->mfmpos); + pos += 16; + pos %= drv->tracklen; + } + drv->mfmpos = pos; + if (drv->bridge->isReadyToWrite()) { + drv->bridge->commitWriteBuffer(side, drv->cyl); + } + } else + if (drv->bridge->isWriteComplete()) { + done = 2; + } + } else +#endif if (floppysupported) { for (i = 0; i < dsklength; i++) { uae_u16 w = chipmem_wget_indirect (dskpt + i * 2); @@ -4449,6 +4803,178 @@ void DISK_free (void) } } +static void floppybridge_read_track(drive *drv) +{ + int timeout; + FloppyDiskBridge *b = drv->bridge; + if (!b) { + return; + } + for (;;) { + if (!b->isDiskInDrive()) { + break; + } + b->setMotorStatus(false, true); + b->gotoCylinder(drv->cyl, false); + timeout = 5000 / 10; + while (b->getCurrentCylinderNumber() != drv->cyl) { + if (timeout-- < 0) { + break; + } + sleep_millis(10); + } + while (!b->isReady()) { + if (timeout-- < 0) { + break; + } + sleep_millis(10); + } + + if (!b->isDiskInDrive() || timeout < 0) { + break; + } + int totalbits = FLOPPY_WRITE_LEN_NTSC * 8 * drv->ddhd; + int pos = 0; + uae_u16 *p = drv->bigmfmbuf; + uae_u16 w = 0; + timeout = 5000 / 10; + int max = b->maxMFMBitPosition(); + while (totalbits > 0 && timeout > 0) { + while (b->isMFMDataAvailable() && totalbits > 0) { + uae_u8 bit = b->getMFMBit(pos); + pos++; + if (pos >= max) { + pos = 0; + } + w <<= 1; + w |= bit; + if ((pos & 15) == 0) { + *p++ = w; + } + totalbits--; + } + sleep_millis(10); + timeout--; + } + break; + } + b->setMotorStatus(false, side); +} + +static void floppybridge_init3(void) +{ + static bool checked; + if (checked) { + return; + } + checked = true; + if (FloppyBridgeAPI::isAvailable()) { + floppybridge_available = true; + FloppyBridgeAPI::getDriverList(bridgedriverinfo); + } +} + +bool floppybridge_has(void) +{ + floppybridge_init3(); + return floppybridge_available; +} + +static void floppybridge_init2(struct uae_prefs *p) +{ + bool needbridge = false; + for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) { + int type = p->floppyslots[i].dfxtype; + if (type == DRV_FB_A_35_DD || type == DRV_FB_A_35_HD || type == DRV_FB_B_35_DD || type == DRV_FB_B_35_HD) { + needbridge = true; + } + } + if (!needbridge) { + for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) { + floppy[dr].bridge = NULL; + if (bridges[dr]) { + delete bridges[dr]; + bridges[dr] = NULL; + } + } + return; + } + floppybridge_init3(); + for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) { + int type = p->floppyslots[dr].dfxtype; + if (type == DRV_FB_A_35_DD || type == DRV_FB_A_35_HD || type == DRV_FB_B_35_DD || type == DRV_FB_B_35_HD) { + if (floppy[dr].bridge == NULL || type != bridge_type[dr]) { + if (bridges[dr]) { + bridges[dr]->shutdown(); + delete bridges[dr]; + bridges[dr] = NULL; + } + floppy[dr].bridge = NULL; + bridge_driver[dr] = NULL; + bridge_type[dr] = type; + FloppyBridgeAPI *bridge = NULL; + bool configConfigured = true; + if (p->floppyslots[dr].config[0]) { + char *c = ua(p->floppyslots[dr].config); + bridge = FloppyBridgeAPI::createDriverFromString(c); + xfree(c); + } + if (!bridge) { + configConfigured = false; + bridge = FloppyBridgeAPI::createDriver(1); + p->floppyslots[dr].config[0] = 0; + changed_prefs.floppyslots[dr].config[0] = 0; + } + if (bridge) { + bridge->setBridgeDensityMode(FloppyBridgeAPI::BridgeDensityMode::bdmAuto); + if (p->floppy_speed == 0) { + bridge->setBridgeMode(FloppyBridgeAPI::BridgeMode::bmTurboAmigaDOS); + } else { + bridge->setBridgeMode(FloppyBridgeAPI::BridgeMode::bmFast); + } + if (!configConfigured) { + bridge->setComPortAutoDetect(true); + bridge->setDriveCableSelection(type == DRV_FB_A_35_DD || type == DRV_FB_A_35_HD); // on A + } + if (!bridge->initialise()) { + const char *errorMessage = bridge->getLastErrorMessage(); + const char *name = bridge->getDriverInfo()->name; + TCHAR *terrorMessage = au(errorMessage); + TCHAR *tname = au(name); + TCHAR formattedMessage[512]; + _stprintf(formattedMessage, _T("Floppy Disk Bridge Error\n\nUnable to replace DF%i: using %s\n\n%s.\n\nDrive DF%i: will be disabled and ignored."), dr, tname, terrorMessage, dr); + gui_message(formattedMessage); + xfree(tname); + xfree(terrorMessage); + } else { + char *config = NULL; + bridge->getConfigAsString(&config); + au_copy(p->floppyslots[dr].config, sizeof(p->floppyslots[dr].config) / sizeof(TCHAR), config); + _tcscpy(changed_prefs.floppyslots[dr].config, p->floppyslots[dr].config); + bridge_driver[dr] = bridge->getDriverInfo(); + } + } + bridges[dr] = bridge; + floppy[dr].bridge = bridge; + } + } else { + if (bridges[dr]) { + bridges[dr]->shutdown(); + delete bridges[dr]; + bridges[dr] = NULL; + } + floppy[dr].bridge = NULL; + bridge_driver[dr] = NULL; + } + + } +} + +void floppybridge_init(struct uae_prefs *p) +{ + floppybridge_init2(p); +} + void DISK_init (void) { for (int dr = MAX_FLOPPY_DRIVES - 1; dr >= 0; dr--) { @@ -4458,6 +4984,7 @@ void DISK_init (void) if (!drive_insert (drv, &currprefs, dr, currprefs.floppyslots[dr].df, false, currprefs.floppyslots[dr].forcedwriteprotect)) disk_eject (dr); } + floppybridge_init2(&currprefs); if (disk_empty (0)) write_log (_T("No disk in drive 0.\n")); amax_init (); @@ -4491,7 +5018,7 @@ static void load_track (int num, int cyl, int side, int *sectable) drv->cyl = cyl; side = 0; drv->buffered_cyl = -1; - drive_fill_bigbuf (drv, 1); + drive_fill_bigbuf (drv, -1); decode_buffer (drv->bigmfmbuf, drv->cyl, 11, drv->ddhd, drv->filetype, &drvsec, sectable, 1); drv->cyl = oldcyl; side = oldside; @@ -4632,7 +5159,37 @@ static void abrcheck(struct diskinfo *di) } } -int DISK_examine_image (struct uae_prefs *p, int num, struct diskinfo *di, bool deepcheck) +static void get_floppybridgeinfo(TCHAR *infotext, int num) +{ + if (!infotext) { + return; + } + TCHAR *p = infotext; + _tcscat(p, bridgeinfo.about); + p += _tcslen(p); + if (bridgeinfo.isUpdateAvailable) { + _stprintf(p, _T(" v%u.%u (v%u.%u) "), bridgeinfo.majorVersion, bridgeinfo.minorVersion, bridgeinfo.updateMajorVersion, bridgeinfo.updateMinorVersion); + } else { + _stprintf(p, _T(" v%u.%u "), bridgeinfo.majorVersion, bridgeinfo.minorVersion); + } + p += _tcslen(p); + _stprintf(p, _T("(%s)"), bridgeinfo.url); + _tcscat(p, _T("\r\n\r\n")); + p += _tcslen(p); + if (bridge_driver[num]) { + const FloppyDiskBridge::BridgeDriver *bd = bridge_driver[num]; + TCHAR *name = au(bd->name); + TCHAR *man = au(bd->manufacturer); + TCHAR *url = au(bd->url); + _stprintf(p, _T("%s, %s (%s)\r\n"), name, man, url); + xfree(url); + xfree(man); + xfree(name); + p += _tcslen(p); + } +} + +int DISK_examine_image(struct uae_prefs *p, int num, struct diskinfo *di, bool deepcheck, TCHAR *infotext) { int drvsec; int ret, i; @@ -4642,27 +5199,38 @@ int DISK_examine_image (struct uae_prefs *p, int num, struct diskinfo *di, bool int sectable[MAX_SECTORS]; int oldcyl, oldside; uae_u32 v = 0; + bool fb = DISK_isfloppybridge(p, num); + if (infotext) { + infotext[0] = 0; + } ret = 0; memset (di, 0, sizeof (struct diskinfo)); + + if (fb) { + get_floppybridgeinfo(infotext, num); + } + di->unreadable = true; oldcyl = drv->cyl; oldside = side; - drv->cyl = 0; - side = 0; - if (!drive_insert (drv, p, num, p->floppyslots[num].df, true, true) || !drv->diskfile) { + if (!drive_insert (drv, p, num, p->floppyslots[num].df, true, true) || (!drv->diskfile && !drv->bridge)) { drv->cyl = oldcyl; side = oldside; return 1; } - di->imagecrc32 = zfile_crc32 (drv->diskfile); + if (drv->diskfile) { + di->imagecrc32 = zfile_crc32(drv->diskfile); + di->image_crc_value = true; + } di->unreadable = false; - decode_buffer (drv->bigmfmbuf, drv->cyl, 11, drv->ddhd, drv->filetype, &drvsec, sectable, 1); + decode_buffer(drv->bigmfmbuf, drv->cyl, 11, drv->ddhd, drv->filetype, &drvsec, sectable, 1); di->hd = drv->ddhd == 2; drv->cyl = oldcyl; side = oldside; if (sectable[0] == 0 || sectable[1] == 0) { ret = 2; + di->unreadable = true; goto end2; } crc = crc2 = 0; @@ -4713,7 +5281,7 @@ int DISK_examine_image (struct uae_prefs *p, int num, struct diskinfo *di, bool di->bootblocktype = 2; } end: - load_track (num, 40, 0, sectable); + load_track(num, 40, 0, sectable); if (sectable[0]) { if (!disk_checksum (writebuffer, NULL) && writebuffer[0] == 0 && writebuffer[1] == 0 && writebuffer[2] == 0 && writebuffer[3] == 2 && @@ -4734,6 +5302,7 @@ end2: drv->dskchange_time = wasdelayed; disk_insert (num, drv->newname); } + load_track(num, oldcyl, oldside, sectable); return ret; } @@ -4927,9 +5496,9 @@ uae_u8 *save_disk (int num, int *len, uae_u8 *dstptr, bool usepath) else dstbak = dst = xmalloc (uae_u8, 2 + 1 + 1 + 1 + 1 + 4 + 4 + MAX_DPATH + 2 + 2 + 4 + 2 * MAX_DPATH); save_u32 (drv->drive_id); /* drive type ID */ - save_u8 ((drv->motoroff ? 0 : 1) | ((disabled & (1 << num)) ? 2 : 0) | (drv->idbit ? 4 : 0) | (drv->dskchange ? 8 : 0) | (side ? 16 : 0) | (drv->wrprot ? 32 : 0)); + save_u8 ((drv->motoroff ? 0 : 1) | ((disabled & (1 << num)) ? 2 : 0) | (drv->idbit ? 4 : 0) | (drive_diskchange(drv) ? 8 : 0) | (side ? 16 : 0) | (drv->wrprot ? 32 : 0)); save_u8 (drv->cyl); /* cylinder */ - save_u8 (drv->dskready); /* dskready */ + save_u8 (drive_diskready(drv)); /* dskready */ save_u8 (drv->drive_id_scnt); /* id mode position */ save_u32 (drv->mfmpos); /* disk position */ save_u32 (getadfcrc (drv)); /* CRC of disk image */ @@ -5277,7 +5846,7 @@ bool disk_reserved_getinfo(int num, struct floppy_reserved *fr) fr->drive_cyls = currprefs.floppyslots[idx].dfxtype == DRV_PC_525_ONLY_40 ? 40 : 80; fr->secs = drv->num_secs; fr->heads = drv->num_heads; - fr->disk_changed = drv->dskchange || fr->img == NULL; + fr->disk_changed = drive_diskchange(drv) || fr->img == NULL; if (currprefs.floppyslots[idx].dfxtype == DRV_PC_35_ONLY_80) { if (drv->num_secs > 14) fr->rate = FLOPPY_RATE_500K; // 1.2M/1.4M diff --git a/floppybridge/floppybridge_abstract.h b/floppybridge/floppybridge_abstract.h new file mode 100644 index 00000000..4723e5e3 --- /dev/null +++ b/floppybridge/floppybridge_abstract.h @@ -0,0 +1,182 @@ +/* floppybridge_abstract +* +* Copyright (C) 2021 Robert Smith (@RobSmithDev) +* https://amiga.robsmithdev.co.uk +* +* This library defines a standard interface for connecting physical disk drives to *UAE +* +* Derived classes must be implemented so they are unlikely to cause a delay in any function +* as doing so would cause audio and mouse cursors to stutter +* +* This is free and unencumbered released into the public domain. +* See the file COPYING for more details, or visit . +* +*/ + +/* +* This file, along with currently active and supported interfaces +* are maintained from by GitHub repo at +* https://github.com/RobSmithDev/FloppyDriveBridge +*/ + +#pragma once + +#include + +#ifdef _WIN32 +#include +#else +#ifndef TCHAR +#ifdef _UNICODE +#define TCHAR wchar_t +#define _T(x) L ##x +#else +#define TCHAR char +#define _T(x) x +#endif +#endif +#endif + + + +class FloppyDiskBridge { +public: + + // Driver information + struct BridgeDriver { + // Details about the driver + const char* name; + const char* url; + const char* manufacturer; + const char* driverAuthor; + + // Which options in configuration it can support, aside from the standard ones + const unsigned int configOptions; + }; + + // Definition of the type of drive + enum class DriveTypeID : unsigned char { dti35DD = 0, dti35HD = 1, dti5255SD = 2 }; + + FloppyDiskBridge() {}; + // This is just to force this being virtual + virtual ~FloppyDiskBridge() {}; + + // Call to start the system up. Return false if it fails + virtual bool initialise() = 0; + + // This is called prior to closing down, but shoudl reverse initialise + virtual void shutdown() {}; + + // Returns the name of interface. This pointer should remain valid *after* the class is destroyed so should be static + virtual const BridgeDriver* getDriverInfo() = 0; + + // Return the 'bit cell' time in uSec. Standard DD Amiga disks this would be 2uS, HD disks would be 1us I guess, but mainly used for =4 for SD I think + virtual unsigned char getBitSpeed() { return 2; }; + + // Return the type of disk connected. This is used to tell WinUAE if we're DD or HD. This must return INSTANTLY + virtual DriveTypeID getDriveTypeID() = 0; + + // Call to get the last error message. If the board initialised this may return a compatability warning instead + virtual const char* getLastErrorMessage() { return NULL; }; + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + + // Reset the drive. This should reset it to the state it would be at powerup, ie: motor switched off etc. The current cylinder number can be 'unknown' at this point + virtual bool resetDrive(int trackNumber) = 0; + + + + + /////////////////////// Head movement Controls ////////////////////////////////////////// + // Return TRUE if the drive is currently on cylinder 0 + virtual bool isAtCylinder0() = 0; + + // Return the number of cylinders the drive supports. Eg: 80 or 82 (or 40) + virtual unsigned char getMaxCylinder() = 0; + + // Seek to a specific cylinder + virtual void gotoCylinder(int cylinderNumber, bool side) = 0; + + // Handle the drive stepping to track -1 - this is used to 'no-click' detect the disk + virtual void handleNoClickStep(bool side) = 0; + + // Return the current cylinder number we're on + virtual unsigned char getCurrentCylinderNumber() = 0; + + + + /////////////////////// Drive Motor Controls ///////////////////////////////////////////// + // Return true if the motor is spinning, but not necessarly up to speed + virtual bool isMotorRunning() = 0; + + // Turn on and off the motor + virtual void setMotorStatus(bool turnOn, bool side) = 0; + + // Returns TRUE if the drive is ready (ie: the motor has spun up to speed to speed) + virtual bool isReady() = 0; + + + + /////////////////////// Disk Detection /////////////////////////////////////////////////// + // Return TRUE if there is a disk in the drive. This is usually called after gotoCylinder + virtual bool isDiskInDrive() = 0; + + // Check if the disk has changed. Basically returns FALSE if theres no disk in the drive + virtual bool hasDiskChanged() = 0; + + + + /////////////////////// Reading Data ///////////////////////////////////////////////////// + // Return TRUE if we're at the INDEX marker/sensor. mfmPositionBits is in BITS + virtual bool isMFMPositionAtIndex(int mfmPositionBits) = 0; + + // Returns TRUE if data is ready and available + virtual bool isMFMDataAvailable() = 0; + + // This returns a single MFM bit at the position provided + virtual bool getMFMBit(const int mfmPositionBits) = 0; + + // This asks the time taken to read the bit at mfmPositionBits. 1000=100%, <1000 data is read faster, >1000 data is read slower. + // This number is used in a loop (scaled) starting with a number, and decrementing by this number. + // Each loop a single bit is read. So the smaller the number, the more loops that occur, and the more bits that are read + virtual int getMFMSpeed(const int mfmPositionBits) = 0; + + // This is called in both modes. It is called when WinUAE detects a full revolution of data has been read. This could allow you to switch to a different recording of the same cylinder if needed. + virtual void mfmSwitchBuffer(bool side) = 0; + + // Quick confirmation from UAE that we're actually on the same side + virtual void setSurface(bool side) = 0; + + // Return the maximum size of bits available in this revolution. This is the maximimum passed to getMFMBit + virtual int maxMFMBitPosition() = 0; + + /////////////////////// Writing Data ///////////////////////////////////////////////////// + + // Submits a single WORD of data received during a DMA transfer to the disk buffer. This needs to be saved. It is usually flushed when commitWriteBuffer is called + // You should reset this buffer if side or track changes, mfmPosition is provided purely for any index sync you may wish to do + virtual void writeShortToBuffer(bool side, unsigned int track, unsigned short mfmData, int mfmPosition) = 0; + + // Return TRUE if the currently insrted disk is write protected + virtual bool isWriteProtected() = 0; + + // Requests that any data received via writeShortToBuffer be saved to disk. The side and track should match against what you have been collected + // and the buffer should be reset upon completion. You should return the new tracklength (maxMFMBitPosition) with optional padding if needed + virtual unsigned int commitWriteBuffer(bool side, unsigned int track) = 0; + + // Returns TRUE if commitWriteBuffer has been called but not written to disk yet + virtual bool isWritePending() = 0; + + // Returns TRUE if a write is no longer pending. This should only return TRUE the first time, and then should reset + virtual bool isWriteComplete() = 0; + + // Set to TRUE if turbo writing is allowed (this is a sneaky DMA bypass trick) + virtual bool canTurboWrite() = 0; + + // Return TRUE if there is data ready to be committed to disk + virtual bool isReadyToWrite() = 0; +}; + + diff --git a/floppybridge/floppybridge_lib.cpp b/floppybridge/floppybridge_lib.cpp new file mode 100644 index 00000000..47716612 --- /dev/null +++ b/floppybridge/floppybridge_lib.cpp @@ -0,0 +1,629 @@ +/* floppybridge_lib +* +* Copyright (C) 2021 Robert Smith (@RobSmithDev) +* https://amiga.robsmithdev.co.uk +* +* This class connects to the external FloppyBridge DLL library rather than +* having all the code compiled in. That library is maintained at +* https://amiga.robsmithdev.co.uk/winuae +* +* This is free and unencumbered released into the public domain +* But please don't remove the above information +* +* For more details visit . +* +*/ + +#include "floppybridge_lib.h" +#include +#include +#include +#include + + +// Used by BRIDGE_About +struct BridgeAbout { + const char* about; + const char* url; + unsigned int majorVersion, minorVersion; + unsigned int isBeta; + unsigned int isUpdateAvailable; + unsigned int updateMajorVersion, updateMinorVersion; +}; + +#ifdef _WIN32 +#include +#define CALLING_CONVENSION _cdecl +#define GETFUNC GetProcAddress +HMODULE WIN32_LoadLibrary(const TCHAR *name); +#else +#define CALLING_CONVENSION +#define GETFUNC dlsym +#endif + +#ifdef WIN64 +#define MODULENAME _T("FloppyBridge_x64.dll") +#else +#ifdef _WIN32 +#define MODULENAME _T("FloppyBridge.dll") +#else +#define MODULENAME "FloppyBridge.so" +#endif +#endif + +#ifdef _WIN32 +HMODULE hBridgeDLLHandle = 0; +#else +void* hBridgeDLLHandle = nullptr; +#endif + + + +// Bridge library function definitions +typedef void (CALLING_CONVENSION* _BRIDGE_About)(BridgeAbout** output); +typedef unsigned int (CALLING_CONVENSION* _BRIDGE_NumDrivers)(void); +typedef bool (CALLING_CONVENSION* _BRIDGE_GetDriverInfo)(unsigned int driverIndex, FloppyDiskBridge::BridgeDriver** driverInformation); + +typedef bool (CALLING_CONVENSION* _BRIDGE_EnumComports)(char* output, unsigned int* bufferSize); + +typedef bool (CALLING_CONVENSION* _BRIDGE_CreateDriver)(unsigned int driverIndex, BridgeDriverHandle* bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _BRIDGE_CreateDriverFromConfigString)(char* config, BridgeDriverHandle* bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _BRIDGE_Close)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _BRIDGE_Open)(BridgeDriverHandle bridgeDriverHandle, char** errorMessage); +typedef bool (CALLING_CONVENSION* _BRIDGE_GetDriverIndex)(BridgeDriverHandle bridgeDriverHandle, unsigned int* driverIndex); +typedef bool (CALLING_CONVENSION* _BRIDGE_FreeDriver)(BridgeDriverHandle bridgeDriverHandle); + +typedef bool (CALLING_CONVENSION* _BRIDGE_GetConfigString)(BridgeDriverHandle bridgeDriverHandle, char** config); +typedef bool (CALLING_CONVENSION* _BRIDGE_SetConfigFromString)(BridgeDriverHandle bridgeDriverHandle, char* config); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverGetAutoCache)(BridgeDriverHandle bridgeDriverHandle, bool* isAutoCacheMode); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverSetAutoCache)(BridgeDriverHandle bridgeDriverHandle, bool isAutoCacheMode); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverGetMode)(BridgeDriverHandle bridgeDriverHandle, FloppyBridgeAPI::BridgeMode* bridgeMode); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverSetMode)(BridgeDriverHandle bridgeDriverHandle, FloppyBridgeAPI::BridgeMode bridgeMode); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverGetDensityMode)(BridgeDriverHandle bridgeDriverHandle, FloppyBridgeAPI::BridgeDensityMode* densityMode); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverSetDensityMode)(BridgeDriverHandle bridgeDriverHandle, FloppyBridgeAPI::BridgeDensityMode densityMode); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverGetCurrentComPort)(BridgeDriverHandle bridgeDriverHandle, char** comPort); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverSetCurrentComPort)(BridgeDriverHandle bridgeDriverHandle, char* comPort); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverGetAutoDetectComPort)(BridgeDriverHandle bridgeDriverHandle, bool* autoDetectComPort); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverSetAutoDetectComPort)(BridgeDriverHandle bridgeDriverHandle, bool autoDetectComPort); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverGetCable)(BridgeDriverHandle bridgeDriverHandle, bool* isOnB); +typedef bool (CALLING_CONVENSION* _BRIDGE_DriverSetCable)(BridgeDriverHandle bridgeDriverHandle, bool isOnB); +typedef unsigned char (CALLING_CONVENSION* _DRIVER_getBitSpeed)(BridgeDriverHandle bridgeDriverHandle); +typedef FloppyDiskBridge::DriveTypeID (CALLING_CONVENSION* _DRIVER_getDriveTypeID)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _DRIVER_resetDrive)(BridgeDriverHandle bridgeDriverHandle, int trackNumber); +typedef bool (CALLING_CONVENSION* _DRIVER_isAtCylinder0)(BridgeDriverHandle bridgeDriverHandle); +typedef unsigned char (CALLING_CONVENSION* _DRIVER_getMaxCylinder)(BridgeDriverHandle bridgeDriverHandle); +typedef void (CALLING_CONVENSION* _DRIVER_gotoCylinder)(BridgeDriverHandle bridgeDriverHandle, int cylinderNumber, bool side); +typedef void (CALLING_CONVENSION* _DRIVER_handleNoClickStep)(BridgeDriverHandle bridgeDriverHandle, bool side); +typedef unsigned char (CALLING_CONVENSION* _DRIVER_getCurrentCylinderNumber)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _DRIVER_isMotorRunning)(BridgeDriverHandle bridgeDriverHandle); +typedef void (CALLING_CONVENSION* _DRIVER_setMotorStatus)(BridgeDriverHandle bridgeDriverHandle, bool turnOn, bool side); +typedef bool (CALLING_CONVENSION* _DRIVER_isReady)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _DRIVER_isDiskInDrive)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _DRIVER_hasDiskChanged)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _DRIVER_isMFMPositionAtIndex)(BridgeDriverHandle bridgeDriverHandle, int mfmPositionBits); +typedef bool (CALLING_CONVENSION* _DRIVER_isMFMDataAvailable)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _DRIVER_getMFMBit)(BridgeDriverHandle bridgeDriverHandle, const int mfmPositionBits); +typedef int (CALLING_CONVENSION* _DRIVER_getMFMSpeed)(BridgeDriverHandle bridgeDriverHandle, const int mfmPositionBits); +typedef void (CALLING_CONVENSION* _DRIVER_mfmSwitchBuffer)(BridgeDriverHandle bridgeDriverHandle, bool side); +typedef void (CALLING_CONVENSION* _DRIVER_setSurface)(BridgeDriverHandle bridgeDriverHandle, bool side); +typedef int (CALLING_CONVENSION* _DRIVER_maxMFMBitPosition)(BridgeDriverHandle bridgeDriverHandle); +typedef void (CALLING_CONVENSION* _DRIVER_writeShortToBuffer)(BridgeDriverHandle bridgeDriverHandle, bool side, unsigned int track, unsigned short mfmData, int mfmPosition); +typedef bool (CALLING_CONVENSION* _DRIVER_isWriteProtected)(BridgeDriverHandle bridgeDriverHandle); +typedef unsigned int (CALLING_CONVENSION* _DRIVER_commitWriteBuffer)(BridgeDriverHandle bridgeDriverHandle, bool side, unsigned int track); +typedef bool (CALLING_CONVENSION* _DRIVER_isWritePending)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _DRIVER_isWriteComplete)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _DRIVER_canTurboWrite)(BridgeDriverHandle bridgeDriverHandle); +typedef bool (CALLING_CONVENSION* _DRIVER_isReadyToWrite)(BridgeDriverHandle bridgeDriverHandle); + + +// Library function pointers +_BRIDGE_About BRIDGE_About = nullptr; +_BRIDGE_NumDrivers BRIDGE_NumDrivers = nullptr; +_BRIDGE_EnumComports BRIDGE_EnumComports = nullptr; +_BRIDGE_GetDriverInfo BRIDGE_GetDriverInfo = nullptr; +_BRIDGE_CreateDriver BRIDGE_CreateDriver = nullptr; +_BRIDGE_Close BRIDGE_Close = nullptr; +_BRIDGE_Open BRIDGE_Open = nullptr; +_BRIDGE_GetDriverIndex BRIDGE_GetDriverIndex = nullptr; +_BRIDGE_FreeDriver BRIDGE_FreeDriver = nullptr; +_BRIDGE_DriverGetMode BRIDGE_DriverGetMode = nullptr; +_BRIDGE_DriverSetMode BRIDGE_DriverSetMode = nullptr; +_BRIDGE_DriverGetDensityMode BRIDGE_DriverGetDensityMode = nullptr; +_BRIDGE_DriverSetDensityMode BRIDGE_DriverSetDensityMode = nullptr; +_BRIDGE_DriverGetCurrentComPort BRIDGE_DriverGetCurrentComPort = nullptr; +_BRIDGE_DriverSetCurrentComPort BRIDGE_DriverSetCurrentComPort = nullptr; +_BRIDGE_DriverGetAutoDetectComPort BRIDGE_DriverGetAutoDetectComPort = nullptr; +_BRIDGE_DriverSetAutoDetectComPort BRIDGE_DriverSetAutoDetectComPort = nullptr; +_BRIDGE_DriverGetCable BRIDGE_DriverGetCable = nullptr; +_BRIDGE_DriverSetCable BRIDGE_DriverSetCable = nullptr; +_BRIDGE_DriverGetAutoCache BRIDGE_DriverGetAutoCache = nullptr; +_BRIDGE_DriverSetAutoCache BRIDGE_DriverSetAutoCache = nullptr; +_BRIDGE_GetConfigString BRIDGE_GetConfigString = nullptr; +_BRIDGE_SetConfigFromString BRIDGE_SetConfigFromString = nullptr; +_BRIDGE_CreateDriverFromConfigString BRIDGE_CreateDriverFromConfigString = nullptr; +_DRIVER_getBitSpeed DRIVER_getBitSpeed = nullptr; +_DRIVER_getDriveTypeID DRIVER_getDriveTypeID = nullptr; +_DRIVER_resetDrive DRIVER_resetDrive = nullptr; +_DRIVER_isAtCylinder0 DRIVER_isAtCylinder0 = nullptr; +_DRIVER_getMaxCylinder DRIVER_getMaxCylinder = nullptr; +_DRIVER_gotoCylinder DRIVER_gotoCylinder = nullptr; +_DRIVER_handleNoClickStep DRIVER_handleNoClickStep = nullptr; +_DRIVER_getCurrentCylinderNumber DRIVER_getCurrentCylinderNumber = nullptr; +_DRIVER_isMotorRunning DRIVER_isMotorRunning = nullptr; +_DRIVER_setMotorStatus DRIVER_setMotorStatus = nullptr; +_DRIVER_isReady DRIVER_isReady = nullptr; +_DRIVER_isDiskInDrive DRIVER_isDiskInDrive = nullptr; +_DRIVER_hasDiskChanged DRIVER_hasDiskChanged = nullptr; +_DRIVER_isMFMPositionAtIndex DRIVER_isMFMPositionAtIndex = nullptr; +_DRIVER_isMFMDataAvailable DRIVER_isMFMDataAvailable = nullptr; +_DRIVER_getMFMBit DRIVER_getMFMBit = nullptr; +_DRIVER_getMFMSpeed DRIVER_getMFMSpeed = nullptr; +_DRIVER_mfmSwitchBuffer DRIVER_mfmSwitchBuffer = nullptr; +_DRIVER_setSurface DRIVER_setSurface = nullptr; +_DRIVER_maxMFMBitPosition DRIVER_maxMFMBitPosition = nullptr; +_DRIVER_writeShortToBuffer DRIVER_writeShortToBuffer = nullptr; +_DRIVER_isWriteProtected DRIVER_isWriteProtected = nullptr; +_DRIVER_commitWriteBuffer DRIVER_commitWriteBuffer = nullptr; +_DRIVER_isWritePending DRIVER_isWritePending = nullptr; +_DRIVER_isWriteComplete DRIVER_isWriteComplete = nullptr; +_DRIVER_canTurboWrite DRIVER_canTurboWrite = nullptr; +_DRIVER_isReadyToWrite DRIVER_isReadyToWrite = nullptr; + +// Sets up the bridge. We assume it will persist while the application is open. +void prepareBridge() { + if (hBridgeDLLHandle) return; + +#ifdef WIN32 + hBridgeDLLHandle = WIN32_LoadLibrary(MODULENAME); +#else + hBridgeDLLHandle = dlopen(MODULENAME, RTLD_NOW); +#endif + + // Did it open? + if (!hBridgeDLLHandle) return; + + BRIDGE_About = (_BRIDGE_About)GETFUNC(hBridgeDLLHandle, "BRIDGE_About"); + BRIDGE_NumDrivers = (_BRIDGE_NumDrivers)GETFUNC(hBridgeDLLHandle, "BRIDGE_NumDrivers"); + BRIDGE_EnumComports = (_BRIDGE_EnumComports)GETFUNC(hBridgeDLLHandle, "BRIDGE_EnumComports"); + BRIDGE_GetDriverInfo = (_BRIDGE_GetDriverInfo)GETFUNC(hBridgeDLLHandle, "BRIDGE_GetDriverInfo"); + BRIDGE_CreateDriver = (_BRIDGE_CreateDriver)GETFUNC(hBridgeDLLHandle, "BRIDGE_CreateDriver"); + BRIDGE_GetDriverIndex = (_BRIDGE_GetDriverIndex)GETFUNC(hBridgeDLLHandle, "BRIDGE_GetDriverIndex"); + BRIDGE_Close = (_BRIDGE_Close)GETFUNC(hBridgeDLLHandle, "BRIDGE_Close"); + BRIDGE_Open = (_BRIDGE_Open)GETFUNC(hBridgeDLLHandle, "BRIDGE_Open"); + BRIDGE_FreeDriver = (_BRIDGE_FreeDriver)GETFUNC(hBridgeDLLHandle, "BRIDGE_FreeDriver"); + BRIDGE_DriverGetAutoCache = (_BRIDGE_DriverGetAutoCache)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverGetAutoCache"); + BRIDGE_DriverSetAutoCache = (_BRIDGE_DriverSetAutoCache)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverSetAutoCache"); + BRIDGE_GetConfigString = (_BRIDGE_GetConfigString)GETFUNC(hBridgeDLLHandle, "BRIDGE_GetConfigString"); + BRIDGE_SetConfigFromString = (_BRIDGE_SetConfigFromString)GETFUNC(hBridgeDLLHandle, "BRIDGE_SetConfigFromString"); + BRIDGE_CreateDriverFromConfigString = (_BRIDGE_CreateDriverFromConfigString)GETFUNC(hBridgeDLLHandle, "BRIDGE_CreateDriverFromConfigString"); + BRIDGE_DriverGetMode = (_BRIDGE_DriverGetMode)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverGetMode"); + BRIDGE_DriverSetMode = (_BRIDGE_DriverSetMode)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverSetMode"); + BRIDGE_DriverGetDensityMode = (_BRIDGE_DriverGetDensityMode)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverGetDensityMode"); + BRIDGE_DriverSetDensityMode = (_BRIDGE_DriverSetDensityMode)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverSetDensityMode"); + BRIDGE_DriverGetCurrentComPort = (_BRIDGE_DriverGetCurrentComPort)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverGetCurrentComPort"); + BRIDGE_DriverSetCurrentComPort = (_BRIDGE_DriverSetCurrentComPort)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverSetCurrentComPort"); + BRIDGE_DriverGetAutoDetectComPort = (_BRIDGE_DriverGetAutoDetectComPort)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverGetAutoDetectComPort"); + BRIDGE_DriverSetAutoDetectComPort = (_BRIDGE_DriverSetAutoDetectComPort)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverSetAutoDetectComPort"); + BRIDGE_DriverGetCable = (_BRIDGE_DriverGetCable)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverGetCable"); + BRIDGE_DriverSetCable = (_BRIDGE_DriverSetCable)GETFUNC(hBridgeDLLHandle, "BRIDGE_DriverSetCable"); + DRIVER_getBitSpeed = (_DRIVER_getBitSpeed)GETFUNC(hBridgeDLLHandle, "DRIVER_getBitSpeed"); + DRIVER_getDriveTypeID = (_DRIVER_getDriveTypeID)GETFUNC(hBridgeDLLHandle, "DRIVER_getDriveTypeID"); + DRIVER_resetDrive = (_DRIVER_resetDrive)GETFUNC(hBridgeDLLHandle, "DRIVER_resetDrive"); + DRIVER_isAtCylinder0 = (_DRIVER_isAtCylinder0)GETFUNC(hBridgeDLLHandle, "DRIVER_isAtCylinder0"); + DRIVER_getMaxCylinder = (_DRIVER_getMaxCylinder)GETFUNC(hBridgeDLLHandle, "DRIVER_getMaxCylinder"); + DRIVER_gotoCylinder = (_DRIVER_gotoCylinder)GETFUNC(hBridgeDLLHandle, "DRIVER_gotoCylinder"); + DRIVER_handleNoClickStep = (_DRIVER_handleNoClickStep)GETFUNC(hBridgeDLLHandle, "DRIVER_handleNoClickStep"); + DRIVER_getCurrentCylinderNumber = (_DRIVER_getCurrentCylinderNumber)GETFUNC(hBridgeDLLHandle, "DRIVER_getCurrentCylinderNumber"); + DRIVER_isMotorRunning = (_DRIVER_isMotorRunning)GETFUNC(hBridgeDLLHandle, "DRIVER_isMotorRunning"); + DRIVER_setMotorStatus = (_DRIVER_setMotorStatus)GETFUNC(hBridgeDLLHandle, "DRIVER_setMotorStatus"); + DRIVER_isReady = (_DRIVER_isReady)GETFUNC(hBridgeDLLHandle, "DRIVER_isReady"); + DRIVER_isDiskInDrive = (_DRIVER_isDiskInDrive)GETFUNC(hBridgeDLLHandle, "DRIVER_isDiskInDrive"); + DRIVER_hasDiskChanged = (_DRIVER_hasDiskChanged)GETFUNC(hBridgeDLLHandle, "DRIVER_hasDiskChanged"); + DRIVER_isMFMPositionAtIndex = (_DRIVER_isMFMPositionAtIndex)GETFUNC(hBridgeDLLHandle, "DRIVER_isMFMPositionAtIndex"); + DRIVER_isMFMDataAvailable = (_DRIVER_isMFMDataAvailable)GETFUNC(hBridgeDLLHandle, "DRIVER_isMFMDataAvailable"); + DRIVER_getMFMBit = (_DRIVER_getMFMBit)GETFUNC(hBridgeDLLHandle, "DRIVER_getMFMBit"); + DRIVER_getMFMSpeed = (_DRIVER_getMFMSpeed)GETFUNC(hBridgeDLLHandle, "DRIVER_getMFMSpeed"); + DRIVER_mfmSwitchBuffer = (_DRIVER_mfmSwitchBuffer)GETFUNC(hBridgeDLLHandle, "DRIVER_mfmSwitchBuffer"); + DRIVER_setSurface = (_DRIVER_setSurface)GETFUNC(hBridgeDLLHandle, "DRIVER_setSurface"); + DRIVER_maxMFMBitPosition = (_DRIVER_maxMFMBitPosition)GETFUNC(hBridgeDLLHandle, "DRIVER_maxMFMBitPosition"); + DRIVER_writeShortToBuffer = (_DRIVER_writeShortToBuffer)GETFUNC(hBridgeDLLHandle, "DRIVER_writeShortToBuffer"); + DRIVER_isWriteProtected = (_DRIVER_isWriteProtected)GETFUNC(hBridgeDLLHandle, "DRIVER_isWriteProtected"); + DRIVER_commitWriteBuffer = (_DRIVER_commitWriteBuffer)GETFUNC(hBridgeDLLHandle, "DRIVER_commitWriteBuffer"); + DRIVER_isWritePending = (_DRIVER_isWritePending)GETFUNC(hBridgeDLLHandle, "DRIVER_isWritePending"); + DRIVER_isWriteComplete = (_DRIVER_isWriteComplete)GETFUNC(hBridgeDLLHandle, "DRIVER_isWriteComplete"); + DRIVER_canTurboWrite = (_DRIVER_canTurboWrite)GETFUNC(hBridgeDLLHandle, "DRIVER_canTurboWrite"); + DRIVER_isReadyToWrite = (_DRIVER_isReadyToWrite)GETFUNC(hBridgeDLLHandle, "DRIVER_isReadyToWrite"); + + // Test a few + if ((!BRIDGE_About) || (!BRIDGE_NumDrivers)) { +#ifdef WIN32 + if (hBridgeDLLHandle) FreeLibrary(hBridgeDLLHandle); + hBridgeDLLHandle = 0; +#else + if (hBridgeDLLHandle) dlclose(hBridgeDLLHandle); + hBridgeDLLHandle = nullptr; +#endif + } +} + + +// character conversions +using convert_t = std::codecvt_utf8; +static std::wstring_convert strconverter; + +void _quickw2a(const std::wstring& wstr, std::string& str) { + str = strconverter.to_bytes(wstr); +} +void _quicka2w(const std::string& str, std::wstring& wstr) { + wstr = strconverter.from_bytes(str); +} + +// Copy or convert a char* to a TCHAR +void _char2TChar(const char* input, TCHAR* output, unsigned maxLength) { +#ifdef _UNICODE + std::wstring outputw; + _quicka2w(input, outputw); +#ifdef _WIN32 + wcscpy_s(output, maxLength, outputw.c_str()); +#else + wcscpy(output, outputw.c_str()); +#endif +#else +#ifdef _WIN32 + strcpy_s(output, maxLength, input); +#else + strcpy_s(output, input); +#endif +#endif +} + +#ifdef _UNICODE +std::vector memoryPortList; +#else +std::vector memoryPortList; +#endif + +/*********** STATIC FUNCTIONS ************************/ + +// Returns TRUE if the floppy bridge library has been loaded and is ready to be queried +const bool FloppyBridgeAPI::isAvailable() { + prepareBridge(); + + return hBridgeDLLHandle != 0; +} + +// Populates bridgeInformation with information about the Bridge DLL. This should be called and shown somewhere +// As it contains update and support information too +bool FloppyBridgeAPI::getBridgeDriverInformation(BridgeInformation& bridgeInformation) { + if (!isAvailable()) { + // Populate some basics + memset(&bridgeInformation, 0, sizeof(bridgeInformation)); + _char2TChar("FloppyBridge Driver Not Installed.", bridgeInformation.about, BRIDGE_STRING_MAX_LENGTH - 1); + _char2TChar("https://amiga.robsmithdev.co.uk/winuae", bridgeInformation.url, BRIDGE_STRING_MAX_LENGTH - 1); + return false; + } + + BridgeAbout* info = nullptr; + BRIDGE_About(&info); + if (!info) return false; + + bridgeInformation.isBeta = info->isBeta != 0; + bridgeInformation.isUpdateAvailable = info->isUpdateAvailable != 0; + + bridgeInformation.majorVersion = info->majorVersion; + bridgeInformation.minorVersion = info->minorVersion; + bridgeInformation.updateMajorVersion = info->updateMajorVersion; + bridgeInformation.updateMinorVersion = info->updateMinorVersion; + + _char2TChar(info->about, bridgeInformation.about, BRIDGE_STRING_MAX_LENGTH - 1); + _char2TChar(info->url, bridgeInformation.url, BRIDGE_STRING_MAX_LENGTH - 1); + return true; +} + +// Populates driverList with a list of available floppy bridge drivers that could be created +void FloppyBridgeAPI::getDriverList(std::vector& driverList) { + driverList.clear(); + + if (!isAvailable()) return; + + unsigned int total = BRIDGE_NumDrivers(); + if (total < 1) return; + + BridgeDriver* info = nullptr; + for (unsigned int index = 0; index < total; index++) { + if (BRIDGE_GetDriverInfo(index, &info)) { + + DriverInformation infoOut; + + _char2TChar(info->name, infoOut.name, BRIDGE_STRING_MAX_LENGTH - 1); + _char2TChar(info->url, infoOut.url, BRIDGE_STRING_MAX_LENGTH - 1); + _char2TChar(info->manufacturer, infoOut.manufacturer, BRIDGE_STRING_MAX_LENGTH - 1); + _char2TChar(info->driverAuthor, infoOut.driverAuthor, BRIDGE_STRING_MAX_LENGTH - 1); + infoOut.configOptions = info->configOptions; + infoOut.driverIndex = index; + + driverList.push_back(infoOut); + } + } +} + +// Creates a driver. If it fails, it will return NULL. It should only fail if the index is invalid. +FloppyBridgeAPI* FloppyBridgeAPI::createDriver(unsigned int driverIndex) { + if (!isAvailable()) return nullptr; + + BridgeDriverHandle driverHandle = nullptr; + + if (!BRIDGE_CreateDriver(driverIndex, &driverHandle)) return nullptr; + + // Create the class and return it. + return new FloppyBridgeAPI(driverIndex, driverHandle); +} + +// Createw a driver from a config string previously saved. This will auto-select the driverIndex. +FloppyBridgeAPI* FloppyBridgeAPI::createDriverFromString(const char* config) { + if (!isAvailable()) return nullptr; + + BridgeDriverHandle driverHandle = nullptr; + + if (!BRIDGE_CreateDriverFromConfigString((char*)config, &driverHandle)) return nullptr; + + unsigned int driverIndex; + if (!BRIDGE_GetDriverIndex(driverHandle, &driverIndex)) { + BRIDGE_FreeDriver(driverHandle); + return nullptr; + } + + return new FloppyBridgeAPI(driverIndex, driverHandle); +} + +// Populates portList with a list of serial port devices that you can use with setComPort() below +void FloppyBridgeAPI::enumCOMPorts(std::vector& portList) { + portList.clear(); + + if (!isAvailable()) return; + + unsigned int sizeNeeded = 0; + BRIDGE_EnumComports(NULL, &sizeNeeded); + + char* tmp = (char*)malloc(sizeNeeded); + if (!tmp) return; + + if (BRIDGE_EnumComports(tmp, &sizeNeeded)) { + char* str = tmp; + TCharString opString; + + memoryPortList.clear(); + + while (*str) { + _char2TChar(str, opString, BRIDGE_STRING_MAX_LENGTH); + memoryPortList.push_back(opString); + str += strlen(str) + 1; // skip pas the null terminator + } + + for (auto& string : memoryPortList) + portList.push_back(string.c_str()); + } + free(tmp); +} + +/*********** CLASS FUNCTIONS ************************/ + +// Dont call this. You should use the static createDriver member to create it. +FloppyBridgeAPI::FloppyBridgeAPI(unsigned int driverIndex, BridgeDriverHandle handle) : FloppyDiskBridge(), m_handle(handle), m_driverIndex(driverIndex) { +} + +FloppyBridgeAPI::~FloppyBridgeAPI() { + BRIDGE_FreeDriver(m_handle); +} + +/************** CONFIG RELATED FUNCTIONS *************************************/ +// Returns a pointer to a string containing the current config. This can be used with setConfigFromString() or createDriverFromString() +bool FloppyBridgeAPI::getConfigAsString(char** config) { + return BRIDGE_GetConfigString(m_handle, config); +} +// Applies the config to the currently driver. Returns TRUE if successful. +bool FloppyBridgeAPI::setConfigFromString(char* config) { + return BRIDGE_SetConfigFromString(m_handle, config); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Return the current bridge mode selected +bool FloppyBridgeAPI::getBridgeMode(FloppyBridgeAPI::BridgeMode* mode) { + return BRIDGE_DriverGetMode(m_handle, mode); +} +// Set the currently active bridge mode. This can be set while the bridge is in use +bool FloppyBridgeAPI::setBridgeMode(BridgeMode newMode) { + return BRIDGE_DriverSetMode(m_handle, newMode); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Return the current bridge density mode selected +bool FloppyBridgeAPI::getBridgeDensityMode(FloppyBridgeAPI::BridgeDensityMode* mode) { + return BRIDGE_DriverGetDensityMode(m_handle, mode); +} +// Set the currently active bridge density mode. This can be set while the bridge is in use +bool FloppyBridgeAPI::setBridgeDensityMode(BridgeDensityMode newMode) { + return BRIDGE_DriverSetDensityMode(m_handle, newMode); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// These require ConfigOption_AutoCache bit set in DriverInformation::configOptions +// Returns if auto-disk caching (while the drive is idle) mode is enabled +bool FloppyBridgeAPI::getAutoCacheMode(bool* autoCacheMode) { + return BRIDGE_DriverGetAutoCache(m_handle, autoCacheMode); +} +// Sets if auto-disk caching (while the drive is idle) mode is enabled. This can be set while the bridge is in use +bool FloppyBridgeAPI::setAutoCacheMode(bool autoCacheMode) { + return BRIDGE_DriverSetAutoCache(m_handle, autoCacheMode); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// These require ConfigOption_ComPort bit set in DriverInformation::configOptions +// Returns the currently selected COM port. This port is only used if auto detect com port is false +bool FloppyBridgeAPI::getComPort(TCharString* comPort) { + char* port = nullptr; + if (!BRIDGE_DriverGetCurrentComPort(m_handle, &port)) return false; + if (!port) return false; + + _char2TChar(port, *comPort, BRIDGE_STRING_MAX_LENGTH - 1); + return true; +} +// Sets the com port to use. This port is only used if auto detect com port is false. +bool FloppyBridgeAPI::setComPort(TCHAR* comPort) { + if (!comPort) return false; + +#ifdef _UNICODE + std::string comPortA; + _quickw2a(comPort, comPortA); + return BRIDGE_DriverSetCurrentComPort(m_handle, (char*)comPortA.c_str()); +#else + return BRIDGE_DriverSetCurrentComPort(m_handle, comPort); +#endif +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// These require ConfigOption_AutoDetectComport bit set in DriverInformation::configOptions +// Returns if com port auto-detect is enabled +bool FloppyBridgeAPI::getComPortAutoDetect(bool* autoDetect) { + return BRIDGE_DriverGetAutoDetectComPort(m_handle, autoDetect); +} +// Sets if auto-detect com port should be used +bool FloppyBridgeAPI::setComPortAutoDetect(bool autoDetect) { + return BRIDGE_DriverSetAutoDetectComPort(m_handle, autoDetect); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// These require ConfigOption_DriveABCable bit set in DriverInformation::configOptions +// Returns if the driver should use a drive connected as Drive B (true) on the cable rather than Drive A (false) +bool FloppyBridgeAPI::getDriveCableSelection(bool* connectToDriveB) { + return BRIDGE_DriverGetCable(m_handle, connectToDriveB); +} +// Sets if the driver should use a drive connected as Drive B (true) on the cable rather than Drive A (false) +bool FloppyBridgeAPI::setDriveCableSelection(bool connectToDriveB) { + return BRIDGE_DriverSetCable(m_handle, connectToDriveB); +} + + +/******************* BRIDGE Functions for UAE **********************************/ + +bool FloppyBridgeAPI::initialise() { + if (m_isOpen) shutdown(); + + memset(m_error, 0, sizeof(m_error)); + memset(m_warning, 0, sizeof(m_warning)); + + char* msg; + m_isOpen = BRIDGE_Open(m_handle, &msg); + + if (m_isOpen) { + if (msg) _char2TChar(msg, m_warning, BRIDGE_STRING_MAX_LENGTH-1); + return true; + } + else { + if (msg) _char2TChar(msg, m_error, BRIDGE_STRING_MAX_LENGTH - 1); + return false; + } +} +void FloppyBridgeAPI::shutdown() { + if (m_isOpen) { + BRIDGE_Close(m_handle); + m_isOpen = false; + } + FloppyDiskBridge::shutdown(); +} + + +//virtual const BridgeDriver* getDriverInfo() override; +unsigned char FloppyBridgeAPI::getBitSpeed() { + return DRIVER_getBitSpeed(m_handle); +} +FloppyDiskBridge::DriveTypeID FloppyBridgeAPI::getDriveTypeID() { + return DRIVER_getDriveTypeID(m_handle); +} +const char* FloppyBridgeAPI::getLastErrorMessage() { +#ifdef _UNICODE + _quickw2a(m_error, m_lastErrorAnsi); + return m_lastErrorAnsi.c_str(); +#else + return m_lastError; +#endif +} +const FloppyDiskBridge::BridgeDriver* FloppyBridgeAPI::getDriverInfo() { + if (BRIDGE_GetDriverInfo(m_driverIndex, &m_driverInfo)) return m_driverInfo; + return nullptr; +} +bool FloppyBridgeAPI::resetDrive(int trackNumber) { + return DRIVER_resetDrive(m_handle, trackNumber); +} +bool FloppyBridgeAPI::isAtCylinder0() { + return DRIVER_isAtCylinder0(m_handle); +} +unsigned char FloppyBridgeAPI::getMaxCylinder() { + return DRIVER_getMaxCylinder(m_handle); +} +void FloppyBridgeAPI::gotoCylinder(int cylinderNumber, bool side) { + DRIVER_gotoCylinder(m_handle, cylinderNumber, side); +} +void FloppyBridgeAPI::handleNoClickStep(bool side) { + DRIVER_handleNoClickStep(m_handle, side); +} +unsigned char FloppyBridgeAPI::getCurrentCylinderNumber() { + return DRIVER_getCurrentCylinderNumber(m_handle); +} +bool FloppyBridgeAPI::isMotorRunning() { + return DRIVER_isMotorRunning(m_handle); +} +void FloppyBridgeAPI::setMotorStatus(bool turnOn, bool side) { + DRIVER_setMotorStatus(m_handle, turnOn, side); +} +bool FloppyBridgeAPI::isReady() { + return DRIVER_isReady(m_handle); +} +bool FloppyBridgeAPI::isDiskInDrive() { + return DRIVER_isDiskInDrive(m_handle); +} +bool FloppyBridgeAPI::hasDiskChanged() { + return DRIVER_hasDiskChanged(m_handle); +} +bool FloppyBridgeAPI::isMFMPositionAtIndex(int mfmPositionBits) { + return DRIVER_isMFMPositionAtIndex(m_handle, mfmPositionBits); +} +bool FloppyBridgeAPI::isMFMDataAvailable() { + return DRIVER_isMFMDataAvailable(m_handle); +} +bool FloppyBridgeAPI::getMFMBit(const int mfmPositionBits) { + return DRIVER_getMFMBit(m_handle, mfmPositionBits); +} +int FloppyBridgeAPI::getMFMSpeed(const int mfmPositionBits) { + return DRIVER_getMFMSpeed(m_handle, mfmPositionBits); +} +void FloppyBridgeAPI::mfmSwitchBuffer(bool side) { + DRIVER_mfmSwitchBuffer(m_handle, side); +} +void FloppyBridgeAPI::setSurface(bool side) { + DRIVER_setSurface(m_handle, side); +} +int FloppyBridgeAPI::maxMFMBitPosition() { + return DRIVER_maxMFMBitPosition(m_handle); +} +void FloppyBridgeAPI::writeShortToBuffer(bool side, unsigned int track, unsigned short mfmData, int mfmPosition) { + DRIVER_writeShortToBuffer(m_handle, side, track, mfmData, mfmPosition); +} +bool FloppyBridgeAPI::isWriteProtected() { + return DRIVER_isWriteProtected(m_handle); +} +unsigned int FloppyBridgeAPI::commitWriteBuffer(bool side, unsigned int track) { + return DRIVER_commitWriteBuffer(m_handle, side, track); +} +bool FloppyBridgeAPI::isWritePending() { + return DRIVER_isWritePending(m_handle); +} +bool FloppyBridgeAPI::isWriteComplete() { + return DRIVER_isWriteComplete(m_handle); +} +bool FloppyBridgeAPI::canTurboWrite() { + return DRIVER_canTurboWrite(m_handle); +} +bool FloppyBridgeAPI::isReadyToWrite() { + return DRIVER_isReadyToWrite(m_handle); +} \ No newline at end of file diff --git a/floppybridge/floppybridge_lib.h b/floppybridge/floppybridge_lib.h new file mode 100644 index 00000000..e8d81c0a --- /dev/null +++ b/floppybridge/floppybridge_lib.h @@ -0,0 +1,229 @@ +/* floppybridge_lib +* +* Copyright (C) 2021 Robert Smith (@RobSmithDev) +* https://amiga.robsmithdev.co.uk +* +* This class connects to the external FloppyBridge DLL library rather than +* having all the code compiled in. That library is maintained at +* https://amiga.robsmithdev.co.uk/winuae +* +* This is free and unencumbered released into the public domain +* But please don't remove the above information +* +* For more details visit . +* +*/ + +#pragma once + +#include "floppybridge_abstract.h" + +#define BRIDGE_STRING_MAX_LENGTH 255 +typedef TCHAR TCharString[BRIDGE_STRING_MAX_LENGTH]; + +typedef void* BridgeDriverHandle; + +// Class to access the 'floppybridge' via a DLL but using the same interface +class FloppyBridgeAPI : public FloppyDiskBridge { +public: + // Type of bridge mode + enum class BridgeMode : unsigned char { + bmFast = 0, // Fast mode. This is suitable for most disks and games + bmCompatiable = 1, // More compatiable mode. Some games require this. + bmTurboAmigaDOS = 2, // Very fast mode. This will break all copy protcetion, but is great for AmigaDOS disks in Workbench + bmStalling = 3, // Very slow. Will cause the emulator to freeze and stall while disk access occurs. + bmMax = 3 + }; + + // How to use disk density + enum class BridgeDensityMode : unsigned char { + bdmAuto = 0, // Auto-detect the type of disk when its inserted + bdmDDOnly = 1, // Always detect all inserted disks as DD + bdmHDOnly = 2, // Always detect all inserted disks as HD + bdmMax = 2 + }; + + // Information about the bridge driver DLL that was loaded. + struct BridgeInformation { + // Information about the bridge + TCharString about; + // A url where you can get support/download updates from + TCharString url; + // The current version + unsigned int majorVersion, minorVersion; + // Is this version a beta build? + bool isBeta; + // Is there an update to this version available? + bool isUpdateAvailable; + // The version number of the update/latest version available + unsigned int updateMajorVersion, updateMinorVersion; + }; + + // These bitmasks are used with DriverInformation::configOptions + static const unsigned int ConfigOption_AutoCache = 0x01; // The driver can cache data from other cylinders while the disk isn't in use + static const unsigned int ConfigOption_ComPort = 0x02; // The driver requires a COM port selection + static const unsigned int ConfigOption_AutoDetectComport = 0x04; // The driver supports automatic com port detection and selection + static const unsigned int ConfigOption_DriveABCable = 0x08; // The driver allows you to specify using cable select for Drive A or Drive B + + // Information about a Bridge Driver (eg: DrawBridge, Greaseweazle etc) + struct DriverInformation { + // Used to identify the type of driver. Use this to create the device or multiple instances of the device (possibly on different COM ports) + unsigned int driverIndex; + + // Details about the driver + TCharString name; + TCharString url; + TCharString manufacturer; + TCharString driverAuthor; + + // A bitmask of which options in configuration the driver can support, aside from the standard ones. See the ConfigOption_ consts above + unsigned int configOptions; + }; + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Static functions for accessing parts of the API before creating an instance of this + // Route is: choose driver, create driver, configure it, then set the "bridge" variable in UAE to the created instance and it will do the rest + + // Returns TRUE if the floppy bridge library has been loaded and is ready to be queried. All functions are safe to call regardless the return value + static const bool isAvailable(); + + // Populares bridgeInformation with information about the Bridge DLL. This should be called and shown somewhere + // As it contains update and support information too. If this returns FALSE it will still contain basic information such as a URL to get the DLL from. + static bool getBridgeDriverInformation(BridgeInformation& bridgeInformation); + + // Populates driverList with a list of available floppy bridge drivers that could be created + static void getDriverList(std::vector& driverList); + + // Populates portList with a list of serial port devices that you can use with setComPort() below + // NOTE: The TCHARs in the vector are only valid until this function is called again + static void enumCOMPorts(std::vector& portList); + + // Creates a driver. If it fails, it will return NULL. It should only fail if the index is invalid. + static FloppyBridgeAPI* createDriver(unsigned int driverIndex); + + // Createw a driver from a config string previously saved. This will auto-select the driverIndex. + static FloppyBridgeAPI* createDriverFromString(const char* config); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Functions for configuring the driver once it has been created. + // Returns a pointer to a string containing the current config. This can be used with setConfigFromString() or createDriverFromString() + bool getConfigAsString(char** config); + // Applies the config to the currently driver. Returns TRUE if successful. + bool setConfigFromString(char* config); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Return the current bridge mode selected + bool getBridgeMode(BridgeMode* mode); + // Set the currently active bridge mode. This can be set while the bridge is in use + bool setBridgeMode(BridgeMode newMode); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Return the current bridge density mode selected + bool getBridgeDensityMode(BridgeDensityMode* mode); + // Set the currently active bridge density mode. This can be set while the bridge is in use + bool setBridgeDensityMode(BridgeDensityMode newMode); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // These require ConfigOption_AutoCache bit set in DriverInformation::configOptions + // Returns if auto-disk caching (while the drive is idle) mode is enabled + bool getAutoCacheMode(bool* autoCacheMode); + // Sets if auto-disk caching (while the drive is idle) mode is enabled. This can be set while the bridge is in use + bool setAutoCacheMode(bool autoCacheMode); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // These require ConfigOption_ComPort bit set in DriverInformation::configOptions + // Returns the currently selected COM port. This port is only used if auto detect com port is false + bool getComPort(TCharString* comPort); + // Sets the com port to use. This port is only used if auto detect com port is false. + bool setComPort(TCHAR* comPort); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // These require ConfigOption_AutoDetectComport bit set in DriverInformation::configOptions + // Returns if com port auto-detect is enabled + bool getComPortAutoDetect(bool* autoDetect); + // Sets if auto-detect com port should be used + bool setComPortAutoDetect(bool autoDetect); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // These require ConfigOption_DriveABCable bit set in DriverInformation::configOptions + // Returns if the driver should use a drive connected as Drive B (true) on the cable rather than Drive A (false) + bool getDriveCableSelection(bool* connectToDriveB); + // Sets if the driver should use a drive connected as Drive B (true) on the cable rather than Drive A (false) + bool setDriveCableSelection(bool connectToDriveB); + + + + + + + + + + + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Functions required by UAE - see floppybridge_abstract for more details + FloppyBridgeAPI(unsigned int driverIndex, BridgeDriverHandle handle); // Dont call this. You should use the static createDriver member to create it. + virtual ~FloppyBridgeAPI(); + virtual bool initialise() override; + virtual void shutdown() override; + virtual const BridgeDriver* getDriverInfo() override; + virtual unsigned char getBitSpeed() override; + virtual FloppyDiskBridge::DriveTypeID getDriveTypeID() override; + virtual const char* getLastErrorMessage() override; + virtual bool resetDrive(int trackNumber) override; + virtual bool isAtCylinder0() override; + virtual unsigned char getMaxCylinder() override; + virtual void gotoCylinder(int cylinderNumber, bool side) override; + virtual void handleNoClickStep(bool side) override; + virtual unsigned char getCurrentCylinderNumber() override; + virtual bool isMotorRunning() override; + virtual void setMotorStatus(bool turnOn, bool side) override; + virtual bool isReady() override; + virtual bool isDiskInDrive() override; + virtual bool hasDiskChanged() override; + virtual bool isMFMPositionAtIndex(int mfmPositionBits) override; + virtual bool isMFMDataAvailable() override; + virtual bool getMFMBit(const int mfmPositionBits) override; + virtual int getMFMSpeed(const int mfmPositionBits) override; + virtual void mfmSwitchBuffer(bool side) override; + virtual void setSurface(bool side) override; + virtual int maxMFMBitPosition() override; + virtual void writeShortToBuffer(bool side, unsigned int track, unsigned short mfmData, int mfmPosition) override; + virtual bool isWriteProtected() override; + virtual unsigned int commitWriteBuffer(bool side, unsigned int track) override; + virtual bool isWritePending() override; + virtual bool isWriteComplete() override; + virtual bool canTurboWrite() override; + virtual bool isReadyToWrite() override; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +private: + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Private stuff + BridgeDriverHandle m_handle; // Handle to loaded driver + unsigned int m_driverIndex; // Index of that driver + TCharString m_error = { 0 }; // Last error + TCharString m_warning = { 0 }; // Last warning + BridgeDriver* m_driverInfo; // Pointer to the driver info if retreived +#ifdef _UNICODE + std::string m_lastErrorAnsi; // Non-unicode version of the last error +#endif + bool m_isOpen = false; // If the driver is 'open' (ie connected to the drive) or not +}; \ No newline at end of file diff --git a/include/disk.h b/include/disk.h index f0314a94..53c53e85 100644 --- a/include/disk.h +++ b/include/disk.h @@ -11,7 +11,10 @@ #include "uae/types.h" -typedef enum { DRV_NONE = -1, DRV_35_DD = 0, DRV_35_HD, DRV_525_SD, DRV_35_DD_ESCOM, DRV_PC_525_ONLY_40, DRV_PC_35_ONLY_80, DRV_PC_525_40_80, DRV_525_DD } drive_type; +typedef enum { + DRV_NONE = -1, DRV_35_DD = 0, DRV_35_HD, DRV_525_SD, DRV_35_DD_ESCOM, DRV_PC_525_ONLY_40, DRV_PC_35_ONLY_80, DRV_PC_525_40_80, DRV_525_DD, + DRV_FB_A_35_DD, DRV_FB_A_35_HD, DRV_FB_B_35_DD, DRV_FB_B_35_HD, +} drive_type; #define HISTORY_FLOPPY 0 #define HISTORY_CD 1 @@ -30,6 +33,7 @@ struct diskinfo { uae_u8 bootblock[1024]; bool bb_crc_valid; + bool image_crc_value; uae_u32 imagecrc32; uae_u32 bootblockcrc32; bool hd; @@ -74,23 +78,24 @@ extern void disk_insert (int num, const TCHAR *name); extern void disk_insert (int num, const TCHAR *name, bool forcedwriteprotect); extern void disk_insert_force (int num, const TCHAR *name, bool forcedwriteprotect); extern void DISK_vsync (void); -extern int DISK_validate_filename (struct uae_prefs *p, const TCHAR *fname, TCHAR *outfname, int leave_open, bool *wrprot, uae_u32 *crc32, struct zfile **zf); +extern int DISK_validate_filename (struct uae_prefs *p, const TCHAR *fname, int num, TCHAR *outfname, int leave_open, bool *wrprot, uae_u32 *crc32, struct zfile **zf); extern void DISK_handler (uae_u32); extern void DISK_update (int hpos); extern void DISK_update_adkcon (int hpos, uae_u16 v); extern void DISK_hsync (void); extern void DISK_reset (void); -extern int disk_getwriteprotect (struct uae_prefs *p, const TCHAR *name); +extern int disk_getwriteprotect (struct uae_prefs *p, const TCHAR *name, int num); extern int disk_setwriteprotect (struct uae_prefs *p, int num, const TCHAR *name, bool writeprotected); extern bool disk_creatediskfile (struct uae_prefs *p, const TCHAR *name, int type, drive_type adftype, int hd, const TCHAR *disk_name, bool ffs, bool bootable, struct zfile *copyfrom); extern void dumpdisk (const TCHAR*); extern int DISK_history_add (const TCHAR *name, int idx, int type, int donotcheck); extern TCHAR *DISK_history_get (int idx, int type); -int DISK_examine_image (struct uae_prefs *p, int num, struct diskinfo *di, bool deepcheck); +int DISK_examine_image (struct uae_prefs *p, int num, struct diskinfo *di, bool deepcheck, TCHAR *info); extern TCHAR *DISK_get_saveimagepath(const TCHAR *name, int type); extern void DISK_reinsert (int num); extern int disk_prevnext (int drive, int dir); extern int disk_prevnext_name (TCHAR *img, int dir); +extern void DISK_get_path_text(struct uae_prefs *p, int n, TCHAR *text); extern bool gui_ask_disk(int drv, TCHAR*); @@ -114,4 +119,8 @@ extern int disk_debug_track; #define MAX_PREVIOUS_IMAGES 50 +void floppybridge_init(struct uae_prefs *p); +bool floppybridge_has(void); +bool DISK_isfloppybridge(struct uae_prefs*, int); + #endif /* UAE_DISK_H */ diff --git a/include/gui.h b/include/gui.h index 815978a5..60d701d5 100644 --- a/include/gui.h +++ b/include/gui.h @@ -57,6 +57,7 @@ struct gui_info_drive { TCHAR df[256]; /* inserted image */ uae_u32 crc32; /* crc32 of image */ bool floppy_protected; /* image is write protected */ + bool floppy_inserted; /* disk inserted */ }; struct gui_info diff --git a/include/options.h b/include/options.h index 9f8dcbbf..901896f3 100644 --- a/include/options.h +++ b/include/options.h @@ -164,6 +164,7 @@ struct floppyslot int dfxclick; TCHAR dfxclickexternal[256]; bool forcedwriteprotect; + TCHAR config[256]; }; #define ASPECTMULT 1024 @@ -921,7 +922,7 @@ extern void cfgfile_target_write_bool (struct zfile *f, const TCHAR *option, boo extern void cfgfile_target_dwrite_bool (struct zfile *f, const TCHAR *option, bool b); extern void cfgfile_write_str(struct zfile *f, const TCHAR *option, const TCHAR *value); -extern void cfgfile_write_str_escape(struct zfile* f, const TCHAR* option, const TCHAR* value); +extern void cfgfile_write_str_escape(struct zfile *f, const TCHAR *option, const TCHAR *value); extern void cfgfile_dwrite_str(struct zfile *f, const TCHAR *option, const TCHAR *value); extern void cfgfile_dwrite_str_escape(struct zfile *f, const TCHAR *option, const TCHAR *value); extern void cfgfile_target_write_str(struct zfile *f, const TCHAR *option, const TCHAR *value); diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index 890341fc..fd811d5e 100644 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -342,8 +342,8 @@ BEGIN GROUPBOX "Floppy Drives",IDC_SETTINGSTEXT3,1,23,393,163 CONTROL "DF0:",IDC_DF0ENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7,37,34,15 PUSHBUTTON "Delete save image",IDC_SAVEIMAGE0,69,36,78,15,NOT WS_VISIBLE - COMBOBOX IDC_DF0TYPE,152,37,65,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - RTEXT "Write-protected",IDC_STATIC,221,40,74,10,SS_CENTERIMAGE + COMBOBOX IDC_DF0TYPE,152,37,76,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "Write-protected",IDC_STATIC,229,40,66,10,SS_CENTERIMAGE CONTROL "",IDC_DF0WP,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,300,36,10,15 PUSHBUTTON "?",IDC_INFO0,323,35,17,15 PUSHBUTTON "Eject",IDC_EJECT0,345,35,30,15 @@ -351,8 +351,8 @@ BEGIN COMBOBOX IDC_DF0TEXT,6,54,384,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP CONTROL "DF1:",IDC_DF1ENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7,74,34,15 PUSHBUTTON "Delete save image",IDC_SAVEIMAGE1,69,72,78,15,NOT WS_VISIBLE - COMBOBOX IDC_DF1TYPE,152,74,65,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - RTEXT "Write-protected",IDC_STATIC,221,76,74,10,SS_CENTERIMAGE + COMBOBOX IDC_DF1TYPE,152,74,76,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "Write-protected",IDC_STATIC,229,76,66,10,SS_CENTERIMAGE CONTROL "",IDC_DF1WP,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,300,73,10,15 PUSHBUTTON "?",IDC_INFO1,323,72,17,15 PUSHBUTTON "Eject",IDC_EJECT1,345,72,30,15 @@ -360,8 +360,8 @@ BEGIN COMBOBOX IDC_DF1TEXT,6,91,383,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP CONTROL "DF2:",IDC_DF2ENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7,110,34,15 PUSHBUTTON "Delete save image",IDC_SAVEIMAGE2,69,108,78,15,NOT WS_VISIBLE - COMBOBOX IDC_DF2TYPE,152,110,65,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - RTEXT "Write-protected",IDC_STATIC,222,111,73,10,SS_CENTERIMAGE + COMBOBOX IDC_DF2TYPE,152,110,76,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "Write-protected",IDC_STATIC,229,111,66,10,SS_CENTERIMAGE CONTROL "",IDC_DF2WP,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,300,109,9,15 PUSHBUTTON "?",IDC_INFO2,323,108,17,15 PUSHBUTTON "Eject",IDC_EJECT2,345,108,30,15 @@ -369,8 +369,8 @@ BEGIN COMBOBOX IDC_DF2TEXT,6,127,384,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP CONTROL "DF3:",IDC_DF3ENABLE,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7,146,34,15 PUSHBUTTON "Delete save image",IDC_SAVEIMAGE3,69,144,78,15,NOT WS_VISIBLE - COMBOBOX IDC_DF3TYPE,152,146,65,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - RTEXT "Write-protected",IDC_STATIC,222,148,73,10,SS_CENTERIMAGE + COMBOBOX IDC_DF3TYPE,152,146,76,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "Write-protected",IDC_STATIC,229,148,66,10,SS_CENTERIMAGE CONTROL "",IDC_DF3WP,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,300,146,9,15 PUSHBUTTON "?",IDC_INFO3,323,145,17,15 PUSHBUTTON "Eject",IDC_EJECT3,345,144,30,15 diff --git a/od-win32/sysconfig.h b/od-win32/sysconfig.h index d1369746..2cb29723 100644 --- a/od-win32/sysconfig.h +++ b/od-win32/sysconfig.h @@ -106,6 +106,7 @@ #define WITH_PCI #define WITH_X86 #define WITH_THREADED_CPU +#define FLOPPYBRIDGE #else diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 83d5c2a9..fa40854b 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -233,7 +233,7 @@ static int quickstart_ok, quickstart_ok_floppy; static bool firstautoloadconfig = false; static void addfloppytype (HWND hDlg, int n); static void addfloppyhistory (HWND hDlg); -static void addhistorymenu (HWND hDlg, const TCHAR*, int f_text, int type, bool manglepath); +static void addhistorymenu (HWND hDlg, const TCHAR*, int f_text, int type, bool manglepath, int num); static void addcdtype (HWND hDlg, int id); static void getfloppyname (HWND hDlg, int n, int cd, int f_text); @@ -2538,28 +2538,41 @@ void gui_infotextbox(HWND hDlg, const TCHAR *text) if (stringboxdialogactive == -1) break; } - DeleteObject (font); + if (font) { + DeleteObject(font); + } } static void infofloppy (HWND hDlg, int n) { struct diskinfo di; - TCHAR tmp2[MAX_DPATH], tmp1[MAX_DPATH]; + TCHAR tmp2[MAX_DPATH], tmp1[MAX_DPATH], tmp3[MAX_DPATH]; TCHAR text[20000]; - DISK_examine_image (&workprefs, n, &di, true); - DISK_validate_filename(&workprefs, workprefs.floppyslots[n].df, tmp1, 0, NULL, NULL, NULL); + DISK_examine_image (&workprefs, n, &di, true, tmp3); + DISK_validate_filename(&workprefs, workprefs.floppyslots[n].df, n, tmp1, 0, NULL, NULL, NULL); - _stprintf (tmp2, - _T("'%s'\r\nDisk readable: %s\r\nDisk CRC32: %08X\r\nBoot block CRC32: %08X\r\nBoot block checksum valid: %s\r\nBoot block type: %s\r\n"), - tmp1, - di.unreadable ? _T("No") : _T("Yes"), - di.imagecrc32, + text[0] = 0; + if (tmp3[0]) { + _tcscpy(text, tmp3); + _tcscat(text, _T("\r\n\r\n")); + } + tmp2[0] = 0; + if (tmp1[0]) { + _stprintf(tmp2, _T("'%s'\r\n"), tmp1); + } + _stprintf (tmp2 + _tcslen(tmp2), _T("Disk readable: %s\r\n"), di.unreadable ? _T("No") : _T("Yes")); + if (di.image_crc_value) { + _stprintf(tmp2 + _tcslen(tmp2), _T("Disk CRC32: %08X\r\n"), di.imagecrc32); + } + _stprintf(tmp2 + _tcslen(tmp2), + _T("Boot block CRC32: %08X\r\nBoot block checksum valid: %s\r\nBoot block type: %s\r\n"), di.bootblockcrc32, di.bb_crc_valid ? _T("Yes") : _T("No"), di.bootblocktype == 0 ? _T("Custom") : (di.bootblocktype == 1 ? _T("Standard 1.x") : _T("Standard 2.x+")) ); - _tcscpy (text, tmp2); + + _tcscat(text, tmp2); if (di.diskname[0]) { _stprintf (tmp2, _T("Label: '%s'\r\n"), di.diskname); @@ -5966,7 +5979,7 @@ static int LoadConfigTreeView (HWND hDlg, int idx, HTREEITEM parent) static void InitializeConfig (HWND hDlg, struct ConfigStruct *config) { - addhistorymenu(hDlg, config == NULL ? _T("") : config->Name, IDC_EDITNAME, HISTORY_CONFIGFILE, false); + addhistorymenu(hDlg, config == NULL ? _T("") : config->Name, IDC_EDITNAME, HISTORY_CONFIGFILE, false, -1); if (config == NULL) { SetDlgItemText (hDlg, IDC_EDITDESCRIPTION, _T("")); } else { @@ -7270,7 +7283,7 @@ static void testimage (HWND hDlg, int num) } if (!workprefs.floppyslots[num].df[0]) return; - ret = DISK_examine_image (&workprefs, num, &di, false); + ret = DISK_examine_image (&workprefs, num, &di, false, NULL); if (!ret) return; floppytooltip (hDlg, num, di.imagecrc32); @@ -8822,9 +8835,9 @@ static void setgenlock(HWND hDlg) { setautocomplete(hDlg, IDC_GENLOCKFILE); if (workprefs.genlock_image == 3) { - addhistorymenu(hDlg, workprefs.genlock_image_file, IDC_GENLOCKFILE, HISTORY_GENLOCK_IMAGE, true); + addhistorymenu(hDlg, workprefs.genlock_image_file, IDC_GENLOCKFILE, HISTORY_GENLOCK_IMAGE, true, -1); } else if (workprefs.genlock_image == 4 || workprefs.genlock_image >= 6) { - addhistorymenu(hDlg, workprefs.genlock_video_file, IDC_GENLOCKFILE, HISTORY_GENLOCK_VIDEO, true); + addhistorymenu(hDlg, workprefs.genlock_video_file, IDC_GENLOCKFILE, HISTORY_GENLOCK_VIDEO, true, -1); } } @@ -8924,7 +8937,7 @@ static INT_PTR CALLBACK ChipsetDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPAR TCHAR *p = workprefs.genlock_image == 3 ? workprefs.genlock_image_file : workprefs.genlock_video_file; getcomboboxtext(hDlg, IDC_GENLOCKFILE, p, MAX_DPATH); parsefilepath(p, MAX_DPATH); - addhistorymenu(hDlg, p, IDC_GENLOCKFILE, workprefs.genlock_image == 3 ? HISTORY_GENLOCK_IMAGE : HISTORY_GENLOCK_VIDEO, true); + addhistorymenu(hDlg, p, IDC_GENLOCKFILE, workprefs.genlock_image == 3 ? HISTORY_GENLOCK_IMAGE : HISTORY_GENLOCK_VIDEO, true, -1); break; } } @@ -12366,7 +12379,7 @@ static INT_PTR MiscDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) InitializeListView (hDlg); values_to_miscdlg (hDlg); enable_for_miscdlg (hDlg); - addhistorymenu(hDlg, NULL, IDC_STATENAME, HISTORY_STATEFILE, true); + addhistorymenu(hDlg, NULL, IDC_STATENAME, HISTORY_STATEFILE, true, -1); setstatefilename(hDlg); recursive--; return TRUE; @@ -13825,7 +13838,7 @@ static INT_PTR CALLBACK VolumeSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, archivehd = 0; recursive++; setautocomplete (hDlg, IDC_PATH_NAME); - addhistorymenu(hDlg, current_fsvdlg.ci.rootdir, IDC_PATH_NAME, HISTORY_DIR, false); + addhistorymenu(hDlg, current_fsvdlg.ci.rootdir, IDC_PATH_NAME, HISTORY_DIR, false, -1); SetDlgItemText (hDlg, IDC_VOLUME_NAME, current_fsvdlg.ci.volname); SetDlgItemText (hDlg, IDC_VOLUME_DEVICE, current_fsvdlg.ci.devname); SetDlgItemInt (hDlg, IDC_VOLUME_BOOTPRI, current_fsvdlg.ci.bootpri, TRUE); @@ -14408,7 +14421,7 @@ static INT_PTR CALLBACK TapeDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara inithdcontroller(hDlg, current_tapedlg.ci.controller_type, current_tapedlg.ci.controller_type_unit, UAEDEV_TAPE, current_tapedlg.ci.rootdir[0] != 0); SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_tapedlg.ci.controller_unit, 0); setautocomplete (hDlg, IDC_PATH_NAME); - addhistorymenu(hDlg, current_tapedlg.ci.rootdir, IDC_PATH_NAME, HISTORY_TAPE, false); + addhistorymenu(hDlg, current_tapedlg.ci.rootdir, IDC_PATH_NAME, HISTORY_TAPE, false, -1); readonly = !tape_can_write(current_tapedlg.ci.rootdir); CheckDlgButton (hDlg, IDC_TAPE_RW, current_tapedlg.ci.readonly == 0 && !readonly); ew (hDlg, IDC_TAPE_RW, !readonly); @@ -14620,10 +14633,10 @@ static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam setautocomplete (hDlg, IDC_PATH_NAME); setautocomplete (hDlg, IDC_PATH_FILESYS); setautocomplete (hDlg, IDC_PATH_GEOMETRY); - addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false); + addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false, -1); inithardfile (hDlg, current_hfdlg.ci.rootdir[0] != 0); - addhistorymenu(hDlg, current_hfdlg.ci.rootdir, IDC_PATH_NAME, HISTORY_HDF, false); - addhistorymenu(hDlg, current_hfdlg.ci.filesys, IDC_PATH_FILESYS, HISTORY_FS, false); + addhistorymenu(hDlg, current_hfdlg.ci.rootdir, IDC_PATH_NAME, HISTORY_HDF, false, -1); + addhistorymenu(hDlg, current_hfdlg.ci.filesys, IDC_PATH_FILESYS, HISTORY_FS, false, -1); updatehdfinfo (hDlg, true, false, false); sethardfile (hDlg); sethfdostype (hDlg, 0); @@ -14668,7 +14681,7 @@ static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam case IDC_PATH_GEOMETRY: getcomboboxtext(hDlg, IDC_PATH_GEOMETRY, current_hfdlg.ci.geometry, sizeof current_hfdlg.ci.geometry / sizeof(TCHAR)); if (HIWORD (wParam) == CBN_KILLFOCUS) { - addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false); + addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false, -1); sethardfile(hDlg); updatehdfinfo (hDlg, true, false, false); } @@ -14683,13 +14696,13 @@ static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam } } if (HIWORD (wParam) == CBN_KILLFOCUS) { - addhistorymenu(hDlg, current_hfdlg.ci.rootdir, IDC_PATH_NAME, HISTORY_HDF, false); + addhistorymenu(hDlg, current_hfdlg.ci.rootdir, IDC_PATH_NAME, HISTORY_HDF, false, -1); } break; case IDC_PATH_FILESYS: getcomboboxtext(hDlg, IDC_PATH_FILESYS, current_hfdlg.ci.filesys, sizeof current_hfdlg.ci.filesys / sizeof(TCHAR)); if (HIWORD(wParam) == CBN_KILLFOCUS) { - addhistorymenu(hDlg, current_hfdlg.ci.filesys, IDC_PATH_FILESYS, HISTORY_FS, false); + addhistorymenu(hDlg, current_hfdlg.ci.filesys, IDC_PATH_FILESYS, HISTORY_FS, false, -1); } break; } @@ -14892,7 +14905,7 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara hdf_init_target (); recursive++; setautocomplete (hDlg, IDC_PATH_GEOMETRY); - addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false); + addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false, -1); setchecked(hDlg, IDC_HDF_PHYSGEOMETRY, current_hfdlg.ci.physical_geometry); setharddrive(hDlg); inithdcontroller(hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF, current_hfdlg.ci.rootdir[0] != 0); @@ -14929,7 +14942,7 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara case IDC_PATH_GEOMETRY: getcomboboxtext(hDlg, IDC_PATH_GEOMETRY, current_hfdlg.ci.geometry, sizeof current_hfdlg.ci.geometry / sizeof(TCHAR)); if (HIWORD (wParam) == CBN_KILLFOCUS) { - addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false); + addhistorymenu(hDlg, current_hfdlg.ci.geometry, IDC_PATH_GEOMETRY, HISTORY_GEO, false, -1); setharddrive(hDlg); updatehdfinfo (hDlg, true, false, true); } @@ -15448,7 +15461,7 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA CheckDlgButton (hDlg, IDC_CD_SPEED, workprefs.cd_speed == 0); InitializeListView (hDlg); setautocomplete (hDlg, IDC_CD_TEXT); - addhistorymenu (hDlg, workprefs.cdslots[0].name, IDC_CD_TEXT, HISTORY_CD, true); + addhistorymenu (hDlg, workprefs.cdslots[0].name, IDC_CD_TEXT, HISTORY_CD, true, -1); addcdtype (hDlg, IDC_CD_TYPE); hilitehd (hDlg); break; @@ -15481,7 +15494,7 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA if (full_property_sheet) workprefs.cdslots[0].type = SCSI_UNIT_DEFAULT; addcdtype (hDlg, IDC_CD_TYPE); - addhistorymenu (hDlg, workprefs.cdslots[0].name, IDC_CD_TEXT, HISTORY_CD, true); + addhistorymenu (hDlg, workprefs.cdslots[0].name, IDC_CD_TEXT, HISTORY_CD, true, -1); InitializeListView (hDlg); hilitehd (hDlg); break; @@ -15511,7 +15524,7 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA } } addcdtype (hDlg, IDC_CD_TYPE); - addhistorymenu (hDlg, workprefs.cdslots[0].name, IDC_CD_TEXT, HISTORY_CD, true); + addhistorymenu (hDlg, workprefs.cdslots[0].name, IDC_CD_TEXT, HISTORY_CD, true, -1); InitializeListView (hDlg); hilitehd (hDlg); } @@ -15580,6 +15593,14 @@ static const int floppybuttonsq[][BUTTONSPERFLOPPY] = { { -1,-1,-1,-1,-1,-1,-1,-1 } }; +static int isfloppybridge(int type) +{ + if (type >= DRV_FB_A_35_DD) { + return type - DRV_FB_A_35_DD; + } + return -1; +} + static void floppytooltip (HWND hDlg, int num, uae_u32 crc32) { TOOLINFO ti; @@ -15606,7 +15627,20 @@ static void floppytooltip (HWND hDlg, int num, uae_u32 crc32) SendMessage (ToolTipHWND, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti); } -static void addhistorymenu(HWND hDlg, const TCHAR *text, int f_text, int type, bool manglepath) +static void updatedfname(HWND hDlg, const TCHAR *text, int f_text, int type, int num) +{ + if (type == HISTORY_FLOPPY && DISK_isfloppybridge(&workprefs, num)) { + TCHAR text2[MAX_DPATH]; + DISK_get_path_text(&workprefs, num, text2); + if (text) + SendDlgItemMessage(hDlg, f_text, WM_SETTEXT, 0, (LPARAM)text2); + } else { + if (text) + SendDlgItemMessage(hDlg, f_text, WM_SETTEXT, 0, (LPARAM)text); + } +} + +static void addhistorymenu(HWND hDlg, const TCHAR *text, int f_text, int type, bool manglepath, int num) { int i, j; TCHAR *s; @@ -15616,9 +15650,7 @@ static void addhistorymenu(HWND hDlg, const TCHAR *text, int f_text, int type, b if (f_text < 0) return; - SendDlgItemMessage (hDlg, f_text, CB_RESETCONTENT, 0, 0); - if (text) - SendDlgItemMessage (hDlg, f_text, WM_SETTEXT, 0, (LPARAM)text); + SendDlgItemMessage(hDlg, f_text, CB_RESETCONTENT, 0, 0); fkey = read_disk_history (type); if (fkey == NULL) return; @@ -15660,8 +15692,12 @@ static void addhistorymenu(HWND hDlg, const TCHAR *text, int f_text, int type, b if (text && !_tcscmp (text, s)) curidx = i - 1; } - if (f_text >= 0 && curidx >= 0) - SendDlgItemMessage (hDlg, f_text, CB_SETCURSEL, curidx, 0); + if (f_text >= 0) { + if (curidx >= 0) + SendDlgItemMessage(hDlg, f_text, CB_SETCURSEL, curidx, 0); + else + updatedfname(hDlg, text, f_text, type, num); + } regclosetree (fkey); } @@ -15688,7 +15724,7 @@ static void addfloppyhistory (HWND hDlg) TCHAR *name = workprefs.floppyslots[n].df; if (iscd(n)) name = workprefs.cdslots[0].name; - addhistorymenu (hDlg, name, f_text, iscd (n) ? HISTORY_CD : HISTORY_FLOPPY, true); + addhistorymenu(hDlg, name, f_text, iscd(n) ? HISTORY_CD : HISTORY_FLOPPY, true, n); } } } @@ -15723,39 +15759,133 @@ static void addcdtype (HWND hDlg, int id) SendDlgItemMessage (hDlg, id, CB_SETCURSEL, cdtype, 0); } -static int fromdfxtype(int dfx) +static int fromdfxtype(int num, int dfx) { - if (dfx == 7) - dfx = 3; - else if (dfx >= 3) - dfx++; - dfx++; - return dfx; -} - -static int todfxtype(int val) -{ - val--; - if (val == 3) - val = 7; - else if (val > 3) - val--; - return val; + switch (dfx) + { + case DRV_35_DD: + return 1; + case DRV_35_HD: + return 2; + case DRV_525_SD: + return 3; + case DRV_525_DD: + return 4; + case DRV_35_DD_ESCOM: + return 5; + } + if (num < 2) { + switch (dfx) + { + case DRV_FB_A_35_DD: + if (!floppybridge_has()) { + return 1; + } + return 6; + case DRV_FB_A_35_HD: + if (!floppybridge_has()) { + return 1; + } + return 7; + case DRV_FB_B_35_DD: + if (!floppybridge_has()) { + return 1; + } + return 8; + case DRV_FB_B_35_HD: + if (!floppybridge_has()) { + return 1; + } + return 9; + } +} else { + switch (dfx) + { + case DRV_PC_525_ONLY_40: + return 6; + case DRV_PC_525_40_80: + return 7; + case DRV_PC_35_ONLY_80: + return 8; + case DRV_FB_A_35_DD: + if (!floppybridge_has()) { + return 1; + } + return 9; + case DRV_FB_A_35_HD: + if (!floppybridge_has()) { + return 1; + } + return 10; + case DRV_FB_B_35_DD: + if (!floppybridge_has()) { + return 1; + } + return 11; + case DRV_FB_B_35_HD: + if (!floppybridge_has()) { + return 1; + } + return 11; + } + } + return 0; } -static int swapdrives(int v) +static int todfxtype(int num, int dfx) { - if (v == 7) - v = 8; - else if (v == 8) - v = 7; - return v; + switch (dfx) + { + case 1: + return DRV_35_DD; + case 2: + return DRV_35_HD; + case 3: + return DRV_525_SD; + case 4: + return DRV_525_DD; + case 5: + return DRV_35_DD_ESCOM; + } + if (num < 2) { + switch (dfx) + { + case 6: + return DRV_FB_A_35_DD; + case 7: + return DRV_FB_A_35_HD; + case 8: + return DRV_FB_B_35_DD; + case 9: + return DRV_FB_B_35_HD; + } + } else { + switch (dfx) + { + case 6: + return DRV_PC_525_ONLY_40; + case 7: + return DRV_PC_525_40_80; + case 8: + return DRV_PC_35_ONLY_80; + case 9: + return DRV_FB_A_35_DD; + case 10: + return DRV_FB_A_35_HD; + case 11: + return DRV_FB_A_35_DD; + case 12: + return DRV_FB_A_35_HD; + } + } + return -1; } static void addfloppytype (HWND hDlg, int n) { int state, chk; - int nn = fromdfxtype(workprefs.floppyslots[n].dfxtype); + int nn = fromdfxtype(n, workprefs.floppyslots[n].dfxtype); + int fb = DISK_isfloppybridge(&workprefs, n); int showcd = 0; TCHAR *text; @@ -15816,7 +15946,7 @@ static void addfloppytype (HWND hDlg, int n) else state = TRUE; if (f_type >= 0) { - SendDlgItemMessage(hDlg, f_type, CB_SETCURSEL, swapdrives(nn), 0); + SendDlgItemMessage(hDlg, f_type, CB_SETCURSEL, nn, 0); } if (f_si >= 0) { TCHAR *path = DISK_get_saveimagepath(text, -2); @@ -15824,11 +15954,11 @@ static void addfloppytype (HWND hDlg, int n) xfree(path); } if (f_text >= 0) - ew (hDlg, f_text, state); + ew (hDlg, f_text, state && !fb); if (f_eject >= 0) - ew (hDlg, f_eject, text[0] != 0); + ew (hDlg, f_eject, text[0] != 0 && !fb); if (f_drive >= 0) - ew (hDlg, f_drive, state); + ew (hDlg, f_drive, state && !fb); if (f_enable >= 0) { if (currentpage == QUICKSTART_ID) { ew (hDlg, f_enable, (n > 0 && workprefs.nr_floppies > 0) && !showcd); @@ -15848,12 +15978,14 @@ static void addfloppytype (HWND hDlg, int n) if (tmp[0]) SetWindowText(GetDlgItem(hDlg, f_enable), tmp); } - chk = !showcd && disk_getwriteprotect (&workprefs, text) && state == TRUE ? BST_CHECKED : 0; - if (f_wp >= 0) - CheckDlgButton (hDlg, f_wp, chk); + chk = !showcd && disk_getwriteprotect (&workprefs, text, n) && state == TRUE ? BST_CHECKED : 0; + if (f_wp >= 0) { + CheckDlgButton(hDlg, f_wp, chk); + ew(hDlg, f_wp, !fb); + } if (f_info >= 0) - ew (hDlg, f_info, text[0] != 0); - chk = !showcd && state && DISK_validate_filename (&workprefs, text, NULL, 0, NULL, NULL, NULL) ? TRUE : FALSE; + ew (hDlg, f_info, text[0] != 0 || fb); + chk = !showcd && state && DISK_validate_filename (&workprefs, text, n, NULL, 0, NULL, NULL, NULL) ? TRUE : FALSE; if (f_wp >= 0) { ew (hDlg, f_wp, chk && !workprefs.floppy_read_only); if (f_wptext >= 0) @@ -15861,16 +15993,24 @@ static void addfloppytype (HWND hDlg, int n) } } -static void getfloppytype (HWND hDlg, int n) +static void getfloppytype(HWND hDlg, int n) { + int f_text = floppybuttons[n][0]; int f_type = floppybuttons[n][3]; - LRESULT val = SendDlgItemMessage (hDlg, f_type, CB_GETCURSEL, 0, 0L); + LRESULT val = SendDlgItemMessage(hDlg, f_type, CB_GETCURSEL, 0, 0L); - val = swapdrives(val); - - if (val != CB_ERR && workprefs.floppyslots[n].dfxtype != todfxtype(val)) { - workprefs.floppyslots[n].dfxtype = todfxtype(val); - addfloppytype (hDlg, n); + if (val != CB_ERR && workprefs.floppyslots[n].dfxtype != todfxtype(n, val)) { + workprefs.floppyslots[n].dfxtype = todfxtype(n, val); + workprefs.floppyslots[n].config[0] = 0; + for (int i = 0; i < 4; i++) { + if (i != n && DISK_isfloppybridge(&workprefs, i) && DISK_isfloppybridge(&workprefs, n)) { + workprefs.floppyslots[n].dfxtype = DRV_35_DD; + } + } + floppybridge_init(&workprefs); + addfloppytype(hDlg, n); + addhistorymenu(hDlg, NULL, f_text, HISTORY_FLOPPY, true, n); + updatedfname(hDlg, workprefs.floppyslots[n].df, f_text, HISTORY_FLOPPY, n); } } static void getfloppytypeq (HWND hDlg, int n) @@ -15896,33 +16036,42 @@ static void getfloppytypeq (HWND hDlg, int n) } } -static int getfloppybox (HWND hDlg, int f_text, TCHAR *out, int maxlen, int type) +static int getfloppybox (HWND hDlg, int f_text, TCHAR *out, int maxlen, int type, int num) { LRESULT val; TCHAR *p; int i; - out[0] = 0; - val = SendDlgItemMessage (hDlg, f_text, CB_GETCURSEL, 0, 0L); - if (val != CB_ERR) { - int len = SendDlgItemMessage(hDlg, f_text, CB_GETLBTEXTLEN, (WPARAM)val, 0); - if (len < maxlen) { - val = SendDlgItemMessage (hDlg, f_text, CB_GETLBTEXT, (WPARAM)val, (LPARAM)out); - } + if (num >= 0 && DISK_isfloppybridge(&workprefs, num)) { + + out[0] = 0; + } else { - SendDlgItemMessage (hDlg, f_text, WM_GETTEXT, (WPARAM)maxlen, (LPARAM)out); - } - parsefilepath(out, maxlen); + out[0] = 0; + val = SendDlgItemMessage(hDlg, f_text, CB_GETCURSEL, 0, 0L); + if (val != CB_ERR) { + int len = SendDlgItemMessage(hDlg, f_text, CB_GETLBTEXTLEN, (WPARAM)val, 0); + if (len < maxlen) { + val = SendDlgItemMessage(hDlg, f_text, CB_GETLBTEXT, (WPARAM)val, (LPARAM)out); + } + } else { + SendDlgItemMessage(hDlg, f_text, WM_GETTEXT, (WPARAM)maxlen, (LPARAM)out); + } - i = 0; - while ((p = DISK_history_get (i, type))) { - if (!_tcscmp (p, out)) { - DISK_history_add (out, -1, type, 0); - break; + parsefilepath(out, maxlen); + + i = 0; + while ((p = DISK_history_get(i, type))) { + if (!_tcscmp(p, out)) { + DISK_history_add(out, -1, type, 0); + break; + } + i++; } - i++; + } + return out[0] ? 1 : 0; } @@ -15939,7 +16088,7 @@ static void getfloppyname (HWND hDlg, int n, int cd, int f_text) { TCHAR tmp[MAX_DPATH]; - if (getfloppybox (hDlg, f_text, tmp, sizeof (tmp) / sizeof (TCHAR), cd ? HISTORY_CD : HISTORY_FLOPPY)) { + if (getfloppybox (hDlg, f_text, tmp, sizeof (tmp) / sizeof (TCHAR), cd ? HISTORY_CD : HISTORY_FLOPPY, n)) { if (!cd) { disk_insert (n, tmp); _tcscpy (workprefs.floppyslots[n].df, tmp); @@ -16094,9 +16243,16 @@ static INT_PTR CALLBACK FloppyDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARA SendDlgItemMessage (hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("5.25\" (80)")); SendDlgItemMessage (hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)ft35ddescom); if (i >= 2) { - SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("Bridge 5.25\" 40")); - SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("Bridge 5.25\" 80")); - SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("Bridge 3.5\" 80")); + SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("Bridgeboard 5.25\" 40")); + SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("Bridgeboard 5.25\" 80")); + SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("Bridgeboard 3.5\" 80")); + } + if (floppybridge_has()) { + floppybridge_init(&workprefs); + SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("FloppyBridge A: 3.5\" DD")); + SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("FloppyBridge A: 3.5\" HD")); + SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("FloppyBridge B: 3.5\" DD")); + SendDlgItemMessage(hDlg, f_type, CB_ADDSTRING, 0, (LPARAM)_T("FloppyBridge B: 3.5\" HD")); } } setmultiautocomplete (hDlg, df0texts); @@ -16527,7 +16683,7 @@ static INT_PTR CALLBACK SwapperDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPAR case IDC_DISKLISTINSERT: if (entry >= 0) { - if (getfloppybox (hDlg, IDC_DISKTEXT, tmp, sizeof (tmp) / sizeof (TCHAR), HISTORY_FLOPPY)) { + if (getfloppybox (hDlg, IDC_DISKTEXT, tmp, sizeof (tmp) / sizeof (TCHAR), HISTORY_FLOPPY, -1)) { _tcscpy (workprefs.dfxlist[entry], tmp); addfloppyhistory (hDlg); InitializeListView (hDlg); diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj b/od-win32/winuae_msvc15/winuae_msvc.vcxproj index 4f0225a9..95f0e2da 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj @@ -927,6 +927,7 @@ + diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters index 5b01b9eb..7eb12d70 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters @@ -982,6 +982,9 @@ pcem + + common + diff --git a/savestate.cpp b/savestate.cpp index 2ed1d8b9..5d7ad11d 100644 --- a/savestate.cpp +++ b/savestate.cpp @@ -1864,7 +1864,7 @@ retry2: input_record++; for (i = 0; i < 4; i++) { bool wp = true; - DISK_validate_filename (&currprefs, currprefs.floppyslots[i].df, NULL, false, &wp, NULL, NULL); + DISK_validate_filename (&currprefs, currprefs.floppyslots[i].df, i, NULL, false, &wp, NULL, NULL); inprec_recorddiskchange (i, currprefs.floppyslots[i].df, wp); } input_record--; diff --git a/statusline.cpp b/statusline.cpp index 1dcf17b8..bc010d5b 100644 --- a/statusline.cpp +++ b/statusline.cpp @@ -206,7 +206,7 @@ void draw_status_line_single(int monid, uae_u8 *buf, int bpp, int y, int totalwi on_rgb = 0xcc0000; } half = gui_data.drive_side ? 1 : -1; - if (gid->df[0] == 0) { + if (!gid->floppy_inserted) { pen_rgb = ledcolor(0x00aaaaaa, rc, gc, bc, alpha); } else if (gid->floppy_protected) { cb = ledcolor(0x00cc00, rc, gc, bc, alpha);