From a7bc7485b1a4d7e1b1a12ff593ca4ccb1d59e466 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sat, 23 Feb 2008 01:51:37 +0000 Subject: configure.ac: Add checks for Flex/Yacc/Bison and other furry animals, for the new goom 2k4 based plugin Original commit message from CVS: 2008-02-23 Bastien Nocera * 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 --- gst/goom/Makefile.am | 79 +- gst/goom/README | 3 + gst/goom/config_param.c | 141 ++ gst/goom/convolve_fx.c | 342 +++++ gst/goom/default_scripts.h | 6 + gst/goom/drawmethods.c | 204 +++ gst/goom/drawmethods.h | 9 + gst/goom/filters.c | 1284 ++++++++++-------- gst/goom/filters.h | 83 -- gst/goom/filters_mmx.s | 132 +- gst/goom/flying_stars_fx.c | 341 +++++ gst/goom/gfontlib.c | 260 ++++ gst/goom/gfontlib.h | 10 + gst/goom/gfontrle.c | 3080 ++++++++++++++++++++++++++++++++++++++++++ gst/goom/gfontrle.h | 7 + gst/goom/goom.h | 30 + gst/goom/goom_config.h | 28 + gst/goom/goom_config_param.h | 115 ++ gst/goom/goom_core.c | 1103 +++++++++++---- gst/goom/goom_core.h | 43 - gst/goom/goom_filters.h | 52 + gst/goom/goom_fx.h | 12 + gst/goom/goom_graphic.h | 74 + gst/goom/goom_plugin_info.h | 176 +++ gst/goom/goom_tools.c | 32 + gst/goom/goom_tools.h | 49 +- gst/goom/goom_typedefs.h | 11 + gst/goom/goom_visual_fx.h | 26 + gst/goom/goomsl.c | 1660 +++++++++++++++++++++++ gst/goom/goomsl.h | 34 + gst/goom/goomsl_hash.c | 153 +++ gst/goom/goomsl_hash.h | 40 + gst/goom/goomsl_heap.c | 126 ++ gst/goom/goomsl_heap.h | 29 + gst/goom/goomsl_lex.l | 94 ++ gst/goom/goomsl_private.h | 251 ++++ gst/goom/goomsl_yacc.y | 1405 +++++++++++++++++++ gst/goom/graphic.c | 16 +- gst/goom/graphic.h | 23 - gst/goom/gstgoom.c | 11 +- gst/goom/gstgoom.h | 4 +- gst/goom/ifs.c | 776 +++++++++++ gst/goom/ifs.h | 27 + gst/goom/lines.c | 288 ++-- gst/goom/lines.h | 83 +- gst/goom/mathtools.c | 95 ++ gst/goom/mathtools.h | 36 + gst/goom/mmx.c | 256 ++++ gst/goom/mmx.h | 729 ++++++++++ gst/goom/motif_goom1.h | 1026 ++++++++++++++ gst/goom/motif_goom2.h | 1026 ++++++++++++++ gst/goom/plugin_info.c | 222 +++ gst/goom/ppc_drawings.h | 18 + gst/goom/ppc_drawings.s | 381 ++++++ gst/goom/ppc_zoom_ultimate.h | 14 + gst/goom/ppc_zoom_ultimate.s | 323 +++++ gst/goom/sound_tester.c | 143 ++ gst/goom/sound_tester.h | 11 + gst/goom/surf3d.c | 123 ++ gst/goom/surf3d.h | 38 + gst/goom/surf3d.s | 484 +++++++ gst/goom/tentacle3d.c | 333 +++++ gst/goom/tentacle3d.h | 8 + gst/goom/v3d.c | 20 + gst/goom/v3d.h | 65 + gst/goom/xmmx.c | 364 +++++ gst/goom/xmmx.h | 537 ++++++++ 67 files changed, 17885 insertions(+), 1119 deletions(-) create mode 100644 gst/goom/config_param.c create mode 100644 gst/goom/convolve_fx.c create mode 100644 gst/goom/default_scripts.h create mode 100644 gst/goom/drawmethods.c create mode 100644 gst/goom/drawmethods.h delete mode 100644 gst/goom/filters.h create mode 100644 gst/goom/flying_stars_fx.c create mode 100644 gst/goom/gfontlib.c create mode 100644 gst/goom/gfontlib.h create mode 100644 gst/goom/gfontrle.c create mode 100644 gst/goom/gfontrle.h create mode 100644 gst/goom/goom.h create mode 100644 gst/goom/goom_config.h create mode 100644 gst/goom/goom_config_param.h delete mode 100644 gst/goom/goom_core.h create mode 100644 gst/goom/goom_filters.h create mode 100644 gst/goom/goom_fx.h create mode 100644 gst/goom/goom_graphic.h create mode 100644 gst/goom/goom_plugin_info.h create mode 100644 gst/goom/goom_tools.c create mode 100644 gst/goom/goom_typedefs.h create mode 100644 gst/goom/goom_visual_fx.h create mode 100644 gst/goom/goomsl.c create mode 100644 gst/goom/goomsl.h create mode 100644 gst/goom/goomsl_hash.c create mode 100644 gst/goom/goomsl_hash.h create mode 100644 gst/goom/goomsl_heap.c create mode 100644 gst/goom/goomsl_heap.h create mode 100644 gst/goom/goomsl_lex.l create mode 100644 gst/goom/goomsl_private.h create mode 100644 gst/goom/goomsl_yacc.y delete mode 100644 gst/goom/graphic.h create mode 100644 gst/goom/ifs.c create mode 100644 gst/goom/ifs.h create mode 100644 gst/goom/mathtools.c create mode 100644 gst/goom/mathtools.h create mode 100644 gst/goom/mmx.c create mode 100644 gst/goom/mmx.h create mode 100644 gst/goom/motif_goom1.h create mode 100644 gst/goom/motif_goom2.h create mode 100644 gst/goom/plugin_info.c create mode 100644 gst/goom/ppc_drawings.h create mode 100644 gst/goom/ppc_drawings.s create mode 100644 gst/goom/ppc_zoom_ultimate.h create mode 100644 gst/goom/ppc_zoom_ultimate.s create mode 100644 gst/goom/sound_tester.c create mode 100644 gst/goom/sound_tester.h create mode 100644 gst/goom/surf3d.c create mode 100644 gst/goom/surf3d.h create mode 100644 gst/goom/surf3d.s create mode 100644 gst/goom/tentacle3d.c create mode 100644 gst/goom/tentacle3d.h create mode 100644 gst/goom/v3d.c create mode 100644 gst/goom/v3d.h create mode 100644 gst/goom/xmmx.c create mode 100644 gst/goom/xmmx.h (limited to 'gst/goom') diff --git a/gst/goom/Makefile.am b/gst/goom/Makefile.am index 4f4abb76..41e9cb32 100644 --- a/gst/goom/Makefile.am +++ b/gst/goom/Makefile.am @@ -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 ' >> 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 ' >> 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: + diff --git a/gst/goom/README b/gst/goom/README index f12cf1b5..1b3736a1 100644 --- a/gst/goom/README +++ b/gst/goom/README @@ -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 index 00000000..4c4cebd9 --- /dev/null +++ b/gst/goom/config_param.c @@ -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 + +/* 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 index 00000000..261c5fa8 --- /dev/null +++ b/gst/goom/convolve_fx.c @@ -0,0 +1,342 @@ +#include "goom_fx.h" +#include "goom_plugin_info.h" +#include "goomsl.h" +#include "goom_config.h" +#include +#include +#include +#include + +//#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 + +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 index 00000000..5984d705 --- /dev/null +++ b/gst/goom/default_scripts.h @@ -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 index 00000000..929564da --- /dev/null +++ b/gst/goom/drawmethods.c @@ -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 index 00000000..76ad6ca0 --- /dev/null +++ b/gst/goom/drawmethods.h @@ -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 */ diff --git a/gst/goom/filters.c b/gst/goom/filters.c index b898e89c..07e989e7 100644 --- a/gst/goom/filters.c +++ b/gst/goom/filters.c @@ -1,606 +1,836 @@ +// --- 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 #include #include #include +#include -#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 index 65eb3e25..00000000 --- a/gst/goom/filters.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef FILTERS_H -#define FILTERS_H - -#include - -#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/goom/filters_mmx.s b/gst/goom/filters_mmx.s index 337de56c..765f1588 100644 --- a/gst/goom/filters_mmx.s +++ b/gst/goom/filters_mmx.s @@ -15,49 +15,117 @@ .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 index 00000000..c323c7c9 --- /dev/null +++ b/gst/goom/flying_stars_fx.c @@ -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 index 00000000..52d3e545 --- /dev/null +++ b/gst/goom/gfontlib.c @@ -0,0 +1,260 @@ +#include "goom_config.h" +#include "gfontrle.h" +#include "gfontlib.h" +#include +#include + +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 index 00000000..0520b7da --- /dev/null +++ b/gst/goom/gfontlib.h @@ -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 index 00000000..e57b494d --- /dev/null +++ b/gst/goom/gfontrle.c @@ -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 index 00000000..41e2462f --- /dev/null +++ b/gst/goom/gfontrle.h @@ -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 index 00000000..b0ddab17 --- /dev/null +++ b/gst/goom/goom.h @@ -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 index 00000000..5f6f1589 --- /dev/null +++ b/gst/goom/goom_config.h @@ -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 index 00000000..3c6838d3 --- /dev/null +++ b/gst/goom/goom_config_param.h @@ -0,0 +1,115 @@ +#ifndef _CONFIG_PARAM_H +#define _CONFIG_PARAM_H + +#include + +/** + * 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 diff --git a/gst/goom/goom_core.c b/gst/goom/goom_core.c index d66ffe25..5dee8278 100644 --- a/gst/goom/goom_core.c +++ b/gst/goom/goom_core.c @@ -1,412 +1,951 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include - +/** +* 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 +#include #include #include -#include "goom_core.h" +#include + +#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 -#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, ¶m1, ¶m2, &couleur, &mode, &litude, + 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, ¶m1, ¶m2, &couleur1, + &mode, &litude, 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, ¶m1, ¶m2, &couleur1, + &mode, &litude, 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 index 1fbc0ee8..00000000 --- a/gst/goom/goom_core.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _GOOMCORE_H -#define _GOOMCORE_H - -#include - -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 index 00000000..f015499a --- /dev/null +++ b/gst/goom/goom_filters.h @@ -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 index 00000000..e672ece3 --- /dev/null +++ b/gst/goom/goom_fx.h @@ -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 index 00000000..9deaf5a9 --- /dev/null +++ b/gst/goom/goom_graphic.h @@ -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 index 00000000..8d5d098b --- /dev/null +++ b/gst/goom/goom_plugin_info.h @@ -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 index 00000000..ebca69e2 --- /dev/null +++ b/gst/goom/goom_tools.c @@ -0,0 +1,32 @@ +#include "goom_tools.h" +#include + +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--; + } +} diff --git a/gst/goom/goom_tools.h b/gst/goom/goom_tools.h index 6178dbaf..31d044e4 100644 --- a/gst/goom/goom_tools.h +++ b/gst/goom/goom_tools.h @@ -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 index 00000000..76036504 --- /dev/null +++ b/gst/goom/goom_typedefs.h @@ -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 index 00000000..6939ac80 --- /dev/null +++ b/gst/goom/goom_visual_fx.h @@ -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 index 00000000..b07b2596 --- /dev/null +++ b/gst/goom/goomsl.c @@ -0,0 +1,1660 @@ +#include +#include +#include +#include +#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 : int\n" + "external : int\n" + "external : 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 index 00000000..b9f20d6c --- /dev/null +++ b/gst/goom/goomsl.h @@ -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 index 00000000..3ce38a72 --- /dev/null +++ b/gst/goom/goomsl_hash.c @@ -0,0 +1,153 @@ +#include "goomsl_hash.h" +#include +#include + +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 index 00000000..26f45167 --- /dev/null +++ b/gst/goom/goomsl_hash.h @@ -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 index 00000000..4cbab5cc --- /dev/null +++ b/gst/goom/goomsl_heap.c @@ -0,0 +1,126 @@ +#include "goomsl_heap.h" +#include + +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 index 00000000..a22bac69 --- /dev/null +++ b/gst/goom/goomsl_heap.h @@ -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 index 00000000..3079c022 --- /dev/null +++ b/gst/goom/goomsl_lex.l @@ -0,0 +1,94 @@ +%{ + +#include +#include +#include +#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 + +%% + +^[ \t]*\n { ++currentGoomSL->num_lines; /* Ignore empty lines */ } +^[ \t]*"//"[^\n]*\n { ++currentGoomSL->num_lines; /* Ignore empty lines */ } + +\n { ++currentGoomSL->num_lines; yylval.charValue=*yytext; BEGIN INITIAL; return '\n'; } +\n { ++currentGoomSL->num_lines; yylval.charValue=*yytext; return '\n'; } + +"*/" { BEGIN INITIAL; } +\n { ++currentGoomSL->num_lines; } +. { /* eat up comment */ } + +"#RST_LINE#" { currentGoomSL->num_lines = 0; } +"#FILE ".*"#" { currentGoomSL->num_lines = 0; printf("%s\n", yytext); } +"#"[^\n]* { /* ignore preprocessor lines */ } + +"/*" { BEGIN C_COMMENT; } +"//" { BEGIN LINE_COMMENT; } +\" { BEGIN STRING; string_size=0; } + +"\\n" { string[string_size++] = '\n'; } +"\\\"" { string[string_size++] = '\"'; } +\" { /* 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_size++] = *yytext; } + +"float" { return FLOAT_TK; } +"int" { return INT_TK; } +"boolean" { return INT_TK; } +"ptr" { return PTR_TK; } +"string" { return PTR_TK; } +"declare" { return DECLARE; } +"external" { return EXTERNAL; } +"struct" { return STRUCT; } +"not" { return NOT; } +"while" { return WHILE; } +"do" { return DO; } +"for" { return FOR; } +"in" { return IN; } +"true" { strncpy(yylval.strValue, "1", 2047); return LTYPE_INTEGER; } +"false" { strncpy(yylval.strValue, "0", 2047); return LTYPE_INTEGER; } +{ID} { strncpy(yylval.strValue, yytext, 2047); return LTYPE_VAR; } +{DIGIT}+ { strncpy(yylval.strValue, yytext, 2047); return LTYPE_INTEGER; } +\'.\' { sprintf(yylval.strValue, "%d", (int)yytext[1]); return LTYPE_INTEGER; } +"0x"{XDIGIT}+ { strncpy(yylval.strValue, yytext, 2047); return LTYPE_INTEGER; } +{DIGIT}+"."{DIGIT}* { strncpy(yylval.strValue, yytext, 2047); return LTYPE_FLOAT; } +{DIGIT}+"%" { sprintf(yylval.strValue, "%3.2f", atof(yytext)/100.0f); return LTYPE_FLOAT; } +"+=" { return PLUS_EQ; } +"*=" { return MUL_EQ; } +"-=" { return SUB_EQ; } +"/=" { return DIV_EQ; } +"<=" { return LOW_EQ; } +">=" { return SUP_EQ; } +"!=" { return NOT_EQ; } +"<>" { return NOT_EQ; } +[ \t]+ /* eat up whitespace */ +. { 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 index 00000000..8be15157 --- /dev/null +++ b/gst/goom/goomsl_private.h @@ -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 index 00000000..c424a50a --- /dev/null +++ b/gst/goom/goomsl_yacc.y @@ -0,0 +1,1405 @@ +/** + * copyright 2004, Jean-Christophe Hoelt + * + * This program is released under the terms of the GNU Lesser General Public Licence. + */ +%{ + #include + #include + #include + #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;jtype == 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;iunode.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 LTYPE_INTEGER +%token LTYPE_FLOAT +%token LTYPE_VAR +%token 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 return_type +%type expression constValue instruction test func_call func_call_expression +%type start_block affectation_list affectation_in_list affectation declaration +%type var_list_content var_list +%type task_name ext_task_name +%type leave_namespace +%type struct_members +%type 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); +} /* }}} */ + diff --git a/gst/goom/graphic.c b/gst/goom/graphic.c index c20f987d..2ee71a6d 100644 --- a/gst/goom/graphic.c +++ b/gst/goom/graphic.c @@ -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 index 4154d7fd..00000000 --- a/gst/goom/graphic.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef GRAPHIC_H -#define GRAPHIC_H - -#include /* 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/goom/gstgoom.c b/gst/goom/gstgoom.c index ca9b3111..7ba6654a 100644 --- a/gst/goom/gstgoom.c +++ b/gst/goom/gstgoom.c @@ -44,7 +44,7 @@ #include #include "gstgoom.h" #include -#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=%" diff --git a/gst/goom/gstgoom.h b/gst/goom/gstgoom.h index 9c25f453..e9ca83ce 100644 --- a/gst/goom/gstgoom.h +++ b/gst/goom/gstgoom.h @@ -24,7 +24,7 @@ G_BEGIN_DECLS #include #include -#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 index 00000000..8e72548f --- /dev/null +++ b/gst/goom/ifs.c @@ -0,0 +1,776 @@ +/* + * ifs.c --- modified iterated functions system for goom. + */ + +/*- + * Copyright (c) 1997 by Massimino Pascal + * + * 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 +#include +#include + +#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<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 index 00000000..fab04266 --- /dev/null +++ b/gst/goom/ifs.h @@ -0,0 +1,27 @@ +/* + * File created 11 april 2002 by JeKo + */ + +#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 diff --git a/gst/goom/lines.c b/gst/goom/lines.c index 3214e1db..a2a94d43 100644 --- a/gst/goom/lines.c +++ b/gst/goom/lines.c @@ -1,107 +1,241 @@ /* * 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 +#include +#include +#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); } } diff --git a/gst/goom/lines.h b/gst/goom/lines.h index 548f339a..9c6df924 100644 --- a/gst/goom/lines.h +++ b/gst/goom/lines.h @@ -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 -#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 index 00000000..4b275c62 --- /dev/null +++ b/gst/goom/mathtools.c @@ -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 index 00000000..0e2293c3 --- /dev/null +++ b/gst/goom/mathtools.h @@ -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 index 00000000..4cee0acb --- /dev/null +++ b/gst/goom/mmx.c @@ -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 index 00000000..3fae26b9 --- /dev/null +++ b/gst/goom/mmx.h @@ -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 + +#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 index 00000000..b4a9f3f1 --- /dev/null +++ b/gst/goom/motif_goom1.h @@ -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 index 00000000..4bde2a3d --- /dev/null +++ b/gst/goom/motif_goom2.h @@ -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 index 00000000..2aeeb4fe --- /dev/null +++ b/gst/goom/plugin_info.c @@ -0,0 +1,222 @@ +#include "config.h" + +#include "goom_plugin_info.h" +#include "goom_fx.h" +#include "default_scripts.h" +#include "drawmethods.h" +#include +#include + + +#if defined (HAVE_CPU_PPC64) || defined (HAVE_CPU_PPC) +#include +#include +#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 +#include +#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 index 00000000..ee438c28 --- /dev/null +++ b/gst/goom/ppc_drawings.h @@ -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 index 00000000..845e5ea1 --- /dev/null +++ b/gst/goom/ppc_drawings.s @@ -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 index 00000000..d6932e7e --- /dev/null +++ b/gst/goom/ppc_zoom_ultimate.h @@ -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 index 00000000..da252c67 --- /dev/null +++ b/gst/goom/ppc_zoom_ultimate.s @@ -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 index 00000000..214ca0ef --- /dev/null +++ b/gst/goom/sound_tester.c @@ -0,0 +1,143 @@ +#include "sound_tester.h" + +#include +#include + +/* 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 index 00000000..51545a80 --- /dev/null +++ b/gst/goom/sound_tester.h @@ -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 index 00000000..f6810f85 --- /dev/null +++ b/gst/goom/surf3d.c @@ -0,0 +1,123 @@ +#include "surf3d.h" +#include "goom_plugin_info.h" +#include +#include +#include + +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 index 00000000..482b6a09 --- /dev/null +++ b/gst/goom/surf3d.h @@ -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 index 00000000..f8c8c5d4 --- /dev/null +++ b/gst/goom/surf3d.s @@ -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 index 00000000..44503934 --- /dev/null +++ b/gst/goom/tentacle3d.c @@ -0,0 +1,333 @@ +#include + +#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 index 00000000..ad0858fa --- /dev/null +++ b/gst/goom/tentacle3d.h @@ -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 index 00000000..54e3c97d --- /dev/null +++ b/gst/goom/v3d.c @@ -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 index 00000000..7690847f --- /dev/null +++ b/gst/goom/v3d.h @@ -0,0 +1,65 @@ +#ifndef _V3D_H +#define _V3D_H + +#include +#include +#include + +#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 index 00000000..40f27fbc --- /dev/null +++ b/gst/goom/xmmx.c @@ -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 index 00000000..70ef3614 --- /dev/null +++ b/gst/goom/xmmx.h @@ -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 + +#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 + -- cgit