#!/usr/bin/perl -I/usr/lib/aladin
#
# Aladin -> PC data transfer tool for Linux/FreeBSD
#    Copyright (C) 1999,2000  kuro@neko.ac
#
#    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.
#
# Edition History:
#    Created 99/10/05 Distribution version 1.0 by kuro@neko.ac
#            99/10/09              Version 1.1 by kuro@neko.ac
#                     # modified:  check sum and end of profile data
#            99/10/13              Version 1.2 by kuro@neko.ac
#                     # modified:  sysread instead of read from Aladin
#            99/10/17              Version 1.3 by kuro@neko.ac
#                     # modified:  plot warning info below profile graph
#            99/11/30              Version 1.4 by kuro@neko.ac
#                     # modified:  lpr bug corrected
#            99/12/08              Version 1.5 by kuro@neko.ac
#                     # modified:  safe rm implemented
#            99/12/12              Version 1.6 by kuro@neko.ac
#                     # modified:  many typos corrected
#            99/12/18              Version 1.7 by kuro@neko.ac
#                     # modified:  bug of logbook disp. etc. corrected
#            00/01/10              Version 1.8 by kuro@neko.ac
#                     # modified:  bottom time: figure of hundreds fixed
#            00/01/12              Version 1.9 by kuro@neko.ac
#                     # modified:  put for datatrak thru dosemu impremented
#            00/01/20              Version 1.10 by kuro@neko.ac
#                     # modified:  autodetect Nitrox. several bug fix.
#            00/01/23              Version 1.11 by kuro@neko.ac
#                     # modified:  get bug removed.
#            00/02/06              Version 1.12 by kuro@neko.ac
#                     # modified:  filename naming scheme changed.
#            00/02/16              Version 1.13 by kuro@neko.ac
#                     # modified:  plot graph bug!!
#            00/02/29              Version 1.14 by kuro@neko.ac
#                     # modified:  Air comsumption changed for Aladin Air.
#            00/03/01              Version 1.15 by kuro@neko.ac
#                     # modified:  Bug on profile display for O2 corrected.
#            00/03/21              Version 1.16 by kuro@neko.ac
#                     # modified:  Msb of $PROFILEEND is garbage!
#            00/06/09              Version 1.17 by kuro@neko.ac
#                     # modified:  Last two received byte from Aladin are fake.
#                     #            Only serial ID is checked to identify
#                     #            each Aladin.
#            00/09/29              Version 1.18 by kuro@neko.ac
#                     # modified:  Plotting graph for O2 divecomputer
#                     #            has a wrong assumption on end of datum.
#            00/10/27              Version 1.19 by kuro@neko.ac
#                     # modified:  Bug in baudrate setting when output
#                     #            to $DOSEmuSerial is corrected.

##########################
# configurable parameters
#
$GnuPlotTmp     = "/tmp/gnuplottmp$$";
$GnuPlotPs      = "/tmp/gnuplotps$$";
$PagerTmp       = "/tmp/pager$$";
$PrintPsCommand = "system \"cp \$GnuPlotPs ../ps/\$DIVE\"";
$Pager          = "pager";
$DiveNoOffset   = 0;
$Device         = "/usr/lib/aladin/device";
$DataDir        = "~/datadir";
$Info           = ".info";
$BuggyPro       = 0;
#$DOSEmuSerial   = "/dev/dosemuserial";
$DOSEmuSerial   = "/dev/pilot";
#$DOSEmuSerial   = "/dev/ttyzf";
##########################

if ($ARGV[0]) {
    eval `cat $ARGV[0]`;
} elsif (-f "$ENV{HOME}/.aladinrc") {
    eval `cat $ENV{HOME}/.aladinrc`;
} elsif (-f "/etc/aladinrc") {
    eval `cat /etc/aladinrc`
} else {
    print STDERR "Warning: Can't find configuration file.\n";
}

$DataDir =~ s{^~([^/]*)}{$1?(getpwnam($1))[7]:$ENV{HOME}}ex;
if (! -d $DataDir) {
    mkdir $DataDir, oct('0755') || die "Can't make datadir\n";
}
chdir $DataDir || die "Can't cd to datadir\n";

