title: Read reversed bytes as decimal number from file
body: <p>I'm trying to read the turn number from Civilization 2 savegame files in Perl. I have a very sloppy solution, but there must be a more elegant solution.</p>
  
  <p>They're stored as two bytes at offsets 28 and 29 (0x1C, 0X1D). For turns less than 256, just the first byte (0x1C) is used. For higher turn numbers, the second byte is used. Oddly, they seem to be the reverse of what I'd expect. That is, turn 300 is stored as 0x2C, 0x01. This is making parsing them difficult for me.</p>
  
  <p>My awful (but working) solution is to read each as byte, convert each to a hex string, use regex substitution to manipulate the strings into the correct order, then to convert this hex string back to a decimal value. This is so bad I'm actually embarrassed; hence why I'd like to know how to do it better.</p>
  
  <p>My code:</p>
  
  <pre><code>use Fcntl qw(:seek);
  
  sub get_savegame_turn_number($);
  sub read_file_hexdata_at_offset($$$);
  
  sub get_savegame_turn_number($) {
      my ($filename) = @_;
  
      my $byteA = read_file_hexdata_at_offset($filename, 28, 1);
      my $byteB = read_file_hexdata_at_offset($filename, 29, 1);
  
      my $byteAhex = sprintf("%#02x", ord($byteA));
      my $byteBhex = sprintf("%#02x", ord($byteB));
      $byteAhex =~ s/^0x//;
      my $bytestring = $byteBhex . $byteAhex;
  
      return hex($bytestring);
  }
  
  sub read_file_hexdata_at_offset($$$) {
      my ($filename, $byte_position, $length) = @_;
      my($fh, $byte_value);
  
      open($fh, "&lt;", $filename)
          || die "can't open $filename: $!";
  
      binmode($fh)
          || die "can't binmode $filename";
  
      sysseek($fh, $byte_position, SEEK_CUR)  # NB: 0-based
          || die "couldn't see to byte $byte_position in $filename: $!";
  
      sysread($fh, $byte_value, $length) == $length
          || die "couldn't read byte from $filename: $!";
  
      return $byte_value;
  }
  </code></pre>