Announcement

Collapse
No announcement yet.

Perl function for decoding RoN recordings

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Perl function for decoding RoN recordings

    I just posted this over on MFO, figured I'd share the wealth...

    First thing you need to know is that a RoN recording is a gzip file. After you've unzipped it by whatever means (for Perl, I used Compress::Zlib, PHP supports gzip files directly), this function will decode the header for you.

    If you need more info on the perl "unpack" function which is pretty much the guts of this, see http://www.perldoc.com/perl5.8.0/pod/func/unpack.html

    I think the only unpack flags I use are:
    C - unsigned byte
    V - little-endian (VAX) long
    v - little-endian (VAX) short
    x - skip bytes
    V/v - little-endian long count followed by little-endian short array (unicode)

    Code:
    # ronrec.pl
    # Perl function
    # Given an uncompressed header of a Rise of Nations recording file,
    # extracts the data into various enumerations.
    # This version of the function does NO error checking.
    sub ronrec() {
      my ($buf) = @_;
      my ($csig1, $csig2, @uversion) =
        unpack("CCV/v", $head);
      my $version = join('', map(chr, @uversion));
      my $ofs = 2 + 4 + 2 * ($#uversion + 1);
    # variable names as in rules.xml
      my (	$Vvers, $Vseed, $Vlong1, $Vlong2, Vlong3, $Vflag,
    	$cgamesytle, $cmapstyle, $cmapsize, $c04, $c05,
    	$cgamespeed, $cgamerules, $cdifficulty, $cstartingtown, $cstartingresources,
    	$cdefenderresources, $ctechcost, $crevealmap, $cpoplimit, $crushrules,
    	$ccannontime, $cstartingtech, $c18, $cendingtech, $celimination,
    	$cvictory, $cwonderwin, $cscore, $cpopwin, $ctimelimit,
    	$cchair, $ceconwin, $c28, $c29 ) =
    	  unpack("x$ofs V6C29", $head);
        my $defenderage = $cstartingresources; # for Barbarians at the Gate
    
      my $ofs += 6*4 + 29;
      my (@ppov, @pflag, @pnation, @pcolor, @pteam, @pskill, @pnum, @px00, @px02,
          @pname);
    
      for (my $player = 0; $player < 8; $player++) {
        my ($ctag, $vpov) = unpack("x$ofs cv");
        $ofs += 3;
        if ($vpov) {
          my ($vpflag, $cnation, $ccolor, $cteam, $cskill, $cnum, $cx00, $cx02, @uname) =
    	unpack("x$ofs x48vc7V/v", $head);
          ofs += 48  + 2 + 7 + 4 + 2 * ($#uname + 1);
          # !!! Note that this unpack skips 48 bytes at the start ofe each player info.
          # !!! I have never seen anything but zeros there, as of this writing,
          # !!! but one never knows.
    
          my $name = join('', map(chr, @uname));
          $name = "Player $cnum" if not $name;
    
          $ppov[$player] = $vpov;
          $pflag[$player] = $cpflag;
          $pnation[$player] = $cnation;
          $pcolor[$player] = $ccolor;
          $pteam[$player] = $cteam;
          $pskill[$player] = $cskill;
          $pnum[$player] = $cnum;
          $px00[$player] = $cx00; # only value I have seen here is 0
          $px02[$player] = $cx02; # only value I have seen here is 2
          $pname[$player] = $name;
        }
      }
    
    # Now you have all the game info in various variables!
    # Stuff 'em into globals, make a hash and return 'em, print 'em, whatever.
    }
    _/\ C
    Sturgeon's Law: 90% of everything is crud.
Working...
X