$Nitrox         = 0;
$NormalAir      = 0;
$TIMECORR = 0;
if (-f $Info) {
    open(INFO, "<$Info");
    read(INFO, $MACHINEID, 52);  # specific values for an Aladin
    $u = substr($MACHINEID, 0, 1);
    $u = unpack('C', $u);
    if ($u == 0xa4) {
        $Nitrox = 3;
    }
    if ($u == 0xf4 || $u == 0xff) {
        $Nitrox = 2;
    }
    if ($u == 0x1c) {
        $NormalAir = 1;
    }
    read(INFO, $b, 4);
    $t = unpack('N', $b) >> 1;
    read(INFO, $b, 4);
    $u = unpack('N', $b);
    $TIMECORR = $u - $t;
    close(INFO);
}

$NEXT = "";
while (1) {
    print STDERR "> ";
    if (! ($_ = <STDIN>)) {
        exit(0);
    }
    /^\s*(.*?)\s*$/;
    $_ = $1;
    if (/^plot\s+([0-9]+)$/) {
        $PrintPs = 0;
        plotgraph($1);
        next;
    } elsif (/^lpr\s+([0-9]+)$/) {
        $PrintPs = 1;
        plotgraph($1);
        next;
    } elsif (/^get$/) {
        receive();
    } elsif (/^([0-9]+)$/) {
        logdata($1);
        next;
    } elsif (/^dump\s+(.+?)$/) {
        readwithpager($1);
    } elsif (/^ls$/) {
        listdir();
    } elsif (/^rm\s+(.+?)$/) {
        remove($1);
    } elsif (/^put\s+(.+?)$/) {
        dosemusend($1);
    } elsif (/^help$/) {
        help();
    } elsif (/^quit$/ or /^exit$/ or /^bye$/) {
        exit(0);
    } elsif (/^$/) {
        if ($NEXT) {
            if ($LOG == 0) {
                plotgraph($NEXT);
            } else {
                logdata($NEXT);
            }
            next;
        }
    } else {
        print STDERR "Illegal command. Type \"help\" to see usage.\n"; 
    }
    $NEXT = "";
}

sub help {
    print STDERR "plot <num>     Display a depth graph of No. <num> dive.\n";
    print STDERR "lpr <num>      Print out a depth graph to PS Printer.\n";
    print STDERR "get            Receive data from Aladin.\n";
    print STDERR "<num>          Logbook for No. <num> dive.\n";
    print STDERR "dump <file>    Show all the contents of <file> (for debug).\n";
    print STDERR "ls             List file names.\n";
    print STDERR "rm <file>      Remove <file>.\n";
    print STDERR "put <file>     Send <file> to DataTrak running under dosemu.  (for debug)\n";
    print STDERR "help           Print this usage.\n";
    print STDERR "quit           Exit the program.\n";
}

sub max {
    return ($_[0] > $_[1]) ? $_[0] : $_[1];
}

sub listdir {
    open(LS, "ls -1 -a |");
    @ls = <LS>;
    close(LS);
    @contents = ();
    foreach (@ls) {
        chop;
        $file = $_;
        if (/^\.{1,2}$/) {
            next;
        }
        if ($file eq $Info) {
            $line = sprintf "0     %-26s", "(information file)";
            open(INFO, "<$Info");
            seek(INFO, 56, 0);
            read(INFO, $b, 4);
            close(INFO);
            $line .= mylocaltime(unpack('N', $b)) . "  $Info\n";
            push(@contents, $line);
            next;
        } 
        if (-s $file != 2048) {
            next;
        }
        analyze0($file);
        $end = $TOTALDIVES;
        $logbegin = max($end - 36, 1);
        $end += $DiveNoOffset;
        $logbegin += $DiveNoOffset;
        $profilebegin = $end - $PROFILES + 1;
        $slogbegin = sprintf "%d", $logbegin;
        $send = sprintf "%d", $end;
        $sprofilebegin = sprintf "%d", $profilebegin;
        $line = sprintf "%5d ", $TOTALDIVES;
        $line .= sprintf "%-11s ", $slogbegin . ' - ' . $send;
        if ($PROFILES == 0) {
            $line .= "no profiles";
        } else {
            $line .= sprintf "%-11s   ", $sprofilebegin . ' - ' . $send;
        }
        $line .= "$RECVTIME  $file\n";
        push(@contents, $line);
    }
    @contents = sort numerically @contents;
    open PAGERTMP, ">$PagerTmp";
    print PAGERTMP "LOGS        PROFILES      UPDATE TIME        FILENAME\n";
    foreach (@contents) {
        print PAGERTMP substr $_, 6;
    }
    close(PAGERTMP);
    if (fork) {
        # parent here.
        wait();
    } else {
        # child here.
        exec "$Pager $PagerTmp";
    }
    unlink $PagerTmp;
}

