#!/usr/bin/perl -w # Parameter search to transform the string table in mile18.c into something # without whitespaces. use strict; # String table to encode. my @strings = ( "#%s %c\n", # 0 "ifdef", # 1 "define", # 2 "undef", # 3 "ifndef", # 4 "#include _", # 5 "usage: [PIN] < input.txt > output.c\n\n" . "where [PIN] is an integer in the range of 1..65535", # 6 "#endif", # 7 "#else", # 8 "static const unsigned char O[] = {", # 9 "};", # 10 "0,", # 11 "-~", # 12 "#define _ __FILE__", # 13 "#ifndef PIN\n#error Please compile with -DPIN=", # 14 "#include\n" . "int main() { return !fwrite(O, %d, %d, stdout); }\n", # 15 "#if PIN %% %d > %d\n", # 16 ); my $data = chr(0) . (join '', map {$_ . chr(0)} @strings); # Unique bytes to encode within string table. my %unique = (); $unique{$_} = 1 foreach unpack 'C*', $data; my $unique_bytes = join '', map {chr} sort {$a <=> $b} keys %unique; # List of acceptable bytes for encoding. my $acceptable_bytes = ""; for(my $i = 33; $i < 127; $i++) { if( index("\"\\,()", chr($i)) < 0 ) { $acceptable_bytes .= chr($i); } } length($acceptable_bytes) >= length($unique_bytes) or die; sub encode_byte($$$) { my ($x, $y, $byte) = @_; my $patch_table = "\n (),\0"; foreach my $e (unpack 'C*', $acceptable_bytes) { if( ($e >= $x && $e < $x + length($patch_table) ? ord(substr($patch_table, $e - $x, 1)) : $e ^ $y) == $byte ) { return $e; } } return undef; } sub encode($$) { my ($x, $y) = @_; foreach my $d (reverse unpack 'C*', $data) { print chr(encode_byte($x, $y, $d)); } print "\n"; } sub search() { for(my $x = 0; $x < 256; $x++) { for(my $y = 0; $y < 256; $y++) { my $all_good = 1; foreach my $d (unpack 'C*', $unique_bytes) { unless( defined(encode_byte($x, $y, $d)) ) { $all_good = 0; last; } } if( $all_good ) { print "x = $x, y = $y\n"; } } } } #search(); encode(81, 0);