From 6cab207231d151f27310e5bdfd34f99eebca6aae Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 15 Feb 2018 23:14:44 +0100 Subject: [PATCH] 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. --- src/cdrom/cdrom.c | 56 +++++-- src/cdrom/cdrom_dosbox.cpp | 70 ++++++++- src/cdrom/cdrom_dosbox.h | 4 + src/cdrom/cdrom_image.cc | 302 +++++++++++++++++++++++++------------ src/sound/filters.h | 30 ++++ src/sound/snd_sb.c | 52 +++++-- src/sound/snd_sb_dsp.c | 46 ++++++ src/sound/sound.c | 73 ++++++--- src/sound/sound.h | 4 +- src/win/win_cdrom_ioctl.c | 38 ++--- src/zip.c | 8 +- 11 files changed, 514 insertions(+), 169 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 592122a6e..b64ba0129 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -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, * @@ -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; } } diff --git a/src/cdrom/cdrom_dosbox.cpp b/src/cdrom/cdrom_dosbox.cpp index e65fe5a9c..99e966640 100644 --- a/src/cdrom/cdrom_dosbox.cpp +++ b/src/cdrom/cdrom_dosbox.cpp @@ -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; diff --git a/src/cdrom/cdrom_dosbox.h b/src/cdrom/cdrom_dosbox.h index d580f6dc6..f5dc4f346 100644 --- a/src/cdrom/cdrom_dosbox.h +++ b/src/cdrom/cdrom_dosbox.h @@ -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); diff --git a/src/cdrom/cdrom_image.cc b/src/cdrom/cdrom_image.cc index 89fef440d..da066c360 100644 --- a/src/cdrom/cdrom_image.cc +++ b/src/cdrom/cdrom_image.cc @@ -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; } diff --git a/src/sound/filters.h b/src/sound/filters.h index bf98aec1f..95354176e 100644 --- a/src/sound/filters.h +++ b/src/sound/filters.h @@ -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; +} diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 5b6f4ac02..0f21b9464 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -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, * Miran Grca, @@ -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); diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 4c6084042..fd71a697d 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -4,6 +4,7 @@ 486-50 - 32kHz Pentium - 45kHz*/ +#include #include #include #include @@ -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) diff --git a/src/sound/sound.c b/src/sound/sound.c index fbb2cc321..96de19948 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -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, * Miran Grca, @@ -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) { diff --git a/src/sound/sound.h b/src/sound/sound.h index 39a2abc45..5f26736cc 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -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, * Miran Grca, @@ -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); diff --git a/src/win/win_cdrom_ioctl.c b/src/win/win_cdrom_ioctl.c index 48a4c60e6..9b1e588bb 100644 --- a/src/win/win_cdrom_ioctl.c +++ b/src/win/win_cdrom_ioctl.c @@ -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, * Miran Grca, @@ -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 */ diff --git a/src/zip.c b/src/zip.c index 7d14ac420..c688d25f6 100644 --- a/src/zip.c +++ b/src/zip.c @@ -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, * @@ -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);