sub plotgraph {
    sub makedata {
        open(IN, "<$_[0]");
        read(IN, $buf, 2048);
        close(IN);
        @buf = unpack('C2048', $buf);
        open(TMP1, ">$GnuPlotTmp");
        select TMP1;
        if ($PrintPs) {
            print "set terminal postscript\n";
            print "set output \"$GnuPlotPs\"\n";
        }
        print "set nokey\n";
        print "set multiplot\n";
        print "set size 1,0.85\n";
        print "set origin 0,0.15\n";
        print "set title \"Dive No.$_[1]\"\n";
        print "set grid y x2\n";
        print "set noxtics\n";
        print "set x2tics nomirror 0,5,240\n";
        print "set format x2 \"\"\n";      
        print "set ytics -100,5,0\n";
        print "set format y \"%4.0f\"\n";
        print "set bmargin 0\n";
        print "plot '-' with lines\n";
    
        $i = $PROFILEEND + 1; $i %= 0x600;
        for ($j = 0; $j < $_[1]-$DiveNoOffset-$TOTALDIVES+$PROFILES; $j++) {
            while($buf[$i++] != 0xff) {
                $i %= 0x600;
            }
        }
        $startaddr = $i;
        $i += 22 + $Nitrox;             # skip decompression info (22 bytes)
        $i %= 0x600;
        $base = $i;
        print "0 0\n";
        for ($j = 1; ; $j++) {
            # there are 3 data a minute.
            last if ($i == ($PROFILEEND +1)%0x600 || $i == $PROFILEEND);
            $u = $buf[$i++]; $i %= 0x600;
            last if ($u == 0xff);
            $u = $u * 256 + $buf[$i++]; $i %= 0x600;
            printf "%f %f\n", $j/3.0, -($u >> 6) * 5.0 / 32.0; # depth (m)
            if ($j % 3 == 0 && $i != ($PROFILEEND +1)%0x600) {
                $u = $buf[$i++]; $i %= 0x600;
                last if $u == 0xff; 
                if ($Nitrox == 3 && $i != ($PROFILEEND +1)%0x600) {
                    $i++; $i %= 0x600;
                }
            }
        }
        $xrange = $j / 3.0;
        printf "%f 0\n", $xrange;
        print "e\n";
        print "set size 1,0.15\n";
        print "set origin 0,0\n";
        print "set title\n";
        print "set grid\n";
        print "set nox2tics\n";
        print "set xtics nomirror 0,5,240\n";
        print "set format x\n";
        print "set ytics 0,1,5\n";
        print "set ytics (\"work\" 1, \"rbt \" 2, \"asnt\" 3, \"deco\" 4)\n";
        print "set grid y x\n";
        print "set xrange [0:$xrange]\n";
        print "set yrange [0.4:4.6]\n";
        print "set bmargin\n";
        print "set tmargin 0\n";
        print "plot '-' with linespoints 1 3\n";
    
        $i = $startaddr;
        $i += 22 + $Nitrox;          # skip decompression info (22 bytes)
        $i %= 0x600;
        print "\n";
        for ($j = 1; ; $j++) {
            # there are 3 data a minute.
            last if ($i == ($PROFILEEND + 1)%0x600 || $i == $PROFILEEND);
            $u = $buf[$i++]; $i %= 0x600;
            last if ($u == 0xff);
            $u = $buf[$i++]; $i %= 0x600;
            # print bcheck($u & 0x3f, '  thcard'); 
            if ($u & 0x10) {
                printf "%f %f\n", $j/3.0, 1;
            } else {
                print "\n";
            }
            if ($j % 3 == 0&&$i!=($PROFILEEND+1)%0x600) {
                $u = $buf[$i++]; $i %= 0x600;
                last if $u == 0xff; 
                if ($Nitrox == 3 && $i != ($PROFILEEND +1)%0x600) {
                    $i++; $i %= 0x600;
                }
            }
        }
        $i = $startaddr;
        $i += 22 + $Nitrox;            # skip decompression info (22 bytes)
        $i %= 0x600;
        print "\n";
        for ($j = 1; ; $j++) {
            # there are 3 data a minute.
            last if ($i == ($PROFILEEND + 1)%0x600 || $i == $PROFILEEND);
            $u = $buf[$i++]; $i %= 0x600;
            last if ($u == 0xff);
            $u = $buf[$i++]; $i %= 0x600;
            if ($u & 2) {
                printf "%f %f\n", $j/3.0, 2;
            } else {
                print "\n";
            }
            if ($j % 3 == 0 && $i != ($PROFILEEND +1)%0x600) {
                $u = $buf[$i++]; $i %= 0x600;
                last if $u == 0xff; 
                if ($Nitrox == 3 && $i != ($PROFILEEND +1)%0x600) {
                    $i++; $i %= 0x600;
                }
            }
        }
        $i = $startaddr;
        $i += 22 + $Nitrox;            # skip decompression info (22 bytes)
        $i %= 0x600;
        print "\n";
        for ($j = 1; ; $j++) {
            # there are 3 data a minute.
            last if ($i == ($PROFILEEND + 1)%0x600 || $i == $PROFILEEND);
            $u = $buf[$i++]; $i %= 0x600;
            last if ($u == 0xff);
            $u = $buf[$i++]; $i %= 0x600;
            if ($u & 4) {
                printf "%f %f\n", $j/3.0, 3;
            } else {
                print "\n";
            }
            if ($j % 3 == 0 && ($i != ($PROFILEEND+1)%0x600)) {
                $u = $buf[$i++]; $i %= 0x600;
                last if $u == 0xff; 
                if ($Nitrox == 3 && $i != ($PROFILEEND +1)%0x600) {
                    $i++; $i %= 0x600;
                }
            }
        }
        $i = $startaddr;
        $i += 22 + $Nitrox;            # skip decompression info (22 bytes)
        $i %= 0x600;
        print "\n";
        for ($j = 1; ; $j++) {
            # there are 3 data in a minute.
            last if ($i == ($PROFILEEND + 1)%0x600 || $i == $PROFILEEND);
            $u = $buf[$i++]; $i %= 0x600;
            last if ($u == 0xff);
            $u = $buf[$i++]; $i %= 0x600;
            if ($u & 8) {
                printf "%f %f\n", $j/3.0, 4;
            } else {
                print "\n";
            }
            if ($j % 3 == 0 && ($i != ($PROFILEEND +1)%0x600)) {
                $u = $buf[$i++]; $i %= 0x600;
                last if $u == 0xff; 
                if ($Nitrox == 3 && $i != ($PROFILEEND +1)%0x600) {
                    $i++; $i %= 0x600;
                }
            }
        }
        print "e\n";
        print "set nomultiplot\n";
        if ((!$PrintPs) && $ENV{DISPLAY}) {
            print "pause -1 \"Hit return key to dismiss\"\n";
        }
        close(TMP1);
        select STDOUT;
    }
    
    if (!$_[0]) {
        print STDERR "Please specify a Dive No.\n";
        $NEXT = "";
        return;
    }
    open(LS, "ls -1 |");
    @ls = <LS>;
    close(LS);
    foreach (@ls) {
        chop;
        $file = $_;
        if (-s $file != 2048) {
            next;
        }
        analyze0($file);
        $end = $TOTALDIVES + $DiveNoOffset;
        $profilebegin = $end - $PROFILES + 1;
        if ($profilebegin <= $_[0] and $_[0] <= $end) {
            makedata($file, $_[0]);
            system "gnuplot $GnuPlotTmp";
            unlink $GnuPlotTmp;
            if ($PrintPs) {
                $DIVE = $_[0];
                eval $PrintPsCommand;
                unlink $GnuPlotPs;
            }
            $NEXT = $_[0] + 1; $LOG = 0;
            return; 
        }
    }
    print STDERR "No data\n";
    $NEXT = "";
}

