CD-ROM and Iomega ZIP PIO request length is now reduced if it is bigger than the remaining amount of bytes to transfer;

Fixed CD-ROM sector reading from CUE/BIN images with 2048-byte sectors;
Fixed existing CD-ROM Mode 2 support and adding support for the remaining variants of Mode 2;
The Windows CD-ROM IOCTL code now correctly determines the track type, fixes CD Audio over IOCTL;
Applied all PCem sound-related commits;
Sound Blaster 16/AWE32 mixer effects now also apply to CD Audio when the Sound Blaster 16 or AWE32 is selected.
This commit is contained in:
OBattler
2018-02-15 23:14:44 +01:00
parent 07bc427839
commit 6cab207231
11 changed files with 514 additions and 169 deletions

View File

@@ -9,7 +9,7 @@
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)cdrom.c 1.0.30 2018/01/25
* Version: @(#)cdrom.c 1.0.31 2018/02/15
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -720,7 +720,7 @@ static void cdrom_command_common(uint8_t id)
cdrom_set_callback(id);
} else if (cdrom[id].packet_status == CDROM_PHASE_DATA_IN) {
if (cdrom[id].current_cdb[0] == 0x42) {
cdrom_log("CD-ROM %i: READ SUBCHANNEL\n");
cdrom_log("CD-ROM %i: READ SUBCHANNEL\n", id);
cdrom[id].callback = 1000LL * CDROM_TIME;
cdrom_set_callback(id);
} else {
@@ -1517,9 +1517,6 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM };
uint32_t i = 0;
#if 0
int CdbLength;
#endif
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) {
BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength;
cdrom[id].status &= ~ERR_STAT;
@@ -1548,10 +1545,9 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, cdrom[id].unit_attention);
cdrom_log("CD-ROM %i: Request length: %04X\n", id, cdrom[id].request_length);
#if 0
for (CdbLength = 1; CdbLength < cdrom[id].cdb_len; CdbLength++)
// cdrom_log("CD-ROM %i: CDB[%d] = %d\n", id, CdbLength, cdb[CdbLength]);
#endif
cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", id,
cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
cdb[8], cdb[9], cdb[10], cdb[11]);
}
msf = cdb[1] & 2;
@@ -1666,6 +1662,35 @@ cdrom_readtoc_fallback:
cdrom_set_buf_len(id, BufLen, &len);
if (len >= 8) {
cdrom_log("CD-ROM %i: TOC: %02X %02X %02X %02X %02X %02X %02X %02X\n", id,
cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3],
cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]);
}
if (len >= 16) {
cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n",
cdbufferb[8], cdbufferb[9], cdbufferb[10], cdbufferb[11],
cdbufferb[12], cdbufferb[13], cdbufferb[14], cdbufferb[15]);
}
if (len >= 24) {
cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n",
cdbufferb[16], cdbufferb[17], cdbufferb[18], cdbufferb[19],
cdbufferb[20], cdbufferb[21], cdbufferb[22], cdbufferb[23]);
}
if (len >= 32) {
cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n",
cdbufferb[24], cdbufferb[25], cdbufferb[26], cdbufferb[27],
cdbufferb[28], cdbufferb[29], cdbufferb[30], cdbufferb[31]);
}
if (len >= 36) {
cdrom_log(" %02X %02X %02X %02X\n",
cdbufferb[32], cdbufferb[33], cdbufferb[34], cdbufferb[35]);
}
cdrom_data_command_finish(id, len, len, len, 0);
/* cdrom_log("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", id, toc_format, ide->cylinder, cdbufferb[1]); */
return;
@@ -2155,7 +2180,10 @@ cdrom_readtoc_fallback:
break;
}
if ((cdrom_drive < 1) || (cdrom[id].cd_status <= CD_STATUS_DATA_ONLY) || !cdrom_drives[id].handler->is_track_audio(id, pos, msf)) {
if (!cdrom_drives[id].handler->is_track_audio)
break;
if ((cdrom_drives[id].host_drive < 1) || (cdrom[id].cd_status <= CD_STATUS_DATA_ONLY) || !cdrom_drives[id].handler->is_track_audio(id, pos, msf)) {
cdrom_illegal_mode(id);
break;
}
@@ -2645,10 +2673,18 @@ void cdrom_pio_request(uint8_t id, uint8_t out)
/* Make sure to keep pos, and reset request_pos to 0. */
/* Also make sure to not reset total_read. */
/* If less than (packet length) bytes are remaining, update packet length
accordingly. */
if ((cdrom[id].packet_len - cdrom[id].pos) < (cdrom[id].request_length))
cdrom[id].request_length = cdrom[id].packet_len - cdrom[id].pos;
cdrom_log("CD-ROM %i: Packet length %i, request length %i\n", id, cdrom[id].packet_len, cdrom[id].request_length);
old_pos = cdrom[id].pos;
cdrom[id].packet_status = out ? CDROM_PHASE_DATA_OUT : CDROM_PHASE_DATA_IN;
cdrom_command_common(id);
cdrom[id].pos = old_pos;
cdrom[id].request_pos = 0;
}
}

