| 1 |
=head1 NAME |
| 2 |
|
| 3 |
Convert::CD::Analyze - dirty incorrect guessing of img tracks. |
| 4 |
|
| 5 |
=head1 SYNOPSIS |
| 6 |
|
| 7 |
use Convert::CD::Analyze; |
| 8 |
|
| 9 |
# see Convert::CD::TOCFile |
| 10 |
|
| 11 |
=head1 DESCRIPTION |
| 12 |
|
| 13 |
Try to autodetect the tracks in a monolithic cd image. |
| 14 |
|
| 15 |
Audio tracks cannot be guessed (they are basically just binary data), |
| 16 |
while many other formats can. So far, only ISO filesystems are detected, |
| 17 |
and the space before and after them is ignored. |
| 18 |
|
| 19 |
This even works for uncompressed .fcd and similar files. |
| 20 |
|
| 21 |
=head2 Convert:CD::Analyze METHODS |
| 22 |
|
| 23 |
=over 4 |
| 24 |
|
| 25 |
=cut |
| 26 |
|
| 27 |
package Convert::CD::Analyze; |
| 28 |
|
| 29 |
$VERSION = 0.01; |
| 30 |
|
| 31 |
use Carp; |
| 32 |
|
| 33 |
use Convert::CD::Track; |
| 34 |
|
| 35 |
use base Convert::CD::TOCFile; |
| 36 |
|
| 37 |
=item new param => value... |
| 38 |
|
| 39 |
Create a new Convert::CD::Analyze object. |
| 40 |
|
| 41 |
Parameters: |
| 42 |
|
| 43 |
path the base image filename |
| 44 |
|
| 45 |
=cut |
| 46 |
|
| 47 |
sub new { |
| 48 |
my $class = shift; |
| 49 |
my $self = bless { @_, }, $class; |
| 50 |
|
| 51 |
$self; |
| 52 |
} |
| 53 |
|
| 54 |
sub _read { |
| 55 |
my ($self, $cd) = @_; |
| 56 |
|
| 57 |
defined $self->{path} |
| 58 |
or croak "no path specified"; |
| 59 |
|
| 60 |
open my $img, "<", $self->{path} |
| 61 |
or croak "$self->{path}: $!"; |
| 62 |
|
| 63 |
# scan through the image, if necessary through the full image |
| 64 |
# we are dumb, to instead of using an intelligent algorithm, we just |
| 65 |
# use an overlapping buffer |
| 66 |
my $buf; |
| 67 |
my $secsize; |
| 68 |
my $isoofs; |
| 69 |
|
| 70 |
my $bcd60 = join "", map sprintf ("\\x%02d", $_), 0..59; |
| 71 |
my $bcd75 = join "", map sprintf ("\\x%02d", $_), 0..74; |
| 72 |
my $sync = "\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00"; |
| 73 |
my $msf = qr<(.)([$bcd60])([$bcd75])([\x00\x01\x02])>o; |
| 74 |
|
| 75 |
#my $ |
| 76 |
|
| 77 |
while (sysread $img, $buf, 256*1024, length $buf) { |
| 78 |
# check sync 00 ff ff ff ff ff ff ff ff ff ff 00 M S F mode |
| 79 |
# form1: 00 00 08 00 00 00 08 00 # form1 |
| 80 |
# XA subheader format: FileNumber, ChannelNumber, SubMode, CodingInformation |
| 81 |
# FileNumber = the unique ID for a single XA file |
| 82 |
# ChannelNumber = the file is multimedia (1) or not (0) |
| 83 |
# SubMode = XA content description: struct SubMode { uint8 EndOfRecord:1; |
| 84 |
# CodingInformation = type of data: uint8 VideoData:1; |
| 85 |
# 0x00 = empty/data sector uint8 ADCPM:1; |
| 86 |
# 0x0f = video sector uint8 Data:1; |
| 87 |
# 0x7f = audio sector uint8 TriggerOn:1; |
| 88 |
# 0x80 = MPEG2 (SVCD) uint8 Form2:1; |
| 89 |
# uint8 RealTime:1; |
| 90 |
# uint8 EndOfFile:1; }; |
| 91 |
|
| 92 |
# check for sync, then header and subheader |
| 93 |
if ($buf =~ /$sync $msf (........)/sox) { |
| 94 |
my ($m, $s, $f, $mode, $sub) = ( |
| 95 |
(sprintf "%x", (ord $1) % 0xa0), |
| 96 |
(sprintf "%x", ord $2), |
| 97 |
(sprintf "%x", ord $3), |
| 98 |
ord $4, |
| 99 |
$5 |
| 100 |
); |
| 101 |
$|=1; |
| 102 |
print "found raw sector $m:$s:$f $mode ".(unpack "H*", $sub)."\n"; |
| 103 |
} |
| 104 |
|
| 105 |
# check for iso |
| 106 |
if ($buf =~ /\001CD001\001/g) { |
| 107 |
my $dataofs; |
| 108 |
my $mode; |
| 109 |
my $ofs; |
| 110 |
my $ofs1 = $-[0]; |
| 111 |
|
| 112 |
if ($ofs1 > 24 && $sync eq substr $buf, $ofs1 - 24, 12) { |
| 113 |
$dataofs = 24; |
| 114 |
$ofs = $ofs1 - $dataofs; |
| 115 |
$mode = MODE_MODE2; |
| 116 |
} elsif ($ofs1 > 16 && $sync eq substr $buf, $ofs1 - 16, 12) { |
| 117 |
$dataofs = 16; |
| 118 |
$ofs = $ofs1 - $dataofs; |
| 119 |
$mode = MODE_MODE1; |
| 120 |
} else { |
| 121 |
$dataofs = 0; |
| 122 |
$mode = MODE_MODE1; |
| 123 |
$ofs = $ofs1; |
| 124 |
} |
| 125 |
|
| 126 |
my $size = unpack "N", substr $buf, $ofs1 + 80 + 4, 4; |
| 127 |
|
| 128 |
if ($buf =~ /[\000\001\002\003\004\377]CD001\001/g) { |
| 129 |
my $ofs2 = $-[0]; |
| 130 |
|
| 131 |
$secsize = $ofs2 - $ofs1; |
| 132 |
|
| 133 |
$ofs -= 16 * $secsize; |
| 134 |
|
| 135 |
warn "found ISO $dataofs $secsize $ofs $mode $size\n"; |
| 136 |
$cd->append_track ( |
| 137 |
mode => $mode, |
| 138 |
secsize => $secsize, |
| 139 |
rawsize => $size * $secsize, |
| 140 |
offset => $ofs, |
| 141 |
datasize => 2048, |
| 142 |
dataoffset => $dataofs, |
| 143 |
); |
| 144 |
last; |
| 145 |
} |
| 146 |
} |
| 147 |
|
| 148 |
substr $buf, 0, (length $buf) - 2448, ""; # some overlap + change |
| 149 |
} |
| 150 |
} |
| 151 |
|
| 152 |
#sub _write { |
| 153 |
# my ($self, $cd) = @_; |
| 154 |
#} |
| 155 |
|
| 156 |
1; |
| 157 |
|
| 158 |
=back |
| 159 |
|
| 160 |
=head1 AUTHOR |
| 161 |
|
| 162 |
Marc Lehmann <schmorp@schmorp.de> |
| 163 |
|
| 164 |
=cut |
| 165 |
|