sub readwithpager {
    if (analyze($_[0])) {
        return;
    }
    if (fork) {
        # parent here.
        wait();
    } else {
        # child here.
        exec "$Pager $PagerTmp";
    }
    unlink $PagerTmp;
}

sub analyze0 {
    open(IN, "<$_[0]");
    read(IN, $b, 2048);
    close(IN);
    $buf = "\0".substr($b,2031,1).substr($b,2030,1).substr($b,2029,1);
    $SERIAL = unpack('N', $buf);
    $buf = substr($b, 2032, 1);
    $BUTTERY = unpack('C', $buf) * 99 / 255;
    $buf = "\0" . substr($b, 2033, 3);
    $TOTALDIVES = unpack('N', $buf);
    $buf = substr($b, 2036, 1);
    $NEWESTLOG = unpack('C', $buf);
    $buf = substr($b, 2037, 1);
    $PROFILES = unpack('C', $buf);
    $PROFILES-- if $BuggyPro;
    $buf = substr($b, 2039, 1);
    $PROFILEEND = unpack('C', $buf) * 128;
    $buf = substr($b, 2038, 1);
    $PROFILEEND += unpack('C', $buf);
    $PROFILEEND = $PROFILEEND & 0x7ff;
    $buf = substr($b, 2040, 4);
    $RECVTIME = mylocaltime((unpack('N', $buf) >> 1) + $TIMECORR);
    $buf = substr($b, 2044, 2);
    $CHECKSUM = unpack('v', $buf);
}

