mirror of
https://github.com/Pecusx/libretro-atari800.git
synced 2026-05-20 22:33:22 +02:00
initial commit
This commit is contained in:
@@ -0,0 +1,360 @@
|
||||
#!/usr/bin/perl -w
|
||||
# Performance tester for the Atari800 emulator
|
||||
# by Piotr Fusik <fox@scene.pl>
|
||||
use strict;
|
||||
|
||||
# defaults
|
||||
my $test = '';
|
||||
my $target = '';
|
||||
my $cflags = '';
|
||||
my $default_cflags = '-O2 -Wall';
|
||||
my @features = ();
|
||||
my $reference_program = 'dc.xex'; # "Drunk Chessboard"
|
||||
my $frames = 3 * 60 * 50; # 3 Atari minutes
|
||||
# note that "Drunk Chessboard" ends after 3 minutes
|
||||
my $output = '';
|
||||
|
||||
|
||||
# create 'benchmark' directory under 'src/'
|
||||
sub make_directory() {
|
||||
unless (-d 'benchmark') {
|
||||
print "'benchmark' directory does not exist, creating\n";
|
||||
mkdir 'benchmark' or die "Failed to create 'benchmark' directory\n";
|
||||
}
|
||||
}
|
||||
|
||||
# runs a command (the output goes to the console)
|
||||
sub run_command(@) {
|
||||
print "Running: @_\n";
|
||||
system @_ and die "$_[0] failed\n";
|
||||
}
|
||||
|
||||
# runs a command and captures its output
|
||||
sub pipe_command(@) {
|
||||
print "Running: @_\n";
|
||||
my $result = `@_`;
|
||||
die "$_[0] failed\n" if $?;
|
||||
return $result;
|
||||
}
|
||||
|
||||
# addresses of Atari hardware registers
|
||||
my @hwregs = (
|
||||
0xd000 .. 0xd01f, # GTIA
|
||||
0xd200 .. 0xd21f, # POKEY (stereo)
|
||||
0xd300 .. 0xd303, # PIA
|
||||
0xd400 .. 0xd40f # ANTIC
|
||||
);
|
||||
# built-in Atari programs
|
||||
my %programs = (
|
||||
# yes, I really wrote them here directly in the machine language
|
||||
'blank.xex' =>
|
||||
"\xFF\xFF\x00\x06\x39\x06" .
|
||||
"\x78\xEE\x0E\xD4\xEE\x00\xD4" .
|
||||
"\x8D\x0A\xD4" x 16 .
|
||||
"\x4C\x07\x06" .
|
||||
"\xE0\x02\xE1\x02\x00\x06",
|
||||
'incD01A.xex' =>
|
||||
"\xFF\xFF\x00\x06\x39\x06" .
|
||||
"\x78\xEE\x0E\xD4\xEE\x00\xD4" .
|
||||
"\xEE\x1A\xD0" x 16 .
|
||||
"\x4C\x07\x06" .
|
||||
"\xE0\x02\xE1\x02\x00\x06",
|
||||
'flash.xex' =>
|
||||
"\xFF\xFF\x00\x06\x1B\x06" .
|
||||
"\x78\xA9\x00\x8D\x0E\xD4\x8D\x00\xD4" .
|
||||
"\x8D\x0A\xD4\x8D\x0A\xD4" .
|
||||
"\xAE\x0B\xD4\xD0\xF5" .
|
||||
"\x8D\x1A\xD0\x49\xA4" .
|
||||
"\x4C\x09\x06" .
|
||||
"\xE0\x02\xE1\x02\x00\x06",
|
||||
'ramread.xex' =>
|
||||
"\xFF\xFF\x00\x06" . pack('v', 0x060b + 3 * @hwregs) .
|
||||
"\x78\xA9\x00\x8D\x0E\xD4\x8D\x00\xD4" .
|
||||
"\xAD\xFF\x05" x @hwregs .
|
||||
"\x4C\x09\x06" .
|
||||
"\xE0\x02\xE1\x02\x00\x06",
|
||||
'ramstore.xex' =>
|
||||
"\xFF\xFF\x00\x06" . pack('v', 0x060b + 3 * @hwregs) .
|
||||
"\x78\xA9\x00\x8D\x0E\xD4\x8D\x00\xD4" .
|
||||
"\x8D\xFF\x05" x @hwregs .
|
||||
"\x4C\x09\x06" .
|
||||
"\xE0\x02\xE1\x02\x00\x06",
|
||||
'hwread.xex' =>
|
||||
"\xFF\xFF\x00\x06" . pack('v', 0x060b + 3 * @hwregs) .
|
||||
"\x78\xA9\x00\x8D\x0E\xD4\x8D\x00\xD4" .
|
||||
join('', map("\xAD" . pack('v', $_), @hwregs)) .
|
||||
"\x4C\x09\x06" .
|
||||
"\xE0\x02\xE1\x02\x00\x06",
|
||||
'hwstore.xex' =>
|
||||
"\xFF\xFF\x00\x06" . pack('v', 0x060b + 3 * @hwregs) .
|
||||
"\x78\xA9\x00\x8D\x0E\xD4\x8D\x00\xD4" .
|
||||
join('', map("\x8D" . pack('v', $_), @hwregs)) .
|
||||
"\x4C\x09\x06" .
|
||||
"\xE0\x02\xE1\x02\x00\x06"
|
||||
);
|
||||
|
||||
# write a built-in program to a file
|
||||
sub generate_program($) {
|
||||
my $program = shift;
|
||||
print "Generating $program\n";
|
||||
open XEX, ">benchmark/$program"
|
||||
and binmode XEX
|
||||
and print XEX $programs{$program}
|
||||
and close XEX
|
||||
or die "$!\n";
|
||||
}
|
||||
|
||||
# we will be working in the src directory
|
||||
if (-e 'atari.c') {
|
||||
# ok
|
||||
}
|
||||
elsif (-e '../src/atari.c') {
|
||||
# script was run from the util/ directory
|
||||
chdir '../src' or die "Can't chdir to '../src'\n";
|
||||
}
|
||||
else {
|
||||
die "atari.c not found\n";
|
||||
}
|
||||
|
||||
# supported targets
|
||||
my @targets = qw(
|
||||
default falcon windx x11 x11-motif x11-shm
|
||||
x11-xview x11-xview-shm motif shm xview xview-shm
|
||||
);
|
||||
|
||||
my $help_me = 0;
|
||||
|
||||
# get command line options
|
||||
for (@ARGV) {
|
||||
if (/^--test=(.+)/) {
|
||||
$test = $1;
|
||||
}
|
||||
elsif (/^--target=(.+)/) {
|
||||
$target = $1;
|
||||
grep $target eq $_, @targets or die "$target is not a valid target\n";
|
||||
}
|
||||
elsif (/^--cflags=(.+)/) {
|
||||
$cflags = $1;
|
||||
}
|
||||
elsif (/^--program=(.+)/) {
|
||||
$reference_program = $1;
|
||||
}
|
||||
elsif (/^--frames=(\d+)$/) {
|
||||
$frames = $1;
|
||||
}
|
||||
elsif (/^--output=(.+)/) {
|
||||
$output = $1;
|
||||
}
|
||||
elsif ($_ eq '--generate-programs') {
|
||||
make_directory();
|
||||
generate_program($_) for sort keys %programs;
|
||||
exit;
|
||||
}
|
||||
elsif (/^-?-h(elp)?$/) {
|
||||
$help_me = 1;
|
||||
}
|
||||
else {
|
||||
push @features, $_;
|
||||
}
|
||||
}
|
||||
|
||||
# gfx-generating target: windx on Win32, default otherwise
|
||||
my $gfx_target = 'default';
|
||||
if ($^O =~ /win/i) {
|
||||
$gfx_target = 'windx';
|
||||
}
|
||||
|
||||
# must initialize this after parsing the command line
|
||||
# in order to fill in $reference_program
|
||||
my %tests = (
|
||||
'default' => {
|
||||
'target' => $gfx_target,
|
||||
'cflags' => '-D DONT_DISPLAY',
|
||||
'run' => [ $reference_program, 'blank.xex' ]
|
||||
},
|
||||
'basic' => {
|
||||
'target' => 'default',
|
||||
'run' => [ $reference_program, 'blank.xex' ]
|
||||
},
|
||||
'monitorbreak' => {
|
||||
'target' => 'default',
|
||||
'config' => [ '--disable-monitorbreak', '--enable-monitorbreak' ],
|
||||
'run' => [ $reference_program ],
|
||||
},
|
||||
'pagedattrib' => {
|
||||
'target' => 'default',
|
||||
'config' => [ '--disable-pagedattrib', '--enable-pagedattrib' ],
|
||||
'run' => [ $reference_program, 'ramread.xex', 'ramstore.xex', 'hwread.xex', 'hwstore.xex' ],
|
||||
},
|
||||
'cycleexact' => {
|
||||
'target' => $gfx_target,
|
||||
'cflags' => '-D DONT_DISPLAY',
|
||||
'config' => [ '--disable-newcycleexact', '--enable-newcycleexact' ],
|
||||
'run' => [ $reference_program, 'incD01A.xex' ]
|
||||
},
|
||||
'display' => {
|
||||
'target' => $gfx_target,
|
||||
'run' => [ $reference_program, 'blank.xex', 'flash.xex' ]
|
||||
}
|
||||
);
|
||||
|
||||
if (@ARGV == 0 || $help_me) {
|
||||
# display help and exit
|
||||
print <<EOF;
|
||||
benchmark.pl tests performance of the Atari800 emulator with different
|
||||
configuration options and/or different Atari programs.
|
||||
|
||||
Available options:
|
||||
--test=<test> Choose test (required)
|
||||
--target=<target> Choose Atari800 target for the test
|
||||
--cflags="<cflags>" Override CFLAGS (default: "-O2 -Wall" + test-specific)
|
||||
--program=<filename> Choose Atari program to be run (defaults to $reference_program)
|
||||
--frames=<frames> Set number of frames to be run (defaults to $frames)
|
||||
--output=<filename> Output the results to the specified file
|
||||
--generate-programs Just generate all the built-in Atari programs
|
||||
Any other options are passed to the configure script. Use it to affect the set
|
||||
of optional features and external libraries used during the test.
|
||||
|
||||
Available tests:
|
||||
default Compare chosen Atari program with one that does nothing,
|
||||
using default configuration (may be modified
|
||||
with "--enable-<feature>", "--disable-<feature>")
|
||||
(default target: $gfx_target)
|
||||
basic Compare chosen Atari program with one that does nothing
|
||||
(default target: default)
|
||||
monitorbreak Compare configurations with/without MONITOR_BREAK
|
||||
(default target: default)
|
||||
pagedattrib Compare configurations with/without PAGED_ATTRIB
|
||||
(default target: default)
|
||||
cycleexact Compare configurations with/without NEW_CYCLE_EXACT
|
||||
(default target: $gfx_target)
|
||||
display Compare display performance with different Atari programs
|
||||
(default target: $gfx_target)
|
||||
|
||||
Available Atari800 targets:
|
||||
@targets[0..5]
|
||||
@targets[6..11]
|
||||
|
||||
EOF
|
||||
exit;
|
||||
}
|
||||
|
||||
unless (exists $tests{$test}) {
|
||||
die "$test is not an available test\n";
|
||||
}
|
||||
|
||||
# autoconf stuff
|
||||
unless (-e 'config.h.in') {
|
||||
print "'config.h.in' not found\n";
|
||||
run_command('autoheader');
|
||||
}
|
||||
unless (-e 'configure') {
|
||||
print "'configure' not found\n";
|
||||
run_command('autoconf');
|
||||
}
|
||||
|
||||
# create our directory under 'src/'
|
||||
make_directory();
|
||||
|
||||
# create Atari800 config file with ROM paths
|
||||
unless (-r 'benchmark/atari800.cfg') {
|
||||
print "'benchmark/atari800.cfg' does not exist, creating\n";
|
||||
open CFG, '>benchmark/atari800.cfg'
|
||||
and print CFG <<EOF
|
||||
Atari 800 Emulator, Version 1.4.0
|
||||
OS/A_ROM=benchmark/atariosa.rom
|
||||
OS/B_ROM=benchmark/atariosb.rom
|
||||
XL/XE_ROM=benchmark/atarixl.rom
|
||||
BASIC_ROM=benchmark/ataribas.rom
|
||||
5200_ROM=benchmark/atari5200.rom
|
||||
MACHINE_TYPE=Atari XL/XE
|
||||
RAM_SIZE=64
|
||||
EOF
|
||||
and close CFG
|
||||
or die "$!\n";
|
||||
}
|
||||
|
||||
# check if ROMs are configured
|
||||
print "Checking 'benchmark/atari800.cfg'\n";
|
||||
open CFG, 'benchmark/atari800.cfg' or die "$!\n";
|
||||
while (<CFG>) {
|
||||
m!^(?:XL/XE|BASIC)_ROM=(.*?)\s*$! or next;
|
||||
my $romfile = $1;
|
||||
unless (-r $romfile) {
|
||||
die <<EOF;
|
||||
$romfile not found.
|
||||
Place ROM files in the 'benchmark' directory or edit 'benchmark/atari800.cfg',
|
||||
then re-run this script.
|
||||
EOF
|
||||
}
|
||||
}
|
||||
close CFG;
|
||||
|
||||
# create output file
|
||||
unless ($output) {
|
||||
my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
|
||||
$output = sprintf 'benchmark/%s_%04d-%02d-%02d_%02d-%02d-%02d.txt', $test,
|
||||
$year + 1900, $mon + 1, $mday, $hour, $min, $sec;
|
||||
}
|
||||
|
||||
print "Writing output to: $output\n";
|
||||
open OUT, ">$output" or die "$!\n";
|
||||
|
||||
print "Running test: $test\n";
|
||||
print OUT "Test: $test\n";
|
||||
|
||||
# get test settings
|
||||
my $test_settings = $tests{$test};
|
||||
|
||||
$target ||= $test_settings->{'target'};
|
||||
|
||||
$cflags ||= exists($test_settings->{'cflags'})
|
||||
? $default_cflags . ' ' . $test_settings->{'cflags'}
|
||||
: $default_cflags;
|
||||
$cflags .= ' -D BENCHMARK=' . $frames;
|
||||
$ENV{'CFLAGS'} = $cflags;
|
||||
print "Using CFLAGS: $cflags\n";
|
||||
print OUT "CFLAGS=$cflags\n";
|
||||
|
||||
# compile each configuration
|
||||
my @configs = $test_settings->{'config'} ? @{$test_settings->{'config'}} : ('');
|
||||
for my $config (@configs) {
|
||||
print '-' x 76, "\n";
|
||||
# "@{[]}" trick in this print is to avoid two consecutive spaces when @features is empty
|
||||
print OUT "./configure --target=$target --without-sound @{[@features, $config]}\n";
|
||||
run_command('sh', './configure', "--target=$target", '--without-sound', @features, split(' ', $config));
|
||||
run_command('make', 'clean');
|
||||
run_command('make');
|
||||
# run each program
|
||||
for my $program (@{$test_settings->{'run'}}) {
|
||||
if (-r $program) {
|
||||
# ok
|
||||
}
|
||||
elsif (-r "benchmark/$program") {
|
||||
$program = "benchmark/$program";
|
||||
}
|
||||
elsif (exists $programs{$program}) {
|
||||
generate_program($program);
|
||||
$program = "benchmark/$program";
|
||||
}
|
||||
else {
|
||||
die "$program does not exist\n";
|
||||
}
|
||||
my $result = pipe_command('./atari800', '-config', 'benchmark/atari800.cfg', $program);
|
||||
print $result;
|
||||
# parse result
|
||||
$result =~ /\d+ frames emulated in ([0-9.]+) seconds/
|
||||
or die "Expected 'frames emulated in'\n";
|
||||
my $speed_msg = "$1 seconds";
|
||||
# avoid division by zero
|
||||
if ($1 != 0) {
|
||||
# assuming PAL, real Atari needs (0.02 * $frames) time
|
||||
$speed_msg .= sprintf ' (%d%% of real Atari speed)', 100 * 0.02 * $frames / $1;
|
||||
}
|
||||
print "$speed_msg\n\n";
|
||||
printf OUT "./atari800 %-23s # %s\n", $program, $speed_msg;
|
||||
}
|
||||
}
|
||||
|
||||
print OUT "Test complete.\n";
|
||||
close OUT;
|
||||
Reference in New Issue
Block a user