Esempio n. 1
0
File: cdrom.c Progetto: Geal/vlc
/****************************************************************************
 * 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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
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;
}