=head1 NAME Convert::CD::Analyze - dirty incorrect guessing of img tracks. =head1 SYNOPSIS use Convert::CD::Analyze; # see Convert::CD::TOCFile =head1 DESCRIPTION Try to autodetect the tracks in a monolithic cd image. Audio tracks cannot be guessed (they are basically just binary data), while many other formats can. So far, only ISO filesystems are detected, and the space before and after them is ignored. This even works for uncompressed .fcd and similar files. =head2 Convert:CD::Analyze METHODS =over 4 =cut package Convert::CD::Analyze; $VERSION = 0.01; use Carp; use Convert::CD::Track; use base Convert::CD::TOCFile; =item new param => value... Create a new Convert::CD::Analyze object. Parameters: path the base image filename =cut sub new { my $class = shift; my $self = bless { @_, }, $class; $self; } sub _read { my ($self, $cd) = @_; defined $self->{path} or croak "no path specified"; open my $img, "<", $self->{path} or croak "$self->{path}: $!"; # scan through the image, if necessary through the full image # we are dumb, to instead of using an intelligent algorithm, we just # use an overlapping buffer my $buf; my $secsize; my $isoofs; my $bcd60 = join "", map sprintf ("\\x%02d", $_), 0..59; my $bcd75 = join "", map sprintf ("\\x%02d", $_), 0..74; my $sync = "\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00"; my $msf = qr<(.)([$bcd60])([$bcd75])([\x00\x01\x02])>o; #my $ while (sysread $img, $buf, 256*1024, length $buf) { # check sync 00 ff ff ff ff ff ff ff ff ff ff 00 M S F mode # form1: 00 00 08 00 00 00 08 00 # form1 # XA subheader format: FileNumber, ChannelNumber, SubMode, CodingInformation # FileNumber = the unique ID for a single XA file # ChannelNumber = the file is multimedia (1) or not (0) # SubMode = XA content description: struct SubMode { uint8 EndOfRecord:1; # CodingInformation = type of data: uint8 VideoData:1; # 0x00 = empty/data sector uint8 ADCPM:1; # 0x0f = video sector uint8 Data:1; # 0x7f = audio sector uint8 TriggerOn:1; # 0x80 = MPEG2 (SVCD) uint8 Form2:1; # uint8 RealTime:1; # uint8 EndOfFile:1; }; # check for sync, then header and subheader if ($buf =~ /$sync $msf (........)/sox) { my ($m, $s, $f, $mode, $sub) = ( (sprintf "%x", (ord $1) % 0xa0), (sprintf "%x", ord $2), (sprintf "%x", ord $3), ord $4, $5 ); $|=1; print "found raw sector $m:$s:$f $mode ".(unpack "H*", $sub)."\n"; } # check for iso if ($buf =~ /\001CD001\001/g) { my $dataofs; my $mode; my $ofs; my $ofs1 = $-[0]; if ($ofs1 > 24 && $sync eq substr $buf, $ofs1 - 24, 12) { $dataofs = 24; $ofs = $ofs1 - $dataofs; $mode = MODE_MODE2; } elsif ($ofs1 > 16 && $sync eq substr $buf, $ofs1 - 16, 12) { $dataofs = 16; $ofs = $ofs1 - $dataofs; $mode = MODE_MODE1; } else { $dataofs = 0; $mode = MODE_MODE1; $ofs = $ofs1; } my $size = unpack "N", substr $buf, $ofs1 + 80 + 4, 4; if ($buf =~ /[\000\001\002\003\004\377]CD001\001/g) { my $ofs2 = $-[0]; $secsize = $ofs2 - $ofs1; $ofs -= 16 * $secsize; warn "found ISO $dataofs $secsize $ofs $mode $size\n"; $cd->append_track ( mode => $mode, secsize => $secsize, rawsize => $size * $secsize, offset => $ofs, datasize => 2048, dataoffset => $dataofs, ); last; } } substr $buf, 0, (length $buf) - 2448, ""; # some overlap + change } } #sub _write { # my ($self, $cd) = @_; #} 1; =back =head1 AUTHOR Marc Lehmann =cut