resolutions.pl

#!/usr/bin/perl -s
# resolutions.pl - Copyright (c) 2005,2008 by Mikkel Holm Olsen
use XML::Parser;

sub usage {
    print($err."\n\n") if $err=shift;
    print <<"EOF";
resolutions.pl v2.05  Copyright (c) 2005,2008 by Mikkel Holm Olsen

Generate a list of the most used video-modes for MAME/AdvanceMAME

USAGE
    resolutions.pl [args] list.xml

WHERE
    list.xml - input-file (XML) generated from MAME/AdvanceMAME
               with the --listxml option.

ARGUMENTS
    -r         Don\'t swap hor/ver resolution for vertical games
    -p=pct     Stop after listing pct % (1-100) of the games
    -n=num     Stop after listing num video modes (resolutions)
    -c         Don\'t count clones (only parents)
    -f         Don\'t diffrentiate on refresh frequency
    -o=?       Only list horizontal (h) or vertical (v) games

EOF
    exit;
}

# Handle arguments
$norotate=1 if ${r};
$fraction=$p/100 if ($p)&&($p>0)&&($p<=100);
$maxmodes=$n if $n;
$noclones=1 if $c;
$refresh=1 if !$r;
$filter='';
$filter='horizontal' if ($o eq 'v');
$filter='vertical' if ($o eq 'h');
usage() if $h || ${-help};
usage("Missing filename (list.xml)") if $#ARGV<0;
usage("Only one filename can be given") if $#ARGV>0;

$thisruns=$no_runner=0;

sub start_tag {
my %attrs;
    $expat=shift(@_);
    $elem=shift(@_);
    return if ($elem=~/(rom|chip|dipswitch|dipvalue)/); # x2 speed-up
    while (($key,$val)=splice(@_,0,2)) {
	$attrs{$key}=$val;
    }
    if ($elem eq 'game'){
        $runnable+=$thisruns;
        $norunnable+=$no_runner;
	$thisgame=$attrs{'name'};
	if ($attrs{'runnable'} eq 'yes') {
	    $thisruns=($noclones&&$attrs{'cloneof'})?0:1;
	    $no_runner=0;
	} else {
	    $thisruns=0;
	    $no_runner=1;
	}
    } elsif (!$thisruns) {
	return;
    } elsif (($elem eq 'video')||($elem eq 'display')) {
        $orient="unknown";
        if ($attrs{'orientation'}) { # AdvanceMAME style
            $orient=$attrs{'orientation'};
        } else { # Regular MAME style
            $orient=(((int($attrs{'rotate'})/90)%2)?"vertical":"horizontal");
        }
        if ($filter eq $orient) {
            $thisruns=0;
            return;
        }
	if ($attrs{'type'}.$attrs{'screen'} eq 'raster') {
	    if ($norotate || ($orient eq 'horizontal')) {
		($width,$height)=($attrs{'width'},$attrs{'height'});
	    } else {
		($height,$width)=($attrs{'width'},$attrs{'height'});
	    }
	    $key=$width."x".$height;
	} else { # must be vector then
	    $key="vector";
	}
	$key.="@".sprintf("%.2f",int($attrs{'refresh'}*100)/100) if $refresh;
	$res_count{$key}++;
	$example{$key}=$thisgame;
    }
}

my $file = shift;
die "Can't find file \"$file\"" unless -f $file;

my $parser = new XML::Parser(ErrorContext => 2);
$parser->setHandlers(Start => \&start_tag);
$parser->parsefile($file);
$runnable++ if ($thisruns);
$norunnable++ if ($no_runner);
sub by_count { $res_count{$b} <=> $res_count{$a}; }
foreach $r (sort by_count keys %res_count) {
    printf("%4d %-15s %s\n",$res_count{$r},$r,$example{$r});
    $numgames+=$res_count{$r};
    $nummodes++;
    last if $fraction && ($numgames/$runnable)>=$fraction;
    last if (($maxmodes)&&($nummodes>=$maxmodes));
}

print "\n$nummodes modes for ".$numgames."/".$runnable." ROMs (".
    (int($numgames/$runnable*1000)/10)."%). ".$norunnable." additional non-runnable.\n";

Last updated: 2008.02.26