+ my $size = 8 # unpack length (ugh, ugly recalculation)
+ + (defined $level->{name} ? 1 + length $level->{name} : 0)
+ + 3 * (ref $level->{worms} eq 'ARRAY' ? scalar @{$level->{worms}} : 1)
+ + 2 * ($level->{flags} ? ref $level->{flags} eq 'ARRAY' ? scalar @{$level->{flags}} : 1 : 0)
+ + ($level->{sprite} ? scalar @{$level->{sprite}} : 0)
+ + ($level->{balls} ? 3 * scalar @{$level->{balls}} : 0);
+ $level->{size} = $size;
+ $level->{offset} = $offset + $offsetbase;
+
+ # add objects until terminator
+ $level->{objects} = [];
+ if ($version <= 91) {
+ push @{ $level->{objects} }, { %$_, type => 2 } for map { $level->{$_} ? @{ $level->{$_} } : () } qw(objectlines);
+ push @{ $level->{objects} }, { %$_, type => 3 } for map { $level->{$_} ? @{ $level->{$_} } : () } qw(objectboxes);
+ $size += 1 + 4 * scalar @{ $level->{objects} };
+ }
+ else {
+ while (my $object = ord substr($data->{leveldata}, $offset+$size, 1)) {
+ push @{ $level->{objects} }, Shiar_Parse::Nested->unpack(
+ [@OBJECTFORM], substr($data->{leveldata}, $offset+$size, 5)
+ );
+ $size += 5;
+ }
+ }
+
+ # add parsed level and advance
+ push @{ $data->{levels} }, $level;
+ $offset += ++$size;
+ last if ++$data->{levelcount}->{$variant} >= $amount;
+ }
+
+ if ($variant eq 'single') {
+ $offset++;
+ $data->{finish}->{code} =
+ my $code = substr $data->{leveldata}, $offset, -5*$slots;
+
+ my %FINISHCODE = (
+ 0 => chr 0xC9, # ret
+ 1 => join('',
+ chr 0x21, # ld hl, MESSAGE
+ pack('v', $offsetbase + $offset + 9),
+ (map {chr}
+ 0xCD, 0x37, 0x4A, # call _puts
+ 0xC3, 0xAA, 0x55, # jp _getkey
+ ),
+ ),
+ 2 => join('',
+ (map {chr}
+ 0x21, 0, 0x1C, # ld hl, $POS
+ 0x22, 0x7C, 0xC3, # ld (_penCol), hl
+ 0x21, # ld hl, MESSAGE
+ ),
+ pack('v', $offsetbase + $offset + 15),
+ (map {chr}
+ 0xCD, 0xA5, 0x4A, # call _vputs
+ 0xC3, 0xAA, 0x55, # jp _getkey
+ ),
+ ),
+ );
+ while (my ($finish, $match) = each %FINISHCODE) {
+ $match eq substr $code, 0, length $match or next;
+ $data->{finish}->{type} = $finish and
+ $data->{finish}->{message} = unpack 'Z*', substr($code, length $match);
+ last;
+ }