mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 18:08:20 -07:00
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.
This commit is contained in:
BIN
samples/mitsumi_offseek_80_tracks_1000ms_48000_16_1_PCM.wav
Normal file
BIN
samples/mitsumi_offseek_80_tracks_1000ms_48000_16_1_PCM.wav
Normal file
Binary file not shown.
@@ -664,6 +664,28 @@ real_drive(fdc_t *fdc, int drive)
|
||||
return drive;
|
||||
}
|
||||
|
||||
/* FDD notifies FDC when seek operation is complete */
|
||||
void
|
||||
fdc_seek_complete_interrupt(fdc_t *fdc, int drive)
|
||||
{
|
||||
if (!fdc) {
|
||||
fdc_log("ERROR: fdc_seek_complete_interrupt called with NULL fdc!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fdc_log("FDD %c: Seek complete interrupt\n", 0x41 + drive);
|
||||
|
||||
fdc->fintr = 1;
|
||||
fdc->st0 = 0x20 | (drive & 3);
|
||||
|
||||
if (fdd_get_head(drive))
|
||||
fdc->st0 |= 0x04;
|
||||
|
||||
fdc_int(fdc, 1);
|
||||
|
||||
fdc->stat = (fdc->stat & 0xf) | 0x80;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_seek(fdc_t *fdc, int drive, int params)
|
||||
{
|
||||
@@ -1231,7 +1253,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x0f: /* Seek */
|
||||
fdc->rw_drive = fdc->params[0] & 3;
|
||||
fdc->stat = (1 << fdc->drive);
|
||||
if (!(fdc->flags & FDC_FLAG_PCJR))
|
||||
if (!(fdc->flags & FDC_FLAG_PCJR))
|
||||
fdc->stat |= 0x80;
|
||||
fdc->head = 0; /* TODO: See if this is correct. */
|
||||
fdc->st0 = fdc->params[0] & 0x03;
|
||||
@@ -1909,7 +1931,10 @@ fdc_callback(void *priv)
|
||||
timer_set_delay_u64(&fdc->timer, 1024 * TIMER_USEC);
|
||||
} else {
|
||||
fdc->interrupt = -3;
|
||||
fdc_callback(fdc);
|
||||
// 10 seconds before timeout -> error, Usually BIOS gets angry before this happens
|
||||
// FDD does the seeking and calls callback when done
|
||||
timer_set_delay_u64(&fdc->timer, 1024 * 1024 * 10 * TIMER_USEC);
|
||||
// fdc_callback(fdc); // Immediate callback causes seek to be instant
|
||||
}
|
||||
return;
|
||||
case 0x10: /*Version*/
|
||||
|
||||
@@ -83,6 +83,7 @@ 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];
|
||||
|
||||
static int fdd_notfound = 0;
|
||||
static int driveloaders[FDD_NUM];
|
||||
@@ -187,11 +188,32 @@ int fdd_do_log = ENABLE_FDD_LOG;
|
||||
static void
|
||||
fdd_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap, ap_copy;
|
||||
char timebuf[32];
|
||||
char fullbuf[1056]; // 32 + 1024 bytes for timestamp + message
|
||||
|
||||
if (fdd_do_log) {
|
||||
uint32_t ticks = plat_get_ticks();
|
||||
uint32_t seconds = ticks / 1000;
|
||||
uint32_t milliseconds = ticks % 1000;
|
||||
|
||||
snprintf(timebuf, sizeof(timebuf), "[%07u.%03u] ", seconds, milliseconds);
|
||||
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_copy(ap_copy, ap);
|
||||
|
||||
strcpy(fullbuf, timebuf);
|
||||
vsnprintf(fullbuf + strlen(timebuf), sizeof(fullbuf) - strlen(timebuf), fmt, ap_copy);
|
||||
|
||||
va_end(ap_copy);
|
||||
va_end(ap);
|
||||
|
||||
va_start(ap, fmt);
|
||||
va_end(ap);
|
||||
|
||||
char *msg = fullbuf;
|
||||
va_start(ap, fmt);
|
||||
pclog_ex("%s", (va_list) &msg);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
@@ -247,9 +269,21 @@ fdd_forced_seek(int drive, int track_diff)
|
||||
fdd_do_seek(drive, fdd[drive].track);
|
||||
}
|
||||
|
||||
static void
|
||||
fdd_seek_complete_callback(void *priv)
|
||||
{
|
||||
DRIVE *drive = (DRIVE *) priv;
|
||||
|
||||
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");
|
||||
|
||||
fdc_seek_complete_interrupt(fdd_fdc, drive->id);
|
||||
}
|
||||
|
||||
void
|
||||
fdd_seek(int drive, int track_diff)
|
||||
{
|
||||
fdd_log("fdd_seek(drive=%d, track_diff=%d)\n", drive, track_diff);
|
||||
if (!track_diff)
|
||||
return;
|
||||
|
||||
@@ -274,13 +308,23 @@ fdd_seek(int drive, int track_diff)
|
||||
/* Multi-track seek */
|
||||
fdd_audio_play_multi_track_seek(drive, old_track, fdd[drive].track);
|
||||
}
|
||||
|
||||
|
||||
// Count actual seek time (6ms per track + 50ms base)
|
||||
// 80 tracks -> 50 + 6 * 80 = 530ms
|
||||
uint64_t seek_time_us = (50000 + (abs(track_diff) * 6000)) * TIMER_USEC;
|
||||
if (!fdd_seek_timer[drive].callback) {
|
||||
timer_add(&(fdd_seek_timer[drive]), fdd_seek_complete_callback, &drives[drive], 0);
|
||||
}
|
||||
|
||||
timer_set_delay_u64(&fdd_seek_timer[drive], seek_time_us);
|
||||
fdd_do_seek(drive, fdd[drive].track);
|
||||
}
|
||||
|
||||
int
|
||||
fdd_track0(int drive)
|
||||
{
|
||||
fdd_log("fdd_track0(drive=%d)\n", drive);
|
||||
|
||||
/* If drive is disabled, TRK0 never gets set. */
|
||||
if (!drive_types[fdd[drive].type].max_track)
|
||||
return 0;
|
||||
@@ -423,6 +467,7 @@ fdd_is_double_sided(int drive)
|
||||
void
|
||||
fdd_set_head(int drive, int head)
|
||||
{
|
||||
fdd_log("fdd_set_head(%d, %d)\n", drive, head);
|
||||
if (head && !fdd_is_double_sided(drive))
|
||||
fdd[drive].head = 0;
|
||||
else
|
||||
@@ -470,6 +515,7 @@ fdd_get_densel(int drive)
|
||||
void
|
||||
fdd_load(int drive, char *fn)
|
||||
{
|
||||
fdd_log("fdd_load(%d, %s)\n", drive, fn);
|
||||
int c = 0;
|
||||
int size;
|
||||
const char *p;
|
||||
@@ -558,6 +604,7 @@ fdd_byteperiod(int drive)
|
||||
void
|
||||
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]) {
|
||||
@@ -629,6 +676,7 @@ fdd_reset(void)
|
||||
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 (drives[drive].readsector)
|
||||
drives[drive].readsector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
@@ -638,6 +686,7 @@ fdd_readsector(int drive, int sector, int track, int side, int density, int sect
|
||||
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 (drives[drive].writesector)
|
||||
drives[drive].writesector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
|
||||
@@ -251,6 +251,7 @@ extern uint8_t fdc_read(uint16_t addr, void *priv);
|
||||
extern void fdc_reset(void *priv);
|
||||
|
||||
extern uint8_t fdc_get_current_drive(void);
|
||||
extern void fdc_seek_complete_interrupt(fdc_t *fdc, int drive);
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t fdc_xt_device;
|
||||
|
||||
Reference in New Issue
Block a user