View File

@@ -197,12 +197,17 @@ int CDROM_Interface_Image::GetTrack(unsigned int sector)
bool CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long sector)
{
uint64_t length;
int track = GetTrack(sector) - 1;
if (track < 0) return false;
uint64_t s = (uint64_t) sector;
uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize);
uint64_t length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE);
if (tracks[track].mode2)
length = (raw ? RAW_SECTOR_SIZE : 2336);
else
length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE);
if (tracks[track].sectorSize != RAW_SECTOR_SIZE && raw) return false;
if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16;
if (tracks[track].mode2 && !raw) seek += 24;
@@ -210,6 +215,26 @@ bool CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long se
return tracks[track].file->read(buffer, seek, length);
}
bool CDROM_Interface_Image::ReadSectorSub(Bit8u *buffer, unsigned long sector)
{
int track = GetTrack(sector) - 1;
if (track < 0) return false;
uint64_t s = (uint64_t) sector;
uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize);
if (tracks[track].sectorSize != 2448) return false;
return tracks[track].file->read(buffer, seek, 2448);
}
int CDROM_Interface_Image::GetSectorSize(unsigned long sector)
{
int track = GetTrack(sector) - 1;
if (track < 0) return 0;
return tracks[track].sectorSize;
}
bool CDROM_Interface_Image::IsMode2(unsigned long sector)
{
int track = GetTrack(sector) - 1;
@@ -225,6 +250,14 @@ bool CDROM_Interface_Image::IsMode2(unsigned long sector)
}
}
int CDROM_Interface_Image::GetMode2Form(unsigned long sector)
{
int track = GetTrack(sector) - 1;
if (track < 0) return false;
return tracks[track].form;
}
bool CDROM_Interface_Image::LoadIsoFile(char* filename)
{
tracks.clear();
@@ -240,6 +273,7 @@ bool CDROM_Interface_Image::LoadIsoFile(char* filename)
track.number = 1;
track.track_number = 1;//IMPORTANT: This is needed.
track.attr = DATA_TRACK;//data
track.form = 0;
// try to detect iso type
if (CanReadPVD(track.file, COOKED_SECTOR_SIZE, false)) {
@@ -248,9 +282,13 @@ bool CDROM_Interface_Image::LoadIsoFile(char* filename)
} else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, false)) {
track.sectorSize = RAW_SECTOR_SIZE;
track.mode2 = false;
} else if (CanReadPVD(track.file, 2324, true)) {
track.sectorSize = 2324;
track.form = 2;
track.mode2 = true;
} else if (CanReadPVD(track.file, 2336, true)) {
track.sectorSize = 2336;
track.mode2 = true;
track.mode2 = true;
} else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) {
track.sectorSize = RAW_SECTOR_SIZE;
track.mode2 = true;
@@ -259,7 +297,7 @@ bool CDROM_Interface_Image::LoadIsoFile(char* filename)
track.sectorSize = COOKED_SECTOR_SIZE;
track.mode2 = false;
}
track.length = track.file->getLength() / track.sectorSize;
tracks.push_back(track);
@@ -343,7 +381,9 @@ bool CDROM_Interface_Image::LoadCueSheet(char *cuefile)
track.track_number = track.number;
string type;
GetCueKeyword(type, line);
track.form = 0;
if (type == "AUDIO") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = AUDIO_TRACK;
@@ -356,6 +396,16 @@ bool CDROM_Interface_Image::LoadCueSheet(char *cuefile)
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = false;
} else if (type == "MODE2/2048") {
track.form = 1;
track.sectorSize = 2048;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "MODE2/2324") {
track.form = 2;
track.sectorSize = 2324;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "MODE2/2336") {
track.sectorSize = 2336;
track.attr = DATA_TRACK;
@@ -364,6 +414,18 @@ bool CDROM_Interface_Image::LoadCueSheet(char *cuefile)
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "CDG/2448") {
track.sectorSize = 2448;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "CDI/2336") {
track.sectorSize = 2336;
track.attr = DATA_TRACK;
track.mode2 = true;
} else if (type == "CDI/2352") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = DATA_TRACK;
track.mode2 = true;
} else success = false;
canAddTrack = true;

View File

@@ -119,6 +119,7 @@ private:
int number;
int track_number;
int attr;
int form;
uint64_t start;
uint64_t length;
uint64_t skip;
@@ -140,7 +141,10 @@ public:
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
bool LoadUnloadMedia (bool unload);
bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector);
bool ReadSectorSub (Bit8u *buffer, unsigned long sector);
int GetSectorSize (unsigned long sector);
bool IsMode2 (unsigned long sector);
int GetMode2Form (unsigned long sector);
bool HasDataTrack (void);
bool HasAudioTracks (void);

