{
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);
_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;
}
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)) {
#include "statusline.h"
#include "rommgr.h"
#include "tinyxml2.h"
+#ifdef FLOPPYBRIDGE
+#include "floppybridge/floppybridge_abstract.h"
+#include "floppybridge/floppybridge_lib.h"
+#endif
#undef CATWEASEL
#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;
bool track_access_done;
bool fourms;
#endif
+#ifdef FLOPPYBRIDGE
+ FloppyDiskBridge *bridge;
+#endif
} drive;
#define MIN_STEPLIMIT_CYCLE (CYCLE_UNIT * 140)
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<FloppyBridgeAPI::DriverInformation> 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;
{
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;
{
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:
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;
_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);
}
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];
*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)
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;
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);
{
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)) {
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;
*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);
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);
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;
drv->dskready_down_time = 0;
}
- if (drv->diskfile == NULL && !drv->catweasel) {
+ if (drv->diskfile == NULL && !drv->catweasel && !drv->bridge) {
track_reset (drv);
return 0;
}
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) {
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;
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) {
#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);
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);
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;
}
}
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);
} 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);
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;
}
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;
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;
}
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)
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;
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]);
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) {
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;
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) */
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))) {
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;
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);
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
}
}
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();
}
}
}
}
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];
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)
}
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;
}
}
}
+
+#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;
}
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) {
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) {
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;
}
}
}
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;
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;
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;
}
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;
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;
}
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;
} 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);
}
}
+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--) {
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 ();
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;
}
}
-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;
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;
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 &&
drv->dskchange_time = wasdelayed;
disk_insert (num, drv->newname);
}
+ load_track(num, oldcyl, oldside, sectable);
return ret;
}
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 */
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
--- /dev/null
+/* 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 <http://unlicense.org>.
+*
+*/
+
+/*
+* This file, along with currently active and supported interfaces
+* are maintained from by GitHub repo at
+* https://github.com/RobSmithDev/FloppyDriveBridge
+*/
+
+#pragma once
+
+#include <functional>
+
+#ifdef _WIN32
+#include <tchar.h>
+#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;
+};
+
+
--- /dev/null
+/* 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 <http://unlicense.org>.
+*
+*/
+
+#include "floppybridge_lib.h"
+#include <string>
+#include <codecvt>
+#include <locale>
+#include <algorithm>
+
+
+// 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 <Windows.h>
+#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<wchar_t>;
+static std::wstring_convert<convert_t, wchar_t> 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<std::wstring> memoryPortList;
+#else
+std::vector<std::string> 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<DriverInformation>& 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<const TCHAR*>& 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
--- /dev/null
+/* 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 <http://unlicense.org>.
+*
+*/
+
+#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<DriverInformation>& 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<const TCHAR*>& 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
#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
{
uae_u8 bootblock[1024];
bool bb_crc_valid;
+ bool image_crc_value;
uae_u32 imagecrc32;
uae_u32 bootblockcrc32;
bool hd;
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*);
#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 */
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
int dfxclick;
TCHAR dfxclickexternal[256];
bool forcedwriteprotect;
+ TCHAR config[256];
};
#define ASPECTMULT 1024
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);
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
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
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
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
#define WITH_PCI
#define WITH_X86
#define WITH_THREADED_CPU
+#define FLOPPYBRIDGE
#else
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);
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);
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 {
}
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);
{
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);
}
}
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;
}
}
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;
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);
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);
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);
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);
}
}
}
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;
}
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);
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);
}
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;
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;
}
}
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);
}
{ -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;
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;
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;
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);
}
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);
}
}
}
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;
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);
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);
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)
}
}
-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)
}
}
-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;
}
{
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);
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);
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);
<ClCompile Include="..\..\ethernet.cpp" />
<ClCompile Include="..\..\events.cpp" />
<ClCompile Include="..\..\flashrom.cpp" />
+ <ClCompile Include="..\..\floppybridge\floppybridge_lib.cpp" />
<ClCompile Include="..\..\fpp_native.cpp" />
<ClCompile Include="..\..\fpp_softfloat.cpp" />
<ClCompile Include="..\..\framebufferboards.cpp" />
<ClCompile Include="..\..\pcem\vid_voodoo.cpp">
<Filter>pcem</Filter>
</ClCompile>
+ <ClCompile Include="..\..\floppybridge\floppybridge_lib.cpp">
+ <Filter>common</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\resources\35floppy.ico">
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--;
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);