configure.ac: Add checks for Flex/Yacc/Bison and other furry animals, for the new...
authorBastien Nocera <hadess@hadess.net>
Sat, 23 Feb 2008 01:51:37 +0000 (01:51 +0000)
committerBastien Nocera <hadess@hadess.net>
Sat, 23 Feb 2008 01:51:37 +0000 (01:51 +0000)
Original commit message from CVS:
2008-02-23  Bastien Nocera  <hadess@hadess.net>

* configure.ac: Add checks for Flex/Yacc/Bison and other
furry animals, for the new goom 2k4 based plugin

* gst/goom/*: Update to use goom 2k4, uses liboil to detect
CPU optimisations (not working yet), move the old plugin to...

* gst/goom2k1/*: ... here, in case somebody is sick enough

Fixes #515073

85 files changed:
ChangeLog
common
configure.ac
gst/goom/Makefile.am
gst/goom/README
gst/goom/config_param.c [new file with mode: 0644]
gst/goom/convolve_fx.c [new file with mode: 0644]
gst/goom/default_scripts.h [new file with mode: 0644]
gst/goom/drawmethods.c [new file with mode: 0644]
gst/goom/drawmethods.h [new file with mode: 0644]
gst/goom/filters.c
gst/goom/filters.h [deleted file]
gst/goom/filters_mmx.s
gst/goom/flying_stars_fx.c [new file with mode: 0644]
gst/goom/gfontlib.c [new file with mode: 0644]
gst/goom/gfontlib.h [new file with mode: 0644]
gst/goom/gfontrle.c [new file with mode: 0644]
gst/goom/gfontrle.h [new file with mode: 0644]
gst/goom/goom.h [new file with mode: 0644]
gst/goom/goom_config.h [new file with mode: 0644]
gst/goom/goom_config_param.h [new file with mode: 0644]
gst/goom/goom_core.c
gst/goom/goom_core.h [deleted file]
gst/goom/goom_filters.h [new file with mode: 0644]
gst/goom/goom_fx.h [new file with mode: 0644]
gst/goom/goom_graphic.h [new file with mode: 0644]
gst/goom/goom_plugin_info.h [new file with mode: 0644]
gst/goom/goom_tools.c [new file with mode: 0644]
gst/goom/goom_tools.h
gst/goom/goom_typedefs.h [new file with mode: 0644]
gst/goom/goom_visual_fx.h [new file with mode: 0644]
gst/goom/goomsl.c [new file with mode: 0644]
gst/goom/goomsl.h [new file with mode: 0644]
gst/goom/goomsl_hash.c [new file with mode: 0644]
gst/goom/goomsl_hash.h [new file with mode: 0644]
gst/goom/goomsl_heap.c [new file with mode: 0644]
gst/goom/goomsl_heap.h [new file with mode: 0644]
gst/goom/goomsl_lex.l [new file with mode: 0644]
gst/goom/goomsl_private.h [new file with mode: 0644]
gst/goom/goomsl_yacc.y [new file with mode: 0644]
gst/goom/graphic.c
gst/goom/graphic.h [deleted file]
gst/goom/gstgoom.c
gst/goom/gstgoom.h
gst/goom/ifs.c [new file with mode: 0644]
gst/goom/ifs.h [new file with mode: 0644]
gst/goom/lines.c
gst/goom/lines.h
gst/goom/mathtools.c [new file with mode: 0644]
gst/goom/mathtools.h [new file with mode: 0644]
gst/goom/mmx.c [new file with mode: 0644]
gst/goom/mmx.h [new file with mode: 0644]
gst/goom/motif_goom1.h [new file with mode: 0644]
gst/goom/motif_goom2.h [new file with mode: 0644]
gst/goom/plugin_info.c [new file with mode: 0644]
gst/goom/ppc_drawings.h [new file with mode: 0644]
gst/goom/ppc_drawings.s [new file with mode: 0644]
gst/goom/ppc_zoom_ultimate.h [new file with mode: 0644]
gst/goom/ppc_zoom_ultimate.s [new file with mode: 0644]
gst/goom/sound_tester.c [new file with mode: 0644]
gst/goom/sound_tester.h [new file with mode: 0644]
gst/goom/surf3d.c [new file with mode: 0644]
gst/goom/surf3d.h [new file with mode: 0644]
gst/goom/surf3d.s [new file with mode: 0644]
gst/goom/tentacle3d.c [new file with mode: 0644]
gst/goom/tentacle3d.h [new file with mode: 0644]
gst/goom/v3d.c [new file with mode: 0644]
gst/goom/v3d.h [new file with mode: 0644]
gst/goom/xmmx.c [new file with mode: 0644]
gst/goom/xmmx.h [new file with mode: 0644]
gst/goom2k1/Makefile.am [new file with mode: 0644]
gst/goom2k1/README [new file with mode: 0644]
gst/goom2k1/filters.c [new file with mode: 0644]
gst/goom2k1/filters.h [new file with mode: 0644]
gst/goom2k1/filters_mmx.s [new file with mode: 0644]
gst/goom2k1/goom.vcproj [new file with mode: 0644]
gst/goom2k1/goom_core.c [new file with mode: 0644]
gst/goom2k1/goom_core.h [new file with mode: 0644]
gst/goom2k1/goom_tools.h [new file with mode: 0644]
gst/goom2k1/graphic.c [new file with mode: 0644]
gst/goom2k1/graphic.h [new file with mode: 0644]
gst/goom2k1/gstgoom.c [new file with mode: 0644]
gst/goom2k1/gstgoom.h [new file with mode: 0644]
gst/goom2k1/lines.c [new file with mode: 0644]
gst/goom2k1/lines.h [new file with mode: 0644]

index b071e842ffc1092fe95e1ca83b68d12f4218ce39..c1900626ff499f8057daf87f2f5ac084b8cea054 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-02-23  Bastien Nocera  <hadess@hadess.net>
+
+       * configure.ac: Add checks for Flex/Yacc/Bison and other
+       furry animals, for the new goom 2k4 based plugin
+
+       * gst/goom/*: Update to use goom 2k4, uses liboil to detect
+       CPU optimisations (not working yet), move the old plugin to...
+
+       * gst/goom2k1/*: ... here, in case somebody is sick enough
+
+       Fixes #515073
+
 2008-02-22  Wim Taymans  <wim.taymans@collabora.co.uk>
 
        * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_setup_streams):
diff --git a/common b/common
index 135628f16d422584d3454fb9c9805e7be25760a1..bd6ec57040fe3fa93e21ca440dfe494e3ee18555 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 135628f16d422584d3454fb9c9805e7be25760a1
+Subproject commit bd6ec57040fe3fa93e21ca440dfe494e3ee18555
index 943d81ab9788511c272b74ece75f18d41bf01902..54f33963bf7beb82448d86e4b825fe212ffad2e8 100644 (file)
@@ -94,6 +94,7 @@ GST_PLUGINS_ALL="\
                icydemux \
                flx \
                goom \
+               goom2k1 \
                law \
                level \
                matroska \
@@ -329,6 +330,11 @@ AG_GST_SET_LEVEL_DEFAULT($GST_CVS)
 dnl used in examples
 AG_GST_DEFAULT_ELEMENTS
 
+dnl Check for Yacc and Lex for the goom plugin
+AG_GST_BISON_CHECK
+AG_GST_FLEX_CHECK
+AM_PROG_AS
+
 dnl *** sys plug-ins ***
 
 echo
@@ -1019,6 +1025,7 @@ gst/equalizer/Makefile
 gst/id3demux/Makefile
 gst/icydemux/Makefile
 gst/goom/Makefile
+gst/goom2k1/Makefile
 gst/law/Makefile
 gst/level/Makefile
 gst/matroska/Makefile
index 4f4abb76a14679b6c3dc1b8daa7e7514e211d0c5..41e9cb32725b2dc689d4daf612b5d2dd62fbad3b 100644 (file)
@@ -1,14 +1,79 @@
 plugin_LTLIBRARIES = libgstgoom.la
 
-GOOM_FILTER_FILES = filters.c
-GOOM_FILTER_CFLAGS = -UMMX -UUSE_ASM
+PPC_FILES=ppc_zoom_ultimate.s ppc_drawings.s ppc_drawings.h ppc_zoom_ultimate.h
+MMX_FILES=mmx.c xmmx.c mmx.h xmmx.h
 
-noinst_HEADERS = gstgoom.h filters.h goom_core.h goom_tools.h graphic.h lines.h 
+if HAVE_CPU_PPC
+ARCH_FILES = $(PPC_FILES)
+endif
+if HAVE_CPU_PPC64
+ARCH_FILES = $(PPC_FILES)
+endif
+if HAVE_CPU_I386
+ARCH_FILES = $(MMX_FILES)
+endif
 
-libgstgoom_la_SOURCES = gstgoom.c goom_core.c $(GOOM_FILTER_FILES) graphic.c lines.c
+libgstgoom_la_SOURCES =                                                \
+       gstgoom.c gstgoom.h                                     \
+       drawmethods.c drawmethods.h                             \
+       sound_tester.c sound_tester.h                           \
+       mathtools.c mathtools.h                                 \
+       goomsl_heap.c goomsl_heap.h                             \
+       goomsl_hash.c goomsl_hash.h                             \
+       goomsl.c goomsl_private.h                               \
+       lines.c lines.h ifs.c ifs.h surf3d.c surf3d.h           \
+       tentacle3d.c tentacle3d.h v3d.c v3d.h                   \
+       gfontrle.c gfontrle.h gfontlib.c gfontlib.h             \
+       convolve_fx.c flying_stars_fx.c                         \
+       goom_fx.h goom_visual_fx.h                              \
+       motif_goom1.h motif_goom2.h                             \
+       plugin_info.c goom_plugin_info.h                        \
+       default_scripts.h goom_tools.c                          \
+       config_param.c filters.c goom_core.c graphic.c          \
+       goom.h goom_typedefs.h goom_graphic.h                   \
+       goom_config_param.h goom_visual_fx.h goom_filters.h     \
+       goom_tools.h goom_tools.h goom_config.h                 \
+       $(ARCH_FILES)
 
-libgstgoom_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GOOM_FILTER_CFLAGS)
-libgstgoom_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM)
+ERROR_CFLAGS=
+libgstgoom_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GOOM_FILTER_CFLAGS) $(LIBOIL_CFLAGS)
+libgstgoom_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM) $(LIBOIL_LIBS) libgstgoomconfigparse.la
 libgstgoom_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
-EXTRA_DIST = filters.c
+EXTRA_DIST = filters.c $(PPC_FILES) $(MMX_FILES)
+
+goomsl_yacc.c goomsl_yacc.h: goomsl_yacc.y
+       $(BISON_PATH) -d $(srcdir)/goomsl_yacc.y -o goomsl_yacc.c && \
+       mv goomsl_yacc.c goomsl_yacc_tmp.c && \
+       echo '#ifdef HAVE_CONFIG_H' > goomsl_yacc_tmp2.c && \
+       echo '#include <config.h>' >> goomsl_yacc_tmp2.c && \
+       echo '#endif' >> goomsl_yacc_tmp2.c && \
+       cat goomsl_yacc_tmp.c >> goomsl_yacc_tmp2.c && \
+       rm goomsl_yacc_tmp.c && \
+       mv goomsl_yacc_tmp2.c goomsl_yacc.c
+
+goomsl_lex.c: goomsl_lex.l goomsl_yacc.h
+       $(FLEX_PATH) -ogoomsl_lex.c $(srcdir)/goomsl_lex.l && \
+       mv goomsl_lex.c goomsl_lex_tmp.c && \
+       echo '#ifdef HAVE_CONFIG_H' > goomsl_lex_tmp2.c && \
+       echo '#include <config.h>' >> goomsl_lex_tmp2.c && \
+       echo '#endif' >> goomsl_lex_tmp2.c && \
+       cat goomsl_lex_tmp.c >> goomsl_lex_tmp2.c && \
+       rm goomsl_lex_tmp.c && \
+       mv goomsl_lex_tmp2.c goomsl_lex.c
+
+# libgstgoomconfigparse.la is library linked into the goom plugin
+noinst_LTLIBRARIES = libgstgoomconfigparse.la
+
+# uncomment these lines to dist the generated sources
+#BUILT_SOURCES = goomsl_yacc.h goomsl_yacc.c goomsl_lex.c
+#libgstgoomconfigparse_la_SOURCES = goomsl_lex.c goomsl_yacc.c goomsl_yacc.h
+
+# uncomment these lines to _NOT_ dist the generated sources
+nodist_libgstgoomconfigparse_la_SOURCES = goomsl_lex.c goomsl_yacc.c
+CLEANFILES=goomsl_yacc.c goomsl_lex.c goomsl_yacc.h
+
+EXTRA_DIST += goomsl_yacc.y goomsl_lex.l
+
+.NOTPARALLEL:
+
index f12cf1b55b2151a96f8ff091c729ffe37cb837e5..1b3736a1c496f67141a9b9bd684632faa0ee0ad3 100644 (file)
@@ -3,3 +3,6 @@ the Goom homepage found at:
 http://ios.free.fr/?page=projet&quoi=1 
 
 Like the original library so is the Goom plugin available under the LGPL license
+
+This is based on goom2k4 with changes to plugin_info.c and mmx.h to use liboil for CPU
+detection and GStreamer-specific ifdef's for architecture detection.
diff --git a/gst/goom/config_param.c b/gst/goom/config_param.c
new file mode 100644 (file)
index 0000000..4c4cebd
--- /dev/null
@@ -0,0 +1,141 @@
+/*---------------------------------------------------------------------------*/
+/*
+** config_param.c
+** Goom Project
+**
+** Created by Jean-Christophe Hoelt on Sat Jul 19 2003
+** Copyright (c) 2003 iOS. All rights reserved.
+*/
+/*---------------------------------------------------------------------------*/
+
+#include "goom_config_param.h"
+#include <string.h>
+
+/* TODO: Ajouter goom_ devant ces fonctions */
+
+static void
+empty_fct (PluginParam * dummy)
+{
+}
+
+PluginParam
+goom_secure_param ()
+{
+  PluginParam p;
+
+  p.changed = empty_fct;
+  p.change_listener = empty_fct;
+  p.user_data = 0;
+  p.name = p.desc = 0;
+  p.rw = 1;
+  return p;
+}
+
+PluginParam
+goom_secure_f_param (char *name)
+{
+  PluginParam p = secure_param ();
+
+  p.name = name;
+  p.type = PARAM_FLOATVAL;
+  FVAL (p) = 0.5f;
+  FMIN (p) = 0.0f;
+  FMAX (p) = 1.0f;
+  FSTEP (p) = 0.01f;
+  return p;
+}
+
+PluginParam
+goom_secure_f_feedback (char *name)
+{
+  PluginParam p = secure_f_param (name);
+
+  p.rw = 0;
+  return p;
+}
+
+PluginParam
+goom_secure_s_param (char *name)
+{
+  PluginParam p = secure_param ();
+
+  p.name = name;
+  p.type = PARAM_STRVAL;
+  SVAL (p) = 0;
+  return p;
+}
+
+PluginParam
+goom_secure_b_param (char *name, int value)
+{
+  PluginParam p = secure_param ();
+
+  p.name = name;
+  p.type = PARAM_BOOLVAL;
+  BVAL (p) = value;
+  return p;
+}
+
+PluginParam
+goom_secure_i_param (char *name)
+{
+  PluginParam p = secure_param ();
+
+  p.name = name;
+  p.type = PARAM_INTVAL;
+  IVAL (p) = 50;
+  IMIN (p) = 0;
+  IMAX (p) = 100;
+  ISTEP (p) = 1;
+  return p;
+}
+
+PluginParam
+goom_secure_i_feedback (char *name)
+{
+  PluginParam p = secure_i_param (name);
+
+  p.rw = 0;
+  return p;
+}
+
+PluginParameters
+goom_plugin_parameters (const char *name, int nb)
+{
+  PluginParameters p;
+
+  p.name = (char *) name;
+  p.desc = "";
+  p.nbParams = nb;
+  p.params = (PluginParam **) malloc (nb * sizeof (PluginParam *));
+  return p;
+}
+
+/*---------------------------------------------------------------------------*/
+
+void
+goom_set_str_param_value (PluginParam * p, const char *str)
+{
+  int len = strlen (str);
+
+  if (SVAL (*p))
+    SVAL (*p) = (char *) realloc (SVAL (*p), len + 1);
+  else
+    SVAL (*p) = (char *) malloc (len + 1);
+  memcpy (SVAL (*p), str, len + 1);
+}
+
+void
+goom_set_list_param_value (PluginParam * p, const char *str)
+{
+  int len = strlen (str);
+
+#ifdef VERBOSE
+  printf ("%s: %d\n", str, len);
+#endif
+  if (LVAL (*p))
+    LVAL (*p) = (char *) realloc (LVAL (*p), len + 1);
+  else
+    LVAL (*p) = (char *) malloc (len + 1);
+  memcpy (LVAL (*p), str, len + 1);
+}
diff --git a/gst/goom/convolve_fx.c b/gst/goom/convolve_fx.c
new file mode 100644 (file)
index 0000000..261c5fa
--- /dev/null
@@ -0,0 +1,342 @@
+#include "goom_fx.h"
+#include "goom_plugin_info.h"
+#include "goomsl.h"
+#include "goom_config.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+//#define CONV_MOTIF_W 32
+//#define CONV_MOTIF_WMASK 0x1f
+
+#define CONV_MOTIF_W 128
+#define CONV_MOTIF_WMASK 0x7f
+
+typedef char Motif[CONV_MOTIF_W][CONV_MOTIF_W];
+
+#include "motif_goom1.h"
+#include "motif_goom2.h"
+
+#define NB_THETA 512
+
+#define MAX 2.0f
+
+typedef struct _CONV_DATA
+{
+  PluginParam light;
+  PluginParam factor_adj_p;
+  PluginParam factor_p;
+  PluginParameters params;
+
+  GoomSL *script;
+
+  /* rotozoom */
+  int theta;
+  float ftheta;
+  int h_sin[NB_THETA];
+  int h_cos[NB_THETA];
+  int h_height;
+  float visibility;
+  Motif conv_motif;
+  int inverse_motif;
+
+} ConvData;
+
+/* init rotozoom tables */
+static void
+compute_tables (VisualFX * _this, PluginInfo * info)
+{
+  ConvData *data = (ConvData *) _this->fx_data;
+  double screen_coef;
+  int i;
+  double h;
+  double radian;
+
+  if (data->h_height == info->screen.height)
+    return;
+
+  screen_coef = 2.0 * 300.0 / (double) info->screen.height;
+  data->h_height = info->screen.height;
+
+  for (i = 0; i < NB_THETA; i++) {
+    radian = 2 * i * M_PI / NB_THETA;
+    h = (0.2 + cos (radian) / 15.0 * sin (radian * 2.0 + 12.123)) * screen_coef;
+    data->h_cos[i] = 0x10000 * (-h * cos (radian) * cos (radian));
+    data->h_sin[i] = 0x10000 * (h * sin (radian + 1.57) * sin (radian));
+  }
+}
+
+static void
+set_motif (ConvData * data, Motif motif)
+{
+  int i, j;
+
+  for (i = 0; i < CONV_MOTIF_W; ++i)
+    for (j = 0; j < CONV_MOTIF_W; ++j)
+      data->conv_motif[i][j] =
+          motif[CONV_MOTIF_W - i - 1][CONV_MOTIF_W - j - 1];
+}
+
+static void
+convolve_init (VisualFX * _this, PluginInfo * info)
+{
+  ConvData *data;
+
+  data = (ConvData *) malloc (sizeof (ConvData));
+  _this->fx_data = (void *) data;
+
+  data->light = secure_f_param ("Screen Brightness");
+  data->light.param.fval.max = 300.0f;
+  data->light.param.fval.step = 1.0f;
+  data->light.param.fval.value = 100.0f;
+
+  data->factor_adj_p = secure_f_param ("Flash Intensity");
+  data->factor_adj_p.param.fval.max = 200.0f;
+  data->factor_adj_p.param.fval.step = 1.0f;
+  data->factor_adj_p.param.fval.value = 70.0f;
+
+  data->factor_p = secure_f_feedback ("Factor");
+
+  data->params = plugin_parameters ("Bright Flash", 5);
+  data->params.params[0] = &data->light;
+  data->params.params[1] = &data->factor_adj_p;
+  data->params.params[2] = 0;
+  data->params.params[3] = &data->factor_p;
+  data->params.params[4] = 0;
+
+  /* init rotozoom tables */
+  compute_tables (_this, info);
+  data->theta = 0;
+  data->ftheta = 0.0;
+  data->visibility = 1.0;
+  set_motif (data, CONV_MOTIF2);
+  data->inverse_motif = 0;
+
+  _this->params = &data->params;
+}
+
+static void
+convolve_free (VisualFX * _this)
+{
+  free (_this->fx_data);
+}
+
+static void
+create_output_with_brightness (VisualFX * _this, Pixel * src, Pixel * dest,
+    PluginInfo * info, int iff)
+{
+  ConvData *data = (ConvData *) _this->fx_data;
+
+  int x, y;
+  int i = 0;                    //info->screen.height * info->screen.width - 1;
+
+  const int c = data->h_cos[data->theta];
+  const int s = data->h_sin[data->theta];
+
+  const int xi = -(info->screen.width / 2) * c;
+  const int yi = (info->screen.width / 2) * s;
+
+  const int xj = -(info->screen.height / 2) * s;
+  const int yj = -(info->screen.height / 2) * c;
+
+  int xprime = xj;
+  int yprime = yj;
+
+  int ifftab[16];
+
+  if (data->inverse_motif) {
+    int i;
+
+    for (i = 0; i < 16; ++i)
+      ifftab[i] = (double) iff *(1.0 + data->visibility * (15.0 - i) / 15.0);
+  } else {
+    int i;
+
+    for (i = 0; i < 16; ++i)
+      ifftab[i] = (double) iff / (1.0 + data->visibility * (15.0 - i) / 15.0);
+  }
+
+  for (y = info->screen.height; y--;) {
+    int xtex, ytex;
+
+    xtex = xprime + xi + CONV_MOTIF_W * 0x10000 / 2;
+    xprime += s;
+
+    ytex = yprime + yi + CONV_MOTIF_W * 0x10000 / 2;
+    yprime += c;
+
+#ifdef HAVE_MMX
+    __asm__ __volatile__ ("\n\t pxor  %%mm7,  %%mm7"    /* mm7 = 0   */
+        "\n\t movd %[xtex],  %%mm2" "\n\t movd %[ytex],  %%mm3" "\n\t punpckldq %%mm3, %%mm2"   /* mm2 = [ ytex | xtex ] */
+        "\n\t movd %[c],     %%mm4" "\n\t movd %[s],     %%mm6" "\n\t pxor  %%mm5,   %%mm5" "\n\t psubd %%mm6,   %%mm5" "\n\t punpckldq %%mm5, %%mm4"   /* mm4 = [ -s | c ]      */
+        "\n\t movd %[motif], %%mm6"     /* mm6 = motif           */
+        ::[xtex] "g" (xtex),[ytex] "g" (ytex)
+        ,[c] "g" (c),[s] "g" (s)
+        ,[motif] "g" (&data->conv_motif[0][0]));
+
+    for (x = info->screen.width; x--;) {
+      __asm__ __volatile__ ("\n\t movd  %[src], %%mm0"  /* mm0 = src */
+          "\n\t paddd %%mm4, %%mm2"     /* [ ytex | xtex ] += [ -s | s ] */
+          "\n\t movd  %%esi, %%mm5"     /* save esi into mm5 */
+          "\n\t movq  %%mm2, %%mm3" "\n\t psrld  $16,  %%mm3"   /* mm3 = [ (ytex>>16) | (xtex>>16) ] */
+          "\n\t movd  %%mm3, %%eax"     /* eax = xtex' */
+          "\n\t psrlq $25,   %%mm3" "\n\t movd  %%mm3, %%ecx"   /* ecx = ytex' << 7 */
+          "\n\t andl  $127, %%eax" "\n\t andl  $16256, %%ecx" "\n\t addl  %%ecx, %%eax" "\n\t movd  %%mm6, %%esi"       /* esi = motif */
+          "\n\t xorl  %%ecx, %%ecx" "\n\t movb  (%%eax,%%esi), %%cl" "\n\t movl  %[ifftab], %%eax" "\n\t movd  %%mm5, %%esi"    /* restore esi from mm5 */
+          "\n\t movd  (%%eax,%%ecx,4), %%mm1"   /* mm1 = [0|0|0|iff2] */
+          "\n\t punpcklwd %%mm1, %%mm1"
+          "\n\t punpcklbw %%mm7, %%mm0"
+          "\n\t punpckldq %%mm1, %%mm1"
+          "\n\t psrlw     $1,    %%mm0"
+          "\n\t psrlw     $2,    %%mm1"
+          "\n\t pmullw    %%mm1, %%mm0"
+          "\n\t psrlw     $5,    %%mm0"
+          "\n\t packuswb  %%mm7, %%mm0"
+          "\n\t movd      %%mm0, %[dest]":[dest] "=g" (dest[i].val)
+          :[src] "g" (src[i].val)
+          ,[ifftab] "g" (&ifftab[0])
+          :"eax", "ecx");
+
+      i++;
+    }
+#else
+    for (x = info->screen.width; x--;) {
+
+      int iff2;
+      unsigned int f0, f1, f2, f3;
+
+      xtex += c;
+      ytex -= s;
+
+      iff2 =
+          ifftab[data->
+          conv_motif[(ytex >> 16) & CONV_MOTIF_WMASK][(xtex >> 16) &
+              CONV_MOTIF_WMASK]];
+
+#define sat(a) ((a)>0xFF?0xFF:(a))
+      f0 = src[i].val;
+      f1 = ((f0 >> R_OFFSET) & 0xFF) * iff2 >> 8;
+      f2 = ((f0 >> G_OFFSET) & 0xFF) * iff2 >> 8;
+      f3 = ((f0 >> B_OFFSET) & 0xFF) * iff2 >> 8;
+      dest[i].val =
+          (sat (f1) << R_OFFSET) | (sat (f2) << G_OFFSET) | (sat (f3) <<
+          B_OFFSET);
+/*
+      f0 = (src[i].cop[0] * iff2) >> 8;
+      f1 = (src[i].cop[1] * iff2) >> 8;
+      f2 = (src[i].cop[2] * iff2) >> 8;
+      f3 = (src[i].cop[3] * iff2) >> 8;
+
+      dest[i].cop[0] = (f0 & 0xffffff00) ? 0xff : (unsigned char)f0;
+      dest[i].cop[1] = (f1 & 0xffffff00) ? 0xff : (unsigned char)f1;
+      dest[i].cop[2] = (f2 & 0xffffff00) ? 0xff : (unsigned char)f2;
+      dest[i].cop[3] = (f3 & 0xffffff00) ? 0xff : (unsigned char)f3;
+*/
+      i++;
+    }
+#endif
+  }
+#ifdef HAVE_MMX
+  __asm__ __volatile__ ("\n\t emms");
+#endif
+
+  compute_tables (_this, info);
+}
+
+
+/*#include <stdint.h>
+
+static uint64_t GetTick()
+{
+  uint64_t x;
+  asm volatile ("RDTSC" : "=A" (x));
+  return x;
+}*/
+
+
+static void
+convolve_apply (VisualFX * _this, Pixel * src, Pixel * dest, PluginInfo * info)
+{
+
+  ConvData *data = (ConvData *) _this->fx_data;
+  float ff;
+  int iff;
+
+  ff = (FVAL (data->factor_p) * FVAL (data->factor_adj_p) +
+      FVAL (data->light)) / 100.0f;
+  iff = (unsigned int) (ff * 256);
+
+  {
+    double fcycle = (double) info->cycle;
+    double rotate_param, rotate_coef;
+    float INCREASE_RATE = 1.5;
+    float DECAY_RATE = 0.955;
+
+    if (FVAL (info->sound.last_goom_p) > 0.8)
+      FVAL (data->factor_p) += FVAL (info->sound.goom_power_p) * INCREASE_RATE;
+    FVAL (data->factor_p) *= DECAY_RATE;
+
+    rotate_param = FVAL (info->sound.last_goom_p);
+    if (rotate_param < 0.0)
+      rotate_param = 0.0;
+    rotate_param += FVAL (info->sound.goom_power_p);
+
+    rotate_coef = 4.0 + FVAL (info->sound.goom_power_p) * 6.0;
+    data->ftheta = (data->ftheta + rotate_coef * sin (rotate_param * 6.3));
+    data->theta = ((unsigned int) data->ftheta) % NB_THETA;
+    data->visibility =
+        (cos (fcycle * 0.001 + 1.5) * sin (fcycle * 0.008) +
+        cos (fcycle * 0.011 + 5.0) - 0.8 + info->sound.speedvar) * 1.5;
+    if (data->visibility < 0.0)
+      data->visibility = 0.0;
+    data->factor_p.change_listener (&data->factor_p);
+  }
+
+  if (data->visibility < 0.01) {
+    switch (goom_irand (info->gRandom, 300)) {
+      case 1:
+        set_motif (data, CONV_MOTIF1);
+        data->inverse_motif = 1;
+        break;
+      case 2:
+        set_motif (data, CONV_MOTIF2);
+        data->inverse_motif = 0;
+        break;
+    }
+  }
+
+  if ((ff > 0.98f) && (ff < 1.02f))
+    memcpy (dest, src, info->screen.size * sizeof (Pixel));
+  else
+    create_output_with_brightness (_this, src, dest, info, iff);
+/*
+//   Benching suite...
+   {
+    uint64_t before, after;
+    double   timed;
+    static double stimed = 10000.0;
+    before = GetTick();
+    data->visibility = 1.0;
+    create_output_with_brightness(_this,src,dest,info,iff);
+    after  = GetTick();
+    timed = (double)((after-before) / info->screen.size);
+    if (timed < stimed) {
+      stimed = timed;
+      printf ("CLK = %3.0f CPP\n", stimed);
+    }
+  }
+*/
+}
+
+VisualFX
+convolve_create (void)
+{
+  VisualFX vfx = {
+  init:convolve_init,
+  free:convolve_free,
+  apply:convolve_apply,
+  fx_data:0
+  };
+  return vfx;
+}
diff --git a/gst/goom/default_scripts.h b/gst/goom/default_scripts.h
new file mode 100644 (file)
index 0000000..5984d70
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _DEFAULT_SCRIPTS_H
+#define _DEFAULT_SCRIPTS_H
+
+#define GOOM_MAIN_SCRIPT ""
+
+#endif
diff --git a/gst/goom/drawmethods.c b/gst/goom/drawmethods.c
new file mode 100644 (file)
index 0000000..929564d
--- /dev/null
@@ -0,0 +1,204 @@
+#include "drawmethods.h"
+
+#define DRAWMETHOD_PLUS(_out,_backbuf,_col) \
+{\
+      int tra=0,i=0;\
+      unsigned char *bra = (unsigned char*)&(_backbuf);\
+      unsigned char *dra = (unsigned char*)&(_out);\
+      unsigned char *cra = (unsigned char*)&(_col);\
+      for (;i<4;i++) {\
+                               tra = *cra;\
+                               tra += *bra;\
+                               if (tra>255) tra=255;\
+                               *dra = tra;\
+                               ++dra;++cra;++bra;\
+                       }\
+}
+
+#define DRAWMETHOD DRAWMETHOD_PLUS(*p,*p,col)
+
+void
+draw_line (Pixel * data, int x1, int y1, int x2, int y2, int col, int screenx,
+    int screeny)
+{
+  int x, y, dx, dy, yy, xx;
+  Pixel *p;
+
+  if ((y1 < 0) || (y2 < 0) || (x1 < 0) || (x2 < 0) || (y1 >= screeny)
+      || (y2 >= screeny) || (x1 >= screenx) || (x2 >= screenx))
+    return;
+
+  /* clip to top edge 
+     if ((y1 < 0) && (y2 < 0))
+     return;
+
+     if (y1 < 0) {
+     x1 += (y1 * (x1 - x2)) / (y2 - y1);
+     y1 = 0;
+     }
+     if (y2 < 0) {
+     x2 += (y2 * (x1 - x2)) / (y2 - y1);
+     y2 = 0;
+     }
+
+     clip to bottom edge 
+     if ((y1 >= screeny) && (y2 >= screeny))
+     return;
+     if (y1 >= screeny) {
+     x1 -= ((screeny - y1) * (x1 - x2)) / (y2 - y1);
+     y1 = screeny - 1;
+     }
+     if (y2 >= screeny) {
+     x2 -= ((screeny - y2) * (x1 - x2)) / (y2 - y1);
+     y2 = screeny - 1;
+     }
+     clip to left edge 
+     if ((x1 < 0) && (x2 < 0))
+     return;
+     if (x1 < 0) {
+     y1 += (x1 * (y1 - y2)) / (x2 - x1);
+     x1 = 0;
+     }
+     if (x2 < 0) {
+     y2 += (x2 * (y1 - y2)) / (x2 - x1);
+     x2 = 0;
+     }
+     clip to right edge 
+     if ((x1 >= screenx) && (x2 >= screenx))
+     return;
+     if (x1 >= screenx) {
+     y1 -= ((screenx - x1) * (y1 - y2)) / (x2 - x1);
+     x1 = screenx - 1;
+     }
+     if (x2 >= screenx) {
+     y2 -= ((screenx - x2) * (y1 - y2)) / (x2 - x1);
+     x2 = screenx - 1;
+     }
+   */
+
+  dx = x2 - x1;
+  dy = y2 - y1;
+  if (x1 > x2) {
+    int tmp;
+
+    tmp = x1;
+    x1 = x2;
+    x2 = tmp;
+    tmp = y1;
+    y1 = y2;
+    y2 = tmp;
+    dx = x2 - x1;
+    dy = y2 - y1;
+  }
+
+  /* vertical line */
+  if (dx == 0) {
+    if (y1 < y2) {
+      p = &(data[(screenx * y1) + x1]);
+      for (y = y1; y <= y2; y++) {
+        DRAWMETHOD;
+        p += screenx;
+      }
+    } else {
+      p = &(data[(screenx * y2) + x1]);
+      for (y = y2; y <= y1; y++) {
+        DRAWMETHOD;
+        p += screenx;
+      }
+    }
+    return;
+  }
+  /* horizontal line */
+  if (dy == 0) {
+    if (x1 < x2) {
+      p = &(data[(screenx * y1) + x1]);
+      for (x = x1; x <= x2; x++) {
+        DRAWMETHOD;
+        p++;
+      }
+      return;
+    } else {
+      p = &(data[(screenx * y1) + x2]);
+      for (x = x2; x <= x1; x++) {
+        DRAWMETHOD;
+        p++;
+      }
+      return;
+    }
+  }
+  /* 1    */
+  /* \   */
+  /* \  */
+  /* 2 */
+  if (y2 > y1) {
+    /* steep */
+    if (dy > dx) {
+      dx = ((dx << 16) / dy);
+      x = x1 << 16;
+      for (y = y1; y <= y2; y++) {
+        xx = x >> 16;
+        p = &(data[(screenx * y) + xx]);
+        DRAWMETHOD;
+        if (xx < (screenx - 1)) {
+          p++;
+          /* DRAWMETHOD; */
+        }
+        x += dx;
+      }
+      return;
+    }
+    /* shallow */
+    else {
+      dy = ((dy << 16) / dx);
+      y = y1 << 16;
+      for (x = x1; x <= x2; x++) {
+        yy = y >> 16;
+        p = &(data[(screenx * yy) + x]);
+        DRAWMETHOD;
+        if (yy < (screeny - 1)) {
+          p += screeny;
+          /* DRAWMETHOD; */
+        }
+        y += dy;
+      }
+    }
+  }
+  /* 2 */
+  /* /  */
+  /* /   */
+  /* 1    */
+  else {
+    /* steep */
+    if (-dy > dx) {
+      dx = ((dx << 16) / -dy);
+      x = (x1 + 1) << 16;
+      for (y = y1; y >= y2; y--) {
+        xx = x >> 16;
+        p = &(data[(screenx * y) + xx]);
+        DRAWMETHOD;
+        if (xx < (screenx - 1)) {
+          p--;
+          /* DRAWMETHOD; */
+        }
+        x += dx;
+      }
+      return;
+    }
+    /* shallow */
+    else {
+      dy = ((dy << 16) / dx);
+      y = y1 << 16;
+      for (x = x1; x <= x2; x++) {
+        yy = y >> 16;
+        p = &(data[(screenx * yy) + x]);
+        DRAWMETHOD;
+        if (yy < (screeny - 1)) {
+          p += screeny;
+          /* DRAWMETHOD; */
+        }
+        y += dy;
+      }
+      return;
+    }
+  }
+}
diff --git a/gst/goom/drawmethods.h b/gst/goom/drawmethods.h
new file mode 100644 (file)
index 0000000..76ad6ca
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _DRAWMETHODS_H
+#define _DRAWMETHODS_H
+
+#include "goom_config.h"
+#include "goom_graphic.h"
+
+void draw_line (Pixel *data, int x1, int y1, int x2, int y2, int col, int screenx, int screeny);
+
+#endif /* _DRAWMETHODS_H */
index b898e89cd087bb7bbcc0fa45488b198ac6d935df..07e989e71614dece9ff7bb0706fbb4394e623d80 100644 (file)
+// --- CHUI EN TRAIN DE SUPPRIMER LES EXTERN RESOLX ET C_RESOLY ---
+
 /* filter.c version 0.7
- * contient les filtres applicable a un buffer
- * creation : 01/10/2000
- *  -ajout de sinFilter()
- *  -ajout de zoomFilter()
- *  -copie de zoomFilter() en zoomFilterRGB(), gérant les 3 couleurs
- *  -optimisation de sinFilter (utilisant une table de sin)
- *      -asm
- *      -optimisation de la procedure de génération du buffer de transformation
- *              la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
+* contient les filtres applicable a un buffer
+* creation : 01/10/2000
+*  -ajout de sinFilter()
+*  -ajout de zoomFilter()
+*  -copie de zoomFilter() en zoomFilterRGB(), gerant les 3 couleurs
+*  -optimisation de sinFilter (utilisant une table de sin)
+*      -asm
+*      -optimisation de la procedure de generation du buffer de transformation
+*              la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
 */
 
-/*#define _DEBUG_PIXEL; */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+/* #define _DEBUG_PIXEL */
 
-#include "filters.h"
-#include "graphic.h"
-#include "goom_tools.h"
-#include "goom_core.h"
+#include <string.h>
 #include <stdlib.h>
 #include <math.h>
 #include <stdio.h>
+#include <inttypes.h>
 
-#ifdef MMX
-#define USE_ASM
-#endif
-#ifdef POWERPC
-#define USE_ASM
-#endif
+#include "goom_filters.h"
+#include "goom_graphic.h"
+#include "goom_tools.h"
+#include "goom_plugin_info.h"
+#include "goom_fx.h"
+#include "v3d.h"
 
-#ifdef USE_ASM
-#define EFFECT_DISTORS 4
-#else
-#define EFFECT_DISTORS 10
-#endif
+/* TODO : MOVE THIS AWAY !!! */
+/* jeko: j'ai essayer de le virer, mais si on veut les laisser inline c'est un peu lourdo... */
+static inline void
+setPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color c)
+{
+  Pixel i;
 
+  i.channels.b = c.b;
+  i.channels.g = c.v;
+  i.channels.r = c.r;
+  *(buffer + (x + y * goomInfo->screen.width)) = i;
+}
 
-#ifdef USE_ASM
+static inline void
+setPixelRGB_ (Pixel * buffer, Uint x, Color c)
+{
+  buffer[x].channels.r = c.r;
+  buffer[x].channels.g = c.v;
+  buffer[x].channels.b = c.b;
+}
 
-#ifdef MMX
-int mmx_zoom ();
-guint32 mmx_zoom_size;
-#endif /* MMX */
+static inline void
+getPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color * c)
+{
+  Pixel i = *(buffer + (x + y * goomInfo->screen.width));
 
-#ifdef POWERPC
-extern unsigned int useAltivec;
-extern void ppc_zoom (void);
-extern void ppc_zoom_altivec (void);
-unsigned int ppcsize4;
-#endif /* PowerPC */
+  c->b = i.channels.b;
+  c->v = i.channels.g;
+  c->r = i.channels.r;
+}
 
+static inline void
+getPixelRGB_ (Pixel * buffer, Uint x, Color * c)
+{
+  Pixel i = *(buffer + x);
 
-unsigned int *coeffs = 0, *freecoeffs = 0;
-guint32 *expix1 = 0;            /* pointeur exporte vers p1 */
-guint32 *expix2 = 0;            /* pointeur exporte vers p2 */
-guint32 zoom_width;
-#endif /* ASM */
+  c->b = i.channels.b;
+  c->v = i.channels.g;
+  c->r = i.channels.r;
+}
 
+/* END TODO */
 
-static int firstTime = 1;
-static int sintable[0xffff];
 
-ZoomFilterData *
-zoomFilterNew ()
-{
-  ZoomFilterData *zf = malloc (sizeof (ZoomFilterData));
-
-  zf->vitesse = 128;
-  zf->pertedec = 8;
-  zf->sqrtperte = 16;
-  zf->middleX = 1;
-  zf->middleY = 1;
-  zf->reverse = 0;
-  zf->mode = WAVE_MODE;
-  zf->hPlaneEffect = 0;
-  zf->vPlaneEffect = 0;
-  zf->noisify = 0;
-  zf->buffsize = 0;
-  zf->res_x = 0;
-  zf->res_y = 0;
-
-  zf->buffer = NULL;
-  zf->firedec = NULL;
-
-  zf->wave = 0;
-  zf->wavesp = 0;
-
-  return zf;
-}
+/* DEPRECATED */
+// retourne x>>s , en testant le signe de x
+//#define ShiftRight(_x,_s) (((_x)<0) ? -(-(_x)>>(_s)) : ((_x)>>(_s)))
+//#define EFFECT_DISTORS 4
+//#define EFFECT_DISTORS_SL 2
+//#define INTERLACE_ADD 9
+//#define INTERLACE_AND 0xf
+/* END DEPRECATED */
 
-/* retourne x>>s , en testant le signe de x */
-static inline int
-ShiftRight (int x, const unsigned char s)
+#define BUFFPOINTNB 16
+#define BUFFPOINTNBF 16.0f
+#define BUFFPOINTMASK 0xffff
+
+#define sqrtperte 16
+/* faire : a % sqrtperte <=> a & pertemask */
+#define PERTEMASK 0xf
+/* faire : a / sqrtperte <=> a >> PERTEDEC */
+#define PERTEDEC 4
+
+/* pure c version of the zoom filter */
+static void c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX,
+    unsigned int prevY, signed int *brutS, signed int *brutD, int buffratio,
+    int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
+
+/* simple wrapper to give it the same proto than the others */
+void
+zoom_filter_c (int sizeX, int sizeY, Pixel * src, Pixel * dest, int *brutS,
+    int *brutD, int buffratio, int precalCoef[16][16])
 {
-  if (x < 0)
-    return -(-x >> s);
-  else
-    return x >> s;
+  c_zoom (src, dest, sizeX, sizeY, brutS, brutD, buffratio, precalCoef);
 }
 
-/*
-  calculer px et py en fonction de x,y,middleX,middleY et theMode
-  px et py indique la nouvelle position (en sqrtperte ieme de pixel)
-  (valeur * 16)
-*/
-void
-calculatePXandPY (GoomData * gd, int x, int y, int *px, int *py)
+static void generatePrecalCoef (int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
+
+
+typedef struct _ZOOM_FILTER_FX_WRAPPER_DATA
 {
-  ZoomFilterData *zf = gd->zfd;
+
+  PluginParam enabled_bp;
+  PluginParameters params;
+
+  unsigned int *coeffs, *freecoeffs;
+
+  signed int *brutS, *freebrutS;        /* source */
+  signed int *brutD, *freebrutD;        /* dest */
+  signed int *brutT, *freebrutT;        /* temp (en cours de generation) */
+
+  guint32 zoom_width;
+
+  unsigned int prevX, prevY;
+
+  float general_speed;
+  int reverse;                  /* reverse the speed */
+  char theMode;
+  int waveEffect;
+  int hypercosEffect;
+  int vPlaneEffect;
+  int hPlaneEffect;
+  char noisify;
   int middleX, middleY;
-  guint32 resoly = zf->res_y;
-  int vPlaneEffect = zf->vPlaneEffect;
-  int hPlaneEffect = zf->hPlaneEffect;
-  int vitesse = zf->vitesse;
-  char theMode = zf->mode;
-
-  if (theMode == WATER_MODE) {
-    int wavesp = zf->wavesp;
-    int wave = zf->wave;
-    int yy = y + RAND (gd) % 4 + wave / 10;
-
-    yy -= RAND (gd) % 4;
-    if (yy < 0)
-      yy = 0;
-    if (yy >= resoly)
-      yy = resoly - 1;
-
-    *px = (x << 4) + zf->firedec[yy] + (wave / 10);
-    *py = (y << 4) + 132 - ((vitesse < 132) ? vitesse : 131);
-
-    wavesp += RAND (gd) % 3;
-    wavesp -= RAND (gd) % 3;
-    if (wave < -10)
-      wavesp += 2;
-    if (wave > 10)
-      wavesp -= 2;
-    wave += (wavesp / 10) + RAND (gd) % 3;
-    wave -= RAND (gd) % 3;
-    if (wavesp > 100)
-      wavesp = (wavesp * 9) / 10;
-
-    zf->wavesp = wavesp;
-    zf->wave = wave;
-  } else {
-    int dist;
-    register int vx, vy;
-    int fvitesse = vitesse << 4;
-
-    middleX = zf->middleX;
-    middleY = zf->middleY;
-
-    if (zf->noisify) {
-      x += RAND (gd) % zf->noisify;
-      x -= RAND (gd) % zf->noisify;
-      y += RAND (gd) % zf->noisify;
-      y -= RAND (gd) % zf->noisify;
-    }
 
-    if (hPlaneEffect)
-      vx = ((x - middleX) << 9) + hPlaneEffect * (y - middleY);
-    else
-      vx = (x - middleX) << 9;
-
-    if (vPlaneEffect)
-      vy = ((y - middleY) << 9) + vPlaneEffect * (x - middleX);
-    else
-      vy = (y - middleY) << 9;
-
-    switch (theMode) {
-      case WAVE_MODE:
-        dist =
-            ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
-            9) * ShiftRight (vy, 9);
-        fvitesse *=
-            1024 +
-            ShiftRight (sintable[(unsigned short) (0xffff * dist *
-                    EFFECT_DISTORS)], 6);
-        fvitesse /= 1024;
-        break;
-      case CRYSTAL_BALL_MODE:
-        dist =
-            ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
-            9) * ShiftRight (vy, 9);
-        fvitesse += (dist * EFFECT_DISTORS >> 10);
-        break;
-      case AMULETTE_MODE:
-        dist =
-            ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
-            9) * ShiftRight (vy, 9);
-        fvitesse -= (dist * EFFECT_DISTORS >> 4);
-        break;
-      case SCRUNCH_MODE:
-        dist =
-            ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
-            9) * ShiftRight (vy, 9);
-        fvitesse -= (dist * EFFECT_DISTORS >> 9);
-        break;
-    }
-    if (vx < 0)
-      *px = (middleX << 4) - (-(vx * fvitesse) >> 16);
-    else
-      *px = (middleX << 4) + ((vx * fvitesse) >> 16);
-    if (vy < 0)
-      *py = (middleY << 4) - (-(vy * fvitesse) >> 16);
-    else
-      *py = (middleY << 4) + ((vy * fvitesse) >> 16);
-  }
-}
+  int mustInitBuffers;
+  int interlace_start;
 
-/*#define _DEBUG */
+    /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
+  int buffratio;
+  int *firedec;
 
-static inline void
-setPixelRGB (Uint * buffer, Uint x, Uint y, Color c,
-    guint32 resolx, guint32 resoly)
-{
-/*              buffer[ y*WIDTH + x ] = (c.r<<16)|(c.v<<8)|c.b */
-#ifdef _DEBUG_PIXEL
-  if (x + y * resolx >= resolx * resoly) {
-    fprintf (stderr, "setPixel ERROR : hors du tableau... %i, %i\n", x, y);
-    /*exit (1) ; */
-  }
-#endif
+    /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
+  int precalCoef[BUFFPOINTNB][BUFFPOINTNB];
 
-#ifdef USE_DGA
-  buffer[y * resolx + x] = (c.b << 16) | (c.v << 8) | c.r;
-#else
-  buffer[y * resolx + x] = (c.r << 16) | (c.v << 8) | c.b;
-#endif
-}
+    /** calculatePXandPY statics */
+  int wave;
+  int wavesp;
 
+} ZoomFilterFXWrapperData;
 
-static inline void
-setPixelRGB_ (Uint * buffer, Uint x, Color c, guint32 resolx, guint32 resoly)
+
+
+
+static inline v2g
+zoomVector (ZoomFilterFXWrapperData * data, float X, float Y)
 {
-#ifdef _DEBUG
-  if (x >= resolx * resoly) {
-    printf ("setPixel ERROR : hors du tableau... %i >= %i*%i (%i)\n", x, resolx,
-        resoly, resolx * resoly);
-    exit (1);
+  v2g vecteur;
+  float vx, vy;
+  float sq_dist = X * X + Y * Y;
+
+  /*    sx = (X < 0.0f) ? -1.0f : 1.0f;
+     sy = (Y < 0.0f) ? -1.0f : 1.0f;
+   */
+  float coefVitesse = (1.0f + data->general_speed) / 50.0f;
+
+  // Effects
+
+  /* Centralized FX */
+
+  switch (data->theMode) {
+    case CRYSTAL_BALL_MODE:
+      coefVitesse -= (sq_dist - 0.3f) / 15.0f;
+      break;
+    case AMULETTE_MODE:
+      coefVitesse += sq_dist * 3.5f;
+      break;
+    case WAVE_MODE:
+      coefVitesse += sin (sq_dist * 20.0f) / 100.0f;
+      break;
+    case SCRUNCH_MODE:
+      coefVitesse += sq_dist / 10.0f;
+      break;
+      //case HYPERCOS1_MODE:
+      break;
+      //case HYPERCOS2_MODE:
+      break;
+      //case YONLY_MODE:
+      break;
+    case SPEEDWAY_MODE:
+      coefVitesse *= 4.0f * Y;
+      break;
+    default:
+      break;
   }
-#endif
 
-#ifdef USE_DGA
-  buffer[x] = (c.b << 16) | (c.v << 8) | c.r;
-#else
-  buffer[x] = (c.r << 16) | (c.v << 8) | c.b;
-#endif
-}
+  if (coefVitesse < -2.01f)
+    coefVitesse = -2.01f;
+  if (coefVitesse > 2.01f)
+    coefVitesse = 2.01f;
 
+  vx = coefVitesse * X;
+  vy = coefVitesse * Y;
 
+  /* Amulette 2 */
+  // vx = X * tan(dist);
+  // vy = Y * tan(dist);
 
-static inline void
-getPixelRGB (Uint * buffer, Uint x, Uint y, Color * c,
-    guint32 resolx, guint32 resoly)
-{
-  register unsigned char *tmp8;
+  /* Rotate */
+  //vx = (X+Y)*0.1;
+  //vy = (Y-X)*0.1;
+
+
+  // Effects adds-on
 
-#ifdef _DEBUG
-  if (x + y * resolx >= resolx * resoly) {
-    printf ("getPixel ERROR : hors du tableau... %i, %i\n", x, y);
-    exit (1);
+  /* Noise */
+  if (data->noisify) {
+    vx += (((float) random ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
+    vy += (((float) random ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
   }
-#endif
-
-#ifdef __BIG_ENDIAN__
-  c->b = *(unsigned char *) (tmp8 =
-      (unsigned char *) (buffer + (x + y * resolx)));
-  c->r = *(unsigned char *) (++tmp8);
-  c->v = *(unsigned char *) (++tmp8);
-  c->b = *(unsigned char *) (++tmp8);
-
-#else
-  /* ATTENTION AU PETIT INDIEN  */
-  c->b = *(unsigned char *) (tmp8 =
-      (unsigned char *) (buffer + (x + y * resolx)));
-  c->v = *(unsigned char *) (++tmp8);
-  c->r = *(unsigned char *) (++tmp8);
-/*      *c = (Color) buffer[x+y*WIDTH] ; */
-#endif
+
+  /* Hypercos */
+  if (data->hypercosEffect) {
+    vx += sin (Y * 10.0f) / 120.0f;
+    vy += sin (X * 10.0f) / 120.0f;
+  }
+
+  /* H Plane */
+  if (data->hPlaneEffect)
+    vx += Y * 0.0025f * data->hPlaneEffect;
+
+  /* V Plane */
+  if (data->vPlaneEffect)
+    vy += X * 0.0025f * data->vPlaneEffect;
+
+  /* TODO : Water Mode */
+  //    if (data->waveEffect)
+
+  vecteur.x = vx;
+  vecteur.y = vy;
+
+  return vecteur;
 }
 
 
-static inline void
-getPixelRGB_ (Uint * buffer, Uint x, Color * c, guint32 resolx, guint32 resoly)
+/*
+ * Makes a stripe of a transform buffer (brutT)
+ *
+ * The transform is (in order) :
+ * Translation (-data->middleX, -data->middleY)
+ * Homothetie (Center : 0,0   Coeff : 2/data->prevX)
+ */
+static void
+makeZoomBufferStripe (ZoomFilterFXWrapperData * data, int INTERLACE_INCR)
 {
-  register unsigned char *tmp8;
+  // Position of the pixel to compute in pixmap coordinates
+  Uint x, y;
 
-#ifdef _DEBUG
-  if (x >= resolx * resoly) {
-    printf ("getPixel ERROR : hors du tableau... %i\n", x);
-    exit (1);
+  // Where (verticaly) to stop generating the buffer stripe
+  int maxEnd = (data->interlace_start + INTERLACE_INCR);
+
+  // Ratio from pixmap to normalized coordinates
+  float ratio = 2.0f / ((float) data->prevX);
+
+  // Ratio from normalized to virtual pixmap coordinates
+  float inv_ratio = BUFFPOINTNBF / ratio;
+  float min = ratio / BUFFPOINTNBF;
+
+  // Y position of the pixel to compute in normalized coordinates
+  float Y = ((float) (data->interlace_start - data->middleY)) * ratio;
+
+  maxEnd = data->prevY;
+  if (maxEnd > (data->interlace_start + INTERLACE_INCR))
+    maxEnd = (data->interlace_start + INTERLACE_INCR);
+
+  for (y = data->interlace_start;
+      (y < data->prevY) && ((signed int) y < maxEnd); y++) {
+    Uint premul_y_prevX = y * data->prevX * 2;
+    float X = -((float) data->middleX) * ratio;
+
+    for (x = 0; x < data->prevX; x++) {
+      v2g vector = zoomVector (data, X, Y);
+
+      /* Finish and avoid null displacement */
+      if (fabs (vector.x) < min)
+        vector.x = (vector.x < 0.0f) ? -min : min;
+      if (fabs (vector.y) < min)
+        vector.y = (vector.y < 0.0f) ? -min : min;
+
+      data->brutT[premul_y_prevX] =
+          ((int) ((X - vector.x) * inv_ratio) +
+          ((int) (data->middleX * BUFFPOINTNB)));
+      data->brutT[premul_y_prevX + 1] =
+          ((int) ((Y - vector.y) * inv_ratio) +
+          ((int) (data->middleY * BUFFPOINTNB)));
+      premul_y_prevX += 2;
+      X += ratio;
+    }
+    Y += ratio;
   }
-#endif
-
-#ifdef __BIG_ENDIAN__
-  c->b = *(unsigned char *) (tmp8 = (unsigned char *) (buffer + x));
-  c->r = *(unsigned char *) (++tmp8);
-  c->v = *(unsigned char *) (++tmp8);
-  c->b = *(unsigned char *) (++tmp8);
-
-#else
-  /* ATTENTION AU PETIT INDIEN  */
-  tmp8 = (unsigned char *) (buffer + x);
-  c->b = *(unsigned char *) (tmp8++);
-  c->v = *(unsigned char *) (tmp8++);
-  c->r = *(unsigned char *) (tmp8);
-/*      *c = (Color) buffer[x+y*WIDTH] ; */
-#endif
+  data->interlace_start += INTERLACE_INCR;
+  if (y >= data->prevY - 1)
+    data->interlace_start = -1;
 }
 
+
+/*
+ * calculer px et py en fonction de x,y,middleX,middleY et theMode
+ * px et py indique la nouvelle position (en sqrtperte ieme de pixel)
+ * (valeur * 16)
+ inline void calculatePXandPY (PluginInfo *goomInfo, ZoomFilterFXWrapperData *data, int x, int y, int *px, int *py)
+ {
+     if (data->theMode == WATER_MODE) {
+         int yy;
+         
+         yy = y + goom_irand(goomInfo->gRandom, 4) - goom_irand(goomInfo->gRandom, 4) + data->wave / 10;
+         if (yy < 0)
+             yy = 0;
+         if (yy >= (signed int)goomInfo->screen.height)
+             yy = goomInfo->screen.height - 1;
+         
+         *px = (x << 4) + data->firedec[yy] + (data->wave / 10);
+         *py = (y << 4) + 132 - ((data->vitesse < 131) ? data->vitesse : 130);
+         
+         data->wavesp += goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
+         if (data->wave < -10)
+             data->wavesp += 2;
+         if (data->wave > 10)
+             data->wavesp -= 2;
+         data->wave += (data->wavesp / 10) + goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
+         if (data->wavesp > 100)
+             data->wavesp = (data->wavesp * 9) / 10;
+     }
+     else {
+         int     dist = 0, vx9, vy9;
+         int     vx, vy;
+         int     ppx, ppy;
+         int     fvitesse = data->vitesse << 4;
+         
+         if (data->noisify) {
+             x += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
+             y += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
+         }
+         vx = (x - data->middleX) << 9;
+         vy = (y - data->middleY) << 9;
+         
+         if (data->hPlaneEffect)
+             vx += data->hPlaneEffect * (y - data->middleY);
+         
+         if (data->vPlaneEffect)
+             vy += data->vPlaneEffect * (x - data->middleX);
+         
+         if (data->waveEffect) {
+             fvitesse *=
+             1024 +
+             ShiftRight (goomInfo->sintable
+                         [(unsigned short) (dist * 0xffff + EFFECT_DISTORS)], 6);
+             fvitesse /= 1024;
+         }
+         
+         if (data->hypercosEffect) {
+             vx += ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
+             vy += ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
+         }
+         
+         vx9 = ShiftRight (vx, 9);
+         vy9 = ShiftRight (vy, 9);
+         dist = vx9 * vx9 + vy9 * vy9;
+         
+         switch (data->theMode) {
+             case WAVE_MODE:
+                 fvitesse *=
+                 1024 +
+                 ShiftRight (goomInfo->sintable
+                             [(unsigned short) (dist * 0xffff * EFFECT_DISTORS)], 6);
+                 fvitesse>>=10;
+                 break;
+             case CRYSTAL_BALL_MODE:
+                 fvitesse += (dist >> (10-EFFECT_DISTORS_SL));
+                 break;
+             case AMULETTE_MODE:
+                 fvitesse -= (dist >> (4 - EFFECT_DISTORS_SL));
+                 break;
+             case SCRUNCH_MODE:
+                 fvitesse -= (dist >> (10 - EFFECT_DISTORS_SL));
+                 break;
+             case HYPERCOS1_MODE:
+                 vx = vx + ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
+                 vy = vy + ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
+                 break;
+             case HYPERCOS2_MODE:
+                 vx =
+                 vx + ShiftRight (goomInfo->sintable[(-ShiftRight (vy, 1) + dist) & 0xffff], 0);
+                 vy =
+                     vy + ShiftRight (goomInfo->sintable[(ShiftRight (vx, 1) + dist) & 0xffff], 0);
+                 fvitesse = 128 << 4;
+                 break;
+             case YONLY_MODE:
+                 fvitesse *= 1024 + ShiftRight (goomInfo->sintable[vy & 0xffff], 6);
+                 fvitesse >>= 10;
+                 break;
+             case SPEEDWAY_MODE:
+                 fvitesse -= (ShiftRight(vy,10-EFFECT_DISTORS_SL));
+                 break;
+         }
+         
+         if (fvitesse < -3024)
+             fvitesse = -3024;
+         
+         if (vx < 0)                                                                   // pb avec decalage sur nb negatif
+             ppx = -(-(vx * fvitesse) >> 16);
+         // 16 = 9 + 7 (7 = nb chiffre virgule de vitesse * (v = 128 => immobile)
+         //    * * * * * 9 = nb chiffre virgule de vx) 
+         else
+             ppx = ((vx * fvitesse) >> 16);
+         
+         if (vy < 0)
+             ppy = -(-(vy * fvitesse) >> 16);
+         else
+             ppy = ((vy * fvitesse) >> 16);
+         
+         *px = (data->middleX << 4) + ppx;
+         *py = (data->middleY << 4) + ppy;
+     }
+ }
+ */
+
+
+
 static void
-zoomFilterSetResolution (GoomData * gd, ZoomFilterData * zf)
+c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX, unsigned int prevY,
+    signed int *brutS, signed int *brutD, int buffratio, int precalCoef[16][16])
 {
-  unsigned short us;
+  int myPos, myPos2;
+  Color couleur;
 
-  if (zf->buffsize >= gd->buffsize) {
-    zf->res_x = gd->resolx;
-    zf->res_y = gd->resoly;
-    zf->middleX = gd->resolx / 2;
-    zf->middleY = gd->resoly - 1;
+  unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC;
 
-    return;
-  }
-#ifndef USE_ASM
-  if (zf->buffer)
-    free (zf->buffer);
-  zf->buffer = 0;
-#else
-  if (coeffs)
-    free (freecoeffs);
-  coeffs = 0;
-#endif
-  zf->middleX = gd->resolx / 2;
-  zf->middleY = gd->resoly - 1;
-  zf->res_x = gd->resolx;
-  zf->res_y = gd->resoly;
-
-  if (zf->firedec)
-    free (zf->firedec);
-  zf->firedec = 0;
-
-  zf->buffsize = gd->resolx * gd->resoly * sizeof (unsigned int);
-
-#ifdef USE_ASM
-  freecoeffs = (unsigned int *)
-      malloc (resx * resy * 2 * sizeof (unsigned int) + 128);
-  coeffs = (guint32 *) ((1 + ((unsigned int) (freecoeffs)) / 128) * 128);
-
-#else
-  zf->buffer = calloc (sizeof (guint32), zf->buffsize * 5);
-  zf->pos10 = zf->buffer;
-  zf->c[0] = zf->pos10 + zf->buffsize;
-  zf->c[1] = zf->c[0] + zf->buffsize;
-  zf->c[2] = zf->c[1] + zf->buffsize;
-  zf->c[3] = zf->c[2] + zf->buffsize;
-#endif
-  zf->firedec = (int *) malloc (zf->res_y * sizeof (int));
-
-  if (firstTime) {
-    firstTime = 0;
-
-    /* generation d'une table de sinus */
-    for (us = 0; us < 0xffff; us++) {
-      sintable[us] = (int) (1024.0f * sin (us * 2 * 3.31415f / 0xffff));
-    }
-  }
+  int bufsize = prevX * prevY * 2;
+  int bufwidth = prevX;
 
-  {
-    int loopv;
-
-    for (loopv = zf->res_y; loopv != 0;) {
-      int decc = 0;
-      int spdc = 0;
-      int accel = 0;
-
-      loopv--;
-      zf->firedec[loopv] = decc;
-      decc += spdc / 10;
-      spdc += RAND (gd) % 3;
-      spdc -= RAND (gd) % 3;
-
-      if (decc > 4)
-        spdc -= 1;
-      if (decc < -4)
-        spdc += 1;
-
-      if (spdc > 30)
-        spdc = spdc - RAND (gd) % 3 + accel / 10;
-      if (spdc < -30)
-        spdc = spdc + RAND (gd) % 3 + accel / 10;
-
-      if (decc > 8 && spdc > 1)
-        spdc -= RAND (gd) % 3 - 2;
-
-      if (decc < -8 && spdc < -1)
-        spdc += RAND (gd) % 3 + 2;
-
-      if (decc > 8 || decc < -8)
-        decc = decc * 8 / 9;
-
-      accel += RAND (gd) % 2;
-      accel -= RAND (gd) % 2;
-      if (accel > 20)
-        accel -= 2;
-      if (accel < -20)
-        accel += 2;
+  expix1[0].val = expix1[prevX - 1].val = expix1[prevX * prevY - 1].val =
+      expix1[prevX * prevY - prevX].val = 0;
+
+  for (myPos = 0; myPos < bufsize; myPos += 2) {
+    Color col1, col2, col3, col4;
+    int c1, c2, c3, c4, px, py;
+    int pos;
+    int coeffs;
+
+    int brutSmypos = brutS[myPos];
+
+    myPos2 = myPos + 1;
+
+    px = brutSmypos + (((brutD[myPos] -
+                brutSmypos) * buffratio) >> BUFFPOINTNB);
+    brutSmypos = brutS[myPos2];
+    py = brutSmypos + (((brutD[myPos2] -
+                brutSmypos) * buffratio) >> BUFFPOINTNB);
+
+    if ((py >= ay) || (px >= ax)) {
+      pos = coeffs = 0;
+    } else {
+      pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC));
+      /* coef en modulo 15 */
+      coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK];
     }
+    getPixelRGB_ (expix1, pos, &col1);
+    getPixelRGB_ (expix1, pos + 1, &col2);
+    getPixelRGB_ (expix1, pos + bufwidth, &col3);
+    getPixelRGB_ (expix1, pos + bufwidth + 1, &col4);
+
+    c1 = coeffs;
+    c2 = (c1 >> 8) & 0xFF;
+    c3 = (c1 >> 16) & 0xFF;
+    c4 = (c1 >> 24) & 0xFF;
+    c1 = c1 & 0xff;
+
+    couleur.r = col1.r * c1 + col2.r * c2 + col3.r * c3 + col4.r * c4;
+    if (couleur.r > 5)
+      couleur.r -= 5;
+    couleur.r >>= 8;
+
+    couleur.v = col1.v * c1 + col2.v * c2 + col3.v * c3 + col4.v * c4;
+    if (couleur.v > 5)
+      couleur.v -= 5;
+    couleur.v >>= 8;
+
+    couleur.b = col1.b * c1 + col2.b * c2 + col3.b * c3 + col4.b * c4;
+    if (couleur.b > 5)
+      couleur.b -= 5;
+    couleur.b >>= 8;
+
+    setPixelRGB_ (expix2, myPos >> 1, couleur);
   }
 }
 
-void
-zoomFilterDestroy (ZoomFilterData * zf)
+/** generate the water fx horizontal direction buffer */
+static void
+generateTheWaterFXHorizontalDirectionBuffer (PluginInfo * goomInfo,
+    ZoomFilterFXWrapperData * data)
 {
-  if (zf) {
-    if (zf->firedec)
-      free (zf->firedec);
-    if (zf->buffer)
-      free (zf->buffer);
-    free (zf);
+
+  int loopv;
+  int decc = goom_irand (goomInfo->gRandom, 8) - 4;
+  int spdc = goom_irand (goomInfo->gRandom, 8) - 4;
+  int accel = goom_irand (goomInfo->gRandom, 8) - 4;
+
+  for (loopv = data->prevY; loopv != 0;) {
+
+    loopv--;
+    data->firedec[loopv] = decc;
+    decc += spdc / 10;
+    spdc +=
+        goom_irand (goomInfo->gRandom, 3) - goom_irand (goomInfo->gRandom, 3);
+
+    if (decc > 4)
+      spdc -= 1;
+    if (decc < -4)
+      spdc += 1;
+
+    if (spdc > 30)
+      spdc = spdc - goom_irand (goomInfo->gRandom, 3) + accel / 10;
+    if (spdc < -30)
+      spdc = spdc + goom_irand (goomInfo->gRandom, 3) + accel / 10;
+
+    if (decc > 8 && spdc > 1)
+      spdc -= goom_irand (goomInfo->gRandom, 3) - 2;
+
+    if (decc < -8 && spdc < -1)
+      spdc += goom_irand (goomInfo->gRandom, 3) + 2;
+
+    if (decc > 8 || decc < -8)
+      decc = decc * 8 / 9;
+
+    accel +=
+        goom_irand (goomInfo->gRandom, 2) - goom_irand (goomInfo->gRandom, 2);
+    if (accel > 20)
+      accel -= 2;
+    if (accel < -20)
+      accel += 2;
   }
 }
 
-/*===============================================================*/
+
+
+/**
+* Main work for the dynamic displacement map.
+ * 
+ * Reads data from pix1, write to pix2.
+ *
+ * Useful datas for this FX are stored in ZoomFilterData.
+ * 
+ * If you think that this is a strange function name, let me say that a long time ago,
+ *  there has been a slow version and a gray-level only one. Then came these function,
+ *  fast and workin in RGB colorspace ! nice but it only was applying a zoom to the image.
+ *  So that is why you have this name, for the nostalgy of the first days of goom
+ *  when it was just a tiny program writen in Turbo Pascal on my i486...
+ */
 void
-zoomFilterFastRGB (GoomData * goomdata, ZoomFilterData * zf, int zfd_update)
+zoomFilterFastRGB (PluginInfo * goomInfo, Pixel * pix1, Pixel * pix2,
+    ZoomFilterData * zf, Uint resx, Uint resy, int switchIncr, float switchMult)
 {
-  guint32 prevX = goomdata->resolx;
-  guint32 prevY = goomdata->resoly;
+  Uint x, y;
 
-  guint32 *pix1 = goomdata->p1;
-  guint32 *pix2 = goomdata->p2;
-  unsigned int *pos10;
-  unsigned int **c;
+  ZoomFilterFXWrapperData *data =
+      (ZoomFilterFXWrapperData *) goomInfo->zoomFilter_fx.fx_data;
 
-  Uint x, y;
+  if (!BVAL (data->enabled_bp))
+    return;
 
-/*  static unsigned int prevX = 0, prevY = 0; */
+    /** changement de taille **/
+  if ((data->prevX != resx) || (data->prevY != resy)) {
+    data->prevX = resx;
+    data->prevY = resy;
+
+    if (data->brutS)
+      free (data->freebrutS);
+    data->brutS = 0;
+    if (data->brutD)
+      free (data->freebrutD);
+    data->brutD = 0;
+    if (data->brutT)
+      free (data->freebrutT);
+    data->brutT = 0;
+
+    data->middleX = resx / 2;
+    data->middleY = resy / 2;
+    data->mustInitBuffers = 1;
+    if (data->firedec)
+      free (data->firedec);
+    data->firedec = 0;
+  }
 
-#ifdef USE_ASM
-  expix1 = pix1;
-  expix2 = pix2;
-#else
-  Color couleur;
-  Color col1, col2, col3, col4;
-  Uint position;
-#endif
+  if (data->interlace_start != -2)
+    zf = NULL;
 
-  if ((goomdata->resolx != zf->res_x) || (goomdata->resoly != zf->res_y)) {
-    zoomFilterSetResolution (goomdata, zf);
+    /** changement de config **/
+  if (zf) {
+    data->reverse = zf->reverse;
+    data->general_speed = (float) (zf->vitesse - 128) / 128.0f;
+    if (data->reverse)
+      data->general_speed = -data->general_speed;
+    data->middleX = zf->middleX;
+    data->middleY = zf->middleY;
+    data->theMode = zf->mode;
+    data->hPlaneEffect = zf->hPlaneEffect;
+    data->vPlaneEffect = zf->vPlaneEffect;
+    data->waveEffect = zf->waveEffect;
+    data->hypercosEffect = zf->hypercosEffect;
+    data->noisify = zf->noisify;
+    data->interlace_start = 0;
   }
 
-  pos10 = zf->pos10;
-  c = zf->c;
-
-  if (zfd_update) {
-    guchar sqrtperte = zf->sqrtperte;
-    gint start_y = 0;
-
-    if (zf->reverse)
-      zf->vitesse = 256 - zf->vitesse;
-
-    /* generation du buffer */
-    for (y = 0; y < zf->res_y; y++) {
-      gint y_16 = y << 4;
-      gint max_px = (prevX - 1) * sqrtperte;
-      gint max_py = (prevY - 1) * sqrtperte;
-
-      for (x = 0; x < zf->res_x; x++) {
-        gint px, py;
-        guchar coefv, coefh;
-
-        /* calculer px et py en fonction de */
-        /*   x,y,middleX,middleY et theMode */
-        calculatePXandPY (goomdata, x, y, &px, &py);
-
-        if ((px == x << 4) && (py == y_16))
-          py += 8;
-
-        if ((py < 0) || (px < 0) || (py >= max_py) || (px >= max_px)) {
-#ifdef USE_ASM
-          coeffs[(y * prevX + x) * 2] = 0;
-          coeffs[(y * prevX + x) * 2 + 1] = 0;
-#else
-          pos10[start_y + x] = 0;
-          c[0][start_y + x] = 0;
-          c[1][start_y + x] = 0;
-          c[2][start_y + x] = 0;
-          c[3][start_y + x] = 0;
-#endif
-        } else {
-          int npx10;
-          int npy10;
-          int pos;
-
-          npx10 = (px / sqrtperte);
-          npy10 = (py / sqrtperte);
-
-/*                        if (npx10 >= prevX) fprintf(stderr,"error npx:%d",npx10);
-                          if (npy10 >= prevY) fprintf(stderr,"error npy:%d",npy10);
-*/
-          coefh = px % sqrtperte;
-          coefv = py % sqrtperte;
-#ifdef USE_ASM
-          pos = (y * prevX + x) * 2;
-          coeffs[pos] = (npx10 + prevX * npy10) * 4;
-
-          if (!(coefh || coefv))
-            coeffs[pos + 1] = (sqrtperte * sqrtperte - 1);
-          else
-            coeffs[pos + 1] = ((sqrtperte - coefh) * (sqrtperte - coefv));
-
-          coeffs[pos + 1] |= (coefh * (sqrtperte - coefv)) << 8;
-          coeffs[pos + 1] |= ((sqrtperte - coefh) * coefv) << 16;
-          coeffs[pos + 1] |= (coefh * coefv) << 24;
-#else
-          pos = start_y + x;
-          pos10[pos] = npx10 + prevX * npy10;
-
-          if (!(coefh || coefv))
-            c[0][pos] = sqrtperte * sqrtperte - 1;
-          else
-            c[0][pos] = (sqrtperte - coefh) * (sqrtperte - coefv);
-
-          c[1][pos] = coefh * (sqrtperte - coefv);
-          c[2][pos] = (sqrtperte - coefh) * coefv;
-          c[3][pos] = coefh * coefv;
-#endif
-        }
-      }
-      /* Advance start of line index */
-      start_y += prevX;
+
+  if (data->mustInitBuffers) {
+
+    data->mustInitBuffers = 0;
+    data->freebrutS =
+        (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
+    data->brutS =
+        (gint32 *) ((1 + ((uintptr_t) (data->freebrutS)) / 128) * 128);
+
+    data->freebrutD =
+        (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
+    data->brutD =
+        (gint32 *) ((1 + ((uintptr_t) (data->freebrutD)) / 128) * 128);
+
+    data->freebrutT =
+        (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
+    data->brutT =
+        (gint32 *) ((1 + ((uintptr_t) (data->freebrutT)) / 128) * 128);
+
+    data->buffratio = 0;
+
+    data->firedec = (int *) malloc (data->prevY * sizeof (int));
+    generateTheWaterFXHorizontalDirectionBuffer (goomInfo, data);
+
+    data->interlace_start = 0;
+    makeZoomBufferStripe (data, resy);
+
+    /* Copy the data from temp to dest and source */
+    memcpy (data->brutS, data->brutT, resx * resy * 2 * sizeof (int));
+    memcpy (data->brutD, data->brutT, resx * resy * 2 * sizeof (int));
+  }
+
+  /* generation du buffer de trans */
+  if (data->interlace_start == -1) {
+
+    /* sauvegarde de l'etat actuel dans la nouvelle source
+     * TODO: write that in MMX (has been done in previous version, but did not follow some new fonctionnalities) */
+    y = data->prevX * data->prevY * 2;
+    for (x = 0; x < y; x += 2) {
+      int brutSmypos = data->brutS[x];
+      int x2 = x + 1;
+
+      data->brutS[x] =
+          brutSmypos + (((data->brutD[x] -
+                  brutSmypos) * data->buffratio) >> BUFFPOINTNB);
+      brutSmypos = data->brutS[x2];
+      data->brutS[x2] =
+          brutSmypos + (((data->brutD[x2] -
+                  brutSmypos) * data->buffratio) >> BUFFPOINTNB);
     }
+    data->buffratio = 0;
   }
-#ifdef USE_ASM
-#ifdef MMX
-  zoom_width = prevX;
-  mmx_zoom_size = prevX * prevY;
-  mmx_zoom ();
-#endif
-
-#ifdef POWERPC
-  zoom_width = prevX;
-  if (useAltivec) {
-    ppcsize4 = ((unsigned int) (prevX * prevY)) / 4;
-    ppc_zoom_altivec ();
-  } else {
-    ppcsize4 = ((unsigned int) (prevX * prevY));
-    ppc_zoom ();
+
+  if (data->interlace_start == -1) {
+    signed int *tmp;
+
+    tmp = data->brutD;
+    data->brutD = data->brutT;
+    data->brutT = tmp;
+    tmp = data->freebrutD;
+    data->freebrutD = data->freebrutT;
+    data->freebrutT = tmp;
+    data->interlace_start = -2;
+  }
+
+  if (data->interlace_start >= 0) {
+    /* creation de la nouvelle destination */
+    makeZoomBufferStripe (data, resy / 16);
+  }
+
+  if (switchIncr != 0) {
+    data->buffratio += switchIncr;
+    if (data->buffratio > BUFFPOINTMASK)
+      data->buffratio = BUFFPOINTMASK;
+  }
+
+  if (switchMult != 1.0f) {
+    data->buffratio = (int) ((float) BUFFPOINTMASK * (1.0f - switchMult) +
+        (float) data->buffratio * switchMult);
   }
-#endif
-#else
-  for (position = 0; position < prevX * prevY; position++) {
-    getPixelRGB_ (pix1, pos10[position], &col1, goomdata->resolx,
-        goomdata->resoly);
-    getPixelRGB_ (pix1, pos10[position] + 1, &col2, goomdata->resolx,
-        goomdata->resoly);
-    getPixelRGB_ (pix1, pos10[position] + prevX, &col3, goomdata->resolx,
-        goomdata->resoly);
-    getPixelRGB_ (pix1, pos10[position] + prevX + 1, &col4, goomdata->resolx,
-        goomdata->resoly);
-
-    couleur.r = col1.r * c[0][position]
-        + col2.r * c[1][position]
-        + col3.r * c[2][position]
-        + col4.r * c[3][position];
-    couleur.r >>= zf->pertedec;
-
-    couleur.v = col1.v * c[0][position]
-        + col2.v * c[1][position]
-        + col3.v * c[2][position]
-        + col4.v * c[3][position];
-    couleur.v >>= zf->pertedec;
-
-    couleur.b = col1.b * c[0][position]
-        + col2.b * c[1][position]
-        + col3.b * c[2][position]
-        + col4.b * c[3][position];
-    couleur.b >>= zf->pertedec;
-
-    setPixelRGB_ (pix2, position, couleur, goomdata->resolx, goomdata->resoly);
+
+  data->zoom_width = data->prevX;
+
+  goomInfo->methods.zoom_filter (data->prevX, data->prevY, pix1, pix2,
+      data->brutS, data->brutD, data->buffratio, data->precalCoef);
+}
+
+static void
+generatePrecalCoef (int precalCoef[16][16])
+{
+  int coefh, coefv;
+
+  for (coefh = 0; coefh < 16; coefh++) {
+    for (coefv = 0; coefv < 16; coefv++) {
+
+      int i;
+      int diffcoeffh;
+      int diffcoeffv;
+
+      diffcoeffh = sqrtperte - coefh;
+      diffcoeffv = sqrtperte - coefv;
+
+      if (!(coefh || coefv)) {
+        i = 255;
+      } else {
+        int i1, i2, i3, i4;
+
+        i1 = diffcoeffh * diffcoeffv;
+        i2 = coefh * diffcoeffv;
+        i3 = diffcoeffh * coefv;
+        i4 = coefh * coefv;
+
+        // TODO: faire mieux...
+        if (i1)
+          i1--;
+        if (i2)
+          i2--;
+        if (i3)
+          i3--;
+        if (i4)
+          i4--;
+
+        i = (i1) | (i2 << 8) | (i3 << 16) | (i4 << 24);
+      }
+      precalCoef[coefh][coefv] = i;
+    }
   }
-#endif
 }
 
+/* VisualFX Wrapper */
+
+static void
+zoomFilterVisualFXWrapper_init (struct _VISUAL_FX *_this, PluginInfo * info)
+{
+  ZoomFilterFXWrapperData *data =
+      (ZoomFilterFXWrapperData *) malloc (sizeof (ZoomFilterFXWrapperData));
+
+  data->coeffs = 0;
+  data->freecoeffs = 0;
+  data->brutS = 0;
+  data->freebrutS = 0;
+  data->brutD = 0;
+  data->freebrutD = 0;
+  data->brutT = 0;
+  data->freebrutT = 0;
+  data->prevX = 0;
+  data->prevY = 0;
+
+  data->mustInitBuffers = 1;
+  data->interlace_start = -2;
+
+  data->general_speed = 0.0f;
+  data->reverse = 0;
+  data->theMode = AMULETTE_MODE;
+  data->waveEffect = 0;
+  data->hypercosEffect = 0;
+  data->vPlaneEffect = 0;
+  data->hPlaneEffect = 0;
+  data->noisify = 2;
+
+    /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
+  data->buffratio = 0;
+  data->firedec = 0;
+
+  data->wave = data->wavesp = 0;
+
+  data->enabled_bp = secure_b_param ("Enabled", 1);
+
+  data->params = plugin_parameters ("Zoom Filter", 1);
+  data->params.params[0] = &data->enabled_bp;
+
+  _this->params = &data->params;
+  _this->fx_data = (void *) data;
+
+    /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
+  generatePrecalCoef (data->precalCoef);
+}
+
+static void
+zoomFilterVisualFXWrapper_free (struct _VISUAL_FX *_this)
+{
+  free (_this->fx_data);
+}
+
+static void
+zoomFilterVisualFXWrapper_apply (struct _VISUAL_FX *_this, Pixel * src,
+    Pixel * dest, PluginInfo * info)
+{
+}
+
+VisualFX
+zoomFilterVisualFXWrapper_create (void)
+{
+  VisualFX fx;
+
+  fx.init = zoomFilterVisualFXWrapper_init;
+  fx.free = zoomFilterVisualFXWrapper_free;
+  fx.apply = zoomFilterVisualFXWrapper_apply;
+  return fx;
+}
+
+
+/* TODO : MOVE THIS AWAY */
 
 void
-pointFilter (GoomData * goomdata, Color c,
-    float t1, float t2, float t3, float t4, Uint cycle)
+pointFilter (PluginInfo * goomInfo, Pixel * pix1, Color c, float t1, float t2,
+    float t3, float t4, Uint cycle)
 {
-  Uint *pix1 = goomdata->p1;
-  ZoomFilterData *zf = goomdata->zfd;
-  Uint x = (Uint) (zf->middleX + (int) (t1 * cos ((float) cycle / t3)));
-  Uint y = (Uint) (zf->middleY + (int) (t2 * sin ((float) cycle / t4)));
-
-  if ((x > 1) && (y > 1) && (x < goomdata->resolx - 2)
-      && (y < goomdata->resoly - 2)) {
-    setPixelRGB (pix1, x + 1, y, c, goomdata->resolx, goomdata->resoly);
-    setPixelRGB (pix1, x, y + 1, c, goomdata->resolx, goomdata->resoly);
-    setPixelRGB (pix1, x + 1, y + 1, WHITE, goomdata->resolx, goomdata->resoly);
-    setPixelRGB (pix1, x + 2, y + 1, c, goomdata->resolx, goomdata->resoly);
-    setPixelRGB (pix1, x + 1, y + 2, c, goomdata->resolx, goomdata->resoly);
+  Uint x = (Uint) ((int) (goomInfo->screen.width / 2)
+      + (int) (t1 * cos ((float) cycle / t3)));
+  Uint y = (Uint) ((int) (goomInfo->screen.height / 2)
+      + (int) (t2 * sin ((float) cycle / t4)));
+
+  if ((x > 1) && (y > 1) && (x < goomInfo->screen.width - 2)
+      && (y < goomInfo->screen.height - 2)) {
+    setPixelRGB (goomInfo, pix1, x + 1, y, c);
+    setPixelRGB (goomInfo, pix1, x, y + 1, c);
+    setPixelRGB (goomInfo, pix1, x + 1, y + 1, WHITE);
+    setPixelRGB (goomInfo, pix1, x + 2, y + 1, c);
+    setPixelRGB (goomInfo, pix1, x + 1, y + 2, c);
   }
 }
diff --git a/gst/goom/filters.h b/gst/goom/filters.h
deleted file mode 100644 (file)
index 65eb3e2..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef FILTERS_H
-#define FILTERS_H
-
-#include <glib.h>
-
-#include "graphic.h"
-#include "goom_core.h"
-
-#define NORMAL_MODE 0
-#define WAVE_MODE 1
-#define CRYSTAL_BALL_MODE 2
-#define SCRUNCH_MODE 3
-#define AMULETTE_MODE 4
-#define WATER_MODE 5
-
-struct ZoomFilterData
-{
-  int vitesse;
-  unsigned char pertedec;
-  unsigned char sqrtperte;
-  int middleX;
-  int middleY;
-  char reverse;
-  char mode;
-        /** @since June 2001 */
-  int hPlaneEffect;
-  int vPlaneEffect;
-  char noisify;
-
-  guint32 res_x;
-  guint32 res_y;
-  guint32 buffsize;
-
-  guint32 *buffer;
-  guint32 *pos10;
-  guint32 *c[4];
-  int     *firedec;
-
-  int     wave;
-  int     wavesp;
-};
-
-void pointFilter(GoomData *goomdata, Color c,
-                                 float t1, float t2, float t3, float t4,
-                                 guint32 cycle);
-
-/* filtre de zoom :
- le contenu de pix1 est copie dans pix2, avec l'effet appliqué
- midx et midy represente le centre du zoom
-
-void zoomFilter(Uint *pix1, Uint *pix2, Uint middleX, Uint middleY);
-void zoomFilterRGB(Uint *pix1,
-Uint *pix2,
-Uint middleX,
-Uint middleY);
-*/
-
-ZoomFilterData *zoomFilterNew ();
-void zoomFilterDestroy (ZoomFilterData *zf);
-void zoomFilterFastRGB (GoomData *goomdata, ZoomFilterData *zf,
-                           int zfd_update);
-
-/* filtre sin :
- le contenu de pix1 est copie dans pix2, avec l'effet appliqué
- cycle est la variable de temps.
- mode vaut SIN_MUL ou SIN_ADD
- rate est le pourcentage de l'effet appliqué
- lenght : la longueur d'onde (1..10) [5]
- speed : la vitesse (1..100) [10]
-*/
-/*
-void sinFilter(Uint *pix1,Uint *pix2,
-                           Uint cycle,
-                           Uint mode,
-                           Uint rate,
-                           char lenght,
-                           Uint speed);
-*/
-
-#define SIN_MUL 1
-#define SIN_ADD 2
-
-#endif
index 337de56c39468f1e6bdce0fd07afa9209b875a6a..765f1588e110cd4a1bbe08f5126498f76bc400fe 100644 (file)
 
 .data
 
+chaine:
+       .string "pos = %d\n\0"
+       .long 0x0
+               
 thezero:
        .long 0x00000000
        .long 0x00000000
 
-
 .text
 
 .globl mmx_zoom                ;// name of the function to call by C program
-.extern coeffs         ;// the transformation buffer
+/* .extern coeffs              ;// the transformation buffer */
 .extern expix1,expix2 ;// the source and destination buffer
 .extern mmx_zoom_size, zoom_width ;// size of the buffers
 
+.extern brutS,brutD,buffratio,precalCoef,prevX,prevY
+
+#define PERTEMASK 15
+/* faire : a / sqrtperte <=> a >> PERTEDEC*/
+#define PERTEDEC 4
+
 .align 16
 mmx_zoom:
 
-push %ebp
-push %esp
+               pushl %ebp
+               movl %esp,%ebp
+               subl $12,%esp
 
-;// initialisation du mm7 Ã  zero
-movq (thezero), %mm7
+               movl prevX,%eax
+               decl %eax
+               sarl $4,%eax
+               movl %eax,-4(%ebp)
 
-movl zoom_width, %eax
-movl $4, %ebx
-mull %ebx
-movl %eax, %ebp
+               movl prevY,%eax
+               decl %eax
+               sarl $4,%eax
+               movl %eax,-8(%ebp)
+
+;// initialisation du mm7 Ã  zero
+               movq (thezero), %mm7
 
-movl (coeffs), %eax
-movl (expix1), %edx
-movl (expix2), %ebx
-movl $10, %edi
 movl mmx_zoom_size, %ecx
+decl %ecx
 
 .while:
        ;// esi <- nouvelle position
-       movl (%eax), %esi
-       leal (%edx, %esi), %esi
+       movl brutS, %eax
+       leal (%eax, %ecx, 8),%eax
+
+       movl (%eax),%edx /* = brutS.px (brutSmypos) */
+       movl 4(%eax),%eax /* = brutS.py */
+
+       movl brutD,%ebx
+       leal (%ebx, %ecx, 8),%ebx
+       movl (%ebx),%esi
+       subl %edx, %esi
+       imull buffratio,%esi
+       sarl $16,%esi
+       addl %edx,%esi /* esi = px */
+
+       /* eax contient deja brutS.py = le nouveau brutSmypos*/
+       /* ebx pointe sur brutD[myPos] */
+       movl 4(%ebx),%edi
+       subl %eax,%edi
+       imull buffratio,%edi
+       sarl $16,%edi
+       addl %eax,%edi /* edi = py */
+
+/*             pushl %eax
+               pushl %ebx*/
+/*             popl %ebx
+               popl %eax*/
+               
+       movl %esi,%eax
+       andl $15,%eax /* eax = coefh */
+       movl %edi,%ebx
+       andl $15,%ebx /* ebx = coefv */
+
+       leal 0(,%ebx,4),%ebx
+       sall $6,%eax
+       addl %ebx,%eax
+       movl $precalCoef,%ebx
+/*     movd (%eax,%ebx),%mm6*/ /* mm6 = coeffs */
+
+       cmpl -8(%ebp),%edi
+       jge .then1
+       cmpl -4(%ebp),%esi
+       jge .then1
+
+       sarl $4,%esi
+       sarl $4,%edi
+       imull zoom_width,%edi
+       leal (%esi,%edi),%esi
+       jmp .finsi1
+
+.then1:
+       movl $0,%esi
+.finsi1:
+
+       /** apres ce calcul, %esi = pos, %mm6 = coeffs **/
+/*     pushl %esi
+       pushl $chaine
+       call printf
+       addl $8,%esp*/
+
+       movl expix1,%eax
 
        ;// recuperation des deux premiers pixels dans mm0 et mm1
-       movq (%esi), %mm0               /* b1-v1-r1-a1-b2-v2-r2-a2 */
-       movq %mm0, %mm1                 /* b1-v1-r1-a1-b2-v2-r2-a2 */
+/*     movq (%eax,%esi,4), %mm0                /* b1-v1-r1-a1-b2-v2-r2-a2 */
+       movq %mm0, %mm1                         /* b1-v1-r1-a1-b2-v2-r2-a2 */
 
-       ;// recuperation des 4 coefficients
-       movd 4(%eax), %mm6              /* ??-??-??-??-c4-c3-c2-c1 */
        ;// depackage du premier pixel
        punpcklbw %mm7, %mm0    /* 00-b2-00-v2-00-r2-00-a2 */
 
@@ -87,8 +155,11 @@ movl mmx_zoom_size, %ecx
        punpcklbw %mm7, %mm4    /* 00-c3-00-c3-00-c3-00-c3 */
        punpckhbw %mm7, %mm5    /* 00-c4-00-c4-00-c4-00-c4 */
 
+       /* ajouter la longueur de ligne a esi */
+       addl prevX,%esi
+               
        ;// recuperation des 2 derniers pixels
-       movq (%esi,%ebp), %mm1
+/*     movq (%eax,%esi,4), %mm1*/
        movq %mm1, %mm2
        
        ;// depackage des pixels
@@ -108,23 +179,22 @@ movl mmx_zoom_size, %ecx
        packuswb %mm7, %mm0
        
        ;// passage au suivant
-       leal 8(%eax), %eax
 
-       decl %ecx
        ;// enregistrement du resultat
-       movd %mm0, (%ebx)
-       leal 4(%ebx), %ebx
+       movl expix2,%eax
+/*     movd %mm0,(%eax,%ecx,4)*/
 
+       decl %ecx
        ;// test de fin du tantque
        cmpl $0, %ecx                           ;// 400x300
 
-jz .fin_while
-jmp .while
+       jz .fin_while
+       jmp .while
 
 .fin_while:
-emms
+       emms
 
-pop %esp
-pop %ebp
+       movl %ebp,%esp
+       popl %ebp
 
-ret                  ;//The End
+       ret                  ;//The End
diff --git a/gst/goom/flying_stars_fx.c b/gst/goom/flying_stars_fx.c
new file mode 100644 (file)
index 0000000..c323c7c
--- /dev/null
@@ -0,0 +1,341 @@
+#include "goom_fx.h"
+#include "goom_plugin_info.h"
+#include "goom_tools.h"
+
+#include "mathtools.h"
+
+/* TODO:-- FAIRE PROPREMENT... BOAH... */
+#define NCOL 15
+
+/*static const int colval[] = {
+0xfdf6f5,
+0xfae4e4,
+0xf7d1d1,
+0xf3b6b5,
+0xefa2a2,
+0xec9190,
+0xea8282,
+0xe87575,
+0xe46060,
+0xe14b4c,
+0xde3b3b,
+0xdc2d2f,
+0xd92726,
+0xd81619,
+0xd50c09,
+0
+};
+*/
+static const int colval[] = {
+  0x1416181a,
+  0x1419181a,
+  0x141f181a,
+  0x1426181a,
+  0x142a181a,
+  0x142f181a,
+  0x1436181a,
+  0x142f1819,
+  0x14261615,
+  0x13201411,
+  0x111a100a,
+  0x0c180508,
+  0x08100304,
+  0x00050101,
+  0x0
+};
+
+
+/* The different modes of the visual FX.
+ * Put this values on fx_mode */
+#define FIREWORKS_FX 0
+#define RAIN_FX 1
+#define FOUNTAIN_FX 2
+#define LAST_FX 3
+
+typedef struct _FS_STAR
+{
+  float x, y;
+  float vx, vy;
+  float ax, ay;
+  float age, vage;
+} Star;
+
+typedef struct _FS_DATA
+{
+
+  int fx_mode;
+  int nbStars;
+
+  int maxStars;
+  Star *stars;
+
+  float min_age;
+  float max_age;
+
+  PluginParam min_age_p;
+  PluginParam max_age_p;
+  PluginParam nbStars_p;
+  PluginParam nbStars_limit_p;
+  PluginParam fx_mode_p;
+
+  PluginParameters params;
+} FSData;
+
+static void
+fs_init (VisualFX * _this, PluginInfo * info)
+{
+
+  FSData *data;
+
+  data = (FSData *) malloc (sizeof (FSData));
+
+  data->fx_mode = FIREWORKS_FX;
+  data->maxStars = 4096;
+  data->stars = (Star *) malloc (data->maxStars * sizeof (Star));
+  data->nbStars = 0;
+
+  data->max_age_p = secure_i_param ("Fireworks Smallest Bombs");
+  IVAL (data->max_age_p) = 80;
+  IMIN (data->max_age_p) = 0;
+  IMAX (data->max_age_p) = 100;
+  ISTEP (data->max_age_p) = 1;
+
+  data->min_age_p = secure_i_param ("Fireworks Largest Bombs");
+  IVAL (data->min_age_p) = 99;
+  IMIN (data->min_age_p) = 0;
+  IMAX (data->min_age_p) = 100;
+  ISTEP (data->min_age_p) = 1;
+
+  data->nbStars_limit_p = secure_i_param ("Max Number of Particules");
+  IVAL (data->nbStars_limit_p) = 512;
+  IMIN (data->nbStars_limit_p) = 0;
+  IMAX (data->nbStars_limit_p) = data->maxStars;
+  ISTEP (data->nbStars_limit_p) = 64;
+
+  data->fx_mode_p = secure_i_param ("FX Mode");
+  IVAL (data->fx_mode_p) = data->fx_mode;
+  IMIN (data->fx_mode_p) = 1;
+  IMAX (data->fx_mode_p) = 3;
+  ISTEP (data->fx_mode_p) = 1;
+
+  data->nbStars_p = secure_f_feedback ("Number of Particules (% of Max)");
+
+  data->params = plugin_parameters ("Particule System", 7);
+  data->params.params[0] = &data->fx_mode_p;
+  data->params.params[1] = &data->nbStars_limit_p;
+  data->params.params[2] = 0;
+  data->params.params[3] = &data->min_age_p;
+  data->params.params[4] = &data->max_age_p;
+  data->params.params[5] = 0;
+  data->params.params[6] = &data->nbStars_p;
+
+  _this->params = &data->params;
+  _this->fx_data = (void *) data;
+}
+
+static void
+fs_free (VisualFX * _this)
+{
+  free (_this->fx_data);
+}
+
+
+/**
+ * Cree une nouvelle 'bombe', c'est a dire une particule appartenant a une fusee d'artifice.
+ */
+static void
+addABomb (FSData * fs, int mx, int my, float radius, float vage, float gravity,
+    PluginInfo * info)
+{
+
+  int i = fs->nbStars;
+  float ro;
+  int theta;
+
+  if (fs->nbStars >= fs->maxStars)
+    return;
+  fs->nbStars++;
+
+  fs->stars[i].x = mx;
+  fs->stars[i].y = my;
+
+  ro = radius * (float) goom_irand (info->gRandom, 100) / 100.0f;
+  ro *= (float) goom_irand (info->gRandom, 100) / 100.0f + 1.0f;
+  theta = goom_irand (info->gRandom, 256);
+
+  fs->stars[i].vx = ro * cos256[theta];
+  fs->stars[i].vy = -0.2f + ro * sin256[theta];
+
+  fs->stars[i].ax = 0;
+  fs->stars[i].ay = gravity;
+
+  fs->stars[i].age = 0;
+  if (vage < fs->min_age)
+    vage = fs->min_age;
+  fs->stars[i].vage = vage;
+}
+
+
+/**
+ * Met a jour la position et vitesse d'une particule.
+ */
+static void
+updateStar (Star * s)
+{
+  s->x += s->vx;
+  s->y += s->vy;
+  s->vx += s->ax;
+  s->vy += s->ay;
+  s->age += s->vage;
+}
+
+
+/**
+ * Ajoute de nouvelles particules au moment d'un evenement sonore.
+ */
+static void
+fs_sound_event_occured (VisualFX * _this, PluginInfo * info)
+{
+
+  FSData *data = (FSData *) _this->fx_data;
+  int i;
+
+  int max =
+      (int) ((1.0f + info->sound.goomPower) * goom_irand (info->gRandom,
+          150)) + 100;
+  float radius =
+      (1.0f + info->sound.goomPower) * (float) (goom_irand (info->gRandom,
+          150) + 50) / 300;
+  int mx;
+  int my;
+  float vage, gravity = 0.02f;
+
+  switch (data->fx_mode) {
+    case FIREWORKS_FX:
+    {
+      double dx, dy;
+
+      do {
+        mx = goom_irand (info->gRandom, info->screen.width);
+        my = goom_irand (info->gRandom, info->screen.height);
+        dx = (mx - info->screen.width / 2);
+        dy = (my - info->screen.height / 2);
+      } while (dx * dx + dy * dy <
+          (info->screen.height / 2) * (info->screen.height / 2));
+      vage = data->max_age * (1.0f - info->sound.goomPower);
+    }
+      break;
+    case RAIN_FX:
+      mx = goom_irand (info->gRandom, info->screen.width);
+      if (mx > info->screen.width / 2)
+        mx = info->screen.width;
+      else
+        mx = 0;
+      my = -(info->screen.height / 3) - goom_irand (info->gRandom,
+          info->screen.width / 3);
+      radius *= 1.5;
+      vage = 0.002f;
+      break;
+    case FOUNTAIN_FX:
+      my = info->screen.height + 2;
+      vage = 0.001f;
+      radius += 1.0f;
+      mx = info->screen.width / 2;
+      gravity = 0.04f;
+      break;
+    default:
+      return;
+      /* my = i R A N D (info->screen.height); vage = 0.01f; */
+  }
+
+  radius *= info->screen.height / 200.0f;       /* why 200 ? because the FX was developped on 320x200 */
+  max *= info->screen.height / 200.0f;
+
+  if (info->sound.timeSinceLastBigGoom < 1) {
+    radius *= 1.5;
+    max *= 2;
+  }
+  for (i = 0; i < max; ++i)
+    addABomb (data, mx, my, radius, vage, gravity, info);
+}
+
+
+/**
+ * Main methode of the FX.
+ */
+static void
+fs_apply (VisualFX * _this, Pixel * src, Pixel * dest, PluginInfo * info)
+{
+
+  int i;
+  int col;
+  FSData *data = (FSData *) _this->fx_data;
+
+  /* Get the new parameters values */
+  data->min_age = 1.0f - (float) IVAL (data->min_age_p) / 100.0f;
+  data->max_age = 1.0f - (float) IVAL (data->max_age_p) / 100.0f;
+  FVAL (data->nbStars_p) = (float) data->nbStars / (float) data->maxStars;
+  data->nbStars_p.change_listener (&data->nbStars_p);
+  data->maxStars = IVAL (data->nbStars_limit_p);
+  data->fx_mode = IVAL (data->fx_mode_p);
+
+  /* look for events */
+  if (info->sound.timeSinceLastGoom < 1) {
+    fs_sound_event_occured (_this, info);
+    if (goom_irand (info->gRandom, 20) == 1) {
+      IVAL (data->fx_mode_p) = goom_irand (info->gRandom, (LAST_FX * 3));
+      data->fx_mode_p.change_listener (&data->fx_mode_p);
+    }
+  }
+
+  /* update particules */
+  for (i = 0; i < data->nbStars; ++i) {
+    updateStar (&data->stars[i]);
+
+    /* dead particule */
+    if (data->stars[i].age >= NCOL)
+      continue;
+
+    /* choose the color of the particule */
+    col = colval[(int) data->stars[i].age];
+
+    /* draws the particule */
+    info->methods.draw_line (dest, (int) data->stars[i].x,
+        (int) data->stars[i].y,
+        (int) (data->stars[i].x - data->stars[i].vx * 6),
+        (int) (data->stars[i].y - data->stars[i].vy * 6), col,
+        (int) info->screen.width, (int) info->screen.height);
+    info->methods.draw_line (dest, (int) data->stars[i].x,
+        (int) data->stars[i].y,
+        (int) (data->stars[i].x - data->stars[i].vx * 2),
+        (int) (data->stars[i].y - data->stars[i].vy * 2), col,
+        (int) info->screen.width, (int) info->screen.height);
+  }
+
+  /* look for dead particules */
+  for (i = 0; i < data->nbStars;) {
+
+    if ((data->stars[i].x > info->screen.width + 64)
+        || ((data->stars[i].vy >= 0)
+            && (data->stars[i].y - 16 * data->stars[i].vy >
+                info->screen.height))
+        || (data->stars[i].x < -64)
+        || (data->stars[i].age >= NCOL)) {
+      data->stars[i] = data->stars[data->nbStars - 1];
+      data->nbStars--;
+    } else
+      ++i;
+  }
+}
+
+VisualFX
+flying_star_create (void)
+{
+  VisualFX vfx = {
+  init:fs_init,
+  free:fs_free,
+  apply:fs_apply,
+  fx_data:0
+  };
+  return vfx;
+}
diff --git a/gst/goom/gfontlib.c b/gst/goom/gfontlib.c
new file mode 100644 (file)
index 0000000..52d3e54
--- /dev/null
@@ -0,0 +1,260 @@
+#include "goom_config.h"
+#include "gfontrle.h"
+#include "gfontlib.h"
+#include <string.h>
+#include <stdlib.h>
+
+static Pixel ***font_chars;
+static int *font_width;
+static int *font_height;
+static Pixel ***small_font_chars;
+static int *small_font_width;
+static int *small_font_height;
+
+void
+gfont_load (void)
+{
+  unsigned char *gfont;
+  unsigned int i = 0, j = 0;
+  unsigned int nba = 0;
+  unsigned int current = 32;
+  int *font_pos;
+
+  /* decompress le rle */
+
+
+
+  gfont = malloc (the_font.width * the_font.height * the_font.bytes_per_pixel);
+  while (i < the_font.rle_size) {
+    unsigned char c = the_font.rle_pixel[i++];
+
+    if (c == 0) {
+      unsigned int nb = the_font.rle_pixel[i++];
+
+      while (nb--)
+        gfont[j++] = 0;
+    } else
+      gfont[j++] = c;
+  }
+
+  /* determiner les positions de chaque lettre. */
+
+  font_height = calloc (256, sizeof (int));
+  small_font_height = calloc (256, sizeof (int));
+  font_width = calloc (256, sizeof (int));
+  small_font_width = calloc (256, sizeof (int));
+  font_chars = calloc (256, sizeof (int **));
+  small_font_chars = calloc (256, sizeof (int **));
+  font_pos = calloc (256, sizeof (int));
+
+  for (i = 0; i < the_font.width; i++) {
+    unsigned char a = gfont[i * 4 + 3];
+
+    if (a)
+      nba++;
+    else
+      nba = 0;
+    if (nba == 2) {
+      font_width[current] = i - font_pos[current];
+      small_font_width[current] = font_width[current] / 2;
+      font_pos[++current] = i;
+      font_height[current] = the_font.height - 2;
+      small_font_height[current] = font_height[current] / 2;
+    }
+  }
+  font_pos[current] = 0;
+  font_height[current] = 0;
+  small_font_height[current] = 0;
+
+  /* charger les lettres et convertir au format de la machine */
+
+  for (i = 33; i < current; i++) {
+    int x;
+    int y;
+    font_chars[i] = malloc (font_height[i] * sizeof (int *));
+    small_font_chars[i] = malloc (font_height[i] * sizeof (int *) / 2);
+    for (y = 0; y < font_height[i]; y++) {
+      font_chars[i][y] = malloc (font_width[i] * sizeof (int));
+      for (x = 0; x < font_width[i]; x++) {
+        unsigned int r, g, b, a;
+
+        r = gfont[(y + 2) * (the_font.width * 4) + (x * 4 + font_pos[i] * 4)];
+        g = gfont[(y + 2) * (the_font.width * 4) + (x * 4 + font_pos[i] * 4 +
+                1)];
+        b = gfont[(y + 2) * (the_font.width * 4) + (x * 4 + font_pos[i] * 4 +
+                2)];
+        a = gfont[(y + 2) * (the_font.width * 4) + (x * 4 + font_pos[i] * 4 +
+                3)];
+        font_chars[i][y][x].val =
+            (r << (ROUGE * 8)) | (g << (VERT * 8)) | (b << (BLEU *
+                8)) | (a << (ALPHA * 8));
+      }
+    }
+    for (y = 0; y < font_height[i] / 2; y++) {
+      small_font_chars[i][y] = malloc (font_width[i] * sizeof (int) / 2);
+      for (x = 0; x < font_width[i] / 2; x++) {
+        unsigned int r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3, r4, g4, b4,
+            a4;
+        r1 = gfont[2 * (y + 1) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4)];
+        g1 = gfont[2 * (y + 1) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 1)];
+        b1 = gfont[2 * (y + 1) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 2)];
+        a1 = gfont[2 * (y + 1) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 3)];
+        r2 = gfont[(2 * y + 3) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 4)];
+        g2 = gfont[(2 * y + 3) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 5)];
+        b2 = gfont[(2 * y + 3) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 6)];
+        a2 = gfont[(2 * y + 3) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 7)];
+        r3 = gfont[(2 * y + 3) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4)];
+        g3 = gfont[(2 * y + 3) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 1)];
+        b3 = gfont[(2 * y + 3) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 2)];
+        a3 = gfont[(2 * y + 3) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 3)];
+        r4 = gfont[2 * (y + 1) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 4)];
+        g4 = gfont[2 * (y + 1) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 5)];
+        b4 = gfont[2 * (y + 1) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 6)];
+        a4 = gfont[2 * (y + 1) * (the_font.width * 4) + (x * 8 +
+                font_pos[i] * 4 + 7)];
+        small_font_chars[i][y][x].val =
+            (((r1 + r2 + r3 + r4) >> 2) << (ROUGE * 8)) | (((g1 + g2 + g3 +
+                    g4) >> 2) << (VERT * 8)) | (((b1 + b2 + b3 +
+                    b4) >> 2) << (BLEU * 8)) | (((a1 + a2 + a3 +
+                    a4) >> 2) << (ALPHA * 8));
+      }
+    }
+  }
+
+  /* definir les lettres restantes */
+
+  for (i = 0; i < 256; i++) {
+    if (font_chars[i] == 0) {
+      font_chars[i] = font_chars[42];
+      small_font_chars[i] = small_font_chars[42];
+      font_width[i] = font_width[42];
+      font_pos[i] = font_pos[42];
+      font_height[i] = font_height[42];
+      small_font_width[i] = small_font_width[42];
+      small_font_height[i] = small_font_height[42];
+    }
+  }
+
+  font_width[32] = (the_font.height / 2) - 1;
+  small_font_width[32] = font_width[32] / 2;
+  font_chars[32] = 0;
+  small_font_chars[32] = 0;
+}
+
+void
+goom_draw_text (Pixel * buf, int resolx, int resoly,
+    int x, int y, const char *str, float charspace, int center)
+{
+  float fx = (float) x;
+  int fin = 0;
+
+  Pixel ***cur_font_chars;
+  int *cur_font_width;
+  int *cur_font_height;
+
+  if (resolx > 320) {
+    /* printf("use big\n"); */
+    cur_font_chars = font_chars;
+    cur_font_width = font_width;
+    cur_font_height = font_height;
+  } else {
+    /* printf ("use small\n"); */
+    cur_font_chars = small_font_chars;
+    cur_font_width = small_font_width;
+    cur_font_height = small_font_height;
+  }
+
+  if (cur_font_chars == NULL)
+    return;
+
+  if (center) {
+    unsigned char *tmp = (unsigned char *) str;
+    float lg = -charspace;
+
+    while (*tmp != '\0')
+      lg += cur_font_width[*(tmp++)] + charspace;
+
+    fx -= lg / 2;
+  }
+
+  while (!fin) {
+    unsigned char c = *str;
+
+    x = (int) fx;
+
+    if (c == '\0')
+      fin = 1;
+    else if (cur_font_chars[c] == 0) {
+      fx += cur_font_width[c] + charspace;
+    } else {
+      int xx, yy;
+      int xmin = x;
+      int xmax = x + cur_font_width[c];
+      int ymin = y - cur_font_height[c];
+      int ymax = y;
+
+      yy = ymin;
+
+      if (xmin < 0)
+        xmin = 0;
+
+      if (xmin >= resolx - 1)
+        return;
+
+      if (xmax >= (int) resolx)
+        xmax = resolx - 1;
+
+      if (yy < 0)
+        yy = 0;
+
+      if (yy <= (int) resoly - 1) {
+        if (ymax >= (int) resoly - 1)
+          ymax = resoly - 1;
+
+        for (; yy < ymax; yy++)
+          for (xx = xmin; xx < xmax; xx++) {
+            Pixel color = cur_font_chars[c][yy - ymin][xx - x];
+            Pixel transparency;
+
+            transparency.val = color.val & A_CHANNEL;
+            if (transparency.val) {
+              if (transparency.val == A_CHANNEL)
+                buf[yy * resolx + xx] = color;
+              else {
+                Pixel back = buf[yy * resolx + xx];
+                unsigned int a1 = color.channels.a;
+                unsigned int a2 = 255 - a1;
+
+                buf[yy * resolx + xx].channels.r =
+                    (unsigned char) ((((unsigned int) color.channels.r * a1) +
+                        ((unsigned int) back.channels.r * a2)) >> 8);
+                buf[yy * resolx + xx].channels.g =
+                    (unsigned char) ((((unsigned int) color.channels.g * a1) +
+                        ((unsigned int) back.channels.g * a2)) >> 8);
+                buf[yy * resolx + xx].channels.b =
+                    (unsigned char) ((((unsigned int) color.channels.b * a1) +
+                        ((unsigned int) back.channels.b * a2)) >> 8);
+              }
+            }
+          }
+      }
+      fx += cur_font_width[c] + charspace;
+    }
+    str++;
+  }
+}
diff --git a/gst/goom/gfontlib.h b/gst/goom/gfontlib.h
new file mode 100644 (file)
index 0000000..0520b7d
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _GFONTLIB_H
+#define _GFONTLIB_H
+
+#include "goom_graphic.h"
+
+void gfont_load (void);
+void goom_draw_text (Pixel * buf,int resolx,int resoly, int x, int y,
+               const char *str, float chspace, int center);
+
+#endif
diff --git a/gst/goom/gfontrle.c b/gst/goom/gfontrle.c
new file mode 100644 (file)
index 0000000..e57b494
--- /dev/null
@@ -0,0 +1,3080 @@
+/* RGBA C-Source image dump (with zRLE compression) */
+
+const struct
+{
+  unsigned int width;
+  unsigned int height;
+  unsigned int bytes_per_pixel;
+  unsigned int rle_size;
+  unsigned char rle_pixel[49725];
+} the_font = {
+  1277, 21, 4, 49725, {
+121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255,
+        0, 8, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 36, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 52, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        52, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 52, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 12, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 20, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        20, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 52, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 12, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        36, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 12, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 36, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 12, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 12, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 36, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        36, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 36, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        36, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 36, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        12, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 36, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        52, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 52, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 20, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 36, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        20, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 36, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 36, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 12, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 28, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        12, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 28, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 12, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        52, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 28, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 52, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 44, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 0, 44, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17,
+        164, 255, 121, 17, 164, 255, 0, 28, 121, 17, 164, 0, 1, 121, 17,
+        164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 12, 121, 17, 164,
+        0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0,
+        28, 121, 17, 164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 121,
+        17, 164, 255, 121, 17, 164, 255, 121, 17, 164, 255, 0, 56, 121, 17,
+        164, 0, 1, 121, 17, 164, 255, 121, 17, 164, 255, 13, 4, 17, 0, 1,
+        13, 4, 17, 0, 1, 13, 4, 17, 0, 1, 16, 5, 22, 0, 13, 16, 5, 22, 0, 1,
+        14, 4, 19, 0, 1, 16, 5, 22, 0, 41, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1,
+        16, 5, 22, 0, 57, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0,
+        49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 57, 16, 5, 22,
+        0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 57, 16, 5, 22, 0, 1, 14, 4, 19,
+        0, 1, 16, 5, 22, 0, 17, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22,
+        0, 25, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 25, 16, 5,
+        22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 57, 16, 5, 22, 0, 1, 14, 4,
+        19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5,
+        22, 0, 17, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 41, 16,
+        5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 17, 16, 5, 22, 0, 1, 14,
+        4, 19, 0, 1, 16, 5, 22, 0, 41, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16,
+        5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49,
+        16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1,
+        14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1,
+        16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0,
+        49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22,
+        0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19,
+        0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22,
+        0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 17, 16, 5,
+        22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 17, 16, 5, 22, 0, 1, 14, 4,
+        19, 0, 1, 16, 5, 22, 0, 41, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5,
+        22, 0, 41, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 41, 16,
+        5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14,
+        4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16,
+        5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49,
+        16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1,
+        14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1,
+        16, 5, 22, 0, 41, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0,
+        41, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22,
+        0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19,
+        0, 1, 16, 5, 22, 0, 17, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22,
+        0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5,
+        22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 41, 16, 5, 22, 0, 1, 14, 4,
+        19, 0, 1, 16, 5, 22, 0, 57, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5,
+        22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16,
+        5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14,
+        4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16,
+        5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49,
+        16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1,
+        14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1,
+        16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0,
+        57, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22,
+        0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19,
+        0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22,
+        0, 25, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 41, 16, 5,
+        22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 25, 16, 5, 22, 0, 1, 14, 4,
+        19, 0, 1, 16, 5, 22, 0, 41, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5,
+        22, 0, 41, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 17, 16,
+        5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14,
+        4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16,
+        5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49,
+        16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1,
+        14, 4, 19, 0, 1, 16, 5, 22, 0, 33, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1,
+        16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0,
+        49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 17, 16, 5, 22,
+        0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 33, 16, 5, 22, 0, 1, 14, 4, 19,
+        0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22,
+        0, 17, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 57, 16, 5,
+        22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4,
+        19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5,
+        22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16,
+        5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14,
+        4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16,
+        5, 22, 0, 33, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49,
+        16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22, 0, 1,
+        14, 4, 19, 0, 1, 16, 5, 22, 0, 57, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1,
+        16, 5, 22, 0, 49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0,
+        49, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 49, 16, 5, 22,
+        0, 1, 14, 4, 19, 0, 1, 16, 5, 22, 0, 33, 16, 5, 22, 0, 1, 14, 4, 19,
+        0, 1, 16, 5, 22, 0, 17, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 16, 5, 22,
+        0, 33, 16, 5, 22, 0, 1, 14, 4, 19, 0, 1, 13, 4, 17, 0, 1, 13, 4, 17,
+        0, 1, 16, 5, 22, 0, 61, 16, 5, 22, 0, 1, 14, 4, 19, 0, 255, 0, 255,
+        0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
+        255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
+        0, 255, 0, 25, 8, 6, 3, 57, 10, 8, 5, 85, 9, 7, 4, 76, 0, 12, 8, 6,
+        3, 54, 9, 8, 4, 96, 9, 7, 4, 85, 0, 12, 8, 6, 3, 57, 9, 8, 4, 96, 9,
+        7, 4, 85, 0, 24, 8, 6, 3, 57, 11, 8, 4, 85, 9, 7, 4, 79, 0, 12, 8,
+        6, 3, 51, 10, 8, 5, 85, 8, 6, 3, 85, 0, 40, 8, 6, 3, 57, 11, 8, 4,
+        85, 8, 6, 3, 85, 0, 32, 8, 6, 3, 57, 10, 8, 5, 85, 9, 7, 4, 85, 0,
+        28, 5, 4, 2, 14, 8, 6, 3, 85, 9, 7, 4, 85, 0, 24, 8, 6, 3, 74, 9, 7,
+        4, 113, 8, 6, 3, 167, 8, 6, 3, 139, 9, 7, 4, 85, 5, 4, 2, 14, 0, 36,
+        8, 6, 3, 57, 9, 8, 4, 110, 9, 7, 4, 85, 0, 24, 5, 4, 2, 20, 9, 7, 4,
+        85, 9, 8, 4, 85, 0, 16, 9, 8, 4, 57, 9, 8, 4, 85, 6, 5, 3, 48, 0,
+        255, 0, 29, 5, 4, 2, 17, 8, 6, 3, 85, 9, 7, 4, 82, 0, 20, 5, 4, 2,
+        3, 8, 6, 3, 85, 9, 7, 4, 93, 8, 6, 3, 153, 8, 6, 3, 161, 8, 6, 3,
+        110, 9, 8, 4, 85, 8, 6, 3, 85, 6, 5, 3, 31, 0, 32, 5, 4, 2, 3, 8, 6,
+        3, 85, 10, 8, 5, 85, 10, 7, 5, 85, 0, 36, 5, 4, 2, 57, 8, 6, 3, 85,
+        9, 7, 4, 91, 8, 6, 3, 153, 8, 6, 3, 170, 8, 6, 3, 164, 8, 6, 3, 108,
+        8, 6, 3, 85, 6, 5, 3, 71, 0, 24, 5, 4, 2, 42, 8, 6, 3, 85, 9, 7, 4,
+        91, 8, 6, 3, 153, 8, 6, 3, 170, 8, 6, 3, 164, 8, 6, 3, 108, 8, 6, 3,
+        85, 6, 5, 3, 71, 0, 48, 5, 4, 2, 3, 8, 6, 3, 85, 9, 8, 4, 85, 9, 7,
+        4, 74, 0, 16, 8, 6, 3, 42, 9, 7, 4, 85, 8, 6, 3, 85, 9, 7, 4, 85, 8,
+        6, 3, 125, 8, 6, 3, 170, 7, 6, 4, 170, 9, 7, 4, 170, 12, 9, 7, 170,
+        19, 14, 10, 170, 19, 13, 10, 142, 8, 6, 5, 28, 0, 16, 5, 4, 2, 51,
+        8, 6, 3, 85, 9, 7, 4, 91, 8, 6, 3, 153, 8, 6, 3, 170, 8, 6, 3, 164,
+        8, 6, 3, 108, 8, 6, 3, 85, 6, 5, 3, 71, 0, 20, 10, 8, 5, 57, 9, 7,
+        4, 170, 8, 6, 3, 170, 8, 6, 3, 170, 8, 6, 3, 161, 8, 6, 3, 142, 9,
+        7, 4, 96, 9, 7, 4, 85, 8, 6, 3, 85, 9, 7, 4, 85, 9, 7, 4, 74, 0, 20,
+        5, 4, 2, 42, 8, 6, 3, 85, 9, 7, 4, 91, 8, 6, 3, 153, 8, 6, 3, 170,
+        8, 6, 3, 164, 8, 6, 3, 108, 8, 6, 3, 85, 6, 5, 3, 76, 0, 24, 8, 6,
+        5, 82, 10, 8, 7, 133, 12, 9, 7, 170, 15, 11, 8, 170, 15, 11, 8, 170,
+        15, 11, 8, 170, 13, 10, 8, 170, 10, 8, 7, 161, 10, 8, 7, 85, 6, 5,
+        5, 28, 0, 96, 8, 6, 3, 74, 9, 8, 4, 85, 8, 6, 3, 57, 0, 68, 7, 6, 4,
+        28, 9, 7, 4, 85, 9, 7, 4, 85, 5, 4, 2, 17, 0, 40, 5, 4, 2, 42, 8, 6,
+        3, 85, 9, 7, 4, 91, 8, 6, 3, 153, 8, 6, 3, 170, 8, 6, 3, 164, 8, 6,
+        3, 108, 8, 6, 3, 85, 6, 5, 3, 85, 0, 24, 8, 6, 5, 85, 10, 8, 7, 133,
+        12, 9, 7, 170, 15, 10, 8, 170, 15, 11, 8, 170, 15, 11, 8, 170, 13,
+        10, 8, 170, 10, 8, 7, 150, 8, 6, 5, 62, 0, 24, 8, 6, 5, 82, 10, 8,
+        7, 133, 12, 9, 7, 170, 15, 10, 8, 170, 14, 10, 7, 170, 9, 7, 4, 170,
+        8, 6, 5, 147, 10, 8, 5, 85, 7, 6, 4, 85, 5, 4, 4, 3, 0, 16, 12, 9,
+        7, 57, 11, 8, 6, 161, 9, 7, 6, 170, 10, 8, 7, 170, 13, 10, 8, 170,
+        14, 10, 7, 170, 13, 10, 8, 170, 12, 9, 7, 170, 10, 8, 7, 156, 10, 8,
+        7, 85, 6, 5, 5, 25, 0, 20, 6, 5, 3, 57, 8, 7, 5, 85, 9, 7, 4, 110,
+        9, 7, 4, 170, 10, 8, 5, 170, 10, 8, 5, 170, 11, 8, 6, 170, 10, 8, 7,
+        150, 10, 8, 7, 85, 6, 5, 5, 25, 0, 16, 15, 11, 8, 57, 11, 8, 6, 170,
+        9, 7, 6, 170, 10, 8, 7, 170, 13, 10, 8, 170, 15, 11, 8, 170, 15, 11,
+        8, 170, 13, 10, 8, 170, 10, 8, 7, 159, 10, 8, 7, 85, 6, 5, 5, 25, 0,
+        16, 15, 11, 8, 59, 11, 9, 6, 170, 9, 7, 4, 125, 10, 8, 5, 85, 8, 6,
+        3, 133, 8, 6, 3, 167, 8, 6, 3, 170, 8, 6, 3, 170, 9, 8, 4, 113, 0,
+        16, 8, 6, 3, 42, 10, 8, 5, 85, 10, 7, 5, 85, 9, 7, 4, 125, 10, 8, 5,
+        170, 12, 10, 7, 170, 14, 11, 7, 170, 19, 14, 10, 170, 19, 14, 10,
+        142, 8, 6, 5, 28, 0, 16, 8, 6, 5, 82, 10, 8, 7, 133, 12, 9, 7, 170,
+        15, 11, 8, 170, 15, 11, 8, 170, 15, 11, 8, 170, 13, 10, 8, 170, 10,
+        8, 7, 161, 10, 8, 7, 85, 6, 5, 5, 25, 0, 16, 12, 10, 7, 74, 14, 10,
+        7, 170, 12, 9, 7, 139, 7, 6, 4, 28, 0, 16, 10, 8, 7, 110, 14, 10, 7,
+        170, 13, 10, 8, 125, 0, 16, 13, 10, 8, 71, 15, 11, 8, 170, 13, 10,
+        8, 130, 5, 5, 4, 8, 0, 44, 11, 8, 6, 85, 9, 7, 4, 170, 10, 8, 5, 93,
+        0, 16, 12, 9, 7, 57, 10, 8, 5, 167, 11, 8, 6, 110, 6, 5, 3, 8, 0,
+        16, 11, 8, 6, 57, 10, 7, 5, 159, 11, 8, 6, 102, 0, 16, 8, 6, 3, 51,
+        10, 8, 5, 85, 9, 7, 4, 85, 0, 40, 10, 7, 5, 57, 11, 9, 6, 85, 7, 6,
+        4, 57, 0, 28, 7, 5, 4, 28, 10, 8, 5, 85, 11, 8, 6, 85, 0, 16, 8, 6,
+        3, 48, 10, 8, 5, 85, 8, 6, 3, 85, 0, 20, 8, 6, 3, 57, 11, 8, 4, 85,
+        9, 7, 4, 79, 0, 20, 5, 4, 2, 45, 8, 6, 3, 85, 9, 7, 4, 85, 9, 7, 4,
+        88, 9, 7, 4, 108, 9, 8, 4, 93, 9, 7, 4, 85, 8, 6, 3, 85, 6, 5, 3,
+        74, 0, 20, 8, 6, 3, 45, 9, 7, 4, 85, 8, 6, 3, 85, 9, 7, 4, 85, 8, 6,
+        3, 125, 8, 6, 3, 170, 8, 6, 3, 164, 8, 6, 3, 108, 8, 6, 3, 85, 6, 5,
+        3, 74, 0, 24, 6, 5, 3, 57, 8, 7, 5, 85, 10, 8, 5, 85, 9, 7, 4, 119,
+        8, 6, 3, 142, 9, 7, 4, 130, 10, 8, 5, 91, 10, 7, 5, 85, 6, 5, 3, 85,
+        0, 20, 9, 7, 4, 57, 10, 8, 5, 85, 10, 7, 5, 85, 10, 8, 5, 85, 8, 6,
+        3, 144, 8, 6, 3, 170, 8, 6, 3, 164, 8, 6, 3, 108, 8, 6, 3, 85, 6, 5,
+        3, 71, 0, 24, 5, 4, 2, 45, 8, 6, 3, 85, 9, 7, 4, 91, 8, 6, 3, 153,
+        8, 6, 3, 170, 8, 6, 3, 164, 9, 7, 4, 105, 8, 6, 3, 85, 6, 5, 3, 74,
+        0, 20, 11, 8, 4, 59, 9, 7, 4, 170, 8, 6, 3, 164, 9, 7, 4, 91, 8, 6,
+        3, 85, 8, 6, 3, 85, 8, 6, 3, 85, 9, 7, 4, 85, 8, 6, 3, 142, 9, 6, 4,
+        170, 9, 8, 4, 116, 0, 16, 8, 6, 3, 48, 10, 8, 5, 85, 9, 7, 4, 85, 0,
+        20, 8, 6, 3, 57, 11, 8, 4, 85, 9, 7, 4, 76, 0, 16, 8, 6, 3, 48, 10,
+        8, 5, 85, 9, 7, 4, 85, 0, 20, 8, 6, 3, 57, 11, 8, 4, 85, 9, 7, 4,
+        76, 0, 16, 8, 6, 3, 48, 10, 8, 5, 85, 9, 7, 4, 85, 0, 28, 8, 6, 3,
+        57, 11, 8, 4, 85, 9, 7, 4, 76, 0, 16, 8, 6, 3, 54, 9, 8, 4, 96, 9,
+        7, 4, 85, 0, 20, 8, 6, 3, 57, 9, 8, 4, 96, 9, 7, 4, 85, 0, 16, 10,
+        8, 5, 57, 10, 7, 5, 153, 10, 8, 5, 93, 0, 20, 10, 8, 7, 93, 14, 11,
+        7, 170, 13, 10, 8, 136, 0, 16, 11, 8, 6, 91, 11, 8, 6, 170, 9, 7, 4,
+        170, 9, 7, 4, 170, 8, 6, 5, 170, 8, 6, 3, 119, 9, 7, 4, 85, 8, 6, 3,
+        85, 8, 6, 3, 85, 9, 7, 4, 85, 9, 7, 4, 76, 0, 16, 8, 6, 3, 42, 9, 7,
+        4, 85, 8, 6, 3, 85, 8, 6, 3, 122, 9, 8, 4, 102, 0, 16, 8, 6, 3, 51,
+        9, 7, 4, 85, 6, 5, 3, 45, 0, 40, 12, 8, 5, 57, 8, 6, 3, 156, 10, 7,
+        5, 93, 11, 8, 6, 85, 11, 8, 6, 85, 0, 28, 6, 5, 5, 14, 13, 10, 8,
+        85, 8, 7, 5, 45, 0, 80, 10, 8, 5, 57, 10, 7, 5, 156, 10, 8, 5, 96,
+        0, 76, 9, 7, 4, 57, 10, 8, 5, 93, 10, 8, 5, 85, 0, 140, 10, 8, 7,
+        110, 13, 10, 8, 170, 12, 9, 7, 133, 5, 5, 4, 6, 0, 84, 8, 6, 5, 79,
+        10, 8, 7, 127, 13, 10, 8, 170, 16, 12, 9, 142, 8, 7, 5, 28, 0, 72,
+        8, 6, 3, 57, 10, 8, 5, 85, 9, 6, 4, 85, 0, 48, 15, 11, 8, 113, 25,
+        18, 12, 170, 20, 15, 11, 142, 8, 7, 5, 28, 0, 28, 15, 11, 8, 130,
+        22, 16, 11, 170, 20, 15, 11, 142, 7, 6, 6, 23, 0, 12, 13, 10, 8, 68,
+        12, 9, 7, 170, 11, 8, 6, 116, 6, 5, 3, 8, 0, 44, 12, 9, 7, 82, 15,
+        10, 8, 170, 13, 10, 8, 130, 5, 5, 4, 8, 0, 255, 0, 197, 6, 5, 3, 57,
+        8, 6, 3, 85, 0, 255, 0, 149, 5, 4, 2, 6, 8, 6, 3, 85, 8, 6, 3, 156,
+        9, 8, 4, 113, 0, 16, 8, 6, 3, 48, 9, 8, 4, 91, 9, 7, 4, 76, 0, 16,
+        10, 8, 5, 57, 9, 6, 4, 170, 8, 6, 3, 99, 5, 4, 2, 34, 0, 36, 8, 6,
+        3, 71, 9, 8, 4, 93, 9, 8, 4, 96, 8, 6, 3, 85, 6, 5, 3, 45, 0, 12, 8,
+        6, 3, 76, 0, 44, 8, 6, 3, 57, 58, 31, 9, 255, 93, 50, 12, 255, 88,
+        45, 11, 255, 12, 10, 5, 113, 0, 4, 7, 6, 4, 28, 54, 29, 9, 255, 93,
+        46, 12, 255, 88, 45, 11, 255, 12, 9, 5, 122, 0, 4, 7, 5, 4, 37, 54,
+        29, 9, 255, 93, 46, 12, 255, 88, 45, 11, 255, 14, 10, 5, 142, 0, 16,
+        8, 6, 3, 85, 58, 31, 9, 255, 93, 50, 12, 255, 88, 44, 11, 255, 9, 7,
+        4, 170, 0, 4, 5, 4, 2, 85, 52, 28, 9, 255, 93, 48, 12, 255, 88, 44,
+        11, 255, 12, 10, 5, 170, 0, 32, 7, 6, 4, 85, 58, 31, 9, 255, 93, 50,
+        12, 255, 88, 45, 11, 255, 12, 9, 5, 170, 0, 24, 8, 6, 3, 57, 58, 31,
+        9, 255, 93, 50, 12, 255, 88, 45, 11, 255, 14, 10, 5, 142, 0, 20, 6,
+        5, 3, 28, 19, 12, 6, 227, 76, 37, 11, 255, 88, 45, 11, 255, 14, 10,
+        5, 139, 0, 16, 9, 8, 4, 170, 69, 35, 10, 255, 92, 47, 11, 255, 92,
+        47, 11, 255, 88, 45, 11, 255, 88, 45, 11, 255, 16, 11, 5, 227, 7, 5,
+        4, 28, 0, 28, 8, 6, 3, 57, 58, 31, 9, 255, 93, 46, 12, 255, 88, 45,
+        11, 255, 14, 10, 5, 142, 0, 16, 6, 5, 3, 28, 19, 12, 6, 227, 82, 39,
+        11, 255, 92, 47, 11, 255, 14, 10, 5, 105, 0, 8, 7, 5, 4, 20, 54, 29,
+        9, 255, 100, 50, 13, 255, 30, 19, 7, 255, 8, 6, 3, 85, 0, 255, 0,
+        21, 6, 5, 3, 28, 19, 12, 6, 227, 76, 37, 11, 255, 88, 45, 11, 255,
+        14, 10, 5, 130, 0, 12, 7, 6, 4, 65, 17, 11, 6, 227, 71, 37, 10, 255,
+        88, 45, 11, 255, 92, 47, 11, 255, 92, 47, 11, 255, 88, 45, 11, 255,
+        88, 44, 11, 255, 88, 44, 11, 255, 25, 16, 6, 255, 8, 6, 3, 142, 0,
+        24, 7, 5, 4, 85, 17, 12, 6, 229, 77, 39, 12, 255, 107, 51, 14, 255,
+        113, 55, 16, 255, 20, 14, 9, 178, 0, 28, 14, 11, 7, 170, 29, 18, 8,
+        255, 74, 39, 11, 255, 88, 45, 11, 255, 88, 45, 11, 255, 92, 47, 11,
+        255, 92, 47, 11, 255, 88, 45, 11, 255, 88, 44, 11, 255, 41, 23, 8,
+        255, 12, 9, 5, 227, 5, 5, 4, 23, 0, 12, 9, 7, 4, 170, 26, 17, 6,
+        255, 74, 39, 11, 255, 88, 45, 11, 255, 88, 45, 11, 255, 92, 47, 11,
+        255, 92, 47, 11, 255, 88, 45, 11, 255, 88, 44, 11, 255, 41, 24, 8,
+        255, 12, 9, 5, 227, 6, 5, 3, 28, 0, 36, 6, 5, 3, 85, 16, 11, 5, 227,
+        71, 37, 10, 255, 88, 45, 11, 255, 88, 44, 11, 255, 12, 10, 5, 113,
+        0, 8, 8, 6, 3, 28, 54, 29, 9, 255, 92, 47, 11, 255, 88, 44, 11, 255,
+        88, 45, 11, 255, 92, 46, 13, 255, 100, 52, 13, 255, 109, 53, 16,
+        255, 121, 63, 20, 255, 158, 74, 23, 255, 180, 88, 27, 255, 183, 90,
+        28, 255, 26, 17, 11, 142, 0, 12, 10, 7, 5, 170, 26, 17, 6, 255, 74,
+        39, 11, 255, 88, 45, 11, 255, 92, 47, 11, 255, 92, 47, 11, 255, 92,
+        47, 11, 255, 88, 45, 11, 255, 88, 45, 11, 255, 41, 24, 8, 255, 12,
+        9, 5, 227, 6, 5, 3, 28, 0, 8, 7, 6, 4, 8, 61, 32, 10, 255, 102, 51,
+        13, 255, 92, 46, 13, 255, 92, 46, 13, 255, 92, 46, 13, 255, 92, 46,
+        13, 255, 92, 46, 13, 255, 90, 45, 11, 255, 84, 44, 11, 255, 88, 45,
+        11, 255, 88, 44, 11, 255, 14, 10, 5, 119, 0, 12, 9, 7, 4, 153, 26,
+        17, 6, 255, 74, 39, 11, 255, 88, 45, 11, 255, 92, 47, 11, 255, 92,
+        47, 11, 255, 92, 47, 11, 255, 88, 45, 11, 255, 88, 44, 11, 255, 45,
+        25, 8, 255, 13, 10, 6, 227, 7, 6, 4, 28, 0, 12, 17, 13, 10, 170, 64,
+        39, 21, 255, 155, 78, 26, 255, 169, 83, 26, 255, 165, 80, 24, 255,
+        161, 79, 24, 255, 145, 71, 22, 255, 136, 70, 21, 255, 134, 69, 21,
+        255, 88, 50, 23, 255, 22, 17, 11, 232, 9, 8, 6, 31, 0, 84, 4, 4, 3,
+        23, 12, 9, 5, 173, 71, 34, 10, 255, 92, 43, 13, 255, 33, 20, 8, 255,
+        10, 8, 5, 57, 0, 64, 20, 14, 7, 227, 83, 42, 12, 255, 92, 46, 13,
+        255, 19, 13, 6, 227, 6, 5, 3, 34, 0, 32, 10, 8, 5, 170, 26, 17, 6,
+        255, 76, 37, 11, 255, 90, 46, 11, 255, 92, 46, 13, 255, 92, 46, 13,
+        255, 90, 45, 11, 255, 90, 45, 11, 255, 88, 44, 11, 255, 46, 26, 9,
+        255, 18, 13, 9, 227, 8, 7, 5, 28, 0, 12, 15, 12, 8, 170, 58, 35, 19,
+        255, 134, 73, 23, 255, 153, 76, 24, 255, 142, 69, 21, 255, 131, 64,
+        20, 255, 121, 59, 18, 255, 121, 59, 18, 255, 121, 62, 18, 255, 43,
+        27, 12, 255, 11, 9, 6, 170, 0, 16, 17, 13, 10, 170, 64, 39, 21, 255,
+        164, 85, 27, 255, 177, 86, 26, 255, 154, 75, 23, 255, 121, 62, 18,
+        255, 115, 56, 16, 255, 119, 61, 18, 255, 123, 61, 20, 255, 80, 45,
+        19, 255, 22, 16, 11, 227, 8, 7, 5, 28, 0, 8, 13, 10, 8, 57, 96, 48,
+        19, 255, 165, 80, 24, 255, 159, 78, 24, 255, 159, 78, 24, 255, 165,
+        80, 24, 255, 165, 80, 24, 255, 165, 80, 24, 255, 159, 78, 24, 255,
+        164, 81, 25, 255, 91, 52, 24, 255, 22, 17, 11, 227, 8, 7, 5, 28, 0,
+        12, 13, 10, 8, 170, 38, 24, 11, 255, 99, 47, 16, 255, 116, 59, 17,
+        255, 126, 65, 21, 255, 142, 69, 21, 255, 153, 76, 24, 255, 157, 74,
+        24, 255, 155, 76, 24, 255, 91, 52, 24, 255, 23, 18, 12, 227, 8, 7,
+        5, 28, 0, 8, 13, 10, 8, 57, 104, 52, 21, 255, 171, 84, 26, 255, 155,
+        76, 24, 255, 164, 81, 25, 255, 173, 81, 26, 255, 180, 88, 27, 255,
+        180, 88, 27, 255, 177, 86, 26, 255, 169, 80, 26, 255, 92, 55, 25,
+        255, 22, 17, 11, 227, 8, 7, 5, 28, 0, 8, 13, 10, 8, 57, 114, 63, 25,
+        255, 177, 86, 26, 255, 114, 56, 17, 255, 92, 46, 13, 255, 92, 47,
+        11, 255, 93, 46, 12, 255, 92, 46, 13, 255, 96, 48, 13, 255, 92, 46,
+        13, 255, 18, 12, 5, 91, 0, 8, 8, 6, 3, 40, 55, 29, 10, 255, 108, 50,
+        15, 255, 114, 56, 17, 255, 130, 67, 21, 255, 153, 76, 24, 255, 161,
+        82, 24, 255, 171, 84, 26, 255, 179, 84, 26, 255, 179, 84, 26, 255,
+        25, 17, 10, 142, 0, 12, 15, 12, 8, 170, 64, 39, 21, 255, 162, 84,
+        27, 255, 179, 88, 28, 255, 183, 90, 28, 255, 181, 89, 28, 255, 181,
+        89, 28, 255, 172, 88, 27, 255, 156, 77, 25, 255, 88, 50, 23, 255,
+        22, 17, 11, 227, 8, 7, 5, 28, 0, 8, 13, 9, 6, 57, 96, 48, 19, 255,
+        153, 71, 22, 255, 134, 69, 21, 255, 20, 14, 9, 193, 0, 12, 11, 8, 6,
+        113, 124, 62, 25, 255, 185, 91, 28, 255, 169, 80, 26, 255, 22, 15,
+        9, 142, 0, 8, 11, 8, 6, 57, 111, 61, 24, 255, 184, 90, 27, 255, 177,
+        86, 26, 255, 23, 16, 10, 173, 0, 40, 11, 8, 6, 113, 114, 59, 23,
+        255, 144, 73, 21, 255, 126, 63, 21, 255, 20, 14, 9, 142, 0, 8, 11,
+        9, 6, 57, 97, 51, 20, 255, 152, 71, 23, 255, 134, 69, 21, 255, 20,
+        14, 9, 187, 0, 12, 12, 9, 7, 96, 97, 48, 18, 255, 140, 71, 21, 255,
+        138, 71, 21, 255, 20, 15, 9, 142, 0, 8, 8, 6, 3, 40, 52, 28, 9, 255,
+        93, 50, 12, 255, 88, 45, 11, 255, 14, 10, 5, 142, 0, 32, 13, 10, 8,
+        82, 91, 48, 16, 255, 132, 71, 21, 255, 63, 36, 18, 255, 10, 8, 7,
+        136, 0, 20, 7, 6, 6, 62, 31, 21, 12, 244, 124, 66, 23, 255, 134, 69,
+        21, 255, 20, 15, 9, 142, 0, 8, 8, 6, 3, 28, 54, 29, 9, 255, 93, 46,
+        12, 255, 80, 39, 11, 255, 14, 10, 5, 142, 0, 12, 8, 6, 3, 57, 58,
+        31, 9, 255, 93, 50, 12, 255, 88, 44, 11, 255, 14, 10, 5, 116, 0, 12,
+        9, 7, 4, 153, 26, 17, 6, 255, 74, 39, 11, 255, 88, 45, 11, 255, 88,
+        45, 11, 255, 88, 45, 11, 255, 88, 45, 11, 255, 88, 44, 11, 255, 88,
+        44, 11, 255, 41, 23, 8, 255, 12, 9, 5, 227, 5, 4, 4, 17, 0, 8, 8, 6,
+        3, 34, 54, 29, 9, 255, 92, 43, 11, 255, 88, 44, 11, 255, 88, 45, 11,
+        255, 92, 43, 11, 255, 92, 47, 11, 255, 92, 47, 11, 255, 88, 45, 11,
+        255, 88, 44, 11, 255, 45, 25, 8, 255, 12, 10, 5, 227, 6, 5, 3, 28,
+        0, 12, 13, 10, 6, 170, 40, 24, 11, 255, 97, 48, 16, 255, 113, 55,
+        16, 255, 115, 56, 16, 255, 116, 57, 17, 255, 116, 57, 17, 255, 113,
+        55, 16, 255, 113, 55, 16, 255, 60, 33, 13, 255, 18, 14, 9, 227, 8,
+        6, 5, 28, 0, 8, 12, 9, 7, 57, 77, 38, 14, 255, 118, 57, 17, 255,
+        116, 59, 17, 255, 118, 60, 17, 255, 109, 53, 16, 255, 98, 47, 13,
+        255, 92, 47, 11, 255, 88, 45, 11, 255, 88, 44, 11, 255, 41, 23, 8,
+        255, 12, 9, 5, 227, 6, 5, 3, 28, 0, 12, 10, 8, 5, 170, 28, 18, 7,
+        255, 76, 37, 11, 255, 90, 45, 11, 255, 92, 46, 13, 255, 94, 45, 13,
+        255, 94, 45, 13, 255, 92, 46, 13, 255, 92, 46, 13, 255, 46, 26, 9,
+        255, 13, 10, 6, 227, 6, 5, 5, 28, 0, 8, 7, 6, 4, 8, 61, 32, 10, 255,
+        100, 50, 13, 255, 92, 46, 13, 255, 92, 46, 13, 255, 92, 46, 13, 255,
+        92, 46, 13, 255, 92, 46, 13, 255, 92, 46, 13, 255, 94, 47, 13, 255,
+        98, 49, 13, 255, 94, 47, 13, 255, 18, 12, 5, 93, 0, 8, 8, 6, 3, 42,
+        60, 32, 9, 255, 96, 48, 13, 255, 88, 45, 11, 255, 14, 10, 5, 142, 0,
+        12, 8, 6, 3, 57, 58, 31, 9, 255, 93, 50, 12, 255, 88, 44, 11, 255,
+        12, 10, 5, 113, 0, 8, 8, 6, 3, 28, 54, 29, 9, 255, 93, 50, 12, 255,
+        88, 44, 11, 255, 14, 10, 5, 142, 0, 12, 8, 6, 3, 57, 58, 31, 9, 255,
+        93, 50, 12, 255, 88, 44, 11, 255, 12, 10, 5, 113, 0, 8, 8, 6, 3, 28,
+        54, 29, 9, 255, 93, 50, 12, 255, 88, 44, 11, 255, 14, 10, 5, 142, 0,
+        20, 8, 6, 3, 57, 58, 31, 9, 255, 93, 50, 12, 255, 88, 44, 11, 255,
+        12, 10, 5, 113, 0, 8, 7, 6, 4, 28, 54, 29, 9, 255, 93, 50, 12, 255,
+        88, 45, 11, 255, 14, 10, 5, 142, 0, 12, 8, 7, 3, 57, 60, 31, 9, 255,
+        96, 48, 13, 255, 92, 46, 13, 255, 14, 10, 5, 127, 0, 8, 10, 8, 5,
+        57, 82, 42, 15, 255, 135, 66, 20, 255, 121, 60, 20, 255, 20, 15, 9,
+        176, 0, 12, 11, 9, 6, 108, 107, 56, 22, 255, 172, 84, 25, 255, 158,
+        74, 23, 255, 22, 15, 9, 142, 0, 8, 11, 8, 6, 54, 98, 51, 19, 255,
+        142, 72, 21, 255, 136, 70, 21, 255, 138, 71, 21, 255, 121, 59, 18,
+        255, 100, 52, 13, 255, 90, 46, 11, 255, 88, 44, 11, 255, 88, 44, 11,
+        255, 88, 44, 11, 255, 88, 45, 11, 255, 12, 10, 5, 113, 0, 8, 8, 6,
+        3, 28, 54, 29, 9, 255, 92, 47, 11, 255, 88, 44, 11, 255, 92, 47, 11,
+        255, 92, 47, 11, 255, 18, 12, 5, 85, 0, 8, 7, 6, 4, 45, 54, 30, 9,
+        255, 94, 47, 13, 255, 31, 20, 8, 255, 9, 7, 4, 85, 0, 32, 8, 6, 3,
+        48, 65, 33, 10, 255, 114, 55, 15, 255, 119, 58, 18, 255, 126, 63,
+        21, 255, 128, 66, 21, 255, 22, 15, 9, 164, 0, 20, 5, 5, 4, 28, 19,
+        14, 10, 227, 141, 72, 26, 255, 43, 27, 16, 255, 7, 6, 6, 85, 0, 72,
+        14, 10, 7, 71, 96, 49, 17, 255, 138, 71, 21, 255, 130, 67, 21, 255,
+        22, 15, 9, 164, 0, 68, 12, 9, 7, 76, 77, 39, 14, 255, 118, 57, 17,
+        255, 109, 53, 16, 255, 22, 15, 9, 153, 0, 132, 11, 8, 6, 96, 103,
+        53, 20, 255, 144, 73, 21, 255, 121, 60, 20, 255, 24, 16, 9, 153, 0,
+        80, 15, 12, 8, 184, 61, 36, 20, 255, 141, 68, 24, 255, 168, 82, 25,
+        255, 171, 84, 26, 255, 26, 18, 11, 159, 0, 68, 9, 7, 4, 57, 60, 32,
+        9, 255, 96, 48, 13, 255, 92, 46, 13, 255, 19, 12, 6, 142, 0, 40, 14,
+        10, 7, 76, 129, 67, 26, 255, 190, 97, 29, 255, 180, 88, 27, 255, 26,
+        17, 11, 161, 0, 24, 14, 10, 7, 85, 129, 67, 26, 255, 190, 97, 29,
+        255, 180, 88, 27, 255, 25, 17, 10, 125, 0, 8, 11, 8, 6, 57, 109, 60,
+        24, 255, 175, 86, 26, 255, 142, 73, 23, 255, 20, 14, 9, 187, 0, 40,
+        12, 9, 7, 93, 121, 65, 24, 255, 183, 89, 26, 255, 168, 82, 25, 255,
+        21, 15, 10, 178, 0, 255, 0, 193, 10, 8, 5, 170, 39, 23, 8, 255, 78,
+        41, 11, 255, 16, 11, 5, 142, 0, 255, 0, 141, 6, 5, 3, 85, 16, 11, 5,
+        227, 71, 37, 10, 255, 92, 47, 11, 255, 92, 47, 11, 255, 18, 12, 5,
+        85, 0, 8, 8, 6, 3, 28, 54, 29, 9, 255, 93, 46, 12, 255, 88, 45, 11,
+        255, 12, 10, 5, 113, 0, 12, 58, 31, 9, 255, 93, 50, 12, 255, 88, 45,
+        11, 255, 25, 17, 6, 255, 8, 6, 3, 142, 0, 24, 4, 4, 3, 25, 10, 8, 5,
+        173, 65, 33, 10, 255, 92, 46, 13, 255, 92, 46, 13, 255, 67, 34, 10,
+        255, 27, 18, 8, 255, 9, 7, 4, 156, 3, 3, 2, 85, 10, 8, 5, 184, 69,
+        35, 10, 255, 19, 13, 6, 147, 0, 40, 9, 7, 4, 113, 112, 55, 13, 255,
+        141, 69, 16, 255, 141, 75, 16, 255, 18, 13, 5, 170, 0, 4, 8, 6, 3,
+        85, 110, 54, 13, 255, 143, 76, 16, 255, 139, 68, 16, 255, 19, 13, 6,
+        170, 0, 4, 8, 6, 3, 85, 110, 54, 13, 255, 143, 76, 16, 255, 141, 72,
+        16, 255, 23, 15, 6, 170, 0, 12, 10, 9, 5, 110, 35, 21, 8, 255, 129,
+        63, 14, 255, 141, 69, 16, 255, 139, 68, 16, 255, 52, 27, 9, 255, 9,
+        7, 4, 255, 27, 17, 8, 255, 135, 66, 16, 255, 154, 75, 17, 255, 155,
+        79, 18, 255, 91, 50, 16, 255, 20, 15, 9, 207, 10, 9, 7, 28, 0, 16,
+        5, 4, 4, 20, 8, 6, 3, 127, 31, 20, 8, 255, 130, 66, 15, 255, 143,
+        76, 16, 255, 143, 76, 16, 255, 67, 34, 10, 255, 10, 8, 5, 215, 10,
+        8, 5, 170, 13, 10, 6, 142, 7, 5, 4, 23, 0, 8, 12, 9, 5, 85, 115, 59,
+        14, 255, 149, 72, 16, 255, 143, 76, 16, 255, 18, 12, 5, 235, 0, 16,
+        7, 6, 4, 28, 14, 10, 5, 227, 92, 46, 13, 255, 143, 73, 16, 255, 143,
+        70, 16, 255, 18, 13, 5, 170, 0, 12, 14, 10, 5, 170, 53, 28, 10, 255,
+        114, 56, 13, 255, 56, 29, 9, 255, 16, 11, 5, 255, 34, 20, 7, 255,
+        112, 55, 13, 255, 87, 42, 12, 255, 19, 13, 6, 235, 8, 7, 5, 40, 0,
+        24, 10, 8, 5, 85, 114, 56, 13, 255, 143, 70, 16, 255, 141, 72, 16,
+        255, 23, 15, 6, 170, 0, 12, 7, 6, 4, 28, 14, 10, 5, 227, 90, 44, 13,
+        255, 112, 57, 13, 255, 47, 26, 8, 255, 11, 8, 4, 57, 0, 12, 25, 16,
+        6, 227, 96, 48, 13, 255, 112, 57, 13, 255, 26, 16, 7, 255, 8, 6, 5,
+        85, 0, 24, 13, 10, 6, 85, 8, 7, 5, 57, 0, 20, 6, 5, 3, 28, 15, 11,
+        6, 85, 9, 7, 4, 28, 0, 36, 9, 7, 4, 105, 10, 8, 5, 170, 10, 8, 5,
+        130, 6, 5, 3, 23, 0, 156, 8, 6, 3, 136, 77, 39, 12, 255, 143, 73,
+        16, 255, 139, 74, 16, 255, 18, 12, 5, 170, 0, 12, 21, 14, 6, 227,
+        112, 57, 13, 255, 141, 69, 16, 255, 80, 40, 11, 255, 16, 11, 5, 255,
+        14, 10, 5, 227, 18, 13, 5, 255, 72, 35, 11, 255, 136, 69, 15, 255,
+        130, 66, 15, 255, 46, 26, 9, 255, 8, 6, 3, 105, 0, 16, 8, 7, 5, 57,
+        42, 27, 13, 255, 150, 79, 21, 255, 184, 94, 21, 255, 195, 99, 22,
+        255, 199, 106, 24, 255, 26, 18, 11, 255, 0, 24, 10, 8, 7, 99, 83,
+        45, 18, 255, 144, 74, 17, 255, 143, 70, 16, 255, 94, 47, 13, 255,
+        18, 13, 5, 255, 16, 11, 5, 173, 14, 10, 5, 227, 52, 27, 9, 255, 132,
+        67, 15, 255, 139, 68, 16, 255, 75, 39, 12, 255, 10, 7, 5, 116, 0, 8,
+        6, 5, 3, 57, 52, 27, 9, 255, 137, 73, 16, 255, 143, 76, 16, 255, 94,
+        47, 13, 255, 18, 13, 5, 255, 16, 11, 5, 173, 14, 10, 5, 227, 52, 27,
+        9, 255, 132, 67, 15, 255, 139, 74, 16, 255, 75, 39, 12, 255, 10, 8,
+        5, 142, 0, 32, 8, 6, 5, 85, 22, 15, 7, 255, 102, 51, 13, 255, 137,
+        67, 16, 255, 140, 71, 15, 255, 141, 75, 16, 255, 20, 13, 5, 170, 0,
+        8, 9, 6, 4, 85, 108, 55, 13, 255, 141, 69, 16, 255, 139, 74, 16,
+        255, 74, 36, 11, 255, 18, 12, 7, 255, 20, 13, 7, 181, 22, 15, 9,
+        207, 20, 13, 9, 238, 18, 13, 9, 252, 23, 16, 10, 255, 31, 21, 12,
+        218, 14, 11, 7, 42, 0, 8, 7, 6, 4, 57, 40, 22, 9, 255, 130, 66, 15,
+        255, 141, 75, 16, 255, 84, 42, 11, 255, 18, 12, 5, 255, 16, 12, 5,
+        181, 14, 10, 5, 241, 69, 35, 10, 255, 140, 69, 17, 255, 154, 78, 17,
+        255, 117, 60, 18, 255, 17, 13, 8, 142, 0, 12, 21, 14, 8, 190, 28,
+        18, 9, 255, 23, 15, 8, 255, 21, 14, 8, 255, 21, 14, 8, 255, 23, 15,
+        8, 255, 38, 24, 11, 255, 98, 53, 17, 255, 151, 74, 18, 255, 150, 76,
+        17, 255, 141, 75, 16, 255, 21, 15, 6, 170, 0, 8, 5, 4, 2, 28, 33,
+        20, 8, 255, 130, 66, 15, 255, 141, 72, 16, 255, 84, 42, 11, 255, 18,
+        12, 5, 255, 18, 12, 5, 176, 14, 10, 5, 235, 57, 29, 10, 255, 140,
+        72, 17, 255, 165, 85, 20, 255, 121, 67, 24, 255, 14, 11, 7, 142, 0,
+        8, 8, 6, 5, 57, 72, 46, 23, 255, 198, 113, 29, 255, 200, 102, 23,
+        255, 131, 68, 22, 255, 33, 21, 12, 255, 17, 13, 8, 255, 21, 14, 8,
+        255, 88, 47, 19, 255, 192, 99, 23, 255, 203, 113, 26, 255, 146, 87,
+        29, 255, 13, 11, 8, 164, 0, 12, 10, 8, 5, 85, 13, 10, 6, 170, 11, 9,
+        6, 142, 7, 6, 4, 28, 0, 12, 13, 10, 8, 113, 18, 14, 9, 170, 16, 13,
+        9, 147, 10, 8, 7, 28, 0, 24, 10, 8, 7, 28, 20, 15, 11, 227, 104, 62,
+        21, 255, 184, 94, 21, 255, 117, 62, 22, 255, 17, 12, 8, 227, 7, 5,
+        4, 28, 0, 64, 11, 8, 6, 170, 67, 35, 16, 255, 164, 85, 21, 255, 115,
+        58, 16, 255, 20, 14, 7, 252, 8, 6, 5, 85, 0, 24, 9, 7, 4, 82, 66,
+        37, 13, 255, 145, 75, 18, 255, 154, 78, 17, 255, 115, 58, 16, 255,
+        29, 18, 8, 255, 14, 10, 7, 255, 16, 11, 7, 255, 65, 34, 12, 255,
+        150, 74, 19, 255, 189, 97, 22, 255, 138, 79, 27, 255, 14, 12, 9,
+        142, 0, 8, 7, 6, 6, 57, 55, 33, 16, 255, 158, 81, 19, 255, 162, 80,
+        19, 255, 102, 53, 17, 255, 24, 15, 7, 255, 19, 12, 6, 170, 14, 10,
+        5, 204, 46, 26, 9, 255, 137, 67, 16, 255, 139, 71, 16, 255, 49, 27,
+        10, 255, 7, 6, 4, 105, 0, 8, 7, 6, 6, 62, 72, 46, 23, 255, 199, 115,
+        32, 255, 205, 111, 28, 255, 155, 84, 26, 255, 41, 24, 14, 255, 18,
+        13, 9, 255, 25, 16, 10, 255, 110, 61, 25, 255, 199, 100, 28, 255,
+        205, 112, 30, 255, 146, 87, 29, 255, 13, 11, 8, 142, 0, 8, 10, 8, 7,
+        147, 180, 87, 25, 255, 206, 111, 27, 255, 203, 105, 26, 255, 164,
+        85, 27, 255, 40, 24, 15, 255, 20, 14, 9, 255, 26, 17, 11, 255, 121,
+        64, 26, 255, 201, 101, 28, 255, 205, 112, 30, 255, 146, 87, 29, 255,
+        14, 11, 7, 142, 0, 8, 8, 6, 5, 57, 71, 44, 22, 255, 192, 108, 25,
+        255, 198, 101, 23, 255, 150, 78, 25, 255, 41, 24, 14, 255, 32, 21,
+        13, 255, 74, 41, 21, 255, 184, 105, 27, 255, 202, 104, 25, 255, 202,
+        118, 27, 255, 174, 102, 31, 255, 17, 14, 10, 142, 0, 8, 11, 9, 6,
+        136, 182, 92, 25, 255, 206, 112, 29, 255, 205, 111, 28, 255, 166,
+        79, 27, 255, 43, 25, 16, 255, 21, 15, 10, 255, 29, 19, 12, 255, 116,
+        67, 27, 255, 202, 107, 31, 255, 206, 113, 31, 255, 146, 87, 29, 255,
+        12, 10, 7, 142, 0, 8, 11, 8, 6, 144, 185, 93, 26, 255, 202, 103, 23,
+        255, 157, 77, 18, 255, 83, 42, 12, 255, 19, 13, 6, 255, 13, 10, 6,
+        255, 20, 13, 7, 255, 27, 17, 8, 255, 28, 18, 9, 227, 10, 8, 5, 45,
+        0, 8, 11, 9, 6, 142, 139, 73, 20, 255, 198, 96, 21, 255, 199, 106,
+        24, 255, 155, 78, 26, 255, 41, 25, 14, 255, 21, 15, 10, 255, 28, 18,
+        11, 255, 38, 24, 15, 255, 40, 24, 15, 227, 14, 10, 7, 62, 0, 8, 8,
+        7, 5, 57, 65, 41, 20, 255, 197, 108, 28, 255, 205, 111, 28, 255,
+        170, 88, 27, 255, 43, 27, 16, 255, 19, 14, 10, 255, 29, 19, 12, 255,
+        123, 66, 24, 255, 181, 84, 20, 255, 170, 87, 19, 255, 114, 60, 17,
+        255, 11, 10, 6, 142, 0, 8, 11, 9, 6, 85, 119, 60, 15, 255, 154, 75,
+        17, 255, 154, 78, 17, 255, 18, 13, 7, 255, 0, 12, 13, 10, 8, 170,
+        191, 102, 30, 255, 209, 118, 30, 255, 207, 113, 30, 255, 28, 19, 11,
+        201, 0, 8, 13, 10, 8, 105, 166, 87, 23, 255, 198, 101, 23, 255, 198,
+        97, 23, 255, 26, 18, 11, 255, 0, 40, 13, 10, 8, 170, 189, 100, 28,
+        255, 206, 111, 27, 255, 204, 102, 27, 255, 28, 20, 11, 201, 0, 8,
+        12, 10, 7, 116, 184, 93, 27, 255, 206, 107, 27, 255, 203, 113, 26,
+        255, 23, 17, 10, 255, 0, 8, 6, 5, 5, 28, 25, 18, 12, 244, 192, 105,
+        27, 255, 206, 112, 29, 255, 207, 117, 30, 255, 32, 22, 13, 170, 0,
+        8, 11, 9, 6, 88, 112, 57, 13, 255, 143, 70, 16, 255, 141, 69, 16,
+        255, 17, 12, 6, 227, 0, 32, 14, 11, 9, 170, 184, 92, 25, 255, 206,
+        111, 27, 255, 192, 111, 31, 255, 49, 33, 18, 255, 10, 8, 7, 122, 0,
+        12, 7, 7, 6, 59, 22, 16, 11, 232, 167, 100, 28, 255, 205, 112, 30,
+        255, 205, 116, 30, 255, 26, 18, 11, 210, 0, 8, 8, 7, 3, 85, 110, 54,
+        13, 255, 141, 69, 16, 255, 141, 75, 16, 255, 25, 16, 6, 255, 5, 4,
+        4, 40, 0, 8, 10, 8, 5, 85, 112, 55, 13, 255, 141, 75, 16, 255, 141,
+        75, 16, 255, 20, 13, 5, 170, 0, 8, 5, 4, 2, 28, 33, 20, 8, 255, 130,
+        66, 15, 255, 141, 72, 16, 255, 112, 55, 13, 255, 45, 25, 8, 255, 26,
+        17, 6, 255, 33, 20, 8, 255, 94, 47, 13, 255, 141, 69, 16, 255, 144,
+        71, 17, 255, 80, 40, 13, 255, 9, 7, 4, 125, 0, 8, 10, 8, 5, 85, 112,
+        57, 13, 255, 148, 79, 17, 255, 141, 75, 16, 255, 87, 42, 12, 255,
+        19, 13, 6, 255, 14, 10, 5, 215, 15, 10, 6, 255, 60, 31, 11, 255,
+        143, 71, 18, 255, 160, 82, 19, 255, 96, 54, 17, 255, 12, 9, 7, 142,
+        0, 8, 8, 6, 5, 57, 71, 44, 22, 255, 192, 100, 25, 255, 199, 106, 24,
+        255, 185, 93, 26, 255, 91, 50, 22, 255, 58, 33, 17, 255, 72, 41, 19,
+        255, 158, 81, 25, 255, 199, 106, 24, 255, 199, 106, 24, 255, 138,
+        79, 27, 255, 13, 11, 8, 142, 0, 8, 10, 8, 7, 147, 166, 87, 23, 255,
+        203, 108, 24, 255, 202, 108, 25, 255, 153, 77, 26, 255, 38, 22, 13,
+        255, 15, 11, 6, 255, 14, 10, 5, 255, 52, 28, 9, 255, 132, 70, 15,
+        255, 141, 75, 16, 255, 80, 41, 13, 255, 10, 8, 5, 139, 0, 8, 7, 6,
+        6, 57, 48, 29, 13, 255, 154, 79, 19, 255, 160, 85, 19, 255, 108, 56,
+        17, 255, 30, 18, 9, 255, 16, 11, 7, 255, 24, 15, 9, 255, 96, 51, 17,
+        255, 167, 86, 20, 255, 181, 88, 20, 255, 140, 75, 23, 255, 18, 14,
+        9, 144, 0, 12, 22, 14, 7, 193, 22, 13, 7, 255, 20, 13, 7, 255, 78,
+        40, 15, 255, 165, 81, 20, 255, 177, 90, 20, 255, 177, 90, 20, 255,
+        115, 58, 20, 255, 32, 20, 11, 255, 24, 15, 9, 255, 30, 19, 9, 227,
+        11, 8, 6, 54, 0, 8, 11, 9, 6, 142, 139, 68, 20, 255, 166, 78, 19,
+        255, 144, 71, 17, 255, 19, 12, 6, 215, 0, 12, 9, 7, 4, 136, 114, 56,
+        13, 255, 143, 70, 16, 255, 139, 68, 16, 255, 19, 13, 6, 170, 0, 8,
+        10, 7, 5, 85, 112, 55, 13, 255, 143, 70, 16, 255, 139, 74, 16, 255,
+        17, 11, 6, 221, 0, 12, 9, 7, 4, 136, 114, 56, 13, 255, 143, 70, 16,
+        255, 141, 75, 16, 255, 20, 13, 5, 170, 0, 8, 9, 6, 4, 85, 110, 54,
+        13, 255, 141, 69, 16, 255, 141, 72, 16, 255, 17, 11, 6, 221, 0, 20,
+        9, 7, 4, 136, 114, 56, 13, 255, 143, 73, 16, 255, 139, 74, 16, 255,
+        19, 13, 6, 170, 0, 8, 8, 6, 3, 85, 110, 54, 13, 255, 143, 76, 16,
+        255, 141, 69, 16, 255, 18, 12, 5, 252, 0, 12, 11, 9, 6, 170, 131,
+        69, 18, 255, 170, 87, 19, 255, 168, 86, 19, 255, 28, 19, 9, 170, 0,
+        8, 11, 8, 6, 85, 145, 74, 26, 255, 204, 102, 27, 255, 203, 105, 26,
+        255, 52, 33, 17, 255, 6, 5, 5, 57, 0, 8, 17, 14, 10, 227, 190, 107,
+        25, 255, 204, 113, 25, 255, 174, 86, 27, 255, 18, 13, 9, 170, 0, 12,
+        28, 18, 11, 198, 37, 23, 14, 255, 32, 21, 13, 255, 21, 15, 10, 255,
+        20, 14, 9, 255, 38, 23, 11, 255, 87, 44, 12, 255, 137, 70, 16, 255,
+        141, 72, 16, 255, 143, 70, 16, 255, 141, 72, 16, 255, 18, 12, 5,
+        170, 0, 8, 9, 6, 4, 85, 110, 54, 13, 255, 145, 74, 16, 255, 141, 69,
+        16, 255, 94, 47, 13, 255, 27, 17, 8, 227, 12, 8, 5, 28, 0, 8, 14,
+        10, 7, 85, 121, 62, 18, 255, 172, 87, 19, 255, 139, 69, 18, 255, 20,
+        15, 9, 227, 0, 36, 21, 14, 8, 227, 117, 61, 24, 255, 199, 100, 28,
+        255, 205, 106, 26, 255, 204, 110, 27, 255, 26, 18, 11, 255, 0, 16,
+        8, 7, 5, 28, 20, 15, 11, 227, 135, 73, 22, 255, 192, 97, 21, 255,
+        165, 83, 22, 255, 33, 22, 12, 255, 10, 9, 7, 85, 0, 68, 11, 9, 6,
+        170, 184, 97, 27, 255, 206, 112, 29, 255, 204, 110, 27, 255, 28, 19,
+        11, 255, 0, 68, 14, 11, 7, 170, 179, 93, 24, 255, 202, 103, 23, 255,
+        198, 97, 23, 255, 22, 15, 9, 255, 0, 132, 9, 7, 6, 170, 125, 63, 18,
+        255, 158, 77, 17, 255, 146, 75, 17, 255, 17, 12, 6, 255, 0, 76, 8,
+        6, 5, 76, 72, 46, 23, 255, 197, 108, 28, 255, 201, 107, 24, 255,
+        164, 85, 27, 255, 37, 22, 14, 227, 13, 9, 6, 48, 0, 68, 12, 9, 7,
+        170, 138, 67, 19, 255, 170, 79, 19, 255, 168, 86, 19, 255, 20, 14,
+        9, 255, 0, 40, 8, 7, 5, 20, 21, 15, 10, 184, 26, 17, 11, 255, 26,
+        17, 11, 215, 12, 9, 7, 74, 0, 24, 8, 7, 5, 20, 21, 15, 10, 184, 26,
+        17, 11, 255, 31, 21, 12, 207, 18, 13, 9, 28, 0, 8, 11, 9, 8, 156,
+        184, 93, 27, 255, 208, 105, 29, 255, 205, 111, 28, 255, 28, 19, 11,
+        255, 0, 40, 14, 11, 7, 170, 184, 92, 25, 255, 203, 104, 24, 255,
+        200, 98, 23, 255, 26, 18, 11, 255, 0, 255, 0, 189, 8, 7, 5, 57, 51,
+        29, 12, 255, 152, 75, 19, 255, 162, 86, 19, 255, 19, 13, 8, 246, 0,
+        255, 0, 137, 6, 5, 3, 28, 19, 13, 6, 249, 92, 46, 13, 255, 123, 63,
+        14, 255, 78, 39, 11, 255, 21, 15, 6, 227, 9, 8, 4, 28, 0, 8, 9, 8,
+        4, 85, 110, 59, 13, 255, 141, 69, 16, 255, 141, 75, 16, 255, 21, 14,
+        6, 170, 0, 12, 16, 11, 5, 170, 52, 28, 9, 255, 115, 59, 14, 255,
+        116, 60, 15, 255, 43, 26, 10, 255, 9, 7, 6, 125, 0, 16, 8, 7, 5, 28,
+        21, 17, 10, 227, 109, 59, 18, 255, 160, 82, 19, 255, 121, 64, 18,
+        255, 62, 34, 13, 255, 94, 53, 17, 255, 149, 78, 20, 255, 102, 54,
+        19, 255, 32, 22, 11, 255, 72, 39, 15, 255, 121, 62, 18, 255, 24, 17,
+        9, 187, 0, 40, 8, 6, 3, 167, 128, 66, 15, 255, 161, 85, 17, 255,
+        159, 81, 18, 255, 24, 15, 7, 178, 0, 4, 6, 5, 3, 37, 48, 28, 11,
+        255, 173, 92, 20, 255, 181, 96, 20, 255, 21, 15, 8, 221, 0, 4, 6, 5,
+        3, 28, 40, 24, 9, 255, 143, 74, 18, 255, 158, 80, 17, 255, 21, 15,
+        6, 181, 0, 8, 10, 8, 5, 54, 107, 51, 14, 255, 157, 83, 18, 255, 164,
+        84, 19, 255, 176, 89, 19, 255, 189, 92, 20, 255, 191, 98, 22, 255,
+        190, 106, 23, 255, 197, 110, 26, 255, 203, 108, 24, 255, 203, 117,
+        24, 255, 205, 119, 26, 255, 207, 122, 30, 255, 199, 118, 32, 255,
+        32, 23, 13, 170, 0, 12, 7, 6, 4, 85, 22, 15, 7, 232, 113, 54, 14,
+        255, 146, 75, 17, 255, 158, 80, 17, 255, 154, 78, 17, 255, 158, 80,
+        17, 255, 148, 76, 17, 255, 139, 71, 16, 255, 135, 66, 16, 255, 135,
+        66, 16, 255, 21, 14, 6, 136, 0, 8, 10, 8, 5, 85, 128, 66, 15, 255,
+        161, 85, 17, 255, 158, 80, 17, 255, 25, 16, 6, 204, 0, 12, 7, 6, 4,
+        28, 25, 16, 8, 227, 102, 50, 15, 255, 148, 76, 17, 255, 142, 73, 17,
+        255, 84, 45, 13, 255, 10, 8, 5, 113, 0, 8, 9, 7, 4, 82, 107, 53, 14,
+        255, 146, 75, 17, 255, 84, 41, 13, 255, 8, 7, 5, 198, 3, 2, 2, 23,
+        5, 4, 4, 136, 38, 23, 9, 255, 136, 70, 17, 255, 140, 72, 17, 255,
+        21, 15, 6, 178, 0, 24, 7, 6, 4, 57, 45, 26, 10, 255, 143, 74, 18,
+        255, 158, 80, 17, 255, 26, 17, 6, 170, 0, 12, 24, 16, 7, 227, 115,
+        58, 16, 255, 148, 76, 17, 255, 46, 26, 9, 255, 7, 6, 4, 156, 0, 16,
+        5, 4, 4, 71, 19, 13, 6, 255, 139, 71, 16, 255, 140, 72, 17, 255, 43,
+        26, 10, 255, 9, 8, 4, 85, 0, 16, 14, 10, 5, 85, 109, 52, 14, 255,
+        38, 23, 9, 255, 6, 5, 3, 85, 0, 12, 4, 4, 3, 28, 15, 12, 6, 227,
+        115, 56, 16, 255, 29, 19, 8, 170, 0, 32, 13, 10, 6, 113, 122, 64,
+        21, 255, 164, 85, 21, 255, 138, 71, 17, 255, 21, 15, 6, 161, 0, 156,
+        13, 10, 6, 227, 137, 67, 16, 255, 154, 75, 17, 255, 84, 45, 13, 255,
+        10, 8, 5, 116, 0, 8, 9, 7, 4, 85, 111, 55, 14, 255, 158, 87, 17,
+        255, 158, 80, 17, 255, 19, 13, 6, 255, 4, 4, 3, 28, 0, 4, 3, 3, 2,
+        113, 17, 12, 6, 255, 139, 71, 16, 255, 161, 85, 17, 255, 146, 75,
+        17, 255, 20, 14, 7, 210, 0, 16, 16, 13, 9, 110, 184, 105, 27, 255,
+        209, 123, 30, 255, 210, 124, 31, 255, 208, 123, 31, 255, 207, 122,
+        30, 255, 27, 20, 12, 255, 0, 24, 13, 11, 8, 147, 143, 75, 20, 255,
+        161, 85, 17, 255, 158, 80, 17, 255, 27, 18, 8, 227, 5, 4, 2, 28, 0,
+        8, 10, 7, 5, 198, 131, 65, 16, 255, 161, 85, 17, 255, 150, 76, 17,
+        255, 21, 14, 6, 170, 0, 8, 10, 8, 5, 85, 123, 61, 16, 255, 163, 83,
+        18, 255, 158, 80, 17, 255, 27, 18, 8, 227, 5, 4, 2, 28, 0, 8, 9, 7,
+        4, 198, 130, 66, 15, 255, 163, 83, 18, 255, 148, 76, 17, 255, 21,
+        14, 6, 193, 0, 28, 7, 6, 4, 85, 22, 15, 7, 255, 131, 65, 16, 255,
+        154, 78, 17, 255, 154, 78, 17, 255, 154, 78, 17, 255, 154, 78, 17,
+        255, 21, 15, 6, 170, 0, 8, 10, 8, 5, 85, 129, 64, 16, 255, 163, 86,
+        18, 255, 180, 91, 19, 255, 29, 20, 10, 255, 3, 3, 2, 93, 0, 36, 10,
+        8, 5, 122, 121, 60, 16, 255, 161, 85, 17, 255, 159, 81, 18, 255, 24,
+        15, 7, 255, 4, 4, 3, 34, 0, 4, 2, 2, 1, 6, 17, 13, 8, 181, 181, 93,
+        22, 255, 203, 108, 24, 255, 205, 114, 26, 255, 32, 23, 13, 210, 0,
+        36, 5, 4, 4, 161, 30, 22, 13, 255, 198, 116, 29, 255, 206, 106, 25,
+        255, 191, 96, 20, 255, 26, 17, 7, 170, 0, 8, 9, 7, 4, 85, 116, 60,
+        15, 255, 161, 85, 17, 255, 158, 80, 17, 255, 21, 14, 6, 255, 5, 4,
+        2, 28, 0, 4, 2, 2, 1, 3, 12, 9, 7, 215, 190, 107, 25, 255, 211, 124,
+        30, 255, 208, 134, 37, 255, 32, 22, 13, 178, 0, 8, 13, 11, 8, 96,
+        187, 112, 32, 255, 209, 123, 30, 255, 191, 96, 20, 255, 28, 19, 9,
+        255, 4, 3, 3, 74, 0, 4, 3, 2, 2, 28, 13, 10, 8, 227, 196, 120, 31,
+        255, 211, 124, 30, 255, 199, 106, 24, 255, 27, 19, 10, 170, 0, 8,
+        13, 10, 6, 57, 114, 61, 19, 255, 178, 91, 21, 255, 182, 102, 23,
+        255, 23, 17, 10, 173, 0, 8, 11, 9, 6, 91, 146, 85, 25, 255, 198,
+        113, 29, 255, 196, 120, 31, 255, 27, 20, 12, 207, 0, 20, 5, 5, 4,
+        28, 21, 17, 12, 227, 190, 118, 33, 255, 209, 131, 40, 255, 161, 100,
+        34, 255, 17, 14, 10, 227, 5, 5, 4, 28, 0, 72, 9, 8, 6, 170, 91, 59,
+        28, 255, 189, 94, 24, 255, 162, 83, 19, 255, 39, 25, 12, 255, 7, 7,
+        6, 85, 0, 20, 13, 11, 8, 142, 183, 103, 24, 255, 203, 112, 24, 255,
+        203, 112, 24, 255, 42, 26, 13, 249, 5, 4, 4, 62, 0, 4, 3, 2, 2, 25,
+        12, 9, 7, 227, 195, 115, 30, 255, 212, 127, 35, 255, 211, 132, 38,
+        255, 32, 22, 13, 181, 0, 8, 12, 10, 7, 85, 124, 65, 17, 255, 161,
+        85, 17, 255, 159, 78, 18, 255, 21, 14, 6, 255, 5, 4, 2, 28, 0, 8, 7,
+        6, 4, 224, 133, 68, 16, 255, 159, 81, 18, 255, 146, 72, 17, 255, 22,
+        14, 7, 170, 0, 8, 13, 11, 8, 91, 185, 111, 32, 255, 210, 125, 33,
+        255, 205, 114, 26, 255, 37, 26, 14, 255, 4, 4, 3, 85, 0, 4, 4, 4, 4,
+        28, 13, 10, 8, 227, 193, 105, 26, 255, 206, 111, 27, 255, 202, 118,
+        27, 255, 32, 22, 13, 170, 0, 8, 11, 9, 6, 127, 174, 91, 23, 255,
+        202, 102, 21, 255, 200, 105, 21, 255, 36, 23, 13, 255, 4, 4, 3, 85,
+        0, 4, 3, 3, 2, 28, 13, 11, 8, 227, 198, 118, 33, 255, 212, 127, 35,
+        255, 208, 128, 33, 255, 31, 22, 12, 181, 0, 8, 13, 11, 8, 91, 185,
+        114, 30, 255, 211, 124, 30, 255, 208, 122, 29, 255, 34, 24, 13, 255,
+        4, 4, 3, 85, 0, 4, 7, 6, 6, 113, 32, 24, 13, 255, 185, 95, 22, 255,
+        202, 98, 21, 255, 198, 97, 23, 255, 33, 22, 12, 170, 0, 8, 10, 8, 7,
+        156, 190, 108, 27, 255, 212, 126, 33, 255, 211, 127, 36, 255, 40,
+        26, 15, 255, 4, 4, 3, 85, 0, 4, 3, 3, 2, 28, 13, 11, 8, 227, 198,
+        118, 33, 255, 214, 129, 37, 255, 211, 132, 38, 255, 32, 23, 13, 173,
+        0, 8, 10, 8, 7, 144, 167, 87, 22, 255, 185, 94, 20, 255, 165, 87,
+        18, 255, 25, 17, 8, 255, 3, 3, 2, 57, 0, 28, 13, 11, 8, 170, 195,
+        112, 30, 255, 210, 125, 33, 255, 208, 117, 29, 255, 39, 26, 14, 255,
+        4, 4, 3, 85, 0, 28, 12, 10, 7, 150, 184, 108, 27, 255, 211, 124, 30,
+        255, 211, 127, 36, 255, 40, 27, 15, 255, 4, 4, 3, 85, 0, 4, 3, 3, 2,
+        28, 17, 13, 8, 178, 138, 71, 17, 255, 161, 85, 17, 255, 155, 79, 18,
+        255, 21, 14, 6, 170, 0, 8, 10, 8, 5, 85, 124, 61, 15, 255, 169, 89,
+        18, 255, 180, 91, 19, 255, 25, 18, 10, 255, 0, 12, 13, 11, 8, 170,
+        196, 113, 31, 255, 211, 124, 30, 255, 205, 119, 26, 255, 26, 18, 11,
+        204, 0, 8, 11, 9, 6, 88, 134, 70, 19, 255, 173, 87, 18, 255, 168,
+        86, 19, 255, 20, 13, 7, 255, 0, 40, 13, 11, 8, 170, 196, 113, 31,
+        255, 210, 125, 33, 255, 207, 122, 30, 255, 24, 18, 11, 212, 0, 8,
+        11, 9, 6, 119, 180, 93, 23, 255, 203, 108, 24, 255, 202, 103, 23,
+        255, 20, 15, 9, 255, 0, 8, 15, 13, 10, 195, 101, 63, 26, 255, 202,
+        117, 25, 255, 206, 128, 35, 255, 160, 106, 35, 255, 15, 13, 10, 142,
+        0, 8, 10, 8, 5, 147, 139, 70, 20, 255, 191, 96, 20, 255, 200, 105,
+        21, 255, 25, 18, 10, 255, 0, 32, 13, 10, 8, 170, 189, 99, 26, 255,
+        206, 115, 27, 255, 205, 106, 26, 255, 185, 106, 28, 255, 79, 52, 26,
+        255, 10, 9, 7, 122, 0, 4, 7, 6, 6, 42, 36, 27, 17, 244, 172, 106,
+        35, 255, 207, 128, 34, 255, 211, 126, 34, 255, 211, 127, 36, 255,
+        24, 18, 11, 227, 0, 8, 10, 8, 5, 85, 124, 64, 15, 255, 159, 81, 18,
+        255, 158, 80, 17, 255, 76, 40, 13, 255, 11, 8, 6, 210, 0, 8, 12, 9,
+        5, 85, 129, 64, 16, 255, 161, 85, 17, 255, 158, 80, 17, 255, 26, 16,
+        7, 170, 0, 8, 9, 7, 4, 85, 115, 56, 16, 255, 161, 85, 17, 255, 159,
+        81, 18, 255, 49, 27, 10, 255, 7, 6, 4, 170, 5, 4, 4, 85, 6, 5, 3,
+        113, 26, 19, 11, 255, 185, 95, 22, 255, 202, 102, 21, 255, 197, 104,
+        22, 255, 28, 20, 11, 173, 0, 8, 13, 10, 6, 102, 167, 87, 22, 255,
+        200, 101, 21, 255, 201, 102, 22, 255, 32, 21, 11, 255, 4, 3, 3, 65,
+        0, 4, 2, 2, 1, 17, 12, 10, 7, 221, 190, 98, 23, 255, 208, 116, 27,
+        255, 204, 110, 27, 255, 30, 21, 11, 181, 0, 8, 13, 11, 8, 91, 185,
+        114, 30, 255, 211, 124, 30, 255, 209, 123, 30, 255, 86, 55, 25, 255,
+        9, 8, 6, 187, 6, 6, 5, 85, 7, 6, 6, 130, 32, 24, 15, 255, 200, 122,
+        31, 255, 209, 123, 30, 255, 206, 122, 31, 255, 32, 23, 13, 173, 0,
+        8, 10, 8, 7, 144, 191, 113, 30, 255, 212, 127, 35, 255, 210, 126,
+        35, 255, 40, 27, 15, 255, 4, 4, 3, 85, 0, 4, 2, 2, 1, 8, 11, 9, 6,
+        212, 157, 81, 20, 255, 189, 92, 20, 255, 190, 97, 21, 255, 27, 19,
+        10, 178, 0, 8, 12, 10, 7, 96, 183, 105, 28, 255, 209, 123, 30, 255,
+        205, 114, 26, 255, 36, 24, 13, 255, 4, 4, 3, 85, 0, 4, 4, 4, 4, 28,
+        18, 14, 9, 187, 195, 115, 30, 255, 211, 124, 30, 255, 210, 130, 35,
+        255, 35, 26, 14, 210, 0, 20, 3, 2, 2, 28, 12, 10, 7, 227, 195, 115,
+        30, 255, 211, 124, 30, 255, 209, 123, 30, 255, 38, 25, 15, 255, 4,
+        4, 3, 85, 0, 20, 13, 11, 8, 170, 194, 115, 31, 255, 209, 122, 28,
+        255, 196, 99, 21, 255, 21, 15, 8, 255, 0, 12, 11, 9, 6, 170, 153,
+        79, 20, 255, 187, 91, 20, 255, 181, 96, 20, 255, 30, 20, 9, 178, 0,
+        8, 13, 10, 6, 96, 151, 79, 20, 255, 187, 91, 20, 255, 181, 96, 20,
+        255, 22, 16, 9, 255, 0, 12, 12, 9, 7, 170, 146, 76, 19, 255, 167,
+        88, 18, 255, 158, 77, 17, 255, 23, 15, 6, 170, 0, 8, 10, 8, 5, 85,
+        133, 66, 16, 255, 167, 88, 18, 255, 168, 86, 19, 255, 22, 16, 9,
+        255, 0, 20, 12, 9, 7, 170, 155, 80, 20, 255, 185, 94, 20, 255, 181,
+        96, 20, 255, 22, 16, 9, 221, 0, 8, 6, 6, 5, 42, 51, 29, 12, 255,
+        150, 81, 19, 255, 165, 87, 18, 255, 42, 26, 11, 255, 5, 5, 4, 108,
+        0, 4, 5, 5, 4, 28, 18, 15, 11, 255, 195, 114, 28, 255, 207, 123, 32,
+        255, 158, 94, 31, 255, 17, 13, 10, 142, 0, 8, 6, 5, 5, 57, 50, 34,
+        19, 255, 191, 111, 32, 255, 208, 117, 29, 255, 113, 73, 30, 255, 10,
+        10, 9, 227, 6, 6, 5, 125, 7, 7, 6, 198, 42, 29, 17, 255, 187, 96,
+        22, 255, 166, 87, 23, 255, 42, 27, 15, 255, 8, 6, 5, 110, 0, 32, 5,
+        5, 4, 184, 21, 16, 8, 255, 106, 54, 15, 255, 154, 78, 17, 255, 151,
+        77, 18, 255, 92, 48, 15, 255, 11, 9, 6, 119, 0, 8, 10, 8, 5, 93,
+        131, 69, 18, 255, 189, 92, 20, 255, 200, 105, 21, 255, 33, 22, 12,
+        255, 5, 4, 4, 54, 0, 12, 9, 8, 6, 85, 76, 53, 25, 255, 200, 118, 31,
+        255, 204, 114, 27, 255, 65, 43, 22, 255, 6, 6, 5, 113, 0, 32, 4, 3,
+        3, 17, 14, 11, 9, 227, 195, 111, 28, 255, 206, 115, 27, 255, 204,
+        105, 25, 255, 24, 17, 11, 255, 0, 12, 5, 5, 4, 28, 13, 10, 6, 227,
+        125, 66, 18, 255, 165, 84, 18, 255, 161, 85, 17, 255, 161, 85, 17,
+        255, 155, 79, 18, 255, 28, 19, 9, 255, 6, 5, 3, 85, 0, 64, 11, 9, 8,
+        68, 86, 56, 27, 255, 204, 126, 33, 255, 210, 125, 33, 255, 30, 21,
+        13, 255, 0, 68, 13, 11, 8, 170, 195, 115, 30, 255, 209, 123, 30,
+        255, 207, 122, 30, 255, 27, 19, 12, 255, 3, 3, 2, 28, 0, 128, 7, 6,
+        4, 184, 131, 65, 16, 255, 161, 85, 17, 255, 154, 78, 17, 255, 15,
+        11, 6, 249, 0, 76, 10, 8, 7, 173, 166, 87, 23, 255, 198, 104, 21,
+        255, 196, 99, 21, 255, 35, 23, 12, 255, 3, 3, 2, 85, 0, 72, 13, 11,
+        8, 170, 194, 115, 31, 255, 211, 124, 30, 255, 207, 122, 30, 255, 27,
+        19, 12, 255, 3, 3, 2, 28, 0, 108, 13, 11, 8, 170, 196, 113, 31, 255,
+        213, 132, 36, 255, 211, 127, 36, 255, 30, 21, 13, 255, 0, 40, 11, 9,
+        6, 170, 155, 80, 20, 255, 185, 94, 20, 255, 180, 91, 19, 255, 21,
+        15, 8, 255, 0, 255, 0, 189, 10, 8, 7, 184, 183, 100, 26, 255, 208,
+        116, 27, 255, 204, 114, 27, 255, 26, 18, 11, 255, 4, 4, 4, 28, 0,
+        255, 0, 133, 10, 8, 5, 127, 119, 60, 15, 255, 160, 85, 19, 255, 91,
+        48, 16, 255, 10, 8, 5, 227, 4, 4, 3, 28, 0, 12, 9, 7, 4, 161, 131,
+        67, 16, 255, 159, 81, 18, 255, 159, 78, 18, 255, 18, 13, 7, 249, 0,
+        16, 7, 6, 4, 170, 57, 34, 14, 255, 176, 90, 21, 255, 195, 95, 22,
+        255, 26, 19, 11, 232, 0, 16, 17, 14, 10, 99, 179, 106, 28, 255, 207,
+        122, 30, 255, 180, 109, 33, 255, 25, 20, 12, 255, 7, 6, 6, 170, 20,
+        17, 11, 255, 196, 114, 27, 255, 208, 117, 29, 255, 203, 124, 30,
+        255, 172, 106, 35, 255, 53, 36, 20, 255, 10, 9, 7, 108, 0, 40, 9, 8,
+        6, 170, 159, 82, 20, 255, 202, 103, 23, 255, 206, 111, 27, 255, 22,
+        17, 11, 255, 0, 8, 10, 9, 7, 139, 115, 74, 30, 255, 213, 133, 48,
+        255, 39, 28, 16, 255, 0, 8, 9, 8, 4, 113, 67, 39, 14, 255, 181, 92,
+        20, 255, 24, 18, 9, 255, 0, 12, 28, 19, 9, 227, 139, 79, 26, 255,
+        206, 117, 31, 255, 212, 123, 37, 255, 214, 126, 41, 255, 172, 106,
+        35, 255, 53, 34, 18, 255, 122, 78, 31, 255, 211, 127, 44, 255, 217,
+        136, 50, 255, 216, 135, 49, 255, 190, 122, 41, 255, 65, 43, 22, 255,
+        14, 11, 7, 85, 0, 8, 7, 6, 4, 28, 29, 21, 10, 249, 153, 79, 20, 255,
+        174, 85, 19, 255, 103, 53, 16, 255, 17, 12, 6, 244, 19, 13, 6, 170,
+        21, 14, 6, 170, 27, 17, 6, 170, 21, 14, 6, 212, 21, 14, 6, 255, 25,
+        17, 6, 224, 12, 9, 5, 45, 0, 12, 24, 16, 7, 153, 22, 15, 7, 255, 26,
+        16, 7, 210, 12, 9, 5, 40, 0, 8, 8, 7, 5, 28, 17, 13, 8, 227, 114,
+        61, 19, 255, 174, 85, 19, 255, 154, 79, 19, 255, 60, 33, 13, 255,
+        11, 9, 6, 170, 0, 12, 10, 8, 5, 170, 146, 79, 19, 255, 180, 87, 19,
+        255, 67, 39, 14, 255, 8, 6, 5, 85, 0, 8, 24, 17, 9, 255, 143, 75,
+        20, 255, 162, 80, 19, 255, 22, 15, 7, 215, 0, 28, 8, 7, 5, 110, 60,
+        33, 13, 255, 166, 78, 19, 255, 22, 15, 7, 227, 0, 8, 7, 6, 4, 85,
+        91, 51, 16, 255, 174, 88, 19, 255, 169, 78, 18, 255, 25, 17, 8, 255,
+        3, 3, 2, 8, 0, 20, 11, 9, 6, 178, 143, 74, 18, 255, 177, 89, 18,
+        255, 138, 75, 19, 255, 18, 13, 7, 176, 0, 16, 9, 7, 4, 28, 29, 19,
+        8, 232, 41, 25, 10, 255, 17, 13, 8, 255, 9, 8, 6, 116, 0, 4, 7, 6,
+        4, 59, 14, 11, 7, 227, 32, 21, 9, 255, 40, 24, 9, 255, 12, 9, 5,
+        105, 0, 32, 14, 11, 9, 170, 199, 124, 36, 255, 213, 119, 36, 255,
+        202, 102, 21, 255, 20, 14, 7, 246, 0, 152, 8, 7, 5, 142, 53, 31, 12,
+        255, 162, 86, 19, 255, 121, 64, 18, 255, 19, 14, 8, 252, 6, 5, 3,
+        28, 0, 8, 10, 8, 5, 125, 142, 74, 19, 255, 180, 91, 19, 255, 183,
+        89, 19, 255, 19, 14, 8, 255, 0, 4, 5, 5, 4, 6, 15, 13, 10, 193, 69,
+        42, 18, 255, 171, 91, 20, 255, 189, 88, 20, 255, 200, 101, 21, 255,
+        31, 21, 12, 255, 0, 16, 10, 8, 7, 28, 30, 21, 13, 227, 150, 92, 35,
+        255, 208, 121, 37, 255, 211, 115, 30, 255, 208, 117, 29, 255, 28,
+        21, 13, 255, 0, 24, 10, 8, 7, 28, 22, 15, 7, 198, 26, 17, 7, 255,
+        24, 15, 7, 221, 9, 7, 4, 57, 0, 12, 8, 7, 5, 156, 171, 89, 22, 255,
+        202, 107, 23, 255, 202, 103, 23, 255, 23, 18, 10, 249, 0, 12, 26,
+        18, 9, 198, 29, 19, 8, 255, 24, 16, 7, 215, 10, 8, 5, 51, 0, 12, 10,
+        8, 5, 85, 134, 70, 19, 255, 175, 88, 18, 255, 173, 87, 18, 255, 20,
+        14, 7, 255, 0, 24, 10, 8, 5, 85, 26, 19, 9, 255, 107, 58, 18, 255,
+        154, 83, 19, 255, 168, 79, 19, 255, 169, 78, 18, 255, 173, 87, 18,
+        255, 172, 80, 19, 255, 26, 17, 7, 170, 0, 8, 11, 10, 8, 136, 189,
+        99, 26, 255, 210, 115, 31, 255, 216, 129, 45, 255, 143, 96, 40, 255,
+        15, 13, 10, 227, 12, 12, 11, 170, 15, 13, 12, 170, 13, 12, 10, 170,
+        13, 12, 10, 136, 9, 8, 8, 85, 0, 16, 11, 9, 6, 170, 169, 91, 22,
+        255, 202, 103, 23, 255, 203, 108, 24, 255, 18, 15, 9, 255, 0, 12, 6,
+        5, 5, 23, 28, 19, 11, 156, 31, 22, 12, 255, 34, 24, 13, 227, 14, 11,
+        7, 85, 0, 36, 9, 8, 8, 142, 72, 54, 31, 255, 215, 147, 60, 255, 218,
+        146, 61, 255, 174, 100, 35, 255, 14, 11, 7, 142, 0, 8, 11, 8, 6,
+        102, 142, 74, 19, 255, 185, 86, 20, 255, 195, 98, 20, 255, 18, 14,
+        9, 249, 0, 12, 10, 8, 7, 170, 202, 131, 47, 255, 220, 152, 63, 255,
+        220, 151, 61, 255, 22, 19, 13, 252, 0, 8, 11, 9, 8, 167, 203, 135,
+        46, 255, 217, 139, 48, 255, 210, 120, 33, 255, 18, 14, 9, 255, 0,
+        12, 9, 8, 6, 170, 198, 117, 37, 255, 211, 115, 30, 255, 202, 102,
+        21, 255, 34, 22, 11, 176, 0, 8, 13, 11, 8, 170, 202, 122, 37, 255,
+        218, 144, 49, 255, 217, 144, 50, 255, 28, 21, 13, 255, 0, 8, 12, 11,
+        9, 170, 204, 122, 41, 255, 217, 135, 46, 255, 215, 136, 42, 255, 46,
+        33, 19, 255, 0, 16, 10, 9, 7, 28, 21, 19, 14, 227, 153, 104, 46,
+        255, 214, 149, 55, 255, 158, 103, 39, 255, 16, 14, 11, 221, 7, 6, 6,
+        28, 0, 20, 20, 18, 13, 142, 31, 26, 18, 170, 25, 21, 16, 170, 24,
+        20, 15, 170, 24, 20, 15, 170, 24, 20, 15, 170, 24, 21, 15, 170, 31,
+        26, 18, 170, 25, 21, 16, 170, 14, 12, 9, 31, 0, 20, 10, 9, 7, 167,
+        75, 51, 26, 255, 202, 117, 33, 255, 186, 120, 43, 255, 41, 32, 20,
+        255, 12, 11, 9, 85, 0, 16, 11, 9, 8, 28, 31, 22, 12, 215, 49, 33,
+        18, 255, 41, 27, 16, 227, 12, 10, 7, 85, 0, 12, 14, 12, 9, 170, 204,
+        137, 51, 255, 220, 152, 63, 255, 220, 151, 61, 255, 23, 19, 12, 252,
+        0, 8, 11, 10, 6, 85, 136, 70, 17, 255, 175, 88, 18, 255, 169, 78,
+        18, 255, 15, 11, 6, 255, 0, 8, 9, 8, 6, 85, 26, 19, 9, 255, 153, 82,
+        18, 255, 177, 89, 18, 255, 180, 84, 19, 255, 24, 17, 9, 218, 0, 8,
+        11, 9, 8, 147, 196, 115, 35, 255, 215, 125, 38, 255, 214, 125, 39,
+        255, 20, 16, 11, 255, 0, 12, 9, 8, 6, 159, 165, 86, 22, 255, 197,
+        99, 20, 255, 195, 90, 20, 255, 32, 21, 11, 170, 0, 8, 12, 10, 7, 85,
+        145, 76, 20, 255, 189, 92, 20, 255, 191, 96, 20, 255, 18, 14, 9,
+        255, 0, 12, 9, 8, 6, 170, 199, 126, 39, 255, 217, 133, 50, 255, 217,
+        144, 50, 255, 23, 18, 12, 252, 0, 8, 11, 10, 8, 142, 191, 105, 28,
+        255, 206, 111, 27, 255, 203, 104, 24, 255, 19, 15, 10, 255, 0, 12,
+        9, 8, 6, 57, 21, 15, 8, 198, 28, 19, 9, 255, 32, 21, 11, 227, 11, 9,
+        6, 76, 0, 8, 11, 9, 8, 170, 203, 125, 42, 255, 220, 146, 59, 255,
+        219, 146, 60, 255, 24, 19, 13, 255, 0, 12, 11, 10, 8, 170, 204, 136,
+        47, 255, 220, 146, 59, 255, 218, 147, 55, 255, 25, 19, 12, 232, 0,
+        8, 11, 10, 8, 119, 161, 87, 22, 255, 195, 98, 20, 255, 202, 103, 23,
+        255, 18, 15, 9, 255, 0, 32, 14, 12, 9, 170, 200, 125, 37, 255, 214,
+        124, 37, 255, 205, 106, 26, 255, 20, 16, 9, 221, 0, 32, 16, 13, 9,
+        170, 205, 130, 42, 255, 219, 144, 56, 255, 219, 146, 60, 255, 24,
+        19, 13, 255, 0, 12, 6, 5, 3, 23, 21, 14, 6, 170, 26, 16, 7, 255, 26,
+        17, 7, 224, 14, 10, 5, 31, 0, 8, 11, 9, 6, 125, 170, 89, 23, 255,
+        211, 115, 30, 255, 214, 126, 41, 255, 23, 19, 12, 255, 0, 12, 11,
+        10, 8, 170, 195, 112, 30, 255, 206, 106, 25, 255, 200, 105, 21, 255,
+        29, 20, 10, 170, 0, 8, 11, 9, 6, 85, 134, 70, 19, 255, 177, 85, 18,
+        255, 172, 80, 19, 255, 18, 13, 7, 255, 0, 40, 14, 12, 9, 170, 195,
+        112, 30, 255, 206, 111, 27, 255, 202, 103, 23, 255, 31, 22, 10, 170,
+        0, 8, 13, 10, 6, 85, 151, 79, 20, 255, 189, 92, 20, 255, 183, 89,
+        19, 255, 17, 13, 8, 255, 0, 4, 8, 7, 5, 59, 57, 34, 16, 255, 184,
+        97, 27, 255, 198, 115, 33, 255, 114, 77, 33, 255, 16, 14, 11, 210,
+        6, 5, 5, 8, 0, 8, 12, 10, 7, 170, 195, 113, 32, 255, 215, 123, 42,
+        255, 217, 133, 50, 255, 32, 24, 15, 255, 0, 32, 12, 11, 7, 170, 175,
+        90, 22, 255, 198, 104, 21, 255, 189, 92, 20, 255, 192, 97, 21, 255,
+        189, 97, 22, 255, 45, 29, 14, 255, 10, 9, 7, 210, 22, 17, 11, 255,
+        183, 102, 30, 255, 212, 121, 41, 255, 216, 135, 49, 255, 217, 137,
+        52, 255, 214, 125, 39, 255, 29, 21, 12, 204, 0, 8, 11, 9, 6, 85,
+        143, 75, 20, 255, 193, 97, 20, 255, 195, 98, 20, 255, 180, 93, 23,
+        255, 88, 54, 23, 255, 11, 10, 8, 113, 0, 4, 14, 12, 7, 85, 170, 89,
+        23, 255, 202, 103, 23, 255, 202, 102, 21, 255, 32, 22, 11, 178, 0,
+        8, 12, 10, 7, 113, 176, 91, 23, 255, 205, 105, 24, 255, 209, 117,
+        28, 255, 39, 28, 16, 255, 5, 5, 5, 28, 0, 8, 15, 14, 10, 198, 206,
+        132, 45, 255, 217, 133, 50, 255, 215, 133, 44, 255, 25, 19, 12, 232,
+        0, 8, 11, 10, 8, 125, 198, 118, 39, 255, 218, 145, 51, 255, 218,
+        146, 53, 255, 20, 17, 11, 255, 0, 12, 9, 8, 6, 170, 198, 124, 37,
+        255, 216, 134, 45, 255, 214, 139, 41, 255, 22, 18, 11, 255, 0, 8,
+        11, 10, 8, 136, 191, 105, 28, 255, 206, 111, 27, 255, 206, 106, 25,
+        255, 36, 26, 15, 255, 5, 5, 4, 28, 0, 8, 15, 13, 10, 198, 192, 105,
+        27, 255, 206, 106, 25, 255, 204, 105, 25, 255, 23, 17, 10, 232, 0,
+        8, 12, 10, 7, 125, 196, 119, 37, 255, 218, 141, 51, 255, 218, 139,
+        55, 255, 20, 16, 11, 255, 0, 12, 9, 8, 6, 170, 196, 110, 33, 255,
+        215, 126, 40, 255, 214, 125, 39, 255, 23, 18, 12, 252, 0, 8, 11, 9,
+        8, 167, 201, 123, 40, 255, 217, 133, 50, 255, 214, 136, 43, 255, 20,
+        16, 11, 255, 0, 12, 6, 5, 5, 23, 29, 21, 12, 153, 32, 22, 13, 255,
+        35, 25, 14, 227, 15, 12, 8, 85, 0, 24, 12, 10, 9, 170, 198, 124, 37,
+        255, 215, 125, 38, 255, 213, 124, 38, 255, 23, 18, 12, 255, 0, 24,
+        14, 12, 9, 170, 204, 132, 47, 255, 219, 144, 56, 255, 211, 127, 36,
+        255, 28, 21, 13, 255, 0, 12, 14, 12, 9, 170, 198, 117, 37, 255, 215,
+        123, 42, 255, 214, 125, 39, 255, 25, 20, 12, 215, 0, 8, 11, 10, 8,
+        130, 198, 119, 35, 255, 215, 126, 40, 255, 212, 123, 37, 255, 30,
+        22, 13, 255, 0, 12, 14, 12, 9, 170, 196, 114, 33, 255, 206, 106, 25,
+        255, 200, 105, 21, 255, 30, 21, 11, 184, 0, 8, 13, 11, 8, 99, 184,
+        100, 25, 255, 209, 117, 28, 255, 210, 115, 31, 255, 28, 21, 13, 255,
+        0, 20, 14, 12, 9, 170, 198, 117, 37, 255, 215, 126, 40, 255, 214,
+        126, 41, 255, 25, 19, 12, 255, 0, 12, 10, 9, 7, 125, 61, 42, 22,
+        255, 190, 107, 33, 255, 153, 98, 38, 255, 29, 23, 16, 255, 13, 12,
+        10, 255, 17, 15, 10, 255, 108, 74, 37, 255, 210, 144, 59, 255, 153,
+        98, 38, 255, 16, 14, 11, 224, 6, 6, 5, 17, 0, 12, 15, 13, 8, 227,
+        115, 67, 24, 255, 197, 100, 22, 255, 150, 81, 25, 255, 32, 24, 13,
+        255, 15, 13, 8, 255, 19, 15, 10, 255, 85, 48, 18, 255, 178, 95, 21,
+        255, 115, 65, 20, 255, 15, 12, 8, 255, 5, 5, 4, 34, 0, 32, 10, 9, 7,
+        198, 69, 46, 22, 255, 186, 103, 29, 255, 195, 111, 28, 255, 92, 58,
+        25, 255, 15, 12, 8, 198, 0, 12, 10, 9, 7, 170, 194, 112, 31, 255,
+        215, 125, 38, 255, 218, 146, 53, 255, 24, 19, 13, 255, 0, 20, 15,
+        14, 10, 227, 159, 103, 42, 255, 212, 127, 43, 255, 177, 118, 48,
+        255, 19, 17, 12, 227, 6, 6, 5, 28, 0, 32, 11, 10, 8, 170, 182, 98,
+        23, 255, 202, 106, 21, 255, 195, 98, 20, 255, 24, 17, 9, 212, 0, 12,
+        18, 14, 9, 227, 102, 54, 19, 255, 157, 83, 18, 255, 85, 46, 14, 255,
+        19, 13, 6, 255, 47, 27, 10, 255, 150, 81, 19, 255, 131, 67, 20, 255,
+        39, 26, 14, 255, 12, 11, 9, 85, 0, 64, 10, 9, 7, 170, 118, 75, 33,
+        255, 215, 141, 54, 255, 44, 33, 19, 255, 0, 16, 9, 9, 8, 108, 19,
+        17, 12, 170, 27, 23, 16, 170, 23, 21, 16, 170, 23, 21, 16, 170, 24,
+        20, 15, 170, 20, 18, 13, 170, 15, 14, 10, 170, 10, 9, 7, 113, 7, 6,
+        6, 28, 0, 12, 12, 11, 9, 170, 189, 99, 26, 255, 209, 110, 30, 255,
+        211, 118, 36, 255, 141, 88, 36, 255, 19, 17, 12, 227, 20, 18, 13,
+        170, 24, 20, 15, 170, 21, 19, 14, 170, 16, 14, 11, 170, 10, 9, 7,
+        113, 6, 6, 5, 28, 0, 20, 8, 7, 5, 65, 11, 10, 8, 142, 16, 14, 11,
+        170, 24, 21, 15, 170, 25, 22, 16, 170, 23, 21, 16, 170, 21, 19, 14,
+        170, 16, 14, 11, 170, 11, 10, 8, 113, 7, 7, 6, 28, 0, 20, 8, 7, 5,
+        62, 10, 9, 5, 136, 12, 10, 7, 170, 14, 11, 7, 170, 13, 10, 6, 170,
+        11, 9, 6, 198, 31, 21, 10, 255, 153, 82, 18, 255, 177, 85, 18, 255,
+        169, 78, 18, 255, 22, 15, 7, 204, 0, 16, 8, 7, 5, 57, 11, 10, 6,
+        142, 19, 17, 12, 170, 23, 21, 16, 170, 25, 22, 16, 170, 23, 21, 16,
+        170, 21, 19, 14, 170, 15, 14, 10, 170, 10, 10, 9, 113, 7, 6, 6, 28,
+        0, 16, 12, 10, 7, 153, 55, 32, 14, 255, 175, 93, 20, 255, 185, 94,
+        20, 255, 183, 89, 19, 255, 80, 44, 17, 255, 13, 11, 8, 187, 7, 6, 6,
+        25, 0, 16, 8, 7, 5, 62, 11, 10, 6, 142, 16, 14, 11, 170, 23, 19, 14,
+        170, 25, 22, 16, 170, 23, 21, 16, 170, 19, 17, 12, 170, 15, 14, 10,
+        170, 17, 15, 10, 170, 19, 17, 12, 142, 9, 8, 8, 28, 0, 8, 12, 10, 9,
+        170, 204, 137, 49, 255, 220, 146, 59, 255, 218, 146, 53, 255, 141,
+        91, 38, 255, 19, 17, 12, 227, 19, 17, 12, 170, 24, 20, 15, 170, 21,
+        19, 14, 170, 15, 14, 10, 170, 10, 10, 9, 113, 7, 6, 6, 28, 0, 16,
+        12, 10, 7, 57, 14, 12, 7, 102, 14, 11, 7, 85, 0, 32, 12, 10, 7, 57,
+        13, 11, 8, 105, 15, 13, 8, 85, 0, 12, 12, 11, 9, 170, 204, 136, 47,
+        255, 220, 146, 59, 255, 218, 153, 59, 255, 24, 19, 13, 255, 0, 12,
+        8, 7, 5, 82, 11, 10, 6, 156, 11, 9, 6, 170, 10, 9, 7, 91, 0, 12, 10,
+        8, 5, 127, 144, 78, 19, 255, 180, 87, 19, 255, 174, 81, 19, 255, 24,
+        15, 7, 210, 0, 12, 14, 11, 7, 68, 12, 10, 7, 170, 12, 10, 7, 170,
+        17, 15, 10, 170, 24, 20, 15, 170, 19, 17, 12, 170, 15, 14, 10, 170,
+        18, 15, 11, 170, 24, 21, 15, 170, 21, 19, 14, 170, 15, 14, 10, 170,
+        11, 10, 8, 113, 7, 7, 6, 28, 0, 16, 15, 13, 10, 119, 17, 15, 12,
+        170, 15, 13, 10, 170, 16, 14, 11, 170, 19, 17, 12, 170, 21, 18, 12,
+        170, 18, 15, 11, 170, 15, 13, 8, 170, 11, 9, 6, 170, 10, 8, 7, 88,
+        6, 5, 5, 23, 0, 20, 10, 9, 7, 85, 14, 12, 9, 170, 19, 17, 12, 170,
+        21, 19, 14, 170, 21, 19, 14, 170, 21, 19, 14, 170, 19, 17, 12, 170,
+        15, 14, 10, 170, 11, 10, 8, 116, 7, 7, 6, 28, 0, 16, 15, 14, 10,
+        119, 18, 15, 11, 170, 15, 14, 10, 170, 18, 15, 11, 170, 21, 19, 14,
+        170, 25, 22, 16, 170, 23, 21, 16, 170, 21, 19, 14, 170, 16, 14, 11,
+        170, 11, 10, 8, 113, 7, 7, 6, 28, 0, 20, 10, 9, 7, 85, 14, 12, 9,
+        170, 19, 17, 12, 170, 20, 18, 13, 170, 20, 18, 13, 170, 23, 19, 14,
+        170, 19, 17, 12, 170, 15, 14, 10, 170, 17, 14, 10, 170, 19, 17, 12,
+        142, 10, 9, 7, 28, 0, 12, 15, 13, 10, 113, 18, 15, 11, 170, 15, 14,
+        10, 170, 18, 15, 11, 170, 21, 19, 14, 170, 25, 22, 16, 170, 23, 21,
+        16, 170, 20, 18, 13, 170, 16, 14, 11, 170, 11, 10, 8, 113, 7, 7, 6,
+        28, 0, 20, 7, 7, 6, 82, 11, 10, 6, 142, 16, 13, 9, 170, 19, 17, 12,
+        170, 21, 19, 14, 170, 24, 21, 15, 170, 25, 22, 16, 170, 25, 22, 16,
+        170, 15, 13, 10, 170, 12, 11, 9, 57, 0, 16, 15, 13, 10, 170, 97, 65,
+        34, 255, 209, 132, 42, 255, 214, 136, 43, 255, 214, 127, 43, 255,
+        159, 103, 42, 255, 21, 19, 14, 227, 11, 10, 8, 28, 0, 12, 16, 14,
+        11, 113, 21, 19, 14, 170, 18, 15, 11, 153, 11, 10, 8, 28, 0, 16, 15,
+        14, 10, 125, 21, 19, 14, 170, 19, 17, 12, 142, 10, 9, 7, 28, 0, 12,
+        15, 14, 10, 113, 21, 19, 14, 170, 18, 16, 11, 153, 11, 10, 8, 28, 0,
+        16, 15, 13, 10, 125, 21, 19, 14, 170, 19, 17, 12, 142, 10, 9, 7, 28,
+        0, 12, 15, 14, 10, 113, 21, 19, 14, 170, 18, 16, 11, 153, 11, 10, 8,
+        28, 0, 24, 15, 14, 10, 125, 21, 19, 14, 170, 19, 17, 12, 142, 9, 9,
+        8, 28, 0, 12, 17, 14, 10, 130, 27, 24, 16, 170, 21, 19, 14, 142, 10,
+        9, 7, 28, 0, 16, 16, 14, 11, 113, 28, 24, 17, 170, 24, 21, 15, 161,
+        12, 11, 9, 28, 0, 12, 16, 14, 11, 113, 21, 19, 14, 170, 18, 15, 11,
+        153, 11, 10, 8, 28, 0, 16, 15, 13, 10, 125, 21, 19, 14, 170, 19, 17,
+        12, 142, 9, 8, 6, 28, 0, 12, 18, 15, 11, 136, 19, 16, 10, 170, 16,
+        13, 9, 170, 16, 14, 9, 170, 15, 13, 8, 170, 13, 11, 8, 170, 12, 11,
+        9, 170, 13, 12, 8, 170, 15, 14, 10, 170, 14, 13, 11, 170, 11, 11,
+        10, 113, 0, 20, 13, 11, 8, 170, 190, 98, 23, 255, 204, 116, 31, 255,
+        74, 52, 27, 255, 9, 8, 8, 113, 0, 16, 13, 11, 8, 170, 192, 106, 29,
+        255, 208, 112, 27, 255, 208, 117, 29, 255, 27, 21, 12, 255, 0, 16,
+        5, 5, 4, 28, 27, 23, 16, 255, 199, 121, 44, 255, 214, 139, 41, 255,
+        31, 23, 14, 255, 0, 16, 13, 11, 8, 28, 32, 24, 13, 227, 36, 26, 15,
+        255, 19, 16, 12, 198, 8, 8, 7, 51, 0, 4, 8, 8, 7, 57, 29, 21, 12,
+        218, 48, 32, 17, 255, 45, 30, 16, 255, 20, 16, 11, 218, 10, 9, 7,
+        105, 0, 44, 14, 12, 9, 170, 204, 130, 51, 255, 224, 153, 77, 255,
+        225, 169, 88, 255, 33, 27, 18, 255, 0, 12, 21, 19, 14, 215, 217,
+        163, 86, 255, 61, 46, 28, 255, 0, 12, 19, 16, 12, 201, 203, 121, 40,
+        255, 51, 38, 22, 255, 0, 12, 4, 4, 3, 25, 16, 14, 11, 227, 212, 147,
+        71, 255, 224, 160, 77, 255, 223, 161, 80, 255, 31, 25, 16, 255, 4,
+        4, 4, 102, 10, 10, 9, 215, 206, 133, 55, 255, 223, 156, 70, 255,
+        224, 164, 85, 255, 51, 39, 24, 255, 5, 5, 4, 82, 0, 12, 15, 12, 8,
+        110, 178, 98, 27, 255, 211, 115, 30, 255, 211, 121, 34, 255, 36, 26,
+        15, 255, 3, 3, 2, 85, 0, 60, 8, 8, 5, 28, 27, 20, 10, 232, 125, 73,
+        22, 255, 190, 97, 21, 255, 180, 92, 21, 255, 97, 56, 20, 255, 14,
+        11, 7, 170, 0, 16, 12, 10, 7, 142, 165, 89, 22, 255, 198, 104, 21,
+        255, 84, 50, 19, 255, 7, 6, 4, 159, 0, 4, 5, 5, 4, 82, 32, 23, 11,
+        255, 121, 69, 22, 255, 97, 56, 20, 255, 15, 13, 8, 142, 0, 32, 14,
+        12, 7, 198, 172, 92, 21, 255, 28, 19, 9, 207, 0, 8, 11, 10, 6, 85,
+        148, 78, 21, 255, 198, 104, 21, 255, 192, 97, 21, 255, 21, 15, 8,
+        255, 0, 24, 10, 9, 5, 170, 167, 90, 22, 255, 202, 93, 21, 255, 202,
+        103, 23, 255, 21, 16, 10, 255, 0, 20, 4, 3, 3, 133, 20, 16, 9, 255,
+        151, 80, 22, 255, 75, 42, 16, 255, 10, 8, 7, 255, 32, 22, 11, 255,
+        164, 86, 23, 255, 60, 39, 17, 255, 5, 5, 4, 252, 0, 36, 12, 11, 9,
+        198, 213, 155, 80, 255, 224, 166, 83, 255, 211, 121, 34, 255, 20,
+        16, 9, 255, 3, 3, 2, 28, 0, 144, 6, 6, 5, 51, 27, 20, 10, 255, 160,
+        84, 23, 255, 198, 104, 21, 255, 67, 40, 16, 255, 8, 7, 5, 125, 0,
+        12, 12, 10, 9, 170, 195, 112, 30, 255, 215, 125, 38, 255, 217, 133,
+        50, 255, 49, 35, 22, 255, 5, 5, 4, 133, 13, 12, 10, 210, 189, 119,
+        50, 255, 211, 127, 44, 255, 212, 121, 41, 255, 218, 135, 53, 255,
+        220, 148, 63, 255, 34, 27, 17, 255, 0, 20, 4, 4, 4, 17, 13, 12, 10,
+        227, 196, 113, 31, 255, 212, 118, 35, 255, 214, 123, 43, 255, 33,
+        26, 16, 255, 0, 56, 12, 11, 9, 187, 208, 134, 55, 255, 223, 146, 70,
+        255, 221, 152, 70, 255, 34, 26, 17, 255, 0, 40, 8, 7, 5, 164, 165,
+        86, 22, 255, 202, 98, 21, 255, 198, 96, 21, 255, 22, 16, 9, 255, 0,
+        20, 8, 8, 5, 85, 32, 22, 11, 255, 167, 87, 22, 255, 160, 84, 23,
+        255, 93, 54, 20, 255, 120, 65, 21, 255, 188, 96, 21, 255, 196, 99,
+        21, 255, 200, 105, 21, 255, 24, 19, 11, 207, 0, 8, 15, 14, 10, 110,
+        208, 152, 71, 255, 227, 174, 98, 255, 228, 179, 103, 255, 225, 176,
+        98, 255, 217, 169, 94, 255, 213, 166, 92, 255, 215, 167, 92, 255,
+        213, 155, 80, 255, 204, 136, 55, 255, 138, 89, 37, 255, 25, 22, 16,
+        227, 9, 9, 8, 28, 0, 8, 11, 10, 8, 170, 203, 129, 50, 255, 223, 149,
+        70, 255, 222, 158, 75, 255, 31, 25, 16, 255, 4, 4, 4, 28, 0, 60, 8,
+        8, 7, 57, 49, 40, 26, 255, 206, 152, 83, 255, 224, 169, 91, 255,
+        194, 140, 71, 255, 31, 27, 20, 255, 9, 8, 8, 28, 0, 8, 12, 10, 9,
+        161, 196, 110, 33, 255, 218, 130, 51, 255, 222, 158, 75, 255, 31,
+        25, 16, 255, 4, 4, 4, 28, 0, 8, 11, 10, 8, 198, 213, 160, 84, 255,
+        228, 180, 105, 255, 227, 175, 100, 255, 33, 28, 18, 207, 0, 8, 12,
+        11, 9, 130, 210, 155, 77, 255, 228, 169, 99, 255, 226, 172, 95, 255,
+        30, 25, 17, 255, 4, 4, 4, 28, 0, 8, 11, 10, 8, 198, 204, 129, 49,
+        255, 214, 127, 43, 255, 213, 125, 40, 255, 23, 19, 12, 232, 0, 8,
+        14, 13, 9, 125, 208, 152, 71, 255, 223, 159, 76, 255, 218, 153, 59,
+        255, 33, 26, 16, 210, 0, 8, 13, 12, 10, 127, 198, 118, 39, 255, 215,
+        127, 42, 255, 213, 126, 42, 255, 41, 31, 18, 227, 0, 12, 6, 6, 5,
+        28, 25, 21, 16, 227, 204, 150, 79, 255, 223, 171, 98, 255, 175, 122,
+        60, 255, 18, 15, 11, 218, 5, 4, 4, 17, 0, 20, 20, 18, 13, 85, 177,
+        101, 34, 255, 204, 123, 37, 255, 199, 117, 36, 255, 199, 117, 36,
+        255, 202, 122, 37, 255, 199, 117, 36, 255, 198, 114, 31, 255, 198,
+        110, 31, 255, 202, 118, 35, 255, 46, 33, 21, 170, 0, 24, 10, 9, 7,
+        153, 110, 78, 37, 255, 213, 162, 82, 255, 218, 164, 87, 255, 67, 51,
+        30, 255, 9, 8, 8, 85, 0, 40, 6, 5, 5, 28, 21, 19, 14, 255, 217, 166,
+        92, 255, 227, 175, 100, 255, 224, 169, 91, 255, 31, 25, 16, 215, 0,
+        8, 12, 10, 7, 85, 154, 80, 21, 255, 197, 99, 20, 255, 192, 97, 21,
+        255, 28, 20, 9, 255, 4, 3, 3, 110, 11, 9, 6, 170, 117, 63, 20, 255,
+        184, 94, 21, 255, 198, 104, 21, 255, 203, 104, 24, 255, 210, 122,
+        37, 255, 21, 17, 12, 252, 0, 8, 10, 9, 7, 161, 203, 129, 50, 255,
+        224, 160, 77, 255, 225, 169, 88, 255, 30, 25, 17, 255, 4, 4, 4, 28,
+        0, 8, 8, 7, 5, 190, 165, 86, 22, 255, 198, 104, 21, 255, 196, 99,
+        21, 255, 28, 19, 9, 170, 0, 8, 13, 11, 8, 85, 176, 91, 23, 255, 208,
+        112, 27, 255, 210, 121, 35, 255, 27, 22, 14, 255, 4, 4, 4, 28, 0, 8,
+        11, 10, 8, 198, 211, 149, 76, 255, 224, 168, 87, 255, 224, 162, 81,
+        255, 32, 26, 17, 210, 0, 8, 12, 10, 7, 113, 176, 91, 23, 255, 202,
+        107, 23, 255, 202, 95, 23, 255, 20, 16, 9, 255, 0, 40, 15, 13, 10,
+        170, 213, 160, 84, 255, 228, 180, 105, 255, 227, 174, 98, 255, 33,
+        26, 18, 255, 0, 12, 15, 13, 10, 170, 213, 155, 80, 255, 226, 172,
+        95, 255, 224, 167, 85, 255, 23, 20, 14, 244, 0, 8, 11, 10, 8, 127,
+        189, 104, 28, 255, 214, 127, 43, 255, 221, 148, 70, 255, 31, 25, 16,
+        255, 4, 4, 4, 28, 0, 28, 14, 12, 9, 170, 195, 113, 32, 255, 209,
+        117, 28, 255, 202, 103, 23, 255, 20, 15, 9, 252, 3, 3, 3, 14, 0, 28,
+        15, 14, 10, 170, 213, 155, 80, 255, 226, 172, 95, 255, 221, 152, 70,
+        255, 28, 24, 15, 255, 0, 40, 14, 12, 9, 170, 208, 141, 61, 255, 225,
+        162, 88, 255, 227, 174, 98, 255, 33, 26, 18, 255, 4, 4, 4, 28, 0, 8,
+        10, 8, 7, 198, 182, 98, 23, 255, 202, 103, 23, 255, 198, 104, 21,
+        255, 28, 19, 9, 170, 0, 8, 11, 10, 6, 85, 154, 80, 21, 255, 202, 98,
+        21, 255, 202, 103, 23, 255, 25, 20, 12, 255, 0, 40, 12, 10, 7, 170,
+        186, 100, 23, 255, 202, 99, 23, 255, 200, 105, 21, 255, 30, 21, 9,
+        170, 0, 8, 12, 9, 7, 85, 154, 80, 21, 255, 198, 104, 21, 255, 196,
+        99, 21, 255, 28, 20, 9, 255, 4, 4, 3, 113, 11, 10, 6, 227, 183, 100,
+        26, 255, 212, 127, 43, 255, 167, 117, 52, 255, 17, 15, 12, 215, 5,
+        5, 5, 14, 0, 12, 15, 13, 10, 170, 211, 149, 76, 255, 224, 166, 83,
+        255, 223, 161, 80, 255, 34, 26, 17, 255, 0, 32, 10, 9, 7, 170, 167,
+        87, 22, 255, 198, 92, 21, 255, 196, 99, 21, 255, 196, 95, 21, 255,
+        198, 92, 21, 255, 195, 99, 22, 255, 192, 106, 29, 255, 206, 127, 43,
+        255, 217, 141, 60, 255, 223, 146, 70, 255, 224, 165, 81, 255, 220,
+        148, 63, 255, 212, 124, 39, 255, 25, 19, 12, 215, 0, 8, 12, 11, 9,
+        116, 196, 116, 37, 255, 218, 141, 51, 255, 218, 139, 55, 255, 218,
+        142, 61, 255, 215, 143, 58, 255, 24, 19, 13, 212, 0, 4, 10, 9, 7,
+        156, 203, 129, 50, 255, 221, 150, 66, 255, 220, 148, 63, 255, 25,
+        21, 14, 227, 0, 8, 10, 10, 7, 159, 204, 134, 59, 255, 225, 160, 84,
+        255, 225, 169, 88, 255, 36, 29, 19, 255, 0, 12, 15, 14, 10, 170,
+        204, 130, 51, 255, 220, 142, 59, 255, 218, 139, 55, 255, 21, 18, 12,
+        249, 0, 8, 11, 10, 8, 142, 206, 145, 67, 255, 226, 172, 95, 255,
+        227, 174, 98, 255, 32, 26, 17, 255, 4, 4, 4, 28, 0, 8, 11, 10, 8,
+        198, 198, 117, 37, 255, 215, 125, 38, 255, 211, 122, 36, 255, 28,
+        21, 13, 215, 0, 8, 13, 11, 8, 96, 174, 91, 23, 255, 202, 107, 23,
+        255, 202, 103, 23, 255, 22, 17, 9, 255, 0, 12, 11, 10, 6, 170, 176,
+        91, 23, 255, 202, 103, 23, 255, 203, 108, 24, 255, 21, 15, 10, 238,
+        0, 8, 11, 10, 8, 142, 206, 145, 67, 255, 226, 170, 91, 255, 224,
+        160, 85, 255, 30, 24, 17, 255, 4, 4, 4, 28, 0, 8, 11, 10, 8, 198,
+        209, 149, 70, 255, 224, 160, 77, 255, 222, 158, 75, 255, 31, 25, 16,
+        212, 0, 8, 12, 11, 9, 127, 198, 116, 35, 255, 215, 125, 38, 255,
+        211, 122, 36, 255, 28, 21, 13, 255, 4, 4, 4, 28, 0, 52, 13, 12, 8,
+        170, 195, 112, 30, 255, 209, 110, 30, 255, 207, 105, 30, 255, 25,
+        20, 12, 255, 0, 24, 15, 14, 10, 170, 213, 158, 80, 255, 226, 172,
+        95, 255, 224, 164, 85, 255, 33, 27, 18, 255, 0, 12, 15, 14, 10, 170,
+        210, 143, 65, 255, 224, 168, 87, 255, 224, 165, 81, 255, 25, 21, 14,
+        232, 0, 8, 10, 10, 9, 153, 208, 147, 67, 255, 224, 166, 83, 255,
+        222, 158, 75, 255, 34, 26, 17, 255, 0, 12, 15, 14, 10, 170, 211,
+        149, 76, 255, 223, 149, 70, 255, 219, 146, 60, 255, 25, 20, 14, 235,
+        0, 8, 10, 10, 9, 150, 204, 134, 59, 255, 224, 156, 83, 255, 224,
+        165, 81, 255, 33, 27, 18, 255, 0, 20, 15, 14, 10, 170, 211, 150, 70,
+        255, 226, 170, 91, 255, 226, 172, 95, 255, 33, 26, 18, 255, 0, 16,
+        9, 9, 8, 150, 101, 74, 38, 255, 198, 145, 77, 255, 206, 157, 87,
+        255, 202, 151, 79, 255, 197, 141, 74, 255, 200, 146, 75, 255, 180,
+        126, 57, 255, 21, 19, 14, 227, 5, 5, 4, 28, 0, 16, 8, 7, 5, 113, 43,
+        28, 14, 255, 187, 96, 22, 255, 181, 93, 22, 255, 98, 55, 21, 255,
+        68, 42, 17, 255, 77, 46, 18, 255, 129, 72, 22, 255, 174, 89, 21,
+        255, 83, 47, 18, 255, 11, 9, 6, 221, 0, 28, 6, 6, 5, 28, 16, 14, 11,
+        195, 108, 76, 35, 255, 210, 141, 59, 255, 218, 162, 81, 255, 167,
+        118, 54, 255, 16, 14, 11, 221, 5, 5, 5, 14, 0, 12, 15, 13, 10, 170,
+        211, 149, 76, 255, 224, 168, 87, 255, 223, 154, 80, 255, 31, 25, 16,
+        255, 0, 20, 6, 6, 5, 57, 34, 27, 17, 255, 203, 122, 36, 255, 208,
+        124, 41, 255, 109, 76, 34, 255, 13, 12, 10, 142, 0, 32, 13, 11, 8,
+        170, 176, 91, 23, 255, 202, 93, 21, 255, 196, 99, 21, 255, 28, 19,
+        9, 170, 0, 8, 11, 9, 6, 85, 132, 71, 21, 255, 195, 99, 22, 255, 103,
+        59, 20, 255, 11, 10, 6, 170, 3, 3, 2, 25, 6, 6, 5, 110, 55, 35, 16,
+        255, 198, 113, 29, 255, 212, 134, 51, 255, 41, 32, 20, 210, 0, 68,
+        21, 19, 14, 215, 217, 163, 86, 255, 49, 38, 24, 255, 0, 12, 11, 10,
+        8, 82, 54, 43, 27, 255, 200, 135, 59, 255, 210, 137, 59, 255, 207,
+        131, 50, 255, 205, 127, 44, 255, 199, 117, 36, 255, 195, 111, 28,
+        255, 187, 101, 24, 255, 93, 54, 22, 255, 19, 15, 10, 227, 7, 6, 6,
+        28, 0, 8, 10, 9, 7, 170, 195, 109, 32, 255, 218, 138, 53, 255, 224,
+        158, 81, 255, 223, 173, 95, 255, 219, 167, 94, 255, 217, 169, 94,
+        255, 218, 171, 97, 255, 217, 166, 92, 255, 208, 136, 59, 255, 110,
+        68, 27, 255, 19, 15, 10, 227, 6, 6, 5, 28, 0, 12, 12, 11, 7, 170,
+        61, 42, 20, 255, 188, 106, 33, 255, 208, 134, 55, 255, 215, 163, 82,
+        255, 217, 166, 92, 255, 216, 167, 88, 255, 216, 167, 89, 255, 211,
+        150, 70, 255, 146, 94, 39, 255, 26, 21, 15, 229, 9, 8, 6, 28, 0, 12,
+        12, 10, 7, 170, 51, 32, 14, 255, 151, 80, 22, 255, 169, 91, 22, 255,
+        173, 86, 22, 255, 169, 88, 22, 255, 173, 86, 22, 255, 180, 92, 21,
+        255, 194, 98, 21, 255, 196, 95, 21, 255, 192, 97, 21, 255, 31, 21,
+        10, 170, 0, 12, 12, 10, 7, 170, 57, 37, 18, 255, 189, 107, 34, 255,
+        212, 149, 67, 255, 217, 166, 92, 255, 217, 166, 92, 255, 218, 171,
+        97, 255, 215, 163, 82, 255, 205, 126, 48, 255, 116, 72, 29, 255, 20,
+        16, 11, 227, 6, 6, 5, 28, 0, 8, 11, 9, 6, 68, 126, 68, 21, 255, 191,
+        98, 22, 255, 194, 98, 21, 255, 192, 97, 21, 255, 192, 97, 21, 255,
+        191, 98, 22, 255, 177, 91, 22, 255, 26, 19, 9, 142, 0, 12, 12, 10,
+        7, 170, 58, 37, 17, 255, 185, 107, 30, 255, 208, 134, 55, 255, 216,
+        167, 88, 255, 218, 171, 97, 255, 217, 166, 92, 255, 213, 148, 72,
+        255, 204, 130, 51, 255, 209, 141, 60, 255, 211, 159, 76, 255, 30,
+        25, 17, 170, 0, 8, 10, 10, 7, 167, 210, 155, 77, 255, 228, 178, 99,
+        255, 224, 165, 81, 255, 221, 165, 86, 255, 217, 166, 92, 255, 218,
+        169, 93, 255, 217, 166, 92, 255, 214, 156, 81, 255, 206, 135, 51,
+        255, 116, 72, 29, 255, 20, 16, 11, 227, 6, 6, 5, 28, 0, 8, 13, 10,
+        6, 57, 115, 62, 20, 255, 169, 91, 22, 255, 165, 86, 22, 255, 24, 18,
+        9, 167, 0, 24, 12, 10, 7, 88, 117, 63, 20, 255, 186, 100, 23, 255,
+        191, 107, 32, 255, 35, 27, 16, 144, 0, 8, 10, 10, 7, 170, 210, 155,
+        77, 255, 228, 178, 99, 255, 221, 152, 70, 255, 24, 19, 13, 255, 0,
+        8, 12, 10, 7, 170, 58, 36, 15, 255, 157, 79, 22, 255, 151, 80, 22,
+        255, 58, 35, 15, 255, 11, 9, 6, 57, 0, 8, 12, 10, 7, 85, 157, 81,
+        20, 255, 197, 99, 20, 255, 192, 97, 21, 255, 28, 20, 9, 170, 0, 8,
+        11, 9, 6, 57, 115, 62, 20, 255, 189, 94, 24, 255, 198, 117, 37, 255,
+        213, 157, 76, 255, 218, 171, 97, 255, 217, 169, 94, 255, 214, 161,
+        85, 255, 213, 157, 76, 255, 212, 149, 67, 255, 208, 134, 55, 255,
+        205, 126, 48, 255, 143, 96, 40, 255, 28, 26, 19, 229, 8, 8, 7, 28,
+        0, 8, 13, 12, 8, 85, 141, 74, 24, 255, 190, 94, 23, 255, 183, 95,
+        24, 255, 183, 95, 24, 255, 187, 93, 24, 255, 189, 97, 22, 255, 181,
+        93, 22, 255, 177, 91, 22, 255, 169, 88, 22, 255, 89, 52, 20, 255,
+        21, 18, 12, 227, 9, 9, 8, 28, 0, 12, 18, 17, 13, 181, 103, 74, 40,
+        255, 207, 146, 74, 255, 214, 156, 81, 255, 210, 144, 67, 255, 208,
+        138, 55, 255, 207, 129, 52, 255, 205, 133, 48, 255, 205, 126, 48,
+        255, 151, 101, 42, 255, 28, 26, 19, 232, 9, 8, 8, 28, 0, 8, 13, 12,
+        10, 110, 186, 127, 63, 255, 214, 156, 81, 255, 213, 158, 80, 255,
+        213, 155, 80, 255, 214, 156, 81, 255, 214, 153, 75, 255, 213, 148,
+        72, 255, 213, 148, 72, 255, 211, 150, 70, 255, 159, 111, 54, 255,
+        28, 25, 19, 241, 9, 8, 8, 31, 0, 12, 18, 17, 13, 181, 103, 74, 40,
+        255, 208, 156, 81, 255, 214, 156, 81, 255, 208, 138, 55, 255, 209,
+        137, 60, 255, 213, 158, 80, 255, 213, 155, 80, 255, 213, 160, 84,
+        255, 215, 160, 88, 255, 213, 163, 84, 255, 30, 24, 17, 178, 0, 8,
+        12, 11, 9, 93, 178, 121, 53, 255, 213, 158, 80, 255, 210, 143, 65,
+        255, 211, 146, 62, 255, 213, 148, 72, 255, 215, 163, 82, 255, 213,
+        158, 80, 255, 212, 149, 67, 255, 209, 141, 60, 255, 153, 106, 49,
+        255, 28, 25, 19, 235, 9, 9, 8, 31, 0, 12, 18, 15, 11, 173, 66, 43,
+        21, 255, 187, 101, 32, 255, 207, 132, 52, 255, 210, 144, 67, 255,
+        213, 148, 72, 255, 214, 156, 81, 255, 216, 167, 88, 255, 214, 156,
+        81, 255, 176, 128, 65, 255, 46, 39, 27, 255, 0, 12, 15, 14, 10, 85,
+        181, 111, 42, 255, 215, 136, 52, 255, 213, 125, 40, 255, 211, 122,
+        36, 255, 212, 123, 37, 255, 210, 123, 39, 255, 202, 122, 37, 255,
+        31, 24, 14, 170, 0, 8, 12, 11, 9, 88, 164, 89, 29, 255, 203, 122,
+        36, 255, 199, 117, 36, 255, 30, 23, 15, 212, 0, 12, 15, 13, 10, 127,
+        187, 133, 62, 255, 213, 148, 72, 255, 208, 138, 55, 255, 31, 24, 16,
+        170, 0, 8, 13, 12, 10, 85, 172, 104, 37, 255, 209, 134, 54, 255,
+        206, 135, 51, 255, 32, 25, 17, 212, 0, 12, 15, 13, 10, 127, 181,
+        116, 46, 255, 211, 143, 62, 255, 210, 153, 71, 255, 29, 24, 16, 178,
+        0, 8, 13, 12, 10, 91, 178, 121, 53, 255, 213, 154, 70, 255, 208,
+        134, 55, 255, 31, 25, 16, 210, 0, 20, 15, 14, 10, 125, 179, 110, 42,
+        255, 210, 135, 55, 255, 208, 139, 65, 255, 26, 21, 15, 184, 0, 8,
+        14, 13, 9, 85, 179, 117, 44, 255, 217, 165, 82, 255, 213, 163, 84,
+        255, 27, 23, 16, 221, 0, 12, 14, 12, 9, 136, 174, 103, 39, 255, 206,
+        127, 43, 255, 199, 117, 36, 255, 31, 24, 14, 170, 0, 8, 12, 11, 9,
+        88, 164, 89, 29, 255, 202, 118, 35, 255, 196, 114, 33, 255, 29, 22,
+        14, 210, 0, 12, 14, 12, 9, 125, 169, 95, 30, 255, 202, 119, 37, 255,
+        199, 119, 39, 255, 24, 19, 13, 190, 0, 8, 14, 12, 9, 85, 170, 95,
+        29, 255, 198, 113, 29, 255, 199, 116, 34, 255, 204, 128, 47, 255,
+        206, 135, 51, 255, 204, 129, 49, 255, 204, 129, 49, 255, 208, 134,
+        55, 255, 211, 149, 76, 255, 192, 140, 73, 255, 95, 74, 39, 255, 17,
+        15, 12, 85, 0, 16, 14, 12, 9, 198, 211, 150, 70, 255, 206, 152, 81,
+        255, 31, 26, 20, 255, 7, 7, 6, 48, 0, 16, 15, 13, 10, 170, 211, 149,
+        76, 255, 226, 170, 91, 255, 226, 172, 95, 255, 35, 28, 18, 255, 0,
+        20, 15, 14, 12, 218, 171, 120, 60, 255, 219, 154, 70, 255, 41, 31,
+        20, 255, 4, 4, 3, 28, 0, 104, 17, 16, 12, 170, 219, 179, 116, 255,
+        232, 193, 137, 255, 232, 199, 135, 255, 40, 33, 23, 255, 0, 12, 10,
+        10, 9, 76, 62, 50, 31, 255, 20, 18, 13, 167, 0, 12, 11, 10, 8, 76,
+        58, 46, 29, 255, 20, 18, 13, 167, 0, 16, 13, 12, 10, 170, 210, 150,
+        71, 255, 223, 147, 72, 255, 221, 150, 66, 255, 26, 21, 15, 210, 0,
+        4, 11, 10, 8, 119, 211, 159, 84, 255, 229, 184, 114, 255, 230, 186,
+        123, 255, 30, 26, 19, 255, 0, 16, 12, 11, 9, 93, 137, 90, 40, 255,
+        223, 167, 94, 255, 228, 180, 111, 255, 167, 133, 80, 255, 17, 16,
+        14, 227, 11, 11, 10, 170, 12, 11, 9, 170, 12, 11, 9, 170, 12, 11, 9,
+        119, 7, 7, 6, 57, 0, 36, 7, 7, 6, 62, 21, 18, 12, 227, 157, 92, 28,
+        255, 203, 105, 26, 255, 197, 106, 26, 255, 82, 48, 21, 255, 14, 12,
+        7, 173, 5, 5, 4, 8, 0, 16, 8, 7, 5, 28, 26, 19, 11, 227, 103, 68,
+        25, 255, 158, 96, 29, 255, 57, 41, 22, 255, 13, 12, 10, 241, 33, 26,
+        16, 255, 146, 88, 31, 255, 66, 47, 23, 255, 12, 10, 9, 201, 6, 5, 5,
+        14, 0, 32, 8, 7, 5, 57, 30, 22, 11, 255, 15, 12, 8, 96, 0, 8, 10,
+        10, 7, 130, 190, 104, 27, 255, 209, 118, 30, 255, 211, 117, 34, 255,
+        27, 21, 14, 255, 0, 24, 13, 12, 10, 170, 199, 122, 39, 255, 218,
+        130, 51, 255, 223, 146, 70, 255, 30, 24, 17, 255, 0, 12, 23, 22, 18,
+        139, 30, 27, 21, 170, 16, 15, 11, 255, 89, 59, 26, 255, 203, 110,
+        28, 255, 196, 113, 31, 255, 122, 81, 33, 255, 186, 117, 43, 255,
+        216, 129, 51, 255, 184, 126, 57, 255, 38, 34, 25, 255, 24, 22, 19,
+        221, 33, 30, 24, 170, 15, 15, 12, 28, 0, 12, 24, 22, 19, 142, 32,
+        31, 25, 170, 21, 20, 16, 198, 90, 71, 45, 255, 223, 179, 110, 255,
+        226, 172, 95, 255, 221, 150, 66, 255, 143, 100, 44, 255, 22, 21, 17,
+        227, 28, 27, 21, 170, 29, 28, 22, 170, 13, 13, 12, 42, 0, 36, 8, 8,
+        8, 11, 25, 24, 20, 142, 39, 35, 28, 170, 30, 28, 23, 170, 29, 27,
+        22, 170, 29, 27, 22, 170, 29, 27, 22, 170, 29, 27, 22, 170, 29, 27,
+        20, 170, 23, 21, 16, 170, 14, 13, 11, 34, 0, 52, 13, 12, 10, 159,
+        142, 86, 31, 255, 208, 116, 35, 255, 201, 119, 38, 255, 32, 26, 17,
+        255, 5, 5, 4, 28, 0, 12, 14, 13, 11, 170, 216, 167, 97, 255, 231,
+        184, 124, 255, 231, 193, 128, 255, 181, 146, 92, 255, 52, 44, 33,
+        255, 90, 71, 45, 255, 201, 155, 88, 255, 223, 173, 102, 255, 228,
+        179, 115, 255, 230, 183, 123, 255, 230, 184, 119, 255, 39, 32, 22,
+        255, 0, 24, 12, 12, 11, 170, 206, 139, 61, 255, 226, 164, 91, 255,
+        228, 174, 103, 255, 39, 32, 22, 255, 0, 48, 6, 6, 5, 28, 9, 9, 8,
+        142, 56, 46, 31, 255, 222, 180, 113, 255, 230, 187, 119, 255, 222,
+        180, 113, 255, 23, 21, 16, 255, 0, 36, 15, 14, 12, 164, 79, 59, 30,
+        255, 209, 128, 42, 255, 211, 127, 44, 255, 171, 117, 46, 255, 18,
+        15, 11, 170, 0, 16, 9, 9, 8, 116, 33, 28, 16, 255, 161, 94, 28, 255,
+        199, 107, 26, 255, 65, 40, 18, 255, 8, 7, 5, 255, 25, 20, 12, 255,
+        198, 113, 29, 255, 210, 120, 33, 255, 217, 133, 50, 255, 27, 23, 16,
+        255, 0, 8, 7, 7, 6, 23, 34, 28, 19, 198, 46, 36, 25, 255, 39, 31,
+        22, 255, 41, 33, 22, 255, 59, 46, 28, 255, 51, 40, 26, 255, 61, 47,
+        28, 255, 180, 133, 71, 255, 227, 175, 100, 255, 226, 175, 103, 255,
+        181, 143, 88, 255, 17, 16, 12, 142, 0, 8, 11, 11, 10, 170, 214, 166,
+        97, 255, 229, 179, 114, 255, 228, 185, 111, 255, 161, 121, 68, 255,
+        23, 21, 16, 227, 23, 22, 18, 170, 22, 21, 17, 170, 16, 15, 13, 170,
+        11, 11, 8, 147, 8, 8, 7, 85, 0, 40, 14, 13, 11, 170, 181, 143, 88,
+        255, 228, 185, 123, 255, 218, 168, 97, 255, 70, 54, 35, 255, 9, 9,
+        8, 113, 0, 12, 11, 10, 8, 85, 120, 87, 45, 255, 223, 183, 120, 255,
+        231, 190, 132, 255, 167, 135, 80, 255, 24, 22, 19, 227, 19, 18, 16,
+        170, 19, 18, 16, 198, 95, 80, 46, 255, 226, 193, 129, 255, 228, 187,
+        129, 255, 186, 148, 87, 255, 15, 14, 12, 170, 0, 8, 10, 10, 9, 85,
+        155, 113, 64, 255, 229, 196, 132, 255, 232, 191, 133, 255, 179, 142,
+        90, 255, 27, 25, 20, 227, 18, 18, 15, 170, 19, 18, 16, 198, 90, 71,
+        45, 255, 222, 175, 101, 255, 227, 174, 98, 255, 228, 185, 111, 255,
+        28, 25, 19, 255, 0, 8, 7, 7, 6, 23, 34, 28, 19, 198, 49, 35, 22,
+        255, 39, 29, 18, 227, 12, 11, 9, 85, 0, 8, 8, 7, 7, 28, 33, 26, 16,
+        198, 52, 39, 23, 255, 47, 35, 22, 227, 13, 12, 8, 85, 0, 8, 8, 8, 7,
+        28, 33, 30, 24, 227, 201, 157, 100, 255, 230, 186, 123, 255, 181,
+        137, 74, 255, 16, 15, 11, 207, 6, 6, 5, 23, 0, 24, 11, 10, 8, 28,
+        27, 21, 12, 193, 26, 19, 11, 255, 23, 18, 10, 255, 23, 18, 10, 255,
+        24, 18, 11, 255, 24, 18, 11, 255, 26, 20, 11, 255, 35, 27, 16, 255,
+        42, 31, 19, 241, 17, 14, 10, 85, 0, 28, 9, 9, 8, 144, 91, 67, 36,
+        255, 217, 154, 72, 255, 211, 150, 70, 255, 69, 55, 34, 255, 15, 14,
+        12, 85, 0, 28, 6, 6, 5, 11, 11, 11, 10, 142, 24, 22, 19, 255, 167,
+        135, 80, 255, 225, 172, 104, 255, 224, 166, 83, 255, 193, 126, 54,
+        255, 16, 14, 11, 170, 0, 8, 13, 12, 8, 85, 185, 97, 26, 255, 207,
+        112, 28, 255, 204, 110, 27, 255, 71, 46, 22, 255, 8, 8, 7, 255, 28,
+        22, 13, 255, 198, 107, 27, 255, 193, 111, 30, 255, 126, 78, 31, 255,
+        199, 139, 62, 255, 226, 184, 111, 255, 27, 24, 18, 255, 0, 8, 11,
+        10, 8, 170, 214, 166, 97, 255, 230, 187, 119, 255, 228, 179, 103,
+        255, 143, 102, 48, 255, 17, 16, 12, 227, 12, 12, 9, 170, 13, 12, 10,
+        198, 46, 33, 17, 255, 199, 112, 28, 255, 206, 111, 27, 255, 204,
+        110, 27, 255, 32, 23, 13, 176, 0, 8, 12, 11, 9, 136, 204, 134, 59,
+        255, 226, 172, 95, 255, 228, 181, 107, 255, 162, 125, 73, 255, 24,
+        22, 19, 227, 19, 18, 16, 170, 19, 18, 16, 198, 95, 80, 46, 255, 224,
+        179, 109, 255, 223, 173, 95, 255, 173, 117, 50, 255, 15, 13, 10,
+        156, 0, 8, 12, 11, 7, 99, 185, 97, 26, 255, 208, 112, 27, 255, 204,
+        110, 27, 255, 22, 18, 11, 255, 0, 40, 16, 15, 13, 170, 219, 179,
+        116, 255, 232, 194, 133, 255, 231, 193, 128, 255, 40, 33, 23, 255,
+        0, 12, 16, 15, 13, 170, 219, 177, 112, 255, 230, 187, 119, 255, 224,
+        159, 83, 255, 24, 21, 15, 255, 0, 8, 11, 10, 8, 164, 211, 158, 82,
+        255, 229, 184, 114, 255, 230, 191, 123, 255, 166, 127, 77, 255, 22,
+        21, 17, 227, 22, 21, 17, 170, 20, 19, 13, 170, 14, 13, 11, 28, 0,
+        16, 12, 11, 9, 170, 195, 112, 30, 255, 209, 106, 30, 255, 206, 111,
+        27, 255, 101, 63, 26, 255, 16, 14, 11, 227, 23, 21, 16, 170, 29, 27,
+        22, 170, 13, 13, 12, 42, 0, 16, 16, 15, 13, 170, 216, 167, 97, 255,
+        224, 158, 87, 255, 216, 125, 45, 255, 24, 20, 13, 255, 0, 40, 17,
+        16, 12, 170, 219, 177, 112, 255, 232, 195, 137, 255, 231, 189, 128,
+        255, 162, 125, 73, 255, 22, 21, 17, 227, 14, 14, 11, 170, 13, 12,
+        10, 198, 50, 35, 19, 255, 199, 112, 28, 255, 206, 111, 27, 255, 204,
+        110, 27, 255, 32, 24, 13, 170, 0, 8, 13, 12, 8, 93, 194, 109, 33,
+        255, 219, 139, 54, 255, 224, 158, 81, 255, 39, 32, 22, 255, 0, 40,
+        11, 10, 8, 170, 190, 104, 27, 255, 208, 112, 27, 255, 204, 110, 27,
+        255, 32, 24, 13, 170, 0, 8, 13, 12, 8, 85, 184, 96, 25, 255, 207,
+        112, 28, 255, 204, 102, 27, 255, 129, 78, 28, 255, 31, 26, 16, 255,
+        127, 84, 34, 255, 219, 147, 70, 255, 173, 122, 62, 255, 15, 14, 12,
+        212, 6, 6, 5, 25, 0, 16, 16, 15, 13, 170, 213, 155, 80, 255, 221,
+        144, 68, 255, 217, 130, 52, 255, 31, 25, 16, 255, 0, 32, 10, 9, 7,
+        170, 189, 99, 26, 255, 208, 112, 27, 255, 204, 110, 27, 255, 155,
+        87, 26, 255, 72, 46, 21, 255, 179, 103, 36, 255, 223, 156, 76, 255,
+        216, 170, 97, 255, 134, 96, 47, 255, 174, 127, 71, 255, 221, 167,
+        90, 255, 223, 147, 72, 255, 222, 158, 75, 255, 23, 19, 14, 252, 0,
+        8, 11, 10, 8, 170, 214, 166, 97, 255, 231, 187, 124, 255, 230, 191,
+        123, 255, 228, 182, 117, 255, 222, 175, 101, 255, 64, 50, 33, 255,
+        7, 7, 6, 229, 26, 23, 19, 255, 220, 175, 105, 255, 228, 183, 113,
+        255, 228, 188, 117, 255, 25, 21, 16, 255, 0, 8, 11, 10, 8, 170, 217,
+        176, 112, 255, 232, 197, 137, 255, 232, 199, 135, 255, 37, 31, 22,
+        255, 0, 12, 13, 12, 10, 170, 198, 117, 37, 255, 215, 127, 42, 255,
+        217, 130, 52, 255, 21, 19, 14, 255, 0, 8, 11, 10, 8, 167, 215, 172,
+        104, 255, 232, 191, 133, 255, 231, 190, 132, 255, 166, 127, 77, 255,
+        23, 21, 16, 227, 18, 17, 15, 170, 17, 16, 12, 198, 74, 52, 27, 255,
+        204, 117, 33, 255, 211, 111, 30, 255, 173, 93, 28, 255, 15, 12, 8,
+        164, 0, 8, 13, 12, 8, 88, 185, 97, 26, 255, 208, 112, 27, 255, 204,
+        110, 27, 255, 19, 16, 10, 255, 0, 12, 10, 9, 7, 170, 190, 104, 27,
+        255, 212, 118, 35, 255, 216, 136, 51, 255, 21, 19, 14, 252, 0, 8,
+        11, 10, 8, 167, 215, 172, 104, 255, 232, 194, 127, 255, 231, 193,
+        128, 255, 166, 129, 77, 255, 23, 21, 16, 227, 19, 18, 16, 170, 19,
+        18, 14, 198, 81, 59, 34, 255, 213, 144, 62, 255, 215, 140, 60, 255,
+        165, 108, 40, 255, 13, 12, 10, 167, 0, 8, 8, 8, 7, 85, 101, 63, 26,
+        255, 206, 114, 33, 255, 212, 121, 33, 255, 155, 92, 36, 255, 23, 21,
+        16, 227, 22, 21, 17, 170, 28, 26, 21, 170, 21, 20, 18, 170, 13, 13,
+        12, 164, 10, 10, 9, 85, 6, 6, 6, 6, 0, 28, 12, 11, 9, 170, 194, 112,
+        31, 255, 212, 119, 37, 255, 216, 134, 45, 255, 35, 28, 18, 255, 0,
+        24, 16, 15, 13, 170, 217, 171, 106, 255, 231, 187, 124, 255, 228,
+        181, 107, 255, 39, 32, 22, 255, 0, 12, 16, 15, 11, 170, 208, 134,
+        55, 255, 223, 156, 70, 255, 221, 148, 70, 255, 23, 20, 14, 238, 0,
+        8, 11, 10, 8, 170, 204, 136, 55, 255, 223, 156, 70, 255, 222, 158,
+        75, 255, 34, 28, 19, 255, 0, 12, 14, 13, 11, 170, 217, 171, 106,
+        255, 232, 189, 127, 255, 230, 186, 123, 255, 25, 22, 16, 255, 0, 8,
+        10, 10, 9, 167, 210, 155, 77, 255, 226, 172, 95, 255, 224, 165, 81,
+        255, 31, 26, 18, 255, 0, 20, 15, 13, 12, 170, 217, 173, 104, 255,
+        232, 191, 133, 255, 231, 195, 132, 255, 40, 33, 23, 255, 0, 20, 10,
+        9, 9, 133, 73, 58, 36, 255, 225, 184, 120, 255, 231, 193, 128, 255,
+        228, 180, 111, 255, 147, 102, 48, 255, 15, 13, 10, 227, 8, 7, 7, 28,
+        0, 24, 12, 11, 7, 198, 100, 59, 23, 255, 169, 93, 26, 255, 156, 91,
+        27, 255, 174, 96, 27, 255, 180, 99, 27, 255, 168, 97, 27, 255, 105,
+        62, 24, 255, 18, 15, 9, 255, 7, 6, 6, 48, 0, 24, 7, 7, 7, 28, 15,
+        15, 12, 227, 144, 114, 67, 255, 219, 177, 112, 255, 223, 176, 102,
+        255, 153, 113, 62, 255, 17, 16, 12, 227, 7, 7, 6, 28, 0, 16, 16, 15,
+        13, 170, 213, 155, 80, 255, 223, 146, 70, 255, 217, 129, 50, 255,
+        27, 22, 14, 255, 0, 24, 12, 10, 9, 195, 161, 94, 28, 255, 207, 114,
+        32, 255, 193, 114, 36, 255, 23, 20, 16, 255, 0, 32, 12, 11, 9, 170,
+        191, 105, 28, 255, 207, 100, 28, 255, 204, 110, 27, 255, 26, 20, 11,
+        204, 0, 8, 6, 5, 5, 3, 26, 19, 9, 198, 24, 18, 9, 246, 15, 12, 8,
+        142, 0, 12, 15, 13, 10, 91, 31, 24, 16, 244, 51, 39, 24, 255, 21,
+        19, 14, 91, 0, 68, 10, 10, 9, 76, 61, 49, 30, 255, 20, 18, 13, 156,
+        0, 16, 17, 15, 12, 142, 27, 22, 14, 232, 30, 22, 13, 255, 25, 20,
+        12, 255, 22, 18, 11, 238, 21, 16, 10, 255, 99, 58, 22, 255, 203,
+        113, 26, 255, 205, 111, 28, 255, 131, 80, 30, 255, 12, 11, 9, 142,
+        0, 8, 11, 10, 8, 170, 212, 160, 85, 255, 232, 191, 127, 255, 231,
+        195, 132, 255, 196, 155, 91, 255, 81, 59, 34, 255, 41, 32, 20, 255,
+        54, 43, 27, 255, 180, 133, 71, 255, 216, 144, 59, 255, 208, 115, 33,
+        255, 129, 78, 28, 255, 12, 11, 7, 142, 0, 8, 8, 7, 7, 57, 72, 52,
+        29, 255, 215, 155, 78, 255, 227, 174, 98, 255, 207, 158, 94, 255,
+        85, 63, 34, 255, 36, 29, 19, 255, 57, 43, 26, 255, 189, 130, 66,
+        255, 219, 149, 66, 255, 212, 121, 41, 255, 172, 105, 33, 255, 17,
+        15, 10, 147, 0, 8, 7, 6, 6, 54, 58, 40, 21, 255, 198, 113, 29, 255,
+        206, 103, 27, 255, 165, 87, 24, 255, 42, 28, 13, 255, 21, 16, 8,
+        255, 27, 20, 10, 255, 95, 60, 22, 255, 202, 105, 27, 255, 206, 100,
+        29, 255, 204, 110, 27, 255, 35, 24, 12, 170, 0, 8, 7, 7, 6, 54, 70,
+        50, 27, 255, 212, 145, 65, 255, 227, 174, 98, 255, 201, 155, 88,
+        255, 59, 44, 28, 255, 23, 20, 14, 255, 34, 28, 19, 255, 157, 104,
+        48, 255, 211, 126, 42, 255, 208, 115, 33, 255, 132, 82, 29, 255, 13,
+        11, 8, 142, 0, 12, 24, 18, 9, 221, 108, 61, 23, 255, 201, 112, 26,
+        255, 207, 112, 28, 255, 204, 110, 27, 255, 158, 91, 25, 255, 46, 29,
+        13, 249, 11, 10, 6, 57, 0, 8, 8, 8, 7, 57, 70, 50, 27, 255, 212,
+        142, 59, 255, 226, 172, 95, 255, 207, 158, 94, 255, 85, 63, 34, 255,
+        41, 32, 20, 255, 57, 43, 26, 255, 174, 124, 59, 255, 224, 170, 93,
+        255, 229, 184, 114, 255, 231, 196, 128, 255, 28, 25, 19, 255, 0, 8,
+        10, 10, 9, 167, 215, 169, 102, 255, 232, 191, 127, 255, 231, 193,
+        128, 255, 196, 154, 87, 255, 77, 59, 34, 255, 41, 31, 20, 255, 54,
+        43, 27, 255, 168, 113, 49, 255, 212, 121, 41, 255, 206, 114, 33,
+        255, 132, 82, 29, 255, 12, 11, 9, 130, 0, 8, 12, 11, 7, 110, 188,
+        98, 25, 255, 206, 111, 27, 255, 206, 106, 25, 255, 26, 19, 11, 255,
+        0, 24, 14, 12, 9, 170, 199, 117, 36, 255, 221, 148, 62, 255, 227,
+        174, 98, 255, 28, 26, 19, 255, 0, 8, 10, 10, 9, 167, 212, 161, 89,
+        255, 224, 166, 83, 255, 217, 129, 50, 255, 32, 24, 15, 255, 5, 5, 4,
+        31, 7, 7, 6, 136, 65, 44, 22, 255, 192, 106, 29, 255, 203, 108, 24,
+        255, 114, 66, 23, 255, 17, 13, 8, 221, 0, 12, 10, 9, 7, 139, 185,
+        97, 26, 255, 208, 112, 27, 255, 208, 117, 29, 255, 32, 24, 13, 170,
+        0, 8, 15, 13, 8, 91, 189, 99, 26, 255, 215, 123, 42, 255, 226, 172,
+        95, 255, 198, 152, 87, 255, 81, 58, 34, 255, 176, 133, 71, 255, 224,
+        168, 95, 255, 197, 138, 62, 255, 65, 47, 26, 255, 133, 81, 30, 255,
+        208, 121, 37, 255, 212, 115, 37, 255, 152, 98, 35, 255, 12, 11, 9,
+        142, 0, 8, 10, 9, 7, 147, 190, 107, 25, 255, 206, 111, 27, 255, 206,
+        106, 25, 255, 158, 91, 25, 255, 42, 28, 13, 255, 21, 15, 8, 255, 26,
+        19, 9, 255, 114, 66, 23, 255, 204, 113, 25, 255, 208, 115, 33, 255,
+        173, 122, 62, 255, 16, 15, 13, 150, 0, 8, 8, 8, 7, 71, 110, 87, 51,
+        255, 222, 180, 113, 255, 224, 166, 83, 255, 209, 137, 60, 255, 133,
+        84, 32, 255, 77, 50, 24, 255, 89, 59, 26, 255, 181, 109, 32, 255,
+        210, 121, 35, 255, 212, 121, 41, 255, 171, 116, 52, 255, 15, 14, 12,
+        142, 0, 8, 14, 13, 11, 170, 219, 177, 112, 255, 231, 187, 124, 255,
+        228, 180, 111, 255, 205, 158, 90, 255, 79, 58, 32, 255, 38, 29, 19,
+        255, 49, 35, 22, 255, 167, 114, 46, 255, 217, 146, 62, 255, 219,
+        154, 70, 255, 169, 117, 56, 255, 15, 13, 12, 156, 0, 8, 8, 8, 7, 71,
+        104, 80, 45, 255, 224, 183, 119, 255, 232, 191, 127, 255, 210, 166,
+        97, 255, 81, 60, 32, 255, 39, 30, 18, 255, 52, 40, 25, 255, 175,
+        128, 66, 255, 225, 173, 98, 255, 228, 180, 105, 255, 226, 175, 95,
+        255, 29, 25, 18, 255, 0, 8, 12, 12, 11, 170, 208, 138, 55, 255, 222,
+        145, 63, 255, 220, 139, 59, 255, 193, 121, 50, 255, 68, 50, 29, 255,
+        38, 28, 19, 255, 48, 35, 23, 255, 175, 112, 44, 255, 217, 142, 54,
+        255, 217, 144, 66, 255, 191, 137, 66, 255, 19, 16, 12, 170, 0, 8, 9,
+        8, 8, 74, 111, 82, 40, 255, 216, 155, 75, 255, 226, 172, 95, 255,
+        200, 151, 81, 255, 57, 41, 26, 255, 27, 23, 16, 255, 35, 28, 18,
+        255, 41, 32, 20, 255, 39, 30, 20, 255, 25, 22, 16, 227, 15, 14, 10,
+        142, 0, 12, 10, 9, 7, 28, 33, 24, 14, 227, 135, 81, 28, 255, 206,
+        117, 31, 255, 210, 108, 33, 255, 208, 110, 31, 255, 171, 92, 28,
+        255, 49, 33, 16, 252, 13, 11, 8, 68, 0, 8, 11, 10, 8, 170, 195, 108,
+        30, 255, 212, 118, 35, 255, 217, 137, 52, 255, 42, 33, 23, 255, 0,
+        12, 20, 18, 15, 170, 214, 156, 81, 255, 221, 148, 62, 255, 214, 127,
+        43, 255, 23, 19, 12, 238, 0, 8, 10, 10, 7, 159, 196, 109, 31, 255,
+        213, 119, 36, 255, 212, 123, 37, 255, 31, 24, 14, 255, 0, 12, 15,
+        14, 10, 170, 209, 137, 60, 255, 228, 172, 99, 255, 230, 189, 119,
+        255, 28, 26, 19, 255, 0, 8, 12, 12, 11, 170, 208, 134, 55, 255, 218,
+        137, 51, 255, 214, 127, 43, 255, 35, 27, 16, 255, 0, 20, 16, 14, 11,
+        170, 199, 116, 34, 255, 217, 132, 48, 255, 224, 166, 83, 255, 32,
+        26, 19, 255, 0, 8, 10, 10, 7, 34, 81, 58, 34, 255, 224, 178, 105,
+        255, 226, 172, 95, 255, 129, 92, 40, 255, 9, 9, 8, 170, 6, 6, 6, 85,
+        6, 6, 5, 113, 35, 27, 16, 255, 204, 117, 33, 255, 208, 117, 29, 255,
+        110, 69, 25, 255, 14, 12, 7, 108, 0, 8, 10, 10, 7, 170, 195, 112,
+        30, 255, 211, 115, 30, 255, 211, 115, 30, 255, 30, 23, 13, 255, 0,
+        12, 14, 12, 9, 170, 196, 113, 31, 255, 211, 120, 32, 255, 214, 126,
+        41, 255, 33, 26, 18, 255, 0, 8, 9, 8, 6, 28, 44, 33, 19, 212, 60,
+        42, 23, 255, 46, 35, 21, 255, 74, 53, 31, 255, 156, 109, 53, 255,
+        216, 167, 97, 255, 228, 179, 109, 255, 229, 177, 110, 255, 227, 184,
+        108, 255, 168, 123, 69, 255, 23, 21, 16, 227, 9, 8, 8, 28, 0, 12,
+        17, 16, 14, 170, 134, 98, 51, 255, 223, 166, 92, 255, 132, 100, 53,
+        255, 9, 9, 8, 133, 0, 20, 16, 15, 13, 170, 219, 177, 112, 255, 232,
+        191, 133, 255, 231, 195, 132, 255, 40, 33, 23, 255, 0, 20, 6, 6, 5,
+        45, 39, 32, 22, 255, 210, 129, 49, 255, 172, 106, 35, 255, 20, 17,
+        13, 227, 11, 11, 8, 28, 0, 100, 17, 17, 14, 170, 221, 189, 132, 255,
+        235, 205, 154, 255, 234, 205, 155, 255, 42, 39, 29, 255, 0, 16, 9,
+        9, 8, 25, 0, 20, 9, 8, 8, 25, 0, 20, 14, 14, 11, 170, 208, 141, 61,
+        255, 224, 168, 87, 255, 228, 174, 103, 255, 31, 26, 20, 221, 0, 4,
+        13, 12, 12, 130, 218, 185, 127, 255, 234, 202, 147, 255, 232, 198,
+        139, 255, 40, 33, 25, 255, 0, 20, 17, 17, 14, 176, 140, 115, 71,
+        255, 230, 202, 147, 255, 232, 202, 149, 255, 218, 170, 101, 255,
+        200, 124, 43, 255, 198, 117, 37, 255, 198, 117, 37, 255, 196, 116,
+        37, 255, 72, 52, 27, 255, 12, 11, 9, 170, 0, 28, 8, 8, 7, 85, 37,
+        31, 20, 255, 174, 110, 41, 255, 210, 123, 39, 255, 204, 120, 37,
+        255, 130, 87, 31, 255, 15, 13, 10, 190, 0, 28, 5, 5, 4, 113, 28, 26,
+        19, 255, 210, 143, 65, 255, 220, 163, 81, 255, 217, 166, 92, 255,
+        222, 173, 97, 255, 225, 176, 98, 255, 42, 37, 25, 255, 4, 4, 4, 74,
+        0, 56, 13, 12, 10, 170, 208, 141, 61, 255, 226, 172, 95, 255, 228,
+        183, 111, 255, 40, 34, 25, 255, 0, 24, 17, 16, 14, 170, 219, 177,
+        112, 255, 232, 194, 133, 255, 233, 202, 148, 255, 27, 24, 20, 255,
+        0, 8, 16, 15, 13, 85, 199, 161, 102, 255, 220, 166, 89, 255, 211,
+        143, 62, 255, 217, 154, 72, 255, 223, 161, 80, 255, 224, 169, 91,
+        255, 225, 185, 114, 255, 229, 188, 124, 255, 231, 190, 132, 255,
+        231, 200, 143, 255, 227, 195, 140, 255, 227, 196, 138, 255, 225,
+        195, 136, 255, 44, 37, 27, 170, 0, 8, 17, 16, 14, 85, 200, 165, 109,
+        255, 227, 198, 142, 255, 225, 191, 132, 255, 227, 195, 134, 255,
+        231, 199, 136, 255, 231, 197, 132, 255, 231, 194, 124, 255, 229,
+        191, 130, 255, 225, 195, 136, 255, 225, 195, 136, 255, 225, 191,
+        132, 255, 49, 42, 30, 198, 0, 36, 18, 17, 13, 105, 193, 135, 66,
+        255, 221, 175, 102, 255, 222, 186, 123, 255, 223, 190, 132, 255,
+        224, 192, 135, 255, 223, 190, 132, 255, 222, 186, 123, 255, 221,
+        178, 110, 255, 218, 172, 105, 255, 46, 39, 27, 195, 0, 48, 6, 6, 6,
+        28, 27, 26, 20, 255, 216, 170, 97, 255, 225, 178, 104, 255, 176,
+        136, 83, 255, 16, 15, 13, 198, 0, 16, 17, 17, 14, 170, 221, 188,
+        130, 255, 235, 205, 154, 255, 234, 205, 155, 255, 232, 204, 149,
+        255, 228, 199, 143, 255, 171, 144, 96, 255, 64, 57, 41, 255, 154,
+        126, 81, 255, 227, 189, 122, 255, 230, 184, 119, 255, 227, 171, 98,
+        255, 34, 30, 21, 255, 0, 24, 17, 16, 14, 170, 221, 186, 126, 255,
+        234, 202, 147, 255, 232, 192, 135, 255, 44, 39, 27, 255, 0, 44, 9,
+        9, 8, 142, 25, 24, 20, 255, 114, 95, 53, 255, 207, 169, 102, 255,
+        227, 187, 118, 255, 226, 188, 123, 255, 178, 148, 95, 255, 19, 18,
+        16, 170, 0, 32, 24, 22, 19, 85, 197, 145, 84, 255, 227, 187, 118,
+        255, 231, 194, 124, 255, 207, 173, 114, 255, 61, 55, 38, 255, 8, 8,
+        8, 136, 0, 12, 10, 10, 9, 108, 45, 36, 21, 255, 195, 116, 38, 255,
+        207, 122, 38, 255, 139, 90, 32, 255, 13, 12, 8, 170, 0, 4, 10, 10,
+        9, 198, 208, 140, 59, 255, 226, 170, 91, 255, 231, 193, 128, 255,
+        40, 35, 27, 255, 0, 36, 4, 4, 3, 28, 18, 17, 13, 227, 222, 189, 131,
+        255, 234, 201, 143, 255, 229, 191, 130, 255, 34, 30, 23, 204, 0, 8,
+        11, 11, 10, 170, 211, 158, 82, 255, 226, 170, 91, 255, 224, 165, 81,
+        255, 219, 154, 70, 255, 208, 132, 51, 255, 206, 128, 45, 255, 204,
+        122, 41, 255, 201, 120, 40, 255, 196, 116, 37, 255, 111, 74, 30,
+        255, 20, 18, 13, 227, 8, 8, 7, 28, 0, 28, 6, 6, 6, 28, 28, 26, 21,
+        255, 222, 186, 123, 255, 229, 196, 132, 255, 181, 144, 92, 255, 16,
+        15, 13, 212, 0, 16, 6, 6, 6, 85, 25, 24, 20, 255, 180, 149, 101,
+        255, 231, 205, 154, 255, 232, 204, 149, 255, 227, 198, 142, 255,
+        223, 192, 138, 255, 223, 193, 136, 255, 230, 199, 139, 255, 232,
+        197, 141, 255, 211, 176, 122, 255, 64, 57, 41, 255, 8, 8, 7, 113, 0,
+        8, 6, 6, 5, 14, 33, 31, 24, 227, 186, 155, 107, 255, 232, 204, 149,
+        255, 233, 205, 152, 255, 227, 197, 140, 255, 221, 189, 132, 255,
+        224, 192, 135, 255, 228, 198, 141, 255, 232, 201, 141, 255, 232,
+        192, 135, 255, 231, 197, 132, 255, 41, 35, 26, 255, 0, 64, 17, 16,
+        14, 139, 211, 178, 120, 255, 233, 202, 148, 255, 233, 202, 148, 255,
+        56, 48, 33, 255, 4, 4, 4, 85, 0, 104, 11, 11, 10, 255, 216, 164, 89,
+        255, 230, 191, 123, 255, 227, 195, 134, 255, 40, 35, 27, 227, 0, 28,
+        16, 15, 13, 227, 126, 105, 69, 255, 217, 176, 112, 255, 225, 175,
+        104, 255, 223, 159, 76, 255, 189, 124, 49, 255, 43, 35, 20, 255, 9,
+        8, 8, 57, 0, 8, 10, 10, 9, 133, 194, 109, 33, 255, 215, 125, 38,
+        255, 212, 124, 39, 255, 144, 93, 33, 255, 29, 24, 16, 255, 68, 53,
+        29, 255, 186, 123, 49, 255, 128, 95, 47, 255, 25, 24, 20, 255, 143,
+        119, 78, 255, 230, 201, 145, 255, 33, 30, 24, 255, 0, 8, 11, 11, 10,
+        170, 217, 176, 112, 255, 228, 182, 109, 255, 222, 158, 75, 255, 212,
+        134, 51, 255, 204, 122, 41, 255, 198, 117, 37, 255, 200, 118, 37,
+        255, 208, 123, 39, 255, 212, 123, 37, 255, 214, 121, 39, 255, 217,
+        133, 50, 255, 24, 21, 15, 244, 0, 8, 11, 11, 10, 170, 218, 185, 127,
+        255, 235, 203, 148, 255, 233, 202, 148, 255, 230, 201, 145, 255,
+        227, 197, 140, 255, 221, 187, 128, 255, 221, 184, 120, 255, 224,
+        178, 105, 255, 224, 164, 85, 255, 189, 129, 58, 255, 39, 32, 20,
+        255, 7, 7, 6, 85, 0, 8, 11, 10, 8, 125, 194, 109, 33, 255, 215, 125,
+        38, 255, 213, 125, 40, 255, 29, 24, 16, 255, 0, 40, 17, 17, 14, 170,
+        221, 188, 130, 255, 235, 201, 152, 255, 232, 201, 141, 255, 42, 36,
+        27, 255, 0, 12, 17, 17, 14, 170, 219, 179, 116, 255, 231, 187, 124,
+        255, 228, 183, 111, 255, 24, 22, 17, 255, 0, 8, 11, 11, 10, 170,
+        218, 185, 127, 255, 232, 197, 137, 255, 227, 179, 104, 255, 219,
+        155, 72, 255, 208, 132, 51, 255, 204, 122, 41, 255, 202, 120, 39,
+        255, 38, 31, 19, 170, 0, 16, 12, 11, 9, 170, 196, 110, 33, 255, 215,
+        113, 38, 255, 213, 122, 42, 255, 215, 143, 58, 255, 217, 166, 92,
+        255, 222, 186, 123, 255, 225, 195, 136, 255, 52, 44, 33, 198, 0, 16,
+        17, 16, 14, 170, 211, 150, 70, 255, 219, 140, 56, 255, 213, 126, 42,
+        255, 25, 21, 14, 255, 0, 40, 17, 17, 14, 170, 221, 187, 128, 255,
+        232, 199, 141, 255, 228, 180, 111, 255, 219, 155, 72, 255, 207, 128,
+        44, 255, 199, 119, 39, 255, 200, 118, 37, 255, 208, 123, 39, 255,
+        212, 123, 37, 255, 214, 125, 39, 255, 212, 124, 39, 255, 34, 26, 15,
+        181, 0, 8, 11, 10, 10, 161, 215, 172, 104, 255, 234, 201, 143, 255,
+        234, 206, 151, 255, 42, 39, 29, 255, 0, 40, 12, 11, 9, 170, 196,
+        110, 33, 255, 215, 125, 38, 255, 212, 124, 39, 255, 36, 28, 17, 170,
+        0, 8, 15, 14, 10, 85, 194, 109, 33, 255, 215, 125, 38, 255, 212,
+        124, 39, 255, 210, 128, 41, 255, 211, 135, 54, 255, 225, 176, 98,
+        255, 231, 197, 132, 255, 56, 48, 33, 255, 4, 4, 4, 85, 0, 20, 17,
+        16, 14, 170, 206, 135, 51, 255, 217, 133, 50, 255, 213, 122, 42,
+        255, 25, 21, 14, 255, 0, 32, 12, 11, 9, 170, 196, 110, 33, 255, 215,
+        125, 38, 255, 213, 122, 42, 255, 67, 51, 28, 255, 6, 6, 5, 255, 40,
+        34, 25, 255, 226, 190, 127, 255, 138, 110, 69, 255, 7, 7, 7, 255,
+        25, 24, 20, 255, 221, 179, 112, 255, 232, 191, 127, 255, 232, 201,
+        141, 255, 26, 23, 19, 255, 0, 8, 11, 11, 10, 170, 214, 168, 101,
+        255, 230, 187, 119, 255, 228, 188, 117, 255, 212, 173, 105, 255,
+        150, 118, 67, 255, 102, 86, 47, 255, 111, 90, 50, 255, 185, 145, 88,
+        255, 227, 187, 118, 255, 231, 195, 132, 255, 232, 201, 141, 255, 26,
+        23, 19, 255, 0, 8, 11, 11, 10, 170, 219, 184, 128, 255, 235, 205,
+        154, 255, 234, 206, 151, 255, 42, 36, 27, 255, 0, 12, 15, 15, 12,
+        170, 213, 158, 80, 255, 228, 182, 109, 255, 230, 191, 123, 255, 27,
+        23, 18, 255, 0, 8, 11, 11, 10, 170, 219, 189, 132, 255, 235, 205,
+        154, 255, 232, 197, 141, 255, 225, 185, 114, 255, 215, 155, 78, 255,
+        206, 135, 51, 255, 205, 126, 42, 255, 209, 128, 42, 255, 212, 121,
+        41, 255, 181, 111, 36, 255, 39, 30, 18, 255, 8, 8, 7, 57, 0, 8, 10,
+        10, 9, 136, 194, 109, 33, 255, 215, 125, 38, 255, 212, 124, 39, 255,
+        24, 20, 13, 255, 0, 12, 15, 14, 12, 170, 210, 146, 71, 255, 229,
+        183, 110, 255, 231, 197, 132, 255, 26, 23, 19, 255, 0, 8, 11, 11,
+        10, 170, 218, 189, 127, 255, 234, 199, 143, 255, 231, 197, 132, 255,
+        225, 176, 106, 255, 214, 153, 75, 255, 208, 138, 55, 255, 205, 133,
+        48, 255, 210, 127, 45, 255, 214, 134, 49, 255, 179, 119, 42, 255,
+        37, 30, 18, 255, 7, 7, 6, 85, 0, 12, 23, 20, 14, 227, 161, 115, 50,
+        255, 222, 167, 89, 255, 227, 186, 114, 255, 225, 190, 130, 255, 223,
+        198, 136, 255, 227, 198, 142, 255, 224, 196, 141, 255, 221, 191,
+        134, 255, 161, 130, 86, 255, 33, 30, 24, 229, 10, 10, 9, 42, 0, 24,
+        15, 15, 12, 170, 211, 149, 76, 255, 228, 182, 109, 255, 231, 189,
+        128, 255, 44, 39, 27, 255, 0, 24, 17, 17, 14, 170, 216, 170, 97,
+        255, 226, 172, 95, 255, 224, 165, 81, 255, 31, 26, 18, 255, 0, 12,
+        13, 12, 10, 170, 201, 120, 40, 255, 217, 133, 50, 255, 216, 125, 45,
+        255, 25, 21, 14, 212, 0, 8, 11, 10, 8, 144, 203, 130, 52, 255, 224,
+        166, 83, 255, 228, 174, 103, 255, 40, 34, 25, 255, 0, 12, 17, 16,
+        14, 170, 221, 187, 128, 255, 234, 201, 143, 255, 230, 191, 123, 255,
+        28, 25, 19, 244, 0, 8, 10, 10, 9, 164, 203, 122, 50, 255, 220, 148,
+        63, 255, 217, 141, 52, 255, 23, 20, 14, 255, 0, 8, 14, 13, 11, 108,
+        10, 10, 9, 28, 0, 4, 13, 13, 12, 170, 221, 189, 134, 255, 235, 205,
+        154, 255, 234, 206, 151, 255, 42, 37, 27, 255, 0, 24, 11, 11, 10,
+        255, 222, 189, 131, 255, 232, 195, 131, 255, 224, 162, 81, 255, 36,
+        29, 19, 255, 4, 4, 4, 54, 0, 28, 7, 7, 6, 28, 19, 17, 12, 232, 93,
+        66, 30, 255, 183, 112, 36, 255, 209, 122, 38, 255, 212, 120, 39,
+        255, 159, 102, 34, 255, 22, 19, 13, 255, 7, 7, 6, 85, 0, 24, 6, 6,
+        5, 28, 17, 16, 14, 227, 149, 122, 84, 255, 227, 195, 140, 255, 227,
+        191, 134, 255, 179, 142, 90, 255, 17, 16, 14, 227, 5, 5, 4, 25, 0,
+        20, 15, 14, 12, 170, 204, 129, 49, 255, 218, 141, 51, 255, 213, 126,
+        42, 255, 25, 21, 14, 255, 0, 24, 8, 7, 7, 91, 68, 48, 25, 255, 205,
+        127, 44, 255, 220, 153, 75, 255, 99, 78, 44, 255, 8, 8, 7, 113, 0,
+        28, 12, 11, 9, 170, 196, 110, 33, 255, 215, 125, 38, 255, 212, 124,
+        39, 255, 24, 20, 13, 255, 0, 124, 9, 9, 8, 25, 0, 40, 2, 2, 1, 23,
+        9, 8, 6, 255, 199, 116, 34, 255, 215, 125, 38, 255, 212, 128, 45,
+        255, 27, 24, 16, 207, 0, 8, 11, 11, 10, 170, 219, 184, 128, 255,
+        235, 205, 154, 255, 234, 205, 155, 255, 58, 49, 35, 255, 5, 5, 4,
+        85, 0, 4, 4, 4, 3, 28, 16, 15, 11, 227, 204, 122, 41, 255, 215, 126,
+        40, 255, 210, 123, 39, 255, 32, 25, 15, 170, 0, 8, 13, 13, 12, 122,
+        208, 168, 99, 255, 234, 199, 143, 255, 234, 204, 151, 255, 63, 54,
+        38, 255, 5, 5, 4, 85, 0, 4, 4, 4, 3, 28, 18, 17, 13, 215, 204, 127,
+        45, 255, 214, 125, 39, 255, 212, 121, 41, 255, 34, 27, 15, 170, 0,
+        8, 13, 12, 10, 85, 185, 112, 34, 255, 215, 125, 38, 255, 212, 123,
+        37, 255, 35, 28, 16, 255, 4, 4, 3, 85, 0, 4, 3, 3, 2, 28, 12, 10, 9,
+        224, 198, 117, 37, 255, 215, 125, 38, 255, 212, 124, 39, 255, 34,
+        27, 15, 178, 0, 8, 14, 13, 11, 113, 206, 162, 94, 255, 232, 199,
+        141, 255, 234, 207, 155, 255, 63, 53, 36, 255, 4, 4, 3, 113, 0, 4,
+        3, 3, 3, 28, 10, 10, 9, 255, 200, 118, 37, 255, 215, 125, 38, 255,
+        210, 123, 39, 255, 27, 22, 14, 227, 0, 12, 3, 3, 2, 6, 13, 11, 8,
+        221, 199, 116, 34, 255, 215, 125, 38, 255, 212, 124, 39, 255, 35,
+        27, 16, 255, 5, 4, 4, 57, 0, 12, 15, 14, 12, 147, 206, 154, 87, 255,
+        232, 195, 137, 255, 234, 204, 151, 255, 63, 54, 38, 255, 5, 5, 4,
+        85, 0, 4, 4, 4, 3, 28, 18, 16, 13, 227, 222, 189, 131, 255, 235,
+        205, 152, 255, 234, 205, 155, 255, 27, 24, 20, 255, 0, 8, 11, 11,
+        10, 170, 219, 184, 130, 255, 235, 205, 152, 255, 234, 205, 155, 255,
+        58, 49, 35, 255, 5, 5, 4, 85, 0, 4, 4, 4, 3, 28, 14, 12, 9, 227,
+        199, 117, 36, 255, 215, 113, 38, 255, 210, 123, 39, 255, 32, 25, 15,
+        170, 0, 8, 12, 12, 9, 102, 194, 109, 33, 255, 215, 125, 38, 255,
+        212, 124, 39, 255, 27, 22, 14, 255, 0, 24, 18, 16, 13, 170, 217,
+        176, 110, 255, 234, 196, 143, 255, 234, 204, 151, 255, 27, 24, 20,
+        255, 0, 8, 11, 10, 10, 170, 204, 134, 59, 255, 219, 136, 54, 255,
+        213, 122, 42, 255, 72, 50, 27, 255, 8, 8, 7, 255, 25, 22, 14, 255,
+        195, 116, 38, 255, 208, 123, 39, 255, 142, 91, 31, 255, 16, 14, 9,
+        193, 4, 4, 3, 17, 0, 12, 11, 11, 8, 170, 198, 117, 37, 255, 219,
+        133, 56, 255, 221, 152, 70, 255, 27, 23, 16, 221, 0, 8, 13, 12, 10,
+        99, 193, 113, 34, 255, 223, 156, 70, 255, 231, 193, 128, 255, 40,
+        34, 25, 255, 4, 3, 3, 113, 17, 16, 12, 227, 208, 136, 59, 255, 45,
+        36, 21, 255, 4, 3, 3, 113, 10, 9, 7, 207, 196, 110, 33, 255, 215,
+        125, 38, 255, 210, 128, 41, 255, 32, 25, 15, 170, 0, 8, 12, 11, 9,
+        108, 194, 109, 33, 255, 215, 125, 38, 255, 212, 124, 39, 255, 35,
+        27, 16, 255, 4, 4, 3, 85, 0, 4, 3, 3, 2, 28, 12, 11, 9, 227, 199,
+        117, 36, 255, 221, 150, 66, 255, 229, 191, 126, 255, 32, 29, 23,
+        210, 0, 8, 13, 13, 12, 122, 204, 150, 79, 255, 223, 159, 76, 255,
+        217, 141, 52, 255, 84, 57, 29, 255, 9, 8, 6, 170, 5, 5, 4, 85, 6, 6,
+        5, 113, 27, 22, 14, 255, 207, 128, 44, 255, 223, 147, 72, 255, 227,
+        187, 118, 255, 34, 30, 23, 207, 0, 8, 12, 11, 11, 170, 218, 180,
+        119, 255, 229, 184, 114, 255, 224, 167, 85, 255, 50, 40, 25, 255, 5,
+        5, 4, 85, 0, 4, 4, 4, 3, 28, 14, 12, 9, 227, 203, 125, 42, 255, 217,
+        128, 48, 255, 213, 128, 45, 255, 35, 27, 16, 173, 0, 8, 12, 12, 11,
+        130, 209, 163, 98, 255, 235, 203, 148, 255, 233, 202, 148, 255, 63,
+        54, 36, 255, 5, 5, 4, 85, 0, 4, 4, 4, 3, 28, 15, 15, 12, 227, 209,
+        137, 60, 255, 221, 151, 68, 255, 219, 147, 62, 255, 23, 20, 14, 238,
+        0, 8, 10, 10, 9, 150, 196, 121, 41, 255, 217, 128, 48, 255, 215,
+        133, 44, 255, 40, 31, 19, 255, 5, 5, 5, 85, 0, 4, 4, 4, 3, 28, 16,
+        14, 11, 207, 201, 120, 40, 255, 217, 133, 50, 255, 221, 161, 76,
+        255, 57, 44, 28, 170, 0, 8, 15, 14, 12, 105, 211, 165, 98, 255, 232,
+        197, 137, 255, 232, 199, 141, 255, 58, 49, 35, 255, 4, 4, 3, 113, 0,
+        40, 3, 3, 2, 17, 12, 11, 9, 227, 199, 116, 34, 255, 215, 125, 38,
+        255, 212, 124, 39, 255, 35, 27, 16, 255, 4, 4, 3, 62, 0, 12, 12, 11,
+        9, 170, 200, 120, 41, 255, 223, 159, 76, 255, 230, 191, 123, 255,
+        44, 37, 27, 255, 0, 12, 18, 17, 15, 170, 208, 140, 59, 255, 217,
+        133, 50, 255, 213, 125, 40, 255, 27, 23, 14, 195, 0, 8, 12, 11, 9,
+        108, 194, 109, 33, 255, 215, 125, 38, 255, 212, 124, 39, 255, 25,
+        21, 14, 255, 0, 12, 17, 16, 14, 170, 219, 179, 116, 255, 235, 201,
+        152, 255, 234, 204, 151, 255, 27, 24, 20, 255, 0, 8, 10, 10, 9, 170,
+        198, 122, 41, 255, 215, 127, 42, 255, 213, 125, 40, 255, 27, 22, 14,
+        255, 0, 20, 12, 11, 9, 170, 201, 120, 40, 255, 224, 156, 83, 255,
+        231, 190, 132, 255, 40, 33, 25, 255, 0, 12, 10, 10, 9, 85, 52, 42,
+        29, 255, 200, 142, 59, 255, 183, 119, 44, 255, 72, 52, 27, 255, 39,
+        30, 18, 255, 49, 37, 22, 255, 150, 99, 33, 255, 196, 116, 37, 255,
+        77, 50, 24, 255, 10, 9, 7, 144, 0, 12, 10, 10, 9, 170, 196, 115, 35,
+        255, 215, 125, 38, 255, 212, 124, 39, 255, 25, 21, 14, 255, 0, 12,
+        12, 11, 9, 170, 196, 110, 33, 255, 214, 127, 43, 255, 222, 158, 75,
+        255, 41, 34, 24, 255, 0, 24, 5, 5, 4, 85, 11, 11, 10, 255, 130, 101,
+        59, 255, 223, 176, 102, 255, 224, 176, 101, 255, 177, 137, 74, 255,
+        18, 17, 13, 227, 6, 5, 5, 28, 0, 12, 20, 19, 15, 85, 186, 120, 49,
+        255, 217, 142, 62, 255, 217, 139, 56, 255, 34, 29, 19, 255, 4, 4, 3,
+        17, 0, 20, 17, 17, 14, 170, 221, 188, 130, 255, 235, 205, 152, 255,
+        234, 205, 155, 255, 42, 39, 29, 255, 0, 24, 13, 13, 10, 181, 199,
+        119, 39, 255, 212, 121, 41, 255, 203, 121, 40, 255, 35, 29, 17, 170,
+        0, 100, 20, 18, 15, 170, 222, 186, 123, 255, 234, 201, 143, 255,
+        232, 197, 135, 255, 47, 40, 28, 255, 0, 64, 14, 13, 11, 170, 213,
+        160, 84, 255, 230, 187, 119, 255, 231, 197, 132, 255, 35, 30, 22,
+        198, 0, 4, 14, 13, 11, 108, 217, 176, 112, 255, 232, 193, 137, 255,
+        231, 197, 132, 255, 33, 28, 22, 255, 0, 24, 12, 12, 11, 113, 31, 29,
+        22, 210, 40, 35, 27, 255, 41, 34, 24, 255, 29, 24, 16, 255, 32, 26,
+        17, 255, 146, 92, 35, 255, 214, 134, 49, 255, 212, 128, 45, 255,
+        123, 81, 36, 255, 15, 13, 10, 142, 0, 20, 7, 7, 6, 85, 28, 26, 19,
+        252, 194, 140, 71, 255, 212, 127, 43, 255, 202, 118, 35, 255, 97,
+        66, 30, 255, 15, 14, 10, 207, 6, 6, 5, 25, 0, 24, 6, 6, 5, 8, 15,
+        13, 12, 227, 111, 86, 50, 255, 209, 168, 102, 255, 176, 136, 83,
+        255, 85, 67, 44, 255, 163, 129, 80, 255, 221, 186, 126, 255, 83, 69,
+        44, 255, 7, 7, 6, 170, 5, 5, 5, 8, 0, 4, 9, 9, 8, 108, 20, 18, 13,
+        170, 13, 12, 10, 51, 0, 36, 16, 15, 13, 170, 217, 176, 110, 255,
+        232, 194, 133, 255, 232, 198, 139, 255, 36, 33, 25, 255, 0, 24, 15,
+        15, 12, 170, 219, 179, 116, 255, 232, 193, 137, 255, 232, 199, 135,
+        255, 31, 26, 20, 255, 0, 8, 11, 11, 10, 28, 56, 48, 33, 227, 98, 76,
+        45, 255, 104, 80, 45, 255, 195, 154, 96, 255, 227, 186, 114, 255,
+        226, 189, 125, 255, 207, 173, 114, 255, 222, 188, 123, 255, 231,
+        190, 132, 255, 217, 188, 124, 255, 137, 109, 70, 255, 99, 86, 54,
+        255, 78, 64, 43, 255, 21, 20, 16, 85, 0, 8, 12, 12, 11, 28, 54, 48,
+        35, 227, 86, 72, 47, 255, 74, 63, 43, 255, 171, 137, 84, 255, 229,
+        191, 130, 255, 230, 191, 123, 255, 230, 186, 123, 255, 202, 164,
+        105, 255, 97, 80, 50, 255, 75, 64, 44, 255, 72, 61, 39, 255, 22, 21,
+        17, 102, 0, 36, 12, 11, 11, 45, 55, 45, 30, 227, 90, 71, 45, 255,
+        78, 63, 41, 255, 72, 61, 39, 255, 74, 63, 43, 255, 72, 61, 39, 255,
+        72, 61, 39, 255, 91, 74, 46, 255, 78, 63, 41, 255, 22, 20, 17, 102,
+        0, 48, 12, 12, 11, 176, 132, 106, 61, 255, 228, 188, 125, 255, 210,
+        172, 113, 255, 42, 37, 29, 255, 9, 9, 8, 62, 0, 16, 17, 16, 14, 170,
+        221, 186, 124, 255, 234, 199, 143, 255, 232, 201, 141, 255, 232,
+        201, 141, 255, 221, 189, 134, 255, 52, 46, 33, 255, 6, 7, 6, 227,
+        24, 23, 17, 255, 208, 132, 51, 255, 215, 133, 44, 255, 212, 124, 39,
+        255, 24, 20, 13, 255, 0, 24, 17, 16, 12, 170, 219, 177, 112, 255,
+        231, 187, 124, 255, 228, 182, 109, 255, 40, 33, 23, 255, 0, 36, 9,
+        9, 8, 74, 17, 15, 12, 227, 67, 51, 28, 255, 162, 107, 43, 255, 200,
+        142, 67, 255, 204, 157, 91, 255, 177, 140, 86, 255, 74, 63, 43, 255,
+        19, 17, 16, 198, 9, 9, 8, 28, 0, 32, 14, 14, 11, 31, 56, 46, 31,
+        227, 192, 157, 103, 255, 229, 194, 128, 255, 225, 188, 124, 255,
+        146, 112, 67, 255, 11, 10, 8, 164, 0, 8, 7, 7, 6, 28, 34, 27, 17,
+        255, 190, 107, 33, 255, 210, 121, 35, 255, 146, 95, 35, 255, 16, 14,
+        11, 187, 0, 8, 9, 9, 8, 170, 214, 164, 93, 255, 232, 194, 127, 255,
+        231, 195, 132, 255, 40, 34, 25, 255, 0, 40, 13, 13, 10, 170, 213,
+        157, 84, 255, 224, 166, 83, 255, 221, 150, 66, 255, 23, 20, 14, 246,
+        0, 8, 12, 11, 9, 113, 194, 109, 33, 255, 212, 119, 37, 255, 210,
+        113, 35, 255, 168, 103, 33, 255, 56, 42, 23, 255, 27, 23, 14, 255,
+        38, 31, 19, 255, 149, 92, 30, 255, 207, 118, 32, 255, 207, 113, 30,
+        255, 124, 75, 27, 255, 13, 11, 8, 161, 0, 28, 12, 12, 11, 176, 130,
+        99, 59, 255, 229, 191, 126, 255, 211, 174, 116, 255, 43, 37, 28,
+        255, 9, 9, 8, 59, 0, 16, 8, 8, 7, 85, 68, 58, 37, 255, 214, 177,
+        119, 255, 231, 196, 136, 255, 207, 171, 114, 255, 97, 80, 50, 255,
+        54, 47, 35, 255, 66, 59, 41, 255, 178, 148, 95, 255, 228, 189, 121,
+        255, 224, 187, 123, 255, 146, 112, 67, 255, 12, 12, 11, 170, 0, 12,
+        10, 10, 9, 28, 16, 15, 13, 147, 29, 28, 22, 221, 48, 42, 31, 255,
+        70, 61, 41, 255, 66, 57, 39, 255, 70, 61, 41, 255, 171, 140, 92,
+        255, 224, 170, 101, 255, 224, 168, 87, 255, 224, 165, 81, 255, 39,
+        32, 22, 255, 0, 64, 14, 13, 11, 57, 100, 82, 51, 255, 222, 186, 123,
+        255, 226, 172, 95, 255, 113, 82, 38, 255, 9, 8, 8, 127, 0, 32, 11,
+        9, 6, 102, 11, 10, 6, 170, 11, 10, 8, 170, 12, 11, 9, 170, 15, 13,
+        10, 170, 15, 13, 10, 170, 15, 14, 10, 170, 18, 15, 11, 170, 18, 15,
+        11, 156, 12, 11, 9, 28, 0, 28, 6, 6, 5, 65, 40, 34, 25, 255, 224,
+        183, 119, 255, 229, 195, 136, 255, 171, 140, 92, 255, 21, 20, 18,
+        142, 0, 24, 11, 10, 8, 102, 131, 92, 46, 255, 213, 145, 56, 255,
+        214, 119, 43, 255, 210, 128, 41, 255, 151, 94, 32, 255, 23, 21, 14,
+        255, 10, 10, 9, 85, 0, 12, 10, 9, 7, 170, 191, 106, 30, 255, 211,
+        115, 30, 255, 208, 114, 31, 255, 141, 87, 30, 255, 36, 31, 19, 255,
+        121, 90, 42, 255, 217, 168, 92, 255, 205, 163, 102, 255, 132, 102,
+        59, 255, 213, 172, 108, 255, 231, 193, 128, 255, 35, 30, 22, 255, 0,
+        8, 11, 11, 10, 164, 203, 129, 50, 255, 215, 127, 42, 255, 211, 117,
+        34, 255, 166, 97, 29, 255, 54, 40, 21, 255, 29, 23, 14, 255, 38, 31,
+        19, 255, 120, 78, 29, 255, 206, 118, 33, 255, 214, 127, 43, 255,
+        224, 155, 81, 255, 23, 21, 16, 255, 0, 8, 11, 10, 10, 170, 217, 183,
+        116, 255, 234, 201, 143, 255, 232, 198, 139, 255, 202, 166, 109,
+        255, 97, 78, 50, 255, 52, 46, 33, 255, 58, 50, 33, 255, 150, 96, 39,
+        255, 208, 121, 37, 255, 195, 112, 30, 255, 83, 53, 24, 255, 9, 8, 6,
+        113, 0, 8, 13, 12, 8, 96, 189, 104, 28, 255, 210, 120, 33, 255, 214,
+        132, 45, 255, 34, 29, 19, 255, 0, 40, 17, 16, 12, 170, 217, 172,
+        102, 255, 228, 180, 105, 255, 228, 181, 107, 255, 40, 33, 23, 255,
+        0, 12, 17, 15, 12, 170, 216, 171, 101, 255, 232, 191, 127, 255, 231,
+        197, 132, 255, 24, 22, 17, 255, 0, 8, 11, 11, 10, 167, 209, 146, 72,
+        255, 221, 151, 68, 255, 213, 126, 42, 255, 172, 106, 35, 255, 57,
+        41, 22, 255, 42, 32, 19, 255, 43, 33, 20, 252, 18, 15, 11, 85, 0,
+        16, 11, 10, 8, 170, 193, 111, 30, 255, 215, 113, 38, 255, 220, 144,
+        63, 255, 197, 145, 84, 255, 91, 71, 44, 255, 75, 62, 42, 255, 75,
+        64, 44, 255, 22, 21, 17, 99, 0, 16, 14, 13, 11, 170, 196, 110, 33,
+        255, 210, 115, 31, 255, 210, 115, 31, 255, 22, 19, 11, 227, 0, 8,
+        16, 13, 9, 113, 24, 21, 15, 170, 17, 15, 12, 170, 18, 15, 13, 170,
+        19, 17, 12, 142, 9, 8, 8, 28, 0, 8, 14, 13, 11, 170, 210, 146, 71,
+        255, 220, 142, 59, 255, 213, 125, 40, 255, 168, 103, 33, 255, 54,
+        40, 21, 255, 29, 23, 14, 255, 38, 31, 19, 255, 119, 78, 30, 255,
+        204, 116, 31, 255, 210, 119, 31, 255, 210, 115, 31, 255, 26, 20, 13,
+        210, 0, 8, 11, 11, 10, 170, 217, 179, 120, 255, 234, 202, 147, 255,
+        232, 201, 141, 255, 40, 35, 25, 255, 0, 40, 11, 10, 8, 170, 193,
+        111, 30, 255, 211, 115, 30, 255, 210, 115, 31, 255, 36, 25, 13, 170,
+        0, 8, 14, 12, 9, 85, 190, 105, 29, 255, 210, 107, 31, 255, 208, 114,
+        31, 255, 187, 124, 42, 255, 143, 111, 56, 255, 210, 171, 109, 255,
+        229, 187, 128, 255, 131, 99, 54, 255, 8, 8, 7, 156, 0, 20, 13, 12,
+        10, 170, 194, 112, 31, 255, 210, 107, 31, 255, 210, 115, 31, 255,
+        22, 19, 11, 255, 0, 32, 11, 10, 8, 170, 193, 111, 30, 255, 215, 125,
+        38, 255, 218, 141, 59, 255, 39, 33, 22, 255, 5, 5, 5, 28, 12, 12,
+        11, 170, 156, 126, 83, 255, 27, 24, 20, 227, 5, 5, 5, 23, 14, 13,
+        11, 198, 219, 177, 112, 255, 232, 191, 127, 255, 230, 191, 123, 255,
+        25, 22, 16, 249, 0, 8, 11, 10, 8, 153, 200, 120, 41, 255, 214, 127,
+        43, 255, 213, 126, 42, 255, 93, 66, 32, 255, 11, 11, 10, 255, 34,
+        31, 23, 255, 206, 152, 81, 255, 226, 179, 111, 255, 231, 189, 128,
+        255, 232, 192, 135, 255, 232, 201, 141, 255, 25, 22, 18, 255, 0, 8,
+        11, 10, 10, 170, 215, 171, 102, 255, 228, 174, 105, 255, 222, 158,
+        75, 255, 27, 24, 16, 255, 0, 12, 15, 15, 12, 170, 219, 177, 112,
+        255, 232, 193, 137, 255, 232, 201, 141, 255, 25, 22, 18, 255, 0, 8,
+        11, 10, 10, 170, 215, 172, 104, 255, 228, 182, 109, 255, 221, 155,
+        70, 255, 177, 114, 46, 255, 55, 42, 24, 255, 35, 28, 18, 255, 41,
+        31, 18, 255, 35, 28, 17, 255, 27, 22, 14, 255, 17, 16, 12, 187, 9,
+        9, 8, 79, 0, 12, 10, 9, 7, 170, 191, 106, 30, 255, 211, 115, 30,
+        255, 210, 115, 31, 255, 33, 25, 14, 255, 0, 12, 21, 20, 16, 170,
+        221, 180, 116, 255, 232, 193, 137, 255, 232, 201, 141, 255, 25, 22,
+        18, 255, 0, 8, 11, 11, 10, 170, 212, 160, 85, 255, 224, 156, 83,
+        255, 218, 141, 59, 255, 175, 115, 44, 255, 55, 42, 24, 255, 31, 25,
+        16, 255, 38, 30, 19, 255, 127, 82, 30, 255, 204, 116, 31, 255, 195,
+        112, 30, 255, 82, 55, 25, 255, 11, 10, 8, 150, 0, 12, 9, 9, 8, 28,
+        15, 14, 12, 142, 28, 25, 19, 221, 46, 40, 29, 255, 71, 60, 38, 255,
+        66, 57, 39, 255, 70, 61, 41, 255, 193, 159, 106, 255, 227, 184, 108,
+        255, 221, 153, 72, 255, 155, 98, 36, 255, 13, 12, 10, 170, 0, 24,
+        17, 15, 12, 170, 219, 180, 112, 255, 232, 197, 137, 255, 232, 201,
+        141, 255, 40, 35, 25, 255, 0, 24, 14, 13, 11, 170, 198, 117, 37,
+        255, 213, 124, 38, 255, 210, 121, 35, 255, 23, 19, 12, 255, 0, 12,
+        11, 10, 8, 170, 193, 111, 30, 255, 211, 115, 30, 255, 208, 114, 31,
+        255, 23, 19, 12, 207, 0, 8, 14, 13, 11, 85, 181, 132, 68, 255, 228,
+        185, 117, 255, 231, 193, 128, 255, 54, 46, 31, 255, 5, 5, 4, 8, 0,
+        8, 21, 20, 16, 178, 215, 160, 88, 255, 223, 147, 72, 255, 206, 135,
+        51, 255, 23, 20, 14, 170, 0, 8, 12, 11, 9, 102, 192, 111, 31, 255,
+        210, 108, 33, 255, 208, 114, 31, 255, 22, 18, 11, 255, 0, 4, 10, 10,
+        9, 113, 79, 61, 38, 255, 17, 16, 12, 198, 0, 4, 16, 15, 13, 170,
+        219, 179, 116, 255, 231, 187, 124, 255, 224, 169, 91, 255, 33, 28,
+        20, 255, 0, 20, 9, 8, 8, 85, 39, 33, 24, 255, 217, 166, 92, 255,
+        219, 140, 56, 255, 210, 121, 35, 255, 66, 44, 21, 255, 7, 7, 6, 133,
+        0, 32, 6, 6, 5, 74, 19, 18, 12, 255, 183, 102, 30, 255, 207, 105,
+        30, 255, 210, 111, 31, 255, 73, 51, 24, 255, 8, 8, 7, 116, 0, 24, 6,
+        6, 6, 28, 15, 13, 12, 227, 144, 112, 61, 255, 221, 180, 116, 255,
+        224, 178, 113, 255, 152, 116, 65, 255, 18, 17, 13, 221, 8, 8, 7, 28,
+        0, 24, 12, 10, 9, 170, 193, 111, 30, 255, 210, 107, 31, 255, 210,
+        115, 31, 255, 22, 19, 11, 255, 0, 28, 16, 15, 13, 227, 164, 122, 63,
+        255, 225, 185, 114, 255, 192, 153, 97, 255, 21, 19, 16, 232, 7, 7,
+        6, 28, 0, 24, 11, 10, 8, 170, 193, 111, 30, 255, 211, 115, 30, 255,
+        210, 115, 31, 255, 23, 19, 12, 255, 0, 148, 6, 6, 5, 51, 11, 9, 6,
+        85, 12, 10, 7, 102, 10, 8, 5, 156, 10, 8, 5, 127, 8, 7, 5, 184, 27,
+        22, 12, 255, 198, 105, 29, 255, 211, 122, 36, 255, 220, 136, 61,
+        255, 25, 22, 16, 255, 0, 8, 10, 10, 9, 170, 218, 181, 123, 255, 234,
+        202, 147, 255, 232, 197, 141, 255, 30, 27, 21, 255, 0, 12, 9, 8, 6,
+        170, 191, 106, 30, 255, 211, 115, 30, 255, 210, 111, 31, 255, 39,
+        27, 14, 170, 0, 8, 12, 11, 11, 170, 218, 180, 119, 255, 234, 196,
+        143, 255, 232, 201, 141, 255, 29, 26, 20, 255, 0, 12, 7, 7, 6, 28,
+        27, 22, 14, 156, 25, 22, 14, 255, 32, 25, 15, 210, 22, 18, 11, 28,
+        0, 8, 10, 9, 7, 150, 195, 112, 30, 255, 211, 115, 30, 255, 210, 115,
+        31, 255, 19, 15, 10, 252, 0, 12, 9, 9, 8, 170, 191, 106, 30, 255,
+        211, 111, 30, 255, 208, 114, 31, 255, 25, 20, 12, 204, 0, 8, 12, 11,
+        11, 170, 218, 180, 119, 255, 234, 202, 147, 255, 232, 201, 141, 255,
+        142, 111, 63, 255, 14, 12, 9, 227, 10, 9, 7, 127, 8, 7, 5, 181, 35,
+        25, 14, 255, 199, 112, 28, 255, 209, 118, 30, 255, 209, 117, 28,
+        255, 30, 22, 13, 255, 0, 16, 9, 8, 6, 167, 191, 106, 30, 255, 211,
+        115, 30, 255, 210, 115, 31, 255, 19, 15, 10, 252, 0, 16, 21, 19, 16,
+        170, 220, 178, 113, 255, 232, 197, 137, 255, 232, 201, 141, 255, 26,
+        23, 19, 255, 0, 12, 11, 11, 10, 170, 218, 181, 123, 255, 234, 201,
+        143, 255, 231, 197, 132, 255, 24, 22, 17, 255, 0, 8, 11, 10, 10,
+        170, 218, 181, 123, 255, 234, 201, 143, 255, 231, 197, 132, 255, 30,
+        26, 21, 255, 0, 12, 9, 8, 6, 167, 191, 106, 30, 255, 211, 115, 30,
+        255, 210, 111, 31, 255, 39, 27, 14, 170, 0, 8, 13, 12, 8, 85, 190,
+        105, 29, 255, 213, 119, 36, 255, 214, 132, 45, 255, 32, 26, 17, 255,
+        0, 24, 17, 16, 14, 170, 221, 186, 124, 255, 234, 202, 147, 255, 232,
+        199, 135, 255, 25, 22, 18, 252, 0, 8, 11, 10, 8, 127, 192, 111, 31,
+        255, 210, 107, 31, 255, 208, 114, 31, 255, 161, 94, 28, 255, 65, 43,
+        20, 255, 145, 85, 26, 255, 207, 117, 30, 255, 122, 75, 29, 255, 15,
+        14, 10, 170, 5, 5, 4, 8, 0, 16, 11, 10, 8, 170, 196, 115, 35, 255,
+        223, 146, 70, 255, 228, 183, 111, 255, 25, 22, 16, 252, 0, 8, 14,
+        12, 9, 85, 190, 105, 29, 255, 215, 125, 38, 255, 218, 141, 59, 255,
+        30, 24, 17, 195, 0, 4, 10, 10, 7, 170, 193, 111, 30, 255, 20, 17,
+        11, 252, 0, 4, 11, 10, 8, 85, 188, 103, 27, 255, 211, 115, 30, 255,
+        209, 106, 30, 255, 39, 27, 14, 170, 0, 8, 13, 12, 8, 85, 190, 105,
+        29, 255, 211, 115, 30, 255, 210, 115, 31, 255, 19, 15, 10, 255, 0,
+        12, 9, 8, 6, 167, 192, 111, 31, 255, 218, 137, 51, 255, 227, 175,
+        100, 255, 27, 24, 18, 255, 0, 8, 11, 10, 8, 147, 196, 106, 33, 255,
+        210, 108, 33, 255, 210, 115, 31, 255, 30, 23, 13, 255, 4, 4, 3, 14,
+        0, 8, 15, 14, 12, 195, 211, 149, 76, 255, 229, 184, 114, 255, 232,
+        199, 135, 255, 28, 25, 19, 255, 0, 8, 11, 10, 8, 167, 203, 129, 50,
+        255, 215, 127, 42, 255, 210, 121, 35, 255, 20, 17, 11, 232, 0, 12,
+        9, 8, 6, 139, 190, 105, 29, 255, 211, 111, 30, 255, 209, 114, 30,
+        255, 30, 22, 13, 198, 0, 8, 13, 12, 10, 170, 217, 173, 104, 255,
+        232, 193, 137, 255, 232, 194, 139, 255, 25, 22, 18, 255, 0, 12, 9,
+        8, 8, 156, 192, 111, 31, 255, 210, 108, 33, 255, 210, 115, 31, 255,
+        32, 24, 13, 173, 0, 8, 13, 12, 8, 88, 190, 105, 29, 255, 211, 115,
+        30, 255, 208, 114, 31, 255, 19, 15, 10, 255, 0, 12, 7, 7, 6, 28, 27,
+        22, 14, 198, 45, 36, 21, 255, 52, 43, 29, 244, 14, 13, 11, 85, 0, 8,
+        13, 13, 12, 88, 177, 143, 90, 255, 230, 194, 131, 255, 226, 172, 95,
+        255, 137, 91, 36, 255, 10, 9, 7, 227, 8, 8, 5, 161, 10, 9, 7, 167,
+        10, 9, 7, 136, 13, 10, 6, 85, 7, 6, 6, 74, 0, 24, 9, 8, 6, 167, 191,
+        106, 30, 255, 211, 115, 30, 255, 210, 115, 31, 255, 19, 15, 10, 252,
+        0, 16, 12, 11, 9, 170, 208, 141, 61, 255, 230, 187, 119, 255, 232,
+        201, 141, 255, 40, 34, 25, 255, 0, 12, 14, 12, 9, 170, 196, 109, 31,
+        255, 210, 107, 31, 255, 210, 115, 31, 255, 36, 25, 13, 170, 0, 8,
+        10, 9, 7, 85, 155, 91, 28, 255, 208, 114, 31, 255, 209, 106, 30,
+        255, 30, 22, 13, 255, 0, 12, 22, 21, 17, 176, 222, 186, 123, 255,
+        234, 199, 143, 255, 226, 195, 135, 255, 35, 29, 22, 178, 0, 8, 12,
+        11, 9, 105, 190, 105, 29, 255, 211, 115, 30, 255, 208, 114, 31, 255,
+        23, 19, 12, 210, 0, 8, 15, 12, 8, 59, 7, 6, 4, 3, 0, 4, 9, 9, 8,
+        159, 204, 134, 59, 255, 230, 182, 119, 255, 232, 198, 139, 255, 39,
+        33, 24, 255, 0, 16, 10, 10, 9, 34, 15, 14, 10, 198, 52, 40, 21, 255,
+        165, 96, 28, 255, 198, 113, 29, 255, 185, 102, 28, 255, 80, 53, 25,
+        255, 19, 17, 12, 227, 10, 9, 7, 76, 0, 16, 11, 10, 8, 170, 195, 112,
+        30, 255, 211, 115, 30, 255, 210, 115, 31, 255, 20, 16, 11, 255, 0,
+        12, 10, 9, 7, 170, 192, 111, 31, 255, 215, 125, 38, 255, 224, 159,
+        83, 255, 41, 33, 24, 255, 0, 24, 7, 7, 6, 108, 24, 20, 13, 255, 146,
+        88, 31, 255, 195, 127, 38, 255, 113, 77, 34, 255, 15, 14, 12, 210,
+        7, 7, 6, 28, 0, 16, 12, 12, 11, 28, 37, 30, 18, 227, 168, 99, 31,
+        255, 206, 114, 33, 255, 51, 34, 18, 255, 6, 5, 5, 71, 0, 20, 17, 16,
+        14, 170, 221, 186, 124, 255, 234, 202, 147, 255, 232, 201, 141, 255,
+        40, 35, 25, 255, 0, 24, 17, 15, 10, 227, 198, 105, 29, 255, 194,
+        109, 33, 255, 62, 44, 23, 255, 16, 14, 11, 85, 0, 100, 19, 17, 12,
+        142, 214, 171, 97, 255, 228, 183, 113, 255, 227, 186, 108, 255, 50,
+        40, 25, 227, 0, 64, 12, 11, 9, 198, 214, 158, 85, 255, 229, 183,
+        110, 255, 228, 181, 107, 255, 21, 19, 14, 249, 2, 2, 1, 20, 8, 8, 7,
+        181, 210, 156, 79, 255, 226, 169, 95, 255, 224, 155, 81, 255, 33,
+        26, 18, 255, 4, 4, 4, 28, 0, 40, 3, 3, 2, 28, 11, 10, 8, 255, 209,
+        138, 62, 255, 223, 154, 72, 255, 221, 164, 82, 255, 27, 23, 16, 249,
+        0, 16, 7, 7, 6, 79, 46, 38, 25, 255, 197, 151, 84, 255, 222, 161,
+        89, 255, 209, 128, 42, 255, 141, 91, 32, 255, 15, 13, 10, 218, 5, 5,
+        5, 11, 0, 28, 15, 13, 10, 139, 191, 131, 60, 255, 220, 168, 93, 255,
+        168, 123, 69, 255, 14, 13, 11, 227, 5, 5, 5, 85, 9, 9, 8, 170, 105,
+        78, 40, 255, 162, 116, 61, 255, 88, 66, 37, 255, 23, 21, 16, 255,
+        11, 11, 10, 255, 78, 58, 35, 255, 208, 150, 75, 255, 61, 46, 28,
+        181, 0, 36, 15, 13, 10, 170, 216, 170, 97, 255, 230, 187, 119, 255,
+        228, 178, 113, 255, 34, 28, 19, 255, 0, 24, 15, 13, 10, 170, 215,
+        167, 92, 255, 229, 179, 114, 255, 228, 181, 107, 255, 32, 27, 19,
+        255, 0, 16, 6, 6, 6, 25, 5, 5, 4, 198, 52, 42, 27, 255, 220, 169,
+        97, 255, 189, 142, 76, 255, 35, 31, 22, 255, 134, 96, 51, 255, 225,
+        176, 106, 255, 140, 106, 53, 255, 6, 6, 5, 255, 6, 6, 6, 51, 0, 28,
+        5, 5, 5, 28, 15, 13, 10, 227, 208, 136, 59, 255, 218, 138, 53, 255,
+        213, 122, 42, 255, 43, 31, 18, 255, 5, 5, 4, 85, 0, 136, 9, 8, 8,
+        57, 57, 47, 30, 255, 212, 163, 93, 255, 224, 157, 85, 255, 124, 90,
+        45, 255, 10, 10, 9, 147, 0, 20, 15, 13, 10, 170, 216, 170, 97, 255,
+        228, 181, 107, 255, 224, 165, 81, 255, 194, 136, 61, 255, 58, 46,
+        29, 255, 12, 12, 11, 85, 0, 4, 10, 9, 7, 156, 174, 91, 23, 255, 202,
+        103, 23, 255, 202, 102, 21, 255, 20, 16, 9, 255, 0, 24, 15, 13, 10,
+        170, 213, 155, 80, 255, 227, 175, 100, 255, 227, 171, 98, 255, 35,
+        29, 20, 255, 0, 32, 7, 7, 6, 85, 49, 33, 18, 255, 183, 108, 34, 255,
+        209, 128, 42, 255, 209, 137, 60, 255, 186, 134, 67, 255, 95, 74, 39,
+        255, 22, 20, 15, 229, 8, 8, 7, 105, 0, 44, 5, 4, 4, 28, 17, 15, 12,
+        227, 216, 167, 89, 255, 228, 181, 107, 255, 223, 176, 102, 255, 34,
+        28, 19, 184, 0, 8, 12, 11, 9, 108, 180, 106, 33, 255, 214, 125, 39,
+        255, 217, 141, 52, 255, 42, 33, 21, 255, 4, 4, 4, 85, 0, 8, 11, 10,
+        8, 198, 211, 149, 76, 255, 224, 160, 77, 255, 220, 144, 63, 255, 34,
+        27, 17, 255, 0, 40, 12, 10, 7, 170, 189, 99, 26, 255, 206, 102, 25,
+        255, 203, 100, 24, 255, 30, 21, 11, 176, 0, 8, 12, 10, 7, 85, 167,
+        87, 22, 255, 202, 103, 23, 255, 202, 102, 21, 255, 27, 20, 10, 255,
+        4, 4, 3, 68, 0, 4, 4, 4, 4, 28, 12, 10, 7, 215, 176, 91, 23, 255,
+        203, 104, 24, 255, 202, 105, 27, 255, 28, 21, 13, 249, 0, 24, 9, 8,
+        8, 57, 57, 47, 30, 255, 213, 167, 94, 255, 228, 184, 115, 255, 126,
+        92, 47, 255, 9, 9, 8, 147, 0, 20, 13, 12, 10, 167, 199, 131, 58,
+        255, 220, 148, 63, 255, 219, 147, 62, 255, 49, 38, 24, 255, 6, 6, 6,
+        85, 0, 4, 5, 5, 5, 28, 15, 14, 12, 227, 217, 169, 94, 255, 228, 183,
+        111, 255, 225, 174, 102, 255, 31, 25, 18, 241, 0, 36, 5, 5, 5, 28,
+        15, 13, 10, 227, 204, 127, 45, 255, 219, 133, 56, 255, 221, 150, 66,
+        255, 35, 28, 18, 255, 0, 68, 10, 9, 9, 85, 45, 34, 21, 255, 201,
+        110, 30, 255, 192, 100, 25, 255, 57, 35, 16, 255, 12, 10, 7, 85, 0,
+        24, 13, 11, 6, 79, 126, 68, 21, 255, 191, 100, 26, 255, 198, 117,
+        37, 255, 208, 139, 65, 255, 213, 155, 80, 255, 214, 161, 85, 255,
+        215, 167, 92, 255, 216, 167, 89, 255, 215, 160, 88, 255, 49, 38, 24,
+        170, 0, 24, 7, 7, 6, 76, 45, 36, 24, 249, 207, 164, 90, 255, 228,
+        183, 111, 255, 143, 111, 56, 255, 13, 12, 10, 170, 0, 28, 13, 12, 8,
+        142, 182, 99, 25, 255, 203, 108, 24, 255, 202, 102, 21, 255, 112,
+        65, 23, 255, 15, 13, 8, 227, 6, 6, 5, 45, 0, 16, 10, 8, 7, 170, 171,
+        89, 22, 255, 202, 95, 23, 255, 202, 103, 23, 255, 103, 64, 26, 255,
+        20, 18, 13, 255, 79, 61, 36, 255, 222, 173, 97, 255, 227, 179, 104,
+        255, 224, 172, 97, 255, 226, 171, 99, 255, 224, 176, 93, 255, 36,
+        29, 19, 207, 0, 8, 12, 10, 7, 113, 176, 91, 23, 255, 202, 95, 23,
+        255, 202, 102, 21, 255, 27, 20, 10, 255, 4, 4, 3, 74, 0, 4, 4, 4, 4,
+        28, 11, 9, 6, 215, 187, 101, 24, 255, 216, 134, 45, 255, 226, 172,
+        95, 255, 23, 21, 16, 241, 0, 8, 10, 10, 9, 161, 212, 160, 85, 255,
+        226, 172, 95, 255, 222, 158, 75, 255, 51, 39, 24, 255, 6, 6, 6, 85,
+        0, 4, 4, 4, 3, 28, 11, 10, 6, 215, 176, 91, 23, 255, 202, 102, 21,
+        255, 191, 102, 22, 255, 22, 17, 9, 170, 0, 8, 12, 10, 7, 85, 167,
+        87, 22, 255, 204, 105, 25, 255, 217, 133, 50, 255, 35, 28, 18, 255,
+        0, 40, 15, 13, 10, 170, 199, 116, 34, 255, 212, 114, 35, 255, 218,
+        139, 55, 255, 33, 27, 18, 255, 0, 12, 15, 13, 10, 170, 213, 160, 84,
+        255, 227, 175, 100, 255, 224, 165, 81, 255, 25, 21, 14, 235, 0, 8,
+        13, 11, 8, 108, 184, 96, 25, 255, 203, 96, 24, 255, 202, 95, 23,
+        255, 27, 20, 10, 255, 4, 4, 3, 71, 0, 28, 10, 9, 7, 170, 187, 101,
+        24, 255, 216, 134, 45, 255, 224, 167, 85, 255, 54, 42, 27, 255, 6,
+        6, 6, 85, 0, 28, 10, 9, 7, 170, 171, 89, 22, 255, 202, 103, 23, 255,
+        202, 102, 21, 255, 29, 21, 10, 170, 0, 4, 11, 9, 6, 42, 137, 77, 24,
+        255, 211, 136, 56, 255, 215, 167, 92, 255, 216, 166, 95, 255, 213,
+        163, 84, 255, 33, 28, 18, 161, 0, 8, 11, 10, 8, 130, 184, 100, 25,
+        255, 203, 100, 24, 255, 202, 102, 21, 255, 27, 20, 10, 255, 4, 4, 3,
+        74, 0, 4, 4, 4, 4, 28, 11, 9, 6, 215, 176, 91, 23, 255, 202, 103,
+        23, 255, 202, 95, 23, 255, 28, 21, 11, 190, 0, 8, 10, 10, 9, 161,
+        212, 161, 89, 255, 228, 174, 105, 255, 223, 161, 80, 255, 33, 28,
+        18, 255, 0, 40, 10, 9, 7, 167, 171, 89, 22, 255, 202, 103, 23, 255,
+        202, 102, 21, 255, 29, 21, 10, 170, 0, 8, 12, 10, 7, 85, 167, 87,
+        22, 255, 202, 103, 23, 255, 203, 108, 24, 255, 68, 47, 25, 255, 6,
+        6, 5, 255, 31, 26, 20, 255, 220, 168, 93, 255, 220, 177, 101, 255,
+        110, 80, 41, 255, 12, 11, 9, 150, 0, 16, 10, 9, 7, 170, 171, 89, 22,
+        255, 202, 103, 23, 255, 202, 102, 21, 255, 20, 16, 9, 255, 0, 32,
+        10, 9, 7, 170, 193, 111, 30, 255, 219, 136, 54, 255, 224, 165, 81,
+        255, 27, 24, 16, 255, 0, 4, 7, 7, 7, 28, 21, 20, 16, 181, 10, 10, 9,
+        85, 0, 4, 12, 11, 9, 170, 204, 130, 51, 255, 218, 141, 51, 255, 211,
+        122, 36, 255, 32, 23, 13, 187, 0, 8, 13, 11, 8, 85, 167, 87, 22,
+        255, 203, 100, 24, 255, 208, 105, 29, 255, 23, 19, 12, 255, 4, 4, 3,
+        28, 11, 10, 8, 181, 211, 158, 82, 255, 229, 183, 110, 255, 228, 183,
+        111, 255, 228, 183, 113, 255, 228, 181, 107, 255, 27, 23, 16, 229,
+        0, 8, 10, 10, 9, 150, 192, 111, 31, 255, 208, 112, 27, 255, 203,
+        108, 24, 255, 21, 17, 10, 255, 0, 12, 15, 13, 10, 170, 216, 170, 97,
+        255, 229, 183, 110, 255, 228, 181, 107, 255, 25, 21, 16, 235, 0, 8,
+        11, 10, 8, 142, 194, 116, 33, 255, 209, 106, 30, 255, 203, 108, 24,
+        255, 27, 20, 10, 255, 4, 4, 3, 74, 0, 36, 10, 8, 7, 170, 171, 89,
+        22, 255, 202, 103, 23, 255, 202, 102, 21, 255, 42, 28, 13, 255, 6,
+        5, 5, 48, 0, 4, 6, 6, 6, 28, 21, 19, 14, 255, 221, 175, 102, 255,
+        229, 179, 114, 255, 228, 181, 107, 255, 24, 20, 15, 246, 0, 8, 12,
+        11, 9, 127, 190, 104, 27, 255, 206, 106, 25, 255, 202, 103, 23, 255,
+        27, 20, 10, 255, 4, 4, 3, 74, 0, 4, 4, 4, 4, 28, 11, 10, 6, 215,
+        176, 91, 23, 255, 204, 105, 25, 255, 207, 122, 38, 255, 28, 22, 15,
+        238, 0, 36, 5, 5, 5, 28, 15, 13, 10, 227, 195, 111, 28, 255, 204,
+        105, 25, 255, 197, 100, 22, 255, 22, 17, 9, 224, 0, 24, 15, 13, 10,
+        170, 216, 170, 97, 255, 229, 184, 114, 255, 228, 181, 107, 255, 34,
+        28, 19, 255, 0, 24, 10, 9, 7, 170, 174, 91, 23, 255, 202, 103, 23,
+        255, 202, 102, 21, 255, 20, 16, 9, 252, 0, 12, 10, 9, 7, 170, 171,
+        89, 22, 255, 202, 107, 23, 255, 206, 111, 27, 255, 22, 17, 11, 252,
+        0, 8, 8, 7, 7, 45, 73, 59, 36, 255, 218, 174, 105, 255, 228, 178,
+        107, 255, 89, 67, 36, 255, 7, 7, 6, 113, 0, 4, 5, 5, 4, 28, 20, 18,
+        13, 255, 199, 110, 30, 255, 202, 105, 27, 255, 88, 54, 23, 255, 10,
+        9, 7, 113, 0, 8, 13, 11, 6, 85, 167, 87, 22, 255, 202, 95, 23, 255,
+        202, 90, 23, 255, 32, 24, 13, 255, 4, 4, 3, 178, 19, 16, 12, 238,
+        212, 163, 93, 255, 66, 52, 31, 255, 5, 5, 5, 184, 14, 13, 11, 255,
+        205, 133, 48, 255, 212, 114, 35, 255, 208, 117, 29, 255, 29, 22, 14,
+        255, 0, 16, 12, 11, 9, 85, 101, 74, 38, 255, 189, 121, 49, 255, 185,
+        104, 32, 255, 180, 98, 25, 255, 180, 93, 23, 255, 154, 82, 23, 255,
+        75, 44, 18, 255, 11, 9, 6, 144, 0, 32, 10, 9, 7, 170, 157, 79, 22,
+        255, 202, 102, 21, 255, 202, 102, 21, 255, 22, 17, 9, 255, 0, 28,
+        14, 13, 11, 224, 136, 98, 53, 255, 217, 165, 82, 255, 213, 145, 56,
+        255, 150, 92, 35, 255, 19, 16, 12, 173, 5, 5, 5, 8, 0, 28, 10, 8, 7,
+        170, 171, 89, 22, 255, 202, 103, 23, 255, 202, 102, 21, 255, 20, 16,
+        9, 252, 0, 28, 7, 7, 6, 59, 43, 35, 24, 255, 221, 175, 102, 255,
+        223, 178, 106, 255, 134, 98, 51, 255, 14, 13, 11, 142, 0, 24, 10, 9,
+        7, 167, 171, 89, 22, 255, 202, 103, 23, 255, 202, 102, 21, 255, 20,
+        16, 9, 255, 0, 144, 12, 10, 7, 170, 46, 29, 13, 255, 140, 74, 21,
+        255, 165, 86, 22, 255, 167, 87, 22, 255, 165, 86, 22, 255, 167, 87,
+        22, 255, 185, 95, 22, 255, 198, 97, 23, 255, 206, 111, 27, 255, 221,
+        146, 66, 255, 23, 19, 14, 249, 0, 8, 10, 10, 9, 153, 212, 161, 89,
+        255, 229, 183, 110, 255, 224, 165, 81, 255, 28, 23, 15, 255, 0, 12,
+        10, 8, 7, 156, 171, 89, 22, 255, 202, 103, 23, 255, 202, 102, 21,
+        255, 31, 21, 10, 170, 0, 8, 10, 10, 9, 167, 212, 160, 85, 255, 228,
+        177, 105, 255, 222, 158, 75, 255, 27, 23, 16, 255, 0, 40, 10, 8, 7,
+        170, 167, 87, 22, 255, 202, 103, 23, 255, 202, 102, 21, 255, 20, 16,
+        9, 238, 0, 12, 10, 8, 7, 164, 171, 89, 22, 255, 202, 103, 23, 255,
+        203, 100, 24, 255, 22, 18, 11, 235, 0, 8, 10, 10, 9, 167, 214, 164,
+        93, 255, 228, 182, 109, 255, 223, 154, 80, 255, 207, 120, 36, 255,
+        189, 94, 24, 255, 167, 87, 22, 255, 167, 87, 22, 255, 187, 96, 22,
+        255, 198, 93, 23, 255, 202, 93, 21, 255, 198, 96, 21, 255, 26, 19,
+        9, 227, 0, 16, 10, 8, 7, 167, 171, 89, 22, 255, 202, 103, 23, 255,
+        202, 102, 21, 255, 20, 15, 9, 252, 0, 16, 17, 15, 12, 170, 216, 170,
+        97, 255, 229, 183, 110, 255, 224, 164, 85, 255, 29, 24, 16, 255, 3,
+        3, 2, 28, 0, 8, 12, 11, 9, 198, 211, 149, 76, 255, 221, 151, 68,
+        255, 219, 146, 60, 255, 22, 19, 13, 246, 0, 8, 10, 10, 9, 161, 210,
+        155, 77, 255, 223, 147, 72, 255, 213, 122, 42, 255, 23, 18, 12, 255,
+        0, 12, 10, 8, 7, 167, 171, 89, 22, 255, 202, 103, 23, 255, 202, 102,
+        21, 255, 29, 21, 10, 170, 0, 8, 12, 10, 7, 85, 166, 87, 23, 255,
+        209, 118, 30, 255, 218, 139, 55, 255, 33, 27, 18, 255, 0, 24, 15,
+        13, 10, 170, 215, 159, 92, 255, 226, 169, 95, 255, 218, 141, 59,
+        255, 34, 26, 15, 190, 0, 8, 13, 10, 6, 85, 167, 87, 22, 255, 202,
+        103, 23, 255, 198, 96, 21, 255, 197, 96, 22, 255, 189, 97, 22, 255,
+        198, 96, 21, 255, 198, 96, 21, 255, 25, 19, 10, 255, 4, 4, 3, 28, 0,
+        20, 10, 9, 7, 170, 178, 92, 23, 255, 210, 107, 31, 255, 215, 128,
+        44, 255, 33, 24, 14, 193, 0, 8, 12, 10, 7, 85, 167, 87, 22, 255,
+        202, 95, 23, 255, 202, 103, 23, 255, 32, 22, 11, 170, 0, 4, 10, 8,
+        7, 170, 171, 89, 22, 255, 24, 17, 9, 249, 0, 4, 12, 10, 7, 85, 163,
+        82, 22, 255, 202, 103, 23, 255, 202, 102, 21, 255, 29, 21, 10, 170,
+        0, 8, 12, 10, 7, 85, 166, 87, 23, 255, 202, 103, 23, 255, 202, 102,
+        21, 255, 20, 15, 9, 255, 0, 12, 10, 8, 7, 167, 170, 89, 23, 255,
+        206, 106, 25, 255, 208, 115, 33, 255, 28, 21, 13, 207, 0, 8, 13, 10,
+        6, 85, 167, 87, 22, 255, 202, 95, 23, 255, 202, 102, 21, 255, 20,
+        16, 9, 255, 0, 12, 15, 13, 10, 170, 214, 158, 85, 255, 229, 183,
+        110, 255, 228, 185, 111, 255, 24, 20, 15, 249, 0, 8, 12, 11, 9, 108,
+        176, 91, 23, 255, 202, 95, 23, 255, 202, 102, 21, 255, 18, 15, 9,
+        255, 2, 2, 1, 8, 0, 8, 8, 7, 5, 184, 171, 89, 22, 255, 202, 95, 23,
+        255, 202, 102, 21, 255, 34, 23, 11, 173, 0, 8, 12, 11, 9, 136, 212,
+        160, 85, 255, 228, 180, 105, 255, 225, 165, 88, 255, 31, 25, 18,
+        255, 3, 3, 2, 28, 0, 8, 8, 7, 5, 178, 171, 89, 22, 255, 202, 103,
+        23, 255, 202, 102, 21, 255, 30, 21, 11, 170, 0, 8, 12, 10, 7, 85,
+        167, 87, 22, 255, 202, 103, 23, 255, 202, 102, 21, 255, 20, 15, 9,
+        255, 0, 40, 7, 7, 6, 28, 30, 27, 21, 238, 167, 111, 50, 255, 206,
+        110, 33, 255, 199, 102, 24, 255, 175, 90, 22, 255, 165, 86, 22, 255,
+        167, 87, 22, 255, 167, 87, 22, 255, 161, 87, 22, 255, 84, 48, 19,
+        255, 18, 15, 9, 227, 8, 7, 5, 28, 0, 16, 10, 8, 7, 167, 171, 89, 22,
+        255, 202, 103, 23, 255, 202, 102, 21, 255, 20, 15, 9, 252, 0, 16,
+        15, 13, 10, 170, 211, 159, 76, 255, 229, 180, 110, 255, 228, 182,
+        109, 255, 34, 28, 19, 255, 0, 12, 10, 9, 7, 170, 171, 89, 22, 255,
+        202, 103, 23, 255, 202, 102, 21, 255, 31, 22, 10, 170, 0, 8, 7, 6,
+        6, 28, 48, 31, 15, 255, 189, 93, 22, 255, 202, 102, 21, 255, 45, 29,
+        14, 255, 5, 5, 4, 113, 0, 4, 5, 5, 4, 28, 22, 20, 15, 255, 220, 169,
+        97, 255, 226, 178, 103, 255, 167, 118, 54, 255, 15, 13, 10, 133, 0,
+        8, 13, 11, 6, 85, 167, 87, 22, 255, 202, 103, 23, 255, 202, 102, 21,
+        255, 19, 15, 8, 215, 0, 4, 11, 9, 6, 105, 121, 65, 20, 255, 26, 18,
+        9, 190, 0, 4, 9, 9, 8, 167, 208, 150, 75, 255, 229, 183, 110, 255,
+        228, 181, 113, 255, 37, 29, 20, 255, 0, 24, 8, 8, 5, 218, 167, 87,
+        22, 255, 202, 93, 21, 255, 198, 104, 21, 255, 23, 18, 10, 255, 3, 3,
+        2, 51, 0, 20, 10, 9, 7, 153, 171, 89, 22, 255, 202, 95, 23, 255,
+        202, 102, 21, 255, 20, 15, 9, 255, 2, 2, 1, 17, 0, 8, 8, 7, 5, 181,
+        184, 100, 25, 255, 215, 119, 42, 255, 224, 160, 85, 255, 34, 28, 19,
+        255, 0, 20, 9, 8, 6, 85, 31, 22, 12, 255, 166, 87, 23, 255, 189, 97,
+        22, 255, 99, 60, 22, 255, 15, 13, 8, 170, 0, 28, 4, 3, 3, 23, 13,
+        11, 8, 227, 182, 94, 23, 255, 149, 87, 26, 255, 19, 17, 12, 227, 7,
+        7, 7, 23, 0, 16, 15, 13, 10, 170, 216, 170, 97, 255, 229, 179, 114,
+        255, 228, 182, 109, 255, 34, 28, 19, 255, 0, 20, 9, 8, 6, 130, 69,
+        42, 18, 255, 195, 95, 22, 255, 35, 24, 12, 255, 5, 5, 4, 76, 0, 104,
+        10, 9, 7, 28, 27, 24, 16, 184, 32, 27, 19, 255, 39, 29, 20, 212, 13,
+        12, 10, 85, 0, 60, 13, 11, 8, 170, 81, 54, 28, 255, 216, 148, 67,
+        255, 223, 161, 72, 255, 220, 147, 61, 255, 117, 76, 32, 255, 13, 11,
+        8, 255, 44, 33, 19, 255, 207, 123, 40, 255, 217, 136, 50, 255, 218,
+        142, 53, 255, 156, 100, 39, 255, 18, 15, 11, 227, 10, 8, 7, 28, 0,
+        12, 15, 13, 8, 125, 19, 14, 10, 170, 14, 11, 7, 170, 10, 8, 7, 170,
+        11, 9, 6, 122, 13, 10, 8, 85, 8, 7, 5, 153, 46, 33, 21, 255, 212,
+        138, 51, 255, 221, 151, 68, 255, 191, 132, 62, 255, 19, 17, 12, 176,
+        0, 12, 7, 7, 6, 76, 26, 22, 15, 241, 189, 129, 58, 255, 219, 152,
+        72, 255, 217, 154, 72, 255, 133, 87, 38, 255, 15, 13, 10, 221, 6, 6,
+        5, 28, 0, 8, 15, 12, 8, 113, 20, 16, 11, 170, 17, 14, 10, 142, 7, 6,
+        6, 28, 0, 8, 19, 16, 12, 170, 200, 117, 35, 255, 212, 123, 37, 255,
+        115, 74, 30, 255, 9, 8, 6, 113, 0, 8, 12, 11, 9, 178, 104, 73, 37,
+        255, 206, 147, 63, 255, 178, 121, 53, 255, 58, 46, 29, 255, 46, 36,
+        25, 255, 40, 32, 21, 252, 19, 17, 12, 85, 0, 36, 12, 10, 9, 164,
+        191, 131, 60, 255, 223, 161, 80, 255, 221, 151, 68, 255, 46, 34, 21,
+        255, 4, 4, 3, 3, 0, 20, 19, 16, 12, 173, 208, 134, 55, 255, 223,
+        156, 70, 255, 216, 160, 81, 255, 21, 19, 14, 255, 0, 16, 6, 5, 5,
+        25, 17, 14, 10, 227, 67, 48, 28, 255, 94, 67, 35, 255, 20, 17, 13,
+        227, 6, 6, 5, 113, 12, 11, 9, 198, 67, 51, 30, 255, 85, 62, 32, 255,
+        25, 20, 14, 255, 9, 8, 6, 82, 0, 32, 10, 8, 5, 170, 161, 87, 22,
+        255, 195, 90, 20, 255, 187, 91, 20, 255, 19, 14, 8, 255, 0, 28, 15,
+        12, 8, 119, 20, 16, 11, 170, 17, 14, 10, 156, 10, 8, 7, 28, 0, 64,
+        15, 12, 8, 122, 18, 15, 11, 170, 17, 14, 10, 144, 10, 8, 7, 28, 0,
+        16, 13, 12, 10, 170, 157, 96, 36, 255, 211, 123, 38, 255, 199, 116,
+        34, 255, 31, 24, 16, 255, 6, 6, 6, 28, 0, 20, 16, 13, 11, 170, 197,
+        110, 32, 255, 209, 110, 30, 255, 202, 103, 23, 255, 58, 36, 15, 255,
+        8, 7, 5, 113, 0, 8, 10, 8, 5, 85, 137, 68, 18, 255, 185, 86, 20,
+        255, 174, 88, 19, 255, 18, 13, 7, 255, 0, 24, 12, 10, 9, 170, 204,
+        129, 49, 255, 220, 144, 63, 255, 217, 133, 50, 255, 26, 20, 13, 255,
+        0, 28, 7, 6, 6, 76, 23, 19, 12, 244, 185, 113, 36, 255, 207, 129,
+        52, 255, 173, 117, 50, 255, 59, 46, 28, 255, 18, 15, 13, 198, 9, 9,
+        8, 113, 6, 6, 6, 11, 0, 24, 15, 12, 8, 133, 22, 17, 11, 170, 17, 14,
+        10, 142, 8, 7, 5, 28, 0, 12, 9, 8, 6, 170, 202, 128, 49, 255, 220,
+        148, 63, 255, 219, 140, 56, 255, 22, 19, 13, 255, 0, 8, 12, 10, 9,
+        170, 200, 125, 37, 255, 218, 141, 51, 255, 220, 147, 61, 255, 138,
+        86, 35, 255, 13, 10, 8, 227, 11, 9, 6, 170, 13, 11, 8, 198, 61, 41,
+        22, 255, 202, 111, 31, 255, 204, 105, 25, 255, 200, 105, 21, 255,
+        22, 17, 9, 221, 0, 12, 11, 9, 6, 108, 14, 11, 7, 170, 11, 9, 6, 139,
+        6, 5, 3, 17, 0, 12, 9, 7, 6, 133, 144, 75, 19, 255, 185, 86, 20,
+        255, 178, 86, 19, 255, 27, 18, 8, 170, 0, 8, 11, 9, 6, 85, 134, 70,
+        19, 255, 181, 88, 20, 255, 180, 87, 19, 255, 24, 15, 7, 178, 0, 12,
+        10, 8, 5, 99, 165, 86, 22, 255, 206, 111, 27, 255, 213, 124, 38,
+        255, 36, 27, 17, 255, 0, 24, 10, 10, 9, 133, 167, 112, 48, 255, 222,
+        166, 77, 255, 223, 157, 72, 255, 54, 39, 23, 255, 5, 5, 4, 37, 0,
+        20, 13, 11, 8, 170, 181, 93, 22, 255, 206, 111, 27, 255, 214, 127,
+        43, 255, 20, 16, 11, 255, 0, 12, 9, 8, 8, 170, 203, 129, 50, 255,
+        222, 145, 63, 255, 220, 147, 61, 255, 33, 26, 16, 255, 0, 12, 12,
+        10, 7, 113, 15, 12, 8, 170, 13, 10, 8, 122, 0, 16, 10, 8, 7, 170,
+        200, 120, 41, 255, 220, 142, 59, 255, 219, 146, 60, 255, 27, 21, 14,
+        255, 0, 12, 13, 11, 8, 113, 18, 15, 11, 170, 17, 14, 10, 142, 8, 7,
+        5, 28, 0, 12, 14, 12, 9, 113, 20, 15, 11, 170, 17, 14, 10, 153, 10,
+        8, 7, 28, 0, 16, 9, 8, 6, 85, 29, 21, 10, 255, 119, 62, 20, 255,
+        153, 79, 20, 255, 40, 25, 11, 255, 9, 8, 6, 85, 0, 20, 10, 8, 7, 28,
+        32, 24, 13, 218, 68, 47, 25, 255, 61, 43, 24, 255, 61, 46, 28, 255,
+        61, 47, 28, 255, 61, 47, 28, 255, 66, 50, 29, 255, 73, 55, 32, 255,
+        66, 48, 29, 255, 24, 20, 15, 85, 0, 20, 7, 6, 6, 79, 32, 26, 17,
+        244, 199, 132, 54, 255, 208, 150, 75, 255, 122, 87, 41, 255, 17, 15,
+        10, 170, 0, 32, 10, 9, 7, 28, 32, 23, 11, 227, 53, 33, 14, 255, 34,
+        23, 11, 255, 12, 10, 7, 190, 6, 5, 5, 28, 0, 20, 9, 7, 4, 170, 146,
+        76, 19, 255, 197, 99, 20, 255, 204, 110, 27, 255, 59, 41, 22, 255,
+        6, 6, 6, 170, 10, 9, 9, 113, 31, 26, 18, 184, 30, 25, 17, 255, 29,
+        25, 18, 255, 34, 27, 19, 255, 37, 28, 18, 221, 13, 11, 8, 57, 0, 8,
+        13, 10, 6, 88, 144, 75, 19, 255, 185, 86, 20, 255, 178, 90, 19, 255,
+        20, 14, 7, 212, 0, 12, 9, 7, 4, 125, 157, 81, 20, 255, 212, 117, 33,
+        255, 220, 148, 63, 255, 27, 21, 14, 218, 0, 8, 12, 10, 9, 127, 192,
+        111, 31, 255, 208, 112, 27, 255, 202, 103, 23, 255, 22, 16, 9, 204,
+        0, 12, 10, 8, 5, 93, 137, 68, 18, 255, 185, 94, 20, 255, 180, 91,
+        19, 255, 30, 20, 9, 170, 0, 8, 11, 9, 6, 85, 140, 67, 19, 255, 202,
+        106, 21, 255, 214, 125, 39, 255, 25, 20, 14, 255, 0, 12, 6, 6, 5,
+        28, 13, 11, 8, 139, 20, 16, 11, 170, 19, 15, 10, 142, 8, 7, 5, 28,
+        0, 8, 10, 9, 5, 142, 153, 79, 20, 255, 195, 90, 20, 255, 206, 111,
+        27, 255, 24, 20, 13, 255, 0, 12, 12, 10, 9, 170, 195, 113, 32, 255,
+        211, 115, 30, 255, 203, 108, 24, 255, 31, 21, 10, 173, 0, 8, 11, 9,
+        6, 85, 140, 70, 19, 255, 185, 86, 20, 255, 180, 87, 19, 255, 24, 15,
+        7, 181, 0, 32, 9, 8, 6, 170, 174, 91, 23, 255, 215, 123, 42, 255,
+        221, 150, 66, 255, 25, 20, 14, 255, 0, 32, 9, 7, 4, 170, 148, 77,
+        19, 255, 181, 92, 20, 255, 180, 87, 19, 255, 25, 17, 8, 170, 0, 8,
+        34, 24, 13, 170, 161, 102, 38, 255, 219, 154, 70, 255, 220, 142, 59,
+        255, 213, 124, 38, 255, 32, 24, 13, 198, 0, 8, 11, 9, 6, 85, 140,
+        70, 19, 255, 185, 86, 20, 255, 178, 90, 19, 255, 20, 14, 7, 212, 0,
+        12, 8, 7, 5, 127, 144, 78, 19, 255, 185, 86, 20, 255, 180, 87, 19,
+        255, 29, 19, 10, 170, 0, 8, 13, 11, 8, 116, 194, 116, 33, 255, 209,
+        110, 30, 255, 202, 95, 23, 255, 22, 17, 9, 221, 0, 12, 10, 8, 5, 85,
+        12, 9, 5, 170, 10, 8, 5, 130, 6, 5, 3, 8, 0, 12, 10, 8, 5, 110, 144,
+        78, 19, 255, 185, 86, 20, 255, 178, 86, 19, 255, 27, 18, 8, 170, 0,
+        8, 11, 8, 6, 85, 137, 68, 18, 255, 185, 86, 20, 255, 200, 105, 21,
+        255, 29, 21, 12, 255, 4, 4, 4, 25, 10, 9, 7, 139, 154, 100, 47, 255,
+        215, 148, 70, 255, 198, 131, 45, 255, 46, 34, 19, 255, 11, 9, 6, 88,
+        0, 12, 10, 8, 5, 119, 144, 78, 19, 255, 185, 86, 20, 255, 180, 87,
+        19, 255, 21, 15, 8, 210, 0, 32, 13, 11, 8, 170, 199, 119, 39, 255,
+        220, 144, 63, 255, 221, 155, 70, 255, 27, 21, 14, 255, 0, 20, 10, 9,
+        7, 170, 171, 89, 22, 255, 195, 98, 20, 255, 183, 89, 19, 255, 29,
+        20, 8, 170, 0, 8, 11, 9, 6, 85, 139, 70, 20, 255, 202, 103, 23, 255,
+        211, 118, 36, 255, 28, 21, 13, 201, 0, 4, 8, 8, 7, 57, 118, 84, 39,
+        255, 215, 159, 86, 255, 219, 149, 66, 255, 216, 129, 45, 255, 211,
+        121, 34, 255, 34, 25, 13, 178, 0, 8, 11, 10, 6, 88, 146, 76, 19,
+        255, 185, 94, 20, 255, 178, 90, 19, 255, 24, 18, 9, 255, 0, 12, 18,
+        15, 11, 170, 203, 122, 42, 255, 215, 126, 40, 255, 209, 106, 30,
+        255, 32, 22, 13, 184, 0, 8, 12, 10, 7, 85, 143, 72, 20, 255, 185,
+        94, 20, 255, 178, 90, 19, 255, 20, 14, 7, 210, 0, 40, 9, 7, 4, 170,
+        148, 77, 19, 255, 180, 87, 19, 255, 178, 86, 19, 255, 30, 21, 9,
+        255, 5, 5, 4, 37, 8, 7, 5, 28, 20, 17, 13, 227, 133, 89, 38, 255,
+        215, 142, 56, 255, 216, 129, 45, 255, 209, 115, 32, 255, 26, 19, 11,
+        210, 0, 8, 11, 9, 6, 85, 142, 74, 19, 255, 185, 86, 20, 255, 178,
+        90, 19, 255, 20, 14, 7, 210, 0, 12, 9, 7, 4, 122, 143, 75, 20, 255,
+        203, 108, 24, 255, 216, 129, 45, 255, 30, 23, 15, 255, 0, 12, 12,
+        10, 7, 110, 16, 13, 9, 170, 13, 10, 8, 122, 0, 16, 9, 8, 6, 105,
+        142, 74, 19, 255, 185, 86, 20, 255, 180, 87, 19, 255, 23, 16, 8,
+        255, 0, 24, 15, 13, 10, 170, 203, 122, 42, 255, 215, 126, 40, 255,
+        209, 118, 30, 255, 24, 17, 11, 255, 0, 24, 9, 8, 4, 170, 148, 77,
+        19, 255, 181, 92, 20, 255, 180, 87, 19, 255, 23, 16, 8, 198, 0, 12,
+        9, 7, 6, 139, 159, 82, 20, 255, 203, 100, 24, 255, 212, 121, 33,
+        255, 28, 21, 13, 255, 0, 12, 12, 11, 9, 119, 81, 59, 34, 255, 216,
+        153, 71, 255, 173, 117, 50, 255, 21, 18, 14, 255, 10, 10, 9, 244,
+        11, 10, 8, 255, 60, 35, 15, 255, 173, 85, 20, 255, 84, 49, 17, 255,
+        13, 10, 6, 170, 0, 12, 10, 8, 5, 130, 146, 79, 19, 255, 193, 89, 20,
+        255, 203, 104, 24, 255, 120, 77, 31, 255, 19, 17, 12, 255, 117, 80,
+        36, 255, 219, 154, 70, 255, 178, 121, 53, 255, 20, 17, 13, 255, 45,
+        33, 18, 255, 184, 94, 21, 255, 195, 90, 20, 255, 205, 106, 26, 255,
+        30, 22, 13, 255, 0, 12, 7, 7, 6, 82, 35, 28, 18, 255, 196, 114, 33,
+        255, 148, 80, 25, 255, 32, 22, 11, 255, 20, 15, 9, 255, 26, 18, 9,
+        255, 88, 49, 17, 255, 149, 78, 20, 255, 40, 26, 11, 255, 9, 7, 4,
+        85, 0, 28, 9, 7, 4, 127, 140, 70, 19, 255, 181, 88, 20, 255, 180,
+        87, 19, 255, 18, 13, 7, 235, 0, 24, 10, 9, 7, 93, 104, 69, 35, 255,
+        201, 131, 48, 255, 194, 109, 33, 255, 65, 42, 20, 255, 12, 10, 7,
+        170, 0, 36, 9, 7, 4, 170, 146, 79, 19, 255, 181, 88, 20, 255, 180,
+        87, 19, 255, 23, 16, 8, 198, 0, 32, 15, 14, 10, 198, 188, 133, 61,
+        255, 219, 149, 66, 255, 194, 115, 37, 255, 17, 15, 10, 244, 0, 24,
+        10, 8, 5, 113, 144, 78, 19, 255, 185, 86, 20, 255, 180, 87, 19, 255,
+        18, 13, 7, 255, 0, 140, 7, 6, 4, 65, 53, 31, 12, 255, 162, 83, 19,
+        255, 185, 94, 20, 255, 130, 70, 21, 255, 31, 22, 10, 255, 25, 19,
+        10, 198, 22, 17, 9, 246, 70, 40, 15, 255, 169, 87, 20, 255, 200,
+        105, 21, 255, 212, 123, 37, 255, 28, 21, 13, 221, 0, 8, 12, 10, 9,
+        133, 200, 127, 41, 255, 210, 120, 33, 255, 202, 95, 23, 255, 19, 14,
+        8, 238, 0, 12, 10, 8, 5, 110, 144, 78, 19, 255, 185, 86, 20, 255,
+        178, 86, 19, 255, 28, 19, 9, 170, 0, 8, 12, 10, 9, 133, 194, 112,
+        31, 255, 209, 110, 30, 255, 202, 102, 21, 255, 21, 15, 8, 235, 0,
+        16, 9, 7, 4, 57, 12, 10, 5, 88, 10, 8, 5, 85, 0, 12, 10, 8, 5, 125,
+        146, 79, 19, 255, 181, 88, 20, 255, 180, 87, 19, 255, 25, 17, 8,
+        195, 0, 12, 10, 8, 5, 119, 144, 78, 19, 255, 185, 94, 20, 255, 200,
+        105, 21, 255, 23, 18, 10, 221, 0, 8, 11, 9, 8, 153, 200, 123, 41,
+        255, 212, 117, 33, 255, 202, 103, 23, 255, 111, 63, 20, 255, 27, 20,
+        10, 255, 20, 16, 9, 246, 22, 17, 9, 249, 28, 20, 9, 198, 30, 21, 9,
+        170, 24, 17, 9, 215, 28, 20, 9, 201, 10, 8, 5, 85, 0, 16, 9, 7, 4,
+        170, 146, 79, 19, 255, 181, 88, 20, 255, 180, 87, 19, 255, 18, 13,
+        7, 255, 0, 16, 11, 10, 8, 113, 152, 104, 47, 255, 214, 134, 49, 255,
+        204, 105, 25, 255, 98, 54, 19, 255, 18, 13, 9, 227, 13, 10, 8, 170,
+        14, 12, 9, 198, 60, 41, 21, 255, 199, 112, 28, 255, 202, 102, 21,
+        255, 202, 103, 23, 255, 26, 19, 11, 204, 0, 8, 12, 11, 9, 116, 187,
+        101, 24, 255, 202, 93, 21, 255, 187, 91, 20, 255, 18, 13, 7, 255, 0,
+        12, 9, 7, 4, 170, 146, 79, 19, 255, 181, 88, 20, 255, 178, 90, 19,
+        255, 27, 17, 8, 170, 0, 8, 11, 9, 6, 85, 139, 70, 20, 255, 202, 103,
+        23, 255, 212, 123, 37, 255, 32, 24, 15, 255, 0, 24, 13, 12, 10, 170,
+        196, 114, 33, 255, 206, 106, 25, 255, 196, 99, 21, 255, 28, 19, 9,
+        170, 0, 8, 11, 8, 6, 85, 137, 68, 18, 255, 181, 88, 20, 255, 178,
+        86, 19, 255, 164, 85, 21, 255, 138, 73, 21, 255, 175, 93, 20, 255,
+        178, 86, 19, 255, 46, 28, 11, 255, 6, 5, 3, 108, 0, 20, 9, 7, 4,
+        170, 146, 76, 19, 255, 189, 88, 20, 255, 189, 88, 20, 255, 28, 19,
+        9, 170, 0, 8, 11, 9, 6, 85, 137, 68, 18, 255, 185, 86, 20, 255, 178,
+        90, 19, 255, 27, 17, 8, 170, 0, 4, 9, 7, 4, 167, 146, 79, 19, 255,
+        20, 14, 7, 252, 0, 4, 11, 9, 6, 85, 137, 68, 18, 255, 185, 94, 20,
+        255, 178, 90, 19, 255, 27, 17, 8, 170, 0, 8, 11, 9, 6, 85, 137, 68,
+        18, 255, 185, 86, 20, 255, 180, 87, 19, 255, 18, 13, 7, 255, 0, 12,
+        9, 7, 4, 170, 146, 79, 19, 255, 185, 94, 20, 255, 183, 85, 19, 255,
+        27, 19, 8, 170, 0, 8, 11, 9, 6, 85, 140, 73, 19, 255, 181, 88, 20,
+        255, 178, 90, 19, 255, 20, 15, 7, 255, 0, 12, 16, 14, 11, 170, 208,
+        143, 59, 255, 223, 156, 70, 255, 216, 135, 49, 255, 28, 22, 13, 210,
+        0, 8, 11, 9, 6, 85, 140, 70, 19, 255, 185, 94, 20, 255, 178, 90, 19,
+        255, 72, 39, 13, 255, 10, 8, 5, 218, 8, 6, 3, 170, 9, 7, 4, 193, 39,
+        24, 10, 255, 160, 82, 19, 255, 185, 94, 20, 255, 144, 74, 23, 255,
+        16, 13, 9, 170, 0, 8, 10, 9, 7, 85, 145, 101, 48, 255, 218, 149, 67,
+        255, 210, 115, 31, 255, 99, 57, 19, 255, 10, 8, 5, 227, 8, 6, 3,
+        170, 9, 7, 4, 190, 30, 20, 9, 255, 158, 81, 19, 255, 185, 94, 20,
+        255, 178, 90, 19, 255, 27, 17, 8, 170, 0, 8, 11, 8, 6, 85, 137, 68,
+        18, 255, 185, 86, 20, 255, 180, 87, 19, 255, 18, 13, 7, 255, 0, 44,
+        9, 9, 8, 28, 13, 12, 8, 142, 27, 20, 10, 170, 29, 21, 10, 193, 24,
+        17, 9, 252, 22, 17, 9, 232, 22, 17, 9, 255, 87, 49, 18, 255, 181,
+        88, 20, 255, 178, 90, 19, 255, 100, 54, 17, 255, 11, 10, 6, 150, 0,
+        16, 9, 7, 4, 170, 146, 79, 19, 255, 181, 88, 20, 255, 180, 87, 19,
+        255, 18, 13, 7, 255, 0, 16, 15, 13, 10, 170, 208, 141, 55, 255, 223,
+        156, 70, 255, 217, 133, 50, 255, 23, 19, 12, 255, 0, 12, 10, 8, 5,
+        122, 144, 78, 19, 255, 185, 86, 20, 255, 180, 87, 19, 255, 30, 20,
+        9, 176, 0, 12, 12, 10, 7, 85, 39, 26, 12, 255, 155, 80, 20, 255, 99,
+        55, 19, 255, 19, 16, 12, 255, 12, 11, 9, 255, 18, 15, 11, 255, 119,
+        84, 38, 255, 209, 137, 60, 255, 138, 86, 35, 255, 18, 15, 11, 178,
+        0, 12, 10, 8, 5, 130, 144, 78, 19, 255, 181, 92, 20, 255, 178, 90,
+        19, 255, 39, 24, 10, 255, 6, 5, 3, 210, 29, 20, 8, 255, 169, 87, 20,
+        255, 97, 53, 18, 255, 8, 7, 5, 255, 26, 21, 15, 255, 212, 142, 59,
+        255, 221, 151, 68, 255, 218, 142, 53, 255, 34, 25, 15, 255, 0, 20,
+        5, 5, 4, 82, 16, 12, 7, 255, 160, 82, 19, 255, 185, 86, 20, 255,
+        185, 86, 20, 255, 52, 29, 11, 255, 7, 6, 4, 170, 0, 20, 8, 7, 5, 85,
+        83, 46, 16, 255, 181, 92, 20, 255, 178, 86, 19, 255, 87, 47, 14,
+        255, 10, 8, 5, 224, 8, 6, 3, 170, 9, 7, 4, 190, 29, 20, 8, 255, 195,
+        104, 24, 255, 217, 136, 50, 255, 221, 155, 70, 255, 30, 23, 15, 255,
+        0, 16, 8, 7, 5, 85, 26, 18, 9, 255, 107, 59, 20, 255, 151, 80, 22,
+        255, 60, 34, 15, 255, 11, 9, 6, 170, 0, 36, 8, 7, 5, 170, 159, 82,
+        20, 255, 202, 118, 35, 255, 66, 51, 29, 255, 9, 9, 8, 96, 0, 16, 15,
+        13, 10, 170, 208, 140, 59, 255, 223, 156, 70, 255, 215, 133, 44,
+        255, 27, 20, 12, 255, 0, 20, 14, 12, 7, 244, 131, 67, 20, 255, 176,
+        89, 19, 255, 17, 12, 6, 255, 0, 184, 17, 14, 10, 85, 171, 95, 28,
+        255, 206, 123, 33, 255, 208, 123, 31, 255, 207, 112, 28, 255, 202,
+        107, 23, 255, 191, 98, 22, 255, 170, 91, 21, 255, 195, 107, 22, 255,
+        209, 123, 30, 255, 212, 132, 37, 255, 214, 134, 39, 255, 211, 133,
+        40, 255, 202, 121, 35, 255, 29, 21, 12, 164, 0, 8, 12, 10, 7, 82,
+        168, 98, 29, 255, 202, 121, 35, 255, 196, 120, 31, 255, 194, 115,
+        31, 255, 190, 115, 27, 255, 185, 101, 26, 255, 184, 100, 25, 255,
+        199, 107, 26, 255, 208, 123, 31, 255, 168, 105, 37, 255, 25, 21, 14,
+        227, 9, 8, 8, 28, 0, 8, 8, 8, 7, 28, 39, 30, 18, 249, 183, 122, 42,
+        255, 211, 133, 40, 255, 210, 133, 43, 255, 161, 106, 41, 255, 15,
+        13, 10, 221, 5, 4, 4, 17, 0, 8, 14, 11, 7, 113, 148, 83, 25, 255,
+        193, 108, 24, 255, 180, 93, 23, 255, 27, 18, 10, 153, 0, 8, 12, 9,
+        7, 122, 144, 78, 19, 255, 180, 91, 19, 255, 83, 46, 16, 255, 7, 6,
+        4, 184, 0, 8, 4, 4, 3, 85, 28, 21, 13, 255, 202, 121, 35, 255, 209,
+        132, 42, 255, 131, 87, 36, 255, 10, 9, 7, 255, 5, 5, 5, 28, 0, 40,
+        10, 9, 7, 68, 86, 62, 31, 255, 206, 131, 43, 255, 214, 130, 39, 255,
+        76, 50, 25, 255, 7, 6, 6, 113, 0, 16, 5, 5, 4, 28, 21, 17, 12, 255,
+        202, 121, 35, 255, 210, 135, 37, 255, 157, 100, 38, 255, 18, 15, 11,
+        150, 0, 16, 18, 15, 9, 91, 161, 88, 24, 255, 105, 64, 28, 255, 11,
+        10, 8, 170, 0, 12, 8, 7, 7, 85, 40, 28, 17, 255, 174, 91, 23, 255,
+        42, 27, 13, 173, 0, 32, 10, 8, 5, 116, 133, 66, 16, 255, 161, 85,
+        17, 255, 161, 78, 17, 255, 25, 16, 8, 221, 0, 24, 15, 12, 8, 119,
+        170, 99, 29, 255, 203, 126, 36, 255, 199, 127, 34, 255, 27, 20, 12,
+        210, 0, 60, 13, 11, 8, 122, 170, 99, 29, 255, 204, 127, 37, 255,
+        199, 119, 34, 255, 27, 20, 12, 198, 0, 12, 4, 4, 3, 11, 18, 13, 9,
+        255, 154, 79, 19, 255, 174, 88, 19, 255, 92, 51, 17, 255, 12, 10, 7,
+        198, 0, 24, 11, 9, 6, 147, 142, 74, 19, 255, 171, 90, 18, 255, 159,
+        81, 18, 255, 17, 12, 6, 255, 0, 12, 8, 7, 5, 142, 133, 66, 16, 255,
+        161, 85, 17, 255, 161, 85, 17, 255, 21, 14, 6, 215, 0, 24, 10, 9, 7,
+        198, 190, 107, 25, 255, 203, 104, 24, 255, 196, 99, 21, 255, 21, 15,
+        8, 255, 2, 2, 1, 14, 0, 20, 9, 8, 6, 37, 35, 28, 18, 255, 183, 112,
+        36, 255, 212, 132, 37, 255, 178, 118, 41, 255, 27, 23, 16, 255, 5,
+        5, 4, 198, 0, 32, 15, 12, 8, 105, 142, 79, 23, 255, 189, 97, 22,
+        255, 160, 83, 21, 255, 18, 13, 7, 218, 0, 12, 10, 8, 7, 198, 196,
+        114, 33, 255, 214, 129, 37, 255, 212, 132, 37, 255, 27, 21, 12, 210,
+        0, 8, 13, 11, 8, 116, 192, 114, 31, 255, 210, 125, 33, 255, 209,
+        123, 30, 255, 203, 113, 26, 255, 177, 91, 22, 255, 159, 82, 20, 255,
+        160, 83, 21, 255, 165, 85, 20, 255, 168, 89, 19, 255, 163, 86, 18,
+        255, 161, 78, 17, 255, 23, 15, 6, 170, 0, 8, 9, 7, 4, 57, 99, 48,
+        14, 255, 142, 73, 17, 255, 133, 66, 16, 255, 19, 13, 6, 190, 0, 12,
+        7, 6, 4, 164, 135, 66, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255,
+        25, 16, 6, 170, 0, 8, 10, 8, 5, 85, 131, 65, 16, 255, 161, 85, 17,
+        255, 161, 85, 17, 255, 19, 13, 6, 227, 0, 12, 10, 8, 5, 176, 190,
+        107, 25, 255, 212, 127, 35, 255, 214, 134, 39, 255, 30, 21, 13, 255,
+        0, 24, 12, 10, 7, 170, 194, 109, 33, 255, 213, 132, 36, 255, 208,
+        122, 29, 255, 28, 20, 11, 255, 0, 24, 9, 7, 4, 147, 136, 70, 17,
+        255, 202, 98, 21, 255, 211, 126, 34, 255, 27, 20, 12, 255, 3, 3, 2,
+        28, 0, 8, 10, 8, 7, 195, 180, 93, 23, 255, 202, 102, 21, 255, 202,
+        102, 21, 255, 25, 17, 10, 221, 0, 8, 13, 11, 8, 65, 129, 70, 22,
+        255, 172, 88, 21, 255, 144, 78, 19, 255, 22, 15, 7, 176, 0, 12, 10,
+        8, 7, 198, 198, 124, 37, 255, 215, 136, 42, 255, 214, 134, 39, 255,
+        27, 21, 12, 212, 0, 8, 12, 10, 7, 79, 151, 88, 26, 255, 198, 116,
+        29, 255, 192, 109, 27, 255, 25, 18, 10, 167, 0, 8, 12, 9, 7, 82,
+        119, 62, 20, 255, 174, 89, 21, 255, 154, 79, 19, 255, 22, 15, 7,
+        181, 0, 20, 5, 5, 4, 68, 20, 14, 7, 249, 142, 73, 17, 255, 143, 74,
+        18, 255, 45, 26, 10, 255, 10, 8, 5, 85, 0, 76, 7, 6, 6, 85, 39, 30,
+        18, 255, 196, 121, 41, 255, 213, 135, 42, 255, 115, 72, 30, 255, 10,
+        9, 7, 170, 0, 40, 5, 5, 4, 17, 6, 5, 5, 85, 5, 5, 4, 45, 0, 28, 9,
+        7, 4, 142, 146, 79, 19, 255, 204, 108, 23, 255, 212, 126, 33, 255,
+        30, 22, 13, 255, 3, 3, 3, 40, 0, 36, 10, 8, 5, 125, 133, 66, 16,
+        255, 161, 85, 17, 255, 161, 85, 17, 255, 19, 13, 6, 212, 0, 12, 10,
+        8, 5, 127, 136, 70, 17, 255, 193, 97, 20, 255, 203, 108, 24, 255,
+        30, 21, 11, 193, 0, 8, 13, 10, 6, 85, 134, 70, 19, 255, 171, 90, 18,
+        255, 159, 81, 18, 255, 17, 12, 6, 238, 0, 12, 8, 6, 5, 144, 135, 66,
+        16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 23, 15, 6, 170, 0, 8,
+        10, 7, 5, 85, 133, 66, 16, 255, 185, 94, 20, 255, 209, 123, 30, 255,
+        23, 18, 12, 255, 3, 3, 2, 28, 0, 4, 5, 5, 4, 28, 18, 15, 11, 227,
+        134, 72, 21, 255, 158, 81, 19, 255, 143, 74, 18, 255, 22, 15, 7,
+        142, 0, 8, 10, 8, 5, 85, 131, 65, 16, 255, 163, 79, 18, 255, 178,
+        90, 19, 255, 22, 16, 9, 255, 3, 2, 2, 20, 0, 8, 9, 7, 6, 176, 144,
+        78, 19, 255, 175, 88, 18, 255, 163, 79, 18, 255, 26, 16, 7, 170, 0,
+        8, 10, 8, 5, 85, 129, 64, 16, 255, 161, 85, 17, 255, 161, 78, 17,
+        255, 19, 13, 6, 229, 0, 32, 8, 7, 5, 156, 144, 78, 19, 255, 202,
+        102, 21, 255, 206, 111, 27, 255, 27, 20, 12, 255, 0, 32, 10, 8, 5,
+        133, 135, 66, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 19, 13,
+        6, 227, 0, 12, 8, 7, 5, 255, 172, 85, 21, 255, 189, 92, 20, 255,
+        172, 87, 19, 255, 24, 16, 7, 170, 0, 8, 10, 8, 5, 85, 129, 64, 16,
+        255, 161, 85, 17, 255, 161, 85, 17, 255, 19, 13, 6, 212, 0, 12, 10,
+        8, 5, 127, 135, 66, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 26,
+        16, 7, 170, 0, 8, 11, 9, 6, 85, 134, 70, 19, 255, 171, 90, 18, 255,
+        159, 78, 18, 255, 23, 15, 6, 170, 0, 8, 9, 7, 4, 57, 98, 49, 13,
+        255, 139, 71, 16, 255, 133, 66, 16, 255, 19, 13, 6, 193, 0, 12, 7,
+        6, 4, 176, 133, 66, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 23,
+        15, 6, 170, 0, 8, 10, 8, 5, 85, 129, 64, 16, 255, 165, 87, 18, 255,
+        180, 91, 19, 255, 20, 15, 9, 255, 0, 4, 5, 5, 4, 17, 26, 21, 15,
+        227, 126, 75, 25, 255, 178, 95, 21, 255, 142, 74, 19, 255, 46, 28,
+        11, 255, 10, 8, 5, 57, 0, 8, 10, 8, 5, 85, 131, 65, 16, 255, 161,
+        85, 17, 255, 161, 85, 17, 255, 17, 12, 6, 252, 2, 1, 1, 8, 0, 28,
+        13, 11, 8, 170, 199, 119, 34, 255, 215, 136, 42, 255, 214, 139, 41,
+        255, 28, 20, 13, 255, 0, 20, 8, 7, 5, 170, 135, 66, 16, 255, 161,
+        85, 17, 255, 161, 85, 17, 255, 23, 15, 6, 170, 0, 8, 10, 8, 5, 85,
+        131, 67, 16, 255, 202, 102, 21, 255, 211, 127, 36, 255, 22, 17, 11,
+        249, 0, 8, 16, 14, 11, 201, 101, 67, 28, 255, 191, 98, 22, 255, 185,
+        94, 20, 255, 172, 87, 19, 255, 26, 17, 7, 170, 0, 8, 10, 8, 5, 85,
+        129, 64, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 31, 20, 8,
+        255, 5, 5, 4, 102, 0, 4, 5, 4, 4, 28, 16, 13, 9, 255, 164, 85, 21,
+        255, 180, 91, 19, 255, 165, 87, 18, 255, 26, 17, 7, 170, 0, 8, 10,
+        8, 5, 85, 129, 64, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 19,
+        13, 6, 212, 0, 40, 10, 8, 5, 133, 135, 66, 16, 255, 161, 85, 17,
+        255, 161, 85, 17, 255, 26, 17, 7, 255, 3, 3, 2, 136, 9, 7, 4, 227,
+        131, 67, 20, 255, 197, 104, 22, 255, 198, 104, 21, 255, 183, 93, 19,
+        255, 172, 87, 19, 255, 26, 17, 7, 170, 0, 8, 10, 8, 5, 85, 129, 64,
+        16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 19, 13, 6, 212, 0, 12,
+        10, 8, 5, 127, 135, 66, 16, 255, 193, 97, 20, 255, 209, 123, 30,
+        255, 19, 15, 10, 252, 0, 8, 13, 11, 8, 65, 125, 68, 22, 255, 174,
+        86, 21, 255, 146, 76, 19, 255, 22, 14, 7, 178, 0, 12, 8, 6, 5, 144,
+        135, 66, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 19, 14, 6,
+        238, 0, 24, 13, 11, 8, 170, 163, 87, 20, 255, 180, 91, 19, 255, 165,
+        87, 18, 255, 17, 12, 6, 255, 0, 24, 9, 7, 4, 139, 135, 66, 16, 255,
+        161, 85, 17, 255, 161, 85, 17, 255, 15, 11, 6, 246, 0, 12, 9, 7, 6,
+        184, 180, 93, 23, 255, 211, 115, 30, 255, 213, 133, 38, 255, 28, 20,
+        13, 255, 0, 16, 12, 11, 9, 170, 152, 91, 31, 255, 188, 105, 31, 255,
+        115, 66, 22, 255, 91, 50, 16, 255, 84, 46, 15, 255, 116, 59, 17,
+        255, 118, 62, 17, 255, 15, 11, 6, 221, 0, 16, 10, 8, 5, 116, 146,
+        79, 19, 255, 202, 103, 23, 255, 209, 128, 32, 255, 200, 127, 41,
+        255, 167, 106, 40, 255, 197, 122, 42, 255, 210, 130, 35, 255, 186,
+        106, 27, 255, 88, 51, 19, 255, 102, 55, 17, 255, 157, 83, 18, 255,
+        189, 92, 20, 255, 209, 123, 30, 255, 29, 21, 12, 224, 0, 8, 7, 6, 6,
+        28, 41, 31, 18, 235, 160, 84, 23, 255, 170, 87, 19, 255, 45, 26, 10,
+        255, 5, 5, 4, 170, 4, 4, 4, 8, 4, 4, 3, 99, 15, 12, 6, 255, 140, 72,
+        17, 255, 138, 71, 17, 255, 45, 26, 10, 255, 10, 8, 5, 85, 0, 24, 8,
+        7, 5, 142, 133, 66, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 19,
+        13, 6, 229, 0, 24, 13, 11, 8, 170, 160, 86, 21, 255, 185, 90, 20,
+        255, 91, 50, 16, 255, 7, 6, 4, 255, 0, 40, 8, 7, 5, 150, 133, 66,
+        16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 15, 11, 6, 246, 0, 32,
+        8, 8, 7, 110, 74, 52, 27, 255, 191, 103, 24, 255, 176, 89, 19, 255,
+        34, 22, 9, 255, 6, 5, 3, 57, 0, 20, 8, 6, 5, 161, 133, 66, 16, 255,
+        161, 85, 17, 255, 161, 78, 17, 255, 15, 11, 6, 252, 0, 140, 12, 10,
+        5, 85, 123, 61, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 22, 15,
+        7, 255, 2, 2, 1, 85, 0, 8, 7, 6, 4, 244, 133, 66, 16, 255, 167, 88,
+        18, 255, 189, 92, 20, 255, 27, 19, 10, 195, 0, 8, 12, 10, 7, 110,
+        160, 83, 21, 255, 177, 85, 18, 255, 161, 78, 17, 255, 15, 11, 6,
+        252, 0, 12, 7, 6, 4, 161, 133, 66, 16, 255, 161, 85, 17, 255, 161,
+        85, 17, 255, 23, 15, 6, 170, 0, 8, 11, 9, 6, 85, 134, 70, 19, 255,
+        171, 90, 18, 255, 159, 78, 18, 255, 15, 11, 6, 249, 0, 12, 10, 8, 5,
+        85, 98, 49, 13, 255, 135, 72, 16, 255, 133, 66, 16, 255, 19, 13, 6,
+        139, 0, 8, 10, 8, 5, 85, 131, 65, 16, 255, 161, 85, 17, 255, 161,
+        85, 17, 255, 15, 11, 6, 246, 0, 12, 7, 6, 4, 164, 133, 66, 16, 255,
+        165, 87, 18, 255, 178, 90, 19, 255, 24, 17, 9, 212, 0, 8, 13, 11, 8,
+        105, 165, 86, 22, 255, 180, 91, 19, 255, 159, 81, 18, 255, 19, 14,
+        6, 255, 2, 2, 1, 79, 0, 44, 8, 6, 5, 167, 133, 66, 16, 255, 161, 85,
+        17, 255, 161, 85, 17, 255, 15, 11, 6, 252, 0, 16, 7, 6, 6, 28, 24,
+        19, 13, 227, 103, 59, 20, 255, 157, 83, 18, 255, 154, 78, 17, 255,
+        150, 81, 19, 255, 154, 79, 19, 255, 158, 81, 19, 255, 162, 83, 19,
+        255, 161, 85, 17, 255, 159, 81, 18, 255, 163, 86, 18, 255, 27, 18,
+        8, 170, 0, 8, 11, 9, 6, 85, 131, 67, 16, 255, 165, 87, 18, 255, 161,
+        85, 17, 255, 15, 11, 6, 252, 0, 12, 8, 6, 5, 167, 133, 66, 16, 255,
+        161, 85, 17, 255, 161, 85, 17, 255, 23, 15, 6, 170, 0, 8, 10, 8, 5,
+        85, 131, 65, 16, 255, 175, 88, 18, 255, 191, 96, 20, 255, 25, 18,
+        10, 255, 0, 24, 11, 9, 6, 170, 148, 77, 19, 255, 169, 82, 18, 255,
+        161, 85, 17, 255, 23, 15, 6, 170, 0, 8, 10, 8, 5, 85, 129, 64, 16,
+        255, 161, 85, 17, 255, 161, 85, 17, 255, 87, 47, 14, 255, 23, 17, 8,
+        255, 65, 34, 12, 255, 150, 76, 17, 255, 132, 68, 17, 255, 41, 25,
+        10, 255, 10, 8, 5, 85, 0, 16, 8, 7, 5, 150, 133, 66, 16, 255, 161,
+        85, 17, 255, 161, 78, 17, 255, 23, 15, 6, 170, 0, 8, 10, 8, 5, 85,
+        129, 64, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 23, 15, 6,
+        170, 0, 4, 8, 7, 5, 153, 133, 66, 16, 255, 19, 13, 6, 238, 0, 4, 10,
+        8, 5, 85, 129, 64, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 23,
+        15, 6, 170, 0, 8, 10, 8, 5, 85, 129, 64, 16, 255, 161, 85, 17, 255,
+        161, 85, 17, 255, 15, 11, 6, 252, 0, 12, 8, 6, 5, 167, 133, 66, 16,
+        255, 161, 85, 17, 255, 161, 85, 17, 255, 23, 15, 6, 170, 0, 8, 10,
+        8, 5, 85, 129, 64, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 31,
+        20, 8, 255, 5, 4, 4, 85, 0, 4, 5, 4, 4, 40, 17, 14, 10, 255, 200,
+        120, 35, 255, 207, 112, 28, 255, 195, 98, 20, 255, 29, 20, 8, 170,
+        0, 8, 10, 8, 5, 85, 131, 65, 16, 255, 163, 86, 18, 255, 159, 81, 18,
+        255, 150, 76, 17, 255, 137, 70, 16, 255, 135, 72, 16, 255, 135, 66,
+        16, 255, 146, 75, 17, 255, 159, 81, 18, 255, 131, 67, 20, 255, 42,
+        31, 17, 255, 10, 9, 7, 62, 0, 8, 5, 5, 4, 8, 26, 21, 15, 227, 137,
+        79, 28, 255, 174, 88, 19, 255, 158, 83, 17, 255, 137, 70, 16, 255,
+        135, 72, 16, 255, 135, 66, 16, 255, 146, 75, 17, 255, 159, 81, 18,
+        255, 161, 85, 17, 255, 161, 85, 17, 255, 23, 15, 6, 170, 0, 8, 10,
+        8, 5, 85, 131, 67, 16, 255, 163, 86, 18, 255, 159, 81, 18, 255, 17,
+        12, 6, 255, 0, 68, 2, 1, 1, 8, 7, 6, 4, 249, 137, 67, 16, 255, 165,
+        80, 18, 255, 154, 78, 17, 255, 27, 18, 8, 170, 0, 16, 8, 6, 5, 167,
+        133, 66, 16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 15, 11, 6,
+        252, 0, 16, 13, 11, 8, 170, 199, 124, 36, 255, 211, 125, 32, 255,
+        200, 105, 21, 255, 18, 13, 7, 255, 0, 12, 7, 6, 4, 164, 133, 66, 16,
+        255, 161, 85, 17, 255, 161, 78, 17, 255, 19, 13, 6, 227, 0, 16, 8,
+        7, 5, 122, 68, 38, 13, 255, 150, 83, 23, 255, 174, 107, 35, 255,
+        181, 112, 38, 255, 190, 117, 39, 255, 193, 114, 36, 255, 143, 84,
+        26, 255, 15, 12, 8, 212, 4, 4, 3, 6, 0, 12, 10, 8, 5, 108, 135, 66,
+        16, 255, 161, 85, 17, 255, 161, 85, 17, 255, 125, 65, 16, 255, 90,
+        47, 13, 255, 121, 60, 16, 255, 164, 84, 19, 255, 189, 97, 22, 255,
+        177, 104, 32, 255, 194, 123, 39, 255, 212, 134, 41, 255, 210, 124,
+        31, 255, 200, 105, 21, 255, 23, 17, 8, 218, 0, 16, 10, 8, 5, 167,
+        56, 31, 11, 255, 110, 55, 15, 255, 118, 62, 17, 255, 115, 58, 16,
+        255, 115, 58, 16, 255, 120, 63, 17, 255, 95, 46, 14, 255, 17, 13, 6,
+        227, 7, 6, 4, 28, 0, 16, 14, 12, 7, 227, 87, 43, 14, 255, 154, 78,
+        17, 255, 152, 77, 17, 255, 139, 71, 16, 255, 135, 72, 16, 255, 135,
+        66, 16, 255, 146, 75, 17, 255, 200, 105, 21, 255, 211, 127, 36, 255,
+        214, 134, 39, 255, 23, 18, 12, 255, 0, 12, 7, 6, 4, 85, 26, 16, 7,
+        255, 131, 67, 16, 255, 145, 75, 18, 255, 78, 43, 15, 255, 7, 6, 4,
+        255, 0, 40, 10, 8, 5, 136, 157, 81, 20, 255, 210, 129, 33, 255, 139,
+        89, 36, 255, 10, 9, 7, 198, 0, 16, 13, 11, 8, 170, 196, 113, 31,
+        255, 206, 114, 25, 255, 189, 92, 20, 255, 18, 13, 7, 244, 0, 16, 5,
+        4, 4, 88, 27, 19, 8, 255, 141, 73, 18, 255, 161, 85, 17, 255, 21,
+        14, 6, 218, 0, 112, 12, 9, 7, 99, 11, 8, 6, 170, 10, 8, 5, 91, 0,
+        60, 11, 10, 8, 28, 32, 23, 13, 227, 108, 57, 19, 255, 153, 82, 18,
+        255, 154, 78, 17, 255, 146, 75, 17, 255, 97, 47, 14, 255, 36, 24,
+        11, 255, 108, 64, 25, 255, 203, 111, 30, 255, 207, 118, 32, 255,
+        207, 118, 32, 255, 189, 110, 32, 255, 63, 41, 20, 255, 15, 12, 8,
+        76, 0, 8, 9, 8, 6, 28, 38, 27, 15, 218, 51, 33, 18, 255, 48, 32, 17,
+        255, 131, 74, 24, 255, 182, 97, 21, 255, 176, 89, 19, 255, 170, 87,
+        19, 255, 134, 72, 21, 255, 37, 25, 14, 255, 15, 13, 8, 144, 7, 7, 6,
+        28, 0, 12, 11, 9, 8, 127, 171, 99, 28, 255, 208, 123, 31, 255, 203,
+        124, 30, 255, 104, 63, 27, 255, 15, 13, 10, 212, 7, 6, 6, 28, 0, 12,
+        14, 11, 7, 170, 142, 74, 19, 255, 161, 85, 17, 255, 159, 81, 18,
+        255, 27, 18, 8, 184, 0, 8, 6, 5, 3, 28, 27, 17, 8, 227, 92, 46, 13,
+        255, 111, 55, 14, 255, 31, 20, 8, 255, 8, 6, 3, 198, 9, 7, 4, 170,
+        10, 8, 5, 227, 22, 16, 9, 255, 61, 39, 18, 255, 107, 64, 26, 255,
+        108, 66, 25, 255, 32, 22, 11, 255, 9, 7, 6, 170, 0, 44, 10, 9, 7,
+        156, 56, 36, 19, 255, 191, 114, 32, 255, 175, 98, 30, 255, 41, 27,
+        16, 255, 11, 9, 6, 57, 0, 12, 21, 15, 10, 227, 100, 56, 21, 255,
+        160, 83, 21, 255, 80, 44, 17, 255, 14, 12, 7, 190, 7, 6, 6, 28, 0,
+        16, 13, 10, 6, 28, 29, 20, 10, 212, 21, 15, 10, 144, 0, 20, 12, 9,
+        7, 85, 39, 24, 10, 173, 16, 12, 7, 85, 0, 32, 6, 5, 3, 20, 19, 13,
+        6, 173, 21, 14, 6, 255, 21, 15, 6, 215, 10, 8, 5, 85, 0, 24, 15, 12,
+        8, 170, 190, 98, 23, 255, 203, 108, 24, 255, 202, 111, 23, 255, 23,
+        17, 10, 255, 0, 60, 17, 13, 10, 170, 195, 112, 30, 255, 211, 124,
+        30, 255, 205, 106, 26, 255, 31, 21, 12, 255, 0, 12, 8, 6, 5, 139,
+        44, 25, 9, 255, 135, 72, 16, 255, 104, 54, 13, 255, 15, 11, 6, 249,
+        7, 6, 4, 28, 0, 24, 7, 6, 4, 57, 44, 25, 9, 255, 137, 73, 16, 255,
+        143, 70, 16, 255, 49, 25, 8, 255, 8, 6, 3, 184, 8, 6, 3, 85, 8, 6,
+        3, 142, 23, 16, 6, 255, 130, 66, 15, 255, 145, 77, 16, 255, 87, 44,
+        12, 255, 10, 8, 5, 142, 0, 20, 11, 9, 8, 164, 53, 31, 14, 255, 150,
+        74, 19, 255, 154, 78, 17, 255, 148, 76, 17, 255, 65, 33, 10, 255,
+        10, 8, 5, 184, 6, 5, 5, 28, 0, 16, 11, 9, 6, 142, 175, 102, 30, 255,
+        207, 123, 32, 255, 208, 114, 31, 255, 196, 114, 33, 255, 89, 56, 26,
+        255, 17, 13, 10, 255, 11, 8, 6, 170, 9, 7, 6, 170, 11, 8, 6, 170,
+        15, 11, 8, 170, 18, 13, 9, 142, 8, 6, 5, 28, 0, 8, 10, 8, 5, 93,
+        102, 53, 17, 255, 159, 81, 18, 255, 154, 78, 17, 255, 72, 37, 11,
+        255, 11, 8, 6, 227, 9, 7, 6, 170, 11, 8, 6, 198, 61, 36, 20, 255,
+        196, 107, 27, 255, 204, 114, 27, 255, 182, 102, 31, 255, 19, 14, 10,
+        170, 0, 8, 6, 6, 5, 20, 26, 19, 11, 198, 28, 20, 11, 255, 22, 16, 9,
+        255, 23, 16, 8, 255, 27, 18, 8, 255, 24, 16, 7, 255, 24, 16, 7, 255,
+        74, 39, 11, 255, 139, 68, 16, 255, 143, 70, 16, 255, 143, 70, 16,
+        255, 20, 13, 5, 170, 0, 8, 7, 6, 4, 74, 87, 44, 12, 255, 155, 79,
+        18, 255, 151, 73, 16, 255, 67, 34, 10, 255, 9, 7, 4, 198, 9, 7, 4,
+        96, 8, 6, 5, 159, 27, 17, 8, 255, 137, 67, 16, 255, 158, 80, 17,
+        255, 112, 56, 15, 255, 10, 8, 5, 167, 0, 8, 7, 5, 4, 85, 74, 36, 11,
+        255, 150, 83, 17, 255, 145, 77, 16, 255, 55, 29, 10, 255, 8, 6, 3,
+        198, 8, 6, 3, 88, 7, 6, 4, 153, 39, 24, 12, 255, 199, 112, 28, 255,
+        210, 115, 31, 255, 184, 108, 33, 255, 17, 14, 10, 198, 0, 24, 11, 9,
+        6, 170, 139, 69, 18, 255, 168, 86, 19, 255, 154, 78, 17, 255, 17,
+        12, 6, 235, 0, 24, 7, 6, 4, 85, 64, 32, 11, 255, 162, 80, 19, 255,
+        198, 96, 21, 255, 109, 63, 26, 255, 15, 11, 8, 227, 10, 8, 7, 170,
+        8, 7, 5, 195, 29, 18, 8, 255, 137, 67, 16, 255, 154, 78, 17, 255,
+        114, 59, 15, 255, 11, 10, 6, 164, 0, 8, 9, 7, 6, 85, 97, 50, 16,
+        255, 159, 81, 18, 255, 152, 77, 17, 255, 74, 36, 11, 255, 10, 8, 5,
+        198, 7, 6, 4, 125, 10, 8, 5, 198, 61, 36, 20, 255, 200, 105, 29,
+        255, 209, 122, 28, 255, 180, 104, 29, 255, 16, 12, 9, 170, 0, 8, 12,
+        10, 7, 170, 160, 83, 21, 255, 183, 89, 19, 255, 174, 88, 19, 255,
+        28, 19, 9, 187, 0, 8, 14, 10, 7, 85, 143, 75, 20, 255, 195, 98, 20,
+        255, 189, 92, 20, 255, 21, 15, 8, 224, 0, 24, 7, 6, 4, 85, 26, 16,
+        7, 255, 111, 55, 14, 255, 132, 67, 15, 255, 39, 23, 8, 255, 8, 6, 3,
+        113, 0, 68, 9, 7, 6, 85, 32, 22, 13, 255, 188, 112, 31, 255, 193,
+        114, 30, 255, 94, 57, 25, 255, 17, 13, 10, 170, 0, 44, 9, 7, 4, 142,
+        10, 8, 5, 255, 10, 8, 5, 198, 6, 5, 3, 28, 0, 24, 8, 7, 5, 85, 88,
+        48, 19, 255, 204, 114, 27, 255, 208, 118, 31, 255, 111, 62, 26, 255,
+        11, 8, 6, 227, 8, 7, 5, 150, 10, 8, 5, 116, 10, 8, 5, 88, 9, 7, 4,
+        85, 6, 5, 3, 74, 0, 16, 10, 8, 5, 99, 114, 56, 13, 255, 143, 70, 16,
+        255, 143, 70, 16, 255, 18, 12, 5, 215, 0, 12, 8, 7, 3, 130, 118, 60,
+        13, 255, 148, 76, 17, 255, 150, 76, 17, 255, 24, 16, 7, 170, 0, 8,
+        9, 7, 4, 85, 114, 56, 13, 255, 145, 74, 16, 255, 143, 70, 16, 255,
+        52, 28, 9, 255, 8, 6, 3, 198, 8, 6, 3, 88, 8, 6, 3, 144, 23, 15, 6,
+        255, 130, 66, 15, 255, 151, 80, 16, 255, 111, 55, 14, 255, 10, 8, 5,
+        144, 0, 8, 6, 5, 3, 59, 59, 32, 10, 255, 157, 83, 18, 255, 185, 90,
+        20, 255, 97, 54, 22, 255, 14, 10, 7, 227, 13, 10, 6, 170, 13, 10, 6,
+        255, 84, 41, 13, 255, 148, 76, 17, 255, 155, 82, 18, 255, 135, 66,
+        16, 255, 14, 10, 5, 159, 0, 8, 9, 7, 4, 85, 114, 56, 13, 255, 145,
+        77, 16, 255, 145, 74, 16, 255, 55, 28, 10, 255, 9, 7, 4, 198, 8, 6,
+        3, 93, 8, 6, 3, 147, 25, 16, 6, 255, 130, 64, 15, 255, 151, 80, 16,
+        255, 111, 55, 14, 255, 10, 8, 5, 142, 0, 8, 9, 7, 4, 85, 114, 56,
+        13, 255, 145, 77, 16, 255, 143, 70, 16, 255, 52, 28, 9, 255, 8, 6,
+        3, 198, 8, 6, 3, 102, 8, 6, 3, 139, 8, 6, 3, 170, 9, 8, 4, 113, 0,
+        12, 10, 8, 5, 91, 114, 56, 13, 255, 150, 76, 17, 255, 150, 76, 17,
+        255, 17, 12, 6, 252, 0, 32, 7, 6, 4, 85, 64, 33, 11, 255, 145, 77,
+        16, 255, 143, 70, 16, 255, 56, 29, 9, 255, 8, 6, 3, 198, 8, 6, 3,
+        85, 6, 5, 3, 119, 14, 11, 5, 255, 128, 66, 15, 255, 151, 73, 16,
+        255, 143, 76, 16, 255, 20, 13, 5, 170, 0, 8, 9, 7, 4, 85, 114, 56,
+        13, 255, 143, 70, 16, 255, 143, 70, 16, 255, 18, 12, 5, 215, 0, 12,
+        8, 7, 3, 130, 114, 56, 13, 255, 143, 70, 16, 255, 143, 70, 16, 255,
+        20, 13, 5, 170, 0, 8, 9, 7, 4, 85, 114, 56, 13, 255, 143, 70, 16,
+        255, 143, 70, 16, 255, 20, 13, 5, 170, 0, 8, 7, 6, 4, 71, 87, 44,
+        12, 255, 158, 87, 17, 255, 161, 85, 17, 255, 103, 53, 20, 255, 15,
+        11, 8, 227, 10, 8, 7, 170, 10, 8, 7, 195, 33, 20, 10, 255, 137, 67,
+        16, 255, 151, 73, 16, 255, 111, 55, 14, 255, 10, 8, 5, 142, 0, 8, 9,
+        7, 4, 85, 114, 56, 13, 255, 143, 70, 16, 255, 146, 75, 17, 255, 18,
+        13, 7, 255, 0, 8, 7, 6, 6, 74, 24, 16, 7, 255, 132, 67, 15, 255,
+        145, 77, 16, 255, 135, 72, 16, 255, 14, 10, 5, 170, 0, 8, 9, 7, 4,
+        85, 114, 56, 13, 255, 145, 77, 16, 255, 143, 70, 16, 255, 58, 31,
+        11, 255, 11, 8, 6, 227, 11, 9, 6, 170, 11, 8, 6, 170, 10, 7, 5, 170,
+        9, 8, 4, 113, 0, 12, 11, 9, 6, 161, 175, 92, 24, 255, 203, 108, 24,
+        255, 198, 101, 23, 255, 25, 18, 10, 255, 0, 20, 8, 6, 3, 147, 114,
+        56, 13, 255, 143, 70, 16, 255, 143, 70, 16, 255, 20, 13, 5, 170, 0,
+        8, 9, 7, 4, 85, 114, 56, 13, 255, 170, 87, 19, 255, 199, 106, 24,
+        255, 24, 17, 11, 255, 0, 8, 6, 6, 5, 28, 15, 12, 6, 255, 128, 66,
+        15, 255, 145, 74, 16, 255, 143, 70, 16, 255, 20, 13, 5, 170, 0, 8,
+        6, 5, 3, 57, 57, 31, 10, 255, 145, 77, 16, 255, 143, 70, 16, 255,
+        90, 44, 13, 255, 19, 13, 6, 255, 10, 8, 5, 255, 13, 10, 6, 255, 62,
+        33, 11, 255, 135, 72, 16, 255, 151, 73, 16, 255, 108, 53, 13, 255,
+        10, 8, 5, 142, 0, 8, 9, 7, 4, 85, 114, 56, 13, 255, 143, 70, 16,
+        255, 143, 70, 16, 255, 18, 12, 5, 215, 0, 40, 7, 6, 4, 85, 64, 33,
+        11, 255, 145, 77, 16, 255, 143, 70, 16, 255, 67, 34, 10, 255, 14,
+        10, 5, 255, 49, 27, 9, 255, 140, 72, 17, 255, 160, 85, 19, 255, 160,
+        85, 19, 255, 110, 55, 15, 255, 31, 20, 8, 255, 9, 7, 4, 57, 0, 8, 9,
+        8, 4, 85, 114, 56, 13, 255, 143, 70, 16, 255, 143, 70, 16, 255, 18,
+        12, 5, 215, 0, 12, 8, 7, 3, 136, 118, 60, 13, 255, 154, 75, 17, 255,
+        172, 87, 19, 255, 24, 17, 9, 204, 0, 8, 8, 7, 5, 85, 95, 49, 16,
+        255, 161, 85, 17, 255, 152, 77, 17, 255, 71, 34, 10, 255, 9, 7, 4,
+        198, 8, 6, 3, 88, 8, 6, 3, 142, 23, 15, 6, 255, 130, 66, 15, 255,
+        151, 80, 16, 255, 111, 55, 14, 255, 14, 10, 5, 170, 0, 24, 9, 7, 4,
+        164, 118, 56, 15, 255, 145, 74, 16, 255, 143, 70, 16, 255, 16, 12,
+        5, 224, 0, 24, 9, 7, 4, 85, 85, 43, 12, 255, 151, 80, 16, 255, 143,
+        70, 16, 255, 55, 29, 10, 255, 8, 6, 3, 198, 8, 6, 3, 93, 8, 6, 5,
+        173, 45, 27, 14, 255, 199, 112, 28, 255, 210, 124, 31, 255, 199,
+        119, 34, 255, 19, 15, 10, 221, 0, 20, 13, 11, 8, 170, 46, 28, 11,
+        255, 131, 65, 16, 255, 145, 74, 16, 255, 137, 67, 16, 255, 70, 35,
+        11, 255, 12, 10, 5, 224, 7, 6, 4, 28, 0, 16, 8, 6, 5, 34, 37, 25,
+        14, 255, 181, 100, 28, 255, 206, 113, 31, 255, 207, 123, 32, 255,
+        199, 119, 34, 255, 107, 67, 28, 255, 28, 20, 11, 255, 28, 19, 9,
+        255, 84, 41, 13, 255, 141, 75, 16, 255, 145, 74, 16, 255, 159, 82,
+        20, 255, 88, 53, 25, 255, 13, 11, 8, 99, 0, 8, 13, 10, 6, 85, 114,
+        60, 17, 255, 148, 76, 17, 255, 143, 70, 16, 255, 21, 14, 6, 255, 0,
+        12, 10, 8, 5, 170, 119, 61, 14, 255, 145, 77, 16, 255, 135, 72, 16,
+        255, 19, 13, 6, 170, 0, 24, 8, 7, 3, 142, 114, 56, 13, 255, 143, 70,
+        16, 255, 143, 70, 16, 255, 16, 12, 5, 218, 0, 24, 11, 8, 6, 170,
+        126, 62, 15, 255, 151, 80, 16, 255, 112, 57, 13, 255, 19, 13, 6,
+        255, 8, 6, 3, 144, 8, 6, 3, 85, 9, 7, 4, 113, 8, 6, 3, 167, 8, 6, 3,
+        170, 8, 6, 3, 170, 9, 8, 4, 113, 0, 12, 10, 8, 5, 91, 114, 56, 13,
+        255, 145, 74, 16, 255, 143, 70, 16, 255, 61, 32, 10, 255, 9, 8, 4,
+        170, 0, 32, 12, 10, 7, 207, 74, 36, 11, 255, 139, 74, 16, 255, 79,
+        40, 12, 255, 10, 8, 5, 210, 0, 16, 9, 7, 4, 85, 27, 17, 6, 255, 130,
+        66, 15, 255, 143, 70, 16, 255, 143, 76, 16, 255, 16, 12, 5, 221, 0,
+        140, 8, 6, 3, 85, 74, 39, 11, 255, 145, 77, 16, 255, 143, 70, 16,
+        255, 41, 23, 8, 255, 7, 6, 4, 173, 5, 5, 2, 85, 6, 5, 3, 113, 14,
+        10, 5, 255, 129, 65, 14, 255, 145, 74, 16, 255, 145, 74, 16, 255,
+        24, 16, 7, 170, 0, 8, 10, 8, 5, 85, 112, 57, 13, 255, 145, 77, 16,
+        255, 143, 70, 16, 255, 52, 28, 9, 255, 8, 6, 3, 198, 8, 6, 3, 88, 8,
+        6, 3, 144, 23, 15, 6, 255, 130, 66, 15, 255, 151, 80, 16, 255, 111,
+        55, 14, 255, 10, 8, 5, 144, 0, 8, 6, 5, 3, 59, 63, 34, 10, 255, 145,
+        77, 16, 255, 143, 70, 16, 255, 55, 29, 10, 255, 8, 6, 3, 198, 8, 6,
+        3, 85, 8, 6, 3, 144, 32, 19, 7, 255, 139, 74, 16, 255, 155, 79, 18,
+        255, 135, 66, 16, 255, 14, 10, 5, 170, 0, 8, 6, 5, 3, 57, 57, 31,
+        10, 255, 145, 77, 16, 255, 143, 70, 16, 255, 55, 29, 10, 255, 8, 6,
+        3, 198, 8, 6, 3, 88, 8, 6, 3, 144, 21, 15, 6, 255, 130, 66, 15, 255,
+        143, 76, 16, 255, 146, 75, 17, 255, 24, 15, 7, 184, 0, 8, 7, 6, 4,
+        71, 66, 33, 11, 255, 148, 79, 17, 255, 143, 70, 16, 255, 45, 25, 8,
+        255, 7, 5, 4, 176, 7, 5, 4, 85, 8, 6, 3, 85, 9, 7, 4, 85, 8, 6, 3,
+        82, 0, 28, 8, 7, 3, 136, 114, 56, 13, 255, 143, 70, 16, 255, 143,
+        70, 16, 255, 16, 12, 5, 221, 0, 20, 7, 6, 4, 28, 10, 8, 5, 130, 19,
+        13, 6, 170, 29, 19, 8, 173, 24, 16, 7, 212, 27, 18, 8, 193, 20, 13,
+        7, 246, 55, 29, 10, 255, 139, 74, 16, 255, 143, 70, 16, 255, 143,
+        70, 16, 255, 18, 13, 5, 170, 0, 8, 9, 7, 4, 85, 115, 54, 14, 255,
+        143, 70, 16, 255, 143, 70, 16, 255, 16, 12, 5, 221, 0, 12, 8, 7, 3,
+        136, 114, 56, 13, 255, 143, 70, 16, 255, 143, 70, 16, 255, 20, 13,
+        5, 170, 0, 8, 9, 7, 4, 85, 114, 56, 13, 255, 145, 74, 16, 255, 145,
+        74, 16, 255, 17, 11, 6, 252, 0, 24, 10, 8, 5, 170, 119, 61, 14, 255,
+        145, 74, 16, 255, 143, 70, 16, 255, 18, 13, 5, 170, 0, 8, 9, 7, 4,
+        85, 114, 56, 13, 255, 143, 70, 16, 255, 143, 70, 16, 255, 33, 20, 8,
+        255, 5, 4, 4, 195, 8, 6, 5, 198, 46, 26, 9, 255, 126, 62, 15, 255,
+        132, 67, 15, 255, 35, 22, 8, 255, 9, 7, 4, 93, 0, 12, 10, 8, 5, 93,
+        114, 56, 13, 255, 143, 70, 16, 255, 143, 70, 16, 255, 20, 13, 5,
+        170, 0, 8, 9, 7, 4, 85, 114, 56, 13, 255, 143, 70, 16, 255, 143, 70,
+        16, 255, 20, 13, 5, 170, 0, 4, 9, 7, 4, 125, 114, 56, 13, 255, 21,
+        13, 6, 210, 0, 4, 9, 7, 4, 85, 114, 56, 13, 255, 143, 70, 16, 255,
+        143, 70, 16, 255, 20, 13, 5, 170, 0, 8, 9, 7, 4, 85, 114, 56, 13,
+        255, 143, 70, 16, 255, 143, 70, 16, 255, 16, 12, 5, 221, 0, 12, 8,
+        7, 3, 136, 114, 56, 13, 255, 143, 70, 16, 255, 143, 70, 16, 255, 20,
+        13, 5, 170, 0, 8, 6, 5, 3, 57, 57, 31, 10, 255, 145, 77, 16, 255,
+        143, 70, 16, 255, 90, 44, 13, 255, 17, 12, 6, 255, 12, 9, 5, 255,
+        20, 15, 9, 255, 97, 51, 20, 255, 169, 87, 20, 255, 161, 85, 17, 255,
+        112, 54, 15, 255, 10, 8, 5, 142, 0, 8, 9, 7, 4, 85, 121, 60, 16,
+        255, 174, 88, 19, 255, 176, 89, 19, 255, 112, 59, 17, 255, 37, 23,
+        10, 255, 26, 16, 7, 255, 25, 18, 8, 255, 24, 15, 7, 255, 23, 16, 8,
+        255, 18, 13, 9, 198, 10, 9, 7, 99, 0, 16, 9, 8, 6, 34, 12, 10, 7,
+        167, 20, 14, 7, 210, 21, 15, 6, 255, 26, 17, 7, 255, 24, 16, 7, 255,
+        26, 17, 7, 255, 70, 35, 11, 255, 142, 73, 17, 255, 148, 76, 17, 255,
+        152, 77, 17, 255, 24, 15, 7, 170, 0, 8, 13, 10, 6, 96, 129, 65, 18,
+        255, 170, 87, 19, 255, 170, 87, 19, 255, 24, 16, 9, 255, 0, 48, 5,
+        4, 2, 76, 8, 6, 3, 85, 8, 6, 3, 85, 8, 6, 3, 85, 7, 5, 4, 85, 6, 5,
+        3, 119, 16, 11, 5, 255, 129, 65, 14, 255, 151, 73, 16, 255, 118, 61,
+        15, 255, 14, 10, 5, 170, 0, 16, 8, 7, 3, 136, 114, 56, 13, 255, 143,
+        70, 16, 255, 143, 70, 16, 255, 16, 12, 5, 221, 0, 16, 10, 8, 7, 113,
+        109, 67, 26, 255, 184, 90, 21, 255, 148, 76, 17, 255, 52, 28, 9,
+        255, 8, 6, 3, 198, 8, 6, 3, 88, 8, 6, 3, 144, 21, 15, 6, 255, 130,
+        66, 15, 255, 143, 76, 16, 255, 143, 76, 16, 255, 16, 12, 5, 227, 0,
+        20, 9, 8, 6, 170, 67, 42, 20, 255, 202, 124, 31, 255, 208, 128, 33,
+        255, 205, 106, 26, 255, 104, 58, 21, 255, 14, 11, 7, 218, 6, 5, 5,
+        28, 0, 16, 7, 6, 4, 28, 27, 17, 8, 229, 102, 51, 13, 255, 139, 68,
+        16, 255, 143, 73, 16, 255, 145, 74, 16, 255, 71, 37, 12, 255, 26,
+        18, 9, 255, 80, 50, 23, 255, 204, 122, 33, 255, 208, 115, 33, 255,
+        202, 104, 25, 255, 149, 78, 20, 255, 52, 30, 11, 255, 10, 8, 5, 85,
+        0, 12, 14, 10, 5, 170, 85, 43, 12, 255, 137, 73, 16, 255, 77, 39,
+        12, 255, 14, 10, 5, 227, 10, 8, 5, 170, 10, 8, 5, 198, 46, 26, 9,
+        255, 137, 73, 16, 255, 115, 59, 14, 255, 25, 16, 6, 232, 8, 6, 3,
+        31, 0, 12, 6, 5, 3, 28, 10, 8, 5, 119, 19, 13, 6, 170, 29, 19, 8,
+        173, 26, 16, 7, 210, 27, 18, 8, 187, 17, 12, 6, 246, 58, 30, 11,
+        255, 151, 77, 18, 255, 192, 97, 21, 255, 192, 97, 21, 255, 24, 16,
+        9, 207, 0, 8, 4, 4, 3, 3, 25, 16, 6, 235, 115, 59, 14, 255, 143, 73,
+        16, 255, 145, 77, 16, 255, 108, 53, 13, 255, 21, 14, 6, 255, 7, 6,
+        4, 164, 10, 7, 5, 85, 8, 7, 5, 147, 9, 7, 4, 136, 8, 6, 5, 76, 0,
+        20, 8, 6, 5, 57, 58, 33, 13, 255, 188, 107, 27, 255, 192, 111, 31,
+        255, 85, 51, 24, 255, 18, 13, 9, 187, 6, 5, 5, 20, 0, 8, 11, 9, 6,
+        156, 139, 69, 18, 255, 158, 83, 17, 255, 148, 76, 17, 255, 23, 15,
+        6, 170, 0, 12, 9, 7, 4, 85, 19, 13, 6, 255, 102, 51, 13, 255, 128,
+        66, 15, 255, 81, 41, 12, 255, 12, 9, 5, 142, 0, 108, 13, 10, 8, 85,
+        115, 60, 24, 255, 162, 75, 23, 255, 121, 60, 20, 255, 23, 15, 8,
+        142, 0, 60, 3, 3, 2, 6, 10, 8, 5, 170, 93, 48, 12, 255, 123, 65, 14,
+        255, 123, 60, 14, 255, 14, 10, 5, 227, 3, 3, 2, 85, 12, 10, 7, 170,
+        163, 83, 24, 255, 199, 99, 26, 255, 193, 96, 24, 255, 41, 26, 14,
+        227, 6, 6, 5, 45, 0, 24, 3, 3, 2, 28, 11, 8, 6, 170, 106, 50, 13,
+        255, 129, 63, 14, 255, 129, 63, 14, 255, 29, 18, 8, 227, 6, 5, 5,
+        31, 0, 20, 13, 10, 8, 136, 144, 73, 21, 255, 182, 89, 21, 255, 99,
+        55, 19, 255, 14, 11, 7, 187, 4, 4, 3, 3, 0, 16, 9, 7, 4, 113, 93,
+        46, 12, 255, 131, 66, 14, 255, 121, 62, 14, 255, 16, 11, 5, 170, 0,
+        12, 7, 6, 4, 28, 14, 10, 5, 227, 100, 50, 13, 255, 110, 59, 13, 255,
+        103, 52, 14, 255, 121, 59, 18, 255, 134, 69, 21, 255, 32, 21, 11,
+        255, 6, 5, 5, 198, 10, 8, 7, 227, 46, 28, 13, 255, 104, 51, 15, 255,
+        96, 46, 13, 255, 14, 10, 5, 139, 0, 44, 10, 8, 7, 108, 63, 37, 18,
+        255, 176, 88, 23, 255, 160, 80, 21, 255, 20, 14, 9, 170, 0, 8, 8, 6,
+        5, 79, 85, 41, 12, 255, 131, 65, 16, 255, 66, 34, 11, 255, 10, 8, 5,
+        170, 0, 144, 9, 7, 4, 167, 115, 56, 16, 255, 165, 85, 20, 255, 112,
+        65, 23, 255, 18, 13, 9, 142, 0, 60, 13, 10, 8, 142, 132, 68, 21,
+        255, 162, 80, 19, 255, 141, 70, 18, 255, 17, 12, 6, 181, 0, 12, 17,
+        12, 6, 255, 103, 54, 14, 255, 130, 66, 15, 255, 31, 20, 8, 255, 6,
+        5, 3, 113, 0, 32, 8, 6, 3, 156, 35, 22, 8, 255, 114, 58, 13, 255,
+        110, 59, 13, 255, 88, 45, 11, 255, 88, 42, 11, 255, 92, 47, 11, 255,
+        104, 54, 13, 255, 119, 58, 14, 255, 61, 32, 10, 255, 10, 8, 5, 224,
+        5, 4, 4, 20, 0, 16, 11, 8, 6, 85, 113, 58, 22, 255, 180, 90, 23,
+        255, 140, 69, 17, 255, 123, 63, 14, 255, 123, 60, 14, 255, 119, 56,
+        14, 255, 120, 61, 17, 255, 24, 15, 9, 167, 0, 16, 12, 10, 7, 133,
+        180, 88, 27, 255, 203, 107, 30, 255, 199, 100, 28, 255, 197, 104,
+        28, 255, 191, 93, 28, 255, 167, 78, 24, 255, 132, 68, 21, 255, 121,
+        62, 18, 255, 117, 60, 18, 255, 118, 57, 17, 255, 108, 50, 15, 255,
+        17, 12, 6, 113, 0, 12, 14, 10, 5, 227, 65, 33, 10, 255, 115, 59, 14,
+        255, 115, 59, 14, 255, 109, 52, 14, 255, 116, 57, 17, 255, 121, 59,
+        18, 255, 139, 68, 20, 255, 154, 73, 19, 255, 115, 62, 20, 255, 33,
+        23, 12, 255, 9, 8, 6, 71, 0, 36, 2, 2, 1, 8, 8, 6, 3, 170, 93, 50,
+        12, 255, 125, 64, 14, 255, 123, 60, 14, 255, 14, 10, 5, 159, 0, 12,
+        14, 10, 5, 224, 65, 33, 10, 255, 115, 59, 14, 255, 115, 59, 14, 255,
+        109, 52, 14, 255, 119, 61, 18, 255, 129, 66, 20, 255, 148, 75, 21,
+        255, 170, 84, 21, 255, 129, 67, 22, 255, 37, 25, 14, 255, 8, 7, 5,
+        57, 0, 8, 5, 5, 4, 23, 24, 17, 9, 255, 103, 54, 18, 255, 132, 63,
+        17, 255, 120, 62, 15, 255, 98, 49, 13, 255, 90, 45, 11, 255, 94, 45,
+        13, 255, 124, 60, 17, 255, 172, 81, 21, 255, 150, 78, 25, 255, 44,
+        29, 17, 255, 9, 8, 6, 91, 0, 24, 8, 7, 3, 102, 93, 46, 12, 255, 125,
+        64, 14, 255, 121, 62, 14, 255, 18, 12, 5, 170, 0, 28, 12, 10, 5,
+        227, 64, 33, 11, 255, 132, 66, 17, 255, 158, 79, 21, 255, 151, 70,
+        22, 255, 130, 67, 21, 255, 110, 53, 15, 255, 108, 53, 13, 255, 118,
+        60, 13, 255, 85, 43, 12, 255, 21, 14, 6, 255, 7, 6, 4, 57, 0, 12,
+        14, 10, 5, 227, 65, 33, 10, 255, 131, 65, 16, 255, 149, 72, 20, 255,
+        133, 68, 20, 255, 111, 54, 16, 255, 110, 53, 15, 255, 138, 72, 19,
+        255, 163, 81, 20, 255, 112, 58, 19, 255, 28, 20, 9, 255, 8, 7, 5,
+        57, 0, 8, 9, 7, 4, 91, 96, 48, 13, 255, 132, 70, 15, 255, 123, 60,
+        14, 255, 14, 10, 5, 161, 0, 8, 13, 10, 6, 85, 148, 73, 23, 255, 202,
+        101, 27, 255, 129, 67, 26, 255, 18, 13, 9, 142, 0, 28, 6, 5, 3, 48,
+        17, 12, 6, 227, 108, 55, 13, 255, 112, 55, 13, 255, 35, 22, 8, 255,
+        9, 7, 4, 57, 0, 64, 32, 22, 13, 255, 137, 68, 22, 255, 154, 73, 19,
+        255, 45, 26, 10, 255, 8, 6, 5, 144, 0, 44, 8, 6, 3, 68, 67, 34, 10,
+        255, 115, 56, 16, 255, 109, 52, 14, 255, 16, 11, 5, 147, 0, 24, 5,
+        4, 4, 11, 22, 17, 11, 227, 129, 76, 28, 255, 195, 95, 28, 255, 186,
+        84, 23, 255, 121, 59, 18, 255, 107, 51, 14, 255, 96, 46, 13, 255,
+        90, 45, 11, 255, 88, 45, 11, 255, 41, 24, 8, 255, 12, 10, 5, 176, 0,
+        12, 8, 6, 3, 76, 88, 44, 11, 255, 125, 66, 14, 255, 123, 60, 14,
+        255, 18, 12, 5, 170, 0, 12, 9, 7, 4, 85, 92, 47, 11, 255, 125, 64,
+        14, 255, 123, 60, 14, 255, 16, 11, 5, 150, 0, 8, 8, 6, 3, 62, 88,
+        45, 11, 255, 125, 64, 14, 255, 123, 60, 14, 255, 114, 58, 13, 255,
+        93, 50, 12, 255, 88, 44, 11, 255, 92, 47, 11, 255, 104, 54, 13, 255,
+        119, 58, 14, 255, 85, 43, 12, 255, 21, 15, 6, 255, 7, 6, 4, 51, 0,
+        12, 12, 10, 5, 221, 61, 32, 10, 255, 120, 62, 15, 255, 123, 61, 16,
+        255, 109, 52, 14, 255, 96, 46, 13, 255, 102, 51, 13, 255, 115, 59,
+        14, 255, 123, 65, 14, 255, 85, 43, 12, 255, 25, 16, 6, 255, 7, 6, 4,
+        51, 0, 8, 8, 6, 3, 74, 88, 45, 11, 255, 125, 64, 14, 255, 123, 60,
+        14, 255, 114, 58, 13, 255, 93, 50, 12, 255, 88, 45, 11, 255, 92, 47,
+        11, 255, 104, 52, 13, 255, 118, 60, 13, 255, 85, 43, 12, 255, 21,
+        15, 6, 255, 7, 5, 4, 40, 0, 8, 8, 6, 3, 74, 88, 45, 11, 255, 125,
+        64, 14, 255, 123, 60, 14, 255, 114, 58, 13, 255, 93, 50, 12, 255,
+        88, 45, 11, 255, 92, 43, 11, 255, 93, 50, 12, 255, 93, 50, 12, 255,
+        20, 13, 5, 85, 0, 8, 8, 6, 3, 65, 88, 45, 11, 255, 125, 64, 14, 255,
+        121, 62, 14, 255, 18, 13, 5, 170, 0, 36, 12, 10, 5, 227, 59, 31, 10,
+        255, 115, 62, 14, 255, 114, 58, 13, 255, 93, 50, 12, 255, 88, 44,
+        11, 255, 88, 44, 11, 255, 104, 54, 13, 255, 118, 60, 13, 255, 123,
+        60, 14, 255, 123, 60, 14, 255, 14, 10, 5, 150, 0, 8, 8, 6, 3, 65,
+        88, 45, 11, 255, 125, 66, 14, 255, 123, 60, 14, 255, 18, 12, 5, 170,
+        0, 12, 9, 7, 4, 85, 92, 47, 11, 255, 125, 66, 14, 255, 123, 65, 14,
+        255, 14, 10, 5, 150, 0, 8, 8, 6, 3, 65, 88, 45, 11, 255, 125, 66,
+        14, 255, 123, 65, 14, 255, 14, 10, 5, 159, 0, 12, 14, 10, 5, 221,
+        70, 35, 11, 255, 155, 74, 20, 255, 193, 89, 26, 255, 185, 91, 28,
+        255, 172, 85, 27, 255, 165, 80, 24, 255, 155, 78, 22, 255, 132, 66,
+        17, 255, 90, 44, 13, 255, 21, 15, 6, 255, 7, 5, 4, 40, 0, 8, 8, 6,
+        3, 74, 88, 45, 11, 255, 125, 64, 14, 255, 121, 62, 14, 255, 19, 13,
+        6, 176, 0, 12, 9, 6, 4, 133, 93, 50, 12, 255, 131, 66, 14, 255, 123,
+        65, 14, 255, 14, 11, 5, 150, 0, 8, 8, 6, 3, 62, 88, 45, 11, 255,
+        125, 64, 14, 255, 123, 60, 14, 255, 118, 56, 15, 255, 120, 61, 17,
+        255, 136, 67, 21, 255, 118, 57, 17, 255, 96, 48, 13, 255, 92, 47,
+        11, 255, 18, 12, 5, 85, 0, 8, 9, 7, 4, 79, 104, 51, 15, 255, 140,
+        66, 17, 255, 135, 66, 16, 255, 17, 12, 6, 198, 0, 20, 9, 7, 4, 85,
+        92, 47, 11, 255, 125, 66, 14, 255, 123, 65, 14, 255, 14, 10, 5, 150,
+        0, 8, 8, 6, 3, 65, 88, 45, 11, 255, 135, 66, 16, 255, 136, 67, 17,
+        255, 22, 14, 7, 198, 0, 12, 8, 6, 3, 119, 88, 45, 11, 255, 125, 64,
+        14, 255, 123, 60, 14, 255, 14, 10, 5, 159, 0, 12, 12, 10, 5, 210,
+        59, 31, 10, 255, 115, 62, 14, 255, 118, 60, 13, 255, 104, 54, 13,
+        255, 100, 50, 13, 255, 100, 50, 13, 255, 114, 58, 13, 255, 119, 63,
+        14, 255, 85, 43, 12, 255, 21, 15, 6, 255, 7, 5, 4, 40, 0, 8, 8, 6,
+        3, 74, 88, 45, 11, 255, 125, 66, 14, 255, 123, 60, 14, 255, 18, 12,
+        5, 170, 0, 44, 12, 10, 5, 227, 59, 31, 10, 255, 115, 62, 14, 255,
+        114, 58, 13, 255, 100, 50, 13, 255, 114, 56, 13, 255, 133, 66, 16,
+        255, 160, 80, 21, 255, 176, 83, 21, 255, 45, 27, 12, 255, 6, 5, 3,
+        170, 0, 12, 8, 6, 3, 82, 88, 45, 11, 255, 125, 66, 14, 255, 123, 60,
+        14, 255, 18, 12, 5, 170, 0, 12, 9, 7, 4, 85, 92, 47, 11, 255, 131,
+        61, 14, 255, 126, 62, 15, 255, 17, 11, 6, 170, 0, 12, 14, 10, 5,
+        227, 65, 33, 10, 255, 115, 59, 14, 255, 115, 62, 14, 255, 93, 50,
+        12, 255, 88, 44, 11, 255, 92, 47, 11, 255, 104, 54, 13, 255, 119,
+        58, 14, 255, 85, 43, 12, 255, 21, 15, 6, 255, 7, 6, 4, 57, 0, 24, 9,
+        7, 4, 85, 92, 47, 11, 255, 125, 66, 14, 255, 123, 60, 14, 255, 18,
+        12, 5, 170, 0, 24, 5, 5, 4, 28, 19, 13, 6, 255, 84, 42, 11, 255,
+        115, 62, 14, 255, 110, 59, 13, 255, 93, 50, 12, 255, 84, 44, 11,
+        255, 106, 54, 15, 255, 176, 84, 23, 255, 199, 100, 28, 255, 188,
+        101, 31, 255, 90, 54, 25, 255, 13, 10, 8, 142, 0, 24, 8, 6, 3, 164,
+        72, 37, 11, 255, 131, 66, 14, 255, 110, 54, 13, 255, 12, 9, 5, 224,
+        3, 3, 2, 17, 0, 24, 7, 6, 6, 85, 30, 20, 13, 255, 190, 96, 27, 255,
+        199, 98, 24, 255, 121, 69, 22, 255, 13, 10, 6, 190, 4, 3, 3, 28, 5,
+        4, 2, 105, 27, 17, 6, 255, 114, 56, 13, 255, 125, 64, 14, 255, 45,
+        26, 10, 255, 8, 7, 5, 153, 0, 12, 10, 7, 5, 85, 96, 48, 13, 255,
+        125, 64, 14, 255, 123, 60, 14, 255, 16, 11, 5, 195, 0, 12, 8, 6, 3,
+        110, 92, 47, 11, 255, 131, 66, 14, 255, 123, 65, 14, 255, 18, 13, 5,
+        170, 0, 24, 9, 7, 4, 85, 92, 47, 11, 255, 125, 66, 14, 255, 123, 60,
+        14, 255, 18, 12, 5, 170, 0, 24, 8, 7, 3, 99, 93, 50, 12, 255, 125,
+        66, 14, 255, 115, 59, 14, 255, 104, 54, 13, 255, 88, 45, 11, 255,
+        88, 44, 11, 255, 92, 43, 11, 255, 92, 43, 11, 255, 92, 43, 11, 255,
+        93, 50, 12, 255, 93, 50, 12, 255, 20, 13, 5, 85, 0, 8, 8, 6, 3, 65,
+        88, 45, 11, 255, 125, 64, 14, 255, 123, 60, 14, 255, 115, 62, 14,
+        255, 93, 46, 12, 255, 16, 11, 5, 127, 0, 28, 5, 4, 4, 28, 12, 10, 5,
+        246, 104, 54, 13, 255, 115, 59, 14, 255, 39, 23, 8, 255, 8, 6, 3,
+        82, 0, 12, 58, 31, 9, 255, 114, 58, 13, 255, 119, 63, 14, 255, 123,
+        60, 14, 255, 123, 65, 14, 255, 18, 12, 5, 170, 0, 144, 14, 10, 5,
+        227, 59, 31, 10, 255, 115, 62, 14, 255, 110, 59, 13, 255, 88, 44,
+        11, 255, 80, 42, 11, 255, 88, 44, 11, 255, 104, 54, 13, 255, 115,
+        59, 14, 255, 123, 60, 14, 255, 123, 60, 14, 255, 16, 11, 5, 150, 0,
+        8, 8, 6, 3, 65, 88, 44, 11, 255, 125, 64, 14, 255, 123, 60, 14, 255,
+        114, 58, 13, 255, 93, 50, 12, 255, 88, 44, 11, 255, 92, 47, 11, 255,
+        104, 54, 13, 255, 119, 58, 14, 255, 85, 43, 12, 255, 21, 15, 6, 255,
+        7, 6, 4, 51, 0, 12, 12, 9, 5, 224, 63, 32, 10, 255, 115, 62, 14,
+        255, 114, 56, 13, 255, 93, 50, 12, 255, 88, 44, 11, 255, 88, 45, 11,
+        255, 110, 59, 13, 255, 119, 61, 14, 255, 85, 43, 12, 255, 25, 16, 6,
+        255, 7, 6, 4, 57, 0, 12, 12, 10, 5, 221, 59, 31, 10, 255, 115, 62,
+        14, 255, 114, 56, 13, 255, 93, 50, 12, 255, 88, 44, 11, 255, 92, 47,
+        11, 255, 104, 54, 13, 255, 115, 59, 14, 255, 123, 60, 14, 255, 121,
+        62, 14, 255, 16, 11, 5, 167, 0, 12, 12, 10, 5, 218, 59, 31, 10, 255,
+        115, 62, 14, 255, 110, 59, 13, 255, 88, 44, 11, 255, 80, 42, 11,
+        255, 88, 44, 11, 255, 88, 45, 11, 255, 88, 44, 11, 255, 16, 11, 5,
+        105, 0, 24, 9, 7, 4, 85, 92, 47, 11, 255, 125, 66, 14, 255, 123, 60,
+        14, 255, 18, 12, 5, 170, 0, 48, 7, 5, 4, 198, 93, 50, 12, 255, 125,
+        66, 14, 255, 123, 60, 14, 255, 12, 10, 5, 170, 0, 8, 8, 6, 3, 65,
+        88, 45, 11, 255, 125, 66, 14, 255, 123, 65, 14, 255, 18, 12, 5, 170,
+        0, 12, 9, 7, 4, 85, 92, 47, 11, 255, 125, 66, 14, 255, 123, 65, 14,
+        255, 14, 10, 5, 150, 0, 8, 8, 6, 3, 65, 88, 45, 11, 255, 125, 66,
+        14, 255, 123, 60, 14, 255, 18, 13, 5, 170, 0, 20, 3, 3, 2, 11, 9, 7,
+        4, 227, 100, 50, 13, 255, 123, 60, 14, 255, 123, 60, 14, 255, 12,
+        10, 5, 170, 0, 8, 8, 6, 3, 62, 88, 45, 11, 255, 125, 66, 14, 255,
+        123, 60, 14, 255, 14, 10, 5, 198, 0, 8, 8, 6, 3, 170, 35, 22, 8,
+        255, 115, 59, 14, 255, 112, 55, 13, 255, 33, 21, 8, 255, 8, 6, 3,
+        37, 0, 8, 8, 6, 3, 74, 88, 45, 11, 255, 125, 66, 14, 255, 123, 65,
+        14, 255, 14, 10, 5, 150, 0, 8, 8, 6, 3, 65, 88, 45, 11, 255, 125,
+        66, 14, 255, 123, 65, 14, 255, 14, 11, 5, 147, 0, 4, 9, 7, 4, 85,
+        92, 47, 11, 255, 20, 13, 5, 170, 0, 4, 8, 6, 3, 62, 88, 45, 11, 255,
+        125, 66, 14, 255, 123, 65, 14, 255, 14, 10, 5, 150, 0, 8, 8, 6, 3,
+        65, 88, 45, 11, 255, 125, 66, 14, 255, 123, 60, 14, 255, 18, 12, 5,
+        170, 0, 12, 9, 7, 4, 85, 92, 47, 11, 255, 125, 66, 14, 255, 123, 60,
+        14, 255, 14, 10, 5, 159, 0, 12, 12, 10, 5, 210, 59, 31, 10, 255,
+        115, 59, 14, 255, 118, 60, 13, 255, 104, 54, 13, 255, 102, 51, 13,
+        255, 112, 53, 13, 255, 122, 63, 15, 255, 123, 58, 14, 255, 85, 43,
+        12, 255, 21, 15, 6, 255, 7, 5, 4, 45, 0, 8, 8, 6, 3, 85, 113, 55,
+        16, 255, 196, 92, 23, 255, 195, 96, 24, 255, 25, 17, 10, 255, 4, 3,
+        3, 79, 0, 64, 3, 2, 2, 28, 10, 8, 5, 227, 138, 71, 21, 255, 177, 87,
+        20, 255, 174, 86, 21, 255, 24, 16, 9, 170, 0, 8, 13, 10, 8, 85, 142,
+        73, 23, 255, 195, 96, 24, 255, 194, 91, 23, 255, 24, 17, 11, 227, 0,
+        44, 12, 9, 5, 150, 35, 22, 8, 255, 80, 42, 11, 255, 84, 44, 11, 255,
+        88, 44, 11, 255, 80, 42, 11, 255, 88, 44, 11, 255, 97, 50, 12, 255,
+        118, 60, 13, 255, 85, 43, 12, 255, 21, 15, 6, 255, 8, 6, 3, 57, 0,
+        16, 9, 7, 4, 85, 92, 47, 11, 255, 125, 66, 14, 255, 123, 60, 14,
+        255, 18, 12, 5, 170, 0, 16, 6, 5, 5, 28, 17, 13, 8, 227, 68, 34, 11,
+        255, 115, 59, 14, 255, 110, 59, 13, 255, 93, 50, 12, 255, 88, 44,
+        11, 255, 92, 47, 11, 255, 104, 54, 13, 255, 115, 59, 14, 255, 123,
+        60, 14, 255, 123, 65, 14, 255, 18, 12, 5, 170, 0, 24, 12, 9, 7, 170,
+        131, 69, 24, 255, 191, 90, 22, 255, 136, 71, 19, 255, 15, 11, 6,
+        227, 4, 3, 3, 17, 0, 24, 7, 6, 4, 31, 16, 11, 5, 227, 104, 52, 13,
+        255, 131, 66, 14, 255, 98, 49, 13, 255, 10, 8, 5, 193, 3, 2, 2, 68,
+        8, 7, 5, 170, 121, 66, 26, 255, 195, 96, 24, 255, 156, 74, 19, 255,
+        34, 21, 9, 255, 9, 7, 4, 85, 0, 12, 8, 6, 3, 51, 69, 35, 10, 255,
+        121, 62, 14, 255, 123, 60, 14, 255, 16, 11, 5, 227, 4, 3, 3, 28, 0,
+        8, 8, 6, 3, 170, 92, 47, 11, 255, 125, 64, 14, 255, 108, 55, 13,
+        255, 14, 10, 5, 164, 0, 40, 7, 5, 4, 198, 96, 48, 13, 255, 134, 65,
+        15, 255, 133, 66, 16, 255, 15, 11, 6, 170, 0, 8, 7, 5, 4, 85, 78,
+        39, 11, 255, 130, 64, 15, 255, 130, 64, 15, 255, 134, 65, 15, 255,
+        136, 67, 17, 255, 124, 62, 17, 255, 114, 56, 17, 255, 113, 55, 16,
+        255, 118, 60, 17, 255, 107, 55, 20, 255, 48, 29, 15, 255, 12, 10, 7,
+        85, 0, 20, 9, 8, 6, 170, 45, 27, 12, 255, 139, 70, 20, 255, 131, 66,
+        18, 255, 107, 53, 14, 255, 19, 13, 6, 99, 0, 8, 8, 6, 5, 85, 92, 46,
+        13, 255, 131, 61, 14, 255, 125, 64, 14, 255, 14, 10, 5, 170, 0, 12,
+        58, 31, 9, 255, 110, 59, 13, 255, 115, 59, 14, 255, 56, 29, 9, 255,
+        10, 8, 5, 227, 5, 4, 4, 23, 0, 108, 10, 8, 7, 28, 28, 18, 11, 212,
+        49, 28, 16, 255, 35, 21, 12, 241, 13, 10, 6, 85, 0, 68, 14, 10, 5,
+        142, 20, 14, 5, 170, 16, 12, 5, 164, 8, 6, 3, 28, 0, 8, 24, 16, 9,
+        142, 21, 15, 8, 252, 23, 15, 8, 184, 11, 8, 6, 34, 0, 36, 14, 10, 5,
+        142, 20, 14, 5, 170, 16, 11, 5, 170, 10, 8, 5, 28, 0, 24, 7, 6, 4,
+        25, 20, 13, 7, 147, 22, 15, 7, 170, 10, 8, 5, 142, 5, 4, 4, 3, 0,
+        24, 14, 10, 5, 142, 20, 13, 5, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0,
+        16, 7, 5, 4, 28, 14, 10, 5, 156, 14, 10, 5, 229, 24, 15, 9, 255, 32,
+        20, 11, 255, 28, 18, 11, 244, 12, 9, 7, 108, 0, 8, 10, 8, 5, 142,
+        19, 13, 8, 235, 24, 15, 7, 227, 10, 8, 5, 59, 0, 48, 10, 8, 5, 93,
+        23, 15, 8, 170, 28, 18, 9, 173, 15, 11, 6, 28, 0, 12, 18, 12, 5,
+        142, 21, 14, 6, 170, 9, 7, 4, 133, 0, 148, 8, 6, 5, 113, 89, 44, 14,
+        255, 100, 51, 21, 255, 13, 10, 8, 227, 6, 5, 5, 28, 0, 60, 6, 5, 5,
+        8, 17, 12, 6, 142, 26, 16, 7, 170, 18, 12, 5, 170, 9, 7, 4, 28, 0,
+        8, 6, 5, 3, 85, 54, 28, 11, 255, 136, 66, 19, 255, 121, 59, 18, 255,
+        15, 10, 6, 241, 0, 40, 8, 6, 3, 57, 12, 9, 5, 170, 18, 13, 5, 178,
+        14, 10, 5, 241, 14, 10, 5, 255, 14, 10, 5, 252, 16, 11, 5, 195, 16,
+        11, 5, 170, 8, 6, 3, 113, 0, 24, 8, 6, 5, 28, 24, 16, 9, 204, 24,
+        17, 9, 255, 17, 12, 6, 210, 14, 10, 5, 170, 16, 11, 5, 170, 17, 11,
+        6, 246, 27, 17, 10, 246, 14, 10, 7, 85, 0, 16, 8, 6, 5, 28, 21, 14,
+        10, 195, 22, 15, 11, 255, 18, 13, 9, 255, 18, 13, 9, 255, 22, 15, 9,
+        255, 19, 13, 8, 255, 17, 12, 6, 255, 17, 11, 6, 255, 15, 11, 6, 255,
+        17, 12, 6, 255, 19, 13, 6, 204, 12, 9, 5, 28, 0, 12, 5, 4, 2, 25, 8,
+        6, 3, 122, 14, 10, 5, 170, 18, 13, 5, 176, 14, 10, 5, 235, 15, 11,
+        6, 255, 15, 11, 6, 255, 19, 12, 6, 204, 19, 13, 6, 170, 10, 8, 5,
+        170, 8, 6, 5, 57, 0, 48, 14, 10, 5, 142, 21, 13, 6, 170, 16, 11, 5,
+        170, 9, 7, 4, 28, 0, 12, 5, 4, 2, 25, 8, 6, 3, 125, 14, 10, 5, 170,
+        14, 10, 5, 210, 23, 15, 8, 255, 30, 20, 11, 255, 30, 20, 11, 255,
+        23, 17, 10, 255, 20, 14, 9, 244, 16, 12, 9, 170, 9, 8, 6, 79, 0, 16,
+        9, 7, 6, 65, 15, 11, 8, 170, 17, 12, 8, 232, 21, 14, 8, 255, 26, 16,
+        9, 255, 23, 15, 8, 255, 21, 14, 8, 255, 15, 11, 6, 255, 22, 15, 7,
+        178, 11, 9, 6, 170, 10, 8, 7, 57, 0, 32, 12, 10, 5, 142, 20, 13, 5,
+        170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 28, 5, 5, 4, 28, 8, 6, 3, 133,
+        15, 11, 6, 193, 20, 15, 9, 255, 28, 18, 11, 255, 30, 20, 11, 255,
+        26, 16, 9, 255, 14, 10, 5, 238, 16, 11, 5, 170, 9, 7, 4, 153, 7, 5,
+        4, 57, 0, 16, 5, 4, 2, 28, 8, 6, 3, 142, 18, 12, 7, 207, 22, 15, 9,
+        255, 28, 18, 11, 255, 27, 18, 10, 255, 18, 13, 7, 255, 15, 11, 6,
+        227, 21, 13, 6, 170, 10, 7, 5, 164, 7, 6, 4, 57, 0, 16, 14, 10, 5,
+        142, 20, 13, 5, 170, 16, 12, 5, 170, 9, 7, 4, 28, 0, 8, 10, 8, 7,
+        119, 149, 64, 26, 255, 131, 63, 26, 255, 14, 11, 7, 227, 6, 5, 5,
+        28, 0, 32, 7, 5, 4, 28, 14, 10, 5, 156, 20, 13, 5, 170, 12, 9, 5,
+        142, 6, 5, 3, 6, 0, 64, 12, 10, 7, 142, 24, 15, 7, 170, 21, 13, 6,
+        170, 8, 6, 3, 76, 0, 48, 9, 7, 6, 85, 83, 43, 16, 255, 176, 88, 23,
+        255, 130, 62, 21, 255, 16, 11, 7, 170, 0, 28, 9, 8, 6, 28, 13, 10,
+        8, 164, 23, 16, 10, 190, 16, 11, 7, 252, 15, 11, 6, 255, 14, 10, 5,
+        255, 14, 10, 5, 255, 14, 10, 5, 255, 16, 11, 5, 232, 14, 10, 5, 170,
+        8, 6, 3, 85, 0, 16, 14, 10, 5, 142, 21, 13, 6, 170, 16, 11, 5, 170,
+        9, 7, 4, 28, 0, 16, 14, 10, 5, 142, 20, 13, 5, 170, 16, 11, 5, 170,
+        9, 7, 4, 28, 0, 12, 14, 10, 5, 136, 16, 12, 5, 170, 16, 11, 5, 170,
+        18, 12, 5, 170, 16, 11, 5, 210, 14, 10, 5, 255, 14, 10, 5, 249, 16,
+        12, 5, 193, 16, 11, 5, 170, 9, 7, 4, 153, 7, 5, 4, 57, 0, 16, 5, 5,
+        4, 28, 8, 6, 3, 125, 14, 10, 5, 170, 18, 12, 5, 176, 14, 10, 5, 238,
+        14, 10, 5, 246, 16, 12, 5, 195, 18, 13, 5, 170, 16, 11, 5, 170, 9,
+        7, 4, 150, 7, 5, 4, 54, 0, 16, 14, 10, 5, 142, 16, 12, 5, 170, 16,
+        11, 5, 170, 18, 12, 5, 170, 16, 11, 5, 210, 14, 10, 5, 255, 14, 10,
+        5, 249, 16, 12, 5, 193, 16, 11, 5, 170, 9, 7, 4, 153, 7, 6, 4, 57,
+        0, 16, 14, 10, 5, 142, 16, 12, 5, 170, 16, 11, 5, 170, 18, 12, 5,
+        170, 16, 11, 5, 210, 14, 10, 5, 252, 12, 9, 5, 255, 16, 11, 5, 255,
+        20, 13, 5, 201, 11, 9, 4, 28, 0, 12, 14, 10, 5, 139, 20, 13, 5, 170,
+        16, 11, 5, 170, 9, 7, 4, 28, 0, 36, 5, 5, 4, 28, 8, 6, 3, 125, 14,
+        10, 5, 170, 18, 13, 5, 176, 14, 10, 5, 238, 14, 10, 5, 255, 16, 11,
+        5, 235, 18, 13, 5, 173, 16, 11, 5, 170, 16, 12, 5, 170, 16, 11, 5,
+        164, 9, 7, 4, 28, 0, 12, 12, 9, 5, 142, 21, 13, 6, 170, 16, 11, 5,
+        170, 9, 7, 4, 28, 0, 16, 14, 10, 5, 142, 20, 13, 5, 170, 16, 11, 5,
+        170, 9, 7, 4, 28, 0, 12, 12, 9, 5, 142, 21, 13, 6, 170, 16, 11, 5,
+        170, 9, 7, 4, 28, 0, 12, 6, 5, 3, 28, 8, 7, 5, 139, 19, 13, 8, 193,
+        21, 15, 10, 255, 31, 21, 12, 255, 32, 21, 13, 255, 31, 20, 12, 255,
+        23, 17, 10, 255, 18, 12, 7, 212, 10, 8, 5, 159, 7, 6, 4, 57, 0, 16,
+        14, 10, 5, 142, 21, 13, 6, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 16,
+        14, 10, 5, 142, 21, 13, 6, 170, 16, 12, 5, 170, 9, 7, 4, 28, 0, 12,
+        14, 10, 5, 136, 16, 12, 5, 170, 16, 11, 5, 170, 18, 12, 5, 176, 17,
+        12, 6, 252, 21, 14, 8, 255, 17, 12, 6, 255, 16, 11, 5, 255, 20, 13,
+        5, 204, 11, 9, 4, 28, 0, 12, 14, 10, 5, 142, 21, 14, 6, 170, 18, 12,
+        5, 170, 9, 8, 4, 28, 0, 24, 14, 10, 5, 142, 20, 13, 5, 170, 16, 11,
+        5, 170, 9, 7, 4, 28, 0, 12, 12, 9, 5, 142, 21, 13, 6, 170, 16, 12,
+        5, 170, 10, 8, 5, 28, 0, 16, 12, 9, 5, 142, 20, 13, 5, 170, 16, 11,
+        5, 170, 9, 7, 4, 28, 0, 12, 5, 5, 4, 28, 8, 6, 3, 125, 14, 10, 5,
+        170, 18, 12, 5, 170, 20, 14, 5, 173, 16, 12, 5, 193, 20, 13, 5, 178,
+        20, 13, 5, 170, 16, 11, 5, 170, 9, 7, 4, 153, 7, 6, 4, 57, 0, 16,
+        14, 10, 5, 142, 21, 13, 6, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 44,
+        5, 5, 4, 28, 8, 6, 3, 125, 14, 10, 5, 170, 18, 13, 5, 170, 20, 14,
+        5, 170, 18, 12, 5, 170, 13, 10, 6, 227, 72, 38, 19, 255, 185, 86,
+        32, 255, 144, 64, 29, 255, 20, 15, 11, 232, 8, 7, 7, 28, 0, 12, 14,
+        10, 5, 142, 21, 13, 6, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 16, 14,
+        10, 5, 142, 20, 13, 5, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 12, 5,
+        4, 2, 25, 8, 6, 3, 122, 14, 10, 5, 170, 18, 13, 5, 176, 14, 10, 5,
+        238, 14, 10, 5, 255, 14, 10, 5, 249, 16, 12, 5, 193, 16, 11, 5, 170,
+        9, 7, 4, 153, 7, 5, 4, 57, 0, 32, 14, 10, 5, 142, 21, 13, 6, 170,
+        16, 11, 5, 170, 9, 7, 4, 28, 0, 28, 8, 6, 3, 57, 9, 7, 4, 164, 14,
+        10, 5, 170, 18, 13, 5, 173, 14, 10, 5, 229, 14, 10, 5, 255, 17, 12,
+        6, 255, 22, 15, 9, 255, 20, 14, 9, 252, 21, 15, 10, 176, 11, 9, 6,
+        139, 0, 32, 11, 8, 4, 122, 18, 12, 5, 170, 14, 10, 5, 150, 7, 5, 4,
+        28, 0, 32, 8, 7, 7, 57, 24, 16, 11, 173, 26, 18, 9, 190, 13, 10, 6,
+        142, 5, 4, 4, 11, 0, 8, 8, 7, 3, 68, 14, 10, 5, 170, 16, 11, 5, 170,
+        9, 7, 4, 74, 0, 20, 14, 10, 5, 142, 20, 14, 5, 170, 16, 11, 5, 170,
+        9, 7, 4, 28, 0, 16, 14, 10, 5, 142, 20, 14, 5, 170, 16, 11, 5, 170,
+        9, 8, 4, 28, 0, 28, 14, 10, 5, 142, 20, 13, 5, 170, 16, 11, 5, 170,
+        9, 7, 4, 28, 0, 28, 14, 10, 5, 142, 18, 13, 5, 170, 16, 12, 5, 170,
+        18, 13, 5, 173, 14, 10, 5, 227, 14, 10, 5, 255, 14, 10, 5, 252, 12,
+        9, 5, 255, 12, 9, 5, 255, 16, 11, 5, 255, 20, 13, 5, 201, 11, 9, 4,
+        28, 0, 12, 12, 10, 5, 136, 16, 12, 5, 170, 16, 11, 5, 170, 16, 11,
+        5, 193, 21, 15, 6, 184, 14, 10, 5, 31, 0, 32, 8, 6, 3, 139, 54, 30,
+        9, 255, 107, 50, 12, 255, 78, 39, 11, 255, 9, 7, 4, 161, 0, 12, 20,
+        13, 5, 142, 18, 12, 5, 210, 16, 11, 5, 170, 16, 11, 5, 170, 16, 11,
+        5, 170, 9, 7, 4, 28, 0, 64, 13, 10, 8, 57, 9, 7, 6, 159, 8, 6, 5,
+        159, 10, 8, 7, 130, 10, 8, 7, 119, 9, 7, 6, 133, 9, 7, 6, 167, 10,
+        8, 7, 170, 11, 9, 8, 113, 0, 44, 5, 4, 2, 28, 8, 6, 3, 125, 14, 10,
+        5, 170, 18, 13, 5, 176, 14, 10, 5, 238, 14, 10, 5, 255, 16, 11, 5,
+        235, 18, 13, 5, 173, 16, 11, 5, 170, 16, 12, 5, 170, 16, 11, 5, 164,
+        9, 7, 4, 28, 0, 12, 14, 10, 5, 136, 16, 12, 5, 170, 16, 11, 5, 170,
+        18, 12, 5, 170, 16, 11, 5, 210, 14, 10, 5, 255, 14, 10, 5, 249, 16,
+        12, 5, 193, 16, 11, 5, 170, 9, 7, 4, 153, 7, 5, 4, 57, 0, 16, 5, 5,
+        4, 28, 8, 6, 3, 125, 14, 10, 5, 170, 18, 13, 5, 176, 14, 10, 5, 238,
+        14, 10, 5, 255, 14, 10, 5, 249, 16, 11, 5, 193, 16, 11, 5, 170, 9,
+        7, 4, 150, 7, 5, 4, 57, 0, 16, 5, 5, 4, 28, 8, 6, 3, 125, 14, 10, 5,
+        170, 18, 13, 5, 176, 14, 10, 5, 238, 14, 10, 5, 255, 14, 10, 5, 235,
+        18, 13, 5, 173, 16, 11, 5, 170, 16, 12, 5, 170, 16, 11, 5, 170, 9,
+        7, 4, 28, 0, 12, 5, 5, 4, 28, 8, 6, 3, 125, 14, 10, 5, 170, 18, 13,
+        5, 176, 14, 10, 5, 235, 14, 10, 5, 255, 14, 10, 5, 255, 16, 11, 5,
+        255, 20, 13, 5, 207, 12, 9, 5, 34, 0, 28, 14, 10, 5, 142, 20, 13, 5,
+        170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 28, 6, 5, 3, 85, 7, 5, 4, 85,
+        6, 5, 3, 85, 5, 4, 4, 85, 5, 4, 4, 105, 9, 8, 4, 241, 72, 37, 11,
+        255, 110, 54, 13, 255, 67, 34, 10, 255, 8, 6, 3, 144, 0, 12, 14, 10,
+        5, 142, 21, 14, 6, 170, 16, 12, 5, 170, 9, 8, 4, 28, 0, 16, 14, 10,
+        5, 142, 21, 13, 6, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 12, 12, 9,
+        5, 142, 21, 13, 6, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 12, 7, 5, 2,
+        37, 8, 6, 3, 142, 8, 6, 3, 227, 25, 15, 6, 255, 75, 36, 10, 255, 99,
+        51, 12, 255, 66, 33, 9, 255, 8, 6, 3, 130, 0, 12, 14, 10, 5, 139,
+        21, 13, 6, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 12, 8, 6, 3, 79, 14,
+        10, 5, 170, 18, 13, 5, 170, 12, 9, 5, 142, 0, 16, 14, 10, 5, 142,
+        21, 13, 6, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 12, 12, 9, 5, 142,
+        21, 13, 6, 170, 16, 11, 5, 170, 9, 7, 4, 28, 0, 8, 20, 13, 5, 85,
+        11, 8, 4, 28, 0, 8, 12, 9, 5, 142, 21, 13, 6, 170, 16, 11, 5, 170,
+        9, 7, 4, 28, 0, 12, 12, 9, 5, 142, 21, 13, 6, 170, 16, 11, 5, 170,
+        9, 7, 4, 28, 0, 16, 14, 10, 5, 142, 20, 13, 5, 170, 16, 11, 5, 170,
+        9, 7, 4, 28, 0, 12, 5, 5, 4, 28, 8, 6, 3, 125, 14, 10, 5, 170, 18,
+        12, 5, 170, 20, 14, 5, 173, 16, 12, 5, 193, 20, 13, 5, 178, 20, 13,
+        5, 170, 16, 11, 5, 170, 9, 7, 4, 161, 7, 6, 4, 57, 0, 12, 8, 6, 3,
+        85, 84, 40, 13, 255, 164, 73, 23, 255, 184, 79, 27, 255, 15, 11, 8,
+        246, 0, 72, 11, 10, 10, 170, 176, 83, 37, 255, 196, 87, 33, 255,
+        192, 88, 31, 255, 22, 15, 11, 193, 0, 12, 21, 15, 10, 159, 26, 17,
+        11, 255, 24, 17, 11, 221, 10, 8, 7, 85, 0, 44, 8, 7, 3, 59, 12, 9,
+        5, 170, 16, 11, 5, 210, 14, 10, 5, 255, 14, 10, 5, 255, 14, 10, 5,
+        255, 14, 10, 5, 246, 16, 12, 5, 193, 16, 11, 5, 170, 9, 7, 4, 153,
+        6, 5, 3, 57, 0, 24, 14, 10, 5, 142, 20, 13, 5, 170, 16, 11, 5, 170,
+        9, 7, 4, 28, 0, 20, 6, 5, 3, 28, 8, 6, 3, 127, 14, 10, 5, 170, 18,
+        13, 5, 176, 14, 10, 5, 238, 14, 10, 5, 255, 14, 10, 5, 235, 18, 13,
+        5, 173, 16, 11, 5, 170, 16, 12, 5, 170, 16, 11, 5, 170, 9, 7, 4, 28,
+        0, 28, 14, 11, 7, 142, 29, 19, 8, 170, 17, 11, 6, 159, 8, 6, 3, 28,
+        0, 32, 7, 5, 4, 28, 14, 10, 5, 150, 20, 13, 5, 170, 12, 9, 5, 142,
+        5, 4, 2, 14, 0, 8, 15, 11, 8, 142, 26, 18, 9, 178, 19, 13, 6, 170,
+        8, 6, 3, 68, 0, 20, 18, 12, 5, 142, 16, 11, 5, 238, 16, 11, 5, 170,
+        9, 7, 4, 28, 0, 16, 12, 9, 5, 142, 16, 11, 5, 215, 18, 13, 5, 187,
+        11, 9, 4, 28, 0, 16, 4, 4, 3, 6, 5, 4, 2, 82, 5, 4, 2, 85, 5, 4, 2,
+        85, 5, 4, 2, 85, 5, 4, 2, 99, 9, 7, 4, 241, 72, 37, 11, 255, 112,
+        53, 13, 255, 77, 39, 12, 255, 10, 8, 5, 170, 0, 12, 19, 13, 8, 184,
+        20, 14, 9, 255, 16, 11, 7, 255, 14, 11, 7, 255, 17, 12, 8, 255, 22,
+        15, 9, 255, 27, 17, 10, 255, 30, 19, 11, 255, 28, 18, 11, 255, 21,
+        15, 10, 255, 15, 12, 8, 198, 9, 7, 6, 28, 0, 24, 8, 6, 5, 91, 15,
+        11, 6, 170, 14, 11, 5, 238, 19, 13, 6, 198, 12, 9, 5, 28, 0, 8, 6,
+        5, 3, 85, 54, 29, 9, 255, 100, 48, 13, 255, 109, 52, 14, 255, 15,
+        11, 6, 170, 0, 12, 19, 13, 6, 144, 14, 10, 5, 255, 16, 11, 5, 178,
+        8, 6, 3, 119, 0, 255, 0, 255, 0, 174, 12, 9, 7, 88, 99, 44, 20, 255,
+        26, 16, 11, 232, 5, 4, 4, 28, 0, 92, 6, 5, 3, 57, 60, 28, 11, 255,
+        158, 67, 23, 255, 88, 44, 23, 255, 11, 9, 6, 142, 0, 255, 0, 255, 0,
+        150, 12, 9, 7, 110, 126, 51, 25, 255, 25, 17, 12, 232, 5, 4, 4, 28,
+        0, 184, 6, 5, 5, 28, 19, 14, 10, 227, 52, 29, 17, 255, 30, 20, 13,
+        255, 9, 8, 6, 82, 0, 255, 0, 255, 0, 255, 0, 255, 0, 8, 12, 10, 9,
+        170, 172, 81, 49, 255, 213, 125, 94, 255, 185, 88, 58, 255, 23, 16,
+        14, 159, 0, 255, 0, 255, 0, 106, 5, 4, 2, 28, 16, 11, 5, 244, 68,
+        34, 9, 255, 62, 33, 9, 255, 9, 8, 4, 139, 0, 96, 10, 8, 7, 48, 71,
+        33, 18, 255, 108, 47, 23, 255, 107, 48, 22, 255, 113, 51, 24, 255,
+        109, 50, 24, 255, 104, 45, 21, 255, 104, 45, 21, 255, 113, 49, 24,
+        255, 115, 50, 24, 255, 18, 13, 9, 136, 0, 255, 0, 129, 9, 7, 6, 34,
+        18, 13, 9, 244, 66, 31, 15, 255, 84, 37, 17, 255, 83, 36, 16, 255,
+        75, 34, 14, 255, 73, 35, 14, 255, 91, 41, 16, 255, 110, 47, 19, 255,
+        79, 40, 16, 255, 24, 16, 9, 255, 8, 6, 5, 57, 0, 100, 22, 14, 5,
+        244, 40, 23, 7, 255, 42, 23, 7, 255, 54, 28, 9, 255, 60, 31, 9, 255,
+        36, 22, 7, 255, 12, 9, 5, 244, 6, 5, 3, 28, 0, 255, 0, 29, 9, 7, 6,
+        85, 72, 34, 13, 255, 126, 56, 21, 255, 148, 63, 25, 255, 25, 17, 14,
+        190, 0, 72, 15, 12, 12, 133, 178, 86, 57, 255, 200, 89, 55, 255,
+        194, 82, 47, 255, 30, 20, 17, 187, 0, 255, 0, 169, 9, 7, 4, 99, 17,
+        12, 6, 255, 42, 22, 9, 255, 49, 25, 9, 255, 54, 26, 11, 255, 52, 26,
+        11, 255, 59, 28, 12, 255, 82, 37, 15, 255, 111, 49, 18, 255, 84, 39,
+        17, 255, 25, 17, 10, 255, 8, 7, 5, 57, 0, 112, 6, 5, 3, 57, 38, 22,
+        7, 255, 85, 39, 12, 255, 124, 52, 21, 255, 20, 13, 9, 170, 0, 255,
+        0, 255, 0, 202, 8, 6, 5, 28, 26, 16, 11, 170, 11, 8, 6, 85, 0, 100,
+        12, 8, 5, 119, 20, 14, 9, 170, 12, 9, 7, 142, 0, 255, 0, 255, 0,
+        154, 9, 7, 6, 28, 27, 17, 12, 170, 11, 9, 8, 85, 0, 192, 7, 6, 6,
+        28, 8, 7, 5, 85, 8, 6, 5, 57, 0, 255, 0, 255, 0, 255, 0, 255, 0, 16,
+        25, 17, 16, 161, 41, 27, 26, 255, 40, 26, 23, 235, 14, 12, 11, 82,
+        0, 255, 0, 255, 0, 110, 8, 6, 3, 37, 9, 7, 4, 142, 9, 7, 4, 136, 6,
+        5, 3, 6, 0, 100, 23, 15, 10, 153, 19, 13, 10, 255, 16, 11, 9, 255,
+        16, 11, 9, 255, 16, 11, 9, 255, 16, 11, 9, 255, 16, 11, 9, 255, 18,
+        13, 9, 255, 24, 16, 11, 204, 16, 11, 9, 31, 0, 255, 0, 133, 10, 8,
+        7, 142, 18, 12, 9, 207, 18, 13, 9, 255, 16, 11, 9, 255, 15, 11, 8,
+        255, 15, 11, 8, 252, 18, 13, 9, 195, 18, 12, 9, 170, 11, 8, 6, 167,
+        8, 7, 5, 57, 0, 104, 9, 8, 4, 142, 14, 10, 5, 170, 13, 10, 6, 170,
+        13, 9, 6, 170, 11, 8, 6, 170, 7, 6, 4, 130, 6, 5, 3, 28, 0, 255, 0,
+        37, 14, 10, 7, 142, 21, 14, 10, 170, 19, 13, 10, 170, 14, 11, 9, 31,
+        0, 72, 8, 7, 8, 14, 25, 17, 16, 142, 27, 18, 16, 193, 26, 18, 15,
+        170, 15, 11, 10, 34, 0, 255, 0, 169, 9, 7, 4, 28, 11, 8, 6, 170, 14,
+        10, 7, 232, 15, 10, 8, 255, 15, 10, 8, 255, 15, 10, 8, 255, 15, 10,
+        8, 252, 18, 12, 9, 195, 18, 12, 9, 170, 11, 8, 6, 167, 9, 7, 6, 57,
+        0, 120, 9, 7, 4, 91, 16, 11, 7, 170, 20, 13, 9, 170, 13, 10, 8, 28,
+        0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
+        255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
+        0, 255, 0, 255, 0, 255}};
+ /* Created by MiniCompress.. an iOS RLE compressor.
+  * Compress Rate : 46.36 %
+  */
diff --git a/gst/goom/gfontrle.h b/gst/goom/gfontrle.h
new file mode 100644 (file)
index 0000000..41e2462
--- /dev/null
@@ -0,0 +1,7 @@
+extern const struct {
+       unsigned int width;
+       unsigned int height;
+       unsigned int bytes_per_pixel;
+       unsigned int rle_size;
+       unsigned char rle_pixel [49725];
+} the_font ;
diff --git a/gst/goom/goom.h b/gst/goom/goom.h
new file mode 100644 (file)
index 0000000..b0ddab1
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _GOOMCORE_H
+#define _GOOMCORE_H
+
+#include "goom_config.h"
+#include "goom_plugin_info.h"
+#include "goomsl.h"
+
+#define NB_FX 10
+
+PluginInfo *goom_init (guint32 resx, guint32 resy);
+void goom_set_resolution (PluginInfo *goomInfo, guint32 resx, guint32 resy);
+
+/*
+ * forceMode == 0 : do nothing
+ * forceMode == -1 : lock the FX
+ * forceMode == 1..NB_FX : force a switch to FX n# forceMode
+ *
+ * songTitle = pointer to the title of the song...
+ *      - NULL if it is not the start of the song
+ *      - only have a value at the start of the song
+ */
+guint32 *goom_update (PluginInfo *goomInfo, gint16 data[2][512], int forceMode, float fps,
+                      char *songTitle, char *message);
+
+/* returns 0 if the buffer wasn't accepted */
+int goom_set_screenbuffer(PluginInfo *goomInfo, void *buffer);
+
+void goom_close (PluginInfo *goomInfo);
+
+#endif
diff --git a/gst/goom/goom_config.h b/gst/goom/goom_config.h
new file mode 100644 (file)
index 0000000..5f6f158
--- /dev/null
@@ -0,0 +1,28 @@
+#if WORDS_BIGENDIAN
+#define COLOR_ARGB
+#else
+#define COLOR_BGRA
+#endif
+
+#if 1
+/* ndef COLOR_BGRA */
+/** position des composantes **/
+    #define BLEU 0
+    #define VERT 1
+    #define ROUGE 2
+    #define ALPHA 3
+#else
+    #define ROUGE 1
+    #define BLEU 3
+    #define VERT 2
+    #define ALPHA 0
+#endif
+
+#ifndef guint32
+#define guint8 unsigned char
+#define guin16 unsigned short
+#define guint32 unsigned int
+#define gint8 signed char
+#define gint16 signed short int
+#define gint32 signed int
+#endif
diff --git a/gst/goom/goom_config_param.h b/gst/goom/goom_config_param.h
new file mode 100644 (file)
index 0000000..3c6838d
--- /dev/null
@@ -0,0 +1,115 @@
+#ifndef _CONFIG_PARAM_H
+#define _CONFIG_PARAM_H
+
+#include <stdlib.h>
+
+/**
+ * File created on 2003-05-24 by Jeko.
+ * (c)2003, JC Hoelt for iOS-software.
+ *
+ * LGPL Licence.
+ */
+
+typedef enum {
+  PARAM_INTVAL,
+  PARAM_FLOATVAL,
+  PARAM_BOOLVAL,
+  PARAM_STRVAL,
+  PARAM_LISTVAL,
+} ParamType;
+
+struct IntVal {
+  int value;
+  int min;
+  int max;
+  int step;
+};
+struct FloatVal {
+  float value;
+  float min;
+  float max;
+  float step;
+};
+struct StrVal {
+  char *value;
+};
+struct ListVal {
+  char *value;
+  int nbChoices;
+  char **choices;
+};
+struct BoolVal {
+  int value;
+};
+
+
+typedef struct _PARAM {
+  char *name;
+  char *desc;
+  char rw;
+  ParamType type;
+  union {
+    struct IntVal ival;
+    struct FloatVal fval;
+    struct StrVal sval;
+    struct ListVal slist;
+    struct BoolVal bval;
+  } param;
+  
+  /* used by the core to inform the GUI of a change */
+  void (*change_listener)(struct _PARAM *_this);
+
+  /* used by the GUI to inform the core of a change */
+  void (*changed)(struct _PARAM *_this);
+  
+  void *user_data; /* can be used by the GUI */
+} PluginParam;
+
+#define IVAL(p) ((p).param.ival.value)
+#define SVAL(p) ((p).param.sval.value)
+#define FVAL(p) ((p).param.fval.value)
+#define BVAL(p) ((p).param.bval.value)
+#define LVAL(p) ((p).param.slist.value)
+
+#define FMIN(p) ((p).param.fval.min)
+#define FMAX(p) ((p).param.fval.max)
+#define FSTEP(p) ((p).param.fval.step)
+
+#define IMIN(p) ((p).param.ival.min)
+#define IMAX(p) ((p).param.ival.max)
+#define ISTEP(p) ((p).param.ival.step)
+
+PluginParam goom_secure_param(void);
+
+PluginParam goom_secure_f_param(char *name);
+PluginParam goom_secure_i_param(char *name);
+PluginParam goom_secure_b_param(char *name, int value);
+PluginParam goom_secure_s_param(char *name);
+
+PluginParam goom_secure_f_feedback(char *name);
+PluginParam goom_secure_i_feedback(char *name);
+
+void goom_set_str_param_value(PluginParam *p, const char *str);
+void goom_set_list_param_value(PluginParam *p, const char *str);
+    
+typedef struct _PARAMETERS {
+  char *name;
+  char *desc;
+  int nbParams;
+  PluginParam **params;
+} PluginParameters;
+
+PluginParameters goom_plugin_parameters(const char *name, int nb);
+
+#define secure_param goom_secure_param
+#define secure_f_param goom_secure_f_param
+#define secure_i_param goom_secure_i_param
+#define secure_b_param goom_secure_b_param
+#define secure_s_param goom_secure_s_param
+#define secure_f_feedback goom_secure_f_feedback
+#define secure_i_feedback goom_secure_i_feedback
+#define set_list_param_value goom_set_list_param_value
+#define set_str_param_value goom_set_str_param_value
+#define plugin_parameters goom_plugin_parameters
+
+#endif
index d66ffe25de238ccf1fbe0c93f3cb7351ac44106f..5dee8278d302f4e028496607698b476e660c782b 100644 (file)
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <glib.h>
-
+/**
+* file: goom_core.c
+ * author: Jean-Christophe Hoelt (which is not so proud of it)
+ *
+ * Contains the core of goom's work.
+ *
+ * (c)2000-2003, by iOS-software.
+ */
+
+#include <math.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "goom_core.h"
+#include <inttypes.h>
+
+#include "goom.h"
 #include "goom_tools.h"
-#include "filters.h"
+#include "goom_filters.h"
 #include "lines.h"
+#include "ifs.h"
+#include "tentacle3d.h"
+#include "gfontlib.h"
 
-/*#define VERBOSE */
+#include "sound_tester.h"
+#include "goom_plugin_info.h"
+#include "goom_fx.h"
+#include "goomsl.h"
 
-#ifdef VERBOSE
-#include <stdio.h>
-#endif
+/* #define VERBOSE */
 
 #define STOP_SPEED 128
+/* TODO: put that as variable in PluginInfo */
+#define TIME_BTW_CHG 300
 
-void
-goom_init (GoomData * goomdata, guint32 resx, guint32 resy)
+static void choose_a_goom_line (PluginInfo * goomInfo, float *param1,
+    float *param2, int *couleur, int *mode, float *amplitude, int far);
+
+static void update_message (PluginInfo * goomInfo, char *message);
+
+static void
+init_buffers (PluginInfo * goomInfo, int buffsize)
 {
+  goomInfo->pixel = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
+  bzero (goomInfo->pixel, buffsize * sizeof (guint32) + 128);
+  goomInfo->back = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
+  bzero (goomInfo->back, buffsize * sizeof (guint32) + 128);
+  goomInfo->conv = (Pixel *) malloc (buffsize * sizeof (guint32) + 128);
+  bzero (goomInfo->conv, buffsize * sizeof (guint32) + 128);
+
+  goomInfo->outputBuf = goomInfo->conv;
+
+  goomInfo->p1 = (Pixel *) ((1 + ((uintptr_t) (goomInfo->pixel)) / 128) * 128);
+  goomInfo->p2 = (Pixel *) ((1 + ((uintptr_t) (goomInfo->back)) / 128) * 128);
+}
+
+/**************************
+*         INIT           *
+**************************/
+PluginInfo *
+goom_init (guint32 resx, guint32 resy)
+{
+  PluginInfo *goomInfo = (PluginInfo *) malloc (sizeof (PluginInfo));
+
 #ifdef VERBOSE
   printf ("GOOM: init (%d, %d);\n", resx, resy);
 #endif
-  goomdata->resolx = 0;
-  goomdata->resoly = 0;
-  goomdata->buffsize = 0;
-
-  goomdata->pixel = NULL;
-  goomdata->back = NULL;
-  goomdata->p1 = NULL;
-  goomdata->p2 = NULL;
-
-  goom_set_resolution (goomdata, resx, resy);
-  RAND_INIT (goomdata, GPOINTER_TO_INT (goomdata->pixel));
-  goomdata->cycle = 0;
-
-
-  goomdata->goomlimit = 2;      /* sensibilité du goom */
-  goomdata->zfd = zoomFilterNew ();
-  goomdata->lockvar = 0;        /* pour empecher de nouveaux changements */
-  goomdata->goomvar = 0;        /* boucle des gooms */
-  goomdata->totalgoom = 0;      /* nombre de gooms par seconds */
-  goomdata->agoom = 0;          /* un goom a eu lieu..       */
-  goomdata->loopvar = 0;        /* mouvement des points */
-  goomdata->speedvar = 0;       /* vitesse des particules */
-  goomdata->lineMode = 0;       /* l'effet lineaire a dessiner */
+
+  plugin_info_init (goomInfo, 4);
+
+  goomInfo->star_fx = flying_star_create ();
+  goomInfo->star_fx.init (&goomInfo->star_fx, goomInfo);
+
+  goomInfo->zoomFilter_fx = zoomFilterVisualFXWrapper_create ();
+  goomInfo->zoomFilter_fx.init (&goomInfo->zoomFilter_fx, goomInfo);
+
+  goomInfo->tentacles_fx = tentacle_fx_create ();
+  goomInfo->tentacles_fx.init (&goomInfo->tentacles_fx, goomInfo);
+
+  goomInfo->convolve_fx = convolve_create ();
+  goomInfo->convolve_fx.init (&goomInfo->convolve_fx, goomInfo);
+
+  plugin_info_add_visual (goomInfo, 0, &goomInfo->zoomFilter_fx);
+  plugin_info_add_visual (goomInfo, 1, &goomInfo->tentacles_fx);
+  plugin_info_add_visual (goomInfo, 2, &goomInfo->star_fx);
+  plugin_info_add_visual (goomInfo, 3, &goomInfo->convolve_fx);
+
+  goomInfo->screen.width = resx;
+  goomInfo->screen.height = resy;
+  goomInfo->screen.size = resx * resy;
+
+  init_buffers (goomInfo, goomInfo->screen.size);
+  goomInfo->gRandom = goom_random_init ((uintptr_t) goomInfo->pixel);
+
+  goomInfo->cycle = 0;
+
+  goomInfo->ifs_fx = ifs_visualfx_create ();
+  goomInfo->ifs_fx.init (&goomInfo->ifs_fx, goomInfo);
+
+  goomInfo->gmline1 = goom_lines_init (goomInfo, resx, goomInfo->screen.height,
+      GML_HLINE, goomInfo->screen.height, GML_BLACK,
+      GML_CIRCLE, 0.4f * (float) goomInfo->screen.height, GML_VERT);
+  goomInfo->gmline2 = goom_lines_init (goomInfo, resx, goomInfo->screen.height,
+      GML_HLINE, 0, GML_BLACK,
+      GML_CIRCLE, 0.2f * (float) goomInfo->screen.height, GML_RED);
+
+  gfont_load ();
+
+  /* goom_set_main_script(goomInfo, goomInfo->main_script_str); */
+
+  return goomInfo;
 }
 
+
+
 void
-goom_set_resolution (GoomData * goomdata, guint32 resx, guint32 resy)
+goom_set_resolution (PluginInfo * goomInfo, guint32 resx, guint32 resy)
 {
-  guint32 buffsize = resx * resy;
-
-  if ((goomdata->resolx == resx) && (goomdata->resoly == resy))
-    return;
-
-  if (goomdata->buffsize < buffsize) {
-    if (goomdata->pixel)
-      free (goomdata->pixel);
-    if (goomdata->back)
-      free (goomdata->back);
-    goomdata->pixel = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
-    goomdata->back = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
-    goomdata->buffsize = buffsize;
-
-    goomdata->p1 =
-        (void *) (((unsigned long) goomdata->pixel + 0x7f) & (~0x7f));
-    goomdata->p2 = (void *) (((unsigned long) goomdata->back + 0x7f) & (~0x7f));
-  }
+  free (goomInfo->pixel);
+  free (goomInfo->back);
+  free (goomInfo->conv);
+
+  goomInfo->screen.width = resx;
+  goomInfo->screen.height = resy;
+  goomInfo->screen.size = resx * resy;
+
+  init_buffers (goomInfo, goomInfo->screen.size);
+
+  /* init_ifs (goomInfo, resx, goomInfo->screen.height); */
+  goomInfo->ifs_fx.free (&goomInfo->ifs_fx);
+  goomInfo->ifs_fx.init (&goomInfo->ifs_fx, goomInfo);
 
-  goomdata->resolx = resx;
-  goomdata->resoly = resy;
+  goom_lines_set_res (goomInfo->gmline1, resx, goomInfo->screen.height);
+  goom_lines_set_res (goomInfo->gmline2, resx, goomInfo->screen.height);
+}
 
-  memset (goomdata->pixel, 0, buffsize * sizeof (guint32) + 128);
-  memset (goomdata->back, 0, buffsize * sizeof (guint32) + 128);
+int
+goom_set_screenbuffer (PluginInfo * goomInfo, void *buffer)
+{
+  goomInfo->outputBuf = (Pixel *) buffer;
+  return 1;
 }
 
+/********************************************
+*                  UPDATE                  *
+********************************************
+
+* WARNING: this is a 600 lines function ! (21-11-2003)
+*/
 guint32 *
-goom_update (GoomData * goomdata, gint16 data[2][512])
+goom_update (PluginInfo * goomInfo, gint16 data[2][512],
+    int forceMode, float fps, char *songTitle, char *message)
 {
-  guint32 *return_val;
+  Pixel *return_val;
   guint32 pointWidth;
   guint32 pointHeight;
-  int incvar;                   /* volume du son */
-  int accelvar;                 /* acceleration des particules */
   int i;
   float largfactor;             /* elargissement de l'intervalle d'évolution des points */
-  int zfd_update = 0;
-  int resolx = goomdata->resolx;
-  int resoly = goomdata->resoly;
-  ZoomFilterData *pzfd = goomdata->zfd;
-  guint32 *tmp;
+  Pixel *tmp;
 
-  /* test if the config has changed, update it if so */
+  ZoomFilterData *pzfd;
 
-  pointWidth = (resolx * 2) / 5;
-  pointHeight = (resoly * 2) / 5;
+  /* test if the config has changed, update it if so */
+  pointWidth = (goomInfo->screen.width * 2) / 5;
+  pointHeight = ((goomInfo->screen.height) * 2) / 5;
 
   /* ! etude du signal ... */
-  incvar = 0;
-  for (i = 0; i < 512; i++) {
-    if (incvar < data[0][i])
-      incvar = data[0][i];
-  }
-
-  accelvar = incvar / 5000;
-  if (goomdata->speedvar > 5) {
-    accelvar--;
-    if (goomdata->speedvar > 20)
-      accelvar--;
-    if (goomdata->speedvar > 40)
-      goomdata->speedvar = 40;
-  }
-  accelvar--;
-  goomdata->speedvar += accelvar;
-
-  if (goomdata->speedvar < 0)
-    goomdata->speedvar = 0;
-  if (goomdata->speedvar > 40)
-    goomdata->speedvar = 40;
+  evaluate_sound (data, &(goomInfo->sound));
 
+  /* goom_execute_main_script(goomInfo); */
 
   /* ! calcul du deplacement des petits points ... */
-
   largfactor =
-      ((float) goomdata->speedvar / 40.0f + (float) incvar / 50000.0f) / 1.5f;
+      goomInfo->sound.speedvar / 150.0f + goomInfo->sound.volume / 1.5f;
+
   if (largfactor > 1.5f)
     largfactor = 1.5f;
 
-  for (i = 1; i * 15 <= goomdata->speedvar + 15; i++) {
-    goomdata->loopvar += goomdata->speedvar + 1;
-
-    pointFilter (goomdata,
-        YELLOW,
-        ((pointWidth - 6.0f) * largfactor + 5.0f),
-        ((pointHeight - 6.0f) * largfactor + 5.0f),
-        i * 152.0f, 128.0f, goomdata->loopvar + i * 2032);
-    pointFilter (goomdata, ORANGE,
-        ((pointWidth / 2) * largfactor) / i + 10.0f * i,
-        ((pointHeight / 2) * largfactor) / i + 10.0f * i,
-        96.0f, i * 80.0f, goomdata->loopvar / i);
-    pointFilter (goomdata, VIOLET,
-        ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
-        ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
-        i + 122.0f, 134.0f, goomdata->loopvar / i);
-    pointFilter (goomdata, BLACK,
-        ((pointHeight / 3) * largfactor + 20.0f),
-        ((pointHeight / 3) * largfactor + 20.0f),
-        58.0f, i * 66.0f, goomdata->loopvar / i);
-    pointFilter (goomdata, WHITE,
-        (pointHeight * largfactor + 10.0f * i) / i,
-        (pointHeight * largfactor + 10.0f * i) / i,
-        66.0f, 74.0f, goomdata->loopvar + i * 500);
+  goomInfo->update.decay_ifs--;
+  if (goomInfo->update.decay_ifs > 0)
+    goomInfo->update.ifs_incr += 2;
+  if (goomInfo->update.decay_ifs == 0)
+    goomInfo->update.ifs_incr = 0;
+
+  if (goomInfo->update.recay_ifs) {
+    goomInfo->update.ifs_incr -= 2;
+    goomInfo->update.recay_ifs--;
+    if ((goomInfo->update.recay_ifs == 0) && (goomInfo->update.ifs_incr <= 0))
+      goomInfo->update.ifs_incr = 1;
+  }
+
+  if (goomInfo->update.ifs_incr > 0)
+    goomInfo->ifs_fx.apply (&goomInfo->ifs_fx, goomInfo->p2, goomInfo->p1,
+        goomInfo);
+
+  if (goomInfo->curGState->drawPoints) {
+    for (i = 1; i * 15 <= goomInfo->sound.speedvar * 80.0f + 15; i++) {
+      goomInfo->update.loopvar += goomInfo->sound.speedvar * 50 + 1;
+
+      pointFilter (goomInfo, goomInfo->p1,
+          YELLOW,
+          ((pointWidth - 6.0f) * largfactor + 5.0f),
+          ((pointHeight - 6.0f) * largfactor + 5.0f),
+          i * 152.0f, 128.0f, goomInfo->update.loopvar + i * 2032);
+      pointFilter (goomInfo, goomInfo->p1, ORANGE,
+          ((pointWidth / 2) * largfactor) / i + 10.0f * i,
+          ((pointHeight / 2) * largfactor) / i + 10.0f * i,
+          96.0f, i * 80.0f, goomInfo->update.loopvar / i);
+      pointFilter (goomInfo, goomInfo->p1, VIOLET,
+          ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
+          ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
+          i + 122.0f, 134.0f, goomInfo->update.loopvar / i);
+      pointFilter (goomInfo, goomInfo->p1, BLACK,
+          ((pointHeight / 3) * largfactor + 20.0f),
+          ((pointHeight / 3) * largfactor + 20.0f),
+          58.0f, i * 66.0f, goomInfo->update.loopvar / i);
+      pointFilter (goomInfo, goomInfo->p1, WHITE,
+          (pointHeight * largfactor + 10.0f * i) / i,
+          (pointHeight * largfactor + 10.0f * i) / i,
+          66.0f, 74.0f, goomInfo->update.loopvar + i * 500);
+    }
+  }
+
+  /* par défaut pas de changement de zoom */
+  pzfd = NULL;
+
+  /* 
+   * Test forceMode
+   */
+#ifdef VERBOSE
+  if (forceMode != 0) {
+    printf ("forcemode = %d\n", forceMode);
   }
+#endif
+
 
   /* diminuer de 1 le temps de lockage */
   /* note pour ceux qui n'ont pas suivis : le lockvar permet d'empecher un */
-  /* changement d'etat du plugins juste apres un autre changement d'etat. oki ? */
-  if (--goomdata->lockvar < 0)
-    goomdata->lockvar = 0;
-
-  /* temps du goom */
-  if (--goomdata->agoom < 0)
-    goomdata->agoom = 0;
+  /* changement d'etat du plugin juste apres un autre changement d'etat. oki */
+  if (--goomInfo->update.lockvar < 0)
+    goomInfo->update.lockvar = 0;
 
   /* on verifie qu'il ne se pas un truc interressant avec le son. */
-  if ((accelvar > goomdata->goomlimit) || (accelvar < -goomdata->goomlimit)) {
-    /* UN GOOM !!! YAHOO ! */
-    goomdata->totalgoom++;
-    goomdata->agoom = 20;       /* mais pdt 20 cycles, il n'y en aura plus. */
-    goomdata->lineMode = (goomdata->lineMode + 1) % 20; /* Tous les 10 gooms on change de mode lineaire */
+  if ((goomInfo->sound.timeSinceLastGoom == 0)
+      || (forceMode > 0)
+      || (goomInfo->update.cyclesSinceLastChange > TIME_BTW_CHG)) {
 
     /* changement eventuel de mode */
-    switch (iRAND (goomdata, 10)) {
-      case 0:
-      case 1:
-      case 2:
-        pzfd->mode = WAVE_MODE;
-        pzfd->vitesse = STOP_SPEED - 1;
-        pzfd->reverse = 0;
-        break;
-      case 3:
-      case 4:
-        pzfd->mode = CRYSTAL_BALL_MODE;
-        break;
-      case 5:
-        pzfd->mode = AMULETTE_MODE;
-        break;
-      case 6:
-        pzfd->mode = WATER_MODE;
-        break;
-      case 7:
-        pzfd->mode = SCRUNCH_MODE;
-        break;
-      default:
-        pzfd->mode = NORMAL_MODE;
-    }
+    if (goom_irand (goomInfo->gRandom, 16) == 0)
+      switch (goom_irand (goomInfo->gRandom, 34)) {
+        case 0:
+        case 10:
+          goomInfo->update.zoomFilterData.hypercosEffect =
+              goom_irand (goomInfo->gRandom, 2);
+        case 13:
+        case 20:
+        case 21:
+          goomInfo->update.zoomFilterData.mode = WAVE_MODE;
+          goomInfo->update.zoomFilterData.reverse = 0;
+          goomInfo->update.zoomFilterData.waveEffect =
+              (goom_irand (goomInfo->gRandom, 3) == 0);
+          if (goom_irand (goomInfo->gRandom, 2))
+            goomInfo->update.zoomFilterData.vitesse =
+                (goomInfo->update.zoomFilterData.vitesse + 127) >> 1;
+          break;
+        case 1:
+        case 11:
+          goomInfo->update.zoomFilterData.mode = CRYSTAL_BALL_MODE;
+          goomInfo->update.zoomFilterData.waveEffect = 0;
+          goomInfo->update.zoomFilterData.hypercosEffect = 0;
+          break;
+        case 2:
+        case 12:
+          goomInfo->update.zoomFilterData.mode = AMULETTE_MODE;
+          goomInfo->update.zoomFilterData.waveEffect = 0;
+          goomInfo->update.zoomFilterData.hypercosEffect = 0;
+          break;
+        case 3:
+          goomInfo->update.zoomFilterData.mode = WATER_MODE;
+          goomInfo->update.zoomFilterData.waveEffect = 0;
+          goomInfo->update.zoomFilterData.hypercosEffect = 0;
+          break;
+        case 4:
+        case 14:
+          goomInfo->update.zoomFilterData.mode = SCRUNCH_MODE;
+          goomInfo->update.zoomFilterData.waveEffect = 0;
+          goomInfo->update.zoomFilterData.hypercosEffect = 0;
+          break;
+        case 5:
+        case 15:
+        case 22:
+          goomInfo->update.zoomFilterData.mode = HYPERCOS1_MODE;
+          goomInfo->update.zoomFilterData.waveEffect = 0;
+          goomInfo->update.zoomFilterData.hypercosEffect =
+              (goom_irand (goomInfo->gRandom, 3) == 0);
+          break;
+        case 6:
+        case 16:
+          goomInfo->update.zoomFilterData.mode = HYPERCOS2_MODE;
+          goomInfo->update.zoomFilterData.waveEffect = 0;
+          goomInfo->update.zoomFilterData.hypercosEffect = 0;
+          break;
+        case 7:
+        case 17:
+          goomInfo->update.zoomFilterData.mode = CRYSTAL_BALL_MODE;
+          goomInfo->update.zoomFilterData.waveEffect =
+              (goom_irand (goomInfo->gRandom, 4) == 0);
+          goomInfo->update.zoomFilterData.hypercosEffect =
+              goom_irand (goomInfo->gRandom, 2);
+          break;
+        case 8:
+        case 18:
+        case 19:
+          goomInfo->update.zoomFilterData.mode = SCRUNCH_MODE;
+          goomInfo->update.zoomFilterData.waveEffect = 1;
+          goomInfo->update.zoomFilterData.hypercosEffect = 1;
+          break;
+        case 29:
+        case 30:
+          goomInfo->update.zoomFilterData.mode = YONLY_MODE;
+          break;
+        case 31:
+        case 32:
+        case 33:
+          goomInfo->update.zoomFilterData.mode = SPEEDWAY_MODE;
+          break;
+        default:
+          goomInfo->update.zoomFilterData.mode = NORMAL_MODE;
+          goomInfo->update.zoomFilterData.waveEffect = 0;
+          goomInfo->update.zoomFilterData.hypercosEffect = 0;
+      }
   }
 
   /* tout ceci ne sera fait qu'en cas de non-blocage */
-  if (goomdata->lockvar == 0) {
+  if (goomInfo->update.lockvar == 0) {
     /* reperage de goom (acceleration forte de l'acceleration du volume) */
     /* -> coup de boost de la vitesse si besoin.. */
-    if ((accelvar > goomdata->goomlimit) || (accelvar < -goomdata->goomlimit)) {
-      goomdata->goomvar++;
-      /*if (goomvar % 1 == 0) */
+    if (goomInfo->sound.timeSinceLastGoom == 0) {
+
+      int i;
+
+      goomInfo->update.goomvar++;
+
+      /* SELECTION OF THE GOOM STATE */
+      if ((!goomInfo->update.stateSelectionBlocker)
+          && (goom_irand (goomInfo->gRandom, 3))) {
+        goomInfo->update.stateSelectionRnd =
+            goom_irand (goomInfo->gRandom, goomInfo->statesRangeMax);
+        goomInfo->update.stateSelectionBlocker = 3;
+      } else if (goomInfo->update.stateSelectionBlocker)
+        goomInfo->update.stateSelectionBlocker--;
+
+      for (i = 0; i < goomInfo->statesNumber; i++)
+        if ((goomInfo->update.stateSelectionRnd >= goomInfo->states[i].rangemin)
+            && (goomInfo->update.stateSelectionRnd <=
+                goomInfo->states[i].rangemax))
+          goomInfo->curGState = &(goomInfo->states[i]);
+
+      if ((goomInfo->curGState->drawIFS) && (goomInfo->update.ifs_incr <= 0)) {
+        goomInfo->update.recay_ifs = 5;
+        goomInfo->update.ifs_incr = 11;
+      }
+
+      if ((!goomInfo->curGState->drawIFS) && (goomInfo->update.ifs_incr > 0)
+          && (goomInfo->update.decay_ifs <= 0))
+        goomInfo->update.decay_ifs = 100;
+
+      if (!goomInfo->curGState->drawScope)
+        goomInfo->update.stop_lines = 0xf000 & 5;
+
+      if (!goomInfo->curGState->drawScope) {
+        goomInfo->update.stop_lines = 0;
+        goomInfo->update.lineMode = goomInfo->update.drawLinesDuration;
+      }
+
+      /* if (goomInfo->update.goomvar % 1 == 0) */
       {
         guint32 vtmp;
         guint32 newvit;
 
-        newvit = STOP_SPEED - goomdata->speedvar / 2;
+        goomInfo->update.lockvar = 50;
+        newvit =
+            STOP_SPEED + 1 -
+            ((float) 3.5f * log10 (goomInfo->sound.speedvar * 60 + 1));
         /* retablir le zoom avant.. */
-        if ((pzfd->reverse) && (!(goomdata->cycle % 12)) && (rand () % 3 == 0)) {
-          pzfd->reverse = 0;
-          pzfd->vitesse = STOP_SPEED - 2;
-          goomdata->lockvar = 50;
+        if ((goomInfo->update.zoomFilterData.reverse)
+            && (!(goomInfo->cycle % 13)) && (rand () % 5 == 0)) {
+          goomInfo->update.zoomFilterData.reverse = 0;
+          goomInfo->update.zoomFilterData.vitesse = STOP_SPEED - 2;
+          goomInfo->update.lockvar = 75;
         }
-        if (iRAND (goomdata, 10) == 0) {
-          pzfd->reverse = 1;
-          goomdata->lockvar = 100;
+        if (goom_irand (goomInfo->gRandom, 10) == 0) {
+          goomInfo->update.zoomFilterData.reverse = 1;
+          goomInfo->update.lockvar = 100;
         }
 
+        if (goom_irand (goomInfo->gRandom, 10) == 0)
+          goomInfo->update.zoomFilterData.vitesse = STOP_SPEED - 1;
+        if (goom_irand (goomInfo->gRandom, 12) == 0)
+          goomInfo->update.zoomFilterData.vitesse = STOP_SPEED + 1;
+
         /* changement de milieu.. */
-        switch (iRAND (goomdata, 20)) {
+        switch (goom_irand (goomInfo->gRandom, 25)) {
           case 0:
-            pzfd->middleY = resoly - 1;
-            pzfd->middleX = resolx / 2;
+          case 3:
+          case 6:
+            goomInfo->update.zoomFilterData.middleY =
+                goomInfo->screen.height - 1;
+            goomInfo->update.zoomFilterData.middleX =
+                goomInfo->screen.width / 2;
             break;
           case 1:
-            pzfd->middleX = resolx - 1;
+          case 4:
+            goomInfo->update.zoomFilterData.middleX =
+                goomInfo->screen.width - 1;
             break;
           case 2:
-            pzfd->middleX = 1;
+          case 5:
+            goomInfo->update.zoomFilterData.middleX = 1;
             break;
           default:
-            pzfd->middleY = resoly / 2;
-            pzfd->middleX = resolx / 2;
+            goomInfo->update.zoomFilterData.middleY =
+                goomInfo->screen.height / 2;
+            goomInfo->update.zoomFilterData.middleX =
+                goomInfo->screen.width / 2;
         }
 
-        if (pzfd->mode == WATER_MODE) {
-          pzfd->middleX = resolx / 2;
-          pzfd->middleY = resoly / 2;
+        if ((goomInfo->update.zoomFilterData.mode == WATER_MODE)
+            || (goomInfo->update.zoomFilterData.mode == YONLY_MODE)
+            || (goomInfo->update.zoomFilterData.mode == AMULETTE_MODE)) {
+          goomInfo->update.zoomFilterData.middleX = goomInfo->screen.width / 2;
+          goomInfo->update.zoomFilterData.middleY = goomInfo->screen.height / 2;
         }
 
-        switch (vtmp = (iRAND (goomdata, 27))) {
+        switch (vtmp = (goom_irand (goomInfo->gRandom, 15))) {
           case 0:
-            pzfd->vPlaneEffect = iRAND (goomdata, 3);
-            pzfd->vPlaneEffect -= iRAND (goomdata, 3);
-            pzfd->hPlaneEffect = iRAND (goomdata, 3);
-            pzfd->hPlaneEffect -= iRAND (goomdata, 3);
+            goomInfo->update.zoomFilterData.vPlaneEffect =
+                goom_irand (goomInfo->gRandom, 3)
+                - goom_irand (goomInfo->gRandom, 3);
+            goomInfo->update.zoomFilterData.hPlaneEffect =
+                goom_irand (goomInfo->gRandom, 3)
+                - goom_irand (goomInfo->gRandom, 3);
             break;
           case 3:
-            pzfd->vPlaneEffect = 0;
-            pzfd->hPlaneEffect = iRAND (goomdata, 8);
-            pzfd->hPlaneEffect -= iRAND (goomdata, 8);
+            goomInfo->update.zoomFilterData.vPlaneEffect = 0;
+            goomInfo->update.zoomFilterData.hPlaneEffect =
+                goom_irand (goomInfo->gRandom, 8)
+                - goom_irand (goomInfo->gRandom, 8);
             break;
           case 4:
           case 5:
           case 6:
           case 7:
-            pzfd->vPlaneEffect = iRAND (goomdata, 5);
-            pzfd->vPlaneEffect -= iRAND (goomdata, 5);
-            pzfd->hPlaneEffect = -pzfd->vPlaneEffect;
+            goomInfo->update.zoomFilterData.vPlaneEffect =
+                goom_irand (goomInfo->gRandom, 5)
+                - goom_irand (goomInfo->gRandom, 5);
+            goomInfo->update.zoomFilterData.hPlaneEffect =
+                -goomInfo->update.zoomFilterData.vPlaneEffect;
             break;
           case 8:
-            pzfd->hPlaneEffect = 5 + iRAND (goomdata, 8);
-            pzfd->vPlaneEffect = -pzfd->hPlaneEffect;
+            goomInfo->update.zoomFilterData.hPlaneEffect =
+                5 + goom_irand (goomInfo->gRandom, 8);
+            goomInfo->update.zoomFilterData.vPlaneEffect =
+                -goomInfo->update.zoomFilterData.hPlaneEffect;
             break;
           case 9:
-            pzfd->vPlaneEffect = 5 + iRAND (goomdata, 8);
-            pzfd->hPlaneEffect = -pzfd->hPlaneEffect;
+            goomInfo->update.zoomFilterData.vPlaneEffect =
+                5 + goom_irand (goomInfo->gRandom, 8);
+            goomInfo->update.zoomFilterData.hPlaneEffect =
+                -goomInfo->update.zoomFilterData.hPlaneEffect;
             break;
           case 13:
-            pzfd->hPlaneEffect = 0;
-            pzfd->vPlaneEffect = iRAND (goomdata, 10);
-            pzfd->vPlaneEffect -= iRAND (goomdata, 10);
+            goomInfo->update.zoomFilterData.hPlaneEffect = 0;
+            goomInfo->update.zoomFilterData.vPlaneEffect =
+                goom_irand (goomInfo->gRandom, 10)
+                - goom_irand (goomInfo->gRandom, 10);
+            break;
+          case 14:
+            goomInfo->update.zoomFilterData.hPlaneEffect =
+                goom_irand (goomInfo->gRandom, 10)
+                - goom_irand (goomInfo->gRandom, 10);
+            goomInfo->update.zoomFilterData.vPlaneEffect =
+                goom_irand (goomInfo->gRandom, 10)
+                - goom_irand (goomInfo->gRandom, 10);
             break;
           default:
             if (vtmp < 10) {
-              pzfd->vPlaneEffect = 0;
-              pzfd->hPlaneEffect = 0;
+              goomInfo->update.zoomFilterData.vPlaneEffect = 0;
+              goomInfo->update.zoomFilterData.hPlaneEffect = 0;
             }
         }
 
-        if (iRAND (goomdata, 3) != 0)
-          pzfd->noisify = 0;
+        if (goom_irand (goomInfo->gRandom, 5) != 0)
+          goomInfo->update.zoomFilterData.noisify = 0;
         else {
-          pzfd->noisify = iRAND (goomdata, 3) + 2;
-          goomdata->lockvar *= 3;
+          goomInfo->update.zoomFilterData.noisify =
+              goom_irand (goomInfo->gRandom, 2) + 1;
+          goomInfo->update.lockvar *= 2;
         }
 
-        if (pzfd->mode == AMULETTE_MODE) {
-          pzfd->vPlaneEffect = 0;
-          pzfd->hPlaneEffect = 0;
-          pzfd->noisify = 0;
+        if (goomInfo->update.zoomFilterData.mode == AMULETTE_MODE) {
+          goomInfo->update.zoomFilterData.vPlaneEffect = 0;
+          goomInfo->update.zoomFilterData.hPlaneEffect = 0;
+          goomInfo->update.zoomFilterData.noisify = 0;
         }
 
-        if ((pzfd->middleX == 1) || (pzfd->middleX == resolx - 1)) {
-          pzfd->vPlaneEffect = 0;
-          pzfd->hPlaneEffect = iRAND (goomdata, 2) ? 0 : pzfd->hPlaneEffect;
+        if ((goomInfo->update.zoomFilterData.middleX == 1)
+            || (goomInfo->update.zoomFilterData.middleX ==
+                (signed int) goomInfo->screen.width - 1)) {
+          goomInfo->update.zoomFilterData.vPlaneEffect = 0;
+          if (goom_irand (goomInfo->gRandom, 2))
+            goomInfo->update.zoomFilterData.hPlaneEffect = 0;
         }
 
-        if (newvit < pzfd->vitesse) {   /* on accelere */
-          zfd_update = 1;
+        if ((signed int) newvit < goomInfo->update.zoomFilterData.vitesse) {    /* on accelere */
+          pzfd = &goomInfo->update.zoomFilterData;
           if (((newvit < STOP_SPEED - 7) &&
-                  (pzfd->vitesse < STOP_SPEED - 6) &&
-                  (goomdata->cycle % 3 == 0)) || (iRAND (goomdata, 40) == 0)) {
-            pzfd->vitesse = STOP_SPEED - 1;
-            pzfd->reverse = !pzfd->reverse;
+                  (goomInfo->update.zoomFilterData.vitesse < STOP_SPEED - 6) &&
+                  (goomInfo->cycle % 3 == 0))
+              || (goom_irand (goomInfo->gRandom, 40) == 0)) {
+            goomInfo->update.zoomFilterData.vitesse =
+                STOP_SPEED - goom_irand (goomInfo->gRandom, 2)
+                + goom_irand (goomInfo->gRandom, 2);
+            goomInfo->update.zoomFilterData.reverse =
+                !goomInfo->update.zoomFilterData.reverse;
           } else {
-            pzfd->vitesse = (newvit + pzfd->vitesse * 4) / 5;
+            goomInfo->update.zoomFilterData.vitesse =
+                (newvit + goomInfo->update.zoomFilterData.vitesse * 7) / 8;
           }
-          goomdata->lockvar += 50;
+          goomInfo->update.lockvar += 50;
         }
       }
+
+      if (goomInfo->update.lockvar > 150) {
+        goomInfo->update.switchIncr = goomInfo->update.switchIncrAmount;
+        goomInfo->update.switchMult = 1.0f;
+      }
     }
     /* mode mega-lent */
-    if (iRAND (goomdata, 1000) == 0) {
+    if (goom_irand (goomInfo->gRandom, 700) == 0) {
       /* 
-         printf ("coup du sort...\n") ;
+       * printf ("coup du sort...\n") ;
        */
-      zfd_update = 1;
-      pzfd->vitesse = STOP_SPEED - 1;
-      pzfd->pertedec = 8;
-      pzfd->sqrtperte = 16;
-      goomdata->goomvar = 1;
-      goomdata->lockvar += 70;
+      pzfd = &goomInfo->update.zoomFilterData;
+      goomInfo->update.zoomFilterData.vitesse = STOP_SPEED - 1;
+      goomInfo->update.zoomFilterData.pertedec = 8;
+      goomInfo->update.zoomFilterData.sqrtperte = 16;
+      goomInfo->update.goomvar = 1;
+      goomInfo->update.lockvar += 50;
+      goomInfo->update.switchIncr = goomInfo->update.switchIncrAmount;
+      goomInfo->update.switchMult = 1.0f;
     }
   }
 
-  /* gros frein si la musique est calme */
-  if ((goomdata->speedvar < 1) && (pzfd->vitesse < STOP_SPEED - 4)
-      && (goomdata->cycle % 16 == 0)) {
-    /*
-       printf ("++slow part... %i\n", zfd.vitesse) ;
-     */
-    zfd_update = 1;
-    pzfd->vitesse += 3;
-    pzfd->pertedec = 8;
-    pzfd->sqrtperte = 16;
-    goomdata->goomvar = 0;
+  /*
+   * gros frein si la musique est calme
+   */
+  if ((goomInfo->sound.speedvar < 0.01f)
+      && (goomInfo->update.zoomFilterData.vitesse < STOP_SPEED - 4)
+      && (goomInfo->cycle % 16 == 0)) {
+    pzfd = &goomInfo->update.zoomFilterData;
+    goomInfo->update.zoomFilterData.vitesse += 3;
+    goomInfo->update.zoomFilterData.pertedec = 8;
+    goomInfo->update.zoomFilterData.sqrtperte = 16;
+    goomInfo->update.goomvar = 0;
+  }
+
+  /*
+   * baisser regulierement la vitesse...
+   */
+  if ((goomInfo->cycle % 73 == 0)
+      && (goomInfo->update.zoomFilterData.vitesse < STOP_SPEED - 5)) {
+    pzfd = &goomInfo->update.zoomFilterData;
+    goomInfo->update.zoomFilterData.vitesse++;
+  }
+
+  /*
+   * arreter de decrémenter au bout d'un certain temps
+   */
+  if ((goomInfo->cycle % 101 == 0)
+      && (goomInfo->update.zoomFilterData.pertedec == 7)) {
+    pzfd = &goomInfo->update.zoomFilterData;
+    goomInfo->update.zoomFilterData.pertedec = 8;
+    goomInfo->update.zoomFilterData.sqrtperte = 16;
+  }
+
+  /*
+   * Permet de forcer un effet.
+   */
+  if ((forceMode > 0) && (forceMode <= NB_FX)) {
+    pzfd = &goomInfo->update.zoomFilterData;
+    pzfd->mode = forceMode - 1;
+  }
+
+  if (forceMode == -1) {
+    pzfd = NULL;
+  }
+
+  /*
+   * Changement d'effet de zoom !
+   */
+  if (pzfd != NULL) {
+    int dif;
+
+    goomInfo->update.cyclesSinceLastChange = 0;
+
+    goomInfo->update.switchIncr = goomInfo->update.switchIncrAmount;
+
+    dif =
+        goomInfo->update.zoomFilterData.vitesse -
+        goomInfo->update.previousZoomSpeed;
+    if (dif < 0)
+      dif = -dif;
+
+    if (dif > 2) {
+      goomInfo->update.switchIncr *= (dif + 2) / 2;
+    }
+    goomInfo->update.previousZoomSpeed =
+        goomInfo->update.zoomFilterData.vitesse;
+    goomInfo->update.switchMult = 1.0f;
+
+    if (((goomInfo->sound.timeSinceLastGoom == 0)
+            && (goomInfo->sound.totalgoom < 2)) || (forceMode > 0)) {
+      goomInfo->update.switchIncr = 0;
+      goomInfo->update.switchMult = goomInfo->update.switchMultAmount;
+    }
+  } else {
+    if (goomInfo->update.cyclesSinceLastChange > TIME_BTW_CHG) {
+      pzfd = &goomInfo->update.zoomFilterData;
+      goomInfo->update.cyclesSinceLastChange = 0;
+    } else
+      goomInfo->update.cyclesSinceLastChange++;
+  }
+
+#ifdef VERBOSE
+  if (pzfd) {
+    printf ("GOOM: pzfd->mode = %d\n", pzfd->mode);
+  }
+#endif
+
+  /* Zoom here ! */
+  zoomFilterFastRGB (goomInfo, goomInfo->p1, goomInfo->p2, pzfd,
+      goomInfo->screen.width, goomInfo->screen.height,
+      goomInfo->update.switchIncr, goomInfo->update.switchMult);
+
+  /*
+   * Affichage tentacule
+   */
+
+  goomInfo->tentacles_fx.apply (&goomInfo->tentacles_fx, goomInfo->p1,
+      goomInfo->p2, goomInfo);
+  goomInfo->star_fx.apply (&goomInfo->star_fx, goomInfo->p2, goomInfo->p1,
+      goomInfo);
+
+  /*
+   * Affichage de texte
+   */
+  {
+    /*char title[1024]; */
+    char text[64];
+
     /*
-       printf ("--slow part... %i\n", zfd.vitesse) ;
+     * Le message
      */
-  }
+    update_message (goomInfo, message);
+
+    if (fps > 0) {
+      sprintf (text, "%2.0f fps", fps);
+      goom_draw_text (goomInfo->p1, goomInfo->screen.width,
+          goomInfo->screen.height, 10, 24, text, 1, 0);
+    }
 
-  /* baisser regulierement la vitesse... */
-  if ((goomdata->cycle % 73 == 0) && (pzfd->vitesse < STOP_SPEED - 5)) {
     /*
-       printf ("slow down...\n") ;
+     * Le titre
      */
-    zfd_update = 1;
-    pzfd->vitesse++;
+    if (songTitle != NULL) {
+      strncpy (goomInfo->update.titleText, songTitle, 1023);
+      goomInfo->update.titleText[1023] = 0;
+      goomInfo->update.timeOfTitleDisplay = 200;
+    }
+
+    if (goomInfo->update.timeOfTitleDisplay) {
+      goom_draw_text (goomInfo->p1, goomInfo->screen.width,
+          goomInfo->screen.height, goomInfo->screen.width / 2,
+          goomInfo->screen.height / 2 + 7, goomInfo->update.titleText,
+          ((float) (190 - goomInfo->update.timeOfTitleDisplay) / 10.0f), 1);
+      goomInfo->update.timeOfTitleDisplay--;
+      if (goomInfo->update.timeOfTitleDisplay < 4)
+        goom_draw_text (goomInfo->p2, goomInfo->screen.width,
+            goomInfo->screen.height, goomInfo->screen.width / 2,
+            goomInfo->screen.height / 2 + 7, goomInfo->update.titleText,
+            ((float) (190 - goomInfo->update.timeOfTitleDisplay) / 10.0f), 1);
+    }
   }
 
-  /* arreter de decrémenter au bout d'un certain temps */
-  if ((goomdata->cycle % 101 == 0) && (pzfd->pertedec == 7)) {
-    zfd_update = 1;
-    pzfd->pertedec = 8;
-    pzfd->sqrtperte = 16;
+  /*
+   * Gestion du Scope
+   */
+
+  /*
+   * arret demande
+   */
+  if ((goomInfo->update.stop_lines & 0xf000)
+      || (!goomInfo->curGState->drawScope)) {
+    float param1, param2, amplitude;
+    int couleur;
+    int mode;
+
+    choose_a_goom_line (goomInfo, &param1, &param2, &couleur, &mode, &amplitude,
+        1);
+    couleur = GML_BLACK;
+
+    goom_lines_switch_to (goomInfo->gmline1, mode, param1, amplitude, couleur);
+    goom_lines_switch_to (goomInfo->gmline2, mode, param2, amplitude, couleur);
+    goomInfo->update.stop_lines &= 0x0fff;
   }
 
-  /* Zoom here ! */
-  zoomFilterFastRGB (goomdata, pzfd, zfd_update);
+  /*
+   * arret aleatore.. changement de mode de ligne..
+   */
+  if (goomInfo->update.lineMode != goomInfo->update.drawLinesDuration) {
+    goomInfo->update.lineMode--;
+    if (goomInfo->update.lineMode == -1)
+      goomInfo->update.lineMode = 0;
+  } else
+      if ((goomInfo->cycle % 80 == 0)
+      && (goom_irand (goomInfo->gRandom, 5) == 0) && goomInfo->update.lineMode)
+    goomInfo->update.lineMode--;
+
+  if ((goomInfo->cycle % 120 == 0)
+      && (goom_irand (goomInfo->gRandom, 4) == 0)
+      && (goomInfo->curGState->drawScope)) {
+    if (goomInfo->update.lineMode == 0)
+      goomInfo->update.lineMode = goomInfo->update.drawLinesDuration;
+    else if (goomInfo->update.lineMode == goomInfo->update.drawLinesDuration) {
+      float param1, param2, amplitude;
+      int couleur1, couleur2;
+      int mode;
+
+      goomInfo->update.lineMode--;
+      choose_a_goom_line (goomInfo, &param1, &param2, &couleur1,
+          &mode, &amplitude, goomInfo->update.stop_lines);
+
+      couleur2 = 5 - couleur1;
+      if (goomInfo->update.stop_lines) {
+        goomInfo->update.stop_lines--;
+        if (goom_irand (goomInfo->gRandom, 2))
+          couleur2 = couleur1 = GML_BLACK;
+      }
 
-  /* si on est dans un goom : afficher les lignes... */
-  if (goomdata->agoom > 15)
-    goom_lines (goomdata, data, ((pzfd->middleX == resolx / 2)
-            && (pzfd->middleY == resoly / 2)
-            && (pzfd->mode != WATER_MODE))
-        ? (goomdata->lineMode / 10) : 0, goomdata->p2, goomdata->agoom - 15);
+      goom_lines_switch_to (goomInfo->gmline1, mode, param1, amplitude,
+          couleur1);
+      goom_lines_switch_to (goomInfo->gmline2, mode, param2, amplitude,
+          couleur2);
+    }
+  }
+
+  /*
+   * si on est dans un goom : afficher les lignes...
+   */
+  if ((goomInfo->update.lineMode != 0)
+      || (goomInfo->sound.timeSinceLastGoom < 5)) {
+    goomInfo->gmline2->power = goomInfo->gmline1->power;
+
+    goom_lines_draw (goomInfo, goomInfo->gmline1, data[0], goomInfo->p2);
+    goom_lines_draw (goomInfo, goomInfo->gmline2, data[1], goomInfo->p2);
+
+    if (((goomInfo->cycle % 121) == 9)
+        && (goom_irand (goomInfo->gRandom, 3) == 1)
+        && ((goomInfo->update.lineMode == 0)
+            || (goomInfo->update.lineMode ==
+                goomInfo->update.drawLinesDuration))) {
+      float param1, param2, amplitude;
+      int couleur1, couleur2;
+      int mode;
+
+      choose_a_goom_line (goomInfo, &param1, &param2, &couleur1,
+          &mode, &amplitude, goomInfo->update.stop_lines);
+      couleur2 = 5 - couleur1;
+
+      if (goomInfo->update.stop_lines) {
+        goomInfo->update.stop_lines--;
+        if (goom_irand (goomInfo->gRandom, 2))
+          couleur2 = couleur1 = GML_BLACK;
+      }
+      goom_lines_switch_to (goomInfo->gmline1, mode, param1, amplitude,
+          couleur1);
+      goom_lines_switch_to (goomInfo->gmline2, mode, param2, amplitude,
+          couleur2);
+    }
+  }
 
-  return_val = goomdata->p2;
-  tmp = goomdata->p1;
-  goomdata->p1 = goomdata->p2;
-  goomdata->p2 = tmp;
+  return_val = goomInfo->p1;
+  tmp = goomInfo->p1;
+  goomInfo->p1 = goomInfo->p2;
+  goomInfo->p2 = tmp;
 
   /* affichage et swappage des buffers.. */
-  goomdata->cycle++;
-
-  /* tous les 100 cycles : vérifier si le taux de goom est correct */
-  /* et le modifier sinon.. */
-  if (!(goomdata->cycle % 100)) {
-    if (goomdata->totalgoom > 15) {
-      /*  printf ("less gooms\n") ; */
-      goomdata->goomlimit++;
-    } else {
-      if ((goomdata->totalgoom == 0) && (goomdata->goomlimit > 1))
-        goomdata->goomlimit--;
-    }
-    goomdata->totalgoom = 0;
+  goomInfo->cycle++;
+
+  goomInfo->convolve_fx.apply (&goomInfo->convolve_fx, return_val,
+      goomInfo->outputBuf, goomInfo);
+
+  return (guint32 *) goomInfo->outputBuf;
+}
+
+/****************************************
+*                CLOSE                 *
+****************************************/
+void
+goom_close (PluginInfo * goomInfo)
+{
+  if (goomInfo->pixel != NULL)
+    free (goomInfo->pixel);
+  if (goomInfo->back != NULL)
+    free (goomInfo->back);
+  if (goomInfo->conv != NULL)
+    free (goomInfo->conv);
+
+  goomInfo->pixel = goomInfo->back = NULL;
+  goomInfo->conv = NULL;
+  goom_random_free (goomInfo->gRandom);
+  goom_lines_free (&goomInfo->gmline1);
+  goom_lines_free (&goomInfo->gmline2);
+
+  /* release_ifs (); */
+  goomInfo->ifs_fx.free (&goomInfo->ifs_fx);
+  goomInfo->convolve_fx.free (&goomInfo->convolve_fx);
+  goomInfo->star_fx.free (&goomInfo->star_fx);
+  goomInfo->tentacles_fx.free (&goomInfo->tentacles_fx);
+  goomInfo->zoomFilter_fx.free (&goomInfo->zoomFilter_fx);
+
+  free (goomInfo);
+}
+
+
+/* *** */
+void
+choose_a_goom_line (PluginInfo * goomInfo, float *param1, float *param2,
+    int *couleur, int *mode, float *amplitude, int far)
+{
+  *mode = goom_irand (goomInfo->gRandom, 3);
+  *amplitude = 1.0f;
+  switch (*mode) {
+    case GML_CIRCLE:
+      if (far) {
+        *param1 = *param2 = 0.47f;
+        *amplitude = 0.8f;
+        break;
+      }
+      if (goom_irand (goomInfo->gRandom, 3) == 0) {
+        *param1 = *param2 = 0;
+        *amplitude = 3.0f;
+      } else if (goom_irand (goomInfo->gRandom, 2)) {
+        *param1 = 0.40f * goomInfo->screen.height;
+        *param2 = 0.22f * goomInfo->screen.height;
+      } else {
+        *param1 = *param2 = goomInfo->screen.height * 0.35;
+      }
+      break;
+    case GML_HLINE:
+      if (goom_irand (goomInfo->gRandom, 4) || far) {
+        *param1 = goomInfo->screen.height / 7;
+        *param2 = 6.0f * goomInfo->screen.height / 7.0f;
+      } else {
+        *param1 = *param2 = goomInfo->screen.height / 2.0f;
+        *amplitude = 2.0f;
+      }
+      break;
+    case GML_VLINE:
+      if (goom_irand (goomInfo->gRandom, 3) || far) {
+        *param1 = goomInfo->screen.width / 7.0f;
+        *param2 = 6.0f * goomInfo->screen.width / 7.0f;
+      } else {
+        *param1 = *param2 = goomInfo->screen.width / 2.0f;
+        *amplitude = 1.5f;
+      }
+      break;
   }
-  return return_val;
+
+  *couleur = goom_irand (goomInfo->gRandom, 6);
 }
 
+#define ECART_VARIATION 1.5
+#define POS_VARIATION 3.0
+#define SCROLLING_SPEED 80
+
+/*
+ * Met a jour l'affichage du message defilant
+ */
 void
-goom_close (GoomData * goomdata)
+update_message (PluginInfo * goomInfo, char *message)
 {
-  if (goomdata->pixel != NULL)
-    free (goomdata->pixel);
-  if (goomdata->back != NULL)
-    free (goomdata->back);
-  if (goomdata->zfd != NULL) {
-    zoomFilterDestroy (goomdata->zfd);
-    goomdata->zfd = NULL;
+
+  int fin = 0;
+
+  if (message) {
+    int i = 1, j = 0;
+
+    sprintf (goomInfo->update_message.message, message);
+    for (j = 0; goomInfo->update_message.message[j]; j++)
+      if (goomInfo->update_message.message[j] == '\n')
+        i++;
+    goomInfo->update_message.numberOfLinesInMessage = i;
+    goomInfo->update_message.affiche =
+        goomInfo->screen.height +
+        goomInfo->update_message.numberOfLinesInMessage * 25 + 105;
+    goomInfo->update_message.longueur =
+        strlen (goomInfo->update_message.message);
+  }
+  if (goomInfo->update_message.affiche) {
+    int i = 0;
+    char *msg = malloc (goomInfo->update_message.longueur + 1);
+    char *ptr = msg;
+    int pos;
+    float ecart;
+
+    message = msg;
+    sprintf (msg, goomInfo->update_message.message);
+
+    while (!fin) {
+      while (1) {
+        if (*ptr == 0) {
+          fin = 1;
+          break;
+        }
+        if (*ptr == '\n') {
+          *ptr = 0;
+          break;
+        }
+        ++ptr;
+      }
+      pos =
+          goomInfo->update_message.affiche -
+          (goomInfo->update_message.numberOfLinesInMessage - i) * 25;
+      pos += POS_VARIATION * (cos ((double) pos / 20.0));
+      pos -= SCROLLING_SPEED;
+      ecart = (ECART_VARIATION * sin ((double) pos / 20.0));
+      if ((fin) && (2 * pos < (int) goomInfo->screen.height))
+        pos = (int) goomInfo->screen.height / 2;
+      pos += 7;
+
+      goom_draw_text (goomInfo->p1, goomInfo->screen.width,
+          goomInfo->screen.height, goomInfo->screen.width / 2, pos, message,
+          ecart, 1);
+      message = ++ptr;
+      i++;
+    }
+    goomInfo->update_message.affiche--;
+    free (msg);
   }
-  goomdata->pixel = goomdata->back = NULL;
-  RAND_CLOSE (goomdata);
 }
diff --git a/gst/goom/goom_core.h b/gst/goom/goom_core.h
deleted file mode 100644 (file)
index 1fbc0ee..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _GOOMCORE_H
-#define _GOOMCORE_H
-
-#include <glib.h>
-
-typedef struct ZoomFilterData ZoomFilterData;
-
-typedef struct
-{
-/**-----------------------------------------------------**
- **  SHARED DATA                                        **
- **-----------------------------------------------------**/
-  guint32 *pixel;
-  guint32 *back;
-  guint32 *p1, *p2;
-  guint32 cycle;
-
-  guint32 resolx, resoly, buffsize;
-
-  int lockvar;       /* pour empecher de nouveaux changements */
-  int goomvar;       /* boucle des gooms */
-  int totalgoom;     /* nombre de gooms par seconds */
-  int agoom;         /* un goom a eu lieu..       */
-  int loopvar;       /* mouvement des points */
-  int speedvar;      /* vitesse des particules */
-  int lineMode;      /* l'effet lineaire a dessiner */
-  char goomlimit;    /* sensibilité du goom */
-
-  ZoomFilterData *zfd;
-  
-  /* Random table */
-  gint  *rand_tab;
-  guint  rand_pos;
-} GoomData;
-
-void goom_init (GoomData *goomdata, guint32 resx, guint32 resy);
-void goom_set_resolution (GoomData *goomdata, guint32 resx, guint32 resy);
-
-guint32 *goom_update (GoomData *goomdata, gint16 data [2][512]);
-
-void goom_close (GoomData *goomdata);
-
-#endif
diff --git a/gst/goom/goom_filters.h b/gst/goom/goom_filters.h
new file mode 100644 (file)
index 0000000..f015499
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef FILTERS_H
+#define FILTERS_H
+
+#include "goom_config.h"
+#include "goom_typedefs.h"
+#include "goom_visual_fx.h"
+#include "goom_graphic.h"
+
+VisualFX zoomFilterVisualFXWrapper_create(void);
+
+struct _ZOOM_FILTER_DATA
+{
+       int     vitesse;           /* 128 = vitesse nule... * * 256 = en arriere 
+                                   * hyper vite.. * * 0 = en avant hype vite. */
+       unsigned char pertedec;
+       unsigned char sqrtperte;
+       int     middleX, middleY;  /* milieu de l'effet */
+       char    reverse;           /* inverse la vitesse */
+       char    mode;              /* type d'effet Ã  appliquer (cf les #define) */
+       /** @since June 2001 */
+       int     hPlaneEffect;      /* deviation horitontale */
+       int     vPlaneEffect;      /* deviation verticale */
+       /** @since April 2002 */
+       int     waveEffect;        /* applique une "surcouche" de wave effect */
+       int     hypercosEffect;    /* applique une "surcouche de hypercos effect */
+
+       char    noisify;           /* ajoute un bruit a la transformation */
+};
+
+#define NORMAL_MODE 0
+#define WAVE_MODE 1
+#define CRYSTAL_BALL_MODE 2
+#define SCRUNCH_MODE 3
+#define AMULETTE_MODE 4
+#define WATER_MODE 5
+#define HYPERCOS1_MODE 6
+#define HYPERCOS2_MODE 7
+#define YONLY_MODE 8
+#define SPEEDWAY_MODE 9
+
+void pointFilter (PluginInfo *goomInfo, Pixel * pix1, Color c,
+                  float t1, float t2, float t3, float t4, guint32 cycle);
+
+/* filtre de zoom :
+ * le contenu de pix1 est copie dans pix2.
+ * zf : si non NULL, configure l'effet.
+ * resx,resy : taille des buffers.
+ */
+void zoomFilterFastRGB (PluginInfo *goomInfo, Pixel * pix1, Pixel * pix2, ZoomFilterData * zf, guint32 resx,
+                        guint32 resy, int switchIncr, float switchMult);
+
+#endif
diff --git a/gst/goom/goom_fx.h b/gst/goom/goom_fx.h
new file mode 100644 (file)
index 0000000..e672ece
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _GOOM_FX_H
+#define _GOOM_FX_H
+
+#include "goom_visual_fx.h"
+#include "goom_plugin_info.h"
+
+VisualFX convolve_create ();
+VisualFX flying_star_create (void);
+
+void zoom_filter_c(int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]);
+
+#endif
diff --git a/gst/goom/goom_graphic.h b/gst/goom/goom_graphic.h
new file mode 100644 (file)
index 0000000..9deaf5a
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef GRAPHIC_H
+#define GRAPHIC_H
+
+typedef unsigned int Uint;
+
+typedef struct
+{
+  unsigned short r, v, b;
+}
+Color;
+
+extern const Color BLACK;
+extern const Color WHITE;
+extern const Color RED;
+extern const Color BLUE;
+extern const Color GREEN;
+extern const Color YELLOW;
+extern const Color ORANGE;
+extern const Color VIOLET;
+
+
+#ifdef COLOR_BGRA
+
+#define B_CHANNEL 0xFF000000
+#define G_CHANNEL 0x00FF0000
+#define R_CHANNEL 0x0000FF00
+#define A_CHANNEL 0x000000FF
+#define B_OFFSET  24
+#define G_OFFSET  16
+#define R_OFFSET  8
+#define A_OFFSET  0
+
+typedef union _PIXEL {
+  struct {
+    unsigned char b;
+    unsigned char g;
+    unsigned char r;
+    unsigned char a;
+  } channels;
+  unsigned int val;
+  unsigned char cop[4];
+} Pixel;
+
+#else
+
+#define A_CHANNEL 0xFF000000
+#define R_CHANNEL 0x00FF0000
+#define G_CHANNEL 0x0000FF00
+#define B_CHANNEL 0x000000FF
+#define A_OFFSET  24
+#define R_OFFSET  16
+#define G_OFFSET  8
+#define B_OFFSET  0
+
+typedef union _PIXEL {
+  struct {
+    unsigned char a;
+    unsigned char r;
+    unsigned char g;
+    unsigned char b;
+  } channels;
+  unsigned int val;
+  unsigned char cop[4];
+} Pixel;
+
+#endif /* COLOR_BGRA */
+
+/*
+inline void setPixelRGB (Pixel * buffer, Uint x, Uint y, Color c);
+inline void getPixelRGB (Pixel * buffer, Uint x, Uint y, Color * c);
+*/
+
+
+#endif /* GRAPHIC_H */
diff --git a/gst/goom/goom_plugin_info.h b/gst/goom/goom_plugin_info.h
new file mode 100644 (file)
index 0000000..8d5d098
--- /dev/null
@@ -0,0 +1,176 @@
+#ifndef _PLUGIN_INFO_H
+#define _PLUGIN_INFO_H
+
+#include "goom_typedefs.h"
+
+#include "goom_config.h"
+
+#include "goom_graphic.h"
+#include "goom_config_param.h"
+#include "goom_visual_fx.h"
+#include "goom_filters.h"
+#include "goom_tools.h"
+#include "goomsl.h"
+
+typedef struct {
+       char drawIFS;
+       char drawPoints;
+       char drawTentacle;
+
+       char drawScope;
+       int farScope;
+
+       int rangemin;
+       int rangemax;
+} GoomState;
+
+#define STATES_MAX_NB 128
+
+/**
+ * Gives informations about the sound.
+ */
+struct _SOUND_INFO {
+
+       /* nota : a Goom is just a sound event... */
+
+       int timeSinceLastGoom;   /* >= 0 */
+       float goomPower;         /* power of the last Goom [0..1] */
+
+       int timeSinceLastBigGoom;   /* >= 0 */
+
+       float volume;     /* [0..1] */
+       short samples[2][512];
+
+       /* other "internal" datas for the sound_tester */
+       float goom_limit; /* auto-updated limit of goom_detection */
+       float bigGoomLimit;
+       float accelvar;   /* acceleration of the sound - [0..1] */
+       float speedvar;   /* speed of the sound - [0..100] */
+       int allTimesMax;
+       int totalgoom;    /* number of goom since last reset
+                          * (a reset every 64 cycles) */
+
+       float prov_max;   /* accel max since last reset */
+
+       int cycle;
+
+       /* private */
+       PluginParam volume_p;
+       PluginParam speed_p;
+       PluginParam accel_p;
+       PluginParam goom_limit_p;
+        PluginParam goom_power_p;
+       PluginParam last_goom_p;
+       PluginParam last_biggoom_p;
+       PluginParam biggoom_speed_limit_p;
+       PluginParam biggoom_factor_p;
+
+       PluginParameters params; /* contains the previously defined parameters. */
+};
+
+
+/**
+ * Allows FXs to know the current state of the plugin.
+ */
+struct _PLUGIN_INFO {
+
+       /* public datas */
+
+       int nbParams;
+       PluginParameters *params;
+
+       /* private datas */
+
+       struct _SIZE_TYPE {
+               int width;
+               int height;
+               int size;   /* == screen.height * screen.width. */
+       } screen;
+
+       SoundInfo sound;
+
+       int nbVisuals;
+       VisualFX **visuals; /* pointers on all the visual fx */
+
+       /** The known FX */
+       VisualFX convolve_fx;
+       VisualFX star_fx;
+       VisualFX zoomFilter_fx;
+       VisualFX tentacles_fx;
+       VisualFX ifs_fx;
+
+       /** image buffers */
+       guint32 *pixel;
+       guint32 *back;
+       Pixel *p1, *p2;
+       Pixel *conv;
+  Pixel *outputBuf;
+
+       /** state of goom */
+       guint32 cycle;
+       GoomState states[STATES_MAX_NB];
+       int statesNumber;
+       int statesRangeMax;
+
+       GoomState *curGState;
+
+       /** effet de ligne.. */
+       GMLine *gmline1;
+       GMLine *gmline2;
+
+       /** sinus table */
+       int sintable[0x10000];
+
+       /* INTERNALS */
+       
+       /** goom_update internals.
+        * I took all static variables from goom_update and put them here.. for the moment.
+        */
+       struct {
+               int lockvar;               /* pour empecher de nouveaux changements */
+               int goomvar;               /* boucle des gooms */
+               int loopvar;               /* mouvement des points */
+               int stop_lines;
+               int ifs_incr;              /* dessiner l'ifs (0 = non: > = increment) */
+               int decay_ifs;             /* disparition de l'ifs */
+               int recay_ifs;             /* dedisparition de l'ifs */
+               int cyclesSinceLastChange; /* nombre de Cycle Depuis Dernier Changement */
+               int drawLinesDuration;     /* duree de la transition entre afficher les lignes ou pas */
+               int lineMode;              /* l'effet lineaire a dessiner */
+               float switchMultAmount;    /* SWITCHMULT (29.0f/30.0f) */
+               int switchIncrAmount;      /* 0x7f */
+               float switchMult;          /* 1.0f */
+               int switchIncr;            /*  = SWITCHINCR; */
+               int stateSelectionRnd;
+               int stateSelectionBlocker;
+               int previousZoomSpeed;
+               int timeOfTitleDisplay;
+                char titleText[1024];
+               ZoomFilterData zoomFilterData;                
+       } update;
+
+       struct {
+               int numberOfLinesInMessage;
+               char message[0x800];
+               int affiche;
+               int longueur;
+       } update_message;
+
+       struct {
+               void (*draw_line) (Pixel *data, int x1, int y1, int x2, int y2, int col, int screenx, int screeny);
+               void (*zoom_filter) (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]);
+       } methods;
+       
+       GoomRandom *gRandom;
+    
+    GoomSL *scanner;
+    GoomSL *main_scanner;
+    const char *main_script_str;
+};
+
+void plugin_info_init(PluginInfo *p, int nbVisual); 
+
+/* i = [0..p->nbVisual-1] */
+void plugin_info_add_visual(PluginInfo *p, int i, VisualFX *visual);
+
+#endif
diff --git a/gst/goom/goom_tools.c b/gst/goom/goom_tools.c
new file mode 100644 (file)
index 0000000..ebca69e
--- /dev/null
@@ -0,0 +1,32 @@
+#include "goom_tools.h"
+#include <stdlib.h>
+
+GoomRandom *
+goom_random_init (int i)
+{
+  GoomRandom *grandom = (GoomRandom *) malloc (sizeof (GoomRandom));
+
+  srand (i);
+  grandom->pos = 1;
+  goom_random_update_array (grandom, GOOM_NB_RAND);
+  return grandom;
+}
+
+void
+goom_random_free (GoomRandom * grandom)
+{
+  free (grandom);
+}
+
+void
+goom_random_update_array (GoomRandom * grandom, int numberOfValuesToChange)
+{
+  while (numberOfValuesToChange > 0) {
+#if RAND_MAX < 0x10000
+    grandom->array[grandom->pos++] = ((rand () << 16) + rand ()) / 127;
+#else
+    grandom->array[grandom->pos++] = rand () / 127;
+#endif
+    numberOfValuesToChange--;
+  }
+}
index 6178dbafb192e08695061fe2f912c539827323ed..31d044e4ac148aabeda578167c8f00533c872b4d 100644 (file)
@@ -1,24 +1,33 @@
 #ifndef _GOOMTOOLS_H
 #define _GOOMTOOLS_H
 
-#define NB_RAND 0x10000
-
-#define RAND_INIT(gd,i) \
-        srand (i); \
-        if (gd->rand_tab == NULL) \
-                gd->rand_tab = g_malloc (NB_RAND * sizeof(gint)) ;\
-        gd->rand_pos = 0; \
-        while (gd->rand_pos < NB_RAND) \
-                gd->rand_tab [gd->rand_pos++] = rand ();
-
-#define RAND(gd) \
-        (gd->rand_tab[gd->rand_pos = ((gd->rand_pos + 1) % NB_RAND)])
-
-#define RAND_CLOSE(gd) \
-        g_free (gd->rand_tab); \
-        gd->rand_tab = NULL;
-
-/*#define iRAND(i) ((guint32)((float)i * RAND()/RAND_MAX)) */
-#define iRAND(gd,i) (RAND(gd) % i)
-        
+/**
+ * Random number generator wrapper for faster random number.
+ */
+
+#define GOOM_NB_RAND 0x10000
+
+typedef struct _GOOM_RANDOM {
+       int array[GOOM_NB_RAND];
+       unsigned short pos;
+} GoomRandom;
+
+GoomRandom *goom_random_init(int i);
+void goom_random_free(GoomRandom *grandom);
+
+inline static int goom_random(GoomRandom *grandom) {
+       
+       grandom->pos++; /* works because pos is an unsigned short */
+       return grandom->array[grandom->pos];
+}
+
+inline static int goom_irand(GoomRandom *grandom, int i) {
+
+       grandom->pos++;
+       return grandom->array[grandom->pos] % i;
+}
+
+/* called to change the specified number of value in the array, so that the array does not remain the same*/
+void goom_random_update_array(GoomRandom *grandom, int numberOfValuesToChange);
+
 #endif
diff --git a/gst/goom/goom_typedefs.h b/gst/goom/goom_typedefs.h
new file mode 100644 (file)
index 0000000..7603650
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _GOOM_TYPEDEFS_H
+#define _GOOM_TYPEDEFS_H
+
+typedef struct _PLUGIN_INFO PluginInfo;
+typedef struct _SOUND_INFO SoundInfo;
+typedef struct _GMLINE GMLine;
+typedef struct _GMUNITPOINTER GMUnitPointer;
+typedef struct _ZOOM_FILTER_DATA ZoomFilterData;
+typedef struct _VISUAL_FX VisualFX;
+
+#endif
diff --git a/gst/goom/goom_visual_fx.h b/gst/goom/goom_visual_fx.h
new file mode 100644 (file)
index 0000000..6939ac8
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _VISUAL_FX_H
+#define _VISUAL_FX_H
+
+/**
+ * File created on 2003-05-21 by Jeko.
+ * (c)2003, JC Hoelt for iOS-software.
+ *
+ * LGPL Licence.
+ * If you use this file on a visual program,
+ *    please make my name being visible on it.
+ */
+
+#include "goom_config_param.h"
+#include "goom_graphic.h"
+#include "goom_typedefs.h"
+
+struct _VISUAL_FX {
+  void (*init) (struct _VISUAL_FX *_this, PluginInfo *info);
+  void (*free) (struct _VISUAL_FX *_this);
+  void (*apply) (struct _VISUAL_FX *_this, Pixel *src, Pixel *dest, PluginInfo *info);
+  void *fx_data;
+
+  PluginParameters *params;
+};
+
+#endif
diff --git a/gst/goom/goomsl.c b/gst/goom/goomsl.c
new file mode 100644 (file)
index 0000000..b07b259
--- /dev/null
@@ -0,0 +1,1660 @@
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "goomsl.h"
+#include "goomsl_private.h"
+#include "goomsl_yacc.h"
+
+/*#define TRACE_SCRIPT*/
+
+ /* {{{ definition of the instructions number */
+#define INSTR_SETI_VAR_INTEGER     1
+#define INSTR_SETI_VAR_VAR         2
+#define INSTR_SETF_VAR_FLOAT       3
+#define INSTR_SETF_VAR_VAR         4
+#define INSTR_NOP                  5
+/* #define INSTR_JUMP              6 */
+#define INSTR_SETP_VAR_PTR         7
+#define INSTR_SETP_VAR_VAR         8
+#define INSTR_SUBI_VAR_INTEGER     9
+#define INSTR_SUBI_VAR_VAR         10
+#define INSTR_SUBF_VAR_FLOAT       11
+#define INSTR_SUBF_VAR_VAR         12
+#define INSTR_ISLOWERF_VAR_VAR     13
+#define INSTR_ISLOWERF_VAR_FLOAT   14
+#define INSTR_ISLOWERI_VAR_VAR     15
+#define INSTR_ISLOWERI_VAR_INTEGER 16
+#define INSTR_ADDI_VAR_INTEGER     17
+#define INSTR_ADDI_VAR_VAR         18
+#define INSTR_ADDF_VAR_FLOAT       19
+#define INSTR_ADDF_VAR_VAR         20
+#define INSTR_MULI_VAR_INTEGER     21
+#define INSTR_MULI_VAR_VAR         22
+#define INSTR_MULF_VAR_FLOAT       23
+#define INSTR_MULF_VAR_VAR         24
+#define INSTR_DIVI_VAR_INTEGER     25
+#define INSTR_DIVI_VAR_VAR         26
+#define INSTR_DIVF_VAR_FLOAT       27
+#define INSTR_DIVF_VAR_VAR         28
+/* #define INSTR_JZERO             29 */
+#define INSTR_ISEQUALP_VAR_VAR     30
+#define INSTR_ISEQUALP_VAR_PTR     31
+#define INSTR_ISEQUALI_VAR_VAR     32
+#define INSTR_ISEQUALI_VAR_INTEGER 33
+#define INSTR_ISEQUALF_VAR_VAR     34
+#define INSTR_ISEQUALF_VAR_FLOAT   35
+/* #define INSTR_CALL              36 */
+/* #define INSTR_RET               37 */
+/* #define INSTR_EXT_CALL          38 */
+#define INSTR_NOT_VAR              39
+/* #define INSTR_JNZERO            40 */
+#define  INSTR_SETS_VAR_VAR        41
+#define  INSTR_ISEQUALS_VAR_VAR    42
+#define  INSTR_ADDS_VAR_VAR        43
+#define  INSTR_SUBS_VAR_VAR        44
+#define  INSTR_MULS_VAR_VAR        45
+#define  INSTR_DIVS_VAR_VAR        46
+
+ /* }}} */
+/* {{{ definition of the validation error types */
+static const char *VALIDATE_OK = "ok";
+
+#define VALIDATE_ERROR "error while validating "
+#define VALIDATE_TODO "todo"
+#define VALIDATE_SYNTHAX_ERROR "synthax error"
+#define VALIDATE_NO_SUCH_INT "no such integer variable"
+#define VALIDATE_NO_SUCH_VAR "no such variable"
+#define VALIDATE_NO_SUCH_DEST_VAR "no such destination variable"
+#define VALIDATE_NO_SUCH_SRC_VAR "no such src variable"
+/* }}} */
+
+  /***********************************/
+ /* PROTOTYPE OF INTERNAL FUNCTIONS */
+/***********************************/
+
+/* {{{ */
+static void gsl_instr_free (Instruction * _this);
+static const char *gsl_instr_validate (Instruction * _this);
+static void gsl_instr_display (Instruction * _this);
+
+static InstructionFlow *iflow_new (void);
+static void iflow_add_instr (InstructionFlow * _this, Instruction * instr);
+static void iflow_clean (InstructionFlow * _this);
+static void iflow_free (InstructionFlow * _this);
+static void iflow_execute (FastInstructionFlow * _this, GoomSL * gsl);
+
+/* }}} */
+
+  /************************************/
+ /* DEFINITION OF INTERNAL FUNCTIONS */
+/************************************/
+
+void
+iflow_free (InstructionFlow * _this)
+{                               /* {{{ */
+  goom_hash_free (_this->labels);
+  free (_this);                 /*TODO: finir cette fonction */
+}                               /* }}} */
+
+void
+iflow_clean (InstructionFlow * _this)
+{                               /* {{{ */
+  /* TODO: clean chaque instruction du flot */
+  _this->number = 0;
+  goom_hash_free (_this->labels);
+  _this->labels = goom_hash_new ();
+}                               /* }}} */
+
+InstructionFlow *
+iflow_new (void)
+{                               /* {{{ */
+  InstructionFlow *_this =
+      (InstructionFlow *) malloc (sizeof (InstructionFlow));
+  _this->number = 0;
+  _this->tabsize = 6;
+  _this->instr =
+      (Instruction **) malloc (_this->tabsize * sizeof (Instruction *));
+  _this->labels = goom_hash_new ();
+
+  return _this;
+}                               /* }}} */
+
+void
+iflow_add_instr (InstructionFlow * _this, Instruction * instr)
+{                               /* {{{ */
+  if (_this->number == _this->tabsize) {
+    _this->tabsize *= 2;
+    _this->instr =
+        (Instruction **) realloc (_this->instr,
+        _this->tabsize * sizeof (Instruction *));
+  }
+  _this->instr[_this->number] = instr;
+  instr->address = _this->number;
+  _this->number++;
+}                               /* }}} */
+
+void
+gsl_instr_set_namespace (Instruction * _this, GoomHash * ns)
+{                               /* {{{ */
+  if (_this->cur_param <= 0) {
+    fprintf (stderr, "ERROR: Line %d, No more params to instructions\n",
+        _this->line_number);
+    exit (1);
+  }
+  _this->vnamespace[_this->cur_param - 1] = ns;
+}                               /* }}} */
+
+void
+gsl_instr_add_param (Instruction * instr, char *param, int type)
+{                               /* {{{ */
+  int len;
+
+  if (instr == NULL)
+    return;
+  if (instr->cur_param == 0)
+    return;
+  --instr->cur_param;
+  len = strlen (param);
+  instr->params[instr->cur_param] = (char *) malloc (len + 1);
+  strcpy (instr->params[instr->cur_param], param);
+  instr->types[instr->cur_param] = type;
+  if (instr->cur_param == 0) {
+
+    const char *result = gsl_instr_validate (instr);
+
+    if (result != VALIDATE_OK) {
+      printf ("ERROR: Line %d: ", instr->parent->num_lines + 1);
+      gsl_instr_display (instr);
+      printf ("... %s\n", result);
+      instr->parent->compilationOK = 0;
+      exit (1);
+    }
+#if USE_JITC_X86
+    iflow_add_instr (instr->parent->iflow, instr);
+#else
+    if (instr->id != INSTR_NOP)
+      iflow_add_instr (instr->parent->iflow, instr);
+    else
+      gsl_instr_free (instr);
+#endif
+  }
+}                               /* }}} */
+
+Instruction *
+gsl_instr_init (GoomSL * parent, const char *name, int id, int nb_param,
+    int line_number)
+{                               /* {{{ */
+  Instruction *instr = (Instruction *) malloc (sizeof (Instruction));
+  instr->params = (char **) malloc (nb_param * sizeof (char *));
+  instr->vnamespace = (GoomHash **) malloc (nb_param * sizeof (GoomHash *));
+  instr->types = (int *) malloc (nb_param * sizeof (int));
+  instr->cur_param = instr->nb_param = nb_param;
+  instr->parent = parent;
+  instr->id = id;
+  instr->name = name;
+  instr->jump_label = NULL;
+  instr->line_number = line_number;
+  return instr;
+}                               /* }}} */
+
+void
+gsl_instr_free (Instruction * _this)
+{                               /* {{{ */
+  int i;
+
+  free (_this->types);
+  for (i = _this->cur_param; i < _this->nb_param; ++i)
+    free (_this->params[i]);
+  free (_this->params);
+  free (_this);
+}                               /* }}} */
+
+void
+gsl_instr_display (Instruction * _this)
+{                               /* {{{ */
+  int i = _this->nb_param - 1;
+
+  printf ("%s", _this->name);
+  while (i >= _this->cur_param) {
+    printf (" %s", _this->params[i]);
+    --i;
+  }
+}                               /* }}} */
+
+  /****************************************/
+ /* VALIDATION OF INSTRUCTION PARAMETERS */
+/****************************************/
+
+static const char *
+validate_v_v (Instruction * _this)
+{                               /* {{{ */
+  HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
+  HashValue *src = goom_hash_get (_this->vnamespace[0], _this->params[0]);
+
+  if (dest == NULL) {
+    return VALIDATE_NO_SUCH_DEST_VAR;
+  }
+  if (src == NULL) {
+    return VALIDATE_NO_SUCH_SRC_VAR;
+  }
+  _this->data.udest.var = dest->ptr;
+  _this->data.usrc.var = src->ptr;
+  return VALIDATE_OK;
+}                               /* }}} */
+
+static const char *
+validate_v_i (Instruction * _this)
+{                               /* {{{ */
+  HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
+
+  _this->data.usrc.value_int = strtol (_this->params[0], NULL, 0);
+
+  if (dest == NULL) {
+    return VALIDATE_NO_SUCH_INT;
+  }
+  _this->data.udest.var = dest->ptr;
+  return VALIDATE_OK;
+}                               /* }}} */
+
+static const char *
+validate_v_p (Instruction * _this)
+{                               /* {{{ */
+  HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
+
+  _this->data.usrc.value_ptr = strtol (_this->params[0], NULL, 0);
+
+  if (dest == NULL) {
+    return VALIDATE_NO_SUCH_INT;
+  }
+  _this->data.udest.var = dest->ptr;
+  return VALIDATE_OK;
+}                               /* }}} */
+
+static const char *
+validate_v_f (Instruction * _this)
+{                               /* {{{ */
+  HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
+
+  _this->data.usrc.value_float = atof (_this->params[0]);
+
+  if (dest == NULL) {
+    return VALIDATE_NO_SUCH_VAR;
+  }
+  _this->data.udest.var = dest->ptr;
+  return VALIDATE_OK;
+}                               /* }}} */
+
+static const char *
+validate (Instruction * _this,
+    int vf_f_id, int vf_v_id,
+    int vi_i_id, int vi_v_id, int vp_p_id, int vp_v_id, int vs_v_id)
+{                               /* {{{ */
+  if ((_this->types[1] == TYPE_FVAR) && (_this->types[0] == TYPE_FLOAT)) {
+    _this->id = vf_f_id;
+    return validate_v_f (_this);
+  } else if ((_this->types[1] == TYPE_FVAR) && (_this->types[0] == TYPE_FVAR)) {
+    _this->id = vf_v_id;
+    return validate_v_v (_this);
+  } else if ((_this->types[1] == TYPE_IVAR)
+      && (_this->types[0] == TYPE_INTEGER)) {
+    _this->id = vi_i_id;
+    return validate_v_i (_this);
+  } else if ((_this->types[1] == TYPE_IVAR) && (_this->types[0] == TYPE_IVAR)) {
+    _this->id = vi_v_id;
+    return validate_v_v (_this);
+  } else if ((_this->types[1] == TYPE_PVAR) && (_this->types[0] == TYPE_PTR)) {
+    if (vp_p_id == INSTR_NOP)
+      return VALIDATE_ERROR;
+    _this->id = vp_p_id;
+    return validate_v_p (_this);
+  } else if ((_this->types[1] == TYPE_PVAR) && (_this->types[0] == TYPE_PVAR)) {
+    _this->id = vp_v_id;
+    if (vp_v_id == INSTR_NOP)
+      return VALIDATE_ERROR;
+    return validate_v_v (_this);
+  } else if ((_this->types[1] < FIRST_RESERVED) && (_this->types[1] >= 0)
+      && (_this->types[0] == _this->types[1])) {
+    _this->id = vs_v_id;
+    if (vs_v_id == INSTR_NOP)
+      return "Impossible operation to perform between two structs";
+    return validate_v_v (_this);
+  }
+  return VALIDATE_ERROR;
+}                               /* }}} */
+
+const char *
+gsl_instr_validate (Instruction * _this)
+{                               /* {{{ */
+  if (_this->id != INSTR_EXT_CALL) {
+    int i = _this->nb_param;
+
+    while (i > 0) {
+      i--;
+      if (_this->types[i] == TYPE_VAR) {
+        int type = gsl_type_of_var (_this->vnamespace[i], _this->params[i]);
+
+        if (type == INSTR_INT)
+          _this->types[i] = TYPE_IVAR;
+        else if (type == INSTR_FLOAT)
+          _this->types[i] = TYPE_FVAR;
+        else if (type == INSTR_PTR)
+          _this->types[i] = TYPE_PVAR;
+        else if ((type >= 0) && (type < FIRST_RESERVED))
+          _this->types[i] = type;
+        else
+          fprintf (stderr, "WARNING: Line %d, %s has no namespace\n",
+              _this->line_number, _this->params[i]);
+      }
+    }
+  }
+
+  switch (_this->id) {
+
+      /* set */
+    case INSTR_SET:
+      return validate (_this,
+          INSTR_SETF_VAR_FLOAT, INSTR_SETF_VAR_VAR,
+          INSTR_SETI_VAR_INTEGER, INSTR_SETI_VAR_VAR,
+          INSTR_SETP_VAR_PTR, INSTR_SETP_VAR_VAR, INSTR_SETS_VAR_VAR);
+
+      /* extcall */
+    case INSTR_EXT_CALL:
+      if (_this->types[0] == TYPE_VAR) {
+        HashValue *fval =
+            goom_hash_get (_this->parent->functions, _this->params[0]);
+        if (fval) {
+          _this->data.udest.external_function =
+              (struct _ExternalFunctionStruct *) fval->ptr;
+          return VALIDATE_OK;
+        }
+      }
+      return VALIDATE_ERROR;
+
+      /* call */
+    case INSTR_CALL:
+      if (_this->types[0] == TYPE_LABEL) {
+        _this->jump_label = _this->params[0];
+        return VALIDATE_OK;
+      }
+      return VALIDATE_ERROR;
+
+      /* ret */
+    case INSTR_RET:
+      return VALIDATE_OK;
+
+      /* jump */
+    case INSTR_JUMP:
+
+      if (_this->types[0] == TYPE_LABEL) {
+        _this->jump_label = _this->params[0];
+        return VALIDATE_OK;
+      }
+      return VALIDATE_ERROR;
+
+      /* jzero / jnzero */
+    case INSTR_JZERO:
+    case INSTR_JNZERO:
+
+      if (_this->types[0] == TYPE_LABEL) {
+        _this->jump_label = _this->params[0];
+        return VALIDATE_OK;
+      }
+      return VALIDATE_ERROR;
+
+      /* label */
+    case INSTR_LABEL:
+
+      if (_this->types[0] == TYPE_LABEL) {
+        _this->id = INSTR_NOP;
+        _this->nop_label = _this->params[0];
+        goom_hash_put_int (_this->parent->iflow->labels, _this->params[0],
+            _this->parent->iflow->number);
+        return VALIDATE_OK;
+      }
+      return VALIDATE_ERROR;
+
+      /* isequal */
+    case INSTR_ISEQUAL:
+      return validate (_this,
+          INSTR_ISEQUALF_VAR_FLOAT, INSTR_ISEQUALF_VAR_VAR,
+          INSTR_ISEQUALI_VAR_INTEGER, INSTR_ISEQUALI_VAR_VAR,
+          INSTR_ISEQUALP_VAR_PTR, INSTR_ISEQUALP_VAR_VAR,
+          INSTR_ISEQUALS_VAR_VAR);
+
+      /* not */
+    case INSTR_NOT:
+      _this->id = INSTR_NOT_VAR;
+      return VALIDATE_OK;
+
+      /* islower */
+    case INSTR_ISLOWER:
+      return validate (_this,
+          INSTR_ISLOWERF_VAR_FLOAT, INSTR_ISLOWERF_VAR_VAR,
+          INSTR_ISLOWERI_VAR_INTEGER, INSTR_ISLOWERI_VAR_VAR,
+          INSTR_NOP, INSTR_NOP, INSTR_NOP);
+
+      /* add */
+    case INSTR_ADD:
+      return validate (_this,
+          INSTR_ADDF_VAR_FLOAT, INSTR_ADDF_VAR_VAR,
+          INSTR_ADDI_VAR_INTEGER, INSTR_ADDI_VAR_VAR,
+          INSTR_NOP, INSTR_NOP, INSTR_ADDS_VAR_VAR);
+
+      /* mul */
+    case INSTR_MUL:
+      return validate (_this,
+          INSTR_MULF_VAR_FLOAT, INSTR_MULF_VAR_VAR,
+          INSTR_MULI_VAR_INTEGER, INSTR_MULI_VAR_VAR,
+          INSTR_NOP, INSTR_NOP, INSTR_MULS_VAR_VAR);
+
+      /* sub */
+    case INSTR_SUB:
+      return validate (_this,
+          INSTR_SUBF_VAR_FLOAT, INSTR_SUBF_VAR_VAR,
+          INSTR_SUBI_VAR_INTEGER, INSTR_SUBI_VAR_VAR,
+          INSTR_NOP, INSTR_NOP, INSTR_SUBS_VAR_VAR);
+
+      /* div */
+    case INSTR_DIV:
+      return validate (_this,
+          INSTR_DIVF_VAR_FLOAT, INSTR_DIVF_VAR_VAR,
+          INSTR_DIVI_VAR_INTEGER, INSTR_DIVI_VAR_VAR,
+          INSTR_NOP, INSTR_NOP, INSTR_DIVS_VAR_VAR);
+
+    default:
+      return VALIDATE_TODO;
+  }
+  return VALIDATE_ERROR;
+}                               /* }}} */
+
+  /*************/
+ /* EXECUTION */
+/*************/
+void
+iflow_execute (FastInstructionFlow * _this, GoomSL * gsl)
+{                               /* {{{ */
+  int flag = 0;
+  int ip = 0;
+  FastInstruction *instr = _this->instr;
+  int stack[0x10000];
+  int stack_pointer = 0;
+
+  stack[stack_pointer++] = -1;
+
+  /* Quelques Macro pour rendre le code plus lisible */
+#define pSRC_VAR        instr[ip].data.usrc.var
+#define SRC_VAR_INT    *instr[ip].data.usrc.var_int
+#define SRC_VAR_FLOAT  *instr[ip].data.usrc.var_float
+#define SRC_VAR_PTR    *instr[ip].data.usrc.var_ptr
+
+#define pDEST_VAR       instr[ip].data.udest.var
+#define DEST_VAR_INT   *instr[ip].data.udest.var_int
+#define DEST_VAR_FLOAT *instr[ip].data.udest.var_float
+#define DEST_VAR_PTR   *instr[ip].data.udest.var_ptr
+
+#define VALUE_INT       instr[ip].data.usrc.value_int
+#define VALUE_FLOAT     instr[ip].data.usrc.value_float
+#define VALUE_PTR       instr[ip].data.usrc.value_ptr
+
+#define JUMP_OFFSET     instr[ip].data.udest.jump_offset
+
+#define SRC_STRUCT_ID  instr[ip].data.usrc.var_int[-1]
+#define DEST_STRUCT_ID instr[ip].data.udest.var_int[-1]
+#define SRC_STRUCT_IBLOCK(i)  gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i]
+#define SRC_STRUCT_FBLOCK(i)  gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i]
+#define DEST_STRUCT_IBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i]
+#define DEST_STRUCT_FBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i]
+#define DEST_STRUCT_IBLOCK_VAR(i,j) \
+  ((int*)((char*)pDEST_VAR   + gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i].data))[j]
+#define DEST_STRUCT_FBLOCK_VAR(i,j) \
+  ((float*)((char*)pDEST_VAR + gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i].data))[j]
+#define SRC_STRUCT_IBLOCK_VAR(i,j) \
+  ((int*)((char*)pSRC_VAR    + gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i].data))[j]
+#define SRC_STRUCT_FBLOCK_VAR(i,j) \
+  ((float*)((char*)pSRC_VAR  + gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i].data))[j]
+#define DEST_STRUCT_SIZE      gsl->gsl_struct[DEST_STRUCT_ID]->size
+
+  while (1) {
+    int i;
+
+#ifdef TRACE_SCRIPT
+    printf ("execute ");
+    gsl_instr_display (instr[ip].proto);
+    printf ("\n");
+#endif
+    switch (instr[ip].id) {
+
+        /* SET.I */
+      case INSTR_SETI_VAR_INTEGER:
+        DEST_VAR_INT = VALUE_INT;
+        ++ip;
+        break;
+
+      case INSTR_SETI_VAR_VAR:
+        DEST_VAR_INT = SRC_VAR_INT;
+        ++ip;
+        break;
+
+        /* SET.F */
+      case INSTR_SETF_VAR_FLOAT:
+        DEST_VAR_FLOAT = VALUE_FLOAT;
+        ++ip;
+        break;
+
+      case INSTR_SETF_VAR_VAR:
+        DEST_VAR_FLOAT = SRC_VAR_FLOAT;
+        ++ip;
+        break;
+
+        /* SET.P */
+      case INSTR_SETP_VAR_VAR:
+        DEST_VAR_PTR = SRC_VAR_PTR;
+        ++ip;
+        break;
+
+      case INSTR_SETP_VAR_PTR:
+        DEST_VAR_PTR = VALUE_PTR;
+        ++ip;
+        break;
+
+        /* JUMP */
+      case INSTR_JUMP:
+        ip += JUMP_OFFSET;
+        break;
+
+        /* JZERO */
+      case INSTR_JZERO:
+        ip += (flag ? 1 : JUMP_OFFSET);
+        break;
+
+      case INSTR_NOP:
+        ++ip;
+        break;
+
+        /* ISEQUAL.P */
+      case INSTR_ISEQUALP_VAR_VAR:
+        flag = (DEST_VAR_PTR == SRC_VAR_PTR);
+        ++ip;
+        break;
+
+      case INSTR_ISEQUALP_VAR_PTR:
+        flag = (DEST_VAR_PTR == VALUE_PTR);
+        ++ip;
+        break;
+
+        /* ISEQUAL.I */
+      case INSTR_ISEQUALI_VAR_VAR:
+        flag = (DEST_VAR_INT == SRC_VAR_INT);
+        ++ip;
+        break;
+
+      case INSTR_ISEQUALI_VAR_INTEGER:
+        flag = (DEST_VAR_INT == VALUE_INT);
+        ++ip;
+        break;
+
+        /* ISEQUAL.F */
+      case INSTR_ISEQUALF_VAR_VAR:
+        flag = (DEST_VAR_FLOAT == SRC_VAR_FLOAT);
+        ++ip;
+        break;
+
+      case INSTR_ISEQUALF_VAR_FLOAT:
+        flag = (DEST_VAR_FLOAT == VALUE_FLOAT);
+        ++ip;
+        break;
+
+        /* ISLOWER.I */
+      case INSTR_ISLOWERI_VAR_VAR:
+        flag = (DEST_VAR_INT < SRC_VAR_INT);
+        ++ip;
+        break;
+
+      case INSTR_ISLOWERI_VAR_INTEGER:
+        flag = (DEST_VAR_INT < VALUE_INT);
+        ++ip;
+        break;
+
+        /* ISLOWER.F */
+      case INSTR_ISLOWERF_VAR_VAR:
+        flag = (DEST_VAR_FLOAT < SRC_VAR_FLOAT);
+        ++ip;
+        break;
+
+      case INSTR_ISLOWERF_VAR_FLOAT:
+        flag = (DEST_VAR_FLOAT < VALUE_FLOAT);
+        ++ip;
+        break;
+
+        /* ADD.I */
+      case INSTR_ADDI_VAR_VAR:
+        DEST_VAR_INT += SRC_VAR_INT;
+        ++ip;
+        break;
+
+      case INSTR_ADDI_VAR_INTEGER:
+        DEST_VAR_INT += VALUE_INT;
+        ++ip;
+        break;
+
+        /* ADD.F */
+      case INSTR_ADDF_VAR_VAR:
+        DEST_VAR_FLOAT += SRC_VAR_FLOAT;
+        ++ip;
+        break;
+
+      case INSTR_ADDF_VAR_FLOAT:
+        DEST_VAR_FLOAT += VALUE_FLOAT;
+        ++ip;
+        break;
+
+        /* MUL.I */
+      case INSTR_MULI_VAR_VAR:
+        DEST_VAR_INT *= SRC_VAR_INT;
+        ++ip;
+        break;
+
+      case INSTR_MULI_VAR_INTEGER:
+        DEST_VAR_INT *= VALUE_INT;
+        ++ip;
+        break;
+
+        /* MUL.F */
+      case INSTR_MULF_VAR_FLOAT:
+        DEST_VAR_FLOAT *= VALUE_FLOAT;
+        ++ip;
+        break;
+
+      case INSTR_MULF_VAR_VAR:
+        DEST_VAR_FLOAT *= SRC_VAR_FLOAT;
+        ++ip;
+        break;
+
+        /* DIV.I */
+      case INSTR_DIVI_VAR_VAR:
+        DEST_VAR_INT /= SRC_VAR_INT;
+        ++ip;
+        break;
+
+      case INSTR_DIVI_VAR_INTEGER:
+        DEST_VAR_INT /= VALUE_INT;
+        ++ip;
+        break;
+
+        /* DIV.F */
+      case INSTR_DIVF_VAR_FLOAT:
+        DEST_VAR_FLOAT /= VALUE_FLOAT;
+        ++ip;
+        break;
+
+      case INSTR_DIVF_VAR_VAR:
+        DEST_VAR_FLOAT /= SRC_VAR_FLOAT;
+        ++ip;
+        break;
+
+        /* SUB.I */
+      case INSTR_SUBI_VAR_VAR:
+        DEST_VAR_INT -= SRC_VAR_INT;
+        ++ip;
+        break;
+
+      case INSTR_SUBI_VAR_INTEGER:
+        DEST_VAR_INT -= VALUE_INT;
+        ++ip;
+        break;
+
+        /* SUB.F */
+      case INSTR_SUBF_VAR_FLOAT:
+        DEST_VAR_FLOAT -= VALUE_FLOAT;
+        ++ip;
+        break;
+
+      case INSTR_SUBF_VAR_VAR:
+        DEST_VAR_FLOAT -= SRC_VAR_FLOAT;
+        ++ip;
+        break;
+
+        /* CALL */
+      case INSTR_CALL:
+        stack[stack_pointer++] = ip + 1;
+        ip += JUMP_OFFSET;
+        break;
+
+        /* RET */
+      case INSTR_RET:
+        ip = stack[--stack_pointer];
+        if (ip < 0)
+          return;
+        break;
+
+        /* EXT_CALL */
+      case INSTR_EXT_CALL:
+        instr[ip].data.udest.external_function->function (gsl, gsl->vars,
+            instr[ip].data.udest.external_function->vars);
+        ++ip;
+        break;
+
+        /* NOT */
+      case INSTR_NOT_VAR:
+        flag = !flag;
+        ++ip;
+        break;
+
+        /* JNZERO */
+      case INSTR_JNZERO:
+        ip += (flag ? JUMP_OFFSET : 1);
+        break;
+
+      case INSTR_SETS_VAR_VAR:
+        memcpy (pDEST_VAR, pSRC_VAR, DEST_STRUCT_SIZE);
+        ++ip;
+        break;
+
+      case INSTR_ISEQUALS_VAR_VAR:
+        break;
+
+      case INSTR_ADDS_VAR_VAR:
+        /* process integers */
+        i = 0;
+        while (DEST_STRUCT_IBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_IBLOCK (i).size;
+
+          while (j--) {
+            DEST_STRUCT_IBLOCK_VAR (i, j) += SRC_STRUCT_IBLOCK_VAR (i, j);
+          }
+          ++i;
+        }
+        /* process floats */
+        i = 0;
+        while (DEST_STRUCT_FBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_FBLOCK (i).size;
+
+          while (j--) {
+            DEST_STRUCT_FBLOCK_VAR (i, j) += SRC_STRUCT_FBLOCK_VAR (i, j);
+          }
+          ++i;
+        }
+        ++ip;
+        break;
+
+      case INSTR_SUBS_VAR_VAR:
+        /* process integers */
+        i = 0;
+        while (DEST_STRUCT_IBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_IBLOCK (i).size;
+
+          while (j--) {
+            DEST_STRUCT_IBLOCK_VAR (i, j) -= SRC_STRUCT_IBLOCK_VAR (i, j);
+          }
+          ++i;
+        }
+        /* process floats */
+        i = 0;
+        while (DEST_STRUCT_FBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_FBLOCK (i).size;
+
+          while (j--) {
+            DEST_STRUCT_FBLOCK_VAR (i, j) -= SRC_STRUCT_FBLOCK_VAR (i, j);
+          }
+          ++i;
+        }
+        ++ip;
+        break;
+
+      case INSTR_MULS_VAR_VAR:
+        /* process integers */
+        i = 0;
+        while (DEST_STRUCT_IBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_IBLOCK (i).size;
+
+          while (j--) {
+            DEST_STRUCT_IBLOCK_VAR (i, j) *= SRC_STRUCT_IBLOCK_VAR (i, j);
+          }
+          ++i;
+        }
+        /* process floats */
+        i = 0;
+        while (DEST_STRUCT_FBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_FBLOCK (i).size;
+
+          while (j--) {
+            DEST_STRUCT_FBLOCK_VAR (i, j) *= SRC_STRUCT_FBLOCK_VAR (i, j);
+          }
+          ++i;
+        }
+        ++ip;
+        break;
+
+      case INSTR_DIVS_VAR_VAR:
+        /* process integers */
+        i = 0;
+        while (DEST_STRUCT_IBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_IBLOCK (i).size;
+
+          while (j--) {
+            DEST_STRUCT_IBLOCK_VAR (i, j) /= SRC_STRUCT_IBLOCK_VAR (i, j);
+          }
+          ++i;
+        }
+        /* process floats */
+        i = 0;
+        while (DEST_STRUCT_FBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_FBLOCK (i).size;
+
+          while (j--) {
+            DEST_STRUCT_FBLOCK_VAR (i, j) /= SRC_STRUCT_FBLOCK_VAR (i, j);
+          }
+          ++i;
+        }
+        ++ip;
+        break;
+
+      default:
+        printf ("NOT IMPLEMENTED : %d\n", instr[ip].id);
+        ++ip;
+        exit (1);
+    }
+  }
+}                               /* }}} */
+
+int
+gsl_malloc (GoomSL * _this, int size)
+{                               /* {{{ */
+  if (_this->nbPtr >= _this->ptrArraySize) {
+    _this->ptrArraySize *= 2;
+    _this->ptrArray =
+        (void **) realloc (_this->ptrArray,
+        sizeof (void *) * _this->ptrArraySize);
+  }
+  _this->ptrArray[_this->nbPtr] = malloc (size);
+  return _this->nbPtr++;
+}                               /* }}} */
+
+void *
+gsl_get_ptr (GoomSL * _this, int id)
+{                               /* {{{ */
+  if ((id >= 0) && (id < _this->nbPtr))
+    return _this->ptrArray[id];
+  fprintf (stderr, "INVALID GET PTR 0x%08x\n", id);
+  return NULL;
+}                               /* }}} */
+
+void
+gsl_free_ptr (GoomSL * _this, int id)
+{                               /* {{{ */
+  if ((id >= 0) && (id < _this->nbPtr)) {
+    free (_this->ptrArray[id]);
+    _this->ptrArray[id] = 0;
+  }
+}                               /* }}} */
+
+void
+gsl_enternamespace (const char *name)
+{                               /* {{{ */
+  HashValue *val = goom_hash_get (currentGoomSL->functions, name);
+
+  if (val) {
+    ExternalFunctionStruct *function = (ExternalFunctionStruct *) val->ptr;
+
+    currentGoomSL->currentNS++;
+    currentGoomSL->namespaces[currentGoomSL->currentNS] = function->vars;
+  } else {
+    fprintf (stderr, "ERROR: Line %d, Could not find namespace: %s\n",
+        currentGoomSL->num_lines, name);
+    exit (1);
+  }
+}                               /* }}} */
+
+void
+gsl_reenternamespace (GoomHash * nsinfo)
+{
+  currentGoomSL->currentNS++;
+  currentGoomSL->namespaces[currentGoomSL->currentNS] = nsinfo;
+}
+
+GoomHash *
+gsl_leavenamespace (void)
+{                               /* {{{ */
+  currentGoomSL->currentNS--;
+  return currentGoomSL->namespaces[currentGoomSL->currentNS + 1];
+}                               /* }}} */
+
+GoomHash *
+gsl_find_namespace (const char *name)
+{                               /* {{{ */
+  int i;
+
+  for (i = currentGoomSL->currentNS; i >= 0; --i) {
+    if (goom_hash_get (currentGoomSL->namespaces[i], name))
+      return currentGoomSL->namespaces[i];
+  }
+  return NULL;
+}                               /* }}} */
+
+void
+gsl_declare_task (const char *name)
+{                               /* {{{ */
+  if (goom_hash_get (currentGoomSL->functions, name)) {
+    return;
+  } else {
+    ExternalFunctionStruct *gef =
+        (ExternalFunctionStruct *) malloc (sizeof (ExternalFunctionStruct));
+    gef->function = 0;
+    gef->vars = goom_hash_new ();
+    gef->is_extern = 0;
+    goom_hash_put_ptr (currentGoomSL->functions, name, (void *) gef);
+  }
+}                               /* }}} */
+
+void
+gsl_declare_external_task (const char *name)
+{                               /* {{{ */
+  if (goom_hash_get (currentGoomSL->functions, name)) {
+    fprintf (stderr, "ERROR: Line %d, Duplicate declaration of %s\n",
+        currentGoomSL->num_lines, name);
+    return;
+  } else {
+    ExternalFunctionStruct *gef =
+        (ExternalFunctionStruct *) malloc (sizeof (ExternalFunctionStruct));
+    gef->function = 0;
+    gef->vars = goom_hash_new ();
+    gef->is_extern = 1;
+    goom_hash_put_ptr (currentGoomSL->functions, name, (void *) gef);
+  }
+}                               /* }}} */
+
+static void
+reset_scanner (GoomSL * gss)
+{                               /* {{{ */
+  gss->num_lines = 0;
+  gss->instr = NULL;
+  iflow_clean (gss->iflow);
+
+  /* reset variables */
+  goom_hash_free (gss->vars);
+  gss->vars = goom_hash_new ();
+  gss->currentNS = 0;
+  gss->namespaces[0] = gss->vars;
+
+  goom_hash_free (gss->structIDS);
+  gss->structIDS = goom_hash_new ();
+
+  while (gss->nbStructID > 0) {
+    int i;
+
+    gss->nbStructID--;
+    for (i = 0; i < gss->gsl_struct[gss->nbStructID]->nbFields; ++i)
+      free (gss->gsl_struct[gss->nbStructID]->fields[i]);
+    free (gss->gsl_struct[gss->nbStructID]);
+  }
+
+  gss->compilationOK = 1;
+
+  goom_heap_delete (gss->data_heap);
+  gss->data_heap = goom_heap_new ();
+}                               /* }}} */
+
+static void
+calculate_labels (InstructionFlow * iflow)
+{                               /* {{{ */
+  int i = 0;
+
+  while (i < iflow->number) {
+    Instruction *instr = iflow->instr[i];
+
+    if (instr->jump_label) {
+      HashValue *label = goom_hash_get (iflow->labels, instr->jump_label);
+
+      if (label) {
+        instr->data.udest.jump_offset = -instr->address + label->i;
+      } else {
+        fprintf (stderr, "ERROR: Line %d, Could not find label %s\n",
+            instr->line_number, instr->jump_label);
+        instr->id = INSTR_NOP;
+        instr->nop_label = 0;
+        exit (1);
+      }
+    }
+    ++i;
+  }
+}                               /* }}} */
+
+static int
+powerOfTwo (int i)
+{
+  int b;
+
+  for (b = 0; b < 31; b++)
+    if (i == (1 << b))
+      return b;
+  return 0;
+}
+
+/* Cree un flow d'instruction optimise */
+static void
+gsl_create_fast_iflow (void)
+{                               /* {{{ */
+  int number = currentGoomSL->iflow->number;
+  int i;
+
+#ifdef USE_JITC_X86
+
+  /* pour compatibilite avec les MACROS servant a execution */
+  int ip = 0;
+  GoomSL *gsl = currentGoomSL;
+
+  JitcX86Env *jitc;
+
+  if (currentGoomSL->jitc != NULL)
+    jitc_x86_delete (currentGoomSL->jitc);
+  jitc = currentGoomSL->jitc = jitc_x86_env_new (0xffff);
+  currentGoomSL->jitc_func = jitc_prepare_func (jitc);
+
+#if 0
+#define SRC_STRUCT_ID  instr[ip].data.usrc.var_int[-1]
+#define DEST_STRUCT_ID instr[ip].data.udest.var_int[-1]
+#define SRC_STRUCT_IBLOCK(i)  gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i]
+#define SRC_STRUCT_FBLOCK(i)  gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i]
+#define DEST_STRUCT_IBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i]
+#define DEST_STRUCT_FBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i]
+#define DEST_STRUCT_IBLOCK_VAR(i,j) \
+  ((int*)((char*)pDEST_VAR   + gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i].data))[j]
+#define DEST_STRUCT_FBLOCK_VAR(i,j) \
+  ((float*)((char*)pDEST_VAR + gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i].data))[j]
+#define SRC_STRUCT_IBLOCK_VAR(i,j) \
+  ((int*)((char*)pSRC_VAR    + gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i].data))[j]
+#define SRC_STRUCT_FBLOCK_VAR(i,j) \
+  ((float*)((char*)pSRC_VAR  + gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i].data))[j]
+#define DEST_STRUCT_SIZE      gsl->gsl_struct[DEST_STRUCT_ID]->size
+#endif
+
+  JITC_JUMP_LABEL (jitc, "__very_end__");
+  JITC_ADD_LABEL (jitc, "__very_start__");
+
+  for (i = 0; i < number; ++i) {
+    Instruction *instr = currentGoomSL->iflow->instr[i];
+
+    switch (instr->id) {
+      case INSTR_SETI_VAR_INTEGER:
+        jitc_add (jitc, "mov [$d], $d", instr->data.udest.var_int,
+            instr->data.usrc.value_int);
+        break;
+      case INSTR_SETI_VAR_VAR:
+        jitc_add (jitc, "mov eax, [$d]", instr->data.usrc.var_int);
+        jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+        break;
+        /* SET.F */
+      case INSTR_SETF_VAR_FLOAT:
+        jitc_add (jitc, "mov [$d], $d", instr->data.udest.var_float,
+            *(int *) (&instr->data.usrc.value_float));
+        break;
+      case INSTR_SETF_VAR_VAR:
+        jitc_add (jitc, "mov eax, [$d]", instr->data.usrc.var_float);
+        jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_float);
+        break;
+      case INSTR_NOP:
+        if (instr->nop_label != 0)
+          JITC_ADD_LABEL (jitc, instr->nop_label);
+        break;
+      case INSTR_JUMP:
+        JITC_JUMP_LABEL (jitc, instr->jump_label);
+        break;
+      case INSTR_SETP_VAR_PTR:
+        jitc_add (jitc, "mov [$d], $d", instr->data.udest.var_ptr,
+            instr->data.usrc.value_ptr);
+        break;
+      case INSTR_SETP_VAR_VAR:
+        jitc_add (jitc, "mov eax, [$d]", instr->data.usrc.var_ptr);
+        jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_ptr);
+        break;
+      case INSTR_SUBI_VAR_INTEGER:
+        jitc_add (jitc, "add [$d],  $d", instr->data.udest.var_int,
+            -instr->data.usrc.value_int);
+        break;
+      case INSTR_SUBI_VAR_VAR:
+        jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+        jitc_add (jitc, "sub eax, [$d]", instr->data.usrc.var_int);
+        jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+        break;
+      case INSTR_SUBF_VAR_FLOAT:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_SUBF_VAR_VAR:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_ISLOWERF_VAR_VAR:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_ISLOWERF_VAR_FLOAT:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_ISLOWERI_VAR_VAR:
+        jitc_add (jitc, "mov edx, [$d]", instr->data.udest.var_int);
+        jitc_add (jitc, "sub edx, [$d]", instr->data.usrc.var_int);
+        jitc_add (jitc, "shr edx, $d", 31);
+        break;
+      case INSTR_ISLOWERI_VAR_INTEGER:
+        jitc_add (jitc, "mov edx, [$d]", instr->data.udest.var_int);
+        jitc_add (jitc, "sub edx, $d", instr->data.usrc.value_int);
+        jitc_add (jitc, "shr edx, $d", 31);
+        break;
+      case INSTR_ADDI_VAR_INTEGER:
+        jitc_add (jitc, "add [$d],  $d", instr->data.udest.var_int,
+            instr->data.usrc.value_int);
+        break;
+      case INSTR_ADDI_VAR_VAR:
+        jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+        jitc_add (jitc, "add eax, [$d]", instr->data.usrc.var_int);
+        jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+        break;
+      case INSTR_ADDF_VAR_FLOAT:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_ADDF_VAR_VAR:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_MULI_VAR_INTEGER:
+        if (instr->data.usrc.value_int != 1) {
+          int po2 = powerOfTwo (instr->data.usrc.value_int);
+
+          if (po2) {
+            /* performs (V / 2^n) by doing V >> n */
+            jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
+            jitc_add (jitc, "sal  eax, $d", po2);
+            jitc_add (jitc, "mov  [$d], eax", instr->data.udest.var_int);
+          } else {
+            jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
+            jitc_add (jitc, "imul eax, $d", instr->data.usrc.value_int);
+            jitc_add (jitc, "mov  [$d], eax", instr->data.udest.var_int);
+          }
+        }
+        break;
+      case INSTR_MULI_VAR_VAR:
+        jitc_add (jitc, "mov  eax,  [$d]", instr->data.udest.var_int);
+        jitc_add (jitc, "imul eax,  [$d]", instr->data.usrc.var_int);
+        jitc_add (jitc, "mov  [$d], eax", instr->data.udest.var_int);
+        break;
+      case INSTR_MULF_VAR_FLOAT:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_MULF_VAR_VAR:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_DIVI_VAR_INTEGER:
+        if ((instr->data.usrc.value_int != 1)
+            && (instr->data.usrc.value_int != 0)) {
+          int po2 = powerOfTwo (instr->data.usrc.value_int);
+
+          if (po2) {
+            /* performs (V / 2^n) by doing V >> n */
+            jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
+            jitc_add (jitc, "sar  eax, $d", po2);
+            jitc_add (jitc, "mov  [$d], eax", instr->data.udest.var_int);
+          } else {
+            /* performs (V/n) by doing (V*(32^2/n)) */
+            long coef;
+            double dcoef =
+                (double) 4294967296.0 / (double) instr->data.usrc.value_int;
+            if (dcoef < 0.0)
+              dcoef = -dcoef;
+            coef = (long) floor (dcoef);
+            dcoef -= floor (dcoef);
+            if (dcoef < 0.5)
+              coef += 1;
+
+            jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
+            jitc_add (jitc, "mov  edx, $d", coef);
+            jitc_add (jitc, "imul edx");
+            if (instr->data.usrc.value_int < 0)
+              jitc_add (jitc, "neg edx");
+            jitc_add (jitc, "mov [$d], edx", instr->data.udest.var_int);
+          }
+        }
+        break;
+      case INSTR_DIVI_VAR_VAR:
+        jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
+        jitc_add (jitc, "cdq"); /* sign extend eax into edx */
+        jitc_add (jitc, "idiv [$d]", instr->data.usrc.var_int);
+        jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+        break;
+      case INSTR_DIVF_VAR_FLOAT:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_DIVF_VAR_VAR:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_JZERO:
+        jitc_add (jitc, "cmp edx, $d", 0);
+        jitc_add (jitc, "je $s", instr->jump_label);
+        break;
+      case INSTR_ISEQUALP_VAR_VAR:
+        jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_ptr);
+        jitc_add (jitc, "mov edx, $d", 0);
+        jitc_add (jitc, "cmp eax, [$d]", instr->data.usrc.var_ptr);
+        jitc_add (jitc, "jne $d", 1);
+        jitc_add (jitc, "inc edx");
+        break;
+      case INSTR_ISEQUALP_VAR_PTR:
+        jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_ptr);
+        jitc_add (jitc, "mov edx, $d", 0);
+        jitc_add (jitc, "cmp eax, $d", instr->data.usrc.value_ptr);
+        jitc_add (jitc, "jne $d", 1);
+        jitc_add (jitc, "inc edx");
+        break;
+      case INSTR_ISEQUALI_VAR_VAR:
+        jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+        jitc_add (jitc, "mov edx, $d", 0);
+        jitc_add (jitc, "cmp eax, [$d]", instr->data.usrc.var_int);
+        jitc_add (jitc, "jne $d", 1);
+        jitc_add (jitc, "inc edx");
+        break;
+      case INSTR_ISEQUALI_VAR_INTEGER:
+        jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+        jitc_add (jitc, "mov edx, $d", 0);
+        jitc_add (jitc, "cmp eax, $d", instr->data.usrc.value_int);
+        jitc_add (jitc, "jne $d", 1);
+        jitc_add (jitc, "inc edx");
+        break;
+      case INSTR_ISEQUALF_VAR_VAR:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_ISEQUALF_VAR_FLOAT:
+        printf ("NOT IMPLEMENTED : %d\n", instr->id);
+        break;
+      case INSTR_CALL:
+        jitc_add (jitc, "call $s", instr->jump_label);
+        break;
+      case INSTR_RET:
+        jitc_add (jitc, "ret");
+        break;
+      case INSTR_EXT_CALL:
+        jitc_add (jitc, "mov eax, [$d]",
+            &(instr->data.udest.external_function->vars));
+        jitc_add (jitc, "push eax");
+        jitc_add (jitc, "mov edx, [$d]", &(currentGoomSL->vars));
+        jitc_add (jitc, "push edx");
+        jitc_add (jitc, "mov eax, [$d]", &(currentGoomSL));
+        jitc_add (jitc, "push eax");
+
+        jitc_add (jitc, "mov eax, [$d]",
+            &(instr->data.udest.external_function));
+        jitc_add (jitc, "mov eax, [eax]");
+        jitc_add (jitc, "call [eax]");
+        jitc_add (jitc, "add esp, $d", 12);
+        break;
+      case INSTR_NOT_VAR:
+        jitc_add (jitc, "mov eax, edx");
+        jitc_add (jitc, "mov edx, $d", 1);
+        jitc_add (jitc, "sub edx, eax");
+        break;
+      case INSTR_JNZERO:
+        jitc_add (jitc, "cmp edx, $d", 0);
+        jitc_add (jitc, "jne $s", instr->jump_label);
+        break;
+      case INSTR_SETS_VAR_VAR:
+      {
+        int loop = DEST_STRUCT_SIZE / sizeof (int);
+        int dst = (int) pDEST_VAR;
+        int src = (int) pSRC_VAR;
+
+        while (loop--) {
+          jitc_add (jitc, "mov eax, [$d]", src);
+          jitc_add (jitc, "mov [$d], eax", dst);
+          src += 4;
+          dst += 4;
+        }
+      }
+        break;
+      case INSTR_ISEQUALS_VAR_VAR:
+        break;
+      case INSTR_ADDS_VAR_VAR:
+      {
+        /* process integers */
+        int i = 0;
+
+        while (DEST_STRUCT_IBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_IBLOCK (i).size;
+
+          while (j--) {         /* TODO interlace 2 */
+            jitc_add (jitc, "mov eax, [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
+            jitc_add (jitc, "add eax, [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
+            jitc_add (jitc, "mov [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
+          }
+          ++i;
+        }
+        /* process floats */
+        i = 0;
+        while (DEST_STRUCT_FBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_FBLOCK (i).size;
+
+          while (j--) {
+            /* DEST_STRUCT_FBLOCK_VAR(i,j) += SRC_STRUCT_FBLOCK_VAR(i,j); */
+            /* TODO */
+          }
+          ++i;
+        }
+        break;
+      }
+      case INSTR_SUBS_VAR_VAR:
+      {
+        /* process integers */
+        int i = 0;
+
+        while (DEST_STRUCT_IBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_IBLOCK (i).size;
+
+          while (j--) {
+            jitc_add (jitc, "mov eax, [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
+            jitc_add (jitc, "sub eax, [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
+            jitc_add (jitc, "mov [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
+          }
+          ++i;
+        }
+        break;
+      }
+      case INSTR_MULS_VAR_VAR:
+      {
+        /* process integers */
+        int i = 0;
+
+        while (DEST_STRUCT_IBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_IBLOCK (i).size;
+
+          while (j--) {
+            jitc_add (jitc, "mov  eax,  [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
+            jitc_add (jitc, "imul eax,  [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
+            jitc_add (jitc, "mov  [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
+          }
+          ++i;
+        }
+        break;
+      }
+      case INSTR_DIVS_VAR_VAR:
+      {
+        /* process integers */
+        int i = 0;
+
+        while (DEST_STRUCT_IBLOCK (i).size > 0) {
+          int j = DEST_STRUCT_IBLOCK (i).size;
+
+          while (j--) {
+            jitc_add (jitc, "mov  eax,  [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
+            jitc_add (jitc, "cdq");
+            jitc_add (jitc, "idiv [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
+            jitc_add (jitc, "mov  [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
+          }
+          ++i;
+        }
+        break;
+      }
+    }
+  }
+
+  JITC_ADD_LABEL (jitc, "__very_end__");
+  jitc_add (jitc, "call $s", "__very_start__");
+  jitc_add (jitc, "mov eax, $d", 0);
+  jitc_validate_func (jitc);
+#else
+  InstructionFlow *iflow = currentGoomSL->iflow;
+  FastInstructionFlow *fastiflow =
+      (FastInstructionFlow *) malloc (sizeof (FastInstructionFlow));
+  fastiflow->mallocedInstr = calloc (number * 16, sizeof (FastInstruction));
+  /* fastiflow->instr = (FastInstruction*)(((int)fastiflow->mallocedInstr) + 16 - (((int)fastiflow->mallocedInstr)%16)); */
+  fastiflow->instr = (FastInstruction *) fastiflow->mallocedInstr;
+  fastiflow->number = number;
+  for (i = 0; i < number; ++i) {
+    fastiflow->instr[i].id = iflow->instr[i]->id;
+    fastiflow->instr[i].data = iflow->instr[i]->data;
+    fastiflow->instr[i].proto = iflow->instr[i];
+  }
+  currentGoomSL->fastiflow = fastiflow;
+#endif
+}                               /* }}} */
+
+void yy_scan_string (const char *str);
+void yyparse (void);
+
+GoomHash *
+gsl_globals (GoomSL * _this)
+{
+  return _this->vars;
+}
+
+
+/**
+ * Some native external functions
+ */
+static void
+ext_charAt (GoomSL * gsl, GoomHash * global, GoomHash * local)
+{
+  char *string = GSL_LOCAL_PTR (gsl, local, "value");
+  int index = GSL_LOCAL_INT (gsl, local, "index");
+
+  GSL_GLOBAL_INT (gsl, "charAt") = 0;
+  if (string == NULL) {
+    return;
+  }
+  if (index < strlen (string))
+    GSL_GLOBAL_INT (gsl, "charAt") = string[index];
+}
+
+static void
+ext_i2f (GoomSL * gsl, GoomHash * global, GoomHash * local)
+{
+  int i = GSL_LOCAL_INT (gsl, local, "value");
+
+  GSL_GLOBAL_FLOAT (gsl, "i2f") = i;
+}
+
+static void
+ext_f2i (GoomSL * gsl, GoomHash * global, GoomHash * local)
+{
+  float f = GSL_LOCAL_FLOAT (gsl, local, "value");
+
+  GSL_GLOBAL_INT (gsl, "f2i") = f;
+}
+
+/**
+ *
+ */
+void
+gsl_compile (GoomSL * _currentGoomSL, const char *script)
+{                               /* {{{ */
+  char *script_and_externals;
+  static const char *sBinds =
+      "external <charAt: string value, int index> : int\n"
+      "external <f2i: float value> : int\n"
+      "external <i2f: int value> : float\n";
+
+#ifdef VERBOSE
+  printf ("\n=== Starting Compilation ===\n");
+#endif
+
+  script_and_externals = malloc (strlen (script) + strlen (sBinds) + 2);
+  strcpy (script_and_externals, sBinds);
+  strcat (script_and_externals, script);
+
+  /* 0- reset */
+  currentGoomSL = _currentGoomSL;
+  reset_scanner (currentGoomSL);
+
+  /* 1- create the syntaxic tree */
+  yy_scan_string (script_and_externals);
+  yyparse ();
+
+  /* 2- generate code */
+  gsl_commit_compilation ();
+
+  /* 3- resolve symbols */
+  calculate_labels (currentGoomSL->iflow);
+
+  /* 4- optimize code */
+  gsl_create_fast_iflow ();
+
+  /* 5- bind a few internal functions */
+  gsl_bind_function (currentGoomSL, "charAt", ext_charAt);
+  gsl_bind_function (currentGoomSL, "f2i", ext_f2i);
+  gsl_bind_function (currentGoomSL, "i2f", ext_i2f);
+  free (script_and_externals);
+
+#ifdef VERBOSE
+  printf ("=== Compilation done. # of lines: %d. # of instr: %d ===\n",
+      currentGoomSL->num_lines, currentGoomSL->iflow->number);
+#endif
+}                               /* }}} */
+
+void
+gsl_execute (GoomSL * scanner)
+{                               /* {{{ */
+  if (scanner->compilationOK) {
+#if USE_JITC_X86
+    scanner->jitc_func ();
+#else
+    iflow_execute (scanner->fastiflow, scanner);
+#endif
+  }
+}                               /* }}} */
+
+GoomSL *
+gsl_new (void)
+{                               /* {{{ */
+  GoomSL *gss = (GoomSL *) malloc (sizeof (GoomSL));
+
+  gss->iflow = iflow_new ();
+  gss->vars = goom_hash_new ();
+  gss->functions = goom_hash_new ();
+  gss->nbStructID = 0;
+  gss->structIDS = goom_hash_new ();
+  gss->gsl_struct_size = 32;
+  gss->gsl_struct =
+      (GSL_Struct **) malloc (gss->gsl_struct_size * sizeof (GSL_Struct *));
+  gss->currentNS = 0;
+  gss->namespaces[0] = gss->vars;
+  gss->data_heap = goom_heap_new ();
+
+  reset_scanner (gss);
+
+  gss->compilationOK = 0;
+  gss->nbPtr = 0;
+  gss->ptrArraySize = 256;
+  gss->ptrArray = (void **) malloc (gss->ptrArraySize * sizeof (void *));
+#ifdef USE_JITC_X86
+  gss->jitc = NULL;
+#endif
+  return gss;
+}                               /* }}} */
+
+void
+gsl_bind_function (GoomSL * gss, const char *fname,
+    GoomSL_ExternalFunction func)
+{                               /* {{{ */
+  HashValue *val = goom_hash_get (gss->functions, fname);
+
+  if (val) {
+    ExternalFunctionStruct *gef = (ExternalFunctionStruct *) val->ptr;
+
+    gef->function = func;
+  } else
+    fprintf (stderr, "Unable to bind function %s\n", fname);
+}                               /* }}} */
+
+int
+gsl_is_compiled (GoomSL * gss)
+{                               /* {{{ */
+  return gss->compilationOK;
+}                               /* }}} */
+
+void
+gsl_free (GoomSL * gss)
+{                               /* {{{ */
+  iflow_free (gss->iflow);
+  free (gss->vars);
+  free (gss->functions);
+  free (gss);
+}                               /* }}} */
+
+
+static int gsl_nb_import;
+static char gsl_already_imported[256][256];
+
+char *
+gsl_init_buffer (const char *fname)
+{
+  char *fbuffer;
+
+  fbuffer = (char *) malloc (512);
+  fbuffer[0] = 0;
+  gsl_nb_import = 0;
+  if (fname)
+    gsl_append_file_to_buffer (fname, &fbuffer);
+  return fbuffer;
+}
+
+static char *
+gsl_read_file (const char *fname)
+{
+  FILE *f;
+  char *buffer;
+  int fsize;
+
+  f = fopen (fname, "rt");
+  if (!f) {
+    fprintf (stderr, "ERROR: Could not load file %s\n", fname);
+    exit (1);
+  }
+  fseek (f, 0, SEEK_END);
+  fsize = ftell (f);
+  rewind (f);
+  buffer = (char *) malloc (fsize + 512);
+  fread (buffer, 1, fsize, f);
+  fclose (f);
+  buffer[fsize] = 0;
+  return buffer;
+}
+
+void
+gsl_append_file_to_buffer (const char *fname, char **buffer)
+{
+  char *fbuffer;
+  int size, fsize, i = 0;
+  char reset_msg[256];
+
+  /* look if the file have not been already imported */
+  for (i = 0; i < gsl_nb_import; ++i) {
+    if (strcmp (gsl_already_imported[i], fname) == 0)
+      return;
+  }
+
+  /* add fname to the already imported files. */
+  strcpy (gsl_already_imported[gsl_nb_import++], fname);
+
+  /* load the file */
+  fbuffer = gsl_read_file (fname);
+  fsize = strlen (fbuffer);
+
+  /* look for #import */
+  while (fbuffer[i]) {
+    if ((fbuffer[i] == '#') && (fbuffer[i + 1] == 'i')) {
+      char impName[256];
+      int j;
+
+      while (fbuffer[i] && (fbuffer[i] != ' '))
+        i++;
+      i++;
+      j = 0;
+      while (fbuffer[i] && (fbuffer[i] != '\n'))
+        impName[j++] = fbuffer[i++];
+      impName[j++] = 0;
+      gsl_append_file_to_buffer (impName, buffer);
+    }
+    i++;
+  }
+
+  sprintf (reset_msg, "\n#FILE %s#\n#RST_LINE#\n", fname);
+  strcat (*buffer, reset_msg);
+  size = strlen (*buffer);
+  *buffer = (char *) realloc (*buffer, size + fsize + 256);
+  strcat ((*buffer) + size, fbuffer);
+  free (fbuffer);
+}
diff --git a/gst/goom/goomsl.h b/gst/goom/goomsl.h
new file mode 100644 (file)
index 0000000..b9f20d6
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _GOOMSL_H
+#define _GOOMSL_H
+
+#include "goomsl_hash.h"
+
+typedef struct _GoomSL GoomSL;
+typedef void (*GoomSL_ExternalFunction)(GoomSL *gsl, GoomHash *global_vars, GoomHash *local_vars);
+
+GoomSL*gsl_new(void);
+void   gsl_free(GoomSL *gss);
+
+char *gsl_init_buffer(const char *file_name);
+void  gsl_append_file_to_buffer(const char *file_name, char **buffer);
+
+void   gsl_compile (GoomSL *scanner, const char *script);
+void   gsl_execute (GoomSL *scanner);
+int    gsl_is_compiled  (GoomSL *gss);
+void   gsl_bind_function(GoomSL *gss, const char *fname, GoomSL_ExternalFunction func);
+
+int    gsl_malloc  (GoomSL *_this, int size);
+void  *gsl_get_ptr (GoomSL *_this, int id);
+void   gsl_free_ptr(GoomSL *_this, int id);
+
+GoomHash *gsl_globals(GoomSL *_this);
+
+#define GSL_LOCAL_PTR(gsl,local,name)   gsl_get_ptr(gsl, *(int*)goom_hash_get(local,name)->ptr)
+#define GSL_LOCAL_INT(gsl,local,name)   (*(int*)goom_hash_get(local,name)->ptr)
+#define GSL_LOCAL_FLOAT(gsl,local,name) (*(float*)goom_hash_get(local,name)->ptr)
+
+#define GSL_GLOBAL_PTR(gsl,name)   gsl_get_ptr(gsl, *(int*)goom_hash_get(gsl_globals(gsl),name)->ptr)
+#define GSL_GLOBAL_INT(gsl,name)   (*(int*)goom_hash_get(gsl_globals(gsl),name)->ptr)
+#define GSL_GLOBAL_FLOAT(gsl,name) (*(float*)goom_hash_get(gsl_globals(gsl),name)->ptr)
+
+#endif
diff --git a/gst/goom/goomsl_hash.c b/gst/goom/goomsl_hash.c
new file mode 100644 (file)
index 0000000..3ce38a7
--- /dev/null
@@ -0,0 +1,153 @@
+#include "goomsl_hash.h"
+#include <string.h>
+#include <stdlib.h>
+
+static GoomHashEntry *
+entry_new (const char *key, HashValue value)
+{
+
+  int len = strlen (key);
+  GoomHashEntry *entry = (GoomHashEntry *) malloc (sizeof (GoomHashEntry));
+
+  entry->key = (char *) malloc (len + 1);
+  memcpy (entry->key, key, len + 1);
+  entry->value = value;
+  entry->lower = NULL;
+  entry->upper = NULL;
+
+  return entry;
+}
+
+static void
+entry_free (GoomHashEntry * entry)
+{
+  if (entry != NULL) {
+    entry_free (entry->lower);
+    entry_free (entry->upper);
+    free (entry->key);
+    free (entry);
+  }
+}
+
+static void
+entry_put (GoomHashEntry * entry, const char *key, HashValue value)
+{
+  int cmp = strcmp (key, entry->key);
+
+  if (cmp == 0) {
+    entry->value = value;
+  } else if (cmp > 0) {
+    if (entry->upper == NULL)
+      entry->upper = entry_new (key, value);
+    else
+      entry_put (entry->upper, key, value);
+  } else {
+    if (entry->lower == NULL)
+      entry->lower = entry_new (key, value);
+    else
+      entry_put (entry->lower, key, value);
+  }
+}
+
+static HashValue *
+entry_get (GoomHashEntry * entry, const char *key)
+{
+
+  int cmp;
+
+  if (entry == NULL)
+    return NULL;
+  cmp = strcmp (key, entry->key);
+  if (cmp > 0)
+    return entry_get (entry->upper, key);
+  else if (cmp < 0)
+    return entry_get (entry->lower, key);
+  else
+    return &(entry->value);
+}
+
+GoomHash *
+goom_hash_new ()
+{
+  GoomHash *_this = (GoomHash *) malloc (sizeof (GoomHash));
+
+  _this->root = NULL;
+  _this->number_of_puts = 0;
+  return _this;
+}
+
+void
+goom_hash_free (GoomHash * _this)
+{
+  entry_free (_this->root);
+  free (_this);
+}
+
+void
+goom_hash_put (GoomHash * _this, const char *key, HashValue value)
+{
+  _this->number_of_puts += 1;
+  if (_this->root == NULL)
+    _this->root = entry_new (key, value);
+  else
+    entry_put (_this->root, key, value);
+}
+
+HashValue *
+goom_hash_get (GoomHash * _this, const char *key)
+{
+  if (_this == NULL)
+    return NULL;
+  return entry_get (_this->root, key);
+}
+
+void
+goom_hash_put_int (GoomHash * _this, const char *key, int i)
+{
+  HashValue value;
+
+  value.i = i;
+  goom_hash_put (_this, key, value);
+}
+
+void
+goom_hash_put_float (GoomHash * _this, const char *key, float f)
+{
+  HashValue value;
+
+  value.f = f;
+  goom_hash_put (_this, key, value);
+}
+
+void
+goom_hash_put_ptr (GoomHash * _this, const char *key, void *ptr)
+{
+  HashValue value;
+
+  value.ptr = ptr;
+  goom_hash_put (_this, key, value);
+}
+
+/* FOR EACH */
+
+static void
+_goom_hash_for_each (GoomHash * _this, GoomHashEntry * entry, GH_Func func)
+{
+  if (entry == NULL)
+    return;
+  func (_this, entry->key, &(entry->value));
+  _goom_hash_for_each (_this, entry->lower, func);
+  _goom_hash_for_each (_this, entry->upper, func);
+}
+
+void
+goom_hash_for_each (GoomHash * _this, GH_Func func)
+{
+  _goom_hash_for_each (_this, _this->root, func);
+}
+
+int
+goom_hash_number_of_puts (GoomHash * _this)
+{
+  return _this->number_of_puts;
+}
diff --git a/gst/goom/goomsl_hash.h b/gst/goom/goomsl_hash.h
new file mode 100644 (file)
index 0000000..26f4516
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _GOOMSL_HASH_H
+#define _GOOMSL_HASH_H
+
+typedef struct GOOM_HASH_ENTRY GoomHashEntry;
+typedef struct GOOM_HASH GoomHash;
+
+typedef union {
+    void *ptr;
+    int   i;
+    float f;
+} HashValue;
+
+struct GOOM_HASH_ENTRY {
+       char          *key;
+  HashValue      value;
+       GoomHashEntry *lower;
+       GoomHashEntry *upper;
+};
+
+struct GOOM_HASH {
+       GoomHashEntry *root;
+  int number_of_puts;
+};
+
+GoomHash *goom_hash_new();
+void      goom_hash_free(GoomHash *gh);
+
+void goom_hash_put(GoomHash *gh, const char *key, HashValue value);
+HashValue *goom_hash_get(GoomHash *gh, const char *key);
+
+void goom_hash_put_int  (GoomHash *_this, const char *key, int i);
+void goom_hash_put_float(GoomHash *_this, const char *key, float f);
+void goom_hash_put_ptr  (GoomHash *_this, const char *key, void *ptr);
+
+typedef void (*GH_Func)(GoomHash *caller, const char *key, HashValue *value);
+
+void goom_hash_for_each(GoomHash *_this, GH_Func func);
+int goom_hash_number_of_puts(GoomHash *_this);
+
+#endif /* _GOOM_HASH_H */
diff --git a/gst/goom/goomsl_heap.c b/gst/goom/goomsl_heap.c
new file mode 100644 (file)
index 0000000..4cbab5c
--- /dev/null
@@ -0,0 +1,126 @@
+#include "goomsl_heap.h"
+#include <stdlib.h>
+
+struct _GOOM_HEAP
+{
+  void **arrays;
+  int number_of_arrays;
+  int size_of_each_array;
+  int consumed_in_last_array;
+};
+
+/* Constructors / Destructor */
+GoomHeap *
+goom_heap_new (void)
+{
+  return goom_heap_new_with_granularity (4096);
+}
+
+GoomHeap *
+goom_heap_new_with_granularity (int granularity)
+{
+  GoomHeap *_this;
+
+  _this = (GoomHeap *) malloc (sizeof (GoomHeap));
+  _this->number_of_arrays = 0;
+  _this->size_of_each_array = granularity;
+  _this->consumed_in_last_array = 0;
+  _this->arrays = (void **) malloc (sizeof (void *));
+  return _this;
+}
+
+void
+goom_heap_delete (GoomHeap * _this)
+{
+  int i;
+
+  for (i = 0; i < _this->number_of_arrays; ++i) {
+    free (_this->arrays[i]);
+  }
+  free (_this->arrays);
+  free (_this);
+}
+
+static void
+align_it (GoomHeap * _this, int alignment)
+{
+  if ((alignment > 1) && (_this->number_of_arrays > 0)) {
+    void *last_array = _this->arrays[_this->number_of_arrays - 1];
+    int last_address = (int) last_array + _this->consumed_in_last_array;
+    int decal = (last_address % alignment);
+
+    if (decal != 0) {
+      _this->consumed_in_last_array += alignment - decal;
+    }
+  }
+}
+
+void *
+goom_heap_malloc_with_alignment_prefixed (GoomHeap * _this, int nb_bytes,
+    int alignment, int prefix_bytes)
+{
+  void *retval = NULL;
+
+  /* d'abord on gere les problemes d'alignement */
+  _this->consumed_in_last_array += prefix_bytes;
+  align_it (_this, alignment);
+
+  /* ensuite on verifie que la quantite de memoire demandee tient dans le buffer */
+  if ((_this->consumed_in_last_array + nb_bytes >= _this->size_of_each_array)
+      || (_this->number_of_arrays == 0)) {
+
+    if (prefix_bytes + nb_bytes + alignment >= _this->size_of_each_array) {
+
+      /* Si la zone demandee est plus grosse que la granularitee */
+      /* On alloue un buffer plus gros que les autres */
+      _this->arrays =
+          (void **) realloc (_this->arrays,
+          sizeof (void *) * (_this->number_of_arrays + 2));
+
+      _this->number_of_arrays += 1;
+      _this->consumed_in_last_array = prefix_bytes;
+
+      _this->arrays[_this->number_of_arrays - 1] =
+          malloc (prefix_bytes + nb_bytes + alignment);
+      align_it (_this, alignment);
+      retval =
+          (void *) ((char *) _this->arrays[_this->number_of_arrays - 1] +
+          _this->consumed_in_last_array);
+
+      /* puis on repart sur un nouveau buffer vide */
+      _this->number_of_arrays += 1;
+      _this->consumed_in_last_array = 0;
+      _this->arrays[_this->number_of_arrays - 1] =
+          malloc (_this->size_of_each_array);
+      return retval;
+    } else {
+      _this->number_of_arrays += 1;
+      _this->consumed_in_last_array = prefix_bytes;
+      _this->arrays =
+          (void **) realloc (_this->arrays,
+          sizeof (void *) * _this->number_of_arrays);
+
+      _this->arrays[_this->number_of_arrays - 1] =
+          malloc (_this->size_of_each_array);
+      align_it (_this, alignment);
+    }
+  }
+  retval =
+      (void *) ((char *) _this->arrays[_this->number_of_arrays - 1] +
+      _this->consumed_in_last_array);
+  _this->consumed_in_last_array += nb_bytes;
+  return retval;
+}
+
+void *
+goom_heap_malloc_with_alignment (GoomHeap * _this, int nb_bytes, int alignment)
+{
+  return goom_heap_malloc_with_alignment_prefixed (_this, nb_bytes, alignment,
+      0);
+}
+
+void *
+goom_heap_malloc (GoomHeap * _this, int nb_bytes)
+{
+  return goom_heap_malloc_with_alignment (_this, nb_bytes, 1);
+}
diff --git a/gst/goom/goomsl_heap.h b/gst/goom/goomsl_heap.h
new file mode 100644 (file)
index 0000000..a22bac6
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef GOOMSL_HEAP
+#define GOOMSL_HEAP
+
+/**
+ * Resizable Array that guarranty that resizes don't change address of
+ * the stored datas.
+ *
+ * This is implemented as an array of arrays... granularity is the size
+ * of each arrays.
+ */
+
+typedef struct _GOOM_HEAP GoomHeap;
+
+/* Constructors / Destructor */
+GoomHeap *goom_heap_new(void);
+GoomHeap *goom_heap_new_with_granularity(int granularity);
+void      goom_heap_delete(GoomHeap *_this);
+
+/* This method behaves like malloc. */
+void     *goom_heap_malloc(GoomHeap *_this, int nb_bytes);
+/* This adds an alignment constraint. */
+void     *goom_heap_malloc_with_alignment(GoomHeap *_this, int nb_bytes, int alignment);
+
+/* Returns a pointeur on the bytes... prefix is before */
+void     *goom_heap_malloc_with_alignment_prefixed(GoomHeap *_this, int nb_bytes,
+                                                   int alignment, int prefix_bytes);
+
+#endif
+
diff --git a/gst/goom/goomsl_lex.l b/gst/goom/goomsl_lex.l
new file mode 100644 (file)
index 0000000..3079c02
--- /dev/null
@@ -0,0 +1,94 @@
+%{
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "goomsl.h"
+#include "goomsl_private.h"
+#include "goomsl_yacc.h"
+void yyerror(char *);
+void yyparse(void);
+
+GoomSL *currentGoomSL;
+static int  string_size;
+static char string[1024];
+%}
+
+DIGIT    [0-9]
+XDIGIT   [0-9a-f]
+ID       [a-zA-Z_@&][a-zA-Z0-9_\.]*
+
+%S C_COMMENT
+%S LINE_COMMENT
+%S STRING
+
+%%
+
+<LINE_COMMENT,C_COMMENT,INITIAL>^[ \t]*\n           { ++currentGoomSL->num_lines; /* Ignore empty lines */ }
+<LINE_COMMENT,C_COMMENT,INITIAL>^[ \t]*"//"[^\n]*\n { ++currentGoomSL->num_lines; /* Ignore empty lines */ }
+
+<LINE_COMMENT>\n    { ++currentGoomSL->num_lines; yylval.charValue=*yytext; BEGIN INITIAL; return '\n'; }
+<INITIAL>\n         { ++currentGoomSL->num_lines; yylval.charValue=*yytext; return '\n'; }
+
+<C_COMMENT>"*/"                { BEGIN INITIAL; }
+<C_COMMENT>\n                  { ++currentGoomSL->num_lines; }
+<C_COMMENT,LINE_COMMENT>.      { /* eat up comment */ }
+
+<INITIAL>"#RST_LINE#"             { currentGoomSL->num_lines = 0; }
+<INITIAL>"#FILE ".*"#"            { currentGoomSL->num_lines = 0; printf("%s\n", yytext); }
+<INITIAL>"#"[^\n]*                { /* ignore preprocessor lines */ }
+
+<INITIAL>"/*"                { BEGIN C_COMMENT; }
+<INITIAL>"//"                { BEGIN LINE_COMMENT; }
+<INITIAL>\"                  { BEGIN STRING; string_size=0; }
+
+<STRING>"\\n"                { string[string_size++] = '\n'; }
+<STRING>"\\\""               { string[string_size++] = '\"'; }
+<STRING>\"                   { /* fin de la chaine: on cree le pointeur qui va bien */
+                               unsigned int tmp;
+                               BEGIN INITIAL;
+                               string[string_size]=0;
+                               tmp = gsl_malloc(currentGoomSL, string_size+1);
+                               strcpy((char*)currentGoomSL->ptrArray[tmp],string);
+                               sprintf(yylval.strValue, "0x%08x", tmp);
+                               return LTYPE_PTR;
+                             }
+<STRING>.                    { string[string_size++] = *yytext; }
+
+<INITIAL>"float"                 { return FLOAT_TK; }
+<INITIAL>"int"                   { return INT_TK;   }
+<INITIAL>"boolean"               { return INT_TK;   }
+<INITIAL>"ptr"                   { return PTR_TK;   }
+<INITIAL>"string"                { return PTR_TK;   }
+<INITIAL>"declare"               { return DECLARE;  }
+<INITIAL>"external"              { return EXTERNAL; }
+<INITIAL>"struct"                { return STRUCT;   }
+<INITIAL>"not"                   { return NOT;      }
+<INITIAL>"while"                 { return WHILE;    } 
+<INITIAL>"do"                    { return DO;       }
+<INITIAL>"for"                   { return FOR;      }
+<INITIAL>"in"                    { return IN;       }
+<INITIAL>"true"                  { strncpy(yylval.strValue, "1", 2047);    return LTYPE_INTEGER; }
+<INITIAL>"false"                 { strncpy(yylval.strValue, "0", 2047);    return LTYPE_INTEGER; }
+<INITIAL>{ID}                    { strncpy(yylval.strValue, yytext, 2047); return LTYPE_VAR;     }
+<INITIAL>{DIGIT}+                { strncpy(yylval.strValue, yytext, 2047); return LTYPE_INTEGER; }
+<INITIAL>\'.\'                   { sprintf(yylval.strValue, "%d", (int)yytext[1]); return LTYPE_INTEGER; }
+<INITIAL>"0x"{XDIGIT}+           { strncpy(yylval.strValue, yytext, 2047); return LTYPE_INTEGER; }
+<INITIAL>{DIGIT}+"."{DIGIT}*     { strncpy(yylval.strValue, yytext, 2047); return LTYPE_FLOAT;   }
+<INITIAL>{DIGIT}+"%"             { sprintf(yylval.strValue, "%3.2f", atof(yytext)/100.0f); return LTYPE_FLOAT; }
+<INITIAL>"+="                    { return PLUS_EQ; }
+<INITIAL>"*="                    { return MUL_EQ; }
+<INITIAL>"-="                    { return SUB_EQ; }
+<INITIAL>"/="                    { return DIV_EQ; }
+<INITIAL>"<="                    { return LOW_EQ;  }
+<INITIAL>">="                    { return SUP_EQ;  }
+<INITIAL>"!="                    { return NOT_EQ;  }
+<INITIAL>"<>"                    { return NOT_EQ;  }
+<INITIAL>[ \t]+                  /* eat up whitespace */
+<INITIAL>.                       { yylval.charValue = *yytext; return *yytext;    }
+
+%%
+
+
+int yywrap(void) { return 1; yyunput(0,0); }
+
diff --git a/gst/goom/goomsl_private.h b/gst/goom/goomsl_private.h
new file mode 100644 (file)
index 0000000..8be1515
--- /dev/null
@@ -0,0 +1,251 @@
+#ifndef _GSL_PRIVATE_H
+#define _GSL_PRIVATE_H
+
+/* -- internal use -- */
+
+#include "goomsl.h"
+
+#ifdef USE_JITC_X86
+#include "jitc_x86.h"
+#endif
+
+#include "goomsl_heap.h"
+
+/* {{{ type of nodes */
+#define EMPTY_NODE 0
+#define CONST_INT_NODE 1
+#define CONST_FLOAT_NODE 2
+#define CONST_PTR_NODE 3
+#define VAR_NODE 4
+#define PARAM_NODE 5
+#define READ_PARAM_NODE 6
+#define OPR_NODE 7
+/* }}} */
+/* {{{ type of operations */
+#define OPR_SET 1
+#define OPR_IF 2
+#define OPR_WHILE 3
+#define OPR_BLOCK 4
+#define OPR_ADD 5
+#define OPR_MUL 6
+#define OPR_EQU 7
+#define OPR_NOT 8
+#define OPR_LOW 9
+#define OPR_DIV 10
+#define OPR_SUB 11
+#define OPR_FUNC_INTRO 12
+#define OPR_FUNC_OUTRO 13
+#define OPR_CALL 14
+#define OPR_EXT_CALL 15
+#define OPR_PLUS_EQ 16
+#define OPR_SUB_EQ 17
+#define OPR_MUL_EQ 18
+#define OPR_DIV_EQ 19
+#define OPR_CALL_EXPR 20
+#define OPR_AFFECT_LIST 21
+#define OPR_FOREACH 22
+#define OPR_VAR_LIST 23
+
+/* }}} */
+
+typedef struct _ConstIntNodeType { /* {{{ */
+    int val;
+} ConstIntNodeType; /* }}} */
+typedef struct _ConstFloatNodeType { /* {{{ */
+    float val;
+} ConstFloatNodeType; /* }}} */
+typedef struct _ConstPtrNodeType { /* {{{ */
+    int id;
+} ConstPtrNodeType; /* }}} */
+typedef struct _OprNodeType { /* {{{ */
+    int type;
+    int nbOp;
+    struct _NODE_TYPE *op[3]; /* maximal number of operand needed */
+    struct _NODE_TYPE *next;
+} OprNodeType; /* }}} */
+typedef struct _NODE_TYPE { /* {{{ */
+    int type;
+    char *str;
+    GoomHash *vnamespace;
+    int line_number;
+    union {
+        ConstIntNodeType constInt;
+        ConstFloatNodeType constFloat;
+        ConstPtrNodeType constPtr;
+        OprNodeType opr;
+    } unode;
+} NodeType; /* }}} */
+typedef struct _INSTRUCTION_DATA { /* {{{ */
+  
+  union {
+    void  *var;
+    int   *var_int;
+    int   *var_ptr;
+    float *var_float;
+    int    jump_offset;
+    struct _ExternalFunctionStruct *external_function;
+  } udest;
+
+  union {
+    void  *var;
+    int   *var_int;
+    int   *var_ptr;
+    float *var_float;
+    int    value_int;
+    int    value_ptr;
+    float  value_float;
+  } usrc;
+} InstructionData;
+/* }}} */
+typedef struct _INSTRUCTION { /* {{{ */
+
+    int id;
+    InstructionData data;
+    GoomSL *parent;
+    const char *name; /* name of the instruction */
+
+    char     **params; /* parametres de l'instruction */
+    GoomHash **vnamespace;
+    int       *types;  /* type des parametres de l'instruction */
+    int cur_param;
+    int nb_param;
+
+    int address;
+    char *jump_label;
+    char *nop_label;
+
+    int line_number;
+
+} Instruction;
+/* }}} */
+typedef struct _INSTRUCTION_FLOW { /* {{{ */
+
+    Instruction **instr;
+    int number;
+    int tabsize;
+    GoomHash *labels;
+} InstructionFlow;
+/* }}} */
+typedef struct _FAST_INSTRUCTION { /* {{{ */
+  int id;
+  InstructionData data;
+  Instruction *proto;
+} FastInstruction;
+/* }}} */
+typedef struct _FastInstructionFlow { /* {{{ */
+  int number;
+  FastInstruction *instr;
+  void *mallocedInstr;
+} FastInstructionFlow;
+/* }}} */
+typedef struct _ExternalFunctionStruct { /* {{{ */
+  GoomSL_ExternalFunction function;
+  GoomHash *vars;
+  int is_extern;
+} ExternalFunctionStruct;
+/* }}} */
+typedef struct _Block {
+  int    data;
+  int    size;
+} Block;
+typedef struct _GSL_StructField { /* {{{ */
+  int  type;
+  char name[256];
+  int  offsetInStruct; /* Where this field is stored... */
+} GSL_StructField;
+ /* }}} */
+typedef struct _GSL_Struct { /* {{{ */
+  int nbFields;
+  GSL_StructField *fields[64];
+  int size;
+  Block iBlock[64];
+  Block fBlock[64];
+} GSL_Struct;
+ /* }}} */
+struct _GoomSL { /* {{{ */
+    int num_lines;
+    Instruction *instr;     /* instruction en cours de construction */
+
+    InstructionFlow     *iflow;  /* flow d'instruction 'normal' */
+    FastInstructionFlow *fastiflow; /* flow d'instruction optimise */
+    
+    GoomHash *vars;         /* table de variables */
+    int currentNS;
+    GoomHash *namespaces[16];
+    
+    GoomHash *functions;    /* table des fonctions externes */
+
+    GoomHeap *data_heap; /* GSL Heap-like memory space */
+    
+    int nbStructID;
+    GoomHash   *structIDS;
+    GSL_Struct **gsl_struct;
+    int gsl_struct_size;
+    
+    int    nbPtr;
+    int    ptrArraySize;
+    void **ptrArray;
+    
+    int compilationOK;
+#ifdef USE_JITC_X86
+    JitcX86Env *jitc;
+    JitcFunc    jitc_func;
+#endif
+}; /* }}} */
+
+extern GoomSL *currentGoomSL;
+
+Instruction *gsl_instr_init(GoomSL *parent, const char *name, int id, int nb_param, int line_number);
+void gsl_instr_add_param(Instruction *_this, char *param, int type);
+void gsl_instr_set_namespace(Instruction *_this, GoomHash *ns);
+
+void gsl_declare_task(const char *name);
+void gsl_declare_external_task(const char *name);
+
+int gsl_type_of_var(GoomHash *namespace, const char *name);
+
+void gsl_enternamespace(const char *name);
+void gsl_reenternamespace(GoomHash *ns);
+GoomHash *gsl_leavenamespace(void);
+GoomHash *gsl_find_namespace(const char *name);
+
+void gsl_commit_compilation(void);
+
+/* #define TYPE_PARAM    1 */
+
+#define FIRST_RESERVED 0x80000
+
+#define TYPE_INTEGER  0x90001
+#define TYPE_FLOAT    0x90002
+#define TYPE_VAR      0x90003
+#define TYPE_PTR      0x90004
+#define TYPE_LABEL    0x90005
+
+#define TYPE_OP_EQUAL 6
+#define TYPE_IVAR     0xa0001
+#define TYPE_FVAR     0xa0002
+#define TYPE_PVAR     0xa0003
+#define TYPE_SVAR     0xa0004
+
+#define INSTR_JUMP     6
+#define INSTR_JZERO    29
+#define INSTR_CALL     36 
+#define INSTR_RET      37
+#define INSTR_EXT_CALL 38
+#define INSTR_JNZERO   40
+
+#define INSTR_SET     0x80001
+#define INSTR_INT     0x80002
+#define INSTR_FLOAT   0x80003
+#define INSTR_PTR     0x80004
+#define INSTR_LABEL   0x80005
+#define INSTR_ISLOWER 0x80006
+#define INSTR_ADD     0x80007
+#define INSTR_MUL     0x80008
+#define INSTR_DIV     0x80009
+#define INSTR_SUB     0x80010
+#define INSTR_ISEQUAL 0x80011
+#define INSTR_NOT     0x80012
+
+
+#endif
diff --git a/gst/goom/goomsl_yacc.y b/gst/goom/goomsl_yacc.y
new file mode 100644 (file)
index 0000000..c424a50
--- /dev/null
@@ -0,0 +1,1405 @@
+/**
+ * copyright 2004, Jean-Christophe Hoelt <jeko@ios-software.com>
+ *
+ * This program is released under the terms of the GNU Lesser General Public Licence.
+ */
+%{
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include "goomsl.h"
+    #include "goomsl_private.h"
+
+#define STRUCT_ALIGNMENT 16
+/* #define VERBOSE  */
+
+    int yylex(void);
+    void yyerror(char *);
+    extern GoomSL *currentGoomSL;
+
+    static NodeType *nodeNew(const char *str, int type, int line_number);
+    static NodeType *nodeClone(NodeType *node);
+    static void nodeFreeInternals(NodeType *node);
+    static void nodeFree(NodeType *node);
+
+    static void commit_node(NodeType *node, int releaseIfTemp);
+    static void precommit_node(NodeType *node);
+
+    static NodeType *new_constInt(const char *str, int line_number);
+    static NodeType *new_constFloat(const char *str, int line_number);
+    static NodeType *new_constPtr(const char *str, int line_number);
+    static NodeType *new_var(const char *str, int line_number);
+    static NodeType *new_nop(const char *str);
+    static NodeType *new_op(const char *str, int type, int nbOp);
+
+    static int  allocateLabel();
+    static int  allocateTemp();
+    static void releaseTemp(int n);
+    static void releaseAllTemps();
+
+    static int is_tmp_expr(NodeType *node) {
+        if (node->str) {
+            return (!strncmp(node->str,"_i_tmp_",7))
+              || (!strncmp(node->str,"_f_tmp_",7))
+              || (!strncmp(node->str,"_p_tmp",7));
+        }
+        return 0;
+    }
+    /* pre: is_tmp_expr(node); */
+    static int get_tmp_id(NodeType *node)  { return atoi((node->str)+5); }
+
+    static int is_commutative_expr(int itype)
+    { /* {{{ */
+        return (itype == INSTR_ADD)
+            || (itype == INSTR_MUL)
+            || (itype == INSTR_ISEQUAL);
+    } /* }}} */
+
+    static void GSL_PUT_LABEL(char *name, int line_number)
+    { /* {{{ */
+#ifdef VERBOSE
+      printf("label %s\n", name);
+#endif
+      currentGoomSL->instr = gsl_instr_init(currentGoomSL, "label", INSTR_LABEL, 1, line_number);
+      gsl_instr_add_param(currentGoomSL->instr, name, TYPE_LABEL);
+    } /* }}} */
+    static void GSL_PUT_JUMP(char *name, int line_number)
+    { /* {{{ */
+#ifdef VERBOSE
+      printf("jump %s\n", name);
+#endif
+      currentGoomSL->instr = gsl_instr_init(currentGoomSL, "jump", INSTR_JUMP, 1, line_number);
+      gsl_instr_add_param(currentGoomSL->instr, name, TYPE_LABEL);
+    } /* }}} */
+
+    static void GSL_PUT_JXXX(char *name, char *iname, int instr_id, int line_number)
+    { /* {{{ */
+#ifdef VERBOSE
+      printf("%s %s\n", iname, name);
+#endif
+      currentGoomSL->instr = gsl_instr_init(currentGoomSL, iname, instr_id, 1, line_number);
+      gsl_instr_add_param(currentGoomSL->instr, name, TYPE_LABEL);
+    } /* }}} */
+    static void GSL_PUT_JZERO(char *name,int line_number)
+    { /* {{{ */
+      GSL_PUT_JXXX(name,"jzero.i",INSTR_JZERO,line_number);
+    } /* }}} */
+    static void GSL_PUT_JNZERO(char *name, int line_number)
+    { /* {{{ */
+      GSL_PUT_JXXX(name,"jnzero.i",INSTR_JNZERO,line_number);
+    } /* }}} */
+
+    /* Structures Management */
+
+#define ALIGN_ADDR(_addr,_align) {\
+   if (_align>1) {\
+       int _dec = (_addr%_align);\
+       if (_dec != 0) _addr += _align - _dec;\
+   }}
+
+    /* */
+    void gsl_prepare_struct(GSL_Struct *s, int s_align, int i_align, int f_align)
+    {
+      int i;
+      int consumed = 0;
+      int iblk=0, fblk=0;
+
+      s->iBlock[0].size = 0;
+      s->iBlock[0].data = 0;
+      s->fBlock[0].size = 0;
+      s->fBlock[0].data = 0;
+
+      /* Prepare sub-struct and calculate space needed for their storage */
+      for (i = 0; i < s->nbFields; ++i)
+      {
+        if (s->fields[i]->type < FIRST_RESERVED)
+        {
+          int j=0;
+          GSL_Struct *substruct = currentGoomSL->gsl_struct[s->fields[i]->type];
+          consumed += sizeof(int); /* stocke le prefix */
+          ALIGN_ADDR(consumed, s_align);
+          s->fields[i]->offsetInStruct = consumed;
+          gsl_prepare_struct(substruct, s_align, i_align, f_align);
+          for(j=0;substruct->iBlock[j].size>0;++j) {
+            s->iBlock[iblk].data = consumed + substruct->iBlock[j].data;
+            s->iBlock[iblk].size = substruct->iBlock[j].size;
+            iblk++;
+          }
+          for(j=0;substruct->fBlock[j].size>0;++j) {
+            s->fBlock[fblk].data = consumed + substruct->fBlock[j].data;
+            s->fBlock[fblk].size = substruct->fBlock[j].size;
+            fblk++;
+          }
+          consumed += substruct->size;
+        }
+      }
+
+      /* Then prepare integers */
+      ALIGN_ADDR(consumed, i_align);
+      for (i = 0; i < s->nbFields; ++i)
+      {
+        if (s->fields[i]->type == INSTR_INT)
+        {
+          if (s->iBlock[iblk].size == 0) {
+            s->iBlock[iblk].size = 1;
+            s->iBlock[iblk].data = consumed;
+          } else {
+            s->iBlock[iblk].size += 1;
+          }
+          s->fields[i]->offsetInStruct = consumed;
+          consumed += sizeof(int);
+        }
+      }
+
+      iblk++;
+      s->iBlock[iblk].size = 0;
+      s->iBlock[iblk].data = 0;
+
+      /* Then prepare floats */
+      ALIGN_ADDR(consumed, f_align);
+      for (i = 0; i < s->nbFields; ++i)
+      {
+        if (s->fields[i]->type == INSTR_FLOAT)
+        {
+          if (s->fBlock[fblk].size == 0) {
+            s->fBlock[fblk].size = 1;
+            s->fBlock[fblk].data = consumed;
+          } else {
+            s->fBlock[fblk].size += 1;
+          }
+          s->fields[i]->offsetInStruct = consumed;
+          consumed += sizeof(int);
+        }
+      }
+
+      fblk++;
+      s->fBlock[fblk].size = 0;
+      s->fBlock[fblk].data = 0;
+      
+      /* Finally prepare pointers */
+      ALIGN_ADDR(consumed, i_align);
+      for (i = 0; i < s->nbFields; ++i)
+      {
+        if (s->fields[i]->type == INSTR_PTR)
+        {
+          s->fields[i]->offsetInStruct = consumed;
+          consumed += sizeof(int);
+        }
+      }
+      s->size = consumed;
+    }
+
+    /* Returns the ID of a struct from its name */
+    int gsl_get_struct_id(const char *name) /* {{{ */
+    {
+      HashValue *ret = goom_hash_get(currentGoomSL->structIDS, name);
+      if (ret != NULL) return ret->i;
+      return -1;
+    } /* }}} */
+
+    /* Adds the definition of a struct */
+    void gsl_add_struct(const char *name, GSL_Struct *gsl_struct) /* {{{ */
+    {
+      /* Prepare the struct: ie calculate internal storage format */
+      gsl_prepare_struct(gsl_struct, STRUCT_ALIGNMENT, STRUCT_ALIGNMENT, STRUCT_ALIGNMENT);
+      
+      /* If the struct does not already exists */
+      if (gsl_get_struct_id(name) < 0)
+      {
+        /* adds it */
+        int id = currentGoomSL->nbStructID++;
+        goom_hash_put_int(currentGoomSL->structIDS, name, id);
+        if (currentGoomSL->gsl_struct_size <= id) {
+          currentGoomSL->gsl_struct_size *= 2;
+          currentGoomSL->gsl_struct = (GSL_Struct**)realloc(currentGoomSL->gsl_struct,
+                                                            sizeof(GSL_Struct*) * currentGoomSL->gsl_struct_size);
+        }
+        currentGoomSL->gsl_struct[id] = gsl_struct;
+      }
+    } /* }}} */
+    
+    /* Creates a field for a struct */
+    GSL_StructField *gsl_new_struct_field(const char *name, int type)
+    {
+      GSL_StructField *field = (GSL_StructField*)malloc(sizeof(GSL_StructField));
+      strcpy(field->name, name);
+      field->type = type;
+      return field;
+    }
+    
+    /* Create as field for a struct which will be a struct itself */
+    GSL_StructField *gsl_new_struct_field_struct(const char *name, const char *type)
+    {
+      GSL_StructField *field = gsl_new_struct_field(name, gsl_get_struct_id(type));
+      if (field->type < 0) {
+        fprintf(stderr, "ERROR: Line %d, Unknown structure: '%s'\n",
+                currentGoomSL->num_lines, type);
+        exit(1);
+      }
+      return field;
+    }
+
+    /* Creates a Struct */
+    GSL_Struct *gsl_new_struct(GSL_StructField *field)
+    {
+      GSL_Struct *s = (GSL_Struct*)malloc(sizeof(GSL_Struct));
+      s->nbFields = 1;
+      s->fields[0] = field;
+      return s;
+    }
+
+    /* Adds a field to a struct */
+    void gsl_add_struct_field(GSL_Struct *s, GSL_StructField *field)
+    {
+      s->fields[s->nbFields++] = field;
+    }
+
+    int gsl_type_of_var(GoomHash *ns, const char *name)
+    {
+        char type_of[256];
+        HashValue *hv;
+        sprintf(type_of, "__type_of_%s", name);
+        hv = goom_hash_get(ns, type_of);
+        if (hv != NULL)
+          return hv->i;
+        fprintf(stderr, "ERROR: Unknown variable type: '%s'\n", name);
+        return -1;
+    }
+
+    static void gsl_declare_var(GoomHash *ns, const char *name, int type, void *space)
+    {
+        char type_of[256];
+        if (name[0] == '@') { ns = currentGoomSL->vars; }
+
+        if (space == NULL) {
+          switch (type) {
+            case INSTR_INT:
+            case INSTR_FLOAT:
+            case INSTR_PTR:
+              space = goom_heap_malloc_with_alignment(currentGoomSL->data_heap,
+                  sizeof(int), sizeof(int));
+            break;
+            case -1:
+              fprintf(stderr, "What the fuck!\n");
+              exit(1);
+            default: /* On a un struct_id */
+              space = goom_heap_malloc_with_alignment_prefixed(currentGoomSL->data_heap,
+                  currentGoomSL->gsl_struct[type]->size, STRUCT_ALIGNMENT, sizeof(int));
+          }
+        }
+        goom_hash_put_ptr(ns, name, (void*)space);
+        sprintf(type_of, "__type_of_%s", name);
+        goom_hash_put_int(ns, type_of, type);
+
+        /* Ensuite le hack: on ajoute les champs en tant que variables. */
+        if (type < FIRST_RESERVED)
+        {
+          int i;
+          GSL_Struct *gsl_struct = currentGoomSL->gsl_struct[type];
+          ((int*)space)[-1] = type; /* stockage du type dans le prefixe de structure */
+          for (i = 0; i < gsl_struct->nbFields; ++i)
+          {
+            char full_name[256];
+            char *cspace = (char*)space + gsl_struct->fields[i]->offsetInStruct;
+            sprintf(full_name, "%s.%s", name, gsl_struct->fields[i]->name);
+            gsl_declare_var(ns, full_name, gsl_struct->fields[i]->type, cspace);
+          }
+       }
+    }
+    
+    /* Declare a variable which will be a struct */
+    static void gsl_struct_decl(GoomHash *namespace, const char *struct_name, const char *name)
+    {
+        int  struct_id = gsl_get_struct_id(struct_name);
+        gsl_declare_var(namespace, name, struct_id, NULL);
+    }
+
+    static void gsl_float_decl_global(const char *name)
+    {
+        gsl_declare_var(currentGoomSL->vars, name, INSTR_FLOAT, NULL);
+    }
+    static void gsl_int_decl_global(const char *name)
+    {
+        gsl_declare_var(currentGoomSL->vars, name, INSTR_INT, NULL);
+    }
+    static void gsl_ptr_decl_global(const char *name)
+    {
+        gsl_declare_var(currentGoomSL->vars, name, INSTR_PTR, NULL);
+    }
+    static void gsl_struct_decl_global_from_id(const char *name, int id)
+    {
+        gsl_declare_var(currentGoomSL->vars, name, id, NULL);
+    }
+    
+    /* FLOAT */
+    static void gsl_float_decl_local(const char *name)
+    {
+        gsl_declare_var(currentGoomSL->namespaces[currentGoomSL->currentNS], name, INSTR_FLOAT, NULL);
+    }
+    /* INT */
+    static void gsl_int_decl_local(const char *name)
+    {
+        gsl_declare_var(currentGoomSL->namespaces[currentGoomSL->currentNS], name, INSTR_INT, NULL);
+    }
+    /* PTR */
+    static void gsl_ptr_decl_local(const char *name)
+    {
+        gsl_declare_var(currentGoomSL->namespaces[currentGoomSL->currentNS], name, INSTR_PTR, NULL);
+    }
+    /* STRUCT */
+    static void gsl_struct_decl_local(const char *struct_name, const char *name)
+    {
+        gsl_struct_decl(currentGoomSL->namespaces[currentGoomSL->currentNS],struct_name,name);
+    }
+
+
+    static void commit_test2(NodeType *set,const char *type, int instr);
+    static NodeType *new_call(const char *name, NodeType *affect_list);
+
+    /* SETTER */
+    static NodeType *new_set(NodeType *lvalue, NodeType *expression)
+    { /* {{{ */
+        NodeType *set = new_op("set", OPR_SET, 2);
+        set->unode.opr.op[0] = lvalue;
+        set->unode.opr.op[1] = expression;
+        return set;
+    } /* }}} */
+    static void commit_set(NodeType *set)
+    { /* {{{ */
+      commit_test2(set,"set",INSTR_SET);
+    } /* }}} */
+
+    /* PLUS_EQ */
+    static NodeType *new_plus_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
+    {
+        NodeType *set = new_op("plus_eq", OPR_PLUS_EQ, 2);
+        set->unode.opr.op[0] = lvalue;
+        set->unode.opr.op[1] = expression;
+        return set;
+    }
+    static void commit_plus_eq(NodeType *set)
+    {
+        precommit_node(set->unode.opr.op[1]);
+#ifdef VERBOSE
+        printf("add %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
+#endif
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "add", INSTR_ADD, 2, set->line_number);
+        commit_node(set->unode.opr.op[0],0);
+        commit_node(set->unode.opr.op[1],1);
+    } /* }}} */
+
+    /* SUB_EQ */
+    static NodeType *new_sub_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
+    {
+        NodeType *set = new_op("sub_eq", OPR_SUB_EQ, 2);
+        set->unode.opr.op[0] = lvalue;
+        set->unode.opr.op[1] = expression;
+        return set;
+    }
+    static void commit_sub_eq(NodeType *set)
+    {
+        precommit_node(set->unode.opr.op[1]);
+#ifdef VERBOSE
+        printf("sub %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
+#endif
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "sub", INSTR_SUB, 2, set->line_number);
+        commit_node(set->unode.opr.op[0],0);
+        commit_node(set->unode.opr.op[1],1);
+    } /* }}} */
+
+    /* MUL_EQ */
+    static NodeType *new_mul_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
+    {
+        NodeType *set = new_op("mul_eq", OPR_MUL_EQ, 2);
+        set->unode.opr.op[0] = lvalue;
+        set->unode.opr.op[1] = expression;
+        return set;
+    }
+    static void commit_mul_eq(NodeType *set)
+    {
+        precommit_node(set->unode.opr.op[1]);
+#ifdef VERBOSE
+        printf("mul %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
+#endif
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "mul", INSTR_MUL, 2, set->line_number);
+        commit_node(set->unode.opr.op[0],0);
+        commit_node(set->unode.opr.op[1],1);
+    } /* }}} */
+
+    /* DIV_EQ */
+    static NodeType *new_div_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
+    {
+        NodeType *set = new_op("div_eq", OPR_DIV_EQ, 2);
+        set->unode.opr.op[0] = lvalue;
+        set->unode.opr.op[1] = expression;
+        return set;
+    }
+    static void commit_div_eq(NodeType *set)
+    {
+        precommit_node(set->unode.opr.op[1]);
+#ifdef VERBOSE
+        printf("div %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
+#endif
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "div", INSTR_DIV, 2, set->line_number);
+        commit_node(set->unode.opr.op[0],0);
+        commit_node(set->unode.opr.op[1],1);
+    } /* }}} */
+
+    /* commodity method for add, mult, ... */
+
+    static void precommit_expr(NodeType *expr, const char *type, int instr_id)
+    { /* {{{ */
+        NodeType *tmp, *tmpcpy;
+        int toAdd;
+
+        /* compute "left" and "right" */
+        switch (expr->unode.opr.nbOp) {
+        case 2:
+          precommit_node(expr->unode.opr.op[1]);
+        case 1:
+          precommit_node(expr->unode.opr.op[0]);
+        }
+
+        if (is_tmp_expr(expr->unode.opr.op[0])) {
+            tmp = expr->unode.opr.op[0];
+            toAdd = 1;
+        }
+        else if (is_commutative_expr(instr_id) && (expr->unode.opr.nbOp==2) && is_tmp_expr(expr->unode.opr.op[1])) {
+            tmp = expr->unode.opr.op[1];
+            toAdd = 0;
+        }
+        else {
+            char stmp[256];
+            /* declare a temporary variable to store the result */
+            if (expr->unode.opr.op[0]->type == CONST_INT_NODE) {
+                sprintf(stmp,"_i_tmp_%i",allocateTemp());
+                gsl_int_decl_global(stmp);
+            }
+            else if (expr->unode.opr.op[0]->type == CONST_FLOAT_NODE) {
+                sprintf(stmp,"_f_tmp%i",allocateTemp());
+                gsl_float_decl_global(stmp);
+            }
+            else if (expr->unode.opr.op[0]->type == CONST_PTR_NODE) {
+                sprintf(stmp,"_p_tmp%i",allocateTemp());
+                gsl_ptr_decl_global(stmp);
+            }
+            else {
+                int type = gsl_type_of_var(expr->unode.opr.op[0]->vnamespace, expr->unode.opr.op[0]->str);
+                if (type == INSTR_FLOAT) {
+                    sprintf(stmp,"_f_tmp_%i",allocateTemp());
+                    gsl_float_decl_global(stmp);
+                }
+                else if (type == INSTR_PTR) {
+                    sprintf(stmp,"_p_tmp_%i",allocateTemp());
+                    gsl_ptr_decl_global(stmp);
+                }
+                else if (type == INSTR_INT) {
+                    sprintf(stmp,"_i_tmp_%i",allocateTemp());
+                    gsl_int_decl_global(stmp);
+                }
+                else if (type == -1) {
+                    fprintf(stderr, "ERROR: Line %d, Could not find variable '%s'\n",
+                            expr->line_number, expr->unode.opr.op[0]->str);
+                    exit(1);
+                }
+                else { /* type is a struct_id */
+                    sprintf(stmp,"_s_tmp_%i",allocateTemp());
+                    gsl_struct_decl_global_from_id(stmp,type);
+                }
+            }
+            tmp = new_var(stmp,expr->line_number);
+
+            /* set the tmp to the value of "op1" */
+            tmpcpy = nodeClone(tmp);
+            commit_node(new_set(tmp,expr->unode.opr.op[0]),0);
+            toAdd = 1;
+
+            tmp = tmpcpy;
+        }
+
+        /* add op2 to tmp */
+#ifdef VERBOSE
+        if (expr->unode.opr.nbOp == 2)
+          printf("%s %s %s\n", type, tmp->str, expr->unode.opr.op[toAdd]->str);
+        else
+          printf("%s %s\n", type, tmp->str);
+#endif
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, type, instr_id, expr->unode.opr.nbOp, expr->line_number);
+        tmpcpy = nodeClone(tmp);
+        commit_node(tmp,0);
+        if (expr->unode.opr.nbOp == 2) {
+          commit_node(expr->unode.opr.op[toAdd],1);
+        }
+    
+        /* redefine the ADD node now as the computed variable */
+        nodeFreeInternals(expr);
+        *expr = *tmpcpy;
+        free(tmpcpy);
+    } /* }}} */
+
+    static NodeType *new_expr1(const char *name, int id, NodeType *expr1)
+    { /* {{{ */
+        NodeType *add = new_op(name, id, 1);
+        add->unode.opr.op[0] = expr1;
+        return add;
+    } /* }}} */
+
+    static NodeType *new_expr2(const char *name, int id, NodeType *expr1, NodeType *expr2)
+    { /* {{{ */
+        NodeType *add = new_op(name, id, 2);
+        add->unode.opr.op[0] = expr1;
+        add->unode.opr.op[1] = expr2;
+        return add;
+    } /* }}} */
+
+    /* ADD */
+    static NodeType *new_add(NodeType *expr1, NodeType *expr2) { /* {{{ */
+        return new_expr2("add", OPR_ADD, expr1, expr2);
+    }
+    static void precommit_add(NodeType *add) {
+        precommit_expr(add,"add",INSTR_ADD);
+    } /* }}} */
+
+    /* SUB */
+    static NodeType *new_sub(NodeType *expr1, NodeType *expr2) { /* {{{ */
+        return new_expr2("sub", OPR_SUB, expr1, expr2);
+    }
+    static void precommit_sub(NodeType *sub) {
+        precommit_expr(sub,"sub",INSTR_SUB);
+    } /* }}} */
+
+    /* NEG */
+    static NodeType *new_neg(NodeType *expr) { /* {{{ */
+        NodeType *zeroConst = NULL;
+        if (expr->type == CONST_INT_NODE)
+          zeroConst = new_constInt("0", currentGoomSL->num_lines);
+        else if (expr->type == CONST_FLOAT_NODE)
+          zeroConst = new_constFloat("0.0", currentGoomSL->num_lines);
+        else if (expr->type == CONST_PTR_NODE) {
+          fprintf(stderr, "ERROR: Line %d, Could not negate const pointer.\n",
+            currentGoomSL->num_lines);
+          exit(1);
+        }
+        else {
+            int type = gsl_type_of_var(expr->vnamespace, expr->str);
+            if (type == INSTR_FLOAT)
+              zeroConst = new_constFloat("0.0", currentGoomSL->num_lines);
+            else if (type == INSTR_PTR) {
+              fprintf(stderr, "ERROR: Line %d, Could not negate pointer.\n",
+                currentGoomSL->num_lines);
+              exit(1);
+            }
+            else if (type == INSTR_INT)
+              zeroConst = new_constInt("0", currentGoomSL->num_lines);
+            else if (type == -1) {
+                fprintf(stderr, "ERROR: Line %d, Could not find variable '%s'\n",
+                        expr->line_number, expr->unode.opr.op[0]->str);
+                exit(1);
+            }
+            else { /* type is a struct_id */
+                fprintf(stderr, "ERROR: Line %d, Could not negate struct '%s'\n",
+                        expr->line_number, expr->str);
+                exit(1);
+            }
+        }
+        return new_expr2("sub", OPR_SUB, zeroConst, expr);
+    }
+    /* }}} */
+
+    /* MUL */
+    static NodeType *new_mul(NodeType *expr1, NodeType *expr2) { /* {{{ */
+        return new_expr2("mul", OPR_MUL, expr1, expr2);
+    }
+    static void precommit_mul(NodeType *mul) {
+        precommit_expr(mul,"mul",INSTR_MUL);
+    } /* }}} */
+    
+    /* DIV */
+    static NodeType *new_div(NodeType *expr1, NodeType *expr2) { /* {{{ */
+        return new_expr2("div", OPR_DIV, expr1, expr2);
+    }
+    static void precommit_div(NodeType *mul) {
+        precommit_expr(mul,"div",INSTR_DIV);
+    } /* }}} */
+
+    /* CALL EXPRESSION */
+    static NodeType *new_call_expr(const char *name, NodeType *affect_list) { /* {{{ */
+        NodeType *call = new_call(name,affect_list);
+        NodeType *node = new_expr1(name, OPR_CALL_EXPR, call);
+        node->vnamespace = gsl_find_namespace(name);
+        if (node->vnamespace == NULL)
+          fprintf(stderr, "ERROR: Line %d, No return type for: '%s'\n", currentGoomSL->num_lines, name);
+        return node;
+    }
+    static void precommit_call_expr(NodeType *call) {
+        char stmp[256];
+        NodeType *tmp,*tmpcpy;
+        int type = gsl_type_of_var(call->vnamespace, call->str);
+        if (type == INSTR_FLOAT) {
+          sprintf(stmp,"_f_tmp_%i",allocateTemp());
+          gsl_float_decl_global(stmp);
+        }
+        else if (type == INSTR_PTR) {
+          sprintf(stmp,"_p_tmp_%i",allocateTemp());
+          gsl_ptr_decl_global(stmp);
+        }
+        else if (type == INSTR_INT) {
+          sprintf(stmp,"_i_tmp_%i",allocateTemp());
+          gsl_int_decl_global(stmp);
+        }
+        else if (type == -1) {
+          fprintf(stderr, "ERROR: Line %d, Could not find variable '%s'\n",
+                  call->line_number, call->str);
+          exit(1);
+        }
+        else { /* type is a struct_id */
+          sprintf(stmp,"_s_tmp_%i",allocateTemp());
+          gsl_struct_decl_global_from_id(stmp,type);
+        }
+        tmp = new_var(stmp,call->line_number);
+        commit_node(call->unode.opr.op[0],0);
+        tmpcpy = nodeClone(tmp);
+        commit_node(new_set(tmp,new_var(call->str,call->line_number)),0);
+        
+        nodeFreeInternals(call);
+        *call = *tmpcpy;
+        free(tmpcpy);
+    } /* }}} */
+
+    static void commit_test2(NodeType *set,const char *type, int instr)
+    { /* {{{ */
+        NodeType *tmp;
+        char stmp[256];
+        precommit_node(set->unode.opr.op[0]);
+        precommit_node(set->unode.opr.op[1]);
+        tmp = set->unode.opr.op[0];
+        
+        stmp[0] = 0;
+        if (set->unode.opr.op[0]->type == CONST_INT_NODE) {
+            sprintf(stmp,"_i_tmp_%i",allocateTemp());
+            gsl_int_decl_global(stmp);
+        }
+        else if (set->unode.opr.op[0]->type == CONST_FLOAT_NODE) {
+            sprintf(stmp,"_f_tmp%i",allocateTemp());
+            gsl_float_decl_global(stmp);
+        }
+        else if (set->unode.opr.op[0]->type == CONST_PTR_NODE) {
+            sprintf(stmp,"_p_tmp%i",allocateTemp());
+            gsl_ptr_decl_global(stmp);
+        }
+        if (stmp[0]) {
+            NodeType *tmpcpy;
+            tmp = new_var(stmp, set->line_number);
+            tmpcpy = nodeClone(tmp);
+            commit_node(new_set(tmp,set->unode.opr.op[0]),0);
+            tmp = tmpcpy;
+        }
+
+#ifdef VERBOSE
+        printf("%s %s %s\n", type, tmp->str, set->unode.opr.op[1]->str);
+#endif
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, type, instr, 2, set->line_number);
+        commit_node(tmp,instr!=INSTR_SET);
+        commit_node(set->unode.opr.op[1],1);
+    } /* }}} */
+    
+    /* NOT */
+    static NodeType *new_not(NodeType *expr1) { /* {{{ */
+        return new_expr1("not", OPR_NOT, expr1);
+    }
+    static void commit_not(NodeType *set)
+    {
+        commit_node(set->unode.opr.op[0],0);
+#ifdef VERBOSE
+        printf("not\n");
+#endif
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "not", INSTR_NOT, 1, set->line_number);
+        gsl_instr_add_param(currentGoomSL->instr, "|dummy|", TYPE_LABEL);
+    } /* }}} */
+    
+    /* EQU */
+    static NodeType *new_equ(NodeType *expr1, NodeType *expr2) { /* {{{ */
+        return new_expr2("isequal", OPR_EQU, expr1, expr2);
+    }
+    static void commit_equ(NodeType *mul) {
+        commit_test2(mul,"isequal",INSTR_ISEQUAL);
+    } /* }}} */
+    
+    /* INF */
+    static NodeType *new_low(NodeType *expr1, NodeType *expr2) { /* {{{ */
+        return new_expr2("islower", OPR_LOW, expr1, expr2);
+    }
+    static void commit_low(NodeType *mul) {
+        commit_test2(mul,"islower",INSTR_ISLOWER);
+    } /* }}} */
+
+    /* WHILE */
+    static NodeType *new_while(NodeType *expression, NodeType *instr) { /* {{{ */
+        NodeType *node = new_op("while", OPR_WHILE, 2);
+        node->unode.opr.op[0] = expression;
+        node->unode.opr.op[1] = instr;
+        return node;
+    }
+
+    static void commit_while(NodeType *node)
+    {
+        int lbl = allocateLabel();
+        char start_while[1024], test_while[1024];
+        sprintf(start_while, "|start_while_%d|", lbl);
+        sprintf(test_while, "|test_while_%d|", lbl);
+       
+        GSL_PUT_JUMP(test_while,node->line_number);
+        GSL_PUT_LABEL(start_while,node->line_number);
+
+        /* code */
+        commit_node(node->unode.opr.op[1],0);
+
+        GSL_PUT_LABEL(test_while,node->line_number);
+        commit_node(node->unode.opr.op[0],0);
+        GSL_PUT_JNZERO(start_while,node->line_number);
+    } /* }}} */
+
+    /* FOR EACH */
+    static NodeType *new_static_foreach(NodeType *var, NodeType *var_list, NodeType *instr) { /* {{{ */
+        NodeType *node = new_op("for", OPR_FOREACH, 3);
+        node->unode.opr.op[0] = var;
+        node->unode.opr.op[1] = var_list;
+        node->unode.opr.op[2] = instr;
+        node->line_number = currentGoomSL->num_lines;
+        return node;
+    }
+    static void commit_foreach(NodeType *node)
+    {
+        NodeType *cur = node->unode.opr.op[1];
+        char tmp_func[256], tmp_loop[256];
+        int lbl = allocateLabel();
+        sprintf(tmp_func, "|foreach_func_%d|", lbl);
+        sprintf(tmp_loop, "|foreach_loop_%d|", lbl);
+
+        GSL_PUT_JUMP(tmp_loop, node->line_number);
+        GSL_PUT_LABEL(tmp_func, node->line_number);
+
+        precommit_node(node->unode.opr.op[2]);
+        commit_node(node->unode.opr.op[2], 0);
+
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "ret", INSTR_RET, 1, node->line_number);
+        gsl_instr_add_param(currentGoomSL->instr, "|dummy|", TYPE_LABEL);
+#ifdef VERBOSE
+        printf("ret\n");
+#endif
+        
+        GSL_PUT_LABEL(tmp_loop, node->line_number);
+        
+        while (cur != NULL)
+        {
+          NodeType *x, *var;
+
+          /* 1: x=var */
+          x   = nodeClone(node->unode.opr.op[0]);
+          var = nodeClone(cur->unode.opr.op[0]);
+          commit_node(new_set(x, var),0);
+          
+          /* 2: instr */
+          currentGoomSL->instr = gsl_instr_init(currentGoomSL, "call", INSTR_CALL, 1, node->line_number);
+          gsl_instr_add_param(currentGoomSL->instr, tmp_func, TYPE_LABEL);
+#ifdef VERBOSE
+          printf("call %s\n", tmp_func);
+#endif
+          
+          /* 3: var=x */
+          x   = nodeClone(node->unode.opr.op[0]);
+          var = cur->unode.opr.op[0];
+          commit_node(new_set(var, x),0);
+          cur = cur->unode.opr.op[1];
+        }
+        nodeFree(node->unode.opr.op[0]);
+    } /* }}} */
+
+    /* IF */
+    static NodeType *new_if(NodeType *expression, NodeType *instr) { /* {{{ */
+        NodeType *node = new_op("if", OPR_IF, 2);
+        node->unode.opr.op[0] = expression;
+        node->unode.opr.op[1] = instr;
+        return node;
+    }
+    static void commit_if(NodeType *node) {
+
+        char slab[1024];
+        sprintf(slab, "|eif%d|", allocateLabel());
+        commit_node(node->unode.opr.op[0],0);
+        GSL_PUT_JZERO(slab,node->line_number);
+        /* code */
+        commit_node(node->unode.opr.op[1],0);
+        GSL_PUT_LABEL(slab,node->line_number);
+    } /* }}} */
+
+    /* BLOCK */
+    static NodeType *new_block(NodeType *lastNode) { /* {{{ */
+        NodeType *blk = new_op("block", OPR_BLOCK, 2);
+        blk->unode.opr.op[0] = new_nop("start_of_block");
+        blk->unode.opr.op[1] = lastNode;        
+        return blk;
+    }
+    static void commit_block(NodeType *node) {
+        commit_node(node->unode.opr.op[0]->unode.opr.next,0);
+    } /* }}} */
+
+    /* FUNCTION INTRO */
+    static NodeType *new_function_intro(const char *name) { /* {{{ */
+        char stmp[256];
+        if (strlen(name) < 200) {
+           sprintf(stmp, "|__func_%s|", name);
+        }
+        return new_op(stmp, OPR_FUNC_INTRO, 0);
+    }
+    static void commit_function_intro(NodeType *node) {
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "label", INSTR_LABEL, 1, node->line_number);
+        gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_LABEL);
+#ifdef VERBOSE
+        printf("label %s\n", node->str);
+#endif
+    } /* }}} */
+
+    /* FUNCTION OUTRO */
+    static NodeType *new_function_outro() { /* {{{ */
+        return new_op("ret", OPR_FUNC_OUTRO, 0);
+    }
+    static void commit_function_outro(NodeType *node) {
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "ret", INSTR_RET, 1, node->line_number);
+        gsl_instr_add_param(currentGoomSL->instr, "|dummy|", TYPE_LABEL);
+        releaseAllTemps();
+#ifdef VERBOSE
+        printf("ret\n");
+#endif
+    } /* }}} */
+    
+    /* AFFECTATION LIST */
+    static NodeType *new_affec_list(NodeType *set, NodeType *next) /* {{{ */
+    {
+      NodeType *node = new_op("affect_list", OPR_AFFECT_LIST, 2);
+      node->unode.opr.op[0] = set;
+      node->unode.opr.op[1] = next;
+      return node;
+    }
+    static NodeType *new_affect_list_after(NodeType *affect_list)
+    {
+      NodeType *ret  = NULL;
+      NodeType *cur  =  affect_list;
+      while(cur != NULL) {
+        NodeType *set  = cur->unode.opr.op[0];
+        NodeType *next = cur->unode.opr.op[1];
+        NodeType *lvalue     = set->unode.opr.op[0];
+        NodeType *expression = set->unode.opr.op[1];
+        if ((lvalue->str[0] == '&') && (expression->type == VAR_NODE)) {
+          NodeType *nset = new_set(nodeClone(expression), nodeClone(lvalue));
+          ret  = new_affec_list(nset, ret);
+        }
+        cur = next;
+      }
+      return ret;
+    }
+    static void commit_affect_list(NodeType *node)
+    {
+      NodeType *cur = node;
+      while(cur != NULL) {
+        NodeType *set = cur->unode.opr.op[0];
+        precommit_node(set->unode.opr.op[0]);
+        precommit_node(set->unode.opr.op[1]);
+        cur = cur->unode.opr.op[1];
+      }
+      cur = node;
+      while(cur != NULL) {
+        NodeType *set = cur->unode.opr.op[0];
+        commit_node(set,0);
+        cur = cur->unode.opr.op[1];
+      }
+    } /* }}} */
+
+    /* VAR LIST */
+    static NodeType *new_var_list(NodeType *var, NodeType *next) /* {{{ */
+    {
+      NodeType *node = new_op("var_list", OPR_VAR_LIST, 2);
+      node->unode.opr.op[0] = var;
+      node->unode.opr.op[1] = next;
+      return node;
+    }
+    static void commit_var_list(NodeType *node)
+    {
+    } /* }}} */
+
+    /* FUNCTION CALL */
+    static NodeType *new_call(const char *name, NodeType *affect_list) { /* {{{ */
+        HashValue *fval;
+        fval = goom_hash_get(currentGoomSL->functions, name);
+        if (!fval) {
+            gsl_declare_task(name);
+            fval = goom_hash_get(currentGoomSL->functions, name);
+        }
+        if (!fval) {
+            fprintf(stderr, "ERROR: Line %d, Could not find function %s\n", currentGoomSL->num_lines, name);
+            exit(1);
+            return NULL;
+        }
+        else {
+            ExternalFunctionStruct *gef = (ExternalFunctionStruct*)fval->ptr;
+            if (gef->is_extern) {
+                NodeType *node =  new_op(name, OPR_EXT_CALL, 1);
+                node->unode.opr.op[0] = affect_list;
+                return node;
+            }
+            else {
+                NodeType *node;
+                char stmp[256];
+                if (strlen(name) < 200) {
+                    sprintf(stmp, "|__func_%s|", name);
+                }
+                node = new_op(stmp, OPR_CALL, 1);
+                node->unode.opr.op[0] = affect_list;
+                return node;
+            }
+        }
+    }
+    static void commit_ext_call(NodeType *node) {
+        NodeType *alafter = new_affect_list_after(node->unode.opr.op[0]);
+        commit_node(node->unode.opr.op[0],0);
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "extcall", INSTR_EXT_CALL, 1, node->line_number);
+        gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_VAR);
+#ifdef VERBOSE
+        printf("extcall %s\n", node->str);
+#endif
+        commit_node(alafter,0);
+    }
+    static void commit_call(NodeType *node) {
+        NodeType *alafter = new_affect_list_after(node->unode.opr.op[0]);
+        commit_node(node->unode.opr.op[0],0);
+        currentGoomSL->instr = gsl_instr_init(currentGoomSL, "call", INSTR_CALL, 1, node->line_number);
+        gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_LABEL);
+#ifdef VERBOSE
+        printf("call %s\n", node->str);
+#endif
+        commit_node(alafter,0);
+    } /* }}} */
+
+    /** **/
+
+    static NodeType *rootNode = 0; /* TODO: reinitialiser a chaque compilation. */
+    static NodeType *lastNode = 0;
+    static NodeType *gsl_append(NodeType *curNode) {
+        if (curNode == 0) return 0; /* {{{ */
+        if (lastNode)
+            lastNode->unode.opr.next = curNode;
+        lastNode = curNode;
+        while(lastNode->unode.opr.next) lastNode = lastNode->unode.opr.next;
+        if (rootNode == 0)
+            rootNode = curNode;
+        return curNode;
+    } /* }}} */
+
+#if 1
+    int allocateTemp() {
+      return allocateLabel();
+    }
+    void releaseAllTemps() {}
+    void releaseTemp(int n) {}
+#else
+    static int nbTemp = 0;
+    static int *tempArray = 0;
+    static int tempArraySize = 0;
+    int allocateTemp() { /* TODO: allocateITemp, allocateFTemp */
+        int i = 0; /* {{{ */
+        if (tempArray == 0) {
+          tempArraySize = 256;
+          tempArray = (int*)malloc(tempArraySize * sizeof(int));
+        }
+        while (1) {
+          int j;
+          for (j=0;j<nbTemp;++j) {
+            if (tempArray[j] == i) break;
+          }
+          if (j == nbTemp) {
+            if (nbTemp == tempArraySize) {
+              tempArraySize *= 2;
+              tempArray = (int*)realloc(tempArray,tempArraySize * sizeof(int));
+            }
+            tempArray[nbTemp++] = i;
+            return i;
+          }
+          i++;
+        }
+    } /* }}} */
+    void releaseAllTemps() {
+      nbTemp = 0; /* {{{ */
+    } /* }}} */
+    void releaseTemp(int n) {
+      int j; /* {{{ */
+      for (j=0;j<nbTemp;++j) {
+        if (tempArray[j] == n) {
+          tempArray[j] = tempArray[--nbTemp];
+          break;
+        }
+      }
+    } /* }}} */
+#endif
+
+    static int lastLabel = 0;
+    int allocateLabel() {
+        return ++lastLabel; /* {{{ */
+    } /* }}} */
+
+    void gsl_commit_compilation()
+    { /* {{{ */
+        commit_node(rootNode,0);
+        rootNode = 0;
+        lastNode = 0;
+    } /* }}} */
+    
+    void precommit_node(NodeType *node)
+    { /* {{{ */
+        /* do here stuff for expression.. for exemple */
+        if (node->type == OPR_NODE)
+            switch(node->unode.opr.type) {
+                case OPR_ADD: precommit_add(node); break;
+                case OPR_SUB: precommit_sub(node); break;
+                case OPR_MUL: precommit_mul(node); break;
+                case OPR_DIV: precommit_div(node); break;
+                case OPR_CALL_EXPR: precommit_call_expr(node); break;
+            }
+    } /* }}} */
+    
+    void commit_node(NodeType *node, int releaseIfTmp)
+    { /* {{{ */
+        if (node == 0) return;
+        
+        switch(node->type) {
+            case OPR_NODE:
+                switch(node->unode.opr.type) {
+                    case OPR_SET:           commit_set(node); break;
+                    case OPR_PLUS_EQ:       commit_plus_eq(node); break;
+                    case OPR_SUB_EQ:        commit_sub_eq(node); break;
+                    case OPR_MUL_EQ:        commit_mul_eq(node); break;
+                    case OPR_DIV_EQ:        commit_div_eq(node); break;
+                    case OPR_IF:            commit_if(node); break;
+                    case OPR_WHILE:         commit_while(node); break;
+                    case OPR_BLOCK:         commit_block(node); break;
+                    case OPR_FUNC_INTRO:    commit_function_intro(node); break;
+                    case OPR_FUNC_OUTRO:    commit_function_outro(node); break;
+                    case OPR_CALL:          commit_call(node); break;
+                    case OPR_EXT_CALL:      commit_ext_call(node); break;
+                    case OPR_EQU:           commit_equ(node); break;
+                    case OPR_LOW:           commit_low(node); break;
+                    case OPR_NOT:           commit_not(node); break;
+                    case OPR_AFFECT_LIST:   commit_affect_list(node); break;
+                    case OPR_FOREACH:       commit_foreach(node); break;
+                    case OPR_VAR_LIST:      commit_var_list(node); break;
+#ifdef VERBOSE
+                    case EMPTY_NODE:        printf("NOP\n"); break;
+#endif
+                }
+
+                commit_node(node->unode.opr.next,0); /* recursive for the moment, maybe better to do something iterative? */
+                break;
+
+            case VAR_NODE:         gsl_instr_set_namespace(currentGoomSL->instr, node->vnamespace);
+                                   gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_VAR); break;
+            case CONST_INT_NODE:   gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_INTEGER); break;
+            case CONST_FLOAT_NODE: gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_FLOAT); break;
+            case CONST_PTR_NODE:   gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_PTR); break;
+        }
+        if (releaseIfTmp && is_tmp_expr(node))
+          releaseTemp(get_tmp_id(node));
+        
+        nodeFree(node);
+    } /* }}} */
+
+    NodeType *nodeNew(const char *str, int type, int line_number) {
+        NodeType *node = (NodeType*)malloc(sizeof(NodeType)); /* {{{ */
+        node->type = type;
+        node->str  = (char*)malloc(strlen(str)+1);
+        node->vnamespace = NULL;
+        node->line_number = line_number;
+        strcpy(node->str, str);
+        return node;
+    } /* }}} */
+    static NodeType *nodeClone(NodeType *node) {
+        NodeType *ret = nodeNew(node->str, node->type, node->line_number); /* {{{ */
+        ret->vnamespace = node->vnamespace;
+        ret->unode = node->unode;
+        return ret;
+    } /* }}} */
+
+    void nodeFreeInternals(NodeType *node) {
+        free(node->str); /* {{{ */
+    } /* }}} */
+    
+    void nodeFree(NodeType *node) {
+        nodeFreeInternals(node); /* {{{ */
+        free(node);
+    } /* }}} */
+
+    NodeType *new_constInt(const char *str, int line_number) {
+        NodeType *node = nodeNew(str, CONST_INT_NODE, line_number); /* {{{ */
+        node->unode.constInt.val = atoi(str);
+        return node;
+    } /* }}} */
+
+    NodeType *new_constPtr(const char *str, int line_number) {
+        NodeType *node = nodeNew(str, CONST_PTR_NODE, line_number); /* {{{ */
+        node->unode.constPtr.id = strtol(str,NULL,0);
+        return node;
+    } /* }}} */
+
+    NodeType *new_constFloat(const char *str, int line_number) {
+        NodeType *node = nodeNew(str, CONST_FLOAT_NODE, line_number); /* {{{ */
+        node->unode.constFloat.val = atof(str);
+        return node;
+    } /* }}} */
+
+    NodeType *new_var(const char *str, int line_number) {
+        NodeType *node = nodeNew(str, VAR_NODE, line_number); /* {{{ */
+        node->vnamespace = gsl_find_namespace(str);
+        if (node->vnamespace == 0) {
+            fprintf(stderr, "ERROR: Line %d, Variable not found: '%s'\n", line_number, str);
+            exit(1);
+        }
+        return node;
+    } /* }}} */
+    
+    NodeType *new_nop(const char *str) {
+        NodeType *node = new_op(str, EMPTY_NODE, 0); /* {{{ */
+        return node;
+    } /* }}} */
+    
+    NodeType *new_op(const char *str, int type, int nbOp) {
+        int i; /* {{{ */
+        NodeType *node = nodeNew(str, OPR_NODE, currentGoomSL->num_lines);
+        node->unode.opr.next = 0;
+        node->unode.opr.type = type;
+        node->unode.opr.nbOp = nbOp;
+        for (i=0;i<nbOp;++i) node->unode.opr.op[i] = 0;
+        return node;
+    } /* }}} */
+
+
+    void gsl_declare_global_variable(int type, char *name) {
+      switch(type){
+        case -1: break;
+        case FLOAT_TK:gsl_float_decl_global(name);break;
+        case INT_TK:  gsl_int_decl_global(name);break;
+        case PTR_TK:  gsl_ptr_decl_global(name);break;
+        default:
+        {
+          int id = type - 1000;
+          gsl_struct_decl_global_from_id(name,id);
+        }
+      }
+    }
+
+%}
+
+%union {
+    int intValue;
+    float floatValue;
+    char charValue;
+    char strValue[2048];
+    NodeType *nPtr;
+    GoomHash *namespace;
+    GSL_Struct *gsl_struct;
+    GSL_StructField *gsl_struct_field;
+  };
+  
+%token <strValue>   LTYPE_INTEGER
+%token <strValue>   LTYPE_FLOAT
+%token <strValue>   LTYPE_VAR
+%token <strValue>   LTYPE_PTR
+
+%token PTR_TK INT_TK FLOAT_TK DECLARE EXTERNAL WHILE DO NOT PLUS_EQ SUB_EQ DIV_EQ MUL_EQ SUP_EQ LOW_EQ NOT_EQ STRUCT FOR IN
+
+%type <intValue> return_type
+%type <nPtr> expression constValue instruction test func_call func_call_expression
+%type <nPtr> start_block affectation_list affectation_in_list affectation declaration
+%type <nPtr> var_list_content var_list
+%type <strValue> task_name ext_task_name 
+%type <namespace> leave_namespace
+%type <gsl_struct> struct_members
+%type <gsl_struct_field> struct_member
+%left '\n'
+%left PLUS_EQ SUB_EQ MUL_EQ DIV_EQ
+%left NOT
+%left '=' '<' '>'
+%left '+' '-'
+%left '/' '*'
+
+%%
+
+/* -------------- Global architechture of a GSL program ------------*/
+
+gsl: gsl_code function_outro gsl_def_functions ;
+
+gsl_code: gsl_code instruction              { gsl_append($2); }
+   | gsl_code EXTERNAL '<' ext_task_name '>' return_type '\n' leave_namespace             { gsl_declare_global_variable($6,$4); }
+   | gsl_code EXTERNAL '<' ext_task_name ':' arglist '>' return_type '\n' leave_namespace { gsl_declare_global_variable($8,$4); }
+   | gsl_code DECLARE '<' task_name '>' return_type  '\n' leave_namespace                 { gsl_declare_global_variable($6,$4); }
+   | gsl_code DECLARE '<' task_name ':' arglist '>' return_type '\n' leave_namespace      { gsl_declare_global_variable($8,$4); }
+   | gsl_code struct_declaration
+   | gsl_code '\n'
+   |
+   ;
+
+/* ------------- Declaration of a structure ------------ */
+
+struct_declaration: STRUCT  '<' LTYPE_VAR  ':' struct_members '>' '\n' { gsl_add_struct($3, $5); }
+                  ;
+
+struct_members: opt_nl struct_member                    { $$ = gsl_new_struct($2);               }
+              | struct_members ',' opt_nl struct_member { $$ = $1; gsl_add_struct_field($1, $4); }
+              ;
+
+struct_member: INT_TK    LTYPE_VAR { $$ = gsl_new_struct_field($2, INSTR_INT); }
+             | FLOAT_TK  LTYPE_VAR { $$ = gsl_new_struct_field($2, INSTR_FLOAT); }
+             | PTR_TK    LTYPE_VAR { $$ = gsl_new_struct_field($2, INSTR_PTR); }
+             | LTYPE_VAR LTYPE_VAR { $$ = gsl_new_struct_field_struct($2, $1); }
+             ;
+
+/* ------------- Fonction declarations -------------- */
+
+ext_task_name: LTYPE_VAR { gsl_declare_external_task($1); gsl_enternamespace($1); strcpy($$,$1); }
+             ;
+task_name:     LTYPE_VAR { gsl_declare_task($1); gsl_enternamespace($1); strcpy($$,$1); strcpy($$,$1); }
+         ;
+
+return_type:      { $$=-1; }
+  | ':' INT_TK    { $$=INT_TK; }
+  | ':' FLOAT_TK  { $$=FLOAT_TK; }
+  | ':' PTR_TK    { $$=PTR_TK; }
+  | ':' LTYPE_VAR { $$= 1000 + gsl_get_struct_id($2); }
+  ;
+
+arglist: empty_declaration
+       | empty_declaration ',' arglist
+       ;
+
+/* ------------- Fonction definition -------------- */
+
+gsl_def_functions: gsl_def_functions function
+                 |
+                 ;
+
+function: function_intro gsl_code function_outro { gsl_leavenamespace(); }
+
+function_intro: '<' task_name '>' return_type '\n'             { gsl_append(new_function_intro($2));
+                                                                 gsl_declare_global_variable($4,$2); }
+              | '<' task_name ':' arglist '>' return_type '\n' { gsl_append(new_function_intro($2));
+                                                                 gsl_declare_global_variable($6,$2); }
+              ;
+function_outro: { gsl_append(new_function_outro()); } ;
+
+leave_namespace:      { $$ = gsl_leavenamespace();   };
+
+/* ------------ Variable declaration ---------------- */
+
+declaration: FLOAT_TK LTYPE_VAR '=' expression { gsl_float_decl_local($2); $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
+           | INT_TK   LTYPE_VAR '=' expression { gsl_int_decl_local($2);   $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
+           | PTR_TK   LTYPE_VAR '=' expression { gsl_ptr_decl_local($2);   $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
+           | LTYPE_VAR LTYPE_VAR '=' expression { gsl_struct_decl_local($1,$2); $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
+           | empty_declaration                { $$ = 0; }
+           ;
+
+empty_declaration: FLOAT_TK  LTYPE_VAR { gsl_float_decl_local($2);       }
+                 | INT_TK    LTYPE_VAR { gsl_int_decl_local($2);         }
+                 | PTR_TK    LTYPE_VAR { gsl_ptr_decl_local($2);         }
+                 | LTYPE_VAR LTYPE_VAR { gsl_struct_decl_local($1,$2);   }
+                 ;
+
+/* -------------- Instructions and Expressions ------------------ */
+
+instruction: affectation '\n' { $$ = $1; }
+           | declaration '\n' { $$ = $1; }
+           | '(' test ')' '?' opt_nl instruction     { $$ = new_if($2,$6); }
+           | WHILE test opt_nl DO opt_nl instruction { $$ = new_while($2,$6); }
+           | '{' '\n' start_block gsl_code '}' '\n'  { lastNode = $3->unode.opr.op[1]; $$=$3; }
+           | func_call                               { $$ = $1; }
+           | LTYPE_VAR PLUS_EQ expression { $$ = new_plus_eq(new_var($1,currentGoomSL->num_lines),$3); }
+           | LTYPE_VAR SUB_EQ expression  { $$ = new_sub_eq(new_var($1,currentGoomSL->num_lines),$3); }
+           | LTYPE_VAR MUL_EQ expression  { $$ = new_mul_eq(new_var($1,currentGoomSL->num_lines),$3); }
+           | LTYPE_VAR DIV_EQ expression  { $$ = new_div_eq(new_var($1,currentGoomSL->num_lines),$3); }
+           | FOR LTYPE_VAR IN var_list DO instruction { $$ = new_static_foreach(new_var($2, currentGoomSL->num_lines), $4, $6); }
+           ;
+
+var_list: '(' var_list_content ')'      { $$ = $2; }
+        ;
+var_list_content: LTYPE_VAR             { $$ = new_var_list(new_var($1,currentGoomSL->num_lines), NULL); }
+           | LTYPE_VAR var_list_content { $$ = new_var_list(new_var($1,currentGoomSL->num_lines), $2);   }
+           ;
+
+affectation: LTYPE_VAR '=' expression { $$ = new_set(new_var($1,currentGoomSL->num_lines),$3); } ;
+
+start_block: { $$ = new_block(lastNode); lastNode = $$->unode.opr.op[0]; }
+           ;
+
+expression: LTYPE_VAR   { $$ = new_var($1,currentGoomSL->num_lines); }
+          | constValue  { $$ = $1; }
+          | expression '*' expression { $$ = new_mul($1,$3); } 
+          | expression '/' expression { $$ = new_div($1,$3); } 
+          | expression '+' expression { $$ = new_add($1,$3); } 
+          | expression '-' expression { $$ = new_sub($1,$3); } 
+          | '-' expression            { $$ = new_neg($2);    }
+          | '(' expression ')'        { $$ = $2; }
+          | func_call_expression      { $$ = $1; }
+          ;
+
+test: expression '=' expression { $$ = new_equ($1,$3); } 
+    | expression '<' expression { $$ = new_low($1,$3); } 
+    | expression '>' expression { $$ = new_low($3,$1); }
+    | expression SUP_EQ expression { $$ = new_not(new_low($1,$3)); }
+    | expression LOW_EQ expression { $$ = new_not(new_low($3,$1)); }
+    | expression NOT_EQ expression { $$ = new_not(new_equ($1,$3)); }
+    | NOT test                  { $$ = new_not($2);    }
+    ;
+
+constValue: LTYPE_FLOAT   { $$ = new_constFloat($1,currentGoomSL->num_lines); }
+          | LTYPE_INTEGER { $$ = new_constInt($1,currentGoomSL->num_lines); } 
+          | LTYPE_PTR     { $$ = new_constPtr($1,currentGoomSL->num_lines); } 
+          ;
+
+/* ---------------- Function Calls ------------------ */
+
+func_call:   task_name '\n' leave_namespace                          { $$ = new_call($1,NULL); }
+           | task_name ':' affectation_list '\n' leave_namespace         { $$ = new_call($1,$3); }
+           | '[' task_name ']' '\n' leave_namespace                  { $$ = new_call($2,NULL); }
+           | '[' task_name ':' affectation_list ']' '\n' leave_namespace { $$ = new_call($2,$4); }
+           ;
+
+func_call_expression:
+            '[' task_name leave_namespace ']'                      { $$ = new_call_expr($2,NULL); }
+          | '[' task_name ':' affectation_list ']' leave_namespace { $$ = new_call_expr($2,$4); }
+          ;
+             
+affectation_list: affectation_in_list affectation_list     { $$ = new_affec_list($1,$2);   }
+            | affectation_in_list                          { $$ = new_affec_list($1,NULL); }
+
+affectation_in_list: LTYPE_VAR '=' leave_namespace expression {
+                              gsl_reenternamespace($3);
+                              $$ = new_set(new_var($1,currentGoomSL->num_lines),$4);
+                            }
+                   | ':' leave_namespace expression {
+                              gsl_reenternamespace($2);
+                              $$ = new_set(new_var("&this", currentGoomSL->num_lines),$3);
+                            }
+                   ;
+
+
+/* ------------ Misc ---------- */
+
+opt_nl: '\n' | ;
+           
+
+%%
+
+
+void yyerror(char *str)
+{ /* {{{ */
+    fprintf(stderr, "ERROR: Line %d, %s\n", currentGoomSL->num_lines, str);
+    currentGoomSL->compilationOK = 0;
+    exit(1);
+} /* }}} */
+
index c20f987dd3a57c690de34f28663c744707002391..2ee71a6dd0c1ac2176734f18d05d74d5c1fd84b5 100644 (file)
@@ -1,14 +1,10 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "graphic.h"
+#include "goom_graphic.h"
 
 const Color BLACK = { 0, 0, 0 };
 const Color WHITE = { 0xff, 0xff, 0xff };
-const Color RED = { 0xff, 0, 0 };
-const Color GREEN = { 0, 0xff, 0 };
-const Color BLUE = { 0, 0, 0xff };
+const Color RED = { 0xff, 0x05, 0x05 };
+const Color GREEN = { 0x05, 0xff, 0x05 };
+const Color BLUE = { 0x05, 0x05, 0xff };
 const Color YELLOW = { 0xff, 0xff, 0x33 };
-const Color ORANGE = { 0xff, 0xcc, 0x00 };
-const Color VIOLET = { 0x55, 0x00, 0xff };
+const Color ORANGE = { 0xff, 0xcc, 0x05 };
+const Color VIOLET = { 0x55, 0x05, 0xff };
diff --git a/gst/goom/graphic.h b/gst/goom/graphic.h
deleted file mode 100644 (file)
index 4154d7f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef GRAPHIC_H
-#define GRAPHIC_H
-
-#include <glib.h>  /* defines inline for better portability */
-
-typedef unsigned int Uint;
-
-typedef struct
-{
-  unsigned short r,v,b;
-}
-Color;
-
-extern const Color BLACK;
-extern const Color WHITE;
-extern const Color RED;
-extern const Color BLUE;
-extern const Color GREEN;
-extern const Color YELLOW;
-extern const Color ORANGE;
-extern const Color VIOLET;
-
-#endif /*GRAPHIC_H*/
index ca9b311146cf435e713d79f6cf830193ac24f4c9..7ba6654a3ab431cfa2953987b50f7f3fddba6077 100644 (file)
@@ -44,7 +44,7 @@
 #include <gst/gst.h>
 #include "gstgoom.h"
 #include <gst/video/video.h>
-#include "goom_core.h"
+#include "goom.h"
 
 GST_DEBUG_CATEGORY_STATIC (goom_debug);
 #define GST_CAT_DEFAULT goom_debug
@@ -187,7 +187,7 @@ gst_goom_init (GstGoom * goom)
   goom->rate = 0;
   goom->duration = 0;
 
-  goom_init (&(goom->goomdata), goom->width, goom->height);
+  goom->plugin = goom_init (goom->width, goom->height);
 }
 
 static void
@@ -195,7 +195,7 @@ gst_goom_finalize (GObject * object)
 {
   GstGoom *goom = GST_GOOM (object);
 
-  goom_close (&(goom->goomdata));
+  goom_close (goom->plugin);
 
   g_object_unref (goom->adapter);
 
@@ -250,7 +250,7 @@ gst_goom_src_setcaps (GstPad * pad, GstCaps * caps)
           &goom->fps_d))
     return FALSE;
 
-  goom_set_resolution (&(goom->goomdata), goom->width, goom->height);
+  goom_set_resolution (goom->plugin, goom->width, goom->height);
 
   /* size of the output buffer in bytes, depth is always 4 bytes */
   goom->outsize = goom->width * goom->height * 4;
@@ -523,7 +523,8 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer)
     GST_BUFFER_DURATION (outbuf) = goom->duration;
     GST_BUFFER_SIZE (outbuf) = goom->outsize;
 
-    out_frame = (guchar *) goom_update (&(goom->goomdata), goom->datain);
+    out_frame = (guchar *) goom_update (goom->plugin, goom->datain, 0, 0,
+        NULL, NULL);
     memcpy (GST_BUFFER_DATA (outbuf), out_frame, goom->outsize);
 
     GST_DEBUG ("Pushing frame with time=%" GST_TIME_FORMAT ", duration=%"
index 9c25f453f2b8ad95669d131c55098e5edd5774c4..e9ca83cefbe0176540f78e5103db25780fbd75d4 100644 (file)
@@ -24,7 +24,7 @@ G_BEGIN_DECLS
 
 #include <gst/gst.h>
 #include <gst/base/gstadapter.h>
-#include "goom_core.h"
+#include "goom.h"
 
 #define GOOM_SAMPLES 512
 
@@ -65,7 +65,7 @@ struct _GstGoom
 
   /* goom stuff */
   gint16 datain[2][GOOM_SAMPLES];
-  GoomData goomdata;
+  PluginInfo *plugin;
 
   /* segment state */
   GstSegment segment;
diff --git a/gst/goom/ifs.c b/gst/goom/ifs.c
new file mode 100644 (file)
index 0000000..8e72548
--- /dev/null
@@ -0,0 +1,776 @@
+/*
+ * ifs.c --- modified iterated functions system for goom.
+ */
+
+/*-
+ * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr>
+ *
+ * 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.
+ *
+ * If this mode is weird and you have an old MetroX server, it is buggy.
+ * There is a free SuSE-enhanced MetroX X server that is fine.
+ *
+ * When shown ifs, Diana Rose (4 years old) said, "It looks like dancing."
+ *
+ * Revision History:
+ * 13-Dec-2003: Added some goom specific stuffs (to make ifs a VisualFX).
+ * 11-Apr-2002: jeko@ios-software.com: Make ifs.c system-indendant. (ifs.h added)
+ * 01-Nov-2000: Allocation checks
+ * 10-May-1997: jwz@jwz.org: turned into a standalone program.
+ *              Made it render into an offscreen bitmap and then copy
+ *              that onto the screen, to reduce flicker.
+ */
+
+/* #ifdef STANDALONE */
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "goom_config.h"
+
+#ifdef HAVE_MMX
+#include "mmx.h"
+#endif
+
+#include "goom_graphic.h"
+#include "ifs.h"
+#include "goom_tools.h"
+
+typedef struct _ifsPoint
+{
+  gint32 x, y;
+}
+IFSPoint;
+
+
+#define MODE_ifs
+
+#define PROGCLASS "IFS"
+
+#define HACK_INIT init_ifs
+#define HACK_DRAW draw_ifs
+
+#define ifs_opts xlockmore_opts
+
+#define DEFAULTS "*delay: 20000 \n" \
+"*ncolors: 100 \n"
+
+#define SMOOTH_COLORS
+
+#define LRAND()            ((long) (goom_random(goomInfo->gRandom) & 0x7fffffff))
+#define NRAND(n)           ((int) (LRAND() % (n)))
+
+#if RAND_MAX < 0x10000
+#define MAXRAND (((float)(RAND_MAX<16)+((float)RAND_MAX)+1.0f)/127.0f)
+#else
+#define MAXRAND            (2147483648.0/127.0) /* unsigned 1<<31 / 127.0 (cf goom_tools) as a float */
+#endif
+
+/*****************************************************/
+
+typedef float DBL;
+typedef int F_PT;
+
+/* typedef float               F_PT; */
+
+/*****************************************************/
+
+#define FIX 12
+#define UNIT   ( 1<<FIX )
+#define MAX_SIMI  6
+
+#define MAX_DEPTH_2  10
+#define MAX_DEPTH_3  6
+#define MAX_DEPTH_4  4
+#define MAX_DEPTH_5  2
+
+/* PREVIOUS VALUE 
+#define MAX_SIMI  6
+
+ * settings for a PC 120Mhz... *
+#define MAX_DEPTH_2  10
+#define MAX_DEPTH_3  6
+#define MAX_DEPTH_4  4
+#define MAX_DEPTH_5  3
+*/
+
+#define DBL_To_F_PT(x)  (F_PT)( (DBL)(UNIT)*(x) )
+
+typedef struct Similitude_Struct SIMI;
+typedef struct Fractal_Struct FRACTAL;
+
+struct Similitude_Struct
+{
+
+  DBL c_x, c_y;
+  DBL r, r2, A, A2;
+  F_PT Ct, St, Ct2, St2;
+  F_PT Cx, Cy;
+  F_PT R, R2;
+};
+
+
+struct Fractal_Struct
+{
+
+  int Nb_Simi;
+  SIMI Components[5 * MAX_SIMI];
+  int Depth, Col;
+  int Count, Speed;
+  int Width, Height, Lx, Ly;
+  DBL r_mean, dr_mean, dr2_mean;
+  int Cur_Pt, Max_Pt;
+
+  IFSPoint *Buffer1, *Buffer2;
+};
+
+typedef struct _IFS_DATA
+{
+  FRACTAL *Root;
+  FRACTAL *Cur_F;
+
+  /* Used by the Trace recursive method */
+  IFSPoint *Buf;
+  int Cur_Pt;
+  int initalized;
+} IfsData;
+
+
+/*****************************************************/
+
+static DBL
+Gauss_Rand (PluginInfo * goomInfo, DBL c, DBL A, DBL S)
+{
+  DBL y;
+
+  y = (DBL) LRAND () / MAXRAND;
+  y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
+  if (NRAND (2))
+    return (c + y);
+  return (c - y);
+}
+
+static DBL
+Half_Gauss_Rand (PluginInfo * goomInfo, DBL c, DBL A, DBL S)
+{
+  DBL y;
+
+  y = (DBL) LRAND () / MAXRAND;
+  y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
+  return (c + y);
+}
+
+static void
+Random_Simis (PluginInfo * goomInfo, FRACTAL * F, SIMI * Cur, int i)
+{
+  while (i--) {
+    Cur->c_x = Gauss_Rand (goomInfo, 0.0, .8, 4.0);
+    Cur->c_y = Gauss_Rand (goomInfo, 0.0, .8, 4.0);
+    Cur->r = Gauss_Rand (goomInfo, F->r_mean, F->dr_mean, 3.0);
+    Cur->r2 = Half_Gauss_Rand (goomInfo, 0.0, F->dr2_mean, 2.0);
+    Cur->A = Gauss_Rand (goomInfo, 0.0, 360.0, 4.0) * (M_PI / 180.0);
+    Cur->A2 = Gauss_Rand (goomInfo, 0.0, 360.0, 4.0) * (M_PI / 180.0);
+    Cur++;
+  }
+}
+
+static void
+free_ifs_buffers (FRACTAL * Fractal)
+{
+  if (Fractal->Buffer1 != NULL) {
+    (void) free ((void *) Fractal->Buffer1);
+    Fractal->Buffer1 = (IFSPoint *) NULL;
+  }
+  if (Fractal->Buffer2 != NULL) {
+    (void) free ((void *) Fractal->Buffer2);
+    Fractal->Buffer2 = (IFSPoint *) NULL;
+  }
+}
+
+
+static void
+free_ifs (FRACTAL * Fractal)
+{
+  free_ifs_buffers (Fractal);
+}
+
+/***************************************************************/
+
+static void
+init_ifs (PluginInfo * goomInfo, IfsData * data)
+{
+  int i;
+  FRACTAL *Fractal;
+  int width = goomInfo->screen.width;
+  int height = goomInfo->screen.height;
+
+  if (data->Root == NULL) {
+    data->Root = (FRACTAL *) malloc (sizeof (FRACTAL));
+    if (data->Root == NULL)
+      return;
+    data->Root->Buffer1 = (IFSPoint *) NULL;
+    data->Root->Buffer2 = (IFSPoint *) NULL;
+  }
+  Fractal = data->Root;
+
+  free_ifs_buffers (Fractal);
+
+  i = (NRAND (4)) + 2;          /* Number of centers */
+  switch (i) {
+    case 3:
+      Fractal->Depth = MAX_DEPTH_3;
+      Fractal->r_mean = .6;
+      Fractal->dr_mean = .4;
+      Fractal->dr2_mean = .3;
+      break;
+
+    case 4:
+      Fractal->Depth = MAX_DEPTH_4;
+      Fractal->r_mean = .5;
+      Fractal->dr_mean = .4;
+      Fractal->dr2_mean = .3;
+      break;
+
+    case 5:
+      Fractal->Depth = MAX_DEPTH_5;
+      Fractal->r_mean = .5;
+      Fractal->dr_mean = .4;
+      Fractal->dr2_mean = .3;
+      break;
+
+    default:
+    case 2:
+      Fractal->Depth = MAX_DEPTH_2;
+      Fractal->r_mean = .7;
+      Fractal->dr_mean = .3;
+      Fractal->dr2_mean = .4;
+      break;
+  }
+  Fractal->Nb_Simi = i;
+  Fractal->Max_Pt = Fractal->Nb_Simi - 1;
+  for (i = 0; i <= Fractal->Depth + 2; ++i)
+    Fractal->Max_Pt *= Fractal->Nb_Simi;
+
+  if ((Fractal->Buffer1 = (IFSPoint *) calloc (Fractal->Max_Pt,
+              sizeof (IFSPoint))) == NULL) {
+    free_ifs (Fractal);
+    return;
+  }
+  if ((Fractal->Buffer2 = (IFSPoint *) calloc (Fractal->Max_Pt,
+              sizeof (IFSPoint))) == NULL) {
+    free_ifs (Fractal);
+    return;
+  }
+
+  Fractal->Speed = 6;
+  Fractal->Width = width;       /* modif by JeKo */
+  Fractal->Height = height;     /* modif by JeKo */
+  Fractal->Cur_Pt = 0;
+  Fractal->Count = 0;
+  Fractal->Lx = (Fractal->Width - 1) / 2;
+  Fractal->Ly = (Fractal->Height - 1) / 2;
+  Fractal->Col = rand () % (width * height);    /* modif by JeKo */
+
+  Random_Simis (goomInfo, Fractal, Fractal->Components, 5 * MAX_SIMI);
+}
+
+
+/***************************************************************/
+
+static inline void
+Transform (SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y)
+{
+  F_PT xx, yy;
+
+  xo = xo - Simi->Cx;
+  xo = (xo * Simi->R) >> FIX;   /* / UNIT; */
+  yo = yo - Simi->Cy;
+  yo = (yo * Simi->R) >> FIX;   /* / UNIT; */
+
+  xx = xo - Simi->Cx;
+  xx = (xx * Simi->R2) >> FIX;  /* / UNIT; */
+  yy = -yo - Simi->Cy;
+  yy = (yy * Simi->R2) >> FIX;  /* / UNIT; */
+
+  *x = ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2)
+      >> FIX /* / UNIT */ ) + Simi->Cx;
+  *y = ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2)
+      >> FIX /* / UNIT */ ) + Simi->Cy;
+}
+
+/***************************************************************/
+
+static void
+Trace (FRACTAL * F, F_PT xo, F_PT yo, IfsData * data)
+{
+  F_PT x, y, i;
+  SIMI *Cur;
+
+  Cur = data->Cur_F->Components;
+  for (i = data->Cur_F->Nb_Simi; i; --i, Cur++) {
+    Transform (Cur, xo, yo, &x, &y);
+
+    data->Buf->x = F->Lx + ((x * F->Lx) >> (FIX + 1) /* /(UNIT*2) */ );
+    data->Buf->y = F->Ly - ((y * F->Ly) >> (FIX + 1) /* /(UNIT*2) */ );
+    data->Buf++;
+
+    data->Cur_Pt++;
+
+    if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) {
+      F->Depth--;
+      Trace (F, x, y, data);
+      F->Depth++;
+    }
+  }
+}
+
+static void
+Draw_Fractal (IfsData * data)
+{
+  FRACTAL *F = data->Root;
+  int i, j;
+  F_PT x, y, xo, yo;
+  SIMI *Cur, *Simi;
+
+  for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
+    Cur->Cx = DBL_To_F_PT (Cur->c_x);
+    Cur->Cy = DBL_To_F_PT (Cur->c_y);
+
+    Cur->Ct = DBL_To_F_PT (cos (Cur->A));
+    Cur->St = DBL_To_F_PT (sin (Cur->A));
+    Cur->Ct2 = DBL_To_F_PT (cos (Cur->A2));
+    Cur->St2 = DBL_To_F_PT (sin (Cur->A2));
+
+    Cur->R = DBL_To_F_PT (Cur->r);
+    Cur->R2 = DBL_To_F_PT (Cur->r2);
+  }
+
+
+  data->Cur_Pt = 0;
+  data->Cur_F = F;
+  data->Buf = F->Buffer2;
+  for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
+    xo = Cur->Cx;
+    yo = Cur->Cy;
+    for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) {
+      if (Simi == Cur)
+        continue;
+      Transform (Simi, xo, yo, &x, &y);
+      Trace (F, x, y, data);
+    }
+  }
+
+  /* Erase previous */
+
+  F->Cur_Pt = data->Cur_Pt;
+  data->Buf = F->Buffer1;
+  F->Buffer1 = F->Buffer2;
+  F->Buffer2 = data->Buf;
+}
+
+
+static IFSPoint *
+draw_ifs (PluginInfo * goomInfo, int *nbpt, IfsData * data)
+{
+  int i;
+  DBL u, uu, v, vv, u0, u1, u2, u3;
+  SIMI *S, *S1, *S2, *S3, *S4;
+  FRACTAL *F;
+
+  if (data->Root == NULL)
+    return NULL;
+  F = data->Root;
+  if (F->Buffer1 == NULL)
+    return NULL;
+
+  u = (DBL) (F->Count) * (DBL) (F->Speed) / 1000.0;
+  uu = u * u;
+  v = 1.0 - u;
+  vv = v * v;
+  u0 = vv * v;
+  u1 = 3.0 * vv * u;
+  u2 = 3.0 * v * uu;
+  u3 = u * uu;
+
+  S = F->Components;
+  S1 = S + F->Nb_Simi;
+  S2 = S1 + F->Nb_Simi;
+  S3 = S2 + F->Nb_Simi;
+  S4 = S3 + F->Nb_Simi;
+
+  for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
+    S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x;
+    S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y;
+    S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r;
+    S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2;
+    S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A;
+    S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2;
+  }
+
+  Draw_Fractal (data);
+
+  if (F->Count >= 1000 / F->Speed) {
+    S = F->Components;
+    S1 = S + F->Nb_Simi;
+    S2 = S1 + F->Nb_Simi;
+    S3 = S2 + F->Nb_Simi;
+    S4 = S3 + F->Nb_Simi;
+
+    for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
+      S2->c_x = 2.0 * S4->c_x - S3->c_x;
+      S2->c_y = 2.0 * S4->c_y - S3->c_y;
+      S2->r = 2.0 * S4->r - S3->r;
+      S2->r2 = 2.0 * S4->r2 - S3->r2;
+      S2->A = 2.0 * S4->A - S3->A;
+      S2->A2 = 2.0 * S4->A2 - S3->A2;
+
+      *S1 = *S4;
+    }
+    Random_Simis (goomInfo, F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi);
+
+    Random_Simis (goomInfo, F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi);
+
+    F->Count = 0;
+  } else
+    F->Count++;
+
+  F->Col++;
+
+  (*nbpt) = data->Cur_Pt;
+  return F->Buffer2;
+}
+
+
+/***************************************************************/
+
+static void
+release_ifs (IfsData * data)
+{
+  if (data->Root != NULL) {
+    free_ifs (data->Root);
+    (void) free ((void *) data->Root);
+    data->Root = (FRACTAL *) NULL;
+  }
+}
+
+#define RAND() goom_random(goomInfo->gRandom)
+
+static void
+ifs_update (PluginInfo * goomInfo, Pixel * data, Pixel * back, int increment,
+    IfsData * fx_data)
+{
+  static int couleur = 0xc0c0c0c0;
+  static int v[4] = { 2, 4, 3, 2 };
+  static int col[4] = { 2, 4, 3, 2 };
+
+#define MOD_MER 0
+#define MOD_FEU 1
+#define MOD_MERVER 2
+  static int mode = MOD_MERVER;
+  static int justChanged = 0;
+  static int cycle = 0;
+  int cycle10;
+
+  int nbpt;
+  IFSPoint *points;
+  int i;
+
+  int couleursl = couleur;
+  int width = goomInfo->screen.width;
+  int height = goomInfo->screen.height;
+
+  cycle++;
+  if (cycle >= 80)
+    cycle = 0;
+
+  if (cycle < 40)
+    cycle10 = cycle / 10;
+  else
+    cycle10 = 7 - cycle / 10;
+
+  {
+    unsigned char *tmp = (unsigned char *) &couleursl;
+
+    for (i = 0; i < 4; i++) {
+      *tmp = (*tmp) >> cycle10;
+      tmp++;
+    }
+  }
+
+  points = draw_ifs (goomInfo, &nbpt, fx_data);
+  nbpt--;
+
+#ifdef HAVE_MMX
+  movd_m2r (couleursl, mm1);
+  punpckldq_r2r (mm1, mm1);
+  for (i = 0; i < nbpt; i += increment) {
+    int x = points[i].x;
+    int y = points[i].y;
+
+    if ((x < width) && (y < height) && (x > 0) && (y > 0)) {
+      int pos = x + (y * width);
+
+      movd_m2r (back[pos], mm0);
+      paddusb_r2r (mm1, mm0);
+      movd_r2m (mm0, data[pos]);
+    }
+  }
+  emms ();     /*__asm__ __volatile__ ("emms");*/
+#else
+  for (i = 0; i < nbpt; i += increment) {
+    int x = (int) points[i].x & 0x7fffffff;
+    int y = (int) points[i].y & 0x7fffffff;
+
+    if ((x < width) && (y < height)) {
+      int pos = x + (int) (y * width);
+      int tra = 0, i = 0;
+      unsigned char *bra = (unsigned char *) &back[pos];
+      unsigned char *dra = (unsigned char *) &data[pos];
+      unsigned char *cra = (unsigned char *) &couleursl;
+
+      for (; i < 4; i++) {
+        tra = *cra;
+        tra += *bra;
+        if (tra > 255)
+          tra = 255;
+        *dra = tra;
+        ++dra;
+        ++cra;
+        ++bra;
+      }
+    }
+  }
+#endif /*MMX*/
+      justChanged--;
+
+  col[ALPHA] = couleur >> (ALPHA * 8) & 0xff;
+  col[BLEU] = couleur >> (BLEU * 8) & 0xff;
+  col[VERT] = couleur >> (VERT * 8) & 0xff;
+  col[ROUGE] = couleur >> (ROUGE * 8) & 0xff;
+
+  if (mode == MOD_MER) {
+    col[BLEU] += v[BLEU];
+    if (col[BLEU] > 255) {
+      col[BLEU] = 255;
+      v[BLEU] = -(RAND () % 4) - 1;
+    }
+    if (col[BLEU] < 32) {
+      col[BLEU] = 32;
+      v[BLEU] = (RAND () % 4) + 1;
+    }
+
+    col[VERT] += v[VERT];
+    if (col[VERT] > 200) {
+      col[VERT] = 200;
+      v[VERT] = -(RAND () % 3) - 2;
+    }
+    if (col[VERT] > col[BLEU]) {
+      col[VERT] = col[BLEU];
+      v[VERT] = v[BLEU];
+    }
+    if (col[VERT] < 32) {
+      col[VERT] = 32;
+      v[VERT] = (RAND () % 3) + 2;
+    }
+
+    col[ROUGE] += v[ROUGE];
+    if (col[ROUGE] > 64) {
+      col[ROUGE] = 64;
+      v[ROUGE] = -(RAND () % 4) - 1;
+    }
+    if (col[ROUGE] < 0) {
+      col[ROUGE] = 0;
+      v[ROUGE] = (RAND () % 4) + 1;
+    }
+
+    col[ALPHA] += v[ALPHA];
+    if (col[ALPHA] > 0) {
+      col[ALPHA] = 0;
+      v[ALPHA] = -(RAND () % 4) - 1;
+    }
+    if (col[ALPHA] < 0) {
+      col[ALPHA] = 0;
+      v[ALPHA] = (RAND () % 4) + 1;
+    }
+
+    if (((col[VERT] > 32) && (col[ROUGE] < col[VERT] + 40)
+            && (col[VERT] < col[ROUGE] + 20) && (col[BLEU] < 64)
+            && (RAND () % 20 == 0)) && (justChanged < 0)) {
+      mode = RAND () % 3 ? MOD_FEU : MOD_MERVER;
+      justChanged = 250;
+    }
+  } else if (mode == MOD_MERVER) {
+    col[BLEU] += v[BLEU];
+    if (col[BLEU] > 128) {
+      col[BLEU] = 128;
+      v[BLEU] = -(RAND () % 4) - 1;
+    }
+    if (col[BLEU] < 16) {
+      col[BLEU] = 16;
+      v[BLEU] = (RAND () % 4) + 1;
+    }
+
+    col[VERT] += v[VERT];
+    if (col[VERT] > 200) {
+      col[VERT] = 200;
+      v[VERT] = -(RAND () % 3) - 2;
+    }
+    if (col[VERT] > col[ALPHA]) {
+      col[VERT] = col[ALPHA];
+      v[VERT] = v[ALPHA];
+    }
+    if (col[VERT] < 32) {
+      col[VERT] = 32;
+      v[VERT] = (RAND () % 3) + 2;
+    }
+
+    col[ROUGE] += v[ROUGE];
+    if (col[ROUGE] > 128) {
+      col[ROUGE] = 128;
+      v[ROUGE] = -(RAND () % 4) - 1;
+    }
+    if (col[ROUGE] < 0) {
+      col[ROUGE] = 0;
+      v[ROUGE] = (RAND () % 4) + 1;
+    }
+
+    col[ALPHA] += v[ALPHA];
+    if (col[ALPHA] > 255) {
+      col[ALPHA] = 255;
+      v[ALPHA] = -(RAND () % 4) - 1;
+    }
+    if (col[ALPHA] < 0) {
+      col[ALPHA] = 0;
+      v[ALPHA] = (RAND () % 4) + 1;
+    }
+
+    if (((col[VERT] > 32) && (col[ROUGE] < col[VERT] + 40)
+            && (col[VERT] < col[ROUGE] + 20) && (col[BLEU] < 64)
+            && (RAND () % 20 == 0)) && (justChanged < 0)) {
+      mode = RAND () % 3 ? MOD_FEU : MOD_MER;
+      justChanged = 250;
+    }
+  } else if (mode == MOD_FEU) {
+
+    col[BLEU] += v[BLEU];
+    if (col[BLEU] > 64) {
+      col[BLEU] = 64;
+      v[BLEU] = -(RAND () % 4) - 1;
+    }
+    if (col[BLEU] < 0) {
+      col[BLEU] = 0;
+      v[BLEU] = (RAND () % 4) + 1;
+    }
+
+    col[VERT] += v[VERT];
+    if (col[VERT] > 200) {
+      col[VERT] = 200;
+      v[VERT] = -(RAND () % 3) - 2;
+    }
+    if (col[VERT] > col[ROUGE] + 20) {
+      col[VERT] = col[ROUGE] + 20;
+      v[VERT] = -(RAND () % 3) - 2;
+      v[ROUGE] = (RAND () % 4) + 1;
+      v[BLEU] = (RAND () % 4) + 1;
+    }
+    if (col[VERT] < 0) {
+      col[VERT] = 0;
+      v[VERT] = (RAND () % 3) + 2;
+    }
+
+    col[ROUGE] += v[ROUGE];
+    if (col[ROUGE] > 255) {
+      col[ROUGE] = 255;
+      v[ROUGE] = -(RAND () % 4) - 1;
+    }
+    if (col[ROUGE] > col[VERT] + 40) {
+      col[ROUGE] = col[VERT] + 40;
+      v[ROUGE] = -(RAND () % 4) - 1;
+    }
+    if (col[ROUGE] < 0) {
+      col[ROUGE] = 0;
+      v[ROUGE] = (RAND () % 4) + 1;
+    }
+
+    col[ALPHA] += v[ALPHA];
+    if (col[ALPHA] > 0) {
+      col[ALPHA] = 0;
+      v[ALPHA] = -(RAND () % 4) - 1;
+    }
+    if (col[ALPHA] < 0) {
+      col[ALPHA] = 0;
+      v[ALPHA] = (RAND () % 4) + 1;
+    }
+
+    if (((col[ROUGE] < 64) && (col[VERT] > 32) && (col[VERT] < col[BLEU])
+            && (col[BLEU] > 32)
+            && (RAND () % 20 == 0)) && (justChanged < 0)) {
+      mode = RAND () % 2 ? MOD_MER : MOD_MERVER;
+      justChanged = 250;
+    }
+  }
+
+  couleur = (col[ALPHA] << (ALPHA * 8))
+      | (col[BLEU] << (BLEU * 8))
+      | (col[VERT] << (VERT * 8))
+      | (col[ROUGE] << (ROUGE * 8));
+}
+
+/** VISUAL_FX WRAPPER FOR IFS */
+
+static void
+ifs_vfx_apply (VisualFX * _this, Pixel * src, Pixel * dest,
+    PluginInfo * goomInfo)
+{
+
+  IfsData *data = (IfsData *) _this->fx_data;
+
+  if (!data->initalized) {
+    data->initalized = 1;
+    init_ifs (goomInfo, data);
+  }
+  ifs_update (goomInfo, dest, src, goomInfo->update.ifs_incr, data);
+  /*TODO: trouver meilleur soluce pour increment (mettre le code de gestion de l'ifs dans ce fichier: ifs_vfx_apply) */
+}
+
+static void
+ifs_vfx_init (VisualFX * _this, PluginInfo * info)
+{
+
+  IfsData *data = (IfsData *) malloc (sizeof (IfsData));
+
+  data->Root = (FRACTAL *) NULL;
+  data->initalized = 0;
+  _this->fx_data = data;
+}
+
+static void
+ifs_vfx_free (VisualFX * _this)
+{
+  IfsData *data = (IfsData *) _this->fx_data;
+
+  release_ifs (data);
+  free (data);
+}
+
+VisualFX
+ifs_visualfx_create (void)
+{
+  VisualFX vfx;
+
+  vfx.init = ifs_vfx_init;
+  vfx.free = ifs_vfx_free;
+  vfx.apply = ifs_vfx_apply;
+  return vfx;
+}
diff --git a/gst/goom/ifs.h b/gst/goom/ifs.h
new file mode 100644 (file)
index 0000000..fab0426
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * File created 11 april 2002 by JeKo <jeko@free.fr>
+ */
+
+#ifndef IFS_H
+#define IFS_H
+
+#include "goom_config.h"
+#include "goom_graphic.h"
+#include "goom_plugin_info.h"
+#include "goom_visual_fx.h"
+
+VisualFX ifs_visualfx_create(void);
+
+/* init ifs for a (width)x(height) output. * /
+void init_ifs (PluginInfo *goomInfo, int width, int height);
+
+/ * draw an ifs on the buffer (which size is width * height)
+   increment means that we draw 1/increment of the ifs's points * /
+void ifs_update (PluginInfo *goomInfo, Pixel * buffer, Pixel * back, int width, int height, int increment);
+
+/ * free all ifs's data. * /
+void release_ifs (void);
+*/
+
+
+#endif
index 3214e1db0ca3f6e2d603c10e3770824cff2e7662..a2a94d43ffb38807597aefb9ec544656a0a7460c 100644 (file)
 /*
  *  lines.c
- *  iTunesXPlugIn
- *
- *  Created by guillaum on Tue Aug 14 2001.
- *  Copyright (c) 2001 __CompanyName__. All rights reserved.
- *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "lines.h"
 #include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "goom_tools.h"
+#include "drawmethods.h"
+#include "goom_plugin_info.h"
 
 static inline unsigned char
-lighten (unsigned char value, unsigned char power)
+lighten (unsigned char value, float power)
 {
-  unsigned char i;
+  int val = value;
+  float t = (float) val * log10 (power) / 2.0;
 
-  for (i = 0; i < power; i++)
-    value += (255 - value) / 5;
-  return value;
+  if (t > 0) {
+    val = (int) t;              /* (32.0f * log (t)); */
+    if (val > 255)
+      val = 255;
+    if (val < 0)
+      val = 0;
+    return val;
+  } else {
+    return 0;
+  }
 }
 
-void
-goom_lines (GoomData * goomdata, gint16 data[2][512], unsigned int ID,
-    unsigned int *p, guint32 power)
+static void
+lightencolor (guint32 * col, float power)
 {
-  guint32 color1;
-  guint32 color2;
-  guint32 resolx = goomdata->resolx;
-  guint32 resoly = goomdata->resoly;
-  unsigned char *color = 1 + (unsigned char *) &color1;
-
-  switch (ID) {
-    case 0:                    /* Horizontal stereo lines */
-    {
-      color1 = 0x0000AA00;
-      color2 = 0x00AA0000;
-      break;
-    }
+  unsigned char *color;
 
-    case 1:                    /* Stereo circles */
-    {
-      color1 = 0x00AA33DD;
-      color2 = 0x00AA33DD;
-      break;
-    }
-  }
+  color = (unsigned char *) col;
   *color = lighten (*color, power);
   color++;
   *color = lighten (*color, power);
   color++;
   *color = lighten (*color, power);
-  color = 1 + (unsigned char *) &color2;
-  *color = lighten (*color, power);
-  color++;
-  *color = lighten (*color, power);
   color++;
   *color = lighten (*color, power);
+}
 
-  switch (ID) {
-    case 0:                    /* Horizontal stereo lines */
-    {
-      unsigned int i;
 
+
+static void
+genline (int id, float param, GMUnitPointer * l, int rx, int ry)
+{
+  int i;
+
+  switch (id) {
+    case GML_HLINE:
       for (i = 0; i < 512; i++) {
-        guint32 plot;
-
-        plot = i * resolx / 512 + (resoly / 4 + data[0][i] / 1600) * resolx;
-        p[plot] = color1;
-        p[plot + 1] = color1;
-        plot = i * resolx / 512 + (resoly * 3 / 4 - data[1][i] / 1600) * resolx;
-        p[plot] = color2;
-        p[plot + 1] = color2;
+        l[i].x = ((float) i * rx) / 512.0f;
+        l[i].y = param;
+        l[i].angle = M_PI / 2.0f;
       }
-      break;
-    }
+      return;
+    case GML_VLINE:
+      for (i = 0; i < 512; i++) {
+        l[i].y = ((float) i * ry) / 512.0f;
+        l[i].x = param;
+        l[i].angle = 0.0f;
+      }
+      return;
+    case GML_CIRCLE:
+      for (i = 0; i < 512; i++) {
+        float cosa, sina;
 
-    case 1:                    /* Stereo circles */
-    {
-      float z;
-      unsigned int monX = resolx / 2;
-      float monY = resoly / 4;
-      float monY2 = resoly / 2;
-
-      for (z = 0; z < 6.2832f; z += 1.0f / monY) {
-        /* float offset1 = 128+data[1][(unsigned int)(z*81.33f)])/200000; */
-        p[monX + (unsigned int) ((monY + ((float) resoly) * (128 +
-                        data[1][(unsigned int) (z * 81.33f)]) / 200000) *
-                cos (z) + resolx * (unsigned int) (monY2 + (monY +
-                        ((float) resoly) * (128 +
-                            data[1][(unsigned int) (z * 81.33f)]) / 400000) *
-                    sin (z)))] = color1;
-        p[monX + (unsigned int) ((monY - ((float) resoly) * (128 +
-                        data[0][(unsigned int) (z * 81.33f)]) / 200000) *
-                cos (z) + resolx * (unsigned int) (monY2 + (monY -
-                        ((float) resoly) * (128 +
-                            data[0][(unsigned int) (z * 81.33f)]) / 400000) *
-                    sin (z)))] = color2;
+        l[i].angle = 2.0f * M_PI * (float) i / 512.0f;
+        cosa = param * cos (l[i].angle);
+        sina = param * sin (l[i].angle);
+        l[i].x = ((float) rx / 2.0f) + cosa;
+        l[i].y = (float) ry / 2.0f + sina;
       }
-      break;
+      return;
+  }
+}
+
+static guint32
+getcouleur (int mode)
+{
+  switch (mode) {
+    case GML_RED:
+      return (230 << (ROUGE * 8)) | (120 << (VERT * 8)) | (18 << (BLEU * 8));
+    case GML_ORANGE_J:
+      return (120 << (VERT * 8)) | (252 << (ROUGE * 8)) | (18 << (BLEU * 8));
+    case GML_ORANGE_V:
+      return (160 << (VERT * 8)) | (236 << (ROUGE * 8)) | (40 << (BLEU * 8));
+    case GML_BLEUBLANC:
+      return (40 << (BLEU * 8)) | (220 << (ROUGE * 8)) | (140 << (VERT * 8));
+    case GML_VERT:
+      return (200 << (VERT * 8)) | (80 << (ROUGE * 8)) | (18 << (BLEU * 8));
+    case GML_BLEU:
+      return (250 << (BLEU * 8)) | (30 << (VERT * 8)) | (80 << (ROUGE * 8));
+    case GML_BLACK:
+      return (16 << (BLEU * 8)) | (16 << (VERT * 8)) | (16 << (ROUGE * 8));
+  }
+  return 0;
+}
+
+void
+goom_lines_set_res (GMLine * gml, int rx, int ry)
+{
+  if (gml != NULL) {
+    gml->screenX = rx;
+    gml->screenY = ry;
+
+    genline (gml->IDdest, gml->param, gml->points2, rx, ry);
+  }
+}
+
+
+static void
+goom_lines_move (GMLine * l)
+{
+  int i;
+  unsigned char *c1, *c2;
+
+  for (i = 0; i < 512; i++) {
+    l->points[i].x = (l->points2[i].x + 39.0f * l->points[i].x) / 40.0f;
+    l->points[i].y = (l->points2[i].y + 39.0f * l->points[i].y) / 40.0f;
+    l->points[i].angle =
+        (l->points2[i].angle + 39.0f * l->points[i].angle) / 40.0f;
+  }
+
+  c1 = (unsigned char *) &l->color;
+  c2 = (unsigned char *) &l->color2;
+  for (i = 0; i < 4; i++) {
+    int cc1, cc2;
+
+    cc1 = *c1;
+    cc2 = *c2;
+    *c1 = (unsigned char) ((cc1 * 63 + cc2) >> 6);
+    ++c1;
+    ++c2;
+  }
+
+  l->power += l->powinc;
+  if (l->power < 1.1f) {
+    l->power = 1.1f;
+    l->powinc = (float) (goom_irand (l->goomInfo->gRandom, 20) + 10) / 300.0f;
+  }
+  if (l->power > 17.5f) {
+    l->power = 17.5f;
+    l->powinc = -(float) (goom_irand (l->goomInfo->gRandom, 20) + 10) / 300.0f;
+  }
+
+  l->amplitude = (99.0f * l->amplitude + l->amplitudeF) / 100.0f;
+}
+
+void
+goom_lines_switch_to (GMLine * gml, int IDdest,
+    float param, float amplitude, int col)
+{
+  genline (IDdest, param, gml->points2, gml->screenX, gml->screenY);
+  gml->IDdest = IDdest;
+  gml->param = param;
+  gml->amplitudeF = amplitude;
+  gml->color2 = getcouleur (col);
+}
+
+GMLine *
+goom_lines_init (PluginInfo * goomInfo, int rx, int ry,
+    int IDsrc, float paramS, int coulS, int IDdest, float paramD, int coulD)
+{
+  GMLine *l = (GMLine *) malloc (sizeof (GMLine));
+
+  l->goomInfo = goomInfo;
+
+  l->points = (GMUnitPointer *) malloc (512 * sizeof (GMUnitPointer));
+  l->points2 = (GMUnitPointer *) malloc (512 * sizeof (GMUnitPointer));
+  l->nbPoints = 512;
+
+  l->IDdest = IDdest;
+  l->param = paramD;
+
+  l->amplitude = l->amplitudeF = 1.0f;
+
+  genline (IDsrc, paramS, l->points, rx, ry);
+  genline (IDdest, paramD, l->points2, rx, ry);
+
+  l->color = getcouleur (coulS);
+  l->color2 = getcouleur (coulD);
+
+  l->screenX = rx;
+  l->screenY = ry;
+
+  l->power = 0.0f;
+  l->powinc = 0.01f;
+
+  goom_lines_switch_to (l, IDdest, paramD, 1.0f, coulD);
+
+  return l;
+}
+
+void
+goom_lines_free (GMLine ** l)
+{
+  free ((*l)->points);
+  free (*l);
+  l = NULL;
+}
+
+void
+goom_lines_draw (PluginInfo * plug, GMLine * line, gint16 data[512], Pixel * p)
+{
+  if (line != NULL) {
+    int i, x1, y1;
+    guint32 color = line->color;
+    GMUnitPointer *pt = &(line->points[0]);
+
+    float cosa = cos (pt->angle) / 1000.0f;
+    float sina = sin (pt->angle) / 1000.0f;
+
+    lightencolor (&color, line->power);
+
+    x1 = (int) (pt->x + cosa * line->amplitude * data[0]);
+    y1 = (int) (pt->y + sina * line->amplitude * data[0]);
+
+    for (i = 1; i < 512; i++) {
+      int x2, y2;
+      GMUnitPointer *pt = &(line->points[i]);
+
+      float cosa = cos (pt->angle) / 1000.0f;
+      float sina = sin (pt->angle) / 1000.0f;
+
+      x2 = (int) (pt->x + cosa * line->amplitude * data[i]);
+      y2 = (int) (pt->y + sina * line->amplitude * data[i]);
+
+      plug->methods.draw_line (p, x1, y1, x2, y2, color, line->screenX,
+          line->screenY);
+
+      x1 = x2;
+      y1 = y2;
     }
+    goom_lines_move (line);
   }
 }
index 548f339a06abf7896060aa618c5c12f62a92a4a4..9c6df9240ce1d35b310e4a79499b68801db02850 100644 (file)
@@ -1,16 +1,81 @@
+#ifndef _LINES_H
+#define _LINES_H
+
 /*
  *  lines.h
- *  iGoom
- *
- *  Created by guillaum on Tue Aug 14 2001.
- *  Copyright (c) 2001 ios. All rights reserved.
- *
+ *  Goom
+ *  Copyright (c) 2000-2003 iOS-software. All rights reserved.
  */
-#include <glib.h>
 
-#include "graphic.h"
-#include "goom_core.h"
+#include "goom_typedefs.h"
+#include "goom_graphic.h"
+#include "goom_config.h"
+
+struct _GMUNITPOINTER
+{
+       float   x;
+       float   y;
+       float   angle;
+};
+
+/* tableau de points */
+struct _GMLINE
+{
+
+       GMUnitPointer *points;
+       GMUnitPointer *points2;
+       int     IDdest;
+       float   param;
+       float   amplitudeF;
+       float   amplitude;
+
+       int     nbPoints;
+       guint32 color;     /* pour l'instant je stocke la couleur a terme, on stockera le mode couleur et l'on animera */
+       guint32 color2;
+
+       int     screenX;
+       int     screenY;
+
+       float   power;
+       float   powinc;
+
+       PluginInfo *goomInfo;
+};
+
+/* les ID possibles */
+
+#define GML_CIRCLE 0
+/* (param = radius) */
+
+#define GML_HLINE 1
+/* (param = y) */
+
+#define GML_VLINE 2
+/* (param = x) */
+
+/* les modes couleur possible (si tu mets un autre c'est noir) */
+
+#define GML_BLEUBLANC 0
+#define GML_RED 1
+#define GML_ORANGE_V 2
+#define GML_ORANGE_J 3
+#define GML_VERT 4
+#define GML_BLEU 5
+#define GML_BLACK 6
+
+/* construit un effet de line (une ligne horitontale pour commencer) */
+GMLine *goom_lines_init (PluginInfo *goomInfo, int rx, int ry,
+                        int IDsrc, float paramS, int modeCoulSrc,
+                        int IDdest, float paramD, int modeCoulDest);
+
+void    goom_lines_switch_to (GMLine * gml, int IDdest, float param,
+                       float amplitude,
+                       int modeCoul);
+
+void    goom_lines_set_res (GMLine * gml, int rx, int ry);
 
-void goom_lines(GoomData *goomdata, gint16 data [2][512], unsigned int ID,unsigned int* p, guint32 power);
+void    goom_lines_free (GMLine ** gml);
 
+void    goom_lines_draw (PluginInfo *plugInfo, GMLine * gml, gint16 data[512], Pixel *p);
 
+#endif /* _LINES_H */
diff --git a/gst/goom/mathtools.c b/gst/goom/mathtools.c
new file mode 100644 (file)
index 0000000..4b275c6
--- /dev/null
@@ -0,0 +1,95 @@
+/*---------------------------------------------------------------------------*/
+/*
+** mathtools.c
+** Goom Project
+**
+** Created by Jeko on Sun Jul 20 2003
+ ** Copyright (c) 2003 iOS. All rights reserved.
+*/
+/*---------------------------------------------------------------------------*/
+
+#include "mathtools.h"
+
+float sin256[256] = {
+  0, 0.0245412, 0.0490677, 0.0735646, 0.0980171, 0.122411, 0.14673, 0.170962,
+      0.19509, 0.219101, 0.24298, 0.266713, 0.290285, 0.313682, 0.33689,
+      0.359895, 0.382683, 0.405241, 0.427555, 0.449611, 0.471397, 0.492898,
+      0.514103, 0.534998, 0.55557, 0.575808, 0.595699, 0.615232, 0.634393,
+      0.653173, 0.671559, 0.689541, 0.707107, 0.724247, 0.740951, 0.757209,
+      0.77301, 0.788346, 0.803208, 0.817585, 0.83147, 0.844854, 0.857729,
+      0.870087, 0.881921, 0.893224, 0.903989, 0.91421, 0.92388, 0.932993,
+      0.941544, 0.949528, 0.95694, 0.963776, 0.970031, 0.975702, 0.980785,
+      0.985278, 0.989177, 0.99248, 0.995185, 0.99729, 0.998795, 0.999699, 1,
+      0.999699, 0.998795, 0.99729, 0.995185, 0.99248, 0.989177, 0.985278,
+      0.980785, 0.975702, 0.970031, 0.963776, 0.95694, 0.949528, 0.941544,
+      0.932993, 0.92388, 0.91421, 0.903989, 0.893224, 0.881921, 0.870087,
+      0.857729, 0.844854, 0.83147, 0.817585, 0.803208, 0.788346, 0.77301,
+      0.757209, 0.740951, 0.724247, 0.707107, 0.689541, 0.671559, 0.653173,
+      0.634393, 0.615232, 0.595699, 0.575808, 0.55557, 0.534998, 0.514103,
+      0.492898, 0.471397, 0.449611, 0.427555, 0.405241, 0.382683, 0.359895,
+      0.33689, 0.313682, 0.290285, 0.266713, 0.24298, 0.219101, 0.19509,
+      0.170962, 0.14673, 0.122411, 0.0980171, 0.0735646, 0.0490677, 0.0245412,
+      1.22465e-16, -0.0245412, -0.0490677, -0.0735646, -0.0980171, -0.122411,
+      -0.14673, -0.170962, -0.19509, -0.219101, -0.24298, -0.266713, -0.290285,
+      -0.313682, -0.33689, -0.359895, -0.382683, -0.405241, -0.427555,
+      -0.449611, -0.471397, -0.492898, -0.514103, -0.534998, -0.55557,
+      -0.575808, -0.595699, -0.615232, -0.634393, -0.653173, -0.671559,
+      -0.689541, -0.707107, -0.724247, -0.740951, -0.757209, -0.77301,
+      -0.788346, -0.803208, -0.817585, -0.83147, -0.844854, -0.857729,
+      -0.870087, -0.881921, -0.893224, -0.903989, -0.91421, -0.92388, -0.932993,
+      -0.941544, -0.949528, -0.95694, -0.963776, -0.970031, -0.975702,
+      -0.980785, -0.985278, -0.989177, -0.99248, -0.995185, -0.99729, -0.998795,
+      -0.999699, -1, -0.999699, -0.998795, -0.99729, -0.995185, -0.99248,
+      -0.989177, -0.985278, -0.980785, -0.975702, -0.970031, -0.963776,
+      -0.95694, -0.949528, -0.941544, -0.932993, -0.92388, -0.91421, -0.903989,
+      -0.893224, -0.881921, -0.870087, -0.857729, -0.844854, -0.83147,
+      -0.817585, -0.803208, -0.788346, -0.77301, -0.757209, -0.740951,
+      -0.724247, -0.707107, -0.689541, -0.671559, -0.653173, -0.634393,
+      -0.615232, -0.595699, -0.575808, -0.55557, -0.534998, -0.514103,
+      -0.492898, -0.471397, -0.449611, -0.427555, -0.405241, -0.382683,
+      -0.359895, -0.33689, -0.313682, -0.290285, -0.266713, -0.24298, -0.219101,
+      -0.19509, -0.170962, -0.14673, -0.122411, -0.0980171, -0.0735646,
+      -0.0490677, -0.0245412
+};
+
+float cos256[256] = {
+  0, 0.999699, 0.998795, 0.99729, 0.995185, 0.99248, 0.989177, 0.985278,
+      0.980785, 0.975702, 0.970031, 0.963776, 0.95694, 0.949528, 0.941544,
+      0.932993, 0.92388, 0.91421, 0.903989, 0.893224, 0.881921, 0.870087,
+      0.857729, 0.844854, 0.83147, 0.817585, 0.803208, 0.788346, 0.77301,
+      0.757209, 0.740951, 0.724247, 0.707107, 0.689541, 0.671559, 0.653173,
+      0.634393, 0.615232, 0.595699, 0.575808, 0.55557, 0.534998, 0.514103,
+      0.492898, 0.471397, 0.449611, 0.427555, 0.405241, 0.382683, 0.359895,
+      0.33689, 0.313682, 0.290285, 0.266713, 0.24298, 0.219101, 0.19509,
+      0.170962, 0.14673, 0.122411, 0.0980171, 0.0735646, 0.0490677, 0.0245412,
+      6.12323e-17, -0.0245412, -0.0490677, -0.0735646, -0.0980171, -0.122411,
+      -0.14673, -0.170962, -0.19509, -0.219101, -0.24298, -0.266713, -0.290285,
+      -0.313682, -0.33689, -0.359895, -0.382683, -0.405241, -0.427555,
+      -0.449611, -0.471397, -0.492898, -0.514103, -0.534998, -0.55557,
+      -0.575808, -0.595699, -0.615232, -0.634393, -0.653173, -0.671559,
+      -0.689541, -0.707107, -0.724247, -0.740951, -0.757209, -0.77301,
+      -0.788346, -0.803208, -0.817585, -0.83147, -0.844854, -0.857729,
+      -0.870087, -0.881921, -0.893224, -0.903989, -0.91421, -0.92388, -0.932993,
+      -0.941544, -0.949528, -0.95694, -0.963776, -0.970031, -0.975702,
+      -0.980785, -0.985278, -0.989177, -0.99248, -0.995185, -0.99729, -0.998795,
+      -0.999699, -1, -0.999699, -0.998795, -0.99729, -0.995185, -0.99248,
+      -0.989177, -0.985278, -0.980785, -0.975702, -0.970031, -0.963776,
+      -0.95694, -0.949528, -0.941544, -0.932993, -0.92388, -0.91421, -0.903989,
+      -0.893224, -0.881921, -0.870087, -0.857729, -0.844854, -0.83147,
+      -0.817585, -0.803208, -0.788346, -0.77301, -0.757209, -0.740951,
+      -0.724247, -0.707107, -0.689541, -0.671559, -0.653173, -0.634393,
+      -0.615232, -0.595699, -0.575808, -0.55557, -0.534998, -0.514103,
+      -0.492898, -0.471397, -0.449611, -0.427555, -0.405241, -0.382683,
+      -0.359895, -0.33689, -0.313682, -0.290285, -0.266713, -0.24298, -0.219101,
+      -0.19509, -0.170962, -0.14673, -0.122411, -0.0980171, -0.0735646,
+      -0.0490677, -0.0245412, -1.83697e-16, 0.0245412, 0.0490677, 0.0735646,
+      0.0980171, 0.122411, 0.14673, 0.170962, 0.19509, 0.219101, 0.24298,
+      0.266713, 0.290285, 0.313682, 0.33689, 0.359895, 0.382683, 0.405241,
+      0.427555, 0.449611, 0.471397, 0.492898, 0.514103, 0.534998, 0.55557,
+      0.575808, 0.595699, 0.615232, 0.634393, 0.653173, 0.671559, 0.689541,
+      0.707107, 0.724247, 0.740951, 0.757209, 0.77301, 0.788346, 0.803208,
+      0.817585, 0.83147, 0.844854, 0.857729, 0.870087, 0.881921, 0.893224,
+      0.903989, 0.91421, 0.92388, 0.932993, 0.941544, 0.949528, 0.95694,
+      0.963776, 0.970031, 0.975702, 0.980785, 0.985278, 0.989177, 0.99248,
+      0.995185, 0.99729, 0.998795, 0.999699
+};
diff --git a/gst/goom/mathtools.h b/gst/goom/mathtools.h
new file mode 100644 (file)
index 0000000..0e2293c
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef MATHTOOLS_H
+#define MATHTOOLS_H
+
+
+#define _double2fixmagic (68719476736.0*1.5)
+/* 2^36 * 1.5,  (52-_shiftamt=36) uses limited precisicion to floor */
+#define _shiftamt 16
+/* 16.16 fixed point representation */
+
+#if BigEndian_
+#define iexp_                          0
+#define iman_                          1
+#else
+#define iexp_                          1
+#define iman_                          0
+#endif /* BigEndian_ */
+
+/* TODO: this optimization is very efficient: put it again when all works
+#ifdef HAVE_MMX
+#define F2I(dbl,i) {double d = dbl + _double2fixmagic; i = ((int*)&d)[iman_] >> _shiftamt;}
+#else*/
+#define F2I(dbl,i) i=(int)dbl;
+/*#endif*/
+
+#if 0
+#define SINCOS(f,s,c) \
+  __asm__ __volatile__ ("fsincos" : "=t" (c), "=u" (s) : "0" (f))
+#else
+#define SINCOS(f,s,c) {s=sin(f);c=cos(f);}
+#endif
+
+extern float sin256[256];
+extern float cos256[256];
+
+#endif
+
diff --git a/gst/goom/mmx.c b/gst/goom/mmx.c
new file mode 100644 (file)
index 0000000..4cee0ac
--- /dev/null
@@ -0,0 +1,256 @@
+#include "config.h"
+
+#if defined (HAVE_CPU_I386) || defined (HAVE_CPU_X86_64)
+
+#define BUFFPOINTNB 16
+#define BUFFPOINTMASK 0xffff
+#define BUFFINCR 0xff
+
+#include "mmx.h"
+#include "goom_graphic.h"
+
+#define sqrtperte 16
+// faire : a % sqrtperte <=> a & pertemask
+#define PERTEMASK 0xf
+// faire : a / sqrtperte <=> a >> PERTEDEC
+#define PERTEDEC 4
+
+int
+mmx_supported (void)
+{
+  return (mm_support () & 0x1);
+}
+
+void
+zoom_filter_mmx (int prevX, int prevY,
+    Pixel * expix1, Pixel * expix2,
+    int *brutS, int *brutD, int buffratio, int precalCoef[16][16])
+{
+  unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC;
+
+  int bufsize = prevX * prevY;
+  int loop;
+
+  __asm__ __volatile__ ("pxor %mm7,%mm7");
+
+  for (loop = 0; loop < bufsize; loop++) {
+    /*      int couleur; */
+    int px, py;
+    int pos;
+    int coeffs;
+
+    int myPos = loop << 1, myPos2 = myPos + 1;
+    int brutSmypos = brutS[myPos];
+
+    px = brutSmypos + (((brutD[myPos] -
+                brutSmypos) * buffratio) >> BUFFPOINTNB);
+    brutSmypos = brutS[myPos2];
+    py = brutSmypos + (((brutD[myPos2] -
+                brutSmypos) * buffratio) >> BUFFPOINTNB);
+
+    if ((py >= ay) || (px >= ax)) {
+      pos = coeffs = 0;
+    } else {
+      pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC));
+      // coef en modulo 15
+      coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK];
+    }
+
+    __asm__ __volatile__ ("movd %2, %%mm6 \n\t"
+        /* recuperation des deux premiers pixels dans mm0 et mm1 */
+        "movq (%3,%1,4), %%mm0 \n\t"    /* b1-v1-r1-a1-b2-v2-r2-a2 */
+        "movq %%mm0, %%mm1 \n\t"        /* b1-v1-r1-a1-b2-v2-r2-a2 */
+        /* depackage du premier pixel */
+        "punpcklbw %%mm7, %%mm0 \n\t"   /* 00-b2-00-v2-00-r2-00-a2 */
+        "movq %%mm6, %%mm5 \n\t"        /* ??-??-??-??-c4-c3-c2-c1 */
+        /* depackage du 2ieme pixel */
+        "punpckhbw %%mm7, %%mm1 \n\t"   /* 00-b1-00-v1-00-r1-00-a1 */
+        /* extraction des coefficients... */
+        "punpcklbw %%mm5, %%mm6 \n\t"   /* c4-c4-c3-c3-c2-c2-c1-c1 */
+        "movq %%mm6, %%mm4 \n\t"        /* c4-c4-c3-c3-c2-c2-c1-c1 */
+        "movq %%mm6, %%mm5 \n\t"        /* c4-c4-c3-c3-c2-c2-c1-c1 */
+        "punpcklbw %%mm5, %%mm6 \n\t"   /* c2-c2-c2-c2-c1-c1-c1-c1 */
+        "punpckhbw %%mm5, %%mm4 \n\t"   /* c4-c4-c4-c4-c3-c3-c3-c3 */
+        "movq %%mm6, %%mm3 \n\t"        /* c2-c2-c2-c2-c1-c1-c1-c1 */
+        "punpcklbw %%mm7, %%mm6 \n\t"   /* 00-c1-00-c1-00-c1-00-c1 */
+        "punpckhbw %%mm7, %%mm3 \n\t"   /* 00-c2-00-c2-00-c2-00-c2 */
+        /* multiplication des pixels par les coefficients */
+        "pmullw %%mm6, %%mm0 \n\t"      /* c1*b2-c1*v2-c1*r2-c1*a2 */
+        "pmullw %%mm3, %%mm1 \n\t"      /* c2*b1-c2*v1-c2*r1-c2*a1 */
+        "paddw %%mm1, %%mm0 \n\t"
+        /* ...extraction des 2 derniers coefficients */
+        "movq %%mm4, %%mm5 \n\t"        /* c4-c4-c4-c4-c3-c3-c3-c3 */
+        "punpcklbw %%mm7, %%mm4 \n\t"   /* 00-c3-00-c3-00-c3-00-c3 */
+        "punpckhbw %%mm7, %%mm5 \n\t"   /* 00-c4-00-c4-00-c4-00-c4 */
+        /* ajouter la longueur de ligne a esi */
+        "addl 8(%%ebp),%1 \n\t"
+        /* recuperation des 2 derniers pixels */
+        "movq (%3,%1,4), %%mm1 \n\t" "movq %%mm1, %%mm2 \n\t"
+        /* depackage des pixels */
+        "punpcklbw %%mm7, %%mm1 \n\t" "punpckhbw %%mm7, %%mm2 \n\t"
+        /* multiplication pas les coeffs */
+        "pmullw %%mm4, %%mm1 \n\t" "pmullw %%mm5, %%mm2 \n\t"
+        /* ajout des valeurs obtenues ? la valeur finale */
+        "paddw %%mm1, %%mm0 \n\t" "paddw %%mm2, %%mm0 \n\t"
+        /* division par 256 = 16+16+16+16, puis repackage du pixel final */
+        "psrlw $8, %%mm0 \n\t"
+        "packuswb %%mm7, %%mm0 \n\t" "movd %%mm0,%0 \n\t":"=g" (expix2[loop])
+        :"r" (pos), "r" (coeffs), "r" (expix1)
+
+        );
+
+    emms ();
+  }
+}
+
+#define DRAWMETHOD_PLUS_MMX(_out,_backbuf,_col) \
+{ \
+       movd_m2r(_backbuf, mm0); \
+       paddusb_m2r(_col, mm0); \
+       movd_r2m(mm0, _out); \
+}
+
+#define DRAWMETHOD DRAWMETHOD_PLUS_MMX(*p,*p,col)
+
+void
+draw_line_mmx (Pixel * data, int x1, int y1, int x2, int y2, int col,
+    int screenx, int screeny)
+{
+  int x, y, dx, dy, yy, xx;
+  Pixel *p;
+
+  if ((y1 < 0) || (y2 < 0) || (x1 < 0) || (x2 < 0) || (y1 >= screeny)
+      || (y2 >= screeny) || (x1 >= screenx) || (x2 >= screenx))
+    goto end_of_line;
+
+  dx = x2 - x1;
+  dy = y2 - y1;
+  if (x1 >= x2) {
+    int tmp;
+
+    tmp = x1;
+    x1 = x2;
+    x2 = tmp;
+    tmp = y1;
+    y1 = y2;
+    y2 = tmp;
+    dx = x2 - x1;
+    dy = y2 - y1;
+  }
+
+  /* vertical line */
+  if (dx == 0) {
+    if (y1 < y2) {
+      p = &(data[(screenx * y1) + x1]);
+      for (y = y1; y <= y2; y++) {
+        DRAWMETHOD;
+        p += screenx;
+      }
+    } else {
+      p = &(data[(screenx * y2) + x1]);
+      for (y = y2; y <= y1; y++) {
+        DRAWMETHOD;
+        p += screenx;
+      }
+    }
+    goto end_of_line;
+  }
+  /* horizontal line */
+  if (dy == 0) {
+    if (x1 < x2) {
+      p = &(data[(screenx * y1) + x1]);
+      for (x = x1; x <= x2; x++) {
+        DRAWMETHOD;
+        p++;
+      }
+      goto end_of_line;
+    } else {
+      p = &(data[(screenx * y1) + x2]);
+      for (x = x2; x <= x1; x++) {
+        DRAWMETHOD;
+        p++;
+      }
+      goto end_of_line;
+    }
+  }
+  /* 1    */
+  /*  \   */
+  /*   \  */
+  /*    2 */
+  if (y2 > y1) {
+    /* steep */
+    if (dy > dx) {
+      dx = ((dx << 16) / dy);
+      x = x1 << 16;
+      for (y = y1; y <= y2; y++) {
+        xx = x >> 16;
+        p = &(data[(screenx * y) + xx]);
+        DRAWMETHOD;
+        if (xx < (screenx - 1)) {
+          p++;
+          /* DRAWMETHOD; */
+        }
+        x += dx;
+      }
+      goto end_of_line;
+    }
+    /* shallow */
+    else {
+      dy = ((dy << 16) / dx);
+      y = y1 << 16;
+      for (x = x1; x <= x2; x++) {
+        yy = y >> 16;
+        p = &(data[(screenx * yy) + x]);
+        DRAWMETHOD;
+        if (yy < (screeny - 1)) {
+          p += screeny;
+          /* DRAWMETHOD; */
+        }
+        y += dy;
+      }
+    }
+  }
+  /*    2 */
+  /*   /  */
+  /*  /   */
+  /* 1    */
+  else {
+    /* steep */
+    if (-dy > dx) {
+      dx = ((dx << 16) / -dy);
+      x = (x1 + 1) << 16;
+      for (y = y1; y >= y2; y--) {
+        xx = x >> 16;
+        p = &(data[(screenx * y) + xx]);
+        DRAWMETHOD;
+        if (xx < (screenx - 1)) {
+          p--;
+          /* DRAWMETHOD; */
+        }
+        x += dx;
+      }
+      goto end_of_line;
+    }
+    /* shallow */
+    else {
+      dy = ((dy << 16) / dx);
+      y = y1 << 16;
+      for (x = x1; x <= x2; x++) {
+        yy = y >> 16;
+        p = &(data[(screenx * yy) + x]);
+        DRAWMETHOD;
+        if (yy < (screeny - 1)) {
+          p += screeny;
+          /* DRAWMETHOD; */
+        }
+        y += dy;
+      }
+      goto end_of_line;
+    }
+  }
+end_of_line:
+  emms ();
+  /* __asm__ __volatile__ ("emms"); */
+}
+
+#endif /* HAVE_CPU_I386 || HAVE_CPU_X86_64 */
diff --git a/gst/goom/mmx.h b/gst/goom/mmx.h
new file mode 100644 (file)
index 0000000..3fae26b
--- /dev/null
@@ -0,0 +1,729 @@
+/*     mmx.h
+
+       MultiMedia eXtensions GCC interface library for IA32.
+
+       To use this library, simply include this header file
+       and compile with GCC.  You MUST have inlining enabled
+       in order for mmx_ok() to work; this can be done by
+       simply using -O on the GCC command line.
+
+       Compiling with -DMMX_TRACE will cause detailed trace
+       output to be sent to stderr for each mmx operation.
+       This adds lots of code, and obviously slows execution to
+       a crawl, but can be very useful for debugging.
+
+       THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+       LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+       AND FITNESS FOR ANY PARTICULAR PURPOSE.
+
+       1997-99 by H. Dietz and R. Fisher
+
+ Notes:
+       It appears that the latest gas has the pand problem fixed, therefore
+         I'll undefine BROKEN_PAND by default.
+*/
+
+#ifndef _MMX_H
+#define _MMX_H
+
+#include "goom_graphic.h"
+
+/*     Warning:  at this writing, the version of GAS packaged
+       with most Linux distributions does not handle the
+       parallel AND operation mnemonic correctly.  If the
+       symbol BROKEN_PAND is defined, a slower alternative
+       coding will be used.  If execution of mmxtest results
+       in an illegal instruction fault, define this symbol.
+*/
+#undef BROKEN_PAND
+
+
+/*     The type of an value that fits in an MMX register
+       (note that long long constant values MUST be suffixed
+        by LL and unsigned long long values by ULL, lest
+        they be truncated by the compiler)
+*/
+typedef        union {
+       long long               q;      /* Quadword (64-bit) value */
+       unsigned long long      uq;     /* Unsigned Quadword */
+       int                     d[2];   /* 2 Doubleword (32-bit) values */
+       unsigned int            ud[2];  /* 2 Unsigned Doubleword */
+       short                   w[4];   /* 4 Word (16-bit) values */
+       unsigned short          uw[4];  /* 4 Unsigned Word */
+       char                    b[8];   /* 8 Byte (8-bit) values */
+       unsigned char           ub[8];  /* 8 Unsigned Byte */
+       float                   s[2];   /* Single-precision (32-bit) value */
+} __attribute__ ((aligned (8))) mmx_t; /* On an 8-byte (64-bit) boundary */
+
+
+
+/*     Function to test if multimedia instructions are supported...
+*/
+static int
+mm_support(void)
+{
+       /* Returns 1 if MMX instructions are supported,
+          3 if Cyrix MMX and Extended MMX instructions are supported
+          5 if AMD MMX and 3DNow! instructions are supported
+                13 if AMD Extended MMX, &3dNow supported
+          0 if hardware does not support any of these
+       */
+       register int rval = 0;
+
+       __asm__ __volatile__ (
+               /* See if CPUID instruction is supported ... */
+               /* ... Get copies of EFLAGS into eax and ecx */
+    "pushl %%ebx\n\t"
+               "pushf\n\t"
+               "popl %%eax\n\t"
+               "movl %%eax, %%ecx\n\t"
+
+               /* ... Toggle the ID bit in one copy and store */
+               /*     to the EFLAGS reg */
+               "xorl $0x200000, %%eax\n\t"
+               "push %%eax\n\t"
+               "popf\n\t"
+
+               /* ... Get the (hopefully modified) EFLAGS */
+               "pushf\n\t"
+               "popl %%eax\n\t"
+
+               /* ... Compare and test result */
+               "xorl %%eax, %%ecx\n\t"
+               "testl $0x200000, %%ecx\n\t"
+               "jz NotSupported1\n\t"          /* CPUID not supported */
+
+
+               /* Get standard CPUID information, and
+                      go to a specific vendor section */
+               "movl $0, %%eax\n\t"
+               "cpuid\n\t"
+
+               /* Check for Intel */
+               "cmpl $0x756e6547, %%ebx\n\t"
+               "jne TryAMD\n\t"
+               "cmpl $0x49656e69, %%edx\n\t"
+               "jne TryAMD\n\t"
+               "cmpl $0x6c65746e, %%ecx\n"
+               "jne TryAMD\n\t"
+               "jmp Intel\n\t"
+
+               /* Check for AMD */
+               "\nTryAMD:\n\t"
+               "cmpl $0x68747541, %%ebx\n\t"
+               "jne TryCyrix\n\t"
+               "cmpl $0x69746e65, %%edx\n\t"
+               "jne TryCyrix\n\t"
+               "cmpl $0x444d4163, %%ecx\n"
+               "jne TryCyrix\n\t"
+               "jmp AMD\n\t"
+
+               /* Check for Cyrix */
+               "\nTryCyrix:\n\t"
+               "cmpl $0x69727943, %%ebx\n\t"
+               "jne NotSupported2\n\t"
+               "cmpl $0x736e4978, %%edx\n\t"
+               "jne NotSupported3\n\t"
+               "cmpl $0x64616574, %%ecx\n\t"
+               "jne NotSupported4\n\t"
+               /* Drop through to Cyrix... */
+
+
+               /* Cyrix Section */
+               /* See if extended CPUID level 80000001 is supported */
+               /* The value of CPUID/80000001 for the 6x86MX is undefined
+                  according to the Cyrix CPU Detection Guide (Preliminary
+                  Rev. 1.01 table 1), so we'll check the value of eax for
+                  CPUID/0 to see if standard CPUID level 2 is supported.
+                  According to the table, the only CPU which supports level
+                  2 is also the only one which supports extended CPUID levels.
+               */
+               "cmpl $0x2, %%eax\n\t"
+               "jne MMXtest\n\t"       /* Use standard CPUID instead */
+
+               /* Extended CPUID supported (in theory), so get extended
+                  features */
+               "movl $0x80000001, %%eax\n\t"
+               "cpuid\n\t"
+               "testl $0x00800000, %%eax\n\t"  /* Test for MMX */
+               "jz NotSupported5\n\t"          /* MMX not supported */
+               "testl $0x01000000, %%eax\n\t"  /* Test for Ext'd MMX */
+               "jnz EMMXSupported\n\t"
+               "movl $1, %0\n\n\t"             /* MMX Supported */
+               "jmp Return\n\n"
+               "EMMXSupported:\n\t"
+               "movl $3, %0\n\n\t"             /* EMMX and MMX Supported */
+               "jmp Return\n\t"
+
+
+               /* AMD Section */
+               "AMD:\n\t"
+
+               /* See if extended CPUID is supported */
+               "movl $0x80000000, %%eax\n\t"
+               "cpuid\n\t"
+               "cmpl $0x80000000, %%eax\n\t"
+               "jl MMXtest\n\t"        /* Use standard CPUID instead */
+
+               /* Extended CPUID supported, so get extended features */
+               "movl $0x80000001, %%eax\n\t"
+               "cpuid\n\t"
+               "testl $0x00800000, %%edx\n\t"  /* Test for MMX */
+               "jz NotSupported6\n\t"          /* MMX not supported */
+               "testl $0x80000000, %%edx\n\t"  /* Test for 3DNow! */
+               "jnz ThreeDNowSupported\n\t"
+               "movl $1, %0\n\n\t"             /* MMX Supported */
+               "jmp Return\n\n"
+               "ThreeDNowSupported:\n\t"
+               "testl $0x40000000, %%edx\n\t" /* Test AMD Extended MMX */
+               "jnz AMDXMMXSupported\n\t"
+               "movl $5, %0\n\n\t"             /* 3DNow! and MMX Supported */
+               "jmp Return\n\t"
+               "AMDXMMXSupported:\n\t"
+               "movl $13, %0\n\n\t"            /* XMMX, 3DNow! and MMX Supported */
+               "jmp Return\n\t"
+
+
+               /* Intel Section */
+               "Intel:\n\t"
+
+               /* Check for MMX */
+               "MMXtest:\n\t"
+               "movl $1, %%eax\n\t"
+               "cpuid\n\t"
+               "testl $0x00800000, %%edx\n\t"  /* Test for MMX */
+               "jz NotSupported7\n\t"          /* MMX Not supported */
+               "movl $1, %0\n\n\t"             /* MMX Supported */
+               "jmp Return\n\t"
+
+               /* Nothing supported */
+               "\nNotSupported1:\n\t"
+               "#movl $101, %0\n\n\t"
+               "\nNotSupported2:\n\t"
+               "#movl $102, %0\n\n\t"
+               "\nNotSupported3:\n\t"
+               "#movl $103, %0\n\n\t"
+               "\nNotSupported4:\n\t"
+               "#movl $104, %0\n\n\t"
+               "\nNotSupported5:\n\t"
+               "#movl $105, %0\n\n\t"
+               "\nNotSupported6:\n\t"
+               "#movl $106, %0\n\n\t"
+               "\nNotSupported7:\n\t"
+               "#movl $107, %0\n\n\t"
+               "movl $0, %0\n\n\t"
+
+               "Return:\n\t"
+    "popl %%ebx\n\t"
+               : "=X" (rval)
+               : /* no input */
+               : "eax", "ecx", "edx"
+       );
+
+       /* Return */
+       return(rval);
+}
+
+/*     Function to test if mmx instructions are supported...
+*/
+static inline int
+mmx_ok(void)
+{
+       /* Returns 1 if MMX instructions are supported, 0 otherwise */
+       return ( mm_support() & 0x1 );
+}
+
+int mmx_supported (void);
+int xmmx_supported (void);
+
+
+/* MMX optimized implementations */
+void draw_line_mmx (Pixel *data, int x1, int y1, int x2, int y2, int col, int screenx, int screeny);
+void draw_line_xmmx (Pixel *data, int x1, int y1, int x2, int y2, int col, int screenx, int screeny);
+void zoom_filter_mmx (int prevX, int prevY, Pixel *expix1, Pixel *expix2,
+                     int *brutS, int *brutD, int buffratio, int precalCoef[16][16]);
+void zoom_filter_xmmx (int prevX, int prevY, Pixel *expix1, Pixel *expix2,
+                       int *lbruS, int *lbruD, int buffratio, int precalCoef[16][16]);
+
+
+/*     Helper functions for the instruction macros that follow...
+       (note that memory-to-register, m2r, instructions are nearly
+        as efficient as register-to-register, r2r, instructions;
+        however, memory-to-memory instructions are really simulated
+        as a convenience, and are only 1/3 as efficient)
+*/
+#ifdef MMX_TRACE
+
+/*     Include the stuff for printing a trace to stderr...
+*/
+
+#include <stdio.h>
+
+#define        mmx_i2r(op, imm, reg) \
+       { \
+               mmx_t mmx_trace; \
+               mmx_trace.uq = (imm); \
+               printf(#op "_i2r(" #imm "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               printf(#reg "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ (#op " %0, %%" #reg \
+                                     : /* nothing */ \
+                                     : "X" (imm)); \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               printf(#reg "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#define        mmx_m2r(op, mem, reg) \
+       { \
+               mmx_t mmx_trace; \
+               mmx_trace = (mem); \
+               printf(#op "_m2r(" #mem "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               printf(#reg "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ (#op " %0, %%" #reg \
+                                     : /* nothing */ \
+                                     : "m" (mem)); \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               printf(#reg "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#define        mmx_r2m(op, reg, mem) \
+       { \
+               mmx_t mmx_trace; \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               printf(#op "_r2m(" #reg "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               mmx_trace = (mem); \
+               printf(#mem "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ (#op " %%" #reg ", %0" \
+                                     : "=m" (mem) \
+                                     : /* nothing */ ); \
+               mmx_trace = (mem); \
+               printf(#mem "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#define        mmx_r2r(op, regs, regd) \
+       { \
+               mmx_t mmx_trace; \
+               __asm__ __volatile__ ("movq %%" #regs ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               printf(#op "_r2r(" #regs "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ ("movq %%" #regd ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               printf(#regd "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ (#op " %" #regs ", %" #regd); \
+               __asm__ __volatile__ ("movq %%" #regd ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               printf(#regd "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#define        mmx_m2m(op, mems, memd) \
+       { \
+               mmx_t mmx_trace; \
+               mmx_trace = (mems); \
+               printf(#op "_m2m(" #mems "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               mmx_trace = (memd); \
+               printf(#memd "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+                                     #op " %1, %%mm0\n\t" \
+                                     "movq %%mm0, %0" \
+                                     : "=m" (memd) \
+                                     : "m" (mems)); \
+               mmx_trace = (memd); \
+               printf(#memd "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#else
+
+/*     These macros are a lot simpler without the tracing...
+*/
+
+#define        mmx_i2r(op, imm, reg) \
+       __asm__ __volatile__ (#op " %0, %%" #reg \
+                             : /* nothing */ \
+                             : "X" (imm) )
+
+#define        mmx_m2r(op, mem, reg) \
+       __asm__ __volatile__ (#op " %0, %%" #reg \
+                             : /* nothing */ \
+                             : "m" (mem))
+
+#define        mmx_r2m(op, reg, mem) \
+       __asm__ __volatile__ (#op " %%" #reg ", %0" \
+                             : "=m" (mem) \
+                             : /* nothing */ )
+
+#define        mmx_r2r(op, regs, regd) \
+       __asm__ __volatile__ (#op " %" #regs ", %" #regd)
+
+#define        mmx_m2m(op, mems, memd) \
+       __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+                             #op " %1, %%mm0\n\t" \
+                             "movq %%mm0, %0" \
+                             : "=m" (memd) \
+                             : "m" (mems))
+
+#endif
+
+
+/*     1x64 MOVe Quadword
+       (this is both a load and a store...
+        in fact, it is the only way to store)
+*/
+#define        movq_m2r(var, reg)      mmx_m2r(movq, var, reg)
+#define        movq_r2m(reg, var)      mmx_r2m(movq, reg, var)
+#define        movq_r2r(regs, regd)    mmx_r2r(movq, regs, regd)
+#define        movq(vars, vard) \
+       __asm__ __volatile__ ("movq %1, %%mm0\n\t" \
+                             "movq %%mm0, %0" \
+                             : "=X" (vard) \
+                             : "X" (vars))
+
+
+/*     1x32 MOVe Doubleword
+       (like movq, this is both load and store...
+        but is most useful for moving things between
+        mmx registers and ordinary registers)
+*/
+#define        movd_m2r(var, reg)      mmx_m2r(movd, var, reg)
+#define        movd_r2m(reg, var)      mmx_r2m(movd, reg, var)
+#define        movd_r2r(regs, regd)    mmx_r2r(movd, regs, regd)
+#define        movd(vars, vard) \
+       __asm__ __volatile__ ("movd %1, %%mm0\n\t" \
+                             "movd %%mm0, %0" \
+                             : "=X" (vard) \
+                             : "X" (vars))
+
+
+/*     2x32, 4x16, and 8x8 Parallel ADDs
+*/
+#define        paddd_m2r(var, reg)     mmx_m2r(paddd, var, reg)
+#define        paddd_r2r(regs, regd)   mmx_r2r(paddd, regs, regd)
+#define        paddd(vars, vard)       mmx_m2m(paddd, vars, vard)
+
+#define        paddw_m2r(var, reg)     mmx_m2r(paddw, var, reg)
+#define        paddw_r2r(regs, regd)   mmx_r2r(paddw, regs, regd)
+#define        paddw(vars, vard)       mmx_m2m(paddw, vars, vard)
+
+#define        paddb_m2r(var, reg)     mmx_m2r(paddb, var, reg)
+#define        paddb_r2r(regs, regd)   mmx_r2r(paddb, regs, regd)
+#define        paddb(vars, vard)       mmx_m2m(paddb, vars, vard)
+
+
+/*     4x16 and 8x8 Parallel ADDs using Saturation arithmetic
+*/
+#define        paddsw_m2r(var, reg)    mmx_m2r(paddsw, var, reg)
+#define        paddsw_r2r(regs, regd)  mmx_r2r(paddsw, regs, regd)
+#define        paddsw(vars, vard)      mmx_m2m(paddsw, vars, vard)
+
+#define        paddsb_m2r(var, reg)    mmx_m2r(paddsb, var, reg)
+#define        paddsb_r2r(regs, regd)  mmx_r2r(paddsb, regs, regd)
+#define        paddsb(vars, vard)      mmx_m2m(paddsb, vars, vard)
+
+
+/*     4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic
+*/
+#define        paddusw_m2r(var, reg)   mmx_m2r(paddusw, var, reg)
+#define        paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd)
+#define        paddusw(vars, vard)     mmx_m2m(paddusw, vars, vard)
+
+#define        paddusb_m2r(var, reg)   mmx_m2r(paddusb, var, reg)
+#define        paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd)
+#define        paddusb(vars, vard)     mmx_m2m(paddusb, vars, vard)
+
+
+/*     2x32, 4x16, and 8x8 Parallel SUBs
+*/
+#define        psubd_m2r(var, reg)     mmx_m2r(psubd, var, reg)
+#define        psubd_r2r(regs, regd)   mmx_r2r(psubd, regs, regd)
+#define        psubd(vars, vard)       mmx_m2m(psubd, vars, vard)
+
+#define        psubw_m2r(var, reg)     mmx_m2r(psubw, var, reg)
+#define        psubw_r2r(regs, regd)   mmx_r2r(psubw, regs, regd)
+#define        psubw(vars, vard)       mmx_m2m(psubw, vars, vard)
+
+#define        psubb_m2r(var, reg)     mmx_m2r(psubb, var, reg)
+#define        psubb_r2r(regs, regd)   mmx_r2r(psubb, regs, regd)
+#define        psubb(vars, vard)       mmx_m2m(psubb, vars, vard)
+
+
+/*     4x16 and 8x8 Parallel SUBs using Saturation arithmetic
+*/
+#define        psubsw_m2r(var, reg)    mmx_m2r(psubsw, var, reg)
+#define        psubsw_r2r(regs, regd)  mmx_r2r(psubsw, regs, regd)
+#define        psubsw(vars, vard)      mmx_m2m(psubsw, vars, vard)
+
+#define        psubsb_m2r(var, reg)    mmx_m2r(psubsb, var, reg)
+#define        psubsb_r2r(regs, regd)  mmx_r2r(psubsb, regs, regd)
+#define        psubsb(vars, vard)      mmx_m2m(psubsb, vars, vard)
+
+
+/*     4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic
+*/
+#define        psubusw_m2r(var, reg)   mmx_m2r(psubusw, var, reg)
+#define        psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd)
+#define        psubusw(vars, vard)     mmx_m2m(psubusw, vars, vard)
+
+#define        psubusb_m2r(var, reg)   mmx_m2r(psubusb, var, reg)
+#define        psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd)
+#define        psubusb(vars, vard)     mmx_m2m(psubusb, vars, vard)
+
+
+/*     4x16 Parallel MULs giving Low 4x16 portions of results
+*/
+#define        pmullw_m2r(var, reg)    mmx_m2r(pmullw, var, reg)
+#define        pmullw_r2r(regs, regd)  mmx_r2r(pmullw, regs, regd)
+#define        pmullw(vars, vard)      mmx_m2m(pmullw, vars, vard)
+
+
+/*     4x16 Parallel MULs giving High 4x16 portions of results
+*/
+#define        pmulhw_m2r(var, reg)    mmx_m2r(pmulhw, var, reg)
+#define        pmulhw_r2r(regs, regd)  mmx_r2r(pmulhw, regs, regd)
+#define        pmulhw(vars, vard)      mmx_m2m(pmulhw, vars, vard)
+
+
+/*     4x16->2x32 Parallel Mul-ADD
+       (muls like pmullw, then adds adjacent 16-bit fields
+        in the multiply result to make the final 2x32 result)
+*/
+#define        pmaddwd_m2r(var, reg)   mmx_m2r(pmaddwd, var, reg)
+#define        pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd)
+#define        pmaddwd(vars, vard)     mmx_m2m(pmaddwd, vars, vard)
+
+
+/*     1x64 bitwise AND
+*/
+#ifdef BROKEN_PAND
+#define        pand_m2r(var, reg) \
+       { \
+               mmx_m2r(pandn, (mmx_t) -1LL, reg); \
+               mmx_m2r(pandn, var, reg); \
+       }
+#define        pand_r2r(regs, regd) \
+       { \
+               mmx_m2r(pandn, (mmx_t) -1LL, regd); \
+               mmx_r2r(pandn, regs, regd) \
+       }
+#define        pand(vars, vard) \
+       { \
+               movq_m2r(vard, mm0); \
+               mmx_m2r(pandn, (mmx_t) -1LL, mm0); \
+               mmx_m2r(pandn, vars, mm0); \
+               movq_r2m(mm0, vard); \
+       }
+#else
+#define        pand_m2r(var, reg)      mmx_m2r(pand, var, reg)
+#define        pand_r2r(regs, regd)    mmx_r2r(pand, regs, regd)
+#define        pand(vars, vard)        mmx_m2m(pand, vars, vard)
+#endif
+
+
+/*     1x64 bitwise AND with Not the destination
+*/
+#define        pandn_m2r(var, reg)     mmx_m2r(pandn, var, reg)
+#define        pandn_r2r(regs, regd)   mmx_r2r(pandn, regs, regd)
+#define        pandn(vars, vard)       mmx_m2m(pandn, vars, vard)
+
+
+/*     1x64 bitwise OR
+*/
+#define        por_m2r(var, reg)       mmx_m2r(por, var, reg)
+#define        por_r2r(regs, regd)     mmx_r2r(por, regs, regd)
+#define        por(vars, vard) mmx_m2m(por, vars, vard)
+
+
+/*     1x64 bitwise eXclusive OR
+*/
+#define        pxor_m2r(var, reg)      mmx_m2r(pxor, var, reg)
+#define        pxor_r2r(regs, regd)    mmx_r2r(pxor, regs, regd)
+#define        pxor(vars, vard)        mmx_m2m(pxor, vars, vard)
+
+
+/*     2x32, 4x16, and 8x8 Parallel CoMPare for EQuality
+       (resulting fields are either 0 or -1)
+*/
+#define        pcmpeqd_m2r(var, reg)   mmx_m2r(pcmpeqd, var, reg)
+#define        pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd)
+#define        pcmpeqd(vars, vard)     mmx_m2m(pcmpeqd, vars, vard)
+
+#define        pcmpeqw_m2r(var, reg)   mmx_m2r(pcmpeqw, var, reg)
+#define        pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd)
+#define        pcmpeqw(vars, vard)     mmx_m2m(pcmpeqw, vars, vard)
+
+#define        pcmpeqb_m2r(var, reg)   mmx_m2r(pcmpeqb, var, reg)
+#define        pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd)
+#define        pcmpeqb(vars, vard)     mmx_m2m(pcmpeqb, vars, vard)
+
+
+/*     2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than
+       (resulting fields are either 0 or -1)
+*/
+#define        pcmpgtd_m2r(var, reg)   mmx_m2r(pcmpgtd, var, reg)
+#define        pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd)
+#define        pcmpgtd(vars, vard)     mmx_m2m(pcmpgtd, vars, vard)
+
+#define        pcmpgtw_m2r(var, reg)   mmx_m2r(pcmpgtw, var, reg)
+#define        pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd)
+#define        pcmpgtw(vars, vard)     mmx_m2m(pcmpgtw, vars, vard)
+
+#define        pcmpgtb_m2r(var, reg)   mmx_m2r(pcmpgtb, var, reg)
+#define        pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd)
+#define        pcmpgtb(vars, vard)     mmx_m2m(pcmpgtb, vars, vard)
+
+
+/*     1x64, 2x32, and 4x16 Parallel Shift Left Logical
+*/
+#define        psllq_i2r(imm, reg)     mmx_i2r(psllq, imm, reg)
+#define        psllq_m2r(var, reg)     mmx_m2r(psllq, var, reg)
+#define        psllq_r2r(regs, regd)   mmx_r2r(psllq, regs, regd)
+#define        psllq(vars, vard)       mmx_m2m(psllq, vars, vard)
+
+#define        pslld_i2r(imm, reg)     mmx_i2r(pslld, imm, reg)
+#define        pslld_m2r(var, reg)     mmx_m2r(pslld, var, reg)
+#define        pslld_r2r(regs, regd)   mmx_r2r(pslld, regs, regd)
+#define        pslld(vars, vard)       mmx_m2m(pslld, vars, vard)
+
+#define        psllw_i2r(imm, reg)     mmx_i2r(psllw, imm, reg)
+#define        psllw_m2r(var, reg)     mmx_m2r(psllw, var, reg)
+#define        psllw_r2r(regs, regd)   mmx_r2r(psllw, regs, regd)
+#define        psllw(vars, vard)       mmx_m2m(psllw, vars, vard)
+
+
+/*     1x64, 2x32, and 4x16 Parallel Shift Right Logical
+*/
+#define        psrlq_i2r(imm, reg)     mmx_i2r(psrlq, imm, reg)
+#define        psrlq_m2r(var, reg)     mmx_m2r(psrlq, var, reg)
+#define        psrlq_r2r(regs, regd)   mmx_r2r(psrlq, regs, regd)
+#define        psrlq(vars, vard)       mmx_m2m(psrlq, vars, vard)
+
+#define        psrld_i2r(imm, reg)     mmx_i2r(psrld, imm, reg)
+#define        psrld_m2r(var, reg)     mmx_m2r(psrld, var, reg)
+#define        psrld_r2r(regs, regd)   mmx_r2r(psrld, regs, regd)
+#define        psrld(vars, vard)       mmx_m2m(psrld, vars, vard)
+
+#define        psrlw_i2r(imm, reg)     mmx_i2r(psrlw, imm, reg)
+#define        psrlw_m2r(var, reg)     mmx_m2r(psrlw, var, reg)
+#define        psrlw_r2r(regs, regd)   mmx_r2r(psrlw, regs, regd)
+#define        psrlw(vars, vard)       mmx_m2m(psrlw, vars, vard)
+
+
+/*     2x32 and 4x16 Parallel Shift Right Arithmetic
+*/
+#define        psrad_i2r(imm, reg)     mmx_i2r(psrad, imm, reg)
+#define        psrad_m2r(var, reg)     mmx_m2r(psrad, var, reg)
+#define        psrad_r2r(regs, regd)   mmx_r2r(psrad, regs, regd)
+#define        psrad(vars, vard)       mmx_m2m(psrad, vars, vard)
+
+#define        psraw_i2r(imm, reg)     mmx_i2r(psraw, imm, reg)
+#define        psraw_m2r(var, reg)     mmx_m2r(psraw, var, reg)
+#define        psraw_r2r(regs, regd)   mmx_r2r(psraw, regs, regd)
+#define        psraw(vars, vard)       mmx_m2m(psraw, vars, vard)
+
+
+/*     2x32->4x16 and 4x16->8x8 PACK and Signed Saturate
+       (packs source and dest fields into dest in that order)
+*/
+#define        packssdw_m2r(var, reg)  mmx_m2r(packssdw, var, reg)
+#define        packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd)
+#define        packssdw(vars, vard)    mmx_m2m(packssdw, vars, vard)
+
+#define        packsswb_m2r(var, reg)  mmx_m2r(packsswb, var, reg)
+#define        packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd)
+#define        packsswb(vars, vard)    mmx_m2m(packsswb, vars, vard)
+
+
+/*     4x16->8x8 PACK and Unsigned Saturate
+       (packs source and dest fields into dest in that order)
+*/
+#define        packuswb_m2r(var, reg)  mmx_m2r(packuswb, var, reg)
+#define        packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd)
+#define        packuswb(vars, vard)    mmx_m2m(packuswb, vars, vard)
+
+
+/*     2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low
+       (interleaves low half of dest with low half of source
+        as padding in each result field)
+*/
+#define        punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg)
+#define        punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd)
+#define        punpckldq(vars, vard)   mmx_m2m(punpckldq, vars, vard)
+
+#define        punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg)
+#define        punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd)
+#define        punpcklwd(vars, vard)   mmx_m2m(punpcklwd, vars, vard)
+
+#define        punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg)
+#define        punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd)
+#define        punpcklbw(vars, vard)   mmx_m2m(punpcklbw, vars, vard)
+
+
+/*     2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High
+       (interleaves high half of dest with high half of source
+        as padding in each result field)
+*/
+#define        punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg)
+#define        punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd)
+#define        punpckhdq(vars, vard)   mmx_m2m(punpckhdq, vars, vard)
+
+#define        punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg)
+#define        punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd)
+#define        punpckhwd(vars, vard)   mmx_m2m(punpckhwd, vars, vard)
+
+#define        punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg)
+#define        punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd)
+#define        punpckhbw(vars, vard)   mmx_m2m(punpckhbw, vars, vard)
+
+
+/*     Empty MMx State
+       (used to clean-up when going from mmx to float use
+        of the registers that are shared by both; note that
+        there is no float-to-mmx operation needed, because
+        only the float tag word info is corruptible)
+*/
+#ifdef MMX_TRACE
+
+#define        emms() \
+       { \
+               printf("emms()\n"); \
+               __asm__ __volatile__ ("emms" \
+                        "st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)"); \
+       }
+
+#else
+
+#define        emms() __asm__ __volatile__ ("emms"::: \
+                      "st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)")
+
+#endif
+
+#endif
+
diff --git a/gst/goom/motif_goom1.h b/gst/goom/motif_goom1.h
new file mode 100644 (file)
index 0000000..b4a9f3f
--- /dev/null
@@ -0,0 +1,1026 @@
+static Motif CONV_MOTIF1 = {
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,14,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,13,9,9,7,2,2,9,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,11,
+       11,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,12,7,4,0,0,0,2,0,0,3,14,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,12,10,9,9,4,1,0,
+       1,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,10,3,0,0,0,1,1,3,5,0,0,1,14,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,14,6,3,1,1,4,9,1,
+       1,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       10,3,0,0,2,7,13,14,14,14,7,0,0,2,14,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,12,1,9,15,15,15,15,3,
+       0,13,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,12,4,
+       0,0,2,10,15,15,15,15,15,15,1,0,0,10,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,9,0,2,14,15,15,15,7,
+       0,9,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,14,6,0,0,
+       2,9,15,15,15,15,15,15,15,13,0,0,3,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,11,0,0,10,15,15,15,9,
+       0,9,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,13,3,0,1,5,
+       5,4,4,4,6,12,15,15,15,13,0,0,7,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,14,0,0,5,15,15,15,10,
+       0,7,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,11,1,0,3,3,1,
+       0,0,0,0,0,0,5,13,15,12,0,0,13,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,13,14,15,
+       15,15,15,15,15,15,15,15,14,0,0,1,15,15,15,12,
+       0,3,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,10,1,2,4,0,0,1,
+       9,12,12,12,9,3,0,2,14,5,0,7,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,14,7,4,4,1,1,12,
+       15,15,15,15,15,15,15,15,14,1,0,0,12,15,15,15,
+       1,0,12,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,10,0,3,2,0,0,3,12,
+       15,15,15,15,15,14,2,1,13,2,0,12,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,14,3,0,0,0,0,0,2,
+       13,15,15,15,15,15,15,15,14,1,0,0,8,15,15,15,
+       1,0,9,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,12,2,1,0,0,0,9,14,15,
+       15,15,15,15,15,14,1,1,11,0,3,14,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,7,4,11,12,10,1,0,
+       3,12,15,15,15,15,15,15,13,1,1,0,4,15,15,15,
+       2,0,10,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,14,2,1,0,0,3,12,15,15,15,
+       15,15,15,15,15,11,0,5,9,1,12,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,5,1,13,15,15,12,1,
+       0,1,9,15,15,15,15,15,14,2,5,0,1,14,15,15,
+       2,0,7,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,14,3,0,0,0,7,14,15,15,15,15,
+       15,15,15,15,15,9,0,8,7,4,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,7,0,7,8,11,15,13,
+       2,0,0,3,10,15,15,15,15,5,11,0,0,11,15,15,
+       6,0,2,14,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,6,0,0,0,8,15,15,15,15,15,15,
+       15,15,15,15,15,6,0,4,0,6,15,15,15,15,15,15,
+       14,9,14,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,11,0,3,3,0,8,15,
+       14,5,0,0,0,4,12,15,15,5,13,2,0,6,15,15,
+       12,0,0,11,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,10,0,0,0,8,15,15,15,15,15,15,15,
+       15,15,15,15,10,1,7,6,4,13,15,15,15,15,13,11,
+       6,0,8,11,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,1,1,11,2,0,5,
+       14,15,8,0,0,0,0,7,15,5,14,6,0,2,15,15,
+       15,3,0,5,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,13,1,0,0,7,15,15,15,15,15,15,15,15,
+       15,15,15,15,7,9,15,15,15,15,15,15,12,6,2,1,
+       1,1,8,6,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,4,0,6,12,1,0,
+       3,13,15,11,2,0,0,0,8,4,14,10,0,0,13,15,
+       15,7,0,1,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,5,0,0,5,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,13,15,15,15,15,14,8,3,1,2,7,11,
+       5,4,5,6,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,8,0,1,14,11,0,
+       0,1,9,15,14,5,0,0,2,4,14,13,0,0,10,15,
+       15,12,0,0,12,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,10,0,0,1,14,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,14,13,7,2,0,5,9,15,15,15,
+       5,3,6,9,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,13,0,0,9,15,12,
+       2,0,0,4,13,14,4,0,3,2,12,15,1,0,5,15,
+       15,14,1,0,8,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,2,0,0,9,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,11,6,1,0,2,3,10,15,15,15,15,7,
+       1,2,4,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,5,0,3,14,15,
+       9,2,0,0,1,6,12,13,13,1,9,12,0,0,2,14,
+       15,15,4,0,4,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,10,0,0,2,14,15,15,15,15,15,15,15,15,15,15,
+       13,9,6,0,1,2,9,10,15,15,15,15,14,7,1,0,
+       6,2,4,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,11,0,0,9,15,
+       4,4,11,6,1,0,0,1,1,0,10,4,0,0,0,12,
+       15,15,9,0,1,14,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,3,0,0,8,15,15,15,15,15,15,15,13,12,4,4,
+       1,1,3,10,12,15,15,15,15,15,9,2,1,0,1,6,
+       6,0,10,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,4,0,3,14,
+       4,3,15,15,14,9,7,9,1,0,0,0,0,1,0,7,
+       15,15,13,0,0,9,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       13,0,0,1,14,15,15,15,15,15,12,9,1,0,1,4,
+       7,15,15,15,15,15,15,14,8,2,0,0,0,2,13,9,
+       0,4,14,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,11,0,0,9,
+       3,0,8,14,15,15,15,15,10,5,4,4,7,4,0,3,
+       15,15,15,4,0,3,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       5,0,0,5,15,15,15,15,14,8,7,8,10,12,14,15,
+       15,15,15,15,15,15,11,1,0,0,0,5,11,15,13,1,
+       1,13,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,3,0,4,
+       4,0,0,2,6,10,15,15,15,15,15,15,15,10,0,0,
+       12,15,15,9,0,0,12,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       1,0,0,10,15,15,15,15,15,13,14,15,15,15,15,15,
+       15,15,15,15,14,7,1,0,0,3,12,15,15,15,6,0,
+       7,15,15,15,12,10,9,10,12,14,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,9,0,0,
+       8,3,1,4,1,0,1,12,15,15,15,15,15,14,2,0,
+       6,15,15,15,2,0,6,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       0,0,1,14,15,15,15,15,14,5,15,15,15,15,15,15,
+       15,15,15,7,2,0,0,1,8,15,15,15,15,12,0,2,
+       14,15,12,4,0,0,0,0,0,1,5,10,14,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,14,0,0,
+       5,4,1,14,15,10,7,13,15,15,15,15,15,15,8,0,
+       1,14,15,15,7,0,1,14,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,13,
+       0,0,4,15,15,15,15,15,13,2,13,15,15,15,15,15,
+       12,7,0,0,0,0,5,12,15,15,15,15,14,3,0,9,
+       11,1,0,0,1,1,0,1,0,0,0,0,2,12,15,15,
+       15,15,15,15,15,15,15,14,15,15,15,15,15,15,2,0,
+       5,2,1,14,15,14,13,15,15,15,15,15,15,15,12,0,
+       0,10,15,15,13,0,0,9,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,12,
+       0,0,4,15,15,15,15,15,12,0,12,15,15,15,12,6,
+       0,0,0,0,6,14,15,15,15,15,15,15,7,0,0,12,
+       1,0,0,2,2,1,1,7,12,8,3,0,0,1,13,15,
+       15,15,15,15,15,8,4,8,12,15,15,15,15,15,8,0,
+       4,2,0,14,15,11,9,15,15,15,15,15,15,15,15,3,
+       0,5,15,15,15,5,0,3,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,12,
+       0,0,4,15,15,15,15,15,12,0,12,15,13,3,1,0,
+       0,0,5,12,15,15,15,15,15,15,15,12,0,0,7,7,
+       0,0,0,0,0,0,0,1,12,15,15,12,3,0,5,15,
+       15,15,15,14,5,0,0,0,0,2,2,3,7,14,9,8,
+       14,2,1,14,15,2,12,13,15,15,15,15,15,15,15,9,
+       0,0,13,15,15,10,0,0,12,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,13,
+       0,0,5,15,15,15,15,15,12,0,11,10,1,0,0,1,
+       5,14,15,15,15,15,15,15,15,15,15,6,0,2,7,0,
+       0,0,0,1,2,7,4,0,3,14,15,15,14,2,0,12,
+       15,15,15,9,0,1,2,1,0,0,0,0,0,1,3,7,
+       15,3,0,14,15,4,12,15,15,15,15,15,15,15,15,14,
+       1,0,8,15,15,14,1,0,8,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,13,
+       0,0,4,15,15,15,15,15,12,0,2,0,0,1,10,15,
+       15,15,15,15,15,15,15,15,15,15,12,0,0,6,0,0,
+       0,1,10,14,15,15,11,1,0,9,15,15,15,8,0,9,
+       15,15,12,4,8,14,15,8,1,0,0,0,0,0,1,9,
+       15,2,0,13,15,1,9,15,15,15,15,15,15,15,15,15,
+       6,0,1,14,15,14,1,0,3,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,14,
+       1,0,1,14,15,15,15,15,12,1,3,7,9,13,15,15,
+       15,15,15,15,15,15,15,15,15,15,3,0,2,3,0,4,
+       0,8,15,15,15,15,15,13,1,2,14,15,15,10,0,6,
+       15,14,2,6,15,15,15,1,3,7,3,0,0,0,0,1,
+       11,1,0,11,12,0,12,15,15,15,15,15,15,15,15,15,
+       11,0,0,9,15,15,4,0,0,12,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       6,0,0,9,15,15,15,15,15,12,14,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,11,0,0,3,0,8,14,
+       2,5,15,15,15,15,15,15,5,0,8,15,15,12,0,4,
+       15,5,2,14,15,15,10,0,13,15,13,2,4,5,5,0,
+       9,1,0,10,9,1,14,15,15,15,15,15,15,15,15,15,
+       13,0,0,3,15,15,9,0,0,8,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       12,0,0,3,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,3,0,1,1,5,14,15,
+       11,0,12,15,15,15,15,15,14,1,1,14,15,12,0,4,
+       10,0,9,15,15,11,1,8,15,15,8,1,14,15,14,2,
+       5,0,0,10,6,2,15,15,15,15,15,15,15,15,15,15,
+       15,3,0,0,12,15,13,0,0,2,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,3,0,0,10,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,10,0,0,1,0,11,15,15,
+       15,2,6,15,15,15,15,15,15,6,0,9,15,13,0,6,
+       3,0,13,15,14,2,6,15,15,13,1,8,15,15,15,4,
+       3,1,0,10,7,2,15,15,15,15,15,15,15,15,15,15,
+       15,9,0,0,6,15,15,3,0,0,13,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,9,0,0,2,14,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,11,10,2,0,3,0,3,15,15,15,
+       15,8,1,14,15,15,15,15,15,13,0,2,15,9,1,10,
+       0,3,15,15,6,2,14,15,14,3,1,14,15,15,15,2,
+       4,0,0,12,5,3,15,15,15,15,15,15,15,15,15,15,
+       15,14,1,0,1,14,15,5,0,0,12,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,4,0,0,6,15,15,15,15,15,15,15,15,14,12,
+       12,9,5,4,4,3,0,0,0,0,4,0,8,15,15,15,
+       15,13,1,10,15,15,15,15,15,15,2,0,11,3,5,10,
+       0,7,15,9,1,11,15,15,8,0,6,15,15,15,10,0,
+       3,0,0,13,3,6,15,15,15,15,15,15,15,15,15,15,
+       15,15,6,0,0,12,15,5,0,0,7,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,13,1,0,0,8,14,15,15,13,6,4,4,1,0,
+       0,0,0,0,0,0,2,0,0,4,3,0,12,15,15,15,
+       15,15,5,3,15,15,15,15,14,8,0,0,1,1,12,9,
+       0,9,10,0,6,15,15,15,2,2,14,15,15,13,2,0,
+       4,0,1,13,0,10,15,15,15,15,15,15,15,15,15,15,
+       15,15,13,1,0,10,15,10,0,0,5,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,9,0,0,0,3,2,2,1,0,0,0,1,4,
+       4,5,10,12,12,12,11,0,0,11,4,0,12,15,15,15,
+       15,15,12,0,7,13,15,15,5,0,0,0,1,6,15,9,
+       0,3,0,0,1,6,14,10,0,12,15,15,11,2,0,2,
+       3,0,3,12,1,11,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,3,0,6,8,7,0,0,5,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,9,1,0,0,0,2,6,10,12,12,14,15,
+       15,15,15,15,11,5,4,0,2,14,4,0,12,15,15,15,
+       15,15,15,4,0,3,13,6,0,0,0,1,2,14,15,12,
+       0,0,0,0,0,0,2,2,6,15,14,8,0,0,0,7,
+       4,0,4,12,0,12,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,0,0,0,0,0,0,1,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,12,2,0,0,0,1,6,11,15,15,15,
+       15,15,15,15,2,1,0,0,9,15,6,0,7,15,15,15,
+       15,15,15,13,2,0,0,0,0,0,0,1,12,15,15,15,
+       4,0,0,0,0,0,0,6,13,6,1,0,0,4,13,15,
+       6,0,6,12,0,12,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,14,5,0,0,0,0,0,5,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,14,5,0,0,0,0,0,2,4,5,
+       7,3,6,3,0,2,0,2,15,15,11,0,0,9,15,15,
+       15,15,15,15,11,0,0,0,0,0,2,11,15,15,15,15,
+       12,1,0,0,1,4,6,10,2,0,0,0,7,14,15,15,
+       9,0,9,9,0,12,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,13,9,8,9,7,13,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,12,6,1,0,0,0,0,0,
+       0,0,0,2,8,0,0,9,15,15,14,4,0,0,3,10,
+       14,15,15,15,15,13,3,0,0,4,14,15,15,15,15,15,
+       15,11,2,0,0,1,1,0,0,0,1,11,15,15,15,15,
+       9,0,10,5,3,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,14,12,10,5,4,6,
+       2,4,10,14,8,0,1,14,15,15,15,14,5,0,0,0,
+       1,2,4,4,4,3,1,2,9,14,15,15,15,15,15,15,
+       15,15,15,11,11,13,10,9,9,11,15,15,15,15,15,15,
+       10,0,8,2,4,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       2,7,15,14,1,0,6,15,15,15,15,15,15,10,6,4,
+       2,2,4,4,4,3,9,14,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       11,0,3,1,4,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,11,
+       1,10,15,9,0,0,13,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       11,0,11,11,11,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,2,
+       5,15,14,2,0,5,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       14,1,13,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,10,1,
+       13,15,11,0,0,12,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,5,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,8,1,
+       15,15,5,0,3,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,10,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,12,2,3,
+       15,14,1,0,7,15,15,15,15,15,13,15,15,15,15,14,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,13,12,12,11,9,4,7,14,15,
+       14,13,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,12,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,14,3,0,10,
+       15,9,0,0,8,7,4,2,2,1,0,3,4,3,4,9,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,14,13,11,7,4,2,0,0,0,0,0,0,1,12,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,14,13,11,7,4,2,2,13,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,12,0,3,11,
+       7,1,0,0,0,0,0,1,4,9,11,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,14,12,11,9,7,4,
+       3,1,0,0,0,0,0,0,0,0,0,2,11,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,13,11,8,
+       4,3,1,0,0,0,0,3,8,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,14,11,3,0,0,0,
+       0,0,0,2,6,9,12,14,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,13,9,6,3,1,0,0,0,0,0,0,
+       0,0,0,0,1,4,7,11,12,12,12,14,15,15,15,15,
+       15,15,15,15,15,15,15,14,12,11,7,4,2,0,0,0,
+       0,0,0,1,5,10,13,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,14,12,7,3,1,0,0,0,2,5,
+       2,0,2,14,15,15,15,15,15,15,15,15,15,14,13,12,
+       11,9,6,4,2,0,0,0,0,0,0,0,0,1,2,4,
+       5,9,11,13,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,14,12,11,7,4,3,1,0,0,0,0,0,0,0,1,
+       4,5,10,14,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,13,10,5,1,0,0,0,1,0,0,2,13,14,
+       1,0,8,15,15,14,12,11,9,8,4,3,2,1,0,0,
+       0,0,0,0,1,3,2,3,5,9,10,12,13,14,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,13,11,10,6,4,
+       3,1,0,0,0,0,0,0,0,0,1,4,7,11,13,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,11,4,0,0,0,1,4,9,13,13,1,0,0,1,7,
+       0,0,7,8,5,2,0,0,0,0,0,0,1,2,3,4,
+       5,9,10,12,14,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,14,11,8,4,3,1,0,0,0,0,0,
+       0,0,0,0,1,4,5,9,12,13,15,15,15,15,15,15,
+       15,15,14,12,9,8,8,7,4,2,5,4,5,5,12,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,14,10,5,
+       1,0,1,3,6,11,14,15,15,15,15,13,12,8,3,2,
+       0,0,1,1,3,3,4,5,8,10,12,13,14,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,13,
+       11,9,6,4,2,1,0,0,0,0,0,0,0,1,2,4,
+       6,10,11,13,15,15,15,15,15,15,15,15,13,11,9,7,
+       4,2,1,0,0,0,0,2,4,7,12,14,14,14,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,10,5,1,1,3,
+       8,12,14,15,15,15,15,15,15,15,15,15,15,15,15,9,
+       3,11,14,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,8,6,9,9,9,9,9,8,5,4,4,3,1,0,
+       0,0,0,0,1,2,3,2,4,5,9,11,12,14,15,15,
+       15,15,15,15,15,15,15,14,12,9,5,2,0,0,0,0,
+       0,1,2,4,7,10,14,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,14,9,4,1,3,9,13,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,13,
+       11,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,13,3,1,1,1,1,1,1,1,0,0,0,0,2,3,
+       5,8,10,12,14,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,12,5,2,0,0,0,1,3,4,7,10,
+       12,13,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,13,11,13,13,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,14,12,12,12,13,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,8,1,0,1,4,7,11,13,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,13,7,8,11,14,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
+       };
diff --git a/gst/goom/motif_goom2.h b/gst/goom/motif_goom2.h
new file mode 100644 (file)
index 0000000..4bde2a3
--- /dev/null
@@ -0,0 +1,1026 @@
+static Motif CONV_MOTIF2 = {
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,12,5,14,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,12,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,10,1,14,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,10,0,12,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,6,0,12,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,7,0,8,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,13,2,0,10,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,6,0,2,14,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,5,0,0,10,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,9,0,0,12,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,14,9,0,0,1,14,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,8,0,0,8,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,14,8,3,0,0,0,9,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,11,0,0,2,14,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,13,9,5,3,4,1,0,0,0,0,7,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,14,4,0,0,4,11,13,13,15,15,14,12,10,8,5,
+       6,4,1,0,0,0,0,0,0,0,0,0,0,14,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,12,1,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,9,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       13,9,10,13,14,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,3,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,2,5,6,0,0,0,0,12,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       5,0,0,0,3,10,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,14,9,2,1,0,0,0,1,4,6,6,1,
+       0,0,0,8,13,15,15,15,12,1,0,2,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,14,
+       2,0,0,0,0,0,4,12,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,3,0,0,10,15,15,15,10,
+       0,0,4,15,15,15,15,15,15,2,0,6,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,5,
+       3,11,5,0,0,0,0,0,4,11,14,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,7,0,0,13,15,15,15,11,
+       0,0,7,15,15,15,15,15,15,1,0,9,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,9,0,
+       13,15,15,12,5,0,0,0,0,0,1,8,14,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,7,0,1,14,15,15,15,11,
+       0,0,7,15,15,15,15,15,14,0,0,9,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,11,1,10,
+       15,15,15,15,15,11,5,0,0,0,0,0,1,6,13,15,
+       15,15,15,15,14,8,11,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,6,0,2,15,15,15,15,11,
+       0,0,6,15,15,15,15,15,13,0,0,11,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,11,1,6,15,
+       15,15,15,15,15,15,15,14,5,0,0,0,0,0,0,6,
+       14,15,15,15,6,0,4,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,7,0,5,15,15,15,15,11,
+       0,0,5,15,15,15,15,15,12,0,0,12,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,13,2,1,13,15,
+       15,15,15,15,15,15,15,15,15,12,2,0,0,0,0,0,
+       1,6,11,7,0,0,4,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,7,0,7,15,15,15,15,11,
+       0,0,6,15,15,15,15,15,12,0,0,12,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,5,0,7,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,11,5,0,0,0,
+       0,0,0,0,0,1,11,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,7,0,10,15,15,15,15,11,
+       0,0,6,15,15,15,15,15,12,0,0,12,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,10,0,4,14,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,13,7,0,
+       0,0,0,0,0,1,6,12,14,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,7,0,10,15,15,15,15,11,
+       0,0,7,15,15,15,15,15,12,0,0,12,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,13,1,1,12,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,13,
+       5,0,0,0,0,0,0,0,3,10,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,7,0,10,15,15,15,15,11,
+       0,0,7,15,15,15,15,15,11,0,0,13,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,14,4,0,8,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       13,0,0,0,1,0,0,0,0,1,13,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,7,0,10,15,15,15,15,11,
+       0,0,8,15,15,15,15,15,8,0,2,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,9,0,4,14,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,14,
+       4,0,0,5,13,12,6,2,0,2,13,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,7,0,10,15,15,15,15,11,
+       0,0,7,15,15,15,15,15,4,0,4,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,13,1,1,13,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,11,
+       0,0,1,13,15,15,15,14,9,13,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,5,0,6,15,15,15,15,11,
+       0,0,8,15,15,15,15,15,2,0,8,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,5,0,9,15,15,15,15,15,15,
+       15,15,15,15,15,15,14,11,15,15,15,15,15,15,15,9,
+       0,0,10,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,4,0,4,15,15,15,15,11,
+       0,0,7,15,15,15,15,13,0,0,11,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,10,0,3,14,15,15,15,15,15,15,
+       15,15,15,15,15,14,3,0,13,15,15,15,15,15,15,14,
+       9,11,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,4,0,4,15,15,15,15,11,
+       0,0,8,15,15,15,15,12,0,0,12,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,14,2,1,12,15,15,15,15,15,15,15,
+       15,15,15,15,14,3,0,0,9,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,6,0,3,15,15,15,15,13,
+       1,0,8,15,15,15,15,12,0,0,12,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,9,0,5,15,15,15,15,15,15,15,15,
+       15,15,15,14,4,0,0,0,10,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,8,0,2,15,15,15,15,15,
+       3,0,13,15,15,15,15,12,0,0,12,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,13,2,1,12,15,15,15,15,15,15,15,15,
+       15,15,15,7,0,0,0,0,8,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,10,0,1,14,15,15,15,15,
+       11,5,15,15,15,15,15,12,0,0,11,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,6,0,7,15,15,15,15,15,15,15,15,15,
+       15,15,8,0,0,0,0,0,0,9,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,12,0,0,12,15,15,15,15,
+       15,14,15,15,15,15,15,10,0,0,12,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,13,1,2,14,15,15,15,15,15,15,15,15,15,
+       15,10,0,0,0,6,6,0,0,0,5,12,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,12,12,
+       15,15,15,15,15,15,15,15,13,0,0,11,15,15,15,15,
+       15,15,15,15,15,15,15,9,0,1,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,7,0,8,15,15,15,15,15,15,15,15,15,15,
+       15,9,0,0,4,15,15,8,0,0,0,1,5,13,15,15,
+       15,15,15,15,15,15,15,15,15,15,12,8,7,6,5,3,
+       3,3,4,12,15,15,15,15,15,15,15,15,15,7,0,6,
+       15,15,15,15,15,15,15,15,14,1,0,10,15,15,15,15,
+       15,15,15,15,15,15,15,6,0,3,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,13,1,0,13,15,15,15,15,15,15,15,15,15,15,
+       15,14,7,8,13,15,15,15,11,2,0,0,0,0,5,11,
+       15,15,15,15,15,15,15,15,13,3,0,0,0,0,0,0,
+       0,0,0,5,15,15,15,15,15,15,15,15,12,1,0,0,
+       3,11,15,15,15,15,15,15,13,1,0,10,15,15,15,15,
+       15,15,15,15,15,15,15,3,0,5,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,9,0,5,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,14,8,1,0,0,0,0,
+       4,12,15,15,15,15,15,15,4,0,0,0,0,0,0,0,
+       0,0,0,2,15,15,15,15,15,15,15,14,4,0,0,0,
+       0,0,9,15,15,15,15,15,14,1,0,10,15,15,15,15,
+       15,15,15,15,15,15,15,2,0,9,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,14,4,0,11,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,14,8,2,0,0,
+       0,0,4,10,14,15,15,15,4,0,0,0,0,0,0,0,
+       0,0,0,3,15,15,15,15,15,15,15,6,0,0,0,2,
+       3,0,0,8,15,15,15,15,14,1,0,10,15,15,15,15,
+       15,15,15,15,15,15,15,1,0,9,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       14,5,0,4,14,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,14,9,3,
+       0,0,0,0,2,5,10,15,5,0,1,11,11,12,13,15,
+       11,0,0,7,15,15,15,15,15,15,8,0,0,0,1,12,
+       14,6,0,0,7,14,15,15,14,1,0,9,15,15,15,15,
+       15,15,15,15,15,15,15,2,0,10,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       9,0,1,13,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,14,
+       10,2,0,0,0,0,1,14,4,0,1,14,15,15,15,15,
+       9,0,0,9,15,15,15,15,15,9,0,0,0,0,9,15,
+       15,15,7,0,0,6,14,15,15,3,0,6,15,15,15,15,
+       15,15,15,15,15,15,15,1,0,9,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,9,
+       0,0,1,10,14,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,13,1,0,0,0,1,14,3,0,0,14,15,15,15,15,
+       5,0,0,11,15,15,15,15,13,1,0,0,0,6,15,15,
+       15,15,15,8,0,0,2,10,15,6,0,3,15,15,15,15,
+       15,15,15,15,15,15,15,2,0,10,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,13,1,
+       0,0,0,0,3,9,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,6,1,0,0,0,8,15,1,0,0,14,15,15,15,15,
+       4,0,0,13,15,15,15,14,4,0,0,0,3,14,15,15,
+       15,15,15,15,5,0,0,1,14,9,0,1,14,15,15,15,
+       15,15,15,15,15,15,15,1,0,9,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,13,1,
+       0,0,0,0,0,0,4,12,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       9,0,0,0,0,7,15,15,1,0,0,14,15,15,15,14,
+       2,0,1,14,15,15,15,12,0,0,0,3,13,15,15,15,
+       15,15,15,9,0,0,0,1,14,12,0,0,12,15,15,15,
+       15,15,15,15,15,15,14,1,0,10,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,12,
+       3,0,0,0,0,0,0,1,8,14,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,9,
+       0,0,0,0,7,15,15,15,1,0,0,14,15,15,15,13,
+       0,0,1,15,15,15,15,12,0,0,0,6,14,15,15,15,
+       15,15,12,0,0,0,0,3,14,12,0,0,12,15,15,15,
+       15,15,15,15,15,15,12,0,0,12,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,13,3,0,0,0,0,0,0,1,6,13,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,12,0,
+       0,0,0,3,15,15,15,12,0,0,0,14,15,15,15,11,
+       0,0,3,15,15,15,15,15,12,7,0,0,4,14,15,15,
+       15,11,1,0,0,0,4,13,15,12,0,0,12,15,15,15,
+       15,15,15,15,15,15,10,0,1,14,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,7,0,0,0,0,0,0,0,3,8,12,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,4,0,
+       0,0,1,13,15,15,15,6,0,0,0,14,15,15,15,8,
+       0,0,7,15,15,15,15,15,15,15,8,1,0,2,13,15,
+       14,2,0,0,0,4,14,15,15,13,1,0,10,15,15,15,
+       15,15,15,15,15,15,9,0,2,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,11,6,2,0,0,0,0,0,0,0,1,
+       10,15,15,15,15,15,15,15,15,15,15,15,15,8,0,0,
+       0,0,10,15,15,15,15,4,0,0,1,15,15,15,15,4,
+       0,0,8,15,15,15,15,15,15,15,15,10,1,0,1,8,
+       2,0,0,0,5,15,15,15,15,15,2,0,6,15,15,15,
+       15,15,15,15,15,15,9,0,1,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,9,1,0,0,0,0,0,0,
+       0,1,7,13,14,15,15,15,15,15,15,15,9,0,0,0,
+       0,6,15,15,15,15,15,4,0,0,4,15,15,15,14,1,
+       0,0,9,15,15,15,15,15,15,15,15,15,12,2,0,0,
+       0,0,0,4,14,15,15,15,15,15,4,0,4,15,15,15,
+       15,15,15,15,15,15,7,0,0,14,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,14,11,6,2,0,0,0,
+       0,0,0,0,1,9,12,15,15,15,15,14,3,0,0,0,
+       4,15,15,15,15,15,15,4,0,0,3,6,4,4,2,0,
+       0,0,13,15,15,15,15,15,15,15,15,15,15,12,1,0,
+       0,0,3,14,15,15,15,15,15,15,4,0,4,15,15,15,
+       15,15,15,15,15,15,5,0,0,12,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,8,2,0,
+       0,0,0,0,0,0,0,1,9,15,15,5,0,0,0,0,
+       12,15,15,15,15,15,15,4,0,0,0,0,0,0,0,0,
+       0,3,15,15,15,15,15,15,15,15,15,15,15,14,4,0,
+       0,1,12,15,15,15,15,15,15,15,6,0,1,14,15,15,
+       15,15,15,15,15,15,5,0,0,13,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,12,
+       7,1,0,0,0,0,0,0,0,5,7,0,0,0,0,10,
+       15,15,15,15,15,15,15,7,0,0,0,0,0,0,0,0,
+       1,10,15,15,15,15,15,15,15,15,15,15,15,14,3,0,
+       3,12,15,15,15,15,15,15,15,15,12,0,0,12,15,15,
+       15,15,15,15,15,15,5,0,0,1,1,4,11,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,11,6,1,0,0,0,0,0,0,0,0,0,7,15,
+       15,15,15,15,15,15,15,14,7,4,4,4,5,9,12,13,
+       14,15,15,15,15,15,15,15,15,15,15,15,15,15,11,9,
+       14,15,15,14,12,11,11,11,10,9,7,0,0,5,13,15,
+       15,15,15,15,15,12,1,0,0,0,0,0,0,10,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,14,7,1,0,0,0,0,0,3,14,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,13,2,0,0,0,0,0,0,0,0,0,0,0,8,
+       15,15,15,15,15,11,0,0,0,0,0,0,0,9,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,13,5,0,0,0,0,12,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,8,0,0,0,0,0,0,0,0,0,0,0,0,5,
+       15,15,15,15,15,15,10,5,6,7,7,7,9,14,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,8,3,2,2,2,2,5,14,15,
+       15,15,15,15,15,15,15,15,15,10,3,0,6,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,13,3,1,0,1,0,1,1,2,4,4,3,9,14,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,12,4,0,1,6,7,7,4,1,3,13,
+       15,15,15,15,15,15,15,15,15,15,14,10,13,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,11,11,15,15,15,15,
+       15,15,15,14,14,14,14,14,14,14,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,14,2,0,4,13,15,15,15,15,10,0,12,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,14,13,14,12,12,12,12,12,12,12,
+       12,14,15,15,15,15,15,15,15,15,4,14,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,7,1,5,14,15,15,15,15,15,12,1,11,
+       15,15,15,13,12,13,15,15,14,11,13,15,15,15,15,15,
+       15,15,15,11,6,3,1,1,1,0,0,0,0,0,0,0,
+       0,1,4,7,11,14,15,15,15,14,4,15,13,10,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,14,7,4,5,
+       12,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,13,1,1,14,15,15,14,10,12,15,11,1,12,
+       15,15,11,1,0,4,15,15,6,0,2,14,15,15,15,15,
+       15,15,14,8,6,3,3,2,2,1,0,0,0,0,0,0,
+       0,0,0,0,0,3,11,15,15,11,8,15,12,6,15,9,
+       8,15,15,15,15,15,15,15,15,15,15,15,10,4,4,1,
+       4,15,15,15,15,11,6,2,8,14,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,0,4,15,15,15,11,2,10,15,9,1,13,
+       15,13,1,7,6,2,14,14,1,2,1,14,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,13,12,12,12,12,12,12,
+       11,11,11,10,9,10,12,15,15,6,7,15,9,4,15,4,
+       1,14,15,15,15,15,15,15,15,15,15,15,2,11,15,4,
+       4,15,15,15,15,3,9,4,0,9,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,0,4,15,15,15,5,0,6,6,1,9,15,
+       15,4,1,13,10,1,13,9,2,7,1,14,14,14,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,3,5,15,3,5,14,1,
+       0,12,13,9,14,15,15,15,15,15,15,15,2,2,4,1,
+       6,15,15,15,14,1,5,6,0,9,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,0,4,15,15,15,12,4,2,2,10,15,15,
+       11,0,6,15,12,0,10,7,9,10,1,14,7,14,15,15,
+       15,15,15,15,15,15,13,12,11,11,10,9,9,10,11,13,
+       15,15,15,15,15,15,15,15,15,1,9,15,2,7,14,1,
+       0,10,7,0,8,15,15,15,15,15,15,15,11,4,4,4,
+       13,15,15,15,15,10,2,2,4,14,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,0,4,15,15,15,15,15,15,15,15,15,15,
+       4,2,14,15,15,1,9,5,14,9,1,14,8,14,15,15,
+       15,15,15,15,15,10,3,0,1,0,0,0,0,0,0,5,
+       15,15,15,15,15,15,15,15,15,1,9,14,1,8,14,1,
+       0,11,13,6,11,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,14,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,0,4,15,15,15,15,15,15,15,15,15,11,
+       0,6,15,15,15,1,5,3,13,10,0,6,8,15,15,15,
+       15,15,15,15,15,15,13,12,12,11,10,9,9,10,11,13,
+       15,15,15,15,15,15,15,15,15,1,9,12,1,11,15,4,
+       1,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       14,10,4,2,12,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,12,1,3,14,15,15,15,15,15,15,15,15,4,
+       3,14,15,15,15,5,1,8,15,14,5,2,9,15,15,15,
+       15,15,15,15,15,15,15,15,15,11,9,13,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,1,9,12,1,12,15,13,
+       11,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       10,2,9,2,3,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,14,4,0,5,14,15,15,15,15,15,15,11,0,
+       6,15,15,15,15,15,14,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,8,1,0,3,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,1,9,15,11,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       7,1,12,6,1,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,11,1,0,3,8,9,9,10,11,9,5,4,
+       13,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,12,9,13,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,5,11,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       10,3,4,1,5,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,12,2,0,0,0,0,0,0,1,8,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,14,12,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,13,8,8,10,9,10,11,14,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+       15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
+       };
diff --git a/gst/goom/plugin_info.c b/gst/goom/plugin_info.c
new file mode 100644 (file)
index 0000000..2aeeb4f
--- /dev/null
@@ -0,0 +1,222 @@
+#include "config.h"
+
+#include "goom_plugin_info.h"
+#include "goom_fx.h"
+#include "default_scripts.h"
+#include "drawmethods.h"
+#include <math.h>
+#include <stdio.h>
+
+
+#if defined (HAVE_CPU_PPC64) || defined (HAVE_CPU_PPC)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include "ppc_zoom_ultimate.h"
+#include "ppc_drawings.h"
+#endif /* HAVE_CPU_PPC64 || HAVE_CPU_PPC */
+
+
+#ifdef HAVE_CPU_I386
+#include "mmx.h"
+#endif /* HAVE_CPU_I386 */
+
+#include <liboil/liboil.h>
+#include <liboil/liboilfunction.h>
+#define VERBOSE 1
+
+static void
+setOptimizedMethods (PluginInfo * p)
+{
+
+  unsigned int cpuFlavour = oil_cpu_get_flags ();
+
+  /* set default methods */
+  p->methods.draw_line = draw_line;
+  p->methods.zoom_filter = zoom_filter_c;
+/*    p->methods.create_output_with_brightness = create_output_with_brightness;*/
+
+#ifdef HAVE_CPU_I386
+  printf ("have an x86\n");
+  if (cpuFlavour & OIL_IMPL_FLAG_MMXEXT) {
+#ifdef VERBOSE
+    printf ("Extented MMX detected. Using the fastest methods !\n");
+#endif
+    p->methods.draw_line = draw_line_mmx;
+    p->methods.zoom_filter = zoom_filter_xmmx;
+  } else if (cpuFlavour & OIL_IMPL_FLAG_MMX) {
+#ifdef VERBOSE
+    printf ("MMX detected. Using fast methods !\n");
+#endif
+    p->methods.draw_line = draw_line_mmx;
+    p->methods.zoom_filter = zoom_filter_mmx;
+  }
+#ifdef VERBOSE
+  else
+    printf ("Too bad ! No SIMD optimization available for your CPU.\n");
+#endif
+#endif /* HAVE_CPU_I386 */
+
+#ifdef HAVE_CPU_PPC64
+  if ((cpuFlavour & CPU_OPTION_64_BITS) != 0) {
+/*            p->methods.create_output_with_brightness = ppc_brightness_G5;        */
+    p->methods.zoom_filter = ppc_zoom_generic;
+  }
+#endif /* HAVE_CPU_PPC64 */
+
+#ifdef HAVE_CPU_PPC
+  if ((cpuFlavour & OIL_IMPL_FLAG_ALTIVEC) != 0) {
+/*            p->methods.create_output_with_brightness = ppc_brightness_G4;        */
+    p->methods.zoom_filter = ppc_zoom_G4;
+  } else {
+/*            p->methods.create_output_with_brightness = ppc_brightness_generic;*/
+    p->methods.zoom_filter = ppc_zoom_generic;
+  }
+#endif /* HAVE_CPU_PPC */
+
+}
+
+void
+plugin_info_init (PluginInfo * pp, int nbVisuals)
+{
+
+  PluginInfo p;
+  int i;
+
+  p.sound.speedvar = p.sound.accelvar = p.sound.totalgoom = 0;
+  p.sound.prov_max = 0;
+  p.sound.goom_limit = 1;
+  p.sound.allTimesMax = 1;
+
+  p.sound.volume_p = secure_f_feedback ("Sound Volume");
+  p.sound.accel_p = secure_f_feedback ("Sound Acceleration");
+  p.sound.speed_p = secure_f_feedback ("Sound Speed");
+  p.sound.goom_limit_p = secure_f_feedback ("Goom Limit");
+  p.sound.last_goom_p = secure_f_feedback ("Goom Detection");
+  p.sound.last_biggoom_p = secure_f_feedback ("Big Goom Detection");
+  p.sound.goom_power_p = secure_f_feedback ("Goom Power");
+
+  p.sound.biggoom_speed_limit_p = secure_i_param ("Big Goom Speed Limit");
+  IVAL (p.sound.biggoom_speed_limit_p) = 10;
+  IMIN (p.sound.biggoom_speed_limit_p) = 0;
+  IMAX (p.sound.biggoom_speed_limit_p) = 100;
+  ISTEP (p.sound.biggoom_speed_limit_p) = 1;
+
+  p.sound.biggoom_factor_p = secure_i_param ("Big Goom Factor");
+  IVAL (p.sound.biggoom_factor_p) = 10;
+  IMIN (p.sound.biggoom_factor_p) = 0;
+  IMAX (p.sound.biggoom_factor_p) = 100;
+  ISTEP (p.sound.biggoom_factor_p) = 1;
+
+  p.sound.params = plugin_parameters ("Sound", 11);
+
+  p.nbParams = 0;
+  p.nbVisuals = nbVisuals;
+  p.visuals = (VisualFX **) malloc (sizeof (VisualFX *) * nbVisuals);
+
+  *pp = p;
+  pp->sound.params.params[0] = &pp->sound.biggoom_speed_limit_p;
+  pp->sound.params.params[1] = &pp->sound.biggoom_factor_p;
+  pp->sound.params.params[2] = 0;
+  pp->sound.params.params[3] = &pp->sound.volume_p;
+  pp->sound.params.params[4] = &pp->sound.accel_p;
+  pp->sound.params.params[5] = &pp->sound.speed_p;
+  pp->sound.params.params[6] = 0;
+  pp->sound.params.params[7] = &pp->sound.goom_limit_p;
+  pp->sound.params.params[8] = &pp->sound.goom_power_p;
+  pp->sound.params.params[9] = &pp->sound.last_goom_p;
+  pp->sound.params.params[10] = &pp->sound.last_biggoom_p;
+
+  pp->statesNumber = 8;
+  pp->statesRangeMax = 510;
+  {
+    GoomState states[8] = {
+      {1, 0, 0, 1, 4, 0, 100}
+      ,
+      {1, 0, 0, 0, 1, 101, 140}
+      ,
+      {1, 0, 0, 1, 2, 141, 200}
+      ,
+      {0, 1, 0, 1, 2, 201, 260}
+      ,
+      {0, 1, 0, 1, 0, 261, 330}
+      ,
+      {0, 1, 1, 1, 4, 331, 400}
+      ,
+      {0, 0, 1, 0, 5, 401, 450}
+      ,
+      {0, 0, 1, 1, 1, 451, 510}
+    };
+    for (i = 0; i < 8; ++i)
+      pp->states[i] = states[i];
+  }
+  pp->curGState = &(pp->states[6]);
+
+  /* datas for the update loop */
+  pp->update.lockvar = 0;
+  pp->update.goomvar = 0;
+  pp->update.loopvar = 0;
+  pp->update.stop_lines = 0;
+  pp->update.ifs_incr = 1;      /* dessiner l'ifs (0 = non: > = increment) */
+  pp->update.decay_ifs = 0;     /* disparition de l'ifs */
+  pp->update.recay_ifs = 0;     /* dedisparition de l'ifs */
+  pp->update.cyclesSinceLastChange = 0;
+  pp->update.drawLinesDuration = 80;
+  pp->update.lineMode = pp->update.drawLinesDuration;
+
+  pp->update.switchMultAmount = (29.0f / 30.0f);
+  pp->update.switchIncrAmount = 0x7f;
+  pp->update.switchMult = 1.0f;
+  pp->update.switchIncr = pp->update.switchIncrAmount;
+
+  pp->update.stateSelectionRnd = 0;
+  pp->update.stateSelectionBlocker = 0;
+  pp->update.previousZoomSpeed = 128;
+  pp->update.timeOfTitleDisplay = 0;
+
+  pp->update_message.affiche = 0;
+
+  {
+    ZoomFilterData zfd = {
+      127, 8, 16,
+      1, 1, 0, NORMAL_MODE,
+      0, 0, 0, 0, 0
+    };
+    pp->update.zoomFilterData = zfd;
+  }
+
+  setOptimizedMethods (pp);
+
+  pp->scanner = gsl_new ();
+  pp->main_scanner = gsl_new ();
+  pp->main_script_str = GOOM_MAIN_SCRIPT;
+
+  for (i = 0; i < 0xffff; i++) {
+    pp->sintable[i] =
+        (int) (1024 * sin ((double) i * 360 / (sizeof (pp->sintable) /
+                sizeof (pp->sintable[0]) - 1) * 3.141592 / 180) + .5);
+    /* sintable [us] = (int)(1024.0f * sin (us*2*3.31415f/0xffff)) ; */
+  }
+}
+
+void
+plugin_info_add_visual (PluginInfo * p, int i, VisualFX * visual)
+{
+  p->visuals[i] = visual;
+  if (i == p->nbVisuals - 1) {
+    ++i;
+    p->nbParams = 1;
+    while (i--) {
+      if (p->visuals[i]->params)
+        p->nbParams++;
+    }
+    p->params =
+        (PluginParameters *) malloc (sizeof (PluginParameters) * p->nbParams);
+    i = p->nbVisuals;
+    p->nbParams = 1;
+    p->params[0] = p->sound.params;
+    while (i--) {
+      if (p->visuals[i]->params)
+        p->params[p->nbParams++] = *(p->visuals[i]->params);
+    }
+  }
+}
diff --git a/gst/goom/ppc_drawings.h b/gst/goom/ppc_drawings.h
new file mode 100644 (file)
index 0000000..ee438c2
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *  ppc_drawings.h
+ *  Goom
+ *
+ *  Created by Guillaume Borios on Sun Dec 28 2003.
+ *  Copyright (c) 2003 iOS. All rights reserved.
+ *
+ */
+
+/* Generic PowerPC Code */
+void ppc_brightness_generic(Pixel *src, Pixel *dest, int size, int coeff);
+
+/* G4 Specific PowerPC Code (Possible use of Altivec and Data Streams) */
+void ppc_brightness_G4(Pixel *src, Pixel *dest, int size, int coeff);
+
+/* G5 Specific PowerPC Code (Possible use of Altivec) */
+void ppc_brightness_G5(Pixel *src, Pixel *dest, int size, int coeff);
+
diff --git a/gst/goom/ppc_drawings.s b/gst/goom/ppc_drawings.s
new file mode 100644 (file)
index 0000000..845e5ea
--- /dev/null
@@ -0,0 +1,381 @@
+; PowerPC optimized drawing methods for Goom
+; Â© 2003 Guillaume Borios
+; This Source Code is released under the terms of the General Public License
+
+; Change log :
+; 30 May 2003 : File creation
+
+; Section definition : We use a read only code section for the whole file
+.section __TEXT,__text,regular,pure_instructions
+
+
+; --------------------------------------------------------------------------------------
+; Single 32b pixel drawing macros
+; Usage :
+;      DRAWMETHOD_XXXX_MACRO *pixelIN, *pixelOUT, COLOR, WR1, WR2, WR3, WR4
+;      Only the work registers (WR) can be touched by the macros
+;
+; Available methods :
+;      DRAWMETHOD_DFLT_MACRO : Default drawing method (Actually OVRW)
+;      DRAWMETHOD_PLUS_MACRO : RVB Saturated per channel addition (SLOWEST)
+;      DRAWMETHOD_HALF_MACRO : 50% Transparency color drawing
+;      DRAWMETHOD_OVRW_MACRO : Direct COLOR drawing (FASTEST)
+;      DRAWMETHOD_B_OR_MACRO : Bitwise OR
+;      DRAWMETHOD_BAND_MACRO : Bitwise AND
+;      DRAWMETHOD_BXOR_MACRO : Bitwise XOR
+;      DRAWMETHOD_BNOT_MACRO : Bitwise NOT
+; --------------------------------------------------------------------------------------
+
+.macro DRAWMETHOD_OVRW_MACRO
+    stw                $2,0($1)        ;; *$1 <- $2
+.endmacro
+
+.macro DRAWMETHOD_B_OR_MACRO
+    lwz                $3,0($0)        ;; $3 <- *$0
+    or         $3,$3,$2        ;; $3 <- $3 | $2
+    stw                $3,0($1)        ;; *$1 <- $3
+.endmacro
+
+.macro DRAWMETHOD_BAND_MACRO
+    lwz                $3,0($0)        ;; $3 <- *$0
+    and                $3,$3,$2        ;; $3 <- $3 & $2
+    stw                $3,0($1)        ;; *$1 <- $3
+.endmacro
+
+.macro DRAWMETHOD_BXOR_MACRO
+    lwz                $3,0($0)        ;; $3 <- *$0
+    xor                $3,$3,$2        ;; $3 <- $3 ^ $2
+    stw                $3,0($1)        ;; *$1 <- $3
+.endmacro
+
+.macro DRAWMETHOD_BNOT_MACRO
+    lwz                $3,0($0)        ;; $3 <- *$0
+    nand       $3,$3,$3        ;; $3 <- ~$3
+    stw                $3,0($1)        ;; *$1 <- $3
+.endmacro
+
+.macro DRAWMETHOD_PLUS_MACRO
+    lwz                $4,0($0)        ;; $4 <- *$0
+    andi.      $3,$4,0xFF00    ;; $3 <- $4 & 0x0000FF00
+    andi.      $5,$2,0xFF00    ;; $5 <- $2 & 0x0000FF00
+    add                $3,$3,$5        ;; $3 <- $3 + $5
+    rlwinm     $5,$3,15,0,0    ;; $5 <- 0 | ($3[15] << 15)
+    srawi      $5,$5,23        ;; $5 <- $5 >> 23 (algebraic for sign extension)
+    or         $3,$3,$5        ;; $3 <- $3 | $5
+    lis                $5,0xFF         ;; $5 <- 0x00FF00FF
+    addi       $5,$5,0xFF
+    and                $4,$4,$5        ;; $4 <- $4 & $5
+    and                $6,$2,$5        ;; $6 <- $2 & $5
+    add                $4,$4,$6        ;; $4 <- $4 + $6
+    rlwinm     $6,$4,7,0,0     ;; $6 <- 0 | ($4[7] << 7)
+    srawi      $6,$6,15        ;; $6 <- $6 >> 15 (algebraic for sign extension)
+    rlwinm     $5,$4,23,0,0    ;; $5 <- 0 | ($4[23] << 23)
+    srawi      $5,$5,31        ;; $5 <- $5 >> 31 (algebraic for sign extension)
+    rlwimi     $6,$5,0,24,31   ;; $6[24..31] <- $5[24..31]
+    or         $4,$4,$6        ;; $4 <- $4 | $6
+    rlwimi     $4,$3,0,16,23   ;; $4[16..23] <- $3[16..23]
+    stw                $4,0($1)        ;; *$1 <- $4
+.endmacro
+
+.macro DRAWMETHOD_HALF_MACRO
+    lwz                $4,0($0)        ;; $4 <- *$0
+    andi.      $3,$4,0xFF00    ;; $3 <- $4 & 0x0000FF00
+    andi.      $5,$2,0xFF00    ;; $5 <- $2 & 0x0000FF00
+    add                $3,$3,$5        ;; $3 <- $3 + $5
+    lis                $5,0xFF         ;; $5 <- 0x00FF00FF
+    addi       $5,$5,0xFF
+    and                $4,$4,$5        ;; $4 <- $4 & $5
+    and                $5,$2,$5        ;; $5 <- $2 & $5
+    add                $4,$4,$5        ;; $4 <- $4 + $5
+    srwi       $4,$4,1         ;; $4 <- $4 >> 1
+    rlwimi     $4,$3,31,16,23  ;; $4[16..23] <- $3[15..22]
+    stw                $4,0($1)        ;; *$1 <- $4
+.endmacro
+
+.macro DRAWMETHOD_DFLT_MACRO
+    DRAWMETHOD_PLUS_MACRO
+.endmacro
+
+; --------------------------------------------------------------------------------------
+
+
+
+; **************************************************************************************
+; void DRAWMETHOD_PLUS_PPC(unsigned int * buf, unsigned int _col);
+; void DRAWMETHOD_PLUS_2_PPC(unsigned * in, unsigned int * out, unsigned int _col);
+; **************************************************************************************
+.globl _DRAWMETHOD_PLUS_2_PPC
+.align 3
+_DRAWMETHOD_PLUS_2_PPC:
+    DRAWMETHOD_PLUS_MACRO      r3,r4,r5,r6,r7,r8,r9
+    blr                                ;; return
+
+.globl _DRAWMETHOD_PLUS_PPC
+.align 3
+_DRAWMETHOD_PLUS_PPC:
+    DRAWMETHOD_PLUS_MACRO      r3,r3,r4,r5,r6,r7,r9
+    blr                                ;; return
+
+
+; **************************************************************************************
+; void DRAWMETHOD_HALF_PPC(unsigned int * buf, unsigned int _col);
+; void DRAWMETHOD_HALF_2_PPC(unsigned * in, unsigned int * out, unsigned int _col);
+; **************************************************************************************
+.globl _DRAWMETHOD_HALF_2_PPC
+.align 3
+_DRAWMETHOD_HALF_2_PPC:
+    DRAWMETHOD_HALF_MACRO      r3,r4,r5,r6,r7,r8
+    blr                                ;; return
+
+.globl _DRAWMETHOD_HALF_PPC
+.align 3
+_DRAWMETHOD_HALF_PPC:
+    DRAWMETHOD_HALF_MACRO      r3,r3,r4,r5,r6,r7
+    blr                                ;; return
+
+
+; **************************************************************************************
+; void DRAW_LINE_PPC(unsigned int *data, int x1, int y1, int x2, int y2, unsigned int col,
+;                      unsigned int screenx, unsigned int screeny)
+; **************************************************************************************
+.globl _DRAW_LINE_PPC
+.align 3
+_DRAW_LINE_PPC:
+    ;; NOT IMPLEMENTED YET
+    blr                                ;; return
+
+
+; **************************************************************************************
+; void _ppc_brightness(Pixel * src, Pixel * dest, unsigned int size, unsigned int coeff)
+; **************************************************************************************
+
+
+.const
+.align 4
+vectorZERO:
+    .long 0,0,0,0
+    .long 0x10101000, 0x10101001, 0x10101002, 0x10101003
+    .long 0x10101004, 0x10101005, 0x10101006, 0x10101007
+    .long 0x10101008, 0x10101009, 0x1010100A, 0x1010100B
+    .long 0x1010100C, 0x1010100D, 0x1010100E, 0x1010100F
+
+
+.section __TEXT,__text,regular,pure_instructions
+
+.globl _ppc_brightness_G4
+.align 3
+_ppc_brightness_G4:
+
+
+;; PowerPC Altivec code
+    srwi    r5,r5,2
+    mtctr   r5
+
+;;vrsave
+    mfspr   r11,256
+    lis     r12,0xCFFC
+    mtspr   256,r12
+
+        mflr r0
+        bcl 20,31,"L00000000001$pb"
+"L00000000001$pb":
+        mflr r10
+        mtlr r0
+
+    addis   r9,r10,ha16(vectorZERO-"L00000000001$pb")
+    addi    r9,r9,lo16(vectorZERO-"L00000000001$pb")
+    
+    vxor    v0,v0,v0 ;; V0 = NULL vector
+
+    addi    r9,r9,16
+    lvx     v10,0,r9
+    addi    r9,r9,16
+    lvx     v11,0,r9
+    addi    r9,r9,16
+    lvx     v12,0,r9
+    addi    r9,r9,16
+    lvx     v13,0,r9
+
+    addis   r9,r10,ha16(vectortmpwork-"L00000000001$pb")
+    addi    r9,r9,lo16(vectortmpwork-"L00000000001$pb")
+    stw     r6,0(r9)
+    li      r6,8
+    stw     r6,4(r9)
+    lvx     v9,0,r9
+    li      r9,128
+    vspltw  v8,v9,0
+    vspltw  v9,v9,1
+
+;; elt counter
+    li      r9,0
+    lis     r7,0x0F01
+    b L7
+.align 4
+L7:
+    lvx     v1,r9,r3
+
+    vperm   v4,v1,v0,v10
+    ;*********************
+     add r10,r9,r3
+    ;*********************
+    vperm   v5,v1,v0,v11
+    vperm   v6,v1,v0,v12
+    vperm   v7,v1,v0,v13
+
+    vmulouh  v4,v4,v8
+    ;*********************
+     dst     r10,r7,3
+    ;*********************
+    vmulouh  v5,v5,v8
+    vmulouh  v6,v6,v8
+    vmulouh  v7,v7,v8
+    vsrw     v4,v4,v9
+    vsrw     v5,v5,v9
+    vsrw     v6,v6,v9
+    vsrw     v7,v7,v9 
+    
+    vpkuwus v4,v4,v5
+    vpkuwus v6,v6,v7
+    vpkuhus v1,v4,v6
+
+    stvx    v1,r9,r4
+    addi    r9,r9,16
+
+    bdnz L7
+
+    mtspr   256,r11
+    blr
+
+
+.globl _ppc_brightness_G5
+.align 3
+_ppc_brightness_G5:
+
+;; PowerPC Altivec G5 code
+    srwi    r5,r5,2
+    mtctr   r5
+
+;;vrsave
+    mfspr   r11,256
+    lis     r12,0xCFFC
+    mtspr   256,r12
+
+        mflr r0
+        bcl 20,31,"L00000000002$pb"
+"L00000000002$pb":
+        mflr r10
+        mtlr r0
+
+    addis   r9,r10,ha16(vectorZERO-"L00000000002$pb")
+    addi    r9,r9,lo16(vectorZERO-"L00000000002$pb")
+    
+    vxor    v0,v0,v0 ;; V0 = NULL vector
+
+    addi    r9,r9,16
+    lvx     v10,0,r9
+    addi    r9,r9,16
+    lvx     v11,0,r9
+    addi    r9,r9,16
+    lvx     v12,0,r9
+    addi    r9,r9,16
+    lvx     v13,0,r9
+
+    addis   r9,r10,ha16(vectortmpwork-"L00000000002$pb")
+    addi    r9,r9,lo16(vectortmpwork-"L00000000002$pb")
+    stw     r6,0(r9)
+    li      r6,8
+    stw     r6,4(r9)
+    lvx     v9,0,r9
+    li      r9,128
+    vspltw  v8,v9,0
+    vspltw  v9,v9,1
+
+;; elt counter
+    li      r9,0
+    lis     r7,0x0F01
+    b L6
+.align 4
+L6:
+    lvx     v1,r9,r3
+
+    vperm   v4,v1,v0,v10
+    ;*********************
+    add r10,r9,r3
+    ;*********************
+    vperm   v5,v1,v0,v11
+    vperm   v6,v1,v0,v12
+    vperm   v7,v1,v0,v13
+
+    vmulouh  v4,v4,v8
+    vmulouh  v5,v5,v8
+    vmulouh  v6,v6,v8
+    vmulouh  v7,v7,v8
+    vsrw     v4,v4,v9
+    vsrw     v5,v5,v9
+    vsrw     v6,v6,v9
+    vsrw     v7,v7,v9 
+    
+    vpkuwus v4,v4,v5
+    vpkuwus v6,v6,v7
+    vpkuhus v1,v4,v6
+
+    stvx    v1,r9,r4
+    addi    r9,r9,16
+
+    bdnz L6
+
+    mtspr   256,r11
+    blr
+
+
+.globl _ppc_brightness_generic
+.align 3
+_ppc_brightness_generic:
+    lis   r12,0x00FF
+    ori   r12,r12,0x00FF
+    subi  r3,r3,4
+    subi  r4,r4,4
+    mtctr r5
+    b L1
+.align 4
+L1:
+    lwzu  r7,4(r3)
+
+    rlwinm  r8,r7,16,24,31
+    rlwinm  r9,r7,24,24,31
+    mullw   r8,r8,r6
+    rlwinm  r10,r7,0,24,31
+    mullw   r9,r9,r6
+    srwi    r8,r8,8
+    mullw   r10,r10,r6
+    srwi    r9,r9,8
+
+    rlwinm. r11,r8,0,0,23
+    beq     L2
+    li      r8,0xFF
+L2:
+    srwi    r10,r10,8
+    rlwinm. r11,r9,0,0,23
+    beq     L3
+    li      r9,0xFF
+L3:
+    rlwinm  r7,r8,16,8,15
+    rlwinm. r11,r10,0,0,23
+    beq     L4
+    li      r10,0xFF
+L4:
+    rlwimi  r7,r9,8,16,23
+    rlwimi  r7,r10,0,24,31
+
+    stwu    r7,4(r4)
+    bdnz L1
+
+    blr
+
+
+
+.static_data
+.align 4
+vectortmpwork:
+    .long 0,0,0,0
+
diff --git a/gst/goom/ppc_zoom_ultimate.h b/gst/goom/ppc_zoom_ultimate.h
new file mode 100644 (file)
index 0000000..d6932e7
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ *  ppc_zoom_ultimate.h
+ *  Goom
+ *
+ *  Created by Guillaume Borios on Sun Dec 28 2003.
+ *  Copyright (c) 2003 iOS. All rights reserved.
+ *
+ */
+
+/* Generic PowerPC Code */
+void ppc_zoom_generic (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]);
+
+/* G4 Specific PowerPC Code (Possible use of Altivec and Data Streams) */
+void ppc_zoom_G4 (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]);
\ No newline at end of file
diff --git a/gst/goom/ppc_zoom_ultimate.s b/gst/goom/ppc_zoom_ultimate.s
new file mode 100644 (file)
index 0000000..da252c6
--- /dev/null
@@ -0,0 +1,323 @@
+; PowerPC optimized zoom for Goom
+; Â© 2001-2003 Guillaume Borios
+; This Source Code is released under the terms of the General Public License
+
+; Change log :
+; 21 Dec 2003 : Use of altivec is now determined with a parameter
+
+; Section definition : We use a read only section
+.text
+
+; name of the function to call by C program : ppc_zoom
+; We declare this label as a global to extend its scope outside this file
+.globl _ppc_zoom_generic
+.globl _ppc_zoom_G4
+
+; Description :
+; This routine dynamically computes and applies a zoom filter
+
+; parameters :
+; r3  <=> unsigned int sizeX (in pixels)
+; r4  <=> unsigned int sizeY (in pixels)
+; r5  <=> unsigned int * frompixmap
+; r6  <=> unsigned int * topixmap
+; r7  <=> unsigned int * brutS
+; r8  <=> unsigned int * brutD
+; r9  <=> unsigned int buffratio
+; r10 <=> int [16][16] precalccoeffs
+
+; globals after init
+; r5  <=> frompixmap - 1 byte needed for preincremental fetch (replaces r5)
+; r6  <=> topixmap - 1 byte needed for preincremental fetch (replaces r6)
+; r3 <=> ax = x max in 16th of pixels (replaces old r3)
+; r4 <=> ay = y max in 16th of pixels (replaces old r4)
+; r20 <=> row size in bytes
+; r12 <=> 0xFF00FF (mask for parallel 32 bits pixs computing)
+; r30 <=> brutS - 1 byte needed for preincremental fetch (replaces r7)
+; r31 <=> brutD - 1 byte needed for preincremental fetch (replaces r8)
+
+; ABI notes :
+; r1 is the Stack Pointer (SP) => Do not use
+; r13..r31 are non-volatiles => Do not use
+
+_ppc_zoom_generic:
+
+; Saves the used non volatile registers in the Mach-O stack s Red-Zone
+stmw   r18,-56(r1)
+
+; init
+li      r18,0          ; Default value if out of range : 0 (Black)
+mr      r11,r10
+lis     r12,0xFF
+mullw   r2,r3,r4       ; Number of pixels to compute
+subi    r30,r8,0
+slwi   r20,r3,2
+srawi   r19,r20,2
+ori     r12,r12,0xFF
+subi    r3,r3,1
+subi    r4,r4,1
+mtspr  ctr,r2          ; Init the loop count (one loop per pixel computed)
+subi    r31,r7,0
+subi    r6,r6,4
+slwi   r3,r3,4
+slwi   r4,r4,4
+
+;pre init for loop
+lwz    r2,0(r31)    ; px
+lwz    r29,4(r31)   ; py
+lwz    r8,0(r30)    ; px2
+lwz    r10,4(r30)   ; py2
+
+b       L1
+.align  5
+L1:
+
+; computes dynamically the position to fetch
+sub     r8,r8,r2
+sub     r10,r10,r29
+mullw   r8,r8,r9
+addi    r31,r31,8
+mullw   r10,r10,r9
+addi    r30,r30,8
+
+srawi   r8,r8,16
+srawi   r10,r10,16
+add     r2,r2,r8
+add     r29,r29,r10
+
+; if px>ax or py>ay goto outofrange
+; computes the attenuation coeffs and the original point address
+rlwinm  r10,r2,6,28-6,31-6 ; r10 <- (r2 << 2) & 0x000002D0   (r10=(r2%16)*4*16)
+cmpl    cr4,0,r2,r3
+rlwimi  r10, r29, 2, 28-2, 31-2 ; r10 <- ((r29 << 2) & 0x0000002D) | (r10 & !0x0000002D)      (r10=(r10%16)*4 | r10)
+cmpl    cr7,0,r29,r4
+srawi   r29,r29,4     ; pos computing
+bge-   cr4,L4
+srawi   r2,r2,4       ; pos computing
+mullw   r29, r29,r19  ; pos computing
+bge-   cr7,L4
+
+; Channels notation : 00112233 (AARRVVBB)
+
+add     r2,r2,r29              ; pos computing
+lwzx    r10,r11,r10            ; Loads coefs
+slwi    r2,r2,2                ; pos computing
+add    r2,r2,r5                ; pos computing
+rlwinm  r21,r10,0,24,31                ; Isolates coef1 (??????11 -> 00000011)
+lwz    r25,0(r2)               ; Loads col1 -> r25
+lwz    r26,4(r2)               ; Loads col2 -> r26
+rlwinm  r22,r10,24,24,31       ; Isolates coef2 (????22?? -> 00000022)
+rlwinm  r23,r10,16,24,31       ; Isolates coef3 (??33???? -> 00000033)
+add    r2,r2,r20               ; Adds one line for future load of col3 and col4
+and    r8, r25,r12             ; Masks col1 channels 1 & 3 : 0x00XX00XX
+rlwinm  r24,r10,8,24,31                ; Isolates coef4 (44?????? -> 00000044)
+andi.  r25,r25,0xFF00          ; Masks col1 channel 2 : 0x0000XX00
+mullw  r8, r8, r21             ; Applies coef1 on col1 channels 1 & 3
+
+
+; computes final pixel color
+and    r10,r26,r12             ; Masks col2 channels 1 & 3 : 0x00XX00XX
+lwz    r27,0(r2)               ; Loads col3 -> r27
+mullw  r10,r10,r22             ; Applies coef2 on col2 channels 1 & 3
+mullw  r25,r25,r21             ; Applies coef1 on col1 channel 2
+andi.  r29,r26,0xFF00          ; Masks col2 channel 2 : 0x0000XX00
+mullw  r29,r29,r22             ; Applies coef2 on col2 channel 2
+lwz    r28,4(r2)               ; Loads col4 -> r28
+add    r8 ,r8 ,r10             ; Adds col1 & col2 channels 1 & 3
+and    r10,r27,r12             ; Masks col3 channels 1 & 3 : 0x00XX00XX
+add    r25,r25,r29             ; Adds col1 & col2 channel 2
+mullw  r10,r10,r23             ; Applies coef3 on col3 channels 1 & 3
+andi.  r29,r27,0xFF00          ; Masks col3 channel 2 : 0x0000XX00
+mullw  r29,r29,r23             ; Applies coef3 on col3 channel 2
+lwz    r2,0(r31)               ; px
+add    r7 ,r8 ,r10             ; Adds col3 to (col1 + col2) channels 1 & 3
+and    r10,r28,r12             ; Masks col4 channels 1 & 3 : 0x00XX00XX
+mullw  r10,r10,r24             ; Applies coef4 on col4 channels 1 & 3
+add    r25,r25,r29             ; Adds col 3 to (col1 + col2) channel 2
+lwz    r8,0(r30)               ; px2
+andi.  r28,r28,0xFF00          ; Masks col4 channel 2 : 0x0000XX00
+add    r7 ,r7 ,r10             ; Adds col4 to (col1 + col2 + col3) channels 1 & 3
+lwz    r10,4(r30)              ; py2
+mullw  r28,r28,r24             ; Applies coef4 on col4 channel 2
+srawi  r7, r7, 8               ; (sum of channels 1 & 3) >> 8
+lwz    r29,4(r31)              ; py
+add    r25,r25,r28             ; Adds col 4 to (col1 + col2 + col3) channel 2
+rlwimi  r7, r25, 24, 16, 23    ; (((sum of channels 2) >> 8 ) & 0x0000FF00) | ((sum of channels 1 and 3) & 0xFFFF00FF)
+stwu   r7,4(r6)                ; Stores the computed pixel
+bdnz   L1                      ; Iterate again if needed
+b       L3     ;goto end       ; If not, returns from the function
+
+
+; if out of range
+L4:
+stwu   r18,4(r6)
+lwz    r8,0(r30)    ; px2
+lwz    r10,4(r30)   ; py2
+lwz    r2,0(r31)    ; px
+lwz    r29,4(r31)   ; py
+bdnz   L1
+
+
+L3:
+
+; Restore saved registers and return
+lmw    r18,-56(r1)
+blr
+
+
+
+
+
+
+
+
+_ppc_zoom_G4:
+
+; Saves the used non volatile registers in the Mach-O stack s Red-Zone
+stmw   r17,-60(r1)
+
+; init
+li      r18,0          ; Default value if out of range : 0 (Black)
+mr      r11,r10
+lis     r12,0xFF
+mullw   r2,r3,r4       ; Number of pixels to compute
+subi    r30,r8,0
+slwi   r20,r3,2
+srawi   r19,r20,2
+ori     r12,r12,0xFF
+subi    r3,r3,1
+subi    r4,r4,1
+mtspr  ctr,r2          ; Init the loop count (one loop per pixel computed)
+subi    r31,r7,0
+subi    r6,r6,4
+slwi   r3,r3,4
+slwi   r4,r4,4
+
+;pre init for loop
+lwz    r2,0(r31)    ; px
+lwz    r29,4(r31)   ; py
+lwz    r8,0(r30)    ; px2
+lwz    r10,4(r30)   ; py2
+
+;*********************
+lis     r17,0x0F01
+
+b       L100
+.align  5
+L100:
+
+addi    r6,r6,4
+
+; Optimization to ensure the destination buffer
+; won't be loaded into the data cache
+rlwinm. r0,r6,0,27,31
+bne+    L500
+dcbz    0,r6
+;dcba    0,r6
+L500:
+
+; computes dynamically the position to fetch
+;mullw   r8,r8,r29
+;mullw   r2,r2,r29
+;add     r2,r8,r2
+;srawi   r2,r2,17
+
+sub     r8,r8,r2
+sub     r10,r10,r29
+mullw   r8,r8,r9
+addi    r31,r31,8
+mullw   r10,r10,r9
+addi    r30,r30,8
+
+dst     r30,r17,0
+
+srawi    r8,r8,16
+srawi    r10,r10,16
+add     r2,r2,r8
+add     r29,r29,r10
+
+dst     r31,r17,1
+
+; if px>ax or py>ay goto outofrange
+; computes the attenuation coeffs and the original point address
+rlwinm  r10,r2,6,28-6,31-6 ; r10 <- (r2 << 2) & 0x000002D0   (r10=(r2%16)*4*16)
+cmpl    cr4,0,r2,r3
+rlwimi  r10, r29, 2, 28-2, 31-2 ; r10 <- ((r29 << 2) & 0x0000002D) | (r10 & !0x0000002D)      (r10=(r29%16)*4 | r10)
+cmpl    cr7,0,r29,r4
+srawi   r29,r29,4     ; pos computing
+bge-   cr4,L400
+srawi   r2,r2,4       ; pos computing
+mullw   r29, r29,r19  ; pos computing
+bge-   cr7,L400
+
+; Channels notation : 00112233 (AARRVVBB)
+
+add     r2,r2,r29              ; pos computing
+lwzx    r10,r11,r10            ; Loads coefs
+slwi    r2,r2,2                ; pos computing
+add    r2,r2,r5                ; pos computing
+rlwinm  r21,r10,0,24,31                ; Isolates coef1 (??????11 -> 00000011)
+lwz    r25,0(r2)               ; Loads col1 -> r25
+lwz    r26,4(r2)               ; Loads col2 -> r26
+rlwinm  r22,r10,24,24,31       ; Isolates coef2 (????22?? -> 00000022)
+rlwinm  r23,r10,16,24,31       ; Isolates coef3 (??33???? -> 00000033)
+add    r2,r2,r20               ; Adds one line for future load of col3 and col4
+and    r8, r25,r12             ; Masks col1 channels 1 & 3 : 0x00XX00XX
+rlwinm  r24,r10,8,24,31                ; Isolates coef4 (44?????? -> 00000044)
+dst     r2,r17,2
+rlwinm  r25,r25,0,16,23                ; Masks col1 channel 2 : 0x0000XX00
+;andi. r25,r25,0xFF00          ; Masks col1 channel 2 : 0x0000XX00
+mullw  r8, r8, r21             ; Applies coef1 on col1 channels 1 & 3
+
+
+; computes final pixel color
+and    r10,r26,r12             ; Masks col2 channels 1 & 3 : 0x00XX00XX
+lwz    r27,0(r2)               ; Loads col3 -> r27
+mullw  r10,r10,r22             ; Applies coef2 on col2 channels 1 & 3
+mullw  r25,r25,r21             ; Applies coef1 on col1 channel 2
+rlwinm  r29,r26,0,16,23                ; Masks col2 channel 2 : 0x0000XX00
+;andi. r29,r26,0xFF00          ; Masks col2 channel 2 : 0x0000XX00
+mullw  r29,r29,r22             ; Applies coef2 on col2 channel 2
+lwz    r28,4(r2)               ; Loads col4 -> r28
+add    r8 ,r8 ,r10             ; Adds col1 & col2 channels 1 & 3
+and    r10,r27,r12             ; Masks col3 channels 1 & 3 : 0x00XX00XX
+add    r25,r25,r29             ; Adds col1 & col2 channel 2
+mullw  r10,r10,r23             ; Applies coef3 on col3 channels 1 & 3
+rlwinm  r29,r27,0,16,23                ; Masks col3 channel 2 : 0x0000XX00
+;andi. r29,r27,0xFF00          ; Masks col3 channel 2 : 0x0000XX00
+mullw  r29,r29,r23             ; Applies coef3 on col3 channel 2
+lwz    r2,0(r31)               ; px
+add    r7 ,r8 ,r10             ; Adds col3 to (col1 + col2) channels 1 & 3
+and    r10,r28,r12             ; Masks col4 channels 1 & 3 : 0x00XX00XX
+mullw  r10,r10,r24             ; Applies coef4 on col4 channels 1 & 3
+add    r25,r25,r29             ; Adds col 3 to (col1 + col2) channel 2
+lwz    r8,0(r30)               ; px2
+rlwinm  r28,r28,0,16,23                ; Masks col4 channel 2 : 0x0000XX00
+;andi. r28,r28,0xFF00          ; Masks col4 channel 2 : 0x0000XX00
+add    r7 ,r7 ,r10             ; Adds col4 to (col1 + col2 + col3) channels 1 & 3
+lwz    r10,4(r30)              ; py2
+mullw  r28,r28,r24             ; Applies coef4 on col4 channel 2
+srawi  r7, r7, 8               ; (sum of channels 1 & 3) >> 8
+lwz    r29,4(r31)              ; py
+add    r25,r25,r28             ; Adds col 4 to (col1 + col2 + col3) channel 2
+rlwimi  r7, r25, 24, 16, 23    ; (((sum of channels 2) >> 8 ) & 0x0000FF00) | ((sum of channels 1 and 3) & 0xFFFF00FF)
+stw    r7,0(r6)                ; Stores the computed pixel
+bdnz   L100                    ; Iterate again if needed
+b       L300   ;goto end       ; If not, returns from the function
+
+
+; if out of range
+L400:
+stw    r18,0(r6)
+lwz    r8,0(r30)    ; px2
+lwz    r10,4(r30)   ; py2
+lwz    r2,0(r31)    ; px
+lwz    r29,4(r31)   ; py
+bdnz   L100
+
+
+L300:
+
+; Restore saved registers and return
+lmw    r17,-60(r1)
+blr
diff --git a/gst/goom/sound_tester.c b/gst/goom/sound_tester.c
new file mode 100644 (file)
index 0000000..214ca0e
--- /dev/null
@@ -0,0 +1,143 @@
+#include "sound_tester.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* some constants */
+#define BIG_GOOM_DURATION 100
+#define BIG_GOOM_SPEED_LIMIT 0.1f
+
+#define ACCEL_MULT 0.95f
+#define SPEED_MULT 0.99f
+
+
+void
+evaluate_sound (gint16 data[2][512], SoundInfo * info)
+{
+
+  int i;
+  float difaccel;
+  float prevspeed;
+
+  /* find the max */
+  int incvar = 0;
+
+  for (i = 0; i < 512; i += 2) {
+    if (incvar < data[0][i])
+      incvar = data[0][i];
+  }
+
+  if (incvar > info->allTimesMax)
+    info->allTimesMax = incvar;
+
+  /* volume sonore */
+  info->volume = (float) incvar / (float) info->allTimesMax;
+  memcpy (info->samples[0], data[0], 512 * sizeof (short));
+  memcpy (info->samples[1], data[1], 512 * sizeof (short));
+
+  difaccel = info->accelvar;
+  info->accelvar = info->volume;        /* accel entre 0 et 1 */
+
+  /* transformations sur la vitesse du son */
+  if (info->speedvar > 1.0f)
+    info->speedvar = 1.0f;
+
+  if (info->speedvar < 0.1f)
+    info->accelvar *= (1.0f - (float) info->speedvar);
+  else if (info->speedvar < 0.3f)
+    info->accelvar *= (0.9f - (float) (info->speedvar - 0.1f) / 2.0f);
+  else
+    info->accelvar *= (0.8f - (float) (info->speedvar - 0.3f) / 4.0f);
+
+  /* adoucissement de l'acceleration */
+  info->accelvar *= ACCEL_MULT;
+  if (info->accelvar < 0)
+    info->accelvar = 0;
+
+  difaccel = info->accelvar - difaccel;
+  if (difaccel < 0)
+    difaccel = -difaccel;
+
+  /* mise a jour de la vitesse */
+  prevspeed = info->speedvar;
+  info->speedvar = (info->speedvar + difaccel * 0.5f) / 2;
+  info->speedvar *= SPEED_MULT;
+  info->speedvar = (info->speedvar + 3.0f * prevspeed) / 4.0f;
+  if (info->speedvar < 0)
+    info->speedvar = 0;
+  if (info->speedvar > 1)
+    info->speedvar = 1;
+
+  /* temps du goom */
+  info->timeSinceLastGoom++;
+  info->timeSinceLastBigGoom++;
+  info->cycle++;
+
+  /* detection des nouveaux gooms */
+  if ((info->speedvar > (float) IVAL (info->biggoom_speed_limit_p) / 100.0f)
+      && (info->accelvar > info->bigGoomLimit)
+      && (info->timeSinceLastBigGoom > BIG_GOOM_DURATION)) {
+    info->timeSinceLastBigGoom = 0;
+  }
+
+  if (info->accelvar > info->goom_limit) {
+    /* TODO: tester && (info->timeSinceLastGoom > 20)) { */
+    info->totalgoom++;
+    info->timeSinceLastGoom = 0;
+    info->goomPower = info->accelvar - info->goom_limit;
+  }
+
+  if (info->accelvar > info->prov_max)
+    info->prov_max = info->accelvar;
+
+  if (info->goom_limit > 1)
+    info->goom_limit = 1;
+
+  /* toute les 2 secondes : vérifier si le taux de goom est correct
+   * et le modifier sinon.. */
+  if (info->cycle % 64 == 0) {
+    if (info->speedvar < 0.01f)
+      info->goom_limit *= 0.91;
+    if (info->totalgoom > 4) {
+      info->goom_limit += 0.02;
+    }
+    if (info->totalgoom > 7) {
+      info->goom_limit *= 1.03f;
+      info->goom_limit += 0.03;
+    }
+    if (info->totalgoom > 16) {
+      info->goom_limit *= 1.05f;
+      info->goom_limit += 0.04;
+    }
+    if (info->totalgoom == 0) {
+      info->goom_limit = info->prov_max - 0.02;
+    }
+    if ((info->totalgoom == 1) && (info->goom_limit > 0.02))
+      info->goom_limit -= 0.01;
+    info->totalgoom = 0;
+    info->bigGoomLimit =
+        info->goom_limit * (1.0f +
+        (float) IVAL (info->biggoom_factor_p) / 500.0f);
+    info->prov_max = 0;
+  }
+
+  /* mise a jour des parametres pour la GUI */
+  FVAL (info->volume_p) = info->volume;
+  info->volume_p.change_listener (&info->volume_p);
+  FVAL (info->speed_p) = info->speedvar * 4;
+  info->speed_p.change_listener (&info->speed_p);
+  FVAL (info->accel_p) = info->accelvar;
+  info->accel_p.change_listener (&info->accel_p);
+
+  FVAL (info->goom_limit_p) = info->goom_limit;
+  info->goom_limit_p.change_listener (&info->goom_limit_p);
+  FVAL (info->goom_power_p) = info->goomPower;
+  info->goom_power_p.change_listener (&info->goom_power_p);
+  FVAL (info->last_goom_p) = 1.0 - ((float) info->timeSinceLastGoom / 20.0f);
+  info->last_goom_p.change_listener (&info->last_goom_p);
+  FVAL (info->last_biggoom_p) =
+      1.0 - ((float) info->timeSinceLastBigGoom / 40.0f);
+  info->last_biggoom_p.change_listener (&info->last_biggoom_p);
+
+  /* bigGoomLimit ==goomLimit*9/8+7 ? */
+}
diff --git a/gst/goom/sound_tester.h b/gst/goom/sound_tester.h
new file mode 100644 (file)
index 0000000..51545a8
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _SOUND_TESTER_H
+#define _SOUND_TESTER_H
+
+#include "goom_plugin_info.h"
+#include "goom_config.h"
+
+/** change les donnees du SoundInfo */
+void evaluate_sound(gint16 data[2][512], SoundInfo *sndInfo);
+
+#endif
+
diff --git a/gst/goom/surf3d.c b/gst/goom/surf3d.c
new file mode 100644 (file)
index 0000000..f6810f8
--- /dev/null
@@ -0,0 +1,123 @@
+#include "surf3d.h"
+#include "goom_plugin_info.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+grid3d *
+grid3d_new (int sizex, int defx, int sizez, int defz, v3d center)
+{
+  int x = defx;
+  int y = defz;
+  grid3d *g = malloc (sizeof (grid3d));
+  surf3d *s = &(g->surf);
+
+  s->nbvertex = x * y;
+  s->vertex = malloc (x * y * sizeof (v3d));
+  s->svertex = malloc (x * y * sizeof (v3d));
+  s->center = center;
+
+  g->defx = defx;
+  g->sizex = sizex;
+  g->defz = defz;
+  g->sizez = sizez;
+  g->mode = 0;
+
+  while (y) {
+    --y;
+    x = defx;
+    while (x) {
+      --x;
+      s->vertex[x + defx * y].x = (float) (x - defx / 2) * sizex / defx;
+      s->vertex[x + defx * y].y = 0;
+      s->vertex[x + defx * y].z = (float) (y - defz / 2) * sizez / defz;
+    }
+  }
+  return g;
+}
+
+void
+grid3d_draw (PluginInfo * plug, grid3d * g, int color, int colorlow,
+    int dist, Pixel * buf, Pixel * back, int W, int H)
+{
+
+  int x;
+  v2d v2, v2x;
+
+  v2d *v2_array = malloc (g->surf.nbvertex * sizeof (v2d));
+
+  v3d_to_v2d (g->surf.svertex, g->surf.nbvertex, W, H, dist, v2_array);
+
+  for (x = 0; x < g->defx; x++) {
+    int z;
+
+    v2x = v2_array[x];
+
+    for (z = 1; z < g->defz; z++) {
+      v2 = v2_array[z * g->defx + x];
+      if (((v2.x != -666) || (v2.y != -666))
+          && ((v2x.x != -666) || (v2x.y != -666))) {
+        plug->methods.draw_line (buf, v2x.x, v2x.y, v2.x, v2.y, colorlow, W, H);
+        plug->methods.draw_line (back, v2x.x, v2x.y, v2.x, v2.y, color, W, H);
+      }
+      v2x = v2;
+    }
+  }
+
+  free (v2_array);
+}
+
+void
+surf3d_rotate (surf3d * s, float angle)
+{
+  int i;
+  float cosa;
+  float sina;
+
+  SINCOS (angle, sina, cosa);
+  for (i = 0; i < s->nbvertex; i++) {
+    Y_ROTATE_V3D (s->vertex[i], s->svertex[i], cosa, sina);
+  }
+}
+
+void
+surf3d_translate (surf3d * s)
+{
+  int i;
+
+  for (i = 0; i < s->nbvertex; i++) {
+    TRANSLATE_V3D (s->center, s->svertex[i]);
+  }
+}
+
+void
+grid3d_update (grid3d * g, float angle, float *vals, float dist)
+{
+  int i;
+  float cosa;
+  float sina;
+  surf3d *s = &(g->surf);
+  v3d cam = s->center;
+
+  cam.z += dist;
+
+  SINCOS ((angle / 4.3f), sina, cosa);
+  cam.y += sina * 2.0f;
+  SINCOS (angle, sina, cosa);
+
+  if (g->mode == 0) {
+    if (vals)
+      for (i = 0; i < g->defx; i++)
+        s->vertex[i].y = s->vertex[i].y * 0.2 + vals[i] * 0.8;
+
+    for (i = g->defx; i < s->nbvertex; i++) {
+      s->vertex[i].y *= 0.255f;
+      s->vertex[i].y += (s->vertex[i - g->defx].y * 0.777f);
+    }
+  }
+
+  for (i = 0; i < s->nbvertex; i++) {
+    Y_ROTATE_V3D (s->vertex[i], s->svertex[i], cosa, sina);
+    TRANSLATE_V3D (cam, s->svertex[i]);
+  }
+}
diff --git a/gst/goom/surf3d.h b/gst/goom/surf3d.h
new file mode 100644 (file)
index 0000000..482b6a0
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _SURF3D_H
+#define _SURF3D_H
+
+#include "v3d.h"
+#include "goom_graphic.h"
+#include "goom_typedefs.h"
+
+typedef struct {
+       v3d *vertex;
+       v3d *svertex;
+       int nbvertex;
+
+       v3d center;
+} surf3d;
+
+typedef struct {
+       surf3d surf;
+       
+       int defx;
+       int sizex;
+       int defz;
+       int sizez;
+       int mode;
+} grid3d;
+
+/* hi-level */
+
+/* works on grid3d */
+grid3d *grid3d_new (int sizex, int defx, int sizez, int defz, v3d center);
+void grid3d_update (grid3d *s, float angle, float *vals, float dist);
+
+/* low level */
+void surf3d_draw (surf3d *s, int color, int dist, int *buf, int *back, int W,int H);
+void grid3d_draw (PluginInfo *plug, grid3d *g, int color, int colorlow, int dist, Pixel *buf, Pixel *back, int W,int H);
+void surf3d_rotate (surf3d *s, float angle);
+void surf3d_translate (surf3d *s);
+
+#endif
diff --git a/gst/goom/surf3d.s b/gst/goom/surf3d.s
new file mode 100644 (file)
index 0000000..f8c8c5d
--- /dev/null
@@ -0,0 +1,484 @@
+       .file   "surf3d.c"
+       .version        "01.01"
+gcc2_compiled.:
+.text
+       .align 4
+.globl grid3d_new
+       .type    grid3d_new,@function
+grid3d_new:
+       pushl %ebp
+       movl %esp,%ebp
+       subl $44,%esp
+       pushl %edi
+       pushl %esi
+       pushl %ebx
+       movl 20(%ebp),%eax
+       movl 12(%ebp),%esi
+       movl %eax,-8(%ebp)
+       addl $-12,%esp
+       pushl $44
+       call malloc
+       movl %esi,%edx
+       imull -8(%ebp),%edx
+       movl %eax,%edi
+       movl %edx,-12(%ebp)
+       leal (%edx,%edx,2),%ebx
+       movl %edx,8(%edi)
+       addl $-12,%esp
+       sall $2,%ebx
+       pushl %ebx
+       call malloc
+       addl $32,%esp
+       movl %eax,(%edi)
+       addl $-12,%esp
+       pushl %ebx
+       call malloc
+       movl %eax,4(%edi)
+       movl 24(%ebp),%eax
+       movl %eax,12(%edi)
+       movl 28(%ebp),%eax
+       movl %eax,16(%edi)
+       movl 32(%ebp),%eax
+       movl %eax,20(%edi)
+       movl 8(%ebp),%eax
+       movl %eax,28(%edi)
+       movl %esi,24(%edi)
+       movl -8(%ebp),%edx
+       movl 16(%ebp),%eax
+       movl %edx,32(%edi)
+       movl %eax,36(%edi)
+       movl $0,40(%edi)
+       testl %edx,%edx
+       je .L480
+       movl %esi,%eax
+       movl %esi,-28(%ebp)
+       shrl $31,%eax
+       addl %eax,%esi
+       movl -8(%ebp),%eax
+       shrl $31,%eax
+       addl -8(%ebp),%eax
+       movl -12(%ebp),%edx
+       sarl $1,%eax
+       movl %edx,-24(%ebp)
+       negl -28(%ebp)
+       movl %esi,-16(%ebp)
+       movl %eax,-20(%ebp)
+       .p2align 4,,7
+.L481:
+       movl -28(%ebp),%eax
+       addl %eax,-24(%ebp)
+       decl -8(%ebp)
+       movl 12(%ebp),%esi
+       testl %esi,%esi
+       je .L479
+       movl -8(%ebp),%eax
+       subl -20(%ebp),%eax
+       movl %eax,-4(%ebp)
+       fildl -4(%ebp)
+       movl %esi,-4(%ebp)
+       movl -24(%ebp),%edx
+       leal (%edx,%esi),%eax
+       movl -16(%ebp),%ebx
+       fildl 16(%ebp)
+       leal (%eax,%eax,2),%eax
+       sarl $1,%ebx
+       leal 0(,%eax,4),%ecx
+       fmulp %st,%st(1)
+       fildl 20(%ebp)
+       fdivrp %st,%st(1)
+       fildl 8(%ebp)
+       fildl -4(%ebp)
+       jmp .L484
+.L487:
+       fxch %st(2)
+       .p2align 4,,7
+.L484:
+       decl %esi
+       movl %esi,%eax
+       movl (%edi),%edx
+       subl %ebx,%eax
+       movl %eax,-4(%ebp)
+       fildl -4(%ebp)
+       addl $-12,%ecx
+       fmul %st(2),%st
+       fdiv %st(1),%st
+       fstps (%edx,%ecx)
+       fxch %st(2)
+       movl (%edi),%eax
+       movl $0,4(%eax,%ecx)
+       movl (%edi),%eax
+       fsts 8(%eax,%ecx)
+       testl %esi,%esi
+       jne .L487
+       fstp %st(0)
+       fstp %st(0)
+       fstp %st(0)
+.L479:
+       cmpl $0,-8(%ebp)
+       jne .L481
+.L480:
+       leal -56(%ebp),%esp
+       popl %ebx
+       movl %edi,%eax
+       popl %esi
+       popl %edi
+       leave
+       ret
+.Lfe1:
+       .size    grid3d_new,.Lfe1-grid3d_new
+.section       .rodata
+       .align 8
+.LC48:
+       .long 0x0,0x3fe00000
+       .align 4
+.LC49:
+       .long 0x3f19999a
+       .align 4
+.LC50:
+       .long 0x3ee3d70a
+.text
+       .align 4
+.globl grid3d_update
+       .type    grid3d_update,@function
+grid3d_update:
+       pushl %ebp
+       movl %esp,%ebp
+       subl $32,%esp
+       pushl %esi
+       pushl %ebx
+       flds 12(%ebp)
+       movl 8(%ebp),%ebx
+       movl 16(%ebp),%ecx
+       fld %st(0)
+#APP
+       fsin
+#NO_APP
+       fstps -4(%ebp)
+       flds -4(%ebp)
+       fxch %st(1)
+#APP
+       fcos
+#NO_APP
+       fstps -4(%ebp)
+       flds -4(%ebp)
+       cmpl $0,40(%ebx)
+       jne .L519
+       testl %ecx,%ecx
+       je .L520
+       xorl %esi,%esi
+       cmpl 24(%ebx),%esi
+       jge .L520
+       fldl .LC48
+       xorl %edx,%edx
+       .p2align 4,,7
+.L524:
+       movl (%ebx),%eax
+       fld %st(0)
+       fld %st(1)
+       fxch %st(1)
+       fmuls 4(%eax,%edx)
+       fxch %st(1)
+       fmuls (%ecx,%esi,4)
+       faddp %st,%st(1)
+       incl %esi
+       fstps 4(%eax,%edx)
+       addl $12,%edx
+       cmpl 24(%ebx),%esi
+       jl .L524
+       fstp %st(0)
+.L520:
+       movl 24(%ebx),%esi
+       cmpl 8(%ebx),%esi
+       jge .L519
+       leal (%esi,%esi,2),%eax
+       flds .LC49
+       flds .LC50
+       leal 0(,%eax,4),%ecx
+       .p2align 4,,7
+.L529:
+       movl (%ebx),%eax
+       flds 4(%eax,%ecx)
+       fmul %st(2),%st
+       fstps 4(%eax,%ecx)
+       movl %esi,%eax
+       subl 24(%ebx),%eax
+       movl (%ebx),%edx
+       leal (%eax,%eax,2),%eax
+       flds 4(%edx,%eax,4)
+       fmul %st(1),%st
+       fadds 4(%edx,%ecx)
+       incl %esi
+       fstps 4(%edx,%ecx)
+       addl $12,%ecx
+       cmpl 8(%ebx),%esi
+       jl .L529
+       fstp %st(0)
+       fstp %st(0)
+.L519:
+       xorl %esi,%esi
+       cmpl 8(%ebx),%esi
+       jge .L536
+       xorl %ecx,%ecx
+       .p2align 4,,7
+.L534:
+       movl (%ebx),%eax
+       flds (%eax,%ecx)
+       flds 8(%eax,%ecx)
+       fmul %st(2),%st
+       fxch %st(1)
+       fmul %st(3),%st
+       fsubp %st,%st(1)
+       movl 4(%ebx),%edx
+       incl %esi
+       fstps (%edx,%ecx)
+       movl (%ebx),%eax
+       flds (%eax,%ecx)
+       flds 8(%eax,%ecx)
+       fxch %st(1)
+       fmul %st(2),%st
+       fxch %st(1)
+       fmul %st(3),%st
+       faddp %st,%st(1)
+       movl 4(%ebx),%edx
+       fstps 8(%edx,%ecx)
+       movl (%ebx),%eax
+       flds 4(%eax,%ecx)
+       movl 4(%ebx),%edx
+       fstps 4(%edx,%ecx)
+       movl 4(%ebx),%eax
+       flds (%eax,%ecx)
+       fadds 12(%ebx)
+       fstps (%eax,%ecx)
+       movl 4(%ebx),%eax
+       flds 4(%eax,%ecx)
+       fadds 16(%ebx)
+       fstps 4(%eax,%ecx)
+       movl 4(%ebx),%eax
+       flds 8(%eax,%ecx)
+       fadds 20(%ebx)
+       fstps 8(%eax,%ecx)
+       addl $12,%ecx
+       cmpl 8(%ebx),%esi
+       jl .L534
+.L536:
+       fstp %st(0)
+       fstp %st(0)
+       popl %ebx
+       popl %esi
+       leave
+       ret
+.Lfe2:
+       .size    grid3d_update,.Lfe2-grid3d_update
+.section       .rodata
+       .align 4
+.LC51:
+       .long 0x40000000
+       .align 8
+.LC52:
+       .long 0x0,0x42380000
+.text
+       .align 4
+.globl surf3d_draw
+       .type    surf3d_draw,@function
+surf3d_draw:
+       pushl %ebp
+       movl %esp,%ebp
+       subl $60,%esp
+       pushl %edi
+       pushl %esi
+       pushl %ebx
+       movl $0,-20(%ebp)
+       movl -20(%ebp),%edx
+       movl 8(%ebp),%eax
+       cmpl 8(%eax),%edx
+       jge .L493
+       fldl .LC52
+       flds .LC51
+       xorl %edi,%edi
+       .p2align 4,,7
+.L495:
+       movl 8(%ebp),%eax
+       movl 4(%eax),%eax
+       movl %eax,-36(%ebp)
+       fcoms 8(%eax,%edi)
+       fnstsw %ax
+       andb $69,%ah
+       cmpb $1,%ah
+       jne .L496
+       fildl 16(%ebp)
+       movl -36(%ebp),%edx
+       fld %st(0)
+       fmuls (%edx,%edi)
+       fdivs 8(%edx,%edi)
+       fld %st(3)
+       faddp %st,%st(1)
+       fstpl -32(%ebp)
+       movl -32(%ebp),%eax
+       movl -28(%ebp),%edx
+       movl %eax,-40(%ebp)
+       sarl $16,-40(%ebp)
+       movl -36(%ebp),%edx
+       fmuls 4(%edx,%edi)
+       fdivs 8(%edx,%edi)
+       movl -40(%ebp),%ecx
+       fld %st(2)
+       faddp %st,%st(1)
+       fstpl -32(%ebp)
+       movl -32(%ebp),%eax
+       movl -28(%ebp),%edx
+       movl %eax,-44(%ebp)
+       movl 28(%ebp),%eax
+       sarl $1,%eax
+       addl %eax,%ecx
+       movl 32(%ebp),%eax
+       sarl $16,-44(%ebp)
+       sarl $1,%eax
+       movl %ecx,%ebx
+       subl -44(%ebp),%eax
+       movl %eax,%esi
+       cmpl 28(%ebp),%ebx
+       jge .L496
+       testl %ecx,%ecx
+       jl .L496
+       cmpl 32(%ebp),%esi
+       jge .L496
+       testl %eax,%eax
+       jge .L499
+.L496:
+       xorl %esi,%esi
+       xorl %ebx,%ebx
+.L499:
+       movl 20(%ebp),%eax
+       movl %ebx,%edx
+       leal (%eax,%edx,4),%edx
+       movl 28(%ebp),%eax
+       imull %esi,%eax
+       leal (%edx,%eax,4),%eax
+       testl %ebx,%ebx
+       je .L494
+       testl %esi,%esi
+       je .L494
+#APP
+       movd (%eax), %mm0
+       paddusb 12(%ebp), %mm0
+       movd %mm0, (%eax)
+#NO_APP
+.L494:
+       incl -20(%ebp)
+       addl $12,%edi
+       movl -20(%ebp),%eax
+       movl 8(%ebp),%edx
+       cmpl 8(%edx),%eax
+       jl .L495
+       fstp %st(0)
+       fstp %st(0)
+.L493:
+       popl %ebx
+       popl %esi
+       popl %edi
+       leave
+       ret
+.Lfe3:
+       .size    surf3d_draw,.Lfe3-surf3d_draw
+       .align 4
+.globl surf3d_rotate
+       .type    surf3d_rotate,@function
+surf3d_rotate:
+       pushl %ebp
+       movl %esp,%ebp
+       subl $32,%esp
+       pushl %esi
+       pushl %ebx
+       flds 12(%ebp)
+       movl 8(%ebp),%ebx
+       fld %st(0)
+#APP
+       fsin
+#NO_APP
+       fstps -4(%ebp)
+       flds -4(%ebp)
+       fxch %st(1)
+#APP
+       fcos
+#NO_APP
+       fstps -4(%ebp)
+       xorl %esi,%esi
+       flds -4(%ebp)
+       cmpl 8(%ebx),%esi
+       jge .L537
+       xorl %ecx,%ecx
+       .p2align 4,,7
+.L508:
+       movl (%ebx),%eax
+       flds (%eax,%ecx)
+       flds 8(%eax,%ecx)
+       fmul %st(2),%st
+       fxch %st(1)
+       fmul %st(3),%st
+       fsubp %st,%st(1)
+       movl 4(%ebx),%edx
+       incl %esi
+       fstps (%edx,%ecx)
+       movl (%ebx),%eax
+       flds (%eax,%ecx)
+       flds 8(%eax,%ecx)
+       fxch %st(1)
+       fmul %st(2),%st
+       fxch %st(1)
+       fmul %st(3),%st
+       faddp %st,%st(1)
+       movl 4(%ebx),%edx
+       fstps 8(%edx,%ecx)
+       movl (%ebx),%eax
+       flds 4(%eax,%ecx)
+       movl 4(%ebx),%edx
+       fstps 4(%edx,%ecx)
+       addl $12,%ecx
+       cmpl 8(%ebx),%esi
+       jl .L508
+.L537:
+       fstp %st(0)
+       fstp %st(0)
+       popl %ebx
+       popl %esi
+       leave
+       ret
+.Lfe4:
+       .size    surf3d_rotate,.Lfe4-surf3d_rotate
+       .align 4
+.globl surf3d_translate
+       .type    surf3d_translate,@function
+surf3d_translate:
+       pushl %ebp
+       movl %esp,%ebp
+       pushl %ebx
+       movl 8(%ebp),%ecx
+       xorl %ebx,%ebx
+       cmpl 8(%ecx),%ebx
+       jge .L512
+       xorl %edx,%edx
+       .p2align 4,,7
+.L514:
+       movl 4(%ecx),%eax
+       flds (%eax,%edx)
+       fadds 12(%ecx)
+       incl %ebx
+       fstps (%eax,%edx)
+       movl 4(%ecx),%eax
+       flds 4(%eax,%edx)
+       fadds 16(%ecx)
+       fstps 4(%eax,%edx)
+       movl 4(%ecx),%eax
+       flds 8(%eax,%edx)
+       fadds 20(%ecx)
+       fstps 8(%eax,%edx)
+       addl $12,%edx
+       cmpl 8(%ecx),%ebx
+       jl .L514
+.L512:
+       popl %ebx
+       leave
+       ret
+.Lfe5:
+       .size    surf3d_translate,.Lfe5-surf3d_translate
+       .ident  "GCC: (GNU) 2.95.3 19991030 (prerelease)"
diff --git a/gst/goom/tentacle3d.c b/gst/goom/tentacle3d.c
new file mode 100644 (file)
index 0000000..4450393
--- /dev/null
@@ -0,0 +1,333 @@
+#include <stdlib.h>
+
+#include "v3d.h"
+#include "surf3d.h"
+#include "goom_tools.h"
+#include "goom_config.h"
+#include "goom_plugin_info.h"
+#include "tentacle3d.h"
+
+#define D 256.0f
+
+#define nbgrid 6
+#define definitionx 15
+#define definitionz 45
+
+typedef struct _TENTACLE_FX_DATA
+{
+  PluginParam enabled_bp;
+  PluginParameters params;
+
+  float cycle;
+  grid3d *grille[nbgrid];
+  float *vals;
+
+#define NB_TENTACLE_COLORS 4
+  int colors[NB_TENTACLE_COLORS];
+
+  int col;
+  int dstcol;
+  float lig;
+  float ligs;
+
+  /* statics from pretty_move */
+  float distt;
+  float distt2;
+  float rot;                    /* entre 0 et 2 * M_PI */
+  int happens;
+  int rotation;
+  int lock;
+} TentacleFXData;
+
+static void tentacle_new (TentacleFXData * data);
+static void tentacle_update (PluginInfo * goomInfo, Pixel * buf, Pixel * back,
+    int W, int H, short[2][512], float, int drawit, TentacleFXData * data);
+static void tentacle_free (TentacleFXData * data);
+
+/* 
+ * VisualFX wrapper for the tentacles
+ */
+
+static void
+tentacle_fx_init (VisualFX * _this, PluginInfo * info)
+{
+
+  TentacleFXData *data = (TentacleFXData *) malloc (sizeof (TentacleFXData));
+
+  data->enabled_bp = secure_b_param ("Enabled", 1);
+  data->params = plugin_parameters ("3D Tentacles", 1);
+  data->params.params[0] = &data->enabled_bp;
+
+  data->cycle = 0.0f;
+  data->col =
+      (0x28 << (ROUGE * 8)) | (0x2c << (VERT * 8)) | (0x5f << (BLEU * 8));
+  data->dstcol = 0;
+  data->lig = 1.15f;
+  data->ligs = 0.1f;
+
+  data->distt = 10.0f;
+  data->distt2 = 0.0f;
+  data->rot = 0.0f;             /* entre 0 et 2 * M_PI */
+  data->happens = 0;
+
+  data->rotation = 0;
+  data->lock = 0;
+  data->colors[0] =
+      (0x18 << (ROUGE * 8)) | (0x4c << (VERT * 8)) | (0x2f << (BLEU * 8));
+  data->colors[1] =
+      (0x48 << (ROUGE * 8)) | (0x2c << (VERT * 8)) | (0x6f << (BLEU * 8));
+  data->colors[2] =
+      (0x58 << (ROUGE * 8)) | (0x3c << (VERT * 8)) | (0x0f << (BLEU * 8));
+  data->colors[3] =
+      (0x87 << (ROUGE * 8)) | (0x55 << (VERT * 8)) | (0x74 << (BLEU * 8));
+  tentacle_new (data);
+
+  _this->params = &data->params;
+  _this->fx_data = (void *) data;
+}
+
+static void
+tentacle_fx_apply (VisualFX * _this, Pixel * src, Pixel * dest,
+    PluginInfo * goomInfo)
+{
+  TentacleFXData *data = (TentacleFXData *) _this->fx_data;
+
+  if (BVAL (data->enabled_bp)) {
+    tentacle_update (goomInfo, dest, src, goomInfo->screen.width,
+        goomInfo->screen.height, goomInfo->sound.samples,
+        (float) goomInfo->sound.accelvar,
+        goomInfo->curGState->drawTentacle, data);
+  }
+}
+
+static void
+tentacle_fx_free (VisualFX * _this)
+{
+  tentacle_free ((TentacleFXData *) _this->fx_data);
+  free (_this->fx_data);
+}
+
+VisualFX
+tentacle_fx_create (void)
+{
+  VisualFX fx;
+
+  fx.init = tentacle_fx_init;
+  fx.apply = tentacle_fx_apply;
+  fx.free = tentacle_fx_free;
+  return fx;
+}
+
+/* ----- */
+
+static void
+tentacle_free (TentacleFXData * data)
+{
+  /* TODO : un vrai FREE GRID!! */
+  free (data->vals);
+}
+
+static void
+tentacle_new (TentacleFXData * data)
+{
+  int tmp;
+
+  v3d center = { 0, -17.0, 0 };
+  data->vals = (float *) malloc ((definitionx + 20) * sizeof (float));
+
+  for (tmp = 0; tmp < nbgrid; tmp++) {
+    int x, z;
+
+    z = 45 + rand () % 30;
+    x = 85 + rand () % 5;
+    center.z = z;
+    data->grille[tmp] =
+        grid3d_new (x, definitionx, z, definitionz + rand () % 10, center);
+    center.y += 8;
+  }
+}
+
+static inline unsigned char
+lighten (unsigned char value, float power)
+{
+  int val = value;
+  float t = (float) val * log10 (power) / 2.0;
+
+  if (t > 0) {
+    val = (int) t;              /* (32.0f * log (t)); */
+    if (val > 255)
+      val = 255;
+    if (val < 0)
+      val = 0;
+    return val;
+  } else {
+    return 0;
+  }
+}
+
+static void
+lightencolor (int *col, float power)
+{
+  unsigned char *color;
+
+  color = (unsigned char *) col;
+  *color = lighten (*color, power);
+  color++;
+  *color = lighten (*color, power);
+  color++;
+  *color = lighten (*color, power);
+  color++;
+  *color = lighten (*color, power);
+}
+
+/* retourne x>>s , en testant le signe de x */
+#define ShiftRight(_x,_s) ((_x<0) ? -(-_x>>_s) : (_x>>_s))
+
+static int
+evolutecolor (unsigned int src, unsigned int dest,
+    unsigned int mask, unsigned int incr)
+{
+
+  int color = src & (~mask);
+
+  src &= mask;
+  dest &= mask;
+
+  if ((src != mask)
+      && (src < dest))
+    src += incr;
+
+  if (src > dest)
+    src -= incr;
+  return (src & mask) | color;
+}
+
+static void
+pretty_move (PluginInfo * goomInfo, float cycle, float *dist, float *dist2,
+    float *rotangle, TentacleFXData * fx_data)
+{
+
+  float tmp;
+
+  /* many magic numbers here... I don't really like that. */
+  if (fx_data->happens)
+    fx_data->happens -= 1;
+  else if (fx_data->lock == 0) {
+    fx_data->happens =
+        goom_irand (goomInfo->gRandom,
+        200) ? 0 : 100 + goom_irand (goomInfo->gRandom, 60);
+    fx_data->lock = fx_data->happens * 3 / 2;
+  } else
+    fx_data->lock--;
+
+  tmp = fx_data->happens ? 8.0f : 0;
+  *dist2 = fx_data->distt2 = (tmp + 15.0f * fx_data->distt2) / 16.0f;
+
+  tmp = 30 + D - 90.0f * (1.0f + sin (cycle * 19 / 20));
+  if (fx_data->happens)
+    tmp *= 0.6f;
+
+  *dist = fx_data->distt = (tmp + 3.0f * fx_data->distt) / 4.0f;
+
+  if (!fx_data->happens) {
+    tmp = M_PI * sin (cycle) / 32 + 3 * M_PI / 2;
+  } else {
+    fx_data->rotation =
+        goom_irand (goomInfo->gRandom,
+        500) ? fx_data->rotation : goom_irand (goomInfo->gRandom, 2);
+    if (fx_data->rotation)
+      cycle *= 2.0f * M_PI;
+    else
+      cycle *= -1.0f * M_PI;
+    tmp = cycle - (M_PI * 2.0) * floor (cycle / (M_PI * 2.0));
+  }
+
+  if (abs (tmp - fx_data->rot) > abs (tmp - (fx_data->rot + 2.0 * M_PI))) {
+    fx_data->rot = (tmp + 15.0f * (fx_data->rot + 2 * M_PI)) / 16.0f;
+    if (fx_data->rot > 2.0 * M_PI)
+      fx_data->rot -= 2.0 * M_PI;
+    *rotangle = fx_data->rot;
+  } else if (abs (tmp - fx_data->rot) > abs (tmp - (fx_data->rot - 2.0 * M_PI))) {
+    fx_data->rot = (tmp + 15.0f * (fx_data->rot - 2.0 * M_PI)) / 16.0f;
+    if (fx_data->rot < 0.0f)
+      fx_data->rot += 2.0 * M_PI;
+    *rotangle = fx_data->rot;
+  } else
+    *rotangle = fx_data->rot = (tmp + 15.0f * fx_data->rot) / 16.0f;
+}
+
+static void
+tentacle_update (PluginInfo * goomInfo, Pixel * buf, Pixel * back, int W, int H,
+    short data[2][512], float rapport, int drawit, TentacleFXData * fx_data)
+{
+
+  int tmp;
+  int tmp2;
+
+  int color;
+  int colorlow;
+
+  float dist, dist2, rotangle;
+
+  if ((!drawit) && (fx_data->ligs > 0.0f))
+    fx_data->ligs = -fx_data->ligs;
+
+  fx_data->lig += fx_data->ligs;
+
+  if (fx_data->lig > 1.01f) {
+    if ((fx_data->lig > 10.0f) | (fx_data->lig < 1.1f))
+      fx_data->ligs = -fx_data->ligs;
+
+    if ((fx_data->lig < 6.3f) && (goom_irand (goomInfo->gRandom, 30) == 0))
+      fx_data->dstcol = goom_irand (goomInfo->gRandom, NB_TENTACLE_COLORS);
+
+    fx_data->col =
+        evolutecolor (fx_data->col, fx_data->colors[fx_data->dstcol], 0xff,
+        0x01);
+    fx_data->col =
+        evolutecolor (fx_data->col, fx_data->colors[fx_data->dstcol], 0xff00,
+        0x0100);
+    fx_data->col =
+        evolutecolor (fx_data->col, fx_data->colors[fx_data->dstcol], 0xff0000,
+        0x010000);
+    fx_data->col =
+        evolutecolor (fx_data->col, fx_data->colors[fx_data->dstcol],
+        0xff000000, 0x01000000);
+
+    color = fx_data->col;
+    colorlow = fx_data->col;
+
+    lightencolor (&color, fx_data->lig * 2.0f + 2.0f);
+    lightencolor (&colorlow, (fx_data->lig / 3.0f) + 0.67f);
+
+    rapport = 1.0f + 2.0f * (rapport - 1.0f);
+    rapport *= 1.2f;
+    if (rapport > 1.12f)
+      rapport = 1.12f;
+
+    pretty_move (goomInfo, fx_data->cycle, &dist, &dist2, &rotangle, fx_data);
+
+    for (tmp = 0; tmp < nbgrid; tmp++) {
+      for (tmp2 = 0; tmp2 < definitionx; tmp2++) {
+        float val =
+            (float) (ShiftRight (data[0][goom_irand (goomInfo->gRandom, 511)],
+                10)) * rapport;
+        fx_data->vals[tmp2] = val;
+      }
+
+      grid3d_update (fx_data->grille[tmp], rotangle, fx_data->vals, dist2);
+    }
+    fx_data->cycle += 0.01f;
+    for (tmp = 0; tmp < nbgrid; tmp++)
+      grid3d_draw (goomInfo, fx_data->grille[tmp], color, colorlow, dist, buf,
+          back, W, H);
+  } else {
+    fx_data->lig = 1.05f;
+    if (fx_data->ligs < 0.0f)
+      fx_data->ligs = -fx_data->ligs;
+    pretty_move (goomInfo, fx_data->cycle, &dist, &dist2, &rotangle, fx_data);
+    fx_data->cycle += 0.1f;
+    if (fx_data->cycle > 1000)
+      fx_data->cycle = 0;
+  }
+}
diff --git a/gst/goom/tentacle3d.h b/gst/goom/tentacle3d.h
new file mode 100644 (file)
index 0000000..ad0858f
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _TENTACLE3D_H
+#define _TENTACLE3D_H
+
+#include "goom_visual_fx.h"
+
+VisualFX tentacle_fx_create(void);
+
+#endif
diff --git a/gst/goom/v3d.c b/gst/goom/v3d.c
new file mode 100644 (file)
index 0000000..54e3c97
--- /dev/null
@@ -0,0 +1,20 @@
+#include "v3d.h"
+
+void
+v3d_to_v2d (v3d * v3, int nbvertex, int width, int height, float distance,
+    v2d * v2)
+{
+  int i;
+
+  for (i = 0; i < nbvertex; ++i) {
+    if (v3[i].z > 2) {
+      int Xp, Yp;
+
+      F2I ((distance * v3[i].x / v3[i].z), Xp);
+      F2I ((distance * v3[i].y / v3[i].z), Yp);
+      v2[i].x = Xp + (width >> 1);
+      v2[i].y = -Yp + (height >> 1);
+    } else
+      v2[i].x = v2[i].y = -666;
+  }
+}
diff --git a/gst/goom/v3d.h b/gst/goom/v3d.h
new file mode 100644 (file)
index 0000000..7690847
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef _V3D_H
+#define _V3D_H
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "mathtools.h"
+
+typedef struct {
+    float x,y,z;
+} v3d;
+
+typedef struct {
+    int x,y;
+} v2d;
+
+typedef struct {
+    double x,y;
+} v2g;
+
+/* 
+ * projete le vertex 3D sur le plan d'affichage
+ * retourne (0,0) si le point ne doit pas etre affiche.
+ *
+ * bonne valeur pour distance : 256
+ */
+#define V3D_TO_V2D(v3,v2,width,height,distance) \
+{ \
+  int Xp, Yp; \
+  if (v3.z > 2) { \
+        F2I((distance * v3.x / v3.z),Xp) ; \
+        F2I((distance * v3.y / v3.z),Yp) ; \
+        v2.x = Xp + (width>>1); \
+        v2.y = -Yp + (height>>1); \
+  } \
+  else v2.x=v2.y=-666; \
+}
+
+void v3d_to_v2d(v3d *src, int nbvertex, int width, int height, float distance, v2d *v2_array);
+
+/*
+ * rotation selon Y du v3d vi d'angle a (cosa=cos(a), sina=sin(a))
+ * centerz = centre de rotation en z
+ */
+#define Y_ROTATE_V3D(vi,vf,sina,cosa)\
+{\
+ vf.x = vi.x * cosa - vi.z * sina;\
+ vf.z = vi.x * sina + vi.z * cosa;\
+ vf.y = vi.y;\
+}
+
+/*
+ * translation
+ */
+#define TRANSLATE_V3D(vsrc,vdest)\
+{\
+ vdest.x += vsrc.x;\
+ vdest.y += vsrc.y;\
+ vdest.z += vsrc.z;\
+}
+
+#define MUL_V3D(lf,v) {v.x*=lf;v.y*=lf;v.z*=lf;}
+
+#endif
diff --git a/gst/goom/xmmx.c b/gst/goom/xmmx.c
new file mode 100644 (file)
index 0000000..40f27fb
--- /dev/null
@@ -0,0 +1,364 @@
+
+#ifdef HAVE_MMX
+
+/* a definir pour avoir exactement le meme resultat que la fonction C
+ * (un chouillat plus lent).. mais la difference est assez peu notable.
+ */
+// #define STRICT_COMPAT
+
+#define BUFFPOINTNB 16
+#define BUFFPOINTMASK 0xffff
+#define BUFFINCR 0xff
+
+#define sqrtperte 16
+/* faire : a % sqrtperte <=> a & pertemask*/
+#define PERTEMASK 0xf
+/* faire : a / sqrtperte <=> a >> PERTEDEC*/
+#define PERTEDEC 4
+
+
+/*#define MMX_TRACE*/
+#include "mmx.h"
+/*#include "xmmx.h"*/
+#include "goom_graphic.h"
+
+int
+xmmx_supported (void)
+{
+  return (mm_support () & 0x8) >> 3;
+}
+
+void
+zoom_filter_xmmx (int prevX, int prevY,
+    Pixel * expix1, Pixel * expix2,
+    int *lbruS, int *lbruD, int buffratio, int precalCoef[16][16])
+{
+  int bufsize = prevX * prevY;  /* taille du buffer */
+  volatile int loop;            /* variable de boucle */
+
+  mmx_t *brutS = (mmx_t *) lbruS;       /* buffer de transformation source */
+  mmx_t *brutD = (mmx_t *) lbruD;       /* buffer de transformation dest */
+
+  volatile mmx_t prevXY;
+  volatile mmx_t ratiox;
+
+  /*      volatile mmx_t interpix; */
+
+  expix1[0].val = expix1[prevX - 1].val = expix1[prevX * prevY - 1].val =
+      expix1[prevX * prevY - prevX].val = 0;
+
+  prevXY.ud[0] = (prevX - 1) << PERTEDEC;
+  prevXY.ud[1] = (prevY - 1) << PERTEDEC;
+
+  ratiox.d[0] = buffratio;
+  ratiox.d[1] = buffratio;
+
+  asm volatile ("\n\t movq  %[ratio], %%mm6" "\n\t pslld $16,      %%mm6"       /* mm6 = [rat16=buffratio<<16 | rat16=buffratio<<16] */
+      "\n\t pxor  %%mm7,    %%mm7"      /* mm7 = 0 */
+      ::[ratio] "m" (ratiox));
+
+  loop = 0;
+
+  /*
+   * NOTE : mm6 et mm7 ne sont pas modifies dans la boucle.
+   */
+  while (loop < bufsize) {
+    /* Thread #1
+     * pre :  mm6 = [rat16|rat16]
+     * post : mm0 = S + ((D-S)*rat16 format [X|Y]
+     * modified = mm0,mm1,mm2
+     */
+
+    asm volatile ("#1 \n\t movq %[brutS], %%mm0" "#1 \n\t movq %[brutD], %%mm1" "#1 \n\t psubd   %%mm0, %%mm1"  /* mm1 = D - S */
+        "#1 \n\t movq    %%mm1, %%mm2"  /* mm2 = D - S */
+        "#1 \n\t pslld     $16, %%mm1" "#1 \n\t pmullw  %%mm6, %%mm2" "#1 \n\t pmulhuw %%mm6, %%mm1" "#1 \n\t pslld   $16,   %%mm0" "#1 \n\t paddd   %%mm2, %%mm1"      /* mm1 = (D - S) * buffratio >> 16 */
+        "#1 \n\t paddd   %%mm1, %%mm0"  /* mm0 = S + mm1 */
+        "#1 \n\t psrld   $16,   %%mm0"::[brutS] "g" (brutS[loop])
+        ,[brutD] "g" (brutD[loop])
+        );                      /* mm0 = S */
+
+    /*
+     * pre : mm0 : position vector on screen
+     *       prevXY : coordinate of the lower-right point on screen
+     * post : clipped mm0
+     * modified : mm0,mm1,mm2
+     */
+    asm volatile
+        ("#1 \n\t movq %[prevXY], %%mm1" "#1 \n\t pcmpgtd %%mm0,  %%mm1"
+        /* mm0 en X contient (idem pour Y) :
+         *   1111 si prevXY > px
+         *   0000 si prevXY <= px */
+#ifdef STRICT_COMPAT
+        "#1 \n\t movq      %%mm1, %%mm2"
+        "#1 \n\t punpckhdq %%mm2, %%mm2"
+        "#1 \n\t punpckldq %%mm1, %%mm1" "#1 \n\t pand      %%mm2, %%mm0"
+#endif
+        "#1 \n\t pand %%mm1, %%mm0"     /* on met a zero la partie qui deborde */
+        ::[prevXY] "m" (prevXY));
+
+    /* Thread #2
+     * pre :  mm0 : clipped position on screen
+     *
+     * post : mm3 : coefs for this position
+     *        mm1 : X vector [0|X]
+     *
+     * modif : eax,esi
+     */
+    __asm__ __volatile__ ("#2 \n\t movd %%mm0,%%esi"
+        "#2 \n\t movq %%mm0,%%mm1"
+        "#2 \n\t andl $15,%%esi"
+        "#2 \n\t psrlq $32,%%mm1"
+        "#2 \n\t shll $6,%%esi"
+        "#2 \n\t movd %%mm1,%%eax"
+        "#2 \n\t addl %[precalCoef],%%esi"
+        "#2 \n\t andl $15,%%eax"
+        "#2 \n\t movd (%%esi,%%eax,4),%%mm3"::[precalCoef]
+        "g" (precalCoef):"eax", "esi");
+
+    /*
+     * extraction des coefficients... (Thread #3)
+     *
+     * pre : coef dans mm3
+     *
+     * post : coef extraits dans mm3 (c1 & c2)
+     *                        et mm4 (c3 & c4)
+     *
+     * modif : mm5
+     */
+
+    /* (Thread #4)
+     * pre : mm0 : Y pos [*|Y]
+     *       mm1 : X pos [*|X]
+     *
+     * post : mm0 : expix1[position]
+     *        mm2 : expix1[position+largeur]
+     *
+     * modif : eax, esi
+     */
+    __asm__ __volatile__ ("#2 \n\t psrld $4, %%mm0" "#2 \n\t psrld $4, %%mm1"   /* PERTEDEC = $4 */
+        "#4 \n\t movd %%mm1,%%eax"
+        "#3 \n\t movq %%mm3,%%mm5"
+        "#4 \n\t mull %[prevX]"
+        "#4 \n\t movd %%mm0,%%esi"
+        "#3 \n\t punpcklbw %%mm5, %%mm3"
+        "#4 \n\t addl %%esi, %%eax"
+        "#3 \n\t movq %%mm3, %%mm4"
+        "#3 \n\t movq %%mm3, %%mm5"
+        "#4 \n\t movl %[expix1], %%esi"
+        "#3 \n\t punpcklbw %%mm5, %%mm3"
+        "#4 \n\t movq (%%esi,%%eax,4),%%mm0"
+        "#3 \n\t punpckhbw %%mm5, %%mm4"
+        "#4 \n\t addl %[prevX],%%eax"
+        "#4 \n\t movq (%%esi,%%eax,4),%%mm2"::[expix1] "g" (expix1)
+        ,[prevX] "g" (prevX)
+        :"eax", "esi");
+
+    /*
+     * pre :       mm0 : expix1[position]
+     *             mm2 : expix1[position+largeur]
+     *       mm3 & mm4 : coefs
+     */
+
+    /* recopie des deux premiers pixels dans mm0 et mm1 */
+    movq_r2r (mm0, mm1);        /* b1-v1-r1-a1-b2-v2-r2-a2 */
+
+    /* depackage du premier pixel */
+    punpcklbw_r2r (mm7, mm0);   /* 00-b2-00-v2-00-r2-00-a2 */
+
+    /* extraction des coefficients... */
+
+    movq_r2r (mm3, mm5);        /* c2-c2-c2-c2-c1-c1-c1-c1 */
+
+    /*^en parrallele^ *//* depackage du 2ieme pixel */
+                                        /*^ */ punpckhbw_r2r (mm7, mm1);
+                                        /* 00-b1-00-v1-00-r1-00-a1 */
+
+    punpcklbw_r2r (mm7, mm5);   /* 00-c1-00-c1-00-c1-00-c1 */
+    punpckhbw_r2r (mm7, mm3);   /* 00-c2-00-c2-00-c2-00-c2 */
+
+    /* multiplication des pixels par les coefficients */
+    pmullw_r2r (mm5, mm0);      /* c1*b2-c1*v2-c1*r2-c1*a2 */
+    pmullw_r2r (mm3, mm1);      /* c2*b1-c2*v1-c2*r1-c2*a1 */
+    paddw_r2r (mm1, mm0);
+
+    /* ...extraction des 2 derniers coefficients */
+    movq_r2r (mm4, mm5);        /* c4-c4-c4-c4-c3-c3-c3-c3 */
+    punpcklbw_r2r (mm7, mm4);   /* 00-c3-00-c3-00-c3-00-c3 */
+    punpckhbw_r2r (mm7, mm5);   /* 00-c4-00-c4-00-c4-00-c4 */
+
+    /* recuperation des 2 derniers pixels */
+    movq_r2r (mm2, mm1);
+
+    /* depackage des pixels */
+    punpcklbw_r2r (mm7, mm1);
+    punpckhbw_r2r (mm7, mm2);
+
+    /* multiplication pas les coeffs */
+    pmullw_r2r (mm4, mm1);
+    pmullw_r2r (mm5, mm2);
+
+    /* ajout des valeurs obtenues Ã  la valeur finale */
+    paddw_r2r (mm1, mm0);
+    paddw_r2r (mm2, mm0);
+
+    /* division par 256 = 16+16+16+16, puis repackage du pixel final */
+    psrlw_i2r (8, mm0);
+    packuswb_r2r (mm7, mm0);
+
+    movd_r2m (mm0, expix2[loop]);
+
+    ++loop;
+  }
+  __asm__ __volatile__ ("femms\n");
+}
+
+#define DRAWMETHOD_PLUS_XMMX(_out,_backbuf,_col) \
+{ \
+       movd_m2r(_backbuf, mm0); \
+       paddusb_m2r(_col, mm0); \
+       movd_r2m(mm0, _out); \
+}
+
+#define DRAWMETHOD DRAWMETHOD_PLUS_XMMX(*p,*p,col)
+
+void
+draw_line_xmmx (Pixel * data, int x1, int y1, int x2, int y2, int col,
+    int screenx, int screeny)
+{
+  int x, y, dx, dy, yy, xx;
+  Pixel *p;
+
+  if ((y1 < 0) || (y2 < 0) || (x1 < 0) || (x2 < 0) || (y1 >= screeny)
+      || (y2 >= screeny) || (x1 >= screenx) || (x2 >= screenx))
+    goto end_of_line;
+
+  dx = x2 - x1;
+  dy = y2 - y1;
+  if (x1 >= x2) {
+    int tmp;
+
+    tmp = x1;
+    x1 = x2;
+    x2 = tmp;
+    tmp = y1;
+    y1 = y2;
+    y2 = tmp;
+    dx = x2 - x1;
+    dy = y2 - y1;
+  }
+
+  /* vertical line */
+  if (dx == 0) {
+    if (y1 < y2) {
+      p = &(data[(screenx * y1) + x1]);
+      for (y = y1; y <= y2; y++) {
+        DRAWMETHOD;
+        p += screenx;
+      }
+    } else {
+      p = &(data[(screenx * y2) + x1]);
+      for (y = y2; y <= y1; y++) {
+        DRAWMETHOD;
+        p += screenx;
+      }
+    }
+    goto end_of_line;
+  }
+  /* horizontal line */
+  if (dy == 0) {
+    if (x1 < x2) {
+      p = &(data[(screenx * y1) + x1]);
+      for (x = x1; x <= x2; x++) {
+        DRAWMETHOD;
+        p++;
+      }
+      goto end_of_line;
+    } else {
+      p = &(data[(screenx * y1) + x2]);
+      for (x = x2; x <= x1; x++) {
+        DRAWMETHOD;
+        p++;
+      }
+      goto end_of_line;
+    }
+  }
+  /* 1    */
+  /*  \   */
+  /*   \  */
+  /*    2 */
+  if (y2 > y1) {
+    /* steep */
+    if (dy > dx) {
+      dx = ((dx << 16) / dy);
+      x = x1 << 16;
+      for (y = y1; y <= y2; y++) {
+        xx = x >> 16;
+        p = &(data[(screenx * y) + xx]);
+        DRAWMETHOD;
+        if (xx < (screenx - 1)) {
+          p++;
+          /* DRAWMETHOD; */
+        }
+        x += dx;
+      }
+      goto end_of_line;
+    }
+    /* shallow */
+    else {
+      dy = ((dy << 16) / dx);
+      y = y1 << 16;
+      for (x = x1; x <= x2; x++) {
+        yy = y >> 16;
+        p = &(data[(screenx * yy) + x]);
+        DRAWMETHOD;
+        if (yy < (screeny - 1)) {
+          p += screeny;
+          /* DRAWMETHOD; */
+        }
+        y += dy;
+      }
+    }
+  }
+  /*    2 */
+  /*   /  */
+  /*  /   */
+  /* 1    */
+  else {
+    /* steep */
+    if (-dy > dx) {
+      dx = ((dx << 16) / -dy);
+      x = (x1 + 1) << 16;
+      for (y = y1; y >= y2; y--) {
+        xx = x >> 16;
+        p = &(data[(screenx * y) + xx]);
+        DRAWMETHOD;
+        if (xx < (screenx - 1)) {
+          p--;
+          /* DRAWMETHOD; */
+        }
+        x += dx;
+      }
+      goto end_of_line;
+    }
+    /* shallow */
+    else {
+      dy = ((dy << 16) / dx);
+      y = y1 << 16;
+      for (x = x1; x <= x2; x++) {
+        yy = y >> 16;
+        p = &(data[(screenx * yy) + x]);
+        DRAWMETHOD;
+        if (yy < (screeny - 1)) {
+          p += screeny;
+          /* DRAWMETHOD; */
+        }
+        y += dy;
+      }
+      goto end_of_line;
+    }
+  }
+end_of_line:
+  __asm__ __volatile__ ("femms\n");
+}
+
+#endif
diff --git a/gst/goom/xmmx.h b/gst/goom/xmmx.h
new file mode 100644 (file)
index 0000000..70ef361
--- /dev/null
@@ -0,0 +1,537 @@
+/*     xmmx.h
+
+       eXtended MultiMedia eXtensions GCC interface library for IA32.
+
+       To use this library, simply include this header file
+       and compile with GCC.  You MUST have inlining enabled
+       in order for xmmx_ok() to work; this can be done by
+       simply using -O on the GCC command line.
+
+       Compiling with -DXMMX_TRACE will cause detailed trace
+       output to be sent to stderr for each mmx operation.
+       This adds lots of code, and obviously slows execution to
+       a crawl, but can be very useful for debugging.
+
+       THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+       LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+       AND FITNESS FOR ANY PARTICULAR PURPOSE.
+
+       1999 by R. Fisher
+       Based on libmmx, 1997-99 by H. Dietz and R. Fisher
+
+ Notes:
+       It appears that the latest gas has the pand problem fixed, therefore
+         I'll undefine BROKEN_PAND by default.
+*/
+
+#ifndef _XMMX_H
+#define _XMMX_H
+
+
+/*     Warning:  at this writing, the version of GAS packaged
+       with most Linux distributions does not handle the
+       parallel AND operation mnemonic correctly.  If the
+       symbol BROKEN_PAND is defined, a slower alternative
+       coding will be used.  If execution of mmxtest results
+       in an illegal instruction fault, define this symbol.
+*/
+#undef BROKEN_PAND
+
+
+/*     The type of an value that fits in an (Extended) MMX register
+       (note that long long constant values MUST be suffixed
+        by LL and unsigned long long values by ULL, lest
+        they be truncated by the compiler)
+*/
+#ifndef _MMX_H
+typedef        union {
+       long long               q;      /* Quadword (64-bit) value */
+       unsigned long long      uq;     /* Unsigned Quadword */
+       int                     d[2];   /* 2 Doubleword (32-bit) values */
+       unsigned int            ud[2];  /* 2 Unsigned Doubleword */
+       short                   w[4];   /* 4 Word (16-bit) values */
+       unsigned short          uw[4];  /* 4 Unsigned Word */
+       char                    b[8];   /* 8 Byte (8-bit) values */
+       unsigned char           ub[8];  /* 8 Unsigned Byte */
+       float                   s[2];   /* Single-precision (32-bit) value */
+} __attribute__ ((aligned (8))) mmx_t; /* On an 8-byte (64-bit) boundary */
+#endif
+
+
+
+/*     Function to test if multimedia instructions are supported...
+*/
+static int
+mm_support(void)
+{
+       /* Returns 1 if MMX instructions are supported,
+          3 if Cyrix MMX and Extended MMX instructions are supported
+          5 if AMD MMX and 3DNow! instructions are supported
+          0 if hardware does not support any of these
+       */
+       register int rval = 0;
+
+       __asm__ __volatile__ (
+               /* See if CPUID instruction is supported ... */
+               /* ... Get copies of EFLAGS into eax and ecx */
+               "pushf\n\t"
+               "popl %%eax\n\t"
+               "movl %%eax, %%ecx\n\t"
+
+               /* ... Toggle the ID bit in one copy and store */
+               /*     to the EFLAGS reg */
+               "xorl $0x200000, %%eax\n\t"
+               "push %%eax\n\t"
+               "popf\n\t"
+
+               /* ... Get the (hopefully modified) EFLAGS */
+               "pushf\n\t"
+               "popl %%eax\n\t"
+
+               /* ... Compare and test result */
+               "xorl %%eax, %%ecx\n\t"
+               "testl $0x200000, %%ecx\n\t"
+               "jz NotSupported1\n\t"          /* CPUID not supported */
+
+
+               /* Get standard CPUID information, and
+                      go to a specific vendor section */
+               "movl $0, %%eax\n\t"
+               "cpuid\n\t"
+
+               /* Check for Intel */
+               "cmpl $0x756e6547, %%ebx\n\t"
+               "jne TryAMD\n\t"
+               "cmpl $0x49656e69, %%edx\n\t"
+               "jne TryAMD\n\t"
+               "cmpl $0x6c65746e, %%ecx\n"
+               "jne TryAMD\n\t"
+               "jmp Intel\n\t"
+
+               /* Check for AMD */
+               "\nTryAMD:\n\t"
+               "cmpl $0x68747541, %%ebx\n\t"
+               "jne TryCyrix\n\t"
+               "cmpl $0x69746e65, %%edx\n\t"
+               "jne TryCyrix\n\t"
+               "cmpl $0x444d4163, %%ecx\n"
+               "jne TryCyrix\n\t"
+               "jmp AMD\n\t"
+
+               /* Check for Cyrix */
+               "\nTryCyrix:\n\t"
+               "cmpl $0x69727943, %%ebx\n\t"
+               "jne NotSupported2\n\t"
+               "cmpl $0x736e4978, %%edx\n\t"
+               "jne NotSupported3\n\t"
+               "cmpl $0x64616574, %%ecx\n\t"
+               "jne NotSupported4\n\t"
+               /* Drop through to Cyrix... */
+
+
+               /* Cyrix Section */
+               /* See if extended CPUID level 80000001 is supported */
+               /* The value of CPUID/80000001 for the 6x86MX is undefined
+                  according to the Cyrix CPU Detection Guide (Preliminary
+                  Rev. 1.01 table 1), so we'll check the value of eax for
+                  CPUID/0 to see if standard CPUID level 2 is supported.
+                  According to the table, the only CPU which supports level
+                  2 is also the only one which supports extended CPUID levels.
+               */
+               "cmpl $0x2, %%eax\n\t"
+               "jne MMXtest\n\t"       /* Use standard CPUID instead */
+
+               /* Extended CPUID supported (in theory), so get extended
+                  features */
+               "movl $0x80000001, %%eax\n\t"
+               "cpuid\n\t"
+               "testl $0x00800000, %%eax\n\t"  /* Test for MMX */
+               "jz NotSupported5\n\t"          /* MMX not supported */
+               "testl $0x01000000, %%eax\n\t"  /* Test for Ext'd MMX */
+               "jnz EMMXSupported\n\t"
+               "movl $1, %0:\n\n\t"            /* MMX Supported */
+               "jmp Return\n\n"
+               "EMMXSupported:\n\t"
+               "movl $3, %0:\n\n\t"            /* EMMX and MMX Supported */
+               "jmp Return\n\t"
+
+
+               /* AMD Section */
+               "AMD:\n\t"
+
+               /* See if extended CPUID is supported */
+               "movl $0x80000000, %%eax\n\t"
+               "cpuid\n\t"
+               "cmpl $0x80000000, %%eax\n\t"
+               "jl MMXtest\n\t"        /* Use standard CPUID instead */
+
+               /* Extended CPUID supported, so get extended features */
+               "movl $0x80000001, %%eax\n\t"
+               "cpuid\n\t"
+               "testl $0x00800000, %%edx\n\t"  /* Test for MMX */
+               "jz NotSupported6\n\t"          /* MMX not supported */
+               "testl $0x80000000, %%edx\n\t"  /* Test for 3DNow! */
+               "jnz ThreeDNowSupported\n\t"
+               "movl $1, %0:\n\n\t"            /* MMX Supported */
+               "jmp Return\n\n"
+               "ThreeDNowSupported:\n\t"
+               "movl $5, %0:\n\n\t"            /* 3DNow! and MMX Supported */
+               "jmp Return\n\t"
+
+
+               /* Intel Section */
+               "Intel:\n\t"
+
+               /* Check for MMX */
+               "MMXtest:\n\t"
+               "movl $1, %%eax\n\t"
+               "cpuid\n\t"
+               "testl $0x00800000, %%edx\n\t"  /* Test for MMX */
+               "jz NotSupported7\n\t"          /* MMX Not supported */
+               "movl $1, %0:\n\n\t"            /* MMX Supported */
+               "jmp Return\n\t"
+
+               /* Nothing supported */
+               "\nNotSupported1:\n\t"
+               "#movl $101, %0:\n\n\t"
+               "\nNotSupported2:\n\t"
+               "#movl $102, %0:\n\n\t"
+               "\nNotSupported3:\n\t"
+               "#movl $103, %0:\n\n\t"
+               "\nNotSupported4:\n\t"
+               "#movl $104, %0:\n\n\t"
+               "\nNotSupported5:\n\t"
+               "#movl $105, %0:\n\n\t"
+               "\nNotSupported6:\n\t"
+               "#movl $106, %0:\n\n\t"
+               "\nNotSupported7:\n\t"
+               "#movl $107, %0:\n\n\t"
+               "movl $0, %0:\n\n\t"
+
+               "Return:\n\t"
+               : "=a" (rval)
+               : /* no input */
+               : "eax", "ebx", "ecx", "edx"
+       );
+
+       /* Return */
+       return(rval);
+}
+
+/*     Function to test if mmx instructions are supported...
+*/
+#ifndef _XMMX_H
+inline extern int
+mmx_ok(void)
+{
+       /* Returns 1 if MMX instructions are supported, 0 otherwise */
+       return ( mm_support() & 0x1 );
+}
+#endif
+
+/*     Function to test if xmmx instructions are supported...
+*/
+inline extern int
+xmmx_ok(void)
+{
+       /* Returns 1 if Extended MMX instructions are supported, 0 otherwise */
+       return ( (mm_support() & 0x2) >> 1 );
+}
+
+
+/*     Helper functions for the instruction macros that follow...
+       (note that memory-to-register, m2r, instructions are nearly
+        as efficient as register-to-register, r2r, instructions;
+        however, memory-to-memory instructions are really simulated
+        as a convenience, and are only 1/3 as efficient)
+*/
+#ifdef XMMX_TRACE
+
+/*     Include the stuff for printing a trace to stderr...
+*/
+
+#include <stdio.h>
+
+#define        mmx_i2r(op, imm, reg) \
+       { \
+               mmx_t mmx_trace; \
+               mmx_trace.uq = (imm); \
+               fprintf(stderr, #op "_i2r(" #imm "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               fprintf(stderr, #reg "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ (#op " %0, %%" #reg \
+                                     : /* nothing */ \
+                                     : "X" (imm)); \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               fprintf(stderr, #reg "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#define        mmx_m2r(op, mem, reg) \
+       { \
+               mmx_t mmx_trace; \
+               mmx_trace = (mem); \
+               fprintf(stderr, #op "_m2r(" #mem "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               fprintf(stderr, #reg "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ (#op " %0, %%" #reg \
+                                     : /* nothing */ \
+                                     : "X" (mem)); \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               fprintf(stderr, #reg "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#define        mmx_r2m(op, reg, mem) \
+       { \
+               mmx_t mmx_trace; \
+               __asm__ __volatile__ ("movq %%" #reg ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               fprintf(stderr, #op "_r2m(" #reg "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               mmx_trace = (mem); \
+               fprintf(stderr, #mem "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ (#op " %%" #reg ", %0" \
+                                     : "=X" (mem) \
+                                     : /* nothing */ ); \
+               mmx_trace = (mem); \
+               fprintf(stderr, #mem "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#define        mmx_r2r(op, regs, regd) \
+       { \
+               mmx_t mmx_trace; \
+               __asm__ __volatile__ ("movq %%" #regs ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               fprintf(stderr, #op "_r2r(" #regs "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ ("movq %%" #regd ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               fprintf(stderr, #regd "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ (#op " %" #regs ", %" #regd); \
+               __asm__ __volatile__ ("movq %%" #regd ", %0" \
+                                     : "=X" (mmx_trace) \
+                                     : /* nothing */ ); \
+               fprintf(stderr, #regd "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#define        mmx_m2m(op, mems, memd) \
+       { \
+               mmx_t mmx_trace; \
+               mmx_trace = (mems); \
+               fprintf(stderr, #op "_m2m(" #mems "=0x%08x%08x, ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               mmx_trace = (memd); \
+               fprintf(stderr, #memd "=0x%08x%08x) => ", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+               __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+                                     #op " %1, %%mm0\n\t" \
+                                     "movq %%mm0, %0" \
+                                     : "=X" (memd) \
+                                     : "X" (mems)); \
+               mmx_trace = (memd); \
+               fprintf(stderr, #memd "=0x%08x%08x\n", \
+                       mmx_trace.d[1], mmx_trace.d[0]); \
+       }
+
+#else
+
+/*     These macros are a lot simpler without the tracing...
+*/
+
+#define        mmx_i2r(op, imm, reg) \
+       __asm__ __volatile__ (#op " %0, %%" #reg \
+                             : /* nothing */ \
+                             : "X" (imm) )
+
+#define        mmx_m2r(op, mem, reg) \
+       __asm__ __volatile__ (#op " %0, %%" #reg \
+                             : /* nothing */ \
+                             : "X" (mem))
+
+#define        mmx_m2ir(op, mem, rs) \
+       __asm__ __volatile__ (#op " %0, %%" #rs \
+                             : /* nothing */ \
+                             : "X" (mem) )
+
+#define        mmx_r2m(op, reg, mem) \
+       __asm__ __volatile__ (#op " %%" #reg ", %0" \
+                             : "=X" (mem) \
+                             : /* nothing */ )
+
+#define        mmx_r2r(op, regs, regd) \
+       __asm__ __volatile__ (#op " %" #regs ", %" #regd)
+
+#define        mmx_r2ir(op, rs1, rs2) \
+       __asm__ __volatile__ (#op " %%" #rs1 ", %%" #rs2 \
+                             : /* nothing */ \
+                             : /* nothing */ )
+
+#define        mmx_m2m(op, mems, memd) \
+       __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+                             #op " %1, %%mm0\n\t" \
+                             "movq %%mm0, %0" \
+                             : "=X" (memd) \
+                             : "X" (mems))
+
+#endif
+
+
+
+/*     1x64 MOVe Quadword
+       (this is both a load and a store...
+        in fact, it is the only way to store)
+*/
+#define        movq_m2r(var, reg)      mmx_m2r(movq, var, reg)
+#define        movq_r2m(reg, var)      mmx_r2m(movq, reg, var)
+#define        movq_r2r(regs, regd)    mmx_r2r(movq, regs, regd)
+#define        movq(vars, vard) \
+       __asm__ __volatile__ ("movq %1, %%mm0\n\t" \
+                             "movq %%mm0, %0" \
+                             : "=X" (vard) \
+                             : "X" (vars))
+
+
+/*     1x32 MOVe Doubleword
+       (like movq, this is both load and store...
+        but is most useful for moving things between
+        mmx registers and ordinary registers)
+*/
+#define        movd_m2r(var, reg)      mmx_m2r(movd, var, reg)
+#define        movd_r2m(reg, var)      mmx_r2m(movd, reg, var)
+#define        movd_r2r(regs, regd)    mmx_r2r(movd, regs, regd)
+#define        movd(vars, vard) \
+       __asm__ __volatile__ ("movd %1, %%mm0\n\t" \
+                             "movd %%mm0, %0" \
+                             : "=X" (vard) \
+                             : "X" (vars))
+
+
+
+/*     4x16 Parallel MAGnitude
+*/
+#define        pmagw_m2r(var, reg)     mmx_m2r(pmagw, var, reg)
+#define        pmagw_r2r(regs, regd)   mmx_r2r(pmagw, regs, regd)
+#define        pmagw(vars, vard)       mmx_m2m(pmagw, vars, vard)
+
+
+/*     4x16 Parallel ADDs using Saturation arithmetic
+       and Implied destination
+*/
+#define        paddsiw_m2ir(var, rs)           mmx_m2ir(paddsiw, var, rs)
+#define        paddsiw_r2ir(rs1, rs2)          mmx_r2ir(paddsiw, rs1, rs2)
+#define        paddsiw(vars, vard)             mmx_m2m(paddsiw, vars, vard)
+
+
+/*     4x16 Parallel SUBs using Saturation arithmetic
+       and Implied destination
+*/
+#define        psubsiw_m2ir(var, rs)           mmx_m2ir(psubsiw, var, rs)
+#define        psubsiw_r2ir(rs1, rs2)          mmx_r2ir(psubsiw, rs1, rs2)
+#define        psubsiw(vars, vard)             mmx_m2m(psubsiw, vars, vard)
+
+
+/*     4x16 Parallel MULs giving High 4x16 portions of results
+       Rounded with 1/2 bit 15.
+*/
+#define        pmulhrw_m2r(var, reg)   mmx_m2r(pmulhrw, var, reg)
+#define        pmulhrw_r2r(regs, regd) mmx_r2r(pmulhrw, regs, regd)
+#define        pmulhrw(vars, vard)     mmx_m2m(pmulhrw, vars, vard)
+
+
+/*     4x16 Parallel MULs giving High 4x16 portions of results
+       Rounded with 1/2 bit 15, storing to Implied register
+*/
+#define        pmulhriw_m2ir(var, rs)          mmx_m2ir(pmulhriw, var, rs)
+#define        pmulhriw_r2ir(rs1, rs2)         mmx_r2ir(pmulhriw, rs1, rs2)
+#define        pmulhriw(vars, vard)            mmx_m2m(pmulhriw, vars, vard)
+
+
+/*     4x16 Parallel Muls (and ACcumulate) giving High 4x16 portions
+       of results Rounded with 1/2 bit 15, accumulating with Implied register
+*/
+#define        pmachriw_m2ir(var, rs)          mmx_m2ir(pmachriw, var, rs)
+#define        pmachriw_r2ir(rs1, rs2)         mmx_r2ir(pmachriw, rs1, rs2)
+#define        pmachriw(vars, vard)            mmx_m2m(pmachriw, vars, vard)
+
+
+/*     8x8u Parallel AVErage
+*/
+#define        paveb_m2r(var, reg)     mmx_m2r(paveb, var, reg)
+#define        paveb_r2r(regs, regd)   mmx_r2r(paveb, regs, regd)
+#define        paveb(vars, vard)       mmx_m2m(paveb, vars, vard)
+
+
+/*     8x8u Parallel DISTance and accumulate with
+       unsigned saturation to Implied register
+*/
+#define        pdistib_m2ir(var, rs)           mmx_m2ir(pdistib, var, rs)
+#define        pdistib(vars, vard)             mmx_m2m(pdistib, vars, vard)
+
+
+/*     8x8 Parallel conditional MoVe
+       if implied register field is Zero
+*/
+#define        pmvzb_m2ir(var, rs)             mmx_m2ir(pmvzb, var, rs)
+
+
+/*     8x8 Parallel conditional MoVe
+       if implied register field is Not Zero
+*/
+#define        pmvnzb_m2ir(var, rs)            mmx_m2ir(pmvnzb, var, rs)
+
+
+/*     8x8 Parallel conditional MoVe
+       if implied register field is Less than Zero
+*/
+#define        pmvlzb_m2ir(var, rs)            mmx_m2ir(pmvlzb, var, rs)
+
+
+/*     8x8 Parallel conditional MoVe
+       if implied register field is Greater than or Equal to Zero
+*/
+#define        pmvgezb_m2ir(var, rs)           mmx_m2ir(pmvgezb, var, rs)
+
+
+/*     Fast Empty MMx State
+       (used to clean-up when going from mmx to float use
+        of the registers that are shared by both; note that
+        there is no float-to-xmmx operation needed, because
+        only the float tag word info is corruptible)
+*/
+#ifdef XMMX_TRACE
+
+#define        femms() \
+       { \
+               fprintf(stderr, "femms()\n"); \
+               __asm__ __volatile__ ("femms"); \
+       }
+
+#else
+
+#define        femms()                 __asm__ __volatile__ ("femms")
+
+#endif
+
+#endif
+
diff --git a/gst/goom2k1/Makefile.am b/gst/goom2k1/Makefile.am
new file mode 100644 (file)
index 0000000..4f4abb7
--- /dev/null
@@ -0,0 +1,14 @@
+plugin_LTLIBRARIES = libgstgoom.la
+
+GOOM_FILTER_FILES = filters.c
+GOOM_FILTER_CFLAGS = -UMMX -UUSE_ASM
+
+noinst_HEADERS = gstgoom.h filters.h goom_core.h goom_tools.h graphic.h lines.h 
+
+libgstgoom_la_SOURCES = gstgoom.c goom_core.c $(GOOM_FILTER_FILES) graphic.c lines.c
+
+libgstgoom_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GOOM_FILTER_CFLAGS)
+libgstgoom_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM)
+libgstgoom_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+EXTRA_DIST = filters.c
diff --git a/gst/goom2k1/README b/gst/goom2k1/README
new file mode 100644 (file)
index 0000000..f12cf1b
--- /dev/null
@@ -0,0 +1,5 @@
+The Goom plugin is based on the Goom visualization code from
+the Goom homepage found at: 
+http://ios.free.fr/?page=projet&quoi=1 
+
+Like the original library so is the Goom plugin available under the LGPL license
diff --git a/gst/goom2k1/filters.c b/gst/goom2k1/filters.c
new file mode 100644 (file)
index 0000000..b898e89
--- /dev/null
@@ -0,0 +1,606 @@
+/* filter.c version 0.7
+ * contient les filtres applicable a un buffer
+ * creation : 01/10/2000
+ *  -ajout de sinFilter()
+ *  -ajout de zoomFilter()
+ *  -copie de zoomFilter() en zoomFilterRGB(), gérant les 3 couleurs
+ *  -optimisation de sinFilter (utilisant une table de sin)
+ *      -asm
+ *      -optimisation de la procedure de génération du buffer de transformation
+ *              la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
+*/
+
+/*#define _DEBUG_PIXEL; */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "filters.h"
+#include "graphic.h"
+#include "goom_tools.h"
+#include "goom_core.h"
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+
+#ifdef MMX
+#define USE_ASM
+#endif
+#ifdef POWERPC
+#define USE_ASM
+#endif
+
+#ifdef USE_ASM
+#define EFFECT_DISTORS 4
+#else
+#define EFFECT_DISTORS 10
+#endif
+
+
+#ifdef USE_ASM
+
+#ifdef MMX
+int mmx_zoom ();
+guint32 mmx_zoom_size;
+#endif /* MMX */
+
+#ifdef POWERPC
+extern unsigned int useAltivec;
+extern void ppc_zoom (void);
+extern void ppc_zoom_altivec (void);
+unsigned int ppcsize4;
+#endif /* PowerPC */
+
+
+unsigned int *coeffs = 0, *freecoeffs = 0;
+guint32 *expix1 = 0;            /* pointeur exporte vers p1 */
+guint32 *expix2 = 0;            /* pointeur exporte vers p2 */
+guint32 zoom_width;
+#endif /* ASM */
+
+
+static int firstTime = 1;
+static int sintable[0xffff];
+
+ZoomFilterData *
+zoomFilterNew ()
+{
+  ZoomFilterData *zf = malloc (sizeof (ZoomFilterData));
+
+  zf->vitesse = 128;
+  zf->pertedec = 8;
+  zf->sqrtperte = 16;
+  zf->middleX = 1;
+  zf->middleY = 1;
+  zf->reverse = 0;
+  zf->mode = WAVE_MODE;
+  zf->hPlaneEffect = 0;
+  zf->vPlaneEffect = 0;
+  zf->noisify = 0;
+  zf->buffsize = 0;
+  zf->res_x = 0;
+  zf->res_y = 0;
+
+  zf->buffer = NULL;
+  zf->firedec = NULL;
+
+  zf->wave = 0;
+  zf->wavesp = 0;
+
+  return zf;
+}
+
+/* retourne x>>s , en testant le signe de x */
+static inline int
+ShiftRight (int x, const unsigned char s)
+{
+  if (x < 0)
+    return -(-x >> s);
+  else
+    return x >> s;
+}
+
+/*
+  calculer px et py en fonction de x,y,middleX,middleY et theMode
+  px et py indique la nouvelle position (en sqrtperte ieme de pixel)
+  (valeur * 16)
+*/
+void
+calculatePXandPY (GoomData * gd, int x, int y, int *px, int *py)
+{
+  ZoomFilterData *zf = gd->zfd;
+  int middleX, middleY;
+  guint32 resoly = zf->res_y;
+  int vPlaneEffect = zf->vPlaneEffect;
+  int hPlaneEffect = zf->hPlaneEffect;
+  int vitesse = zf->vitesse;
+  char theMode = zf->mode;
+
+  if (theMode == WATER_MODE) {
+    int wavesp = zf->wavesp;
+    int wave = zf->wave;
+    int yy = y + RAND (gd) % 4 + wave / 10;
+
+    yy -= RAND (gd) % 4;
+    if (yy < 0)
+      yy = 0;
+    if (yy >= resoly)
+      yy = resoly - 1;
+
+    *px = (x << 4) + zf->firedec[yy] + (wave / 10);
+    *py = (y << 4) + 132 - ((vitesse < 132) ? vitesse : 131);
+
+    wavesp += RAND (gd) % 3;
+    wavesp -= RAND (gd) % 3;
+    if (wave < -10)
+      wavesp += 2;
+    if (wave > 10)
+      wavesp -= 2;
+    wave += (wavesp / 10) + RAND (gd) % 3;
+    wave -= RAND (gd) % 3;
+    if (wavesp > 100)
+      wavesp = (wavesp * 9) / 10;
+
+    zf->wavesp = wavesp;
+    zf->wave = wave;
+  } else {
+    int dist;
+    register int vx, vy;
+    int fvitesse = vitesse << 4;
+
+    middleX = zf->middleX;
+    middleY = zf->middleY;
+
+    if (zf->noisify) {
+      x += RAND (gd) % zf->noisify;
+      x -= RAND (gd) % zf->noisify;
+      y += RAND (gd) % zf->noisify;
+      y -= RAND (gd) % zf->noisify;
+    }
+
+    if (hPlaneEffect)
+      vx = ((x - middleX) << 9) + hPlaneEffect * (y - middleY);
+    else
+      vx = (x - middleX) << 9;
+
+    if (vPlaneEffect)
+      vy = ((y - middleY) << 9) + vPlaneEffect * (x - middleX);
+    else
+      vy = (y - middleY) << 9;
+
+    switch (theMode) {
+      case WAVE_MODE:
+        dist =
+            ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
+            9) * ShiftRight (vy, 9);
+        fvitesse *=
+            1024 +
+            ShiftRight (sintable[(unsigned short) (0xffff * dist *
+                    EFFECT_DISTORS)], 6);
+        fvitesse /= 1024;
+        break;
+      case CRYSTAL_BALL_MODE:
+        dist =
+            ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
+            9) * ShiftRight (vy, 9);
+        fvitesse += (dist * EFFECT_DISTORS >> 10);
+        break;
+      case AMULETTE_MODE:
+        dist =
+            ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
+            9) * ShiftRight (vy, 9);
+        fvitesse -= (dist * EFFECT_DISTORS >> 4);
+        break;
+      case SCRUNCH_MODE:
+        dist =
+            ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
+            9) * ShiftRight (vy, 9);
+        fvitesse -= (dist * EFFECT_DISTORS >> 9);
+        break;
+    }
+    if (vx < 0)
+      *px = (middleX << 4) - (-(vx * fvitesse) >> 16);
+    else
+      *px = (middleX << 4) + ((vx * fvitesse) >> 16);
+    if (vy < 0)
+      *py = (middleY << 4) - (-(vy * fvitesse) >> 16);
+    else
+      *py = (middleY << 4) + ((vy * fvitesse) >> 16);
+  }
+}
+
+/*#define _DEBUG */
+
+static inline void
+setPixelRGB (Uint * buffer, Uint x, Uint y, Color c,
+    guint32 resolx, guint32 resoly)
+{
+/*              buffer[ y*WIDTH + x ] = (c.r<<16)|(c.v<<8)|c.b */
+#ifdef _DEBUG_PIXEL
+  if (x + y * resolx >= resolx * resoly) {
+    fprintf (stderr, "setPixel ERROR : hors du tableau... %i, %i\n", x, y);
+    /*exit (1) ; */
+  }
+#endif
+
+#ifdef USE_DGA
+  buffer[y * resolx + x] = (c.b << 16) | (c.v << 8) | c.r;
+#else
+  buffer[y * resolx + x] = (c.r << 16) | (c.v << 8) | c.b;
+#endif
+}
+
+
+static inline void
+setPixelRGB_ (Uint * buffer, Uint x, Color c, guint32 resolx, guint32 resoly)
+{
+#ifdef _DEBUG
+  if (x >= resolx * resoly) {
+    printf ("setPixel ERROR : hors du tableau... %i >= %i*%i (%i)\n", x, resolx,
+        resoly, resolx * resoly);
+    exit (1);
+  }
+#endif
+
+#ifdef USE_DGA
+  buffer[x] = (c.b << 16) | (c.v << 8) | c.r;
+#else
+  buffer[x] = (c.r << 16) | (c.v << 8) | c.b;
+#endif
+}
+
+
+
+static inline void
+getPixelRGB (Uint * buffer, Uint x, Uint y, Color * c,
+    guint32 resolx, guint32 resoly)
+{
+  register unsigned char *tmp8;
+
+#ifdef _DEBUG
+  if (x + y * resolx >= resolx * resoly) {
+    printf ("getPixel ERROR : hors du tableau... %i, %i\n", x, y);
+    exit (1);
+  }
+#endif
+
+#ifdef __BIG_ENDIAN__
+  c->b = *(unsigned char *) (tmp8 =
+      (unsigned char *) (buffer + (x + y * resolx)));
+  c->r = *(unsigned char *) (++tmp8);
+  c->v = *(unsigned char *) (++tmp8);
+  c->b = *(unsigned char *) (++tmp8);
+
+#else
+  /* ATTENTION AU PETIT INDIEN  */
+  c->b = *(unsigned char *) (tmp8 =
+      (unsigned char *) (buffer + (x + y * resolx)));
+  c->v = *(unsigned char *) (++tmp8);
+  c->r = *(unsigned char *) (++tmp8);
+/*      *c = (Color) buffer[x+y*WIDTH] ; */
+#endif
+}
+
+
+static inline void
+getPixelRGB_ (Uint * buffer, Uint x, Color * c, guint32 resolx, guint32 resoly)
+{
+  register unsigned char *tmp8;
+
+#ifdef _DEBUG
+  if (x >= resolx * resoly) {
+    printf ("getPixel ERROR : hors du tableau... %i\n", x);
+    exit (1);
+  }
+#endif
+
+#ifdef __BIG_ENDIAN__
+  c->b = *(unsigned char *) (tmp8 = (unsigned char *) (buffer + x));
+  c->r = *(unsigned char *) (++tmp8);
+  c->v = *(unsigned char *) (++tmp8);
+  c->b = *(unsigned char *) (++tmp8);
+
+#else
+  /* ATTENTION AU PETIT INDIEN  */
+  tmp8 = (unsigned char *) (buffer + x);
+  c->b = *(unsigned char *) (tmp8++);
+  c->v = *(unsigned char *) (tmp8++);
+  c->r = *(unsigned char *) (tmp8);
+/*      *c = (Color) buffer[x+y*WIDTH] ; */
+#endif
+}
+
+static void
+zoomFilterSetResolution (GoomData * gd, ZoomFilterData * zf)
+{
+  unsigned short us;
+
+  if (zf->buffsize >= gd->buffsize) {
+    zf->res_x = gd->resolx;
+    zf->res_y = gd->resoly;
+    zf->middleX = gd->resolx / 2;
+    zf->middleY = gd->resoly - 1;
+
+    return;
+  }
+#ifndef USE_ASM
+  if (zf->buffer)
+    free (zf->buffer);
+  zf->buffer = 0;
+#else
+  if (coeffs)
+    free (freecoeffs);
+  coeffs = 0;
+#endif
+  zf->middleX = gd->resolx / 2;
+  zf->middleY = gd->resoly - 1;
+  zf->res_x = gd->resolx;
+  zf->res_y = gd->resoly;
+
+  if (zf->firedec)
+    free (zf->firedec);
+  zf->firedec = 0;
+
+  zf->buffsize = gd->resolx * gd->resoly * sizeof (unsigned int);
+
+#ifdef USE_ASM
+  freecoeffs = (unsigned int *)
+      malloc (resx * resy * 2 * sizeof (unsigned int) + 128);
+  coeffs = (guint32 *) ((1 + ((unsigned int) (freecoeffs)) / 128) * 128);
+
+#else
+  zf->buffer = calloc (sizeof (guint32), zf->buffsize * 5);
+  zf->pos10 = zf->buffer;
+  zf->c[0] = zf->pos10 + zf->buffsize;
+  zf->c[1] = zf->c[0] + zf->buffsize;
+  zf->c[2] = zf->c[1] + zf->buffsize;
+  zf->c[3] = zf->c[2] + zf->buffsize;
+#endif
+  zf->firedec = (int *) malloc (zf->res_y * sizeof (int));
+
+  if (firstTime) {
+    firstTime = 0;
+
+    /* generation d'une table de sinus */
+    for (us = 0; us < 0xffff; us++) {
+      sintable[us] = (int) (1024.0f * sin (us * 2 * 3.31415f / 0xffff));
+    }
+  }
+
+  {
+    int loopv;
+
+    for (loopv = zf->res_y; loopv != 0;) {
+      int decc = 0;
+      int spdc = 0;
+      int accel = 0;
+
+      loopv--;
+      zf->firedec[loopv] = decc;
+      decc += spdc / 10;
+      spdc += RAND (gd) % 3;
+      spdc -= RAND (gd) % 3;
+
+      if (decc > 4)
+        spdc -= 1;
+      if (decc < -4)
+        spdc += 1;
+
+      if (spdc > 30)
+        spdc = spdc - RAND (gd) % 3 + accel / 10;
+      if (spdc < -30)
+        spdc = spdc + RAND (gd) % 3 + accel / 10;
+
+      if (decc > 8 && spdc > 1)
+        spdc -= RAND (gd) % 3 - 2;
+
+      if (decc < -8 && spdc < -1)
+        spdc += RAND (gd) % 3 + 2;
+
+      if (decc > 8 || decc < -8)
+        decc = decc * 8 / 9;
+
+      accel += RAND (gd) % 2;
+      accel -= RAND (gd) % 2;
+      if (accel > 20)
+        accel -= 2;
+      if (accel < -20)
+        accel += 2;
+    }
+  }
+}
+
+void
+zoomFilterDestroy (ZoomFilterData * zf)
+{
+  if (zf) {
+    if (zf->firedec)
+      free (zf->firedec);
+    if (zf->buffer)
+      free (zf->buffer);
+    free (zf);
+  }
+}
+
+/*===============================================================*/
+void
+zoomFilterFastRGB (GoomData * goomdata, ZoomFilterData * zf, int zfd_update)
+{
+  guint32 prevX = goomdata->resolx;
+  guint32 prevY = goomdata->resoly;
+
+  guint32 *pix1 = goomdata->p1;
+  guint32 *pix2 = goomdata->p2;
+  unsigned int *pos10;
+  unsigned int **c;
+
+  Uint x, y;
+
+/*  static unsigned int prevX = 0, prevY = 0; */
+
+#ifdef USE_ASM
+  expix1 = pix1;
+  expix2 = pix2;
+#else
+  Color couleur;
+  Color col1, col2, col3, col4;
+  Uint position;
+#endif
+
+  if ((goomdata->resolx != zf->res_x) || (goomdata->resoly != zf->res_y)) {
+    zoomFilterSetResolution (goomdata, zf);
+  }
+
+  pos10 = zf->pos10;
+  c = zf->c;
+
+  if (zfd_update) {
+    guchar sqrtperte = zf->sqrtperte;
+    gint start_y = 0;
+
+    if (zf->reverse)
+      zf->vitesse = 256 - zf->vitesse;
+
+    /* generation du buffer */
+    for (y = 0; y < zf->res_y; y++) {
+      gint y_16 = y << 4;
+      gint max_px = (prevX - 1) * sqrtperte;
+      gint max_py = (prevY - 1) * sqrtperte;
+
+      for (x = 0; x < zf->res_x; x++) {
+        gint px, py;
+        guchar coefv, coefh;
+
+        /* calculer px et py en fonction de */
+        /*   x,y,middleX,middleY et theMode */
+        calculatePXandPY (goomdata, x, y, &px, &py);
+
+        if ((px == x << 4) && (py == y_16))
+          py += 8;
+
+        if ((py < 0) || (px < 0) || (py >= max_py) || (px >= max_px)) {
+#ifdef USE_ASM
+          coeffs[(y * prevX + x) * 2] = 0;
+          coeffs[(y * prevX + x) * 2 + 1] = 0;
+#else
+          pos10[start_y + x] = 0;
+          c[0][start_y + x] = 0;
+          c[1][start_y + x] = 0;
+          c[2][start_y + x] = 0;
+          c[3][start_y + x] = 0;
+#endif
+        } else {
+          int npx10;
+          int npy10;
+          int pos;
+
+          npx10 = (px / sqrtperte);
+          npy10 = (py / sqrtperte);
+
+/*                        if (npx10 >= prevX) fprintf(stderr,"error npx:%d",npx10);
+                          if (npy10 >= prevY) fprintf(stderr,"error npy:%d",npy10);
+*/
+          coefh = px % sqrtperte;
+          coefv = py % sqrtperte;
+#ifdef USE_ASM
+          pos = (y * prevX + x) * 2;
+          coeffs[pos] = (npx10 + prevX * npy10) * 4;
+
+          if (!(coefh || coefv))
+            coeffs[pos + 1] = (sqrtperte * sqrtperte - 1);
+          else
+            coeffs[pos + 1] = ((sqrtperte - coefh) * (sqrtperte - coefv));
+
+          coeffs[pos + 1] |= (coefh * (sqrtperte - coefv)) << 8;
+          coeffs[pos + 1] |= ((sqrtperte - coefh) * coefv) << 16;
+          coeffs[pos + 1] |= (coefh * coefv) << 24;
+#else
+          pos = start_y + x;
+          pos10[pos] = npx10 + prevX * npy10;
+
+          if (!(coefh || coefv))
+            c[0][pos] = sqrtperte * sqrtperte - 1;
+          else
+            c[0][pos] = (sqrtperte - coefh) * (sqrtperte - coefv);
+
+          c[1][pos] = coefh * (sqrtperte - coefv);
+          c[2][pos] = (sqrtperte - coefh) * coefv;
+          c[3][pos] = coefh * coefv;
+#endif
+        }
+      }
+      /* Advance start of line index */
+      start_y += prevX;
+    }
+  }
+#ifdef USE_ASM
+#ifdef MMX
+  zoom_width = prevX;
+  mmx_zoom_size = prevX * prevY;
+  mmx_zoom ();
+#endif
+
+#ifdef POWERPC
+  zoom_width = prevX;
+  if (useAltivec) {
+    ppcsize4 = ((unsigned int) (prevX * prevY)) / 4;
+    ppc_zoom_altivec ();
+  } else {
+    ppcsize4 = ((unsigned int) (prevX * prevY));
+    ppc_zoom ();
+  }
+#endif
+#else
+  for (position = 0; position < prevX * prevY; position++) {
+    getPixelRGB_ (pix1, pos10[position], &col1, goomdata->resolx,
+        goomdata->resoly);
+    getPixelRGB_ (pix1, pos10[position] + 1, &col2, goomdata->resolx,
+        goomdata->resoly);
+    getPixelRGB_ (pix1, pos10[position] + prevX, &col3, goomdata->resolx,
+        goomdata->resoly);
+    getPixelRGB_ (pix1, pos10[position] + prevX + 1, &col4, goomdata->resolx,
+        goomdata->resoly);
+
+    couleur.r = col1.r * c[0][position]
+        + col2.r * c[1][position]
+        + col3.r * c[2][position]
+        + col4.r * c[3][position];
+    couleur.r >>= zf->pertedec;
+
+    couleur.v = col1.v * c[0][position]
+        + col2.v * c[1][position]
+        + col3.v * c[2][position]
+        + col4.v * c[3][position];
+    couleur.v >>= zf->pertedec;
+
+    couleur.b = col1.b * c[0][position]
+        + col2.b * c[1][position]
+        + col3.b * c[2][position]
+        + col4.b * c[3][position];
+    couleur.b >>= zf->pertedec;
+
+    setPixelRGB_ (pix2, position, couleur, goomdata->resolx, goomdata->resoly);
+  }
+#endif
+}
+
+
+void
+pointFilter (GoomData * goomdata, Color c,
+    float t1, float t2, float t3, float t4, Uint cycle)
+{
+  Uint *pix1 = goomdata->p1;
+  ZoomFilterData *zf = goomdata->zfd;
+  Uint x = (Uint) (zf->middleX + (int) (t1 * cos ((float) cycle / t3)));
+  Uint y = (Uint) (zf->middleY + (int) (t2 * sin ((float) cycle / t4)));
+
+  if ((x > 1) && (y > 1) && (x < goomdata->resolx - 2)
+      && (y < goomdata->resoly - 2)) {
+    setPixelRGB (pix1, x + 1, y, c, goomdata->resolx, goomdata->resoly);
+    setPixelRGB (pix1, x, y + 1, c, goomdata->resolx, goomdata->resoly);
+    setPixelRGB (pix1, x + 1, y + 1, WHITE, goomdata->resolx, goomdata->resoly);
+    setPixelRGB (pix1, x + 2, y + 1, c, goomdata->resolx, goomdata->resoly);
+    setPixelRGB (pix1, x + 1, y + 2, c, goomdata->resolx, goomdata->resoly);
+  }
+}
diff --git a/gst/goom2k1/filters.h b/gst/goom2k1/filters.h
new file mode 100644 (file)
index 0000000..65eb3e2
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef FILTERS_H
+#define FILTERS_H
+
+#include <glib.h>
+
+#include "graphic.h"
+#include "goom_core.h"
+
+#define NORMAL_MODE 0
+#define WAVE_MODE 1
+#define CRYSTAL_BALL_MODE 2
+#define SCRUNCH_MODE 3
+#define AMULETTE_MODE 4
+#define WATER_MODE 5
+
+struct ZoomFilterData
+{
+  int vitesse;
+  unsigned char pertedec;
+  unsigned char sqrtperte;
+  int middleX;
+  int middleY;
+  char reverse;
+  char mode;
+        /** @since June 2001 */
+  int hPlaneEffect;
+  int vPlaneEffect;
+  char noisify;
+
+  guint32 res_x;
+  guint32 res_y;
+  guint32 buffsize;
+
+  guint32 *buffer;
+  guint32 *pos10;
+  guint32 *c[4];
+  int     *firedec;
+
+  int     wave;
+  int     wavesp;
+};
+
+void pointFilter(GoomData *goomdata, Color c,
+                                 float t1, float t2, float t3, float t4,
+                                 guint32 cycle);
+
+/* filtre de zoom :
+ le contenu de pix1 est copie dans pix2, avec l'effet appliqué
+ midx et midy represente le centre du zoom
+
+void zoomFilter(Uint *pix1, Uint *pix2, Uint middleX, Uint middleY);
+void zoomFilterRGB(Uint *pix1,
+Uint *pix2,
+Uint middleX,
+Uint middleY);
+*/
+
+ZoomFilterData *zoomFilterNew ();
+void zoomFilterDestroy (ZoomFilterData *zf);
+void zoomFilterFastRGB (GoomData *goomdata, ZoomFilterData *zf,
+                           int zfd_update);
+
+/* filtre sin :
+ le contenu de pix1 est copie dans pix2, avec l'effet appliqué
+ cycle est la variable de temps.
+ mode vaut SIN_MUL ou SIN_ADD
+ rate est le pourcentage de l'effet appliqué
+ lenght : la longueur d'onde (1..10) [5]
+ speed : la vitesse (1..100) [10]
+*/
+/*
+void sinFilter(Uint *pix1,Uint *pix2,
+                           Uint cycle,
+                           Uint mode,
+                           Uint rate,
+                           char lenght,
+                           Uint speed);
+*/
+
+#define SIN_MUL 1
+#define SIN_ADD 2
+
+#endif
diff --git a/gst/goom2k1/filters_mmx.s b/gst/goom2k1/filters_mmx.s
new file mode 100644 (file)
index 0000000..337de56
--- /dev/null
@@ -0,0 +1,130 @@
+;// file : mmx_zoom.s
+;// author : JC Hoelt <jeko@free.fr>
+;//
+;// history
+;// 07/01/2001 : Changing FEMMS to EMMS : slower... but run on intel machines
+;//    03/01/2001 : WIDTH and HEIGHT are now variable
+;//    28/12/2000 : adding comments to the code, suppress some useless lines
+;//    27/12/2000 : reducing memory access... improving performance by 20%
+;//            coefficients are now on 1 byte
+;//    22/12/2000 : Changing data structure
+;//    16/12/2000 : AT&T version
+;//    14/12/2000 : unrolling loop
+;//    12/12/2000 : 64 bits memory access
+
+
+.data
+
+thezero:
+       .long 0x00000000
+       .long 0x00000000
+
+
+.text
+
+.globl mmx_zoom                ;// name of the function to call by C program
+.extern coeffs         ;// the transformation buffer
+.extern expix1,expix2 ;// the source and destination buffer
+.extern mmx_zoom_size, zoom_width ;// size of the buffers
+
+.align 16
+mmx_zoom:
+
+push %ebp
+push %esp
+
+;// initialisation du mm7 Ã  zero
+movq (thezero), %mm7
+
+movl zoom_width, %eax
+movl $4, %ebx
+mull %ebx
+movl %eax, %ebp
+
+movl (coeffs), %eax
+movl (expix1), %edx
+movl (expix2), %ebx
+movl $10, %edi
+movl mmx_zoom_size, %ecx
+
+.while:
+       ;// esi <- nouvelle position
+       movl (%eax), %esi
+       leal (%edx, %esi), %esi
+
+       ;// recuperation des deux premiers pixels dans mm0 et mm1
+       movq (%esi), %mm0               /* b1-v1-r1-a1-b2-v2-r2-a2 */
+       movq %mm0, %mm1                 /* b1-v1-r1-a1-b2-v2-r2-a2 */
+
+       ;// recuperation des 4 coefficients
+       movd 4(%eax), %mm6              /* ??-??-??-??-c4-c3-c2-c1 */
+       ;// depackage du premier pixel
+       punpcklbw %mm7, %mm0    /* 00-b2-00-v2-00-r2-00-a2 */
+
+       movq %mm6, %mm5                 /* ??-??-??-??-c4-c3-c2-c1 */
+       ;// depackage du 2ieme pixel
+       punpckhbw %mm7, %mm1    /* 00-b1-00-v1-00-r1-00-a1 */
+
+       ;// extraction des coefficients...
+       punpcklbw %mm5, %mm6    /* c4-c4-c3-c3-c2-c2-c1-c1 */
+       movq %mm6, %mm4                 /* c4-c4-c3-c3-c2-c2-c1-c1 */
+       movq %mm6, %mm5                 /* c4-c4-c3-c3-c2-c2-c1-c1 */
+
+       punpcklbw %mm5, %mm6    /* c2-c2-c2-c2-c1-c1-c1-c1 */
+       punpckhbw %mm5, %mm4    /* c4-c4-c4-c4-c3-c3-c3-c3 */
+
+       movq %mm6, %mm3                 /* c2-c2-c2-c2-c1-c1-c1-c1 */
+       punpcklbw %mm7, %mm6    /* 00-c1-00-c1-00-c1-00-c1 */
+       punpckhbw %mm7, %mm3    /* 00-c2-00-c2-00-c2-00-c2 */
+       
+       ;// multiplication des pixels par les coefficients
+       pmullw %mm6, %mm0               /* c1*b2-c1*v2-c1*r2-c1*a2 */
+       pmullw %mm3, %mm1               /* c2*b1-c2*v1-c2*r1-c2*a1 */
+       paddw %mm1, %mm0
+       
+       ;// ...extraction des 2 derniers coefficients
+       movq %mm4, %mm5                 /* c4-c4-c4-c4-c3-c3-c3-c3 */
+       punpcklbw %mm7, %mm4    /* 00-c3-00-c3-00-c3-00-c3 */
+       punpckhbw %mm7, %mm5    /* 00-c4-00-c4-00-c4-00-c4 */
+
+       ;// recuperation des 2 derniers pixels
+       movq (%esi,%ebp), %mm1
+       movq %mm1, %mm2
+       
+       ;// depackage des pixels
+       punpcklbw %mm7, %mm1
+       punpckhbw %mm7, %mm2
+       
+       ;// multiplication pas les coeffs
+       pmullw %mm4, %mm1
+       pmullw %mm5, %mm2
+       
+       ;// ajout des valeurs obtenues Ã  la valeur finale
+       paddw %mm1, %mm0
+       paddw %mm2, %mm0
+
+       ;// division par 256 = 16+16+16+16, puis repackage du pixel final
+       psrlw $8, %mm0
+       packuswb %mm7, %mm0
+       
+       ;// passage au suivant
+       leal 8(%eax), %eax
+
+       decl %ecx
+       ;// enregistrement du resultat
+       movd %mm0, (%ebx)
+       leal 4(%ebx), %ebx
+
+       ;// test de fin du tantque
+       cmpl $0, %ecx                           ;// 400x300
+
+jz .fin_while
+jmp .while
+
+.fin_while:
+emms
+
+pop %esp
+pop %ebp
+
+ret                  ;//The End
diff --git a/gst/goom2k1/goom.vcproj b/gst/goom2k1/goom.vcproj
new file mode 100644 (file)
index 0000000..7d4c1ef
--- /dev/null
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+       ProjectType="Visual C++"
+       Version="7.10"
+       Name="goom"
+       ProjectGUID="{979C216F-0ACF-4956-AE00-055A42D678B4}"
+       Keyword="Win32Proj">
+       <Platforms>
+               <Platform
+                       Name="Win32"/>
+       </Platforms>
+       <Configurations>
+               <Configuration
+                       Name="Debug|Win32"
+                       OutputDirectory="../../win32/Debug"
+                       IntermediateDirectory="../../win32/Debug"
+                       ConfigurationType="2"
+                       CharacterSet="2">
+                       <Tool
+                               Name="VCCLCompilerTool"
+                               Optimization="0"
+                               AdditionalIncludeDirectories="../../../gstreamer/win32;../../../gstreamer;../../../gstreamer/libs;../../../glib;../../../glib/glib;../../../glib/gmodule;&quot;../../gst-libs&quot;;../../../popt/include;../../../libxml2/include/libxml2"
+                               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;goom_EXPORTS;HAVE_CONFIG_H;_USE_MATH_DEFINES"
+                               MinimalRebuild="TRUE"
+                               BasicRuntimeChecks="3"
+                               RuntimeLibrary="3"
+                               UsePrecompiledHeader="0"
+                               WarningLevel="3"
+                               Detect64BitPortabilityProblems="TRUE"
+                               DebugInformationFormat="4"/>
+                       <Tool
+                               Name="VCCustomBuildTool"/>
+                       <Tool
+                               Name="VCLinkerTool"
+                               AdditionalDependencies="glib-2.0.lib gmodule-2.0.lib gthread-2.0.lib gobject-2.0.lib libgstreamer.lib gstbytestream.lib iconv.lib intl.lib"
+                               OutputFile="$(OutDir)/gstgoom2k1.dll"
+                               LinkIncremental="2"
+                               AdditionalLibraryDirectories="../../../gstreamer/win32/Debug;../../../glib/glib;../../../glib/gmodule;../../../glib/gthread;../../../glib/gobject;../../../gettext/lib;../../../libiconv/lib"
+                               ModuleDefinitionFile=""
+                               GenerateDebugInformation="TRUE"
+                               ProgramDatabaseFile="$(OutDir)/goom.pdb"
+                               SubSystem="2"
+                               OptimizeReferences="2"
+                               ImportLibrary="$(OutDir)/gstgoom2k1.lib"
+                               TargetMachine="1"/>
+                       <Tool
+                               Name="VCMIDLTool"/>
+                       <Tool
+                               Name="VCPostBuildEventTool"
+                               CommandLine="copy /Y $(TargetPath) c:\gstreamer\plugins"/>
+                       <Tool
+                               Name="VCPreBuildEventTool"/>
+                       <Tool
+                               Name="VCPreLinkEventTool"/>
+                       <Tool
+                               Name="VCResourceCompilerTool"/>
+                       <Tool
+                               Name="VCWebServiceProxyGeneratorTool"/>
+                       <Tool
+                               Name="VCXMLDataGeneratorTool"/>
+                       <Tool
+                               Name="VCWebDeploymentTool"/>
+                       <Tool
+                               Name="VCManagedWrapperGeneratorTool"/>
+                       <Tool
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+               </Configuration>
+               <Configuration
+                       Name="Release|Win32"
+                       OutputDirectory="../../win32/Release"
+                       IntermediateDirectory="../../win32/Release"
+                       ConfigurationType="2"
+                       CharacterSet="2">
+                       <Tool
+                               Name="VCCLCompilerTool"
+                               AdditionalIncludeDirectories="../../../gstreamer/win32;../../../gstreamer;../../../gstreamer/libs;../../../glib;../../../glib/glib;../../../glib/gmodule;&quot;../../gst-libs&quot;;../../../popt/include;../../../libxml2/include/libxml2"
+                               PreprocessorDefinitions="WIN32;NDEBUG;GST_DISABLE_GST_DEBUG;_WINDOWS;_USRDLL;goom_EXPORTS;HAVE_CONFIG_H;_USE_MATH_DEFINES"
+                               RuntimeLibrary="2"
+                               UsePrecompiledHeader="0"
+                               WarningLevel="3"
+                               Detect64BitPortabilityProblems="TRUE"
+                               DebugInformationFormat="3"/>
+                       <Tool
+                               Name="VCCustomBuildTool"/>
+                       <Tool
+                               Name="VCLinkerTool"
+                               AdditionalDependencies="glib-2.0.lib gmodule-2.0.lib gthread-2.0.lib gobject-2.0.lib libgstreamer.lib gstbytestream.lib iconv.lib intl.lib"
+                               OutputFile="$(OutDir)/gstgoom2k1.dll"
+                               LinkIncremental="1"
+                               AdditionalLibraryDirectories="../../../gstreamer/win32/Release;../../../glib/glib;../../../glib/gmodule;../../../glib/gthread;../../../glib/gobject;../../../gettext/lib;../../../libiconv/lib"
+                               ModuleDefinitionFile=""
+                               GenerateDebugInformation="TRUE"
+                               SubSystem="2"
+                               OptimizeReferences="2"
+                               EnableCOMDATFolding="2"
+                               ImportLibrary="$(OutDir)/gstgoom2k1.lib"
+                               TargetMachine="1"/>
+                       <Tool
+                               Name="VCMIDLTool"/>
+                       <Tool
+                               Name="VCPostBuildEventTool"
+                               CommandLine="copy /Y $(TargetPath) c:\gstreamer\plugins"/>
+                       <Tool
+                               Name="VCPreBuildEventTool"/>
+                       <Tool
+                               Name="VCPreLinkEventTool"/>
+                       <Tool
+                               Name="VCResourceCompilerTool"/>
+                       <Tool
+                               Name="VCWebServiceProxyGeneratorTool"/>
+                       <Tool
+                               Name="VCXMLDataGeneratorTool"/>
+                       <Tool
+                               Name="VCWebDeploymentTool"/>
+                       <Tool
+                               Name="VCManagedWrapperGeneratorTool"/>
+                       <Tool
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+               </Configuration>
+       </Configurations>
+       <References>
+       </References>
+       <Files>
+               <Filter
+                       Name="Source Files"
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+                       <File
+                               RelativePath=".\gstgoom2k1.c">
+                       </File>
+                       <File
+                               RelativePath=".\goom_core.c">
+                       </File>
+                       <File
+                               RelativePath=".\graphic.c">
+                       </File>
+                       <File
+                               RelativePath=".\lines.c">
+                       </File>
+                       <File
+                               RelativePath=".\filters.c">
+                       </File>
+               </Filter>
+               <Filter
+                       Name="Header Files"
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+                       <File
+                               RelativePath=".\filters.h">
+                       </File>
+                       <File
+                               RelativePath=".\goom_core.h">
+                       </File>
+                       <File
+                               RelativePath=".\goom_tools.h">
+                       </File>
+                       <File
+                               RelativePath=".\graphic.h">
+                       </File>
+                       <File
+                               RelativePath=".\lines.h">
+                       </File>
+               </Filter>
+               <Filter
+                       Name="Resource Files"
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+                       UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+               </Filter>
+       </Files>
+       <Globals>
+       </Globals>
+</VisualStudioProject>
diff --git a/gst/goom2k1/goom_core.c b/gst/goom2k1/goom_core.c
new file mode 100644 (file)
index 0000000..d66ffe2
--- /dev/null
@@ -0,0 +1,412 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <glib.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include "goom_core.h"
+#include "goom_tools.h"
+#include "filters.h"
+#include "lines.h"
+
+/*#define VERBOSE */
+
+#ifdef VERBOSE
+#include <stdio.h>
+#endif
+
+#define STOP_SPEED 128
+
+void
+goom_init (GoomData * goomdata, guint32 resx, guint32 resy)
+{
+#ifdef VERBOSE
+  printf ("GOOM: init (%d, %d);\n", resx, resy);
+#endif
+  goomdata->resolx = 0;
+  goomdata->resoly = 0;
+  goomdata->buffsize = 0;
+
+  goomdata->pixel = NULL;
+  goomdata->back = NULL;
+  goomdata->p1 = NULL;
+  goomdata->p2 = NULL;
+
+  goom_set_resolution (goomdata, resx, resy);
+  RAND_INIT (goomdata, GPOINTER_TO_INT (goomdata->pixel));
+  goomdata->cycle = 0;
+
+
+  goomdata->goomlimit = 2;      /* sensibilité du goom */
+  goomdata->zfd = zoomFilterNew ();
+  goomdata->lockvar = 0;        /* pour empecher de nouveaux changements */
+  goomdata->goomvar = 0;        /* boucle des gooms */
+  goomdata->totalgoom = 0;      /* nombre de gooms par seconds */
+  goomdata->agoom = 0;          /* un goom a eu lieu..       */
+  goomdata->loopvar = 0;        /* mouvement des points */
+  goomdata->speedvar = 0;       /* vitesse des particules */
+  goomdata->lineMode = 0;       /* l'effet lineaire a dessiner */
+}
+
+void
+goom_set_resolution (GoomData * goomdata, guint32 resx, guint32 resy)
+{
+  guint32 buffsize = resx * resy;
+
+  if ((goomdata->resolx == resx) && (goomdata->resoly == resy))
+    return;
+
+  if (goomdata->buffsize < buffsize) {
+    if (goomdata->pixel)
+      free (goomdata->pixel);
+    if (goomdata->back)
+      free (goomdata->back);
+    goomdata->pixel = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
+    goomdata->back = (guint32 *) malloc (buffsize * sizeof (guint32) + 128);
+    goomdata->buffsize = buffsize;
+
+    goomdata->p1 =
+        (void *) (((unsigned long) goomdata->pixel + 0x7f) & (~0x7f));
+    goomdata->p2 = (void *) (((unsigned long) goomdata->back + 0x7f) & (~0x7f));
+  }
+
+  goomdata->resolx = resx;
+  goomdata->resoly = resy;
+
+  memset (goomdata->pixel, 0, buffsize * sizeof (guint32) + 128);
+  memset (goomdata->back, 0, buffsize * sizeof (guint32) + 128);
+}
+
+guint32 *
+goom_update (GoomData * goomdata, gint16 data[2][512])
+{
+  guint32 *return_val;
+  guint32 pointWidth;
+  guint32 pointHeight;
+  int incvar;                   /* volume du son */
+  int accelvar;                 /* acceleration des particules */
+  int i;
+  float largfactor;             /* elargissement de l'intervalle d'évolution des points */
+  int zfd_update = 0;
+  int resolx = goomdata->resolx;
+  int resoly = goomdata->resoly;
+  ZoomFilterData *pzfd = goomdata->zfd;
+  guint32 *tmp;
+
+  /* test if the config has changed, update it if so */
+
+  pointWidth = (resolx * 2) / 5;
+  pointHeight = (resoly * 2) / 5;
+
+  /* ! etude du signal ... */
+  incvar = 0;
+  for (i = 0; i < 512; i++) {
+    if (incvar < data[0][i])
+      incvar = data[0][i];
+  }
+
+  accelvar = incvar / 5000;
+  if (goomdata->speedvar > 5) {
+    accelvar--;
+    if (goomdata->speedvar > 20)
+      accelvar--;
+    if (goomdata->speedvar > 40)
+      goomdata->speedvar = 40;
+  }
+  accelvar--;
+  goomdata->speedvar += accelvar;
+
+  if (goomdata->speedvar < 0)
+    goomdata->speedvar = 0;
+  if (goomdata->speedvar > 40)
+    goomdata->speedvar = 40;
+
+
+  /* ! calcul du deplacement des petits points ... */
+
+  largfactor =
+      ((float) goomdata->speedvar / 40.0f + (float) incvar / 50000.0f) / 1.5f;
+  if (largfactor > 1.5f)
+    largfactor = 1.5f;
+
+  for (i = 1; i * 15 <= goomdata->speedvar + 15; i++) {
+    goomdata->loopvar += goomdata->speedvar + 1;
+
+    pointFilter (goomdata,
+        YELLOW,
+        ((pointWidth - 6.0f) * largfactor + 5.0f),
+        ((pointHeight - 6.0f) * largfactor + 5.0f),
+        i * 152.0f, 128.0f, goomdata->loopvar + i * 2032);
+    pointFilter (goomdata, ORANGE,
+        ((pointWidth / 2) * largfactor) / i + 10.0f * i,
+        ((pointHeight / 2) * largfactor) / i + 10.0f * i,
+        96.0f, i * 80.0f, goomdata->loopvar / i);
+    pointFilter (goomdata, VIOLET,
+        ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
+        ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i,
+        i + 122.0f, 134.0f, goomdata->loopvar / i);
+    pointFilter (goomdata, BLACK,
+        ((pointHeight / 3) * largfactor + 20.0f),
+        ((pointHeight / 3) * largfactor + 20.0f),
+        58.0f, i * 66.0f, goomdata->loopvar / i);
+    pointFilter (goomdata, WHITE,
+        (pointHeight * largfactor + 10.0f * i) / i,
+        (pointHeight * largfactor + 10.0f * i) / i,
+        66.0f, 74.0f, goomdata->loopvar + i * 500);
+  }
+
+  /* diminuer de 1 le temps de lockage */
+  /* note pour ceux qui n'ont pas suivis : le lockvar permet d'empecher un */
+  /* changement d'etat du plugins juste apres un autre changement d'etat. oki ? */
+  if (--goomdata->lockvar < 0)
+    goomdata->lockvar = 0;
+
+  /* temps du goom */
+  if (--goomdata->agoom < 0)
+    goomdata->agoom = 0;
+
+  /* on verifie qu'il ne se pas un truc interressant avec le son. */
+  if ((accelvar > goomdata->goomlimit) || (accelvar < -goomdata->goomlimit)) {
+    /* UN GOOM !!! YAHOO ! */
+    goomdata->totalgoom++;
+    goomdata->agoom = 20;       /* mais pdt 20 cycles, il n'y en aura plus. */
+    goomdata->lineMode = (goomdata->lineMode + 1) % 20; /* Tous les 10 gooms on change de mode lineaire */
+
+    /* changement eventuel de mode */
+    switch (iRAND (goomdata, 10)) {
+      case 0:
+      case 1:
+      case 2:
+        pzfd->mode = WAVE_MODE;
+        pzfd->vitesse = STOP_SPEED - 1;
+        pzfd->reverse = 0;
+        break;
+      case 3:
+      case 4:
+        pzfd->mode = CRYSTAL_BALL_MODE;
+        break;
+      case 5:
+        pzfd->mode = AMULETTE_MODE;
+        break;
+      case 6:
+        pzfd->mode = WATER_MODE;
+        break;
+      case 7:
+        pzfd->mode = SCRUNCH_MODE;
+        break;
+      default:
+        pzfd->mode = NORMAL_MODE;
+    }
+  }
+
+  /* tout ceci ne sera fait qu'en cas de non-blocage */
+  if (goomdata->lockvar == 0) {
+    /* reperage de goom (acceleration forte de l'acceleration du volume) */
+    /* -> coup de boost de la vitesse si besoin.. */
+    if ((accelvar > goomdata->goomlimit) || (accelvar < -goomdata->goomlimit)) {
+      goomdata->goomvar++;
+      /*if (goomvar % 1 == 0) */
+      {
+        guint32 vtmp;
+        guint32 newvit;
+
+        newvit = STOP_SPEED - goomdata->speedvar / 2;
+        /* retablir le zoom avant.. */
+        if ((pzfd->reverse) && (!(goomdata->cycle % 12)) && (rand () % 3 == 0)) {
+          pzfd->reverse = 0;
+          pzfd->vitesse = STOP_SPEED - 2;
+          goomdata->lockvar = 50;
+        }
+        if (iRAND (goomdata, 10) == 0) {
+          pzfd->reverse = 1;
+          goomdata->lockvar = 100;
+        }
+
+        /* changement de milieu.. */
+        switch (iRAND (goomdata, 20)) {
+          case 0:
+            pzfd->middleY = resoly - 1;
+            pzfd->middleX = resolx / 2;
+            break;
+          case 1:
+            pzfd->middleX = resolx - 1;
+            break;
+          case 2:
+            pzfd->middleX = 1;
+            break;
+          default:
+            pzfd->middleY = resoly / 2;
+            pzfd->middleX = resolx / 2;
+        }
+
+        if (pzfd->mode == WATER_MODE) {
+          pzfd->middleX = resolx / 2;
+          pzfd->middleY = resoly / 2;
+        }
+
+        switch (vtmp = (iRAND (goomdata, 27))) {
+          case 0:
+            pzfd->vPlaneEffect = iRAND (goomdata, 3);
+            pzfd->vPlaneEffect -= iRAND (goomdata, 3);
+            pzfd->hPlaneEffect = iRAND (goomdata, 3);
+            pzfd->hPlaneEffect -= iRAND (goomdata, 3);
+            break;
+          case 3:
+            pzfd->vPlaneEffect = 0;
+            pzfd->hPlaneEffect = iRAND (goomdata, 8);
+            pzfd->hPlaneEffect -= iRAND (goomdata, 8);
+            break;
+          case 4:
+          case 5:
+          case 6:
+          case 7:
+            pzfd->vPlaneEffect = iRAND (goomdata, 5);
+            pzfd->vPlaneEffect -= iRAND (goomdata, 5);
+            pzfd->hPlaneEffect = -pzfd->vPlaneEffect;
+            break;
+          case 8:
+            pzfd->hPlaneEffect = 5 + iRAND (goomdata, 8);
+            pzfd->vPlaneEffect = -pzfd->hPlaneEffect;
+            break;
+          case 9:
+            pzfd->vPlaneEffect = 5 + iRAND (goomdata, 8);
+            pzfd->hPlaneEffect = -pzfd->hPlaneEffect;
+            break;
+          case 13:
+            pzfd->hPlaneEffect = 0;
+            pzfd->vPlaneEffect = iRAND (goomdata, 10);
+            pzfd->vPlaneEffect -= iRAND (goomdata, 10);
+            break;
+          default:
+            if (vtmp < 10) {
+              pzfd->vPlaneEffect = 0;
+              pzfd->hPlaneEffect = 0;
+            }
+        }
+
+        if (iRAND (goomdata, 3) != 0)
+          pzfd->noisify = 0;
+        else {
+          pzfd->noisify = iRAND (goomdata, 3) + 2;
+          goomdata->lockvar *= 3;
+        }
+
+        if (pzfd->mode == AMULETTE_MODE) {
+          pzfd->vPlaneEffect = 0;
+          pzfd->hPlaneEffect = 0;
+          pzfd->noisify = 0;
+        }
+
+        if ((pzfd->middleX == 1) || (pzfd->middleX == resolx - 1)) {
+          pzfd->vPlaneEffect = 0;
+          pzfd->hPlaneEffect = iRAND (goomdata, 2) ? 0 : pzfd->hPlaneEffect;
+        }
+
+        if (newvit < pzfd->vitesse) {   /* on accelere */
+          zfd_update = 1;
+          if (((newvit < STOP_SPEED - 7) &&
+                  (pzfd->vitesse < STOP_SPEED - 6) &&
+                  (goomdata->cycle % 3 == 0)) || (iRAND (goomdata, 40) == 0)) {
+            pzfd->vitesse = STOP_SPEED - 1;
+            pzfd->reverse = !pzfd->reverse;
+          } else {
+            pzfd->vitesse = (newvit + pzfd->vitesse * 4) / 5;
+          }
+          goomdata->lockvar += 50;
+        }
+      }
+    }
+    /* mode mega-lent */
+    if (iRAND (goomdata, 1000) == 0) {
+      /* 
+         printf ("coup du sort...\n") ;
+       */
+      zfd_update = 1;
+      pzfd->vitesse = STOP_SPEED - 1;
+      pzfd->pertedec = 8;
+      pzfd->sqrtperte = 16;
+      goomdata->goomvar = 1;
+      goomdata->lockvar += 70;
+    }
+  }
+
+  /* gros frein si la musique est calme */
+  if ((goomdata->speedvar < 1) && (pzfd->vitesse < STOP_SPEED - 4)
+      && (goomdata->cycle % 16 == 0)) {
+    /*
+       printf ("++slow part... %i\n", zfd.vitesse) ;
+     */
+    zfd_update = 1;
+    pzfd->vitesse += 3;
+    pzfd->pertedec = 8;
+    pzfd->sqrtperte = 16;
+    goomdata->goomvar = 0;
+    /*
+       printf ("--slow part... %i\n", zfd.vitesse) ;
+     */
+  }
+
+  /* baisser regulierement la vitesse... */
+  if ((goomdata->cycle % 73 == 0) && (pzfd->vitesse < STOP_SPEED - 5)) {
+    /*
+       printf ("slow down...\n") ;
+     */
+    zfd_update = 1;
+    pzfd->vitesse++;
+  }
+
+  /* arreter de decrémenter au bout d'un certain temps */
+  if ((goomdata->cycle % 101 == 0) && (pzfd->pertedec == 7)) {
+    zfd_update = 1;
+    pzfd->pertedec = 8;
+    pzfd->sqrtperte = 16;
+  }
+
+  /* Zoom here ! */
+  zoomFilterFastRGB (goomdata, pzfd, zfd_update);
+
+  /* si on est dans un goom : afficher les lignes... */
+  if (goomdata->agoom > 15)
+    goom_lines (goomdata, data, ((pzfd->middleX == resolx / 2)
+            && (pzfd->middleY == resoly / 2)
+            && (pzfd->mode != WATER_MODE))
+        ? (goomdata->lineMode / 10) : 0, goomdata->p2, goomdata->agoom - 15);
+
+  return_val = goomdata->p2;
+  tmp = goomdata->p1;
+  goomdata->p1 = goomdata->p2;
+  goomdata->p2 = tmp;
+
+  /* affichage et swappage des buffers.. */
+  goomdata->cycle++;
+
+  /* tous les 100 cycles : vérifier si le taux de goom est correct */
+  /* et le modifier sinon.. */
+  if (!(goomdata->cycle % 100)) {
+    if (goomdata->totalgoom > 15) {
+      /*  printf ("less gooms\n") ; */
+      goomdata->goomlimit++;
+    } else {
+      if ((goomdata->totalgoom == 0) && (goomdata->goomlimit > 1))
+        goomdata->goomlimit--;
+    }
+    goomdata->totalgoom = 0;
+  }
+  return return_val;
+}
+
+void
+goom_close (GoomData * goomdata)
+{
+  if (goomdata->pixel != NULL)
+    free (goomdata->pixel);
+  if (goomdata->back != NULL)
+    free (goomdata->back);
+  if (goomdata->zfd != NULL) {
+    zoomFilterDestroy (goomdata->zfd);
+    goomdata->zfd = NULL;
+  }
+  goomdata->pixel = goomdata->back = NULL;
+  RAND_CLOSE (goomdata);
+}
diff --git a/gst/goom2k1/goom_core.h b/gst/goom2k1/goom_core.h
new file mode 100644 (file)
index 0000000..1fbc0ee
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _GOOMCORE_H
+#define _GOOMCORE_H
+
+#include <glib.h>
+
+typedef struct ZoomFilterData ZoomFilterData;
+
+typedef struct
+{
+/**-----------------------------------------------------**
+ **  SHARED DATA                                        **
+ **-----------------------------------------------------**/
+  guint32 *pixel;
+  guint32 *back;
+  guint32 *p1, *p2;
+  guint32 cycle;
+
+  guint32 resolx, resoly, buffsize;
+
+  int lockvar;       /* pour empecher de nouveaux changements */
+  int goomvar;       /* boucle des gooms */
+  int totalgoom;     /* nombre de gooms par seconds */
+  int agoom;         /* un goom a eu lieu..       */
+  int loopvar;       /* mouvement des points */
+  int speedvar;      /* vitesse des particules */
+  int lineMode;      /* l'effet lineaire a dessiner */
+  char goomlimit;    /* sensibilité du goom */
+
+  ZoomFilterData *zfd;
+  
+  /* Random table */
+  gint  *rand_tab;
+  guint  rand_pos;
+} GoomData;
+
+void goom_init (GoomData *goomdata, guint32 resx, guint32 resy);
+void goom_set_resolution (GoomData *goomdata, guint32 resx, guint32 resy);
+
+guint32 *goom_update (GoomData *goomdata, gint16 data [2][512]);
+
+void goom_close (GoomData *goomdata);
+
+#endif
diff --git a/gst/goom2k1/goom_tools.h b/gst/goom2k1/goom_tools.h
new file mode 100644 (file)
index 0000000..6178dba
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _GOOMTOOLS_H
+#define _GOOMTOOLS_H
+
+#define NB_RAND 0x10000
+
+#define RAND_INIT(gd,i) \
+        srand (i); \
+        if (gd->rand_tab == NULL) \
+                gd->rand_tab = g_malloc (NB_RAND * sizeof(gint)) ;\
+        gd->rand_pos = 0; \
+        while (gd->rand_pos < NB_RAND) \
+                gd->rand_tab [gd->rand_pos++] = rand ();
+
+#define RAND(gd) \
+        (gd->rand_tab[gd->rand_pos = ((gd->rand_pos + 1) % NB_RAND)])
+
+#define RAND_CLOSE(gd) \
+        g_free (gd->rand_tab); \
+        gd->rand_tab = NULL;
+
+/*#define iRAND(i) ((guint32)((float)i * RAND()/RAND_MAX)) */
+#define iRAND(gd,i) (RAND(gd) % i)
+        
+#endif
diff --git a/gst/goom2k1/graphic.c b/gst/goom2k1/graphic.c
new file mode 100644 (file)
index 0000000..c20f987
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "graphic.h"
+
+const Color BLACK = { 0, 0, 0 };
+const Color WHITE = { 0xff, 0xff, 0xff };
+const Color RED = { 0xff, 0, 0 };
+const Color GREEN = { 0, 0xff, 0 };
+const Color BLUE = { 0, 0, 0xff };
+const Color YELLOW = { 0xff, 0xff, 0x33 };
+const Color ORANGE = { 0xff, 0xcc, 0x00 };
+const Color VIOLET = { 0x55, 0x00, 0xff };
diff --git a/gst/goom2k1/graphic.h b/gst/goom2k1/graphic.h
new file mode 100644 (file)
index 0000000..4154d7f
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef GRAPHIC_H
+#define GRAPHIC_H
+
+#include <glib.h>  /* defines inline for better portability */
+
+typedef unsigned int Uint;
+
+typedef struct
+{
+  unsigned short r,v,b;
+}
+Color;
+
+extern const Color BLACK;
+extern const Color WHITE;
+extern const Color RED;
+extern const Color BLUE;
+extern const Color GREEN;
+extern const Color YELLOW;
+extern const Color ORANGE;
+extern const Color VIOLET;
+
+#endif /*GRAPHIC_H*/
diff --git a/gst/goom2k1/gstgoom.c b/gst/goom2k1/gstgoom.c
new file mode 100644 (file)
index 0000000..812d423
--- /dev/null
@@ -0,0 +1,602 @@
+/* gstgoom.c: implementation of goom drawing element
+ * Copyright (C) <2001> Richard Boulton <richard@tartarus.org>
+ *           (C) <2006> Wim Taymans <wim at fluendo dot com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:element-goom
+ * @see_also: synaesthesia
+ *
+ * <refsect2>
+ * <para>
+ * Goom is an audio visualisation element. It creates warping structures
+ * based on the incomming audio signal.
+ * </para>
+ * <title>Example launch line</title>
+ * <para>
+ * <programlisting>
+ * gst-launch -v audiotestsrc ! goom2k1 ! ffmpegcolorspace ! xvimagesink
+ * </programlisting>
+ * </para>
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <gst/gst.h>
+#include "gstgoom.h"
+#include <gst/video/video.h>
+#include "goom_core.h"
+
+GST_DEBUG_CATEGORY_STATIC (goom_debug);
+#define GST_CAT_DEFAULT goom_debug
+
+/* elementfactory information */
+static const GstElementDetails gst_goom_details =
+GST_ELEMENT_DETAILS ("GOOM: what a GOOM! 2k1",
+    "Visualization",
+    "Takes frames of data and outputs video frames using the GOOM 2k1 filter",
+    "Wim Taymans <wim@fluendo.com>");
+
+/* signals and args */
+enum
+{
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum
+{
+  ARG_0
+      /* FILL ME */
+};
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN)
+    );
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",    /* the name of the pads */
+    GST_PAD_SINK,               /* type of the pad */
+    GST_PAD_ALWAYS,             /* ALWAYS/SOMETIMES */
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "endianness = (int) BYTE_ORDER, "
+        "signed = (boolean) TRUE, "
+        "width = (int) 16, "
+        "depth = (int) 16, "
+        "rate = (int) [ 8000, 96000 ], " "channels = (int) { 1, 2 }")
+    );
+
+
+static void gst_goom_class_init (GstGoomClass * klass);
+static void gst_goom_base_init (GstGoomClass * klass);
+static void gst_goom_init (GstGoom * goom);
+static void gst_goom_finalize (GObject * object);
+
+static GstStateChangeReturn gst_goom_change_state (GstElement * element,
+    GstStateChange transition);
+
+static GstFlowReturn gst_goom_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean gst_goom_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_goom_sink_event (GstPad * pad, GstEvent * event);
+
+static gboolean gst_goom_sink_setcaps (GstPad * pad, GstCaps * caps);
+static gboolean gst_goom_src_setcaps (GstPad * pad, GstCaps * caps);
+
+static GstElementClass *parent_class = NULL;
+
+GType
+gst_goom_get_type (void)
+{
+  static GType type = 0;
+
+  if (!type) {
+    static const GTypeInfo info = {
+      sizeof (GstGoomClass),
+      (GBaseInitFunc) gst_goom_base_init,
+      NULL,
+      (GClassInitFunc) gst_goom_class_init,
+      NULL,
+      NULL,
+      sizeof (GstGoom),
+      0,
+      (GInstanceInitFunc) gst_goom_init,
+    };
+
+    type = g_type_register_static (GST_TYPE_ELEMENT, "GstGoom", &info, 0);
+  }
+  return type;
+}
+
+static void
+gst_goom_base_init (GstGoomClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_set_details (element_class, &gst_goom_details);
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_template));
+}
+
+static void
+gst_goom_class_init (GstGoomClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->finalize = gst_goom_finalize;
+
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_goom_change_state);
+
+  GST_DEBUG_CATEGORY_INIT (goom_debug, "goom", 0, "goom visualisation element");
+}
+
+static void
+gst_goom_init (GstGoom * goom)
+{
+  /* create the sink and src pads */
+  goom->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
+  gst_pad_set_chain_function (goom->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_goom_chain));
+  gst_pad_set_event_function (goom->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_goom_sink_event));
+  gst_pad_set_setcaps_function (goom->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_goom_sink_setcaps));
+  gst_element_add_pad (GST_ELEMENT (goom), goom->sinkpad);
+
+  goom->srcpad = gst_pad_new_from_static_template (&src_template, "src");
+  gst_pad_set_setcaps_function (goom->srcpad,
+      GST_DEBUG_FUNCPTR (gst_goom_src_setcaps));
+  gst_pad_set_event_function (goom->srcpad,
+      GST_DEBUG_FUNCPTR (gst_goom_src_event));
+  gst_element_add_pad (GST_ELEMENT (goom), goom->srcpad);
+
+  goom->adapter = gst_adapter_new ();
+
+  goom->width = 320;
+  goom->height = 200;
+  goom->fps_n = 25;             /* desired frame rate */
+  goom->fps_d = 1;              /* desired frame rate */
+  goom->channels = 0;
+  goom->rate = 0;
+  goom->duration = 0;
+
+  goom_init (&(goom->goomdata), goom->width, goom->height);
+}
+
+static void
+gst_goom_finalize (GObject * object)
+{
+  GstGoom *goom = GST_GOOM (object);
+
+  goom_close (&(goom->goomdata));
+
+  g_object_unref (goom->adapter);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_goom_reset (GstGoom * goom)
+{
+  goom->next_ts = -1;
+  gst_adapter_clear (goom->adapter);
+  gst_segment_init (&goom->segment, GST_FORMAT_UNDEFINED);
+
+  GST_OBJECT_LOCK (goom);
+  goom->proportion = 1.0;
+  goom->earliest_time = -1;
+  GST_OBJECT_UNLOCK (goom);
+}
+
+static gboolean
+gst_goom_sink_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstGoom *goom;
+  GstStructure *structure;
+  gboolean res;
+
+  goom = GST_GOOM (GST_PAD_PARENT (pad));
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  res = gst_structure_get_int (structure, "channels", &goom->channels);
+  res &= gst_structure_get_int (structure, "rate", &goom->rate);
+
+  goom->bps = goom->channels * sizeof (gint16);
+
+  return res;
+}
+
+static gboolean
+gst_goom_src_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstGoom *goom;
+  GstStructure *structure;
+
+  goom = GST_GOOM (GST_PAD_PARENT (pad));
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (structure, "width", &goom->width) ||
+      !gst_structure_get_int (structure, "height", &goom->height) ||
+      !gst_structure_get_fraction (structure, "framerate", &goom->fps_n,
+          &goom->fps_d))
+    return FALSE;
+
+  goom_set_resolution (&(goom->goomdata), goom->width, goom->height);
+
+  /* size of the output buffer in bytes, depth is always 4 bytes */
+  goom->outsize = goom->width * goom->height * 4;
+  goom->duration =
+      gst_util_uint64_scale_int (GST_SECOND, goom->fps_d, goom->fps_n);
+  goom->spf = gst_util_uint64_scale_int (goom->rate, goom->fps_d, goom->fps_n);
+  goom->bpf = goom->spf * goom->bps;
+
+  GST_DEBUG_OBJECT (goom, "dimension %dx%d, framerate %d/%d, spf %d",
+      goom->width, goom->height, goom->fps_n, goom->fps_d, goom->spf);
+
+  return TRUE;
+}
+
+static gboolean
+gst_goom_src_negotiate (GstGoom * goom)
+{
+  GstCaps *othercaps, *target, *intersect;
+  GstStructure *structure;
+  const GstCaps *templ;
+
+  templ = gst_pad_get_pad_template_caps (goom->srcpad);
+
+  GST_DEBUG_OBJECT (goom, "performing negotiation");
+
+  /* see what the peer can do */
+  othercaps = gst_pad_peer_get_caps (goom->srcpad);
+  if (othercaps) {
+    intersect = gst_caps_intersect (othercaps, templ);
+    gst_caps_unref (othercaps);
+
+    if (gst_caps_is_empty (intersect))
+      goto no_format;
+
+    target = gst_caps_copy_nth (intersect, 0);
+    gst_caps_unref (intersect);
+  } else {
+    target = gst_caps_ref ((GstCaps *) templ);
+  }
+
+  structure = gst_caps_get_structure (target, 0);
+  gst_structure_fixate_field_nearest_int (structure, "width", 320);
+  gst_structure_fixate_field_nearest_int (structure, "height", 240);
+  gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
+
+  gst_pad_set_caps (goom->srcpad, target);
+  gst_caps_unref (target);
+
+  return TRUE;
+
+no_format:
+  {
+    gst_caps_unref (intersect);
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_goom_src_event (GstPad * pad, GstEvent * event)
+{
+  gboolean res;
+  GstGoom *goom;
+
+  goom = GST_GOOM (gst_pad_get_parent (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_QOS:
+    {
+      gdouble proportion;
+      GstClockTimeDiff diff;
+      GstClockTime timestamp;
+
+      gst_event_parse_qos (event, &proportion, &diff, &timestamp);
+
+      /* save stuff for the _chain() function */
+      GST_OBJECT_LOCK (goom);
+      goom->proportion = proportion;
+      if (diff >= 0)
+        /* we're late, this is a good estimate for next displayable
+         * frame (see part-qos.txt) */
+        goom->earliest_time = timestamp + 2 * diff + goom->duration;
+      else
+        goom->earliest_time = timestamp + diff;
+      GST_OBJECT_UNLOCK (goom);
+
+      res = gst_pad_push_event (goom->sinkpad, event);
+      break;
+    }
+    default:
+      res = gst_pad_push_event (goom->sinkpad, event);
+      break;
+  }
+  gst_object_unref (goom);
+
+  return res;
+}
+
+static gboolean
+gst_goom_sink_event (GstPad * pad, GstEvent * event)
+{
+  gboolean res;
+  GstGoom *goom;
+
+  goom = GST_GOOM (gst_pad_get_parent (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH_START:
+      res = gst_pad_push_event (goom->srcpad, event);
+      break;
+    case GST_EVENT_FLUSH_STOP:
+      gst_goom_reset (goom);
+      res = gst_pad_push_event (goom->srcpad, event);
+      break;
+    case GST_EVENT_NEWSEGMENT:
+    {
+      GstFormat format;
+      gdouble rate, arate;
+      gint64 start, stop, time;
+      gboolean update;
+
+      /* the newsegment values are used to clip the input samples
+       * and to convert the incomming timestamps to running time so
+       * we can do QoS */
+      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+          &start, &stop, &time);
+
+      /* now configure the values */
+      gst_segment_set_newsegment_full (&goom->segment, update,
+          rate, arate, format, start, stop, time);
+
+      res = gst_pad_push_event (goom->srcpad, event);
+      break;
+    }
+    default:
+      res = gst_pad_push_event (goom->srcpad, event);
+      break;
+  }
+  gst_object_unref (goom);
+
+  return res;
+}
+
+static GstFlowReturn
+get_buffer (GstGoom * goom, GstBuffer ** outbuf)
+{
+  GstFlowReturn ret;
+
+  if (GST_PAD_CAPS (goom->srcpad) == NULL) {
+    if (!gst_goom_src_negotiate (goom))
+      return GST_FLOW_NOT_NEGOTIATED;
+  }
+
+  GST_DEBUG_OBJECT (goom, "allocating output buffer with caps %"
+      GST_PTR_FORMAT, GST_PAD_CAPS (goom->srcpad));
+
+  ret =
+      gst_pad_alloc_buffer_and_set_caps (goom->srcpad,
+      GST_BUFFER_OFFSET_NONE, goom->outsize,
+      GST_PAD_CAPS (goom->srcpad), outbuf);
+  if (ret != GST_FLOW_OK)
+    return ret;
+
+  return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_goom_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstGoom *goom;
+  GstFlowReturn ret;
+  GstBuffer *outbuf = NULL;
+
+  goom = GST_GOOM (gst_pad_get_parent (pad));
+
+  /* If we don't have an output format yet, preallocate a buffer to try and
+   * set one */
+  if (GST_PAD_CAPS (goom->srcpad) == NULL) {
+    ret = get_buffer (goom, &outbuf);
+    if (ret != GST_FLOW_OK) {
+      gst_buffer_unref (buffer);
+      goto beach;
+    }
+  }
+
+  /* don't try to combine samples from discont buffer */
+  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
+    gst_adapter_clear (goom->adapter);
+    goom->next_ts = -1;
+  }
+
+  /* Match timestamps from the incoming audio */
+  if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE)
+    goom->next_ts = GST_BUFFER_TIMESTAMP (buffer);
+
+  GST_DEBUG_OBJECT (goom,
+      "Input buffer has %d samples, time=%" G_GUINT64_FORMAT,
+      GST_BUFFER_SIZE (buffer) / goom->bps, GST_BUFFER_TIMESTAMP (buffer));
+
+  /* Collect samples until we have enough for an output frame */
+  gst_adapter_push (goom->adapter, buffer);
+
+  ret = GST_FLOW_OK;
+
+  while (TRUE) {
+    const guint16 *data;
+    gboolean need_skip;
+    guchar *out_frame;
+    gint i;
+    guint avail, to_flush;
+
+    avail = gst_adapter_available (goom->adapter);
+    GST_DEBUG_OBJECT (goom, "avail now %u", avail);
+
+    /* we need GOOM_SAMPLES to get a meaningful result from goom. */
+    if (avail < (GOOM_SAMPLES * goom->bps))
+      break;
+
+    /* we also need enough samples to produce one frame at least */
+    if (avail < goom->bpf)
+      break;
+
+    GST_DEBUG_OBJECT (goom, "processing buffer");
+
+    if (goom->next_ts != -1) {
+      gint64 qostime;
+
+      qostime = gst_segment_to_running_time (&goom->segment, GST_FORMAT_TIME,
+          goom->next_ts);
+
+      GST_OBJECT_LOCK (goom);
+      /* check for QoS, don't compute buffers that are known to be late */
+      need_skip = goom->earliest_time != -1 && qostime <= goom->earliest_time;
+      GST_OBJECT_UNLOCK (goom);
+
+      if (need_skip) {
+        GST_WARNING_OBJECT (goom,
+            "QoS: skip ts: %" GST_TIME_FORMAT ", earliest: %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (qostime), GST_TIME_ARGS (goom->earliest_time));
+        goto skip;
+      }
+    }
+
+    /* get next GOOM_SAMPLES, we have at least this amount of samples */
+    data =
+        (const guint16 *) gst_adapter_peek (goom->adapter,
+        GOOM_SAMPLES * goom->bps);
+
+    if (goom->channels == 2) {
+      for (i = 0; i < GOOM_SAMPLES; i++) {
+        goom->datain[0][i] = *data++;
+        goom->datain[1][i] = *data++;
+      }
+    } else {
+      for (i = 0; i < GOOM_SAMPLES; i++) {
+        goom->datain[0][i] = *data;
+        goom->datain[1][i] = *data++;
+      }
+    }
+
+    /* alloc a buffer if we don't have one yet, this happens
+     * when we pushed a buffer in this while loop before */
+    if (outbuf == NULL) {
+      ret = get_buffer (goom, &outbuf);
+      if (ret != GST_FLOW_OK) {
+        goto beach;
+      }
+    }
+
+    GST_BUFFER_TIMESTAMP (outbuf) = goom->next_ts;
+    GST_BUFFER_DURATION (outbuf) = goom->duration;
+    GST_BUFFER_SIZE (outbuf) = goom->outsize;
+
+    out_frame = (guchar *) goom_update (&(goom->goomdata), goom->datain);
+    memcpy (GST_BUFFER_DATA (outbuf), out_frame, goom->outsize);
+
+    GST_DEBUG ("Pushing frame with time=%" GST_TIME_FORMAT ", duration=%"
+        GST_TIME_FORMAT, GST_TIME_ARGS (goom->next_ts),
+        GST_TIME_ARGS (goom->duration));
+
+    ret = gst_pad_push (goom->srcpad, outbuf);
+    outbuf = NULL;
+
+  skip:
+    /* interpollate next timestamp */
+    if (goom->next_ts != -1)
+      goom->next_ts += goom->duration;
+
+    /* Now flush the samples we needed for this frame, which might be more than
+     * the samples we used (GOOM_SAMPLES). */
+    to_flush = goom->bpf;
+
+    GST_DEBUG_OBJECT (goom, "finished frame, flushing %u bytes from input",
+        to_flush);
+    gst_adapter_flush (goom->adapter, to_flush);
+
+    if (ret != GST_FLOW_OK)
+      break;
+  }
+
+  if (outbuf != NULL)
+    gst_buffer_unref (outbuf);
+
+beach:
+  gst_object_unref (goom);
+
+  return ret;
+}
+
+static GstStateChangeReturn
+gst_goom_change_state (GstElement * element, GstStateChange transition)
+{
+  GstGoom *goom = GST_GOOM (element);
+  GstStateChangeReturn ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      break;
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      gst_goom_reset (goom);
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  return gst_element_register (plugin, "goom2k1", GST_RANK_NONE, GST_TYPE_GOOM);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "goom2k1",
+    "GOOM 2k1 visualization filter",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/gst/goom2k1/gstgoom.h b/gst/goom2k1/gstgoom.h
new file mode 100644 (file)
index 0000000..9c25f45
--- /dev/null
@@ -0,0 +1,91 @@
+/* gstgoom.c: implementation of goom drawing element
+ * Copyright (C) <2001> Richard Boulton <richard@tartarus.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_GOOM_H__
+#define __GST_GOOM_H__
+
+G_BEGIN_DECLS
+
+#include <gst/gst.h>
+#include <gst/base/gstadapter.h>
+#include "goom_core.h"
+
+#define GOOM_SAMPLES 512
+
+#define GST_TYPE_GOOM            (gst_goom_get_type())
+#define GST_GOOM(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GOOM,GstGoom))
+#define GST_GOOM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GOOM,GstGoomClass))
+#define GST_IS_GOOM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GOOM))
+#define GST_IS_GOOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GOOM))
+
+typedef struct _GstGoom GstGoom;
+typedef struct _GstGoomClass GstGoomClass;
+
+struct _GstGoom
+{
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad, *srcpad;
+  GstAdapter *adapter;
+
+  /* input tracking */
+  gint rate;
+  gint channels;
+  guint bps;
+
+  /* video state */
+  gint fps_n;
+  gint fps_d;
+  gint width;
+  gint height;
+  GstClockTime duration;
+  guint outsize;
+
+  /* samples per frame */
+  guint spf;
+  /* bytes per frame */
+  guint bpf;
+
+  /* goom stuff */
+  gint16 datain[2][GOOM_SAMPLES];
+  GoomData goomdata;
+
+  /* segment state */
+  GstSegment segment;
+
+  /* the timestamp of the next frame */
+  GstClockTime next_ts;
+
+  /* QoS stuff *//* with LOCK */
+  gdouble proportion;
+  GstClockTime earliest_time;
+};
+
+struct _GstGoomClass
+{
+  GstElementClass parent_class;
+};
+
+GType gst_goom_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_GOOM_H__ */
+
diff --git a/gst/goom2k1/lines.c b/gst/goom2k1/lines.c
new file mode 100644 (file)
index 0000000..3214e1d
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *  lines.c
+ *  iTunesXPlugIn
+ *
+ *  Created by guillaum on Tue Aug 14 2001.
+ *  Copyright (c) 2001 __CompanyName__. All rights reserved.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "lines.h"
+#include <math.h>
+
+static inline unsigned char
+lighten (unsigned char value, unsigned char power)
+{
+  unsigned char i;
+
+  for (i = 0; i < power; i++)
+    value += (255 - value) / 5;
+  return value;
+}
+
+void
+goom_lines (GoomData * goomdata, gint16 data[2][512], unsigned int ID,
+    unsigned int *p, guint32 power)
+{
+  guint32 color1;
+  guint32 color2;
+  guint32 resolx = goomdata->resolx;
+  guint32 resoly = goomdata->resoly;
+  unsigned char *color = 1 + (unsigned char *) &color1;
+
+  switch (ID) {
+    case 0:                    /* Horizontal stereo lines */
+    {
+      color1 = 0x0000AA00;
+      color2 = 0x00AA0000;
+      break;
+    }
+
+    case 1:                    /* Stereo circles */
+    {
+      color1 = 0x00AA33DD;
+      color2 = 0x00AA33DD;
+      break;
+    }
+  }
+  *color = lighten (*color, power);
+  color++;
+  *color = lighten (*color, power);
+  color++;
+  *color = lighten (*color, power);
+  color = 1 + (unsigned char *) &color2;
+  *color = lighten (*color, power);
+  color++;
+  *color = lighten (*color, power);
+  color++;
+  *color = lighten (*color, power);
+
+  switch (ID) {
+    case 0:                    /* Horizontal stereo lines */
+    {
+      unsigned int i;
+
+      for (i = 0; i < 512; i++) {
+        guint32 plot;
+
+        plot = i * resolx / 512 + (resoly / 4 + data[0][i] / 1600) * resolx;
+        p[plot] = color1;
+        p[plot + 1] = color1;
+        plot = i * resolx / 512 + (resoly * 3 / 4 - data[1][i] / 1600) * resolx;
+        p[plot] = color2;
+        p[plot + 1] = color2;
+      }
+      break;
+    }
+
+    case 1:                    /* Stereo circles */
+    {
+      float z;
+      unsigned int monX = resolx / 2;
+      float monY = resoly / 4;
+      float monY2 = resoly / 2;
+
+      for (z = 0; z < 6.2832f; z += 1.0f / monY) {
+        /* float offset1 = 128+data[1][(unsigned int)(z*81.33f)])/200000; */
+        p[monX + (unsigned int) ((monY + ((float) resoly) * (128 +
+                        data[1][(unsigned int) (z * 81.33f)]) / 200000) *
+                cos (z) + resolx * (unsigned int) (monY2 + (monY +
+                        ((float) resoly) * (128 +
+                            data[1][(unsigned int) (z * 81.33f)]) / 400000) *
+                    sin (z)))] = color1;
+        p[monX + (unsigned int) ((monY - ((float) resoly) * (128 +
+                        data[0][(unsigned int) (z * 81.33f)]) / 200000) *
+                cos (z) + resolx * (unsigned int) (monY2 + (monY -
+                        ((float) resoly) * (128 +
+                            data[0][(unsigned int) (z * 81.33f)]) / 400000) *
+                    sin (z)))] = color2;
+      }
+      break;
+    }
+  }
+}
diff --git a/gst/goom2k1/lines.h b/gst/goom2k1/lines.h
new file mode 100644 (file)
index 0000000..548f339
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  lines.h
+ *  iGoom
+ *
+ *  Created by guillaum on Tue Aug 14 2001.
+ *  Copyright (c) 2001 ios. All rights reserved.
+ *
+ */
+#include <glib.h>
+
+#include "graphic.h"
+#include "goom_core.h"
+
+void goom_lines(GoomData *goomdata, gint16 data [2][512], unsigned int ID,unsigned int* p, guint32 power);
+
+