diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 41cc1db98..4dc03885e 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -1520,13 +1520,13 @@ track_type_is_valid(UNUSED(uint8_t id), int type, int flags, int audio, int mode return 1; } -static void +static int read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, int mode2, int len) { uint8_t *bb = rbuf; const int offset = (!!(mode2 & 0x03)) ? 24 : 16; - dev->ops->read_sector(dev, CD_READ_DATA, rbuf + offset, lba); + int ret = dev->ops->read_sector(dev, CD_READ_DATA, rbuf + offset, lba); /* Sync bytes */ bb[0] = 0; @@ -1546,25 +1546,30 @@ read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, i memset(bb, 0, 280); else if (!mode2) memset(bb, 0, 288); + + return ret; } -static void +static int read_audio(cdrom_t *dev, uint32_t lba, uint8_t *b) { - dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); + int ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); memcpy(b, raw_buffer, 2352); cdrom_sector_size = 2352; + + return ret; } -static void +static int read_mode1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { + int ret; if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2048)) - read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); + ret = read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); else - dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); + ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); cdrom_sector_size = 0; @@ -1610,15 +1615,18 @@ read_mode1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int cdrom_sector_size += 288; b += 288; } + + return ret; } -static void +static int read_mode2_non_xa(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { + int ret; if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2336)) - read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2336); + ret = read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2336); else - dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); + ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); cdrom_sector_size = 0; @@ -1654,15 +1662,18 @@ read_mode2_non_xa(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t m cdrom_sector_size += 2336; b += 2336; } + + return ret; } -static void +static int read_mode2_xa_form1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { + int ret; if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2048)) - read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); + ret = read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); else - dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); + ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); cdrom_sector_size = 0; @@ -1705,15 +1716,18 @@ read_mode2_xa_form1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t cdrom_sector_size += 280; b += 280; } + + return ret; } -static void +static int read_mode2_xa_form2(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { + int ret; if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2324)) - read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2324); + ret = read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2324); else - dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); + ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba); cdrom_sector_size = 0; @@ -1748,6 +1762,8 @@ read_mode2_xa_form2(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t cdrom_sector_size += 2328; b += 2328; } + + return ret; } int @@ -1763,6 +1779,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c int m; int s; int f; + int ret = 0; if (dev->cd_status == CD_STATUS_EMPTY) return 0; @@ -1827,21 +1844,21 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c return 0; } - read_audio(dev, lba, temp_b); + ret = read_audio(dev, lba, temp_b); } else if (cdrom_sector_type == 2) { if (audio || mode2) { cdrom_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", dev->id); return 0; } - read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + ret = read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 3) { if (audio || !mode2 || (mode2 & 0x03)) { cdrom_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", dev->id); return 0; } - read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + ret = read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 4) { if (audio || !mode2 || ((mode2 & 0x03) != 1)) { cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", dev->id); @@ -1855,7 +1872,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c return 0; } - read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + ret = read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 8) { if (audio) { cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", dev->id); @@ -1863,9 +1880,9 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c } if (mode2 && ((mode2 & 0x03) == 1)) - read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + ret = read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); else if (!mode2) - read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + ret = read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); else { cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", dev->id); return 0; @@ -1873,16 +1890,16 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c } else { if (mode2) { if ((mode2 & 0x03) == 0x01) - read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + ret = read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); else if ((mode2 & 0x03) == 0x02) - read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + ret = read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); else - read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + ret = read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else { if (audio) - read_audio(dev, lba, temp_b); + ret = read_audio(dev, lba, temp_b); else - read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); + ret = read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } } @@ -1914,7 +1931,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c *len = cdrom_sector_size; - return 1; + return ret; } /* Peform a master init on the entire module. */ diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 7dcde1cdb..a1223bd17 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -181,13 +181,13 @@ bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) if (fseeko64(tf->fp, seek, SEEK_SET) == -1) { cdrom_image_backend_log("CDROM: binary_read failed during seek!\n"); - return 0; + return -1; } if (fread(buffer, count, 1, tf->fp) != 1) { cdrom_image_backend_log("CDROM: binary_read failed during read!\n"); - return 0; + return -1; } if (UNLIKELY(tf->motorola)) { @@ -502,8 +502,8 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) if (raw && !track_is_raw) { memset(buffer, 0x00, 2448); const int ret = trk->file->read(trk->file, buffer + offset, seek, length); - if (!ret) - return 0; + if (ret <= 0) + return ret; /* Construct the rest of the raw sector. */ memset(buffer + 1, 0xff, 10); buffer += 12; @@ -534,7 +534,7 @@ cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint3 for (uint32_t i = 0; i < num; i++) { success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); - if (!success) + if (success <= 0) break; /* Based on the DOSBox patch, but check all 8 bytes and makes sure it's not an audio track. */ diff --git a/src/cdrom/cdrom_image_viso.c b/src/cdrom/cdrom_image_viso.c index 90bd83cf7..edca09d91 100644 --- a/src/cdrom/cdrom_image_viso.c +++ b/src/cdrom/cdrom_image_viso.c @@ -716,8 +716,11 @@ viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count) } /* Read data. */ - if (entry->file && (fseeko64(entry->file, seek - entry->data_offset, SEEK_SET) != -1)) - read = fread(buffer, 1, sector_remain, entry->file); + if (!entry->file || (fseeko64(entry->file, seek - entry->data_offset, SEEK_SET) == -1)) + return -1; + read = fread(buffer, 1, sector_remain, entry->file); + if (sector_remain && !read) + return -1; } /* Fill remainder with 00 bytes if needed. */ diff --git a/src/cdrom/cdrom_mitsumi.c b/src/cdrom/cdrom_mitsumi.c index 01a9cf047..0cebfe7f6 100644 --- a/src/cdrom/cdrom_mitsumi.c +++ b/src/cdrom/cdrom_mitsumi.c @@ -197,7 +197,7 @@ mitsumi_cdrom_read_sector(mcd_t *dev, int first) } cdrom_stop(&cdrom); ret = cdrom_readsector_raw(&cdrom, dev->buf, cdrom.seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0); - if (!ret) + if (ret <= 0) return 0; if (dev->mode & 0x40) { dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff); diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index 64d3bc853..abcd415f4 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -189,6 +189,7 @@ /* SCSI Sense Keys */ #define SENSE_NONE 0 #define SENSE_NOT_READY 2 +#define SENSE_MEDIUM_ERROR 3 #define SENSE_ILLEGAL_REQUEST 5 #define SENSE_UNIT_ATTENTION 6 @@ -196,6 +197,7 @@ #define ASC_NONE 0x00 #define ASC_AUDIO_PLAY_OPERATION 0x00 #define ASC_NOT_READY 0x04 +#define ASC_UNRECOVERED_READ_ERROR 0x11 #define ASC_ILLEGAL_OPCODE 0x20 #define ASC_LBA_OUT_OF_RANGE 0x21 #define ASC_INV_FIELD_IN_CMD_PACKET 0x24 @@ -212,6 +214,7 @@ #define ASCQ_NONE 0x00 #define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01 #define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 +#define ASCQ_CIRC_UNRECOVERED_ERROR 0x06 #define ASCQ_CAPACITY_DATA_CHANGED 0x09 #define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11 #define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12 diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index 5c533b216..fed1444d1 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -207,7 +207,7 @@ plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector) plat_cdrom_close(); dummy_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%" PRId64 ".\n", status, sector, (long long) size); - return 0; + return -1; } void diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index ff422bcd2..995876c1d 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -342,7 +342,7 @@ plat_cdrom_get_sector_size(UNUSED(uint32_t sector)) int plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector) { - BOOL status; + int status; long size = 0; int buflen = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; @@ -370,7 +370,7 @@ plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector) plat_cdrom_close(); win_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%" PRId64 ".\n", status, sector, (long long) size); - return (size == buflen) && (status > 0); + return (status > 0) ? (size == buflen) : -1; } void diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index d014945a7..c527465fc 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1244,6 +1244,15 @@ scsi_cdrom_not_ready(scsi_cdrom_t *dev) scsi_cdrom_cmd_error(dev); } +static void +scsi_cdrom_circ_error(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_MEDIUM_ERROR; + scsi_cdrom_asc = ASC_UNRECOVERED_READ_ERROR; + scsi_cdrom_ascq = ASCQ_CIRC_UNRECOVERED_ERROR; + scsi_cdrom_cmd_error(dev); +} + static void scsi_cdrom_invalid_lun(scsi_cdrom_t *dev) { @@ -1367,6 +1376,10 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, int msf, int type, int flags, int32_t *l if (!ret) { scsi_cdrom_illegal_mode(dev); return 0; + } else if (ret < 0) { + pclog("we have a circ\n"); + scsi_cdrom_circ_error(dev); + return -1; } }