CD-ROM: Do not stop playing on a READ command that immediately terminates with an "illegal mode for this track" error, fixes track skipping in the Windows 95 CD Player.
This commit is contained in:
@@ -2274,6 +2274,65 @@ cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
cdrom_msf_to_lba(const int sector, const int ismsf,
|
||||||
|
int cdrom_sector_type, const uint8_t vendor_type)
|
||||||
|
{
|
||||||
|
int pos = sector;
|
||||||
|
uint32_t lba;
|
||||||
|
|
||||||
|
if ((cdrom_sector_type & 0x0f) >= 0x08) {
|
||||||
|
mult = cdrom_sector_type >> 4;
|
||||||
|
pos /= mult;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ismsf) {
|
||||||
|
const int m = (pos >> 16) & 0xff;
|
||||||
|
const int s = (pos >> 8) & 0xff;
|
||||||
|
const int f = pos & 0xff;
|
||||||
|
|
||||||
|
lba = MSFtoLBA(m, s, f) - 150;
|
||||||
|
} else {
|
||||||
|
switch (vendor_type) {
|
||||||
|
case 0x00:
|
||||||
|
lba = pos;
|
||||||
|
break;
|
||||||
|
case 0x40: {
|
||||||
|
const int m = bcd2bin((pos >> 24) & 0xff);
|
||||||
|
const int s = bcd2bin((pos >> 16) & 0xff);
|
||||||
|
const int f = bcd2bin((pos >> 8) & 0xff);
|
||||||
|
|
||||||
|
lba = MSFtoLBA(m, s, f) - 150;
|
||||||
|
break;
|
||||||
|
} case 0x80:
|
||||||
|
lba = bcd2bin((pos >> 24) & 0xff);
|
||||||
|
break;
|
||||||
|
/* Never used values but the compiler complains. */
|
||||||
|
default:
|
||||||
|
lba = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lba;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cdrom_is_track_audio(cdrom_t *dev, const int sector,
|
||||||
|
const int ismsf, int cdrom_sector_type,
|
||||||
|
const uint8_t vendor_type)
|
||||||
|
{
|
||||||
|
int audio = 0;
|
||||||
|
uint32_t lba = cdrom_msf_to_lba(sector, ismsf,
|
||||||
|
cdrom_sector_type, vendor_type);
|
||||||
|
|
||||||
|
if (dev->ops->get_track_type)
|
||||||
|
audio = dev->ops->get_track_type(dev->local, lba);
|
||||||
|
|
||||||
|
audio &= CD_TRACK_AUDIO;
|
||||||
|
|
||||||
|
return audio;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf,
|
cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf,
|
||||||
int cdrom_sector_type, const int cdrom_sector_flags,
|
int cdrom_sector_type, const int cdrom_sector_flags,
|
||||||
@@ -2298,38 +2357,12 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int
|
|||||||
uint8_t *temp_b;
|
uint8_t *temp_b;
|
||||||
uint8_t *b = temp_b = buffer;
|
uint8_t *b = temp_b = buffer;
|
||||||
int audio = 0;
|
int audio = 0;
|
||||||
uint32_t lba;
|
uint32_t lba = cdrom_msf_to_lba(sector, ismsf,
|
||||||
|
cdrom_sector_type, vendor_type);
|
||||||
int mode2 = 0;
|
int mode2 = 0;
|
||||||
|
|
||||||
*len = 0;
|
*len = 0;
|
||||||
|
|
||||||
if (ismsf) {
|
|
||||||
const int m = (pos >> 16) & 0xff;
|
|
||||||
const int s = (pos >> 8) & 0xff;
|
|
||||||
const int f = pos & 0xff;
|
|
||||||
|
|
||||||
lba = MSFtoLBA(m, s, f) - 150;
|
|
||||||
} else {
|
|
||||||
switch (vendor_type) {
|
|
||||||
case 0x00:
|
|
||||||
lba = pos;
|
|
||||||
break;
|
|
||||||
case 0x40: {
|
|
||||||
const int m = bcd2bin((pos >> 24) & 0xff);
|
|
||||||
const int s = bcd2bin((pos >> 16) & 0xff);
|
|
||||||
const int f = bcd2bin((pos >> 8) & 0xff);
|
|
||||||
|
|
||||||
lba = MSFtoLBA(m, s, f) - 150;
|
|
||||||
break;
|
|
||||||
} case 0x80:
|
|
||||||
lba = bcd2bin((pos >> 24) & 0xff);
|
|
||||||
break;
|
|
||||||
/* Never used values but the compiler complains. */
|
|
||||||
default:
|
|
||||||
lba = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev->ops->get_track_type)
|
if (dev->ops->get_track_type)
|
||||||
audio = dev->ops->get_track_type(dev->local, lba);
|
audio = dev->ops->get_track_type(dev->local, lba);
|
||||||
|
|
||||||
|
|||||||
@@ -425,6 +425,8 @@ extern uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint
|
|||||||
#endif
|
#endif
|
||||||
extern uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b,
|
extern uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b,
|
||||||
const uint8_t track, const int type);
|
const uint8_t track, const int type);
|
||||||
|
extern int cdrom_is_track_audio(cdrom_t *dev, const int sector, const int ismsf,
|
||||||
|
int cdrom_sector_type, const uint8_t vendor_type);
|
||||||
extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf,
|
extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf,
|
||||||
int cdrom_sector_type, const int cdrom_sector_flags,
|
int cdrom_sector_type, const int cdrom_sector_flags,
|
||||||
int *len, const uint8_t vendor_type);
|
int *len, const uint8_t vendor_type);
|
||||||
|
|||||||
@@ -2610,6 +2610,11 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb)
|
|||||||
dev->sector_len = 256;
|
dev->sector_len = 256;
|
||||||
dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) |
|
dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) |
|
||||||
(((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]);
|
(((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]);
|
||||||
|
if (cdrom_is_track_audio(dev->drv, dev->sector_pos, msf,
|
||||||
|
dev->sector_type, 0x00)) {
|
||||||
|
scsi_cdrom_illegal_mode(dev);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
scsi_cdrom_log(dev->log, "READ (6): Length: %i, LBA: %i\n",
|
scsi_cdrom_log(dev->log, "READ (6): Length: %i, LBA: %i\n",
|
||||||
dev->sector_len, dev->sector_pos);
|
dev->sector_len, dev->sector_pos);
|
||||||
break;
|
break;
|
||||||
@@ -2617,6 +2622,12 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb)
|
|||||||
dev->sector_len = (cdb[7] << 8) | cdb[8];
|
dev->sector_len = (cdb[7] << 8) | cdb[8];
|
||||||
dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) |
|
dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) |
|
||||||
(cdb[4] << 8) | cdb[5];
|
(cdb[4] << 8) | cdb[5];
|
||||||
|
if (cdrom_is_track_audio(dev->drv, dev->sector_pos, msf,
|
||||||
|
dev->sector_type, dev->use_cdb_9 ?
|
||||||
|
(cdb[9] & 0xc0) : 0x00)) {
|
||||||
|
scsi_cdrom_illegal_mode(dev);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
scsi_cdrom_log(dev->log, "READ (10): Length: %i, LBA: %i\n",
|
scsi_cdrom_log(dev->log, "READ (10): Length: %i, LBA: %i\n",
|
||||||
dev->sector_len, dev->sector_pos);
|
dev->sector_len, dev->sector_pos);
|
||||||
break;
|
break;
|
||||||
@@ -2627,6 +2638,12 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb)
|
|||||||
dev->sector_pos = (((uint32_t) cdb[2]) << 24) |
|
dev->sector_pos = (((uint32_t) cdb[2]) << 24) |
|
||||||
(((uint32_t) cdb[3]) << 16) |
|
(((uint32_t) cdb[3]) << 16) |
|
||||||
(((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]);
|
(((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]);
|
||||||
|
if (cdrom_is_track_audio(dev->drv, dev->sector_pos, msf,
|
||||||
|
dev->sector_type, dev->use_cdb_9 ?
|
||||||
|
(cdb[9] & 0xc0) : 0x00)) {
|
||||||
|
scsi_cdrom_illegal_mode(dev);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
scsi_cdrom_log(dev->log, "READ (12): Length: %i, LBA: %i\n",
|
scsi_cdrom_log(dev->log, "READ (12): Length: %i, LBA: %i\n",
|
||||||
dev->sector_len, dev->sector_pos);
|
dev->sector_len, dev->sector_pos);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user