diff --git a/src/cdrom.c b/src/cdrom.c index 21eba3ae0..2f02f42cd 100644 --- a/src/cdrom.c +++ b/src/cdrom.c @@ -2421,7 +2421,9 @@ void cdrom_command(uint8_t id, uint8_t *cdb) ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb); if (!ret) { - return; + /* return; */ + cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; + goto cdrom_readtoc_fallback; } alloc_length = cdbufferb[0]; alloc_length <<= 8; @@ -2434,6 +2436,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb) } else { +cdrom_readtoc_fallback: toc_format = cdb[2] & 0xf; if (toc_format == 0) @@ -2451,7 +2454,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb) cdbufferb[0] = 0; cdbufferb[1] = 0xA; break; case 2: /*Raw*/ - len = cdrom_drives[id].handler->readtoc_raw(id, cdbufferb, msf, max_len); + len = cdrom_drives[id].handler->readtoc_raw(id, cdbufferb, max_len); break; default: cdrom_invalid_field(id); diff --git a/src/cdrom.h b/src/cdrom.h index 6f10756c0..871dc1f02 100644 --- a/src/cdrom.h +++ b/src/cdrom.h @@ -46,7 +46,7 @@ typedef struct CDROM void (*audio_stop)(uint8_t id); int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); int (*readtoc_session)(uint8_t id, uint8_t *b, int msf, int maxlen); - int (*readtoc_raw)(uint8_t id, uint8_t *b, int msf, int maxlen); + int (*readtoc_raw)(uint8_t id, uint8_t *b, int maxlen); uint8_t (*getcurrentsubchannel)(uint8_t id, uint8_t *b, int msf); int (*pass_through)(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len); int (*readsector_raw)(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len); diff --git a/src/cdrom_image.cc b/src/cdrom_image.cc index ae4ef727c..07380e79a 100644 --- a/src/cdrom_image.cc +++ b/src/cdrom_image.cc @@ -854,7 +854,7 @@ static int image_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxl return len; } -static int image_readtoc_raw(uint8_t id, unsigned char *b, int msf, int maxlen) +static int image_readtoc_raw(uint8_t id, unsigned char *b, int maxlen) { int track; int len = 4; diff --git a/src/cdrom_ioctl.c b/src/cdrom_ioctl.c index 5422c25b5..408f691b7 100644 --- a/src/cdrom_ioctl.c +++ b/src/cdrom_ioctl.c @@ -1036,7 +1036,7 @@ split_block_read_iterate: cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is -1, this indicates an illegal mode\n", id, temp_block_length); } - cdrom_ioctl_log("IOCTL DATA: %02X %02X %02X %02X %02X %02X %02X %02X\n", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + cdrom_ioctl_log("IOCTL DATA: %02X %02X %02X %02X %02X %02X %02X %02X\n", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); ioctl_close(id); @@ -1045,6 +1045,160 @@ split_block_read_iterate: return ret; } +static int ioctl_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) +{ + int len=4; + long size; + int c,d; + uint32_t temp; + uint32_t last_block; + if (!cdrom_drives[id].host_drive) + { + return 0; + } + cdrom_ioctl[id].cd_state = CD_STOPPED; + ioctl_hopen(id); + 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; + b[2]=cdrom_ioctl_windows[id].toc.FirstTrack; + b[3]=cdrom_ioctl_windows[id].toc.LastTrack; + d=0; + for (c=0;c<=cdrom_ioctl_windows[id].toc.LastTrack;c++) + { + if (cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber>=starttrack) + { + d=c; + break; + } + } + b[2]=cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber; + last_block = 0; + for (c=d;c<=cdrom_ioctl_windows[id].toc.LastTrack;c++) + { + uint32_t address; + if ((len+8)>maxlen) break; + b[len++]=0; /*Reserved*/ + b[len++]=(cdrom_ioctl_windows[id].toc.TrackData[c].Adr<<4)|cdrom_ioctl_windows[id].toc.TrackData[c].Control; + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber; + b[len++]=0; /*Reserved*/ + 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 (address > last_block) + last_block = address; + + if (msf) + { + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[0]; + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[1]; + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[2]; + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]; + } + else + { + temp=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]) - 150; + b[len++]=temp>>24; + b[len++]=temp>>16; + b[len++]=temp>>8; + b[len++]=temp; + } + if (single) break; + } + b[0] = (uint8_t)(((len-2) >> 8) & 0xff); + b[1] = (uint8_t)((len-2) & 0xff); + return len; +} + +static int ioctl_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) +{ + int len=4; + int size; + uint32_t temp; + CDROM_READ_TOC_EX toc_ex; + CDROM_TOC_SESSION_DATA toc; + if (!cdrom_drives[id].host_drive) + { + return 0; + } + cdrom_ioctl[id].cd_state = CD_STOPPED; + memset(&toc_ex,0,sizeof(toc_ex)); + memset(&toc,0,sizeof(toc)); + toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_SESSION; + toc_ex.Msf=msf; + toc_ex.SessionTrack=0; + ioctl_hopen(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); + ioctl_close(id); + b[2]=toc.FirstCompleteSession; + b[3]=toc.LastCompleteSession; + b[len++]=0; /*Reserved*/ + b[len++]=(toc.TrackData[0].Adr<<4)|toc.TrackData[0].Control; + b[len++]=toc.TrackData[0].TrackNumber; + b[len++]=0; /*Reserved*/ + if (msf) + { + b[len++]=toc.TrackData[0].Address[0]; + b[len++]=toc.TrackData[0].Address[1]; + b[len++]=toc.TrackData[0].Address[2]; + b[len++]=toc.TrackData[0].Address[3]; + } + else + { + temp=MSFtoLBA(toc.TrackData[0].Address[1],toc.TrackData[0].Address[2],toc.TrackData[0].Address[3]) - 150; + b[len++]=temp>>24; + b[len++]=temp>>16; + b[len++]=temp>>8; + b[len++]=temp; + } + + return len; +} + +static int ioctl_readtoc_raw(uint8_t id, uint8_t *b, int maxlen) +{ + int len=4; + int size; + uint32_t temp; + int i; + int BytesRead = 0; + CDROM_READ_TOC_EX toc_ex; + CDROM_TOC_FULL_TOC_DATA toc; + if (!cdrom_drives[id].host_drive) + { + return 0; + } + cdrom_ioctl[id].cd_state = CD_STOPPED; + memset(&toc_ex,0,sizeof(toc_ex)); + memset(&toc,0,sizeof(toc)); + toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_FULL_TOC; + toc_ex.Msf=1; + toc_ex.SessionTrack=0; + ioctl_hopen(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); + ioctl_close(id); + b[2]=toc.FirstCompleteSession; + b[3]=toc.LastCompleteSession; + + size -= sizeof(CDROM_TOC_FULL_TOC_DATA); + size /= sizeof(toc.Descriptors[0]); + + for (i = 0; i <= size; i++) + { + b[len++]=toc.Descriptors[i].SessionNumber; + b[len++]=(toc.Descriptors[i].Adr<<4)|toc.Descriptors[i].Control; + b[len++]=0; + b[len++]=toc.Descriptors[i].Reserved1; /*Reserved*/ + b[len++]=toc.Descriptors[i].MsfExtra[0]; + b[len++]=toc.Descriptors[i].MsfExtra[1]; + b[len++]=toc.Descriptors[i].MsfExtra[2]; + b[len++]=toc.Descriptors[i].Zero; + b[len++]=toc.Descriptors[i].Msf[0]; + b[len++]=toc.Descriptors[i].Msf[1]; + b[len++]=toc.Descriptors[i].Msf[2]; + } + + return len; +} + static uint32_t ioctl_size(uint8_t id) { uint8_t capacity_buffer[8]; @@ -1142,9 +1296,9 @@ static CDROM ioctl_cdrom= ioctl_media_type_id, ioctl_audio_callback, ioctl_audio_stop, - NULL, - NULL, - NULL, + ioctl_readtoc, + ioctl_readtoc_session, + ioctl_readtoc_raw, ioctl_getcurrentsubchannel, ioctl_pass_through, NULL, diff --git a/src/cdrom_null.c b/src/cdrom_null.c index a2383b626..c9d759bba 100644 --- a/src/cdrom_null.c +++ b/src/cdrom_null.c @@ -63,7 +63,7 @@ static int null_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxle return 0; } -static int null_readtoc_raw(uint8_t id, unsigned char *b, int msf, int maxlen) +static int null_readtoc_raw(uint8_t id, unsigned char *b, int maxlen) { return 0; }