Fixes #6220 floppy disk issues with OS/2 and NT 3.1 systems (#6232)

* Initial spindle emulation working for windows atleast

* Spingle motor spin-up, spin-down implemented with smooth transitions to motor-on loop.

* Moved fdd audio emulation to a separate file

* Multiple drives sound emulation

* Single sector movement sound emulations implemented

* Rename project to Immersive86Box and update details

Updated README to reflect the new project name and added details about the Immersive86Box features and future plans.

* Revise contribution guidelines in CONTRIBUTING.md

* Update vulnerability reporting instructions

* System fan-sound next feature after basic fdd sound emulation is ready

* v0.5 multitrack audio seek sfx

* Removed unnecessary stuff

* no .vs folder for git

* Added currently used fdd sound effects and readme.txt for source of the files and intallation instructions

* Add audio emulation installation instructions

Added instructions for audio emulation installation.

* Code and audio samples merged

* Simplify audio emulation installation instructions

* FDC seeking fixed, not instant anymore drive is set to busy during the operation and when it's finished at call fdc to set the appropriate fdc flags.

Also added time logic to fdd to calculate seek duration and a callback function for it.

* FDD sound samples volume control

* Menu options to enable / disable fdd sound for all drives.
DISABLE_FDD_AUDIO definition added, to disable the feature via cmake/build.

* Revert readme etc. changes

* Revert "Revise contribution guidelines in CONTRIBUTING.md"

This reverts commit 98a0478225.

* Revert "Update vulnerability reporting instructions"

This reverts commit 7d32cb659b.

* Fixed merge issue

* Removed excess files

* Fixed PCJr seeking not to break the FDC implementation. Now seeking will take the "correct" amount of time for each system and the seek time is based on the track count. E.g. 40 track FDD system causes 40 track seek time to be 80/40 * 6ms * 40 tracks + 50ms = 480ms + 50ms -> 530ms.

80 track system full seek is 80/80 * 6ms * 80 + 50ms = 530ms, 40 track seek would take 240 + 50 = 290ms.

* Fixed PS/1, PS/2 and PS/55 FDD issues.

* FDD_AUDIO: Updating samples looked in executablePath/samples and if now found there, looks in the executable directory

* Updated installation instructions

* Removed samples path strcat use

* fdd_audio 5.25 samples and support added

* FDD audio timing/volume tunings

* Timing fixes for authentity and special longer timings for PCJr

* Fixed second drive motor keeps running when first drive is only accessed.

* Fixed PCJr random failure issue, timings

* CodeQL fix for load_wav-function. Check the filename to be proper filename

* Revert "Fixed second drive motor keeps running when first drive is only accessed."

This reverts commit 307b173ae7.

* Teac 5.25" drive samples added. Added per drive audio selection to FDD settings.

* Fixes merge problem

* Fixes #6220: OS/2 Warp 3.0 install disk issue and NT 3.1 floppy disk issues. Changed the fdc->stat bit to 0x10 which states fdc busy. Previous implementation with seek time 0, set the ready flag 0x80 immediadely - which was correct for that time, but now as the drive is busy during seek, the value should 0x10. Implemented a backup for fdd commands during fdd seek to be processes after the seek is completed.

---------

