From 10503674eb0a6ae5ef555adf4bc6fcfa506d24cd Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 27 Jan 2017 23:03:20 +0100 Subject: [PATCH] All MODE SENSE and MODE SELECT commands now support the block descriptor when a CD-ROM drive is set to SCSI; Fixed MODE SELECT behavior with ATAPI; Removed excess PIIX logging; Fixed and improved the CD Audio buffer code in sound.c. --- src/cdrom-ioctl.c | 167 +++++++++++++++++++----------- src/cdrom-iso.c | 13 +++ src/cdrom-null.c | 6 ++ src/cdrom.c | 255 +++++++++++++++++++++++++++++++++------------- src/cdrom.h | 2 + src/piix.c | 1 - src/sound.c | 106 ++++++++++--------- 7 files changed, 371 insertions(+), 179 deletions(-) diff --git a/src/cdrom-ioctl.c b/src/cdrom-ioctl.c index fdd4433ef..807f188fd 100644 --- a/src/cdrom-ioctl.c +++ b/src/cdrom-ioctl.c @@ -304,6 +304,7 @@ static int ioctl_medium_changed(uint8_t id) if (!cdrom_ioctl[id].tocvalid || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) { cdrom_ioctl[id].cd_state = CD_STOPPED; + cdrom_ioctl_log("Setting TOC...\n"); cdrom_ioctl_windows[id].toc = ltoc; cdrom_ioctl[id].tocvalid = 1; if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive) @@ -318,6 +319,7 @@ static int ioctl_medium_changed(uint8_t id) (ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3])) { cdrom_ioctl[id].cd_state = CD_STOPPED; + cdrom_ioctl_log("Setting TOC...\n"); cdrom_ioctl_windows[id].toc = ltoc; cdrom_ioctl[id].cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); return 1; /* TOC mismatches. */ @@ -345,69 +347,77 @@ static uint8_t ioctl_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) int track = get_track_nr(id, cdpos); uint32_t track_address = cdrom_ioctl_windows[id].toc.TrackData[track].Address[3] + (cdrom_ioctl_windows[id].toc.TrackData[track].Address[2] * 75) + (cdrom_ioctl_windows[id].toc.TrackData[track].Address[1] * 75 * 60); - b[pos++] = sub.CurrentPosition.Control; - b[pos++] = track + 1; - b[pos++] = sub.CurrentPosition.IndexNumber; + cdrom_ioctl_log("cdpos = %i, track = %i, track_address = %i\n", cdpos, track, track_address); + + b[pos++] = sub.CurrentPosition.Control; + b[pos++] = track + 1; + b[pos++] = sub.CurrentPosition.IndexNumber; - if (msf) - { - uint32_t dat = cdpos; - b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; - b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; - b[pos + 1] = (uint8_t)dat; - b[pos] = 0; - pos += 4; - dat = cdpos - track_address; - b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; - b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; - b[pos + 1] = (uint8_t)dat; - b[pos] = 0; - pos += 4; - } - else - { - b[pos++] = (cdpos >> 24) & 0xff; - b[pos++] = (cdpos >> 16) & 0xff; - b[pos++] = (cdpos >> 8) & 0xff; - b[pos++] = cdpos & 0xff; - cdpos -= track_address; - b[pos++] = (cdpos >> 24) & 0xff; - b[pos++] = (cdpos >> 16) & 0xff; - b[pos++] = (cdpos >> 8) & 0xff; - b[pos++] = cdpos & 0xff; - } + if (msf) + { + uint32_t dat = cdpos; + b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; + b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; + b[pos + 1] = (uint8_t)dat; + b[pos] = 0; + pos += 4; + dat = cdpos - track_address; + b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; + b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; + b[pos + 1] = (uint8_t)dat; + b[pos] = 0; + pos += 4; + } + else + { + b[pos++] = (cdpos >> 24) & 0xff; + b[pos++] = (cdpos >> 16) & 0xff; + b[pos++] = (cdpos >> 8) & 0xff; + b[pos++] = cdpos & 0xff; + cdpos -= track_address; + b[pos++] = (cdpos >> 24) & 0xff; + b[pos++] = (cdpos >> 16) & 0xff; + b[pos++] = (cdpos >> 8) & 0xff; + b[pos++] = cdpos & 0xff; + } - if (cdrom_ioctl[id].cd_state == CD_PLAYING) return 0x11; - return 0x12; - } + if (cdrom_ioctl[id].cd_state == CD_PLAYING) return 0x11; + return 0x12; + } - b[pos++]=sub.CurrentPosition.Control; - b[pos++]=sub.CurrentPosition.TrackNumber; - b[pos++]=sub.CurrentPosition.IndexNumber; + b[pos++]=sub.CurrentPosition.Control; + b[pos++]=sub.CurrentPosition.TrackNumber; + b[pos++]=sub.CurrentPosition.IndexNumber; + + cdrom_ioctl_log("cdpos = %i, track_address = %i\n", MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]), MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3])); - if (msf) - { - int c; - for (c = 0; c < 4; c++) - b[pos++] = sub.CurrentPosition.AbsoluteAddress[c]; - for (c = 0; c < 4; c++) - b[pos++] = sub.CurrentPosition.TrackRelativeAddress[c]; - } - else - { - uint32_t temp = MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]); - b[pos++] = temp >> 24; - b[pos++] = temp >> 16; - b[pos++] = temp >> 8; - b[pos++] = temp; - temp = MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3]); - b[pos++] = temp >> 24; - b[pos++] = temp >> 16; - b[pos++] = temp >> 8; - b[pos++] = temp; - } + if (msf) + { + int c; + for (c = 0; c < 4; c++) + { + b[pos++] = sub.CurrentPosition.AbsoluteAddress[c]; + } + for (c = 0; c < 4; c++) + { + b[pos++] = sub.CurrentPosition.TrackRelativeAddress[c]; + } + } + else + { + uint32_t temp = MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]); + b[pos++] = temp >> 24; + b[pos++] = temp >> 16; + b[pos++] = temp >> 8; + b[pos++] = temp; + temp = MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3]); + b[pos++] = temp >> 24; + b[pos++] = temp >> 16; + b[pos++] = temp >> 8; + b[pos++] = temp; + } - return 0x13; + return 0x13; } static void ioctl_eject(uint8_t id) @@ -664,6 +674,43 @@ static void ioctl_read_capacity(uint8_t id, uint8_t *b) ioctl_close(id); } +static int ioctl_media_type_id(uint8_t id) +{ + uint8_t old_sense[3] = { 0, 0, 0 }; + + UCHAR msbuf[28]; + int len = 0; + int sense = 0; + + const UCHAR cdb[] = { 0x5A, 0x00, 0x2A, 0, 0, 0, 0, 0, 28, 0, 0, 0 }; + + old_sense[0] = cdrom_sense_key; + old_sense[1] = cdrom_asc; + old_sense[2] = cdrom_asc; + + ioctl_open(id, 0); + + SCSICommand(id, cdb, msbuf, &len, 1); + + pclog("Returned length: %i, media type: %i\n", len, msbuf[2]); + + ioctl_close(id); + + sense = cdrom_sense_key; + cdrom_sense_key = old_sense[0]; + cdrom_asc = old_sense[1]; + cdrom_asc = old_sense[2]; + + if (sense == 0) + { + return msbuf[2]; + } + else + { + return 3; + } +} + static uint32_t msf_to_lba32(int lba) { int m = (lba >> 16) & 0xff; @@ -754,6 +801,7 @@ static void ioctl_validate_toc(uint8_t id) } cdrom_ioctl[id].cd_state = CD_STOPPED; ioctl_open(id, 0); + cdrom_ioctl_log("Validating TOC...\n"); DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&cdrom_ioctl_windows[id].toc,sizeof(cdrom_ioctl_windows[id].toc),&size,NULL); ioctl_close(id); cdrom_ioctl[id].tocvalid=1; @@ -781,7 +829,7 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t int temp_len = 0; int chunk = 0; - if (cdb[0] == 0x43) + if (in_cdb[0] == 0x43) { /* This is a read TOC, so we have to validate the TOC to make the rest of the emulator happy. */ ioctl_validate_toc(id); @@ -950,6 +998,7 @@ static CDROM ioctl_cdrom= { ioctl_ready, ioctl_medium_changed, + ioctl_media_type_id, ioctl_audio_callback, ioctl_audio_stop, NULL, diff --git a/src/cdrom-iso.c b/src/cdrom-iso.c index 241e1e3dd..dc10fbf64 100644 --- a/src/cdrom-iso.c +++ b/src/cdrom-iso.c @@ -589,10 +589,23 @@ static int iso_is_track_audio(uint8_t id, uint32_t pos, int ismsf) return 0; } +static int iso_media_type_id(uint8_t id) +{ + if (iso_size(id) <= 405000) + { + return 1; /* Data CD. */ + } + else + { + return 65; /* DVD. */ + } +} + static CDROM iso_cdrom = { iso_ready, iso_medium_changed, + iso_media_type_id, NULL, NULL, iso_readtoc, diff --git a/src/cdrom-null.c b/src/cdrom-null.c index 6e886ed27..2409df412 100644 --- a/src/cdrom-null.c +++ b/src/cdrom-null.c @@ -100,10 +100,16 @@ static int null_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t * return 0; } +static int null_media_type_id(uint8_t id) +{ + return 0x70; +} + static CDROM null_cdrom = { null_ready, null_medium_changed, + null_media_type_id, NULL, NULL, null_readtoc, diff --git a/src/cdrom.c b/src/cdrom.c index b86ffd284..02d693b43 100644 --- a/src/cdrom.c +++ b/src/cdrom.c @@ -27,8 +27,9 @@ #define MODE_SELECT_PHASE_IDLE 0 #define MODE_SELECT_PHASE_HEADER 1 -#define MODE_SELECT_PHASE_PAGE_HEADER 2 -#define MODE_SELECT_PHASE_PAGE 3 +#define MODE_SELECT_PHASE_BLOCK_DESC 2 +#define MODE_SELECT_PHASE_PAGE_HEADER 3 +#define MODE_SELECT_PHASE_PAGE 4 cdrom_t cdrom[CDROM_NUM]; cdrom_drive_t cdrom_drives[CDROM_NUM]; @@ -170,19 +171,19 @@ uint8_t cdrom_mode_sense_pages_changeable[CDROM_NUM][0x40][0x40] = { { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 }, [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 }, - [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0xFF, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 }, [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 }, - [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0xFF, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 }, [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 }, - [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0xFF, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 }, [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 }, - [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0xFF, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } }; @@ -535,7 +536,7 @@ int cdrom_mode_select_terminate(uint8_t id, int force) { cdrom_mode_sense_save(id); } - cdrom[id].current_page_pos = cdrom[id].current_page_len = 0; + cdrom[id].current_page_pos = cdrom[id].current_page_len = cdrom[id].block_descriptor_len = 0; cdrom[id].total_length = cdrom[id].written_length = 0; cdrom[id].mode_select_phase = MODE_SELECT_PHASE_IDLE; if (force) @@ -550,10 +551,51 @@ int cdrom_mode_select_terminate(uint8_t id, int force) } } -int cdrom_mode_select_header(uint8_t id) +int cdrom_mode_select_header(uint8_t id, uint8_t val) +{ + if (cdrom[id].current_page_pos == 0) + { + cdrom[id].block_descriptor_len = 0; + } + else if (cdrom[id].current_page_pos == (cdrom[id].current_page_len - 2)) + { + if (cdrom_drives[id].bus_type && (cdrom[id].current_page_len == 8)) + { + cdrom[id].block_descriptor_len |= ((uint16_t) val) << 8; + cdrom_log("CD-ROM %i: Position: %02X, value: %02X, block descriptor length: %02X\n", id, cdrom[id].current_page_pos, val, cdrom[id].block_descriptor_len); + } + } + else if (cdrom[id].current_page_pos == (cdrom[id].current_page_len - 1)) + { + if (cdrom_drives[id].bus_type) + { + cdrom[id].block_descriptor_len |= (uint16_t) val; + cdrom_log("CD-ROM %i: Position: %02X, value: %02X, block descriptor length: %02X\n", id, cdrom[id].current_page_pos, val, cdrom[id].block_descriptor_len); + } + } + + cdrom[id].current_page_pos++; + + if (cdrom[id].current_page_pos >= cdrom[id].current_page_len) + { + cdrom[id].current_page_pos = 0; + if (cdrom[id].block_descriptor_len) + { + cdrom[id].mode_select_phase = MODE_SELECT_PHASE_BLOCK_DESC; + } + else + { + cdrom[id].mode_select_phase = MODE_SELECT_PHASE_PAGE_HEADER; + } + } + + return 1; +} + +int cdrom_mode_select_block_desc(uint8_t id) { cdrom[id].current_page_pos++; - if (cdrom[id].current_page_pos >= cdrom[id].current_page_len) + if (cdrom[id].current_page_pos >= 8) { cdrom[id].current_page_pos = 0; cdrom[id].mode_select_phase = MODE_SELECT_PHASE_PAGE_HEADER; @@ -652,7 +694,11 @@ int cdrom_mode_select_write(uint8_t id, uint8_t val) break; case MODE_SELECT_PHASE_HEADER: cdrom_log("CD-ROM %i: MODE SELECT header (%02X)\n", id, val); - ret = cdrom_mode_select_header(id); + ret = cdrom_mode_select_header(id, val); + break; + case MODE_SELECT_PHASE_BLOCK_DESC: + cdrom_log("CD-ROM %i: MODE SELECT block descriptor (%02X)\n", id, val); + ret = cdrom_mode_select_block_desc(id); break; case MODE_SELECT_PHASE_PAGE_HEADER: cdrom_log("CD-ROM %i: MODE SELECT page header (%02X)\n", id, val); @@ -682,6 +728,41 @@ int cdrom_mode_select_write(uint8_t id, uint8_t val) return ret; } +uint8_t cdrom_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static int cdrom_pass_through(uint8_t id, int *len, uint8_t *cdb, uint8_t *buffer); + +int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, int *len) +{ + int ret = 0; + int size = 0; + + if (cdrom_drives[id].handler->pass_through) + { + ret = cdrom_pass_through(id, len, cdb, buffer); + if (!ret) + { + return 0; + } + if (*len == 65534) + { + *len = 8; + } + } + else + { + size = cdrom_drives[id].handler->size(id) - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(buffer, 0, 8); + buffer[0] = (size >> 24) & 0xff; + buffer[1] = (size >> 16) & 0xff; + buffer[2] = (size >> 8) & 0xff; + buffer[3] = size & 0xff; + buffer[6] = 8; /* 2048 = 0x0800 */ + *len = 8; + } + return 1; +} + /*SCSI Mode Sense 6/10*/ uint8_t cdrom_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) { @@ -700,7 +781,7 @@ uint8_t cdrom_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, ui } } -uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type) +uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) { uint8_t page_control = (type >> 6) & 3; @@ -711,6 +792,20 @@ uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type) type &= 0x3f; + int len = 0; + + if (block_descriptor_len) + { + buf[pos++] = 1; /* Density code. */ + buf[pos++] = 0; /* Number of blocks (0 = all). */ + buf[pos++] = 0; + buf[pos++] = 0; + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ + buf[pos++] = 8; + buf[pos++] = 0; + } + for (i = 0; i < 0x40; i++) { if ((type == GPMODE_ALL_PAGES) || (type == i)) @@ -1018,13 +1113,15 @@ static void cdrom_data_phase_error(uint8_t id) cdrom_cmd_error(id); } -static int cdrom_pass_through(uint8_t id, int *len) +static int cdrom_pass_through(uint8_t id, int *len, uint8_t *cdb, uint8_t *buffer) { int ret = 0; - uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer; + // uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer; - ret = cdrom_drives[id].handler->pass_through(id, cdrom[id].current_cdb, cdbufferb + cdrom[id].data_pos, len); - cdrom_log("CD-ROM %i: Data from pass through: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[cdrom[id].data_pos + 0], cdbufferb[cdrom[id].data_pos + 1], cdbufferb[cdrom[id].data_pos + 2], cdbufferb[cdrom[id].data_pos + 3], cdbufferb[cdrom[id].data_pos + 4], cdbufferb[cdrom[id].data_pos + 5], cdbufferb[cdrom[id].data_pos + 6], cdbufferb[cdrom[id].data_pos + 7]); + // ret = cdrom_drives[id].handler->pass_through(id, cdrom[id].current_cdb, cdbufferb + cdrom[id].data_pos, len); + ret = cdrom_drives[id].handler->pass_through(id, cdb, buffer, len); + // cdrom_log("CD-ROM %i: Data from pass through: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[cdrom[id].data_pos + 0], cdbufferb[cdrom[id].data_pos + 1], cdbufferb[cdrom[id].data_pos + 2], cdbufferb[cdrom[id].data_pos + 3], cdbufferb[cdrom[id].data_pos + 4], cdbufferb[cdrom[id].data_pos + 5], cdbufferb[cdrom[id].data_pos + 6], cdbufferb[cdrom[id].data_pos + 7]); + cdrom_log("CD-ROM %i: Data from pass through: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]); cdrom_log("CD-ROM %i: Returned value: %i\n", id, ret); if (!ret) @@ -1124,7 +1221,7 @@ int cdrom_read_data(uint8_t id, int msf, int type, int flags, int *len) { cdsize = cdrom_drives[id].handler->size(id); - ret = cdrom_pass_through(id, len); + ret = cdrom_pass_through(id, len, cdrom[id].current_cdb, cdbufferb + cdrom[id].data_pos); cdrom[id].data_pos += *len; if (!ret) @@ -1656,6 +1753,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb) int alloc_length; int completed; uint8_t index = 0; + int block_desc = 0; int media; int format; int ret; @@ -1688,16 +1786,19 @@ void cdrom_command(uint8_t id, uint8_t *cdb) memcpy(cdrom[id].current_cdb, cdb, cdrom[id].cdb_len); - cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, ins, cdrom[id].unit_attention); - cdrom_log("CD-ROM %i: Request length: %04X\n", id, cdrom[id].request_length); -#if 0 - - int CdbLength; - for (CdbLength = 1; CdbLength < cdrom[id].cdb_len; CdbLength++) + if (cdb[0] != 0) { - cdrom_log("CD-ROM %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]); - } + cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, ins, cdrom[id].unit_attention); + cdrom_log("CD-ROM %i: Request length: %04X\n", id, cdrom[id].request_length); + +#if 0 + int CdbLength; + for (CdbLength = 1; CdbLength < cdrom[id].cdb_len; CdbLength++) + { + cdrom_log("CD-ROM %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]); + } #endif + } msf = cdb[1] & 2; cdrom[id].sector_len = 0; @@ -1754,7 +1855,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb) if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len); + ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb); if (!ret) { return; @@ -1894,7 +1995,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb) case GPCMD_READ_HEADER: if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len); + ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb); if (!ret) { return; @@ -1927,6 +2028,15 @@ void cdrom_command(uint8_t id, uint8_t *cdb) case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: + if (cdrom_drives[id].bus_type) + { + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + } + else + { + block_desc = 0; + } + if (cdb[0] == GPCMD_MODE_SENSE_6) { len = cdb[4]; @@ -1947,30 +2057,44 @@ void cdrom_command(uint8_t id, uint8_t *cdb) if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdrom_mode_sense(id, cdbufferb, 4, cdb[2]); - cdbufferb[0] = len - 1; - cdbufferb[1] = 3; /*120mm data CD-ROM*/ + len = cdrom_mode_sense(id, cdbufferb, 4, cdb[2], block_desc); if (len > alloc_length) { len = alloc_length; } + cdbufferb[0] = len - 1; + cdbufferb[1] = cdrom_drives[id].handler->media_type_id(id); + if (block_desc) + { + cdbufferb[3] = 8; + } } else { - len = cdrom_mode_sense(id, cdbufferb, 8, cdb[2]); + len = cdrom_mode_sense(id, cdbufferb, 8, cdb[2], block_desc); if (len > alloc_length) { len = alloc_length; } cdbufferb[0]=(len - 2) >> 8; cdbufferb[1]=(len - 2) & 255; - cdbufferb[2] = 3; /*120mm data CD-ROM*/ - if (len > alloc_length) + cdbufferb[2] = cdrom_drives[id].handler->media_type_id(id); + if (block_desc) { - len = alloc_length; + cdbufferb[6] = 0; + cdbufferb[7] = 8; } } + if (len > alloc_length) + { + len = alloc_length; + } + else if (len < alloc_length) + { + alloc_length = len; + } + cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", id, cdb[2]); cdrom_data_command_finish(id, len, len, alloc_length, 0); @@ -2105,7 +2229,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb) if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len); + ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb); if (!ret) { return; @@ -2145,7 +2269,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb) if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len); + ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb); if (!ret) { return; @@ -2246,11 +2370,12 @@ void cdrom_command(uint8_t id, uint8_t *cdb) max_len = cdb[7]; max_len <<= 8; max_len |= cdb[8]; + msf = (cdb[1] >> 1) & 1; cdrom_log("CD-ROM %i: Getting page %i\n", id, cdb[3]); if ((cdrom_drives[id].handler->pass_through) && (cdb[3] != 1)) { - ret = cdrom_pass_through(id, &len); + ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb); if (!ret) { return; @@ -2264,15 +2389,11 @@ void cdrom_command(uint8_t id, uint8_t *cdb) case CD_STATUS_PAUSED: cdbufferb[1] = 0x12; break; + case CD_STATUS_DATA_ONLY: + cdbufferb[1] = 0x15; + break; default: - if (completed) - { - cdbufferb[1] = 0x13; - } - else - { - cdbufferb[1] = 0x15; - } + cdbufferb[1] = 0x13; break; } if (len == 65534) @@ -2322,9 +2443,20 @@ void cdrom_command(uint8_t id, uint8_t *cdb) if (cdb[3] == 1) { cdbufferb[1] = cdrom_drives[id].handler->getcurrentsubchannel(id, &cdbufferb[5], msf); - if (((cdbufferb[1] == 0x13) && !completed) || (cdrom[id].cd_status == CD_STATUS_DATA_ONLY)) + switch(cdrom[id].cd_status) { - cdbufferb[1] = 0x15; + case CD_STATUS_PLAYING: + cdbufferb[1] = 0x11; + break; + case CD_STATUS_PAUSED: + cdbufferb[1] = 0x12; + break; + case CD_STATUS_DATA_ONLY: + cdbufferb[1] = 0x15; + break; + default: + cdbufferb[1] = 0x13; + break; } } if (!(cdb[2] & 0x40) || (cdb[3] == 0)) @@ -2343,7 +2475,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb) case GPCMD_READ_DVD_STRUCTURE: if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len); + ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb); if (!ret) { return; @@ -2559,28 +2691,9 @@ atapi_out: break; case GPCMD_READ_CDROM_CAPACITY: - if (cdrom_drives[id].handler->pass_through) + if (cdrom_read_capacity(id, cdrom[id].current_cdb, cdbufferb, &len) == 0) { - ret = cdrom_pass_through(id, &len); - if (!ret) - { - return; - } - if (len == 65534) - { - len = 8; - } - } - else - { - size = cdrom_drives[id].handler->size(id) - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(cdbufferb, 0, 8); - cdbufferb[0] = (size >> 24) & 0xff; - cdbufferb[1] = (size >> 16) & 0xff; - cdbufferb[2] = (size >> 8) & 0xff; - cdbufferb[3] = size & 0xff; - cdbufferb[6] = 8; /* 2048 = 0x0800 */ - len = 8; + return; } cdrom_data_command_finish(id, len, len, len, 0); @@ -3037,6 +3150,8 @@ void cdrom_write(uint8_t channel, uint32_t val, int length) uint16_t *cdbufferw; uint32_t *cdbufferl; + uint8_t old_pos = 0; + uint8_t id = atapi_cdrom_drives[channel]; int ret = 0; @@ -3050,6 +3165,8 @@ void cdrom_write(uint8_t channel, uint32_t val, int length) cdbufferw = cdrom[id].buffer; cdbufferl = (uint32_t *) cdrom[id].buffer; + old_pos = cdrom[id].pos; + switch(length) { case 1: @@ -3072,7 +3189,7 @@ void cdrom_write(uint8_t channel, uint32_t val, int length) { for (i = 0; i < length; i++) { - ret = cdrom_mode_select_write(id, val); + ret = cdrom_mode_select_write(id, cdbufferb[old_pos + i]); cdrom_mode_select_return(id, ret); } return; diff --git a/src/cdrom.h b/src/cdrom.h index 3cbbcaec2..08dc4ffc2 100644 --- a/src/cdrom.h +++ b/src/cdrom.h @@ -24,6 +24,7 @@ typedef struct CDROM { int (*ready)(uint8_t id); int (*medium_changed)(uint8_t id); + int (*media_type_id)(uint8_t id); void (*audio_callback)(uint8_t id, int16_t *output, int len); void (*audio_stop)(uint8_t id); int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); @@ -110,6 +111,7 @@ typedef struct __attribute__((__packed__)) int all_blocks_total; int old_len; + int block_descriptor_len; } cdrom_t; extern cdrom_t cdrom[CDROM_NUM]; diff --git a/src/piix.c b/src/piix.c index e4297d276..2a28547c9 100644 --- a/src/piix.c +++ b/src/piix.c @@ -85,7 +85,6 @@ void piix_write(int func, int addr, uint8_t val, void *priv) { uint16_t base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); - pclog("Setting PIIX IDE bus master to new base address: %04X\n", base); if (card_piix_ide[0x04] & 1) { io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); diff --git a/src/sound.c b/src/sound.c index 97ee72733..e290a0fdc 100644 --- a/src/sound.c +++ b/src/sound.c @@ -109,15 +109,15 @@ static void sound_cd_thread(void *param) { int i = 0; - while (1) - { - int c, has_audio; - - thread_wait_event(sound_cd_event, -1); + while (1) + { + int c, has_audio; + + thread_wait_event(sound_cd_event, -1); for (c = 0; c < CD_BUFLEN*2; c += 2) { - cd_out_buffer[c] = 0; - cd_out_buffer[c+1] = 0; + cd_out_buffer[c] = 0.0; + cd_out_buffer[c+1] = 0.0; } for (i = 0; i < CDROM_NUM; i++) { @@ -127,57 +127,63 @@ static void sound_cd_thread(void *param) cdrom_drives[i].handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2); has_audio = cdrom_drives[i].sound_on; } - if (soundon && has_audio) - { - int32_t audio_vol_l = cdrom_mode_sense_get_volume(i, 0); - int32_t audio_vol_r = cdrom_mode_sense_get_volume(i, 1); - int channel_select[2]; - - channel_select[0] = cdrom_mode_sense_get_channel(i, 0); - channel_select[1] = cdrom_mode_sense_get_channel(i, 1); - - for (c = 0; c < CD_BUFLEN*2; c += 2) - { - int32_t cd_buffer_temp[2] = {0, 0}; + if (soundon && has_audio) + { + int32_t audio_vol_l = cdrom_mode_sense_get_volume(i, 0); + int32_t audio_vol_r = cdrom_mode_sense_get_volume(i, 1); + int channel_select[2]; - /*First, adjust input from drive according to ATAPI/SCSI volume.*/ - cd_buffer[i][c] = ((int32_t)cd_buffer[i][c] * audio_vol_l) / 255; - cd_buffer[i][c+1] = ((int32_t)cd_buffer[i][c+1] * audio_vol_r) / 255; + channel_select[0] = cdrom_mode_sense_get_channel(i, 0); + channel_select[1] = cdrom_mode_sense_get_channel(i, 1); - /*Apply ATAPI channel select*/ - if (channel_select[0] & 1) - cd_buffer_temp[0] += cd_buffer[i][c]; - if (channel_select[0] & 2) - cd_buffer_temp[1] += cd_buffer[i][c]; - if (channel_select[1] & 1) - cd_buffer_temp[0] += cd_buffer[i][c+1]; - if (channel_select[1] & 2) - cd_buffer_temp[1] += cd_buffer[i][c+1]; - - /*Apply sound card CD volume*/ - cd_buffer_temp[0] = (cd_buffer_temp[0] * (int)cd_vol_l) / 65535; - cd_buffer_temp[1] = (cd_buffer_temp[1] * (int)cd_vol_r) / 65535; + for (c = 0; c < CD_BUFLEN*2; c += 2) + { + float cd_buffer_temp[2] = {0.0, 0.0}; + float cd_buffer_temp2[2] = {0.0, 0.0}; - if (cd_buffer_temp[0] > 32767) - cd_buffer_temp[0] = 32767; - if (cd_buffer_temp[0] < -32768) - cd_buffer_temp[0] = -32768; - if (cd_buffer_temp[1] > 32767) - cd_buffer_temp[1] = 32767; - if (cd_buffer_temp[1] < -32768) - cd_buffer_temp[1] = -32768; + /* First, transfer the CD audio data to the temporary buffer. */ + cd_buffer_temp[0] = (float) cd_buffer[i][c]; + cd_buffer_temp[1] = (float) cd_buffer[i][c+1]; + + /* Then, adjust input from drive according to ATAPI/SCSI volume. */ + cd_buffer_temp[0] *= (float) audio_vol_l; + cd_buffer_temp[0] /= 255.0; + cd_buffer_temp[1] *= (float) audio_vol_r; + cd_buffer_temp[1] /= 255.0; - cd_buffer[i][c] = cd_buffer_temp[0]; - cd_buffer[i][c+1] = cd_buffer_temp[1]; + /*Apply ATAPI channel select*/ + cd_buffer_temp2[0] = cd_buffer_temp2[1] = 0.0; + if (channel_select[0] & 1) + { + cd_buffer_temp2[0] += cd_buffer_temp[0]; + } + if (channel_select[0] & 2) + { + cd_buffer_temp2[1] += cd_buffer_temp[0]; + } + if (channel_select[1] & 1) + { + cd_buffer_temp2[0] += cd_buffer_temp[1]; + } + if (channel_select[1] & 2) + { + cd_buffer_temp2[1] += cd_buffer_temp[1]; + } - cd_out_buffer[c] += ((float) cd_buffer[i][c]) / 32768.0; - cd_out_buffer[c+1] += ((float) cd_buffer[i][c+1]) / 32768.0; - } + /*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; + + cd_out_buffer[c] += (cd_buffer_temp2[0] / 32768.0); + cd_out_buffer[c+1] += (cd_buffer_temp2[1] / 32768.0); + } + } } givealbuffer_cd(cd_out_buffer); - } + } } static int32_t *outbuffer;