From 551b3de3f619c04c2dd1971ee9b3f02e270c28c9 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Mon, 2 Mar 2009 00:42:33 -0500 Subject: [PATCH] http://ftp.x.org/contrib/applications/xscreensaver-3.10.tar.gz -rw-r--r-- 1 zblaxell zblaxell 1085749 Apr 26 1999 xscreensaver-3.10.tar.gz 0ef47faea495b2452c4ffee0c809d8205e314864 xscreensaver-3.10.tar.gz --- README | 11 + configure | 53 ++ configure.in | 53 ++ driver/Makefile.in | 40 +- driver/XScreenSaver.ad.in | 9 +- driver/XScreenSaver_ad.h | 5 +- driver/passwd-pwent.c | 13 +- driver/passwd.c | 38 +- driver/prefs.c | 1 - driver/subprocs.c | 2 +- driver/windows.c | 10 +- driver/xscreensaver-command.man | 2 +- driver/xscreensaver-demo.man | 2 +- driver/xscreensaver.c | 22 +- driver/xscreensaver.h | 1 + driver/xscreensaver.man | 2 +- hacks/Makefile.in | 34 +- hacks/compile_axp.com | 2 + hacks/compile_decc.com | 2 + hacks/critical.c | 9 +- hacks/glx/Makefile.in | 21 +- hacks/glx/glplanet.c | 2 +- hacks/glx/pulsar.c | 783 +++++++++++++++++++++++++++ hacks/images/matrix.xbm | 394 ++++++++++++++ hacks/images/matrix.xpm | 904 ++++++++++++++++++++++++++++++++ hacks/penrose.c | 30 +- hacks/penrose.man | 15 +- hacks/phosphor.c | 801 ++++++++++++++++++++++++++++ hacks/screenhack.c | 2 +- hacks/slip.c | 2 +- hacks/sphere.c | 2 +- hacks/squiral.c | 1 + hacks/t3d.c | 7 +- hacks/xflame.c | 9 + hacks/xlyap.c | 2 +- hacks/xmatrix.c | 438 ++++++++++++++++ setup.com | 2 + utils/colors.c | 3 +- utils/version.h | 2 +- xscreensaver.lsm | 16 +- xscreensaver.spec | 2 +- 41 files changed, 3682 insertions(+), 67 deletions(-) create mode 100644 hacks/glx/pulsar.c create mode 100644 hacks/images/matrix.xbm create mode 100644 hacks/images/matrix.xpm create mode 100644 hacks/phosphor.c create mode 100644 hacks/xmatrix.c diff --git a/README b/README index 88904437..417e248a 100644 --- a/README +++ b/README @@ -77,6 +77,17 @@ http://www.jwz.org/xscreensaver/. ============ +Changes since 3.09: * Added `phosphor', `xmatrix', and `pulsar' hacks. + * Fixed a bug in the color allocator that sometimes + caused `starfish' to fall back to monochrome. + * Reduced the amount of code that runs before root + privileges are disavowed: "normal" and "shadow" + passwords now do some initialization as root, but the + PAM and Kerberos authorization schemes will be + initialized while running as "nobody". Supposedly + this closes a potential security hole when using + Kerberos. + * Added some more sanity checking to configure. Changes since 3.08: * Added `compass', `squiral', `xflame', `wander', `spotlight', and `critical' hacks. * Added some new modes to `decayscreen'. diff --git a/configure b/configure index 43a972c2..5d61f180 100755 --- a/configure +++ b/configure @@ -8327,7 +8327,60 @@ eval HACKDIR=${HACKDIR} bindir=`echo "${bindir}" | sed 's@/$@@;s@//*@/@g'` HACKDIR=`echo "${HACKDIR}" | sed 's@/$@@;s@//*@/@g'` + +# Sanity check the subdir +for bad_choice in xscreensaver xscreensaver-demo xscreensaver-command ; do + if test "${HACKDIR}" = "${bindir}/${bad_choice}" ; then + echo "" + { echo "configure: error: \"--enable-subdir=${bindir}/${bad_choice}\" won't work. + There will be an executable installed with that name, so + that can't be the name of a directory as well. Please + re-configure with a different directory name." 1>&2; exit 1; } + fi +done + + +do_dir_warning=no + +# Now let's see if there's a previous RPM version already installed. Blargh! + +# M4 sucks!! + +rpmv=`(rpm -qv xscreensaver) 2>&- | \ + sed 's/^xscreensaver-\([0-9][0-9]*[.][0-9][0-9]*\)-[0-9][0-9]*$/\1/'` + + +if test \! -z "$rpmv" ; then + rpmbdir=`rpm -ql xscreensaver | sed -n 's@^\(.*\)/xscreensaver-demo$@\1@p'` + rpmhdir=`rpm -ql xscreensaver | sed -n 's@^\(.*\)/attraction$@\1@p'` + + warning=no + warnL "There is already an installed RPM of xscreensaver $rpmv" + warn2 "on this system. You might want to remove it (with" + warn2 '"rpm -ve xscreensaver") before running "make install"' + warn2 "from this directory." + echo "" + warn2 "Alternately, you could build this version of xscreensaver" + warn2 'as an RPM, and then install that. An "xscreensaver.spec"' + warn2 "file is included. See the RPM documentation for more info." + echo "" + + if test "$rpmbdir" = "$rpmhdir" ; then + warn2 "The RPM version was installed in $rpmbdir." + else + warn2 "The RPM version was installed in $rpmbdir," + warn2 "with demos in $rpmhdir." + fi + + do_dir_warning=yes +fi + + if test "${bindir}" = "${HACKDIR}" ; then + do_dir_warning=yes +fi + +if test "$do_dir_warning" = yes; then echo "" echo "$warnsep" echo "" diff --git a/configure.in b/configure.in index 39a30f9d..75a8fe32 100644 --- a/configure.in +++ b/configure.in @@ -2180,7 +2180,60 @@ eval HACKDIR=${HACKDIR} bindir=`echo "${bindir}" | sed 's@/$@@;s@//*@/@g'` HACKDIR=`echo "${HACKDIR}" | sed 's@/$@@;s@//*@/@g'` + +# Sanity check the subdir +for bad_choice in xscreensaver xscreensaver-demo xscreensaver-command ; do + if test "${HACKDIR}" = "${bindir}/${bad_choice}" ; then + echo "" + AC_MSG_ERROR([\"--enable-subdir=${bindir}/${bad_choice}\" won't work. + There will be an executable installed with that name, so + that can't be the name of a directory as well. Please + re-configure with a different directory name.]) + fi +done + + +do_dir_warning=no + +# Now let's see if there's a previous RPM version already installed. Blargh! + +# M4 sucks!! +changequote(X,Y) +rpmv=`(rpm -qv xscreensaver) 2>&- | \ + sed 's/^xscreensaver-\([0-9][0-9]*[.][0-9][0-9]*\)-[0-9][0-9]*$/\1/'` +changequote([,]) + +if test \! -z "$rpmv" ; then + rpmbdir=`rpm -ql xscreensaver | sed -n 's@^\(.*\)/xscreensaver-demo$@\1@p'` + rpmhdir=`rpm -ql xscreensaver | sed -n 's@^\(.*\)/attraction$@\1@p'` + + warning=no + warnL "There is already an installed RPM of xscreensaver $rpmv" + warn2 "on this system. You might want to remove it (with" + warn2 '"rpm -ve xscreensaver") before running "make install"' + warn2 "from this directory." + echo "" + warn2 "Alternately, you could build this version of xscreensaver" + warn2 'as an RPM, and then install that. An "xscreensaver.spec"' + warn2 "file is included. See the RPM documentation for more info." + echo "" + + if test "$rpmbdir" = "$rpmhdir" ; then + warn2 "The RPM version was installed in $rpmbdir." + else + warn2 "The RPM version was installed in $rpmbdir," + warn2 "with demos in $rpmhdir." + fi + + do_dir_warning=yes +fi + + if test "${bindir}" = "${HACKDIR}" ; then + do_dir_warning=yes +fi + +if test "$do_dir_warning" = yes; then echo "" echo "$warnsep" echo "" diff --git a/driver/Makefile.in b/driver/Makefile.in index d9b51229..0187e217 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -176,6 +176,7 @@ install-program: $(EXES) else \ e=echo ; \ $$e "" ;\ + $$e " ####################################################################";\ $$e " Warning: xscreensaver has been compiled with support for shadow" ;\ $$e " passwords. If your system actually uses shadow passwords," ;\ $$e " then xscreensaver must be installed as a setuid root" ;\ @@ -184,6 +185,7 @@ install-program: $(EXES) $$e "" ;\ $$e " For now, xscreensaver will be installed non-setuid, which" ;\ $$e " means that locking might not work. (Try it and see.)" ;\ + $$e " ####################################################################";\ $$e "" ;\ fi ; \ fi ; \ @@ -194,7 +196,32 @@ install-program: $(EXES) install-ad: XScreenSaver.ad @if [ ! -d $(AD_DIR) ]; then $(INSTALL_DIRS) $(AD_DIR) ; fi - $(INSTALL_DATA) XScreenSaver.ad $(AD_DIR)/XScreenSaver + @-echo $(INSTALL_DATA) XScreenSaver.ad $(AD_DIR)/XScreenSaver ; \ + if $(INSTALL_DATA) XScreenSaver.ad $(AD_DIR)/XScreenSaver ; then \ + true ; \ + else \ + e=echo ; \ + if [ -f $(AD_DIR)/XScreenSaver ]; then \ + $$e "" ;\ + $$e " ####################################################################";\ + $$e " Warning: unable to install $(AD_DIR)/XScreenSaver" ;\ + $$e " That file exists, and is unwritable. It is probably from" ;\ + $$e " an older version of xscreensaver, and could cause things" ;\ + $$e " to malfunction. Please delete it!" ;\ + $$e " ####################################################################";\ + $$e "" ;\ + exit 1 ; \ + else \ + $$e "" ;\ + $$e " ####################################################################";\ + $$e " Warning: unable to install $(AD_DIR)/XScreenSaver" ;\ + $$e " The directory is unwritable. This is probably ok;" ;\ + $$e " xscreensaver should work without that file." ;\ + $$e " ####################################################################";\ + $$e "" ;\ + exit 0 ; \ + fi \ + fi install-man: $(MEN) @men="$(MEN)" ; \ @@ -235,11 +262,14 @@ install-pam: if [ ! -f $$dir/$$dest ]; then \ e=echo ; \ $$e "" ;\ + $$e " ####################################################################";\ $$e " Warning: xscreensaver has been compiled with support for Pluggable" ;\ $$e " Authentication Modules (PAM). However, we were unable to" ;\ - $$e " install the file $$dir/$$dest. PAM is unlikely to work" ;\ - $$e " without this file (and old-style password authentication" ;\ - $$e " will be used instead, which may or may not work.)" ;\ + $$e " install the file $$dir/$$dest. PAM is unlikely" ;\ + $$e " to work without this file (and old-style password" ;\ + $$e " authentication will be used instead, which may or may not" ;\ + $$e " work.)" ;\ + $$e " ####################################################################";\ $$e "" ;\ fi ; \ elif [ -f $$conf ]; then \ @@ -248,9 +278,11 @@ install-pam: else \ e=echo ; \ $$e "" ;\ + $$e " ####################################################################";\ $$e " Warning: xscreensaver has been compiled with support for Pluggable" ;\ $$e " Authentication Modules (PAM). To complete the installation";\ $$e " of PAM support, you must add this to the file $$conf:" ;\ + $$e " ####################################################################";\ $$e "" ;\ cat $$src | grep -v '#%' | sed "s/^/ $$dest /" ; \ echo ""; \ diff --git a/driver/XScreenSaver.ad.in b/driver/XScreenSaver.ad.in index bdfcc586..cc35ca4a 100644 --- a/driver/XScreenSaver.ad.in +++ b/driver/XScreenSaver.ad.in @@ -4,8 +4,8 @@ ! a screen saver and locker for the X window system ! by Jamie Zawinski ! -! version 3.09 -! 11-Apr-99 +! version 3.10 +! 27-Apr-99 ! ! See "man xscreensaver" for more info. The latest version is always ! available at http://www.jwz.org/xscreensaver/ @@ -188,6 +188,8 @@ wander -root -advance 0 -size 10 -circles True \ -length 10000 -reset 100000 \n\ critical -root \n\ + phosphor -root \n\ + xmatrix -root \n\ \ mono: rocks -root \n\ color: rocks -root -fg darksalmon \n\ @@ -216,7 +218,8 @@ @GL_KLUDGE@ atlantis -root \n\ @GL_KLUDGE@ lament -root \n\ @GL_KLUDGE@ bubble3d -root \n\ -@GL_KLUDGE@ glplanet -root \n +@GL_KLUDGE@ glplanet -root \n\ +@GL_KLUDGE@ pulsar -root \n ! A few of the hacks require OpenGL, and will only be built if you have it. diff --git a/driver/XScreenSaver_ad.h b/driver/XScreenSaver_ad.h index 9d4c348e..01787522 100644 --- a/driver/XScreenSaver_ad.h +++ b/driver/XScreenSaver_ad.h @@ -116,6 +116,8 @@ wander -root -advance 0 -size 10 -circles True \ -length 10000 -reset 100000 \\n\ critical -root \\n\ + phosphor -root \\n\ + xmatrix -root \\n\ \ mono: rocks -root \\n\ color: rocks -root -fg darksalmon \\n\ @@ -144,7 +146,8 @@ atlantis -root \\n\ lament -root \\n\ bubble3d -root \\n\ - glplanet -root \\n", + glplanet -root \\n\ + pulsar -root \\n", " ", "XScreenSaver.pointerPollTime: 5", "XScreenSaver.initialDelay: 0", diff --git a/driver/passwd-pwent.c b/driver/passwd-pwent.c index 6e83e0f4..5bfaec9e 100644 --- a/driver/passwd-pwent.c +++ b/driver/passwd-pwent.c @@ -213,7 +213,7 @@ get_encrypted_passwd(const char *user) #ifndef VMS Bool -pwent_lock_init (int argc, char **argv, Bool verbose_p) +pwent_priv_init (int argc, char **argv, Bool verbose_p) { char *u; @@ -234,6 +234,17 @@ pwent_lock_init (int argc, char **argv, Bool verbose_p) } +Bool +pwent_lock_init (int argc, char **argv, Bool verbose_p) +{ + if (encrypted_user_passwd) + return True; + else + return False; +} + + + static Bool passwds_match_p (const char *cleartext, const char *ciphertext) { diff --git a/driver/passwd.c b/driver/passwd.c index 25b3b048..1847d1be 100644 --- a/driver/passwd.c +++ b/driver/passwd.c @@ -39,8 +39,10 @@ extern char *blurb(void); struct auth_methods { const char *name; Bool (*init) (int argc, char **argv, Bool verbose_p); + Bool (*priv_init) (int argc, char **argv, Bool verbose_p); Bool (*valid_p) (const char *typed_passwd, Bool verbose_p); Bool initted_p; + Bool priv_initted_p; }; @@ -53,6 +55,7 @@ extern Bool pam_lock_init (int argc, char **argv, Bool verbose_p); extern Bool pam_passwd_valid_p (const char *typed_passwd, Bool verbose_p); #endif extern Bool pwent_lock_init (int argc, char **argv, Bool verbose_p); +extern Bool pwent_priv_init (int argc, char **argv, Bool verbose_p); extern Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p); @@ -63,15 +66,41 @@ extern Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p); */ struct auth_methods methods[] = { # ifdef HAVE_KERBEROS - { "Kerberos", kerberos_lock_init, kerberos_passwd_valid_p, False }, + { "Kerberos", kerberos_lock_init, 0, kerberos_passwd_valid_p, + False, False }, # endif # ifdef HAVE_PAM - { "PAM", pam_lock_init, pam_passwd_valid_p, False }, + { "PAM", pam_lock_init, 0, pam_passwd_valid_p, + False, False }, # endif - { "normal", pwent_lock_init, pwent_passwd_valid_p, False } + { "normal", pwent_lock_init, pwent_priv_init, pwent_passwd_valid_p, + False, False } }; +Bool +lock_priv_init (int argc, char **argv, Bool verbose_p) +{ + int i; + Bool any_ok = False; + for (i = 0; i < countof(methods); i++) + { + if (!methods[i].priv_init) + methods[i].priv_initted_p = True; + else + methods[i].priv_initted_p = methods[i].priv_init (argc, argv, + verbose_p); + + if (methods[i].priv_initted_p) + any_ok = True; + else if (verbose_p) + fprintf (stderr, "%s: initialization of %s passwords failed.\n", + blurb(), methods[i].name); + } + return any_ok; +} + + Bool lock_init (int argc, char **argv, Bool verbose_p) { @@ -79,6 +108,9 @@ lock_init (int argc, char **argv, Bool verbose_p) Bool any_ok = False; for (i = 0; i < countof(methods); i++) { + if (!methods[i].priv_initted_p) /* Bail if lock_priv_init failed. */ + continue; + methods[i].initted_p = methods[i].init (argc, argv, verbose_p); if (methods[i].initted_p) any_ok = True; diff --git a/driver/prefs.c b/driver/prefs.c index e006e577..e1913142 100644 --- a/driver/prefs.c +++ b/driver/prefs.c @@ -800,7 +800,6 @@ load_init_file (saver_preferences *p) */ if (p->passwd_timeout <= 0) p->passwd_timeout = 30000; /* 30 secs */ if (p->timeout < 10000) p->timeout = 10000; /* 10 secs */ - if (p->cycle < 0) p->cycle = 0; if (p->cycle != 0 && p->cycle < 2000) p->cycle = 2000; /* 2 secs */ if (p->pointer_timeout <= 0) p->pointer_timeout = 5000; /* 5 secs */ if (p->notice_events_timeout <= 0) diff --git a/driver/subprocs.c b/driver/subprocs.c index 0e104c7f..8b6187d9 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -739,7 +739,7 @@ select_visual_of_hack (saver_screen_info *ssi, const char *hack) (si->demoing_p ? "%s: warning, no \"%s\" visual for \"%s\".\n" : "%s: no \"%s\" visual; skipping \"%s\".\n"), - blurb(), (vis ? vis : "???"), in); + blurb(), (*vis ? vis : "???"), in); } return selected; diff --git a/driver/windows.c b/driver/windows.c index 909abe51..4945202a 100644 --- a/driver/windows.c +++ b/driver/windows.c @@ -98,11 +98,11 @@ grab_string(int status) { switch (status) { - case GrabSuccess: return "GrabSuccess"; break; - case AlreadyGrabbed: return "AlreadyGrabbed"; break; - case GrabInvalidTime: return "GrabInvalidTime"; break; - case GrabNotViewable: return "GrabNotViewable"; break; - case GrabFrozen: return "GrabFrozen"; break; + case GrabSuccess: return "GrabSuccess"; + case AlreadyGrabbed: return "AlreadyGrabbed"; + case GrabInvalidTime: return "GrabInvalidTime"; + case GrabNotViewable: return "GrabNotViewable"; + case GrabFrozen: return "GrabFrozen"; default: { static char foo[255]; diff --git a/driver/xscreensaver-command.man b/driver/xscreensaver-command.man index fb314710..88d09d29 100644 --- a/driver/xscreensaver-command.man +++ b/driver/xscreensaver-command.man @@ -11,7 +11,7 @@ .if n .sp 1 .if t .sp .5 .. -.TH XScreenSaver 1 "11-Apr-99 (3.09)" "X Version 11" +.TH XScreenSaver 1 "27-Apr-99 (3.10)" "X Version 11" .SH NAME xscreensaver-command - control a running xscreensaver process .SH SYNOPSIS diff --git a/driver/xscreensaver-demo.man b/driver/xscreensaver-demo.man index 86a470aa..01adfdcf 100644 --- a/driver/xscreensaver-demo.man +++ b/driver/xscreensaver-demo.man @@ -11,7 +11,7 @@ .if n .sp 1 .if t .sp .5 .. -.TH XScreenSaver 1 "11-Apr-99 (3.09)" "X Version 11" +.TH XScreenSaver 1 "27-Apr-99 (3.10)" "X Version 11" .SH NAME xscreensaver-demo - interactively control the background xscreensaver daemon .SH SYNOPSIS diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c index dda587a1..4460c19d 100644 --- a/driver/xscreensaver.c +++ b/driver/xscreensaver.c @@ -419,12 +419,29 @@ set_version_string (saver_info *si, int *argc, char **argv) static void privileged_initialization (saver_info *si, int *argc, char **argv) { +#ifndef NO_LOCKING + /* before hack_uid() for proper permissions */ + lock_priv_init (*argc, argv, si->prefs.verbose_p); +#endif /* NO_LOCKING */ + +#ifndef NO_SETUID + hack_uid (si); +#endif /* NO_SETUID */ +} + + +/* Figure out what locking mechanisms are supported. + */ +static void +lock_initialization (saver_info *si, int *argc, char **argv) +{ #ifdef NO_LOCKING si->locking_disabled_p = True; si->nolock_reason = "not compiled with locking support"; #else /* !NO_LOCKING */ si->locking_disabled_p = False; - /* before hack_uid() for proper permissions */ + + /* Finish initializing locking, now that we're out of privileged code. */ if (! lock_init (*argc, argv, si->prefs.verbose_p)) { si->locking_disabled_p = True; @@ -894,7 +911,7 @@ main_loop (saver_info *si) fprintf (stderr, "%s: unable to grab keyboard or mouse! Blanking aborted.\n", - blurb(), timestring ()); + blurb()); continue; } @@ -1015,6 +1032,7 @@ main (int argc, char **argv) exit (1); load_init_file (p); + lock_initialization (si, &argc, argv); if (p->xsync_p) XSynchronize (si->dpy, True); blurb_timestamp_p = p->timestamp_p; /* kludge */ diff --git a/driver/xscreensaver.h b/driver/xscreensaver.h index 7860dfe4..7a61d166 100644 --- a/driver/xscreensaver.h +++ b/driver/xscreensaver.h @@ -279,6 +279,7 @@ extern void unblank_screen (saver_info *si); #ifndef NO_LOCKING extern Bool unlock_p (saver_info *si); +extern Bool lock_priv_init (int argc, char **argv, Bool verbose_p); extern Bool lock_init (int argc, char **argv, Bool verbose_p); extern Bool passwd_valid_p (const char *typed_passwd, Bool verbose_p); diff --git a/driver/xscreensaver.man b/driver/xscreensaver.man index 44507587..9c468f75 100644 --- a/driver/xscreensaver.man +++ b/driver/xscreensaver.man @@ -11,7 +11,7 @@ .if n .sp 1 .if t .sp .5 .. -.TH XScreenSaver 1 "11-Apr-99 (3.09)" "X Version 11" +.TH XScreenSaver 1 "27-Apr-99 (3.10)" "X Version 11" .SH NAME xscreensaver - graphics hack and screen locker, launched when the user is idle .SH SYNOPSIS diff --git a/hacks/Makefile.in b/hacks/Makefile.in index e9ce414e..fb393afa 100644 --- a/hacks/Makefile.in +++ b/hacks/Makefile.in @@ -82,7 +82,8 @@ SRCS = attraction.c blitspin.c bouboule.c braid.c bubbles.c \ cynosure.c moire2.c flow.c epicycle.c interference.c \ truchet.c bsod.c crystal.c discrete.c distort.c kumppa.c \ sonar.c demon.c loop.c t3d.c penetrate.c deluxe.c compass.c \ - squiral.c xflame.c wander.c spotlight.c critical.c + squiral.c xflame.c wander.c spotlight.c critical.c \ + phosphor.c xmatrix.c OBJS = attraction.o blitspin.o bouboule.o braid.o bubbles.o \ bubbles-default.o decayscreen.o deco.o drift.o flag.o \ @@ -98,7 +99,8 @@ OBJS = attraction.o blitspin.o bouboule.o braid.o bubbles.o \ cynosure.o moire2.o flow.o epicycle.o interference.o \ truchet.o bsod.o crystal.o discrete.o distort.o kumppa.o \ sonar.o demon.o loop.o t3d.o penetrate.o deluxe.o compass.o \ - squiral.o xflame.o wander.o spotlight.o critical.o + squiral.o xflame.o wander.o spotlight.o critical.o \ + phosphor.o xmatrix.o EXES = attraction blitspin bouboule braid bubbles decayscreen deco \ drift flag flame forest vines galaxy grav greynetic halo \ @@ -110,7 +112,7 @@ EXES = attraction blitspin bouboule braid bubbles decayscreen deco \ ant xjack xlyap jigsaw cynosure moire2 flow epicycle \ interference truchet bsod crystal discrete distort kumppa \ sonar demon loop t3d penetrate deluxe compass squiral \ - xflame wander spotlight critical + xflame wander spotlight critical phosphor xmatrix HACK_OBJS_1 = $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \ $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o @XMU_OBJS@ @@ -492,6 +494,12 @@ spotlight: spotlight.o $(HACK_OBJS) $(GRAB) critical: critical.o $(HACK_OBJS) $(COL) $(ERASE) $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(COL) $(ERASE) $(HACK_LIBS) +phosphor: phosphor.o $(HACK_OBJS) $(COL) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(COL) $(HACK_LIBS) + +xmatrix: xmatrix.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) $(XPM_LIBS) + # The rules for those hacks which follow the `xlockmore' API. # @@ -1594,4 +1602,24 @@ critical.o: $(UTILS_SRC)/colors.h critical.o: $(UTILS_SRC)/grabscreen.h critical.o: $(UTILS_SRC)/visual.h critical.o: $(UTILS_SRC)/erase.h +phosphor.o: $(srcdir)/screenhack.h +phosphor.o: ../config.h +phosphor.o: $(UTILS_SRC)/yarandom.h +phosphor.o: $(UTILS_SRC)/usleep.h +phosphor.o: $(UTILS_SRC)/resources.h +phosphor.o: $(UTILS_SRC)/hsv.h +phosphor.o: $(UTILS_SRC)/colors.h +phosphor.o: $(UTILS_SRC)/grabscreen.h +phosphor.o: $(UTILS_SRC)/visual.h +xmatrix.o: $(srcdir)/screenhack.h +xmatrix.o: ../config.h +xmatrix.o: $(UTILS_SRC)/yarandom.h +xmatrix.o: $(UTILS_SRC)/usleep.h +xmatrix.o: $(UTILS_SRC)/resources.h +xmatrix.o: $(UTILS_SRC)/hsv.h +xmatrix.o: $(UTILS_SRC)/colors.h +xmatrix.o: $(UTILS_SRC)/grabscreen.h +xmatrix.o: $(UTILS_SRC)/visual.h +xmatrix.o: $(srcdir)/images/matrix.xpm +xmatrix.o: $(srcdir)/images/matrix.xbm diff --git a/hacks/compile_axp.com b/hacks/compile_axp.com index 676d5e25..13adf739 100644 --- a/hacks/compile_axp.com +++ b/hacks/compile_axp.com @@ -54,6 +54,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PEDAL.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PENETRATE.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PENROSE.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PHOSPHOR.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PYRO.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) QIX.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) RD-BOMB.C @@ -82,6 +83,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XJACK.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XLOCKMORE.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XLYAP.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XMATRIX.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XROGER-HACK.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XSCREENSAVER-SGIGL.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE,XLOCKMORE)/INCL=([],[-],[-.UTILS])/OBJ=SCREENHACK-XLOCK.OBJ SCREENHACK.C diff --git a/hacks/compile_decc.com b/hacks/compile_decc.com index 676d5e25..13adf739 100644 --- a/hacks/compile_decc.com +++ b/hacks/compile_decc.com @@ -54,6 +54,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PEDAL.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PENETRATE.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PENROSE.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PHOSPHOR.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PYRO.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) QIX.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) RD-BOMB.C @@ -82,6 +83,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XJACK.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XLOCKMORE.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XLYAP.C +$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XMATRIX.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XROGER-HACK.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XSCREENSAVER-SGIGL.C $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE,XLOCKMORE)/INCL=([],[-],[-.UTILS])/OBJ=SCREENHACK-XLOCK.OBJ SCREENHACK.C diff --git a/hacks/critical.c b/hacks/critical.c index ae3df0b1..17abf8f4 100644 --- a/hacks/critical.c +++ b/hacks/critical.c @@ -308,12 +308,11 @@ screenhack (Display *dpy, Window window) x2 * cell_size + cell_size/2, y2 * cell_size + cell_size/2); - /* Flush changes to display, and discard any pending input -- - we'll never look at it anyhow, and it saves it filling up - memory. */ - XSync (dpy, True); + XSync (dpy, False); + screenhack_handle_events (dpy); - usleep (delay_usecs); + if (delay_usecs) + usleep (delay_usecs); } i_restart = (i_restart + 1) % n_restart; diff --git a/hacks/glx/Makefile.in b/hacks/glx/Makefile.in index 16b8bd68..cd082002 100644 --- a/hacks/glx/Makefile.in +++ b/hacks/glx/Makefile.in @@ -64,17 +64,17 @@ SRCS = atlantis.c b_draw.c b_lockglue.c b_sphere.c bubble3d.c \ morph3d.c pipeobjs.c pipes.c rubik.c s1_1.c s1_2.c s1_3.c \ s1_4.c s1_5.c s1_6.c s1_b.c shark.c sproingies.c \ sproingiewrap.c stairs.c superquadrics.c swim.c whale.c \ - xlock-gl.c xpm-ximage.c glplanet.c + xlock-gl.c xpm-ximage.c glplanet.c pulsar.c OBJS = atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \ buildlwo.o cage.o dolphin.o gears.o lament.o moebius.o \ morph3d.o pipeobjs.o pipes.o rubik.o s1_1.o s1_2.o s1_3.o \ s1_4.o s1_5.o s1_6.o s1_b.o shark.o sproingies.o \ sproingiewrap.o stairs.o superquadrics.o swim.o whale.o \ - xlock-gl.o xpm-ximage.o glplanet.o + xlock-gl.o xpm-ximage.o glplanet.o pulsar.o GL_EXES = cage gears moebius pipes sproingies stairs superquadrics \ - morph3d rubik atlantis lament bubble3d glplanet + morph3d rubik atlantis lament bubble3d glplanet pulsar EXES = @GL_EXES@ HACK_OBJS = screenhack-gl.o xlock-gl.o $(HACK_BIN)/xlockmore.o \ @@ -249,6 +249,9 @@ bubble3d: bubble3d.o $(HACK_OBJS) $(B3D) glplanet: glplanet.o $(HACK_OBJS) xpm-ximage.o $(CC_HACK) -o $@ $@.o $(HACK_OBJS) xpm-ximage.o $(XPM_LIBS) +pulsar: pulsar.o $(HACK_OBJS) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(HACK_LIBS) + ############################################################################## # @@ -505,4 +508,16 @@ glplanet.o: $(UTILS_SRC)/visual.h glplanet.o: $(UTILS_SRC)/xshm.h glplanet.o: $(HACK_SRC)/images/earth.xbm glplanet.o: $(srcdir)/xpm-ximage.h +pulsar.o: $(HACK_SRC)/xlockmore.h +pulsar.o: ../../config.h +pulsar.o: $(HACK_SRC)/xlockmoreI.h +pulsar.o: $(HACK_SRC)/screenhack.h +pulsar.o: $(UTILS_SRC)/yarandom.h +pulsar.o: $(UTILS_SRC)/usleep.h +pulsar.o: $(UTILS_SRC)/resources.h +pulsar.o: $(UTILS_SRC)/hsv.h +pulsar.o: $(UTILS_SRC)/colors.h +pulsar.o: $(UTILS_SRC)/grabscreen.h +pulsar.o: $(UTILS_SRC)/visual.h +pulsar.o: $(UTILS_SRC)/xshm.h diff --git a/hacks/glx/glplanet.c b/hacks/glx/glplanet.c index 7c71fc7d..39ae21bb 100644 --- a/hacks/glx/glplanet.c +++ b/hacks/glx/glplanet.c @@ -323,7 +323,7 @@ setup_file_texture (ModeInfo *mi, char *filename) exit (1); } - setup_xbm_texture (data, width, height, &gp->fg, &gp->bg); + setup_xbm_texture ((char *) data, width, height, &gp->fg, &gp->bg); } #else /* !XMU */ diff --git a/hacks/glx/pulsar.c b/hacks/glx/pulsar.c new file mode 100644 index 00000000..b7a8e433 --- /dev/null +++ b/hacks/glx/pulsar.c @@ -0,0 +1,783 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* pulsar --- pulsar module for xscreensaver */ +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + + * Revision History: + * 4-Apr-1999: dek@cgl.ucsf.edu Created module "pulsar" + * + */ + +#include +#include +#include + +/*- + * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock. + * otherwise caddr_t is not defined correctly + */ + +#include + +#ifdef STANDALONE +# define PROGCLASS "Screensaver" +# define HACK_INIT init_screensaver +# define HACK_DRAW draw_screensaver +# define screensaver_opts xlockmore_opts +#define DEFAULTS "*light: False \n" \ + "*wire: False \n" \ + "*blend: True \n" \ + "*fog: False \n" \ + "*antialias: False \n" \ + "*texture: False \n" \ + "*texture_quality: False \n" \ + "*mipmap: False \n" \ + "*fps: False \n" \ + "*doDepth: False \n" \ + +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL /* whole file */ + +#ifdef HAVE_XPM +# include +# ifndef PIXEL_ALREADY_TYPEDEFED +# define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */ +# endif +#endif + +#ifdef HAVE_XMU +# ifndef VMS +# include +#else /* VMS */ +# include +# endif /* VMS */ +#endif + + +#include +#include + +#include +#include +#include + +/* Functions for loading and storing textures */ + +#define checkImageWidth 64 +#define checkImageHeight 64 + +char *Textures[] = { + "./test.ppm4", +}; + +typedef struct { + int sizeX, sizeY; + GLubyte *data; +} PPMImage; + +/* Functions for handling the frames per second timer */ +#include "GL/glx.h" + +#ifndef SAMPLE_FRAMES +#define SAMPLE_FRAMES 10 +#endif + +static GLint base; +static int FrameCounter = 0; +static double oldtime=-1., newtime=-1.; +static char FPSstring[1024]="FPS: NONE"; + +static float x_pos=0, y_pos=0; + +#define FONT "-*-courier-medium-r-normal-*-240-*" + + + +#define NUM_TRIANGLES 5 +static float scale_x=1, scale_y=1, scale_z=1; +static int frame = 0; +struct triangle +{ + GLfloat tx, ty, tz; + GLfloat rx, ry, rz; + + GLfloat dtx, dty, dtz; + GLfloat drx, dry, drz; + +}; +struct triangle triangles[NUM_TRIANGLES]; +GLint tri_list; + + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#define WIDTH 800 +#define HEIGHT 600 + +int global_width=WIDTH, global_height=HEIGHT; + + +static XrmOptionDescRec opts[] = { + {"-light", ".pulsar.light", XrmoptionNoArg, (caddr_t) "true" }, + {"+light", ".pulsar.light", XrmoptionNoArg, (caddr_t) "false" }, + {"-wire", ".pulsar.wire", XrmoptionNoArg, (caddr_t) "true" }, + {"+wire", ".pulsar.wire", XrmoptionNoArg, (caddr_t) "false" }, + {"-blend", ".pulsar.blend", XrmoptionNoArg, (caddr_t) "true" }, + {"+blend", ".pulsar.blend", XrmoptionNoArg, (caddr_t) "false" }, + {"-fog", ".pulsar.fog", XrmoptionNoArg, (caddr_t) "true" }, + {"+fog", ".pulsar.fog", XrmoptionNoArg, (caddr_t) "false" }, + {"-antialias", ".pulsar.antialias", XrmoptionNoArg, (caddr_t) "true" }, + {"+antialias", ".pulsar.antialias", XrmoptionNoArg, (caddr_t) "false" }, + {"-texture", ".pulsar.texture", XrmoptionNoArg, (caddr_t) "true" }, + {"+texture", ".pulsar.texture", XrmoptionNoArg, (caddr_t) "false" }, + {"-texture_quality", ".pulsar.texture_quality", XrmoptionNoArg, (caddr_t) "true" }, + {"+texture_quality", ".pulsar.texture_quality", XrmoptionNoArg, (caddr_t) "false" }, + {"-mipmap", ".pulsar.mipmap", XrmoptionNoArg, (caddr_t) "true" }, + {"+mipmap", ".pulsar.mipmap", XrmoptionNoArg, (caddr_t) "false" }, + {"-fps", ".pulsar.fps", XrmoptionNoArg, (caddr_t) "true" }, + {"+fps", ".pulsar.fps", XrmoptionNoArg, (caddr_t) "false" }, + {"-do_depth", ".pulsar.doDepth", XrmoptionNoArg, (caddr_t) "true" }, + {"+do_depth", ".pulsar.doDepth", XrmoptionNoArg, (caddr_t) "false" }, +}; + +#define DEF_LIGHT "False" +#define DEF_WIRE "False" +#define DEF_BLEND "True" +#define DEF_FOG "False" +#define DEF_ANTIALIAS "False" +#define DEF_TEXTURE "False" +#define DEF_TEXTURE_QUALITY "False" +#define DEF_MIPMAP "False" +#define DEF_FPS "False" +#define DEF_DO_DEPTH "False" + +static int do_light; +static int do_wire; +static int do_blend; +static int do_fog; +static int do_antialias; +static int do_texture; +static int do_texture_quality; +static int do_mipmap; +static int do_fps; +static int do_depth; + +static argtype vars[] = { + {(caddr_t *) &do_light, "light", "Light", DEF_LIGHT, t_Bool}, + {(caddr_t *) &do_wire, "wire", "Wire", DEF_WIRE, t_Bool}, + {(caddr_t *) &do_blend, "blend", "Blend", DEF_BLEND, t_Bool}, + {(caddr_t *) &do_fog, "fog", "Fog", DEF_FOG, t_Bool}, + {(caddr_t *) &do_antialias, "antialias", "Antialias", DEF_ANTIALIAS, t_Bool}, + {(caddr_t *) &do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {(caddr_t *) &do_texture_quality, "texture_quality", "Texture_quality", DEF_TEXTURE_QUALITY, t_Bool}, + {(caddr_t *) &do_mipmap, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool}, + {(caddr_t *) &do_fps, "fps", "fps", DEF_FPS, t_Bool}, + {(caddr_t *) &do_depth, "doDepth", "DoDepth", DEF_DO_DEPTH, t_Bool}, +}; + + +ModeSpecOpt screensaver_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct screensaver_description = +{"screensaver", "init_screensaver", "draw_screensaver", "release_screensaver", + "draw_screensaver", "init_screensaver", NULL, &screensaver_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "OpenGL screensaver", 0, NULL}; +#endif + + +/* structure for holding the screensaver data */ +typedef struct { + int screen_width, screen_height; + GLXContext *glx_context; + Window window; + XColor fg, bg; +} screensaverstruct; + +static screensaverstruct *Screensaver = NULL; + + +void FPS_Setup(void) +{ + Display *Dpy; + XFontStruct *fontInfo; + Font id; + int first=0, last=255; + + Dpy = XOpenDisplay(NULL); + fontInfo = XLoadQueryFont(Dpy, FONT); + if (fontInfo == NULL) + { + fprintf(stderr, "Failed to load font %s\n", FONT); + exit(1); + } + + id = fontInfo->fid; + first = fontInfo->min_char_or_byte2; + last = fontInfo->max_char_or_byte2; + + base = glGenLists((GLuint) last+1); + if (base == 0) { + fprintf (stderr, "out of display lists\n"); + exit(1); + } + glXUseXFont(id, first, last-first+1, base+first); + +} + +void PrintString(float x, float y, char *string) +{ + int len, i; + + /* save the current state */ + /* note: could be expensive! */ + glPushAttrib(GL_ALL_ATTRIB_BITS); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, global_width, 0, global_height); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + /* disable lighting and texturing when drawing bitmaps! */ + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glDisable(GL_BLEND); + + /* draw a black background */ + + /* draw the text */ + glColor3f(1,1,1); + glRasterPos2f( x, y); + len = (int) strlen(string); + for (i = 0; i < len; i++) { + glCallList(base+string[i]); + } + + /* clean up after our state changes */ + glPopAttrib(); +} + +double gettime(void) +{ + struct timeval now; +#ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone tzp; + gettimeofday(&now, &tzp); +#else + gettimeofday(&now); +#endif + return (double) (now.tv_sec + (((double) now.tv_usec) * 0.000001)); +} + +void DoFPS(void) +{ + /* every SAMPLE_FRAMES frames, get the time and use it to get the + frames per second */ + if (!(FrameCounter % SAMPLE_FRAMES)) { + oldtime = newtime; + newtime = gettime(); + sprintf(FPSstring, "FPS: %.02f", SAMPLE_FRAMES/(newtime-oldtime)); + } + + PrintString(x_pos,y_pos,FPSstring); + + FrameCounter++; +} + +GLubyte *Generate_Image(int *width, int *height, int *format) +{ + GLubyte *result; + int i, j, c; + int counter=0; + + *width = checkImageWidth; + *height = checkImageHeight; + result = (GLubyte *)malloc(4 * *width * *height); + + counter = 0; + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + c = (((((i&0x8)==0))^(((j&0x8))==0)))*255; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) 255; + } + } + + *format = GL_RGBA; + return result; +} + + + +#ifdef TIFF +#include +/* Load a TIFF texture: requires libtiff */ +uint32 *LoadTIFF(char *filename, int *width, int *height, int *format) +{ + TIFF *tif; + char emsg[1024]; + uint32 *raster; + TIFFRGBAImage img; + tsize_t npixels; + + tif = TIFFOpen(filename, "r"); + if (tif == NULL) { + fprintf(stderr, "Problem showing %s\n", filename); + return Generate_Image(&width, &height, &format); + } + if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) { + npixels = (tsize_t) (img.width * img.height); + raster = (uint32 *) _TIFFmalloc(npixels * (tsize_t) sizeof(uint32)); + if (raster != NULL) { + if (TIFFRGBAImageGet(&img, raster, img.width, img.height) == 0) { + TIFFError(filename, emsg); + return Generate_Image(&width, &height, &format); + } + } + TIFFRGBAImageEnd(&img); + } else { + TIFFError(filename, emsg); + return Generate_Image(&width, &height, &format); + } + + *width = img.width; + *height = img.height; + *format = GL_RGBA; + + TIFFClose(tif); + return raster; +} +#endif + + +/* Load a modified version of PPM format with an extra byte for alpha */ +GLubyte *LoadPPM4(const char *filename, int *width, int *height, int *format) +{ + char buff[1024]; + PPMImage *result; + FILE *fp; + int maxval; + + fp = fopen(filename, "rb"); + if (!fp) + { + fprintf(stderr, "Unable to open file '%s'\n", filename); + return Generate_Image(width, height, format); + } + + if (!fgets(buff, sizeof(buff), fp)) + { + perror(filename); + return Generate_Image(width, height, format); + } + + if (buff[0] != '6' || buff[1] != 'P') + { + fprintf(stderr, "Invalid image format (must be `6P')\n"); + return Generate_Image(width, height, format); + } + + result = malloc(sizeof(PPMImage)); + if (!result) + { + fprintf(stderr, "Unable to allocate memory\n"); + return Generate_Image(width, height, format); + } + + do + { + fgets(buff, sizeof(buff), fp); + } + while (buff[0] == '#'); + + if (sscanf(buff, "%d %d", &result->sizeX, &result->sizeY) != 2) + { + fprintf(stderr, "Error loading image `%s'\n", filename); + return Generate_Image(width, height, format); + } + + if (fscanf(fp, "%d", &maxval) != 1) + { + fprintf(stderr, "Error loading image `%s'\n", filename); + return Generate_Image(width, height, format); + } + + while (fgetc(fp) != '\n') + ; + + result->data = (GLubyte *)malloc(4 * result->sizeX * result->sizeY); + if (!result) + { + fprintf(stderr, "Unable to allocate memory\n"); + exit(1); + } + + if (fread(result->data, 4 * result->sizeX, result->sizeY, fp) != result->sizeY) + { + fprintf(stderr, "Error loading image `%s'\n", filename); + return Generate_Image(width, height, format); + } + + fclose(fp); + + *width = result->sizeX; + *height = result->sizeY; + *format = GL_RGBA; + return result->data; +} + +/* Load a plain PPM image */ +GLubyte *LoadPPM(const char *filename, int *width, int *height, int *format) +{ + char buff[1024]; + PPMImage *result; + FILE *fp; + int maxval; + + fp = fopen(filename, "rb"); + if (!fp) + { + fprintf(stderr, "Unable to open file '%s'\n", filename); + return Generate_Image(width, height, format); + exit(1); + } + if (!fgets(buff, sizeof(buff), fp)) + { + perror(filename); + return Generate_Image(width, height, format); + } + + if (buff[0] != 'P' || buff[1] != '6') + { + fprintf(stderr, "Invalid image format (must be `P6')\n"); + return Generate_Image(width, height, format); + } + + result = malloc(sizeof(PPMImage)); + if (!result) + { + fprintf(stderr, "Unable to allocate memory\n"); + return Generate_Image(width, height, format); + } + + do + { + fgets(buff, sizeof(buff), fp); + } + while (buff[0] == '#'); + + if (sscanf(buff, "%d %d", &result->sizeX, &result->sizeY) != 2) + { + fprintf(stderr, "Error loading image `%s'\n", filename); + return Generate_Image(width, height, format); + } + + if (fscanf(fp, "%d", &maxval) != 1) + { + fprintf(stderr, "Error loading image `%s'\n", filename); + return Generate_Image(width, height, format); + } + + while (fgetc(fp) != '\n') + ; + + result->data = (GLubyte *)malloc(3 * result->sizeX * result->sizeY); + if (!result) + { + fprintf(stderr, "Unable to allocate memory\n"); + return Generate_Image(width, height, format); + } + + if (fread(result->data, 3 * result->sizeX, result->sizeY, fp) != result->sizeY) + { + fprintf(stderr, "Error loading image `%s'\n", filename); + return Generate_Image(width, height, format); + } + + fclose(fp); + + *width = result->sizeX; + *height = result->sizeY; + *format = GL_RGB; + return result->data; +} + +/* Create a texture in OpenGL. First an image is loaded + and stored in a raster buffer, then it's */ +void Create_Texture(char *filename) +{ + int height, width; + GLubyte *image; + GLint a; + int format; + + fprintf(stdout, "Loading texture '%s'\n", filename); + + if ( !strncmp((filename+strlen(filename)-3), "ppm", 3)) + image = LoadPPM(filename, &width, &height, &format); + else if ( !strncmp((filename+strlen(filename)-4), "ppm4", 4)) + image = LoadPPM4(filename, &width, &height, &format); +#ifdef TIFF + else if ( !strncmp((filename+strlen(filename)-4), "tiff", 4)) + image = (GLubyte *)LoadTIFF(filename, &width, &height, &format); +#endif + else { + fprintf(stderr, "Unknown file format extension: '%s'\n", filename); + image = Generate_Image(&width, &height, &format); + } + + /* GL_MODULATE or GL_DECAL depending on what you want */ + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + if (do_texture_quality) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + } + else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + } + + if (do_mipmap) + a=gluBuild2DMipmaps(GL_TEXTURE_2D, format, width, height, format, GL_UNSIGNED_BYTE, image); + else + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, + format, GL_UNSIGNED_BYTE, image); + + free(image); +} + +void resetProjection(void) { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1, 1, -1, 1, 1, 100); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + + +void GenerateTriangle(void) +{ + int i; + + tri_list = glGenLists(1); + glNewList(tri_list,GL_COMPILE); +/* glBegin(GL_TRIANGLES); */ + glBegin(GL_QUADS); + glColor4f(1,0,0,.4); glNormal3f(0,0,1); glTexCoord2f(0,0); glVertex2f(-1, -1); + glColor4f(0,1,0,.4); glNormal3f(0,0,1); glTexCoord2f(0,1); glVertex2f(-1, 1); + glColor4f(0,0,1,.4); glNormal3f(0,0,1); glTexCoord2f(1,1); glVertex2f( 1, 1); + glColor4f(1,1,1,1); glNormal3f(0,0,1); glTexCoord2f(1,0); glVertex2f( 1, -1); + glEnd(); + glEndList(); + + for (i=0; i < NUM_TRIANGLES; i++) + { + triangles[i].rx = 0.; + triangles[i].ry = 0.; + triangles[i].rz = 0.; + triangles[i].tx = 0.; + triangles[i].ty = 0.; + triangles[i].tz = -10; + + triangles[i].drx = drand48() * 5.; + triangles[i].dry = drand48() * 5.; + triangles[i].drz = 0; + } +} + +void initializeGL(GLsizei width, GLsizei height) +{ + GLfloat fogColor[4] = { 0.1, 0.1, 0.1, 0.1 }; + + global_width=width; + global_height=height; + + glViewport( 0, 0, width, height ); + resetProjection(); + + if (do_depth) + glEnable(GL_DEPTH_TEST); + + if (do_fps) + FPS_Setup(); + + if (do_antialias) { + do_blend = 1; + glEnable(GL_LINE_SMOOTH); + } + + if (do_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + + if (do_light) { + glShadeModel(GL_SMOOTH); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + } + + if (do_wire) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + else + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + if (do_fog) { + glEnable(GL_FOG); + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogfv(GL_FOG_COLOR, fogColor); + glFogf(GL_FOG_DENSITY, 0.35); +/* glHint(GL_FOG_HINT, GL_FASTEST); */ + glFogf(GL_FOG_START, 50.0); + glFogf(GL_FOG_END, 100.0); + } + + + if (do_texture) + { + Create_Texture(Textures[0]); + } + + GenerateTriangle(); +} +void drawTriangles(void) { + int i; + for (i=0; i < NUM_TRIANGLES; i++) + { + glPushMatrix(); + glTranslatef(triangles[i].tx,0,0); + glTranslatef(0,triangles[i].ty,0); + glTranslatef(0,0,triangles[i].tz); + glRotatef(triangles[i].rx, 1,0,0); + glRotatef(triangles[i].ry, 0,1,0); + glRotatef(triangles[i].rz, 0,0,1); + glCallList(tri_list); + glPopMatrix(); + + triangles[i].rx += triangles[i].drx; + triangles[i].ry += triangles[i].dry; + triangles[i].rz += triangles[i].drz; + + } +} + +GLvoid drawScene(GLvoid) +{ + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* we have to do this here because the FPS meter turns these 3 features off!! */ + { + if (do_light) { + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + } + + if (do_texture) { + glEnable(GL_TEXTURE_2D); + } + + if (do_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + } + + resetProjection(); + glScalef(scale_x, scale_y, scale_z); + drawTriangles(); + + scale_x = cos(frame/360.)*10.; + scale_y = sin(frame/360.)*10.; + scale_z = 1; + + frame++; + DoFPS(); +} + + +void draw_screensaver(ModeInfo * mi) +{ + screensaverstruct *gp = &Screensaver[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!gp->glx_context) + return; + + glXMakeCurrent(display, window, *(gp->glx_context)); + drawScene(); + glXSwapBuffers(display, window); +} + +/* Standard reshape function */ +static void +reshape(int width, int height) +{ + glViewport( 0, 0, global_width, global_height ); + resetProjection(); +} + +void +init_screensaver(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + + screensaverstruct *gp; + + if (Screensaver == NULL) { + if ((Screensaver = (screensaverstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (screensaverstruct))) == NULL) + return; + } + gp = &Screensaver[screen]; + + gp->window = MI_WINDOW(mi); + if ((gp->glx_context = init_GL(mi)) != NULL) { + reshape(MI_WIDTH(mi), MI_HEIGHT(mi)); + initializeGL(MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } +} + + +/* all sorts of nice cleanup code should go here! */ +void release_screensaver(ModeInfo * mi) +{ + int screen; + if (Screensaver != NULL) { + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { +/* screensaverstruct *gp = &Screensaver[screen];*/ + } + (void) free((void *) Screensaver); + Screensaver = NULL; + } + FreeAllGL(mi); +} +#endif + diff --git a/hacks/images/matrix.xbm b/hacks/images/matrix.xbm new file mode 100644 index 00000000..9d297513 --- /dev/null +++ b/hacks/images/matrix.xbm @@ -0,0 +1,394 @@ +#define matrix_width 56 +#define matrix_height 837 +static char matrix_bits[] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xf7,0xff,0xff,0x7b,0xff, + 0xff,0xaf,0xc8,0xff,0xff,0x4d,0xfd,0xff,0x0f,0x22,0xff,0x7f,0x75,0xfb,0xff, + 0x17,0x89,0xff,0xff,0xda,0xf5,0xff,0x47,0x25,0xfe,0xff,0xfd,0xfb,0xff,0x0b, + 0x1f,0xff,0x7f,0xfa,0xf2,0xff,0x85,0x17,0xfe,0xbf,0xfd,0xf5,0xff,0x45,0x9d, + 0xfe,0x7f,0xf5,0xf7,0xff,0x52,0x17,0xfd,0xaf,0xfd,0xe9,0xff,0x81,0x1f,0xfe, + 0xbf,0xfe,0xf7,0xff,0x4a,0x2d,0xfa,0xbf,0xfa,0xe9,0xff,0xa1,0x1f,0xfd,0xbf, + 0xfd,0xf7,0xff,0x92,0x2e,0xfc,0xdf,0xda,0xe9,0xff,0x85,0x9b,0xfe,0x7f,0xfd, + 0xf7,0xff,0x52,0x0f,0xfe,0xdf,0xfa,0xf2,0xff,0x85,0x3d,0xfe,0xff,0xfa,0xfb, + 0xff,0x47,0x8f,0xfe,0x7f,0xf9,0xea,0xff,0x0b,0x15,0xfe,0xff,0xdd,0xf5,0xff, + 0x87,0x0b,0xff,0x7f,0x75,0xfb,0xff,0x17,0xad,0xfe,0xff,0xff,0xfe,0xff,0x5f, + 0xa1,0xff,0xff,0x4b,0xff,0xff,0x5f,0xd4,0xff,0xff,0xff,0xff,0xff,0x77,0xeb, + 0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xff, + 0xff,0xff,0xf4,0xff,0xff,0x57,0xff,0xff,0x3f,0x90,0xff,0xff,0x4b,0xfd,0xff, + 0x7f,0x48,0xff,0xff,0xa7,0xff,0xff,0x7f,0xe8,0xff,0xff,0xcf,0xff,0xff,0x3f, + 0xe8,0xff,0xff,0xa7,0xff,0xff,0x7f,0xf8,0xff,0xff,0xcb,0xff,0xff,0x3f,0xfc, + 0xff,0xff,0xcf,0xff,0xff,0x7f,0xf8,0xff,0xff,0xc7,0xff,0xff,0x3f,0xfa,0xff, + 0xff,0xeb,0xff,0xff,0x7f,0xf8,0xff,0xff,0xa7,0xff,0xff,0x3f,0xfc,0xff,0xff, + 0xcf,0xff,0xff,0x7f,0xf8,0xff,0xff,0xe7,0xff,0xff,0x3f,0xfa,0xff,0xff,0xcb, + 0xff,0xff,0x7f,0xf8,0xff,0xff,0xcf,0xff,0xff,0x3f,0xfc,0xff,0xff,0xc7,0xff, + 0xff,0x7f,0xf8,0xff,0xff,0xd7,0xff,0xff,0x3f,0xfc,0xff,0xff,0xcb,0xff,0xff, + 0x7f,0xf8,0xff,0xff,0xcf,0xff,0xff,0x3f,0xf8,0xff,0xff,0xe7,0xff,0xff,0x5f, + 0xfa,0xff,0xff,0xad,0xff,0xff,0x3f,0xe8,0xff,0xff,0xd7,0xff,0xff,0x57,0xf5, + 0xff,0xff,0xff,0xff,0xff,0xbf,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x7f,0xfb,0xff,0xff,0xed,0xff,0xff,0x4f,0xad,0xff,0xff,0xb5,0xfa,0xff, + 0x0f,0x12,0xff,0x7f,0x79,0xfb,0xff,0x07,0x09,0xff,0xff,0xea,0xf5,0xff,0x97, + 0x2a,0xff,0x7f,0xfd,0xff,0xff,0x87,0x5e,0xff,0xff,0xf4,0xf5,0xff,0x4b,0x2b, + 0xff,0xff,0xfa,0xff,0xff,0x05,0xbf,0xff,0xff,0xfa,0xff,0xff,0x8b,0xfd,0xff, + 0xff,0xfa,0xff,0xff,0x47,0xf7,0xff,0xff,0xda,0xff,0xff,0x8f,0xfe,0xff,0xff, + 0xf5,0xff,0xff,0x27,0xfa,0xff,0xff,0xdb,0xff,0xff,0x1f,0xfd,0xff,0xff,0xee, + 0xff,0xff,0xaf,0xea,0xff,0xff,0x57,0xff,0xff,0x5f,0xf4,0xff,0xff,0xef,0xff, + 0xff,0x77,0xd1,0xff,0xff,0xbb,0xfe,0xff,0xaf,0xd4,0xff,0xbf,0x5f,0xfd,0xff, + 0xbb,0x42,0xff,0xff,0x75,0xfb,0xff,0x4f,0x29,0xff,0x7f,0xdf,0xfa,0xff,0x25, + 0x05,0xff,0xff,0x55,0xfb,0xff,0x97,0x40,0xff,0x7f,0xab,0xfa,0xff,0x2f,0x12, + 0xff,0xff,0x75,0xfd,0xff,0x8b,0x44,0xff,0xff,0xdf,0xff,0xff,0x7f,0xb5,0xff, + 0xff,0xff,0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0xf5,0xff,0xff,0x55,0xff,0xff, + 0x8f,0xd2,0xff,0xff,0x7a,0xfd,0xff,0x17,0x44,0xff,0x7f,0x55,0xff,0xff,0x07, + 0xa3,0xff,0xff,0xf9,0xfb,0xff,0x4f,0xa9,0xff,0xff,0xfc,0xfe,0xff,0x05,0x57, + 0xff,0xff,0xda,0xff,0xff,0x8b,0xad,0xff,0x7f,0xf5,0xff,0xff,0x47,0xfa,0xff, + 0xff,0xba,0xff,0xff,0x0f,0xfd,0xff,0xff,0xea,0xff,0xff,0x0f,0xf5,0xff,0xff, + 0xd5,0xff,0xff,0x47,0xfc,0xff,0x7f,0xf5,0xff,0xff,0x17,0xf5,0xff,0xff,0xaa, + 0xff,0xff,0x05,0xfa,0xff,0xbf,0xfd,0xff,0xff,0x4b,0xfd,0xff,0xff,0xf6,0xff, + 0xff,0x25,0xfb,0xff,0x5f,0xfd,0xff,0xff,0x91,0xff,0xff,0xbf,0xfb,0xff,0xff, + 0xc5,0xb6,0xff,0x7f,0xdd,0xfb,0xff,0x15,0x5b,0xff,0xff,0xfd,0xfa,0xff,0xc7, + 0x0d,0xff,0xff,0x76,0xfb,0xff,0x95,0x26,0xff,0xff,0xdd,0xff,0xff,0x5f,0x91, + 0xff,0xff,0x77,0xfd,0xff,0xaf,0xd4,0xff,0xff,0xdf,0xff,0xff,0x5f,0xd5,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x5f,0xfd,0xff,0xff,0xd7,0xff,0xff,0x7f,0xfc,0xff,0xff,0xe5,0xff,0xff,0x17, + 0xf8,0xff,0xff,0xab,0xff,0xff,0xaf,0xf4,0xff,0xff,0xd7,0xff,0xff,0x2f,0xe8, + 0xff,0xff,0x55,0xff,0xff,0x9f,0xe4,0xff,0x7f,0xaf,0xfe,0xff,0x57,0xd0,0xff, + 0xff,0x55,0xff,0xff,0x2f,0xa2,0xff,0xff,0xaf,0xfa,0xff,0x5f,0x11,0xff,0xff, + 0x6a,0xfb,0xff,0x2f,0x44,0xff,0xff,0xad,0xf5,0xff,0x97,0x22,0xfe,0xff,0xd6, + 0xfa,0xff,0x2b,0x14,0xfd,0xff,0x55,0xeb,0xff,0x8f,0x48,0xfe,0xff,0x6a,0xf5, + 0xff,0x05,0x02,0xfa,0x7f,0x91,0xed,0xff,0x17,0x50,0xfd,0xff,0x4a,0xf5,0xff, + 0x03,0x08,0xfd,0x7f,0xeb,0xff,0xff,0x4d,0xd2,0xfe,0xff,0xb5,0xfe,0xff,0x2f, + 0xfa,0xff,0xff,0xef,0xff,0xff,0x57,0xed,0xff,0xff,0xfb,0xff,0xff,0xaf,0xfc, + 0xff,0xff,0xff,0xff,0xff,0x5f,0xff,0xff,0xff,0xef,0xff,0xff,0x7f,0xfd,0xff, + 0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff, + 0xaf,0xf6,0xff,0xff,0x55,0xff,0xff,0x5f,0xc1,0xff,0xff,0x5f,0xfd,0xff,0x97, + 0xa8,0xff,0xff,0xaa,0xfe,0xff,0x17,0x81,0xff,0xff,0x5f,0xfd,0xff,0x6f,0x62, + 0xff,0xff,0xf7,0xfe,0xff,0xbf,0x95,0xff,0xff,0x5f,0xfb,0xff,0xdf,0xa2,0xff, + 0xff,0xfe,0xfe,0xff,0xbf,0x4a,0xff,0xff,0x2b,0xfd,0xff,0xaf,0xa0,0xff,0xff, + 0xab,0xfe,0xff,0x17,0x80,0xff,0x7f,0x55,0xfb,0xff,0x4f,0xd5,0xff,0xff,0xfa, + 0xff,0xff,0x05,0xd2,0xff,0xff,0x6d,0xff,0xff,0x4b,0xf5,0xff,0x5f,0xf9,0xff, + 0xff,0x85,0xfe,0xff,0x7f,0xfd,0xff,0xff,0x13,0xf7,0xff,0xdf,0xf6,0xff,0xff, + 0xc5,0xfd,0xff,0xbf,0xfd,0xff,0xff,0x51,0xff,0xff,0xff,0xbe,0xff,0xff,0x8f, + 0xa5,0xff,0xff,0xf5,0xfa,0xff,0x4b,0x2b,0xff,0xff,0xfe,0xff,0xff,0x97,0x95, + 0xff,0xff,0xb7,0xfa,0xff,0xaf,0x4a,0xff,0xff,0xdf,0xff,0xff,0x5f,0xe5,0xff, + 0xff,0x7b,0xff,0xff,0x7f,0xd2,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfe,0xff,0xff,0xeb,0xff,0xff, + 0x3f,0xfd,0xff,0xff,0xff,0xff,0xff,0xaf,0xfa,0xff,0xff,0xad,0xff,0xff,0x7f, + 0xe9,0xff,0xff,0xff,0xfe,0xff,0xbf,0xd2,0xff,0xff,0x2f,0xff,0xff,0xff,0xc2, + 0xff,0xff,0xff,0xfa,0xff,0x7f,0x2b,0xff,0xff,0xbf,0xfb,0xff,0xff,0x15,0xff, + 0xff,0xff,0xf5,0xff,0x7f,0x8b,0xfe,0xff,0x5b,0xf5,0xff,0x4f,0x11,0xfe,0x7f, + 0x6d,0xf1,0xff,0x97,0x04,0xff,0xff,0xa9,0xf4,0xff,0x0f,0x01,0xfe,0x7f,0xdd, + 0xf2,0xff,0x45,0x14,0xfe,0xff,0xf5,0xf5,0xff,0x0b,0x8b,0xfe,0xbf,0xfe,0xf5, + 0xff,0xc2,0x1d,0xff,0xdf,0xba,0xf7,0xff,0x2b,0x17,0xfe,0x7f,0xfd,0xf2,0xff, + 0x81,0x9d,0xfe,0xbf,0xff,0xfb,0xff,0x55,0x17,0xfe,0xff,0xfa,0xf5,0xff,0xa5, + 0x1b,0xff,0x7f,0xfb,0xf5,0xff,0x4b,0x8d,0xfe,0xff,0xbd,0xfa,0xff,0x0f,0x27, + 0xff,0x7f,0xf5,0xf7,0xff,0xcb,0x92,0xfe,0xff,0x7f,0xfd,0xff,0xaf,0xaa,0xff, + 0xff,0xd7,0xff,0xff,0x5f,0xd5,0xff,0xff,0x7f,0xff,0xff,0x7f,0xf5,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x5f,0xf5,0xff,0xff,0xdb,0xff,0xff,0xef,0x96,0xff,0xff,0x7e,0xfd,0xff,0x1f, + 0x55,0xff,0xff,0xa9,0xf7,0xff,0x87,0x90,0xfe,0xff,0x74,0xf9,0xff,0x0f,0x0a, + 0xfd,0xff,0xd2,0xee,0xff,0x07,0x49,0xfe,0xff,0xfa,0xfb,0xff,0x17,0x55,0xff, + 0xff,0xad,0xff,0xff,0x4f,0xfa,0xff,0xff,0xfb,0xff,0xff,0x17,0xbd,0xff,0xff, + 0xee,0xff,0xff,0xaf,0xfa,0xff,0xff,0xd7,0xff,0xff,0x5f,0xfa,0xff,0xff,0xef, + 0xff,0xff,0x7f,0xfa,0xff,0xff,0xb7,0xff,0xff,0xbf,0xf8,0xff,0xff,0xef,0xff, + 0xff,0x7f,0xed,0xff,0xff,0xbf,0xff,0xff,0xbf,0xf4,0xff,0xff,0xef,0xff,0xff, + 0xff,0xea,0xff,0xff,0xbf,0xfe,0xff,0xff,0xe5,0xff,0xff,0x7f,0xff,0xff,0xff, + 0xe7,0xff,0xff,0x7f,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xfd,0xff,0xff,0xa5, + 0xff,0xff,0xbf,0xfe,0xff,0xff,0xa7,0xff,0xff,0xff,0xfb,0xff,0xff,0x57,0xff, + 0xff,0xff,0xff,0xff,0xff,0x2f,0xff,0xff,0xff,0xfb,0xff,0xff,0xbf,0xff,0xff, + 0xff,0xff,0xff,0xff,0x5f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xff,0xff,0x6f,0xff,0xff,0xbf,0xd4, + 0xff,0xff,0xfb,0xff,0xff,0xaf,0x56,0xff,0xff,0xb6,0xfa,0xff,0x5f,0x29,0xff, + 0xff,0xfb,0xf5,0xff,0x87,0x8e,0xfe,0x7f,0xd9,0xf5,0xff,0x8f,0x12,0xfe,0xff, + 0xfd,0xf5,0xff,0x0f,0x1b,0xff,0xff,0x74,0xf3,0xff,0x07,0x15,0xfe,0xff,0xda, + 0xfa,0xff,0x97,0x8a,0xfe,0xff,0x6b,0xf5,0xff,0x0f,0x01,0xfe,0xff,0x15,0xf2, + 0xff,0x5f,0x20,0xff,0xff,0x56,0xf9,0xff,0x17,0x04,0xfe,0xff,0xab,0xea,0xff, + 0x4f,0x10,0xfd,0x7f,0xa5,0xf5,0xff,0x17,0x82,0xfe,0xff,0xda,0xf5,0xff,0x4f, + 0x28,0xfe,0xff,0xe9,0xf6,0xff,0x0f,0x16,0xfd,0xff,0xfd,0xeb,0xff,0x87,0x55, + 0xfd,0xff,0xb4,0xff,0xff,0x97,0x2e,0xfa,0xff,0xfb,0xea,0xff,0x0f,0x9b,0xfe, + 0x7f,0xf9,0xf3,0xff,0x47,0x1d,0xfd,0xff,0xfd,0xeb,0xff,0x97,0x16,0xfe,0xff, + 0xd7,0xfd,0xff,0x4f,0xab,0xfe,0xff,0x7d,0xf7,0xff,0x7f,0x55,0xff,0xff,0xff, + 0xff,0xff,0xbf,0xaa,0xff,0xff,0xb7,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe8, + 0xff,0xff,0x5f,0xff,0xff,0xbf,0xd6,0xff,0xff,0xf7,0xfd,0xff,0xaf,0x52,0xff, + 0xff,0xdd,0xf7,0xff,0x5f,0x2d,0xff,0xff,0xf5,0xfa,0xff,0x07,0x15,0xfe,0xff, + 0xfa,0xeb,0xff,0x97,0xae,0xfe,0xff,0xdd,0xfd,0xff,0x4f,0x1b,0xfa,0xff,0xfa, + 0xf7,0xff,0x8f,0xae,0xfd,0xff,0xfd,0xdb,0xff,0x47,0x5b,0xfc,0xff,0xf4,0xf6, + 0xff,0x0f,0x2f,0xfb,0xff,0xda,0xf7,0xff,0x8f,0x9a,0xfc,0xff,0xfa,0xea,0xff, + 0x87,0x2a,0xfe,0xff,0x55,0xfb,0xff,0x17,0x04,0xfd,0xff,0x50,0xe9,0xff,0x0f, + 0x81,0xfe,0xff,0xad,0xfa,0xff,0x07,0x14,0xff,0xff,0xd6,0xff,0xff,0x5f,0x50, + 0xff,0xff,0xeb,0xff,0xff,0x97,0xfc,0xff,0xff,0x57,0xff,0xff,0x3f,0xea,0xff, + 0xff,0xef,0xff,0xff,0xbf,0xe8,0xff,0xff,0xaf,0xfe,0xff,0x7f,0xe4,0xff,0xff, + 0x77,0xff,0xff,0xff,0xd2,0xff,0xff,0xbf,0xff,0xff,0x7f,0xd5,0xff,0xff,0xff, + 0xfd,0xff,0xff,0x57,0xff,0xff,0x7f,0xff,0xff,0xff,0xab,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0x7f,0xff,0xff,0xff,0xe2,0xff,0xff, + 0x5f,0xff,0xff,0xff,0xe5,0xff,0xff,0xbf,0xfe,0xff,0xff,0xd3,0xff,0xff,0x7f, + 0xff,0xff,0xff,0xe1,0xff,0xff,0xbf,0xfe,0xff,0xff,0xc7,0xff,0xff,0x7f,0xff, + 0xff,0xff,0xe1,0xff,0xff,0xbf,0xfd,0xff,0xff,0x97,0xff,0xff,0xff,0xfe,0xff, + 0xff,0x53,0xff,0xff,0xff,0xfb,0xff,0x7f,0xab,0xff,0xff,0x7f,0xff,0xff,0xdf, + 0x16,0xff,0xff,0xed,0xf5,0xff,0x5f,0xad,0xfe,0xff,0xff,0xfb,0xff,0xa7,0x3f, + 0xff,0xff,0xfa,0xfb,0xff,0x5b,0x8d,0xfe,0x7f,0xff,0xf7,0xff,0xa5,0x3f,0xff, + 0xbf,0xed,0xfa,0xff,0x92,0x8a,0xfc,0xaf,0xbe,0xa5,0xff,0xc9,0x0a,0xe2,0xbf, + 0xd6,0x52,0xff,0x20,0x02,0xd0,0x9f,0xbd,0xaa,0xff,0xa1,0x55,0xe8,0xff,0xff, + 0xff,0xfe,0xf5,0x56,0xf7,0xbf,0xff,0xff,0xff,0xf5,0xff,0xfd,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff, + 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xef,0xff,0xff,0xaf,0xfc,0xff,0xff, + 0xf5,0xff,0xff,0x2f,0xfd,0xff,0xff,0xdb,0xff,0xff,0x5f,0xfa,0xff,0xff,0xb7, + 0xff,0xff,0x7f,0xe9,0xff,0xff,0xdf,0xfe,0xff,0xbf,0xe4,0xff,0xff,0x7f,0xff, + 0xff,0xff,0xd2,0xff,0xff,0xdf,0xfd,0xff,0xff,0x4b,0xff,0xff,0x7f,0xf7,0xff, + 0xff,0x2d,0xff,0xff,0xff,0xfb,0xff,0xff,0x17,0xfe,0xff,0xff,0xf5,0xff,0xff, + 0x5f,0xff,0xff,0xff,0xf5,0xff,0xff,0x1f,0xfd,0xff,0xff,0xf7,0xff,0xff,0x17, + 0xfe,0xff,0x7f,0xfb,0xff,0xff,0xad,0xff,0xff,0xff,0xff,0xff,0xff,0x53,0xff, + 0xff,0xbf,0xfe,0xff,0xff,0xe5,0xff,0xff,0xdf,0xff,0xff,0x7f,0xea,0xff,0xff, + 0x6b,0xff,0xff,0xbf,0xf4,0xff,0xff,0xef,0xff,0xff,0x7f,0xfa,0xff,0xff,0xef, + 0xff,0xff,0x2f,0xfc,0xff,0xff,0xfb,0xff,0xff,0x9f,0xff,0xff,0xff,0xfd,0xff, + 0xff,0x57,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x7f,0xe5,0xff,0xff,0xb7,0xfe,0xff,0x5f,0xa9,0xff,0xff,0x7d, + 0xff,0xff,0x57,0x45,0xff,0xbf,0xbf,0xfa,0xff,0x55,0x53,0xfd,0xff,0x76,0xed, + 0xff,0xab,0x83,0xfa,0xbf,0xbf,0xf6,0xff,0xd1,0x51,0xfa,0x6f,0x7f,0xbf,0xff, + 0x6a,0xc7,0xfa,0xbf,0x7f,0xed,0xff,0xf1,0xa1,0xea,0xbf,0x7f,0xbf,0xff,0xf4, + 0xd7,0xea,0xdf,0xbe,0xf5,0xfe,0xd2,0x4b,0xd5,0xbf,0xff,0xdf,0x7d,0xf9,0xa5, + 0xca,0xaf,0xff,0xf5,0xfe,0xe2,0x1f,0xa6,0x7f,0xff,0xbb,0xff,0xb9,0x57,0xd5, + 0xaf,0xff,0xed,0xfd,0xe0,0x2f,0xca,0x7f,0xfb,0x77,0xff,0xf5,0x9f,0xea,0xbf, + 0xef,0xdb,0xff,0x97,0x3e,0xe9,0xff,0xfe,0x6f,0xff,0x6d,0xdb,0xf4,0xff,0xfb, + 0xbf,0xff,0x5f,0x7d,0xf9,0xff,0xef,0xff,0xff,0xff,0xff,0xfa,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x7f,0x6d,0xfd,0xff,0xdf,0xab,0xff,0xbf,0x55,0xaa,0xff,0xbf,0xd6, + 0xfa,0xff,0x24,0x50,0xff,0xf7,0xd7,0xff,0x7f,0x5b,0xda,0xff,0xff,0xd7,0xff, + 0xff,0x57,0xe8,0xff,0xff,0xdb,0xff,0xff,0xbf,0xfc,0xff,0xbf,0xcf,0xff,0xbf, + 0x5a,0xb4,0xff,0xf7,0x6b,0xff,0xbf,0x5e,0xd8,0xff,0x7b,0xd7,0xfd,0x5f,0x25, + 0xea,0xfe,0xef,0xcb,0xff,0x3f,0x5d,0xb4,0xff,0xff,0x6f,0xff,0x7f,0x2b,0xd4, + 0xfe,0xff,0xd5,0xfb,0xff,0xbf,0xe8,0xff,0xdf,0xd7,0xff,0x7f,0x2b,0x7a,0xff, + 0xff,0xd7,0xff,0xff,0x7f,0xf8,0xff,0xff,0xef,0xff,0xff,0xbf,0xfc,0xff,0xff, + 0xd7,0xff,0xff,0x7f,0xfa,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xd7, + 0xff,0xff,0x7f,0xfa,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xd7,0xff, + 0xff,0xbf,0xf8,0xff,0xff,0xdf,0xff,0xff,0x7f,0xfa,0xff,0xff,0xe7,0xff,0xff, + 0x7f,0xf4,0xff,0xff,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff, + 0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xef, + 0xff,0xff,0x7f,0xfc,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xef,0xff, + 0xff,0x7f,0xfd,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xef,0xff,0xff, + 0x7f,0xfd,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xeb,0xff,0xff,0xbf, + 0xfc,0xff,0xff,0xdf,0xff,0xff,0x7f,0xfc,0xff,0xff,0xef,0xff,0xff,0xbf,0xfc, + 0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xd7,0xff,0xff,0x7f,0xfd,0xff, + 0xff,0xef,0xff,0xff,0x7f,0xfa,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff, + 0xdf,0xff,0xff,0xbf,0xfa,0xff,0xff,0xef,0xff,0xff,0xff,0xf4,0xff,0xff,0x7f, + 0xff,0xff,0xff,0xea,0xff,0xff,0x7f,0xff,0xff,0xff,0xe3,0xff,0xff,0xbf,0xff, + 0xff,0xff,0xd5,0xff,0xff,0xff,0xfe,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,0xff, + 0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xaf,0xaa,0xfe,0xff,0x55,0xf5,0xff,0x5f,0x95,0xfa,0xff,0xff,0xdf, + 0xff,0x2f,0x52,0xf9,0x7f,0xd9,0xb6,0xff,0x8f,0xad,0xfa,0xff,0xf6,0xdf,0xff, + 0x97,0xb6,0xf0,0xff,0xfb,0xab,0xff,0x0f,0x55,0xfa,0xff,0xac,0xde,0xff,0xa7, + 0x54,0xf1,0xff,0xd7,0xaa,0xff,0x17,0x02,0xf8,0xff,0xb4,0xaa,0xff,0x8d,0x54, + 0xf2,0x7f,0xab,0xd5,0xff,0x43,0x82,0xe8,0xbf,0xdd,0x6a,0xff,0x29,0x11,0xf4, + 0xaf,0xb6,0xda,0xff,0x05,0x8a,0xea,0x7f,0x6b,0xeb,0xff,0xaa,0x24,0xfa,0xff, + 0xbd,0xb1,0xff,0x57,0x09,0xfa,0xff,0xd6,0xed,0xff,0x8f,0x14,0xfd,0xff,0x7b, + 0xf5,0xff,0x2f,0x25,0xfa,0x7f,0xed,0xdb,0xff,0x8f,0x9a,0xfa,0xff,0xfa,0xff, + 0xff,0x4f,0xab,0xfa,0xff,0xdd,0xee,0xff,0x17,0xed,0xfe,0xff,0xf7,0xff,0xff, + 0x4f,0xb5,0xff,0xff,0x5a,0xff,0xff,0xaf,0xea,0xff,0xff,0xef,0xff,0xff,0x3f, + 0xf4,0xff,0xff,0xb7,0xff,0xff,0x5f,0xe9,0xff,0xff,0xcf,0xff,0xff,0x7f,0xf4, + 0xff,0xff,0x7f,0xff,0xff,0xbf,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xaf,0xff,0xff,0xff,0xff,0xff,0xff,0xb7,0xff,0xff,0xff,0xfa,0xff, + 0xff,0x4b,0xff,0xff,0x7f,0xff,0xff,0xff,0xa5,0xff,0xff,0xdf,0xfa,0xff,0xbf, + 0x25,0xff,0x7f,0x75,0xfb,0xff,0x41,0x95,0xfe,0x5f,0xad,0xf5,0xff,0x01,0x08, + 0xff,0xbf,0xd5,0xfa,0xff,0x4a,0x25,0xfe,0xff,0x7a,0xf7,0xff,0x15,0x92,0xfe, + 0xff,0xcf,0xfb,0xff,0x97,0xa8,0xfa,0xff,0xea,0xde,0xff,0x4f,0x56,0xfd,0xff, + 0xaf,0xf7,0xff,0x3f,0xb8,0xfa,0xff,0xeb,0xdf,0xff,0xff,0xec,0xfa,0xff,0xdf, + 0xff,0xff,0x3f,0xfa,0xfb,0xff,0xef,0xff,0xff,0x7f,0xe9,0xfd,0xff,0x7f,0xff, + 0xff,0xff,0xed,0xff,0xff,0xbf,0xff,0xff,0x7f,0xe5,0xff,0xff,0xff,0xfe,0xff, + 0xff,0xdb,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0xff,0xff,0xff,0xfd,0xff,0xff, + 0xef,0xff,0xff,0xff,0xff,0xff,0xff,0x5b,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff, + 0xff,0xff,0xe7,0xff,0xff,0xbd,0xff,0xff,0x9f,0xf3,0xff,0xff,0xff,0xfe,0xff, + 0xaf,0xc5,0xff,0xff,0x5a,0xff,0xff,0x97,0xe2,0xff,0xff,0xbd,0xfe,0xff,0x4f, + 0xd3,0xff,0xff,0xba,0xfe,0xff,0x0f,0xc5,0xff,0xff,0x7b,0xff,0xff,0xa7,0xd1, + 0xff,0xff,0x5c,0xfd,0xff,0x8f,0x42,0xff,0xff,0x55,0xfe,0xff,0x8a,0x64,0xff, + 0x57,0xba,0xfa,0x3f,0x05,0x41,0xfd,0xef,0x29,0xd5,0xbf,0x44,0x80,0xfa,0x7b, + 0xb5,0xfe,0xbf,0x0a,0x45,0xfd,0xef,0xba,0xfa,0x7f,0x47,0xa1,0xfe,0xff,0x6d, + 0xff,0xff,0x17,0xa5,0xff,0x7f,0x7d,0xfd,0xff,0x8f,0x53,0xff,0xff,0xbb,0xf7, + 0xff,0xaf,0x4a,0xff,0xff,0xfd,0xfd,0xff,0x8f,0x55,0xff,0x7f,0x75,0xfb,0xff, + 0x4f,0x2b,0xff,0xff,0xfd,0xff,0xff,0x97,0x9f,0xfe,0xff,0xff,0xf5,0xff,0x4f, + 0x5f,0xff,0xff,0xfa,0xfb,0xff,0x97,0x2f,0xfe,0xff,0xfd,0xff,0xff,0xdf,0xff, + 0xff,0xff,0xff,0xff,0xff,0xaf,0xff,0xfa,0xff,0xff,0xdf,0xff,0xdf,0xff,0xfd, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0x7f,0xfd,0xff,0xff,0xf7,0xff,0xff, + 0x7f,0xfc,0xff,0xff,0xdf,0xff,0xff,0x7f,0xfa,0xff,0xff,0xe7,0xff,0xff,0xbf, + 0xf8,0xff,0xff,0xdb,0xff,0xff,0x5b,0xfc,0xff,0x7f,0xa7,0xff,0xff,0x2a,0x48, + 0xff,0x9f,0xad,0xf5,0xff,0xa1,0x24,0xfe,0xaf,0xc6,0xf6,0xff,0x10,0x10,0xfd, + 0x5f,0x6b,0xeb,0x7f,0x41,0x4a,0xfd,0x5f,0xd7,0xfd,0xff,0x34,0x28,0xfd,0xbf, + 0xcf,0xeb,0xff,0xa9,0x2c,0xfd,0x5f,0xe5,0xfe,0xff,0x20,0x94,0xfc,0x2f,0x57, + 0xeb,0xff,0x51,0x28,0xfe,0xbf,0xa5,0xf5,0xff,0x01,0x80,0xfa,0xdf,0xae,0xeb, + 0xff,0x6a,0x2a,0xfe,0xbf,0xd7,0xfe,0xff,0x35,0xb8,0xff,0xff,0xef,0xff,0xff, + 0xbb,0x5c,0xfd,0xff,0xd7,0xff,0xff,0x7f,0xf4,0xff,0xff,0xef,0xff,0xff,0xbf, + 0xfc,0xff,0xff,0xd7,0xff,0xff,0x7f,0xfa,0xff,0xff,0xef,0xff,0xff,0xbf,0xfc, + 0xff,0xff,0xff,0xff,0xff,0x7f,0xfd,0xff,0xff,0xef,0xff,0xff,0xff,0xfe,0xff, + 0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xef,0xff,0xff,0x7f,0xff,0xff,0xff,0xd7,0xff,0xff,0xff,0xfd,0xff,0xff, + 0x53,0xff,0xff,0xbf,0xfe,0xff,0xff,0x45,0xfd,0xff,0x7f,0xf5,0xff,0xff,0x53, + 0xff,0xff,0x7f,0xff,0xff,0xff,0x85,0xfe,0xff,0xff,0xf2,0xff,0xff,0x2b,0xff, + 0xff,0xff,0xfb,0xff,0xff,0x97,0xfe,0xff,0x5f,0xf5,0xff,0xff,0x01,0xfe,0xff, + 0x7f,0xfd,0xff,0x7f,0x55,0xff,0xff,0x5f,0xf5,0xff,0xff,0x02,0xfd,0xff,0x7f, + 0xfb,0xff,0xff,0xa5,0xfe,0xff,0x5f,0xed,0xff,0xff,0x43,0xfd,0xff,0x7f,0xfd, + 0xff,0xff,0x92,0xfe,0xff,0xbf,0xea,0xff,0xff,0x45,0xfa,0xff,0x7f,0xdb,0xff, + 0xff,0x13,0xfa,0xff,0xff,0xed,0xff,0xff,0x85,0xfa,0xff,0x2f,0xf5,0xff,0x2f, + 0x25,0xfd,0xbf,0xf5,0xda,0xff,0xb5,0x10,0xfd,0x7f,0x97,0xfd,0xff,0x0a,0x8a, + 0xfe,0xff,0xfd,0xf7,0xff,0x6b,0x69,0xfd,0xdf,0xef,0xff,0xff,0xaa,0xbe,0xff, + 0x7f,0xff,0xdf,0xff,0xef,0xff,0xf9,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xfd,0xff,0xff,0xef,0xff,0xff,0xbf,0xfe,0xff,0xff,0xff,0xff,0xff,0x7f, + 0xf9,0xff,0xff,0xcf,0xff,0xff,0x7f,0xfc,0xff,0xff,0xeb,0xff,0xff,0x7f,0xf4, + 0xff,0xff,0xaf,0xff,0xff,0x2b,0xd8,0xff,0xaf,0xa2,0xfd,0xff,0x21,0xa2,0xfe, + 0x3f,0x8b,0xf6,0xff,0x08,0x28,0xfd,0x9f,0x6a,0xfb,0xff,0x50,0x80,0xfe,0xbf, + 0xd7,0xee,0xff,0xa2,0xd4,0xfe,0xaf,0xbe,0xff,0xff,0x51,0x52,0xff,0xbf,0x6f, + 0xfd,0xff,0x68,0xd5,0xff,0x5f,0xbf,0xff,0xff,0xb3,0xa2,0xff,0xbf,0xfb,0xfe, + 0xff,0xd0,0xd3,0xff,0x7f,0x5f,0xff,0xff,0x6b,0xe5,0xff,0xdf,0x7d,0xfd,0xff, + 0xa9,0xa2,0xff,0x7f,0xb7,0xff,0xff,0x55,0xd5,0xff,0xff,0xfd,0xfe,0xff,0x0b, + 0xd5,0xff,0xff,0xd5,0xfb,0xff,0xa7,0xaa,0xfe,0xff,0xfa,0xff,0xff,0x17,0x3d, + 0xff,0xff,0xed,0xeb,0xff,0x8f,0x5e,0xfd,0xff,0xff,0xff,0xff,0x5f,0x7f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xbf,0xff,0xff,0xff,0x51,0x9f, + 0xfe,0xdf,0xfe,0xf5,0xff,0xea,0x5b,0xfe,0xbf,0xff,0xfb,0xff,0xb1,0x5f,0xfd, + 0xdf,0xfe,0xef,0xff,0xea,0x3e,0xfd,0xbf,0xff,0xf7,0xff,0xd1,0x57,0xfd,0x7f, + 0xff,0xdd,0xff,0x6a,0xaf,0xfa,0xaf,0xfb,0xf7,0xff,0xe9,0x3f,0xfd,0x7f,0xff, + 0xfb,0xff,0xb1,0x5b,0xfd,0xbf,0xff,0xdf,0xff,0xea,0x2f,0xfa,0xdf,0xfe,0xf5, + 0xff,0x69,0xbf,0xfd,0xbf,0xf7,0xef,0xff,0xe1,0x57,0xfc,0x5f,0xdf,0xf5,0xff, + 0xb5,0x2e,0xfb,0xbf,0xff,0xdb,0xff,0xa1,0x15,0xfd,0x7f,0x75,0xf5,0xff,0x54, + 0x95,0xfc,0x5f,0xdf,0xf7,0xff,0x43,0x15,0xfd,0xff,0xfd,0xed,0xff,0xb4,0x5b, + 0xfd,0xbf,0xff,0xfb,0xff,0xeb,0x5f,0xfe,0xdf,0xff,0xff,0xff,0xf2,0x7f,0xfb, + 0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xfe,0xff,0x7f,0xed,0xff,0xff,0x55,0x53, + 0xfd,0xbf,0xb6,0xea,0xff,0x02,0x09,0xfa,0x5f,0x59,0xb5,0xff,0x41,0xa2,0xf4, + 0xff,0xb6,0xfe,0xff,0x17,0x91,0xfa,0xff,0x5b,0xf7,0xff,0x57,0x64,0xff,0xff, + 0xb7,0xfe,0xff,0x5f,0xd1,0xff,0xff,0x6f,0xff,0xff,0xaf,0xc2,0xff,0xff,0x5f, + 0xfd,0xff,0xff,0x65,0xff,0xff,0x7f,0xff,0xff,0xff,0xd2,0xff,0xff,0xbf,0xfe, + 0xff,0xff,0xe3,0xff,0xff,0x7f,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xff,0xff, + 0xff,0xe5,0xff,0xff,0xbf,0xfe,0xff,0xff,0xd7,0xff,0xff,0xff,0xff,0xff,0xff, + 0xd3,0xff,0xff,0xff,0xfe,0xff,0xff,0xaf,0xff,0xff,0xff,0xff,0xff,0xff,0xb7, + 0xff,0xff,0xff,0xfb,0xff,0xff,0xbf,0xfe,0xff,0xff,0xff,0xff,0xff,0x5f,0xff, + 0xff,0xff,0xfb,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf, + 0x9c,0xfe,0xff,0xd7,0xf5,0xff,0x7f,0x5a,0xfe,0xff,0xef,0xf7,0xff,0xbf,0x2c, + 0xfd,0xff,0xdb,0xed,0xff,0x7f,0x3a,0xfd,0xff,0xef,0xfb,0xff,0x5f,0x98,0xfa, + 0xff,0xab,0xd7,0xff,0x77,0x4c,0xfc,0xff,0xd7,0xea,0xff,0x1f,0x28,0xf2,0xff, + 0x4a,0xab,0xff,0xa5,0x08,0xf9,0xff,0xd7,0xd5,0xff,0x17,0x52,0xe8,0xff,0x6b, + 0xbb,0xff,0x5f,0x14,0xfa,0xff,0xd7,0xed,0xff,0x7f,0xa8,0xfa,0xff,0xdf,0xf7, + 0xff,0xbf,0x2c,0xfd,0xff,0xe7,0xdb,0xff,0x7f,0xaa,0xfa,0xff,0xdf,0xf6,0xff, + 0x7f,0x38,0xfd,0xff,0xeb,0xdb,0xff,0xbf,0x4c,0xfa,0xff,0xcf,0xff,0xff,0x7f, + 0x3a,0xfd,0xff,0xef,0xeb,0xff,0x7f,0x94,0xfa,0xff,0xd7,0xf6,0xff,0x7f,0x5a, + 0xfd,0xff,0xef,0xdb,0xff,0x7f,0x14,0xfd,0xff,0xaf,0xf6,0xff,0x7f,0x54,0xfc, + 0xff,0xd7,0xf5,0xff,0x7f,0x08,0xfe,0xff,0xef,0xfb,0xff,0xbf,0xaa,0xfd,0xff, + 0xff,0xef,0xff,0xff,0xbe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb, + 0xff,0xff,0x7f,0xff,0xff,0xff,0xa5,0xff,0xff,0xaf,0xfd,0xff,0xff,0xa9,0xeb, + 0xff,0xbf,0x77,0xff,0xff,0x52,0x95,0xfe,0xff,0xde,0xe9,0xff,0xab,0x2a,0xf2, + 0xff,0x6b,0x55,0xff,0x56,0x00,0xd4,0x7f,0xaf,0xeb,0xff,0x2b,0x15,0xf1,0xff, + 0xf5,0xb5,0xff,0xaf,0xac,0xfc,0xff,0xdf,0xff,0xff,0x57,0x2a,0xf6,0xff,0xea, + 0xd6,0xff,0x17,0xbd,0xfa,0xff,0xf5,0xff,0xff,0x4f,0xdd,0xfa,0xbf,0xde,0xbf, + 0xff,0x25,0xfa,0xfa,0xff,0xf5,0xef,0xff,0x4b,0xfd,0xf9,0x5f,0xff,0xbf,0xff, + 0x29,0xdd,0xf4,0x7f,0xd7,0xdf,0xff,0xe1,0xfa,0xfa,0xaf,0xff,0xbf,0xff,0x74, + 0x7e,0xf1,0xff,0xd7,0xdf,0xff,0xb7,0xfa,0xf9,0xff,0xef,0xaf,0xff,0x7d,0xfc, + 0xf8,0xff,0xb7,0xdf,0xff,0xbf,0x6c,0xf5,0xff,0xdf,0xf5,0xff,0xff,0x92,0xf8, + 0xff,0x6f,0xad,0xff,0xbf,0x08,0xfd,0xff,0xbf,0xf5,0xff,0x7f,0x25,0xfc,0xff, + 0xff,0xfe,0xff,0xff,0x95,0xff,0xff,0xff,0xfb,0xff,0xff,0x77,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff, + 0xff,0xff,0xfd,0xff,0xff,0xdf,0xfe,0xff,0xff,0xf7,0xff,0xff,0xaf,0xfe,0xfa, + 0xff,0xff,0xdf,0xff,0x5f,0x5a,0xf9,0xff,0xd7,0xaf,0xff,0x2f,0xbd,0xf4,0xff, + 0xed,0xfb,0xff,0x7f,0x5a,0xfa,0xff,0xd7,0xed,0xff,0x5f,0x2c,0xfd,0xff,0xef, + 0xf7,0xff,0xbf,0xb8,0xfa,0xff,0xaf,0xfa,0xff,0x7f,0x0a,0xff,0xff,0xd7,0xff, + 0xff,0xbf,0xd0,0xfe,0xff,0x3f,0xf5,0xff,0xff,0x44,0xff,0xff,0xaf,0xfe,0xff, + 0x3f,0xa1,0xff,0xff,0xb7,0xfe,0xff,0xff,0xc4,0xff,0xff,0x2f,0xfd,0xff,0x5f, + 0x50,0xff,0xff,0xbb,0xfe,0xff,0x7f,0xa1,0xff,0xff,0xd6,0xf5,0xff,0x05,0x8a, + 0xfe,0xbf,0xea,0xfa,0xff,0x8b,0x14,0xfe,0xff,0xfa,0xf7,0xff,0x05,0x55,0xff, + 0xbf,0xef,0xfd,0xff,0xd5,0x5e,0xfd,0xff,0xfe,0xf7,0xff,0xd5,0xff,0xfb,0xdf, + 0xff,0xff,0xff,0xfb,0x7f,0xfd,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xe9,0xff,0xff, + 0x57,0xff,0xff,0xbf,0xd2,0xff,0xff,0xbf,0xfd,0xff,0xbf,0xc8,0xff,0xff,0xdf, + 0xfe,0xff,0xff,0xa2,0xff,0xff,0x7f,0xff,0xff,0xff,0x95,0xff,0xff,0xdf,0xfd, + 0xff,0xff,0xa3,0xff,0xff,0xff,0xfa,0xff,0xff,0x4a,0xff,0xfa,0x7f,0xfd,0xdf, + 0xff,0x87,0xff,0xfa,0x7f,0xf9,0xef,0xff,0x0b,0x3f,0xf9,0xff,0xfd,0xfb,0xff, + 0x8f,0x5d,0xfd,0xff,0xf6,0xef,0xff,0xa7,0xbe,0xfe,0xff,0xfb,0xfb,0xff,0x9f, + 0x2a,0xff,0xff,0xd6,0xff,0xff,0x4f,0xbe,0xff,0xff,0xef,0xff,0xff,0x7f,0xf8, + 0xff,0xff,0xab,0xff,0xff,0x3f,0xfc,0xff,0xff,0xef,0xff,0xff,0xff,0xea,0xff, + 0xff,0xbf,0xfe,0xff,0x7f,0xe9,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xff,0xff, + 0xff,0xfe,0xff,0xff,0xd7,0xff,0xff,0xbf,0xff,0xff,0xff,0x55,0xff,0xff,0xff, + 0xfb,0xff,0xff,0x2f,0xff,0xff,0xff,0xfd,0xff,0xff,0x5f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; diff --git a/hacks/images/matrix.xpm b/hacks/images/matrix.xpm new file mode 100644 index 00000000..f740ad7c --- /dev/null +++ b/hacks/images/matrix.xpm @@ -0,0 +1,904 @@ +/* XPM */ +static char * matrix[] = { +"56 837 64 1", +". c #000000", +"+ c #178618", +"@ c #26C227", +"# c #114410", +"$ c #7AEB7A", +"% c #5AC254", +"& c #136314", +"* c #1AA614", +"= c #52DB51", +"- c #127410", +"; c #169614", +"> c #062604", +", c #32D634", +"' c #145417", +") c #B2F6B0", +"! c #42A244", +"~ c #62E75C", +"{ c #2F832F", +"] c #3AC237", +"^ c #246624", +"/ c #2B7729", +"( c #0C360E", +"_ c #92F294", +": c #4CB34A", +"< c #298B27", +"[ c #0E4E0C", +"} c #62DE64", +"| c #3B9439", +"1 c #1D5E1D", +"2 c #26B529", +"3 c #CCFDD1", +"4 c #73E774", +"5 c #32CB34", +"6 c #021804", +"7 c #4ED64C", +"8 c #7AF67C", +"9 c #2E9A34", +"0 c #26CB24", +"a c #166E14", +"b c #52BB54", +"c c #5ED05C", +"d c #36B634", +"e c #0B3008", +"f c #44AB42", +"g c #020E04", +"h c #8AEC8C", +"i c #1E751C", +"j c #2AA62C", +"k c #42D73C", +"l c #286E26", +"m c #1F561E", +"n c #368B34", +"o c #40CC44", +"p c #3E9C3C", +"q c #0D3E0E", +"r c #66E264", +"s c #76EE74", +"t c #269624", +"u c #A1F2A1", +"v c #1C4E1C", +"w c #3EDE3C", +"x c #5ACA5C", +"y c #52E24C", +"z c #021E04", +"........................................................", +"...........gggggg......................gggggg...........", +"........gggg6gggggg.................g6g6>6666gg.........", +".......g666>>>e>z66gg..............g66>eee#e>z66g.......", +"......g6>>>>(>((ezz6g.............66eeeq[q[[#e>66.......", +".....g6e#m'''&&1[v#e>gg..........6z[-t*;;**2;+-[e6g.....", +"....g6>v^{{///n|{^1#(6g.........g>e<]k7,]===7]*i[6g.....", +"...gzze^|:f!|!::!n/^q>6g.......g>zq@}h44rrhh4=o2&ezg....", +"...g>>[/|b!|nnp!p|n/m>6g.......6e#-o}_4}==r44}=kt#z6....", +"..g6e[m{:%!{^l/{n!:|1(>6g.....gz[+t7hu4k@5]k=4h}2[ezg...", +".ggzqml|fxp/''''{!c:/q>gg....gg>&j]}hur5;;;;k4)ho&e6g...", +"..g6#^/pbx|a[[[[/f}:/#>>g.....6>i2]4hur@++++]4)$o-qe6...", +".gz>m/npfbnl[#[#l!x:{'(e6....gzqto=44_=@++++54uh7;[q6...", +".g6em{|!!f{a[[[#/|xf{1#>6g...gzqjk}444w@+++-]}u$7ji#>g..", +".gze^n!fff{1q#[#l|%:{^v(6g...6z#2=r4$4k2--+-]ruh72+[zg..", +".g6e^n!!!p{&[[qq/|b:n^m(zg...g>#d=444r,2++--5}uh=2t[>g..", +".g6(l|:!!p{'q##ql!%:|^1q6g...gz[]}h44r,*----]4uh}]j&>g..", +".66e^|f!pp/&[[##/|%:|lmq6g...6>#dr44~r0*++--]}uh}]t&>g..", +".66(mnpf!fn&[[##/|%:{mv(6g...6z[j=r44$=2++--5ru$=j+[>g..", +".g6e1/n!:bn^[[[[lpbf{mq>6g...gzqjo=44_w@++++]}u47t&q6g..", +".ggemln!:b9^[[#[l|%!/v(>g....gzqt]=4h_=@++++@ru4o+'e6...", +".gg>#ml|:x!i['''/!%:/#e>6....g6e-j]}huy0+;;;54uh,-[ez...", +"..g6([mp%}f/''1^{fx!/q>gg.....g>[+jy_)$,;;2274u4o&e6g...", +"..g6e(v{%cfi'&&lnfc:/e>6g.....g6q&+7u)40;22@=4)h][e6g...", +"...g>(#l!bp{a//{n|!/1e6g.......6e[-o4h~k@@0k7}47jq>6....", +"...g6ze1/nn{<{n|n/l1#66g.......g6eqjo==7k=y}=kbj-z6g....", +"....gz>q1l{npp!pn^#(e6g.........g>e&j]k=rr4472-'q>g.....", +"....gg6(#mm^ll//^vq>6gg.........g66'-tjd]]]od+&q>gg.....", +".....gg6e(##vvvvq(>6g............gg>q[--<<+<-[e6z.......", +".......g666>>zz>z6g6...............g6>zeeeee>z6z........", +"........ggg66zg66gg.................ggz6z>66zgg.........", +"........................................................", +"............g.g.........................g.g.............", +"..........gg66g6gg....................g6>z666g..........", +".........g6z>e>z6gg..................gzze#q>z6g.........", +"........g6>(qe(e>zgg................g>e[&[[qe>6g........", +".......g66vlnll^mv#eg..............g6>+]=5]2t+i[6.......", +".......g6>^|%:|{/l^ve..............6>edruhr7k]d<#.......", +".......66>{%8}%!nn/^q..............6zq7u3)u4}7]d&.......", +"......g6>(/x8c!{/^mqe.............gze#ou3)4oodjiq.......", +"......g6>({b8%|mmvve6.............g>e[7u3u}j9.......", +"......g6een%8b/#q>>6g.............g>q[7u3_o-&qe>g.......", +"......g6>(nb_:/qee6gg.............gzq[7u3ho&[qz6g.......", +"......gz>(nb8:{q(>z6..............g>e'7u3hk&[e>z........", +"......g6een%8b/qe>g6..............g>q[=u3ho&[e66........", +"......g6een%8b/q>>zg..............gzq[7u3h5&qe>g........", +"......66>enb8:/ee6gg..............zze[=u3ho[qzzg........", +"......g6e(n%8:/q>>6...............g>qv7u3ho&qe6.........", +".....g6>>enb_:/qe66..............g6eq[=u3$]&q>6.........", +"......g6eqnx8b/(>>gg..............z>q&7u3hk[qe6g........", +".....g6>eenb8b/qe>6g.............g6eq[=u3hk&qe6g........", +".....g6>eqnx8b/qe>gg.............g>e[&7u3h0&[e6g........", +".....gg>eq{%8b/(ee6g.............g6e[&=u3_o[[q>g........", +".....gzzeqnx8:/(e>6g.............g>eq&cu3ho&q(zg........", +".....gzee#{%sb{((>6g.............g>q[-=u3_k&[e>6........", +".....6ge#mn:c!{&#q>6.............66[-97h)4k*-&e6........", +".....g6qv^{f%!{^'q>zg............gz&g.......", +"......geqvm^/^mvqe66..............gq&6........", +".......gze(q#qqee6g................6eqv&i&&q#>g.........", +"........gg6g6gg6g...................g6666666g...........", +".........gggggg......................ggg6gg.............", +"...........ggggg.......................ggggg............", +"........ggg6zgg6gg..................gg6z>zz66g..........", +".......g6z>e(e>e>6gg...............g>>eq[q#qez6g........", +".....gg6>eeqqqqqeezgg............g6>e[[&&&&&[q>6g.......", +".....g6>##vv#v[[#q(>6g...........g6q&-++++++-&[qzg......", +"....gz>m/n{ll^^^^^/1qg..........g>eto=7@]@22@]oj'6......", +"...gg>el|%!|{{{{n||{v>g........g6e[]ru4}kk7k7}r7g........g>q&7h)u4==7=r4h}jeg.....", +"...g>qv{bc:|/l^l{|fnm>g........gq&+=h)$=55@]7}h=9e6.....", +"...gev^|bcp{&&'m^np{m>g........6[+d}_u4k2**;]=r7teg.....", +"..g6qm^|bx|l'[[#m/|{v6g.......gz&t]}hu}5;++-jo}7<>g.....", +"..ggev^|bc!i[[##vm^me6g.......g6'+d}_u4@++a-+jd9'zg.....", +"..g6e#m|:c!/[[#(####>g........g6[ij}h)45++-&-ii&eg......", +"...g(#m|bc!i[[#q(e>6gg.........6[ij}h)40;+-&[qe>zg......", +"...6e(v{!%pzg..........6q[+74ur,@*+&[(ezz.......", +"...g6e(/|f!n{a1(qe>6gg.........gz[&]}$r=,@*&&qe>gg......", +"..g6zee^n|!!p{&#q>>66g........gz>q[2=r44r,*-&qe>6g......", +"...g6>e'l{n9!{i'vq>>gg.........g>e[;@ky=~,0*+&qe6g......", +"...66>e[1l{|f|e[+j@kr~rw02+[q>6......", +"...gz>(#['itpp9|/1q>>6g........gzq[-+;5w4~=y0*&qe6g.....", +"..g6eeq['1lt|ppp{^'#e6g.......gzq[-+;*5wy~~~k@;-[z6.....", +"...ge#m1&-{{{t9!p<{^#>6........6#-;*20,,kwy~~=,2-ez.....", +"...6qv1ll{iiizg.......z&<2]@,500wr4~r}ktqzg....", +"...6(m1i{{<{{tpf!f!6........g#&(q^n!!!!p!!p||lv>g........ge[-d=4444444r}}o+e6.....", +"....g>evm^lll/ll^^^v(6g.........6eq+9d]]d5]]]dd<'zg.....", +".....g6>e(q(#q#qq((e6g...........6>e[v&&-&-&&[[(zg......", +"......gg66>>>>>>66ggg.............g66zeeeeeezz6zg.......", +"........gg.6gg6g6gg.................ggg6666zzgg.........", +"..........gg6ggg......................gg6ggg............", +"........g666>>>6gg..................6z>>eeezzg..........", +"......g6z>e(qee(ezgg..............g6>e#[&[[[(>6g........", +".....gg6eeq#####ee6gg............gz>q[&-----[qz6g.......", +"....ggzqm1mmm11mvq(>g...........gzz&;jjtjjjj+&[e6.......", +"....gz>m{pn/l//n/^m#>g..........g>q97~=o5ok=odtiqg......", +"...g6>(/fx:p{n|!|{/mqg.........g6e[o4uhrk=}4r759v6......", +"...g6e#nbc:|{||!|n/^q6.........g>#-=_)hr,=r4r=kd&6......", +"...ge(vn:cfnl/{n{//mq6.........gq&{7h)47@o777o]9&>......", +"...gevm|:c!/11lllllm(g.........6[+j}h)45*2@]o]]9'6......", +"..g6qv^|:x|l'1mm^^^m(g........gz&<2}hur5;jjjdddt[g......", +"..gg(#vnfxfn^a1mvv#(>g........g6[-t=hu4=@@*t+ev{fxf|e#{!xbpn{m#ee6gg.........g>q[-k$u$4=5j-[qz6g.......", +"..gzeqvn!x:f|{^#qe66g.........gzq&+k4uh~rk2-&qzzg.......", +"..g6e#'n!%:f9{^mq>gg..........z>[-t=$uh4yk@t&q6g........", +"..gzq[mnfx:!|{lm#(zgg.........g>&+j=$uh4r7]t-[>zg.......", +".g66v^/|!:pn/^1[qez6g........g6z+20}4h~75@j+&q>6g.......", +"..g>m/n|ppn/&'vqe>>ggg........ze9]=}rr=,2;+&[(e66g......", +"..6>mnpp!9{&'[qq(>ez6g........zej=r~~y,2;+-&[qq>6g......", +"..g>m/nppp{a[[[['1mveg........getorrrr,@++++;jj+[6......", +"..g6vl{n!!{^'1'1l{n/v6g.......6>+]7}r4k@;***@k}o+>g.....", +"..gzqml|p:n-''&l{!b|1>g.......g>&j]=4hk@;*2]74_rjeg.....", +"...gq#m/n!n/&ll{{np{m6g........6[ito=~=02@@k7}}79zg.....", +"...g>e#1/{{{/{{{n{{^q6g........ge[ijo=k,ok77777d&>g.....", +"....66e#1ll{nnn|nlmv(gg.........6>#-j]]7===r=]j+[zg.....", +"....g6gqvm^^///llmvq>6..........g66&+jd@]oo]]j<&e6......", +".....g6>(q#vvvmmvq(egg...........g6e[&i++ttt{&[#6g......", +".......gg6>>>e>>>6ggg..............g6>eeqqqeez6gg.......", +"........ggg6g66666g.................gg66zz>>zzg.........", +"...........gggggg.g....................gggggg.g.........", +"..........g.g.........................g.g...............", +"........g6g66gg.....................66zz66g.............", +"......g66e>>e66gg.................g6>qe#q>zgg...........", +"......g6e>((ee>6g.................g>qq[[[qe>6...........", +".....g6>#[milmq>66...............g6q-+*@5t&ez6..........", +".....66qvm{n!{1(e6gg.............6>&+jo}r,j[q>6g........", +"....g6>v^l!%c!l((e6g............g6e+25~u)$5&[qzg........", +"....g6z[^{p:cfn&[ezzg...........g>e+dk4h)4k2+[>>6.......", +"....6z>'a{!:xfp{a[>z6g..........6>q;@krhusrk@+q>6g......", +"....6>em^{|:b:!p{1(e6g..........zeqt2kr$_h4r,*[q>6......", +"....g>>ml<|fbbf!n^[qe6g.........6eqt5ky4h$$$=@+&qzg.....", +"...gzz(&/<9fffffp{im(>6g.......g>e[*5w=~$s4~rk5;&e>g....", +"...gz>('/<9pfff!f9{/[e6g.......g>q[*0wy~~~$$~==5+qz6....", +"...gzeq1/t|jffj:ppp{1(>6g......gzq&j5wyr~s~44~}7j&ezg...", +"...g>e[a{|!!dfp!p!f|l'(zg......ge[+@ky~~4~~r~~4y];&eg...", +"...g>q[^|!j::j!g..", +"..ggq'1n!b]xxdj!f!f!{^'ez.....g6&t2=~__uus~~~4h47@t[z...", +"...6q1l!bcxccb:j::dp{lm(6......6&j]~huuuu_s~$$$r7]9'z...", +"..g6qm/pbxcxcx:d!!p|{lmqz.....g>&jo~_uu)uuss~4r}7]t&>...", +"...gq[1{!dbdbj|<{{llmvq>g......z[+*k~$$s$~ykw,]@j+&qg...", +"...6>e#l{ppp!<{&1''[qe>6g......6e[-]kr~~4w52*;;+&[q6g...", +"...g6>>'^{{n|i1#((e>>z6g.......g>eq;@kk==52-&'qqe>zg....", +"....6ze[^i{{{^[e(>>z6g..........6eq+25ok=@+[[qqzzg......", +"....g6zqm^a//1#e>zzggg..........g6z19d@o]j-qe>>6gg......", +".....g6qvm^^lmq666g..............6>&+jdd]t&>z6g.........", +".....gge(##vvqe6gg...............g6#'ii++&qzgg..........", +".......g>e>e>>gg...................6eqqq#egg............", +".........6ggg........................6ggg...............", +"........................................................", +"........................................................", +"........gg6g6g6ggg..................gg666666gg..........", +"......g6>>ee(e(e>6g...............g>e#q[[[[[qz6.........", +".....ggeq#vvv'vvq(z6g............g6q&i++zg.......", +".....6>(vm111m1^v#e6g............6e'6.......", +"....gzevmll{{nnn{^v#>g..........6e#+joook==}kd+&eg......", +"....6>q1/nnnn!fb|{mveg..........6q&j]===r4$hr7j+[g......", +"....zeq^{|p!pbxcb|/m(6..........>q&d7r~4rhu)_}o9'z......", +"....ge(v^/{n{|:bfn/m#6g.........6q[td]k=krhh$=oj&>g.....", +"....6ze#m1aii<|f|n/1q6g.........ze#-;2@00w=$rk]j&6g.....", +"...g6>e(#['1&i{|n{lm#gg........g6eq&-+;**0kyykoj-6g.....", +"...gg>>#'1ai/|9fp{/1qzg........gzeq-;2@0,wy4rkoj&>g.....", +"...g6>('a{{|t!fbfn/mqgg........gze[;@,,=y$$h$=oj&6g.....", +"...g>>(m/n!f:bxx:|/mqzg........6>q[jo=4sshuuh}o9&>g.....", +"..g6e([/|!!!f!f:|{^veg........g6q&+0=$4~~4$hrk2+[6......", +"..ggev1g........gz[+j=$h4r=k==o2+&eg......", +"..6z#1l!bxftii^1mvee6g........6>-*5r_)4w5@@2t{[#zg......", +"..g>#l{!:x!{a&1'#q>6gg........gei]74hu4,@2*;-&q>6g......", +"..6>'/n!:fnl1''[q(ezgg........6et]=4$hy5*;;+&[q>6g......", +"..gzm{pp|!{&[##qe>>z6.........ze97~rrr,2+--&[qezz.......", +"..g>m/np||{&[q##qqe>g.........geto}rr=k*+---&&[e6.......", +"..gg#m/{|p{a'&&^^m^m(g........g6ij],r4,@;**22jdt'g......", +"..66(#m{|p{^'1l/{{{l#g........z6'-jo}r7@;*]o777]i6......", +"...geq[ln!{^'^/nn{|/#6.........zq&+]=4w@;@0===}oi6......", +"...g6e(ml{/ial{n/{lm(g.........g>q&*]7o5@o7=77]j'g......", +"....66>#'^l//{{n/^m#eg..........6>e-t2]oo777odjiqg......", +"....ggze#'^/{{/{/m#(6g..........g6z[-;2o7o77]9iv>g......", +".....g6>eq#vmm^mv#e>6............gzeq&i;tjjjeeqq((ee6...............g6>eq[&&v'qq>g........", +"........gg66g666ggg.................g666zz>>6gg.........", +"..........ggggggg.....................ggggggg...........", +"........................................................", +".......gg>>>ezg6gg.................g6eqeqe66gg..........", +".......eq#vmmvq>6gg................q&i<9j+&#>6g.........", +"......gqml//{^vqe>6gg.............g&9]5o7d+&qezgg.......", +"......g#ml/{n/^[#e66g.............6&j]o7=]2+-[>>g.......", +".....gg(vm^//{{/^'(>6g...........gg'{tdo7k7,2;[qzg......", +".....ggz(#m^/{p!n&#(>6g..........g6e[-j25k}4=2-[e>g.....", +".....gz>e(mm^n!:p/'#(6g..........gzeq[;j@74hr5;-[z6.....", +".....66>eq['&/e[&+;25wrr==@+q>6....", +"....g66eeq['&^{t|pf{^(z6........g6>q[&+;*@,wy~$=2[>6....", +"....gg>>e([''aa{9fb!^q>6g.......gzeq[&+;;@@ky4h4]&q>g...", +"....6zev^liii<q+2@000wwr4_)h5&qzg...", +"...g6>q^n!p||pffbx4b{[>>g......g>q&d=4rryr~$_u)_,+qe6...", +"..gg>e#{!x:f!f:bxrsxn[e>6.....gge[-,4uh4~4shu)3u=+qe6...", +"..g6(v1nf:f9+|9pdxrb{[e>gg....gz[+27$h4ywyy~$))u,+[e6g..", +"..g6#^l|f:|{aii{|fc:{q(>6g....g>i2o}$hrk205,=$)hk-[e6g..", +"..6>m/||f!na1''&/!%!i#(>gg....zeto}r4$k@****,4_4@-[#zg..", +"..g>m/p|!!{&'''&+p%!{qe>gg....gejorr44k2;;;*,ru$o-qe6g..", +"..g>m{|p|p{a['''/pxfi#ez6.....6e97}r}~,@+;;;5ru40-[z6...", +"..g>m{p|||l&'[[[{9x!/qe6g.....6ej7rr}}52;+;+,ru$]&q>6...", +"..g>vln|||{&[''&{!%!iq>zg.....geg...", +"..ggqmlnp!na'&&^{!%!l(>zg.....g6&t]=~$=@;*2@k4u4][e>g...", +"..g6e(v/!b|l'&//|!b|1ezg......g6q&+o4h=0*25o=4hr2[z6....", +"...g>(#l|!n/'li{{|!n1>6g.......6e[i]}$=5*@5k7r4=j#6g....", +"...g6eevl{lill{{{/lmqz6g.......gzq[<]ko@]5k77o]9&zzg....", +"....g6>(v1^///{{lm#(>gg.........g6e&+jdoooo7]j-[e6g.....", +"....gggeq#1^//l/mv>66gg.........g66(&-jdo]ooj-q>>gg.....", +".....gg6>(q#vvvvqez6g............gg>q[&-<++{&q>6g.......", +".......g66>e>>e>>6gg...............g6>eqqqqqe66g........", +".........ggg6g6ggg...................gg66666zg..........", +"...........ggg.g.......................ggg.g............", +"........................................................", +"......g6>e>eee(e>e>>6g............gze(#[[[[[#qqezg......", +".....g6eqvmmmvvmvvvq>6g..........g>[&+#ij22]@]@]ddjt&#>g....", +"....6>(m/n/{{//{l{l^vq>g........6e[9o=77oooooood<&e6....", +"....g>q/!%f|nnnnn||n^vq>........6e&oru4r=====rr=d+&e....", +"....>e#nb4xf||nn|!:|/m#e........e#i=u3u4ry==r4hr]jiq....", +"....6e#|%4x:|||n||p|/m#>........zqi}u)uhy}y=}r4}o9iq....", +"....g>(/!x:p<{/l///^mv(>........6ev74uh~wko@]oo]ji'e....", +"....66(^|:p|{aa'vmm##(eg........zz[d}h~},@@;;tti^'q6....", +"....66e1n!n{{l1#qq((ee>g........z>qj=4==k@*-&&&[[qe6....", +"....g66v^/n9p{&q#eee>66.........g6>+do==r,2-a[qqe>6.....", +".....66qv^{|:{^qqe>66g...........6>&<27rh72&&[ez6g......", +".....g6>q#/|b|&qee>6g............g6(&+or_w@&[qe>z.......", +"......g>e#ln!nl[qe>66.............geq-]7$7@+&[e66.......", +"......ggzem{|n^1ve>6g.............g6e(j7}=@*+[e>g.......", +".......66>m/|{l1vq>6g..............6>eto}7]j+&e>g.......", +".......gz>qm^//{^#>zg..............g>e&j]]kk@-e>6.......", +"........g6eqvln|/m>z6g..............g>q&+]7rote>6g......", +"........g6zee1n:nm>>gg..............g6eq[2=h=*qe6g......", +".........g6>emn!n/q(>g...............gzeqj=$=]-[eg......", +".........g6>>m/!n/^veg...............gzeeto4y]d<#6......", +"..........g6>vl|n//mq6................gze+]}=7]j&6......", +"..........gg6qm///{lqg................gg>^9ooo7]&6......", +"...........ggeqv^/{lvg.................g6q&evl|/#6..................g6eq<]}ki6......", +".............gg6qmlm(g...................g6>^9]jmg......", +"...............ge(#(>......................gqvive.......", +".................gg..........................gg.........", +"........................................................", +"........................................................", +"........................................................", +"...........ggggggg.....................ggg6ggg..........", +".........ggg66z6g6gg.................g66z>z>666g........", +".......ggze(qqq#eez6g..............g6>#[&&&-[qez6.......", +"......g6>e#v11m1m#(ezgg...........g6eq-6g.....", +".....gg6eqm^////l1qqe6g..........g6>#&t2ook5]j-&qz6.....", +".....g6qm^ll////ii/1#>6g.........gz&j]]oo55o00oj-ez6....", +"....gg>m{|n{l/il{np{1(z6........g6et7}=k@555k=~7j[>6....", +"....gz>l|%p{laiinfx!iq>6g.......g>e]}_rk@@@@=4u45&q>g...", +"....g6e/fx!{iiiie/:cf<^aaa|fx:{q>>6.......6e#oh)4k@@@@w$u4,-qez...", +"....6>e{:}ftaaa&(lfx!9/{{{pb%:{[e>6g.....gze[]$u4w,0,,~su4,+[e>g..", +"...gg>(l|:f!fjfd:]x!i'e>gg.....g6e[]}$$~~~4$s_u45+[e6g..", +"...g6e(m/|fdbxcccxxf/[#>zg.....g>q[jor~s_uu)uuu$0+&q>g..", +"...g6>em{n:%cxcccxbf+#(e6g.....g>e[j5}$_uuuuuu_~,+[q>g..", +"...gz>(l{ff:xbb::bx!{'(>zg.....gzq[@=~4su__$$_u$,;&qz6..", +"...gzee/pb]b%dfjfdx!{'#e66.....g>q[5~s___$~~~$u~,;&qz6..", +"...gz>qipb:]bf9q&5rh$_s~yw~$_4k*-[zg..", +"...gze(/!xfp9<{i<9fp{&[(6g.....g>q&5$u$ryw,0k=$rk2+[>g..", +"...g6zq/fxfg.....gze&o4u~w00@@,w4rk@;&e6..", +"...gz>q{:x!{''&'i<|n{^&qz6.....g>e&7hu4,****0,==k]j&>6..", +"...gz>e/!cpia'&'in:!{^m(6g.....gzq[]4)r02**;5yh472;'zg..", +"....6ze/!x!{&1&'ip%:{mv(gg......6>[o$u4,2**;0ruh7j+'6g..", +"....66e/!%!/&''[/px:n1#e6.......z>q]4u~02*;+54uh=jiqz...", +"....ggzm/|{/aa&&/n!n^#e6g.......g6>to}7o@@22574=di[>g...", +"....gg6qm^ll/ll^///lve>6........gg>&9d@]0]@]5oo]<[e6....", +"......g>e(m^l///l^mv(66g..........ge[&td]o]o]dj+[>6g....", +"......ggz>qv1mmmm#v(>6g...........gzzq&+jt9jtii'e6g.....", +".......g66>eq((((e>>.g.............gz>e#&''[[qqegg......", +"...........6g6g6gggg..................g66>6>66gg........", +"............gggggg......................gggggg..........", +"..........gg6666ggg...................gg666zggg.........", +"........gggg66666ggg................ggz6>>>>>z6g........", +".......gg6eqv#vv#(e>gg.............g6>q&ii++-[qe6g......", +"......g6z>#m^^^^1#q(z6g...........66>e-t@dddji&[e6g.....", +".....g66eevl////l1[q(6gg.........g6>q[+@oooo]*+&[>6g....", +"....g6zqm^ll///lll/^v(z6........gz>&t@]]o5o@5oo2+[e6....", +"....g6>v{|{{/l^^/n|n1qe6g.......gzqtk==k55@@]=r=2&q>g...", +"...g6z(^|:!nii&&{!:!lv(>g......gzz[drhr=5@22k~h4o+[q6...", +"...g6>(lp:|{l^&1lnf|{'#e6g.....g6q[5rhr,@2**5=4rot-q6g..", +"...gze(/pb|i&&''anpn/^'e6g.....g>q[o~_}52*;;@=r=o2t[>g..", +"...g6e(l!b|i''''^/n|/^mqzg.....z>q&54_=0;;;;25}=k]j&z6..", +"..g6>(#{!xpi'&'[a{||{l1qz6....g6e[-o4ur0**;;@kr=k]j&>6..", +"...6z>q{fxp+'&''a{!|{l1q>g.....6eqak$uy,;**;@k~rk@j&eg..", +"..g6eeq<:x!/'&1&i{!p{lmq6g....g6qq-kh)~,****0krr7]j&>6..", +"...6ze#{:c:ti-ia{p:p{^vezg.....ze[a7$usw000@krh4k2+[>g..", +"...6>>qq&kh)u_4s_4__u$k+[eg...", +"...g6>q/fxx%b::p!ff|^qe6g......gzq&o$uu_hhs44$$}d&#>g...", +"...g6>>^n!fbbf|{{{/^ve66.......gzeq2=44h_~},o7o]+[z6....", +"....6>e'inpf:p+''mv#e>gg........6eq;5=~4hr,*;;+-#ezg....", +"....gg>#1i|!b9{1'q(e>66g........g6eij5=4h=k*;-&qq>6g....", +".....66(#'{t!|{i^[(e>ggg.........6>[-tky$rw52+&(e6gg....", +".....g6>e(^nf!pni'(>zzg..........g6e[&d=44r=5;[q>>g.....", +"......g6>>m/p|||{1qe6gg...........g6eq*or}r}o*&q>zg.....", +".......66>qml/{n/1m#e6.............z>e^t]o7=o2;iq6......", +"........gzeeqm^//llmeg..............gzq[&t2oo]]9[6......", +".........gg6zqml^/lm#6...............gzze&9]]o]j&6......", +"..........g66eqvvvvq>g................g6>q1<{<{&eg......", +"...........ggg6>>e>6g..................gg6>e(qe>g.......", +"..............ggg.g.......................6gggg.........", +"........................................................", +"........................................................", +"........................................................", +"........................................................", +".............gggg........................gg6g...........", +"...........gg6ee>g.....................g6z#qe6..........", +"..........6>(#ml'#gg..................6q[ij]t&6g........", +"..........>(v^{|/v6g..................e'+d7ro6g................g#&(vlp%|mez6................gevi]ru}jq>6.......", +".........g6>(l|%|le>zg...............gzq'b}ur][e>6......", +"........g66>e^px|lq>z6..............zz>e#]rur]&(>6......", +"........ggz>(^|:|l'q>6g.............g6>q[d}$}5;&q66.....", +"......ggzz>eem{!n/^v(z6...........gg>zeq[*747o2+&>6.....", +"......g66>>((1l|{{l1qzgg..........gzzeq[[jo}=7]j&z6g....", +".....g6ee##vvml//{/lv>6g.........66#[--++*]ook7]+e6g....", +"....666qm1m111m^/{|/'>6gg.......6zz&tj**j*j257}ot#>6g...", +"...g6z>v^/l^l&'[l{!{1(>6g......g>>q+2k5@]2;+@k47j[e6g...", +"..g6>q#m/{i^m''#^{!n^q>6gg....g6q&-joo]2*;;+274=2&e>6g..", +".ggzqm^l/{/&''[[a/!n1qe>6g...gzz&t2]ok52;;++@kr=2&qez6..", +".gz>vl/{{{^1[[[v^{!n^q(>z6g..gze+]]kk7@*++++2k4=2-[q>zg.", +".g6em{||n..g>[j7r}=k52***2,}hrk@t+&[e.", +".geq/pb!|{{/^i{{|:%b!pnl^v(g.zq&o4h4y=k0@@,krhuh4r=o2+[6", +"g6e#nbcb!{{{{npf:%cxxxb|/^#zg>qi=_)h~k7,k=r$hu)uuuhrodi>", +".6e#/:xp{{/ii{n|!!::::p|/mqz.>q-7hu4=o55]k7}r4hhhh4}oj&z", +".g>q^n!{^m1''m^1l/////l^1v(g.6e&d747@tj;tj2d]]oooo]dj<'6", +".6>evl/m'(eee(e(qq#q#####qeg.zeqt]]j+&[[['[[^&i&iiiii&#g", +".g6>qm1#(ee>>e>z>>e>e>e((e6..g>e19ji[qqeeqeeeq#eq(q''q>.", +"..g6e(qe>66z6g6z6z666z66666...g>#'&[e>>>z6>z>zz>z>>z>>6.", +"....g6zg66gggggggg6ggg6g........g>zz66gggggggg6gzg6g....", +".......................g...........................g....", +"........................................................", +"........................................................", +"..........g66gg.......................66>6g.............", +"........g6>eqe6g....................g6e[&q>g............", +".......ggz(#mq>gg..................g6>'it&q6g...........", +".......6(qvm^vq6gg.................>[&+jd<'66g..........", +"......gev1l/{^#>6gg...............g[>zgg..............gi]c7}}o;qe>6g........", +"......g(^/n||/^vqe6gg.............g&d7=}}od+&qz6g.......", +"......g(#ml/nn{/&#ezgg............g'i9]o==kk2-q>6g......", +".......g>(ml/np!{1>>6g.............6evt]7=}47jqe66......", +".......gg6#m/{!fn^#(>zg............g6>ijo74h=d-[q>6.....", +".......g66(#m^/n/{/^#e>g...........g6>[itd]=kko2iqeg....", +"........g6>(qvm^/n!{^q>6............66e[^+j2o74=2&qz....", +"........gg6>e(#v/|:!/#(>g...........g6zeq[-g...", +".........g6>eeq[l|:!/vq>g............66eq[&+@}_4o<&eg...", +".........g66>e##^|:p/ve>g............g>zq[a-]}h4]+[eg...", +"........gg>e(vml//n/mq>g............ggeq[+*]]7=o9&q6....", +"........g6>e[^/n{lmmq>zg............g>([+2o=7]jt&q>g....", +"........66(#vlnp{^qe>66.............6z[-+]=47d&'e6z.....", +".......g6ev^{{/{^v(>zgg............6>q6g.....", +".......ze(^npn/mvee66g.............>#&d=47oj{[qzzg......", +"......g>(v/!%p^(e>ggg.............ge&i74urd[qe6gg.......", +"......g(v^/|p/m(zz6g..............g'zg........", +"......gq^{/llmq66gg...............g&d7ob]t&>zgg.........", +".....ggv/|/m((e6g................ggggg..................&j]9i'e6gg...........", +".......>(vee6zg....................e'<[qz>g.............", +"........gggggg......................g6gggg..............", +"..........g...........................g.................", +"........................................................", +"........................................................", +"........................................................", +".........ggg6g6g6g...................gg666666g..........", +".......gg6gz6z>z6g6gg..............g666>>>e>>666g.......", +".....ggz>((q#####(e>6g...........gg>#[[&-----&#ezg......", +".....g6eqmmm1^^l^m#(eggg........gg6[&ttjj2@b2t-gg....", +"...g66>qm^ll/{nn{l1vqzgg.......g6>e&t]]]o7==7]j+&e6g....", +"..gg>e#m^llll{npn{l1vq(>g.....gge[-t2@]]]k=4=k]j+&[e6...", +"..g6qml^l/^&1/p:pn{ll1v(6g....6>&9]]b5@2*or$4=,]]j+[zg..", +".g6>mln{/l^'[/|bf|{{/l^#>6g..gzeto77k]2;+5}_4r=koodie>g.", +"gg6e1{|{/l1'[/p%:p{{{{lv(>g.gg>#j7}75@j;+5ru$}kkkko<[e6.", +".6e(^n|{1''#ql|bp{all//1#(eg.zq&d=}k2;;a-5}h4k@5]o@j-&qg", +"g>e#l||{mqq##a|bp{1&/{/^1#ezgeq-]}roj----@=_}k*257k@ti[>", +"g>e#/|!l'qqq#^n!|/&al//l^mq6ze[io}$];&&&&@=4r5*@55o]dj&z", +"6eqvlpf{'q(qq'/|n{/{/ll//lv>6q&{5}$o;&&&&*o==koo5@]oo]g#-97r$5*'&&[+2ok=yk5@@7y=9#", +"6e#v/pf/1q(qe['1/{p|i&^{|n1(6qito}$k*&[&[+;25=~y52@xr=j[", +".zev/|f{'#qeq(['lnp|{ll/n{vegeqior47*--[&&+;574}75]k77(lp:n^[#(((q#anf!nl//{/v>.6e'brh=2+-[[[&-@7$475@o7o.z6qd}47];--[[[&j=44=oooo]ie", +".gg>v^{ll^1''#qq'l{{nn{l^v(g.g6e6..gzqi<9d]djd;-[-;25=rybi&e6", +"...gg>eqm//ll1[e(##m{!|^(>gg...g6eqij]o]]j+[&-ij74}d&ezg", +"...ggg>(#vvvvq(ee((vm^^#>gg....gg6e[i<<<+&vqq[[ij]die6g.", +".....g66eeeeeeee>>>e(qqe6g.......g6>(#[q[[#qeqeqv&&q6g..", +".......gggg6g6z>6666gggg...........gg66666eez6>66zgg....", +"..........ggggg6gggggg................gggg6zgggggg......", +"...............g...........................g............", +"........................................................", +"........................................................", +"........................................................", +".........gg.g........................gg.g...............", +"..ggg6g66g6g6g6ggg............gg666z66z6666ggg..........", +".gg>>>ez6zzz>z6666gg.........g6eeqq>>>>>e>>>z66g........", +".z>eeeq(ee>>e>e>>z6ggg.......>e[#[&[qqqqqqqee>z6gg......", +"g>#vmm''['1^^^'[###(>6g.....gq-6g....6&td]oo]@5k=}=o]2jj+&qzg....", +"6#^/{{nn{{pf%fp/{/l^#e>g....>id]777=7krhu4roooodi#e6....", +"g(vm^l^lal|f%!{^^11vqez6....6'<*2@@525=4u4k@2jj<&q>6....", +"6ee#['&&1&{!bp{1''[#e>6g....zq[i+;**22k$h~k*;;+-[q>g....", +"g>>ee(#[[&{fbpi[#q((e>6gg...6eeq[&-++*,~_r0;-&&[qe>6g...", +">ev'''['1&g...", +"(^np{l&a-ipfcfg...q9o7]@*2@@ysu$=@2**;+-&e6...", +"e#ml111^al|:xf<^&1[m[#(>g...#ij]jj*2@@~hu4,22j;t+i'eg...", +"6(#vv['1&ln:x!{&&m'v##(>g...>vi<+;t*2@=hu$k22;;+i-[eg...", +"g>eq#v['m&n!x!{1''##q(egg...ge[1-++;j*=$u4,*;;i-&[#zg...", +".66>e((q['{!%|/##qee>>6g.....6>e#'&&+;,4u}]--&[qeezg....", +"..gg66>ee(/|b|1q(>>6gg........g6>ze[[&o}_}2&[qe>6g......", +"....66z>eelpb|1e(>>6g...........6zzeq[]}_=2[[ee66.......", +".....g6>>(l|:n&(>>g6g............gzeq[]}h=2[qe6zg.......", +".....g.>>>l|:n1(>>6g.............ggzeq@}_=j[qe6g........", +"......g6>e^|bn1(ezgg..............g>eqdrhk2[q>zg........", +"......gg6>^|%|lqe>6g..............g6zedrur@&[ezg........", +".......gz>^|%|/vq>g................g>edrur5<&eg.........", +".......gg61|%|/vq>g................g6>jru}]<&qg.........", +"........g6vm{^v(e6g.................g6ij7d<&q6g.........", +".........ge(q(e>6g...................gqv^&qe>g..........", +"...........6g6gg......................g6666g............", +"............gg.g........................gg.g............", +"........................................................", +"...........gg..........................gz...............", +"........g6e(qeg.....................6zq'.............", +".......6>e#vm#>....................ze'i{j&e.............", +".......ge(v^lme....................6#vem/|^(g...................6eq9orj&g............", +".......g6em{!/#g...................gz#974kig............", +".......ggem|:/vgg..................g6#j}ho<6g...........", +".......gz6mn:{v6g..................g>>9=h7<6g...........", +".......gzem|:/vgg..................gz#j}ho<66...........", +".......6g>mn:{mzgg.................6ze9}$7t>gg..........", +".......66>m|:/m66g.................6>ej}h79>6g..........", +".......66e^{b{v>gg.................6>qj=h76g.................6>qj}h7te>g..........", +".......g6em|:nm>zg.................6>#j}h=tez6..........", +".......66em|:{m>>6g................6>qj}h=jee6g.........", +".......66>^nb{1>>6g................6>ed}h7*qe>g.........", +".......g6>m|:{me>6g................g>ej}h7jqe>6.........", +".......g6>^/:n1e>z6g...............g>ej7h=j[qz6g........", +".......gg6mnp{^q(>gg...............g6>j=472&[(6g........", +"........6zvl|{l^vezg................6>{]}7]2+[>6........", +"........6g#m^//{l#e6g...............6z&9]o77]iq6g.......", +".........geqv/|:{1>6g................6#&+]}h7jq>6.......", +".........g6e(m/|/1#e6................g>q^joroj&qz.......", +"..........g6e#m^1mvq>.................6z#&9dj9<&e.......", +"...........gg>e(#mmv>..................g6eq'itj(#m#e...................gz>e'i9i#.......", +"..............gg6e(eg.....................g6z#'q6.......", +".................gg..........................g6.........", +"........................................................", +"........................................................", +"........................................................", +"............g.ggg.g.....................g.ggg.g.........", +"........ggg6g6gg66g6ggg.............gg666z666z666gg.....", +".......gggz6z>>>>z>6z6gg...........gg6>>>eeee>e>>z6g....", +"......g>eqqq#q#(#q##qqez6g........ge[&&&-&-&----&&[e6g..", +".....ggqm^^^1^&^&&^&1'v(6g.......g6&t2d222222222*t+[>g..", +"....g66v^{{{{{{{{{{{//1#>6g.....gz>+]7,7k,ko,7okk52-qzg.", +"....g6>m{nn/{/{/{/{{<{{'ezg.....6>et7}77ook,okkkk=5;q>6.", +"....66>^|!p{aiiaiii{||n1(>6g....6zqd=4=k@@@0@00,=~=j&e6g", +"...gz>(l|bt{aaaaaiii9fp^#e6g...g>e[]r_y,@@@@@00,y4r@-q>g", +"...gz>q/!:p{ai&iii+npdpaqe6g...6>q&]4hrw0@@0@00w~4~@-q>6", +"..g6>(#/p:!9n<<<<<<9f:fi#ez6..g6e[a,~$~=,w,wwwwy~s4@-[>z", +"..g6>([{|f!p!|9p!f!j::p+[>>g..g6q&+5r$~~~yyy~~~~ss~0+qe6", +"..g6(v'{!:dfjf!jfjf:fd!/[(>6..gz[+;k~4s~~~~~~~~s$$4,+[ez", +"..g>v^{np!p!!!f!fd:::!pl&q>6..6e+]7}~~~~~~~~~s$444r5*-(z", +"..gzmnp!!!jppj9ffd:d!f9i1[(6..gej74~4~~}~~~~~sss~~y@*+[z", +"..6>^|f!p!9!!p!jf:bd!9{l1v(g..zed}44~~y~~y~~~$ss~yk5j+[z", +"..6zv^{n9p9|99p9!dxdf<{&[(e6..6>+dk==~yy=yyy~sus~w,2+", +"..gge#'ltp9||<|9fbcb!i&'q>6g..g6[i;5w~=yywyy48u_~52;&q6g", +"...6zeq&{p|gg...zzq&2k~ywwwww~$)sy0;-qe6g", +"...gz>(l|f9q[@=syww,,,wr$4=52-q>g.", +"...gg>(a|bp6g....g6e[@~4~w0000,wy=k]2-q>g.", +"...gz>>l|b|/-iaaii{///lv>g.....gzeq]rh=,00@@0@,oko]+eg..", +"....66e^|!9{iaaa&^&111v(6g......z>(2=$y,0@@@@222jj+[>g..", +"....g6>1{!n{{/il1'v##qe>g.......g>ej74=k,0@@2;+--&[eg...", +".....66vl{n{{{la^[e(>66g.........zz<]==kkk5@2+[[#>6g....", +".....g6#^l{{|n{l1#e>z6g..........g>-jo7=r=ko*-qez>6.....", +".....g6eq'/|fn{l1#>66g...........g6#&;]}4}o]j-ezzg......", +"......g6eelp%fnl'(>gg.............g>q']ru$=]t&e6g.......", +"......gg6em/n{^'#e66..............gg>q9o}7dt-qz6........", +".......ggz(vmmq(e6g................g6>v{jti[q>g.........", +".........g6z>>z6gg...................6z>eezz6g..........", +"........................................................", +"........................................................", +"...............g.g.........................g.g..........", +".............gg>ze>>g....................g6eeqqe6.......", +"...........gg>>(qqvq>g.................g6eq[&&+&eg......", +".........gg6ze(qvmmveg...............g66>q[&<9j<[6......", +"......gggz6>>q'^^^lm(6g...........gg6>>eq&;22d]t'6g.....", +"....gg6gz>>>('l/{//1#6g.........gg66>eeq[;]oko]j->6.....", +"...gg6z>>e(qq1{pn{l1#>66.......gg>>eqq[&&*kr=7oj-ez6....", +"..g6e#'m'1''1l{p|nn/mezg......6>[it;;*;**57rr==otq>6....", +".6z(m/n{{n{//{6g...", +".6e#/!%:::!p9|nnp:bpl(>6g....>#io4uh$h4~y==wrh_4@&e>g...", +".6>q^|f!::!f!p|6...", +".66>v^/n|!fpp9<{|np|l1#e6....zzqg..", +"...gg>evm^nj:p/1&11^l/lv>6g....g6eq+j@=~h}5***j2]o]+#zg.", +"...ggg>eq[/pb|i[[[#v^/lm(>g....gg6e[&+]~hr0+++-;do]t'eg.", +"....ggz>>ql|:nl[#((#m/lv(>g.....g6>eq&]rh}@+-&[ij]]{'e6.", +".....g6z>>m{nnl1'#((#vq(>g.......g6zeqto}=]2;-[[/<&'e6..", +"......g6z>v^//{/^[>ee>>6g.........gz>e+2oookd+qqq#e>g...", +".......gg6e#^^/{lve>6zgg...........g6z'+2]ok]+qe>z6g....", +"........g6ee#ml/lv#(>6g.............g6q[ij]o]t-'ezg.....", +".........g6>emm/lmm#egg..............g6e({jo]jti#6g.....", +"..........gggqm/l^m#e6g...............gz6&jo]djiq6g.....", +"...........gg>#vvmmv(g.................gge&<<99{'z......", +"............gg>eq#m#(>g.................g6eq&i9ive6.....", +"...............ge(v#(66...................ggq'6.....", +"................ge(e>6......................6q[qez......", +".................6ggg........................z66g.......", +"........................................................", +"........................................................", +"...........gggggg......................gggggg...........", +"........ggggggg6gg..................g6g6666>6g..........", +".......6eqee>(vm#e6g...............z#&qqe[+9i[zg........", +"......ge#m#qev^{^q>6g.............6#iti&q+d72&e>g.......", +".....g6qm^mqq1{|/me66g...........g6&t];-&*7}otqz>g......", +"....g66vl{l'qln:{1ee>gg.........66><]7];-@=h=*[qe6g.....", +"...g66>mnp{^[lnb|a#>>6gg.......gz>(j=472+5}hr@-qez6g....", +"...g6>e^|:ni1{!b|iqqe>6g.......gze#d}h=5*k4_r@-&qezg....", +".g6z>ee/|:ni1{!xp+[q(>z6g....g>>eq[5rh=@*kru~0+-[qe6g...", +".g>e>eq/!:p/at!xp{'[qeegg....6eqq[&]rhr,@w~uy,;+&qq6g...", +"g6e((eq/p:9/a[[[[&5~hy,@wsu~,*+&[qe6g..", +"6(v111mnfxft/!dx:g..", +"6#l{/llpbxf!tf%}%p/ia1&(>6g.6i]7o55r_us~w~_)_~,0@2*&qzg.", +">mn||n|!bcbfpdxcx:9t{{^vezg.ej=r}==4_)h4rsu)u4www5]+#>g.", +"6v^////!:x:f6g.6g.", +"ge#vmmmndbp<+9:x:9i^&'#ez6..gqi>(q/pb9{agg...g6eq[&o4hy,@w~s~k@*-&qezg..", +".ggg>>(lpbn-1i9f9{a'[(>66g...gg6e#&]rh=@*0y~y,@*+[q>6g..", +"..g6ze>l|:ni&a{|n{/^[(e6g.....g6zq(]rhy0*0kr==]@+[q>6...", +"...g66e^|:{^[^i{{z6......gzzqd}h7@+25,kk=@;[ezz...", +"....g6>^{:{^['&l/{nl'e>6g.......g>ed=$72+;2@,7=o;[e>g...", +"....g66mn:{m##''^{|{1qezg.......gzzj=h7j--;t@7r7*&qz6...", +".....gzmn!/mqqqqm{|n^(e>6g.......g>j=4oj&&&&j,}=2&qe6g..", +".....g6m{!/meee(vl|{^#e>gg.......gz974ot[[[[{]r7d-[e6g..", +"......gvl|^#>>>>qmmm1m#(6g........g<]}d-eeee&tjjj;i[>6..", +".......#^{mq>6>6>(q#m^mq>6........gid79&eze>e[&itd9&e6..", +".......(mlv(6g6g66ze#^mqegg........v9]#idjg.", +".......>(#(66gggggg>eqqe6g.........e'i[>6ggggg6e#&g..", +"........g66g....g.gg6>6g............666g....g.gg>e>6....", +"........................................................", +"........................................................", +"...........ggg.........................ggg..............", +"........gg6>>>6gg...................gg>eqezgg...........", +".......gg6ev^#(ggg.................g66[m/nlv>6g6g.............g6z>eto=]+ez66g........", +"....g6z>>em{!/meez6gg...........g6>eeqj=rktq#>>6g.......", +"...g66>>eql|:{&qee>6gg.........6>zeq[&]}h=2&[qez6g......", +"..66>eeqqq/pb|^(qeeezgg.......66eq[&&a5rh}@&&[qq>6g.....", +".g6>e###['{p%p/'[qq(ez6g.....6ze[---+;k4u}5;+--[qe6g....", +"gz>q1/{{i^|:c!{aa/i1mqe6....g>e&*o,,0@=hu$,@@002t&[z....", +"g>(v/f:p|{pb}bp{{|p{lm#>g...ge&+k4hr=wrh)hr,7=r=]tiqg...", +"6e(1|b}bpt:%cbfq&j=u)h~w$_)_~wr4h47d<[6...", +"ge([n:%!<{9%cdp/<|!|{^m(g...6q&+=hu4w,~_)sr5krrr7dt'6...", +"6e(#n:%!{i9fxf(#{!%9i&|fxf{'a{|n/^m(g...6e[-k4_y02w4u~k*@,}=odt'6...", +"6>eq{fxp{a9bcfeq{f%dn{!bcbp{npf|{^v(g...zeq-ohu$=w~_)h~,=r4r7d<'6...", +"g>>({:x:ptfx}bf{pf:!{^v(6...6eq&khu$r=$u)_4=r$hr=d+v6...", +"gz>e^n!|{/p:cf|/{{!n/mveg...g>e[@}$}k5~hu$}57=4=oj+#g...", +"g6>em/nl^&nfxf{1l///mv(>g...g6e(t5752*7$u4k*@]7oj<&eg...", +".g6>(v1[[#l!bn^[v1^^vv(z.....6ze&z.....g6zq&+-&&]}h}2&-+ti&'ez....", +"..gg>>e(((lpb{^qeq((e6g.......ggeq[[[']r_72&[&v'q>z.....", +"....g66z>e^nb{mee>6gg...........g6z>e(d}_7jq(e>66.......", +".....gg66>m{!{vz6z6g.............g6>>e97476g........", +".......666v/|l#>6gg................z6z<]}b-ez6g.........", +"........gg#m{m#g6g..................ggij7j&66g..........", +"..........(v^veg.g...................g'>>666gg..................gzqqez>z6g.....", +"............g>(#qe(e>66g................ge'i&[[#ez>g....", +"............ge#mm#q((eeg................6#ijt-&&[#q6....", +"...........6g#1/l1[##(e6g..............z6&jk]j+--&qzg...", +"..........g6>v/pn/1'[#q>g.............g>e+or752;+-&eg...", +"..........66>mnf|n^^1'q>g.............6zej7hrk@@jt...", +".........g6>>^n:!|{/1'qe6............g6eq2=h4}k5j;&q6...", +".........gg>em{p||n{^#e>g............gze[j,rrr=k2-[e6...", +".........gze('ln9!fn^#e66............zzq[;5==r4=@-q>6...", +"........g6>(#&l<9pf|&#ez6g..........gzq[-25wy~$=2-qe6g..", +"........gge#m/n!!ffn^[e>gg..........g6q-t5=~~~4=@+[e6g..", +"........g6e'^{pdfp!&;d=4_$~rw@;&[>g..", +".......g66e[1{pbf!9{l'[e6g.........g6z[+*,rh4~=w5;+[>6..", +".......g6>eq[{!bdp<6.........g>eq-+k~_s~wk5*+&e6..", +"......g66z(([a9::!n{i1'qz6g.......gz>e[&+@yh4~=,52;&e6g.", +".....6g6>e(q#/|bfj!n{l1#egg......6zzeq[&-5yhs~~=,]*-q6g.", +"...gg6z>>e(q[-eqq&-+@w$44~~=k@-#zg.", +"...gg6>z(eqq[it!ffd!9{iv>6g....gz>ee[[&-+0w~$$sryk5+qzg.", +".g6>(q#[''&aln|!f!!pn/1#z6g..g>e[&-+;;2@@=y4~~$~=]j-e>g.", +".g>evml^l/{{p|9|p!!|l^[qz6g..6e[+j@]@@k=r~y}~~4=52+&z6g.", +".z(q1/{{{n|!:f!9p||n^[(e6g...z[&jo777=}$h44=rrr=@+&q>6..", +".6>(v^////{nn{/li/{i^1#e66...ze'q+j]]]]@2dj*t;j;j2jt&zg..", +".g66qmm1mmv(e(e(eee(1l1#g....g6>&tjjjj+&[[[[q[[&j]j&z...", +"..gge#vvv[q(e>>>ez>e#vveg.....g6'&+<<+&[qe(eqee[i<ee((>>6z6g6z6zee>6.......g>e[q[[qe>>zz>>6>q[e>....", +".....ggg6666g6g6gggg.g...........gg66666zzg6gggg.g......", +"........................................................", +"........................................................", +"...........gggg........................gggg.............", +".........g6>e>>6gg...................gzq[qez6g..........", +".......g6ge#vvq(>6g................g66#i<+&[ezg.........", +"......ggz>#mlmvq(>gg..............g6>ei9]j+&[e6g........", +"....gg6z>>m/n/1qe>z6g...........g6>>eq;o=oja[e>zg.......", +"...g6>>>qe^|:n1#eee6g6.........g6eeq[[2}h=2-[[q>66......", +"..gg6eeeq#/px|/qq(eezgg.......g6>q[[&-]4ur5-&[[q>6g.....", +".g6>#1l^11nbc:na&'[#qe>6.....gzeij]2*2}h)h7@**+-&[qz....", +".geq^n!n{{f%rbp{{/l^1mqeg....6q&d=4}kk$u)h4,k5]d*<&#g...", +".>evn:xb!|bc4xbj||{{l^meg....e[+=huh4r_))uh~r==7]dt[6...", +"g6eqnbx:p|f%cx:ppnn/lmveg...g>#i=_uhr=4u)uh~r==o]j<#g...", +".6eq/f%!{in!b!!p|{ll1vq>g....zq&74u4k0=~s$~~yw5]j+&qg...", +".6>(/!%n/'-<|9nt{{^mv(>6.....ze']4u=o*0ky==wko2j+[q6....", +"g66(/!:ni1a/{t|9{i1'q(>6....g>>'o4h=@*@5kwy=k52;&[ez....", +".66el!:n^&&ai{9!{^'#e>66.....6z[]4$=@*2@0ky~7@;-[e>z....", +".66e^|!ni'&'&/|:|a#q>>6g.....6>qd}$=0*2**,}h=@-&qe6g....", +".66e^|!na1&'&/n:na#(ez6g.....6>qd}4k@*2**0=h=@-[q>>g....", +".g6>m/|/{/aa&{n!nl[q>>gg.....g6q9o}7o0@@2k=~=]+&qe6g....", +".g66v^/{{{{/l{nn{1'#(6zg.....g6>g....", +"..g6q^l/nn{{i{{n/^'v(>gg......gz&j]o=}7k5kk7]];+[e66....", +"..g6eqv/|fnn/i^1^/l^mqezg.....gz'i{o}4}7]5@d2]]dt&#>g...", +"...g6eqlpb!n/^m[mlnl^m#>g......g>q&orh4=o2t+j]=o2tiqg...", +"....66>l|%pn/m#ev^n{lm#eg.......6>e]ru4=oj-[+]=7]9iqg...", +"....ggzv^{lmm#(>qv^mmvq>g.......g6>i]7bjt-'e&6ze(qqq(>g........g6e&iiv'qezeq[^&&'eg...", +".......gg6g6gg6z6gg6eeezg..........6g>6666zz6z66#v#>g...", +".........gggg6gggggg6>6g.............gggg6gggggg>ezg....", +"....................ggg.........................ggg.....", +"........................................................", +"........................................................", +"........................................................", +"........................................................", +"......gg6g6g6g6g6ggg..............g66666666666gg........", +"....gg66z6>>z>z6z666gg..........g666>>ee>e>>>z>z6g......", +"...g6z>>>e>>>>>e>e>>z6g........g6>qeqqeqeqqqeqee>zg.....", +"..gg(v1'#(#e(ee>q#'v#e>6......g6[+j;-&&[[q[q&-;+-[qz....", +"..g>vl{/&'[qqeqq[1/^m#q>g.....ge<]752;+&&[&&+jo]ti&eg...", +".gg>^np{^&'[q#(('/n{l1#>6....gze2=47@*;+&-&&*5=7]j-q6...", +".g6>^|!ni''[(###&lnnlmv(g....g6qd}4=@*;+&---*5==]j<[6...", +".gz>^|!nl'[[##qq&lnn/^m(6g...gz#d}4=@*++-a&-*@==]2t'zg..", +".g6e^|!{^&[[##q#'/{n/^mqzg...g>qd}4,@*++----*o=7,dt&>g..", +".g6e^|!na[[q####1/n{/^1q6g...gz#d}$7@;+--a--*5==k@j&>g..", +".g6(^|fn^&[#qq##'i|n{lmqzg...g>[]}4=@*+a&&--*5=7o@j&z6..", +".66e^|!g..", +".6ze^|!n^&[[qqq#&i|n{l1q6g...z>[d}4k@*++&-&-*5y=5]j&zg..", +".g6e^|f{a[[qqqqq1in{/^1q>g...g>q]}$k2;+-'&-a*5==o@j&e6..", +".g6e^|!{^[[#q(qq&/|n{l1q66...g>qd}4k@;+-&&&a*,y=k]j&>6..", +".g6e^|fni&&[[['[a{|n{^m#6g...g>q]}4=@2*;++;+@,}=k]*&>g..", +".g6e^|!|{l-a&&&^/nf|{l1qzg...g6qd}$},0@@*222o=4r7@j&>6..", +".g6>^|f||{{/{//{n!:!nlmqzg...g>ed}$r==k,o5ok=4h47]t&>g..", +"..g>mn!pn{//lllln|!p{lmq6g....6ej=4r=ko555]5=r4rk]t&zg..", +"..g>mn|{l^11m'1&l{pn/1m(gg....6ej=r752j*tt**@7r=o2t'6g..", +"..gzm/|/1[#(qeq('^n//mm(6.....g>9or]j+-&&[&&;]=7ojtvz...", +"...6vl{^v(((e>ee#mll1m#eg......6<]7d+&[[qqq[-j]]jjiqg...", +"...ge#v#ee>>z>>e(#vv#ve>g......gqi>>666zz66zz>ee>>>.........6eqezz>zz>zz>q(#qeeg....", +"......ggggggggg6g6666g6...........gggggggggz66>6>z6.....", +"........g.g......ggg................g.g......ggg........", +"........................................................", +"........................................................", +"........................................................", +".......gggggggggg..................gggg6ggggg...........", +".....ggg666z66ggg6ggg............gg6>>>>>z66666gg.......", +"....g6>>>>>ee>e>>z6gg6g.........6>eeeeeq#eqee>z666g.....", +"...gze(ee(ee((e(>>e>z6zg.......g>q[[[[[[&[[[qq#e>>z6....", +"...6>#[[[[[[[#[##qqq(e>66g.....6q-+++++++-+---&&[[ez6g..", +"...6#l{{{{/iaa-iiii^&^mq>6g....>-]7k,,0@@@00@@5@22t&#zg.", +"..g>^nf!ff|n{nn9||||n{lmq>6...ged=h4$$~w,k=yy}}}=7o9.", +"..g>^|b:bbf!n9!f!!!!||{1qeg...ged}hhh_4~=y~$~444r}7j&q6.", +"..g6v^{n!!p!9p!:pn{//l^ve>6...gzg..", +"...gg>evl{|<|j::|i'###q>gg.....g6e(;5k==y~4_y@;---&e6g..", +"....66>#'^i{{9!bpi[#qee6g.......z>e&t255ky$hr0+-&[#zg...", +"....gg6e([''&npb|i[(e>>gg.......gz>q&+;*2,~_r5+&[qezg...", +".....g66>e([[{9%pl((ezzg.........g6>eq&++krhr@&[qz>g....", +"......g66eeq#^p:naqee66g..........g6>q[&-@rh=@&[q>6g....", +".......g66>eq1n:n^(e>zg............g6>e[&2=hk2&qqzz.....", +"........g6>>(1{p{&ee>6g.............gzee[j747*[qe6g.....", +".........g6z>[/|{1#eezg..............g>zq;]}7*-[q>6.....", +"..........gz>vl{l^[q>66...............g>e+]7]2+&qz6.....", +"..........g66qm/lmm#(6g...............g6>^j]]jj-[66.....", +"...........ggevm1^^mqe6g...............g6#+jj2dt&#zg....", +"............6>(#v^l^vqe6................6e[i<2od<&#>....", +".............ggz#^{lm#(6.................g6>id7]jivz....", +".............g6g(ml^mq(z.................g66vt]dt&'>....", +"..............g6>(#v((e6..................g6e'ii&v#z....", +"................gg6>>>>6....................g6>eeeez....", +"..................gg66gg......................gg>z6g....", +"....................g6g.........................gzg.....", +"........................................................", +"........................................................", +"........................................................", +".........gg6g66gzg66ggg..............6g66z66z6z66gg.....", +".......g66>#v((>(q##(>6g...........g6z#&+&[e[&i-&qzg....", +"......gg>evm/1#>#^l^1v(>g.........g6e#+joj-qi2odji&eg...", +"......g6eq^n!/1qm{pnl1#>g.........g>q&d=4oj&*or}ojiq6...", +".....66eeql|f{1#m{!|{^'(zg.......6>q[&]}4=*-j74}od;[>g..", +"....gz>(q#lnbn^#^{|n{^mq6g......6>#[&i]}_=@-2kr=kdt&z6..", +"....ze(qqv/|%ni'1{|n{lm#>6g.....>qv&-[i-+t74u45*5k~==k@+[zg.", +"....eqvm^^|:xf|i{p!!|{{m#e6.....q&{j2]}hu4y5kr$$y=oj-#>.", +"....e#ml/np%x:!<|fb:fp|lvq>g....#ij]]=4u)h~ky4sh44y]{&eg", +"....e#mll{pbcbp{9!::!!nl'q>....gqi9]ox4h)h4ky4$h44=];&e.", +"....6eq#m^n:xf|l<9!fpn/mqe6.....>q&itd=hu4y5ky4$}=oj&q>.", +"....gg>e(#/!%p/&/n!|n/lve66.....g6qq&io4ur,*,k~=yo]+'>6.", +".....6g>eel|%pi&a{9|{l^#>6g......66eq[]}u}5*@ky=k52-e>g.", +".....g66e(lp:|l[a{pn{/^#>6g......gz>q[]rhr5;@kryk5d-e6g.", +"......g6e>l|%|/[^{9|{im#>gg.......gzqq]}u}5+2k=rk5jie6g.", +"......g6zel|bni[a/|n{l1q>6.......ggze(]}h}@;@,y=k@j&ez..", +"......gg>>^|%|i[&{|{{/m#6g........gzeqdrur0+2,}=k5j-z6..", +"......g66e^|b|l'&{9n/l1qz6........g6>qd}hr@;2,==o]j&>6..", +".......66>^nb|l[&{n|{^mq6g.........6zed}hr@+*k}=,@j&>g..", +".......g6>^|%|{&lnpn{l1qzg.........g>edrur,25=~}7]j&>g..", +".......gg>^!%!nl{pf|{lme6g.........g6e24u475kr$r7]t[>g..", +".......g66^px:|{n!:!{^m(6..........gz>d4uhr7=rh47dt'6...", +"........ggv/|{l^//|{lm#eg...........g6g...........ggv9dj{-td]29+&eg...", +".........gg>eeez(qvvq(>6.............g6eq#(e[&{+^'q6....", +"..........gg6666eeqee>>g..............g6>z>>q[&[qeeg....", +"...........g6gggg6>>6gg................gzgg66>eezzg.....", +".................g.g.........................g.g........", +"........................................................", +"........................................................", +"...g6>>>e>>6gzg6g6ggg..........gzeqqqeez6z6666ggg.......", +"..6>qm1m##q(>>eee>6gggg.......ze&;j;+-&[eq#[qq>66gg.....", +".6>em/{/l1[q(qq#q(eez6g6g....ze[jo7]]*+&[&&-&[q#ez66g...", +".6eql|!n{l1[(#vm'v((e>zggg...z#^]}4}752+&-+;;+&[qe>66g..", +".g>(m/|{{/^i&^^il//^^mv#(>6..6e'jor7k5@@2@@5]5o]2;<-'q6.", +".g6evl////{{{<{{{|fpn{/1m#>g.g>q{]o]o5k,7k7k=r$r=7]jti#g", +".g6>#m^l/i{!!!|pfbxxf!|{l1(6.g>e-;d@55k~44}}4huuh4r7]j'6", +"..z6qv'^i{||!|{{|!::!nn/mveg..z>&+*@5k==rrkk}$hh4}7oj{qg", +".g66e#'&/{tn!n/&{|!!n{lmvqzg.gzz#-;25wwrrk52k=4r=7bj+^eg", +"..gz>e[1+nn|9/a[1{nn{lmve>6g..6>q[-2,=y=yk@+2k==7]ji[e>g", +"..6zeq[^{|9n|/1[1^////^v>>g...6zq&+@7=y==5*+*@ko552+qez.", +"..66(v1/n!||{i1q[m^1/llvez6g..z>&+j0=~yyk5*-+t22o]]+q>6g", +"..6zq'^{|!pn{l&q##[ml{lme6g...6>&;2kr4~==5*a-a+j@7ot[>6.", +"..66#^/{9|9|{a'q((qml{/mez6...zzi@okyry=k@;&&&&;]=]tqzz.", +"..g>1{pn{/{{{^'qq((m/|{m(6g...gej7r=,5kkk@;&&&&;or=j[66.", +"..6>lpf|i&^l{^'qq((m/!|1e66...zq]rh}5*@]72;&&[[t7rrj[z6.", +"..g>^p:{1'&/{a[(((qm{!|^e6g...gedrh72;2o72+&[&&;74rd[>g.", +"..gg#^/mv#^n|/'q(qqm/fp1(zg...g6idoj<-2k}k;&[&&t74~j'>g.", +"...geqv#qq^nf{1(qeqm{f|^egg....6q&i-&&d=47*&&[&97$rd(zg.", +"....gze>>e^|!n&####^/!|^e6g.....6eqq([2}4=*--a-2x4}d#6g.", +"....ggzz>>m/|n/^//{{||/v>g......g6z>eq9or=o@]o77}}ovln||p|!!p|/l#>6........gz>e<]=rrrr444}7]iez..", +".......gg6qm/n|!::%!|lmq6g.........g66&jo=r4h$u4}]9&zg..", +"........ggeqvm//{/{{mvq>g...........g6#^g...", +"...........gzze((((e>gg................6>e#''vvqe6g.....", +"............g66>>>>z6g..................g6>eeeee6gg.....", +".............gg6ggggg....................g6666zgg.......", +"................g...........................g...........", +"........................................................", +"........................................................", +".........gggg........................gggg...............", +".......6eqqee>ggggg666gg...........z[&&[qe6ggg66zz6g....", +"......gevmvv#qe6666>eqeg..........g#z>e#'#6....", +"......gq1l^mm#(zz>>eeq(>g.........g&j]djj-[>>eq[[&'(g...", +"......g(^llllm#e(q#m^l1#>g........6^j]b]]t-q[&itd]jieg..", +"......6qml/{{^'e#v1^/|{meg........6&9]oc7];[-+jdo}79q6..", +".....ggqml{{|/1q[m^/|!|^ezg......g6^j]k=}5*&+;2kr$}d[>g.", +".....gg(#m/|!{1#ml{{nnlm(6g......gz[i9o}4k2-t]7x==ot'zg.", +"......6e(v/|:n^[1/nn//1#(6g.......6q&+]rh=@+20}=ooji'>g.", +".....ggze(/|%pi'^{!|lmvqe>g......gzz#&5r_r@;@74}]j<&qe6.", +".....g6zeql|:pg.......g6eq&@}h~w0kk}7d+&[e6..", +".....g6>>elnff|||{{lm#(>6g.......gzeq[@=4$r==w,]t-[ezg..", +".....g6>eq&{p!f:|nl^qe>ggg.......g6q[&2k~44sr752-qezgg..", +".....gz>eqln!f:%!nlm#>>6g........6ze[&@7~$s_$k@t-qezg...", +"....g66e(q&{|dbx:{1'#e6zg.......gz>q[&2kr4hu4k2;-qz>g...", +"...ggz>>q#a{p:xc:t1[ee>gg......gg>eq&-@,~hu)h=*+[q(zg...", +"...g6eq['1/{9!:%!nlm[>>6g......g>[&+;25ky4s_4=5*+qe6g...", +"..gzqvm/n|p|p9|9ppp{1e>6g.....g>&+j57}rrr=ry~rr7j[e>6...", +"..g>#m/|:%!!nn/ln!:!l#>z6g....zeij]rhu$~==o@=4h4]-qz6g..", +"..6evl{|!:!|{/1m/n:|/#(>6g....6q<]7r4h4==52j]yh}5i[(zg..", +"..g>vl{{nnllm'[#m^ll^mvq>>g...6e<]77==]]j;+-9d]]dj<&#eg.", +"..g>vl{/l^m#(qeeqqvmm^mvqe6...ge{]7]]dt-[&[[&&>>>>zeqvmmvqe6....zid7jti&[eeeeeeq&.", +"...ge#m#((e66z6g666>(#qezzg....gqiz>>66z>e'&&#e>g.", +"....g6z>66gggggggg6g66666g......6>eez66ggggggg6gz>>>6g..", +"........gggg.........g..............gggg.........g......", +"........................................................", +"........................................................", +"........................................................", +"........................................................", +"........................................................", +"...g66>6ggg....................gzzez6gg.................", +"..gg>(ee>6g...................g6([[qe66.................", +".g>eq#vqeez6g................6eq&i+-[qe6g...............", +"6e#'^lll1'q>gg..............6#it2]o]j;&q6g..............", +"g#^/{n|{/lm(6gg.............6ido7=}kkdt[>6g.............", +"6v1/n|!nn/1q>6gg............6id]=r4}=7*&e6gg............", +"ge#mln|nnn^[>>6ggggg6>>g6...g#i9]=}===d+qez6ggggzee66...", +"g6eq^/|||nl[(>zzggg6>e>>zg..gz#&do}r}}]+[e>>666>eqqe>6..", +".g6em//||p/'e>>zzzz>e#qe>6g..6>#to7=r~o;[qe>>>zq'-&[e6g.", +".66z#^/|f:n^q(e>e(qmm/m#>g...66ei2]}4h=2&[qqq[&+j]jie6..", +".g66#vl|fx|&qee>(vm^/n/veg...g6>-t@}hur2&[qq[+tdo=]g....6z[-jrhuy@-&[[&tdo=r=teg..", +"..g6eqv/p%pi'[q([m///l^(6g....g6#&+k4ur5;+&[+jooo]d&>6..", +"....>>q/|!n/&'#em^{/^m#e6g.....geq&]}$}52;-[;d7od9i#6g..", +"...g66>1{!|{l&[(mln/mqe>g......g6zq*7ryk02+&;]=]j&qeg...", +"....gzev^{n|pi'q#m^m#e>gg.......z>q6g........g6z&;2k4$y2&--<-qe6z....", +".....66>e#{!cplq((>e666g.........z>q[ik4)r@&&[qq>>6g....", +"......gzeq^n!nl1[qe>>g6g..........g>[&d=4=5*+&qeez6g....", +"......gg6ev^//{{l#(>>6gg..........g6>q+d]o7,@+[ee66g....", +".......g66>qvl{p/m>e6zgg...........g>>q&+]7ro;qq>>6g....", +"........6z>eqml{/^m#e>6g............6ze[&j]7o2;-[ezg....", +".........g6>>#m^lll^#>66.............g>eqit]]]]2-q>z....", +"..........g66eq#^/|/1q>z..............g6zq&a27}oj&e>....", +"...........gg>e(v^/lmq(6g..............g6e#&{dkb;&[zg...", +"............gg6e(#mvmv#eg...............g6z('iteq#mv>g.................g6ze#&it+#6...", +"...............gggg>(v#eg..................gg66#[e>g....................g.g6eqe6....", +".....................gg..........................gg.....", +"........................................................"}; diff --git a/hacks/penrose.c b/hacks/penrose.c index 6e401aa6..a8af2e51 100644 --- a/hacks/penrose.c +++ b/hacks/penrose.c @@ -102,9 +102,6 @@ If one of these are hit penrose will reinitialize. * vertex rules only allow at most seven tiles to meet at a vertex. */ -#define CELEBRATE 31415927 /* This causes a pause, an error occurred. */ -#define COMPLETION 3141593 /* This causes a pause, an error occurred. */ - #define MAX_TILES_PER_VERTEX 7 #define N_VERTEX_RULES 8 #define ALLOC_NODE( type) ((type *)malloc( sizeof( type))) @@ -112,21 +109,28 @@ If one of these are hit penrose will reinitialize. static Bool ammann; +/* How long in seconds should we wait before starting a new tiling? */ +static long redo_delay = 3; +static long redo_delay_usec; + static XrmOptionDescRec opts[] = { {"-ammann", ".penrose.ammann", XrmoptionNoArg, (caddr_t) "on"}, - {"+ammann", ".penrose.ammann", XrmoptionNoArg, (caddr_t) "off"} + {"+ammann", ".penrose.ammann", XrmoptionNoArg, (caddr_t) "off"}, + {"-redoDelay", ".penrose.redoDelay", XrmoptionSepArg, NULL} }; static argtype vars[] = { - {(caddr_t *) & ammann, "ammann", "Ammann", DEF_AMMANN, t_Bool} + {(caddr_t *) & ammann, "ammann", "Ammann", DEF_AMMANN, t_Bool}, + {(caddr_t *) & redo_delay, "redoDelay", "RedoDelay", "3", t_Int} }; static OptionStruct desc[] = { - {"-/+ammann", "turn on/off Ammann lines"} + {"-/+ammann", "turn on/off Ammann lines"}, + {"-redoDelay", "delay between new tilings"} }; -ModeSpecOpt penrose_opts = { 2, opts, 1, vars, desc }; +ModeSpecOpt penrose_opts = { 3, opts, 2, vars, desc }; /*- @@ -326,7 +330,7 @@ vertex_dir(ModeInfo * mi, fringe_node_c * vertex, unsigned side) (void) fprintf(stderr, "v2->fived[%d]=%d, vertex->fived[%d]=%d\n", i, v2->fived[i], i, vertex->fived[i]); } - MI_PAUSE(mi) = CELEBRATE; + MI_PAUSE(mi) = redo_delay_usec; return 0; } @@ -414,6 +418,8 @@ init_penrose(ModeInfo * mi) fringe_node_c *fp; int i, size; + redo_delay_usec = redo_delay * 1000000; + if (tilings == NULL) { if ((tilings = (tiling_c *) calloc(MI_NUM_SCREENS(mi), sizeof (tiling_c))) == NULL) @@ -715,7 +721,7 @@ check_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp) if (MI_WIN_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Dislocation occured!\n"); } - MI_PAUSE(mi) = CELEBRATE; /* Should be able to recover */ + MI_PAUSE(mi) = redo_delay_usec; /* Should be able to recover */ } if (1 == find_completions(vertex, hits, n_hits, S_LEFT, 0 /*, False */ )) forced_sides |= S_LEFT; @@ -770,7 +776,7 @@ delete_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp) (void) fprintf(stderr, "Weirdness in delete_penrose()\n"); (void) fprintf(stderr, "tp->fringe.nodes == vertex\n"); } - MI_PAUSE(mi) = CELEBRATE; + MI_PAUSE(mi) = redo_delay_usec; } if (vertex->list_ptr != 0) { forced_node_c *node = *vertex->list_ptr; @@ -910,7 +916,7 @@ alloc_vertex(ModeInfo * mi, angle_c dir, fringe_node_c * from, tiling_c * tp) (void) fprintf(stderr, "Weirdness in alloc_vertex()\n"); (void) fprintf(stderr, "v = 0\n"); } - MI_PAUSE(mi) = CELEBRATE; + MI_PAUSE(mi) = redo_delay_usec; } *v = *from; add_unit_vec(dir, v->fived); @@ -1230,7 +1236,7 @@ draw_penrose(ModeInfo * mi) /* No visible nodes left. */ if (tp->fringe.n_nodes == 0) { tp->done = True; - MI_PAUSE(mi) = COMPLETION; /* Just finished drawing */ + MI_PAUSE(mi) = redo_delay_usec; /* Just finished drawing */ return; } if (tp->forced.n_visible > 0 && tp->failures < 10) { diff --git a/hacks/penrose.man b/hacks/penrose.man index db4c818c..e4734bf8 100644 --- a/hacks/penrose.man +++ b/hacks/penrose.man @@ -3,7 +3,7 @@ penrose - draws quasiperiodic tilings .SH SYNOPSIS .B penrose -[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-size \fIinteger\fP] [\-ammann] [\-no\-ammann] +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-redoDelay \fIseconds\fP] [\-size \fIinteger\fP] [\-ammann] [\-no\-ammann] .SH DESCRIPTION The \fIpenrose\fP program draws quasiperiodic tilings. @@ -32,6 +32,10 @@ extended a window's length beyond the edge of the window horizontally or vertically or forced rule choice has failed 100 times due to areas about to become enclosed. +Although quasiperiodic tilings are produced, the tiles themselves are +not penrose tiles (darts and kites). In contrast to penrose tiles, +these tiles can be arranged to form a periodic tiling. + .SH OPTIONS .I penrose accepts the following options: @@ -59,6 +63,15 @@ The colors are chosen randomly. .B \-size \fIinteger\fP How big the tiles should be. Default 40 pixels. +.TP 8 +.B \-delay \fImilliseconds\fP +How long (in 1/1,000,000'ths of a second) to wait between drawing each +tile. Default 10,000 or .01 seconds. + +.TP 8 +.B \-redoDelay \fIseconds\fP +How long to wait between starting a completely new tiling. Default 3 seconds. + .TP 8 .B \-ammann \fIinteger\fP .TP 8 diff --git a/hacks/phosphor.c b/hacks/phosphor.c new file mode 100644 index 00000000..c575bb2a --- /dev/null +++ b/hacks/phosphor.c @@ -0,0 +1,801 @@ +/* xscreensaver, Copyright (c) 1999 Jamie Zawinski + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * Phosphor -- simulate a glass tty with long-sustain phosphor. + */ + +#include "screenhack.h" +#include +#include +#include +#include + +extern XtAppContext app; + +#define FUZZY_BORDER + +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) + +#define BLANK 0 +#define FLARE 1 +#define NORMAL 2 +#define FADE 3 + +#define CURSOR_INDEX 128 + +typedef struct { + unsigned char name; + int width, height; + Pixmap pixmap; +#ifdef FUZZY_BORDER + Pixmap pixmap2; +#endif /* FUZZY_BORDER */ + Bool blank_p; +} p_char; + +typedef struct { + p_char *p_char; + int state; + Bool changed; +} p_cell; + +typedef struct { + Display *dpy; + Window window; + XWindowAttributes xgwa; + XFontStruct *font; + int grid_width, grid_height; + int char_width, char_height; + int scale; + int ticks; + p_char **chars; + p_cell *cells; + XGCValues gcv; + GC gc0; + GC gc1; +#ifdef FUZZY_BORDER + GC gc2; +#endif /* FUZZY_BORDER */ + GC *gcs; + XImage *font_bits; + + int cursor_x, cursor_y; + XtIntervalId cursor_timer; + Time cursor_blink; + + FILE *pipe; + XtInputId pipe_id; + Bool input_available_p; + Time subproc_relaunch_delay; + +} p_state; + + +static void capture_font_bits (p_state *state); +static p_char *make_character (p_state *state, int c); +static void drain_input (p_state *state); +static void char_to_pixmap (p_state *state, p_char *pc, int c); +static void launch_text_generator (p_state *state); + + +/* About font metrics: + + "lbearing" is the distance from the leftmost pixel of a character to + the logical origin of that character. That is, it is the number of + pixels of the character which are to the left of its logical origin. + + "rbearing" is the distance from the logical origin of a character to + the rightmost pixel of a character. That is, it is the number of + pixels of the character to the right of its logical origin. + + "descent" is the distance from the bottommost pixel of a character to + the logical baseline. That is, it is the number of pixels of the + character which are below the baseline. + + "ascent" is the distance from the logical baseline to the topmost pixel. + That is, it is the number of pixels of the character above the baseline. + + Therefore, the bounding box of the "ink" of a character is + lbearing + rbearing by ascent + descent; + + "width" is the distance from the logical origin of this character to + the position where the logical orgin of the next character should be + placed. + + For our purposes, we're only interested in the part of the character + lying inside the "width" box. If the characters have ink outside of + that box (the "charcell" box) then we're going to lose it. Alas. + */ + +static p_state * +init_phosphor (Display *dpy, Window window) +{ + int i; + unsigned long flags; + p_state *state = (p_state *) calloc (sizeof(*state), 1); + char *fontname = get_string_resource ("font", "Font"); + XFontStruct *font; + + state->dpy = dpy; + state->window = window; + + XGetWindowAttributes (dpy, window, &state->xgwa); + + state->font = XLoadQueryFont (dpy, fontname); + + if (!state->font) + { + fprintf(stderr, "couldn't load font \"%s\"\n", fontname); + state->font = XLoadQueryFont (dpy, "fixed"); + } + if (!state->font) + { + fprintf(stderr, "couldn't load font \"fixed\""); + exit(1); + } + + font = state->font; + state->scale = get_integer_resource ("scale", "Integer"); + state->ticks = 3 + get_integer_resource ("ticks", "Integer"); + +#if 0 + for (i = 0; i < font->n_properties; i++) + if (font->properties[i].name == XA_FONT) + printf ("font: %s\n", XGetAtomName(dpy, font->properties[i].card32)); +#endif /* 0 */ + + state->cursor_blink = get_integer_resource ("cursor", "Time"); + state->subproc_relaunch_delay = + (1000 * get_integer_resource ("relaunch", "Time")); + + state->char_width = font->max_bounds.width; + state->char_height = font->max_bounds.ascent + font->max_bounds.descent; + + state->grid_width = state->xgwa.width / (state->char_width * state->scale); + state->grid_height = state->xgwa.height /(state->char_height * state->scale); + state->cells = (p_cell *) calloc (sizeof(p_cell), + state->grid_width * state->grid_height); + state->chars = (p_char **) calloc (sizeof(p_char *), 256); + + state->gcs = (GC *) calloc (sizeof(GC), state->ticks + 1); + + { + int ncolors = MAX (0, state->ticks - 3); + XColor *colors = (XColor *) calloc (ncolors, sizeof(XColor)); + int h1, h2; + double s1, s2, v1, v2; + + unsigned long fg = get_pixel_resource ("foreground", "Foreground", + state->dpy, state->xgwa.colormap); + unsigned long bg = get_pixel_resource ("background", "Background", + state->dpy, state->xgwa.colormap); + unsigned long flare = get_pixel_resource ("flareForeground", "Foreground", + state->dpy,state->xgwa.colormap); + unsigned long fade = get_pixel_resource ("fadeForeground", "Foreground", + state->dpy,state->xgwa.colormap); + + XColor start, end; + + start.pixel = fade; + XQueryColor (state->dpy, state->xgwa.colormap, &start); + + end.pixel = bg; + XQueryColor (state->dpy, state->xgwa.colormap, &end); + + /* Now allocate a ramp of colors from the main color to the background. */ + rgb_to_hsv (start.red, start.green, start.blue, &h1, &s1, &v1); + rgb_to_hsv (end.red, end.green, end.blue, &h2, &s2, &v2); + make_color_ramp (state->dpy, state->xgwa.colormap, + h1, s1, v1, + h2, s2, v2, + colors, &ncolors, + False, True, False); + + /* Now, GCs all around. + */ + state->gcv.font = font->fid; + state->gcv.cap_style = CapRound; +#ifdef FUZZY_BORDER + state->gcv.line_width = (int) (((long) state->scale) * 1.3); + if (state->gcv.line_width == state->scale) + state->gcv.line_width++; +#else /* !FUZZY_BORDER */ + state->gcv.line_width = (int) (((long) state->scale) * 0.9); + if (state->gcv.line_width >= state->scale) + state->gcv.line_width = state->scale - 1; + if (state->gcv.line_width < 1) + state->gcv.line_width = 1; +#endif /* !FUZZY_BORDER */ + + flags = (GCForeground | GCBackground | GCCapStyle | GCLineWidth); + + state->gcv.background = bg; + state->gcv.foreground = bg; + state->gcs[BLANK] = XCreateGC (state->dpy, state->window, flags, + &state->gcv); + + state->gcv.foreground = flare; + state->gcs[FLARE] = XCreateGC (state->dpy, state->window, flags, + &state->gcv); + + state->gcv.foreground = fg; + state->gcs[NORMAL] = XCreateGC (state->dpy, state->window, flags, + &state->gcv); + + for (i = 0; i < ncolors; i++) + { + state->gcv.foreground = colors[i].pixel; + state->gcs[FADE + i] = XCreateGC (state->dpy, state->window, + flags, &state->gcv); + } + } + + capture_font_bits (state); + + launch_text_generator (state); + + return state; +} + + +static void +capture_font_bits (p_state *state) +{ + XFontStruct *font = state->font; + int safe_width = font->max_bounds.rbearing - font->min_bounds.lbearing; + int height = state->char_height; + unsigned char string[257]; + int i; + Pixmap p = XCreatePixmap (state->dpy, state->window, + (safe_width * 256), height, 1); + + for (i = 0; i < 256; i++) + string[i] = (unsigned char) i; + string[256] = 0; + + state->gcv.foreground = 0; + state->gcv.background = 0; + state->gc0 = XCreateGC (state->dpy, p, + (GCForeground | GCBackground), + &state->gcv); + + state->gcv.foreground = 1; + state->gc1 = XCreateGC (state->dpy, p, + (GCFont | GCForeground | GCBackground | + GCCapStyle | GCLineWidth), + &state->gcv); + +#ifdef FUZZY_BORDER + { + state->gcv.line_width = (int) (((long) state->scale) * 0.8); + if (state->gcv.line_width >= state->scale) + state->gcv.line_width = state->scale - 1; + if (state->gcv.line_width < 1) + state->gcv.line_width = 1; + state->gc2 = XCreateGC (state->dpy, p, + (GCFont | GCForeground | GCBackground | + GCCapStyle | GCLineWidth), + &state->gcv); + } +#endif /* FUZZY_BORDER */ + + XFillRectangle (state->dpy, p, state->gc0, 0, 0, (safe_width * 256), height); + + for (i = 0; i < 256; i++) + { + if (string[i] < font->min_char_or_byte2 || + string[i] > font->max_char_or_byte2) + continue; + XDrawString (state->dpy, p, state->gc1, + i * safe_width, font->ascent, + string + i, 1); + } + + /* Draw the cursor. */ + XFillRectangle (state->dpy, p, state->gc1, + (CURSOR_INDEX * safe_width), 1, + (font->per_char + ? font->per_char['n'-font->min_char_or_byte2].width + : font->max_bounds.width), + font->ascent - 1); + +#if 0 + XCopyPlane (state->dpy, p, state->window, state->gcs[FLARE], + 0, 0, (safe_width * 256), height, 0, 0, 1L); + XSync(state->dpy, False); +#endif + + XSync (state->dpy, False); + state->font_bits = XGetImage (state->dpy, p, 0, 0, + (safe_width * 256), height, ~0L, XYPixmap); + XFreePixmap (state->dpy, p); + + for (i = 0; i < 256; i++) + state->chars[i] = make_character (state, i); + state->chars[CURSOR_INDEX] = make_character (state, CURSOR_INDEX); +} + + +static p_char * +make_character (p_state *state, int c) +{ + p_char *pc = (p_char *) malloc (sizeof (*pc)); + pc->name = (unsigned char) c; + pc->width = state->scale * state->char_width; + pc->height = state->scale * state->char_height; + char_to_pixmap (state, pc, c); + return pc; +} + + +static void +char_to_pixmap (p_state *state, p_char *pc, int c) +{ + Pixmap p = 0; + GC gc; +#ifdef FUZZY_BORDER + Pixmap p2 = 0; + GC gc2; +#endif /* FUZZY_BORDER */ + int from, to; + int x1, y; + + XFontStruct *font = state->font; + int safe_width = font->max_bounds.rbearing - font->min_bounds.lbearing; + + int width = state->scale * state->char_width; + int height = state->scale * state->char_height; + + if (c < font->min_char_or_byte2 || + c > font->max_char_or_byte2) + goto DONE; + + gc = state->gc1; + p = XCreatePixmap (state->dpy, state->window, width, height, 1); + XFillRectangle (state->dpy, p, state->gc0, 0, 0, width, height); +#ifdef FUZZY_BORDER + gc2 = state->gc2; + p2 = XCreatePixmap (state->dpy, state->window, width, height, 1); + XFillRectangle (state->dpy, p2, state->gc0, 0, 0, width, height); +#endif /* FUZZY_BORDER */ + + from = safe_width * c; + to = safe_width * (c + 1); + +#if 0 + if (c > 75 && c < 150) + { + printf ("\n=========== %d (%c)\n", c, c); + for (y = 0; y < state->char_height; y++) + { + for (x1 = from; x1 < to; x1++) + printf (XGetPixel (state->font_bits, x1, y) ? "* " : ". "); + printf ("\n"); + } + } +#endif + + pc->blank_p = True; + for (y = 0; y < state->char_height; y++) + for (x1 = from; x1 < to; x1++) + if (XGetPixel (state->font_bits, x1, y)) + { + int xoff = state->scale / 2; + int x2; + for (x2 = x1; x2 < to; x2++) + if (!XGetPixel (state->font_bits, x2, y)) + break; + x2--; + XDrawLine (state->dpy, p, gc, + (x1 - from) * state->scale + xoff, y * state->scale, + (x2 - from) * state->scale + xoff, y * state->scale); +#ifdef FUZZY_BORDER + XDrawLine (state->dpy, p2, gc2, + (x1 - from) * state->scale + xoff, y * state->scale, + (x2 - from) * state->scale + xoff, y * state->scale); +#endif /* FUZZY_BORDER */ + x1 = x2; + pc->blank_p = False; + } + + /* if (pc->blank_p && c == CURSOR_INDEX) + abort();*/ + + DONE: + pc->pixmap = p; +#ifdef FUZZY_BORDER + pc->pixmap2 = p2; +#endif /* FUZZY_BORDER */ +} + + +/* Managing the display. + */ + +static void cursor_on_timer (XtPointer closure, XtIntervalId *id); +static void cursor_off_timer (XtPointer closure, XtIntervalId *id); + +static Bool +set_cursor_1 (p_state *state, Bool on) +{ + p_cell *cell = &state->cells[state->grid_width * state->cursor_y + + state->cursor_x]; + p_char *cursor = state->chars[CURSOR_INDEX]; + int new_state = (on ? NORMAL : FADE); + + if (cell->p_char != cursor) + cell->changed = True; + + if (cell->state != new_state) + cell->changed = True; + + cell->p_char = cursor; + cell->state = new_state; + return cell->changed; +} + +static void +set_cursor (p_state *state, Bool on) +{ + if (set_cursor_1 (state, on)) +; + { + if (state->cursor_timer) + XtRemoveTimeOut (state->cursor_timer); + state->cursor_timer = 0; + cursor_on_timer (state, 0); + } +} + + + + +static void +cursor_off_timer (XtPointer closure, XtIntervalId *id) +{ + p_state *state = (p_state *) closure; + set_cursor_1 (state, False); + state->cursor_timer = XtAppAddTimeOut (app, state->cursor_blink, + cursor_on_timer, closure); +} + +static void +cursor_on_timer (XtPointer closure, XtIntervalId *id) +{ + p_state *state = (p_state *) closure; + set_cursor_1 (state, True); + state->cursor_timer = XtAppAddTimeOut (app, 2 * state->cursor_blink, + cursor_off_timer, closure); +} + + +static void +clear (p_state *state) +{ + int x, y; + state->cursor_x = 0; + state->cursor_y = 0; + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + p_cell *cell = &state->cells[state->grid_width * y + x]; + if (cell->state == FLARE || cell->state == NORMAL) + { + cell->state = FADE; + cell->changed = True; + } + } + set_cursor (state, True); +} + + +static void +decay (p_state *state) +{ + int x, y; + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + p_cell *cell = &state->cells[state->grid_width * y + x]; + if (cell->state == FLARE) + { + cell->state = NORMAL; + cell->changed = True; + } + else if (cell->state >= FADE) + { + cell->state++; + if (cell->state >= state->ticks) + cell->state = BLANK; + cell->changed = True; + } + } +} + + +static void +scroll (p_state *state) +{ + int x, y; + for (x = 0; x < state->grid_width; x++) + { + p_cell *from, *to; + for (y = 1; y < state->grid_height; y++) + { + from = &state->cells[state->grid_width * y + x]; + to = &state->cells[state->grid_width * (y-1) + x]; + + if ((from->state == FLARE || from->state == NORMAL) && + !from->p_char->blank_p) + { + *to = *from; + to->state = NORMAL; /* should be FLARE? Looks bad... */ + } + else + { + if (to->state == FLARE || to->state == NORMAL) + to->state = FADE; + } + + to->changed = True; + } + + to = from; + if (to->state == FLARE || to->state == NORMAL) + { + to->state = FADE; + to->changed = True; + } + } + set_cursor (state, True); +} + + +static void +print_char (p_state *state, int c) +{ + p_cell *cell = &state->cells[state->grid_width * state->cursor_y + + state->cursor_x]; + + /* Start the cursor fading (in case we don't end up overwriting it.) */ + if (cell->state == FLARE || cell->state == NORMAL) + { + cell->state = FADE; + cell->changed = True; + } + + if (c == '\t') c = ' '; /* blah. */ + + if (c == '\r' || c == '\n') + { + state->cursor_x = 0; + if (state->cursor_y == state->grid_height - 1) + scroll (state); + else + state->cursor_y++; + } + else if (c == '\014') + { + clear (state); + } + else + { + cell->state = FLARE; + cell->p_char = state->chars[c]; + cell->changed = True; + state->cursor_x++; + + if (c != ' ' && cell->p_char->blank_p) + cell->p_char = state->chars[CURSOR_INDEX]; + + if (state->cursor_x >= state->grid_width - 1) + { + state->cursor_x = 0; + if (state->cursor_y >= state->grid_height - 1) + scroll (state); + else + state->cursor_y++; + } + } + set_cursor (state, True); +} + + +static void +update_display (p_state *state, Bool changed_only) +{ + int x, y; + + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + p_cell *cell = &state->cells[state->grid_width * y + x]; + int width, height, tx, ty; + + if (changed_only && !cell->changed) + continue; + + width = state->char_width * state->scale; + height = state->char_height * state->scale; + tx = x * width; + ty = y * height; + + if (cell->state == BLANK || cell->p_char->blank_p) + { + XFillRectangle (state->dpy, state->window, state->gcs[BLANK], + tx, ty, width, height); + } + else + { +#ifdef FUZZY_BORDER + GC gc1 = state->gcs[cell->state]; + GC gc2 = ((cell->state + 2) < state->ticks + ? state->gcs[cell->state + 2] + : 0); + XCopyPlane (state->dpy, cell->p_char->pixmap, state->window, + (gc2 ? gc2 : gc1), + 0, 0, width, height, tx, ty, 1L); + if (gc2) + { + XSetClipMask (state->dpy, gc1, cell->p_char->pixmap2); + XSetClipOrigin (state->dpy, gc1, tx, ty); + XFillRectangle (state->dpy, state->window, gc1, + tx, ty, width, height); + XSetClipMask (state->dpy, gc1, None); + } +#else /* !FUZZY_BORDER */ + + XCopyPlane (state->dpy, + cell->p_char->pixmap, state->window, + state->gcs[cell->state], + 0, 0, width, height, tx, ty, 1L); + +#endif /* !FUZZY_BORDER */ + } + + cell->changed = False; + } +} + + +static void +run_phosphor (p_state *state) +{ + update_display (state, True); + decay (state); + drain_input (state); +} + + +/* Subprocess. + */ + +static void +subproc_cb (XtPointer closure, int *source, XtInputId *id) +{ + p_state *state = (p_state *) closure; + state->input_available_p = True; +} + + +static void +launch_text_generator (p_state *state) +{ + char *oprogram = get_string_resource ("program", "Program"); + char *program = (char *) malloc (strlen (oprogram) + 10); + + strcpy (program, "( "); + strcat (program, oprogram); + strcat (program, " ) 2>&1"); + + if ((state->pipe = popen (program, "r"))) + { + state->pipe_id = + XtAppAddInput (app, fileno (state->pipe), + (XtPointer) (XtInputReadMask | XtInputExceptMask), + subproc_cb, (XtPointer) state); + } + else + { + perror (program); + } +} + + +static void +relaunch_generator_timer (XtPointer closure, XtIntervalId *id) +{ + p_state *state = (p_state *) closure; + launch_text_generator (state); +} + + +static void +drain_input (p_state *state) +{ + if (state->input_available_p) + { + char s[2]; + int n = read (fileno (state->pipe), (void *) s, 1); + if (n == 1) + { + print_char (state, s[0]); + } + else + { + XtRemoveInput (state->pipe_id); + state->pipe_id = 0; + pclose (state->pipe); + state->pipe = 0; + + if (state->cursor_x != 0) /* break line if unbroken */ + print_char (state, '\n'); /* blank line */ + print_char (state, '\n'); + + /* Set up a timer to re-launch the subproc in a bit. */ + XtAppAddTimeOut (app, state->subproc_relaunch_delay, + relaunch_generator_timer, + (XtPointer) state); + } + + state->input_available_p = False; + } +} + + + +char *progclass = "Phosphor"; + +char *defaults [] = { + ".background: Black", + ".foreground: Green", + "*fadeForeground: DarkGreen", + "*flareForeground: White", + "*font: fixed", + "*scale: 6", + "*ticks: 20", + "*delay: 50000", + "*cursor: 333", + "*program: " ZIPPY_PROGRAM, + "*relaunch: 5", + 0 +}; + +XrmOptionDescRec options [] = { + { "-font", ".font", XrmoptionSepArg, 0 }, + { "-scale", ".scale", XrmoptionSepArg, 0 }, + { "-ticks", ".ticks", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-program", ".program", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +void +screenhack (Display *dpy, Window window) +{ + int delay = get_integer_resource ("delay", "Integer"); + p_state *state = init_phosphor (dpy, window); + + clear (state); + + while (1) + { + run_phosphor (state); + XSync (dpy, False); + screenhack_handle_events (dpy); + + if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput|XtIMSignal)) + XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput|XtIMSignal); + + if (delay) usleep (delay); + } +} diff --git a/hacks/screenhack.c b/hacks/screenhack.c index 7c147346..eb9d7185 100644 --- a/hacks/screenhack.c +++ b/hacks/screenhack.c @@ -59,6 +59,7 @@ char *progname; XrmDatabase db; +XtAppContext app; Bool mono_p; static XrmOptionDescRec default_options [] = { @@ -240,7 +241,6 @@ screenhack_handle_events (Display *dpy) int main (int argc, char **argv) { - XtAppContext app; Widget toplevel; Display *dpy; Window window; diff --git a/hacks/slip.c b/hacks/slip.c index 91694e93..395fea1c 100644 --- a/hacks/slip.c +++ b/hacks/slip.c @@ -196,7 +196,7 @@ draw_slip(ModeInfo * mi) double x, y, dx = 0, dy = 0, t, s1, s2; if (0 == s->nblits_remaining--) { - static lut[] = + static int lut[] = {0, 0, 0, 1, 1, 1, 2}; prepare_screen(mi, s); diff --git a/hacks/sphere.c b/hacks/sphere.c index cffe9842..e0a81e3a 100644 --- a/hacks/sphere.c +++ b/hacks/sphere.c @@ -106,7 +106,7 @@ draw_sphere(ModeInfo * mi) Display *display = MI_DISPLAY(mi); GC gc = MI_GC(mi); spherestruct *sp = &spheres[MI_SCREEN(mi)]; - register minx = 0, maxx = 0, miny = 0, maxy = 0, npts = 0; + int minx = 0, maxx = 0, miny = 0, maxy = 0, npts = 0; if ((sp->dirx && ABS(sp->x) >= sp->radius) || (sp->diry && ABS(sp->y) >= sp->radius)) { diff --git a/hacks/squiral.c b/hacks/squiral.c index 57feea0f..fb7868fe 100644 --- a/hacks/squiral.c +++ b/hacks/squiral.c @@ -219,4 +219,5 @@ XrmOptionDescRec options[] = { {"-ncolors", ".ncolors", XrmoptionSepArg, 0}, {"-cycle", ".cycle", XrmoptionNoArg, "True"}, {"-no-cycle", ".cycle", XrmoptionNoArg, "False"}, + { 0, 0, 0, 0 } }; diff --git a/hacks/t3d.c b/hacks/t3d.c index 58ec47f2..b569c751 100644 --- a/hacks/t3d.c +++ b/hacks/t3d.c @@ -209,7 +209,7 @@ initColor (double r, double g, double b) { int n,n1; unsigned long pixels[12]; - long dummy; + unsigned long dummy; cmap = xgwa.colormap; @@ -293,7 +293,7 @@ initialize (void) if (s && *s) { double hh, ss, vv; - if (3 == sscanf (s, "%lf %lf %lf", &hh, &ss, &vv, &dummy)) { + if (3 == sscanf (s, "%lf %lf %lf %c", &hh, &ss, &vv, &dummy)) { hue = hh, sat = ss, val = vv; hsv2rgb(hue,sat,val,&r,&g,&b); } @@ -816,7 +816,8 @@ screenhack (Display *d, Window w) { Window junk_win,in_win; - int px,py,junk,kb/*,wai*/; + int px,py,junk/*,wai*/; + unsigned int kb; /* int act,act1,tc;*/ double vnorm; /* double var=0.0; */ diff --git a/hacks/xflame.c b/hacks/xflame.c index 360ef379..dcac9600 100755 --- a/hacks/xflame.c +++ b/hacks/xflame.c @@ -125,9 +125,14 @@ MakeImage(void) { XGCValues gcv; +#ifdef HAVE_XSHM_EXTENSION shared = True; xim = create_xshm_image (display, visual, depth, ZPixmap, NULL, &shminfo, width, height); +#else /* !HAVE_XSHM_EXTENSION */ + xim = 0; +#endif /* !HAVE_XSHM_EXTENSION */ + if (!xim) { shared = False; @@ -180,10 +185,12 @@ InitColors(void) static void DisplayImage(void) { +#ifdef HAVE_XSHM_EXTENSION if (shared) XShmPutImage(display, window, gc, xim, 0,(top - 1) << 1, 0, (top - 1) << 1, width, height - ((top - 1) << 1), False); else +#endif /* HAVE_XSHM_EXTENSION */ XPutImage(display, window, gc, xim, 0, (top - 1) << 1, 0, (top - 1) << 1, width, height - ((top - 1) << 1)); } @@ -521,6 +528,7 @@ loadBitmap(int *w, int *h) *bitmap_name && !!strcmp(bitmap_name, "none")) { +#ifdef HAVE_XPM XpmInfo xpm_info = { 0, }; XpmImage xpm_image = { 0, }; @@ -582,6 +590,7 @@ loadBitmap(int *w, int *h) return result; } else /* failed to read XPM -- fall through and try XBM */ +#endif /* HAVE_XPM */ { #ifdef HAVE_XMU XImage *ximage = 0; diff --git a/hacks/xlyap.c b/hacks/xlyap.c index b180fc43..3742df68 100644 --- a/hacks/xlyap.c +++ b/hacks/xlyap.c @@ -599,7 +599,7 @@ main_event(void) static int complyap(void) { - register i, bindex; + int i, bindex; double total, prod, x, dx, r; if (!run) diff --git a/hacks/xmatrix.c b/hacks/xmatrix.c new file mode 100644 index 00000000..38d9af14 --- /dev/null +++ b/hacks/xmatrix.c @@ -0,0 +1,438 @@ +/* xscreensaver, Copyright (c) 1999 Jamie Zawinski + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * Matrix -- simulate the text scrolls from the movie "The Matrix". + * + * The movie people distribute their own Windows/Mac screensaver that does + * a similar thing, so I wrote one for Unix. However, that version (the + * Windows/Mac version at http://www.whatisthematrix.com/) doesn't match my + * memory of what the screens in the movie looked like, so my `xmatrix' + * does things differently. + */ + +#include "screenhack.h" +#include +#include + +#ifdef HAVE_XPM +# include +# include "images/matrix.xpm" +#endif + +#include "images/matrix.xbm" + +#define CHAR_HEIGHT 31 + +typedef struct { + int glyph; + Bool changed; + int glow; +} m_cell; + +typedef struct { + int remaining; + int throttle; + int y; +} m_feeder; + +typedef struct { + Display *dpy; + Window window; + XWindowAttributes xgwa; + GC draw_gc, erase_gc; + int grid_width, grid_height; + int char_width, char_height; + m_cell *cells; + m_feeder *feeders; + Bool insert_top_p, insert_bottom_p; + int density; + + Pixmap images; + int image_width, image_height; + int nglyphs; + +} m_state; + + +static void +load_images (m_state *state) +{ +#ifdef HAVE_XPM + if (!get_boolean_resource ("mono", "Boolean") && + state->xgwa.depth > 1) + { + XpmAttributes xpmattrs; + int result; + xpmattrs.valuemask = 0; + +# ifdef XpmCloseness + xpmattrs.valuemask |= XpmCloseness; + xpmattrs.closeness = 40000; +# endif +# ifdef XpmVisual + xpmattrs.valuemask |= XpmVisual; + xpmattrs.visual = state->xgwa.visual; +# endif +# ifdef XpmDepth + xpmattrs.valuemask |= XpmDepth; + xpmattrs.depth = state->xgwa.depth; +# endif +# ifdef XpmColormap + xpmattrs.valuemask |= XpmColormap; + xpmattrs.colormap = state->xgwa.colormap; +# endif + + result = XpmCreatePixmapFromData (state->dpy, state->window, matrix, + &state->images, 0 /* mask */, + &xpmattrs); + if (!state->images || (result != XpmSuccess && result != XpmColorError)) + state->images = 0; + + state->image_width = xpmattrs.width; + state->image_height = xpmattrs.height; + state->nglyphs = state->image_height / CHAR_HEIGHT; + } + else +#endif /* !HAVE_XPM */ + { + unsigned long fg, bg; + state->image_width = matrix_width; + state->image_height = matrix_height; + state->nglyphs = state->image_height / CHAR_HEIGHT; + + fg = get_pixel_resource("foreground", "Foreground", + state->dpy, state->xgwa.colormap); + bg = get_pixel_resource("background", "Background", + state->dpy, state->xgwa.colormap); + state->images = + XCreatePixmapFromBitmapData (state->dpy, state->window, + (char *) matrix_bits, + state->image_width, state->image_height, + bg, fg, state->xgwa.depth); + } +} + + +static m_state * +init_matrix (Display *dpy, Window window) +{ + XGCValues gcv; + char *insert; + m_state *state = (m_state *) calloc (sizeof(*state), 1); + state->dpy = dpy; + state->window = window; + + XGetWindowAttributes (dpy, window, &state->xgwa); + load_images (state); + + gcv.foreground = get_pixel_resource("foreground", "Foreground", + state->dpy, state->xgwa.colormap); + gcv.background = get_pixel_resource("background", "Background", + state->dpy, state->xgwa.colormap); + state->draw_gc = XCreateGC (state->dpy, state->window, + GCForeground|GCBackground, &gcv); + gcv.foreground = gcv.background; + state->erase_gc = XCreateGC (state->dpy, state->window, + GCForeground|GCBackground, &gcv); + + state->char_width = state->image_width / 2; + state->char_height = CHAR_HEIGHT; + + state->grid_width = state->xgwa.width / state->char_width; + state->grid_height = state->xgwa.height / state->char_height; + state->grid_width++; + state->grid_height++; + + state->cells = (m_cell *) + calloc (sizeof(m_cell), state->grid_width * state->grid_height); + state->feeders = (m_feeder *) calloc (sizeof(m_feeder), state->grid_width); + + state->density = get_integer_resource ("density", "Integer"); + + insert = get_string_resource("insert", "Insert"); + if (insert && !strcmp(insert, "top")) + { + state->insert_top_p = True; + state->insert_bottom_p = False; + } + else if (insert && !strcmp(insert, "bottom")) + { + state->insert_top_p = False; + state->insert_bottom_p = True; + } + else if (insert && !strcmp(insert, "both")) + { + state->insert_top_p = True; + state->insert_bottom_p = True; + } + else + { + if (insert && *insert) + fprintf (stderr, + "%s: `insert' must be `top', `bottom', or `both', not \%s'\n", + progname, insert); + state->insert_top_p = False; + state->insert_bottom_p = True; + } + + if (insert) + free (insert); + + return state; +} + + +static void +insert_glyph (m_state *state, int glyph, int x, int y) +{ + Bool bottom_feeder_p = (y >= 0); + m_cell *from, *to; + + if (y >= state->grid_height) + return; + + if (bottom_feeder_p) + { + to = &state->cells[state->grid_width * y + x]; + } + else + { + for (y = state->grid_height-1; y > 0; y--) + { + from = &state->cells[state->grid_width * (y-1) + x]; + to = &state->cells[state->grid_width * y + x]; + *to = *from; + to->changed = True; + } + to = &state->cells[x]; + } + + to->glyph = glyph; + to->changed = True; + + if (!to->glyph) + ; + else if (bottom_feeder_p) + to->glow = 1 + (random() % 2); + else + to->glow = 0; +} + + +static void +feed_matrix (m_state *state) +{ + int x; + + /* Update according to current feeders. */ + for (x = 0; x < state->grid_width; x++) + { + m_feeder *f = &state->feeders[x]; + + if (f->throttle) /* this is a delay tick, synced to frame. */ + { + f->throttle--; + } + else if (f->remaining > 0) /* how many items are in the pipe */ + { + int g = (random() % state->nglyphs) + 1; + insert_glyph (state, g, x, f->y); + f->remaining--; + if (f->y >= 0) /* bottom_feeder_p */ + f->y++; + } + else /* if pipe is empty, insert spaces */ + { + insert_glyph (state, 0, x, f->y); + if (f->y >= 0) /* bottom_feeder_p */ + f->y++; + } + + if ((random() % 10) == 0) /* randomly change throttle speed */ + { + f->throttle = ((random() % 5) + (random() % 5)); + } + } +} + +static int +densitizer (m_state *state) +{ + /* Horrid kludge that converts percentages (density of screen coverage) + to the parameter that actually controls this. I got this mapping + empirically, on a 1024x768 screen. Sue me. */ + if (state->density < 10) return 85; + else if (state->density < 15) return 60; + else if (state->density < 20) return 45; + else if (state->density < 25) return 25; + else if (state->density < 30) return 20; + else if (state->density < 35) return 15; + else if (state->density < 45) return 10; + else if (state->density < 50) return 8; + else if (state->density < 55) return 7; + else if (state->density < 65) return 5; + else if (state->density < 80) return 3; + else if (state->density < 90) return 2; + else return 1; +} + + +static void +hack_matrix (m_state *state) +{ + int x; + + /* Glow some characters. */ + if (!state->insert_bottom_p) + { + int i = random() % (state->grid_width / 2); + while (--i > 0) + { + int x = random() % state->grid_width; + int y = random() % state->grid_height; + m_cell *cell = &state->cells[state->grid_width * y + x]; + if (cell->glyph && cell->glow == 0) + { + cell->glow = random() % 10; + cell->changed = True; + } + } + } + + /* Change some of the feeders. */ + for (x = 0; x < state->grid_width; x++) + { + m_feeder *f = &state->feeders[x]; + Bool bottom_feeder_p; + + if (f->remaining > 0) /* never change if pipe isn't empty */ + continue; + + if ((random() % densitizer(state)) != 0) /* then change N% of the time */ + continue; + + f->remaining = 3 + (random() % state->grid_height); + f->throttle = ((random() % 5) + (random() % 5)); + + if ((random() % 4) != 0) + f->remaining = 0; + + if (state->insert_top_p && state->insert_bottom_p) + bottom_feeder_p = (random() & 1); + else + bottom_feeder_p = state->insert_bottom_p; + + if (bottom_feeder_p) + f->y = random() % (state->grid_height / 2); + else + f->y = -1; + } +} + + +static void +draw_matrix (m_state *state) +{ + int x, y; + int count = 0; + + feed_matrix (state); + hack_matrix (state); + + for (y = 0; y < state->grid_height; y++) + for (x = 0; x < state->grid_width; x++) + { + m_cell *cell = &state->cells[state->grid_width * y + x]; + + if (cell->glyph) + count++; + + if (!cell->changed) + continue; + + if (cell->glyph == 0) + XFillRectangle (state->dpy, state->window, state->erase_gc, + x * state->char_width, + y * state->char_height, + state->char_width, + state->char_height); + else + XCopyArea (state->dpy, state->images, state->window, state->draw_gc, + (cell->glow ? state->char_width : 0), + (cell->glyph - 1) * state->char_height, + state->char_width, state->char_height, + x * state->char_width, + y * state->char_height); + + cell->changed = False; + + if (cell->glow > 0) + { + cell->glow--; + cell->changed = True; + } + } + +#if 0 + { + static int i = 0; + static int ndens = 0; + static int tdens = 0; + i++; + if (i > 50) + { + int dens = (100.0 * + (((double)count) / + ((double) (state->grid_width * state->grid_height)))); + tdens += dens; + ndens++; + printf ("density: %d%% (%d%%)\n", dens, (tdens / ndens)); + i = 0; + } + } +#endif + +} + + +char *progclass = "XMatrix"; + +char *defaults [] = { + ".background: black", + ".foreground: green", + "*delay: 10000", + "*insert: both", + "*density: 85", + 0 +}; + +XrmOptionDescRec options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-top", ".insert", XrmoptionNoArg, "top" }, + { "-bottom", ".insert", XrmoptionNoArg, "bottom" }, + { "-both", ".insert", XrmoptionNoArg, "both" }, + { "-density", ".density", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +void +screenhack (Display *dpy, Window window) +{ + m_state *state = init_matrix (dpy, window); + int delay = get_integer_resource ("delay", "Integer"); + while (1) + { + draw_matrix (state); + XSync (dpy, False); + screenhack_handle_events (dpy); + if (delay) usleep (delay); + } +} diff --git a/setup.com b/setup.com index a3a9a840..ec96853e 100644 --- a/setup.com +++ b/setup.com @@ -58,6 +58,7 @@ $ noseguy :== $'mydir'noseguy $ pedal :== $'mydir'pedal $ penetrate :== $'mydir'penetrate $ penrose :== $'mydir'penrose +$ phosphor :== $'mydir'phosphor $ pyro :== $'mydir'pyro $ qix :== $'mydir'qix $ rd-bomb :== $'mydir'rd-bomb @@ -84,6 +85,7 @@ $ worm :== $'mydir'worm $ xflame :== $'mydir'xflame $ xjack :== $'mydir'xjack $ xlyap :== $'mydir'xlyap +$ xmatrix :== $'mydir'xmatrix $ xroger :== $'mydir'xroger $ set def [-.DRIVER] $ mydir = mydisk+f$directory() diff --git a/utils/colors.c b/utils/colors.c index b568a24d..698bc940 100644 --- a/utils/colors.c +++ b/utils/colors.c @@ -560,7 +560,8 @@ make_uniform_colormap (Display *dpy, Visual *visual, Colormap cmap, 0, S, V, 359, S, V, colors, &ncolors, - False, True, wanted_writable); + False, True, + (writable_pP && *writable_pP)); /* If we tried for writable cells and got none, try for non-writable. */ if (allocate_p && *ncolorsP == 0 && writable_pP && *writable_pP) diff --git a/utils/version.h b/utils/version.h index 6e82718d..ddd41578 100644 --- a/utils/version.h +++ b/utils/version.h @@ -1,2 +1,2 @@ static const char screensaver_id[] = - "@(#)xscreensaver 3.09 (11-Apr-99), by Jamie Zawinski (jwz@jwz.org)"; + "@(#)xscreensaver 3.10 (27-Apr-99), by Jamie Zawinski (jwz@jwz.org)"; diff --git a/xscreensaver.lsm b/xscreensaver.lsm index dfe67b66..12e7a5b0 100644 --- a/xscreensaver.lsm +++ b/xscreensaver.lsm @@ -1,7 +1,7 @@ Begin3 Title: xscreensaver -Version: 3.09 -Entered-date: 11APR99 +Version: 3.10 +Entered-date: 27APR99 Description: A modular screen saver and locker for the X Window System. Highly customizable: allows the use of any program that can draw on the root window as a display mode. @@ -10,16 +10,16 @@ Keywords: screen saver, screen lock, lock, xlock, X11 Author: jwz@jwz.org (Jamie Zawinski) Maintained-by: jwz@jwz.org (Jamie Zawinski) Primary-site: http://www.jwz.org/xscreensaver/ - 1047K xscreensaver-3.09.tar.gz - 29K xscreensaver.README + 1081K xscreensaver-3.10.tar.gz + 30K xscreensaver.README 1K xscreensaver.lsm Alternate-site: sunsite.unc.edu /pub/Linux/X11/screensavers/ - 1047K xscreensaver-3.09.tar.gz - 29K xscreensaver.README + 1081K xscreensaver-3.10.tar.gz + 30K xscreensaver.README 1K xscreensaver.lsm Alternate-site: ftp.x.org /contrib/applications/ - 1047K xscreensaver-3.09.tar.gz - 29K xscreensaver.README + 1081K xscreensaver-3.10.tar.gz + 30K xscreensaver.README 1K xscreensaver.lsm Platforms: Linux, Irix, SunOS, Solaris, HPUX, AIX, FreeBSD, NetBSD, BSDI, SCO, OSF1, Ultrix, VMS. diff --git a/xscreensaver.spec b/xscreensaver.spec index bab9a8fc..c7b265c2 100644 --- a/xscreensaver.spec +++ b/xscreensaver.spec @@ -1,7 +1,7 @@ Name: xscreensaver Summary: X screen saver and locker Vendor: Jamie Zawinski -Version: 3.09 +Version: 3.10 Release: 1 URL: http://www.jwz.org/xscreensaver/ Source: xscreensaver-%{version}.tar.gz -- 2.30.2