sub logdata {
    sub makelog {
        open(IN, "<$_[0]");
        seek(IN, 0x600, 0);
        read(IN, $buf, 444);
        close(IN);
        @buf = unpack('C444', $buf);
    
        $i = ($_[1]+$NEWESTLOG-$TOTALDIVES + 36 - $DiveNoOffset)*12 % 444;
        $w = $buf[$i];                 # dive mode
        $v = $buf[$i+1];               # bottom time (bcd)
        printf "Logbook No. %5d  ", $_[1];
        print bcheck($w, '21Swd ra');
        print "\n";
        if ($w & 4) {
            printf "bottom time   = 1%s (min)\n", 
                pack('c2', $v / 16 + 0x30, $v % 16 + 0x30);
        } else {
            printf "bottom time   = %s (min)\n", 
                pack('c2', $v / 16 + 0x30, $v % 16 + 0x30);
        }
        $u = $buf[$i+2]*256+$buf[$i+3];                 # max depth
        printf "maximum depth = %3.1f (m)\n", ($u >> 6) * 10 / 64;
        if (($w & 2) == 0) {
            print "interval      = infty\n";
        } else {
            $u = $buf[$i+4];                 # interval time (bcd)
            printf "interval      = %s:", # hour
            pack('c2', $u / 16 + 0x30, $u % 16 + 0x30);
            $u = $buf[$i+5];
            printf "%s\n",                # minute
            pack('c2', $u / 16 + 0x30, $u % 16 + 0x30);
        }
        $u = $buf[$i+6];                 # used air
        if ($u == 0) {
            print "used air      = unknown\n";
        } else {
            printf "used air      = %d (bar)\n", $NormalAir ? $u * 1.37634409: $u;
        }
        $s = mylocaltime(
             (($buf[$i+7]*16777216+$buf[$i+8]*65536
               +$buf[$i+9]*256+$buf[$i+10])>>1) + $TIMECORR);
        printf "start time    = %s\n", $s;
        printf "temperature   = %2.1f (C)\n", $buf[$i+11] / 4;
    }

    if (!$_[0]) {
        print STDERR "Please specify a Dive No.\n";
        $NEXT = "";
        return;
    }
    open(LS, "ls -1 |");
    @ls = <LS>;
    close(LS);
    foreach (@ls) {
        chop;
        $file = $_;
        if (-s $file != 2048) {
            next;
        }
        analyze0($file);
        $end = $TOTALDIVES;
        $logbegin = max($end - 36, 1);
        $logbegin += $DiveNoOffset;
        $end += $DiveNoOffset;
        if ($logbegin <= $_[0] and $_[0] <= $end) {
            makelog($file, $_[0]);
            $NEXT = $_[0] + 1; $LOG = 1;
            return; 
        }
    }
    print STDERR "No data\n";
    $NEXT = "";
}

