From c0b0123313d8a4895d1c42c8f74675a2be5b6e08 Mon Sep 17 00:00:00 2001 From: Mischa Poslawsky Date: Fri, 27 Feb 2009 00:38:20 +0100 Subject: [PATCH] parse-wormedit: guess specific variant of v95 levels There were 3 different level formats all with the same version 95. Try to autodetect which by looking at some conflicting byte offsets; the only other way is manual specification, which hopefully isn't needed in any practical cases. --- parse-wormedit | 55 +++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/parse-wormedit b/parse-wormedit index 26d6cbd..bc0d926 100755 --- a/parse-wormedit +++ b/parse-wormedit @@ -97,39 +97,52 @@ my @FORMAT = ( sub read { my ($self, $input) = @_; - my ($id, $subid) = (substr($input, 0, 15), ord substr($input, 15, 1)); - my $version = $opt{version} // $MAGICID{$id} + my ($id, $version) = (substr($input, 0, 15), ord substr($input, 15, 1)); + my $fileversion = $MAGICID{$id} or die "File does not match any known WormEdit level header\n"; - $subid == $version - or warn "Unsupported version $subid (expecting $version)\n"; - given ($version) { - when (53) { - # current @FORMAT + + if ($opt{version}) { + warn "Override version $version to $opt{version}\n"; + $version = $opt{version}; + } + elsif ($version != $fileversion) { + warn "Unexpected version $version (expecting $fileversion)\n"; + } + elsif ($version == 95) { + # auto-detect exact variant + if (ord substr($input, 70, 1) ~~ [1 .. 8]) { + # valid sprite length instead of description byte + # (which is usually a letter or nul) + $version = 94; } - when ($_ <= 95 and $_ > 90) { - ref $_ and pop @$_ for @{ $FORMAT[11] }; # only 8 moderefs - $FORMAT[-1]->[-1]->[0] = '32C'; # less objects - continue; + elsif (ord substr($input, 147, 1) == 0) { + # nul of end type is 2 bytes later (unlike first char of endstr) + $version = 96; } - when (95) { + warn "Ambiguous file version 95; guessing subversion $version\n"; + }; + + $fileversion += 100 if $fileversion < 90; # 93..95 came before 50..53 + given ($fileversion) { + when (153) { } # current @FORMAT $FORMAT[7] = 'Ca64'; # no reserved space after description - #ref $_ and $_->[-1] = 'C' for @{ $FORMAT[11] }; # only 9 moderefs $FORMAT[19] = 'Ca255'; # enddata - splice @FORMAT, 6, 2 if $subid < 95; # early (sub)version without description + $FORMAT[-1]->[-1]->[0] = '32C'; # less objects + when ($version == 96) { + ref $_ and $_->[-1] = 'C' for @{ $FORMAT[11] }; # 9 moderefs } - when ($_ <= 94 and $_ > 90) { - splice @FORMAT, 6, 2; # no description + ref $_ and pop @$_ for @{ $FORMAT[11] }; # only 8 moderefs + splice @FORMAT, 6, 2 if $version <= 94; # earlier version without description + when (95) { } splice @{ $FORMAT[7] }, 4, 2; # no race splice @FORMAT, 16, 2; # no enddata splice @{ $FORMAT[-1] }, 1, 2; # no name - continue if $_ < 94; - } - when (93) { + when (94) { } splice @FORMAT, 16, 2; # no hiname $FORMAT[-1]->[0] = 64; # constant amount of levels - } + when (93) { } default { - die "Cannot parse data for Wormedit $version\n"; + die "Cannot parse data for Wormedit $fileversion/$version\n"; } } -- 2.30.0