also read replay header in screp
authorShiar <shiar@shiar.org>
Mon, 12 Nov 2007 04:24:26 +0000 (05:24 +0100)
committerShiar <shiar@shiar.org>
Mon, 12 Nov 2007 14:00:35 +0000 (15:00 +0100)
Parses the header leading commands (no problem since it should always
have a constant size), so input (extractor) needs to be modified.
Recognizes most data, but players array can benefit from some additional
parsing and usage in commands output.

screp

diff --git a/screp b/screp
index 1922415d9b61c5f6f696054e634e4bde069d2612..10a2554826707ef615ef04465ce76b808b43c8c2 100755 (executable)
--- a/screp
+++ b/screp
@@ -417,6 +417,53 @@ sub showtime {
        return sprintf "%d:%04.1f", $minutes, $time - $minutes * 60;
 }
 
+sub unpackhash {
+       my ($template, $expr, @elements) = @_;
+       my @data = unpack $template, $expr;
+       my %map;
+       $map{$_} = shift @data for @elements;
+       return (\%map, @data);
+}
+
+local $_ = Data::StarCraft::Replay::_read(undef, \*STDIN, 633)
+       and my ($head, @headdata) = unpackhash("CVa3Va12Z28v2Z16Z24Ca26a38a*", $_, qw(
+               engine frames mag1 time mag2 name width height
+               unknown1 creator unknown2 map unknown3
+       ))
+       or die "Couldn't read replay header\n";
+
+$_ eq "\0\0\110" or warn sprintf(
+       "Mismatch in first header constant: %s\n",
+       join ",", map ord, split //, $_
+) for $head->{mag1};
+$_ eq "\10"x8 . "\0"x4 or warn sprintf(
+       "Mismatch in second header constant: %s\n",
+       join ",", map ord, split //, $_
+) for $head->{mag2};
+delete $head->{$_} for qw(mag1 mag2 unknown1 unknown2);
+
+my @playdata = unpack "a36"x12 . "V8C8", $headdata[0]
+       or die "Couldn't parse player data in replay header\n";
+
+my @player;
+push @player, unpackhash("x11Z25", shift @playdata, qw/name/) for 0 .. 11;
+$player[$_]->{color} = shift @playdata for 0 .. 7;
+$player[$_]->{index} = shift @playdata for 0 .. 7;
+
+printf "%s: %s\n", $_, $head->{$_} for qw(name creator);
+use Date::Format;
+printf "created: %s\n", time2str('%Y-%m-%d %X', $_) for $head->{time};
+printf "map: %s (%dx%d)\n", map $head->{$_}, qw(map width height);
+printf "frames: %s (%s)\n", $_, showtime($_) for $head->{frames};
+print "\n";
+
+if ($SHOWWARN) {
+       print Dumper $head;
+       print Dumper \@player;
+       #printf ":%s\n", join ",", map sprintf('%X', ord $_), split // for @headdata;
+       print "\n";
+}
+
 my $map = Data::StarCraft::Replay->new->open(\*STDIN);
 
 if ($SHOWWARN) {