aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon duSaint2022-04-30 16:16:25 -0700
committerJon duSaint2022-04-30 16:16:25 -0700
commit3160d814a1a088cfbcbd3c48c02d36273fd56383 (patch)
treeee703f562c870ee7ea675b8b682a48da2750ecfa
parent659f12ede69726f46487d6e44aa79f48c2bd2aae (diff)

Commit a bunch of old software

-rwxr-xr-xaudiotron/audiotron402
-rw-r--r--bombs/README3
-rw-r--r--bombs/bombs.pl605
-rw-r--r--bombs/bombs.pngbin0 -> 3197 bytes
-rw-r--r--decomp/COPYING340
-rw-r--r--decomp/Makefile83
-rw-r--r--decomp/README4
-rw-r--r--decomp/alpha.c22
-rw-r--r--decomp/code.c247
-rw-r--r--decomp/data.c245
-rw-r--r--decomp/decomp.c312
-rw-r--r--decomp/decomp.h289
-rw-r--r--decomp/decomp.texinfo611
-rw-r--r--decomp/dos.c887
-rw-r--r--decomp/dos.h675
-rw-r--r--decomp/elf.c853
-rw-r--r--decomp/error.c55
-rw-r--r--decomp/fileinfo.c234
-rw-r--r--decomp/foo.S8684
-rw-r--r--decomp/hash.c307
-rw-r--r--decomp/ia32.c4960
-rw-r--r--decomp/ia32.h327
-rw-r--r--decomp/memory.c454
-rw-r--r--decomp/symtab.c272
-rw-r--r--decomp/test/.runtest0
-rw-r--r--decomp/test/Makefile9
-rw-r--r--decomp/test/bound.S19
-rw-r--r--decomp/test/bound_decomp.S26
-rw-r--r--decomp/test/brev.c54
-rw-r--r--decomp/test/data.c22
-rw-r--r--decomp/test/data_decomp.S282
-rw-r--r--decomp/test/foo.c91
-rw-r--r--decomp/test/hashtest.c555
-rw-r--r--decomp/test/hll.S318
-rw-r--r--decomp/test/hll.c28
-rw-r--r--decomp/test/memtest.c222
-rw-r--r--decomp/test/movlps.S18
-rw-r--r--decomp/test/movtest1.S10
-rw-r--r--decomp/test/prefetch.S18
-rw-r--r--decomp/test/regsize.S12
-rw-r--r--decomp/test/testfoo.c30
-rw-r--r--decomp/test/ud.S13
-rw-r--r--defwrite/README3
-rwxr-xr-xdefwrite/defwrite.m1868
-rwxr-xr-xdefwrite/defwrite.matbin0 -> 53576 bytes
-rwxr-xr-xdefwrite/proceed.bmpbin0 -> 10746 bytes
-rwxr-xr-xdefwrite/quit.bmpbin0 -> 10746 bytes
-rwxr-xr-xdefwrite/reset.bmpbin0 -> 10746 bytes
-rwxr-xr-xdefwrite/view.bmpbin0 -> 10746 bytes
-rw-r--r--fileselect/README4
-rwxr-xr-xfileselect/fileselect.pl303
-rwxr-xr-xfluxbox/fluxbox-generate_menu181
-rwxr-xr-xgpx/gpx2kml.pl253
-rwxr-xr-xgpx/gpxinfo.pl188
-rw-r--r--matfun/README17
-rw-r--r--matfun/matfun.glbbin0 -> 6669 bytes
-rw-r--r--matfun/matfun.h15
-rw-r--r--matfun/matfun.hg3
-rw-r--r--matfun/matfun.hs3
-rw-r--r--matfun/matfun.slbbin0 -> 6669 bytes
-rw-r--r--matfun/matfun.src2197
-rw-r--r--matfun/matfun.txt164
-rw-r--r--matops/matops.pm2625
-rwxr-xr-xmv/MVbin0 -> 1069 bytes
-rw-r--r--mv/mv.src259
-rw-r--r--mv/mv.txt41
-rwxr-xr-xplot/freq.icobin0 -> 1078 bytes
-rwxr-xr-xplot/genfun.c667
-rwxr-xr-xplot/pld.icobin0 -> 1078 bytes
-rwxr-xr-xplot/plot.c2101
-rwxr-xr-xplot/plot.exebin0 -> 90112 bytes
-rwxr-xr-xplot/plot.h103
-rwxr-xr-xplot/plot.rc207
-rwxr-xr-xplot/sawtooth_wave.bmpbin0 -> 358 bytes
-rwxr-xr-xplot/sin_wave.bmpbin0 -> 358 bytes
-rwxr-xr-xplot/square_wave.bmpbin0 -> 358 bytes
-rw-r--r--signature/COPYING341
-rw-r--r--signature/INSTALL20
-rw-r--r--signature/Makefile25
-rw-r--r--signature/NEWS1
-rw-r--r--signature/README15
-rwxr-xr-xsignature/configure.pl65
-rw-r--r--signature/signature.c229
-rw-r--r--signature/version.h1
-rw-r--r--spacetweet/README6
-rw-r--r--spacetweet/rocket.pngbin0 -> 6458 bytes
-rwxr-xr-xspacetweet/spacetweet.py227
-rwxr-xr-xtap/BUGS0
-rwxr-xr-xtap/INSTALL0
-rwxr-xr-xtap/Makefile69
-rwxr-xr-xtap/NEWS0
-rwxr-xr-xtap/README8
-rwxr-xr-xtap/command_struct.h122
-rwxr-xr-xtap/commands/Makefile18
-rwxr-xr-xtap/commands/alias.c185
-rwxr-xr-xtap/commands/commands.h30
-rwxr-xr-xtap/commands/serial.c110
-rwxr-xr-xtap/commands/set.c315
-rwxr-xr-xtap/commands/translate.c431
-rwxr-xr-xtap/commands/user.c378
-rwxr-xr-xtap/memmgr.c257
-rwxr-xr-xtap/readline/Makefile38
-rwxr-xr-xtap/readline/history.c244
-rwxr-xr-xtap/readline/line.c340
-rwxr-xr-xtap/readline/readline.h243
-rwxr-xr-xtap/readline/ring.c114
-rwxr-xr-xtap/readline/tab.c530
-rwxr-xr-xtap/readline/text.c354
-rwxr-xr-xtap/serial.c87
-rwxr-xr-xtap/tap.c274
-rwxr-xr-xtap/tap.h370
-rwxr-xr-xtap/tap.texinfo826
-rwxr-xr-xtap/ui.c369
-rwxr-xr-xtap/version.h1
-rwxr-xr-xupdate/update.c224
-rwxr-xr-xupdate/update.exebin0 -> 60416 bytes
-rwxr-xr-xupdate/update.icobin0 -> 1078 bytes
-rwxr-xr-xupdate/update.rc3
-rw-r--r--uu/AUTHORS3
-rw-r--r--uu/COPYING340
-rw-r--r--uu/INSTALL6
-rw-r--r--uu/Makefile28
-rw-r--r--uu/NEWS3
-rw-r--r--uu/TODO1
-rw-r--r--uu/uu.h58
-rw-r--r--uu/uudecode.c461
-rw-r--r--uu/uuencode.c211
-rw-r--r--xalarm/AUTHORS2
-rw-r--r--xalarm/BUGS10
-rw-r--r--xalarm/COPYING340
-rw-r--r--xalarm/Makefile.in32
-rw-r--r--xalarm/NEWS9
-rw-r--r--xalarm/README65
-rw-r--r--xalarm/TODO4
-rw-r--r--xalarm/configure.in36
-rw-r--r--xalarm/version.h1
-rw-r--r--xalarm/xalarm.c486
-rw-r--r--xkill/xkill.c88
-rwxr-xr-xxkill/xkill.exebin0 -> 57344 bytes
-rw-r--r--xkill/xkill.icobin0 -> 1078 bytes
140 files changed, 42854 insertions, 0 deletions
diff --git a/audiotron/audiotron b/audiotron/audiotron
new file mode 100755
index 0000000..a9c5d3a
--- /dev/null
+++ b/audiotron/audiotron
@@ -0,0 +1,402 @@
+#!/usr/bin/env perl
+#
+# audiotron --
+#
+# Scan directories for mp3 files to create a database file for the
+# Turtle Beach AudioTron.
+#
+# Copyright (C) 2011-2013 Jonathan duSaint <jon@rockgeeks.net>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details:
+# <http://www.gnu.org/licenses/gpl-2.0.html>
+#
+
+use strict;
+use warnings;
+
+use File::Spec::Functions qw(abs2rel catfile splitdir splitpath tmpdir);
+use Getopt::Long;
+use MP3::Info;
+use Pod::Usage;
+
+
+my $verbose = 0;
+my $log = undef;
+my $test = 0;
+my $help = 0;
+my $man = 0;
+GetOptions('verbose|v' => \$verbose,
+ 'log|L=s' => \$log,
+ 'test|t' => \$test,
+ 'help|h' => \$help,
+ 'man' => \$man) or pod2usage(2);
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+
+my $TOCFILE = 'atrontc.vtc';
+my $nfiles = 0;
+my $logfile;
+
+sub verbose($) {
+ print $_[0] if $verbose;
+ print $logfile $_[0] if defined $logfile;
+}
+
+if (defined($log)) {
+ verbose("Logging to $log\n");
+ open($logfile, ">$log") or die "Logging to $log failed: $!";
+}
+
+my $start_time = time();
+
+foreach my $basedir (@ARGV) {
+ unless (-d $basedir) {
+ warn "$basedir does not exist. Skipping.";
+ next;
+ }
+
+ $nfiles += process_directory($basedir);
+}
+
+my $etime = time() - $start_time;
+
+print "Done. Processed $nfiles files in $etime seconds.\n";
+close($logfile) if defined $logfile;
+
+exit(0);
+
+
+#
+# guess_mp3info --
+#
+# If no ID3 tag is present in the mp3, this routine guesses the
+# contents of the fields based on filename and directory
+# information.
+#
+# Filename and path formats tend to be:
+#
+# <ARTIST>-<TITLE>
+# <ARTIST>/<ALBUM>/<TITLE>
+# <ARTIST>/<TITLE>
+# <TITLE>
+# Sometimes <TRACKNUM> is present in the filename, too.
+#
+
+sub guess_mp3info {
+ my ($basedir, $path) = @_;
+
+ my $dir;
+ my ($artist, $album, $title, $tracknum) =
+ ('Unknown', 'Unknown', 'Unknown', undef);
+
+ ($dir, $title) = (splitpath(abs2rel($path, $basedir)))[1..2];
+
+ my @path = splitdir($dir);
+ pop @path if $path[-1] eq '';
+
+ if (@path >= 2) {
+ ($artist, $album) = @path[-2..-1];
+ } elsif (@path == 1) {
+ $artist = $path[0];
+ }
+
+ $title =~ s/\.mp3$//;
+ if ($title =~ m/(\d+)[-_](.+)$/) {
+ ($tracknum, $title) = ($1, $2);
+ $title =~ s/^-//;
+ }
+
+ if ($title =~ m/([^-]+)-(.+)/) {
+ $title = $2;
+ if ($album eq 'Unknown') {
+ $album = $artist;
+ }
+ $artist = $1;
+ }
+
+ foreach my $v (\($artist, $album, $title)) {
+ $$v =~ s/_/ /g; # Underscores to spaces
+ $$v =~ s/^\s+//; # Delete leading spaces
+ $$v =~ s/\s+$//; # Delete trailing spaces
+ $$v =~ s/\b(\w)/\u$1/g; # Convert name to titlecase
+ }
+
+ verbose "Guessing ID3: $artist/$album/" . ($tracknum || '--') . "/$title\n";
+
+ return +{ARTIST => $artist,
+ ALBUM => $album,
+ TITLE => $title,
+ GENRE => 'Unknown',
+ TRACKNUM => $tracknum};
+}
+
+#
+# cleanup_entry --
+#
+# Examine the fields in the hash returned by MP3::Info, modifying
+# them as needed so that no field is empty and that the information
+# is in a format acceptable to the Audiotron.
+#
+# The input argument $info is modified by this subroutine.
+
+sub cleanup_entry {
+ my ($infile, $basedir, $mp3s, $info) = @_;
+
+ # Add fields:
+ # FILE
+ # DIR
+ # SECS
+
+ my ($vol, $dir, $file) = splitpath($infile);
+ my $reldir = abs2rel($dir, $basedir);
+ $reldir .= '/' unless $reldir =~ m|/$|;
+ $reldir =~ s|/|\\|g;
+ $info->{FILE} = $file;
+ $info->{DIR} = $reldir;
+
+ my $i = get_mp3info($infile);
+ $info->{SECS} = int($i->{SECS});
+
+ # Check fields:
+ # ARTIST
+ # ALBUM
+ # TITLE
+ # GENRE
+ # TRACKNUM
+
+ foreach my $v (\($info->{ARTIST}, $info->{ALBUM}, $info->{TITLE})) {
+
+ $$v =~ s/_/ /g; # Underscores to spaces
+ $$v =~ s/^\s+//; # Delete leading spaces
+ $$v =~ s/\s+$//; # Delete trailing spaces
+ $$v =~ s/\b(\w)/\u$1/g; # Convert name to titlecase
+ }
+
+ $info->{GENRE} = 'Unknown' unless $info->{GENRE};
+
+ if ($info->{TRACKNUM}) {
+ # Ensure the tracknum is canonical.
+ $info->{TRACKNUM} =~ s/^\D*(\d+).*/$1/;
+ } else {
+ # If there is no track information, first check the filename for a
+ # digit prefix. If found use that, otherwise, use "unsorted%n" as
+ # the key to maintain uniqueness and translate it later.
+ if ($info->{FILE} =~ m/^(\d+)/) {
+ $info->{TRACKNUM} = $1;
+ } else {
+ my @tracks = sort(keys(%{$mp3s->{$info->{ARTIST}}->{$info->{ALBUM}}}));
+ my $idx = 0;
+ if (@tracks and $tracks[-1] =~ m/^unsorted(\d\d)$/) {
+ $idx = $1 + 1;
+ }
+ $info->{TRACKNUM} = sprintf('unsorted%02d', $idx);
+ }
+ }
+}
+
+#
+# process_mp3 --
+#
+# Process one mp3 file, getting or guessing its ID3 info.
+#
+
+sub process_mp3 {
+ my ($mp3s, $basedir, $file) = @_;
+ my $info = get_mp3tag($file);
+
+ if (not defined($info) or
+ not $info->{ARTIST} or not $info->{ALBUM} or not $info->{TITLE}) {
+ $info = guess_mp3info($basedir, $file);
+ }
+
+ cleanup_entry($file, $basedir, $mp3s, $info);
+
+ unless (defined($mp3s->{$info->{ARTIST}})) {
+ $mp3s->{$info->{ARTIST}} = {};
+ }
+ unless (defined($mp3s->{$info->{ARTIST}}->{$info->{ALBUM}})) {
+ $mp3s->{$info->{ARTIST}}->{$info->{ALBUM}} = {};
+ }
+
+ $mp3s->{$info->{ARTIST}}->{$info->{ALBUM}}->{$info->{TRACKNUM}} = $info;
+}
+
+
+#
+# sort_album --
+#
+# Sort an album by its track info and return an ordered list of
+# keys. If no track number information was present, the order is
+# whatever the album directory structure returned.
+#
+
+sub sort_album {
+ my $album = $_[0];
+
+ my @sorted = ();
+ my @unsorted = ();
+
+ foreach my $k (keys(%$album)) {
+ if ($k =~ m/^unsorted/) {
+ push @unsorted, $k;
+ } else {
+ push @sorted, $k;
+ }
+ }
+
+ @sorted = sort {$a <=> $b} @sorted;
+ my $maxidx = @sorted ? int($sorted[-1]) + 1 : 0;
+ foreach my $k (sort {substr($a, 8, 2) <=> substr($b, 8, 2)} @unsorted) {
+ $album->{$k}->{TRACKNUM} = int(substr($k, 8, 2)) + $maxidx;
+ push @sorted, $k;
+ }
+
+ return @sorted;
+}
+
+#
+# create_output_entry --
+#
+# Create one entry in the TOC file.
+#
+
+sub create_output_entry {
+ my ($outfile, $entry) = @_;
+
+ print $outfile <<"ENTRY";
+SONG
+FILE=$entry->{FILE}
+DIR =$entry->{DIR}
+TCON=$entry->{GENRE}
+TLEN=$entry->{SECS}
+TRCK=$entry->{TRACKNUM}
+TALB=$entry->{ALBUM}
+TPE1=$entry->{ARTIST}
+TIT2=$entry->{TITLE}
+END
+ENTRY
+}
+
+#
+# create_output_file --
+#
+# Generate a TOC file.
+#
+
+sub create_output_file {
+ my ($mp3s, $output_filename) = @_;
+ my $outfile;
+
+ open($outfile, ">$output_filename") or die "Failed to open $output_filename";
+
+ foreach my $artist (sort(keys(%$mp3s))) {
+ foreach my $album (sort(keys(%{$mp3s->{$artist}}))) {
+ foreach my $tracknum (sort_album($mp3s->{$artist}->{$album})) {
+ verbose "Outputting $artist/$album/$tracknum\n";
+ create_output_entry($outfile, $mp3s->{$artist}->{$album}->{$tracknum});
+ }
+ }
+ }
+
+ close($outfile);
+}
+
+
+#
+# process_directory --
+#
+# Process one directory tree and output one TOC file in the top
+# directory. This should generally be the base directory of a
+# share used by the Audiotron that contains mp3 files.
+#
+
+sub process_directory {
+ my $basedir = $_[0];
+ my @dirs = ($basedir);
+ my $mp3s = {};
+ my $nfiles = 0;
+
+ while (1) {
+ last unless @dirs;
+ my $dir = shift(@dirs);
+
+ verbose "Processing $dir\n";
+
+ unless (opendir(D, $dir)) {
+ warn "Failed to open $dir\n";
+ next;
+ }
+
+ foreach my $entry (readdir(D)) {
+ next if $entry =~ m/^\.\.?$/;
+ $entry = catfile($dir, $entry);
+ if (-d $entry) {
+ push(@dirs, $entry);
+ } elsif (-f $entry and $entry =~ m/\.mp3$/) {
+ $nfiles++;
+ process_mp3($mp3s, $basedir, $entry);
+ }
+ }
+
+ closedir(D);
+ }
+
+ my $outfile = catfile($test ? tmpdir() : $basedir, $TOCFILE);
+
+ print "Creating $outfile\n";
+ create_output_file($mp3s, $outfile);
+
+ return $nfiles;
+}
+
+__END__
+
+=head1 NAME
+
+audiotron - Generate TOC files for the Audiotron
+
+=head1 SYNOPSIS
+
+audiotron [options] <directories>
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--help>
+
+Print a brief help message and exit.
+
+=item B<--man>
+
+Print the manual page and exit
+
+=item B<--verbose>
+
+Print processing information to the console.
+
+=item B<--log>
+
+Print processing information to a log file.
+
+=item B<--test>
+
+Output TOC file to /tmp/atrontc.vtc
+
+=back
+
+=head1 DESCRIPTION
+
+B<audiotron> scans directories for mp3 files to create a database
+file for the Turtle Beach AudioTron. The directory should be the
+base directory of an exported share.
+
+=cut
diff --git a/bombs/README b/bombs/README
new file mode 100644
index 0000000..11e0cc3
--- /dev/null
+++ b/bombs/README
@@ -0,0 +1,3 @@
+A simple game ala Missile Command where you have to shoot falling
+bombs before they blow up your otherwise defenseless territory. One
+way to waste some time.
diff --git a/bombs/bombs.pl b/bombs/bombs.pl
new file mode 100644
index 0000000..adb9cdb
--- /dev/null
+++ b/bombs/bombs.pl
@@ -0,0 +1,605 @@
+# bombs.pl
+# shoot the bombs
+
+# FIXME: eliminate collisions with dup scores (add .1 to each dupe)
+
+use strict;
+use warnings;
+use Tk;
+
+my $score = 0;
+my $level = 1;
+my $high_score; # get this from the score file
+
+my $score_increment = 1;
+
+my $in_game = 0;
+my $paused = 0;
+
+my $bfreq = 40; # chance of dropping a new bomb == 1/$bfreq
+
+# level = ( bfreq, bm )
+my @levels = (
+ [ 10, 5 ], # level 0 - not really a level, but used after 31
+ [ 40, 2 ], # level 1
+ [ 39, 2 ], # level 2
+ [ 38, 2 ], # level 3
+ [ 37, 2 ], # level 4
+ [ 36, 2 ], # level 5
+ [ 35, 2 ], # level 6
+ [ 34, 2 ], # level 7
+ [ 33, 2 ], # level 8
+ [ 32, 3 ], # level 9
+ [ 31, 3 ], # level 10
+ [ 30, 3 ], # level 11
+ [ 29, 3 ], # level 12
+ [ 28, 3 ], # level 13
+ [ 27, 3 ], # level 14
+ [ 26, 3 ], # level 15
+ [ 25, 3 ], # level 16
+ [ 24, 4 ], # level 17
+ [ 23, 4 ], # level 18
+ [ 22, 4 ], # level 19
+ [ 21, 4 ], # level 21
+ [ 20, 4 ], # level 22
+ [ 19, 4 ], # level 23
+ [ 18, 4 ], # level 24
+ [ 17, 5 ], # level 25
+ [ 16, 5 ], # level 26
+ [ 15, 5 ], # level 27
+ [ 14, 5 ], # level 28
+ [ 13, 5 ], # level 29
+ [ 12, 5 ], # level 30
+ [ 11, 5 ] # level 31 - last real level
+ );
+
+my $score_dir = 'S:\\';
+my $score_file = 'scores.txt';
+my %scores;
+
+$score_file = "$score_dir$score_file" if -d $score_dir;
+
+
+my $width = 500;
+my $height = 300;
+
+my $pd; # the defender
+my $dw = 10; # defender width
+my $dh = 10; # defender height
+my $dx = $width / 2; # defender x pos
+my $dm = 7; # defender movement
+
+my $sy = 5; # shot height
+my $sm = 10; # shot movement
+
+my $bh = 10; # bomb height
+my $bw = 5; # bomb width
+my $bm = 2; # bomb movement
+my $prox = 3; # kill proximity for a bomb
+
+my $oh = 12; # boom height
+my $ow = 12; # boom width
+
+my %shots; # shots from the defender
+my %bombs; # bombs from the sky
+my %booms; # collision after-effects
+
+my $mode = 'NORMAL';
+
+my $blitz = 'Blitz';
+
+my $txcolor = 'white'; # text color
+my $bkcolor = 'black'; # background color
+my $bbcolor = 'red'; # bomb color
+my $bocolor = 'orange'; # boom color
+my $shcolor = 'blue'; # shot color
+my $decolor = 'white'; # defender color
+
+
+my $start_string = "Press 'n' to start a new game\n'h' for help";
+
+my $tick;
+my $super = '';;
+
+my $old_level;
+
+my ( $thscore, $tscore, $tstart, $thelp, $tscores );
+
+my $main = MainWindow->new (-title => 'Bombs!');
+my $canvas = $main->Canvas (-width => $width, -height => $height,
+ -bg => $bkcolor, -relief => 'ridge')->pack;
+
+read_scores ();
+bind_keys ();
+draw_scores ();
+show_start ();
+
+srand ();
+
+MainLoop;
+
+quit ();
+
+
+# quit the program
+sub quit {
+ write_scores ();
+ exit (0);
+}
+
+# create key bindings
+sub bind_keys {
+ $main->bind ('<h>', \&show_help);
+ $main->bind ('<H>', \&show_help);
+ $main->bind ('<n>', \&start_game);
+ $main->bind ('<N>', \&start_game);
+ $main->bind ('<p>', \&pause_game);
+ $main->bind ('<P>', \&pause_game);
+ $main->bind ('<q>', \&quit_game);
+ $main->bind ('<Q>', \&quit_game);
+ $main->bind ('<s>', \&show_scores);
+ $main->bind ('<S>', \&show_scores);
+ $main->bind ('<KeyPress-space>', \&fire);
+ $main->bind ('<Left>', \&move_left);
+ $main->bind ('<Right>', \&move_right);
+ $main->bind ('<b>', \&toggle_blitz);
+ $main->bind ('<B>', \&toggle_blitz);
+ $main->bind ('<c>', \&toggle_cnn);
+ $main->bind ('<C>', \&toggle_cnn);
+ $main->bind ('<l>', \&toggle_super);
+ $main->bind ('<L>', \&toggle_super);
+}
+
+sub start_timer {
+ $tick = $main->repeat (100, \&tick);
+}
+
+sub stop_timer {
+ $tick->cancel ();
+}
+
+
+#############################################################################
+# Score section #
+#############################################################################
+
+# read the scores file, or create one if it doesn't exist
+sub read_scores {
+ # make sure the score file exists
+ unless (-f $score_file) {
+ open SF, ">$score_file" or return;
+ print SF <<"DEFSCORES"
+300:JR Bob Dobbs
+200:William Wallace
+100:Paul Atreides
+75:Kaiser Soze
+50:Silent Bob
+40:Bill S Preston, Esquire
+30:The machine that goes Ping
+20:Texas Pete
+10:Michael Bolton
+5:Nobody
+DEFSCORES
+ ;
+ close SF
+ }
+
+ open SF, "<$score_file" or return;
+ $scores{$1} = $2 while (<SF> =~ m/^(\d+):(.*)$/);
+ close SF;
+
+ my @tscorelist = sort { $b <=> $a } keys (%scores);
+ $high_score = $tscorelist[0];
+}
+
+# write the score file
+sub write_scores {
+ open SF, ">$score_file" or return;
+ print SF "$_:" . $scores{$_} ."\n" foreach (sort { $b <=> $a } keys %scores);
+ close SF;
+}
+
+my $score_name;
+my $stext;
+sub get_score_name {
+ my $c = $_[1];
+
+ $c = ' ' if $c eq 'KeyPress-space';
+ chop $score_name, $c = '' if $c eq 'BackSpace';
+
+ if ($c eq 'Return') {
+ foreach my $k ('A' .. 'Z', 'a' .. 'z', '0' .. '9',
+ 'KeyPress-space', 'Return', 'BackSpace') {
+ $main->bind ("<$k>", undef);
+ }
+ bind_keys ();
+ $scores{$score} = $score_name;
+ write_scores ();
+ $canvas->delete ($stext);
+ show_scores ();
+ return;
+ }
+
+ $score_name .= $c;
+
+ clear_screen ();
+ $canvas->delete ($stext);
+ $stext = $canvas->create ('text', $width / 2, $height / 2,
+ -anchor => 'center', -fill => $txcolor,
+ -justify => 'center',
+ -text => "Congratulations, you have a high score\n"
+ . "Please enter your name\n\n${score_name}|");
+}
+
+# called at the end of a game - add the score to the high scores, if applicable
+sub score_game {
+ read_scores ();
+
+ $scores{$score} = '';
+ my @tscorelist = sort { $b <=> $a } keys (%scores);
+ my %ts;
+
+ $ts{$_} = $scores{$_} foreach (@tscorelist[0 .. 9]);
+ %scores = %ts;
+
+ return show_start () if not defined $scores{$score}; # not a high score
+
+ # a high score, get the name
+ $score_name = '';
+ foreach my $k ('A' .. 'Z', 'a' .. 'z', '0' .. '9',
+ 'KeyPress-space', 'Return', 'BackSpace') {
+ $main->bind ("<$k>", [ \&get_score_name, $k ]);
+ }
+
+ get_score_name ('', '');
+}
+
+
+#############################################################################
+# Screen message section #
+#############################################################################
+
+# clear messages off the screen
+sub clear_screen {
+ $canvas->delete ($tstart);
+ $canvas->delete ($thelp);
+ $canvas->delete ($tscores);
+}
+
+# delete bombs, booms, and shots from the screen
+sub clear_sprites {
+ foreach my $s (keys %shots) {
+ $canvas->delete ($s);
+ delete ($shots{$s});
+ }
+ foreach my $b (keys %bombs) {
+ $canvas->delete ($b);
+ delete ($bombs{$b});
+ }
+ foreach my $b (keys %booms) {
+ $canvas->delete ($b);
+ delete ($booms{$b});
+ }
+}
+
+# display a message while waiting for the game to start
+sub show_start {
+ clear_screen ();
+ $tstart = $canvas->create ('text', $width / 2, $height / 2,
+ -anchor => 'center', -fill => $txcolor,
+ -justify => 'center',
+ -text => $start_string);
+}
+
+# display the high score list
+sub show_scores {
+ return if $in_game;
+
+ clear_screen ();
+
+ my $slist = "High Scores\n\n";
+
+ $slist .= sprintf ("%-10s", $_) . $scores{$_} . "\n"
+ foreach (sort { $b <=> $a } keys %scores);
+
+ $thelp = $canvas->create ('text', $width / 2, $height / 2,
+ -anchor => 'center', -fill => $txcolor,
+ -justify => 'left',
+ -text => $slist);
+}
+
+# display help text
+sub show_help {
+ return if $in_game;
+
+ clear_screen ();
+
+ $thelp = $canvas->create ('text', $width / 2, $height / 2,
+ -anchor => 'center', -fill => $txcolor,
+ -justify => 'center',
+ -text => "Bombs!\n\n"
+ . "Destroy the bombs before they fall on your "
+ . "otherwise defenseless territory.\n\n"
+ . "Left Arrow moves left\n"
+ . "Right Arrow moves right\n"
+ . "Space fires\n"
+ . "b toggles blitz mode (costs 15 points)\n"
+ . "c toggles CNN mode (bombs over Baghdad)\n"
+ . "h gets you this help\n"
+ . "n starts a new game\n"
+ . "p pauses your game\n"
+ . "q quits\n"
+ . "s shows you the high scores\n");
+}
+
+# draw the status messages in the top corners
+sub draw_scores {
+ $canvas->delete ($tscore);
+ $tscore = $canvas->create ('text', 1, 1, -anchor => 'nw',
+ -width => $width - 2, -justify => 'left',
+ -fill => $txcolor,
+ -text => "Score: $score\n${super}Level: $level");
+ $canvas->delete ($thscore);
+ $thscore = $canvas->create ('text', $width - 1, 1, -anchor => 'ne',
+ -width => $width - 2, -justify => 'right',
+ -fill => $txcolor,
+ -text => "High Score: $high_score");
+}
+
+
+#############################################################################
+# Key handling routines
+#############################################################################
+
+
+# Move defender left
+sub move_left {
+ return if not $in_game or $paused;
+
+ $canvas->move ($pd, -$dm, 0), $dx -= $dm if $dx > 0;
+}
+
+# Move defender right
+sub move_right {
+ return if not $in_game or $paused;
+
+ $canvas->move ($pd, $dm, 0), $dx += $dm if $dx < $width;
+}
+
+# Fire a shot
+sub fire {
+ return if not $in_game or $paused;
+
+ my $dy = $height - $dh;
+ $shots{$canvas->create ('line', $dx, $dy, $dx, $dy - $sy,
+ -fill => $shcolor)} = [ $dx, $dy ];
+}
+
+
+# Start a new game with defaults
+sub start_game {
+ return if $in_game;
+
+ $score = 0;
+ $level = 1;
+ $dx = $width / 2;
+ $in_game = 1;
+
+ change_level ();
+ clear_screen ();
+ draw_defender ();
+ start_timer ();
+}
+
+# Pause a game in progress
+sub pause_game {
+ return if not $in_game;
+
+ if ($paused) {
+ start_timer ();
+ $paused = 0;
+ } else {
+ stop_timer ();
+ $paused = 1;
+ }
+}
+
+# Quit game or toggle blitz mode off
+sub quit_game {
+ quit () if not $in_game;
+
+ # reset to previous level if in blitz mode
+ toggle_blitz (), return if shift eq $blitz;
+
+ $start_string = "GAME OVER\n\nPress 'n' for a new game\n'h' for help";
+
+ $in_game = 0;
+ $canvas->delete ($pd);
+
+ clear_sprites ();
+ stop_timer ();
+ score_game ();
+}
+
+# Turn blitz mode on and off
+sub toggle_blitz {
+ return if not $in_game;
+
+ clear_sprites ();
+
+ if ($level eq $blitz) {
+ $level = $old_level;
+ $score_increment = 1;
+ } else {
+ $old_level = $level;
+ $level = $blitz;
+ $bfreq = 10;
+ $bm = 6;
+ $score_increment = 5;
+ $score -= 15;
+ }
+
+ change_level ();
+}
+
+# Turn supervisor mode on and off
+sub toggle_super {
+ if (length $super) {
+ $super = '';
+ $main->bind ('<Up>', undef);
+ $main->bind ('<Down>', undef);
+ } else {
+ return if $level eq $blitz;
+ $super = '(S)';
+ $main->bind ('<Up>', sub { $level++; change_level (); });
+ $main->bind ('<Down>', sub { $level--; change_level (); });
+ }
+}
+
+# Turn CNN mode on and off
+sub toggle_cnn {
+ if ($mode eq 'CNN') {
+ ( $txcolor, $bkcolor, $bbcolor, $bocolor, $shcolor, $decolor )
+ = ( 'white', 'black', 'red', 'orange', 'blue', 'white' );
+ $mode = 'NORMAL';
+ } else {
+ ( $txcolor, $bkcolor, $bbcolor, $bocolor, $shcolor, $decolor )
+ = ( 'yellow', 'green', 'yellow', 'yellow', 'yellow', 'yellow' );
+ $mode = 'CNN';
+ }
+
+ # redraw stuff here
+ $canvas->configure (-bg => $bkcolor);
+ $canvas->itemconfigure ($pd, -fill, $decolor);
+
+ foreach my $s (keys %shots) {
+ $canvas->itemconfigure ($s, -fill, $shcolor);
+ }
+ foreach my $b (keys %bombs) {
+ $canvas->itemconfigure ($b, -fill, $bbcolor, -outline, $bbcolor);
+ }
+ foreach my $b (keys %booms) {
+ $canvas->itemconfigure ($b, -fill, $bocolor, -outline, $bocolor);
+ }
+}
+
+
+# Create the defender at the start of a game
+sub draw_defender {
+ $pd = $canvas->create ('polygon', $dx - $dw / 2, $height,
+ $dx + $dw / 2, $height,
+ $dx, $height - $dh,
+ -fill => $decolor);
+}
+
+
+# set the defaults for the current level
+sub change_level {
+ my $lv = $level;
+ return if $lv eq $blitz;
+ $lv = 0 if not defined $levels[$lv];
+
+ $bfreq = $levels[$lv][0];
+ $bm = $levels[$lv][1];
+
+ # level 1-19, score += 1; 20-29, += 2, 30+, += 3
+ $score_increment = ($level < 20) ? 1 : ($level < 30) ? 2 : 3;
+}
+
+# hit a bomb, increase the score, and the level if it's not blitz mode
+sub increment_score {
+ $score += $score_increment;
+ $high_score = $score if $score > $high_score;
+
+ if ($level ne $blitz and not ($score % 15)) { $level++; change_level (); }
+}
+
+
+# callback for drawing sprites
+sub tick {
+
+ # do the shots
+ foreach my $s (keys %shots) {
+ my ( $dx, $y ) = @{$shots{$s}};
+
+ if ($y < $sm) {
+ $canvas->delete ($s);
+ delete ($shots{$s});
+ next;
+ }
+
+ $canvas->move ($s, 0, -$sm);
+ ${$shots{$s}}[1] -= $sm;
+ }
+
+ # do the bombs
+
+ # 1/bfreq chance of a new bomb dropping, or create one if there are none
+ if (rand $bfreq > ($bfreq - 1) or scalar (keys(%bombs)) < 1) {
+ my $dx = int rand ($width - $bw + 1);
+ $bombs{$canvas->create ('oval', $dx, 0, $dx + $bw, $bh,
+ -fill => $bbcolor, -outline => $bbcolor)}
+ = [ $dx, 0 ];
+ }
+
+ foreach my $b (keys %bombs) {
+ my ( $dx, $dy ) = @{$bombs{$b}};
+
+ if (($dy + $bh) > $height) {
+ # bomb got us !!
+ return quit_game ($level);
+ }
+
+ $canvas->move ($b, 0, $bm);
+ ${$bombs{$b}}[1] += $bm;
+ }
+
+ # check for collisions
+ COLLISION:
+ foreach my $b (keys %bombs) {
+ my ( $x, $y ) = @{$bombs{$b}};
+
+ my @tags = $canvas->find ('overlapping', $x - $prox, $y - $prox,
+ $x + $bw + $prox, $y + $bh + $prox);
+
+ next if @tags == 0; # not in proximity to anything
+
+ # find out if there is a shot or boom nearby
+ foreach my $t (@tags) {
+ goto BOOM if defined ($shots{$t}) or defined ($booms{$t});
+ }
+ next COLLISION; # didn't find anything - try again
+
+ BOOM:
+ # delete the bomb
+ $canvas->delete ($b);
+ delete ($bombs{$b});
+
+ # delete everything nearby
+ foreach my $t (@tags) {
+ # make sure to not destroy the defender
+ next if defined ($canvas->type ($t)) and $canvas->type ($t) eq 'polygon';
+ $canvas->delete ($t);
+ delete ($shots{$t}) if defined $shots{$t};
+ }
+
+ # create a boom
+ $booms{$canvas->create ('oval', $x, $y, $x + $ow, $y + $oh,
+ -fill => $bocolor, -outline => $bocolor)} = 5;
+
+ increment_score ();
+ }
+
+ # decrement booms and get rid of them as needed
+ foreach my $b (keys %booms) {
+ unless ($booms{$b}) {
+ $canvas->delete ($b);
+ delete ($booms{$b});
+ next;
+ }
+
+ $booms{$b}--;
+ }
+
+ draw_scores ();
+}
diff --git a/bombs/bombs.png b/bombs/bombs.png
new file mode 100644
index 0000000..832b798
--- /dev/null
+++ b/bombs/bombs.png
Binary files differ
diff --git a/decomp/COPYING b/decomp/COPYING
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/decomp/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/decomp/Makefile b/decomp/Makefile
new file mode 100644
index 0000000..da0acf0
--- /dev/null
+++ b/decomp/Makefile
@@ -0,0 +1,83 @@
+# Makefile for decomp - a decompiler
+#
+# Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+
+SHELL = /bin/bash
+CC = gcc
+CFLAGS = -g -Wall -O2
+
+CORESOURCE = decomp.c data.c code.c fileinfo.c symtab.c memory.c hash.c error.c
+FILESOURCE = elf.c dos.c
+ARCHSOURCE = ia32.c alpha.c
+SOURCES = $(CORESOURCE) $(FILESOURCE) $(ARCHSOURCE)
+
+EXE = decomp
+
+DOCSOURCE = decomp.texinfo
+TEXI2DVI = texi2dvi
+DVIPS = dvips
+TEXI2HTML = texi2html -monolithic
+DOCEXTRAS = *.aux *.cp *.dvi *.fn *.ky *.log *.pg *.toc *.tp *.vr *.ps
+MEMTESTFILES = memtest.c memory.c error.c
+HASHTESTFILES = hashtest.c hash.c error.c
+
+
+.PHONY : all dist clean doc ps info html install installdoc help test
+
+all : $(EXE)
+
+dist : clean
+ (cd ..; tar -c decomp | gzip -c > decomp-0.0.tar.gz)
+
+help :
+ @echo Valid targets are
+ @echo - all: make the executable file
+ @echo - install: install the executable file
+ @echo - clean: remove any generated files
+ @echo - doc: create all of the documentation
+ @echo - ps: create the Postscript documentation
+ @echo - html: create the HTML documentation
+ @echo - info: create the Texinfo documentation
+ @echo - installdoc: install the HTML and Texinfo documentation
+ @echo - help: print this message
+ @echo - test: run the testsuite
+
+
+$(EXE) : $(SOURCES:.c=.o)
+
+doc : ps info html
+
+ps : $(DOCSOURCE:.texinfo=.ps)
+
+$(DOCSOURCE:.texinfo=.ps) : $(DOCSOURCE:.texinfo=.dvi)
+ $(DVIPS) -o $@ $<
+
+$(DOCSOURCE:.texinfo=.dvi) : $(DOCSOURCE)
+ $(TEXI2DVI) $<
+
+info : $(DOCSOURCE:.texinfo=.info)
+
+$(DOCSOURCE:.texinfo=.info) : $(DOCSOURCE)
+ $(MAKEINFO) $<
+
+html : $(DOCSOURCE:.texinfo=.html)
+
+$(DOCSOURCE:.texinfo=.html) : $(DOCSOURCE)
+ $(TEXI2HTML) $<
+
+install : $(EXE)
+ @echo Not much here yet...
+installdoc : info html
+ @echo Not much here yet...
+
+clean :
+ rm -f *.o *~ $(EXE) memtest hashtest *.info *.html $(DOCEXTRAS)
+
+test :
+ touch test/.runtest
+ make -C test
+
+memtest : $(MEMTESTFILES:.c=.o)
+
+hashtest : LDFLAGS = -lreadline -lhistory -ltermcap
+hashtest : $(HASHTESTFILES:.c=.o)
diff --git a/decomp/README b/decomp/README
new file mode 100644
index 0000000..c799f1a
--- /dev/null
+++ b/decomp/README
@@ -0,0 +1,4 @@
+A decompiler. This isn't complete yet, but it satisfactorily
+decompiles Linux ELF32/64 binaries as well as MS PE files (Windows
+.exe/.scr files) on the Intel IA-32 (x86). Beta support for MS NE (New
+Executable - Win16 .exe).
diff --git a/decomp/alpha.c b/decomp/alpha.c
new file mode 100644
index 0000000..9b0dfb3
--- /dev/null
+++ b/decomp/alpha.c
@@ -0,0 +1,22 @@
+/* alpha.c
+ * This file is part of Decomp - a disassembler. This file contains
+ * routines for disassembling instructions for the AXP Alpha architecture.
+ *
+ * Copyright (C) 2002 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started on 24 Feb 2002
+ */
+
+#include "decomp.h"
+
+char not_implemented[] = "Alpha routine not implemented";
+
+char *
+alpha_disassemble_instruction (unsigned char *text, unsigned long *pos,
+ unsigned long flags, unsigned long vaddr,
+ hash_t symtab)
+{
+ *pos += 4;
+
+ return not_implemented;
+}
diff --git a/decomp/code.c b/decomp/code.c
new file mode 100644
index 0000000..b75706c
--- /dev/null
+++ b/decomp/code.c
@@ -0,0 +1,247 @@
+/* code.c
+ * This file is part of Decomp - a decompiler. This is the main code
+ * decompilation routine.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started around 1 December 2001.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "decomp.h"
+
+
+#define TAB_STOP 8
+#define COMMENT_COLUMN 48
+
+
+struct output_queue {
+ struct output_queue *next;
+ unsigned long vaddr;
+ char *instruction;
+ char *opcode;
+};
+
+
+struct output_queue *output_queue = NULL;
+unsigned long items_in_queue = 0;
+unsigned long max_queue_size = MAX_OUTPUT_QUEUE_SIZE;
+
+
+/* count_length
+ * Count the number of characters a line will take up.
+ */
+int
+count_length (char *line)
+{
+ char *tmp;
+ int tab_stop = TAB_STOP, count = 0, current = -1;
+
+ while ((tmp = strchr (line, '\n')) != NULL) line = tmp + 1;
+
+ while (line[++current])
+ {
+ if (line[current] == '\t')
+ while (++count % tab_stop);
+ else
+ count++;
+ }
+
+ return count;
+}
+
+
+/* print_queue_head
+ * Print the instruction at the head of the instruction queue with
+ * its label, if any.
+ */
+void
+print_queue_head (hash_t symtab, FILE *ofp)
+{
+ int len, k, comment_column = COMMENT_COLUMN, tab_stop = TAB_STOP;
+ char *line;
+ struct symtab *sym;
+ struct output_queue *tmp;
+
+ tmp = output_queue;
+ output_queue = output_queue->next;
+ items_in_queue--;
+
+ line = tmp->instruction;
+
+ sym = hash_get (symtab, tmp->vaddr);
+
+ /* if there is a symbol at this virtual address */
+ if (sym != NULL)
+ {
+ fprintf (ofp, "\n");
+
+ /* if it's global, mark it as such */
+ if (sym->type == GLOBAL_FUNCTION || sym->type == GLOBAL_UNKNOWN)
+ fprintf (ofp, "\t.global\t%s\n", sym->name);
+
+ /* if it's a function, say so */
+ if (sym->type == GLOBAL_FUNCTION || sym->type == LOCAL_FUNCTION
+ || sym->type == UNKNOWN_FUNCTION)
+ fprintf (ofp, "\t.type\t%s,@function\n", sym->name);
+
+ if (sym->size != 0) fprintf (ofp, "\t.size\t%s, %ld\n", sym->name,
+ sym->size);
+
+ fprintf (ofp, "%s:\n", sym->name);
+ }
+
+
+ fprintf (ofp, "%s", line);
+
+ if (print_address || print_opcode)
+ {
+ len = count_length (line);
+
+ if (len < comment_column - tab_stop)
+ for (k = 0;
+ k < (((comment_column - tab_stop) - (len - len % tab_stop))
+ / tab_stop);
+ k++)
+ fputc ('\t', ofp);
+
+ fprintf (ofp, "\t;");
+ }
+
+ if (print_address)
+ fprintf (ofp, " %08lx", tmp->vaddr);
+
+ if (print_opcode)
+ {
+ fputc (' ', ofp);
+
+ for (k = 1; k < tmp->opcode[0] + 1; k++)
+ fprintf (ofp, "%02hhx", tmp->opcode[k]);
+
+ xfree (tmp->opcode);
+ }
+
+ fprintf (ofp, "\n");
+
+
+ xfree (line);
+ xfree (tmp);
+}
+
+
+/* output_line
+ * Queue an output line, printing the line at the head of the queue
+ * if the queue is full.
+ */
+void
+output_line (hash_t symtab, FILE *ofp, char *line, unsigned long vaddr,
+ char *opcode)
+{
+ struct output_queue *new, *tmp;
+
+ new = xmalloc (sizeof (struct output_queue));
+
+ new->next = NULL;
+ new->vaddr = vaddr;
+ new->instruction = xmalloc (strlen (line) + 1);
+ strcpy (new->instruction, line);
+ new->opcode = opcode;
+
+ /* if the queue is full, output one line */
+ if (items_in_queue >= max_queue_size)
+ print_queue_head (symtab, ofp);
+
+
+ /* find the end of the output queue */
+ if (output_queue == NULL)
+ output_queue = new;
+ else
+ {
+ tmp = output_queue;
+ while (tmp->next != NULL) tmp = tmp->next;
+
+ tmp->next = new;
+ }
+
+ items_in_queue++;
+}
+
+/* flush_output_queue
+ * Print all lines remaining in the output queue.
+ */
+void
+flush_output_queue (hash_t symtab, FILE *ofp)
+{
+ while (output_queue != NULL) print_queue_head (symtab, ofp);
+}
+
+
+/* decode_code_section
+ * Disassemble a code section from the input file.
+ */
+void
+decode_code_section (struct file_info *fi, struct section_info *s,
+ hash_t symtab, FILE *ofp)
+{
+ char *text, *line = NULL, *opcode = NULL;
+ unsigned long old_pos = 0, pos = 0, flags = 0, vaddr;
+
+ /* set flags */
+ switch (fi->arch)
+ {
+ case MT_IA32:
+ flags |= (fi->bit_size == BS_32) ? (F_IA32_A | F_IA32_D) : 0x0;
+ flags |= (print_prefix) ? F_IA32_P : 0x0;
+ break;
+ case MT_ALPHA:
+ /* nothing here yet */
+ default:
+ ;
+ }
+
+ fseek (fi->fp, s->section_offset, SEEK_SET);
+ text = xmalloc (s->section_size);
+ fread (text, 1, s->section_size, fi->fp);
+
+ fprintf (ofp, "\n\t.section\t%s%s, @progbits\n\t.align\t%d\n\n",
+ s->section_name, s->flags, s->align);
+
+ vaddr = s->load_address;
+
+ while (pos < s->section_size)
+ {
+ switch (fi->arch)
+ {
+ case MT_IA32:
+ line = ia32_disassemble_instruction (text, &pos, flags, vaddr,
+ symtab);
+ break;
+ case MT_ALPHA:
+ line = alpha_disassemble_instruction (text, &pos, flags, vaddr,
+ symtab);
+ break;
+ default:
+ ;
+ }
+
+ if (print_opcode)
+ {
+ opcode = xmalloc (pos - old_pos + 1);
+ opcode[0] = pos - old_pos;
+ memcpy (opcode + 1, text + old_pos, opcode[0]);
+ }
+
+ output_line (symtab, ofp, line, vaddr, opcode);
+
+ xfree (line);
+
+ vaddr += pos - old_pos;
+ old_pos = pos;
+ }
+
+ flush_output_queue (symtab, ofp);
+
+ xfree (text);
+}
diff --git a/decomp/data.c b/decomp/data.c
new file mode 100644
index 0000000..034a688
--- /dev/null
+++ b/decomp/data.c
@@ -0,0 +1,245 @@
+/* data.c
+ * This file is part of Decomp - a decompiler. In this file are
+ * routines for disassembling data sections from an object file.
+ *
+ * Copyright (C) 2001, Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started around 1 December 2001.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <ctype.h>
+
+#include "decomp.h"
+
+
+/* Whether or not to align the datum size. */
+int unalign;
+
+
+/* find_size
+ * Guess the size of the datum at OFFSET.
+ */
+unsigned long
+find_size (hash_t symtab, char *data, unsigned long base,
+ unsigned long offset, unsigned long limit)
+{
+ unsigned long seek;
+
+ /* check for a zero byte or for another symbol */
+ for (seek = offset + 1; data[seek]; seek++) {
+ if (hash_get (symtab, base + seek) != NULL) { unalign = 1; break; }
+ }
+
+ return seek - offset;
+}
+
+
+/* check_is_string
+ * Determine if STR, which is LEN bytes long, is a string or not, using
+ * a heuristic.
+ */
+int
+check_is_string (char *str, unsigned long len)
+{
+ unsigned long k = -1;
+
+ if (len < 2) return 0;
+
+ if (str[len - 1] != '\0' && str[len] != '\0') return 0;
+
+ while (++k < len - 1) if (!isgraph (str[k]) && !isspace (str[k])) return 0;
+
+ return 1;
+}
+
+/* escape_string
+ * Convert chars that need escaping into an escape. The returned string
+ * must be freed.
+ */
+char *
+escape_string (char *str)
+{
+ unsigned long k, o;
+ char *esc;
+
+ /* allocate a lot */
+ esc = xmalloc (strlen (str) * 2 + 1);
+
+ for (k = 0, o = 0; k < strlen (str); k++)
+ switch (str[k])
+ {
+ case '\f':
+ esc[o++] = '\\';
+ esc[o++] = 'f';
+ break;
+ case '\n':
+ esc[o++] = '\\';
+ esc[o++] = 'n';
+ break;
+ case '\r':
+ esc[o++] = '\\';
+ esc[o++] = 'r';
+ break;
+ case '\t':
+ esc[o++] = '\\';
+ esc[o++] = 't';
+ break;
+ case '\v':
+ esc[o++] = '\\';
+ esc[o++] = 'v';
+ break;
+ case '"':
+ esc[o++] = '\\';
+ esc[o++] = '"';
+ break;
+ case '\\':
+ esc[o++] = '\\';
+ esc[o++] = '\\';
+ break;
+ default:
+ esc[o++] = str[k];
+ break;
+ }
+
+ return esc;
+}
+
+/* print_symbol
+ * Print the named object at VADDR.
+ */
+void
+print_symbol (hash_t symtab, struct symtab *sym, unsigned long load_addr,
+ unsigned long *offset, unsigned long limit,
+ unsigned long align, char *data, FILE *ofp)
+{
+ unsigned long k, size;
+ char *buff;
+
+ unalign = 0;
+
+ if (sym->size == 0)
+ size = find_size (symtab, data, load_addr, *offset, limit);
+ else
+ size = sym->size;
+
+ /* double check the size */
+ if (size == 0) /* rare but possible */
+ size = align;
+
+ buff = xmalloc (size);
+ memcpy (buff, data + *offset, size);
+
+/* fprintf (ofp, "\t.size\t%ld\n", size); */
+
+ if (check_is_string (buff, size))
+ {
+ char *esc = escape_string (buff);
+
+ fprintf (ofp, "\t.string\t\"%s\"", esc);
+
+ xfree (esc);
+ }
+ else
+ {
+ /* if we guessed the size, it's not a string and there isn't a symbol
+ immediately after, round up to align */
+ if (sym->size == 0 && !unalign) while (size % align) size++;
+
+ switch (size)
+ {
+ case 1:
+ fprintf (ofp, "\t.byte\t%#x", *buff);
+ break;
+ case 2:
+ fprintf (ofp, "\t.hword\t%#hx", *(uint16_t *)buff);
+ break;
+ case 4:
+ fprintf (ofp, "\t.int\t%#x", *(uint32_t *)buff);
+ break;
+ case 8:
+ fprintf (ofp, "\t.quad\t%#llx", *(uint64_t *)buff);
+ break;
+ default:
+ for (k = 0; k < size; k++)
+ {
+ if (!(k % 8)) fprintf (ofp, "\n\t.byte\t0x%02hhx", buff[k]);
+ else fprintf (ofp, ", 0x%02hhx", buff[k]);
+ }
+ }
+ }
+
+ fputc ('\n', ofp);
+
+ xfree (buff);
+
+ *offset += size;
+}
+
+/* decode_data_section
+ * Disassemble a data section into named and unnamed chunks of data.
+ */
+void
+decode_data_section (struct file_info *fi, struct section_info *s,
+ hash_t symtab, FILE *ofp)
+{
+ int need_to_print_header = 1;
+ unsigned long offset = 0;
+ struct symtab *sym;
+ char *data;
+
+ data = xmalloc (s->section_size);
+ fseek (fi->fp, s->section_offset, SEEK_SET);
+ if (fread (data, sizeof (char), s->section_size, fi->fp) < s->section_size)
+ error_out (ERR_READ_SECTION);
+
+
+ fprintf (ofp, "\n\n\t.section\t%s%s\n\t.align\t%d\n", s->section_name,
+ s->flags, s->align);
+
+ for (offset = 0; offset < s->section_size;)
+ {
+ sym = hash_get (symtab, s->load_address + offset);
+
+ if (sym != NULL)
+ {
+ fputc ('\n', ofp);
+
+ /* if this sym is global, mark it */
+ if (sym->type == GLOBAL_DATA || sym->type == GLOBAL_UNKNOWN)
+ fprintf (ofp, "\n\t.global\t%s", sym->name);
+
+ /* if it's data, say so */
+ if (sym->type == GLOBAL_DATA || sym->type == LOCAL_DATA
+ || sym->type == UNKNOWN_DATA)
+ fprintf (ofp, "\n\t.type\t%s,@object", sym->name);
+
+ if (sym->size != 0) fprintf (ofp, "\n\t.size\t%s, %ld", sym->name,
+ sym->size);
+
+ fprintf (ofp, "\n%s:", sym->name);
+ print_symbol (symtab, sym, s->load_address, &offset, s->section_size,
+ s->align, data, ofp);
+
+ /* skip to next aligned address */
+ /* this doesn't seem to be a good idea - not sure why */
+ /* maybe it's because data isn't always aligned in the object file */
+/* while ((s->load_address + offset) % s->align) offset++; */
+ need_to_print_header = 1;
+ }
+ else /* no data - just print out the section contents */
+ {
+ char byte = data[offset++];
+
+ if (!((s->load_address + offset) % 8) || need_to_print_header)
+ {
+ fprintf (ofp, "\n\t.byte\t0x%02hhx", byte);
+ need_to_print_header = 0;
+ }
+ else
+ fprintf (ofp, ", 0x%02hhx", byte);
+ }
+ }
+}
diff --git a/decomp/decomp.c b/decomp/decomp.c
new file mode 100644
index 0000000..0793526
--- /dev/null
+++ b/decomp/decomp.c
@@ -0,0 +1,312 @@
+/* decomp.c
+ * Decompile an executable file.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started around 15 November 2001.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdint.h>
+
+/*#include <signal.h>*/
+
+#include "decomp.h"
+
+
+char pname[] = PACKAGE_NAME;
+char version[] = PACKAGE_VERSION;
+char author[] = AUTHOR;
+char author_email[] = AUTHOR_EMAIL;
+
+
+int debug = 0;
+int print_address = 0;
+int print_opcode = 0;
+int print_prefix = 0;
+enum syntax syntax = INTEL;
+int host_endian = ELITTLE, target_endian = ELITTLE; /* handy default */
+
+void
+write_file_header (FILE *fp, const char *source_file, const char *file_name)
+{
+ fprintf (fp,
+ "\t; %s\n"
+ "\t; Decompiled by Decomp from %s.\n"
+ "\t; In case of an incorrect decompilation, let the author know.\n"
+ "\n",
+ file_name, source_file);
+}
+
+
+/* get_output_name
+ * Called when an output file has not been specified with -o. Appends
+ * DEFAULT_OUTPUT_EXTENSION on to the file name of the object file. The
+ * returned memory must be freed.
+ */
+char *
+get_output_name (const char *file_name)
+{
+ char *output_name;
+ char output_extension[] = DEFAULT_OUTPUT_EXTENSION;
+
+ output_name = xmalloc (strlen (file_name) + strlen (output_extension) + 1);
+
+ sprintf (output_name, "%s%s", file_name, output_extension);
+
+ return (output_name);
+}
+
+
+/* byte_reverse
+ * Convert from big to little endian and vice-versa.
+ */
+void
+byte_reverse (void *ptr, size_t size, size_t nmemb)
+{
+ uint8_t *buf = (uint8_t *)ptr;
+
+ if (size == 1 || nmemb == 0) return;
+
+ do
+ {
+ register size_t low = 0, high = size - 1;
+
+ while (high > low)
+ {
+ register uint8_t tmp;
+
+ tmp = buf[low];
+ buf[low] = buf[high];
+ buf[high] = tmp;
+
+ high--; low++;
+ }
+
+ buf += size;
+ }
+ while (--nmemb);
+}
+
+
+/* d_read
+ * Similar in functionality to fread, except ensures that > 0 bytes are
+ * read and accounts for byte order.
+ */
+void
+d_read (void *ptr, size_t size, size_t nmemb, FILE *stream, int as_is)
+{
+ if (fread (ptr, size, nmemb, stream) <= 0) error_out (ERR_FILE_READ);
+
+ if (as_is) return;
+
+ /* if (host_endian .xor. target_endian) */
+ if ((host_endian || target_endian) - (host_endian && target_endian))
+ byte_reverse (ptr, size, nmemb);
+}
+
+
+int
+get_host_endian (void)
+{
+ union {
+ char c[4];
+ uint32_t i;
+ } x;
+
+ memset (&x, 0, 4); /* just to be sure */
+
+ x.i = 1;
+
+ if (x.c[0] != 0) return ELITTLE;
+ else return EBIG;
+}
+
+
+void
+print_version (void)
+{
+ printf ("%s %s\n"
+ "Copyright (C) 2001 %s %s\n"
+ "%s comes with NO WARRANTY, to the extent\n"
+ "permitted by law. You may redistribute copies\n"
+ "of %s under the terms of the GNU General\n"
+ "Public License. For more information about\n"
+ "these matters, see the file named COPYING.\n",
+ pname, version, author, author_email, pname, pname);
+
+ exit (EXIT_SUCCESS);
+}
+
+void
+print_help (void)
+{
+ printf ("Usage: decomp [OPTION]... <FILE>\n"
+ "Decompile FILE into a complete assembly language file\n"
+ "which can in turn be re-assembled.\n"
+ "\n"
+ " -o, --output <file> Place output in file. The default is\n"
+ " to append .S to the input file name.\n"
+ "\n"
+ " -h, --help Print this message.\n"
+ " -v, --version Print version information.\n"
+ "\n"
+ " -a, --address Print the address of each instruction.\n"
+ " -c, --opcode Print the opcode of each instruction.\n"
+ " -p, --prefix Print any instruction prefixes.\n"
+ "\n"
+ " -d, --debug Print debugging information.\n"
+ " -t, --trace Turn on memory tracing.\n"
+ "\n"
+ " -q, --queue-size <size> Adjust the size of the output\n"
+ " instruction queue. Only use this if\n"
+ " you know what you are doing.\n"
+ "IA-32 specific options:\n"
+ " -s, --style <nasm|gas> Select assembly language style.\n"
+ " Not yet implemented.\n"
+ "\n"
+ "Report bugs to %s %s\n",
+ author, author_email);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int k;
+ char opt, *output_file_name = NULL;
+ struct file_info fi;
+ hash_t symtab;
+ FILE *ofp;
+ struct option options[] = {
+ { "address", no_argument, NULL, 'a' },
+ { "debug", no_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ { "opcode", no_argument, NULL, 'c' },
+ { "output", required_argument, NULL, 'o' },
+ { "prefix", no_argument, NULL, 'p' },
+ { "queue-size", required_argument, NULL, 'q' },
+ { "style", required_argument, NULL, 's' },
+ { "trace", no_argument, NULL, 't' },
+ { "version", no_argument, NULL, 'v' },
+ { 0, 0, 0, 0 }
+ };
+
+
+ /* parse through argv, looking for options */
+ while (1)
+ {
+ opt = getopt_long (argc, argv, "acdho:pq:s:tv", options, NULL);
+
+ if (opt == EOF) break;
+
+ switch (opt)
+ {
+ case 'a':
+ print_address = 1;
+ break;
+ case 'c':
+ print_opcode = 1;
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case 'h':
+ print_help ();
+ exit (EXIT_SUCCESS);
+ case 'o':
+ output_file_name = optarg;
+ break;
+ case 'p':
+ print_prefix = 1;
+ break;
+ case 'q':
+ max_queue_size = strtol (optarg, NULL, 0);
+ if (max_queue_size < 1)
+ {
+ fprintf (stderr, "DECOMP: invalid queue size - using default\n");
+ max_queue_size = MAX_OUTPUT_QUEUE_SIZE;
+ }
+ break;
+ case 's':
+ if (!strcmp (optarg, "att"))
+ syntax = ATT;
+ else if (!strcmp (optarg, "intel"))
+ syntax = INTEL;
+ else
+ {
+ fprintf (stderr, "DECOMP: unknown disassembly syntax `%s'\n",
+ optarg);
+ exit (1);
+ }
+ break;
+ case 't':
+ memory_trace = 1;
+ break;
+ case 'v':
+ print_version ();
+ exit (EXIT_SUCCESS);
+ case '?':
+ fprintf (stderr, "DECOMP: unknown option character `%c'\n", optopt);
+ exit (EXIT_FAILURE);
+ default:
+ fprintf (stderr,
+ "DECOMP: ?? getopt returned character code 0x%x (%c) ??\n",
+ opt, opt);
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ /* all that's left in argv should be a file name to disassemble */
+ if (argv[optind] == NULL) error_out (ERR_NEED_FILE_NAME);
+
+
+ /* get host endian-ness and set target as the same for now */
+ target_endian = host_endian = get_host_endian ();
+
+
+ /* open_files (); */
+ /* get_file_info (); */
+ if (get_file_info (&fi, argv[optind])) error_out (ERR_FILE_INFO);
+
+ /* write_asm_header (); */
+ if (output_file_name == NULL)
+ output_file_name = get_output_name (argv[optind]);
+
+ ofp = fopen (output_file_name, "wt");
+ if (ofp == NULL) error_out (ERR_FILE_OPEN);
+
+ if (debug)
+ setvbuf (ofp, NULL, _IONBF, 0);
+
+ write_file_header (ofp, argv[optind], output_file_name);
+
+ /* read the symtab */
+ symtab = read_symtab (&fi);
+
+ /* decode and write out the code sections */
+ k = -1;
+ while (fi.code_sections[++k])
+ decode_code_section (&fi, fi.code_sections[k], symtab, ofp);
+
+ /* decode and write out the data sections */
+ k = -1;
+ while (fi.data_sections[++k])
+ decode_data_section (&fi, fi.data_sections[k], symtab, ofp);
+
+
+ /* write_asm_footer (); */
+
+
+ /* clean up */
+ clean_symtab (symtab);
+ fclose (ofp);
+ if (clean_up_file (&fi)) error_out (ERR_CLEAN_UP);
+ free_all ();
+
+ return (0);
+}
diff --git a/decomp/decomp.h b/decomp/decomp.h
new file mode 100644
index 0000000..0057fd3
--- /dev/null
+++ b/decomp/decomp.h
@@ -0,0 +1,289 @@
+/* decomp.h
+ * This file is part of decomp - a disassembler.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ */
+
+#ifndef DECOMP_H
+#define DECOMP_H
+
+#include <stdio.h>
+
+/* something really bad just happened and it's time to bail */
+#define PANIC panic (__LINE__, __FILE__)
+
+/* some kind of error */
+#define error_out(index) error_out_internal ((index), __LINE__, __FILE__)
+
+
+/* used for debugging */
+#define PRINT_OK fprintf (stderr, "ok at %d in %s\n", __LINE__, __FILE__)
+
+
+#define PACKAGE_NAME "Decomp"
+#define PACKAGE_VERSION "0.0"
+#define AUTHOR "Jonathan duSaint"
+#define AUTHOR_EMAIL "<dusaint@earthlink.net>"
+
+#define DEFAULT_OUTPUT_EXTENSION "_decomp.S"
+
+/* an invalid hash key */
+#define HASH_END (-1UL)
+
+/* the maximum output buffer size - this should be sufficiently large
+ so that backwards jump destinations will be properly labeled with
+ temporary labels */
+#define MAX_OUTPUT_QUEUE_SIZE 512
+
+
+/* flags for use with the FLAGS variable passed to the disassembly routines */
+#define F_IA32_A (1UL << 0) /* addressing mode 16/32 */
+#define F_IA32_D (1UL << 1) /* data mode 16/32 */
+#define F_IA32_P (1UL << 2) /* print instruction prefix comments */
+
+
+/* endian-ness used for the read routines */
+#define ELITTLE 0
+#define EBIG 1
+
+
+/* indices into the message table */
+enum message_table_index {
+ ERR_INTERNAL_ERROR = 0, ERR_NEED_FILE_NAME, ERR_FILE_INFO, ERR_CLEAN_UP,
+ ERR_FILE_OPEN, ERR_FILE_READ, ERR_INVALID_FILE, ERR_FILE_TYPE,
+ ERR_READ_SECTION
+};
+
+
+/* hash table stuff */
+struct hash_bucket {
+ struct hash_bucket *next;
+ unsigned long key;
+ void *data;
+};
+
+struct hash_table {
+ struct hash_bucket **table;
+ unsigned long size;
+ unsigned long items;
+};
+
+typedef struct hash_table *hash_t;
+
+
+/* type of file */
+enum file_type {
+ FT_ELF, /* ELF32/64 */
+ FT_AOUT, /* a.out - this isn't used for now */
+ FT_PE, /* Win32 Portable Executable */
+ FT_NE, /* Win16 New Executable */
+ FT_MZ, /* Legacy DOS Executable */
+ FT_COM, /* Legacy DOS COM - this isn't used for now */
+ FT_UNK /* huh??? - maybe someday I'll add more file types */
+};
+
+/* type of machine */
+enum mach_type {
+ MT_IA32, /* aka x86/i386/... */
+ MT_ALPHA, /* DEC Alpha */
+ MT_UNK /* huh??? - maybe someday I'll add more architectures */
+};
+
+
+/* the data/code wordsize */
+enum bs {
+ BS_16, /* 16 bit code/machine */
+ BS_32, /* 32 bit code/machine */
+ BS_64, /* 64 bit code/machine */
+ BS_UNK
+};
+
+/* the byte order */
+enum bo {
+ BO_LITTLE_ENDIAN, BO_BIG_ENDIAN
+};
+
+/* the type of a section (as concerns decomp) */
+enum section_type {
+ CODE_SECTION, DATA_SECTION, HASH_SECTION, STRING_SECTION, OTHER_SECTION
+};
+
+
+/* information about a section */
+struct section_info {
+ /* the name of the section from .shstrtab */
+ char *section_name;
+ /* the type of this section */
+ enum section_type section_type;
+ /* offset in the file of this section */
+ unsigned long section_offset;
+ /* the section's size */
+ unsigned long section_size;
+ /* the size of an entry (used for the symtab) */
+ unsigned long entsize;
+ /* internal section index */
+ unsigned long section_index;
+ /* virtual load address of this section */
+ unsigned long load_address;
+ /* the hash table for this section's symbols */
+ hash_t symtab;
+ /* a string describing any section flags */
+ char *flags;
+ /* the alignment of the section */
+ unsigned int align;
+};
+
+
+/* all of the relevant information about the file to be disassembled */
+struct file_info {
+ /* the name of the file as passed to decomp - prob read-only */
+ char *file_name;
+ /* the size as returned from fstat */
+ unsigned long file_size;
+ /* the "bit size" of the object file - 16, 32, or 64 */
+ enum bs bit_size;
+ /* the machine */
+ enum mach_type arch;
+ /* object file type */
+ enum file_type file_type;
+ /* the machine/file byte order */
+ enum bo endian;
+ /* the file descriptor */
+ FILE *fp;
+ /* the virtual load address */
+ unsigned long load_address;
+ /* a NULL terminated array of data sections */
+ struct section_info **data_sections;
+ /* a NULL terminated array of code sections */
+ struct section_info **code_sections;
+ /* every other section */
+ struct section_info **other_sections;
+ /* the .symtab section */
+ struct section_info *symtab;
+ /* the .strtab section. */
+ struct section_info *strtab;
+};
+
+
+/* do not reorder these */
+enum symbol_type {
+ LOCAL_DATA, GLOBAL_DATA, LOCAL_FUNCTION, GLOBAL_FUNCTION,
+ LOCAL_UNKNOWN, GLOBAL_UNKNOWN, UNKNOWN_DATA, UNKNOWN_FUNCTION,
+ UNKNOWN_SYMBOL
+};
+
+struct symtab {
+ char *name;
+ unsigned long address;
+ unsigned long size;
+ unsigned long idx;
+ enum symbol_type type;
+};
+
+enum syntax {
+ ATT, INTEL
+};
+
+
+/* overall control over AT&T or Intel style disassembly */
+extern enum syntax syntax;
+
+
+extern volatile int memory_trace;
+extern int print_address;
+extern int print_opcode;
+extern int print_prefix;
+extern int debug;
+extern unsigned long max_queue_size;
+extern int host_endian, target_endian;
+
+extern char pname[];
+extern char version[];
+
+
+/* decomp.c */
+void d_read (void *ptr, size_t size, size_t nmemb, FILE *stream, int as_is);
+
+/* error.c */
+void panic (long line, char *file) __attribute__ ((noreturn));
+void error_out_internal (int index, long ling,
+ char *file) __attribute__ ((noreturn));
+
+/* memory.c */
+void *xmalloc (size_t amount);
+void xfree (void *mem);
+void free_all (void);
+void mem_trace (void);
+
+/* fileinfo.c */
+int get_file_info (struct file_info *fi, const char *file);
+int clean_up_file (struct file_info *fi);
+struct section_info *alloc_section_info (char *name, enum section_type type,
+ unsigned long offset,
+ unsigned long size,
+ unsigned long entsize,
+ unsigned long index,
+ unsigned long addr, hash_t symtab,
+ char *flags, unsigned int align);
+
+/* symtab.c */
+char *create_hash_key_from_addr (unsigned long addr);
+hash_t read_symtab (struct file_info *fi);
+void clean_symtab (hash_t symtab);
+void put_data_limits (unsigned long low, unsigned long high);
+int check_is_data (unsigned long vaddr);
+struct symtab *create_jump_ref (hash_t symtab, unsigned long vaddr);
+struct symtab *create_data_ref (hash_t symtab, unsigned long vaddr);
+
+/* hash.c */
+hash_t hash_new (unsigned long size);
+double hash_goodness (hash_t table);
+int hash_add (hash_t table, unsigned long key, void *data);
+void *hash_get (hash_t table, unsigned long key);
+void *hash_remove (hash_t table, unsigned long key);
+void hash_delete (hash_t table);
+hash_t hash_rehash (hash_t table, unsigned long size);
+unsigned long hash_walk (hash_t table);
+void hash_print (hash_t table);
+
+/* data.c */
+void decode_data_section (struct file_info *fi, struct section_info *s,
+ hash_t symtab, FILE *ofp);
+
+/* code.c */
+void decode_code_section (struct file_info *fi, struct section_info *s,
+ hash_t symtab, FILE *ofp);
+
+/* files dealing with file types */
+
+/* elf.c */
+void elf_get_file_info (struct file_info *fi);
+char *elf_read_strtab (struct file_info *fi);
+struct symtab *elf_get_next_symbol (struct file_info *fi, char *strtab);
+
+/* dos.c */
+void mz_get_file_info (struct file_info *fi);
+char *mz_read_strtab (struct file_info *fi);
+struct symtab *mz_get_next_symbol (struct file_info *fi, char *strtab);
+
+void ne_get_file_info (struct file_info *fi);
+char *ne_read_strtab (struct file_info *fi);
+struct symtab *ne_get_next_symbol (struct file_info *fi, char *strtab);
+
+void pe_get_file_info (struct file_info *fi);
+char *pe_read_strtab (struct file_info *fi);
+struct symtab *pe_get_next_symbol (struct file_info *fi, char *strtab);
+
+
+/* ia32.c */
+char *ia32_disassemble_instruction (unsigned char *text, unsigned long *pos,
+ unsigned long flags, unsigned long vaddr,
+ hash_t symtab);
+
+/* alpha.c */
+char *alpha_disassemble_instruction (unsigned char *text, unsigned long *pos,
+ unsigned long flags, unsigned long vaddr,
+ hash_t symtab);
+
+
+#endif /* DECOMP_H */
diff --git a/decomp/decomp.texinfo b/decomp/decomp.texinfo
new file mode 100644
index 0000000..7f92eea
--- /dev/null
+++ b/decomp/decomp.texinfo
@@ -0,0 +1,611 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename decomp.info
+@settitle Decomp
+@c %**end of header
+
+@c put in the purty style sheet
+@ifhtml
+<style type="text/css">
+<!--
+a
+{
+ color: blue;
+ text-decoration: none;
+}
+a:active
+{
+ color: red;
+}
+a:hover
+{
+ color: white;
+}
+
+body
+{
+ background-color: black;
+ color: white;
+}
+--></style>
+@end ifhtml
+
+
+@setchapternewpage odd
+
+
+@ifinfo
+Decomp is a decompiler for the x86 architecture.
+
+Copyright @copyright{} 2001 Jonathan duSaint @email{dusaint@@earthlink.net}
+
+Permission is granted to make and distribute verbatim copies of this
+document provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified version of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified version,
+except that this permission notice may be stated in a translation
+approved by the author.
+@end ifinfo
+
+
+@c title page cruft
+@titlepage
+@title Decomp
+@author Jonathan duSaint @email{dusaint@@earthlink.net}
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 2001 Jonathan duSaint @email{dusaint@@earthlink.net}
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified version of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified version,
+except that this permission notice may be stated in a translation
+approved by the author.
+@end titlepage
+
+
+@node Top, Overview, , (dir)
+@top
+
+Decomp is a decompiler which aims to be able to disassemble any
+executable file in any format on any machine into an assembly language
+file. It's current state falls somewhat short of that goal, but
+the sky's the limit.
+
+@menu
+* Overview:: Decomp for the impatient
+* Options:: Controlling Decomp
+* Extending:: Adding new architectures and object file formats
+* Copying:: Your rights
+* Concept Index:: Key concepts
+@end menu
+
+
+@node Overview
+@chapter Overview
+
+Decomp is a decompiler. It can be used to convert an object file into a
+assembly language source file. The assembly language source file can
+then, in turn, be recompiled using an assembler and linked with any
+appropriate libraries to recreate the original executable (or something
+functionally identical).
+
+To use Decomp, you need merely invoke it with the name of an object
+file. For example, assuming that @file{foo} is the name of an object
+file, execute the command @kbd{decomp foo}. The decompilation will be
+located in the file @file{foo_decomp.S}. A quick perusal of the
+decompilation will show that not only have the executable sections of
+the object file been disassembled, but also the data sections have been
+decompiled. The data may not be exactly like the original source data,
+but they should be functionally equivalent.
+
+
+@node Options
+@chapter Options
+
+There are a number of options to control the decompilation process and
+the output.
+
+@menu
+* Getting Help:: Help and version information.
+* Debugging:: Options which print debugging information.
+* Extra Information:: Printing extra information in the output file.
+* Run-time parameters:: Controlling how Decomp executes.
+@end menu
+
+
+@node Getting Help
+@section Getting Help
+
+There are two command line options which tell Decomp to print
+information and exit.
+
+@subsection @samp{-h, --help}
+
+Invoking Decomp with this option will cause it to print a short message
+explaining basic usage of the program and then exit.
+
+@subsection @samp{-v, --version}
+
+This option causes Decomp to print version and copyright information and
+exit.
+
+
+@node Debugging
+@section Debugging
+
+The following two commands tell Decomp to print out different types of
+debugging information. Beware, though, as a lot of information can be
+printed.
+
+@subsection @samp{-d, --debug}
+
+This option causes Decomp to print a lot of debugging information from
+all stages of decompilation. To explain the output, here is an example.
+
+This first block is a listing of the sections in the object
+file. The first field is the name, the next is the index in the file,
+and the last field is the offset in the file.
+
+@example
+read , idx 0, offset 0
+read .text, idx 0x1, offset 0x74
+read .data, idx 0x2, offset 0xb4
+read .sbss, idx 0x3, offset 0xbc
+read .bss, idx 0x4, offset 0xbc
+read .shstrtab, idx 0x5, offset 0xbc
+read .symtab, idx 0x6, offset 0x230
+read .strtab, idx 0x7, offset 0x320
+@end example
+
+
+The next block describes which sections are being used by Decomp and
+what they are being used for. Any sections under @samp{data:} will be
+decompiled as regular data. Any sections under @samp{code:} will be
+disassembled. Sections under @samp{symtab:} are used as the symbol
+table, and the names of the symbols in the symbol table are found in the
+sections listed under @samp{strtab:}. The fields may be interpreted as
+follows: The first field is the section name and its index. The next
+field is the section type as defined in @file{decomp.h}. The following
+field is the offset of the section in the object file, and the field
+after that is the size of the section in the object file. The last
+field is the virtual address of the start of the section at run time.
+
+@example
+data:
+ .data (0x2), 1, 0xb4, 0x7, 0x80490b4
+code:
+ .text (0x1), 0, 0x74, 0x3e, 0x8048074
+symtab:
+ .symtab (0x6), 4, 0x230, 0xf0, 0
+strtab:
+ .strtab (0x7), 3, 0x320, 0x36, 0
+@end example
+
+
+The last block of lines is the output from parsing the symbol table.
+The first field is the virtual address of the symbol at run time
+followed by the name of the symbol. The size of whatever the symbol
+refers to follows. If the size is specified as 0 (as it is here), that
+does not necessarily mean that the object has no size. It merely means
+that when the file was originally assembled, the object size was not
+specified. The @samp{info} and @samp{other} fields are the ELF32
+symbol information and other information fields, and the values are
+defined by the ELF32 standard. The last field is the index of the
+section where this symbol is located.
+
+
+@example
+0x80490b4:msg: size 0, info 00, other 00, idx 0x2
+0x7:len: size 0, info 00, other 00, idx 0xfff1
+0x804809b:print_message: size 0, info 00, other 00, idx 0x1
+0x8048074:_start: size 0, info 0x10, other 00, idx 0x1
+0x80490bb:__bss_start: size 0, info 0x11, other 00, idx 0xfff1
+0x80490bb:_edata: size 0, info 0x11, other 00, idx 0xfff1
+@end example
+
+
+@subsection @samp{-t, --trace}
+
+This option causes the memory allocation routines to print out
+information on every invocation. At the end of this information, a
+summary of memory usage is printed. An in-depth explanation of the
+memory allocation routine is beyond the scope of this manual. Those
+wishing more information are free to peruse the source file
+@file{memory.c}, which includes a lengthy discussion of the mechanism
+used and justification for its use.
+
+
+@node Extra Information
+@section Extra Information
+
+It is possible to include extra information in the output file in the
+form of comments after the assembly language statements. This
+information is of three types.
+
+@subsection @samp{-a, --address}
+
+This option causes the virtual address of each instruction to be printed
+as a commment on the same line as the instruction.
+
+
+@subsection @samp{-c, --opcode}
+
+This option causes the opcode of the instruction to be printed as a
+comment on the same line as the instruction, after the virtual address,
+if it is present.
+
+
+@subsection @samp{-p, --prefix}
+
+If an opcode prefix is used for this instruction, then this option will
+cause Decomp to print a comment on the line before the instruction
+explaining what the prefix does.
+
+
+@node Run-time parameters
+@section Run-time parameters
+
+A few run-time parameters may be adjusted to assist Decomp in
+decompilation.
+
+
+@subsection @samp{-q, --queue-size <size>}
+
+During the disassembly process, Decomp buffers lines which are to be
+output. This option controlls the size of the FIFO where they are
+held. The reason for this buffering is that when a local label is
+assembled, it is not preserved in the object file. When jump and call
+instructions are disassembled, a temporary label is created for them and
+inserted into the symbol table. However, if a jump or a call is to an
+earlier location in the object file, the label will never be output,
+causing a dangling jump. To prevent (or at least reduce) this, the
+output is buffered and the line with any label is output after
+@samp{<size>} lines have been disassembled. The default value is 512.
+This value should work under most circumstances. However, if a label is
+found to be missing, then this value should be increased until the label
+is output. The disadvantage of using a large value is that more memory
+is needed to hold the instruction and its corresponding data structure.
+
+
+@node Extending
+@chapter Extending
+
+It is entirely possible to add computer architectures and object file
+formats. However, at the moment it is about as easy as pulling teeth
+(your own). Hopefully soon, this will be alleviated.
+
+@menu
+* Adding Machines:: Adding new machine types to Decomp.
+* Adding File Formats:: Adding new executable file formats to Decomp.
+@end menu
+
+
+@node Adding Machines
+@section Adding Machines
+
+To add a machine type, create a separate file with the following function:
+
+@code{MACHINE_get_next_instruction (unsigned char *text,
+ unsigned long *pos,
+ unsigned long flags,
+ unsigned long vaddr,
+ hash_t symtab)}
+
+
+
+@node Adding File Formats
+@section Adding File Formats
+
+To add a file format, create a separate file with the following function:
+
+
+
+@node Copying
+@chapter Copying
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+@node Concept Index
+@unnumbered Concept Index
+
+@printindex cp
+
+@contents
+@bye
diff --git a/decomp/dos.c b/decomp/dos.c
new file mode 100644
index 0000000..3d2d6a7
--- /dev/null
+++ b/decomp/dos.c
@@ -0,0 +1,887 @@
+/* dos.c
+ * This file is part of Decomp - a disassembler. In this file are
+ * routines for handling various types of DOS/Win32 executable types
+ * i.e. PE, NE, MZ, and COM.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started early Feb 2002.
+ */
+
+
+/* not implemented yet */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "decomp.h"
+
+/* various defines for dos/win files */
+#include "dos.h"
+
+
+/* void */
+/* com_get_file_info (struct file_info *fi) */
+/* { */
+
+/* } */
+
+
+/* MZ (legacy DOS executable) section */
+void
+mz_get_file_info (struct file_info *fi)
+{
+
+}
+char *
+mz_read_strtab (struct file_info *fi)
+{
+ return NULL;
+}
+
+struct symtab *
+mz_get_next_symbol (struct file_info *fi, char *strtab)
+{
+ return NULL;
+}
+
+
+/* NE (Win16 New Executable) section */
+
+void
+read_ne_header (struct ne_file_header *nh, FILE *fp)
+{
+ d_read (nh->Signature, sizeof (char), 2, fp, 1);
+ d_read (&nh->LinkerMajorVersion, sizeof (BYTE), 1, fp, 0);
+ d_read (&nh->LinkerMinorVersion, sizeof (BYTE), 1, fp, 0);
+ d_read (&nh->EntryTableOffset, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->EntryTableSize, sizeof (WORD), 1, fp, 0);
+ d_read (nh->Reserved, sizeof (BYTE), 4, fp, 1);
+ d_read (&nh->Flags, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->AutoDataSegment, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->HeapSize, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->StackSize, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->CS, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->IP, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->SS, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->SP, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->SegmentTableEntries, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->ModuleRefTableEntries, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->NonresidentNameTableSize, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->SegmentTableOffset, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->ResourceTableOffset, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->ResidentNameTableOffset, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->ModuleReferenceTableOffset, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->ImportedNameTableOffset, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->NonresidentNameTableOffset, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->MovableEntryPoints, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->Alignment, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->ResourceSegments, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->OperatingSystem, sizeof (BYTE), 1, fp, 0);
+ d_read (&nh->AdditionalInformation, sizeof (BYTE), 1, fp, 0);
+ d_read (&nh->FastLoadSectorOffset, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->FastLoadSectorSize, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->Reserved1, sizeof (WORD), 1, fp, 0);
+ d_read (&nh->WindowsVersion, sizeof (WORD), 1, fp, 0);
+}
+
+void
+ne_read_segment_header (struct ne_segment_header *sh, FILE *fp)
+{
+ d_read (&sh->SegmentDataSectorOffset, sizeof (WORD), 1, fp, 0);
+ d_read (&sh->SegmentLength, sizeof (WORD), 1, fp, 0);
+ d_read (&sh->Flags, sizeof (WORD), 1, fp, 0);
+ d_read (&sh->AllocationSize, sizeof (WORD), 1, fp, 0);
+}
+
+void
+ne_get_file_info (struct file_info *fi)
+{
+ int k, n_code = 0, n_data = 0;
+ WORD ne_header_pos, sector_size;
+ DWORD addr;
+ struct ne_file_header nh;
+
+ fi->bit_size = BS_16;
+ fi->arch = MT_IA32;
+ fi->endian = BO_LITTLE_ENDIAN;
+
+
+ /* position at NE header */
+ fseek (fi->fp, NE_POS_HEADER_OFFSET, SEEK_SET);
+ d_read (&ne_header_pos, sizeof (WORD), 1, fi->fp, 0);
+ fseek (fi->fp, ne_header_pos, SEEK_SET);
+
+
+ read_ne_header (&nh, fi->fp);
+
+
+ addr = fi->load_address = NE_MAKE_REAL_ADDRESS (nh.CS, nh.IP);
+ sector_size = 1 << nh.Alignment;
+
+ fi->data_sections = xmalloc ((nh.SegmentTableEntries + 1)
+ * sizeof (struct section_info *));
+ fi->code_sections = xmalloc ((nh.SegmentTableEntries + 1)
+ * sizeof (struct section_info *));
+
+ fseek (fi->fp, ne_header_pos + nh.SegmentTableOffset, SEEK_SET);
+
+ for (k = 0; k < nh.SegmentTableEntries; k++)
+ {
+ char *section_name;
+ WORD segment_size, loaded_segment_size;
+ char *flags;
+ struct ne_segment_header sh;
+
+ ne_read_segment_header (&sh, fi->fp);
+
+ /* NE doesn't have section names, so we create an arbitrary name */
+ section_name = xmalloc (18);
+
+ segment_size = sh.SegmentLength ? sh.SegmentLength : 0xffff;
+ loaded_segment_size = sh.AllocationSize ? sh.AllocationSize : 0xffff;
+
+ flags = "";
+
+ if (NE_DATA_SEGMENT (sh.Flags))
+ {
+ snprintf (section_name, 18, ".dataSection%d", n_data);
+
+ if (debug)
+ printf ("read data segment, idx %#x, offset %#x, size %#x\n", k,
+ sh.SegmentDataSectorOffset * sector_size, segment_size);
+
+ fi->data_sections[n_data] = alloc_section_info (section_name,
+ DATA_SECTION,
+ sh.SegmentDataSectorOffset * sector_size,
+ segment_size,
+ 0, k, addr,
+ NULL, flags,
+ nh.Alignment);
+
+ put_data_limits (addr, addr + loaded_segment_size);
+ n_data++;
+ }
+ else if (NE_CODE_SEGMENT (sh.Flags))
+ {
+ snprintf (section_name, 18, ".codeSection%d", n_code);
+
+ if (debug)
+ printf ("read code segment, idx %#x, offset %#x, size %#x\n", k,
+ sh.SegmentDataSectorOffset * sector_size, segment_size);
+
+ fi->code_sections[n_code] = alloc_section_info (section_name,
+ CODE_SECTION,
+ sh.SegmentDataSectorOffset * sector_size,
+ segment_size,
+ 0, k, addr,
+ NULL, flags,
+ nh.Alignment);
+
+ n_code++;
+ }
+
+ /* guess start address of next section */
+ addr = ((addr >> nh.Alignment) + 1) << nh.Alignment;
+ }
+/* struct section_info *symtab; */
+ fi->symtab = NULL;
+/* struct section_info *strtab; */
+ fi->strtab = NULL;
+}
+
+char *
+ne_read_strtab (struct file_info *fi)
+{
+ return NULL;
+}
+
+struct symtab *
+ne_get_next_symbol (struct file_info *fi, char *strtab)
+{
+ return NULL;
+}
+
+
+/* PE (Win32 Portable Executable) section */
+
+char *pe_flags[] = {
+ "", /* no flags */
+ ", \"w\"", /* writeable */
+ ", \"x\"", /* executable */
+ ", \"xw\"", /* executable and writeable */
+};
+
+char *
+pe_get_flags (DWORD flags)
+{
+ int index = 0;
+
+ index |= ((flags & IMAGE_SCN_MEM_WRITE) ? 1 : 0);
+ index |= ((flags & IMAGE_SCN_MEM_EXECUTE) ? 2 : 0);
+
+ return pe_flags[index];
+}
+
+int
+pe_get_align (DWORD flags)
+{
+ return 1 << (((flags >> 20) & 0xf) - 1);
+}
+
+
+void
+read_pe_header (PCOFF_HEADER ch, FILE *fp)
+{
+ d_read (&ch->PeSignature, sizeof (char), 4, fp, 1);
+ d_read (&ch->Machine, sizeof (WORD), 1, fp, 0);
+ d_read (&ch->NumberOfSections, sizeof (WORD), 1, fp, 0);
+ d_read (&ch->TimeDateStamp, sizeof (DWORD), 1, fp, 0);
+ d_read (&ch->PointerToSymbolTable, sizeof (DWORD), 1, fp, 0);
+ d_read (&ch->NumberOfSymbols, sizeof (DWORD), 1, fp, 0);
+ d_read (&ch->SizeOfOptionalHeader, sizeof (WORD), 1, fp, 0);
+ d_read (&ch->Characteristics, sizeof (WORD), 1, fp, 0);
+}
+
+void
+read_pe_optional_header (PPE32_OPTIONAL_HEADER oh, FILE *fp, WORD oh_size)
+{
+ WORD size = 0;
+
+ d_read (&oh->Magic, sizeof (WORD), 1, fp, 0);
+ size += sizeof (WORD);
+
+ d_read (&oh->MajorLinkerVersion, sizeof (BYTE), 1, fp, 0);
+ size += sizeof (BYTE);
+
+ d_read (&oh->MinorLinkerVersion, sizeof (BYTE), 1, fp, 0);
+ size += sizeof (BYTE);
+
+ d_read (&oh->SizeOfCode, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->SizeOfInitializedData, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->SizeOfUninitializedData, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->AddressOfEntryPoint, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->BaseOfCode, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ if (oh->Magic == PE32_MAGIC)
+ {
+ d_read (&oh->BaseOfData, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+ }
+ else
+ oh->BaseOfData = 0;
+
+ if (oh->Magic == PE32_MAGIC)
+ {
+ d_read (&oh->ImageBase, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+ }
+ else
+ {
+ QWORD temp;
+
+ d_read (&temp, sizeof (QWORD), 1, fp, 0);
+ size += sizeof (QWORD);
+
+ oh->ImageBase = (DWORD) temp;
+ }
+
+ d_read (&oh->SectionAlignment, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->FileAlignment, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->MajorOperatingSystemVersion, sizeof (WORD), 1, fp, 0);
+ size += sizeof (WORD);
+
+ d_read (&oh->MinorOperatingSystemVersion, sizeof (WORD), 1, fp, 0);
+ size += sizeof (WORD);
+
+ d_read (&oh->MajorImageVersion, sizeof (WORD), 1, fp, 0);
+ size += sizeof (WORD);
+
+ d_read (&oh->MinorImageVersion, sizeof (WORD), 1, fp, 0);
+ size += sizeof (WORD);
+
+ d_read (&oh->MajorSubsystemVersion, sizeof (WORD), 1, fp, 0);
+ size += sizeof (WORD);
+
+ d_read (&oh->MinorSubsystemVersion, sizeof (WORD), 1, fp, 0);
+ size += sizeof (WORD);
+
+ d_read (&oh->Reserved, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->SizeOfImage, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->SizeOfHeaders, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->CheckSum, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->Subsystem, sizeof (WORD), 1, fp, 0);
+ size += sizeof (WORD);
+
+ d_read (&oh->DLLCharacteristics, sizeof (WORD), 1, fp, 0);
+ size += sizeof (WORD);
+
+ if (oh->Magic == PE32_MAGIC)
+ {
+ d_read (&oh->SizeOfStackReserve, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+ }
+ else
+ {
+ QWORD temp;
+
+ d_read (&temp, sizeof (QWORD), 1, fp, 0);
+ size += sizeof (QWORD);
+
+ oh->SizeOfStackReserve = (DWORD) temp;
+ }
+
+ if (oh->Magic == PE32_MAGIC)
+ {
+ d_read (&oh->SizeOfStackCommit, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+ }
+ else
+ {
+ QWORD temp;
+
+ d_read (&temp, sizeof (QWORD), 1, fp, 0);
+ size += sizeof (QWORD);
+
+ oh->SizeOfStackCommit = (DWORD) temp;
+ }
+
+ if (oh->Magic == PE32_MAGIC)
+ {
+ d_read (&oh->SizeOfHeapReserve, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+ }
+ else
+ {
+ QWORD temp;
+
+ d_read (&temp, sizeof (QWORD), 1, fp, 0);
+ size += sizeof (QWORD);
+
+ oh->SizeOfHeapReserve = (DWORD) temp;
+ }
+
+ if (oh->Magic == PE32_MAGIC)
+ {
+ d_read (&oh->SizeOfHeapCommit, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+ }
+ else
+ {
+ QWORD temp;
+
+ d_read (&temp, sizeof (QWORD), 1, fp, 0);
+ size += sizeof (QWORD);
+
+ oh->SizeOfHeapCommit = (DWORD) temp;
+ }
+
+ d_read (&oh->LoaderFlags, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+
+ d_read (&oh->NumberOfRvaAndSizes, sizeof (DWORD), 1, fp, 0);
+ size += sizeof (DWORD);
+}
+
+void
+read_oh_data_directories (IMAGE_DATA_DIRECTORY idd[N_OHDD], FILE *fp,
+ DWORD n_dd)
+{
+ int k;
+
+ for (k = 0; k < n_dd; k++)
+ {
+ d_read (&idd[k].RVA, sizeof (DWORD), 1, fp, 0);
+ d_read (&idd[k].Size, sizeof (DWORD), 1, fp, 0);
+ }
+}
+
+void
+read_pe_section_header (PSECTION_HEADER sh, FILE *fp)
+{
+ d_read (sh->Name, sizeof (char), 8, fp, 1);
+ d_read (&sh->VirtualSize, sizeof (DWORD), 1, fp, 0);
+ d_read (&sh->VirtualAddress, sizeof (DWORD), 1, fp, 0);
+ d_read (&sh->SizeOfRawData, sizeof (DWORD), 1, fp, 0);
+ d_read (&sh->PointerToRawData, sizeof (DWORD), 1, fp, 0);
+ d_read (&sh->PointerToRelocations, sizeof (DWORD), 1, fp, 0);
+ d_read (&sh->PointerToLinenumbers, sizeof (DWORD), 1, fp, 0);
+ d_read (&sh->NumberOfRelocations, sizeof (WORD), 1, fp, 0);
+ d_read (&sh->NumberOfLinenumbers, sizeof (WORD), 1, fp, 0);
+ d_read (&sh->Characteristics, sizeof (DWORD), 1, fp, 0);
+}
+
+char *
+get_pe_name (char *raw_name)
+{
+ char *name;
+ int count;
+
+ for (count = 0; count < 8; count++)
+ if (!raw_name[count]) break;
+
+ name = xmalloc (count + 1);
+ memcpy (name, raw_name, count);
+
+ return name;
+}
+
+
+void
+pe_get_file_info (struct file_info *fi)
+{
+ int n_code = 0, n_data = 0, k;
+ char *section_name;
+ DWORD pe_header_location;
+ COFF_HEADER ch;
+ PE32_OPTIONAL_HEADER oh;
+ SECTION_HEADER sh;
+ IMAGE_DATA_DIRECTORY idd[N_OHDD];
+
+
+ /* find the PE header */
+ fseek (fi->fp, PE_HEADER_OFFSET, SEEK_SET);
+ d_read (&pe_header_location, sizeof (DWORD), 1, fi->fp, 0);
+ fseek (fi->fp, pe_header_location, SEEK_SET);
+
+
+ read_pe_header (&ch, fi->fp);
+
+
+ switch (ch.Machine)
+ {
+ case IMAGE_FILE_MACHINE_ALPHA:
+ fi->arch = MT_ALPHA;
+ break;
+ case IMAGE_FILE_MACHINE_I386:
+ fi->arch = MT_IA32;
+ break;
+ default:
+ fi->arch = MT_UNK;
+ }
+
+
+ if (ch.Characteristics & IMAGE_FILE_BYTES_REVERSED_LO)
+ fi->endian = BO_LITTLE_ENDIAN;
+ else if (ch.Characteristics & IMAGE_FILE_BYTES_REVERSED_HI)
+ fi->endian = BO_BIG_ENDIAN;
+
+ if (ch.Characteristics & IMAGE_FILE_32BIT_MACHINE)
+ fi->bit_size = BS_32;
+ else if (ch.Characteristics & IMAGE_FILE_16BIT_MACHINE) /* won't see this */
+ fi->bit_size = BS_16;
+ else
+ fi->bit_size = BS_64;
+
+
+ /* handle symbol table and string table */
+ if (ch.PointerToSymbolTable)
+ {
+ long file_pos;
+ uint32_t strtab_size;
+
+ fi->symtab = alloc_section_info (".symtab", OTHER_SECTION,
+ ch.PointerToSymbolTable,
+ ch.NumberOfSymbols * SIZE_SYMBOL_TABLE,
+ SIZE_SYMBOL_TABLE, 0, 0, NULL,
+ NULL, 0);
+
+ /* read the size of the string table */
+ file_pos = ftell (fi->fp);
+ fseek (fi->fp, (ch.PointerToSymbolTable + (ch.NumberOfSymbols
+ * SIZE_SYMBOL_TABLE)),
+ SEEK_SET);
+ d_read (&strtab_size, sizeof (uint32_t), 1, fi->fp, 0);
+ fseek (fi->fp, file_pos, SEEK_SET);
+
+ strtab_size -= 4;
+
+ fi->strtab = alloc_section_info (".strtab", STRING_SECTION,
+ (ch.PointerToSymbolTable
+ + (ch.NumberOfSymbols
+ * SIZE_SYMBOL_TABLE)) + 4,
+ strtab_size, 0, 0, 0, NULL, NULL, 0);
+ }
+
+
+ oh.NumberOfRvaAndSizes = 0;
+
+ read_pe_optional_header (&oh, fi->fp, ch.SizeOfOptionalHeader);
+ read_oh_data_directories (idd, fi->fp, oh.NumberOfRvaAndSizes);
+
+
+ /* find load address */
+ fi->load_address = oh.ImageBase + oh.AddressOfEntryPoint;
+
+
+ /* should be pointing at the section headers here */
+ fi->data_sections = xmalloc ((ch.NumberOfSections + 1)
+ * sizeof (struct section_info));
+ fi->code_sections = xmalloc ((ch.NumberOfSections + 1)
+ * sizeof (struct section_info));
+
+ for (k = 1; k < ch.NumberOfSections + 1; k++)
+ {
+ read_pe_section_header (&sh, fi->fp);
+
+ section_name = get_pe_name (sh.Name);
+
+ if (debug)
+ printf ("read %s, idx %#x, offset %#x\n", section_name, k,
+ sh.PointerToRawData);
+
+
+ if (sh.Characteristics & IMAGE_SCN_CNT_CODE) /* code section */
+ {
+ fi->code_sections[n_code] = alloc_section_info (section_name,
+ CODE_SECTION,
+ sh.PointerToRawData,
+ sh.SizeOfRawData,
+ 0, k,
+ oh.ImageBase
+ + sh.VirtualAddress,
+ NULL,
+ pe_get_flags (sh.Characteristics),
+ pe_get_align (sh.Characteristics));
+
+ n_code++;
+
+ put_data_limits (oh.ImageBase + sh.VirtualAddress,
+ oh.ImageBase + sh.VirtualAddress + sh.VirtualSize);
+ }
+ else if (sh.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA
+ || sh.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ {
+
+
+ fi->data_sections[n_data] = alloc_section_info (section_name,
+ DATA_SECTION,
+ sh.PointerToRawData,
+ sh.SizeOfRawData,
+ 0, k,
+ oh.ImageBase
+ + sh.VirtualAddress,
+ NULL,
+ pe_get_flags (sh.Characteristics),
+ pe_get_align (sh.Characteristics));
+
+ n_data++;
+
+ put_data_limits (oh.ImageBase + sh.VirtualAddress,
+ oh.ImageBase + sh.VirtualAddress + sh.VirtualSize);
+ }
+ else /* not sure what this section could be */
+ {
+ if (debug)
+ printf ("unknown section: %s, flags: %08X\n", section_name,
+ sh.Characteristics);
+
+ xfree (section_name);
+ }
+ }
+
+
+
+ /* print debug info */
+ if (debug)
+ {
+ k = -1;
+ printf ("data:\n");
+ while (fi->data_sections[++k])
+ {
+ printf (" %s (%#lx), %d, %#lx, %#lx, %#lx\n",
+ fi->data_sections[k]->section_name,
+ fi->data_sections[k]->section_index,
+ fi->data_sections[k]->section_type,
+ fi->data_sections[k]->section_offset,
+ fi->data_sections[k]->section_size,
+ fi->data_sections[k]->load_address);
+ }
+
+ k = -1;
+ printf ("code:\n");
+ while (fi->code_sections[++k])
+ {
+ printf (" %s (%#lx), %d, %#lx, %#lx, %#lx\n",
+ fi->code_sections[k]->section_name,
+ fi->code_sections[k]->section_index,
+ fi->code_sections[k]->section_type,
+ fi->code_sections[k]->section_offset,
+ fi->code_sections[k]->section_size,
+ fi->code_sections[k]->load_address);
+ }
+
+ if (fi->symtab != NULL)
+ printf ("symtab:\n %s (%#lx), %d, %#lx, %#lx, %#lx\n",
+ fi->symtab->section_name,
+ fi->symtab->section_index,
+ fi->symtab->section_type,
+ fi->symtab->section_offset,
+ fi->symtab->section_size,
+ fi->symtab->load_address);
+
+ if (fi->strtab != NULL)
+ printf ("strtab:\n %s (%#lx), %d, %#lx, %#lx, %#lx\n",
+ fi->strtab->section_name,
+ fi->strtab->section_index,
+ fi->strtab->section_type,
+ fi->strtab->section_offset,
+ fi->strtab->section_size,
+ fi->strtab->load_address);
+ }
+}
+
+
+char *
+pe_read_strtab (struct file_info *fi)
+{
+ char *strtab;
+
+ if (fi->strtab == NULL) return NULL;
+
+ fseek (fi->fp, fi->strtab->section_offset, SEEK_SET);
+
+ strtab = xmalloc (fi->strtab->section_size);
+
+ d_read (strtab, sizeof (char), fi->strtab->section_size, fi->fp, 1);
+
+ return strtab;
+}
+
+
+/* pe_read_symbol
+ * Read a symbol from the symbol table.
+ */
+void
+pe_read_symbol (PCOFF_SYMBOL_TABLE sym, FILE *fp)
+{
+ DWORD temp;
+
+ d_read (&temp, sizeof (DWORD), 1, fp, 0);
+ fseek (fp, -4, SEEK_CUR);
+
+ if (temp != 0)
+ d_read (sym->Name.ShortName, sizeof (char), 8, fp, 1);
+ else
+ {
+ d_read (&sym->Name.LongName.Zeroes, sizeof (DWORD), 1, fp, 0);
+ d_read (&sym->Name.LongName.Offset, sizeof (DWORD), 1, fp, 0);
+ }
+
+ d_read (&sym->Value, sizeof (DWORD), 1, fp, 0);
+ d_read (&sym->SectionNumber, sizeof (WORD), 1, fp, 0);
+ d_read (&sym->Type, sizeof (WORD), 1, fp, 0);
+ d_read (&sym->StorageClass, sizeof (BYTE), 1, fp, 0);
+ d_read (&sym->NumberOfAuxSymbols, sizeof (BYTE), 1, fp, 0);
+}
+
+
+/* pe_read_aux_format_one
+ * Read in function definition information.
+ */
+void
+pe_read_aux_format_one (PAUXILIARY_FORMAT_ONE af, FILE *fp)
+{
+ d_read (&af->TagIndex, sizeof (DWORD), 1, fp, 0);
+ d_read (&af->TotalSize, sizeof (DWORD), 1, fp, 0);
+ d_read (&af->PointerToLinenumber, sizeof (DWORD), 1, fp, 0);
+ d_read (&af->PointerToNextFunction, sizeof (DWORD), 1, fp, 0);
+ d_read (&af->Unused, sizeof (BYTE), 2, fp, 0);
+}
+
+/* pe_read_aux_format_two
+ * Read in information on the .bf and .ef symbols.
+ */
+void
+pe_read_aux_format_two (PAUXILIARY_FORMAT_TWO af, FILE *fp)
+{
+ d_read (&af->Unused1, sizeof (BYTE), 4, fp, 0);
+ d_read (&af->Linenumber, sizeof (WORD), 1, fp, 0);
+ d_read (&af->Unused2, sizeof (BYTE), 6, fp, 0);
+ d_read (&af->PointerToNextFunction, sizeof (DWORD), 1, fp, 0);
+ d_read (&af->Unused3, sizeof (BYTE), 2, fp, 0);
+}
+
+/* pe_read_aux_format_three
+ * Read in information on weak external symbols.
+ */
+void
+pe_read_aux_format_three (PAUXILIARY_FORMAT_THREE af, FILE *fp)
+{
+ d_read (&af->TagIndex, sizeof (DWORD), 1, fp, 0);
+ d_read (&af->Characteristics, sizeof (DWORD), 1, fp, 0);
+ d_read (&af->Unused, sizeof (BYTE), 10, fp, 0);
+}
+
+/* pe_read_aux_format_four
+ * Read in information on a .file symbol.
+ */
+void
+pe_read_aux_format_four (PAUXILIARY_FORMAT_FOUR af, FILE *fp)
+{
+ d_read (af->FileName, sizeof (char), 18, fp, 1);
+}
+
+/* pe_read_aux_format_five
+ * Read in section definition information.
+ */
+void
+pe_read_aux_format_five (PAUXILIARY_FORMAT_FIVE af, FILE *fp)
+{
+ d_read (&af->Length, sizeof (DWORD), 1, fp, 0);
+ d_read (&af->NumberOfRelocations, sizeof (WORD), 1, fp, 0);
+ d_read (&af->NumberOfLineNumbers, sizeof (WORD), 1, fp, 0);
+ d_read (&af->CheckSum, sizeof (DWORD), 1, fp, 0);
+ d_read (&af->Number, sizeof (WORD), 1, fp, 0);
+ d_read (&af->Selection, sizeof (BYTE), 1, fp, 0);
+ d_read (&af->Unused, sizeof (BYTE), 3, fp, 0);
+}
+
+
+enum symbol_type
+pe_get_symbol_type (WORD type, BYTE class)
+{
+ if (((type >> 4) & 0xf) == IMAGE_SYM_DTYPE_FUNCTION) /* function */
+ {
+ if (class == IMAGE_SYM_CLASS_EXTERNAL)
+ return GLOBAL_FUNCTION;
+ else
+ return LOCAL_FUNCTION;
+ }
+ else /* data */
+ {
+ if (class == IMAGE_SYM_CLASS_EXTERNAL)
+ return GLOBAL_DATA;
+ else
+ return LOCAL_DATA;
+ }
+
+ return UNKNOWN_SYMBOL;
+}
+
+
+/* pe_get_next_symbol
+ * Read in the next symbol from the symbol table and return
+ * it as a struct symtab.
+ */
+struct symtab *
+pe_get_next_symbol (struct file_info *fi, char *strtab)
+{
+ struct symtab *sym;
+ COFF_SYMBOL_TABLE symbol;
+
+ sym = xmalloc (sizeof (struct symtab));
+
+ pe_read_symbol (&symbol, fi->fp);
+
+ /* get the symbol name */
+ if (symbol.Name.LongName.Zeroes != 0)
+ sym->name = get_pe_name (symbol.Name.ShortName);
+ else
+ {
+ sym->name = xmalloc (strlen (strtab + symbol.Name.LongName.Offset) + 1);
+ strcpy (sym->name, strtab + symbol.Name.LongName.Offset);
+ }
+
+ sym->address = symbol.Value; /* most likely */
+
+ if (symbol.SectionNumber < 1)
+ {
+ sym->address = 0;
+ sym->idx = 0;
+ }
+ else
+ sym->idx = symbol.SectionNumber;
+
+ /* if this is an external or static symbol, the load address is
+ the Value added to the load address of the section */
+ if (symbol.StorageClass == IMAGE_SYM_CLASS_EXTERNAL
+ || symbol.StorageClass == IMAGE_SYM_CLASS_STATIC)
+ {
+ if (symbol.SectionNumber > 0)
+ {
+ /* need to find the section with the matching number */
+ int k;
+
+ for (k = 0; fi->code_sections[k] != NULL; k++)
+ if (fi->code_sections[k]->section_index == symbol.SectionNumber)
+ {
+ sym->address = (fi->code_sections[k]->load_address
+ + symbol.Value);
+ goto GOT_SECTION_NUMBER;
+ }
+
+ for (k = 0; fi->data_sections[k] != NULL; k++)
+ if (fi->data_sections[k]->section_index == symbol.SectionNumber)
+ sym->address = (fi->data_sections[k]->load_address
+ + symbol.Value);
+
+ GOT_SECTION_NUMBER:
+ ;
+ }
+ }
+
+ sym->type = pe_get_symbol_type (symbol.Type, symbol.StorageClass);
+
+ switch (symbol.Type & 0xf)
+ {
+ case IMAGE_SYM_TYPE_CHAR:
+ case IMAGE_SYM_TYPE_BYTE:
+ sym->size = 1;
+ break;
+ case IMAGE_SYM_TYPE_SHORT:
+ sym->size = 2;
+ break;
+ case IMAGE_SYM_TYPE_INT:
+ case IMAGE_SYM_TYPE_LONG:
+ case IMAGE_SYM_TYPE_FLOAT:
+ case IMAGE_SYM_TYPE_UINT:
+ case IMAGE_SYM_TYPE_DWORD:
+ sym->size = 4;
+ break;
+ case IMAGE_SYM_TYPE_DOUBLE:
+ sym->size = 8;
+ break;
+ default:
+ sym->size = 0;
+ }
+
+ if (sym->size == 0 && ((symbol.Type >> 4) & 0xf) == IMAGE_SYM_DTYPE_POINTER)
+ {
+ if (fi->bit_size == BS_32)
+ sym->size = 4;
+ else if (fi->bit_size == BS_64)
+ sym->size = 8;
+ }
+
+ /* auxiliary data isn't necessarily used */
+ fseek (fi->fp, 18 * symbol.NumberOfAuxSymbols, SEEK_CUR);
+
+ if (debug)
+ printf ("%#lx:%s: size %lx, type %x, class %x, idx %lx\n", sym->address,
+ sym->name, sym->size, symbol.Type, symbol.StorageClass, sym->idx);
+
+ return sym;
+}
diff --git a/decomp/dos.h b/decomp/dos.h
new file mode 100644
index 0000000..33da9cf
--- /dev/null
+++ b/decomp/dos.h
@@ -0,0 +1,675 @@
+/* dos.h
+ * This file is part of Decomp - a disassembler. This file contains
+ * definitions used in the DOS/Win32 module.
+ *
+ * Copyright (C) 2002 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started on 25 Feb 2002
+ */
+
+#ifndef DOS_H
+#define DOS_H
+
+
+#include <stdint.h>
+
+
+/* define some Windows types */
+
+typedef uint8_t BYTE;
+typedef uint16_t WORD;
+typedef uint32_t DWORD;
+typedef uint64_t QWORD;
+/* typedef uint128_t OWORD */
+
+
+/* NE definitions */
+
+#define NE_POS_ISNE_INDICATOR 0x18
+#define NE_ISNE_INDICATOR 0x40
+
+#define NE_POS_HEADER_OFFSET 0x3c
+
+#define NE_MAKE_REAL_ADDRESS(segment,offset) (((DWORD)(segment) << 16) \
+ + (DWORD)(offset))
+
+struct ne_file_header {
+ char Signature[2]; /* NE */
+ BYTE LinkerMajorVersion;
+ BYTE LinkerMinorVersion;
+ WORD EntryTableOffset;
+ WORD EntryTableSize;
+ BYTE Reserved[4];
+ WORD Flags;
+ WORD AutoDataSegment;
+ WORD HeapSize;
+ WORD StackSize;
+ WORD CS;
+ WORD IP;
+ WORD SS;
+ WORD SP;
+ WORD SegmentTableEntries;
+ WORD ModuleRefTableEntries;
+ WORD NonresidentNameTableSize;
+ WORD SegmentTableOffset;
+ WORD ResourceTableOffset;
+ WORD ResidentNameTableOffset;
+ WORD ModuleReferenceTableOffset;
+ WORD ImportedNameTableOffset;
+ WORD NonresidentNameTableOffset;
+ WORD MovableEntryPoints;
+ WORD Alignment;
+ WORD ResourceSegments;
+ BYTE OperatingSystem;
+ BYTE AdditionalInformation;
+ WORD FastLoadSectorOffset;
+ WORD FastLoadSectorSize;
+ WORD Reserved1;
+ WORD WindowsVersion;
+};
+
+/* values for the Flags field */
+#define NEFLAG_SINGLEDATA (1<<0)
+#define NEFLAG_MULTIPLEDATA (1<<1)
+#define NEFLAG_BOOTSTRAP (1<<11)
+#define NEFLAG_HAS_ERRORS (1<<13)
+#define NEFLAG_ISLIB (1<<15)
+
+/* values for the OperatingSystem field */
+#define NEOS_UNKNOWN (1<<0)
+#define NEOS_MSWINDOWS (1<<2)
+
+/* values for the AdditionalInformation field */
+#define NEAINFO_PROTECTED (1<<1)
+#define NEAINFO_PROPORTIONAL_FONTS (1<<2)
+#define NEAINFO_FASTLOAD_AREA (1<<3)
+
+
+struct ne_segment_header {
+ WORD SegmentDataSectorOffset; /* from file start to segment in sectors */
+ WORD SegmentLength; /* 0 -> 64K */
+ WORD Flags;
+ WORD AllocationSize; /* 0 -> 64K */
+};
+
+#define NE_SEGMENT_TYPE (1<<0)
+
+#define NE_CODE_SEGMENT(flags) (!((flags) & NE_SEGMENT_TYPE))
+#define NE_DATA_SEGMENT(flags) ((flags) & NE_SEGMENT_TYPE)
+
+#define NE_MEM_ALLOCED (1<<1)
+#define NE_SEGMENT_LOADED (1<<2)
+#define NE_SEGMENT_MOVABLE (1<<4)
+#define NE_SEGMENT_SHAREABLE (1<<5)
+#define NE_SEGMENT_PRELOAD (1<<6)
+#define NE_CODE_EXECUTEONLY (1<<7)
+#define NE_DATA_READONLY (1<<7)
+#define NE_CONTAINS_RELOC_DATA (1<<8)
+#define NE_DISCARDABLE_SEGMENT (1<<12)
+
+
+/* resource table ?? */
+
+
+/* PE definitions */
+
+#define PE_HEADER_OFFSET 0x3c
+
+#define PE32_MAGIC 0x010b
+#define PE32PLUS_MAGIC 0x020b
+#define PE_ROM_MAGIC 0x0107 /* shouldn't see this */
+
+/* number of optional header data directories */
+#define N_OHDD 16
+
+
+/* the names in this header may not be strictly correct, I'm just
+ going off of the documentation and some educated guesses. */
+
+typedef struct _COFF_HEADER {
+ char PeSignature[4]; /* 4 byte signature (PE\0\0) */
+ WORD Machine; /* PE machine type */
+ WORD NumberOfSections; /* number of sections */
+ DWORD TimeDateStamp; /* time and date of file creation */
+ DWORD PointerToSymbolTable; /* file offset of the symbol table or 0 */
+ DWORD NumberOfSymbols; /* number of entries in the symbol table */
+ WORD SizeOfOptionalHeader; /* size of the optional header */
+ WORD Characteristics; /* attribute flags for this file */
+} COFF_HEADER, *PCOFF_HEADER;
+
+
+/* machine types (Machine field) */
+
+#define IMAGE_FILE_MACHINE_UNKNOWN 0x0 /* applicable to any machine */
+#define IMAGE_FILE_MACHINE_ALPHA 0x184 /* AXP Alpha */
+#define IMAGE_FILE_MACHINE_ARM 0x1c0 /* Strong ARM */
+#define IMAGE_FILE_MACHINE_ALPHA64 0x284 /* 64 bit AXP Alpha (err??) */
+#define IMAGE_FILE_MACHINE_I386 0x14c /* 386 and later */
+#define IMAGE_FILE_MACHINE_IA64 0x200 /* IA-64 */
+#define IMAGE_FILE_MACHINE_M68K 0x268 /* Motorola 68K series */
+#define IMAGE_FILE_MACHINE_MIPS16 0x266 /* 16 bit MIPS */
+#define IMAGE_FILE_MACHINE_MIPSFPU 0x366 /* MIPS with FPU */
+#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466 /* 16 bit MIPS with FPU */
+#define IMAGE_FILE_MACHINE_POWERPC 0x110 /* Power PC, little endian */
+#define IMAGE_FILE_MACHINE_R3000 0x162
+#define IMAGE_FILE_MACHINE_R4000 0x166 /* MIPS little endian */
+#define IMAGE_FILE_MACHINE_R10000 0x168
+#define IMAGE_FILE_MACHINE_SH3 0x1a2 /* Hitachi SH3 */
+#define IMAGE_FILE_MACHINE_SH4 0x1a8 /* Hitachi SH4 */
+#define IMAGE_FILE_MACHINE_THUMB 0x1c2
+
+
+/* characteristics (Characteristics field) */
+
+#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
+#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
+#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
+#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010
+#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
+#define IMAGE_FILE_16BIT_MACHINE 0x0040
+#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
+#define IMAGE_FILE_32BIT_MACHINE 0x0100
+#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400
+#define IMAGE_FILE_SYSTEM 0x1000
+#define IMAGE_FILE_DLL 0x2000
+#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
+#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
+
+
+/* optional header info */
+
+typedef struct _PE32PLUS_OPTIONAL_HEADER {
+ /* standard fields */
+ WORD Magic; /* PE32/PE32+ magic number */
+ BYTE MajorLinkerVersion; /* linker major version number */
+ BYTE MinorLinkerVersion; /* linker minor version number */
+ DWORD SizeOfCode; /* size of all of the text sections */
+ DWORD SizeOfInitializedData; /* size of all the data sections */
+ DWORD SizeOfUninitializedData; /* size of all the bss sections */
+ DWORD AddressOfEntryPoint; /* relative entry point */
+ DWORD BaseOfCode; /* relative address of the start of
+ the code section */
+ /* Windows NT specific fields */
+ /* this next field is 32 bits in PE32 and 64 bits in PE32+ */
+ QWORD ImageBase; /* address of start of image in memory */
+ DWORD SectionAlignment; /* byte alignment of sections in memory */
+ DWORD FileAlignment; /* byte alignment of sections on disk */
+ WORD MajorOperatingSystemVersion;
+ WORD MinorOperatingSystemVersion;
+ WORD MajorImageVersion;
+ WORD MinorImageVersion;
+ WORD MajorSubsystemVersion;
+ WORD MinorSubsystemVersion;
+ DWORD Reserved; /* dd (??) */
+ DWORD SizeOfImage; /* size of the image with headers */
+ DWORD SizeOfHeaders; /* size of the stubs/headers */
+ DWORD CheckSum; /* image checksum */
+ WORD Subsystem; /* Windows NT subsystem */
+ WORD DLLCharacteristics;
+
+ /* next field is 32 bits in PE32, 64 in PE32+ */
+ QWORD SizeOfStackReserve; /* size of stack to reserve */
+ /* next field is 32 bits in PE32, 64 in PE32+ */
+ QWORD SizeOfStackCommit; /* size of stack to commit */
+ /* next field is 32 bits in PE32, 64 in PE32+ */
+ QWORD SizeOfHeapReserve; /* size of heap to reserve */
+ /* next field is 32 bits in PE32, 64 in PE32+ */
+ QWORD SizeOfHeapCommit; /* size of heap to commit */
+
+ DWORD LoaderFlags; /* this field is obselete */
+ DWORD NumberOfRvaAndSizes; /* number of data dictionary entries */
+} PE32PLUS_OPTIONAL_HEADER, *PPE32PLUS_OPTIONAL_HEADER;
+
+typedef struct _PE32_OPTIONAL_HEADER {
+ /* standard fields */
+ WORD Magic; /* PE32/PE32+ magic number */
+ BYTE MajorLinkerVersion; /* linker major version number */
+ BYTE MinorLinkerVersion; /* linker minor version number */
+ DWORD SizeOfCode; /* size of all of the text sections */
+ DWORD SizeOfInitializedData; /* size of all the data sections */
+ DWORD SizeOfUninitializedData; /* size of all the bss sections */
+ DWORD AddressOfEntryPoint; /* relative entry point */
+ DWORD BaseOfCode; /* relative address of the start of
+ the code section */
+ /* this next field is only in PE32 files */
+ DWORD BaseOfData; /* relative address of the start of the data section */
+
+ /* Windows NT specific fields */
+ /* this next field is 32 bits in PE32 and 64 bits in PE32+ */
+ DWORD ImageBase; /* address of start of image in memory */
+ DWORD SectionAlignment; /* byte alignment of sections in memory */
+ DWORD FileAlignment; /* byte alignment of sections on disk */
+ WORD MajorOperatingSystemVersion;
+ WORD MinorOperatingSystemVersion;
+ WORD MajorImageVersion;
+ WORD MinorImageVersion;
+ WORD MajorSubsystemVersion;
+ WORD MinorSubsystemVersion;
+ DWORD Reserved; /* dd (??) */
+ DWORD SizeOfImage; /* size of the image with headers */
+ DWORD SizeOfHeaders; /* size of the stubs/headers */
+ DWORD CheckSum; /* image checksum */
+ WORD Subsystem; /* Windows NT subsystem */
+ WORD DLLCharacteristics;
+ /* next field is 32 bits in PE32, 64 in PE32+ */
+ DWORD SizeOfStackReserve; /* size of stack to reserve */
+ /* next field is 32 bits in PE32, 64 in PE32+ */
+ DWORD SizeOfStackCommit; /* size of stack to commit */
+ /* next field is 32 bits in PE32, 64 in PE32+ */
+ DWORD SizeOfHeapReserve; /* size of heap to reserve */
+ /* next field is 32 bits in PE32, 64 in PE32+ */
+ DWORD SizeOfHeapCommit; /* size of heap to commit */
+ DWORD LoaderFlags; /* this field is obselete */
+ DWORD NumberOfRvaAndSizes; /* number of data dictionary entries */
+} PE32_OPTIONAL_HEADER, *PPE32_OPTIONAL_HEADER;
+
+
+#define MAGIC_PE32 0x10b
+#define MAGIC_PE32_PLUS 0x20b
+
+
+/* Subsystem field in optional header */
+
+#define IMAGE_SUBSYSTEM_UNKNOWN 0
+#define IMAGE_SUBSYSTEM_NATIVE 1
+#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
+#define IMAGE_SUBSYSTEM_POSIX_CUI 7
+#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9
+#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
+#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
+
+
+/* DLLCharacteristics field in optional header */
+
+#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800
+#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000
+#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER 0x8000
+
+
+/* optional header data directory */
+
+typedef struct _IMAGE_DATA_DIRECTORY {
+ DWORD RVA; /* relative virtual address (to base of image at runtime) */
+ DWORD Size; /* size in bytes */
+} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
+
+
+/* section information */
+
+typedef struct _SECTION_HEADER {
+ char Name[8];
+ DWORD VirtualSize;
+ DWORD VirtualAddress;
+ DWORD SizeOfRawData;
+ DWORD PointerToRawData;
+ DWORD PointerToRelocations;
+ DWORD PointerToLinenumbers;
+ WORD NumberOfRelocations;
+ WORD NumberOfLinenumbers;
+ DWORD Characteristics;
+} SECTION_HEADER, *PSECTION_HEADER;
+
+
+/* section flags */
+
+#define IMAGE_SCN_TYPE_REG 0x00000000
+#define IMAGE_SCN_TYPE_DSECT 0x00000001
+#define IMAGE_SCN_TYPE_NOLOAD 0x00000002
+#define IMAGE_SCN_TYPE_GROUP 0x00000004
+#define IMAGE_SCN_TYPE_NO_PAD 0x00000008
+#define IMAGE_SCN_TYPE_COPY 0x00000010
+#define IMAGE_SCN_CNT_CODE 0x00000020
+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
+#define IMAGE_SCN_LNK_OTHER 0x00000100
+#define IMAGE_SCN_LNK_INFO 0x00000200
+#define IMAGE_SCN_TYPE_OVER 0x00000400
+#define IMAGE_SCN_LNK_REMOVE 0x00000800
+#define IMAGE_SCN_LNK_COMDAT 0x00001000
+#define IMAGE_SCN_MEM_FARDATA 0x00008000
+#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 /* huh? these two */
+#define IMAGE_SCN_MEM_16BIT 0x00020000 /* have the same value */
+#define IMAGE_SCN_MEM_LOCKED 0x00040000
+#define IMAGE_SCN_MEM_PRELOAD 0x00080000
+#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
+#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
+#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
+#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
+#define IMAGE_SCN_ALIGN_16BYTES 0x00500000
+#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
+#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
+#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
+#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
+#define IMAGE_SCN_ALIGN_512BYTES 0x00a00000
+#define IMAGE_SCN_ALIGN_1024BYTES 0x00b00000
+#define IMAGE_SCN_ALIGN_2048BYTES 0x00c00000
+#define IMAGE_SCN_ALIGN_4096BYTES 0x00d00000
+#define IMAGE_SCN_ALIGN_8192BYTES 0x00e00000
+#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
+#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
+#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
+#define IMAGE_SCN_MEM_SHARED 0x10000000
+#define IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define IMAGE_SCN_MEM_READ 0x40000000
+#define IMAGE_SCN_MEM_WRITE 0x80000000
+
+
+/* COFF relocations */
+
+typedef struct _COFF_RELOCATIONS {
+ DWORD VirtualAddress;
+ DWORD SymbolTableIndex;
+ WORD Type;
+} COFF_RELOCATIONS, *PCOFF_RELOCATIONS;
+
+/* COFF relocation type indicators */
+
+/* IA-32 */
+#define IMAGE_REL_I386_ABSOLUTE 0x0000
+#define IMAGE_REL_I386_DIR16 0x0001
+#define IMAGE_REL_I386_REL16 0x0002
+#define IMAGE_REL_I386_DIR32 0x0006
+#define IMAGE_REL_I386_DIR32NB 0x0007
+#define IMAGE_REL_I386_SEG12 0x0009
+#define IMAGE_REL_I386_SECTION 0x000a
+#define IMAGE_REL_I386_SECREL 0x000b
+#define IMAGE_REL_I386_REL32 0x0014
+
+/* Alpha */
+#define IMAGE_REL_ALPHA_ABSOLUTE 0x0000
+#define IMAGE_REL_ALPHA_REFLONG 0x0001
+#define IMAGE_REL_ALPHA_REFQUAD 0x0002
+#define IMAGE_REL_ALPHA_GPREL32 0x0003
+#define IMAGE_REL_ALPHA_LITERAL 0x0004
+#define IMAGE_REL_ALPHA_LITUSE 0x0005
+#define IMAGE_REL_ALPHA_GPDISP 0x0006
+#define IMAGE_REL_ALPHA_BRADDR 0x0007
+#define IMAGE_REL_ALPHA_HINT 0x0008
+#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x0009
+#define IMAGE_REL_ALPHA_REFHI 0x000a
+#define IMAGE_REL_ALPHA_REFLO 0x000b
+#define IMAGE_REL_ALPHA_PAIR 0x000c
+#define IMAGE_REL_ALPHA_MATCH 0x000d
+#define IMAGE_REL_ALPHA_SECTION 0x000e
+#define IMAGE_REL_ALPHA_SECREL 0x000f
+#define IMAGE_REL_ALPHA_REFLONGNB 0x0010
+#define IMAGE_REL_ALPHA_SECRELLO 0x0011
+#define IMAGE_REL_ALPHA_SECRELHI 0x0012
+#define IMAGE_REL_ALPHA_REFQ3 0x0013
+#define IMAGE_REL_ALPHA_REFQ2 0x0014
+#define IMAGE_REL_ALPHA_REFQ1 0x0015
+#define IMAGE_REL_ALPHA_GPRELLO 0x0016
+#define IMAGE_REL_ALPHA_GPRELHI 0x0017
+
+/* IBM PowerPC */
+/* Hitachi SuperH */
+/* ARM */
+/* MIPS */
+/* if I ever get around to including support for these processors,
+ then I'll fill out these sections */
+
+
+/* COFF line numbers */
+
+typedef struct _COFF_LINE_NUMBERS {
+ union {
+ DWORD SymbolTableIndex;
+ DWORD RVA;
+ } Type;
+ WORD Linenumber;
+ DWORD SymbolTableIndex;
+ DWORD VirtualAddress;
+} COFF_LINE_NUMBERS, *PCOFF_LINE_NUMBERS;
+
+
+/* COFF symbol table */
+
+#define SIZE_SYMBOL_TABLE 18
+
+typedef struct _COFF_SYMBOL_TABLE {
+ union {
+ char ShortName[8];
+ struct {
+ DWORD Zeroes;
+ DWORD Offset;
+ } LongName;
+ } Name;
+ DWORD Value;
+ WORD SectionNumber;
+ WORD Type;
+ BYTE StorageClass;
+ BYTE NumberOfAuxSymbols;
+} COFF_SYMBOL_TABLE, *PCOFF_SYMBOL_TABLE;
+
+/* section number values */
+
+#define IMAGE_SYM_UNDEFINED (0UL)
+#define IMAGE_SYM_ABSOLUTE (-1UL)
+#define IMAGE_SYM_DEBUG (-2UL)
+
+/* type representation */
+
+/* simple types */
+#define IMAGE_TYPE_MSB(type) ((type) >> 8)
+/* complex types */
+#define IMAGE_TYPE_LSB(type) ((type) & 0x00ff)
+
+/* LSB */
+#define IMAGE_SYM_TYPE_NULL 0 /* Microsoft tools use this setting */
+#define IMAGE_SYM_TYPE_VOID 1
+#define IMAGE_SYM_TYPE_CHAR 2
+#define IMAGE_SYM_TYPE_SHORT 3
+#define IMAGE_SYM_TYPE_INT 4
+#define IMAGE_SYM_TYPE_LONG 5
+#define IMAGE_SYM_TYPE_FLOAT 6
+#define IMAGE_SYM_TYPE_DOUBLE 7
+#define IMAGE_SYM_TYPE_STRUCT 8
+#define IMAGE_SYM_TYPE_UNION 9
+#define IMAGE_SYM_TYPE_ENUM 10
+#define IMAGE_SYM_TYPE_MOE 11
+#define IMAGE_SYM_TYPE_BYTE 12
+#define IMAGE_SYM_TYPE_WORD 13
+#define IMAGE_SYM_TYPE_UINT 14
+#define IMAGE_SYM_TYPE_DWORD 15
+
+/* MSB */
+#define IMAGE_SYM_DTYPE_NULL 0 /* Microsoft tools use either this value */
+#define IMAGE_SYM_DTYPE_POINTER 1
+#define IMAGE_SYM_DTYPE_FUNCTION 2 /* or this one */
+#define IMAGE_SYM_DTYPE_ARRAY 3
+
+/* storage class */
+#define IMAGE_SYM_CLASS_END_OF_FUNCTION 0xff /* -1 */
+#define IMAGE_SYM_CLASS_NULL 0
+#define IMAGE_SYM_CLASS_AUTOMATIC 1
+#define IMAGE_SYM_CLASS_EXTERNAL 2
+#define IMAGE_SYM_CLASS_STATIC 3
+#define IMAGE_SYM_CLASS_REGISTER 4
+#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define IMAGE_SYM_CLASS_LABEL 6
+#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define IMAGE_SYM_CLASS_ARGUMENT 9
+#define IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define IMAGE_SYM_CLASS_UNION_TAG 12
+#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define IMAGE_SYM_CLASS_ENUM_TAG 15
+#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define IMAGE_SYM_CLASS_BIT_FIELD 18
+#define IMAGE_SYM_CLASS_BLOCK 100
+#define IMAGE_SYM_CLASS_FUNCTION 101
+#define IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define IMAGE_SYM_CLASS_FILE 103
+#define IMAGE_SYM_CLASS_SECTION 104
+#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+
+
+/* Auxiliary symbol records - these will always be 18 bytes */
+
+/* format 1: function definitions */
+typedef struct _AUXILIARY_FORMAT_ONE {
+ DWORD TagIndex;
+ DWORD TotalSize;
+ DWORD PointerToLinenumber;
+ DWORD PointerToNextFunction;
+ BYTE Unused[2];
+} AUXILIARY_FORMAT_ONE, *PAUXILIARY_FORMAT_ONE;
+
+/* format 2: .bf and .ef symbols */
+typedef struct _AUXILIARY_FORMAT_TWO {
+ BYTE Unused1[4];
+ WORD Linenumber;
+ BYTE Unused2[6];
+ DWORD PointerToNextFunction; /* only used with .bf */
+ BYTE Unused3[2];
+} AUXILIARY_FORMAT_TWO, *PAUXILIARY_FORMAT_TWO;
+
+/* format 3: weak externals */
+typedef struct _AUXILIARY_FORMAT_THREE {
+ DWORD TagIndex;
+ DWORD Characteristics;
+ BYTE Unused[10];
+} AUXILIARY_FORMAT_THREE, *PAUXILIARY_FORMAT_THREE;
+
+/* format 4: files */
+typedef struct _AUXILIARY_FORMAT_FOUR {
+ char FileName[18];
+} AUXILIARY_FORMAT_FOUR, *PAUXILIARY_FORMAT_FOUR;
+
+/* format 5: section definitions */
+typedef struct _AUXILIARY_FORMAT_FIVE {
+ DWORD Length;
+ WORD NumberOfRelocations;
+ WORD NumberOfLineNumbers;
+ DWORD CheckSum;
+ WORD Number;
+ BYTE Selection;
+ BYTE Unused[3];
+} AUXILIARY_FORMAT_FIVE, *PAUXILIARY_FORMAT_FIVE;
+
+
+/* COMDAT sections */
+
+#define IMAGE_COMDAT_SELECT_NODUPLICATES 1
+#define IMAGE_COMDAT_SELECT_ANY 2
+#define IMAGE_COMDAT_SELECT_SAME_SIZE 3
+#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4
+#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
+#define IMAGE_COMDAT_SELECT_LARGEST 6
+
+
+/* Attribute Certificate table */
+
+typedef struct _ATTRIBUTE_CERTIFICATE_TABLE_ENTRY {
+ DWORD CertificateData;
+ DWORD SizeOfCertificate;
+} ATTRIBUTE_CERTIFICATE_TABLE_ENTRY, *PATTRIBUTE_CERTIFICATE_TABLE_ENTRY;
+
+
+/* Delay-Load Import table */
+
+typedef struct _DELAY_LOAD_DIRECTORY_TABLE {
+ DWORD Attributes;
+ DWORD Name;
+ DWORD ModuleHandle;
+ DWORD DelayImportAddressTable;
+ DWORD DelayImportNameTable;
+ DWORD BoundDelayImportTable;
+ DWORD UnloadDelayImportTable;
+ DWORD TimeStamp;
+} DELAY_LOAD_DIRECTORY_TABLE, *PDELAY_LOAD_DIRECTORY_TABLE;
+
+
+/* the .debug section */
+
+/* debug directory */
+
+typedef struct _DEBUG_DIRECTORY {
+ DWORD Characteristics;
+ DWORD TimeDateStamp;
+ WORD MajorVersion;
+ WORD MinorVersion;
+ DWORD Type;
+ DWORD SizeOfData;
+ DWORD AddressOfRawData;
+ DWORD PointerToRawData;
+} DEBUG_DIRECTORY, *PDEBUG_DIRECTORY;
+
+/* debug type */
+
+#define IMAGE_DEBUG_TYPE_UNKNOWN 0
+#define IMAGE_DEBUG_TYPE_COFF 1
+#define IMAGE_DEBUG_TYPE_CODEVIEW 2
+#define IMAGE_DEBUG_TYPE_FPO 3
+#define IMAGE_DEBUG_TYPE_MISC 4
+#define IMAGE_DEBUG_TYPE_EXCEPTION 5
+#define IMAGE_DEBUG_TYPE_FIXUP 6
+#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7
+#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8
+#define IMAGE_DEBUG_TYPE_BORLAND 9
+
+
+/* .edata section - exported symbols */
+
+/* ignore for now (pg 49) */
+
+
+/* .idata section - imported symbols */
+
+/* ignore for now (pg 52) */
+
+
+/* .pdata section - function pointers for exception handling */
+
+/* ignore for now (pg 54) */
+
+
+/* .reloc section */
+
+/* ignore for now (pg 55) */
+
+
+/* .tls section */
+
+/* ignore for now (pg 57) */
+
+
+/* .rsrc section */
+
+/* resource directory table */
+
+typedef struct _RESOURCE_DIRECTORY_TABLE {
+ DWORD Characteristics;
+ DWORD TimeDateStamp;
+ WORD MajorVersion;
+ WORD MinorVersion;
+ WORD NumberOfNameEntries;
+ WORD NumberOfIDEntries;
+} RESOURCE_DIRECTORY_TABLE, *PRESOURCE_DIRECTORY_TABLE;
+
+/* resource directory entries */
+
+typedef struct _RESOURCE_DIRECTORY_ENTRY {
+ DWORD NameRVA;
+ DWORD IntegerID;
+ DWORD DataEntryRVA;
+ DWORD SubdirectoryRVA;
+} RESOURCE_DIRECTORY_ENTRY, *PRESOURCE_DIRECTORY_ENTRY;
+
+/* resource directory string */
+/* 2 byte length field followed by LENGTH sized unicode string */
+
+/* resource data entry */
+
+
+
+
+#endif /* !DOS_H */
diff --git a/decomp/elf.c b/decomp/elf.c
new file mode 100644
index 0000000..e5e06d8
--- /dev/null
+++ b/decomp/elf.c
@@ -0,0 +1,853 @@
+/* elf.c
+ * This file is part of decomp - a disassembler. Here are the routines
+ * for manipulating ELF32/64 files.
+ *
+ * Copyright (C) 2002 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started on 30 January 2002.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <elf.h>
+
+#include "decomp.h"
+
+
+/* give these forward references */
+int elf_unneeded_section (const char *name);
+char *elf_get_flags (unsigned long flags);
+enum symbol_type elf_get_symbol_type (struct file_info *fi,unsigned char info);
+
+
+/* I finally found a problem with C - the lack of dynamic types forces
+ me to separate elf32/elf64 handling into two virtually identical
+ largish functions. Of course, that sort of thing would cause a lot
+ of bloat in the language itself, so I guess I'll live. */
+
+
+/* ELF32 section */
+
+/* elf32_read_file_header
+ * Reads the ELF32 file header in the file pointed to by FP and
+ * populates FILE_HEADER with the information.
+ */
+void
+elf32_read_file_header (Elf32_Ehdr *file_header, FILE *fp)
+{
+ d_read (file_header->e_ident, sizeof (char), EI_NIDENT, fp, 1);
+ d_read (&file_header->e_type, sizeof (Elf32_Half), 1, fp, 0);
+ d_read (&file_header->e_machine, sizeof (Elf32_Half), 1, fp, 0);
+ d_read (&file_header->e_version, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&file_header->e_entry, sizeof (Elf32_Addr), 1, fp, 0);
+ d_read (&file_header->e_phoff, sizeof (Elf32_Off), 1, fp, 0);
+ d_read (&file_header->e_shoff, sizeof (Elf32_Off), 1, fp, 0);
+ d_read (&file_header->e_flags, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&file_header->e_ehsize, sizeof (Elf32_Half), 1, fp, 0);
+ d_read (&file_header->e_phentsize, sizeof (Elf32_Half), 1, fp, 0);
+ d_read (&file_header->e_phnum, sizeof (Elf32_Half), 1, fp, 0);
+ d_read (&file_header->e_shentsize, sizeof (Elf32_Half), 1, fp, 0);
+ d_read (&file_header->e_shnum, sizeof (Elf32_Half), 1, fp, 0);
+ d_read (&file_header->e_shstrndx, sizeof (Elf32_Half), 1, fp, 0);
+}
+
+
+/* elf32_read_section_header
+ * Reads and ELF32 section header which is pointed to by FP and
+ * uses the information to populate SH.
+ */
+void
+elf32_read_section_header (Elf32_Shdr *sh, FILE *fp)
+{
+ d_read (&sh->sh_name, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&sh->sh_type, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&sh->sh_flags, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&sh->sh_addr, sizeof (Elf32_Addr), 1, fp, 0);
+ d_read (&sh->sh_offset, sizeof (Elf32_Off), 1, fp, 0);
+ d_read (&sh->sh_size, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&sh->sh_link, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&sh->sh_info, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&sh->sh_addralign, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&sh->sh_entsize, sizeof (Elf32_Word), 1, fp, 0);
+}
+
+
+/* elf32_get_file_info
+ * Get the information from an ELF32 file and populate FI with the
+ * information.
+ */
+void
+elf32_get_file_info (struct file_info *fi)
+{
+ int k, n_data = 0, n_code = 0;
+ char *shstrtab;
+ Elf32_Ehdr fh;
+ Elf32_Shdr sh;
+
+ elf32_read_file_header (&fh, fi->fp);
+
+ fi->bit_size = BS_32;
+ fi->load_address = fh.e_entry;
+ fi->endian = ((fh.e_ident[EI_DATA] == ELFDATA2LSB)
+ ? BO_LITTLE_ENDIAN
+ : BO_BIG_ENDIAN);
+
+ /* do some sanity checks on the header */
+ if (strncmp (fh.e_ident, ELFMAG, SELFMAG) /* magic - \x7fELF */
+ || (fh.e_ident[EI_VERSION] != EV_CURRENT) /* current version */
+ || (fh.e_type != ET_REL /* object file */
+ && fh.e_type != ET_EXEC /* or executable */
+ && fh.e_type != ET_DYN) /* or library */
+ || (fh.e_version != EV_CURRENT)) /* current version */
+ error_out (ERR_INVALID_FILE);
+
+
+ /* only handle IA-32 for now... */
+ if (fh.e_machine == EM_386)
+ fi->arch = MT_IA32;
+ else
+ fi->arch = MT_UNK;
+
+
+ /* read the section header string table index */
+ fseek (fi->fp, fh.e_shoff + fh.e_shstrndx * fh.e_shentsize, SEEK_SET);
+ elf32_read_section_header (&sh, fi->fp);
+
+ shstrtab = xmalloc (sh.sh_size);
+ fseek (fi->fp, sh.sh_offset, SEEK_SET);
+
+ /* and then read the section header string table */
+ fread (shstrtab, sizeof (char), sh.sh_size, fi->fp);
+
+
+ /* read the sections and put them in their proper places */
+
+ fi->data_sections = xmalloc ((fh.e_shnum + 1)
+ * sizeof (struct section_info *));
+ fi->code_sections = xmalloc ((fh.e_shnum + 1)
+ * sizeof (struct section_info *));
+
+ /* position at start of section headers */
+ fseek (fi->fp, fh.e_shoff, SEEK_SET);
+
+
+ for (k = 0; k < fh.e_shnum; k++)
+ {
+ char *section_name = NULL;
+
+ /* read the header */
+ elf32_read_section_header (&sh, fi->fp);
+
+ /* find the name */
+ section_name = xmalloc (strlen (shstrtab + sh.sh_name) + 1);
+ strcpy (section_name, shstrtab + sh.sh_name);
+
+
+ if (debug)
+ printf ("read %s, idx %#x, offset %#x\n", section_name, k,
+ sh.sh_offset);
+
+ /* parse the header into the proper place */
+ switch (sh.sh_type)
+ {
+ case SHT_PROGBITS:
+ if (sh.sh_flags & SHF_EXECINSTR) /* code section */
+ {
+ if (elf_unneeded_section (section_name))
+ {
+ xfree (section_name);
+ continue;
+ }
+
+ fi->code_sections[n_code] = alloc_section_info (section_name,
+ CODE_SECTION,
+ sh.sh_offset,
+ sh.sh_size, 0, k,
+ sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+
+ put_data_limits (sh.sh_addr, sh.sh_addr + sh.sh_size);
+
+ n_code++;
+ }
+ else /* data section */
+ {
+ if (elf_unneeded_section (section_name))
+ {
+ xfree (section_name);
+ continue;
+ }
+
+ fi->data_sections[n_data] = alloc_section_info (section_name,
+ DATA_SECTION,
+ sh.sh_offset,
+ sh.sh_size, 0, k,
+ sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+
+ put_data_limits (sh.sh_addr, sh.sh_addr + sh.sh_size);
+
+ n_data++;
+ }
+
+ break;
+ case SHT_SYMTAB: /* symbol table */
+ fi->symtab = alloc_section_info (section_name, OTHER_SECTION,
+ sh.sh_offset, sh.sh_size,
+ sh.sh_entsize, k, sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+
+ break;
+ case SHT_STRTAB: /* string table */
+ if (elf_unneeded_section (section_name))
+ {
+ xfree (section_name);
+ continue;
+ }
+
+ if (!strcmp (section_name, ".strtab")) /* the string table */
+ {
+ fi->strtab = alloc_section_info (section_name, STRING_SECTION,
+ sh.sh_offset, sh.sh_size, 0, k,
+ sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+ }
+ else /* another table with strings (??) */
+ {
+ fi->data_sections[n_data] = alloc_section_info (section_name,
+ STRING_SECTION,
+ sh.sh_offset,
+ sh.sh_size, 0, k,
+ sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+
+ put_data_limits (sh.sh_addr, sh.sh_addr + sh.sh_size);
+
+ n_data++;
+ }
+
+ break;
+ /*
+ I don't think that these two are needed, but they're here
+ as a reminder, just in case.
+ case SHT_RELA:
+ case SHT_HASH:
+ */
+ default:
+ xfree (section_name);
+ continue;
+ }
+ }
+
+
+ xfree (shstrtab);
+}
+
+/* elf32_read_symbol
+ * Read an Elf32_Sym and store it into SYM.
+ */
+void
+elf32_read_symbol (Elf32_Sym *sym, FILE *fp)
+{
+ d_read (&sym->st_name, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&sym->st_value, sizeof (Elf32_Addr), 1, fp, 0);
+ d_read (&sym->st_size, sizeof (Elf32_Word), 1, fp, 0);
+ d_read (&sym->st_info, sizeof (unsigned char), 1, fp, 0);
+ d_read (&sym->st_other, sizeof (unsigned char), 1, fp, 0);
+ d_read (&sym->st_shndx, sizeof (Elf32_Section), 1, fp, 0);
+}
+
+/* elf_32_get_next_symbol
+ * Read the next symbol from the object file and return it as a struct symtab.
+ */
+struct symtab *
+elf32_get_next_symbol (struct file_info *fi, char *strtab)
+{
+ unsigned long unnamed_index = 0;
+ char *tmp;
+ struct symtab *sym;
+ Elf32_Sym symbol;
+
+ elf32_read_symbol (&symbol, fi->fp);
+
+ /* ignore symbols with no section */
+ /* if (symbol.st_shndx == 0xfff1) continue; */
+
+ /* ignore unknown symbol types */
+ /*if (get_symbol_type (symbol.st_info) == UNKNOWN_SYMBOL) continue;*/
+
+ /* ignore null-named symbols */
+ /*if (!strlen (strtab + symbol.st_name)) continue;*/
+
+ /* if this symbol references a section or a file, ignore */
+ if (ELF32_ST_TYPE (symbol.st_info) == STT_SECTION
+ || ELF32_ST_TYPE (symbol.st_info) == STT_FILE) return NULL;
+
+ if (symbol.st_value == 0) return NULL;
+
+ sym = xmalloc (sizeof (struct symtab));
+
+ /* if a symbol has no name, make up a (sorta) random name */
+ if (!strlen (strtab + symbol.st_name))
+ {
+ char *tmp_name;
+
+ tmp_name = xmalloc (16);
+ snprintf (tmp_name, 16, "sym_%ld", unnamed_index++);
+
+ sym->name = xmalloc (strlen (tmp_name) + 1);
+ strcpy (sym->name, tmp_name);
+
+ xfree (tmp_name);
+ }
+ else /* symbol has a name */
+ {
+ sym->name = xmalloc (strlen (strtab + symbol.st_name) + 1);
+ strcpy (sym->name, strtab + symbol.st_name);
+ }
+
+ sym->address = symbol.st_value;
+ sym->size = symbol.st_size;
+ sym->idx = symbol.st_shndx;
+ sym->type = elf_get_symbol_type (fi, symbol.st_info);
+
+ if (debug)
+ printf ("%#lx:%s: size %#lx, info %#02x, other %#02x, idx %#x\n",
+ (unsigned long)symbol.st_value, sym->name,
+ (unsigned long)symbol.st_size, symbol.st_info,
+ symbol.st_other, symbol.st_shndx);
+ /* if (debug) */
+ /* printf ("%s: %#lx, %#lx, %#lx, %d\n", sym->name, sym->address, */
+ /* sym->size, sym->section_index, sym->type); */
+
+ /* check for @@foo at the end of a symbol - if it is there, strip it */
+ if ((tmp = strchr (sym->name, '@')) != NULL) *tmp = '\0';
+
+ return sym;
+}
+
+
+/* ELF64 section */
+
+/* elf64_read_file_header
+ * Reads the ELF64 file header in the file pointed to by FP and
+ * populates FILE_HEADER with the information.
+ */
+void
+elf64_read_file_header (Elf64_Ehdr *file_header, FILE *fp)
+{
+ d_read (file_header->e_ident, sizeof (char), EI_NIDENT, fp, 1);
+ d_read (&file_header->e_type, sizeof (Elf64_Half), 1, fp, 0);
+ d_read (&file_header->e_machine, sizeof (Elf64_Half), 1, fp, 0);
+ d_read (&file_header->e_version, sizeof (Elf64_Word), 1, fp, 0);
+ d_read (&file_header->e_entry, sizeof (Elf64_Addr), 1, fp, 0);
+ d_read (&file_header->e_phoff, sizeof (Elf64_Off), 1, fp, 0);
+ d_read (&file_header->e_shoff, sizeof (Elf64_Off), 1, fp, 0);
+ d_read (&file_header->e_flags, sizeof (Elf64_Word), 1, fp, 0);
+ d_read (&file_header->e_ehsize, sizeof (Elf64_Half), 1, fp, 0);
+ d_read (&file_header->e_phentsize, sizeof (Elf64_Half), 1, fp, 0);
+ d_read (&file_header->e_phnum, sizeof (Elf64_Half), 1, fp, 0);
+ d_read (&file_header->e_shentsize, sizeof (Elf64_Half), 1, fp, 0);
+ d_read (&file_header->e_shnum, sizeof (Elf64_Half), 1, fp, 0);
+ d_read (&file_header->e_shstrndx, sizeof (Elf64_Half), 1, fp, 0);
+}
+
+
+/* elf64_read_section_header
+ * Reads and ELF64 section header which is pointed to by FP and
+ * uses the information to populate SH.
+ */
+void
+elf64_read_section_header (Elf64_Shdr *sh, FILE *fp)
+{
+ d_read (&sh->sh_name, sizeof (Elf64_Word), 1, fp, 0);
+ d_read (&sh->sh_type, sizeof (Elf64_Word), 1, fp, 0);
+ d_read (&sh->sh_flags, sizeof (Elf64_Xword), 1, fp, 0);
+ d_read (&sh->sh_addr, sizeof (Elf64_Addr), 1, fp, 0);
+ d_read (&sh->sh_offset, sizeof (Elf64_Off), 1, fp, 0);
+ d_read (&sh->sh_size, sizeof (Elf64_Xword), 1, fp, 0);
+ d_read (&sh->sh_link, sizeof (Elf64_Word), 1, fp, 0);
+ d_read (&sh->sh_info, sizeof (Elf64_Word), 1, fp, 0);
+ d_read (&sh->sh_addralign, sizeof (Elf64_Xword), 1, fp, 0);
+ d_read (&sh->sh_entsize, sizeof (Elf64_Xword), 1, fp, 0);
+}
+
+
+/* elf64_get_file_info
+ * Get the information from an ELF64 file and populate FI with the
+ * information.
+ */
+void
+elf64_get_file_info (struct file_info *fi)
+{
+ int k, n_data = 0, n_code = 0;
+ char *shstrtab;
+ Elf64_Ehdr fh;
+ Elf64_Shdr sh;
+
+ elf64_read_file_header (&fh, fi->fp);
+
+ fi->bit_size = BS_64;
+ fi->load_address = fh.e_entry;
+ fi->endian = ((fh.e_ident[EI_DATA] == ELFDATA2LSB)
+ ? BO_LITTLE_ENDIAN
+ : BO_BIG_ENDIAN);
+
+ /* do some sanity checks on the header */
+ if (strncmp (fh.e_ident, ELFMAG, SELFMAG) /* magic - \x7fELF */
+ || (fh.e_ident[EI_VERSION] != EV_CURRENT) /* current version */
+ || (fh.e_type != ET_REL /* object file */
+ && fh.e_type != ET_EXEC /* or executable */
+ && fh.e_type != ET_DYN) /* or library */
+ || (fh.e_version != EV_CURRENT)) /* current version */
+ error_out (ERR_INVALID_FILE);
+
+
+ /* only handle IA-32 for now... */
+ switch (fh.e_machine)
+ {
+ case EM_386:
+ fi->arch = MT_IA32;
+ break;
+ default:
+ fi->arch = MT_UNK;
+ }
+
+
+ /* read the section header string table index */
+ fseek (fi->fp, fh.e_shoff + fh.e_shstrndx * fh.e_shentsize, SEEK_SET);
+ elf64_read_section_header (&sh, fi->fp);
+
+ shstrtab = xmalloc (sh.sh_size);
+ fseek (fi->fp, sh.sh_offset, SEEK_SET);
+
+ /* and then read the section header string table */
+ fread (shstrtab, sizeof (char), sh.sh_size, fi->fp);
+
+
+ /* read the sections and put them in their proper places */
+
+ fi->data_sections = xmalloc ((fh.e_shnum + 1)
+ * sizeof (struct section_info *));
+ fi->code_sections = xmalloc ((fh.e_shnum + 1)
+ * sizeof (struct section_info *));
+
+ /* position at start of section headers */
+ fseek (fi->fp, fh.e_shoff, SEEK_SET);
+
+
+ for (k = 0; k < fh.e_shnum; k++)
+ {
+ char *section_name = NULL;
+
+ /* read the header */
+ elf64_read_section_header (&sh, fi->fp);
+
+ /* find the name */
+ section_name = xmalloc (strlen (shstrtab + sh.sh_name) + 1);
+ strcpy (section_name, shstrtab + sh.sh_name);
+
+
+ if (debug)
+ printf ("read %s, idx %#x, offset %#llx\n", section_name, k,
+ sh.sh_offset);
+
+ /* parse the header into the proper place */
+ switch (sh.sh_type)
+ {
+ case SHT_PROGBITS:
+ if (sh.sh_flags & SHF_EXECINSTR) /* code section */
+ {
+ if (elf_unneeded_section (section_name))
+ {
+ xfree (section_name);
+ continue;
+ }
+
+ fi->code_sections[n_code] = alloc_section_info (section_name,
+ CODE_SECTION,
+ sh.sh_offset,
+ sh.sh_size, 0, k,
+ sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+
+ put_data_limits (sh.sh_addr, sh.sh_addr + sh.sh_size);
+
+ n_code++;
+ }
+ else /* data section */
+ {
+ if (elf_unneeded_section (section_name))
+ {
+ xfree (section_name);
+ continue;
+ }
+
+ fi->data_sections[n_data] = alloc_section_info (section_name,
+ DATA_SECTION,
+ sh.sh_offset,
+ sh.sh_size, 0, k,
+ sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+
+ put_data_limits (sh.sh_addr, sh.sh_addr + sh.sh_size);
+
+ n_data++;
+ }
+
+ break;
+ case SHT_SYMTAB: /* symbol table */
+ fi->symtab = alloc_section_info (section_name, OTHER_SECTION,
+ sh.sh_offset, sh.sh_size,
+ sh.sh_entsize, k, sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+
+ break;
+ case SHT_STRTAB: /* string table */
+ if (elf_unneeded_section (section_name))
+ {
+ xfree (section_name);
+ continue;
+ }
+
+ if (!strcmp (section_name, ".strtab")) /* the string table */
+ {
+ fi->strtab = alloc_section_info (section_name, STRING_SECTION,
+ sh.sh_offset, sh.sh_size, 0, k,
+ sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+ }
+ else /* another table with strings (??) */
+ {
+ fi->data_sections[n_data] = alloc_section_info (section_name,
+ STRING_SECTION,
+ sh.sh_offset,
+ sh.sh_size, 0, k,
+ sh.sh_addr, NULL,
+ elf_get_flags (sh.sh_flags),
+ sh.sh_addralign);
+
+ put_data_limits (sh.sh_addr, sh.sh_addr + sh.sh_size);
+
+ n_data++;
+ }
+
+ break;
+ /*
+ I don't think that these two are needed, but they're here
+ as a reminder, just in case.
+ case SHT_RELA:
+ case SHT_HASH:
+ */
+ default:
+ xfree (section_name);
+ continue;
+ }
+ }
+
+
+ xfree (shstrtab);
+}
+
+/* elf64_read_symbol
+ * Read an Elf64_Sym and store it into SYM.
+ */
+void
+elf64_read_symbol (Elf64_Sym *sym, FILE *fp)
+{
+ d_read (&sym->st_name, sizeof (Elf64_Word), 1, fp, 0);
+ d_read (&sym->st_info, sizeof (unsigned char), 1, fp, 0);
+ d_read (&sym->st_other, sizeof (unsigned char), 1, fp, 0);
+ d_read (&sym->st_shndx, sizeof (Elf64_Section), 1, fp, 0);
+ d_read (&sym->st_value, sizeof (Elf64_Addr), 1, fp, 0);
+ d_read (&sym->st_size, sizeof (Elf64_Xword), 1, fp, 0);
+}
+
+/* elf64_get_next_symbol
+ * Read the next symbol from the object file and return it as a struct symtab.
+ */
+struct symtab *
+elf64_get_next_symbol (struct file_info *fi, char *strtab)
+{
+ unsigned long unnamed_index = 0;
+ char *tmp;
+ struct symtab *sym;
+ Elf64_Sym symbol;
+
+ elf64_read_symbol (&symbol, fi->fp);
+
+ /* ignore symbols with no section */
+ /* if (symbol.st_shndx == 0xfff1) continue; */
+
+ /* ignore unknown symbol types */
+ /*if (get_symbol_type (symbol.st_info) == UNKNOWN_SYMBOL) continue;*/
+
+ /* ignore null-named symbols */
+ /*if (!strlen (strtab + symbol.st_name)) continue;*/
+
+ /* if this symbol references a section or a file, ignore */
+ if (ELF64_ST_TYPE (symbol.st_info) == STT_SECTION
+ || ELF64_ST_TYPE (symbol.st_info) == STT_FILE) return NULL;
+
+ if (symbol.st_value == 0) return NULL;
+
+ sym = xmalloc (sizeof (struct symtab));
+
+ /* if a symbol has no name, make up a (sorta) random name */
+ if (!strlen (strtab + symbol.st_name))
+ {
+ char *tmp_name;
+
+ tmp_name = xmalloc (16);
+ snprintf (tmp_name, 16, "sym_%ld", unnamed_index++);
+
+ sym->name = xmalloc (strlen (tmp_name) + 1);
+ strcpy (sym->name, tmp_name);
+
+ xfree (tmp_name);
+ }
+ else /* symbol has a name */
+ {
+ sym->name = xmalloc (strlen (strtab + symbol.st_name) + 1);
+ strcpy (sym->name, strtab + symbol.st_name);
+ }
+
+ sym->address = symbol.st_value;
+ sym->size = symbol.st_size;
+ sym->idx = symbol.st_shndx;
+ sym->type = elf_get_symbol_type (fi, symbol.st_info);
+
+ if (debug)
+ printf ("%#lx:%s: size %#lx, info %#02x, other %#02x, idx %#x\n",
+ (unsigned long)symbol.st_value, sym->name,
+ (unsigned long)symbol.st_size, symbol.st_info,
+ symbol.st_other, symbol.st_shndx);
+ /* if (debug) */
+ /* printf ("%s: %#lx, %#lx, %#lx, %d\n", sym->name, sym->address, */
+ /* sym->size, sym->section_index, sym->type); */
+
+ /* check for @@foo at the end of a symbol - if it is there, strip it */
+ if ((tmp = strchr (sym->name, '@')) != NULL) *tmp = '\0';
+
+ return sym;
+}
+
+
+/* Generic ELF section */
+
+
+/* elf_unneeded_section
+ * If NAME matches one of the names of the unneeded data sections,
+ * then 1 is returned, otherwise 0 is returned.
+ */
+int
+elf_unneeded_section (const char *name)
+{
+ int k = -1;
+ char *unneeded[] = { ".interp", ".plt", ".stab", ".comment", ".sbss",
+ ".shstrtab", ".stabstr", ".got", ".dtors", ".dynstr",
+ ".ctors", ".eh_frame", NULL };
+
+ while (unneeded[++k] != NULL) if (!strcmp (name, unneeded[k])) return 1;
+
+ if (!strncmp (name, ".debug", 6)) return 1;
+
+ return 0;
+}
+
+
+char *flag_str_array[] = {
+ "", /* no flags */
+ ", \"w\"", /* writeable */
+ ", \"a\"", /* occupies memory during execution */
+ ", \"aw\"", /* writeable and occupies memory during execution */
+ ", \"x\"", /* executable */
+ ", \"xw\"", /* executable and writeable */
+ ", \"xa\"", /* executable and occupies memory during execution */
+ ", \"xaw\"", /* executable, occupies memory during execution and writeable */
+};
+
+/* elf_get_flags
+ * Translate the flags from the section header into textual flags that the
+ * assembler will understand.
+ */
+char *
+elf_get_flags (unsigned long flags)
+{
+ int index;
+
+ index = (flags & SHF_WRITE) + (flags & SHF_ALLOC) + (flags & SHF_EXECINSTR);
+ if (index > 7) index = 0;
+
+ return flag_str_array[index];
+}
+
+
+/* elf_get_file_info
+ * Get the information from the object file and populate FI.
+ */
+void
+elf_get_file_info (struct file_info *fi)
+{
+ int k;
+ char ident_buffer[EI_NIDENT];
+
+
+ fi->symtab = NULL;
+ fi->strtab = NULL;
+
+
+ /* read in the first EI_NIDENT chars in to find out if this is ELF32
+ or ELF64 */
+ fseek (fi->fp, 0, SEEK_SET);
+ fread (ident_buffer, sizeof (char), EI_NIDENT, fi->fp);
+
+ /* reset the file pointer */
+ fseek (fi->fp, 0, SEEK_SET);
+
+
+ /* find the target byte order */
+ if (ident_buffer[EI_DATA] == ELFDATA2LSB) /* little endian */
+ target_endian = BO_LITTLE_ENDIAN;
+ else /* big endian */
+ target_endian = BO_BIG_ENDIAN;
+
+
+ if (ident_buffer[EI_CLASS] == ELFCLASS32)
+ elf32_get_file_info (fi);
+ else
+ elf64_get_file_info (fi);
+
+
+ /* print debug info */
+ if (debug)
+ {
+ k = -1;
+ printf ("data:\n");
+ while (fi->data_sections[++k])
+ {
+ printf (" %s (%#lx), %d, %#lx, %#lx, %#lx\n",
+ fi->data_sections[k]->section_name,
+ fi->data_sections[k]->section_index,
+ fi->data_sections[k]->section_type,
+ fi->data_sections[k]->section_offset,
+ fi->data_sections[k]->section_size,
+ fi->data_sections[k]->load_address);
+ }
+
+ k = -1;
+ printf ("code:\n");
+ while (fi->code_sections[++k])
+ {
+ printf (" %s (%#lx), %d, %#lx, %#lx, %#lx\n",
+ fi->code_sections[k]->section_name,
+ fi->code_sections[k]->section_index,
+ fi->code_sections[k]->section_type,
+ fi->code_sections[k]->section_offset,
+ fi->code_sections[k]->section_size,
+ fi->code_sections[k]->load_address);
+ }
+
+ if (fi->symtab != NULL)
+ printf ("symtab:\n %s (%#lx), %d, %#lx, %#lx, %#lx\n",
+ fi->symtab->section_name,
+ fi->symtab->section_index,
+ fi->symtab->section_type,
+ fi->symtab->section_offset,
+ fi->symtab->section_size,
+ fi->symtab->load_address);
+
+ if (fi->strtab != NULL)
+ printf ("strtab:\n %s (%#lx), %d, %#lx, %#lx, %#lx\n",
+ fi->strtab->section_name,
+ fi->strtab->section_index,
+ fi->strtab->section_type,
+ fi->strtab->section_offset,
+ fi->strtab->section_size,
+ fi->strtab->load_address);
+ }
+}
+
+
+/* elf_read_strtab
+ * Read the string table from the object file.
+ */
+char *
+elf_read_strtab (struct file_info *fi)
+{
+ char *strtab;
+
+ if (fi->strtab == NULL) return (NULL);
+
+ fseek (fi->fp, fi->strtab->section_offset, SEEK_SET);
+
+ strtab = xmalloc (fi->strtab->section_size);
+
+ d_read (strtab, sizeof (char), fi->strtab->section_size, fi->fp, 1);
+
+ return strtab;
+}
+
+
+/* elf_get_symbol_type
+ * Translate a symbol's type into the internal format.
+ */
+enum symbol_type
+elf_get_symbol_type (struct file_info *fi, unsigned char info)
+{
+ unsigned char bind, type;
+ enum symbol_type stype = UNKNOWN_SYMBOL;
+
+ if (fi->bit_size == BS_32)
+ {
+ bind = ELF32_ST_BIND (info);
+ type = ELF32_ST_TYPE (info);
+ }
+ else
+ {
+ bind = ELF64_ST_BIND (info);
+ type = ELF64_ST_TYPE (info);
+ }
+
+ if (bind == STB_LOCAL && type == STT_OBJECT)
+ stype = LOCAL_DATA;
+ else if (bind == STB_LOCAL && type == STT_FUNC)
+ stype = LOCAL_FUNCTION;
+ else if (bind == STB_GLOBAL && type == STT_OBJECT)
+ stype = GLOBAL_DATA;
+ else if (bind == STB_GLOBAL && type == STT_FUNC)
+ stype = GLOBAL_FUNCTION;
+ else if (bind == STB_GLOBAL)
+ stype = GLOBAL_UNKNOWN;
+ else if (bind == STB_LOCAL)
+ stype = LOCAL_UNKNOWN;
+ else if (type == STT_OBJECT)
+ stype = UNKNOWN_DATA;
+ else if (type == STT_FUNC)
+ stype = UNKNOWN_FUNCTION;
+ else
+ stype = UNKNOWN_SYMBOL;
+
+ return (stype);
+}
+
+/* elf_get_next_symbol
+ * Read the next symbol from the object file and return it as a struct symtab.
+ */
+struct symtab *
+elf_get_next_symbol (struct file_info *fi, char *strtab)
+{
+ if (fi->bit_size == BS_32)
+ return elf32_get_next_symbol (fi, strtab);
+ else
+ return elf64_get_next_symbol (fi, strtab);
+}
diff --git a/decomp/error.c b/decomp/error.c
new file mode 100644
index 0000000..b78af3c
--- /dev/null
+++ b/decomp/error.c
@@ -0,0 +1,55 @@
+/* error.c
+ * This file is part of Decomp - a decompiler. In this file are
+ * various error routines and the message table used by
+ * error_out ().
+ *
+ * Copyright (C) 2001, Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started around 10 November 2001.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "decomp.h"
+
+char *message_table[] = {
+ "internal error",
+ "need input file name",
+ "unable to get information on input file",
+ "unable to deallocate resources used by input file",
+ "unable to open a file",
+ "unable to read input file",
+ "invalid input file",
+ "unrecognized file format",
+ "unable to read entire section",
+};
+
+
+/* panic
+ * A library function failed that really shouldn't have and to try
+ * to continue would be senseless.
+ */
+void
+panic (long line, char *file)
+{
+ fprintf (stderr, "%s: PANIC at %ld of %s: %s\n", pname, line, file,
+ strerror (errno));
+ abort ();
+}
+
+
+/* error_out
+ * Some kind of error occurred which isn't necessarily disastrous, but
+ * it would be kind of hard to continue.
+ */
+void
+error_out_internal (int error_index, long where, char *location)
+{
+ fprintf (stderr, "%s: %s at %ld in %s%s%s\n", pname,
+ message_table[error_index], where, location,
+ (errno != 0) ? ": " : "", (errno != 0) ? strerror (errno) : "");
+ exit (EXIT_FAILURE);
+}
diff --git a/decomp/fileinfo.c b/decomp/fileinfo.c
new file mode 100644
index 0000000..86115d0
--- /dev/null
+++ b/decomp/fileinfo.c
@@ -0,0 +1,234 @@
+/* fileinfo.c
+ * This file is part of decomp - a disassembler. This file contains
+ * routines for getting information about the input file and
+ * mapping the relevant sections for later use.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started around 15 November 2001.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <elf.h>
+
+#include "decomp.h"
+
+
+/* these three functions are used for printing out debug information */
+
+/* bit_size
+ * Translate an enum bs into a string.
+ */
+char *
+bit_size (enum bs size)
+{
+ switch (size)
+ {
+ case BS_16: return "16";
+ case BS_32: return "32";
+ case BS_64: return "64";
+ default:
+ ;
+ }
+
+ return "??";
+}
+
+/* file_type
+ * Translate an enum file_type into a string.
+ */
+char *
+file_type (enum file_type ft)
+{
+ switch (ft)
+ {
+ case FT_ELF: return "ELF";
+ case FT_MZ: return "MS-DOS Executable";
+ case FT_NE: return "Win16 New Executable";
+ case FT_PE: return "Win32 Portable Executable";
+ default:
+ ;
+ }
+
+ return "unknown";
+}
+
+/* arch_name
+ * Translate an enum mach_type into a string.
+ */
+char *
+arch_name (enum mach_type machine)
+{
+ switch (machine)
+ {
+ case MT_IA32: return "IA-32";
+ case MT_ALPHA: return "AXP Alpha";
+ default:
+ ;
+ }
+
+ return "unknown";
+}
+
+
+/* general file info stuff */
+
+
+/* get_file_type
+ * Determine the type of a file so that the proper module can be
+ * called to parse the file. get_file_type assumes that FP is
+ * positioned at the start of the file.
+ */
+enum file_type
+get_file_type (FILE *fp)
+{
+ char signature[4];
+ uint32_t addr;
+ enum file_type type = FT_UNK;
+
+ if (fread (signature, sizeof (char), 4, fp) < 4) error_out (ERR_FILE_READ);
+
+ if (!strncmp (signature, ELFMAG, 4)) /* ELF */
+ type = FT_ELF;
+ /* I'll add the next two in some other time */
+/* else if (!strncmp (signature, "AOUT", 4)) ; */
+/* else if (!strncmp (signature, "COM", 3)) ; */
+ else if (!strncmp (signature, "MZ", 2)) /* win/dos */
+ {
+ /* read the offset to the PE/NE header, if any */
+ fseek (fp, 0x3c, SEEK_SET);
+ fread (&addr, 4, 1, fp);
+ fseek (fp, addr, SEEK_SET);
+
+ /* read the PE/NE header, if any */
+ fread (signature, sizeof (char), 4, fp);
+
+ if (!strncmp (signature, "PE\0\0", 4)) /* PE file */
+ type = FT_PE;
+ else if (!strncmp (signature, "NE", 2)) /* NE file */
+ type = FT_NE;
+ else
+ type = FT_MZ; /* vanilla MS-DOS executable */
+ }
+
+ return type;
+}
+
+
+/* get_file_info
+ * Opens FILE for reading and uses the information to populate
+ * FI. Returns 0 if everything is OK, 1 otherwise.
+ */
+int
+get_file_info (struct file_info *fi, const char *file)
+{
+ struct stat buf;
+
+ fi->symtab = NULL;
+ fi->strtab = NULL;
+
+ fi->file_name = xmalloc (strlen (file) + 1);
+ strcpy (fi->file_name, file);
+
+ fi->fp = fopen (file, "rb");
+ if (fi->fp == NULL) error_out (ERR_FILE_OPEN);
+
+ fi->file_type = get_file_type (fi->fp);
+
+ stat (fi->file_name, &buf);
+ fi->file_size = buf.st_size;
+
+ /* call the appropriate routine based on the type of executable */
+ switch (fi->file_type)
+ {
+ case FT_ELF:
+ elf_get_file_info (fi);
+ break;
+ case FT_PE:
+ pe_get_file_info (fi);
+ break;
+ case FT_NE:
+ ne_get_file_info (fi);
+ break;
+ case FT_MZ:
+ mz_get_file_info (fi);
+ break;
+ default:
+ error_out (ERR_FILE_TYPE);
+ }
+
+ if (debug)
+ printf ("file information for %s:\n"
+ " %ld bytes\n"
+ " %s bit %s on %s\n"
+ " load address %08lx\n",
+ fi->file_name, fi->file_size, bit_size (fi->bit_size),
+ file_type (fi->file_type), arch_name (fi->arch),
+ fi->load_address);
+
+ return 0; /* just return OK for now */
+}
+
+
+/* clean_up_file
+ * Clean up the data in FI.
+ */
+int
+clean_up_file (struct file_info *fi)
+{
+ int k;
+ int retval = 0;
+
+ xfree (fi->file_name);
+
+ if (fclose (fi->fp) == -1) PANIC;
+
+ k = -1;
+ while (fi->data_sections[++k]) xfree (fi->data_sections[k]);
+ xfree (fi->data_sections);
+
+ k = -1;
+ while (fi->code_sections[++k]) xfree (fi->code_sections[k]);
+ xfree (fi->code_sections);
+
+ if (fi->symtab != NULL) xfree (fi->symtab);
+ if (fi->strtab != NULL) xfree (fi->strtab);
+
+ memset (fi, 0, sizeof (struct file_info));
+
+ return (retval);
+}
+
+
+/* alloc_section_info
+ * Allocate a struct section info and populate it with the provided data.
+ */
+struct section_info *
+alloc_section_info (char *name, enum section_type type, unsigned long offset,
+ unsigned long size, unsigned long entsize,
+ unsigned long index, unsigned long addr, hash_t symtab,
+ char *flags, unsigned int align)
+{
+ struct section_info *si;
+
+ si = xmalloc (sizeof (struct section_info));
+
+ si->section_name = name;
+ si->section_type = type;
+ si->section_offset = offset;
+ si->section_size = size;
+ si->entsize = entsize;
+ si->section_index = index;
+ si->load_address = addr;
+ si->symtab = symtab;
+ si->flags = flags;
+ si->align = align;
+
+ return si;
+}
diff --git a/decomp/foo.S b/decomp/foo.S
new file mode 100644
index 0000000..6e46b7f
--- /dev/null
+++ b/decomp/foo.S
@@ -0,0 +1,8684 @@
+ ; foo.S
+ ; Decompiled by Decomp from /windows/windows/sol.exe.
+ ; In case of an incorrect decompilation, let the author know.
+
+
+ .section .codeSection0, @progbits
+ .align 0
+
+ jc L0 ; 00940008 7265
+ jnc L1 ; 0094000a 7320
+ dec bp ; 0094000c 4d
+ imul sp, [bp + di + 0x72], 0x736f ; 0094000d 6963726f73
+ outsw ; 00940012 6f
+ o32 jz L2 ; 00940013 667420
+ push di ; 00940016 57
+ imul bp, [bp + 0x64], 0x776f ; 00940017 696e646f77
+ jnc L3 ; 0094001c 732e
+ or ax, 0x240a ; 0094001e 0d0a24
+ add [bx + si], al ; 00940021 0000
+ add [bx + si], al ; 00940023 0000
+ add [bx + si], al ; 00940025 0000
+ add [bp + 0x45], cl ; 00940027 004e45
+ add ax, 0x1e3c ; 0094002a 053c1e
+ add ax, 0x01 ; 0094002d 050100
+ add [bx + si], al ; 00940030 0000
+ add [bx + si], al ; 00940032 0000
+ add al, [bp + di] ; 00940034 0203
+
+L2:
+ or ax, [bx + si] ; 00940036 0b00
+ add [bx + si], dl ; 00940038 0010
+ add [bx + si], dl ; 0094003a 0010
+ xchg ax, sp ; 0094003c 94
+ add [bx + si], cl ; 0094003d 0008
+ add [bx + si], al ; 0094003f 0000
+ add [bp + di], cl ; 00940041 000b
+ add [bp + di], cl ; 00940043 000b
+ add [si], al ; 00940045 0004
+ add [bx], dl ; 00940047 0017
+ add [bx + si + 0], al ; 00940049 004000
+ cbw ; 0094004c 98
+ add al, bh ; 0094004d 00f8
+ add al, 0xff ; 0094004f 04ff
+ add al, 0x7 ; 00940051 0407
+ add ax, 0x59f ; 00940053 059f05
+ add [bx + si], al ; 00940056 0000
+ add [bx + si], al ; 00940058 0000
+ add al, 0x0 ; 0094005a 0400
+ add [bx + si], al ; 0094005c 0000
+ add cl, [bx + si] ; 0094005e 0208
+ pop si ; 00940060 5e
+ add L4, bl ; 00940061 001e0100
+ add [bx + si], al ; 00940065 0000
+ add al, 0x60 ; 00940067 0460
+ add [si], cl ; 00940069 000c
+ or si, [bx + si + 0x1d] ; 0094006b 0b701d
+ or al, 0xb ; 0094006e 0c0b
+ jl L5 ; 00940070 7c01
+ or ax, [bx] ; 00940072 0b07
+ xor [di], bl ; 00940074 301d
+ or al, 0x7 ; 00940076 0c07
+ test word [bx + di], 0xb3c ; 00940078 f7013c0b
+ xor [di], bl ; 0094007c 301d
+ cmp al, 0xb ; 0094007e 3c0b
+ mov ah, 0x2 ; 00940080 b402
+ ill_grp_4 ; 00940082 fe16301d
+ ill_grp_4 ; 00940086 fe162e04
+ imul cx, [bx], 0x30 ; 0094008a 6b0f30
+ sbb ax, 0xf6c ; 0094008d 1d6c0f
+ sub ax, [di] ; 00940090 2b05
+ test [bx + si], al ; 00940092 8400
+ xor [di], bl ; 00940094 301d
+ test [bx + si], al ; 00940096 8400
+ xor ax, 0x5005 ; 00940098 350550
+ add al, 0x30 ; 0094009b 0430
+ sbb ax, 0x450 ; 0094009d 1d5004
+ sub al, L4 ; 009400a0 2c01
+ lodsb ; 009400a2 ac
+ add [bx + si + 0x1d], si ; 009400a3 01701d
+ lodsb ; 009400a6 ac
+ add [bp + 0xffffd805], ax ; 009400a7 018605d8
+ add dh, [bx + si] ; 009400ab 0230
+ sbb ax, 0x2d8 ; 009400ad 1dd802
+ mov si, 0xb805 ; 009400b0 be05b8
+ or [bx + si], dh ; 009400b3 0830
+ sbb ax, 0x8b8 ; 009400b5 1db808
+ dec sp ; 009400b8 4c
+ add [bp + 0x5102], si ; 009400b9 01b60251
+ or al, 0xb6 ; 009400bd 0cb6
+ add al, [si] ; 009400bf 0204
+ add L6, cl ; 009400c1 000e8001
+ add [bx + si], al ; 009400c5 0000
+ add [bx + si], al ; 009400c7 0000
+ add [bp + si + 0x6], dl ; 009400c9 005206
+ add ax, [bx + si] ; 009400cc 0300
+ xor [si], bl ; 009400ce 301c
+ pop sp ; 009400d0 5c
+ add al, 0x0 ; 009400d1 0400
+ add [bx + si], al ; 009400d3 0000
+ add [bp + si], al ; 009400d5 0002
+ or byte [bp + si + 0], 0x0 ; 009400d7 804a0000
+ add [bx + si], al ; 009400db 0000
+ add [di + 0x6], dl ; 009400dd 005506
+ fld [bx + si] ; 009400e0 dd00
+ xor [si], bl ; 009400e2 301c
+ ss add byte ss:[bx + si], 0x0 ; 009400e4 36800000
+ add [bx + si], al ; 009400e8 0000
+ xor al, [bx] ; 009400ea 3207
+ fld [bx + si] ; 009400ec dd00
+ xor [si], bl ; 009400ee 301c
+ aaa ; 009400f0 37
+ add byte [bx + si], 0x0 ; 009400f1 800000
+ add [bx + si], al ; 009400f4 0000
+ invd ; 009400f6 0f08
+ fadd [bx + si] ; 009400f8 dc00
+ xor [si], bl ; 009400fa 301c
+ cmp [bx + si + 0], al ; 009400fc 38800000
+ add [bx + si], al ; 00940100 0000
+ jmp short L7 ; 00940102 eb08
+ fild [bx + si] ; 00940104 df00
+ xor [si], bl ; 00940106 301c
+ cmp [bx + si + 0], ax ; 00940108 39800000
+ add [bx + si], al ; 0094010c 0000
+ retf 0xdc09 ; 0094010e ca09dc
+ add [bx + si], dh ; 00940111 0030
+ sbb al, 0x3a ; 00940113 1c3a
+ add byte [bx + si], 0x0 ; 00940115 800000
+ add [bx + si], al ; 00940118 0000
+ cmpsb ; 0094011a a6
+ or bl, ah ; 0094011b 0adc
+ add [bx + si], dh ; 0094011d 0030
+ sbb al, 0x3b ; 0094011f 1c3b
+ add byte [bx + si], 0x0 ; 00940121 800000
+ add [bx + si], al ; 00940124 0000
+ or byte [bp + di], 0xdd ; 00940126 820bdd
+ add [bx + si], dh ; 00940129 0030
+ sbb al, 0x3c ; 0094012b 1c3c
+ add byte [bx + si], 0x0 ; 0094012d 800000
+ add [bx + si], al ; 00940130 0000
+ pop di ; 00940132 5f
+ or al, 0xdd ; 00940133 0cdd
+ add [bx + si], dh ; 00940135 0030
+ sbb al, 0x3d ; 00940137 1c3d
+ add byte [bx + si], 0x0 ; 00940139 800000
+ add [bx + si], al ; 0094013c 0000
+ cmp al, 0xd ; 0094013e 3c0d
+ fadd [bx + si] ; 00940140 dc00
+ xor [si], bl ; 00940142 301c
+ ds add byte ds:[bx + si], 0x0 ; 00940144 3e800000
+ add [bx + si], al ; 00940148 0000
+ sbb L8, cl ; 0094014a 180edc00
+ xor [si], bl ; 0094014e 301c
+ aas ; 00940150 3f
+ add byte [bx + si], 0x0 ; 00940151 800000
+ add [bx + si], al ; 00940154 0000
+ hlt ; 00940156 f4
+ push cs ; 00940157 0e
+ fadd [bx + si] ; 00940158 dc00
+ xor [si], bl ; 0094015a 301c
+ inc ax ; 0094015c 40
+ add byte [bx + si], 0x0 ; 0094015d 800000
+ add [bx + si], al ; 00940160 0000
+ ror byte [bx], 1 ; 00940162 d00f
+ fadd [bx + si] ; 00940164 dc00
+ xor [si], bl ; 00940166 301c
+ inc cx ; 00940168 41
+ add byte [bx + si], 0x0 ; 00940169 800000
+ add [bx + si], al ; 0094016c 0000
+ lodsb ; 0094016e ac
+ adc [bp + si + 0], cl ; 0094016f 104a00
+ xor [si], bl ; 00940172 301c
+ xor ax, 0x80 ; 00940174 358000
+ add [bx + si], al ; 00940177 0000
+ add dh, dh ; 00940179 00f6
+ adc [bp + si], bl ; 0094017b 101a
+ add [bx + si], dh ; 0094017d 0030
+ sbb al, 0xa6 ; 0094017f 1ca6
+ add byte [bx + si], 0x0 ; 00940181 820000
+ add [bx + si], al ; 00940184 0000
+ adc [bx + di], dl ; 00940186 1011
+ sbb al, [bx + si] ; 00940188 1a00
+ xor [si], bl ; 0094018a 301c
+ cmpsw ; 0094018c a7
+ add byte [bx + si], 0x0 ; 0094018d 820000
+ add [bx + si], al ; 00940190 0000
+ sub dl, [bx + di] ; 00940192 2a11
+ adc [bx + si], al ; 00940194 1000
+ xor [si], bl ; 00940196 301c
+ test al, 0x82 ; 00940198 a882
+ add [bx + si], al ; 0094019a 0000
+ add [bx + si], al ; 0094019c 0000
+ cmp dl, [bx + di] ; 0094019e 3a11
+ or al, [bx + si] ; 009401a0 0a00
+ xor [si], bl ; 009401a2 301c
+ test ax, 0x82 ; 009401a4 a98200
+ add [bx + si], al ; 009401a7 0000
+ add [si + 0x11], al ; 009401a9 004411
+ or al, [bx + si] ; 009401ac 0a00
+ xor [si], bl ; 009401ae 301c
+ stosb ; 009401b0 aa
+ add byte [bx + si], 0x0 ; 009401b1 820000
+ add [bx + si], al ; 009401b4 0000
+ dec si ; 009401b6 4e
+ adc [bx + di], cx ; 009401b7 1109
+ add [bx + si], dh ; 009401b9 0030
+ sbb al, 0xab ; 009401bb 1cab
+ add byte [bx + si], 0x0 ; 009401bd 820000
+ add [bx + si], al ; 009401c0 0000
+ push di ; 009401c2 57
+ adc [bx + di], cx ; 009401c3 1109
+ add [bx + si], dh ; 009401c5 0030
+ sbb al, 0xac ; 009401c7 1cac
+ add byte [bx + si], 0x0 ; 009401c9 820000
+ add [bx + si], al ; 009401cc 0000
+ pusha ; 009401ce 60
+ adc [bp + si + 0], cx ; 009401cf 114a00
+ xor [si], bl ; 009401d2 301c
+ add [bx + si + 0], ax ; 009401d4 01800000
+ add [bx + si], al ; 009401d8 0000
+ stosb ; 009401da aa
+ adc [bp + si + 0], cx ; 009401db 114a00
+ xor [si], bl ; 009401de 301c
+ add al, [bx + si + 0] ; 009401e0 02800000
+ add [bx + si], al ; 009401e4 0000
+ hlt ; 009401e6 f4
+ adc [bp + si + 0], cx ; 009401e7 114a00
+ xor [si], bl ; 009401ea 301c
+ add ax, [bx + si + 0] ; 009401ec 03800000
+ add [bx + si], al ; 009401f0 0000
+ ds adc cl, ds:[bp + si + 0] ; 009401f2 3e124a00
+ xor [si], bl ; 009401f6 301c
+ add al, 0x80 ; 009401f8 0480
+ add [bx + si], al ; 009401fa 0000
+ add [bx + si], al ; 009401fc 0000
+ mov [bp + si], dl ; 009401fe 8812
+ dec dx ; 00940200 4a
+ add [bx + si], dh ; 00940201 0030
+ sbb al, 0x5 ; 00940203 1c05
+ add byte [bx + si], 0x0 ; 00940205 800000
+ add [bx + si], al ; 00940208 0000
+ rcl byte [bp + si], cl ; 0094020a d212
+ dec dx ; 0094020c 4a
+ add [bx + si], dh ; 0094020d 0030
+ sbb al, 0x6 ; 0094020f 1c06
+ add byte [bx + si], 0x0 ; 00940211 800000
+ add [bx + si], al ; 00940214 0000
+ sbb al, 0x13 ; 00940216 1c13
+ dec dx ; 00940218 4a
+ add [bx + si], dh ; 00940219 0030
+ sbb al, 0x7 ; 0094021b 1c07
+ add byte [bx + si], 0x0 ; 0094021d 800000
+ add [bx + si], al ; 00940220 0000
+ o32 adc ecx, [bp + si + 0] ; 00940222 66134a00
+ xor [si], bl ; 00940226 301c
+ or [bx + si + 0], al ; 00940228 08800000
+ add [bx + si], al ; 0094022c 0000
+ mov al, 0x13 ; 0094022e b013
+ dec dx ; 00940230 4a
+ add [bx + si], dh ; 00940231 0030
+ sbb al, 0x9 ; 00940233 1c09
+ add byte [bx + si], 0x0 ; 00940235 800000
+ add [bx + si], al ; 00940238 0000
+ cli ; 0094023a fa
+ adc cx, [bp + si + 0] ; 0094023b 134a00
+ xor [si], bl ; 0094023e 301c
+ or al, [bx + si + 0] ; 00940240 0a800000
+ add [bx + si], al ; 00940244 0000
+ inc sp ; 00940246 44
+ adc al, 0xdd ; 00940247 14dd
+ add [bx + si], dh ; 00940249 0030
+ sbb al, 0xb ; 0094024b 1c0b
+ add byte [bx + si], 0x0 ; 0094024d 800000
+ add [bx + si], al ; 00940250 0000
+ and [di], dx ; 00940252 2115
+ fld [bx + si] ; 00940254 dd00
+ xor [si], bl ; 00940256 301c
+ or al, 0x80 ; 00940258 0c80
+ add [bx + si], al ; 0094025a 0000
+ add [bx + si], al ; 0094025c 0000
+ ill_grp_4 ; 0094025e fe15
+ fld [bx + si] ; 00940260 dd00
+ xor [si], bl ; 00940262 301c
+ or ax, 0x80 ; 00940264 0d8000
+ add [bx + si], al ; 00940267 0000
+ add bl, bl ; 00940269 00db
+ push ss ; 0094026b 16
+ dec bx ; 0094026c 4b
+ add [bx + si], dh ; 0094026d 0030
+ sbb al, 0xe ; 0094026f 1c0e
+ add byte [bx + si], 0x0 ; 00940271 800000
+ add [bx + si], al ; 00940274 0000
+ es pop ss ; 00940276 2617
+ dec bx ; 00940278 4b
+ add [bx + si], dh ; 00940279 0030
+ sbb al, 0xf ; 0094027b 1c0f
+ add byte [bx + si], 0x0 ; 0094027d 800000
+ add [bx + si], al ; 00940280 0000
+ jno L9 ; 00940282 7117
+ dec bx ; 00940284 4b
+ add [bx + si], dh ; 00940285 0030
+ sbb al, 0x10 ; 00940287 1c10
+ add byte [bx + si], 0x0 ; 00940289 800000
+ add [bx + si], al ; 0094028c 0000
+ mov sp, 0x4b17 ; 0094028e bc174b
+ add [bx + si], dh ; 00940291 0030
+ sbb al, 0x11 ; 00940293 1c11
+ add byte [bx + si], 0x0 ; 00940295 800000
+ add [bx + si], al ; 00940298 0000
+ pop es ; 0094029a 07
+ sbb [bp + di + 0], cl ; 0094029b 184b00
+ xor [si], bl ; 0094029e 301c
+ adc al, [bx + si + 0] ; 009402a0 12800000
+ add [bx + si], al ; 009402a4 0000
+ push dx ; 009402a6 52
+ sbb [bp + di + 0], cl ; 009402a7 184b00
+ xor [si], bl ; 009402aa 301c
+ adc ax, [bx + si + 0] ; 009402ac 13800000
+ add [bx + si], al ; 009402b0 0000
+ popf ; 009402b2 9d
+ sbb [bp + di + 0], cl ; 009402b3 184b00
+ xor [si], bl ; 009402b6 301c
+ adc al, 0x80 ; 009402b8 1480
+ add [bx + si], al ; 009402ba 0000
+ add [bx + si], al ; 009402bc 0000
+ call L10 ; 009402be e8184b
+ add [bx + si], dh ; 009402c1 0030
+ sbb al, 0x15 ; 009402c3 1c15
+ add byte [bx + si], 0x0 ; 009402c5 800000
+ add [bx + si], al ; 009402c8 0000
+ xor bx, [bx + di] ; 009402ca 3319
+ dec bx ; 009402cc 4b
+ add [bx + si], dh ; 009402cd 0030
+ sbb al, 0x16 ; 009402cf 1c16
+ add byte [bx + si], 0x0 ; 009402d1 800000
+ add [bx + si], al ; 009402d4 0000
+ jle L11 ; 009402d6 7e19
+ dec bx ; 009402d8 4b
+ add [bx + si], dh ; 009402d9 0030
+ sbb al, 0x17 ; 009402db 1c17
+ add byte [bx + si], 0x0 ; 009402dd 800000
+ add [bx + si], al ; 009402e0 0000
+ leave ; 009402e2 c9
+ sbb bp, bx ; 009402e3 19dd
+ add [bx + si], dh ; 009402e5 0030
+ sbb al, 0x18 ; 009402e7 1c18
+ add byte [bx + si], 0x0 ; 009402e9 800000
+ add [bx + si], al ; 009402ec 0000
+ cmpsb ; 009402ee a6
+ sbb bl, ch ; 009402ef 1add
+ add [bx + si], dh ; 009402f1 0030
+ sbb al, 0x19 ; 009402f3 1c19
+ add byte [bx + si], 0x0 ; 009402f5 800000
+ add [bx + si], al ; 009402f8 0000
+ sbb word [bp + di], byte 0xdd ; 009402fa 831bdd
+ add [bx + si], dh ; 009402fd 0030
+ sbb al, 0x1a ; 009402ff 1c1a
+ add byte [bx + si], 0x0 ; 00940301 800000
+ add [bx + si], al ; 00940304 0000
+ pusha ; 00940306 60
+ sbb al, 0x4b ; 00940307 1c4b
+ add [bx + si], dh ; 00940309 0030
+ sbb al, 0x1b ; 0094030b 1c1b
+ add byte [bx + si], 0x0 ; 0094030d 800000
+ add [bx + si], al ; 00940310 0000
+ stosw ; 00940312 ab
+ sbb al, 0x4b ; 00940313 1c4b
+ add [bx + si], dh ; 00940315 0030
+ sbb al, 0x1c ; 00940317 1c1c
+ add byte [bx + si], 0x0 ; 00940319 800000
+ add [bx + si], al ; 0094031c 0000
+ neg byte [si] ; 0094031e f61c
+ dec bx ; 00940320 4b
+ add [bx + si], dh ; 00940321 0030
+ sbb al, 0x1d ; 00940323 1c1d
+ add byte [bx + si], 0x0 ; 00940325 800000
+ add [bx + si], al ; 00940328 0000
+ inc cx ; 0094032a 41
+ sbb ax, 0x4b ; 0094032b 1d4b00
+ xor [si], bl ; 0094032e 301c
+ push ds ; 00940330 1e
+ add byte [bx + si], 0x0 ; 00940331 800000
+ add [bx + si], al ; 00940334 0000
+ mov word [di], ds ; 00940336 8c1d
+ dec bx ; 00940338 4b
+ add [bx + si], dh ; 00940339 0030
+ sbb al, 0x1f ; 0094033b 1c1f
+ add byte [bx + si], 0x0 ; 0094033d 800000
+ add [bx + si], al ; 00940340 0000
+ xlatb ; 00940342 d7
+ sbb ax, 0x4b ; 00940343 1d4b00
+ xor [si], bl ; 00940346 301c
+ and [bx + si + 0], al ; 00940348 20800000
+ add [bx + si], al ; 0094034c 0000
+ and bl, L12 ; 0094034e 221e4b00
+ xor [si], bl ; 00940352 301c
+ and [bx + si + 0], ax ; 00940354 21800000
+ add [bx + si], al ; 00940358 0000
+ insw ; 0094035a 6d
+ push ds ; 0094035b 1e
+ dec bx ; 0094035c 4b
+ add [bx + si], dh ; 0094035d 0030
+ sbb al, 0x22 ; 0094035f 1c22
+ add byte [bx + si], 0x0 ; 00940361 800000
+ add [bx + si], al ; 00940364 0000
+ mov ax, 0x4b1e ; 00940366 b81e4b
+ add [bx + si], dh ; 00940369 0030
+ sbb al, 0x23 ; 0094036b 1c23
+ add byte [bx + si], 0x0 ; 0094036d 800000
+ add [bx + si], al ; 00940370 0000
+ add bx, [bx] ; 00940372 031f
+ dec bx ; 00940374 4b
+ add [bx + si], dh ; 00940375 0030
+ sbb al, 0x24 ; 00940377 1c24
+ add byte [bx + si], 0x0 ; 00940379 800000
+ add [bx + si], al ; 0094037c 0000
+ dec si ; 0094037e 4e
+ pop ds ; 0094037f 1f
+ fld [bx + si] ; 00940380 dd00
+ xor [si], bl ; 00940382 301c
+ and ax, 0x80 ; 00940384 258000
+ add [bx + si], al ; 00940387 0000
+ add [bp + di], ch ; 00940389 002b
+ and ch, bl ; 0094038b 20dd
+ add [bx + si], dh ; 0094038d 0030
+ sbb al, 0x26 ; 0094038f 1c26
+ add byte [bx + si], 0x0 ; 00940391 800000
+ add [bx + si], al ; 00940394 0000
+ or [bx + di], ah ; 00940396 0821
+ fld [bx + si] ; 00940398 dd00
+ xor [si], bl ; 0094039a 301c
+ daa ; 0094039c 27
+ add byte [bx + si], 0x0 ; 0094039d 800000
+ add [bx + si], al ; 009403a0 0000
+ in ax, 0x21 ; 009403a2 e521
+ dec dx ; 009403a4 4a
+ add [bx + si], dh ; 009403a5 0030
+ sbb al, 0x28 ; 009403a7 1c28
+ add byte [bx + si], 0x0 ; 009403a9 800000
+ add [bx + si], al ; 009403ac 0000
+ das ; 009403ae 2f
+ and cl, [bp + si + 0] ; 009403af 224a00
+ xor [si], bl ; 009403b2 301c
+ sub [bx + si + 0], ax ; 009403b4 29800000
+ add [bx + si], al ; 009403b8 0000
+ jns L13 ; 009403ba 7922
+ dec dx ; 009403bc 4a
+ add [bx + si], dh ; 009403bd 0030
+ sbb al, 0x2a ; 009403bf 1c2a
+ add byte [bx + si], 0x0 ; 009403c1 800000
+ add [bx + si], al ; 009403c4 0000
+ ret ; 009403c6 c3
+ and cl, [bp + si + 0] ; 009403c7 224a00
+ xor [si], bl ; 009403ca 301c
+ sub ax, [bx + si + 0] ; 009403cc 2b800000
+ add [bx + si], al ; 009403d0 0000
+ or ax, 0x4a23 ; 009403d2 0d234a
+ add [bx + si], dh ; 009403d5 0030
+ sbb al, L1 ; 009403d7 1c2c
+ add byte [bx + si], 0x0 ; 009403d9 800000
+ add [bx + si], al ; 009403dc 0000
+ push di ; 009403de 57
+ and cx, [bp + si + 0] ; 009403df 234a00
+ xor [si], bl ; 009403e2 301c
+ sub ax, 0x80 ; 009403e4 2d8000
+ add [bx + si], al ; 009403e7 0000
+ add [bx + di + 0x4a23], ah ; 009403e9 00a1234a
+ add [bx + si], dh ; 009403ed 0030
+ sbb al, 0x2e ; 009403ef 1c2e
+ add byte [bx + si], 0x0 ; 009403f1 800000
+ add [bx + si], al ; 009403f4 0000
+ jmp short L14 ; 009403f6 eb23
+ dec dx ; 009403f8 4a
+ add [bx + si], dh ; 009403f9 0030
+ sbb al, 0x2f ; 009403fb 1c2f
+ add byte [bx + si], 0x0 ; 009403fd 800000
+ add [bx + si], al ; 00940400 0000
+ xor ax, 0x4a24 ; 00940402 35244a
+ add [bx + si], dh ; 00940405 0030
+ sbb al, 0x30 ; 00940407 1c30
+ add byte [bx + si], 0x0 ; 00940409 800000
+ add [bx + si], al ; 0094040c 0000
+ jg L15 ; 0094040e 7f24
+ dec dx ; 00940410 4a
+ add [bx + si], dh ; 00940411 0030
+ sbb al, 0x31 ; 00940413 1c31
+ add byte [bx + si], 0x0 ; 00940415 800000
+ add [bx + si], al ; 00940418 0000
+ leave ; 0094041a c9
+ and al, 0xdd ; 0094041b 24dd
+ add [bx + si], dh ; 0094041d 0030
+ sbb al, 0x32 ; 0094041f 1c32
+ add byte [bx + si], 0x0 ; 00940421 800000
+ add [bx + si], al ; 00940424 0000
+ cmpsb ; 00940426 a6
+ and ax, 0xdd ; 00940427 25dd00
+ xor [si], bl ; 0094042a 301c
+ xor ax, [bx + si + 0] ; 0094042c 33800000
+ add [bx + si], al ; 00940430 0000
+ and word L16, byte 0x30 ; 00940432 8326dd0030
+ sbb al, 0x34 ; 00940437 1c34
+ add byte [bx + si], 0x0 ; 00940439 800000
+ add [bx + si], al ; 0094043c 0000
+ pusha ; 0094043e 60
+ daa ; 0094043f 27
+ fadd [bx + si] ; 00940440 dc00
+ xor [si], bl ; 00940442 301c
+ inc sp ; 00940444 44
+ add byte [bx + si], 0x0 ; 00940445 800000
+ add [bx + si], al ; 00940448 0000
+ cmp al, 0x28 ; 0094044a 3c28
+ fadd [bx + si] ; 0094044c dc00
+ xor [si], bl ; 0094044e 301c
+ inc bx ; 00940450 43
+ add byte [bx + si], 0x0 ; 00940451 800000
+ add [bx + si], al ; 00940454 0000
+ add al, 0x80 ; 00940456 0480
+ add [bx + si], ax ; 00940458 0100
+ add [bx + si], al ; 0094045a 0000
+ add [bx + si], al ; 0094045c 0000
+ sbb [bx + di], ch ; 0094045e 1829
+ or [bx + si], ax ; 00940460 0900
+ xor [si], bl ; 00940462 301c
+ add [bx + si + 0], ax ; 00940464 01800000
+ add [bx + si], al ; 00940468 0000
+ add ax, 0x280 ; 0094046a 058002
+ add [bx + si], al ; 0094046d 0000
+ add [bx + si], al ; 0094046f 0000
+ add [bx + di], ah ; 00940471 0021
+ sub [bp + di], dx ; 00940473 2913
+ add [bx + si], dh ; 00940475 0030
+ sbb al, 0x65 ; 00940477 1c65
+ add byte [bx + si], 0x0 ; 00940479 800000
+ add [bx + si], al ; 0094047c 0000
+ xor al, 0x29 ; 0094047e 3429
+ sbb [bx + si], al ; 00940480 1800
+ xor [si], bl ; 00940482 301c
+ a16 add byte [eax], 0x0 ; 00940484 67800000
+ add [bx + si], al ; 00940488 0000
+ push es ; 0094048a 06
+ add byte [bx], 0x0 ; 0094048b 800700
+ add [bx + si], al ; 0094048e 0000
+ add [bx + si], al ; 00940490 0000
+ dec sp ; 00940492 4c
+ sub [bp + si], cx ; 00940493 290a
+ add [bx + si], dh ; 00940495 0030
+ sbb al, 0x7 ; 00940497 1c07
+ add byte [bx + si], 0x0 ; 00940499 800000
+ add [bx + si], al ; 0094049c 0000
+ push si ; 0094049e 56
+ sub [si], ax ; 0094049f 2904
+ add [bx + si], dh ; 009404a1 0030
+ sbb al, 0xd ; 009404a3 1c0d
+ add byte [bx + si], 0x0 ; 009404a5 800000
+ add [bx + si], al ; 009404a8 0000
+ pop dx ; 009404aa 5a
+ sub L17, cx ; 009404ab 290e0030
+ sbb al, 0x13 ; 009404af 1c13
+ add byte [bx + si], 0x0 ; 009404b1 800000
+ add [bx + si], al ; 009404b4 0000
+ push 0x729 ; 009404b6 682907
+ add [bx + si], dh ; 009404b9 0030
+ sbb al, 0x3f ; 009404bb 1c3f
+ add byte [bx + si], 0x0 ; 009404bd 800000
+ add [bx + si], al ; 009404c0 0000
+ outsw ; 009404c2 6f
+ sub [si], ax ; 009404c3 2904
+ add [bx + si], dh ; 009404c5 0030
+ sbb al, 0x0 ; 009404c7 1c00
+ nop ; 009404c9 90
+ add [bx + si], al ; 009404ca 0000
+ add [bx + si], al ; 009404cc 0000
+ jnc L18 ; 009404ce 7329
+ add al, 0x0 ; 009404d0 0400
+ xor [si], bl ; 009404d2 301c
+ add ax, [bx + si + 0] ; 009404d4 03800000
+ add [bx + si], al ; 009404d8 0000
+ ja L19 ; 009404da 7729
+ add al, [bx + si] ; 009404dc 0200
+ xor [si], bl ; 009404de 301c
+ jle L20 ; 009404e0 7e80
+ add [bx + si], al ; 009404e2 0000
+ add [bx + si], al ; 009404e4 0000
+ adc [bx + si + 0x1], al ; 009404e6 10800100
+ add [bx + si], al ; 009404ea 0000
+ add [bx + si], al ; 009404ec 0000
+ jns L21 ; 009404ee 7929
+ push ds ; 009404f0 1e
+ add [bx + si], dh ; 009404f1 0030
+ or al, L4 ; 009404f3 0c01
+ add byte [bx + si], 0x0 ; 009404f5 800000
+ add [bx + si], al ; 009404f8 0000
+ add ax, [bx + si + 0x2] ; 009404fa 03800200
+ add [bx + si], al ; 009404fe 0000
+ add [bx + si], al ; 00940500 0000
+ xchg ax, di ; 00940502 97
+ sub [bx], bp ; 00940503 292f
+ add [bx + si], dl ; 00940505 0010
+ sbb al, L4 ; 00940507 1c01
+ add byte [bx + si], 0x0 ; 00940509 800000
+ add [bx + si], al ; 0094050c 0000
+ mov byte [bx + di], 0x13 ; 0094050e c62913
+ add [bx + si], dl ; 00940511 0010
+ sbb al, 0x2 ; 00940513 1c02
+ add byte [bx + si], 0x0 ; 00940515 800000
+ add [bx + si], al ; 00940518 0000
+ add [bx + si], al ; 0094051a 0000
+ add dx, [bp + di + 0x4f] ; 0094051c 03534f
+ dec sp ; 0094051f 4c
+ add dx, [bp + di + 0x4f] ; 00940520 03534f
+ dec sp ; 00940523 4c
+ add [bx + si], al ; 00940524 0000
+ add [bx + di], al ; 00940526 0001
+ add [bx + si], cl ; 00940528 0008
+ add [di], cl ; 0094052a 000d
+ add [bx + di], dl ; 0094052c 0011
+ add [bx + si], al ; 0094052e 0000
+ push es ; 00940530 06
+ dec bx ; 00940531 4b
+ inc bp ; 00940532 45
+ push dx ; 00940533 52
+ dec si ; 00940534 4e
+ inc bp ; 00940535 45
+ dec sp ; 00940536 4c
+ add al, 0x55 ; 00940537 0455
+ push bx ; 00940539 53
+ inc bp ; 0094053a 45
+ push dx ; 0094053b 52
+ add ax, [bx + 0x44] ; 0094053c 034744
+ dec cx ; 0094053f 49
+ add ax, 0x4853 ; 00940540 055348
+ inc bp ; 00940543 45
+ dec sp ; 00940544 4c
+ dec sp ; 00940545 4c
+ add [bp + di], dl ; 00940546 0013
+ dec bp ; 00940548 4d
+ imul sp, [bp + di + 0x72], 0x736f ; 00940549 6963726f73
+ outsw ; 0094054e 6f
+ o32 jz L22 ; 0094054f 667420
+ push bx ; 00940552 53
+ outsw ; 00940553 6f
+ insb ; 00940554 6c
+ imul si, [si + 0x61], 0x7269 ; 00940555 6974616972
+ gs add gs:[bx + si], al ; 0094055a 650000
+ add [bx + si], al ; 0094055d 0000
+ add [bx + si], al ; 0094055f 0000
+ add [bx + si], al ; 00940561 0000
+ add [bx + si], al ; 00940563 0000
+ add [bx + si], al ; 00940565 0000
+ add [bx + si], al ; 00940567 0000
+ add [bx + si], al ; 00940569 0000
+ add [bx + si], al ; 0094056b 0000
+ add [bx + si], al ; 0094056d 0000
+ add [bx + si], al ; 0094056f 0000
+ add [bx + si], al ; 00940571 0000
+ add [bx + si], al ; 00940573 0000
+ add [bx + si], al ; 00940575 0000
+ add [bx + si], al ; 00940577 0000
+ add [bx + si], al ; 00940579 0000
+ add [bx + si], al ; 0094057b 0000
+ add [bx + si], al ; 0094057d 0000
+ add [bx + si], al ; 0094057f 0000
+ add [bx + si], al ; 00940581 0000
+ add [bx + si], al ; 00940583 0000
+ add [bx + si], al ; 00940585 0000
+ add [bx + si], al ; 00940587 0000
+ add [bx + si], al ; 00940589 0000
+ add [bx + si], al ; 0094058b 0000
+ add [bx + si], al ; 0094058d 0000
+ add [bx + si], al ; 0094058f 0000
+ add [bx + si], al ; 00940591 0000
+ add [bx + si], al ; 00940593 0000
+ add [bx + si], al ; 00940595 0000
+ add [bx + si], al ; 00940597 0000
+ add [bx + si], al ; 00940599 0000
+ add [bx + si], al ; 0094059b 0000
+ add [bx + si], al ; 0094059d 0000
+ add [bx + si], al ; 0094059f 0000
+ add [bx + si], al ; 009405a1 0000
+ add [bx + si], al ; 009405a3 0000
+ add [bx + si], al ; 009405a5 0000
+ add al, cl ; 009405a7 00c8
+ sbb [bx + si], al ; 009405a9 1800
+ add [bp + di + 0xc7e], al ; 009405ab 00837e0c
+ add [si + 0x55], dh ; 009405af 007455
+ push word [bp + 0xc] ; 009405b2 ff760c
+ push 0x1f0 ; 009405b5 68f001
+ push 0x2 ; 009405b8 6a02
+ callf ; 009405ba 9affff0000
+ push word L23 ; 009405bf ff36f001
+ callf ; 009405c3 9affff0000
+ mov [bp + 0xffffffec], ax ; 009405c8 8946ec
+ push word L23 ; 009405cb ff36f001
+ push 0x0 ; 009405cf 6a00
+ push 0x0 ; 009405d1 6a00
+ push 0x0 ; 009405d3 6a00
+ push 0x0 ; 009405d5 6a00
+ push 0x0 ; 009405d7 6a00
+ push 0x43 ; 009405d9 6a43
+ callf ; 009405db 9affff0000
+ push word L23 ; 009405e0 ff36f001
+ callf ; 009405e4 9affff0000
+ or ax, ax ; 009405e9 0bc0
+ jz L24 ; 009405eb 740d
+ push word L23 ; 009405ed ff36f001
+ push 0x9 ; 009405f1 6a09
+ callf ; 009405f3 9affff0000
+ jmp short L25 ; 009405f8 eb08
+ push word [bp + 0xffffffec] ; 009405fa ff76ec
+ callf ; 009405fd 9affff0000
+ xor ax, ax ; 00940602 33c0
+ jmp L26 ; 00940604 e98200
+ o32 push dword [bp + 0xc] ; 00940607 66ff760c
+ o32 push dword [bp + 0x8] ; 0094060b 66ff7608
+ push word [bp + 0x6] ; 0094060f ff7606
+ push cs ; 00940612 0e
+ call L27 ; 00940613 e87800
+ or ax, ax ; 00940616 0bc0
+ jz L25 ; 00940618 74e8
+ push 0x29 ; 0094061a 6a29
+ callf ; 0094061c 9affff0000
+ push ax ; 00940621 50
+ push ds ; 00940622 1e
+ push 0x3c ; 00940623 683c00
+ callf ; 00940626 9affff0000
+ mov [bp + 0xffffffe8], ax ; 0094062b 8946e8
+ mov [bp + 0xffffffea], dx ; 0094062e 8956ea
+ or dx, ax ; 00940631 0bd0
+ jz L28 ; 00940633 7407
+ push L4 ; 00940635 6a01
+ push L4 ; 00940637 6a01
+ call far oword [bp + 0xffffffe8] ; 00940639 ff5ee8
+ lea ax, [bp + 0xffffffee] ; 0094063c 8d46ee
+ push ss ; 0094063f 16
+ push ax ; 00940640 50
+ push 0x0 ; 00940641 6a00
+ push 0x0 ; 00940643 6a00
+ push 0x0 ; 00940645 6a00
+ callf ; 00940647 9ac8000000
+ or ax, ax ; 0094064c 0bc0
+ jz L29 ; 0094064e 7428
+ lea ax, [bp + 0xffffffee] ; 00940650 8d46ee
+ push ss ; 00940653 16
+ push ax ; 00940654 50
+ callf ; 00940655 9affff0000
+ lea ax, [bp + 0xffffffee] ; 0094065a 8d46ee
+ push ss ; 0094065d 16
+ push ax ; 0094065e 50
+ callf ; 0094065f 9affff0000
+ lea ax, [bp + 0xffffffee] ; 00940664 8d46ee
+ push ss ; 00940667 16
+ push ax ; 00940668 50
+ push 0x0 ; 00940669 6a00
+ push 0x0 ; 0094066b 6a00
+ push 0x0 ; 0094066d 6a00
+ callf ; 0094066f 9affff0000
+ or ax, ax ; 00940674 0bc0
+ jnz L30 ; 00940676 75d8
+ o32 cmp dword [bp + 0xffffffe8], byte 0x0 ; 00940678 66837ee800
+ jz L31 ; 0094067d 7407
+ push L4 ; 0094067f 6a01
+ push 0x0 ; 00940681 6a00
+ call far oword [bp + 0xffffffe8] ; 00940683 ff5ee8
+ mov ax, [bp + 0xfffffff2] ; 00940686 8b46f2
+ leave ; 00940689 c9
+ retf 0x0a ; 0094068a ca0a00
+ nop ; 0094068d 90
+ enter 0x72, 0x0 ; 0094068e c8720000
+ mov ax, [bp + 0xe] ; 00940692 8b460e
+ mov [0x2b0], ax ; 00940695 a3b002
+ push 0x200 ; 00940698 680002
+ push 0x12c ; 0094069b 682c01
+ callf ; 0094069e 9a2806d401
+ push ds ; 009406a3 1e
+ push 0x268 ; 009406a4 686802
+ push ds ; 009406a7 1e
+ push 0x26a ; 009406a8 686a02
+ callf ; 009406ab 9a0000ffff
+ or ax, ax ; 009406b0 0bc0
+ jz L32 ; 009406b2 741d
+ push 0x0 ; 009406b4 6a00
+ push 0x0 ; 009406b6 6a00
+ push 0x7f00 ; 009406b8 68007f
+ callf ; 009406bb 9affff0000
+ mov [bp + 0xffffffb4], ax ; 009406c0 8946b4
+ push 0x0 ; 009406c3 6a00
+ callf ; 009406c5 9affff0000
+ mov [bp + 0xffffffd8], ax ; 009406ca 8946d8
+ or ax, ax ; 009406cd 0bc0
+ jnz L33 ; 009406cf 7503
+ jmp L34 ; 009406d1 e99802
+ push ax ; 009406d4 50
+ lea ax, [bp + 0xffffffb8] ; 009406d5 8d46b8
+ push ss ; 009406d8 16
+ push ax ; 009406d9 50
+ callf ; 009406da 9affff0000
+ mov ax, [bp + 0xffffffb8] ; 009406df 8b46b8
+ mov [0x23e], ax ; 009406e2 a33e02
+ mov ax, [bp + 0xffffffc4] ; 009406e5 8b46c4
+ mov [0x23c], ax ; 009406e8 a33c02
+ push word [bp + 0xffffffd8] ; 009406eb ff76d8
+ push 0x18 ; 009406ee 6a18
+ callf ; 009406f0 9a5e010000
+ cmp ax, 0x02 ; 009406f5 3d0200
+ jnz L35 ; 009406f8 7506
+ mov word L36, L4 ; 009406fa c706f6010100
+ push word [bp + 0xffffffd8] ; 00940700 ff76d8
+ push 0x8 ; 00940703 6a08
+ callf ; 00940705 9a6b010000
+ mov [0x24c], ax ; 0094070a a34c02
+ push word [bp + 0xffffffd8] ; 0094070d ff76d8
+ push 0xa ; 00940710 6a0a
+ callf ; 00940712 9affff0000
+ mov [0x24e], ax ; 00940717 a34e02
+ cmp ax, 0x12c ; 0094071a 3d2c01
+ jge L37 ; 0094071d 7d05
+ mov ax, L4 ; 0094071f b80100
+ jmp short L38 ; 00940722 eb02
+ xor ax, ax ; 00940724 33c0
+ mov [0x38], ax ; 00940726 a33800
+ or ax, ax ; 00940729 0bc0
+ jz L39 ; 0094072b 740c
+ mov cx, 0x02 ; 0094072d b90200
+ mov ax, [0x26a] ; 00940730 a16a02
+ cwd ; 00940733 99
+ idiv cx, ax ; 00940734 f7f9
+ mov [0x26a], ax ; 00940736 a36a02
+ push 0x0 ; 00940739 6a00
+ push word [bp + 0xffffffd8] ; 0094073b ff76d8
+ callf ; 0094073e 9affff0000
+ cmp word L36, byte 0x0 ; 00940743 833ef60100
+ jz L40 ; 00940748 7408
+ mov ax, 0xffff ; 0094074a b8ffff
+ mov dx, 0xff ; 0094074d baff00
+ jmp short L41 ; 00940750 eb05
+ mov ax, 0x8000 ; 00940752 b80080
+ xor dx, dx ; 00940755 33d2
+ mov [0x2b2], ax ; 00940757 a3b202
+ mov L42, dx ; 0094075a 8916b402
+ push dx ; 0094075e 52
+ push ax ; 0094075f 50
+ callf ; 00940760 9affff0000
+ mov [0x266], ax ; 00940765 a36602
+ callf ; 00940768 9affff0000
+ push ax ; 0094076d 50
+ callf ; 0094076e 9a3201ffff
+ pop bx ; 00940773 5b
+ push 0x26e ; 00940774 686e02
+ push 0x64 ; 00940777 6a64
+ callf ; 00940779 9a2806de01
+ push 0x250 ; 0094077e 685002
+ push 0x65 ; 00940781 6a65
+ callf ; 00940783 9a2806e901
+ lea ax, [bp + 0xffffff98] ; 00940788 8d4698
+ push ax ; 0094078b 50
+ push 0x67 ; 0094078c 6a67
+ callf ; 0094078e 9a2806ffff
+ lea ax, [bp + 0xffffff98] ; 00940793 8d4698
+ push ss ; 00940796 16
+ push ax ; 00940797 50
+ callf ; 00940798 9affff0000
+ mov [0x1f8], ax ; 0094079d a3f801
+ mov word [bp + 0xffffffb2], 0x00 ; 009407a0 c746b20000
+ o32 mov eax, [bp + 0x8] ; 009407a5 668b4608
+ mov dx, [bp + 0xa] ; 009407a9 8b560a
+ o32 mov [bp + 0xffffffae], eax ; 009407ac 668946ae
+ mov es, dx ; 009407b0 8ec2
+ mov bx, ax ; 009407b2 8bd8
+ es cmp byte es:[bx], 0x0 ; 009407b4 26803f00
+ jz L43 ; 009407b8 7420
+ es cmp byte es:[bx], 0x2f ; 009407ba 26803f2f
+ jnz L44 ; 009407be 7507
+ es cmp byte es:[bx + 0x1], 0x49 ; 009407c0 26807f0149
+ jz L45 ; 009407c5 740e
+ inc word [bp + 0xffffffae] ; 009407c7 ff46ae
+ mov bx, [bp + 0xffffffae] ; 009407ca 8b5eae
+ es cmp byte es:[bx], 0x0 ; 009407cd 26803f00
+ jnz L46 ; 009407d1 75e7
+ jmp short L43 ; 009407d3 eb05
+ mov word [bp + 0xffffffb2], L4 ; 009407d5 c746b20100
+ cmp word [bp + 0xc], byte 0x0 ; 009407da 837e0c00
+ jnz L47 ; 009407de 7556
+ mov word [bp + 0xffffffe6], 0x2008 ; 009407e0 c746e60820
+ mov word [bp + 0xffffffe8], 0x40c ; 009407e5 c746e80c04
+ mov word [bp + 0xffffffea], 0xffff ; 009407ea c746eaffff
+ o32 mov dword [bp + 0xffffffec], 0x0000 ; 009407ef 66c746ec00000000
+ mov ax, [0x2b0] ; 009407f7 a1b002
+ mov [bp + 0xfffffff0], ax ; 009407fa 8946f0
+ push ax ; 009407fd 50
+ push ds ; 009407fe 1e
+ push L12 ; 009407ff 684b00
+ callf ; 00940802 9affff0000
+ mov [bp + 0xfffffff2], ax ; 00940807 8946f2
+ mov ax, [bp + 0xffffffb4] ; 0094080a 8b46b4
+ mov [bp + 0xfffffff4], ax ; 0094080d 8946f4
+ mov ax, [0x266] ; 00940810 a16602
+ mov [bp + 0xfffffff6], ax ; 00940813 8946f6
+ o32 mov dword [bp + 0xfffffff8], L4 ; 00940816 66c746f801000000
+ mov word [bp + 0xfffffffc], 0x22 ; 0094081e c746fc2200
+ mov word [bp + 0xfffffffe], ds ; 00940823 8c5efe
+ lea ax, [bp + 0xffffffe6] ; 00940826 8d46e6
+ push ss ; 00940829 16
+ push ax ; 0094082a 50
+ callf ; 0094082b 9affff0000
+ or ax, ax ; 00940830 0bc0
+ je L34 ; 00940832 0f843601
+ mov ax, [0x268] ; 00940836 a16802
+ imul cx, ax, 0x7 ; 00940839 6bc807
+ cwd ; 0094083c 99
+ and dx, byte 0x7 ; 0094083d 83e207
+ add ax, dx ; 00940840 03c2
+ sar ax, byte 0x3 ; 00940842 c1f803
+ add ax, 0x03 ; 00940845 050300
+ mov [0x240], ax ; 00940848 a34002
+ shl ax, byte 0x3 ; 0094084b c1e003
+ add cx, ax ; 0094084e 03c8
+ mov [bp + 0xffffff92], cx ; 00940850 894e92
+ mov ax, [0x26a] ; 00940853 a16a02
+ shl ax, byte 0x2 ; 00940856 c1e002
+ mov [bp + 0xffffff94], ax ; 00940859 894694
+ o32 mov dword [bp + 0xffffff8e], 0x0000 ; 0094085c 66c7468e00000000
+ lea ax, [bp + 0xffffff8e] ; 00940864 8d468e
+ push ss ; 00940867 16
+ push ax ; 00940868 50
+ push 0xcf ; 00940869 68cf00
+ push 0x0 ; 0094086c 6a00
+ push L4 ; 0094086e 6a01
+ push 0x0 ; 00940870 6a00
+ push 0x200 ; 00940872 680002
+ callf ; 00940875 9affff0000
+ mov ax, [bp + 0xffffff8e] ; 0094087a 8b468e
+ sub [bp + 0xffffff92], ax ; 0094087d 294692
+ mov ax, [0x24e] ; 00940880 a14e02
+ mov cx, [bp + 0xffffff90] ; 00940883 8b4e90
+ sub [bp + 0xffffff94], cx ; 00940886 294e94
+ cmp [bp + 0xffffff94], ax ; 00940889 394694
+ jle L48 ; 0094088c 7e03
+ mov [bp + 0xffffff94], ax ; 0094088e 894694
+ push 0x0 ; 00940891 6a00
+ push 0x200 ; 00940893 680002
+ push ds ; 00940896 1e
+ push 0x22 ; 00940897 682200
+ push ds ; 0094089a 1e
+ push 0x26e ; 0094089b 686e02
+ cmp word [bp + 0xffffffb2], byte 0x0 ; 0094089e 837eb200
+ jz L49 ; 009408a2 7407
+ xor ax, ax ; 009408a4 33c0
+ mov dx, 0x22cf ; 009408a6 bacf22
+ jmp short L50 ; 009408a9 eb05
+ xor ax, ax ; 009408ab 33c0
+ mov dx, 0x2cf ; 009408ad bacf02
+ push dx ; 009408b0 52
+ push ax ; 009408b1 50
+ push 0x8000 ; 009408b2 680080
+ push ax ; 009408b5 50
+ push word [bp + 0xffffff92] ; 009408b6 ff7692
+ push word [bp + 0xffffff94] ; 009408b9 ff7694
+ push ax ; 009408bc 50
+ push ax ; 009408bd 50
+ push word L51 ; 009408be ff36b002
+ push ax ; 009408c2 50
+ push ax ; 009408c3 50
+ callf ; 009408c4 9affff0000
+ or ax, ax ; 009408c9 0bc0
+ je L34 ; 009408cb 0f849d00
+ lea ax, [bp + 0xffffffac] ; 009408cf 8d46ac
+ push ax ; 009408d2 50
+ push cs ; 009408d3 0e
+ call L52 ; 009408d4 e8d105
+ push 0x245 ; 009408d7 684502
+ push 0x85a ; 009408da 685a08
+ push word [bp + 0xe] ; 009408dd ff760e
+ callf ; 009408e0 9affff0000
+ mov [0x1f2], ax ; 009408e5 a3f201
+ mov L53, dx ; 009408e8 8916f401
+ mov ax, dx ; 009408ec 8bc2
+ or ax, L54 ; 009408ee 0b06f201
+ jz L55 ; 009408f2 747d
+ push word L23 ; 009408f4 ff36f001
+ o32 push 0x29a00fa ; 009408f8 6668fa009a02
+ push dx ; 009408fe 52
+ push word L54 ; 009408ff ff36f201
+ callf ; 00940903 9affff0000
+ or ax, ax ; 00940908 0bc0
+ jz L34 ; 0094090a 7460
+ callf ; 0094090c 9a24026f03
+ push word [bp + 0xffffffac] ; 00940911 ff76ac
+ callf ; 00940914 9ac6000b05
+ push word L23 ; 00940919 ff36f001
+ push word [bp + 0x6] ; 0094091d ff7606
+ callf ; 00940920 9a4c000000
+ push word L23 ; 00940925 ff36f001
+ callf ; 00940929 9affff0000
+ cmp word [bp + 0xc], L4 ; 0094092e 837e0c01
+ sbb ax, ax ; 00940932 1bc0
+ neg ax ; 00940934 f7d8
+ push ax ; 00940936 50
+ callf ; 00940937 9a00009e03
+ cmp word L1, byte 0x0 ; 0094093c 833e2c0000
+ jz L56 ; 00940941 7405
+ callf ; 00940943 9a6600ffff
+ cmp word [bp + 0x6], byte 0x7 ; 00940948 837e0607
+ jz L57 ; 0094094c 7419
+ cmp word [bp + 0x6], byte 0x6 ; 0094094e 837e0606
+ jz L57 ; 00940952 7413
+ push word L23 ; 00940954 ff36f001
+ o32 push 0x11103e8 ; 00940958 6668e8031101
+ push 0x0 ; 0094095e 6a00
+ push 0x0 ; 00940960 6a00
+ callf ; 00940962 9acb040000
+ mov ax, L4 ; 00940967 b80100
+ jmp short L58 ; 0094096a eb07
+ callf ; 0094096c 9a1806f900
+ xor ax, ax ; 00940971 33c0
+ leave ; 00940973 c9
+ retf 0x0a ; 00940974 ca0a00
+ nop ; 00940977 90
+ enter 0x20, 0x0 ; 00940978 c8200000
+ push word [bp + 0x6] ; 0094097c ff7606
+ lea ax, [bp + 0xffffffe0] ; 0094097f 8d46e0
+ push ss ; 00940982 16
+ push ax ; 00940983 50
+ callf ; 00940984 9affff0000
+ cmp word L59, byte 0x0 ; 00940989 833e180000
+ jz L60 ; 0094098e 7412
+ push word L59 ; 00940990 ff361800
+ push 0x7 ; 00940994 6a07
+ lea ax, [bp + 0xffffffe0] ; 00940996 8d46e0
+ push ax ; 00940999 50
+ push 0x0 ; 0094099a 6a00
+ mov bx, L59 ; 0094099c 8b1e1800
+ call far oword [bx] ; 009409a0 ff1f
+ push word [bp + 0x6] ; 009409a2 ff7606
+ lea ax, [bp + 0xffffffe0] ; 009409a5 8d46e0
+ push ss ; 009409a8 16
+ push ax ; 009409a9 50
+ callf ; 009409aa 9affff0000
+ leave ; 009409af c9
+ retf 0x02 ; 009409b0 ca0200
+ nop ; 009409b3 90
+ enter 0xd6, 0x0 ; 009409b4 c8d60000
+ mov ax, [bp + 0xc] ; 009409b8 8b460c
+ dec ax ; 009409bb 48
+ je L61 ; 009409bc 0f84bf00
+ dec ax ; 009409c0 48
+ je L62 ; 009409c1 0f84c300
+ dec ax ; 009409c5 48
+ je L63 ; 009409c6 0f846a01
+ dec ax ; 009409ca 48
+ dec ax ; 009409cb 48
+ je L64 ; 009409cc 0f84f400
+ dec ax ; 009409d0 48
+ je L65 ; 009409d1 0f846701
+ dec ax ; 009409d5 48
+ je L66 ; 009409d6 0f848701
+ dec ax ; 009409da 48
+ je L67 ; 009409db 0f846f01
+ sub ax, 0x07 ; 009409df 2d0700
+ je L68 ; 009409e2 0f848901
+ dec ax ; 009409e6 48
+ je L69 ; 009409e7 0f849901
+ sub ax, 0xf0 ; 009409eb 2df000
+ je L70 ; 009409ee 0f84b401
+ sub ax, 0x11 ; 009409f2 2d1100
+ je L71 ; 009409f5 0f84c101
+ sub ax, 0x05 ; 009409f9 2d0500
+ je L72 ; 009409fc 0f845302
+ sub ax, 0x09 ; 00940a00 2d0900
+ je L73 ; 00940a03 0f84dc02
+ sub ax, 0xe1 ; 00940a07 2de100
+ je L74 ; 00940a0a 0f840303
+ dec ax ; 00940a0e 48
+ je L75 ; 00940a0f 0f840f03
+ dec ax ; 00940a13 48
+ je L76 ; 00940a14 0f842303
+ dec ax ; 00940a18 48
+ je L77 ; 00940a19 0f843403
+ mov ax, [0x1f8] ; 00940a1d a1f801
+ cmp [bp + 0xc], ax ; 00940a20 39460c
+ jne L78 ; 00940a23 0f855403
+ mov ax, [bp + 0xa] ; 00940a27 8b460a
+ dec ax ; 00940a2a 48
+ jz L79 ; 00940a2b 7409
+ dec ax ; 00940a2d 48
+ jz L80 ; 00940a2e 7410
+ dec ax ; 00940a30 48
+ jz L81 ; 00940a31 7431
+ jmp L78 ; 00940a33 e94503
+ mov ax, [0x268] ; 00940a36 a16802
+ mov dx, L82 ; 00940a39 8b166a02
+ jmp L83 ; 00940a3d e94b03
+ les bx, ; 00940a40 c45e0626ff3726
+ push word [bx + 0x2] ; 00940a47 ff7702
+ es push word es:[bx + 0x4] ; 00940a4a 26ff7704
+ es push word es:[bx + 0x6] ; 00940a4e 26ff7706
+ es push word es:[bx + 0x8] ; 00940a52 26ff7708
+ o32 push dword es:[bx + 0xa] ; 00940a56 6626ff770a
+ callf ; 00940a5b 9a5a031005
+ cwd ; 00940a60 99
+ jmp L83 ; 00940a61 e92703
+ push word L23 ; 00940a64 ff36f001
+ o32 push 0x112f060 ; 00940a68 666860f01201
+ push 0x0 ; 00940a6e 6a00
+ push 0x0 ; 00940a70 6a00
+ callf ; 00940a72 9affff0000
+ mov ax, L4 ; 00940a77 b80100
+ xor dx, dx ; 00940a7a 33d2
+ jmp L83 ; 00940a7c e90c03
+ mov ax, [bp + 0xe] ; 00940a7f 8b460e
+ mov [0x1f0], ax ; 00940a82 a3f001
+ jmp L78 ; 00940a85 e9f302
+ push word L23 ; 00940a88 ff36f001
+ push 0x29a ; 00940a8c 689a02
+ callf ; 00940a8f 9affff0000
+ o32 push dword L54 ; 00940a94 66ff36f201
+ callf ; 00940a99 9affff0000
+ push word L59 ; 00940a9e ff361800
+ push L4 ; 00940aa2 6a01
+ push 0x0 ; 00940aa4 6a00
+ push 0x0 ; 00940aa6 6a00
+ mov bx, L59 ; 00940aa8 8b1e1800
+ call far oword [bx] ; 00940aac ff1f
+ push L4 ; 00940aae 6a01
+ callf ; 00940ab0 9ac600ffff
+ callf ; 00940ab5 9a78080601
+ push 0x0 ; 00940aba 6a00
+ callf ; 00940abc 9affff0000
+ jmp L78 ; 00940ac1 e9b702
+ push word [bp + 0xe] ; 00940ac4 ff760e
+ callf ; 00940ac7 9a3d000000
+ mov [0x14], ax ; 00940acc a31400
+ push word [bp + 0xe] ; 00940acf ff760e
+ push ds ; 00940ad2 1e
+ push 0x244 ; 00940ad3 684402
+ callf ; 00940ad6 9affff0000
+ imul ax, L84, 0x7 ; 00940adb 6b06680207
+ sub ax, [bp + 0x6] ; 00940ae0 2b4606
+ neg ax ; 00940ae3 f7d8
+ cwd ; 00940ae5 99
+ and dx, byte 0x7 ; 00940ae6 83e207
+ add ax, dx ; 00940ae9 03c2
+ sar ax, byte 0x3 ; 00940aeb c1f803
+ mov [bp + 0xffffff92], ax ; 00940aee 894692
+ mov ax, [0x268] ; 00940af1 a16802
+ cwd ; 00940af4 99
+ and dx, byte 0x7 ; 00940af5 83e207
+ add ax, dx ; 00940af8 03c2
+ sar ax, byte 0x3 ; 00940afa c1f803
+ add ax, 0x03 ; 00940afd 050300
+ mov [bp + 0xffffff90], ax ; 00940b00 894690
+ cmp [bp + 0xffffff92], ax ; 00940b03 394692
+ jge L85 ; 00940b06 7d0e
+ mov ax, [0x240] ; 00940b08 a14002
+ cmp [bp + 0xffffff90], ax ; 00940b0b 394690
+ jz L85 ; 00940b0e 7406
+ mov ax, [bp + 0xffffff90] ; 00940b10 8b4690
+ mov [bx + si], ax ; 00940b13 8900
+
+ .section .codeSection1, @progbits
+ .align 0
+
+ add [bx + si], al ; 00940009 0000
+ or byte [bp + di], L16 ; 0094000b 820bdd
+ add [bx + si], dh ; 0094000e 0030
+ sbb al, 0x3c ; 00940010 1c3c
+ add byte [bx + si], 0x0 ; 00940012 800000
+ add [bx + si], al ; 00940015 0000
+ pop di ; 00940017 5f
+ or al, L16 ; 00940018 0cdd
+ add [bx + si], dh ; 0094001a 0030
+ sbb al, 0x3d ; 0094001c 1c3d
+ add byte [bx + si], 0x0 ; 0094001e 800000
+ add [bx + si], al ; 00940021 0000
+ cmp al, 0xd ; 00940023 3c0d
+ fadd [bx + si] ; 00940025 dc00
+ xor [si], bl ; 00940027 301c
+ ds add byte ds:[bx + si], 0x0 ; 00940029 3e800000
+ add [bx + si], al ; 0094002d 0000
+ sbb L8, cl ; 0094002f 180edc00
+ xor [si], bl ; 00940033 301c
+ aas ; 00940035 3f
+
+L2:
+ add byte [bx + si], 0x0 ; 00940036 800000
+ add [bx + si], al ; 00940039 0000
+ hlt ; 0094003b f4
+ push cs ; 0094003c 0e
+ fadd [bx + si] ; 0094003d dc00
+ xor [si], bl ; 0094003f 301c
+ inc ax ; 00940041 40
+ add byte [bx + si], 0x0 ; 00940042 800000
+ add [bx + si], al ; 00940045 0000
+ ror byte [bx], 1 ; 00940047 d00f
+ fadd [bx + si] ; 00940049 dc00
+ xor [si], bl ; 0094004b 301c
+ inc cx ; 0094004d 41
+ add byte [bx + si], 0x0 ; 0094004e 800000
+ add [bx + si], al ; 00940051 0000
+ lodsb ; 00940053 ac
+ adc [bp + si + 0], cl ; 00940054 104a00
+ xor [si], bl ; 00940057 301c
+ xor ax, 0x80 ; 00940059 358000
+ add [bx + si], al ; 0094005c 0000
+ add dh, dh ; 0094005e 00f6
+ adc [bp + si], bl ; 00940060 101a
+ add [bx + si], dh ; 00940062 0030
+ sbb al, 0xa6 ; 00940064 1ca6
+ add byte [bx + si], 0x0 ; 00940066 820000
+ add [bx + si], al ; 00940069 0000
+ adc [bx + di], dl ; 0094006b 1011
+ sbb al, [bx + si] ; 0094006d 1a00
+ xor [si], bl ; 0094006f 301c
+ cmpsw ; 00940071 a7
+ add byte [bx + si], 0x0 ; 00940072 820000
+ add [bx + si], al ; 00940075 0000
+ sub dl, [bx + di] ; 00940077 2a11
+ adc [bx + si], al ; 00940079 1000
+ xor [si], bl ; 0094007b 301c
+ test al, 0x82 ; 0094007d a882
+ add [bx + si], al ; 0094007f 0000
+ add [bx + si], al ; 00940081 0000
+ cmp dl, [bx + di] ; 00940083 3a11
+ or al, [bx + si] ; 00940085 0a00
+ xor [si], bl ; 00940087 301c
+ test ax, 0x82 ; 00940089 a98200
+ add [bx + si], al ; 0094008c 0000
+ add [si + 0x11], al ; 0094008e 004411
+ or al, [bx + si] ; 00940091 0a00
+ xor [si], bl ; 00940093 301c
+ stosb ; 00940095 aa
+ add byte [bx + si], 0x0 ; 00940096 820000
+ add [bx + si], al ; 00940099 0000
+ dec si ; 0094009b 4e
+ adc [bx + di], cx ; 0094009c 1109
+ add [bx + si], dh ; 0094009e 0030
+ sbb al, 0xab ; 009400a0 1cab
+ add byte [bx + si], 0x0 ; 009400a2 820000
+ add [bx + si], al ; 009400a5 0000
+ push di ; 009400a7 57
+ adc [bx + di], cx ; 009400a8 1109
+ add [bx + si], dh ; 009400aa 0030
+ sbb al, 0xac ; 009400ac 1cac
+ add byte [bx + si], 0x0 ; 009400ae 820000
+ add [bx + si], al ; 009400b1 0000
+ pusha ; 009400b3 60
+ adc [bp + si + 0], cx ; 009400b4 114a00
+ xor [si], bl ; 009400b7 301c
+ add [bx + si + 0], ax ; 009400b9 01800000
+ add [bx + si], al ; 009400bd 0000
+ stosb ; 009400bf aa
+ adc [bp + si + 0], cx ; 009400c0 114a00
+ xor [si], bl ; 009400c3 301c
+ add al, [bx + si + 0] ; 009400c5 02800000
+ add [bx + si], al ; 009400c9 0000
+ hlt ; 009400cb f4
+ adc [bp + si + 0], cx ; 009400cc 114a00
+ xor [si], bl ; 009400cf 301c
+ add ax, [bx + si + 0] ; 009400d1 03800000
+ add [bx + si], al ; 009400d5 0000
+ ds adc cl, ds:[bp + si + 0] ; 009400d7 3e124a00
+ xor [si], bl ; 009400db 301c
+ add al, 0x80 ; 009400dd 0480
+ add [bx + si], al ; 009400df 0000
+ add [bx + si], al ; 009400e1 0000
+ mov [bp + si], dl ; 009400e3 8812
+ dec dx ; 009400e5 4a
+ add [bx + si], dh ; 009400e6 0030
+ sbb al, 0x5 ; 009400e8 1c05
+ add byte [bx + si], 0x0 ; 009400ea 800000
+ add [bx + si], al ; 009400ed 0000
+ rcl byte [bp + si], cl ; 009400ef d212
+ dec dx ; 009400f1 4a
+ add [bx + si], dh ; 009400f2 0030
+ sbb al, 0x6 ; 009400f4 1c06
+ add byte [bx + si], 0x0 ; 009400f6 800000
+ add [bx + si], al ; 009400f9 0000
+ sbb al, 0x13 ; 009400fb 1c13
+ dec dx ; 009400fd 4a
+ add [bx + si], dh ; 009400fe 0030
+ sbb al, 0x7 ; 00940100 1c07
+ add byte [bx + si], 0x0 ; 00940102 800000
+ add [bx + si], al ; 00940105 0000
+ o32 adc ecx, [bp + si + 0] ; 00940107 66134a00
+ xor [si], bl ; 0094010b 301c
+ or [bx + si + 0], al ; 0094010d 08800000
+ add [bx + si], al ; 00940111 0000
+ mov al, 0x13 ; 00940113 b013
+ dec dx ; 00940115 4a
+ add [bx + si], dh ; 00940116 0030
+ sbb al, 0x9 ; 00940118 1c09
+ add byte [bx + si], 0x0 ; 0094011a 800000
+ add [bx + si], al ; 0094011d 0000
+ cli ; 0094011f fa
+ adc cx, [bp + si + 0] ; 00940120 134a00
+ xor [si], bl ; 00940123 301c
+ or al, [bx + si + 0] ; 00940125 0a800000
+ add [bx + si], al ; 00940129 0000
+ inc sp ; 0094012b 44
+ adc al, L16 ; 0094012c 14dd
+ add [bx + si], dh ; 0094012e 0030
+ sbb al, 0xb ; 00940130 1c0b
+ add byte [bx + si], 0x0 ; 00940132 800000
+ add [bx + si], al ; 00940135 0000
+ and [di], dx ; 00940137 2115
+ fld [bx + si] ; 00940139 dd00
+ xor [si], bl ; 0094013b 301c
+ or al, 0x80 ; 0094013d 0c80
+ add [bx + si], al ; 0094013f 0000
+ add [bx + si], al ; 00940141 0000
+ ill_grp_4 ; 00940143 fe15
+ fld [bx + si] ; 00940145 dd00
+ xor [si], bl ; 00940147 301c
+ or ax, 0x80 ; 00940149 0d8000
+ add [bx + si], al ; 0094014c 0000
+ add bl, bl ; 0094014e 00db
+ push ss ; 00940150 16
+ dec bx ; 00940151 4b
+ add [bx + si], dh ; 00940152 0030
+ sbb al, 0xe ; 00940154 1c0e
+ add byte [bx + si], 0x0 ; 00940156 800000
+ add [bx + si], al ; 00940159 0000
+ es pop ss ; 0094015b 2617
+ dec bx ; 0094015d 4b
+ add [bx + si], dh ; 0094015e 0030
+ sbb al, 0xf ; 00940160 1c0f
+ add byte [bx + si], 0x0 ; 00940162 800000
+ add [bx + si], al ; 00940165 0000
+ jno L6 ; 00940167 7117
+ dec bx ; 00940169 4b
+ add [bx + si], dh ; 0094016a 0030
+ sbb al, 0x10 ; 0094016c 1c10
+ add byte [bx + si], 0x0 ; 0094016e 800000
+ add [bx + si], al ; 00940171 0000
+ mov sp, 0x4b17 ; 00940173 bc174b
+ add [bx + si], dh ; 00940176 0030
+ sbb al, 0x11 ; 00940178 1c11
+ add byte [bx + si], 0x0 ; 0094017a 800000
+ add [bx + si], al ; 0094017d 0000
+ pop es ; 0094017f 07
+ sbb [bp + di + 0], cl ; 00940180 184b00
+ xor [si], bl ; 00940183 301c
+ adc al, [bx + si + 0] ; 00940185 12800000
+ add [bx + si], al ; 00940189 0000
+ push dx ; 0094018b 52
+ sbb [bp + di + 0], cl ; 0094018c 184b00
+ xor [si], bl ; 0094018f 301c
+ adc ax, [bx + si + 0] ; 00940191 13800000
+ add [bx + si], al ; 00940195 0000
+ popf ; 00940197 9d
+ sbb [bp + di + 0], cl ; 00940198 184b00
+ xor [si], bl ; 0094019b 301c
+ adc al, 0x80 ; 0094019d 1480
+ add [bx + si], al ; 0094019f 0000
+ add [bx + si], al ; 009401a1 0000
+ call L86 ; 009401a3 e8184b
+ add [bx + si], dh ; 009401a6 0030
+ sbb al, 0x15 ; 009401a8 1c15
+ add byte [bx + si], 0x0 ; 009401aa 800000
+ add [bx + si], al ; 009401ad 0000
+ xor bx, [bx + di] ; 009401af 3319
+ dec bx ; 009401b1 4b
+ add [bx + si], dh ; 009401b2 0030
+ sbb al, 0x16 ; 009401b4 1c16
+ add byte [bx + si], 0x0 ; 009401b6 800000
+ add [bx + si], al ; 009401b9 0000
+ jle L87 ; 009401bb 7e19
+ dec bx ; 009401bd 4b
+ add [bx + si], dh ; 009401be 0030
+ sbb al, 0x17 ; 009401c0 1c17
+ add byte [bx + si], 0x0 ; 009401c2 800000
+ add [bx + si], al ; 009401c5 0000
+ leave ; 009401c7 c9
+ sbb bp, bx ; 009401c8 19dd
+ add [bx + si], dh ; 009401ca 0030
+ sbb al, L59 ; 009401cc 1c18
+ add byte [bx + si], 0x0 ; 009401ce 800000
+ add [bx + si], al ; 009401d1 0000
+ cmpsb ; 009401d3 a6
+ sbb bl, ch ; 009401d4 1add
+ add [bx + si], dh ; 009401d6 0030
+ sbb al, 0x19 ; 009401d8 1c19
+ add byte [bx + si], 0x0 ; 009401da 800000
+ add [bx + si], al ; 009401dd 0000
+ sbb word [bp + di], L16 ; 009401df 831bdd
+ add [bx + si], dh ; 009401e2 0030
+ sbb al, 0x1a ; 009401e4 1c1a
+ add byte [bx + si], 0x0 ; 009401e6 800000
+ add [bx + si], al ; 009401e9 0000
+ pusha ; 009401eb 60
+ sbb al, L12 ; 009401ec 1c4b
+ add [bx + si], dh ; 009401ee 0030
+ sbb al, 0x1b ; 009401f0 1c1b
+ add byte [bx + si], 0x0 ; 009401f2 800000
+ add [bx + si], al ; 009401f5 0000
+ stosw ; 009401f7 ab
+ sbb al, L12 ; 009401f8 1c4b
+ add [bx + si], dh ; 009401fa 0030
+ sbb al, 0x1c ; 009401fc 1c1c
+ add byte [bx + si], 0x0 ; 009401fe 800000
+ add [bx + si], al ; 00940201 0000
+ neg byte [si] ; 00940203 f61c
+ dec bx ; 00940205 4b
+ add [bx + si], dh ; 00940206 0030
+ sbb al, 0x1d ; 00940208 1c1d
+ add byte [bx + si], 0x0 ; 0094020a 800000
+ add [bx + si], al ; 0094020d 0000
+ inc cx ; 0094020f 41
+ sbb ax, L12 ; 00940210 1d4b00
+ xor [si], bl ; 00940213 301c
+ push ds ; 00940215 1e
+ add byte [bx + si], 0x0 ; 00940216 800000
+ add [bx + si], al ; 00940219 0000
+ mov word [di], ds ; 0094021b 8c1d
+ dec bx ; 0094021d 4b
+ add [bx + si], dh ; 0094021e 0030
+ sbb al, 0x1f ; 00940220 1c1f
+ add byte [bx + si], 0x0 ; 00940222 800000
+ add [bx + si], al ; 00940225 0000
+ xlatb ; 00940227 d7
+ sbb ax, L12 ; 00940228 1d4b00
+ xor [si], bl ; 0094022b 301c
+ and [bx + si + 0], al ; 0094022d 20800000
+ add [bx + si], al ; 00940231 0000
+ and bl, L12 ; 00940233 221e4b00
+ xor [si], bl ; 00940237 301c
+ and [bx + si + 0], ax ; 00940239 21800000
+ add [bx + si], al ; 0094023d 0000
+ insw ; 0094023f 6d
+ push ds ; 00940240 1e
+ dec bx ; 00940241 4b
+ add [bx + si], dh ; 00940242 0030
+ sbb al, 0x22 ; 00940244 1c22
+ add byte [bx + si], 0x0 ; 00940246 800000
+ add [bx + si], al ; 00940249 0000
+ mov ax, 0x4b1e ; 0094024b b81e4b
+ add [bx + si], dh ; 0094024e 0030
+ sbb al, 0x23 ; 00940250 1c23
+ add byte [bx + si], 0x0 ; 00940252 800000
+ add [bx + si], al ; 00940255 0000
+ add bx, [bx] ; 00940257 031f
+ dec bx ; 00940259 4b
+ add [bx + si], dh ; 0094025a 0030
+ sbb al, 0x24 ; 0094025c 1c24
+ add byte [bx + si], 0x0 ; 0094025e 800000
+ add [bx + si], al ; 00940261 0000
+ dec si ; 00940263 4e
+ pop ds ; 00940264 1f
+ fld [bx + si] ; 00940265 dd00
+ xor [si], bl ; 00940267 301c
+ and ax, 0x80 ; 00940269 258000
+ add [bx + si], al ; 0094026c 0000
+ add [bp + di], ch ; 0094026e 002b
+ and ch, bl ; 00940270 20dd
+ add [bx + si], dh ; 00940272 0030
+ sbb al, 0x26 ; 00940274 1c26
+ add byte [bx + si], 0x0 ; 00940276 800000
+ add [bx + si], al ; 00940279 0000
+ or [bx + di], ah ; 0094027b 0821
+ fld [bx + si] ; 0094027d dd00
+ xor [si], bl ; 0094027f 301c
+ daa ; 00940281 27
+ add byte [bx + si], 0x0 ; 00940282 800000
+ add [bx + si], al ; 00940285 0000
+ in ax, 0x21 ; 00940287 e521
+ dec dx ; 00940289 4a
+ add [bx + si], dh ; 0094028a 0030
+ sbb al, 0x28 ; 0094028c 1c28
+ add byte [bx + si], 0x0 ; 0094028e 800000
+ add [bx + si], al ; 00940291 0000
+ das ; 00940293 2f
+ and cl, [bp + si + 0] ; 00940294 224a00
+ xor [si], bl ; 00940297 301c
+ sub [bx + si + 0], ax ; 00940299 29800000
+ add [bx + si], al ; 0094029d 0000
+ jns L88 ; 0094029f 7922
+ dec dx ; 009402a1 4a
+ add [bx + si], dh ; 009402a2 0030
+ sbb al, 0x2a ; 009402a4 1c2a
+ add byte [bx + si], 0x0 ; 009402a6 800000
+ add [bx + si], al ; 009402a9 0000
+ ret ; 009402ab c3
+ and cl, [bp + si + 0] ; 009402ac 224a00
+ xor [si], bl ; 009402af 301c
+ sub ax, [bx + si + 0] ; 009402b1 2b800000
+ add [bx + si], al ; 009402b5 0000
+ or ax, 0x4a23 ; 009402b7 0d234a
+ add [bx + si], dh ; 009402ba 0030
+ sbb al, L1 ; 009402bc 1c2c
+ add byte [bx + si], 0x0 ; 009402be 800000
+ add [bx + si], al ; 009402c1 0000
+ push di ; 009402c3 57
+ and cx, [bp + si + 0] ; 009402c4 234a00
+ xor [si], bl ; 009402c7 301c
+ sub ax, 0x80 ; 009402c9 2d8000
+ add [bx + si], al ; 009402cc 0000
+ add [bx + di + 0x4a23], ah ; 009402ce 00a1234a
+ add [bx + si], dh ; 009402d2 0030
+ sbb al, 0x2e ; 009402d4 1c2e
+ add byte [bx + si], 0x0 ; 009402d6 800000
+ add [bx + si], al ; 009402d9 0000
+ jmp short L89 ; 009402db eb23
+ dec dx ; 009402dd 4a
+ add [bx + si], dh ; 009402de 0030
+ sbb al, 0x2f ; 009402e0 1c2f
+ add byte [bx + si], 0x0 ; 009402e2 800000
+ add [bx + si], al ; 009402e5 0000
+ xor ax, 0x4a24 ; 009402e7 35244a
+ add [bx + si], dh ; 009402ea 0030
+ sbb al, 0x30 ; 009402ec 1c30
+ add byte [bx + si], 0x0 ; 009402ee 800000
+ add [bx + si], al ; 009402f1 0000
+ jg L90 ; 009402f3 7f24
+ dec dx ; 009402f5 4a
+ add [bx + si], dh ; 009402f6 0030
+ sbb al, 0x31 ; 009402f8 1c31
+ add byte [bx + si], 0x0 ; 009402fa 800000
+ add [bx + si], al ; 009402fd 0000
+ leave ; 009402ff c9
+ and al, L16 ; 00940300 24dd
+ add [bx + si], dh ; 00940302 0030
+ sbb al, 0x32 ; 00940304 1c32
+ add byte [bx + si], 0x0 ; 00940306 800000
+ add [bx + si], al ; 00940309 0000
+ cmpsb ; 0094030b a6
+ and ax, L16 ; 0094030c 25dd00
+ xor [si], bl ; 0094030f 301c
+ xor ax, [bx + si + 0] ; 00940311 33800000
+ add [bx + si], al ; 00940315 0000
+ and word L16, byte 0x30 ; 00940317 8326dd0030
+ sbb al, 0x34 ; 0094031c 1c34
+ add byte [bx + si], 0x0 ; 0094031e 800000
+ add [bx + si], al ; 00940321 0000
+ pusha ; 00940323 60
+ daa ; 00940324 27
+ fadd [bx + si] ; 00940325 dc00
+ xor [si], bl ; 00940327 301c
+ inc sp ; 00940329 44
+ add byte [bx + si], 0x0 ; 0094032a 800000
+ add [bx + si], al ; 0094032d 0000
+ cmp al, 0x28 ; 0094032f 3c28
+ fadd [bx + si] ; 00940331 dc00
+ xor [si], bl ; 00940333 301c
+ inc bx ; 00940335 43
+ add byte [bx + si], 0x0 ; 00940336 800000
+ add [bx + si], al ; 00940339 0000
+ add al, 0x80 ; 0094033b 0480
+ add [bx + si], ax ; 0094033d 0100
+ add [bx + si], al ; 0094033f 0000
+ add [bx + si], al ; 00940341 0000
+ sbb [bx + di], ch ; 00940343 1829
+ or [bx + si], ax ; 00940345 0900
+ xor [si], bl ; 00940347 301c
+ add [bx + si + 0], ax ; 00940349 01800000
+ add [bx + si], al ; 0094034d 0000
+ add ax, 0x280 ; 0094034f 058002
+ add [bx + si], al ; 00940352 0000
+ add [bx + si], al ; 00940354 0000
+ add [bx + di], ah ; 00940356 0021
+ sub [bp + di], dx ; 00940358 2913
+ add [bx + si], dh ; 0094035a 0030
+ sbb al, 0x65 ; 0094035c 1c65
+ add byte [bx + si], 0x0 ; 0094035e 800000
+ add [bx + si], al ; 00940361 0000
+ xor al, 0x29 ; 00940363 3429
+ sbb [bx + si], al ; 00940365 1800
+ xor [si], bl ; 00940367 301c
+ a16 add byte [eax], 0x0 ; 00940369 67800000
+ add [bx + si], al ; 0094036d 0000
+ push es ; 0094036f 06
+ add byte [bx], 0x0 ; 00940370 800700
+ add [bx + si], al ; 00940373 0000
+ add [bx + si], al ; 00940375 0000
+ dec sp ; 00940377 4c
+ sub [bp + si], cx ; 00940378 290a
+ add [bx + si], dh ; 0094037a 0030
+ sbb al, 0x7 ; 0094037c 1c07
+ add byte [bx + si], 0x0 ; 0094037e 800000
+ add [bx + si], al ; 00940381 0000
+ push si ; 00940383 56
+ sub [si], ax ; 00940384 2904
+ add [bx + si], dh ; 00940386 0030
+ sbb al, 0xd ; 00940388 1c0d
+ add byte [bx + si], 0x0 ; 0094038a 800000
+ add [bx + si], al ; 0094038d 0000
+ pop dx ; 0094038f 5a
+ sub L17, cx ; 00940390 290e0030
+ sbb al, 0x13 ; 00940394 1c13
+ add byte [bx + si], 0x0 ; 00940396 800000
+ add [bx + si], al ; 00940399 0000
+ push 0x729 ; 0094039b 682907
+ add [bx + si], dh ; 0094039e 0030
+ sbb al, 0x3f ; 009403a0 1c3f
+ add byte [bx + si], 0x0 ; 009403a2 800000
+ add [bx + si], al ; 009403a5 0000
+ outsw ; 009403a7 6f
+ sub [si], ax ; 009403a8 2904
+ add [bx + si], dh ; 009403aa 0030
+ sbb al, 0x0 ; 009403ac 1c00
+ nop ; 009403ae 90
+ add [bx + si], al ; 009403af 0000
+ add [bx + si], al ; 009403b1 0000
+ jnc L13 ; 009403b3 7329
+ add al, 0x0 ; 009403b5 0400
+ xor [si], bl ; 009403b7 301c
+ add ax, [bx + si + 0] ; 009403b9 03800000
+ add [bx + si], al ; 009403bd 0000
+ ja L91 ; 009403bf 7729
+ add al, [bx + si] ; 009403c1 0200
+ xor [si], bl ; 009403c3 301c
+ jle L92 ; 009403c5 7e80
+ add [bx + si], al ; 009403c7 0000
+ add [bx + si], al ; 009403c9 0000
+ adc [bx + si + 0x1], al ; 009403cb 10800100
+ add [bx + si], al ; 009403cf 0000
+ add [bx + si], al ; 009403d1 0000
+ jns L93 ; 009403d3 7929
+ push ds ; 009403d5 1e
+ add [bx + si], dh ; 009403d6 0030
+ or al, L4 ; 009403d8 0c01
+ add byte [bx + si], 0x0 ; 009403da 800000
+ add [bx + si], al ; 009403dd 0000
+ add ax, [bx + si + 0x2] ; 009403df 03800200
+ add [bx + si], al ; 009403e3 0000
+ add [bx + si], al ; 009403e5 0000
+ xchg ax, di ; 009403e7 97
+ sub [bx], bp ; 009403e8 292f
+ add [bx + si], dl ; 009403ea 0010
+ sbb al, L4 ; 009403ec 1c01
+ add byte [bx + si], 0x0 ; 009403ee 800000
+ add [bx + si], al ; 009403f1 0000
+ mov byte [bx + di], 0x13 ; 009403f3 c62913
+ add [bx + si], dl ; 009403f6 0010
+ sbb al, 0x2 ; 009403f8 1c02
+ add byte [bx + si], 0x0 ; 009403fa 800000
+ add [bx + si], al ; 009403fd 0000
+ add [bx + si], al ; 009403ff 0000
+ add dx, [bp + di + 0x4f] ; 00940401 03534f
+ dec sp ; 00940404 4c
+ add dx, [bp + di + 0x4f] ; 00940405 03534f
+ dec sp ; 00940408 4c
+ add [bx + si], al ; 00940409 0000
+ add [bx + di], al ; 0094040b 0001
+ add [bx + si], cl ; 0094040d 0008
+ add [di], cl ; 0094040f 000d
+ add [bx + di], dl ; 00940411 0011
+ add [bx + si], al ; 00940413 0000
+ push es ; 00940415 06
+ dec bx ; 00940416 4b
+ inc bp ; 00940417 45
+ push dx ; 00940418 52
+ dec si ; 00940419 4e
+ inc bp ; 0094041a 45
+ dec sp ; 0094041b 4c
+ add al, 0x55 ; 0094041c 0455
+ push bx ; 0094041e 53
+ inc bp ; 0094041f 45
+ push dx ; 00940420 52
+ add ax, [bx + 0x44] ; 00940421 034744
+ dec cx ; 00940424 49
+ add ax, 0x4853 ; 00940425 055348
+ inc bp ; 00940428 45
+ dec sp ; 00940429 4c
+ dec sp ; 0094042a 4c
+ add [bp + di], dl ; 0094042b 0013
+ dec bp ; 0094042d 4d
+ imul sp, [bp + di + 0x72], 0x736f ; 0094042e 6963726f73
+ outsw ; 00940433 6f
+ o32 jz L94 ; 00940434 667420
+ push bx ; 00940437 53
+ outsw ; 00940438 6f
+ insb ; 00940439 6c
+ imul si, [si + 0x61], 0x7269 ; 0094043a 6974616972
+ gs add gs:[bx + si], al ; 0094043f 650000
+ add [bx + si], al ; 00940442 0000
+ add [bx + si], al ; 00940444 0000
+ add [bx + si], al ; 00940446 0000
+ add [bx + si], al ; 00940448 0000
+ add [bx + si], al ; 0094044a 0000
+ add [bx + si], al ; 0094044c 0000
+ add [bx + si], al ; 0094044e 0000
+ add [bx + si], al ; 00940450 0000
+ add [bx + si], al ; 00940452 0000
+ add [bx + si], al ; 00940454 0000
+ add [bx + si], al ; 00940456 0000
+ add [bx + si], al ; 00940458 0000
+ add [bx + si], al ; 0094045a 0000
+ add [bx + si], al ; 0094045c 0000
+ add [bx + si], al ; 0094045e 0000
+ add [bx + si], al ; 00940460 0000
+ add [bx + si], al ; 00940462 0000
+ add [bx + si], al ; 00940464 0000
+ add [bx + si], al ; 00940466 0000
+ add [bx + si], al ; 00940468 0000
+ add [bx + si], al ; 0094046a 0000
+ add [bx + si], al ; 0094046c 0000
+ add [bx + si], al ; 0094046e 0000
+ add [bx + si], al ; 00940470 0000
+ add [bx + si], al ; 00940472 0000
+ add [bx + si], al ; 00940474 0000
+ add [bx + si], al ; 00940476 0000
+ add [bx + si], al ; 00940478 0000
+ add [bx + si], al ; 0094047a 0000
+ add [bx + si], al ; 0094047c 0000
+ add [bx + si], al ; 0094047e 0000
+ add [bx + si], al ; 00940480 0000
+ add [bx + si], al ; 00940482 0000
+ add [bx + si], al ; 00940484 0000
+ add [bx + si], al ; 00940486 0000
+ add [bx + si], al ; 00940488 0000
+ add [bx + si], al ; 0094048a 0000
+ add al, cl ; 0094048c 00c8
+ sbb [bx + si], al ; 0094048e 1800
+ add [bp + di + 0xc7e], al ; 00940490 00837e0c
+ add [si + 0x55], dh ; 00940494 007455
+ push word [bp + 0xc] ; 00940497 ff760c
+ push L23 ; 0094049a 68f001
+ push 0x2 ; 0094049d 6a02
+ callf ; 0094049f 9affff0000
+ push word L23 ; 009404a4 ff36f001
+ callf ; 009404a8 9affff0000
+ mov [bp + 0xffffffec], ax ; 009404ad 8946ec
+ push word L23 ; 009404b0 ff36f001
+ push 0x0 ; 009404b4 6a00
+ push 0x0 ; 009404b6 6a00
+ push 0x0 ; 009404b8 6a00
+ push 0x0 ; 009404ba 6a00
+ push 0x0 ; 009404bc 6a00
+ push 0x43 ; 009404be 6a43
+ callf ; 009404c0 9affff0000
+ push word L23 ; 009404c5 ff36f001
+ callf ; 009404c9 9affff0000
+ or ax, ax ; 009404ce 0bc0
+ jz L95 ; 009404d0 740d
+ push word L23 ; 009404d2 ff36f001
+ push 0x9 ; 009404d6 6a09
+ callf ; 009404d8 9affff0000
+ jmp short L96 ; 009404dd eb08
+ push word [bp + 0xffffffec] ; 009404df ff76ec
+ callf ; 009404e2 9affff0000
+ xor ax, ax ; 009404e7 33c0
+ jmp L97 ; 009404e9 e98200
+ o32 push dword [bp + 0xc] ; 009404ec 66ff760c
+ o32 push dword [bp + 0x8] ; 009404f0 66ff7608
+ push word [bp + 0x6] ; 009404f4 ff7606
+ push cs ; 009404f7 0e
+ call L98 ; 009404f8 e87800
+ or ax, ax ; 009404fb 0bc0
+ jz L96 ; 009404fd 74e8
+ push 0x29 ; 009404ff 6a29
+ callf ; 00940501 9affff0000
+ push ax ; 00940506 50
+ push ds ; 00940507 1e
+ push 0x3c ; 00940508 683c00
+ callf ; 0094050b 9affff0000
+ mov [bp + 0xffffffe8], ax ; 00940510 8946e8
+ mov [bp + 0xffffffea], dx ; 00940513 8956ea
+ or dx, ax ; 00940516 0bd0
+ jz L99 ; 00940518 7407
+ push L4 ; 0094051a 6a01
+ push L4 ; 0094051c 6a01
+ call far oword [bp + 0xffffffe8] ; 0094051e ff5ee8
+ lea ax, [bp + 0xffffffee] ; 00940521 8d46ee
+ push ss ; 00940524 16
+ push ax ; 00940525 50
+ push 0x0 ; 00940526 6a00
+ push 0x0 ; 00940528 6a00
+ push 0x0 ; 0094052a 6a00
+ callf ; 0094052c 9ac8000000
+ or ax, ax ; 00940531 0bc0
+ jz L100 ; 00940533 7428
+ lea ax, [bp + 0xffffffee] ; 00940535 8d46ee
+ push ss ; 00940538 16
+ push ax ; 00940539 50
+ callf ; 0094053a 9affff0000
+ lea ax, [bp + 0xffffffee] ; 0094053f 8d46ee
+ push ss ; 00940542 16
+ push ax ; 00940543 50
+ callf ; 00940544 9affff0000
+ lea ax, [bp + 0xffffffee] ; 00940549 8d46ee
+ push ss ; 0094054c 16
+ push ax ; 0094054d 50
+ push 0x0 ; 0094054e 6a00
+ push 0x0 ; 00940550 6a00
+ push 0x0 ; 00940552 6a00
+ callf ; 00940554 9affff0000
+ or ax, ax ; 00940559 0bc0
+ jnz L101 ; 0094055b 75d8
+ o32 cmp dword [bp + 0xffffffe8], byte 0x0 ; 0094055d 66837ee800
+ jz L102 ; 00940562 7407
+ push L4 ; 00940564 6a01
+ push 0x0 ; 00940566 6a00
+ call far oword [bp + 0xffffffe8] ; 00940568 ff5ee8
+ mov ax, [bp + 0xfffffff2] ; 0094056b 8b46f2
+ leave ; 0094056e c9
+ retf 0x0a ; 0094056f ca0a00
+
+L22:
+ nop ; 00940572 90
+ enter 0x72, 0x0 ; 00940573 c8720000
+ mov ax, [bp + 0xe] ; 00940577 8b460e
+ mov [0x2b0], ax ; 0094057a a3b002
+ push 0x200 ; 0094057d 680002
+ push 0x12c ; 00940580 682c01
+ callf ; 00940583 9a2806d401
+ push ds ; 00940588 1e
+ push L84 ; 00940589 686802
+ push ds ; 0094058c 1e
+ push L82 ; 0094058d 686a02
+ callf ; 00940590 9a0000ffff
+ or ax, ax ; 00940595 0bc0
+ jz L103 ; 00940597 741d
+ push 0x0 ; 00940599 6a00
+ push 0x0 ; 0094059b 6a00
+ push 0x7f00 ; 0094059d 68007f
+ callf ; 009405a0 9affff0000
+ mov [bp + 0xffffffb4], ax ; 009405a5 8946b4
+ push 0x0 ; 009405a8 6a00
+ callf ; 009405aa 9affff0000
+ mov [bp + 0xffffffd8], ax ; 009405af 8946d8
+ or ax, ax ; 009405b2 0bc0
+ jnz L104 ; 009405b4 7503
+ jmp L105 ; 009405b6 e99802
+ push ax ; 009405b9 50
+ lea ax, [bp + 0xffffffb8] ; 009405ba 8d46b8
+ push ss ; 009405bd 16
+ push ax ; 009405be 50
+ callf ; 009405bf 9affff0000
+ mov ax, [bp + 0xffffffb8] ; 009405c4 8b46b8
+ mov [0x23e], ax ; 009405c7 a33e02
+ mov ax, [bp + 0xffffffc4] ; 009405ca 8b46c4
+ mov [0x23c], ax ; 009405cd a33c02
+ push word [bp + 0xffffffd8] ; 009405d0 ff76d8
+ push L59 ; 009405d3 6a18
+ callf ; 009405d5 9a5e010000
+ cmp ax, 0x02 ; 009405da 3d0200
+ jnz L106 ; 009405dd 7506
+ mov word L36, L4 ; 009405df c706f6010100
+ push word [bp + 0xffffffd8] ; 009405e5 ff76d8
+ push 0x8 ; 009405e8 6a08
+ callf ; 009405ea 9a6b010000
+ mov [0x24c], ax ; 009405ef a34c02
+ push word [bp + 0xffffffd8] ; 009405f2 ff76d8
+ push 0xa ; 009405f5 6a0a
+ callf ; 009405f7 9affff0000
+ mov [0x24e], ax ; 009405fc a34e02
+ cmp ax, 0x12c ; 009405ff 3d2c01
+ jge L107 ; 00940602 7d05
+ mov ax, L4 ; 00940604 b80100
+ jmp short L108 ; 00940607 eb02
+ xor ax, ax ; 00940609 33c0
+ mov [0x38], ax ; 0094060b a33800
+ or ax, ax ; 0094060e 0bc0
+ jz L109 ; 00940610 740c
+ mov cx, 0x02 ; 00940612 b90200
+ mov ax, [0x26a] ; 00940615 a16a02
+ cwd ; 00940618 99
+ idiv cx, ax ; 00940619 f7f9
+ mov [0x26a], ax ; 0094061b a36a02
+ push 0x0 ; 0094061e 6a00
+ push word [bp + 0xffffffd8] ; 00940620 ff76d8
+ callf ; 00940623 9affff0000
+ cmp word L36, byte 0x0 ; 00940628 833ef60100
+ jz L110 ; 0094062d 7408
+ mov ax, 0xffff ; 0094062f b8ffff
+ mov dx, 0xff ; 00940632 baff00
+ jmp short L28 ; 00940635 eb05
+ mov ax, 0x8000 ; 00940637 b80080
+ xor dx, dx ; 0094063a 33d2
+ mov [0x2b2], ax ; 0094063c a3b202
+ mov L42, dx ; 0094063f 8916b402
+ push dx ; 00940643 52
+ push ax ; 00940644 50
+ callf ; 00940645 9affff0000
+ mov [0x266], ax ; 0094064a a36602
+ callf ; 0094064d 9affff0000
+ push ax ; 00940652 50
+ callf ; 00940653 9a3201ffff
+ pop bx ; 00940658 5b
+ push 0x26e ; 00940659 686e02
+ push 0x64 ; 0094065c 6a64
+ callf ; 0094065e 9a2806de01
+ push 0x250 ; 00940663 685002
+ push 0x65 ; 00940666 6a65
+ callf ; 00940668 9a2806e901
+ lea ax, [bp + 0xffffff98] ; 0094066d 8d4698
+ push ax ; 00940670 50
+ push 0x67 ; 00940671 6a67
+ callf ; 00940673 9a2806ffff
+ lea ax, [bp + 0xffffff98] ; 00940678 8d4698
+ push ss ; 0094067b 16
+ push ax ; 0094067c 50
+ callf ; 0094067d 9affff0000
+ mov [0x1f8], ax ; 00940682 a3f801
+ mov word [bp + 0xffffffb2], 0x00 ; 00940685 c746b20000
+ o32 mov eax, [bp + 0x8] ; 0094068a 668b4608
+ mov dx, [bp + 0xa] ; 0094068e 8b560a
+ o32 mov [bp + 0xffffffae], eax ; 00940691 668946ae
+ mov es, dx ; 00940695 8ec2
+ mov bx, ax ; 00940697 8bd8
+ es cmp byte es:[bx], 0x0 ; 00940699 26803f00
+ jz L111 ; 0094069d 7420
+ es cmp byte es:[bx], 0x2f ; 0094069f 26803f2f
+ jnz L112 ; 009406a3 7507
+ es cmp byte es:[bx + 0x1], 0x49 ; 009406a5 26807f0149
+ jz L113 ; 009406aa 740e
+ inc word [bp + 0xffffffae] ; 009406ac ff46ae
+ mov bx, [bp + 0xffffffae] ; 009406af 8b5eae
+ es cmp byte es:[bx], 0x0 ; 009406b2 26803f00
+ jnz L114 ; 009406b6 75e7
+ jmp short L111 ; 009406b8 eb05
+ mov word [bp + 0xffffffb2], L4 ; 009406ba c746b20100
+ cmp word [bp + 0xc], byte 0x0 ; 009406bf 837e0c00
+ jnz L115 ; 009406c3 7556
+ mov word [bp + 0xffffffe6], 0x2008 ; 009406c5 c746e60820
+ mov word [bp + 0xffffffe8], 0x40c ; 009406ca c746e80c04
+ mov word [bp + 0xffffffea], 0xffff ; 009406cf c746eaffff
+ o32 mov dword [bp + 0xffffffec], 0x0000 ; 009406d4 66c746ec00000000
+ mov ax, [0x2b0] ; 009406dc a1b002
+ mov [bp + 0xfffffff0], ax ; 009406df 8946f0
+ push ax ; 009406e2 50
+ push ds ; 009406e3 1e
+ push L12 ; 009406e4 684b00
+ callf ; 009406e7 9affff0000
+ mov [bp + 0xfffffff2], ax ; 009406ec 8946f2
+ mov ax, [bp + 0xffffffb4] ; 009406ef 8b46b4
+ mov [bp + 0xfffffff4], ax ; 009406f2 8946f4
+ mov ax, [0x266] ; 009406f5 a16602
+ mov [bp + 0xfffffff6], ax ; 009406f8 8946f6
+ o32 mov dword [bp + 0xfffffff8], L4 ; 009406fb 66c746f801000000
+ mov word [bp + 0xfffffffc], 0x22 ; 00940703 c746fc2200
+ mov word [bp + 0xfffffffe], ds ; 00940708 8c5efe
+ lea ax, [bp + 0xffffffe6] ; 0094070b 8d46e6
+ push ss ; 0094070e 16
+ push ax ; 0094070f 50
+ callf ; 00940710 9affff0018
+
+ .section .codeSection2, @progbits
+ .align 0
+
+ adc [bp + si], cx ; 0094000a 110a
+ add [bx + si], dh ; 0094000c 0030
+ sbb al, 0xa9 ; 0094000e 1ca9
+ add byte [bx + si], 0x0 ; 00940010 820000
+ add [bx + si], al ; 00940013 0000
+ inc sp ; 00940015 44
+ adc [bp + si], cx ; 00940016 110a
+ add [bx + si], dh ; 00940018 0030
+ sbb al, 0xaa ; 0094001a 1caa
+ add byte [bx + si], 0x0 ; 0094001c 820000
+ add [bx + si], al ; 0094001f 0000
+ dec si ; 00940021 4e
+ adc [bx + di], cx ; 00940022 1109
+ add [bx + si], dh ; 00940024 0030
+ sbb al, 0xab ; 00940026 1cab
+ add byte [bx + si], 0x0 ; 00940028 820000
+ add [bx + si], al ; 0094002b 0000
+ push di ; 0094002d 57
+ adc [bx + di], cx ; 0094002e 1109
+ add [bx + si], dh ; 00940030 0030
+ sbb al, 0xac ; 00940032 1cac
+ add byte [bx + si], 0x0 ; 00940034 820000
+ add [bx + si], al ; 00940037 0000
+ pusha ; 00940039 60
+ adc [bp + si + 0], cx ; 0094003a 114a00
+ xor [si], bl ; 0094003d 301c
+ add [bx + si + 0], ax ; 0094003f 01800000
+ add [bx + si], al ; 00940043 0000
+ stosb ; 00940045 aa
+ adc [bp + si + 0], cx ; 00940046 114a00
+ xor [si], bl ; 00940049 301c
+ add al, [bx + si + 0] ; 0094004b 02800000
+ add [bx + si], al ; 0094004f 0000
+ hlt ; 00940051 f4
+ adc [bp + si + 0], cx ; 00940052 114a00
+ xor [si], bl ; 00940055 301c
+ add ax, [bx + si + 0] ; 00940057 03800000
+ add [bx + si], al ; 0094005b 0000
+ ds adc cl, ds:[bp + si + 0] ; 0094005d 3e124a00
+ xor [si], bl ; 00940061 301c
+ add al, 0x80 ; 00940063 0480
+ add [bx + si], al ; 00940065 0000
+ add [bx + si], al ; 00940067 0000
+ mov [bp + si], dl ; 00940069 8812
+ dec dx ; 0094006b 4a
+ add [bx + si], dh ; 0094006c 0030
+ sbb al, 0x5 ; 0094006e 1c05
+ add byte [bx + si], 0x0 ; 00940070 800000
+ add [bx + si], al ; 00940073 0000
+ rcl byte [bp + si], cl ; 00940075 d212
+ dec dx ; 00940077 4a
+ add [bx + si], dh ; 00940078 0030
+ sbb al, 0x6 ; 0094007a 1c06
+ add byte [bx + si], 0x0 ; 0094007c 800000
+ add [bx + si], al ; 0094007f 0000
+ sbb al, 0x13 ; 00940081 1c13
+ dec dx ; 00940083 4a
+ add [bx + si], dh ; 00940084 0030
+ sbb al, 0x7 ; 00940086 1c07
+ add byte [bx + si], 0x0 ; 00940088 800000
+ add [bx + si], al ; 0094008b 0000
+ o32 adc ecx, [bp + si + 0] ; 0094008d 66134a00
+ xor [si], bl ; 00940091 301c
+ or [bx + si + 0], al ; 00940093 08800000
+ add [bx + si], al ; 00940097 0000
+ mov al, 0x13 ; 00940099 b013
+ dec dx ; 0094009b 4a
+ add [bx + si], dh ; 0094009c 0030
+ sbb al, 0x9 ; 0094009e 1c09
+ add byte [bx + si], 0x0 ; 009400a0 800000
+ add [bx + si], al ; 009400a3 0000
+ cli ; 009400a5 fa
+ adc cx, [bp + si + 0] ; 009400a6 134a00
+ xor [si], bl ; 009400a9 301c
+ or al, [bx + si + 0] ; 009400ab 0a800000
+ add [bx + si], al ; 009400af 0000
+ inc sp ; 009400b1 44
+ adc al, L16 ; 009400b2 14dd
+ add [bx + si], dh ; 009400b4 0030
+ sbb al, 0xb ; 009400b6 1c0b
+ add byte [bx + si], 0x0 ; 009400b8 800000
+ add [bx + si], al ; 009400bb 0000
+ and [di], dx ; 009400bd 2115
+ fld [bx + si] ; 009400bf dd00
+ xor [si], bl ; 009400c1 301c
+ or al, 0x80 ; 009400c3 0c80
+ add [bx + si], al ; 009400c5 0000
+ add [bx + si], al ; 009400c7 0000
+ ill_grp_4 ; 009400c9 fe15
+ fld [bx + si] ; 009400cb dd00
+ xor [si], bl ; 009400cd 301c
+ or ax, 0x80 ; 009400cf 0d8000
+ add [bx + si], al ; 009400d2 0000
+ add bl, bl ; 009400d4 00db
+ push ss ; 009400d6 16
+ dec bx ; 009400d7 4b
+ add [bx + si], dh ; 009400d8 0030
+ sbb al, 0xe ; 009400da 1c0e
+ add byte [bx + si], 0x0 ; 009400dc 800000
+ add [bx + si], al ; 009400df 0000
+ es pop ss ; 009400e1 2617
+ dec bx ; 009400e3 4b
+ add [bx + si], dh ; 009400e4 0030
+ sbb al, 0xf ; 009400e6 1c0f
+ add byte [bx + si], 0x0 ; 009400e8 800000
+ add [bx + si], al ; 009400eb 0000
+ jno L116 ; 009400ed 7117
+ dec bx ; 009400ef 4b
+ add [bx + si], dh ; 009400f0 0030
+ sbb al, 0x10 ; 009400f2 1c10
+ add byte [bx + si], 0x0 ; 009400f4 800000
+ add [bx + si], al ; 009400f7 0000
+ mov sp, 0x4b17 ; 009400f9 bc174b
+ add [bx + si], dh ; 009400fc 0030
+ sbb al, 0x11 ; 009400fe 1c11
+ add byte [bx + si], 0x0 ; 00940100 800000
+ add [bx + si], al ; 00940103 0000
+ pop es ; 00940105 07
+ sbb [bp + di + 0], cl ; 00940106 184b00
+ xor [si], bl ; 00940109 301c
+ adc al, [bx + si + 0] ; 0094010b 12800000
+ add [bx + si], al ; 0094010f 0000
+ push dx ; 00940111 52
+ sbb [bp + di + 0], cl ; 00940112 184b00
+ xor [si], bl ; 00940115 301c
+ adc ax, [bx + si + 0] ; 00940117 13800000
+ add [bx + si], al ; 0094011b 0000
+ popf ; 0094011d 9d
+ sbb [bp + di + 0], cl ; 0094011e 184b00
+ xor [si], bl ; 00940121 301c
+ adc al, 0x80 ; 00940123 1480
+ add [bx + si], al ; 00940125 0000
+ add [bx + si], al ; 00940127 0000
+ call L117 ; 00940129 e8184b
+ add [bx + si], dh ; 0094012c 0030
+ sbb al, 0x15 ; 0094012e 1c15
+ add byte [bx + si], 0x0 ; 00940130 800000
+ add [bx + si], al ; 00940133 0000
+ xor bx, [bx + di] ; 00940135 3319
+ dec bx ; 00940137 4b
+ add [bx + si], dh ; 00940138 0030
+ sbb al, 0x16 ; 0094013a 1c16
+ add byte [bx + si], 0x0 ; 0094013c 800000
+ add [bx + si], al ; 0094013f 0000
+ jle L118 ; 00940141 7e19
+ dec bx ; 00940143 4b
+ add [bx + si], dh ; 00940144 0030
+ sbb al, 0x17 ; 00940146 1c17
+ add byte [bx + si], 0x0 ; 00940148 800000
+ add [bx + si], al ; 0094014b 0000
+ leave ; 0094014d c9
+ sbb bp, bx ; 0094014e 19dd
+ add [bx + si], dh ; 00940150 0030
+ sbb al, L59 ; 00940152 1c18
+ add byte [bx + si], 0x0 ; 00940154 800000
+ add [bx + si], al ; 00940157 0000
+ cmpsb ; 00940159 a6
+ sbb bl, ch ; 0094015a 1add
+ add [bx + si], dh ; 0094015c 0030
+ sbb al, 0x19 ; 0094015e 1c19
+ add byte [bx + si], 0x0 ; 00940160 800000
+ add [bx + si], al ; 00940163 0000
+ sbb word [bp + di], L16 ; 00940165 831bdd
+ add [bx + si], dh ; 00940168 0030
+ sbb al, 0x1a ; 0094016a 1c1a
+ add byte [bx + si], 0x0 ; 0094016c 800000
+ add [bx + si], al ; 0094016f 0000
+ pusha ; 00940171 60
+ sbb al, L12 ; 00940172 1c4b
+ add [bx + si], dh ; 00940174 0030
+ sbb al, 0x1b ; 00940176 1c1b
+ add byte [bx + si], 0x0 ; 00940178 800000
+ add [bx + si], al ; 0094017b 0000
+ stosw ; 0094017d ab
+ sbb al, L12 ; 0094017e 1c4b
+ add [bx + si], dh ; 00940180 0030
+ sbb al, 0x1c ; 00940182 1c1c
+ add byte [bx + si], 0x0 ; 00940184 800000
+ add [bx + si], al ; 00940187 0000
+ neg byte [si] ; 00940189 f61c
+ dec bx ; 0094018b 4b
+ add [bx + si], dh ; 0094018c 0030
+ sbb al, 0x1d ; 0094018e 1c1d
+ add byte [bx + si], 0x0 ; 00940190 800000
+ add [bx + si], al ; 00940193 0000
+ inc cx ; 00940195 41
+ sbb ax, L12 ; 00940196 1d4b00
+ xor [si], bl ; 00940199 301c
+ push ds ; 0094019b 1e
+ add byte [bx + si], 0x0 ; 0094019c 800000
+ add [bx + si], al ; 0094019f 0000
+ mov word [di], ds ; 009401a1 8c1d
+ dec bx ; 009401a3 4b
+ add [bx + si], dh ; 009401a4 0030
+ sbb al, 0x1f ; 009401a6 1c1f
+ add byte [bx + si], 0x0 ; 009401a8 800000
+ add [bx + si], al ; 009401ab 0000
+ xlatb ; 009401ad d7
+ sbb ax, L12 ; 009401ae 1d4b00
+ xor [si], bl ; 009401b1 301c
+ and [bx + si + 0], al ; 009401b3 20800000
+ add [bx + si], al ; 009401b7 0000
+ and bl, L12 ; 009401b9 221e4b00
+ xor [si], bl ; 009401bd 301c
+ and [bx + si + 0], ax ; 009401bf 21800000
+ add [bx + si], al ; 009401c3 0000
+ insw ; 009401c5 6d
+ push ds ; 009401c6 1e
+ dec bx ; 009401c7 4b
+ add [bx + si], dh ; 009401c8 0030
+ sbb al, 0x22 ; 009401ca 1c22
+ add byte [bx + si], 0x0 ; 009401cc 800000
+ add [bx + si], al ; 009401cf 0000
+ mov ax, 0x4b1e ; 009401d1 b81e4b
+ add [bx + si], dh ; 009401d4 0030
+ sbb al, 0x23 ; 009401d6 1c23
+ add byte [bx + si], 0x0 ; 009401d8 800000
+ add [bx + si], al ; 009401db 0000
+ add bx, [bx] ; 009401dd 031f
+ dec bx ; 009401df 4b
+ add [bx + si], dh ; 009401e0 0030
+ sbb al, 0x24 ; 009401e2 1c24
+ add byte [bx + si], 0x0 ; 009401e4 800000
+ add [bx + si], al ; 009401e7 0000
+ dec si ; 009401e9 4e
+ pop ds ; 009401ea 1f
+ fld [bx + si] ; 009401eb dd00
+ xor [si], bl ; 009401ed 301c
+ and ax, 0x80 ; 009401ef 258000
+ add [bx + si], al ; 009401f2 0000
+ add [bp + di], ch ; 009401f4 002b
+ and ch, bl ; 009401f6 20dd
+ add [bx + si], dh ; 009401f8 0030
+ sbb al, 0x26 ; 009401fa 1c26
+ add byte [bx + si], 0x0 ; 009401fc 800000
+ add [bx + si], al ; 009401ff 0000
+ or [bx + di], ah ; 00940201 0821
+ fld [bx + si] ; 00940203 dd00
+ xor [si], bl ; 00940205 301c
+ daa ; 00940207 27
+ add byte [bx + si], 0x0 ; 00940208 800000
+ add [bx + si], al ; 0094020b 0000
+ in ax, 0x21 ; 0094020d e521
+ dec dx ; 0094020f 4a
+ add [bx + si], dh ; 00940210 0030
+ sbb al, 0x28 ; 00940212 1c28
+ add byte [bx + si], 0x0 ; 00940214 800000
+ add [bx + si], al ; 00940217 0000
+ das ; 00940219 2f
+ and cl, [bp + si + 0] ; 0094021a 224a00
+ xor [si], bl ; 0094021d 301c
+ sub [bx + si + 0], ax ; 0094021f 29800000
+ add [bx + si], al ; 00940223 0000
+ jns L119 ; 00940225 7922
+ dec dx ; 00940227 4a
+ add [bx + si], dh ; 00940228 0030
+ sbb al, 0x2a ; 0094022a 1c2a
+ add byte [bx + si], 0x0 ; 0094022c 800000
+ add [bx + si], al ; 0094022f 0000
+ ret ; 00940231 c3
+ and cl, [bp + si + 0] ; 00940232 224a00
+ xor [si], bl ; 00940235 301c
+ sub ax, [bx + si + 0] ; 00940237 2b800000
+ add [bx + si], al ; 0094023b 0000
+ or ax, 0x4a23 ; 0094023d 0d234a
+ add [bx + si], dh ; 00940240 0030
+ sbb al, L1 ; 00940242 1c2c
+ add byte [bx + si], 0x0 ; 00940244 800000
+ add [bx + si], al ; 00940247 0000
+ push di ; 00940249 57
+ and cx, [bp + si + 0] ; 0094024a 234a00
+ xor [si], bl ; 0094024d 301c
+ sub ax, 0x80 ; 0094024f 2d8000
+ add [bx + si], al ; 00940252 0000
+ add [bx + di + 0x4a23], ah ; 00940254 00a1234a
+ add [bx + si], dh ; 00940258 0030
+ sbb al, 0x2e ; 0094025a 1c2e
+ add byte [bx + si], 0x0 ; 0094025c 800000
+ add [bx + si], al ; 0094025f 0000
+ jmp short L120 ; 00940261 eb23
+ dec dx ; 00940263 4a
+ add [bx + si], dh ; 00940264 0030
+ sbb al, 0x2f ; 00940266 1c2f
+ add byte [bx + si], 0x0 ; 00940268 800000
+ add [bx + si], al ; 0094026b 0000
+ xor ax, 0x4a24 ; 0094026d 35244a
+ add [bx + si], dh ; 00940270 0030
+ sbb al, 0x30 ; 00940272 1c30
+ add byte [bx + si], 0x0 ; 00940274 800000
+ add [bx + si], al ; 00940277 0000
+ jg L121 ; 00940279 7f24
+ dec dx ; 0094027b 4a
+ add [bx + si], dh ; 0094027c 0030
+ sbb al, 0x31 ; 0094027e 1c31
+ add byte [bx + si], 0x0 ; 00940280 800000
+ add [bx + si], al ; 00940283 0000
+ leave ; 00940285 c9
+ and al, L16 ; 00940286 24dd
+ add [bx + si], dh ; 00940288 0030
+ sbb al, 0x32 ; 0094028a 1c32
+ add byte [bx + si], 0x0 ; 0094028c 800000
+ add [bx + si], al ; 0094028f 0000
+ cmpsb ; 00940291 a6
+ and ax, L16 ; 00940292 25dd00
+ xor [si], bl ; 00940295 301c
+ xor ax, [bx + si + 0] ; 00940297 33800000
+ add [bx + si], al ; 0094029b 0000
+ and word L16, byte 0x30 ; 0094029d 8326dd0030
+ sbb al, 0x34 ; 009402a2 1c34
+ add byte [bx + si], 0x0 ; 009402a4 800000
+ add [bx + si], al ; 009402a7 0000
+ pusha ; 009402a9 60
+ daa ; 009402aa 27
+ fadd [bx + si] ; 009402ab dc00
+ xor [si], bl ; 009402ad 301c
+ inc sp ; 009402af 44
+ add byte [bx + si], 0x0 ; 009402b0 800000
+ add [bx + si], al ; 009402b3 0000
+ cmp al, 0x28 ; 009402b5 3c28
+ fadd [bx + si] ; 009402b7 dc00
+ xor [si], bl ; 009402b9 301c
+ inc bx ; 009402bb 43
+ add byte [bx + si], 0x0 ; 009402bc 800000
+ add [bx + si], al ; 009402bf 0000
+ add al, 0x80 ; 009402c1 0480
+ add [bx + si], ax ; 009402c3 0100
+ add [bx + si], al ; 009402c5 0000
+ add [bx + si], al ; 009402c7 0000
+ sbb [bx + di], ch ; 009402c9 1829
+ or [bx + si], ax ; 009402cb 0900
+ xor [si], bl ; 009402cd 301c
+ add [bx + si + 0], ax ; 009402cf 01800000
+ add [bx + si], al ; 009402d3 0000
+ add ax, 0x280 ; 009402d5 058002
+ add [bx + si], al ; 009402d8 0000
+ add [bx + si], al ; 009402da 0000
+ add [bx + di], ah ; 009402dc 0021
+ sub [bp + di], dx ; 009402de 2913
+ add [bx + si], dh ; 009402e0 0030
+ sbb al, 0x65 ; 009402e2 1c65
+ add byte [bx + si], 0x0 ; 009402e4 800000
+ add [bx + si], al ; 009402e7 0000
+ xor al, 0x29 ; 009402e9 3429
+ sbb [bx + si], al ; 009402eb 1800
+ xor [si], bl ; 009402ed 301c
+ a16 add byte [eax], 0x0 ; 009402ef 67800000
+ add [bx + si], al ; 009402f3 0000
+ push es ; 009402f5 06
+ add byte [bx], 0x0 ; 009402f6 800700
+ add [bx + si], al ; 009402f9 0000
+ add [bx + si], al ; 009402fb 0000
+ dec sp ; 009402fd 4c
+ sub [bp + si], cx ; 009402fe 290a
+ add [bx + si], dh ; 00940300 0030
+ sbb al, 0x7 ; 00940302 1c07
+ add byte [bx + si], 0x0 ; 00940304 800000
+ add [bx + si], al ; 00940307 0000
+ push si ; 00940309 56
+ sub [si], ax ; 0094030a 2904
+ add [bx + si], dh ; 0094030c 0030
+ sbb al, 0xd ; 0094030e 1c0d
+ add byte [bx + si], 0x0 ; 00940310 800000
+ add [bx + si], al ; 00940313 0000
+ pop dx ; 00940315 5a
+ sub L17, cx ; 00940316 290e0030
+ sbb al, 0x13 ; 0094031a 1c13
+ add byte [bx + si], 0x0 ; 0094031c 800000
+ add [bx + si], al ; 0094031f 0000
+ push 0x729 ; 00940321 682907
+ add [bx + si], dh ; 00940324 0030
+ sbb al, 0x3f ; 00940326 1c3f
+ add byte [bx + si], 0x0 ; 00940328 800000
+ add [bx + si], al ; 0094032b 0000
+ outsw ; 0094032d 6f
+ sub [si], ax ; 0094032e 2904
+ add [bx + si], dh ; 00940330 0030
+ sbb al, 0x0 ; 00940332 1c00
+ nop ; 00940334 90
+ add [bx + si], al ; 00940335 0000
+ add [bx + si], al ; 00940337 0000
+ jnc L122 ; 00940339 7329
+ add al, 0x0 ; 0094033b 0400
+ xor [si], bl ; 0094033d 301c
+ add ax, [bx + si + 0] ; 0094033f 03800000
+ add [bx + si], al ; 00940343 0000
+ ja L123 ; 00940345 7729
+ add al, [bx + si] ; 00940347 0200
+ xor [si], bl ; 00940349 301c
+ jle L124 ; 0094034b 7e80
+ add [bx + si], al ; 0094034d 0000
+ add [bx + si], al ; 0094034f 0000
+ adc [bx + si + 0x1], al ; 00940351 10800100
+ add [bx + si], al ; 00940355 0000
+ add [bx + si], al ; 00940357 0000
+ jns L125 ; 00940359 7929
+ push ds ; 0094035b 1e
+ add [bx + si], dh ; 0094035c 0030
+ or al, L4 ; 0094035e 0c01
+ add byte [bx + si], 0x0 ; 00940360 800000
+ add [bx + si], al ; 00940363 0000
+ add ax, [bx + si + 0x2] ; 00940365 03800200
+ add [bx + si], al ; 00940369 0000
+ add [bx + si], al ; 0094036b 0000
+ xchg ax, di ; 0094036d 97
+ sub [bx], bp ; 0094036e 292f
+ add [bx + si], dl ; 00940370 0010
+ sbb al, L4 ; 00940372 1c01
+ add byte [bx + si], 0x0 ; 00940374 800000
+ add [bx + si], al ; 00940377 0000
+ mov byte [bx + di], 0x13 ; 00940379 c62913
+ add [bx + si], dl ; 0094037c 0010
+ sbb al, 0x2 ; 0094037e 1c02
+ add byte [bx + si], 0x0 ; 00940380 800000
+ add [bx + si], al ; 00940383 0000
+ add [bx + si], al ; 00940385 0000
+ add dx, [bp + di + 0x4f] ; 00940387 03534f
+ dec sp ; 0094038a 4c
+ add dx, [bp + di + 0x4f] ; 0094038b 03534f
+ dec sp ; 0094038e 4c
+ add [bx + si], al ; 0094038f 0000
+ add [bx + di], al ; 00940391 0001
+ add [bx + si], cl ; 00940393 0008
+ add [di], cl ; 00940395 000d
+ add [bx + di], dl ; 00940397 0011
+ add [bx + si], al ; 00940399 0000
+ push es ; 0094039b 06
+ dec bx ; 0094039c 4b
+ inc bp ; 0094039d 45
+ push dx ; 0094039e 52
+ dec si ; 0094039f 4e
+ inc bp ; 009403a0 45
+ dec sp ; 009403a1 4c
+ add al, 0x55 ; 009403a2 0455
+ push bx ; 009403a4 53
+ inc bp ; 009403a5 45
+ push dx ; 009403a6 52
+ add ax, [bx + 0x44] ; 009403a7 034744
+ dec cx ; 009403aa 49
+ add ax, 0x4853 ; 009403ab 055348
+ inc bp ; 009403ae 45
+ dec sp ; 009403af 4c
+ dec sp ; 009403b0 4c
+ add [bp + di], dl ; 009403b1 0013
+ dec bp ; 009403b3 4d
+ imul sp, [bp + di + 0x72], 0x736f ; 009403b4 6963726f73
+ outsw ; 009403b9 6f
+ o32 jz L126 ; 009403ba 667420
+ push bx ; 009403bd 53
+ outsw ; 009403be 6f
+ insb ; 009403bf 6c
+ imul si, [si + 0x61], 0x7269 ; 009403c0 6974616972
+ gs add gs:[bx + si], al ; 009403c5 650000
+ add [bx + si], al ; 009403c8 0000
+ add [bx + si], al ; 009403ca 0000
+ add [bx + si], al ; 009403cc 0000
+ add [bx + si], al ; 009403ce 0000
+ add [bx + si], al ; 009403d0 0000
+ add [bx + si], al ; 009403d2 0000
+ add [bx + si], al ; 009403d4 0000
+ add [bx + si], al ; 009403d6 0000
+ add [bx + si], al ; 009403d8 0000
+ add [bx + si], al ; 009403da 0000
+ add [bx + si], al ; 009403dc 0000
+ add [bx + si], al ; 009403de 0000
+ add [bx + si], al ; 009403e0 0000
+ add [bx + si], al ; 009403e2 0000
+ add [bx + si], al ; 009403e4 0000
+ add [bx + si], al ; 009403e6 0000
+ add [bx + si], al ; 009403e8 0000
+ add [bx + si], al ; 009403ea 0000
+ add [bx + si], al ; 009403ec 0000
+ add [bx + si], al ; 009403ee 0000
+ add [bx + si], al ; 009403f0 0000
+ add [bx + si], al ; 009403f2 0000
+ add [bx + si], al ; 009403f4 0000
+ add [bx + si], al ; 009403f6 0000
+ add [bx + si], al ; 009403f8 0000
+ add [bx + si], al ; 009403fa 0000
+ add [bx + si], al ; 009403fc 0000
+ add [bx + si], al ; 009403fe 0000
+ add [bx + si], al ; 00940400 0000
+ add [bx + si], al ; 00940402 0000
+ add [bx + si], al ; 00940404 0000
+ add [bx + si], al ; 00940406 0000
+ add [bx + si], al ; 00940408 0000
+ add [bx + si], al ; 0094040a 0000
+ add [bx + si], al ; 0094040c 0000
+ add [bx + si], al ; 0094040e 0000
+ add [bx + si], al ; 00940410 0000
+ add al, cl ; 00940412 00c8
+ sbb [bx + si], al ; 00940414 1800
+ add [bp + di + 0xc7e], al ; 00940416 00837e0c
+ add [si + 0x55], dh ; 0094041a 007455
+ push word [bp + 0xc] ; 0094041d ff760c
+ push L23 ; 00940420 68f001
+ push 0x2 ; 00940423 6a02
+ callf ; 00940425 9affff0000
+ push word L23 ; 0094042a ff36f001
+ callf ; 0094042e 9affff0000
+ mov [bp + 0xffffffec], ax ; 00940433 8946ec
+ push word L23 ; 00940436 ff36f001
+ push 0x0 ; 0094043a 6a00
+ push 0x0 ; 0094043c 6a00
+ push 0x0 ; 0094043e 6a00
+ push 0x0 ; 00940440 6a00
+ push 0x0 ; 00940442 6a00
+ push 0x43 ; 00940444 6a43
+ callf ; 00940446 9affff0000
+ push word L23 ; 0094044b ff36f001
+ callf ; 0094044f 9affff0000
+ or ax, ax ; 00940454 0bc0
+ jz L127 ; 00940456 740d
+ push word L23 ; 00940458 ff36f001
+ push 0x9 ; 0094045c 6a09
+ callf ; 0094045e 9affff0000
+ jmp short L128 ; 00940463 eb08
+ push word [bp + 0xffffffec] ; 00940465 ff76ec
+ callf ; 00940468 9affff0000
+ xor ax, ax ; 0094046d 33c0
+ jmp L129 ; 0094046f e98200
+ o32 push dword [bp + 0xc] ; 00940472 66ff760c
+ o32 push dword [bp + 0x8] ; 00940476 66ff7608
+ push word [bp + 0x6] ; 0094047a ff7606
+ push cs ; 0094047d 0e
+ call L18 ; 0094047e e87800
+ or ax, ax ; 00940481 0bc0
+ jz L128 ; 00940483 74e8
+ push 0x29 ; 00940485 6a29
+ callf ; 00940487 9affff0000
+ push ax ; 0094048c 50
+ push ds ; 0094048d 1e
+ push 0x3c ; 0094048e 683c00
+ callf ; 00940491 9affff0000
+ mov [bp + 0xffffffe8], ax ; 00940496 8946e8
+ mov [bp + 0xffffffea], dx ; 00940499 8956ea
+ or dx, ax ; 0094049c 0bd0
+ jz L130 ; 0094049e 7407
+ push L4 ; 009404a0 6a01
+ push L4 ; 009404a2 6a01
+ call far oword [bp + 0xffffffe8] ; 009404a4 ff5ee8
+ lea ax, [bp + 0xffffffee] ; 009404a7 8d46ee
+ push ss ; 009404aa 16
+ push ax ; 009404ab 50
+ push 0x0 ; 009404ac 6a00
+ push 0x0 ; 009404ae 6a00
+ push 0x0 ; 009404b0 6a00
+ callf ; 009404b2 9ac8000000
+ or ax, ax ; 009404b7 0bc0
+ jz L131 ; 009404b9 7428
+ lea ax, [bp + 0xffffffee] ; 009404bb 8d46ee
+ push ss ; 009404be 16
+ push ax ; 009404bf 50
+ callf ; 009404c0 9affff0000
+ lea ax, [bp + 0xffffffee] ; 009404c5 8d46ee
+ push ss ; 009404c8 16
+ push ax ; 009404c9 50
+ callf ; 009404ca 9affff0000
+ lea ax, [bp + 0xffffffee] ; 009404cf 8d46ee
+ push ss ; 009404d2 16
+ push ax ; 009404d3 50
+ push 0x0 ; 009404d4 6a00
+ push 0x0 ; 009404d6 6a00
+ push 0x0 ; 009404d8 6a00
+ callf ; 009404da 9affff0000
+ or ax, ax ; 009404df 0bc0
+ jnz L132 ; 009404e1 75d8
+ o32 cmp dword [bp + 0xffffffe8], byte 0x0 ; 009404e3 66837ee800
+ jz L133 ; 009404e8 7407
+ push L4 ; 009404ea 6a01
+ push 0x0 ; 009404ec 6a00
+ call far oword [bp + 0xffffffe8] ; 009404ee ff5ee8
+ mov ax, [bp + 0xfffffff2] ; 009404f1 8b46f2
+ leave ; 009404f4 c9
+ retf 0x0a ; 009404f5 ca0a00
+ nop ; 009404f8 90
+ enter 0x72, 0x0 ; 009404f9 c8720000
+ mov ax, [bp + 0xe] ; 009404fd 8b460e
+ mov [0x2b0], ax ; 00940500 a3b002
+ push 0x200 ; 00940503 680002
+ push 0x12c ; 00940506 682c01
+ callf ; 00940509 9a2806d401
+ push ds ; 0094050e 1e
+ push L84 ; 0094050f 686802
+ push ds ; 00940512 1e
+ push L82 ; 00940513 686a02
+ callf ; 00940516 9a0000ffff
+ or ax, ax ; 0094051b 0bc0
+ jz L134 ; 0094051d 741d
+ push 0x0 ; 0094051f 6a00
+ push 0x0 ; 00940521 6a00
+ push 0x7f00 ; 00940523 68007f
+ callf ; 00940526 9affff0000
+ mov [bp + 0xffffffb4], ax ; 0094052b 8946b4
+ push 0x0 ; 0094052e 6a00
+ callf ; 00940530 9affff0000
+ mov [bp + 0xffffffd8], ax ; 00940535 8946d8
+ or ax, ax ; 00940538 0bc0
+ jnz L135 ; 0094053a 7503
+ jmp L136 ; 0094053c e99802
+ push ax ; 0094053f 50
+ lea ax, [bp + 0xffffffb8] ; 00940540 8d46b8
+ push ss ; 00940543 16
+ push ax ; 00940544 50
+ callf ; 00940545 9affff0000
+ mov ax, [bp + 0xffffffb8] ; 0094054a 8b46b8
+ mov [0x23e], ax ; 0094054d a33e02
+ mov ax, [bp + 0xffffffc4] ; 00940550 8b46c4
+ mov [0x23c], ax ; 00940553 a33c02
+ push word [bp + 0xffffffd8] ; 00940556 ff76d8
+ push L59 ; 00940559 6a18
+ callf ; 0094055b 9a5e010000
+ cmp ax, 0x02 ; 00940560 3d0200
+ jnz L102 ; 00940563 7506
+ mov word L36, L4 ; 00940565 c706f6010100
+ push word [bp + 0xffffffd8] ; 0094056b ff76d8
+ push 0x8 ; 0094056e 6a08
+ callf ; 00940570 9a6b010000
+ mov [0x24c], ax ; 00940575 a34c02
+ push word [bp + 0xffffffd8] ; 00940578 ff76d8
+ push 0xa ; 0094057b 6a0a
+ callf ; 0094057d 9affff0000
+ mov [0x24e], ax ; 00940582 a34e02
+ cmp ax, 0x12c ; 00940585 3d2c01
+ jge L137 ; 00940588 7d05
+ mov ax, L4 ; 0094058a b80100
+ jmp short L138 ; 0094058d eb02
+ xor ax, ax ; 0094058f 33c0
+ mov [0x38], ax ; 00940591 a33800
+ or ax, ax ; 00940594 0bc0
+ jz L139 ; 00940596 740c
+ mov cx, 0x02 ; 00940598 b90200
+ mov ax, [0x26a] ; 0094059b a16a02
+ cwd ; 0094059e 99
+ idiv cx, ax ; 0094059f f7f9
+ mov [0x26a], ax ; 009405a1 a36a02
+ push 0x0 ; 009405a4 6a00
+ push word [bp + 0xffffffd8] ; 009405a6 ff76d8
+ callf ; 009405a9 9affff0000
+ cmp word L36, byte 0x0 ; 009405ae 833ef60100
+ jz L140 ; 009405b3 7408
+ mov ax, 0xffff ; 009405b5 b8ffff
+ mov dx, 0xff ; 009405b8 baff00
+ jmp short L141 ; 009405bb eb05
+ mov ax, 0x8000 ; 009405bd b80080
+ xor dx, dx ; 009405c0 33d2
+ mov [0x2b2], ax ; 009405c2 a3b202
+ mov L42, dx ; 009405c5 8916b402
+ push dx ; 009405c9 52
+ push ax ; 009405ca 50
+ callf ; 009405cb 9affff0000
+ mov [0x266], ax ; 009405d0 a36602
+ callf ; 009405d3 9affff0000
+ push ax ; 009405d8 50
+ callf ; 009405d9 9a3201ffff
+ pop bx ; 009405de 5b
+ push 0x26e ; 009405df 686e02
+ push 0x64 ; 009405e2 6a64
+ callf ; 009405e4 9a2806de01
+ push 0x250 ; 009405e9 685002
+ push 0x65 ; 009405ec 6a65
+ callf ; 009405ee 9a2806e901
+ lea ax, [bp + 0xffffff98] ; 009405f3 8d4698
+ push ax ; 009405f6 50
+ push 0x67 ; 009405f7 6a67
+ callf ; 009405f9 9a2806ffff
+ lea ax, [bp + 0xffffff98] ; 009405fe 8d4698
+ push ss ; 00940601 16
+ push ax ; 00940602 50
+ callf ; 00940603 9affff0000
+ mov [0x1f8], ax ; 00940608 a3f801
+ mov word [bp + 0xffffffb2], 0x00 ; 0094060b c746b20000
+ o32 mov eax, [bp + 0x8] ; 00940610 668b4608
+ mov dx, [bp + 0xa] ; 00940614 8b560a
+ o32 mov [bp + 0xffffffae], eax ; 00940617 668946ae
+ mov es, dx ; 0094061b 8ec2
+ mov bx, ax ; 0094061d 8bd8
+ es cmp byte es:[bx], 0x0 ; 0094061f 26803f00
+ jz L142 ; 00940623 7420
+ es cmp byte es:[bx], 0x2f ; 00940625 26803f2f
+ jnz L143 ; 00940629 7507
+ es cmp byte es:[bx + 0x1], 0x49 ; 0094062b 26807f0149
+ jz L144 ; 00940630 740e
+ inc word [bp + 0xffffffae] ; 00940632 ff46ae
+ mov bx, [bp + 0xffffffae] ; 00940635 8b5eae
+ es cmp byte es:[bx], 0x0 ; 00940638 26803f00
+ jnz L145 ; 0094063c 75e7
+ jmp short L142 ; 0094063e eb05
+ mov word [bp + 0xffffffb2], L4 ; 00940640 c746b20100
+ cmp word [bp + 0xc], byte 0x0 ; 00940645 837e0c00
+ jnz L146 ; 00940649 7556
+ mov word [bp + 0xffffffe6], 0x2008 ; 0094064b c746e60820
+ mov word [bp + 0xffffffe8], 0x40c ; 00940650 c746e80c04
+ mov word [bp + 0xffffffea], 0xffff ; 00940655 c746eaffff
+ o32 mov dword [bp + 0xffffffec], 0x0000 ; 0094065a 66c746ec00000000
+ mov ax, [0x2b0] ; 00940662 a1b002
+ mov [bp + 0xfffffff0], ax ; 00940665 8946f0
+ push ax ; 00940668 50
+ push ds ; 00940669 1e
+ push L12 ; 0094066a 684b00
+ callf ; 0094066d 9affff0000
+ mov [bp + 0xfffffff2], ax ; 00940672 8946f2
+ mov ax, [bp + 0xffffffb4] ; 00940675 8b46b4
+ mov [bp + 0xfffffff4], ax ; 00940678 8946f4
+ mov ax, [0x266] ; 0094067b a16602
+ mov [bp + 0xfffffff6], ax ; 0094067e 8946f6
+ o32 mov dword [bp + 0xfffffff8], L4 ; 00940681 66c746f801000000
+ mov word [bp + 0xfffffffc], 0x22 ; 00940689 c746fc2200
+ mov word [bp + 0xfffffffe], ds ; 0094068e 8c5efe
+ lea ax, [bp + 0xffffffe6] ; 00940691 8d46e6
+ push ss ; 00940694 16
+ push ax ; 00940695 50
+ callf ; 00940696 9affff0000
+ or ax, ax ; 0094069b 0bc0
+ je L136 ; 0094069d 0f843601
+ mov ax, [0x268] ; 009406a1 a16802
+ imul cx, ax, 0x7 ; 009406a4 6bc807
+ cwd ; 009406a7 99
+ and dx, byte 0x7 ; 009406a8 83e207
+ add ax, dx ; 009406ab 03c2
+ sar ax, byte 0x3 ; 009406ad c1f803
+ add ax, 0x03 ; 009406b0 050300
+ mov [0x240], ax ; 009406b3 a34002
+ shl ax, byte 0x3 ; 009406b6 c1e003
+ add cx, ax ; 009406b9 03c8
+ mov [bp + 0xffffff92], cx ; 009406bb 894e92
+ mov ax, [0x26a] ; 009406be a16a02
+ shl ax, byte 0x2 ; 009406c1 c1e002
+ mov [bp + 0xffffff94], ax ; 009406c4 894694
+ o32 mov dword [bp + 0xffffff8e], 0x0000 ; 009406c7 66c7468e00000000
+ lea ax, [bp + 0xffffff8e] ; 009406cf 8d468e
+ push ss ; 009406d2 16
+ push ax ; 009406d3 50
+ push 0xcf ; 009406d4 68cf00
+ push 0x0 ; 009406d7 6a00
+ push L4 ; 009406d9 6a01
+ push 0x0 ; 009406db 6a00
+ push 0x200 ; 009406dd 680002
+ callf ; 009406e0 9affff0000
+ mov ax, [bp + 0xffffff8e] ; 009406e5 8b468e
+ sub [bp + 0xffffff92], ax ; 009406e8 294692
+ mov ax, [0x24e] ; 009406eb a14e02
+ mov cx, [bp + 0xffffff90] ; 009406ee 8b4e90
+ sub [bp + 0xffffff94], cx ; 009406f1 294e94
+ cmp [bp + 0xffffff94], ax ; 009406f4 394694
+ jle L147 ; 009406f7 7e03
+ mov [bp + 0xffffff94], ax ; 009406f9 894694
+ push 0x0 ; 009406fc 6a00
+ push 0x200 ; 009406fe 680002
+ push ds ; 00940701 1e
+ push 0x22 ; 00940702 682200
+ push ds ; 00940705 1e
+ push 0x26e ; 00940706 686e02
+ cmp word [bp + 0xffffffb2], byte 0x0 ; 00940709 837eb200
+ jz L148 ; 0094070d 7407
+ xor ax, ax ; 0094070f 33c0
+ mov dx, 0x22cf ; 00940711 bacf22
+ jmp short L115 ; 00940714 eb05
+ xor ax, ax ; 00940716 33c0
+ mov dx, 0x2cf ; 00940718 bacf02
+ push dx ; 0094071b 52
+ push ax ; 0094071c 50
+ push 0x8000 ; 0094071d 680080
+ push ax ; 00940720 50
+ push word [bp + 0xffffff92] ; 00940721 ff7692
+ push word [bp + 0xffffff94] ; 00940724 ff7694
+ push ax ; 00940727 50
+ push ax ; 00940728 50
+ push word L51 ; 00940729 ff36b002
+ push ax ; 0094072d 50
+ push ax ; 0094072e 50
+ callf ; 0094072f 9affff0000
+ or ax, ax ; 00940734 0bc0
+ je L136 ; 00940736 0f849d00
+ lea ax, [bp + 0xffffffac] ; 0094073a 8d46ac
+ push ax ; 0094073d 50
+ push cs ; 0094073e 0e
+ call L149 ; 0094073f e8d105
+ push 0x245 ; 00940742 684502
+ push 0x85a ; 00940745 685a08
+ push word [bp + 0xe] ; 00940748 ff760e
+ callf ; 0094074b 9affff0000
+ mov [0x1f2], ax ; 00940750 a3f201
+ mov L53, dx ; 00940753 8916f401
+ mov ax, dx ; 00940757 8bc2
+ or ax, L54 ; 00940759 0b06f201
+ jz L150 ; 0094075d 747d
+ push word L23 ; 0094075f ff36f001
+ o32 push 0x29a00fa ; 00940763 6668fa009a02
+ push dx ; 00940769 52
+ push word L54 ; 0094076a ff36f201
+ callf ; 0094076e 9affff0000
+ or ax, ax ; 00940773 0bc0
+ jz L136 ; 00940775 7460
+ callf ; 00940777 9a24026f03
+ push word [bp + 0xffffffac] ; 0094077c ff76ac
+ callf ; 0094077f 9ac6000b05
+ push word L23 ; 00940784 ff36f001
+ push word [bp + 0x6] ; 00940788 ff7606
+ callf ; 0094078b 9a4c000000
+ push word L23 ; 00940790 ff36f001
+ callf ; 00940794 9affff0000
+ cmp word [bp + 0xc], L4 ; 00940799 837e0c01
+ sbb ax, ax ; 0094079d 1bc0
+ neg ax ; 0094079f f7d8
+ push ax ; 009407a1 50
+ callf ; 009407a2 9a00009e03
+ cmp word L1, byte 0x0 ; 009407a7 833e2c0000
+ jz L151 ; 009407ac 7405
+ callf ; 009407ae 9a6600ffff
+ cmp word [bp + 0x6], byte 0x7 ; 009407b3 837e0607
+ jz L152 ; 009407b7 7419
+ cmp word [bp + 0x6], byte 0x6 ; 009407b9 837e0606
+ jz L152 ; 009407bd 7413
+ push word L23 ; 009407bf ff36f001
+ o32 push 0x11103e8 ; 009407c3 6668e8031101
+ push 0x0 ; 009407c9 6a00
+ push 0x0 ; 009407cb 6a00
+ callf ; 009407cd 9acb040000
+ mov ax, L4 ; 009407d2 b80100
+ jmp short L153 ; 009407d5 eb07
+ callf ; 009407d7 9a1806f900
+ xor ax, ax ; 009407dc 33c0
+ leave ; 009407de c9
+ retf 0x0a ; 009407df ca0a00
+ nop ; 009407e2 90
+ enter 0x20, 0x0 ; 009407e3 c8200000
+ push word [bp + 0x6] ; 009407e7 ff7606
+ lea ax, [bp + 0xffffffe0] ; 009407ea 8d46e0
+ push ss ; 009407ed 16
+ push ax ; 009407ee 50
+ callf ; 009407ef 9affff0000
+ cmp word L59, byte 0x0 ; 009407f4 833e180000
+ jz L154 ; 009407f9 7412
+ push word L59 ; 009407fb ff361800
+ push 0x7 ; 009407ff 6a07
+ lea ax, [bp + 0xffffffe0] ; 00940801 8d46e0
+ push ax ; 00940804 50
+ push 0x0 ; 00940805 6a00
+ mov bx, L59 ; 00940807 8b1e1800
+ call far oword [bx] ; 0094080b ff1f
+ push word [bp + 0x6] ; 0094080d ff7606
+ lea ax, [bp + 0xffffffe0] ; 00940810 8d46e0
+ push ss ; 00940813 16
+ push ax ; 00940814 50
+ callf ; 00940815 9affff0000
+ leave ; 0094081a c9
+ retf 0x02 ; 0094081b ca0200
+ nop ; 0094081e 90
+ enter 0xd6, 0x0 ; 0094081f c8d60000
+ mov ax, [bp + 0xc] ; 00940823 8b460c
+ dec ax ; 00940826 48
+ je L155 ; 00940827 0f84bf00
+ dec ax ; 0094082b 48
+ je L156 ; 0094082c 0f84c300
+ dec ax ; 00940830 48
+ je L157 ; 00940831 0f846a01
+ dec ax ; 00940835 48
+ dec ax ; 00940836 48
+ je L158 ; 00940837 0f84f400
+ dec ax ; 0094083b 48
+ je L159 ; 0094083c 0f846701
+ dec ax ; 00940840 48
+ je L160 ; 00940841 0f848701
+ dec ax ; 00940845 48
+ je L161 ; 00940846 0f846f01
+ sub ax, 0x07 ; 0094084a 2d0700
+ je L162 ; 0094084d 0f848901
+ dec ax ; 00940851 48
+ je L163 ; 00940852 0f849901
+ sub ax, 0xf0 ; 00940856 2df000
+ je L164 ; 00940859 0f84b401
+ sub ax, 0x11 ; 0094085d 2d1100
+ je L165 ; 00940860 0f84c101
+ sub ax, 0x05 ; 00940864 2d0500
+ je L166 ; 00940867 0f845302
+ sub ax, 0x09 ; 0094086b 2d0900
+ je L67 ; 0094086e 0f84dc02
+ sub ax, 0xe1 ; 00940872 2de100
+ je L167 ; 00940875 0f840303
+ dec ax ; 00940879 48
+ je L168 ; 0094087a 0f840f03
+ dec ax ; 0094087e 48
+ je L70 ; 0094087f 0f842303
+ dec ax ; 00940883 48
+ je L169 ; 00940884 0f843403
+ mov ax, [0x1f8] ; 00940888 a1f801
+ cmp [bp + 0xc], ax ; 0094088b 39460c
+ jne L170 ; 0094088e 0f855403
+ mov ax, [bp + 0xa] ; 00940892 8b460a
+ dec ax ; 00940895 48
+ jz L171 ; 00940896 7409
+ dec ax ; 00940898 48
+ jz L49 ; 00940899 7410
+ dec ax ; 0094089b 48
+ jz L172 ; 0094089c 7431
+ jmp L170 ; 0094089e e94503
+ mov ax, [0x268] ; 009408a1 a16802
+ mov dx, L82 ; 009408a4 8b166a02
+ jmp L173 ; 009408a8 e94b03
+ les bx, ; 009408ab c45e0626ff3726
+ push word [bx + 0x2] ; 009408b2 ff7702
+ es push word es:[bx + 0x4] ; 009408b5 26ff7704
+ es push word es:[bx + 0x6] ; 009408b9 26ff7706
+ es push word es:[bx + 0x8] ; 009408bd 26ff7708
+ o32 push dword es:[bx + 0xa] ; 009408c1 6626ff770a
+ callf ; 009408c6 9a5a031005
+ cwd ; 009408cb 99
+ jmp L173 ; 009408cc e92703
+ push word L23 ; 009408cf ff36f001
+ o32 push 0x112f060 ; 009408d3 666860f01201
+ push 0x0 ; 009408d9 6a00
+ push 0x0 ; 009408db 6a00
+ callf ; 009408dd 9affff0000
+ mov ax, L4 ; 009408e2 b80100
+ xor dx, dx ; 009408e5 33d2
+ jmp L173 ; 009408e7 e90c03
+ mov ax, [bp + 0xe] ; 009408ea 8b460e
+ mov [0x1f0], ax ; 009408ed a3f001
+ jmp L170 ; 009408f0 e9f302
+ push word L23 ; 009408f3 ff36f001
+ push 0x29a ; 009408f7 689a02
+ callf ; 009408fa 9affff0000
+ o32 push dword L54 ; 009408ff 66ff36f201
+ callf ; 00940904 9affff0000
+ push word L59 ; 00940909 ff361800
+ push L4 ; 0094090d 6a01
+ push 0x0 ; 0094090f 6a00
+ push 0x0 ; 00940911 6a00
+ mov bx, L59 ; 00940913 8b1e1800
+ call far oword [bx] ; 00940917 ff1f
+ push L4 ; 00940919 6a01
+ callf ; 0094091b 9ac600ffff
+ callf ; 00940920 9a78080601
+ push 0x0 ; 00940925 6a00
+ callf ; 00940927 9affff0000
+ jmp L170 ; 0094092c e9b702
+ push word [bp + 0xe] ; 0094092f ff760e
+ callf ; 00940932 9a3d000000
+ mov [0x14], ax ; 00940937 a31400
+ push word [bp + 0xe] ; 0094093a ff760e
+ push ds ; 0094093d 1e
+ push 0x244 ; 0094093e 684402
+ callf ; 00940941 9affff0000
+ imul ax, L84, 0x7 ; 00940946 6b06680207
+ sub ax, [bp + 0x6] ; 0094094b 2b4606
+ neg ax ; 0094094e f7d8
+ cwd ; 00940950 99
+ and dx, byte 0x7 ; 00940951 83e207
+ add ax, dx ; 00940954 03c2
+ sar ax, byte 0x3 ; 00940956 c1f803
+ mov [bp + 0xffffff92], ax ; 00940959 894692
+ mov ax, [0x268] ; 0094095c a16802
+ cwd ; 0094095f 99
+ and dx, byte 0x7 ; 00940960 83e207
+ add ax, dx ; 00940963 03c2
+ sar ax, byte 0x3 ; 00940965 c1f803
+ add ax, 0x03 ; 00940968 050300
+ mov [bp + 0xffffff90], ax ; 0094096b 894690
+ cmp [bp + 0xffffff92], ax ; 0094096e 394692
+ jge L174 ; 00940971 7d0e
+ mov ax, [0x240] ; 00940973 a14002
+ cmp [bp + 0xffffff90], ax ; 00940976 394690
+ jz L174 ; 00940979 7406
+ mov ax, [bp + 0xffffff90] ; 0094097b 8b4690
+ mov [bp + 0xffffff92], ax ; 0094097e 894692
+ mov ax, [bp + 0xffffff92] ; 00940981 8b4692
+ cmp [bp + 0xffffff90], ax ; 00940984 394690
+ jg L157 ; 00940987 7f16
+ mov [0x240], ax ; 00940989 a34002
+ callf ; 0094098c 9aa001ffff
+ push word [bp + 0xe] ; 00940991 ff760e
+ push 0x0 ; 00940994 6a00
+ push 0x0 ; 00940996 6a00
+ push L4 ; 00940998 6a01
+ callf ; 0094099a 9affff0000
+ callf ; 0094099f 9aca019203
+ jmp L170 ; 009409a4 e93f02
+ cmp word [bp + 0xa], byte 0x0 ; 009409a7 837e0a00
+ je L170 ; 009409ab 0f843702
+ push word [bp + 0xe] ; 009409af ff760e
+ push cs ; 009409b2 0e
+ call L175 ; 009409b3 e82dfe
+ jmp L170 ; 009409b6 e92d02
+ mov bx, L59 ; 009409b9 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 009409bd 837f2600
+ jz L160 ; 009409c1 7409
+ push bx ; 009409c3 53
+ push 0x4 ; 009409c4 6a04
+ push 0x0 ; 009409c6 6a00
+ push L4 ; 009409c8 6a01
+ call far oword [bx] ; 009409ca ff1f
+ cmp word [bp + 0xc], byte 0x7 ; 009409cc 837e0c07
+ jne L176 ; 009409d0 0f850a02
+ mov ax, L4 ; 009409d4 b80100
+ jmp L177 ; 009409d7 e90602
+ cmp word L178, byte 0x0 ; 009409da 833e140000
+ jne L170 ; 009409df 0f850302
+ push word [bp + 0xe] ; 009409e3 ff760e
+ push cs ; 009409e6 0e
+ call L175 ; 009409e7 e8f9fd
+ xor ax, ax ; 009409ea 33c0
+ jmp L179 ; 009409ec e9f6fe
+ lea ax, [bp + 0xffffff94] ; 009409ef 8d4694
+ push ax ; 009409f2 50
+ push 0x69 ; 009409f3 6a69
+ callf ; 009409f5 9a2806c703
+ push word L23 ; 009409fa ff36f001
+ lea ax, [bp + 0xffffff94] ; 009409fe 8d4694
+ push ss ; 00940a01 16
+ push ax ; 00940a02 50
+ push 0x2 ; 00940a03 6a02
+ push 0x0 ; 00940a05 6a00
+ push 0x0 ; 00940a07 6a00
+ callf ; 00940a09 9affff0000
+ jmp L170 ; 00940a0e e9d501
+ push word L59 ; 00940a11 ff361800
+ push 0x2 ; 00940a15 6a02
+ push word [bp + 0xa] ; 00940a17 ff760a
+ push 0x0 ; 00940a1a 6a00
+ mov bx, L59 ; 00940a1c 8b1e1800
+ call far oword [bx] ; 00940a20 ff1f
+ jmp L170 ; 00940a22 e9c101
+ mov ax, [bp + 0xa] ; 00940a25 8b460a
+ inc ax ; 00940a28 40
+ jz L180 ; 00940a29 7419
+ sub ax, 0x3e9 ; 00940a2b 2de903
+ jz L181 ; 00940a2e 741e
+ dec ax ; 00940a30 48
+ jz L182 ; 00940a31 7426
+ dec ax ; 00940a33 48
+ jz L183 ; 00940a34 742d
+ dec ax ; 00940a36 48
+ jz L184 ; 00940a37 7432
+ dec ax ; 00940a39 48
+ jz L185 ; 00940a3a 7437
+ sub ax, 0x3e4 ; 00940a3c 2de403
+ jz L62 ; 00940a3f 7447
+ jmp L170 ; 00940a41 e9a201
+ push word [bp + 0xa] ; 00940a44 ff760a
+ push cs ; 00940a47 0e
+ call L186 ; 00940a48 e89402
+ jmp L170 ; 00940a4b e99801
+ push L4 ; 00940a4e 6a01
+ push 0x0 ; 00940a50 6a00
+ push cs ; 00940a52 0e
+ call L187 ; 00940a53 e85902
+ jmp L170 ; 00940a56 e98d01
+ push word L59 ; 00940a59 ff361800
+ push 0x9 ; 00940a5d 6a09
+ push 0x0 ; 00940a5f 6a00
+ jmp short L188 ; 00940a61 ebb7
+ callf ; 00940a63 9a18045b06
+ jmp L170 ; 00940a68 e97b01
+ callf ; 00940a6b 9af801ffff
+ jmp L170 ; 00940a70 e97301
+ push word [bp + 0xe] ; 00940a73 ff760e
+ o32 push 0x112f060 ; 00940a76 666860f01201
+ push 0x0 ; 00940a7c 6a00
+ push 0x0 ; 00940a7e 6a00
+ callf ; 00940a80 9abb030000
+ jmp L170 ; 00940a85 e95e01
+ push word L51 ; 00940a88 ff36b002
+ push 0x6c ; 00940a8c 6a6c
+ lea ax, [bp + 0xffffff2c] ; 00940a8e 8d862cff
+ push ss ; 00940a92 16
+ push ax ; 00940a93 50
+ push 0x64 ; 00940a94 6a64
+ callf ; 00940a96 9affff0000
+ push word [bp + 0xe] ; 00940a9b ff760e
+ push ds ; 00940a9e 1e
+ push 0x26e ; 00940a9f 686e02
+ lea ax, [bp + 0xffffff2c] ; 00940aa2 8d862cff
+ push ss ; 00940aa6 16
+ push ax ; 00940aa7 50
+ push word L51 ; 00940aa8 ff36b002
+ push ds ; 00940aac 1e
+ push 0x4f ; 00940aad 684f00
+ callf ; 00940ab0 9a5b020000
+ push ax ; 00940ab5 50
+ callf ; 00940ab6 9affff0000
+ jmp L170 ; 00940abb e92801
+ push word [bp + 0xe] ; 00940abe ff760e
+ callf ; 00940ac1 9affff0000
+ mov [bp + 0xfffffffe], ax ; 00940ac6 8946fe
+ mov bx, L59 ; 00940ac9 8b1e1800
+ cmp word [bx + 0x4], byte 0x0 ; 00940acd 837f0400
+ jz L189 ; 00940ad1 740e
+ cmp word [bx + 0x2c], byte 0xff ; 00940ad3 837f2cff
+ jnz L189 ; 00940ad7 7508
+ mov word [bp + 0xffffff2a], 0x00 ; 00940ad9 c7862aff0000
+ jmp short L190 ; 00940adf eb06
+ mov word [bp + 0xffffff2a], 0x03 ; 00940ae1 c7862aff0300
+ push ax ; 00940ae7 50
+ push 0x3e9 ; 00940ae8 68e903
+ push word [bp + 0xffffff2a] ; 00940aeb ffb62aff
+ callf ; 00940aef 9afa060000
+ push word [bp + 0xfffffffe] ; 00940af4 ff76fe
+ push 0x3e8 ; 00940af7 68e803
+ mov bx, L59 ; 00940afa 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 00940afe 837f2cff
+ jz L191 ; 00940b02 7405
+ mov ax, 0x03 ; 00940b04 b80300
+ jmp short L192 ; 00940b07 eb02
+ xor ax, ax ; 00940b09 33c0
+ push ax ; 00940b0b 50
+ callf ; 00940b0c 9a17070000
+ push word [bp + 0xfffffffe] ; 00940b11 ff76fe
+ push L91 ; 00940b14 68ea03
+ mov bx, L59 ; 00940b17 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 00940b1b 837f2cff
+ jz L193 ; 00940b1f 7405
+ mov ax, 0x03 ; 00940b21 b80300
+ jmp short L194 ; 00940b24 eb02
+ xor ax, ax ; 00940b26 33c0
+ push ax ; 00940b28 50
+ callf ; 00940b29 9a34070000
+ push word [bp + 0xfffffffe] ; 00940b2e ff76fe
+ push 0x7d0 ; 00940b31 68d007
+ mov bx, L59 ; 00940b34 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 00940b38 837f2cff
+ jz L195 ; 00940b3c 7405
+ mov ax, 0x03 ; 00940b3e b80300
+ jmp short L196 ; 00940b41 eb02
+ xor ax, ax ; 00940b43 33c0
+ push ax ; 00940b45 50
+
+ .section .codeSection3, @progbits
+ .align 0
+
+ add [bx + si], al ; 0094000b 0000
+ ill_grp_4 ; 0094000d fe15
+ fld [bx + si] ; 0094000f dd00
+ xor [si], bl ; 00940011 301c
+ or ax, 0x80 ; 00940013 0d8000
+ add [bx + si], al ; 00940016 0000
+ add bl, bl ; 00940018 00db
+ push ss ; 0094001a 16
+ dec bx ; 0094001b 4b
+ add [bx + si], dh ; 0094001c 0030
+ sbb al, 0xe ; 0094001e 1c0e
+ add byte [bx + si], 0x0 ; 00940020 800000
+ add [bx + si], al ; 00940023 0000
+ es pop ss ; 00940025 2617
+ dec bx ; 00940027 4b
+ add [bx + si], dh ; 00940028 0030
+ sbb al, 0xf ; 0094002a 1c0f
+ add byte [bx + si], 0x0 ; 0094002c 800000
+ add [bx + si], al ; 0094002f 0000
+ jno L197 ; 00940031 7117
+ dec bx ; 00940033 4b
+ add [bx + si], dh ; 00940034 0030
+
+L2:
+ sbb al, 0x10 ; 00940036 1c10
+ add byte [bx + si], 0x0 ; 00940038 800000
+ add [bx + si], al ; 0094003b 0000
+ mov sp, 0x4b17 ; 0094003d bc174b
+ add [bx + si], dh ; 00940040 0030
+ sbb al, 0x11 ; 00940042 1c11
+ add byte [bx + si], 0x0 ; 00940044 800000
+ add [bx + si], al ; 00940047 0000
+ pop es ; 00940049 07
+ sbb [bp + di + 0], cl ; 0094004a 184b00
+ xor [si], bl ; 0094004d 301c
+ adc al, [bx + si + 0] ; 0094004f 12800000
+ add [bx + si], al ; 00940053 0000
+ push dx ; 00940055 52
+ sbb [bp + di + 0], cl ; 00940056 184b00
+ xor [si], bl ; 00940059 301c
+ adc ax, [bx + si + 0] ; 0094005b 13800000
+ add [bx + si], al ; 0094005f 0000
+ popf ; 00940061 9d
+ sbb [bp + di + 0], cl ; 00940062 184b00
+ xor [si], bl ; 00940065 301c
+ adc al, 0x80 ; 00940067 1480
+ add [bx + si], al ; 00940069 0000
+ add [bx + si], al ; 0094006b 0000
+ call L198 ; 0094006d e8184b
+ add [bx + si], dh ; 00940070 0030
+ sbb al, 0x15 ; 00940072 1c15
+ add byte [bx + si], 0x0 ; 00940074 800000
+ add [bx + si], al ; 00940077 0000
+ xor bx, [bx + di] ; 00940079 3319
+ dec bx ; 0094007b 4b
+ add [bx + si], dh ; 0094007c 0030
+ sbb al, 0x16 ; 0094007e 1c16
+ add byte [bx + si], 0x0 ; 00940080 800000
+ add [bx + si], al ; 00940083 0000
+ jle L199 ; 00940085 7e19
+ dec bx ; 00940087 4b
+ add [bx + si], dh ; 00940088 0030
+ sbb al, 0x17 ; 0094008a 1c17
+ add byte [bx + si], 0x0 ; 0094008c 800000
+ add [bx + si], al ; 0094008f 0000
+ leave ; 00940091 c9
+ sbb bp, bx ; 00940092 19dd
+ add [bx + si], dh ; 00940094 0030
+ sbb al, L59 ; 00940096 1c18
+ add byte [bx + si], 0x0 ; 00940098 800000
+ add [bx + si], al ; 0094009b 0000
+ cmpsb ; 0094009d a6
+ sbb bl, ch ; 0094009e 1add
+ add [bx + si], dh ; 009400a0 0030
+ sbb al, 0x19 ; 009400a2 1c19
+ add byte [bx + si], 0x0 ; 009400a4 800000
+ add [bx + si], al ; 009400a7 0000
+ sbb word [bp + di], L16 ; 009400a9 831bdd
+ add [bx + si], dh ; 009400ac 0030
+ sbb al, 0x1a ; 009400ae 1c1a
+ add byte [bx + si], 0x0 ; 009400b0 800000
+ add [bx + si], al ; 009400b3 0000
+ pusha ; 009400b5 60
+ sbb al, L12 ; 009400b6 1c4b
+ add [bx + si], dh ; 009400b8 0030
+ sbb al, 0x1b ; 009400ba 1c1b
+ add byte [bx + si], 0x0 ; 009400bc 800000
+ add [bx + si], al ; 009400bf 0000
+ stosw ; 009400c1 ab
+ sbb al, L12 ; 009400c2 1c4b
+ add [bx + si], dh ; 009400c4 0030
+ sbb al, 0x1c ; 009400c6 1c1c
+ add byte [bx + si], 0x0 ; 009400c8 800000
+ add [bx + si], al ; 009400cb 0000
+ neg byte [si] ; 009400cd f61c
+ dec bx ; 009400cf 4b
+ add [bx + si], dh ; 009400d0 0030
+ sbb al, 0x1d ; 009400d2 1c1d
+ add byte [bx + si], 0x0 ; 009400d4 800000
+ add [bx + si], al ; 009400d7 0000
+ inc cx ; 009400d9 41
+ sbb ax, L12 ; 009400da 1d4b00
+ xor [si], bl ; 009400dd 301c
+ push ds ; 009400df 1e
+ add byte [bx + si], 0x0 ; 009400e0 800000
+ add [bx + si], al ; 009400e3 0000
+ mov word [di], ds ; 009400e5 8c1d
+ dec bx ; 009400e7 4b
+ add [bx + si], dh ; 009400e8 0030
+ sbb al, 0x1f ; 009400ea 1c1f
+ add byte [bx + si], 0x0 ; 009400ec 800000
+ add [bx + si], al ; 009400ef 0000
+ xlatb ; 009400f1 d7
+ sbb ax, L12 ; 009400f2 1d4b00
+ xor [si], bl ; 009400f5 301c
+ and [bx + si + 0], al ; 009400f7 20800000
+ add [bx + si], al ; 009400fb 0000
+ and bl, L12 ; 009400fd 221e4b00
+ xor [si], bl ; 00940101 301c
+ and [bx + si + 0], ax ; 00940103 21800000
+ add [bx + si], al ; 00940107 0000
+ insw ; 00940109 6d
+ push ds ; 0094010a 1e
+ dec bx ; 0094010b 4b
+ add [bx + si], dh ; 0094010c 0030
+ sbb al, 0x22 ; 0094010e 1c22
+ add byte [bx + si], 0x0 ; 00940110 800000
+ add [bx + si], al ; 00940113 0000
+ mov ax, 0x4b1e ; 00940115 b81e4b
+ add [bx + si], dh ; 00940118 0030
+ sbb al, 0x23 ; 0094011a 1c23
+ add byte [bx + si], 0x0 ; 0094011c 800000
+ add [bx + si], al ; 0094011f 0000
+ add bx, [bx] ; 00940121 031f
+ dec bx ; 00940123 4b
+ add [bx + si], dh ; 00940124 0030
+ sbb al, 0x24 ; 00940126 1c24
+ add byte [bx + si], 0x0 ; 00940128 800000
+ add [bx + si], al ; 0094012b 0000
+ dec si ; 0094012d 4e
+ pop ds ; 0094012e 1f
+ fld [bx + si] ; 0094012f dd00
+ xor [si], bl ; 00940131 301c
+ and ax, 0x80 ; 00940133 258000
+ add [bx + si], al ; 00940136 0000
+ add [bp + di], ch ; 00940138 002b
+ and ch, bl ; 0094013a 20dd
+ add [bx + si], dh ; 0094013c 0030
+ sbb al, 0x26 ; 0094013e 1c26
+ add byte [bx + si], 0x0 ; 00940140 800000
+ add [bx + si], al ; 00940143 0000
+ or [bx + di], ah ; 00940145 0821
+ fld [bx + si] ; 00940147 dd00
+ xor [si], bl ; 00940149 301c
+ daa ; 0094014b 27
+ add byte [bx + si], 0x0 ; 0094014c 800000
+ add [bx + si], al ; 0094014f 0000
+ in ax, 0x21 ; 00940151 e521
+ dec dx ; 00940153 4a
+ add [bx + si], dh ; 00940154 0030
+ sbb al, 0x28 ; 00940156 1c28
+ add byte [bx + si], 0x0 ; 00940158 800000
+ add [bx + si], al ; 0094015b 0000
+ das ; 0094015d 2f
+ and cl, [bp + si + 0] ; 0094015e 224a00
+ xor [si], bl ; 00940161 301c
+ sub [bx + si + 0], ax ; 00940163 29800000
+ add [bx + si], al ; 00940167 0000
+ jns L200 ; 00940169 7922
+ dec dx ; 0094016b 4a
+ add [bx + si], dh ; 0094016c 0030
+ sbb al, 0x2a ; 0094016e 1c2a
+ add byte [bx + si], 0x0 ; 00940170 800000
+ add [bx + si], al ; 00940173 0000
+ ret ; 00940175 c3
+ and cl, [bp + si + 0] ; 00940176 224a00
+ xor [si], bl ; 00940179 301c
+ sub ax, [bx + si + 0] ; 0094017b 2b800000
+ add [bx + si], al ; 0094017f 0000
+ or ax, 0x4a23 ; 00940181 0d234a
+ add [bx + si], dh ; 00940184 0030
+ sbb al, L1 ; 00940186 1c2c
+ add byte [bx + si], 0x0 ; 00940188 800000
+ add [bx + si], al ; 0094018b 0000
+ push di ; 0094018d 57
+ and cx, [bp + si + 0] ; 0094018e 234a00
+ xor [si], bl ; 00940191 301c
+ sub ax, 0x80 ; 00940193 2d8000
+ add [bx + si], al ; 00940196 0000
+ add [bx + di + 0x4a23], ah ; 00940198 00a1234a
+ add [bx + si], dh ; 0094019c 0030
+ sbb al, 0x2e ; 0094019e 1c2e
+ add byte [bx + si], 0x0 ; 009401a0 800000
+ add [bx + si], al ; 009401a3 0000
+ jmp short L201 ; 009401a5 eb23
+ dec dx ; 009401a7 4a
+ add [bx + si], dh ; 009401a8 0030
+ sbb al, 0x2f ; 009401aa 1c2f
+ add byte [bx + si], 0x0 ; 009401ac 800000
+ add [bx + si], al ; 009401af 0000
+ xor ax, 0x4a24 ; 009401b1 35244a
+ add [bx + si], dh ; 009401b4 0030
+ sbb al, 0x30 ; 009401b6 1c30
+ add byte [bx + si], 0x0 ; 009401b8 800000
+ add [bx + si], al ; 009401bb 0000
+ jg L202 ; 009401bd 7f24
+ dec dx ; 009401bf 4a
+ add [bx + si], dh ; 009401c0 0030
+ sbb al, 0x31 ; 009401c2 1c31
+ add byte [bx + si], 0x0 ; 009401c4 800000
+ add [bx + si], al ; 009401c7 0000
+ leave ; 009401c9 c9
+ and al, L16 ; 009401ca 24dd
+ add [bx + si], dh ; 009401cc 0030
+ sbb al, 0x32 ; 009401ce 1c32
+ add byte [bx + si], 0x0 ; 009401d0 800000
+ add [bx + si], al ; 009401d3 0000
+ cmpsb ; 009401d5 a6
+ and ax, L16 ; 009401d6 25dd00
+ xor [si], bl ; 009401d9 301c
+ xor ax, [bx + si + 0] ; 009401db 33800000
+ add [bx + si], al ; 009401df 0000
+ and word L16, byte 0x30 ; 009401e1 8326dd0030
+ sbb al, 0x34 ; 009401e6 1c34
+ add byte [bx + si], 0x0 ; 009401e8 800000
+ add [bx + si], al ; 009401eb 0000
+ pusha ; 009401ed 60
+ daa ; 009401ee 27
+ fadd [bx + si] ; 009401ef dc00
+ xor [si], bl ; 009401f1 301c
+ inc sp ; 009401f3 44
+ add byte [bx + si], 0x0 ; 009401f4 800000
+ add [bx + si], al ; 009401f7 0000
+ cmp al, 0x28 ; 009401f9 3c28
+ fadd [bx + si] ; 009401fb dc00
+ xor [si], bl ; 009401fd 301c
+ inc bx ; 009401ff 43
+ add byte [bx + si], 0x0 ; 00940200 800000
+ add [bx + si], al ; 00940203 0000
+ add al, 0x80 ; 00940205 0480
+ add [bx + si], ax ; 00940207 0100
+ add [bx + si], al ; 00940209 0000
+ add [bx + si], al ; 0094020b 0000
+ sbb [bx + di], ch ; 0094020d 1829
+ or [bx + si], ax ; 0094020f 0900
+ xor [si], bl ; 00940211 301c
+ add [bx + si + 0], ax ; 00940213 01800000
+ add [bx + si], al ; 00940217 0000
+ add ax, 0x280 ; 00940219 058002
+ add [bx + si], al ; 0094021c 0000
+ add [bx + si], al ; 0094021e 0000
+ add [bx + di], ah ; 00940220 0021
+ sub [bp + di], dx ; 00940222 2913
+ add [bx + si], dh ; 00940224 0030
+ sbb al, 0x65 ; 00940226 1c65
+ add byte [bx + si], 0x0 ; 00940228 800000
+ add [bx + si], al ; 0094022b 0000
+ xor al, 0x29 ; 0094022d 3429
+ sbb [bx + si], al ; 0094022f 1800
+ xor [si], bl ; 00940231 301c
+ a16 add byte [eax], 0x0 ; 00940233 67800000
+ add [bx + si], al ; 00940237 0000
+ push es ; 00940239 06
+ add byte [bx], 0x0 ; 0094023a 800700
+ add [bx + si], al ; 0094023d 0000
+ add [bx + si], al ; 0094023f 0000
+ dec sp ; 00940241 4c
+ sub [bp + si], cx ; 00940242 290a
+ add [bx + si], dh ; 00940244 0030
+ sbb al, 0x7 ; 00940246 1c07
+ add byte [bx + si], 0x0 ; 00940248 800000
+ add [bx + si], al ; 0094024b 0000
+ push si ; 0094024d 56
+ sub [si], ax ; 0094024e 2904
+ add [bx + si], dh ; 00940250 0030
+ sbb al, 0xd ; 00940252 1c0d
+ add byte [bx + si], 0x0 ; 00940254 800000
+ add [bx + si], al ; 00940257 0000
+ pop dx ; 00940259 5a
+ sub L17, cx ; 0094025a 290e0030
+ sbb al, 0x13 ; 0094025e 1c13
+ add byte [bx + si], 0x0 ; 00940260 800000
+ add [bx + si], al ; 00940263 0000
+ push 0x729 ; 00940265 682907
+ add [bx + si], dh ; 00940268 0030
+ sbb al, 0x3f ; 0094026a 1c3f
+ add byte [bx + si], 0x0 ; 0094026c 800000
+ add [bx + si], al ; 0094026f 0000
+ outsw ; 00940271 6f
+ sub [si], ax ; 00940272 2904
+ add [bx + si], dh ; 00940274 0030
+ sbb al, 0x0 ; 00940276 1c00
+ nop ; 00940278 90
+ add [bx + si], al ; 00940279 0000
+ add [bx + si], al ; 0094027b 0000
+ jnc L203 ; 0094027d 7329
+ add al, 0x0 ; 0094027f 0400
+ xor [si], bl ; 00940281 301c
+ add ax, [bx + si + 0] ; 00940283 03800000
+ add [bx + si], al ; 00940287 0000
+ ja L42 ; 00940289 7729
+ add al, [bx + si] ; 0094028b 0200
+ xor [si], bl ; 0094028d 301c
+ jle L204 ; 0094028f 7e80
+ add [bx + si], al ; 00940291 0000
+ add [bx + si], al ; 00940293 0000
+ adc [bx + si + 0x1], al ; 00940295 10800100
+ add [bx + si], al ; 00940299 0000
+ add [bx + si], al ; 0094029b 0000
+ jns L205 ; 0094029d 7929
+ push ds ; 0094029f 1e
+ add [bx + si], dh ; 009402a0 0030
+ or al, L4 ; 009402a2 0c01
+ add byte [bx + si], 0x0 ; 009402a4 800000
+ add [bx + si], al ; 009402a7 0000
+ add ax, [bx + si + 0x2] ; 009402a9 03800200
+ add [bx + si], al ; 009402ad 0000
+ add [bx + si], al ; 009402af 0000
+ xchg ax, di ; 009402b1 97
+ sub [bx], bp ; 009402b2 292f
+ add [bx + si], dl ; 009402b4 0010
+ sbb al, L4 ; 009402b6 1c01
+ add byte [bx + si], 0x0 ; 009402b8 800000
+ add [bx + si], al ; 009402bb 0000
+ mov byte [bx + di], 0x13 ; 009402bd c62913
+ add [bx + si], dl ; 009402c0 0010
+ sbb al, 0x2 ; 009402c2 1c02
+ add byte [bx + si], 0x0 ; 009402c4 800000
+ add [bx + si], al ; 009402c7 0000
+ add [bx + si], al ; 009402c9 0000
+ add dx, [bp + di + 0x4f] ; 009402cb 03534f
+ dec sp ; 009402ce 4c
+ add dx, [bp + di + 0x4f] ; 009402cf 03534f
+ dec sp ; 009402d2 4c
+ add [bx + si], al ; 009402d3 0000
+ add [bx + di], al ; 009402d5 0001
+ add [bx + si], cl ; 009402d7 0008
+ add [di], cl ; 009402d9 000d
+ add [bx + di], dl ; 009402db 0011
+ add [bx + si], al ; 009402dd 0000
+ push es ; 009402df 06
+ dec bx ; 009402e0 4b
+ inc bp ; 009402e1 45
+ push dx ; 009402e2 52
+ dec si ; 009402e3 4e
+ inc bp ; 009402e4 45
+ dec sp ; 009402e5 4c
+ add al, 0x55 ; 009402e6 0455
+ push bx ; 009402e8 53
+ inc bp ; 009402e9 45
+ push dx ; 009402ea 52
+ add ax, [bx + 0x44] ; 009402eb 034744
+ dec cx ; 009402ee 49
+ add ax, 0x4853 ; 009402ef 055348
+ inc bp ; 009402f2 45
+ dec sp ; 009402f3 4c
+ dec sp ; 009402f4 4c
+ add [bp + di], dl ; 009402f5 0013
+ dec bp ; 009402f7 4d
+ imul sp, [bp + di + 0x72], 0x736f ; 009402f8 6963726f73
+ outsw ; 009402fd 6f
+ o32 jz L206 ; 009402fe 667420
+ push bx ; 00940301 53
+ outsw ; 00940302 6f
+ insb ; 00940303 6c
+ imul si, [si + 0x61], 0x7269 ; 00940304 6974616972
+ gs add gs:[bx + si], al ; 00940309 650000
+ add [bx + si], al ; 0094030c 0000
+ add [bx + si], al ; 0094030e 0000
+ add [bx + si], al ; 00940310 0000
+ add [bx + si], al ; 00940312 0000
+ add [bx + si], al ; 00940314 0000
+ add [bx + si], al ; 00940316 0000
+ add [bx + si], al ; 00940318 0000
+ add [bx + si], al ; 0094031a 0000
+ add [bx + si], al ; 0094031c 0000
+ add [bx + si], al ; 0094031e 0000
+ add [bx + si], al ; 00940320 0000
+ add [bx + si], al ; 00940322 0000
+ add [bx + si], al ; 00940324 0000
+ add [bx + si], al ; 00940326 0000
+ add [bx + si], al ; 00940328 0000
+ add [bx + si], al ; 0094032a 0000
+ add [bx + si], al ; 0094032c 0000
+ add [bx + si], al ; 0094032e 0000
+ add [bx + si], al ; 00940330 0000
+ add [bx + si], al ; 00940332 0000
+ add [bx + si], al ; 00940334 0000
+ add [bx + si], al ; 00940336 0000
+ add [bx + si], al ; 00940338 0000
+ add [bx + si], al ; 0094033a 0000
+ add [bx + si], al ; 0094033c 0000
+ add [bx + si], al ; 0094033e 0000
+ add [bx + si], al ; 00940340 0000
+ add [bx + si], al ; 00940342 0000
+ add [bx + si], al ; 00940344 0000
+ add [bx + si], al ; 00940346 0000
+ add [bx + si], al ; 00940348 0000
+ add [bx + si], al ; 0094034a 0000
+ add [bx + si], al ; 0094034c 0000
+ add [bx + si], al ; 0094034e 0000
+ add [bx + si], al ; 00940350 0000
+ add [bx + si], al ; 00940352 0000
+ add [bx + si], al ; 00940354 0000
+ add al, cl ; 00940356 00c8
+ sbb [bx + si], al ; 00940358 1800
+ add [bp + di + 0xc7e], al ; 0094035a 00837e0c
+ add [si + 0x55], dh ; 0094035e 007455
+ push word [bp + 0xc] ; 00940361 ff760c
+ push L23 ; 00940364 68f001
+ push 0x2 ; 00940367 6a02
+ callf ; 00940369 9affff0000
+ push word L23 ; 0094036e ff36f001
+ callf ; 00940372 9affff0000
+ mov [bp + 0xffffffec], ax ; 00940377 8946ec
+ push word L23 ; 0094037a ff36f001
+ push 0x0 ; 0094037e 6a00
+ push 0x0 ; 00940380 6a00
+ push 0x0 ; 00940382 6a00
+ push 0x0 ; 00940384 6a00
+ push 0x0 ; 00940386 6a00
+ push 0x43 ; 00940388 6a43
+ callf ; 0094038a 9affff0000
+ push word L23 ; 0094038f ff36f001
+ callf ; 00940393 9affff0000
+ or ax, ax ; 00940398 0bc0
+ jz L207 ; 0094039a 740d
+ push word L23 ; 0094039c ff36f001
+ push 0x9 ; 009403a0 6a09
+ callf ; 009403a2 9affff0000
+ jmp short L208 ; 009403a7 eb08
+ push word [bp + 0xffffffec] ; 009403a9 ff76ec
+ callf ; 009403ac 9affff0000
+ xor ax, ax ; 009403b1 33c0
+ jmp L209 ; 009403b3 e98200
+ o32 push dword [bp + 0xc] ; 009403b6 66ff760c
+ o32 push dword [bp + 0x8] ; 009403ba 66ff7608
+ push word [bp + 0x6] ; 009403be ff7606
+ push cs ; 009403c1 0e
+ call L210 ; 009403c2 e87800
+ or ax, ax ; 009403c5 0bc0
+ jz L208 ; 009403c7 74e8
+ push 0x29 ; 009403c9 6a29
+ callf ; 009403cb 9affff0000
+ push ax ; 009403d0 50
+ push ds ; 009403d1 1e
+ push 0x3c ; 009403d2 683c00
+ callf ; 009403d5 9affff0000
+ mov [bp + 0xffffffe8], ax ; 009403da 8946e8
+
+L126:
+ mov [bp + 0xffffffea], dx ; 009403dd 8956ea
+ or dx, ax ; 009403e0 0bd0
+ jz L211 ; 009403e2 7407
+ push L4 ; 009403e4 6a01
+ push L4 ; 009403e6 6a01
+ call far oword [bp + 0xffffffe8] ; 009403e8 ff5ee8
+ lea ax, [bp + 0xffffffee] ; 009403eb 8d46ee
+ push ss ; 009403ee 16
+ push ax ; 009403ef 50
+ push 0x0 ; 009403f0 6a00
+ push 0x0 ; 009403f2 6a00
+ push 0x0 ; 009403f4 6a00
+ callf ; 009403f6 9ac8000000
+ or ax, ax ; 009403fb 0bc0
+ jz L212 ; 009403fd 7428
+ lea ax, [bp + 0xffffffee] ; 009403ff 8d46ee
+ push ss ; 00940402 16
+ push ax ; 00940403 50
+ callf ; 00940404 9affff0000
+ lea ax, [bp + 0xffffffee] ; 00940409 8d46ee
+ push ss ; 0094040c 16
+ push ax ; 0094040d 50
+ callf ; 0094040e 9affff0000
+ lea ax, [bp + 0xffffffee] ; 00940413 8d46ee
+ push ss ; 00940416 16
+ push ax ; 00940417 50
+ push 0x0 ; 00940418 6a00
+ push 0x0 ; 0094041a 6a00
+ push 0x0 ; 0094041c 6a00
+ callf ; 0094041e 9affff0000
+ or ax, ax ; 00940423 0bc0
+ jnz L213 ; 00940425 75d8
+ o32 cmp dword [bp + 0xffffffe8], byte 0x0 ; 00940427 66837ee800
+ jz L214 ; 0094042c 7407
+ push L4 ; 0094042e 6a01
+ push 0x0 ; 00940430 6a00
+ call far oword [bp + 0xffffffe8] ; 00940432 ff5ee8
+ mov ax, [bp + 0xfffffff2] ; 00940435 8b46f2
+ leave ; 00940438 c9
+ retf 0x0a ; 00940439 ca0a00
+ nop ; 0094043c 90
+ enter 0x72, 0x0 ; 0094043d c8720000
+ mov ax, [bp + 0xe] ; 00940441 8b460e
+ mov [0x2b0], ax ; 00940444 a3b002
+ push 0x200 ; 00940447 680002
+ push 0x12c ; 0094044a 682c01
+ callf ; 0094044d 9a2806d401
+ push ds ; 00940452 1e
+ push L84 ; 00940453 686802
+ push ds ; 00940456 1e
+
+L94:
+ push L82 ; 00940457 686a02
+ callf ; 0094045a 9a0000ffff
+ or ax, ax ; 0094045f 0bc0
+ jz L215 ; 00940461 741d
+ push 0x0 ; 00940463 6a00
+ push 0x0 ; 00940465 6a00
+ push 0x7f00 ; 00940467 68007f
+ callf ; 0094046a 9affff0000
+ mov [bp + 0xffffffb4], ax ; 0094046f 8946b4
+ push 0x0 ; 00940472 6a00
+ callf ; 00940474 9affff0000
+ mov [bp + 0xffffffd8], ax ; 00940479 8946d8
+ or ax, ax ; 0094047c 0bc0
+ jnz L216 ; 0094047e 7503
+ jmp L115 ; 00940480 e99802
+ push ax ; 00940483 50
+ lea ax, [bp + 0xffffffb8] ; 00940484 8d46b8
+ push ss ; 00940487 16
+ push ax ; 00940488 50
+ callf ; 00940489 9affff0000
+ mov ax, [bp + 0xffffffb8] ; 0094048e 8b46b8
+ mov [0x23e], ax ; 00940491 a33e02
+ mov ax, [bp + 0xffffffc4] ; 00940494 8b46c4
+ mov [0x23c], ax ; 00940497 a33c02
+ push word [bp + 0xffffffd8] ; 0094049a ff76d8
+ push L59 ; 0094049d 6a18
+ callf ; 0094049f 9a5e010000
+ cmp ax, 0x02 ; 009404a4 3d0200
+ jnz L217 ; 009404a7 7506
+ mov word L36, L4 ; 009404a9 c706f6010100
+ push word [bp + 0xffffffd8] ; 009404af ff76d8
+ push 0x8 ; 009404b2 6a08
+ callf ; 009404b4 9a6b010000
+ mov [0x24c], ax ; 009404b9 a34c02
+ push word [bp + 0xffffffd8] ; 009404bc ff76d8
+ push 0xa ; 009404bf 6a0a
+ callf ; 009404c1 9affff0000
+ mov [0x24e], ax ; 009404c6 a34e02
+ cmp ax, 0x12c ; 009404c9 3d2c01
+ jge L218 ; 009404cc 7d05
+ mov ax, L4 ; 009404ce b80100
+ jmp short L219 ; 009404d1 eb02
+ xor ax, ax ; 009404d3 33c0
+ mov [0x38], ax ; 009404d5 a33800
+ or ax, ax ; 009404d8 0bc0
+ jz L220 ; 009404da 740c
+ mov cx, 0x02 ; 009404dc b90200
+ mov ax, [0x26a] ; 009404df a16a02
+ cwd ; 009404e2 99
+ idiv cx, ax ; 009404e3 f7f9
+ mov [0x26a], ax ; 009404e5 a36a02
+ push 0x0 ; 009404e8 6a00
+ push word [bp + 0xffffffd8] ; 009404ea ff76d8
+ callf ; 009404ed 9affff0000
+ cmp word L36, byte 0x0 ; 009404f2 833ef60100
+ jz L221 ; 009404f7 7408
+ mov ax, 0xffff ; 009404f9 b8ffff
+ mov dx, 0xff ; 009404fc baff00
+ jmp short L222 ; 009404ff eb05
+ mov ax, 0x8000 ; 00940501 b80080
+ xor dx, dx ; 00940504 33d2
+ mov [0x2b2], ax ; 00940506 a3b202
+ mov L42, dx ; 00940509 8916b402
+ push dx ; 0094050d 52
+ push ax ; 0094050e 50
+ callf ; 0094050f 9affff0000
+ mov [0x266], ax ; 00940514 a36602
+ callf ; 00940517 9affff0000
+ push ax ; 0094051c 50
+ callf ; 0094051d 9a3201ffff
+ pop bx ; 00940522 5b
+ push 0x26e ; 00940523 686e02
+ push 0x64 ; 00940526 6a64
+ callf ; 00940528 9a2806de01
+ push 0x250 ; 0094052d 685002
+ push 0x65 ; 00940530 6a65
+ callf ; 00940532 9a2806e901
+ lea ax, [bp + 0xffffff98] ; 00940537 8d4698
+ push ax ; 0094053a 50
+ push 0x67 ; 0094053b 6a67
+ callf ; 0094053d 9a2806ffff
+ lea ax, [bp + 0xffffff98] ; 00940542 8d4698
+ push ss ; 00940545 16
+ push ax ; 00940546 50
+ callf ; 00940547 9affff0000
+ mov [0x1f8], ax ; 0094054c a3f801
+ mov word [bp + 0xffffffb2], 0x00 ; 0094054f c746b20000
+ o32 mov eax, [bp + 0x8] ; 00940554 668b4608
+ mov dx, [bp + 0xa] ; 00940558 8b560a
+ o32 mov [bp + 0xffffffae], eax ; 0094055b 668946ae
+ mov es, dx ; 0094055f 8ec2
+ mov bx, ax ; 00940561 8bd8
+ es cmp byte es:[bx], 0x0 ; 00940563 26803f00
+ jz L223 ; 00940567 7420
+ es cmp byte es:[bx], 0x2f ; 00940569 26803f2f
+ jnz L224 ; 0094056d 7507
+ es cmp byte es:[bx + 0x1], 0x49 ; 0094056f 26807f0149
+ jz L225 ; 00940574 740e
+ inc word [bp + 0xffffffae] ; 00940576 ff46ae
+ mov bx, [bp + 0xffffffae] ; 00940579 8b5eae
+ es cmp byte es:[bx], 0x0 ; 0094057c 26803f00
+ jnz L226 ; 00940580 75e7
+ jmp short L223 ; 00940582 eb05
+ mov word [bp + 0xffffffb2], L4 ; 00940584 c746b20100
+ cmp word [bp + 0xc], byte 0x0 ; 00940589 837e0c00
+ jnz L106 ; 0094058d 7556
+ mov word [bp + 0xffffffe6], 0x2008 ; 0094058f c746e60820
+ mov word [bp + 0xffffffe8], 0x40c ; 00940594 c746e80c04
+ mov word [bp + 0xffffffea], 0xffff ; 00940599 c746eaffff
+ o32 mov dword [bp + 0xffffffec], 0x0000 ; 0094059e 66c746ec00000000
+ mov ax, [0x2b0] ; 009405a6 a1b002
+ mov [bp + 0xfffffff0], ax ; 009405a9 8946f0
+ push ax ; 009405ac 50
+ push ds ; 009405ad 1e
+ push L12 ; 009405ae 684b00
+ callf ; 009405b1 9affff0000
+ mov [bp + 0xfffffff2], ax ; 009405b6 8946f2
+ mov ax, [bp + 0xffffffb4] ; 009405b9 8b46b4
+ mov [bp + 0xfffffff4], ax ; 009405bc 8946f4
+ mov ax, [0x266] ; 009405bf a16602
+ mov [bp + 0xfffffff6], ax ; 009405c2 8946f6
+ o32 mov dword [bp + 0xfffffff8], L4 ; 009405c5 66c746f801000000
+ mov word [bp + 0xfffffffc], 0x22 ; 009405cd c746fc2200
+ mov word [bp + 0xfffffffe], ds ; 009405d2 8c5efe
+ lea ax, [bp + 0xffffffe6] ; 009405d5 8d46e6
+ push ss ; 009405d8 16
+ push ax ; 009405d9 50
+ callf ; 009405da 9affff0000
+ or ax, ax ; 009405df 0bc0
+ je L115 ; 009405e1 0f843601
+ mov ax, [0x268] ; 009405e5 a16802
+ imul cx, ax, 0x7 ; 009405e8 6bc807
+ cwd ; 009405eb 99
+ and dx, byte 0x7 ; 009405ec 83e207
+ add ax, dx ; 009405ef 03c2
+ sar ax, byte 0x3 ; 009405f1 c1f803
+ add ax, 0x03 ; 009405f4 050300
+ mov [0x240], ax ; 009405f7 a34002
+ shl ax, byte 0x3 ; 009405fa c1e003
+ add cx, ax ; 009405fd 03c8
+ mov [bp + 0xffffff92], cx ; 009405ff 894e92
+ mov ax, [0x26a] ; 00940602 a16a02
+ shl ax, byte 0x2 ; 00940605 c1e002
+ mov [bp + 0xffffff94], ax ; 00940608 894694
+ o32 mov dword [bp + 0xffffff8e], 0x0000 ; 0094060b 66c7468e00000000
+ lea ax, [bp + 0xffffff8e] ; 00940613 8d468e
+ push ss ; 00940616 16
+ push ax ; 00940617 50
+ push 0xcf ; 00940618 68cf00
+ push 0x0 ; 0094061b 6a00
+ push L4 ; 0094061d 6a01
+ push 0x0 ; 0094061f 6a00
+ push 0x200 ; 00940621 680002
+ callf ; 00940624 9affff0000
+ mov ax, [bp + 0xffffff8e] ; 00940629 8b468e
+ sub [bp + 0xffffff92], ax ; 0094062c 294692
+ mov ax, [0x24e] ; 0094062f a14e02
+ mov cx, [bp + 0xffffff90] ; 00940632 8b4e90
+ sub [bp + 0xffffff94], cx ; 00940635 294e94
+ cmp [bp + 0xffffff94], ax ; 00940638 394694
+ jle L144 ; 0094063b 7e03
+ mov [bp + 0xffffff94], ax ; 0094063d 894694
+ push 0x0 ; 00940640 6a00
+ push 0x200 ; 00940642 680002
+ push ds ; 00940645 1e
+ push 0x22 ; 00940646 682200
+ push ds ; 00940649 1e
+ push 0x26e ; 0094064a 686e02
+ cmp word [bp + 0xffffffb2], byte 0x0 ; 0094064d 837eb200
+ jz L227 ; 00940651 7407
+ xor ax, ax ; 00940653 33c0
+ mov dx, 0x22cf ; 00940655 bacf22
+ jmp short L228 ; 00940658 eb05
+ xor ax, ax ; 0094065a 33c0
+ mov dx, 0x2cf ; 0094065c bacf02
+ push dx ; 0094065f 52
+ push ax ; 00940660 50
+ push 0x8000 ; 00940661 680080
+ push ax ; 00940664 50
+ push word [bp + 0xffffff92] ; 00940665 ff7692
+ push word [bp + 0xffffff94] ; 00940668 ff7694
+ push ax ; 0094066b 50
+ push ax ; 0094066c 50
+ push word L51 ; 0094066d ff36b002
+ push ax ; 00940671 50
+ push ax ; 00940672 50
+ callf ; 00940673 9affff0000
+ or ax, ax ; 00940678 0bc0
+ je L115 ; 0094067a 0f849d00
+ lea ax, [bp + 0xffffffac] ; 0094067e 8d46ac
+ push ax ; 00940681 50
+ push cs ; 00940682 0e
+ call L229 ; 00940683 e8d105
+ push 0x245 ; 00940686 684502
+ push 0x85a ; 00940689 685a08
+ push word [bp + 0xe] ; 0094068c ff760e
+ callf ; 0094068f 9affff0000
+ mov [0x1f2], ax ; 00940694 a3f201
+ mov L53, dx ; 00940697 8916f401
+ mov ax, dx ; 0094069b 8bc2
+ or ax, L54 ; 0094069d 0b06f201
+ jz L230 ; 009406a1 747d
+ push word L23 ; 009406a3 ff36f001
+ o32 push 0x29a00fa ; 009406a7 6668fa009a02
+ push dx ; 009406ad 52
+ push word L54 ; 009406ae ff36f201
+ callf ; 009406b2 9affff0000
+ or ax, ax ; 009406b7 0bc0
+ jz L115 ; 009406b9 7460
+ callf ; 009406bb 9a24026f03
+ push word [bp + 0xffffffac] ; 009406c0 ff76ac
+ callf ; 009406c3 9ac6000b05
+ push word L23 ; 009406c8 ff36f001
+ push word [bp + 0x6] ; 009406cc ff7606
+ callf ; 009406cf 9a4c000000
+ push word L23 ; 009406d4 ff36f001
+ callf ; 009406d8 9affff0000
+ cmp word [bp + 0xc], L4 ; 009406dd 837e0c01
+ sbb ax, ax ; 009406e1 1bc0
+ neg ax ; 009406e3 f7d8
+ push ax ; 009406e5 50
+ callf ; 009406e6 9a00009e03
+ cmp word L1, byte 0x0 ; 009406eb 833e2c0000
+ jz L231 ; 009406f0 7405
+ callf ; 009406f2 9a6600ffff
+ cmp word [bp + 0x6], byte 0x7 ; 009406f7 837e0607
+ jz L148 ; 009406fb 7419
+ cmp word [bp + 0x6], byte 0x6 ; 009406fd 837e0606
+ jz L148 ; 00940701 7413
+ push word L23 ; 00940703 ff36f001
+ o32 push 0x11103e8 ; 00940707 6668e8031101
+ push 0x0 ; 0094070d 6a00
+ push 0x0 ; 0094070f 6a00
+ callf ; 00940711 9acb040000
+ mov ax, L4 ; 00940716 b80100
+ jmp short L232 ; 00940719 eb07
+ callf ; 0094071b 9a1806f900
+ xor ax, ax ; 00940720 33c0
+ leave ; 00940722 c9
+ retf 0x0a ; 00940723 ca0a00
+ nop ; 00940726 90
+ enter 0x20, 0x0 ; 00940727 c8200000
+ push word [bp + 0x6] ; 0094072b ff7606
+ lea ax, [bp + 0xffffffe0] ; 0094072e 8d46e0
+ push ss ; 00940731 16
+ push ax ; 00940732 50
+ callf ; 00940733 9affff0000
+ cmp word L59, byte 0x0 ; 00940738 833e180000
+ jz L233 ; 0094073d 7412
+ push word L59 ; 0094073f ff361800
+ push 0x7 ; 00940743 6a07
+ lea ax, [bp + 0xffffffe0] ; 00940745 8d46e0
+ push ax ; 00940748 50
+ push 0x0 ; 00940749 6a00
+ mov bx, L59 ; 0094074b 8b1e1800
+ call far oword [bx] ; 0094074f ff1f
+ push word [bp + 0x6] ; 00940751 ff7606
+ lea ax, [bp + 0xffffffe0] ; 00940754 8d46e0
+ push ss ; 00940757 16
+ push ax ; 00940758 50
+ callf ; 00940759 9affff0000
+ leave ; 0094075e c9
+ retf 0x02 ; 0094075f ca0200
+ nop ; 00940762 90
+ enter 0xd6, 0x0 ; 00940763 c8d60000
+ mov ax, [bp + 0xc] ; 00940767 8b460c
+ dec ax ; 0094076a 48
+ je L234 ; 0094076b 0f84bf00
+ dec ax ; 0094076f 48
+ je L235 ; 00940770 0f84c300
+ dec ax ; 00940774 48
+ je L236 ; 00940775 0f846a01
+ dec ax ; 00940779 48
+ dec ax ; 0094077a 48
+ je L237 ; 0094077b 0f84f400
+ dec ax ; 0094077f 48
+ je L238 ; 00940780 0f846701
+ dec ax ; 00940784 48
+ je L239 ; 00940785 0f848701
+ dec ax ; 00940789 48
+ je L240 ; 0094078a 0f846f01
+ sub ax, 0x07 ; 0094078e 2d0700
+ je L241 ; 00940791 0f848901
+ dec ax ; 00940795 48
+ je L242 ; 00940796 0f849901
+ sub ax, 0xf0 ; 0094079a 2df000
+ je L243 ; 0094079d 0f84b401
+ sub ax, 0x11 ; 009407a1 2d1100
+ je L244 ; 009407a4 0f84c101
+ sub ax, 0x05 ; 009407a8 2d0500
+ je L245 ; 009407ab 0f845302
+ sub ax, 0x09 ; 009407af 2d0900
+ je L246 ; 009407b2 0f84dc02
+ sub ax, 0xe1 ; 009407b6 2de100
+ je L247 ; 009407b9 0f840303
+ dec ax ; 009407bd 48
+ je L248 ; 009407be 0f840f03
+ dec ax ; 009407c2 48
+ je L249 ; 009407c3 0f842303
+ dec ax ; 009407c7 48
+ je L250 ; 009407c8 0f843403
+ mov ax, [0x1f8] ; 009407cc a1f801
+ cmp [bp + 0xc], ax ; 009407cf 39460c
+ jne L251 ; 009407d2 0f855403
+ mov ax, [bp + 0xa] ; 009407d6 8b460a
+ dec ax ; 009407d9 48
+ jz L252 ; 009407da 7409
+ dec ax ; 009407dc 48
+ jz L253 ; 009407dd 7410
+ dec ax ; 009407df 48
+ jz L254 ; 009407e0 7431
+ jmp L251 ; 009407e2 e94503
+ mov ax, [0x268] ; 009407e5 a16802
+ mov dx, L82 ; 009407e8 8b166a02
+ jmp L255 ; 009407ec e94b03
+ les bx, ; 009407ef c45e0626ff3726
+ push word [bx + 0x2] ; 009407f6 ff7702
+ es push word es:[bx + 0x4] ; 009407f9 26ff7704
+ es push word es:[bx + 0x6] ; 009407fd 26ff7706
+ es push word es:[bx + 0x8] ; 00940801 26ff7708
+ o32 push dword es:[bx + 0xa] ; 00940805 6626ff770a
+ callf ; 0094080a 9a5a031005
+ cwd ; 0094080f 99
+ jmp L255 ; 00940810 e92703
+ push word L23 ; 00940813 ff36f001
+ o32 push 0x112f060 ; 00940817 666860f01201
+ push 0x0 ; 0094081d 6a00
+ push 0x0 ; 0094081f 6a00
+ callf ; 00940821 9affff0000
+ mov ax, L4 ; 00940826 b80100
+ xor dx, dx ; 00940829 33d2
+ jmp L255 ; 0094082b e90c03
+ mov ax, [bp + 0xe] ; 0094082e 8b460e
+ mov [0x1f0], ax ; 00940831 a3f001
+ jmp L251 ; 00940834 e9f302
+ push word L23 ; 00940837 ff36f001
+ push 0x29a ; 0094083b 689a02
+ callf ; 0094083e 9affff0000
+ o32 push dword L54 ; 00940843 66ff36f201
+ callf ; 00940848 9affff0000
+ push word L59 ; 0094084d ff361800
+ push L4 ; 00940851 6a01
+ push 0x0 ; 00940853 6a00
+ push 0x0 ; 00940855 6a00
+ mov bx, L59 ; 00940857 8b1e1800
+ call far oword [bx] ; 0094085b ff1f
+ push L4 ; 0094085d 6a01
+ callf ; 0094085f 9ac600ffff
+ callf ; 00940864 9a78080601
+ push 0x0 ; 00940869 6a00
+ callf ; 0094086b 9affff0000
+ jmp L251 ; 00940870 e9b702
+ push word [bp + 0xe] ; 00940873 ff760e
+ callf ; 00940876 9a3d000000
+ mov [0x14], ax ; 0094087b a31400
+ push word [bp + 0xe] ; 0094087e ff760e
+ push ds ; 00940881 1e
+ push 0x244 ; 00940882 684402
+ callf ; 00940885 9affff0000
+ imul ax, L84, 0x7 ; 0094088a 6b06680207
+ sub ax, [bp + 0x6] ; 0094088f 2b4606
+ neg ax ; 00940892 f7d8
+ cwd ; 00940894 99
+ and dx, byte 0x7 ; 00940895 83e207
+ add ax, dx ; 00940898 03c2
+ sar ax, byte 0x3 ; 0094089a c1f803
+ mov [bp + 0xffffff92], ax ; 0094089d 894692
+ mov ax, [0x268] ; 009408a0 a16802
+ cwd ; 009408a3 99
+ and dx, byte 0x7 ; 009408a4 83e207
+ add ax, dx ; 009408a7 03c2
+ sar ax, byte 0x3 ; 009408a9 c1f803
+ add ax, 0x03 ; 009408ac 050300
+ mov [bp + 0xffffff90], ax ; 009408af 894690
+ cmp [bp + 0xffffff92], ax ; 009408b2 394692
+ jge L256 ; 009408b5 7d0e
+ mov ax, [0x240] ; 009408b7 a14002
+ cmp [bp + 0xffffff90], ax ; 009408ba 394690
+ jz L256 ; 009408bd 7406
+ mov ax, [bp + 0xffffff90] ; 009408bf 8b4690
+ mov [bp + 0xffffff92], ax ; 009408c2 894692
+ mov ax, [bp + 0xffffff92] ; 009408c5 8b4692
+ cmp [bp + 0xffffff90], ax ; 009408c8 394690
+ jg L236 ; 009408cb 7f16
+ mov [0x240], ax ; 009408cd a34002
+ callf ; 009408d0 9aa001ffff
+ push word [bp + 0xe] ; 009408d5 ff760e
+ push 0x0 ; 009408d8 6a00
+ push 0x0 ; 009408da 6a00
+ push L4 ; 009408dc 6a01
+ callf ; 009408de 9affff0000
+ callf ; 009408e3 9aca019203
+ jmp L251 ; 009408e8 e93f02
+ cmp word [bp + 0xa], byte 0x0 ; 009408eb 837e0a00
+ je L251 ; 009408ef 0f843702
+ push word [bp + 0xe] ; 009408f3 ff760e
+ push cs ; 009408f6 0e
+ call L257 ; 009408f7 e82dfe
+ jmp L251 ; 009408fa e92d02
+ mov bx, L59 ; 009408fd 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940901 837f2600
+ jz L239 ; 00940905 7409
+ push bx ; 00940907 53
+ push 0x4 ; 00940908 6a04
+ push 0x0 ; 0094090a 6a00
+ push L4 ; 0094090c 6a01
+ call far oword [bx] ; 0094090e ff1f
+ cmp word [bp + 0xc], byte 0x7 ; 00940910 837e0c07
+ jne L258 ; 00940914 0f850a02
+ mov ax, L4 ; 00940918 b80100
+ jmp L259 ; 0094091b e90602
+ cmp word L178, byte 0x0 ; 0094091e 833e140000
+ jne L251 ; 00940923 0f850302
+ push word [bp + 0xe] ; 00940927 ff760e
+ push cs ; 0094092a 0e
+ call L257 ; 0094092b e8f9fd
+ xor ax, ax ; 0094092e 33c0
+ jmp L260 ; 00940930 e9f6fe
+ lea ax, [bp + 0xffffff94] ; 00940933 8d4694
+ push ax ; 00940936 50
+ push 0x69 ; 00940937 6a69
+ callf ; 00940939 9a2806c703
+ push word L23 ; 0094093e ff36f001
+ lea ax, [bp + 0xffffff94] ; 00940942 8d4694
+ push ss ; 00940945 16
+ push ax ; 00940946 50
+ push 0x2 ; 00940947 6a02
+ push 0x0 ; 00940949 6a00
+ push 0x0 ; 0094094b 6a00
+ callf ; 0094094d 9affff0000
+ jmp L251 ; 00940952 e9d501
+ push word L59 ; 00940955 ff361800
+ push 0x2 ; 00940959 6a02
+ push word [bp + 0xa] ; 0094095b ff760a
+ push 0x0 ; 0094095e 6a00
+ mov bx, L59 ; 00940960 8b1e1800
+ call far oword [bx] ; 00940964 ff1f
+ jmp L251 ; 00940966 e9c101
+ mov ax, [bp + 0xa] ; 00940969 8b460a
+ inc ax ; 0094096c 40
+ jz L261 ; 0094096d 7419
+ sub ax, 0x3e9 ; 0094096f 2de903
+ jz L262 ; 00940972 741e
+ dec ax ; 00940974 48
+ jz L263 ; 00940975 7426
+ dec ax ; 00940977 48
+ jz L159 ; 00940978 742d
+ dec ax ; 0094097a 48
+ jz L264 ; 0094097b 7432
+ dec ax ; 0094097d 48
+ jz L265 ; 0094097e 7437
+ sub ax, 0x3e4 ; 00940980 2de403
+ jz L160 ; 00940983 7447
+ jmp L251 ; 00940985 e9a201
+ push word [bp + 0xa] ; 00940988 ff760a
+ push cs ; 0094098b 0e
+ call L266 ; 0094098c e89402
+ jmp L251 ; 0094098f e99801
+ push L4 ; 00940992 6a01
+ push 0x0 ; 00940994 6a00
+ push cs ; 00940996 0e
+ call L267 ; 00940997 e85902
+ jmp L251 ; 0094099a e98d01
+ push word L59 ; 0094099d ff361800
+ push 0x9 ; 009409a1 6a09
+ push 0x0 ; 009409a3 6a00
+ jmp short L268 ; 009409a5 ebb7
+ callf ; 009409a7 9a18045b06
+ jmp L251 ; 009409ac e97b01
+ callf ; 009409af 9af801ffff
+ jmp L251 ; 009409b4 e97301
+ push word [bp + 0xe] ; 009409b7 ff760e
+ o32 push 0x112f060 ; 009409ba 666860f01201
+ push 0x0 ; 009409c0 6a00
+ push 0x0 ; 009409c2 6a00
+ callf ; 009409c4 9abb030000
+ jmp L251 ; 009409c9 e95e01
+ push word L51 ; 009409cc ff36b002
+ push 0x6c ; 009409d0 6a6c
+ lea ax, [bp + 0xffffff2c] ; 009409d2 8d862cff
+ push ss ; 009409d6 16
+ push ax ; 009409d7 50
+ push 0x64 ; 009409d8 6a64
+ callf ; 009409da 9affff0000
+ push word [bp + 0xe] ; 009409df ff760e
+ push ds ; 009409e2 1e
+ push 0x26e ; 009409e3 686e02
+ lea ax, [bp + 0xffffff2c] ; 009409e6 8d862cff
+ push ss ; 009409ea 16
+ push ax ; 009409eb 50
+ push word L51 ; 009409ec ff36b002
+ push ds ; 009409f0 1e
+ push 0x4f ; 009409f1 684f00
+ callf ; 009409f4 9a5b020000
+ push ax ; 009409f9 50
+ callf ; 009409fa 9affff0000
+ jmp L251 ; 009409ff e92801
+ push word [bp + 0xe] ; 00940a02 ff760e
+ callf ; 00940a05 9affff0000
+ mov [bp + 0xfffffffe], ax ; 00940a0a 8946fe
+ mov bx, L59 ; 00940a0d 8b1e1800
+ cmp word [bx + 0x4], byte 0x0 ; 00940a11 837f0400
+ jz L165 ; 00940a15 740e
+ cmp word [bx + 0x2c], byte 0xff ; 00940a17 837f2cff
+ jnz L165 ; 00940a1b 7508
+ mov word [bp + 0xffffff2a], 0x00 ; 00940a1d c7862aff0000
+ jmp short L269 ; 00940a23 eb06
+ mov word [bp + 0xffffff2a], 0x03 ; 00940a25 c7862aff0300
+ push ax ; 00940a2b 50
+ push 0x3e9 ; 00940a2c 68e903
+ push word [bp + 0xffffff2a] ; 00940a2f ffb62aff
+ callf ; 00940a33 9afa060000
+ push word [bp + 0xfffffffe] ; 00940a38 ff76fe
+ push 0x3e8 ; 00940a3b 68e803
+ mov bx, L59 ; 00940a3e 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 00940a42 837f2cff
+ jz L270 ; 00940a46 7405
+ mov ax, 0x03 ; 00940a48 b80300
+ jmp short L271 ; 00940a4b eb02
+ xor ax, ax ; 00940a4d 33c0
+ push ax ; 00940a4f 50
+ callf ; 00940a50 9a17070000
+ push word [bp + 0xfffffffe] ; 00940a55 ff76fe
+ push L91 ; 00940a58 68ea03
+ mov bx, L59 ; 00940a5b 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 00940a5f 837f2cff
+ jz L272 ; 00940a63 7405
+ mov ax, 0x03 ; 00940a65 b80300
+ jmp short L273 ; 00940a68 eb02
+ xor ax, ax ; 00940a6a 33c0
+ push ax ; 00940a6c 50
+ callf ; 00940a6d 9a34070000
+ push word [bp + 0xfffffffe] ; 00940a72 ff76fe
+ push 0x7d0 ; 00940a75 68d007
+ mov bx, L59 ; 00940a78 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 00940a7c 837f2cff
+ jz L274 ; 00940a80 7405
+ mov ax, 0x03 ; 00940a82 b80300
+ jmp short L275 ; 00940a85 eb02
+ xor ax, ax ; 00940a87 33c0
+ push ax ; 00940a89 50
+ callf ; 00940a8a 9affff0000
+ jmp L251 ; 00940a8f e99800
+ cmp word [bp + 0xa], byte 0x0 ; 00940a92 837e0a00
+ jz L276 ; 00940a96 7411
+ o32 cmp dword [bp + 0x6], 0xffff ; 00940a98 66817e06ffff0000
+ jz L276 ; 00940aa0 7407
+ test word [bp + 0x6], 0x2810 ; 00940aa2 f746061028
+ jz L277 ; 00940aa7 740d
+ mov word [bp + 0xa], 0x1fff ; 00940aa9 c7460aff1f
+ o32 mov dword [bp + 0x6], 0x0000 ; 00940aae 66c7460600000000
+ push word [bp + 0xa] ; 00940ab6 ff760a
+ callf ; 00940ab9 9aae028f05
+ jmp short L251 ; 00940abe eb6a
+ mov word [bp + 0xfffffff8], 0x05 ; 00940ac0 c746f80500
+ mov bx, L59 ; 00940ac5 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940ac9 837f2600
+ jz L251 ; 00940acd 745b
+ jmp short L278 ; 00940acf eb3e
+ push word [bp + 0xe] ; 00940ad1 ff760e
+ callf ; 00940ad4 9affff0000
+ mov bx, L59 ; 00940ad9 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940add 837f2600
+ jnz L251 ; 00940ae1 7547
+ mov word [bp + 0xfffffff8], 0x03 ; 00940ae3 c746f80300
+ jmp short L278 ; 00940ae8 eb25
+ callf ; 00940aea 9affff0000
+ mov word [bp + 0xfffffff8], 0x04 ; 00940aef c746f80400
+ mov bx, L59 ; 00940af4 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940af8 837f2600
+ jnz L278 ; 00940afc 7511
+ jmp short L251 ; 00940afe eb2a
+ mov word [bp + 0xfffffff8], 0x06 ; 00940b00 c746f80600
+ mov bx, L59 ; 00940b05 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940b09 837f2600
+ jnz L251 ; 00940b0d 751b
+ o32 mov eax, [bp + 0x6] ; 00940b0f 668b4606
+ o32 mov [bp + 0xfffffffa], eax ; 00940b13 668946fa
+ push bx ; 00940b17 53
+ push word [bp + 0xfffffff8] ; 00940b18 ff76f8
+ lea ax, [bp + 0xfffffffa] ; 00940b1b 8d46fa
+ push ax ; 00940b1e 50
+ jmp L268 ; 00940b1f e93cfe
+ xor ax, ax ; 00940b22 33c0
+ push ax ; 00940b24 50
+ callf ; 00940b25 9affff0000
+ o32 push dword [bp + 0xc] ; 00940b2a 66ff760c
+ o32 push dword [bp + 0x8] ; 00940b2e 66ff7608
+ push word [bp + 0x6] ; 00940b32 ff7606
+ callf ; 00940b35 9affff0000
+ leave ; 00940b3a c9
+ retf 0x0a ; 00940b3b ca0a00
+ nop ; 00940b3e 90
+ enter 0x02, 0x0 ; 00940b3f c8020000
+ mov ax, [0x1a] ; 00940b43 a11a00
+ mov [bp + 0xfffffffe], ax ; 00940b46 8946fe
+ mov ax, [bp + 0xa] ; 00940b49 8b460a
+ mov [0x1a], ax ; 00940b4c a31a00
+ mov ax, [bp + 0x8] ; 00940b4f 8b4608
+ mov [0x1e], ax ; 00940b52 a31e00
+ mov ax, [bp + 0x6] ; 00940b55 8b4606
+ mov [0x20], ax ; 00940b58 a32000
+ mov ax, [bp + 0xfffffffe] ; 00940b5b 8b46fe
+ leave ; 00940b5e c9
+ retf 0x06 ; 00940b5f ca0600
+ nop ; 00940b62 90
+ cmp word L279, byte 0x0 ; 00940b63 833e1a0000
+ jz L280 ; 00940b68 7408
+ inc word L281 ; 00940b6a ff061c00
+ mov ax, L4 ; 00940b6e b80100
+ retf ; 00940b71 cb
+ push word L23 ; 00940b72 ff36f001
+ callf ; 00940b76 9a1e010000
+ or ax, ax ; 00940b7b 0bc0
+ jz L282 ; 00940b7d 740f
+ push ax ; 00940b7f 50
+ push 0x0 ; 00940b80 6a00
+ push 0x0 ; 00940b82 6a00
+ push cs ; 00940b84 0e
+ call L283 ; 00940b85 e8b7ff
+ mov ax, L4 ; 00940b88 b80100
+ mov [0x1c], ax ; 00940b8b a31c00
+ retf ; 00940b8e cb
+ cmp word L279, byte 0x0 ; 00940b8f 833e1a0000
+ jz L284 ; 00940b94 7419
+ dec word L281 ; 00940b96 ff0e1c00
+ jnz L284 ; 00940b9a 7513
+ push word L23 ; 00940b9c ff36f001
+ push word L279 ; 00940ba0 ff361a00
+ callf ; 00940ba4 9a97010000
+ mov word L279, 0x00 ; 00940ba9 c7061a000000
+ retf ; 00940baf cb
+ nop ; 00940bb0 90
+ cmp word L59, byte 0x0 ; 00940bb1 833e180000
+ jz L285 ; 00940bb6 7410
+ push word L59 ; 00940bb8 ff361800
+ push 0x11 ; 00940bbc 6a11
+ push 0x0 ; 00940bbe 6a00
+ push 0x0 ; 00940bc0 6a00
+ mov bx, L59 ; 00940bc2 8b1e1800
+ call far oword [bx] ; 00940bc6 ff1f
+ mov ax, L4 ; 00940bc8 b80100
+ retf 0x0a ; 00940bcb ca0a00
+ nop ; 00940bce 90
+ push bp ; 00940bcf 55
+ mov bp, sp ; 00940bd0 8bec
+ mov ax, [0x16] ; 00940bd2 a11600
+ cmp [bp + 0x6], ax ; 00940bd5 394606
+ jz L286 ; 00940bd8 7415
+ mov ax, [bp + 0x6] ; 00940bda 8b4606
+ mov [0x16], ax ; 00940bdd a31600
+ push word L23 ; 00940be0 ff36f001
+ push 0x0 ; 00940be4 6a00
+ push 0x0 ; 00940be6 6a00
+ push L4 ; 00940be8 6a01
+ callf ; 00940bea 9a88050000
+ leave ; 00940bef c9
+ retf 0x02 ; 00940bf0 ca0200
+ push bp ; 00940bf3 55
+ mov bp, sp ; 00940bf4 8bec
+ cmp word [bp + 0x8], byte 0x0 ; 00940bf6 837e0800
+ jz L287 ; 00940bfa 7412
+ callf ; 00940bfc 9ac1010000
+ and ah, 0x7f ; 00940c01 80e47f
+ mov [0x242], ax ; 00940c04 a34202
+ push ax ; 00940c07 50
+ callf ; 00940c08 9a3201c901
+ pop bx ; 00940c0d 5b
+ push word L59 ; 00940c0e ff361800
+ push 0x8 ; 00940c12 6a08
+ push word [bp + 0x6] ; 00940c14 ff7606
+ push 0x0 ; 00940c17 6a00
+ mov bx, L59 ; 00940c19 8b1e1800
+ call far oword [bx] ; 00940c1d ff1f
+ leave ; 00940c1f c9
+ retf 0x04 ; 00940c20 ca0400
+ enter 0x66, 0x0 ; 00940c23 c8660000
+ lea ax, [bp + 0xffffff9c] ; 00940c27 8d469c
+ push ax ; 00940c2a 50
+ push 0x69 ; 00940c2b 6a69
+ callf ; 00940c2d 9a2806f908
+ push word L23 ; 00940c32 ff36f001
+ lea ax, [bp + 0xffffff9c] ; 00940c36 8d469c
+ push ss ; 00940c39 16
+ push ax ; 00940c3a 50
+ push 0xb ; 00940c3b 6a0b
+ push 0x0 ; 00940c3d 6a00
+ push 0x0 ; 00940c3f 6a00
+ callf ; 00940c41 9af7050000
+ or ax, ax ; 00940c46 0bc0
+ jnz L288 ; 00940c48 7508
+ push 0x12d ; 00940c4a 682d01
+ callf ; 00940c4d 9af8048109
+ leave ; 00940c52 c9
+ retf 0x02 ; 00940c53 ca0200
+ nop ; 00940c56 90
+ enter 0x86, 0x0 ; 00940c57 c8860000
+ mov word [bp + 0xffffff7e], 0x00 ; 00940c5b c7867eff0000
+ mov al, [0xff0000] ; 00940c61 a0
+ sub al, 0x0 ; 00940c62 2c00
+ and ax, L4 ; 00940c64 250100
+ mov [bp + 0xffffff7e], ax ; 00940c67 89867eff
+ mov cx, ax ; 00940c6b 8bc8
+ mov dx, L289 ; 00940c6d 8b162e00
+ add dx, dx ; 00940c71 03d2
+ xor al, dl ; 00940c73 32c2
+ and ax, 0x02 ; 00940c75 250200
+ xor cx, ax ; 00940c78 33c8
+ mov [bp + 0xffffff7e], cx ; 00940c7a 898e7eff
+ mov ax, cx ; 00940c7e 8bc1
+ mov dx, L290 ; 00940c80 8b163600
+ shl dx, byte 0x2 ; 00940c84 c1e202
+ xor cl, dl ; 00940c87 32ca
+ and cx, byte 0x4 ; 00940c89 83e104
+ xor ax, cx ; 00940c8c 33c1
+ mov [bp + 0xffffff7e], ax ; 00940c8e 89867eff
+ mov [bp + 0xffffff7a], ax ; 00940c92 89867aff
+ cmp word L291, byte 0x3 ; 00940c96 833e340003
+ jnz L292 ; 00940c9b 7505
+ mov ax, L4 ; 00940c9d b80100
+ jmp short L293 ; 00940ca0 eb02
+ xor ax, ax ; 00940ca2 33c0
+ shl ax, byte 0x3 ; 00940ca4 c1e003
+ mov cl, [bp + 0xffffff7a] ; 00940ca7 8a8e7aff
+ xor cl, al ; 00940cab 32c8
+ and cx, byte 0x8 ; 00940cad 83e108
+ xor cx, [bp + 0xffffff7a] ; 00940cb0 338e7aff
+ mov [bp + 0xffffff7e], cx ; 00940cb4 898e7eff
+ mov ax, [0x30] ; 00940cb8 a13000
+ shl ax, byte 0x6 ; 00940cbb c1e006
+ xor cl, al ; 00940cbe 32c8
+ and cx, byte 0x40 ; 00940cc0 83e140
+ xor [bp + 0xffffff7e], cx ; 00940cc3 318e7eff
+ push 0x63 ; 00940cc7 6a63
+ push 0xc9 ; 00940cc9 68c900
+ and byte [bp + 0xffffff7e], 0xcf ; 00940ccc 80a67effcf
+ push word [bp + 0xffffff7e] ; 00940cd1 ffb67eff
+ callf ; 00940cd5 9ad806030a
+ mov [bp + 0xffffff7e], ax ; 00940cda 89867eff
+ and ax, L4 ; 00940cde 250100
+ mov [0x2c], ax ; 00940ce1 a32c00
+ mov al, [bp + 0xffffff7e] ; 00940ce4 8a867eff
+ and ax, 0x02 ; 00940ce8 250200
+ shr al, 1 ; 00940ceb d0e8
+ mov [0x2e], ax ; 00940ced a32e00
+ mov al, [bp + 0xffffff7e] ; 00940cf0 8a867eff
+ and ax, 0x04 ; 00940cf4 250400
+ mov bx, [bp + 0x6] ; 00940cf7 8b5e06
+ shr al, 0x2 ; 00940cfa c0e802
+ mov [bx], ax ; 00940cfd 8907
+ mov al, [bp + 0xffffff7e] ; 00940cff 8a867eff
+ and ax, 0x08 ; 00940d03 250800
+ cmp ax, L4 ; 00940d06 3d0100
+ sbb ax, ax ; 00940d09 1bc0
+ and al, 0xfe ; 00940d0b 24fe
+ add ax, 0x03 ; 00940d0d 050300
+ mov [0x34], ax ; 00940d10 a33400
+ mov al, [bp + 0xffffff7e] ; 00940d13 8a867eff
+ and ax, 0x40 ; 00940d17 254000
+ shr al, 0x6 ; 00940d1a c0e806
+ mov [0x30], ax ; 00940d1d a33000
+ mov al, [bp + 0xffffff7e] ; 00940d20 8a867eff
+ and ax, 0x30 ; 00940d24 253000
+ shr al, 0x4 ; 00940d27 c0e804
+ dec ax ; 00940d2a 48
+ jz L294 ; 00940d2b 740b
+ dec ax ; 00940d2d 48
+ jz L295 ; 00940d2e 7410
+ mov word L296, 0x12e ; 00940d30 c70632002e01
+ jmp short L297 ; 00940d36 eb0e
+ mov word L296, 0x12f ; 00940d38 c70632002f01
+ jmp short L297 ; 00940d3e eb06
+ mov word L296, 0x130 ; 00940d40 c70632003001
+ push 0x63 ; 00940d46 6a63
+ push 0xc8 ; 00940d48 68c800
+ callf ; 00940d4b 9a4a01b408
+ mov cx, 0x0c ; 00940d50 b90c00
+ cwd ; 00940d53 99
+ idiv cx, ax ; 00940d54 f7f9
+ push dx ; 00940d56 52
+ callf ; 00940d57 9ad806100a
+ add ax, 0x35 ; 00940d5c 053500
+ push ax ; 00940d5f 50
+ push L290 ; 00940d60 6a36
+ push 0x41 ; 00940d62 6a41
+ callf ; 00940d64 9afc05220a
+ push ax ; 00940d69 50
+ push cs ; 00940d6a 0e
+ call L298 ; 00940d6b e861fe
+ o32 push 0xcd00cb ; 00940d6e 6668cb00cd00
+ push 0x0 ; 00940d74 6a00
+ callf ; 00940d76 9ad806380a
+ mov [0x264], ax ; 00940d7b a36402
+ o32 push 0xcd00cc ; 00940d7e 6668cc00cd00
+ push 0x1fa ; 00940d84 68fa01
+ push 0x53 ; 00940d87 685300
+ push 0x5 ; 00940d8a 6a05
+ callf ; 00940d8c 9a9806ef0a
+ leave ; 00940d91 c9
+ retf 0x02 ; 00940d92 ca0200
+ enter 0x84, 0x0 ; 00940d95 c8840000
+ test byte [bp + 0x6], L4 ; 00940d99 f6460601
+ je L299 ; 00940d9d 0f84a700
+ mov word [bp + 0xffffff7e], 0x00 ; 00940da1 c7867eff0000
+ mov al, [0x1ff0000] ; 00940da7 a0
+ sub al, 0x0 ; 00940da8 2c00
+ and ax, L4 ; 00940daa 250100
+ mov [bp + 0xffffff7e], ax ; 00940dad 89867eff
+ mov cx, ax ; 00940db1 8bc8
+ mov dx, L289 ; 00940db3 8b162e00
+ add dx, dx ; 00940db7 03d2
+ xor al, dl ; 00940db9 32c2
+ and ax, 0x02 ; 00940dbb 250200
+ xor cx, ax ; 00940dbe 33c8
+ mov [bp + 0xffffff7e], cx ; 00940dc0 898e7eff
+ mov ax, cx ; 00940dc4 8bc1
+ mov dx, L290 ; 00940dc6 8b163600
+ shl dx, byte 0x2 ; 00940dca c1e202
+ xor cl, dl ; 00940dcd 32ca
+ and cx, byte 0x4 ; 00940dcf 83e104
+ xor ax, cx ; 00940dd2 33c1
+ mov [bp + 0xffffff7e], ax ; 00940dd4 89867eff
+ mov [bp + 0xffffff7c], ax ; 00940dd8 89867cff
+ cmp word L291, byte 0x3 ; 00940ddc 833e340003
+ jnz L300 ; 00940de1 7505
+ mov ax, L4 ; 00940de3 b80100
+ jmp short L301 ; 00940de6 eb02
+ xor ax, ax ; 00940de8 33c0
+ shl ax, byte 0x3 ; 00940dea c1e003
+ mov cl, [bp + 0xffffff7c] ; 00940ded 8a8e7cff
+ xor cl, al ; 00940df1 32c8
+ and cx, byte 0x8 ; 00940df3 83e108
+ xor cx, [bp + 0xffffff7c] ; 00940df6 338e7cff
+ mov [bp + 0xffffff7e], cx ; 00940dfa 898e7eff
+ mov ax, [0x30] ; 00940dfe a13000
+ shl ax, byte 0x6 ; 00940e01 c1e006
+ xor cl, al ; 00940e04 32c8
+ and cx, byte 0x40 ; 00940e06 83e140
+ xor [bp + 0xffffff7e], cx ; 00940e09 318e7eff
+ mov ax, [0x32] ; 00940e0d a13200
+ sub ax, 0x12e ; 00940e10 2d2e01
+ jz L302 ; 00940e13 7408
+ dec ax ; 00940e15 48
+ jz L303 ; 00940e16 740c
+ dec ax ; 00940e18 48
+ jz L304 ; 00940e19 7413
+ jmp short L305 ; 00940e1b eb1d
+ and byte [bp + 0xffffff7e], 0xcf ; 00940e1d 80a67effcf
+ jmp short L305 ; 00940e22 eb16
+ mov ax, [bp + 0xffffff7e] ; 00940e24 8b867eff
+ and al, 0xdf ; 00940e28 24df
+ or al, 0x10 ; 00940e2a 0c10
+ jmp short L306 ; 00940e2c eb08
+ mov ax, [bp + 0xffffff7e] ; 00940e2e 8b867eff
+ and al, 0xef ; 00940e32 24ef
+ or al, 0x20 ; 00940e34 0c20
+ mov [bp + 0xffffff7e], ax ; 00940e36 89867eff
+ push 0x63 ; 00940e3a 6a63
+ push 0xc9 ; 00940e3c 68c900
+ push word [bp + 0xffffff7e] ; 00940e3f ffb67eff
+ callf ; 00940e43 9a7806060b
+ test byte [bp + 0x6], 0x4 ; 00940e48 f6460604
+ jz L307 ; 00940e4c 7411
+ push 0x63 ; 00940e4e 6a63
+ push 0xc8 ; 00940e50 68c800
+ mov ax, [0x16] ; 00940e53 a11600
+ sub ax, 0x35 ; 00940e56 2d3500
+ push ax ; 00940e59 50
+ callf ; 00940e5a 9a7806e505
+ leave ; 00940e5f c9
+ retf 0x02 ; 00940e60 ca0200
+ xor ax, [bx + si] ; 00940e63 3300
+ add ax, [bx + di] ; 00940e65 0301
+ scasb ; 00940e67 ae
+ add [bp + si], al ; 00940e68 0002
+ add [bx + di + 0], dh ; 00940e6a 007100
+ add ax, [bx + di] ; 00940e6d 0301
+ mov ax, 0x200 ; 00940e6f b80002
+ add [bp + si + 0], dh ; 00940e72 007200
+ add al, [bx + si] ; 00940e75 0200
+ xor [bp + di], al ; 00940e77 3003
+ add [bx + si], ax ; 00940e79 0100
+ add [bx + si], al ; 00940e7b 0000
+ add ax, [bx + di] ; 00940e7d 0301
+ ill_f1 ; 00940e7f f1
+ add [bp + si], ax ; 00940e80 0102
+ add [bp + 0], dh ; 00940e82 007600
+ add al, [bx + si] ; 00940e85 0200
+ ill_d9 ; 00940e87 d908
+ add al, [bx + si] ; 00940e89 0200
+ add [bx + si], al ; 00940e8b 0000
+ add al, [bx + si] ; 00940e8d 0200
+ a16 add ax, [ebx] ; 00940e8f 670303
+ add [bx + si], al ; 00940e92 0000
+ add [bp + di], al ; 00940e94 0003
+ add [bp + si + 0x203], ax ; 00940e96 01820302
+ add [si + 0], bh ; 00940e9a 007c00
+ add ax, [bx + di] ; 00940e9d 0301
+ xchg ax, sp ; 00940e9f 94
+ or [bp + si], al ; 00940ea0 0802
+ add [di + 0], bh ; 00940ea2 007d00
+ add al, [bx + si] ; 00940ea5 0200
+ jl L308 ; 00940ea7 7c05
+ add al, 0x0 ; 00940ea9 0400
+ add [bx + si], al ; 00940eab 0000
+ add ax, [bx + di] ; 00940ead 0301
+ adc ax, 0x205 ; 00940eaf 150502
+ add L89, al ; 00940eb2 00060003
+ add [si + 0x3], bx ; 00940eb6 015c03
+ add al, [bx + si] ; 00940eb9 0200
+ or al, [bx + si] ; 00940ebb 0a00
+ add ax, [bx + di] ; 00940ebd 0301
+ call L309 ; 00940ebf e80402
+ add [si], cl ; 00940ec2 000c
+ add [bp + si], al ; 00940ec4 0002
+ add [bp + di + 0x6], dl ; 00940ec6 005306
+ pop es ; 00940ec9 07
+ add [bx + si], al ; 00940eca 0000
+ add [bp + di], al ; 00940ecc 0003
+ add [bp + 0x208], sp ; 00940ece 01a60802
+ add [bx], cl ; 00940ed2 000f
+ add [bp + si], al ; 00940ed4 0002
+ add bh, dh ; 00940ed6 00f7
+ or [bx + si], cx ; 00940ed8 0908
+ add [bx + si], al ; 00940eda 0000
+ add [bp + di], al ; 00940edc 0003
+ add [bp + 0x7], di ; 00940ede 017e07
+ add al, [bx + si] ; 00940ee1 0200
+ adc al, [bx + si] ; 00940ee3 1200
+ add ax, [bx + di] ; 00940ee5 0301
+ xchg ax, sp ; 00940ee7 94
+ pop es ; 00940ee8 07
+ add al, [bx + si] ; 00940ee9 0200
+ adc ax, [bx + si] ; 00940eeb 1300
+ add al, [bx + si] ; 00940eed 0200
+ gs pop es ; 00940eef 6507
+ or [bx + si], ax ; 00940ef1 0900
+ add [bx + si], al ; 00940ef3 0000
+ add al, [bx + si] ; 00940ef5 0200
+ mov dh, 0x4 ; 00940ef7 b604
+ or al, [bx + si] ; 00940ef9 0a00
+ add [bx + si], al ; 00940efb 0000
+ add ax, [bx + di] ; 00940efd 0301
+ fld L310 ; 00940eff dd060200
+ fwait ; 00940f03 9b
+ add [bp + di], al ; 00940f04 0003
+ add [bx + 0x206], bp ; 00940f06 01af0602
+ add [di + 0x300], bl ; 00940f0a 009d0003
+ add [bx + si], sp ; 00940f0e 0120
+ add ax, L310 ; 00940f10 050200
+ pop ds ; 00940f13 1f
+ add [bp + di], al ; 00940f14 0003
+ add [si], bx ; 00940f16 011c
+ add [bp + si], al ; 00940f18 0002
+ add [bx], bl ; 00940f1a 001f
+ add [bp + di], ax ; 00940f1c 0103
+ add [bx], bp ; 00940f1e 012f
+ add ax, L310 ; 00940f20 050200
+ and [bx + si], ax ; 00940f23 2100
+ add ax, [bx + di] ; 00940f25 0301
+ movsb ; 00940f27 a4
+ push es ; 00940f28 06
+ add al, 0x0 ; 00940f29 0400
+ push ss ; 00940f2b 16
+ add [bp + di], al ; 00940f2c 0003
+ add bp, bx ; 00940f2e 01dd
+ add ax, [bp + si] ; 00940f30 0302
+ add [bx], ah ; 00940f32 0027
+ add [bp + di], al ; 00940f34 0003
+ add [bp + di], ax ; 00940f36 0103
+ add al, L310 ; 00940f38 0402
+ add [bx + si], ch ; 00940f3a 0028
+ add [bp + di], al ; 00940f3c 0003
+ add [bx + 0], di ; 00940f3e 017f00
+ add [bx + si], ax ; 00940f41 0100
+ xor al, [bx + si] ; 00940f43 3200
+ add ax, [bx + di] ; 00940f45 0301
+ jns L311 ; 00940f47 7903
+ add al, [bx + si] ; 00940f49 0200
+ sub al, [bx + si] ; 00940f4b 2a00
+ add ax, [bx + di] ; 00940f4d 0301
+ cmp [bp + di], ax ; 00940f4f 3903
+ add [bx + si], ax ; 00940f51 0100
+ xor ax, [bx + si] ; 00940f53 3300
+ add ax, [bx + di] ; 00940f55 0301
+ jmp short L312 ; 00940f57 eb08
+ add al, [bx + si] ; 00940f59 0200
+ stosw ; 00940f5b ab
+ add [bp + di], al ; 00940f5c 0003
+ add dx, si ; 00940f5e 01f2
+ add al, L4 ; 00940f60 0401
+ add [si], dh ; 00940f62 0034
+ add [bp + di], al ; 00940f64 0003
+ add [si], dx ; 00940f66 0114
+ add [bp + si], ax ; 00940f68 0102
+ add [di + 0x300], ch ; 00940f6a 00ad0003
+ add [bp + 0x206], bx ; 00940f6e 019e0602
+ add [bp + 0x300], ch ; 00940f72 00ae0003
+ add [bp + di], dx ; 00940f76 0113
+ add [bx + di], al ; 00940f78 0001
+ add L89, dh ; 00940f7a 00360003
+ add [si + 0x206], ax ; 00940f7e 01840602
+ add [bx + si + 0x300], dh ; 00940f82 00b00003
+ add [di + 0], si ; 00940f86 017500
+ add al, [bx + si] ; 00940f89 0200
+ mov bl, 0x0 ; 00940f8b b300
+ add ax, [bx + di] ; 00940f8d 0301
+ test [bp + si], al ; 00940f8f 8402
+ add al, [bx + si] ; 00940f91 0200
+ cmp [bx + si], ax ; 00940f93 3900
+ add ax, [bx + di] ; 00940f95 0301
+ push si ; 00940f97 56
+ add [bp + si], al ; 00940f98 0002
+ add [bp + di], bh ; 00940f9a 003b
+ add [bp + di], al ; 00940f9c 0003
+ add [bx + si], sp ; 00940f9e 0120
+ or [bp + si], al ; 00940fa0 0802
+ add [bp + si + 0], al ; 00940fa2 004200
+ add ax, [bx + di] ; 00940fa5 0301
+ dec si ; 00940fa7 4e
+ or [bp + si], al ; 00940fa8 0802
+ add [si + 0], al ; 00940faa 004400
+ add ax, [bx + di] ; 00940fad 0301
+ sbb ax, 0x203 ; 00940faf 1d0302
+ add ah, al ; 00940fb2 00c4
+ add [bp + di], ax ; 00940fb4 0103
+ add si, cx ; 00940fb6 01ce
+ add al, [bp + si] ; 00940fb8 0202
+ add dh, al ; 00940fba 00c6
+ add [bp + di], ax ; 00940fbc 0103
+ add di, cx ; 00940fbe 01cf
+ pop es ; 00940fc0 07
+ add al, [bx + si] ; 00940fc1 0200
+ inc di ; 00940fc3 47
+ add [bp + di], al ; 00940fc4 0003
+ add [bx + di + 0x301], di ; 00940fc6 01b90103
+ add [bp + si + 0], al ; 00940fca 004200
+ add ax, [bx + di] ; 00940fcd 0301
+ dec cx ; 00940fcf 49
+ add [bp + di], ax ; 00940fd0 0103
+ add [bx + si + 0], dl ; 00940fd2 005000
+ add ax, [bx + di] ; 00940fd5 0301
+ xor ax, [bx + di] ; 00940fd7 3301
+ add ax, [bx + si] ; 00940fd9 0300
+ pop bp ; 00940fdb 5d
+ add [bp + di], al ; 00940fdc 0003
+ add [si], si ; 00940fde 0134
+ add [bp + si], al ; 00940fe0 0002
+ add al, ch ; 00940fe2 00e8
+ add [bp + di], al ; 00940fe4 0003
+ add di, bx ; 00940fe6 01df
+ pop es ; 00940fe8 07
+ add al, [bx + si] ; 00940fe9 0200
+ imul ax, [bx + si], 0x3 ; 00940feb 6b0003
+ add [bx + si + 0x200], sp ; 00940fee 01a00002
+ add [si + 0], ch ; 00940ff2 006c00
+ add ax, [bx + di] ; 00940ff5 0301
+ outsb ; 00940ff7 6e
+ push es ; 00940ff8 06
+ add al, [bx + si] ; 00940ff9 0200
+ outsb ; 00940ffb 6e
+ add [bx + si], al ; 00940ffc 0000
+ add [bx + si], al ; 00940ffe 0000
+ add [bx + si], al ; 00941000 0000
+ add [bx + si], al ; 00941002 0000
+ add [bx + si], al ; 00941004 0000
+ add [bx + si], al ; 00941006 0000
+ add [bx + si], al ; 00941008 0000
+ add [bx + si], al ; 0094100a 0000
+ add [bx + si], al ; 0094100c 0000
+ add [bx + si], al ; 0094100e 0000
+ add [bx + si], al ; 00941010 0000
+ add [bx + si], al ; 00941012 0000
+ add [bx + si], al ; 00941014 0000
+ add [bx + si], al ; 00941016 0000
+ add [bx + si], al ; 00941018 0000
+ add [bx + si], al ; 0094101a 0000
+ add [bx + si], al ; 0094101c 0000
+ add [bx + si], al ; 0094101e 0000
+ add [bx + si], al ; 00941020 0000
+ add [bx + si], al ; 00941022 0000
+ add [bx + si], al ; 00941024 0000
+ add [si + 0xffff90d8], cl ; 00941026 008cd890
+ inc bp ; 0094102a 45
+ push bp ; 0094102b 55
+ mov bp, sp ; 0094102c 8bec
+ push ds ; 0094102e 1e
+ mov ds, ax ; 0094102f 8ed8
+ mov bx, [bp + 0x6] ; 00941031 8b5e06
+ mov cx, bx ; 00941034 8bcb
+ or bx, bx ; 00941036 0bdb
+ jns L313 ; 00941038 7902
+ neg bx ; 0094103a f7db
+ mov ax, [bp + 0xa] ; 0094103c 8b460a
+ xor cx, ax ; 0094103f 33c8
+ or ax, ax ; 00941041 0bc0
+ jns L314 ; 00941043 7902
+ neg ax ; 00941045 f7d8
+ mov dx, [bp + 0x8] ; 00941047 8b5608
+ xor cx, dx ; 0094104a 33ca
+ or dx, dx ; 0094104c 0bd2
+ jns L315 ; 0094104e 7902
+ neg dx ; 00941050 f7da
+ mul dx, ax ; 00941052 f7e2
+ mov cl, bl ; 00941054 8acb
+ sar bx, 1 ; 00941056 d1fb
+ add ax, bx ; 00941058 03c3
+ adc dx, byte 0x0 ; 0094105a 83d200
+ shl bx, 1 ; 0094105d d1e3
+ or bl, cl ; 0094105f 0ad9
+ cmp dx, bx ; 00941061 3bd3
+ jnc L316 ; 00941063 7318
+ div bx, ax ; 00941065 f7f3
+ or ax, ax ; 00941067 0bc0
+ js L316 ; 00941069 7812
+ or cx, cx ; 0094106b 0bc9
+ jns L317 ; 0094106d 7902
+ neg ax ; 0094106f f7d8
+ mov dx, L4 ; 00941071 ba0100
+ lea sp, [bp + 0xfffffffe] ; 00941074 8d66fe
+ pop ds ; 00941077 1f
+ pop bp ; 00941078 5d
+ dec bp ; 00941079 4d
+ retf 0x06 ; 0094107a ca0600
+ xor dx, dx ; 0094107d 33d2
+ mov ax, 0x7fff ; 0094107f b8ff7f
+ or cx, cx ; 00941082 0bc9
+ jns L318 ; 00941084 79ee
+ not ax ; 00941086 f7d0
+ jmp short L318 ; 00941088 ebea
+ add bh, bh ; 0094108a 00ff
+ call far oword [bx + si + 0x58] ; 0094108c ff5858
+ pop ax ; 0094108f 58
+ mov ah, L3 ; 00941090 b44c
+ cs test word cs:L319, L4 ; 00941092 2ef70674000100
+ jz L320 ; 00941099 7407
+ callf ; 0094109b 9affff0000
+ jmp short L321 ; 009410a0 eb02
+ int 0x21 ; 009410a2 cd21
+ mov al, 0xff ; 009410a4 b0ff
+ push ax ; 009410a6 50
+ push cs ; 009410a7 0e
+ call L322 ; 009410a8 e8e2ff
+ xor bp, bp ; 009410ab 33ed
+ push bp ; 009410ad 55
+ callf ; 009410ae 9affff0000
+ or ax, ax ; 009410b3 0bc0
+ jz L321 ; 009410b5 74ed
+ add cx, 0x100 ; 009410b7 81c10001
+ jc L321 ; 009410bb 72e7
+ mov L323, cx ; 009410bd 890ec201
+ mov L324, si ; 009410c1 8936c401
+ mov L325, di ; 009410c5 893ec601
+ mov L326, bx ; 009410c9 891ec801
+ mov word L201, es ; 009410cd 8c06ca01
+ mov L327, dx ; 009410d1 8916cc01
+ xor ax, ax ; 009410d5 33c0
+ push ax ; 009410d7 50
+ callf ; 009410d8 9affff0000
+ push word L325 ; 009410dd ff36c601
+ callf ; 009410e1 9affff0000
+ or ax, ax ; 009410e6 0bc0
+ jz L321 ; 009410e8 74ba
+ push word L325 ; 009410ea ff36c601
+ push word L324 ; 009410ee ff36c401
+ push word L201 ; 009410f2 ff36ca01
+ push word L326 ; 009410f6 ff36c801
+ push word L327 ; 009410fa ff36cc01
+ callf ; 009410fe 9a0000ffff
+ push ax ; 00941103 50
+ push cs ; 00941104 0e
+ call L322 ; 00941105 e885ff
+ add [di + 0xffffff8b], dl ; 00941108 00558b
+ in al, dx ; 0094110b ec
+ mov dx, di ; 0094110c 8bd7
+ mov bx, si ; 0094110e 8bde
+ mov ax, ds ; 00941110 8cd8
+ mov es, ax ; 00941112 8ec0
+ mov si, [bp + 0x8] ; 00941114 8b7608
+ mov di, [bp + 0x6] ; 00941117 8b7e06
+ mov ax, di ; 0094111a 8bc7
+ mov cx, [bp + 0xa] ; 0094111c 8b4e0a
+ jcxz L328 ; 0094111f e30e
+ test al, L4 ; 00941121 a801
+ jz L329 ; 00941123 7402
+ movsb ; 00941125 a4
+ dec cx ; 00941126 49
+ shr cx, 1 ; 00941127 d1e9
+ repe movsw ; 00941129 f3a5
+ adc cx, cx ; 0094112b 13c9
+ repe movsb ; 0094112d f3a4
+ mov si, bx ; 0094112f 8bf3
+ mov di, dx ; 00941131 8bfa
+ pop bp ; 00941133 5d
+ retf ; 00941134 cb
+ inc bp ; 00941135 45
+ push bp ; 00941136 55
+ mov bp, sp ; 00941137 8bec
+ push ds ; 00941139 1e
+ mov ax, [bp + 0x6] ; 0094113a 8b4606
+ cwd ; 0094113d 99
+ xor ax, dx ; 0094113e 33c2
+ sub ax, dx ; 00941140 2bc2
+ lea sp, [bp + 0xfffffffe] ; 00941142 8d66fe
+ pop ds ; 00941145 1f
+ pop bp ; 00941146 5d
+ dec bp ; 00941147 4d
+ retf ; 00941148 cb
+ inc bp ; 00941149 45
+ push bp ; 0094114a 55
+ mov bp, sp ; 0094114b 8bec
+ push ds ; 0094114d 1e
+ mov ax, [bp + 0x6] ; 0094114e 8b4606
+ mov [0x1d6], ax ; 00941151 a3d601
+ mov word L330, 0x00 ; 00941154 c706d8010000
+ lea sp, [bp + 0xfffffffe] ; 0094115a 8d66fe
+ pop ds ; 0094115d 1f
+ pop bp ; 0094115e 5d
+ dec bp ; 0094115f 4d
+ retf ; 00941160 cb
+ inc bp ; 00941161 45
+ push bp ; 00941162 55
+ mov bp, sp ; 00941163 8bec
+ push ds ; 00941165 1e
+ push 0x3 ; 00941166 6a03
+ push 0x43fd ; 00941168 68fd43
+ push word L330 ; 0094116b ff36d801
+ push word L87 ; 0094116f ff36d601
+ callf ; 00941173 9a7a01ffff
+ add ax, 0x9ec3 ; 00941178 05c39e
+ adc dx, byte 0x26 ; 0094117b 83d226
+ mov [0x1d6], ax ; 0094117e a3d601
+ mov L330, dx ; 00941181 8916d801
+ mov ax, dx ; 00941185 8bc2
+ and ah, 0x7f ; 00941187 80e47f
+ lea sp, [bp + 0xfffffffe] ; 0094118a 8d66fe
+ pop ds ; 0094118d 1f
+ pop bp ; 0094118e 5d
+ dec bp ; 0094118f 4d
+ retf ; 00941190 cb
+ push bp ; 00941191 55
+ mov bp, sp ; 00941192 8bec
+ mov ax, [bp + 0x8] ; 00941194 8b4608
+ mov cx, [bp + 0xc] ; 00941197 8b4e0c
+ or cx, ax ; 0094119a 0bc8
+ mov cx, [bp + 0xa] ; 0094119c 8b4e0a
+ jnz L331 ; 0094119f 7509
+ mov ax, [bp + 0x6] ; 009411a1 8b4606
+ mul cx, ax ; 009411a4 f7e1
+ pop bp ; 009411a6 5d
+ retf 0x08 ; 009411a7 ca0800
+ push bx ; 009411aa 53
+ mul cx, ax ; 009411ab f7e1
+ mov bx, ax ; 009411ad 8bd8
+ mov ax, [bp + 0x6] ; 009411af 8b4606
+ mul word [bp + 0xc], ax ; 009411b2 f7660c
+ add bx, ax ; 009411b5 03d8
+ mov ax, [bp + 0x6] ; 009411b7 8b4606
+ mul cx, ax ; 009411ba f7e1
+ add dx, bx ; 009411bc 03d3
+ pop bx ; 009411be 5b
+ pop bp ; 009411bf 5d
+ retf 0x08 ; 009411c0 ca0800
+ pop es ; 009411c3 07
+ add [bp + si], al ; 009411c4 0002
+ add dl, ch ; 009411c6 00ea
+ add [bx + di], al ; 009411c8 0001
+ add [bx + si], al ; 009411ca 0000
+ add [bp + di], al ; 009411cc 0003
+ add bx, cx ; 009411ce 01cb
+ add [bp + si], al ; 009411d0 0002
+ add [di], al ; 009411d2 0005
+ add [bp + si], al ; 009411d4 0002
+ add [bx + 0x1], bl ; 009411d6 005f01
+ or [bx + si], al ; 009411d9 0800
+ add [bx + si], al ; 009411db 0000
+ add ax, [bx + di] ; 009411dd 0301
+ ret 0x100 ; 009411df c20001
+ add L332, bl ; 009411e2 001e0005
+ add [si + 0], si ; 009411e6 017400
+ add [bx + si], ax ; 009411e9 0100
+ mov dl, 0x0 ; 009411eb b200
+ add ax, [bx + di] ; 009411ed 0301
+ cbw ; 009411ef 98
+ add [bx + di], al ; 009411f0 0001
+ add [bp + di + 0], bl ; 009411f2 005b00
+ add ax, [bx + di] ; 009411f5 0301
+ test [bx + si], ax ; 009411f7 8500
+ add [bx + si], ax ; 009411f9 0100
+ o32 add [bx + si], al ; 009411fb 660000
+ add [bx + si], al ; 009411fe 0000
+ add [bx + si], al ; 00941200 0000
+ add [bx + si], al ; 00941202 0000
+ add [bx + si], al ; 00941204 0000
+ add [bx + si], al ; 00941206 0000
+ add [bx + si], al ; 00941208 0000
+ add [bx + si], al ; 0094120a 0000
+ add [bx + si], al ; 0094120c 0000
+ add [bx + si], al ; 0094120e 0000
+ add [bx + si], al ; 00941210 0000
+ add [bx + si], al ; 00941212 0000
+ add [bx + si], al ; 00941214 0000
+ add [bx + si], al ; 00941216 0000
+ add [bx + si], al ; 00941218 0000
+ add [di], al ; 0094121a 0005
+ add [bx + si], al ; 0094121c 0000
+ add [bx + si], al ; 0094121e 0000
+ add [bx + si], al ; 00941220 0000
+ add [bx + si], al ; 00941222 0000
+ add [bx + si], al ; 00941224 0000
+ add bh, bh ; 00941226 00ff
+ jg L333 ; 00941228 7fff
+ jg L334 ; 0094122a 7f00
+ add bh, bh ; 0094122c 00ff
+ inc word [bx + si] ; 0094122e ff00
+ add [bx + si], al ; 00941230 0000
+ add [bx + si], al ; 00941232 0000
+ add [bx + si], al ; 00941234 0000
+ add [bx + si], al ; 00941236 0000
+ add [bp + di + 0x6f], dl ; 00941238 00536f
+ insb ; 0094123b 6c
+ imul si, [si + 0x61], 0x7269 ; 0094123c 6974616972
+ gs add gs:[bx + di], al ; 00941241 650001
+ add [bx + di], al ; 00941244 0001
+ add [bx + si], al ; 00941246 0000
+ add L335, ch ; 00941248 002e0103
+ add [bx + si], al ; 0094124c 0000
+ add [bx + si], al ; 0094124e 0000
+ add [bx + si], al ; 00941250 0000
+ add [bp + si + 0x65], dl ; 00941252 005265
+ a16 imul si, [ebx + 0x74], 0x7265 ; 00941255 676973746572
+ push ax ; 0094125b 50
+ gs outsb ; 0094125c 656e
+ inc cx ; 0094125e 41
+ jo L336 ; 0094125f 7070
+ add [bp + di + 0x6f], dl ; 00941261 00536f
+ insb ; 00941264 6c
+ add [bp + di + 0x6f], dl ; 00941265 00536f
+ insb ; 00941268 6c
+ add [si], ah ; 00941269 0024
+ add [bx + si], al ; 0094126b 0000
+ dec si ; 0094126d 4e
+ outsw ; 0094126e 6f
+ jz L337 ; 0094126f 7420
+ pop cx ; 00941271 59
+# invalid branch hint (65)
+ jz L338 ; 00941272 657420
+ dec cx ; 00941275 49
+ insw ; 00941276 6d
+ jo L339 ; 00941277 706c
+ gs insw ; 00941279 656d
+ gs outsb ; 0094127b 656e
+ jz L340 ; 0094127d 7465
+ fs add fs:[bp + di + 0x4f], dl ; 0094127f 6400534f
+ dec sp ; 00941283 4c
+ cs dec cx ; 00941284 2e49
+ dec si ; 00941286 4e
+ dec cx ; 00941287 49
+ add [bp + di + 0x4f], dl ; 00941288 00534f
+ dec sp ; 0094128b 4c
+ cs dec cx ; 0094128c 2e49
+ dec si ; 0094128e 4e
+ dec cx ; 0094128f 49
+ add [bp + di + 0x4f], dl ; 00941290 00534f
+ dec sp ; 00941293 4c
+ cs dec cx ; 00941294 2e49
+ dec si ; 00941296 4e
+ dec cx ; 00941297 49
+ add [bx + si], al ; 00941298 0000
+ add [bx + si], al ; 0094129a 0000
+ add [bx + si], al ; 0094129c 0000
+ add [bx + si], al ; 0094129e 0000
+ add [bx + si], al ; 009412a0 0000
+ add [bx + si], al ; 009412a2 0000
+ add [bx + si], al ; 009412a4 0000
+ add [bx + si], al ; 009412a6 0000
+ add [bx + si], al ; 009412a8 0000
+ add [bx + si], al ; 009412aa 0000
+ add [bx + si], al ; 009412ac 0000
+ add [bx + si], al ; 009412ae 0000
+ add [bx + si], al ; 009412b0 0000
+ add [bx + si], al ; 009412b2 0000
+ add [bx + si], al ; 009412b4 0000
+ add dh, bh ; 009412b6 00fe
+ jmp far xmm4 ; 009412b8 ffec
+ dec word [bp + si] ; 009412ba ff0a
+ add [di], al ; 009412bc 0005
+ add [di], al ; 009412be 0005
+ add cl, dh ; 009412c0 00f1
+ inc word [bx + si] ; 009412c2 ff00
+ add [bx + si], al ; 009412c4 0000
+ add [bx + si], al ; 009412c6 0000
+ add [bx + si], al ; 009412c8 0000
+ add [di], al ; 009412ca 0005
+ add [bx + si], al ; 009412cc 0000
+ add [bx + si], al ; 009412ce 0000
+ add bl, bh ; 009412d0 00fb
+ dec sp ; 009412d2 ffcc
+ inc word [bx + si] ; 009412d4 ff00
+ add [bp + di + 0x74], dl ; 009412d6 005374
+ popa ; 009412d9 61
+ jz L341 ; 009412da 7400
+ add [bx + si], al ; 009412dc 0000
+ add [bx + si], al ; 009412de 0000
+ add [bx + di + 0], al ; 009412e0 004100
+ and [bx + si], al ; 009412e3 2000
+ push ss ; 009412e5 16
+ add [si], al ; 009412e6 0004
+ add [bp + 0x2002], ah ; 009412e8 00a60220
+ add [bx + si], ah ; 009412ec 0020
+ add [bx + 0x2002], ah ; 009412ee 00a70220
+ add [bx + si], ah ; 009412f2 0020
+ add [bp + 0x2002], ah ; 009412f4 00a60220
+ add [bx + si], ah ; 009412f8 0020
+ add [bx + di + 0], al ; 009412fa 004100
+ and [bx + si], al ; 009412fd 2000
+ and [bx + si], al ; 009412ff 2000
+ aas ; 00941301 3f
+ add [si], ah ; 00941302 0024
+ add [si], cl ; 00941304 000c
+ add [bp + si], al ; 00941306 0002
+ add [bx + si + 0x2a02], ch ; 00941308 00a8022a
+ add [si], cl ; 0094130c 000c
+ add [bx], bh ; 0094130e 003f
+ add [bp + si], ch ; 00941310 002a
+ add [si], cl ; 00941312 000c
+ add [bx + si], al ; 00941314 0000
+ add [bx + si], al ; 00941316 0000
+ add [bx + si], al ; 00941318 0000
+ add [bx + si], al ; 0094131a 0000
+ add [bx + si], al ; 0094131c 0000
+ add [bx + si], al ; 0094131e 0000
+ add [bx + si + 0], al ; 00941320 004000
+ push cs ; 00941323 0e
+ add [si], cl ; 00941324 000c
+ add [si], al ; 00941326 0004
+ add [bx + di + 0x2f02], ch ; 00941328 00a9022f
+ add [bx + di], al ; 0094132c 0001
+ add [bp + si + 0x2f02], ch ; 0094132e 00aa022f
+ add [bx + di], al ; 00941332 0001
+ add [bx + di + 0x2f02], ch ; 00941334 00a9022f
+ add [bx + di], al ; 00941338 0001
+ add [bx + si + 0], al ; 0094133a 004000
+ das ; 0094133d 2f
+ add [bx + di], al ; 0094133e 0001
+ add [bx + si], bh ; 00941340 0038
+ add [bx + si], bl ; 00941342 0018
+ add [bx], al ; 00941344 0007
+ add [si], al ; 00941346 0004
+ add [bp + di + 0x1802], ch ; 00941348 00ab0218
+ add [bx + si], ch ; 0094134c 0028
+ add [si + 0x1802], ch ; 0094134e 00ac0218
+ add [bx + si], ch ; 00941352 0028
+ add [bp + di + 0x1802], ch ; 00941354 00ab0218
+ add [bx + si], ch ; 00941358 0028
+ add [bx + si], bh ; 0094135a 0038
+ add [bx + si], bl ; 0094135c 0018
+ add [bx + si], ch ; 0094135e 0028
+ add [bx + si], al ; 00941360 0000
+ add [bx + si], al ; 00941362 0000
+ add [bx + si], al ; 00941364 0000
+ add [bx + si], al ; 00941366 0000
+ add [bx + si], al ; 00941368 0000
+ add [bx + si], al ; 0094136a 0000
+ add [bx + si], al ; 0094136c 0000
+ add [bx + si], al ; 0094136e 0000
+ add [bx + si], al ; 00941370 0000
+ add [bx + si], al ; 00941372 0000
+ add [bx + si], al ; 00941374 0000
+ add [bx + si], al ; 00941376 0000
+ add [bx + si], al ; 00941378 0000
+ add [bx + si], al ; 0094137a 0000
+ add [bx + si], al ; 0094137c 0000
+ add [bx + si], al ; 0094137e 0000
+ add [bx + si], al ; 00941380 0000
+ add [bx + si], al ; 00941382 0000
+ add [bx + si], al ; 00941384 0000
+ add [bx + si], al ; 00941386 0000
+ add [bx + si], al ; 00941388 0000
+ add [bx + si], al ; 0094138a 0000
+ add [bx + si], al ; 0094138c 0000
+ add [bx + si], al ; 0094138e 0000
+ add [bx + si], al ; 00941390 0000
+ add [bx + si], al ; 00941392 0000
+ add [bx + si], al ; 00941394 0000
+ add [bx + si], al ; 00941396 0000
+ add [bx + si], al ; 00941398 0000
+ add [bx + si], al ; 0094139a 0000
+ add [bx + si], al ; 0094139c 0000
+ add [bx + si], al ; 0094139e 0000
+ add [bx + si], al ; 009413a0 0000
+ add [bx + si], al ; 009413a2 0000
+ add [bx + si], al ; 009413a4 0000
+ add [bx + si], al ; 009413a6 0000
+ add [bx + si], al ; 009413a8 0000
+ add [bx + si], al ; 009413aa 0000
+ add [bx + si], al ; 009413ac 0000
+ add [bx + si], al ; 009413ae 0000
+ add [bx + si], al ; 009413b0 0000
+ add [bx + si], al ; 009413b2 0000
+ add [bx + si], al ; 009413b4 0000
+ add [bx + si], al ; 009413b6 0000
+ add [bx + si], al ; 009413b8 0000
+ add [bx + si], al ; 009413ba 0000
+ add [bx + si], al ; 009413bc 0000
+ add [bx + si], al ; 009413be 0000
+ add [bx + si], al ; 009413c0 0000
+ add [bx + si], al ; 009413c2 0000
+ add [bx + si], al ; 009413c4 0000
+ add [bx + si], al ; 009413c6 0000
+ add [bx + si], al ; 009413c8 0000
+ add [bx + si], al ; 009413ca 0000
+ add [bx + si], al ; 009413cc 0000
+ add [bx + si], al ; 009413ce 0000
+ add [bx + si], al ; 009413d0 0000
+ add [bx + si], al ; 009413d2 0000
+ add [bx + si], al ; 009413d4 0000
+ add [bx + si], al ; 009413d6 0000
+ add [bx + si], al ; 009413d8 0000
+ add [bx + si], al ; 009413da 0000
+ add [bx + si], al ; 009413dc 0000
+ add [bx + si], al ; 009413de 0000
+ add [bx + si], al ; 009413e0 0000
+ add [bx + si], al ; 009413e2 0000
+ add [bx + di], al ; 009413e4 0001
+ add bh, bh ; 009413e6 00ff
+ inc word [bx + si] ; 009413e8 ff00
+ add [bx + si], al ; 009413ea 0000
+ add [bx + di], al ; 009413ec 0001
+ add [bx + si], al ; 009413ee 0000
+ add [bx + si], al ; 009413f0 0000
+ add [bx + si], al ; 009413f2 0000
+ add [bx + si], al ; 009413f4 0000
+ add [bx + si], al ; 009413f6 0000
+ add [bx + si], al ; 009413f8 0000
+ add [bx + si], al ; 009413fa 0000
+ add [bx + si], al ; 009413fc 0000
+ add [bx + si], al ; 009413fe 0000
+ add [bx + si], al ; 00941400 0000
+ add [bx + si], al ; 00941402 0000
+ add [bx + si], al ; 00941404 0000
+ add [bx + si], al ; 00941406 0000
+ add [bx + si], al ; 00941408 0000
+ add [bx + si], al ; 0094140a 0000
+ add [bx + si], al ; 0094140c 0000
+ add [bx + si], al ; 0094140e 0000
+ add [bx + si], al ; 00941410 0000
+ add [bx + si], al ; 00941412 0000
+ add [bx + si], al ; 00941414 0000
+ add [bx + si], al ; 00941416 0000
+ add [bx + si], al ; 00941418 0000
+ add [bx + si], al ; 0094141a 0000
+ add [bx + si], al ; 0094141c 0000
+ add [bx + si], al ; 0094141e 0000
+ add [bx + si], al ; 00941420 0000
+ add [bx + si], al ; 00941422 0000
+ add [bx + si], al ; 00941424 0000
+ add [bx + si], al ; 00941426 0000
+ add [bx + si], al ; 00941428 0000
+ add [bx + si], al ; 0094142a 0000
+ add [bx + si], al ; 0094142c 0000
+ add [bx + si], al ; 0094142e 0000
+ add [bx + si], al ; 00941430 0000
+ add [bx + si], al ; 00941432 0000
+ add [bx + si], al ; 00941434 0000
+ add [bx + si], al ; 00941436 0000
+ add [bx + si], al ; 00941438 0000
+ add [bx + si], al ; 0094143a 0000
+ add [bx + si], al ; 0094143c 0000
+ add [bx + si], al ; 0094143e 0000
+ add [bx + si], al ; 00941440 0000
+ add [bx + si], al ; 00941442 0000
+ add [bx + si], al ; 00941444 0000
+ add [bx + si], al ; 00941446 0000
+ add [bx + si], al ; 00941448 0000
+ add [bx + si], al ; 0094144a 0000
+ add [bx + si], al ; 0094144c 0000
+ add [bx + si], al ; 0094144e 0000
+ add [bx + si], al ; 00941450 0000
+ add [bx + si], al ; 00941452 0000
+ add [bx + si], al ; 00941454 0000
+ add [bx + si], al ; 00941456 0000
+ add [bx + si], al ; 00941458 0000
+ add [bx + si], al ; 0094145a 0000
+ add [bx + si], al ; 0094145c 0000
+ add [bx + si], al ; 0094145e 0000
+ add [bx + si], al ; 00941460 0000
+ add [bx + si], al ; 00941462 0000
+ add [bx + si], al ; 00941464 0000
+ add [bx + si], al ; 00941466 0000
+ add [bx + si], al ; 00941468 0000
+ add [bx + si], al ; 0094146a 0000
+ add [bx + si], al ; 0094146c 0000
+ add [bx + si], al ; 0094146e 0000
+ add [bx + si], al ; 00941470 0000
+ add [bx + si], al ; 00941472 0000
+ add [bx + si], al ; 00941474 0000
+ add [bx + si], al ; 00941476 0000
+ add [bx + si], al ; 00941478 0000
+ add [bx + si], al ; 0094147a 0000
+ add [bx + si], al ; 0094147c 0000
+ add [bx + si], al ; 0094147e 0000
+ add [bx + si], al ; 00941480 0000
+ add [bx + si], al ; 00941482 0000
+ add [bx + si], al ; 00941484 0000
+ add [bx + si], al ; 00941486 0000
+ add [bx + si], al ; 00941488 0000
+ add [bx + si], al ; 0094148a 0000
+ add [bx + si], al ; 0094148c 0000
+ add [bx + si], al ; 0094148e 0000
+ add [bx + si], al ; 00941490 0000
+ add [bx + si], al ; 00941492 0000
+ add [bx + si], al ; 00941494 0000
+ add [bx + si], al ; 00941496 0000
+ add [bx + si], al ; 00941498 0000
+ add [bx + si], al ; 0094149a 0000
+ add [bx + si], al ; 0094149c 0000
+ add [bx + si], al ; 0094149e 0000
+ add [bx + si], al ; 009414a0 0000
+ add [bx + si], al ; 009414a2 0000
+ add [bx + si], al ; 009414a4 0000
+ add [bx + si], al ; 009414a6 0000
+ add [bx + si], al ; 009414a8 0000
+ add [bx + si], al ; 009414aa 0000
+ add [bx + si], al ; 009414ac 0000
+ add [bx + si], al ; 009414ae 0000
+ add [bx + si], al ; 009414b0 0000
+ add [bx + si], al ; 009414b2 0000
+ add [bx + si], al ; 009414b4 0000
+ add [bx + si], al ; 009414b6 0000
+ add [bx + si], al ; 009414b8 0000
+ add [bx + si], al ; 009414ba 0000
+ add [bx + si], al ; 009414bc 0000
+ add [bx + si], al ; 009414be 0000
+ add [bx + si], al ; 009414c0 0000
+ add [bx + si], al ; 009414c2 0000
+ add [bx + si], al ; 009414c4 0000
+ add [bx + si], al ; 009414c6 0000
+ add [bx + si], al ; 009414c8 0000
+ add [bx + si], al ; 009414ca 0000
+ add [bx + si], al ; 009414cc 0000
+ add [bx + si], al ; 009414ce 0000
+ add [bx + si], al ; 009414d0 0000
+ add [bx + si], al ; 009414d2 0000
+ add [bx + si], al ; 009414d4 0000
+ add [bx + si], al ; 009414d6 0000
+ add [bx + si], al ; 009414d8 0000
+ add [bx + si], al ; 009414da 0000
+ add [bx + si], al ; 009414dc 0000
+ add [bx + si], al ; 009414de 0000
+ add [bx + si], al ; 009414e0 0000
+ add [bx + si], al ; 009414e2 0000
+ add [bx + si], al ; 009414e4 0000
+ add [bx + si], al ; 009414e6 0000
+ add [bx + si], al ; 009414e8 0000
+ add [bx + si], al ; 009414ea 0000
+ add [bx + si], al ; 009414ec 0000
+ add [bx + si], al ; 009414ee 0000
+ add [bx + si], al ; 009414f0 0000
+ add [bx + si], al ; 009414f2 0000
+ add [bx + si], al ; 009414f4 0000
+ add [bx + si], al ; 009414f6 0000
+ add [bx + si], al ; 009414f8 0000
+ add [bx + si], al ; 009414fa 0000
+ add [bx + si], al ; 009414fc 0000
+ add [bx + si], al ; 009414fe 0000
+ add [bx + si], al ; 00941500 0000
+ add [bx + si], al ; 00941502 0000
+ add [bx + si], al ; 00941504 0000
+ add [bx + si], al ; 00941506 0000
+ add [bx + si], al ; 00941508 0000
+ add [bx + si], al ; 0094150a 0000
+ add [bx + si], al ; 0094150c 0000
+ add [bx + si], al ; 0094150e 0000
+ add [bx + si], al ; 00941510 0000
+ add [bx + si], al ; 00941512 0000
+ add [bx + si], al ; 00941514 0000
+ add al, cl ; 00941516 00c8
+ add al, [bx + si] ; 00941518 0200
+ add [bp + si + 0x40], ch ; 0094151a 006a40
+ push word [bp + 0x6] ; 0094151d ff7606
+ callf ; 00941520 9affff0000
+ leave ; 00941525 c9
+ retf L310 ; 00941526 ca0200
+ push bp ; 00941529 55
+ mov bp, sp ; 0094152a 8bec
+ push word [bp + 0x6] ; 0094152c ff7606
+ callf ; 0094152f 9affff0000
+ leave ; 00941534 c9
+ retf L310 ; 00941535 ca0200
+ nop ; 00941538 90
+ push bp ; 00941539 55
+ mov bp, sp ; 0094153a 8bec
+ push word L279 ; 0094153c ff361a00
+ push ds ; 00941540 1e
+ push word [bp + 0x6] ; 00941541 ff7606
+ callf ; 00941544 9affff0000
+ leave ; 00941549 c9
+ retf L310 ; 0094154a ca0200
+ enter L310, 0x0 ; 0094154d c8020000
+ mov bx, [bp + 0x6] ; 00941551 8b5e06
+ test byte [bx + 0x1], 0x80 ; 00941554 f6470180
+ jz L342 ; 00941558 7407
+ mov ax, [bx] ; 0094155a 8b07
+ and ah, 0x7f ; 0094155c 80e47f
+ jmp short L343 ; 0094155f eb03
+ mov ax, [0x16] ; 00941561 a11600
+ mov [bp + 0xfffffffe], ax ; 00941564 8946fe
+ push word L279 ; 00941567 ff361a00
+ mov ax, [bx + 0x2] ; 0094156b 8b4702
+ sub ax, L344 ; 0094156e 2b061e00
+ push ax ; 00941572 50
+ mov ax, [bx + 0x4] ; 00941573 8b4704
+ sub ax, L345 ; 00941576 2b062000
+ push ax ; 0094157a 50
+ push word L84 ; 0094157b ff366802
+ push word L82 ; 0094157f ff366a02
+ push word [bp + 0xfffffffe] ; 00941583 ff76fe
+ mov ah, [bx + 0x1] ; 00941586 8a6701
+ and ax, 0x8000 ; 00941589 250080
+ cmp ax, L4 ; 0094158c 3d0100
+ sbb ax, ax ; 0094158f 1bc0
+ neg ax ; 00941591 f7d8
+ push ax ; 00941593 50
+ o32 push dword L346 ; 00941594 66ff36b202
+ callf ; 00941599 9a9200b801
+ leave ; 0094159e c9
+ retf L310 ; 0094159f ca0200
+ nop ; 009415a2 90
+ enter 0x08, 0x0 ; 009415a3 c8080000
+ callf ; 009415a7 9a0c085d01
+ or ax, ax ; 009415ac 0bc0
+ je L347 ; 009415ae 0f84c400
+ mov bx, [bp + 0xc] ; 009415b2 8b5e0c
+ o32 mov eax, [bx] ; 009415b5 668b07
+ o32 mov [bp + 0xfffffffa], eax ; 009415b8 668946fa
+ push word L279 ; 009415bc ff361a00
+ push 0x6 ; 009415c0 6a06
+ callf ; 009415c2 9a56010000
+ mov [bp + 0xfffffff8], ax ; 009415c7 8946f8
+ push word L279 ; 009415ca ff361a00
+ push word [bp + 0xfffffffa] ; 009415ce ff76fa
+ push word [bp + 0xfffffffc] ; 009415d1 ff76fc
+ callf ; 009415d4 9a31010000
+ push word L279 ; 009415d9 ff361a00
+ mov ax, [bp + 0xfffffffa] ; 009415dd 8b46fa
+ add ax, L84 ; 009415e0 03066802
+ push ax ; 009415e4 50
+ push word [bp + 0xfffffffc] ; 009415e5 ff76fc
+ callf ; 009415e8 9af5000000
+ push word L279 ; 009415ed ff361a00
+ mov ax, [bp + 0xfffffffa] ; 009415f1 8b46fa
+ add ax, L84 ; 009415f4 03066802
+ push ax ; 009415f8 50
+ mov ax, [bp + 0xa] ; 009415f9 8b460a
+ dec ax ; 009415fc 48
+ imul word [bp + 0x6], ax ; 009415fd f76e06
+ add ax, [bp + 0xfffffffc] ; 00941600 0346fc
+ add ax, L82 ; 00941603 03066a02
+ mov [bp + 0xfffffffe], ax ; 00941607 8946fe
+ push ax ; 0094160a 50
+ callf ; 0094160b 9a04010000
+ push word L279 ; 00941610 ff361a00
+ push word [bp + 0xfffffffa] ; 00941614 ff76fa
+ push word [bp + 0xfffffffe] ; 00941617 ff76fe
+ callf ; 0094161a 9a13010000
+ push word L279 ; 0094161f ff361a00
+ push word [bp + 0xfffffffa] ; 00941623 ff76fa
+ push word [bp + 0xfffffffc] ; 00941626 ff76fc
+ callf ; 00941629 9a45010000
+ mov ax, [bp + 0xfffffffc] ; 0094162e 8b46fc
+ mov [bp + 0xfffffffe], ax ; 00941631 8946fe
+ jmp short L348 ; 00941634 eb2a
+ push word L279 ; 00941636 ff361a00
+ push word [bp + 0xfffffffa] ; 0094163a ff76fa
+ mov ax, [bp + 0x6] ; 0094163d 8b4606
+ add [bp + 0xfffffffe], ax ; 00941640 0146fe
+ mov ax, [bp + 0xfffffffe] ; 00941643 8b46fe
+ push ax ; 00941646 50
+ callf ; 00941647 9affff0000
+ push word L279 ; 0094164c ff361a00
+ mov ax, [bp + 0xfffffffa] ; 00941650 8b46fa
+ add ax, L84 ; 00941653 03066802
+ push ax ; 00941657 50
+ push word [bp + 0xfffffffe] ; 00941658 ff76fe
+ callf ; 0094165b 9affff0000
+ dec word [bp + 0xa] ; 00941660 ff4e0a
+ jnz L349 ; 00941663 75d1
+ push word L279 ; 00941665 ff361a00
+ push word [bp + 0xfffffff8] ; 00941669 ff76f8
+ callf ; 0094166c 9affff0000
+ callf ; 00941671 9a38086702
+ leave ; 00941676 c9
+ retf 0x08 ; 00941677 ca0800
+ nop ; 0094167a 90
+ enter L310, 0x0 ; 0094167b c8020000
+ mov bx, [bp + 0x8] ; 0094167f 8b5e08
+ test byte [bx + 0x1], 0x80 ; 00941682 f6470180
+ jz L350 ; 00941686 7407
+ mov ax, [bx] ; 00941688 8b07
+ and ah, 0x7f ; 0094168a 80e47f
+ jmp short L351 ; 0094168d eb03
+ mov ax, [0x16] ; 0094168f a11600
+ mov [bp + 0xfffffffe], ax ; 00941692 8946fe
+ push word L279 ; 00941695 ff361a00
+ mov bx, [bp + 0x6] ; 00941699 8b5e06
+ mov ax, [bx] ; 0094169c 8b07
+ sub ax, L344 ; 0094169e 2b061e00
+ push ax ; 009416a2 50
+ mov ax, [bx + 0x2] ; 009416a3 8b4702
+ sub ax, L345 ; 009416a6 2b062000
+ push ax ; 009416aa 50
+ push word L84 ; 009416ab ff366802
+ push word L82 ; 009416af ff366a02
+ push word [bp + 0xfffffffe] ; 009416b3 ff76fe
+ mov bx, [bp + 0x8] ; 009416b6 8b5e08
+ mov ah, [bx + 0x1] ; 009416b9 8a6701
+ and ax, 0x8000 ; 009416bc 250080
+ cmp ax, L4 ; 009416bf 3d0100
+ sbb ax, ax ; 009416c2 1bc0
+ neg ax ; 009416c4 f7d8
+ push ax ; 009416c6 50
+ o32 push dword L346 ; 009416c7 66ff36b202
+ callf ; 009416cc 9a9200eb01
+ leave ; 009416d1 c9
+ retf 0x04 ; 009416d2 ca0400
+ push bp ; 009416d5 55
+ mov bp, sp ; 009416d6 8bec
+ push word L279 ; 009416d8 ff361a00
+ mov bx, [bp + 0xa] ; 009416dc 8b5e0a
+ mov ax, [bx] ; 009416df 8b07
+ sub ax, L344 ; 009416e1 2b061e00
+ push ax ; 009416e5 50
+ mov ax, [bx + 0x2] ; 009416e6 8b4702
+ sub ax, L345 ; 009416e9 2b062000
+ push ax ; 009416ed 50
+ push word L84 ; 009416ee ff366802
+ push word L82 ; 009416f2 ff366a02
+ o32 push dword [bp + 0x6] ; 009416f6 66ff7606
+ o32 push dword L346 ; 009416fa 66ff36b202
+ callf ; 009416ff 9a9200ffff
+ leave ; 00941704 c9
+ retf 0x06 ; 00941705 ca0600
+ nop ; 00941708 90
+
+ .section .codeSection4, @progbits
+ .align 0
+
+ xor [si], bl ; 0094000c 301c
+ sub al, 0x80 ; 0094000e 2c80
+ add [bx + si], al ; 00940010 0000
+ add [bx + si], al ; 00940012 0000
+ push di ; 00940014 57
+ and cx, [bp + si + 0] ; 00940015 234a00
+ xor [si], bl ; 00940018 301c
+ sub ax, 0x80 ; 0094001a 2d8000
+ add [bx + si], al ; 0094001d 0000
+ add [bx + di + 0x4a23], ah ; 0094001f 00a1234a
+ add [bx + si], dh ; 00940023 0030
+ sbb al, L289 ; 00940025 1c2e
+ add byte [bx + si], 0x0 ; 00940027 800000
+ add [bx + si], al ; 0094002a 0000
+ jmp short L352 ; 0094002c eb23
+ dec dx ; 0094002e 4a
+ add [bx + si], dh ; 0094002f 0030
+ sbb al, 0x2f ; 00940031 1c2f
+ add byte [bx + si], 0x0 ; 00940033 800000
+
+L2:
+ add [bx + si], al ; 00940036 0000
+ xor ax, 0x4a24 ; 00940038 35244a
+ add [bx + si], dh ; 0094003b 0030
+ sbb al, 0x30 ; 0094003d 1c30
+ add byte [bx + si], 0x0 ; 0094003f 800000
+ add [bx + si], al ; 00940042 0000
+ jg L353 ; 00940044 7f24
+ dec dx ; 00940046 4a
+ add [bx + si], dh ; 00940047 0030
+ sbb al, 0x31 ; 00940049 1c31
+ add byte [bx + si], 0x0 ; 0094004b 800000
+ add [bx + si], al ; 0094004e 0000
+ leave ; 00940050 c9
+ and al, L16 ; 00940051 24dd
+ add [bx + si], dh ; 00940053 0030
+ sbb al, L296 ; 00940055 1c32
+ add byte [bx + si], 0x0 ; 00940057 800000
+ add [bx + si], al ; 0094005a 0000
+ cmpsb ; 0094005c a6
+ and ax, L16 ; 0094005d 25dd00
+ xor [si], bl ; 00940060 301c
+ xor ax, [bx + si + 0] ; 00940062 33800000
+ add [bx + si], al ; 00940066 0000
+ and word L16, byte 0x30 ; 00940068 8326dd0030
+ sbb al, L291 ; 0094006d 1c34
+ add byte [bx + si], 0x0 ; 0094006f 800000
+ add [bx + si], al ; 00940072 0000
+ pusha ; 00940074 60
+ daa ; 00940075 27
+ fadd [bx + si] ; 00940076 dc00
+ xor [si], bl ; 00940078 301c
+ inc sp ; 0094007a 44
+ add byte [bx + si], 0x0 ; 0094007b 800000
+ add [bx + si], al ; 0094007e 0000
+ cmp al, 0x28 ; 00940080 3c28
+ fadd [bx + si] ; 00940082 dc00
+ xor [si], bl ; 00940084 301c
+ inc bx ; 00940086 43
+ add byte [bx + si], 0x0 ; 00940087 800000
+ add [bx + si], al ; 0094008a 0000
+ add al, 0x80 ; 0094008c 0480
+ add [bx + si], ax ; 0094008e 0100
+ add [bx + si], al ; 00940090 0000
+ add [bx + si], al ; 00940092 0000
+ sbb [bx + di], ch ; 00940094 1829
+ or [bx + si], ax ; 00940096 0900
+ xor [si], bl ; 00940098 301c
+ add [bx + si + 0], ax ; 0094009a 01800000
+ add [bx + si], al ; 0094009e 0000
+ add ax, 0x280 ; 009400a0 058002
+ add [bx + si], al ; 009400a3 0000
+ add [bx + si], al ; 009400a5 0000
+ add [bx + di], ah ; 009400a7 0021
+ sub [bp + di], dx ; 009400a9 2913
+ add [bx + si], dh ; 009400ab 0030
+ sbb al, 0x65 ; 009400ad 1c65
+ add byte [bx + si], 0x0 ; 009400af 800000
+ add [bx + si], al ; 009400b2 0000
+ xor al, 0x29 ; 009400b4 3429
+ sbb [bx + si], al ; 009400b6 1800
+ xor [si], bl ; 009400b8 301c
+ a16 add byte [eax], 0x0 ; 009400ba 67800000
+ add [bx + si], al ; 009400be 0000
+ push es ; 009400c0 06
+ add byte [bx], 0x0 ; 009400c1 800700
+ add [bx + si], al ; 009400c4 0000
+ add [bx + si], al ; 009400c6 0000
+ dec sp ; 009400c8 4c
+ sub [bp + si], cx ; 009400c9 290a
+ add [bx + si], dh ; 009400cb 0030
+ sbb al, 0x7 ; 009400cd 1c07
+ add byte [bx + si], 0x0 ; 009400cf 800000
+ add [bx + si], al ; 009400d2 0000
+ push si ; 009400d4 56
+ sub [si], ax ; 009400d5 2904
+ add [bx + si], dh ; 009400d7 0030
+ sbb al, 0xd ; 009400d9 1c0d
+ add byte [bx + si], 0x0 ; 009400db 800000
+ add [bx + si], al ; 009400de 0000
+ pop dx ; 009400e0 5a
+ sub L17, cx ; 009400e1 290e0030
+ sbb al, 0x13 ; 009400e5 1c13
+ add byte [bx + si], 0x0 ; 009400e7 800000
+ add [bx + si], al ; 009400ea 0000
+ push 0x729 ; 009400ec 682907
+ add [bx + si], dh ; 009400ef 0030
+ sbb al, 0x3f ; 009400f1 1c3f
+ add byte [bx + si], 0x0 ; 009400f3 800000
+ add [bx + si], al ; 009400f6 0000
+ outsw ; 009400f8 6f
+ sub [si], ax ; 009400f9 2904
+ add [bx + si], dh ; 009400fb 0030
+ sbb al, 0x0 ; 009400fd 1c00
+ nop ; 009400ff 90
+ add [bx + si], al ; 00940100 0000
+ add [bx + si], al ; 00940102 0000
+ jnc L354 ; 00940104 7329
+ add al, 0x0 ; 00940106 0400
+ xor [si], bl ; 00940108 301c
+ add ax, [bx + si + 0] ; 0094010a 03800000
+ add [bx + si], al ; 0094010e 0000
+ ja L355 ; 00940110 7729
+ add al, [bx + si] ; 00940112 0200
+ xor [si], bl ; 00940114 301c
+ jle L356 ; 00940116 7e80
+ add [bx + si], al ; 00940118 0000
+ add [bx + si], al ; 0094011a 0000
+ adc [bx + si + 0x1], al ; 0094011c 10800100
+ add [bx + si], al ; 00940120 0000
+ add [bx + si], al ; 00940122 0000
+ jns L357 ; 00940124 7929
+ push ds ; 00940126 1e
+ add [bx + si], dh ; 00940127 0030
+ or al, L4 ; 00940129 0c01
+ add byte [bx + si], 0x0 ; 0094012b 800000
+ add [bx + si], al ; 0094012e 0000
+ add ax, [bx + si + 0x2] ; 00940130 03800200
+ add [bx + si], al ; 00940134 0000
+ add [bx + si], al ; 00940136 0000
+ xchg ax, di ; 00940138 97
+ sub [bx], bp ; 00940139 292f
+ add [bx + si], dl ; 0094013b 0010
+ sbb al, L4 ; 0094013d 1c01
+ add byte [bx + si], 0x0 ; 0094013f 800000
+ add [bx + si], al ; 00940142 0000
+ mov byte [bx + di], 0x13 ; 00940144 c62913
+ add [bx + si], dl ; 00940147 0010
+ sbb al, L310 ; 00940149 1c02
+ add byte [bx + si], 0x0 ; 0094014b 800000
+ add [bx + si], al ; 0094014e 0000
+ add [bx + si], al ; 00940150 0000
+ add dx, [bp + di + 0x4f] ; 00940152 03534f
+ dec sp ; 00940155 4c
+ add dx, [bp + di + 0x4f] ; 00940156 03534f
+ dec sp ; 00940159 4c
+ add [bx + si], al ; 0094015a 0000
+ add [bx + di], al ; 0094015c 0001
+ add [bx + si], cl ; 0094015e 0008
+ add [di], cl ; 00940160 000d
+ add [bx + di], dl ; 00940162 0011
+ add [bx + si], al ; 00940164 0000
+ push es ; 00940166 06
+ dec bx ; 00940167 4b
+ inc bp ; 00940168 45
+ push dx ; 00940169 52
+ dec si ; 0094016a 4e
+ inc bp ; 0094016b 45
+ dec sp ; 0094016c 4c
+ add al, 0x55 ; 0094016d 0455
+ push bx ; 0094016f 53
+ inc bp ; 00940170 45
+ push dx ; 00940171 52
+ add ax, [bx + 0x44] ; 00940172 034744
+ dec cx ; 00940175 49
+ add ax, 0x4853 ; 00940176 055348
+ inc bp ; 00940179 45
+ dec sp ; 0094017a 4c
+ dec sp ; 0094017b 4c
+ add [bp + di], dl ; 0094017c 0013
+ dec bp ; 0094017e 4d
+ imul sp, [bp + di + 0x72], 0x736f ; 0094017f 6963726f73
+ outsw ; 00940184 6f
+ o32 jz L358 ; 00940185 667420
+ push bx ; 00940188 53
+ outsw ; 00940189 6f
+ insb ; 0094018a 6c
+ imul si, [si + 0x61], 0x7269 ; 0094018b 6974616972
+ gs add gs:[bx + si], al ; 00940190 650000
+ add [bx + si], al ; 00940193 0000
+ add [bx + si], al ; 00940195 0000
+ add [bx + si], al ; 00940197 0000
+ add [bx + si], al ; 00940199 0000
+ add [bx + si], al ; 0094019b 0000
+ add [bx + si], al ; 0094019d 0000
+ add [bx + si], al ; 0094019f 0000
+ add [bx + si], al ; 009401a1 0000
+ add [bx + si], al ; 009401a3 0000
+ add [bx + si], al ; 009401a5 0000
+ add [bx + si], al ; 009401a7 0000
+ add [bx + si], al ; 009401a9 0000
+ add [bx + si], al ; 009401ab 0000
+ add [bx + si], al ; 009401ad 0000
+ add [bx + si], al ; 009401af 0000
+ add [bx + si], al ; 009401b1 0000
+ add [bx + si], al ; 009401b3 0000
+ add [bx + si], al ; 009401b5 0000
+ add [bx + si], al ; 009401b7 0000
+ add [bx + si], al ; 009401b9 0000
+ add [bx + si], al ; 009401bb 0000
+ add [bx + si], al ; 009401bd 0000
+ add [bx + si], al ; 009401bf 0000
+ add [bx + si], al ; 009401c1 0000
+ add [bx + si], al ; 009401c3 0000
+ add [bx + si], al ; 009401c5 0000
+ add [bx + si], al ; 009401c7 0000
+ add [bx + si], al ; 009401c9 0000
+ add [bx + si], al ; 009401cb 0000
+ add [bx + si], al ; 009401cd 0000
+ add [bx + si], al ; 009401cf 0000
+ add [bx + si], al ; 009401d1 0000
+ add [bx + si], al ; 009401d3 0000
+ add [bx + si], al ; 009401d5 0000
+ add [bx + si], al ; 009401d7 0000
+ add [bx + si], al ; 009401d9 0000
+ add [bx + si], al ; 009401db 0000
+ add al, cl ; 009401dd 00c8
+ sbb [bx + si], al ; 009401df 1800
+ add [bp + di + 0xc7e], al ; 009401e1 00837e0c
+ add [si + 0x55], dh ; 009401e5 007455
+ push word [bp + 0xc] ; 009401e8 ff760c
+ push L23 ; 009401eb 68f001
+ push L310 ; 009401ee 6a02
+ callf ; 009401f0 9affff0000
+ push word L23 ; 009401f5 ff36f001
+ callf ; 009401f9 9affff0000
+ mov [bp + 0xffffffec], ax ; 009401fe 8946ec
+ push word L23 ; 00940201 ff36f001
+ push 0x0 ; 00940205 6a00
+ push 0x0 ; 00940207 6a00
+ push 0x0 ; 00940209 6a00
+ push 0x0 ; 0094020b 6a00
+ push 0x0 ; 0094020d 6a00
+ push 0x43 ; 0094020f 6a43
+ callf ; 00940211 9affff0000
+ push word L23 ; 00940216 ff36f001
+ callf ; 0094021a 9affff0000
+ or ax, ax ; 0094021f 0bc0
+ jz L359 ; 00940221 740d
+ push word L23 ; 00940223 ff36f001
+ push 0x9 ; 00940227 6a09
+ callf ; 00940229 9affff0000
+ jmp short L360 ; 0094022e eb08
+ push word [bp + 0xffffffec] ; 00940230 ff76ec
+ callf ; 00940233 9affff0000
+ xor ax, ax ; 00940238 33c0
+ jmp L361 ; 0094023a e98200
+ o32 push dword [bp + 0xc] ; 0094023d 66ff760c
+ o32 push dword [bp + 0x8] ; 00940241 66ff7608
+ push word [bp + 0x6] ; 00940245 ff7606
+ push cs ; 00940248 0e
+ call L362 ; 00940249 e87800
+ or ax, ax ; 0094024c 0bc0
+ jz L360 ; 0094024e 74e8
+ push 0x29 ; 00940250 6a29
+ callf ; 00940252 9affff0000
+ push ax ; 00940257 50
+ push ds ; 00940258 1e
+ push 0x3c ; 00940259 683c00
+ callf ; 0094025c 9affff0000
+ mov [bp + 0xffffffe8], ax ; 00940261 8946e8
+ mov [bp + 0xffffffea], dx ; 00940264 8956ea
+ or dx, ax ; 00940267 0bd0
+ jz L363 ; 00940269 7407
+ push L4 ; 0094026b 6a01
+ push L4 ; 0094026d 6a01
+ call far oword [bp + 0xffffffe8] ; 0094026f ff5ee8
+ lea ax, [bp + 0xffffffee] ; 00940272 8d46ee
+ push ss ; 00940275 16
+ push ax ; 00940276 50
+ push 0x0 ; 00940277 6a00
+ push 0x0 ; 00940279 6a00
+ push 0x0 ; 0094027b 6a00
+ callf ; 0094027d 9ac8000000
+ or ax, ax ; 00940282 0bc0
+ jz L364 ; 00940284 7428
+ lea ax, [bp + 0xffffffee] ; 00940286 8d46ee
+ push ss ; 00940289 16
+ push ax ; 0094028a 50
+ callf ; 0094028b 9affff0000
+ lea ax, [bp + 0xffffffee] ; 00940290 8d46ee
+ push ss ; 00940293 16
+ push ax ; 00940294 50
+ callf ; 00940295 9affff0000
+ lea ax, [bp + 0xffffffee] ; 0094029a 8d46ee
+ push ss ; 0094029d 16
+ push ax ; 0094029e 50
+ push 0x0 ; 0094029f 6a00
+ push 0x0 ; 009402a1 6a00
+ push 0x0 ; 009402a3 6a00
+ callf ; 009402a5 9affff0000
+ or ax, ax ; 009402aa 0bc0
+ jnz L120 ; 009402ac 75d8
+ o32 cmp dword [bp + 0xffffffe8], byte 0x0 ; 009402ae 66837ee800
+ jz L365 ; 009402b3 7407
+ push L4 ; 009402b5 6a01
+ push 0x0 ; 009402b7 6a00
+ call far oword [bp + 0xffffffe8] ; 009402b9 ff5ee8
+ mov ax, [bp + 0xfffffff2] ; 009402bc 8b46f2
+ leave ; 009402bf c9
+ retf 0x0a ; 009402c0 ca0a00
+ nop ; 009402c3 90
+ enter 0x72, 0x0 ; 009402c4 c8720000
+ mov ax, [bp + 0xe] ; 009402c8 8b460e
+ mov [0x2b0], ax ; 009402cb a3b002
+ push 0x200 ; 009402ce 680002
+ push 0x12c ; 009402d1 682c01
+ callf ; 009402d4 9a2806d401
+ push ds ; 009402d9 1e
+ push L84 ; 009402da 686802
+ push ds ; 009402dd 1e
+ push L82 ; 009402de 686a02
+ callf ; 009402e1 9a0000ffff
+ or ax, ax ; 009402e6 0bc0
+ jz L366 ; 009402e8 741d
+ push 0x0 ; 009402ea 6a00
+ push 0x0 ; 009402ec 6a00
+ push 0x7f00 ; 009402ee 68007f
+ callf ; 009402f1 9affff0000
+ mov [bp + 0xffffffb4], ax ; 009402f6 8946b4
+ push 0x0 ; 009402f9 6a00
+ callf ; 009402fb 9affff0000
+ mov [bp + 0xffffffd8], ax ; 00940300 8946d8
+ or ax, ax ; 00940303 0bc0
+ jnz L367 ; 00940305 7503
+ jmp L368 ; 00940307 e99802
+ push ax ; 0094030a 50
+ lea ax, [bp + 0xffffffb8] ; 0094030b 8d46b8
+ push ss ; 0094030e 16
+ push ax ; 0094030f 50
+ callf ; 00940310 9affff0000
+ mov ax, [bp + 0xffffffb8] ; 00940315 8b46b8
+ mov [0x23e], ax ; 00940318 a33e02
+ mov ax, [bp + 0xffffffc4] ; 0094031b 8b46c4
+ mov [0x23c], ax ; 0094031e a33c02
+
+L206:
+ push word [bp + 0xffffffd8] ; 00940321 ff76d8
+ push L59 ; 00940324 6a18
+ callf ; 00940326 9a5e010000
+ cmp ax, L310 ; 0094032b 3d0200
+ jnz L369 ; 0094032e 7506
+ mov word L36, L4 ; 00940330 c706f6010100
+ push word [bp + 0xffffffd8] ; 00940336 ff76d8
+ push 0x8 ; 00940339 6a08
+ callf ; 0094033b 9a6b010000
+ mov [0x24c], ax ; 00940340 a34c02
+ push word [bp + 0xffffffd8] ; 00940343 ff76d8
+ push 0xa ; 00940346 6a0a
+ callf ; 00940348 9affff0000
+ mov [0x24e], ax ; 0094034d a34e02
+ cmp ax, 0x12c ; 00940350 3d2c01
+ jge L370 ; 00940353 7d05
+ mov ax, L4 ; 00940355 b80100
+ jmp short L371 ; 00940358 eb02
+ xor ax, ax ; 0094035a 33c0
+ mov [0x38], ax ; 0094035c a33800
+ or ax, ax ; 0094035f 0bc0
+ jz L372 ; 00940361 740c
+ mov cx, L310 ; 00940363 b90200
+ mov ax, [0x26a] ; 00940366 a16a02
+ cwd ; 00940369 99
+ idiv cx, ax ; 0094036a f7f9
+ mov [0x26a], ax ; 0094036c a36a02
+ push 0x0 ; 0094036f 6a00
+ push word [bp + 0xffffffd8] ; 00940371 ff76d8
+ callf ; 00940374 9affff0000
+ cmp word L36, byte 0x0 ; 00940379 833ef60100
+ jz L373 ; 0094037e 7408
+ mov ax, 0xffff ; 00940380 b8ffff
+ mov dx, 0xff ; 00940383 baff00
+ jmp short L374 ; 00940386 eb05
+ mov ax, 0x8000 ; 00940388 b80080
+ xor dx, dx ; 0094038b 33d2
+ mov [0x2b2], ax ; 0094038d a3b202
+ mov L42, dx ; 00940390 8916b402
+ push dx ; 00940394 52
+ push ax ; 00940395 50
+ callf ; 00940396 9affff0000
+ mov [0x266], ax ; 0094039b a36602
+ callf ; 0094039e 9affff0000
+ push ax ; 009403a3 50
+ callf ; 009403a4 9a3201ffff
+ pop bx ; 009403a9 5b
+ push 0x26e ; 009403aa 686e02
+ push 0x64 ; 009403ad 6a64
+ callf ; 009403af 9a2806de01
+ push 0x250 ; 009403b4 685002
+ push 0x65 ; 009403b7 6a65
+ callf ; 009403b9 9a2806e901
+ lea ax, [bp + 0xffffff98] ; 009403be 8d4698
+ push ax ; 009403c1 50
+ push 0x67 ; 009403c2 6a67
+ callf ; 009403c4 9a2806ffff
+ lea ax, [bp + 0xffffff98] ; 009403c9 8d4698
+ push ss ; 009403cc 16
+ push ax ; 009403cd 50
+ callf ; 009403ce 9affff0000
+ mov [0x1f8], ax ; 009403d3 a3f801
+ mov word [bp + 0xffffffb2], 0x00 ; 009403d6 c746b20000
+ o32 mov eax, [bp + 0x8] ; 009403db 668b4608
+ mov dx, [bp + 0xa] ; 009403df 8b560a
+ o32 mov [bp + 0xffffffae], eax ; 009403e2 668946ae
+ mov es, dx ; 009403e6 8ec2
+ mov bx, ax ; 009403e8 8bd8
+ es cmp byte es:[bx], 0x0 ; 009403ea 26803f00
+ jz L375 ; 009403ee 7420
+ es cmp byte es:[bx], 0x2f ; 009403f0 26803f2f
+ jnz L376 ; 009403f4 7507
+ es cmp byte es:[bx + 0x1], 0x49 ; 009403f6 26807f0149
+ jz L377 ; 009403fb 740e
+ inc word [bp + 0xffffffae] ; 009403fd ff46ae
+ mov bx, [bp + 0xffffffae] ; 00940400 8b5eae
+ es cmp byte es:[bx], 0x0 ; 00940403 26803f00
+ jnz L378 ; 00940407 75e7
+ jmp short L375 ; 00940409 eb05
+ mov word [bp + 0xffffffb2], L4 ; 0094040b c746b20100
+ cmp word [bp + 0xc], byte 0x0 ; 00940410 837e0c00
+ jnz L379 ; 00940414 7556
+ mov word [bp + 0xffffffe6], 0x2008 ; 00940416 c746e60820
+ mov word [bp + 0xffffffe8], 0x40c ; 0094041b c746e80c04
+ mov word [bp + 0xffffffea], 0xffff ; 00940420 c746eaffff
+ o32 mov dword [bp + 0xffffffec], 0x0000 ; 00940425 66c746ec00000000
+ mov ax, [0x2b0] ; 0094042d a1b002
+ mov [bp + 0xfffffff0], ax ; 00940430 8946f0
+ push ax ; 00940433 50
+ push ds ; 00940434 1e
+ push L12 ; 00940435 684b00
+ callf ; 00940438 9affff0000
+ mov [bp + 0xfffffff2], ax ; 0094043d 8946f2
+ mov ax, [bp + 0xffffffb4] ; 00940440 8b46b4
+ mov [bp + 0xfffffff4], ax ; 00940443 8946f4
+ mov ax, [0x266] ; 00940446 a16602
+ mov [bp + 0xfffffff6], ax ; 00940449 8946f6
+ o32 mov dword [bp + 0xfffffff8], L4 ; 0094044c 66c746f801000000
+ mov word [bp + 0xfffffffc], 0x22 ; 00940454 c746fc2200
+ mov word [bp + 0xfffffffe], ds ; 00940459 8c5efe
+ lea ax, [bp + 0xffffffe6] ; 0094045c 8d46e6
+ push ss ; 0094045f 16
+ push ax ; 00940460 50
+ callf ; 00940461 9affff0000
+ or ax, ax ; 00940466 0bc0
+ je L368 ; 00940468 0f843601
+ mov ax, [0x268] ; 0094046c a16802
+ imul cx, ax, 0x7 ; 0094046f 6bc807
+ cwd ; 00940472 99
+ and dx, byte 0x7 ; 00940473 83e207
+ add ax, dx ; 00940476 03c2
+ sar ax, byte 0x3 ; 00940478 c1f803
+ add ax, 0x03 ; 0094047b 050300
+ mov [0x240], ax ; 0094047e a34002
+ shl ax, byte 0x3 ; 00940481 c1e003
+ add cx, ax ; 00940484 03c8
+ mov [bp + 0xffffff92], cx ; 00940486 894e92
+ mov ax, [0x26a] ; 00940489 a16a02
+ shl ax, L310 ; 0094048c c1e002
+ mov [bp + 0xffffff94], ax ; 0094048f 894694
+ o32 mov dword [bp + 0xffffff8e], 0x0000 ; 00940492 66c7468e00000000
+ lea ax, [bp + 0xffffff8e] ; 0094049a 8d468e
+ push ss ; 0094049d 16
+ push ax ; 0094049e 50
+ push 0xcf ; 0094049f 68cf00
+ push 0x0 ; 009404a2 6a00
+ push L4 ; 009404a4 6a01
+ push 0x0 ; 009404a6 6a00
+ push 0x200 ; 009404a8 680002
+ callf ; 009404ab 9affff0000
+ mov ax, [bp + 0xffffff8e] ; 009404b0 8b468e
+ sub [bp + 0xffffff92], ax ; 009404b3 294692
+ mov ax, [0x24e] ; 009404b6 a14e02
+ mov cx, [bp + 0xffffff90] ; 009404b9 8b4e90
+ sub [bp + 0xffffff94], cx ; 009404bc 294e94
+ cmp [bp + 0xffffff94], ax ; 009404bf 394694
+ jle L380 ; 009404c2 7e03
+ mov [bp + 0xffffff94], ax ; 009404c4 894694
+ push 0x0 ; 009404c7 6a00
+ push 0x200 ; 009404c9 680002
+ push ds ; 009404cc 1e
+ push 0x22 ; 009404cd 682200
+ push ds ; 009404d0 1e
+ push 0x26e ; 009404d1 686e02
+ cmp word [bp + 0xffffffb2], byte 0x0 ; 009404d4 837eb200
+ jz L381 ; 009404d8 7407
+ xor ax, ax ; 009404da 33c0
+ mov dx, 0x22cf ; 009404dc bacf22
+ jmp short L382 ; 009404df eb05
+ xor ax, ax ; 009404e1 33c0
+ mov dx, 0x2cf ; 009404e3 bacf02
+ push dx ; 009404e6 52
+ push ax ; 009404e7 50
+ push 0x8000 ; 009404e8 680080
+ push ax ; 009404eb 50
+ push word [bp + 0xffffff92] ; 009404ec ff7692
+ push word [bp + 0xffffff94] ; 009404ef ff7694
+ push ax ; 009404f2 50
+ push ax ; 009404f3 50
+ push word L51 ; 009404f4 ff36b002
+ push ax ; 009404f8 50
+ push ax ; 009404f9 50
+ callf ; 009404fa 9affff0000
+ or ax, ax ; 009404ff 0bc0
+ je L368 ; 00940501 0f849d00
+ lea ax, [bp + 0xffffffac] ; 00940505 8d46ac
+ push ax ; 00940508 50
+ push cs ; 00940509 0e
+ call L383 ; 0094050a e8d105
+ push 0x245 ; 0094050d 684502
+ push 0x85a ; 00940510 685a08
+ push word [bp + 0xe] ; 00940513 ff760e
+ callf ; 00940516 9affff0000
+ mov [0x1f2], ax ; 0094051b a3f201
+ mov L53, dx ; 0094051e 8916f401
+ mov ax, dx ; 00940522 8bc2
+ or ax, L54 ; 00940524 0b06f201
+ jz L384 ; 00940528 747d
+ push word L23 ; 0094052a ff36f001
+ o32 push 0x29a00fa ; 0094052e 6668fa009a02
+ push dx ; 00940534 52
+ push word L54 ; 00940535 ff36f201
+ callf ; 00940539 9affff0000
+ or ax, ax ; 0094053e 0bc0
+ jz L368 ; 00940540 7460
+ callf ; 00940542 9a24026f03
+ push word [bp + 0xffffffac] ; 00940547 ff76ac
+ callf ; 0094054a 9ac6000b05
+ push word L23 ; 0094054f ff36f001
+ push word [bp + 0x6] ; 00940553 ff7606
+ callf ; 00940556 9a4c000000
+ push word L23 ; 0094055b ff36f001
+ callf ; 0094055f 9affff0000
+ cmp word [bp + 0xc], L4 ; 00940564 837e0c01
+ sbb ax, ax ; 00940568 1bc0
+ neg ax ; 0094056a f7d8
+ push ax ; 0094056c 50
+ callf ; 0094056d 9a00009e03
+
+L22:
+ cmp word L1, byte 0x0 ; 00940572 833e2c0000
+ jz L385 ; 00940577 7405
+ callf ; 00940579 9a6600ffff
+ cmp word [bp + 0x6], byte 0x7 ; 0094057e 837e0607
+ jz L386 ; 00940582 7419
+ cmp word [bp + 0x6], byte 0x6 ; 00940584 837e0606
+ jz L386 ; 00940588 7413
+ push word L23 ; 0094058a ff36f001
+ o32 push 0x11103e8 ; 0094058e 6668e8031101
+ push 0x0 ; 00940594 6a00
+ push 0x0 ; 00940596 6a00
+ callf ; 00940598 9acb040000
+ mov ax, L4 ; 0094059d b80100
+ jmp short L387 ; 009405a0 eb07
+ callf ; 009405a2 9a1806f900
+ xor ax, ax ; 009405a7 33c0
+ leave ; 009405a9 c9
+ retf 0x0a ; 009405aa ca0a00
+ nop ; 009405ad 90
+ enter L345, 0x0 ; 009405ae c8200000
+ push word [bp + 0x6] ; 009405b2 ff7606
+ lea ax, [bp + 0xffffffe0] ; 009405b5 8d46e0
+ push ss ; 009405b8 16
+ push ax ; 009405b9 50
+ callf ; 009405ba 9affff0000
+ cmp word L59, byte 0x0 ; 009405bf 833e180000
+ jz L388 ; 009405c4 7412
+ push word L59 ; 009405c6 ff361800
+ push 0x7 ; 009405ca 6a07
+ lea ax, [bp + 0xffffffe0] ; 009405cc 8d46e0
+ push ax ; 009405cf 50
+ push 0x0 ; 009405d0 6a00
+ mov bx, L59 ; 009405d2 8b1e1800
+ call far oword [bx] ; 009405d6 ff1f
+ push word [bp + 0x6] ; 009405d8 ff7606
+ lea ax, [bp + 0xffffffe0] ; 009405db 8d46e0
+ push ss ; 009405de 16
+ push ax ; 009405df 50
+ callf ; 009405e0 9affff0000
+ leave ; 009405e5 c9
+ retf L310 ; 009405e6 ca0200
+ nop ; 009405e9 90
+ enter 0xd6, 0x0 ; 009405ea c8d60000
+ mov ax, [bp + 0xc] ; 009405ee 8b460c
+ dec ax ; 009405f1 48
+ je L389 ; 009405f2 0f84bf00
+ dec ax ; 009405f6 48
+ je L390 ; 009405f7 0f84c300
+ dec ax ; 009405fb 48
+ je L391 ; 009405fc 0f846a01
+ dec ax ; 00940600 48
+ dec ax ; 00940601 48
+ je L392 ; 00940602 0f84f400
+ dec ax ; 00940606 48
+ je L393 ; 00940607 0f846701
+ dec ax ; 0094060b 48
+ je L394 ; 0094060c 0f848701
+ dec ax ; 00940610 48
+ je L395 ; 00940611 0f846f01
+ sub ax, 0x07 ; 00940615 2d0700
+ je L396 ; 00940618 0f848901
+ dec ax ; 0094061c 48
+ je L46 ; 0094061d 0f849901
+ sub ax, 0xf0 ; 00940621 2df000
+ je L150 ; 00940624 0f84b401
+ sub ax, 0x11 ; 00940628 2d1100
+ je L397 ; 0094062b 0f84c101
+ sub ax, 0x05 ; 0094062f 2d0500
+ je L398 ; 00940632 0f845302
+ sub ax, 0x09 ; 00940636 2d0900
+ je L399 ; 00940639 0f84dc02
+ sub ax, 0xe1 ; 0094063d 2de100
+ je L400 ; 00940640 0f840303
+ dec ax ; 00940644 48
+ je L401 ; 00940645 0f840f03
+ dec ax ; 00940649 48
+ je L55 ; 0094064a 0f842303
+ dec ax ; 0094064e 48
+ je L402 ; 0094064f 0f843403
+ mov ax, [0x1f8] ; 00940653 a1f801
+ cmp [bp + 0xc], ax ; 00940656 39460c
+ jne L403 ; 00940659 0f855403
+ mov ax, [bp + 0xa] ; 0094065d 8b460a
+ dec ax ; 00940660 48
+ jz L404 ; 00940661 7409
+ dec ax ; 00940663 48
+ jz L405 ; 00940664 7410
+ dec ax ; 00940666 48
+ jz L406 ; 00940667 7431
+ jmp L403 ; 00940669 e94503
+ mov ax, [0x268] ; 0094066c a16802
+ mov dx, L82 ; 0094066f 8b166a02
+ jmp L407 ; 00940673 e94b03
+ les bx, ; 00940676 c45e0626ff3726
+ push word [bx + 0x2] ; 0094067d ff7702
+ es push word es:[bx + 0x4] ; 00940680 26ff7704
+ es push word es:[bx + 0x6] ; 00940684 26ff7706
+ es push word es:[bx + 0x8] ; 00940688 26ff7708
+ o32 push dword es:[bx + 0xa] ; 0094068c 6626ff770a
+ callf ; 00940691 9a5a031005
+ cwd ; 00940696 99
+ jmp L407 ; 00940697 e92703
+ push word L23 ; 0094069a ff36f001
+ o32 push 0x112f060 ; 0094069e 666860f01201
+ push 0x0 ; 009406a4 6a00
+ push 0x0 ; 009406a6 6a00
+ callf ; 009406a8 9affff0000
+ mov ax, L4 ; 009406ad b80100
+ xor dx, dx ; 009406b0 33d2
+ jmp L407 ; 009406b2 e90c03
+ mov ax, [bp + 0xe] ; 009406b5 8b460e
+ mov [0x1f0], ax ; 009406b8 a3f001
+ jmp L403 ; 009406bb e9f302
+ push word L23 ; 009406be ff36f001
+ push 0x29a ; 009406c2 689a02
+ callf ; 009406c5 9affff0000
+ o32 push dword L54 ; 009406ca 66ff36f201
+ callf ; 009406cf 9affff0000
+ push word L59 ; 009406d4 ff361800
+ push L4 ; 009406d8 6a01
+ push 0x0 ; 009406da 6a00
+ push 0x0 ; 009406dc 6a00
+ mov bx, L59 ; 009406de 8b1e1800
+ call far oword [bx] ; 009406e2 ff1f
+ push L4 ; 009406e4 6a01
+ callf ; 009406e6 9ac600ffff
+ callf ; 009406eb 9a78080601
+ push 0x0 ; 009406f0 6a00
+ callf ; 009406f2 9affff0000
+ jmp L403 ; 009406f7 e9b702
+ push word [bp + 0xe] ; 009406fa ff760e
+ callf ; 009406fd 9a3d000000
+ mov [0x14], ax ; 00940702 a31400
+ push word [bp + 0xe] ; 00940705 ff760e
+ push ds ; 00940708 1e
+ push 0x244 ; 00940709 684402
+ callf ; 0094070c 9affff0000
+ imul ax, L84, 0x7 ; 00940711 6b06680207
+ sub ax, [bp + 0x6] ; 00940716 2b4606
+ neg ax ; 00940719 f7d8
+ cwd ; 0094071b 99
+ and dx, byte 0x7 ; 0094071c 83e207
+ add ax, dx ; 0094071f 03c2
+ sar ax, byte 0x3 ; 00940721 c1f803
+ mov [bp + 0xffffff92], ax ; 00940724 894692
+ mov ax, [0x268] ; 00940727 a16802
+ cwd ; 0094072a 99
+ and dx, byte 0x7 ; 0094072b 83e207
+ add ax, dx ; 0094072e 03c2
+ sar ax, byte 0x3 ; 00940730 c1f803
+ add ax, 0x03 ; 00940733 050300
+ mov [bp + 0xffffff90], ax ; 00940736 894690
+ cmp [bp + 0xffffff92], ax ; 00940739 394692
+ jge L408 ; 0094073c 7d0e
+ mov ax, [0x240] ; 0094073e a14002
+ cmp [bp + 0xffffff90], ax ; 00940741 394690
+ jz L408 ; 00940744 7406
+ mov ax, [bp + 0xffffff90] ; 00940746 8b4690
+ mov [bp + 0xffffff92], ax ; 00940749 894692
+ mov ax, [bp + 0xffffff92] ; 0094074c 8b4692
+ cmp [bp + 0xffffff90], ax ; 0094074f 394690
+ jg L391 ; 00940752 7f16
+ mov [0x240], ax ; 00940754 a34002
+ callf ; 00940757 9aa001ffff
+ push word [bp + 0xe] ; 0094075c ff760e
+ push 0x0 ; 0094075f 6a00
+ push 0x0 ; 00940761 6a00
+ push L4 ; 00940763 6a01
+ callf ; 00940765 9affff0000
+ callf ; 0094076a 9aca019203
+ jmp L403 ; 0094076f e93f02
+ cmp word [bp + 0xa], byte 0x0 ; 00940772 837e0a00
+ je L403 ; 00940776 0f843702
+ push word [bp + 0xe] ; 0094077a ff760e
+ push cs ; 0094077d 0e
+ call L409 ; 0094077e e82dfe
+ jmp L403 ; 00940781 e92d02
+ mov bx, L59 ; 00940784 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940788 837f2600
+ jz L394 ; 0094078c 7409
+ push bx ; 0094078e 53
+ push 0x4 ; 0094078f 6a04
+ push 0x0 ; 00940791 6a00
+ push L4 ; 00940793 6a01
+ call far oword [bx] ; 00940795 ff1f
+ cmp word [bp + 0xc], byte 0x7 ; 00940797 837e0c07
+ jne L410 ; 0094079b 0f850a02
+ mov ax, L4 ; 0094079f b80100
+ jmp L411 ; 009407a2 e90602
+ cmp word L178, byte 0x0 ; 009407a5 833e140000
+ jne L403 ; 009407aa 0f850302
+ push word [bp + 0xe] ; 009407ae ff760e
+ push cs ; 009407b1 0e
+ call L409 ; 009407b2 e8f9fd
+ xor ax, ax ; 009407b5 33c0
+ jmp L412 ; 009407b7 e9f6fe
+ lea ax, [bp + 0xffffff94] ; 009407ba 8d4694
+ push ax ; 009407bd 50
+ push 0x69 ; 009407be 6a69
+ callf ; 009407c0 9a2806c703
+ push word L23 ; 009407c5 ff36f001
+ lea ax, [bp + 0xffffff94] ; 009407c9 8d4694
+ push ss ; 009407cc 16
+ push ax ; 009407cd 50
+ push L310 ; 009407ce 6a02
+ push 0x0 ; 009407d0 6a00
+ push 0x0 ; 009407d2 6a00
+ callf ; 009407d4 9affff0000
+ jmp L403 ; 009407d9 e9d501
+ push word L59 ; 009407dc ff361800
+ push L310 ; 009407e0 6a02
+ push word [bp + 0xa] ; 009407e2 ff760a
+ push 0x0 ; 009407e5 6a00
+ mov bx, L59 ; 009407e7 8b1e1800
+ call far oword [bx] ; 009407eb ff1f
+ jmp L403 ; 009407ed e9c101
+ mov ax, [bp + 0xa] ; 009407f0 8b460a
+ inc ax ; 009407f3 40
+ jz L413 ; 009407f4 7419
+ sub ax, 0x3e9 ; 009407f6 2de903
+ jz L414 ; 009407f9 741e
+ dec ax ; 009407fb 48
+ jz L415 ; 009407fc 7426
+ dec ax ; 009407fe 48
+ jz L234 ; 009407ff 742d
+ dec ax ; 00940801 48
+ jz L47 ; 00940802 7432
+ dec ax ; 00940804 48
+ jz L416 ; 00940805 7437
+ sub ax, 0x3e4 ; 00940807 2de403
+ jz L417 ; 0094080a 7447
+ jmp L403 ; 0094080c e9a201
+ push word [bp + 0xa] ; 0094080f ff760a
+ push cs ; 00940812 0e
+ call L418 ; 00940813 e89402
+ jmp L403 ; 00940816 e99801
+ push L4 ; 00940819 6a01
+ push 0x0 ; 0094081b 6a00
+ push cs ; 0094081d 0e
+ call L419 ; 0094081e e85902
+ jmp L403 ; 00940821 e98d01
+ push word L59 ; 00940824 ff361800
+ push 0x9 ; 00940828 6a09
+ push 0x0 ; 0094082a 6a00
+ jmp short L252 ; 0094082c ebb7
+ callf ; 0094082e 9a18045b06
+ jmp L403 ; 00940833 e97b01
+ callf ; 00940836 9af801ffff
+ jmp L403 ; 0094083b e97301
+ push word [bp + 0xe] ; 0094083e ff760e
+ o32 push 0x112f060 ; 00940841 666860f01201
+ push 0x0 ; 00940847 6a00
+ push 0x0 ; 00940849 6a00
+ callf ; 0094084b 9abb030000
+ jmp L403 ; 00940850 e95e01
+ push word L51 ; 00940853 ff36b002
+ push 0x6c ; 00940857 6a6c
+ lea ax, [bp + 0xffffff2c] ; 00940859 8d862cff
+ push ss ; 0094085d 16
+ push ax ; 0094085e 50
+ push 0x64 ; 0094085f 6a64
+ callf ; 00940861 9affff0000
+ push word [bp + 0xe] ; 00940866 ff760e
+ push ds ; 00940869 1e
+ push 0x26e ; 0094086a 686e02
+ lea ax, [bp + 0xffffff2c] ; 0094086d 8d862cff
+ push ss ; 00940871 16
+ push ax ; 00940872 50
+ push word L51 ; 00940873 ff36b002
+ push ds ; 00940877 1e
+ push 0x4f ; 00940878 684f00
+ callf ; 0094087b 9a5b020000
+ push ax ; 00940880 50
+ callf ; 00940881 9affff0000
+ jmp L403 ; 00940886 e92801
+ push word [bp + 0xe] ; 00940889 ff760e
+ callf ; 0094088c 9affff0000
+ mov [bp + 0xfffffffe], ax ; 00940891 8946fe
+ mov bx, L59 ; 00940894 8b1e1800
+ cmp word [bx + 0x4], byte 0x0 ; 00940898 837f0400
+ jz L420 ; 0094089c 740e
+ cmp word [bx + 0x2c], byte 0xff ; 0094089e 837f2cff
+ jnz L420 ; 009408a2 7508
+ mov word [bp + 0xffffff2a], 0x00 ; 009408a4 c7862aff0000
+ jmp short L421 ; 009408aa eb06
+ mov word [bp + 0xffffff2a], 0x03 ; 009408ac c7862aff0300
+ push ax ; 009408b2 50
+ push 0x3e9 ; 009408b3 68e903
+ push word [bp + 0xffffff2a] ; 009408b6 ffb62aff
+ callf ; 009408ba 9afa060000
+ push word [bp + 0xfffffffe] ; 009408bf ff76fe
+ push 0x3e8 ; 009408c2 68e803
+ mov bx, L59 ; 009408c5 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 009408c9 837f2cff
+ jz L422 ; 009408cd 7405
+ mov ax, 0x03 ; 009408cf b80300
+ jmp short L423 ; 009408d2 eb02
+ xor ax, ax ; 009408d4 33c0
+ push ax ; 009408d6 50
+ callf ; 009408d7 9a17070000
+ push word [bp + 0xfffffffe] ; 009408dc ff76fe
+ push L91 ; 009408df 68ea03
+ mov bx, L59 ; 009408e2 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 009408e6 837f2cff
+ jz L424 ; 009408ea 7405
+ mov ax, 0x03 ; 009408ec b80300
+ jmp short L156 ; 009408ef eb02
+ xor ax, ax ; 009408f1 33c0
+ push ax ; 009408f3 50
+ callf ; 009408f4 9a34070000
+ push word [bp + 0xfffffffe] ; 009408f9 ff76fe
+ push 0x7d0 ; 009408fc 68d007
+ mov bx, L59 ; 009408ff 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 00940903 837f2cff
+ jz L425 ; 00940907 7405
+ mov ax, 0x03 ; 00940909 b80300
+ jmp short L239 ; 0094090c eb02
+ xor ax, ax ; 0094090e 33c0
+ push ax ; 00940910 50
+ callf ; 00940911 9affff0000
+ jmp L403 ; 00940916 e99800
+ cmp word [bp + 0xa], byte 0x0 ; 00940919 837e0a00
+ jz L426 ; 0094091d 7411
+ o32 cmp dword [bp + 0x6], 0xffff ; 0094091f 66817e06ffff0000
+ jz L426 ; 00940927 7407
+ test word [bp + 0x6], 0x2810 ; 00940929 f746061028
+ jz L427 ; 0094092e 740d
+ mov word [bp + 0xa], 0x1fff ; 00940930 c7460aff1f
+ o32 mov dword [bp + 0x6], 0x0000 ; 00940935 66c7460600000000
+ push word [bp + 0xa] ; 0094093d ff760a
+ callf ; 00940940 9aae028f05
+ jmp short L403 ; 00940945 eb6a
+ mov word [bp + 0xfffffff8], 0x05 ; 00940947 c746f80500
+ mov bx, L59 ; 0094094c 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940950 837f2600
+ jz L403 ; 00940954 745b
+ jmp short L428 ; 00940956 eb3e
+ push word [bp + 0xe] ; 00940958 ff760e
+ callf ; 0094095b 9affff0000
+ mov bx, L59 ; 00940960 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940964 837f2600
+ jnz L403 ; 00940968 7547
+ mov word [bp + 0xfffffff8], 0x03 ; 0094096a c746f80300
+ jmp short L428 ; 0094096f eb25
+ callf ; 00940971 9affff0000
+ mov word [bp + 0xfffffff8], 0x04 ; 00940976 c746f80400
+ mov bx, L59 ; 0094097b 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 0094097f 837f2600
+ jnz L428 ; 00940983 7511
+ jmp short L403 ; 00940985 eb2a
+ mov word [bp + 0xfffffff8], 0x06 ; 00940987 c746f80600
+ mov bx, L59 ; 0094098c 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940990 837f2600
+ jnz L403 ; 00940994 751b
+ o32 mov eax, [bp + 0x6] ; 00940996 668b4606
+ o32 mov [bp + 0xfffffffa], eax ; 0094099a 668946fa
+ push bx ; 0094099e 53
+ push word [bp + 0xfffffff8] ; 0094099f ff76f8
+ lea ax, [bp + 0xfffffffa] ; 009409a2 8d46fa
+ push ax ; 009409a5 50
+ jmp L252 ; 009409a6 e93cfe
+ xor ax, ax ; 009409a9 33c0
+ push ax ; 009409ab 50
+ callf ; 009409ac 9affff0000
+ o32 push dword [bp + 0xc] ; 009409b1 66ff760c
+ o32 push dword [bp + 0x8] ; 009409b5 66ff7608
+ push word [bp + 0x6] ; 009409b9 ff7606
+ callf ; 009409bc 9affff0000
+ leave ; 009409c1 c9
+ retf 0x0a ; 009409c2 ca0a00
+ nop ; 009409c5 90
+ enter L310, 0x0 ; 009409c6 c8020000
+ mov ax, [0x1a] ; 009409ca a11a00
+ mov [bp + 0xfffffffe], ax ; 009409cd 8946fe
+ mov ax, [bp + 0xa] ; 009409d0 8b460a
+ mov [0x1a], ax ; 009409d3 a31a00
+ mov ax, [bp + 0x8] ; 009409d6 8b4608
+ mov [0x1e], ax ; 009409d9 a31e00
+ mov ax, [bp + 0x6] ; 009409dc 8b4606
+ mov [0x20], ax ; 009409df a32000
+ mov ax, [bp + 0xfffffffe] ; 009409e2 8b46fe
+ leave ; 009409e5 c9
+ retf 0x06 ; 009409e6 ca0600
+ nop ; 009409e9 90
+ cmp word L279, byte 0x0 ; 009409ea 833e1a0000
+ jz L429 ; 009409ef 7408
+ inc word L281 ; 009409f1 ff061c00
+ mov ax, L4 ; 009409f5 b80100
+ retf ; 009409f8 cb
+ push word L23 ; 009409f9 ff36f001
+ callf ; 009409fd 9a1e010000
+ or ax, ax ; 00940a02 0bc0
+ jz L430 ; 00940a04 740f
+ push ax ; 00940a06 50
+ push 0x0 ; 00940a07 6a00
+ push 0x0 ; 00940a09 6a00
+ push cs ; 00940a0b 0e
+ call L431 ; 00940a0c e8b7ff
+ mov ax, L4 ; 00940a0f b80100
+ mov [0x1c], ax ; 00940a12 a31c00
+ retf ; 00940a15 cb
+ cmp word L279, byte 0x0 ; 00940a16 833e1a0000
+ jz L79 ; 00940a1b 7419
+ dec word L281 ; 00940a1d ff0e1c00
+ jnz L79 ; 00940a21 7513
+ push word L23 ; 00940a23 ff36f001
+ push word L279 ; 00940a27 ff361a00
+ callf ; 00940a2b 9a97010000
+ mov word L279, 0x00 ; 00940a30 c7061a000000
+ retf ; 00940a36 cb
+ nop ; 00940a37 90
+ cmp word L59, byte 0x0 ; 00940a38 833e180000
+ jz L271 ; 00940a3d 7410
+ push word L59 ; 00940a3f ff361800
+ push 0x11 ; 00940a43 6a11
+ push 0x0 ; 00940a45 6a00
+ push 0x0 ; 00940a47 6a00
+ mov bx, L59 ; 00940a49 8b1e1800
+ call far oword [bx] ; 00940a4d ff1f
+ mov ax, L4 ; 00940a4f b80100
+ retf 0x0a ; 00940a52 ca0a00
+ nop ; 00940a55 90
+ push bp ; 00940a56 55
+ mov bp, sp ; 00940a57 8bec
+ mov ax, [0x16] ; 00940a59 a11600
+ cmp [bp + 0x6], ax ; 00940a5c 394606
+ jz L432 ; 00940a5f 7415
+ mov ax, [bp + 0x6] ; 00940a61 8b4606
+ mov [0x16], ax ; 00940a64 a31600
+ push word L23 ; 00940a67 ff36f001
+ push 0x0 ; 00940a6b 6a00
+ push 0x0 ; 00940a6d 6a00
+ push L4 ; 00940a6f 6a01
+ callf ; 00940a71 9a88050000
+ leave ; 00940a76 c9
+ retf L310 ; 00940a77 ca0200
+ push bp ; 00940a7a 55
+ mov bp, sp ; 00940a7b 8bec
+ cmp word [bp + 0x8], byte 0x0 ; 00940a7d 837e0800
+ jz L433 ; 00940a81 7412
+ callf ; 00940a83 9ac1010000
+ and ah, 0x7f ; 00940a88 80e47f
+ mov [0x242], ax ; 00940a8b a34202
+ push ax ; 00940a8e 50
+ callf ; 00940a8f 9a3201c901
+ pop bx ; 00940a94 5b
+ push word L59 ; 00940a95 ff361800
+ push 0x8 ; 00940a99 6a08
+ push word [bp + 0x6] ; 00940a9b ff7606
+ push 0x0 ; 00940a9e 6a00
+ mov bx, L59 ; 00940aa0 8b1e1800
+ call far oword [bx] ; 00940aa4 ff1f
+ leave ; 00940aa6 c9
+ retf 0x04 ; 00940aa7 ca0400
+ enter 0x66, 0x0 ; 00940aaa c8660000
+ lea ax, [bp + 0xffffff9c] ; 00940aae 8d469c
+ push ax ; 00940ab1 50
+ push 0x69 ; 00940ab2 6a69
+ callf ; 00940ab4 9a2806f908
+ push word L23 ; 00940ab9 ff36f001
+ lea ax, [bp + 0xffffff9c] ; 00940abd 8d469c
+ push ss ; 00940ac0 16
+ push ax ; 00940ac1 50
+ push 0xb ; 00940ac2 6a0b
+ push 0x0 ; 00940ac4 6a00
+ push 0x0 ; 00940ac6 6a00
+ callf ; 00940ac8 9af7050000
+ or ax, ax ; 00940acd 0bc0
+ jnz L434 ; 00940acf 7508
+ push 0x12d ; 00940ad1 682d01
+ callf ; 00940ad4 9af8048109
+ leave ; 00940ad9 c9
+ retf L310 ; 00940ada ca0200
+ nop ; 00940add 90
+ enter 0x86, 0x0 ; 00940ade c8860000
+ mov word [bp + 0xffffff7e], 0x00 ; 00940ae2 c7867eff0000
+ mov al, [0xff0000] ; 00940ae8 a0
+ sub al, 0x0 ; 00940ae9 2c00
+ and ax, L4 ; 00940aeb 250100
+ mov [bp + 0xffffff7e], ax ; 00940aee 89867eff
+ mov cx, ax ; 00940af2 8bc8
+ mov dx, L289 ; 00940af4 8b162e00
+ add dx, dx ; 00940af8 03d2
+ xor al, dl ; 00940afa 32c2
+ and ax, L310 ; 00940afc 250200
+ xor cx, ax ; 00940aff 33c8
+ mov [bp + 0xffffff7e], cx ; 00940b01 898e7eff
+ mov ax, cx ; 00940b05 8bc1
+ mov dx, L290 ; 00940b07 8b163600
+ shl dx, L310 ; 00940b0b c1e202
+ xor cl, dl ; 00940b0e 32ca
+ and cx, byte 0x4 ; 00940b10 83e104
+ xor ax, cx ; 00940b13 33c1
+ mov [bp + 0xffffff7e], ax ; 00940b15 89867eff
+ mov [bp + 0xffffff7a], ax ; 00940b19 89867aff
+ cmp word L291, byte 0x3 ; 00940b1d 833e340003
+ jnz L435 ; 00940b22 7505
+ mov ax, L4 ; 00940b24 b80100
+ jmp short L436 ; 00940b27 eb02
+ xor ax, ax ; 00940b29 33c0
+ shl ax, byte 0x3 ; 00940b2b c1e003
+ mov cl, [bp + 0xffffff7a] ; 00940b2e 8a8e7aff
+ xor cl, al ; 00940b32 32c8
+ and cx, byte 0x8 ; 00940b34 83e108
+ xor cx, [bp + 0xffffff7a] ; 00940b37 338e7aff
+ mov [bp + 0xffffff7e], cx ; 00940b3b 898e7eff
+ mov ax, [0x30] ; 00940b3f a13000
+ shl ax, byte 0x6 ; 00940b42 c1e006
+ xor cl, al ; 00940b45 32c8
+ and cx, byte 0x40 ; 00940b47 83e140
+ xor [bp + 0xffffff7e], cx ; 00940b4a 318e7eff
+ push 0x63 ; 00940b4e 6a63
+ push 0xc9 ; 00940b50 68c900
+ and byte [bp + 0xffffff7e], 0xcf ; 00940b53 80a67effcf
+ push word [bp + 0xffffff7e] ; 00940b58 ffb67eff
+ callf ; 00940b5c 9ad806030a
+ mov [bp + 0xffffff7e], ax ; 00940b61 89867eff
+ and ax, L4 ; 00940b65 250100
+ mov [0x2c], ax ; 00940b68 a32c00
+ mov al, [bp + 0xffffff7e] ; 00940b6b 8a867eff
+ and ax, L310 ; 00940b6f 250200
+ shr al, 1 ; 00940b72 d0e8
+ mov [0x2e], ax ; 00940b74 a32e00
+ mov al, [bp + 0xffffff7e] ; 00940b77 8a867eff
+ and ax, 0x04 ; 00940b7b 250400
+ mov bx, [bp + 0x6] ; 00940b7e 8b5e06
+ shr al, L310 ; 00940b81 c0e802
+ mov [bx], ax ; 00940b84 8907
+ mov al, [bp + 0xffffff7e] ; 00940b86 8a867eff
+ and ax, 0x08 ; 00940b8a 250800
+ cmp ax, L4 ; 00940b8d 3d0100
+ sbb ax, ax ; 00940b90 1bc0
+ and al, 0xfe ; 00940b92 24fe
+ add ax, 0x03 ; 00940b94 050300
+ mov [0x34], ax ; 00940b97 a33400
+ mov al, [bp + 0xffffff7e] ; 00940b9a 8a867eff
+ and ax, 0x40 ; 00940b9e 254000
+ shr al, 0x6 ; 00940ba1 c0e806
+ mov [0x30], ax ; 00940ba4 a33000
+ mov al, [bp + 0xffffff7e] ; 00940ba7 8a867eff
+ and ax, 0x30 ; 00940bab 253000
+ shr al, 0x4 ; 00940bae c0e804
+ dec ax ; 00940bb1 48
+ jz L437 ; 00940bb2 740b
+ dec ax ; 00940bb4 48
+ jz L438 ; 00940bb5 7410
+ mov word L296, 0x12e ; 00940bb7 c70632002e01
+ jmp short L439 ; 00940bbd eb0e
+ mov word L296, L354 ; 00940bbf c70632002f01
+ jmp short L439 ; 00940bc5 eb06
+ mov word L296, 0x130 ; 00940bc7 c70632003001
+ push 0x63 ; 00940bcd 6a63
+ push 0xc8 ; 00940bcf 68c800
+ callf ; 00940bd2 9a4a01b408
+ mov cx, 0x0c ; 00940bd7 b90c00
+ cwd ; 00940bda 99
+ idiv cx, ax ; 00940bdb f7f9
+ push dx ; 00940bdd 52
+ callf ; 00940bde 9ad806100a
+ add ax, 0x35 ; 00940be3 053500
+ push ax ; 00940be6 50
+ push L290 ; 00940be7 6a36
+ push 0x41 ; 00940be9 6a41
+ callf ; 00940beb 9afc05220a
+ push ax ; 00940bf0 50
+ push cs ; 00940bf1 0e
+ call L440 ; 00940bf2 e861fe
+ o32 push 0xcd00cb ; 00940bf5 6668cb00cd00
+ push 0x0 ; 00940bfb 6a00
+ callf ; 00940bfd 9ad806380a
+ mov [0x264], ax ; 00940c02 a36402
+ o32 push 0xcd00cc ; 00940c05 6668cc00cd00
+ push 0x1fa ; 00940c0b 68fa01
+ push 0x53 ; 00940c0e 685300
+ push 0x5 ; 00940c11 6a05
+ callf ; 00940c13 9a9806ef0a
+ leave ; 00940c18 c9
+ retf L310 ; 00940c19 ca0200
+ enter 0x84, 0x0 ; 00940c1c c8840000
+ test byte [bp + 0x6], L4 ; 00940c20 f6460601
+ je L441 ; 00940c24 0f84a700
+ mov word [bp + 0xffffff7e], 0x00 ; 00940c28 c7867eff0000
+ mov al, [0x1ff0000] ; 00940c2e a0
+ sub al, 0x0 ; 00940c2f 2c00
+ and ax, L4 ; 00940c31 250100
+ mov [bp + 0xffffff7e], ax ; 00940c34 89867eff
+ mov cx, ax ; 00940c38 8bc8
+ mov dx, L289 ; 00940c3a 8b162e00
+ add dx, dx ; 00940c3e 03d2
+ xor al, dl ; 00940c40 32c2
+ and ax, L310 ; 00940c42 250200
+ xor cx, ax ; 00940c45 33c8
+ mov [bp + 0xffffff7e], cx ; 00940c47 898e7eff
+ mov ax, cx ; 00940c4b 8bc1
+ mov dx, L290 ; 00940c4d 8b163600
+ shl dx, L310 ; 00940c51 c1e202
+ xor cl, dl ; 00940c54 32ca
+ and cx, byte 0x4 ; 00940c56 83e104
+ xor ax, cx ; 00940c59 33c1
+ mov [bp + 0xffffff7e], ax ; 00940c5b 89867eff
+ mov [bp + 0xffffff7c], ax ; 00940c5f 89867cff
+ cmp word L291, byte 0x3 ; 00940c63 833e340003
+ jnz L442 ; 00940c68 7505
+ mov ax, L4 ; 00940c6a b80100
+ jmp short L443 ; 00940c6d eb02
+ xor ax, ax ; 00940c6f 33c0
+ shl ax, byte 0x3 ; 00940c71 c1e003
+ mov cl, [bp + 0xffffff7c] ; 00940c74 8a8e7cff
+ xor cl, al ; 00940c78 32c8
+ and cx, byte 0x8 ; 00940c7a 83e108
+ xor cx, [bp + 0xffffff7c] ; 00940c7d 338e7cff
+ mov [bp + 0xffffff7e], cx ; 00940c81 898e7eff
+ mov ax, [0x30] ; 00940c85 a13000
+ shl ax, byte 0x6 ; 00940c88 c1e006
+ xor cl, al ; 00940c8b 32c8
+ and cx, byte 0x40 ; 00940c8d 83e140
+ xor [bp + 0xffffff7e], cx ; 00940c90 318e7eff
+ mov ax, [0x32] ; 00940c94 a13200
+ sub ax, 0x12e ; 00940c97 2d2e01
+ jz L293 ; 00940c9a 7408
+ dec ax ; 00940c9c 48
+ jz L444 ; 00940c9d 740c
+ dec ax ; 00940c9f 48
+ jz L445 ; 00940ca0 7413
+ jmp short L446 ; 00940ca2 eb1d
+ and byte [bp + 0xffffff7e], 0xcf ; 00940ca4 80a67effcf
+ jmp short L446 ; 00940ca9 eb16
+ mov ax, [bp + 0xffffff7e] ; 00940cab 8b867eff
+ and al, 0xdf ; 00940caf 24df
+ or al, 0x10 ; 00940cb1 0c10
+ jmp short L447 ; 00940cb3 eb08
+ mov ax, [bp + 0xffffff7e] ; 00940cb5 8b867eff
+ and al, 0xef ; 00940cb9 24ef
+ or al, L345 ; 00940cbb 0c20
+ mov [bp + 0xffffff7e], ax ; 00940cbd 89867eff
+ push 0x63 ; 00940cc1 6a63
+ push 0xc9 ; 00940cc3 68c900
+ push word [bp + 0xffffff7e] ; 00940cc6 ffb67eff
+ callf ; 00940cca 9a7806060b
+ test byte [bp + 0x6], 0x4 ; 00940ccf f6460604
+ jz L448 ; 00940cd3 7411
+ push 0x63 ; 00940cd5 6a63
+ push 0xc8 ; 00940cd7 68c800
+ mov ax, [0x16] ; 00940cda a11600
+ sub ax, 0x35 ; 00940cdd 2d3500
+ push ax ; 00940ce0 50
+ callf ; 00940ce1 9a7806e505
+ leave ; 00940ce6 c9
+ retf L310 ; 00940ce7 ca0200
+ xor ax, [bx + si] ; 00940cea 3300
+ add ax, [bx + di] ; 00940cec 0301
+ scasb ; 00940cee ae
+ add [bp + si], al ; 00940cef 0002
+ add [bx + di + 0], dh ; 00940cf1 007100
+ add ax, [bx + di] ; 00940cf4 0301
+ mov ax, 0x200 ; 00940cf6 b80002
+ add [bp + si + 0], dh ; 00940cf9 007200
+ add al, [bx + si] ; 00940cfc 0200
+ xor [bp + di], al ; 00940cfe 3003
+ add [bx + si], ax ; 00940d00 0100
+ add [bx + si], al ; 00940d02 0000
+ add ax, [bx + di] ; 00940d04 0301
+ ill_f1 ; 00940d06 f1
+ add [bp + si], ax ; 00940d07 0102
+ add [bp + 0], dh ; 00940d09 007600
+ add al, [bx + si] ; 00940d0c 0200
+ ill_d9 ; 00940d0e d908
+ add al, [bx + si] ; 00940d10 0200
+ add [bx + si], al ; 00940d12 0000
+ add al, [bx + si] ; 00940d14 0200
+ a16 add ax, [ebx] ; 00940d16 670303
+ add [bx + si], al ; 00940d19 0000
+ add [bp + di], al ; 00940d1b 0003
+ add [bp + si + 0x203], ax ; 00940d1d 01820302
+ add [si + 0], bh ; 00940d21 007c00
+ add ax, [bx + di] ; 00940d24 0301
+ xchg ax, sp ; 00940d26 94
+ or [bp + si], al ; 00940d27 0802
+ add [di + 0], bh ; 00940d29 007d00
+ add al, [bx + si] ; 00940d2c 0200
+ jl L449 ; 00940d2e 7c05
+ add al, 0x0 ; 00940d30 0400
+ add [bx + si], al ; 00940d32 0000
+ add ax, [bx + di] ; 00940d34 0301
+ adc ax, 0x205 ; 00940d36 150502
+ add L89, al ; 00940d39 00060003
+ add [si + 0x3], bx ; 00940d3d 015c03
+ add al, [bx + si] ; 00940d40 0200
+ or al, [bx + si] ; 00940d42 0a00
+ add ax, [bx + di] ; 00940d44 0301
+ call L450 ; 00940d46 e80402
+ add [si], cl ; 00940d49 000c
+ add [bp + si], al ; 00940d4b 0002
+ add [bp + di + 0x6], dl ; 00940d4d 005306
+ pop es ; 00940d50 07
+ add [bx + si], al ; 00940d51 0000
+ add [bp + di], al ; 00940d53 0003
+ add [bp + 0x208], sp ; 00940d55 01a60802
+ add [bx], cl ; 00940d59 000f
+ add [bp + si], al ; 00940d5b 0002
+ add bh, dh ; 00940d5d 00f7
+ or [bx + si], cx ; 00940d5f 0908
+ add [bx + si], al ; 00940d61 0000
+ add [bp + di], al ; 00940d63 0003
+ add [bp + 0x7], di ; 00940d65 017e07
+ add al, [bx + si] ; 00940d68 0200
+ adc al, [bx + si] ; 00940d6a 1200
+ add ax, [bx + di] ; 00940d6c 0301
+ xchg ax, sp ; 00940d6e 94
+ pop es ; 00940d6f 07
+ add al, [bx + si] ; 00940d70 0200
+ adc ax, [bx + si] ; 00940d72 1300
+ add al, [bx + si] ; 00940d74 0200
+ gs pop es ; 00940d76 6507
+ or [bx + si], ax ; 00940d78 0900
+ add [bx + si], al ; 00940d7a 0000
+ add al, [bx + si] ; 00940d7c 0200
+ mov dh, 0x4 ; 00940d7e b604
+ or al, [bx + si] ; 00940d80 0a00
+ add [bx + si], al ; 00940d82 0000
+ add ax, [bx + di] ; 00940d84 0301
+ fld L310 ; 00940d86 dd060200
+ fwait ; 00940d8a 9b
+ add [bp + di], al ; 00940d8b 0003
+ add [bx + 0x206], bp ; 00940d8d 01af0602
+ add [di + 0x300], bl ; 00940d91 009d0003
+ add [bx + si], sp ; 00940d95 0120
+ add ax, L310 ; 00940d97 050200
+ pop ds ; 00940d9a 1f
+ add [bp + di], al ; 00940d9b 0003
+ add [si], bx ; 00940d9d 011c
+ add [bp + si], al ; 00940d9f 0002
+ add [bx], bl ; 00940da1 001f
+ add [bp + di], ax ; 00940da3 0103
+ add [bx], bp ; 00940da5 012f
+ add ax, L310 ; 00940da7 050200
+ and [bx + si], ax ; 00940daa 2100
+ add ax, [bx + di] ; 00940dac 0301
+ movsb ; 00940dae a4
+ push es ; 00940daf 06
+ add al, 0x0 ; 00940db0 0400
+ push ss ; 00940db2 16
+ add [bp + di], al ; 00940db3 0003
+ add bp, bx ; 00940db5 01dd
+ add ax, [bp + si] ; 00940db7 0302
+ add [bx], ah ; 00940db9 0027
+ add [bp + di], al ; 00940dbb 0003
+ add [bp + di], ax ; 00940dbd 0103
+ add al, L310 ; 00940dbf 0402
+ add [bx + si], ch ; 00940dc1 0028
+ add [bp + di], al ; 00940dc3 0003
+ add [bx + 0], di ; 00940dc5 017f00
+ add [bx + si], ax ; 00940dc8 0100
+ xor al, [bx + si] ; 00940dca 3200
+ add ax, [bx + di] ; 00940dcc 0301
+ jns L451 ; 00940dce 7903
+ add al, [bx + si] ; 00940dd0 0200
+ sub al, [bx + si] ; 00940dd2 2a00
+ add ax, [bx + di] ; 00940dd4 0301
+ cmp [bp + di], ax ; 00940dd6 3903
+ add [bx + si], ax ; 00940dd8 0100
+ xor ax, [bx + si] ; 00940dda 3300
+ add ax, [bx + di] ; 00940ddc 0301
+ jmp short L300 ; 00940dde eb08
+ add al, [bx + si] ; 00940de0 0200
+ stosw ; 00940de2 ab
+ add [bp + di], al ; 00940de3 0003
+ add dx, si ; 00940de5 01f2
+ add al, L4 ; 00940de7 0401
+ add [si], dh ; 00940de9 0034
+ add [bp + di], al ; 00940deb 0003
+ add [si], dx ; 00940ded 0114
+ add [bp + si], ax ; 00940def 0102
+ add [di + 0x300], ch ; 00940df1 00ad0003
+ add [bp + 0x206], bx ; 00940df5 019e0602
+ add [bp + 0x300], ch ; 00940df9 00ae0003
+ add [bp + di], dx ; 00940dfd 0113
+ add [bx + di], al ; 00940dff 0001
+ add L89, dh ; 00940e01 00360003
+ add [si + 0x206], ax ; 00940e05 01840602
+ add [bx + si + 0x300], dh ; 00940e09 00b00003
+ add [di + 0], si ; 00940e0d 017500
+ add al, [bx + si] ; 00940e10 0200
+ mov bl, 0x0 ; 00940e12 b300
+ add ax, [bx + di] ; 00940e14 0301
+ test [bp + si], al ; 00940e16 8402
+ add al, [bx + si] ; 00940e18 0200
+ cmp [bx + si], ax ; 00940e1a 3900
+ add ax, [bx + di] ; 00940e1c 0301
+ push si ; 00940e1e 56
+ add [bp + si], al ; 00940e1f 0002
+ add [bp + di], bh ; 00940e21 003b
+ add [bp + di], al ; 00940e23 0003
+ add [bx + si], sp ; 00940e25 0120
+ or [bp + si], al ; 00940e27 0802
+ add [bp + si + 0], al ; 00940e29 004200
+ add ax, [bx + di] ; 00940e2c 0301
+ dec si ; 00940e2e 4e
+ or [bp + si], al ; 00940e2f 0802
+ add [si + 0], al ; 00940e31 004400
+ add ax, [bx + di] ; 00940e34 0301
+ sbb ax, 0x203 ; 00940e36 1d0302
+ add ah, al ; 00940e39 00c4
+ add [bp + di], ax ; 00940e3b 0103
+ add si, cx ; 00940e3d 01ce
+ add al, [bp + si] ; 00940e3f 0202
+ add dh, al ; 00940e41 00c6
+ add [bp + di], ax ; 00940e43 0103
+ add di, cx ; 00940e45 01cf
+ pop es ; 00940e47 07
+ add al, [bx + si] ; 00940e48 0200
+ inc di ; 00940e4a 47
+ add [bp + di], al ; 00940e4b 0003
+ add [bx + di + 0x301], di ; 00940e4d 01b90103
+ add [bp + si + 0], al ; 00940e51 004200
+ add ax, [bx + di] ; 00940e54 0301
+ dec cx ; 00940e56 49
+ add [bp + di], ax ; 00940e57 0103
+ add [bx + si + 0], dl ; 00940e59 005000
+ add ax, [bx + di] ; 00940e5c 0301
+ xor ax, [bx + di] ; 00940e5e 3301
+ add ax, [bx + si] ; 00940e60 0300
+ pop bp ; 00940e62 5d
+ add [bp + di], al ; 00940e63 0003
+ add [si], si ; 00940e65 0134
+ add [bp + si], al ; 00940e67 0002
+ add al, ch ; 00940e69 00e8
+ add [bp + di], al ; 00940e6b 0003
+ add di, bx ; 00940e6d 01df
+ pop es ; 00940e6f 07
+ add al, [bx + si] ; 00940e70 0200
+ imul ax, [bx + si], 0x3 ; 00940e72 6b0003
+ add [bx + si + 0x200], sp ; 00940e75 01a00002
+ add [si + 0], ch ; 00940e79 006c00
+ add ax, [bx + di] ; 00940e7c 0301
+ outsb ; 00940e7e 6e
+ push es ; 00940e7f 06
+ add al, [bx + si] ; 00940e80 0200
+ outsb ; 00940e82 6e
+ add [bx + si], al ; 00940e83 0000
+ add [bx + si], al ; 00940e85 0000
+ add [bx + si], al ; 00940e87 0000
+ add [bx + si], al ; 00940e89 0000
+ add [bx + si], al ; 00940e8b 0000
+ add [bx + si], al ; 00940e8d 0000
+ add [bx + si], al ; 00940e8f 0000
+ add [bx + si], al ; 00940e91 0000
+ add [bx + si], al ; 00940e93 0000
+ add [bx + si], al ; 00940e95 0000
+ add [bx + si], al ; 00940e97 0000
+ add [bx + si], al ; 00940e99 0000
+ add [bx + si], al ; 00940e9b 0000
+ add [bx + si], al ; 00940e9d 0000
+ add [bx + si], al ; 00940e9f 0000
+ add [bx + si], al ; 00940ea1 0000
+ add [bx + si], al ; 00940ea3 0000
+ add [bx + si], al ; 00940ea5 0000
+ add [bx + si], al ; 00940ea7 0000
+ add [bx + si], al ; 00940ea9 0000
+ add [bx + si], al ; 00940eab 0000
+ add [si + 0xffff90d8], cl ; 00940ead 008cd890
+ inc bp ; 00940eb1 45
+ push bp ; 00940eb2 55
+ mov bp, sp ; 00940eb3 8bec
+ push ds ; 00940eb5 1e
+ mov ds, ax ; 00940eb6 8ed8
+ mov bx, [bp + 0x6] ; 00940eb8 8b5e06
+ mov cx, bx ; 00940ebb 8bcb
+ or bx, bx ; 00940ebd 0bdb
+ jns L452 ; 00940ebf 7902
+ neg bx ; 00940ec1 f7db
+ mov ax, [bp + 0xa] ; 00940ec3 8b460a
+ xor cx, ax ; 00940ec6 33c8
+ or ax, ax ; 00940ec8 0bc0
+ jns L453 ; 00940eca 7902
+ neg ax ; 00940ecc f7d8
+ mov dx, [bp + 0x8] ; 00940ece 8b5608
+ xor cx, dx ; 00940ed1 33ca
+ or dx, dx ; 00940ed3 0bd2
+ jns L454 ; 00940ed5 7902
+ neg dx ; 00940ed7 f7da
+ mul dx, ax ; 00940ed9 f7e2
+ mov cl, bl ; 00940edb 8acb
+ sar bx, 1 ; 00940edd d1fb
+ add ax, bx ; 00940edf 03c3
+ adc dx, byte 0x0 ; 00940ee1 83d200
+ shl bx, 1 ; 00940ee4 d1e3
+ or bl, cl ; 00940ee6 0ad9
+ cmp dx, bx ; 00940ee8 3bd3
+ jnc L455 ; 00940eea 7318
+ div bx, ax ; 00940eec f7f3
+ or ax, ax ; 00940eee 0bc0
+ js L455 ; 00940ef0 7812
+ or cx, cx ; 00940ef2 0bc9
+ jns L456 ; 00940ef4 7902
+ neg ax ; 00940ef6 f7d8
+ mov dx, L4 ; 00940ef8 ba0100
+ lea sp, [bp + 0xfffffffe] ; 00940efb 8d66fe
+ pop ds ; 00940efe 1f
+ pop bp ; 00940eff 5d
+ dec bp ; 00940f00 4d
+ retf 0x06 ; 00940f01 ca0600
+ xor dx, dx ; 00940f04 33d2
+ mov ax, 0x7fff ; 00940f06 b8ff7f
+ or cx, cx ; 00940f09 0bc9
+ jns L457 ; 00940f0b 79ee
+ not ax ; 00940f0d f7d0
+ jmp short L457 ; 00940f0f ebea
+ add bh, bh ; 00940f11 00ff
+ call far oword [bx + si + 0x58] ; 00940f13 ff5858
+ pop ax ; 00940f16 58
+ mov ah, L3 ; 00940f17 b44c
+ cs test word cs:L319, L4 ; 00940f19 2ef70674000100
+ jz L458 ; 00940f20 7407
+ callf ; 00940f22 9affff0000
+ jmp short L459 ; 00940f27 eb02
+ int 0x21 ; 00940f29 cd21
+ mov al, 0xff ; 00940f2b b0ff
+ push ax ; 00940f2d 50
+ push cs ; 00940f2e 0e
+ call L460 ; 00940f2f e8e2ff
+ xor bp, bp ; 00940f32 33ed
+ push bp ; 00940f34 55
+ callf ; 00940f35 9affff0000
+ or ax, ax ; 00940f3a 0bc0
+ jz L459 ; 00940f3c 74ed
+ add cx, 0x100 ; 00940f3e 81c10001
+ jc L459 ; 00940f42 72e7
+ mov L323, cx ; 00940f44 890ec201
+ mov L324, si ; 00940f48 8936c401
+ mov L325, di ; 00940f4c 893ec601
+ mov L326, bx ; 00940f50 891ec801
+ mov word L201, es ; 00940f54 8c06ca01
+ mov L327, dx ; 00940f58 8916cc01
+ xor ax, ax ; 00940f5c 33c0
+ push ax ; 00940f5e 50
+ callf ; 00940f5f 9affff0000
+ push word L325 ; 00940f64 ff36c601
+ callf ; 00940f68 9affff0000
+ or ax, ax ; 00940f6d 0bc0
+ jz L459 ; 00940f6f 74ba
+ push word L325 ; 00940f71 ff36c601
+ push word L178 ; 00940f75 ff361400
+
+ .section .codeSection5, @progbits
+ .align 0
+
+ sbb al, 0x3 ; 0094000d 1c03
+ add byte [bx + si], 0x0 ; 0094000f 800000
+ add [bx + si], al ; 00940012 0000
+ ja L461 ; 00940014 7729
+ add al, [bx + si] ; 00940016 0200
+ xor [si], bl ; 00940018 301c
+ jle L462 ; 0094001a 7e80
+ add [bx + si], al ; 0094001c 0000
+ add [bx + si], al ; 0094001e 0000
+ adc [bx + si + 0x1], al ; 00940020 10800100
+ add [bx + si], al ; 00940024 0000
+ add [bx + si], al ; 00940026 0000
+ jns L463 ; 00940028 7929
+ push ds ; 0094002a 1e
+ add [bx + si], dh ; 0094002b 0030
+ or al, L4 ; 0094002d 0c01
+ add byte [bx + si], 0x0 ; 0094002f 800000
+ add [bx + si], al ; 00940032 0000
+ add ax, [bx + si + 0x2] ; 00940034 03800200
+ add [bx + si], al ; 00940038 0000
+ add [bx + si], al ; 0094003a 0000
+ xchg ax, di ; 0094003c 97
+ sub [bx], bp ; 0094003d 292f
+ add [bx + si], dl ; 0094003f 0010
+ sbb al, L4 ; 00940041 1c01
+ add byte [bx + si], 0x0 ; 00940043 800000
+ add [bx + si], al ; 00940046 0000
+ mov byte [bx + di], 0x13 ; 00940048 c62913
+ add [bx + si], dl ; 0094004b 0010
+ sbb al, L310 ; 0094004d 1c02
+ add byte [bx + si], 0x0 ; 0094004f 800000
+ add [bx + si], al ; 00940052 0000
+ add [bx + si], al ; 00940054 0000
+ add dx, [bp + di + 0x4f] ; 00940056 03534f
+ dec sp ; 00940059 4c
+ add dx, [bp + di + 0x4f] ; 0094005a 03534f
+ dec sp ; 0094005d 4c
+ add [bx + si], al ; 0094005e 0000
+ add [bx + di], al ; 00940060 0001
+ add [bx + si], cl ; 00940062 0008
+ add [di], cl ; 00940064 000d
+ add [bx + di], dl ; 00940066 0011
+ add [bx + si], al ; 00940068 0000
+ push es ; 0094006a 06
+ dec bx ; 0094006b 4b
+ inc bp ; 0094006c 45
+ push dx ; 0094006d 52
+ dec si ; 0094006e 4e
+ inc bp ; 0094006f 45
+ dec sp ; 00940070 4c
+ add al, 0x55 ; 00940071 0455
+ push bx ; 00940073 53
+ inc bp ; 00940074 45
+ push dx ; 00940075 52
+ add ax, [bx + 0x44] ; 00940076 034744
+ dec cx ; 00940079 49
+ add ax, 0x4853 ; 0094007a 055348
+ inc bp ; 0094007d 45
+ dec sp ; 0094007e 4c
+ dec sp ; 0094007f 4c
+ add [bp + di], dl ; 00940080 0013
+ dec bp ; 00940082 4d
+ imul sp, [bp + di + 0x72], 0x736f ; 00940083 6963726f73
+ outsw ; 00940088 6f
+ o32 jz L464 ; 00940089 667420
+ push bx ; 0094008c 53
+ outsw ; 0094008d 6f
+ insb ; 0094008e 6c
+ imul si, [si + 0x8], 0x00 ; 0094008f 6974080000
+
+ .section .codeSection6, @progbits
+ .align 0
+
+ add [bx + si], dh ; 0094000e 0030
+ sbb al, 0x7e ; 00940010 1c7e
+ add byte [bx + si], 0x0 ; 00940012 800000
+ add [bx + si], al ; 00940015 0000
+ adc [bx + si + 0x1], al ; 00940017 10800100
+ add [bx + si], al ; 0094001b 0000
+ add [bx + si], al ; 0094001d 0000
+ jns L197 ; 0094001f 7929
+ push ds ; 00940021 1e
+ add [bx + si], dh ; 00940022 0030
+ or al, L4 ; 00940024 0c01
+ add byte [bx + si], 0x0 ; 00940026 800000
+ add [bx + si], al ; 00940029 0000
+ add ax, [bx + si + 0x2] ; 0094002b 03800200
+ add [bx + si], al ; 0094002f 0000
+ add [bx + si], al ; 00940031 0000
+ xchg ax, di ; 00940033 97
+ sub [bx], bp ; 00940034 292f
+
+L2:
+ add [bx + si], dl ; 00940036 0010
+ sbb al, L4 ; 00940038 1c01
+ add byte [bx + si], 0x0 ; 0094003a 800000
+ add [bx + si], al ; 0094003d 0000
+ mov byte [bx + di], 0x13 ; 0094003f c62913
+ add [bx + si], dl ; 00940042 0010
+ sbb al, L310 ; 00940044 1c02
+ add byte [bx + si], 0x0 ; 00940046 800000
+ add [bx + si], al ; 00940049 0000
+ add [bx + si], al ; 0094004b 0000
+ add dx, [bp + di + 0x4f] ; 0094004d 03534f
+ dec sp ; 00940050 4c
+ add dx, [bp + di + 0x4f] ; 00940051 03534f
+ dec sp ; 00940054 4c
+ add [bx + si], al ; 00940055 0000
+ add [bx + di], al ; 00940057 0001
+ add [bx + si], cl ; 00940059 0008
+ add [di], cl ; 0094005b 000d
+ add [bx + di], dl ; 0094005d 0011
+ add [bx + si], al ; 0094005f 0000
+ push es ; 00940061 06
+ dec bx ; 00940062 4b
+ inc bp ; 00940063 45
+ push dx ; 00940064 52
+ dec si ; 00940065 4e
+ inc bp ; 00940066 45
+ dec sp ; 00940067 4c
+ add al, 0x55 ; 00940068 0455
+ push bx ; 0094006a 53
+ inc bp ; 0094006b 45
+ push dx ; 0094006c 52
+ add ax, [bx + 0x44] ; 0094006d 034744
+ dec cx ; 00940070 49
+ add ax, 0x4853 ; 00940071 055348
+ inc bp ; 00940074 45
+ dec sp ; 00940075 4c
+ dec sp ; 00940076 4c
+ add [bp + di], dl ; 00940077 0013
+ dec bp ; 00940079 4d
+ imul sp, [bp + di + 0x72], 0x736f ; 0094007a 6963726f73
+ outsw ; 0094007f 6f
+ o32 jz L465 ; 00940080 667420
+ push bx ; 00940083 53
+ outsw ; 00940084 6f
+ insb ; 00940085 6c
+ imul si, [si + 0x61], 0x7269 ; 00940086 6974616972
+ gs add gs:[bx + si], al ; 0094008b 650000
+ add [bx + si], al ; 0094008e 0000
+ add [bx + si], al ; 00940090 0000
+ add [bx + si], al ; 00940092 0000
+ add [bx + si], al ; 00940094 0000
+ add [bx + si], al ; 00940096 0000
+ add [bx + si], al ; 00940098 0000
+ add [bx + si], al ; 0094009a 0000
+ add [bx + si], al ; 0094009c 0000
+ add [bx + si], al ; 0094009e 0000
+ add [bx + si], al ; 009400a0 0000
+ add [bx + si], al ; 009400a2 0000
+ add [bx + si], al ; 009400a4 0000
+ add [bx + si], al ; 009400a6 0000
+ add [bx + si], al ; 009400a8 0000
+ add [bx + si], al ; 009400aa 0000
+
+L464:
+ add [bx + si], al ; 009400ac 0000
+ add [bx + si], al ; 009400ae 0000
+ add [bx + si], al ; 009400b0 0000
+ add [bx + si], al ; 009400b2 0000
+ add [bx + si], al ; 009400b4 0000
+ add [bx + si], al ; 009400b6 0000
+ add [bx + si], al ; 009400b8 0000
+ add [bx + si], al ; 009400ba 0000
+ add [bx + si], al ; 009400bc 0000
+ add [bx + si], al ; 009400be 0000
+ add [bx + si], al ; 009400c0 0000
+ add [bx + si], al ; 009400c2 0000
+ add [bx + si], al ; 009400c4 0000
+ add [bx + si], al ; 009400c6 0000
+ add [bx + si], al ; 009400c8 0000
+ add [bx + si], al ; 009400ca 0000
+ add [bx + si], al ; 009400cc 0000
+ add [bx + si], al ; 009400ce 0000
+ add [bx + si], al ; 009400d0 0000
+ add [bx + si], al ; 009400d2 0000
+ add [bx + si], al ; 009400d4 0000
+ add [bx + si], al ; 009400d6 0000
+ add al, cl ; 009400d8 00c8
+ sbb [bx + si], al ; 009400da 1800
+ add [bp + di + 0xc7e], al ; 009400dc 00837e0c
+ add [si + 0x55], dh ; 009400e0 007455
+ push word [bp + 0xc] ; 009400e3 ff760c
+ push L23 ; 009400e6 68f001
+ push L310 ; 009400e9 6a02
+ callf ; 009400eb 9affff0000
+ push word L23 ; 009400f0 ff36f001
+ callf ; 009400f4 9affff0000
+ mov [bp + 0xffffffec], ax ; 009400f9 8946ec
+ push word L23 ; 009400fc ff36f001
+ push 0x0 ; 00940100 6a00
+ push 0x0 ; 00940102 6a00
+ push 0x0 ; 00940104 6a00
+ push 0x0 ; 00940106 6a00
+ push 0x0 ; 00940108 6a00
+ push 0x43 ; 0094010a 6a43
+ callf ; 0094010c 9affff0000
+ push word L23 ; 00940111 ff36f001
+ callf ; 00940115 9affff0000
+ or ax, ax ; 0094011a 0bc0
+ jz L466 ; 0094011c 740d
+ push word L23 ; 0094011e ff36f001
+ push 0x9 ; 00940122 6a09
+ callf ; 00940124 9affff0000
+ jmp short L467 ; 00940129 eb08
+ push word [bp + 0xffffffec] ; 0094012b ff76ec
+ callf ; 0094012e 9affff0000
+ xor ax, ax ; 00940133 33c0
+ jmp L468 ; 00940135 e98200
+ o32 push dword [bp + 0xc] ; 00940138 66ff760c
+ o32 push dword [bp + 0x8] ; 0094013c 66ff7608
+ push word [bp + 0x6] ; 00940140 ff7606
+ push cs ; 00940143 0e
+ call L469 ; 00940144 e87800
+ or ax, ax ; 00940147 0bc0
+ jz L467 ; 00940149 74e8
+ push 0x29 ; 0094014b 6a29
+ callf ; 0094014d 9affff0000
+ push ax ; 00940152 50
+ push ds ; 00940153 1e
+ push 0x3c ; 00940154 683c00
+ callf ; 00940157 9affff0000
+ mov [bp + 0xffffffe8], ax ; 0094015c 8946e8
+ mov [bp + 0xffffffea], dx ; 0094015f 8956ea
+ or dx, ax ; 00940162 0bd0
+ jz L470 ; 00940164 7407
+ push L4 ; 00940166 6a01
+ push L4 ; 00940168 6a01
+ call far oword [bp + 0xffffffe8] ; 0094016a ff5ee8
+ lea ax, [bp + 0xffffffee] ; 0094016d 8d46ee
+ push ss ; 00940170 16
+ push ax ; 00940171 50
+ push 0x0 ; 00940172 6a00
+ push 0x0 ; 00940174 6a00
+ push 0x0 ; 00940176 6a00
+ callf ; 00940178 9ac8000000
+ or ax, ax ; 0094017d 0bc0
+ jz L471 ; 0094017f 7428
+ lea ax, [bp + 0xffffffee] ; 00940181 8d46ee
+ push ss ; 00940184 16
+ push ax ; 00940185 50
+ callf ; 00940186 9affff0000
+ lea ax, [bp + 0xffffffee] ; 0094018b 8d46ee
+ push ss ; 0094018e 16
+ push ax ; 0094018f 50
+ callf ; 00940190 9affff0000
+ lea ax, [bp + 0xffffffee] ; 00940195 8d46ee
+ push ss ; 00940198 16
+ push ax ; 00940199 50
+ push 0x0 ; 0094019a 6a00
+ push 0x0 ; 0094019c 6a00
+ push 0x0 ; 0094019e 6a00
+ callf ; 009401a0 9affff0000
+ or ax, ax ; 009401a5 0bc0
+ jnz L472 ; 009401a7 75d8
+ o32 cmp dword [bp + 0xffffffe8], byte 0x0 ; 009401a9 66837ee800
+ jz L473 ; 009401ae 7407
+ push L4 ; 009401b0 6a01
+ push 0x0 ; 009401b2 6a00
+ call far oword [bp + 0xffffffe8] ; 009401b4 ff5ee8
+ mov ax, [bp + 0xfffffff2] ; 009401b7 8b46f2
+ leave ; 009401ba c9
+ retf 0x0a ; 009401bb ca0a00
+ nop ; 009401be 90
+ enter 0x72, 0x0 ; 009401bf c8720000
+ mov ax, [bp + 0xe] ; 009401c3 8b460e
+ mov [0x2b0], ax ; 009401c6 a3b002
+ push 0x200 ; 009401c9 680002
+ push 0x12c ; 009401cc 682c01
+ callf ; 009401cf 9a2806d401
+ push ds ; 009401d4 1e
+ push L84 ; 009401d5 686802
+ push ds ; 009401d8 1e
+ push L82 ; 009401d9 686a02
+ callf ; 009401dc 9a0000ffff
+ or ax, ax ; 009401e1 0bc0
+ jz L474 ; 009401e3 741d
+ push 0x0 ; 009401e5 6a00
+ push 0x0 ; 009401e7 6a00
+ push 0x7f00 ; 009401e9 68007f
+ callf ; 009401ec 9affff0000
+ mov [bp + 0xffffffb4], ax ; 009401f1 8946b4
+ push 0x0 ; 009401f4 6a00
+ callf ; 009401f6 9affff0000
+ mov [bp + 0xffffffd8], ax ; 009401fb 8946d8
+ or ax, ax ; 009401fe 0bc0
+ jnz L475 ; 00940200 7503
+ jmp L476 ; 00940202 e99802
+ push ax ; 00940205 50
+ lea ax, [bp + 0xffffffb8] ; 00940206 8d46b8
+ push ss ; 00940209 16
+ push ax ; 0094020a 50
+ callf ; 0094020b 9affff0000
+ mov ax, [bp + 0xffffffb8] ; 00940210 8b46b8
+ mov [0x23e], ax ; 00940213 a33e02
+ mov ax, [bp + 0xffffffc4] ; 00940216 8b46c4
+ mov [0x23c], ax ; 00940219 a33c02
+ push word [bp + 0xffffffd8] ; 0094021c ff76d8
+ push L59 ; 0094021f 6a18
+ callf ; 00940221 9a5e010000
+ cmp ax, L310 ; 00940226 3d0200
+ jnz L477 ; 00940229 7506
+ mov word L36, L4 ; 0094022b c706f6010100
+ push word [bp + 0xffffffd8] ; 00940231 ff76d8
+ push 0x8 ; 00940234 6a08
+ callf ; 00940236 9a6b010000
+ mov [0x24c], ax ; 0094023b a34c02
+ push word [bp + 0xffffffd8] ; 0094023e ff76d8
+ push 0xa ; 00940241 6a0a
+ callf ; 00940243 9affff0000
+ mov [0x24e], ax ; 00940248 a34e02
+ cmp ax, 0x12c ; 0094024b 3d2c01
+ jge L478 ; 0094024e 7d05
+ mov ax, L4 ; 00940250 b80100
+ jmp short L479 ; 00940253 eb02
+ xor ax, ax ; 00940255 33c0
+ mov [0x38], ax ; 00940257 a33800
+ or ax, ax ; 0094025a 0bc0
+ jz L82 ; 0094025c 740c
+ mov cx, L310 ; 0094025e b90200
+ mov ax, [0x26a] ; 00940261 a16a02
+ cwd ; 00940264 99
+ idiv cx, ax ; 00940265 f7f9
+ mov [0x26a], ax ; 00940267 a36a02
+ push 0x0 ; 0094026a 6a00
+ push word [bp + 0xffffffd8] ; 0094026c ff76d8
+ callf ; 0094026f 9affff0000
+ cmp word L36, byte 0x0 ; 00940274 833ef60100
+ jz L480 ; 00940279 7408
+ mov ax, 0xffff ; 0094027b b8ffff
+ mov dx, 0xff ; 0094027e baff00
+ jmp short L481 ; 00940281 eb05
+ mov ax, 0x8000 ; 00940283 b80080
+ xor dx, dx ; 00940286 33d2
+ mov [0x2b2], ax ; 00940288 a3b202
+ mov L42, dx ; 0094028b 8916b402
+ push dx ; 0094028f 52
+ push ax ; 00940290 50
+ callf ; 00940291 9affff0000
+ mov [0x266], ax ; 00940296 a36602
+ callf ; 00940299 9affff0000
+ push ax ; 0094029e 50
+ callf ; 0094029f 9a3201ffff
+ pop bx ; 009402a4 5b
+ push 0x26e ; 009402a5 686e02
+ push 0x64 ; 009402a8 6a64
+ callf ; 009402aa 9a2806de01
+ push 0x250 ; 009402af 685002
+ push 0x65 ; 009402b2 6a65
+ callf ; 009402b4 9a2806e901
+ lea ax, [bp + 0xffffff98] ; 009402b9 8d4698
+ push ax ; 009402bc 50
+ push 0x67 ; 009402bd 6a67
+ callf ; 009402bf 9a2806ffff
+ lea ax, [bp + 0xffffff98] ; 009402c4 8d4698
+ push ss ; 009402c7 16
+ push ax ; 009402c8 50
+ callf ; 009402c9 9affff0000
+ mov [0x1f8], ax ; 009402ce a3f801
+ mov word [bp + 0xffffffb2], 0x00 ; 009402d1 c746b20000
+ o32 mov eax, [bp + 0x8] ; 009402d6 668b4608
+ mov dx, [bp + 0xa] ; 009402da 8b560a
+ o32 mov [bp + 0xffffffae], eax ; 009402dd 668946ae
+ mov es, dx ; 009402e1 8ec2
+ mov bx, ax ; 009402e3 8bd8
+ es cmp byte es:[bx], 0x0 ; 009402e5 26803f00
+ jz L482 ; 009402e9 7420
+ es cmp byte es:[bx], 0x2f ; 009402eb 26803f2f
+ jnz L483 ; 009402ef 7507
+ es cmp byte es:[bx + 0x1], 0x49 ; 009402f1 26807f0149
+ jz L484 ; 009402f6 740e
+ inc word [bp + 0xffffffae] ; 009402f8 ff46ae
+ mov bx, [bp + 0xffffffae] ; 009402fb 8b5eae
+ es cmp byte es:[bx], 0x0 ; 009402fe 26803f00
+ jnz L485 ; 00940302 75e7
+ jmp short L482 ; 00940304 eb05
+ mov word [bp + 0xffffffb2], L4 ; 00940306 c746b20100
+ cmp word [bp + 0xc], byte 0x0 ; 0094030b 837e0c00
+ jnz L486 ; 0094030f 7556
+ mov word [bp + 0xffffffe6], 0x2008 ; 00940311 c746e60820
+ mov word [bp + 0xffffffe8], 0x40c ; 00940316 c746e80c04
+ mov word [bp + 0xffffffea], 0xffff ; 0094031b c746eaffff
+ o32 mov dword [bp + 0xffffffec], 0x0000 ; 00940320 66c746ec00000000
+ mov ax, [0x2b0] ; 00940328 a1b002
+ mov [bp + 0xfffffff0], ax ; 0094032b 8946f0
+ push ax ; 0094032e 50
+ push ds ; 0094032f 1e
+ push L12 ; 00940330 684b00
+ callf ; 00940333 9affff0000
+ mov [bp + 0xfffffff2], ax ; 00940338 8946f2
+ mov ax, [bp + 0xffffffb4] ; 0094033b 8b46b4
+ mov [bp + 0xfffffff4], ax ; 0094033e 8946f4
+ mov ax, [0x266] ; 00940341 a16602
+ mov [bp + 0xfffffff6], ax ; 00940344 8946f6
+ o32 mov dword [bp + 0xfffffff8], L4 ; 00940347 66c746f801000000
+ mov word [bp + 0xfffffffc], 0x22 ; 0094034f c746fc2200
+ mov word [bp + 0xfffffffe], ds ; 00940354 8c5efe
+ lea ax, [bp + 0xffffffe6] ; 00940357 8d46e6
+ push ss ; 0094035a 16
+ push ax ; 0094035b 50
+ callf ; 0094035c 9affff0000
+ or ax, ax ; 00940361 0bc0
+ je L476 ; 00940363 0f843601
+ mov ax, [0x268] ; 00940367 a16802
+ imul cx, ax, 0x7 ; 0094036a 6bc807
+ cwd ; 0094036d 99
+ and dx, byte 0x7 ; 0094036e 83e207
+ add ax, dx ; 00940371 03c2
+ sar ax, byte 0x3 ; 00940373 c1f803
+ add ax, 0x03 ; 00940376 050300
+ mov [0x240], ax ; 00940379 a34002
+ shl ax, byte 0x3 ; 0094037c c1e003
+ add cx, ax ; 0094037f 03c8
+ mov [bp + 0xffffff92], cx ; 00940381 894e92
+ mov ax, [0x26a] ; 00940384 a16a02
+ shl ax, L310 ; 00940387 c1e002
+ mov [bp + 0xffffff94], ax ; 0094038a 894694
+ o32 mov dword [bp + 0xffffff8e], 0x0000 ; 0094038d 66c7468e00000000
+ lea ax, [bp + 0xffffff8e] ; 00940395 8d468e
+ push ss ; 00940398 16
+ push ax ; 00940399 50
+ push 0xcf ; 0094039a 68cf00
+ push 0x0 ; 0094039d 6a00
+ push L4 ; 0094039f 6a01
+ push 0x0 ; 009403a1 6a00
+ push 0x200 ; 009403a3 680002
+ callf ; 009403a6 9affff0000
+ mov ax, [bp + 0xffffff8e] ; 009403ab 8b468e
+ sub [bp + 0xffffff92], ax ; 009403ae 294692
+ mov ax, [0x24e] ; 009403b1 a14e02
+ mov cx, [bp + 0xffffff90] ; 009403b4 8b4e90
+ sub [bp + 0xffffff94], cx ; 009403b7 294e94
+ cmp [bp + 0xffffff94], ax ; 009403ba 394694
+ jle L487 ; 009403bd 7e03
+ mov [bp + 0xffffff94], ax ; 009403bf 894694
+ push 0x0 ; 009403c2 6a00
+ push 0x200 ; 009403c4 680002
+ push ds ; 009403c7 1e
+ push 0x22 ; 009403c8 682200
+ push ds ; 009403cb 1e
+ push 0x26e ; 009403cc 686e02
+ cmp word [bp + 0xffffffb2], byte 0x0 ; 009403cf 837eb200
+ jz L488 ; 009403d3 7407
+ xor ax, ax ; 009403d5 33c0
+ mov dx, 0x22cf ; 009403d7 bacf22
+ jmp short L489 ; 009403da eb05
+ xor ax, ax ; 009403dc 33c0
+ mov dx, 0x2cf ; 009403de bacf02
+ push dx ; 009403e1 52
+ push ax ; 009403e2 50
+ push 0x8000 ; 009403e3 680080
+ push ax ; 009403e6 50
+ push word [bp + 0xffffff92] ; 009403e7 ff7692
+ push word [bp + 0xffffff94] ; 009403ea ff7694
+ push ax ; 009403ed 50
+ push ax ; 009403ee 50
+ push word L51 ; 009403ef ff36b002
+ push ax ; 009403f3 50
+ push ax ; 009403f4 50
+ callf ; 009403f5 9affff0000
+ or ax, ax ; 009403fa 0bc0
+ je L476 ; 009403fc 0f849d00
+ lea ax, [bp + 0xffffffac] ; 00940400 8d46ac
+ push ax ; 00940403 50
+ push cs ; 00940404 0e
+ call L490 ; 00940405 e8d105
+ push 0x245 ; 00940408 684502
+ push 0x85a ; 0094040b 685a08
+ push word [bp + 0xe] ; 0094040e ff760e
+ callf ; 00940411 9affff0000
+ mov [0x1f2], ax ; 00940416 a3f201
+ mov L53, dx ; 00940419 8916f401
+ mov ax, dx ; 0094041d 8bc2
+ or ax, L54 ; 0094041f 0b06f201
+ jz L491 ; 00940423 747d
+ push word L23 ; 00940425 ff36f001
+ o32 push 0x29a00fa ; 00940429 6668fa009a02
+ push dx ; 0094042f 52
+ push word L54 ; 00940430 ff36f201
+ callf ; 00940434 9affff0000
+ or ax, ax ; 00940439 0bc0
+ jz L476 ; 0094043b 7460
+ callf ; 0094043d 9a24026f03
+ push word [bp + 0xffffffac] ; 00940442 ff76ac
+ callf ; 00940445 9ac6000b05
+ push word L23 ; 0094044a ff36f001
+ push word [bp + 0x6] ; 0094044e ff7606
+ callf ; 00940451 9a4c000000
+ push word L23 ; 00940456 ff36f001
+ callf ; 0094045a 9affff0020
+
+ .section .codeSection7, @progbits
+ .align 0
+
+ add [bx + si], al ; 0094000f 0000
+ add al, [bx + si + 0x4a] ; 00940011 02804a00
+ add [bx + si], al ; 00940015 0000
+ add [bx + si], al ; 00940017 0000
+ push bp ; 00940019 55
+ push es ; 0094001a 06
+ fld [bx + si] ; 0094001b dd00
+ xor [si], bl ; 0094001d 301c
+ ss add byte ss:[bx + si], 0x0 ; 0094001f 36800000
+ add [bx + si], al ; 00940023 0000
+ xor al, [bx] ; 00940025 3207
+ fld [bx + si] ; 00940027 dd00
+ xor [si], bl ; 00940029 301c
+ aaa ; 0094002b 37
+ add byte [bx + si], 0x0 ; 0094002c 800000
+ add [bx + si], al ; 0094002f 0000
+ invd ; 00940031 0f08
+ fadd [bx + si] ; 00940033 dc00
+ xor [si], bl ; 00940035 301c
+ cmp [bx + si + 0], al ; 00940037 38800000
+ add [bx + si], al ; 0094003b 0000
+ jmp short L492 ; 0094003d eb08
+ fild [bx + si] ; 0094003f df00
+ xor [si], bl ; 00940041 301c
+ cmp [bx + si + 0], ax ; 00940043 39800000
+ add [bx + si], al ; 00940047 0000
+ retf 0xdc09 ; 00940049 ca09dc
+ add [bx + si], dh ; 0094004c 0030
+ sbb al, 0x3a ; 0094004e 1c3a
+ add byte [bx + si], 0x0 ; 00940050 800000
+ add [bx + si], al ; 00940053 0000
+ cmpsb ; 00940055 a6
+ or bl, ah ; 00940056 0adc
+ add [bx + si], dh ; 00940058 0030
+ sbb al, 0x3b ; 0094005a 1c3b
+ add byte [bx + si], 0x0 ; 0094005c 800000
+ add [bx + si], al ; 0094005f 0000
+ or byte [bp + di], L16 ; 00940061 820bdd
+ add [bx + si], dh ; 00940064 0030
+ sbb al, 0x3c ; 00940066 1c3c
+ add byte [bx + si], 0x0 ; 00940068 800000
+ add [bx + si], al ; 0094006b 0000
+ pop di ; 0094006d 5f
+ or al, L16 ; 0094006e 0cdd
+ add [bx + si], dh ; 00940070 0030
+ sbb al, 0x3d ; 00940072 1c3d
+ add byte [bx + si], 0x0 ; 00940074 800000
+ add [bx + si], al ; 00940077 0000
+ cmp al, 0xd ; 00940079 3c0d
+ fadd [bx + si] ; 0094007b dc00
+ xor [si], bl ; 0094007d 301c
+ ds add byte ds:[bx + si], 0x0 ; 0094007f 3e800000
+ add [bx + si], al ; 00940083 0000
+ sbb L8, cl ; 00940085 180edc00
+ xor [si], bl ; 00940089 301c
+ aas ; 0094008b 3f
+ add byte [bx + si], 0x0 ; 0094008c 800000
+ add [bx + si], al ; 0094008f 0000
+ hlt ; 00940091 f4
+ push cs ; 00940092 0e
+ fadd [bx + si] ; 00940093 dc00
+ xor [si], bl ; 00940095 301c
+ inc ax ; 00940097 40
+ add byte [bx + si], 0x0 ; 00940098 800000
+ add [bx + si], al ; 0094009b 0000
+ ror byte [bx], 1 ; 0094009d d00f
+ fadd [bx + si] ; 0094009f dc00
+ xor [si], bl ; 009400a1 301c
+
+L465:
+ inc cx ; 009400a3 41
+ add byte [bx + si], 0x0 ; 009400a4 800000
+ add [bx + si], al ; 009400a7 0000
+ lodsb ; 009400a9 ac
+ adc [bp + si + 0], cl ; 009400aa 104a00
+ xor [si], bl ; 009400ad 301c
+ xor ax, 0x80 ; 009400af 358000
+ add [bx + si], al ; 009400b2 0000
+ add dh, dh ; 009400b4 00f6
+ adc [bp + si], bl ; 009400b6 101a
+ add [bx + si], dh ; 009400b8 0030
+ sbb al, 0xa6 ; 009400ba 1ca6
+ add byte [bx + si], 0x0 ; 009400bc 820000
+ add [bx + si], al ; 009400bf 0000
+ adc [bx + di], dl ; 009400c1 1011
+ sbb al, [bx + si] ; 009400c3 1a00
+ xor [si], bl ; 009400c5 301c
+ cmpsw ; 009400c7 a7
+ add byte [bx + si], 0x0 ; 009400c8 820000
+ add [bx + si], al ; 009400cb 0000
+ sub dl, [bx + di] ; 009400cd 2a11
+ adc [bx + si], al ; 009400cf 1000
+ xor [si], bl ; 009400d1 301c
+ test al, 0x82 ; 009400d3 a882
+ add [bx + si], al ; 009400d5 0000
+ add [bx + si], al ; 009400d7 0000
+ cmp dl, [bx + di] ; 009400d9 3a11
+ or al, [bx + si] ; 009400db 0a00
+ xor [si], bl ; 009400dd 301c
+ test ax, 0x82 ; 009400df a98200
+ add [bx + si], al ; 009400e2 0000
+ add [si + 0x11], al ; 009400e4 004411
+ or al, [bx + si] ; 009400e7 0a00
+ xor [si], bl ; 009400e9 301c
+ stosb ; 009400eb aa
+ add byte [bx + si], 0x0 ; 009400ec 820000
+ add [bx + si], al ; 009400ef 0000
+ dec si ; 009400f1 4e
+ adc [bx + di], cx ; 009400f2 1109
+ add [bx + si], dh ; 009400f4 0030
+ sbb al, 0xab ; 009400f6 1cab
+ add byte [bx + si], 0x0 ; 009400f8 820000
+ add [bx + si], al ; 009400fb 0000
+ push di ; 009400fd 57
+ adc [bx + di], cx ; 009400fe 1109
+ add [bx + si], dh ; 00940100 0030
+ sbb al, 0xac ; 00940102 1cac
+ add byte [bx + si], 0x0 ; 00940104 820000
+ add [bx + si], al ; 00940107 0000
+ pusha ; 00940109 60
+ adc [bp + si + 0], cx ; 0094010a 114a00
+ xor [si], bl ; 0094010d 301c
+ add [bx + si + 0], ax ; 0094010f 01800000
+ add [bx + si], al ; 00940113 0000
+ stosb ; 00940115 aa
+ adc [bp + si + 0], cx ; 00940116 114a00
+ xor [si], bl ; 00940119 301c
+ add al, [bx + si + 0] ; 0094011b 02800000
+ add [bx + si], al ; 0094011f 0000
+ hlt ; 00940121 f4
+ adc [bp + si + 0], cx ; 00940122 114a00
+ xor [si], bl ; 00940125 301c
+ add ax, [bx + si + 0] ; 00940127 03800000
+ add [bx + si], al ; 0094012b 0000
+ ds adc cl, ds:[bp + si + 0] ; 0094012d 3e124a00
+ xor [si], bl ; 00940131 301c
+ add al, 0x80 ; 00940133 0480
+ add [bx + si], al ; 00940135 0000
+ add [bx + si], al ; 00940137 0000
+ mov [bp + si], dl ; 00940139 8812
+ dec dx ; 0094013b 4a
+ add [bx + si], dh ; 0094013c 0030
+ sbb al, 0x5 ; 0094013e 1c05
+ add byte [bx + si], 0x0 ; 00940140 800000
+ add [bx + si], al ; 00940143 0000
+ rcl byte [bp + si], cl ; 00940145 d212
+ dec dx ; 00940147 4a
+ add [bx + si], dh ; 00940148 0030
+ sbb al, 0x6 ; 0094014a 1c06
+ add byte [bx + si], 0x0 ; 0094014c 800000
+ add [bx + si], al ; 0094014f 0000
+ sbb al, 0x13 ; 00940151 1c13
+ dec dx ; 00940153 4a
+ add [bx + si], dh ; 00940154 0030
+ sbb al, 0x7 ; 00940156 1c07
+ add byte [bx + si], 0x0 ; 00940158 800000
+ add [bx + si], al ; 0094015b 0000
+ o32 adc ecx, [bp + si + 0] ; 0094015d 66134a00
+ xor [si], bl ; 00940161 301c
+ or [bx + si + 0], al ; 00940163 08800000
+ add [bx + si], al ; 00940167 0000
+ mov al, 0x13 ; 00940169 b013
+ dec dx ; 0094016b 4a
+ add [bx + si], dh ; 0094016c 0030
+ sbb al, 0x9 ; 0094016e 1c09
+ add byte [bx + si], 0x0 ; 00940170 800000
+ add [bx + si], al ; 00940173 0000
+ cli ; 00940175 fa
+ adc cx, [bp + si + 0] ; 00940176 134a00
+ xor [si], bl ; 00940179 301c
+ or al, [bx + si + 0] ; 0094017b 0a800000
+ add [bx + si], al ; 0094017f 0000
+ inc sp ; 00940181 44
+ adc al, L16 ; 00940182 14dd
+ add [bx + si], dh ; 00940184 0030
+ sbb al, 0xb ; 00940186 1c0b
+ add byte [bx + si], 0x0 ; 00940188 800000
+ add [bx + si], al ; 0094018b 0000
+ and [di], dx ; 0094018d 2115
+ fld [bx + si] ; 0094018f dd00
+ xor [si], bl ; 00940191 301c
+ or al, 0x80 ; 00940193 0c80
+ add [bx + si], al ; 00940195 0000
+ add [bx + si], al ; 00940197 0000
+ ill_grp_4 ; 00940199 fe15
+ fld [bx + si] ; 0094019b dd00
+ xor [si], bl ; 0094019d 301c
+ or ax, 0x80 ; 0094019f 0d8000
+ add [bx + si], al ; 009401a2 0000
+ add bl, bl ; 009401a4 00db
+ push ss ; 009401a6 16
+ dec bx ; 009401a7 4b
+
+L358:
+ add [bx + si], dh ; 009401a8 0030
+ sbb al, 0xe ; 009401aa 1c0e
+ add byte [bx + si], 0x0 ; 009401ac 800000
+ add [bx + si], al ; 009401af 0000
+ es pop ss ; 009401b1 2617
+ dec bx ; 009401b3 4b
+ add [bx + si], dh ; 009401b4 0030
+ sbb al, 0xf ; 009401b6 1c0f
+ add byte [bx + si], 0x0 ; 009401b8 800000
+
+ .section .codeSection8, @progbits
+ .align 0
+
+ add [bx + si], al ; 00940010 0000
+ push es ; 00940012 06
+ dec bx ; 00940013 4b
+ inc bp ; 00940014 45
+ push dx ; 00940015 52
+ dec si ; 00940016 4e
+ inc bp ; 00940017 45
+ dec sp ; 00940018 4c
+ add al, 0x55 ; 00940019 0455
+ push bx ; 0094001b 53
+ inc bp ; 0094001c 45
+ push dx ; 0094001d 52
+ add ax, [bx + 0x44] ; 0094001e 034744
+ dec cx ; 00940021 49
+ add ax, 0x4853 ; 00940022 055348
+ inc bp ; 00940025 45
+ dec sp ; 00940026 4c
+ dec sp ; 00940027 4c
+ add [bp + di], dl ; 00940028 0013
+ dec bp ; 0094002a 4d
+ imul sp, [bp + di + 0x72], 0x736f ; 0094002b 6963726f73
+ outsw ; 00940030 6f
+ o32 jz L493 ; 00940031 667420
+ push bx ; 00940034 53
+ outsw ; 00940035 6f
+
+L2:
+ insb ; 00940036 6c
+ imul si, [si + 0x61], 0x7269 ; 00940037 6974616972
+ gs add gs:[bx + si], al ; 0094003c 650000
+ add [bx + si], al ; 0094003f 0000
+ add [bx + si], al ; 00940041 0000
+ add [bx + si], al ; 00940043 0000
+ add [bx + si], al ; 00940045 0000
+ add [bx + si], al ; 00940047 0000
+ add [bx + si], al ; 00940049 0000
+ add [bx + si], al ; 0094004b 0000
+ add [bx + si], al ; 0094004d 0000
+ add [bx + si], al ; 0094004f 0000
+ add [bx + si], al ; 00940051 0000
+ add [bx + si], al ; 00940053 0000
+ add [bx + si], al ; 00940055 0000
+ add [bx + si], al ; 00940057 0000
+ add [bx + si], al ; 00940059 0000
+ add [bx + si], al ; 0094005b 0000
+ add [bx + si], al ; 0094005d 0000
+ add [bx + si], al ; 0094005f 0000
+ add [bx + si], al ; 00940061 0000
+ add [bx + si], al ; 00940063 0000
+ add [bx + si], al ; 00940065 0000
+ add [bx + si], al ; 00940067 0000
+ add [bx + si], al ; 00940069 0000
+ add [bx + si], al ; 0094006b 0000
+ add [bx + si], al ; 0094006d 0000
+ add [bx + si], al ; 0094006f 0000
+ add [bx + si], al ; 00940071 0000
+ add [bx + si], al ; 00940073 0000
+ add [bx + si], al ; 00940075 0000
+ add [bx + si], al ; 00940077 0000
+ add [bx + si], al ; 00940079 0000
+ add [bx + si], al ; 0094007b 0000
+ add [bx + si], al ; 0094007d 0000
+ add [bx + si], al ; 0094007f 0000
+ add [bx + si], al ; 00940081 0000
+ add [bx + si], al ; 00940083 0000
+ add [bx + si], al ; 00940085 0000
+ add [bx + si], al ; 00940087 0000
+ add al, cl ; 00940089 00c8
+ sbb [bx + si], al ; 0094008b 1800
+ add [bp + di + 0xc7e], al ; 0094008d 00837e0c
+ add [si + 0x55], dh ; 00940091 007455
+ push word [bp + 0xc] ; 00940094 ff760c
+ push L23 ; 00940097 68f001
+ push L310 ; 0094009a 6a02
+ callf ; 0094009c 9affff0000
+ push word L23 ; 009400a1 ff36f001
+ callf ; 009400a5 9affff0000
+ mov [bp + 0xffffffec], ax ; 009400aa 8946ec
+ push word L23 ; 009400ad ff36f001
+ push 0x0 ; 009400b1 6a00
+ push 0x0 ; 009400b3 6a00
+ push 0x0 ; 009400b5 6a00
+ push 0x0 ; 009400b7 6a00
+ push 0x0 ; 009400b9 6a00
+ push 0x43 ; 009400bb 6a43
+ callf ; 009400bd 9affff0000
+ push word L23 ; 009400c2 ff36f001
+ callf ; 009400c6 9affff0000
+ or ax, ax ; 009400cb 0bc0
+ jz L8 ; 009400cd 740d
+ push word L23 ; 009400cf ff36f001
+ push 0x9 ; 009400d3 6a09
+ callf ; 009400d5 9affff0000
+ jmp short L494 ; 009400da eb08
+ push word [bp + 0xffffffec] ; 009400dc ff76ec
+ callf ; 009400df 9affff0000
+ xor ax, ax ; 009400e4 33c0
+ jmp L495 ; 009400e6 e98200
+ o32 push dword [bp + 0xc] ; 009400e9 66ff760c
+ o32 push dword [bp + 0x8] ; 009400ed 66ff7608
+ push word [bp + 0x6] ; 009400f1 ff7606
+ push cs ; 009400f4 0e
+ call L496 ; 009400f5 e87800
+ or ax, ax ; 009400f8 0bc0
+ jz L494 ; 009400fa 74e8
+ push 0x29 ; 009400fc 6a29
+ callf ; 009400fe 9affff0000
+ push ax ; 00940103 50
+ push ds ; 00940104 1e
+ push 0x3c ; 00940105 683c00
+ callf ; 00940108 9affff0000
+ mov [bp + 0xffffffe8], ax ; 0094010d 8946e8
+ mov [bp + 0xffffffea], dx ; 00940110 8956ea
+ or dx, ax ; 00940113 0bd0
+ jz L497 ; 00940115 7407
+ push L4 ; 00940117 6a01
+ push L4 ; 00940119 6a01
+ call far oword [bp + 0xffffffe8] ; 0094011b ff5ee8
+ lea ax, [bp + 0xffffffee] ; 0094011e 8d46ee
+ push ss ; 00940121 16
+ push ax ; 00940122 50
+ push 0x0 ; 00940123 6a00
+ push 0x0 ; 00940125 6a00
+ push 0x0 ; 00940127 6a00
+ callf ; 00940129 9ac8000000
+ or ax, ax ; 0094012e 0bc0
+ jz L498 ; 00940130 7428
+ lea ax, [bp + 0xffffffee] ; 00940132 8d46ee
+ push ss ; 00940135 16
+ push ax ; 00940136 50
+ callf ; 00940137 9affff0000
+ lea ax, [bp + 0xffffffee] ; 0094013c 8d46ee
+ push ss ; 0094013f 16
+ push ax ; 00940140 50
+ callf ; 00940141 9affff0000
+ lea ax, [bp + 0xffffffee] ; 00940146 8d46ee
+ push ss ; 00940149 16
+ push ax ; 0094014a 50
+ push 0x0 ; 0094014b 6a00
+ push 0x0 ; 0094014d 6a00
+ push 0x0 ; 0094014f 6a00
+ callf ; 00940151 9affff0000
+ or ax, ax ; 00940156 0bc0
+ jnz L499 ; 00940158 75d8
+ o32 cmp dword [bp + 0xffffffe8], byte 0x0 ; 0094015a 66837ee800
+ jz L500 ; 0094015f 7407
+ push L4 ; 00940161 6a01
+ push 0x0 ; 00940163 6a00
+ call far oword [bp + 0xffffffe8] ; 00940165 ff5ee8
+ mov ax, [bp + 0xfffffff2] ; 00940168 8b46f2
+ leave ; 0094016b c9
+ retf 0x0a ; 0094016c ca0a00
+ nop ; 0094016f 90
+ enter 0x72, 0x0 ; 00940170 c8720000
+ mov ax, [bp + 0xe] ; 00940174 8b460e
+ mov [0x2b0], ax ; 00940177 a3b002
+ push 0x200 ; 0094017a 680002
+ push 0x12c ; 0094017d 682c01
+ callf ; 00940180 9a2806d401
+ push ds ; 00940185 1e
+ push L84 ; 00940186 686802
+ push ds ; 00940189 1e
+ push L82 ; 0094018a 686a02
+ callf ; 0094018d 9a0000ffff
+ or ax, ax ; 00940192 0bc0
+ jz L501 ; 00940194 741d
+ push 0x0 ; 00940196 6a00
+ push 0x0 ; 00940198 6a00
+ push 0x7f00 ; 0094019a 68007f
+ callf ; 0094019d 9affff0000
+ mov [bp + 0xffffffb4], ax ; 009401a2 8946b4
+ push 0x0 ; 009401a5 6a00
+ callf ; 009401a7 9affff0000
+ mov [bp + 0xffffffd8], ax ; 009401ac 8946d8
+ or ax, ax ; 009401af 0bc0
+ jnz L502 ; 009401b1 7503
+ jmp L503 ; 009401b3 e99802
+ push ax ; 009401b6 50
+ lea ax, [bp + 0xffffffb8] ; 009401b7 8d46b8
+ push ss ; 009401ba 16
+ push ax ; 009401bb 50
+ callf ; 009401bc 9affff0000
+ mov ax, [bp + 0xffffffb8] ; 009401c1 8b46b8
+ mov [0x23e], ax ; 009401c4 a33e02
+ mov ax, [bp + 0xffffffc4] ; 009401c7 8b46c4
+ mov [0x23c], ax ; 009401ca a33c02
+ push word [bp + 0xffffffd8] ; 009401cd ff76d8
+ push L59 ; 009401d0 6a18
+ callf ; 009401d2 9a5e010000
+ cmp ax, L310 ; 009401d7 3d0200
+ jnz L504 ; 009401da 7506
+ mov word L36, L4 ; 009401dc c706f6010100
+ push word [bp + 0xffffffd8] ; 009401e2 ff76d8
+ push 0x8 ; 009401e5 6a08
+ callf ; 009401e7 9a6b010000
+ mov [0x24c], ax ; 009401ec a34c02
+ push word [bp + 0xffffffd8] ; 009401ef ff76d8
+ push 0xa ; 009401f2 6a0a
+ callf ; 009401f4 9affff0000
+ mov [0x24e], ax ; 009401f9 a34e02
+ cmp ax, 0x12c ; 009401fc 3d2c01
+ jge L505 ; 009401ff 7d05
+ mov ax, L4 ; 00940201 b80100
+ jmp short L506 ; 00940204 eb02
+ xor ax, ax ; 00940206 33c0
+ mov [0x38], ax ; 00940208 a33800
+ or ax, ax ; 0094020b 0bc0
+ jz L507 ; 0094020d 740c
+ mov cx, L310 ; 0094020f b90200
+ mov ax, [0x26a] ; 00940212 a16a02
+ cwd ; 00940215 99
+ idiv cx, ax ; 00940216 f7f9
+ mov [0x26a], ax ; 00940218 a36a02
+ push 0x0 ; 0094021b 6a00
+ push word [bp + 0xffffffd8] ; 0094021d ff76d8
+ callf ; 00940220 9affff0000
+ cmp word L36, byte 0x0 ; 00940225 833ef60100
+ jz L508 ; 0094022a 7408
+ mov ax, 0xffff ; 0094022c b8ffff
+ mov dx, 0xff ; 0094022f baff00
+ jmp short L509 ; 00940232 eb05
+ mov ax, 0x8000 ; 00940234 b80080
+ xor dx, dx ; 00940237 33d2
+ mov [0x2b2], ax ; 00940239 a3b202
+ mov L42, dx ; 0094023c 8916b402
+ push dx ; 00940240 52
+ push ax ; 00940241 50
+ callf ; 00940242 9affff0000
+ mov [0x266], ax ; 00940247 a36602
+ callf ; 0094024a 9affff0000
+ push ax ; 0094024f 50
+ callf ; 00940250 9a3201ffff
+ pop bx ; 00940255 5b
+ push 0x26e ; 00940256 686e02
+ push 0x64 ; 00940259 6a64
+ callf ; 0094025b 9a2806de01
+ push 0x250 ; 00940260 685002
+ push 0x65 ; 00940263 6a65
+ callf ; 00940265 9a2806e901
+ lea ax, [bp + 0xffffff98] ; 0094026a 8d4698
+ push ax ; 0094026d 50
+ push 0x67 ; 0094026e 6a67
+ callf ; 00940270 9a2806ffff
+ lea ax, [bp + 0xffffff98] ; 00940275 8d4698
+ push ss ; 00940278 16
+ push ax ; 00940279 50
+ callf ; 0094027a 9affff0000
+ mov [0x1f8], ax ; 0094027f a3f801
+ mov word [bp + 0xffffffb2], 0x00 ; 00940282 c746b20000
+ o32 mov eax, [bp + 0x8] ; 00940287 668b4608
+ mov dx, [bp + 0xa] ; 0094028b 8b560a
+ o32 mov [bp + 0xffffffae], eax ; 0094028e 668946ae
+ mov es, dx ; 00940292 8ec2
+ mov bx, ax ; 00940294 8bd8
+ es cmp byte es:[bx], 0x0 ; 00940296 26803f00
+ jz L365 ; 0094029a 7420
+ es cmp byte es:[bx], 0x2f ; 0094029c 26803f2f
+ jnz L510 ; 009402a0 7507
+ es cmp byte es:[bx + 0x1], 0x49 ; 009402a2 26807f0149
+ jz L511 ; 009402a7 740e
+ inc word [bp + 0xffffffae] ; 009402a9 ff46ae
+ mov bx, [bp + 0xffffffae] ; 009402ac 8b5eae
+ es cmp byte es:[bx], 0x0 ; 009402af 26803f00
+ jnz L512 ; 009402b3 75e7
+ jmp short L365 ; 009402b5 eb05
+ mov word [bp + 0xffffffb2], L4 ; 009402b7 c746b20100
+ cmp word [bp + 0xc], byte 0x0 ; 009402bc 837e0c00
+ jnz L513 ; 009402c0 7556
+ mov word [bp + 0xffffffe6], 0x2008 ; 009402c2 c746e60820
+ mov word [bp + 0xffffffe8], 0x40c ; 009402c7 c746e80c04
+ mov word [bp + 0xffffffea], 0xffff ; 009402cc c746eaffff
+ o32 mov dword [bp + 0xffffffec], 0x0000 ; 009402d1 66c746ec00000000
+ mov ax, [0x2b0] ; 009402d9 a1b002
+ mov [bp + 0xfffffff0], ax ; 009402dc 8946f0
+ push ax ; 009402df 50
+ push ds ; 009402e0 1e
+ push L12 ; 009402e1 684b00
+ callf ; 009402e4 9affff00d4
+
+ .section .codeSection9, @progbits
+ .align 0
+
+ add [bx + si], al ; 00940011 0000
+ add [bx + si], al ; 00940013 0000
+ add [bx + si], al ; 00940015 0000
+ add [bx + si], al ; 00940017 0000
+ add [bx + si], al ; 00940019 0000
+ add [bx + si], al ; 0094001b 0000
+ add [bx + si], al ; 0094001d 0000
+ add [bx + si], al ; 0094001f 0000
+ add [bx + si], al ; 00940021 0000
+ add [bx + si], al ; 00940023 0000
+ add [bx + si], al ; 00940025 0000
+ add [bx + si], al ; 00940027 0000
+ add [bx + si], al ; 00940029 0000
+ add [bx + si], al ; 0094002b 0000
+ add [bx + si], al ; 0094002d 0000
+ add [bx + si], al ; 0094002f 0000
+ add [bx + si], al ; 00940031 0000
+ add [bx + si], al ; 00940033 0000
+ add [bx + si], al ; 00940035 0000
+ add [bx + si], al ; 00940037 0000
+ add [bx + si], al ; 00940039 0000
+ add [bx + si], al ; 0094003b 0000
+ add [bx + si], al ; 0094003d 0000
+ add [bx + si], al ; 0094003f 0000
+ add [bx + si], al ; 00940041 0000
+ add [bx + si], al ; 00940043 0000
+ add [bx + si], al ; 00940045 0000
+ add [bx + si], al ; 00940047 0000
+ add [bx + si], al ; 00940049 0000
+ add [bx + si], al ; 0094004b 0000
+ add [bx + si], al ; 0094004d 0000
+ add [bx + si], al ; 0094004f 0000
+ add [bx + si], al ; 00940051 0000
+ enter L59, 0x0 ; 00940053 c8180000
+ cmp word [bp + 0xc], byte 0x0 ; 00940057 837e0c00
+ jz L514 ; 0094005b 7455
+ push word [bp + 0xc] ; 0094005d ff760c
+ push L23 ; 00940060 68f001
+ push L310 ; 00940063 6a02
+ callf ; 00940065 9affff0000
+ push word L23 ; 0094006a ff36f001
+ callf ; 0094006e 9affff0000
+ mov [bp + 0xffffffec], ax ; 00940073 8946ec
+ push word L23 ; 00940076 ff36f001
+ push 0x0 ; 0094007a 6a00
+ push 0x0 ; 0094007c 6a00
+ push 0x0 ; 0094007e 6a00
+ push 0x0 ; 00940080 6a00
+ push 0x0 ; 00940082 6a00
+ push 0x43 ; 00940084 6a43
+ callf ; 00940086 9affff0000
+ push word L23 ; 0094008b ff36f001
+ callf ; 0094008f 9affff0000
+ or ax, ax ; 00940094 0bc0
+ jz L515 ; 00940096 740d
+ push word L23 ; 00940098 ff36f001
+ push 0x9 ; 0094009c 6a09
+ callf ; 0094009e 9affff0000
+
+L465:
+ jmp short L516 ; 009400a3 eb08
+ push word [bp + 0xffffffec] ; 009400a5 ff76ec
+ callf ; 009400a8 9affff0000
+ xor ax, ax ; 009400ad 33c0
+ jmp L517 ; 009400af e98200
+ o32 push dword [bp + 0xc] ; 009400b2 66ff760c
+ o32 push dword [bp + 0x8] ; 009400b6 66ff7608
+ push word [bp + 0x6] ; 009400ba ff7606
+ push cs ; 009400bd 0e
+ call L518 ; 009400be e87800
+ or ax, ax ; 009400c1 0bc0
+ jz L516 ; 009400c3 74e8
+ push 0x29 ; 009400c5 6a29
+ callf ; 009400c7 9affff0000
+ push ax ; 009400cc 50
+ push ds ; 009400cd 1e
+ push 0x3c ; 009400ce 683c00
+ callf ; 009400d1 9affff0000
+ mov [bp + 0xffffffe8], ax ; 009400d6 8946e8
+ mov [bp + 0xffffffea], dx ; 009400d9 8956ea
+ or dx, ax ; 009400dc 0bd0
+ jz L519 ; 009400de 7407
+ push L4 ; 009400e0 6a01
+ push L4 ; 009400e2 6a01
+ call far oword [bp + 0xffffffe8] ; 009400e4 ff5ee8
+ lea ax, [bp + 0xffffffee] ; 009400e7 8d46ee
+ push ss ; 009400ea 16
+ push ax ; 009400eb 50
+ push 0x0 ; 009400ec 6a00
+ push 0x0 ; 009400ee 6a00
+ push 0x0 ; 009400f0 6a00
+ callf ; 009400f2 9ac8000000
+ or ax, ax ; 009400f7 0bc0
+ jz L520 ; 009400f9 7428
+ lea ax, [bp + 0xffffffee] ; 009400fb 8d46ee
+ push ss ; 009400fe 16
+ push ax ; 009400ff 50
+ callf ; 00940100 9affff0000
+ lea ax, [bp + 0xffffffee] ; 00940105 8d46ee
+ push ss ; 00940108 16
+ push ax ; 00940109 50
+ callf ; 0094010a 9affff0000
+ lea ax, [bp + 0xffffffee] ; 0094010f 8d46ee
+ push ss ; 00940112 16
+ push ax ; 00940113 50
+ push 0x0 ; 00940114 6a00
+ push 0x0 ; 00940116 6a00
+ push 0x0 ; 00940118 6a00
+ callf ; 0094011a 9affff0000
+ or ax, ax ; 0094011f 0bc0
+ jnz L521 ; 00940121 75d8
+ o32 cmp dword [bp + 0xffffffe8], byte 0x0 ; 00940123 66837ee800
+ jz L522 ; 00940128 7407
+ push L4 ; 0094012a 6a01
+ push 0x0 ; 0094012c 6a00
+ call far oword [bp + 0xffffffe8] ; 0094012e ff5ee8
+ mov ax, [bp + 0xfffffff2] ; 00940131 8b46f2
+ leave ; 00940134 c9
+ retf 0x0a ; 00940135 ca0a00
+ nop ; 00940138 90
+ enter 0x72, 0x0 ; 00940139 c8720000
+ mov ax, [bp + 0xe] ; 0094013d 8b460e
+ mov [0x2b0], ax ; 00940140 a3b002
+ push 0x200 ; 00940143 680002
+ push 0x12c ; 00940146 682c01
+ callf ; 00940149 9a2806d401
+ push ds ; 0094014e 1e
+ push L84 ; 0094014f 686802
+ push ds ; 00940152 1e
+ push L82 ; 00940153 686a02
+ callf ; 00940156 9a0000ffff
+ or ax, ax ; 0094015b 0bc0
+ jz L523 ; 0094015d 741d
+ push 0x0 ; 0094015f 6a00
+ push 0x0 ; 00940161 6a00
+ push 0x7f00 ; 00940163 68007f
+ callf ; 00940166 9affff0000
+ mov [bp + 0xffffffb4], ax ; 0094016b 8946b4
+ push 0x0 ; 0094016e 6a00
+ callf ; 00940170 9affff0000
+ mov [bp + 0xffffffd8], ax ; 00940175 8946d8
+ or ax, ax ; 00940178 0bc0
+ jnz L524 ; 0094017a 7503
+ jmp L525 ; 0094017c e99802
+ push ax ; 0094017f 50
+ lea ax, [bp + 0xffffffb8] ; 00940180 8d46b8
+ push ss ; 00940183 16
+ push ax ; 00940184 50
+ callf ; 00940185 9affff0000
+ mov ax, [bp + 0xffffffb8] ; 0094018a 8b46b8
+ mov [0x23e], ax ; 0094018d a33e02
+ mov ax, [bp + 0xffffffc4] ; 00940190 8b46c4
+ mov [0x23c], ax ; 00940193 a33c02
+ push word [bp + 0xffffffd8] ; 00940196 ff76d8
+ push L59 ; 00940199 6a18
+ callf ; 0094019b 9a5e010000
+ cmp ax, L310 ; 009401a0 3d0200
+ jnz L526 ; 009401a3 7506
+ mov word L36, L4 ; 009401a5 c706f6010100
+ push word [bp + 0xffffffd8] ; 009401ab ff76d8
+ push 0x8 ; 009401ae 6a08
+ callf ; 009401b0 9a6b010000
+ mov [0x24c], ax ; 009401b5 a34c02
+ push word [bp + 0xffffffd8] ; 009401b8 ff76d8
+ push 0xa ; 009401bb 6a0a
+ callf ; 009401bd 9affff0000
+ mov [0x24e], ax ; 009401c2 a34e02
+ cmp ax, 0x12c ; 009401c5 3d2c01
+ jge L527 ; 009401c8 7d05
+ mov ax, L4 ; 009401ca b80100
+ jmp short L528 ; 009401cd eb02
+ xor ax, ax ; 009401cf 33c0
+ mov [0x38], ax ; 009401d1 a33800
+ or ax, ax ; 009401d4 0bc0
+ jz L529 ; 009401d6 740c
+ mov cx, L310 ; 009401d8 b90200
+ mov ax, [0x26a] ; 009401db a16a02
+ cwd ; 009401de 99
+ idiv cx, ax ; 009401df f7f9
+ mov [0x26a], ax ; 009401e1 a36a02
+ push 0x0 ; 009401e4 6a00
+ push word [bp + 0xffffffd8] ; 009401e6 ff76d8
+ callf ; 009401e9 9affff0000
+ cmp word L36, byte 0x0 ; 009401ee 833ef60100
+ jz L530 ; 009401f3 7408
+ mov ax, 0xffff ; 009401f5 b8ffff
+ mov dx, 0xff ; 009401f8 baff00
+ jmp short L474 ; 009401fb eb05
+ mov ax, 0x8000 ; 009401fd b80080
+ xor dx, dx ; 00940200 33d2
+ mov [0x2b2], ax ; 00940202 a3b202
+ mov L42, dx ; 00940205 8916b402
+ push dx ; 00940209 52
+ push ax ; 0094020a 50
+ callf ; 0094020b 9affff0000
+ mov [0x266], ax ; 00940210 a36602
+ callf ; 00940213 9affff0000
+ push ax ; 00940218 50
+ callf ; 00940219 9a3201ffff
+ pop bx ; 0094021e 5b
+ push 0x26e ; 0094021f 686e02
+ push 0x64 ; 00940222 6a64
+ callf ; 00940224 9a2806de01
+ push 0x250 ; 00940229 685002
+ push 0x65 ; 0094022c 6a65
+ callf ; 0094022e 9a2806e901
+ lea ax, [bp + 0xffffff98] ; 00940233 8d4698
+ push ax ; 00940236 50
+ push 0x67 ; 00940237 6a67
+ callf ; 00940239 9a2806ffff
+ lea ax, [bp + 0xffffff98] ; 0094023e 8d4698
+ push ss ; 00940241 16
+ push ax ; 00940242 50
+ callf ; 00940243 9affff0000
+ mov [0x1f8], ax ; 00940248 a3f801
+ mov word [bp + 0xffffffb2], 0x00 ; 0094024b c746b20000
+ o32 mov eax, [bp + 0x8] ; 00940250 668b4608
+ mov dx, [bp + 0xa] ; 00940254 8b560a
+ o32 mov [bp + 0xffffffae], eax ; 00940257 668946ae
+ mov es, dx ; 0094025b 8ec2
+ mov bx, ax ; 0094025d 8bd8
+ es cmp byte es:[bx], 0x0 ; 0094025f 26803f00
+ jz L531 ; 00940263 7420
+ es cmp byte es:[bx], 0x2f ; 00940265 26803f2f
+ jnz L363 ; 00940269 7507
+ es cmp byte es:[bx + 0x1], 0x49 ; 0094026b 26807f0149
+ jz L532 ; 00940270 740e
+ inc word [bp + 0xffffffae] ; 00940272 ff46ae
+ mov bx, [bp + 0xffffffae] ; 00940275 8b5eae
+ es cmp byte es:[bx], 0x0 ; 00940278 26803f00
+ jnz L533 ; 0094027c 75e7
+ jmp short L531 ; 0094027e eb05
+ mov word [bp + 0xffffffb2], L4 ; 00940280 c746b20100
+ cmp word [bp + 0xc], byte 0x0 ; 00940285 837e0c00
+ jnz L534 ; 00940289 7556
+ mov word [bp + 0xffffffe6], 0x2008 ; 0094028b c746e60820
+ mov word [bp + 0xffffffe8], 0x40c ; 00940290 c746e80c04
+ mov word [bp + 0xffffffea], 0xffff ; 00940295 c746eaffff
+ o32 mov dword [bp + 0xffffffec], 0x0000 ; 0094029a 66c746ec00000000
+ mov ax, [0x2b0] ; 009402a2 a1b002
+ mov [bp + 0xfffffff0], ax ; 009402a5 8946f0
+ push ax ; 009402a8 50
+ push ds ; 009402a9 1e
+ push L12 ; 009402aa 684b00
+ callf ; 009402ad 9affff0000
+ mov [bp + 0xfffffff2], ax ; 009402b2 8946f2
+ mov ax, [bp + 0xffffffb4] ; 009402b5 8b46b4
+ mov [bp + 0xfffffff4], ax ; 009402b8 8946f4
+ mov ax, [0x266] ; 009402bb a16602
+ mov [bp + 0xfffffff6], ax ; 009402be 8946f6
+ o32 mov dword [bp + 0xfffffff8], L4 ; 009402c1 66c746f801000000
+ mov word [bp + 0xfffffffc], 0x22 ; 009402c9 c746fc2200
+ mov word [bp + 0xfffffffe], ds ; 009402ce 8c5efe
+ lea ax, [bp + 0xffffffe6] ; 009402d1 8d46e6
+ push ss ; 009402d4 16
+ push ax ; 009402d5 50
+ callf ; 009402d6 9affff0000
+ or ax, ax ; 009402db 0bc0
+ je L525 ; 009402dd 0f843601
+ mov ax, [0x268] ; 009402e1 a16802
+ imul cx, ax, 0x7 ; 009402e4 6bc807
+ cwd ; 009402e7 99
+ and dx, byte 0x7 ; 009402e8 83e207
+ add ax, dx ; 009402eb 03c2
+ sar ax, byte 0x3 ; 009402ed c1f803
+ add ax, 0x03 ; 009402f0 050300
+ mov [0x240], ax ; 009402f3 a34002
+ shl ax, byte 0x3 ; 009402f6 c1e003
+ add cx, ax ; 009402f9 03c8
+ mov [bp + 0xffffff92], cx ; 009402fb 894e92
+ mov ax, [0x26a] ; 009402fe a16a02
+ shl ax, L310 ; 00940301 c1e002
+ mov [bp + 0xffffff94], ax ; 00940304 894694
+ o32 mov dword [bp + 0xffffff8e], 0x0000 ; 00940307 66c7468e00000000
+ lea ax, [bp + 0xffffff8e] ; 0094030f 8d468e
+ push ss ; 00940312 16
+ push ax ; 00940313 50
+ push 0xcf ; 00940314 68cf00
+ push 0x0 ; 00940317 6a00
+ push L4 ; 00940319 6a01
+ push 0x0 ; 0094031b 6a00
+ push 0x200 ; 0094031d 680002
+ callf ; 00940320 9affff0000
+ mov ax, [bp + 0xffffff8e] ; 00940325 8b468e
+ sub [bp + 0xffffff92], ax ; 00940328 294692
+ mov ax, [0x24e] ; 0094032b a14e02
+ mov cx, [bp + 0xffffff90] ; 0094032e 8b4e90
+ sub [bp + 0xffffff94], cx ; 00940331 294e94
+ cmp [bp + 0xffffff94], ax ; 00940334 394694
+ jle L535 ; 00940337 7e03
+ mov [bp + 0xffffff94], ax ; 00940339 894694
+ push 0x0 ; 0094033c 6a00
+ push 0x200 ; 0094033e 680002
+ push ds ; 00940341 1e
+ push 0x22 ; 00940342 682200
+ push ds ; 00940345 1e
+ push 0x26e ; 00940346 686e02
+ cmp word [bp + 0xffffffb2], byte 0x0 ; 00940349 837eb200
+ jz L536 ; 0094034d 7407
+ xor ax, ax ; 0094034f 33c0
+ mov dx, 0x22cf ; 00940351 bacf22
+ jmp short L537 ; 00940354 eb05
+ xor ax, ax ; 00940356 33c0
+ mov dx, 0x2cf ; 00940358 bacf02
+ push dx ; 0094035b 52
+ push ax ; 0094035c 50
+ push 0x8000 ; 0094035d 680080
+ push ax ; 00940360 50
+ push word [bp + 0xffffff92] ; 00940361 ff7692
+ push word [bp + 0xffffff94] ; 00940364 ff7694
+ push ax ; 00940367 50
+ push ax ; 00940368 50
+ push word L51 ; 00940369 ff36b002
+ push ax ; 0094036d 50
+ push ax ; 0094036e 50
+ callf ; 0094036f 9affff0000
+ or ax, ax ; 00940374 0bc0
+ je L525 ; 00940376 0f849d00
+ lea ax, [bp + 0xffffffac] ; 0094037a 8d46ac
+ push ax ; 0094037d 50
+ push cs ; 0094037e 0e
+ call L538 ; 0094037f e8d105
+ push 0x245 ; 00940382 684502
+ push 0x85a ; 00940385 685a08
+ push word [bp + 0xe] ; 00940388 ff760e
+ callf ; 0094038b 9affff0000
+ mov [0x1f2], ax ; 00940390 a3f201
+ mov L53, dx ; 00940393 8916f401
+ mov ax, dx ; 00940397 8bc2
+ or ax, L54 ; 00940399 0b06f201
+ jz L539 ; 0094039d 747d
+ push word L23 ; 0094039f ff36f001
+ o32 push 0x29a00fa ; 009403a3 6668fa009a02
+ push dx ; 009403a9 52
+ push word L54 ; 009403aa ff36f201
+ callf ; 009403ae 9affff0000
+ or ax, ax ; 009403b3 0bc0
+ jz L525 ; 009403b5 7460
+ callf ; 009403b7 9a24026f03
+ push word [bp + 0xffffffac] ; 009403bc ff76ac
+ callf ; 009403bf 9ac6000b05
+ push word L23 ; 009403c4 ff36f001
+ push word [bp + 0x6] ; 009403c8 ff7606
+ callf ; 009403cb 9a4c000000
+ push word L23 ; 009403d0 ff36f001
+ callf ; 009403d4 9affff0000
+ cmp word [bp + 0xc], L4 ; 009403d9 837e0c01
+
+L126:
+ sbb ax, ax ; 009403dd 1bc0
+ neg ax ; 009403df f7d8
+ push ax ; 009403e1 50
+ callf ; 009403e2 9a00009e03
+ cmp word L1, byte 0x0 ; 009403e7 833e2c0000
+ jz L540 ; 009403ec 7405
+ callf ; 009403ee 9a6600ffff
+ cmp word [bp + 0x6], byte 0x7 ; 009403f3 837e0607
+ jz L541 ; 009403f7 7419
+ cmp word [bp + 0x6], byte 0x6 ; 009403f9 837e0606
+ jz L541 ; 009403fd 7413
+ push word L23 ; 009403ff ff36f001
+ o32 push 0x11103e8 ; 00940403 6668e8031101
+ push 0x0 ; 00940409 6a00
+ push 0x0 ; 0094040b 6a00
+ callf ; 0094040d 9acb040000
+ mov ax, L4 ; 00940412 b80100
+ jmp short L542 ; 00940415 eb07
+ callf ; 00940417 9a1806f900
+ xor ax, ax ; 0094041c 33c0
+ leave ; 0094041e c9
+ retf 0x0a ; 0094041f ca0a00
+ nop ; 00940422 90
+ enter L345, 0x0 ; 00940423 c8200000
+ push word [bp + 0x6] ; 00940427 ff7606
+ lea ax, [bp + 0xffffffe0] ; 0094042a 8d46e0
+ push ss ; 0094042d 16
+ push ax ; 0094042e 50
+ callf ; 0094042f 9affff0000
+ cmp word L59, byte 0x0 ; 00940434 833e180000
+ jz L543 ; 00940439 7412
+ push word L59 ; 0094043b ff361800
+ push 0x7 ; 0094043f 6a07
+ lea ax, [bp + 0xffffffe0] ; 00940441 8d46e0
+ push ax ; 00940444 50
+ push 0x0 ; 00940445 6a00
+ mov bx, L59 ; 00940447 8b1e1800
+ call far oword [bx] ; 0094044b ff1f
+ push word [bp + 0x6] ; 0094044d ff7606
+ lea ax, [bp + 0xffffffe0] ; 00940450 8d46e0
+ push ss ; 00940453 16
+ push ax ; 00940454 50
+ callf ; 00940455 9affff0000
+ leave ; 0094045a c9
+ retf L310 ; 0094045b ca0200
+ nop ; 0094045e 90
+ enter 0xd6, 0x0 ; 0094045f c8d60000
+ mov ax, [bp + 0xc] ; 00940463 8b460c
+ dec ax ; 00940466 48
+ je L544 ; 00940467 0f84bf00
+ dec ax ; 0094046b 48
+ je L545 ; 0094046c 0f84c300
+ dec ax ; 00940470 48
+ je L546 ; 00940471 0f846a01
+ dec ax ; 00940475 48
+ dec ax ; 00940476 48
+ je L547 ; 00940477 0f84f400
+ dec ax ; 0094047b 48
+ je L548 ; 0094047c 0f846701
+ dec ax ; 00940480 48
+ je L549 ; 00940481 0f848701
+ dec ax ; 00940485 48
+ je L550 ; 00940486 0f846f01
+ sub ax, 0x07 ; 0094048a 2d0700
+ je L551 ; 0094048d 0f848901
+ dec ax ; 00940491 48
+ je L552 ; 00940492 0f849901
+ sub ax, 0xf0 ; 00940496 2df000
+ je L553 ; 00940499 0f84b401
+ sub ax, 0x11 ; 0094049d 2d1100
+ je L554 ; 009404a0 0f84c101
+ sub ax, 0x05 ; 009404a4 2d0500
+ je L555 ; 009404a7 0f845302
+ sub ax, 0x09 ; 009404ab 2d0900
+ je L556 ; 009404ae 0f84dc02
+ sub ax, 0xe1 ; 009404b2 2de100
+ je L557 ; 009404b5 0f840303
+ dec ax ; 009404b9 48
+ je L558 ; 009404ba 0f840f03
+ dec ax ; 009404be 48
+ je L559 ; 009404bf 0f842303
+ dec ax ; 009404c3 48
+ je L560 ; 009404c4 0f843403
+ mov ax, [0x1f8] ; 009404c8 a1f801
+ cmp [bp + 0xc], ax ; 009404cb 39460c
+ jne L561 ; 009404ce 0f855403
+ mov ax, [bp + 0xa] ; 009404d2 8b460a
+ dec ax ; 009404d5 48
+ jz L381 ; 009404d6 7409
+ dec ax ; 009404d8 48
+ jz L562 ; 009404d9 7410
+ dec ax ; 009404db 48
+ jz L563 ; 009404dc 7431
+ jmp L561 ; 009404de e94503
+ mov ax, [0x268] ; 009404e1 a16802
+ mov dx, L82 ; 009404e4 8b166a02
+ jmp L47 ; 009404e8 e94b03
+ les bx, ; 009404eb c45e0626ff3726
+ push word [bx + 0x2] ; 009404f2 ff7702
+ es push word es:[bx + 0x4] ; 009404f5 26ff7704
+ es push word es:[bx + 0x6] ; 009404f9 26ff7706
+ es push word es:[bx + 0x8] ; 009404fd 26ff7708
+ o32 push dword es:[bx + 0xa] ; 00940501 6626ff770a
+ callf ; 00940506 9a5a031005
+ cwd ; 0094050b 99
+ jmp L47 ; 0094050c e92703
+ push word L23 ; 0094050f ff36f001
+ o32 push 0x112f060 ; 00940513 666860f01201
+ push 0x0 ; 00940519 6a00
+ push 0x0 ; 0094051b 6a00
+ callf ; 0094051d 9affff0000
+ mov ax, L4 ; 00940522 b80100
+ xor dx, dx ; 00940525 33d2
+ jmp L47 ; 00940527 e90c03
+ mov ax, [bp + 0xe] ; 0094052a 8b460e
+ mov [0x1f0], ax ; 0094052d a3f001
+ jmp L561 ; 00940530 e9f302
+ push word L23 ; 00940533 ff36f001
+ push 0x29a ; 00940537 689a02
+ callf ; 0094053a 9affff0000
+ o32 push dword L54 ; 0094053f 66ff36f201
+ callf ; 00940544 9affff0000
+ push word L59 ; 00940549 ff361800
+ push L4 ; 0094054d 6a01
+ push 0x0 ; 0094054f 6a00
+ push 0x0 ; 00940551 6a00
+ mov bx, L59 ; 00940553 8b1e1800
+ call far oword [bx] ; 00940557 ff1f
+ push L4 ; 00940559 6a01
+ callf ; 0094055b 9ac600ffff
+ callf ; 00940560 9a78080601
+ push 0x0 ; 00940565 6a00
+ callf ; 00940567 9affff0000
+ jmp L561 ; 0094056c e9b702
+ push word [bp + 0xe] ; 0094056f ff760e
+
+L22:
+ callf ; 00940572 9a3d000000
+ mov [0x14], ax ; 00940577 a31400
+ push word [bp + 0xe] ; 0094057a ff760e
+ push ds ; 0094057d 1e
+ push 0x244 ; 0094057e 684402
+ callf ; 00940581 9affff0000
+ imul ax, L84, 0x7 ; 00940586 6b06680207
+ sub ax, [bp + 0x6] ; 0094058b 2b4606
+ neg ax ; 0094058e f7d8
+ cwd ; 00940590 99
+ and dx, byte 0x7 ; 00940591 83e207
+ add ax, dx ; 00940594 03c2
+ sar ax, byte 0x3 ; 00940596 c1f803
+ mov [bp + 0xffffff92], ax ; 00940599 894692
+ mov ax, [0x268] ; 0094059c a16802
+ cwd ; 0094059f 99
+ and dx, byte 0x7 ; 009405a0 83e207
+ add ax, dx ; 009405a3 03c2
+ sar ax, byte 0x3 ; 009405a5 c1f803
+ add ax, 0x03 ; 009405a8 050300
+ mov [bp + 0xffffff90], ax ; 009405ab 894690
+ cmp [bp + 0xffffff92], ax ; 009405ae 394692
+ jge L564 ; 009405b1 7d0e
+ mov ax, [0x240] ; 009405b3 a14002
+ cmp [bp + 0xffffff90], ax ; 009405b6 394690
+ jz L564 ; 009405b9 7406
+ mov ax, [bp + 0xffffff90] ; 009405bb 8b4690
+ mov [bp + 0xffffff92], ax ; 009405be 894692
+ mov ax, [bp + 0xffffff92] ; 009405c1 8b4692
+ cmp [bp + 0xffffff90], ax ; 009405c4 394690
+ jg L546 ; 009405c7 7f16
+ mov [0x240], ax ; 009405c9 a34002
+ callf ; 009405cc 9aa001ffff
+ push word [bp + 0xe] ; 009405d1 ff760e
+ push 0x0 ; 009405d4 6a00
+ push 0x0 ; 009405d6 6a00
+ push L4 ; 009405d8 6a01
+ callf ; 009405da 9affff0000
+ callf ; 009405df 9aca019203
+ jmp L561 ; 009405e4 e93f02
+ cmp word [bp + 0xa], byte 0x0 ; 009405e7 837e0a00
+ je L561 ; 009405eb 0f843702
+ push word [bp + 0xe] ; 009405ef ff760e
+ push cs ; 009405f2 0e
+ call L565 ; 009405f3 e82dfe
+ jmp L561 ; 009405f6 e92d02
+ mov bx, L59 ; 009405f9 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 009405fd 837f2600
+ jz L549 ; 00940601 7409
+ push bx ; 00940603 53
+ push 0x4 ; 00940604 6a04
+ push 0x0 ; 00940606 6a00
+ push L4 ; 00940608 6a01
+ call far oword [bx] ; 0094060a ff1f
+ cmp word [bp + 0xc], byte 0x7 ; 0094060c 837e0c07
+ jne L566 ; 00940610 0f850a02
+ mov ax, L4 ; 00940614 b80100
+ jmp L567 ; 00940617 e90602
+ cmp word L178, byte 0x0 ; 0094061a 833e140000
+ jne L561 ; 0094061f 0f850302
+ push word [bp + 0xe] ; 00940623 ff760e
+ push cs ; 00940626 0e
+ call L565 ; 00940627 e8f9fd
+ xor ax, ax ; 0094062a 33c0
+ jmp L568 ; 0094062c e9f6fe
+ lea ax, [bp + 0xffffff94] ; 0094062f 8d4694
+ push ax ; 00940632 50
+ push 0x69 ; 00940633 6a69
+ callf ; 00940635 9a2806c703
+ push word L23 ; 0094063a ff36f001
+ lea ax, [bp + 0xffffff94] ; 0094063e 8d4694
+ push ss ; 00940641 16
+ push ax ; 00940642 50
+ push L310 ; 00940643 6a02
+ push 0x0 ; 00940645 6a00
+ push 0x0 ; 00940647 6a00
+ callf ; 00940649 9affff0000
+ jmp L561 ; 0094064e e9d501
+ push word L59 ; 00940651 ff361800
+ push L310 ; 00940655 6a02
+ push word [bp + 0xa] ; 00940657 ff760a
+ push 0x0 ; 0094065a 6a00
+ mov bx, L59 ; 0094065c 8b1e1800
+ call far oword [bx] ; 00940660 ff1f
+ jmp L561 ; 00940662 e9c101
+ mov ax, [bp + 0xa] ; 00940665 8b460a
+ inc ax ; 00940668 40
+ jz L569 ; 00940669 7419
+ sub ax, 0x3e9 ; 0094066b 2de903
+ jz L27 ; 0094066e 741e
+ dec ax ; 00940670 48
+ jz L570 ; 00940671 7426
+ dec ax ; 00940673 48
+ jz L571 ; 00940674 742d
+ dec ax ; 00940676 48
+ jz L572 ; 00940677 7432
+ dec ax ; 00940679 48
+ jz L573 ; 0094067a 7437
+ sub ax, 0x3e4 ; 0094067c 2de403
+ jz L574 ; 0094067f 7447
+ jmp L561 ; 00940681 e9a201
+ push word [bp + 0xa] ; 00940684 ff760a
+ push cs ; 00940687 0e
+ call L575 ; 00940688 e89402
+ jmp L561 ; 0094068b e99801
+ push L4 ; 0094068e 6a01
+ push 0x0 ; 00940690 6a00
+ push cs ; 00940692 0e
+ call L576 ; 00940693 e85902
+ jmp L561 ; 00940696 e98d01
+ push word L59 ; 00940699 ff361800
+ push 0x9 ; 0094069d 6a09
+ push 0x0 ; 0094069f 6a00
+ jmp short L227 ; 009406a1 ebb7
+ callf ; 009406a3 9a18045b06
+ jmp L561 ; 009406a8 e97b01
+ callf ; 009406ab 9af801ffff
+ jmp L561 ; 009406b0 e97301
+ push word [bp + 0xe] ; 009406b3 ff760e
+ o32 push 0x112f060 ; 009406b6 666860f01201
+ push 0x0 ; 009406bc 6a00
+ push 0x0 ; 009406be 6a00
+ callf ; 009406c0 9abb030000
+ jmp L561 ; 009406c5 e95e01
+ push word L51 ; 009406c8 ff36b002
+ push 0x6c ; 009406cc 6a6c
+ lea ax, [bp + 0xffffff2c] ; 009406ce 8d862cff
+ push ss ; 009406d2 16
+ push ax ; 009406d3 50
+ push 0x64 ; 009406d4 6a64
+ callf ; 009406d6 9affff0000
+ push word [bp + 0xe] ; 009406db ff760e
+ push ds ; 009406de 1e
+ push 0x26e ; 009406df 686e02
+ lea ax, [bp + 0xffffff2c] ; 009406e2 8d862cff
+ push ss ; 009406e6 16
+ push ax ; 009406e7 50
+ push word L51 ; 009406e8 ff36b002
+ push ds ; 009406ec 1e
+ push 0x4f ; 009406ed 684f00
+ callf ; 009406f0 9a5b020000
+ push ax ; 009406f5 50
+ callf ; 009406f6 9affff0000
+ jmp L561 ; 009406fb e92801
+ push word [bp + 0xe] ; 009406fe ff760e
+ callf ; 00940701 9affff0000
+ mov [bp + 0xfffffffe], ax ; 00940706 8946fe
+ mov bx, L59 ; 00940709 8b1e1800
+ cmp word [bx + 0x4], byte 0x0 ; 0094070d 837f0400
+ jz L577 ; 00940711 740e
+ cmp word [bx + 0x2c], byte 0xff ; 00940713 837f2cff
+ jnz L577 ; 00940717 7508
+ mov word [bp + 0xffffff2a], 0x00 ; 00940719 c7862aff0000
+ jmp short L257 ; 0094071f eb06
+ mov word [bp + 0xffffff2a], 0x03 ; 00940721 c7862aff0300
+ push ax ; 00940727 50
+ push 0x3e9 ; 00940728 68e903
+ push word [bp + 0xffffff2a] ; 0094072b ffb62aff
+ callf ; 0094072f 9afa060000
+ push word [bp + 0xfffffffe] ; 00940734 ff76fe
+ push 0x3e8 ; 00940737 68e803
+ mov bx, L59 ; 0094073a 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 0094073e 837f2cff
+ jz L578 ; 00940742 7405
+ mov ax, 0x03 ; 00940744 b80300
+ jmp short L579 ; 00940747 eb02
+ xor ax, ax ; 00940749 33c0
+ push ax ; 0094074b 50
+ callf ; 0094074c 9a17070000
+ push word [bp + 0xfffffffe] ; 00940751 ff76fe
+ push L91 ; 00940754 68ea03
+ mov bx, L59 ; 00940757 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 0094075b 837f2cff
+ jz L580 ; 0094075f 7405
+ mov ax, 0x03 ; 00940761 b80300
+ jmp short L581 ; 00940764 eb02
+ xor ax, ax ; 00940766 33c0
+ push ax ; 00940768 50
+ callf ; 00940769 9a34070000
+ push word [bp + 0xfffffffe] ; 0094076e ff76fe
+ push 0x7d0 ; 00940771 68d007
+ mov bx, L59 ; 00940774 8b1e1800
+ cmp word [bx + 0x2c], byte 0xff ; 00940778 837f2cff
+ jz L582 ; 0094077c 7405
+ mov ax, 0x03 ; 0094077e b80300
+ jmp short L583 ; 00940781 eb02
+ xor ax, ax ; 00940783 33c0
+ push ax ; 00940785 50
+ callf ; 00940786 9affff0000
+ jmp L561 ; 0094078b e99800
+ cmp word [bp + 0xa], byte 0x0 ; 0094078e 837e0a00
+ jz L396 ; 00940792 7411
+ o32 cmp dword [bp + 0x6], 0xffff ; 00940794 66817e06ffff0000
+ jz L396 ; 0094079c 7407
+ test word [bp + 0x6], 0x2810 ; 0094079e f746061028
+ jz L584 ; 009407a3 740d
+ mov word [bp + 0xa], 0x1fff ; 009407a5 c7460aff1f
+ o32 mov dword [bp + 0x6], 0x0000 ; 009407aa 66c7460600000000
+ push word [bp + 0xa] ; 009407b2 ff760a
+ callf ; 009407b5 9aae028f05
+ jmp short L561 ; 009407ba eb6a
+ mov word [bp + 0xfffffff8], 0x05 ; 009407bc c746f80500
+ mov bx, L59 ; 009407c1 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 009407c5 837f2600
+ jz L561 ; 009407c9 745b
+ jmp short L585 ; 009407cb eb3e
+ push word [bp + 0xe] ; 009407cd ff760e
+ callf ; 009407d0 9affff0000
+ mov bx, L59 ; 009407d5 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 009407d9 837f2600
+ jnz L561 ; 009407dd 7547
+ mov word [bp + 0xfffffff8], 0x03 ; 009407df c746f80300
+ jmp short L585 ; 009407e4 eb25
+ callf ; 009407e6 9affff0000
+ mov word [bp + 0xfffffff8], 0x04 ; 009407eb c746f80400
+ mov bx, L59 ; 009407f0 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 009407f4 837f2600
+ jnz L585 ; 009407f8 7511
+ jmp short L561 ; 009407fa eb2a
+ mov word [bp + 0xfffffff8], 0x06 ; 009407fc c746f80600
+ mov bx, L59 ; 00940801 8b1e1800
+ cmp word [bx + 0x26], byte 0x0 ; 00940805 837f2600
+ jnz L561 ; 00940809 751b
+ o32 mov eax, [bp + 0x6] ; 0094080b 668b4606
+ o32 mov [bp + 0xfffffffa], eax ; 0094080f 668946fa
+ push bx ; 00940813 53
+ push word [bp + 0xfffffff8] ; 00940814 ff76f8
+ lea ax, [bp + 0xfffffffa] ; 00940817 8d46fa
+ push ax ; 0094081a 50
+ jmp L227 ; 0094081b e93cfe
+ xor ax, ax ; 0094081e 33c0
+ push ax ; 00940820 50
+ callf ; 00940821 9affff0000
+ o32 push dword [bp + 0xc] ; 00940826 66ff760c
+ o32 push dword [bp + 0x8] ; 0094082a 66ff7608
+ push word [bp + 0x6] ; 0094082e ff7606
+ callf ; 00940831 9affff0000
+ leave ; 00940836 c9
+ retf 0x0a ; 00940837 ca0a00
+ nop ; 0094083a 90
+ enter L310, 0x0 ; 0094083b c8020000
+ mov ax, [0x1a] ; 0094083f a11a00
+ mov [bp + 0xfffffffe], ax ; 00940842 8946fe
+ mov ax, [bp + 0xa] ; 00940845 8b460a
+ mov [0x1a], ax ; 00940848 a31a00
+ mov ax, [bp + 0x8] ; 0094084b 8b4608
+ mov [0x1e], ax ; 0094084e a31e00
+ mov ax, [bp + 0x6] ; 00940851 8b4606
+ mov [0x20], ax ; 00940854 a32000
+ mov ax, [bp + 0xfffffffe] ; 00940857 8b46fe
+ leave ; 0094085a c9
+ retf 0x06 ; 0094085b ca0600
+ nop ; 0094085e 90
+ cmp word L279, byte 0x0 ; 0094085f 833e1a0000
+ jz L586 ; 00940864 7408
+ inc word L281 ; 00940866 ff061c00
+ mov ax, L4 ; 0094086a b80100
+ retf ; 0094086d cb
+ push word L23 ; 0094086e ff36f001
+ callf ; 00940872 9a1e010000
+ or ax, ax ; 00940877 0bc0
+ jz L587 ; 00940879 740f
+ push ax ; 0094087b 50
+ push 0x0 ; 0094087c 6a00
+ push 0x0 ; 0094087e 6a00
+ push cs ; 00940880 0e
+ call L588 ; 00940881 e8b7ff
+ mov ax, L4 ; 00940884 b80100
+ mov [0x1c], ax ; 00940887 a31c00
+ retf ; 0094088a cb
+ cmp word L279, byte 0x0 ; 0094088b 833e1a0000
+ jz L49 ; 00940890 7419
+ dec word L281 ; 00940892 ff0e1c00
+ jnz L49 ; 00940896 7513
+ push word L23 ; 00940898 ff36f001
+ push word L279 ; 0094089c ff361a00
+ callf ; 009408a0 9a97010000
+ mov word L279, 0x00 ; 009408a5 c7061a000000
+ retf ; 009408ab cb
+ nop ; 009408ac 90
+ cmp word L59, byte 0x0 ; 009408ad 833e180000
+ jz L589 ; 009408b2 7410
+ push word L59 ; 009408b4 ff361800
+ push 0x11 ; 009408b8 6a11
+ push 0x0 ; 009408ba 6a00
+ push 0x0 ; 009408bc 6a00
+ mov bx, L59 ; 009408be 8b1e1800
+ call far oword [bx] ; 009408c2 ff1f
+ mov ax, L4 ; 009408c4 b80100
+ retf 0x310a ; 009408c7 ca0a31
+
+
+ .section .dataSection0
+ .align 0
+
+ .byte 0x00, 0x00, 0x0f, 0x08, 0xdc
+ .byte 0x00, 0x30, 0x1c, 0x38, 0x80, 0x00, 0x00, 0x00
+ .byte 0x00, 0xeb, 0x08, 0xdf, 0x00, 0x30, 0x1c, 0x39
+ .byte 0x80, 0x00, 0x00, 0x00, 0x00, 0xca, 0x09, 0xdc
+ .byte 0x00, 0x30, 0x1c, 0x3a, 0x80, 0x00, 0x00
+
+L2: \ No newline at end of file
diff --git a/decomp/hash.c b/decomp/hash.c
new file mode 100644
index 0000000..12570e7
--- /dev/null
+++ b/decomp/hash.c
@@ -0,0 +1,307 @@
+/* hash.c
+ * This file is part of Decomp - a decompiler. This file contains
+ * generic hash table manipulation routines.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started around 20 October 2001.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "decomp.h"
+
+
+#define DEFAULT_HASH_SIZE 256
+
+
+/* hash_key
+ * Create an index from 0 to SIZE - 1 using the NUL terminated string KEY.
+ */
+/* unsigned long */
+/* hash_key (char *key, unsigned long size) */
+/* { */
+/* unsigned long k, hash = 0; */
+
+/* for (k = 0; k < strlen (key); k++) hash += key[k]; */
+
+/* return (hash % size); */
+/* } */
+
+
+/* hash_key
+ * Create an index from 0 to SIZE - 1 using the value contained in KEY.
+ */
+unsigned long
+hash_key (unsigned long key, unsigned long size)
+{
+ unsigned long k, hash = 0;
+
+ for (k = 0; k < sizeof (unsigned long) * 4; k++)
+ {
+ hash += key & 0xff;
+ key >>= 2;
+ }
+
+ return (hash % size);
+}
+
+
+/* hash_goodness
+ * Return the "goodness" value of the hash table which is the
+ * ratio of the number of filled buckets to the number of items
+ * total. The closer the value is to 1.0, the better. This,
+ * combined with the ratio of the number of filled buckets to
+ * the table size can be used to determine how well the hashing
+ * algorithm works.
+ */
+double
+hash_goodness (hash_t table)
+{
+ double goodness;
+ unsigned long filled_buckets = 0, k;
+
+ for (k = 0; k < table->size; k++)
+ if (table->table[k] != NULL) filled_buckets++;
+
+ goodness = (double)filled_buckets / (double)table->items;
+
+ if (debug)
+ printf ("hash goodness = %lf\nfilled:total = %lf\n", goodness,
+ (double)filled_buckets / (double)table->size);
+
+ return (goodness);
+}
+
+
+/* hash_new
+ * Create a new hash table. If SIZE is 0, then the size is
+ * DEFAULT_HASH_SIZE, otherwise it is SIZE.
+ */
+hash_t
+hash_new (unsigned long size)
+{
+ hash_t table;
+
+ if (size == 0) size = DEFAULT_HASH_SIZE;
+
+ table = xmalloc (sizeof (struct hash_table));
+
+ table->table = xmalloc (size * sizeof (struct hash_bucket));
+ table->size = size;
+ table->items = 0;
+
+ return (table);
+}
+
+/* hash_add
+ * Add DATA to TABLE using KEY.
+ */
+int
+hash_add (hash_t table, unsigned long key, void *data)
+{
+ unsigned long index;
+ struct hash_bucket *tmp;
+
+ index = hash_key (key, table->size);
+
+ /* find empty bucket */
+ if (table->table[index] != NULL)
+ {
+ tmp = table->table[index];
+ while (tmp->next != NULL) tmp = tmp->next;
+
+ tmp->next = xmalloc (sizeof (struct hash_bucket));
+ tmp = tmp->next;
+ }
+ else
+ {
+ table->table[index] = xmalloc (sizeof (struct hash_bucket));
+ tmp = table->table[index];
+ }
+
+
+ /* insert new data */
+ tmp->next = NULL;
+ tmp->key = key;
+ tmp->data = data;
+
+ table->items++;
+
+ return (0);
+}
+
+/* hash_get
+ * Return the data indexed by KEY or NULL if the slot is empty.
+ */
+void *
+hash_get (hash_t table, unsigned long key)
+{
+ unsigned long index;
+ struct hash_bucket *tmp;
+
+ index = hash_key (key, table->size);
+
+ tmp = table->table[index];
+
+ while (tmp != NULL)
+ {
+ if (key == tmp->key) return tmp->data;
+
+ tmp = tmp->next;
+ }
+
+ /* only get here if the item wasn't found */
+ return NULL;
+}
+
+/* hash_remove
+ * Remove the data indexed by KEY from TABLE.
+ */
+void *
+hash_remove (hash_t table, unsigned long key)
+{
+ unsigned long index;
+ struct hash_bucket *tmp, *del = NULL;
+ void *data;
+
+ index = hash_key (key, table->size);
+
+ if (table->table[index] == NULL) return NULL;
+
+ if (table->table[index]->key == key)
+ {
+ del = table->table[index];
+ table->table[index] = table->table[index]->next;
+ }
+ else
+ {
+ tmp = table->table[index];
+
+ while (tmp->next != NULL)
+ {
+ if (tmp->next->key == key) break;
+ else tmp = tmp->next;
+ }
+
+ if (tmp->next == NULL) return NULL;
+
+ del = tmp->next;
+ tmp->next = del->next;
+ }
+
+ data = del->data;
+ xfree (del);
+
+ return (data);
+}
+
+/* hash_walk
+ * Walk through TABLE, returning keys one at a time. If TABLE is NULL,
+ * HASH_END is returned, and initialization is performed.
+ */
+unsigned long
+hash_walk (hash_t table)
+{
+ unsigned long key;
+ static unsigned long index;
+ static struct hash_bucket *bucket;
+
+ /* init */
+ if (table == NULL)
+ {
+ index = 0;
+ bucket = NULL;
+ return HASH_END;
+ }
+
+ /* looking for buckets */
+ if (bucket == NULL)
+ {
+ while (table->table[index] == NULL)
+ {
+ index++;
+ if (index >= table->size) return HASH_END; /* signal done */
+ }
+
+ bucket = table->table[index];
+ }
+
+ key = bucket->key;
+ bucket = bucket->next;
+
+ return (key);
+}
+
+/* hash_delete
+ * Delete TABLE.
+ */
+void
+hash_delete (hash_t table)
+{
+ unsigned long key;
+
+ hash_walk (NULL);
+
+ while ((key = hash_walk (table)) != HASH_END)
+ hash_remove (table, key);
+
+ xfree (table->table);
+ xfree (table);
+}
+
+/* hash_rehash
+ * Resize TABLE. If SIZE is 0, then the new table is twice the size
+ * of the old table, otherwise it has SIZE buckets.
+ */
+hash_t
+hash_rehash (hash_t table, unsigned long size)
+{
+ unsigned long key;
+ hash_t new;
+
+ if (size == 0)
+ new = hash_new (2 * table->size);
+ else
+ new = hash_new (size);
+
+ hash_walk (NULL);
+
+ while ((key = hash_walk (table)) != HASH_END)
+ {
+ printf (" adding %#lx\n", key);
+ hash_add (new, key, hash_get (table, key));
+ hash_remove (table, key);
+ }
+
+ hash_delete (table);
+
+ return (new);
+}
+
+/* hash_print
+ * Print all of the items in the hash table in a human-readable format.
+ */
+void
+hash_print (hash_t table)
+{
+ unsigned long k;
+ struct hash_bucket *tmp;
+
+ for (k = 0; k < table->size; k++)
+ {
+ if (table->table[k] == NULL) continue;
+
+ printf ("%ld: %#lx -> %s\n", k, table->table[k]->key,
+ (char *)table->table[k]->data);
+
+ tmp = table->table[k]->next;
+
+ while (tmp != NULL)
+ {
+ printf (" --> %#lx -> %s\n", tmp->key, (char *)tmp->data);
+ tmp = tmp->next;
+ }
+ }
+}
diff --git a/decomp/ia32.c b/decomp/ia32.c
new file mode 100644
index 0000000..f77c3a3
--- /dev/null
+++ b/decomp/ia32.c
@@ -0,0 +1,4960 @@
+/* ia32.c
+ * This file is part of Decomp - an interactive disassembler.
+ *
+ * This file contains routines for disassembling an x86 instruction. This
+ * file includes instructions from all x86 CPU's up to and including the
+ * Pentium 4.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * DECOMP is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * DECOMP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DECOMP; see the file COPYING. If not, write to the Free
+ * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * As a note, whenever "IA-32 SDM V2 or SDM V2 is mentioned, it means:
+ * IA-32 Intel Architecture Software Developer's Manual Volume 2.
+ *
+ * Started sometime around 2 December 2001.
+ * Completed 8 December 2001.
+ * The debugging just never ends.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "ia32.h"
+
+
+/* function prototypes for filling in the tables */
+
+/* 0fxx - two byte escape */
+void esc_0f_opcode (struct disassembly_state *state);
+
+/* escape to coprocessor */
+void d8_opcode (struct disassembly_state *state);
+void d9_opcode (struct disassembly_state *state);
+void da_opcode (struct disassembly_state *state);
+void db_opcode (struct disassembly_state *state);
+void dc_opcode (struct disassembly_state *state);
+void dd_opcode (struct disassembly_state *state);
+void de_opcode (struct disassembly_state *state);
+void df_opcode (struct disassembly_state *state);
+
+/* various groups */
+void immed_grp_1 (struct disassembly_state *state); /* opcodes 80-83 */
+void shift_grp_2 (struct disassembly_state *state); /* opcodes C0-C1, D0-D3 */
+void unary_grp_3 (struct disassembly_state *state); /* opcodes F6-F7 */
+void grp_4 (struct disassembly_state *state); /* opcode FE */
+void grp_5 (struct disassembly_state *state); /* opcode FF */
+void grp_6 (struct disassembly_state *state); /* opcode 0F00 */
+void grp_7 (struct disassembly_state *state); /* opcode 0F01 */
+void grp_8 (struct disassembly_state *state); /* opcode 0FBA */
+void grp_9 (struct disassembly_state *state); /* opcode 0FC7 */
+void grp_10 (struct disassembly_state *state); /* opcode 0FB9 */
+void grp_11 (struct disassembly_state *state); /* opcodes C6-C7 */
+void grp_12 (struct disassembly_state *state); /* opcode 0F71 */
+void grp_13 (struct disassembly_state *state); /* opcode 0F72 */
+void grp_14 (struct disassembly_state *state); /* opcode 0F73 */
+void grp_15 (struct disassembly_state *state); /* opcode 0FAE */
+void grp_16 (struct disassembly_state *state); /* opcode OF18 */
+
+/* MMX/SSE/SSE2 escapes */
+void esc_0f10_17 (struct disassembly_state *state);
+void esc_0f28_2f (struct disassembly_state *state);
+void esc_0f50_70 (struct disassembly_state *state);
+void esc_0f74_76 (struct disassembly_state *state);
+void esc_0f7e_7f (struct disassembly_state *state);
+void esc_0fc2 (struct disassembly_state *state);
+void esc_0fc4_c6 (struct disassembly_state *state);
+void esc_0fd1_ef (struct disassembly_state *state);
+void esc_0ff1_fe (struct disassembly_state *state);
+
+
+/* an array of opcodes where the first opcode byte is the index */
+insn one_byte_opcode_table[] = {
+ /* 00 */
+ { "add", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 01 */
+ { "add", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 02 */
+ { "add", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 03 */
+ { "add", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 04 */
+ { "add", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* 05 */
+ { "add", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* 06 */
+ { "push", { R_ES, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 07 */
+ { "pop", { R_ES, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 08 */
+ { "or", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 09 */
+ { "or", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 0A */
+ { "or", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 0B */
+ { "or", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 0C */
+ { "or", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* 0D */
+ { "or", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* 0E */
+ { "push", { R_CS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 0F */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f_opcode },
+ /* 10 */
+ { "adc", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 11 */
+ { "adc", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 12 */
+ { "adc", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 13 */
+ { "adc", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 14 */
+ { "adc", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* 15 */
+ { "adc", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* 16 */
+ { "push", { R_SS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 17 */
+ { "pop", { R_SS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 18 */
+ { "sbb", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 19 */
+ { "sbb", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 1A */
+ { "sbb", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 1B */
+ { "sbb", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 1C */
+ { "sbb", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* 1D */
+ { "sbb", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* 1E */
+ { "push", { R_DS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 1F */
+ { "pop", { R_DS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 20 */
+ { "and", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 21 */
+ { "and", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 22 */
+ { "and", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 23 */
+ { "and", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 24 */
+ { "and", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* 25 */
+ { "and", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* 26 */
+ { "es", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 27 */
+ { "daa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 28 */
+ { "sub", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 29 */
+ { "sub", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 2A */
+ { "sub", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 2B */
+ { "sub", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 2C */
+ { "sub", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* 2D */
+ { "sub", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* 2E */
+ { "cs", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 2F */
+ { "das", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 30 */
+ { "xor", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 31 */
+ { "xor", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 32 */
+ { "xor", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 33 */
+ { "xor", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 34 */
+ { "xor", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* 35 */
+ { "xor", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* 36 */
+ { "ss", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 37 */
+ { "aaa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 38 */
+ { "cmp", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 39 */
+ { "cmp", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 3A */
+ { "cmp", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 3B */
+ { "cmp", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 3C */
+ { "cmp", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* 3D */
+ { "cmp", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* 3E */
+ { "ds", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 3F */
+ { "aas", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 40 */
+ { "inc", { R_AX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 41 */
+ { "inc", { R_CX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 42 */
+ { "inc", { R_DX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 43 */
+ { "inc", { R_BX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 44 */
+ { "inc", { R_SP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 45 */
+ { "inc", { R_BP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 46 */
+ { "inc", { R_SI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 47 */
+ { "inc", { R_DI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 48 */
+ { "dec", { R_AX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 49 */
+ { "dec", { R_CX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 4A */
+ { "dec", { R_DX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 4B */
+ { "dec", { R_BX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 4C */
+ { "dec", { R_SP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 4D */
+ { "dec", { R_BP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 4E */
+ { "dec", { R_SI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 4F */
+ { "dec", { R_DI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 50 */
+ { "push", { R_AX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 51 */
+ { "push", { R_CX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 52 */
+ { "push", { R_DX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 53 */
+ { "push", { R_BX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 54 */
+ { "push", { R_SP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 55 */
+ { "push", { R_BP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 56 */
+ { "push", { R_SI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 57 */
+ { "push", { R_DI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 58 */
+ { "pop", { R_AX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 59 */
+ { "pop", { R_CX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 5A */
+ { "pop", { R_DX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 5B */
+ { "pop", { R_BX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 5C */
+ { "pop", { R_SP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 5D */
+ { "pop", { R_BP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 5E */
+ { "pop", { R_SI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 5F */
+ { "pop", { R_DI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* 60 */
+ { "pusha", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 61 */
+ { "popa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 62 */
+ { "bound", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_A, OP_0 }, NULL },
+ /* 63 */
+ { "arpl", { ADDR_E, ADDR_G, ADDR_0 }, { OP_W, OP_W, OP_0 }, NULL },
+ /* 64 */
+ { "fs", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 65 */
+ { "gs", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 66 - this changes the operand size */
+ { "opd-size", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 67 - this changes the operand size */
+ { "addr-size", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 68 */
+ { "push", { ADDR_I, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 69 */
+ { "imul", { ADDR_G, ADDR_E, ADDR_I }, { OP_V, OP_V, OP_V }, NULL },
+ /* 6A */
+ { "push", { ADDR_I, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 6B */
+ { "imul", { ADDR_G, ADDR_E, ADDR_I }, { OP_V, OP_V, OP_B }, NULL },
+ /* 6C - may need to document 6c - 6f: sdmv2 pp 3-328-330 and 3-519-521 */
+ { "insb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 6D */
+ { "insw", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 6E */
+ { "outsb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 6F */
+ { "outsw", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 70 */
+ { "jo", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 71 */
+ { "jno", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 72 - this insn is jb/jnae/jc and is equiv to jump if carry set */
+ { "jc", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 73 - this insn is jnb/jnae/jnc and is equiv to jump if carry clear */
+ { "jnc", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 74 */
+ { "jz", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 75 */
+ { "jnz", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 76 */
+ { "jbe", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 77 */
+ { "ja", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 78 */
+ { "js", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 79 */
+ { "jns", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 7A */
+ { "jp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 7B */
+ { "jnp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 7C */
+ { "jl", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 7D */
+ { "jge", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 7E */
+ { "jle", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 7F */
+ { "jg", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 80 */
+ { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_B, OP_B, OP_0 }, immed_grp_1 },
+ /* 81 */
+ { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_V, OP_0 }, immed_grp_1 },
+ /* 82 */
+ { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_B, OP_B, OP_0 }, immed_grp_1 },
+ /* 83 */
+ { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_B, OP_0 }, immed_grp_1 },
+ /* 84 */
+ { "test", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 85 */
+ { "test", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 86 */
+ { "xchg", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 87 */
+ { "xchg", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 88 */
+ { "mov", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 89 */
+ { "mov", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 8A */
+ { "mov", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* 8B */
+ { "mov", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 8C */
+ { "mov", { ADDR_E, ADDR_S, ADDR_0 }, { OP_W, OP_W, OP_0 }, NULL },
+ /* 8D */
+ { "lea", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 8E */
+ { "mov", { ADDR_S, ADDR_E, ADDR_0 }, { OP_W, OP_W, OP_0 }, NULL },
+ /* 8F */
+ { "pop", { ADDR_E, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 90 */
+ { "nop", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 91 */
+ { "xchg", { R_AX, R_CX, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL },
+ /* 92 */
+ { "xchg", { R_AX, R_DX, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL },
+ /* 93 */
+ { "xchg", { R_AX, R_BX, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL },
+ /* 94 */
+ { "xchg", { R_AX, R_SP, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL },
+ /* 95 */
+ { "xchg", { R_AX, R_BP, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL },
+ /* 96 */
+ { "xchg", { R_AX, R_SI, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL },
+ /* 97 */
+ { "xchg", { R_AX, R_DI, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL },
+ /* 98 - cbw/cwde dep on opsize */
+ { "cbw", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 99 - cwd/cdq dep on opsize */
+ { "cwd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 9A */
+ { "callf", { ADDR_A, ADDR_0, ADDR_0 }, { OP_P, OP_0, OP_0 }, NULL },
+ /* 9B */
+ { "fwait", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 9C */
+ { "pushf", { ADDR_F, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 9D */
+ { "popf", { ADDR_F, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 9E */
+ { "sahf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 9F */
+ { "lahf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* A0 */
+ { "mov", { R_AL, ADDR_O, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* A1 */
+ { "mov", { R_AX, ADDR_O, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* A2 */
+ { "mov", { ADDR_O, R_AL, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* A3 */
+ { "mov", { ADDR_O, R_AX, ADDR_0 }, { OP_V, OP_E, OP_0 }, NULL },
+ /* A4 */
+ { "movs", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* A5 */
+ { "movs", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* A6 */
+ { "cmps", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* A7 */
+ { "cmps", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* A8 */
+ { "test", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* A9 */
+ { "test", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* AA - stosb and stosw are names for stos m8,16,32 */
+ { "stos", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* AB - this is given as Yv, eAX, but both are optional */
+ { "stos", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+/* { "stosw", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL }, */
+ /* AC */
+ { "lods", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* AD */
+ { "lods", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* AE */
+ { "scas", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* AF - sdmv2 A-7 gives this opcode as SCASW eAX, Xv - should be Yv (?) */
+ { "scas", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* B0 */
+ { "mov", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* B1 */
+ { "mov", { R_CL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* B2 */
+ { "mov", { R_DL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* B3 */
+ { "mov", { R_BL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* B4 */
+ { "mov", { R_AH, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* B5 */
+ { "mov", { R_CH, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* B6 */
+ { "mov", { R_DH, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* B7 */
+ { "mov", { R_BH, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* B8 */
+ { "mov", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* B9 */
+ { "mov", { R_CX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* BA */
+ { "mov", { R_DX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* BB */
+ { "mov", { R_BX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* BC */
+ { "mov", { R_SP, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* BD */
+ { "mov", { R_BP, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* BE */
+ { "mov", { R_SI, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* BF */
+ { "mov", { R_DI, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL },
+ /* C0 */
+ { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_B, OP_B, OP_0 }, shift_grp_2 },
+ /* C1 */
+ { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_B, OP_0 }, shift_grp_2 },
+ /* C2 */
+ { "ret", { ADDR_I, ADDR_0, ADDR_0 }, { OP_W, OP_0, OP_0 }, NULL },
+ /* C3 */
+ { "ret", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* C4 */
+ { "les", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_P, OP_0 }, NULL },
+ /* C5 */
+ { "lds", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_P, OP_0 }, NULL },
+ /* C6 */
+ { "mov", { ADDR_E, ADDR_I, ADDR_0 }, { OP_B, OP_B, OP_0 }, grp_11 },
+ /* C7 */
+ { "mov", { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_V, OP_0 }, grp_11 },
+ /* C8 */
+ { "enter", { ADDR_I, ADDR_I, ADDR_0 }, { OP_W, OP_B, OP_0 }, NULL },
+ /* C9 */
+ { "leave", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CA */
+ { "retf", { ADDR_I, ADDR_0, ADDR_0 }, { OP_W, OP_0, OP_0 }, NULL },
+ /* CB */
+ { "retf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CC */
+ { "int\t3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CD */
+ { "int", { ADDR_I, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* CE */
+ { "into", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CF */
+ { "iret", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* D0 */
+ { NULL, { ADDR_E, IMMED_1, ADDR_0 }, { OP_B, OP_0, OP_0 }, shift_grp_2 },
+ /* D1 */
+ { NULL, { ADDR_E, IMMED_1, ADDR_0 }, { OP_V, OP_0, OP_0 }, shift_grp_2 },
+ /* D2 */
+ { NULL, { ADDR_E, R_CL, ADDR_0 }, { OP_B, OP_0, OP_0 }, shift_grp_2 },
+ /* D3 */
+ { NULL, { ADDR_E, R_CL, ADDR_0 }, { OP_V, OP_0, OP_0 }, shift_grp_2 },
+ /* D4 */
+ { "aam", { ADDR_I, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* D5 */
+ { "aad", { ADDR_I, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* D6 - illegal instruction */
+ { "ill_d6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* D7 */
+ { "xlatb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* D8 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, d8_opcode },
+ /* D9 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, d9_opcode },
+ /* DA */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, da_opcode },
+ /* DB */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, db_opcode },
+ /* DC */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, dc_opcode },
+ /* DD */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, dd_opcode },
+ /* DE */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, de_opcode },
+ /* DF */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, df_opcode },
+ /* E0 */
+ { "loopne", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* E1 */
+ { "loope", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* E2 */
+ { "loop", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* E3 */
+ { "jcxz", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* E4 */
+ { "in", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL },
+ /* E5 */
+ { "in", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_B, OP_0 }, NULL },
+ /* E6 */
+ { "out", { ADDR_I, R_AL, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* E7 */
+ { "out", { ADDR_I, R_AX, ADDR_0 }, { OP_B, OP_E, OP_0 }, NULL },
+ /* E8 */
+ { "call", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* E9 - near jmp */
+ { "jmp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* EA - far jmp */
+ { "jmp", { ADDR_A, ADDR_0, ADDR_0 }, { OP_P, OP_0, OP_0 }, NULL },
+ /* EB - short jmp */
+ { "jmp short", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* EC */
+ { "in", { R_AL, R_DX, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* ED */
+ { "in", { R_AX, R_DX, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL },
+ /* EE */
+ { "out", { R_DX, R_AL, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* EF */
+ { "out", { R_DX, R_AX, ADDR_0 }, { OP_0, OP_E, OP_0 }, NULL },
+ /* F0 */
+ { "lock", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F1 */
+ { "ill_f1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F2 */
+ { "repne", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "repe", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F4 */
+ { "hlt", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F5 */
+ { "cmc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F6 */
+ { NULL, { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, unary_grp_3 },
+ /* F7 */
+ { NULL, { ADDR_E, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, unary_grp_3 },
+ /* F8 */
+ { "clc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F9 */
+ { "stc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* FA */
+ { "cli", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* FB */
+ { "sti", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* FC */
+ { "cld", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* FD */
+ { "std", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* FE - inc/dec */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_4 },
+ /* FF - inc/dec */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_5 },
+};
+
+
+/* opcode 0F escape table */
+insn esc_0f_opcode_table[] = {
+ /* 00 - grp 6 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_6 },
+ /* 01 - grp 7 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_7 },
+ /* 02 */
+ { "lar", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_W, OP_0 }, NULL },
+ /* 03 */
+ { "lsl", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_W, OP_0 }, NULL },
+ /* 04 */
+ { "ill_0f04", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 05 */
+ { "ill_0f05", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 06 */
+ { "clts", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 07 */
+ { "ill_0f07", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 08 */
+ { "invd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 09 */
+ { "wbinvd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 0A */
+ { "ill_0f0a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 0B */
+ { "ud2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 0C */
+ { "ill_0f0c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 0D */
+ { "ill_0f0d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 0E */
+ { "ill_0f0e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 0F */
+ { "ill_0f0f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 10 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17 },
+ /* 11 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17 },
+ /* 12 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17 },
+ /* 13 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17 },
+ /* 14 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17 },
+ /* 15 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17 },
+ /* 16 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17 },
+ /* 17 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17 },
+ /* 18 - prefetch */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_16 },
+ /* 19 */
+ { "ill_0f19", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 1A */
+ { "ill_0f1a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 1B */
+ { "ill_0f1b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 1C */
+ { "ill_0f1c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 1D */
+ { "ill_0f1d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 1E */
+ { "ill_0f1e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 1F */
+ { "ill_0f1f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 20 */
+ { "mov", { ADDR_R, ADDR_C, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL },
+ /* 21 */
+ { "mov", { ADDR_R, ADDR_D, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL },
+ /* 22 */
+ { "mov", { ADDR_C, ADDR_R, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL },
+ /* 23 */
+ { "mov", { ADDR_D, ADDR_R, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL },
+ /* 24 */
+ { "mov", { ADDR_R, ADDR_T, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL },
+ /* 25 */
+ { "ill_0f25", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 26 */
+ { "mov", { ADDR_T, ADDR_R, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL },
+ /* 27 */
+ { "ill_0f27", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 28 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f },
+ /* 29 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f },
+ /* 2A */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f },
+ /* 2B */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f },
+ /* 2C */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f },
+ /* 2D */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f },
+ /* 2E */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f },
+ /* 2F */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f },
+ /* 30 */
+ { "wrmsr", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 31 */
+ { "rdtsc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 32 */
+ { "rdmsr", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 33 */
+ { "rdpmc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 34 */
+ { "sysenter", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 35 */
+ { "sysexit", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 36 */
+ { "ill_0f36", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 37 */
+ { "ill_0f37", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 38 */
+ { "ill_0f38", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 39 */
+ { "ill_0f39", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 3A */
+ { "ill_0f3a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 3B */
+ { "ill_0f3b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 3C */
+ { "ill_0f3c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 3D */
+ { "ill_0f3d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 3E */
+ { "ill_0f3e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 3F */
+ { "ill_0f3f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 40 */
+ { "cmovo", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 41 */
+ { "cmovno", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 42 - cmovb/cmovc/cmovnae */
+ { "cmovb", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 43 - cmovae/cmovnb/cmovnc */
+ { "cmovnb", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 44 - cmove/cmovz */
+ { "cmove", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 45 - cmovne/cmovnz */
+ { "cmovne", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 46 - cmovbe/cmovna */
+ { "cmovna", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 47 - cmova/cmovnbe */
+ { "cmova", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 48 */
+ { "cmovs", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 49 */
+ { "cmovns", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 4A - cmovp/cmovpe */
+ { "cmovp", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 4B - cmovnp/cmovpo */
+ { "cmovnp", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 4C - cmovl/cmovnge */
+ { "cmovl", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 4D - cmovnl/cmovge */
+ { "cmovge", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 4E - cmovle/cmovng */
+ { "cmovle", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 4F - cmovnle/cmovg */
+ { "cmovg", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* 50 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 51 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 52 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 53 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 54 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 55 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 56 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 57 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 58 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 59 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 5A */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 5B */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 5C */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 5D */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 5E */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 5F */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 60 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 61 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 62 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 63 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 64 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 65 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 66 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 67 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 68 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 69 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 6A */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 6B */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 6C */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 6D */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 6E */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 6F */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 70 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70 },
+ /* 71 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_12 },
+ /* 72 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_13 },
+ /* 73 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_14 },
+ /* 74 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f74_76 },
+ /* 75 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f74_76 },
+ /* 76 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f74_76 },
+ /* 77 */
+ { "emms", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 78 */
+ { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 79 */
+ { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 7A */
+ { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 7B */
+ { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 7C */
+ { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 7D */
+ { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 7E */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f7e_7f },
+ /* 7F */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f7e_7f },
+ /* 80 - incorrectly listed as JS */
+ { "jo", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 81 - incorrectly listed as JNS */
+ { "jno", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 82 - jnae/jb/jc - incorrectly listed as JP/JPE */
+ { "jb", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 83 - jae/jnb/jnc - incorrectly listed as JNP/JPO */
+ { "jae", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 84 - je/jz - incorrectly listed as JL/JNGE */
+ { "je", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 85 - jne/jnz - incorrectly listed as JNL/JGE */
+ { "jne", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 86 - jbe/jna - incorrectly listed as JLE/JNG */
+ { "jbe", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 87 - ja/jnbe - incorrectly listed as JNLE/JG */
+ { "ja", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 88 */
+ { "js", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 89 */
+ { "jns", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 8A - jp/jpe */
+ { "jp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 8B - jnp/jpo */
+ { "jnp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 8C - jl/jnge */
+ { "jl", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 8D - jnl/jge */
+ { "jge", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 8E - jle/jng */
+ { "jle", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 8F - jnle/jg */
+ { "jg", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL },
+ /* 90 */
+ { "seto", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 91 */
+ { "setno", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 92 - setb/setc/setnae */
+ { "setb", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 93 - setae/setnb/setnc */
+ { "setae", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 94 - sete/setz */
+ { "sete", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 95 - setne/setnz */
+ { "setne", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 96 - setbe/setna */
+ { "setbe", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 97 - seta/setnbe */
+ { "seta", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 98 */
+ { "sets", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 99 */
+ { "setns", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 9A - setp/setpe */
+ { "setp", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 9B - setnp/setpo */
+ { "setnp", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 9C - setl/setnge */
+ { "setl", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 9D - setnl/setge */
+ { "setge", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 9E - setle/setng */
+ { "setle", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* 9F - setnle/setg */
+ { "setg", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL },
+ /* A0 */
+ { "push", { R_FS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* A1 */
+ { "pop", { R_FS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* A2 */
+ { "cpuid", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* A3 */
+ { "bt", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* A4 */
+ { "shld", { ADDR_E, ADDR_G, ADDR_I }, { OP_V, OP_V, OP_B }, NULL },
+ /* A5 */
+ { "shld", { ADDR_E, ADDR_G, R_CL }, { OP_V, OP_V, OP_0 }, NULL },
+ /* A6 */
+ { "ill_0fa6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* A7 */
+ { "ill_0fa7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* A8 */
+ { "push", { R_GS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* A9 */
+ { "pop", { R_GS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* AA */
+ { "rsm", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* AB */
+ { "bts", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* AC */
+ { "shrd", { ADDR_E, ADDR_G, ADDR_I }, { OP_V, OP_V, OP_B }, NULL },
+ /* AD */
+ { "shrd", { ADDR_E, ADDR_G, R_CL }, { OP_V, OP_V, OP_0 }, NULL },
+ /* AE */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_15 },
+ /* AF */
+ { "imul", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* B0 */
+ { "cmpxchg", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* B1 */
+ { "cmpxchg", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* B2 */
+ { "lss", { ADDR_M, ADDR_0, ADDR_0 }, { OP_P, OP_0, OP_0 }, NULL },
+ /* B3 */
+ { "btr", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* B4 */
+ { "lfs", { ADDR_M, ADDR_0, ADDR_0 }, { OP_P, OP_0, OP_0 }, NULL },
+ /* B5 */
+ { "lgs", { ADDR_M, ADDR_0, ADDR_0 }, { OP_P, OP_0, OP_0 }, NULL },
+ /* B6 */
+ { "movzx", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_B, OP_0 }, NULL },
+ /* B7 */
+ { "movzx", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_W, OP_0 }, NULL },
+ /* B8 */
+ { "ill_0fb8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* B9 - not too sure of this one - it's both UD and group 10 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_10 },
+ /* BA */
+ { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_B, OP_0 }, grp_8 },
+ /* BB */
+ { "btc", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* BC */
+ { "bsf", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* BD */
+ { "bsr", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* BE */
+ { "movsx", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_B, OP_0 }, NULL },
+ /* BF */
+ { "movsx", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_W, OP_0 }, NULL },
+ /* C0 */
+ { "xadd", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL },
+ /* C1 */
+ { "xadd", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL },
+ /* C2 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fc2 },
+ /* C3 */
+ { "movnti", { ADDR_E, ADDR_G, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL },
+ /* C4 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fc4_c6 },
+ /* C5 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fc4_c6 },
+ /* C6 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fc4_c6 },
+ /* C7 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_9 },
+ /* C8 */
+ { "bswap", { R_EAX, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* C9 */
+ { "bswap", { R_ECX, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CA */
+ { "bswap", { R_EDX, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CB */
+ { "bswap", { R_EBX, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CC */
+ { "bswap", { R_ESP, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CD */
+ { "bswap", { R_EBP, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CE */
+ { "bswap", { R_ESI, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* CF */
+ { "bswap", { R_EDI, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* D0 */
+ { "ill_0fd0", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* D1 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* D2 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* D3 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* D4 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* D5 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* D6 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* D7 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* D8 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* D9 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* DA */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* DB */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* DC */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* DD */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* DE */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* DF */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E0 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E1 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E2 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E3 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E4 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E5 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E6 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E7 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E8 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* E9 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* EA */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* EB */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* EC */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* ED */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* EE */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* EF */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef },
+ /* F0 */
+ { "ill_0ff0", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F1 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* F2 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* F3 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* F4 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* F5 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* F6 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* F7 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* F8 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* F9 */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* FA */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* FB */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* FC */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* FD */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* FE */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe },
+ /* FF */
+ { "ill_0fff", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+};
+
+
+/* esc_0f_opcode
+ * Handles all opcodes which start with 0x0f
+ */
+void
+esc_0f_opcode (struct disassembly_state *state)
+{
+ unsigned char opcode;
+ insn_table table = esc_0f_opcode_table;
+
+ opcode = state->text[state->pos];
+ state->pos++;
+
+ /* get the instruction operands */
+ state->addr[0] = table[opcode].addr_method[0];
+ state->addr[1] = table[opcode].addr_method[1];
+ state->addr[2] = table[opcode].addr_method[2];
+
+ state->op[0] = table[opcode].operand_type[0];
+ state->op[1] = table[opcode].operand_type[1];
+ state->op[2] = table[opcode].operand_type[2];
+
+ state->opcode[1] = opcode;
+
+
+ /* check for esc opcode */
+ if (table[opcode].instruction == NULL) /* this opcode is an escape */
+ {
+ /* sanity check */
+ if (table[opcode].esc_function == NULL)
+ fprintf (stderr, "%s: internal error at %d\n", __FILE__, __LINE__);
+ else
+ table[opcode].esc_function (state);
+ }
+ else /* normal instruction */
+ strcat (state->instruction, table[opcode].instruction);
+}
+
+
+/* read_modrm
+ * Store the next byte to STATE->modrm and increment STATE->pos.
+ */
+inline void
+read_modrm (struct disassembly_state *state)
+{
+ state->modrm = state->text[state->pos];
+ state->pos++;
+ state->read_modrm = 1;
+}
+
+
+/* d8_opcode
+ * x87 escape.
+ */
+void
+d8_opcode (struct disassembly_state *state)
+{
+ read_modrm (state);
+
+ if (state->modrm > 0xbf)
+ {
+ switch (state->modrm >> 4)
+ {
+ case 0xc:
+ if ((state->modrm & 0x0f) < 0x8)
+ strcat (state->instruction, "fadd");
+ else
+ strcat (state->instruction, "fmul");
+ break;
+ case 0xd:
+ if ((state->modrm & 0x0f) < 0x8)
+ strcat (state->instruction, "fcom");
+ else
+ strcat (state->instruction, "fcomp");
+ break;
+ case 0xe:
+ if ((state->modrm & 0x0f) < 0x8)
+ strcat (state->instruction, "fsub");
+ else
+ strcat (state->instruction, "fsubr");
+ break;
+ case 0xf:
+ if ((state->modrm & 0x0f) < 0x8)
+ strcat (state->instruction, "fdiv");
+ else
+ strcat (state->instruction, "fdivr");
+ }
+
+ state->addr[0] = R_ST0;
+
+ switch (state->modrm & 0x03) /* should be made into a lookup table */
+ {
+ case 0x0:
+ state->addr[1] = R_ST0;
+ break;
+ case 0x1:
+ state->addr[1] = R_ST1;
+ break;
+ case 0x2:
+ state->addr[1] = R_ST2;
+ break;
+ case 0x3:
+ state->addr[1] = R_ST3;
+ break;
+ case 0x4:
+ state->addr[1] = R_ST4;
+ break;
+ case 0x5:
+ state->addr[1] = R_ST5;
+ break;
+ case 0x6:
+ state->addr[1] = R_ST6;
+ break;
+ case 0x7:
+ state->addr[1] = R_ST7;
+ }
+ }
+ else
+ {
+ /* the nnn field of the ModR/M byte selects the instruction */
+ switch ((state->modrm >> 3) & 0x07)
+ {
+ case 0x0:
+ strcat (state->instruction, "fadd");
+ break;
+ case 0x1:
+ strcat (state->instruction, "fmul");
+ break;
+ case 0x2:
+ strcat (state->instruction, "fcom");
+ break;
+ case 0x3:
+ strcat (state->instruction, "fcomp");
+ break;
+ case 0x4:
+ strcat (state->instruction, "fsub");
+ break;
+ case 0x5:
+ strcat (state->instruction, "fsubr");
+ break;
+ case 0x6:
+ strcat (state->instruction, "fdiv");
+ break;
+ case 0x7:
+ strcat (state->instruction, "fdivr");
+ }
+
+ /* the operand is a 32 bit float in mem */
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_D;
+ }
+}
+
+/* d9_opcode
+ * x87 escape.
+ */
+void
+d9_opcode (struct disassembly_state *state)
+{
+ read_modrm (state);
+
+ if (state->modrm > 0xbf)
+ {
+ switch (state->modrm >> 4)
+ {
+ case 0xc:
+ if (state->modrm < 0xc8)
+ strcat (state->instruction, "fld");
+ else
+ strcat (state->instruction, "fxch");
+
+ switch (state->modrm & 0x07)
+ {
+ case 0x0:
+ state->addr[0] = R_ST0;
+ break;
+ case 0x1:
+ state->addr[0] = R_ST1;
+ break;
+ case 0x2:
+ state->addr[0] = R_ST2;
+ break;
+ case 0x3:
+ state->addr[0] = R_ST3;
+ break;
+ case 0x4:
+ state->addr[0] = R_ST4;
+ break;
+ case 0x5:
+ state->addr[0] = R_ST5;
+ break;
+ case 0x6:
+ state->addr[0] = R_ST6;
+ break;
+ case 0x7:
+ state->addr[0] = R_ST7;
+ }
+ break;
+ case 0xd:
+ if (state->modrm == 0xd0)
+ strcat (state->instruction, "fnop");
+ else
+ strcat (state->instruction, "ill_d9");
+ break;
+ case 0xe:
+ {
+ char *insn;
+
+ switch (state->modrm & 0x0f)
+ {
+ case 0x0:
+ insn = "fchs";
+ break;
+ case 0x1:
+ insn = "fabs";
+ break;
+ case 0x4:
+ insn = "ftst";
+ break;
+ case 0x5:
+ insn = "fxam";
+ break;
+ case 0x8:
+ insn = "fld1";
+ break;
+ case 0x9:
+ insn = "fldl2t";
+ break;
+ case 0xa:
+ insn = "fldl2e";
+ break;
+ case 0xb:
+ insn = "fldpi";
+ break;
+ case 0xc:
+ insn = "fldlg2";
+ break;
+ case 0xd:
+ insn = "fldln2";
+ break;
+ case 0xe:
+ insn = "fldz";
+ break;
+ default:
+ insn = "ill_d9";
+ }
+
+ strcat (state->instruction, insn);
+ break;
+ }
+ case 0xf:
+ {
+ char *insn[] = { "f2xm1", "fyl2x", "fptan", "fpatan",
+ "fxtract", "fprem1", "fdecstp", "fincstp",
+ "fprem", "fyl2xp1", "fsqrt", "fsincos",
+ "frndint", "fscale", "fsin", "fcos" };
+
+ strcat (state->instruction, insn[state->modrm & 0x0f]);
+ }
+ }
+ }
+ else
+ {
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_B; /* not strictly correct, but it'll suffice */
+
+ /* the nnn field of the ModR/M byte selects the instruction */
+ switch ((state->modrm >> 3) & 0x07)
+ {
+ case 0x0:
+ strcat (state->instruction, "fld");
+ break;
+ case 0x2:
+ strcat (state->instruction, "fst");
+ break;
+ case 0x3:
+ strcat (state->instruction, "fstp");
+ break;
+ case 0x4:
+ strcat (state->instruction, "fldenv");
+ break;
+ case 0x5:
+ strcat (state->instruction, "fldcw");
+ break;
+ case 0x6:
+ strcat (state->instruction, "fstenv");
+ break;
+ case 0x7:
+ strcat (state->instruction, "fstcw");
+ break;
+ default:
+ strcat (state->instruction, "ill_d9");
+ state->addr[0] = ADDR_0;
+ state->op[0] = OP_0;
+ }
+ }
+}
+
+/* da_opcode
+ * x87 escape.
+ */
+void
+da_opcode (struct disassembly_state *state)
+{
+ read_modrm (state);
+
+ if (state->modrm > 0xbf)
+ {
+ char *insn;
+
+ if (state->modrm == 0xe9)
+ {
+ strcat (state->instruction, "fucompp");
+ return;
+ }
+
+ switch (state->modrm >> 4)
+ {
+ case 0xc:
+ if (state->modrm < 0xc8)
+ insn = "fcmovb";
+ else
+ insn = "fcmove";
+ break;
+ case 0xd:
+ if (state->modrm < 0xd8)
+ insn = "fcmovbe";
+ else
+ insn = "fcmovu";
+ break;
+ default:
+ strcat (state->instruction, "ill_da");
+ return;
+ }
+
+ strcat (state->instruction, insn);
+ state->addr[0] = R_ST0;
+
+ switch (state->modrm & 0x07)
+ {
+ case 0x0:
+ state->addr[1] = R_ST0;
+ break;
+ case 0x1:
+ state->addr[1] = R_ST1;
+ break;
+ case 0x2:
+ state->addr[1] = R_ST2;
+ break;
+ case 0x3:
+ state->addr[1] = R_ST3;
+ break;
+ case 0x4:
+ state->addr[1] = R_ST4;
+ break;
+ case 0x5:
+ state->addr[1] = R_ST5;
+ break;
+ case 0x6:
+ state->addr[1] = R_ST6;
+ break;
+ case 0x7:
+ state->addr[1] = R_ST7;
+ }
+ }
+ else
+ {
+ char *insn;
+
+ /* Md */
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_D;
+
+ insn = ""; /* shut gcc up */
+
+ switch ((state->modrm >> 3) & 0x07)
+ {
+ case 0x0:
+ insn = "fiadd";
+ break;
+ case 0x1:
+ insn = "fimul";
+ break;
+ case 0x2:
+ insn = "ficom";
+ break;
+ case 0x3:
+ insn = "ficomp";
+ break;
+ case 0x4:
+ insn = "fisub";
+ break;
+ case 0x5:
+ insn = "fisubr";
+ break;
+ case 0x6:
+ insn = "fidiv";
+ break;
+ case 0x7:
+ insn = "fidivr";
+ }
+
+ strcat (state->instruction, insn);
+ }
+}
+
+/* db_opcode
+ * x87 escape.
+ */
+void
+db_opcode (struct disassembly_state *state)
+{
+ char *insn;
+
+ insn = ""; /* shut gcc up */
+
+ read_modrm (state);
+
+ if (state->modrm > 0xbf)
+ {
+ if (state->modrm == 0xe2)
+ {
+ strcat (state->instruction, "fclex");
+ return;
+ }
+ else if (state->modrm == 0xe3)
+ {
+ strcat (state->instruction, "finit");
+ return;
+ }
+ else if (state->modrm > 0xf7
+ || (state->modrm > 0xdf && state->modrm < 0xf0))
+ insn = "ill_db";
+ else
+ {
+ state->addr[0] = R_ST0;
+
+ switch (state->modrm >> 4)
+ {
+ case 0xc:
+ if (state->modrm < 0xc8)
+ insn = "fcmovnb";
+ else
+ insn = "fcmovne";
+ break;
+ case 0xd:
+ if (state->modrm < 0xd8)
+ insn = "fcmovnbe";
+ else
+ insn = "fcmovnu";
+ break;
+ case 0xe:
+ insn = "fucomi";
+ break;
+ case 0xf:
+ insn = "fcomi";
+ }
+
+ switch (state->modrm & 0x07)
+ {
+ case 0x0:
+ state->addr[1] = R_ST0;
+ break;
+ case 0x1:
+ state->addr[1] = R_ST1;
+ break;
+ case 0x2:
+ state->addr[1] = R_ST2;
+ break;
+ case 0x3:
+ state->addr[1] = R_ST3;
+ break;
+ case 0x4:
+ state->addr[1] = R_ST4;
+ break;
+ case 0x5:
+ state->addr[1] = R_ST5;
+ break;
+ case 0x6:
+ state->addr[1] = R_ST6;
+ break;
+ case 0x7:
+ state->addr[1] = R_ST7;
+ }
+ }
+ }
+ else
+ {
+ state->addr[0] = ADDR_M;
+
+ switch ((state->modrm >> 3) & 0x07)
+ {
+ case 0x0:
+ state->op[0] = OP_D;
+ insn = "fild";
+ break;
+ case 0x2:
+ state->op[0] = OP_D;
+ insn = "fist";
+ break;
+ case 0x3:
+ state->op[0] = OP_D;
+ insn = "fistp";
+ break;
+ case 0x5:
+ state->op[0] = OP_Q;
+ insn = "fld";
+ break;
+ case 0x7:
+ state->op[0] = OP_Q;
+ insn = "fstp";
+ break;
+ default:
+ insn = "ill_db";
+ state->addr[0] = ADDR_0;
+ }
+ }
+
+ strcat (state->instruction, insn);
+}
+
+/* dc_opcode
+ * x87 escape.
+ */
+void
+dc_opcode (struct disassembly_state *state)
+{
+ char *insn;
+ char *low_insn[] = { "fadd", "fmul", "fcom", "fcomp",
+ "fsub", "fsubr", "fdiv", "fdivr" };
+
+ read_modrm (state);
+
+ insn = ""; /* shut gcc up */
+
+ if (state->modrm > 0xbf)
+ {
+ if (state->modrm >> 4 == 0xd)
+ insn = "ill_dc";
+ else
+ {
+ state->addr[1] = R_ST0;
+
+ switch (state->modrm >> 4)
+ {
+ case 0xc:
+ if (state->modrm < 0xc8)
+ insn = "fadd";
+ else
+ insn = "fmul";
+ break;
+ case 0xe:
+ if (state->modrm < 0xe8)
+ insn = "fsubr";
+ else
+ insn = "fsub";
+ break;
+ case 0xf:
+ if (state->modrm < 0xf8)
+ insn = "fdivr";
+ else
+ insn = "fdiv";
+ }
+
+ switch (state->modrm & 0x07)
+ {
+ case 0x0:
+ state->addr[0] = R_ST0;
+ break;
+ case 0x1:
+ state->addr[0] = R_ST1;
+ break;
+ case 0x2:
+ state->addr[0] = R_ST2;
+ break;
+ case 0x3:
+ state->addr[0] = R_ST3;
+ break;
+ case 0x4:
+ state->addr[0] = R_ST4;
+ break;
+ case 0x5:
+ state->addr[0] = R_ST5;
+ break;
+ case 0x6:
+ state->addr[0] = R_ST6;
+ break;
+ case 0x7:
+ state->addr[0] = R_ST7;
+ }
+ }
+ }
+ else
+ {
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_Q;
+
+ insn = low_insn[(state->modrm >> 3) & 0x07];
+ }
+
+ strcat (state->instruction, insn);
+}
+
+/* dd_opcode
+ * x87 escape.
+ */
+void
+dd_opcode (struct disassembly_state *state)
+{
+ char *insn;
+
+ read_modrm (state);
+
+ insn = ""; /* shut gcc up */
+
+ if (state->modrm > 0xbf)
+ {
+ if (state->modrm < 0xc8 || state->modrm > 0xef)
+ insn = "ill_dd";
+ else
+ {
+ if (state->modrm > 0xdf && state->modrm < 0xe8)
+ state->addr[1] = R_ST0;
+
+ switch (state->modrm >> 4)
+ {
+ case 0xc:
+ insn = "ffree";
+ break;
+ case 0xd:
+ if (state->modrm < 0xd8)
+ insn = "fst";
+ else
+ insn = "fstp";
+ break;
+ case 0xe:
+ if (state->modrm < 0xe8)
+ insn = "fucom";
+ else
+ insn = "fucomp";
+ }
+
+ switch (state->modrm & 0x07)
+ {
+ case 0x0:
+ state->addr[0] = R_ST0;
+ break;
+ case 0x1:
+ state->addr[0] = R_ST1;
+ break;
+ case 0x2:
+ state->addr[0] = R_ST2;
+ break;
+ case 0x3:
+ state->addr[0] = R_ST3;
+ break;
+ case 0x4:
+ state->addr[0] = R_ST4;
+ break;
+ case 0x5:
+ state->addr[0] = R_ST5;
+ break;
+ case 0x6:
+ state->addr[0] = R_ST6;
+ break;
+ case 0x7:
+ state->addr[0] = R_ST7;
+ }
+ }
+ }
+ else
+ {
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_B;
+
+ switch ((state->modrm >> 3) & 0x07)
+ {
+ case 0x0:
+ insn = "fld";
+ break;
+ case 0x2:
+ insn = "fst";
+ break;
+ case 0x3:
+ insn = "fstp";
+ break;
+ case 0x4:
+ insn = "frstor";
+ break;
+ case 0x6:
+ insn = "fsave";
+ break;
+ case 0x7:
+ insn = "fstsw";
+ break;
+ default:
+ insn = "ill_dd";
+ state->addr[0] = ADDR_0;
+ }
+ }
+
+ strcat (state->instruction, insn);
+}
+
+/* de_opcode
+ * x87 escape.
+ */
+void
+de_opcode (struct disassembly_state *state)
+{
+ char *insn;
+ char *low_insn[] = { "fiadd", "fimul", "ficom", "ficomp",
+ "fisub", "fisubr", "fidiv", "fidivr" };
+
+ read_modrm (state);
+
+ insn = ""; /* shut gcc up */
+
+ if (state->modrm > 0xbf)
+ {
+ if (state->modrm == 0xd9)
+ insn = "fcompp";
+ else if (state->modrm >> 4 == 0xd)
+ insn = "ill_de";
+ else
+ {
+ state->addr[1] = R_ST0;
+
+ switch (state->modrm & 0xf8)
+ {
+ case 0xc0:
+ insn = "faddp";
+ break;
+ case 0xc8:
+ insn = "fmulp";
+ break;
+ case 0xe0:
+ insn = "fsubrp";
+ break;
+ case 0xe8:
+ insn = "fsubp";
+ break;
+ case 0xf0:
+ insn = "fdivrp";
+ break;
+ case 0xf8:
+ insn = "fdivp";
+ }
+
+ switch (state->modrm & 0x07)
+ {
+ case 0x0:
+ state->addr[0] = R_ST0;
+ break;
+ case 0x1:
+ state->addr[0] = R_ST1;
+ break;
+ case 0x2:
+ state->addr[0] = R_ST2;
+ break;
+ case 0x3:
+ state->addr[0] = R_ST3;
+ break;
+ case 0x4:
+ state->addr[0] = R_ST4;
+ break;
+ case 0x5:
+ state->addr[0] = R_ST5;
+ break;
+ case 0x6:
+ state->addr[0] = R_ST6;
+ break;
+ case 0x7:
+ state->addr[0] = R_ST7;
+ }
+ }
+ }
+ else
+ {
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_W;
+
+ insn = low_insn[(state->modrm >> 3) & 0x07];
+ }
+
+ strcat (state->instruction, insn);
+}
+
+/* df_opcode
+ * x87 escape.
+ */
+void
+df_opcode (struct disassembly_state *state)
+{
+ char *insn;
+ char *low_insn[] = { "fild", "ill_df", "fist", "fistp",
+ "fbld", "fild", "fbstp", "fistp" };
+
+ read_modrm (state);
+
+ if (state->modrm > 0xbf)
+ {
+ if (state->modrm == 0xe0)
+ {
+ insn = "fstsw";
+ state->addr[0] = R_AX;
+ }
+ else if (state->modrm < 0xe8 || state->modrm > 0xf7)
+ insn = "ill_df";
+ else
+ {
+ state->addr[0] = R_ST0;
+
+ switch (state->modrm & 0x07)
+ {
+ case 0x0:
+ state->addr[1] = R_ST0;
+ break;
+ case 0x1:
+ state->addr[1] = R_ST1;
+ break;
+ case 0x2:
+ state->addr[1] = R_ST2;
+ break;
+ case 0x3:
+ state->addr[1] = R_ST3;
+ break;
+ case 0x4:
+ state->addr[1] = R_ST4;
+ break;
+ case 0x5:
+ state->addr[1] = R_ST5;
+ break;
+ case 0x6:
+ state->addr[1] = R_ST6;
+ break;
+ case 0x7:
+ state->addr[1] = R_ST7;
+ }
+
+ if (state->modrm > 0xef)
+ insn = "fcomip";
+ else
+ insn = "fucomip";
+ }
+ }
+ else
+ {
+ unsigned char enc = (state->modrm >> 3) & 0x07;
+
+ if (enc != 0x1)
+ {
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_B;
+ }
+
+ insn = low_insn[enc];
+ }
+
+ strcat (state->instruction, insn);
+}
+
+
+/* SSE/SSE2 opcode extensions - for these instructions an optional 3rd
+ byte specifies the instruction and its operands. */
+
+/* sse_prefix_to_index
+ * Convert an SSE/SSE2 opcode prefix to an index into the escape opcode
+ * tables.
+ */
+int
+sse_prefix_to_index (unsigned char sse_prefix)
+{
+ int index = 0;
+
+ switch (sse_prefix)
+ {
+ case 0x00:
+ index = 0;
+ break;
+ case 0x66:
+ index = 1;
+ break;
+ case 0xf2:
+ index = 2;
+ break;
+ case 0xf3:
+ index = 3;
+ }
+
+ return index;
+}
+
+
+/* sse_esc
+ * Process SSE/SSE2 escaped opcodes. The instruction is
+ * table[state->opcode[1] - base][sse_prefix_to_index (state->sse_prefix)]
+ * All relevant fields in STATE are filled in.
+ */
+void
+sse_esc (struct disassembly_state *state, insn table[][4], unsigned char base)
+{
+ insn instruction;
+
+ instruction = (table[state->opcode[1] - base]
+ [sse_prefix_to_index (state->sse_prefix)]);
+
+ strcat (state->instruction, instruction.instruction);
+
+ state->addr[0] = instruction.addr_method[0];
+ state->addr[1] = instruction.addr_method[1];
+ state->addr[2] = instruction.addr_method[2];
+
+ state->op[0] = instruction.operand_type[0];
+ state->op[1] = instruction.operand_type[1];
+ state->op[2] = instruction.operand_type[2];
+}
+
+
+/* esc_0f10_17
+ * Opcodes from 0f10 to 0f17.
+ */
+void
+esc_0f10_17 (struct disassembly_state *state)
+{
+ insn table[][4] = {
+ /* 0F10 */
+ {
+ /* 00 */
+ { "movups", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "movupd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "movsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "movss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* OF11 */
+ {
+ /* 00 */
+ { "movups", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "movupd", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "movsd", { ADDR_W, ADDR_V, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "movss", { ADDR_W, ADDR_V, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* OF12 */
+ {
+ /* 00 - odd situation, handled below */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 66 */
+ { "movlpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_Q, OP_S, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f12", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f20f13", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F13 */
+ {
+ /* 00 */
+ { "movlps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "movlpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f13", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f13", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F14 */
+ {
+ /* 00 */
+ { "unpcklps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "unpcklpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_Q, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f14", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f14", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F15 */
+ {
+ /* 00 */
+ { "unpckhps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "unpckhpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_Q, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f15", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f15", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F16 */
+ {
+ /* 00 - odd situation, handled below */
+ { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 66 */
+ { "movhpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f16", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f16", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F17 */
+ {
+ /* 00 */
+ { "movhps", { ADDR_W, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "movhpd", { ADDR_W, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f17", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f17", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ }
+ };
+
+ /* Unbelievable - not only are four of these instructions determined
+ by an extra prefix byte, they also (appear to) use the ModR/M for
+ an escape. Not only that, but they are not listed in sdmv2 as using
+ any kind of escape at all. Just try and assembling
+
+ movlps xmm0, a_64_bit_memory_location
+ movhlps xmm0, xmm1
+
+ movhps xmm0, a_64_bit_memory_location
+ movlhps xmm0, xmm1
+
+ and noting the difference. The only difference in each pair is in
+ the ModR/M byte, which would be OK if these were listed as using
+ the ModR/M for an escape, but they aren't. Grr.
+ */
+
+
+ if ((state->opcode[1] == 0x12 || state->opcode[1] == 0x16)
+ && state->sse_prefix == 0)
+ {
+ unsigned char opcode = state->opcode[1];
+ int index = 0;
+ insn table[] = {
+ /* 0f12 */
+ /* mem->reg only */
+ { "movlps", { ADDR_W, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* reg->reg only */
+ { "movhlps", { ADDR_V, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 0f16 */
+ /* mem->reg only */
+ { "movhps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* reg->reg only */
+ { "movlhps", { ADDR_V, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL }
+ };
+
+ read_modrm (state);
+
+ if (state->modrm >> 6 == 0x3) /* reg->reg */
+ {
+ if (opcode == 0x12)
+ index = 1;
+ else
+ index = 3;
+ }
+ else /* mem->reg */
+ {
+ if (opcode == 0x12)
+ index = 0;
+ else
+ index = 2;
+ }
+
+ strcat (state->instruction, table[index].instruction);
+
+ state->addr[0] = table[index].addr_method[0];
+ state->addr[1] = table[index].addr_method[1];
+ state->addr[2] = table[index].addr_method[2];
+
+ state->op[0] = table[index].operand_type[0];
+ state->op[1] = table[index].operand_type[1];
+ state->op[2] = table[index].operand_type[2];
+
+ return;
+ }
+
+
+ sse_esc (state, table, 0x10);
+}
+
+void
+esc_0f28_2f (struct disassembly_state *state)
+{
+ insn table[][4] = {
+ /* 0F28 */
+ {
+ /* 00 */
+ { "movaps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "movapd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f28", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f28", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F29 */
+ {
+ /* 00 */
+ { "movaps", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "movapd", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f29", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f29", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F2A */
+ {
+ /* 00 */
+ { "cvtpi2ps", { ADDR_V, ADDR_Q, ADDR_0 }, { OP_PS, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "cvtpi2pd", { ADDR_V, ADDR_Q, ADDR_0 }, { OP_PD, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "cvtsi2sd", { ADDR_V, ADDR_E, ADDR_0 }, { OP_SD, OP_D, OP_0 }, NULL },
+ /* F3 */
+ { "cvtsi2ss", { ADDR_V, ADDR_E, ADDR_0 }, { OP_SS, OP_D, OP_0 }, NULL }
+ },
+ /* 0F2B */
+ {
+ /* 00 */
+ { "movntps", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 - misprinted in sdmv2 as movntps */
+ { "movntpd", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f2b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f2b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F2C */
+ {
+ /* 00 */
+ { "cvttps2pi", { ADDR_Q, ADDR_W, ADDR_0 }, { OP_Q, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "cvttpd2pi", { ADDR_Q, ADDR_W, ADDR_0 }, { OP_DQ, OP_PD, OP_0}, NULL },
+ /* F2 */
+ { "cvttsd2si", { ADDR_G, ADDR_W, ADDR_0 }, { OP_D, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "cvttss2si", { ADDR_G, ADDR_W, ADDR_0 }, { OP_D, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F2D */
+ {
+ /* 00 */
+ { "cvtps2pi", { ADDR_Q, ADDR_W, ADDR_0 }, { OP_Q, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "cvtpd2pi", { ADDR_Q, ADDR_W, ADDR_0 }, { OP_DQ, OP_PD, OP_0}, NULL },
+ /* F2 */
+ { "cvtsd2si", { ADDR_G, ADDR_W, ADDR_0 }, { OP_D, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "cvtss2si", { ADDR_G, ADDR_W, ADDR_0 }, { OP_D, OP_SS, OP_0 }, NULL }
+ },
+ /* OF2E */
+ {
+ /* 00 */
+ { "ucomiss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL },
+ /* 66 */
+ { "ucomisd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f2e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f2e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F2F */
+ {
+ /* 00 */
+ { "comiss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "comisd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f2f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f2f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ }
+ };
+
+ sse_esc (state, table, 0x28);
+}
+
+void
+esc_0f50_70 (struct disassembly_state *state)
+{
+ insn table[][4] = {
+ /* 0F50 */
+ {
+ /* 00 */
+ { "movmskps", { ADDR_E, ADDR_V, ADDR_0 }, { OP_D, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "movmskpd", { ADDR_E, ADDR_V, ADDR_0 }, { OP_D, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f50", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f50", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F51 */
+ {
+ /* 00 */
+ { "sqrtps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "sqrtpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "sqrtsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "sqrtss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F52 */
+ {
+ /* 00 */
+ { "rsqrtps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "ill_660f52", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f52", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "rsqrtss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F53 */
+ {
+ /* 00 */
+ { "rcpps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "ill_660f52", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f52", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "rcpss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F54 */
+ {
+ /* 00 */
+ { "andps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "andpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f54", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f54", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F55 */
+ {
+ /* 00 */
+ { "andnps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "andnpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f55", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f55", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F56 */
+ {
+ /* 00 */
+ { "orps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "orpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f56", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f56", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F57 */
+ {
+ /* 00 */
+ { "xorps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "xorpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f57", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f57", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F58 */
+ {
+ /* 00 */
+ { "addps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "addpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "addsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "addss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F59 */
+ {
+ /* 00 */
+ { "mulps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "mulpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "mulsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "mulss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F5A */
+ {
+ /* 00 */
+ { "cvtps2pd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "cvtpd2ps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "cvtsd2ss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "cvtss2sd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F5B */
+ {
+ /* 00 */
+ { "cvtdq2ps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_DQ, OP_0 }, NULL },
+ /* 66 */
+ { "cvtps2dq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_PS, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f5b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "cvttps2dq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_PS, OP_0}, NULL }
+ },
+ /* 0F5C */
+ {
+ /* 00 */
+ { "subps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "subpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "subsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "subss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F5D */
+ {
+ /* 00 */
+ { "minps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "minpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "minsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "minss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F5E */
+ {
+ /* 00 */
+ { "divps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "divpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "divsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "divss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F5F */
+ {
+ /* 00 */
+ { "maxps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL },
+ /* 66 */
+ { "maxpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL },
+ /* F2 */
+ { "maxsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL },
+ /* F3 */
+ { "maxss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL }
+ },
+ /* 0F60 */
+ {
+ /* 00 */
+ { "punpcklbw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL },
+ /* 66 */
+ { "punpcklbw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f60", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f60", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F61 */
+ {
+ /* 00 */
+ { "punpcklwd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL },
+ /* 66 */
+ { "punpcklwd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f61", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f61", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F62 */
+ {
+ /* 00 */
+ { "punpckldq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL },
+ /* 66 */
+ { "punpckldq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f62", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f62", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F63 */
+ {
+ /* 00 */
+ { "packsswb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "packsswb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f63", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f63", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F64 */
+ {
+ /* 00 */
+ { "pcmpgtb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pcmpgtb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f64", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f64", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F65 */
+ {
+ /* 00 */
+ { "pcmpgtw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pcmpgtw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f65", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f65", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F66 */
+ {
+ /* 00 */
+ { "pcmpgtd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pcmpgtd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f66", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f66", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F67 */
+ {
+ /* 00 */
+ { "packuswb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "packuswb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f67", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f67", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F68 */
+ {
+ /* 00 */
+ { "punpckhbw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL },
+ /* 66 */
+ { "punpckhbw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f68", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f68", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F69 */
+ {
+ /* 00 */
+ { "punpckhwd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL },
+ /* 66 */
+ { "punpckhwd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f69", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f69", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F6A */
+ {
+ /* 00 */
+ { "punpckhdq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL },
+ /* 66 */
+ { "punpckhdq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f6a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f6a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F6B */
+ {
+ /* 00 */
+ { "packssdw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL },
+ /* 66 */
+ { "packssdw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f6b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f6b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F6C */
+ {
+ /* 00 */
+ { "ill_0f6c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 66 */
+ { "punpcklqdq", { ADDR_V, ADDR_W, ADDR_0}, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f6c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f6c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F6D */
+ {
+ /* 00 */
+ { "ill_0f6d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 66 */
+ { "punpckhqdq", { ADDR_V, ADDR_W, ADDR_0}, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20f6d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f6d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F6E */
+ {
+ /* 00 */
+ { "movd", { ADDR_P, ADDR_E, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL },
+ /* 66 */
+ { "movd", { ADDR_V, ADDR_E, ADDR_0 }, { OP_DQ, OP_D, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f6e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f6e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F6F */
+ {
+ /* 00 */
+ { "movq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "movdqa", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f6f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "movdqu", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ },
+ /* 0F70 */
+ {
+ /* 00 */
+ { "pshufw", { ADDR_P, ADDR_Q, ADDR_I }, { OP_Q, OP_Q, OP_B }, NULL },
+ /* 66 */
+ { "pshufd", { ADDR_V, ADDR_W, ADDR_I }, { OP_DQ, OP_DQ, OP_B }, NULL },
+ /* F2 */
+ { "pshuflw", { ADDR_V, ADDR_W, ADDR_I }, { OP_DQ, OP_DQ, OP_B }, NULL },
+ /* F3 */
+ { "pshufhw", { ADDR_V, ADDR_W, ADDR_I }, { OP_DQ, OP_DQ, OP_B }, NULL }
+ }
+ };
+
+ sse_esc (state, table, 0x50);
+}
+
+void
+esc_0f74_76 (struct disassembly_state *state)
+{
+ insn table[][4] = {
+ /* 0F74 */
+ {
+ /* 00 */
+ { "pcmpeqb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pcmpeqb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f74", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f74", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F75 */
+ {
+ /* 00 */
+ { "pcmpeqw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pcmpeqw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f75", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f75", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0F76 */
+ {
+ /* 00 */
+ { "pcmpeqd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pcmpeqd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f76", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30f76", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ }
+ };
+
+ sse_esc (state, table, 0x74);
+}
+
+void
+esc_0f7e_7f (struct disassembly_state *state)
+{
+ insn table[][4] = {
+ /* OF7E */
+ {
+ /* 00 */
+ { "movd", { ADDR_E, ADDR_P, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL },
+ /* 66 */
+ { "movd", { ADDR_E, ADDR_V, ADDR_0 }, { OP_D, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f7e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "movq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL }
+ },
+ /* 0F7F */
+ {
+ /* 00 */
+ { "movq", { ADDR_Q, ADDR_P, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "movdqa", { ADDR_W, ADDR_V, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20f7f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "movdqu", { ADDR_W, ADDR_V, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL }
+ }
+ };
+
+ sse_esc (state, table, 0x7e);
+}
+
+void
+esc_0fc2 (struct disassembly_state *state)
+{
+ insn table[][4] = {
+ /* 0FC2 */
+ {
+ /* 00 */
+ { "cmpps", { ADDR_V, ADDR_W, ADDR_I }, { OP_PS, OP_PS, OP_B }, NULL },
+ /* 66 */
+ { "cmppd", { ADDR_V, ADDR_W, ADDR_I }, { OP_PD, OP_PD, OP_B }, NULL },
+ /* F2 */
+ { "cmpsd", { ADDR_V, ADDR_W, ADDR_I }, { OP_SD, OP_SD, OP_B }, NULL },
+ /* F3 */
+ { "cmpss", { ADDR_V, ADDR_W, ADDR_I }, { OP_SS, OP_SS, OP_B }, NULL },
+ }
+ };
+
+ sse_esc (state, table, 0xc2);
+}
+
+void
+esc_0fc4_c6 (struct disassembly_state *state)
+{
+ insn table[][4] = {
+ /* 0FC4 */
+ {
+ /* 00 */
+ { "pinsrw", { ADDR_P, ADDR_E, ADDR_I }, { OP_Q, OP_D, OP_B }, NULL },
+ /* 66 */
+ { "pinsrw", { ADDR_V, ADDR_E, ADDR_I }, { OP_DQ, OP_D, OP_B }, NULL },
+ /* F2 */
+ { "ill_f20fc4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fc4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FC5 */
+ {
+ /* 00 */
+ { "pextrw", { ADDR_G, ADDR_P, ADDR_I }, { OP_D, OP_Q, OP_B }, NULL },
+ /* 66 */
+ { "pextrw", { ADDR_G, ADDR_V, ADDR_I }, { OP_D, OP_DQ, OP_B }, NULL },
+ /* F2 */
+ { "ill_f20fc5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fc5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FC6 */
+ {
+ /* 00 */
+ { "shufps", { ADDR_V, ADDR_W, ADDR_I }, { OP_PS, OP_PS, OP_B }, NULL },
+ /* 66 */
+ { "shufpd", { ADDR_V, ADDR_W, ADDR_I }, { OP_PD, OP_PD, OP_B }, NULL },
+ /* F2 */
+ { "ill_f20fc6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fc6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ }
+ };
+
+ sse_esc (state, table, 0xc4);
+}
+
+void
+esc_0fd1_ef (struct disassembly_state *state)
+{
+ insn table[][4] = {
+ /* 0FD1 */
+ {
+ /* 00 */
+ { "psrlw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psrlw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fd1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fd1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FD2 */
+ {
+ /* 00 */
+ { "psrld", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psrld", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fd2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fd2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FD3 */
+ {
+ /* 00 */
+ { "psrlq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psrlq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fd3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fd3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FD4 */
+ {
+ /* 00 */
+ { "paddq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "paddq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fd4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fd4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FD5 */
+ {
+ /* 00 */
+ { "pmulw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pmulw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fd5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fd5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FD6 */
+ {
+ /* 00 */
+ { "ill_0fd6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 66 */
+ { "movq", { ADDR_W, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* F2 */
+ { "movdq2q", { ADDR_P, ADDR_W, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* F3 */
+ { "movq2dq", { ADDR_V, ADDR_Q, ADDR_0 }, { OP_DQ, OP_Q, OP_0 }, NULL }
+ },
+ /* 0FD7 */
+ {
+ /* 00 */
+ { "pmovmskb", { ADDR_G, ADDR_P, ADDR_0 }, { OP_D, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pmovmksb", { ADDR_G, ADDR_V, ADDR_0 }, { OP_D, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fd7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fd7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FD8 */
+ {
+ /* 00 */
+ { "psubusb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psubusb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fd8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fd8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FD9 */
+ {
+ /* 00 */
+ { "psubusw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psubusw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fd9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fd9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FDA */
+ {
+ /* 00 */
+ { "pminub", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pminub", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fda", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fda", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FDB */
+ {
+ /* 00 */
+ { "pand", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pand", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fdb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fdb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FDC */
+ {
+ /* 00 */
+ { "paddusb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "paddusb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fdc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fdc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FDD */
+ {
+ /* 00 */
+ { "paddusw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "paddusw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fdd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fdd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FDE */
+ {
+ /* 00 */
+ { "pmaxub", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pmaxub", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fde", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fde", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FDF */
+ {
+ /* 00 */
+ { "pandn", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pandn", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fdf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fdf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FE0 */
+ {
+ /* 00 */
+ { "pavgb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pavgb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fe0", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fe0", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FE1 */
+ {
+ /* 00 */
+ { "praw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "praw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fe1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fe1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FE2 */
+ {
+ /* 00 */
+ { "prad", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "prad", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fe2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fe2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FE3 */
+ {
+ /* 00 */
+ { "pavgw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pavgw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fe3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fe3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FE4 */
+ {
+ /* 00 */
+ { "pmulhuw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pmulhuw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fe4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fe4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FE5 */
+ {
+ /* 00 */
+ { "pmulhw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pmulhw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fe5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fe5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FE6 */
+ {
+ /* 00 */
+ { "ill_0fe6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* 66 */
+ { "cvttpd2dq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_PD, OP_0}, NULL },
+ /* F2 */
+ { "cvtpd2dq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_PD, OP_0 }, NULL },
+ /* F3 */
+ { "cvtdq2pd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_DQ, OP_0 }, NULL }
+ },
+ /* 0FE7 */
+ {
+ /* 00 */
+ { "movntq", { ADDR_G, ADDR_P, ADDR_0 }, { OP_D, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "movntdq", { ADDR_W, ADDR_V, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fe7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fe7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FE8 */
+ {
+ /* 00 */
+ { "psubsb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psubsb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fe8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fe8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FE9 */
+ {
+ /* 00 */
+ { "psubsw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psubsw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fe9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fe9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FEA */
+ {
+ /* 00 */
+ { "pminusw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pminusw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fea", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fea", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FEB */
+ {
+ /* 00 */
+ { "por", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "por", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20feb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30feb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FEC */
+ {
+ /* 00 */
+ { "paddsb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "paddsb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fec", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fec", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FED */
+ {
+ /* 00 */
+ { "paddsw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "paddsw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fed", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fed", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FEE */
+ {
+ /* 00 */
+ { "pmaxsw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pmaxsw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fee", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fee", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FEF */
+ {
+ /* 00 */
+ { "pxor", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pxor", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20fef", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30fef", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ }
+ };
+
+ sse_esc (state, table, 0xd1);
+}
+
+void
+esc_0ff1_fe (struct disassembly_state *state)
+{
+ insn table[][4] = {
+ /* 0FF1 */
+ {
+ /* 00 */
+ { "psllw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psllw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ff1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ff1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FF2 */
+ {
+ /* 00 */
+ { "pslld", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pslld", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ff2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ff2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FF3 */
+ {
+ /* 00 */
+ { "psllq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psllq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ff3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ff3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FF4 */
+ {
+ /* 00 */
+ { "pmuludq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pmuludq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ff4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ff4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FF5 */
+ {
+ /* 00 */
+ { "pmaddwd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "pmaddwd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ff5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ff5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FF6 */
+ {
+ /* 00 */
+ { "psadbw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psadbw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ff6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ff6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FF7 */
+ {
+ /* 00 */
+ { "maskmovq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_PI, OP_PI, OP_0 }, NULL },
+ /* 66 */
+ { "maskmovdqu", { ADDR_V, ADDR_W, ADDR_0}, { OP_DQ, OP_DQ, OP_0}, NULL },
+ /* F2 */
+ { "ill_f20ff7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ff7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FF8 */
+ {
+ /* 00 */
+ { "psubb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psubb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ff8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ff8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FF9 */
+ {
+ /* 00 */
+ { "psubw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psubw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ff9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ff9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FFA */
+ {
+ /* 00 */
+ { "psubd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psubd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ffa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ffa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FFB */
+ {
+ /* 00 */
+ { "psubq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "psubq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ffb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ffb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FFC */
+ {
+ /* 00 */
+ { "paddb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "paddb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ffc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ffc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FFD */
+ {
+ /* 00 */
+ { "paddw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "paddw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ffd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ffd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ },
+ /* 0FFE */
+ {
+ /* 00 */
+ { "paddd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL },
+ /* 66 */
+ { "paddd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL },
+ /* F2 */
+ { "ill_f20ffe", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL },
+ /* F3 */
+ { "ill_f30ffe", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL }
+ }
+ };
+
+ sse_esc (state, table, 0xf1);
+}
+
+
+/* opcode extension groups - these use bits 5-3 of the ModR/M for the insn */
+
+/* immed_grp_1
+ * In group 1, the opcode may be from 0x80 to 0x83. The instruction is
+ * selected based on bits 5-3 of the ModR/M byte.
+ */
+void
+immed_grp_1 (struct disassembly_state *state) /* opcodes 80-83 */
+{
+ unsigned char encoding;
+ char *instructions[] = { "add", "or", "adc", "sbb",
+ "and", "sub", "xor", "cmp" };
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+
+ strcat (state->instruction, instructions[encoding]);
+}
+
+void
+shift_grp_2 (struct disassembly_state *state) /* opcodes C0-C1, D0-D3 */
+{
+ unsigned char encoding;
+ char *instructions[] = { "rol", "ror", "rcl", "rcr",
+ "shl", "shr", "ill_grp_2", "sar" };
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+
+ strcat (state->instruction, instructions[encoding]);
+}
+
+void
+unary_grp_3 (struct disassembly_state *state) /* opcodes F6-F7 */
+{
+ unsigned char encoding, opcode;
+ char *instructions[] = { "test", "ill_grp_3", "not", "neg",
+ "mul", "imul", "div", "idiv" };
+ enum addr_method addr[8][2] = { { ADDR_I, ADDR_I }, { ADDR_0, ADDR_0 },
+ { ADDR_0, ADDR_0 }, { ADDR_0, ADDR_0 },
+ { R_AL, R_AX }, { R_AL, R_AX },
+ { R_AL, R_AX }, { R_AL, R_AX } };
+ enum operand_type op[8][2] = { { OP_B, OP_V }, { OP_0, OP_0 },
+ { OP_0, OP_0 }, { OP_0, OP_0 },
+ { OP_0, OP_E }, { OP_0, OP_E },
+ { OP_0, OP_E }, { OP_0, OP_E } };
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+ opcode = state->opcode[0] - 0xf6;
+
+ strcat (state->instruction, instructions[encoding]);
+
+ state->addr[1] = addr[encoding][opcode];
+ state->op[1] = op[encoding][opcode];
+}
+
+void
+grp_4 (struct disassembly_state *state) /* opcode FE */
+{
+ unsigned char encoding;
+ char *instruction;
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+
+ switch (encoding)
+ {
+ case 0:
+ instruction = "inc";
+ break;
+ case 1:
+ instruction = "dec";
+ break;
+ default:
+ instruction = "ill_grp_4";
+ }
+
+ if (encoding < 2)
+ {
+ state->addr[0] = ADDR_E;
+ state->op[0] = OP_B;
+ }
+
+ strcat (state->instruction, instruction);
+}
+
+void
+grp_5 (struct disassembly_state *state) /* opcode FF */
+{
+ unsigned char encoding;
+ char *instructions[] = { "inc", "dec", "call", "call far",
+ "jmp", "jmp far", "push", "ill_grp_5" };
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+
+ strcat (state->instruction, instructions[encoding]);
+
+ if (encoding == 0x07) return;
+
+ state->addr[0] = ADDR_E;
+
+ if (encoding == 0x03 || encoding == 0x05)
+ state->op[0] = OP_P;
+ else
+ state->op[0] = OP_V;
+}
+
+void
+grp_6 (struct disassembly_state *state) /* opcode 0F00 */
+{
+ unsigned char encoding;
+ char *instructions[] = { "sldt", "str", "lldt", "ltr", "verr", "verw" };
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+
+ if (encoding > 0x05)
+ {
+ strcat (state->instruction, "ill_grp_6");
+ return;
+ }
+
+ strcat (state->instruction, instructions[encoding]);
+
+ state->addr[0] = ADDR_E;
+ state->op[0] = (encoding < 2) ? OP_V : OP_W;
+}
+
+void
+grp_7 (struct disassembly_state *state) /* opcode 0F01 */
+{
+ unsigned char encoding;
+ char *instructions[] = { "sgdt", "sidt", "lgdt", "lidt",
+ "smsw", "ill_grp_7", "lmsw", "invlpg" };
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+
+ strcat (state->instruction, instructions[encoding]);
+
+ if (encoding == 0x05) return;
+
+ if (encoding < 4)
+ {
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_S;
+ }
+ else if (encoding == 0x07)
+ {
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_B;
+ }
+ else
+ {
+ state->addr[0] = ADDR_E;
+ state->op[0] = OP_W;
+ }
+}
+
+void
+grp_8 (struct disassembly_state *state) /* opcode 0FBA */
+{
+ unsigned char encoding;
+ char *instructions[] = { "bt", "bts", "btr", "btc" };
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+
+ if (encoding < 4)
+ {
+ strcat (state->instruction, "ill_grp_8");
+ return;
+ }
+
+ encoding -= 4;
+ strcat (state->instruction, instructions[encoding]);
+}
+
+void
+grp_9 (struct disassembly_state *state) /* opcode 0FC7 */
+{
+ unsigned char encoding, mod;
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+ mod = (state->modrm >> 6) & 0x03;
+
+ if (mod != 0x03 && encoding == 0x01)
+ {
+ strcat (state->instruction, "cmpxch8b");
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_Q;
+ }
+ else
+ strcat (state->instruction, "ill_grp_9");
+}
+
+void
+grp_10 (struct disassembly_state *state) /* opcode 0FB9 */
+{
+ strcat (state->instruction, "ud\t# grp_10");
+}
+
+void
+grp_11 (struct disassembly_state *state) /* opcodes C6-C7 */
+{
+ read_modrm (state);
+
+ if ((state->modrm >> 3) & 0x07)
+ {
+ strcat (state->instruction, "ill_grp_11");
+ return;
+ }
+
+ strcat (state->instruction, "mov");
+ state->addr[0] = ADDR_E;
+ state->addr[1] = ADDR_I;
+
+ if (state->opcode[0] == 0xc6)
+ state->op[0] = state->op[1] = OP_B;
+ else
+ state->op[0] = state->op[1] = OP_V;
+}
+
+void
+grp_12 (struct disassembly_state *state) /* opcode 0F71 */
+{
+ unsigned char encoding, mod, sse_prefix;
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+ mod = (state->modrm >> 6) & 0x03;
+ sse_prefix = state->sse_prefix;
+
+ state->prefix[0] = state->prefix[3] = 0x00; /* clear out grp 1 & 3 prefix */
+
+ if (mod != 0x03) goto ILL_GRP_12;
+ if (sse_prefix != 0x66 && sse_prefix != 0x00) goto ILL_GRP_12;
+
+ switch (encoding)
+ {
+ case 0x02:
+ strcat (state->instruction, "psrlw");
+ break;
+ case 0x04:
+ strcat (state->instruction, "psraw");
+ break;
+ case 0x06:
+ strcat (state->instruction, "psllw");
+ break;
+ default:
+ goto ILL_GRP_12;
+ }
+
+ state->addr[0] = ADDR_P;
+ state->addr[1] = ADDR_I;
+
+ if (sse_prefix == 0x66)
+ state->op[0] = OP_DQ;
+ else
+ state->op[0] = OP_Q;
+
+ state->op[1] = OP_B;
+
+ return;
+
+ ILL_GRP_12:
+ strcat (state->instruction, "ill_grp_12");
+}
+
+void
+grp_13 (struct disassembly_state *state) /* opcode 0F72 */
+{
+ unsigned char encoding, mod, sse_prefix;
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+ mod = (state->modrm >> 6) & 0x03;
+ sse_prefix = state->sse_prefix;
+
+ state->prefix[0] = state->prefix[2] = 0x00; /* clear out grp 1 & 3 prefix */
+
+ if (mod != 0x03) goto ILL_GRP_13;
+ if (sse_prefix != 0x66 && sse_prefix != 0x00) goto ILL_GRP_13;
+
+ switch (encoding)
+ {
+ case 0x02:
+ strcat (state->instruction, "psrld");
+ break;
+ case 0x04:
+ strcat (state->instruction, "psrad");
+ break;
+ case 0x06:
+ strcat (state->instruction, "pslld");
+ break;
+ default:
+ goto ILL_GRP_13;
+ }
+
+ if (sse_prefix == 0x66)
+ {
+ state->addr[0] = ADDR_P;
+ state->op[0] = OP_DQ;
+ }
+ else
+ {
+ state->addr[0] = ADDR_W;
+ state->op[0] = OP_Q;
+ }
+
+ state->addr[1] = ADDR_I;
+ state->op[1] = OP_B;
+
+ return;
+
+ ILL_GRP_13:
+ strcat (state->instruction, "ill_grp_13");
+}
+
+void
+grp_14 (struct disassembly_state *state) /* opcode 0F73 */
+{
+ unsigned char encoding, mod, sse_prefix;
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+ mod = (state->modrm >> 6) & 0x03;
+ sse_prefix = state->sse_prefix;
+
+ state->prefix[0] = state->prefix[3] = 0x00; /* clear out grp 1 & 3 prefix */
+
+ if (mod != 0x03) goto ILL_GRP_14;
+
+ /* For encoding 0x02 and 0x06, valid sse prefix values are 0x00 and 0x66.
+ For encoding 0x03 and 0x07, the only valid sse_prefix is 0x66 */
+ if ((!((encoding == 0x02 || encoding == 0x06)
+ && (sse_prefix || (sse_prefix == 0x66))))
+ || (!((encoding == 0x03 || encoding == 0x07) && (sse_prefix == 0x66))))
+ goto ILL_GRP_14;
+
+ switch (encoding)
+ {
+ case 0x02:
+ strcat (state->instruction, "psrlq");
+ break;
+ case 0x03:
+ strcat (state->instruction, "psrldq");
+ break;
+ case 0x06:
+ strcat (state->instruction, "psllq");
+ break;
+ case 0x07:
+ strcat (state->instruction, "pslldq");
+ break;
+ default:
+ goto ILL_GRP_14;
+ }
+
+ if (sse_prefix == 0x66)
+ {
+ state->addr[0] = ADDR_W;
+ state->op[0] = OP_DQ;
+ }
+ else
+ {
+ state->addr[0] = ADDR_P;
+ state->op[0] = OP_Q;
+ }
+
+ state->addr[1] = ADDR_I;
+ state->op[0] = OP_B;
+
+ ILL_GRP_14:
+ strcpy (state->instruction, "ill_grp_14");
+}
+
+void
+grp_15 (struct disassembly_state *state) /* opcode 0FAE */
+{
+ unsigned char encoding, mod;
+ char *insn;
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+ mod = (state->modrm >> 6) & 0x03;
+ insn = "";
+
+ if ((mod == 0x03 && encoding < 0x05)
+ || (mod != 0x03 && (encoding < 0x07 && encoding > 0x03)))
+ {
+ strcat (state->instruction, "ill_grp_15");
+ return;
+ }
+
+ if (mod == 0x03)
+ {
+ switch (encoding)
+ {
+ case 0x05:
+ insn = "lfence";
+ break;
+ case 0x06:
+ insn = "mfence";
+ break;
+ case 0x07:
+ insn = "sfence";
+ break;
+ }
+ }
+ else
+ {
+ switch (encoding)
+ {
+ case 0x00:
+ insn = "fxsave";
+ break;
+ case 0x01:
+ insn = "fxrstor";
+ break;
+ case 0x02:
+ insn = "ldmxcsr";
+ break;
+ case 0x03:
+ insn = "stmxcsr";
+ break;
+ case 0x07:
+ insn = "clflush";
+ break;
+ }
+
+ /* addr/op for these is prob Mb */
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_B;
+ }
+
+ strcat (state->instruction, insn);
+}
+
+void
+grp_16 (struct disassembly_state *state) /* opcode OF18 */
+{
+ unsigned char encoding, mod;
+
+ read_modrm (state);
+
+ encoding = (state->modrm >> 3) & 0x07;
+ mod = (state->modrm >> 6) & 0x03;
+
+ if (mod == 0x03 || encoding > 0x03)
+ {
+ strcat (state->instruction, "ill_grp_16");
+ return;
+ }
+
+ switch (encoding)
+ {
+ case 0x00:
+ strcat (state->instruction, "prefetchnta");
+ break;
+ case 0x01:
+ strcat (state->instruction, "prefetcht0");
+ break;
+ case 0x02:
+ strcat (state->instruction, "prefetcht1");
+ break;
+ case 0x03:
+ strcat (state->instruction, "prefetcht2");
+ break;
+ }
+
+ /* although sdmv2 doesn't specify anywhere, the addr/op for these
+ instructions is Mb */
+ state->addr[0] = ADDR_M;
+ state->op[0] = OP_B;
+}
+
+
+/* this is used by a few other functions */
+void format_addr_m (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op);
+
+/* the names of the registers */
+char *register_names[5][8] = {
+ { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }, /* 8 */
+ { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }, /* 16 */
+ { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }, /* 32 */
+ { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, /* 64 */
+ { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" } /* 128 */
+};
+
+
+/* The format_foo functions use the instruction, addressing method, and
+ * operand type to make a human readable operand.
+ */
+
+/* format_addr_a
+ * Direct address. No ModR/M byte, no base register, no index register,
+ * no scaling factor. Simple, right??
+ */
+void
+format_addr_a (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ uint16_t segment, short_offset;
+ uint32_t long_offset, offset;
+
+ /* this only make sense as Ap, so a check will be left in for
+ other circumstances, but that's all */
+ if (op == OP_P)
+ {
+ /* get the segment */
+ memcpy (&segment, state->text + state->pos, 2);
+ state->pos += 2;
+
+ /* get the offset */
+ if (state->opd_size == SIZE_16) /* 16 bit */
+ {
+ memcpy (&short_offset, state->text + state->pos, 2);
+ state->pos += 2;
+ offset = short_offset;
+ }
+ else /* 32 bit */
+ {
+ memcpy (&long_offset, state->text + state->pos, 4);
+ state->pos += 4;
+ offset = long_offset;
+ }
+
+ /* print the absolute address as either ssss:oooo or ssss:oooooooo */
+ sprintf (state->scratch, "%04hx:%0*x", segment,
+ (state->opd_size == SIZE_16) ? 4 : 8, offset);
+ }
+ else
+ {
+ fprintf (stderr, "%s: internal error at %d\n", __FILE__, __LINE__);
+ }
+}
+
+/* format_addr_c
+ * Bits 5-3 of the ModR/M byte selects a control register.
+ */
+void
+format_addr_c (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ char *control_reg;
+
+ switch ((state->modrm >> 3) & 0x07)
+ {
+ case 0:
+ control_reg = "cr0";
+ break;
+ case 2:
+ control_reg = "cr2";
+ break;
+ case 3:
+ control_reg = "cr3";
+ break;
+ case 4:
+ control_reg = "cr4";
+ break;
+ default:
+ control_reg = "cr_undef";
+ }
+
+ strcat (state->instruction, control_reg);
+}
+
+/* format_addr_d
+ * Bits 5-3 of the ModR/M byte select a debug register.
+ */
+void
+format_addr_d (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ char *debug_reg;
+
+ switch ((state->modrm >> 3) & 0x07)
+ {
+ case 0:
+ debug_reg = "dr0";
+ break;
+ case 1:
+ debug_reg = "dr1";
+ break;
+ case 2:
+ debug_reg = "dr2";
+ break;
+ case 3:
+ debug_reg = "dr3";
+ break;
+ case 6:
+ debug_reg = "dr6";
+ break;
+ case 7:
+ debug_reg = "dr7";
+ break;
+ default:
+ debug_reg = "dr_undef";
+ }
+
+ strcat (state->instruction, debug_reg);
+}
+
+/* format_addr_e
+ * Depending on the ModR/M byte, the operand is either a register,
+ * or a memory address with optional base register, index register
+ * scaling factor, and displacement. Yuk.
+ */
+void
+format_addr_e (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ /* If ModR/M specifies a register, then OP will specify its width e.g.
+ ax/eax. If ModR/M specifies an address, then OP will specify
+ the data pointed to e.g. byte ptr/word ptr/... */
+ unsigned char rm;
+ enum reg_size reg_size = REG_SIZE_128;
+
+ rm = state->modrm & 0x07;
+
+ switch (op)
+ {
+ case OP_B: /* 1 */
+ reg_size = REG_SIZE_8;
+ break;
+ case OP_C: /* 1/2 */
+ if (state->opd_size == SIZE_16)
+ {
+ reg_size = REG_SIZE_8;
+ break;
+ }
+ case OP_W: /* 2 */
+ reg_size = REG_SIZE_16;
+ break;
+ case OP_V: /* 2/4 */
+ if (state->opd_size == SIZE_16)
+ {
+ reg_size = REG_SIZE_16;
+ break;
+ }
+ case OP_D: /* 4 */
+ case OP_SI: /* 4 */
+ reg_size = REG_SIZE_32;
+ break;
+ case OP_Q: /* 8 */
+ case OP_PI: /* 8 */
+ reg_size = REG_SIZE_64;
+ break;
+ case OP_DQ: /* 16 */
+ case OP_PS: /* 16 */
+ case OP_PD: /* 16 */
+ reg_size = REG_SIZE_128;
+ default:
+ ;
+ }
+
+
+ if (state->modrm >> 6 == 0x3) /* specifies a register */
+ strcat (state->instruction, register_names[reg_size][rm]);
+ else
+ {
+ char *size;
+
+ switch (reg_size)
+ {
+ case REG_SIZE_8:
+ size = "byte ";
+ break;
+ case REG_SIZE_16:
+ size = "word ";
+ break;
+ case REG_SIZE_32:
+ size = "dword ";
+ break;
+ case REG_SIZE_64:
+ size = "qword ";
+ break;
+ case REG_SIZE_128:
+ size = "oword ";
+ break;
+ default:
+ size = "";
+ }
+
+ if (state->addr[0] != ADDR_G
+ && state->addr[1] != ADDR_G
+ && state->addr[2] != ADDR_G)
+ strcat (state->instruction, size);
+
+ format_addr_m (state, addr, op); /* pass off the mem reference */
+ }
+}
+
+/* format_addr_g
+ * The Reg field of the ModR/M specifies a register.
+ */
+void
+format_addr_g (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ enum reg_size reg_size;
+ int reg_field;
+
+ /* handy default - most likely incorrect so apt to be noticed */
+ reg_size = REG_SIZE_128;
+ reg_field = (state->modrm >> 3) & 0x07;
+
+ switch (op)
+ {
+ case OP_B: /* 8 */
+ reg_size = REG_SIZE_8;
+ break;
+ case OP_C: /* 8/16 */
+ if (state->opd_size == SIZE_16)
+ {
+ reg_size = REG_SIZE_8;
+ break;
+ }
+ /* else fall through */
+ case OP_W: /* 16 */
+ reg_size = REG_SIZE_16;
+ break;
+ case OP_V: /* 16/32 */
+ if (state->opd_size == SIZE_16)
+ {
+ reg_size = REG_SIZE_16;
+ break;
+ }
+ /* else fall through */
+ case OP_D: /* 32 */
+ case OP_SI: /* 32 */
+ reg_size = REG_SIZE_32;
+ break;
+ default: /* the register shouldn't be larger than 32 bits */
+ fprintf (stderr, "%s: internal error at %d\n", __FILE__, __LINE__);
+ }
+
+
+ strcat (state->instruction, register_names[reg_size][reg_field]);
+}
+
+/* format_addr_i
+ * Immediate data.
+ */
+void
+format_addr_i (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ /* immediate data is 1, 2, or 4 bytes */
+ int immed_size = 0;
+ uint8_t byte;
+ uint16_t word;
+ uint32_t dword, immed_data = 0;
+ struct symtab *sym;
+
+ switch (op)
+ {
+ case OP_B: /* 8 */
+ immed_size = 1;
+ break;
+ case OP_C: /* 8/16 */
+ if (state->opd_size == SIZE_16)
+ {
+ immed_size = 1;
+ break;
+ }
+ /* else fall through */
+ case OP_W: /* 16 */
+ immed_size = 2;
+ break;
+ case OP_V: /* 16/32 */
+ if (state->opd_size == SIZE_16)
+ {
+ immed_size = 2;
+ break;
+ }
+ /* else fall through */
+ case OP_D: /* 32 */
+ immed_size = 4;
+ default:
+ ;
+ }
+
+ switch (immed_size)
+ {
+ case 1:
+ memcpy (&byte, state->text + state->pos, immed_size);
+ immed_data = byte;
+ break;
+ case 2:
+ memcpy (&word, state->text + state->pos, immed_size);
+ immed_data = word;
+ break;
+ case 4:
+ memcpy (&dword, state->text + state->pos, immed_size);
+ immed_data = dword;
+ }
+
+ sym = hash_get (state->symtab, immed_data);
+
+ if (check_is_data (immed_data) || sym != NULL)
+ {
+ /* there is no label at the destination, so one must be created */
+ if (sym == NULL)
+ sym = create_data_ref (state->symtab, immed_data);
+
+ strcat (state->instruction, sym->name);
+ }
+ else
+ {
+ /* Check to see if this instruction has a byte second operand
+ and a different sized first operand. If so, "byte" needs
+ to be prepended to the value. */
+ if (state->addr[1] == ADDR_I && state->op[1] == OP_B
+ && state->op[0] == OP_V)
+ strcat (state->instruction, "byte ");
+
+ sprintf (state->scratch, "0x%0*x", immed_size, immed_data);
+ strcat (state->instruction, state->scratch);
+ }
+
+ state->pos += immed_size; /* skip past immediate data */
+}
+
+/* format_addr_j
+ * The instruction contains an EIP relative offset.
+ */
+void
+format_addr_j (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ int off_size = 0, jump_size = 0;
+ /* signed jump */
+ unsigned long jump_dest;
+ int8_t byte_jump;
+ int16_t word_jump;
+ int32_t dword_jump;
+ struct symtab *sym;
+
+ switch (op)
+ {
+ case OP_B: /* 8 */
+ off_size = 1;
+ break;
+ case OP_C: /* 8/16 */
+ if (state->opd_size == SIZE_16)
+ {
+ off_size = 1;
+ break;
+ }
+ /* else fall through */
+ case OP_W: /* 16 */
+ off_size = 2;
+ break;
+ case OP_V: /* 16/32 */
+ if (state->opd_size == SIZE_16)
+ {
+ off_size = 2;
+ break;
+ }
+ /* else fall through */
+ case OP_D: /* 32 */
+ off_size = 4;
+ default:
+ ;
+ }
+
+ jump_size = off_size;
+
+ switch (off_size)
+ {
+ case 4:
+ memcpy (&dword_jump, state->text + state->pos, off_size);
+ break;
+ case 2:
+ memcpy (&word_jump, state->text + state->pos, off_size);
+ break;
+ case 1:
+ memcpy (&byte_jump, state->text + state->pos, off_size);
+ /* sign extend */
+ if (state->opd_size == SIZE_16)
+ {
+ word_jump = (int16_t)byte_jump;
+ jump_size = 2;
+ }
+ else
+ {
+ dword_jump = (int32_t)byte_jump;
+ jump_size = 4;
+ }
+ break;
+ default:
+ fprintf (stderr, "%s: internal error at %d: %d\n", __FILE__, __LINE__,
+ jump_size);
+ return;
+ }
+
+ state->pos += off_size;
+
+ state->vaddr += state->pos - state->orig_pos;
+
+ if (jump_size == 2) /* 16 bit addresses */
+ {
+ jump_dest = ((state->vaddr & 0xffff) + word_jump);
+ sprintf (state->scratch, "%#hx",
+ (uint16_t)((state->vaddr & 0xffff) + word_jump));
+ }
+ else /* 32 bit addresses */
+ {
+ jump_dest = (state->vaddr + dword_jump);
+ sprintf (state->scratch, "%#x", (uint32_t)(state->vaddr + dword_jump));
+ }
+
+ sym = hash_get (state->symtab, jump_dest);
+
+ /* there is no label at the destination, so one must be created */
+ if (sym == NULL)
+ sym = create_jump_ref (state->symtab, jump_dest);
+
+ strcat (state->instruction, sym->name);
+}
+
+/* format_addr_m
+ * The ModR/M byte may refer to memory only, and the memory format is
+ * ugly:
+ * [base + index * scale + displacement]
+ * All of the elements are optional (although there must be *something*).
+ */
+void
+format_addr_m (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ int no_sib_base = 0;
+ unsigned char mod, rm;
+ unsigned long mem_ref;
+ struct symtab *sym;
+
+ if (addr == ADDR_M && op == OP_P)
+ {
+ format_addr_a (state, addr, op);
+ return;
+ }
+
+ mod = state->modrm >> 6;
+ rm = state->modrm & 0x07;
+
+ if (mod == 0x3) /* shouldn't happen, but I'm paranoid */
+ {
+ /* This happens with the bound Gv,Ma instruction (opcode 62)
+ * 62 f8, to be exact
+ * mod = 11
+ * reg = 111
+ * r/m = 000
+ * To watch it in action, decompile calc.exe
+ */
+ fprintf (stderr,
+ "%s: internal error at %d: ModR/M %#02x, vaddr: %#08lx\n",
+ __FILE__, __LINE__, state->modrm, state->vaddr);
+ return;
+ }
+
+ /* check for a segment override prefix */
+ if (state->prefix[1])
+ {
+ strcat (state->instruction,
+ one_byte_opcode_table[state->prefix[1]].instruction);
+ strcat (state->instruction, ":");
+ }
+
+ strcat (state->instruction, "[");
+
+ /* handle 16 bit and 32 bit stuff separately */
+ if (state->addr_size == SIZE_16)
+ {
+ int8_t disp8;
+ int16_t disp16;
+ char *eff_addr[] = { "bx + si", "bx + di", "bp + si", "bp + di",
+ "si", "di", "bp", "bx" };
+
+ /* if Mod is 00b and R/M is 110b then there is only
+ a 16 bit displacement */
+ if (mod == 0x0 && rm == 0x6)
+ {
+ memcpy (&disp16, state->text + state->disp_offset, 2);
+
+ /* create a symbolic ref */
+ mem_ref = (unsigned long)disp16;
+
+ sym = hash_get (state->symtab, mem_ref);
+
+ /* there is no label at the destination, so one must be created */
+ if (sym == NULL)
+ sym = create_data_ref (state->symtab, mem_ref);
+
+ state->instruction[strlen (state->instruction) - 1] = '\0';
+ strcat (state->instruction, sym->name);
+
+ return;
+ }
+
+ strcat (state->instruction, eff_addr[rm]);
+
+ /* if Mod is 01b or 10b then it has an 8 or 16 bit
+ displacement, respectively */
+ if (mod == 0x1)
+ {
+ memcpy (&disp8, state->text + state->disp_offset, 1);
+ sprintf (state->scratch, " + %#x", (int16_t)disp8);
+ strcat (state->instruction, state->scratch);
+ }
+ else if (mod == 0x2)
+ {
+ memcpy (&disp16, state->text + state->disp_offset, 2);
+ sprintf (state->scratch, " + %#x", disp16);
+ strcat (state->instruction, state->scratch);
+ }
+ }
+ else /* 32 bit addr */
+ {
+ int8_t disp8;
+ int32_t disp32;
+ char *eff_addr[] = { "eax", "ecx", "edx", "ebx",
+ "", "ebp", "esi", "edi" };
+
+ /* If Mod is 00b and R/M is 101b then there is only a disp32 */
+ if (mod == 0x0 && rm == 0x5)
+ {
+ memcpy (&disp32, state->text + state->disp_offset, 4);
+
+ /* create a symbolic ref */
+ mem_ref = (unsigned long)disp32;
+
+ sym = hash_get (state->symtab, mem_ref);
+
+ /* there is no label at the destination, so one must be created */
+ if (sym == NULL)
+ sym = create_data_ref (state->symtab, mem_ref);
+
+ state->instruction[strlen (state->instruction) - 1] = '\0';
+ strcat (state->instruction, sym->name);
+
+ return;
+ }
+
+ /* if R/M is 100b then there is an SIB which specifies the operand */
+ if (rm == 0x4)
+ {
+ unsigned char ss, idx, base;
+ char *scale;
+ char *base_r[] = { "eax", "ecx", "edx", "ebx",
+ "esp", "ebp", "esi", "edi" };
+ char *idx_r[] = { "eax", "ecx", "edx", "ebx",
+ "", "ebp", "esi", "edi" };
+
+ ss = state->sib >> 6;
+ idx = (state->sib >> 3) & 0x07;
+ base = state->sib & 0x07;
+
+ scale = "";
+
+ /* determine base register */
+ if (mod == 0 && base == 0x5)
+ no_sib_base = 1;
+ else
+ strcat (state->instruction, base_r[base]);
+
+
+ /* if there is an index register */
+ if (idx != 0x4)
+ {
+ if (!no_sib_base)
+ strcat (state->instruction, " + ");
+
+ /* check scaling */
+ switch (ss)
+ {
+ case 1:
+ scale = " * 2";
+ break;
+ case 2:
+ scale = " * 4";
+ break;
+ case 3:
+ scale = " * 8";
+ }
+
+ sprintf (state->scratch, "%s%s", idx_r[idx], scale);
+ strcat (state->instruction, state->scratch);
+ }
+ }
+ else /* no SIB */
+ strcat (state->instruction, eff_addr[rm]);
+
+ /* if Mod is 01b or 10b then there is an 8 bit or 32 bit
+ displacement, respectively */
+ if (mod == 0x1)
+ {
+ memcpy (&disp8, state->text + state->disp_offset, 1);
+ sprintf (state->scratch, " + %#x", (int32_t)disp8);
+ strcat (state->instruction, state->scratch);
+ }
+ else if (mod == 0x2)
+ {
+ memcpy (&disp32, state->text + state->disp_offset, 4);
+ sprintf (state->scratch, " + %#x", disp32);
+ strcat (state->instruction, state->scratch);
+ }
+ else if (no_sib_base)
+ {
+ memcpy (&disp32, state->text + state->pos, 4);
+ sprintf (state->scratch, " + %#x", disp32);
+ strcat (state->instruction, state->scratch);
+
+ state->pos += 4;
+ }
+ }
+
+ strcat (state->instruction, "]");
+}
+
+
+/* format_addr_o
+ * No ModR/M byte. There is an offset of size OP directly after the
+ * instruction.
+ */
+void
+format_addr_o (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ uint16_t woff;
+ uint32_t doff;
+ int offsize = 0;
+
+ switch (op)
+ {
+ case OP_W: /* 16 */
+ offsize = 2;
+ break;
+ case OP_V: /* 16/32 */
+ if (state->opd_size == SIZE_16)
+ {
+ offsize = 2;
+ break;
+ }
+ /* else fall through */
+ case OP_D: /* 32 */
+ offsize = 4;
+ default:
+ ;
+ }
+
+ if (offsize == 2)
+ memcpy (&woff, state->text + state->pos, offsize);
+ else
+ memcpy (&doff, state->text + state->pos, offsize);
+
+ state->pos += offsize;
+
+ /* hmm, maybe there should be a check for a data reference here */
+
+ sprintf (state->scratch, "[0x%0*x]", offsize, (offsize == 2) ? woff : doff);
+ strcat (state->instruction, state->scratch);
+}
+
+/* format_addr_p
+ * The reg field of the ModR/M byte selects an MMX register.
+ */
+void
+format_addr_p (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ unsigned char reg;
+
+ reg = (state->modrm >> 3) & 0x07;
+
+ strcat (state->instruction, register_names[REG_SIZE_64][reg]);
+}
+
+/* format_addr_q
+ * The ModR/M byte specifies either a memory location or an MMX register.
+ */
+void
+format_addr_q (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ if (state->modrm >> 6 == 0x3) /* specifies a register */
+ strcat (state->instruction,
+ register_names[REG_SIZE_64][state->modrm & 0x07]);
+ else
+ format_addr_m (state, addr, op);
+}
+
+/* format_addr_r
+ * The Mod field of the ModR/M byte may only refer to a general purpose
+ * register.
+ */
+void
+format_addr_r (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ /* this is only used with OP_D so only a check is made for others */
+
+ if (op != OP_D)
+ fprintf (stderr, "%s: internal error at %d\n", __FILE__, __LINE__);
+
+ strcat (state->instruction,
+ register_names[REG_SIZE_32][state->modrm & 0x07]);
+}
+
+/* format_addr_s
+ * The Reg field of the ModR/M byte selects a segment register.
+ */
+void
+format_addr_s (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ unsigned char reg;
+ /* r_seg means reserved segment register */
+ char *sreg[] = { "es", "cs", "ss", "ds", "fs", "gs", "r_seg", "r_seg" };
+
+ reg = (state->modrm >> 3) & 0x07;
+
+ strcat (state->instruction, sreg[reg]);
+}
+
+/* format_addr_t
+ * Reg field of the ModR/M byte selects a test register. After digging
+ * through sdmv1-3, it was discovered that the test registers were only
+ * used in the 80486, they have been supplanted in the Pentium and later
+ * with MSRs, and with the advent of the P6 architecture, a mov instruction
+ * with a test register argument will generate a UD exception. However,
+ * since this is a decompiler and not an emulator, we'll happily
+ * disassemble an instruction with these registers. Of course, the syntax
+ * is probably incorrect because I don't have an sdm for the 80486
+ * handy.
+ */
+void
+format_addr_t (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ sprintf (state->scratch, "tr%x", (state->modrm >> 3) & 0x07);
+ strcat (state->instruction, state->scratch);
+}
+
+/* format_addr_v
+ * The Reg field of the ModR/M byte selects an XMM register.
+ */
+void
+format_addr_v (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ strcat (state->instruction,
+ register_names[REG_SIZE_128][(state->modrm >> 3) & 0x07]);
+}
+
+/* format_addr_w
+ * The ModR/M byte specifies either an XMM register or memory.
+ */
+void
+format_addr_w (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ if (state->modrm >> 6 == 0x3)
+ strcat (state->instruction,
+ register_names[REG_SIZE_128][state->modrm & 0x07]);
+ else
+ format_addr_m (state, addr, op);
+}
+
+/* format_addr_x
+ * X is an implied operand, but the suffix on the instruction is b,
+ * so the instruction itself is modified here.
+ */
+void
+format_addr_x (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ state->instruction[strlen (state->instruction) - 1] = 'b';
+}
+
+/* format_addr_y
+ * Y is an implied operand, but the suffix on the instruction is b,
+ * so the instruction itself is modified here.
+ */
+void
+format_addr_y (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ char suffix;
+
+ suffix = (state->opd_size == SIZE_32) ? 'd' : 'w';
+
+ state->instruction[strlen (state->instruction) - 1] = suffix;
+}
+
+
+void
+format_addr_op (struct disassembly_state *state, enum addr_method addr,
+ enum operand_type op)
+{
+ char *registers[] = {
+ "al", "ah", "ax", "eax", "bl", "bh", "bx", "ebx",
+ "cl", "ch", "cx", "ecx", "dl", "dh", "dx", "edx",
+ "si", "esi", "di", "edi", "bp", "ebp", "sp", "esp",
+ "cs", "ds", "ss", "es", "fs", "gs",
+ "flags", "eflags", "ip", "eip",
+ "st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
+ };
+
+ switch (addr)
+ {
+ case ADDR_A:
+ format_addr_a (state, addr, op);
+ break;
+ case ADDR_C:
+ format_addr_c (state, addr, op);
+ break;
+ case ADDR_D:
+ format_addr_d (state, addr, op);
+ break;
+ case ADDR_E:
+ format_addr_e (state, addr, op);
+ break;
+ case ADDR_F:
+ /* don't need to do anything for this addressing method - it
+ is only used by pushf/popf and always references eflags */
+ break;
+ case ADDR_G:
+ format_addr_g (state, addr, op);
+ break;
+ case ADDR_I:
+ format_addr_i (state, addr, op);
+ break;
+ case ADDR_J:
+ format_addr_j (state, addr, op);
+ break;
+ case ADDR_M:
+ format_addr_m (state, addr, op);
+ break;
+ case ADDR_O:
+ format_addr_o (state, addr, op);
+ break;
+ case ADDR_P:
+ format_addr_p (state, addr, op);
+ break;
+ case ADDR_Q:
+ format_addr_q (state, addr, op);
+ break;
+ case ADDR_R:
+ format_addr_r (state, addr, op);
+ break;
+ case ADDR_S:
+ format_addr_s (state, addr, op);
+ break;
+ case ADDR_T:
+ format_addr_t (state, addr, op);
+ break;
+ case ADDR_V:
+ format_addr_v (state, addr, op);
+ break;
+ case ADDR_W:
+ format_addr_w (state, addr, op);
+ break;
+ case ADDR_X:
+ format_addr_x (state, addr, op);
+ break;
+ case ADDR_Y:
+ format_addr_y (state, addr, op);
+ break;
+ case R_START ... R_END: /* this construct is a GNU extension */
+ /* if this is a general register, check for the width */
+ if (op == OP_E && state->opd_size == SIZE_32) addr++;
+ strcat (state->instruction, registers[addr - R_START - 1]);
+ break;
+ case IMMED_1:
+ strcat (state->instruction, "1");
+ break;
+ default: /* to appease gcc */
+ ;
+ }
+}
+
+
+/* i386_disassemble_instruction
+ * Fully disassemble the instruction at TEXT + *POS and return
+ * one line of assembly language (without the '\n') after
+ * updating *POS.
+ *
+ * Some observations after writing about half of this file: I can't say
+ * that I'm very fond of CISC. How many register specifiers, escape
+ * sequences, and memory addressing methods suffice??? I suppose
+ * that it really isn't worth griping as I'm not the one who had to
+ * design the chip itself.
+ */
+char *
+ia32_disassemble_instruction (unsigned char *text, unsigned long *pos,
+ unsigned long flags, unsigned long vaddr,
+ hash_t symtab)
+{
+ int k, print_prefixes;
+ unsigned char opcode;
+ insn_table table = one_byte_opcode_table;
+ struct disassembly_state state;
+
+
+ state.instruction = xmalloc (MAX_LINE_LENGTH);
+ state.scratch = xmalloc (MAX_LINE_LENGTH);
+
+ state.text = text;
+ state.pos = *pos;
+
+ state.opd_size = D32 (flags) ? SIZE_32 : SIZE_16;
+ state.addr_size = A32 (flags) ? SIZE_32 : SIZE_16;
+
+ state.modrm = 0;
+ state.read_modrm = 0;
+ state.sib = 0;
+
+ state.sse_prefix = 0;
+ state.prefix[0] = 0;
+ state.prefix[1] = 0;
+ state.prefix[2] = 0;
+ state.prefix[3] = 0;
+
+ state.orig_pos = *pos;
+ state.vaddr = vaddr;
+ state.symtab = symtab;
+
+ print_prefixes = PREFIXES (flags);
+
+
+ /* check for and handle prefixes - some xmm insns have prefixes
+ which aren't prefixes so we need to defer prefix handling
+ as far as possible */
+ while (1)
+ {
+ /* read in opcode */
+ opcode = state.text[state.pos];
+ state.pos++;
+
+ if (!is_prefix (opcode)) break;
+
+ /* 66,F2,F3 - SSE prefixes */
+ /* check for SSE/SSE2 opcode byte 3 */
+ if (is_sse_prefix (opcode))
+ state.sse_prefix = opcode;
+
+ /* we have a prefix, find out what type */
+ if (p_is_group1 (opcode)) /* lock/repne/repe */
+ {
+ if (!state.prefix[0]) /* ignore additional opcode prefixes */
+ state.prefix[0] = opcode;
+ }
+ else if (p_is_group2 (opcode)) /* segment override/branch hint */
+ {
+ if (!state.prefix[1]) /* ignore additional opcode prefixes */
+ state.prefix[1] = opcode;
+ }
+ else if (p_is_group3 (opcode)) /* operand size override prefix */
+ {
+ if (!state.prefix[2]) /* ignore additional opcode prefixes */
+ state.prefix[2] = opcode;
+ }
+ else if (p_is_group4 (opcode)) /* address size override prefix */
+ {
+ if (!state.prefix[3]) /* ignore additional opcode prefixes */
+ state.prefix[3] = opcode;
+ }
+ else /* huh??? */
+ fprintf (stderr, "%s: internal error at %d\n", __FILE__, __LINE__);
+ }
+
+
+ /* get the instruction operands */
+ state.addr[0] = table[opcode].addr_method[0];
+ state.addr[1] = table[opcode].addr_method[1];
+ state.addr[2] = table[opcode].addr_method[2];
+
+ state.op[0] = table[opcode].operand_type[0];
+ state.op[1] = table[opcode].operand_type[1];
+ state.op[2] = table[opcode].operand_type[2];
+
+
+ state.opcode[0] = opcode;
+
+
+
+ /* check for esc opcode */
+
+ if (table[opcode].instruction == NULL) /* this opcode is an escape */
+ {
+ /* sanity check */
+ if (table[opcode].esc_function == NULL)
+ fprintf (stderr, "%s: internal error at %d\n", __FILE__, __LINE__);
+ else
+ table[opcode].esc_function (&state);
+ }
+ else /* normal instruction */
+ strcat (state.instruction, table[opcode].instruction);
+
+ /* copy the instruction to temporary space to make room for any prefixes */
+ memset (state.scratch, 0, MAX_LINE_LENGTH);
+ strcpy (state.scratch, state.instruction);
+ memset (state.instruction, 0, MAX_LINE_LENGTH);
+
+
+ /* act on instruction prefixes - if one of the SSE "prefixes" was
+ present, then it was already set to zero, so it won't show up here */
+
+ if (state.prefix[0])
+ {
+ sprintf (state.instruction, "\t%s ", table[state.prefix[0]].instruction);
+ }
+ /* if we have a group 2 prefix, check for Jcc insn */
+ if (state.prefix[1])
+ {
+ if (is_jcc_insn (state.opcode[0])
+ || (state.opcode[0] == 0x0f && is_esc_jcc_insn (state.opcode[1])))
+ /* branch hint prefix */
+ {
+ if (print_prefixes)
+ {
+ if (state.prefix[1] == 0x2e) /* branch not taken */
+ sprintf (state.instruction,
+ "# branch hint: branch not taken\n\t");
+ else if (state.prefix[1] == 0x3e) /* branch taken */
+ sprintf (state.instruction, "# branch hint: branch taken\n\t");
+ else
+ sprintf (state.instruction, "# invalid branch hint (%02x)\n\t",
+ state.prefix[1]);
+ }
+
+ state.prefix[1] = 0;
+ }
+ else /* segment override prefix */
+ {
+ sprintf (state.instruction, "\t%s ",
+ table[state.prefix[1]].instruction);
+ }
+ }
+ if (state.prefix[2] == 0x66)
+ {
+ state.opd_size = (state.opd_size == SIZE_32) ? SIZE_16 : SIZE_32;
+
+ sprintf (state.instruction, "\t%s ", ((state.opd_size == SIZE_32)
+ ? "o32" : "o16"));
+ }
+ if (state.prefix[3] == 0x67)
+ {
+ state.addr_size = (state.addr_size == SIZE_32) ? SIZE_16 : SIZE_32;
+
+ sprintf (state.instruction, "\t%s ", ((state.opd_size == SIZE_32)
+ ? "a32" : "a16"));
+ }
+
+ /* print the instruction where it belongs */
+ if (!strlen (state.instruction))
+ strcat (state.instruction, "\t");
+
+ strcat (state.instruction, state.scratch);
+
+
+ /* find out the offsets of various parts of the instruction */
+
+ /* check for ModR/M byte */
+ if (!state.read_modrm && (has_modrm (state.addr[0])
+ || has_modrm (state.addr[1]) || has_modrm (state.addr[2])))
+ {
+ state.modrm = state.text[state.pos];
+ state.pos++;
+ }
+
+ /* check for SIB byte */
+ if (has_sib (state.modrm, state.addr_size))
+ {
+ state.sib = state.text[state.pos];
+ state.pos++;
+ }
+
+ /* check for a displacement */
+ state.disp_size = disp_size (state.modrm, state.addr_size);
+
+ switch (state.disp_size)
+ {
+ case 4:
+ case 2:
+ case 1:
+ state.disp_offset = state.pos;
+ state.pos += state.disp_size;
+ }
+ /* at this point, state.pos is either the offset of any immediate
+ data or the offset of the next instruction */
+
+
+ /* calculation of immediate data is left until later on */
+
+
+ /* handle addr/op */
+ for (k = 0; k < 3; k++)
+ {
+ if (state.addr[k] == ADDR_0) break; /* all done */
+
+ /* format the instruction nice and purty */
+ if (k == 0)
+ strcat (state.instruction, "\t");
+ else
+ strcat (state.instruction, ", ");
+
+ /* pass off the addr/op pair */
+ format_addr_op (&state, state.addr[k], state.op[k]);
+ }
+
+ xfree (state.scratch);
+
+ *pos = state.pos;
+
+ return (state.instruction);
+}
diff --git a/decomp/ia32.h b/decomp/ia32.h
new file mode 100644
index 0000000..afd2db1
--- /dev/null
+++ b/decomp/ia32.h
@@ -0,0 +1,327 @@
+/* ia32.h
+ * This file is part of Decomp - an interactive disassembler.
+ *
+ * This file contains definitions for use in i386_opcode.c.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * DECOMP is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * DECOMP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DECOMP; see the file COPYING. If not, write to the Free
+ * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * As a note, whenever "IA-32 SDM V2 or SDM V2 is mentioned, it means:
+ * IA-32 Intel Architecture Software Developer's Manual Volume 2.
+ */
+
+#ifndef IA32_H
+#define IA32_H
+
+#include "decomp.h"
+
+#define MAX_LINE_LENGTH 256
+
+
+/* FLAGS as passed in the flags variable */
+
+#define A32(f) ((f) & F_IA32_A) /* using 32 bit addresses? */
+#define D32(f) ((f) & F_IA32_D) /* using 32 bit data sizes? */
+#define PREFIXES(f) ((f) & F_IA32_P) /* print instruction prefix comments? */
+
+
+/* prefix testing */
+
+#define p_is_group1(p) (((p) == 0xf0) /* lock */ \
+ || ((p) == 0xf2) /* repne/repnz */ \
+ || ((p) == 0xf3)) /* rep/repe/repz */
+
+#define p_is_group2(p) (((p) == 0x2e) /* CS override/branch not taken */ \
+ || ((p) == 0x36) /* SS override */ \
+ || ((p) == 0x3e) /* DS override/branch taken */ \
+ || ((p) == 0x26) /* ES override */ \
+ || ((p) == 0x64) /* FS override */ \
+ || ((p) == 0x65)) /* GS override */
+
+#define p_is_group3(p) ((p) == 0x66) /* opsize override */
+
+#define p_is_group4(p) ((p) == 0x67) /* addr size override */
+
+#define is_prefix(o) (p_is_group1 (o) || p_is_group2 (o) \
+ || p_is_group3 (o) || p_is_group4 (o))
+
+#define is_sse_prefix(o) (((o) == 0xf2) || ((o) == 0xf3) || ((o) == 0x66))
+
+
+/* test for Jcc insn */
+
+/* opcode is in the range 70-7f,e3 */
+#define is_jcc_insn(o) (((o) == 0xe3) || (((o) >= 0x70) && ((o) <= 0x7f)))
+
+/* opcode is in the range 80-8f (for the times when the first byte is 0f) */
+#define is_esc_jcc_insn(o) (((o) >= 0x80) && ((o) <= 0x8f))
+
+
+/* the instruction operands specify whether or not there is a ModR/M byte */
+#define has_modrm(addr) (((addr) == ADDR_C) \
+ || ((addr) == ADDR_D) \
+ || ((addr) == ADDR_E) \
+ || ((addr) == ADDR_G) \
+ || ((addr) == ADDR_M) \
+ || ((addr) == ADDR_P) \
+ || ((addr) == ADDR_Q) \
+ || ((addr) == ADDR_R) \
+ || ((addr) == ADDR_S) \
+ || ((addr) == ADDR_T) \
+ || ((addr) == ADDR_V) \
+ || ((addr) == ADDR_W))
+
+/* there is an SIB byte if the Mod field is not 11b, the R/M field
+ is 100b and the addressing mode is 32 bits */
+#define has_sib(modrm, addr) ((((modrm) & 0x07) == 0x04) \
+ && ((addr) == SIZE_32) \
+ && (((modrm) & 0xC0) != 0xC0))
+
+/* If the Mod field of the ModR/M byte is 01b, then there is a 1 byte
+ displacement. If the Mod field is 00b, the R/M field is 110b, and
+ the current addressing mode is 16 bit, then there is a 2 byte
+ displacement. Also, if the addressing mode is 16 bit and
+ the Mod field is 10b, then there is a 2 byte displacement. If the
+ addressing mode is 32 bit and either the Mod field is 00b and the
+ R/M field is 101b, or the Mod field is 10b, then there is a
+ 4 byte displacement. Otherwise there is no displacement. */
+#define disp_size(modrm,addr) ((((modrm) & 0xC0) == 0x40) ? 1 \
+ : ((((addr) == SIZE_16) \
+ && ((((modrm) & 0xC7) == 0x06) \
+ || (((modrm) & 0xC0) == 0x80))) ? 2 \
+ : ((((addr) == SIZE_32) \
+ && ((((modrm) & 0xC7) == 0x05) \
+ || (((modrm) & 0xC0) == 0x80))) ? 4\
+ : 0)))
+
+/* If ADDR is ADDR_I, then there is immediate data, the size of which
+ is given in OP. If ADDR is ADDR_A, then there is either 32 or
+ 48 bits of immediate data, depending on the addressing mode. If
+ ADDR is ADDR_J, then there is a jump offset. */
+/*#define imm_size(addr,op) (((addr) == ADDR_I)
+ ? ()
+ : 0) */
+
+
+enum addr_method {
+ ADDR_0, /* no addressing method */
+ ADDR_A, /* direct address, no ModR/M byte */
+ ADDR_C, /* reg field of the ModR/M byte selects a control register */
+ ADDR_D, /* reg field of the ModR/M byte selects a debug register */
+ ADDR_E, /* ModR/M byte specifies operand - either a general purpose
+ register or a memory address offset from a segment register
+ with poss base reg, index reg, scale factor, or disp */
+ ADDR_F, /* EFLAGS register */
+ ADDR_G, /* reg field of ModR/M byte selects a general register */
+ ADDR_I, /* immediate data */
+ ADDR_J, /* insn contains rel offset from IP */
+ ADDR_M, /* ModR/M byte may refer only to mem */
+ ADDR_O, /* no ModR/M byte - op is coded as a word or dword */
+ ADDR_P, /* reg field of the ModR/M byte selects a packed qword MMX reg */
+ ADDR_Q, /* ModR/M byte specifies either MMX reg or mem addr (scaled etc.) */
+ ADDR_R, /* reg field of ModR/M byte may only refer to a general reg */
+ ADDR_S, /* reg field of ModR/M byte selects a segment register */
+ ADDR_T, /* reg field of ModR/M byte selects a test reg */
+ ADDR_V, /* reg field of the ModR/M byte selects a XMM reg */
+ ADDR_W, /* ModR/M byte selects either XMM reg or mem addr (scaled etc.) */
+ ADDR_X, /* memory addressed by DS:SI */
+ ADDR_Y, /* memory addressed by ES:DI */
+
+ /* actual registers encoded - DO NOT REORDER THESE!!! */
+ R_START, /* this value _MUST_ appear directly before register definitions */
+
+ R_AL,
+ R_AH,
+ R_AX,
+ R_EAX,
+
+ R_BL,
+ R_BH,
+ R_BX,
+ R_EBX,
+
+ R_CL,
+ R_CH,
+ R_CX,
+ R_ECX,
+
+ R_DL,
+ R_DH,
+ R_DX,
+ R_EDX,
+
+ R_SI,
+ R_ESI,
+ R_DI,
+ R_EDI,
+ R_BP,
+ R_EBP,
+ R_SP,
+ R_ESP,
+
+ /* segment registers */
+ R_CS,
+ R_DS,
+ R_SS,
+ R_ES,
+ R_FS,
+ R_GS,
+
+ /* EFLAGS */
+ R_F,
+ R_EF,
+
+ /* EIP */
+ R_IP,
+ R_EIP,
+
+ /* floating point registers */
+ R_ST0,
+ R_ST1,
+ R_ST2,
+ R_ST3,
+ R_ST4,
+ R_ST5,
+ R_ST6,
+ R_ST7,
+
+ /* MMX registers */
+ R_MM0,
+ R_MM1,
+ R_MM2,
+ R_MM3,
+ R_MM4,
+ R_MM5,
+ R_MM6,
+ R_MM7,
+
+ /* SSE/SSE2 registers */
+ R_XMM0,
+ R_XMM1,
+ R_XMM2,
+ R_XMM3,
+ R_XMM4,
+ R_XMM5,
+ R_XMM6,
+ R_XMM7,
+
+ /* this value _MUST_ appear directly after register definitions */
+ R_END,
+
+ /* immediate value integral to instruction (see D0, D1) */
+ IMMED_1, /* the value 1 (one) */
+};
+
+enum operand_type {
+ OP_0, /* no type */
+ OP_A, /* two 1 word ops or 2 dword ops in mem (dep on opsize attr) */
+ OP_B, /* byte regardless of opsize attr */
+ OP_C, /* byte or word dep on opsize attr */
+ OP_D, /* dword regardless of opsize attr */
+ OP_DQ, /* dqword regardless or opsize attr */
+ OP_P, /* 32 or 48 bit pointer dep on opsize attr */
+ OP_PI, /* qword mmx reg */
+ OP_PS, /* 128 bit packed single float data */
+ OP_Q, /* qword regardless of opsize attr */
+ OP_S, /* 6 byte pseudo-descriptor */
+ OP_SS, /* scalar element of 128 bit packed single float data */
+ OP_SI, /* dword int reg (e.g. eax) */
+ OP_V, /* word or dword dep on opsize attr */
+ OP_W, /* word regardless or opsize attr */
+
+ /* these aren't listed in sdmv2, but are used */
+ OP_PD, /* dqword or xmm register */
+ OP_SD, /* qword or xmm register */
+
+ /* used when register are directly encoded - operand size attribute */
+ OP_E
+};
+
+/* operand / address size */
+enum op_size {
+ SIZE_16,
+ SIZE_32
+};
+
+/* DO NOT REORDER THESE!!! */
+enum reg_size {
+ REG_SIZE_8, REG_SIZE_16, REG_SIZE_32, REG_SIZE_64, REG_SIZE_128
+};
+
+
+/* used for keeping track of the cpu and interpreting instructions */
+struct disassembly_state {
+ /* current operand size */
+ enum op_size opd_size;
+ /* current address size */
+ enum op_size addr_size;
+ /* current .text section (where we are disassembling) */
+ unsigned char *text;
+ /* current position in TEXT */
+ unsigned long pos;
+ /* the current opcode */
+ unsigned char opcode[2];
+ /* ModR/M byte or 0x00 */
+ unsigned char modrm;
+ /* indicates whether the ModR/M byte has been read */
+ int read_modrm;
+ /* SIB byte or 0x00 */
+ unsigned char sib;
+ /* the start of the displacement or 0 */
+ unsigned long disp_offset;
+ /* the size in bytes of the displacement */
+ int disp_size;
+ /* the start of immediate data or 0 */
+ unsigned long immed_offset;
+ /* the size of the immediate data */
+ int immed_size;
+ /* code for addressing method */
+ enum addr_method addr[3];
+ /* code for operand type */
+ enum operand_type op[3];
+ /* instruction prefixes or 0x00 */
+ unsigned char prefix[4];
+ /* byte 3 of SSE/SSE2 instructions */
+ unsigned char sse_prefix;
+ /* instruction disassembly being constructed */
+ char *instruction;
+ /* scratch area */
+ char *scratch;
+ /* original position of ip */
+ unsigned long orig_pos;
+ /* virtual address of start position */
+ unsigned long vaddr;
+ /* symbol hash table */
+ hash_t symtab;
+};
+
+
+struct _insn {
+ /* the nominal name of the instruction e.g. "mov" */
+ char *instruction;
+ /* the addressing method from Appendix A of the IA-32 SDM V2 */
+ enum addr_method addr_method[3];
+ /* the corresponding type also from Appendix A */
+ enum operand_type operand_type[3];
+ /* if there are additional bytes in the opcode */
+ void (*esc_function)(struct disassembly_state *);
+};
+
+typedef struct _insn insn, *insn_table;
+
+
+#endif /* IA32_H */
diff --git a/decomp/memory.c b/decomp/memory.c
new file mode 100644
index 0000000..da173d7
--- /dev/null
+++ b/decomp/memory.c
@@ -0,0 +1,454 @@
+/* memory.c
+ * This file is a part of decomp - a disassembler. Here are the memory
+ * allocation and deallocation routines.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * The memory allocation is fairly routine. The justification for not
+ * using malloc as is is primarily a speed issue. Secondary is the
+ * fact that this organization allows sloppy memory accounting in the
+ * main program. When disassembling a file, there will be a lot of
+ * allocations and deallocations of small, similarly-sized blocks of
+ * memory (i.e. INSN). By not releasing the memory each time a section
+ * read is completed, it allows the same block to be reused for the
+ * next section.
+ * The mechanism of allocation is that large, CHUNK_SIZE sized blocks
+ * of memory are requested from the system. They are kept track of
+ * by overlaying the first sizeof (sys_block) bytes with a
+ * struct sys_block and having the next pointer point to the next
+ * block, or being NULL. That way, when xfree is called, the linked
+ * list, kept in the variable memory, is walked and each node is free'd.
+ * Each block is then carved up into smaller blocks. Each of these
+ * smaller blocks has the first sizeof (mem_header) bytes overlaid
+ * by a struct mem_header. Then, if one of the smaller blocks is needed,
+ * the struct mem_header is placed on the alloc list. If, relative
+ * to the size of the memory request, it is fairly large, it is
+ * partitioned into two blocks. One is placed on the alloc list and
+ * returned to the caller; the other is placed on the free list. Then,
+ * as space is needed, adjacent free blocks are merged to create larger
+ * blocks. If the global variable memory_trace is non-zero, then
+ * messages are printed to stdout as important/interesting events
+ * take place. Also provided is the function void mem_trace (void),
+ * which prints the alloc list, the free list, and the sys list.
+ *
+ * Started around 15 October 2001.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "decomp.h"
+
+
+/* the default amount of memory to request from the system each time */
+#define DEFAULT_CHUNK_SIZE 2048
+
+/* the minimum size of housekeeping info in a sys block */
+#define ALLOC_ADJUST (sizeof (struct sys_block) + sizeof (struct mem_header))
+
+/* the smallest amount which will be returned */
+#define MIN_ALLOC_AMOUNT 8
+
+/* the largest amount that can be handled at one time */
+#define MAX_ALLOC_AMOUNT (chunk_size - ALLOC_ADJUST)
+
+
+/* header for a block of memory - this is what is referenced on
+ both the alloc and free lists */
+struct mem_header {
+ /* size of the chunk, not including the header */
+ unsigned long size;
+ struct mem_header *next;
+} __attribute__ ((packed));
+
+
+/* header for the block returned by a call to malloc(3) */
+struct sys_block {
+ struct sys_block *next;
+} __attribute__ ((packed));
+
+
+/* the free list */
+struct mem_header *free_list = NULL;
+
+/* the alloc list */
+struct mem_header *alloc_list = NULL;
+
+/* the list of malloc'ed blocks */
+struct sys_block *memory;
+
+
+/* info used for keeping stats */
+
+/* the total memory alloc'ed from the OS */
+unsigned long total_alloced;
+
+/* the number of calls to xmalloc */
+unsigned long xmalloc_calls;
+
+/* the number of bytes returned by xmalloc */
+unsigned long xmalloc_bytes;
+
+/* the number of bytes free'd by xfree */
+unsigned long xfree_bytes;
+
+
+/* the allocation size for memory chunks */
+unsigned long chunk_size;
+
+/* whether or not to print status messages */
+volatile int memory_trace = 0;
+
+/* whether or not memory is fragmented */
+int free_list_needs_compacting = 0;
+
+/* forward declaration needed for mem_trace */
+void compact_free_list (void);
+
+
+/* mem_trace
+ * Called in case something bad has happened. Prints the contents
+ * of the alloc list, the free list, and the sys list.
+ */
+void
+mem_trace (void)
+{
+ struct mem_header *tmp;
+ struct sys_block *sys;
+
+ if (free_list_needs_compacting)
+ compact_free_list ();
+
+ fprintf (stderr, "alloc list:\n");
+ tmp = alloc_list;
+ while (tmp != NULL)
+ {
+ fprintf (stderr, " %p->(%p, %ld)\n", tmp, tmp->next, tmp->size);
+ tmp = tmp->next;
+ }
+
+ fprintf (stderr, "free list (%d):\n", free_list_needs_compacting);
+ tmp = free_list;
+ while (tmp != NULL)
+ {
+ fprintf (stderr, " %p->(%p, %ld)\n", tmp, tmp->next, tmp->size);
+ tmp = tmp->next;
+ }
+
+ sys = memory;
+ fprintf (stderr, "system memory:\n");
+ while (sys != NULL)
+ {
+ fprintf (stderr, " %p - %p ->(%p)\n", sys, sys + chunk_size,
+ sys->next);
+ sys = sys->next;
+ }
+}
+
+
+/* free_list_insert_sorted
+ * Insert NEW onto the free list, sorted numerically by address.
+ */
+void
+free_list_insert_sorted (struct mem_header *new)
+{
+ struct mem_header *free_tmp = free_list;
+
+ /* check for empty list */
+ if (free_list == NULL)
+ {
+ free_list = new;
+ free_list->next = NULL;
+ return;
+ }
+
+ /* if NEW is the lowest address */
+ if (new < free_tmp)
+ {
+ new->next = free_tmp;
+ free_list = new;
+ return;
+ }
+
+ /* general case - find the insertion point */
+ while (free_tmp->next != NULL)
+ {
+ if (new < free_tmp->next) break;
+ free_tmp = free_tmp->next;
+ }
+
+ new->next = free_tmp->next;
+ free_tmp->next = new;
+}
+
+
+/* compact_free_list
+ * Defragment memory by merging all adjacent free blocks.
+ */
+void
+compact_free_list (void)
+{
+ struct mem_header *free_tmp = free_list;
+
+ /* search through the free list for adjacent blocks - if two
+ are adjacent, then merge them to create a larger block */
+ while (free_tmp != NULL)
+ {
+ if (free_tmp->next == NULL) break; /* at the end of the list */
+
+ /* if two free blocks are adjacent */
+ if ((void *)free_tmp + free_tmp->size
+ + sizeof (struct mem_header) == (void *)free_tmp->next)
+ {
+ /* merge them */
+ free_tmp->size += free_tmp->next->size
+ + sizeof (struct mem_header);
+ free_tmp->next = free_tmp->next->next;
+
+ continue; /* try again with this same block */
+ }
+
+ free_tmp = free_tmp->next;
+ }
+
+ free_list_needs_compacting = 0;
+}
+
+/* safe_malloc
+ * A wrapper around malloc which never returns NULL.
+ */
+void *
+safe_malloc (size_t amount)
+{
+ void *mem;
+
+ mem = malloc (amount);
+
+ if (mem == NULL) PANIC; /* Houston, we have a problem */
+
+ /* keep stats */
+ total_alloced += amount;
+
+ return (mem);
+}
+
+/* mem_init
+ * Called when xmalloc is first invoked. Sets up the necessary
+ * data structures.
+ */
+void
+mem_init (void)
+{
+ /* set up stats */
+ total_alloced = 0;
+ xmalloc_calls = 0;
+ xmalloc_bytes = 0;
+ xfree_bytes = 0;
+
+ /* set up the system list */
+ memory = safe_malloc (chunk_size);
+ memory->next = NULL;
+
+ /* set up the free list */
+ free_list = (void *)memory + sizeof (struct sys_block);
+ free_list->size = chunk_size - sizeof (struct sys_block)
+ - sizeof (struct mem_header);
+ free_list->next = NULL;
+
+ if (memory_trace)
+ printf ("=== alloc'ed block (%p) ===\n", memory);
+}
+
+
+/* xmalloc
+ * Allocate AMOUNT bytes of memory and return it with all of
+ * its bytes set to 0x00.
+ */
+void *
+xmalloc (size_t amount)
+{
+ struct mem_header *free_tmp, *last, *ret_block;
+ struct sys_block *sys_temp;
+
+ chunk_size = DEFAULT_CHUNK_SIZE;
+
+ /* if more than the default chunk size was requested */
+ if (amount > MAX_ALLOC_AMOUNT)
+ chunk_size = amount + ALLOC_ADJUST;
+
+ if (free_list == NULL && alloc_list == NULL) mem_init ();
+
+ /* don't allocate less than MIN_ALLOC_AMOUNT */
+ if (amount < MIN_ALLOC_AMOUNT)
+ amount = MIN_ALLOC_AMOUNT;
+
+ if (memory_trace)
+ printf ("=== %d bytes requested ===\n", amount);
+
+ /* keep stats */
+ xmalloc_calls++;
+ xmalloc_bytes += amount;
+
+
+ /* loop until a block is found */
+ while (1)
+ {
+ /* first walk the free list, looking for the correct size */
+ last = NULL;
+ free_tmp = free_list;
+
+ while (free_tmp != NULL)
+ {
+ if (free_tmp->size >= amount) goto GOT_FREE_BLOCK;
+
+ last = free_tmp;
+ free_tmp = free_tmp->next;
+ }
+
+
+ /* didn't find a free block of the right size
+ - try compacting the free list */
+ if (free_list_needs_compacting)
+ {
+ compact_free_list ();
+ continue;
+ }
+
+
+ /* if we got here, then we need to allocate a new chunk */
+
+ /* find the last chunk */
+ sys_temp = memory;
+ while (sys_temp->next != NULL) sys_temp = sys_temp->next;
+
+ /* alloc a new chunk and save its ptr */
+ sys_temp->next = safe_malloc (chunk_size);
+ sys_temp->next->next = NULL;
+
+ if (memory_trace)
+ printf ("=== alloc'ed block (%p) ===\n", sys_temp->next);
+
+ /* create the new free block */
+ free_tmp = (void *)sys_temp->next + sizeof (struct sys_block);
+ free_tmp->next = NULL;
+ free_tmp->size = chunk_size - ALLOC_ADJUST;
+
+ /* put that bad boy in the free list */
+ free_list_insert_sorted (free_tmp);
+
+ /* with this new large chunk, try again */
+ }
+
+ GOT_FREE_BLOCK:
+ /* remove the block from the free list */
+ if (last == NULL)
+ free_list = free_tmp->next;
+ else
+ last->next = free_tmp->next;
+
+ ret_block = free_tmp;
+
+
+ /* shrink the block, if possible */
+ if (ret_block->size > amount + sizeof (struct mem_header) + MIN_ALLOC_AMOUNT)
+ {
+ struct mem_header *new = (void *)ret_block
+ + sizeof (struct mem_header) + amount;
+
+ new->size = ret_block->size - sizeof (struct mem_header) - amount;
+ new->next = NULL;
+ ret_block->size = amount;
+
+ free_list_insert_sorted (new);
+ }
+
+ /* put it on the alloc list */
+ ret_block->next = alloc_list;
+ alloc_list = ret_block;
+
+ /* and (finally) return the memory */
+ memset ((void *)ret_block + sizeof (struct mem_header), 0, amount);
+ return ((void *)ret_block + sizeof (struct mem_header));
+}
+
+/* xfree
+ * Add FREEMEM to the free list.
+ */
+void
+xfree (void *freemem)
+{
+ struct mem_header *mem;
+ struct mem_header *tmp = alloc_list, *last = NULL;
+
+ if (freemem == NULL) return;
+
+ mem = freemem - sizeof (struct mem_header);
+
+ /* find FREEMEM on the alloc list */
+ while (tmp != NULL)
+ {
+ if (tmp == mem) break;
+
+ last = tmp;
+ tmp = tmp->next;
+ }
+
+ /* sanity check */
+ if (tmp == NULL)
+ {
+ fprintf (stderr,
+ "tried to free block %p (%p->(%p, %ld)) not on alloc list\n",
+ freemem, mem, mem->next, mem->size);
+
+ if (memory_trace)
+ mem_trace ();
+
+ exit (EXIT_FAILURE);
+ }
+
+ /* keep stats */
+ xfree_bytes += tmp->size;
+
+ if (memory_trace)
+ printf ("=== %ld byte block freed ===\n", tmp->size);
+
+ /* remove from the alloc list */
+ if (last == NULL)
+ alloc_list = tmp->next;
+ else
+ last->next = tmp->next;
+
+ /* put it on the free list */
+ free_list_insert_sorted (mem);
+ free_list_needs_compacting = 1;
+}
+
+/* free_all
+ * Release all memory back to the OS.
+ */
+void
+free_all (void)
+{
+ struct sys_block *temp;
+
+ do
+ {
+ if (memory_trace)
+ printf ("=== freeing %p ===\n", memory);
+
+ temp = memory->next;
+ free (memory);
+ memory = temp;
+ }
+ while (memory != NULL);
+
+ if (memory_trace)
+ printf ("\n*** Stats ***\n"
+ " %ld total bytes alloc'ed from the system\n"
+ " %ld calls to xmalloc\n"
+ " %ld total bytes alloc'ed\n"
+ " %ld bytes freed\n",
+ total_alloced, xmalloc_calls, xmalloc_bytes, xfree_bytes);
+}
diff --git a/decomp/symtab.c b/decomp/symtab.c
new file mode 100644
index 0000000..778e9e7
--- /dev/null
+++ b/decomp/symtab.c
@@ -0,0 +1,272 @@
+/* symtab.c
+ * This file is part of decomp - a disassembler. This file contains
+ * routines for parsing the symbol table.
+ *
+ * Copyright (C) 2001 Jonathan duSaint <dusaint@earthlink.net>
+ *
+ * Started around 10 December 2001.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <elf.h>
+
+#include "decomp.h"
+
+
+#define LOCAL_LABEL_SIZE 32
+
+
+/* create_mem_ref
+ * Internal subroutine. Creates a symbol of type TYPE at virtual address
+ * VADDR and inserts it into SYMTAB, returning the new symbol.
+ */
+struct symtab *
+create_mem_ref (hash_t symtab, unsigned long vaddr, enum symbol_type type)
+{
+ static unsigned long label_value = 0;
+ struct symtab *sym;
+
+ sym = xmalloc (sizeof (struct symtab));
+
+ sym->name = xmalloc (LOCAL_LABEL_SIZE);
+
+ sprintf (sym->name, "L%ld", label_value++);
+ sym->address = vaddr;
+ sym->size = 0;
+ sym->idx = 0;
+ sym->type = type;
+
+ hash_add (symtab, vaddr, sym);
+
+ return sym;
+}
+
+/* create_jump_ref
+ * This is called when there is a jmp or a call instruction with
+ * an unnamed destination. A local label is created and
+ * inserted into SYMTAB with the key VADDR.
+ */
+struct symtab *
+create_jump_ref (hash_t symtab, unsigned long vaddr)
+{
+ return create_mem_ref (symtab, vaddr, LOCAL_UNKNOWN);
+}
+
+/* create_data_ref
+ * This is used to create a label for unnamed data that is referenced
+ * somewhere in code.
+ */
+struct symtab *
+create_data_ref (hash_t symtab, unsigned long vaddr)
+{
+ return create_mem_ref (symtab, vaddr, LOCAL_DATA);
+}
+
+
+#define N_SECTION_LIMITS 64
+
+struct section_limits {
+ unsigned long low;
+ unsigned long high;
+};
+
+struct section_limits **limits = NULL;
+
+
+/* check_is_data
+ * If VADDR is a virtual address value that is within a data section,
+ * then return 1, otherwise return 0.
+ */
+int
+check_is_data (unsigned long vaddr)
+{
+ int k = -1;
+
+ if (debug)
+ printf ("checking limit %#lx... ", vaddr);
+
+ while (limits[++k] != NULL)
+ if (vaddr >= limits[k]->low && vaddr <= limits[k]->high)
+ {
+ if (debug)
+ printf ("ok\n");
+
+ return 1;
+ }
+
+ if (debug)
+ printf ("no\n");
+
+ return 0;
+}
+
+/* put_data_limits
+ * Store the start and end virtual address of a section so that value
+ * references in code can be determined to be in a data section or not.
+ */
+void
+put_data_limits (unsigned long low, unsigned long high)
+{
+ int k = -1;
+
+ if (limits == NULL)
+ limits = xmalloc (sizeof (struct section_limits *) * N_SECTION_LIMITS);
+
+ /* find an empty slot */
+ while (limits[++k] != NULL);
+
+ limits[k] = xmalloc (sizeof (struct section_limits));
+
+ limits[k]->low = low;
+ limits[k]->high = high;
+
+ if (debug)
+ printf ("adding section limits: %#lx - %#lx\n", low, high);
+}
+
+
+/* has_precedence
+ * Determine if SYM has precedence over OLD_SYM.
+ */
+int
+has_precedence (struct symtab *sym, struct symtab *old_sym)
+{
+ return ((sym->type < LOCAL_UNKNOWN && old_sym->type >= LOCAL_UNKNOWN)
+ || (sym->size > 0 && old_sym->size == 0));
+}
+
+
+/* read_strtab
+ * Read the string table from the object file, if it exists.
+ */
+char *
+read_strtab (struct file_info *fi)
+{
+ switch (fi->file_type)
+ {
+ case FT_ELF:
+ return elf_read_strtab (fi);
+/* case FT_AOUT: */
+/* return aout_read_strtab (fi); */
+ case FT_PE:
+ return pe_read_strtab (fi);
+ case FT_NE:
+ return ne_read_strtab (fi);
+ case FT_MZ:
+ return mz_read_strtab (fi);
+/* case FT_COM: */
+/* return com_read_strtab (fi); */
+ default:
+ ;
+ }
+
+ return NULL;
+}
+
+
+/* get_next_symbol
+ * Get the next symbol from the object file and return it as a struct symtab.
+ */
+struct symtab *
+get_next_symbol (struct file_info *fi, char *strtab)
+{
+ switch (fi->file_type)
+ {
+ case FT_ELF:
+ return elf_get_next_symbol (fi, strtab);
+/* case FT_AOUT: */
+/* return aout_get_next_symbol (fi, strtab); */
+ case FT_PE:
+ return pe_get_next_symbol (fi, strtab);
+ case FT_NE:
+ return ne_get_next_symbol (fi, strtab);
+ case FT_MZ:
+ return mz_get_next_symbol (fi, strtab);
+/* case FT_COM: */
+/* return com_get_next_symbol (fi, strtab); */
+ default:
+ ;
+ }
+
+ return NULL;
+}
+
+
+/* read_symtab
+ * Read the symbol table in the object file if it exists.
+ */
+hash_t
+read_symtab (struct file_info *fi)
+{
+ unsigned long k;
+ char *strtab;
+ hash_t symtab;
+ struct symtab *sym, *old_sym;
+
+ symtab = hash_new (0);
+
+ /* if this program has been stripped, return an empty hash table */
+ if (fi->symtab == NULL) return symtab;
+ if (fi->symtab->section_name == 0) return symtab;
+
+
+ /* read in the strtab */
+ strtab = read_strtab (fi);
+
+
+ /* read in the symtab */
+ fseek (fi->fp, fi->symtab->section_offset, SEEK_SET);
+
+ for (k = 0; k < fi->symtab->section_size / fi->symtab->entsize; k++)
+ {
+ sym = get_next_symbol (fi, strtab);
+
+ if (sym == NULL) continue;
+
+ /* check if there is already a symbol at this location */
+ /* check the logic here */
+ old_sym = hash_get (symtab, sym->address);
+
+ if (old_sym != NULL)
+ {
+ if (has_precedence (sym, old_sym))
+ {
+ hash_remove (symtab, old_sym->address);
+ hash_add (symtab, sym->address, sym);
+ }
+ }
+ else
+ hash_add (symtab, sym->address, sym);
+ }
+
+ xfree (strtab);
+
+ /*if (debug)
+ hash_print (symtab);*/
+
+ return (symtab);
+}
+
+
+/* clean_symtab
+ * Clean up and deallocate the symbol table.
+ */
+void
+clean_symtab (hash_t symtab)
+{
+ unsigned long key;
+ struct symtab *sym;
+
+ hash_walk (NULL);
+
+ while ((key = hash_walk (symtab)) != HASH_END)
+ {
+ sym = hash_remove (symtab, key);
+
+ xfree (sym->name);
+ xfree (sym);
+ }
+
+ hash_delete (symtab);
+}
diff --git a/decomp/test/.runtest b/decomp/test/.runtest
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/decomp/test/.runtest
diff --git a/decomp/test/Makefile b/decomp/test/Makefile
new file mode 100644
index 0000000..904d5bf
--- /dev/null
+++ b/decomp/test/Makefile
@@ -0,0 +1,9 @@
+# test/Makefile
+# Run the testsuite
+
+SHELL = /bin/sh
+
+.PHONY : all
+
+all : .runtest
+ @echo - Running tests
diff --git a/decomp/test/bound.S b/decomp/test/bound.S
new file mode 100644
index 0000000..2cc61d9
--- /dev/null
+++ b/decomp/test/bound.S
@@ -0,0 +1,19 @@
+ # test the bound instruction
+
+ .intel_syntax noprefix
+
+ .data
+foo: .word 0
+bar: .word 10
+
+ .text
+ .global _start
+_start: int 3
+ mov ebx, foo
+ bound eax, [ebx]
+ bound eax, [edi]
+ bound edi, [eax]
+ bound edi, [edi]
+ bound [edi], edi
+ int 3
+ \ No newline at end of file
diff --git a/decomp/test/bound_decomp.S b/decomp/test/bound_decomp.S
new file mode 100644
index 0000000..77f6606
--- /dev/null
+++ b/decomp/test/bound_decomp.S
@@ -0,0 +1,26 @@
+ ; bound_decomp.S
+ ; Decompiled by Decomp from bound.
+ ; In case of an incorrect decompilation, let the author know.
+
+
+ .section .text, "xa", @progbits
+ .align 4
+
+
+ .global _start
+_start:
+ int 3 ; 08048074 cc
+ mov ebx, foo ; 08048075 8b1d84900408
+ bound eax, [ebx] ; 0804807b 6203
+ bound eax, [edi] ; 0804807d 6207
+ bound edi, [eax] ; 0804807f 6238
+ bound edi, [edi] ; 08048081 623f
+ int 3 ; 08048083 cc
+
+
+ .section .data, "aw"
+ .align 4
+
+
+foo: .int 0
+
diff --git a/decomp/test/brev.c b/decomp/test/brev.c
new file mode 100644
index 0000000..06a155f
--- /dev/null
+++ b/decomp/test/brev.c
@@ -0,0 +1,54 @@
+/* brev.c
+ * test the byte reversal routine
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+
+void
+byte_reverse (void *ptr, size_t size, size_t nmemb)
+{
+ uint8_t *buf = (uint8_t *)ptr;
+
+ if (size == 1 || nmemb == 0) return;
+
+ do
+ {
+ size_t low = 0, high = size - 1;
+
+ while (high > low)
+ {
+ uint8_t tmp;
+
+ tmp = buf[low];
+ buf[low] = buf[high];
+ buf[high] = tmp;
+
+ high--, low++;
+ }
+ }
+ while (buf += size, --nmemb);
+}
+
+
+int
+main (void)
+{
+ int unit;
+ char buffer[256];
+
+ printf ("enter some text >> ");
+ fgets (buffer, 256, stdin);
+
+ printf ("enter the unit size >> ");
+ scanf ("%d", &unit);
+
+
+ byte_reverse (buffer, unit, strlen (buffer) / unit);
+
+
+ printf ("%s", buffer);
+
+ return (0);
+}
diff --git a/decomp/test/data.c b/decomp/test/data.c
new file mode 100644
index 0000000..c071c72
--- /dev/null
+++ b/decomp/test/data.c
@@ -0,0 +1,22 @@
+/* data.c
+ * This is a test file which uses a lot of different data and datatypes.
+ * All integer values are stored as with a little endian byte order
+ * for ease of finding in the object file.
+ */
+
+
+char outside_char_array[] = "ABCDEFGHIJKLMNOP";
+short outside_short = 0x2301;
+
+int
+main (void)
+{
+ char inside_char_array[] = "0123456789:;<=>?";
+ int inside_int = 0x10325476;
+ void *inside_void_pointer = (void *)0xefcdab89;
+
+ inside_char_array[0] = outside_char_array[0];
+ inside_void_pointer = (void *)(inside_int & (int)outside_short);
+
+ return 0;
+}
diff --git a/decomp/test/data_decomp.S b/decomp/test/data_decomp.S
new file mode 100644
index 0000000..f332878
--- /dev/null
+++ b/decomp/test/data_decomp.S
@@ -0,0 +1,282 @@
+ ; data_decomp.S
+ ; Decompiled by Decomp from data.
+ ; In case of an incorrect decompilation, let the author know.
+
+
+ .section .init, "xa", @progbits
+ .align 4
+
+
+ .global _init
+ .type _init,@function
+_init:
+ push ebp ; 0804820c 55
+ mov ebp, esp ; 0804820d 89e5
+ sub esp, byte 0x8 ; 0804820f 83ec08
+ call call_gmon_start ; 08048212 e851000000
+ nop ; 08048217 90
+ call frame_dummy ; 08048218 e8ab000000
+ call __do_global_ctors_aux ; 0804821d e83e010000
+ leave ; 08048222 c9
+ ret ; 08048223 c3
+
+ .section .text, "xa", @progbits
+ .align 4
+
+
+ .global _start
+ .type _start,@function
+_start:
+ xor ebp, ebp ; 08048244 31ed
+ pop esi ; 08048246 5e
+ mov ecx, esp ; 08048247 89e1
+ and esp, byte 0xf0 ; 08048249 83e4f0
+ push eax ; 0804824c 50
+ push esp ; 0804824d 54
+ push edx ; 0804824e 52
+ push __libc_csu_fini ; 0804824f 6854830408
+ push __libc_csu_init ; 08048254 6848830408
+ push ecx ; 08048259 51
+ push esi ; 0804825a 56
+ push main ; 0804825b 68f4820408
+ call __libc_start_main ; 08048260 e8cfffffff
+ hlt ; 08048265 f4
+ nop ; 08048266 90
+ nop ; 08048267 90
+
+ .type call_gmon_start,@function
+call_gmon_start:
+ push ebp ; 08048268 55
+ mov ebp, esp ; 08048269 89e5
+ push ebx ; 0804826b 53
+ push eax ; 0804826c 50
+ call L0 ; 0804826d e800000000
+
+L0:
+ pop ebx ; 08048272 5b
+ add ebx, 0x124a ; 08048273 81c34a120000
+ mov eax, [ebx + 0x10] ; 08048279 8b8310000000
+ test eax, eax ; 0804827f 85c0
+ jz L1 ; 08048281 7402
+ call eax ; 08048283 ffd0
+
+L1:
+ mov ebx, [ebp + 0xfffffffc] ; 08048285 8b5dfc
+ leave ; 08048288 c9
+ ret ; 08048289 c3
+ nop ; 0804828a 90
+ nop ; 0804828b 90
+
+ .type __do_global_dtors_aux,@function
+__do_global_dtors_aux:
+ push ebp ; 0804828c 55
+ mov ebp, esp ; 0804828d 89e5
+ sub esp, byte 0x8 ; 0804828f 83ec08
+ cmp byte completed.1, 0x0 ; 08048292 803dd094040800
+ jnz L2 ; 08048299 7529
+ mov eax, [0x80493c4] ; 0804829b a1c4930408
+ mov edx, [eax] ; 080482a0 8b10
+ test edx, edx ; 080482a2 85d2
+ jz L3 ; 080482a4 7417
+ mov esi, esi ; 080482a6 89f6
+
+L4:
+ add eax, byte 0x4 ; 080482a8 83c004
+ mov [0x80493c4], eax ; 080482ab a3c4930408
+ call edx ; 080482b0 ffd2
+ mov eax, [0x80493c4] ; 080482b2 a1c4930408
+ mov edx, [eax] ; 080482b7 8b10
+ test edx, edx ; 080482b9 85d2
+ jnz L4 ; 080482bb 75eb
+
+L3:
+ mov byte completed.1, 0x1 ; 080482bd c605d094040801
+
+L2:
+ leave ; 080482c4 c9
+ ret ; 080482c5 c3
+ mov esi, esi ; 080482c6 89f6
+
+ .type frame_dummy,@function
+frame_dummy:
+ push ebp ; 080482c8 55
+ mov ebp, esp ; 080482c9 89e5
+ sub esp, byte 0x8 ; 080482cb 83ec08
+ mov eax, [0x80494b8] ; 080482ce a1b8940408
+ test eax, eax ; 080482d3 85c0
+ jz L5 ; 080482d5 7419
+ mov eax, 0x0000 ; 080482d7 b800000000
+ test eax, eax ; 080482dc 85c0
+ jz L5 ; 080482de 7410
+ sub esp, byte 0xc ; 080482e0 83ec0c
+ push __JCR_LIST__ ; 080482e3 68b8940408
+ call L6 ; 080482e8 e8137dfbf7
+ add esp, byte 0x10 ; 080482ed 83c410
+
+L5:
+ leave ; 080482f0 c9
+ ret ; 080482f1 c3
+ nop ; 080482f2 90
+ nop ; 080482f3 90
+
+ .global main
+ .type main,@function
+ .size main, 81
+main:
+ push ebp ; 080482f4 55
+ mov ebp, esp ; 080482f5 89e5
+ push edi ; 080482f7 57
+ push esi ; 080482f8 56
+ sub esp, byte 0x30 ; 080482f9 83ec30
+ and esp, byte 0xf0 ; 080482fc 83e4f0
+ mov eax, L6 ; 080482ff b800000000
+ sub esp, eax ; 08048304 29c4
+ lea edi, [ebp + 0xffffffd8] ; 08048306 8d7dd8
+ mov esi, L7 ; 08048309 bea8830408
+ cld ; 0804830e fc
+ mov ecx, 0x0011 ; 0804830f b911000000
+ repe movsb ; 08048314 f3a4
+ mov dword [ebp + 0xffffffd4], 0x10325476 ; 08048316 c745d476543210
+ mov dword [ebp + 0xffffffd0], 0xefcdab89 ; 0804831d c745d089abcdef
+ mov al, [0xbffff568] ; 08048324 a0
+ enter 0x493, 0x8 ; 08048325 c8930408
+ mov [ebp + 0xffffffd8], al ; 08048329 8845d8
+ movsx eax, outside_short ; 0804832c 0fbf05da930408
+ and eax, [ebp + 0xffffffd4] ; 08048333 2345d4
+ mov [ebp + 0xffffffd0], eax ; 08048336 8945d0
+ mov eax, L6 ; 08048339 b800000000
+ lea esp, [ebp + 0xfffffff8] ; 0804833e 8d65f8
+ pop esi ; 08048341 5e
+ pop edi ; 08048342 5f
+ leave ; 08048343 c9
+ ret ; 08048344 c3
+ nop ; 08048345 90
+ nop ; 08048346 90
+ nop ; 08048347 90
+
+ .global __libc_csu_init
+ .type __libc_csu_init,@function
+ .size __libc_csu_init, 9
+__libc_csu_init:
+ push ebp ; 08048348 55
+ mov ebp, esp ; 08048349 89e5
+ leave ; 0804834b c9
+ jmp _init ; 0804834c e9bbfeffff
+ nop ; 08048351 90
+ mov esi, esi ; 08048352 89f6
+
+ .global __libc_csu_fini
+ .type __libc_csu_fini,@function
+ .size __libc_csu_fini, 9
+__libc_csu_fini:
+ push ebp ; 08048354 55
+ mov ebp, esp ; 08048355 89e5
+ leave ; 08048357 c9
+ jmp _fini ; 08048358 e927000000
+ nop ; 0804835d 90
+ nop ; 0804835e 90
+ nop ; 0804835f 90
+
+ .type __do_global_ctors_aux,@function
+__do_global_ctors_aux:
+ push ebp ; 08048360 55
+ mov ebp, esp ; 08048361 89e5
+ push ebx ; 08048363 53
+ push edx ; 08048364 52
+ mov eax, [0x80494a8] ; 08048365 a1a8940408
+ cmp eax, byte 0xff ; 0804836a 83f8ff
+ mov ebx, __CTOR_LIST__ ; 0804836d bba8940408
+ jz L8 ; 08048372 740c
+
+L9:
+ sub ebx, byte 0x4 ; 08048374 83eb04
+ call eax ; 08048377 ffd0
+ mov eax, [ebx] ; 08048379 8b03
+ cmp eax, byte 0xff ; 0804837b 83f8ff
+ jnz L9 ; 0804837e 75f4
+
+L8:
+ pop eax ; 08048380 58
+ pop ebx ; 08048381 5b
+ leave ; 08048382 c9
+ ret ; 08048383 c3
+
+ .section .fini, "xa", @progbits
+ .align 4
+
+
+ .global _fini
+ .type _fini,@function
+_fini:
+ push ebp ; 08048384 55
+ mov ebp, esp ; 08048385 89e5
+ push ebx ; 08048387 53
+ push edx ; 08048388 52
+ call L10 ; 08048389 e800000000
+
+L10:
+ pop ebx ; 0804838e 5b
+ add ebx, 0x112e ; 0804838f 81c32e110000
+ nop ; 08048395 90
+ call __do_global_dtors_aux ; 08048396 e8f1feffff
+ mov ebx, [ebp + 0xfffffffc] ; 0804839b 8b5dfc
+ leave ; 0804839e c9
+ ret ; 0804839f c3
+
+
+ .section .rodata, "a"
+ .align 4
+
+
+ .global _fp_hw
+ .type _fp_hw,@object
+ .size _fp_hw, 4
+_fp_hw: .int 0x3
+
+
+ .global _IO_stdin_used
+ .type _IO_stdin_used,@object
+ .size _IO_stdin_used, 4
+_IO_stdin_used: .int 0x20001
+
+
+ .type L7,@object
+L7: .string "0123456789:;<=>?"
+
+ .byte 0x00
+
+ .section .data, "aw"
+ .align 4
+
+
+data_start: .int 0
+
+
+ .global __dso_handle
+ .type __dso_handle,@object
+__dso_handle: .int 0
+
+
+ .type p.0,@object
+p.0: .int 0x80494b4
+
+
+ .global outside_char_array
+ .type outside_char_array,@object
+ .size outside_char_array, 17
+outside_char_array: .string "ABCDEFGHIJKLMNOP"
+
+ .byte 0x00
+
+ .global outside_short
+ .type outside_short,@object
+ .size outside_short, 2
+outside_short: .hword 0x2301
+
+
+ .section .jcr, "aw"
+ .align 4
+
+
+ .type __JCR_LIST__,@object
+__JCR_LIST__: .int 0
diff --git a/decomp/test/foo.c b/decomp/test/foo.c
new file mode 100644
index 0000000..fa9c86f
--- /dev/null
+++ b/decomp/test/foo.c
@@ -0,0 +1,91 @@
+/* foo.c
+ * one file of a testlib
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+/* text_number
+ * Convert NR to a textual representation and place it in STR. The
+ * largest number that will be converted is 999,999,999.
+ */
+void
+text_number (char *str, unsigned long nr)
+{
+ unsigned long tmp;
+ char *ones[] = { "zero", "one", "two", "three", "four",
+ "five", "six", "seven", "eight", "nine",
+ "ten", "eleven", "twelve", "thirteen", "fourteen",
+ "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
+
+ char *tens[] = { NULL, NULL, "twenty", "thirty", "forty",
+ "fifty", "sixty", "seventy", "eighty", "ninety" };
+
+ char hundred[] = "hundred";
+ char thousand[] = "thousand";
+ char million[] = "million";
+
+ /* handle unusual cases */
+ if (nr > 999999999L)
+ {
+ strcat (str, "big number");
+ return;
+ }
+ else if (nr == 0)
+ {
+ strcat (str, ones[nr]);
+ return;
+ }
+
+ /* do 1000000's first */
+ if (nr > 999999)
+ {
+ tmp = nr / 1000000;
+ text_number (str, tmp);
+ strcat (str, " ");
+ strcat (str, million);
+ strcat (str, " ");
+ nr -= tmp * 1000000;
+ }
+
+ /* then do 1000's */
+ if (nr > 999)
+ {
+ tmp = nr / 1000;
+ text_number (str, tmp);
+ strcat (str, " ");
+ strcat (str, thousand);
+ strcat (str, " ");
+ nr -= tmp * 1000;
+ }
+
+ /* do 100's */
+ tmp = nr / 100;
+ if (tmp)
+ {
+ strcat (str, ones[tmp]);
+ strcat (str, " ");
+ strcat (str, hundred);
+ strcat (str, " ");
+ }
+
+ /* do tens */
+ nr -= tmp * 100;
+ if (nr == 0) return;
+
+ if (nr < 20)
+ {
+ strcat (str, ones[nr]);
+ return;
+ }
+
+ tmp = nr / 10;
+ strcat (str, tens[tmp]);
+
+ /* do ones */
+ nr -= tmp * 10;
+ if (nr == 0) return;
+
+ strcat (str, "-");
+ strcat (str, ones[nr]);
+}
diff --git a/decomp/test/hashtest.c b/decomp/test/hashtest.c
new file mode 100644
index 0000000..63d67a5
--- /dev/null
+++ b/decomp/test/hashtest.c
@@ -0,0 +1,555 @@
+/* hashtest.c
+ * This file is part of Decomp - a disassembler. This file is
+ * intended to stress test the hash routines.
+ *
+ * Copyright (C) 2001 Jonathan duSaint
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <getopt.h>
+
+#include "decomp.h"
+
+
+#define MAX_LINE_SIZE 256
+
+
+char pname[] = "Hashtest";
+int debug = 0;
+int file_is_loaded = 0;
+hash_t table = NULL;
+
+
+struct command {
+ char *text;
+ void (*function)(char *);
+};
+
+
+/* command functions */
+void create (char *line);
+void destroy (char *line);
+void load_file (char *line);
+void get_entry (char *line);
+void put_entry (char *line);
+void del_entry (char *line);
+void good_test (char *line);
+void resize (char *line);
+void list (char *line);
+void print (char *line);
+void quit (char *line);
+
+struct command commands[] = {
+ { "commands", list },
+ { "create", create },
+ { "del", del_entry },
+ { "destroy", destroy },
+ { "exit", quit },
+ { "get", get_entry },
+ { "good", good_test },
+ { "help", list },
+ { "load", load_file },
+ { "print", print },
+ { "put", put_entry },
+ { "quit", quit },
+ { "resize", resize },
+ { NULL, NULL }
+};
+
+
+/* text_number
+ * Convert NR to a textual representation and place it in STR. The
+ * largest number that will be converted is 999,999,999.
+ */
+void
+text_number (char *str, unsigned long nr)
+{
+ unsigned long tmp;
+ char *ones[] = { "zero", "one", "two", "three", "four",
+ "five", "six", "seven", "eight", "nine",
+ "ten", "eleven", "twelve", "thirteen", "fourteen",
+ "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
+
+ char *tens[] = { NULL, NULL, "twenty", "thirty", "forty",
+ "fifty", "sixty", "seventy", "eighty", "ninety" };
+
+ char hundred[] = "hundred";
+ char thousand[] = "thousand";
+ char million[] = "million";
+
+ /* handle unusual cases */
+ if (nr > 999999999L)
+ {
+ strcat (str, "big number");
+ return;
+ }
+ else if (nr == 0)
+ {
+ strcat (str, ones[nr]);
+ return;
+ }
+
+ /* do 1000000's first */
+ if (nr > 999999)
+ {
+ tmp = nr / 1000000;
+ text_number (str, tmp);
+ strcat (str, " ");
+ strcat (str, million);
+ strcat (str, " ");
+ nr -= tmp * 1000000;
+ }
+
+ /* then do 1000's */
+ if (nr > 999)
+ {
+ tmp = nr / 1000;
+ text_number (str, tmp);
+ strcat (str, " ");
+ strcat (str, thousand);
+ strcat (str, " ");
+ nr -= tmp * 1000;
+ }
+
+ /* do 100's */
+ tmp = nr / 100;
+ if (tmp)
+ {
+ strcat (str, ones[tmp]);
+ strcat (str, " ");
+ strcat (str, hundred);
+ strcat (str, " ");
+ }
+
+ /* do tens */
+ nr -= tmp * 100;
+ if (nr == 0) return;
+
+ if (nr < 20)
+ {
+ strcat (str, ones[nr]);
+ return;
+ }
+
+ tmp = nr / 10;
+ strcat (str, tens[tmp]);
+
+ /* do ones */
+ nr -= tmp * 10;
+ if (nr == 0) return;
+
+ strcat (str, "-");
+ strcat (str, ones[nr]);
+}
+
+
+void
+create (char *line)
+{
+ if (table != NULL)
+ {
+ printf ("--> Hash table already created, use 'destroy' first\n");
+ return;
+ }
+
+ table = hash_new (0);
+}
+
+void
+destroy (char *line)
+{
+ if (table == NULL)
+ {
+ printf ("--> No hash table created, use create or load first\n");
+ return;
+ }
+
+ hash_delete (table);
+
+ table = NULL;
+}
+
+void
+load_file (char *line)
+{
+ char *file_line, *line_number;
+ char **command_line;
+ unsigned long line_no = 0;
+ FILE *fp;
+
+ if (table != NULL)
+ {
+ printf ("--> Hash table already created, use 'destroy' first\n");
+ return;
+ }
+
+ command_line = history_tokenize (line);
+
+ if (command_line[1] == NULL)
+ {
+ printf ("--> %s requires a file name\n", command_line[0]);
+ return;
+ }
+
+ fp = fopen (command_line[1], "rt");
+ if (fp == NULL)
+ {
+ printf ("--> Unable to open %s: %s\n", command_line[1],
+ strerror (errno));
+ return;
+ }
+
+ table = hash_new (0);
+
+ while (1)
+ {
+ line_number = xmalloc (MAX_LINE_SIZE);
+ memset (line_number, 0, MAX_LINE_SIZE);
+ file_line = xmalloc (MAX_LINE_SIZE);
+
+ if (fgets (file_line, MAX_LINE_SIZE, fp) == NULL) break;
+ file_line[strlen (file_line) - 1] = '\0';
+ text_number (line_number, line_no);
+
+ hash_add (table, line_number, file_line);
+ printf ("put '%s'\n", line_number);
+
+ xfree (line_number);
+ line_no++;
+ }
+
+ file_is_loaded = 1;
+ fclose (fp);
+}
+
+void
+get_entry (char *line)
+{
+ char *line_number;
+ char **command_line;
+ unsigned long line_no;
+
+ if (table == NULL)
+ {
+ printf ("--> No hash table created, use create or load first\n");
+ return;
+ }
+
+ command_line = history_tokenize (line);
+
+ if (command_line[1] == NULL)
+ {
+ printf ("--> A line number or key is required\n");
+ return;
+ }
+
+ if (isdigit (command_line[1][0]))
+ {
+ line_no = strtoul (command_line[1], NULL, 0);
+ line_number = xmalloc (MAX_LINE_SIZE);
+ text_number (line_number, line_no);
+
+ printf (" '%s' ->\n'%s'\n\n", line_number,
+ (char *)hash_get (table, line_number));
+
+ xfree (line_number);
+ }
+ else
+ {
+ printf (" '%s' ->\n'%s'\n\n", command_line[1],
+ (char *)hash_get (table, command_line[1]));
+ }
+}
+
+void
+put_entry (char *line)
+{
+ char *key;
+ char **command_line;
+
+ if (table == NULL)
+ {
+ printf ("--> No hash table created, use create or load first\n");
+ return;
+ }
+
+ command_line = history_tokenize (line);
+
+ if (command_line[1] == NULL || command_line[2] == NULL)
+ {
+ printf ("--> Correct syntax is put <key> <value>\n");
+ return;
+ }
+
+ if (isdigit (command_line[1][0]))
+ {
+ unsigned long line_no;
+
+ line_no = strtoul (command_line[1], NULL, 0);
+ key = xmalloc (MAX_LINE_SIZE);
+ text_number (key, line_no);
+ }
+ else
+ key = command_line[1];
+
+ hash_add (table, key, command_line[2]);
+
+ if (key != command_line[1])
+ xfree (key);
+}
+
+void
+del_entry (char *line)
+{
+ char *key;
+ char **command_line;
+
+ if (table == NULL)
+ {
+ printf ("--> No hash table created, use create or load first\n");
+ return;
+ }
+
+ command_line = history_tokenize (line);
+
+ if (command_line[1] == NULL)
+ {
+ printf ("--> Correct syntax is del <key>\n");
+ return;
+ }
+
+ if (isdigit (command_line[1][0]))
+ {
+ unsigned long line_no;
+
+ line_no = strtoul (command_line[1], NULL, 0);
+ key = xmalloc (MAX_LINE_SIZE);
+ text_number (key, line_no);
+ }
+ else
+ key = command_line[1];
+
+ hash_remove (table, key);
+
+ if (key != command_line[1])
+ xfree (key);
+}
+
+void
+good_test (char *line)
+{
+ if (table == NULL)
+ {
+ printf ("--> No hash table created, use create or load first\n");
+ return;
+ }
+
+ printf (" goodness value %lf\n", hash_goodness (table));
+}
+
+void
+resize (char *line)
+{
+ unsigned long size;
+ char **command_line;
+
+ if (table == NULL)
+ {
+ printf ("--> No hash table created, use create or load first\n");
+ return;
+ }
+
+ command_line = history_tokenize (line);
+
+ if (command_line[1] == NULL)
+ size = 0;
+ else
+ size = strtoul (command_line[1], NULL, 0);
+
+ table = hash_rehash (table, size);
+}
+
+void
+list (char *line)
+{
+ int k = -1;
+
+ printf ("possible commands are:\n");
+
+ while (commands[++k].text != NULL) printf (" %s\n", commands[k].text);
+}
+
+void
+print (char *line)
+{
+ if (table == NULL)
+ {
+ printf ("--> No hash table created, use create or load first\n");
+ return;
+ }
+
+ hash_print (table);
+}
+
+void
+quit (char *line)
+{
+ exit (EXIT_SUCCESS);
+}
+
+
+/* can't use the xmalloc/xfree from memory.c because of readline */
+void *
+xmalloc (size_t amt)
+{
+ void *mem;
+
+ mem = malloc (amt);
+
+ if (mem == NULL) PANIC;
+
+ memset (mem, 0, amt);
+ return mem;
+}
+
+void
+xfree (void *mem)
+{
+ free (mem);
+}
+
+/* generate_tablist
+ * Generator function for TAB completion with READLINE.
+ */
+char *
+generate_tablist (char *text, int state)
+{
+ static int index;
+ char *str;
+
+ if (!state) index = -1;
+
+ while (commands[++index].text != NULL)
+ {
+ if (!strncmp (commands[index].text, text, strlen (text)))
+ {
+ str = xmalloc (strlen (commands[index].text) + 1);
+ strcpy (str, commands[index].text);
+
+ return (str);
+ }
+ }
+
+ return (NULL);
+}
+
+
+void
+print_help (void)
+{
+
+}
+
+void
+print_version (void)
+{
+
+}
+
+int
+main (int argc, char *argv[])
+{
+ int opt;
+ char *prompt, *line;
+ struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { 0, 0, 0, 0 }
+ };
+
+ prompt = "hashtest>> ";
+
+
+ /* parse through argv, looking for options */
+ while (1)
+ {
+ opt = getopt_long (argc, argv, "hv", options, NULL);
+
+ if (opt == EOF) break;
+
+ switch (opt)
+ {
+ case 'h':
+ print_help ();
+ exit (EXIT_SUCCESS);
+ case 'v':
+ print_version ();
+ exit (EXIT_SUCCESS);
+ case '?':
+ fprintf (stderr, "%s: unknown option character `%c'\n", pname,
+ optopt);
+ exit (EXIT_FAILURE);
+ default:
+ fprintf (stderr,
+ "%s: ?? getopt returned character code 0x%x (%c) ??\n",
+ pname, opt, opt);
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ debug = 1;
+ rl_completion_entry_function = (Function *)generate_tablist;
+ rl_readline_name = pname;
+
+ using_history ();
+
+ while (1)
+ {
+ int k = -1, start = 0;
+
+ fflush (stdin);
+ line = readline (prompt);
+
+ if (line == NULL) break;
+ if (!line[0]) continue;
+
+ add_history (line);
+
+ /* find start of string */
+ while (line[start] && !isalpha (line[start])) start++;
+
+ /* dispatch the function */
+ while (commands[++k].text != NULL)
+ if (!strncmp (commands[k].text, line + start,
+ strlen (commands[k].text)))
+ {
+ commands[k].function (line + start);
+ goto SKIP;
+ }
+
+
+ /* if we got here, then we have a problem */
+
+ /* find the token end */
+ k = start;
+ while (line[k] && !isspace (line[k])) k++;
+
+ k -= start;
+ start += strlen (prompt);
+
+ while (start--) printf (" ");
+ while (k--) printf ("^");
+
+ printf ("\n--> Invalid command - type 'commands' for a list\n");
+
+ SKIP:
+ ;
+ }
+
+ return (0);
+}
diff --git a/decomp/test/hll.S b/decomp/test/hll.S
new file mode 100644
index 0000000..986e516
--- /dev/null
+++ b/decomp/test/hll.S
@@ -0,0 +1,318 @@
+ ; foo.S
+ ; Decompiled by Decomp from test/hll.
+ ; In case of an incorrect decompilation, let the author know.
+
+
+ .section .init, "xa", @progbits
+ .align 4
+
+
+ .global _init
+ .type _init,@function
+_init:
+ push ebp ; 08048350 55
+ mov ebp, esp ; 08048351 89e5
+ sub esp, byte 0x8 ; 08048353 83ec08
+ call call_gmon_start ; 08048356 e8c9000000
+ nop ; 0804835b 90
+ call frame_dummy ; 0804835c e85f010000
+ call __do_global_ctors_aux ; 08048361 e82a020000
+ leave ; 08048366 c9
+ ret ; 08048367 c3
+
+ .section .text, "xa", @progbits
+ .align 16
+
+
+ .global _start
+_start:
+ xor ebp, ebp ; 08048400 31ed
+ pop esi ; 08048402 5e
+ mov ecx, esp ; 08048403 89e1
+ and esp, byte 0xf0 ; 08048405 83e4f0
+ push eax ; 08048408 50
+ push esp ; 08048409 54
+ push edx ; 0804840a 52
+ push _fini ; 0804840b 68cc850408
+ push _init ; 08048410 6850830408
+ push ecx ; 08048415 51
+ push esi ; 08048416 56
+ push main ; 08048417 6800850408
+ call __libc_start_main ; 0804841c e887ffffff
+ hlt ; 08048421 f4
+ nop ; 08048422 90
+ nop ; 08048423 90
+
+ .type call_gmon_start,@function
+call_gmon_start:
+ push ebp ; 08048424 55
+ mov ebp, esp ; 08048425 89e5
+ push ebx ; 08048427 53
+ push eax ; 08048428 50
+ call L0 ; 08048429 e800000000
+
+L0:
+ pop ebx ; 0804842e 5b
+ add ebx, 0x1202 ; 0804842f 81c302120000
+ mov eax, [ebx + 0x2c] ; 08048435 8b832c000000
+ test eax, eax ; 0804843b 85c0
+ jz L1 ; 0804843d 7402
+ call eax ; 0804843f ffd0
+
+L1:
+ mov ebx, [ebp + 0xfffffffc] ; 08048441 8b5dfc
+ leave ; 08048444 c9
+ ret ; 08048445 c3
+ nop ; 08048446 90
+ nop ; 08048447 90
+ nop ; 08048448 90
+ nop ; 08048449 90
+ nop ; 0804844a 90
+ nop ; 0804844b 90
+ nop ; 0804844c 90
+ nop ; 0804844d 90
+ nop ; 0804844e 90
+ nop ; 0804844f 90
+
+ .type __do_global_dtors_aux,@function
+__do_global_dtors_aux:
+ push ebp ; 08048450 55
+ mov edx, completed.1 ; 08048451 8b1514960408
+ mov ebp, esp ; 08048457 89e5
+ sub esp, byte 0x8 ; 08048459 83ec08
+ test edx, edx ; 0804845c 85d2
+ jnz L2 ; 0804845e 7549
+ mov edx, p.0 ; 08048460 8b1510960408
+ mov eax, [edx] ; 08048466 8b02
+ test eax, eax ; 08048468 85c0
+ jz L3 ; 0804846a 741a
+ lea esi, [esi + 0] ; 0804846c 8d742600
+
+L4:
+ lea eax, [edx + 0x4] ; 08048470 8d4204
+ mov [0x8049610], eax ; 08048473 a310960408
+ call dword [edx] ; 08048478 ff12
+ mov edx, p.0 ; 0804847a 8b1510960408
+ mov ecx, [edx] ; 08048480 8b0a
+ test ecx, ecx ; 08048482 85c9
+ jnz L4 ; 08048484 75ea
+
+L3:
+ mov eax, __deregister_frame_info ; 08048486 b898830408
+ test eax, eax ; 0804848b 85c0
+ jz L5 ; 0804848d 7410
+ sub esp, byte 0xc ; 0804848f 83ec0c
+ push __EH_FRAME_BEGIN__ ; 08048492 681c960408
+ call __deregister_frame_info ; 08048497 e8fcfeffff
+ add esp, byte 0x10 ; 0804849c 83c410
+
+L5:
+ mov eax, 0x0001 ; 0804849f b801000000
+ mov [0x8049614], eax ; 080484a4 a314960408
+
+L2:
+ mov esp, ebp ; 080484a9 89ec
+ pop ebp ; 080484ab 5d
+ ret ; 080484ac c3
+ lea esi, [esi + 0] ; 080484ad 8d7600
+
+ .type fini_dummy,@function
+fini_dummy:
+ push ebp ; 080484b0 55
+ mov ebp, esp ; 080484b1 89e5
+ sub esp, byte 0x8 ; 080484b3 83ec08
+ mov esp, ebp ; 080484b6 89ec
+ pop ebp ; 080484b8 5d
+ ret ; 080484b9 c3
+ lea esi, [esi + 0] ; 080484ba 8db600000000
+
+ .type frame_dummy,@function
+frame_dummy:
+ push ebp ; 080484c0 55
+ mov ebp, esp ; 080484c1 89e5
+ mov eax, __register_frame_info ; 080484c3 b878830408
+ sub esp, byte 0x8 ; 080484c8 83ec08
+ test eax, eax ; 080484cb 85c0
+ jz L6 ; 080484cd 7415
+ sub esp, byte 0x8 ; 080484cf 83ec08
+ push object.2 ; 080484d2 6800970408
+ push __EH_FRAME_BEGIN__ ; 080484d7 681c960408
+ call __register_frame_info ; 080484dc e897feffff
+ add esp, byte 0x10 ; 080484e1 83c410
+
+L6:
+ mov esp, ebp ; 080484e4 89ec
+ pop ebp ; 080484e6 5d
+ ret ; 080484e7 c3
+ nop ; 080484e8 90
+ lea esi, [esi + 0] ; 080484e9 8db42600000000
+
+ .type init_dummy,@function
+init_dummy:
+ push ebp ; 080484f0 55
+ mov ebp, esp ; 080484f1 89e5
+ sub esp, byte 0x8 ; 080484f3 83ec08
+ mov esp, ebp ; 080484f6 89ec
+ pop ebp ; 080484f8 5d
+ ret ; 080484f9 c3
+ nop ; 080484fa 90
+ nop ; 080484fb 90
+ nop ; 080484fc 90
+ nop ; 080484fd 90
+ nop ; 080484fe 90
+ nop ; 080484ff 90
+
+ .global main
+ .type main,@function
+ .size main, 138
+main:
+ push ebp ; 08048500 55
+ mov ebp, esp ; 08048501 89e5
+ sub esp, byte 0x8 ; 08048503 83ec08
+ sub esp, byte 0xc ; 08048506 83ec0c
+ push 0x20 ; 08048509 6a20
+ call malloc ; 0804850b e878feffff
+ add esp, byte 0x10 ; 08048510 83c410
+ mov eax, eax ; 08048513 89c0
+ mov [0x8049718], eax ; 08048515 a318970408
+ lea esi, [esi + 0] ; 0804851a 8db600000000
+
+L11:
+ cmp dword foo, byte 0x9 ; 08048520 833d1896040809
+ jle L7 ; 08048527 7e07
+ jmp short L8 ; 08048529 eb45
+ nop ; 0804852b 90
+ lea esi, [esi + 0] ; 0804852c 8d742600
+
+L7:
+ sub esp, byte 0x4 ; 08048530 83ec04
+ push dword foo ; 08048533 ff3518960408
+ push L9 ; 08048539 68f4850408
+ push dword bar ; 0804853e ff3518970408
+ call sprintf ; 08048544 e89ffeffff
+ add esp, byte 0x10 ; 08048549 83c410
+ sub esp, byte 0x8 ; 0804854c 83ec08
+ push dword bar ; 0804854f ff3518970408
+ push L10 ; 08048555 6805860408
+ call printf ; 0804855a e859feffff
+ add esp, byte 0x10 ; 0804855f 83c410
+ inc dword foo ; 08048562 ff0518960408
+ jmp short L11 ; 08048568 ebb6
+ lea esi, [esi + 0] ; 0804856a 8db600000000
+
+L8:
+ sub esp, byte 0xc ; 08048570 83ec0c
+ push dword bar ; 08048573 ff3518970408
+ call free ; 08048579 e85afeffff
+ add esp, byte 0x10 ; 0804857e 83c410
+ mov eax, 0x0000 ; 08048581 b800000000
+ mov esp, ebp ; 08048586 89ec
+ pop ebp ; 08048588 5d
+ ret ; 08048589 c3
+ nop ; 0804858a 90
+ nop ; 0804858b 90
+ nop ; 0804858c 90
+ nop ; 0804858d 90
+ nop ; 0804858e 90
+ nop ; 0804858f 90
+
+ .type __do_global_ctors_aux,@function
+__do_global_ctors_aux:
+ push ebp ; 08048590 55
+ mov eax, [0x8049620] ; 08048591 a120960408
+ mov ebp, esp ; 08048596 89e5
+ push ebx ; 08048598 53
+ sub esp, byte 0x4 ; 08048599 83ec04
+ cmp eax, byte 0xff ; 0804859c 83f8ff
+ mov ebx, __CTOR_LIST__ ; 0804859f bb20960408
+ jz L12 ; 080485a4 7416
+ lea esi, [esi + 0] ; 080485a6 8d7600
+ lea edi, [edi + 0] ; 080485a9 8dbc2700000000
+
+L13:
+ sub ebx, byte 0x4 ; 080485b0 83eb04
+ call eax ; 080485b3 ffd0
+ mov eax, [ebx] ; 080485b5 8b03
+ cmp eax, byte 0xff ; 080485b7 83f8ff
+ jnz L13 ; 080485ba 75f4
+
+L12:
+ pop eax ; 080485bc 58
+ pop ebx ; 080485bd 5b
+ pop ebp ; 080485be 5d
+ ret ; 080485bf c3
+
+ .type init_dummy,@function
+init_dummy:
+ push ebp ; 080485c0 55
+ mov ebp, esp ; 080485c1 89e5
+ sub esp, byte 0x8 ; 080485c3 83ec08
+ mov esp, ebp ; 080485c6 89ec
+ pop ebp ; 080485c8 5d
+ ret ; 080485c9 c3
+ nop ; 080485ca 90
+ nop ; 080485cb 90
+
+ .section .fini, "xa", @progbits
+ .align 4
+
+
+ .global _fini
+ .type _fini,@function
+_fini:
+ push ebp ; 080485cc 55
+ mov ebp, esp ; 080485cd 89e5
+ push ebx ; 080485cf 53
+ push edx ; 080485d0 52
+ call L14 ; 080485d1 e800000000
+
+L14:
+ pop ebx ; 080485d6 5b
+ add ebx, 0x105a ; 080485d7 81c35a100000
+ lea esi, [esi + 0] ; 080485dd 8d7600
+ call __do_global_dtors_aux ; 080485e0 e86bfeffff
+ mov ebx, [ebp + 0xfffffffc] ; 080485e5 8b5dfc
+ leave ; 080485e8 c9
+ ret ; 080485e9 c3
+
+
+ .section .rodata, "a"
+ .align 4
+
+ .byte 0x03, 0x00, 0x00
+ .byte 0x00
+
+ .global _IO_stdin_used
+ .type _IO_stdin_used,@object
+ .size _IO_stdin_used, 4
+_IO_stdin_used: .int 0x20001
+
+
+ .type L9,@object
+L9: .string "this is loop %d\n"
+
+
+ .type L10,@object
+L10: .string "%s"
+
+
+ .section .data, "aw"
+ .align 4
+
+
+data_start: .int 0
+
+
+ .global __dso_handle
+ .type __dso_handle,@object
+__dso_handle: .int 0
+
+
+ .type p.0,@object
+p.0: .quad 0x804962c
+
+
+ .global foo
+ .type foo,@object
+ .size foo, 4
+foo: .int 0
diff --git a/decomp/test/hll.c b/decomp/test/hll.c
new file mode 100644
index 0000000..ea01e53
--- /dev/null
+++ b/decomp/test/hll.c
@@ -0,0 +1,28 @@
+/* hll.c
+ * High level language test.
+ *
+ * Copyright (C) 2002 Jonathan duSaint
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int foo = 0;
+char *bar;
+
+int
+main (void)
+{
+ bar = malloc (32);
+
+ for (; foo < 10; foo++)
+ {
+ sprintf (bar, "this is loop %d\n", foo);
+ printf ("%s", bar);
+ }
+
+ free (bar);
+
+ return 0;
+}
diff --git a/decomp/test/memtest.c b/decomp/test/memtest.c
new file mode 100644
index 0000000..7faba54
--- /dev/null
+++ b/decomp/test/memtest.c
@@ -0,0 +1,222 @@
+/* memtest.c
+ * Stress test the memory routines.
+ *
+ * Copyright (C) 2001 Jonathan duSaint
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include <getopt.h>
+
+#include "decomp.h"
+
+
+/* the largest block of memory to allocate */
+#define MAX_TEST_SIZE 512
+
+/* the default number of allocations to make */
+#define NUM_TESTS 2048
+
+/* the likelyhood that a block of memory will be freed */
+#define DEFAULT_PERCENT 75
+
+/* return a value from 1 to MAX_TEST_SIZE */
+#define RANDOM_BLOCK_SIZE ((int)((double)rand ()/RAND_MAX*MAX_TEST_SIZE) + 1);
+
+
+/* the nominal name of the program */
+char pname[] = "Memtest";
+
+/* current version */
+char version[] = "1.0";
+
+
+/* set if a SIGSEGV is recieved - if this is set and another SIGSEGV
+ is recieved, then abort is immediately called */
+volatile int got_segv = 0;
+
+
+/* segv_handler
+ * Handle a SIGSEGV
+ */
+void
+segv_handler (int sig)
+{
+ fprintf (stderr, "got SIGSEGV\n");
+
+ /* two SEGV's in a row - bad juju, but it has been known to happen */
+ if (got_segv) abort ();
+
+ got_segv = 1;
+}
+
+
+/* print_help
+ * Print a usage message.
+ */
+void
+print_help (void)
+{
+ printf ("Usage: memtest [OPTION]...\n"
+ "Stress-test the memory allocation routines\n"
+ "\n"
+ " -c, --calls <CALLS> The number of times to call alloc\n"
+ " default is %d, "
+ "valid values are 1-65535\n"
+ " -f, --free <PERCENT> What percentage of allocations "
+ "are freed\n"
+ " default is %d, "
+ "valid values are 1-100\n"
+ " -h, --help Print this message\n"
+ " -o, --no-output Don't print alloc and free messages\n"
+ " -t, --no-trace Instruct the allocation routines\n"
+ " not to print messages\n"
+ " -v, --version Print version information\n"
+ "\n"
+ "Report bugs to Jonathan duSaint <jdusaint@penguinpunk.com>\n",
+ NUM_TESTS, DEFAULT_PERCENT);
+}
+
+/* print_version
+ * Print version and copyright information.
+ */
+void
+print_version (void)
+{
+ printf ("%s (%s %s) %s\n"
+ "Copyright (C) 2001 Jonathan duSaint <jdusaint@penguinpunk.com>\n"
+ "%s comes with NO WARRANTY, to the extent\n"
+ "permitted by law. You may redistribute copies\n"
+ "of %s under the terms of the GNU General\n"
+ "Public License. For more information about\n"
+ "these matters, see the file named COPYING.\n",
+ pname, PACKAGE_NAME, PACKAGE_VERSION, version, pname, pname);
+
+}
+
+/* main
+ */
+int
+main (int argc, char *argv[])
+{
+ int k, block_size, output = 1, trace = 1, free_percent = DEFAULT_PERCENT;
+ long calls = NUM_TESTS;
+ char *some_memory, opt;
+ struct option options[] = {
+ { "calls", required_argument, NULL, 'c' },
+ { "free", required_argument, NULL, 'f' },
+ { "help", no_argument, NULL, 'h' },
+ { "no-output", no_argument, NULL, 'o' },
+ { "no-trace", no_argument, NULL, 't' },
+ { "version", no_argument, NULL, 'v' },
+ { 0, 0, 0, 0 }
+ };
+
+
+ /* parse through argv, looking for options */
+ while (1)
+ {
+ opt = getopt_long (argc, argv, "c:f:hotv", options, NULL);
+
+ if (opt == EOF) break;
+
+ switch (opt)
+ {
+ case 'c':
+ calls = strtol (optarg, NULL, 0);
+ if (calls < 1 || calls > 65536)
+ {
+ fprintf (stderr,
+ "%s: number of calls must be in the range 1-65535\n",
+ pname);
+ exit (EXIT_FAILURE);
+ }
+ break;
+ case 'f':
+ free_percent = (int)strtol (optarg, NULL, 0);
+ if (free_percent < 1 || free_percent > 100)
+ {
+ fprintf (stderr,
+ "%s: free value must be in the range 1-100\n",
+ pname);
+ exit (EXIT_FAILURE);
+ }
+ break;
+ case 'h':
+ print_help ();
+ exit (EXIT_SUCCESS);
+ case 'o':
+ output = 0;
+ break;
+ case 't':
+ trace = 0;
+ break;
+ case 'v':
+ print_version ();
+ exit (EXIT_SUCCESS);
+ case '?':
+ fprintf (stderr, "%s: unknown option character `%c'\n", pname,
+ optopt);
+ exit (EXIT_FAILURE);
+ default:
+ fprintf (stderr,
+ "%s: ?? getopt returned character code 0x%x (%c) ??\n",
+ pname, opt, opt);
+ exit (EXIT_FAILURE);
+ }
+ }
+
+
+ signal (SIGSEGV, segv_handler);
+
+ srand (time (NULL));
+
+ if (trace)
+ memory_trace = 1;
+
+ for (k = 0; k < calls; k++)
+ {
+ if (got_segv)
+ {
+ mem_trace ();
+ abort ();
+ }
+
+ block_size = RANDOM_BLOCK_SIZE;
+
+ /* a 1:MAX_TEST_SIZE chance of allocating more
+ than the size of a sys chunk */
+ if (block_size == MAX_TEST_SIZE / 2) block_size = 8192;
+
+ some_memory = xmalloc (block_size);
+
+ if (output)
+ printf ("%d: alloc'ed %d bytes, got addr %p\n", k, block_size,
+ some_memory);
+
+ memset (some_memory, 0xFF, block_size);
+
+ /* maybe we'll free it, maybe not */
+ if (rand () < (unsigned long)RAND_MAX /100 * free_percent)
+ {
+ xfree (some_memory);
+ if (output)
+ printf (" --> freed it\n");
+ }
+ }
+
+ fflush (stdout);
+ if (trace)
+ mem_trace ();
+
+ free_all ();
+
+ printf ("memtest OK\n");
+
+ return (0);
+}
diff --git a/decomp/test/movlps.S b/decomp/test/movlps.S
new file mode 100644
index 0000000..be20631
--- /dev/null
+++ b/decomp/test/movlps.S
@@ -0,0 +1,18 @@
+ # movlps.S
+ # trying to find out the opcodes for movlps and movhlps
+
+ .intel_syntax noprefix
+
+ .data
+foo: .quad 0
+
+ .text
+ .global _start
+_start:
+ .code16
+ int 3
+ movlps xmm0, foo # should be 0f12??mem
+ int 3
+ movhlps xmm0, xmm1 # should be 0f12??
+ int 3
+ \ No newline at end of file
diff --git a/decomp/test/movtest1.S b/decomp/test/movtest1.S
new file mode 100644
index 0000000..2652722
--- /dev/null
+++ b/decomp/test/movtest1.S
@@ -0,0 +1,10 @@
+ # movtest1.S
+ # check the generated code when using MOV with a relative offset
+
+ .intel_syntax noprefix
+
+ .text
+ .global _start
+_start:
+ mov eax, [0x1234]
+ \ No newline at end of file
diff --git a/decomp/test/prefetch.S b/decomp/test/prefetch.S
new file mode 100644
index 0000000..b20e169
--- /dev/null
+++ b/decomp/test/prefetch.S
@@ -0,0 +1,18 @@
+ # prefetch.S
+ # see what the output of the prefetch insn is
+
+ .intel_syntax noprefix
+ .data
+
+foo: .string "foo"
+
+ .text
+ .global _start
+_start:
+ int 3
+ prefetcht0 foo
+ int 3
+ mov ecx, foo
+ prefetcht0 [ecx]
+ int 3
+ \ No newline at end of file
diff --git a/decomp/test/regsize.S b/decomp/test/regsize.S
new file mode 100644
index 0000000..3d851f0
--- /dev/null
+++ b/decomp/test/regsize.S
@@ -0,0 +1,12 @@
+ # regsize.S
+ # use a 16 bit register in a 32 bit environment
+
+ .intel_syntax noprefix
+
+ .text
+ .global _start
+_start:
+ int 3
+ mov ax, 20
+ int 3
+ \ No newline at end of file
diff --git a/decomp/test/testfoo.c b/decomp/test/testfoo.c
new file mode 100644
index 0000000..ec8775b
--- /dev/null
+++ b/decomp/test/testfoo.c
@@ -0,0 +1,30 @@
+/* testfoo.c
+ * test the foo library
+ *
+ * compile with:
+ * gcc -Wall -O2 -g -lfoo -o testfoo testfoo.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void text_number (char *, unsigned long);
+
+int
+main (void)
+{
+ char buffer[256];
+ unsigned long number;
+
+ while (1)
+ {
+ fgets (buffer, 256, stdin);
+ number = strtoul (buffer, NULL, 0);
+
+ memset (buffer, 0, 256);
+ text_number (buffer, number);
+ }
+
+ return (0);
+}
diff --git a/decomp/test/ud.S b/decomp/test/ud.S
new file mode 100644
index 0000000..3cf4221
--- /dev/null
+++ b/decomp/test/ud.S
@@ -0,0 +1,13 @@
+ # ud.S
+ # see what happens with a UD2 instruction
+
+ .intel_syntax noprefix
+
+ .text
+ .global _start
+_start:
+ ud2
+ mov ebx, 0
+ mov eax, 1
+ int 0x80
+ \ No newline at end of file
diff --git a/defwrite/README b/defwrite/README
new file mode 100644
index 0000000..f8521df
--- /dev/null
+++ b/defwrite/README
@@ -0,0 +1,3 @@
+DEFwrite is a user-friendly interface for creating m-files suitable
+for use with one of Matlab's ODE solvers. It's a pretty powerful tool,
+and I highly recommend it to anyone using the ODE solvers.
diff --git a/defwrite/defwrite.m b/defwrite/defwrite.m
new file mode 100755
index 0000000..836ed8b
--- /dev/null
+++ b/defwrite/defwrite.m
@@ -0,0 +1,1868 @@
+function varargout = defwrite(varargin)
+%DEFWRITE ODE file writer.
+% DEFWRITE is a GUI designed to simplify writing ODE files
+%
+% See also ODEFILE and
+% ode solvers: ODE45, ODE23, ODE113, ODE15S, ODE23S, ODE23T, ODE23TB
+% options handling: ODESET, ODEGET
+% output functions: ODEPLOT, ODEPHAS2, ODEPHAS3, ODEPRINT
+% odefile examples: ORBITODE, ORBT2ODE, RIGIDODE, VDPODE
+
+% 1997, Jonathan duSaint
+
+if nargin==0
+ status='init';
+ state = get(0,'ShowHiddenHandles');
+ set(0,'ShowHiddenHandles','On')
+ k=findobj(get(0,'Children'),'Tag','defwrite');
+ set(0,'ShowHiddenHandles',state)
+ if ~isempty(k)
+ figure(k);
+ return
+ end
+else
+ status=varargin{1};
+end
+
+%Set up figure defaults
+figs.NumberTitle = 'Off';
+figs.MenuBar = 'None';
+figs.Units = 'Pixels';
+figs.Color = get(0,'DefaultUIControlBackgroundColor');
+
+%Set up frame default values
+frame.Style = 'Frame';
+frame.BackgroundColor = figs.Color;
+frame.Units = 'Normalized';
+
+%Set up button default values
+button.Style = 'Push';
+button.BackgroundColor = figs.Color;
+button.Units = 'Normalized';
+
+%Set up text box values
+bgtext.Style = 'Text';
+bgtext.BackgroundColor = figs.Color;
+bgtext.Units = 'Normalized';
+
+%Set up the edit boxes
+edbox.Style = 'Edit';
+edbox.BackgroundColor = [1 1 1];
+edbox.Units = 'Normalized';
+edbox.HorizontalAlignment = 'Left';
+
+%Set up the listboxes
+lbox.Style = 'ListBox';
+lbox.BackgroundColor = [1 1 1];
+lbox.Units = 'Normalized';
+
+%Only used for titles
+%ttext.FontWeight = 'demi';
+ttext.HorizontalAlignment = 'Center';
+
+switch status
+case 'init'
+ %first, size and create the figure window
+ k = get(0,'ScreenSize');
+ k(1) = .5*(k(3)-455);
+ k(2) = .5*(k(4)-255);
+ fsize = [k(1) k(2) 455 255];
+
+ Hf = figure(figs,...
+ 'UserData',sum(clock),...
+ 'IntegerHandle','Off',...
+ 'Tag','defwrite',...
+ 'Name','ODE File Writer',...
+ 'Position',fsize,...
+ 'CloseRequestFcn','defwrite CloseReq');
+
+ %The menus
+
+ Hmenf = uimenu('Label','&File');
+
+ fmenu.Parent = Hmenf;
+
+ Hmenf1 = uimenu(fmenu,...
+ 'Label','&Proceed',...
+ 'Callback','defwrite(''proceed'')');
+ Hmenf2 = uimenu(fmenu,...
+ 'Label','Previe&w File',...
+ 'Callback','defwrite(''preview'')');
+ Hmenf3 = uimenu(fmenu,...
+ 'Tag','ViewFile',...
+ 'Label','&View Output',...
+ 'Callback','defwrite(''ViewOutFile'')',...
+ 'Enable','Off');
+ Hmenf4 = uimenu(fmenu,...
+ 'Label','&Reset Values',...
+ 'Callback','defwrite(''reset'')',...
+ 'Separator','On');
+ Hmenf5 = uimenu(fmenu,...
+ 'Label','&Quit',...
+ 'Callback','close(gcf)');
+
+ Hmens = uimenu('Label','&Solvers');
+
+ smenu.Parent = Hmens;
+ smenu.Enable = 'Off';
+ smenu.Tag = 'SolverMenu';
+
+ Hms1 = uimenu(smenu,...
+ 'Label','ode113',...
+ 'Callback','defwrite(''solve'',''ode113'')');
+ Hms2 = uimenu(smenu,...
+ 'Label','ode15s',...
+ 'Callback','defwrite(''solve'',''ode15s'')');
+ Hms3 = uimenu(smenu,...
+ 'Label','ode23',...
+ 'Callback','defwrite(''solve'',''ode23'')');
+ Hms4 = uimenu(smenu,...
+ 'Label','ode23s',...
+ 'Callback','defwrite(''solve'',''ode23s'')');
+ Hms5 = uimenu(smenu,...
+ 'Label','ode23tb',...
+ 'Callback','defwrite(''solve'',''ode23tb'')');
+ Hms6 = uimenu(smenu,...
+ 'Label','ode23t',...
+ 'Callback','defwrite(''solve'',''ode23t'')');
+ Hms7 = uimenu(smenu,...
+ 'Label','ode45',...
+ 'Callback','defwrite(''solve'',''ode45'')');
+ Hms8 = uimenu(smenu,...
+ 'Tag','wizard',...
+ 'Label','Open Wizard...',...
+ 'Separator','On',...
+ 'Callback','odesolw(get(findobj(''Tag'',''filename''),''String''))');
+
+ %This is a structure of default values
+ optstruct.AbsTol = 1e-6;
+ optstruct.BDF = 'off';
+ optstruct.InitialStep = [];
+ optstruct.MaxOrder = 5;
+ optstruct.MaxStep = [];
+ optstruct.OutputFcn = '';
+ optstruct.OutputSel = '';
+ optstruct.Refine = [];
+ optstruct.RelTol = 1e-3;
+ optstruct.Stats = 'off';
+ optstruct.Vectorized = 'off';
+ optstruct.Comments = 'off';
+ optstruct.NormControl = 'off';
+ optstruct.OldStyle = 'off';
+
+ Hmeno = uimenu('Label','&Options',...
+ 'Tag','OptMenu',...
+ 'UserData',optstruct);
+
+ omenu.Parent = Hmeno;
+ omenu.Checked='Off';
+
+ Hmo1 = uimenu(omenu,...
+ 'Label','RelTol',...
+ 'Callback','defwrite(''options'',''setreltol'')');
+ Hmo2 = uimenu(omenu,...
+ 'Label','AbsTol',...
+ 'Callback','defwrite(''options'',''setabstol'')');
+ Hmo3 = uimenu(omenu,...
+ 'Label','OutputFcn');
+ Hmo3a = uimenu('Parent',Hmo3,...
+ 'Tag','Hmo3a',...
+ 'Label','Default (None)',...
+ 'Checked','On',...
+ 'Callback',['set(findobj(''Tag'',''Hmo3a''),''Checked'',''On''); ',...
+ 'set(findobj(''Tag'',''Hmo3b''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3c''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3d''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''Off''); ',...
+ 'defwrite(''options'',''nameoutputfcn'',''none'')']);
+ Hmo3b = uimenu('Parent',Hmo3,...
+ 'Tag','Hmo3b',...
+ 'Label','ODEPLOT',...
+ 'Callback',['set(findobj(''Tag'',''Hmo3a''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3b''),''Checked'',''On''); ',...
+ 'set(findobj(''Tag'',''Hmo3c''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3d''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''Off''); ',...
+ 'defwrite(''options'',''nameoutputfcn'',''odeplot'')']);
+ Hmo3c = uimenu('Parent',Hmo3,...
+ 'Tag','Hmo3c',...
+ 'Label','ODEPHAS2',...
+ 'Enable','Off',...
+ 'Callback',['set(findobj(''Tag'',''Hmo3a''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3b''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3c''),''Checked'',''On''); ',...
+ 'set(findobj(''Tag'',''Hmo3d''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''Off''); ',...
+ 'defwrite(''options'',''nameoutputfcn'',''odephas2'')']);
+ Hmo3d = uimenu('Parent',Hmo3,...
+ 'Tag','Hmo3d',...
+ 'Label','ODEPHAS3',...
+ 'Enable','Off',...
+ 'Callback',['set(findobj(''Tag'',''Hmo3a''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3b''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3c''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3d''),''Checked'',''On''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''Off''); ',...
+ 'defwrite(''options'',''nameoutputfcn'',''odephas3'')']);
+ Hmo3e = uimenu('Parent',Hmo3,...
+ 'Tag','Hmo3e',...
+ 'Label','ODEPRINT',...
+ 'Callback',['set(findobj(''Tag'',''Hmo3a''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3b''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3c''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3d''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''On''); ',...
+ 'set(findobj(''Tag'',''Hmo3f''),''Checked'',''Off''); ',...
+ 'defwrite(''options'',''nameoutputfcn'',''odeprint'')']);
+ Hmo3f = uimenu('Parent',Hmo3,...
+ 'Tag','Hmo3f',...
+ 'Label','Other...',...
+ 'Callback',['set(findobj(''Tag'',''Hmo3a''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3b''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3c''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3d''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3e''),''Checked'',''Off''); ',...
+ 'set(findobj(''Tag'',''Hmo3f''),''Checked'',''On''); ',...
+ 'defwrite(''options'',''nameoutputfcn'',''other'')']);
+ Hmo4 = uimenu(omenu,...
+ 'Label','OutputSel',...
+ 'Callback','defwrite(''options'',''outputselvec'')');
+ Hmo5 = uimenu(omenu,...
+ 'Label','Refine',...
+ 'Callback','defwrite(''options'',''refinenum'')');
+ Hmo6 = uimenu(omenu,...
+ 'Label','Stats');
+ Hmo6a = uimenu('Parent',Hmo6,...
+ 'Tag','hmo6a',...
+ 'Label','On',...
+ 'Callback',['defwrite(''options'',''Stats'',''on''), ',...
+ 'set(findobj(''Tag'',''hmo6a''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo6b''),''Checked'',''Off'')']);
+ Hmo6b = uimenu('Parent',Hmo6,...
+ 'Checked','On',...
+ 'Tag','hmo6b',...
+ 'Label','Off',...
+ 'Callback',['defwrite(''options'',''Stats'',''off''), ',...
+ 'set(findobj(''Tag'',''hmo6b''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo6a''),''Checked'',''Off'')']);
+ Hmo7 = uimenu(omenu,...
+ 'Label','NormControl');
+ Hmo7a = uimenu('Parent',Hmo7,...
+ 'Tag','hmo7a',...
+ 'Label','On',...
+ 'Callback',['defwrite(''options'',''NormControl'',''on''), ',...
+ 'set(findobj(''Tag'',''hmo7a''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo7b''),''Checked'',''Off'')']);
+ Hmo7b = uimenu('Parent',Hmo7,...
+ 'Checked','On',...
+ 'Tag','hmo7b',...
+ 'Label','Off',...
+ 'Callback',['defwrite(''options'',''NormControl'',''off''), ',...
+ 'set(findobj(''Tag'',''hmo7b''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo7a''),''Checked'',''Off'')']);
+ Hmo8 = uimenu(omenu,...
+ 'Label','InitialStep',...
+ 'Callback','defwrite(''options'',''initstep'')');
+ Hmo9 = uimenu(omenu,...
+ 'Label','MaxStep',...
+ 'Callback','defwrite(''options'',''maxstep'')');
+ Hmo10 = uimenu(omenu,...
+ 'Label','Vectorized');
+ Hmo10a = uimenu('Parent',Hmo10,...
+ 'Tag','hmo10a',...
+ 'Label','On',...
+ 'Callback',['defwrite(''options'',''Vectorized'',''on''), ',...
+ 'set(findobj(''Tag'',''hmo10a''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo10b''),''Checked'',''Off'')']);
+ Hmo10b = uimenu('Parent',Hmo10,...
+ 'Checked','On',...
+ 'Tag','hmo10b',...
+ 'Label','Off',...
+ 'Callback',['defwrite(''options'',''Vectorized'',''off''), ',...
+ 'set(findobj(''Tag'',''hmo10b''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo10a''),''Checked'',''Off'')']);
+ Hmo11 = uimenu(omenu,...
+ 'Separator','On',...
+ 'Label','Maxorder');
+ Hmo11a = uimenu('Parent',Hmo11,...
+ 'Tag','hmo11a',...
+ 'Label','1',...
+ 'Callback',['defwrite(''options'',''MaxOrder'',1), ',...
+ 'set(findobj(''Tag'',''hmo11a''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo11b''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11c''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11d''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11e''),''Checked'',''Off'')']);
+ Hmo11b = uimenu('Parent',Hmo11,...
+ 'Tag','hmo11b',...
+ 'Label','2',...
+ 'Callback',['defwrite(''options'',''MaxOrder'',2), ',...
+ 'set(findobj(''Tag'',''hmo11a''),''Checked'',''Off''), ',...
+ 'set(findobj(''Tag'',''hmo11b''),''Checked'',''On''),',...
+ 'set(findobj(''Tag'',''hmo11c''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11d''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11e''),''Checked'',''Off'')']);
+ Hmo11c = uimenu('Parent',Hmo11,...
+ 'Tag','hmo11c',...
+ 'Label','3',...
+ 'Callback',['defwrite(''options'',''MaxOrder'',3), ',...
+ 'set(findobj(''Tag'',''hmo11a''),''Checked'',''Off''), ',...
+ 'set(findobj(''Tag'',''hmo11b''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11c''),''Checked'',''On''),',...
+ 'set(findobj(''Tag'',''hmo11d''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11e''),''Checked'',''Off'')']);
+ Hmo11d = uimenu('Parent',Hmo11,...
+ 'Tag','hmo11d',...
+ 'Label','4',...
+ 'Callback',['defwrite(''options'',''MaxOrder'',4), ',...
+ 'set(findobj(''Tag'',''hmo11a''),''Checked'',''Off''), ',...
+ 'set(findobj(''Tag'',''hmo11b''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11c''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11d''),''Checked'',''On''),',...
+ 'set(findobj(''Tag'',''hmo11e''),''Checked'',''Off'')']);
+ Hmo11e = uimenu('Parent',Hmo11,...
+ 'Tag','hmo11e',...
+ 'Label','5',...
+ 'Checked','On',...
+ 'Callback',['defwrite(''options'',''MaxOrder'',5), ',...
+ 'set(findobj(''Tag'',''hmo11a''),''Checked'',''Off''), ',...
+ 'set(findobj(''Tag'',''hmo11b''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11c''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11d''),''Checked'',''Off''),',...
+ 'set(findobj(''Tag'',''hmo11e''),''Checked'',''On'')']);
+ Hmo12 = uimenu(omenu,...
+ 'Label','BDF');
+ Hmo12a = uimenu('Parent',Hmo12,...
+ 'Tag','hmo12a',...
+ 'Label','On',...
+ 'Callback',['defwrite(''options'',''BDF'',''on''), ',...
+ 'set(findobj(''Tag'',''hmo12a''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo12b''),''Checked'',''Off'')']);
+ Hmo12b = uimenu('Parent',Hmo12,...
+ 'Tag','hmo12b',...
+ 'Checked','On',...
+ 'Label','Off',...
+ 'Callback',['defwrite(''options'',''BDF'',''off''), ',...
+ 'set(findobj(''Tag'',''hmo12b''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo12a''),''Checked'',''Off'')']);
+ Hmo13 = uimenu(omenu,...
+ 'Tag','comments',...
+ 'UserData',{''},...
+ 'Separator','On',...
+ 'Label','Add Help Text',...
+ 'Callback','defwrite(''AddHelpText'')');
+ Hmo14 = uimenu(omenu,...
+ 'Label','Comments');
+ Hmo14a = uimenu('Parent',Hmo14,...
+ 'Tag','hmo14a',...
+ 'Label','On',...
+ 'Callback',['defwrite(''options'',''Comments'',''on''), ',...
+ 'set(findobj(''Tag'',''hmo14a''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo14b''),''Checked'',''Off'')']);
+ Hmo14b = uimenu('Parent',Hmo14,...
+ 'Tag','hmo14b',...
+ 'Checked','On',...
+ 'Label','Off',...
+ 'Callback',['defwrite(''options'',''Comments'',''off''), ',...
+ 'set(findobj(''Tag'',''hmo14b''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''hmo14a''),''Checked'',''Off'')']);
+ Hmo15 = uimenu(omenu,...
+ 'Separator','On',...
+ 'Label','Compatability');
+ Hmo15a = uimenu('Parent',Hmo15,...
+ 'Tag','CompOn',...
+ 'Label','On',...
+ 'Callback',['defwrite(''options'',''OldStyle'',''on''), ',...
+ 'set(findobj(''Tag'',''CompOn''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''CompOff''),''Checked'',''Off'')']);
+ Hmo15b = uimenu('Parent',Hmo15,...
+ 'Tag','CompOff',...
+ 'Checked','On',...
+ 'Label','Off',...
+ 'Callback',['defwrite(''options'',''OldStyle'',''off''), ',...
+ 'set(findobj(''Tag'',''CompOff''),''Checked'',''On''), ',...
+ 'set(findobj(''Tag'',''CompOn''),''Checked'',''Off'')']);
+
+ Hmenh = uimenu('Label','&Help');
+ hmenu.Parent = Hmenh;
+
+ Hmh1 = uimenu(hmenu,...
+ 'Label','Contents',...
+ 'Callback','defwrite(''ContentsHelp'')');
+ Hmh2 = uimenu(hmenu,...
+ 'Label','Related Topics',...
+ 'Callback','defwrite(''RelatedHelp'')');
+ Hmh3 = uimenu(hmenu,...
+ 'Label','About',...
+ 'Separator','On',...
+ 'Callback','defwrite(''AboutHelp'')');
+
+
+ %The frames
+ Hfr1 = uicontrol(frame,...
+ 'Position',[5/455 80/255 220/455 170/255]);
+ Hfr2 = uicontrol(frame,...
+ 'Position',[230/455 160/255 220/455 90/255]);
+ Hfr3 = uicontrol(frame,...
+ 'Position',[230/455 5/255 220/455 150/255]);
+
+ %The image data
+ load defwrite.mat
+
+ %The four "main" buttons
+ Hbqt=uicontrol(button,...
+ 'Position',[5/455 5/255 (220-5)/2/455 (70-5)/2/255],...
+ 'CData',qpic,...
+ 'Callback','close(gcf)',...
+ 'TooltipString','Quits DEFWRITE');
+ Hbgo=uicontrol(button,...
+ 'Position',[5/455 10/255+(70-5)/2/255 (220-5)/2/455 (70-5)/2/255],...
+ 'CData',procpic,...
+ 'Callback','defwrite(''proceed'')',...
+ 'TooltipString','Create file');
+ Hbrv=uicontrol(button,...
+ 'Position',[10/455+(220-5)/2/455 10/255+(70-5)/2/255 (220-5)/2/455 (70-5)/2/255],...
+ 'CData',respic,...
+ 'Callback','defwrite(''reset'')',...
+ 'TooltipString','Clear all values');
+ Hbview=uicontrol(button,...
+ 'Tag','ViewFile',...
+ 'Position',[10/455+(220-5)/2/455 5/255 (220-5)/2/455 (70-5)/2/255],...
+ 'CData',viewpic,...
+ 'Enable','off',...
+ 'Callback','defwrite(''ViewOutFile'')',...
+ 'TooltipString','View output file in the editor');
+
+ %Titles
+ Ht1 = uicontrol(bgtext,ttext,...
+ 'Position',[20/455 225/255 190/455 20/255],...
+ 'String','Equation(s)');
+ Ht2 = uicontrol(bgtext,ttext,...
+ 'Position',[245/455 225/255 190/455 20/255],...
+ 'String','File Name & Path');
+ Ht3 = uicontrol(bgtext,ttext,...
+ 'Position',[245/455 130/255 190/455 20/255],...
+ 'String','Default Values and Parameters');
+
+ %Now for the individual areas
+
+ %Equation area
+ Htiv = uicontrol(bgtext,...
+ 'Position',[15/455 200/255 125/455 20/255],...
+ 'String','Indep. Variable:');
+ Heiv = uicontrol(edbox,...
+ 'Tag','indepvar',...
+ 'Position',[140/455 200/255 75/455 20/255],...
+ 'UserData','resetdlg');
+ Hleq = uicontrol(lbox,...
+ 'Position',[10/455 110/255 210/455 80/255],...
+ 'Tag','eqbox',...
+ 'UserData','resetdlg',...
+ 'Callback','defwrite(''checkEqList'')');
+ Hbadd = uicontrol(button,...
+ 'Position',[10/455 85/255 200/3/455 20/255],...
+ 'String','Add',...
+ 'Callback','defwrite(''AddEquation'')',...
+ 'TooltipString','Add equation to list');
+ Hbedit = uicontrol(button,...
+ 'Tag','Eqbutton',...
+ 'Position',[(15+200/3)/455 85/255 200/3/455 20/255],...
+ 'String','Edit',...
+ 'Enable','Off',...
+ 'Callback','defwrite(''EditEquation'')',...
+ 'TooltipString','Edits selected equation');
+ Hbdel = uicontrol(button,...
+ 'Tag','Eqbutton',...
+ 'Position',[(20+2*200/3)/455 85/255 200/3/455 20/255],...
+ 'String','Delete',...
+ 'Enable','Off',...
+ 'Callback','defwrite(''DelEquation'')',...
+ 'TooltipString','Deletes selected equation');
+
+ %File name and path area
+ Htfn = uicontrol(bgtext,...
+ 'Position',[240/455 200/255 40/455 20/255],...
+ 'String','Name:');
+ Htpth = uicontrol(bgtext,...
+ 'Position',[240/455 170/255 40/455 20/255],...
+ 'String','Path:');
+ Hefn = uicontrol(edbox,...
+ 'Tag','filename',...
+ 'UserData','resetdlg',...
+ 'Position',[280/455 200/255 160/455 20/255]);
+ Hepth = uicontrol(edbox,...
+ 'Tag','storepath',...
+ 'Position',[280/455 170/255 105/455 20/255],...
+ 'String',pwd);
+ Hbcpth = uicontrol(button,...
+ 'Position',[390/455 170/255 50/455 20/255],...
+ 'String','Change',...
+ 'Callback','defwrite(''ChangeDir'')',...
+ 'TooltipSTring','Change destination directory');
+
+ %Default value area
+ Httspn = uicontrol(bgtext,...
+ 'Position',[240/455 110/255 40/455 20/255],...
+ 'String','Tspan:');
+ Htto = uicontrol(bgtext,...
+ 'Position',[350/455 110/255 20/455 20/255],...
+ 'String','to');
+ Het0 = uicontrol(edbox,...
+ 'Tag','t0',...
+ 'UserData','resetdlg',...
+ 'Position',[280/455 110/255 70/455 20/255]);
+ Hetf = uicontrol(edbox,...
+ 'Tag','tf',...
+ 'UserData','resetdlg',...
+ 'Position',[370/455 110/255 70/455 20/255]);
+ Htic = uicontrol(bgtext,ttext,...
+ 'Position',[235/455 90/255 100/455 18/255],...
+ 'String','Initial Conditions');
+ Htpar = uicontrol(bgtext,ttext,...
+ 'Position',[340/455 90/255 100/455 18/255],...
+ 'String','Parameters');
+ Hlic = uicontrol(lbox,...
+ 'Tag','init',...
+ 'UserData','resetdlg',...
+ 'Position',[235/455 35/255 100/455 55/255],...
+ 'Callback','defwrite(''checkInit'')');
+ Hbmic = uicontrol(button,...
+ 'Tag','Eqbutton',...
+ 'Position',[235/455 10/255 100/455 20/255],...
+ 'String','Modify',...
+ 'Callback','defwrite ModifyInit',...
+ 'Enable','Off',...
+ 'TooltipString','Add or edit selected initial condition');
+ Hlpar = uicontrol(lbox,...
+ 'Tag','pars',...
+ 'UserData','resetdlg',...
+ 'Position',[340/455 35/255 100/455 55/255],...
+ 'Callback','defwrite(''checkPars'')');
+ Hbnpar = uicontrol(button,...
+ 'Position',[340/455 10/255 47.5/455 20/255],...
+ 'String','New',...
+ 'Callback','defwrite NewPar',...
+ 'TooltipString','Add new parameter to list');
+ Hbepar = uicontrol(button,...
+ 'Tag','editpar',...
+ 'Position',[392.5/455 10/255 47.5/455 20/255],...
+ 'String','Edit',...
+ 'Enable','Off',...
+ 'Callback','defwrite EditPar',...
+ 'TooltipString','Edit or delete existing parameter');
+
+ %Prevent user from damaging the interface
+ set(findobj('Tag','defwrite'),'HandleVisibility','Callback')
+case 'CloseReq'
+ %If a file hasn't been written, verify choice
+ oktoquit = get(findobj('Tag','ViewFile'),'Enable');
+ if strcmp(lower(oktoquit{1}),'off')
+ Choice = questdlg('Are you sure you want to quit?',...
+ 'No file was written','Yes','No','No');
+ if strcmp(Choice,'No')
+ return
+ end
+ end
+
+ delete(findobj('Tag','defwrite'))
+case 'reset'
+ %Get handles of objects to clear
+ Handles = findobj('UserData','resetdlg');
+
+ %Clear them
+ set(Handles,'String','');
+
+ %Get handles of objects to disable
+ Handles = findobj('Tag','Eqbutton');
+ Handles2 = findobj('Tag','editpar');
+
+ %Clear them
+ set(Handles,'Enable','Off')
+ set(Handles2,'Enable','Off')
+
+ %Clear comments
+ set(findobj('Tag','comments'),'UserData',{''})
+
+ %Reset options
+ optstruct.AbsTol = 1e-6;
+ optstruct.BDF = 'off';
+ optstruct.InitialStep = [];
+ optstruct.MaxOrder = 5;
+ optstruct.MaxStep = [];
+ optstruct.OutputFcn = '';
+ optstruct.OutputSel = '';
+ optstruct.Refine = [];
+ optstruct.RelTol = 1e-3;
+ optstruct.Stats = 'off';
+ optstruct.Vectorized = 'off';
+ optstruct.Comments = 'off';
+ optstruct.NormControl = 'off';
+ optstruct.OldStyle = 'off';
+
+ set(findobj('Tag','OptMenu'),'UserData',optstruct)
+
+ %Reset checks
+ OnHandles = findobj('Label','Off');
+ OffHandles = findobj('Label','On');
+
+ set(OnHandles,'Checked','On')
+ set(OffHandles,'Checked','Off')
+
+ OffHandles = [findobj('Tag','hmo11a'); findobj('Tag','hmo11b');...
+ findobj('Tag','hmo11c'); findobj('Tag','hmo11d')];
+
+ set(OffHandles,'Checked','Off')
+ set(findobj('Tag','hmo11e'),'Checked','On')
+
+ %Make sure that "View Output" & solver menu are disabled
+ set(findobj('Tag','ViewFile'),'Enable','Off')
+ set(findobj('Tag','SolverMenu'),'Enable','Off')
+ set(findobj('Tag','wizard'),'Enable','Off')
+case 'checkEqList'
+ %Check for a double click
+ ptime = get(findobj('Tag','defwrite'),'UserData');
+ ntime = sum(clock);
+ set(findobj('Tag','defwrite'),'UserData',ntime)
+
+ if isempty(get(findobj('Tag','eqbox'),'String'))
+ defwrite('AddEquation')
+ elseif ntime-ptime < .2
+ defwrite('EditEquation')
+ end
+case 'checkInit'
+ %Check for a double click
+ ptime = get(findobj('Tag','defwrite'),'UserData');
+ ntime = sum(clock);
+ set(findobj('Tag','defwrite'),'UserData',ntime)
+
+ if ntime-ptime < .2 & ~isempty(get(findobj('Tag','eqbox'),'String'))
+ defwrite('ModifyInit')
+ end
+case 'checkPars'
+ %Check for a double click
+ ptime = get(findobj('Tag','defwrite'),'UserData');
+ ntime = sum(clock);
+ set(findobj('Tag','defwrite'),'UserData',ntime)
+
+ if isempty(get(findobj('Tag','pars'),'String'))
+ defwrite('NewPar')
+ elseif ntime-ptime < .2
+ defwrite('EditPar')
+ end
+case 'AddEquation'
+
+ %Get the old equation string
+ Hbox = findobj('Tag','eqbox');
+ OldEqs = get(Hbox,'String');
+
+ %Call draweqdlg with no input equation
+ [Eq, Msg] = draweqdlg('',bgtext,edbox,button);
+
+ %Check whether user pressed Cancel
+ if ~Msg
+ return
+ end
+
+ %Put the dependent variables in the proper place
+ DepVar = strtok(Eq, '''=');
+ DepVarStr = get(findobj('Tag', 'init'), 'String');
+ DepVarStr = strvcat(DepVarStr, [ DepVar '(t0) =']);
+ set(findobj('Tag', 'init'), 'String', DepVarStr)
+
+ %Enable Edit and Delete
+ set(findobj('Tag','Eqbutton'),'Enable','On')
+
+
+ %Add the new equation to the old
+ if isempty(OldEqs)
+ OldEqs = Eq;
+ else
+ [r c] = size(OldEqs);
+ OldEqs = [OldEqs char(124*ones(r,1))];
+ OldEqs = OldEqs';
+ OldEqs = [OldEqs(:) ; Eq']';
+ end
+
+ %The code to find parameters
+ %Not yet implemented
+
+ if length(find(OldEqs == '|')) == 1
+ set(findobj('Tag','Hmo3c'),'Enable','On')
+ elseif length(find(OldEqs == '|')) > 1
+ set(findobj('Tag','Hmo3d'),'Enable','On')
+ end
+
+ %Put equations in listbox
+ set(Hbox,'String',OldEqs);
+
+ %Set Value of both relevant listboxes
+ set(Hbox,'Value',1)
+ set(findobj('Tag', 'init'),'Value',1)
+case 'EditEquation'
+ %Get the equation number & extract the equation
+ Hbox = findobj('Tag','eqbox');
+ EqNum = get(Hbox,'Value');
+ EqStr = get(Hbox,'String');
+ EdEq = deblank(EqStr(EqNum,:));
+
+ %Pass to draweqdlg to be edited
+ [Eq, Msg] = draweqdlg(EdEq,bgtext,edbox,button);
+
+ %Check if OK to proceed
+ if ~Msg
+ return
+ end
+
+ %Replace old dependent variable with new
+ DepVar = strtok(Eq, '''=');
+ DepList = get(findobj('Tag','init'),'String');
+ DepCell = cellstr(DepList);
+ DepCell{EqNum} = [DepVar '(t0) ='];
+ DepList = char(DepCell);
+ set(findobj('Tag', 'init'), 'String', DepList)
+
+ %Now format the strings to replace the equation
+ [Dim1 Dim2] = size(EqStr);
+ LStr = length(Eq);
+ if Dim2 > LStr
+ Eq = [Eq char(32*ones(1,Dim2-LStr))];
+ elseif Dim2 < LStr
+ EqStr = [EqStr char(32*ones(Dim1,LStr-Dim2))];
+ end
+ EqStr(EqNum,:) = Eq;
+
+ if isempty(EqStr)
+ set(findobj('Tag','Eqbutton'),'Enable','Off')
+ end
+
+ %And return the value to the listbox
+ set(Hbox,'String',EqStr)
+
+ %Set Value of both relevant listboxes
+ set(Hbox,'Value',1)
+ set(findobj('Tag', 'init'),'Value',1)
+case 'DelEquation'
+ %Get the number of the equation to delete
+ Hbox = findobj('Tag','eqbox');
+ EqNum = get(Hbox,'Value');
+ EqStr = get(Hbox,'String');
+
+ %Find the name of the dependent variable
+ Eq = EqStr(EqNum,:);
+ [T, R] = strtok(Eq,'''=');
+
+ %Delete the variable from the list
+ DepList = get(findobj('Tag','init'),'String');
+ DepList(EqNum,:) = '';
+
+ set(findobj('Tag','init'),'String',DepList)
+
+ %Now delete the equation
+ EqStr(EqNum,:) = [];
+
+ %If the string is empty, set the Enable of Delete, Edit and Initial Values to off
+ if isempty(EqStr)
+ set(findobj('Tag','Eqbutton'),'Enable','Off')
+ end
+
+ if size(EqStr,1) < 2
+ set(findobj('Tag','Hmo3c'),'Enable','Off')
+ elseif size(EqStr,1) < 3
+ set(findobj('Tag','Hmo3d'),'Enable','Off')
+ end
+
+ %Put the new equation list back and set the Value to 1
+ set(Hbox,'String',EqStr)
+ set(Hbox,'Value',1)
+ set(findobj('Tag', 'init'),'Value',1)
+case 'ViewOutFile'
+ fname = get(findobj('Tag','filename'),'String');
+ pth = get(findobj('Tag','storepath'),'String');
+
+ if isempty(fname)
+ H = errordlg('No File Name Specified','DEFWRITE Error','replace');
+ return
+ end
+
+ if isempty(pth)
+ H = errordlg('No Directory Specified','DEFWRITE Error','replace');
+ return
+ end
+
+ if exist(pth,'dir') ~= 7
+ H = errordlg('Invalid Directory','DEFWRITE Error','replace');
+ return
+ end
+
+ if pth(length(pth)) ~= filesep
+ pth = [pth filesep];
+ end
+
+ if ~(fname(end) == 'm' & fname(end-1) == '.')
+ fname = [fname '.m'];
+ end
+
+ edit([pth fname])
+case 'ChangeDir'
+ fname = get(findobj('Tag','filename'),'String');
+ if isempty(fname)
+ errordlg('You must specify a filename first','DEFWRITE Error','replace');
+ return
+ end
+ cpath = get(findobj('Tag','storepath'),'String');
+
+ npath = pwd;
+ try
+ cd(cpath)
+ catch
+ set(findobj('Tag','storepath'),'String',pwd)
+ end
+
+ [fname, newpath] = uiputfile([fname '.'''],'Select Directory');
+ if all(fname) == 0
+ return
+ end
+ set(findobj('Tag','storepath'),'String',newpath)
+ cd(npath)
+case 'ModifyInit'
+ %Get string and current position
+ HBox = findobj('Tag','init');
+ DStr = get(HBox,'String');
+ Val = get(HBox,'Value');
+ DStr = cellstr(DStr);
+
+ %Extract the string to edit and edit it
+ Str = DStr{Val};
+ NewStr = drawinitbox(Str, bgtext, edbox, button);
+
+ %Put new string back in old
+ DStr{Val} = NewStr;
+ DStr = char(DStr);
+
+ %Put the string in the listbox
+ set(HBox,'String',DStr)
+case 'NewPar'
+ %get old parameter string
+ Hbox = findobj('Tag','pars');
+ Str = get(Hbox,'String');
+
+ %get new string
+ [NewPar, Msg] = drawparbox('', bgtext, edbox, button);
+
+ %return if cancel was pressed
+ if ~Msg
+ return
+ end
+
+ %Enable edit
+ set(findobj('Tag','editpar'),'Enable','On')
+
+ %Return the new string to the listbox
+ Str = strvcat(Str, NewPar);
+ set(Hbox, 'String', Str)
+case 'EditPar'
+ Hbox = findobj('Tag','pars');
+ Str = get(Hbox,'String');
+ Val = get(Hbox,'Value');
+
+ %Converting the string into a cell array makes for easier editing
+ Str = cellstr(Str);
+ EditStr = Str{Val};
+
+ [NewPar, Msg, Del] = drawparbox(EditStr, bgtext, edbox, button);
+
+ %Return if
+ if ~Msg
+ return
+ end
+
+ if Del
+ Str = char(Str);
+ Str(Val,:) = [];
+ if isempty(Str)
+ set(findobj('Tag','editpar'),'Enable','Off')
+ end
+ else
+ Str{Val} = NewPar;
+ Str = char(Str);
+ end
+
+ set(Hbox,'String',Str);
+ set(Hbox,'Value',1)
+case 'options'
+ optaction = varargin{2};
+ optstruct = get(findobj('Tag','OptMenu'),'UserData');
+
+ switch optaction
+ case 'setreltol'
+ oldval = '';
+ defval = '1e-3';
+ if ~isempty(optstruct.RelTol)
+ oldval = mat2str(optstruct.RelTol);
+ end
+ val = optionenter('RelTol',oldval,defval,button,bgtext,edbox);
+ optstruct.RelTol = str2num(val{1});
+ case 'setabstol'
+ oldval = '';
+ defval = '1e-6';
+ if ~isempty(optstruct.AbsTol)
+ oldval = mat2str(optstruct.AbsTol);
+ end
+ val = optionenter('AbsTol',oldval,defval,button,bgtext,edbox);
+ optstruct.AbsTol = str2num(val{1});
+ case 'nameoutputfcn';
+ switch varargin{3}
+ case 'other'
+ defval = '';
+ val = optionenter('OutputFcn',optstruct.OutputFcn,defval,button,bgtext,edbox);
+ optstruct.OutputFcn = val{1};
+ case 'none'
+ optstruct.OutputFcn = '';
+ otherwise
+ optstruct.OutputFcn = varargin{3};
+ end
+ case 'outputselvec'
+ defval = '';
+ val = optionenter('OutputSel',optstruct.OutputSel,defval,button,bgtext,edbox);
+ optstruct.OutputSel = val{1};
+ case 'refinenum'
+ oldval = '';
+ defval = '';
+ if ~isempty(optstruct.Refine)
+ oldval = mat2str(optstruct.Refine);
+ end
+ val = optionenter('Refine',oldval,defval,button,bgtext,edbox);
+ optstruct.Refine = str2num(val{1});
+ case 'Stats'
+ optstruct.Stats = varargin{3};
+ case 'initstep'
+ oldval = '';
+ defval = '';
+ if ~isempty(optstruct.InitialStep)
+ oldval = mat2str(optstruct.InitialStep);
+ end
+ val = optionenter('InitialStep',oldval,defval,button,bgtext,edbox);
+ optstruct.InitialStep = str2num(val{1});
+ case 'maxstep'
+ oldval = '';
+ defval = '';
+ if ~isempty(optstruct.MaxStep)
+ oldval = mat2str(optstruct.MaxStep);
+ end
+ val = optionenter('MaxStep',oldval,defval,button,bgtext,edbox);
+ optstruct.MaxStep = str2num(val{1});
+ case 'MaxOrder'
+ optstruct.MaxOrder = varargin{3};
+ case 'BDF'
+ optstruct.BDF = varargin{3};
+ case 'Vectorized'
+ optstruct.Vectorized = varargin{3};
+ case 'Comments'
+ optstruct.Comments = varargin{3};
+ case 'NormControl'
+ optstruct.NormControl = varargin{3};
+ case 'OldStyle'
+ optstruct.OldStyle = varargin{3};
+ otherwise
+ error(['Invalid input: ''', optaction, ''''])
+ end
+
+ set(findobj('Tag','OptMenu'),'UserData',optstruct)
+case 'ContentsHelp'
+ helpwin('defwrite')
+case 'RelatedHelp'
+ helpwin('odefile')
+case 'AboutHelp'
+ load defwrite.mat
+ Title = 'About DEFWRITE';
+ Message = sprintf(['DEFWRITE is a tool designed\nto simplify the process\n',...
+ 'of creating ODE Files\n 1997, Jonathan duSaint']);
+ msgbox(Message,Title,'custom',mlogo,map)
+case 'solve' %From the pulldown menu
+ solver = varargin{2};
+ fname = get(findobj('Tag','filename'),'String');
+ clear(fname)
+ if isempty(fname)
+ H = errordlg('No file is specified','DEFWRITE Error','replace');
+ else
+ figure;
+ eval(['' solver '(''' fname ''')'])
+ end
+case 'AddHelpText'
+ oldtext = get(findobj('Tag','comments'),'UserData');
+ newtext = inputdlg('Enter Text:','Help Text',5,oldtext);
+ if isempty(newtext)
+ newtext{1} = oldtext{1};
+ end
+ set(findobj('Tag','comments'),'UserData',newtext)
+case 'preview'
+ EnState = get(findobj('Tag','ViewFile'),'Enable');
+
+ [Fstr, isready] = defwrite('proceed','DoStrOnly');
+
+ set(findobj('Tag','ViewFile'),'Enable',EnState{1})
+
+ if ~isready
+ return
+ end
+
+ Fstr = strrep(Fstr,sprintf('\n\n'),sprintf('\n@@\n'));
+
+ DStr = '';
+ while ~isempty(Fstr)
+ [T, Fstr] = strtok(Fstr,sprintf('\n'));
+ if strcmp(T,'@@')
+ T = char(32*ones(1,size(Fstr,2)));
+ end
+ DStr = strvcat(DStr, T);
+ end
+
+ pos = get(findobj('Tag','defwrite'),'Position');
+ pos = pos - 20;
+ pos(3:4) = [320 300];
+
+ Hf = dialog('WindowStyle','Normal',...
+ 'Name','Preview File',...
+ 'Position',pos,...
+ 'Tag','previewer');
+ Hcb = uicontrol(button,...
+ 'String','OK',...
+ 'Position',[285/320 5/300 30/320 20/300],...
+ 'Callback','close(findobj(''Tag'',''previewer''))');
+ Hlp = uicontrol(lbox,...
+ 'Position',[5/320 30/300 310/320 260/300],...
+ 'String',DStr);
+
+case 'proceed'
+ Fig = watchon;
+ set(findobj('Tag','ViewFile'),'Enable','Off') %Don't want to view incomplete file
+
+ enableflag = 0; %Indicates whether or not to enable solver menu
+ isready = 0; %Used if in preview mode
+
+ if nargout == 2 %Defaults in case of error exit
+ varargout{1} = '';
+ varargout{2} = isready;
+ end
+
+ if nargin == 2
+ if strcmp(varargin{2},'DoStrOnly');
+ StrOutput = 1;
+ else
+ watchoff(Fig)
+ errordlg(['Invalid argument ''' varargin{2} '''.'],'DEFWRITE Error','replace');
+ return
+ end
+ else
+ StrOutput = 0;
+ end
+
+
+ %First verify the necessary input
+
+ %Independent variable
+ indep = get(findobj('Tag','indepvar'),'String');
+ if isempty(indep)
+ watchoff(Fig)
+ errordlg('You must specify an independent variable','DEFWRITE Error','replace');
+ return
+ end
+
+ %Equations
+ Eqs = get(findobj('Tag','eqbox'),'String');
+ if isempty(Eqs)
+ watchoff(Fig)
+ errordlg('The equation field is empty','DEFWRITE Error','replace');
+ return
+ end
+
+ %File name
+ fname = get(findobj('Tag','filename'),'String');
+ if isempty(fname) & ~StrOutput
+ watchoff(Fig)
+ errordlg('A file name must be specified','DEFWRITE Error','replace');
+ return
+ elseif isempty(fname) & StrOutput
+ fname = 'no name';
+ end
+ k = findstr(fname,'.m'); %don't want to call it f.m.m or write function dydt = f.m(t,y)
+ if ~isempty(k)
+ fname = fname(1:k-1);
+ end
+ if ~StrOutput
+ %Directory
+ oldpath = pwd;
+ pth = get(findobj('Tag','storepath'),'String');
+
+ if isempty(pth)
+ watchoff(Fig)
+ errordlg('No Directory Specified','DEFWRITE Error','replace');
+ return
+ end
+
+ if exist(pth,'dir') ~= 7
+ watchoff(Fig)
+ errordlg('Invalid directory','DEFWRITE Error','replace');
+ return
+ end
+
+ %Check that path and filename concatenated will form a valid name
+ if pth(end) ~= filesep
+ pth = [pth filesep];
+ end
+ end
+
+ %Time span
+ t0 = get(findobj('Tag','t0'),'String');
+ tf = get(findobj('Tag','tf'),'String');
+ if xor(isempty(t0),isempty(tf)) %If only one is filled in
+ watchoff(Fig)
+ errordlg('Only one time span box is filled in.','DEFWRITE Error','replace');
+ return
+ end
+
+ %Parameters
+ Pars = get(findobj('Tag','pars'),'String');
+ Pars = cellstr(Pars);
+ LeftPar = {};
+ RightPar = {};
+ pflag = 1; %Assume no unmatched parameters
+ if ~isempty(Pars{1})
+ for k = 1:length(Pars)
+ [L, R] = strtok(Pars{k},'=');
+ R = R(2:length(R));
+ LeftPar = [LeftPar {deblank(L)}];
+ RightPar = [RightPar {fliplr(deblank(fliplr(deblank(R))))}];
+ if isempty(deblank(fliplr(deblank(R)))) %Unmatched parameter
+ pflag = 0;
+ end
+ end
+ end
+
+ %Initial conditions
+ Init = get(findobj('Tag','init'),'String');
+ [r, c] = size(Init);
+ InitList = {};
+ for k = 1:r
+ [T, R] = strtok(Init(k,:),'=');
+ R = deblank(R);
+ if length(R) > 1 %If there is an initial condition for this dep var
+ InitList = [InitList {deblank(R(2:length(R)))}];
+ end
+ end
+ if (length(InitList) ~= r) & ~isempty(InitList) %Better have either no init or one per dep var
+ watchoff(Fig)
+ errordlg('Missing initial condition(s)','DEFWRITE Error','replace');
+ return
+ end
+
+ %Help text
+ Help = get(findobj('Tag','comments'),'UserData');
+ HelpText = Help{1};
+ [r,c] = size(HelpText);
+ HelpText = [char(37*ones(r,1)) char(32*ones(r,3)) HelpText char(10*ones(r,1))]';
+ HelpText = HelpText(:)';
+
+ if ~StrOutput
+ %Check for unique filename in pwd
+ %This is the last validation because if a file exists, it may be
+ %deleted and it's not a good idea to delete a file
+ %only to find out that a new one can't be written
+ if pth(end) == filesep
+ pth = pth(1:end-1);
+ end
+
+ W = what(pth);
+ W = char(W.m)';
+ W = (W(:))';
+ k = findstr(W,fname);
+ if ~isempty(k) %If a file "fname.m" is in the destination directory
+ Ans = questdlg(sprintf(['A file named ''' fname '.m'' exists',...
+ ' in this directory.\nWhat would you like to do?']),...
+ 'DEFWRITE Error','Overwrite','Cancel','Cancel');
+ switch Ans
+ case 'Cancel'
+ watchoff(Fig)
+ return
+ otherwise
+ delete(fullfile(pth, fname, '.m'))
+ end
+ end
+ end
+
+ %Get options
+ optstruct = get(findobj('Tag','OptMenu'),'UserData');
+ optlist = {};
+ %Find which ones were changed
+ %Kind of a tedious method
+ if optstruct.AbsTol ~= 1e-6
+ optlist = [optlist {'AbsTol' optstruct.AbsTol}];
+ end
+ if ~strcmp(optstruct.BDF,'off')
+ optlist = [optlist {'BDF' optstruct.BDF}];
+ end
+ if ~isempty(optstruct.InitialStep)
+ optlist = [optlist {'InitialStep' optstruct.InitialStep}];
+ end
+ if optstruct.MaxOrder ~= 5
+ optlist = [optlist {'MaxOrder' optstruct.MaxOrder}];
+ end
+ if ~isempty(optstruct.MaxStep)
+ optlist = [optlist {'MaxStep' optstruct.MaxStep}];
+ end
+ if ~isempty(optstruct.OutputFcn)
+ optlist = [optlist {'OutputFcn' optstruct.OutputFcn}];
+ end
+ if ~isempty(optstruct.OutputSel)
+ optlist = [optlist {'OutputSel' optstruct.OutputSel}];
+ end
+ if ~isempty(optstruct.Refine)
+ optlist = [optlist {'Refine' optstruct.Refine}];
+ end
+ if optstruct.RelTol ~= 1e-3
+ optlist = [optlist {'RelTol' optstruct.RelTol}];
+ end
+ if ~strcmp(optstruct.Stats,'off')
+ optlist = [optlist {'Stats' optstruct.Stats}];
+ end
+ if ~strcmp(optstruct.Vectorized,'off')
+ optlist = [optlist {'Vectorized' optstruct.Vectorized}];
+ end
+ if ~strcmp(optstruct.NormControl,'off')
+ optlist = [optlist {'NormControl' optstruct.NormControl}];
+ end
+
+ %Auto generate comments or not
+ comments = strcmp(optstruct.Comments,'on');
+
+ %If an old style file is being written
+ oldstyle = strcmp(optstruct.OldStyle,'on');
+
+ %Check to signal for enabling solver menu
+ enableflag = ~isempty(InitList) & ~isempty(t0) & ~isempty(tf) & pflag;
+
+
+ %Now to do the final preparations for writing
+
+ %Format equations
+ [r, c] = size(Eqs);
+ EqList = {};
+ DepList = {};
+ for k = 1:r %Separate left and right sides
+ Eq = Eqs(k,:);
+ [Left, Right] = strtok(Eq, '''');
+ DepList = [DepList {deblank(Left)}];
+ Right = deblank(fliplr(deblank(fliplr(Right(3:length(Right))))));
+ EqList = [EqList {Right}];
+ end
+ for k = 1:length(EqList)
+ for m = 1:length(DepList)
+ %In the next section # and @ are used to ensure that no naming conflict will occur
+ if strcmp(optstruct.Vectorized,'on') %If vect = 'on' write y as y(n,:)
+ EqList{k} = strrep(EqList{k},DepList{m},['#(' int2str(m) ',:)']); %dependent = #
+ else %otherwise as y(n)
+ EqList{k} = strrep(EqList{k},DepList{m},['#(' int2str(m) ')']);
+ end
+ end
+ EqList{k} = strrep(EqList{k},indep,'@'); %indep = @
+ if strcmp(optstruct.Vectorized,'on') %This may have to be changed to always
+ EqList{k} = vectorize(EqList{k});
+ end
+ if isempty(find(EqList{k}=='#')) & strcmp(optstruct.Vectorized,'on')
+ %This is for when "y" doesn't appear in the right side of
+ %an equation. In order to vectorize properly, this term must be added
+ EqList{k} = [EqList{k} '.*ones(size(#(1,:)))'];
+ end
+ %Replace # and @ with the real variables y and t
+ EqList{k} = strrep(EqList{k},'#','y');
+ EqList{k} = strrep(EqList{k},'@','t');
+ end
+
+ if strcmp(fname,'f')
+ subfname = 'subf';
+ else
+ subfname = 'f';
+ end
+
+ %Now to write
+ if ~StrOutput
+ if pth(end) ~= filesep
+ pth = [pth filesep];
+ end
+ Fid = fopen([pth fname '.m'],'wt');
+ end
+
+ OutStr = '';
+
+ if ~isempty(optlist) | ~isempty(t0) | ~isempty(InitList)
+ OutStr = [OutStr sprintf(['function varargout = ' fname '(t,y,flag'])];
+ else %The absolute simplest form
+ OutStr = [OutStr sprintf(['function dydt = ' fname '(t,y'])];
+ if ~isempty(LeftPar)
+ OutStr = [OutStr sprintf(',flag')];
+ end
+ end
+ if ~isempty(LeftPar) %If there are parameters, write them
+ for k = 1:length(LeftPar)
+ OutStr = [OutStr sprintf(',%s',LeftPar{k})];
+ end
+ end
+
+ OutStr = [OutStr sprintf(')\n')];
+ if ~isempty(Help{1})
+ OutStr = [OutStr sprintf('%%%s.M\n',upper(fname))];
+ OutStr = [OutStr sprintf('%s\n',HelpText)];
+ end
+
+ OutStr = [OutStr sprintf('%%%s.M created by DEFWRITE.M on %s\n\n',upper(fname),date)];
+
+ if ~isempty(RightPar) %For default parameter values
+ for k = length(RightPar):-1:1
+ if ~isempty(RightPar{k})
+ if comments
+ OutStr = [OutStr sprintf('%%Default value for %s\n',LeftPar{k})];
+ end
+ OutStr = [OutStr sprintf('if nargin < %d | isempty(%s)\n %s = %s;\nend\n\n',...
+ k+3,LeftPar{k},LeftPar{k},RightPar{k})];
+ end
+ end
+ end
+
+ if ~isempty(optlist) | ~isempty(t0) | ~isempty(InitList) %If we're using subfunctions
+ if oldstyle
+ if comments
+ OutStr = [OutStr sprintf('%%This block is for compatability with older solvers.\n')];
+ end
+ OutStr = [OutStr sprintf('if nargin < 3 | isempty(flag)\n ')];
+ OutStr = [OutStr sprintf('flag = '''';\nend\n\n')];
+ end
+
+ OutStr = [OutStr sprintf('switch(flag)\ncase ''''\n varargout{1} = %s(t,y',subfname)];
+ if ~isempty(LeftPar)
+ for k = 1:length(LeftPar)
+ OutStr = [OutStr sprintf(',%s',LeftPar{k})];
+ end
+ end
+ OutStr = [OutStr sprintf(');')];
+ if comments
+ OutStr = [OutStr sprintf(' %%Return dy/dt = f(t,y)\n')];
+ else
+ OutStr = [OutStr sprintf('\n')];
+ end
+
+ OutStr = [OutStr sprintf('case ''init''\n [varargout{1:3}] = init')];
+ if ~isempty(LeftPar)
+ for k = 1:length(LeftPar)
+ if k == 1
+ OutStr = [OutStr sprintf('(%s',LeftPar{k})];
+ else
+ OutStr = [OutStr sprintf(',%s',LeftPar{k})];
+ end
+ end
+ OutStr = [OutStr sprintf(')')];
+ end
+ OutStr = [OutStr sprintf(';')];
+ if comments
+ OutStr = [OutStr sprintf(' %%Return default [tspan,y0,options]\n')];
+ else
+ OutStr = [OutStr sprintf('\n')];
+ end
+ OutStr = [OutStr sprintf('otherwise\n error([''Unknown flag '''''' flag ''''''.'']);\nend\n\n')];
+
+ OutStr = [OutStr sprintf('%% ----------------------------------------\n\n')];
+ OutStr = [OutStr sprintf('function dydt = %s(t,y',subfname)];
+ if ~isempty(LeftPar)
+ for k = 1:length(LeftPar)
+ OutStr = [OutStr sprintf(',%s',LeftPar{k})];
+ end
+ end
+ OutStr = [OutStr sprintf(')\n')];
+
+ if comments
+ OutStr = [OutStr sprintf('%%Returns dy/dt\n')];
+ end
+ else
+ if comments
+ OutStr = [OutStr sprintf('%%Returns dy/dt\n')];
+ end
+ end
+ OutStr = [OutStr sprintf('dydt = [')]; %write the equations
+ for k = 1:length(EqList)
+ if k ~= 1 & mod(k,3) ~= 1 %For the equations, put no more than 3 per row
+ OutStr = [OutStr sprintf('; ')];
+ end
+ OutStr = [OutStr sprintf('%s',EqList{k})];
+ if mod(k,3) == 0 & k ~= length(EqList)
+ OutStr = [OutStr sprintf(';...\n ')];
+ end
+ end
+ OutStr = [OutStr sprintf('];')];
+ if comments & strcmp(optstruct.Vectorized,'on')
+ OutStr = [OutStr sprintf(' %%Vectorized')];
+ end
+ OutStr = [OutStr sprintf('\n\n')];
+
+ if ~isempty(optlist) | ~isempty(t0) | ~isempty(InitList)
+ OutStr = [OutStr sprintf('%% ----------------------------------------\n\n')];
+ OutStr = [OutStr sprintf('function [tspan,y0,options] = init')];
+ if ~isempty(LeftPar)
+ for k = 1:length(LeftPar)
+ if k == 1
+ OutStr = [OutStr sprintf('(%s',LeftPar{k})];
+ else
+ OutStr = [OutStr sprintf(',%s',LeftPar{k})];
+ end
+ end
+ OutStr = [OutStr sprintf(')')];
+ end
+ OutStr = [OutStr sprintf('\n')];
+
+ if comments
+ OutStr = [OutStr sprintf(['%%Returns initial conditions,',...
+ ' options, and default time span\n'])];
+ OutStr = [OutStr sprintf('\n')];
+ end
+ OutStr = [OutStr sprintf('tspan = [')];
+ if ~isempty(t0)
+ OutStr = [OutStr sprintf('%s; %s',t0,tf)];
+ end
+ OutStr = [OutStr sprintf('];\n')];
+ OutStr = [OutStr sprintf('y0 = [')]; %%%%
+ if ~isempty(InitList)
+ for k = 1:length(InitList)
+ if k ~= 1
+ OutStr = [OutStr sprintf('; ')];
+ end
+ OutStr = [OutStr sprintf('%s',fliplr(deblank(fliplr(InitList{k}))))];
+ end
+ end
+ OutStr = [OutStr sprintf('];\n')];
+ if ~isempty(optlist) %If there are options
+ OutStr = [OutStr sprintf('options = odeset(')];
+ for k = 1:2:(length(optlist)-1)
+ if k ~= 1
+ OutStr = [OutStr sprintf(',...\n ')];
+ end
+ OutStr = [OutStr sprintf('''%s'',',optlist{k})];
+ if ischar(optlist{k+1})
+ OutStr = [OutStr sprintf('''%s''',optlist{k+1})];
+ else
+ OutStr = [OutStr sprintf('%d',optlist{k+1})];
+ end
+ end
+ OutStr = [OutStr sprintf(');\n\n')];
+ else
+ OutStr = [OutStr sprintf('options = [];\n\n')]; %If not, return []
+ end
+ end
+
+ isready = 1; % If we've made it to here, the write was a success
+
+ if ~StrOutput
+ OutStr = strrep(OutStr,'%','%%');
+
+ %Depending on the line used of the two below, either \
+ %will be written unchanged, or it will be removed. Having
+ %it removed makes the use of the \ operator impossible
+ %OutStr = strrep(OutStr,'\','\\');
+ OutStr(find(OutStr=='\')) = '';
+
+ fprintf(Fid,OutStr);
+ fclose(Fid);
+ set(findobj('Tag','wizard'),'Enable','On')
+ else
+ varargout{1} = OutStr;
+ varargout{2} = isready;
+ end
+
+ if ~StrOutput
+ if enableflag %If all the defaults are present
+ set(findobj('Tag','SolverMenu'),'Enable','On');
+ else
+ set(findobj('Tag','SolverMenu'),'Enable','Off');
+ end
+ set(findobj('Tag','ViewFile'),'Enable','On')
+ end
+
+ watchoff(Fig)
+otherwise
+ error(['Invalid input: ''',status,''''])
+end
+
+%===================================================
+function [Eq, Msg] = draweqdlg(EQstr, bgtext, edbox, button)
+%DRAWEQDLG
+% Creates a dialog box which prompts the user for an equation
+% if EQstr is empty, or displays EQstr for the user to edit
+
+%First check for an independent variable
+indep = get(findobj('Tag','indepvar'),'String');
+if isempty(indep)
+ H = errordlg('You must specify an independent variable first',...
+ 'DEFWRITE Error','replace');
+ Eq = '';
+ Msg = 0;
+ return
+end
+
+if isempty(EQstr)
+ namestr = 'Enter Equation';
+ leftstr = '';
+ rightstr = '';
+else
+ namestr = 'Edit Equation';
+ k = find(EQstr=='''');
+ leftstr = EQstr(1:k-1);
+ rightstr = EQstr(k+2:length(EQstr));
+end
+
+pos = get(findobj('Tag','defwrite'),'Position');
+pos = [pos(1)+50 pos(2)+150 250 70];
+Fig = dialog('Units','Pixels',...
+ 'Name',namestr,...
+ 'Position',pos,...
+ 'Tag','eqdlgbox',...
+ 'UserData',0);
+
+%The two buttons
+Hb1 = uicontrol(button,...
+ 'Position',[10/250 10/70 50/250 20/70],...
+ 'String','Cancel',...
+ 'ToolTipString','Don''t accept equation',...
+ 'Callback','set(findobj(''Tag'',''eqdlgbox''),''UserData'',0), uiresume');
+Hb2 = uicontrol(button,...
+ 'Position',[190/250 10/70 50/250 20/70],...
+ 'String','OK',...
+ 'ToolTipString','Accept equation',...
+ 'Callback','set(findobj(''Tag'',''eqdlgbox''),''UserData'',1), uiresume');
+
+Hels = uicontrol(edbox,...
+ 'Position',[5/250 40/70 65/250 20/70],...
+ 'String',leftstr,...
+ 'Tag','leftside',...
+ 'HorizontalAlignment','Right');
+Hers = uicontrol(edbox,...
+ 'Position',[90/250 40/70 155/250 20/70],...
+ 'String',rightstr,...
+ 'Tag','rightside');
+
+Hteq = uicontrol(bgtext,...
+ 'Position',[70/250 40/70 20/250 20/70],...
+ 'String','''=');
+
+%Ensures valid input
+flag = 1;
+
+%Loop until valid input is given
+while flag
+ %Pause for input
+ uiwait
+
+ %Now get output variables
+ Msg = get(findobj('Tag','eqdlgbox'),'UserData');
+
+ %If either both fields are not empty or both fields are
+ %not filled, signal to loop again & give error message
+ %Also loop again if either equation contains '@', '#', or '='
+ Lside = get(findobj('Tag','leftside'),'String');
+ Rside = get(findobj('Tag','rightside'),'String');
+ if ~isempty(Lside) & ~isempty(Rside)
+ k = ~isempty([find(Lside=='#'),find(Lside=='@'),find(Lside=='='),...
+ find(Lside=='!'),find(Lside=='%'),find(Lside=='&'),...
+ find(Rside=='#'),find(Rside=='@'),find(Rside=='='),...
+ find(Rside=='!'),find(Rside=='%'),find(Rside=='&')]);
+ else
+ k = 0;
+ end
+
+ flag = xor(isempty(Lside),isempty(Rside)) | k;
+
+ if Msg & ~flag %flag must be 0
+ Eq = [Lside '''=' Rside];
+ else
+ Eq = '';
+ end
+
+ %If OK was pressed & One side missing, produce error
+ if Msg
+ if flag
+ if k
+ Herr = errordlg('Illegal character: #, @, %, &, !, or =',...
+ 'DEFWRITE Error','replace');
+ flag = 1;
+ else
+ Herr = errordlg('One of the fields are empty',...
+ 'DEFWRITE Error','replace');
+ end
+ uiwait
+ end
+ else
+ flag = 0;
+ end
+end
+
+%Check that empty data wasn't provided. If it was signal 0
+if length(Eq) == 2
+ Msg = 0;
+end
+
+%If the dialog was not closed with the provided buttons
+%then make sure Msg is 0
+fig = findobj('Tag','eqdlgbox');
+if isempty(fig)
+ Msg = 0;
+else
+ close(fig)
+end
+
+%==========================================================
+function Value = drawinitbox(OldValue, bgtext, edbox, button)
+%DRAWINITBOX
+% drawinitbox is the engine that draws an input box
+%for user specified initial conditions
+
+[T, R] = strtok(OldValue,'=');
+if length(R) > 2
+ Num = fliplr(deblank(fliplr(R(2:length(R)))));
+ Old = [T '='];
+else
+ Num = '';
+ Old = OldValue;
+end
+
+%Create dialog box
+pos = get(findobj('Tag','defwrite'),'Position');
+pos = [pos(1)+100 pos(2)+100 170 70];
+Fig = dialog('Units','Pixels',...
+ 'Name','Initial Conditions',...
+ 'Position',pos,...
+ 'Tag','initdlgbox',...
+ 'UserData',0);
+
+%The two buttons
+Hb1 = uicontrol(button,...
+ 'Parent',Fig,...
+ 'Position',[10/170 10/70 50/170 20/70],...
+ 'String','Cancel',...
+ 'ToolTipString','Don''t accept',...
+ 'Callback','set(findobj(''Tag'',''initdlgbox''),''UserData'',0), uiresume');
+Hb2 = uicontrol(button,...
+ 'Parent',Fig,...
+ 'Position',[110/170 10/70 50/170 20/70],...
+ 'String','OK',...
+ 'ToolTipString','Accept',...
+ 'Callback','set(findobj(''Tag'',''initdlgbox''),''UserData'',1), uiresume');
+
+%The display boxes for the values
+Ht = uicontrol(bgtext,...
+ 'Parent',Fig,...
+ 'Position',[10/170 40/70 50/170 20/70],...
+ 'String',Old);
+He = uicontrol(edbox,...
+ 'Parent',Fig,...
+ 'Position',[60/170 40/70 100/170 20/70],...
+ 'String',Num,...
+ 'Tag','thebox');
+
+%Pause for input
+uiwait
+
+%Checks for OK or Cancel
+flag = get(findobj('Tag','initdlgbox'),'UserData');
+
+%Either change values or not
+if flag
+ Value = [Old ' ' get(findobj('Tag','thebox'),'String')];
+else
+ Value = OldValue;
+end
+
+%Checks for "normal" exit
+if isempty(findobj('Tag','initdlgbox'))
+ Value = OldValue;
+else
+ close(gcf)
+end
+
+%====================================================
+function [NewStr, Msg, Del] = drawparbox(Str, bgtext, edbox, button)
+%DRAWPARBOX
+% drawparbox creates an input window for editing and creating
+% parameters
+
+%Make sure to assign values
+Del = 0;
+Msg = 0;
+NewStr = '';
+
+if ~isempty(Str) %If we're editing
+ [T, R] = strtok(Str, '=');
+ Left = deblank(T);
+ if strncmp(R, '=' ,1);
+ Right = R(2:length(R));
+ else
+ Right = '';
+ end
+ namestr = 'Edit Parameter';
+else %Otherwise, it must be new
+ Left = '';
+ Right = '';
+ namestr = 'New Parameter';
+end
+
+pos = get(findobj('Tag','defwrite'),'Position');
+pos = [pos(1)+150 pos(2)+100 190 70];
+Fig = dialog('Units','Pixels',...
+ 'Name',namestr,...
+ 'Position',pos,...
+ 'Tag','parbox',...
+ 'UserData',0);
+%The two buttons
+Hb1 = uicontrol(button,...
+ 'Position',[10/190 10/70 50/190 20/70],...
+ 'String','Cancel',...
+ 'ToolTipString','Don''t accept',...
+ 'Callback','set(findobj(''Tag'',''parbox''),''UserData'',0), uiresume');
+Hb2 = uicontrol(button,...
+ 'Position',[130/190 10/70 50/190 20/70],...
+ 'String','OK',...
+ 'ToolTipString','Accept',...
+ 'Callback','set(findobj(''Tag'',''parbox''),''UserData'',1), uiresume');
+
+Hels = uicontrol(edbox,...
+ 'Position',[5/190 40/70 70/190 20/70],...
+ 'String',Left,...
+ 'Tag','leftside',...
+ 'HorizontalAlignment','Right');
+Hers = uicontrol(edbox,...
+ 'Position',[85/190 40/70 100/190 20/70],...
+ 'String',Right,...
+ 'Tag','rightside');
+
+Hteq = uicontrol(bgtext,...
+ 'Position',[75/190 40/70 10/190 20/70],...
+ 'String','=');
+
+%The delete button--used if we're editing
+if ~isempty(Str)
+ Hb3 = uicontrol(button,...
+ 'Position',[70/190 10/70 50/190 20/70],...
+ 'String','Delete',...
+ 'ToolTipString','Delete this parameter from list',...
+ 'Callback','set(findobj(''Tag'',''parbox''),''UserData'',2), uiresume');
+end
+
+flag = 1;
+
+while flag
+ %Pause for input
+ uiwait
+
+ Left = deblank(get(findobj('Tag','leftside'),'String'));
+ Msg = get(findobj('Tag','parbox'),'UserData');
+
+ if isempty(findobj('Tag','parbox')) %If it was closed by the "x"
+ Msg = 0;
+ end
+
+ if Msg == 1
+ if ~isempty(Left) %If OK, validate input
+ Right = get(findobj('Tag','rightside'),'String');
+ Right = fliplr(deblank(fliplr(Right)));
+ flag = 0;
+ else
+ H = errordlg('The left field cannot be empty','DEFWRITE Error','replace');
+ uiwait
+ end
+ elseif Msg == 2 %If delete, signal so
+ Del = 1;
+ flag = 0;
+ else
+ flag = 0;
+ end
+end
+
+if Msg == 1
+ NewStr = [Left ' = ' Right];
+end
+
+if ~isempty(findobj('Tag','parbox')) %If closed by one of the buttons
+ close(gcf)
+end
+
+%=======================================================
+function NewVal = optionenter(Title,oldval,defval,button,bgtext,edbox)
+%OPTIONENTER
+% Creates a GUI for user input of options
+
+%Get the new value
+%If the string given turns out to be empty, it is OK because for some options,
+%the default is an empty string
+%NewVal = inputdlg('Enter New Value:',['Modify ' Title],1,cellstr(oldval));
+
+%if isempty(NewVal) %If cancel was pressed, return the old value
+% NewVal = cellstr(oldval);
+%end
+
+%Make sure of a return value
+NewVal = cellstr(oldval);
+
+pos = get(findobj('Tag','defwrite'),'Position');
+pos = [pos(1)+100 pos(2)+180 190 70];
+Fig = dialog('Units','Pixels',...
+ 'Name',['Modify ' Title],...
+ 'Position',pos,...
+ 'Tag','optbox',...
+ 'UserData',0);
+
+Hb1 = uicontrol(button,...
+ 'Position',[10/190 10/70 50/190 20/70],...
+ 'String','Cancel',...
+ 'Callback','set(findobj(''Tag'',''optbox''),''UserData'',0), uiresume',...
+ 'ToolTipString','Don''t change option');
+Hb2 = uicontrol(button,...
+ 'Position',[70/190 10/70 50/190 20/70],...
+ 'String','Default',...
+ 'ToolTipString','Restore default value',...
+ 'Callback',['set(findobj(''Tag'',''optedfield''),''String'',''' defval ''')']);
+Hb3 = uicontrol(button,...
+ 'Position',[130/190 10/70 50/190 20/70],...
+ 'String','OK',...
+ 'ToolTipString','Accept new option value',...
+ 'Callback','set(findobj(''Tag'',''optbox''),''UserData'',1), uiresume');
+
+Heval = uicontrol(edbox,...
+ 'Tag','optedfield',...
+ 'Position',[80/190 40/70 100/190 20/70],...
+ 'String',oldval);
+
+Hteq = uicontrol(bgtext,...
+ 'Position',[10/190 40/70 70/190 20/70],...
+ 'HorizontalAlignment','Right',...
+ 'String','Enter a Value:');
+
+uiwait
+
+if isempty(findobj('Tag','optbox'))
+ return
+end
+
+if get(findobj('Tag','optbox'),'UserData')
+ NewVal = cellstr(get(findobj('Tag','optedfield'),'String'));
+end
+
+delete(findobj('Tag','optbox'))
+
+%=======================================================
+function Str = vectorize(Str)
+%VECTORIZE
+% Vectorizes a string i.e. 'a/b*x^2' becomes 'a./b.*x.^2'
+
+Str = strrep(Str,'*','.*');
+Str = strrep(Str,'/','./');
+Str = strrep(Str,'^','.^');
+Str(findstr(Str,'..')) = [];
diff --git a/defwrite/defwrite.mat b/defwrite/defwrite.mat
new file mode 100755
index 0000000..8bbba66
--- /dev/null
+++ b/defwrite/defwrite.mat
Binary files differ
diff --git a/defwrite/proceed.bmp b/defwrite/proceed.bmp
new file mode 100755
index 0000000..3fa6f5e
--- /dev/null
+++ b/defwrite/proceed.bmp
Binary files differ
diff --git a/defwrite/quit.bmp b/defwrite/quit.bmp
new file mode 100755
index 0000000..16832dc
--- /dev/null
+++ b/defwrite/quit.bmp
Binary files differ
diff --git a/defwrite/reset.bmp b/defwrite/reset.bmp
new file mode 100755
index 0000000..2e7c777
--- /dev/null
+++ b/defwrite/reset.bmp
Binary files differ
diff --git a/defwrite/view.bmp b/defwrite/view.bmp
new file mode 100755
index 0000000..3354685
--- /dev/null
+++ b/defwrite/view.bmp
Binary files differ
diff --git a/fileselect/README b/fileselect/README
new file mode 100644
index 0000000..55fa7fe
--- /dev/null
+++ b/fileselect/README
@@ -0,0 +1,4 @@
+A Win32-only replacement for the standard Tk::FileSelect widget. UNC
+pathname navigation might need a little work. Currently implemented
+as a subroutine, but it would be a trivial exercise to convert it to a
+module.
diff --git a/fileselect/fileselect.pl b/fileselect/fileselect.pl
new file mode 100755
index 0000000..5c6d86b
--- /dev/null
+++ b/fileselect/fileselect.pl
@@ -0,0 +1,303 @@
+# an alternate file select widget
+
+use strict;
+use warnings;
+
+use Tk;
+use Tk::BrowseEntry;
+use Tk::ROText;
+use Tk::Toplevel;
+
+use Win32API::File 0.08 qw( :ALL );
+
+
+my $main = MainWindow->new (-title => 'File Select Test');
+
+$main->Label (-text => 'Initial Directory')->pack;
+my $edir = $main->Entry (-width => 40)->pack;
+
+$main->Label (-text => 'Filter')->pack;
+my $efil = $main->Entry (-width => 40)->pack;
+
+$main->Label (-text => 'Filter Description')->pack;
+my $efid = $main->Entry (-width => 40)->pack;
+
+$main->Label (-text => 'Selected File')->pack;
+my $e = $main->Entry (-width => 40)->pack;
+$main->Button (-text => 'Select File',
+ -command => sub {
+ $e->delete ('0', 'end');
+ my $file = select_file ($main, $edir->get,
+ $efil->get, $efid->get);
+ $e->delete ('0', 'end');
+ return if not defined $file;
+ $e->insert ('end', $file);
+ })->pack (-fill => 'x');
+
+MainLoop;
+
+
+# select_file is a drop-in replacement for Tk::FileSelect. It works
+# much better the interface is more intuitive.
+# Parameters:
+# mw Handle to the application's MainWindow
+# idir Initial directory. If this isn't specified, the current
+# directory is used.
+# filter Optional file filter.
+# desc Optional description for the file filter.
+# Returns:
+# A string containing the full path to a file, or undef, if no file
+# was selected.
+# Uses
+# Tk
+# Tk::BrowseEntry
+# Tk::ROText
+# Tk::Toplevel
+# Win32API::File 0.08 qw( :ALL )
+sub select_file {
+ my ( $mw, $idir, $filter, $desc ) = @_;
+ my ( $file, $sel );
+
+ $idir = Win32::GetCwd () if not defined $idir or length $idir == 0;
+ $filter = '' if not defined $filter;
+ $desc = '' if not defined $desc;
+
+ my $fs = $mw->Toplevel (-title => 'Select File');
+
+ # create the fonts to use for files and directories
+ my $ffont = 'file_font';
+ my $dfont = 'dir_font';
+ $fs->fontCreate ($ffont, -family => 'courier', -size => 8);
+ $fs->fontCreate ($dfont, -family => 'courier',-size => 8,-weight => 'bold');
+
+
+ my @drives; # list of currently "mounted" drives
+ my $curdir = $idir; # the current directory name - not the full path
+ my $curpath; # the current path minus the current directory
+ my $flist; # the file list
+ my $fileb; # the file entry box
+ my $filtb; # the filter entry box
+ my $curfilter = $filter; # the current filter
+ my $fstr; # the filter string
+ my $at_top = 0; # at the top of the drive heirarchy
+
+ # chop the dir into the first part and display part
+ # i.e. H:\foo\bar\biff\ -> H:\foo\bar\ biff\
+ if ($curdir =~ m|(\w+:\\([^\\]+\\)*)([^\\]+\\?)|) {
+ ( $curpath, $curdir ) = ( $1, $3 );
+ }
+
+ # subroutines
+
+ # refresh the current directory view
+ my $refresh;
+ $refresh = sub {
+ my @files;
+
+ $curpath = '' if not defined $curpath;
+ $curdir = '' if not defined $curdir;
+ $curpath =~ s|\\+|\\|g;
+
+ if ($at_top) {
+ my $drives = '';
+ GetLogicalDriveStrings (26*4+1, $drives);
+
+ @files = split /\0/, $drives;
+ } else {
+ opendir DH, "$curpath$curdir";
+ @files = readdir DH;
+ closedir DH;
+ }
+
+ $flist->delete ('0.0', 'end');
+ foreach my $f (@files) {
+ next if $f =~ m/^\.\.?$/;
+ if (length $curfilter > 0) {
+ next unless $f =~ m/\.\Q$curfilter\E$/
+ or -d "$curpath$curdir\\$f" or $at_top;
+ }
+ # get rid of spaces in tag names - this could cause problems if
+ # there is one file called 'foo_bar' and another called 'foo bar'
+ my $t = $f; $t =~ s/ /_/g;
+ $flist->insert ('end', "$f\n", $t);
+ if ($at_top or -d "$curpath$curdir\\$f") {
+ $flist->tag ('configure', $t, -font => $dfont);
+ $flist->tag ('bind', $t, '<Any-Enter>' => sub {
+ shift->tag ('configure', $t, -underline => 'on');
+ });
+ $flist->tag ('bind', $t, '<Any-Leave>' => sub {
+ shift->tag ('configure', $t, -underline => undef);
+ });
+ $flist->tag ('bind', $t, '<Double-Button-1>' => sub {
+ $curpath = "$curpath$curdir\\" unless $at_top;
+ $curdir = $flist->get ("${t}.first", "${t}.last");
+ chomp $curdir;
+ $at_top = 0;
+ &$refresh;
+ });
+ } else {
+ $flist->tag ('configure', $t, -font => $ffont);
+ $flist->tag ('bind', $t, '<Button-1>' => sub {
+ my $sel_f = $flist->get ("${t}.first", "${t}.last");
+ chomp $sel_f;
+ $fileb->delete ('0', 'end');
+ $fileb->insert ('end', $sel_f);
+ });
+ $flist->tag ('bind', $t, '<Double-Button-1>' => sub {
+ my $sel_f = $flist->get ("${t}.first", "${t}.last");
+ chomp $sel_f;
+ $fileb->delete ('0', 'end');
+ $fileb->insert ('end', $sel_f);
+
+ $sel = 'Accept';
+ });
+ }
+ }
+
+ # fix the selection - doesn't seem to work the way expected
+ $flist->markUnset ($flist->markNames);
+ };
+
+ my $get_dirs = sub {
+ my $drives = '';
+ GetLogicalDriveStrings (26*4+1, $drives);
+
+ my $curdrive = "$curpath$curdir";
+ $curdrive =~ s|(\w+:\\?).*|$1|;
+ $curdrive .= '\\' unless $curdrive =~ m/\\$/;
+
+ @drives = ();
+ foreach my $d (split /\0/, $drives) {
+ push @drives, $d;
+
+ if ($d =~ m/^\Q$curdrive\E/i) {
+ my $curdir_t = "$curpath$curdir";
+ $curdir_t =~ s|[^\\]+\\(.*)|$1|;
+ my $spc = ' ';
+ while ($curdir_t =~ m|([^\\]+)|g) {
+ push @drives, "$spc$1";
+ $spc .= ' ';
+ }
+ }
+ }
+
+ return @drives;
+ };
+
+ $fs->Label (-text => 'Current Directory')->pack;
+
+ my $df = $fs->Frame->pack (-fill => 'x');
+ my $cdir;
+ $cdir = $df->BrowseEntry (-width => 40,
+ -variable => \$curdir,
+ -state => 'readonly',
+ -browsecmd => sub {
+ my $k;
+ foreach my $n (0 .. $#drives) {
+ $k = $n - 1, last if $drives[$n] eq $curdir;
+ }
+ $curdir =~ s/^ +//;
+ $curpath = '';
+ unless ($curdir =~ m|\w+:\\|) {
+ while ($k and $drives[$k] !~ m|\w+:\\|) {
+ $curpath = "$drives[$k]\\$curpath";
+ $curpath =~ s/^ +//;
+ $k--;
+ }
+ $curpath = "$drives[$k]$curpath";
+ }
+
+ &$refresh;
+ }, -listcmd => sub {
+ $cdir->delete ('0', 'end');
+ $cdir->insert ('0', &$get_dirs);
+ })->pack (-side => 'left');
+ $cdir->insert ('end', $idir);
+ $df->Button (-text => 'Up',
+ -command => sub {
+ if ($at_top) {
+ # already at the top
+ return;
+ } elsif (length $curpath == 0) {
+ # at the drive root - go to the top
+ $curdir = 'Top of Tree';
+ $at_top = 1;
+ } elsif ($curpath =~ m/^\w+:\\?$/) {
+ # one deep in the drive - go to the drive root
+ $curdir = $curpath;
+ $curpath = '';
+ } elsif ($curpath =~ m|(\w+:\\([^\\]+\\)*)([^\\]+\\?)|) {
+ # just go up one
+ ( $curpath, $curdir ) = ( $1, $3 );
+ }
+
+ &$refresh;
+ })->pack (-side => 'right');
+
+ $flist = $fs->Scrolled ('ROText', -scrollbars => 'osoe',
+ -cursor => 'arrow', -width => 40,
+ -height => 10, -wrap => 'none')->pack;
+
+ my $ff = $fs->Frame->pack (-fill => 'x');
+ $ff->Label (-text => ' File:', -justify => 'right')->pack (-side => 'left');
+ $fileb = $ff->Entry (-width => 30)->pack (-side => 'left');
+ $fileb->bind ('<Return>', sub { $sel = 'Accept' });
+ $ff->Button (-text => 'Accept',
+ -command => sub {
+ $sel = 'Accept';
+ })->pack (-side => 'right');
+
+ my $rf = $fs->Frame->pack (-fill => 'x');
+ $rf->Label (-text => 'Filter:', -justify => 'right')->pack (-side => 'left');
+
+
+ $filtb = $rf->BrowseEntry (-width => 30,
+ -state => 'readonly',
+ -variable => \$fstr,
+ -browsecmd => sub {
+ if ($fstr eq 'All Files (*.*)') {
+ $curfilter = '';
+ } else {
+ $curfilter = $filter;
+ }
+
+ &$refresh;
+ })->pack (-side => 'left');
+ {
+ my @choices;
+ push @choices, "$desc (*.$filter)" if length $filter;
+ push @choices, 'All Files (*.*)';
+ $filtb->insert ('end', $_) foreach (@choices);
+ $fstr = $choices[0];
+ }
+
+ $rf->Button (-text => 'Cancel',
+ -command => sub {
+ $sel = 'Cancel';
+ })->pack (-side => 'right');
+
+ &$refresh;
+
+ my $old_focus = $fs->focusSave;
+ my $old_grab = $fs->grabSave;
+ $fs->transient ($mw);
+ $fs->protocol('WM_DELETE_WINDOW' => sub {});
+ $fs->focus;
+ $fs->grab;
+
+ $fs->waitVariable (\$sel);
+
+ $fs->grabRelease;
+ $fs->withdraw;
+ &$old_focus;
+ &$old_grab;
+
+ $file = $fileb->get;
+ $file = (length $file) ? "$curpath$curdir\\$file" : undef;
+ $file =~ s|\\+|\\|g if defined $file;
+
+ $fs->fontDelete ($ffont);
+ $fs->fontDelete ($dfont);
+
+ return $file;
+}
diff --git a/fluxbox/fluxbox-generate_menu b/fluxbox/fluxbox-generate_menu
new file mode 100755
index 0000000..14fdc5a
--- /dev/null
+++ b/fluxbox/fluxbox-generate_menu
@@ -0,0 +1,181 @@
+#!/usr/bin/perl
+#
+# Alternate fluxbox-generate_menu. Searches all the installed
+# .desktop files to generate the menu.
+#
+
+use strict;
+use warnings;
+use File::Find;
+use File::Which;
+
+my $fluxbox_menu = "$ENV{HOME}/.fluxbox/menu";
+my @desktop_dirs = ('/usr/share/applications', "$ENV{HOME}/.local/share/applications");
+my @desktop_files = ();
+my %desktop_entries;
+
+for my $dir (@desktop_dirs) {
+ opendir (my $dh, $dir) or die "opendir($dir)";
+ my @files = grep { /\.desktop$/ && -f "$dir/$_" } readdir ($dh);
+ push @desktop_files, map { "$dir/$_" } @files;
+ closedir ($dh);
+}
+
+foreach my $file (@desktop_files) {
+ open (my $fh, "<$file") or die "open($file)";
+ my %entry = (file => $file);
+ my $header_found = 0;
+ foreach my $line (<$fh>) {
+ chomp $line;
+ next if $line =~ m/^\s*#/;
+ if ($line =~ m/\[Desktop Entry\]/) { $header_found = 1; next; }
+ next unless $header_found;
+ last if $line =~ m/^\[.+\]/;
+
+ my ($k, $v) = split (/=/, $line);
+ next unless $k && $v;
+ next if $k =~ m/\[[-\w@]+\]$/; # Skip alt language entries;
+ next if $k eq 'OnlyShowIn' && $v !~ m/fluxbox/i;
+
+ $entry{$k} = $v;
+ }
+ if ($entry{Name} &&
+ ! (($entry{Hidden} && $entry{Hidden} eq 'true') ||
+ ($entry{NoDisplay} && $entry{NoDisplay} eq 'true'))) {
+ $desktop_entries{$entry{Name}} = \%entry;
+ }
+}
+
+# See https://specifications.freedesktop.org/menu-spec/latest/apa.html
+# Sorted in descending order of menu preference
+my @menus = qw/TerminalEmulator
+ Network
+ AudioVideo
+ Graphics
+ Science
+ Development
+ Game
+ Utility
+ Office
+ System
+ Other/;
+my %menus;
+
+name: foreach my $name (sort keys %desktop_entries) {
+ my @categories = split (';', $desktop_entries{$name}->{Categories} // 'Other');
+ next if grep { /^(X-)?(XFCE|LXDE)(-Settings)?$/ } @categories;
+ next unless which split (' ', $desktop_entries{$name}->{Exec});
+
+ foreach my $menu (@menus) {
+ if (grep { /^$menu$/ } @categories) {
+ $menus{$menu}->{$name} = $desktop_entries{$name};
+ next name;
+ }
+ }
+
+ $menus{Other}->{$desktop_entries{$name}->{Name}} = $desktop_entries{$name};
+}
+
+rename $fluxbox_menu, "$fluxbox_menu.bak" or die "rename($fluxbox_menu,$fluxbox_menu.bak)";
+
+open (my $fh, ">$fluxbox_menu") or die "open($fluxbox_menu)";
+
+print $fh <<"HEADER";
+# Generated by fluxbox-generate_menu
+
+[begin] (Fluxbox)
+[encoding] {UTF-8}
+ [exec] (Terminator) {terminator} </usr/share/icons/hicolor/48x48/apps/terminator.png>
+ [exec] (firefox) {firefox} </usr/share/icons/nuoveXT2/32x32/apps/firefox.png>
+ [exec] (thunderbird) {thunderbird} </usr/share/icons/hicolor/256x256/apps/thunderbird-icon.png>
+ [exec] (Run) {fbrun}
+ [exec] (Suspend to RAM) {gotosleep ram}
+ [exec] (Suspend to Disk) {gotosleep disk}
+HEADER
+
+foreach my $menu (@menus) {
+ next unless exists $menus{$menu};
+ my %rename = (TerminalEmulator => 'Terminals',
+ AudioVideo => 'Media',
+ Game => 'Games');
+
+ my $menuname = $rename{$menu} // $menu;
+
+ print $fh "[submenu] ($menuname)\n";
+
+ foreach my $name (sort keys %{$menus{$menu}}) {
+ my $icontext = '';
+ my $foundicon;
+ my $icon = $desktop_entries{$name}->{Icon};
+
+ if ($icon) {
+ if (-f $icon) {
+ $icontext = " <$icon>";
+ } else {
+ # Play a game of find the icon
+ find (sub {
+ if ($_ =~ m/$icon/ && ! defined ($foundicon) && $_ =~ m/\.(png|jpg|jpeg|xpm)$/) {
+ $foundicon = $File::Find::name;
+ }
+ }, ("$ENV{HOME}/.local/share/icons",
+ qw(/usr/share/icons/hicolor
+ /usr/share/icons/
+ /usr/share/pixmaps)));
+ if (defined ($foundicon)) {
+ $icontext = " <$foundicon>";
+ }
+ }
+ }
+
+ my $exec = $desktop_entries{$name}->{Exec};
+ # Remove file/url arguments (they make no sense here) and deprecated entries
+ $exec =~ s/%[fFuUdDnNvm]//g;
+ # Replace %i (icon), %c (name), and %k (desktop file)
+ $exec =~ s/%i/--icon $foundicon/g if $foundicon;
+ $exec =~ s/%c/$name/g;
+ $exec =~ s/%k/$desktop_entries{$name}->{file}/g;
+
+ print $fh " [exec] ($name) {$exec}$icontext\n";
+ }
+
+ print $fh "[end]\n";
+}
+
+print $fh <<"USER";
+[submenu] (User Programs)
+ [exec] (VMware) {/usr/bin/vmware}
+ [exec] (KiCad) {/usr/bin/kicad}
+ [exec] (Eagle) {/opt/bin/eagle}
+ [exec] (GThumb) {/usr/bin/gthumb}
+ [exec] (QBitTorrent) {/usr/bin/qbittorrent}
+ [exec] (HandBrake) {/usr/bin/ghb}
+[end]
+USER
+
+print $fh <<"FOOTER";
+[submenu] (Fluxbox menu)
+ [config] (Configure)
+[submenu] (Styles)
+ [include] (/usr/share/fluxbox/menu.d/styles/)
+[end]
+ [workspaces] (Workspace List)
+[submenu] (Tools)
+ [exec] (Window name) {xprop WM_CLASS|cut -d \" -f 2|gxmessage -file - -center}
+ [exec] (Run) {fbrun}
+ [exec] (Regen Menu) {fluxbox-generate_menu -ds -is}
+[end]
+[submenu] (Window Managers)
+ [restart] (openbox) {openbox} </usr/share/pixmaps/openbox.png>
+[end]
+ [commanddialog] (Fluxbox Command)
+ [reconfig] (Reload config)
+ [restart] (Restart)
+ [exec] (About) {(fluxbox -v; fluxbox -info | sed 1d) | gxmessage -file - -center}
+ [separator]
+ [exit] (Exit)
+[end]
+[endencoding]
+[end]
+FOOTER
+
+close ($fh);
diff --git a/gpx/gpx2kml.pl b/gpx/gpx2kml.pl
new file mode 100755
index 0000000..22d09f4
--- /dev/null
+++ b/gpx/gpx2kml.pl
@@ -0,0 +1,253 @@
+#!/usr/bin/perl
+#
+# Convert GPX to KML. Simple and probably incomplete, but nicely formatted.
+#
+
+use strict;
+use warnings;
+
+use File::Copy;
+use File::Temp 'tempfile';
+use Getopt::Long;
+use XML::Simple;
+
+my $stuckToGround = 0;
+my $pretend = 0;
+my $rename = 0;
+my $name = '';
+my $folder = 0;
+
+sub usage {
+ print <<"USAGE";
+gpx2kml.pl [options] <file.gpx> [files.gpx...] [outfile.kml]
+
+Convert a GPX file into a KML file. Temporal information is not
+preserved.
+
+Options:
+ --clamp,-c set altitudeMode to clampToGround
+ --ground,-g same as above
+ --autoname,-a rename KML file based on start date/time
+ --name,-n name of track
+ --pretend,-n show what would be done, but don't do it
+USAGE
+ exit;
+}
+
+my ($gpx, $kml);
+
+GetOptions('outfile|o' => \$kml,
+ 'clamp|c' => \$stuckToGround,
+ 'ground|g' => \$stuckToGround,
+ 'pretend|n' => \$pretend,
+ 'name|n=s' => \$name,
+ 'autorename|a' => \$rename) or usage();
+
+@ARGV > 0 || usage;
+
+unless ($kml) {
+ if ($ARGV[-1] =~ m/\.kml$/) {
+ $kml = pop @ARGV;
+ } else {
+ $kml = $ARGV[0];
+ $kml =~ s/\.gpx$/.kml/;
+ }
+}
+
+my $altitudeMode = $stuckToGround ? 'clampToGround' : 'absolute';
+
+my ($kx, $outfile) = tempfile ();
+
+my $indent_level = 0;
+
+# Just in case we want to view the output...
+print $kx "<!-- -*- xml -*- -->\n";
+
+kml_push ('kml',
+ 'xmlns' => 'http://www.opengis.net/kml/2.2',
+ 'xmlns:gx' => 'http://www.google.com/kml/ext/2.2');
+
+if (@ARGV > 1) {
+ kml_push ('Folder');
+ kml_print ('name', $name);
+}
+
+# Create a combined track if there are multiple gpx files
+my @total_track_points;
+
+foreach my $gpx (@ARGV) {
+ my $gx = XMLin($gpx);
+
+ if ($rename) {
+ unless (defined($gx->{trk}->{trkseg}->{trkpt}->[0]->{time})) {
+ warn "Unable to autorename -- no temporal information available\n";
+ } else {
+ $kml = $gx->{trk}->{trkseg}->{trkpt}->[0]->{time} . ($name ? "-$name" : '') . '.kml';
+ $kml =~ s/[: ]/-/g;
+ }
+ $rename = 0; # only use the first gpx
+ }
+
+ if ($gx->{trk}) {
+ my $trkname = $gx->{trk}->{name}
+ // $gx->{metadata}->{name}
+ // ($gx->{name} . ($name ? "-$name" : ''))
+ // $name;
+
+ my $color = color ($gx->{trk}->{extensions}->{"gpxx:TrackExtension"}->{"gpxx:DisplayColor"});
+
+ kml_push ('Placemark');
+ kml_print ('name', "<![CDATA[$trkname]]>");
+ kml_print ('visibility', '1');
+
+ kml_push ('Style');
+ kml_push ('LineStyle');
+ kml_print ('color', $color);
+ kml_print ('width', '1.9');
+ kml_pop (); # LineStyle
+ kml_pop (); # Style
+
+ kml_push ('LineString');
+ kml_print ('altitudeMode', $altitudeMode);
+ kml_push ('coordinates');
+
+ foreach my $p (@{$gx->{trk}->{trkseg}->{trkpt}}) {
+ my $coordinate = "$p->{lon}.,$p->{lat},$p->{ele}";
+ kml_print (undef, $coordinate); # XXX: Strip out time info for now
+ push @total_track_points, $coordinate;
+ }
+
+ kml_pop (); # coordinates
+ kml_pop (); # LineString
+ kml_pop (); # Placemark
+
+ } elsif ($gx->{wpt}) {
+ sub waypoint {
+ my ($wptname, $wpt) = @_;
+
+ kml_push ('Placemark');
+ kml_print ('name', "<![CDATA[$wptname]]>");
+ kml_print ('visibility', '1');
+
+ kml_push ('Style');
+ kml_push ('IconStyle');
+ kml_print ('scale', '1.1');
+ kml_print ('color', color (undef));
+ kml_push ('Icon');
+ # XXX: Can avoid hitting google if bundling an icon in a kmz
+ # icons: blu-blank.png grn-blank.png ltblu-blank.png pink-blank.png wht-blank.png
+ kml_print ('href', 'http://maps.google.com/mapfiles/kml/paddle/wht-blank.png');
+ kml_pop (); # Icon
+ kml_pop (); # IconStyle
+ kml_pop (); # Style
+
+ kml_push ('Point');
+ kml_print ('altitudeMode', $altitudeMode);
+ kml_push ('coordinates');
+ kml_print (undef, "$wpt->{lon}.,$wpt->{lat},$wpt->{ele}"); # XXX: Strip out time info for now
+ kml_pop (); # coordinates
+ kml_pop (); # Point
+
+ kml_pop (); # Placemark
+ }
+
+ if ($gx->{wpt}->{lat}) {
+ # single waypoint
+ waypoint ($gx->{wpt}->{name} // 'waypoint', $gx->{wpt});
+ } else {
+ foreach my $wptname (keys (%{$gx->{wpt}})) {
+ waypoint ($wptname, $gx->{wpt}->{$wptname});
+ }
+ }
+ }
+}
+
+if (@ARGV > 1) {
+ # Generate combined track
+ kml_push ('Placemark');
+ kml_print ('name', "Combined Track");
+ kml_print ('visibility', '0');
+
+ kml_push ('Style');
+ kml_push ('LineStyle');
+ kml_print ('color', color ('red'));
+ kml_print ('width', '1.9');
+ kml_pop (); # LineStyle
+ kml_pop (); # Style
+
+ kml_push ('LineString');
+ kml_print ('altitudeMode', $altitudeMode);
+ kml_push ('coordinates');
+
+ kml_print (undef, $_) foreach @total_track_points;
+
+ kml_pop (); # coordinates
+ kml_pop (); # LineString
+ kml_pop (); # Placemark
+
+
+ kml_pop (); # Folder
+}
+
+kml_pop ();
+
+close ($kx);
+
+move ($outfile, $kml) or die "Failed to rename $outfile => $kml: $!\n";
+
+print "Wrote $kml\n";
+
+exit 0;
+
+
+my @elements;
+
+sub kml_push {
+ my $element = shift;
+ my %params = @_;
+ push @elements, $element;
+ print $kx ' ' x $indent_level . "<$element" . join ('', map { qq( $_="$params{$_}") } keys (%params)) . ">\n";
+ $indent_level += 2;
+}
+
+sub kml_pop {
+ my $element = pop @elements;
+ $indent_level -= 2 if $indent_level;
+ print $kx ' ' x $indent_level . "</$element>\n" if $element;
+}
+
+sub kml_print {
+ my ($element, $contents) = @_;
+ print $kx ' ' x $indent_level;
+ print $kx "<$element>" if $element;
+ print $kx $contents;
+ print $kx "</$element>" if $element;
+ print $kx "\n";
+}
+
+sub color {
+ my $name = shift;
+ my $color = '000000';
+ my $havename = defined($name);
+ $name = ".+" unless $havename;
+
+ my $rgbfile = '/usr/share/X11/rgb.txt';
+ my $rand = int(rand((split(/ /, `wc -l $rgbfile`))[0]));
+ open(RGB, "<$rgbfile") or goto END;
+
+ foreach my $rgb (<RGB>) {
+ if (((!$havename and $rand-- <= 0) or $havename) and
+ $rgb =~ m/(\d+)\s+(\d+)\s+(\d+)\s+($name)$/i) {
+ my ($r, $g, $b) = ($1, $2, $3);
+ next if $4 =~ m/gr[ae]y/i;
+ $color = sprintf('ff%02x%02x%02x', $b, $g, $r); # AABBGGRR
+ #print "Found $1,$2,$3 ($rgb)\n";
+ last;
+ }
+ }
+
+ close(RGB);
+
+ END:
+ return $color;
+}
diff --git a/gpx/gpxinfo.pl b/gpx/gpxinfo.pl
new file mode 100755
index 0000000..9a70e08
--- /dev/null
+++ b/gpx/gpxinfo.pl
@@ -0,0 +1,188 @@
+#!/usr/bin/perl
+#
+# Basic information about a GPS track.
+#
+# N.b. fetching DEM elevations is very slow and not really more
+# accurate than just using the GPS values.
+
+use strict;
+use warnings;
+
+use Date::Parse;
+use Getopt::Long;
+#use LWP::Simple;
+use HTTP::Request;
+use LWP::UserAgent;
+
+use XML::Simple;
+
+
+my $sum = 0;
+my $sum_only = 0;
+my $offline = 0; # Do not compute DEM elevations if set
+my $show_progress = 0;
+my $exclude;
+
+sub usage {
+ print <<"USAGE";
+Usage: gpxinfo.pl <gpx>
+USAGE
+ exit;
+}
+
+my $spinner = 0;
+my @spinner = qw(| / - \\);
+sub spinner {
+ print "\b".$spinner[$spinner++ % @spinner];
+}
+
+my $radius = 3963.1; # radius of the earth in miles
+my $pi = atan2(1, 1) * 4;
+
+sub deg2rad {
+ return $pi * $_[0] / 180.0;
+}
+
+sub acos {
+ $_[0] = 1.0 if $_[0] > 1.0;
+ return atan2(sqrt(1.0 - $_[0] ** 2.0), $_[0]);
+}
+
+sub lateral_distance {
+ # From http://www8.nau.edu/cvm/latlon_formula.html
+ my ($a1, $b1, $a2, $b2) = @_;
+ return &acos(cos($a1)*cos($b1)*cos($a2)*cos($b2) + cos($a1)*sin($b1)*cos($a2)*sin($b2) + sin($a1)*sin($a2)) * $radius;
+}
+
+my $ua;
+
+sub fetch_dem_elevation {
+ my ($lat, $lon) = @_;
+ my $request = HTTP::Request->new(GET => "https://nationalmap.gov/epqs/pqs.php?units=feet&output=xml&x=$lon&y=$lat");
+ $ua = LWP::UserAgent->new(keep_alive => 1) unless $ua;
+ my $response = $ua->request($request);
+ return undef unless $response->is_success;
+ my $xml = $response->decoded_content;
+ spinner if $show_progress;
+ my $data = XMLin($xml);
+ $data->{Elevation_Query}->{Elevation};
+}
+
+sub compute {
+ my $gpx = shift;
+ my $offline = shift;
+ my $gx = XMLin($gpx);
+ my $name = $gx->{trk}->{name} // $gx->{name} // '';
+ my $distance = 0.0;
+ my $gps_elevation_gain = 0.0;
+ my $gps_elevation_loss = 0.0;
+ my $dem_elevation_gain = 0.0;
+ my $dem_elevation_loss = 0.0;
+ my $start_time = $gx->{trk}->{trkseg}->{trkpt}->[0]->{time};
+ my $end_time = $gx->{trk}->{trkseg}->{trkpt}->[-1]->{time};
+ my $dem_ele = 0;
+ my $count = 0;
+
+ my $prev_lat = undef;
+ my $prev_lon = undef;
+ my $prev_gps_ele = undef;
+ my $prev_dem_ele = undef;
+
+ foreach my $p (@{$gx->{trk}->{trkseg}->{trkpt}}) {
+ my ($lat, $lon) = (deg2rad($p->{lat}), deg2rad($p->{lon}));
+
+ if (defined($prev_lat) and defined($prev_lon)) {
+ $distance += lateral_distance($prev_lat, $prev_lon, $lat, $lon);
+ }
+ if (defined($prev_gps_ele)) {
+ if ($p->{ele} > $prev_gps_ele) {
+ $gps_elevation_gain += $p->{ele} - $prev_gps_ele;
+ } else {
+ $gps_elevation_loss -= $prev_gps_ele - $p->{ele};
+ }
+ }
+ unless ($offline) {
+ if (defined($prev_dem_ele)) {
+ $dem_ele = fetch_dem_elevation ($p->{lat}, $p->{lon}) // $prev_dem_ele;
+ if ($dem_ele > $prev_dem_ele) {
+ $dem_elevation_gain += $dem_ele - $prev_dem_ele;
+ } else {
+ $dem_elevation_loss -= $prev_dem_ele - $dem_ele;
+ }
+ }
+ }
+ ($prev_lat, $prev_lon, $prev_gps_ele, $prev_dem_ele) = ($lat, $lon, $p->{ele}, $dem_ele);
+ $count++;
+ }
+
+ # Convert GPS elevation to feet (DEM is already in feet)
+ $gps_elevation_gain /= 0.3048;
+ $gps_elevation_loss /= 0.3048;
+
+ return ($name, $start_time, $end_time, $distance, $gps_elevation_gain, $gps_elevation_loss, $dem_elevation_gain, $dem_elevation_loss);
+}
+
+sub elapsed_time {
+ my ($start_time, $end_time) = @_;
+ my $seconds = int (str2time ($end_time) - str2time ($start_time));
+ my $minutes = int ($seconds / 60);
+ my $hours = int ($minutes / 60);
+ $seconds %= 60;
+ $minutes %= 60;
+
+ my $h = $hours > 0 ? "${hours}h" : '';
+ my $m = $minutes > 0 ? "${minutes}m" : '';
+ my $s = $seconds > 0 ? "${seconds}s" : '';
+
+ join (' ', ($h, $m, $s));
+}
+
+sub display {
+ my ($name, $start_time, $end_time, $distance, $gps_gain, $gps_loss, $dem_gain, $dem_loss) = @_;
+
+ my $fdistance = sprintf("%.1f", $distance);
+ my $fgpsgain = sprintf("%.0f", $gps_gain);
+ my $fgpsloss = sprintf("%.0f", $gps_loss);
+ my $fdemgain = sprintf("%.0f", $dem_gain);
+ my $fdemloss = sprintf("%.0f", $dem_loss);
+
+ print <<"INFO";
+name:$name
+INFO
+ print "Start: $start_time\n" if defined $start_time;
+ print "End: $end_time\n" if defined $end_time;
+ print "Elapsed: ".elapsed_time($start_time,$end_time)."\n" if defined $start_time && defined $end_time;
+ print <<"INFO";
+Distance: $fdistance
+GPS gain: $fgpsgain
+GPS loss: $fgpsloss
+DEM gain: $fdemgain
+DEM loss: $fdemloss
+INFO
+}
+
+
+GetOptions ('exclude=s' => \$exclude,
+ 'p|progress' => \$show_progress,
+ 'offline' => \$offline,
+ 's|sum' => \$sum,
+ 'S|sum-only' => \$sum_only) or die "Usage: gpxinfo [--sum|sum-only] <gpx> [gpx...]\n";
+
+my ($distance_total, $gps_gain_total, $gps_loss_total, $dem_gain_total, $dem_loss_total) = (0.0) x 5;
+
+$| = 1 if $show_progress;
+
+foreach my $gpx (@ARGV) {
+ next if $exclude and $gpx =~ m/$exclude/;
+ print "$gpx: " if $show_progress;
+ my ($name, $start_time, $end_time, $distance, $gps_gain, $gps_loss, $dem_gain, $dem_loss) = compute ($gpx, $offline);
+ printf "\b%.0f:+%.0f:%.0f\n", $distance, $dem_gain, $dem_loss if $show_progress;
+ display ($name, $start_time, $end_time, $distance, $gps_gain, $gps_loss, $dem_gain, $dem_loss) unless $sum_only;
+ $distance_total += $distance;
+ $gps_gain_total += $gps_gain;
+ $gps_loss_total -= $gps_loss;
+ $dem_gain_total += $dem_gain;
+ $dem_loss_total -= $dem_loss;
+}
+
+display ('Total', undef, $distance_total, $gps_gain_total, $gps_loss_total, $dem_gain_total, $dem_loss_total) if $sum or $sum_only;
diff --git a/matfun/README b/matfun/README
new file mode 100644
index 0000000..482217c
--- /dev/null
+++ b/matfun/README
@@ -0,0 +1,17 @@
+In this distribution:
+
+README This file
+matfun.glb The compiled library for the G(X)
+matfun.slb The compiled library for the S(X)
+matfun.src The source code suitable for compilation with Jazz.
+matfun.h The main header file.
+matfun.hg G(X) specific header file
+matfun.hs S(X) specific header file
+matfun.txt Inadequate documentation
+
+To install:
+Download either matfun.glb or matfun.slb (depending upon what type
+of calculator you have). RCL the library to the stack and purge the
+variable it was in. Execute 0 STO and then warm start your calculator
+(press ON+C). If all is OK, it should be available in the library
+menu.
diff --git a/matfun/matfun.glb b/matfun/matfun.glb
new file mode 100644
index 0000000..5d6af97
--- /dev/null
+++ b/matfun/matfun.glb
Binary files differ
diff --git a/matfun/matfun.h b/matfun/matfun.h
new file mode 100644
index 0000000..8a10406
--- /dev/null
+++ b/matfun/matfun.h
@@ -0,0 +1,15 @@
+DEFINE FINDVAR PTR 353AB
+DEFINE C%C*R PTR 51D4C
+DEFINE C%R*C PTR 51D60
+DEFINE C%C+C PTR 51C16
+DEFINE CKRARRY PTR 194BB
+DEFINE DOARRY> PTR 1D0AB
+DEFINE C%C*C PTR 51D88
+DEFINE C%C-C PTR 51CFC
+DEFINE DOARRYPRG1 PTR 35C2C
+DEFINE MAT+ PTR 36115
+DEFINE MAT- PTR 36278
+DEFINE MATR>C PTR 36039
+DEFINE MATC>R PTR 360B6
+DEFINE MATCONJ PTR 35F30
+DEFINE MATFLOAT* PTR 362DC
diff --git a/matfun/matfun.hg b/matfun/matfun.hg
new file mode 100644
index 0000000..d0276e9
--- /dev/null
+++ b/matfun/matfun.hg
@@ -0,0 +1,3 @@
+(GX Specific)
+DEFINE SWITCHFLOATS PTR 35B47
+DEFINE MATFLOAT/ PTR 363DB
diff --git a/matfun/matfun.hs b/matfun/matfun.hs
new file mode 100644
index 0000000..03ada95
--- /dev/null
+++ b/matfun/matfun.hs
@@ -0,0 +1,3 @@
+(SX Specific)
+DEFINE SWITCHFLOATS PTR 35B4F
+DEFINE MATFLOAT/ PTR 3633C
diff --git a/matfun/matfun.slb b/matfun/matfun.slb
new file mode 100644
index 0000000..6af5526
--- /dev/null
+++ b/matfun/matfun.slb
Binary files differ
diff --git a/matfun/matfun.src b/matfun/matfun.src
new file mode 100644
index 0000000..426a6b5
--- /dev/null
+++ b/matfun/matfun.src
@@ -0,0 +1,2197 @@
+INCLUDE matfun.hgx
+INCLUDE matfun.h
+
+ASSEMBLE
+ TITLE MATFUN C 1997-98 Jon duSaint
+ STITLE Last modified 02/03/98 11:31:57A
+RPL
+
+xROMID 837
+xTITLE MATFUN A collection of useful matrix functions, 1997-98 Jon duSaint
+xCONFIG MCnfg
+
+(User Commands)
+EXTERNAL xIARR
+EXTERNAL xONES
+EXTERNAL xZEROS
+EXTERNAL x\->2D
+EXTERNAL xLENGTH
+EXTERNAL xFLIPLR
+EXTERNAL xFLIPUD
+EXTERNAL xMTXELM
+EXTERNAL xMMIN
+EXTERNAL xMMAX
+EXTERNAL xMPLOT
+EXTERNAL xMFFT
+EXTERNAL xFILTER
+EXTERNAL xCONV
+EXTERNAL xCCONV
+EXTERNAL xINTERP
+EXTERNAL xMPLUS
+EXTERNAL xMMINUS
+EXTERNAL xMMULT
+EXTERNAL xMDIV
+EXTERNAL xSINC
+EXTERNAL xMTRN
+EXTERNAL xMRL
+EXTERNAL xMRR
+EXTERNAL xMSUM
+EXTERNAL xMPROD
+
+(Internal Commands)
+EXTERNAL iarr
+EXTERNAL rdisp
+EXTERNAL ldisp
+EXTERNAL ones
+EXTERNAL zeros
+EXTERNAL ckdim
+EXTERNAL \->2d
+EXTERNAL LEN
+EXTERNAL FLIP
+EXTERNAL FFLIP
+EXTERNAL errf2
+EXTERNAL errf
+EXTERNAL min
+EXTERNAL max
+EXTERNAL MCOMP
+EXTERNAL rplot
+EXTERNAL cplot
+EXTERNAL xyrng
+EXTERNAL ddchs
+EXTERNAL get
+EXTERNAL rsinc
+EXTERNAL csinc
+EXTERNAL chk2
+EXTERNAL iconv
+EXTERNAL mplus
+EXTERNAL mcplus
+EXTERNAL plus
+EXTERNAL minus%
+EXTERNAL minusc%
+EXTERNAL %minus
+EXTERNAL cminus
+EXTERNAL m%-
+EXTERNAL mc%-
+EXTERNAL mult
+EXTERNAL div1
+EXTERNAL div
+EXTERNAL fft2
+EXTERNAL fftc
+EXTERNAL dft
+EXTERNAL isscalar
+EXTERNAL isrvec
+EXTERNAL iscvec
+EXTERNAL isarray
+EXTERNAL mtxelm
+EXTERNAL frr
+EXTERNAL frl
+EXTERNAL msum
+EXTERNAL mprod
+EXTERNAL cconv
+
+(For debugging)
+EXTERNAL dbreak
+
+LABEL MCnfg
+::
+ 837 TOSRRP
+;
+(
+* IARR
+* Create incremented array
+* %s %i %f \-> []
+* %s %f \-> []
+)
+NIBB 3 000
+sNAME IARR IARR
+::
+ CK2&Dispatch
+ 3REAL
+ ::
+ THREE NDUP ROT
+ %- SWAP %/ %0>
+ NOT_IT SETSIZEERR
+ iarr
+ ;
+ 2REAL
+ ::
+ %1 SWAP
+ IARR
+ ;
+;
+
+(
+* ONES
+* Create array of %1
+* %c \-> []
+* {%r %c} \-> []
+)
+NIBB 3 000
+sNAME ONES ONES
+::
+ CK1&Dispatch
+ ONE
+ ::
+ rdisp
+ ones
+ ;
+ FIVE
+ ::
+ ldisp
+ ones
+ ;
+;
+
+(
+* ZEROS
+* Create array of %0
+* %c \-> []
+* {%r %c} \-> []
+)
+NIBB 1 8
+sNAME ZEROS ZEROS
+::
+ CK1&Dispatch
+ ONE
+ ::
+ rdisp
+ zeros
+ ;
+ FIVE
+ ::
+ ldisp
+ zeros
+ ;
+;
+
+(
+* \->2D
+* Ensure a matrix is 2-D
+* [1-D] \-> [2-D]
+* [2-D] \-> [2-D]
+)
+NIBB 1 8
+sNAME \->2D \->2D
+::
+ CK1&Dispatch FOUR
+ \->2d
+;
+
+(
+* LENGTH
+* Size of largest dimension of
+* an array
+* [] \-> %
+)
+NIBB 1 8
+sNAME LENGTH LENGTH
+::
+ CK1&Dispatch FOUR
+ LEN
+;
+
+(
+* FLIPLR
+* Exchange all columns of
+* an array. A different algorithm
+* is used when the array is
+* 1xN and is ~10x faster
+* [] \-> []
+)
+NIBB 1 8
+sNAME FLIPLR FLIPLR
+::
+ CK1&Dispatch FOUR
+ ::
+ iscvec
+ case errf2
+ FLIP
+ ;
+;
+
+(
+* FLIPUD
+* Equivalent to TRN FLIPLR TRN
+* [] \-> []
+)
+NIBB 1 8
+sNAME FLIPUD FLIPUD
+::
+ CK1&Dispatch FOUR
+ ::
+ isrvec
+ case errf2
+ MATTRN FLIP MATTRN
+ ;
+;
+
+(
+* MTXELM
+* Apply a program or an
+* equation to each element
+* of an array
+* [] :: \-> []'
+* [] SYMB \-> []'
+)
+NIBB 1 8
+sNAME MTXELM MTXELM
+::
+ CK2&Dispatch SIXTYFOUR
+ ::
+ DUPTYPESYMB?
+ IT
+ ::
+ DUP FINDVAR
+ SWAP
+ INNERCOMP DUP
+CODE
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ B=A A
+ B=-B A
+ D1=D1+ 5
+ LA(5) =DOIDNT
+- C=DAT1 A
+ CD1EX
+ D=C A
+ C=DAT1 A
+ ?A#C A
+ GOYES +
+ LC(5) =DOLAM
+ DAT1=C A
++ C=D A
+ CD1EX
+ D1=D1+ 5
+ B=B+1 A
+ GONC -
+ GOVLNG =GETPTRLOOP
+ENDCODE
+ SYMBN
+ ' x<< SWAP
+ ' xALG-> SWAP
+ 4ROLL
+ DUPLENCOMP
+ ONE #> case
+ ::
+ DROP SWAPDROP SWAPDROP
+ DO>STR palparse DROP
+ #103 DO#EXIT
+ ;
+ ONE NTHCOMPDROP
+CODE
+ GOSBVL =SAVPTR
+ A=DAT1 A
+ D1=A
+ LA(5) =DOLAM
+ DAT1=A A
+ GOVLNG =GETPTRLOOP
+ENDCODE
+ SWAP
+ ' x>>
+ FIVE ::N
+ ;
+ DUPTYPECOL?
+ NcaseTYPEERR
+ DEPTH #2-
+ ' NULLLAM DUPDUP THREE
+ DOBIND
+ 3GETLAM TYPERARRY? ITE %1 C%1
+ 2GETLAM
+ ERRSET
+ ::
+ EVAL
+ ;
+ ERRTRAP
+ ::
+ ERROR@ DUP # 201 #=
+ SWAP # 202 #= OR ITE errf
+ ::
+ 3GETLAM 2GETLAM ABND
+ AtUserStack ERRJMP
+ ;
+ ;
+ DEPTH #1-
+ 1GETLAM #= ?SKIP
+ ::
+ DROP DEPTH 1GETLAM #-
+ NDROP errf
+ ;
+ DUPTYPEREAL? SWAP
+ TYPECMP? OR ?SKIP errf
+ 3GETLAM 2GETLAM
+ ABND
+ mtxelm
+ ;
+;
+
+(
+* MMIN
+* Columnwise minimum of an array
+* [] \-> %
+)
+NIBB 1 8
+sNAME MMIN MMIN
+::
+ CK1&Dispatch FOUR
+ min
+;
+
+(
+* MMAX
+* Columnwise maximum of an array
+* [] \-> %
+)
+NIBB 1 8
+sNAME MMAX MMAX
+::
+ CK1&Dispatch FOUR
+ max
+;
+
+(
+* MPLOT
+* Plots the columns of an array
+* in the same manner as Matlab's
+* plot routine.
+* If the array is real:
+* if Nx1 plots the array vs the
+* index
+* if Nx2 plots column 2 vs
+* column 1
+* if NxM plots column 2 vs
+* column 1, column 3 vs column
+* 1, etc
+* If complex:
+* for each column plots imag
+* vs real
+* [] \->
+)
+NIBB 1 8
+sNAME MPLOT MPLOT
+::
+ CK1&Dispatch FOUR
+ ::
+ DUP MDIMS
+ NOTcasedrop errf2
+ DROP #1=case errf2
+ DUP TYPECARRY?
+ case cplot
+ 1LAMBIND
+ 1GETLAM MDIMSDROP SWAPDROP
+ ::
+ ONE #=casedrop
+ ::
+ %1 %1 1GETLAM LEN
+ iarr
+ MATTRN 1GETLAM
+ %2 xCOL+ 1PUTLAM
+ rplot
+ ;
+ TWO #=casedrop rplot
+ ONE_DO
+ 1GETLAM %1 xCOL-
+ \->2d MATTRN SWAP
+ INDEX@ UNCOERCE
+ xCOL- SWAPDROP
+ \->2d MATTRN MATR>C
+ LOOP
+ 1GETLAM MDIMSDROP
+ SWAPDROP #1-
+ ONE_DO
+ %1 xCOL+
+ LOOP
+ cplot
+ ;
+ ABND
+ ;
+;
+
+(
+* MFFT
+* The fast fourier transform
+* of a vector. If the length
+* is a power of 2, a fast
+* radix 2 algorithm is used.
+* If the length is factorizeable,
+* a mixed radix algorithm is
+* used. If the length is
+* prime, the transform is
+* calculated from the definition
+* [] \-> []'
+)
+NIBB 1 8
+sNAME MFFT MFFT
+::
+ CK1&Dispatch FOUR
+ ::
+ isarray case errf2
+ DUP LEN COERCE
+ #1= ?SEMI
+ DUP LEN COERCE
+ TWO #=casedrop
+ ::
+ DOARRY> UNROT
+ 2DUP DUPTYPEREAL?
+ ITE
+ ::
+ %+ UNROT %-
+ ;
+ ::
+ C%C+C UNROT C%C-C
+ ;
+ ROT XEQ>ARRAY
+ ;
+ UNCOERCE
+ %LN %2 %LN %/ %FP
+ %0= case xFFT
+ dft
+ ;
+;
+
+(
+* FILTER
+* An implementation of an
+* FIR filter and an IIR
+* filter. Uses the proper
+* filter type automaticaly.
+* [] [] [] \-> [] IIR
+* [] [] % \-> [] FIR
+)
+NIBB 1 8
+sNAME FILTER FILTER
+::
+ CK3&Dispatch
+ # 441
+ ::
+
+ ;
+ # 444
+ ::
+
+ ;
+;
+
+(
+* CONV
+* Convolution and polynomial
+* multiplication
+* [] [] \-> []
+)
+NIBB 1 8
+sNAME CONV CONV
+::
+ CK2&Dispatch SIXTYEIGHT
+ ::
+ chk2
+ DUP ARSIZE 3PICK ARSIZE
+ #> IT SWAP FLIP
+ iconv
+ ;
+;
+
+(
+* CCONV
+* Circular convolution
+* [] [] \-> []
+)
+NIBB 1 8
+sNAME CCONV CCONV
+::
+ CK2&Dispatch # 44
+ ::
+ chk2
+ OVER DIMLIMITS
+ OVER DIMLIMITS
+ EQUAL NOTcase errf2
+ cconv
+ ;
+;
+
+(
+* INTERP
+* Interpolation
+* Works best for periodic
+* signals, but will still
+* work with those that are
+* aperiodic
+* [] % \-> []'
+)
+NIBB 1 8
+sNAME INTERP INTERP
+::
+ CK2&Dispatch #41
+ ::
+ DUP %1 %> OVER
+ %FP %0= AND
+ ?SKIP SETSIZEERR
+ OVER isscalar SWAP
+ isarray ROT OR
+ casedrop errf2
+ CKRARRY DROP
+ OVER MDIMS IT #*
+ OVER COERCE #*
+ 3PICK MDIMS ITE
+ ::
+ DROP #1= ITE ONESWAP ONE
+ TWO{}N
+ ;
+ ::
+ DROP ONE{}N
+ ;
+ 3PICKSWAP MATREDIM
+ %0 MATCON
+ 3PICK LEN
+ { LAM arry LAM mf
+ LAM outarry LAM N }
+ BIND
+ LAM outarry LEN COERCE
+ #1+_ONE_DO
+ %0 LAM N COERCE
+ ZERO_DO
+ INDEX@ #1+ LAM arry
+ GETATELN DROP
+ %PI INDEX@ UNCOERCE
+ JINDEX@ UNCOERCE
+ %1- LAM mf %/ %-
+ %* rsinc %* %+
+ LOOP
+ LAM outarry SWAP INDEX@
+ PUTREALEL
+ ' LAM outarry STO
+ LOOP
+ LAM outarry
+ ABND
+ ;
+;
+
+(
+* MPLUS
+* Element-wise addition
+* [] [] \-> []
+* [] % \-> []
+* % [] \-> []
+* [] C% \-> []
+* C% [] \-> []
+)
+NIBB 3 000
+sNAME MPLUS MPLUS
+::
+ CK2&Dispatch
+ # 41 mplus
+ # 42 mcplus
+ # 44 MAT+
+ TWENTY
+ ::
+ SWAP mplus
+ ;
+ THIRTYSIX
+ ::
+ SWAP mcplus
+ ;
+;
+
+(
+* MMINUS
+* Element-wise subtraction
+* Stack same as for MPLUS
+)
+NIBB 3 000
+sNAME MMINUS MMINUS
+::
+ CK2&Dispatch
+ # 41 minus%
+ # 42 minusc%
+ TWENTY %minus
+ THIRTYSIX cminus
+ # 44 MAT-
+;
+
+(
+* MMULT
+* Element-wise multiplication
+* Stack same as for MPLUS
+)
+NIBB 3 000
+sNAME MMULT MMULT
+::
+ CK2&Dispatch
+ # 41 MATFLOAT*
+ # 42 MATFLOAT*
+ TWENTY MATFLOAT*
+ THIRTYSIX MATFLOAT*
+ # 44 mult
+;
+
+(
+* MDIV
+* Element-wise division
+* Stack same as for MPLUS
+)
+NIBB 3 000
+sNAME MDIV MDIV
+::
+ CK2&Dispatch
+ # 41 MATFLOAT/
+ # 42 MATFLOAT/
+ TWENTY div1
+ THIRTYSIX div1
+ # 44 div
+;
+
+(
+* SINC
+* sin(x)/x
+* % \-> %'
+* C% \-> C%'
+* [] \-> []'
+)
+NIBB 3 000
+sNAME SINC SINC
+::
+ CK1&Dispatch
+ ONE rsinc
+ TWO csinc
+ FOUR
+ ::
+ ' ::
+ x<< ROMPTR 345 14 x>>
+ ;
+ mtxelm
+ ;
+;
+
+(
+* MTRN
+* Same as TRN except for
+* complex arrays, does not
+* take the complex conjugate
+)
+NIBB 1 8
+sNAME MTRN MTRN
+::
+ CK1&Dispatch
+ FOUR
+ ::
+ ckdim NOTcase errf2
+ MATTRN
+ MATCONJ
+ ;
+;
+
+(
+* MRL
+* Circular matrix rotation.
+* MRL rotates a vector left
+* the number of elements
+* specified.
+* [] % \-> []
+)
+NIBB 1 8
+sNAME MRL MRL
+::
+ CK2&Dispatch # 41
+ ::
+ SWAP \->2d SWAP
+ COERCE
+ frl
+ ;
+;
+
+(
+* MRR
+* Circular matrix rotation.
+* Rotates a matrix right the
+* number of elements specified
+* [] % \-> []
+)
+NIBB 1 8
+sNAME MRR MRR
+::
+ CK2&Dispatch # 41
+ ::
+ SWAP \->2d SWAP
+ COERCE
+ frr
+ ;
+;
+
+(
+* MSUM
+* The sum of all of the elements
+* in an array
+* [%] \-> %
+* [C%] \-> C%
+)
+NIBB 1 8
+sNAME MSUM MSUM
+::
+ CK1&Dispatch FOUR
+ msum
+;
+
+(
+* MPROD
+* The product of all of the
+* elements of an array.
+* Stack same as for MSUM
+)
+NIBB 1 8
+sNAME MPROD MPROD
+::
+ CK1&Dispatch FOUR
+ mprod
+;
+
+NULLNAME iarr
+::
+ TOTEMPOB ROT
+ TOTEMPOB ROT
+ TOTEMPOB ROT
+ DUP 4PICK %MAX
+ %2 %* % 1E-11 %*
+ OVER5PICK %- %SGN
+ 5PICK 5PICK 5PICK ROTSWAP
+ %- SWAP %/ %ABS %0
+ RNDXY 5PICK OVER %*
+ 7PICK %+ 5PICK %-
+ 4PICK %> IT %1-
+ 5PICK OVER %* 7PICK
+ %+ ROT OVER 6PICK
+ %- %* 4ROLL %CHS
+ %> ITE DROPSWAP ROTDROP
+ SWAP COERCE DUP#1+
+ ONESWAP TWO{}N %0
+ MAKEARRY SWAP
+CODE
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ C=A A
+ RSTK=C
+ CSRB.F A
+ RSTK=C
+ D1=D1+ 5
+ C=DAT1 A
+ CD1EX
+ D1=D1+ 5
+ A=DAT1 W
+ R4=A
+ D1=C
+ D1=D1+ 5
+ C=DAT1 A
+ CD1EX
+ D1=D1+ 5
+ A=DAT1 W
+ R3=A
+ D1=C
+ D1=D1+ 5
+ C=DAT1 A
+ CD1EX
+ D1=D1+ 5
+ A=DAT1 W
+ R2=A
+ D1=C
+ D1=D1- 15
+ A=DAT1 A
+ D1=A
+ D1=D1+ 30
+ C=RSTK
+- RSTK=C
+ A=0 W
+ A=C A
+ GOSBVL =HXDCW
+ GOSBVL =FLOAT
+ C=R3
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ GOSBVL =STAB0
+ A=R4
+ GOSBVL =SPLITA
+ GOSBVL =XYEX
+ GOSBVL =RCAB0
+ A=-A-1 S
+ GOSBVL =ADDF
+ GOSBVL =PACK
+ SETHEX
+ C=RSTK
+ D=C A
+ C=RSTK
+ RSTK=C
+ CDEX A
+ RSTK=C
+ CDEX A
+ C=C-D A
+ CSL A
+ D=C A
+ CD1EX
+ CDEX A
+ C=C+D A
+ D1=C
+ DAT1=A W
+ C=D A
+ D1=C
+ A=R2
+ GOSBVL =SPLITA
+ GOSBVL =XYEX
+ GOSBVL =RCAB0
+ GOSBVL =ADDF
+ GOSBVL =PACK
+ SETHEX
+ C=RSTK
+ RSTK=C
+ CSL A
+ D=C A
+ CD1EX
+ CDEX A
+ C=C+D A
+ D1=C
+ DAT1=A W
+ C=D A
+ D1=C
+ C=RSTK
+ C=C-1 A
+ GOC +
+ GOTO -
++ C=RSTK
+ GOVLNG =GETPTRLOOP
+ENDCODE
+ DUP LEN COERCEDUP
+ #1- ZERO #> SWAP
+ TWO #/ SWAPDROP #0=
+ AND IT
+ ::
+ 4PICK 3PICK %+ %2 %/
+ OVER LEN COERCE #2/
+ PUTEL
+ ;
+ 4UNROLL THREE NDROP
+;
+
+NULLNAME rdisp
+::
+ DUP %1 %>=
+ NcaseSIZEERR
+ COERCE ONESWAP TWO{}N
+;
+
+NULLNAME ldisp
+::
+ DUPLENCOMP TWO #<> caseSIZEERR
+ INCOMPDROP DUPTYPEREAL? 3PICK
+ TYPEREAL? AND ?SKIP
+ ::
+ TWO{}N SETSIZEERR
+ ;
+ DUP %1 %>= 3PICK %1 %>= AND
+ ?SKIP
+ ::
+ TWO{}N SETSIZEERR
+ ;
+ COERCE2 TWO{}N
+;
+
+NULLNAME ones
+::
+ %1 MAKEARRY
+;
+
+NULLNAME zeros
+::
+ %0 MAKEARRY
+;
+
+( [] \-> [] T/F )
+NULLNAME ckdim
+CODE
+ GOSBVL =SAVPTR
+ A=DAT1 A
+ D1=A
+ D1=D1+ 15
+ A=DAT1 A
+ LC(5) 1
+ ?A=C A
+ GOYES +
+ GOVLNG =GPPushTLoop
++ GOVLNG =GPPushFLoop
+ENDCODE
+
+NULLNAME \->2d
+::
+ ckdim
+ ?SEMI
+ FIVE EXPAND
+CODE
+ GOSBVL =SAVPTR
+ A=DAT1 A
+ D1=A
+ D1=D1+ 5
+ A=DAT1 A
+ LC(5) 25
+ A=A-C A
+ C=A A
+ D1=D1+ 20
+ AD1EX
+ A=A+C A
+ D1=A
+ D0=A
+ D1=D1+ 5
+ GOSBVL =MOVEUP
+ D0=D0- 10
+ LA(5) 2
+ DAT0=A A
+ D0=D0+ 5
+ A=DAT0 A
+ LC(5) 1
+ DAT0=C A
+ D0=D0+ 5
+ DAT0=A A
+ GOVLNG =GETPTRLOOP
+ENDCODE
+;
+
+NULLNAME LEN
+::
+ MDIMS IT ::
+ 2DUP #<
+ ITE SWAPDROP DROP
+ ;
+ UNCOERCE
+;
+
+NULLNAME FLIP
+::
+ TOTEMPOB
+ isscalar case errf2
+ isrvec
+ case FFLIP
+ DUP MDIMSDROP SWAPDROP
+ UNCOERCE DUP %1
+ { LAM H LAM L }
+ BIND
+ %2 %/ %0 RNDXY %1 SWAP
+ xSTART
+ LAM H LAM L xCSWP
+ %1 ' LAM L xSTO+
+ ' LAM H %1 xSTO-
+ xNEXT
+ ABND
+;
+
+NULLNAME FFLIP
+CODE
+ GOSBVL =SAVPTR
+ A=DAT1 A
+ D1=A
+ D1=D1+ 5
+ A=DAT1 A
+ LC(5) 20
+ A=A-C A
+ LC(5) =DOREAL
+ D=C A
+ D1=D1+ 5
+ C=DAT1 A
+ ST=0 0
+ ST=0 1
+ ?C=D A
+ GOYES +
+ ST=1 1
++ D1=D1+ 5
+ C=DAT1 A
+ D1=D1+ 10
+ C=C-1 A
+ C=C-1 A
+ GOC +
+ ST=1 0
+ A=A-CON A,5
+ D1=D1+ 5
++ CD1EX
+ D1=C
+ C=C+A A
+ D0=C
+ D0=D0- 16
+ ASR A
+ ASRB.F A
+ ?ST=0 1
+ GOYES +
+ ASRB.F A
+ D0=D0- 16
++ B=A A
+ B=-B A
+- A=DAT1 W
+ C=DAT0 W
+ DAT1=C W
+ DAT0=A W
+ ?ST=0 1
+ GOYES +
+ D1=D1+ 16
+ D0=D0+ 16
+ A=DAT1 W
+ C=DAT0 W
+ DAT1=C W
+ DAT0=A W
+ D0=D0- 32
++ D1=D1+ 16
+ D0=D0- 16
+ B=B+1 A
+ GONC -
+ GOVLNG =GETPTRLOOP
+ENDCODE
+
+NULLNAME errf2
+::
+ CK0NOLASTWD # 501 ERROROUT
+;
+
+NULLNAME errf
+::
+ 3GETLAM 2GETLAM
+ AtUserStack
+ ABND
+ # 103 ERROROUT
+;
+
+NULLNAME min
+::
+ %MAXREAL ' %<
+ TWO{}N
+ MCOMP
+;
+
+NULLNAME max
+::
+ %MINREAL ' %>
+ TWO{}N
+ MCOMP
+;
+
+NULLNAME MCOMP
+::
+ SWAPDUP TYPECARRY?
+ IT
+ ::
+ SWAPDROP SETSIZEERR
+ ;
+ \->2d NULLLAM DUPTWO
+ DOBIND
+ 1GETLAM MDIMSDROP
+ SWAPDROP
+ #1+_ONE_DO
+ 2GETLAM ONE NTHCOMPDROP
+ 1GETLAM MDIMSDROP DROP
+ #1+_ONE_DO
+ JINDEX@ INDEX@ #1-
+ 1GETLAM MDIMSDROP
+ SWAPDROP #* #+
+ 1GETLAM GETATELN
+ DROP 2DUP 2GETLAM
+ TWO NTHCOMPDROP EVAL
+ ITE DROP SWAPDROP
+ LOOP
+ LOOP
+ ABND
+;
+
+NULLNAME rplot
+::
+ DOERASE
+ 1GETLAM DUP min ROT max
+ ROTDUP %0>
+ ddchs
+ SWAPDUP %0<
+ ddchs
+ PUTYMAX PUTYMIN
+ DUP %0<
+ ddchs
+ SWAPDUP %0>
+ ddchs
+ PUTXMIN PUTXMAX
+ GDISPCENTER
+ TURNMENUOFF
+ 1GETLAM MDIMSDROP DROP
+ ONE_DO
+ INDEX@ #2* #1-
+ get
+ INDEX@ #2*
+ get
+ %>C%
+ INDEX@ #1+ #2* #1-
+ get
+ INDEX@ #1+ #2*
+ get
+ %>C%
+ xLINE
+ LOOP
+ xDRAX
+ xPICTURE
+;
+
+NULLNAME cplot
+::
+ DOERASE
+ DUP MDIMSDROP SWAPDROP
+ #1=case
+ ::
+ MATC>R %2 xCOL+
+ 1LAMBIND
+ rplot
+ ABND
+ ;
+ { LAM arry }
+ BIND
+ LAM arry MATC>R
+ xyrng
+ PUTYMAX PUTYMIN
+ xyrng
+ PUTXMAX PUTXMIN
+ GDISPCENTER
+ TURNMENUOFF
+ LAM arry MDIMSDROP SWAPDROP
+ #1+_ONE_DO
+ LAM arry INDEX@ UNCOERCE
+ xCOL- SWAPDROP
+ { LAM ar1 }
+ BIND
+ LAM ar1 MDIMSDROP
+ ONE_DO
+ INDEX@ LAM ar1
+ GETATELN DROP
+ INDEX@ #1+ LAM ar1
+ GETATELN DROP
+ xLINE
+ LOOP
+ ABND
+ LOOP
+ ABND
+ xDRAX
+ xPICTURE
+;
+
+NULLNAME xyrng
+::
+ DUP max
+ LAM arry MDIMSDROP SWAPDROP
+ ONE_DO
+ 2DUP %> ITE DROP SWAPDROP
+ LOOP
+ SWAP min
+ LAM arry MDIMSDROP SWAPDROP
+ ONE_DO
+ 2DUP %< ITE DROP SWAPDROP
+ LOOP
+ DUP %0> ddchs
+ SWAPDUP %0< ddchs
+;
+
+NULLNAME ddchs
+::
+ IT
+ ::
+ DROPDUP %20 %/
+ %CHS
+ ;
+;
+
+NULLNAME get
+::
+ 1GETLAM GETATELN DROP
+;
+
+NULLNAME rsinc
+::
+ %0=case
+ ::
+ DROP %1
+ ;
+ DUP %SIN SWAP %/
+;
+
+NULLNAME csinc
+::
+ DUP C%0 EQUALcase
+ ::
+ DROP C%1
+ ;
+ DUP C%SIN SWAP PTR 51EC8
+;
+
+NULLNAME chk2
+::
+ CKRARRY SWAP
+ CKRARRY SWAP
+ isscalar SWAP isarray
+ ROT OR ROT isscalar
+ SWAP isarray ROT OR
+ ROT ORcase errf2
+ \->2d SWAP \->2d
+ iscvec IT MATTRN
+ SWAP iscvec IT MATTRN
+ SWAP
+;
+
+NULLNAME iconv
+::
+ DUP LEN
+ ROTSWAP
+ COERCE DUP ROTSWAP
+ #1- SWAPCKREF
+ DUP MDIMSDROP DROP
+ #1<> IT MATTRN
+ OVER SIXTEEN #*
+ EXPAND SWAP
+CODE
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ C=DAT1 A
+ D1=C
+ D1=D1+ 5
+ C=DAT1 A
+ B=C A
+ D1=D1+ 20
+ C=DAT1 A
+ C=C+A A
+ DAT1=C A
+ D1=D1+ 5
+ ASL A
+ B=B-CON A,16
+ B=B-CON A,9
+ ABEX A
+ A=A-B A
+ C=A A
+ D=C A
+ A=A-CON A,16
+ CD1EX
+ C=C+A A
+ CD1EX
+ DSR A
+Moveel A=DAT1 W
+ C=0 W
+ DAT1=C W
+ CD1EX
+ C=C+B A
+ CD1EX
+ DAT1=A W
+ CD1EX
+ C=C-B A
+ CD1EX
+ D1=D1- 16
+ D=D-1 A
+ ?D#0 A
+ GOYES Moveel
+ GOVLNG =GETPTRLOOP
+ENDCODE
+ DUP LEN COERCE #1-
+ ROT#+ ONESWAP
+ TWO{}N MATREDIM
+ ONE OVERARSIZE
+ 4PICK ARSIZE #1- #-
+ TWO{}N %0 MAKEARRY
+ NULLLAM THREE NDUPN
+ DOBIND
+ 1GETLAM ARSIZE
+ #1+_ONE_DO
+ %%0 3GETLAM ARSIZE
+ #1+_ONE_DO
+ INDEX@ 3GETLAM
+ GETATELN DROP %>%%
+ JINDEX@ #1-
+ INDEX@ #+
+ 2GETLAM GETATELN DROP
+ %>%% %%* %%+
+ LOOP
+ %%>% 1GETLAM SWAP
+ INDEX@ PUTEL
+ 1PUTLAM
+ LOOP
+ 1GETLAM
+ ABND
+;
+
+NULLNAME mplus
+::
+ SWAPDUP
+ TYPECARRY?
+ ITE
+ ::
+ SWAP Re>C%
+ ;
+ SWAP
+ plus
+;
+
+NULLNAME mcplus
+::
+ SWAPDUP
+ TYPERARRY?
+ IT
+ ::
+ DUP %0 MATCON
+ MATR>C
+ ;
+ SWAP
+ plus
+;
+
+NULLNAME plus
+::
+ OVERSWAP
+ MATCON
+ x+
+;
+
+NULLNAME minus%
+::
+ %CHS
+ m%-
+;
+
+NULLNAME minusc%
+::
+ C%CHS
+ mc%-
+;
+
+NULLNAME %minus
+::
+ PTR 35DEB
+ SWAP m%-
+;
+
+NULLNAME cminus
+::
+ PTR 35DEB
+ SWAP mc%-
+;
+
+NULLNAME m%-
+::
+ SWAPDUP
+ TYPECARRY?
+ ITE
+ ::
+ SWAP
+ Re>C%
+ ;
+ SWAP
+ plus
+;
+
+NULLNAME mc%-
+::
+ SWAPDUP TYPERARRY?
+ IT
+ ::
+ DUP %0 MATCON
+ MATR>C
+ ;
+ SWAP plus
+;
+
+NULLNAME mult
+::
+ SWAPCKREF
+ SWAPCKREF
+ OVER \->2d DIMLIMITS
+ OVER \->2d DIMLIMITS
+ EQUAL NOTcase errf2
+ \->2d SWAP \->2d
+ OVER TYPECARRY?
+ OVER TYPECARRY?
+ OR
+ ITE
+ ::
+ DUP TYPECARRY?
+ IT SWAP
+ DUP TYPECARRY?
+ ?SKIP
+ ::
+ DUP %0 MATCON
+ MATR>C
+ ;
+ OVERARSIZE
+CODE
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ C=A A
+ A=DAT1 A
+ D0=A
+ D1=D1+ 5
+ A=DAT1 A
+ D1=A
+ D0=D0+ 30
+ D1=D1+ 30
+calcp RSTK=C
+ A=DAT1 W
+ R4=A
+ D1=D1+ 16
+ A=DAT1 W
+ R1=A
+ D1=D1- 16
+ A=DAT0 W
+ R3=A
+ D0=D0+ 16
+ A=DAT0 W
+ R2=A
+ D0=D0+ 16
+ CD0EX
+ RSTK=C
+ SETDEC
+ A=R4
+ C=R3
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ C=R1
+ R0=A
+ A=B W
+ R1=A
+ A=R2
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ C=R1
+ D=C W
+ C=R0
+ A=-A-1 S
+ GOSBVL =ADDF
+ GOSBVL =PACKSB
+ DAT1=A W
+ D1=D1+ 16
+ A=DAT1 W
+ R1=A
+ C=R3
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ R0=A
+ A=B W
+ R1=A
+ A=R4
+ C=R2
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ C=R1
+ D=C W
+ C=R0
+ GOSBVL =ADDF
+ GOSBVL =PACKSB
+ DAT1=A W
+ D1=D1+ 16
+ SETHEX
+ C=RSTK
+ CD0EX
+ C=RSTK
+ C=C-1 A
+ ?C=0 A
+ GOYES End
+ GOTO calcp
+End GOSBVL =GETPTR
+ D1=D1+ 5
+ D=D+1 A
+ GOVLNG =Loop
+ENDCODE
+ ;
+ ::
+ OVERARSIZE
+CODE
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ C=DAT1 A
+ D0=C
+ D1=D1+ 5
+ C=DAT1 A
+ D1=C
+ D0=D0+ 14
+ D1=D1+ 14
+calc R0=A
+ D0=D0+ 16
+ D1=D1+ 16
+ A=DAT1 W
+ C=DAT0 W
+ SETDEC
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ GOSBVL =PACKSB
+ SETHEX
+ DAT1=A W
+ A=R0
+ A=A-1 A
+ ?A#0 A
+ GOYES calc
+ GOSBVL =GETPTR
+ D1=D1+ 5
+ D=D+1 A
+ GOVLNG =Loop
+ENDCODE
+ ;
+;
+
+NULLNAME div1
+::
+ DUP DIMLIMITS
+ ROT MAKEARRY
+ SWAP
+ div
+;
+
+NULLNAME div
+::
+ SWAPCKREF
+ SWAPCKREF
+ OVER \->2d DIMLIMITS
+ OVER \->2d DIMLIMITS
+ EQUAL NOTcase errf2
+ \->2d SWAP \->2d SWAP
+ OVER TYPECARRY?
+ OVER TYPECARRY?
+ OR ITE
+ ::
+ DUP TYPECARRY? ITE
+ ::
+ SWAPDUP TYPERARRY? IT
+ ::
+ DUP %0 MATCON MATR>C
+ ;
+ SWAP
+ ;
+ ::
+ DUP %0 MATCON MATR>C
+ ;
+ OVERARSIZE
+CODE
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ C=DAT1 A
+ D0=C
+ D1=D1+ 5
+ C=DAT1 A
+ D1=C
+ D0=D0+ 30
+ D1=D1+ 30
+ C=A A
+qcalc RSTK=C
+ SETDEC
+ A=DAT1 W
+ R2=A
+ D1=D1+ 16
+ A=DAT0 W
+ R3=A
+ D0=D0+ 16
+ A=DAT0 W
+ R4=A
+ D0=D0- 16
+ CD0EX
+ RSTK=C
+ A=R3
+ C=A W
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ R0=A
+ A=B W
+ R1=A
+ A=R4
+ C=A W
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ C=R1
+ D=C W
+ C=R0
+ GOSBVL =ADDF
+ SETHEX
+ C=RSTK
+ CD0EX
+ C=B W
+ DAT0=C W
+ D0=D0+ 16
+ DAT0=A W
+ D0=D0- 16
+ CD0EX
+ RSTK=C
+ SETDEC
+ A=DAT1 W
+ C=R4
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ R0=A
+ A=B W
+ R1=A
+ A=R2
+ C=R3
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ C=R1
+ D=C W
+ C=R0
+ GOSBVL =ADDF
+ SETHEX
+ C=RSTK
+ CD0EX
+ C=DAT0 W
+ D=C W
+ D0=D0+ 16
+ C=DAT0 W
+ D0=D0- 16
+ R0=C
+ CD0EX
+ RSTK=C
+ SETDEC
+ C=R0
+ GOSBVL =DIVF
+ GOSBVL =PACKSB
+ D1=D1- 16
+ DAT1=A W
+ D1=D1+ 16
+ A=DAT1 W
+ C=R3
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ R0=A
+ A=B W
+ R1=A
+ A=R2
+ C=R4
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ A=-A-1 S
+ C=R1
+ D=C W
+ C=R0
+ GOSBVL =ADDF
+ SETHEX
+ C=RSTK
+ CD0EX
+ C=DAT0 W
+ D=C W
+ D0=D0+ 16
+ C=DAT0 W
+ R0=C
+ D0=D0+ 16
+ CD0EX
+ RSTK=C
+ SETDEC
+ C=R0
+ GOSBVL =DIVF
+ GOSBVL =PACKSB
+ DAT1=A W
+ D1=D1+ 16
+ SETHEX
+ C=RSTK
+ CD0EX
+ C=RSTK
+ C=C-1 A
+ ?C=0 A
+ GOYES END
+ GOTO qcalc
+END GOSBVL =GETPTR
+ D1=D1+ 5
+ D=D+1 A
+ GOVLNG =Loop
+ENDCODE
+ ;
+ ::
+ OVERARSIZE
+CODE
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ C=DAT1 A
+ D0=C
+ D1=D1+ 5
+ C=DAT1 A
+ D1=C
+ D0=D0+ 14
+ D1=D1+ 14
+calcq R0=A
+ D0=D0+ 16
+ D1=D1+ 16
+ A=DAT1 W
+ C=DAT0 W
+ SETDEC
+ GOSBVL =SPLTAC
+ GOSBVL =DIVF
+ GOSBVL =PACKSB
+ SETHEX
+ DAT1=A W
+ A=R0
+ A=A-1 A
+ ?A#0 A
+ GOYES calcq
+ GOSBVL =GETPTR
+ D1=D1+ 5
+ D=D+1 A
+ GOVLNG =Loop
+ENDCODE
+ ;
+;
+
+NULLNAME fft2
+::
+
+;
+
+NULLNAME fftc
+::
+
+;
+
+NULLNAME dft
+::
+ DUP DIMLIMITS C%0 MAKEARRY
+ NULL$TEMP 128
+ EXPAND %%2PI %%CHS 3PICK
+ LEN %>%% %%/
+CODE
+ GOSBVL #2A060 * POP1%% *
+ SETHEX
+ GOSBVL =D1=DSKTOP
+ C=DAT1 A
+ D1=C
+ D1=D1+ 26
+ DAT1=A W
+ D1=D1- 16
+ A=B W
+ DAT1=A W
+ GOVLNG =GETPTRLOOP
+ENDCODE
+ 3PICK TYPERARRY?
+CODE
+ ST=0 0
+ ST=0 4
+ ST=1 9
+ GOSBVL =popflag
+ GOC Real
+ GOTO Cmp
+Real GOSBVL =SAVPTR
+ D1=D1+ 5
+ A=DAT1 A
+ D1=A
+ D1=D1+ 5
+ C=DAT1 A
+ LA(5) 25
+ C=C-A A
+ CSR A
+ CSRB.F A
+ C=C-1 A
+ RSTK=C
+ C=0 A
+ GOSUB putn
+ GOSUB putk
+rkloop C=0 W
+ GOSUB D0\->R0
+ DAT0=C W
+ D0=D0+ 16
+ DAT0=C W
+ R2=C
+ R3=C
+rnloop GOSUB getn
+ GOSUB GetInd
+ C=A W
+ D=C W
+ SETHEX
+ GOSUB getk
+ GOSUB GetInd
+ C=D W
+ GOSBVL =SPLTAC
+ GOSBVL =MULTF
+ P= 0
+ GOSBVL =D1=DSKTOP
+ C=DAT1 A
+ D1=C
+ D1=D1+ 10
+ C=DAT1 W
+ D=C W
+ D1=D1+ 16
+ C=DAT1 W
+ GOSBVL =MULTF
+ P= 0
+ SETHEX
+ GOSUB pbuff
+ DAT1=A W
+ D1=D1+ 16
+ C=B W
+ DAT1=C W
+ SETDEC
+ GOSBVL #79664
+ P= 0
+ SETHEX
+ GOSUB x*W
+ SETHEX
+ GOSUB D0\->R1
+ C=DAT0 W
+ D=C W
+ D0=D0- 16
+ C=DAT0 W
+ SETDEC
+ GOSBVL =ADDF
+ SETHEX
+ P= 0
+ GOSUB D0\->R0
+ DAT0=A W
+ A=B W
+ D0=D0+ 16
+ DAT0=A W
+ GOSUB pbuff
+ A=DAT1 W
+ D1=D1+ 16
+ C=DAT1 W
+ B=C W
+ SETDEC
+ GOSBVL #7965D
+ P= 0
+ SETHEX
+ GOSUB x*W
+ C=R3
+ D=C W
+ C=R2
+ GOSBVL =ADDF
+ P= 0
+ R2=A
+ A=B W
+ R3=A
+ SETHEX
+ C=RSTK
+ RSTK=C
+ A=C A
+ GOSUB getn
+ ?A=C A
+ GOYES +
+ C=C+1 A
+ GOSUB putn
+ GOTO rnloop
++ GOSBVL =D1=DSKTOP
+ D1=D1+ 5
+ A=DAT1 A
+ GOSUB getk
+ CSL A
+ C=C+C A
+ A=A+C A
+ LC(5) 30
+ A=A+C A
+ D1=A
+ GOSUB D0\->R0
+ A=DAT0 W
+ D0=D0+ 16
+ C=DAT0 W
+ B=C W
+ SETDEC
+ GOSBVL =PACK
+ SETHEX
+ DAT1=A W
+ D1=D1+ 16
+ A=R2
+ C=R3
+ B=C W
+ SETDEC
+ GOSBVL =PACK
+ SETHEX
+ ?A=0 W
+ GOYES +
+ ST=1 0
++ DAT1=A W
+ C=RSTK
+ RSTK=C
+ A=C A
+ GOSUB getk
+ ?A=C A
+ GOYES +
+ C=C+1 A
+ GOSUB putk
+ C=0 A
+ GOSUB putn
+ GOTO rkloop
++ C=RSTK
+ ?ST=0 0
+ GOYES +
+ GOVLNG =GPPushFLoop
++ GOVLNG =GPPushTLoop
+Cmp GOSBVL =SAVPTR
+
+ GOVLNG =GPPushTLoop
+
+GetInd P= 0
+ A=0 W
+ A=C A
+ GOSBVL =HXDCW
+ GOVLNG =FLOAT
+
+pbuff P= 0
+ LC(5) 42
+ D=C A
+ GOSBVL =D1=DSKTOP
+ C=DAT1 A
+ C=C+D A
+ D1=C
+ RTN
+
+x*W GOSUB pbuff
+ LC(5) 32
+ D=C A
+ CD1EX
+ C=C+D A
+ D1=C
+ DAT1=A W
+ D1=D1+ 16
+ C=B W
+ DAT1=C W
+ GOSBVL =D1=DSKTOP
+ D1=D1+ 10
+ A=DAT1 A
+ GOSUB getn
+ CSL A
+ A=A+C A
+ LC(5) 30
+ A=A+C A
+ D1=A
+ A=DAT1 W
+ SETDEC
+ GOSBVL =SPLITA
+ SETHEX
+ GOSUB pbuff
+ LC(5) 48
+ D=C A
+ CD1EX
+ C=C+D A
+ D1=C
+ C=DAT1 W
+ D=C W
+ D1=D1- 16
+ C=DAT1 W
+ SETDEC
+ GOSBVL =MULTF
+ P= 0
+ RTN
+
+getn C=R4
+ RTN
+
+putn R4=C
+ RTN
+
+getk C=R4
+ CSR W
+ CSR W
+ CSR W
+ CSR W
+ CSR W
+ SB=0
+ RTN
+
+putk CSL W
+ CSL W
+ CSL W
+ CSL W
+ CSL W
+ SB=0
+ C=R4.F A
+ R4=C
+ RTN
+
+D0\->R0 R0=A
+ R1=C
+ GOSBVL =D0=DSKTOP
+ A=DAT0 A
+ LC(5) 106
+ A=A+C A
+ D0=A
+ A=R0
+ C=R1
+ RTN
+
+D0\->R1 R0=A
+ R1=C
+ GOSBVL =D0=DSKTOP
+ A=DAT0 A
+ LC(5) 122
+ A=A+C A
+ D0=A
+ A=R0
+ C=R1
+ RTN
+ENDCODE
+ SWAPDROP ROTDROP
+ IT xRE
+;
+
+NULLNAME isscalar
+::
+ DUP MDIMS ITE
+ ::
+ #1= SWAP #1= AND
+ ;
+ #1=
+;
+
+NULLNAME isrvec
+::
+ DUP MDIMS ITE
+ ::
+ DROP #1=
+ ;
+ DROPTRUE
+;
+
+NULLNAME iscvec
+::
+ DUP MDIMS ITE
+ ::
+ SWAPDROP #1=
+ ;
+ DROPFALSE
+;
+
+NULLNAME isarray
+::
+ DUP MDIMS ITE
+ ::
+ #1<> SWAP #1<> AND
+ ;
+ DROPFALSE
+;
+
+NULLNAME mtxelm
+::
+ SWAP TOTEMPOB SWAP
+ INNERCOMP
+ '
+ ::
+ SWITCHFLOATS
+ NOP
+ NOP
+ %%>%
+ C%%>C%
+ ;
+ OVER #1+UNROLL
+ #1+ ::N
+ SWAP
+ DOARRYPRG1
+;
+
+NULLNAME frr
+::
+ SWAP TOTEMPOB SWAP
+ DUP #0=case DROP
+CODE
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ C=A A
+ A=DAT1 A
+ D1=A
+ D1=D1+ 5
+ A=DAT1 A
+ D1=D1+ 5
+ D=C A
+ D=-D A
+ LC(5) 25
+ A=A-C A
+ B=A A
+ LC(5) =DOREAL
+ ST=0 0
+ A=DAT1 A
+ ?A=C A
+ GOYES +
+ ST=1 0
++ D1=D1+ 20
+ LC(5) 16
+ ?ST=0 0
+ GOYES +
+ C=C-CON A,16
++ B=B-C A
+ CD1EX
+ D1=C
+ R0=C
+ C=C+B A
+ R1=C
+ C=C+CON A,16
+ ?ST=0 0
+ GOYES +
+ C=C+CON A,16
++ R2=C
+- C=R1
+ D0=C
+ C=DAT0 W
+ R3=C
+ ?ST=0 0
+ GOYES +
+ D0=D0+ 16
+ C=DAT0 W
+ R4=C
+ D0=D0- 16
++ C=R2
+ D1=C
+ C=B A
+ GOSBVL =MOVEUP
+ C=R0
+ D1=C
+ C=R3
+ DAT1=C W
+ ?ST=0 0
+ GOYES +
+ D1=D1+ 16
+ C=R4
+ DAT1=C W
++ D=D+1 A
+ GONC -
+ GOVLNG =GETPTRLOOP
+ENDCODE
+;
+
+NULLNAME frl
+::
+ OVERARSIZE SWAP #-
+ frr
+;
+
+NULLNAME msum
+::
+ isscalar case
+ ::
+ ONESWAP GETATELN DROP
+ ;
+ \->2d DOARRY> ldisp
+ INCOMPDROP #*
+ OVER TYPEREAL? ITE
+ ::
+ ONE_DO
+ %+
+ LOOP
+ ;
+ ::
+ ONE_DO
+ C%C+C
+ LOOP
+ ;
+;
+
+NULLNAME mprod
+::
+ isscalar case
+ ::
+ ONESWAP GETATELN DROP
+ ;
+ \->2d DOARRY> ldisp
+ INCOMPDROP #*
+ OVER TYPEREAL? ITE
+ ::
+ ONE_DO
+ %*
+ LOOP
+ ;
+ ::
+ ONE_DO
+ C%C*C
+ LOOP
+ ;
+;
+
+NULLNAME cconv
+::
+ DUP DIMLIMITS %0 MAKEARRY
+ NULLLAM THREE NDUPN DOBIND
+ 1GETLAM ARSIZE
+ #1+_ONE_DO
+ 1GETLAM 3GETLAM 2GETLAM
+ mult msum
+ INDEX@ PUTEL 1PUTLAM
+ 2GETLAM ONE frr 2PUTLAM
+ LOOP
+ 1GETABND
+;
+
+NULLNAME dbreak
+::
+ # 123 DO#EXIT
+;
diff --git a/matfun/matfun.txt b/matfun/matfun.txt
new file mode 100644
index 0000000..324c11a
--- /dev/null
+++ b/matfun/matfun.txt
@@ -0,0 +1,164 @@
+MATFUN v2 beta 1
+by Jonathan duSaint
+jon@wpi.edu
+jdusaint@mathworks.com
+
+Disclaimer: This is a beta release and as such, some bugs
+may exist which can cause a severe crash (however unlikely).
+
+Please email me at either of the above addresses with
+suggestions, comments, questions, bug reports, bug fixes,
+etc.
+
+For slightly better documentation, read the source code. All user
+level functions are prefixed with a block explaining the
+functionality. On Windows, it is best viewed in wordpad, and
+on Unix, any editor will work (I use emacs). I don't know about
+the Mac (sorry!).
+
+Matfun is a collection of very useful matrix oriented functions.
+Stack diagrams will be shown as:
+ 3 2 1 -> 3 2 1
+Various symbols are used:
+% real number
+C% complex number
+[] array
+:: program
+
+IARR
+ %s %i %f -> []
+This program creates an incremented array from %s to %f in
+steps of %i.
+For example:
+0 .1 1 <IARR> -> [[ 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1 ]]
+The stepsize can also be negative:
+1 -.1 0 <IARR> -> [[ 1 .9 .8 .7 .6 .5 .4 .3 .2 .1 0 ]]
+
+->2D
+[2d] -> [2d]
+[1d] -> [2d]
+This program turns a one dimensional vector into a two dimensional
+array without changing the elements. If a two dimensional array is
+entered, it will be unchanged.
+
+LENGTH
+[] -> %
+Returns the length of an array.
+
+FLIPLR
+[] -> []'
+Flips an array from left to right.
+
+FLIPUD
+[] -> []'
+Flips an array upside down.
+
+MTXELM
+[] :: -> []'
+Applies a program to each element of an array. The program should
+take one real or complex argument and return one real or
+complex argument. Errors for invalid programs.
+
+MMIN
+[] -> % ... %
+Returns the smallest element of each column of an array.
+
+MMAX
+[] -> % ... %
+Returns the largest element of each column of an array.
+
+MPLOT
+[] ->
+This program plots an array columnwise. For an Nx1 real array,
+the elements are plotted versus their indices. For an Nx2
+real array, column two is plotted versus column one, For an NxM
+real array, columns two through M are plotted individually versus
+column one. For an Nx1 complex array, the plot is of imag versus
+real. For an NxM complex array, the plot is imag versus real for
+each column of the array.
+
+CONV
+[] [] -> []'
+Convolution. This program convolves the two arrays with each
+other. A practical application of which is polynomial multiplication. For example, the two equations x-1 and x+1 can be represented
+by [1 -1] and [1 1]. Convolving these two vectors returns
+[1 0 -1], or x^2-1 which is (x-1)(x+1).
+
+INTERP
+[] % -> []'
+Interpolation. This program interpolates the input array to
+be % times larger.
+
+MPLUS
+[] [] -> []
+[] % -> []
+% [] -> []
+[] C% -> []
+C% [] -> []
+Matrix addition.
+
+MMINUS
+Stack same as MPLUS
+Matrix subtraction.
+
+MMULT
+Stack same as for MPLUS
+Matrix multiplication.
+
+MDIV
+Stack same as for MPLUS
+Matrix division.
+
+All four of the above commands are element by element operations.
+
+MTRN
+[] -> []
+Matrix transposition, but the complex conjugate is not taken.
+
+SINC
+% -> %'
+C% -> C%'
+[] -> []'
+The sinc function is sin(x)/x. This function find the sinc of
+real numbers, complex numbers, and the elements of arrays, real
+or complex.
+
+
+New in this beta:
+ONES
+ % -> []
+{ % % } -> []
+Creates a vector of ones
+
+ZEROS
+Same as ones, but creates a vector of zeros.
+
+CCONV
+[] [] -> []'
+Circular convolution
+
+MFFT
+[] -> []
+This still has a long way to go before it is fully functional. As
+of this release, it only performs the DFT on real vectors. It is,
+however, useful for arbitrary length real vectors.
+
+FILTER
+This doesn't do anything yet. Someday it will implement both a FIR
+and an IIR filter.
+
+MRL
+[] -> []
+Rotates a vector left one element.
+
+MRR
+[] -> []
+Rotates a vector right one element.
+
+MSUM
+[] -> %
+The sum of all of the elements in a matrix.
+
+MPROD
+[] -> %
+The product of all of the elements in a matrix.
diff --git a/matops/matops.pm b/matops/matops.pm
new file mode 100644
index 0000000..ef9d147
--- /dev/null
+++ b/matops/matops.pm
@@ -0,0 +1,2625 @@
+#!/usr/bin/perl
+#
+# matops.pm --
+#
+# Matrix operations. This module implements a vectorized
+# Matlab-esque language to be used from Perl scripts.
+#
+
+use strict;
+use warnings;
+
+package matops;
+
+use Carp;
+use Data::Dumper;
+
+sub RunScript;
+sub Compile;
+
+require Exporter;
+our @ISA = ('Exporter');
+our @EXPORT = qw(&RunScript &Compile);
+
+my $debug = 0;
+
+
+############################################################################
+#
+
+sub Debug {
+ return unless $debug;
+
+ print $_[0];
+}
+
+
+############################################################################
+#
+
+my @environments = ();
+my @symbolTables = ();
+my $currentEnvironment;
+
+my %functions = (length => \&DoLength,
+ sum => \&DoSum,
+ min => \&DoMin,
+ max => \&DoMax,
+ sort => \&DoSort,
+ int => \&DoInt,
+ abs => \&DoAbs,
+ diff => \&DoDiff,
+ flip => \&DoFlip,
+ sqrt => \&DoSqrt,
+ ones => \&DoOnes,
+ zeros => \&DoZeros,
+ rand => \&DoRand,
+ all => \&DoAll,
+ any => \&DoAny,
+ sin => \&DoSin,
+ cos => \&DoCos,
+ tan => \&DoTan,
+ error => \&DoError,
+ disp => \&DoDisp,
+ save => \&DoSave);
+my @userFunctions = ();
+
+
+############################################################################
+#
+
+sub DeepCopy {
+ my $this = shift;
+ if (not ref $this) {
+ $this;
+ } elsif (ref $this eq "ARRAY") {
+ [map DeepCopy($_), @$this];
+ } elsif (ref $this eq "HASH") {
+ +{map { $_ => DeepCopy($this->{$_}) } keys %$this};
+ } else {
+ croak "what type is $_?" . Backtrace();
+ }
+}
+
+
+############################################################################
+#
+# Error --
+#
+# Error handling. Call die with the error message passed in and
+# the line and column position of the error. This has the effect
+# of unwinding the stack back to RunScript() (which then has the
+# job of reporting the error to the user).
+#
+
+sub Error {
+ my ($msg, $token) = @_;
+
+ croak <<"ERROR";
+Error:$$token[3]:$$token[4]: $msg
+ERROR
+}
+
+
+sub Backtrace {
+ my $unwind = '';
+ my $frame = 0;
+
+ my ($package, $file, $line, $sub);
+
+ while (1) {
+ my ($package, $file, $line) = caller($frame);
+ my $thisFrame = sprintf("\n %3d: $file:$line in ", $frame);
+ ($package, $file, $line, $sub) = caller($frame + 1);
+
+ if (not defined($sub)) {
+ $unwind = "$thisFrame(toplevel)$unwind";
+ last;
+ } else {
+ $unwind = "$thisFrame$sub$unwind";
+ }
+ $frame++;
+ }
+
+ return "\n==================== Backtrace ====================$unwind\n"
+}
+
+
+
+############################################################################
+#
+# Various utilities --
+#
+
+sub IdentName {
+ my $t = shift;
+
+ if (!ref($t)) {
+ print Dumper $t;
+ croak q(Yo! $t isn't a ref) . Backtrace();
+ }
+ if ($t->[0] ne 'IDENT') {
+ croak "Token is of type $t->[0], not IDENT!";
+ }
+
+ return $t->[1];
+}
+
+
+############################################################################
+#
+# Lexical analysis --
+#
+# Interface to lexical analyzer is provided by these four functions:
+#
+# Pushback
+# Peek
+# Match
+# Expect
+#
+############################################################################
+
+no warnings 'qw';
+
+my %tokens = qw$NUMBER (?:[0-9]*\\.[0-9]+|[0-9]+)(?:[eE]-?[0-9]+)?
+ IDENT [A-Za-z_][A-Za-z0-9_]*
+ STRING '(?:[^'\\n]|\\')*?'
+ LBRACK \\[
+ RBRACK \\]
+ LPAREN \\(
+ RPAREN \\)
+ COLON :
+ PLUS \\+
+ MINUS -
+ TIMES \\*
+ DIVIDE /
+ MODULO %
+ EXP \\^
+ AND &
+ OR \\|
+ EQ ==
+ NE ~=
+ LE <=
+ LT <
+ GE >=
+ GT >
+ NOT ~
+ ASSIGN =
+ NL (?:\\n|;)
+ COMMA ,
+ VARS vars:$;
+
+my %keywords = qw$IF if
+ ELIF elif
+ ELSE else
+ ENDIF endif
+ DEFUN defun
+ ENDFUN endfun
+ WHILE while
+ NEXT next$;
+
+## Global state (no, this isn't a reentrant parser).
+
+my @tokenList = ();
+my $line = 1;
+my $pos = 0;
+
+
+############################################################################
+#
+# Token --
+#
+# Get the next token from the input. This function is not
+# intended to be called by the parser.
+#
+# The returned token is in the form:
+#
+# (symbol, token, nextTokenPos)
+#
+
+sub Token {
+ my $s = shift;
+
+ unless (length($$s)) {
+ return ('END', '', 0);
+ }
+
+ # XXX: This currently returns the first token to match, but it
+ # should return instead the longest valid match.
+ foreach my $sym (keys(%tokens)) {
+ my $re = $tokens{$sym};
+
+ if ($$s =~ m/^([ \t]*)($re)([ \t]*)(.*)/s) {
+ my ($token, $rest) = ($2, $4);
+
+ if ($sym eq 'IDENT') {
+ # Check for keywords
+ foreach my $kw (keys(%keywords)) {
+ if ($token eq $keywords{$kw}) {
+ $sym = $kw;
+ last;
+ }
+ }
+ }
+
+ $$s = $4;
+ return ($sym, $token, length($1)+length($2)+length($3));
+ }
+ }
+
+ Error('Unrecognized character', [undef, undef, length($$s), $line, $pos]);
+}
+
+
+############################################################################
+#
+# Pushback --
+#
+# Push the provided token back. It will then be the next token
+# returned by Peek or Expect.
+#
+
+sub Pushback {
+ my $token = $_[0];
+
+ push @tokenList, $token;
+}
+
+
+############################################################################
+#
+# Peek --
+#
+# Return the top token on the stack without popping it. Used for
+# lookahead.
+#
+
+sub Peek {
+ my $expr = $_[0];
+
+ if (@tokenList == 0) {
+ push @tokenList, [Token($expr), $line, $pos];
+
+ if ($tokenList[-1][0] eq 'NL') {
+ $tokenList[-1][1] = ''; # for debugging
+ $line++;
+ $pos = 0;
+ }
+
+ Debug("type $tokenList[-1][0] token: <$tokenList[-1][1]>\n");
+ }
+
+ return $tokenList[-1];
+}
+
+
+############################################################################
+#
+# Match --
+#
+# Determine if the provided token matches the expected symbol
+# type.
+#
+
+sub Match {
+ my ($token, $match) = @_;
+
+ return defined($$token[0]) && $$token[0] eq $match;
+}
+
+
+############################################################################
+#
+# Expect --
+#
+# Pop the next symbol off the stack (or retrieve it from the
+# lexer), compare it with the expected symbol type, and, if it
+# matches, return it. If it doesn't match, throw an error.
+#
+
+sub Expect {
+ if (@_ != 2) {
+ croak "Hey dumbo! Expect takes two args.\n" . Backtrace();
+ }
+
+ my ($expr, $match) = @_;
+
+ my $token;
+
+ if (@tokenList) {
+ $token = pop @tokenList;
+ } else {
+ $token = [Token($expr), $line, $pos];
+
+ if ($$token[0] eq 'NL') {
+ $$token[1] = ''; # for debugging
+ $line++;
+ $pos = 0;
+ }
+
+ Debug("type $$token[0] token: <$$token[1]>\n");
+ }
+
+ if (Match($token, $match)) {
+ $pos += $$token[2];
+ return $token;
+ }
+
+ Error("expected $match token but found $$token[0]", $token);
+}
+
+
+############################################################################
+#
+# Parser --
+#
+# This grammar is implemented as an LL(2) parser.
+#
+############################################################################
+
+
+############################################################################
+#
+# varlist : IDENT
+# | IDENT COMMA varlist
+#
+
+sub varlist {
+ my $expr = $_[0];
+
+ my $token = Expect($expr, 'IDENT');
+ my $tree = [$token];
+
+ if (Match(Peek($expr), 'COMMA')) {
+ Expect($expr, 'COMMA');
+ push @$tree, @{varlist($expr)};
+ }
+
+ return $tree;
+}
+
+
+############################################################################
+#
+# vardecl : VARS varlist NL
+#
+
+sub vardecl {
+ my $expr = $_[0];
+
+ my $tree = ['VARDECL'];
+
+ Expect($expr, 'VARS');
+ push @$tree, @{varlist($expr)};
+ Expect($expr, 'NL');
+
+ return $tree;
+}
+
+
+############################################################################
+#
+# arrexpr : IDENT LBRACK expr RBRACK
+#
+
+sub arrexpr {
+ my $expr = $_[0];
+
+ my $token = Expect($expr, 'IDENT');
+
+ my @tree = ('ARREXPR', $token);
+
+ Expect($expr, 'LBRACK');
+ push @tree, expr($expr);
+ Expect($expr, 'RBRACK');
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# array_list :
+# | expr
+# | expr COMMA array_list
+#
+
+sub array_list {
+ my $expr = $_[0];
+
+ my @tree = (expr($expr));
+
+ while (Match(Peek($expr), 'COMMA')) {
+ Expect($expr, 'COMMA');
+ push @tree, @{array_list($expr)};
+ }
+
+ return \@tree;
+}
+
+
+
+############################################################################
+#
+# array : LBRACK array_list RBRACK
+#
+
+sub array {
+ my $expr = $_[0];
+
+ my @tree = ('ARRAY');;
+
+ Expect($expr, 'LBRACK');
+ if (!Match(Peek($expr), 'RBRACK')) {
+ push @tree, @{array_list($expr)};
+ }
+ Expect($expr, 'RBRACK');
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# funargs :
+# | expr
+# | expr COMMA funargs
+#
+
+sub funargs {
+ my $expr = $_[0];
+
+ my @args = ();
+
+ while (1) {
+ push @args, expr($expr);
+
+ if (not Match(Peek($expr), 'COMMA')) {
+ last;
+ }
+
+ Expect($expr, 'COMMA');
+ }
+
+ return \@args;
+}
+
+
+############################################################################
+#
+# funcall : IDENT LPAREN funargs RPAREN
+#
+
+sub funcall {
+ my $expr = $_[0];
+
+ my $token = Expect($expr, 'IDENT');
+ my @tree = ('FUNCALL', $token);
+
+ Expect($expr, 'LPAREN');
+ if (not Match(Peek($expr), 'RPAREN')) {
+ my $args;
+ $args = funargs($expr);
+ if (@$args) {
+ push @tree, @$args;
+ }
+ }
+ Expect($expr, 'RPAREN');
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# uniexpr : IDENT
+# | NUMBER
+# | arrexpr
+# | array
+# | funcall
+# | LPAREN expr RPAREN
+# | MINUS uniexpr
+# | PLUS uniexpr
+# | NOT uniexpr
+#
+
+sub uniexpr {
+ my $expr = $_[0];
+
+ my $tree = [];
+ my $token = Peek($expr);
+
+ if (Match($token, 'MINUS')) {
+ $token = Expect($expr, 'MINUS');
+ $tree = ['UNIEXPR', $token, uniexpr($expr)];
+
+ } elsif(Match($token, 'PLUS')) {
+ $token = Expect($expr, 'PLUS');
+ $tree = ['UNIEXPR', $token, uniexpr($expr)];
+
+ } elsif(Match($token, 'NOT')) {
+ $token = Expect($expr, 'NOT');
+ $tree = ['UNIEXPR', $token, uniexpr($expr)];
+
+ } elsif (Match($token, 'IDENT')) {
+ # IDENT, TERMINAL, or arrexpr
+
+ $token = Expect($expr, 'IDENT');
+
+ if (Match(Peek($expr), 'LPAREN')) {
+ Pushback($token);
+ $tree = funcall($expr);
+
+ } elsif (Match(Peek($expr), 'LBRACK')) {
+ Pushback($token);
+ $tree = arrexpr($expr);
+
+ } else {
+ # IDENT
+ $tree = ['TERMINAL', $token];
+
+ }
+
+ } elsif (Match($token, 'NUMBER')) {
+ # NUMBER
+ $tree = ['TERMINAL', Expect($expr, 'NUMBER')];
+
+ } elsif (Match($token, 'LPAREN')) {
+ Expect($expr, 'LPAREN');
+ $tree = ['UNIEXPR', expr($expr)];
+ Expect($expr, 'RPAREN');
+
+ } elsif (Match($token, 'LBRACK')) {
+ $tree = array($expr);
+
+ } else {
+ Error('missing expression', $token);
+ }
+
+ return $tree;
+}
+
+############################################################################
+#
+# expr : uniexpr
+# | uniexpr EXP expr
+# | uniexpr TIMES expr
+# | uniexpr DIVIDE expr
+# | uniexpr MODULO expr
+# | uniexpr PLUS expr
+# | uniexpr MINUS expr
+# | uniexpr AND expr
+# | uniexpr OR expr
+# | uniexpr EQ expr
+# | uniexpr NE expr
+# | uniexpr LT expr
+# | uniexpr LE expr
+# | uniexpr GT expr
+# | uniexpr GE expr
+#
+
+# Operator precedence:
+#
+# 11: f(...) function call postfix ltr
+# 10: ~ logical not unary rtl
+# 9: - + negation, plus unary rtl
+# 8: ^ exponentiation binary rtl
+# 7: * / % multiplicative binary ltr
+# 6: + - additive binary ltr
+# 5: < > <= >= relational binary ltr
+# 4: == ~= equality binary ltr
+# 3: & logical and binary ltr
+# 2: | logical or binary ltr
+# 1: : colon operator binary/trinary ltr
+#
+# Precedence levels 11, 10, and 9 are handled by uniexpr().
+#
+
+my %precedence = (EXP => 8,
+ TIMES => 7,
+ DIVIDE => 7,
+ MODULO => 7,
+ PLUS => 6,
+ MINUS => 6,
+ LT => 5,
+ GT => 5,
+ LE => 5,
+ GE => 5,
+ EQ => 4,
+ NE => 4,
+ AND => 3,
+ OR => 2,
+ COLON => 1);
+
+sub Precedence {
+ my $op = $_[0];
+
+ return $precedence{$op->[0]};
+}
+
+sub Assoc {
+ my $op = $_[0];
+
+ if ($op->[0] eq 'EXP') {
+ # ~ and unary +- are handled in uniexpr()
+ return 'RTL';
+ } else {
+ return 'LTR';
+ }
+}
+
+
+sub expr {
+ my $expr = $_[0];
+
+ my $left = uniexpr($expr);
+ my $op;
+ my $right;
+
+ expr_loop:
+ $op = Peek($expr);
+
+ if (Match($op, 'EQ')) {
+ $op = Expect($expr, 'EQ');
+ } elsif (Match($op, 'NE')) {
+ $op = Expect($expr, 'NE');
+ } elsif (Match($op, 'LT')) {
+ $op = Expect($expr, 'LT');
+ } elsif (Match($op, 'LE')) {
+ $op = Expect($expr, 'LE');
+ } elsif (Match($op, 'GT')) {
+ $op = Expect($expr, 'GT');
+ } elsif (Match($op, 'GE')) {
+ $op = Expect($expr, 'GE');
+ } elsif (Match($op, 'AND')) {
+ $op = Expect($expr, 'AND');
+ } elsif (Match($op, 'OR')) {
+ $op = Expect($expr, 'OR');
+ } elsif (Match($op, 'PLUS')) {
+ $op = Expect($expr, 'PLUS');
+ } elsif (Match($op, 'MINUS')) {
+ $op = Expect($expr, 'MINUS');
+ } elsif (Match($op, 'TIMES')) {
+ $op = Expect($expr, 'TIMES');
+ } elsif (Match($op, 'DIVIDE')) {
+ $op = Expect($expr, 'DIVIDE');
+ } elsif (Match($op, 'MODULO')) {
+ $op = Expect($expr, 'MODULO');
+ } elsif (Match($op, 'EXP')) {
+ $op = Expect($expr, 'EXP');
+ } elsif (Match($op, 'COLON')) {
+ $op = Expect($expr, 'COLON');
+ } else {
+ # Done with expr
+
+ # Special case for x:y:z - flatten the tree somewhat.
+ if (@$left > 1 and
+ $left->[1]->[0] eq 'COLON' and
+ $left->[2]->[0] eq 'EXPR' and
+ $left->[2]->[1]->[0] eq 'COLON') {
+
+ $left = [$left->[0],
+ $left->[1],
+ $left->[2]->[2],
+ $left->[2]->[3],
+ $left->[3]];
+ }
+
+ return $left;
+ }
+
+ $right = expr($expr);
+
+ if ($right->[0] ne 'EXPR') {
+ $left = ['EXPR', $op, $left, $right];
+ } else {
+ my $rop = $right->[1];
+
+ my ($pl, $pr) = (Precedence($op), Precedence($rop));
+
+ if ($pl < $pr || ($pl == $pr && Assoc($op) eq 'RTL')) {
+ $left = ['EXPR', $op, $left, $right];
+ } else {
+ $left = ['EXPR',
+ $right->[1],
+ ['EXPR', $op, $left, $right->[2]],
+ $right->[3]];
+ }
+ }
+
+ $op = undef;
+ $right = undef;
+ goto expr_loop;
+}
+
+
+############################################################################
+#
+# str : STRING
+# | expr
+
+sub str {
+ my $expr = $_[0];
+
+ my $token = Peek($expr);
+ if (Match($token, 'STRING')) {
+ $token = Expect($expr, 'STRING');
+ } else {
+ $token = expr($expr);
+ }
+
+ return $token;
+}
+
+
+############################################################################
+#
+# strs : str
+# | str COMMA strs
+#
+
+sub strs {
+ my $expr = $_[0];
+
+ my @tree = ();
+
+ while (1) {
+ push @tree, str($expr);
+
+ last if not Match(Peek($expr), 'COMMA');
+ Expect($expr, 'COMMA');
+ }
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# proc_stmnt : IDENT LPAREN strs RPAREN
+#
+
+sub proc_stmnt {
+ my $expr = $_[0];
+
+ my @tree = ('PROCEDURE');
+
+ my $token = Expect($expr, 'IDENT');
+ push @tree, $token;
+ Expect($expr, 'LPAREN');
+ my $strs = strs($expr);
+ push @tree, @$strs;
+ Expect($expr, 'RPAREN');
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# assn_stmnt : IDENT ASSIGN expr
+# | arrexp ASSIGN expr
+#
+
+sub assn_stmnt {
+ my $expr = $_[0];
+
+ my $token = Expect($expr, 'IDENT');
+
+ my @tree = ('ASSIGN');
+
+ if (Match(Peek($expr), 'LBRACK')) {
+ Pushback($token);
+ push @tree, arrexpr($expr);
+ } else {
+ # IDENT
+ push @tree, $token;
+ }
+
+ Expect($expr, 'ASSIGN');
+ push @tree, expr($expr);
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# loop_stmnt : WHILE expr NL stmnts NL NEXT
+#
+
+sub loop_stmnt {
+ my $expr = $_[0];
+
+ my @tree = ('LOOP');
+
+ Expect($expr, 'WHILE');
+ push @tree, expr($expr);
+ Expect($expr, 'NL');
+ push @tree, stmnts($expr);
+ Expect($expr, 'NEXT');
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# elif_stmnt : ELIF expr NL stmnts
+# | elif_stmnt NL elif_stmnt
+#
+
+sub elif_stmnt {
+ my $expr = $_[0];
+
+ my @elif = ();
+
+ Expect($expr, 'ELIF');
+ push @elif, expr($expr);
+ Expect($expr, 'NL');
+ push @elif, stmnts($expr);
+
+ return \@elif;
+}
+
+
+############################################################################
+#
+# cond_stmnt : IF expr NL stmnts ENDIF
+# | IF expr NL stmnts ELSE NL stmnts ENDIF
+# | IF expr NL stmnts elif_stmnt ENDIF
+# | IF expr NL stmnts elif_stmnt ELSE NL stmnts ENDIF
+#
+
+sub cond_stmnt {
+ my $expr = $_[0];
+
+ my @tree = ('COND');
+ my @if;
+
+ Expect($expr, 'IF');
+ push @if, expr($expr);
+ Expect($expr, 'NL');
+ push @if, stmnts($expr);
+
+ push @tree, \@if;
+
+ while (Match(Peek($expr), 'ELIF')) {
+ push @tree, elif_stmnt($expr);
+ }
+
+ my $token = Peek($expr);
+
+ if (Match($token, 'ELSE')) {
+ Expect($expr, 'ELSE');
+ Expect($expr, 'NL');
+ push @tree, [['TERMINAL', ['NUMBER', '1', 0, 0, 0]], stmnts($expr)];
+ } elsif (Match($token, 'ENDIF')) {
+ # nop
+ } else {
+ Error("expected 'endif' before '$$token[1]' token", $token);
+ }
+
+ Expect($expr, 'ENDIF');
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# defun_stmnt: DEFUN IDENT ASSIGN IDENT LPAREN varlist RPAREN NL stmnts ENDFUN
+# | DEFUN IDENT ASSIGN IDENT LPAREN RPAREN NL stmnts ENDFUN
+#
+
+sub defun_stmnt {
+ my $expr = $_[0];
+
+ my @tree = ('DEFUN');
+
+ Expect($expr, 'DEFUN');
+ push @tree, Expect($expr, 'IDENT');
+ Expect($expr, 'ASSIGN');
+
+ my $fcn = Expect($expr, 'IDENT');
+
+ push @tree, $fcn;
+ Expect($expr, 'LPAREN');
+ if (Match(Peek($expr), 'RPAREN')) {
+ push @tree, [];
+ } else {
+ push @tree, varlist($expr);
+ }
+ Expect($expr, 'RPAREN');
+ Expect($expr, 'NL');
+ push @tree, stmnts($expr);
+ Expect($expr, 'ENDFUN');
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# stmnt : NL
+# | proc_stmnt NL
+# | assn_stmnt NL
+# | loop_stmnt NL
+# | cond_stmnt NL
+#
+
+sub stmnt {
+ my $expr = $_[0];
+
+ my $token = Peek($expr);
+ my $tree;
+
+ if (Match($token, 'NL')) {
+ $tree = [];
+ } elsif (Match($token, 'IF')) {
+ $tree = cond_stmnt($expr);
+ } elsif (Match($token, 'WHILE')) {
+ $tree = loop_stmnt($expr);
+ } elsif (Match($token, 'DEFUN')) {
+ $tree = defun_stmnt($expr);
+ } elsif (Match($token, 'IDENT')) {
+ $token = Expect($expr, 'IDENT');
+ if (Match(Peek($expr), 'LPAREN')) {
+ Pushback($token);
+ $tree = proc_stmnt($expr);
+ } else {
+ Pushback($token);
+ $tree = assn_stmnt($expr);
+ }
+ } else {
+ Error("expected identifier or 'if' or 'while' or 'defun'", $token);
+ }
+
+ Expect($expr, 'NL');
+
+ return $tree;
+}
+
+
+############################################################################
+#
+# stmnts : stmnt
+# | stmnt stmnts
+#
+
+sub stmnts {
+ my $expr = $_[0];
+ my @tree = ();
+
+ restart:
+ my $s = stmnt($expr);
+ push @tree, $s if @$s;
+
+ my $token = Peek($expr);
+
+ if (Match($token, 'ELIF') or
+ Match($token, 'ELSE') or
+ Match($token, 'ENDIF') or
+ Match($token, 'ENDFUN') or
+ Match($token, 'NEXT') or
+ Match($token, 'END')) {
+ return \@tree;
+ }
+
+ goto restart;
+}
+
+
+############################################################################
+#
+# script : vardecl stmnts
+#
+
+sub ParseScript {
+ my $expr = $_[0];
+
+ my @tree = ();
+ push @tree, vardecl($expr);
+ push @tree, stmnts($expr);
+
+ return \@tree;
+}
+
+
+############################################################################
+#
+# function : defun_stmnt NL
+#
+
+sub ParseFunction {
+ my $expr = $_[0];
+
+ my $tree = defun_stmnt($expr);
+ Expect($expr, 'NL');
+ Expect($expr, 'END');
+
+ return $tree;
+}
+
+
+############################################################################
+#
+# program : script
+# | function
+#
+
+sub Parse {
+ my $expr = $_[0];
+
+ # Strip comments
+ $expr =~ s/#.*$//mg;
+
+ @tokenList = ();
+ $line = 1;
+ $pos = 0;
+
+ my $token = Peek(\$expr);
+ my $tree;
+
+ if (Match($token, 'VARS')) {
+ $tree = ParseScript(\$expr);
+ } elsif (Match($token, 'DEFUN')) {
+ $tree = ParseFunction(\$expr);
+ } else {
+ Error("Source must be either a function or script", $token);
+ }
+
+ return $tree;
+}
+
+
+############################################################################
+#
+# Analysis section --
+#
+# Go through the parse tree, reducing common subexpressions,
+# adding vars to the symbol table and functions to the function
+# table, and creating bind environments.
+#
+
+sub IsRunnable {
+ my $r = shift;
+
+ return ref($r) and ref($r) eq 'HASH';
+}
+
+
+
+############################################################################
+#
+# Analyze_CheckVars --
+#
+# Check that vars are defined before use (and that defined vars
+# are used).
+#
+
+sub Analyze_CheckVars {
+ my ($environmentName, $line1, $defined, $used) = @_;
+
+ foreach my $dv (keys(%$defined)) {
+ unless (defined($used->{$dv})) {
+ print "Warning:" . $defined->{$dv} .
+ ": '${environmentName}::${dv}' defined but not used\n"
+ }
+ }
+
+ foreach my $uv (keys(%$used)) {
+ if (not defined($defined->{$uv}) or
+ ($defined->{$uv} >= $used->{$uv} and
+ $defined->{$uv} != $line1 and $used->{$uv} != $line1)) {
+ Error("'${environmentName}::${uv}' used before definition",
+ ['IDENT', $uv, length($uv), $used->{$uv}, 0]);
+ }
+ }
+
+}
+
+
+############################################################################
+#
+
+sub Analyze_expr {
+ my ($expr, $used, $symbolTable) = @_;
+
+ if ($expr->[0] eq 'EXPR') {
+ Analyze_expr($expr->[2], $used, $symbolTable);
+ Analyze_expr($expr->[3], $used, $symbolTable);
+
+ } elsif ($expr->[0] eq 'UNIEXPR') {
+ if ($expr->[1]->[0] eq 'EXPR') {
+ Analyze_expr($expr->[1], $used, $symbolTable);
+ } else {
+ Analyze_expr($expr->[2], $used, $symbolTable);
+ }
+
+ } elsif ($expr->[0] eq 'FUNCALL') {
+ foreach my $e (2..$#$expr) {
+ Analyze_expr($expr->[$e], $used, $symbolTable);
+ }
+
+ } elsif ($expr->[0] eq 'ARREXPR') {
+ $used->{IdentName($expr->[1])} = $expr->[1]->[3];
+ Analyze_expr($expr->[2], $used, $symbolTable);
+
+ } elsif ($expr->[0] eq 'ARRAY') {
+ foreach my $a (1..$#$expr) {
+ Analyze_expr($expr->[$a], $used, $symbolTable);
+ }
+
+ } elsif ($expr->[0] eq 'TERMINAL') {
+ if (IsIdent($expr->[1])) {
+ my $i = IdentName($expr->[1]);
+
+ if (not defined($used->{$i})) {
+ $used->{$i} = $expr->[1]->[3];
+ $symbolTable->{$i} = [];
+ }
+ }
+
+ } elsif ($expr->[0] eq 'STRING') {
+ # nop
+ } else {
+ print Backtrace() . "\n";
+ print "Analyze_expr: ????\n";
+ print Dumper $expr;
+ croak "Analyze_expr: ????";
+ }
+}
+
+
+############################################################################
+#
+
+sub Analyze_defun {
+ my $ptree = $_[0];
+
+ my %defined = ();
+ my %used = ();
+
+ my ($environmentName, $symbolTable);
+
+ my $bindTable = {type => 'function', in => [], out => []};
+
+ # structure is ['DEFUN',out,name,[in],stmnts]
+ $environmentName = IdentName($ptree->[2]);
+
+ my $line1 = $ptree->[2]->[3];
+
+ if (defined($functions{$environmentName})) {
+ Error("Attempt to redefine function '" .
+ IdentName($ptree->[2]) . "'", $ptree->[2]);
+ }
+
+ my $o = IdentName($ptree->[1]);
+ $used{$o} = $ptree->[1]->[3];
+ $bindTable->{out} = $o;
+
+ foreach my $in (@{$ptree->[3]}) {
+ my $i = IdentName($in);
+ $defined{$i} = $in->[3];
+ push @{$bindTable->{in}}, $i;
+ }
+
+ my $fcn = Analyze_stmnts($ptree->[4], $symbolTable, \%defined, \%used);
+
+ Analyze_CheckVars($environmentName, $line1, \%defined, \%used);
+
+
+ ## Create caller and add to function table
+ push @userFunctions, $environmentName;
+ $functions{$environmentName} = sub {
+ my @in = @_;
+
+ push @environments, $currentEnvironment;
+ $currentEnvironment = $environmentName;
+
+ # Bind input vars
+ foreach my $k (0..$#in) {
+ my $var = $bindTable->{in}->[$k];
+ $symbolTable->{$var} = $in[$k];
+ }
+
+ push @symbolTables, $symbolTable;
+
+ Exec_stmnts(DeepCopy($fcn));
+
+ # Bind output vars
+
+ my $out = $symbolTable->{$bindTable->{out}};
+
+ # Clean up input vars
+ foreach my $k (0..$#in) {
+ my $var = $bindTable->{in}->[$k];
+ $symbolTable->{$var} = [];
+ }
+
+ $currentEnvironment = pop @environments;
+ pop @symbolTables;
+
+ return $out;
+ };
+}
+
+
+############################################################################
+#
+
+sub Analyze_stmnts {
+ my ($stmnts, $symbolTable, $defined, $used) = @_;
+
+ my $tree = [];
+
+ foreach my $stmnt (@$stmnts) {
+ my $new;
+
+ if ($stmnt->[0] eq 'DEFUN') {
+ Analyze_defun($stmnt);
+
+ next; # Don't add to output tree.
+
+ } elsif ($stmnt->[0] eq 'LOOP') {
+ $new = ['LOOP', $stmnt->[1]];
+ Analyze_expr($stmnt->[1], $used, $symbolTable);
+
+ push @$new, Analyze_stmnts($stmnt->[2], $symbolTable, $defined, $used);
+
+ } elsif ($stmnt->[0] eq 'COND') {
+ $new = ['COND'];
+
+ foreach my $c (1..$#$stmnt) {
+ my $cond = $stmnt->[$c];
+
+ Analyze_expr($cond->[0], $used, $symbolTable);
+
+ push @$new, [$cond->[0], Analyze_stmnts($cond->[1], $symbolTable,
+ $defined, $used)];
+ }
+
+ } elsif ($stmnt->[0] eq 'ASSIGN') {
+ my $id;
+ if (IsIdent($stmnt->[1])) {
+ $id = $stmnt->[1];
+ } else {
+ $id = $stmnt->[1]->[1];
+ }
+
+ if (not defined($defined->{IdentName($id)})) {
+ $defined->{IdentName($id)} = $id->[3];
+ }
+
+ Analyze_expr($stmnt->[2], $used, $symbolTable);
+
+ $new = $stmnt;
+
+ } elsif ($stmnt->[0] eq 'PROCEDURE') {
+ foreach my $e (2..$#$stmnt) {
+ Analyze_expr($stmnt->[$e], $used, $symbolTable);
+ }
+
+ $new = $stmnt;
+
+ } else {
+ croak "Unknown stmnt: " . $stmnt->[0] . "!" . Backtrace();
+ }
+
+ push @$tree, $new;
+ }
+
+ return $tree;
+}
+
+
+############################################################################
+#
+
+sub Analyze {
+ my $ptree = shift;
+
+ ## XXX for now, just look for vars and functions
+
+ # Sets of defined/used variables. Used vars that aren't defined or
+ # that are defined after usage cause an error. Defined vars that
+ # aren't used cause a warning.
+ my %defined = ();
+ my %used = ();
+
+ my ($runnable, $environmentName);
+
+ if (!ref($ptree->[0]) and $ptree->[0] eq 'DEFUN') {
+ # Function
+
+ Analyze_defun($ptree);
+ $runnable = {};
+
+ } else {
+ # Script
+ my ($symbolTable, $bindTable, $tree);
+
+ $bindTable = {type => 'script', vars => []};
+ $environmentName = '__main__';
+
+ foreach my $k (1..$#{$ptree->[0]}) {
+ my $v = $ptree->[0]->[$k];
+ my $id = IdentName($v);
+
+ push @{$bindTable->{vars}}, $id;
+ $defined{$id} = $v->[3];
+ $used{$id} = $v->[3];
+ }
+
+ $tree = Analyze_stmnts($ptree->[1], $symbolTable, \%defined, \%used);
+
+ $runnable = {environmentName => $environmentName,
+ symbolTable => $symbolTable,
+ bindTable => $bindTable,
+ tree => [$ptree->[0], $tree]};
+ }
+
+ Analyze_CheckVars($environmentName, 1, \%defined, \%used);
+
+ return $runnable;
+}
+
+
+############################################################################
+#
+# Execution engine --
+#
+#
+
+sub NotImplemented {
+ print Dumper $_[1];
+
+ croak "Not implemented ($_[0])\n" . Backtrace();
+}
+
+
+############################################################################
+#
+
+sub IsIdent {
+ my $v = $_[0];
+
+ return $v->[0] eq 'IDENT';
+}
+
+
+############################################################################
+#
+
+sub NumberValue {
+ my $n = $_[0];
+
+ return 0 + $n->[1];
+}
+
+
+############################################################################
+#
+
+sub IsEmpty {
+ return @{$_[0]} == 0;
+}
+
+
+############################################################################
+#
+
+sub IsScalar {
+ return @{$_[0]} == 1;
+}
+
+
+############################################################################
+#
+
+sub CheckDim {
+ my ($op, $left, $right) = @_;
+
+ if (@$left != @$right) {
+ Error('Array size mismatch', $op);
+ }
+}
+
+
+############################################################################
+#
+
+sub ApplyOne {
+ my ($arg, $fcn) = @_;
+
+ my @out = (0) x @$arg;
+ foreach my $k (0..$#$arg) {
+ $out[$k] = &$fcn($arg->[$k]);
+ }
+
+ return \@out;
+}
+
+
+############################################################################
+#
+
+sub ApplyTwo {
+ my ($left, $right, $fcn) = @_;
+
+ my @out = 0 x @$left;
+ foreach my $k (0..$#$left) {
+ $out[$k] = &$fcn($left->[$k], $right->[$k]);
+ }
+
+ return \@out;
+}
+
+
+############################################################################
+#
+
+sub DoLength {
+ my $arg = $_[0];
+
+ return [scalar(@$arg)];
+}
+
+
+############################################################################
+#
+
+sub DoSum {
+ my $arg = $_[0];
+
+ my $s = 0;
+ $s += $_ foreach @$arg;
+
+ return [$s];
+}
+
+
+############################################################################
+#
+
+sub DoMin {
+ my @A = @{$_[0]};
+
+ return 0 unless @A;
+
+ my $m = $A[0];
+
+ foreach (@A) {
+ $m = $_ if $_ < $m;
+ }
+
+ return [$m];
+}
+
+
+############################################################################
+#
+
+sub DoMax {
+ my @A = @{$_[0]};
+
+ return 0 unless @A;
+
+ my $m = $A[0];
+
+ foreach (@A) {
+ $m = $_ if $_ > $m;
+ }
+
+ return [$m];
+}
+
+
+############################################################################
+#
+
+sub DoSort {
+ my $arg = $_[0];
+
+ my @r = sort { $a <=> $b } @{DeepCopy($arg)};
+
+ return \@r;
+}
+
+
+############################################################################
+#
+
+sub DoInt {
+ my $arg = $_[0];
+
+ my @a = ();
+ push @a, int($_) foreach @$arg;
+
+ return \@a;
+}
+
+
+############################################################################
+#
+
+sub DoAbs {
+ my $arg = $_[0];
+
+ return ApplyOne($arg, sub { return abs($_[0]); });
+}
+
+
+############################################################################
+#
+
+sub DoSin {
+ my $arg = $_[0];
+
+ return ApplyOne($arg, sub { return sin($_[0]); });
+}
+
+
+############################################################################
+#
+
+sub DoCos {
+ my $arg = $_[0];
+
+ return ApplyOne($arg, sub { return cos($_[0]); });
+}
+
+
+############################################################################
+#
+
+sub DoTan {
+ my $arg = $_[0];
+
+ return ApplyOne($arg, sub { return sin($_[0]) / cos(($_[0])); });
+}
+
+############################################################################
+#
+
+sub DoDiff {
+ my $arg = $_[0];
+
+ my @arr = (0) x @$arg;
+
+ foreach my $k (1..$#$arg) {
+ $arr[$k] = $arg->[$k] - $arg->[$k-1];
+ }
+
+ return \@arr;
+}
+
+
+############################################################################
+#
+
+sub DoFlip {
+ my $arg = $_[0];
+
+ my @arr = @{DeepCopy($arg)};
+ my @rev = reverse @arr;
+
+ return \@rev;
+}
+
+
+############################################################################
+#
+
+sub DoSqrt {
+ my $arg = $_[0];
+
+ return ApplyOne($arg, sub { return sqrt($_[0]); });
+}
+
+
+############################################################################
+#
+
+sub DoOnes {
+ my $arr = $_[0];
+
+ my $len = @$arr;
+ $len = $arr->[0] if $len == 1;
+
+ my @out = (1) x $len;
+
+ return \@out;
+}
+
+############################################################################
+#
+
+sub DoZeros {
+ my $arr = $_[0];
+
+ my $len = @$arr;
+ $len = $arr->[0] if $len == 1;
+
+ my @out = (0) x $len;
+
+ return \@out;
+}
+
+############################################################################
+#
+
+sub DoAny {
+ my $arr = $_[0];
+
+ foreach my $v (@$arr) {
+ return [1] if $v;
+ }
+
+ return [0];
+}
+
+############################################################################
+#
+
+sub DoRand {
+ my $arr = $_[0];
+
+ my $len = @$arr;
+ $len = $arr->[0] if $len == 1;
+
+ my @out = ();
+ foreach (1..$len) {
+ push @out, rand();
+ }
+
+ return \@out;
+}
+
+
+############################################################################
+#
+
+sub DoAll {
+ my $arr = $_[0];
+
+ foreach my $v (@$arr) {
+ return [0] if !$v;
+ }
+
+ return [1];
+}
+
+
+############################################################################
+#
+
+sub DoError {
+ croak "Error: $_[0]\n";
+}
+
+
+############################################################################
+#
+
+sub DoDisp {
+ my @strs = ();
+
+ foreach my $arg (@_) {
+ if (ref($arg) ne 'ARRAY') {
+ push @strs, $arg;
+ } else {
+ my $s;
+ if (@$arg == 1) {
+ $s = $arg->[0];
+ } else {
+ $s = '[' . join(',', @$arg) . ']';
+ }
+ push @strs, $s;
+ }
+ }
+
+ print join(' ', @strs) . "\n";
+}
+
+
+############################################################################
+#
+
+sub DoSave {
+ my $f = shift;
+
+ if (@_ == 0) {
+ croak('save: Missing argument')
+ }
+
+ my $N = @{$_[0]};
+
+ # Check arg dimensions if more than one array was passed in.
+ if (@_ > 1) {
+ foreach my $a (0..$#_) {
+ if (@{$_[$a]} != $N) {
+ croak('save: array size mismatch in arg ' . ($a + 2))
+ }
+ }
+ }
+
+ open OUTFILE, ">$f" or croak "Unable to open $f: $!";
+ foreach my $k (0..$N-1) {
+ my @vals = ();
+ foreach my $a (0..$#_) {
+ push @vals, $_[$a]->[$k];
+ }
+
+ print OUTFILE join(',', @vals) . "\n";
+ }
+ close OUTFILE;
+}
+
+############################################################################
+#
+
+sub DoColon {
+ my ($start, $incr, $stop);
+
+ if (defined($_[2])) {
+ ($start, $incr, $stop) = @_;
+ } else {
+ ($start, $incr, $stop) = ($_[0], [1], $_[1]);
+ }
+
+ if (!IsScalar($start) ||
+ !IsScalar($incr) ||
+ !IsScalar($stop)) {
+ croak ": args must be scalar";
+ }
+
+ ($start, $incr, $stop) = ($start->[0], $incr->[0], $stop->[0]);
+
+ # check vals
+ if ($stop < $start && $incr > 0 or
+ $stop > $start && $incr < 0 or
+ $incr == 0 or
+ $start == $stop) {
+ return [];
+ }
+
+ my @out = ();
+
+ my $d = 1; # direction + => 1, - => -1
+ $d = -1 if $stop < $start;
+
+ while ($d * $start <= $d * $stop) {
+ push @out, $start;
+ $start += $incr;
+ }
+
+ return \@out;
+}
+
+
+############################################################################
+#
+
+sub DoOperation {
+ my ($op, $left, $right, $extra) = @_;
+
+ my $o = $op->[0];
+
+ if (IsEmpty($left) || IsEmpty($right)) {
+ return [];
+ }
+
+ if (IsScalar($left) xor IsScalar($right)) {
+ if (IsScalar($left)) {
+ my @a = ($left->[0]) x @$right;
+ $left = \@a;
+ } else {
+ my @a = ($right->[0]) x @$left;
+ $right = \@a;
+ }
+ }
+
+ CheckDim($op, $left, $right);
+
+ my $val;
+
+ if ($o eq 'EXP') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] ** $_[1]; });
+ } elsif ($o eq 'TIMES') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] * $_[1]; });
+ } elsif ($o eq 'DIVIDE') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] / $_[1]; });
+ } elsif ($o eq 'MODULO') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] % $_[1]; });
+ } elsif ($o eq 'PLUS') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] + $_[1]; });
+ } elsif ($o eq 'MINUS') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] - $_[1]; });
+ } elsif ($o eq 'LT') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] < $_[1]; });
+ } elsif ($o eq 'GT') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] > $_[1]; });
+ } elsif ($o eq 'LE') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] <= $_[1]; });
+ } elsif ($o eq 'GE') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] >= $_[1]; });
+ } elsif ($o eq 'EQ') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] == $_[1]; });
+ } elsif ($o eq 'NE') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] != $_[1]; });
+ } elsif ($o eq 'AND') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] && $_[1]; });
+ } elsif ($o eq 'OR') {
+ $val = ApplyTwo($left, $right, sub { return $_[0] || $_[1]; });
+ } elsif ($o eq 'COLON') {
+ $val = DoColon($left, $right, $extra);
+ } else {
+ NotImplemented("Unknown operation ($o)", $op);
+ }
+
+ return $val;
+}
+
+
+############################################################################
+#
+
+sub Exec_uniexpr {
+ my $expr = $_[0];
+
+ my $val = [];
+ my $arg = Exec_expr($expr->[2]);
+
+ if ($expr->[1]->[0] eq 'MINUS') {
+ $val = ApplyOne($arg, sub { return -($_[0]); });
+ } elsif ($expr->[1]->[0] eq 'PLUS') {
+ $val = ApplyOne($arg, sub { return +($_[0]); });
+ } elsif ($expr->[1]->[0] eq 'NOT') {
+ $val = ApplyOne($arg, sub { return !($_[0]); });
+ }
+
+ return $val;
+}
+
+
+############################################################################
+#
+
+sub Exec_array {
+ my $expr = $_[0];
+
+ my @out = ();
+
+ shift @$expr;
+ foreach my $e (@$expr) {
+ push @out, @{Exec_expr($e)};
+ }
+
+ return \@out;
+}
+
+
+############################################################################
+#
+
+sub Exec_arrexpr {
+ my $expr = $_[0];
+
+ my $val = $symbolTables[-1]->{IdentName($expr->[1])};
+ my $indices = Exec_expr($expr->[2]);
+
+ my @out = @$val[@$indices];
+
+ foreach my $k (0..$#out) {
+ $out[$k] = 0 if not defined $out[$k];
+ }
+
+
+ return \@out;
+}
+
+
+############################################################################
+#
+
+sub Exec_funcall {
+ my $expr = $_[0];
+
+ my $fcn = $functions{IdentName($expr->[1])};
+
+ unless (defined($fcn)) {
+ Error(q(Function ') . IdentName($expr->[1]) . q(' does not exist),
+ $expr->[1]);
+ }
+
+ my @args = ();
+ foreach my $a (2..$#$expr) {
+ push @args, Exec_expr($expr->[$a]);
+ }
+
+ return &$fcn(@args);
+}
+
+
+############################################################################
+#
+
+sub Exec_expr {
+ my $expr = $_[0];
+
+ my $val = [];
+
+ if ($expr->[0] eq 'EXPR') {
+ my $extra = undef;
+
+ if (@$expr == 5) {
+ # For :
+ $extra = Exec_expr($expr->[4]);
+ }
+
+ $val = DoOperation($expr->[1],
+ Exec_expr($expr->[2]),
+ Exec_expr($expr->[3]),
+ $extra);
+
+ } elsif ($expr->[0] eq 'TERMINAL') {
+
+ if (IsIdent($expr->[1])) {
+ $val = $symbolTables[-1]->{IdentName($expr->[1])};
+
+ if (!defined($val)) {
+ Error("Variable '${currentEnvironment}::" . IdentName($expr->[1]) .
+ "' used before defined", $expr->[1]);
+ }
+ } else {
+ # NUMBER
+ $val = [NumberValue($expr->[1])];
+ }
+
+ } elsif ($expr->[0] eq 'UNIEXPR') {
+ # UNIEXPR
+ if ($expr->[1]->[0] eq 'EXPR') {
+ # parenthetical expression
+ $val = Exec_expr($expr->[1]);
+ } else {
+ $val = Exec_uniexpr($expr);
+ }
+ } elsif ($expr->[0] eq 'ARRAY') {
+ $val = Exec_array($expr);
+ } elsif ($expr->[0] eq 'ARREXPR') {
+ $val = Exec_arrexpr($expr);
+ } elsif ($expr->[0] eq 'FUNCALL') {
+ $val = Exec_funcall($expr);
+ } else {
+ NotImplemented('Exec_expr', $expr);
+ }
+
+ return $val;
+}
+
+
+############################################################################
+#
+
+sub Exec_assign {
+ my $stmnt = $_[0];
+
+ my $val = Exec_expr($stmnt->[2]);
+
+ if (IsIdent($stmnt->[1])) {
+ if ($debug) {
+ print 'Assigning to ' . IdentName($stmnt->[1]) . "\n";
+ }
+
+ $symbolTables[-1]->{IdentName($stmnt->[1])} = $val;
+ } else {
+ # subscripted reference
+ my $indices = Exec_expr($stmnt->[1]->[2]);
+
+ if (IsScalar($val)) {
+ my @vals = (@$val) x @$indices;
+ $val = \@vals;
+ }
+
+ # var[indices] = val
+ my $var = $symbolTables[-1]->{IdentName($stmnt->[1]->[1])};
+ $var = [] if not defined $var;
+
+ CheckDim(['ASSIGN', '=', 1,
+ $stmnt->[1]->[1]->[3],
+ $stmnt->[1]->[1]->[4]],
+ $indices, $val);
+
+ @$var[@$indices] = @$val;
+
+ for my $k (0..$#$var) {
+ $var->[$k] = 0 if not defined $var->[$k];
+ }
+
+ $symbolTables[-1]->{IdentName($stmnt->[1]->[1])} = $var;
+ }
+}
+
+
+############################################################################
+#
+
+sub Exec_cond {
+ my $stmnt = $_[0];
+
+ foreach my $k (1..$#$stmnt) {
+ my $cond = $stmnt->[$k];
+
+ if (@{DoAll(Exec_expr($cond->[0]))}[0]) {
+ Exec_stmnts($cond->[1]);
+ last;
+ }
+ }
+}
+
+
+############################################################################
+#
+
+sub Exec_loop {
+ my $stmnt = $_[0];
+
+ while (@{DoAll(Exec_expr(DeepCopy($stmnt->[1])))}[0]) {
+ Exec_stmnts(DeepCopy($stmnt->[2]));
+ }
+}
+
+
+############################################################################
+#
+
+sub Exec_procedure {
+ my $stmnt = $_[0];
+
+ my $fcn = $functions{IdentName($stmnt->[1])};
+
+ unless (defined($fcn)) {
+ Error(q(Function ') . IdentName($stmnt->[1]) . q(' does not exist),
+ $stmnt->[1]);
+ }
+
+ my @args = ();
+ foreach my $k (2..$#$stmnt) {
+ my $e = $stmnt->[$k];
+
+ if ($e->[0] eq 'STRING') {
+ my $s = $e->[1];
+ $s =~ s/'(.*)'/$1/;
+ $s =~ s/\\'/'/g;
+ push @args, $s;
+ } else {
+ push @args, Exec_expr($e);
+ }
+ }
+
+ &$fcn(@args);
+}
+
+
+############################################################################
+#
+
+sub Exec_stmnt {
+ my $stmnt = $_[0];
+
+ my $action = $stmnt->[0];
+ croak "Exec_stmnt: ACTION undefined!" . Backtrace() unless defined $action;
+
+ if ($action eq 'ASSIGN') {
+ Exec_assign($stmnt);
+ } elsif ($action eq 'COND') {
+ Exec_cond($stmnt);
+ } elsif ($action eq 'LOOP') {
+ Exec_loop($stmnt);
+ } elsif ($action eq 'PROCEDURE') {
+ Exec_procedure($stmnt);
+ }
+}
+
+
+############################################################################
+#
+
+sub Exec_stmnts {
+ my $stmnts = $_[0];
+
+ foreach my $stmnt (@$stmnts) {
+ Exec_stmnt($stmnt);
+ }
+}
+
+
+############################################################################
+#
+
+sub Eval {
+ my ($runnable, $vars) = @_;
+
+ my $symbolTable = {};
+ $currentEnvironment = '__main__';
+
+ # Bind vars
+ my $tree = $runnable->{tree};
+ my $vardecl = $tree->[0];
+
+ if (@$vardecl - 1 != @$vars) {
+ my $want = @$vardecl - 1;
+ my $have = @$vars;
+ croak("Number of args ($have) != number of vars in declaration ($want)");
+ }
+
+ push @symbolTables, $symbolTable;
+
+ foreach my $v (0..$#$vars) {
+ $symbolTables[-1]->{IdentName($vardecl->[$v + 1])} = $vars->[$v];
+
+ if ($debug) {
+ print 'Binding ' . IdentName($vardecl->[$v + 1]) . "\n";
+ }
+ }
+
+ # Now exec everything recursively
+ my $stmnts = $tree->[1];
+ Exec_stmnts($stmnts);
+
+ # Unbind vars
+
+ my @out = ();
+ foreach my $v (0..$#$vars) {
+ push @out, $symbolTables[-1]->{IdentName($vardecl->[$v + 1])};
+ if ($debug) {
+ print 'Unbinding ' . IdentName($vardecl->[$v + 1]) . "\n";
+ }
+ }
+
+ pop @symbolTables;
+
+ return @out;
+}
+
+
+############################################################################
+#
+
+sub CompileWork {
+ my ($script, $rrunnable) = @_;
+
+ my ($tree, $runnable);
+
+ eval {
+ $tree = Parse($script);
+ $runnable = Analyze($tree);
+ };
+
+ $$rrunnable = $runnable;
+ return $@;
+}
+
+
+############################################################################
+#
+
+sub RunScriptWork {
+ my $script = shift;
+ my @args = @_;
+
+ my $runnable;
+
+ if (IsRunnable($script)) {
+ $runnable = $script;
+ } else {
+ my $err = CompileWork($script, \$runnable);
+ return $err if $err;
+ }
+
+ # Evaluate tree
+
+ my @outArgs;
+ eval {
+ @outArgs = Eval($runnable, \@args);
+ };
+ return $@ if $@;
+
+ # Reassign args
+ foreach my $k (0..$#outArgs) {
+ eval {
+ splice @{$args[$k]}, 0, @{$args[$k]}, @{$outArgs[$k]};
+ };
+ if ($@) {
+ croak $@ . Backtrace();
+ }
+ }
+}
+
+
+############################################################################
+#
+
+sub new {
+ my $class = shift;
+ my $this = {};
+ bless($this, $class);
+
+ if (@userFunctions) {
+ foreach my $f (@userFunctions) {
+ undef $functions{$f};
+ }
+ @userFunctions = ();
+ }
+
+ return $this;
+}
+
+
+############################################################################
+#
+# Compile a script only - add to function table.
+
+sub Compile {
+ my $this = shift;
+ croak("Missing script") unless @_ >= 1;
+ my $script = shift;
+
+ Debug("======================================\n$script\n");
+
+ my $runnable;
+ my $err = CompileWork($script, \$runnable);
+
+ chomp $err;
+ croak "$err" if $err;
+
+ return $runnable;
+}
+
+
+############################################################################
+#
+
+sub RunScript {
+ my $this = shift;
+
+ croak("Missing script") unless @_ >= 1;
+ my $script = shift;
+
+ croak("Must have one or more arguments") unless @_ >= 1;
+
+ foreach (@_) {
+ croak("Arguments must be array refs") unless ref($_) eq 'ARRAY';
+ }
+
+ unless (ref($script)) {
+ Debug("======================================\n$script\n");
+ }
+
+ my $err = RunScriptWork($script, @_);
+
+ chomp $err;
+ croak "$err" if $err;
+}
+
+
+1;
+
+__END__
+
+=head1 MATOPS
+
+Simple matrix operations for Perl (actually vector operations, but
+that's splitting hairs).
+
+=head1 SYNOPSIS
+
+ use matops;
+
+ @x = 1..3;
+ @y = undef
+ $m = matops->new();
+ $m->RunScript(<<"SCRIPT", \@x, \@y);
+ vars: x, y
+ y = x^2
+ SCRIPT
+
+ @x = [data from somewhere]
+ @m = undef
+ $s = $m->Compile(<<"FUNCTION");
+ vars: out, in
+ out = mean(in)
+ defun x = mean(data)
+ x = sum(data) / length(data)
+ endfun
+ FUNCTION
+ $m->RunScript($s, \@m, \@x);
+ print "mean is $m[0]\n";
+
+
+=head1 DESCRIPTION
+
+matops is a Perl module which implements a simple and intuitive
+language designed to operate in a seamless fashion on vectors of data.
+
+Using the Compile function, it is possible to build a library of
+subfunctions, and then execute scripts that use them. It is also
+possible to precompile scripts with the Compile function to save
+future execution time.
+
+Input and output is via array references. Any array reference passed
+in can be used for both input and output.
+
+
+=head1 EXAMPLES
+
+
+=item FIR filter:
+
+ vars: y, x, f
+
+ F = length(f)
+ N = length(x) + F - 1
+ f = flip(f)
+ k = 0
+ while (k < N)
+ y[k] = sum(x[k:k+length(f)-1] * f)
+ loop
+
+=item Median absolute deviation:
+
+ vars MAD, X
+
+ mad = median(abs(X - median(X)))
+
+ defun m = median(X)
+ N = length(X)
+ X = sort(X)
+ mid = int(N / 2)
+
+ if N % 2
+ m = X[mid]
+ else
+ m = (X[mid] + X[mid - 1]) / 2
+ endif
+ endfun
+
+
+=head1 BUILTIN FUNCTIONS
+
+=item length:
+
+Return the length of a vector.
+
+=item sum:
+
+Return the sum of all elements of a vector.
+
+=item min:
+
+Return the smallest element of a vector.
+
+=item max:
+
+Return the largest element of a vector.
+
+=item sort:
+
+Return a sorted vector, from small to large.
+
+=item int:
+
+Integer part.
+
+=item abs:
+
+Absolute value.
+
+=item diff:
+
+Return the difference between each adjacent element of a vector.
+
+=item flip:
+
+Return a vector that is the mirror image of the input. E.g.:
+
+ [1,2,3,4,5] => [5,4,3,2,1]
+
+=item sqrt:
+
+Square root.
+
+=item ones:
+
+Create a vector of ones of a specified length.
+
+ ones(5) => [1,1,1,1,1]
+
+=item zeros:
+
+Create a vector of zeros of a specified length.
+
+ zeros(5) => [0,0,0,0,0]
+
+=item rand:
+
+Create a vector of a specified length with random elements, in between
+0 and 1.
+
+=item all:
+
+Return 1 if all elements in a vector are non-zero.
+
+=item any:
+
+Return 1 if any of the elements in a vector are non-zero.
+
+=item sin:
+
+Sine.
+
+=item cos:
+
+Cosine.
+
+=item tan:
+
+Tangent.
+
+=item error:
+
+Abort execution and print an error message.
+
+=item disp:
+
+Display a message to the console. If an argument is a vector, convert
+it to a string reprentation first.
+
+=item save:
+
+Save an array to a file. The first argument is the filename, the
+second is the array.
+
+
+=head1 OPERATOR PRECEDENCE
+
+
+11: f(...) function call postfix ltr
+10: ~ logical not unary rtl
+ 9: - + negation, plus unary rtl
+ 8: ^ exponentiation binary rtl
+ 7: * / % multiplicative binary ltr
+ 6: + - additive binary ltr
+ 5: < > <= >= relational binary ltr
+ 4: == ~= equality binary ltr
+ 3: & logical and binary ltr
+ 2: | logical or binary ltr
+ 1: : colon operator binary/trinary ltr
+
+=head1 GRAMMAR
+
+ IDENT => [A-Za-z_][A-Za-z0-9_]*
+ NUMBER => ([0-9]*\\.[0-9]+|[0-9]+)([eE]-?[0-9]+)?
+ STRING => '(?:[^'\\n]|\\')*?'
+ IF => if
+ ELIF => elif
+ ELSE => else
+ ENDIF => endif
+ WHILE => while
+ NEXT => next
+ DEFUN => defun
+ ENDFUN => endfun
+ LBRACK => [
+ RBRACK => ]
+ LPAREN => (
+ RPAREN => )
+ COLON => :
+ PLUS => +
+ MINUS => -
+ TIMES => *
+ DIVIDE => /
+ MODULO => %
+ EXP => ^
+ AND => &
+ OR => |
+ EQ => ==
+ NE => ~=
+ LT => <
+ LE => <=
+ GT => >
+ GE => >=
+ NOT => ~
+ ASSIGN => =
+ NL => \n|;
+ COMMA => ,
+ VARS => vars:
+
+
+ varlist : IDENT
+ | IDENT COMMA varlist
+
+ vardecl : VARS varlist NL
+
+ arrexpr : IDENT LBRACK expr RBRACK
+
+ array_list :
+ | expr
+ | expr COMMA array_list
+
+ array : LBRACK array_list RBRACK
+
+ funargs :
+ | expr
+ | expr COMMA funargs
+
+ funcall : IDENT LPAREN funargs RPAREN
+
+ uniexpr : IDENT
+ | NUMBER
+ | arrexpr
+ | array
+ | funcall
+ | LPAREN expr RPAREN
+ | MINUS uniexpr
+ | PLUS uniexpr
+ | NOT uniexpr
+
+ expr : uniexpr
+ | uniexpr EXP expr
+ | uniexpr TIMES expr
+ | uniexpr DIVIDE expr
+ | uniexpr MODULO expr
+ | uniexpr PLUS expr
+ | uniexpr MINUS expr
+ | uniexpr AND expr
+ | uniexpr OR expr
+ | uniexpr EQ expr
+ | uniexpr NE expr
+ | uniexpr LT expr
+ | uniexpr LE expr
+ | uniexpr GT expr
+ | uniexpr GE expr
+
+ str : STRING
+ | expr
+
+ strs : str
+ | str COMMA strs
+
+ proc_stmnt : IDENT LPAREN strs RPAREN
+
+ assn_stmnt : IDENT ASSIGN expr
+ | arrexp ASSIGN expr
+
+ loop_stmnt : WHILE expr NL stmnts NL NEXT
+
+ elif_stmnt : ELIF expr NL stmnts
+ | elif_stmnt NL elif_stmnt
+
+ cond_stmnt : IF expr NL stmnts ENDIF
+ | IF expr NL stmnts ELSE NL stmnts ENDIF
+ | IF expr NL stmnts elif_stmnt ENDIF
+ | IF expr NL stmnts elif_stmnt ELSE NL stmnts ENDIF
+
+ stmnt : NL
+ | proc_stmnt NL
+ | assn_stmnt NL
+ | loop_stmnt NL
+ | cond_stmnt NL
+
+ stmnts : stmnt
+ | stmnt stmnts
+
+ script : vardecl stmnts
+
+ defun_stmnt : DEFUN IDENT ASSIGN LPAREN varlist RPAREN NL stmnts ENDFUN
+ | DEFUN IDENT ASSIGN LPAREN RPAREN NL stmnts ENDFUN
+
+ function : defun_stmnt NL
+
+ program : script
+ | function
+
+=cut
diff --git a/mv/MV b/mv/MV
new file mode 100755
index 0000000..faf3640
--- /dev/null
+++ b/mv/MV
Binary files differ
diff --git a/mv/mv.src b/mv/mv.src
new file mode 100644
index 0000000..5825d9e
--- /dev/null
+++ b/mv/mv.src
@@ -0,0 +1,259 @@
+(MV - A memory viewer)
+::
+ 0LASTOWDOB!
+ DEPTH #0<>
+ DUP IT :: DROPDUP TYPEHSTR? ;
+ ITE
+ :: CK1NOLASTWD HXS># ;
+ :: CK0NOLASTWD # 80000 ;
+ ClrDA1IsStat RECLAIMDISP
+
+ (display the menu area)
+ {
+ $ "ASCII"
+ $ "ADDR"
+ $ "-1"
+ $ "+1"
+ $ "-16"
+ $ "+16"
+ }
+ >R ZERO
+ BEGIN
+ RSWAP ticR DUP IT RSWAP
+ WHILE
+ ::
+ OVERSWAP Str>Menu
+ TWENTYTWO #+
+ ;
+ REPEAT
+ DROP
+
+ (set up vars)
+ASSEMBLE
+ CON(5) =DOCSTR
+ REL(5) end
+ BSS 32
+end
+RPL
+ SIXTEEN
+ ' NULLLAM THREE NDUPN DOBIND
+ BEGIN
+ ::
+ SEVEN ZERO_DO
+ 3GETLAM 1GETLAM INDEX@
+ #* #+DUP #>HXS
+ hxs>$ CDR$ CDR$
+ BEGIN
+ FIVE OVERLEN$ #- #0<>
+ WHILE
+ ::
+ CHR_0 >H$
+ ;
+ REPEAT
+ CHR_: >T$ SWAP
+ 2GETLAM SWAP
+ 1GETLAM SIXTEEN #=ITE
+CODE
+* HEX code
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ D0=A
+ A=DAT1 A
+ D1=A
+ D1=D1+ 10
+ C=0 A
+ LC(1) 10
+ D=C A
+ LC(2) #30
+ B=C A
+
+* D1str D0mem B=#30 D=#A
+- C=0 A
+ C=DAT0 1
+ ?C<D A
+ GOYES +
+ C=C+CON A,7
++ C=C+B A
+ DAT1=C B
+ D1=D1+ 2
+ D0=D0+ 1
+ P=P+1
+ GONC -
+
+ GOVLNG =GETPTRLOOP
+ENDCODE
+CODE
+* ASCII code
+ GOSBVL =POP#
+ GOSBVL =SAVPTR
+ D0=A
+ A=DAT1 A
+ D1=A
+ D1=D1+ 10
+
+* D0mem D1str
+- C=DAT0 B
+ DAT1=C B
+ D0=D0+ 2
+ D1=D1+ 2
+ P=P+1
+ GONC -
+
+ GOVLNG =GETPTRLOOP
+ENDCODE
+ &$ INDEX@ #1+ DISPN
+ LOOP
+
+ WaitForKey
+
+ #1<> casedrop
+ ::
+ DoBadKey FALSE
+ ;
+
+ ONE #=casedrop (ASCII/HEX)
+ ::
+ 1GETLAM SIXTEEN #=ITE
+ ::
+ $ "HEX"
+ THIRTYTWO
+ ;
+ ::
+ $ "ASCII"
+ SIXTEEN
+ ;
+ 1PUTLAM ZEROSWAP Str>Menu
+ FALSE
+ ;
+ TWO #=casedrop (ADDR)
+ ::
+ NULL$TEMP
+ BEGIN
+ ::
+ DUP CHR_< >T$ DISPROW7
+ WaitForKey
+ #1<> casedrop
+ :: DoBadKey FALSE ;
+ ::
+ ONE #=casedrop
+ :: CHR_A FalseTrue ;
+ TWO #=casedrop
+ :: CHR_B FalseTrue ;
+ THREE #=casedrop
+ :: CHR_C FalseTrue ;
+ FOUR #=casedrop
+ :: CHR_D FalseTrue ;
+ FIVE #=casedrop
+ :: CHR_E FalseTrue ;
+ SIX #=casedrop
+ :: CHR_F FalseTrue ;
+ THIRTYONE #=casedrop
+ :: CHR_7 FalseTrue ;
+ THIRTYTWO #=casedrop
+ :: CHR_8 FalseTrue ;
+ THIRTYTHREE #=casedrop
+ :: CHR_9 FalseTrue ;
+ THIRTYSIX #=casedrop
+ :: CHR_4 FalseTrue ;
+ THIRTYSEVEN #=casedrop
+ :: CHR_5 FalseTrue ;
+ THIRTYEIGHT #=casedrop
+ :: CHR_6 FalseTrue ;
+ FORTYONE #=casedrop
+ :: CHR_1 FalseTrue ;
+ FORTYTWO #=casedrop
+ :: CHR_2 FalseTrue ;
+ FORTYTHREE #=casedrop
+ :: CHR_3 FalseTrue ;
+ FORTYSIX #=casedrop
+ :: CHR_0 FalseTrue ;
+ TWENTYNINE #=casedrop
+ :: CHR_Space FalseTrue ;
+ TWENTYFIVE #=casedrop
+ :: TRUE TrueFalse ;
+ FORTYFIVE #=casedrop
+ :: FALSE TrueFalse ;
+ DROP DoBadKey FalseFalse
+ ;
+ IT
+ ::
+ UNROTDUP CHR># THIRTYTWO
+ #=ITE
+ ::
+ DROP DUPLEN$ DUP
+ #0=case :: DROP DoBadKey ;
+ 1_#1-SUB$
+ ;
+ ::
+ OVERLEN$ FIVE
+ #=case :: DROP DoBadKey ;
+ >T$
+ ;
+ SWAP
+ ;
+ ;
+ UNTIL
+ ITE
+ ::
+ CHR_# >H$ CHR_h >T$
+ palparse
+ ITE
+ ::
+ HXS># 3PUTLAM
+ ;
+ ::
+ 2DROP DoBadKey
+ ;
+ ;
+ DROP
+ FALSE
+ ;
+ THREE #=casedrop (-1)
+ ::
+ 3GETLAM #1- 3PUTLAM
+ FALSE
+ ;
+ SIXTEEN #=casedrop (-1)
+ ::
+ 3GETLAM #1- 3PUTLAM
+ FALSE
+ ;
+ FOUR #=casedrop (+1)
+ ::
+ 3GETLAM #1+ 3PUTLAM
+ FALSE
+ ;
+ EIGHTEEN #=casedrop (+1)
+ ::
+ 3GETLAM #1+ 3PUTLAM
+ FALSE
+ ;
+ FIVE #=casedrop (-16)
+ ::
+ 3GETLAM SIXTEEN #- 3PUTLAM
+ FALSE
+ ;
+ ELEVEN #=casedrop (-16)
+ ::
+ 3GETLAM 1GETLAM #- 3PUTLAM
+ FALSE
+ ;
+ SIX #=casedrop (+16)
+ ::
+ 3GETLAM SIXTEEN #+ 3PUTLAM
+ FALSE
+ ;
+ SEVENTEEN #=casedrop (+16)
+ ::
+ 3GETLAM 1GETLAM #+ 3PUTLAM
+ FALSE
+ ;
+ FORTYFIVE #=casedrop (ON)
+ TRUE
+
+ DROPFALSE DoBadKey
+ ;
+ UNTIL
+ ABND
+ ClrDAsOK
+;
diff --git a/mv/mv.txt b/mv/mv.txt
new file mode 100644
index 0000000..994b2dc
--- /dev/null
+++ b/mv/mv.txt
@@ -0,0 +1,41 @@
+MV
+Memory viewer
+
+1998, Jonathan duSaint
+jdusaint@mathworks.com
+jon@wpi.edu
+
+MV is a simple memory viewer for the HP48. All of the entries used are
+supported, so it should work on both the S and the G.
+
+To start, either have a hex string with the starting address on
+the stack, or if one isn't there, the program defaults to #80000h
+(the start of RAM on the G). A screen will then appear. For example,
+when given the address #3FF9h (the address of the supported entry
+ONE), the screen looks like:
+
+<MV>#+0123456789ABCDEF
+03FF9:1192010000119202
+04009:0000119203000011
+04019:9204000011920500
+04029:0011920600001192
+04039:0700001192080000
+04049:119209000011920A
+04059:000011920B000011
+
+Along the top row are the offsets from the address in the left column,
+as well as the name of the program. The left column displays the
+addresses that are currently being viewed. The right column (to the
+right of the colons) shows the memory dump. At the address #03FF9h
+is the data 1192010000. This is the object pointed to by ONE. The
+prologue of a bint is 02911 and the value is 00001 (note how the data
+is in reverse order). Further along are other built in bints.
+
+Pressing the down button will scroll +#10h, pressing the up button
+will scroll -#10h, pressing the left button will scroll -1, and
+pressing the right button will scroll +1. The keys 0-9 and A-F will
+jump to memory locations #x0000h, where x is the value of the key
+(0-F). The program is terminated with the On button. The calculator
+can be turned off while the program is running by pressing RS + Off,
+and will continue where it left off when the calculator is turned
+back on.
diff --git a/plot/freq.ico b/plot/freq.ico
new file mode 100755
index 0000000..1b7a7db
--- /dev/null
+++ b/plot/freq.ico
Binary files differ
diff --git a/plot/genfun.c b/plot/genfun.c
new file mode 100755
index 0000000..2010467
--- /dev/null
+++ b/plot/genfun.c
@@ -0,0 +1,667 @@
+/* genfun.c
+ * General function generator.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define MAX_INPUT_LENGTH 512
+
+#define PI 3.14159265359
+#define E 2.71828182846
+/* these both have values, but I don't know what they are */
+#define INF 0.0
+#define NAN 0.0
+
+#define WRITE_FILENAME "output.pld"
+
+
+typedef struct _array {
+ double *data;
+ unsigned long length;
+} array_t;
+
+struct command {
+ int (*command)(void);
+ char *command_name;
+};
+
+struct stack {
+ struct stack *next;
+ array_t *data;
+};
+
+
+struct stack *stack = NULL;
+
+int print_output;
+
+
+int dopush (double value);
+
+int doclear (void);
+int doquit (void);
+int dowrite (void);
+int dodepth (void);
+int dodup (void);
+int dodrop (void);
+int doswap (void);
+int dorot (void);
+int dounrot (void);
+int doroll (void);
+int dounroll (void);
+int dopick (void);
+int docol (void);
+int doplus (void);
+int dominus (void);
+int domult (void);
+int dodiv (void);
+int dosin (void);
+int docos (void);
+int dosinc (void);
+int doexp (void);
+int dopi (void);
+int doe (void);
+int nooutput (void);
+
+
+struct command commands[] = {
+ { doclear, "clear" },
+ { doquit, "quit" },
+ { dowrite, "write" },
+ { dodepth, "depth" },
+ { dodup, "dup" },
+ { dodrop, "drop" },
+ { doswap, "swap" },
+ { dorot, "rot" },
+ { dounrot, "unrot" },
+ { doroll, "roll" },
+ { dounroll, "unroll" },
+ { dopick, "pick" },
+ { docol, ":" },
+ { doplus, "+" },
+ { dominus, "-" },
+ { domult, "*" },
+ { dodiv, "/" },
+ { dosin, "sin" },
+ { docos, "cos" },
+ { dosinc, "sinc" },
+ { doexp, "exp" },
+ { dopi, "PI" },
+ { doe, "E" },
+ { nooutput, ";" },
+ { NULL, NULL }
+};
+
+
+double
+sinc (double x)
+{
+ if (x == 0.0) return 1.0;
+ else return sin (x) / x;
+}
+
+double
+safediv (double x, double y)
+{
+ double val;
+
+ if (y == 0.0)
+ {
+ if (x == 0.0) val = NAN;
+ else val = INF;
+ }
+ else
+ {
+ val = x / y;
+ }
+
+ return val;
+}
+
+
+int
+check_depth (void)
+{
+ int depth = 0;
+ struct stack *stp;
+
+ stp = stack;
+
+ while (stp != NULL) { depth++; stp = stp->next; }
+
+ return depth;
+}
+
+int
+check_dims (void)
+{
+ if (check_depth () < 2) return 0;
+ return (stack->data->length == stack->next->data->length
+ || stack->data->length == 1);
+}
+
+int
+check1 (void)
+{
+ return (check_depth () >= 1);
+}
+
+int
+check2 (void)
+{
+ return (check_depth () >= 2);
+}
+
+int
+check3 (void)
+{
+ return (check_depth () >= 3);
+}
+
+/* []n ... []1 -> */
+int
+doclear (void)
+{
+ while (!dodrop ());
+ return 0;
+}
+
+int
+doquit (void)
+{
+ doclear ();
+
+ exit (0);
+
+ /* not reached */
+ return 1;
+}
+
+int
+dowrite (void)
+{
+ unsigned long k;
+ FILE *fp;
+
+ if (!check_dims ()) return 1;
+
+ fp = fopen (WRITE_FILENAME, "wt");
+
+ for (k = 0; k < stack->data->length; k++)
+ fprintf (fp, "%lf, %lf\n", stack->next->data->data[k],
+ stack->data->data[k]);
+
+ fclose (fp);
+
+ return 0;
+}
+
+/* []n ... []1 -> []n ... []1 [n] */
+int
+dodepth (void)
+{
+ return dopush ((double) check_depth ());
+}
+
+/* []1 -> []1' []1 */
+int
+dodup (void)
+{
+ unsigned long k;
+ struct stack *stk_new;
+
+ if (!check1 ()) return 1;
+
+ stk_new = malloc (sizeof (struct stack));
+ stk_new->data = malloc (sizeof (array_t));
+ stk_new->data->data = malloc (stack->data->length * sizeof (double));
+
+ for (k = 0; k < stack->data->length; k++)
+ stk_new->data->data[k] = stack->data->data[k];
+
+ stk_new->data->length = stack->data->length;
+
+ stk_new->next = stack;
+ stack = stk_new;
+
+ return 0;
+}
+
+/* []1 -> */
+int
+dodrop (void)
+{
+ struct stack *stk;
+
+ if (!check1 ()) return 1;
+
+ stk = stack;
+ stack = stack->next;
+
+ free (stk->data->data);
+ free (stk->data);
+ free (stk);
+
+ return 0;
+}
+
+/* []2 []1 -> []1 []2 */
+int
+doswap (void)
+{
+ struct stack *stk;
+
+ if (!check2 ()) return 1;
+
+ stk = stack;
+ stack = stack->next;
+ stk->next = stack->next;
+ stack->next = stk;
+
+ return 0;
+}
+
+/* []3 []2 []1 -> []2 []1 []3 */
+int
+dorot (void)
+{
+ struct stack *stk;
+
+ if (!check3 ()) return 1;
+
+ stk = stack->next->next;
+ stack->next->next = stk->next;
+ stk->next = stack;
+ stack = stk;
+
+ return 0;
+}
+
+/* []3 []2 []1 -> []1 []3 []2 */
+int
+dounrot (void)
+{
+ struct stack *stk;
+
+ if (!check3 ()) return 1;
+
+ stk = stack;
+ stack = stack->next;
+ stk->next = stack->next->next;
+ stack->next->next = stk;
+
+ return 0;
+}
+
+/* []n ... []2 [n]1 -> []n-1 ... []2 []n */
+int
+doroll (void)
+{
+ return 0;
+}
+
+/* ... []2 [n]1 -> []2(n) ... */
+int
+dounroll (void)
+{
+ return 0;
+}
+
+/* []n ... []2 [n] -> []n ... []2 []n */
+int
+dopick (void)
+{
+ return 0;
+}
+
+/* [start] [incr] [end] -> [start:incr:end] */
+int
+docol (void)
+{
+ double *x, start, incr, end;
+ unsigned long length, idx;
+ struct stack *new_stack;
+
+
+ /* check args */
+ if (!check3 ()) return 1;
+ if (stack->data->length + stack->next->data->length
+ + stack->next->next->data->length != 3) return 1;
+
+ /* get args and clear stack */
+ start = stack->next->next->data->data[0];
+ incr = stack->next->data->data[0];
+ end = stack->data->data[0];
+
+ dodrop (); dodrop (); dodrop ();
+
+ length = (unsigned long)((end - start) / incr + 1);
+
+ /* create new slot */
+ new_stack = malloc (sizeof (struct stack));
+
+ new_stack->data = malloc (sizeof (array_t));
+ new_stack->data->data = malloc (length * sizeof (double));
+ new_stack->data->length = length;
+
+ if (stack == NULL)
+ {
+ new_stack->next = NULL;
+ stack = new_stack;
+ }
+ else
+ {
+ new_stack->next = stack;
+ stack = new_stack;
+ }
+
+ /* create the new array */
+ for (idx = 0; idx < (length + 1) / 2; idx++)
+ {
+ stack->data->data[idx] = start + (double)idx * incr;
+ stack->data->data[length - idx - 1] = end - (double)idx * incr;
+ }
+
+ return 0;
+}
+
+/* [a] [b] -> [a + b] */
+int
+doplus (void)
+{
+ unsigned long k;
+
+ if (!check_dims ()) return 1;
+
+ for (k = 0; k < stack->data->length; k++)
+ {
+ if (stack->data->length == 1)
+ stack->next->data->data[k] = (stack->next->data->data[k]
+ + stack->data->data[0]);
+ else
+ stack->next->data->data[k] = (stack->next->data->data[k]
+ + stack->data->data[k]);
+ }
+
+ dodrop ();
+
+ return 0;
+}
+
+/* [a] [b] -> [a - b] */
+int
+dominus (void)
+{
+ unsigned long k;
+
+ if (!check_dims ()) return 1;
+
+ for (k = 0; k < stack->data->length; k++)
+ {
+ if (stack->data->length == 1)
+ stack->next->data->data[k] = (stack->next->data->data[k]
+ - stack->data->data[0]);
+ else
+ stack->next->data->data[k] = (stack->next->data->data[k]
+ - stack->data->data[k]);
+ }
+
+ dodrop ();
+
+ return 0;
+}
+
+/* [a] [b] -> [a * b] */
+int
+domult (void)
+{
+ unsigned long k;
+
+ if (!check_dims ()) return 1;
+
+ for (k = 0; k < stack->data->length; k++)
+ {
+ if (stack->data->length == 1)
+ stack->next->data->data[k] = (stack->next->data->data[k]
+ * stack->data->data[0]);
+ else
+ stack->next->data->data[k] = (stack->next->data->data[k]
+ * stack->data->data[k]);
+ }
+
+ dodrop ();
+
+ return 0;
+}
+
+/* [a] [b] -> [a / b] */
+int
+dodiv (void)
+{
+ unsigned long k;
+
+ if (!check_dims ()) return 1;
+
+ for (k = 0; k < stack->data->length; k++)
+ {
+ if (stack->data->length == 1)
+ stack->next->data->data[k] = safediv (stack->next->data->data[k],
+ stack->data->data[0]);
+ else
+ stack->next->data->data[k] = safediv (stack->next->data->data[k],
+ stack->data->data[k]);
+ }
+
+ dodrop ();
+
+ return 0;
+}
+
+/* [a] -> [sin (a)] */
+int
+dosin (void)
+{
+ unsigned long k;
+
+ if (!check1 ()) return 1;
+
+ for (k = 0; k < stack->data->length; k++)
+ stack->data->data[k] = sin (stack->data->data[k]);
+
+ return 0;
+}
+
+/* [a] -> [cos (a)] */
+int
+docos (void)
+{
+ unsigned long k;
+
+ if (!check1 ()) return 1;
+
+ for (k = 0; k < stack->data->length; k++)
+ stack->data->data[k] = cos (stack->data->data[k]);
+
+ return 0;
+}
+
+/* [a] -> [sin (a) / a] */
+int
+dosinc (void)
+{
+ unsigned long k;
+
+ if (!check1 ()) return 1;
+
+ for (k = 0; k < stack->data->length; k++)
+ stack->data->data[k] = sinc (stack->data->data[k]);
+
+ return 0;
+}
+
+/* [a] -> [exp (a)] */
+int
+doexp (void)
+{
+ unsigned long k;
+
+ if (!check1 ()) return 1;
+
+ for (k = 0; k < stack->data->length; k++)
+ stack->data->data[k] = exp (stack->data->data[k]);
+
+ return 0;
+}
+
+/* -> [PI] */
+int
+dopi (void)
+{
+ dopush (PI);
+ return 0;
+}
+
+/* -> [E] */
+int
+doe (void)
+{
+ dopush (E);
+ return 0;
+}
+
+/* -> [value] */
+int
+dopush (double value)
+{
+ struct stack *new_stack;
+
+ new_stack = malloc (sizeof (struct stack));
+
+ new_stack->data = malloc (sizeof (array_t));
+ new_stack->data->data = malloc (sizeof (double));
+ new_stack->data->data[0] = value;
+ new_stack->data->length = 1;
+
+ if (stack == NULL)
+ {
+ new_stack->next = NULL;
+ stack = new_stack;
+ }
+ else
+ {
+ new_stack->next = stack;
+ stack = new_stack;
+ }
+
+ return 0;
+}
+
+int
+nooutput (void)
+{
+ print_output = 0;
+ return 0;
+}
+
+void
+print_array (double *array, unsigned long length)
+{
+ unsigned long k;
+
+ printf ("[");
+
+ for (k = 0; k < length; k++) printf (" %lf", array[k]);
+
+ printf ("]\n");
+}
+
+void
+dispatch (char *command)
+{
+ int k = 0;
+
+ if (isdigit (command[0]) || command[0] == '.' || command[0] == '-')
+ {
+ double num;
+
+ sscanf (command, "%lf", &num);
+ dopush (num);
+ return;
+ }
+
+ while (commands[k].command_name != NULL)
+ {
+ if (!strcmp (command, commands[k].command_name))
+ {
+ if (commands[k].command ())
+ printf (" Error -> incorrect usage\n");
+
+ return;
+ }
+
+ k++;
+ }
+
+ printf (" Error -> command '%s' not found\n", command);
+}
+
+
+int
+isvalid (char c)
+{
+ return isalnum (c) || ispunct (c);
+}
+
+
+int
+main (void)
+{
+ char *input;
+ int istart, iend;
+ unsigned long k;
+ struct stack *stk;
+
+ input = malloc (MAX_INPUT_LENGTH);
+
+ for (;;)
+ {
+ print_output = 1;
+
+ fgets (input, MAX_INPUT_LENGTH, stdin);
+
+ iend = 0;
+
+ while (input[iend])
+ {
+ istart = iend;
+ while (!isvalid (input[istart])) istart++;
+ iend = istart;
+ while (isvalid (input[iend])) iend++;
+ input[iend] = '\0';
+ iend++;
+
+ dispatch (input + istart);
+ }
+
+ /* print the stack */
+ if (print_output)
+ {
+ stk = stack;
+ for (k = 0; k < 4; k++)
+ {
+ if (k + 1 > (unsigned long)check_depth ()) break;
+ printf ("%d: ", k + 1);
+ print_array (stk->data->data, stk->data->length);
+
+ stk = stk->next;
+ }
+ }
+ }
+
+ /* not reached */
+ return 0;
+}
diff --git a/plot/pld.ico b/plot/pld.ico
new file mode 100755
index 0000000..18e1a8d
--- /dev/null
+++ b/plot/pld.ico
Binary files differ
diff --git a/plot/plot.c b/plot/plot.c
new file mode 100755
index 0000000..3d7ab92
--- /dev/null
+++ b/plot/plot.c
@@ -0,0 +1,2101 @@
+ /* plot.c
+ * Plot data from a file.
+ */
+
+#include <windows.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+#include <limits.h>
+#include "plot.h"
+
+
+/* global variables */
+
+/* main window handle */
+HWND hWnd;
+/* this application instance */
+HANDLE ghInstance;
+
+/* default cursor (cross) and wait cursor (hourglass) */
+HCURSOR hdefcursor, hwaitcursor;
+/* foreground color, background color, and font color */
+COLORREF fgColor, bgColor, fnColor;
+/* font to use for labels */
+HFONT hFont;
+
+/* the x and y parts of the data */
+double *xdata = NULL, *ydata = NULL;
+/* the minimum and maximum values displayed */
+double x_min, x_max, y_min, y_max;
+/* the number of items in the data arrays */
+unsigned long n_items = 0;
+
+/* which transform algorithm to use */
+enum transform_algorithm transform_algorithm = FFT2;
+/* window function to put the data through before the transform */
+enum window_function window_function = SQUARE;
+/* which output data to display */
+enum output_data output_data = MAGNITUDE;
+
+/* the alpha value for the hanning window */
+double hanning_alpha = 0.1;
+/* scaling factor for the square window */
+double square_scaling_factor = 1.0;
+
+/* standard function sampling frequency */
+int sf_sample_freq = 1000;
+/* standard function base frequency */
+int sf_base_freq = 100;
+/* standard function amplitude */
+double sf_amplitude = 1.0;
+/* standard function duration */
+double sf_duration = 1.0;
+
+
+/* Transform Region has been selected and the app is waiting for a region */
+int get_transform_region = 0;
+/* need to find the limits of the new view */
+int zooming_in = 0;
+/* Transform or Transform Region has been selected and is being processed */
+int in_transform = 0;
+/* whether or not to print out information during the fft */
+int debug_fft = 0;
+
+
+/* xmalloc
+ * Allocate memory and ensure that NULL values are flagged.
+ */
+void *
+xmalloc (size_t amt)
+{
+ void *mem;
+ char buffer[64];
+
+ mem = malloc (amt);
+
+ if (mem == NULL)
+ {
+ sprintf (buffer, "Error allocating %ld bytes of memory - bailing.", amt);
+ MessageBox (hWnd, buffer, "Fatal Error", MB_OK | MB_ICONASTERISK);
+ PostQuitMessage (0);
+ }
+
+ return mem;
+}
+
+void
+wait_cursor (void)
+{
+ hdefcursor = SetCursor (hwaitcursor);
+}
+
+void
+default_cursor (void)
+{
+ hwaitcursor = SetCursor (hdefcursor);
+}
+
+
+void
+get_client_rect (RECT *rc)
+{
+ GetClientRect (hWnd, rc);
+
+ rc->bottom -= STATUS_HEIGHT;
+}
+
+
+void
+data_limits (void)
+{
+ unsigned long k;
+
+ if (xdata == NULL || ydata == NULL) return;
+
+ if (zooming_in)
+ zooming_in = 0;
+
+ x_min = x_max = xdata[0];
+ y_min = y_max = ydata[0];
+
+
+ for (k = 0; k < n_items; k++)
+ {
+ if (xdata[k] < x_min) x_min = xdata[k];
+ if (xdata[k] > x_max) x_max = xdata[k];
+ if (ydata[k] < y_min) y_min = ydata[k];
+ if (ydata[k] > y_max) y_max = ydata[k];
+ }
+}
+
+
+void
+draw_status (int x, int y)
+{
+ char buffer[64];
+ double xspan, yspan, xsspan, ysspan, xpos, ypos;
+ static int last_x, last_y;
+ RECT status_rc, rc;
+ HDC hDC;
+ unsigned int foo;
+
+ GetClientRect (hWnd, &rc);
+
+ if (xdata == NULL || ydata == NULL || x_min > x_max || y_min > y_max)
+ {
+ buffer[0] = '\0';
+ }
+ else if (get_transform_region)
+ {
+ sprintf (buffer, "Select region to be transformed...");
+ }
+ else if (in_transform)
+ {
+ sprintf (buffer, "Calculating transform - Ctrl+Break to stop");
+ }
+ else
+ {
+ if (x < 0) x = last_x;
+ if (y < 0) y = last_y;
+
+ xspan = x_max - x_min;
+ yspan = y_max - y_min;
+ xsspan = (double)rc.right - rc.left;
+ ysspan = (double)rc.bottom - rc.top;
+
+ xpos = x_min + ((double)(x - rc.left)) * xspan / xsspan;
+
+ /* this is necessary because the borland compiler is syntax retarded */
+ foo = rc.bottom - STATUS_HEIGHT;
+
+ ypos = y_min + ((double)(foo - y)) * yspan / ysspan;
+ sprintf (buffer, "x: %lf, y: %lf", xpos, ypos);
+ }
+
+ status_rc.left = rc.left;
+ status_rc.right = rc.right;
+ status_rc.bottom = rc.bottom;
+ status_rc.top = rc.bottom - STATUS_HEIGHT;
+
+ hDC = GetDC (hWnd);
+ DrawStatusText (hDC, &status_rc, buffer, SBT_POPOUT);
+ ReleaseDC (hWnd, hDC);
+
+ last_x = x;
+ last_y = y;
+}
+
+
+void
+hanning (double *x, unsigned long N, double alpha)
+{
+ unsigned long n;
+
+ for (n = 0; n < N; n++)
+ x[REAL_IDX (n)] = alpha + (1 - alpha) * cos (2 * n * M_PI / N);
+}
+
+void
+square (double *x, unsigned long N, double scale)
+{
+ unsigned long k;
+
+ if (scale == 1.0) return;
+
+ for (k = 0; k < N; k++) x[REAL_IDX (k)] *= scale;
+}
+
+/* dft
+ * Discrete Fourier Transform. Slower than molasses - use with caution.
+ */
+void
+dft (double *x, unsigned long N)
+{
+ double *y, scale;
+ unsigned long j, k;
+
+ scale = 1 / sqrt (N);
+
+ y = malloc (2 * N * sizeof (double));
+
+ for (k = 0; k < N; k++)
+ {
+ y[REAL_IDX (k)] = 0.0;
+ y[IMAG_IDX (k)] = 0.0;
+
+ for (j = 0; j < N; j++)
+ {
+ double tpjkN, rt, it;
+
+ tpjkN = 2 * M_PI * j * k / N;
+ rt = cos (tpjkN);
+ it = sin (tpjkN);
+
+ y[REAL_IDX (k)] += x[REAL_IDX (j)] * rt - x[IMAG_IDX (j)] * it;
+ y[IMAG_IDX (k)] += x[IMAG_IDX (j)] * rt + x[REAL_IDX (j)] * it;
+ }
+
+ y[REAL_IDX (k)] *= scale;
+ y[IMAG_IDX (k)] *= scale;
+ }
+
+ for (k = 0; k < N; k++)
+ {
+ x[REAL_IDX (k)] = y[REAL_IDX (k)];
+ x[IMAG_IDX (k)] = y[IMAG_IDX (k)];
+ }
+
+ free (y);
+}
+
+
+enum fftstate {
+ FFT_INIT, FFT_BREV, FFT_ITER, FFT_END
+};
+
+void
+arrprint (double *x, unsigned long N, FILE *fp)
+{
+ unsigned long k;
+
+ fprintf (fp, "[ ");
+
+ for (k = 0; k < N; k++)
+ fprintf (fp, "%lf + %lf i ", x[REAL_IDX (k)], x[IMAG_IDX (k)]);
+
+ fprintf (fp, "]\n");
+}
+
+void
+fftprint (double *x, unsigned long N, char *buf, enum fftstate fftstate)
+{
+ static FILE *fp;
+
+ if (!debug_fft) return;
+
+ switch (fftstate)
+ {
+ case FFT_INIT:
+ fp = fopen ("fftdebug.txt", "wt");
+ if (fp == NULL)
+ {
+ MessageBox (hWnd, "Error opening fftdebug.txt.",
+ "Sorry", MB_OK | MB_ICONASTERISK);
+ }
+ fprintf (fp, "%ld point FFT started\nInitial array:\n", N);
+ arrprint (x, N, fp);
+ break;
+ case FFT_BREV:
+ fprintf (fp, "After bit reversal\n");
+ arrprint (x, N, fp);
+ break;
+ case FFT_ITER:
+ fprintf (fp, "%s\n", buf);
+ arrprint (x, N, fp);
+ break;
+ case FFT_END:
+ fprintf (fp, "Final array:\n");
+ arrprint (x, N, fp);
+ fclose (fp);
+ }
+}
+
+unsigned long
+bit_reverse (unsigned long jf, unsigned long N)
+{
+ unsigned long jr = 0;
+
+ while (N >>= 1)
+ {
+ jr <<= 1;
+ jr += jf & 0x1;
+ jf >>= 1;
+ }
+
+ return jr;
+}
+
+void
+fft2 (double *x, unsigned long N)
+{
+ unsigned long butterfly_start, butterfly_length, k;
+
+ /* if the array is of size one, just return */
+ if (N == 1) return;
+
+ fftprint (x, N, NULL, FFT_INIT);
+
+ /* perform bit reversal */
+ for (k = 0; k < N; k++)
+ {
+ unsigned long kr = bit_reverse (k, N);
+
+ if (kr <= k) continue;
+
+ swap (x[REAL_IDX (k)], x[REAL_IDX (kr)]);
+ swap (x[IMAG_IDX (k)], x[IMAG_IDX (kr)]);
+ }
+
+ fftprint (x, N, NULL, FFT_BREV);
+
+ /* do the trivial butterflies separately */
+ for (k = 0; k < N; k += 2)
+ {
+ double xer = x[REAL_IDX (k)];
+ double xei = x[IMAG_IDX (k)];
+ double xor = x[REAL_IDX (k + 1)];
+ double xoi = x[IMAG_IDX (k + 1)];
+
+ x[REAL_IDX (k)] = xer + xor;
+ x[IMAG_IDX (k)] = xei + xoi;
+ x[REAL_IDX (k + 1)] = xer - xor;
+ x[IMAG_IDX (k + 1)] = xei - xoi;
+ }
+
+ fftprint (x, N, "Array after trivial butterflies", FFT_ITER);
+
+ /* loop from length 4 butterflies to length N */
+ for (butterfly_length = 4; butterfly_length <= N; butterfly_length *= 2)
+ {
+ char buffer[64];
+
+ for (k = 0; k < butterfly_length / 2; k++)
+ {
+ double rw = cos (-2 * M_PI * k / butterfly_length);
+ double iw = sin (-2 * M_PI * k / butterfly_length);
+
+ for (butterfly_start = 0;
+ butterfly_start < N;
+ butterfly_start += butterfly_length)
+ {
+ double xer = x[REAL_IDX (butterfly_start + k)];
+ double xei = x[IMAG_IDX (butterfly_start + k)];
+ double xor = x[REAL_IDX (butterfly_start+butterfly_length/2+k)];
+ double xoi = x[IMAG_IDX (butterfly_start+butterfly_length/2+k)];
+ double wxor = rw * xor - iw * xoi;
+ double wxoi = rw * xoi + iw * xor;
+
+ x[REAL_IDX (butterfly_start + k)] = xer + wxor;
+ x[IMAG_IDX (butterfly_start + k)] = xei + wxoi;
+ x[REAL_IDX (butterfly_start+butterfly_length/2+k)] = xer - wxor;
+ x[IMAG_IDX (butterfly_start+butterfly_length/2+k)] = xei - wxoi;
+ }
+ }
+
+ if (debug_fft)
+ sprintf (buffer, "Array after length %ld butterfly", butterfly_length);
+ fftprint (x, N, buffer, FFT_ITER);
+ }
+
+ fftprint (x, N, NULL, FFT_END);
+}
+
+/* FIXME
+ */
+void
+fftn (double *y, unsigned long N)
+{
+ fft2 (y, N);
+}
+
+
+double
+magnitude (double x, double y)
+{
+ return sqrt (x * x + y * y);
+}
+
+double
+phase (double x, double y)
+{
+ if (x == 0.0) return fsign (y) * M_PI / 2;
+
+ return atan (y / x);
+}
+
+/* assumes that values increase from left to right */
+void
+get_indices (unsigned long *start, unsigned long *end)
+{
+ unsigned long k = 0;
+
+ while (x_min < xdata[k] && k < n_items) k++;
+ *start = k;
+
+ while (x_max > xdata[k] && k < n_items) k++;
+ *end = k;
+}
+
+void
+transform (void)
+{
+ char buffer[256];
+ unsigned long start, end, N = 1, k;
+ double *x, *y, sample_interval = 0.0, sample_freq;
+
+ in_transform = 1;
+ wait_cursor ();
+
+ get_indices (&start, &end);
+ while (N < end - start) N <<= 1; /* power of 2 length */
+
+ /* find the sampling frequency */
+ for (k = 0; k < n_items - 2; k++)
+ {
+ sample_interval += fabs (xdata[k + 1] - xdata[k]);
+ }
+
+ sample_freq = (n_items - 2) / sample_interval;
+
+ x = xmalloc (N * sizeof (double));
+ y = xmalloc (2 * N * sizeof (double));
+
+ /* copy the data and zero pad as necessary */
+ for (k = 0; k < N; start++, k++)
+ {
+ x[k] = k * sample_freq / (double)N;
+
+ y[REAL_IDX (k)] = (start <= end) ? ydata[start] : 0.0;
+ y[IMAG_IDX (k)] = 0.0;
+ }
+
+ free (xdata); xdata = NULL;
+ free (ydata); ydata = NULL;
+
+ switch (window_function)
+ {
+ case HANNING:
+ hanning (y, N, hanning_alpha);
+ break;
+ case SQUARE:
+ square (y, N, square_scaling_factor);
+ break;
+ }
+
+
+ /* do the transform */
+ switch (transform_algorithm)
+ {
+ case DFT:
+ dft (y, N);
+ break;
+ case FFT2:
+ fft2 (y, N);
+ break;
+ case FFTN:
+/* N = end - start; */
+ fftn (y, N);
+ break;
+ }
+
+
+ xdata = x;
+ ydata = xmalloc (N * sizeof (double));
+ for (k = 0; k < N; k++)
+ {
+ switch (output_data)
+ {
+ case REAL:
+ ydata[k] = y[REAL_IDX (k)];
+ break;
+ case IMAGINARY:
+ ydata[k] = y[IMAG_IDX (k)];
+ break;
+ case MAGNITUDE:
+ ydata[k] = magnitude (y[REAL_IDX (k)], y[IMAG_IDX (k)]);
+ break;
+ case PHASE:
+ ydata[k] = phase (y[REAL_IDX (k)], y[IMAG_IDX (k)]);
+ break;
+ }
+ }
+
+
+ n_items = N;
+
+ data_limits ();
+ InvalidateRect (hWnd, NULL, FALSE);
+
+ default_cursor ();
+ in_transform = 0;
+}
+
+void
+transform_region (void)
+{
+ get_transform_region = 1;
+}
+
+
+/* enable_menus
+ * Called when a datafile is first opened to allow the grayed out
+ * menu items to be used.
+ */
+void
+enable_menus (void)
+{
+ unsigned int menu_list[] = { IDM_LIMITS, IDM_ORIGINAL, IDM_DATA,
+ IDM_TRANSFORM, IDM_TRANSREGION,
+ IDM_ZOOM_IN, IDM_ZOOM_OUT, IDM_ROTATE };
+ int k;
+ static int menus_are_enabled = 0;
+
+ if (menus_are_enabled) return;
+
+ for (k = 0; k < 8; k++)
+ EnableMenuItem (GetMenu (hWnd), menu_list[k], MF_ENABLED);
+
+ menus_are_enabled = 1;
+}
+
+
+/* zoom_in
+ * Doesn't actually perform a zoom. Calculates the coordinates which
+ * a given zoom will use and stores them to (x|y)_(min|max).
+ */
+void
+zoom_in (int xl, int yt, int xr, int yb)
+{
+ double xspan, yspan, xsspan, ysspan;
+ HDC hDC;
+ RECT rc;
+
+ get_client_rect (&rc);
+
+ xspan = x_max - x_min;
+ yspan = y_max - y_min;
+ xsspan = (double)rc.right - rc.left;
+ ysspan = (double)rc.bottom - rc.top;
+
+ x_min = x_min + ((double)(xl - rc.left)) * xspan / xsspan;
+ x_max = x_max - ((double)(rc.right - xr)) * xspan / xsspan;
+
+ y_min = y_min + ((double)(rc.bottom - yb)) * yspan / ysspan;
+ y_max = y_max - ((double)(yt - rc.top)) * yspan / ysspan;
+
+ zooming_in = 1;
+}
+
+
+/* get_data
+ * Reads the .pld file FILE_NAME and stores the points in the file
+ * in the arrays xdata and ydata.
+ */
+void
+get_data (char *file_name)
+{
+ unsigned long max_items;
+ FILE *fp;
+
+ fp = fopen (file_name, "rt");
+
+ if (xdata != NULL) { free (xdata); xdata = NULL; }
+ if (ydata != NULL) { free (ydata); ydata = NULL; }
+ n_items = 0;
+ max_items = 0;
+
+ while (!feof (fp))
+ {
+ if (n_items == max_items)
+ {
+ max_items = (max_items) ? max_items << 1 : 1;
+ xdata = realloc (xdata, max_items * sizeof (double));
+ ydata = realloc (ydata, max_items * sizeof (double));
+ }
+
+ if (fscanf (fp, "%lf, %lf", &xdata[n_items], &ydata[n_items]) != 2)
+ continue;
+ n_items++;
+ }
+
+ fclose (fp);
+
+ if (!n_items)
+ {
+ MessageBox (hWnd, "Invalid PLD file.",
+ "Error", MB_OK | MB_ICONASTERISK);
+ if (xdata != NULL) { free (xdata); xdata = NULL; }
+ if (ydata != NULL) { free (ydata); ydata = NULL; }
+ return;
+ }
+
+ data_limits ();
+}
+
+/* get_audio_data
+ * Opens a .wav file, reads it, and plots the data.
+ */
+void
+get_audio_data (char *filename)
+{
+ HMMIO hmmio;
+ MMIOINFO mmioinfo;
+ MMCKINFO mmckinfo, mmckinfo_fmt, mmckinfo_data; /* chunk info */
+ WAVEFORMATEX *wfe;
+ int wfe_size, data_size;
+ unsigned char *data, *pdata;
+ double freq_interval;
+ unsigned long sample_size, max_items;
+
+ if (xdata != NULL) { free (xdata); xdata = NULL; }
+ if (ydata != NULL) { free (ydata); ydata = NULL; }
+ n_items = 0;
+
+
+ hmmio = mmioOpen (filename, NULL, MMIO_READ | MMIO_ALLOCBUF);
+
+ if (hmmio == NULL)
+ {
+ MessageBox (hWnd, "Error opening MM file.",
+ "Error", MB_OK | MB_ICONASTERISK);
+ return;
+ }
+
+ /* check that this is a wave file */
+ mmckinfo.fccType = mmioFOURCC ('W', 'A', 'V', 'E');
+ if (mmioDescend (hmmio, &mmckinfo, NULL, MMIO_FINDRIFF))
+ {
+ /* error */
+ MessageBox (hWnd, "Not a wave file.",
+ "Error", MB_OK | MB_ICONASTERISK);
+ return;
+ }
+
+ mmckinfo_fmt.ckid = mmioFOURCC ('f', 'm', 't', ' ');
+ if (mmioDescend (hmmio, &mmckinfo_fmt, &mmckinfo, MMIO_FINDCHUNK))
+ {
+ /* error */
+ MessageBox (hWnd, "Missing FMT chunk.",
+ "Error", MB_OK | MB_ICONASTERISK);
+ return;
+ }
+
+ wfe_size = mmckinfo_fmt.cksize;
+ wfe = xmalloc (wfe_size);
+
+ mmioRead (hmmio, (HPSTR)wfe, wfe_size);
+
+ mmioAscend (hmmio, &mmckinfo_fmt, 0);
+
+ if (wfe->wFormatTag != WAVE_FORMAT_PCM)
+ {
+ /* error */
+ MessageBox (hWnd, "Not a PCM wave file.",
+ "Error", MB_OK | MB_ICONASTERISK);
+ return;
+ }
+
+ mmckinfo_data.ckid = mmioFOURCC ('d', 'a', 't', 'a');
+ if (mmioDescend (hmmio, &mmckinfo_data, &mmckinfo, MMIO_FINDCHUNK))
+ {
+ /* error */
+ MessageBox (hWnd, "Missing DATA chunk.",
+ "Error", MB_OK | MB_ICONASTERISK);
+ return;
+ }
+
+ data_size = mmckinfo_data.cksize;
+ data = xmalloc (data_size);
+
+ mmioRead (hmmio, (HPSTR)data, data_size);
+
+ sample_size = wfe->nChannels * wfe->wBitsPerSample / 8;
+ max_items = data_size / sample_size;
+ freq_interval = 1.0 / (double)wfe->nSamplesPerSec;
+
+ xdata = xmalloc (max_items * sizeof (double));
+ ydata = xmalloc (max_items * sizeof (double));
+
+ pdata = data;
+
+/* if (1) */
+/* { */
+/* char *buffer; */
+/* buffer = xmalloc (256); */
+/* sprintf (buffer, "%d channel %d bits %d samples at %d Hz", */
+/* wfe->nChannels, wfe->wBitsPerSample, max_items, */
+/* wfe->nSamplesPerSec); */
+/* MessageBox (hWnd, buffer, "Info", MB_OK | MB_ICONASTERISK); */
+/* free (buffer); */
+/* } */
+
+ while (n_items < max_items)
+ {
+ unsigned short lsample, rsample, sample;
+
+ xdata[n_items] = (double)n_items * freq_interval;
+
+ if (wfe->nChannels == 2)
+ {
+ if (wfe->wBitsPerSample == 16) /* 2 channel 16 bit */
+ {
+ lsample = pdata[0] + (pdata[1] << 8);
+ rsample = pdata[2] + (pdata[3] << 8);
+ }
+ else /* 2 channel 8 bit */
+ {
+ lsample = pdata[0];
+ rsample = pdata[1];
+ }
+
+ /* average left and right */
+ sample = (lsample >> 1) + (rsample >> 1);
+ }
+ else
+ {
+ if (wfe->wBitsPerSample == 16) /* 1 channel 16 bit */
+ sample = pdata[0] + (pdata[1] << 8);
+ else /* 1 channel 8 bit */
+ sample = pdata[0];
+ }
+
+ /* normalize */
+ if (wfe->wBitsPerSample == 16) sample += 0x8000;
+ ydata[n_items] = (double)sample;
+ ydata[n_items] /= (wfe->wBitsPerSample == 16) ? 32767 : 127;
+ ydata[n_items] -= 1.0;
+
+ pdata += sample_size;
+ n_items++;
+ }
+
+ free (data);
+ free (wfe);
+ mmioClose (hmmio, 0);
+
+ data_limits ();
+}
+
+/* clear_screen
+ * Draw the background color over the entire client area.
+ */
+void
+clear_screen (void)
+{
+/* PAINTSTRUCT ps; */
+ HDC hDC;
+ RECT rc;
+ HBRUSH hOldBrush;
+
+ hDC = GetDC (hWnd);
+
+ hOldBrush = SelectObject (hDC, CreateSolidBrush (bgColor));
+
+ get_client_rect (&rc);
+ Rectangle (hDC, rc.left, rc.top, rc.right, rc.bottom);
+
+ SelectObject (hDC, hOldBrush);
+ DeleteObject (hOldBrush);
+
+ ReleaseDC (hWnd, hDC);
+}
+
+/* plot_data
+ * Calculates the screen limits if necessary and plots the data in
+ * the arrays xdata and ydata to the screen using a polyline.
+ */
+void
+plot_data (void)
+{
+ unsigned long k, point_x, point_y;
+ double x_span, y_span;
+ HDC hDC;
+ RECT rc;
+ HPEN hPen_old;
+ POINT *pts;
+
+ if (xdata == NULL || ydata == NULL) return;
+
+ pts = xmalloc (n_items * sizeof (POINT));
+ ZeroMemory (pts, n_items * sizeof (POINT));
+
+ hDC = GetDC (hWnd);
+ hPen_old = SelectObject (hDC, CreatePen (PS_SOLID, 0, fgColor));
+
+ x_span = x_max - x_min;
+ y_span = y_max - y_min;
+
+ get_client_rect (&rc);
+
+ for (k = 0; k < n_items; k++)
+ {
+ pts[k].x = (xdata[k] - x_min) * ((double)(rc.right - rc.left)) / x_span;
+ pts[k].y = (rc.bottom - ((ydata[k] - y_min)
+ * ((double)(rc.bottom - rc.top))
+ / y_span));
+ }
+
+ Polyline (hDC, pts, n_items);
+
+ SelectObject (hDC, hPen_old);
+ ReleaseDC (hWnd, hDC);
+
+ free (pts);
+}
+
+
+/* open_file
+ * Gets a filename, opens it, and plots the data.
+ */
+void
+open_file (int type)
+{
+ char *buffer;
+ char *window_text;
+ OPENFILENAME ofn;
+
+ buffer = xmalloc (2048);
+ ZeroMemory (buffer, 2048);
+ window_text = xmalloc (64);
+ ZeroMemory (window_text, 64);
+
+ ZeroMemory (&ofn, sizeof (OPENFILENAME));
+ ofn.lStructSize = sizeof (OPENFILENAME);
+ ofn.hwndOwner = hWnd;
+ ofn.hInstance = ghInstance;
+ ofn.lpstrFilter = ("Plotter Data Files (*.pld)\0*.pld\0"
+ "Wave Files (*.wav)\0*.wav\0"
+ "All Files (*.*)\0*.*\0");
+ ofn.nFilterIndex = (type == IDM_OPEN_AUDIO) ? 2 : 1;
+ ofn.lpstrFile = buffer;
+ ofn.nMaxFile = 2048;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
+
+ if (GetOpenFileName (&ofn))
+ {
+ wait_cursor ();
+
+ if (xdata != NULL) { free (xdata); xdata = NULL; }
+ if (ydata != NULL) { free (ydata); ydata = NULL; }
+
+ if (strstr (ofn.lpstrFile, ".wav") != NULL)
+ get_audio_data (ofn.lpstrFile);
+ else
+ get_data (ofn.lpstrFile);
+
+ sprintf (window_text, "Data Plotter - %s",
+ ofn.lpstrFile + ofn.nFileOffset);
+ SetWindowText (hWnd, window_text);
+
+ /* enable menus (since there is data now) */
+ enable_menus ();
+ data_limits (); /* this shouldn't be here */
+
+ InvalidateRect (hWnd, NULL, FALSE);
+
+ default_cursor ();
+ }
+
+ free (buffer);
+ free (window_text);
+}
+
+void
+rotate_data (void)
+{
+ unsigned long k;
+
+ if (xdata == NULL || ydata == NULL) return;
+
+ for (k = 0; k < n_items / 2; k++)
+ {
+ swap (ydata[k], ydata[k + n_items / 2]);
+ xdata[k + n_items / 2] = xdata[k];
+ }
+ for (k = 0; k < n_items / 2; k++)
+ xdata[k] = -xdata[n_items - k - 1];
+
+ data_limits ();
+ InvalidateRect (hWnd, NULL, FALSE);
+}
+
+/* set_font
+ * Uses a standard dialog to set the font used for plot annotation.
+ */
+void
+set_font (void)
+{
+ CHOOSEFONT cf;
+ LOGFONT lf;
+
+ ZeroMemory (&cf, sizeof (CHOOSEFONT));
+ cf.lStructSize = sizeof (CHOOSEFONT);
+ cf.hwndOwner = hWnd;
+ cf.lpLogFont = &lf;
+ cf.Flags = CF_EFFECTS | CF_FORCEFONTEXIST | CF_SCREENFONTS;
+ cf.rgbColors = fnColor;
+
+ if (ChooseFont (&cf))
+ {
+ hFont = CreateFontIndirect (&lf);
+ fnColor = cf.rgbColors;
+ }
+}
+
+/* SetColorDlgProc
+ * The window function for the color dialog box. Enables the color
+ * of the plot and the background to be changed.
+ */
+LRESULT CALLBACK
+SetColorDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ CHOOSECOLOR cc;
+ static COLORREF newfgColor, newbgColor;
+ RECT rc;
+ HBRUSH hbOld;
+ DRAWITEMSTRUCT sdis, *dis;
+ static COLORREF acrCustClr[16];
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ newfgColor = fgColor;
+ newbgColor = bgColor;
+
+ return TRUE;
+ case WM_DRAWITEM:
+ dis = (DRAWITEMSTRUCT *)lParam;
+
+ if (wParam == BID_FGCOLOR)
+ hbOld = SelectObject (dis->hDC, CreateSolidBrush (newfgColor));
+ else if (wParam == BID_BGCOLOR)
+ hbOld = SelectObject (dis->hDC, CreateSolidBrush (newbgColor));
+ else
+ return FALSE;
+
+ Rectangle (dis->hDC, dis->rcItem.left, dis->rcItem.top,
+ dis->rcItem.right, dis->rcItem.bottom);
+
+ SelectObject (dis->hDC, hbOld);
+
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD (wParam))
+ {
+ case CLR_FOREGROUND: /* fall through */
+ case CLR_BACKGROUND:
+ ZeroMemory (&cc, sizeof (CHOOSECOLOR));
+ cc.lStructSize = sizeof (CHOOSECOLOR);
+ cc.hwndOwner = hDlg;
+ cc.lpCustColors = acrCustClr;
+ cc.rgbResult = (wParam == CLR_FOREGROUND) ? newfgColor : newbgColor;
+ cc.Flags = CC_RGBINIT | CC_FULLOPEN;
+
+ if (ChooseColor (&cc))
+ {
+ int bid;
+
+ if (wParam == CLR_FOREGROUND)
+ {
+ newfgColor = cc.rgbResult;
+ bid = BID_FGCOLOR;
+ }
+ else
+ {
+ newbgColor = cc.rgbResult;
+ bid = BID_BGCOLOR;
+ }
+
+ /* display color in the appropriate static control */
+ GetClientRect (GetDlgItem (hDlg, bid), &rc);
+ InvalidateRect (GetDlgItem (hDlg, bid), &rc, FALSE);
+ SendMessage (hDlg, WM_PAINT, NULL, NULL);
+ }
+
+ return TRUE;
+ case IDOK:
+ fgColor = newfgColor;
+ bgColor = newbgColor;
+
+ InvalidateRect (hWnd, NULL, FALSE);
+ /* fall through */
+ case 149: /* Cancel */
+ EndDialog (hDlg, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/* LimitsDlgProc
+ * Window procedure for the limits dialog box which allow the data
+ * limits to be changed.
+ */
+LRESULT CALLBACK
+LimitsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int close_dlg = 1;
+ char *buffer;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ buffer = xmalloc (256);
+
+ sprintf (buffer, "%lf", x_min);
+ SetDlgItemText (hDlg, 122, buffer);
+ sprintf (buffer, "%lf", y_min);
+ SetDlgItemText (hDlg, 124, buffer);
+ sprintf (buffer, "%lf", x_max);
+ SetDlgItemText (hDlg, 127, buffer);
+ sprintf (buffer, "%lf", y_max);
+ SetDlgItemText (hDlg, 129, buffer);
+
+ free (buffer);
+ return TRUE;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case 130: /* Cancel */
+ EndDialog (hDlg, TRUE);
+ return TRUE;
+ case 131: /* Apply */
+ close_dlg = 0;
+ case IDOK: /* OK */
+ buffer = xmalloc (256);
+
+ GetDlgItemText (hDlg, 122, buffer, 255);
+ sscanf (buffer, "%lf", &x_min);
+ GetDlgItemText (hDlg, 124, buffer, 255);
+ sscanf (buffer, "%lf", &y_min);
+ GetDlgItemText (hDlg, 127, buffer, 255);
+ sscanf (buffer, "%lf", &x_max);
+ GetDlgItemText (hDlg, 129, buffer, 255);
+ sscanf (buffer, "%lf", &y_max);
+
+ free (buffer);
+
+ InvalidateRect (hWnd, NULL, FALSE);
+
+ if (close_dlg) EndDialog (hDlg, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+void
+do_window_function_layout (HWND text, HWND edit)
+{
+ char buffer[64];
+
+ if (window_function == HANNING)
+ {
+ SetWindowText (text, "Alpha:");
+ sprintf (buffer, "%lf", hanning_alpha);
+ }
+ else if (window_function == SQUARE)
+ {
+ SetWindowText (text, "Scaling Factor:");
+ sprintf (buffer, "%lf", square_scaling_factor);
+ }
+
+ SetWindowText (edit, buffer);
+}
+
+LRESULT CALLBACK
+TransformSettingsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int k;
+ char *transform_algorithm_names[] = {
+ "Discrete Fourier Transform",
+ "Radix 2 Fast Fourier Transform",
+ "General Radix Fast Fourier Transform"
+ };
+ char *window_function_names[] = {
+ "Hanning",
+ "Square"
+ };
+ char *output_data_names[] = {
+ "Real",
+ "Imaginary",
+ "Magnitude",
+ "Phase"
+ };
+ char *buffer;
+ double temp;
+ static enum window_function original_window_function;
+ HWND hcombo;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ /* transform algorithm */
+ hcombo = GetDlgItem (hDlg, 151);
+ SendMessage (hcombo, CB_SETEXTENDEDUI, TRUE, 0);
+ SendMessage (hcombo, CB_RESETCONTENT, 0, 0);
+ for (k = 0; k < N_TRANSFORM_ALGORITHM; k++)
+ {
+ SendMessage (hcombo, CB_ADDSTRING,
+ 0, (LPARAM)transform_algorithm_names[k]);
+ }
+ SendMessage (hcombo, CB_SETCURSEL, transform_algorithm, 0);
+
+ /* window function */
+ original_window_function = window_function;
+ hcombo = GetDlgItem (hDlg, 153);
+ SendMessage (hcombo, CB_SETEXTENDEDUI, TRUE, 0);
+ SendMessage (hcombo, CB_RESETCONTENT, 0, 0);
+ for (k = 0; k < N_WINDOW_FUNCTION; k++)
+ {
+ SendMessage (hcombo, CB_ADDSTRING,
+ 0, (LPARAM)window_function_names[k]);
+ }
+ SendMessage (hcombo, CB_SETCURSEL, window_function, 0);
+
+ do_window_function_layout (GetDlgItem (hDlg, 154),
+ GetDlgItem (hDlg, 155));
+
+ /* output data */
+ hcombo = GetDlgItem (hDlg, 157);
+ SendMessage (hcombo, CB_SETEXTENDEDUI, TRUE, 0);
+ SendMessage (hcombo, CB_RESETCONTENT, 0, 0);
+ for (k = 0; k < N_OUTPUT_DATA; k++)
+ {
+ SendMessage (hcombo, CB_ADDSTRING,
+ 0, (LPARAM)output_data_names[k]);
+ }
+ SendMessage (hcombo, CB_SETCURSEL, output_data, 0);
+
+ /* use CB_GETCURSEL with wParam = 0, lParam = 0 to get current index */
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD (wParam))
+ {
+ case 153: /* window function combobox */
+ if (HIWORD (wParam) == CBN_SELCHANGE)
+ {
+ window_function = SendMessage ((HWND)lParam, CB_GETCURSEL, 0, 0);
+ do_window_function_layout (GetDlgItem (hDlg, 154),
+ GetDlgItem (hDlg, 155));
+ return TRUE;
+ }
+ return FALSE;
+ case 158: /* apply */
+ case IDOK:
+ transform_algorithm = SendMessage (GetDlgItem (hDlg, 151),
+ CB_GETCURSEL, 0, 0);
+
+ window_function = SendMessage (GetDlgItem (hDlg, 153),
+ CB_GETCURSEL, 0, 0);
+ buffer = xmalloc (64);
+ GetDlgItemText (hDlg, 155, buffer, 63);
+ sscanf (buffer, "%lf", &temp);
+ if (window_function == HANNING)
+ hanning_alpha = temp;
+ else if (window_function == SQUARE)
+ square_scaling_factor = temp;
+ free (buffer);
+
+ output_data = SendMessage (GetDlgItem (hDlg, 157),
+ CB_GETCURSEL, 0, 0);
+
+ original_window_function = window_function;
+ if (LOWORD (wParam) == 158) break;
+ case IDCANCEL:
+ window_function = original_window_function;
+ EndDialog (hDlg, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/* SettingsDlgProc
+ * Window procedure for the settings dialog box.
+ */
+LRESULT CALLBACK
+SettingsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ return TRUE;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case 112:
+ set_font ();
+ break;
+ case 114:
+ DialogBox (ghInstance, "ColorDlg", hWnd, (DLGPROC) SetColorDlgProc);
+ break;
+ case IDOK:
+ EndDialog (hDlg, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+void
+insert_data (HWND hDlg, unsigned long pos)
+{
+ unsigned long k;
+ int index_id[] = { VD_INDEX1, VD_INDEX2, VD_INDEX3, VD_INDEX4 };
+ int x_id[] = { VD_X1, VD_X2, VD_X3, VD_X4 };
+ int y_id[] = { VD_Y1, VD_Y2, VD_Y3, VD_Y4 };
+ char buffer[64];
+
+ for (k = 0; k < 4; k++)
+ {
+ sprintf (buffer, "%lu", pos + k + 1);
+ SetWindowText (GetDlgItem (hDlg, index_id[k]), buffer);
+ sprintf (buffer, "%lf", xdata[pos + k]);
+ SetWindowText (GetDlgItem (hDlg, x_id[k]), buffer);
+ sprintf (buffer, "%lf", ydata[pos + k]);
+ SetWindowText (GetDlgItem (hDlg, y_id[k]), buffer);
+ }
+}
+
+
+LRESULT CALLBACK
+ViewDataDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static unsigned long current_pos = 0;
+ SCROLLINFO si;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ ZeroMemory (&si, sizeof (SCROLLINFO));
+ si.cbSize = sizeof (SCROLLINFO);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = n_items - 4;
+ si.nPage = 4;
+ si.nPos = 0;
+ SetScrollInfo (GetDlgItem (hDlg, VD_SCROLL), SB_CTL, &si, FALSE);
+
+ insert_data (hDlg, 0);
+
+ current_pos = 0;
+
+ return TRUE;
+ case WM_VSCROLL:
+ switch (LOWORD (wParam))
+ {
+ case SB_LINEUP:
+ if (current_pos) current_pos--;
+ break;
+ case SB_LINEDOWN:
+ if (current_pos < n_items - 4) current_pos++;
+ break;
+ case SB_PAGEUP:
+ if (current_pos > 3) current_pos -= 4;
+ break;
+ case SB_PAGEDOWN:
+ if (current_pos < n_items - 4) current_pos += 4;
+ break;
+/* case SB_THUMBTRACK: */
+ case SB_THUMBPOSITION:
+ current_pos = (unsigned long)GetScrollPos (GetDlgItem (hDlg,
+ VD_SCROLL),
+ SB_CTL);
+ break;
+ default:
+ return FALSE;
+ }
+
+ insert_data (hDlg, current_pos);
+
+ SetScrollPos (GetDlgItem (hDlg, VD_SCROLL), SB_CTL, current_pos, TRUE);
+
+ return TRUE;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ EndDialog (hDlg, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+void
+generate_x_y (void)
+{
+ unsigned long k;
+ double freq_interval;
+
+ n_items = (unsigned long)sf_sample_freq * sf_duration;
+ freq_interval = 1.0 / (double)sf_sample_freq;
+
+ if (xdata != NULL) free (xdata);
+ if (ydata != NULL) free (ydata);
+
+ xdata = xmalloc (n_items * sizeof (double));
+ ydata = xmalloc (n_items * sizeof (double));
+
+ for (k = 0; k < n_items; k++) xdata[k] = k * freq_interval;
+}
+
+void
+plot_standard_sine (void)
+{
+ unsigned long k;
+
+ generate_x_y ();
+
+ for (k = 0; k < n_items; k++)
+ ydata[k] = sf_amplitude * sin (2 * M_PI * xdata[k] * sf_base_freq);
+}
+
+/* scale
+ * Scale X so that it lies within [ 0 : 2*PI ]
+ */
+double
+scale (double x)
+{
+ double sign;
+
+ sign = (x < 0.0) ? -1.0 : 1.0;
+ x = fabs (x);
+
+ x -= floor (x / (2 * M_PI)) * (2 * M_PI);
+
+ return (sign < 0) ? (2 * M_PI - x) : x;
+}
+
+/* square
+ * Returns the value of a square wave with period 2pi.
+ */
+double
+fsquare (double x)
+{
+ x = scale (x);
+ return (x < M_PI) ? 1 : -1;
+}
+
+void
+plot_standard_square (void)
+{
+ unsigned long k;
+
+ generate_x_y ();
+
+ for (k = 0; k < n_items; k++)
+ ydata[k] = sf_amplitude * fsquare (2 * M_PI * xdata[k] * sf_base_freq);
+}
+
+double
+fsaw (double x)
+{
+ x += M_PI / 2;
+ x = scale (x);
+ if (x < M_PI)
+ {
+ x = -1.0 + 2.0 * x / M_PI;
+ }
+ else
+ {
+ x -= M_PI;
+ x = 1.0 - 2.0 * x / M_PI;
+ }
+ return x;
+}
+
+void
+plot_standard_saw (void)
+{
+ unsigned long k;
+
+ generate_x_y ();
+
+ for (k = 0; k < n_items; k++)
+ ydata[k] = sf_amplitude * fsaw (2 * M_PI * xdata[k] * sf_base_freq);
+}
+
+
+LRESULT CALLBACK
+StandardFuncDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ HDC hDC;
+ LPDRAWITEMSTRUCT lpdis;
+ static HBITMAP hBmp, hBmp1, hBmp2, hBmp3;
+ SCROLLINFO si;
+ int mult, iscratch, end_dlg = 0;
+ char buffer[64];
+ double dscratch;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ hBmp1 = LoadBitmap ((HANDLE)ghInstance, "SINE_WAVE");
+ hBmp2 = LoadBitmap ((HANDLE)ghInstance, "SQUARE_WAVE");
+ hBmp3 = LoadBitmap ((HANDLE)ghInstance, "SAWTOOTH_WAVE");
+ CheckRadioButton (hDlg, SFR_SINE, SFR_SAW, SFR_SINE);
+
+ ZeroMemory (&si, sizeof (SCROLLINFO));
+ si.cbSize = sizeof (SCROLLINFO);
+ si.fMask = SIF_ALL;
+
+ si.nMin = 1;
+ si.nMax = INT_MAX;
+ si.nPage = 0;
+ si.nPos = sf_sample_freq;
+ SetScrollInfo (GetDlgItem (hDlg, SFS_SFREQ), SB_CTL, &si, FALSE);
+ si.nMin = 1;
+ si.nMax = INT_MAX;
+ si.nPage = 0;
+ si.nPos = sf_base_freq;
+ SetScrollInfo (GetDlgItem (hDlg, SFS_BFREQ), SB_CTL, &si, FALSE);
+ si.nMin = INT_MIN;
+ si.nMax = INT_MAX;
+ si.nPage = 0;
+ si.nPos = sf_amplitude * 100;
+ SetScrollInfo (GetDlgItem (hDlg, SFS_AMP), SB_CTL, &si, FALSE);
+ si.nMin = 1;
+ si.nMax = INT_MAX;
+ si.nPage = 0;
+ si.nPos = sf_duration * 100;
+ SetScrollInfo (GetDlgItem (hDlg, SFS_DUR), SB_CTL, &si, FALSE);
+
+ sprintf (buffer, "%d", sf_sample_freq);
+ SetDlgItemText (hDlg, SF_SFREQ, buffer);
+ sprintf (buffer, "%d", sf_base_freq);
+ SetDlgItemText (hDlg, SF_BFREQ, buffer);
+ sprintf (buffer, "%.2lf", sf_amplitude);
+ SetDlgItemText (hDlg, SF_AMP, buffer);
+ sprintf (buffer, "%.2lf", sf_duration);
+ SetDlgItemText (hDlg, SF_DUR, buffer);
+
+ return TRUE;
+ case WM_DRAWITEM:
+ switch (wParam)
+ {
+ case SF_SINE:
+ hBmp = hBmp1;
+ break;
+ case SF_SQUARE:
+ hBmp = hBmp2;
+ break;
+ case SF_SAW:
+ hBmp = hBmp3;
+ break;
+ default:
+ return FALSE;
+ }
+
+ lpdis = (LPDRAWITEMSTRUCT)lParam;
+ hDC = CreateCompatibleDC (lpdis->hDC);
+ SelectObject (hDC, hBmp);
+ StretchBlt (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
+ lpdis->rcItem.right - lpdis->rcItem.left,
+ lpdis->rcItem.bottom - lpdis->rcItem.top,
+ hDC, 0, 0, 30, 15, SRCCOPY);
+
+ DeleteDC (hDC);
+
+ return TRUE;
+ case WM_VSCROLL:
+ switch (LOWORD (wParam))
+ {
+ case SB_LINEUP:
+ mult = 1;
+ break;
+ case SB_LINEDOWN:
+ mult = -1;
+ break;
+ default:
+ return TRUE;
+ }
+
+ switch (GetDlgCtrlID ((HWND)lParam))
+ {
+ case SFS_SFREQ:
+ GetDlgItemText (hDlg, SF_SFREQ, buffer, 64);
+ sscanf (buffer, "%d", &iscratch);
+ iscratch += mult;
+ if (iscratch < 1) break;
+ sprintf (buffer, "%d", iscratch);
+ SetDlgItemText (hDlg, SF_SFREQ, buffer);
+ break;
+ case SFS_BFREQ:
+ GetDlgItemText (hDlg, SF_BFREQ, buffer, 64);
+ sscanf (buffer, "%d", &iscratch);
+ iscratch += mult;
+ if (iscratch < 1) break;
+ sprintf (buffer, "%d", iscratch);
+ SetDlgItemText (hDlg, SF_BFREQ, buffer);
+ break;
+ case SFS_AMP:
+ GetDlgItemText (hDlg, SF_AMP, buffer, 64);
+ sscanf (buffer, "%lf", &dscratch);
+ dscratch += mult * .01;
+ sprintf (buffer, "%.2lf", dscratch);
+ SetDlgItemText (hDlg, SF_AMP, buffer);
+ break;
+ case SFS_DUR:
+ GetDlgItemText (hDlg, SF_DUR, buffer, 64);
+ sscanf (buffer, "%lf", &dscratch);
+ dscratch += mult * .01;
+ if (dscratch < .01) break;
+ sprintf (buffer, "%.2lf", dscratch);
+ SetDlgItemText (hDlg, SF_DUR, buffer);
+ break;
+ }
+
+ return TRUE;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ end_dlg = 1;
+ case 179: /* APPLY */
+ GetDlgItemText (hDlg, SF_SFREQ, buffer, 64);
+ sscanf (buffer, "%d", &sf_sample_freq);
+ GetDlgItemText (hDlg, SF_BFREQ, buffer, 64);
+ sscanf (buffer, "%d", &sf_base_freq);
+ GetDlgItemText (hDlg, SF_AMP, buffer, 64);
+ sscanf (buffer, "%lf", &sf_amplitude);
+ GetDlgItemText (hDlg, SF_DUR, buffer, 64);
+ sscanf (buffer, "%lf", &sf_duration);
+
+ if (IsDlgButtonChecked (hDlg, SFR_SINE))
+ plot_standard_sine ();
+ else if (IsDlgButtonChecked (hDlg, SFR_SQUARE))
+ plot_standard_square ();
+ else if (IsDlgButtonChecked (hDlg, SFR_SAW))
+ plot_standard_saw ();
+
+ data_limits ();
+ enable_menus ();
+ InvalidateRect (hWnd, NULL, FALSE);
+
+ if (!end_dlg) break;
+ case IDCANCEL:
+ EndDialog (hDlg, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/* AboutDlgProc
+ * Window procedure for the about box.
+ */
+LRESULT CALLBACK
+AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ return TRUE;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDCANCEL:
+ case IDOK:
+ case BN_CLICKED:
+ EndDialog (hDlg, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+/* MainWndProc
+ * Main window procedure for the program.
+ */
+LRESULT WINAPI
+MainWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PAINTSTRUCT ps;
+ HDC hDC;
+ RECT rc;
+ static BOOL lbuttondown = FALSE, dragging = FALSE, iscontrol = FALSE;
+ static int mouse_x, mouse_y, mouse_nxl, mouse_nxr, mouse_nyt, mouse_nyb;
+ static int old_draw_mode;
+ static int left_button_is_down = 0;
+ int new_xl, new_xr, new_yt, new_yb, yspan, xspan, pan;
+
+ if (hwnd != hWnd) return (DefWindowProc (hwnd, uMsg, wParam, lParam));
+
+ switch (uMsg)
+ {
+ case WM_COMMAND:
+ switch (LOWORD (wParam))
+ {
+ case IDM_OPEN:
+ case IDM_OPEN_AUDIO:
+ open_file ((int)wParam);
+ break;
+ case IDM_EXIT:
+ SendMessage (hWnd, WM_DESTROY, NULL, NULL);
+ break;
+ case IDM_SETTINGS:
+ DialogBox (ghInstance, "SettingsDlg",
+ hWnd, (DLGPROC)SettingsDlgProc);
+ break;
+ case IDM_FFTSETTINGS:
+ DialogBox (ghInstance, "TransformSettingsDlg",
+ hWnd, (DLGPROC)TransformSettingsDlgProc);
+ break;
+ case IDM_LIMITS:
+ DialogBox (ghInstance, "LimitsDlg", hWnd, (DLGPROC) LimitsDlgProc);
+ break;
+ case IDM_ZOOM_IN:
+ get_client_rect (&rc);
+
+ xspan = (rc.right - rc.left) / 6;
+ yspan = (rc.bottom - rc.top) / 6;
+
+ new_xl = rc.left + xspan;
+ if (new_xl < 0) new_xl = 0;
+ new_xr = rc.right - xspan;
+
+ new_yt = rc.top + yspan;
+ if (new_yt < 0) new_yt = 0;
+ new_yb = rc.bottom - yspan;
+
+ zoom_in (new_xl, new_yt, new_xr, new_yb);
+ InvalidateRect (hWnd, NULL, FALSE);
+
+ break;
+ case IDM_ZOOM_OUT:
+ get_client_rect (&rc);
+
+ xspan = (rc.right - rc.left) / 4;
+ yspan = (rc.bottom - rc.top) / 4;
+
+ new_xl = rc.left - xspan;
+ new_xr = rc.right + xspan;
+
+ new_yt = rc.top - yspan;
+ new_yb = rc.bottom + yspan;
+
+ zoom_in (new_xl, new_yt, new_xr, new_yb);
+ InvalidateRect (hWnd, NULL, FALSE);
+
+ break;
+ case IDM_ORIGINAL:
+ data_limits ();
+ InvalidateRect (hWnd, NULL, FALSE);
+ break;
+ case IDM_DATA:
+ DialogBox (ghInstance, "ViewDataDlg", hWnd,
+ (DLGPROC) ViewDataDlgProc);
+ break;
+ case IDM_FUNCTION:
+ DialogBox (ghInstance, "StandardFuncDlg", hWnd,
+ (DLGPROC) StandardFuncDlgProc);
+ break;
+ case IDM_EXPRESSION:
+ MessageBox (hWnd, "Feature not yet implemented.", "Sorry",
+ MB_OK | MB_ICONASTERISK);
+ break;
+ case IDM_TRANSFORM:
+ transform ();
+ break;
+ case IDM_TRANSREGION:
+ transform_region ();
+ break;
+ case IDM_ROTATE:
+ rotate_data ();
+ break;
+ case IDM_PLAYSOUND:
+ /* figure out how to convert data into .wav format */
+ case IDM_CONTENTS:
+ MessageBox (hWnd, "Feature not yet implemented.", "Sorry",
+ MB_OK | MB_ICONASTERISK);
+ break;
+ case IDM_ABOUT:
+ DialogBox (ghInstance, "AboutDlg", hWnd, (DLGPROC) AboutDlgProc );
+ break;
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ /* If the left button is down, and then comes up without moving,
+ the app is zoomed in centered. If the left button is down and
+ then drags, a rectangle is drawn and that is the zoom region.
+ If the left button is down and the control key is pressed
+ then the mouse only drags in the X direction.
+ */
+
+ if (xdata == NULL && ydata == NULL) break;
+
+ lbuttondown = TRUE;
+
+ mouse_x = LOWORD (lParam);
+ mouse_y = HIWORD (lParam);
+
+ /* test for control key */
+ if ((wParam & MK_CONTROL) || get_transform_region)
+ {
+ iscontrol = TRUE;
+
+ get_client_rect (&rc);
+
+ mouse_y = rc.top;
+ }
+
+ left_button_is_down = 1;
+
+ break;
+ case WM_LBUTTONUP:
+ if (xdata == NULL && ydata == NULL) break;
+ if (!left_button_is_down) break;
+
+ get_client_rect (&rc);
+
+ if (dragging)
+ {
+ hDC = GetDC (hWnd);
+ Rectangle (hDC, mouse_nxl, mouse_nyt, mouse_nxr, mouse_nyb);
+ SetROP2 (hDC, old_draw_mode);
+ ReleaseDC (hWnd, hDC);
+ }
+
+ if (lbuttondown) /* single click, no drag */
+ {
+ lbuttondown = FALSE;
+
+ xspan = (rc.right - rc.left) / 6;
+ yspan = (rc.bottom - rc.top) / 6;
+
+ new_xl = rc.left + xspan;
+ if (new_xl < 0) new_xl = 0;
+ new_xr = rc.right - xspan;
+
+ new_yt = rc.top + yspan;
+ if (new_yt < 0) new_yt = 0;
+ new_yb = rc.bottom - yspan;
+ }
+ else if (iscontrol && dragging) /* click and drag with the control key */
+ {
+ dragging = FALSE;
+ iscontrol = FALSE;
+
+ /* y stays the same */
+ new_yt = rc.top;
+ new_yb = rc.bottom;
+
+ if (mouse_x < LOWORD (lParam))
+ {
+ new_xl = mouse_x;
+ new_xr = LOWORD (lParam);
+ }
+ else
+ {
+ new_xl = LOWORD (lParam);
+ new_xr = mouse_x;
+ }
+ }
+ else if (dragging) /* click and drag */
+ {
+ dragging = FALSE;
+
+ if (mouse_x < LOWORD (lParam))
+ {
+ new_xl = mouse_x;
+ new_xr = LOWORD (lParam);
+ }
+ else
+ {
+ new_xl = LOWORD (lParam);
+ new_xr = mouse_x;
+ }
+ if (mouse_y < HIWORD (lParam))
+ {
+ new_yt = mouse_y;
+ new_yb = HIWORD (lParam);
+ }
+ else
+ {
+ new_yt = HIWORD (lParam);
+ new_yb = mouse_y;
+ }
+ }
+ else
+ break; /* huh? */
+
+ left_button_is_down = 0;
+ zoom_in (new_xl, new_yt, new_xr, new_yb);
+
+ if (get_transform_region)
+ {
+ get_transform_region = 0;
+ transform ();
+ }
+ else
+ InvalidateRect (hWnd, NULL, FALSE);
+
+ break;
+ case WM_MOUSEMOVE:
+ if (xdata == NULL && ydata == NULL)
+ {
+ RECT rc;
+
+ GetClientRect (hWnd, &rc);
+
+ rc.top = rc.bottom - STATUS_HEIGHT;
+
+ hDC = GetDC (hWnd);
+ DrawStatusText (hDC, &rc, "", SBT_POPOUT);
+ ReleaseDC (hWnd, hDC);
+
+ break;
+ }
+
+ draw_status (LOWORD (lParam), HIWORD (lParam));
+
+ if (!dragging && !lbuttondown) break;
+
+ hDC = GetDC (hWnd);
+
+ if (lbuttondown) /* starting to drag */
+ {
+ lbuttondown = FALSE;
+ dragging = TRUE;
+
+ /* create rubber rectangle */
+ old_draw_mode = SetROP2 (hDC, R2_NOT);
+ }
+ else
+ {
+ /* erase the old rectangle */
+ Rectangle (hDC, mouse_nxl, mouse_nyt, mouse_nxr, mouse_nyb);
+ }
+
+ /* draw the new rectangle */
+ mouse_nxl = (LOWORD (lParam) < mouse_x) ? LOWORD (lParam) : mouse_x;
+ mouse_nxr = (mouse_nxl == mouse_x) ? LOWORD (lParam) : mouse_x;
+
+ if (!iscontrol)
+ {
+ mouse_nyt = (HIWORD (lParam) < mouse_y) ? HIWORD (lParam) : mouse_y;
+ mouse_nyb = (mouse_y == mouse_nyt) ? HIWORD (lParam) : mouse_y;
+ }
+ else
+ {
+ get_client_rect (&rc);
+ mouse_nyt = rc.top;
+ mouse_nyb = rc.bottom;
+ }
+
+ Rectangle (hDC, mouse_nxl, mouse_nyt, mouse_nxr, mouse_nyb);
+
+ ReleaseDC (hWnd, hDC);
+
+ break;
+ case WM_RBUTTONUP:
+ if (xdata == NULL && ydata == NULL) break;
+
+ get_client_rect (&rc);
+
+ xspan = (rc.right - rc.left) / 4;
+ yspan = (rc.bottom - rc.top) / 4;
+
+ new_xl = rc.left - xspan;
+ new_xr = rc.right + xspan;
+
+ if (wParam & MK_CONTROL)
+ {
+ new_yt = rc.top;
+ new_yb = rc.bottom;
+ }
+ else
+ {
+ new_yt = rc.top - yspan;
+ new_yb = rc.bottom + yspan;
+ }
+
+ zoom_in (new_xl, new_yt, new_xr, new_yb);
+ InvalidateRect (hWnd, NULL, FALSE);
+
+ break;
+ case WM_KEYDOWN: /* use the arrow keys for panning */
+ get_client_rect (&rc);
+
+ switch (wParam)
+ {
+ case VK_LEFT:
+ pan = (rc.right - rc.left) / 8;
+ rc.left -= pan;
+ rc.right -= pan;
+
+ break;
+ case VK_RIGHT:
+ pan = (rc.right - rc.left) / 8;
+ rc.left += pan;
+ rc.right += pan;
+
+ break;
+ case VK_UP:
+ pan = (rc.bottom - rc.top) / 8;
+ rc.top -= pan;
+ rc.bottom -= pan;
+
+ break;
+ case VK_DOWN:
+ pan = (rc.bottom - rc.top) / 8;
+ rc.top += pan;
+ rc.bottom += pan;
+
+ break;
+ default:
+ return (DefWindowProc (hWnd, uMsg, wParam, lParam));
+ }
+
+ zoom_in (rc.left, rc.top, rc.right, rc.bottom);
+ InvalidateRect (hWnd, NULL, FALSE);
+
+ break;
+ case WM_PAINT:
+ if (GetUpdateRect (hWnd, &rc, FALSE))
+ {
+ clear_screen ();
+ plot_data ();
+ draw_status (-1, -1);
+ ValidateRect (hWnd, &rc);
+ }
+ break;
+ case WM_DESTROY:
+ PostQuitMessage (0);
+ break;
+ default:
+ return (DefWindowProc (hWnd, uMsg, wParam, lParam));
+ }
+
+ return 0;
+}
+
+
+/* WinMain
+ * Win32 entry point. Creates a window of class PLOT and draws it. Also
+ * parses any command line options (which should only be a filename).
+ */
+int WINAPI
+WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpszCmdLine, int nCmdShow)
+{
+ WNDCLASS wc;
+ MSG msg;
+ HACCEL acc;
+ RECT rc;
+
+ InitCommonControls ();
+
+ if (!hPrevInstance)
+ {
+ wc.lpszClassName = "PLOT";
+ wc.lpfnWndProc = MainWndProc;
+ wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon (hInstance, "PlotIcon");
+ wc.hCursor = LoadCursor (NULL, IDC_CROSS);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wc.lpszMenuName = "PlotAppMenu";
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+
+ RegisterClass (&wc);
+ }
+
+ ghInstance = hInstance;
+
+ fgColor = RGB (0, 0, 0); /* black */
+ bgColor = RGB (255, 255, 255); /* white */
+ fnColor = RGB (0, 0, 0); /* black */
+
+ hWnd = CreateWindow ("PLOT",
+ "Data Plotter",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL,
+ NULL,
+ hInstance,
+ NULL);
+
+ ShowWindow (hWnd, nCmdShow);
+
+ acc = LoadAccelerators (hInstance, "PlotAccelTable");
+ if (acc == NULL)
+ MessageBox (hWnd, "LoadAccelerators failed.", "Sorry",
+ MB_OK | MB_ICONASTERISK);
+
+ hwaitcursor = LoadCursor (NULL, IDC_WAIT);
+
+ draw_status (-1, -1);
+
+ /* handle command line args */
+ if (strlen (lpszCmdLine))
+ {
+ int k = strlen (lpszCmdLine);
+ char buffer[64];
+ HANDLE hfile;
+
+ /* check to see if the name is surrounded by "" */
+ if (lpszCmdLine[0] == '"')
+ {
+ int k;
+ for (k = 0; lpszCmdLine[k + 1] != '"'; k++)
+ lpszCmdLine[k] = lpszCmdLine[k + 1];
+ lpszCmdLine[k] = '\0';
+ }
+
+ /* test that the file exists */
+ hfile = CreateFile (lpszCmdLine, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hfile == INVALID_HANDLE_VALUE)
+ {
+ sprintf (buffer, "Unable to open %s.", lpszCmdLine);
+ MessageBox (hWnd, buffer, "Sorry",
+ MB_OK | MB_ICONASTERISK);
+ }
+ else
+ {
+ CloseHandle (hfile);
+
+ get_data (lpszCmdLine);
+
+ while (--k)
+ if (lpszCmdLine[k] == '\\' || lpszCmdLine[k] == '/')
+ break;
+
+ sprintf (buffer, "Data Plotter - %s", lpszCmdLine + k + 1);
+ SetWindowText (hWnd, buffer);
+
+ enable_menus ();
+ InvalidateRect (hWnd, NULL, FALSE);
+ }
+ }
+
+ /* message loop */
+ while (GetMessage (&msg, NULL, 0, 0))
+ {
+ if (!TranslateAccelerator (hWnd, acc, &msg))
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+
+ return msg.wParam;
+}
diff --git a/plot/plot.exe b/plot/plot.exe
new file mode 100755
index 0000000..cfb522d
--- /dev/null
+++ b/plot/plot.exe
Binary files differ
diff --git a/plot/plot.h b/plot/plot.h
new file mode 100755
index 0000000..a673c68
--- /dev/null
+++ b/plot/plot.h
@@ -0,0 +1,103 @@
+/* plot.h
+ * Header file for plot.exe
+ */
+
+#include <math.h>
+
+/* resource definitions */
+
+/* menu item definitions */
+#define IDM_OPEN 1000
+#define IDM_OPEN_AUDIO 1005
+#define IDM_EXIT 1010
+#define IDM_SETTINGS 1015
+#define IDM_FFTSETTINGS 1020
+#define IDM_LIMITS 1025
+#define IDM_ZOOM_IN 1026
+#define IDM_ZOOM_OUT 1027
+#define IDM_ORIGINAL 1028
+#define IDM_COLOR 1030
+#define IDM_FONT 1035
+#define IDM_DATA 1040
+#define IDM_FUNCTION 1044
+#define IDM_EXPRESSION 1045
+#define IDM_TRANSFORM 1046
+#define IDM_TRANSREGION 1047
+#define IDM_PLAYSOUND 1048
+#define IDM_ROTATE 1049
+#define IDM_CONTENTS 1050
+#define IDM_ABOUT 1055
+
+/* status window ID */
+#define WID_STATUS_WINDOW 2000
+
+/* color dialog button IDs */
+#define BID_FGCOLOR 141
+#define CLR_FOREGROUND 142
+#define BID_BGCOLOR 146
+#define CLR_BACKGROUND 147
+
+/* standard function bmp IDs */
+#define SF_SINE 161
+#define SF_SQUARE 162
+#define SF_SAW 163
+
+/* standard function radio button IDs */
+#define SFR_SINE 164
+#define SFR_SQUARE 165
+#define SFR_SAW 166
+
+/* standard function parameters */
+#define SF_SFREQ 171
+#define SF_BFREQ 172
+#define SF_AMP 173
+#define SF_DUR 174
+
+/* standard function parameter scrollbars */
+#define SFS_SFREQ 175
+#define SFS_BFREQ 176
+#define SFS_AMP 177
+#define SFS_DUR 178
+
+/* view data elements */
+#define VD_SCROLL 184
+#define VD_INDEX1 186
+#define VD_INDEX2 187
+#define VD_INDEX3 188
+#define VD_INDEX4 189
+#define VD_X1 190
+#define VD_X2 191
+#define VD_X3 192
+#define VD_X4 193
+#define VD_Y1 194
+#define VD_Y2 195
+#define VD_Y3 196
+#define VD_Y4 197
+
+
+/* element access for data array */
+#define REAL_IDX(x) ((x) * 2)
+#define IMAG_IDX(x) ((x) * 2 + 1)
+
+/* swap used for bit reversing */
+#define swap(a, b) do { double t = a; a = b; b = t; } while (0)
+
+/* the height of the status bar */
+#define STATUS_HEIGHT 20;
+
+
+#define N_TRANSFORM_ALGORITHM 3
+enum transform_algorithm {
+ DFT, FFT2, FFTN
+};
+
+#define N_WINDOW_FUNCTION 2
+enum window_function {
+ HANNING, SQUARE
+};
+
+#define N_OUTPUT_DATA 4
+enum output_data {
+ REAL, IMAGINARY, MAGNITUDE, PHASE
+};
+
diff --git a/plot/plot.rc b/plot/plot.rc
new file mode 100755
index 0000000..edc3764
--- /dev/null
+++ b/plot/plot.rc
@@ -0,0 +1,207 @@
+/* plot.rc
+ * resource script for plot.exe
+ */
+
+#include <windows.h>
+#include "plot.h"
+
+
+PlotIcon ICON "freq.ico"
+
+2 ICON "pld.ico"
+
+
+SAWTOOTH_WAVE BITMAP "sawtooth_wave.bmp"
+SINE_WAVE BITMAP "sin_wave.bmp"
+SQUARE_WAVE BITMAP "square_wave.bmp"
+
+
+PlotAppMenu MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&Open Datafile...\tCtrl+D", IDM_OPEN
+ MENUITEM "Open &Audiofile...\tCtrl+A", IDM_OPEN_AUDIO
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit\tCtrl+X", IDM_EXIT
+ END
+ POPUP "&Options"
+ BEGIN
+ MENUITEM "&Settings...", IDM_SETTINGS
+ MENUITEM "&Transform Settings...", IDM_FFTSETTINGS
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "Set &Limits...\tCtrl+L", IDM_LIMITS, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "Zoom &In\tCtrl+I", IDM_ZOOM_IN, GRAYED
+ MENUITEM "Zoom &Out\tCtrl+O", IDM_ZOOM_OUT, GRAYED
+ MENUITEM "&Zap to Original Scale\tCtrl+Z", IDM_ORIGINAL, GRAYED
+ END
+ POPUP "&Data"
+ BEGIN
+ MENUITEM "&Show Data...", IDM_DATA, GRAYED
+ MENUITEM "&Plot Standard Function...", IDM_FUNCTION
+ MENUITEM "Build &Expression...", IDM_EXPRESSION
+ END
+ POPUP "&Action"
+ BEGIN
+ MENUITEM "&Transform\tCtrl+T", IDM_TRANSFORM, GRAYED
+ MENUITEM "Transform &Region\tCtrl+R", IDM_TRANSREGION, GRAYED
+ MENUITEM "R&otate Data", IDM_ROTATE, GRAYED
+ MENUITEM "&Play Sound", IDM_PLAYSOUND, GRAYED
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Contents...\tF1", IDM_CONTENTS
+ MENUITEM SEPARATOR
+ MENUITEM "&About Data Plotter...", IDM_ABOUT
+ END
+END
+
+
+PlotAccelTable ACCELERATORS
+BEGIN
+ "A", IDM_OPEN_AUDIO, CONTROL, VIRTKEY
+ "D", IDM_OPEN, CONTROL, VIRTKEY
+ "I", IDM_ZOOM_IN, CONTROL, VIRTKEY
+ "L", IDM_LIMITS, CONTROL, VIRTKEY
+ "O", IDM_ZOOM_OUT, CONTROL, VIRTKEY
+ "R", IDM_TRANSREGION, CONTROL, VIRTKEY
+ "T", IDM_TRANSFORM, CONTROL, VIRTKEY
+ "X", IDM_EXIT, CONTROL, VIRTKEY
+ "Z", IDM_ORIGINAL, CONTROL, VIRTKEY
+END
+
+
+AboutDlg DIALOG FIXED 6, 21, 180, 99
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "About Data Plotter"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ ICON "PlotIcon", 103, 10, 10, 0, 0
+ DEFPUSHBUTTON "&OK", IDOK, 72, 74, 40, 14
+ LTEXT "Data Plotter", 104, 55, 14, 140, 8
+ LTEXT "Data Plotter plots data files and sound files. It also has the capability to calculate the fast fourier transform of the data and display the resulting frequency spectrum.", 105, 10, 35, 160, 32
+END
+
+SettingsDlg DIALOG FIXED 50, 50, 140, 80
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_CAPTION
+CAPTION "Settings"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "", 110, 5, 5, 130, 50
+ LTEXT "", 111, 10, 15, 50, 15, SS_OWNERDRAW
+ PUSHBUTTON "Change Font...", 112, 65, 15, 60, 15
+ LTEXT "", 113, 10, 35, 50, 15, SS_OWNERDRAW
+ PUSHBUTTON "Change Colors...", 114, 65, 35, 60, 15
+ DEFPUSHBUTTON "Dismiss", IDOK, 5, 60, 130, 15
+END
+
+ColorDlg DIALOG FIXED 6, 21, 95, 95
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_CAPTION
+CAPTION "Set Colors"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Foreground", 140, 5, 5, 85, 30
+ LTEXT "", BID_FGCOLOR, 10, 15, 30, 15, SS_OWNERDRAW
+ PUSHBUTTON "Change...", CLR_FOREGROUND, 45, 15, 40, 15
+ GROUPBOX "Background", 145, 5, 40, 85, 30
+ LTEXT "", BID_BGCOLOR, 10, 50, 30, 15, SS_OWNERDRAW
+ PUSHBUTTON "Change...", CLR_BACKGROUND, 45, 50, 40, 15
+ PUSHBUTTON "Cancel", 149, 5, 75, 40, 15
+ DEFPUSHBUTTON "OK", IDOK, 50, 75, 40, 15
+END
+
+TransformSettingsDlg DIALOG FIXED 6, 21, 140, 155
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_CAPTION
+CAPTION "Transform Settings"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Transform Algorithm", 150, 5, 5, 130, 30
+ COMBOBOX 151, 10, 15, 120, 60, CBS_DROPDOWNLIST | WS_VSCROLL
+ GROUPBOX "Window Function", 152, 5, 40, 130, 50
+ COMBOBOX 153, 10, 50, 120, 60, CBS_DROPDOWNLIST | WS_VSCROLL
+ RTEXT "", 154, 10, 70, 60, 15
+ EDITTEXT 155, 70, 70, 60, 15
+ GROUPBOX "Plotted Data", 156, 5, 95, 130, 30
+ COMBOBOX 157, 10, 105, 120, 60, CBS_DROPDOWNLIST | WS_VSCROLL
+ PUSHBUTTON "Cancel", IDCANCEL, 5, 130, 40, 20
+ PUSHBUTTON "Apply", 158, 50, 130, 40, 20
+ DEFPUSHBUTTON "OK", IDOK, 95, 130, 40, 20
+END
+
+LimitsDlg DIALOG FIXED 6, 21, 140, 135
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_CAPTION
+CAPTION "Set Plot Limits"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Lower Left", 120, 5, 5, 130, 50
+ RTEXT "X:", 121, 10, 15, 10, 15
+ EDITTEXT 122, 20, 15, 110, 15
+ RTEXT "Y:", 123, 10, 35, 10, 15
+ EDITTEXT 124, 20, 35, 110, 15
+ GROUPBOX "Upper Right", 125, 5, 60, 130, 50
+ RTEXT "X:", 126, 10, 70, 10, 15
+ EDITTEXT 127, 20, 70, 110, 15
+ RTEXT "Y:", 128, 10, 90, 10, 15
+ EDITTEXT 129, 20, 90, 110, 15
+ PUSHBUTTON "Cancel", 130, 5, 115, 40, 15
+ PUSHBUTTON "Apply", 131, 50, 115, 40, 15
+ DEFPUSHBUTTON "OK", IDOK, 95, 115, 40, 15
+END
+
+ViewDataDlg DIALOG FIXED 6, 21, 150, 115
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_CAPTION
+CAPTION "View Data"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "", 180, 5, 5, 140, 85
+ CTEXT "Index", 181, 10, 10, 40, 15
+ CTEXT "X", 182, 50, 10, 40, 15
+ CTEXT "Y", 183, 90, 10, 40, 15
+ SCROLLBAR VD_SCROLL, 130, 10, 10, 75, SBS_VERT
+ RTEXT "", VD_INDEX1, 10, 20, 40, 15
+ RTEXT "", VD_INDEX2, 10, 35, 40, 15
+ RTEXT "", VD_INDEX3, 10, 50, 40, 15
+ RTEXT "", VD_INDEX4, 10, 65, 40, 15
+ RTEXT "", VD_X1, 50, 20, 40, 15
+ RTEXT "", VD_X2, 50, 35, 40, 15
+ RTEXT "", VD_X3, 50, 50, 40, 15
+ RTEXT "", VD_X4, 50, 65, 40, 15
+ RTEXT "", VD_Y1, 90, 20, 40, 15
+ RTEXT "", VD_Y2, 90, 35, 40, 15
+ RTEXT "", VD_Y3, 90, 50, 40, 15
+ RTEXT "", VD_Y4, 90, 65, 40, 15
+ DEFPUSHBUTTON "Dismiss", IDOK, 5, 95, 140, 15
+END
+
+StandardFuncDlg DIALOG FIXED 6, 21, 140, 200
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_CAPTION
+CAPTION "Plot Standard Function"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Function", 160, 5, 5, 130, 70
+ PUSHBUTTON "", SF_SINE, 10, 15, 30, 15, BS_OWNERDRAW
+ PUSHBUTTON "", SF_SQUARE, 10, 35, 30, 15, BS_OWNERDRAW
+ PUSHBUTTON "", SF_SAW, 10, 55, 30, 15, BS_OWNERDRAW
+ AUTORADIOBUTTON "Sine Wave", SFR_SINE, 50, 15, 80, 15, WS_GROUP
+ AUTORADIOBUTTON "Square Wave", SFR_SQUARE, 50, 35, 80, 15
+ AUTORADIOBUTTON "Sawtooth Wave", SFR_SAW, 50, 55, 80, 15
+ GROUPBOX "Parameters", 169, 5, 80, 130, 90
+ RTEXT "Sampling Frequency (Hz)", 167, 10, 90, 80, 15
+ RTEXT "Base Frequency (Hz)", 168, 10, 110, 80, 15
+ RTEXT "Amplitude", 169, 10, 130, 80, 15
+ RTEXT "Duration (s)", 170, 10, 150, 80, 15
+ EDITTEXT SF_SFREQ, 95, 90, 20, 15, ES_RIGHT
+ SCROLLBAR SFS_SFREQ, 115, 90, 10, 15, SBS_VERT
+ EDITTEXT SF_BFREQ, 95, 110, 20, 15, ES_RIGHT
+ SCROLLBAR SFS_BFREQ, 115, 110, 10, 15, SBS_VERT
+ EDITTEXT SF_AMP, 95, 130, 20, 15, ES_RIGHT
+ SCROLLBAR SFS_AMP, 115, 130, 10, 15, SBS_VERT
+ EDITTEXT SF_DUR, 95, 150, 20, 15, ES_RIGHT
+ SCROLLBAR SFS_DUR, 115, 150, 10, 15, SBS_VERT
+ PUSHBUTTON "Cancel", IDCANCEL, 5, 175, 40, 20
+ PUSHBUTTON "Apply", 179, 50, 175, 40, 20
+ DEFPUSHBUTTON "OK", IDOK, 95, 175, 40, 20
+END
diff --git a/plot/sawtooth_wave.bmp b/plot/sawtooth_wave.bmp
new file mode 100755
index 0000000..45b5130
--- /dev/null
+++ b/plot/sawtooth_wave.bmp
Binary files differ
diff --git a/plot/sin_wave.bmp b/plot/sin_wave.bmp
new file mode 100755
index 0000000..a8c6b7e
--- /dev/null
+++ b/plot/sin_wave.bmp
Binary files differ
diff --git a/plot/square_wave.bmp b/plot/square_wave.bmp
new file mode 100755
index 0000000..395b2d7
--- /dev/null
+++ b/plot/square_wave.bmp
Binary files differ
diff --git a/signature/COPYING b/signature/COPYING
new file mode 100644
index 0000000..86cf81a
--- /dev/null
+++ b/signature/COPYING
@@ -0,0 +1,341 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
diff --git a/signature/INSTALL b/signature/INSTALL
new file mode 100644
index 0000000..e3dbf85
--- /dev/null
+++ b/signature/INSTALL
@@ -0,0 +1,20 @@
+INSTALL - quick and dirty install instructions
+
+To install, first run configure.pl:
+
+[jon@chainik ~/signature]$ ./configure.pl
+
+Answer the questions it asks, and it will create the Makefile. Next build
+and install the program.
+
+[jon@chainik ~/signature]$ make
+...
+[jon@chainik ~/signature]$ su
+Password:
+[root@chainik ~jon/signature]# make install
+...
+[root@chainik ~jon/signature]# exit
+[jon@chainik ~/signature]$
+
+Then, you need merely start signature, and you will have a working
+signature pipe.
diff --git a/signature/Makefile b/signature/Makefile
new file mode 100644
index 0000000..61293bf
--- /dev/null
+++ b/signature/Makefile
@@ -0,0 +1,25 @@
+# Makefile for signature
+# this is autogenerated by configure.pl
+
+FORTUNE = \"/usr/bin/fortune\"
+INSTALL_DIRECTORY = /home/jon/bin
+
+CC = gcc
+CFLAGS = -Wall -O2 -g
+INSTALL = install
+INSTALL_FLAGS = -s
+
+.PHONY: all install clean veryclean
+
+all: signature
+
+signature: signature.c
+ $(CC) $(CFLAGS) -DFORTUNE=$(FORTUNE) -o signature signature.c
+
+install: signature
+ $(INSTALL) $(INSTALL_FLAGS) signature $(INSTALL_DIRECTORY)
+
+clean:
+ rm -f signature *~
+veryclean:
+ rm -f signature Makefile *~
diff --git a/signature/NEWS b/signature/NEWS
new file mode 100644
index 0000000..44f2554
--- /dev/null
+++ b/signature/NEWS
@@ -0,0 +1 @@
+6 December, 2000: Signature 1.0.0 released
diff --git a/signature/README b/signature/README
new file mode 100644
index 0000000..12c2bf0
--- /dev/null
+++ b/signature/README
@@ -0,0 +1,15 @@
+Signature is a program which creates a dynamic signature file. It does
+this by creating a pipe to the fortune program, which, when read from,
+prints out a random fortune.
+
+To use, type
+
+$ signature
+
+This should return immediately. However, signature is still working in
+the background. To stop the program, type
+
+$ killall signature
+
+You may specify an alternate filename on the command line. The program
+also understands the standard options --help and --version.
diff --git a/signature/configure.pl b/signature/configure.pl
new file mode 100755
index 0000000..1cbc606
--- /dev/null
+++ b/signature/configure.pl
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+# configure.pl
+# Configure signature for the system
+
+START:
+
+$fortune = "/usr/games/fortune";
+$install_prefix = "/usr/local";
+
+unless (-x $fortune)
+{
+ print "enter the location of your fortune program >> ";
+ $fortune = <>;
+ chop $fortune;
+
+ -x $fortune || die "configure: sorry still can't find fortune\n";
+}
+
+print "enter install prefix [/usr/local] >> ";
+$prefix = <>;
+chop $prefix;
+
+if ($prefix =~ m/./) { $install_prefix = $prefix; }
+unless (-d $install_prefix) { die "configure: that's not a valid directory\n"; }
+
+print "-> install information:\n" .
+ "-> fortune program: $fortune\n" .
+ "-> install prefix: $install_prefix\n" .
+ "is this OK [Y/n]? >> ";
+$response = <>;
+chop $response;
+
+goto START unless ($response =~ m/^y?$/i);
+
+open (MAKEFILE, ">Makefile") || die "configure: can't write Makefile\n";
+
+print MAKEFILE <<FOO;
+# Makefile for signature
+# this is autogenerated by configure.pl
+
+FORTUNE = \\"$fortune\\"
+INSTALL_DIRECTORY = $install_prefix/bin
+
+CC = gcc
+CFLAGS = -Wall -O2 -g
+INSTALL = install
+INSTALL_FLAGS = -s
+
+.PHONY: all install clean veryclean
+
+all: signature
+
+signature: signature.c
+ \$(CC) \$(CFLAGS) -DFORTUNE=\$(FORTUNE) -o signature signature.c
+
+install: signature
+ \$(INSTALL) \$(INSTALL_FLAGS) signature \$(INSTALL_DIRECTORY)
+
+clean:
+ rm -f signature *~
+veryclean:
+ rm -f signature Makefile *~
+FOO
+
+close MAKEFILE;
diff --git a/signature/signature.c b/signature/signature.c
new file mode 100644
index 0000000..eda7b3a
--- /dev/null
+++ b/signature/signature.c
@@ -0,0 +1,229 @@
+/* signature.c
+ *
+ * Copyright (C) 2000 Jonathan duSaint
+ *
+ * This file is part of Signature, a per-user daemon which implements
+ * a .signature file as a pipe, with the BSD program fortune on the
+ * other end. In this manner, a different signature is produced every
+ * time.
+ *
+ * Signature is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Signature is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license,
+ * write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/errno.h>
+#include <signal.h>
+#include <getopt.h>
+
+#include "version.h"
+
+/* the canonical name of the program */
+#define pname "signature"
+
+/* Defining these here makes for cleaner code. */
+#define NORMAL_EXIT 0
+#define ERROR_EXIT 1
+
+/* exit_value is used so that a clean exit can be made via SIGINT. */
+int exit_value = NORMAL_EXIT;
+
+/* This is the file handle used to communicate with fortune. */
+FILE *fortune_fd = NULL;
+
+/* This is the file handle for the .signature pipe. */
+int sig_fd = -1;
+
+/* The name of the .signature file; nominally ~/.signature. */
+char *sig_file;
+
+
+/* SIGINT is the signal to clean up and exit. */
+void
+sigint (int sig)
+{
+ /* kill fortune subprocess, if any */
+ if (fortune_fd != NULL) pclose (fortune_fd);
+
+ /* close pipe */
+ if (sig_fd < 0) close (sig_fd);
+
+ /* delete pipe */
+ remove (sig_file);
+
+ /* clean up memory */
+ free (sig_file);
+
+ /* ... and exit */
+ exit (exit_value);
+}
+
+/* xmalloc safely allocates memory. */
+void *
+xmalloc (size_t amt)
+{
+ void *mem;
+
+ mem = malloc (amt);
+
+ if (mem == NULL)
+ {
+ fprintf (stderr, "%s: unable to allocate %d bytes of memory\n",
+ pname, amt);
+ exit (ERROR_EXIT);
+ }
+
+ return (mem);
+}
+
+/* Print a help message. */
+void
+print_help (void)
+{
+ printf ("Signature %s:\n"
+ "Usage:\n"
+ " signature [signature_file]\n"
+ "\n"
+ "Signature creates a named pipe, nominally ~/.signature,\n"
+ "which, when read from, will write a signature. For the\n"
+ "signatures, the program fortune is used.\n",
+ version);
+}
+
+/* Print version and copyright information. */
+void
+print_version (void)
+{
+ printf ("Signature %s:\n"
+ "\n"
+ "Copyright (C) 2000 Jonathan duSaint <jdusaint@penguinpunk.com>\n"
+ "\n"
+ "Signature comes with NO WARRANTY,\n"
+ "to the extent permitted by law.\n"
+ "You may redistribute copies of Signature\n"
+ "under the terms of the GNU General Public License.\n"
+ "For more information about these matters,\n"
+ "see the file named COPYING.\n",
+ version);
+}
+
+
+/* Signature, itself. */
+int
+main (int argc, char *argv[])
+{
+ char line[100], *home;
+ int opt;
+ struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { 0, 0, 0, 0 }
+ };
+
+ /* parse through argv, looking for options */
+ while (1)
+ {
+ opt = getopt_long (argc, argv, "hv", options, NULL);
+
+ if (opt == EOF) break;
+
+ switch (opt)
+ {
+ case 'h':
+ print_help ();
+ exit (NORMAL_EXIT);
+ case 'v':
+ print_version ();
+ exit (NORMAL_EXIT);
+ case '?':
+ fprintf (stderr, "%s: unknown option character `%c'\n",
+ pname, optopt);
+ exit (ERROR_EXIT);
+ default:
+ fprintf (stderr,
+ "%s: ?? getopt returned character code 0x%x (%c) ??\n",
+ pname, opt, opt);
+ exit (ERROR_EXIT);
+ }
+ }
+
+ if (argc == 2) /* user specified file */
+ {
+ sig_file = xmalloc (strlen (argv[1]) + 1);
+ strcpy (sig_file, argv[1]);
+ }
+ else /* default: ~/.signature */
+ {
+ home = getenv ("HOME");
+ sig_file = xmalloc (strlen (home) + 12);
+ sprintf (sig_file, "%s/.signature", home);
+ }
+
+ /* install SIGINT handler */
+ signal (SIGINT, sigint);
+
+ /* run in background */
+ if (fork () != 0) return (NORMAL_EXIT);
+
+ /* create the .signature pipe */
+ if ((mknod (sig_file, S_IFIFO | 0666, 0) < 0)
+ && (errno != EEXIST))
+ {
+ fprintf (stderr, "%s: unable to create %s\n", pname, sig_file);
+ exit_value = ERROR_EXIT;
+ kill (getpid (), SIGINT); /* exit via sigint */
+ }
+
+ /* loop until SIGINT is recieved */
+ while (1)
+ {
+ /* open the pipe for writing */
+ if ((sig_fd = open (sig_file, 1)) < 0)
+ {
+ fprintf (stderr, "%s: unable to open %s\n", pname, sig_file);
+ exit_value = ERROR_EXIT;
+ kill (getpid (), SIGINT); /* exit via sigint */
+ }
+
+ /* a read request was recieved - fire off fortune */
+ if ((fortune_fd = popen (FORTUNE, "r")) == NULL)
+ {
+ fprintf (stderr, "%s: unable to execute %s\n", pname, FORTUNE);
+ exit_value = ERROR_EXIT;
+ kill (getpid (), SIGINT); /* exit via sigint */
+ }
+
+ /* transfer fortune's output */
+ while ((fgets (line, 99, fortune_fd)) != NULL)
+ write (sig_fd, line, strlen (line));
+
+ /* clean up */
+ pclose (fortune_fd);
+ close (sig_fd);
+
+ /* and prepare for another loop */
+ fortune_fd = NULL;
+ sig_fd = -1;
+ }
+
+ /* not reached */
+ return (NORMAL_EXIT);
+}
diff --git a/signature/version.h b/signature/version.h
new file mode 100644
index 0000000..96e4d8c
--- /dev/null
+++ b/signature/version.h
@@ -0,0 +1 @@
+char version[] = "1.0.0";
diff --git a/spacetweet/README b/spacetweet/README
new file mode 100644
index 0000000..c80d262
--- /dev/null
+++ b/spacetweet/README
@@ -0,0 +1,6 @@
+Simple program to fetch the latest tweets from SpaceX, guess the next
+launch, and display to a Ink wHAT screen. You'll want to run this
+from an internet-connected raspberry pi of some sort. The next launch
+guessing is somewhat flaky, but good enough for my purposes.
+
+Inky wHAT: https://www.adafruit.com/product/4142
diff --git a/spacetweet/rocket.png b/spacetweet/rocket.png
new file mode 100644
index 0000000..d9b3ec5
--- /dev/null
+++ b/spacetweet/rocket.png
Binary files differ
diff --git a/spacetweet/spacetweet.py b/spacetweet/spacetweet.py
new file mode 100755
index 0000000..b406888
--- /dev/null
+++ b/spacetweet/spacetweet.py
@@ -0,0 +1,227 @@
+#!/usr/bin/python3
+
+from inky import InkyWHAT
+from PIL import Image, ImageFont, ImageDraw
+
+from font_fredoka_one import FredokaOne
+from font_hanken_grotesk import HankenGrotesk
+from font_intuitive import Intuitive
+from font_source_serif_pro import SourceSerifPro
+
+from datetime import datetime
+import re
+import requests
+import textwrap
+import time
+
+# Screen is 400 x 300
+
+# XXX: enter your own twitter API bearer token here
+token = 'NOPE'
+
+spacex_username = 'SpaceX'
+
+# Convert username to user id
+def user_id (username):
+ url = "https://api.twitter.com/2/users/by?usernames={}".format(username)
+ headers = {"Authorization": "Bearer {}".format(token)}
+ r = requests.get (url, headers=headers)
+ if r.status_code != 200:
+ return None
+ j = r.json()
+ j = j['data']
+ if len(j) == 0:
+ return None
+ return j[0]['id']
+
+# Get most recent tweets
+def tweets (uid):
+ url = "https://api.twitter.com/2/users/{}/tweets?tweet.fields=created_at".format(uid)
+ headers = {"Authorization": "Bearer {}".format(token)}
+ r = requests.get (url, headers=headers)
+ if r.status_code != 200:
+ return None
+ j = r.json()
+ return j['data']
+
+
+r_time = r'(\d\d?):(\d\d) ?([AP]\.?[M]\.?) ?(\w\w\w)?'
+r_weekday = r'(?:Sun|Mon|Tues|Wed|Thurs|Fri|Satur)day'
+r_month = r'Jan(?:uary)|Feb(?:ruary)|Mar(?:ch)|Apr(?:il)|May|June?|July?|Aug(?:ust)|Sep(?:tember)|Oct(?:ober)|Nov(?:ember)|Dec(?:ember)'
+r_date = '(?:('+r_weekday+'),? ?)('+r_month+') ?(\d\d?)'
+
+# time and datetime can only make this name -> offset for the system's current time zone
+tzoffsets = {'EST': -5,
+ 'EDT': -4,
+ 'CST': -6,
+ 'CDT': -5,
+ 'MST': -7,
+ 'MDT': -6,
+ 'PST': -8,
+ 'PDT': -7,
+ 'AST': -9,
+ 'ADT': -8,
+ 'UTC': 0}
+
+# Month name -> 1-based month number
+def month_number(name):
+ months = {'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4, 'may': 5, 'jun': 6,
+ 'jul': 7, 'aug': 8, 'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12}
+ try:
+ return months[name[0:3]].lower()
+ except:
+ return None
+
+# Heuristic to check for a next launch
+def check_for_next_launch(tweet_time, string):
+ tweet_epoch = time.mktime (datetime.fromisoformat (tweet_time.replace('Z', '+00:00')).timetuple())
+
+ # "Watch" or "Live views"
+ m = re.search(r'Watch|Live view', string, re.I)
+ if m is not None:
+ if tweet_epoch < time.time() - 60 * 60:
+ #print (time.strftime("%a %b %d %H:%M", time.localtime (tweet_epoch)) + ' is too far in the past to display')
+ return None
+
+ launch_time = tweet_epoch - (time.mktime(time.gmtime(0)) - time.mktime(time.localtime(0)))
+ return time.strftime("%a %b %d %H:%M", time.localtime (launch_time))
+
+ # T-<n> launch times
+ m = re.search (r'T-(\d\d?) (hour|minute)s?', string, re.I)
+ if string.find ('T-0') == -1 and m is not None:
+ offset = int (m.group(1)) * 60
+ if m.group(2).lower() == 'hour':
+ offset = offset * 60
+ launch_time_gmt = tweet_epoch + offset
+ launch_time = launch_time_gmt - (time.mktime(time.gmtime(0)) - time.mktime(time.localtime(0)))
+
+ if launch_time_gmt < time.time() - 60 * 60:
+ #print (time.strftime("%a %b %d %H:%M", time.localtime (launch_time))+' is too far in the past to display')
+ return None
+
+ return time.strftime("%a %b %d %H:%M", time.localtime (launch_time))
+
+ # Specific date/time for launch
+ month, day, hour, minute, tz = None, None, None, 0, 0
+
+ m = re.search (r_time, string, re.I)
+ if m is not None:
+ hh = int (m.group(1))
+ mm = int (m.group(2))
+ if m.group(3) is not None:
+ if hh == 12:
+ hh -= 12
+ if m.group(3)[0] == 'p' or m.group(3)[0] == 'P':
+ hh += 12
+ if hh < 24 and mm < 60:
+ hour = hh
+ minute = mm
+ if m.group(4) and m.group(4).upper() in tzoffsets:
+ tz = tzoffsets[m.group(4).upper()]
+
+ m = re.search (r_date, string, re.I)
+ if m is not None:
+ if m.group(1) is not None:
+ weekday = m.group(1)[0:3]
+ month = month_number (m.group(2)[0:3])
+ day = int (m.group(3))
+
+ # Couldn't find a timestamp
+ if month is None and hour is None:
+ return None
+
+ # Switch to "local to launch" tz
+ local_tuple = time.gmtime (tweet_epoch + tz * 60 * 60)
+ year = local_tuple[0]
+
+ if hour is None:
+ hour = 0
+ elif day is None and hour < local_tuple[3]:
+ day = local_tuple[2] + 1
+
+ if minute is None:
+ minute = local_tuple[4]
+
+ if month is None:
+ month = local_tuple[1]
+ elif month < local_tuple[1]:
+ year += 1
+
+ if day is None:
+ day = local_tuple[2]
+
+ launch_tuple = (year, month, day, hour, minute, 0, -1, -1, -1)
+ launch_time_gmt = time.mktime(launch_tuple) - tz * 60 * 60
+ launch_time = launch_time_gmt - (time.mktime(time.gmtime(0)) - time.mktime(time.localtime(0)))
+
+ if launch_time_gmt < time.time() - 60 * 60:
+ #print (time.strftime("%a %b %d %H:%M", time.localtime (launch_time))+' is too far in the past to display')
+ return None
+
+ return time.strftime("launch time %a %b %d %H:%M", time.localtime (launch_time))
+
+
+pad = 4
+y = 2
+
+iw = InkyWHAT('black')
+i = Image.new ("P", (iw.WIDTH, iw.HEIGHT))
+d = ImageDraw.Draw (i)
+
+font = ImageFont.truetype (FredokaOne, 18)
+
+# Header
+rl = Image.open ('rocket.png') # 22x22
+rr = rl.transpose (method=Image.FLIP_LEFT_RIGHT)
+i.paste (rl, (0, 0))
+i.paste (rl, (22, 0))
+i.paste (rl, (44, 0))
+i.paste (rr, (iw.WIDTH - 22, 0))
+i.paste (rr, (iw.WIDTH - 44, 0))
+i.paste (rr, (iw.WIDTH - 66, 0))
+
+tstring = time.strftime ("%a %b %d %H:%M")
+w, h = font.getsize (tstring)
+d.text ((iw.WIDTH / 2 - w / 2, y), tstring, iw.BLACK, font)
+d.line ([(0, y + h + pad / 2 - 1), (iw.WIDTH - 1, y + h + pad / 2 - 1)], fill=iw.BLACK, width=2)
+
+y += h + pad
+
+nextlaunch_y = y # will fill in text later
+
+# Tweets
+y += h + 14
+
+nextlaunch = None
+
+uid = user_id (spacex_username)
+if uid is not None:
+ render = True
+ ts = tweets (uid)
+ for tw in ts:
+ if nextlaunch is None:
+ nextlaunch = check_for_next_launch (tw['created_at'], tw['text'])
+ if not render:
+ continue
+ tm = time.strftime("*** %a %b %d %H:%M", datetime.fromisoformat (tw['created_at'].replace('Z', '+00:00')).astimezone().timetuple())
+ tm += ': ' + tw['text']
+ tm = textwrap.wrap (tm, width=40)
+ if len (tm) > 3:
+ tm = tm[0:3]
+ tm[2] += '...'
+ message = '\n'.join (tm)
+ w, h = font.getsize_multiline (message)
+ if y + h > iw.HEIGHT:
+ render = False
+ continue
+ d.text ((pad, y), message, iw.BLACK, font)
+ y += h + pad * 2
+
+# Next launch
+if nextlaunch is None:
+ nextlaunch = 'not scheduled'
+d.text ((pad, nextlaunch_y), "Next launch: " + nextlaunch, iw.BLACK, font)
+
+
+iw.set_image (i)
+iw.show ()
diff --git a/tap/BUGS b/tap/BUGS
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/tap/BUGS
diff --git a/tap/INSTALL b/tap/INSTALL
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/tap/INSTALL
diff --git a/tap/Makefile b/tap/Makefile
new file mode 100755
index 0000000..4f993f3
--- /dev/null
+++ b/tap/Makefile
@@ -0,0 +1,69 @@
+# Makefile for Tap
+
+CC = gcc
+CFLAGS = -O2 -g -Wall
+LIBS = -lncurses
+
+TAP = tap
+
+PREFIX = /usr/local
+BINDIR = $(PREFIX)/bin
+INFODIR = $(PREFIX)/info
+MANDIR = $(PREFIX)/man/man1
+DOCDIR = $(PREFIX)/doc/tap
+INSTALL-INFO = /sbin/install-info
+
+SRCFILES = memmgr.c serial.c tap.c ui.c
+HDRFILES = tap.h version.h command_struct.h
+OBJFILES = $(SRCFILES:%.c=%.o)
+
+READLINE = readline/readline.o
+READLINESRC = readline/*.c
+
+COMMANDS = commands/commands.o
+COMMANDSSRC = commands/*.c
+
+DOCEXTRAS = tap.cp tap.fn tap.ky tap.pg tap.tp tap.vr \
+ tap.aux tap.log tap.cps tap.toc
+DOCFILES = tap.dvi tap.ps tap.html tap.info
+
+
+.PHONY : all doc ps dvi info html install clean
+
+
+all : $(TAP)
+
+$(TAP) : $(READLINE) $(COMMANDS) $(SERIAL) $(OBJFILES) $(HDRFILES)
+ $(CC) $(CFLAGS) $(LIBS) -o $@ $(OBJFILES) $(READLINE) $(COMMANDS)
+
+$(READLINE) : $(READLINESRC)
+ make -C readline
+
+$(COMMANDS) : $(COMMANDSSRC)
+ make -C commands
+
+
+doc : tap.ps tap.html tap.info tap.texinfo
+
+ps : tap.ps
+dvi : tap.dvi
+info : tap.info
+html : tap.html
+
+tap.ps : tap.dvi tap.texinfo
+ dvips tap.dvi -o tap.ps
+tap.dvi : tap.texinfo
+ texi2dvi tap.texinfo
+tap.info : tap.texinfo
+ makeinfo tap.texinfo
+tap.html : tap.texinfo
+ makeinfo --html tap.texinfo
+
+
+install : tap info html
+
+
+clean :
+ make -C readline clean
+ make -C commands clean
+ rm -f $(OBJFILES) $(TAP) $(DOCFILES) $(DOCEXTRAS) core *~
diff --git a/tap/NEWS b/tap/NEWS
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/tap/NEWS
diff --git a/tap/README b/tap/README
new file mode 100755
index 0000000..6d9a9a8
--- /dev/null
+++ b/tap/README
@@ -0,0 +1,8 @@
+tap - a serial line tapper
+
+Started sometime around 17 July 1999.
+
+This is not an official release. Some sections of code aren't yet
+complete, and a lot hasn't been thoroughly tested. Also, although it
+should be totally portable (among Linuxes), it has only been tested on
+Linux/Alpha, so there might be some 64-bit-isms (though not likely).
diff --git a/tap/command_struct.h b/tap/command_struct.h
new file mode 100755
index 0000000..db9e0a6
--- /dev/null
+++ b/tap/command_struct.h
@@ -0,0 +1,122 @@
+/* command_struct.h
+ * This file contains all of the external commands for Tap.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+struct command commands[] = {
+ /* help */
+ { "help", help,
+ "unalias,set,quit,print,out,open,help,close,clear,capture,alias",
+ "print help for a function",
+ "help [function]\n \
+print a summary of functions or help for a specific function\n" },
+
+ /* set */
+ { "set", set, "of{ascii-cooked,ascii-raw,hex,oct,bin},"
+ "if{ascii-cooked,ascii-raw,hex,oct,bin},regsize{\\d},"
+ "mode{passive,active},echo{off,on},baud{\\d}",
+ "set various properties",
+ "set <properties> [values]\n \
+where properties are\n \
+if <bin|oct|hex|ascii-raw|ascii-cooked> - data entry format\n \
+In ascii-cooked mode, certain escapes are recognized:\n \
+\\a - 0x07 alert\n \
+\\b - 0x08 backspace\n \
+\\f - 0x0C form feed\n \
+\\n - 0x0A new line\n \
+\\r - 0x0D carriage return\n \
+\\v - 0x0B vertical tab\n \
+\\\\ - literal backslash\n \
+\\num - the character whose ASCII code is NUM (octal).\n \
+of <bin|oct|hex|ascii-raw|ascii-cooked> - data output format\n \
+The difference between ascii-raw and ascii-cooked is that cooked\n \
+mode converts non-printing characters to hexidecimal escape codes.\n \
+regsize <value> - the default register size in bytes\n \
+baud <value> - the speed of the port\n \
+echo <on|off> - whether or not terminal echo is on\n \
+mode <active|passive>\n \
+Active mode is default. In passive mode, more space is devoted\n \
+to the output window.\n" },
+
+ /* out */
+ { "out", out, "\\m",
+ "write data out to the serial port",
+ "out <data>\n \
+write data with the input format controlled by <set if> to the\n \
+serial port\n \
+see also <set> for a summary of input formats\n" },
+
+ /* quit */
+ { "quit", quit, "",
+ "quit the program",
+ "quit\n \
+quit the program\n" },
+
+ /* capture */
+ { "capture", capture, "register{\\m},file{\\f}",
+ "capture data from the serial port",
+ "capture <file|register> [file_name|register_number|off]\n \
+capture data from the serial port to a file, and continue\n \
+until the program is closed or <capture off> is entered\n \
+or to a register 1-64, and only capture <set regsize> bytes\n" },
+
+ /* open */
+ { "open", open_p, "\\f",
+ "open a serial device",
+ "open <serial port>\n \
+open a serial connection with <serial port>" },
+
+ /* close */
+ { "close", close_p, "",
+ "close a serial device",
+ "close\n \
+close the currently open serial connection\n" },
+
+ /* clear */
+ { "clear", clear_scr, "",
+ "clear the screen",
+ "clear\n \
+clear the screen\n" },
+
+ /* print */
+ { "print", print, "register{\\m{\\m}},file{\\f{\\m}}",
+ "print contents of a register or file",
+ "print <file|register> [file name|register number] [number of bytes]\n \
+print the contents of a file or a register\n \
+if n_bytes is specified print that many bytes\n" },
+
+ /* alias */
+ { "alias", make_alias, "\\m{\\c}",
+ "specify another name to use for a command",
+ "alias <new name> <command name>\n \
+assign an alias to <command name>\n" },
+
+ /* unalias */
+ { "unalias", unalias, "\\m",
+ "remove an alias",
+ "unalias <alias>\n \
+remove an alias from the alias list.\n" },
+
+ /* the end */
+ { NULL, NULL, NULL, NULL, NULL }
+};
diff --git a/tap/commands/Makefile b/tap/commands/Makefile
new file mode 100755
index 0000000..e265a19
--- /dev/null
+++ b/tap/commands/Makefile
@@ -0,0 +1,18 @@
+# makefile for commands
+
+CC = gcc
+CFLAGS = -Wall -g -O2 -I..
+
+SRCFILES = serial.c set.c user.c translate.c alias.c
+OBJFILES = $(SRCFILES:%.c=%.o)
+INCLUDEFILES = commands.h
+
+.PHONY : all clean
+
+all : commands.o
+
+commands.o : $(OBJFILES) $(INCLUDEFILES)
+ ld -r -o commands.o $(OBJFILES)
+
+clean :
+ rm -f commands.o $(OBJFILES) *~ core
diff --git a/tap/commands/alias.c b/tap/commands/alias.c
new file mode 100755
index 0000000..55d82ea
--- /dev/null
+++ b/tap/commands/alias.c
@@ -0,0 +1,185 @@
+/* commands/alias.c
+ * Implementation of the alias command.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "commands.h"
+
+struct alias_ {
+
+ /* the actual command name */
+ char *command;
+
+ /* the alias for the command */
+ char *alias;
+
+ /* the alias list is linked */
+ struct alias_ *next;
+};
+
+
+/* the alias list -- these are stored alphabetically
+ * as determined by strcmp ()
+ */
+struct alias_ *alias_list = NULL;
+
+
+/* If NAME is on the alias list, return the command to which it
+ * was aliased, otherwise just return NAME.
+ */
+char *
+resolve_alias (char *name)
+{
+ char *copy;
+ struct alias_ *current = alias_list;
+
+ while (current != NULL)
+ {
+ if (!strcmp (name, current->alias))
+ {
+ copy = xmalloc (strlen (current->command) + 1);
+ strcpy (copy, current->command);
+
+ return (copy);
+ }
+
+ current = current->next;
+ }
+
+ /* NAME isn't on the list */
+ return (name);
+}
+
+/* This command has three forms:
+ * alias
+ * will print all of the aliases
+ * alias foo
+ * will print what foo is the alias for
+ * alias foo bar
+ * will asign the name foo to the command bar
+ */
+int
+make_alias (char *line)
+{
+ char *alias, *command;
+ int len, next;
+ struct alias_ *current = alias_list, *prev = NULL;
+
+ alias = get_token (line, &next, &len);
+ command = get_token_only (line + next);
+
+ if (alias[0] == 0 && command[0] == 0)
+ { /* first form */
+ page_init ();
+
+ while (current != NULL)
+ {
+ wprintw (input_window, "%s -> %s\n",
+ current->alias, current->command);
+ current = current->next;
+
+ if (page_line_printed ()) break;
+ }
+ }
+ else if (command[0] == 0)
+ { /* second form */
+ command = resolve_alias (alias);
+
+ if (strcmp (alias, command))
+ { /* if alias != command */
+ wprintw (input_window, "%s -> %s\n", alias, command);
+ wrefresh (input_window);
+ }
+ }
+ else
+ {
+ /* search for the insertion point */
+ for (;;)
+ {
+ /* pointing at the end of the list */
+ if (current == NULL) break;
+
+ /* pointing to the insertion point */
+ if (strcmp (current->alias, alias) > 0) break;
+
+ /* the alias already exists */
+ if (strcmp (current->alias, alias) == 0)
+ {
+ inp_error ("alias already exists");
+ return (0);
+ }
+
+ prev = current;
+ current = current->next;
+ }
+
+ if (prev != NULL)
+ {
+ prev->next = xmalloc (sizeof (struct alias_));
+ prev->next->next = current;
+ prev->next->alias = alias;
+ prev->next->command = command;
+ }
+ else
+ { /* at the start of the list */
+ alias_list = xmalloc (sizeof (struct alias_));
+ alias_list->next = current;
+ alias_list->alias = alias;
+ alias_list->command = command;
+ }
+ }
+
+ return (0);
+}
+
+/* Remove an alias from the alias list. */
+int
+unalias (char *line)
+{
+ char *alias;
+ struct alias_ *current = alias_list, *prev = NULL;
+
+ alias = get_token_only (line);
+
+ while (current != NULL)
+ {
+ if (!strcmp (alias, current->alias))
+ {
+ if (prev == NULL) alias_list = current->next;
+ else prev->next = current->next;
+
+ xfree (current->alias);
+ xfree (current->command);
+ xfree (current);
+
+ return (0);
+ }
+
+ prev = current;
+ current = current->next;
+ }
+
+ inp_error ("alias not on list");
+
+ return (0);
+}
diff --git a/tap/commands/commands.h b/tap/commands/commands.h
new file mode 100755
index 0000000..653833d
--- /dev/null
+++ b/tap/commands/commands.h
@@ -0,0 +1,30 @@
+/* commands.h
+ * This is the main header file for the Commands modules of Tap. Which
+ * contains all of the user level commmands.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "tap.h"
+
+/* needed by serial.c */
+#include <termios.h>
diff --git a/tap/commands/serial.c b/tap/commands/serial.c
new file mode 100755
index 0000000..15aaf3e
--- /dev/null
+++ b/tap/commands/serial.c
@@ -0,0 +1,110 @@
+/* serial.c
+ * functions specifically for the serial port
+ */
+
+#include "commands.h"
+
+/* global variables */
+
+/* file identifier for the serial port */
+
+int serial_port_fd;
+
+/* incoming serial data */
+
+char *serial_buffer = NULL;
+
+/* the size of the serial buffer */
+int serial_buffer_size = DEFAULT_MAXIMUM_ONE_TIME_SERIAL_DATA;
+
+/* Sends everything on the command line out to the serial port
+ * (if one is open) after any necessary translation.
+ */
+int
+out (char *line)
+{
+ char *outb = NULL;
+
+ if (port == NULL)
+ {
+ inp_error ("no serial port open");
+ return (0);
+ }
+
+ switch (input_format)
+ {
+ case BIN:
+ outb = translate_from_bin (line);
+ break;
+ case OCT:
+ outb = translate_from_oct (line);
+ break;
+ case HEX:
+ outb = translate_from_hex (line);
+ break;
+ case ASCII_RAW:
+ outb = translate_from_ascii_raw (line);
+ break;
+ case ASCII_COOKED:
+ outb = translate_from_ascii_cooked (line);
+ break;
+ }
+
+ if (outb == NULL) return (0);
+
+ /* write the whole line at once */
+ write (serial_port_fd, outb, strlen (outb));
+
+ xfree (outb);
+
+ return (0);
+}
+
+/* This opens a serial port for reading/writing. */
+int
+open_p (char *line)
+{
+ char *n_port;
+ struct termios tio;
+
+ if (port != NULL) {
+ inp_error("serial port already open");
+ return(0);
+ }
+
+ n_port = get_token_only (line);
+
+ serial_port_fd = open (n_port, O_RDWR | O_NONBLOCK | O_NOCTTY);
+ if (serial_port_fd == -1)
+ {
+ inp_error ("unable to open serial device");
+ return (0);
+ }
+
+ /* set to non-canonical and turn off echo */
+ tcgetattr (serial_port_fd, &tio);
+ tio.c_lflag &= ~ (ICANON | ECHO);
+ tcflush (serial_port_fd, TCIFLUSH);
+ tcsetattr (serial_port_fd, TCSANOW, &tio);
+
+ port = xmalloc (strlen (n_port)+1);
+ strcpy (port, n_port);
+
+ /* make sure that the serial buffer exists */
+ if (serial_buffer == NULL) serial_buffer = xmalloc (serial_buffer_size);
+
+ return (0);
+}
+
+/* This closes a serial port. */
+int
+close_p (char *line)
+{
+ if (port == NULL) return (0);
+
+ close (serial_port_fd);
+ xfree (port);
+ port = NULL;
+
+ return (0);
+}
diff --git a/tap/commands/set.c b/tap/commands/set.c
new file mode 100755
index 0000000..e4a3516
--- /dev/null
+++ b/tap/commands/set.c
@@ -0,0 +1,315 @@
+/* set.c
+ * set () and its helper functions
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "commands.h"
+
+/* control of active or passive mode */
+
+enum winmode { ACTIVE, PASSIVE } wmode = ACTIVE;
+
+/* the array of valid baud rates */
+
+struct baud_rates_ {
+ speed_t rate;
+ long speed;
+} baud_rates[] = {
+ { 0, -1 },
+ { B0, 0, }, /* this actually is not allowec */
+ { B50, 50 },
+ { B75, 75 },
+ { B110, 110 },
+ { B134, 134 },
+ { B150, 150 },
+ { B200, 200 },
+ { B300, 300 },
+ { B600, 600 },
+ { B1200, 1200 },
+ { B1800, 1800 },
+ { B2400, 2400 },
+ { B4800, 4800 },
+ { B9600, 9600 },
+ { B19200, 19200 },
+ { B38400, 38400 },
+ { B57600, 57600 },
+ { B115200, 115200 },
+ { B230400, 230400 },
+ { B460800, 460800 },
+ { B500000, 500000 },
+ { B576000, 576000 },
+ { B921600, 921600 },
+ { B1000000, 1000000 },
+ { B1152000, 1152000 },
+ { B1500000, 1500000 },
+ { B2000000, 2000000 },
+ { B2500000, 2500000 },
+ { B3000000, 3000000 },
+ { B3500000, 3500000 },
+ { B4000000, 4000000 },
+ { B4000000, 4000000 },
+ { 0, -1 }
+};
+
+/* This tests the validity of a baud rate and
+ * returns an index into the baud_rates array.
+ */
+int
+valid_baud_rate (long rate)
+{
+ int index;
+
+ for (index = 1; baud_rates[index].speed != -1; index++)
+ if (baud_rates[index].speed == rate) return (index);
+
+ /* invalid baud rate */
+ return (0);
+}
+
+/* This converts an internal representation of the baud rate (B??)
+ * into an actual number which can be printed out.
+ */
+long
+get_baud_rate (speed_t rate)
+{
+ struct baud_rates_ *ptr = baud_rates;
+
+ while ((++ptr)->speed != -1)
+ if (ptr->rate == rate) return (ptr->speed);
+
+ /* this should never be reached */
+ return (0);
+}
+
+/* These functions change modes. */
+
+void
+switch_to_active_mode (void)
+{
+ if (wmode == ACTIVE) return;
+
+ wmode = ACTIVE;
+ ui_expand_input_window ();
+}
+
+void
+switch_to_passive_mode (void)
+{
+ if (wmode == PASSIVE) return;
+
+ wmode = PASSIVE;
+ ui_shrink_input_window ();
+}
+
+/* The set command itself */
+int
+set (char *line)
+{
+ char *tok, *val;
+ int nxt = 0, cmd_len, pr_info = 0;
+
+ if (strlen (line) == 0)
+ {
+ inp_error ("nothing specified");
+ return (0);
+ }
+
+ tok = get_token (line, &nxt, &cmd_len);
+ val = get_token (line+nxt, &nxt, &cmd_len);
+
+ if (strlen (val) == 0) pr_info = 1;
+
+ if (!strcmp (tok, "if") || !strcmp (tok, "of"))
+ {
+ enum io_format tformat = (!strcmp (tok, "if"))
+ ? input_format : output_format;
+
+ if (pr_info)
+ {
+ switch (tformat)
+ {
+ case BIN:
+ val = "bin";
+ break;
+ case OCT:
+ val = "oct";
+ break;
+ case HEX:
+ val = "hex";
+ break;
+ case ASCII_RAW:
+ val = "ascii-raw";
+ break;
+ case ASCII_COOKED:
+ val = "ascii-cooked";
+ break;
+ }
+ }
+ else
+ {
+ if (!strcmp (val, "bin"))
+ tformat = BIN;
+ else if (!strcmp (val, "oct"))
+ tformat = OCT;
+ else if (!strcmp (val, "hex"))
+ tformat = HEX;
+ else if (!strcmp (val, "ascii-raw"))
+ tformat = ASCII_RAW;
+ else if (!strcmp (val, "ascii-cooked"))
+ tformat = ASCII_COOKED;
+ else
+ {
+ inp_error ("invalid value");
+ return (0);
+ }
+
+ if (!strcmp (tok, "if"))
+ input_format = tformat;
+ else
+ output_format = tformat;
+ }
+ }
+ else if (!strcmp (tok, "regsize"))
+ {
+ if (pr_info)
+ {
+ val = xmalloc (11);
+ sprintf (val, "%d", register_size);
+ }
+ else
+ {
+ long tval;
+
+ tval = strtol (val, NULL, 0);
+
+ if (tval < 1)
+ inp_error ("invalid value");
+ else
+ register_size = tval;
+ }
+ }
+ else if (!strcmp (tok, "echo"))
+ {
+ struct termios tio;
+
+ if (port == NULL)
+ {
+ inp_error ("no serial port open");
+ return (0);
+ }
+
+ tcdrain (serial_port_fd);
+ tcgetattr (serial_port_fd, &tio);
+
+ if (val[0] == 0)
+ {
+ pr_info = 1;
+ val = (tio.c_lflag & ECHO) ? "on" : "off";
+ }
+ else
+ {
+ if (!strcmp (val, "on"))
+ tio.c_lflag |= ECHO;
+ else if (!strcmp (val, "off"))
+ tio.c_lflag &= ~ECHO;
+ else
+ {
+ inp_error ("echo can only be on or off");
+ return (0);
+ }
+ tcsetattr (serial_port_fd, TCSANOW, &tio);
+ }
+ }
+ else if (!strcmp (tok, "baud"))
+ {
+ speed_t baud_rate;
+ struct termios tio;
+ long rate;
+
+ if (port == NULL)
+ {
+ inp_error ("no serial port open");
+ return (0);
+ }
+
+ tcdrain (serial_port_fd);
+ tcgetattr (serial_port_fd, &tio);
+
+ if (val[0] == 0)
+ {
+ xfree (val);
+ val = xmalloc (8); /* largest baud rate is 4000000 */
+
+ baud_rate = cfgetispeed (&tio);
+ rate = get_baud_rate (baud_rate);
+ if (rate != 134) /* the rate is actually 134.5 */
+ sprintf (val, "%ld", rate);
+ else
+ sprintf (val, "%4.1f", 134.5);
+ }
+ else
+ {
+ baud_rate = baud_rates[valid_baud_rate (strtol (val, NULL, 0))].rate;
+
+ if (!baud_rate || baud_rate == B0)
+ {
+ inp_error ("invalid baud rate");
+ return (0);
+ }
+
+ cfsetispeed (&tio, baud_rate);
+ cfsetospeed (&tio, baud_rate);
+ tcsetattr (serial_port_fd, TCSANOW, &tio);
+ }
+ }
+ else if (!strcmp (tok, "mode"))
+ {
+ if (val[0] == 0)
+ {
+ pr_info = 1;
+ val = (wmode == ACTIVE) ? "active" : "passive";
+ }
+ else if (!strcmp (val, "active"))
+ switch_to_active_mode ();
+ else if (!strcmp (val, "passive"))
+ switch_to_passive_mode ();
+ else
+ {
+ inp_error ("unknown mode");
+ return (0);
+ }
+ }
+ else
+ {
+ inp_error ("unknown property");
+ return (0);
+ }
+
+ if (pr_info)
+ wprintw (input_window, "%s = %s\n", tok, val);
+
+ xfree (tok);
+ if (!pr_info) xfree (val);
+
+ return (0);
+}
diff --git a/tap/commands/translate.c b/tap/commands/translate.c
new file mode 100755
index 0000000..34dc993
--- /dev/null
+++ b/tap/commands/translate.c
@@ -0,0 +1,431 @@
+/* translate.c
+ * functions which translate a string from one format into another
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* !!! WARNING !!!
+ * The contents of this file should not be viewed less than an
+ * hour after eating or in the presence of small children.
+ */
+
+#include "commands.h"
+
+#define TOUP(ch) (isalpha (ch) ? toupper (ch) : (ch))
+
+/* Check that a user-entered string is valid for the given mode. If
+ * STRING has characters which aren't in VALID, returns 1.
+ */
+int
+check_validity (char *string, char *valid)
+{
+ char *tptr;
+
+ string--;
+ while (*(++string))
+ {
+ tptr = valid - 1;
+ while (*(++tptr)) if (*string == *tptr) goto NO_ERROR;
+ return (1);
+ NO_ERROR:
+ ;
+ }
+
+ return (0);
+}
+
+/* translate_from_?? translates user input from ?? into usable format
+ * to be written out of the serial port.
+ */
+
+char *
+translate_from_bin (char *input)
+{
+ unsigned char *output;
+ long byte, bit, length = strlen (input)/8, diff;
+
+ if (check_validity (input, "01"))
+ {
+ inp_error ("invalid_character");
+ return (NULL);
+ }
+
+ output = xmalloc (length + 2);
+ memset (output, 0, length + 2);
+
+ for (byte = 0; byte < length; byte++)
+ {
+ for (bit = 0; bit < 8; bit++)
+ {
+ output[byte] ^=
+ ((unsigned char) ((input[byte*8 + bit] == '1') ? 1 : 0)) << (7 - bit);
+ }
+ }
+
+ diff = strlen (input) - length*8;
+
+ if (diff)
+ {
+ for (bit = 0; bit < diff; bit++)
+ {
+ output[byte] ^=
+ ((unsigned char)((input[byte*8 + bit] == '1') ? 1 : 0)) << (7 - bit);
+ }
+ }
+
+ return (output);
+}
+
+char *
+translate_from_oct (char *input)
+{
+ unsigned char *output = NULL;
+ int length = (strlen (input) * 3) / 8 + 1, k;
+
+ if (check_validity (input, "01234567"))
+ {
+ inp_error ("invalid_character");
+ return (NULL);
+ }
+
+ output = xmalloc (length + 1);
+ memset (output, 0, length + 1);
+
+ for (k = 0; k < strlen (input) / 8; k++)
+ {
+ output[k*3] = ((input[k*8] << 5) & 0xE0)
+ | ((input[k*8+1] << 2) & 0x1C)
+ | ((input[k*8+2] >> 1) & 0x03);
+ output[k*3+1] = ((input[k*8+2] << 7) & 0x80)
+ | ((input[k*8+3] << 4) & 0x70)
+ | ((input[k*8+4] << 1) & 0x0E)
+ | ((input[k*8+5] >> 2) & 0x01);
+ output[k*3+2] = ((input[k*8+5] << 6) & 0xC0)
+ | ((input[k*8+6] << 3) & 0x38)
+ | (input[k+8+7] & 0x07);
+ }
+
+ /* take care of trailers */
+ switch (strlen (input) % 8)
+ {
+ case 7:
+ output[k*3+2] = (input[k*8+6] << 3) & 0x38;
+ case 6:
+ output[k*3+2] |= (input[k*8+5] << 6) & 0xC0;
+ output[k*3+1] = (input[k*8+5] >> 2) & 0x01;
+ case 5:
+ output[k*3+1] |= (input[k*8+4] << 1) & 0x0E;
+ case 4:
+ output[k*3+1] |= (input[k*8+3] << 4) & 0x70;
+ case 3:
+ output[k*3+1] |= (input[k*8+2] << 7) & 0x80;
+ output[k*3] = (input[k*8+2] >> 1) & 0x03;
+ case 2:
+ output[k*3] |= (input[k*8+1] << 2) & 0x1C;
+ case 1:
+ output[k*3] |= (input[k*8] << 5) & 0xE0;
+ default:
+ }
+
+ return (output);
+}
+
+char *
+translate_from_hex (char *input)
+{
+ unsigned char *output = NULL;
+ int length = strlen (input) / 2, k;
+ char translate_table[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* placeholders */
+ 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ };
+
+ if (check_validity (input, "0123456789ABCDEFabcdef"))
+ {
+ inp_error ("invalid_character");
+ return (NULL);
+ }
+
+ output = xmalloc (length + 1);
+ memset (output, 0, length + 1);
+
+ for (k = 0; k < length; k++)
+ {
+ output[k] = (translate_table[TOUP (input[k*2]) - '0'] << 4)
+ | translate_table[TOUP (input[k*2+1]) - '0'];
+ }
+
+ return (output);
+}
+
+char *
+translate_from_ascii_raw (char *input)
+{
+ char *output;
+
+ output = xmalloc (strlen (input) + 1);
+ memcpy (output, input, strlen (input) + 1);
+
+ return (output);
+}
+
+char *
+translate_from_ascii_cooked (char *input)
+{
+ char *output;
+ int amt = 0;
+
+ output = xmalloc (strlen (input) + 1);
+ memset (output, 0, strlen (input) + 1);
+
+ for (--input; * (++input); amt++)
+ {
+ if (*input == '\\')
+ {
+ switch (* (++input))
+ {
+ case 'a':
+ output[amt] = 0x07;
+ break;
+ case 'b':
+ output[amt] = 0x08;
+ break;
+ case 'f':
+ output[amt] = 0x0C;
+ break;
+ case 'n':
+ output[amt] = 0x0A;
+ break;
+ case 'r':
+ output[amt] = 0x0D;
+ break;
+ case 'v':
+ output[amt] = 0x0B;
+ break;
+ case '\\':
+ output[amt] = '\\';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ unsigned char val = 0;
+
+ val = *input & 0x07;
+ input++;
+ if (*input <= '7' && *input >= '0')
+ {
+ val <<= 3;
+ val |= *input & 0x07;
+
+ input++;
+ if (*input <= '7' && *input >= '0')
+ {
+ val <<= 3;
+ val |= *input & 0x07;
+ }
+ else
+ input--;
+ }
+ else
+ input--;
+
+ output[amt] = val;
+ }
+ break;
+ default:
+ inp_error ("invalid escape code");
+ xfree (output);
+ return (NULL);
+ }
+ }
+ else
+ {
+ output[amt] = *input;
+ }
+ }
+
+ return (output);
+}
+
+/* translate_to_?? () takes input from the serial port and translates
+ * it into the format ?? for display in OUTPUT_WINDOW.
+ */
+
+char *
+translate_to_bin (char *input)
+{
+ char *output;
+ int current, offset;
+
+ output = xmalloc (8 * strlen (input) + 1);
+
+ for (current = 0; current < strlen (input); current++)
+ {
+ for (offset = 0; offset < 8; offset++)
+ output[8 * current + offset] =
+ (input[current] & (0x01 << (7 - offset))) ? '1' : '0';
+ }
+
+ output[8 * strlen (input)] = '\0';
+
+ return (output);
+}
+
+char *
+translate_to_oct (char *input)
+{
+ char *output = NULL;
+ int length = (strlen (input) * 8) / 3 + 1, k;
+ char translate_table[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7'
+ };
+
+ output = xmalloc (length + 1);
+
+ memset (output, 0, length + 1);
+
+ /* convert 3 bytes of input at a time */
+ for (k = 0; k < strlen (input) / 3; k++)
+ {
+ output[k*8] = translate_table[ (input[k*3] & 0xE0) >> 5];
+ output[k*8+1] = translate_table[ (input[k*3] & 0x1C) >> 2];
+ output[k*8+2] = translate_table[ ((input[k*3] & 0x03) << 1) | ((input[k*3+1] & 0x80) >> 7)];
+ output[k*8+3] = translate_table[ (input[k*3+1] & 0x70) >> 4];
+ output[k*8+4] = translate_table[ (input[k*3+1] & 0x0E) >> 1];
+ output[k*8+5] = translate_table[ ((input[k*3+1] & 0x01) << 2) | ((input[k*3+2] & 0xC0) >> 6)];
+ output[k*8+6] = translate_table[ (input[k*3+2] & 0x38) >> 3];
+ output[k*8+7] = translate_table[input[k*3+2] & 0x07];
+ }
+
+ /* handle any trailers -- ugly, yeah, but it works... */
+ switch (strlen (input) % 3)
+ {
+ case 2: /* 6 additional */
+ output[k*8+3] = translate_table[ (input[k*3+1] & 0x70) >> 4];
+ output[k*8+4] = translate_table[ (input[k*3+1] & 0x0E) >> 1];
+ output[k*8+5] = translate_table[ ((input[k*3+1] & 0x01) << 2)
+ | ((input[k*3+2] & 0xC0) >> 6)];
+ /* fall through */
+ case 1: /* 3 additional */
+ output[k*8] = translate_table[ (input[k*3] & 0xE0) >> 5];
+ output[k*8+1] = translate_table[ (input[k*3] & 0x1C) >> 2];
+ output[k*8+2] = translate_table[ ((input[k*3] & 0x03) << 1)
+ | ((input[k*3+1] & 0x80) >> 7)];
+ }
+
+ return (output);
+}
+
+char *
+translate_to_hex (char *input)
+{
+ char *output;
+ char hex_table[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ long k, length = strlen (input)*2;
+
+ output = xmalloc (length + 1);
+ memset (output, 0, length + 1);
+
+ for (k = 0; k < length/2; k++)
+ {
+ output[2 * k] = hex_table[ (input[k] >> 4) & 0x0F];
+ output[2 * k + 1] = hex_table[input[k] & 0x0F];
+ }
+
+ return (output);
+}
+
+char *
+translate_to_ascii_raw (char *input)
+{
+ char *output;
+
+ output = xmalloc (strlen (input) + 1);
+ memcpy (output, input, strlen (input) + 1);
+
+ return (output);
+}
+
+/* This is a helper function for translate_to_ascii_cooked(). */
+void
+add_character (char **pstring, char ch)
+{
+ static int buffer_size = 0, chars_in_buffer = 0;
+
+ if (pstring == NULL)
+ {
+ buffer_size = chars_in_buffer = 0;
+ return;
+ }
+
+ if (chars_in_buffer == buffer_size)
+ {
+ char *temp;
+
+ buffer_size += GROW_SIZE;
+ temp = xrealloc (*pstring, buffer_size);
+
+ *pstring = temp;
+ }
+
+ (*pstring)[chars_in_buffer] = ch;
+ chars_in_buffer++;
+}
+
+#define not_escaped(ch) (isalnum (ch) || ispunct (ch) || isspace (ch))
+
+char *
+translate_to_ascii_cooked (char *input)
+{
+ char *output, hex_table[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ /* initialize */
+ add_character (NULL, 0);
+ output = xmalloc (0);
+
+ for (--input; *(++input);)
+ {
+ if (not_escaped (*input)) add_character (&output, *input);
+ else
+ {
+ add_character (&output, '<');
+ add_character (&output, hex_table[(*input >> 4) & 0x0F]);
+ add_character (&output, hex_table[*input & 0x0F]);
+ add_character (&output, '>');
+ }
+ }
+
+ add_character (&output, '\0');
+
+ return (output);
+}
diff --git a/tap/commands/user.c b/tap/commands/user.c
new file mode 100755
index 0000000..14a6969
--- /dev/null
+++ b/tap/commands/user.c
@@ -0,0 +1,378 @@
+/* commands/user.c
+ * User support functions
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "commands.h"
+
+/* the current register number */
+
+int capture_register = 0;
+
+/* the file to capture to */
+
+FILE *capture_fid = NULL;
+
+/* the name of that file */
+
+char *capture_fname = NULL;
+
+
+/* Get help on a command. */
+int
+help (char *line)
+{
+ char *cmd;
+ int current = 0;
+
+ page_init ();
+
+ if (strlen (line) == 0)
+ {
+ /* print help on all of the topics */
+ while (commands[current].name != NULL)
+ {
+ wprintw (input_window, "%-*s: %s\n", MAXIMUM_COMMAND_SIZE,
+ commands[current].name, commands[current].blurb_help);
+ current++;
+
+ if (page_line_printed ()) break;
+ }
+ }
+ else
+ {
+ /* help on a selected topic */
+ cmd = get_token_only (line);
+ if (cmd == NULL) return (0);
+
+ while (commands[current].name != NULL)
+ {
+ if (!strcmp (commands[current].name, cmd))
+ {
+ wprintstr (input_window, commands[current].full_help);
+ return (0);
+ }
+ current++;
+ }
+
+ inp_error ("unknown command");
+ }
+
+ return (0);
+}
+
+/* Quit the program. */
+int
+quit (char *line)
+{
+ return (1);
+}
+
+/* Write incoming data to a register without translating. */
+void
+write_to_capture_register (int how_much)
+{
+ if (capture_register == 0) return;
+
+ if (how_much > registers[capture_register].size
+ - registers[capture_register].offset)
+ how_much = registers[capture_register].size
+ - registers[capture_register].offset;
+
+ memcpy (registers[capture_register].data
+ + registers[capture_register].offset, serial_buffer, how_much);
+ registers[capture_register].offset += how_much;
+
+ /* if the register is full, stop capturing */
+ if (registers[capture_register].offset == registers[capture_register].size)
+ capture_register = 0;
+}
+
+/* Write incoming data to a file without translating. */
+void
+write_to_capture_file (int how_much)
+{
+ if (capture_fid == NULL) return;
+
+ fwrite (serial_buffer, how_much, sizeof (char), capture_fid);
+}
+
+/* This function turns capturing on and off for registers and
+ * files.
+ */
+int
+capture (char *line)
+{
+ char *where, *name;
+ int next, len;
+
+ where = get_token (line, &next, &len);
+ name = get_token_only (line + next);
+
+ if (!strcmp (where, "file"))
+ {
+ if (name[0] == 0)
+ {
+ if (capture_fname != NULL)
+ wprintw (input_window, "%s\n", capture_fname);
+ return (0);
+ }
+
+ if (!strcmp (name, "off"))
+ {
+ if (capture_fid != NULL)
+ {
+ fclose (capture_fid);
+ capture_fid = NULL;
+
+ xfree (capture_fname);
+ capture_fname = NULL;
+ }
+ return (0);
+ }
+
+ if (capture_fid != NULL)
+ {
+ inp_error ("already capturing to a file");
+ return (0);
+ }
+
+ name = tilde_expand (name);
+
+ capture_fid = fopen (name, "a+b");
+
+ if (capture_fid == NULL)
+ {
+ xfree (name);
+
+ inp_error ("unable to open file for capture");
+ return (0);
+ }
+
+ capture_fname = name;
+
+ }
+ else if (!strcmp (where, "register"))
+ {
+ if (name[0] == 0)
+ {
+ if (capture_register != 0)
+ wprintw (input_window, "%d\n", capture_register);
+ return (0);
+ }
+
+ if (!strcmp (name, "off"))
+ {
+ registers[capture_register].size
+ = registers[capture_register].offset;
+ registers[capture_register].offset = 0;
+
+ capture_register = 0;
+ return (0);
+ }
+
+ /* if one is already in use, close it */
+ if (capture_register != 0)
+ {
+ registers[capture_register].size
+ = registers[capture_register].offset;
+ registers[capture_register].offset = 0;
+ }
+
+ capture_register = strtol (name, NULL, 0);
+
+ if (capture_register < 1 || capture_register > MAX_REGISTERS)
+ {
+ inp_error ("invalid register number");
+ capture_register = 0;
+ return (0);
+ }
+
+ if (registers[capture_register].data != (void *)0)
+ xfree (registers[capture_register].data);
+
+ registers[capture_register].size = register_size;
+ registers[capture_register].offset = 0;
+ registers[capture_register].data = xmalloc (register_size);
+
+ }
+ else
+ inp_error ("invalid capture location");
+
+ return (0);
+}
+
+/* This function prints the contents of a file with
+ * translation. Use is made of the serial buffer.
+ */
+void
+print_file (FILE *fid, long data_printed)
+{
+ long amount_read = 0;
+ long amount_to_read = serial_buffer_size;
+
+ if (serial_buffer == NULL) serial_buffer = xmalloc (serial_buffer_size);
+
+ if (data_printed != -1)
+ amount_to_read = MIN (serial_buffer_size, data_printed);
+
+ for (;;)
+ {
+ amount_read = fread (serial_buffer, amount_to_read, sizeof (char), fid);
+
+ if (amount_read == 0) break;
+
+ write_to_output_window (amount_to_read);
+
+ if (data_printed != -1)
+ {
+ data_printed -= amount_to_read;
+ amount_to_read = MIN (serial_buffer_size, data_printed);
+
+ if (amount_to_read == 0) break;
+ }
+ }
+}
+
+/* This function prints the contents of a file
+ * or a register.
+ */
+int
+print (char *line)
+{
+ int next, len, pr_register;
+ long amount, printed = 0, amount_to_print;
+ char *what, *where, *size;
+ FILE *fid;
+
+ what = get_token (line, &next, &len);
+ line += next;
+ where = get_token (line, &next, &len);
+ size = get_token_only (line+next);
+
+ if (size[0] == 0)
+ amount = -1;
+ else
+ {
+ amount = strtol (size, NULL, 0);
+ if (amount == 0)
+ amount = -1;
+ }
+
+ if (!strcmp (what, "file"))
+ {
+ if (where[0] == 0)
+ {
+ if (capture_fname == NULL)
+ inp_error ("no open capture file");
+ else
+ {
+ rewind (capture_fid);
+ print_file (capture_fid, -1);
+ fseek (capture_fid, 0, SEEK_END);
+ }
+
+ return (0);
+ }
+
+ if (capture_fname != NULL)
+ {
+ if (!strcmp (where, "current") || !strcmp (where, capture_fname))
+ {
+ rewind (capture_fid);
+ print_file (capture_fid, amount);
+ fseek (capture_fid, 0, SEEK_END);
+
+ return (0);
+ }
+ }
+
+ fid = fopen (where, "rb");
+ if (fid == NULL)
+ {
+ inp_error ("unable to open file");
+ return (0);
+ }
+
+ print_file (fid, amount);
+
+ fclose (fid);
+
+ }
+ else if (!strcmp (what, "register"))
+ {
+ if (where[0] == 0)
+ {
+ if (capture_register == 0)
+ {
+ inp_error ("no register specified");
+ return (0);
+ }
+ pr_register = capture_register;
+ }
+ else
+ {
+ pr_register = strtol (where, NULL, 0);
+
+ if (pr_register < 1 || pr_register > MAX_REGISTERS)
+ {
+ inp_error ("invalid register");
+ return (0);
+ }
+ }
+
+ /* if the register is empty */
+ if (registers[pr_register].data == (void *)0) return (0);
+
+ /* print until there is no more data */
+ if (amount == -1) amount = registers[pr_register].size;
+
+ for (;;)
+ {
+ amount_to_print = MIN (serial_buffer_size, amount);
+
+ memcpy (serial_buffer, registers[pr_register].data+printed,
+ amount_to_print);
+
+ write_to_output_window (amount_to_print);
+
+ printed += amount_to_print;
+ if (printed >= amount) break;
+ }
+ }
+ else
+ inp_error ("nothing specified");
+
+ return (0);
+}
+
+/* Clear the input window. */
+int
+clear_scr (char *line)
+{
+ werase (input_window);
+ wmove (input_window, 0, 0);
+ wrefresh (input_window);
+
+ return (0);
+}
diff --git a/tap/memmgr.c b/tap/memmgr.c
new file mode 100755
index 0000000..04b0e49
--- /dev/null
+++ b/tap/memmgr.c
@@ -0,0 +1,257 @@
+/* memmgr.c
+ * This is the memory manager for Tap. The visible functions are
+ * xmalloc - allocate a block of memory
+ * xrealloc - change the size of a block of memory
+ * xfree - free a block of memory
+ * free_alloc_list - called at exit to free all memory
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "tap.h"
+
+/* minimum size block to allocate */
+
+#define MIN_ALLOC 8
+
+
+/* the alloc / free list */
+
+struct memory_block *alloc_list = NULL;
+
+/* the total available slots (the size of the alloc list) */
+
+long number_of_blocks = 0;
+
+/* the number of blocks that have been filled */
+
+long block_pointers_allocated = 0;
+
+
+/* This is called if malloc or realloc return NULL
+ *
+ * Give the user a choice to continue (and possibly
+ * close other memory-intensive applications) or to
+ * just exit. If this gets called more than
+ * MAX_TIMES_OUT_OF_MEMORY then just abort.
+ */
+void
+out_of_memory (void)
+{
+ char key;
+ static int times_out_of_memory = 0;
+
+ if (times_out_of_memory > MAX_TIMES_OUT_OF_MEMORY)
+ {
+ fprintf (stderr, "%s: virtual memory exhausted\n", pname);
+ abort ();
+ }
+
+ waddstr (input_window, "!! out of virtual memory !!\n\
+press <c> to attempt to continue (and possibly close other applications)\n\
+or any other key to abort: ");
+
+ /* don't use sgetch () here */
+ key = wgetch (input_window);
+
+ if (tolower (key) == 'c')
+ {
+ times_out_of_memory++;
+ longjmp (start_of_input_loop, 1);
+ }
+
+ abort ();
+}
+
+/* This is passed a pointer to memory (the same as passed to xrealloc
+ * or xfree). If it isn't found on the alloc list (using the mark)
+ * then abort is called.
+ */
+long
+get_block_index (void *mem)
+{
+ long mark;
+
+ /* in other words, mark = (long) mem[-MARK_SIZE] */
+ mark = ((long)* ((long *) ((mem) - MARK_SIZE)));
+
+ /* just check that it's somewhere on the list */
+ if (mark < block_pointers_allocated) return (mark);
+
+ /* this should never be reached */
+ fprintf (stderr,
+ "\n\r%s: tried to free or realloc block not on alloc list\n\r\
+block index %ld\n\r", pname, mark);
+ abort ();
+
+}
+
+/* Search for an unused block of memory with
+ * size >= min_size. If nothing is found return -1 otherwise
+ * return the index of a suitable block.
+ */
+long
+find_free_block (size_t min_size)
+{
+ long index;
+
+ /* scan through the whole list */
+ for (index = 0; index < block_pointers_allocated; index++)
+ {
+ if (alloc_list[index].in_use == FREE)
+ {
+ if (alloc_list[index].size >= min_size) return (index); /* got one */
+ }
+ }
+
+ /* nothing */
+ return (-1);
+}
+
+/* This function acts just like malloc except for using the
+ * alloc list to keep track of used and unused memory and
+ * checking for errors.
+ */
+void *
+xmalloc (size_t how_much)
+{
+ long block_index;
+
+ /* try to find a suitable block */
+ block_index = find_free_block (how_much);
+
+ if (block_index == -1)
+ { /* nothing found */
+
+ /* if the alloc list needs to be expanded */
+ if (block_pointers_allocated == number_of_blocks)
+ {
+ struct memory_block *temp;
+
+ temp = realloc (alloc_list, sizeof (struct memory_block)
+ * (number_of_blocks + GROW_SIZE));
+
+ if (temp == NULL) out_of_memory ();
+
+ alloc_list = temp;
+ number_of_blocks += GROW_SIZE;
+ }
+
+ /* now allocate a new block */
+
+ block_index = block_pointers_allocated;
+
+ block_pointers_allocated++;
+
+ alloc_list[block_index].memory = malloc ((how_much < MIN_ALLOC
+ ? MIN_ALLOC : how_much)
+ + MARK_SIZE);
+ if (alloc_list[block_index].memory == NULL) out_of_memory ();
+
+ alloc_list[block_index].size = (how_much < MIN_ALLOC)
+ ? MIN_ALLOC : how_much;
+
+ /* mark the block with the index */
+ * ((long *)alloc_list[block_index].memory) = block_index;
+ }
+
+ alloc_list[block_index].in_use = USED;
+ alloc_list[block_index].size_used = how_much;
+
+ return (alloc_list[block_index].memory + MARK_SIZE);
+}
+
+/* This function is just like realloc except that it uses the
+ * alloc list and checks the validity of realloc'ed memory.
+ */
+void *
+xrealloc (void *mem, size_t how_much)
+{
+ long index, orig_index;
+ void *new;
+
+ orig_index = get_block_index (mem);
+
+ /* first check if the block is already big enough */
+ if (alloc_list[orig_index].size >= how_much)
+ {
+ alloc_list[orig_index].size_used = how_much;
+ return (mem);
+ }
+
+ /* not big enough - try to find another one */
+
+ /* scan the alloc list */
+ for (index = 0; index < block_pointers_allocated; index++)
+ {
+ if (alloc_list[index].in_use == FREE)
+ {
+ if (alloc_list[index].size >= how_much)
+ {
+ /* found suitable block */
+ memcpy (alloc_list[index].memory + MARK_SIZE,
+ alloc_list[orig_index].memory + MARK_SIZE,
+ alloc_list[orig_index].size_used);
+
+ alloc_list[index].in_use = USED;
+ alloc_list[orig_index].in_use = FREE;
+
+ return (alloc_list[index].memory + MARK_SIZE);
+ }
+ }
+ }
+
+ /* have to actually realloc */
+ new = realloc (alloc_list[orig_index].memory, how_much + MARK_SIZE);
+
+ if (new == NULL) out_of_memory ();
+
+ alloc_list[orig_index].memory = new;
+
+ alloc_list[orig_index].size = how_much;
+ alloc_list[orig_index].size_used = how_much;
+
+ return (alloc_list[orig_index].memory + MARK_SIZE);
+}
+
+/* This function acts just like free except that it uses the alloc list. */
+void
+xfree (void *mem)
+{
+ long index;
+
+ index = get_block_index (mem);
+
+ alloc_list[index].in_use = FREE;
+}
+
+/* This is called at exit and it frees every block of memory allocated. */
+void
+free_alloc_list (void)
+{
+ long index;
+
+ for (index = 0; index < block_pointers_allocated; index++)
+ free (alloc_list[index].memory);
+
+ free (alloc_list);
+}
diff --git a/tap/readline/Makefile b/tap/readline/Makefile
new file mode 100755
index 0000000..a83987c
--- /dev/null
+++ b/tap/readline/Makefile
@@ -0,0 +1,38 @@
+# makefile for the Readline module of Tap.
+# Copyright (C) 1999 Jonathan duSaint
+#
+# This file is part of Tap, an interactive program for reading and
+# writing data to the serial port to facilitate the reverse
+# engineering of communication protocols.
+#
+# Tap is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# Tap is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# The GNU General Public License is generally kept in a file called
+# COPYING or LICENSE. If you do not have a copy of the license, write
+# to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+CC = gcc
+CFLAGS = -Wall -g -O2 -I..
+
+SRCFILES = history.c line.c ring.c tab.c text.c
+OBJFILES = $(SRCFILES:%.c=%.o)
+INCLUDEFILES = readline.h
+
+.PHONY : all clean
+
+all : readline.o
+
+readline.o : $(OBJFILES) $(INCLUDEFILES)
+ ld -r -o readline.o $(OBJFILES)
+
+clean :
+ rm -f readline.o $(OBJFILES) *~ core
diff --git a/tap/readline/history.c b/tap/readline/history.c
new file mode 100755
index 0000000..a833e1a
--- /dev/null
+++ b/tap/readline/history.c
@@ -0,0 +1,244 @@
+/* history.c
+ * Part of the Readline module for Tap. This is a simpler
+ * implementation of the GNU History library.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "readline.h"
+
+/* the history list itself
+ * The first node is not dynamically allocated. That way, no
+ * initialization function needs to be called.
+ */
+
+struct history_node the_history_list = { NULL, NULL, NULL, NULL };
+
+
+/* pointers into the history list */
+
+/* the last item in the history list */
+
+struct history_node *last_history = &the_history_list;
+
+/* the current item when the list is being traversed */
+
+struct history_node *current_history = &the_history_list;
+
+
+/* the most current line (which isn't itself on the history list) */
+
+char *saved_line = NULL;
+
+
+/* Get the next entry on the history list. If there isn't another node,
+ * return the saved line, or if that is the current line, return NULL.
+ */
+char *
+next_history (void)
+{
+ char *line_to_return;
+
+ /* already at the last entry */
+ if (current_history == last_history)
+ line_to_return = NULL;
+ else
+ {
+ current_history = current_history->next;
+
+ /* at the last entry, but still not on the most current line */
+ if (current_history == last_history)
+ {
+ line_to_return = saved_line;
+ saved_line = NULL;
+ }
+ else
+ {
+ /* (re)allocate scratch area if necessary */
+ if (current_history->saved_data == NULL)
+ {
+ current_history->saved_data =
+ xmalloc (ROUND_UP_SIZE (strlen (current_history->data)));
+
+ strcpy (current_history->saved_data, current_history->data);
+ }
+
+ line_to_return = current_history->saved_data;
+ }
+ }
+
+ return (line_to_return);
+}
+
+/* Get the previous line on the history list. If the current node is
+ * the first one, return NULL.
+ */
+char *
+prev_history (void)
+{
+ char *line_to_return;
+
+ /* at the oldest entry already */
+ if (current_history == &the_history_list)
+ line_to_return = NULL;
+ else
+ {
+ /* about to start traversing the list proper --
+ * need to save the most recent line
+ */
+ if (current_history == last_history)
+ saved_line = current_line;
+
+ current_history = current_history->prev;
+
+ /* (re)allocate scratch area if necessary */
+ if (current_history->saved_data == NULL)
+ {
+ current_history->saved_data =
+ xmalloc (ROUND_UP_SIZE (strlen (current_history->data)));
+
+ strcpy (current_history->saved_data, current_history->data);
+ }
+
+ line_to_return = current_history->saved_data;
+ }
+
+ return (line_to_return);
+}
+
+/* Add an entry into the history list. Don't save empty lines or
+ * lines that are exactly the same as the line immediately above.
+ */
+void
+add_history (char *line)
+{
+ /* don't save empty lines */
+ if (strlen (line) == 0) return;
+
+ /* if this is a modification of an earlier line, restore the original */
+ if (current_history != last_history) current_history->saved_data = NULL;
+
+ if (last_history->prev != NULL)
+ {
+ /* don't save copies */
+ if (!strcmp (last_history->prev->data, line))
+ {
+ current_history = last_history;
+ return;
+ }
+ }
+
+ /* save the line in the list */
+ last_history->data = xmalloc (ROUND_UP_SIZE (strlen (line)));
+ strcpy (last_history->data, line);
+
+ /* create a new node ... */
+ last_history->next = xmalloc (sizeof (struct history_node));
+
+ /* ... and fill it in */
+ last_history->next->data = NULL;
+ last_history->next->saved_data = NULL;
+ last_history->next->prev = last_history;
+ last_history->next->next = NULL;
+
+ /* update all pointers */
+ last_history = last_history->next;
+ current_history = last_history;
+}
+
+/* Expand a path if it contains a tilde */
+char *
+tilde_expand (char *file)
+{
+ char *expansion, *home;
+
+ home = getenv ("HOME");
+
+ if (file[0] == '~' && home != NULL)
+ {
+ expansion = xmalloc (strlen(file) + strlen(home));
+
+ sprintf (expansion, "%s%s", home, file + 1);
+ }
+ else
+ {
+ /* If there is no HOME or ~ is not in the string, just
+ * return a pointer which can be freed.
+ */
+ expansion = xmalloc (strlen(file) + 1);
+ strcpy (expansion, file);
+ }
+
+ return (expansion);
+}
+
+/* save the history list to a file -- usually ~/.tap_history */
+void
+save_history_to_file (char *file)
+{
+ char *path;
+ FILE *fd;
+
+ path = tilde_expand (file);
+
+ fd = fopen (path, "wt");
+ if (fd == NULL) return;
+
+ current_history = &the_history_list;
+
+ while (current_history != last_history)
+ {
+ fprintf (fd, "%s\n", current_history->data);
+
+ current_history = current_history->next;
+ }
+
+ fclose (fd);
+ xfree (path);
+}
+
+#define MAX_LINE_SIZE 1024
+
+void
+read_history_from_file (char *file)
+{
+ FILE *fd;
+ char *line, *path;
+
+ line = xmalloc (MAX_LINE_SIZE);
+
+ path = tilde_expand (file);
+
+ fd = fopen (path, "rt");
+ if (fd == NULL) return;
+
+ while (fgets (line, MAX_LINE_SIZE, fd) != NULL)
+ {
+ if (line[strlen (line) - 1] == '\n') line[strlen (line) - 1] = '\0';
+
+ add_history (line);
+ }
+
+ fclose (fd);
+ xfree (line);
+ xfree (path);
+}
diff --git a/tap/readline/line.c b/tap/readline/line.c
new file mode 100755
index 0000000..55ac482
--- /dev/null
+++ b/tap/readline/line.c
@@ -0,0 +1,340 @@
+/* line.c
+ * Part of the Readline module for Tap. This is the main file.
+ * The readline module was designed in a similar spirit as the GNU
+ * Readline module, but to work with ncurses, and, more specifically,
+ * with Tap. The functionality is similar, and the bindings are the
+ * same as in Emacs, however it is not as complete as in GNU Readline.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "readline.h"
+
+/* global variables which are important to the readline module */
+
+/* prompt to use */
+
+char *prompt;
+
+/* the line under construction */
+
+char *current_line;
+
+/* its actual size */
+
+long line_size;
+
+/* number of characters active */
+
+long chars_in_line;
+
+/* where the point is */
+
+long current_position;
+
+/* for when C-<spc> is pressed
+ * -1 means mark not set
+ */
+
+long mark_start;
+
+/* start position of the cursor */
+
+int start_y;
+
+/* repeat value from C-U */
+
+int repeat_value = 1;
+
+/* the kill ring */
+
+struct kill_ring *the_kill_ring = NULL;
+
+/* Clear the screen and reprint the current line */
+void
+clear_screen (void)
+{
+ clear_scr (NULL);
+
+ start_y = 0;
+
+ wprintw (input_window, "%s%s", prompt, current_line);
+}
+
+/* readchar () returns either an ASCII character, or a control
+ * code, which is a value >0xFF. All values are defined in readline.h.
+ */
+int
+readchar (void)
+{
+ int ch;
+
+ /* sgetch() is in serial/char.c */
+ ch = sgetch ();
+ /*ch = wgetch (input_window);*/
+
+ if (((char)ch) == '\n') return (ECQUIT);
+
+ if (isgraph (ch) || ch == ' ') return (ch);
+
+ switch (ch)
+ {
+ case RCUP:
+ return (ECUP);
+ case RCDOWN:
+ return (ECDOWN);
+ case RCLEFT:
+ return (ECLEFT);
+ case RCRIGHT:
+ return (ECRIGHT);
+ case RCSTART:
+ return (ECSTART);
+ case RCEND:
+ return (ECEND);
+ case RCDEL:
+ case RCDELK:
+ return (ECDEL);
+ case RCERASE:
+ return (ECERASE);
+ case RCMARK:
+ return (ECMARK);
+ case RCKILLL:
+ return (ECKILLL);
+ case RCKILLR:
+ return (ECKILLR);
+ case RCYANK:
+ return (ECYANK);
+ case RCTRANS:
+ return (ECTRANS);
+ case RCCLEAR:
+ return (ECCLEAR);
+ case RCCOUNT:
+ return (ECCOUNT);
+ case RCTAB:
+ return (ECTAB);
+ case RCESC:
+ ch = wgetch (input_window);
+
+ if (ch == EARROW)
+ {
+ int tch;
+
+ tch = wgetch (input_window);
+
+ switch (tch)
+ {
+ case AUP:
+ return (ECUP);
+ case ADOWN:
+ return (ECDOWN);
+ case ALEFT:
+ return (ECLEFT);
+ case ARIGHT:
+ return (ECRIGHT);
+ }
+
+ ungetch (tch);
+ }
+ /* fall through if one of the arrow keys wasn't recieved */
+ }
+
+ return (ECUNKNOWN);
+}
+
+/* If a control code was returned by readchar (), this function
+ * is called.
+ */
+void
+dispatch_special (int code)
+{
+ switch (code)
+ {
+ case ECLEFT:
+ move_cursor_left ();
+ break;
+ case ECRIGHT:
+ move_cursor_right ();
+ break;
+ case ECSTART:
+ move_cursor_to_start ();
+ break;
+ case ECEND:
+ move_cursor_to_end ();
+ break;
+ case ECDEL:
+ delete_char (RIGHT);
+ break;
+ case ECERASE:
+ delete_char (LEFT);
+ break;
+ case ECMARK:
+ mark_start = current_position;
+ break;
+ case ECKILLR:
+ kill_region ();
+ break;
+ case ECKILLL:
+ kill_to_eol ();
+ break;
+ case ECYANK:
+ yank_text ();
+ break;
+ case ECTRANS:
+ transpose_chars ();
+ break;
+ case ECCOUNT:
+ do_count ();
+ break;
+ case ECTAB:
+ do_tab_completion ();
+ break;
+ case ECUP:
+ {
+ char *line;
+
+ line = prev_history ();
+
+ if (line == NULL) warning_beep ();
+ else
+ {
+ move_cursor_to_start ();
+
+ current_line = line;
+ chars_in_line = strlen (line);
+ line_size = ROUND_UP_SIZE (chars_in_line);
+
+ move_cursor_to_end ();
+
+ mark_start = -1;
+ repeat_value = 1;
+ }
+ break;
+ }
+ case ECDOWN:
+ {
+ char *line;
+
+ line = next_history ();
+
+ if (line == NULL) warning_beep ();
+ else
+ {
+ move_cursor_to_start ();
+
+ current_line = line;
+ chars_in_line = strlen (line);
+ line_size = ROUND_UP_SIZE (chars_in_line);
+
+ move_cursor_to_end ();
+
+ mark_start = -1;
+ repeat_value = 1;
+ }
+
+ break;
+ }
+ case ECCLEAR:
+ {
+ int y_offset = input_window->_cury - start_y;
+ int x_pos = input_window->_curx;
+
+ clear_screen ();
+
+ input_window->_curx = x_pos;
+ input_window->_cury = y_offset;
+
+ break;
+ }
+ default:
+ warning_beep ();
+ }
+}
+
+/* Make sure that the screen is clear of junk after it has been
+ * modified (i.e. from inserting/removing a character).
+ */
+void
+refresh_screen (void)
+{
+ int x, y;
+
+ x = input_window->_curx;
+ y = input_window->_cury;
+
+ input_window->_cury = start_y;
+ input_window->_curx = 0;
+
+ wclrtobot (input_window);
+
+ wprintw (input_window, "%s%s", prompt, current_line);
+
+ input_window->_curx = x;
+ input_window->_cury = y;
+
+ wrefresh (input_window);
+}
+
+/* Given the prompt P, read a line of text in a user friendly manner. */
+char *
+readline (char *p)
+{
+ int ch;
+
+ /* initialize the kill ring if needed */
+ if (the_kill_ring == NULL) ring_init ();
+
+ /* initialize globals */
+ prompt = p;
+ chars_in_line = 0;
+ current_position = 0;
+ mark_start = -1;
+
+ start_y = input_window->_cury;
+
+ current_line = xmalloc (GROW_SIZE);
+ line_size = GROW_SIZE;
+
+ current_line[0] = 0;
+
+ waddstr (input_window, prompt);
+
+ while (1)
+ {
+ ch = readchar ();
+
+ if (ch == ECQUIT) break;
+
+ if (ch > 0xFF)
+ dispatch_special (ch);
+ else
+ insert_char (ch);
+
+ refresh_screen ();
+ }
+
+ add_history (current_line);
+
+ move_cursor_to_end ();
+ waddch (input_window, '\n');
+
+ return (current_line);
+}
diff --git a/tap/readline/readline.h b/tap/readline/readline.h
new file mode 100755
index 0000000..5a4cd69
--- /dev/null
+++ b/tap/readline/readline.h
@@ -0,0 +1,243 @@
+/* readline.h
+ * This is the header file for the Readline module for Tap.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "tap.h"
+
+/* extended character codes returned by readchar() */
+
+#define ECQUIT 0x100 /* \n */
+
+#define ECUP 0x101 /* ^P */
+#define ECDOWN 0x102 /* ^N */
+#define ECLEFT 0x103 /* ^B */
+#define ECRIGHT 0x104 /* ^F */
+#define ECSTART 0x105 /* ^A */
+#define ECEND 0x106 /* ^E */
+
+#define ECDEL 0x107 /* ^D */
+#define ECERASE 0x108 /* ^H */
+
+#define ECMARK 0x109 /* ^<spc> */
+#define ECKILLR 0x10A /* ^W */
+#define ECKILLL 0x10B /* ^K */
+#define ECYANK 0x10C /* ^Y */
+#define ECTRANS 0x10D /* ^T */
+#define ECCLEAR 0x10E /* ^L */
+
+#define ECCOUNT 0x10F /* ^U */
+
+#define ECTAB 0x110 /* \t */
+
+#define ECUNKNOWN 0xFFF /* unrecognized control code */
+
+
+/* raw character codes */
+
+#define RCUP 0x10
+#define RCDOWN 0x0E
+#define RCLEFT 0x02
+#define RCRIGHT 0x06
+#define RCSTART 0x01
+#define RCEND 0x05
+
+#define RCDEL 0x04
+#define RCDELK 0x7F
+#define RCERASE 0x08
+
+#define RCMARK 0x00
+#define RCKILLR 0x17
+#define RCKILLL 0x0B
+#define RCYANK 0x19
+#define RCTRANS 0x14
+#define RCCLEAR 0x0C
+
+#define RCCOUNT 0x15
+
+#define RCTAB '\t'
+
+/* arrow key escape sequence */
+
+#define RCESC 0x1B
+
+#define EARROW 0x4F
+
+#define AUP 0x41
+#define ADOWN 0x42
+#define ARIGHT 0x43
+#define ALEFT 0x44
+
+/* used by do_tab_completion () when creating internal structures */
+
+#define INCR_VALUE 8
+
+/* the default number of entries in the kill ring */
+
+#define DEFAULT_KILL_RING_SIZE 32
+
+/* the minimum amount of padding to use when printing partial matches */
+
+#define PADDING 2
+
+
+/* used for determing the actual amount of memory used by a line of text */
+
+#define ROUND_UP_SIZE(nom) (((nom + 1) / GROW_SIZE) * GROW_SIZE + GROW_SIZE)
+
+
+/* specifies to delete_char() whether to delete the
+ * character to the left or the right of the point
+ */
+
+enum direction
+{
+ LEFT, RIGHT
+};
+
+
+/* kill ring entries */
+
+struct kill_ring
+{
+ long length; /* the length of TEXT */
+ char *text; /* the actual text in the ring */
+
+ struct kill_ring *prev; /* the previous entry in the kill ring */
+ struct kill_ring *next; /* the next entry in the kill ring */
+};
+
+/* history list entries */
+
+struct history_node
+{
+ char *data; /* the actual history entry */
+ char *saved_data; /* temporary entry used for when an
+ earlier line is being edited */
+ struct history_node *prev; /* the previous entry in the history list */
+ struct history_node *next; /* the next entry in the history list */
+};
+
+
+/* global variables */
+
+/* prompt to use */
+
+extern char *prompt;
+
+/* the line under construction */
+
+extern char *current_line;
+
+/* its actual size */
+
+extern long line_size;
+
+/* number of characters active */
+
+extern long chars_in_line;
+
+/* where the point is */
+
+extern long current_position;
+
+/* for when C-<spc> is pressed */
+
+extern long mark_start;
+
+/* start position of the cursor */
+
+extern int start_y;
+
+/* cursor position after the prompt has been printed */
+
+extern int start_x;
+
+/* the last repeat value -- should be 1 unless C-U has just been typed */
+
+extern int repeat_value;
+
+/* the kill ring */
+
+extern struct kill_ring *the_kill_ring;
+
+/* a zero length string */
+
+extern char zero_length_string[];
+
+
+/* function prototypes */
+
+/* the main function -- read a line of text */
+
+extern char *readline (char *);
+
+/* character functions used by readline () */
+
+extern int readchar (void);
+
+extern void dispatch_special (int);
+
+/* keystroke functions */
+
+extern void kill_region (void);
+
+extern void kill_to_eol (void);
+
+extern void insert_char (char);
+
+extern void delete_char (enum direction);
+
+extern void move_cursor_left (void);
+
+extern void move_cursor_right (void);
+
+extern void move_cursor_to_start (void);
+
+extern void move_cursor_to_end (void);
+
+extern void transpose_chars (void);
+
+extern void yank_text (void);
+
+extern void do_count (void);
+
+/* functions for the kill ring */
+
+extern void kill_to_ring (int, int);
+
+extern char *get_ring_entry (int);
+
+extern void ring_init (void);
+
+/* tab completion */
+
+extern void do_tab_completion (void);
+
+/* history functions */
+
+extern void add_history(char *);
+
+extern char *next_history (void);
+
+extern char *prev_history (void);
diff --git a/tap/readline/ring.c b/tap/readline/ring.c
new file mode 100755
index 0000000..474cc27
--- /dev/null
+++ b/tap/readline/ring.c
@@ -0,0 +1,114 @@
+/* ring.c
+ * Part of the Readline module for Tap. This is the implementation
+ * of the kill ring.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "readline.h"
+
+/* If the requested entry in the kill ring is NULL,
+ * this is returned instead.
+ */
+char zero_length_string[] = "";
+
+/* Returns text previously yanked, with the most recent
+ * having an index of 1. If the entry is NULL, returns
+ * a pointer to a zero length string. Memory returned by
+ * this call should never be freed
+ */
+char *
+get_ring_entry (int which)
+{
+ struct kill_ring *current;
+ int k;
+
+ which--;
+ current = the_kill_ring;
+
+ for (k = 0; k < which; k++) current = current->prev;
+
+ if (current->text == NULL) return (zero_length_string);
+
+ return (current->text);
+}
+
+/* Add TEXT to the kill ring and advance the ring. The
+ * memory passed to this function should never be freed.
+ */
+void
+add_ring_entry (char *text)
+{
+ the_kill_ring = the_kill_ring->next;
+
+ if (the_kill_ring->text != NULL) xfree (the_kill_ring->text);
+
+ the_kill_ring->text = text;
+ the_kill_ring->length = strlen (text);
+}
+
+/* Copy text from START to FINISH to a new block
+ * and add block to kill ring
+ */
+void
+kill_to_ring (int start, int finish)
+{
+ char *text;
+
+ text = xmalloc (finish - start + 1);
+
+ strncpy (text, current_line + start, finish - start);
+ text[finish - start] = 0;
+
+ add_ring_entry (text);
+}
+
+/* Initialize the kill ring.
+ */
+void
+ring_init (void)
+{
+ int k;
+ struct kill_ring *current;
+
+ /* allocate first separately */
+ the_kill_ring = xmalloc (sizeof (struct kill_ring));
+ the_kill_ring->length = 0;
+ the_kill_ring->text = NULL;
+
+ current = the_kill_ring;
+
+ for (k = 0; k < DEFAULT_KILL_RING_SIZE - 2; k++)
+ {
+ current->next = xmalloc (sizeof (struct kill_ring));
+
+ current->next->length = 0;
+ current->next->text = NULL;
+ current->next->prev = current;
+
+ current = current->next;
+ }
+
+ /* complete the ring */
+ current->next = the_kill_ring;
+ the_kill_ring->prev = current;
+}
diff --git a/tap/readline/tab.c b/tap/readline/tab.c
new file mode 100755
index 0000000..dea8e15
--- /dev/null
+++ b/tap/readline/tab.c
@@ -0,0 +1,530 @@
+/* tab.c
+ * Part of the Readline module for Tap. This is where command line
+ * completion is implemented.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "readline.h"
+#include <glob.h>
+
+/* returned to do_tab_completion () when a successful match hasn't been made */
+char *null_match[] = { NULL, NULL };
+
+/* find the number of matching characters in the two strings */
+int
+strmatch (char *first, char *second)
+{
+ int highest;
+
+ for (highest = 0; highest < MAX (strlen (first), strlen (second)); highest++)
+ if (first[highest] != second[highest]) break;
+
+ return (highest);
+}
+
+/* Scan an array of strings looking for the largest
+ * number of matching characters. For the array
+ *
+ * "dobri"
+ * "dyen"
+ * "dinamacheskiye"
+ * "dudayevtsi"
+ *
+ * the result would be 1.
+ */
+int
+find_matching_chars (char *matches[])
+{
+ int current_match, max_match = INT_MAX, index, last = 0;
+
+ while (matches[last + 1] != NULL) last++;
+
+ if (!last) return (strlen (matches[0])); /* one item in array */
+
+ for (index = 1; index <= last; index++)
+ {
+ current_match = strmatch (matches[index - 1], matches[index]);
+
+ max_match = MIN (max_match, current_match);
+ }
+
+ return (max_match);
+}
+
+/* Return an array of strings containing the main command names */
+char **
+command_names (void)
+{
+ static char **names = NULL;
+ int index = 0, max_commands;
+
+ if (names != NULL) return (names);
+
+ names = xmalloc (sizeof (char *) * INCR_VALUE);
+ max_commands = INCR_VALUE;
+
+ while (commands[index].name != NULL)
+ {
+ if (index == max_commands - 1)
+ {
+ names = xrealloc (names, sizeof (char *)*(max_commands+INCR_VALUE));
+ max_commands += INCR_VALUE;
+ }
+
+ names[index] = commands[index].name;
+ index++;
+ }
+
+ names[index] = NULL;
+
+ return (names);
+}
+
+/* Return the `number' of the current token */
+int
+find_current_token_number (void)
+{
+ int token_number = 1, pos = current_position + 1;
+
+ while (pos--)
+ { /* scan backward counting whitespace regions */
+
+ if (current_line[pos] == ' ') /* found one */
+ {
+ token_number++;
+
+ /* skip the rest of the region */
+ while (current_line[pos] == ' ' && pos) pos--;
+
+ /* if the first char is ' ' */
+ if (!pos && current_line[pos] == ' ') token_number--;
+ }
+ }
+
+ return (token_number);
+}
+
+/* move the point to the end of the current token */
+void
+move_to_token_end (void)
+{
+ while (current_line[current_position] != ' '
+ && current_position != chars_in_line) move_cursor_right ();
+}
+
+/* If a match string for a command is \f, this function is
+ * called. Uses the POSIX.2 function glob() to match files
+ * and returns all files matched by SEARCH with a '*' tacked
+ * onto the end.
+ */
+char **
+match_file_esc (char *search)
+{
+ glob_t file_list;
+ int k;
+ char **ret_list, *pattern;
+
+ pattern = xmalloc (strlen (search) + 2);
+ sprintf (pattern, "%s*", search);
+
+ if (glob (pattern, GLOB_MARK, NULL, &file_list)) return (null_match);
+
+ ret_list = xmalloc ((file_list.gl_pathc + 1) * sizeof (char *));
+
+ for (k = 0; k < file_list.gl_pathc; k++)
+ {
+ ret_list[k] = xmalloc (strlen (file_list.gl_pathv[k]) + 1);
+ strcpy (ret_list[k], file_list.gl_pathv[k]);
+ }
+
+ ret_list[file_list.gl_pathc] = NULL;
+
+ xfree (pattern);
+ return (ret_list);
+}
+
+/* Returns an array of strings which match the escape. Valid
+ * escapes are \f - a filename, \c - a command name, and \m - anything.
+ */
+char **
+find_esc_matches (char *search, char *esc_code)
+{
+ switch (esc_code[1])
+ {
+ case 'f':
+ return (match_file_esc (search));
+
+ /* this will be made functional later -- it isn't
+ * used for anything now anyways */
+ case 'c':
+
+ case 'm': /* this doesn't match anything specific */
+ return (null_match);
+ }
+
+ return (null_match);
+}
+
+/* Given a search string and an array of strings, returns an
+ * array of strings which match
+ */
+char **
+find_matches (char *search, char **potential_matches)
+{
+ char **actual_matches;
+ int possible_completions, length = strlen (search), last_completion = -1, k;
+
+ /* count the entries in potential_matches */
+ for (possible_completions = 0;
+ potential_matches[possible_completions] != NULL;
+ possible_completions++);
+
+ /* check for escapes */
+ if (possible_completions == 1 && potential_matches[0][0] == '\\')
+ return (find_esc_matches (search, potential_matches[0]));
+
+ actual_matches = xmalloc ((possible_completions + 1) * sizeof (char *));
+
+ /* zero out the output array */
+ for (k = 0; k < possible_completions + 1; k++) actual_matches[k] = NULL;
+
+ /* loop backward looking for matches */
+ while (possible_completions--)
+ {
+ /* found a match */
+ if (!strncmp (search, potential_matches[possible_completions], length))
+ {
+ /* add to match list */
+ actual_matches[++last_completion] =
+ potential_matches[possible_completions];
+ }
+ }
+
+ return (actual_matches);
+}
+
+/* Expands a token to the maximum possible size using
+ * partial matches. Assumes that the point is at the end of the token
+ * to be expanded, that token contains the partial token, and
+ * that matches is a NULL terminated array with strings that
+ * are matched by token.
+ */
+void
+expand_text (char *token, char *matches[])
+{
+ int match_length, tok_length, match_pos;
+
+ match_pos = tok_length = strlen (token);
+
+ match_length = find_matching_chars (matches) - tok_length;
+
+ if (match_length < 1) return;
+
+ while (match_length--) insert_char (matches[0][match_pos++]);
+
+ if (current_line[current_position] != ' '
+ && matches[1] == NULL
+ && current_line[current_position - 1] != '/')
+ insert_char (' ');
+}
+
+/* Retrieves the match string for COMMAND. In other words
+ * returns commands[n].tab_completion when
+ * strcmp (command, commands[n].name) == 0
+ */
+char *
+get_match_string (char *command)
+{
+ int index = -1, tok_len = strlen (command);
+
+ while (commands[++index].name != NULL)
+ {
+ if (!strncmp (command, commands[index].name, tok_len))
+ return (commands[index].tab_completion);
+ }
+
+ /* this should never be reached */
+ return (zero_length_string);
+}
+
+/* print all of the strings in MATCHES */
+void
+print_partial_matches (char *matches[])
+{
+ int index, command_width = 0, commands_per_line;
+ int x_pos = input_window->_curx, y, y_offset;
+
+ y = input_window->_cury;
+ move_cursor_to_end ();
+ y_offset = input_window->_cury - y;
+
+ waddch (input_window, '\n');
+
+ /* find longest string */
+ index = -1;
+ while (matches[++index] != NULL)
+ command_width = MAX (command_width, strlen (matches[index]));
+
+ command_width += PADDING;
+
+ commands_per_line = window_width / command_width;
+
+ /* print strings */
+ index = -1;
+ while (matches[++index] != NULL)
+ {
+ wprintw (input_window, "%-*s", command_width, matches[index]);
+ if (!((index + 1) % commands_per_line)) waddch (input_window, '\n');
+ }
+
+ if (input_window->_curx) waddch (input_window, '\n');
+
+ start_y = input_window->_cury;
+
+ wprintw (input_window, "%s%s", prompt, current_line);
+
+ input_window->_curx = x_pos;
+ input_window->_cury -= y_offset;
+}
+
+/* Returns the NUMBERth token in current_line */
+char *
+get_token_by_number (int number)
+{
+ int pos = 0;
+
+ while (number--)
+ {
+ if (number)
+ while (current_line[pos] != ' ' && pos < chars_in_line) pos++;
+
+ while (current_line[pos] == ' ' && pos < chars_in_line) pos++;
+ }
+
+ return (get_token_only (current_line + pos));
+}
+
+/* Returns the position of the next level one match_string
+ */
+int
+next_level_one (char *match_string, int pos)
+{
+ int depth = 0;
+
+ pos--;
+
+ while (match_string[++pos] != '\0')
+ {
+ switch (match_string[pos])
+ {
+ case '{':
+ depth++;
+ break;
+ case '}':
+ depth--;
+ break;
+ case ',':
+ if (!depth)
+ return (pos + 1);
+ }
+ }
+
+ return (-1);
+}
+
+/* Returns the sub-match_string for TOKEN. If TOKEN isn't in
+ * MATCH_STRING, returns ""
+ */
+char *
+get_sublist (char *token, char *match_string)
+{
+ int pos = 0, len;
+ char *sublist;
+
+ while (1)
+ {
+ /* got a match */
+ if (!strncmp (token, match_string + pos, strlen (token))) break;
+
+ pos = next_level_one (match_string, pos);
+
+ if (pos == -1) return (zero_length_string);
+ }
+
+ /* skip to end of token */
+ while ((match_string[pos] != ',') && (match_string[pos] != '{')
+ && (match_string[pos] != '\0')) pos++;
+
+ if (match_string[pos] != '{') return (zero_length_string);
+
+ /* find substring */
+ len = next_level_one (match_string, pos);
+
+ if (len == -1)
+ len = strlen (match_string) - pos + 1;
+ else
+ len -= pos;
+
+ len -= 3;
+
+ /* extract */
+ sublist = xmalloc (len + 1);
+ strncpy (sublist, match_string + pos + 1, len);
+ sublist[len] = '\0';
+
+ return (sublist);
+}
+
+/* Returns an array with the top level entries in SEARCH_TEXT */
+char **
+get_search_strings (char *search_text)
+{
+ char **search_strings = NULL;
+ int offset, pos = 0, current = 0, max_str;
+
+ search_strings = xmalloc (INCR_VALUE * sizeof (char *));
+ max_str = INCR_VALUE;
+
+ while (1)
+ {
+ offset = 0;
+ while ((search_text[pos + offset] != ',')
+ && (search_text[pos + offset] != '{')
+ && (search_text[pos + offset] != '\0')) offset++;
+
+ if (offset == 0) break;
+
+ if (current == max_str - 1)
+ {
+ search_strings = xrealloc (search_strings,
+ sizeof (char *) * (max_str + INCR_VALUE));
+ max_str += INCR_VALUE;
+ }
+
+ search_strings[current] = xmalloc (offset + 1);
+ strncpy (search_strings[current], search_text + pos, offset);
+ search_strings[current++][offset] = '\0';
+
+ switch (search_text[pos + offset])
+ {
+ case ',':
+ pos = pos + offset + 1;
+ break;
+ case '{':
+ pos = next_level_one (search_text, pos + offset);
+ break;
+ case '\0':
+ goto END;
+ }
+ }
+
+ END:
+ search_strings[current] = NULL;
+ return (search_strings);
+}
+
+/* Frees the array returned by get_search_strings () */
+void
+free_search_strings (char *search_strings[])
+{
+ int index = -1;
+
+ while (search_strings[++index] != NULL) xfree (search_strings[index]);
+
+ xfree (search_strings);
+}
+
+/* Completes the current token as much as possible */
+void
+do_tab_completion (void)
+{
+ char *first, **matches, **search_strings, *match_string, *token = NULL;
+ int token_number = find_current_token_number (), tok;
+
+ search_strings = command_names ();
+
+ first = get_token_by_number (1);
+
+ matches = find_matches (first, search_strings);
+
+ if (matches[0] == NULL)
+ {
+ warning_beep ();
+ return;
+ }
+
+ if (token_number == 1)
+ {
+ /* just matching the first token */
+ move_to_token_end ();
+ expand_text (first, matches);
+
+ if (matches[1] != NULL) print_partial_matches (matches);
+
+ return;
+ }
+ else if (matches[1] != NULL)
+ {
+ /* trying to match other than the first token w/o a unique
+ * first token -- bad news
+ */
+ warning_beep ();
+ return;
+ }
+
+ /* matching other than the first token */
+ match_string = get_match_string (first);
+
+ /* match all preceding tokens to find out what is trying to be matched */
+ for (tok = 2; tok < token_number; tok++)
+ {
+ token = get_token_by_number (tok);
+ match_string = get_sublist (token, match_string);
+
+ if (strlen (match_string) == 0)
+ {
+ warning_beep ();
+ return;
+ }
+ }
+
+ token = get_token_by_number (token_number);
+
+ /* got a matchlist for this token */
+ search_strings = get_search_strings (match_string);
+
+ matches = find_matches (token, search_strings);
+
+ if (matches[0] == NULL)
+ {
+ warning_beep ();
+ return;
+ }
+
+ move_to_token_end ();
+ expand_text (token, matches);
+
+ if (matches[1] != NULL) print_partial_matches (matches);
+
+ free_search_strings (search_strings);
+}
diff --git a/tap/readline/text.c b/tap/readline/text.c
new file mode 100755
index 0000000..2cb7adf
--- /dev/null
+++ b/tap/readline/text.c
@@ -0,0 +1,354 @@
+/* text.c
+ * Part of the Readline module for Tap. These are functions which
+ * manipulate the text in some way.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "readline.h"
+
+/* Move the cursor one space to the left,
+ * don't perform range check and don't update
+ * position in line
+ */
+void
+cursor_left (void)
+{
+ if (input_window->_curx == 0)
+ {
+ input_window->_cury--;
+ input_window->_curx = window_width - 1;
+ }
+ else
+ input_window->_curx--;
+}
+
+/* Move the cursor one space to the right,
+ * don't perform range check and don't update
+ * position in line
+ */
+void
+cursor_right (void)
+{
+ if (input_window->_curx + 1 == window_width)
+ {
+ input_window->_cury++;
+ input_window->_curx = 0;
+ }
+ else
+ input_window->_curx++;
+}
+
+/* Kill the region from the mark to the point;
+ * bound to C-w
+ */
+void
+kill_region (void)
+{
+ long kstart, kend;
+
+ /* find the region to be killed */
+ if (mark_start == -1)
+ {
+ warning_beep ();
+ return;
+ }
+ else if (mark_start == current_position)
+ {
+ mark_start = -1;
+ return;
+ }
+ else if (mark_start < current_position)
+ {
+ int k;
+
+ kstart = mark_start;
+ kend = current_position;
+
+ for (k = 0; k < kend - kstart; k++) cursor_left ();
+ }
+ else
+ {
+ kstart = current_position;
+ kend = mark_start;
+ }
+
+ kill_to_ring (kstart, kend);
+
+ memmove (current_line + kstart, current_line + kend,
+ chars_in_line - kend + 1);
+
+ chars_in_line -= kend - kstart;
+ mark_start = -1;
+
+ current_position = kstart;
+}
+
+/* Kill from the point to the end of the line;
+ * bound to C-k
+ */
+void
+kill_to_eol (void)
+{
+ kill_to_ring (current_position, chars_in_line);
+
+ current_line[current_position] = 0;
+ chars_in_line = current_position;
+}
+
+/* Move the cursor left, doing range check and
+ * updating position in line;
+ * bound to C-b and the left arrow key
+ */
+void
+move_cursor_left (void)
+{
+ if (current_position == 0)
+ {
+ warning_beep ();
+ return;
+ }
+
+ current_position--;
+
+ cursor_left ();
+}
+
+/* Move the cursor right, doing range check and
+ * updating position in line;
+ * bound to C-f and the right arrow key
+ */
+void
+move_cursor_right (void)
+{
+ if (current_position == chars_in_line)
+ {
+ warning_beep ();
+ return;
+ }
+
+ current_position++;
+
+ cursor_right ();
+}
+
+/* Move the cursor to the start of the line;
+ * bound to C-a
+ */
+void
+move_cursor_to_start (void)
+{
+ int k;
+
+ for (k = 0; k < current_position; k++) cursor_left ();
+
+ current_position = 0;
+}
+
+/* Move the cursor to the end of the line;
+ * bound to C-e
+ */
+void
+move_cursor_to_end (void)
+{
+ int k;
+
+ for (k = 0; k < chars_in_line - current_position; k++) cursor_right ();
+
+ current_position = chars_in_line;
+}
+
+/* Transpose the character under the point with the one
+ * to the left performing range checking;
+ * bound to C-t
+ */
+void
+transpose_chars (void)
+{
+ char ch;
+
+ if (current_position == 0 || current_position == chars_in_line)
+ {
+ warning_beep ();
+ return;
+ }
+
+ ch = current_line[current_position];
+ current_line[current_position] = current_line[current_position - 1];
+ current_line[current_position - 1] = ch;
+
+ move_cursor_right ();
+}
+
+/* Insert CH into the line at CURRENT_POSITION
+ */
+void
+insert_char (char ch)
+{
+ if (chars_in_line + 1 == line_size)
+ {
+ current_line = xrealloc (current_line, line_size + GROW_SIZE);
+ line_size += GROW_SIZE;
+ }
+
+ memmove (current_line + current_position + 1,
+ current_line + current_position,
+ chars_in_line - current_position + 1);
+
+ current_line[current_position] = ch;
+
+ cursor_right ();
+
+ current_position++;
+ chars_in_line++;
+}
+
+/* Delete the character either under the point
+ * or to the left depending on the direction;
+ * bound to C-d and DEL as RIGHT and C-h and
+ * BACKSPACE as LEFT
+ */
+void
+delete_char (enum direction which)
+{
+ /* check if there is a char to delete */
+ if ((which == LEFT && current_position == 0)
+ || (which == RIGHT && current_position == chars_in_line))
+ {
+ warning_beep ();
+ return;
+ }
+
+ if (which == LEFT)
+ {
+ current_position--;
+ cursor_left ();
+ }
+
+ memmove (current_line + current_position,
+ current_line + current_position + 1,
+ chars_in_line - current_position);
+
+ chars_in_line--;
+}
+
+/* Yank text out of the kill ring and insert into the line;
+ * bound to C-y
+ */
+void
+yank_text (void)
+{
+ int k;
+ char *insert_text;
+
+ insert_text = get_ring_entry (repeat_value);
+
+ for (k = 0; k < strlen (insert_text); k++)
+ {
+ insert_char (insert_text[k]);
+ }
+}
+
+/* Read in a number and repeat the following command that
+ * many times, or if the next command is yank, uses the
+ * count as an index into the kill ring;
+ * bound to C-u
+ */
+void
+do_count (void)
+{
+ int k, y_save, ok, ch = 0, x0, y0, line_pos;
+
+ /* save the sojourn */
+ x0 = input_window->_curx;
+ y0 = input_window->_cury;
+ line_pos = current_position;
+
+ move_cursor_to_end ();
+
+ waddstr (input_window, "\nC-u> "); wrefresh (input_window);
+
+ y_save = input_window->_cury;
+
+ repeat_value = 0;
+
+ /* read in a number */
+ while (1)
+ {
+ ch = wgetch (input_window);
+ if (ch >= '0' && ch <= '9')
+ {
+ repeat_value *= 10;
+ repeat_value += ch - '0';
+
+ waddch (input_window, ch); wrefresh (input_window);
+ }
+ else
+ {
+ /* if ok == 1 , the number has been read */
+ ok = (ch == '\n') ? 1 : 0;
+ break;
+ }
+ }
+
+ if (ok) /* got a \n */
+ {
+ waddch (input_window, ' '); wrefresh (input_window);
+ ch = readchar ();
+ }
+
+ /* restore the old positions */
+ input_window->_cury = y_save;
+ input_window->_curx = 0;
+
+ waddnstr (input_window, " ", window_width); wrefresh (input_window);
+
+ input_window->_curx = x0;
+ input_window->_cury = y0;
+ current_position = line_pos;
+
+ if (!ok) /* if a valid number wasn't read, just return */
+ {
+ repeat_value = 1;
+ warning_beep ();
+ return;
+ }
+
+ if (ch == ECYANK)
+ yank_text ();
+ else if (ch == ECQUIT)
+ ungetch ('\n');
+ else if (ch == ECCOUNT)
+ warning_beep ();
+ else
+ {
+ for (k = 0; k < repeat_value; k++)
+ {
+ if (ch > 0xFF)
+ dispatch_special (ch);
+ else
+ insert_char (ch);
+ }
+ }
+
+ repeat_value = 1;
+}
diff --git a/tap/serial.c b/tap/serial.c
new file mode 100755
index 0000000..2963897
--- /dev/null
+++ b/tap/serial.c
@@ -0,0 +1,87 @@
+/* serial.c
+ * This file contains the function sgetch () which reads a
+ * character from stdin while listening to the serial port.
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "tap.h"
+
+/* This function reads a fixed number of chars from the serial port
+ * and then writes it to wherever it needs to go. */
+void
+read_serial_data (void)
+{
+ int data_read;
+
+ data_read = read (serial_port_fd, serial_buffer, serial_buffer_size);
+
+ write_to_output_window (data_read);
+ write_to_capture_register (data_read);
+ write_to_capture_file (data_read);
+}
+
+/* This function reads a character from stdin while listening to
+ * the serial port (if one is open).
+ */
+int
+sgetch (void)
+{
+ fd_set readfs;
+ int ret, highest_port = 1, fds;
+
+ for (;;)
+ {
+ /* set focus to input_window */
+ wrefresh (input_window);
+
+ FD_ZERO (&readfs);
+ FD_SET (0, &readfs); /* always listen to stdin */
+
+ if (port != NULL)
+ { /* if a serial port is open */
+ FD_SET (serial_port_fd, &readfs);
+ highest_port = serial_port_fd + 1;
+ }
+
+ fds = select (highest_port, &readfs, NULL, NULL, NULL);
+
+ if (fds < 0)
+ { /* error */
+ /* for now just ignore it */
+ }
+ else if (fds > 0)
+ {
+ if (FD_ISSET (0, &readfs))
+ {
+ ret = wgetch (input_window);
+ return (ret);
+ }
+ else if (FD_ISSET (serial_port_fd, &readfs))
+ {
+ read_serial_data (); /* and reloop */
+ }
+ }
+ }
+
+ return (ret);
+}
diff --git a/tap/tap.c b/tap/tap.c
new file mode 100755
index 0000000..dd55ff7
--- /dev/null
+++ b/tap/tap.c
@@ -0,0 +1,274 @@
+/* tap.c
+ * Main program of Tap.
+ *
+ * Usage:
+ * -p --port <serial port> serial port to open on startup
+ * -s --save_history [<file name>] whether or not to save the command history
+ *
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "tap.h"
+#include "version.h"
+#include "command_struct.h"
+
+
+/* global variables */
+
+/* name of the program (argv[0]) */
+
+char *pname;
+
+/* the name of the serial port */
+
+char *port = NULL;
+
+/* the name of the history file */
+
+char *history_file_name;
+
+/* whether or not to save history */
+
+int save_history = 0;
+
+/* the size for the data registers */
+
+int register_size = DEFAULT_REGISTER_SIZE;
+
+/* the registers themselves */
+
+struct data_register registers[MAX_REGISTERS];
+
+/* jmp_buf for recovery from nearly unrecoverable situations */
+
+jmp_buf start_of_input_loop;
+
+/* the format for displaying output and parsing input */
+
+enum io_format input_format = ASCII_COOKED;
+
+enum io_format output_format = ASCII_COOKED;
+
+
+/* Print useful version information. */
+void
+print_version (void)
+{
+ printf ("Tap %s\n\
+Copyright (C) 1999 Jonathan duSaint <jon@mbayweb.com>\n\
+Tap comes with NO WARRANTY,\n\
+to the extent permitted by law.\n\
+You may redistribute copies of Tap\n\
+under the terms of the GNU General Public License.\n\
+For more information about these matters,\n\
+see the file named COPYING.\n", version);
+}
+
+/* Print some usage information. */
+void
+print_help (void)
+{
+ printf ("Tap %s\n\
+Usage: tap [-p <port>][-s [history file name]]\n\
+Report bugs to jon@mbayweb.com after consulting\n\
+the file BUGS\n", version);
+}
+
+/* Returns the first token in line, but does not return any of
+ * the other information provided by get_token.
+ */
+char *
+get_token_only (const char *line)
+{
+ int next, length;
+
+ return (get_token (line, &next, &length));
+}
+
+/* Returns the first token in LINE. The index of the next token is
+ * returned in NEXT and the length of the token is returned in
+ * TOK_LEN. It is assumed that the first char of line is not
+ * a token delimeter, which is the space character.
+ */
+char *
+get_token (const char *line, int *next, int *tok_len)
+{
+ int got_name = 0, nxt = 0, cmd_len = 0;
+ char *cmd = NULL;
+
+ do
+ {
+ switch (line[nxt])
+ {
+ case ' ':
+ case 0:
+ /* found the end of the token */
+ got_name = 1;
+ cmd_len = nxt;
+
+ /* skip to the next token */
+ while (!(isgraph (line[nxt]) || (line[nxt] == 0))) nxt++;
+
+ break;
+ default:
+ if (!isgraph (line[nxt]))
+ {
+ inp_error ("invalid character");
+ return (NULL);
+ }
+ }
+
+ nxt++;
+ }
+ while (!got_name);
+
+ cmd = xmalloc (cmd_len + 1);
+ strncpy (cmd, line, cmd_len);
+ cmd[cmd_len] = 0;
+
+ *next = nxt - 1;
+ *tok_len = cmd_len;
+ return (cmd);
+}
+
+/* This function is responsible for taking the line returned by
+ * readline() and dispatching it off to the proper place. Anything
+ * other than a zero return value indicates to terminate the program.
+ */
+int
+parse_command_line (char *line)
+{
+ char *cmd;
+ int cmd_len, nxt = 0, current = 0;
+
+ /* skip initial whitespace */
+ while (*line == ' ') line++;
+
+ cmd = get_token (line, &nxt, &cmd_len);
+ if (cmd == NULL) return (0);
+
+ cmd = resolve_alias (cmd);
+
+ while (commands[current].function != NULL)
+ {
+ if (!strcmp (commands[current].name, cmd))
+ return (commands[current].function (line + nxt));
+ current++;
+ }
+
+ inp_error ("unknown command");
+ return (0);
+}
+
+
+/* Tap itself */
+int
+main (int argc, char *argv[])
+{
+ int opt, index = 0, have_port = 0;
+ char *line, *t_port = NULL;
+ struct option options[] = {
+ { "port", required_argument, NULL, 'p' },
+ { "save-history", optional_argument, NULL, 's' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { 0, 0, 0, 0 }
+ };
+
+ /* initialize global variables */
+ pname = argv[0];
+ opterr = 0;
+ history_file_name = "~/.tap_history";
+
+ /* parse command line for options */
+ while (1)
+ {
+ opt = getopt_long (argc, argv, "p:s::hv", options, &index);
+
+ if (opt == EOF) break;
+
+ switch (opt)
+ {
+ case 'p':
+ t_port = optarg;
+ have_port = 1;
+ break;
+ case 's':
+ if (optarg) history_file_name = optarg;
+ read_history_from_file (history_file_name);
+ save_history = 1;
+ break;
+ case 'h':
+ print_help ();
+ return (0);
+ case 'v':
+ print_version ();
+ return (0);
+ case ':':
+ exit (1);
+ case '?':
+ fprintf (stderr, "%s: unknown option character `%c'\n",
+ pname, optopt);
+ break;
+ default:
+ fprintf (stderr, "%s: ?? getopt returned character code 0x%x ??\n",
+ pname, opt);
+ }
+ }
+
+ initscr ();
+
+ keypad (stdscr, TRUE);
+ raw ();
+ noecho ();
+
+ init_console_ui ();
+
+ /* --port was passed */
+ if (have_port) open_p (t_port);
+
+ /* prepare for truly horrendous errors (only from the memory manager) */
+ setjmp (start_of_input_loop);
+
+ /* main loop */
+ for (;;)
+ {
+ refresh_console_status_line ();
+
+ line = readline (">> ");
+
+ if (!strlen (line)) continue;
+ if (parse_command_line (line)) break;
+ }
+
+ destroy_console_ui ();
+ endwin ();
+
+ close_p (NULL);
+
+ if (save_history) save_history_to_file (history_file_name);
+
+ free_alloc_list ();
+
+ return (0);
+}
diff --git a/tap/tap.h b/tap/tap.h
new file mode 100755
index 0000000..5cd778b
--- /dev/null
+++ b/tap/tap.h
@@ -0,0 +1,370 @@
+/* tap.h
+ * This is the main header file for Tap. In this file are declarations
+ * of all visible functions and all external datatypes.
+ */
+
+/* all of the includes for all of the source files */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <signal.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <getopt.h>
+#include <ncurses.h>
+
+
+/* the default number of user registers */
+
+#define MAX_REGISTERS 64
+
+/* default size of registers, user may reset size with a call to set */
+
+#define DEFAULT_REGISTER_SIZE 64
+
+/* by how much command line buffer grows with each realloc */
+
+#define GROW_SIZE 8
+
+/* the minimum size of an alloc'ed block of memory */
+
+#define MINIMUM_ALLOC_SIZE 8
+
+/* the number of times out_of_memory may be called
+ * any more will cause the program to abort
+ */
+
+#define MAX_TIMES_OUT_OF_MEMORY 5
+
+/* the size of the mark on each alloc'ed block of memory */
+
+#define MARK_SIZE sizeof (long)
+
+/* The default amount of data to try to read from the serial port
+ * at one time. This should not be too large, as the more time
+ * spent reading the serial port, the longer it takes to respond to
+ * user keystrokes.
+ */
+
+#define DEFAULT_MAXIMUM_ONE_TIME_SERIAL_DATA 16
+
+/* This is only used for pretty printing the command names. There
+ * is no maximum command size, but larger than this may make the
+ * output from HELP look strange.
+ */
+
+#define MAXIMUM_COMMAND_SIZE 10
+
+
+/* prototypes for user functions */
+
+#define USER_FUNCTION(fname) extern int fname (char *)
+
+/* max and min macros */
+
+#ifndef MAX
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+/* indicate whether or not a block of memory is in use */
+enum mem_in_use
+ {
+ USED, FREE
+ };
+
+/* current format for input/output */
+
+enum io_format
+ {
+ BIN, OCT, HEX, ASCII_RAW, ASCII_COOKED
+ };
+
+
+/* data structures */
+
+/* the format for a user command */
+
+struct command
+ {
+
+ /* the user-level name */
+ char *name;
+
+ /* pointer to the actual function */
+ int (*function)(char *);
+
+ /* a string describing how to do command line completion
+ * of the form
+ * option1{suboption1,suboption2{subsuboption1}},option2...
+ * special values are
+ * \f - a filename
+ * \c - a command name
+ * \m - miscellaneous (can't be completed)
+ */
+ char *tab_completion;
+
+ /* a short description of the function */
+ char *blurb_help;
+
+ /* the full help text for the function */
+ char *full_help;
+ };
+
+/* temporary data storage register */
+
+struct data_register
+ {
+
+ /* size of register (default size may be set with "set regsize ???" */
+ long size;
+
+ /* the current write position (active when the register is) */
+ long offset;
+
+ /* the data */
+ char *data;
+ };
+
+/* storage on the alloc list */
+
+struct memory_block
+ {
+
+ /* whether this chunk can be used or not */
+ enum mem_in_use in_use;
+
+ /* the actual chunk size (minus MARK_SIZE) */
+ unsigned long size;
+
+ /* the size requested ( <= size ) */
+ unsigned long size_used;
+
+ /* pointer to the memory
+ * the memory returned is actually &memory[MARK_SIZE] */
+ void *memory;
+ };
+
+
+/* global variables */
+
+/* name of the program (argv[0]) */
+
+extern char *pname;
+
+/* currently open port */
+
+extern char *port;
+
+/* the open port as returned by open() */
+
+extern int serial_port_fd;
+
+/* the number of lines per window */
+
+extern int window_height;
+
+/* the number of columns per window */
+
+extern int window_width;
+
+/* the current size of a storage register */
+
+extern int register_size;
+
+/* the actual storage registers */
+
+extern struct data_register registers[];
+
+/* jmp_buf used by out_of_memory() to recover from near-fatal errors */
+
+extern jmp_buf start_of_input_loop;
+
+/* the data entry format */
+
+extern enum io_format input_format;
+
+/* the data display format */
+
+extern enum io_format output_format;
+
+/* the windows where all of the action takes place */
+
+extern WINDOW *input_window;
+extern WINDOW *output_window;
+
+/* all of the user-level commands, their associated functions and the
+ * helper functions
+ */
+
+extern struct command commands[];
+
+/* the buffer which is used for communication with the serial port */
+
+extern char *serial_buffer;
+
+/* the current size of the buffer */
+
+extern int serial_buffer_size;
+
+
+/* functions */
+
+
+/* read a line in a manner similar to the GNU Readline library */
+
+extern char *readline (char *);
+
+/* read a character from the keyboard */
+
+extern int sgetch (void);
+
+
+/* memory management functions */
+
+/* just like malloc */
+
+extern void *xmalloc (size_t);
+
+/* just like realloc */
+
+extern void *xrealloc (void *, size_t);
+
+/* just like free */
+
+extern void xfree (void *);
+
+/* free everything allocated - called at exit */
+
+extern void free_alloc_list (void);
+
+
+/* user interface functions */
+
+/* just beep */
+
+extern void warning_beep (void);
+
+/* beep and print a message */
+
+extern void inp_error (char *);
+
+/* initialization */
+
+extern void init_console_ui (void);
+
+/* finalization */
+
+extern void destroy_console_ui (void);
+
+/* called periodically to refresh the status bar */
+
+extern void refresh_console_status_line (void);
+
+/* print and paginate a multiline string */
+
+extern void wprintstr (WINDOW *, char *);
+
+/* change the size of the windows when switching from active mode
+ * to passive mode and back
+ */
+
+extern void ui_expand_input_window(void);
+
+extern void ui_shrink_input_window(void);
+
+/* supply pagination for functions which print several functions, one
+ * line at a time
+ */
+
+extern void page_init (void);
+
+extern int page_line_printed (void);
+
+extern void page_finalize (void);
+
+
+/* utility functions */
+
+/* tokenize a string, returning the token length and the position
+ * of the next token
+ */
+
+extern char *get_token (const char *, int *, int *);
+
+/* tokenize a string and return just the token */
+
+extern char *get_token_only (const char *);
+
+/* expand a filename with a tilde in it */
+
+extern char *tilde_expand (char *);
+
+
+/* history functions */
+
+extern void read_history_from_file (char *);
+
+extern void save_history_to_file (char *);
+
+
+/* get the command to which an alias is assigned */
+
+extern char *resolve_alias (char *);
+
+
+/* functions used to write incoming serial port data */
+
+extern void write_to_output_window (int);
+
+extern void write_to_capture_register (int);
+
+extern void write_to_capture_file (int);
+
+
+/* translation functions for input and output */
+
+extern char *translate_to_bin (char *);
+
+extern char *translate_to_oct (char *);
+
+extern char *translate_to_hex (char *);
+
+extern char *translate_to_ascii_raw (char *);
+
+extern char *translate_to_ascii_cooked (char *);
+
+extern char *translate_from_bin (char *);
+
+extern char *translate_from_oct (char *);
+
+extern char *translate_from_hex (char *);
+
+extern char *translate_from_ascii_raw (char *);
+
+extern char *translate_from_ascii_cooked (char *);
+
+
+/* user level functions */
+
+/* the user functions */
+USER_FUNCTION (help);
+USER_FUNCTION (set);
+USER_FUNCTION (out);
+USER_FUNCTION (quit);
+USER_FUNCTION (capture);
+USER_FUNCTION (open_p);
+USER_FUNCTION (close_p);
+USER_FUNCTION (clear_scr);
+USER_FUNCTION (print);
+USER_FUNCTION (make_alias);
+USER_FUNCTION (unalias);
diff --git a/tap/tap.texinfo b/tap/tap.texinfo
new file mode 100755
index 0000000..820e803
--- /dev/null
+++ b/tap/tap.texinfo
@@ -0,0 +1,826 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename tap.info
+@setcontentsaftertitlepage
+@settitle Tap
+@c %**end of header
+
+
+@c information for a proper install
+@dircategory Communication Programs
+@direntry
+* Tap: (tap). A program to communicate with a serial line tap.
+@end direntry
+
+
+@c include commands and keystrokes with the regular index
+@syncodeindex fn cp
+@syncodeindex ky cp
+
+
+@ifinfo
+This file documents Tap, a program to read data from (and write data to)
+a serial port. Amongst other things, it may be used to facilitate the
+reverse engineering of serial communication protocols.
+
+Copyright @copyright{} 1999 Jonathan E duSaint @email{jon@@mbayweb.com}.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries a copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Copying'' and ``GNU General Public License'' are
+included exactly as in the original, and provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
+@end ifinfo
+
+
+@titlepage
+@title Tap 1.0
+@subtitle A program to communicate with a serial line tap.
+@author Jonathan E duSaint <jon@@mbayweb.com>
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1999 Jonathan E duSaint @email{jon@@mbayweb.com}
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Copying'' and ``GNU General Public License'' are
+included exactly as in the original, and provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
+@end titlepage
+
+
+@ifnottex
+@node Top, Introduction, , (dir)
+@comment node-name, next, previous, up
+@top Tap
+
+Tap is a program designed to read data from and write data to the serial
+port. As such it has a wide variety of applications. For example, it
+can be used to prototype serial hardware, or to read data from a serial
+line tap, which can facilitate the reverse engineering of serial line
+communication protocols.
+
+This documentation corresponds with version 1.0 of Tap.
+@end ifnottex
+
+@menu
+* Introduction:: An introduction to @code{Tap} and the manual.
+* The Command Line:: The ins and outs of the interface.
+* Command Overview:: A look at the commands.
+* Input and Output:: Communicating with the serial line.
+* The Set Command:: Setting the environment.
+
+* Index:: The command, concept, and keystroke index.
+
+@detailmenu
+--- The Detailed Node Listing ---
+* Conventions:: Document conventions.
+* Invocation:: How to start @code{Tap} and the command line options.
+* Overview:: A brief tour through @code{Tap}.
+
+* History:: How to use the history functionality.
+* Editing:: Command line editing.
+
+* C-B: Moving Left. Moving the cursor to the left.
+* Left Arrow: Moving Left.
+ Moving the cursor to the left.
+* C-F: Moving Right. Moving the cursor to the right.
+* Right Arrow: Moving Right.
+ Moving the cursor to the right.
+* C-A:: Moving the cursor to the start of the line.
+* C-E:: Moving the cursor to the end of the line.
+* C-D:: Deleting the character under the point.
+* C-H:: Deleting the character to the left of the point.
+* C-U:: Entering a numerical argument.
+* C-space: Killing and Yanking Text.
+ Setting the mark position.
+* C-K: Killing and Yanking Text.
+ Killing from the point to the end of the line.
+* C-W: Killing and Yanking Text.
+ Killing in between the mark and the point.
+* C-Y: Killing and Yanking Text.
+ Yanking text from the kill ring.
+* C-T:: Transposing characters.
+* C-L:: Clearing the screen.
+* tab:: Command line completion.
+
+* alias:: Assign a different name to a command.
+* capture:: Capture incoming data to a file or a register.
+* clear:: Clear the input window.
+* close:: Close an open serial port.
+* help:: Get help on a command.
+* open:: Open a serial port.
+* out:: Write format controlled data to the serial port.
+* print:: Print the contents of a file or a register.
+* quit:: Quit the program.
+* set:: Change the behavior of the program.
+* unalias:: Remove an alias.
+
+* Help:: The --help command line option.
+* version:: The --version command line option.
+* port:: The --port command line option.
+* save-history:: The --save-history command line option.
+@end detailmenu
+@end menu
+
+
+@node Introduction, The Command Line, Top, Top
+@comment node-name, next, previous, up
+@chapter Introduction
+
+This chapter serves as an introduction to the manual as well as to
+@code{Tap}, and documents the command line options.
+
+@menu
+* Conventions:: Document conventions.
+* Invocation:: How to start @code{Tap} and the command line options.
+* Overview:: A brief tour through @code{Tap}.
+@end menu
+
+
+@node Conventions, Invocation, Introduction, Introduction
+@comment node-name, next, previous, up
+@section Conventions
+@cindex Document, How to Read
+@cindex Explanation of the C-? Syntax
+@cindex C-? Syntax, Explanation of
+
+The syntax @dfn{C-whatever} means to press the @kbd{Control} key and to
+simultaneously press the @kbd{whatever} key. For example, @kbd{C-P}
+means to hold down the @kbd{Control} key, and then hit the @kbd{P} key.
+
+When the command definitions are presented, the command usage is put
+first. Then follows a description of the function. If there is more
+than one way to use a function, then each invocation is shown with an
+explanation after it.
+
+
+@node Invocation, Overview, Conventions, Top
+@comment node-name, next, previous, up
+@section Invocation
+@cindex Options
+@cindex Command Line Options
+@cindex Startup Options
+@cindex Invocation
+
+To start @code{Tap}, merely type @kbd{tap} at the shell prompt. If it
+is properly installed, you should be presented with the interface. If
+it isn't, then read the file @file{INSTALL} for information on how to do
+so. @code{Tap} can be invoked with several different command line
+options.
+
+@menu
+* Help:: The --help command line option.
+* version:: The --version command line option.
+* port:: The --port command line option.
+* save-history:: The --save-history command line option.
+@end menu
+
+
+@node Help, version, Invocation, Invocation
+@comment node-name, next, previous, up
+@subsection @code{--help}
+@findex --help
+@findex -h
+@cindex @code{help}, Command Line Option
+
+@code{--help}, @code{-h}
+
+Invoking @code{Tap} with this option will cause @code{Tap} to print a
+short help message to @var{stdout} and then exit.
+
+
+@node version, port, Help, Invocation
+@comment node-name, next, previous, up
+@subsection @code{--version}
+@findex --version
+@findex -v
+@cindex @code{version}, Command Line Option
+
+@code{--version}, @code{-v}
+
+Invoking @code{Tap} with this option will cause @code{Tap} to print
+version and copyright information to @var{stdout} and then exit.
+
+
+@node port, save-history, version, Invocation
+@comment node-name, next, previous, up
+@subsection @code{--port}
+@cindex Default Port
+@cindex Port, Opening on Invocation
+@findex --port
+@findex -p
+@cindex @code{port}, Command Line Option
+
+@code{--port} @file{serial port}, @code{-p} @file{serial port}
+
+With this option, @code{Tap} will open @file{serial port} at startup.
+If the serial port can't be opened, @code{Tap} will print an error
+message at startup.
+
+
+@node save-history, , port, Invocation
+@comment node-name, next, previous, up
+@subsection @code{--save-history}
+@findex --save-history
+@findex -s
+@cindex @code{save-history}, Command Line Option
+@cindex Saving History
+@cindex History, Saving
+@cindex History File
+@cindex Default History File
+
+@code{--save-history} @file{history filename}, @code{-s} @file{history filename}
+
+This option will cause @code{Tap} to read history information at startup
+from the file specified and to write history information at shutdown to
+the file. If the file specified doesn't exist, it will be created, and
+if no file is specified, the default will be used, which is usually
+@file{~/.tap_history}.
+
+
+@node Overview, , Invocation, Introduction
+@comment node-name, next, previous, up
+@section Overview
+@findex help, Command
+
+This overview assumes that @code{tap} is already properly installed on
+your system. If it isn't, read the file @file{INSTALL} for instructions.
+
+To start, invoke @code{tap} from the command line by typing @kbd{tap}.
+Once it is started, you will notice that the screen is divided into two
+parts, both with headers. The top part is called the @dfn{input window}
+and the bottom part is called the @dfn{output window}. At the bottom of
+the screen is the status bar. It should state that no serial port is
+open on one side, and suggest typing @code{help} for help.
+
+As a first experiment, try typing @code{help}. You will be presented
+with a brief summary of all of the commands available. To get more
+specific help information, type @code{help command-name}
+
+
+@node The Command Line, Command Overview, Introduction, Top
+@comment node-name, next, previous, up
+@chapter The Command Line
+@cindex Command Line Interface
+
+If you are familiar with @code{Bash} or @code{Emacs}, then you should
+already have a good grasp of most of the functionality of the command
+line interface. While @code{Tap} doesn't actually use the @code{GNU
+Readline} or the @code{GNU History} libraries, the interface was
+designed to be very similar. All commands are saved in a history list,
+although if a command is repeated one or more times, only one copy is
+saved. Also, while entering text on the command line, a variety of
+keystrokes are available for command line editing.
+
+@menu
+* History:: How to use the history functionality.
+* Editing:: Command line editing.
+@end menu
+
+@node History, Editing, The Command Line, The Command Line
+@comment node-name, next, previous, up
+@section History
+@cindex History Functionality
+@cindex History List
+@cindex History File
+@kindex C-P
+@kindex C-N
+@kindex Up Arrow
+@kindex Arrow, Up
+@kindex Down Arrow
+@kindex Arrow, Down
+
+Every time a command is entered, it is automatically inserted into the
+internal history list. However, if the command is identical to the
+previous command, a list entry is not made.
+
+To access previous entries, press either @kbd{Up Arrow}, or
+@kbd{C-P}. To access more recent entries, press either @kbd{Down
+Arrow}, or @kbd{C-N}.
+
+If a previous entry is edited and @kbd{Enter} is not pressed, the edited
+copy will be saved in the place of the original. However, once
+@kbd{Enter} is pressed, the original copy will once again be available.
+
+When @code{Tap} is invoked with the @code{--save-history}
+(@pxref{save-history}) option, all history entries are read at startup
+from the file specified, or, if one isn't specified, from the default
+file. At shutdown, the current history list is appended onto the file.
+
+If a file is specified that doesn't exist, then one will be created at
+shutdown.
+
+
+@node Editing, , History, The Command Line
+@comment node-name, next, previous, up
+@section Editing
+@cindex Command Line Editing
+@cindex Editing, Command Line
+
+@code{Tap} contains features for editing the current command line. The
+keystrokes are the same as used in @code{Emacs} and in the @code{Bash}
+shell's @code{Emacs} mode.
+
+@menu
+--- list of keystrokes ---
+* C-B: Moving Left. Moving the cursor to the left.
+* Left Arrow: Moving Left.
+ Moving the cursor to the left.
+* C-F: Moving Right. Moving the cursor to the right.
+* Right Arrow: Moving Right.
+ Moving the cursor to the right.
+* C-A:: Moving the cursor to the start of the line.
+* C-E:: Moving the cursor to the end of the line.
+* C-D:: Deleting the character under the point.
+* C-H:: Deleting the character to the left of the point.
+* C-U:: Entering a numerical argument.
+* C-space: Killing and Yanking Text.
+ Setting the mark position.
+* C-K: Killing and Yanking Text.
+ Killing from the point to the end of the line.
+* C-W: Killing and Yanking Text.
+ Killing in between the mark and the point.
+* C-Y: Killing and Yanking Text.
+ Yanking text from the kill ring.
+* C-T:: Transposing characters.
+* C-L:: Clearing the screen.
+* tab:: Command line completion.
+@end menu
+
+@node Moving Left, Moving Right, Editing, Editing
+@comment node-name, next, previous, up
+@subsection Moving Left
+@kindex C-B
+@kindex Left Arrow
+@kindex Arrow, Left
+@cindex Point Movement
+@cindex Cursor Movement
+
+@kbd{C-B}, @kbd{Left Arrow}
+
+Both of these keystrokes will move the point one character to the left,
+if possible.
+
+
+@node Moving Right, C-A, Moving Left, Editing
+@comment node-name, next, previous, up
+@subsection Moving Right
+@kindex C-F
+@kindex Right Arrow
+@kindex Arrow, Right
+@cindex Point Movement
+@cindex Cursor Movement
+
+@kbd{C-F}, @kbd{Right Arrow}
+
+Both of these keystrokes will move the point one character to the right,
+if possible.
+
+
+@node C-A, C-E, Moving Right, Editing
+@comment node-name, next, previous, up
+@subsection @kbd{C-A}
+@kindex C-A
+@cindex Cursor Movement
+@cindex Point Movement
+@cindex Start of Line, Moving the Point to
+
+@kbd{C-A}
+
+This keystroke will move the point to the start of the line.
+
+
+@node C-E, C-D, C-A, Editing
+@comment node-name, next, previous, up
+@subsection @kbd{C-E}
+@kindex C-E
+@cindex Cursor Movement
+@cindex Point Movement
+@cindex End of Line, Moving the Point to
+
+@kbd{C-E}
+
+This keystroke will move the point to the end of the line.
+
+
+@node C-D, C-H, C-E, Editing
+@comment node-name, next, previous, up
+@subsection @kbd{C-D}
+@kindex C-D
+@kindex Delete
+@cindex Deleting Characters
+
+@kbd{C-D}, @kbd{Delete}
+
+Both of these keystrokes will delete the character under the point.
+
+
+@node C-H, C-U, C-D, Editing
+@comment node-name, next, previous, up
+@subsection @kbd{C-H}
+@kindex C-H
+@kindex Backspace
+@cindex Deleting Characters
+
+@kbd{C-H}, @kbd{Backspace}
+
+Both of these keystrokes will delete the character to the left of the
+point.
+
+
+@node C-U, Killing and Yanking Text, C-H, Editing
+@comment node-name, next, previous, up
+@subsection @kbd{C-U}
+@kindex C-U
+@cindex Entering Numerical Arguments
+@cindex Numerical Arguments, Entering
+@cindex Arguments, Numerical
+@cindex Numerical Arguments
+
+@kbd{C-U}
+
+This command prompts for a number. After the number is entered, press
+@kbd{Enter}, and then the desired key. If the key entered was @kbd{C-Y}
+(@pxref{Killing and Yanking Text}), then text from the kill ring will be
+entered. If @kbd{Enter} was pressed, then it will be just as if
+@kbd{Enter} had been pressed without the argument (i.e. the command line
+will be processed). Any other key will be repeated as many times as was
+indicated by the number.
+
+For example, type
+
+@example
+@kbd{C-U} @kbd{2} @kbd{0} @kbd{Enter} @kbd{a}
+@end example
+
+@noindent
+to insert 20 copies of the letter `a', or type
+
+@example
+@kbd{C-U} @kbd{5} @kbd{Enter} @kbd{C-D}
+@end example
+
+@noindent
+to delete the character under the point and four to the right of it.
+
+
+@node Killing and Yanking Text, C-T, C-U, Editing
+@comment node-name, next, previous, up
+@subsection Killing and Yanking Text
+@kindex C-space
+@kindex C-W
+@kindex C-K
+@kindex C-Y
+@cindex Killing Text
+@cindex Yanking Text
+@cindex Kill Ring
+@cindex Copying Text
+@cindex Cutting Text
+@cindex Pasting Text
+@cindex Setting the Mark
+@cindex Mark, Setting
+
+@kbd{C-space} Set the mark.
+
+@kbd{C-W} Kill the text from the mark to the point.
+
+@kbd{C-K} Kill the text from the mark to the end of the line.
+
+@kbd{C-Y} Yank from the kill ring and insert it at the point.
+
+Tap utilizes a kill ring for storage of text which has been killed using
+the above commands. The single character delete commands will not
+store anything to the ring.
+
+The @kbd{C-Y} command will only yank the most recent entry. In order to
+yank older entries than that, it must be used in combination with the
+@kbd{C-U} command (@pxref{C-U}). For example, type
+
+@example
+@kbd{C-U} @kbd{3} @kbd{Enter} @kbd{C-Y}
+@end example
+
+@noindent
+to insert the text from the third to last kill.
+
+
+@node C-T, C-L, Killing and Yanking Text, Editing
+@comment node-name, next, previous, up
+@subsection @kbd{C-T}
+@kindex C-T
+@cindex Transposing Characters
+@cindex Characters, Transposing
+
+@kbd{C-T}
+
+This keystroke transposes the character under the point with the
+character to its left.
+
+
+@node C-L, tab, C-T, Editing
+@comment node-name, next, previous, up
+@subsection @kbd{C-L}
+@kindex C-T
+@cindex Clearing the Screen
+
+@kbd{C-L}
+
+This keystroke clears the screen and redraws the current line.
+
+@xref{clear}.
+
+
+@node tab, , C-L, Editing
+@comment node-name, next, previous, up
+@subsection @kbd{tab}
+@kindex tab
+@cindex Command Line Completion
+@cindex Completion, Command
+@cindex Command Completion
+
+@kbd{tab}
+
+Pressing the tab key will complete the token under the point, if at all
+possible. If the point is over the first token, then a command
+completion will be attempted. If it is over any other token, a
+completion will be attempted, based on the arguments that the command
+takes. If only a partial completion is possible, the token is completed
+as far as it can be, and all of the matching completions are printed
+out. If no completion is possible, the program just beeps.
+
+
+@node Command Overview, Input and Output, The Command Line, Top
+@comment node-name, next, previous, up
+@chapter Command Overview
+@cindex Commands
+@cindex Command Overview
+
+These are descriptions of all of the commands. Some commands are
+documented elsewhere, so for them, there will be only a short
+description.
+
+@menu
+* alias:: Assign a different name to a command.
+* capture:: Capture incoming data to a file or a register.
+* clear:: Clear the input window.
+* close:: Close an open serial port.
+* help:: Get help on a command.
+* open:: Open a serial port.
+* out:: Write format controlled data to the serial port.
+* print:: Print the contents of a file or a register.
+* quit:: Quit the program.
+* set:: Change the behavior of the program.
+* unalias:: Remove an alias.
+@end menu
+
+
+@node alias, capture, Command Overview, Command Overview
+@comment node-name, next, previous, up
+@section @code{alias}
+@findex alias, Command
+@cindex Aliasing Command Names
+@cindex Renaming Commands
+
+@code{alias}
+
+Invoking @code{alias} with no arguments will print out all of the
+aliases which have been assigned.
+
+@code{alias} @var{alias}
+
+The @code{alias} command with one argument will print out the alias and
+the command to which it is aliased.
+
+@code{alias} @var{alias} @var{command}
+
+With two options, @code{alias} will assign @var{alias} to @var{command}
+so that when @var{alias} is entered, the program will act as if
+@var{command} itself had been entered.
+
+This command can be very useful to decrease the amount of typing
+necessary. If, for example, the @code{out} (@pxref{out}) command were to
+be aliased to @code{o}, then rather than typing
+
+@example
+out foo bar\n
+@end example
+
+@noindent
+it would be possible to merely type
+
+@example
+o foo bar\n
+@end example
+
+@noindent
+which doesn't save that much typing, but does illustrate the point.
+
+However, @code{alias} is limited to aliasing commands only, so it is not
+possible to type something like
+
+@example
+alias bin 'set if bin'
+@end example
+
+Also see @ref{unalias}.
+
+
+@node capture, clear, alias, Command Overview
+@comment node-name, next, previous, up
+@section @code{capture}
+
+@code{capture} @option{file} @file{filename}
+
+When invoked in this manner, @code{capture} starts capturing data
+recieved from the serial port to @file{filename}. Only one file may be
+open at a time.
+
+@code{capture} @option{file} @option{off}
+
+This causes @code{Tap} to stop capturing data and to close the file.
+
+@code{capture} @option{register} @option{1--64}
+
+@code{capture}, when invoked like this, will cause @code{Tap} to start
+capturing data to a register. Data is captured until it is turned off,
+as described below, or the register is full. The size of the registers
+may be changed by using the command @code{set}.
+
+@code{capture} @option{register} @option{off}
+
+This stops the capturing to the register.
+
+
+@xref{set}, and @ref{The Set Command}.
+
+@node clear, close, capture, Command Overview
+@comment node-name, next, previous, up
+@section @code{clear}
+
+@code{clear}
+
+Invoking clear will clear the input window.
+
+@xref{C-L}.
+
+
+@node close, help, clear, Command Overview
+@comment node-name, next, previous, up
+@section @code{close}
+
+@code{close}
+
+This command closes the currently open serial port.
+
+
+@node help, open, close, Command Overview
+@comment node-name, next, previous, up
+@section @code{help}
+
+@code{help}
+
+When invoked without a command name, @code{help} prints a short
+description of every command.
+
+@code{help} @option{command name}
+
+This provides help on individual commands.
+
+
+@node open, out, help, Command Overview
+@comment node-name, next, previous, up
+@section @code{open}
+
+@code{open} @option{serial port}
+
+@code{open} opens a serial port and prepares it for communication. The
+properties of the serial port may be changed with the command
+@code{set}.
+
+@xref{set}.
+
+
+@node out, print, open, Command Overview
+@comment node-name, next, previous, up
+@section @code{out}
+
+@code{out} @option{data}
+
+The @code{out} command writes data to the serial port.
+
+@xref{Input and Output}.
+
+
+@node print, quit, out, Command Overview
+@comment node-name, next, previous, up
+@section @code{print}
+
+@code{print} @option{file}
+
+If a file is currently being captured to, this will print the contents
+of that file. If no file is open, then an error will be thrown.
+
+@code{print} @option{file} @file{filename}
+
+This prints the contents of the file specified in @file{filename}.
+
+@code{print} @option{file} @file{filename} @option{bytes}
+
+This does the same as above, but only prints the first @option{bytes}
+number of bytes.
+
+@code{print} @option{register}
+
+If a register is currently being captured to, this will print its
+contents. If one isn't being used, then an error will be thrown.
+
+@code{print} @option{register} @option{register number}
+
+This will print the contents of the register specified.
+
+@code{print} @option{register} @option{register number} @option{bytes}
+
+This will print the first @option{bytes} number of bytes of the
+specified register.
+
+
+@node quit, set, print, Command Overview
+@comment node-name, next, previous, up
+@section @code{quit}
+
+@code{quit}
+
+This command quits the program, closing any open files and the serial
+port, if one is open.
+
+
+@node set, unalias, quit, Command Overview
+@comment node-name, next, previous, up
+@section @code{set}
+
+@code{set} @option{options}
+
+The @code{set} command adjusts various run time parameters of
+@code{Tap}. @xref{The Set Command}, for a full explanation.
+
+
+@node unalias, , set, Command Overview
+@comment node-name, next, previous, up
+@section @code{unalias}
+
+@code{unalias} @option{alias}
+
+The @code{unalias} command removes the alias @option{alias} from the
+alias list.
+
+
+@node Input and Output, The Set Command, Command Overview, Top
+@comment node-name, next, previous, up
+@chapter Input and Output
+
+
+
+@node The Set Command, Index, Input and Output, Top
+@comment node-name, next, previous, up
+@chapter The Set Command
+
+Often, while working with @code{Tap}, you will find that you might want
+to change some of the operational parameters.
+
+@node Index, , The Set Command, Top
+@comment node-name, next, previous, up
+@unnumbered Command, Concept, and Keystroke Index
+
+@printindex cp
+
+@contents
+@bye
diff --git a/tap/ui.c b/tap/ui.c
new file mode 100755
index 0000000..02822ec
--- /dev/null
+++ b/tap/ui.c
@@ -0,0 +1,369 @@
+/* ui.c
+ * This is everything concerned with the visual part of Tap's
+ * user interface (almost).
+ */
+
+/* Copyright (C) 1999 Jonathan duSaint
+ *
+ * This file is part of Tap, an interactive program for reading and
+ * writing data to the serial port to facilitate the reverse
+ * engineering of communication protocols.
+ *
+ * Tap is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Tap is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License is generally kept in a file called
+ * COPYING or LICENSE. If you do not have a copy of the license, write
+ * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "tap.h"
+
+/* global variables used to determine window dimensions */
+int window_height;
+int window_width;
+
+/* used when in passive mode */
+int saved_window_height;
+
+/* the windows where all of the action takes place */
+WINDOW *input_window;
+WINDOW *output_window;
+
+/* just header/footer information */
+WINDOW *status_bar;
+WINDOW *input_header;
+WINDOW *output_header;
+
+/* this is displayed if there are an even number of lines in the terminal */
+WINDOW *title_bar = NULL;
+
+
+/* Write HOW_MUCH bytes from serial_buffer to output_window using
+ * the default format.
+ */
+void
+write_to_output_window (int how_much)
+{
+ char *inpb, *outb = NULL;
+
+ inpb = xmalloc (how_much + 1);
+
+ strncpy (inpb, serial_buffer, how_much);
+ inpb[how_much] = 0;
+
+ switch (output_format)
+ {
+ case BIN:
+ outb = translate_to_bin (inpb);
+ break;
+ case OCT:
+ outb = translate_to_oct (inpb);
+ break;
+ case HEX:
+ outb = translate_to_hex (inpb);
+ break;
+ case ASCII_RAW:
+ outb = translate_to_ascii_raw (inpb);
+ break;
+ case ASCII_COOKED:
+ outb = translate_to_ascii_cooked (inpb);
+ }
+
+ waddstr (output_window, outb);
+ wrefresh (output_window);
+
+ xfree (outb);
+ xfree (inpb);
+
+ wrefresh (input_window); /* transfer control back to input_window */
+}
+
+/* The next three functions are for displaying a series of
+ * lines with pagination.
+ */
+
+/* The number of lines which have been printed. */
+int lines_printed;
+
+/* Initialize pagination */
+void
+page_init (void)
+{
+ lines_printed = 0;
+}
+
+/* Called after a single line has been printed. Returns 0 if
+ * it is OK to keep printing lines, otherwise 1.
+ */
+int
+page_line_printed (void)
+{
+ int answer;
+
+ lines_printed++;
+
+ /* a full page has been output */
+ if (!((lines_printed + 1) % window_height))
+ {
+ waddstr (input_window, "press any key to continue, <q> to quit: ");
+ answer = sgetch ();
+ waddch (input_window, '\n');
+
+ if (answer == 'q' || answer == 'Q') return (1);
+
+ clear_scr (NULL);
+ lines_printed = 0;
+ }
+
+ return (0);
+}
+
+/* Finalize. This isn't always necessary to call. */
+void
+page_finalize (void)
+{
+ lines_printed = 0;
+}
+
+/* Print a multiline string to WINDOW with pagination. */
+void
+wprintstr (WINDOW *window, char *string)
+{
+ char *work_area;
+ int start = 0, end = 0;
+
+ work_area = xmalloc (strlen (string) + 2);
+
+ strcpy (work_area, string);
+
+ if (string[strlen (string) - 1] != '\n')
+ {
+ work_area[strlen (string)] = '\n';
+ work_area[strlen (string) + 1] = 0;
+ }
+
+ page_init ();
+
+ while (1)
+ {
+ while (work_area[end] != '\n') end++;
+
+ work_area[end] = 0;
+
+ wprintw (window, "%s\n", work_area + start);
+
+ start = ++end;
+
+ if (page_line_printed ()) break;
+ if (work_area[start] == 0) break;
+ }
+
+ page_finalize ();
+
+ xfree (work_area);
+}
+
+/* beep and print a message */
+void
+inp_error (char *msg)
+{
+ beep ();
+
+ wprintw (input_window, "?? %s\n", msg);
+ wrefresh (input_window);
+}
+
+/* just beep */
+void
+warning_beep (void)
+{
+ beep ();
+}
+
+/* This is used when going from passive mode into active mode. Changes
+ * the dimensions of input_window.
+ */
+void
+ui_expand_input_window (void)
+{
+ int pad;
+ WINDOW *twoutput, *twinput;
+
+ window_height = saved_window_height;
+ pad = 1 - (LINES % 2);
+
+ twinput = newwin (window_height, window_width, pad + 1, 0);
+
+ mvwin (output_header, window_height + pad + 1, 0);
+
+ twoutput = newwin (window_height, window_width, window_height + pad + 2, 0);
+
+ scrollok (twinput, TRUE);
+ scrollok (twoutput, TRUE);
+
+ delwin (input_window);
+ delwin (output_window);
+
+ input_window = twinput;
+ output_window = twoutput;
+
+ wrefresh (input_window);
+ wrefresh (output_header);
+ wrefresh (output_window);
+
+ return;
+}
+
+/* This is used when going from active mode into passive mode. Changes
+ * the dimensions of input_window.
+ */
+void
+ui_shrink_input_window (void)
+{
+ int pad;
+ WINDOW *twoutput, *twinput;
+
+ if (window_height - 5 < 1) return;
+
+ saved_window_height = window_height;
+ window_height = 5;
+
+ pad = 1 - (LINES % 2);
+
+ twinput = newwin (window_height, window_width, pad + 1, 0);
+
+ mvwin (output_header, window_height + pad + 1, 0);
+
+ twoutput = newwin (2 * saved_window_height - 5, window_width,
+ window_height + pad + 2, 0);
+
+ scrollok (twinput, TRUE);
+ scrollok (twoutput, TRUE);
+
+ delwin (input_window);
+ delwin (output_window);
+
+ input_window = twinput;
+ output_window = twoutput;
+
+ wrefresh (input_window);
+ wrefresh (output_header);
+ wrefresh (output_window);
+
+ return;
+}
+
+/* set up the user interface */
+void
+init_console_ui (void)
+{
+ int io_win_height, k, pad = 0;
+
+ if ((LINES < 11) || (COLS < 70))
+ {
+ fprintf (stderr, "%s: window too small to be of use\n", pname);
+ endwin ();
+ exit (1);
+ }
+
+ /* the display should look something like
+ *
+ * ----------- title bar --------------
+ * | input header |
+ * | |
+ * | input area |
+ * | |
+ * | output header |
+ * | |
+ * | output area |
+ * | |
+ * ---- status area -------------------
+ *
+ * although if there are an odd number of lines in the terminal,
+ * then there will be no title bar
+ */
+
+ io_win_height = ((LINES / 2) + ((LINES % 2) - 1)) - 1;
+
+ /* create title if space permits */
+ if (!(LINES % 2))
+ {
+ pad = 1;
+ title_bar = newwin (1, COLS, 0, 0);
+ wattron (title_bar, A_REVERSE);
+ for (k = 0; k < (COLS - 32) / 2; k++) waddch (title_bar, ' ');
+ waddstr (title_bar, "*** tap - serial line tapper ***");
+ for (k = 0; k < (COLS - 32) / 2; k++) waddch (title_bar, ' ');
+ wrefresh (title_bar);
+ }
+
+ input_header = newwin (1, COLS, pad, 0);
+ wattron (input_header, A_REVERSE);
+ waddstr (input_header, "+++ to serial port ");
+ for (k = 19; k < COLS; k++) waddch (input_header, '+');
+ wrefresh (input_header);
+
+ input_window = newwin (io_win_height, COLS, 1 + pad, 0);
+ scrollok (input_window, TRUE);
+
+ output_header = newwin (1, COLS, io_win_height + pad + 1, 0);
+ wattron (output_header, A_REVERSE);
+ waddstr (output_header, "+++ from serial port ");
+ for (k = 21; k < COLS; k++) waddch (output_header, '+');
+ wrefresh (output_header);
+
+ output_window = newwin (io_win_height, COLS, io_win_height + pad + 2, 0);
+ scrollok (output_window, TRUE);
+
+ status_bar = newwin (1, COLS, LINES - 1, 0);
+ wattron (status_bar, A_REVERSE);
+
+ window_height = io_win_height;
+ window_width = COLS;
+}
+
+/* clean up the user interface */
+void
+destroy_console_ui (void)
+{
+ delwin (input_window);
+ delwin (output_window);
+ delwin (status_bar);
+ delwin (input_header);
+ delwin (output_header);
+
+ if (title_bar != NULL) delwin (title_bar);
+}
+
+
+/* periodically refresh the status bar */
+void
+refresh_console_status_line (void)
+{
+ int k, len;
+
+ if (port == NULL)
+ {
+ waddstr (status_bar, "+++ no serial port open ");
+ len = 24;
+ }
+ else
+ {
+ len = 5 + strlen (port);
+ wprintw (status_bar, "+++ %s ", port);
+ }
+
+ for (k = 0; k < COLS - (len + 25); k++) waddch (status_bar, '+');
+ waddstr (status_bar, " type `help' for help +++");
+ wrefresh (status_bar);
+
+ wmove (status_bar, 0, 0);
+}
diff --git a/tap/version.h b/tap/version.h
new file mode 100755
index 0000000..9afb71a
--- /dev/null
+++ b/tap/version.h
@@ -0,0 +1 @@
+char version[] = "1.0pre1";
diff --git a/update/update.c b/update/update.c
new file mode 100755
index 0000000..2a27f77
--- /dev/null
+++ b/update/update.c
@@ -0,0 +1,224 @@
+/* update.c
+ * A very simplified version of make which updates the Perl programs
+ * if needed. The "makefile" used is .\update.txt unless a file has
+ * been specified on the command line. Within that file are several
+ * commands described below.
+ *
+ * FILE = <filepath\filename>
+ * Specify a source file to be updated.
+ *
+ * DEST = <filepath>
+ * Specifiy a destination path.
+ *
+ * Lines starting with # are ignored. There must be one FILE entry per
+ * file to be updated with only one file per entry. When a DEST entry
+ * is encountered, all following FILE entries are updated using the DEST
+ * entry.
+ *
+ * Copyright (C) 2002 Jonathan duSaint under the terms of the GPL.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <windows.h>
+
+#define UPDATE_FILE "update.txt"
+#define LINE_SIZE 256
+#define COMMENT_CHAR '#'
+
+#define CMD_FILE "FILE"
+#define LCMD_FILE 4
+#define CMD_DEST "DEST"
+#define LCMD_DEST 4
+
+
+void *
+xmalloc (size_t amt)
+{
+ void *mem;
+
+ mem = malloc (amt);
+
+ if (mem == NULL)
+ {
+ fprintf (stderr, "update: Unable to allocate %d bytes\n", amt);
+ exit (1);
+ }
+
+ memset (mem, 0, amt);
+
+ return (mem);
+}
+
+
+void
+update_file (char *file, char *dest)
+{
+ int pos, copy = 0;
+ char *filename, *destination;
+ FILETIME fts, ftd;
+ HANDLE hFiles, hFiled;
+ LARGE_INTEGER lis, lid;
+
+ pos = strlen (file) - 1;
+ while (file[pos] != '\\' && pos) pos--;
+ filename = xmalloc (strlen (file) - pos);
+ strcpy (filename, file + pos + 1);
+
+ destination = xmalloc (strlen (dest) + strlen (filename) + 2);
+ sprintf (destination, "%s\\%s", dest, filename);
+
+
+ hFiles = CreateFile (file, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ hFiled = CreateFile (destination, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hFiles == INVALID_HANDLE_VALUE)
+ {
+ fprintf (stderr, "update: Unable to access %s\n", file);
+ exit (1);
+ }
+ if (hFiled == INVALID_HANDLE_VALUE)
+ copy = 1;
+
+
+ if (copy);
+ else if (!GetFileTime (hFiles, NULL, NULL, &fts))
+ {
+ fprintf (stderr, "update: Unable to access %s\n", file);
+ exit (1);
+ }
+ if (copy);
+ else if (GetFileTime (hFiled, NULL, NULL, &ftd))
+ {
+ lis.u.LowPart = fts.dwLowDateTime;
+ lis.u.HighPart = fts.dwHighDateTime;
+ lid.u.LowPart = ftd.dwLowDateTime;
+ lid.u.HighPart = ftd.dwHighDateTime;
+
+ if (lis.QuadPart > lid.QuadPart) copy = 1;
+ }
+ else
+ copy = 1;
+
+ CloseHandle (hFiles);
+ CloseHandle (hFiled);
+
+ if (copy)
+ {
+ if (!CopyFile (file, destination, FALSE))
+ printf ("failed to ");
+
+ printf ("copy %s to %s\n", file, destination);
+ }
+
+ free (filename);
+ free (destination);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int pos, epos, lineno = 0;
+ char *filename, *line, *dest = NULL;
+ FILE *update;
+
+ if (argc > 1)
+ filename = argv[1];
+ else
+ filename = UPDATE_FILE;
+
+ update = fopen (filename, "rt");
+ if (update == NULL)
+ {
+ fprintf (stderr, "update: Unable to open %s\n", filename);
+ exit (1);
+ }
+
+ line = xmalloc (LINE_SIZE);
+
+ while (fgets (line, LINE_SIZE, update) != NULL)
+ {
+ lineno++;
+ if (line[0] == COMMENT_CHAR) continue;
+ if (line[0] == '\n') continue;
+
+ for (pos = 0; !isalpha (line[pos]); pos++);
+
+ if (!strncmp (line + pos, CMD_FILE, LCMD_FILE))
+ {
+ char *file;
+
+ epos = pos + LCMD_FILE;
+ while (!isspace (line[epos])) epos++;
+ while (isspace (line[epos])) epos++;
+ pos = epos;
+ epos = strlen (line);
+
+ while (isspace(line[epos - 1]))
+ {
+ if (epos <= pos)
+ {
+ fprintf (stderr, "update: invalid FILE command on line %d\n",
+ lineno);
+ exit (1);
+ }
+ epos--;
+ }
+
+ if (dest == NULL)
+ {
+ fprintf (stderr, "update: missing DEST command\n");
+ exit (1);
+ }
+
+ file = xmalloc (epos - pos + 1);
+ strncpy (file, line + pos, epos - pos);
+
+ update_file (file, dest);
+
+ free (file);
+ }
+ else if (!strncmp (line + pos, CMD_DEST, LCMD_DEST))
+ {
+ epos = pos + LCMD_FILE;
+ while (!isspace (line[epos])) epos++;
+ while (isspace (line[epos])) epos++;
+ pos = epos;
+ epos = strlen (line);
+
+ while (isspace(line[epos - 1]))
+ {
+ if (epos <= pos)
+ {
+ fprintf (stderr, "update: invalid DEST command on line %d\n",
+ lineno);
+ exit (1);
+ }
+ epos--;
+ }
+
+ if (dest != NULL) free (dest);
+ dest = xmalloc (epos - pos + 1);
+ strncpy (dest, line + pos, epos - pos);
+ }
+ else
+ {
+ epos = pos;
+ while (isalpha (line[epos])) epos++;
+ line[epos] = '\0';
+
+ fprintf (stderr, "update: unknown command '%s'\n", line + pos);
+ exit (1);
+ }
+
+ }
+
+ if (dest != NULL) free (dest);
+
+ return (0);
+}
diff --git a/update/update.exe b/update/update.exe
new file mode 100755
index 0000000..02f5fe4
--- /dev/null
+++ b/update/update.exe
Binary files differ
diff --git a/update/update.ico b/update/update.ico
new file mode 100755
index 0000000..62e36f3
--- /dev/null
+++ b/update/update.ico
Binary files differ
diff --git a/update/update.rc b/update/update.rc
new file mode 100755
index 0000000..3a73ba6
--- /dev/null
+++ b/update/update.rc
@@ -0,0 +1,3 @@
+/* update.rc */
+
+UpdateIcon ICON "update.ico"
diff --git a/uu/AUTHORS b/uu/AUTHORS
new file mode 100644
index 0000000..ad21064
--- /dev/null
+++ b/uu/AUTHORS
@@ -0,0 +1,3 @@
+Jonathan duSaint <dusaint@gmail.com>
+
+Wrote the whole thamn ding.
diff --git a/uu/COPYING b/uu/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/uu/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/uu/INSTALL b/uu/INSTALL
new file mode 100644
index 0000000..40b893a
--- /dev/null
+++ b/uu/INSTALL
@@ -0,0 +1,6 @@
+Simply type 'make' at the shell prompt. You'll have to manually copy the
+executables to a bin directory. For example:
+
+bob@furble# cp uuencode uudecode /usr/local/bin/
+
+Enjoy!
diff --git a/uu/Makefile b/uu/Makefile
new file mode 100644
index 0000000..a99fa4a
--- /dev/null
+++ b/uu/Makefile
@@ -0,0 +1,28 @@
+# Makefile for the UU utilities
+#
+# Copyright (C) 2003-2006 Jonathan duSaint <dusaint@gmail.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+CC = /usr/bin/gcc
+CFLAGS = -Wall -O2
+
+
+.PHONY : all clean
+
+all : uuencode uudecode
+
+clean :
+ rm -f uuencode uudecode *.o *~
diff --git a/uu/NEWS b/uu/NEWS
new file mode 100644
index 0000000..c69b090
--- /dev/null
+++ b/uu/NEWS
@@ -0,0 +1,3 @@
+20060210 - Jonathan duSaint
+Updated email address and copyright dates. I hadn't touched this thing
+since 2003!
diff --git a/uu/TODO b/uu/TODO
new file mode 100644
index 0000000..978e7ee
--- /dev/null
+++ b/uu/TODO
@@ -0,0 +1 @@
+Nothing!
diff --git a/uu/uu.h b/uu/uu.h
new file mode 100644
index 0000000..f8d9e93
--- /dev/null
+++ b/uu/uu.h
@@ -0,0 +1,58 @@
+/* uu.h
+ * Version/program information for uuencode and uudecode
+ *
+ * Copyright (C) 2003-2006 Jonathan duSaint <dusaint@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef UU_H
+#define UU_H
+
+#define PACKAGE "UU"
+#define AUTHOR "Jonathan duSaint"
+#define EMAIL "dusaint@gmail.com"
+
+#define DTITLE "uudecode"
+#define ETITLE "uuencode"
+#define VERSION "1.0"
+
+
+#ifndef STDOUT_DEV
+# define STDOUT_DEV "/dev/stdout"
+#endif
+#ifndef STDIN_DEV
+# define STDIN_DEV "/dev/stdin"
+#endif
+#ifndef MAX_LINE
+# define MAX_LINE 64
+#endif
+
+
+enum algorithm {
+ HISTORICAL, BASE64, NONE
+};
+
+
+/* simplify i18n later */
+#define LOCALEDIR ""
+#define _(s) (s)
+#define N_(s) s
+#define setlocale(c, l)
+#define textdomain(d)
+#define bindtextdomain(p, d)
+
+
+#endif /* UU_H */
diff --git a/uu/uudecode.c b/uu/uudecode.c
new file mode 100644
index 0000000..ec106de
--- /dev/null
+++ b/uu/uudecode.c
@@ -0,0 +1,461 @@
+/* uudecode.c
+ * UU Decode a file.
+ *
+ * Copyright (C) 2003-2006 Jonathan duSaint <dusaint@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#include "uu.h"
+
+
+#define DEFAULT_MODE 0644
+
+/* the who in a symbolic mode */
+#define M_U 1
+#define M_G 2
+#define M_O 4
+#define M_A (M_U | M_G | M_O)
+
+/* permission mask used for symbolic modes */
+#define P_S 07000
+#define P_U 00700
+#define P_G 00070
+#define P_O 00007
+#define P_A (P_U | P_G | P_O)
+
+/* permission masks */
+#define SUID 04000
+#define SGID 02000
+#define SVTX 01000
+#define RUSR 00400
+#define WUSR 00200
+#define XUSR 00100
+#define RGRP 00040
+#define WGRP 00020
+#define XGRP 00010
+#define ROTH 00004
+#define WOTH 00002
+#define XOTH 00001
+
+
+/* Call malloc and check for NULL.
+ */
+void *
+safe_alloc (size_t amt)
+{
+ void *mem;
+
+ mem = malloc (amt);
+
+ if (mem != NULL) return mem;
+
+ fprintf (stderr, _("%s: Unable to allocate %ld bytes: %s\n"), DTITLE,
+ (long int)amt, strerror (errno));
+ exit (1);
+}
+
+
+/* Compile a mode from a textual representation to mode_t. Thanks to
+ * the code in the GNU fileutils for some ideas. Sorry about all the
+ * goto's.
+ */
+mode_t
+mode_compile (char *rmode)
+{
+ int k = -1, s = 0;
+ mode_t mode;
+ unsigned int omit_mask; /* used when user is omitted */
+
+ /* check whether the mode is all digits */
+ while (rmode[++k]) if (!isdigit (rmode[k])) goto SYMBOLIC;
+
+ return (mode_t)strtoul (rmode, NULL, 8); /* all digits */
+
+
+ /* a symbolic mode doesn't make as much sense, but the spec
+ says "in chmod octal or symbolic notation", so it is thus */
+ SYMBOLIC:
+ /* get the initial mode - 0777 & ~umask */
+ mode = umask (0);
+ umask (mode);
+ mode = 0777 & ~mode;
+ omit_mask = mode | 07000;
+
+
+ /* [ugoa]*[+-=][rwxXstugo]+(,[ugoa]*[+-=][rwxXstugo]+)* */
+ while (rmode[s])
+ {
+ unsigned int who = 0, bits, pmask = 07777, omask = omit_mask;
+ int compound;
+ char how = '=';
+
+ /* find out the mode change to be */
+
+ /* who */
+ for (;; s++)
+ switch (rmode[s])
+ {
+ case 'u':
+ who |= M_U;
+ pmask &= ~P_U;
+ break;
+ case 'g':
+ who |= M_G;
+ pmask &= ~P_G;
+ break;
+ case 'o':
+ who |= M_O;
+ pmask &= ~P_O;
+ break;
+ case 'a':
+ who |= M_A;
+ pmask &= ~P_A;
+ break;
+ default:
+ if (!who)
+ {
+ /* if no one is specified, then use umask */
+ who = M_A;
+ pmask &= ~P_A;
+ }
+ else
+ omask = 07777; /* user specified, zero out omit mask */
+
+ goto find_out_how;
+ }
+
+ find_out_how:
+ bits = 0;
+ compound = 0;
+
+
+ /* how */
+ how = rmode[s++];
+
+ /* find out what */
+ for (; rmode[s]; s++)
+ switch (rmode[s])
+ {
+ case 'r':
+ if (who & M_U) bits |= RUSR;
+ if (who & M_G) bits |= RGRP;
+ if (who & M_O) bits |= ROTH;
+ break;
+ case 'w':
+ if (who & M_U) bits |= WUSR;
+ if (who & M_G) bits |= WGRP;
+ if (who & M_O) bits |= WOTH;
+ break;
+ case 'x':
+ if (who & M_U) bits |= XUSR;
+ if (who & M_G) bits |= XGRP;
+ if (who & M_O) bits |= XOTH;
+ break;
+ case 's':
+ if (who & M_U) bits |= SUID;
+ if (who & M_G) bits |= SGID;
+ if (who & M_O) /* no effect */;
+ pmask &= ~P_S;
+ break;
+ case 't':
+ if (who & M_U || who & M_G) /* no effect */;
+ if (who & M_O) bits |= SVTX;
+ pmask &= ~P_S;
+ break;
+ case 'u':
+ if (who & M_U) { bits &= ~P_U; bits |= mode & P_U; }
+ if (who & M_G) { bits &= ~P_G; bits |= (mode & P_U) >> 3; }
+ if (who & M_O) { bits &= ~P_O; bits |= (mode & P_U) >> 6; }
+ break;
+ case 'g':
+ if (who & M_U) { bits &= ~P_U; bits |= (mode & P_G) << 3; }
+ if (who & M_G) { bits &= ~P_G; bits |= mode & P_G; }
+ if (who & M_O) { bits &= ~P_O; bits |= (mode & P_G) >> 3; }
+ break;
+ case 'o':
+ if (who & M_U) { bits &= ~P_U; bits |= (mode & P_O) << 6; }
+ if (who & M_G) { bits &= ~P_G; bits |= (mode & P_O) << 3; }
+ if (who & M_O) { bits &= ~P_O; bits |= mode & P_O; }
+ break;
+ case 'X':
+ if ((mode & XUSR) | (mode & XGRP) | (mode & XOTH))
+ {
+ if (who & M_U) bits |= XUSR;
+ if (who & M_G) bits |= XGRP;
+ if (who & M_O) bits |= XOTH;
+ }
+ break;
+ case ',':
+ /* prep for next iteration */
+ s++;
+ goto do_it;
+ case '+':
+ case '-':
+ case '=':
+ /* compound symbolic mode - i.e. o+x-w */
+ compound = 1;
+ goto do_it;
+ default:
+ fprintf (stderr, _("%s: Invalid mode action '%c' in mode %s\n"),
+ DTITLE, rmode[s], rmode);
+ return DEFAULT_MODE;
+ }
+
+ /* ok we have our mode, now do the op */
+ do_it:
+ switch (how)
+ {
+ case '=': /* only affect the bits specified (ugo) */
+ mode &= pmask;
+ mode |= bits;
+ break;
+ case '+': /* or */
+ mode = mode | bits;
+ break;
+ case '-': /* a and not b */
+ mode &= ~bits;
+ break;
+ default:
+ fprintf (stderr, _("%s: Invalid mode operation '%c' in mode %s\n"),
+ DTITLE, how, rmode);
+ return DEFAULT_MODE;
+ }
+
+ mode &= omask;
+
+ /* if more than one op was specified for a given user, do it again */
+ if (compound) goto find_out_how;
+ }
+
+
+ return mode;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int arg, close_in = 0, close_out = 0;
+ char *infile, *outfile, *nom_outfile, *mode;
+ char *line;
+ FILE *in = stdin, *out;
+ enum algorithm algorithm = NONE;
+
+
+ /* start i18n */
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+
+ /* allocate buffers */
+ outfile = safe_alloc (MAX_LINE);
+ nom_outfile = safe_alloc (MAX_LINE);
+ mode = safe_alloc (MAX_LINE);
+ line = safe_alloc (MAX_LINE);
+
+ outfile[0] = '\0';
+
+
+ infile = STDIN_DEV;
+
+ /* check for args */
+ for (arg = 1; argv[arg]; arg++)
+ {
+ if (!strcmp (argv[arg], "-o"))
+ {
+ strcpy (outfile, argv[++arg]);
+ }
+ else if (!strcmp (argv[arg], "-h") || !strcmp (argv[arg], "--help"))
+ {
+ printf (_("%s\n"
+ "Decode a file which was encoded with uuencode\n"
+ "Synopsis:\n"
+ " uudecode [-h][-v][-o outfile] [file]\n"
+ "Options:\n"
+ " -o <file> Write output to <file>\n"
+ " -h Print this message\n"
+ " -v Print version information\n"),
+ DTITLE);
+ return 0;
+ }
+ else if (!strcmp (argv[arg], "-v") || !strcmp (argv[arg], "--version"))
+ {
+ printf (_("%s %s\n"
+ "Copyright (C) 2003-2006 %s <%s>\n"
+ "%s Comes with NO WARRANTY, to the extent permitted\n"
+ "by law. You may redistribute copies of %s\n"
+ "under the terms of the GNU General Public License.\n"
+ "See the file COPYING for more information.\n"),
+ DTITLE, VERSION, AUTHOR, EMAIL, DTITLE, DTITLE);
+ return 0;
+ }
+ else
+ infile = argv[arg];
+ }
+
+ /* open infile, if necessary */
+ if (strcmp (infile, STDIN_DEV))
+ {
+ close_in = 1;
+ in = fopen (infile, "r");
+ if (in == NULL)
+ {
+ fprintf (stderr, _("%s: Unable to open input file %s: %s\n"), DTITLE,
+ infile, strerror (errno));
+ exit (1);
+ }
+ }
+
+ /* loop, looking for the begin line */
+ while (fgets (line, MAX_LINE, in))
+ {
+ if (!strncmp (line, "begin ", 6))
+ {
+ algorithm = HISTORICAL;
+ if (sscanf (line, "begin %s %s", mode, nom_outfile) == 2)
+ {
+ if (!strlen (outfile)) strcpy (outfile, nom_outfile);
+ break;
+ }
+ fprintf (stderr, _("%s: Invalid begin line...\n"), DTITLE);
+ }
+ else if (!strncmp (line, "begin-base64 ", 13))
+ {
+ algorithm = BASE64;
+ if (sscanf (line, "begin-base64 %s %s", mode, nom_outfile) == 2)
+ {
+ if (!strlen (outfile)) strcpy (outfile, nom_outfile);
+ break;
+ }
+ fprintf (stderr, _("%s: Invalid begin-base64 line...\n"), DTITLE);
+ }
+ }
+
+
+ if (!strcmp (outfile, STDOUT_DEV))
+ out = stdout;
+ else
+ {
+ close_out = 1;
+ out = fopen (outfile, "wb");
+ if (out == NULL)
+ {
+ fprintf (stderr, _("%s: Unable to open output file %s: %s\n"),
+ DTITLE, outfile, strerror (errno));
+ exit (1);
+ }
+
+ /* set the file mode here */
+ if (chmod (outfile, mode_compile (mode)))
+ {
+ fprintf (stderr, _("%s: Unable to set file mode %s on %s: %s\n"),
+ DTITLE, mode, outfile, strerror (errno));
+ exit (1);
+ }
+ }
+
+ if (algorithm == HISTORICAL)
+ {
+ int k, p, length, rem;
+ unsigned char output[3];
+
+ while (fgets (line, MAX_LINE, in))
+ {
+ if (!strcmp (line, "end\n")) break;
+
+ line[strlen (line) - 1] = 0;
+
+ line[0] -= 0x20;
+ for (k = 1; k < line[0] * 4 / 3 + 1; k++) line[k] -= 0x20;
+
+ length = (line[0] + 2) / 3; /* length in blocks */
+ if (!(rem = line[0] - length * 3)) rem = 3;
+
+ /* do 1 block per loop */
+ for (p = 0; p < length; p++)
+ {
+ output[0] = (((line[4 * p + 1] << 2) & 0xfc)
+ | ((line[4 * p + 2] >> 4) & 0x3));
+ output[1] = ((((line[4 * p + 2] & 0xf) << 4) & 0xf0)
+ | ((line[4 * p + 3] >> 2) & 0xf));
+ output[2] = (((line[4 * p + 3] << 6) & 0xc0)
+ | (line[4 * p + 4] & 0x3f));
+
+ fwrite ((void *)output, sizeof (unsigned char),
+ (p == (length - 1)) ? rem : 3, out);
+ }
+ }
+ }
+ else if (algorithm == BASE64)
+ {
+ int k, p, length;
+ unsigned char output[3];
+ char reverse[] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
+ "ghijklmnopqrstuvwxyz0123456789+/"), lookup[128];
+
+ /* build the lookup table */
+ for (k = 0; k < 64; k++) lookup[(int)reverse[k]] = k;
+
+ while (fgets (line, MAX_LINE, in))
+ {
+ if (!strcmp (line, "====\n")) break;
+
+ length = (strlen (line) - 1) / 4;
+
+ for (p = 0; p < length; p++)
+ {
+ int outlen = 1;
+
+ output[0] = ((lookup[(int)line[4 * p]] << 2)
+ | (lookup[(int)line[4 * p + 1]] >> 4));
+ if (line[4 * p + 2] != '=')
+ {
+ outlen++;
+ output[1] = ((lookup[(int)line[4 * p + 1]] << 4)
+ | (lookup[(int)line[4 * p + 2]] >> 2));
+ }
+ if (line[4 * p + 3] != '=')
+ {
+ outlen++;
+ output[2] = ((lookup[(int)line[4 * p + 2]] << 6)
+ | lookup[(int)line[4 * p + 3]]);
+ }
+
+ fwrite ((void *)output, sizeof (unsigned char), outlen, out);
+ }
+ }
+ }
+
+ if (close_in) fclose (in);
+ if (close_out) fclose (out);
+
+ free (outfile);
+ free (nom_outfile);
+ free (mode);
+ free (line);
+
+ return 0;
+}
diff --git a/uu/uuencode.c b/uu/uuencode.c
new file mode 100644
index 0000000..df28d3d
--- /dev/null
+++ b/uu/uuencode.c
@@ -0,0 +1,211 @@
+/* uuencode.c
+ * UU Encode a file.
+ *
+ * Copyright (C) 2003-2006 Jonathan duSaint <dusaint@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "uu.h"
+
+
+void *
+safe_alloc (size_t amt)
+{
+ void *mem;
+
+ mem = malloc (amt);
+
+ if (mem != NULL) return mem;
+
+ fprintf (stderr, _("%s: Unable to allocate %ld bytes: %s\n"), DTITLE,
+ (long int)amt, strerror (errno));
+ exit (1);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ char *infile = NULL, *outfile = NULL, *decode = NULL;
+ unsigned int perm = 0644;
+ int arg;
+ enum algorithm algorithm = HISTORICAL;
+ struct stat sbuf;
+ FILE *in, *out;
+
+
+ /* start i18n */
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+
+ /* check for args */
+ for (arg = 1; argv[arg]; arg++)
+ {
+ if (!strcmp (argv[arg], "-m"))
+ {
+ algorithm = BASE64;
+ }
+ else if (!strcmp (argv[arg], "-h") || !strcmp (argv[arg], "--help"))
+ {
+ printf (_("%s\n"
+ "UU encode a file\n"
+ "Synopsis:\n"
+ " uuencode [-h][-v][-m] [file] decode_pathname\n"
+ "Options:\n"
+ " -m Encode using MIME Base64 algorithm\n"
+ " -h Print this message\n"
+ " -v Print version information\n"),
+ DTITLE);
+ return 0;
+ }
+ else if (!strcmp (argv[arg], "-v") || !strcmp (argv[arg], "--version"))
+ {
+ printf (_("%s %s\n"
+ "Copyright (C) 2003-2006 %s <%s>\n"
+ "%s Comes with NO WARRANTY, to the extent permitted\n"
+ "by law. You may redistribute copies of %s\n"
+ "under the terms of the GNU General Public License.\n"
+ "See the file COPYING for more information.\n"),
+ ETITLE, VERSION, AUTHOR, EMAIL, ETITLE, ETITLE);
+ return 0;
+ }
+ else
+ {
+ if (decode != NULL)
+ infile = decode;
+
+ decode = argv[arg];
+ }
+ }
+
+ if (decode == NULL)
+ {
+ fprintf (stderr, _("%s: decode_pathname not specified\n"), ETITLE);
+ exit (1);
+ }
+
+
+ if (infile != NULL)
+ {
+ if (stat (infile, &sbuf))
+ {
+ fprintf (stderr, _("%s: Unable to stat %s: %s\n"), ETITLE, infile,
+ strerror (errno));
+ exit (1);
+ }
+
+ perm = (unsigned int)sbuf.st_mode & 0xfff;
+
+ in = fopen (infile, "rb");
+ if (in == NULL)
+ {
+ fprintf (stderr, _("%s: Unable to open %s: %s\n"), ETITLE, infile,
+ strerror (errno));
+ exit (1);
+ }
+ }
+ else
+ in = stdin;
+
+ if (!strcmp (decode, "/dev/stdout")) perm = 0444;
+
+ out = stdout;
+
+
+ if (algorithm == HISTORICAL)
+ {
+ unsigned char inp[45], inc;
+ char outp[61];
+
+ memset (inp, 0, 45);
+ memset (outp, 0, 61);
+
+ fprintf (out, "begin %04o %s\n", perm, decode);
+
+ while (!feof (in))
+ {
+ int k, m, groups = 0;
+
+ inc = (unsigned char)fread (inp, 1, 45, in);
+
+ fprintf (out, "%c", inc + 0x20);
+
+ /* do the line */
+ for (k = 0, m = 0; k < inc; k += 3, m += 4)
+ {
+ outp[m] = 0x20 + ((inp[k] >> 2) & 0x3f);
+ outp[m + 1] = 0x20 + (((inp[k] << 4)
+ | ((inp[k + 1] >> 4) & 0xf)) & 0x3f);
+ outp[m + 2] = 0x20 + (((inp[k + 1] << 2)
+ | ((inp[k + 2] >> 6) & 0x3)) & 0x3f);
+ outp[m + 3] = 0x20 + (inp[k + 2] & 0x3f);
+
+ groups++;
+ }
+
+ for (k = 0; k < groups * 4; k++) if (outp[k]) fputc (outp[k], out);
+ fputc ('\n', out);
+
+ /* get ready for the next read */
+ memset (inp, 0, 45);
+ memset (outp, 0, 61);
+ }
+
+ fprintf (out, "end\n");
+ }
+ else /* BASE64 */
+ {
+ char encoder[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ unsigned char inp[3];
+ char outp[5];
+ int groups = 0, inc;
+
+ fprintf (out, "begin-base64 %04o %s\n", perm, decode);
+
+ /* do 24 bit groups */
+ for (groups = 0; (inc = (int)fread (inp, 1, 3, in)); groups++)
+ {
+ outp[0] = encoder[(inp[0] >> 2) & 0x3f];
+ outp[1] = encoder[(((inp[0] << 4)) | (inp[1] >> 4)) & 0x3f];
+ outp[2] = (inc >= 2)
+ ? encoder[((inp[1] << 2) | (inp[2] >> 6)) & 0x3f] : '=';;
+ outp[3] = (inc == 3) ? encoder[inp[2] & 0x3f] : '=';
+
+ fprintf (out, "%s%s", outp, (groups % 15) ? "" : "\n");
+ }
+
+ if (groups % 15) fprintf (out, "\n");
+ fprintf (out, "===\n");
+ }
+
+ fclose (in);
+ fclose (out);
+
+ free (outfile);
+
+ return 0;
+}
diff --git a/xalarm/AUTHORS b/xalarm/AUTHORS
new file mode 100644
index 0000000..a758b53
--- /dev/null
+++ b/xalarm/AUTHORS
@@ -0,0 +1,2 @@
+XAlarm author:
+Jonathan duSaint <jon@mbayweb.com>
diff --git a/xalarm/BUGS b/xalarm/BUGS
new file mode 100644
index 0000000..2e2c73e
--- /dev/null
+++ b/xalarm/BUGS
@@ -0,0 +1,10 @@
+XAlarm 1.0.1
+Copyright (C) 1999 Jonathan duSaint
+known bugs:
+
+Has to write \a to a terminal in order to make the beep. Eventually
+configure will be able to detect the presence of a soundcard
+or a working XBeep, and alternately use those.
+
+Display of snooze time doesn't update unless the pointer is
+moved over the Label widget.
diff --git a/xalarm/COPYING b/xalarm/COPYING
new file mode 100644
index 0000000..2ba72d5
--- /dev/null
+++ b/xalarm/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/xalarm/Makefile.in b/xalarm/Makefile.in
new file mode 100644
index 0000000..cc91ea1
--- /dev/null
+++ b/xalarm/Makefile.in
@@ -0,0 +1,32 @@
+# Makefile for xalarm
+
+SRC = xalarm.c
+EXE = xalarm
+BINDIR = /usr/X11R6/bin
+CC = gcc
+CFLAGS = -O2 -Wall
+LIBS = -lXt -lpthread @XAWLIB@
+LIBDIRS = -L/usr/X11R6/lib
+INSTALL = install
+INSTALL_FLAGS = -s -m 755
+
+CONFIG_FILES = config.cache config.log config.status
+
+.PHONY: install clean distclean all debug
+
+xalarm: $(SRC) version.h
+ $(CC) $(CFLAGS) $(LIBDIRS) $(LIBS) -o $(EXE) $(SRC)
+
+all: xalarm
+
+install:
+ $(INSTALL) $(INSTALL_FLAGS) $(EXE) $(BINDIR)
+
+clean:
+ rm -f core $(EXE)
+
+distclean:
+ rm -f Makefile $(CONFIG_FILES) core $(EXE) *~
+
+debug: $(SRC) version.h
+ $(CC) $(CFLAGS) -DDEBUG $(LIBDIRS) $(LIBS) -o $(EXE) $(SRC)
diff --git a/xalarm/NEWS b/xalarm/NEWS
new file mode 100644
index 0000000..bd9683e
--- /dev/null
+++ b/xalarm/NEWS
@@ -0,0 +1,9 @@
+XAlarm 1.0.1
+Copyright (C) 1999 Jonathan duSaint <jon@mbayweb.com>
+
+4 May 1999:
+XAlarm 1.0.0 released!
+
+3 June 1999:
+XAlarm 1.0.1 released! Fixes a few bugs and adds the --kill
+functionality.
diff --git a/xalarm/README b/xalarm/README
new file mode 100644
index 0000000..3b099ed
--- /dev/null
+++ b/xalarm/README
@@ -0,0 +1,65 @@
+XAlarm 1.0.1
+Copyright (C) 1999, Jonathan duSaint <jon@mbayweb.com>
+
+XAlarm is an X windows based "one shot" alarm. It does not contain a
+built-in clock, so it is best to use it with cron or at. When invoked,
+it pops a window up on the screen and starts beeping. If snooze is
+pressed, then it goes to sleep for 7 minutes. While asleep, the time
+left until wakeup is displayed. After it is done snoozing, the beeping
+starts again and the whole process is repeated until the off button is
+pressed.
+
+Both the snooze time and the time in between beeps can be adjusted
+with options. The '-s' option controls the snooze time, which defaults
+to 7 minutes, and the '-i' option controls the interval between beep,
+which defaults to 300 msec.
+
+The beep is made by opening a terminal (/dev/tty1 is the default) and
+writing a '\a' to it. In the works now is support for XStdBeep and
+also the use of a soundcard to generate the beep. To change which
+terminal is used, the '-o' option may be used.
+
+To use with at, do something like the following:
+
+alpha$ at '5:30am tomorrow'
+> xalarm -display :0.0 &
+> EOT (type a Control-D)
+alpha$
+
+or create a file alarm.at:
+xalarm -display :0.0 &
+
+and invoke at like
+
+alpha$ at -f alarm.at '5:30am tomorrow'
+
+For more information on invoking at, see at(1).
+
+To use with cron, create a file alarm.cron like as the following:
+# Sample cronfile
+30 05 * * 01,03,05 xalarm -display :0.0 &
+
+and invoke crontab like so:
+
+alpha$ crontab alarm.cron
+
+That file will set cron to invoke xalarm at 5:30 am every Monday,
+Wednesday, and Friday.
+
+If you already have a cronfile, then make sure and save the old one
+and merely append the above line onto it and then invoke cron.
+
+For more information about cron or crontab, see cron(8) or crontab(1).
+
+It is important to use the '-display :0.0' option, or else xalarm will
+be unable to connect with the X server when invoked from at or
+cron. When just invoking xalarm from the command line, it is not
+necessary. Remember to adjust :0.0 accordingly to your actual display.
+
+XAlarm uses the Athena widget set and the pthread library, so you need
+to have a working X installation and a working pthread library for it
+to work.
+
+It is hoped that this program will be useful to the world at
+large. Please email me with any problems, suggestions, etc at
+jon@mbayweb.com
diff --git a/xalarm/TODO b/xalarm/TODO
new file mode 100644
index 0000000..51e13f3
--- /dev/null
+++ b/xalarm/TODO
@@ -0,0 +1,4 @@
+XAlarm 1.0.1
+
+Make XStdBeep work and add soundcard support.
+Somehow get the text widget to update without moving the mouse over it.
diff --git a/xalarm/configure.in b/xalarm/configure.in
new file mode 100644
index 0000000..c397600
--- /dev/null
+++ b/xalarm/configure.in
@@ -0,0 +1,36 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(xalarm.c)
+
+dnl Check for programs.
+AC_PROG_CC
+
+dnl Check for libraries.
+OLDLIBS=${LIBS}
+AC_CHECK_LIB(Xaw, XawFormDoLayout,, \
+ echo -e '\a!! need libXaw to work !!'; exit -1, \
+ -L/usr/X11R6/lib)
+AC_CHECK_LIB(Xt, XtMainLoop,, \
+ echo -e '\a!! need libXt to work !!'; exit -1, \
+ -L/usr/X11R6/lib)
+LIBS=${OLDLIBS}
+
+dnl Check for Xaw3d (use instead of Xaw if present)
+AC_CHECK_LIB(Xaw3d, XawFormDoLayout, \
+ XAWLIB=-lXaw3d, XAWLIB=-lXaw, \
+ -L/usr/X11R6/lib)
+AC_SUBST(XAWLIB)
+LIBS=${OLDLIBS}
+
+dnl POSIX library
+AC_CHECK_LIB(pthread, pthread_create,, \
+ echo -e '\a!! need libpthread to work !!'; exit -1)
+LIBS=${OLDLIBS}
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h unistd.h)
+
+dnl Check for library functions.
+AC_CHECK_FUNCS(strtol)
+
+AC_OUTPUT(Makefile)
diff --git a/xalarm/version.h b/xalarm/version.h
new file mode 100644
index 0000000..0414a78
--- /dev/null
+++ b/xalarm/version.h
@@ -0,0 +1 @@
+char version[] = "1.0.1";
diff --git a/xalarm/xalarm.c b/xalarm/xalarm.c
new file mode 100644
index 0000000..c97452f
--- /dev/null
+++ b/xalarm/xalarm.c
@@ -0,0 +1,486 @@
+/* xalarm an X based alarm
+ * Makes an annoying beep (over and over again).
+ * Best used with cron or at.
+ *
+ * Copyright (C) 1999, Jonathan duSaint <jon@mbayweb.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <time.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Command.h>
+
+/* none of this is implemented yet */
+#ifdef XKBBELL_BEEP
+# include <X11/XKBlib.h>
+# include <X11/extensions/XKBbells.h>
+#elif defined SOUNDCARD_BEEP
+# include <linux/sound.h>
+# include <linux/soundcard.h>
+#else
+# define TERM_BEEP
+#endif /* (XKBBELL|SOUNDCARD|TERM)_BEEP */
+
+#include "version.h"
+
+#ifdef DEBUG
+# define SEC_PER_MINUTE 1
+#else
+# define SEC_PER_MINUTE 60
+#endif
+
+#ifdef TERM_BEEP
+# define DEFAULT_SOUND_DEVICE "/dev/tty"
+#endif
+
+#define XALARM_PID_FILE "/tmp/.current-xalarm-pid"
+
+typedef volatile int flag_t;
+#define STOP ((flag_t) 0)
+#define GO ((flag_t) 1)
+
+struct beep_thread_data {
+ long msec_delay;
+ long snooze_time;
+ flag_t keep_going;
+ pthread_t threads[2];
+ Widget widget[2];
+};
+
+#define THREAD_DATA_INITIALIZER { 300, 7, GO, \
+ { (pthread_t) -1, (pthread_t) -1}, \
+ { (Widget) 0, (Widget) 0} }
+
+#define beep_thread threads[0]
+#define snooze_thread threads[1]
+#define top widget[0]
+#define text_box widget[1]
+
+/* global variables */
+char *pname; /* the name of the program (argv[0]) */
+flag_t *stop_or_go; /* points at thread_data.keep_going */
+
+void
+print_help(void) {
+ fprintf(stdout,
+ "usage: xalarm [-o] [-h] [-v] [-i val] [-s val]\n"
+ "-i --interval <val>\n"
+ "\tset the delay between beeps to val msec\n"
+ "-s --snooze <val>\n"
+ "\tset the snooze delay to val minutes\n"
+ "-o --output-device <name>"
+ "\tset the output device to name. Must be of the form\n"
+ "\t/dev/ttyXX. Defaults to /dev/tty1\n"
+ "-k --kill\n"
+ "\tkills an already running xalarm\n"
+ "-h --help\n"
+ "\tprint this message and exit\n"
+ "-v --version\n"
+ "\tdisplay the version and exit\n"
+ "Also accepts standard X toolkit arguments.\n"
+ "Report bugs to jon@mbayweb.com, but first check\n"
+ "the file BUGS.\n");
+ exit(0);
+}
+
+void
+print_version(void) {
+ fprintf(stdout,
+ "XAlarm %s\n"
+ "Copyright (C) 1999 Jonathan duSaint\n"
+ "XAlarm comes with ABSOLUTELY NO WARRANTY.\n"
+ "For information about copying and redistribution, "
+ "see the file COPYING.\n",
+ version);
+ exit(0);
+}
+
+/* what to do when SIGUSR1 is recieved i.e.
+ * when another xalarm is invoked with --kill --
+ * pretty ugly way to do it
+ */
+void
+remotely_killed(int sig) {
+ *stop_or_go = STOP;
+ usleep(50000); /* give some time for the thread to terminate */
+ exit(0);
+}
+
+enum sound_function {
+ INIT_SOUND, OPEN_DEVICE, CLOSE_DEVICE, TEST_DEVICE, MAKE_BEEP
+};
+
+/* sound functions */
+#define init_sound_device(device) sound_function(INIT_SOUND, (device))
+#define open_sound_device() sound_function(OPEN_DEVICE, NULL)
+#define close_sound_device() sound_function(CLOSE_DEVICE, NULL)
+#define test_sound_device() sound_function(TEST_DEVICE, NULL)
+#define make_beep() sound_function(MAKE_BEEP, NULL)
+
+/* The reason for putting all of the sound functions into
+ * one big function is to eliminate both global variables
+ * and crazy parameter passing (i.e. there is no reason to
+ * have to pass the file handle to every function every
+ * time and the only other way to eliminate it is through
+ * global variables).
+ */
+static int
+sound_function(enum sound_function flag, void *data) {
+ static int sound_device;
+ static char *sound_device_name;
+ char beep = '\a';
+
+ switch (flag) {
+ case INIT_SOUND:
+ sound_device_name = (char *)data;
+ break;
+ case OPEN_DEVICE:
+ sound_device = open(sound_device_name, O_WRONLY);
+ break;
+ case CLOSE_DEVICE:
+ close(sound_device);
+ break;
+ case TEST_DEVICE:
+ open_sound_device();
+ if (sound_device != -1)
+ close_sound_device();
+ return (sound_device);
+ case MAKE_BEEP:
+ write(sound_device, &beep, 1);
+ break;
+ }
+
+ return (0);
+}
+
+/* routines for atexit() */
+void
+close_sound_device_at_exit(void) {
+ close_sound_device();
+}
+
+void
+remove_pid_file(void) {
+ unlink(XALARM_PID_FILE);
+}
+
+/* This is what does the beeping */
+void *
+irritating_beeper_thread(void *args) {
+ struct timespec how_long;
+ struct beep_thread_data *my_data = (struct beep_thread_data *) args;
+
+ how_long.tv_sec = 0;
+ how_long.tv_nsec = my_data->msec_delay * 1000000L;
+
+ while (my_data->keep_going) {
+ make_beep();
+ nanosleep(&how_long, NULL);
+ }
+
+ return (void *) 0;
+}
+
+void *
+snoozer_thread(void *args) {
+ static int sleeping = 0;
+ static char *txt = NULL;
+ Arg text;
+ struct timespec one_second;
+ struct beep_thread_data *my_data = (struct beep_thread_data *) args;
+ long time_left = my_data->snooze_time;
+
+ if (sleeping == 1) return ((void *)0);
+ sleeping = 1;
+
+ text.name = XtNlabel;
+ one_second.tv_nsec = 0;
+ one_second.tv_sec = 1;
+
+ /* the string being allocated here is "xx:xx left to snooze" */
+ if (txt == NULL) {
+ txt = malloc(21*sizeof(char));
+ txt[20] = 0;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "%s: pausing for %ld seconds...\n", pname, time_left);
+#endif
+
+ while (--time_left) {
+ sprintf(txt, "%02ld:%02ld left to snooze", time_left / 60, time_left % 60);
+ text.value = (XtArgVal)txt;
+
+#ifdef DEBUG
+ fprintf(stderr, "%s\n", txt);
+#endif
+
+ XtSetValues(my_data->text_box, &text, 1);
+ /* have to throw some sort of callback here to refresh the widget */
+ nanosleep(&one_second, NULL);
+
+ if (!my_data->keep_going) {
+ free (txt);
+ pthread_exit((void *) 0);
+ }
+ }
+
+ /* all done sleeping... */
+ sleeping = 0;
+ pthread_create(&my_data->beep_thread, NULL,
+ irritating_beeper_thread, (void *) args);
+
+ return (void *) 0;
+}
+
+/* this function kills the beeper thread and starts the snoozer thread */
+void
+hit_snooze(Widget w, XtPointer client_data, XtPointer call_data) {
+ struct beep_thread_data *my_data = (struct beep_thread_data *)client_data;
+
+ my_data->keep_going = 0;
+ pthread_join(my_data->beep_thread, NULL);
+
+ my_data->keep_going = 1;
+ pthread_create(&my_data->snooze_thread, NULL,
+ snoozer_thread, (void *)client_data);
+}
+
+/* time to wake up */
+void
+kill_alarm(Widget w, XtPointer client_data, XtPointer call_data) {
+ struct beep_thread_data *my_data = (struct beep_thread_data *)client_data;
+
+ my_data->keep_going = 0;
+
+#ifdef DEBUG
+ fprintf(stderr, "%s: waiting for beep thread to terminate\n", pname);
+#endif
+
+ pthread_join(my_data->beep_thread, NULL);
+ pthread_join(my_data->snooze_thread, NULL);
+
+ exit(0);
+}
+
+void
+set_up_ui(void *data) {
+ struct beep_thread_data *my_data = (struct beep_thread_data *) data;
+ Widget window, snooze, stop;
+ XtCallbackRec stop_callback[] = {
+ {kill_alarm, (XtPointer)data},
+ {NULL, NULL}
+ };
+ XtCallbackRec snooze_callback[] = {
+ {hit_snooze, (XtPointer)data},
+ {NULL, NULL}
+ };
+ Arg window_args[] = {
+ {XtNresizable, True},
+ {XtNwidth, (XtArgVal)150},
+ {XtNheight, (XtArgVal)200}
+ };
+ Arg text_args[] = {
+ {XtNwidth, (XtArgVal)140},
+ {XtNheight, (XtArgVal)40},
+ };
+ Arg snooze_args[] = {
+ {NULL, 0},
+ {XtNwidth, (XtArgVal)140},
+ {XtNheight, (XtArgVal)70},
+ {XtNcallback, (XtArgVal)snooze_callback}
+ };
+ Arg stop_args[] = {
+ {NULL, 0},
+ {XtNwidth, (XtArgVal)140},
+ {XtNheight, (XtArgVal)70},
+ {XtNcallback, (XtArgVal)stop_callback}
+ };
+
+ /* create window */
+ window = XtCreateManagedWidget("window", formWidgetClass,
+ my_data->top, window_args,
+ XtNumber(window_args));
+ XtRealizeWidget(my_data->top);
+ XtRealizeWidget(window);
+
+ /* create label */
+ my_data->text_box = XtCreateManagedWidget("Wake Up time!!",
+ labelWidgetClass, window,
+ text_args, XtNumber(text_args));
+
+ /* create snooze button */
+ XtSetArg(snooze_args[0], XtNfromVert, my_data->text_box);
+ snooze = XtCreateManagedWidget("snooze", commandWidgetClass,
+ window, snooze_args, XtNumber(snooze_args));
+
+ /* create off button */
+ XtSetArg(stop_args[0], XtNfromVert, snooze);
+ stop = XtCreateManagedWidget("stop", commandWidgetClass,
+ window, stop_args, XtNumber(stop_args));
+
+ XtRealizeWidget(snooze);
+ XtRealizeWidget(stop);
+}
+
+void
+kill_xalarm(void) {
+ FILE *fid;
+ int pid;
+
+ fid = fopen(XALARM_PID_FILE, "r");
+ if (fid == NULL) {
+ fprintf(stderr, "xalarm: unable to find remote xalarm\n");
+ exit (1);
+ }
+
+ fscanf(fid, "%d", &pid);
+ fclose(fid);
+
+ if (kill(pid, SIGUSR1)) {
+ fprintf(stderr, "xalarm: unable to signal remote xalarm: %s\n",
+ strerror(errno));
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ XtAppContext app_con;
+ int index = 0, opt;
+ char *sound_device_name;
+ FILE *fid;
+ struct beep_thread_data thread_data = THREAD_DATA_INITIALIZER;
+ struct option options[] = {
+ {"interval", 1, NULL, 'i'},
+ {"snooze", 1, NULL, 's'},
+ {"output-device", 1, NULL, 'o'},
+ {"kill", 0, NULL, 'k'},
+ {"help", 0, NULL, 'h'},
+ {"version", 0, NULL, 'v'},
+ {0, 0, 0, 0}
+ };
+
+ pname = argv[0];
+ sound_device_name = DEFAULT_SOUND_DEVICE;
+
+ /* parse through remaining args */
+ while (1) {
+ opt = getopt_long(argc, argv, "i:s:o:khv", options, &index);
+
+ if (opt == EOF) break;
+
+ switch (opt) {
+ case 'i': /* set beep interval */
+ thread_data.msec_delay = strtol(optarg, NULL, 0);
+ if (thread_data.msec_delay > 1000 || thread_data.msec_delay < 1) {
+ fprintf(stderr, "%s: invalid value for %s: `%s'\n",
+ pname, argv[optind-2], optarg);
+ thread_data.msec_delay = 300;
+ }
+ break;
+ case 's': /* duration for snooze timer */
+ thread_data.snooze_time = strtol(optarg, NULL, 0);
+ if (thread_data.snooze_time < 1 || thread_data.snooze_time > 60) {
+ fprintf(stderr, "%s: invalid value for %s: `%s'\n",
+ pname, argv[optind-2], optarg);
+ thread_data.snooze_time = 7;
+ }
+ break;
+ case 'o': /* from where to output the beep */
+ sound_device_name = optarg;
+ break;
+ case 'k': /* kill an already running alarm */
+ kill_xalarm();
+ return (0);
+ break;
+ case 'h':
+ print_help();
+ case 'v':
+ print_version();
+ case '?':
+ break;
+ default:
+ fprintf(stderr, "%s: ?? getopt returned character code 0x%x ??\n",
+ pname, opt);
+ }
+ }
+
+ /* handle SIGUSR1 */
+ signal(SIGUSR1, remotely_killed);
+
+ /* finalize signal handler setup */
+ stop_or_go = &thread_data.keep_going;
+
+ /* store pid in an easy to access location */
+ fid = fopen(XALARM_PID_FILE, "w");
+ if (fid != NULL) {
+ fprintf(fid, "%d\n", getpid());
+ fclose(fid);
+
+ atexit(remove_pid_file);
+ }
+
+ /* start the X part */
+ XtSetLanguageProc(NULL, NULL, NULL);
+ thread_data.top = XtAppInitialize(&app_con, "XAlarmBeep", NULL, 0,
+ &argc, argv, NULL, NULL, 0);
+
+#ifdef DEBUG
+ fprintf(stderr, "%s: parameters:\ndelay: %ld\ninterval: %ld\noutput: %s\n",
+ pname, thread_data.msec_delay, thread_data.snooze_time,
+ sound_device_name);
+#endif
+
+ thread_data.snooze_time *= SEC_PER_MINUTE;
+
+ set_up_ui((void *)&thread_data);
+
+ /* Even if small errors occur, it is still important
+ * that the alarm should continue: small errors are
+ * merely reported and the program continues despite
+ * them as best as possible
+ */
+
+ init_sound_device(sound_device_name);
+ if (test_sound_device() == -1) {
+ init_sound_device(DEFAULT_SOUND_DEVICE); /* reinitialize */
+ fprintf(stderr, "%s: unable to open %s for writing\n",
+ pname, sound_device_name);
+ }
+ open_sound_device();
+
+ atexit(close_sound_device_at_exit);
+ pthread_create(&thread_data.beep_thread, NULL,
+ &irritating_beeper_thread, (void *) &thread_data);
+
+ XtAppMainLoop(app_con);
+
+ return(0);
+}
diff --git a/xkill/xkill.c b/xkill/xkill.c
new file mode 100644
index 0000000..1ef0527
--- /dev/null
+++ b/xkill/xkill.c
@@ -0,0 +1,88 @@
+/* xkill.c
+ * Misnamed program which will kill whatever window is clicked on.
+ */
+
+#include <windows.h>
+
+HWND me, target;
+
+LRESULT CALLBACK
+MainWindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ POINT pt;
+ WINDOWPLACEMENT wp;
+
+ switch (uMsg)
+ {
+ case WM_CREATE:
+ SetCapture (me);
+ break;
+ case WM_NCPAINT:
+ case WM_NCACTIVATE: /* prevent painting of nonclient areas */
+ return TRUE;
+ case WM_LBUTTONDOWN:
+ pt.x = LOWORD (lParam);
+ pt.y = HIWORD (lParam);
+
+ wp.length = sizeof (WINDOWPLACEMENT);
+ wp.flags = 0;
+ wp.showCmd = SW_MINIMIZE;
+ SetWindowPlacement (me, &wp);
+
+ target = WindowFromPoint (pt);
+ if (target == NULL) target = GetDesktopWindow ();
+ SendMessage (target, WM_CLOSE, 0, 0);
+ SendMessage (target, WM_DESTROY, 0, 0);
+ SendMessage (target, WM_QUIT, 0, 0);
+
+ wp.length = sizeof (WINDOWPLACEMENT);
+ wp.flags = 0;
+ wp.showCmd = SW_MAXIMIZE;
+ SetWindowPlacement (me, &wp);
+
+ break;
+ case WM_RBUTTONUP:
+ PostQuitMessage (0);
+ break;
+ case WM_DESTROY:
+ PostQuitMessage (0);
+ break;
+ default:
+ return DefWindowProc (hWnd, uMsg, wParam, lParam);
+ }
+
+ return 0;
+}
+
+int WINAPI
+WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
+{
+ WNDCLASS wc;
+ MSG msg;
+
+ ZeroMemory (&wc, sizeof (WNDCLASS));
+ wc.lpfnWndProc = MainWindowProc;
+ wc.hInstance = hInst;
+ wc.hIcon = LoadIcon (hInst, "xkill_icon");
+ wc.hCursor = LoadCursor (hInst, "xkill_cursor");
+ wc.lpszClassName = "XKILL";
+
+ RegisterClass (&wc);
+
+ me = CreateWindowEx (WS_EX_TRANSPARENT, "XKILL", "XKill", 0,
+ 0, -GetSystemMetrics (SM_CYCAPTION),
+ GetSystemMetrics (SM_CXSCREEN),
+ GetSystemMetrics (SM_CYSCREEN)
+ + GetSystemMetrics (SM_CYCAPTION),
+ NULL, NULL, hInst, NULL);
+
+ ShowWindow (me, nCmdShow);
+
+ while (GetMessage (&msg, NULL, 0, 0))
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+
+ return (int)msg.wParam;
+}
diff --git a/xkill/xkill.exe b/xkill/xkill.exe
new file mode 100755
index 0000000..8181a26
--- /dev/null
+++ b/xkill/xkill.exe
Binary files differ
diff --git a/xkill/xkill.ico b/xkill/xkill.ico
new file mode 100644
index 0000000..4264318
--- /dev/null
+++ b/xkill/xkill.ico
Binary files differ