View File

@@ -46,9 +46,6 @@ int cdrom_image_do_log = ENABLE_CDROM_IMAGE_LOG;
CDROM_Interface_Image* cdimg[CDROM_NUM] = { NULL, NULL, NULL, NULL };
extern "C" void pclog(const char *fmt, ...);
void cdrom_image_log(const char *format, ...)
{
#ifdef ENABLE_CDROM_IMAGE_LOG
@@ -407,9 +404,84 @@ typedef union __attribute__((__packed__))
sector_buffer_t cdrom_sector_buffer;
int cdrom_sector_size;
uint8_t raw_buffer[2352];
uint8_t raw_buffer[2448];
uint8_t extra_buffer[296];
static int is_legal(int id, int cdrom_sector_type, int cdrom_sector_flags, int audio, int mode2, int form)
{
if (!(cdrom_sector_flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */
cdrom_image_log("CD-ROM %i: [Any Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id);
return 0;
}
if ((cdrom_sector_type != 1) && !audio)
{
if (!(cdrom_sector_flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */
cdrom_image_log("CD-ROM %i: [Any Data Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id);
return 0;
}
if ((cdrom_sector_flags & 0x06) == 0x06) {
cdrom_image_log("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id);
return 0;
}
if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) {
cdrom_image_log("CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X)\n", id, cdrom_sector_flags & 0x700);
return 0;
}
if ((cdrom_sector_flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */
cdrom_image_log("CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode\n", id);
return 0;
}
if (((cdrom_sector_flags & 0xf0) == 0x90) || ((cdrom_sector_flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */
cdrom_image_log("CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n", id);
return 0;
}
if (((cdrom_sector_type > 3) && (cdrom_sector_type != 8)) || (mode2 && form))
{
if ((cdrom_sector_flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */
cdrom_image_log("CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes\n", id);
return 0;
}
if (((cdrom_sector_flags & 0xf0) == 0xb0) || ((cdrom_sector_flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */
cdrom_image_log("CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes\n", id);
return 0;
}
}
}
return 1;
}
static void read_sector_to_buffer(uint8_t id, uint8_t *raw_buffer, uint32_t msf, uint32_t lba, int mode2, int form, int len)
{
cdimg[id]->ReadSector(raw_buffer + 16, false, lba);
uint8_t *bb = raw_buffer;
/* sync bytes */
bb[0] = 0;
memset(bb + 1, 0xff, 10);
bb[11] = 0;
bb += 12;
bb[0] = (msf >> 16) & 0xff;
bb[1] = (msf >> 8) & 0xff;
bb[2] = msf & 0xff;
bb[3] = 1; /* mode 1 data */
bb += mode2 ? 12 : 4;
bb += len;
if (mode2 && (form == 1))
memset(bb, 0, 280);
else if (!mode2)
memset(bb, 0, 288);
}
static int image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len)
{
uint8_t *b;
@@ -419,6 +491,7 @@ static int image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ism
int audio;
int mode2;
int m, s, f;
int form;
if (!cdimg[id])
return 0;
@@ -448,8 +521,9 @@ static int image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ism
audio = image_is_track_audio(id, sector, ismsf);
mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0;
}
form = cdimg[id]->GetMode2Form(lba);
memset(raw_buffer, 0, 2352);
memset(raw_buffer, 0, 2448);
memset(extra_buffer, 0, 296);
if (!(cdrom_sector_flags & 0xf0)) { /* 0x00 and 0x08 are illegal modes */
@@ -471,53 +545,32 @@ static int image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ism
}
read_audio:
cdimg[id]->ReadSector(raw_buffer, true, lba);
if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form))
return 0;
if (cdimg[id]->GetSectorSize(lba) == 2352)
cdimg[id]->ReadSector(raw_buffer, true, lba);
else
cdimg[id]->ReadSectorSub(raw_buffer, lba);
memcpy(temp_b, raw_buffer, 2352);
cdrom_sector_size = 2352;
} else if (cdrom_sector_type == 2) {
if (audio || mode2) {
cdrom_image_log("CD-ROM %i: [Mode 1] Attempting to read a non-Mode 1 sector from an audio track\n", id);
cdrom_image_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", id);
return 0;
}
read_mode1:
if ((cdrom_sector_flags & 0x06) == 0x06) {
cdrom_image_log("CD-ROM %i: [Mode 1] Invalid error flags\n", id);
if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form))
return 0;
}
if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) {
cdrom_image_log("CD-ROM %i: [Mode 1] Invalid subchannel data flags (%02X)\n", id, cdrom_sector_flags & 0x700);
return 0;
}
if ((cdrom_sector_flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */
cdrom_image_log("CD-ROM %i: [Mode 1] EDC/ECC without user data is an illegal mode\n", id);
return 0;
}
if (cdrom_image[id].image_is_iso) {
cdimg[id]->ReadSector(raw_buffer + 16, false, lba);
uint8_t *bb = raw_buffer;
/* sync bytes */
bb[0] = 0;
memset(bb + 1, 0xff, 10);
bb[11] = 0;
bb += 12;
bb[0] = (msf >> 16) & 0xff;
bb[1] = (msf >> 8) & 0xff;
bb[2] = msf & 0xff;
bb[3] = 1; /* mode 1 data */
bb += 4;
bb += 2048;
memset(bb, 0, 288);
}
else
if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048))
read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2048);
else if (cdimg[id]->GetSectorSize(lba) == 2352)
cdimg[id]->ReadSector(raw_buffer, true, lba);
else
cdimg[id]->ReadSectorSub(raw_buffer, lba);
cdrom_sector_size = 0;
@@ -535,7 +588,6 @@ read_mode1:
temp_b += 4;
}
/* Mode 1 sector, expected type is 1 type. */
if (cdrom_sector_flags & 0x40) { /* Sub-header */
if (!(cdrom_sector_flags & 0x10)) { /* No user data */
cdrom_image_log("CD-ROM %i: [Mode 1] Sub-header\n", id);
@@ -558,59 +610,69 @@ read_mode1:
cdrom_sector_size += 288;
temp_b += 288;
}
} else if (cdrom_sector_type == 4) {
if (audio || !mode2) {
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a non-XA Mode 2 Form 1 sector from an audio track\n", id);
} else if (cdrom_sector_type == 3) {
if (audio || !mode2 || form) {
cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", id);
return 0;
}
read_mode2:
if (!(cdrom_sector_flags & 0xf0)) { /* 0x00 and 0x08 are illegal modes */
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] 0x00 and 0x08 are illegal modes\n", id);
read_mode2_non_xa:
if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form))
return 0;
}
if (((cdrom_sector_flags & 0xf0) == 0xb0) || ((cdrom_sector_flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] 0xBx and 0xDx are illegal modes\n", id);
return 0;
}
if ((cdrom_sector_flags & 0x06) == 0x06) {
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Invalid error flags\n", id);
return 0;
}
if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) {
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Invalid subchannel data flags (%02X)\n", id, cdrom_sector_flags & 0x700);
return 0;
}
if ((cdrom_sector_flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC without user data is an illegal mode\n", id);
return 0;
}
if (cdrom_image[id].image_is_iso) {
cdimg[id]->ReadSector(raw_buffer + 24, false, lba);
uint8_t *bb = raw_buffer;
/* sync bytes */
bb[0] = 0;
memset(bb + 1, 0xff, 10);
bb[11] = 0;
bb += 12;
bb[0] = (msf >> 16) & 0xff;
bb[1] = (msf >> 8) & 0xff;
bb[2] = msf & 0xff;
bb[3] = 1; /* mode 1 data */
bb += 12;
bb += 2048;
memset(bb, 0, 280);
} else
if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2336))
read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2336);
else if (cdimg[id]->GetSectorSize(lba) == 2352)
cdimg[id]->ReadSector(raw_buffer, true, lba);
else
cdimg[id]->ReadSectorSub(raw_buffer, lba);
cdrom_sector_size = 0;
if (cdrom_sector_flags & 0x80) { /* Sync */
cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Sync\n", id);
memcpy(temp_b, raw_buffer, 12);
cdrom_sector_size += 12;
temp_b += 12;
}
if (cdrom_sector_flags & 0x20) { /* Header */
cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Header\n", id);
memcpy(temp_b, raw_buffer + 12, 4);
cdrom_sector_size += 4;
temp_b += 4;
}
/* Mode 1 sector, expected type is 1 type. */
if (cdrom_sector_flags & 0x40) { /* Sub-header */
cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Sub-header\n", id);
memcpy(temp_b, raw_buffer + 16, 8);
cdrom_sector_size += 8;
temp_b += 8;
}
if (cdrom_sector_flags & 0x10) { /* User data */
cdrom_image_log("CD-ROM %i: [Mode 2 Formless] User data\n", id);
memcpy(temp_b, raw_buffer + 24, 2336);
cdrom_sector_size += 2336;
temp_b += 2336;
}
} else if (cdrom_sector_type == 4) {
if (audio || !mode2 || (form != 1)) {
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", id);
return 0;
}
read_mode2_xa_form1:
if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form))
return 0;
if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048))
read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2048);
else if (cdimg[id]->GetSectorSize(lba) == 2352)
cdimg[id]->ReadSector(raw_buffer, true, lba);
else
cdimg[id]->ReadSectorSub(raw_buffer, lba);
cdrom_sector_size = 0;
@@ -628,7 +690,6 @@ read_mode2:
temp_b += 4;
}
/* Mode 1 sector, expected type is 1 type. */
if (cdrom_sector_flags & 0x40) { /* Sub-header */
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", id);
memcpy(temp_b, raw_buffer + 16, 8);
@@ -649,6 +710,52 @@ read_mode2:
cdrom_sector_size += 280;
temp_b += 280;
}
} else if (cdrom_sector_type == 5) {
if (audio || !mode2 || (form != 2)) {
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", id);
return 0;
}
read_mode2_xa_form2:
if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form))
return 0;
if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2324))
read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2324);
else if (cdimg[id]->GetSectorSize(lba) == 2352)
cdimg[id]->ReadSector(raw_buffer, true, lba);
else
cdimg[id]->ReadSectorSub(raw_buffer, lba);
cdrom_sector_size = 0;
if (cdrom_sector_flags & 0x80) { /* Sync */
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", id);
memcpy(temp_b, raw_buffer, 12);
cdrom_sector_size += 12;
temp_b += 12;
}
if (cdrom_sector_flags & 0x20) { /* Header */
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Header\n", id);
memcpy(temp_b, raw_buffer + 12, 4);
cdrom_sector_size += 4;
temp_b += 4;
}
if (cdrom_sector_flags & 0x40) { /* Sub-header */
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", id);
memcpy(temp_b, raw_buffer + 16, 8);
cdrom_sector_size += 8;
temp_b += 8;
}
if (cdrom_sector_flags & 0x10) { /* User data */
cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] User data\n", id);
memcpy(temp_b, raw_buffer + 24, 2328);
cdrom_sector_size += 2328;
temp_b += 2328;
}
} else if (cdrom_sector_type == 8) {
if (audio) {
cdrom_image_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", id);
@@ -656,12 +763,17 @@ read_mode2:
}
if (mode2)
goto read_mode2;
goto read_mode2_non_xa;
else
goto read_mode1;
} else {
if (mode2)
goto read_mode2;
if (form == 1)
goto read_mode2_xa_form1;
else if (form == 2)
goto read_mode2_xa_form2;
else
goto read_mode2_non_xa;
else {
if (audio)
goto read_audio;
@@ -685,17 +797,17 @@ read_mode2:
if ((cdrom_sector_flags & 0x700) == 0x100) {
cdrom_image_log("CD-ROM %i: Raw subchannel data\n", id);
memcpy(b + cdrom_sector_size, extra_buffer, 96);
memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96);
cdrom_sector_size += 96;
}
else if ((cdrom_sector_flags & 0x700) == 0x200) {
cdrom_image_log("CD-ROM %i: Q subchannel data\n", id);
memcpy(b + cdrom_sector_size, extra_buffer, 16);
memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16);
cdrom_sector_size += 16;
}
else if ((cdrom_sector_flags & 0x700) == 0x400) {
cdrom_image_log("CD-ROM %i: R/W subchannel data\n", id);
memcpy(b + cdrom_sector_size, extra_buffer, 96);
memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96);
cdrom_sector_size += 96;
}

