From e4408bc84db9460ad541d6e3e635d4b37fd97542 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 19 Nov 2019 04:35:54 +0100 Subject: [PATCH] Fixed CD-ROM timings on the NCR 53x8xx SCSI controllers, the IDE_TIME, CDROM_TIME, and ZIP_TIME values, and the delay added to the CD-ROM READ SUBCHANNEL command, fixes slowdowns on several games that use CD Audio, such as Tomb Raider II. --- src/disk/hdc_ide.c | 61 +++++++++++++++++++++++++-------------- src/disk/hdc_ide.h | 7 +++-- src/disk/zip.c | 32 +++++++++++++++----- src/disk/zip.h | 6 ++-- src/scsi/scsi_cdrom.c | 18 +++++++----- src/scsi/scsi_cdrom.h | 6 ++-- src/scsi/scsi_ncr53c8xx.c | 25 ++++++++-------- 7 files changed, 97 insertions(+), 58 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index bd1931222..a9d1e8e59 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -9,7 +9,7 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdc_ide.c 1.0.64 2019/11/06 + * Version: @(#)hdc_ide.c 1.0.65 2019/11/19 * * Authors: Sarah Walker, * Miran Grca, @@ -109,7 +109,7 @@ #define FEATURE_DISABLE_IRQ_OVERLAPPED 0xdd #define FEATURE_DISABLE_IRQ_SERVICE 0xde -#define IDE_TIME 20.0 / 3.0 +#define IDE_TIME 10.0 typedef struct { @@ -175,70 +175,72 @@ ide_get_drive(int ch) double ide_get_period(ide_t *ide, int size) { - double period = 10.0 / 3.0; + double period = (10.0 / 3.0); + /* We assume that 1 MB = 1000000 B in this case, so we have as + many B/us as there are MB/s because 1 s = 1000000 us. */ switch(ide->mdma_mode & 0x300) { case 0x000: /* PIO */ switch(ide->mdma_mode & 0xff) { case 0: - period = 10.0 / 3.0; + period = (10.0 / 3.0); break; case 1: - period = (period * 600.0) / 383.0; + period = (20.0 / 3.83); break; case 2: - period = 25.0 / 3.0; + period = (25.0 / 3.0); break; case 3: - period = 100.0 / 9.0; + period = (100.0 / 9.0); break; case 4: - period = 50.0 / 3.0; + period = (50.0 / 3.0); break; } break; case 0x100: /* Single Word DMA */ switch(ide->mdma_mode & 0xff) { case 0: - period = 25.0 / 12.0; + period = (25.0 / 12.0); break; case 1: - period = 25.0 / 6.0; + period = (25.0 / 6.0); break; case 2: - period = 25.0 / 3.0; + period = (25.0 / 3.0); break; } break; case 0x200: /* Multiword DMA */ switch(ide->mdma_mode & 0xff) { case 0: - period = 25.0 / 6.0; + period = (25.0 / 6.0); break; case 1: - period = 40.0 / 3.0; + period = (40.0 / 3.0); break; case 2: - period = 50.0 / 3.0; + period = (50.0 / 3.0); break; } break; case 0x300: /* Ultra DMA */ switch(ide->mdma_mode & 0xff) { case 0: - period = 50.0 / 3.0; + period = (50.0 / 3.0); break; case 1: period = 25.0; break; case 2: - period = 100.0 / 3.0; + period = (100.0 / 3.0); break; case 3: - period = 400.0 / 9.0; + period = (400.0 / 9.0); break; case 4: - period = 200.0 / 3.0; + period = (200.0 / 3.0); break; case 5: period = 100.0; @@ -247,9 +249,26 @@ ide_get_period(ide_t *ide, int size) break; } - period *= 1048576.0; /* period * MB - get bytes per second */ - period = ((double) size) / period; /* size / period to get seconds */ - return period * 1000000.0; /* return seconds * 1000000 to convert to us */ + period = (10.0 / 3.0); + + period = (1.0 / period); /* get us for 1 byte */ + return period * ((double) size); /* multiply by bytes to get period for the entire transfer */ +} + + +double +ide_atapi_get_period(uint8_t channel) +{ + ide_t *ide = ide_drives[channel]; + + ide_log("ide_atapi_get_period(%i)\n", channel); + + if (!ide) { + ide_log("Get period failed\n"); + return -1.0; + } + + return ide_get_period(ide, 1); } diff --git a/src/disk/hdc_ide.h b/src/disk/hdc_ide.h index b2f96807a..b1e172748 100644 --- a/src/disk/hdc_ide.h +++ b/src/disk/hdc_ide.h @@ -9,12 +9,12 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdd_ide.h 1.0.15 2018/10/31 + * Version: @(#)hdd_ide.h 1.0.16 2019/11/19 * * Authors: Sarah Walker, * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #ifndef EMU_IDE_H # define EMU_IDE_H @@ -130,6 +130,7 @@ extern void ide_pri_disable(void); extern void ide_sec_enable(void); extern void ide_sec_disable(void); +extern double ide_atapi_get_period(uint8_t channel); extern void ide_set_callback(uint8_t channel, double callback); extern void ide_padstr(char *str, const char *src, int len); diff --git a/src/disk/zip.c b/src/disk/zip.c index 2da62f4af..60c775810 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -9,11 +9,11 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.c 1.0.37 2018/11/02 + * Version: @(#)zip.c 1.0.38 2019/11/19 * * Author: Miran Grca, * - * Copyright 2018 Miran Grca. + * Copyright 2018,2019 Miran Grca. */ #include #include @@ -854,6 +854,26 @@ zip_update_request_length(zip_t *dev, int len, int block_len) } +static double +zip_bus_speed(zip_t *dev) +{ + double ret = -1.0; + + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + dev->callback = -1.0; /* Speed depends on SCSI controller */ + return 0.0; + } else { + if (dev && dev->drv) + ret = ide_atapi_get_period(dev->drv->ide_channel); + if (ret == -1.0) { + dev->callback = -1.0; + return 0.0; + } else + return ret * 1000000.0; + } +} + + static void zip_command_common(zip_t *dev) { @@ -868,12 +888,8 @@ zip_command_common(zip_t *dev) if (dev->drv->bus_type == ZIP_BUS_SCSI) { dev->callback = -1.0; /* Speed depends on SCSI controller */ return; - } else { - if (zip_current_mode(dev) == 2) - bytes_per_second = 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ - else - bytes_per_second = 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ - } + } else + bytes_per_second = zip_bus_speed(dev); period = 1000000.0 / bytes_per_second; dev->callback = period * (double) (dev->packet_len); diff --git a/src/disk/zip.h b/src/disk/zip.h index b36b7e6bd..02c355472 100644 --- a/src/disk/zip.h +++ b/src/disk/zip.h @@ -9,11 +9,11 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.h 1.0.9 2018/10/31 + * Version: @(#)zip.h 1.0.10 2019/11/19 * * Author: Miran Grca, * - * Copyright 2018 Miran Grca. + * Copyright 2018,2019 Miran Grca. */ #ifndef EMU_ZIP_H #define EMU_ZIP_H @@ -23,7 +23,7 @@ #define BUF_SIZE 32768 -#define ZIP_TIME 500.0 +#define ZIP_TIME 10.0 #define ZIP_SECTORS (96*2048) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 846ef8ef7..045c78fa9 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -9,7 +9,7 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)scsi_cdrom.c 1.0.71 2019/09/26 + * Version: @(#)scsi_cdrom.c 1.0.72 2019/11/19 * * Author: Miran Grca, * @@ -604,15 +604,19 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) static double scsi_cdrom_bus_speed(scsi_cdrom_t *dev) { + double ret = -1.0; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { dev->callback = -1.0; /* Speed depends on SCSI controller */ return 0.0; } else { - /* TODO: Get the actual selected speed from IDE. */ - if (scsi_cdrom_current_mode(dev) == 2) - return 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ - else - return 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ + if (dev && dev->drv) + ret = ide_atapi_get_period(dev->drv->ide_channel); + if (ret == -1.0) { + dev->callback = -1.0; + return 0.0; + } else + return ret * 1000000.0; } } @@ -663,7 +667,7 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) case 0xb9: case 0xbe: if (dev->current_cdb[0] == 0x42) - dev->callback += 200.0 * CDROM_TIME; + dev->callback += 40.0; /* Account for seek time. */ bytes_per_second = 176.0 * 1024.0; bytes_per_second *= (double) dev->drv->cur_speed; diff --git a/src/scsi/scsi_cdrom.h b/src/scsi/scsi_cdrom.h index f83c6457c..1c8be1382 100644 --- a/src/scsi/scsi_cdrom.h +++ b/src/scsi/scsi_cdrom.h @@ -9,17 +9,17 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)scsi_cdrom.h 1.0.1 2018/10/17 + * Version: @(#)scsi_cdrom.h 1.0.2 2019/11/19 * * Author: Miran Grca, * - * Copyright 2018 Miran Grca. + * Copyright 2018,2019 Miran Grca. */ #ifndef EMU_SCSI_CDROM_H #define EMU_SCSI_CDROM_H -#define CDROM_TIME 500.0 +#define CDROM_TIME 10.0 #ifdef SCSI_DEVICE_H diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index 65b680483..56af023a1 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -13,7 +13,7 @@ * To do: Identify the type of serial EEPROM used and its * interface. * - * Version: @(#)scsi_ncr53c8xx.c 1.0.17 2018/10/30 + * Version: @(#)scsi_ncr53c8xx.c 1.0.18 2019/11/19 * * Authors: Paul Brook (QEMU) * Artyom Tarasenko (QEMU) @@ -705,10 +705,12 @@ ncr53c8xx_add_msg_byte(ncr53c8xx_t *dev, uint8_t data) static void ncr53c8xx_timer_on(ncr53c8xx_t *dev, scsi_device_t *sd, double p) { - if (p <= 0) - timer_on_auto(&dev->timer, ((double) sd->buffer_length) * 0.1); /* Fast SCSI: 10000000 bytes per second */ - else - timer_on_auto(&dev->timer, p); + double period; + + /* Fast SCSI: 10000000 bytes per second */ + period = (p > 0.0) ? p : (((double) sd->buffer_length) * 0.1); + + timer_on_auto(&dev->timer, period + 40.0); } @@ -1023,11 +1025,12 @@ again: /* If we receive an empty opcode increment the DSP by 4 bytes instead of 8 and execute the next opcode at that location */ dev->dsp += 4; - timer_on_auto(&dev->timer, 10.0); if (insn_processed < 100) goto again; - else + else { + timer_on_auto(&dev->timer, 10.0); return; + } } addr = read_dword(dev, dev->dsp + 4); ncr53c8xx_log("SCRIPTS dsp=%08x opcode %08x arg %08x\n", dev->dsp, insn, addr); @@ -1093,8 +1096,6 @@ again: dev->dfifo = dev->dbc & 0xff; dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); - timer_on_auto(&dev->timer, 40.0); - if (dev->dcntl & NCR_DCNTL_SSM) ncr53c8xx_script_dma_interrupt(dev, NCR_DSTAT_SSI); return; @@ -1363,8 +1364,6 @@ again: ncr53c8xx_log("%02X: Unknown command\n", (uint8_t) (insn >> 30)); } - timer_on_auto(&dev->timer, 40.0); - ncr53c8xx_log("instructions processed %i\n", insn_processed); if (insn_processed > 10000 && !dev->waiting) { /* Some windows drivers make the device spin waiting for a memory @@ -1393,6 +1392,8 @@ again: ncr53c8xx_log("NCR 810: SCRIPTS: Waiting\n"); } + timer_on_auto(&dev->timer, 40.0); + ncr53c8xx_log("SCRIPTS execution stopped\n"); } @@ -1419,8 +1420,6 @@ ncr53c8xx_callback(void *p) if (dev->sstop) timer_stop(&dev->timer); - else - timer_on_auto(&dev->timer, 10.0); }