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.
sub read {
my ($self, $input) = @_;
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";
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;
+ 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
$FORMAT[7] = 'Ca64'; # no reserved space after description
- #ref $_ and $_->[-1] = 'C' for @{ $FORMAT[11] }; # only 9 moderefs
$FORMAT[19] = 'Ca255'; # enddata
$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
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) {
splice @FORMAT, 16, 2; # no hiname
$FORMAT[-1]->[0] = 64; # constant amount of levels
splice @FORMAT, 16, 2; # no hiname
$FORMAT[-1]->[0] = 64; # constant amount of levels
- die "Cannot parse data for Wormedit $version\n";
+ die "Cannot parse data for Wormedit $fileversion/$version\n";