Line 119:
Line 119:
<source lang="perl">
<source lang="perl">
−
#!/usr/bin/perl
−
#-----------------------------------
−
# Wii Savegame Parser
−
# written by Lockhool
−
# for #wiidev @ EFnet
−
#-----------------------------------
−
use strict;
+
#!/usr/bin/perl
−
use Fcntl;
+
#-----------------------------------
−
+
# Wii Savegame Parser
−
sub readLong($;$);
+
# written by Lockhool
−
sub readByte($;$);
+
# for #wiidev @ EFnet
−
sub readString($);
+
#-----------------------------------
−
sub readUpto($$);
+
−
sub readBlock($$;$);
+
use strict;
−
sub readEof();
+
use Fcntl;
−
+
−
my $file_in=shift;
+
sub readLong($;$);
−
die("\n Usage: ./wiiparse.pl <datafile>\n\n")
+
sub readByte($;$);
+
sub readString($);
+
sub readUpto($$);
+
sub readBlock($$;$);
+
sub readEof();
+
+
my $file_in=shift;
+
die("\n Usage: ./wiiparse.pl <datafile>\n\n")
unless(sysopen(IN,$file_in,O_RDONLY));
unless(sysopen(IN,$file_in,O_RDONLY));
−
+
−
my $add=0;
+
my $add=0;
−
my $in;
+
my $in;
−
+
−
readUpto('Header',0x00000070);
+
readUpto('Header',0x00000070);
−
readLong('Magic',0x426B0001);
+
readLong('Magic',0x426B0001);
−
readLong('WiiID');
+
readLong('WiiID');
−
my $numfiles = readLong('NumFiles');
+
my $numfiles = readLong('NumFiles');
−
readLong('FileDataLen');
+
readLong('FileDataLen');
−
readLong('Magic',0x00000000);
+
readLong('Magic',0x00000000);
−
readLong('Magic',0x00000000);
+
readLong('Magic',0x00000000);
−
readLong('PostHeadLen');
+
readLong('PostHeadLen');
−
readBlock('Zeros',64);
+
readBlock('Zeros',64);
−
readLong('Magic',0x00010000);
+
readLong('Magic',0x00010000);
−
readLong('PrgID');
+
readLong('PrgID');
−
readLong('MacAdd');
+
readLong('MacAdd');
−
readLong('Magic',0xF5550000);
+
readLong('Magic',0xF5550000);
−
readBlock('Hash1',16,'hash1');
+
readBlock('Hash1',16,'hash1');
−
for(1..$numfiles){
+
for(1..$numfiles){
readLong('Magic'.$_,0x03ADF17E);
readLong('Magic'.$_,0x03ADF17E);
my $filesize = readLong('Filesize'.$_);
my $filesize = readLong('Filesize'.$_);
Line 167:
Line 168:
readBlock('Filedata'.$_,$filesize,'f'.$_.'data');
readBlock('Filedata'.$_,$filesize,'f'.$_.'data');
readBlock('DataFiller'.$_,$filesize % 64,'f'.$_.'dfill');
readBlock('DataFiller'.$_,$filesize % 64,'f'.$_.'dfill');
−
}
+
}
−
readBlock('Hash2',60,'hash2');
+
readBlock('Hash2',60,'hash2');
−
readLong('Magic',0x00000000);
+
readLong('Magic',0x00000000);
−
readLong('Magic',0x00010002);
+
readLong('Magic',0x00010002);
−
readBlock('Hash3',60,'hash3');
+
readBlock('Hash3',60,'hash3');
−
readBlock('Zeros',64);
+
readBlock('Zeros',64);
−
my $strlen = readString('RootCA');
+
my $strlen = readString('RootCA');
−
readBlock('Zeros',64-$strlen);
+
readBlock('Zeros',64-$strlen);
−
readLong('Magic',0x00000002);
+
readLong('Magic',0x00000002);
−
my $strlen = readString('NG');
+
my $strlen = readString('NG');
−
readBlock('Zeros',64-$strlen);
+
readBlock('Zeros',64-$strlen);
−
readBlock('Hash4',64,'hash4');
+
readBlock('Hash4',64,'hash4');
−
readBlock('Zeros',60);
+
readBlock('Zeros',60);
−
readLong('Magic',0x00010002);
+
readLong('Magic',0x00010002);
−
readBlock('Hash5',60,'hash5');
+
readBlock('Hash5',60,'hash5');
−
readBlock('Zeros',64);
+
readBlock('Zeros',64);
−
my $strlen = readString('RootCA-MS-NG');
+
my $strlen = readString('RootCA-MS-NG');
−
readBlock('Zeros',64-$strlen);
+
readBlock('Zeros',64-$strlen);
−
readLong('Magic',0x00000002);
+
readLong('Magic',0x00000002);
−
my $strlen = readString('AP');
+
my $strlen = readString('AP');
−
readBlock('Zeros',64-$strlen);
+
readBlock('Zeros',64-$strlen);
−
readLong('Magic',0x00000000);
+
readLong('Magic',0x00000000);
−
readBlock('Hash6',60,'hash6');
+
readBlock('Hash6',60,'hash6');
−
readEof;
+
readEof;
+
+
close(IN);
−
close(IN);
+
sub readLong($;$){
−
−
sub readLong($;$){
printf("% 12u : ",$add);
printf("% 12u : ",$add);
my $name=shift;
my $name=shift;
Line 205:
Line 206:
if(defined $val){print(' 'x17);
if(defined $val){print(' 'x17);
if($val==$in){print('==');}else{print('!=')}
if($val==$in){print('==');}else{print('!=')}
−
printf(" 0x%08X (%u)\n",$val,$val);
+
printf(" 0x%08X (%u)\n",$val,$val);
}
}
return($in);
return($in);
−
}
+
}
−
sub readByte($;$){
+
sub readByte($;$){
printf("% 12u : ",$add);
printf("% 12u : ",$add);
my $name=shift;
my $name=shift;
Line 221:
Line 222:
if(defined $val){print(' 'x17);
if(defined $val){print(' 'x17);
if($val==$in){print('==');}else{print('!=')}
if($val==$in){print('==');}else{print('!=')}
−
printf(" 0x%02X (%u)\n",$val,$val);
+
printf(" 0x%02X (%u)\n",$val,$val);
}
}
return($in);
return($in);
−
}
+
}
−
sub readBlock($$;$){
+
sub readBlock($$;$){
printf("% 12u : ",$add);
printf("% 12u : ",$add);
my $name=shift;
my $name=shift;
Line 234:
Line 235:
my $size=$cnt;
my $size=$cnt;
if(defined $file){
if(defined $file){
−
die("!! Can't open $file !!\n")
+
die("!! Can't open $file !!\n")
−
unless(sysopen(OUT,$file,O_WRONLY|O_CREAT));}
+
unless(sysopen(OUT,$file,O_WRONLY|O_CREAT));}
while($cnt!=0){
while($cnt!=0){
−
die("!! '$name' premature EOF !!\n")
+
die("!! '$name' premature EOF !!\n")
−
unless(1==sysread(IN,$in,1));
+
unless(1==sysread(IN,$in,1));
−
if(defined $file){syswrite(OUT,$in,1);}
+
if(defined $file){syswrite(OUT,$in,1);}
−
$add++;
+
$add++;
−
$cnt--;}
+
$cnt--;}
if(defined $file){close(OUT);}
if(defined $file){close(OUT);}
printf(" BLOCK '$name' ends after %u bytes\n",$size);
printf(" BLOCK '$name' ends after %u bytes\n",$size);
return($size);
return($size);
−
}
+
}
−
sub readString($){
+
sub readString($){
printf("% 12u : ",$add);
printf("% 12u : ",$add);
my $name=shift;
my $name=shift;
Line 255:
Line 256:
my $in;
my $in;
while(1){
while(1){
−
die("!! '$name' premature EOF !!\n")
+
die("!! '$name' premature EOF !!\n")
−
unless(1==sysread(IN,$in,1));
+
unless(1==sysread(IN,$in,1));
−
$add+=1;
+
$add+=1;
−
$size+=1;
+
$size+=1;
−
$string=$string.unpack('a',$in);
+
$string=$string.unpack('a',$in);
−
if(ord($in)==0){last;}
+
if(ord($in)==0){last;}
}
}
printf("STRING '$name' ends after %u bytes\n",$size);
printf("STRING '$name' ends after %u bytes\n",$size);
print(' 'x15 ."\"$string\"\n");
print(' 'x15 ."\"$string\"\n");
return($size);
return($size);
−
}
+
}
−
sub readEof(){
+
sub readEof(){
printf("% 12u",$add);
printf("% 12u",$add);
my $name=shift;
my $name=shift;
Line 274:
Line 275:
my $in;
my $in;
while(1){
while(1){
−
last unless(0!=sysread(IN,$in,1));
+
last unless(0!=sysread(IN,$in,1));
−
$add++;
+
$add++;
−
$size++;}
+
$size++;}
printf(" - %u : EOF reached after %u bytes\n",$add,$size);
printf(" - %u : EOF reached after %u bytes\n",$add,$size);
return($size);
return($size);
−
}
+
}
−
sub readUpto($$){
+
sub readUpto($$){
printf("% 12u : ",$add);
printf("% 12u : ",$add);
my $name=shift;
my $name=shift;
Line 288:
Line 289:
my $in;
my $in;
while(1){
while(1){
−
die("!! '$name' premature EOF !!\n")
+
die("!! '$name' premature EOF !!\n")
−
unless(4==sysread(IN,$in,4));
+
unless(4==sysread(IN,$in,4));
−
$add+=4;
+
$add+=4;
−
$size+=4;
+
$size+=4;
−
if($upto==unpack("N",$in)){last;}}
+
if($upto==unpack("N",$in)){last;}}
printf(" UPTO '$name' ends after %u bytes\n",$size);
printf(" UPTO '$name' ends after %u bytes\n",$size);
return($size);
return($size);
−
}
+
}
+
</source>
</source>