View File

@@ -345,3 +345,33 @@ static inline float dac_iir(int i, float NewSample) {
return y[i][0];
}
#define SB16_NCoef 51
extern float low_fir_sb16_coef[SB16_NCoef];
static inline float low_fir_sb16(int i, float NewSample)
{
static float x[2][SB16_NCoef+1]; //input samples
static int pos = 0;
float out = 0.0;
int n;
/* Calculate the new output */
x[i][pos] = NewSample;
for (n = 0; n < ((SB16_NCoef+1)-pos) && n < SB16_NCoef; n++)
out += low_fir_sb16_coef[n] * x[i][n+pos];
for (; n < SB16_NCoef; n++)
out += low_fir_sb16_coef[n] * x[i][(n+pos) - (SB16_NCoef+1)];
if (i == 1)
{
pos++;
if (pos > SB16_NCoef)
pos = 0;
}
return out;
}

View File

@@ -8,7 +8,7 @@
*
* Sound Blaster emulation.
*
* Version: @(#)sound_sb.c 1.0.4 2017/11/04
* Version: @(#)sound_sb.c 1.0.5 2018/02/15
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -272,6 +272,41 @@ static void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p)
sb->dsp.pos = 0;
}
static void sb_process_buffer_sb16(int32_t *buffer, int len, void *p)
{
sb_t *sb = (sb_t *)p;
sb_ct1745_mixer_t *mixer = &sb->mixer_sb16;
int c;
for (c = 0; c < len * 2; c += 2)
{
int32_t out_l = 0, out_r = 0;
out_l = ((int32_t)(buffer[c] * mixer->cd_l) / 3) >> 15;
out_r = ((int32_t)(buffer[c + 1] * mixer->cd_r) / 3) >> 15;
out_l = (out_l * mixer->master_l) >> 15;
out_r = (out_r * mixer->master_r) >> 15;
if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8)
{
/* This is not exactly how one does bass/treble controls, but the end result is like it. A better implementation would reduce the cpu usage */
if (mixer->bass_l>8) out_l += (int32_t)(low_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->bass_l]);
if (mixer->bass_r>8) out_r += (int32_t)(low_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->bass_r]);
if (mixer->treble_l>8) out_l += (int32_t)(high_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->treble_l]);
if (mixer->treble_r>8) out_r += (int32_t)(high_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->treble_r]);
if (mixer->bass_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->bass_l] + low_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->bass_l]));
if (mixer->bass_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->bass_r] + low_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->bass_r]));
if (mixer->treble_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->treble_l] + high_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->treble_l]));
if (mixer->treble_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->treble_r] + high_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->treble_r]));
}
buffer[c] = (out_l << mixer->output_gain_L);
buffer[c + 1] = (out_r << mixer->output_gain_R);
}
}
static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p)
{
sb_t *sb = (sb_t *)p;
@@ -296,10 +331,9 @@ static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p)
in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0;
in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0;
/*TODO: CT1745 features dynamic filtering. https://www.vogons.org/viewtopic.php?f=62&t=51514 */
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 15;
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 15;
out_l += ((int32_t)(low_fir_sb16(0, (float)sb->dsp.buffer[c]) * mixer->voice_l) / 3) >> 15;
out_r += ((int32_t)(low_fir_sb16(1, (float)sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3) >> 15;
out_l = (out_l * mixer->master_l) >> 15;
out_r = (out_r * mixer->master_r) >> 15;
@@ -379,10 +413,8 @@ static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p)
in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0;
in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0;
/*TODO: CT1745 features dynamic filtering. https://www.vogons.org/viewtopic.php?f=62&t=51514 */
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 15;
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 15;
out_l += ((int32_t)(low_fir_sb16(0, (float)sb->dsp.buffer[c]) * mixer->voice_l) / 3) >> 15;
out_r += ((int32_t)(low_fir_sb16(1, (float)sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3) >> 15;
out_l = (out_l * mixer->master_l) >> 15;
out_r = (out_r * mixer->master_r) >> 15;
@@ -1217,6 +1249,7 @@ void *sb_16_init()
}
io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_sb16, sb);
sound_add_process_handler(sb_process_buffer_sb16, sb);
mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401"));
sb_dsp_set_mpu(&sb->mpu);
@@ -1255,6 +1288,7 @@ void *sb_awe32_init()
}
io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_emu8k, sb);
sound_add_process_handler(sb_process_buffer_sb16, sb);
mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401"));
sb_dsp_set_mpu(&sb->mpu);
emu8k_init(&sb->emu8k, emu_addr, onboard_ram);

