#!/usr/bin/perl printf STDERR "cload.pl version 1.0 (13th Mar. 2003) by Yagshi\n"; die "cload.pl [-old] [-o ] \n -old for PC-1245/5x." if($#ARGV<0||$#ARGV>3); while($ARGV[0]){ if( $ARGV[0]=~/^-old$/ ){ $isOld = 1; next; } if( $ARGV[0]=~/^-o$/ ){ die "output file unspecified." if $#ARGV==0; $ARGV=shift; $rawFile = $ARGV[0]; open(RAWFILE,">$rawFile") or die "cannot open output file."; next; } die "invalid switch $ARGV[0]." if $ARGV[0]=~/^-/; open WAV,$ARGV[0] or die "cannot open file."; }continue{ $ARGV=shift; } # check wav header read WAV,$bin,4; die "WAV format error." if $bin ne "RIFF"; $fileLength = ReadBin( WAV,4 ); # file size - 8 printf STDERR "file length= $fileLength+8\n"; die "WAV format error. No WAVE header." if ReadStr( WAV,4 ) ne "WAVE"; do{ $tag = ReadStr(WAV, 4); $chunkLength = ReadBin(WAV, 4); SWITCH: for ($tag){ /fmt / and Decode_fmt(), last SWITCH; /LIST/ and Decode_LIST(), last SWITCH; /data/ and Decode_data(), last SWITCH; ReadStr(WAV, $chunkLength); print "unknown tag $tag.\n"; } }while(!eof(WAV)); sub Decode_fmt{ die "WAV format error in fmt chunk." if $chunkLength != 16; die "only linear PCM is acceptable." if ReadBin( WAV,2 )!=1; die "only monoral file is acceptable." if ReadBin( WAV,2 )!=1; $hz = ReadBin( WAV,4 ); $bytePerSec = ReadBin( WAV,4 ); $bytePerSample = ReadBin( WAV,2 ); $bitPerSample = ReadBin( WAV,2 ); printf STDERR "freq. = %dHz\n",$hz; die "freq. is too high." if $hz>16000*2; printf STDERR "byte/sec = %d\n",$bytePerSec; printf STDERR "byte/sample= %d\n",$bytePerSample; printf STDERR " bit/sample= %d\n",$bitPerSample; die "only 8bit file is acceptable." if $bitPerSample!=8; } sub Decode_LIST{ print ReadStr(WAV, $chunkLength),"\n"; } sub Decode_data{ printf STDERR "data length= %d\n",$chunkLength; # 各種初期化 $level = 0; $isSync=1; # スタートビット待ち? $syncCount=0; # スタートビット待ちタイムアウトカウンタ $gapCount0 = int($hz/500); # ビット間の中央までいくつか(bit間=2[ms]) $gapCount = 0; $readBit = 0x01; $data = 0; $fileType = -1; # BASIC とか 機械語とか(実機準拠) -1 は未解決 $fileName=""; $checkSum=0; # check sum $sc=0; # check sum counter $scNext=8 if $isOld; $scNext=120 unless $isOld; $f5=0; $topAddrH = $topAddr = -1; # start address $binLengthH = $binLength = -1; # length while(!eof(WAV)){ read WAV,$z[0],1; $z[0]=ord($z[0]); $y = $z[0]-$z[int($hz/4000+.5)]; # eliminate 4KHz if($y>20 || $y<-20){ $level=0; $lcount=0; }else{ if($lcount>3){ $level=1; } $lcount++; } if($isSync){ if($gapCount){ $gapCount--; }else{ if($level==0){ # start bit $isSync = 0; $gapCount = int($gapCount0*1.5); }else{ $syncCount++; if( $syncCount>1000 && $readBit==0x10 ){ # 半byteエラー回復 $readBit=0x01; $data = 0; } } } }else{ if(--$gapCount<=0){ $gapCount = $gapCount0; if( $level ){ $data = $data | $readBit; } $readBit = $readBit*2; if( $readBit==0x100 ){ $isSync=1; $syncCount = 0; if( $isOld ){ $data = (($data<<4)|($data>>4))&0xff; } ProcessByteStream($data); $data=0; $readBit = 0x01; } if( $readBit==0x10 ){ $isSync=1; $syncCount = 0; } } } }continue{ $z[8]=$z[7]; $z[7]=$z[6]; $z[6]=$z[5]; $z[5]=$z[4]; $z[4]=$z[3]; $z[3]=$z[2]; $z[2]=$z[1]; $z[1]=$z[0]; } } sub ProcessByteStream{ if($sc==$scNext){ $readSum = $_[0] if $isOld; $readSum = ($_[0]>>4)+($_[0]<<4&0xf0) unless $isOld; die "ERROR 8 $checkSum!=$readSum" if $checkSum!=$readSum; $sc=0 or $checkSum=0 if (!$isOld) or $sc>=80; if($isOld){ $scNext=$sc+8; }else{ $scNext=$sc+120; $checkSum=0; } $checkSum=0 or $sc=0 or $scNext=8 if ($isOld and $numCheck<2); $checkSum=0 or $sc=0 or $scNext=8 if not $isOld and $numCheck<1; $numCheck++; print STDERR "--- CHECK SUM OK ---\n"; return; } unless($isOld){ if( $finalSum!=2 ){ $checkSum+=($_[0]&0x0f); $checkSum=($checkSum+1)&0xff if $checkSum>0xff; $checkSum=($checkSum+($_[0]>>4&0x0f))&0xff; $finalSum++ if $finalSum==1; } }else{ $checkSum+=($_[0]&0xf0)>>4; $checkSum=($checkSum+1)&0xff if $checkSum>0xff; $checkSum=($checkSum+($_[0]&0x0f))&0xff; } $sc++; if($fileType<0){ # $fileType = $_[0]; printf "file ID=%02x ",$_[0]; # PC-1245/5x $fileType = $_[0] and printf "BINARY\n" if $_[0] == 0x26; $fileType = $_[0] and printf "BASIC\n" if $_[0] == 0x20; $fileType = $_[0] and printf "BASIC(PASS)\n" if $_[0] == 0x21; # newer machine $fileType = $_[0] and printf "BINARY\n" if $_[0] == 0x67; die "unknown type ($_[0]). Try -old switch." if $fileType<0; $sc=0; $checkSum=0; $scNext = 8; return; } if( length($fileName)<7 ){ if($isOld){ $ch0 = ($_[0]>>4 | $_[0]<<4)&0xff; $ch = $ch0 +ord('0')-0x40 if($ch0>=0x40 && $ch0<=0x49); $ch = $ch0 +ord('A')-0x51 if($ch0>=0x51 && $ch0<=0x6a); $fileName = sprintf( "%c%s",$ch,$fileName); }else{ $fileName = sprintf( "%c%s",$_[0],$fileName); } printf STDERR "FOUND : $fileName\n" if length($fileName)==7; return; } if( $f5<5 ){ # skip "f5 00 00 00 00" $f5++; return; } if( $fileType==0x26 or $fileType==0x67 ){ # binary file if( $topAddrH<0 ){ $topAddrH = $_[0]<<8 unless $isOld; $topAddrH = (($_[0]>>4 | $_[0]<<4)&0xff)<<8 if $isOld; return; } if( $topAddr<0 ){ $topAddr = $topAddrH | $_[0] unless $isOld; $topAddr = $topAddrH | $_[0]>>4 | ($_[0]<<4)&0xff if $isOld; printf STDERR "START : %04x\n",$topAddr; $curAddr = $topAddr; return; } if( $binLengthH<0 ){ $binLengthH = $_[0]<<8 unless $isOld; $binLengthH = (($_[0]>>4 | $_[0]<<4)&0xff)<<8 if $isOld; return; } if( $binLength<0 ){ $binLength = $binLengthH | $_[0] unless $isOld; $binLength = $binLengthH | $_[0]>>4 | ($_[0]<<4)&0xff if $isOld; printf STDERR "LENGTH: %04x\n",$binLength; return; } } if( $binLength and $topAddr+$binLength==$curAddr ){ $scNext=$sc+2; $finalSum=1; } if($binLength and $curAddr-$topAddr<=$binLength){ $_[0]=$_[0]>>4 | $_[0]<<4&0xf0 unless $isOld; print RAWFILE chr($_[0]) if $rawFile; }else{ print "-----END-----\n"; } printf "%04x %02x sum=%02x\n",$curAddr,$_[0],$checkSum; $curAddr++; } sub ReadStr{ my $ret; read $_[0], $ret, $_[1]; return $ret; } sub ReadBin{ my $ret = 0; my $mag = 1; my $data; my $count = $_[1]; while( $count-- ){ read $_[0], $data, 1; $ret += ord($data)*$mag; $mag *= 256; } return $ret; }