[Pkg-wmaker-commits] [wmbubble] 01/207: Initial checkin from upstream (asked; he doesn't have anything older)
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Mon Aug 24 04:17:46 UTC 2015
This is an automated email from the git hooks/post-receive script.
dtorrance-guest pushed a commit to branch master
in repository wmbubble.
commit 8a500c12bcc27bb8da3e705fb93fa612b49f8b99
Author: Robert Jacobs <rnjacobs at mit.edu>
Date: Mon Aug 29 19:00:41 2011 -0700
Initial checkin from upstream (asked; he doesn't have anything older)
---
ChangeLog | 154 +++++
INSTALL | 22 +
Makefile | 81 +++
Makefile.FreeBSD | 37 ++
Makefile.NetBSD | 37 ++
README | 128 ++++
SUPPORTED_SYSTEMS | 5 +
bubblemon.c | 1579 +++++++++++++++++++++++++++++++++++++++++++++++++
doc/COPYING | 3 +
doc/Xdefaults.sample | 12 +
include/bubblemon.h | 139 +++++
include/digits.h | 81 +++
include/ducks.h | 59 ++
include/load_screen.h | 464 +++++++++++++++
include/master.xpm | 71 +++
include/mem_screen.h | 466 +++++++++++++++
include/sys_include.h | 31 +
misc/load_1.1.xcf | Bin 0 -> 7339 bytes
misc/mem_1.1.xcf | Bin 0 -> 7809 bytes
misc/wak.wav | Bin 0 -> 4012 bytes
misc/wakwak.sh | 3 +
sys_freebsd.c | 210 +++++++
sys_linux.c | 176 ++++++
sys_netbsd.c | 132 +++++
sys_openbsd.c | 130 ++++
sys_sunos.c | 325 ++++++++++
26 files changed, 4345 insertions(+)
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..dc3bcaf
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,154 @@
+This ChangeLog file is backwards. Press "G" in vi to go to the end of it.
+
+Sun, 7 Jan 2001 - 1.0
+ Initial FreeBSD port
+
+Fri, 12 Jan 2001 - 1.0pl1
+ Duck "upside down" mode
+ Initial version of "memory info" screen
+
+Mon, 15 Jan 2001 - 1.0pl2
+ FreeBSD memory code fixes
+
+Tue, 16 Jan 2001 - 1.0pl3
+ Most drawing operations rewritten and optimized
+ Modular changes - extra features under #ifdef
+ FreeBSD fixes
+
+Tue, 16 Jan 2001 - 1.0pl4
+ More fixes
+
+Thu, 18 Jan 2001 - 1.0pl6
+ Code reorganization
+ Command line options
+
+Thu, 18 Jan 2001 - 1.0pl7
+ All floating point calculations eliminated
+ FreeBSD changes
+ Added Xresource parsing for color, etc options
+ Load average/Memory screen toggle via shift key
+
+Sun, 21 Jan 2001 - 1.0pl8
+ Load average graph inside load average screen
+ system-dependent code updates
+ more features #ifdef'd
+
+Sun, 21 Jan 2001 - 1.0pl9
+ Load average / memory info screens, "picture lock".
+
+Sun, 21 Jan 2001 - 1.1test1
+ bubblemon_update() cleanup
+ bubblemon.h cleanup
+ load average graph updates
+ session_defaults() update
+ documentation updates
+
+Sun, 21 Jan 2001 - 1.1test2
+ argv count bug found and fixed
+ range checking for values read from Xdefaults
+ performance improvements in bubblemon_update()
+ FreeBSD memory code changes
+ documentation updates
+ removed last pieces of floating point numbers
+
+Mon, 22 Jan 2001 - 1.1test3
+ bubblemon_update() cleanup
+
+Thu, 25 Jan 2001 - 1.1test4
+ Code reorganization
+ Main Makefile will detect OS if GNU make is used
+ Moved system dependent code into sys_(uname).c
+ Changes to system-dependent code structure
+ Reorganization of include files and directory structure
+ History graphs for load average and memory use updates
+ Performance improvements
+ Some functions renamed
+ Off-by-one error in rgb image data fixed
+ BlackBox don't-draw-on-win feature
+ bubblemon_update() cleanup
+ Swapped load / memory screen order
+ FreeBSD memory code updates
+
+Sun, 28 Jan 2001 - 1.1test5
+ Load average logic change, update to Linux and FreeBSD dependent code
+ Other misc changes
+
+Mon, 29 Jan 2001 - 1.1test6
+ BubbleMonData is now a static structure
+ Performance improvements
+
+Wed, 31 Jan 2001 - 1.1test7
+ Documentation updates
+ Possible buffer overflow fix in session_defaults()
+
+Thu 01 Feb 2001 - 1.1
+ Minor documentation update
+ sys_freebsd math update
+ Version 1.1 released
+
+Wed 14 Feb 2001 - 1.2test1
+ SunOS port added
+
+Thu 15 Feb 2001 - 1.2
+ SunOS port fixed
+ Version 1.2 released
+
+Mon 19 Feb 2001 - 1.21test1
+ Various updates to the SunOS port
+ Added -k command line switch to display memory/swap in megabytes instead
+ of kilobytes. Useful for machines with > 1024mb memory, since kilobytes
+ display stops at 999mb for both swap and physical ram
+ Portability fixes
+
+Thu 22 Feb 2001 - 1.21
+ Fix for FreeBSD CPU usage problem under high load
+ Released version 1.21
+
+Sun 25 Feb 2001 - 1.22
+ Fixed segfault which occured under certain low memory conditions, found
+ and fixed by "John H. Robinson, IV" <jaqque at ucsd.edu>
+ Released version 1.22
+
+Sat 10 Mar 2001 - 1.23
+ Patch from Dan Price to fix Shift Key detection on all platforms
+ Tracked down another segfault related to off-by-one-scanline error
+ Increased bm.bubblebuf allocation because bubbles created at the very
+ bottom of the "water" are drawn outside of 56x56 region.
+ Released version 1.23
+
+Fri 16 Mar 2001 - 1.3
+ Fixed load average graph - I don't know what the hell I was doing that
+ it worked before, but the way the code was written it was never supposed
+ to work :)
+ Added some contributed code to hopefully catch most of bubble-related
+ segfaults. Thanks to "John H. Robinson, IV" <jaqque at ucsd.edu>
+ Updated Makefile to use proper libs when linking with gdk, etc. Should
+ stop complaints about "missing library dependencies"
+ This is a recommented upgrade if you use bubblemon version 1.2 or newer.
+ Released version 1.3
+
+Sat 14 Apr 2001 - 1.31
+ FreeBSD machines were compiling bubblemon as "big-endian", resulting in
+ fairly weird looking color problem. This has been fixed :) Minor change
+ to Makefile.FreeBSD to put bubblemon in /usr/X11R6 during install.
+ Released version 1.31
+
+Mon 16 Apr 2001 - 1.32
+ Important security update for FreeBSD - previous versions did not drop
+ kmem privileges, and programs started by clicking on the dockapp were
+ started with elevated privileges. This is a required upgrade for FreeBSD
+ users.
+
+Tue 28 Aug 2001 - 1.4
+ Added OpenBSD support. Thanks to Peter Stromberg <wilfried at openbsd.org>.
+
+Wed 1 Oct 2003 - 1.41
+ Added support for Linux kernel 2.6
+ Fixed 101% cpu usage problem on kernel 2.6
+
+Thu 13 May 2004 - 1.45
+ Added support for NetBSD. Thanks to Metalhead <metalhead at metalhead.ws>
+ This support is untested, use Makefile.NetBSD to compile.
+
+Sat 15 May 2004 - 1.46
+ Compile fix for FreeBSD-5.x, forgotten include.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..b599e81
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,22 @@
+Install instructions:
+
+1. read README
+1a. On Linux 2.6, edit Makefile and uncommend top line that adds -DKERNEL_26
+2. make (on FreeBSD, make -f Makefile.FreeBSD)
+3. make install (this will put bubblemon in /usr/local/bin)
+4. bubblemon &
+
+Using GNU make bubblemon should compile without changes on any system listed
+in SUPPORTED_SYSTEMS file. If not, feel free to fix it and send me a diff -u.
+
+Check README file for configuration options - you can either permanently
+disable a feature by editing Makefile and commenting out any of the EXTRA
+defines, or disable it at run-time by using command-line switches. Colors
+and bubble physics can also be configured through ~/.Xdefaults file.
+
+If your FreeBSD system doesn't have GNU Make, use Makefile.FreeBSD. If it
+does, regular Makefile should be able to detect things correctly. Also,
+on FreeBSD, you can do make install as root to install in /usr/local/bin
+and give bubblemon proper permissions, or you'll have to give bubblemon
+kmem access yourself:
+root:~# chown root:kmem bubblemon; chmod g+s bubblemon
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1396075
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,81 @@
+# bubblemon configuration
+EXTRA = -DENABLE_DUCK
+EXTRA += -DENABLE_CPU
+EXTRA += -DENABLE_MEMSCREEN
+EXTRA += -DKERNEL_26
+# EXTRA += -DKDE_DOCKAPP
+# EXTRA += -DUPSIDE_DOWN_DUCK
+
+# where to install this program
+PREFIX = /usr/local
+
+# no user serviceable parts below
+EXTRA += $(WMAN)
+# optimization cflags
+CFLAGS = -O3 -ansi -Wall `gtk-config --cflags` ${EXTRA}
+# profiling cflags
+# CFLAGS = -ansi -Wall -pg -O3 `gtk-config --cflags` ${EXTRA} -DPRO
+# test coverage cflags
+# CFLAGS = -fprofile-arcs -ftest-coverage -Wall -ansi -g `gtk-config --cflags` ${EXTRA} -DPRO
+
+
+SHELL=sh
+OS = $(shell uname -s)
+OBJS = bubblemon.o
+CC = gcc
+
+# special things for Linux
+ifeq ($(OS), Linux)
+ OBJS += sys_linux.o
+ LIBS = `gtk-config --libs | sed "s/-lgtk//g"`
+ INSTALL = -m 755
+endif
+
+# special things for FreeBSD
+ifeq ($(OS), FreeBSD)
+ OBJS += sys_freebsd.o
+ LIBS = `gtk-config --libs | sed "s/-lgtk//g"` -lkvm
+ INSTALL = -c -g kmem -m 2755 -o root
+endif
+
+# special things for OpenBSD
+ifeq ($(OS), OpenBSD)
+ OBJS += sys_openbsd.o
+ LIBS = `gtk-config --libs | sed "s/-lgtk//g"`
+endif
+
+#special things for SunOS
+ifeq ($(OS), SunOS)
+
+ # try to detect if gcc is available (also works if you call gmake CC=cc to
+ # select the sun compilers on a system with both)
+ COMPILER=$(shell \
+ if [ `$(CC) -v 2>&1 | egrep -c '(gcc|egcs|g\+\+)'` = 0 ]; then \
+ echo suncc; else echo gcc; fi)
+
+ # if not, fix up CC and the CFLAGS for the Sun compiler
+ ifeq ($(COMPILER), suncc)
+ CC=cc
+ CFLAGS=-v -xO3
+ endif
+
+ ifeq ($(COMPILER), gcc)
+ CFLAGS=-O3 -Wall
+ endif
+ CFLAGS +=`gtk-config --cflags` ${EXTRA}
+ OBJS += sys_sunos.o
+ LIBS = `gtk-config --libs` -lkstat -lm
+ INSTALL = -m 755
+endif
+
+
+all: bubblemon
+
+bubblemon: $(OBJS)
+ $(CC) $(CFLAGS) -o bubblemon $(OBJS) $(LIBS)
+
+clean:
+ rm -f bubblemon *.o *.bb* *.gcov gmon.* *.da *~
+
+install:
+ install $(INSTALL) bubblemon $(PREFIX)/bin
diff --git a/Makefile.FreeBSD b/Makefile.FreeBSD
new file mode 100644
index 0000000..04f53c5
--- /dev/null
+++ b/Makefile.FreeBSD
@@ -0,0 +1,37 @@
+# bubblemon configuration
+EXTRA = -DENABLE_DUCK
+EXTRA += -DENABLE_CPU
+EXTRA += -DENABLE_MEMSCREEN
+EXTRA += -DUPSIDE_DOWN_DUCK
+
+EXTRA += $(WMAN)
+
+# no user serviceable parts below
+CC = gcc
+
+# optimization cflags
+CFLAGS = -O3 -ansi -Wall `gtk-config --cflags` ${EXTRA}
+# profiling cflags
+# CFLAGS = -ansi -Wall -pg -O3 `gtk-config --cflags` ${EXTRA} -DPRO
+# test coverage cflags
+# CFLAGS = -fprofile-arcs -ftest-coverage -Wall -ansi -g `gtk-config --cflags` ${EXTRA} -DPRO
+
+LIBS = `gtk-config --libs | sed "s/-l.*//g"` -lgdk12 -lkvm
+PREFIX = /usr/X11R6
+VPATH = include
+
+all: bubblemon
+
+bubblemon: bubblemon.o sys_freebsd.o
+ gcc ${CFLAGS} -o bubblemon bubblemon.o sys_freebsd.o ${LIBS}
+
+clean:
+ rm -f bubblemon bubblemon.o *.o *.bb* *.gcov gmon.* *.da winglue.c bubblemon32 *.so win32.spec *~ *.gmon *.s *.core
+
+install:
+ install -c -g kmem -m 2755 -o root bubblemon ${PREFIX}/bin
+
+bubblemon.o: bubblemon.h ducks.h master.xpm sys_include.h digits.h \
+ load_screen.h mem_screen.h
+
+sys_freebsd.o: bubblemon.h
diff --git a/Makefile.NetBSD b/Makefile.NetBSD
new file mode 100644
index 0000000..88534cf
--- /dev/null
+++ b/Makefile.NetBSD
@@ -0,0 +1,37 @@
+# bubblemon configuration
+EXTRA = -DENABLE_DUCK
+EXTRA += -DENABLE_CPU
+EXTRA += -DENABLE_MEMSCREEN
+#EXTRA += -DUPSIDE_DOWN_DUCK
+
+EXTRA += $(WMAN)
+
+# no user serviceable parts below
+CC = gcc
+
+# optimization cflags
+CFLAGS = -O2 -ansi -Wall `gtk-config --cflags` ${EXTRA}
+# profiling cflags
+# CFLAGS = -ansi -Wall -pg -O3 `gtk-config --cflags` ${EXTRA} -DPRO
+# test coverage cflags
+# CFLAGS = -fprofile-arcs -ftest-coverage -Wall -ansi -g `gtk-config --cflags` ${EXTRA} -DPRO
+
+LIBS = `gtk-config --libs | sed "s/-l.*//g"` -lgdk -lkvm
+PREFIX = /usr/X11R6
+VPATH = include
+
+all: bubblemon
+
+bubblemon: bubblemon.o sys_netbsd.o
+ gcc ${CFLAGS} -o bubblemon bubblemon.o sys_netbsd.o ${LIBS}
+
+clean:
+ rm -f bubblemon bubblemon.o *.o *.bb* *.gcov gmon.* *.da winglue.c bubblemon32 *.so win32.spec *~ *.gmon *.s *.core
+
+install:
+ install -c -g kmem -m 2755 -o root bubblemon ${PREFIX}/bin
+
+bubblemon.o: bubblemon.h ducks.h master.xpm sys_include.h digits.h \
+ load_screen.h mem_screen.h
+
+sys_netbsd.o: bubblemon.h
diff --git a/README b/README
new file mode 100644
index 0000000..5306cc8
--- /dev/null
+++ b/README
@@ -0,0 +1,128 @@
+For copyright/authors/contributors see top of bubblemon.c. For list of
+supported operating systems, see SUPPORTED_SYSTEMS.
+
+Abstract:
+
+This program is a dockapp-style CPU, memory, swap and load average monitor.
+Based on the GNOME BubbleMon applet, this program has been considerably
+improved. Many new features have been added. This is version 1.3.
+
+Features:
+
+On the surface, dockapp BubbleMon follows the same style as original GNOME
+applet. Main screen area is split into 2 parts - air and water. Water level
+depends on how much physical and virtual memory is used by the system. CPU
+activity makes water "boil" and creates bubbles. CPU meter near the bottom
+shows actual value in percent. As memory usage increases, water level goes
+up. When system runs out of physical memory and begins using swap, both
+water and air colors change depending on amount of swap used. There is a
+cute yellow duck swimming from one corner of the dockapp to another. The
+duck really doesn't do anything at the moment, but in a future version it's
+speed might correspond to system load average or another variable. This is
+the "main" mode of BubbleMon.
+
+There are 2 additional screens available - memory and load average. Load
+average screen is accessed by simply hovering the mouse pointer over BubbleMon
+window. Memory screen is accessed same way, except you must hold down either
+left or right "Shift" key before moving the mouse pointer over BubbleMon
+window. Both Memory and Load average screens fade in slowly for a reason -
+during fade, you can click "Right" mouse button to lock currently fading
+screen. This way you can see both CPU load screen and either memory or load
+average screen. To exit "locked" mode, simply move the mouse pointer in and
+out of the BubbleMon window.
+
+Memory screen displays current amount of free memory and swap, in kilobytes
+and percent. Top number is amount of used memory, in kilobytes and percent,
+and bottom number is amount of used swap. Under Linux implementation, used
+swap is set to "0" until 100% of system memory is used. Below these numbers
+is a graph of recent memory use. Unless you are running something that
+dynamically allocates and deallocates huge amounts of memory, this graph is
+most likely going to be more or less a straight line. Percentage and kilobyte
+counters will change color in case of memory or swap use over 90%.
+Load average screen displays system load average, same way as presented by
+"uptime" command. Approximately last 3 minutes of system load are graphed
+below the load average numbers. Default "light blue" color of load average
+and memory screens can be changed to a "pale" version by using "-p" command
+line switch.
+
+You can start BubbleMon with up to 2 command-line argumens (not counting
+switches), each being a path to a program or shell script to execute when
+you click Left or Middle mouse button inside BubbleMon window. These must
+be the last 2 parameters. There is a .wav file and a simple shell script
+to play it, inside misc/ directory, which you can use to make some duck
+sounds with bubblemon.
+
+Configuration:
+
+BubbleMon is very configurable. Previous section explains many features, but
+all of them can be disabled, either through compile-time settings or with
+command-line switches at startup. Either the general Makefile or FreeBSD-
+specific Makefile contain compilation defines near the top. You can comment out
+a particular line, to disable that feature. Alternatively, you can run
+"bubblemon -h" for a list of command line options. This will show command-line
+switches which can be used to disable certain BubbleMon modes, and modify color
+scheme used in memory and load average screens. You can also change colors of
+the air, water, various physics constants which control bubble generation, and
+maximum number of bubbles to make. All of these settings are read on start-up
+from the user's HOME directory, using .Xdefaults file. If you don't have a
+.Xdefaults file in your home directory, you can copy Xdefaults.sample which
+is distributed with BubbleMon. If you already have some settings in .Xdefaults
+you can simply append BubbleMon settings file to your current configuration:
+hostname:~$ cat /path/to/bubblemon-src/Xdefaults.sample >> ~/.Xdefaults
+However if you are happy with the current color scheme or bubble physics, you
+don't need to do anything at all, because BubbleMon has default settings
+compiled in.
+
+Information about original GNOME BubbleMon applet:
+
+You can get the original BubbleMon applet from
+http://www.nada.kth.se/~d92-jwa/code - but that version requires GNOME, does
+not have a cute duck, uses more CPU, and doesn't allow you to start programs
+by clicking on it. But, I guess if you like GNOME, you might want to check
+it out.
+
+Programming details:
+
+It's been a long tradition that dockapps use Xlib to draw, mainly because
+that's what the first dockapp used and because there are some abstraction
+layers to hide some of Xlib ugliness (libdockapp, wmgeneral, etc). Xlib is
+fine if all you do is change a couple pixels every other second, like most
+dockapps do. But if you deal with 3D, or any kind of large amount of pixel
+shuffling, Xlib really starts to suck. Common mistake when doing lots of
+pixel shuffling in Xlib is using XPutPixel or XCopyArea. Say, you got a
+56x56 dockapp, and 80% of it is changed every 10ms. That's almost 2.5
+thousand pixel ops. And a 1x1 XCopyArea takes as much server overhead as a
+64x64 XCopyArea. Since X11 sucks, each one of these puts a request in the
+server queue and will waste ungodly amounts of bandwidth (if you run a
+remote X session) and use CPU time on the server machine. X11 really doesn't
+provide any simple way to deal with drawing stuff on screen without messing
+with colormaps or other serious ugliness. If you are familiar with game
+programming and that kind of stuff, you know that screen is usually drawn on
+a back buffer and then switched, so the user sees smooth animation instead
+of watching the screen redraw. X11 doesn't really have this feature, because
+even drawing to a off-screen pixmap is still slow - and requires contacting
+the server, and still requires dealing with colormaps.
+
+Solution is simple. GDK. Gimp Drawing toolKit. And a large buffer to draw
+in. Render your screen on the "back buffer", which is completely in memory
+and thus doesn't need to contact the server, and then use gdk_draw_rgb_image
+to quicky slap that on-screen. That's about the only GDK function you will
+ever need to use. Results are impressive - very complex scenes could be
+rendered in local memory, fast, and the only network I/O generated is from
+copying backbuffer to the screen, which is minimal compared to updating the
+same screen pixel by pixel. Since bubblemon does a lot of pixel shuffling,
+it uses this technique to draw. Thanks to gdkrgb, BubbleMon achieves fluid
+animation at 33 frames per second. Some window managers, like BlackBox,
+don't require dockapps to draw on the main window, only on the icon window.
+You can run make with "make WMAN=-DBLACKBOX" to remove code dealing with
+drawing on main window, for a marginal performance improvement, though it's
+very unlikely you will notice the difference unless you are profiling.
+
+timecop at japan.co.jp
+
+
+Notes from the FreeBSD port author:
+For FreeBSD, the percentage of used memory is calculated as
+number_of_active_pages / total_number_of_pages_in_the_system * 100%.
+If you have any concerns regarding this or FreeBSD port of BubbleMon
+in general, please email oleg dashevskii <od at iclub.nsu.ru>.
diff --git a/SUPPORTED_SYSTEMS b/SUPPORTED_SYSTEMS
new file mode 100644
index 0000000..cfae4e9
--- /dev/null
+++ b/SUPPORTED_SYSTEMS
@@ -0,0 +1,5 @@
+Linux - timecop at japan.co.jp, added support for kernel 2.6
+FreeBSD - od at iclub.nsu.ru
+OpenBSD - wilfried at openbsd.org
+NetBSD - metalhead at metalhead.ws
+Solaris/SunOS - wplu13 at netscape.net, dp at rampant.org
diff --git a/bubblemon.c b/bubblemon.c
new file mode 100644
index 0000000..c0679c1
--- /dev/null
+++ b/bubblemon.c
@@ -0,0 +1,1579 @@
+/* BubbleMon dockapp 1.32
+ *
+ * - dockapp for Window Maker/Blackbox/E/Afterstep/SawBabble
+ * - Code outside of bubblemon_update copyright 2000, 2001
+ * timecop at japan.co.jp
+ * - oleg dashevskii <od at iclub.nsu.ru> made changes to collect memory
+ * and cpu information on FreeBSD. Some major performance improvements
+ * and other cool hacks. Useful ideas - memscreen, load screen, etc.
+ * - Adrian B <midnight at bigpond.net.au> came up with the idea of load
+ * meter.
+ * - tarzeau at space.ch sent in cute duck gfx and suggestions, plus some
+ * code and duck motion fixes.
+ * - Phil Lu <wplu13 at netscape.net> Dan Price <dp at rampant.org> - Solaris/SunOS
+ * port
+ * - Everything else copyright one of the guys below
+ *
+ * TODO: Anything else? Add fish?
+ *
+ * *************************************************************************
+ *
+ * Bubbling Load Monitoring Applet
+ * - A GNOME panel applet that displays the CPU + memory load as a
+ * bubbling liquid.
+ * Copyright (C) 1999-2000 Johan Walles
+ * - d92-jwa at nada.kth.se
+ * Copyright (C) 1999 Merlin Hughes
+ * - merlin at merlin.org
+ * - http://nitric.com/freeware/
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+#define _GNU_SOURCE
+
+#define VERSION "1.41"
+
+/* general includes */
+#include <stdio.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* x11 includes */
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xresource.h>
+
+#include "include/master.xpm"
+#include "include/bubblemon.h"
+#include "include/sys_include.h"
+
+#ifdef ENABLE_DUCK
+#include "include/ducks.h"
+#endif
+#if defined(ENABLE_CPU)
+#include "include/digits.h"
+#endif
+#if defined(ENABLE_MEMSCREEN)
+#include "include/load_screen.h"
+#include "include/mem_screen.h"
+#endif
+
+/* #define DEBUG_DUCK 1 */
+
+/* local prototypes *INDENT-OFF* */
+static void bubblemon_setup_samples(void);
+static void bubblemon_setup_colors(void);
+static void bubblemon_allocate_buffers(void);
+static void bubblemon_update(int proximity);
+static void make_new_bubblemon_dockapp(void);
+static void get_memory_load_percentage(void);
+static void bubblemon_session_defaults(void);
+static int get_screen_selection(void);
+#if defined(ENABLE_CPU) || defined(ENABLE_MEMSCREEN)
+/* draw functions for load average / memory screens */
+static void draw_pixel(unsigned int x, unsigned int y, unsigned char *buf,
+ unsigned char *c);
+static void draw_history(int num, int size, unsigned int *history,
+ unsigned char *buf);
+static void draw_digit(int srcx, int srcy, int destx, int desty);
+static void draw_string(char *string, int x, int y, int color);
+static void draw_cpudigit(const int what, const int where,
+ unsigned char *kit);
+
+static void render_secondary(void);
+static void realtime_alpha_blend_of_cpu_usage(int cpu, int proximity);
+static void roll_membuffer(void);
+static void roll_history(void);
+#endif
+#ifdef ENABLE_DUCK
+static int animate_correctly(void);
+static void duck_set(int x, int y, int nr, int rev, int upsidedown);
+static void duck_swimmer(int posy);
+#endif
+#ifdef __FreeBSD__
+extern int init_stuff(); /* defined in sys_freebsd.c */
+#endif
+/* local prototypes end *INDENT-ON* */
+
+/* global variables */
+BubbleMonData bm;
+
+/* compiled-in options string */
+char options[1024];
+
+#ifdef ENABLE_DUCK
+int duck_enabled = 1;
+#ifdef UPSIDE_DOWN_DUCK
+int upside_down_duck_enabled = 1;
+#endif /* UPSIDE_DOWN_DUCK */
+#endif /* ENABLE_DUCK */
+#ifdef ENABLE_CPU
+int cpu_enabled = 1;
+#endif /* ENABLE_CPU */
+#ifdef ENABLE_MEMSCREEN
+int memscreen_enabled = 1;
+int memscreen_megabytes = 0;
+#endif /* ENABLE_MEMSCREEN */
+
+#define INT_VAL 0
+#define DOUBLE_VAL 1
+#define COLOR_VAL 2
+
+static void bubblemon_session_defaults(void)
+{
+ /* handy way to collect all this stuff in one place */
+ typedef struct {
+ char *name; /* name as appears in Xdefaults */
+ int type; /* int, double, or color, see up */
+ void *var; /* pointer to value - only handles INT atm */
+ } xrm_vars;
+
+ /* XResource stuff */
+ char name[BUFSIZ] = "", *ptr;
+ XrmDatabase db = NULL;
+ XrmValue val;
+ char *type;
+ int i;
+
+ xrm_vars tab[] = {
+ {"bubblemon.maxbubbles", INT_VAL, &bm.maxbubbles},
+ {"bubblemon.air_noswap", COLOR_VAL, &bm.air_noswap},
+ {"bubblemon.air_maxswap", COLOR_VAL, &bm.air_maxswap},
+ {"bubblemon.liquid_noswap", COLOR_VAL, &bm.liquid_noswap},
+ {"bubblemon.liquid_maxswap", COLOR_VAL, &bm.liquid_maxswap},
+ {"bubblemon.ripples", DOUBLE_VAL, &bm.ripples},
+ {"bubblemon.gravity", DOUBLE_VAL, &bm.gravity},
+ {"bubblemon.volatility", DOUBLE_VAL, &bm.volatility},
+ {"bubblemon.viscosity", DOUBLE_VAL, &bm.viscosity},
+ {"bubblemon.speed_limit", DOUBLE_VAL, &bm.speed_limit}
+ };
+
+ /* number of CPU load samples */
+ bm.samples = 16;
+
+ /* default colors. changeable from Xdefaults */
+ bm.air_noswap = 0x2299ff;
+ bm.liquid_noswap = 0x0055ff;
+ bm.air_maxswap = 0xff0000;
+ bm.liquid_maxswap = 0xaa0000;
+
+ /* default bubble engine parameters. Changeable from Xdefaults */
+ bm.maxbubbles = 100;
+ bm.ripples = 0.2;
+ bm.gravity = 0.01;
+ bm.volatility = 1.0;
+ bm.viscosity = 0.98;
+ bm.speed_limit = 1.0;
+
+ db = NULL;
+ XrmInitialize();
+
+ /* get users's local Xdefaults */
+ if ((ptr = getenv("HOME")) != NULL) {
+ snprintf(name, sizeof(name), "%s/.Xdefaults", ptr);
+ }
+
+ /* get the database and parse resources if we have some */
+ if ((db = XrmGetFileDatabase(name)) != NULL) {
+ for (i = 0; i < (sizeof(tab) / sizeof(tab[0])); i++) {
+ if (XrmGetResource(db, tab[i].name, tab[i].name, &type, &val)) {
+ if (val.size > 0) /* no empty strings and shit like that */
+ switch (tab[i].type) {
+ case INT_VAL:
+ *(int *) tab[i].var = atoi(val.addr);
+ break;
+ case DOUBLE_VAL:
+ *(double *) tab[i].var = atof(val.addr);
+ break;
+ case COLOR_VAL:
+ sscanf(val.addr, "#%x", (int *) tab[i].var);
+ break;
+ default:
+ /* WTF? */
+ break;
+ }
+ }
+ }
+ }
+#define RANGE_CHECK(x, min, max, def) \
+ if ((x) > (max) || (x) < (min)) { \
+ fprintf(stderr, #x" value is out of range. Using default value ("#def")\n"); \
+ (x) = (def); \
+ }
+
+ /* range validation. 3l33t hackerz NO PASARAN */
+ RANGE_CHECK(bm.air_noswap, 0, 0xffffff, 0x2299ff);
+ RANGE_CHECK(bm.liquid_noswap, 0, 0xffffff, 0x0055ff);
+ RANGE_CHECK(bm.air_maxswap, 0, 0xffffff, 0xff0000);
+ RANGE_CHECK(bm.liquid_maxswap, 0, 0xffffff, 0xaa0000);
+
+ RANGE_CHECK(bm.maxbubbles, 10, 200, 100);
+ RANGE_CHECK(bm.ripples, 0, 1, 0.2);
+ RANGE_CHECK(bm.gravity, 0.005, 0.5, 0.01);
+ RANGE_CHECK(bm.volatility, 0.1, 2, 1.0);
+ RANGE_CHECK(bm.viscosity, 0, 1.0, 0.98);
+ RANGE_CHECK(bm.speed_limit, 0.5, 2, 1.0);
+
+#undef RANGE_CHECK
+
+ /* convert doubles into integer representation */
+ bm.ripples_int = MAKE_INTEGER(bm.ripples);
+ bm.gravity_int = MAKE_INTEGER(bm.gravity);
+ bm.volatility_int = MAKE_INTEGER(bm.volatility);
+ bm.viscosity_int = MAKE_INTEGER(bm.viscosity);
+ bm.speed_limit_int = MAKE_INTEGER(bm.speed_limit);
+}
+
+#undef INT_VAL
+#undef DOUBLE_VAL
+#undef COLOR_VAL
+
+/* *INDENT-OFF* */
+static void print_usage(void)
+{
+ printf( "BubbleMon version "VERSION", features: %s\n"
+ "Usage: bubblemon [switches] [program_1] [program_2]\n\n"
+ "Disable compiled-in features\n"
+#ifdef ENABLE_DUCK
+ " -d\tdisable swimming duck\n"
+#ifdef UPSIDE_DOWN_DUCK
+ " -u\tdisable upside-down duck\n"
+#endif /* UPSIDE_DOWN_DUCK */
+#endif /* ENABLE_DUCK */
+#ifdef ENABLE_CPU
+ " -c\tdisable CPU meter\n"
+#endif /* ENABLE_CPU */
+#ifdef ENABLE_MEMSCREEN
+ " -m\tdisable memory screen\n"
+#endif /* ENABLE_MEMSCREEN */
+ "\nGeneral options\n"
+#ifdef ENABLE_MEMSCREEN
+ " -p\tuse alternative color scheme in memory info screen\n"
+ " -k\tdisplay memory and swap statistics in megabytes\n"
+#endif
+ " -h\tdisplay this help\n",
+ options /* this is the global static string with compiled features */
+ );
+}
+/* *INDENT-ON* */
+
+int main(int argc, char **argv)
+{
+ char execute[256];
+ int proximity = 0;
+ int ch;
+#ifdef FPS
+ int f, o;
+ time_t y;
+#endif
+#ifdef PRO
+ int cnt = 25000;
+#endif
+ GdkEvent *event;
+
+#ifdef FPS
+ o = f = y = 0;
+#endif
+
+ /* initialize GDK */
+ if (!gdk_init_check(&argc, &argv)) {
+ fprintf(stderr,
+ "GDK init failed, bye bye. Check \"DISPLAY\" variable.\n");
+ exit(-1);
+ }
+ gdk_rgb_init();
+
+ /* dynamically generate getopt string depending on compile options
+ * we are going to borrow 256 char string from exec function, and
+ * also build up the "compiled features" string */
+ memset(execute, 0, 256);
+ strcat(execute, "h"); /* help, always in */
+#ifdef ENABLE_DUCK
+ strcat(options, "DUCK ");
+ strcat(execute, "d");
+#ifdef UPSIDE_DOWN_DUCK
+ strcat(options, "INVERT ");
+ strcat(execute, "u");
+#endif /* UPSIDE_DOWN_DUCK */
+#endif /* ENABLE_DUCK */
+#ifdef ENABLE_CPU
+ strcat(options, "CPU ");
+ strcat(execute, "c");
+#endif /* ENABLE_CPU */
+#ifdef ENABLE_MEMSCREEN
+ strcat(options, "MEMSCREEN ");
+ strcat(execute, "pmk");
+#endif /* ENABLE_MEMSCREEN */
+
+ /* command line options */
+ while ((ch = getopt(argc, argv, execute)) != -1) {
+ switch (ch) {
+#ifdef ENABLE_DUCK
+ case 'd':
+ duck_enabled = 0;
+ break;
+#ifdef UPSIDE_DOWN_DUCK
+ case 'u':
+ upside_down_duck_enabled = 0;
+ break;
+#endif /* UPSIDE_DOWN_DUCK */
+#endif /* ENABLE_DUCK */
+#ifdef ENABLE_CPU
+ case 'c':
+ cpu_enabled = 0;
+ break;
+#endif /* ENABLE_CPU */
+#ifdef ENABLE_MEMSCREEN
+ case 'm':
+ memscreen_enabled = 0;
+ break;
+ case 'p':
+ {
+ /* no sense having -p if memscreen isn't compiled in, right?
+ * what we are going to do is to change the colors as follows:
+ *
+ * (48,140,240) replaced with (158,196,237) - more pale blue
+ * (237,23,23) replaced with (0,255,233) */
+ unsigned char *p = mem_screen;
+
+ while (p < mem_screen + sizeof(mem_screen))
+ if (*p == 48) { /* hopefully no other colors beginning with 48 */
+ *p++ = 158;
+ *p++ = 196;
+ *p++ = 237;
+ } else if (*p == 237) { /* hopefully no other colors beginning with 237 */
+ *p++ = 0;
+ *p++ = 255;
+ *p++ = 233;
+ } else
+ p += 3;
+
+ p = load_screen;
+
+ while (p < load_screen + sizeof(load_screen))
+ if (*p == 48) { /* hopefully no other colors beginning with 48 */
+ *p++ = 158;
+ *p++ = 196;
+ *p++ = 237;
+ } else
+ p += 3;
+ }
+ break;
+ case 'k':
+ memscreen_megabytes = 1;
+ break;
+#endif /* ENABLE_MEMSCREEN */
+ default:
+ print_usage();
+ exit(-1);
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* zero data structure */
+ memset(&bm, 0, sizeof(bm));
+
+#ifdef __FreeBSD__
+ if (init_stuff())
+ exit(-1);
+#endif
+
+ /* set default things, from Xresources or compiled-in defaults */
+ bubblemon_session_defaults();
+
+ /* create dockapp window. creates windows, allocates memory, etc */
+ make_new_bubblemon_dockapp();
+
+#ifdef PRO
+ while (cnt--) {
+#else
+ while (1) {
+#endif
+ while (gdk_events_pending()) {
+ event = gdk_event_get();
+ if (event) {
+ switch (event->type) {
+ case GDK_DESTROY:
+ gdk_exit(0);
+ exit(0);
+ break;
+ case GDK_BUTTON_PRESS:
+ if (event->button.button == 3) {
+ bm.picture_lock = 1;
+ break;
+ }
+ if (event->button.button <= argc) {
+ snprintf(execute, 250, "%s &",
+ argv[event->button.button - 1]);
+ system(execute);
+ }
+ break;
+#if defined(ENABLE_CPU) || defined(ENABLE_MEMSCREEN)
+ case GDK_ENTER_NOTIFY:
+ /* mouse in: make it darker, and eventually bring up
+ * meminfo */
+ proximity = 1;
+
+ bm.screen_type = get_screen_selection();
+ bm.picture_lock = 0;
+ break;
+ case GDK_LEAVE_NOTIFY:
+ /* mouse out: back to light */
+ proximity = 0;
+ break;
+#endif /* ENABLE_CPU || ENABLE_MEMSCREEN */
+ default:
+ break;
+ }
+ }
+ }
+#ifndef PRO
+ usleep(15000);
+#else
+ /* amazingly enough just calling this function takes insane
+ * amount of time.
+ usleep(0); */
+#endif
+ /* get system statistics */
+ get_memory_load_percentage();
+ /* update main rgb buffer: bm.rgb_buf */
+ bubblemon_update(proximity);
+
+/* *INDENT-OFF* */
+#ifdef FPS
+ /* render frames per second on bottom-right corner :)
+ * This is GCC-specific (functions inside functions)
+ * and very unoptimized. this is obfuscated 'cause its ugly */
+ f++;{int b;void q(int sx,int sy,int dx,int dy){int i,j;char *from,*to;
+ for(j=0;j<8;j++){from=mem_screen+56*3*(sy+j)+sx*3;to=bm.rgb_buf+56*3*
+ (dy+j)+dx*3;i=12;while(i--)*to++=*from++;}}b=o;if(b>=100){q((b/100)*4,
+ 60,43,46);b=b%100;}q((b/10)*4,60,47,46);q((b%10)*4,60,51,46);}if(time(
+ NULL)!=y){o=f;f=0;y=time(NULL);}
+#endif
+/* *INDENT-ON* */
+
+ /* actually draw the screen */
+#ifndef BLACKBOX
+ gdk_draw_rgb_image(bm.win, bm.gc, 4, 4, 56, 56,
+ GDK_RGB_DITHER_NONE, bm.rgb_buf, 56 * 3);
+#endif
+ gdk_draw_rgb_image(bm.iconwin, bm.gc, 4, 4, 56, 56,
+ GDK_RGB_DITHER_NONE, bm.rgb_buf, 56 * 3);
+#ifdef ENABLE_MEMSCREEN
+ /* update graph histories */
+ if (memscreen_enabled)
+ roll_history();
+#endif /* ENABLE_MEMSCREEN */
+ }
+ return 0;
+} /* main */
+
+/*
+ * This determines if the left or right shift keys are depressed.
+ */
+static int get_screen_selection(void)
+{
+ static KeyCode lshift_code, rshift_code;
+ static int first_time = 1;
+ char keys[32];
+
+ if (first_time) {
+ first_time = 0;
+ lshift_code = XKeysymToKeycode(GDK_WINDOW_XDISPLAY(bm.win),
+ XStringToKeysym("Shift_L"));
+ rshift_code = XKeysymToKeycode(GDK_WINDOW_XDISPLAY(bm.win),
+ XStringToKeysym("Shift_R"));
+ }
+
+ XQueryKeymap(GDK_WINDOW_XDISPLAY(bm.win), keys);
+
+#if 0
+ if (0) { /* debug */
+ int i = 0;
+ printf("lshift_code = 0x%x (index = %d, bit = %d\n", lshift_code,
+ lshift_code >> 3, lshift_code % 8);
+ printf("rshift_code = 0x%x (index = %d, bit = %d\n", rshift_code,
+ rshift_code >> 3, rshift_code % 8);
+ for (i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) {
+ if (0 == (i % 8)) {
+ printf("\n%2d:", i);
+ }
+ printf(" %2d", keys[i]);
+ }
+ printf("\n");
+ }
+#endif
+
+ if ((keys[lshift_code >> 3] == (1 << (lshift_code % 8))) ||
+ (keys[rshift_code >> 3] == (1 << (rshift_code % 8)))) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/* This is the function that actually creates the display widgets */
+static void make_new_bubblemon_dockapp(void)
+{
+#define MASK GDK_BUTTON_PRESS_MASK | \
+ GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK
+
+ GdkWindowAttr attr;
+ GdkWindowAttr attri;
+ Window win;
+ Window iconwin;
+
+ XSizeHints sizehints;
+ XWMHints wmhints;
+
+ attr.width = 64;
+ attr.height = 64;
+ attr.title = "bubblemon";
+ attr.event_mask = MASK;
+ attr.wclass = GDK_INPUT_OUTPUT;
+ attr.visual = gdk_visual_get_system();
+ attr.colormap = gdk_colormap_get_system();
+ attr.wmclass_name = "bubblemon";
+ attr.wmclass_class = "bubblemon";
+ attr.window_type = GDK_WINDOW_TOPLEVEL;
+
+ sizehints.flags = USSize;
+ sizehints.width = 64;
+ sizehints.height = 64;
+
+ bm.win = gdk_window_new(NULL, &attr,
+ GDK_WA_TITLE | GDK_WA_WMCLASS |
+ GDK_WA_VISUAL | GDK_WA_COLORMAP);
+ if (!bm.win)
+ fprintf(stderr, "Cannot make toplevel window\n");
+
+ attri.width = 64;
+ attri.height = 64;
+ attri.title = "bubblemon";
+ attri.event_mask = MASK;
+ attri.wclass = GDK_INPUT_OUTPUT;
+ attri.visual = gdk_visual_get_system();
+ attri.colormap = gdk_colormap_get_system();
+ attri.wmclass_name = "bubblemon";
+ attri.wmclass_class = "bubblemon";
+ attri.window_type = GDK_WINDOW_TOPLEVEL;
+
+ bm.iconwin = gdk_window_new(bm.win, &attri,
+ GDK_WA_TITLE | GDK_WA_WMCLASS);
+ if (!bm.iconwin)
+ fprintf(stderr, "Cannot make icon window\n");
+
+ win = GDK_WINDOW_XWINDOW(bm.win);
+ iconwin = GDK_WINDOW_XWINDOW(bm.iconwin);
+ XSetWMNormalHints(GDK_WINDOW_XDISPLAY(bm.win), win, &sizehints);
+
+ wmhints.initial_state = WithdrawnState;
+ wmhints.icon_window = iconwin;
+ wmhints.icon_x = 0;
+ wmhints.icon_y = 0;
+ wmhints.window_group = win;
+ wmhints.flags =
+ StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
+ XSetWMHints(GDK_WINDOW_XDISPLAY(bm.win), win, &wmhints);
+
+ bm.gc = gdk_gc_new(bm.win);
+
+ bm.pixmap =
+ gdk_pixmap_create_from_xpm_d(bm.win, &(bm.mask), NULL, master_xpm);
+ gdk_window_shape_combine_mask(bm.win, bm.mask, 0, 0);
+ gdk_window_shape_combine_mask(bm.iconwin, bm.mask, 0, 0);
+
+ gdk_window_set_back_pixmap(bm.win, bm.pixmap, False);
+ gdk_window_set_back_pixmap(bm.iconwin, bm.pixmap, False);
+
+ gdk_window_show(bm.win);
+#ifdef KDE_DOCKAPP
+ /* makes the dockapp visible inside KDE wm */
+ gdk_window_show(bm.iconwin);
+#endif
+
+ /* We begin with zero bubbles */
+ bm.n_bubbles = 0;
+
+ /* Allocate memory for calculations */
+ bubblemon_allocate_buffers();
+
+ bubblemon_setup_samples();
+
+ bubblemon_setup_colors();
+#undef MASK
+} /* make_new_bubblemon_dockapp */
+
+/*
+ * This function, bubblemon_update, gets the CPU usage and updates
+ * the bubble array and main rgb buffer.
+ */
+static void bubblemon_update(int proximity)
+{
+ Bubble *bubbles = bm.bubbles;
+ unsigned int i, loadPercentage, *col, x, y;
+ unsigned char *ptr, *buf, *buf_ptr;
+ unsigned int aircolor, watercolor, aliascolor;
+ unsigned int waterlevels_goal;
+ /*int current_waterlevel_goal; */
+
+ /* These values are for keeping track of where we have to start
+ drawing water. */
+ unsigned int waterlevel_min, waterlevel_max;
+ unsigned int real_waterlevel_min, real_waterlevel_max;
+
+ /* These values are for keeping track how deep the duck is inside water */
+ unsigned int action_min = 56;
+ static unsigned int last_action_min = 0;
+
+ /* Find out the CPU load */
+ loadPercentage = system_cpu();
+
+#ifdef ENABLE_MEMSCREEN
+ /* get loadavg */
+ if (memscreen_enabled)
+ system_loadavg();
+#endif /* ENABLE_MEMSCREEN */
+
+ /*
+ The buf is made up of ints (0-(NUM_COLORS-1)), each pointing out
+ an entry in the color table. A pixel in the buf is accessed
+ using the formula buf[row * w + column].
+ */
+
+
+ /* y coordinates are counted from here multiplied by 256 */
+ /* to get actual screen coordinate, divide by 256 */
+ buf = bm.bubblebuf;
+ col = bm.colors;
+
+ waterlevel_max = 0;
+ waterlevel_min = MAKEY(56);
+
+ /* Move the water level with the current memory usage. */
+ waterlevels_goal = MAKEY(56) - ((bm.mem_percent * MAKEY(56)) / 100);
+
+ /* Guard against boundary errors */
+ waterlevels_goal -= (1 << (POWER2 - 1));
+
+ bm.waterlevels[0] = waterlevels_goal;
+ bm.waterlevels[55] = waterlevels_goal;
+
+ for (x = 1; x < 55; x++) {
+ /* Accelerate the current waterlevel towards its correct value */
+ bm.waterlevels_dy[x] +=
+ (((bm.waterlevels[x - 1] + bm.waterlevels[x + 1] -
+ 2 * bm.waterlevels[x]) * bm.volatility_int) >> (POWER2 +
+ 1));
+
+ bm.waterlevels_dy[x] *= bm.viscosity_int;
+ bm.waterlevels_dy[x] >>= POWER2;
+
+ if (bm.waterlevels_dy[x] > bm.speed_limit_int)
+ bm.waterlevels_dy[x] = bm.speed_limit_int;
+ else if (bm.waterlevels_dy[x] < -bm.speed_limit_int)
+ bm.waterlevels_dy[x] = -bm.speed_limit_int;
+ }
+
+ for (x = 1; x < 55; x++) {
+ /* Move the current water level */
+ bm.waterlevels[x] = bm.waterlevels[x] + bm.waterlevels_dy[x];
+
+ if (bm.waterlevels[x] > MAKEY(56)) {
+ /* Stop the wave if it hits the floor... */
+ bm.waterlevels[x] = MAKEY(56);
+ bm.waterlevels_dy[x] = 0;
+ } else if (bm.waterlevels[x] < 0) {
+ /* ... or the ceiling. */
+ bm.waterlevels[x] = 0;
+ bm.waterlevels_dy[x] = 0;
+ }
+ /* Keep track of the highest and lowest water levels */
+ if (bm.waterlevels[x] > waterlevel_max)
+ waterlevel_max = bm.waterlevels[x];
+ if (bm.waterlevels[x] < waterlevel_min)
+ waterlevel_min = bm.waterlevels[x];
+ }
+
+ real_waterlevel_min = REALY(waterlevel_min);
+ real_waterlevel_max = REALY(waterlevel_max);
+
+ if (action_min > real_waterlevel_min)
+ action_min = real_waterlevel_min;
+
+ /*
+ Vary the colors of air and water with how many
+ percent of the available swap space that is in use.
+ 32 = (99_numcolors / 3) - 1
+ */
+
+ watercolor = ((32 * bm.swap_percent) / 100) * 3;
+ aliascolor = watercolor + 1;
+ aircolor = watercolor + 2;
+
+ /*
+ Draw the air-and-water background
+
+ The waterlevel_max is the HIGHEST VALUE for the water level, which is
+ actually the LOWEST VISUAL POINT of the water. Confusing enough?
+
+ So we want to draw from top to bottom:
+ Just air from (y == 0) to (y <= waterlevel_min)
+ Mixed air and water from (y == waterlevel_min) to (y <= waterlevel_max)
+ Just water from (y == waterlevel_max) to (y <= h)
+
+ Three loops is more code than one, but should be faster (fewer comparisons)
+ */
+
+ /* Air only */
+ memset(buf, aircolor, real_waterlevel_min * 56);
+
+ /* Air and water */
+ for (x = 0; x < 56; x++) {
+ /* Air... */
+ for (y = real_waterlevel_min;
+ (signed) y < REALY(bm.waterlevels[x]); y++)
+ buf[y * 56 + x] = aircolor;
+
+ /* ... and water */
+ for (; y < real_waterlevel_max; y++)
+ buf[y * 56 + x] = watercolor;
+ }
+
+ /* Water only */
+ memset(buf + real_waterlevel_max * 56, watercolor,
+ (56 - real_waterlevel_max) * 56);
+
+ /*
+ Here comes the bubble magic. Pixels are drawn by setting values in
+ buf to 0-NUM_COLORS.
+ */
+
+ /* Create a new bubble if the planets are correctly aligned... */
+ if ((bm.n_bubbles < bm.maxbubbles)
+ && ((rand() % 101) <= loadPercentage)) {
+ /* We don't allow bubbles on the edges 'cause we'd have to clip them */
+ bubbles[bm.n_bubbles].x = (rand() % 54) + 1;
+ bubbles[bm.n_bubbles].y = MAKEY(56) - 256;
+ bubbles[bm.n_bubbles].dy = 0;
+#ifdef DEBUG_DUCK
+ fprintf (stderr, "new bubble: bubbles[bm.n_bubbles].x = %i\n",
+ bubbles[bm.n_bubbles].x);
+#endif
+
+ if (bm.ripples_int != 0) {
+ /* Raise the water level above where the bubble is created */
+ if (bubbles[bm.n_bubbles].x > 2)
+ bm.waterlevels[bubbles[bm.n_bubbles].x - 2] -=
+ bm.ripples_int;
+ bm.waterlevels[bubbles[bm.n_bubbles].x - 1] -= bm.ripples_int;
+ bm.waterlevels[bubbles[bm.n_bubbles].x] -= bm.ripples_int;
+ bm.waterlevels[bubbles[bm.n_bubbles].x + 1] -= bm.ripples_int;
+ if (bubbles[bm.n_bubbles].x < 53)
+ bm.waterlevels[bubbles[bm.n_bubbles].x + 2] -=
+ bm.ripples_int;
+ }
+
+ /* Count the new bubble */
+ bm.n_bubbles++;
+ }
+
+ /* Update and draw the bubbles */
+ for (i = 0; i < bm.n_bubbles; i++) {
+ /* Accelerate the bubble */
+ bubbles[i].dy -= bm.gravity_int;
+
+ /* Move the bubble vertically */
+ bubbles[i].y += bubbles[i].dy;
+
+ /* is the bubble grossly out of bounds? */
+ if (bubbles[i].x < 1 || bubbles[i].x > 54 ||
+ bubbles[i].y > MAKEY(56)) {
+#ifdef DEBUG_DUCK
+ fprintf (stderr, "bubble out of bounds "
+ "bubbles[%i].x=%i, bubbles[%i].y=%i\n",
+ i, bubbles[i].x, i, bubbles[i].y);
+#endif
+
+ /* Yes; nuke it */
+ bubbles[i].x = bubbles[bm.n_bubbles - 1].x;
+ bubbles[i].y = bubbles[bm.n_bubbles - 1].y;
+ bubbles[i].dy = bubbles[bm.n_bubbles - 1].dy;
+ bm.n_bubbles--;
+
+ /*
+ We must check the previously last bubble, which is
+ now the current bubble, also.
+ */
+ i--;
+ continue;
+ }
+
+ /* Did we lose it? */
+ if (bubbles[i].y < bm.waterlevels[bubbles[i].x]) {
+ if (bm.ripples_int != 0) {
+ /* Lower the water level around where the bubble is
+ about to vanish */
+ bm.waterlevels[bubbles[i].x - 1] += bm.ripples_int;
+ bm.waterlevels[bubbles[i].x] += 3 * bm.ripples_int;
+ bm.waterlevels[bubbles[i].x + 1] += bm.ripples_int;
+ }
+
+ /* Yes; nuke it */
+ bubbles[i].x = bubbles[bm.n_bubbles - 1].x;
+ bubbles[i].y = bubbles[bm.n_bubbles - 1].y;
+ bubbles[i].dy = bubbles[bm.n_bubbles - 1].dy;
+ bm.n_bubbles--;
+
+ /*
+ We must check the previously last bubble, which is
+ now the current bubble, also.
+ */
+ i--;
+ continue;
+ }
+
+ /* Draw the bubble */
+ x = bubbles[i].x;
+ y = bubbles[i].y;
+
+ /*
+ Clipping is not necessary for x, but it *is* for y.
+ To prevent ugliness, we draw aliascolor only on top of
+ watercolor, and aircolor on top of aliascolor.
+ */
+
+ /* Top row */
+ buf_ptr = &(buf[(((REALY(y) - 1) * 56) + 56) + x - 1]);
+ if (y > bm.waterlevels[x]) {
+ if (*buf_ptr != aircolor) {
+ (*buf_ptr)++;
+ }
+ buf_ptr++;
+
+ *buf_ptr = aircolor;
+ buf_ptr++;
+
+ if (*buf_ptr != aircolor) {
+ (*buf_ptr)++;
+ }
+ buf_ptr += 54;
+ } else {
+ buf_ptr += 56;
+ }
+
+ /* Middle row - no clipping necessary */
+ *buf_ptr = aircolor;
+ buf_ptr++;
+ *buf_ptr = aircolor;
+ buf_ptr++;
+ *buf_ptr = aircolor;
+ buf_ptr += 54;
+
+ /* Bottom row */
+ if (y < (MAKEY(56) - 256)) {
+ if (*buf_ptr != aircolor) {
+ (*buf_ptr)++;
+ }
+ buf_ptr++;
+
+ *buf_ptr = aircolor;
+ buf_ptr++;
+
+ if (*buf_ptr != aircolor) {
+ (*buf_ptr)++;
+ }
+ }
+ }
+
+ /* Drawing magic resides below this point */
+ ptr = bm.rgb_buf;
+ buf_ptr = buf;
+ i = 56 * 56;
+
+ while (i--) {
+ unsigned char *rgb = (unsigned char *) &col[*buf_ptr++];
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || defined(_LITTLE_ENDIAN) || (BYTE_ORDER == LITTLE_ENDIAN)
+ *ptr++ = rgb[2];
+ *ptr++ = rgb[1];
+ *ptr++ = rgb[0];
+#else /* big-endian. */
+ *ptr++ = rgb[1];
+ *ptr++ = rgb[2];
+ *ptr++ = rgb[3];
+#endif
+ }
+#ifdef ENABLE_DUCK
+ if (duck_enabled) {
+ duck_swimmer((last_action_min <
+ action_min) ? last_action_min - 14 : action_min -
+ 14);
+ }
+#endif
+
+ /* damn, thats ugly. Of course, the first solution that comes to mind
+ * about this isn't the right one :) */
+#if defined(ENABLE_CPU) && defined(ENABLE_MEMSCREEN)
+ if (cpu_enabled || memscreen_enabled) {
+ realtime_alpha_blend_of_cpu_usage(loadPercentage, proximity);
+ }
+#endif
+#if defined(ENABLE_CPU) && !defined(ENABLE_MEMSCREEN)
+ if (cpu_enabled) {
+ realtime_alpha_blend_of_cpu_usage(loadPercentage, proximity);
+ }
+#endif
+#if !defined(ENABLE_CPU) && defined(ENABLE_MEMSCREEN)
+ if (memscreen_enabled) {
+ realtime_alpha_blend_of_cpu_usage(loadPercentage, proximity);
+ }
+#endif
+
+ /* Remember where we have been poking around this round */
+ last_action_min = action_min;
+} /* bubblemon_update */
+
+#ifdef ENABLE_MEMSCREEN
+/* draws 4x8 digits for the memory/swap panel */
+static void draw_digit(int srcx, int srcy, int destx, int desty)
+{
+ int i, j;
+ char *from, *to;
+
+ for (j = 0; j < 8; j++) {
+ from = mem_screen + 56 * 3 * (srcy + j) + srcx * 3;
+ to = bm.mem_buf + 56 * 3 * (desty + j) + destx * 3;
+ i = 12;
+ while (i--)
+ *to++ = *from++;
+ }
+}
+
+/* draws a string using previous function. non-digits and non-K/M = space */
+static void draw_string(char *string, int x, int y, int color)
+{
+ unsigned char c;
+
+ while ((c = *string++)) {
+ if (c == 'K') {
+ draw_digit(40, (color) ? 69 : 60, x, y);
+ } else if (c == 'M') {
+ draw_digit(44, (color) ? 69 : 60, x, y);
+ } else if (c == ' ') {
+ draw_digit(50, 60, x, y); /* blank space */
+ } else {
+ c -= '0';
+ draw_digit(c * 4, (color) ? 69 : 60, x, y);
+ }
+ x += 4;
+ }
+}
+
+static void draw_pixel(unsigned int x, unsigned int y, unsigned char *buf,
+ unsigned char *c)
+{
+ unsigned char *ptr;
+ ptr = buf + y * 56 * 3 + x * 3 + 6; /* +6 = x + 2 */
+ *ptr++ = *c++;
+ *ptr++ = *c++;
+ *ptr++ = *c++;
+}
+
+/* draw graph num x size, data taken from history, into rgb buffer buf.
+ * this is called not very often: only 1 time out of 250 */
+static void draw_history(int num, int size, unsigned int *history,
+ unsigned char *buf)
+{
+ int pixels_per_byte;
+ int j, k;
+ int *p;
+ int d;
+
+ pixels_per_byte = 100;
+ p = history;
+
+ for (j = 0; j < num; j++) {
+ if (p[0] > pixels_per_byte)
+ pixels_per_byte += 100;
+ p++;
+ }
+
+ p = history;
+
+ for (k = 0; k < num; k++) {
+ d = (1.0 * p[0] / pixels_per_byte) * size;
+
+ for (j = 0; j < size; j++) {
+ if (j < d - 2)
+ draw_pixel(k, size - j - 1, buf, "\x00\x7d\x71");
+ else if (j < d)
+ draw_pixel(k, size - j - 1, buf, "\x20\xb6\xae");
+ }
+ p++;
+ }
+
+ for (j = pixels_per_byte - 100; j > 0; j -= 100) {
+ for (k = 0; k < num; k++) {
+ d = ((float) size / pixels_per_byte) * j;
+ draw_pixel(k, size - d - 1, buf, "\x71\xe3\x71");
+ }
+ }
+}
+
+/* refreshes memory/swap screen */
+static void render_secondary(void)
+{
+ char percent[4];
+ char number[8];
+ int i;
+ /* mem: 2, 24
+ * mem %: 38, 24
+ * swap: 2, 43
+ * 38, 43
+ * digits: 0, 60 and 0, 69 */
+
+ /* make a clean buffer with blank spaces. */
+ memcpy(bm.mem_buf, bm.screen_type ? load_screen : mem_screen,
+ 56 * 56 * 3);
+
+ if (bm.screen_type) {
+ for (i = 0; i < 3; i++) {
+ sprintf(number, "%2d", bm.loadavg[i].i);
+ draw_string(number, 19 * i, 8, 0);
+ sprintf(number, "%02d", bm.loadavg[i].f);
+ draw_string(number, 19 * i + 10, 8, 0);
+ }
+ /* copy history graph from previous rollover */
+ memcpy(bm.mem_buf + 19 * 56 * 3, bm.his_bufb, 56 * 33 * 3);
+ } else {
+ /* draw memory */
+ if (memscreen_megabytes)
+ snprintf(number, 8, "%6lluM", bm.mem_used >> 20);
+ else
+ snprintf(number, 8, "%6lluK", bm.mem_used >> 10);
+ snprintf(percent, 4, "%03d", bm.mem_percent);
+ draw_string(number, 2, 1, (bm.mem_percent > 90) ? 1 : 0);
+ draw_string(percent, 38, 1, (bm.mem_percent > 90) ? 1 : 0);
+
+ /* draw swap */
+ if (memscreen_megabytes)
+ snprintf(number, 8, "%6lluM", bm.swap_used >> 20);
+ else
+ snprintf(number, 8, "%6lluK", bm.swap_used >> 10);
+ snprintf(percent, 4, "%03d", bm.swap_percent);
+ draw_string(number, 2, 10, (bm.swap_percent > 90) ? 1 : 0);
+ draw_string(percent, 38, 10, (bm.swap_percent > 90) ? 1 : 0);
+
+ /* copy history graph from previous rollover */
+ memcpy(bm.mem_buf + 21 * 56 * 3, bm.his_bufa, 56 * 31 * 3);
+ }
+}
+
+static void roll_membuffer(void)
+{
+ static int delay;
+
+ if (++delay < 30)
+ return;
+
+ delay = 0;
+ render_secondary();
+}
+
+static void roll_history(void)
+{
+ unsigned int yep, j;
+ static int update, doit;
+
+ if (doit-- <= 0) {
+ doit = ROLLVALUE;
+ if (update-- <= 0) {
+
+ /* roll history buffers, averaging last 5 samples */
+ if (bm.history[52])
+ bm.history[52] /= bm.hisadd;
+
+ if (bm.memhist[52])
+ bm.memhist[52] /= bm.memadd;
+
+ for (j = 1; j < 53; j++) {
+ bm.history[j - 1] = bm.history[j];
+ bm.memhist[j - 1] = bm.memhist[j];
+ }
+ bm.history[52] = 0;
+ bm.hisadd = 0;
+ bm.memhist[52] = 0;
+ bm.memadd = 0;
+
+ /* refresh backgrounds */
+ memcpy(bm.his_bufa, mem_screen + 21 * 56 * 3, 31 * 56 * 3);
+ memcpy(bm.his_bufb, load_screen + 19 * 56 * 3, 33 * 56 * 3);
+
+ /* render memory graph */
+ draw_history(52, 31, bm.memhist, bm.his_bufa);
+ /* render load average graph */
+ draw_history(52, 33, bm.history, bm.his_bufb);
+
+ /* reset counter */
+ update = 5;
+ }
+
+ /* do load average history update */
+ yep = bm.loadavg[0].f + (bm.loadavg[0].i * 100);
+ bm.history[52] += yep;
+ bm.hisadd++;
+
+ /* do memory history update */
+ yep = bm.mem_percent;
+ bm.memhist[52] += yep;
+ bm.memadd++;
+ }
+}
+#endif /* ENABLE_MEMSCREEN */
+
+#ifdef ENABLE_CPU
+/* draws digits for the CPU meter. This function is very specific
+ * to the meter. Arguments it takes are not what they seem initially */
+static void draw_cpudigit(const int what, const int where,
+ unsigned char *kit)
+{
+ unsigned int len, y;
+ unsigned char *to, *from;
+ for (y = 0; y < 9; y++) {
+ len = 21;
+ to = kit + y * 75 + where;
+ from = digits + y * 285 + what;
+ while (len--)
+ *to++ = *from++;
+ }
+}
+#endif /* ENABLE_CPU */
+
+#if defined(ENABLE_CPU) || defined(ENABLE_MEMSCREEN)
+static void realtime_alpha_blend_of_cpu_usage(int cpu, int proximity)
+{
+ /* where is the text going to be (now, bottom-center) */
+#define POSX 16
+#define POSY 46
+ int bob;
+
+ /* memory window */
+ static int blend = MAXBLEND;
+#ifdef ENABLE_MEMSCREEN
+ static int memblend = 256;
+ static int showmem = 0;
+#endif /* ENABLE_MEMSCREEN */
+#ifdef ENABLE_CPU
+ static int yoh;
+ static int avg;
+ int hibyte, y, pos;
+
+ /* CPU load buffer */
+ static unsigned char kit[25 * 3 * 9 + 1];
+ unsigned char *kitptr;
+
+ /* the plan is simple. we don't want to redraw the digits every update
+ * because that doesn't look so good. so we average it, and draw only
+ * once every 10 updates. We alpha blend the static buffer so we still
+ * get cool transparency effects. */
+ avg += cpu;
+
+ while (++yoh > 10) {
+ cpu = avg / 10;
+ avg ^= avg; /* zero. Haha, I guess these are not */
+ yoh ^= yoh; /* register vars, optimizer just zeros them */
+ hibyte = cpu / 10; /* but it's cool to know it understands xor a, a */
+ if (hibyte == 10) {
+ draw_cpudigit(18, 0, kit);
+ draw_cpudigit(0, 18, kit);
+ draw_cpudigit(0, 36, kit);
+ } else {
+ draw_cpudigit(216, 0, kit);
+ draw_cpudigit(hibyte * 18, 18, kit);
+ draw_cpudigit((cpu % 10) * 18, 36, kit);
+ }
+ /* percent sign is always there */
+ draw_cpudigit(180, 54, kit);
+ }
+#endif /* ENABLE_CPU */
+ /* sexy fade effect */
+ if (proximity) {
+ blend -= 4;
+ if (blend < MINBLEND) {
+ blend = MINBLEND;
+#ifdef ENABLE_MEMSCREEN
+ if (memscreen_enabled) {
+ if (!showmem) {
+ /* first time here, update memory stats */
+ render_secondary();
+ }
+ showmem = 1;
+ if (!bm.picture_lock)
+ memblend -= 6;
+ if (memblend < 40) {
+ roll_membuffer();
+ memblend = 40;
+ }
+ }
+#endif /* ENABLE_MEMSCREEN */
+ }
+ } else {
+ blend += 4;
+#ifdef ENABLE_MEMSCREEN
+ if (bm.picture_lock)
+ roll_membuffer();
+
+ if (memscreen_enabled && !bm.picture_lock)
+ memblend += 10;
+#endif /* ENABLE_MEMSCREEN */
+ if (blend > MAXBLEND) {
+ blend = MAXBLEND;
+ }
+#ifdef ENABLE_MEMSCREEN
+ if (memscreen_enabled && memblend > 256) {
+ memblend = 256;
+ showmem = 0;
+ }
+#endif /* ENABLE_MEMSCREEN */
+ }
+
+#ifdef ENABLE_CPU
+ if (cpu_enabled) {
+ /* bit shifts result in smaller and faster code without an extra jns
+ * which appears if we / 128 instead of >> 7.
+ */
+ kitptr = kit;
+ for (y = 0; y < 9; y++) {
+ unsigned char src;
+ pos = (y + POSY) * 56 * 3 + (POSX * 3);
+ bob = 75; /* 25 * 3 */
+ while (bob--) {
+ src = bm.rgb_buf[pos];
+
+ if (!src)
+ bm.rgb_buf[pos++] = *kitptr++;
+ else
+ bm.rgb_buf[pos++] =
+ (blend * src + (256 - blend) * *kitptr++) >> 8;
+ }
+ }
+ }
+#endif /* ENABLE_CPU */
+
+#ifdef ENABLE_MEMSCREEN
+ /* we hovered long enough to print some memory info */
+ if (memscreen_enabled && showmem) {
+ unsigned char *ptr, *ptr2, src;
+ ptr = bm.mem_buf;
+ ptr2 = bm.rgb_buf;
+ bob = 9408; /* 56 * 56 * 3 */
+ while (bob--) {
+ src = *ptr2;
+ *ptr2++ = (memblend * src + (256 - memblend) * *ptr++) >> 8;
+ }
+ }
+#endif /* ENABLE_MEMSCREEN */
+#undef POSY
+#undef POSX
+}
+#endif
+
+#ifdef ENABLE_DUCK
+static void duck_set(int x, int y, int nr, int rev, int upsidedown)
+{
+ int w, h;
+ int rw;
+#ifdef UPSIDE_DOWN_DUCK
+ int rh;
+#endif
+ int pos;
+ int dw, di, dh, ds;
+ int cmap; /* index into duck colors */
+#define _R(idx) ((int)duck_cmap[idx][0])
+#define _G(idx) ((int)duck_cmap[idx][1])
+#define _B(idx) ((int)duck_cmap[idx][2])
+#define GETME(x, y, idx) ((int)duck_data[idx][y * 18 + x])
+ ds = 0;
+ if (y < 0)
+ ds = -(y);
+ dh = 17;
+ if ((y + 17) > 56)
+ dh = 56 - y;
+ dw = 18;
+ if (x > 38)
+ dw = 18 - (x - 38);
+ di = 0;
+ if (x < 0)
+ di = -(x);
+ for (h = ds; h < dh; h++) {
+ /* calculate this only once */
+ int ypos = (h + y) * 56;
+#ifdef UPSIDE_DOWN_DUCK
+ rh = (upsidedown && upside_down_duck_enabled) ? 17 - h : h;
+#endif
+ for (w = di; w < dw; w++) {
+ rw = (rev) ? 17 - w : w;
+#ifdef UPSIDE_DOWN_DUCK
+ if ((cmap = GETME(rw, rh, nr)) != 0) {
+#else
+ if ((cmap = GETME(rw, h, nr)) != 0) {
+#endif
+ unsigned char r, g, b;
+ pos = (ypos + w + x) * 3;
+
+ r = _R(cmap);
+ g = _G(cmap);
+ b = _B(cmap);
+
+ /* and now we'll blend the duck part that in water */
+ /* if we use integers here we speed up this function about
+ * 40%. */
+ if (h + y < REALY(bm.waterlevels[w + x])) {
+ bm.rgb_buf[pos++] = r;
+ bm.rgb_buf[pos++] = g;
+ bm.rgb_buf[pos] = b;
+ } else {
+ bm.rgb_buf[pos] = (DUCKBLEND * (int) bm.rgb_buf[pos]
+ + (256 - DUCKBLEND) * (int) r) >> 8;
+ bm.rgb_buf[pos + 1] =
+ (DUCKBLEND * (int) bm.rgb_buf[pos + 1]
+ + (256 - DUCKBLEND) * (int) g) >> 8;
+ bm.rgb_buf[pos + 2] =
+ (DUCKBLEND * (int) bm.rgb_buf[pos + 2]
+ + (256 - DUCKBLEND) * (int) b) >> 8;
+ }
+ }
+ }
+ }
+#undef _R
+#undef _G
+#undef _B
+#undef GETME
+}
+
+static int animate_correctly(void)
+{
+ /* returns the correct order of framenumber 0,1,2,1,0,1,2...
+ instead of 0,1,2,0,1,2 <- this way the duck looks really ugly
+ instead of keeping 2 counters we just made it longer */
+
+ static int outp[48] =
+ { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
+ 2, 2, 1, 1, 1, 1
+ };
+ static int totalcounter = -1;
+
+ if (++totalcounter > 47)
+ totalcounter = 0;
+
+ return outp[totalcounter];
+}
+
+static void duck_swimmer(int posy)
+{
+ static int tx = -19;
+ static int rp;
+ static int rev = 1;
+ static int upsidedown = 0;
+
+#ifdef UPSIDE_DOWN_DUCK
+ /* dive */
+ if (upside_down_duck_enabled) {
+ if (upsidedown == 0 && posy < 2)
+ upsidedown = 1;
+ else if (upsidedown == 1 && posy > 5) /* jump out */
+ upsidedown = 0;
+
+ if (upsidedown)
+ posy += 10;
+ }
+#endif
+ if (rp++ < 10) {
+ duck_set(tx, posy, animate_correctly(), rev, upsidedown);
+ return;
+ }
+
+ rp = 0;
+ if (!rev) {
+ if (tx-- < -18) {
+ tx = -18;
+ rev = 1;
+ }
+ } else {
+ if (tx++ > 57) {
+ tx = 57;
+ rev = 0;
+ }
+ }
+ duck_set(tx, posy, animate_correctly(), rev, upsidedown);
+}
+#endif /* ENABLE_DUCK */
+
+static void bubblemon_setup_samples(void)
+{
+ int i;
+ u_int64_t load = 0, total = 0;
+
+ if (bm.load) {
+ load = bm.load[bm.loadIndex];
+ free(bm.load);
+ }
+
+ if (bm.total) {
+ total = bm.total[bm.loadIndex];
+ free(bm.total);
+ }
+
+ bm.loadIndex = 0;
+ bm.load = malloc(bm.samples * sizeof(u_int64_t));
+ bm.total = malloc(bm.samples * sizeof(u_int64_t));
+ for (i = 0; i < bm.samples; i++) {
+ bm.load[i] = load;
+ bm.total[i] = total;
+ }
+}
+
+static void bubblemon_setup_colors(void)
+{
+#define NUM_COLORS 99
+ int i, j, *col;
+ int r_air_noswap, g_air_noswap, b_air_noswap;
+ int r_liquid_noswap, g_liquid_noswap, b_liquid_noswap;
+ int r_air_maxswap, g_air_maxswap, b_air_maxswap;
+ int r_liquid_maxswap, g_liquid_maxswap, b_liquid_maxswap;
+ int actual_colors = NUM_COLORS / 3;
+
+ if (!bm.colors)
+ bm.colors = malloc(NUM_COLORS * sizeof(int));
+
+ col = bm.colors;
+
+ r_air_noswap = (bm.air_noswap >> 16) & 0xff;
+ g_air_noswap = (bm.air_noswap >> 8) & 0xff;
+ b_air_noswap = (bm.air_noswap) & 0xff;
+
+ r_liquid_noswap = (bm.liquid_noswap >> 16) & 0xff;
+ g_liquid_noswap = (bm.liquid_noswap >> 8) & 0xff;
+ b_liquid_noswap = (bm.liquid_noswap) & 0xff;
+
+ r_air_maxswap = (bm.air_maxswap >> 16) & 0xff;
+ g_air_maxswap = (bm.air_maxswap >> 8) & 0xff;
+ b_air_maxswap = (bm.air_maxswap) & 0xff;
+
+ r_liquid_maxswap = (bm.liquid_maxswap >> 16) & 0xff;
+ g_liquid_maxswap = (bm.liquid_maxswap >> 8) & 0xff;
+ b_liquid_maxswap = (bm.liquid_maxswap) & 0xff;
+
+ for (i = 0; i < actual_colors; i++) {
+ int r, g, b;
+ int r_composite, g_composite, b_composite;
+
+ j = i >> 1;
+
+ /* Liquid */
+ r = (r_liquid_maxswap * j +
+ r_liquid_noswap * ((actual_colors - 1) -
+ j)) / (actual_colors - 1);
+ g = (g_liquid_maxswap * j +
+ g_liquid_noswap * ((actual_colors - 1) -
+ j)) / (actual_colors - 1);
+ b = (b_liquid_maxswap * j +
+ b_liquid_noswap * ((actual_colors - 1) -
+ j)) / (actual_colors - 1);
+
+ r_composite = r;
+ g_composite = g;
+ b_composite = b;
+ col[(i * 3)] = (r << 16) | (g << 8) | b;
+
+ /* Air */
+ r = (r_air_maxswap * j +
+ r_air_noswap * ((actual_colors - 1) - j)) / (actual_colors -
+ 1);
+ g = (g_air_maxswap * j +
+ g_air_noswap * ((actual_colors - 1) - j)) / (actual_colors -
+ 1);
+ b = (b_air_maxswap * j +
+ b_air_noswap * ((actual_colors - 1) - j)) / (actual_colors -
+ 1);
+ r_composite += r;
+ g_composite += g;
+ b_composite += b;
+ col[(i * 3) + 2] = (r << 16) | (g << 8) | b;
+
+ /* Anti-alias */
+ r = r_composite >> 1;
+ g = g_composite >> 1;
+ b = b_composite >> 1;
+ col[(i * 3) + 1] = (r << 16) | (g << 8) | b;
+ }
+#undef NUM_COLORS
+}
+
+static void bubblemon_allocate_buffers(void)
+{
+ int i;
+
+ /* storage for bubbles */
+ bm.bubbles = (Bubble *) malloc(sizeof(Bubble) * bm.maxbubbles);
+
+ /* Allocate (zeroed) bubble memory */
+ if (bm.bubblebuf)
+ free(bm.bubblebuf);
+
+ bm.bubblebuf = calloc(56 * 60, sizeof(char));
+
+ /* Allocate water level memory */
+ if (bm.waterlevels)
+ free(bm.waterlevels);
+
+ bm.waterlevels = malloc(56 * sizeof(int));
+ for (i = 0; i < 56; i++) {
+ bm.waterlevels[i] = MAKEY(56);
+ }
+
+ /* Allocate water level velocity memory */
+ if (bm.waterlevels_dy)
+ free(bm.waterlevels_dy);
+
+ bm.waterlevels_dy = calloc(56, sizeof(int));
+}
+
+static void get_memory_load_percentage(void)
+{
+ /* system_memory() will return true on initial run so that we get
+ * correct memory info, but may subsequently return 0 if memory
+ * is not changing */
+ if (system_memory()) {
+ /* new memory/swap data is in, calculate things */
+ bm.mem_percent = (100 * bm.mem_used) / bm.mem_max;
+
+ if (bm.swap_max != 0) {
+ bm.swap_percent = (100 * bm.swap_used) / bm.swap_max;
+ } else {
+ bm.swap_percent = 0;
+ }
+ }
+}
+
+/* ex:set ts=8: */
diff --git a/doc/COPYING b/doc/COPYING
new file mode 100644
index 0000000..6d23ef0
--- /dev/null
+++ b/doc/COPYING
@@ -0,0 +1,3 @@
+#include <GPL.v2>
+On a Debian system, you can find the GPL license in
+/usr/share/common-licenses/GPL
diff --git a/doc/Xdefaults.sample b/doc/Xdefaults.sample
new file mode 100644
index 0000000..f1d5544
--- /dev/null
+++ b/doc/Xdefaults.sample
@@ -0,0 +1,12 @@
+! BubbleMon settings
+! vim: syntax=xdefaults
+bubblemon.maxbubbles: 100
+bubblemon.air_noswap: #2299FF
+bubblemon.air_maxswap: #FF0000
+bubblemon.liquid_noswap: #0055FF
+bubblemon.liquid_maxswap: #AA0000
+bubblemon.ripples: 0.2
+bubblemon.gravity: 0.01
+bubblemon.volatility: 1.0
+bubblemon.viscosity: 0.98
+bubblemon.speed_limit: 1.0
diff --git a/include/bubblemon.h b/include/bubblemon.h
new file mode 100644
index 0000000..1c25016
--- /dev/null
+++ b/include/bubblemon.h
@@ -0,0 +1,139 @@
+/* BubbleMon dockapp 1.2
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _BUBBLEMON_H_
+#define _BUBBLEMON_H_
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+/* CPU load alpha-blending: smaller values = ligher text
+ * minblend = mouseout
+ * maxblend = mousein
+ * min = 0
+ * max = 128 */
+#if defined(ENABLE_CPU) || defined(ENABLE_MEMSCREEN)
+# define MINBLEND 80
+# define MAXBLEND 190
+#endif
+
+#ifdef ENABLE_DUCK
+#define DUCKBLEND 100
+#endif
+
+#define MULTIPLIER 4096.0
+#define POWER2 12
+#define REALY(y) ((y) >> POWER2)
+#define MAKEY(y) ((y) << POWER2)
+#define MAKE_INTEGER(x) ((int)((x)*MULTIPLIER+0.5))
+#define ROLLVALUE 100 /* frequency of history rollover */
+
+#ifdef sun
+#include <sys/types.h>
+#if defined (uint64_t)
+ typedef uint64_t u_int64_t;
+#else
+ typedef unsigned long long u_int64_t;
+#endif /* defined (uint64_t) */
+#endif
+
+typedef struct {
+ int x; /* Horizontal coordinate */
+ int y; /* Vertical coordinate */
+ int dy; /* Vertical velocity */
+} Bubble;
+
+typedef struct {
+ int i; /* integer part */
+ int f; /* fractional part */
+} LoadAvg;
+
+typedef struct {
+ /* X11 stuff */
+ Display *display;
+ GdkWindow *win; /* main window */
+ GdkWindow *iconwin; /* icon window */
+ GdkGC *gc; /* drawing GC */
+ GdkPixmap *pixmap; /* main dockapp pixmap */
+ GdkBitmap *mask; /* dockapp mask */
+
+ /* main image buffer */
+ unsigned char rgb_buf[56 * 56 * 3 + 1];
+
+#ifdef ENABLE_MEMSCREEN
+ /* memory / swap screen buffer */
+ unsigned char mem_buf[56 * 56 * 3 + 1];
+ /* memory screen graph buffer */
+ unsigned char his_bufa[56 * 31 * 3 + 1];
+ /* loadavg screen graph buffer */
+ unsigned char his_bufb[56 * 33 * 3 + 1];
+
+ int screen_type; /* 0 - memory, 1 - cpu */
+ int picture_lock; /* blend coeff not changed when this is not 0 */
+#endif
+
+ /* bubble stuff */
+ int samples;
+ unsigned char *bubblebuf;
+ int *colors;
+ int *waterlevels;
+ int *waterlevels_dy;
+ Bubble *bubbles;
+ int n_bubbles;
+
+ /* Color definitions */
+ int air_noswap, liquid_noswap, air_maxswap, liquid_maxswap;
+
+ /* CPU percentage stuff. soon to go away */
+ int loadIndex;
+ u_int64_t *load, *total;
+
+ /* various params */
+ int maxbubbles; /* max bubbles number */
+ double ripples; /* Do we make ripples on the surface after bubbles? */
+ double gravity; /* How fast do the bubbles rise? */
+ double volatility; /* How fast do the water levels accelerate? */
+ double viscosity; /* 0.0 means the liquid never moves.
+ 1.0 means the liquid will continue to oscillate forever. */
+ double speed_limit; /* How fast are the water levels allowed to move? */
+
+ /* stuff above in integer format */
+ int ripples_int;
+ int gravity_int;
+ int volatility_int;
+ int viscosity_int;
+ int speed_limit_int;
+
+ /* system stuff. Moved here because various places need it */
+ u_int64_t mem_used;
+ u_int64_t mem_max;
+ u_int64_t swap_used;
+ u_int64_t swap_max;
+ unsigned int swap_percent; /* swap used, in percent */
+ unsigned int mem_percent; /* memory used, in percent */
+ /* history of memory use */
+ unsigned int memhist[53];
+ unsigned int memadd;
+
+ /* loadavg stuff */
+ LoadAvg loadavg[3];
+ /* history of loadavgs */
+ unsigned int history[53];
+ unsigned int hisadd;
+} BubbleMonData;
+#endif /* _BUBBLEMON_H_ */
diff --git a/include/digits.h b/include/digits.h
new file mode 100644
index 0000000..9f0f852
--- /dev/null
+++ b/include/digits.h
@@ -0,0 +1,81 @@
+/* digits for the CPU counter */
+unsigned char digits[95 * 9 * 3 + 1] =
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\40\260\254\40\260\254\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0}"
+ "q\0\0\0\0\0\0\0}q\40\260\254\40\260\254\40\260\254\0}q\0\0\0\0}q\40\260\254"
+ "\40\260\254\40\260\254\0}q\0\0\0\0}q\0\0\0\0\0\0\0\0\0\0}q\0\0\0\0}q\40\260"
+ "\254\40\260\254\40\260\254\0}q\0\0\0\0}q\40\260\254\40\260\254\40\260\254"
+ "\0}q\0\0\0\0}q\40\260\254\40\260\254\40\260\254\0}q\0\0\0\0}q\40\260\254"
+ "\40\260\254\40\260\254\0}q\0\0\0\0}q\40\260\254\40\260\254\40\260\254\0}"
+ "q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\40\260\254\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\40\260"
+ "\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0"
+ "\40\260\254\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\40\260\254"
+ "\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254"
+ "\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40"
+ "\260\254\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\40\260\254\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260"
+ "\254\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0}q\0\0\0\0\0\0\0"
+ "\0\0\0}q\0\0\0\0\0\0\0\0\0\0\0\0\0}q\0\0\0\0\0\0\0}q\40\260\254\40\260\254"
+ "\40\260\254\0}q\0\0\0\0\0\0\40\260\254\40\260\254\40\260\254\0}q\0\0\0\0"
+ "}q\40\260\254\40\260\254\40\260\254\0}q\0\0\0\0}q\40\260\254\40\260\254\40"
+ "\260\254\0}q\0\0\0\0}q\40\260\254\40\260\254\40\260\254\0}q\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0}q\0\0\0\0IA\40\260\254\40\260\254\40\260\254\0IA\0\0\0"
+ "\0}q\40\260\254\40\260\254\40\260\254\0}q\0\0\0\0\0\0\0\0\0\40\260\254\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0"
+ "\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\40\260\254\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254"
+ "\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\40\260\254\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\40\260"
+ "\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254"
+ "\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\40\260\254\0\0\0\40\260\254\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\260\254\40\260\254\40\260\254\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\40\260\254\0\0\0\0\0\0\0}q\40\260\254\40\260\254\40"
+ "\260\254\0}q\0\0\0\0}q\40\260\254\40\260\254\40\260\254\0}q\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0}q\0\0\0\0}q\40\260\254\40\260\254\40\260\254\0}q\0\0\0"
+ "\0}q\40\260\254\40\260\254\40\260\254\0}q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "}q\0\0\0\0}q\40\260\254\40\260\254\40\260\254\0}q\0\0\0\0}q\40\260\254\40"
+ "\260\254\40\260\254\0}q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0";
diff --git a/include/ducks.h b/include/ducks.h
new file mode 100644
index 0000000..b09559b
--- /dev/null
+++ b/include/ducks.h
@@ -0,0 +1,59 @@
+static char duck_cmap[4][3] = {
+ { 32,152,248},
+ {248,252, 0},
+ {248,176, 64},
+ { 0, 0, 0}
+ };
+static int duck_data[3][306] = {
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,2,2,2,1,3,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,0,1,1,1,1,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,2,2,2,1,3,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,2,2,2,1,3,1,1,1,1,0,0,0,0,0,0,0,
+ 0,0,0,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
+ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+ 0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0}
+};
diff --git a/include/load_screen.h b/include/load_screen.h
new file mode 100644
index 0000000..0f3cb72
--- /dev/null
+++ b/include/load_screen.h
@@ -0,0 +1,464 @@
+unsigned char load_screen[56 * 80 * 3 + 1] =
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\303"
+ "\0\300\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\0\0\0\300\303\0\300"
+ "\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\300\303\0\300\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300"
+ "\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\300\303\0\0\0\0\300\303\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\303"
+ "\0\300\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\0\0\0\300\303\0\300"
+ "\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300"
+ "\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\0\0\0\0\0\0\300\303\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\300\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\300\303"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\0\0\0\300\303\0\300\303\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\212\356"
+ "0\212\3560\212\356\0\0\0""0\212\3560\212\3560\212\356\0\0\0\0\0\0\0\0\0""0"
+ "\212\3560\212\3560\212\356\0\0\0""0\212\3560\212\3560\212\356\0\0\0\0\0\0"
+ """0\212\3560\212\3560\212\356\0\0\0""0\212\3560\212\3560\212\356\0\0\0\0"
+ "\0\0\0\0\0""0\212\3560\212\3560\212\356\0\0\0""0\212\3560\212\3560\212\356"
+ "\0\0\0\0\0\0""0\212\3560\212\3560\212\356\0\0\0""0\212\3560\212\3560\212"
+ "\356\0\0\0\0\0\0\0\0\0""0\212\3560\212\3560\212\356\0\0\0""0\212\3560\212"
+ "\3560\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0"
+ "\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0"
+ "\0\0""0\212\356\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356"
+ "\0\0\0""0\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0"
+ "\212\356\0\0\0""0\212\356\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0"
+ "\212\356\0\0\0""0\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0"
+ "\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0"
+ """0\212\356\0\0\0""0\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356"
+ "\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356"
+ "\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0"
+ "\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0""0\212\356\0\0\0""0"
+ "\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0"
+ "\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0"
+ """0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0\0\0\0""0\212\356"
+ "\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0""0\212\356"
+ "\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0\0\0\0""0"
+ "\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0""0"
+ "\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0\0"
+ "\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0"
+ """0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0"
+ "\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0"
+ "\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356"
+ "\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0"
+ "\212\356\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0"
+ "\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0"
+ "\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0"
+ """0\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356"
+ "\0\0\0""0\212\356\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356"
+ "\0\0\0""0\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0"
+ "\212\356\0\0\0""0\212\356\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0"
+ "\212\356\0\0\0""0\212\356\0\0\0\0\0\0\0\0\0""0\212\356\0\0\0""0\212\356\0"
+ "\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0"
+ """0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212"
+ "\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0""0\212\356\0\0\0""0\212"
+ "\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356"
+ "\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0\0\0\0""0\212\356"
+ "\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0"
+ "\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0\212\356\0\0\0""0"
+ "\212\3560\212\3560\212\356\0\0\0""0\212\3560\212\3560\212\356\0\0\0""0\212"
+ "\356\0\0\0""0\212\3560\212\3560\212\356\0\0\0""0\212\3560\212\3560\212\356"
+ "\0\0\0\0\0\0""0\212\3560\212\3560\212\356\0\0\0""0\212\3560\212\3560\212"
+ "\356\0\0\0""0\212\356\0\0\0""0\212\3560\212\3560\212\356\0\0\0""0\212\356"
+ "0\212\3560\212\356\0\0\0\0\0\0""0\212\3560\212\3560\212\356\0\0\0""0\212"
+ "\3560\212\3560\212\356\0\0\0""0\212\356\0\0\0""0\212\3560\212\3560\212\356"
+ "\0\0\0""0\212\3560\212\3560\212\356\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\212\3560\212\3560\212\3560\212\3560\212\356"
+ "0\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\356"
+ "0\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\356"
+ "0\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\356"
+ "0\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\356"
+ "0\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\356"
+ "0\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\356\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*"
+ "\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\356\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357"
+ "0\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\3570\213\357"
+ "0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357"
+ "\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213\357\0"
+ "\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0"
+ "\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ """0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0"
+ "\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0"
+ "\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0\0\0\0\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0"
+ """0\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\3570"
+ "\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0"
+ "\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\3570\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0"
+ "\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0"
+ """0\213\357\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ """0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0"
+ "\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213"
+ "\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213\357"
+ "\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0"
+ "\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357"
+ "0\213\3570\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357\0"
+ "\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354"
+ "\27\27\354\27\27\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354"
+ "\27\27\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\0\0\0\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\354\27\27\354"
+ "\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\354\27\27\354"
+ "\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27"
+ "\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0"
+ "\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0"
+ "\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0"
+ "\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0\0"
+ "\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27"
+ "\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354"
+ "\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\354\27"
+ "\27\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27"
+ "\27\354\27\27\0\0\0\0\0\0\354\27\27\354\27\27\0\0\0\354\27\27\0\0\0\354\27"
+ "\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0"
+ "\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0"
+ "\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\0\0"
+ "\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0"
+ "\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0"
+ "\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27"
+ "\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0"
+ "\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0"
+ "\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354"
+ "\27\27\354\27\27\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354"
+ "\27\27\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\0\0"
+ "\0\354\27\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0";
diff --git a/include/master.xpm b/include/master.xpm
new file mode 100644
index 0000000..4941a88
--- /dev/null
+++ b/include/master.xpm
@@ -0,0 +1,71 @@
+/* XPM */
+static char * master_xpm[] = {
+"64 64 4 1",
+" c None",
+". c #000000",
+"+ c #2299FF",
+"@ c #ABBAC6",
+" ",
+" ",
+" ",
+" .......................................................... ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" .++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ",
+" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",
+" ",
+" ",
+" "};
diff --git a/include/mem_screen.h b/include/mem_screen.h
new file mode 100644
index 0000000..12f62ea
--- /dev/null
+++ b/include/mem_screen.h
@@ -0,0 +1,466 @@
+unsigned char mem_screen[56 * 80 * 3 + 1] =
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ """0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\357"
+ "0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213"
+ "\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\3570\213\357"
+ "0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213"
+ "\357\0\0\0""0\213\357\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213"
+ "\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0\0\0\0\300\303\0\300\303\0\300\303\0\300\303\0\0\0\0\0\0\0\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0"
+ "\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213"
+ "\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0\0\0\0\300\303\0\0\0\0\300\303\0\0\0\0\300\303\0\0\0\0\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\3570\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "0\213\357\0\0\0\0\0\0\0\0\0\300\303\0\0\0\0\300\303\0\0\0\0\300\303\0\0\0"
+ "\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0"
+ "\213\3570\213\3570\213\357\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0\0\0\0\300\303\0\0\0\0\300\303\0\0\0\0\300\303\0\0"
+ "\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0"
+ """0\213\357\0\0\0""0\213\357\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ """0\213\357\0\0\0\0\0\0\300\303\0\0\0\0\300\303\0\0\0\0\300\303\0\0\0\0\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0"
+ "\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0"
+ "\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357"
+ "0\213\3570\213\357\0\0\0""0\213\357\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213\357\0"
+ "\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357\0\0\0\0\0\0""0\213\357"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ """0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\300\303\0\300\303\0\300\303\0"
+ "\300\303\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ """0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0\0\0\0\300\303\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ """0\213\3570\213\357\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\300\303\0\300\303"
+ "\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0""0\213\357\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\303\0\0\0\0\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ """0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\300\303\0\300\303\0\300\303\0\300"
+ "\303\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0""0\213\357\0"
+ "\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\3570\213"
+ "\3570\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\357"
+ "0\213\357\0\0\0""0\213\357\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\356\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*"
+ "\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6"
+ "*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0\6*\0"
+ "\6*\0\6*\0\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6"
+ "*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\40\40\40\40\40\40\40\40\6*\0\40\40\40\40\40\40\40\40\40\40"
+ "\40\40\40\40\40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0""0\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212\3560\212"
+ "\3560\212\3560\212\3560\212\3560\212\3560\212\356\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376\376"
+ "\376\376\376\376\376\376\376\376\376\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0"
+ "\0\0\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357"
+ "0\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\3570\213\357"
+ "0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213"
+ "\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ """0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\3570\213\357"
+ "0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357"
+ "\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0\0\0"
+ "\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0"
+ "\0\0\0\0\0\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0"
+ "\0\0""0\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357"
+ "0\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0"
+ "\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0""0\213\3570\213\357\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0"
+ "\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213"
+ "\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ """0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\357"
+ "\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0"
+ "\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0"
+ "\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\213\3570\213\3570\213"
+ "\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0"
+ "\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0\0""0\213\357\0\0\0""0\213"
+ "\3570\213\3570\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0\0\0\0\0\0"
+ "\0""0\213\357\0\0\0""0\213\3570\213\3570\213\357\0\0\0""0\213\3570\213\357"
+ "0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213\357\0\0\0""0\213"
+ "\357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\0"
+ "\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27"
+ "\354\27\27\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27"
+ "\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\354\27\27"
+ "\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\354\27\27"
+ "\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0"
+ "\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0"
+ "\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\0\0\0\0\0"
+ "\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0"
+ "\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354"
+ "\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\354\27"
+ "\27\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\354\27\27\354\27\27\0\0\0\0\0\0\354\27\27\354\27\27\0\0\0\354\27\27\0\0"
+ "\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0"
+ "\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\0\0\0\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27"
+ "\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0"
+ "\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\354\27"
+ "\27\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27"
+ "\27\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0"
+ "\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0"
+ "\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27"
+ "\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354"
+ "\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0"
+ "\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27"
+ "\354\27\27\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27\0\0\0\354\27\27\354\27\27"
+ "\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\0\0\0\0\0\0\354\27\27"
+ "\0\0\0\354\27\27\354\27\27\354\27\27\0\0\0\354\27\27\354\27\27\354\27\27"
+ "\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\354\27\27\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
diff --git a/include/sys_include.h b/include/sys_include.h
new file mode 100644
index 0000000..8597fbd
--- /dev/null
+++ b/include/sys_include.h
@@ -0,0 +1,31 @@
+/* BubbleMon dockapp 1.2
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _SYS_INCLUDE_H_
+#define _SYS_INCLUDE_H_
+
+/* these routines must be written for each new platform */
+int system_cpu(void); /* return total CPU load in percent */
+int system_memory(void); /* set memory related values in BubbleMonData
+ and return 1, or return 0 if memory didn't
+ change */
+#ifdef ENABLE_MEMSCREEN
+void system_loadavg(void); /* get current load average and put into
+ bm->loadavg[].{i,f} */
+#endif
+#endif /* _SYS_INCLUDE_H_ */
diff --git a/misc/load_1.1.xcf b/misc/load_1.1.xcf
new file mode 100644
index 0000000..b3a11aa
Binary files /dev/null and b/misc/load_1.1.xcf differ
diff --git a/misc/mem_1.1.xcf b/misc/mem_1.1.xcf
new file mode 100644
index 0000000..d44f1ef
Binary files /dev/null and b/misc/mem_1.1.xcf differ
diff --git a/misc/wak.wav b/misc/wak.wav
new file mode 100644
index 0000000..6b3f4c4
Binary files /dev/null and b/misc/wak.wav differ
diff --git a/misc/wakwak.sh b/misc/wakwak.sh
new file mode 100644
index 0000000..3ee379d
--- /dev/null
+++ b/misc/wakwak.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+play wak.wav > /dev/null
+play wak.wav > /dev/null
diff --git a/sys_freebsd.c b/sys_freebsd.c
new file mode 100644
index 0000000..4ae0de0
--- /dev/null
+++ b/sys_freebsd.c
@@ -0,0 +1,210 @@
+/* BubbleMon dockapp 1.2 - FreeBSD specific code
+ * Copyright (C) 2001, oleg dashevskii <od at iclub.nsu.ru>
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <kvm.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/dkstat.h>
+#include <sys/vmmeter.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <vm/vm_param.h>
+#include <time.h>
+#include "include/bubblemon.h"
+#include "include/sys_include.h"
+
+extern BubbleMonData bm;
+
+static kvm_t *kd = NULL;
+static struct nlist nlst[] = {
+ {"_cp_time", 0},
+ {"_cnt", 0},
+ {"_bufspace", 0},
+ {0, 0}
+};
+static int pageshift;
+
+#define pagetob(size) ((size) << pageshift)
+
+int init_stuff()
+{
+ /* calculate page shift to convert pages into kilobytes */
+ int pagesize = getpagesize();
+ pageshift = 0;
+
+ while (pagesize > 1) {
+ pageshift++;
+ pagesize >>= 1;
+ }
+
+ /* open kernel memory */
+ kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open");
+
+ if (kd == NULL) {
+ puts("Could not open kernel virtual memory");
+ return 1;
+ }
+
+ kvm_nlist(kd, nlst);
+
+ if (nlst[0].n_type == 0 || nlst[1].n_type == 0 || nlst[2].n_type == 0) {
+ puts("Error extracting symbols");
+ return 2;
+ }
+
+ /* drop setgid & setuid (the latter should not be there really) */
+ seteuid(getuid());
+ setegid(getgid());
+
+ if (geteuid() != getuid() || getegid() != getgid()) {
+ puts("Unable to drop privileges");
+ return 3;
+ }
+
+ return 0;
+}
+
+/* Returns the current CPU load in percent */
+int system_cpu(void)
+{
+ int loadPercentage;
+ int previous_total, previous_load;
+ int total, load;
+ unsigned long int cpu_time[CPUSTATES];
+ int i;
+
+ if (kvm_read(kd, nlst[0].n_value, &cpu_time, sizeof(cpu_time))
+ != sizeof(cpu_time))
+ return 0;
+
+ load = cpu_time[CP_USER] + cpu_time[CP_SYS] + cpu_time[CP_NICE];
+ total = load + cpu_time[CP_IDLE];
+
+ i = bm.loadIndex;
+ previous_load = bm.load[i];
+ previous_total = bm.total[i];
+
+ bm.load[i] = load;
+ bm.total[i] = total;
+ bm.loadIndex = (i + 1) % bm.samples;
+
+ if (previous_total == 0)
+ loadPercentage = 0; /* first time here */
+ else
+ if (total == previous_total)
+ loadPercentage = 100;
+ else
+ loadPercentage = (100 * (load - previous_load)) /
+ (total - previous_total);
+
+ return loadPercentage;
+}
+
+int system_memory(void)
+{
+ u_int64_t my_mem_used, my_mem_max;
+ u_int64_t my_swap_used, my_swap_max;
+ struct vmmeter sum;
+ int bufspace;
+ static int swappgsin = -1;
+ static int swappgsout = -1;
+ static int swap_firsttime = 1;
+ static int swapavail = 0, swapused = 0;
+ static time_t last_time_swap = 0;
+ time_t curr_time;
+
+ if (kvm_read(kd, nlst[1].n_value, &sum, sizeof(sum)) != sizeof(sum))
+ return 0; /* _cnt */
+
+ if (kvm_read(kd, nlst[2].n_value, &bufspace, sizeof(bufspace)) !=
+ sizeof(bufspace))
+ return 0; /* _bufspace */
+
+ my_mem_max = pagetob((u_int64_t) sum.v_page_count);
+ my_mem_used = pagetob((u_int64_t) sum.v_active_count);
+
+ /* only calculate when first time or when changes took place */
+ /* do not call it more than 1 time per 2 seconds */
+ /* otherwise it can eat up to 50% of CPU time on heavy swap activity */
+ curr_time = time(NULL);
+
+ if (swap_firsttime ||
+ (((sum.v_swappgsin > swappgsin) || (sum.v_swappgsout > swappgsout)) &&
+ curr_time > last_time_swap + 1)) {
+
+ struct kvm_swap swap;
+ int n;
+
+ swapavail = 0;
+ swapused = 0;
+
+ n = kvm_getswapinfo(kd, &swap, 1, 0);
+ if (n >= 0 && swap.ksw_total != 0) {
+ swapavail = pagetob(swap.ksw_total);
+ swapused = pagetob(swap.ksw_used);
+ }
+
+ swap_firsttime = 0;
+ last_time_swap = curr_time;
+ }
+
+ my_swap_used = swapused;
+ my_swap_max = swapavail;
+
+ swappgsin = sum.v_swappgsin;
+ swappgsout = sum.v_swappgsout;
+
+ bm.mem_used = my_mem_used;
+ bm.mem_max = my_mem_max;
+ bm.swap_used = my_swap_used;
+ bm.swap_max = my_swap_max;
+ return 1;
+}
+
+#ifdef ENABLE_MEMSCREEN
+void system_loadavg(void)
+{
+ static int avg_delay;
+
+ if (avg_delay-- <= 0) {
+ struct loadavg loadinfo;
+ int i, mib[2];
+ size_t size;
+
+ mib[0] = CTL_VM;
+ mib[1] = VM_LOADAVG;
+ size = sizeof (loadinfo);
+
+ if (sysctl(mib, 2, &loadinfo, &size, NULL, 0) >= 0)
+ for (i = 0; i < 3; i++) {
+ bm.loadavg[i].i = loadinfo.ldavg[i] / loadinfo.fscale;
+ bm.loadavg[i].f = ((loadinfo.ldavg[i] * 100 +
+ loadinfo.fscale / 2) / loadinfo.fscale) % 100;
+ }
+
+ avg_delay = ROLLVALUE;
+ }
+}
+#endif /* ENABLE_MEMSCREEN */
+
+/* ex:set ts=8: */
diff --git a/sys_linux.c b/sys_linux.c
new file mode 100644
index 0000000..0aaeb7a
--- /dev/null
+++ b/sys_linux.c
@@ -0,0 +1,176 @@
+/* BubbleMon dockapp 1.2 - Linux specific code
+ * Copyright 2000, 2001 timecop at japan.co.jp
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "include/bubblemon.h"
+#include "include/sys_include.h"
+
+extern BubbleMonData bm;
+
+/* returns current CPU load in percent, 0 to 100 */
+int system_cpu(void)
+{
+ unsigned int cpuload;
+ u_int64_t load, total, oload, ototal;
+ u_int64_t ab, ac, ad, ae;
+ int i;
+ FILE *stat;
+
+ stat = fopen("/proc/stat", "r");
+ fscanf(stat, "%*s %Ld %Ld %Ld %Ld", &ab, &ac, &ad, &ae);
+ fclose(stat);
+
+ /* Find out the CPU load */
+ /* user + sys = load
+ * total = total */
+ load = ab + ac + ad; /* cpu.user + cpu.sys; */
+ total = ab + ac + ad + ae; /* cpu.total; */
+
+ /* "i" is an index into a load history */
+ i = bm.loadIndex;
+ oload = bm.load[i];
+ ototal = bm.total[i];
+
+ bm.load[i] = load;
+ bm.total[i] = total;
+ bm.loadIndex = (i + 1) % bm.samples;
+
+ /*
+ Because the load returned from libgtop is a value accumulated
+ over time, and not the current load, the current load percentage
+ is calculated as the extra amount of work that has been performed
+ since the last sample. yah, right, what the fuck does that mean?
+ */
+ if (ototal == 0) /* ototal == 0 means that this is the first time
+ we get here */
+ cpuload = 0;
+ else if ((total - ototal) <= 0)
+ cpuload = 100;
+ else
+ cpuload = (100 * (load - oload)) / (total - ototal);
+
+ return cpuload;
+}
+
+int system_memory(void)
+{
+ u_int64_t my_mem_used, my_mem_max;
+ u_int64_t my_swap_used, my_swap_max;
+#ifdef KERNEL_26
+ char *p;
+#endif
+
+ static int mem_delay = 0;
+ FILE *mem;
+ static u_int64_t aa, ab, ac, ad;
+#ifndef KERNEL_26
+ static u_int64_t ae, af, ag, ah;
+#endif
+ /* put this in permanent storage instead of stack */
+ static char shit[2048];
+
+ /* we might as well get both swap and memory at the same time.
+ * sure beats opening the same file twice */
+ if (mem_delay-- <= 0) {
+#ifdef KERNEL_26
+ mem = fopen("/proc/meminfo", "r");
+ memset(shit, 0, sizeof(shit));
+ fread(shit, 2048, 1, mem);
+ p = strstr(shit, "MemTotal");
+ if (p) {
+ sscanf(p, "MemTotal:%Ld", &aa);
+ my_mem_max = aa << 10;
+
+ p = strstr(p, "Active");
+ if (p) {
+ sscanf(p, "Active:%Ld", &ab);
+ my_mem_used = ab << 10;
+
+ p = strstr(p, "SwapTotal");
+ if (p) {
+ sscanf(p, "SwapTotal:%Ld", &ac);
+ my_swap_max = ac << 10;
+
+ p = strstr(p, "SwapFree");
+ if (p) {
+ sscanf(p, "SwapFree:%Ld", &ad);
+ my_swap_used = my_swap_max - (ad << 10);
+
+ bm.mem_used = my_mem_used;
+ bm.mem_max = my_mem_max;
+ bm.swap_used = my_swap_used;
+ bm.swap_max = my_swap_max;
+ }
+ }
+ }
+ }
+ fclose(mem);
+ mem_delay = 25;
+#else
+ mem = fopen("/proc/meminfo", "r");
+ fgets(shit, 2048, mem);
+
+ fscanf(mem, "%*s %Ld %Ld %Ld %Ld %Ld %Ld", &aa, &ab, &ac,
+ &ad, &ae, &af);
+ fscanf(mem, "%*s %Ld %Ld", &ag, &ah);
+ fclose(mem);
+ mem_delay = 25;
+
+ /* calculate it */
+ my_mem_max = aa; /* memory.total; */
+ my_swap_max = ag; /* swap.total; */
+
+ my_mem_used = ah + ab - af - ae; /* swap.used + memory.used - memory.cached - memory.buffer; */
+
+ if (my_mem_used > my_mem_max) {
+ my_swap_used = my_mem_used - my_mem_max;
+ my_mem_used = my_mem_max;
+ } else {
+ my_swap_used = 0;
+ }
+
+ bm.mem_used = my_mem_used;
+ bm.mem_max = my_mem_max;
+ bm.swap_used = my_swap_used;
+ bm.swap_max = my_swap_max;
+#endif
+
+ /* memory info changed - update things */
+ return 1;
+ }
+ /* nothing new */
+ return 0;
+}
+
+#ifdef ENABLE_MEMSCREEN
+void system_loadavg(void)
+{
+ FILE *avg;
+ static int avg_delay;
+ if (avg_delay-- <= 0) {
+ avg = fopen("/proc/loadavg", "r");
+ fscanf(avg, "%d.%d %d.%d %d.%d", &bm.loadavg[0].i, &bm.loadavg[0].f,
+ &bm.loadavg[1].i, &bm.loadavg[1].f,
+ &bm.loadavg[2].i, &bm.loadavg[2].f);
+ fclose(avg);
+ avg_delay = ROLLVALUE;
+ }
+}
+#endif /* ENABLE_MEMSCREEN */
diff --git a/sys_netbsd.c b/sys_netbsd.c
new file mode 100644
index 0000000..c80ba19
--- /dev/null
+++ b/sys_netbsd.c
@@ -0,0 +1,132 @@
+/* BubbleMon dockapp 1.2 - NetBSD specific code
+ * Copyright (C) 2001, Peter Stromberg <wilfried at openbsd.org>
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/dkstat.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/resource.h>
+#include <sys/sched.h>
+
+#include <uvm/uvm_object.h>
+#include <uvm/uvm_extern.h>
+#include <sys/swap.h>
+
+#include "include/bubblemon.h"
+#include "include/sys_include.h"
+
+extern BubbleMonData bm;
+
+/* Returns the current CPU load in percent */
+int system_cpu(void)
+{
+ int loadPercentage;
+ int previous_total, previous_load;
+ int total, load;
+ long cpu_time[40];
+ int i;
+
+ int mib[] = { CTL_KERN, KERN_CP_TIME };
+ size_t size;
+
+ size = sizeof (cpu_time);
+
+ if (sysctl(mib, 2, &cpu_time, &size, NULL, 0) < 0)
+ return 0;
+
+ load = cpu_time[CP_USER] + cpu_time[CP_SYS] + cpu_time[CP_NICE];
+ total = load + cpu_time[CP_IDLE];
+
+ i = bm.loadIndex;
+ previous_load = bm.load[i];
+ previous_total = bm.total[i];
+
+ bm.load[i] = load;
+ bm.total[i] = total;
+ bm.loadIndex = (i + 1) % bm.samples;
+
+ if (previous_total == 0)
+ loadPercentage = 0; /* first time here */
+ /* Ok, this is ugly. Return 0 unless at least 3 clock cycles have been
+ * performed since last check. Flattens the data considerably, but otherwise
+ * we get really ugly zick-zack loads all the time. */
+ else if ((total == previous_total) || (total == previous_total + 1) || (total == previous_total + 2))
+ loadPercentage = 0;
+ else
+ loadPercentage = (100 * (load - previous_load)) / (total - previous_total);
+
+ return loadPercentage;
+}
+
+int system_memory(void)
+{
+#define pagetob(size) ((size) << (uvmexp.pageshift))
+ struct uvmexp uvmexp;
+ int nswap, rnswap, i;
+ int mib[] = { CTL_VM, VM_UVMEXP };
+ size_t size = sizeof (uvmexp);
+
+ if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0)
+ return 0;
+
+ bm.mem_used = pagetob(uvmexp.active);
+ bm.mem_max = pagetob(uvmexp.npages);
+ bm.swap_used = 0;
+ bm.swap_max = 0;
+ if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) != 0) {
+ struct swapent *swdev = malloc(nswap * sizeof(*swdev));
+ if((rnswap = swapctl(SWAP_STATS, swdev, nswap)) != nswap) {
+ for (i = 0; i < nswap; i++) {
+ if (swdev[i].se_flags & SWF_ENABLE) {
+ bm.swap_used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
+ bm.swap_max += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
+ }
+ }
+ }
+ free(swdev);
+ }
+
+ return 1;
+}
+
+#ifdef ENABLE_MEMSCREEN
+void system_loadavg(void)
+{
+ static int avg_delay;
+
+ if (avg_delay-- <= 0) {
+ struct loadavg loadinfo;
+ int i;
+ int mib[] = { CTL_VM, VM_LOADAVG };
+ size_t size = sizeof (loadinfo);
+
+ if (sysctl(mib, 2, &loadinfo, &size, NULL, 0) >= 0)
+ for (i = 0; i < 3; i++) {
+ bm.loadavg[i].i = loadinfo.ldavg[i] / loadinfo.fscale;
+ bm.loadavg[i].f = ((loadinfo.ldavg[i] * 100 +
+ loadinfo.fscale / 2) / loadinfo.fscale) % 100;
+ }
+
+ avg_delay = ROLLVALUE;
+ }
+}
+#endif /* ENABLE_MEMSCREEN */
+
+/* ex:set sw=4 ts=4: */
diff --git a/sys_openbsd.c b/sys_openbsd.c
new file mode 100644
index 0000000..a07ee72
--- /dev/null
+++ b/sys_openbsd.c
@@ -0,0 +1,130 @@
+/* BubbleMon dockapp 1.2 - OpenBSD specific code
+ * Copyright (C) 2001, Peter Stromberg <wilfried at openbsd.org>
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/dkstat.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/resource.h>
+
+#include <uvm/uvm_object.h>
+#include <uvm/uvm_extern.h>
+#include <sys/swap.h>
+
+#include "include/bubblemon.h"
+#include "include/sys_include.h"
+
+extern BubbleMonData bm;
+
+/* Returns the current CPU load in percent */
+int system_cpu(void)
+{
+ int loadPercentage;
+ int previous_total, previous_load;
+ int total, load;
+ long cpu_time[CPUSTATES];
+ int i;
+
+ int mib[2];
+ size_t size;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CPTIME;
+ size = sizeof (cpu_time);
+
+ if (sysctl(mib, 2, &cpu_time, &size, NULL, 0) < 0)
+ return 0;
+
+ load = cpu_time[CP_USER] + cpu_time[CP_SYS] + cpu_time[CP_NICE];
+ total = load + cpu_time[CP_IDLE];
+
+ i = bm.loadIndex;
+ previous_load = bm.load[i];
+ previous_total = bm.total[i];
+
+ bm.load[i] = load;
+ bm.total[i] = total;
+ bm.loadIndex = (i + 1) % bm.samples;
+
+ if (previous_total == 0)
+ loadPercentage = 0; /* first time here */
+ else if (total == previous_total)
+ loadPercentage = 100;
+ else
+ loadPercentage = (100 * (load - previous_load)) / (total - previous_total);
+
+ return loadPercentage;
+}
+
+int system_memory(void)
+{
+#define pagetob(size) ((size) << (uvmexp.pageshift))
+ struct uvmexp uvmexp;
+ int nswap, rnswap, i;
+ int mib[] = { CTL_VM, VM_UVMEXP };
+ size_t size = sizeof (uvmexp);
+
+ if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0)
+ return 0;
+
+ bm.mem_used = pagetob(uvmexp.active);
+ bm.mem_max = pagetob(uvmexp.npages);
+ bm.swap_used = 0;
+ bm.swap_max = 0;
+ if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) != 0) {
+ struct swapent *swdev = malloc(nswap * sizeof(*swdev));
+ if((rnswap = swapctl(SWAP_STATS, swdev, nswap)) != nswap) {
+ for (i = 0; i < nswap; i++) {
+ if (swdev[i].se_flags & SWF_ENABLE) {
+ bm.swap_used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
+ bm.swap_max += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
+ }
+ }
+ }
+ free(swdev);
+ }
+
+ return 1;
+}
+
+#ifdef ENABLE_MEMSCREEN
+void system_loadavg(void)
+{
+ static int avg_delay;
+
+ if (avg_delay-- <= 0) {
+ struct loadavg loadinfo;
+ int i;
+ int mib[] = { CTL_VM, VM_LOADAVG };
+ size_t size = sizeof (loadinfo);
+
+ if (sysctl(mib, 2, &loadinfo, &size, NULL, 0) >= 0)
+ for (i = 0; i < 3; i++) {
+ bm.loadavg[i].i = loadinfo.ldavg[i] / loadinfo.fscale;
+ bm.loadavg[i].f = ((loadinfo.ldavg[i] * 100 +
+ loadinfo.fscale / 2) / loadinfo.fscale) % 100;
+ }
+
+ avg_delay = ROLLVALUE;
+ }
+}
+#endif /* ENABLE_MEMSCREEN */
+
+/* ex:set sw=4 ts=4: */
diff --git a/sys_sunos.c b/sys_sunos.c
new file mode 100644
index 0000000..9bae147
--- /dev/null
+++ b/sys_sunos.c
@@ -0,0 +1,325 @@
+/* BubbleMon dockapp 1.2 - SunOS specific code
+ * Copyright 2001 Phil Lu <wplu13 at netscape.net>
+ * Copyright 2001 Dan Price <dp at rampant.org>
+ * vim: ts=4 sw=4
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+ * This file is best viewed with tab stop set to 4 spaces ...
+ *
+ * For Nedit, from ~/.nedit:
+ * nedit.tabDistance: 4
+ * For vi*, from ~/.exrc:
+ * set ts=4 sw=4
+ */
+
+#include <sys/kstat.h>
+#include <sys/cpuvar.h>
+#include <sys/swap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+#include <kstat.h>
+#include <utmp.h>
+#include <math.h>
+
+#include "include/bubblemon.h"
+#include "include/sys_include.h"
+
+extern BubbleMonData bm;
+
+static kstat_ctl_t *kc = 0;
+static kstat_t **cpu_ksp_list = 0;
+static int ncpus = 0;
+
+static void GetMemoryStats(u_int64_t *pMemMax, u_int64_t *pMemFree);
+static void GetSwapStats(u_int64_t *pSwapTotal, u_int64_t *pSwapFree);
+static void GetCPULoadAverage(float *one_m, float *five_m, float *fift_m);
+
+static int dbg_print_mem = 0; /* from environment: DBG_PRINT_MEM=interval */
+static int dbg_print_cpu = 0; /* from environment: DBG_PRINT_CPU=interval */
+static int dbg_hardcode = 0; /* from environment: DBG_HARDCODE */
+
+
+/*
+ * setup_system() gets called to initialize everything specific to Solaris,
+ * and when kstat_chain_update() indicates that the kernel's kstat chain has
+ * altered.
+ *
+ * When that occurs, CPUs may have come on- or off-line, so we need to
+ * rediscover the system cpus.
+ */
+void setup_system()
+{
+ char *str = 0;
+ kstat_t *ksp = 0;
+ static int bootstrap = 1;
+ int i = 0;
+
+ if (bootstrap) {
+ /* grab debugging flags from environment */
+ if ((str = getenv("DBG_PRINT_MEM")))
+ dbg_print_mem = atoi(str);
+ if ((str = getenv("DBG_PRINT_CPU")))
+ dbg_print_cpu = atoi(str);
+ if ((str = getenv("DBG_HARDCODE")))
+ dbg_hardcode = 1;
+
+ if ((kc = kstat_open()) == NULL) {
+ perror("can't open /dev/kstat");
+ exit(1);
+ }
+ bootstrap = 0;
+ }
+
+ /*
+ * User selected to monitor all CPUs. First, count them.
+ */
+ for (i = 0, ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
+ if (strcmp(ksp->ks_module, "cpu_stat") == 0)
+ i++;
+ }
+
+ if (cpu_ksp_list) {
+ free(cpu_ksp_list);
+ }
+
+ cpu_ksp_list = (kstat_t **) calloc(i * sizeof (kstat_t *), 1);
+ ncpus = i;
+
+ /*
+ * stash the ksp for each CPU.
+ */
+ for (i = 0, ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
+ if (strcmp(ksp->ks_module, "cpu_stat") == 0) {
+ cpu_ksp_list[i] = ksp;
+ i++;
+ }
+ }
+}
+
+/* returns current CPU load in percent, 0 to 100 */
+int system_cpu(void)
+{
+ static int previous_total = 0, previous_used = 0;
+ int used = 0, idle = 0, total = 0, i = 0, t = 0;
+ cpu_stat_t stat;
+
+ if (dbg_hardcode)
+ return 20;
+
+ if (kc == NULL || kstat_chain_update(kc)) {
+ setup_system();
+ }
+
+ /*
+ * Read each cpu's data. If the kstat chain has changed (a state change
+ * has happened, maybe a new cpu was added to the system or one went
+ * away), then reinitialize everything with setup_system(). Finally,
+ * recursively call system_cpu()
+ *
+ * We'll need to do a little better than this in the future, since we
+ * could recurse too much in the pathological case here.
+ */
+
+ for (i = 0; i < ncpus; i++) {
+ if (kstat_read(kc, cpu_ksp_list[i], (void *)&stat) == -1) {
+ setup_system();
+ return (system_cpu());
+ }
+ used += stat.cpu_sysinfo.cpu[CPU_USER]; /* user */
+ used += stat.cpu_sysinfo.cpu[CPU_KERNEL]; /* sys */
+ used += stat.cpu_sysinfo.cpu[CPU_WAIT]; /* wait */
+ idle += stat.cpu_sysinfo.cpu[CPU_IDLE]; /*idle ("free") */
+ }
+
+ total = used + idle;
+ t = 100 * (double)(used - previous_used) /
+ (double)(total - previous_total);
+ previous_total = total;
+ previous_used = used;
+
+ if (dbg_print_cpu) {
+ static int i = 0;
+ if (0 == (i % dbg_print_cpu)) {
+ printf("system_cpu: %d%%, total=%d\n", t, total);
+ printf("system_cpu: used=%d, idle=%d\n", used, idle);
+ }
+ i++;
+ }
+ return (t);
+}
+
+typedef struct TMyMem {
+ u_int64_t lMemMax;
+ u_int64_t lMemFree;
+ u_int64_t lSwapMax;
+ u_int64_t lSwapFree;
+} MyMem;
+
+int system_memory(void)
+{
+ static MyMem last = { 100, 20, 200, 10, };
+ MyMem cur = { 100, 20, 200, 10, };
+ int rc = 0;
+
+ if (dbg_hardcode) {
+ bm.mem_max = 100;
+ bm.mem_used = 20;
+ bm.swap_max = 200;
+ bm.swap_used = 0;
+ return 1;
+ }
+
+ GetSwapStats(&cur.lSwapMax, &cur.lSwapFree);
+ bm.swap_max = cur.lSwapMax;
+ bm.swap_used = cur.lSwapMax - cur.lSwapFree;
+
+ GetMemoryStats(&cur.lMemMax, &cur.lMemFree);
+ bm.mem_max = cur.lMemMax + cur.lSwapMax;
+ bm.mem_used = cur.lMemMax - cur.lMemFree + bm.swap_used;
+
+ if (dbg_print_mem) {
+ static int i = 0;
+ if (0 == (i % dbg_print_mem)) {
+ printf("system_memory: mem: max=%llu used=%llu\n",
+ bm.mem_max, bm.mem_used);
+ printf("system_memory: swap: max=%llu used=%llu\n",
+ bm.swap_max, bm.swap_used);
+ }
+ i++;
+ }
+
+ /* if memory info changed - update things */
+ rc = (0 == memcmp(&last, &cur, sizeof(last)) ? 0 : 1);
+
+ memcpy(&last, &cur, sizeof(last));
+ return rc;
+}
+
+#ifdef ENABLE_MEMSCREEN
+void system_loadavg(void)
+{
+ static int avg_delay = 0;
+ float one_m = 0, five_m = 0, fift_m = 0;
+
+ if (dbg_hardcode) {
+ bm.loadavg[0].i = 0; bm.loadavg[0].f = 53; /* 0.53 */
+ bm.loadavg[1].i = 0; bm.loadavg[1].f = 45; /* 0.45 */
+ bm.loadavg[2].i = 0; bm.loadavg[2].f = 38; /* 0.38 */
+ return;
+ }
+
+ if (avg_delay-- <= 0) {
+ GetCPULoadAverage(&one_m, &five_m, &fift_m);
+
+ if (dbg_print_cpu) {
+ static int i = 0;
+ if (0 == (i % dbg_print_cpu))
+ printf("loadavg: %0.2f %0.2f %0.2f\n",
+ one_m, five_m, fift_m);
+ i++;
+ }
+
+ bm.loadavg[0].i = floor(one_m);
+ bm.loadavg[0].f = 100 * (one_m - floor(one_m));
+ bm.loadavg[1].i = floor(five_m);
+ bm.loadavg[1].f = 100 * (five_m - floor(five_m));
+ bm.loadavg[2].i = floor(fift_m);
+ bm.loadavg[2].f = 100 * (fift_m - floor(fift_m));
+ avg_delay = ROLLVALUE;
+ }
+}
+#endif /* ENABLE_MEMSCREEN */
+
+static void GetMemoryStats(u_int64_t *pMemMax, u_int64_t *pMemFree)
+{
+ uint_t lPagesToBytesMult = sysconf(_SC_PAGESIZE);
+
+ *pMemMax = (uint64_t)sysconf(_SC_PHYS_PAGES) * lPagesToBytesMult;
+ *pMemFree = (uint64_t)sysconf(_SC_AVPHYS_PAGES) * lPagesToBytesMult;
+
+ if (dbg_print_mem) {
+ static int i = 0;
+ if (0 == (i % dbg_print_mem)) {
+ printf("GetMemoryStats: pMemMax=%llu Bytes\n", *pMemMax);
+ printf("GetMemoryStats: pMemFree=%llu Bytes\n", *pMemFree);
+ }
+ i++;
+ }
+}
+
+static void GetSwapStats(u_int64_t *pSwapTotal, u_int64_t *pSwapFree)
+{
+ struct anoninfo anon;
+ uint_t lPagesToBytesMult = sysconf(_SC_PAGESIZE);
+
+ if (swapctl(SC_AINFO, &anon) == -1) {
+ perror("swapctl failed");
+ /* let's not blow up code by setting stuff to 0 :) */
+ *pSwapTotal = *pSwapFree = 1;
+ return;
+ }
+
+ *pSwapTotal = lPagesToBytesMult * (anon.ani_max);
+ *pSwapFree = lPagesToBytesMult * (anon.ani_max - anon.ani_resv);
+
+ if (dbg_print_mem) {
+ static int i = 0;
+ if (0 == (i % dbg_print_mem)) {
+ (void) printf("GetSwapStats: pSwapMax=%llu Bytes\n",
+ *pSwapTotal);
+ (void) printf("GetSwapStats: pSwapFree=%llu Bytes\n",
+ *pSwapFree);
+ }
+ i++;
+ }
+}
+
+/*
+ * we'd prefer to use getloadavg(3C) but it wasn't present in Solaris until
+ * sunos 5.7. (sigh)
+ */
+static void GetCPULoadAverage(float *one_m, float *five_m, float *fift_m)
+{
+ kstat_named_t *kn = 0;
+ kstat_t *ks = 0;
+
+ if (kc == NULL || kstat_chain_update(kc)) {
+ setup_system();
+ }
+
+ ks = kstat_lookup(kc, "unix", 0, "system_misc");
+ if (kstat_read(kc, ks, 0) == -1) {
+ perror("kstat_read");
+ exit(1);
+ }
+
+ /*
+ * Get the 1, 5 and 15min load average.
+ */
+ kn = kstat_data_lookup(ks, "avenrun_1min");
+ *one_m = kn->value.ul / (ncpus * 256.0);
+
+ kn = kstat_data_lookup(ks, "avenrun_5min");
+ *five_m = kn->value.ul / (ncpus * 256.0);
+
+ kn = kstat_data_lookup(ks, "avenrun_15min");
+ *fift_m = kn->value.ul / (ncpus * 256.0);
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-wmaker/wmbubble.git
More information about the Pkg-wmaker-commits
mailing list