/**************************************************************************** * OpenVCDImage: try to open a vcd image from a .cue file ****************************************************************************/ static int OpenVCDImage( vlc_object_t * p_this, const char *psz_dev, vcddev_t *p_vcddev ) { int i_ret = -1; char *p_pos; char *psz_vcdfile = NULL; char *psz_cuefile = NULL; FILE *cuefile = NULL; int *p_sectors = NULL; char line[1024]; bool b_found = false; /* Check if we are dealing with a .cue file */ p_pos = strrchr( psz_dev, '.' ); if( p_pos && !strcmp( p_pos, ".cue" ) ) { /* psz_dev must be the cue file. Let's assume there's a .bin * file with the same filename */ if( asprintf( &psz_vcdfile, "%.*s.bin", (int)(p_pos - psz_dev), psz_dev ) < 0 ) psz_vcdfile = NULL; psz_cuefile = strdup( psz_dev ); } else if( p_pos ) { /* psz_dev must be the actual vcd file. Let's assume there's a .cue * file with the same filename */ if( asprintf( &psz_cuefile, "%.*s.cue", (int)(p_pos - psz_dev), psz_dev ) < 0 ) psz_cuefile = NULL; psz_vcdfile = strdup( psz_dev ); } else { if( asprintf( &psz_cuefile, "%s.cue", psz_dev ) == -1 ) psz_cuefile = NULL; /* If we need to look up the .cue file, then we don't have to look * for the vcd */ psz_vcdfile = strdup( psz_dev ); } if( psz_cuefile == NULL || psz_vcdfile == NULL ) goto error; /* Open the cue file and try to parse it */ msg_Dbg( p_this,"trying .cue file: %s", psz_cuefile ); cuefile = vlc_fopen( psz_cuefile, "rt" ); if( cuefile == NULL ) { msg_Dbg( p_this, "could not find .cue file" ); goto error; } msg_Dbg( p_this,"guessing vcd image file: %s", psz_vcdfile ); p_vcddev->i_vcdimage_handle = vlc_open( psz_vcdfile, O_RDONLY | O_NONBLOCK | O_BINARY ); while( fgets( line, 1024, cuefile ) && !b_found ) { /* We have a cue file, but no valid vcd file yet */ char filename[1024]; char type[16]; int i_temp = sscanf( line, "FILE \"%1023[^\"]\" %15s", filename, type ); switch( i_temp ) { case 2: msg_Dbg( p_this, "the cue file says the data file is %s", type ); if( strcasecmp( type, "BINARY" ) ) goto error; /* Error if not binary, otherwise treat as case 1 */ case 1: if( p_vcddev->i_vcdimage_handle == -1 ) { msg_Dbg( p_this, "we could not find the data file, but we found a new path" ); free( psz_vcdfile); if( *filename != '/' && ((p_pos = strrchr( psz_cuefile, '/' )) || (p_pos = strrchr( psz_cuefile, '\\' ) )) ) { psz_vcdfile = malloc( strlen(filename) + (p_pos - psz_cuefile + 1) + 1 ); strncpy( psz_vcdfile, psz_cuefile, (p_pos - psz_cuefile + 1) ); strcpy( psz_vcdfile + (p_pos - psz_cuefile + 1), filename ); } else psz_vcdfile = strdup( filename ); msg_Dbg( p_this,"using vcd image file: %s", psz_vcdfile ); p_vcddev->i_vcdimage_handle = vlc_open( psz_vcdfile, O_RDONLY | O_NONBLOCK | O_BINARY ); } b_found = true; default: break; } } if( p_vcddev->i_vcdimage_handle == -1) goto error; /* Try to parse the i_tracks and p_sectors info so we can just forget * about the cuefile */ size_t i_tracks = 0; while( fgets( line, 1024, cuefile ) && i_tracks < INT_MAX-1 ) { /* look for a TRACK line */ char psz_dummy[10]; if( !sscanf( line, "%9s", psz_dummy ) || strcmp(psz_dummy, "TRACK") ) continue; /* look for an INDEX line */ while( fgets( line, 1024, cuefile ) ) { int i_num, i_min, i_sec, i_frame; if( (sscanf( line, "%*9s %2u %2u:%2u:%2u", &i_num, &i_min, &i_sec, &i_frame ) != 4) || (i_num != 1) ) continue; int *buf = realloc (p_sectors, (i_tracks + 1) * sizeof (*buf)); if (buf == NULL) goto error; p_sectors = buf; p_sectors[i_tracks] = MSF_TO_LBA(i_min, i_sec, i_frame); msg_Dbg( p_this, "vcd track %i begins at sector:%i", (int)i_tracks, (int)p_sectors[i_tracks] ); i_tracks++; break; } } /* fill in the last entry */ int *buf = realloc (p_sectors, (i_tracks + 1) * sizeof (*buf)); if (buf == NULL) goto error; p_sectors = buf; p_sectors[i_tracks] = lseek(p_vcddev->i_vcdimage_handle, 0, SEEK_END) / VCD_SECTOR_SIZE; msg_Dbg( p_this, "vcd track %i, begins at sector:%i", (int)i_tracks, (int)p_sectors[i_tracks] ); p_vcddev->i_tracks = ++i_tracks; p_vcddev->p_sectors = p_sectors; p_sectors = NULL; i_ret = 0; error: if( cuefile ) fclose( cuefile ); free( p_sectors ); free( psz_cuefile ); free( psz_vcdfile ); return i_ret; }
s32 cdvdParseTOC() { memset(&cdtoc,0,sizeof(cdtoc)); s32 len = src->GetSectorCount(); tracks[0].length = len; tracks[0].start_lba=0; tracks[0].type=0; tracks[1].start_lba=0; if(len<=0) { curDiskType=CDVD_TYPE_NODISC; tracks[0].length=0; strack=1; etrack=0; return 0; } s32 lastaddr = src->GetLayerBreakAddress(); if(lastaddr>=0) { if((lastaddr > 0)&&(tracks[0].length>lastaddr)) { tracks[1].length=lastaddr+1; tracks[1].type=0; tracks[2].start_lba = tracks[1].length; tracks[2].length = tracks[0].length-tracks[1].length; tracks[2].type=0; strack=1; etrack=2; } else { tracks[1].length=tracks[0].length; tracks[1].type=0; strack=1; etrack=1; } } else { u8 min, sec, frm; if(src->ReadTOC((char*)&cdtoc,sizeof(cdtoc))<0) { /* printf(" * CDVD: WARNING ReadTOC() failed, trying to use MCI instead...\n"); delete src; int status = MCI_CDGetTOC(source_drive); src=new SOURCECLASS(csrc); if(status<0)*/ return -1; //return 0; } #define btoi(b) ((b>>4)*10+(b&0xF)) int length = (cdtoc.Length[0]<<8) | cdtoc.Length[1]; int descriptors = length/sizeof(cdtoc.Descriptors[0]); for(int i=0;i<descriptors;i++) { switch(cdtoc.Descriptors[i].Point) { case 0xa0: if(cdtoc.Descriptors[i].SessionNumber==cdtoc.FirstCompleteSession) { strack = cdtoc.Descriptors[i].Msf[0]; } break; case 0xa1: if(cdtoc.Descriptors[i].SessionNumber==cdtoc.LastCompleteSession) { etrack = cdtoc.Descriptors[i].Msf[0]; } break; case 0xa2: // session size if(cdtoc.Descriptors[i].SessionNumber==cdtoc.LastCompleteSession) { min=cdtoc.Descriptors[i].Msf[0]; sec=cdtoc.Descriptors[i].Msf[1]; frm=cdtoc.Descriptors[i].Msf[2]; tracks[0].length = MSF_TO_LBA(min,sec,frm); tracks[0].type = 0; } break; case 0xb0: break; case 0xb1: break; case 0xb2: break; case 0xc0: break; default: if((cdtoc.Descriptors[i].Point<100)&&(cdtoc.Descriptors[i].Point>0)) { int tn=cdtoc.Descriptors[i].Point; min=cdtoc.Descriptors[i].Msf[0]; sec=cdtoc.Descriptors[i].Msf[1]; frm=cdtoc.Descriptors[i].Msf[2]; tracks[tn].start_lba = MSF_TO_LBA(min,sec,frm); if(tn>1) tracks[tn-1].length = tracks[tn].start_lba - tracks[tn-1].start_lba; if((cdtoc.Descriptors[i].Control&4)==0) { tracks[tn].type = 1; } else if((cdtoc.Descriptors[i].Control&0xE)==4) { tracks[tn].type = CDVD_MODE1_TRACK; } else { tracks[tn].type = CDVD_MODE1_TRACK; } fprintf(stderr,"Track %d: %d mins %d secs %d frames\n",tn,min,sec,frm); } else if(cdtoc.Descriptors[i].Point>0) { printf("Found code 0x%02x\n",cdtoc.Descriptors[i].Point); } break; } } tracks[etrack].length = tracks[0].length - tracks[etrack].start_lba; } return 0; }
s32 IOCtlSrc::GetSectorCount() { if (discSizeCached) return discSize; DWORD size; GET_LENGTH_INFORMATION info; if (DeviceIoControl(device, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &info, sizeof(info), &size, NULL)) { discSizeCached = true; discSize = (s32)(info.Length.QuadPart / 2048); return discSize; } memset(&tocrq, 0, sizeof(CDROM_READ_TOC_EX)); tocrq.Format = CDROM_READ_TOC_EX_FORMAT_FULL_TOC; tocrq.Msf = 1; tocrq.SessionTrack = 1; CDROM_TOC_FULL_TOC_DATA *ftd = (CDROM_TOC_FULL_TOC_DATA *)sectorbuffer; if (DeviceIoControl(device, IOCTL_CDROM_READ_TOC_EX, &tocrq, sizeof(tocrq), ftd, 2048, &size, NULL)) { for (int i = 0; i < 101; i++) { if (ftd->Descriptors[i].Point == 0xa2) { if (ftd->Descriptors[i].SessionNumber == ftd->LastCompleteSession) { int min = ftd->Descriptors[i].Msf[0]; int sec = ftd->Descriptors[i].Msf[1]; int frm = ftd->Descriptors[i].Msf[2]; discSizeCached = true; discSize = (s32)MSF_TO_LBA(min, sec, frm); return discSize; } } } } dvdrs.BlockByteOffset.QuadPart = 0; dvdrs.Format = DvdPhysicalDescriptor; dvdrs.SessionId = sessID; dvdrs.LayerNumber = 0; if (DeviceIoControl(device, IOCTL_DVD_READ_STRUCTURE, &dvdrs, sizeof(dvdrs), &dld, sizeof(dld), &size, NULL) != 0) { s32 sectors1 = _byteswap_ulong(dld.ld.EndDataSector) - _byteswap_ulong(dld.ld.StartingDataSector) + 1; if (dld.ld.NumberOfLayers == 1) { // PTP, OTP if (dld.ld.TrackPath == 0) { // PTP dvdrs.LayerNumber = 1; if (DeviceIoControl(device, IOCTL_DVD_READ_STRUCTURE, &dvdrs, sizeof(dvdrs), &dld, sizeof(dld), &size, nullptr) != 0) { sectors1 += _byteswap_ulong(dld.ld.EndDataSector) - _byteswap_ulong(dld.ld.StartingDataSector) + 1; } } else { // OTP // sectors = end_sector - (~end_sector_l0 & 0xFFFFFF) + end_sector_l0 - start_sector dld.ld.EndLayerZeroSector = _byteswap_ulong(dld.ld.EndLayerZeroSector); sectors1 += dld.ld.EndLayerZeroSector - (~dld.ld.EndLayerZeroSector & 0x00FFFFFF) + 1; } } discSizeCached = true; discSize = sectors1; return discSize; } return -1; }