+ } else {
+ printf "# sector %-2d with %d blocks\n", $sector, $blocks;
+ }
+
+ my $trailer_pos = $pos + $blocks * 0x10 - 0x10;
+ my $c1 = ( ord(substr($card,$trailer_pos+7,1)) & 0xf0 ) >> 4;
+ my $c2 = ( ord(substr($card,$trailer_pos+8,1)) & 0x0f );
+ my $c3 = ( ord(substr($card,$trailer_pos+8,1)) & 0xf0 ) >> 4;
+
+ printf "# trailer @%x %016b c1:%08b c2:%08b c3:%08b\n"
+ , unpack('n',(substr($card,$trailer_pos+7,2)))
+ , $trailer_pos, $c1, $c2, $c3
+ ;
+
+ my $condition = '';
+ foreach my $j ( 0 .. $blocks - 1 ) {
+ my $offset = $pos + $j * 0x10;
+ my $block = substr($card, $offset, 0x10);
+
+ my $acl_block =
+ $sector < 32 ? $j :
+ $j % 5 == 0 ? $j / 5 :
+ undef; # display condition only once for block group
+
+ if ( defined $acl_block ) {
+ my $trailer = $j == ( $blocks - 1 );
+ my $mask = 1 << $acl_block;
+ my $cond
+ = ( ( $c1 & $mask ) * 4 )
+ + ( ( $c2 & $mask ) * 2 )
+ + ( ( $c3 & $mask ) * 1 )
+ ;
+ $cond >>= $acl_block;
+ $condition = sprintf ' %03b %s'
+ , $cond
+ , $trailer ? $access_condition_trailer->{$cond}
+ : $access_condition_data->{$cond}
+ ;
+ if ( ! $trailer && ( $cond == 0b001 || $cond == 0b011 ) ) {
+ my ( $value_block, $not ) = unpack 'llx8', $block;
+ my $value = $value_block;
+# my $positive = $value_block & 0x8000_0000;
+# my $value = $value_block & 0x7fff_ffff;
+# $value = -$value if ! $positive;
+ #$condition .= sprintf " = %d 0x%x", $value, $value_block;
+ $condition .= sprintf " = %d 0x%x", $value_block, $not;
+ }
+ } else {
+ $condition = '';
+ }
+
+ my $hex = unpack('H*',$block);
+ $hex =~ s/(....)/$1 /g;
+
+ if ( $ENV{SWAP} ) {
+ my $hex_sw = unpack('h*',$block);
+ $hex_sw =~ s/(....)/$1 /g;
+ $hex .= " | $hex_sw";
+ }
+
+ printf "%x %03x %s%s\n", $j, $offset, $hex, $condition;
+ }
+
+ printf "KEY A:%s | %s GDP: %s | B:%s %s\n"
+ ,unpack('H*',substr($card,$trailer_pos ,6))
+ ,unpack('H*',substr($card,$trailer_pos+6 ,3))
+ ,unpack('H*',substr($card,$trailer_pos+9 ,1))
+ ,unpack('H*',substr($card,$trailer_pos+10,6))
+ ,$life_cycle->{substr($card,$trailer_pos+6,3)} || ''
+ ;
+
+ print "\n";
+
+ $pos += $blocks * 0x10;