View File

@@ -4,6 +4,7 @@
486-50 - 32kHz
Pentium - 45kHz*/
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -15,6 +16,7 @@
#include "../dma.h"
#include "../timer.h"
#include "../device.h"
#include "filters.h"
#include "sound.h"
#include "midi.h"
#include "snd_mpu401.h"
@@ -115,6 +117,41 @@ uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x
252, 0, 252, 0
};
float low_fir_sb16_coef[SB16_NCoef];
static inline double sinc(double x)
{
return sin(M_PI * x) / (M_PI * x);
}
static void recalc_sb16_filter(int playback_freq)
{
/*Cutoff frequency = playback / 2*/
float fC = ((float)playback_freq / 2.0) / 48000.0;
float gain;
int n;
for (n = 0; n < SB16_NCoef; n++)
{
/*Blackman window*/
double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(SB16_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(SB16_NCoef-1)));
/*Sinc filter*/
double h = sinc(2.0 * fC * ((double)n - ((double)(SB16_NCoef-1) / 2.0)));
/*Create windowed-sinc filter*/
low_fir_sb16_coef[n] = w * h;
}
low_fir_sb16_coef[(SB16_NCoef - 1) / 2] = 1.0;
gain = 0.0;
for (n = 0; n < SB16_NCoef; n++)
gain += low_fir_sb16_coef[n];
/*Normalise filter, to produce unity gain*/
for (n = 0; n < SB16_NCoef; n++)
low_fir_sb16_coef[n] /= gain;
}
void sb_irq(sb_dsp_t *dsp, int irq8)
@@ -423,6 +460,8 @@ void sb_exec_command(sb_dsp_t *dsp)
temp = 256 - dsp->sb_data[0];
temp = 1000000 / temp;
// pclog("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho);
if (dsp->sb_freq != temp && dsp->sb_type >= SB16)
recalc_sb16_filter(temp);
dsp->sb_freq = temp;
break;
case 0x41: /*Set output sampling rate*/
@@ -430,10 +469,13 @@ void sb_exec_command(sb_dsp_t *dsp)
if (dsp->sb_type < SB16) break;
dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8))));
// pclog("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho);
temp = dsp->sb_freq;
dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8);
dsp->sb_timeo = 256LL + dsp->sb_freq;
dsp->sblatchi = dsp->sblatcho;
dsp->sb_timei = dsp->sb_timeo;
if (dsp->sb_freq != temp && dsp->sb_type >= SB16)
recalc_sb16_filter(dsp->sb_freq);
break;
case 0x48: /*Set DSP block transfer size*/
dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8);
@@ -773,6 +815,10 @@ void sb_dsp_init(sb_dsp_t *dsp, int type)
timer_add(pollsb, &dsp->sbcount, &dsp->sbenable, dsp);
timer_add(sb_poll_i, &dsp->sb_count_i, &dsp->sb_enable_i, dsp);
timer_add(sb_wb_clear, &dsp->wb_time, &dsp->wb_time, dsp);
/*Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when
a set frequency command is sent.*/
recalc_sb16_filter(3200*2);
}
void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr)