Co-authored-by: Toni Riikonen <domppari@hotmail.com>
This commit is contained in:
Toni Riikonen
2025-09-27 11:51:38 +03:00
committed by GitHub
parent 809e1f3efb
commit 836f855683
3 changed files with 914 additions and 760 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -79,11 +79,34 @@ typedef struct fdd_t {
fdd_t fdd[FDD_NUM];
enum {
FDD_OP_NONE = 0,
FDD_OP_READ,
FDD_OP_WRITE,
FDD_OP_COMPARE,
FDD_OP_READADDR,
FDD_OP_FORMAT
};
typedef struct fdd_pending_op_t {
int pending;
int op;
int sector;
int track;
int side;
int density;
int sector_size;
uint8_t fill;
} fdd_pending_op_t;
static fdd_pending_op_t fdd_pending[FDD_NUM];
char floppyfns[FDD_NUM][512];
char *fdd_image_history[FDD_NUM][FLOPPY_IMAGE_HISTORY];
pc_timer_t fdd_poll_time[FDD_NUM];
pc_timer_t fdd_seek_timer[FDD_NUM];
int fdd_seek_in_progress[FDD_NUM] = { 0, 0, 0, 0 };
static int fdd_notfound = 0;
static int driveloaders[FDD_NUM];
@@ -293,10 +316,49 @@ fdd_seek_complete_callback(void *priv)
{
DRIVE *drive = (DRIVE *) priv;
fdd_seek_in_progress[drive->id] = 0;
fdd_log("fdd_seek_complete_callback(drive=%d) - TIMER FIRED! seek_in_progress=1\n", drive->id);
fdd_log("Notifying FDC of seek completion\n");
fdd_do_seek(drive->id, fdd[drive->id].track);
fdc_seek_complete_interrupt(fdd_fdc, drive->id);
int had_pending = fdd_pending[drive->id].pending;
if (had_pending) {
fdd_pending_op_t *po = &fdd_pending[drive->id];
fdd_log("Starting deferred op %d after seek on drive %d (trk=%d, side=%d, sec=%d)\n",
po->op, drive->id, po->track, po->side, po->sector);
switch (po->op) {
case FDD_OP_READ:
if (drives[drive->id].readsector)
drives[drive->id].readsector(drive->id, po->sector, po->track, po->side, po->density, po->sector_size);
break;
case FDD_OP_WRITE:
if (drives[drive->id].writesector)
drives[drive->id].writesector(drive->id, po->sector, po->track, po->side, po->density, po->sector_size);
break;
case FDD_OP_COMPARE:
if (drives[drive->id].comparesector)
drives[drive->id].comparesector(drive->id, po->sector, po->track, po->side, po->density, po->sector_size);
break;
case FDD_OP_READADDR:
if (drives[drive->id].readaddress)
drives[drive->id].readaddress(drive->id, po->side, po->density);
break;
case FDD_OP_FORMAT:
if (drives[drive->id].format)
drives[drive->id].format(drive->id, po->side, po->density, po->fill);
break;
default:
break;
}
po->pending = 0;
po->op = FDD_OP_NONE;
}
if (!had_pending)
fdc_seek_complete_interrupt(fdd_fdc, drive->id);
}
void
@@ -306,6 +368,11 @@ fdd_seek(int drive, int track_diff)
if (!track_diff)
return;
if (fdd_seek_in_progress[drive]) {
fdd_log("Seek already in progress for drive %d, ignoring new seek request\n", drive);
return;
}
int old_track = fdd[drive].track;
fdd[drive].track += track_diff;
@@ -327,12 +394,14 @@ fdd_seek(int drive, int track_diff)
/* Multi-track seek */
fdd_audio_play_multi_track_seek(drive, old_track, fdd[drive].track);
}
if (old_track + track_diff < 0) {
fdd_do_seek(drive, fdd[drive].track);
return;
}
fdd_seek_in_progress[drive] = 1;
if (!fdd_seek_timer[drive].callback) {
timer_add(&(fdd_seek_timer[drive]), fdd_seek_complete_callback, &drives[drive], 0);
}
@@ -629,7 +698,7 @@ fdd_set_motor_enable(int drive, int motor_enable)
{
fdd_log("fdd_set_motor_enable(%d, %d)\n", drive, motor_enable);
fdd_audio_set_motor_enable(drive, motor_enable);
if (motor_enable && !motoron[drive]) {
timer_set_delay_u64(&fdd_poll_time[drive], fdd_byteperiod(drive));
} else if (!motor_enable && motoron[drive]) {
@@ -700,6 +769,22 @@ void
fdd_readsector(int drive, int sector, int track, int side, int density, int sector_size)
{
fdd_log("fdd_readsector(%d, %d, %d, %d, %d, %d)\n", drive, sector, track, side, density, sector_size);
if (fdd_seek_in_progress[drive]) {
fdd_log("Seek in progress on drive %d, deferring READ (trk=%d->%d, side=%d, sec=%d)\n",
drive, fdd[drive].track, track, side, sector);
fdd_pending[drive] = (fdd_pending_op_t) {
.pending = 1,
.op = FDD_OP_READ,
.sector = sector,
.track = track,
.side = side,
.density = density,
.sector_size = sector_size
};
return;
}
if (drives[drive].readsector)
drives[drive].readsector(drive, sector, track, side, density, sector_size);
else
@@ -710,6 +795,22 @@ void
fdd_writesector(int drive, int sector, int track, int side, int density, int sector_size)
{
fdd_log("fdd_writesector(%d, %d, %d, %d, %d, %d)\n", drive, sector, track, side, density, sector_size);
if (fdd_seek_in_progress[drive]) {
fdd_log("Seek in progress on drive %d, deferring WRITE (trk=%d->%d, side=%d, sec=%d)\n",
drive, fdd[drive].track, track, side, sector);
fdd_pending[drive] = (fdd_pending_op_t) {
.pending = 1,
.op = FDD_OP_WRITE,
.sector = sector,
.track = track,
.side = side,
.density = density,
.sector_size = sector_size
};
return;
}
if (drives[drive].writesector)
drives[drive].writesector(drive, sector, track, side, density, sector_size);
else
@@ -719,6 +820,21 @@ fdd_writesector(int drive, int sector, int track, int side, int density, int sec
void
fdd_comparesector(int drive, int sector, int track, int side, int density, int sector_size)
{
if (fdd_seek_in_progress[drive]) {
fdd_log("Seek in progress on drive %d, deferring COMPARE (trk=%d->%d, side=%d, sec=%d)\n",
drive, fdd[drive].track, track, side, sector);
fdd_pending[drive] = (fdd_pending_op_t) {
.pending = 1,
.op = FDD_OP_COMPARE,
.sector = sector,
.track = track,
.side = side,
.density = density,
.sector_size = sector_size
};
return;
}
if (drives[drive].comparesector)
drives[drive].comparesector(drive, sector, track, side, density, sector_size);
else
@@ -728,6 +844,19 @@ fdd_comparesector(int drive, int sector, int track, int side, int density, int s
void
fdd_readaddress(int drive, int side, int density)
{
if (fdd_seek_in_progress[drive]) {
fdd_log("Seek in progress on drive %d, deferring READADDRESS (trk=%d, side=%d)\n",
drive, fdd[drive].track, side);
fdd_pending[drive] = (fdd_pending_op_t) {
.pending = 1,
.op = FDD_OP_READADDR,
.track = fdd[drive].track,
.side = side,
.density = density
};
return;
}
if (drives[drive].readaddress)
drives[drive].readaddress(drive, side, density);
}
@@ -735,6 +864,20 @@ fdd_readaddress(int drive, int side, int density)
void
fdd_format(int drive, int side, int density, uint8_t fill)
{
if (fdd_seek_in_progress[drive]) {
fdd_log("Seek in progress on drive %d, deferring FORMAT (trk=%d, side=%d)\n",
drive, fdd[drive].track, side);
fdd_pending[drive] = (fdd_pending_op_t) {
.pending = 1,
.op = FDD_OP_FORMAT,
.track = fdd[drive].track,
.side = side,
.density = density,
.fill = fill
};
return;
}
if (drives[drive].format)
drives[drive].format(drive, side, density, fill);
else
@@ -777,7 +920,7 @@ fdd_init(void)
if (fdd_sounds_enabled) {
fdd_audio_init();
}
}
}
void

View File

@@ -176,6 +176,7 @@ static int16_t *
load_wav(const char *filename, int *sample_count)
{
FILE *f = NULL;
char full_path[2048];
if ((filename == NULL) || (strlen(filename) == 0))
return NULL;