aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/3rdparty/boing/gfxconf.h (renamed from demos/3thparty/boing/gfxconf.h)0
-rw-r--r--demos/3rdparty/boing/main.c (renamed from demos/3thparty/boing/main.c)0
-rw-r--r--demos/3rdparty/bubbles/gfxconf.h (renamed from demos/3thparty/bubbles/gfxconf.h)0
-rw-r--r--demos/3rdparty/bubbles/main.c (renamed from demos/3thparty/bubbles/main.c)0
-rw-r--r--demos/3rdparty/readme.txt (renamed from demos/3thparty/readme.txt)0
-rw-r--r--demos/modules/gdisp/gdisp_images_animated/gfxconf.h57
-rw-r--r--demos/modules/gdisp/gdisp_images_animated/main.c101
-rw-r--r--demos/modules/gdisp/gdisp_images_animated/testanim.gifbin0 -> 8938 bytes
-rw-r--r--demos/modules/gdisp/gdisp_images_animated/testanim.h567
-rw-r--r--gfxconf.example.h1
-rw-r--r--include/gdisp/image.h20
-rw-r--r--include/gdisp/options.h7
-rw-r--r--src/gdisp/image.c33
-rw-r--r--src/gdisp/image_bmp.c21
-rw-r--r--src/gdisp/image_gif.c1170
15 files changed, 1953 insertions, 24 deletions
diff --git a/demos/3thparty/boing/gfxconf.h b/demos/3rdparty/boing/gfxconf.h
index 45b6d7ab..45b6d7ab 100644
--- a/demos/3thparty/boing/gfxconf.h
+++ b/demos/3rdparty/boing/gfxconf.h
diff --git a/demos/3thparty/boing/main.c b/demos/3rdparty/boing/main.c
index a34cd2a9..a34cd2a9 100644
--- a/demos/3thparty/boing/main.c
+++ b/demos/3rdparty/boing/main.c
diff --git a/demos/3thparty/bubbles/gfxconf.h b/demos/3rdparty/bubbles/gfxconf.h
index 9b1f76a6..9b1f76a6 100644
--- a/demos/3thparty/bubbles/gfxconf.h
+++ b/demos/3rdparty/bubbles/gfxconf.h
diff --git a/demos/3thparty/bubbles/main.c b/demos/3rdparty/bubbles/main.c
index 81c5dbe3..81c5dbe3 100644
--- a/demos/3thparty/bubbles/main.c
+++ b/demos/3rdparty/bubbles/main.c
diff --git a/demos/3thparty/readme.txt b/demos/3rdparty/readme.txt
index 3f97204a..3f97204a 100644
--- a/demos/3thparty/readme.txt
+++ b/demos/3rdparty/readme.txt
diff --git a/demos/modules/gdisp/gdisp_images_animated/gfxconf.h b/demos/modules/gdisp/gdisp_images_animated/gfxconf.h
new file mode 100644
index 00000000..cd368e95
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_images_animated/gfxconf.h
@@ -0,0 +1,57 @@
+/**
+ * This file has a different license to the rest of the GFX system.
+ * You can copy, modify and distribute this file as you see fit.
+ * You do not need to publish your source modifications to this file.
+ * The only thing you are not permitted to do is to relicense it
+ * under a different license.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN FALSE
+#define GFX_USE_GEVENT FALSE
+#define GFX_USE_GTIMER FALSE
+#define GFX_USE_GINPUT FALSE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT FALSE
+#define GDISP_NEED_CIRCLE FALSE
+#define GDISP_NEED_ELLIPSE FALSE
+#define GDISP_NEED_ARC FALSE
+#define GDISP_NEED_CONVEX_POLYGON FALSE
+#define GDISP_NEED_SCROLL FALSE
+#define GDISP_NEED_PIXELREAD FALSE
+#define GDISP_NEED_CONTROL FALSE
+#define GDISP_NEED_IMAGE TRUE
+#define GDISP_NEED_MULTITHREAD FALSE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_SMALL FALSE
+#define GDISP_INCLUDE_FONT_LARGER FALSE
+#define GDISP_INCLUDE_FONT_UI1 FALSE
+#define GDISP_INCLUDE_FONT_UI2 FALSE
+#define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
+
+/* GDISP image decoders */
+#define GDISP_NEED_IMAGE_NATIVE FALSE
+#define GDISP_NEED_IMAGE_GIF TRUE
+#define GDISP_NEED_IMAGE_BMP FALSE
+#define GDISP_NEED_IMAGE_JPG FALSE
+#define GDISP_NEED_IMAGE_PNG FALSE
+#define GDISP_NEED_IMAGE_ACCOUNTING FALSE
+
+/* Features for the GWIN sub-system. */
+#define GWIN_NEED_BUTTON FALSE
+#define GWIN_NEED_CONSOLE FALSE
+
+/* Features for the GINPUT sub-system. */
+#define GINPUT_NEED_MOUSE FALSE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/modules/gdisp/gdisp_images_animated/main.c b/demos/modules/gdisp/gdisp_images_animated/main.c
new file mode 100644
index 00000000..d5c3d712
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_images_animated/main.c
@@ -0,0 +1,101 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012, 2013
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#define USE_IMAGE_CACHE FALSE // Only if you want to get performance at the expense of RAM
+#define MY_BG_COLOR RGB2COLOR(220, 220, 255) // Pale blue so we can see the transparent parts
+
+#ifdef WIN32
+ #define USE_MEMORY_FILE FALSE // Can be true or false for Win32
+#else
+ #define USE_MEMORY_FILE TRUE // Non-Win32 - use the compiled in image
+#endif
+
+#define SHOW_ERROR(color) gdispFillArea(swidth-10, 0, 10, sheight, color)
+
+#if USE_MEMORY_FILE
+ #include "testanim.h"
+#endif
+
+static gdispImage myImage;
+
+/**
+ * This demo display the animated gif (either directly from a file or from a
+ * file encoded in flash.
+ * To show the various stages of encoding it displays a colored bar down the
+ * right hand side of the display to indicate what is happenning.
+ * Green - Image has completed and is displayed correctly
+ * Red - A really bad image fault. We couldn't open the image
+ * Yellow - Waiting to decode the next animation frame
+ * Orange - Decoding a frame has produced an error.
+ */
+int main(void) {
+ coord_t swidth, sheight;
+ systime_t delay;
+
+ halInit(); // Initialize the Hardware
+ chSysInit(); // Initialize the OS
+ gdispInit(); // Initialize the display
+
+ gdispClear(MY_BG_COLOR);
+
+ // Get the display dimensions
+ swidth = gdispGetWidth();
+ sheight = gdispGetHeight();
+
+ // Set up IO for our image
+#if USE_MEMORY_FILE
+ gdispImageSetMemoryReader(&myImage, testanim);
+#else
+ gdispImageSetSimulFileReader(&myImage, "testanim.gif");
+#endif
+
+ if (gdispImageOpen(&myImage) == GDISP_IMAGE_ERR_OK) {
+ gdispImageSetBgColor(&myImage, MY_BG_COLOR);
+ while(1) {
+ #if USE_IMAGE_CACHE
+ gdispImageCache(&myImage);
+ #endif
+ if (gdispImageDraw(&myImage, 5, 5, myImage.width, myImage.height, 0, 0) != GDISP_IMAGE_ERR_OK) {
+ SHOW_ERROR(Orange);
+ break;
+ }
+ delay = gdispImageNext(&myImage);
+ if (delay == TIME_INFINITE) {
+ SHOW_ERROR(Green);
+ break;
+ }
+ SHOW_ERROR(Yellow);
+ if (delay != TIME_IMMEDIATE)
+ chThdSleepMilliseconds(delay);
+ }
+ gdispImageClose(&myImage);
+ } else
+ SHOW_ERROR(Red);
+
+ while(1) {
+ chThdSleepMilliseconds(1000);
+ }
+
+ return 0;
+}
diff --git a/demos/modules/gdisp/gdisp_images_animated/testanim.gif b/demos/modules/gdisp/gdisp_images_animated/testanim.gif
new file mode 100644
index 00000000..6639acb2
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_images_animated/testanim.gif
Binary files differ
diff --git a/demos/modules/gdisp/gdisp_images_animated/testanim.h b/demos/modules/gdisp/gdisp_images_animated/testanim.h
new file mode 100644
index 00000000..ce2ba8c7
--- /dev/null
+++ b/demos/modules/gdisp/gdisp_images_animated/testanim.h
@@ -0,0 +1,567 @@
+/**
+ * This file was generated from "testanim.gif" using...
+ *
+ * file2c -cs testanim.gif testanim.h
+ *
+ */
+static const unsigned char testanim[] = {
+ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x99, 0x00, 0x73, 0x00, 0xE6, 0x46, 0x00, 0x04, 0x07, 0x00,
+ 0x10, 0x0F, 0x04, 0x1D, 0x1E, 0x29, 0x20, 0x23, 0x08, 0x2E, 0x2C, 0x18, 0x31, 0x32, 0x01, 0x2E,
+ 0x32, 0x2A, 0x35, 0x37, 0x3B, 0x20, 0x28, 0x42, 0x2B, 0x37, 0x53, 0x3E, 0x41, 0x03, 0x3C, 0x44,
+ 0x53, 0x3C, 0x4E, 0x67, 0x44, 0x3B, 0x34, 0x44, 0x3D, 0x43, 0x63, 0x36, 0x42, 0x7A, 0x35, 0x46,
+ 0x51, 0x4E, 0x04, 0x4C, 0x49, 0x32, 0x62, 0x5C, 0x06, 0x6C, 0x6D, 0x0A, 0x68, 0x65, 0x2C, 0x4F,
+ 0x55, 0x68, 0x5F, 0x5F, 0x60, 0x5D, 0x66, 0x79, 0x63, 0x5B, 0x4E, 0x4A, 0x5C, 0x81, 0x58, 0x68,
+ 0x89, 0x56, 0x79, 0xAF, 0x63, 0x6E, 0x81, 0x6E, 0x75, 0x8C, 0x78, 0x61, 0x8C, 0x6E, 0x7C, 0xA6,
+ 0x7F, 0x7E, 0xBF, 0x7D, 0x84, 0x7B, 0x5C, 0x82, 0xBA, 0x7D, 0x83, 0x96, 0x5B, 0x8A, 0xD2, 0x5F,
+ 0x9D, 0xEF, 0x77, 0xA4, 0xD0, 0x6F, 0xB2, 0xEF, 0x7E, 0xC1, 0xF3, 0x8C, 0x7F, 0x33, 0xB5, 0x6C,
+ 0x83, 0x9C, 0x86, 0x4B, 0x80, 0x83, 0xA1, 0x88, 0x95, 0xAA, 0x8C, 0x9B, 0xB5, 0x99, 0xA6, 0x9A,
+ 0xAE, 0xAD, 0x9A, 0x92, 0x9F, 0xC0, 0xA7, 0xA4, 0xC0, 0xA1, 0xAA, 0xC0, 0xAE, 0xB7, 0xD0, 0xB8,
+ 0xC3, 0xBC, 0x99, 0xC8, 0xDB, 0x91, 0xCD, 0xF0, 0x9C, 0xD7, 0xF1, 0xB8, 0xC7, 0xD5, 0xAE, 0xE7,
+ 0xF9, 0xC8, 0xC9, 0xBB, 0xD3, 0xC2, 0xBB, 0xC2, 0xD2, 0xDE, 0xD1, 0xE4, 0xDE, 0xC8, 0xF2, 0xEA,
+ 0xE1, 0xDE, 0xDB, 0xEE, 0xEB, 0xDA, 0xFA, 0xF7, 0xE6, 0xFD, 0xFC, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x21, 0xFF, 0x0B,
+ 0x4E, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2E, 0x30, 0x03, 0x01, 0x00, 0x00, 0x00,
+ 0x21, 0xF9, 0x04, 0x05, 0x16, 0x00, 0x46, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x73,
+ 0x00, 0x00, 0x07, 0xFE, 0x80, 0x00, 0x01, 0x01, 0x16, 0x16, 0x82, 0x04, 0x08, 0x46, 0x8A, 0x8B,
+ 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x94, 0x38, 0x26, 0x29, 0x29,
+ 0x25, 0x1E, 0x16, 0x1B, 0x02, 0x02, 0x04, 0x83, 0x00, 0x82, 0x02, 0x01, 0x00, 0x07, 0x27, 0x2D,
+ 0xA5, 0xAD, 0x82, 0x00, 0x08, 0xA7, 0x03, 0x0B, 0x97, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0x95, 0x38,
+ 0x08, 0x0C, 0x0C, 0x16, 0x18, 0x18, 0x1B, 0x16, 0x01, 0x08, 0x09, 0xA4, 0xA5, 0xB1, 0x2D, 0x08,
+ 0x0B, 0xAE, 0x00, 0xA1, 0x00, 0xA3, 0x82, 0x1B, 0x23, 0x20, 0xBA, 0xD7, 0xD8, 0xD9, 0xD8, 0x25,
+ 0x25, 0x32, 0x09, 0x08, 0x85, 0x16, 0xDF, 0x01, 0xA1, 0x06, 0x83, 0xE7, 0x82, 0x08, 0x01, 0xAC,
+ 0xC5, 0x0C, 0xA5, 0x0B, 0xA8, 0xA4, 0x01, 0x03, 0xA7, 0xDA, 0xF6, 0xF7, 0xF8, 0x8E, 0xDF, 0xCB,
+ 0xBF, 0x85, 0x08, 0xFF, 0xE6, 0x4E, 0x91, 0x43, 0x95, 0x2A, 0x40, 0x82, 0x66, 0x86, 0x50, 0xE0,
+ 0x00, 0xC0, 0xEE, 0x95, 0xC0, 0x75, 0xF9, 0x22, 0x4A, 0xCC, 0xF5, 0x6D, 0xC1, 0xAF, 0x0D, 0x1B,
+ 0x18, 0xFC, 0x8B, 0xB5, 0x80, 0x99, 0x81, 0x53, 0xCF, 0xCE, 0x2D, 0x80, 0x57, 0x0C, 0x43, 0x0B,
+ 0x14, 0x08, 0x5C, 0x91, 0x22, 0x46, 0x6B, 0xA2, 0xCB, 0x97, 0x90, 0x34, 0x0A, 0xF8, 0x27, 0xC0,
+ 0x62, 0xAC, 0x99, 0x33, 0x8D, 0x85, 0xEA, 0x38, 0xE0, 0x5C, 0x80, 0x03, 0xCD, 0x4A, 0x11, 0x00,
+ 0xB0, 0x21, 0x05, 0x41, 0x9F, 0xA6, 0x2C, 0x30, 0x80, 0xC9, 0x74, 0xE2, 0x0C, 0x23, 0x00, 0x47,
+ 0xCE, 0x2C, 0x94, 0x20, 0x94, 0x80, 0x6F, 0xA1, 0x36, 0xCE, 0xF4, 0x80, 0xAA, 0x81, 0xA0, 0xA0,
+ 0x00, 0x06, 0x3C, 0xF3, 0xA0, 0x52, 0x90, 0xCF, 0x44, 0x4D, 0xD3, 0x66, 0x5B, 0x11, 0xC2, 0xC2,
+ 0x32, 0x8E, 0xFE, 0x16, 0x16, 0x08, 0x50, 0x4A, 0x33, 0x67, 0x47, 0x04, 0x06, 0xC0, 0x81, 0x90,
+ 0x4B, 0xB0, 0x94, 0xD8, 0x78, 0x09, 0xC8, 0x96, 0x92, 0xE7, 0x33, 0x00, 0x06, 0xB5, 0x88, 0x71,
+ 0xE5, 0xE0, 0x70, 0x80, 0xE6, 0xC7, 0x6F, 0xC6, 0x22, 0x83, 0x8B, 0x65, 0xE0, 0xEE, 0x81, 0x04,
+ 0x16, 0x7A, 0xAA, 0x1B, 0x2C, 0xE0, 0x59, 0xA9, 0xCE, 0x9D, 0xE5, 0x0E, 0x7E, 0x35, 0x98, 0x5C,
+ 0xE2, 0xD3, 0x96, 0x72, 0x78, 0x5A, 0xF0, 0x31, 0x32, 0x56, 0x66, 0x1B, 0x63, 0x13, 0xA8, 0xBC,
+ 0x00, 0x58, 0xAB, 0x79, 0x03, 0x8D, 0x25, 0x2B, 0x65, 0xA0, 0xF1, 0x68, 0xB3, 0xF1, 0x36, 0x50,
+ 0x5A, 0x8A, 0x3A, 0xED, 0x07, 0x10, 0x0C, 0x3A, 0x62, 0x86, 0xAD, 0x35, 0x56, 0xEC, 0x7E, 0xB5,
+ 0x99, 0x1D, 0x3C, 0x70, 0x3B, 0x1A, 0x80, 0x04, 0x97, 0x35, 0x5A, 0xC4, 0x40, 0xE8, 0xF7, 0xD1,
+ 0x9E, 0xC4, 0x8D, 0x68, 0x70, 0xB4, 0x21, 0x81, 0x22, 0x6E, 0x46, 0x0A, 0x09, 0x10, 0xDF, 0xA8,
+ 0x84, 0xB0, 0x12, 0xC5, 0x71, 0xC9, 0xB4, 0x20, 0xE0, 0x40, 0xF2, 0x8A, 0xB1, 0x9D, 0x5B, 0xD0,
+ 0xB0, 0x1A, 0x18, 0xDE, 0x94, 0x5E, 0xB9, 0x32, 0x0A, 0x46, 0x07, 0x8D, 0xE4, 0x0B, 0x7D, 0x66,
+ 0xDD, 0x16, 0x4F, 0x00, 0xF0, 0x29, 0xD2, 0x8B, 0x11, 0x0C, 0x08, 0x67, 0x11, 0x01, 0x23, 0x55,
+ 0x58, 0xDB, 0x02, 0x18, 0x60, 0xE8, 0xC1, 0x02, 0xC3, 0x00, 0x15, 0x97, 0x00, 0x0F, 0x40, 0x10,
+ 0x1F, 0x25, 0x1F, 0xDC, 0xB7, 0xC1, 0x5D, 0x35, 0xC9, 0x05, 0x94, 0x31, 0x09, 0x54, 0x85, 0xC0,
+ 0x30, 0xC1, 0x84, 0x63, 0x81, 0x07, 0x02, 0x18, 0xA0, 0x92, 0x61, 0x07, 0x14, 0xB2, 0xC0, 0x2C,
+ 0xBE, 0x94, 0x87, 0xCC, 0x2B, 0xE8, 0x0C, 0xD2, 0x20, 0x07, 0x73, 0x19, 0x51, 0xC2, 0x41, 0xB4,
+ 0x59, 0xFE, 0xB8, 0x00, 0x85, 0x23, 0x11, 0x70, 0xC1, 0x02, 0x0D, 0x60, 0xE0, 0x01, 0x02, 0x19,
+ 0x8E, 0x34, 0x0B, 0x06, 0x27, 0xA4, 0x30, 0x22, 0x24, 0x98, 0x85, 0xC3, 0x80, 0x01, 0xFE, 0x6C,
+ 0x84, 0x61, 0x8E, 0x71, 0x05, 0x63, 0xE6, 0x5C, 0x85, 0x80, 0x80, 0xD7, 0x60, 0xB3, 0x10, 0x70,
+ 0x40, 0x00, 0xB5, 0x61, 0xA0, 0x40, 0x04, 0x18, 0x30, 0x70, 0x80, 0x01, 0x09, 0x88, 0x35, 0xDA,
+ 0x82, 0xD1, 0x58, 0xA0, 0xC8, 0x31, 0x79, 0xED, 0x48, 0x61, 0x95, 0x71, 0x5D, 0x68, 0xC0, 0x47,
+ 0x14, 0x52, 0x18, 0xD7, 0x8C, 0x0B, 0x78, 0x80, 0xC1, 0x00, 0x95, 0x65, 0xB8, 0xA5, 0x3E, 0xDF,
+ 0x08, 0xF3, 0x4F, 0x02, 0xC9, 0x4D, 0x76, 0x90, 0x9D, 0x91, 0xCD, 0xE5, 0x81, 0x07, 0x2D, 0xE4,
+ 0xE4, 0xD6, 0x9B, 0x23, 0x79, 0x08, 0x82, 0x7A, 0x4A, 0xC5, 0x45, 0x80, 0x04, 0x03, 0x10, 0x40,
+ 0x41, 0x04, 0x05, 0x0C, 0x25, 0x0F, 0x70, 0x03, 0x20, 0x47, 0xCC, 0x6C, 0x23, 0x45, 0xBA, 0x00,
+ 0x50, 0x16, 0x2A, 0xCA, 0x5A, 0x86, 0x51, 0x9A, 0xB9, 0x6A, 0x03, 0xAD, 0x36, 0xD0, 0xC0, 0x0B,
+ 0x93, 0x2E, 0x02, 0x0E, 0x9A, 0x1B, 0x00, 0x74, 0xA7, 0x81, 0x9E, 0x78, 0x54, 0x4E, 0x9C, 0x0C,
+ 0xEC, 0x64, 0xC1, 0x46, 0x19, 0xE6, 0x15, 0x98, 0x94, 0x71, 0x69, 0x34, 0xE8, 0x02, 0x19, 0x10,
+ 0xA0, 0x67, 0x75, 0x0B, 0x22, 0xA2, 0xCE, 0x3C, 0x4D, 0xC2, 0x59, 0xA8, 0x01, 0x04, 0x6C, 0x58,
+ 0xA5, 0x01, 0xC1, 0x30, 0xE3, 0x81, 0x01, 0x03, 0x5C, 0x90, 0xE1, 0x00, 0xF8, 0x12, 0x3B, 0x80,
+ 0x94, 0xC9, 0x16, 0xB8, 0x00, 0x66, 0x1D, 0x01, 0xC5, 0xC0, 0x37, 0x07, 0xC5, 0x82, 0xDD, 0x4D,
+ 0x56, 0x5D, 0x65, 0x15, 0x33, 0x72, 0xD5, 0xE6, 0x89, 0x2F, 0x1A, 0x50, 0x09, 0x5D, 0x7D, 0x11,
+ 0xFE, 0x44, 0xD0, 0x93, 0x50, 0x85, 0xF9, 0x05, 0xA9, 0x4F, 0x0D, 0xCC, 0xD6, 0x2A, 0x94, 0x23,
+ 0x65, 0x28, 0xE5, 0xBB, 0x0D, 0x8F, 0x84, 0xD7, 0x02, 0x17, 0x88, 0x5B, 0xEC, 0x48, 0x0D, 0x4C,
+ 0xCA, 0xCC, 0xC0, 0x2D, 0xD2, 0xD7, 0x91, 0x76, 0x1B, 0x7D, 0x93, 0xD7, 0x4D, 0x37, 0xE5, 0x48,
+ 0x93, 0x74, 0xA1, 0x60, 0x76, 0x22, 0x33, 0x1A, 0x14, 0x52, 0x67, 0x8B, 0x3B, 0x52, 0xD0, 0x53,
+ 0x04, 0x0B, 0x06, 0x39, 0xC8, 0x28, 0xE7, 0x88, 0xDB, 0x51, 0xC9, 0xD7, 0xB2, 0x1B, 0x4C, 0x92,
+ 0x18, 0x06, 0x20, 0x6E, 0x03, 0xF4, 0xF6, 0x64, 0xF5, 0x20, 0x0D, 0x78, 0x40, 0xC2, 0x88, 0xBF,
+ 0xEC, 0xBC, 0xD1, 0xB5, 0xB1, 0x2C, 0x7A, 0xED, 0x55, 0xEA, 0xE1, 0x7C, 0x10, 0x64, 0x3B, 0x65,
+ 0x65, 0x5F, 0xC1, 0x98, 0xFD, 0x52, 0x67, 0x47, 0x4F, 0x36, 0x10, 0x00, 0xD2, 0xA5, 0x11, 0xB6,
+ 0x75, 0x3C, 0x1F, 0x97, 0x2C, 0x65, 0x85, 0xF4, 0x36, 0xE0, 0x40, 0x95, 0x56, 0xF6, 0x84, 0x2F,
+ 0xBE, 0x56, 0x1F, 0xBE, 0x80, 0x04, 0xF1, 0x5D, 0xBB, 0x9C, 0x46, 0x3A, 0x89, 0x23, 0xC0, 0x7D,
+ 0x05, 0xD7, 0xF4, 0x29, 0xC2, 0xE0, 0x84, 0xD9, 0xDC, 0x41, 0x3A, 0x9A, 0x6C, 0xD1, 0x2F, 0x07,
+ 0x21, 0x82, 0x6F, 0x01, 0x37, 0x16, 0x16, 0x24, 0xBE, 0xBB, 0x16, 0xD2, 0x93, 0x00, 0xD9, 0x12,
+ 0xC0, 0x24, 0x6D, 0x8E, 0xEE, 0x78, 0x8E, 0xDD, 0x14, 0x1A, 0x4E, 0x21, 0xB2, 0xA8, 0xC1, 0xAC,
+ 0x55, 0x4D, 0xB1, 0x59, 0x54, 0x55, 0x63, 0x68, 0xD6, 0x66, 0x95, 0x05, 0x40, 0x61, 0x5A, 0x17,
+ 0x33, 0x97, 0x61, 0x10, 0xD7, 0x3F, 0x18, 0x7C, 0x95, 0x01, 0x9C, 0x7E, 0xCD, 0x53, 0xBA, 0x59,
+ 0x5A, 0xFF, 0x35, 0x80, 0x04, 0xF6, 0x66, 0x78, 0x0E, 0x95, 0xC1, 0x00, 0x5E, 0xD2, 0xA1, 0xFE,
+ 0x61, 0xCD, 0xA3, 0xF5, 0x3C, 0x04, 0x34, 0xF0, 0xEB, 0x69, 0x2D, 0x40, 0xB6, 0xBB, 0x31, 0xF4,
+ 0x25, 0x90, 0x57, 0xB5, 0x75, 0x35, 0x4A, 0x02, 0x7D, 0x38, 0xCD, 0xA8, 0x23, 0x06, 0x75, 0x59,
+ 0x10, 0x81, 0x04, 0x2F, 0xEA, 0x3F, 0x00, 0x75, 0xB8, 0x21, 0x88, 0x58, 0x22, 0xE0, 0x8C, 0x04,
+ 0x89, 0x2F, 0x1E, 0xE1, 0x73, 0x14, 0x77, 0xC4, 0x87, 0x80, 0x4F, 0x01, 0xA3, 0x4A, 0x18, 0xA8,
+ 0xD1, 0xA1, 0x06, 0xD1, 0x91, 0xF0, 0xED, 0x2D, 0x00, 0x12, 0x38, 0x0C, 0x62, 0x7A, 0xA0, 0xBB,
+ 0xFC, 0x60, 0x06, 0x7F, 0x77, 0xE1, 0xC8, 0x54, 0xEC, 0x27, 0xB9, 0x9B, 0x1C, 0xE4, 0x02, 0xCB,
+ 0x50, 0xDE, 0x3F, 0x74, 0x34, 0xBF, 0x42, 0x34, 0x20, 0x02, 0xE2, 0x0A, 0x00, 0x05, 0x06, 0x41,
+ 0x40, 0xD2, 0xDC, 0x88, 0x4D, 0x7F, 0x69, 0x9A, 0x07, 0x8C, 0x35, 0x88, 0x59, 0x34, 0x6C, 0x16,
+ 0x87, 0x3A, 0xC0, 0x01, 0xE8, 0xE1, 0x93, 0x66, 0x9C, 0x03, 0x5F, 0xAB, 0xCA, 0x60, 0x23, 0x44,
+ 0x41, 0x02, 0x0F, 0x4C, 0x64, 0x4A, 0xFF, 0xD2, 0x49, 0x2F, 0xCA, 0xA6, 0xB6, 0x4B, 0xD5, 0xA6,
+ 0x10, 0x39, 0xBA, 0xDC, 0xC2, 0xE6, 0xE2, 0x80, 0x84, 0xCD, 0x65, 0x24, 0xC0, 0xC8, 0x00, 0x05,
+ 0x2E, 0x20, 0x08, 0xA4, 0x89, 0xA5, 0x00, 0xB8, 0x21, 0x5D, 0x5F, 0xF2, 0x46, 0x18, 0xEA, 0xE1,
+ 0x0A, 0x37, 0x24, 0x38, 0xC0, 0xA3, 0xC8, 0x17, 0xB2, 0x76, 0xCD, 0xEA, 0x10, 0x3D, 0x64, 0xD5,
+ 0x48, 0x18, 0x21, 0x0C, 0x03, 0xE8, 0x80, 0x42, 0x93, 0xA8, 0x8D, 0x70, 0x2C, 0xD1, 0x83, 0x6E,
+ 0xE1, 0xCF, 0x39, 0xCF, 0x11, 0xC7, 0xD3, 0xEC, 0x82, 0x01, 0x07, 0x60, 0x47, 0x88, 0xE0, 0x98,
+ 0xD2, 0xC2, 0x9C, 0x93, 0xB0, 0x7F, 0x01, 0xA3, 0x00, 0xB0, 0xEA, 0x8B, 0xC5, 0x5C, 0xFE, 0x31,
+ 0x81, 0x02, 0x26, 0xED, 0x93, 0xE8, 0x32, 0x0B, 0xD3, 0x6A, 0x23, 0x88, 0x56, 0x11, 0x20, 0x33,
+ 0x01, 0xA4, 0x60, 0x29, 0x0D, 0x37, 0x8F, 0x0C, 0x68, 0xF0, 0x3C, 0xDC, 0x39, 0x54, 0xCB, 0x1C,
+ 0x21, 0x83, 0x45, 0x58, 0x00, 0x90, 0x96, 0x00, 0x82, 0x3F, 0x64, 0x62, 0xB0, 0x99, 0x14, 0x8C,
+ 0x19, 0x02, 0x00, 0xC5, 0x4C, 0x02, 0x96, 0x1C, 0x21, 0x7A, 0xE8, 0x6C, 0x94, 0x9C, 0x64, 0x64,
+ 0x1C, 0x70, 0xB7, 0x01, 0x58, 0x6C, 0x02, 0x46, 0x03, 0x00, 0x1A, 0x61, 0x55, 0x40, 0x20, 0x1D,
+ 0xB1, 0x30, 0xA6, 0xB4, 0x51, 0x00, 0x48, 0x40, 0x02, 0x0C, 0x30, 0x2D, 0x71, 0xE7, 0x6A, 0x23,
+ 0x28, 0xE1, 0xD4, 0x12, 0x45, 0xB4, 0x40, 0x06, 0xF4, 0xC0, 0x65, 0x23, 0x5A, 0x30, 0x00, 0x08,
+ 0x6D, 0x88, 0x00, 0xB8, 0xA3, 0x04, 0xC1, 0x76, 0xA6, 0xBE, 0xE6, 0x74, 0xE4, 0x5A, 0x8D, 0xC9,
+ 0x4B, 0x38, 0xB0, 0xE3, 0x40, 0xAC, 0x24, 0x2C, 0x36, 0x55, 0x99, 0xD1, 0x39, 0x24, 0x80, 0xC6,
+ 0xC3, 0xA1, 0xF1, 0x55, 0xCE, 0xF4, 0x64, 0x69, 0x80, 0x73, 0x44, 0x78, 0xD8, 0x48, 0x76, 0x50,
+ 0xEA, 0xE1, 0xE1, 0x0E, 0xB8, 0xC6, 0xBC, 0xF5, 0x64, 0x24, 0x2D, 0x58, 0xC4, 0x08, 0x76, 0x62,
+ 0x1A, 0x45, 0x68, 0x49, 0x11, 0x24, 0x18, 0xC0, 0x0B, 0x5A, 0xD0, 0x02, 0x78, 0x10, 0xA0, 0x12,
+ 0x64, 0xE3, 0x65, 0x4E, 0x68, 0x22, 0x93, 0x16, 0xF1, 0x0E, 0x92, 0x72, 0x99, 0x9C, 0x3F, 0x6A,
+ 0xF3, 0xCB, 0x7F, 0x5E, 0xAA, 0x40, 0x85, 0x5A, 0x00, 0x26, 0x5F, 0x15, 0x81, 0x09, 0x44, 0xC0,
+ 0x68, 0x33, 0xAC, 0x26, 0x69, 0x4C, 0x17, 0x3E, 0xE0, 0x08, 0x60, 0x75, 0xAB, 0x44, 0x5C, 0xAB,
+ 0x18, 0xEA, 0x1D, 0x5C, 0xCD, 0xC8, 0x96, 0x24, 0x41, 0x9D, 0x11, 0x4E, 0xA0, 0xFE, 0xC1, 0x13,
+ 0x30, 0x60, 0x00, 0xEB, 0x6A, 0x15, 0x0C, 0x22, 0xB1, 0x83, 0x1D, 0x40, 0x05, 0x1C, 0xD5, 0x5A,
+ 0x69, 0x6C, 0x14, 0xA6, 0xB0, 0x86, 0xB5, 0x08, 0x28, 0x72, 0xC4, 0x40, 0x63, 0x26, 0x43, 0x8E,
+ 0x8D, 0x34, 0xE6, 0x9E, 0x0E, 0x08, 0x87, 0xEB, 0x62, 0xC5, 0x1D, 0x67, 0x16, 0x00, 0x9A, 0xF3,
+ 0xA8, 0x00, 0xE9, 0x6E, 0x68, 0xC0, 0xF1, 0x21, 0x85, 0xA1, 0xCF, 0xA3, 0x9E, 0xE9, 0x70, 0xC3,
+ 0xD0, 0x56, 0xF9, 0xB0, 0x9C, 0xD5, 0x1A, 0x08, 0x86, 0x16, 0xC0, 0x81, 0x0D, 0x38, 0xD1, 0x08,
+ 0x21, 0xC5, 0x2A, 0x86, 0x5C, 0xF7, 0x35, 0x48, 0x74, 0x55, 0x07, 0xBE, 0xD4, 0x4A, 0x14, 0x27,
+ 0x47, 0x49, 0x84, 0x0D, 0xB3, 0x61, 0xC0, 0x88, 0xD6, 0x5C, 0x4E, 0x51, 0x9F, 0x48, 0xCE, 0x48,
+ 0x79, 0x85, 0xC0, 0x88, 0x01, 0x62, 0x95, 0xC3, 0x34, 0x0E, 0xC0, 0xA7, 0x35, 0x2C, 0xDD, 0x51,
+ 0x94, 0x86, 0x0E, 0x41, 0xB0, 0x2A, 0x00, 0x01, 0x12, 0x2C, 0x02, 0x6F, 0x53, 0x3D, 0x5C, 0x49,
+ 0x40, 0x9D, 0x0B, 0x24, 0x07, 0x87, 0x76, 0xD0, 0x28, 0x23, 0x78, 0x80, 0x54, 0x02, 0xA0, 0x81,
+ 0x28, 0x8E, 0x25, 0x89, 0xB7, 0x84, 0xF0, 0x2A, 0xAE, 0xF1, 0x85, 0x73, 0x6E, 0xF6, 0x11, 0x34,
+ 0xAD, 0xF0, 0x8A, 0x1B, 0xAA, 0x89, 0x30, 0x3E, 0x05, 0x2A, 0x0F, 0x5C, 0x00, 0x04, 0x0E, 0x04,
+ 0x46, 0x00, 0x2A, 0x83, 0x08, 0x69, 0xF4, 0xB0, 0x87, 0x7B, 0x1D, 0x6A, 0x6D, 0x99, 0xCA, 0xA7,
+ 0x78, 0x98, 0x6F, 0x34, 0xE3, 0xB3, 0xA1, 0x35, 0xD9, 0x64, 0x81, 0x8E, 0x31, 0xCE, 0x08, 0x32,
+ 0x10, 0x05, 0x6E, 0x28, 0x54, 0xD2, 0x44, 0x24, 0x47, 0x5C, 0x16, 0x00, 0x41, 0xD6, 0x74, 0x50,
+ 0x4B, 0x48, 0x2C, 0x6F, 0x9E, 0x62, 0x1D, 0x49, 0x55, 0x70, 0xE2, 0x59, 0xFE, 0xB7, 0x78, 0x6D,
+ 0x4A, 0x71, 0x39, 0xC0, 0x30, 0x95, 0xE7, 0x28, 0xEF, 0x5A, 0x98, 0xBB, 0x85, 0xC8, 0xCB, 0x2C,
+ 0x36, 0x33, 0x13, 0x4C, 0x4A, 0x6F, 0x5C, 0x0A, 0xCD, 0x18, 0x70, 0xE6, 0x3B, 0x4E, 0x10, 0xCB,
+ 0x96, 0x82, 0xA3, 0x80, 0xD4, 0x09, 0x94, 0x42, 0x02, 0x73, 0x9C, 0xA3, 0xA4, 0x2D, 0xD8, 0xD0,
+ 0x39, 0xE6, 0xB2, 0x34, 0x0C, 0xC4, 0xB3, 0x11, 0x77, 0x81, 0xDC, 0xF0, 0x56, 0xD8, 0x22, 0xF5,
+ 0x79, 0x51, 0x00, 0x2D, 0x68, 0xE1, 0x15, 0x63, 0xA1, 0xA8, 0x0D, 0xC5, 0xEE, 0xB8, 0xA7, 0x0D,
+ 0x2F, 0x06, 0x5C, 0xC4, 0x61, 0xC4, 0x11, 0x90, 0x9A, 0x42, 0x6D, 0xEF, 0x51, 0x46, 0xFC, 0x23,
+ 0x03, 0x56, 0xB4, 0x2F, 0xDF, 0xF1, 0x2B, 0x21, 0x42, 0x25, 0x90, 0x56, 0x09, 0x63, 0x18, 0x31,
+ 0x9E, 0xF1, 0x1C, 0xCD, 0xF7, 0xCA, 0x45, 0x78, 0x60, 0x07, 0x85, 0x72, 0xD1, 0x4E, 0xF2, 0xD3,
+ 0x59, 0x04, 0x48, 0x38, 0x2B, 0x15, 0x52, 0x1E, 0xFE, 0xF2, 0x52, 0x13, 0x0B, 0x1C, 0xAA, 0x51,
+ 0x85, 0xF0, 0xC4, 0xA2, 0x62, 0x84, 0x9D, 0xAB, 0x24, 0x20, 0x2C, 0x61, 0x71, 0xA6, 0x5D, 0x29,
+ 0x20, 0x54, 0x05, 0x29, 0xAD, 0x3A, 0x65, 0x61, 0x63, 0x1B, 0xCB, 0x22, 0x51, 0xDC, 0x20, 0x60,
+ 0x04, 0x2D, 0xE0, 0xC0, 0x2A, 0x2D, 0xD0, 0xC2, 0x70, 0x0E, 0x62, 0x81, 0xF0, 0x2C, 0xA7, 0x22,
+ 0x7E, 0x71, 0x97, 0x7A, 0xD6, 0x53, 0x26, 0x56, 0x51, 0x73, 0xFD, 0xB0, 0x78, 0x80, 0xD9, 0xB8,
+ 0x39, 0x47, 0x42, 0xA4, 0x50, 0x02, 0x2E, 0x40, 0x1F, 0x37, 0x07, 0x98, 0xCF, 0xDF, 0x78, 0x53,
+ 0x00, 0x41, 0x32, 0x0F, 0x02, 0x56, 0xD4, 0x19, 0xC8, 0xF8, 0xD1, 0xAD, 0x6F, 0x78, 0x5E, 0xF9,
+ 0x5A, 0xF3, 0xBC, 0xE8, 0x6A, 0xC1, 0x82, 0x50, 0x97, 0xDC, 0x03, 0xFE, 0xC2, 0x2B, 0x33, 0x8A,
+ 0x6B, 0x84, 0x07, 0x11, 0x49, 0x93, 0x2E, 0x4D, 0x25, 0x3F, 0x59, 0x01, 0x47, 0x86, 0xEA, 0x63,
+ 0x15, 0x42, 0x78, 0x20, 0x39, 0x3F, 0xC9, 0x62, 0x0B, 0x4C, 0xD2, 0xDD, 0x65, 0x60, 0x07, 0x3B,
+ 0x86, 0xBD, 0x9B, 0x57, 0xF8, 0xA4, 0xD0, 0xE8, 0x05, 0x29, 0x6F, 0xBE, 0xFE, 0x75, 0x95, 0x69,
+ 0x7B, 0x4D, 0x9F, 0x0C, 0xF1, 0xBC, 0x3D, 0x99, 0xA0, 0x44, 0xEB, 0x8A, 0x2E, 0x23, 0x6C, 0xC2,
+ 0x48, 0xE0, 0x08, 0x21, 0x22, 0xF9, 0x72, 0x4A, 0xCC, 0x40, 0xB7, 0x26, 0x38, 0xC9, 0x4A, 0xA0,
+ 0x6A, 0xD3, 0xC3, 0x2C, 0x6A, 0x6F, 0x5F, 0x81, 0x69, 0xC1, 0x0B, 0xE2, 0xE2, 0xC0, 0xE2, 0xB9,
+ 0x6F, 0x7F, 0x77, 0xDB, 0x64, 0x01, 0x5E, 0x55, 0x68, 0x45, 0x5F, 0x59, 0x41, 0x15, 0xF7, 0x0E,
+ 0x02, 0x53, 0xC9, 0xF1, 0x61, 0x6F, 0x18, 0x23, 0xED, 0xC6, 0x4D, 0x4D, 0x5A, 0x90, 0x83, 0x1B,
+ 0x78, 0x43, 0x32, 0x63, 0xA5, 0x97, 0x28, 0x28, 0xB9, 0xD6, 0x95, 0xD6, 0xCF, 0x43, 0xCD, 0x12,
+ 0xC9, 0x86, 0x30, 0x74, 0x38, 0x39, 0x82, 0x6A, 0x49, 0x52, 0x72, 0xF5, 0x5A, 0x2D, 0x28, 0xCD,
+ 0x02, 0xD8, 0x35, 0xE3, 0x9F, 0x2C, 0xB7, 0xAE, 0x85, 0xCE, 0x46, 0x86, 0x9A, 0xEE, 0x62, 0xE7,
+ 0x25, 0x86, 0x96, 0x0F, 0xD8, 0x2A, 0x19, 0xE4, 0x20, 0x01, 0xE5, 0x69, 0x76, 0x47, 0xA2, 0xFD,
+ 0xEE, 0x62, 0x8C, 0x36, 0x67, 0x04, 0x58, 0x98, 0x10, 0x05, 0x79, 0x8C, 0xA5, 0x1D, 0xA0, 0x63,
+ 0x59, 0x9F, 0x07, 0x09, 0x2E, 0xF0, 0xA9, 0x6A, 0x19, 0x60, 0x02, 0x87, 0x6A, 0x55, 0x65, 0x24,
+ 0x00, 0x00, 0x02, 0xA2, 0xF1, 0x6E, 0x01, 0xC0, 0x64, 0xC6, 0x47, 0xAC, 0xDE, 0xA4, 0x55, 0xFC,
+ 0x8E, 0x56, 0xC6, 0xA6, 0x88, 0x7B, 0x08, 0x80, 0xF9, 0xF1, 0xFE, 0x6D, 0x7C, 0xA8, 0xCB, 0x41,
+ 0x0A, 0x34, 0x42, 0x2F, 0x68, 0xCF, 0xA5, 0xEB, 0x90, 0x3A, 0xC5, 0x4D, 0xE6, 0x81, 0x80, 0x01,
+ 0x20, 0x6C, 0x46, 0x09, 0x58, 0x72, 0xE3, 0x07, 0xE1, 0x00, 0x96, 0xB9, 0xEE, 0xA8, 0x03, 0xE0,
+ 0xA6, 0x9E, 0xC5, 0xE5, 0x66, 0x04, 0x14, 0x60, 0x01, 0x15, 0xC0, 0x00, 0xAB, 0x7C, 0x4E, 0x01,
+ 0xD2, 0xA9, 0xF1, 0xEE, 0x06, 0x64, 0x6F, 0x95, 0xA3, 0xBC, 0xFA, 0x90, 0x8B, 0xAF, 0x94, 0x84,
+ 0xC1, 0x97, 0xD4, 0x88, 0xD1, 0x34, 0x89, 0x0E, 0xC0, 0x03, 0x27, 0x80, 0x4C, 0xA0, 0x8E, 0x67,
+ 0x8C, 0x37, 0xB5, 0xEA, 0xA8, 0xD5, 0x6E, 0xD5, 0x3C, 0x86, 0x19, 0x0E, 0x8B, 0xB8, 0xB8, 0x6F,
+ 0x3D, 0x19, 0x85, 0xEB, 0x8E, 0x7D, 0xAD, 0x7E, 0x2F, 0xA9, 0x55, 0x72, 0x24, 0xE8, 0xE1, 0x14,
+ 0x30, 0x81, 0x02, 0x58, 0x9F, 0xF5, 0x18, 0xC7, 0x3B, 0xA0, 0x81, 0x9E, 0xA0, 0xEA, 0xC4, 0x17,
+ 0x71, 0x1D, 0x07, 0xF6, 0xC6, 0x8F, 0x68, 0xD8, 0x05, 0xB0, 0xB3, 0x18, 0xF3, 0x14, 0x53, 0xEF,
+ 0x03, 0x32, 0x88, 0x99, 0xCC, 0xD6, 0xF1, 0xAB, 0xD6, 0x9C, 0x9B, 0xF3, 0x08, 0x8F, 0x59, 0xD4,
+ 0x2B, 0x43, 0x4A, 0x69, 0xD1, 0x2C, 0xBE, 0x2E, 0x2E, 0x03, 0x48, 0x00, 0x86, 0x3F, 0x25, 0x16,
+ 0x03, 0x80, 0x49, 0xD7, 0x77, 0x77, 0x22, 0x56, 0x4D, 0xAB, 0x97, 0x68, 0xE4, 0xE2, 0x13, 0x80,
+ 0x47, 0x6E, 0x49, 0x35, 0x62, 0x48, 0xB7, 0x24, 0x18, 0xA2, 0x0E, 0x98, 0x87, 0x08, 0x93, 0x94,
+ 0x00, 0x0E, 0x70, 0x00, 0x53, 0x72, 0x16, 0x8D, 0x67, 0x38, 0xA8, 0x73, 0x00, 0x19, 0xF0, 0x09,
+ 0xBB, 0x22, 0x61, 0x0C, 0x28, 0x17, 0x48, 0xA4, 0x76, 0xBE, 0x10, 0x3A, 0xE6, 0x00, 0x43, 0x2A,
+ 0x63, 0x0E, 0x43, 0x61, 0x31, 0xCE, 0x34, 0x01, 0xD2, 0xFE, 0x50, 0x68, 0xA4, 0x10, 0x5F, 0x53,
+ 0x86, 0x6E, 0x44, 0xB7, 0x5B, 0x52, 0x66, 0x77, 0x46, 0x67, 0x18, 0x8E, 0x16, 0x7B, 0xB8, 0x62,
+ 0x3E, 0xE3, 0xC5, 0x2E, 0xF9, 0xD1, 0x0F, 0xD8, 0x36, 0x0F, 0x1D, 0x13, 0x0A, 0x47, 0x24, 0x2E,
+ 0x83, 0xB2, 0x64, 0xAA, 0xF2, 0x4D, 0x4C, 0x67, 0x38, 0x33, 0x61, 0x1F, 0x1D, 0x71, 0x67, 0xAE,
+ 0x63, 0x4A, 0x86, 0x13, 0x68, 0x7F, 0x01, 0x65, 0xAC, 0x17, 0x5F, 0x40, 0x62, 0x68, 0xBB, 0x66,
+ 0x77, 0x53, 0xA6, 0x77, 0xA8, 0x20, 0x2B, 0xA5, 0xC3, 0x34, 0xF2, 0x86, 0x0A, 0xEC, 0xD2, 0x24,
+ 0xE0, 0x67, 0x2E, 0x2B, 0x24, 0x0E, 0x6B, 0x93, 0x27, 0x4B, 0x43, 0x0F, 0x5D, 0x26, 0x7C, 0x59,
+ 0xB7, 0x21, 0x71, 0x41, 0x2F, 0x01, 0x24, 0x7B, 0xBD, 0x55, 0x3E, 0x7E, 0x38, 0x1B, 0x40, 0xE1,
+ 0x3A, 0x08, 0x70, 0x85, 0x82, 0xE0, 0x73, 0x7A, 0x32, 0x3A, 0x06, 0xC8, 0x6E, 0xD3, 0x73, 0x6B,
+ 0x58, 0x56, 0x77, 0xEA, 0xB6, 0x7D, 0x36, 0x44, 0x18, 0x2F, 0x02, 0x24, 0x3D, 0xB1, 0x28, 0xD0,
+ 0x27, 0x7C, 0x2C, 0xA2, 0x3C, 0x60, 0xF4, 0x11, 0x4B, 0xD8, 0x1A, 0xE2, 0xA3, 0x7C, 0x02, 0xE0,
+ 0x28, 0xD3, 0x11, 0x43, 0x4D, 0xA3, 0x32, 0x9F, 0xE8, 0x3A, 0x1D, 0x93, 0x2B, 0x0E, 0x70, 0x28,
+ 0x83, 0x38, 0x88, 0xD2, 0xE4, 0x4C, 0x71, 0x97, 0x49, 0xE9, 0x05, 0x74, 0x7F, 0xB5, 0x46, 0x7F,
+ 0xC5, 0x68, 0x77, 0xA4, 0x37, 0xB7, 0x88, 0x8B, 0xBA, 0x36, 0x08, 0x81, 0x08, 0x29, 0xE0, 0x17,
+ 0x00, 0x95, 0xB7, 0x00, 0x1D, 0x80, 0x1D, 0x16, 0x21, 0x3B, 0xA6, 0x24, 0x01, 0xAC, 0x11, 0x8C,
+ 0x90, 0x42, 0x21, 0x2F, 0xC3, 0x00, 0x7B, 0x88, 0x44, 0x4C, 0xE8, 0x3A, 0x2A, 0x33, 0x1B, 0x84,
+ 0xC3, 0x1A, 0x41, 0x34, 0x5E, 0x07, 0x34, 0x71, 0xFE, 0xD3, 0x44, 0x68, 0x73, 0xB7, 0x5E, 0x88,
+ 0x86, 0x71, 0xAC, 0x67, 0x8B, 0x44, 0x95, 0x80, 0x91, 0xD8, 0x19, 0xBC, 0xF5, 0x89, 0xAC, 0xF4,
+ 0x31, 0x1D, 0xA0, 0x3C, 0xC5, 0x53, 0x38, 0x2A, 0xB3, 0x8A, 0x7A, 0x18, 0x43, 0xD9, 0x24, 0x17,
+ 0x78, 0x31, 0x08, 0x2E, 0x26, 0x01, 0xBF, 0x75, 0x25, 0x15, 0x60, 0x67, 0x4C, 0x68, 0x3E, 0xF6,
+ 0xC3, 0x2B, 0xF4, 0x12, 0x16, 0x15, 0xD3, 0x76, 0x16, 0x63, 0x31, 0xB3, 0xB8, 0x6B, 0x3D, 0xF8,
+ 0x1B, 0x8C, 0xD6, 0x7D, 0x8A, 0xE6, 0x49, 0xE7, 0x06, 0x91, 0x03, 0x91, 0x31, 0x83, 0x20, 0x02,
+ 0x3C, 0x10, 0x03, 0x42, 0x30, 0x04, 0x3C, 0x20, 0x73, 0x9F, 0x30, 0x38, 0x34, 0x77, 0x38, 0xA3,
+ 0x43, 0x3E, 0x12, 0x10, 0x2E, 0xF4, 0x38, 0x1B, 0x12, 0x80, 0x35, 0x50, 0xD2, 0x31, 0xEC, 0xA2,
+ 0x76, 0xD4, 0x28, 0x2E, 0xA2, 0x20, 0x41, 0x50, 0x62, 0x01, 0x71, 0x45, 0x3C, 0x29, 0x56, 0x0A,
+ 0xB0, 0x72, 0x34, 0x15, 0x33, 0x8B, 0x51, 0x96, 0x43, 0x5A, 0xE3, 0x90, 0x0A, 0x98, 0x68, 0x48,
+ 0x67, 0x71, 0xE0, 0x78, 0x1B, 0xEC, 0xC2, 0x90, 0x5B, 0x43, 0x00, 0x24, 0xF0, 0x03, 0x42, 0xB0,
+ 0x94, 0x43, 0x20, 0x04, 0x31, 0x90, 0x3D, 0xD8, 0xD5, 0x01, 0x2A, 0x63, 0x88, 0x48, 0x24, 0x00,
+ 0x23, 0x29, 0x01, 0x0E, 0x60, 0x2C, 0xBF, 0xB5, 0x23, 0xE0, 0x82, 0x2B, 0x26, 0x58, 0x0E, 0xA1,
+ 0xA0, 0x32, 0x76, 0xB8, 0x7C, 0x8B, 0x82, 0x8D, 0x08, 0x74, 0x34, 0x98, 0x04, 0x8B, 0xDF, 0xE8,
+ 0x17, 0xDD, 0x67, 0x8E, 0xE6, 0x18, 0x8E, 0x7A, 0xE3, 0x85, 0xB8, 0xC6, 0x96, 0x63, 0x18, 0x77,
+ 0xAB, 0x42, 0x03, 0x3F, 0xF0, 0x03, 0x34, 0xD0, 0x94, 0x3C, 0x30, 0x04, 0x7E, 0xE9, 0x97, 0x42,
+ 0xF0, 0x03, 0x7F, 0x09, 0x98, 0x3E, 0xA0, 0xFE, 0x02, 0xCA, 0x97, 0x01, 0x88, 0x89, 0x98, 0xC6,
+ 0x22, 0x38, 0x7D, 0x23, 0x15, 0x02, 0xE0, 0x00, 0x19, 0xC0, 0x3F, 0x4C, 0x68, 0x4A, 0x2D, 0x69,
+ 0x3E, 0xFF, 0x12, 0x1D, 0x18, 0x54, 0x6B, 0x3E, 0x55, 0x00, 0x2A, 0xC0, 0x8D, 0x73, 0x67, 0x71,
+ 0x0B, 0x15, 0x89, 0x0A, 0x49, 0x77, 0x48, 0x41, 0x54, 0x12, 0x29, 0x9A, 0x89, 0x23, 0x01, 0x24,
+ 0x20, 0x04, 0x36, 0x10, 0x03, 0x31, 0x10, 0x04, 0x3C, 0x10, 0x04, 0x83, 0x39, 0x98, 0x19, 0x39,
+ 0x04, 0x3F, 0x60, 0x03, 0xCF, 0x13, 0x2B, 0x4E, 0x72, 0x01, 0x19, 0xF0, 0x24, 0x06, 0x60, 0x2C,
+ 0x47, 0xD5, 0x31, 0x95, 0x97, 0x8A, 0x19, 0x60, 0x7F, 0x47, 0x75, 0x8A, 0xD4, 0x18, 0x44, 0xA9,
+ 0x36, 0x88, 0xB0, 0xE8, 0x73, 0x48, 0x83, 0x90, 0x9F, 0x59, 0x54, 0x3D, 0x29, 0x8E, 0xF3, 0x85,
+ 0x7D, 0x7B, 0x32, 0x58, 0x10, 0x89, 0x68, 0x4B, 0x83, 0x98, 0x4F, 0x42, 0x03, 0x3A, 0x60, 0x03,
+ 0x3F, 0x40, 0x02, 0x7E, 0xE9, 0x01, 0xB3, 0xE9, 0x97, 0x82, 0xF9, 0x97, 0x34, 0xC0, 0x4E, 0x6D,
+ 0xE8, 0x00, 0x75, 0x53, 0x01, 0x19, 0x40, 0x2F, 0x59, 0x99, 0x95, 0x0B, 0xE0, 0x00, 0x0E, 0x90,
+ 0x75, 0xAB, 0xD3, 0x7E, 0x93, 0x99, 0x9C, 0xBD, 0xE1, 0x8A, 0x29, 0x51, 0x6B, 0x98, 0x44, 0x8F,
+ 0xD1, 0x39, 0x4E, 0xA1, 0x49, 0x9D, 0x43, 0x85, 0x8B, 0x16, 0x45, 0x18, 0xDF, 0xC4, 0x5E, 0xAF,
+ 0x40, 0x00, 0x19, 0x20, 0x02, 0x19, 0xE0, 0x02, 0x24, 0xE0, 0x03, 0x32, 0xE0, 0x01, 0x30, 0xF0,
+ 0x03, 0xE4, 0x09, 0x98, 0x7F, 0x69, 0x03, 0x83, 0xE9, 0x9D, 0xAF, 0x87, 0x44, 0xF3, 0x59, 0x9C,
+ 0x60, 0x72, 0x58, 0x83, 0x78, 0x28, 0x2E, 0x89, 0x2F, 0x47, 0x45, 0x8D, 0x61, 0xA9, 0x9F, 0xB1,
+ 0x10, 0x7B, 0x05, 0x75, 0x90, 0xD1, 0xFE, 0x59, 0x74, 0x3E, 0x69, 0x8B, 0xD9, 0xA9, 0x37, 0x5F,
+ 0x38, 0x6B, 0xB3, 0x10, 0x2A, 0x48, 0x31, 0x2E, 0xB3, 0xB2, 0x4D, 0x3A, 0xE0, 0x03, 0x63, 0x67,
+ 0x91, 0x31, 0x80, 0x9E, 0x7F, 0x29, 0x9B, 0x7F, 0xF9, 0x03, 0x3E, 0xC0, 0x03, 0x54, 0x29, 0x0B,
+ 0xB3, 0x41, 0x5E, 0xEC, 0x22, 0x0A, 0xBD, 0xD1, 0x11, 0x59, 0xA7, 0x0E, 0x26, 0xBA, 0x7C, 0x6A,
+ 0xE7, 0xA4, 0xEC, 0x72, 0x28, 0x01, 0xB1, 0x4A, 0xE7, 0x10, 0x5B, 0xD1, 0x79, 0x31, 0x33, 0xCA,
+ 0x83, 0xB8, 0x66, 0x9A, 0x42, 0x19, 0x00, 0x91, 0x69, 0x03, 0x24, 0x80, 0x98, 0xA3, 0x29, 0x08,
+ 0x1E, 0xF0, 0x02, 0x35, 0xE0, 0x02, 0x2F, 0xE0, 0x02, 0x42, 0x20, 0x02, 0x3E, 0xE0, 0x97, 0x3A,
+ 0xA0, 0x03, 0x7E, 0x69, 0x03, 0xB5, 0x39, 0x04, 0x34, 0x20, 0x03, 0x3E, 0xE0, 0x73, 0xE4, 0x47,
+ 0x8D, 0xC6, 0xC2, 0x2E, 0x97, 0x97, 0x75, 0x84, 0xAA, 0x84, 0xE4, 0x83, 0x17, 0xF4, 0x30, 0x88,
+ 0xCB, 0x77, 0xA5, 0x02, 0x51, 0x0A, 0x69, 0xF9, 0x7A, 0x2F, 0x9A, 0x4A, 0x3F, 0xB9, 0x50, 0x61,
+ 0x38, 0x4E, 0xD8, 0xA9, 0x35, 0xC4, 0xF2, 0xA1, 0x6F, 0x39, 0x08, 0x17, 0x20, 0x03, 0x2E, 0xD0,
+ 0x02, 0x17, 0x10, 0x9E, 0x49, 0xF9, 0x03, 0x32, 0x00, 0x04, 0x76, 0xDA, 0xA3, 0xB6, 0xA9, 0x97,
+ 0x2E, 0x40, 0x03, 0x54, 0xE9, 0x81, 0x8F, 0xD9, 0x92, 0xB3, 0x21, 0x88, 0x44, 0x56, 0xA8, 0x97,
+ 0x67, 0x15, 0x2E, 0x49, 0x8D, 0xBF, 0x77, 0x74, 0x72, 0xF9, 0x8D, 0xA8, 0x60, 0x62, 0xBB, 0x05,
+ 0xA3, 0x40, 0x39, 0x5B, 0xB1, 0xC7, 0x80, 0x12, 0xD5, 0x00, 0x12, 0xF0, 0x10, 0xD8, 0x29, 0x03,
+ 0x2F, 0xA0, 0x03, 0xA0, 0xEA, 0x03, 0x34, 0xE0, 0x02, 0x3E, 0xE0, 0x03, 0x15, 0xDA, 0xA3, 0x2F,
+ 0x20, 0x98, 0x3F, 0x00, 0x04, 0xFE, 0x2D, 0xE0, 0x02, 0x1D, 0xE0, 0x73, 0xF4, 0xE8, 0xAA, 0x4E,
+ 0x8A, 0x17, 0x19, 0x28, 0x44, 0x44, 0xB8, 0x7C, 0xFF, 0x01, 0xAB, 0xA5, 0x56, 0x8D, 0x5D, 0xD6,
+ 0x6B, 0x2F, 0xEA, 0x7D, 0x21, 0x76, 0x9D, 0xE3, 0x48, 0x9A, 0x96, 0x8A, 0x9D, 0xBF, 0xBA, 0x27,
+ 0x32, 0xA0, 0x03, 0x1D, 0x40, 0x03, 0x0B, 0x00, 0x03, 0x71, 0xFA, 0x02, 0x7A, 0x9A, 0x97, 0x40,
+ 0x40, 0x02, 0x78, 0x69, 0x9B, 0x31, 0x26, 0x03, 0xE2, 0x33, 0x51, 0xF4, 0x30, 0xA5, 0xB3, 0x81,
+ 0x35, 0x77, 0x42, 0x5D, 0x58, 0x5A, 0x19, 0xE5, 0xEA, 0x66, 0x27, 0x2A, 0x0B, 0x33, 0xE6, 0x6B,
+ 0x0A, 0x89, 0x65, 0xB3, 0x35, 0xA0, 0xA5, 0xE9, 0x93, 0xBC, 0x78, 0x9D, 0xEA, 0xFA, 0x1D, 0xAE,
+ 0xD3, 0x88, 0x05, 0x1A, 0x00, 0x9E, 0xDA, 0x02, 0x33, 0xE2, 0x01, 0x16, 0xFA, 0x02, 0x42, 0xF0,
+ 0x02, 0x3E, 0x90, 0x97, 0x3A, 0x80, 0x97, 0xA4, 0xEA, 0x03, 0x24, 0x45, 0x3E, 0xAC, 0x64, 0xAB,
+ 0x47, 0x95, 0x81, 0xE1, 0x9A, 0x17, 0x37, 0x73, 0x27, 0x6E, 0x86, 0xA5, 0x00, 0xD1, 0xA4, 0x2E,
+ 0xA9, 0x8B, 0x91, 0xAA, 0x83, 0x07, 0x98, 0x7D, 0x43, 0x69, 0x68, 0x46, 0xAB, 0x7A, 0x7C, 0x15,
+ 0x8E, 0x43, 0x95, 0x9E, 0x32, 0x40, 0x02, 0x2E, 0x30, 0x04, 0xDC, 0x14, 0x03, 0x3E, 0xA0, 0x03,
+ 0x3F, 0xD0, 0xB2, 0x2B, 0xAB, 0x03, 0x4F, 0xBB, 0x6D, 0xB8, 0x31, 0x51, 0xFB, 0x25, 0x00, 0x8B,
+ 0x49, 0x1B, 0xD4, 0xD5, 0x79, 0xCE, 0x82, 0xA5, 0x2D, 0x77, 0xA5, 0x33, 0xF6, 0x96, 0x34, 0x28,
+ 0xA3, 0x74, 0x07, 0x97, 0x0A, 0xE9, 0xA5, 0xB9, 0x36, 0x7E, 0x03, 0xAA, 0xB1, 0xAD, 0x30, 0x14,
+ 0xAE, 0x50, 0x03, 0x3E, 0xF0, 0xA9, 0xA1, 0x7A, 0x01, 0x2F, 0x00, 0x04, 0xCE, 0x0A, 0x04, 0x43,
+ 0x20, 0x03, 0x35, 0x40, 0xFE, 0xB5, 0xB6, 0x59, 0x03, 0x34, 0x90, 0x62, 0x5B, 0x7B, 0x5E, 0x0D,
+ 0x50, 0x01, 0xC6, 0x82, 0x17, 0x38, 0xCB, 0xB0, 0x8D, 0x0B, 0x14, 0xBD, 0xC1, 0x8A, 0xFF, 0x31,
+ 0x91, 0x68, 0x1B, 0xA0, 0xBB, 0x5A, 0xA0, 0x14, 0x2B, 0xAC, 0x57, 0x26, 0x86, 0x20, 0x06, 0xB7,
+ 0x4B, 0x53, 0x40, 0x18, 0xF0, 0xAC, 0x34, 0x90, 0x94, 0x1D, 0xA0, 0xAF, 0x7F, 0x9B, 0x97, 0x43,
+ 0xE0, 0xAC, 0x7E, 0x19, 0xAD, 0x34, 0xF0, 0x3C, 0xE2, 0x03, 0x7C, 0xA1, 0x60, 0x2C, 0x0E, 0xC0,
+ 0xB8, 0xB2, 0x8A, 0x17, 0x6B, 0xB5, 0xB0, 0x0A, 0x0B, 0x49, 0xEE, 0x03, 0x10, 0xD5, 0x96, 0xA6,
+ 0x96, 0xEB, 0x96, 0x89, 0x16, 0x86, 0x38, 0xD8, 0x88, 0xE0, 0x58, 0x5B, 0xEE, 0x35, 0x83, 0x83,
+ 0x61, 0x00, 0x80, 0xEB, 0x02, 0x16, 0xE0, 0x02, 0x9F, 0xEA, 0x03, 0x42, 0x00, 0xAD, 0xE0, 0xE9,
+ 0x9D, 0x7F, 0xE9, 0x03, 0x2F, 0x70, 0x0C, 0x20, 0x49, 0x87, 0xE1, 0xB2, 0x30, 0xB1, 0x8A, 0x08,
+ 0x41, 0xF4, 0xBD, 0x0B, 0x2B, 0x44, 0x18, 0x28, 0x8F, 0x77, 0x32, 0x91, 0xEB, 0x1A, 0x65, 0xBA,
+ 0x65, 0x80, 0x46, 0x87, 0x6E, 0xE2, 0x24, 0x9A, 0x3C, 0xD9, 0x31, 0x7E, 0x25, 0x54, 0x06, 0x10,
+ 0x64, 0x9E, 0x80, 0x01, 0x31, 0x70, 0xAF, 0x43, 0x00, 0xAD, 0x79, 0xE9, 0x02, 0x35, 0x30, 0x04,
+ 0x40, 0x90, 0x97, 0xF3, 0xB2, 0xB5, 0xC5, 0xD2, 0x00, 0xC0, 0x27, 0xA8, 0xD2, 0xB8, 0xA4, 0x38,
+ 0x8B, 0x8D, 0xFF, 0x50, 0x3C, 0x8E, 0xB4, 0x56, 0xFD, 0xE9, 0xBB, 0x01, 0x4A, 0x65, 0x0D, 0x69,
+ 0x94, 0xB9, 0xB8, 0x27, 0x24, 0x86, 0x43, 0x56, 0xF3, 0x8F, 0x6B, 0x5B, 0x40, 0x48, 0xD9, 0x02,
+ 0x1D, 0x80, 0x32, 0x43, 0x40, 0xA1, 0x7A, 0xE9, 0xB2, 0x6E, 0x2A, 0x98, 0xD1, 0xEA, 0x01, 0x1D,
+ 0x90, 0x7C, 0x0C, 0xFE, 0x9A, 0x01, 0x04, 0x0C, 0xAB, 0x28, 0xCA, 0x84, 0xFF, 0x61, 0x00, 0xAB,
+ 0x28, 0x44, 0x96, 0x79, 0x99, 0x90, 0x64, 0x0E, 0xF4, 0x70, 0xBE, 0xDC, 0xC7, 0x88, 0x13, 0xBC,
+ 0x71, 0x73, 0x49, 0xA9, 0x85, 0x75, 0x3D, 0x93, 0x59, 0x5B, 0x36, 0x52, 0x40, 0xF0, 0xE2, 0x01,
+ 0x34, 0x80, 0x01, 0xA1, 0xEA, 0x01, 0x2E, 0x50, 0xB5, 0x2E, 0xBB, 0xAC, 0x2B, 0x0B, 0x04, 0x40,
+ 0x50, 0x03, 0x5C, 0x41, 0x9F, 0xE4, 0x30, 0xA8, 0xCB, 0x47, 0x3B, 0x57, 0xE8, 0xA4, 0xCB, 0xC7,
+ 0x1A, 0x07, 0x20, 0x01, 0x97, 0x71, 0x4C, 0x77, 0x52, 0x6A, 0xD2, 0xA3, 0xC3, 0x66, 0xAC, 0xB6,
+ 0xBF, 0xF6, 0xC3, 0xF3, 0x5A, 0x1A, 0x2A, 0xDC, 0x2A, 0x7E, 0xBA, 0xC6, 0x0E, 0x41, 0x8C, 0xF8,
+ 0xE7, 0x03, 0x22, 0x20, 0x02, 0x78, 0x19, 0xB0, 0x34, 0xE0, 0x9D, 0x12, 0x9A, 0x9E, 0xDC, 0xD1,
+ 0x48, 0x57, 0x0C, 0x76, 0x28, 0xFA, 0x7B, 0xE9, 0x14, 0xAB, 0x0D, 0x2B, 0xBE, 0x18, 0x88, 0x67,
+ 0x63, 0x9C, 0xA5, 0x66, 0x8C, 0xBE, 0x9F, 0x59, 0x97, 0x79, 0x67, 0xB1, 0x1C, 0x27, 0x4D, 0x32,
+ 0x3B, 0x00, 0x1D, 0x03, 0x86, 0x1C, 0x9C, 0x64, 0x0B, 0xE0, 0x02, 0x30, 0x40, 0x02, 0x41, 0x0A,
+ 0xAD, 0xD8, 0xDA, 0x02, 0x2B, 0x0B, 0xB3, 0x8D, 0x64, 0x87, 0x2D, 0x6C, 0x2C, 0xD4, 0xD8, 0x81,
+ 0x27, 0x88, 0xAB, 0xE0, 0x5B, 0x19, 0xAB, 0x58, 0x08, 0x5F, 0x52, 0x6A, 0x26, 0xB6, 0xC8, 0x6D,
+ 0x29, 0xB7, 0xB4, 0xB8, 0x6E, 0xE9, 0xD8, 0x57, 0x27, 0x58, 0xB9, 0x02, 0x62, 0x01, 0x1D, 0x10,
+ 0x64, 0x0B, 0x00, 0xB0, 0x22, 0x00, 0x9E, 0xAB, 0x9A, 0x9E, 0x2D, 0x60, 0xA7, 0xD8, 0x7A, 0x5C,
+ 0xA3, 0x20, 0xA8, 0xA8, 0xE8, 0xC2, 0x51, 0x48, 0xA8, 0x08, 0x5C, 0x19, 0x07, 0xE0, 0x48, 0xE1,
+ 0x30, 0xBB, 0xFE, 0xBA, 0xBC, 0xAE, 0x40, 0xCB, 0x7D, 0xA1, 0xE9, 0x80, 0xD4, 0xA3, 0x71, 0x87,
+ 0x43, 0xCB, 0x08, 0x68, 0x00, 0x37, 0xE7, 0x00, 0x1E, 0x40, 0xC7, 0x77, 0x9C, 0xC7, 0x9F, 0x02,
+ 0xCA, 0x32, 0x90, 0xAD, 0x2F, 0x10, 0x57, 0x02, 0x91, 0xA2, 0x95, 0x39, 0x3E, 0x93, 0x29, 0x7B,
+ 0x58, 0xDA, 0x00, 0x97, 0x41, 0x9F, 0xF3, 0xC9, 0x4C, 0x10, 0x7C, 0xBE, 0xEF, 0x97, 0xCF, 0x1C,
+ 0x2B, 0x86, 0xE1, 0x93, 0x43, 0x6C, 0x62, 0x7D, 0xFA, 0x92, 0x7C, 0xF0, 0x50, 0x71, 0xA7, 0x24,
+ 0x0C, 0x18, 0xD2, 0x44, 0x49, 0xE9, 0x9D, 0x2F, 0x80, 0xC2, 0x2D, 0x50, 0x03, 0x13, 0x0A, 0x2A,
+ 0xA3, 0x70, 0xA2, 0x57, 0xAC, 0xA8, 0xF4, 0x32, 0x44, 0x4A, 0x45, 0x0E, 0xD2, 0xB8, 0xB0, 0xBD,
+ 0x61, 0xCF, 0xCB, 0x93, 0x6E, 0xB2, 0x7C, 0x65, 0x5E, 0x8A, 0xB9, 0xA3, 0x59, 0xBC, 0x45, 0xA5,
+ 0xB9, 0xA3, 0x23, 0x01, 0x8A, 0x5B, 0xD0, 0x25, 0x3D, 0x00, 0x0E, 0xF0, 0xC1, 0x95, 0xE7, 0x02,
+ 0x18, 0x10, 0xA1, 0xC5, 0xCC, 0xA7, 0x5E, 0x13, 0xAD, 0xE9, 0x8C, 0x01, 0x4D, 0x6A, 0xAB, 0x94,
+ 0xC9, 0x84, 0x75, 0x78, 0xB0, 0x80, 0x88, 0x8D, 0xF6, 0x6C, 0x21, 0xD3, 0x29, 0xCB, 0x73, 0x29,
+ 0x0F, 0x9D, 0x0B, 0xC1, 0xA5, 0x39, 0x74, 0xDA, 0xC9, 0xB5, 0x27, 0x5D, 0xB1, 0x83, 0x00, 0x0C,
+ 0xEC, 0xE2, 0x16, 0x1D, 0xE0, 0x01, 0x32, 0x90, 0xC7, 0x3A, 0x40, 0xB8, 0x2D, 0x80, 0x97, 0x35,
+ 0x40, 0x02, 0x2D, 0x30, 0x41, 0xA2, 0xE0, 0xC2, 0xF5, 0x49, 0x87, 0x47, 0xD4, 0x00, 0x0C, 0x53,
+ 0x19, 0x87, 0x32, 0xD4, 0x2D, 0xC2, 0x89, 0xD5, 0xBC, 0xC8, 0xF8, 0x92, 0xB6, 0x12, 0x49, 0x91,
+ 0x80, 0x06, 0xA9, 0xAD, 0xC0, 0x4A, 0x41, 0xCB, 0x3A, 0xF3, 0x02, 0x14, 0x31, 0x66, 0xD5, 0x21,
+ 0x4C, 0xFE, 0x52, 0x54, 0x5C, 0xAD, 0x54, 0xDC, 0x01, 0x9C, 0x28, 0x0A, 0xC6, 0x84, 0xA5, 0x51,
+ 0x2A, 0x8D, 0x35, 0x32, 0xC6, 0x98, 0x52, 0x79, 0x33, 0x49, 0xD4, 0x8E, 0x67, 0x15, 0x46, 0xAD,
+ 0xB4, 0x45, 0x85, 0xBE, 0x9B, 0x5B, 0x8E, 0x34, 0xFA, 0x7E, 0x6F, 0x7D, 0x83, 0x08, 0x78, 0x0E,
+ 0xBD, 0xFC, 0x56, 0x2E, 0xE0, 0x28, 0x7B, 0xE9, 0xB4, 0xF5, 0x1A, 0x63, 0xD1, 0x1A, 0x63, 0x5D,
+ 0x3C, 0xC3, 0x1C, 0xBD, 0xA4, 0x61, 0x79, 0x67, 0xBB, 0xA2, 0x24, 0x71, 0xE5, 0x3B, 0x3B, 0x02,
+ 0x29, 0x2B, 0x0A, 0xD2, 0xFA, 0x8C, 0x65, 0x6F, 0x8D, 0xCD, 0xEA, 0x06, 0x6F, 0x71, 0x69, 0x4D,
+ 0xDD, 0x5C, 0xB4, 0x61, 0x8A, 0x55, 0x78, 0xF8, 0xD2, 0xDB, 0xD6, 0xC4, 0x2F, 0x90, 0x9E, 0xCC,
+ 0x5A, 0xAF, 0x35, 0xD0, 0xA6, 0x82, 0xBD, 0x8A, 0xB9, 0x82, 0xA5, 0xF3, 0x59, 0x21, 0xE9, 0x04,
+ 0x26, 0xA8, 0xA5, 0x23, 0x4A, 0xD1, 0xDA, 0x56, 0x13, 0x01, 0x74, 0x86, 0x0A, 0xD0, 0x10, 0xD9,
+ 0xB2, 0xF5, 0x85, 0xC1, 0x6B, 0xCB, 0xD4, 0x83, 0x38, 0xAF, 0x50, 0x3D, 0x9F, 0xD4, 0x93, 0xBE,
+ 0x2B, 0x73, 0x15, 0x72, 0x01, 0x63, 0xD7, 0x02, 0x7A, 0x79, 0xB7, 0x57, 0x2D, 0x03, 0xF0, 0x0D,
+ 0xD1, 0x32, 0x89, 0x32, 0x76, 0xD2, 0xB0, 0xBF, 0xA9, 0x23, 0xDE, 0x2B, 0x23, 0x08, 0x9D, 0x1C,
+ 0xB5, 0x71, 0x55, 0x7E, 0xD8, 0x75, 0xE4, 0x80, 0x8E, 0xC0, 0x4A, 0xDB, 0xEB, 0x86, 0x5E, 0xE2,
+ 0xFD, 0xC3, 0x16, 0x8C, 0xB1, 0xE6, 0x4D, 0x9D, 0x3D, 0xF1, 0xC6, 0x95, 0xBB, 0x20, 0xE0, 0x4C,
+ 0x28, 0x28, 0xCC, 0xBF, 0x46, 0x9A, 0xCE, 0xE7, 0x74, 0x4E, 0xCC, 0x5A, 0x08, 0xF4, 0x09, 0xB9,
+ 0xF4, 0x4C, 0x35, 0xA5, 0xA6, 0x5D, 0x8E, 0x25, 0x25, 0x18, 0x01, 0x23, 0xF4, 0xF2, 0x9B, 0xAC,
+ 0xFE, 0xB2, 0xA2, 0x0F, 0xFC, 0x0C, 0x0F, 0x41, 0x83, 0x49, 0x6B, 0x41, 0xC1, 0x88, 0xE0, 0xBC,
+ 0xB6, 0xA3, 0x54, 0x59, 0xC6, 0x99, 0xAD, 0x31, 0xAD, 0x72, 0x5B, 0x15, 0x5B, 0x1A, 0xF3, 0x9B,
+ 0x11, 0x71, 0x15, 0x64, 0x00, 0xAB, 0xA7, 0x24, 0xA5, 0x70, 0x24, 0x25, 0xA1, 0x1B, 0x62, 0xCF,
+ 0xF2, 0x28, 0x38, 0x15, 0x92, 0x87, 0x6E, 0xF2, 0x40, 0x18, 0x00, 0x5E, 0x18, 0x72, 0x01, 0x87,
+ 0xFB, 0x7C, 0xAE, 0x13, 0x12, 0xED, 0x47, 0x5A, 0xC0, 0x4B, 0x83, 0xAC, 0xD4, 0xAB, 0xB1, 0x9C,
+ 0xB6, 0x9A, 0x9D, 0xE5, 0xBD, 0x7A, 0x3A, 0x62, 0xB9, 0xE5, 0x08, 0x78, 0x4A, 0x66, 0x33, 0xA1,
+ 0x24, 0x00, 0x03, 0x40, 0x90, 0x9E, 0x8E, 0x02, 0xDF, 0x59, 0x4D, 0xB8, 0x18, 0x78, 0x19, 0x8D,
+ 0x0B, 0x26, 0x8B, 0xE2, 0x28, 0x88, 0x80, 0x6C, 0x56, 0xC3, 0x32, 0x27, 0xF9, 0x87, 0x56, 0x83,
+ 0x8E, 0xED, 0xAC, 0x84, 0x86, 0x9A, 0xCF, 0x87, 0x16, 0xBF, 0xB5, 0xBC, 0xA3, 0x02, 0xA4, 0x85,
+ 0xD2, 0x24, 0xC9, 0x1B, 0x67, 0x38, 0x95, 0x9C, 0x88, 0x77, 0xDE, 0x3D, 0x25, 0xEB, 0xB4, 0x78,
+ 0x39, 0xA1, 0xF7, 0xCA, 0xA7, 0x81, 0x0B, 0xDF, 0x39, 0xB2, 0xE1, 0xC6, 0x94, 0xE4, 0xFE, 0xF0,
+ 0xB1, 0x20, 0x59, 0x3E, 0xE5, 0x40, 0x2C, 0xE6, 0xDB, 0xA8, 0x86, 0xBA, 0xE2, 0x8B, 0x8C, 0x5E,
+ 0x15, 0xC0, 0xCF, 0x17, 0xAC, 0xA5, 0xC1, 0x88, 0xD2, 0x03, 0x78, 0x7A, 0xDA, 0xC9, 0xC6, 0xFB,
+ 0x92, 0xAD, 0x23, 0x51, 0x61, 0x24, 0x00, 0xD8, 0x10, 0x9A, 0xDC, 0x04, 0xF6, 0xAC, 0x32, 0x70,
+ 0xCF, 0xD8, 0x41, 0xCF, 0x96, 0x39, 0x23, 0x1A, 0xA0, 0xD3, 0xA6, 0x28, 0xB3, 0x2E, 0xE9, 0x00,
+ 0x6E, 0x5B, 0xE5, 0x94, 0xDB, 0x7E, 0xE6, 0xAB, 0xC3, 0xB5, 0x56, 0x01, 0x0A, 0x60, 0xCD, 0xFE,
+ 0x35, 0xCA, 0x26, 0xE2, 0xD7, 0x17, 0x61, 0xEE, 0x73, 0xA8, 0xD7, 0x43, 0x7A, 0xD1, 0x02, 0x95,
+ 0xD7, 0x01, 0x1D, 0xD0, 0x44, 0xCB, 0xDA, 0xA3, 0x56, 0xCD, 0xBA, 0x92, 0x4E, 0x3C, 0x43, 0xAD,
+ 0x60, 0x57, 0xB4, 0x01, 0xC2, 0x4E, 0x8A, 0xB9, 0x8C, 0x5B, 0x50, 0x38, 0x10, 0xC8, 0xDA, 0x7E,
+ 0x03, 0x4E, 0xDB, 0xB8, 0x36, 0x01, 0x13, 0x30, 0x27, 0xFF, 0x67, 0x1D, 0xC8, 0x60, 0x62, 0xAD,
+ 0x25, 0xDE, 0x06, 0x8B, 0x0E, 0x06, 0xDB, 0xE0, 0x53, 0x3E, 0xA9, 0x3E, 0x51, 0x67, 0xF3, 0xC9,
+ 0xCB, 0xE0, 0xE5, 0xD5, 0x36, 0xE0, 0x03, 0x35, 0x90, 0xAD, 0x2B, 0x0B, 0xDF, 0x1D, 0xE0, 0x02,
+ 0x23, 0x31, 0x8C, 0x60, 0x54, 0x08, 0xD9, 0xB3, 0x01, 0xB3, 0x31, 0x7C, 0x27, 0x48, 0x87, 0x64,
+ 0xFD, 0xE7, 0xEF, 0xCE, 0x54, 0xE5, 0x96, 0x71, 0x82, 0x76, 0x37, 0xDE, 0x58, 0x01, 0x12, 0x80,
+ 0x0A, 0x46, 0x03, 0x9D, 0x46, 0xCB, 0x80, 0x88, 0xE3, 0x73, 0x86, 0x88, 0x0A, 0x7B, 0xF5, 0x89,
+ 0x76, 0x93, 0x80, 0xBA, 0xE8, 0x34, 0x49, 0x5E, 0xD5, 0x0A, 0x77, 0xC7, 0x43, 0x5E, 0xB5, 0x13,
+ 0xFA, 0x02, 0xD7, 0x68, 0x36, 0x41, 0xF3, 0x40, 0xEC, 0x02, 0x4E, 0xF8, 0xF2, 0x5B, 0xB5, 0xDA,
+ 0xBB, 0x12, 0xEC, 0xDD, 0x1F, 0x9F, 0x71, 0xD6, 0x37, 0x08, 0xD5, 0xC7, 0x02, 0x27, 0x4F, 0x01,
+ 0x50, 0x4F, 0x01, 0x2A, 0x40, 0x40, 0xE3, 0x12, 0x94, 0xB7, 0xED, 0xB6, 0x59, 0x68, 0xBC, 0xBD,
+ 0xAD, 0xC6, 0x0C, 0xE5, 0x3A, 0xB9, 0x22, 0x34, 0xA0, 0x52, 0xDC, 0x7A, 0x0A, 0x2A, 0x34, 0x10,
+ 0xAD, 0x23, 0x25, 0x64, 0x85, 0x12, 0x0E, 0x17, 0xC0, 0x6A, 0x19, 0x36, 0x2C, 0x4C, 0xE8, 0x01,
+ 0x2E, 0xED, 0x50, 0x56, 0x91, 0x4E, 0x96, 0xBD, 0x90, 0xA9, 0x27, 0xD9, 0xD2, 0x8E, 0xFE, 0x2F,
+ 0x14, 0x20, 0x01, 0xF4, 0x1E, 0xF5, 0x53, 0x4F, 0x01, 0x13, 0x70, 0x96, 0xD3, 0x29, 0xE8, 0x7F,
+ 0x67, 0x94, 0x06, 0x2B, 0x5F, 0xBA, 0xEA, 0x3A, 0x32, 0x49, 0x1B, 0x33, 0x72, 0x4E, 0x79, 0x4C,
+ 0xC5, 0x48, 0xCC, 0xBA, 0x41, 0x06, 0x0C, 0x9A, 0x1E, 0x0E, 0x7F, 0x73, 0x27, 0x44, 0x3F, 0x00,
+ 0xC5, 0x69, 0x3B, 0x19, 0xB0, 0x8A, 0xFD, 0x89, 0x08, 0x4B, 0x7D, 0xD4, 0x41, 0xEB, 0x71, 0x38,
+ 0xA9, 0x02, 0x52, 0x3F, 0x71, 0x50, 0xBF, 0x49, 0x75, 0xAD, 0x27, 0xB5, 0x38, 0x1A, 0xD6, 0x57,
+ 0xD4, 0x5A, 0xBA, 0x35, 0xA8, 0x49, 0x7E, 0xF0, 0xC2, 0x1A, 0x71, 0x85, 0x42, 0x4C, 0x0C, 0xAD,
+ 0xA3, 0xEB, 0xF8, 0xFB, 0xCB, 0xBC, 0x66, 0x22, 0x25, 0x1A, 0xF0, 0xF3, 0x9E, 0xE0, 0x3A, 0xCA,
+ 0xE8, 0xF6, 0xBF, 0x65, 0x2C, 0xB1, 0x7D, 0xEA, 0x19, 0xFC, 0xB1, 0x79, 0x37, 0xD7, 0xBD, 0x1A,
+ 0xC1, 0xCF, 0x1F, 0x8B, 0x15, 0x03, 0x4D, 0x3F, 0x95, 0xFA, 0x11, 0x50, 0x01, 0x41, 0x15, 0x3E,
+ 0x2D, 0x9F, 0x85, 0xE8, 0xD6, 0xCD, 0x05, 0x64, 0x58, 0x48, 0xA7, 0xB9, 0x12, 0x35, 0x1B, 0x9E,
+ 0x60, 0xCF, 0x64, 0xC7, 0xC4, 0x65, 0xCF, 0xAC, 0xE7, 0x24, 0x03, 0x46, 0xFA, 0xA9, 0xDC, 0x6E,
+ 0x26, 0x1E, 0x10, 0x34, 0x9F, 0xA2, 0xD3, 0x23, 0x41, 0xF4, 0xE5, 0x13, 0x38, 0x1E, 0x58, 0x00,
+ 0x50, 0x6E, 0xD9, 0x32, 0xAA, 0xCD, 0xEA, 0x0B, 0x08, 0x01, 0x03, 0x00, 0x83, 0x05, 0x2A, 0x14,
+ 0x88, 0x87, 0x88, 0x13, 0x14, 0x11, 0x13, 0x11, 0x03, 0x05, 0x82, 0x11, 0x05, 0x05, 0x83, 0x03,
+ 0x03, 0x01, 0x00, 0x84, 0x01, 0x9D, 0x82, 0x92, 0x9D, 0x9B, 0x99, 0x9E, 0x9E, 0x00, 0xA4, 0xA7,
+ 0x98, 0x06, 0x04, 0x18, 0x18, 0x0E, 0x0E, 0x16, 0x17, 0x1D, 0x1E, 0x1E, 0x34, 0xFE, 0x3F, 0x3E,
+ 0x2E, 0x24, 0x2D, 0x2D, 0x35, 0x35, 0x32, 0xBE, 0x1A, 0xAC, 0x18, 0x16, 0x1E, 0x18, 0xB3, 0x0B,
+ 0x16, 0x0B, 0x04, 0x04, 0x0D, 0x06, 0x99, 0xA3, 0x9E, 0x98, 0x03, 0x12, 0xCF, 0xA7, 0x9A, 0xA4,
+ 0xD1, 0x9B, 0xD9, 0xDA, 0xDB, 0x9A, 0xD9, 0x01, 0x95, 0x01, 0x0A, 0x14, 0x2C, 0x14, 0x0A, 0x11,
+ 0x11, 0x88, 0x8B, 0x2A, 0x2A, 0xE0, 0xE7, 0x8D, 0x05, 0xE7, 0x90, 0xA3, 0x98, 0xDF, 0x96, 0x90,
+ 0xDD, 0xA6, 0x82, 0x9D, 0xD4, 0xD0, 0xD1, 0x98, 0x02, 0x06, 0x0C, 0xB0, 0x72, 0xB5, 0x20, 0x96,
+ 0x87, 0x16, 0x32, 0x6C, 0xE9, 0xD2, 0x25, 0xE3, 0x85, 0x8E, 0x5E, 0x1D, 0x30, 0x6C, 0x08, 0xC6,
+ 0xEA, 0x40, 0x83, 0x03, 0x19, 0x1A, 0x28, 0x1B, 0xD0, 0x60, 0x9A, 0xB2, 0x4D, 0x04, 0x04, 0x39,
+ 0xF3, 0x64, 0xA9, 0x94, 0xB7, 0x7D, 0xFB, 0xB6, 0xA9, 0x9C, 0x00, 0xCF, 0x54, 0x3E, 0x70, 0x88,
+ 0x06, 0x88, 0x73, 0x34, 0x80, 0x82, 0x0A, 0x46, 0x88, 0x2A, 0x35, 0x6A, 0xC4, 0xA8, 0x52, 0x24,
+ 0x4C, 0x3E, 0x45, 0x4A, 0x1A, 0xE4, 0x32, 0x1F, 0xBF, 0x7D, 0xCF, 0x32, 0x09, 0x38, 0x20, 0xB0,
+ 0x81, 0x2B, 0x07, 0xB1, 0x48, 0x78, 0x70, 0xA1, 0xC3, 0x87, 0x0C, 0x86, 0x3A, 0x64, 0xD0, 0xA8,
+ 0x41, 0x83, 0xD5, 0x86, 0xAF, 0x20, 0x30, 0x1C, 0x20, 0x80, 0x80, 0x63, 0x47, 0x09, 0x11, 0x34,
+ 0x12, 0x58, 0xE0, 0xB4, 0xC1, 0xCF, 0x48, 0x02, 0x9C, 0x8D, 0xDA, 0xE4, 0x49, 0xC0, 0x29, 0x97,
+ 0xF8, 0x54, 0x9A, 0xCA, 0x54, 0xC0, 0xA8, 0x4C, 0x05, 0x91, 0x0A, 0xEC, 0xBC, 0x99, 0x28, 0x1D,
+ 0x85, 0x09, 0x8F, 0x1C, 0x4D, 0x40, 0x5B, 0xA9, 0x40, 0x83, 0xC6, 0xF3, 0x42, 0xD1, 0x35, 0x5A,
+ 0x4D, 0x2E, 0xCA, 0x00, 0xAA, 0x90, 0x11, 0xB4, 0x50, 0x8C, 0xC4, 0x8B, 0xFE, 0x1A, 0x3F, 0x5C,
+ 0x30, 0xA4, 0xE1, 0x42, 0xC6, 0x09, 0x19, 0x13, 0x41, 0xC8, 0x02, 0x61, 0x41, 0xD5, 0x00, 0x03,
+ 0x67, 0x23, 0x28, 0x63, 0x36, 0x20, 0xA3, 0xDB, 0x01, 0xCA, 0x02, 0x3A, 0x0B, 0x69, 0xAD, 0x77,
+ 0x27, 0xBB, 0xDF, 0x32, 0xE9, 0x9D, 0x8C, 0x2F, 0xA9, 0x4C, 0x49, 0x94, 0xD0, 0x19, 0x76, 0x14,
+ 0x2F, 0x02, 0x5A, 0x74, 0x05, 0x94, 0x41, 0x96, 0x44, 0x1D, 0xD3, 0xDE, 0x93, 0x01, 0x08, 0xD0,
+ 0x7B, 0x66, 0x37, 0x9A, 0x20, 0x80, 0x06, 0x2C, 0x58, 0x20, 0x78, 0x81, 0x95, 0x07, 0x18, 0x34,
+ 0xAC, 0xEA, 0xE2, 0xEA, 0xAB, 0x85, 0xD4, 0x0E, 0x20, 0x3C, 0x90, 0x60, 0x4A, 0x20, 0xA0, 0x04,
+ 0xE9, 0xD3, 0xB2, 0x63, 0xCA, 0x80, 0x5B, 0x82, 0x00, 0x02, 0x71, 0x49, 0x66, 0x52, 0x37, 0x01,
+ 0x04, 0x28, 0x88, 0x36, 0x79, 0x65, 0x13, 0x18, 0x3E, 0x9D, 0x58, 0xB2, 0x5D, 0x24, 0x11, 0x54,
+ 0xD0, 0x88, 0x62, 0x12, 0x52, 0x00, 0xCF, 0x85, 0x94, 0x44, 0xD7, 0x18, 0x28, 0xDB, 0x89, 0xC4,
+ 0x60, 0x27, 0xDA, 0x51, 0xF3, 0x20, 0x26, 0xB3, 0x19, 0xF0, 0x8A, 0x03, 0x07, 0x14, 0x54, 0x8C,
+ 0x2E, 0x34, 0xE8, 0x40, 0x83, 0x0C, 0x2E, 0xB0, 0xE7, 0x0B, 0x0D, 0x0B, 0x11, 0x93, 0x9B, 0x2A,
+ 0xD1, 0x29, 0x43, 0x80, 0x63, 0xDA, 0x75, 0xB4, 0x00, 0x5B, 0x06, 0xFC, 0x27, 0x09, 0x82, 0xF9,
+ 0x60, 0x47, 0xCA, 0x70, 0x0A, 0x9A, 0xC4, 0xC9, 0x27, 0xC1, 0x35, 0xF6, 0xCE, 0x00, 0xE7, 0x54,
+ 0x00, 0x0F, 0x4D, 0x3A, 0xB1, 0xE4, 0xD3, 0x90, 0xF9, 0xA0, 0x24, 0x9C, 0x37, 0x24, 0xFA, 0xE3,
+ 0x8F, 0x00, 0x60, 0x92, 0x65, 0xE2, 0x02, 0xAF, 0xFC, 0xB8, 0x00, 0x03, 0x11, 0x4D, 0x95, 0x1E,
+ 0x0D, 0x34, 0x90, 0xD0, 0x22, 0x9B, 0x3E, 0x90, 0x56, 0xA3, 0x04, 0xFE, 0x12, 0x04, 0xA4, 0x23,
+ 0x60, 0xFD, 0x11, 0x50, 0x01, 0x6E, 0x19, 0x2C, 0x70, 0x80, 0x03, 0x41, 0x6E, 0x49, 0x57, 0x28,
+ 0x09, 0x4E, 0x86, 0xE4, 0x70, 0x5A, 0xF6, 0x05, 0x89, 0x3C, 0x11, 0x1C, 0x02, 0xA5, 0x72, 0xF0,
+ 0x4C, 0x58, 0x80, 0x95, 0x3C, 0x55, 0x52, 0x41, 0x04, 0x9D, 0xC8, 0xA3, 0xC2, 0x37, 0x08, 0x82,
+ 0xA8, 0x9D, 0x8E, 0x00, 0xE6, 0x06, 0xA8, 0x32, 0xAF, 0xB0, 0x72, 0x01, 0x32, 0x06, 0xB1, 0xC8,
+ 0x0B, 0x69, 0x2D, 0xF6, 0xE2, 0xCB, 0x55, 0xC8, 0x64, 0x50, 0x9F, 0x2A, 0xDA, 0x49, 0x20, 0x08,
+ 0x01, 0xB6, 0x55, 0xF0, 0x29, 0x01, 0x0E, 0x84, 0xDA, 0x0C, 0x76, 0x27, 0x15, 0x79, 0x1D, 0x92,
+ 0xD6, 0x01, 0x40, 0xC9, 0x5E, 0x72, 0x11, 0xE2, 0x0C, 0x4B, 0xF5, 0xB0, 0x04, 0xE5, 0x85, 0x8D,
+ 0x01, 0x30, 0x69, 0x4F, 0x0D, 0x34, 0x8A, 0x08, 0x0B, 0xE4, 0x38, 0xA2, 0x02, 0x25, 0x84, 0x66,
+ 0xA2, 0x51, 0x03, 0x66, 0x3A, 0xB5, 0x59, 0x41, 0xE5, 0xCD, 0xE2, 0x41, 0x44, 0x18, 0x90, 0x90,
+ 0x0B, 0x42, 0x5B, 0xB9, 0xF8, 0xE2, 0xAB, 0x2E, 0xC4, 0xBB, 0x00, 0xAD, 0xB0, 0x3D, 0xE6, 0x4C,
+ 0x01, 0xB6, 0x72, 0x04, 0x54, 0x6D, 0xD1, 0xFC, 0x47, 0xA0, 0x3E, 0xDC, 0x14, 0x69, 0xD7, 0xA1,
+ 0xDE, 0x20, 0x6B, 0x21, 0x28, 0xDF, 0x3C, 0xF9, 0x28, 0x25, 0x10, 0xFE, 0xD4, 0xD8, 0x9E, 0x96,
+ 0xC4, 0x34, 0x49, 0x3A, 0x82, 0x29, 0x47, 0x81, 0x70, 0xFE, 0x78, 0x00, 0x2E, 0x32, 0x3F, 0x3A,
+ 0x70, 0x4C, 0x2C, 0x1D, 0xAC, 0xEB, 0x01, 0x08, 0xB9, 0x90, 0x20, 0x4B, 0x2E, 0x2F, 0xB8, 0xC0,
+ 0xE6, 0x8B, 0x5D, 0xE9, 0x12, 0x6F, 0x7C, 0xB3, 0x06, 0xD4, 0x40, 0x47, 0xD2, 0x74, 0xA4, 0x56,
+ 0x74, 0x8F, 0xC1, 0xF6, 0x4F, 0x76, 0xFE, 0x0E, 0x58, 0x0A, 0xFE, 0x81, 0x00, 0x10, 0x20, 0xAC,
+ 0x5E, 0x79, 0xF5, 0x33, 0xC0, 0x04, 0x91, 0x28, 0xA0, 0x09, 0xC3, 0x0D, 0x4A, 0xF3, 0xEC, 0x95,
+ 0x94, 0x24, 0x16, 0xA9, 0x84, 0xF2, 0xD0, 0x63, 0x8E, 0x26, 0x6F, 0x05, 0xB0, 0x00, 0x45, 0x5C,
+ 0x87, 0xAC, 0xB2, 0x56, 0x6C, 0xBA, 0x90, 0xF2, 0x41, 0x9E, 0xCD, 0xD8, 0xE6, 0x8A, 0x07, 0x91,
+ 0x2C, 0x55, 0x40, 0xF6, 0x11, 0x70, 0x1F, 0x47, 0xCA, 0x30, 0xA6, 0x21, 0x6E, 0x33, 0x47, 0xB3,
+ 0x11, 0x6F, 0x0C, 0x1A, 0xFA, 0xB3, 0x26, 0x42, 0x13, 0xBD, 0xCD, 0x3C, 0x43, 0x61, 0xEA, 0x60,
+ 0x5F, 0x3F, 0x07, 0x26, 0xDD, 0x86, 0xF1, 0xEC, 0x74, 0x58, 0xA3, 0x13, 0x04, 0x90, 0x0E, 0x21,
+ 0xE0, 0x7C, 0xA3, 0xAE, 0x7C, 0xEA, 0x2E, 0xA4, 0xAE, 0xD8, 0x2B, 0xAF, 0xDC, 0x5E, 0x0B, 0xF1,
+ 0xD2, 0xF0, 0xC2, 0x8B, 0x1B, 0x5C, 0x70, 0xD0, 0x41, 0x21, 0x77, 0xD0, 0x1A, 0xAD, 0xDF, 0xE6,
+ 0xE6, 0xB6, 0x02, 0x3E, 0x79, 0xE9, 0xE5, 0x7F, 0xC4, 0xA9, 0x54, 0x0D, 0x5D, 0x96, 0x6C, 0x63,
+ 0xD3, 0x04, 0x2A, 0x0D, 0x82, 0x92, 0xD2, 0xA2, 0x48, 0x8B, 0x71, 0x60, 0x19, 0x62, 0x18, 0xE5,
+ 0x84, 0xF1, 0x28, 0x92, 0xD3, 0xBE, 0xD6, 0x0D, 0xB0, 0x2E, 0xCA, 0x2F, 0x5C, 0x75, 0x4C, 0x2E,
+ 0x0D, 0x65, 0xCE, 0x26, 0x8C, 0xAF, 0xB2, 0xDC, 0x02, 0x06, 0xB2, 0x8C, 0xEE, 0x76, 0x6E, 0x36,
+ 0x97, 0xF8, 0x58, 0x86, 0xC6, 0xF9, 0x23, 0xF4, 0xC0, 0x40, 0xE3, 0x03, 0xE6, 0xDE, 0x07, 0x12,
+ 0xA5, 0xCD, 0x04, 0x2A, 0xA8, 0x8F, 0xA0, 0x33, 0xB1, 0xD7, 0x43, 0xC9, 0x8E, 0x1B, 0x5A, 0x22,
+ 0xD8, 0x61, 0x39, 0xB9, 0xF3, 0x68, 0x25, 0x90, 0x20, 0xAD, 0x49, 0x5F, 0xA6, 0xC8, 0x80, 0x7C,
+ 0xDC, 0xE3, 0x81, 0xF0, 0x44, 0xA4, 0x3C, 0x9C, 0xC1, 0xFE, 0x00, 0xE7, 0xA4, 0xE7, 0xB9, 0xE9,
+ 0x71, 0xEE, 0x7A, 0x16, 0xD8, 0xC0, 0x41, 0x04, 0xA0, 0x16, 0x5A, 0x49, 0x20, 0x3A, 0xBD, 0x42,
+ 0x80, 0x76, 0x34, 0x04, 0x8D, 0x7E, 0xC4, 0x85, 0x28, 0x1F, 0x1A, 0x94, 0x64, 0x8A, 0x02, 0x80,
+ 0xC3, 0x48, 0x29, 0x00, 0x55, 0x1B, 0x0A, 0xEE, 0xB8, 0x81, 0x14, 0x80, 0xD9, 0x0F, 0x12, 0x3E,
+ 0x01, 0x1F, 0x50, 0x50, 0x18, 0x09, 0x67, 0x9D, 0x03, 0x6B, 0xCF, 0x18, 0x8A, 0x4F, 0x4C, 0x51,
+ 0x8C, 0x59, 0x80, 0xC0, 0x00, 0x64, 0xAA, 0x8F, 0x04, 0x2C, 0x00, 0x9F, 0x5C, 0x60, 0x60, 0x65,
+ 0x35, 0x78, 0x48, 0x69, 0x3A, 0xD0, 0x82, 0x91, 0x6D, 0x20, 0x22, 0x4F, 0xEC, 0x00, 0xA8, 0xD4,
+ 0xA2, 0x23, 0x5A, 0xE1, 0x26, 0x47, 0xC9, 0x23, 0x89, 0x63, 0x46, 0x32, 0x80, 0xB2, 0x64, 0x69,
+ 0x50, 0xF9, 0xE8, 0x4E, 0x27, 0xCA, 0xE1, 0x38, 0x14, 0xDE, 0x30, 0x02, 0xD2, 0xB2, 0x10, 0x00,
+ 0x70, 0xF7, 0xB3, 0xEA, 0xF0, 0xA5, 0x12, 0x56, 0xB2, 0xC4, 0x8E, 0xB2, 0x36, 0x94, 0x4C, 0xD1,
+ 0x10, 0x4F, 0x36, 0x11, 0xCA, 0x4F, 0xF2, 0x41, 0x80, 0xD1, 0x65, 0x24, 0x03, 0x17, 0xC8, 0x80,
+ 0x04, 0x00, 0xB9, 0x00, 0x12, 0x14, 0x92, 0x89, 0xBC, 0xE0, 0xC5, 0x0B, 0xAC, 0x72, 0xAE, 0x60,
+ 0x10, 0x03, 0x7B, 0x16, 0x58, 0x06, 0x6E, 0x40, 0xB5, 0x11, 0xB9, 0xBC, 0x46, 0x19, 0xA8, 0xB0,
+ 0x0C, 0x18, 0xE3, 0x27, 0x42, 0x7C, 0xA0, 0x71, 0x27, 0x7D, 0x79, 0x1A, 0x74, 0x2C, 0x84, 0x0E,
+ 0xC9, 0xD0, 0x43, 0x1F, 0xDC, 0x0A, 0x8E, 0x48, 0x22, 0xD1, 0xB4, 0x68, 0x44, 0x4E, 0x7F, 0x8F,
+ 0xFB, 0x04, 0x60, 0xD0, 0x28, 0x0A, 0x56, 0x64, 0xC0, 0x02, 0x82, 0x84, 0xCA, 0x20, 0x1B, 0x20,
+ 0xBA, 0x61, 0xB0, 0x42, 0x08, 0x3F, 0x00, 0xE6, 0xFE, 0x10, 0x7E, 0x00, 0x84, 0x1F, 0x74, 0xE0,
+ 0x98, 0x8F, 0x6C, 0xC5, 0x7F, 0x28, 0xA9, 0xA3, 0x49, 0xD6, 0x27, 0x37, 0x6F, 0xBB, 0x86, 0x3E,
+ 0x46, 0x88, 0x17, 0x43, 0x65, 0x89, 0x50, 0x8E, 0x3B, 0x07, 0x75, 0xCC, 0x78, 0x8E, 0xC6, 0x59,
+ 0xE8, 0x11, 0x2D, 0x11, 0x05, 0x0A, 0x83, 0x23, 0xAD, 0xC6, 0x7C, 0x22, 0x78, 0x6F, 0x7C, 0x47,
+ 0x73, 0xA6, 0x84, 0x88, 0x71, 0x42, 0x86, 0x28, 0x03, 0x80, 0xD8, 0x05, 0xD8, 0x32, 0xB3, 0xB8,
+ 0x95, 0xE7, 0x02, 0xF3, 0xB4, 0x80, 0x08, 0x7C, 0xA0, 0x03, 0x18, 0xBC, 0x00, 0x08, 0x36, 0xB0,
+ 0x05, 0xBA, 0x26, 0x12, 0x11, 0x5A, 0x31, 0x93, 0x44, 0xD2, 0xD1, 0x4E, 0x33, 0xA2, 0x43, 0xA8,
+ 0xBD, 0x14, 0x8D, 0x84, 0x24, 0xA4, 0x66, 0x36, 0x6E, 0x48, 0x81, 0x6C, 0x4C, 0x6A, 0x7F, 0xE8,
+ 0x60, 0x44, 0x26, 0x58, 0x27, 0x4E, 0x57, 0x5A, 0xE2, 0x11, 0x98, 0x70, 0x56, 0x49, 0x1A, 0x93,
+ 0x21, 0x6D, 0x5E, 0x70, 0x61, 0x6F, 0x4C, 0x16, 0x07, 0x07, 0xF0, 0xA3, 0x9A, 0x9D, 0xA5, 0x01,
+ 0xB3, 0x28, 0x8F, 0x02, 0x5B, 0x24, 0x84, 0x21, 0x0C, 0x93, 0x04, 0xE9, 0xC2, 0xE9, 0x23, 0x93,
+ 0x91, 0x50, 0x1D, 0xD9, 0xCB, 0xA7, 0x76, 0xD1, 0x08, 0x3F, 0xDE, 0x12, 0x99, 0x04, 0x95, 0x4F,
+ 0x49, 0x9B, 0xA0, 0xA5, 0xEF, 0x0C, 0xA1, 0x1C, 0xF0, 0x7D, 0x02, 0x80, 0xD7, 0x44, 0xE1, 0x48,
+ 0x19, 0xC6, 0xB4, 0x26, 0x55, 0x62, 0x47, 0xCB, 0x70, 0xC4, 0xA5, 0xE6, 0xF8, 0x93, 0x69, 0x3E,
+ 0x4B, 0x2E, 0x94, 0x9C, 0x99, 0x04, 0x1C, 0xD0, 0x00, 0x56, 0x78, 0xC6, 0x07, 0x3F, 0x48, 0x2B,
+ 0x4E, 0x27, 0xE2, 0x48, 0x0C, 0x2C, 0xC0, 0x99, 0xA1, 0x62, 0xA6, 0xEA, 0xE6, 0x37, 0x97, 0x06,
+ 0x05, 0xCF, 0x7E, 0x25, 0xB1, 0x06, 0x91, 0xFE, 0x7A, 0x13, 0x30, 0xA0, 0x5C, 0x88, 0x05, 0x82,
+ 0xDB, 0x0E, 0xA6, 0xC8, 0xA9, 0xBB, 0x4C, 0x10, 0x0F, 0x30, 0xFC, 0x7B, 0xD6, 0x53, 0xEB, 0xA7,
+ 0x13, 0x0A, 0x9C, 0xF0, 0x1B, 0xA4, 0x98, 0x12, 0x5E, 0x71, 0xE3, 0xCC, 0x8E, 0xB8, 0x4D, 0x02,
+ 0x5B, 0xFB, 0x81, 0x0D, 0x7C, 0x20, 0x04, 0x1D, 0xD8, 0xE0, 0x05, 0x2F, 0xA0, 0xC8, 0x2C, 0x5A,
+ 0x03, 0x10, 0xAC, 0x1E, 0xB4, 0x19, 0xFE, 0x80, 0xC7, 0x5C, 0x36, 0xF1, 0xCE, 0xC5, 0x96, 0xE4,
+ 0x19, 0x5F, 0xB4, 0x66, 0x1A, 0x33, 0x85, 0x8E, 0x73, 0xA4, 0x36, 0x30, 0x0E, 0x52, 0x9F, 0x19,
+ 0xDF, 0x91, 0x30, 0x0B, 0xB1, 0x92, 0xB1, 0x95, 0x78, 0x4C, 0x0C, 0xF7, 0x74, 0x8F, 0x7D, 0x90,
+ 0xD4, 0xB6, 0x0E, 0xF2, 0xE9, 0x33, 0x2F, 0x2B, 0x84, 0x16, 0x04, 0x53, 0x08, 0xD0, 0xFD, 0x81,
+ 0x0E, 0x70, 0xDA, 0x99, 0x26, 0x8E, 0xAA, 0xB2, 0x9F, 0x12, 0x09, 0x26, 0x43, 0x94, 0xCA, 0xC2,
+ 0x5D, 0x28, 0x6B, 0xA7, 0xBC, 0x66, 0xC1, 0xB6, 0x31, 0xD8, 0x45, 0x81, 0x02, 0x96, 0x30, 0x81,
+ 0x52, 0xEF, 0xC4, 0x89, 0x42, 0xE2, 0x35, 0x87, 0x49, 0x1C, 0xD1, 0x90, 0x70, 0x27, 0xD5, 0x9C,
+ 0x0B, 0xAA, 0x80, 0x1C, 0xD8, 0xCA, 0x56, 0x8E, 0xAA, 0xA8, 0x8A, 0x80, 0xF4, 0x6A, 0x56, 0xCB,
+ 0xA0, 0x13, 0x9B, 0xA4, 0xA2, 0x2E, 0x1A, 0x08, 0xA1, 0x4D, 0xA8, 0x9D, 0xE4, 0x05, 0xEB, 0x81,
+ 0xD0, 0x1C, 0x25, 0x07, 0xB1, 0x92, 0xD0, 0xCE, 0x02, 0x1C, 0x04, 0xD9, 0x86, 0xCE, 0x6E, 0xBC,
+ 0xDA, 0xA8, 0x21, 0xF2, 0x5A, 0x07, 0xA5, 0x6F, 0x40, 0xA7, 0x12, 0x59, 0x0A, 0xE5, 0xC2, 0x72,
+ 0x1B, 0xB9, 0xC1, 0x7D, 0x37, 0x52, 0x8A, 0x43, 0xC7, 0x21, 0x56, 0xAC, 0x9C, 0xE4, 0x91, 0x85,
+ 0x7B, 0xAA, 0x2B, 0x11, 0x9D, 0xCA, 0x66, 0xE3, 0xA2, 0xCF, 0xBD, 0x49, 0x06, 0x3C, 0xDD, 0x15,
+ 0x65, 0xA7, 0x81, 0xDB, 0x0D, 0x29, 0xE0, 0xC7, 0xAC, 0xBB, 0x95, 0x74, 0x56, 0x79, 0xA4, 0x22,
+ 0xFF, 0x2B, 0x6F, 0x60, 0xBC, 0x61, 0xEF, 0xBA, 0xC1, 0x17, 0xE8, 0x40, 0x82, 0x10, 0x80, 0x69,
+ 0x12, 0x0D, 0x4F, 0xD9, 0xC2, 0xBD, 0xD8, 0x23, 0x39, 0xF6, 0x40, 0x44, 0x73, 0xF2, 0x67, 0x09,
+ 0x5B, 0x65, 0xC7, 0xA0, 0xB0, 0x59, 0x46, 0x47, 0xFA, 0x64, 0x80, 0x41, 0x5E, 0x20, 0xA0, 0xD0,
+ 0x6D, 0xD1, 0x0B, 0x84, 0xE0, 0x01, 0x8B, 0x98, 0x76, 0x47, 0x3C, 0x65, 0xEC, 0x15, 0x7B, 0xCC,
+ 0x11, 0x0F, 0x61, 0xED, 0xA1, 0xB1, 0x15, 0x4E, 0xD1, 0x34, 0x11, 0x08, 0x00, 0x00, 0x21, 0xF9,
+ 0x04, 0x05, 0x1E, 0x00, 0x46, 0x00, 0x2C, 0x48, 0x00, 0x2C, 0x00, 0x23, 0x00, 0x3F, 0x00, 0x00,
+ 0x07, 0xFE, 0x80, 0x46, 0x82, 0x46, 0x16, 0x83, 0x86, 0x87, 0x0B, 0x87, 0x8A, 0x8B, 0x8C, 0x8D,
+ 0x84, 0x8E, 0x90, 0x91, 0x8D, 0x06, 0x92, 0x8A, 0x85, 0x18, 0x8C, 0x01, 0x95, 0x46, 0x31, 0x34,
+ 0x43, 0x46, 0x01, 0x3E, 0x9B, 0x87, 0x19, 0x8A, 0x0D, 0x87, 0x9F, 0x3C, 0x8A, 0x2F, 0x82, 0x03,
+ 0x9C, 0x87, 0x02, 0x83, 0x19, 0xA7, 0x83, 0xB4, 0x82, 0x36, 0x82, 0x43, 0x9F, 0xA3, 0xA5, 0x8C,
+ 0x34, 0x3F, 0xAF, 0x82, 0x41, 0x8A, 0xC3, 0x46, 0x9F, 0x42, 0x46, 0xBD, 0x90, 0x34, 0x42, 0x3F,
+ 0x42, 0xB8, 0x46, 0x3C, 0xC5, 0xA8, 0x83, 0x3C, 0x35, 0x8A, 0x0E, 0x86, 0x24, 0x46, 0x0E, 0x3E,
+ 0x40, 0x32, 0x3A, 0x36, 0x43, 0xE2, 0x87, 0x41, 0x41, 0x9F, 0x3F, 0xC0, 0x3A, 0x30, 0x8A, 0xCA,
+ 0x83, 0xBF, 0xC8, 0x3C, 0x36, 0x24, 0xBB, 0xC8, 0xC2, 0x86, 0x41, 0x34, 0x34, 0x9A, 0x8D, 0xFC,
+ 0x35, 0xBF, 0x1E, 0x38, 0xD1, 0x33, 0xF2, 0x43, 0x97, 0x11, 0x7B, 0x82, 0x0A, 0xD6, 0xE0, 0xE7,
+ 0xC8, 0x83, 0x0F, 0x1D, 0x46, 0x3C, 0xC4, 0x60, 0x65, 0xCC, 0x88, 0xA7, 0x83, 0x3C, 0xEA, 0x01,
+ 0xD9, 0x05, 0xC9, 0x02, 0x0D, 0x1D, 0x1E, 0x2E, 0x90, 0xB0, 0xE1, 0x42, 0x9C, 0x8E, 0x17, 0x3A,
+ 0x88, 0x0C, 0xD1, 0xF1, 0x69, 0xC8, 0x8F, 0x1A, 0x10, 0x23, 0x11, 0xB0, 0x20, 0x43, 0x06, 0x09,
+ 0x12, 0x42, 0x3C, 0x6C, 0xF3, 0x51, 0x92, 0x20, 0x33, 0x82, 0x42, 0x68, 0xB4, 0xB0, 0xD5, 0x68,
+ 0x40, 0xA2, 0x1A, 0x21, 0x87, 0x78, 0x80, 0x11, 0xD4, 0x18, 0xCC, 0x5C, 0x46, 0x80, 0xB4, 0xD0,
+ 0x90, 0x40, 0xD2, 0x82, 0x1A, 0xDB, 0x2E, 0xCC, 0x33, 0xC2, 0x52, 0xC6, 0x0F, 0x5C, 0x32, 0x6A,
+ 0x0C, 0x01, 0xE2, 0xA3, 0x05, 0x86, 0x0E, 0x92, 0x0E, 0x90, 0x78, 0x61, 0x61, 0xC1, 0x0B, 0x1B,
+ 0xFE, 0x2F, 0x3C, 0xD1, 0x20, 0x08, 0xE4, 0xE3, 0x8F, 0x17, 0x35, 0x6A, 0xB4, 0x70, 0x61, 0xD5,
+ 0xC8, 0x82, 0xBF, 0x5C, 0x49, 0xB8, 0xF0, 0xF1, 0x71, 0x88, 0x8C, 0x8F, 0x3E, 0x78, 0x1A, 0x21,
+ 0xD1, 0x22, 0xAD, 0x87, 0x0E, 0x6D, 0x2F, 0xFC, 0xE8, 0x50, 0x92, 0x46, 0x8D, 0x1F, 0x27, 0x8D,
+ 0xF8, 0xF8, 0x41, 0xC3, 0xC7, 0x63, 0x49, 0x06, 0x30, 0x78, 0x60, 0x40, 0xE2, 0xAA, 0x11, 0x17,
+ 0x31, 0x7C, 0xE0, 0xA5, 0x41, 0xE2, 0x17, 0x11, 0x9E, 0x01, 0x37, 0xB9, 0x00, 0x8C, 0x94, 0xC4,
+ 0x35, 0x17, 0x35, 0x5E, 0xDC, 0x14, 0xA4, 0xFA, 0x05, 0x02, 0x43, 0xEE, 0x14, 0x75, 0xC0, 0xF0,
+ 0x77, 0x29, 0x09, 0x60, 0x9D, 0x69, 0x74, 0x20, 0xE1, 0x15, 0xAF, 0x0C, 0x03, 0xAE, 0x22, 0x1D,
+ 0x88, 0x28, 0x48, 0xAB, 0x07, 0x17, 0xC0, 0x08, 0xB7, 0xF0, 0xE0, 0xD5, 0x62, 0x8B, 0x03, 0xD1,
+ 0x3B, 0x62, 0xC0, 0x60, 0x60, 0xC1, 0x52, 0x41, 0x44, 0x34, 0xA3, 0xAC, 0x29, 0x08, 0x29, 0xC3,
+ 0x48, 0x24, 0x2C, 0x4C, 0xF7, 0xD0, 0xB8, 0x85, 0x8E, 0x6D, 0x2E, 0x64, 0xBC, 0x90, 0xA1, 0x59,
+ 0x07, 0xA6, 0x41, 0xD3, 0x35, 0x62, 0x81, 0x07, 0x16, 0x50, 0x62, 0x81, 0x0B, 0x94, 0xF9, 0x80,
+ 0x41, 0x0B, 0x2F, 0xBC, 0xD0, 0xD8, 0x47, 0x20, 0x79, 0xE0, 0x40, 0x22, 0x90, 0x1C, 0x80, 0x89,
+ 0x85, 0x16, 0x5C, 0x63, 0x9B, 0x11, 0x2D, 0xB4, 0x40, 0x83, 0x0C, 0x1E, 0x6A, 0xD6, 0xC2, 0x35,
+ 0x95, 0x9C, 0x95, 0xC8, 0x02, 0x7C, 0xB5, 0x96, 0x9E, 0x11, 0x0E, 0xEA, 0x63, 0x19, 0x83, 0x01,
+ 0x46, 0xC2, 0x00, 0x26, 0x89, 0xE8, 0xC4, 0xDC, 0x4B, 0xDE, 0xB1, 0xE8, 0xE1, 0x61, 0xD9, 0xA4,
+ 0x05, 0x02, 0x71, 0xE6, 0xC5, 0x36, 0x84, 0x0F, 0x35, 0xC8, 0x40, 0x9F, 0x83, 0x32, 0x10, 0xFE,
+ 0xD9, 0xA3, 0x24, 0x1E, 0x10, 0x27, 0x88, 0x6E, 0x7C, 0xD9, 0xB3, 0x1D, 0x8B, 0x04, 0xC5, 0x24,
+ 0x49, 0x00, 0x1B, 0xA0, 0x65, 0x44, 0x07, 0x36, 0x72, 0x25, 0x88, 0x07, 0xDC, 0xE1, 0xF5, 0xD0,
+ 0x5C, 0x83, 0x14, 0xC2, 0x88, 0x01, 0x2E, 0x90, 0x70, 0x81, 0x11, 0x67, 0x2D, 0x66, 0x44, 0x91,
+ 0x20, 0x8D, 0xA8, 0x99, 0x5E, 0x27, 0x54, 0x72, 0x40, 0x87, 0x14, 0x6E, 0xC9, 0x58, 0x92, 0x1C,
+ 0xF6, 0x27, 0xCA, 0x7F, 0x79, 0x36, 0xB2, 0xC0, 0x72, 0x13, 0x1E, 0x88, 0xD6, 0x5E, 0xA2, 0xB4,
+ 0xF7, 0x83, 0x6A, 0x37, 0x99, 0x29, 0xDD, 0x05, 0x0B, 0x4C, 0x88, 0x09, 0x63, 0x2F, 0x2C, 0x4A,
+ 0x03, 0x08, 0x97, 0x71, 0xD6, 0xC2, 0x70, 0x46, 0xC4, 0x28, 0x28, 0x06, 0x0D, 0xE4, 0xB9, 0x8D,
+ 0x66, 0x3C, 0x79, 0xA8, 0x03, 0x67, 0xF4, 0xC5, 0x06, 0x89, 0x01, 0xD3, 0x1D, 0x90, 0x8D, 0x05,
+ 0x37, 0xE5, 0xA7, 0x0F, 0x87, 0xFC, 0x2D, 0xFA, 0x42, 0x9A, 0x5A, 0x42, 0xB2, 0x80, 0x93, 0x8F,
+ 0xEC, 0x19, 0x16, 0x92, 0xBF, 0x18, 0x71, 0x58, 0xAE, 0xE2, 0x09, 0x92, 0x88, 0x68, 0x6B, 0xE9,
+ 0xA0, 0x5D, 0x7E, 0x9A, 0x19, 0x01, 0x82, 0x0B, 0x6B, 0x46, 0x62, 0xC1, 0x7F, 0x46, 0x44, 0xCB,
+ 0xA0, 0xA5, 0xDB, 0x84, 0x55, 0x43, 0x59, 0x48, 0x39, 0xFA, 0xE9, 0x05, 0x3D, 0x8A, 0x96, 0x10,
+ 0x91, 0x7D, 0xC2, 0x69, 0x99, 0xAA, 0x8E, 0x58, 0x90, 0xCD, 0x01, 0xC7, 0x6A, 0xB9, 0xED, 0x35,
+ 0x8D, 0xFD, 0x93, 0x9C, 0x07, 0x1A, 0x3C, 0x72, 0x66, 0xA4, 0x9E, 0x2E, 0xD7, 0x1A, 0x61, 0x83,
+ 0x88, 0x52, 0xD3, 0x5A, 0xD4, 0x0A, 0x2A, 0x9F, 0xB1, 0xE3, 0xED, 0xA6, 0x43, 0x4C, 0x61, 0xD1,
+ 0xF0, 0xC2, 0x09, 0x8D, 0x45, 0x82, 0x00, 0x02, 0x7F, 0x51, 0x38, 0x69, 0x6B, 0xDB, 0xD9, 0x2A,
+ 0x9C, 0xE4, 0x87, 0x73, 0xB1, 0x66, 0x15, 0x60, 0xD3, 0x2E, 0xD6, 0x42, 0x58, 0x84, 0x35, 0x28,
+ 0x8A, 0x65, 0x45, 0x8E, 0xEA, 0xC8, 0x89, 0x27, 0x46, 0xB4, 0xCD, 0x5C, 0x89, 0x26, 0x49, 0xE2,
+ 0x6D, 0x91, 0xEC, 0x7A, 0x81, 0x05, 0x6D, 0xA9, 0xBC, 0x56, 0x7B, 0x1F, 0x8A, 0xF2, 0x4F, 0x5C,
+ 0x14, 0xA5, 0x8B, 0x49, 0xB4, 0x6C, 0xEA, 0x14, 0x97, 0x20, 0x1F, 0x0E, 0xF2, 0xC2, 0x75, 0x15,
+ 0x12, 0x82, 0x41, 0x21, 0x40, 0xDF, 0x34, 0xB4, 0xB0, 0x64, 0xF2, 0x47, 0xDF, 0x21, 0x44, 0x0D,
+ 0xB2, 0x40, 0x64, 0xEA, 0x0A, 0xB2, 0x9B, 0x21, 0x87, 0xB1, 0x08, 0xA2, 0x60, 0x0D, 0x1B, 0x51,
+ 0xB5, 0x20, 0x85, 0xD0, 0x0C, 0x98, 0x9B, 0x71, 0x25, 0xC6, 0xA2, 0xC5, 0x36, 0xB9, 0x00, 0x03,
+ 0x3B, 0xF0, 0x51, 0xD7, 0x41, 0x07, 0x64, 0xBE, 0x69, 0x91, 0x21, 0x6E, 0xBF, 0x3D, 0x0A, 0x09,
+ 0x1D, 0x34, 0xC8, 0x1F, 0x7F, 0x82, 0x74, 0xCD, 0x9F, 0xDB, 0x1C, 0x98, 0x7C, 0x08, 0xE0, 0x0D,
+ 0xF3, 0xD5, 0xA7, 0x22, 0xC3, 0x1A, 0x02, 0x03, 0x07, 0xA3, 0x70, 0x18, 0xF6, 0xDA, 0x16, 0x7D,
+ 0x66, 0x48, 0xBD, 0x44, 0x1B, 0xEB, 0x6D, 0xE4, 0x82, 0x34, 0x16, 0x23, 0x25, 0x5F, 0x32, 0x1E,
+ 0x09, 0xE0, 0x92, 0x53, 0xCD, 0xF9, 0x20, 0x20, 0x50, 0x17, 0x49, 0x06, 0x67, 0xDB, 0x6B, 0x37,
+ 0xD7, 0x82, 0xFC, 0x87, 0xAE, 0x20, 0x04, 0x10, 0xA0, 0x48, 0xA0, 0x86, 0xCC, 0x05, 0x0C, 0x30,
+ 0x87, 0x2C, 0x38, 0x88, 0xED, 0x86, 0x04, 0x02, 0x00, 0x3B,
+};
diff --git a/gfxconf.example.h b/gfxconf.example.h
index 5d29600f..ce4d4ca6 100644
--- a/gfxconf.example.h
+++ b/gfxconf.example.h
@@ -56,6 +56,7 @@
#define GDISP_NEED_IMAGE_BMP FALSE
#define GDISP_NEED_IMAGE_JPG FALSE
#define GDISP_NEED_IMAGE_PNG FALSE
+#define GDISP_NEED_IMAGE_ACCOUNTING FALSE
/* Optional image support that can be turned off */
/*
diff --git a/include/gdisp/image.h b/include/gdisp/image.h
index 49b10d42..99e51118 100644
--- a/include/gdisp/image.h
+++ b/include/gdisp/image.h
@@ -113,9 +113,13 @@ typedef struct gdispImageIO {
typedef struct gdispImage {
gdispImageType type; /* @< The image type */
gdispImageFlags flags; /* @< The image flags */
+ color_t bgcolor; /* @< The default background color */
coord_t width, height; /* @< The image dimensions */
gdispImageIO io; /* @< The image IO functions */
- uint32_t membytes; /* @< How much RAM has been allocated */
+ #if GDISP_NEED_IMAGE_ACCOUNTING
+ uint32_t memused; /* @< How much RAM is currently allocated */
+ uint32_t maxmemused; /* @< How much RAM has been allocated (maximum) */
+ #endif
const struct gdispImageHandlers * fns; /* @< Don't mess with this! */
struct gdispImagePrivate * priv; /* @< Don't mess with this! */
} gdispImage;
@@ -176,6 +180,7 @@ extern "C" {
*
* @note This determines which decoder to use and then initialises all other fields
* in the gdispImage structure.
+ * @note The image background color is set to White.
* @note There are three types of return - everything OK, partial success and unrecoverable
* failures. For everything OK it returns GDISP_IMAGE_ERR_OK. A partial success can
* be distinguished from a unrecoverable failure by testing the GDISP_IMAGE_ERR_UNRECOVERABLE
@@ -197,6 +202,19 @@ extern "C" {
* @note Also calls the IO close function (if it hasn't already been called).
*/
void gdispImageClose(gdispImage *img);
+
+ /**
+ * @brief Set the background color of the image.
+ *
+ * @param[in] img The image structure
+ * @param[in] bgcolor The background color to use
+ *
+ * @pre gdispImageOpen() must have returned successfully.
+ *
+ * @note This color is only used when an image has to restore part of the background before
+ * continuing with drawing that includes transparency eg some GIF animations.
+ */
+ void gdispImageSetBgColor(gdispImage *img, color_t bgcolor);
/**
* @brief Cache the image
diff --git a/include/gdisp/options.h b/include/gdisp/options.h
index deacc036..5cdfbf59 100644
--- a/include/gdisp/options.h
+++ b/include/gdisp/options.h
@@ -186,6 +186,13 @@
#ifndef GDISP_NEED_IMAGE_PNG
#define GDISP_NEED_IMAGE_PNG FALSE
#endif
+ /**
+ * @brief Is memory accounting required during image decoding.
+ * @details Defaults to FALSE
+ */
+ #ifndef GDISP_NEED_IMAGE_ACCOUNTING
+ #define GDISP_NEED_IMAGE_ACCOUNTING FALSE
+ #endif
/**
* @}
*
diff --git a/src/gdisp/image.c b/src/gdisp/image.c
index 3da0844d..061db5fe 100644
--- a/src/gdisp/image.c
+++ b/src/gdisp/image.c
@@ -167,6 +167,7 @@ bool_t gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPt
gdispImageError gdispImageOpen(gdispImage *img) {
gdispImageError err;
+ img->bgcolor = White;
for(img->fns = ImageHandlers; img->fns < ImageHandlers+sizeof(ImageHandlers)/sizeof(ImageHandlers[0]); img->fns++) {
err = img->fns->open(img);
if (err != GDISP_IMAGE_ERR_BADFORMAT) {
@@ -190,6 +191,10 @@ void gdispImageClose(gdispImage *img) {
img->io.fns->close(&img->io);
}
+void gdispImageSetBgColor(gdispImage *img, color_t bgcolor) {
+ img->bgcolor = bgcolor;
+}
+
gdispImageError gdispImageCache(gdispImage *img) {
if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT;
return img->fns->cache(img);
@@ -205,6 +210,34 @@ systime_t gdispImageNext(gdispImage *img) {
return img->fns->next(img);
}
+// Helper Routines
+void *gdispImageAlloc(gdispImage *img, size_t sz) {
+ #if GDISP_NEED_IMAGE_ACCOUNTING
+ void *ptr;
+
+ ptr = chHeapAlloc(NULL, sz);
+ if (ptr) {
+ img->memused += sz;
+ if (img->memused > img->maxmemused)
+ img->maxmemused = img->memused;
+ }
+ return ptr;
+ #else
+ (void) img;
+ return chHeapAlloc(NULL, sz);
+ #endif
+}
+
+void gdispImageFree(gdispImage *img, void *ptr, size_t sz) {
+ #if GDISP_NEED_IMAGE_ACCOUNTING
+ chHeapFree(ptr);
+ img->memused -= sz;
+ #else
+ (void) img;
+ (void) sz;
+ chHeapFree(ptr);
+ #endif
+}
#endif /* GFX_USE_GDISP && GDISP_NEED_IMAGE */
/** @} */
diff --git a/src/gdisp/image_bmp.c b/src/gdisp/image_bmp.c
index 4ddfc7f8..bab9b4e9 100644
--- a/src/gdisp/image_bmp.c
+++ b/src/gdisp/image_bmp.c
@@ -54,6 +54,12 @@
#endif
/**
+ * Helper Routines Needed
+ */
+void *gdispImageAlloc(gdispImage *img, size_t sz);
+void gdispImageFree(gdispImage *img, void *ptr, size_t sz);
+
+/**
* How big a pixel array to allocate for blitting (in pixels)
* Bigger is faster but uses more RAM.
* This must be greater than 40 bytes and 32 pixels as we read our headers into this space as well
@@ -148,9 +154,8 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
img->flags = 0;
/* Allocate our private area */
- if (!(img->priv = (gdispImagePrivate *)chHeapAlloc(NULL, sizeof(gdispImagePrivate))))
+ if (!(img->priv = (gdispImagePrivate *)gdispImageAlloc(img, sizeof(gdispImagePrivate))))
return GDISP_IMAGE_ERR_NOMEMORY;
- img->membytes = sizeof(gdispImagePrivate);
/* Initialise the essential bits in the private area */
priv = img->priv;
@@ -336,9 +341,8 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
if (priv->bmpflags & BMP_PALETTE) {
img->io.fns->seek(&img->io, offsetColorTable);
- if (!(priv->palette = (color_t *)chHeapAlloc(NULL, priv->palsize*sizeof(color_t))))
+ if (!(priv->palette = (color_t *)gdispImageAlloc(img, priv->palsize*sizeof(color_t))))
return GDISP_IMAGE_ERR_NOMEMORY;
- img->membytes += priv->palsize * sizeof(color_t);
if (priv->bmpflags & BMP_V2) {
for(aword = 0; aword < priv->palsize; aword++) {
if (img->io.fns->read(&img->io, &priv->buf, 3) != 3) goto baddatacleanup;
@@ -430,14 +434,13 @@ void gdispImageClose_BMP(gdispImage *img) {
if (img->priv) {
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
if (img->priv->palette)
- chHeapFree((void *)img->priv->palette);
+ gdispImageFree(img, (void *)img->priv->palette, img->priv->palsize*sizeof(color_t));
#endif
if (img->priv->frame0cache)
- chHeapFree((void *)img->priv->frame0cache);
- chHeapFree((void *)img->priv);
+ gdispImageFree(img, (void *)img->priv->frame0cache, img->width*img->height*sizeof(pixel_t));
+ gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
img->priv = 0;
}
- img->membytes = 0;
img->io.fns->close(&img->io);
}
@@ -794,7 +797,7 @@ gdispImageError gdispImageCache_BMP(gdispImage *img) {
/* We need to allocate the cache */
len = img->width * img->height * sizeof(pixel_t);
- priv->frame0cache = (pixel_t *)chHeapAlloc(NULL, len);
+ priv->frame0cache = (pixel_t *)gdispImageAlloc(img, len);
if (!priv->frame0cache)
return GDISP_IMAGE_ERR_NOMEMORY;
img->membytes += len;
diff --git a/src/gdisp/image_gif.c b/src/gdisp/image_gif.c
index b7a940ad..2672333f 100644
--- a/src/gdisp/image_gif.c
+++ b/src/gdisp/image_gif.c
@@ -28,20 +28,1162 @@
#if GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_GIF
-#error "GIF support not implemented yet"
-
-/* A pallete structure */
-typedef struct gdispImagePallete {
- uint8_t flags;
- #define GDISP_IMAGE_FLG_INT_TRANSPARENT 0x01
- uint8_t idxtrans; /* The transparent idx */
- uint8_t maxidx; /* The maximum index (0..255) */
- uint8_t repidx; /* The index to use if the image data > maxidx */
- color_t pal[256]; /* The pallete entries - not all may actually be allocated */
-} gdispImagePallete;
-
-/* Draw a single palletized line (or partial line) */
-static void gdispDrawPalleteLine(const gdispImagePallete *pal, const uint8_t *line, coord_t x, coord_t y, coord_t cx);
+/**
+ * Helper Routines Needed
+ */
+void *gdispImageAlloc(gdispImage *img, size_t sz);
+void gdispImageFree(gdispImage *img, void *ptr, size_t sz);
+
+/**
+ * How big an array to allocate for blitting (in pixels)
+ * Bigger is faster but uses more RAM.
+ */
+#define BLIT_BUFFER_SIZE 32
+
+/*
+ * Determining endianness as at compile time is not guaranteed or compiler portable.
+ * We use the best test we can. If we can't guarantee little endianness we do things the
+ * hard way.
+ */
+#define GUARANTEED_LITTLE_ENDIAN (!defined(SAFE_ENDIAN) && !defined(SAFE_ALIGNMENT) && (\
+ (defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) \
+ || defined(__LITTLE_ENDIAN__) \
+ || defined(__LITTLE_ENDIAN) \
+ || defined(_LITTLE_ENDIAN) \
+/* || (1 == *(unsigned char *)&(const int){1})*/ \
+ ))
+
+
+/* This is a runtime test */
+static const uint8_t dwordOrder[4] = { 1, 2, 3, 4 };
+
+#define isWordLittleEndian() (*(uint16_t *)&dwordOrder == 0x0201)
+#define isDWordLittleEndian() (*(uint32_t *)&dwordOrder == 0x04030201)
+
+#if GUARANTEED_LITTLE_ENDIAN
+ /* These are fast routines for guaranteed little endian machines */
+ #define CONVERT_FROM_WORD_LE(w)
+ #define CONVERT_FROM_DWORD_LE(dw)
+#else
+ /* These are slower routines for when little endianness cannot be guaranteed at compile time */
+ #define CONVERT_FROM_WORD_LE(w) { if (!isWordLittleEndian()) w = ((((uint16_t)(w))>>8)|(((uint16_t)(w))<<8)); }
+ #define CONVERT_FROM_DWORD_LE(dw) { if (!isDWordLittleEndian()) dw = (((uint32_t)(((const uint8_t *)(&dw))[0]))|(((uint32_t)(((const uint8_t *)(&dw))[1]))<<8)|(((uint32_t)(((const uint8_t *)(&dw))[2]))<<16)|(((uint32_t)(((const uint8_t *)(&dw))[3]))<<24)); }
+#endif
+
+// We need a special error to indicate the end of file (which may not actually be an error)
+#define GDISP_IMAGE_EOF ((gdispImageError)-1)
+#define GDISP_IMAGE_LOOP ((gdispImageError)-2)
+
+#define MAX_CODE_BITS 12
+#define CODE_MAX ((1<<MAX_CODE_BITS)-1) // Maximum legal code value
+#define CODE_FLUSH (CODE_MAX+1) // Illegal code to signal flush
+#define CODE_FIRST (CODE_MAX+2) // Illegal code to signal first
+#define CODE_NONE (CODE_MAX+3) // Illegal code to signal empty
+
+// Convert bits to masks for that number of bits
+static const uint16_t BitMask[] = {
+ 0x0000, 0x0001, 0x0003, 0x0007,
+ 0x000f, 0x001f, 0x003f, 0x007f,
+ 0x00ff, 0x01ff, 0x03ff, 0x07ff,
+ 0x0fff
+ };
+
+// Structure for decoding a single frame
+typedef struct imgdecode {
+ uint8_t blocksz; // The size of the block currently being processed
+ uint8_t maxpixel; // The maximum allowed pixel value
+ uint8_t bitsperpixel;
+ uint8_t bitspercode;
+ uint8_t shiftbits;
+ uint16_t maxcodesz;
+ uint16_t stackcnt; // The number of items on the stack
+ uint16_t code_clear;
+ uint16_t code_eof;
+ uint16_t code_max;
+ uint16_t code_last;
+ uint32_t shiftdata;
+ color_t * palette;
+ uint8_t buf[BLIT_BUFFER_SIZE]; // Buffer for decoded pixels
+ uint16_t prefix[1<<MAX_CODE_BITS]; // The LZW table
+ uint8_t suffix[1<<MAX_CODE_BITS]; // So we can trace the codes
+ uint8_t stack[1<<MAX_CODE_BITS]; // Decoded pixels might be stacked here
+} imgdecode;
+
+// The data on a single frame
+typedef struct imgframe {
+ coord_t x, y; // position relative to full image
+ coord_t width, height; // size of frame
+ uint16_t delay; // delay after processing
+ uint8_t flags; // Local flags
+ #define GIFL_TRANSPARENT 0x01 // There exists a transparent color
+ #define GIFL_DISPOSECLEAR 0x02 // Dispose this frame by clearing
+ #define GIFL_DISPOSEREST 0x04 // Dispose this frame by restoring
+ #define GIFL_INTERLACE 0x08 // Current frame is interlaced
+ uint8_t paltrans; // Transparency
+ uint16_t palsize; // Local palette size
+ size_t posstart; // The file position of the start of the image
+ size_t pospal; // The file position of the palette
+ size_t posimg; // The file position of the image bits
+ size_t posend; // The file position of the end of the frame
+} imgframe;
+
+// The data for a cache
+typedef struct imgcache {
+ imgframe frame;
+ color_t * palette; // Local palette
+ uint8_t * imagebits; // Image bits - only saved when caching
+ struct imgcache * next; // Next cached frame
+} imgcache;
+
+// The data for a dispose area
+typedef struct imgdispose {
+ uint8_t flags; // Frame flags
+ uint8_t paltrans; // Transparency
+ coord_t x, y; // position relative to full image
+ coord_t width, height; // size of dispose area
+} imgdispose;
+
+typedef struct gdispImagePrivate {
+ uint8_t flags; // Flags (global)
+ #define GIF_LOOP 0x01 // Loop back to first frame
+ #define GIF_LOOPFOREVER 0x02 // Looping is forever
+ uint8_t bgcolor; // Background Color (global)
+ uint16_t loops; // Remaining frame loops (if animated)
+ uint16_t palsize; // Global palette size (global)
+ pixel_t *palette; // Global palette (global)
+ size_t frame0pos; // The position of the first frame
+ imgcache * cache; // The list of cached frames
+ imgcache * curcache; // The cache of the current frame (if created)
+ imgdecode * decode; // The decode data for the decode in progress
+ imgframe frame;
+ imgdispose dispose;
+ pixel_t buf[BLIT_BUFFER_SIZE]; // Buffer for reading and blitting
+ } gdispImagePrivate;
+
+/**
+ * Get ready for decoding a frame.
+ *
+ * Pre: Frame info has been read.
+ */
+static gdispImageError startDecode(gdispImage *img) {
+ gdispImagePrivate * priv;
+ imgdecode * decode;
+ uint16_t cnt;
+
+ priv = img->priv;
+
+ // We need the decode ram, and possibly a palette
+ if (!(decode = (imgdecode *)gdispImageAlloc(img, sizeof(imgdecode)+priv->frame.palsize*sizeof(color_t))))
+ return GDISP_IMAGE_ERR_NOMEMORY;
+
+ // We currently have not read any image data block
+ decode->blocksz = 0;
+
+ // Set the palette
+ if (priv->frame.palsize) {
+ // Local palette
+ decode->maxpixel = priv->frame.palsize-1;
+ decode->palette = (color_t *)(decode+1);
+ img->io.fns->seek(&img->io, priv->frame.pospal);
+ for(cnt = 0; cnt < priv->frame.palsize; cnt++) {
+ if (img->io.fns->read(&img->io, &decode->buf, 3) != 3)
+ goto baddatacleanup;
+ decode->palette[cnt] = RGB2COLOR(decode->buf[0], decode->buf[1], decode->buf[2]);
+ }
+ } else if (priv->palette) {
+ // Global palette
+ decode->maxpixel = priv->palsize-1;
+ decode->palette = priv->palette;
+ } else {
+ // Oops - we must have a palette
+ goto baddatacleanup;
+ }
+
+ // Get the initial lzw code size and values
+ img->io.fns->seek(&img->io, priv->frame.posimg);
+ if (img->io.fns->read(&img->io, &decode->bitsperpixel, 1) != 1 || decode->bitsperpixel >= MAX_CODE_BITS)
+ goto baddatacleanup;
+ decode->code_clear = 1 << decode->bitsperpixel;
+ decode->code_eof = decode->code_clear + 1;
+ decode->code_max = decode->code_clear + 2;
+ decode->code_last = CODE_NONE;
+ decode->bitspercode = decode->bitsperpixel+1;
+ decode->maxcodesz = 1 << decode->bitspercode;
+ decode->shiftbits = 0;
+ decode->shiftdata = 0;
+ decode->stackcnt = 0;
+ for(cnt = 0; cnt <= CODE_MAX; cnt++)
+ decode->prefix[cnt] = CODE_NONE;
+
+ // All ready to go
+ priv->decode = decode;
+ return GDISP_IMAGE_ERR_OK;
+
+baddatacleanup:
+ gdispImageFree(img, decode, sizeof(imgdecode)+priv->frame.palsize*sizeof(color_t));
+ return GDISP_IMAGE_ERR_BADDATA;
+}
+
+/**
+ * Stop decoding a frame.
+ *
+ * Pre: Frame info has been read.
+ */
+static void stopDecode(gdispImage *img) {
+ gdispImagePrivate * priv;
+
+ priv = img->priv;
+
+ // Free the decode data
+ if (priv->decode) {
+ gdispImageFree(img, (void *)priv->decode, sizeof(imgdecode)+priv->frame.palsize*sizeof(color_t));
+ priv->decode = 0;
+ }
+}
+
+static uint16_t getPrefix(imgdecode *decode, uint16_t code) {
+ uint16_t i;
+
+ for(i=0; code > decode->code_clear && i <= CODE_MAX; i++, code = decode->prefix[code]) {
+ if (code > CODE_MAX)
+ return CODE_NONE;
+ }
+ return code;
+}
+
+/**
+ * Decode some pixels from a frame.
+ *
+ * Pre: We are ready for decoding.
+ *
+ * Return: The number of pixels decoded 0 .. BLIT_BUFFER_SIZE-1. 0 means EOF
+ *
+ * Note: The resulting pixels are stored in decode->buf
+ */
+static uint16_t getbytes(gdispImage *img) {
+ gdispImagePrivate * priv;
+ imgdecode * decode;
+ uint16_t cnt;
+ uint16_t code, prefix;
+ uint8_t bdata;
+
+ priv = img->priv;
+ decode = priv->decode;
+ cnt = 0;
+
+ // At EOF
+ if (decode->code_last == decode->code_eof)
+ return 0;
+
+ while(cnt < sizeof(decode->buf)) {
+ // Use the stack up first
+ if (decode->stackcnt > 0) {
+ decode->buf[cnt++] = decode->stack[--decode->stackcnt];
+ continue;
+ }
+
+ // Get another code - a code is made up of decode->bitspercode bits.
+ while (decode->shiftbits < decode->bitspercode) {
+ // Get a byte - we may have to start a new data block
+ if ((!decode->blocksz && (img->io.fns->read(&img->io, &decode->blocksz, 1) != 1 || !decode->blocksz))
+ || img->io.fns->read(&img->io, &bdata, 1) != 1) {
+ // Pretend we got the EOF code - some encoders seem to just end the file
+ decode->code_last = decode->code_eof;
+ return cnt;
+ }
+ decode->blocksz--;
+
+ decode->shiftdata |= ((unsigned long)bdata) << decode->shiftbits;
+ decode->shiftbits += 8;
+ }
+ code = decode->shiftdata & BitMask[decode->bitspercode];
+ decode->shiftdata >>= decode->bitspercode;
+ decode->shiftbits -= decode->bitspercode;
+ /**
+ * If code cannot fit into bitspercode bits we must raise its size.
+ * Note that codes above CODE_MAX are used for special signaling.
+ * If we're using MAX_CODE_BITS bits already and we're at the max code, just
+ * keep using the table as it is, don't increment decode->bitspercode.
+ */
+ if (decode->code_max < CODE_MAX + 2 && ++decode->code_max > decode->maxcodesz && decode->bitspercode < MAX_CODE_BITS) {
+ decode->maxcodesz <<= 1;
+ decode->bitspercode++;
+ }
+
+ // EOF - the appropriate way to stop decoding
+ if (code == decode->code_eof) {
+ // Skip to the end of the data blocks
+ do {
+ img->io.fns->seek(&img->io, img->io.pos+decode->blocksz);
+ } while (img->io.fns->read(&img->io, &decode->blocksz, 1) == 1 && decode->blocksz);
+
+ // Mark the end
+ decode->code_last = decode->code_eof;
+ break;
+ }
+
+ if (code == decode->code_clear) {
+ // Start again
+ for(prefix = 0; prefix <= CODE_MAX; prefix++)
+ decode->prefix[prefix] = CODE_NONE;
+ decode->code_max = decode->code_eof + 1;
+ decode->bitspercode = decode->bitsperpixel + 1;
+ decode->maxcodesz = 1 << decode->bitspercode;
+ decode->code_last = CODE_NONE;
+ continue;
+ }
+
+ if (code < decode->code_clear) {
+ // Simple unencoded pixel - add it
+ decode->buf[cnt++] = code;
+
+ } else {
+ /**
+ * Its a LZW code - trace the linked list until the prefix is a
+ * valid pixel while pushing the suffix pixels on the stack.
+ * If done, pop the stack in reverse order adding the pixels
+ */
+ if (decode->prefix[code] != CODE_NONE)
+ prefix = code;
+
+ /**
+ * Only allowed if the code equals the partial code.
+ * In that case code = XXXCode, CrntCode or the
+ * prefix code is last code and the suffix char is
+ * exactly the prefix of last code!
+ */
+ else if (code == decode->code_max - 2 && decode->stackcnt < sizeof(decode->stack)) {
+ prefix = decode->code_last;
+ decode->suffix[decode->code_max - 2] = decode->stack[decode->stackcnt++] = getPrefix(decode, decode->code_last);
+ } else
+ return 0;
+
+ /**
+ * If the image is OK we should not get a CODE_NONE while tracing.
+ * To prevent looping with a bad image we use StackPtr as loop counter
+ * and stop before overflowing Stack[].
+ */
+ while (decode->stackcnt < sizeof(decode->stack) && prefix > decode->code_clear && prefix <= CODE_MAX) {
+ decode->stack[decode->stackcnt++] = decode->suffix[prefix];
+ prefix = decode->prefix[prefix];
+ }
+ if (decode->stackcnt >= sizeof(decode->stack) || prefix > CODE_MAX)
+ return 0;
+
+ /* Push the last character on stack: */
+ decode->stack[decode->stackcnt++] = prefix;
+ }
+
+ if (decode->code_last != CODE_NONE && decode->prefix[decode->code_max - 2] == CODE_NONE) {
+ decode->prefix[decode->code_max - 2] = decode->code_last;
+
+ /* Only allowed if code is exactly the running code:
+ * In that case code = XXXCode, CrntCode or the
+ * prefix code is last code and the suffix char is
+ * exactly the prefix of last code! */
+ decode->suffix[decode->code_max - 2] = getPrefix(decode, code == decode->code_max - 2 ? decode->code_last : code);
+ }
+ decode->code_last = code;
+ }
+ return cnt;
+}
+
+/**
+ * Read the info on a frame.
+ *
+ * Pre: The file position is at the start of the frame.
+ */
+static gdispImageError initFrame(gdispImage *img) {
+ gdispImagePrivate * priv;
+ imgcache * cache;
+ uint8_t blocktype;
+ uint8_t blocksz;
+
+ priv = img->priv;
+
+ // Save the dispose info from the existing frame
+ priv->dispose.flags = priv->frame.flags;
+ priv->dispose.paltrans = priv->frame.paltrans;
+ priv->dispose.x = priv->frame.x;
+ priv->dispose.y = priv->frame.y;
+ priv->dispose.width = priv->frame.width;
+ priv->dispose.height = priv->frame.height;
+
+ // Check for a cached version of this image
+ for(cache=priv->cache; cache && cache->frame.posstart <= img->io.pos; cache=cache->next) {
+ if (cache->frame.posstart == img->io.pos) {
+ priv->frame = cache->frame;
+ priv->curcache = cache;
+ return GDISP_IMAGE_ERR_OK;
+ }
+ }
+
+ // Get ready for a new image
+ priv->curcache = 0;
+ priv->frame.posstart = img->io.pos;
+ priv->frame.flags = 0;
+ priv->frame.delay = 0;
+ priv->frame.palsize = 0;
+
+ // Process blocks until we reach the image descriptor
+ while(1) {
+ if (img->io.fns->read(&img->io, &blocktype, 1) != 1)
+ return GDISP_IMAGE_ERR_BADDATA;
+
+ switch(blocktype) {
+ case 0x2C: //',' - IMAGE_DESC_RECORD_TYPE;
+ // Read the Image Descriptor
+ if (img->io.fns->read(&img->io, priv->buf, 9) != 9)
+ return GDISP_IMAGE_ERR_BADDATA;
+ priv->frame.x = *(uint16_t *)(((uint8_t *)priv->buf)+0);
+ CONVERT_FROM_WORD_LE(priv->frame.x);
+ priv->frame.y = *(uint16_t *)(((uint8_t *)priv->buf)+2);
+ CONVERT_FROM_WORD_LE(priv->frame.y);
+ priv->frame.width = *(uint16_t *)(((uint8_t *)priv->buf)+4);
+ CONVERT_FROM_WORD_LE(priv->frame.width);
+ priv->frame.height = *(uint16_t *)(((uint8_t *)priv->buf)+6);
+ CONVERT_FROM_WORD_LE(priv->frame.height);
+ if (((uint8_t *)priv->buf)[8] & 0x80) // Local color table?
+ priv->frame.palsize = 2 << (((uint8_t *)priv->buf)[8] & 0x07);
+ if (((uint8_t *)priv->buf)[8] & 0x40) // Interlaced?
+ priv->frame.flags |= GIFL_INTERLACE;
+
+ // We are ready to go for the actual palette read and image decode
+ priv->frame.pospal = img->io.pos;
+ priv->frame.posimg = priv->frame.pospal+priv->frame.palsize*3;
+ priv->frame.posend = 0;
+
+ // Mark this as an animated image if more than 1 frame.
+ if (priv->frame.posstart != priv->frame0pos)
+ img->flags |= GDISP_IMAGE_FLG_ANIMATED;
+ return GDISP_IMAGE_ERR_OK;
+
+ case 0x21: //'!' - EXTENSION_RECORD_TYPE;
+ // Read the extension type
+ if (img->io.fns->read(&img->io, &blocktype, 1) != 1)
+ return GDISP_IMAGE_ERR_BADDATA;
+
+ switch(blocktype) {
+ case 0xF9: // EXTENSION - Graphics Control Block
+ // Read the GCB
+ if (img->io.fns->read(&img->io, priv->buf, 6) != 6)
+ return GDISP_IMAGE_ERR_BADDATA;
+ // Check we have read a 4 byte data block and a data block terminator (0)
+ if (((uint8_t *)priv->buf)[0] != 4 || ((uint8_t *)priv->buf)[5] != 0)
+ return GDISP_IMAGE_ERR_BADDATA;
+ // Process the flags
+ switch(((uint8_t *)priv->buf)[1] & 0x1C) {
+ case 0x00: case 0x04: break; // Dispose = do nothing
+ case 0x08: priv->frame.flags |= GIFL_DISPOSECLEAR; break; // Dispose = clear
+ case 0x0C: case 0x10: priv->frame.flags |= GIFL_DISPOSEREST; break; // Dispose = restore. Value 0x10 is a hack for bad encoders
+ default: return GDISP_IMAGE_ERR_UNSUPPORTED;
+ }
+ if (((uint8_t *)priv->buf)[1] & 0x01) {
+ priv->frame.flags |= GIFL_TRANSPARENT;
+ img->flags |= GDISP_IMAGE_FLG_TRANSPARENT; // We set this but never clear it
+ }
+ if (((uint8_t *)priv->buf)[1] & 0x02) // Wait for user input?
+ img->flags |= GDISP_IMAGE_FLG_MULTIPAGE;
+ else
+ img->flags &= ~GDISP_IMAGE_FLG_MULTIPAGE;
+ // Process frame delay and the transparent color (if any)
+ priv->frame.delay = *(uint16_t *)(((uint8_t *)priv->buf)+2);
+ CONVERT_FROM_WORD_LE(priv->frame.delay);
+ priv->frame.paltrans = ((uint8_t *)priv->buf)[4];
+ break;
+
+ case 0xFF: // EXTENSION - Application
+ // We only handle this for the special Netscape loop counter for animation
+ if (priv->flags & GIF_LOOP)
+ goto skipdatablocks;
+ // Read the Application header
+ if (img->io.fns->read(&img->io, priv->buf, 16) != 16)
+ return GDISP_IMAGE_ERR_BADDATA;
+ // Check we have read a 11 byte data block
+ if (((uint8_t *)priv->buf)[0] != 11 && ((uint8_t *)priv->buf)[12] != 3)
+ return GDISP_IMAGE_ERR_BADDATA;
+ // Check the vendor
+ if (((uint8_t *)priv->buf)[1] == 'N' && ((uint8_t *)priv->buf)[2] == 'E' && ((uint8_t *)priv->buf)[3] == 'T'
+ && ((uint8_t *)priv->buf)[4] == 'S' && ((uint8_t *)priv->buf)[5] == 'C' && ((uint8_t *)priv->buf)[6] == 'A'
+ && ((uint8_t *)priv->buf)[7] == 'P' && ((uint8_t *)priv->buf)[8] == 'E' && ((uint8_t *)priv->buf)[9] == '2'
+ && ((uint8_t *)priv->buf)[10] == '.' && ((uint8_t *)priv->buf)[11] == '0') {
+ if (((uint8_t *)priv->buf)[13] == 1) {
+ priv->loops = *(uint16_t *)(((uint8_t *)priv->buf)+14);
+ CONVERT_FROM_WORD_LE(priv->loops);
+ priv->flags |= GIF_LOOP;
+ if (!priv->loops)
+ priv->flags |= GIF_LOOPFOREVER;
+ }
+ }
+ goto skipdatablocks;
+
+ case 0x01: // EXTENSION - Plain Text (Graphics Rendering)
+ case 0xFE: // EXTENSION - Comment
+ default:
+ // 0x00-0x7F (0-127) are the Graphic Rendering blocks
+ if (blocktype <= 0x7F)
+ return GDISP_IMAGE_ERR_UNSUPPORTED;
+ // 0x80-0xF9 (128-249) are the Control blocks
+ // 0xFA-0xFF (250-255) are the Special Purpose blocks
+ // We don't understand this extension - just skip it by skipping data blocks
+ skipdatablocks:
+ while(1) {
+ if (img->io.fns->read(&img->io, &blocksz, 1) != 1)
+ return GDISP_IMAGE_ERR_BADDATA;
+ if (!blocksz)
+ break;
+ img->io.fns->seek(&img->io, img->io.pos + blocksz);
+ }
+ break;
+ }
+ break;
+
+ case 0x3B: //';' - TERMINATE_RECORD_TYPE;
+ // Are we an looping animation
+ if (!(priv->flags & GIF_LOOP))
+ return GDISP_IMAGE_EOF;
+ if (!(priv->flags & GIF_LOOPFOREVER)) {
+ if (!priv->loops)
+ return GDISP_IMAGE_EOF;
+ priv->loops--;
+ }
+
+ // Seek back to frame0
+ img->io.fns->seek(&img->io, priv->frame0pos);
+ return GDISP_IMAGE_LOOP;
+
+ default: // UNDEFINED_RECORD_TYPE;
+ return GDISP_IMAGE_ERR_UNSUPPORTED;
+ }
+ }
+}
+
+gdispImageError gdispImageOpen_GIF(gdispImage *img) {
+ gdispImagePrivate *priv;
+ uint8_t hdr[6];
+ uint16_t aword;
+
+ /* Read the file identifier */
+ if (img->io.fns->read(&img->io, hdr, 6) != 6)
+ return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
+
+ /* Process the GIFFILEHEADER structure */
+
+ if (hdr[0] != 'G' || hdr[1] != 'I' || hdr[2] != 'F'
+ || hdr[3] != '8' || (hdr[4] != '7' && hdr[4] != '9') || hdr[5] != 'a')
+ return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
+
+ /* We know we are a GIF format image */
+ img->flags = 0;
+
+ /* Allocate our private area */
+ if (!(img->priv = (gdispImagePrivate *)gdispImageAlloc(img, sizeof(gdispImagePrivate))))
+ return GDISP_IMAGE_ERR_NOMEMORY;
+
+ /* Initialise the essential bits in the private area */
+ priv = img->priv;
+ priv->flags = 0;
+ priv->palsize = 0;
+ priv->palette = 0;
+ priv->frame.flags = 0;
+
+ /* Process the Screen Descriptor structure */
+
+ // Read the screen descriptor
+ if (img->io.fns->read(&img->io, priv->buf, 7) != 7)
+ goto baddatacleanup;
+ // Get the width
+ img->width = *(uint16_t *)(((uint8_t *)priv->buf)+0);
+ CONVERT_FROM_WORD_LE(img->width);
+ // Get the height
+ img->height = *(uint16_t *)(((uint8_t *)priv->buf)+2);
+ CONVERT_FROM_WORD_LE(img->height);
+ if (((uint8_t *)priv->buf)[4] & 0x80) {
+ // Global color table
+ priv->palsize = 2 << (((uint8_t *)priv->buf)[4] & 0x07);
+ // Allocate the global palette
+ if (!(priv->palette = (color_t *)gdispImageAlloc(img, priv->palsize*sizeof(color_t))))
+ goto nomemcleanup;
+ // Read the global palette
+ for(aword = 0; aword < priv->palsize; aword++) {
+ if (img->io.fns->read(&img->io, &priv->buf, 3) != 3)
+ goto baddatacleanup;
+ priv->palette[aword] = RGB2COLOR(((uint8_t *)priv->buf)[0], ((uint8_t *)priv->buf)[1], ((uint8_t *)priv->buf)[2]);
+ }
+ }
+ priv->bgcolor = ((uint8_t *)priv->buf)[5];
+
+ // Save the fram0pos
+ priv->frame0pos = img->io.pos;
+
+ // Read the first frame descriptor
+ switch(initFrame(img)) {
+ case GDISP_IMAGE_ERR_OK: // Everything OK
+ return GDISP_IMAGE_ERR_OK;
+ case GDISP_IMAGE_ERR_UNSUPPORTED: // Unsupported
+ gdispImageClose_GIF(img); // Clean up the private data area
+ return GDISP_IMAGE_ERR_UNSUPPORTED;
+ case GDISP_IMAGE_ERR_NOMEMORY: // Out of Memory
+ nomemcleanup:
+ gdispImageClose_GIF(img); // Clean up the private data area
+ return GDISP_IMAGE_ERR_NOMEMORY;
+ case GDISP_IMAGE_EOF: // We should have a frame but we don't seem to
+ case GDISP_IMAGE_LOOP: // We should have a frame but we don't seem to
+ case GDISP_IMAGE_ERR_BADDATA: // Oops - something wrong with the data
+ default:
+ baddatacleanup:
+ gdispImageClose_GIF(img); // Clean up the private data area
+ return GDISP_IMAGE_ERR_BADDATA;
+ }
+}
+
+void gdispImageClose_GIF(gdispImage *img) {
+ gdispImagePrivate * priv;
+ imgcache * cache;
+ imgcache * ncache;
+
+ priv = img->priv;
+ if (priv) {
+ // Free any stored frames
+ cache = priv->cache;
+ while(cache) {
+ ncache = cache->next;
+ gdispImageFree(img, (void *)cache, sizeof(imgcache)+cache->frame.width*cache->frame.height+cache->frame.palsize*sizeof(color_t));
+ cache = ncache;
+ }
+ if (priv->palette)
+ gdispImageFree(img, (void *)priv->palette, priv->palsize*sizeof(color_t));
+ gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
+ img->priv = 0;
+ }
+ img->io.fns->close(&img->io);
+}
+
+gdispImageError gdispImageCache_GIF(gdispImage *img) {
+ gdispImagePrivate * priv;
+ imgcache * cache;
+ imgdecode * decode;
+ uint8_t * p;
+ uint8_t * q;
+ coord_t mx, my;
+ uint16_t cnt;
+
+ /* If we are already cached - just return OK */
+ priv = img->priv;
+ if (priv->curcache)
+ return GDISP_IMAGE_ERR_OK;
+
+ /* We need to allocate the frame, the palette and bits for the image */
+ if (!(cache = (imgcache *)gdispImageAlloc(img, sizeof(imgcache) + priv->frame.palsize*sizeof(color_t) + priv->frame.width*priv->frame.height)))
+ return GDISP_IMAGE_ERR_NOMEMORY;
+
+ /* Initialise the cache */
+ decode = 0;
+ cache->frame = priv->frame;
+ cache->imagebits = (uint8_t *)(cache+1) + cache->frame.palsize*sizeof(color_t);
+ cache->next = 0;
+
+ /* Start the decode */
+ switch(startDecode(img)) {
+ case GDISP_IMAGE_ERR_OK: break;
+ case GDISP_IMAGE_ERR_NOMEMORY: goto nomemcleanup;
+ case GDISP_IMAGE_ERR_BADDATA:
+ default: goto baddatacleanup;
+ }
+ decode = priv->decode;
+
+ // Save the palette
+ if (cache->frame.palsize) {
+ cache->palette = (color_t *)(cache+1);
+
+ /* Copy the local palette into the cache */
+ for(cnt = 0; cnt < cache->frame.palsize; cnt++)
+ cache->palette[cnt] = decode->palette[cnt];
+ } else
+ cache->palette = priv->palette;
+
+ // Check for interlacing
+ cnt = 0;
+ if (cache->frame.flags & GIFL_INTERLACE) {
+ // Every 8th row starting at row 0
+ for(p=cache->imagebits, my=0; my < cache->frame.height; my+=8, p += cache->frame.width*7) {
+ for(mx=0; mx < cache->frame.width; mx++) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ while(cnt < sizeof(decode->buf))
+ decode->buf[cnt++] = (cache->frame.flags & GIFL_TRANSPARENT) ? cache->frame.paltrans : 0;
+ }
+ q = decode->buf;
+ }
+ *p++ = *q++;
+ cnt--;
+ }
+ }
+ // Every 8th row starting at row 4
+ for(p=cache->imagebits+cache->frame.width*4, my=4; my < cache->frame.height; my+=8, p += cache->frame.width*7) {
+ for(mx=0; mx < cache->frame.width; mx++) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ while(cnt < sizeof(decode->buf))
+ decode->buf[cnt++] = (cache->frame.flags & GIFL_TRANSPARENT) ? cache->frame.paltrans : 0;
+ }
+ q = decode->buf;
+ }
+ *p++ = *q++;
+ cnt--;
+ }
+ }
+ // Every 4th row starting at row 2
+ for(p=cache->imagebits+cache->frame.width*2, my=2; my < cache->frame.height; my+=4, p += cache->frame.width*3) {
+ for(mx=0; mx < cache->frame.width; mx++) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ while(cnt < sizeof(decode->buf))
+ decode->buf[cnt++] = (cache->frame.flags & GIFL_TRANSPARENT) ? cache->frame.paltrans : 0;
+ }
+ q = decode->buf;
+ }
+ *p++ = *q++;
+ cnt--;
+ }
+ }
+ // Every 2nd row starting at row 1
+ for(p=cache->imagebits+cache->frame.width, my=1; my < cache->frame.height; my+=2, p += cache->frame.width) {
+ for(mx=0; mx < cache->frame.width; mx++) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ while(cnt < sizeof(decode->buf))
+ decode->buf[cnt++] = (cache->frame.flags & GIFL_TRANSPARENT) ? cache->frame.paltrans : 0;
+ }
+ q = decode->buf;
+ }
+ *p++ = *q++;
+ cnt--;
+ }
+ }
+ } else {
+ // Every row in sequence
+ p=cache->imagebits;
+ for(my=0; my < cache->frame.height; my++) {
+ for(mx=0; mx < cache->frame.width; mx++) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ while(cnt < sizeof(decode->buf))
+ decode->buf[cnt++] = (cache->frame.flags & GIFL_TRANSPARENT) ? cache->frame.paltrans : 0;
+ }
+ q = decode->buf;
+ }
+ *p++ = *q++;
+ cnt--;
+ }
+ }
+ }
+ // We could be pedantic here but extra bytes won't hurt us
+ while(getbytes(img));
+ priv->frame.posend = cache->frame.posend = img->io.pos;
+
+ // Save everything
+ priv->curcache = cache;
+ if (!priv->cache)
+ priv->cache = cache;
+ else if (priv->cache->frame.posstart > cache->frame.posstart) {
+ cache->next = priv->cache;
+ priv->cache = cache;
+ } else {
+ imgcache *pc;
+
+ for(pc = priv->cache; pc; pc = pc->next) {
+ if (!pc->next || pc->next->frame.posstart > cache->frame.posstart) {
+ cache->next = pc->next;
+ pc->next = cache;
+ break;
+ }
+ }
+ }
+ stopDecode(img);
+ return GDISP_IMAGE_ERR_OK;
+
+nomemcleanup:
+ stopDecode(img);
+ gdispImageFree(img, cache, sizeof(imgcache) + priv->frame.palsize*sizeof(color_t) + priv->frame.width*priv->frame.height);
+ return GDISP_IMAGE_ERR_NOMEMORY;
+
+baddatacleanup:
+ stopDecode(img);
+ gdispImageFree(img, cache, sizeof(imgcache) + priv->frame.palsize*sizeof(color_t) + priv->frame.width*priv->frame.height);
+ return GDISP_IMAGE_ERR_BADDATA;
+}
+
+gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
+ gdispImagePrivate * priv;
+ imgdecode * decode;
+ uint8_t * q;
+ coord_t mx, my, fx, fy;
+ uint16_t cnt, gcnt;
+ uint8_t col;
+
+ priv = img->priv;
+
+ /* Handle previous frame disposing */
+ if (priv->dispose.flags & (GIFL_DISPOSECLEAR|GIFL_DISPOSEREST)) {
+ // Clip to the disposal area - clip area = mx,my -> fx, fy (sx,sy,cx,cy are unchanged)
+ mx = priv->dispose.x;
+ my = priv->dispose.y;
+ fx = priv->dispose.x+priv->dispose.width;
+ fy = priv->dispose.y+priv->dispose.height;
+ if (sx > mx) mx = sx;
+ if (sy > my) my = sy;
+ if (sx+cx <= fx) fx = sx+cx;
+ if (sy+cy <= fy) fy = sy+cy;
+ if (fx > mx && fy > my) {
+ // We only support clearing (not restoring). The specification says that we are allowed to do this.
+ // Calculate the bgcolor
+ // The spec says to restore the backgound color (priv->bgcolor) but in practice if there is transparency
+ // image decoders tend to assume that a restore to the transparent color is required instead
+ if (((priv->dispose.flags & GIFL_TRANSPARENT) /*&& priv->dispose.paltrans == priv->bgcolor*/) || priv->bgcolor >= priv->palsize)
+ gdispFillArea(x+mx, y+my, fx-mx, fy-my, img->bgcolor);
+ else
+ gdispFillArea(x+mx, y+my, fx-mx, fy-my, priv->palette[priv->bgcolor]);
+ }
+ }
+
+ /* Clip to just this frame - clip area = sx,sy -> fx, fy */
+ fx = priv->frame.x+priv->frame.width;
+ fy = priv->frame.y+priv->frame.height;
+ if (sx >= fx || sy >= fy || sx+cx < priv->frame.x || sy+cy < priv->frame.y) return GDISP_IMAGE_ERR_OK;
+ if (sx < priv->frame.x) { mx = priv->frame.x - sx; x += mx; cx -= mx; sx = priv->frame.x; }
+ if (sy < priv->frame.y) { my = priv->frame.y - sy; y += my; cy -= my; sy = priv->frame.y; }
+ if (sx+cx > fx) cx = fx-sx;
+ if (sy+cy > fy) cy = fy-sy;
+
+ // Make sx, sy relative to this frame so we are not adding priv->frame.x & priv->frame.y each time
+ sx -= priv->frame.x; sy -= priv->frame.y;
+ fx = sx + cx;
+ fy = sy + cy;
+
+ /* Draw from the image cache - if it exists */
+ if (priv->curcache) {
+ imgcache * cache;
+
+ cache = priv->curcache;
+ q = cache->imagebits+priv->frame.width*sy+sx;
+
+ for(my=sy; my < fy; my++, q += priv->frame.width - cx) {
+ for(gcnt=0, mx=sx, cnt=0; mx < fx; mx++) {
+ col = *q++;
+ if ((priv->frame.flags & GIFL_TRANSPARENT) && col == priv->frame.paltrans) {
+ // We have a transparent pixel - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ gcnt = 0;
+ continue;
+ }
+ priv->buf[gcnt++] = cache->palette[col];
+ if (gcnt >= BLIT_BUFFER_SIZE) {
+ // We have run out of buffer - dump it to the display
+ gdispBlitAreaEx(x+mx-gcnt+1, y+my, gcnt, 1, 0, 0, gcnt, priv->buf);
+ gcnt = 0;
+ }
+ }
+ // We have finished the line - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ }
+
+ return GDISP_IMAGE_ERR_OK;
+ }
+
+ /* Start the decode */
+ switch(startDecode(img)) {
+ case GDISP_IMAGE_ERR_OK: break;
+ case GDISP_IMAGE_ERR_NOMEMORY: return GDISP_IMAGE_ERR_NOMEMORY;
+ case GDISP_IMAGE_ERR_BADDATA:
+ default: return GDISP_IMAGE_ERR_BADDATA;
+ }
+ decode = priv->decode;
+
+ // Check for interlacing
+ cnt = 0;
+ if (priv->frame.flags & GIFL_INTERLACE) {
+ // Every 8th row starting at row 0
+ for(my=0; my < priv->frame.height; my+=8) {
+ for(gcnt=0, mx=0; mx < priv->frame.width; mx++, q++, cnt--) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ mx++;
+ break;
+ }
+ q = decode->buf;
+ }
+ if (my >= sy && my < fy && mx >= sx && mx < fx) {
+ col = *q;
+ if ((priv->frame.flags & GIFL_TRANSPARENT) && col == priv->frame.paltrans) {
+ // We have a transparent pixel - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ gcnt = 0;
+ continue;
+ }
+ priv->buf[gcnt++] = decode->palette[col];
+ if (gcnt >= BLIT_BUFFER_SIZE) {
+ // We have run out of buffer - dump it to the display
+ gdispBlitAreaEx(x+mx-gcnt+1, y+my, gcnt, 1, 0, 0, gcnt, priv->buf);
+ gcnt = 0;
+ }
+ }
+ }
+ // We have finished the line - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ }
+ // Every 8th row starting at row 4
+ for(my=4; my < priv->frame.height; my+=8) {
+ for(gcnt=0, mx=0; mx < priv->frame.width; mx++, q++, cnt--) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ mx++;
+ break;
+ }
+ q = decode->buf;
+ }
+ if (my >= sy && my < fy && mx >= sx && mx < fx) {
+ col = *q;
+ if ((priv->frame.flags & GIFL_TRANSPARENT) && col == priv->frame.paltrans) {
+ // We have a transparent pixel - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ gcnt = 0;
+ continue;
+ }
+ priv->buf[gcnt++] = decode->palette[col];
+ if (gcnt >= BLIT_BUFFER_SIZE) {
+ // We have run out of buffer - dump it to the display
+ gdispBlitAreaEx(x+mx-gcnt+1, y+my, gcnt, 1, 0, 0, gcnt, priv->buf);
+ gcnt = 0;
+ }
+ }
+ }
+ // We have finished the line - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ }
+ // Every 4th row starting at row 2
+ for(my=2; my < priv->frame.height; my+=4) {
+ for(gcnt=0, mx=0; mx < priv->frame.width; mx++, q++, cnt--) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ mx++;
+ break;
+ }
+ q = decode->buf;
+ }
+ if (my >= sy && my < fy && mx >= sx && mx < fx) {
+ col = *q;
+ if ((priv->frame.flags & GIFL_TRANSPARENT) && col == priv->frame.paltrans) {
+ // We have a transparent pixel - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ gcnt = 0;
+ continue;
+ }
+ priv->buf[gcnt++] = decode->palette[col];
+ if (gcnt >= BLIT_BUFFER_SIZE) {
+ // We have run out of buffer - dump it to the display
+ gdispBlitAreaEx(x+mx-gcnt+1, y+my, gcnt, 1, 0, 0, gcnt, priv->buf);
+ gcnt = 0;
+ }
+ }
+ }
+ // We have finished the line - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ }
+ // Every 2nd row starting at row 1
+ for(my=1; my < priv->frame.height; my+=2) {
+ for(gcnt=0, mx=0; mx < priv->frame.width; mx++, q++, cnt--) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ mx++;
+ break;
+ }
+ q = decode->buf;
+ }
+ if (my >= sy && my < fy && mx >= sx && mx < fx) {
+ col = *q;
+ if ((priv->frame.flags & GIFL_TRANSPARENT) && col == priv->frame.paltrans) {
+ // We have a transparent pixel - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ gcnt = 0;
+ continue;
+ }
+ priv->buf[gcnt++] = decode->palette[col];
+ if (gcnt >= BLIT_BUFFER_SIZE) {
+ // We have run out of buffer - dump it to the display
+ gdispBlitAreaEx(x+mx-gcnt+1, y+my, gcnt, 1, 0, 0, gcnt, priv->buf);
+ gcnt = 0;
+ }
+ }
+ }
+ // We have finished the line - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ }
+ } else {
+ // Every row in sequence
+ for(my=0; my < priv->frame.height; my++) {
+ for(gcnt=0, mx=0; mx < priv->frame.width; mx++, q++, cnt--) {
+ if (!cnt) {
+ if (!(cnt = getbytes(img))) {
+ // Sometimes the image EOF is a bit early - treat the rest as transparent
+ if (decode->code_last != decode->code_eof)
+ goto baddatacleanup;
+ mx++;
+ break;
+ }
+ q = decode->buf;
+ }
+ if (my >= sy && my < fy && mx >= sx && mx < fx) {
+ col = *q;
+ if ((priv->frame.flags & GIFL_TRANSPARENT) && col == priv->frame.paltrans) {
+ // We have a transparent pixel - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ gcnt = 0;
+ continue;
+ }
+ priv->buf[gcnt++] = decode->palette[col];
+ if (gcnt >= BLIT_BUFFER_SIZE) {
+ // We have run out of buffer - dump it to the display
+ gdispBlitAreaEx(x+mx-gcnt+1, y+my, gcnt, 1, 0, 0, gcnt, priv->buf);
+ gcnt = 0;
+ }
+ }
+ }
+ // We have finished the line - dump the buffer to the display
+ switch(gcnt) {
+ case 0: break;
+ case 1: gdispDrawPixel(x+mx-gcnt, y+my, priv->buf[0]); break;
+ default: gdispBlitAreaEx(x+mx-gcnt, y+my, gcnt, 1, 0, 0, gcnt, priv->buf); break;
+ }
+ }
+ }
+ // We could be pedantic here but extra bytes won't hurt us
+ while (getbytes(img));
+ priv->frame.posend = img->io.pos;
+
+ stopDecode(img);
+ return GDISP_IMAGE_ERR_OK;
+
+baddatacleanup:
+ stopDecode(img);
+ return GDISP_IMAGE_ERR_BADDATA;
+}
+
+systime_t gdispImageNext_GIF(gdispImage *img) {
+ gdispImagePrivate * priv;
+ systime_t delay;
+ uint8_t blocksz;
+
+ priv = img->priv;
+
+ // Save the delay and convert to millisecs
+ delay = (systime_t)priv->frame.delay * 10;
+
+ // We need to get to the end of this frame
+ if (!priv->frame.posend) {
+ // We don't know where the end of the frame is yet - find it!
+ img->io.fns->seek(&img->io, priv->frame.posimg+1); // Skip the code size byte too
+ while(1) {
+ if (img->io.fns->read(&img->io, &blocksz, 1) != 1)
+ return TIME_INFINITE;
+ if (!blocksz)
+ break;
+ img->io.fns->seek(&img->io, img->io.pos + blocksz);
+ }
+ priv->frame.posend = img->io.pos;
+ }
+
+ // Seek to the end of this frame
+ img->io.fns->seek(&img->io, priv->frame.posend);
+
+ // Read the next frame descriptor
+ for(blocksz=0; blocksz < 2; blocksz++) { // 2 loops max to prevent cycling forever with a bad file
+ switch(initFrame(img)) {
+ case GDISP_IMAGE_ERR_OK: // Everything OK
+ return delay;
+ case GDISP_IMAGE_LOOP: // Back to the beginning
+ break;
+ case GDISP_IMAGE_EOF: // The real End-Of-File
+ case GDISP_IMAGE_ERR_BADDATA: // Oops - something wrong with the data
+ case GDISP_IMAGE_ERR_NOMEMORY: // Out of Memory
+ case GDISP_IMAGE_ERR_UNSUPPORTED: // Unsupported
+ default:
+ return TIME_INFINITE;
+ }
+ }
+ return TIME_INFINITE;
+}
#endif /* GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_GIF */
/** @} */