From 42fb1ed1d00c1dc0ef7de8839912aa37bd373e9e Mon Sep 17 00:00:00 2001 From: "Howard M. Harte" Date: Sun, 17 Aug 2025 14:50:44 -0700 Subject: [PATCH] AltairZ80: wd179x: Better support for 5.25-inch floppies. --- AltairZ80/s100_64fdc.c | 4 ++++ AltairZ80/wd179x.c | 40 +++++++++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/AltairZ80/s100_64fdc.c b/AltairZ80/s100_64fdc.c index e8ca326f4..742dc4e09 100644 --- a/AltairZ80/s100_64fdc.c +++ b/AltairZ80/s100_64fdc.c @@ -82,6 +82,7 @@ extern t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc); extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, CONST void *desc); extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, int32 (*routine)(const int32, const int32, const int32), const char* name, uint8 unmap); +void wd179x_set_rpm(int rpm); static t_stat cromfdc_svc (UNIT *uptr); @@ -1586,8 +1587,10 @@ static int32 cromfdc_control(const int32 port, const int32 io, const int32 data) } if(data & CROMFDC_CTRL_MAXI) { wd179x_infop->drivetype = 8; + wd179x_set_rpm(360); } else { wd179x_infop->drivetype = 5; + wd179x_set_rpm(300); } if(data & CROMFDC_CTRL_MTRON) { @@ -1611,6 +1614,7 @@ static int32 cromfdc_control(const int32 port, const int32 io, const int32 data) } sim_debug(DRIVE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT " WR CTRL: sel_drive=%d, drivetype=%d, motor=%d, dens=%d, aw=%d\n", PCX, wd179x_infop->sel_drive, wd179x_infop->drivetype, cromfdc_info->motor_on, wd179x_infop->ddens, cromfdc_info->autowait); + } else { /* I/O Read */ result = (crofdc_boot) ? 0 : CROMFDC_FLAG_BOOT; result |= (wd179x_infop->intrq) ? CROMFDC_FLAG_EOJ : 0; diff --git a/AltairZ80/wd179x.c b/AltairZ80/wd179x.c index 78354f853..deabf8bb5 100644 --- a/AltairZ80/wd179x.c +++ b/AltairZ80/wd179x.c @@ -93,11 +93,12 @@ typedef union { typedef struct { UNIT *uptr; DISK_INFO *imd; - uint8 ntracks; /* number of tracks */ - uint8 nheads; /* number of heads */ - uint32 sectsize; /* sector size, not including pre/postamble */ - uint8 track; /* Current Track */ - uint8 ready; /* Is drive ready? */ + uint8 ntracks; /* number of tracks */ + uint8 nheads; /* number of heads */ + uint32 sectsize; /* sector size, not including pre/postamble */ + uint8 track; /* Current Track */ + uint8 ready; /* Is drive ready? */ + int rpm; /* Drive RPM */ } WD179X_DRIVE_INFO; typedef struct { @@ -338,6 +339,14 @@ static t_stat wd179x_reset(DEVICE *dptr) return SCPE_OK; } +void wd179x_set_rpm(int rpm) +{ + if (wd179x_info->sel_drive > WD179X_MAX_DRIVES) { + return; + } + wd179x_info->drive[wd179x_info->sel_drive & 3].rpm = rpm; +} + void wd179x_connect_external_fifo(uint16 fifo_len, uint8* storage) { wd179x_info->external_fifo_len = fifo_len; @@ -1210,11 +1219,24 @@ static uint8 Do1793Command(uint8 cCommand) if (cCommand & 0x04) { wd179x_info->index_pulse_wait = TRUE; if (wd179x_info->sel_drive < WD179X_MAX_DRIVES) { - if (pDrive->uptr->u3 == IMAGE_TYPE_IMD) { - sim_activate (wd179x_unit, ((wd179x_info->drive[wd179x_info->sel_drive].imd->ntracks % 77) == 0) ? CROMFDC_8IN_ROT : CROMFDC_5IN_ROT); /* Generate INDEX pulse */ - } else { - sim_activate(wd179x_unit, CROMFDC_8IN_ROT); /* Generate INDEX pulse */ + int rot = 0; + + switch (pDrive->rpm) { + case 300: + rot = CROMFDC_5IN_ROT; + break; + case 360: + rot = CROMFDC_8IN_ROT; + break; + default: /* RPM not set, infer from the disk image, if possible. */ + if (pDrive->uptr->u3 == IMAGE_TYPE_IMD) { + rot = ((wd179x_info->drive[wd179x_info->sel_drive].imd->ntracks % 77) == 0) ? CROMFDC_8IN_ROT : CROMFDC_5IN_ROT; + } + else { + rot = CROMFDC_8IN_ROT; + } } + sim_activate(wd179x_unit, rot); /* Generate INDEX pulse */ } } else { wd179x_info->intrq = 1;