#!/usr/bin/perl # version 1.03 10/28/2013 brianb@paladingrp.com # fluke 9010a ROM checksum algorithm # reverse engineered from QuarterArcades "calcsig" program $dir = $ARGV[0] || "."; # directory to scan is first arg, or current dir my $str=""; # initialize empty string opendir($dh,$dir) || die "cannot open $dir: $!\n"; while($f=readdir($dh)) { # for each directory entry next if (-d "$dir/$f"); # skip directories $str=getFile("$dir/$f"); # read in file printf("%s/%s: %04x\n",$dir,$f,doChecksum($str)); # compute and print checksum } # getFile takes a pathname, and reads the file and resturns a string # which is the contents of the file sub getFile() { my $str=""; my $file=shift(@_); open(F,"$dir/$f") || die "cannot open $dir/$f: $!\n"; while() { $str = $str .= "$_"; } close(F); return($str); } sub doChecksum() { my @numArray; $numArray[15]=0; # initialize an array with 16 elements my @numArray2=(6,8,11,15,0); # initialize second array with start values my $sig=0; my $str=shift(@_); # retrieve the rom data passed in my @data=unpack("C*",$str); # unpack each char into a list of bytes for(my $i=0; $i <= $#data; $i++) { # for each byte element i in the data my $x=$data[$i]; # x is the data for(my $j=0; $j <= $#numArray2; $j++) { my $index=$numArray2[$j]; if($j == $#numArray2) { # if j is the last element in numArray2 $numArray[$index]=$x; } else { $x = $numArray[$index] ^ $x } if(--$index < 0) { $index = $#numArray; } $numArray2[$j]=$index; } } $sig=0; for my $i (@numArray) { my $x=$i; for(my $k=0; $k < 8; $k++) { $sig=($sig << 1) | ( ($x ^ &shiftbits($sig)) & 1); $x=$x >> 1; } } $sig=$sig % (256*256); # we want only the first 16 bits # so do a modulus of the scalar mod 65536 return($sig); } sub shiftbits() { my $a=shift(@_); return( ($a >> 6) ^ ($a >> 8) ^ ($a >> 11) ^ ($a >> 15)); }