sub bcheck {
    my(@p, $i, $j, $v);
    @p = unpack('C8', $_[1]);
    $j = 0; $v = '';
    for ($i = 128; $i != 0; $i >>= 1) {
        $v .= ($_[0] & $i) ? chr($p[$j]) : ' ';
        $j++;
    }
    $v;
}

sub analyze {
    sub getn {
        my($i, $data);
        $data = 0;
        for ($i = 0; $i < $_[0]; $i++) {
            $data = $data * 256 + $Buf[$Offset];
            inc(1);
        }
        $data;
    }

    sub inc {
        if ($Offset < 0x600) {
            $Offset = ($Offset + $_[0] + 0x600) % 0x600;
        } elsif ($Offset < 0x600 + 444) {
            $Offset = ($Offset + $_[0] - 0x600 + 444) % 444 + 0x600;
        } else {
            $Offset += $_[0];
        }
    }

    if (! -f $_[0]) {
        printf STDERR "File %s not found.\n", $_[0];
        return -1;
    }
    
    open(IN, "<$_[0]");
    read(IN, $Buf, 2048);
    close(IN);
    @Buf = unpack('C2048', $Buf);

    open(PAGERTMP, ">$PagerTmp");
    select PAGERTMP;
    ##############
    # Misc infos #
    ##############
    $Offset = 0x7ed;
    # serial no. (does not match the 'external' serial)
    printf "hardware serial #%08d\n", getn(1) + getn(1) * 256 + getn(1) * 65536;
    # battery status
    printf "battery status = %2d(%%)\n", getn(1) * 99 / 255;
    # number of total dives the aladin have experienced
    $TOTALDIVES = getn(3);
    printf "total dives = %d\n", $TOTALDIVES;
    # location of the newest log data (in 12 bytes unit)
    $NEWESTLOG = getn(1);
    # number of profiles
    # Some Aladins have a bug!  They make this byte to be profiles + 1.
    $PROFILESSAVED = getn(1);
    # workaround (very slow)
    $PROFILES = 0;
    for ($i = 0; $i < 0x600; $i++) {
        $PROFILES++ if $Buf[$i] == 0xff;
    }
    if ($PROFILES != $PROFILESSAVED) {
        printf  "BUGGY. saved profiles = %d, actual profiles = %d\n", 
            $PROFILESSAVED, $PROFILES;
        $BuggyPro = 1;
    }
    printf "number of profiles = %d\n", $PROFILES;
    # end of profile data
    $PROFILEEND = getn(1);
    $tmp = getn(1);
    $PROFILEEND += $tmp*128;
    if ($tmp % 2) {
        print "UNEXPECTED!! Profile-end higher byte lsb = 1\n";    
    }
    if ($PROFILEEND & 0xf800) {
        print "Profile-end byte contains garbage in higher bits.\n";
    }
    $PROFILEEND = $PROFILEEND & 0x7ff;
    printf "end of profile data = 0x%04x\n", $PROFILEEND;
    # time of data reception.
    $RECVTIME = mylocaltime((getn(4) >> 1) + $TIMECORR);
    print "data reception time = $RECVTIME\n";
    # check sum
    $CHECKSUM = getn(1) + getn(1) * 256;
    printf "checksum = 0x%04x\n", $CHECKSUM;

    ######################################
    # dealing with depth and air profile #
    ######################################
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
    for ($i = - $PROFILES; $i < 0#########
    $Offset = $PROFILEEND; inc(1);
    while(getn(1) != 0xff) {
        ;
    }

ONE:
 