View File

@@ -8,7 +8,7 @@
*
* Sound emulation core.
*
* Version: @(#)sound.c 1.0.12 2018/02/11
* Version: @(#)sound.c 1.0.13 2018/02/15
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -48,19 +48,23 @@ typedef struct {
device_t *device;
} SOUND_CARD;
typedef struct {
void (*get_buffer)(int32_t *buffer, int len, void *p);
void *priv;
} sound_handler_t;
int sound_card_current = 0;
int sound_pos_global = 0;
int soundon = 1;
volatile int soundon = 1;
int sound_gain = 0;
static int sound_card_last = 0;
static struct {
void (*get_buffer)(int32_t *buffer, int len, void *p);
void *priv;
} sound_handlers[8];
static sound_handler_t sound_handlers[8];
static sound_handler_t sound_process_handlers[8];
static int sound_handlers_num;
static int sound_process_handlers_num;
static int64_t sound_poll_time = 0LL, sound_poll_latch;
static int16_t cd_buffer[CDROM_NUM][CD_BUFLEN * 2];
static float cd_out_buffer[CD_BUFLEN * 2];
@@ -162,17 +166,19 @@ static void sound_cd_thread(void *param)
float cd_buffer_temp[2] = {0.0, 0.0};
float cd_buffer_temp2[2] = {0.0, 0.0};
int32_t cd_buffer_temp4[2] = {0, 0};
int c, has_audio;
int d;
thread_set_event(sound_cd_start_event);
while (cdaudioon)
{
thread_wait_event(sound_cd_event, -1);
thread_reset_event(sound_cd_event);
if (!soundon || !cdaudioon)
{
return;
}
for (c = 0; c < CD_BUFLEN*2; c += 2)
{
if (sound_is_float)
@@ -189,11 +195,14 @@ static void sound_cd_thread(void *param)
for (i = 0; i < CDROM_NUM; i++)
{
has_audio = 0;
if (cdrom_drives[i].bus_type == CDROM_BUS_DISABLED)
continue;
if (cdrom_drives[i].handler->audio_callback)
{
cdrom_drives[i].handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2);
has_audio = (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on);
}
} else
continue;
if (soundon && has_audio)
{
int32_t audio_vol_l = cdrom_mode_sense_get_volume(i, 0);
@@ -234,12 +243,26 @@ static void sound_cd_thread(void *param)
cd_buffer_temp2[1] += cd_buffer_temp[1];
}
/*Apply sound card CD volume*/
cd_buffer_temp2[0] *= (float) cd_vol_l;
cd_buffer_temp2[0] /= 65535.0;
if (sound_process_handlers_num)
{
cd_buffer_temp4[0] = (int32_t) cd_buffer_temp2[0];
cd_buffer_temp4[1] = (int32_t) cd_buffer_temp2[1];
cd_buffer_temp2[1] *= (float) cd_vol_r;
cd_buffer_temp2[1] /= 65535.0;
for (d = 0; d < sound_process_handlers_num; d++)
sound_process_handlers[d].get_buffer(cd_buffer_temp4, 1, sound_process_handlers[d].priv);
cd_buffer_temp2[0] = (float) cd_buffer_temp4[0];
cd_buffer_temp2[1] = (float) cd_buffer_temp4[1];
}
else
{
/*Apply sound card CD volume*/
cd_buffer_temp2[0] *= (float) cd_vol_l;
cd_buffer_temp2[0] /= 65535.0;
cd_buffer_temp2[1] *= (float) cd_vol_r;
cd_buffer_temp2[1] /= 65535.0;
}
if (sound_is_float)
{
@@ -264,13 +287,9 @@ static void sound_cd_thread(void *param)
}
}
if (sound_is_float)
{
givealbuffer_cd(cd_out_buffer);
}
else
{
givealbuffer_cd(cd_out_buffer_int16);
}
}
}
@@ -327,14 +346,16 @@ void sound_init(void)
if (available_cdrom_drives)
{
cdaudioon = 1;
sound_cd_start_event = thread_create_event();
sound_cd_event = thread_create_event();
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
cdaudioon = 1;
/* pclog("Waiting for CD start event...\n"); */
thread_wait_event(sound_cd_start_event, -1);
thread_reset_event(sound_cd_start_event);
/* pclog("Done!\n"); */
}
else
@@ -350,6 +371,13 @@ void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), vo
sound_handlers_num++;
}
void sound_add_process_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p)
{
sound_process_handlers[sound_process_handlers_num].get_buffer = get_buffer;
sound_process_handlers[sound_process_handlers_num].priv = p;
sound_process_handlers_num++;
}
void sound_poll(void *priv)
{
sound_poll_time += sound_poll_latch;
@@ -422,7 +450,8 @@ void sound_reset(void)
timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL);
sound_handlers_num = 0;
sound_process_handlers_num = 0;
sound_set_cd_volume(65535, 65535);
for (i = 0; i < CDROM_NUM; i++)
@@ -473,13 +502,15 @@ void sound_cd_thread_reset(void)
if (available_cdrom_drives && !cd_thread_enable)
{
cdaudioon = 1;
sound_cd_start_event = thread_create_event();
sound_cd_event = thread_create_event();
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
cdaudioon = 1;
thread_wait_event(sound_cd_start_event, -1);
thread_reset_event(sound_cd_start_event);
}
else if (!available_cdrom_drives && cd_thread_enable)
{

View File

@@ -8,7 +8,7 @@
*
* Sound emulation core.
*
* Version: @(#)sound.h 1.0.4 2018/02/11
* Version: @(#)sound.h 1.0.5 2018/02/15
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -39,6 +39,8 @@ extern int sound_card_current;
extern void sound_add_handler(void (*get_buffer)(int32_t *buffer, \
int len, void *p), void *p);
extern void sound_add_process_handler(void (*get_buffer)(int32_t *buffer, \
int len, void *p), void *p);
extern int sound_card_available(int card);
extern char *sound_card_getname(int card);

View File

@@ -9,7 +9,7 @@
* Implementation of the CD-ROM host drive IOCTL interface for
* Windows using SCSI Passthrough Direct.
*
* Version: @(#)cdrom_ioctl.c 1.0.10 2018/02/01
* Version: @(#)cdrom_ioctl.c 1.0.11 2018/02/15
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -562,7 +562,7 @@ static void ioctl_load(uint8_t id)
cdrom_ioctl[id].cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0);
}
static int is_track_audio(uint8_t id, uint32_t pos)
static int ioctl_is_track_audio(uint8_t id, uint32_t pos, int ismsf)
{
int c;
int control = 0;
@@ -576,43 +576,25 @@ static int is_track_audio(uint8_t id, uint32_t pos)
for (c = 0; cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber != 0xaa; c++)
{
track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]);
if (ismsf) {
track_address = cdrom_ioctl_windows[id].toc.TrackData[c].Address[3];
track_address |= (cdrom_ioctl_windows[id].toc.TrackData[c].Address[2] << 8);
track_address |= (cdrom_ioctl_windows[id].toc.TrackData[c].Address[1] << 16);
} else {
track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]);
track_address -= 150;
}
if (cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber >= cdrom_ioctl_windows[id].toc.FirstTrack &&
cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber <= cdrom_ioctl_windows[id].toc.LastTrack &&
track_address <= pos)
{
control = cdrom_ioctl_windows[id].toc.TrackData[c].Control;
break;
}
}
if ((control & 0xd) <= 1)
{
return 1;
}
else
{
return 0;
}
}
static int ioctl_is_track_audio(uint8_t id, uint32_t pos, int ismsf)
{
int m = 0, s = 0, f = 0;
if (ismsf)
{
m = (pos >> 16) & 0xff;
s = (pos >> 8) & 0xff;
f = pos & 0xff;
pos = MSFtoLBA(m, s, f);
}
else
{
pos += 150;
}
return is_track_audio(id, pos);
}
/* 00, 08, 10, 18, 20, 28, 30, 38 */

View File

@@ -9,7 +9,7 @@
* Implementation of the Iomega ZIP drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)zip.c 1.0.4 2018/02/07
* Version: @(#)zip.c 1.0.5 2018/02/15
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -2194,6 +2194,12 @@ void zip_pio_request(uint8_t id, uint8_t out)
/* Make sure to keep pos, and reset request_pos to 0. */
/* Also make sure to not reset total_read. */
/* If less than (packet length) bytes are remaining, update packet length
accordingly. */
if ((zip[id].packet_len - zip[id].pos) < (zip[id].request_length))
zip[id].request_length = zip[id].packet_len - zip[id].pos;
old_pos = zip[id].pos;
zip[id].packet_status = out ? ZIP_PHASE_DATA_OUT : ZIP_PHASE_DATA_IN;
zip_command_common(id);